> +     Remove EDNS0 option (Fixes BMC #4818)
> +     Implement DNS over TCP for dnsproxy
Is the upstream bug which distribution bug 7497 depends on.
That is the biggest change at ConnMan-0.60.5, and HP/Novell care much.

> -----Original Message-----
> From: Anas Nashif [mailto:[email protected]]
> Sent: Monday, October 11, 2010 1:41 PM
> To: [email protected] (announcement list); Xu, Martin
> Cc: [email protected]
> Subject: Re: [meego-commits] 8278: Changes to
> MeeGo:1.1:Core:Testing/connman
>
>
> On 2010-10-10, at 9:58 PM, Martin Xu wrote:
>
> > Hi,
> > I have made the following changes to connman in project
> MeeGo:1.1:Core:Testing. Please review and accept ASAP.
> >
> > Thank You,
> > Martin Xu
> >
> > [This message was auto-generated]
> >
> > ---
> >
> > Request #8278:
> >
> >  submit:
> home:martin:branches:MeeGo:1.1:Core:Testing/connman(r2)(cleanup) ->
> MeeGo:1.1:Core:Testing/connman
> >
> >
> > Message:
> >    fix BMC #7497
> >
> > State:   new          2010-10-10T21:58:15 martin
> > Comment: None
> >
> >
> >
> > changes files:
> > --------------
> > --- connman.changes
> > +++ connman.changes
> > @@ -0,0 +1,3 @@
> > +* Sat Oct 09 2010 Martin Xu <[email protected]> - 0.60.5
> > +- upgrade to 0.60.5 to fix BMC #7497
> > +
>
> In the change log in the tarball there are many other bugs not mentioned here,
> and that bug (7497) is not mentioned at all? What is going on here? Why those
> other bugs are not mentioned in the package changelog?
>
>
>
> +ver 0.60.5
> +     Remove EDNS0 option (Fixes BMC #4818)
> +     Implement DNS over TCP for dnsproxy
> +
> +ver 0.60.4
> +     Do not remove wifi network upon disconnection (Fixes BMC #7730, #7734)
> +     Set WiFi task scanning flag when receiving a Scanning event
> +     Implement WiFi network driver remove hook
> +     RemoveProvider argument is an object path
> +     Remove providers based on their VPN service path
> +
>
>
>
>
>
>
> >
> > old:
> > ----
> >  connman-0.60.3.tar.bz2
> >
> > new:
> > ----
> >  connman-0.60.5.tar.bz2
> >
> > spec files:
> > -----------
> > --- connman.spec
> > +++ connman.spec
> > @@ -7,7 +7,7 @@
> >
> > Name:       connman
> > Summary:    Connection Manager
> > -Version:    0.60.3
> > +Version:    0.60.5
> > Release:    1
> > Group:      System/Networking
> > License:    GPLv2
> >
> > other changes:
> > --------------
> >
> > ++++++ connman-0.60.3.tar.bz2 -> connman-0.60.5.tar.bz2
> > --- ChangeLog
> > +++ ChangeLog
> > @@ -1,3 +1,14 @@
> > +ver 0.60.5
> > +   Remove EDNS0 option (Fixes BMC #4818)
> > +   Implement DNS over TCP for dnsproxy
> > +
> > +ver 0.60.4
> > +   Do not remove wifi network upon disconnection (Fixes BMC #7730, #7734)
> > +   Set WiFi task scanning flag when receiving a Scanning event
> > +   Implement WiFi network driver remove hook
> > +   RemoveProvider argument is an object path
> > +   Remove providers based on their VPN service path
> > +
> > ver 0.60.3
> >     Fix bug to remove vpn services if offline mode is on (Fixes BMC # 6591)
> >     Schedule delayed scan if disconnected from an AP (Fixes BMC #6831)
> > --- configure
> > +++ configure
> > @@ -1,6 +1,6 @@
> > #! /bin/sh
> > # Guess values for system-dependent variables and create Makefiles.
> > -# Generated by GNU Autoconf 2.64 for connman 0.60.3.
> > +# Generated by GNU Autoconf 2.64 for connman 0.60.5.
> > #
> > # Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
> > # 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software
> > @@ -695,8 +695,8 @@
> > # Identity of this package.
> > PACKAGE_NAME='connman'
> > PACKAGE_TARNAME='connman'
> > -PACKAGE_VERSION='0.60.3'
> > -PACKAGE_STRING='connman 0.60.3'
> > +PACKAGE_VERSION='0.60.5'
> > +PACKAGE_STRING='connman 0.60.5'
> > PACKAGE_BUGREPORT=''
> > PACKAGE_URL=''
> >
> > @@ -1573,7 +1573,7 @@
> >   # Omit some internal or obsolete options to make the list less imposing.
> >   # This message is too long to be a string in the A/UX 3.1 sh.
> >   cat <<_ACEOF
> > -\`configure' configures connman 0.60.3 to adapt to many kinds of systems.
> > +\`configure' configures connman 0.60.5 to adapt to many kinds of systems.
> >
> > Usage: $0 [OPTION]... [VAR=VALUE]...
> >
> > @@ -1643,7 +1643,7 @@
> >
> > if test -n "$ac_init_help"; then
> >   case $ac_init_help in
> > -     short | recursive ) echo "Configuration of connman 0.60.3:";;
> > +     short | recursive ) echo "Configuration of connman 0.60.5:";;
> >    esac
> >   cat <<\_ACEOF
> >
> > @@ -1808,7 +1808,7 @@
> > test -n "$ac_init_help" && exit $ac_status
> > if $ac_init_version; then
> >   cat <<\_ACEOF
> > -connman configure 0.60.3
> > +connman configure 0.60.5
> > generated by GNU Autoconf 2.64
> >
> > Copyright (C) 2009 Free Software Foundation, Inc.
> > @@ -2266,7 +2266,7 @@
> > This file contains any messages produced by compilers while
> > running configure, to aid debugging if configure makes a mistake.
> >
> > -It was created by connman $as_me 0.60.3, which was
> > +It was created by connman $as_me 0.60.5, which was
> > generated by GNU Autoconf 2.64.  Invocation command line was
> >
> >   $ $0 $@
> > @@ -3075,7 +3075,7 @@
> >
> > # Define the identity of the package.
> >  PACKAGE='connman'
> > - VERSION='0.60.3'
> > + VERSION='0.60.5'
> >
> >
> > cat >>confdefs.h <<_ACEOF
> > @@ -13740,7 +13740,7 @@
> > # report actual input values of CONFIG_FILES etc. instead of their
> > # values after options handling.
> > ac_log="
> > -This file was extended by connman $as_me 0.60.3, which was
> > +This file was extended by connman $as_me 0.60.5, which was
> > generated by GNU Autoconf 2.64.  Invocation command line was
> >
> >   CONFIG_FILES    = $CONFIG_FILES
> > @@ -13804,7 +13804,7 @@
> > _ACEOF
> > cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
> > ac_cs_version="\\
> > -connman config.status 0.60.3
> > +connman config.status 0.60.5
> > configured by $0, generated by GNU Autoconf 2.64,
> >   with options \\"`$as_echo "$ac_configure_args" | sed 's/^ //;
> s/[\\""\`\$]/\\\\&/g'`\\"
> >
> > --- configure.ac
> > +++ configure.ac
> > @@ -1,5 +1,5 @@
> > AC_PREREQ(2.60)
> > -AC_INIT(connman, 0.60.3)
> > +AC_INIT(connman, 0.60.5)
> >
> > AM_INIT_AUTOMAKE([foreign subdir-objects])
> > AM_CONFIG_HEADER(config.h)
> > --- plugins/dnsproxy.c
> > +++ plugins/dnsproxy.c
> > @@ -79,18 +79,24 @@
> >     char *interface;
> >     char *domain;
> >     char *server;
> > +   int protocol;
> >     GIOChannel *channel;
> >     guint watch;
> > +   guint timeout;
> >     gboolean enabled;
> > +   gboolean connected;
> > };
> >
> > struct request_data {
> >     struct sockaddr_in sin;
> > +   int client_sk;
> > +   int protocol;
> >     socklen_t len;
> >     guint16 srcid;
> >     guint16 dstid;
> >     guint16 altid;
> >     guint timeout;
> > +   guint watch;
> >     guint numserv;
> >     guint numresp;
> >     gpointer request;
> > @@ -105,8 +111,25 @@
> > static GSList *request_pending_list = NULL;
> > static guint16 request_id = 0x0000;
> >
> > -static GIOChannel *listener_channel = NULL;
> > -static guint listener_watch = 0;
> > +static GIOChannel *udp_listener_channel = NULL;
> > +static guint udp_listener_watch = 0;
> > +static GIOChannel *tcp_listener_channel = NULL;
> > +static guint tcp_listener_watch = 0;
> > +
> > +static int protocol_offset(int protocol)
> > +{
> > +   switch (protocol) {
> > +   case IPPROTO_UDP:
> > +           return 0;
> > +
> > +   case IPPROTO_TCP:
> > +           return 2;
> > +
> > +   default:
> > +           return -EINVAL;
> > +   }
> > +
> > +}
> >
> > static struct request_data *find_request(guint16 id)
> > {
> > @@ -123,7 +146,8 @@
> > }
> >
> > static struct server_data *find_server(const char *interface,
> > -                                   const char *domain, const char *server)
> > +                                   const char *domain, const char *server,
> > +                                           int protocol)
> > {
> >     GSList *list;
> >
> > @@ -136,7 +160,8 @@
> >                     continue;
> >
> >             if (g_str_equal(data->interface, interface) == TRUE &&
> > -                           g_str_equal(data->server, server) == TRUE) {
> > +                           g_str_equal(data->server, server) == TRUE &&
> > +                           data->protocol == protocol) {
> >                     if (domain == NULL) {
> >                             if (data->domain == NULL)
> >                                     return data;
> > @@ -151,155 +176,80 @@
> >     return NULL;
> > }
> >
> > -static gboolean server_event(GIOChannel *channel, GIOCondition condition,
> > -                                                   gpointer user_data)
> > +
> > +static void send_response(int sk, unsigned char *buf, int len,
> > +                           const struct sockaddr *to, socklen_t tolen,
> > +                           int protocol)
> > {
> > -   struct server_data *data = user_data;
> > -   struct request_data *req;
> > -   unsigned char buf[4096];
> > -   struct domain_hdr *hdr = (void *) &buf;
> > -   int sk, err, len;
> > +   struct domain_hdr *hdr;
> > +   int err, offset = protocol_offset(protocol);
> >
> > -   if (condition & (G_IO_NVAL | G_IO_ERR | G_IO_HUP)) {
> > -           connman_error("Error with server channel");
> > -           data->watch = 0;
> > -           return FALSE;
> > -   }
> > +   DBG("");
> >
> > -   sk = g_io_channel_unix_get_fd(channel);
> > +   if (offset < 0)
> > +           return;
> >
> > -   len = recv(sk, buf, sizeof(buf), 0);
> >     if (len < 12)
> > -           return TRUE;
> > -
> > -   DBG("Received %d bytes (id 0x%04x)", len, buf[0] | buf[1] << 8);
> > -
> > -   req = find_request(buf[0] | buf[1] << 8);
> > -   if (req == NULL)
> > -           return TRUE;
> > -
> > -   DBG("id 0x%04x rcode %d", hdr->id, hdr->rcode);
> > -
> > -   buf[0] = req->srcid & 0xff;
> > -   buf[1] = req->srcid >> 8;
> > -
> > -   req->numresp++;
> > -
> > -   if (hdr->rcode == 0 || req->resp == NULL) {
> > -           g_free(req->resp);
> > -           req->resplen = 0;
> > -
> > -           req->resp = g_try_malloc(len);
> > -           if (req->resp == NULL)
> > -                   return TRUE;
> > -
> > -           memcpy(req->resp, buf, len);
> > -           req->resplen = len;
> > -   }
> > -
> > -   if (hdr->rcode > 0 && req->numresp < req->numserv)
> > -           return TRUE;
> > -
> > -   if (req->timeout > 0)
> > -           g_source_remove(req->timeout);
> > +           return;
> >
> > -   request_list = g_slist_remove(request_list, req);
> > +   hdr = (void*) (buf + offset);
> >
> > -   sk = g_io_channel_unix_get_fd(listener_channel);
> > +   DBG("id 0x%04x qr %d opcode %d", hdr->id, hdr->qr, hdr->opcode);
> >
> > -   err = sendto(sk, req->resp, req->resplen, 0,
> > -                           (struct sockaddr *) &req->sin, req->len);
> > +   hdr->qr = 1;
> > +   hdr->rcode = 2;
> >
> > -   g_free(req->resp);
> > -   g_free(req);
> > +   hdr->ancount = 0;
> > +   hdr->nscount = 0;
> > +   hdr->arcount = 0;
> >
> > -   return TRUE;
> > +   err = sendto(sk, buf, len, 0, to, tolen);
> > }
> >
> > -static struct server_data *create_server(const char *interface,
> > -                                   const char *domain, const char *server)
> > +static gboolean request_timeout(gpointer user_data)
> > {
> > -   struct server_data *data;
> > -   struct sockaddr_in sin;
> > -   int sk;
> > +   struct request_data *req = user_data;
> >
> > -   DBG("interface %s server %s", interface, server);
> > +   DBG("id 0x%04x", req->srcid);
> >
> > -   sk = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
> > -   if (sk < 0) {
> > -           connman_error("Failed to create server %s socket", server);
> > -           return NULL;
> > -   }
> > +   if (req == NULL)
> > +           return FALSE;
> >
> > -   if (interface != NULL) {
> > -           if (setsockopt(sk, SOL_SOCKET, SO_BINDTODEVICE,
> > -                           interface, strlen(interface) + 1) < 0) {
> > -                   connman_error("Failed to bind server %s "
> > -                                           "to interface %s",
> > -                                                   server, interface);
> > -                   close(sk);
> > -                   return NULL;
> > -           }
> > -   }
> > +   request_list = g_slist_remove(request_list, req);
> > +   req->numserv--;
> >
> > -   memset(&sin, 0, sizeof(sin));
> > -   sin.sin_family = AF_INET;
> > -   sin.sin_port = htons(53);
> > -   sin.sin_addr.s_addr = inet_addr(server);
> > +   if (req->resplen > 0 && req->resp != NULL) {
> > +           int sk, err;
> >
> > -   if (connect(sk, (struct sockaddr *) &sin, sizeof(sin)) < 0) {
> > -           connman_error("Failed to connect server %s", server);
> > -           close(sk);
> > -           return NULL;
> > -   }
> > +           sk = g_io_channel_unix_get_fd(udp_listener_channel);
> >
> > -   data = g_try_new0(struct server_data, 1);
> > -   if (data == NULL) {
> > -           connman_error("Failed to allocate server %s data", server);
> > -           close(sk);
> > -           return NULL;
> > -   }
> > +           err = sendto(sk, req->resp, req->resplen, 0,
> > +                           (struct sockaddr *) &req->sin, req->len);
> > +   } else if (req->request && req->numserv == 0) {
> > +           struct domain_hdr *hdr;
> >
> > -   data->channel = g_io_channel_unix_new(sk);
> > -   if (data->channel == NULL) {
> > -           connman_error("Failed to create server %s channel", server);
> > -           close(sk);
> > -           g_free(data);
> > -           return NULL;
> > +           if (req->protocol == IPPROTO_TCP) {
> > +                   hdr = (void *) (req->request + 2);
> > +                   hdr->id = req->srcid;
> > +                   send_response(req->client_sk, req->request,
> > +                                   req->request_len, NULL, 0, IPPROTO_TCP);
> > +
> > +           } else if (req->protocol == IPPROTO_UDP) {
> > +                   int sk;
> > +
> > +                   hdr = (void *) (req->request);
> > +                   hdr->id = req->srcid;
> > +                   sk = g_io_channel_unix_get_fd(udp_listener_channel);
> > +                   send_response(sk, req->request, req->request_len,
> > +                                   (struct sockaddr *)&req->sin,
> > +                                           sizeof(req->sin), IPPROTO_UDP);
> > +           }
> >     }
> >
> > -   g_io_channel_set_close_on_unref(data->channel, TRUE);
> > -
> > -   data->watch = g_io_add_watch(data->channel, G_IO_IN,
> > -                                           server_event, data);
> > -
> > -   data->interface = g_strdup(interface);
> > -   data->domain = g_strdup(domain);
> > -   data->server = g_strdup(server);
> > -
> > -   /* Enable new servers by default */
> > -   data->enabled = TRUE;
> > -
> > -   connman_info("Adding DNS server %s", data->server);
> > -
> > -   return data;
> > -}
> > -
> > -static void destroy_server(struct server_data *data)
> > -{
> > -   DBG("interface %s server %s", data->interface, data->server);
> > -
> > -   if (data->watch > 0)
> > -           g_source_remove(data->watch);
> > -
> > -   g_io_channel_unref(data->channel);
> > -
> > -   connman_info("Removing DNS server %s", data->server);
> > +   g_free(req->resp);
> > +   g_free(req);
> >
> > -   g_free(data->server);
> > -   g_free(data->domain);
> > -   g_free(data->interface);
> > -   g_free(data);
> > +   return FALSE;
> > }
> >
> > static int append_query(unsigned char *buf, unsigned int size,
> > @@ -357,84 +307,427 @@
> >     return ptr - buf;
> > }
> >
> > -static gboolean request_timeout(gpointer user_data)
> > +static int ns_resolv(struct server_data *server, struct request_data *req,
> > +                           gpointer request, gpointer name)
> > {
> > -   struct request_data *req = user_data;
> > +   int sk, err;
> >
> > -   DBG("id 0x%04x", req->srcid);
> > +   sk = g_io_channel_unix_get_fd(server->channel);
> >
> > -   request_list = g_slist_remove(request_list, req);
> > +   err = send(sk, request, req->request_len, 0);
> >
> > -   if (req->resplen > 0 && req->resp != NULL) {
> > -           int sk, err;
> > +   req->numserv++;
> > +
> > +   if (server->domain != NULL) {
> > +           unsigned char alt[1024];
> > +           struct domain_hdr *hdr = (void *) &alt;
> > +           int altlen, domlen, offset;
> > +
> > +           offset = protocol_offset(server->protocol);
> > +           if (offset < 0)
> > +                   return offset;
> > +
> > +           domlen = strlen(server->domain) + 1;
> > +           if (domlen < 5)
> > +                   return -EINVAL;
> > +
> > +           alt[offset] = req->altid & 0xff;
> > +           alt[offset + 1] = req->altid >> 8;
> > +
> > +           memcpy(alt + offset + 2, request + offset + 2, 10);
> > +           hdr->qdcount = htons(1);
> > +
> > +           altlen = append_query(alt + offset + 12, sizeof(alt) - 12,
> > +                                   name, server->domain);
> > +           if (altlen < 0)
> > +                   return -EINVAL;
> > +
> > +           altlen += 12;
> > +
> > +           memcpy(alt + offset + altlen,
> > +                   request + offset + altlen - domlen,
> > +                           req->request_len - altlen + domlen);
> > +
> > +           if (server->protocol == IPPROTO_TCP) {
> > +                   int req_len = req->request_len + domlen - 1;
> > +
> > +                   alt[0] = (req_len >> 8) & 0xff;
> > +                   alt[1] = req_len & 0xff;
> > +           }
> > +
> > +           err = send(sk, alt, req->request_len + domlen + 1, 0);
> > +
> > +           req->numserv++;
> > +   }
> > +
> > +   return 0;
> > +}
> > +
> > +static int forward_dns_reply(unsigned char *reply, int reply_len, int 
> > protocol)
> > +{
> > +   struct domain_hdr *hdr;
> > +   struct request_data *req;
> > +   int dns_id, sk, err, offset = protocol_offset(protocol);
> > +
> > +   if (offset < 0)
> > +           return offset;
> > +
> > +   hdr = (void *)(reply + offset);
> > +   dns_id = reply[offset] | reply[offset + 1] << 8;
> > +
> > +   DBG("Received %d bytes (id 0x%04x)", reply_len, dns_id);
> > +
> > +   req = find_request(dns_id);
> > +   if (req == NULL)
> > +           return -EINVAL;
> > +
> > +   DBG("id 0x%04x rcode %d", hdr->id, hdr->rcode);
> > +
> > +   reply[offset] = req->srcid & 0xff;
> > +   reply[offset + 1] = req->srcid >> 8;
> > +
> > +   req->numresp++;
> > +
> > +   if (hdr->rcode == 0 || req->resp == NULL) {
> > +           g_free(req->resp);
> > +           req->resplen = 0;
> > +
> > +           req->resp = g_try_malloc(reply_len);
> > +           if (req->resp == NULL)
> > +                   return -ENOMEM;
> > +
> > +           memcpy(req->resp, reply, reply_len);
> > +           req->resplen = reply_len;
> > +   }
> > +
> > +   if (hdr->rcode > 0 && req->numresp < req->numserv)
> > +           return -EINVAL;
> >
> > -           sk = g_io_channel_unix_get_fd(listener_channel);
> > +   if (req->timeout > 0)
> > +           g_source_remove(req->timeout);
> > +
> > +   request_list = g_slist_remove(request_list, req);
> >
> > +   if (protocol == IPPROTO_UDP) {
> > +           sk = g_io_channel_unix_get_fd(udp_listener_channel);
> >             err = sendto(sk, req->resp, req->resplen, 0,
> >                             (struct sockaddr *) &req->sin, req->len);
> > +   } else {
> > +           sk = req->client_sk;
> > +           err = send(sk, req->resp, req->resplen, 0);
> > +           close(sk);
> >     }
> >
> >     g_free(req->resp);
> >     g_free(req);
> >
> > -   return FALSE;
> > +   return err;
> > }
> >
> > -static gboolean resolv(struct request_data *req,
> > -                           gpointer request, gpointer name)
> > +static void destroy_server(struct server_data *server)
> > {
> > -   int sk, err;
> > -   GSList *list;
> > +   DBG("interface %s server %s", server->interface, server->server);
> >
> > -   request_list = g_slist_append(request_list, req);
> > +   server_list = g_slist_remove(server_list, server);
> >
> > -   req->numserv = 0;
> > -   req->timeout = g_timeout_add_seconds(5, request_timeout, req);
> > +   if (server->watch > 0)
> > +           g_source_remove(server->watch);
> >
> > -   for (list = server_list; list; list = list->next) {
> > -           struct server_data *data = list->data;
> > +   if (server->timeout > 0)
> > +           g_source_remove(server->timeout);
> >
> > -           DBG("server %s domain %s enabled %d",
> > -                           data->server, data->domain, data->enabled);
> > +   g_io_channel_unref(server->channel);
> >
> > -           if (data->enabled == FALSE)
> > -                   continue;
> > +   if (server->protocol == IPPROTO_UDP)
> > +           connman_info("Removing DNS server %s", server->server);
> >
> > -           sk = g_io_channel_unix_get_fd(data->channel);
> > +   g_free(server->server);
> > +   g_free(server->domain);
> > +   g_free(server->interface);
> > +   g_free(server);
> > +}
> >
> > -           err = send(sk, request, req->request_len, 0);
> > +static gboolean udp_server_event(GIOChannel *channel, GIOCondition
> condition,
> > +                                                   gpointer user_data)
> > +{
> > +   struct server_data *data = user_data;
> > +   unsigned char buf[4096];
> > +   int sk, err, len;
> >
> > -           req->numserv++;
> > +   if (condition & (G_IO_NVAL | G_IO_ERR | G_IO_HUP)) {
> > +           connman_error("Error with server channel");
> > +           data->watch = 0;
> > +           return FALSE;
> > +   }
> >
> > -           if (data->domain != NULL) {
> > -                   unsigned char alt[1024];
> > -                   struct domain_hdr *hdr = (void *) &alt;
> > -                   int altlen, domlen;
> > +   sk = g_io_channel_unix_get_fd(channel);
> > +
> > +   len = recv(sk, buf, sizeof(buf), 0);
> > +   if (len < 12)
> > +           return TRUE;
> > +
> > +   err = forward_dns_reply(buf, len, IPPROTO_UDP);
> > +
> > +   return TRUE;
> > +}
> > +
> > +static gboolean tcp_server_event(GIOChannel *channel, GIOCondition
> condition,
> > +                                                   gpointer user_data)
> > +{
> > +   int sk;
> > +   struct server_data *server = user_data;
> > +
> > +   sk = g_io_channel_unix_get_fd(channel);
> > +   if (sk == 0)
> > +           return FALSE;
> > +
> > +   if (condition & (G_IO_NVAL | G_IO_ERR | G_IO_HUP)) {
> > +           GSList *list;
> > +
> > +           DBG("TCP server channel closed");
> >
> > -                   domlen = strlen(data->domain) + 1;
> > -                   if (domlen < 5)
> > +           for (list = request_list; list; list = list->next) {
> > +                   struct request_data *req = list->data;
> > +                   struct domain_hdr *hdr;
> > +
> > +                   if (req->protocol == IPPROTO_UDP)
> > +                           continue;
> > +
> > +                   if (req->request == NULL)
> >                             continue;
> >
> > -                   alt[0] = req->altid & 0xff;
> > -                   alt[1] = req->altid >> 8;
> > +                   /*
> > +                    * If we're not waiting for any further response
> > +                    * from another name server, then we send an error
> > +                    * response to the client.
> > +                    */
> > +                   if (req->numserv && --(req->numserv))
> > +                           continue;
> > +
> > +                   hdr = (void *) (req->request + 2);
> > +                   hdr->id = req->srcid;
> > +                   send_response(req->client_sk, req->request,
> > +                                   req->request_len, NULL, 0, IPPROTO_TCP);
> > +
> > +                   request_list = g_slist_remove(request_list, req);
> > +           }
> > +
> > +           destroy_server(server);
> > +
> > +           return FALSE;
> > +   }
> > +
> > +   if ((condition & G_IO_OUT) && !server->connected) {
> > +           GSList *list;
> > +
> > +           server->connected = TRUE;
> > +           server_list = g_slist_append(server_list, server);
> > +
> > +           if (server->timeout > 0) {
> > +                   g_source_remove(server->timeout);
> > +                   server->timeout = 0;
> > +           }
> >
> > -                   memcpy(alt + 2, request + 2, 10);
> > -                   hdr->qdcount = htons(1);
> > +           for (list = request_list; list; list = list->next) {
> > +                   struct request_data *req = list->data;
> >
> > -                   altlen = append_query(alt + 12, sizeof(alt) - 12,
> > -                                           name, data->domain);
> > -                   if (altlen < 0)
> > +                   if (req->protocol == IPPROTO_UDP)
> >                             continue;
> >
> > -                   altlen += 12;
> > +                   DBG("Sending req %s over TCP", (char *)req->name);
> > +
> > +                   if (req->timeout > 0)
> > +                           g_source_remove(req->timeout);
> > +
> > +                   req->timeout = g_timeout_add_seconds(30,
> > +                                           request_timeout, req);
> > +                   ns_resolv(server, req, req->request, req->name);
> > +           }
> > +
> > +   } else if (condition & G_IO_IN) {
> > +           int len, bytes_recv, total_bytes_recv;
> > +           unsigned char reply_len_buf[2];
> > +           uint16_t reply_len;
> > +           unsigned char *reply;
> >
> > -                   memcpy(alt + altlen, request + altlen - domlen,
> > -                                   req->request_len - altlen + domlen);
> > +           len = recv(sk, reply_len_buf, 2, 0);
> > +           if (len < 2)
> > +                   return TRUE;
> > +
> > +           reply_len = reply_len_buf[1] | reply_len_buf[0] << 8;
> > +
> > +           DBG("TCP reply %d bytes", reply_len);
> > +
> > +           reply = g_try_malloc(reply_len + 2);
> > +           if (reply == NULL)
> > +                   return TRUE;
> > +
> > +           reply[0] = reply_len_buf[0];
> > +           reply[1] = reply_len_buf[1];
> >
> > -                   err = send(sk, alt, req->request_len + domlen + 1, 0);
> > +           total_bytes_recv = bytes_recv = 0;
> > +           while (total_bytes_recv < reply_len) {
> > +                   bytes_recv = recv(sk, reply + 2, reply_len, 0);
> > +                   if (bytes_recv < 0)
> > +                           break;
> >
> > -                   req->numserv++;
> > +                   total_bytes_recv += bytes_recv;
> >             }
> > +
> > +           forward_dns_reply(reply, reply_len + 2, IPPROTO_TCP);
> > +
> > +           g_free(reply);
> > +
> > +           destroy_server(server);
> > +
> > +           return FALSE;
> > +   }
> > +
> > +   return TRUE;
> > +}
> > +
> > +static gboolean tcp_idle_timeout(gpointer user_data)
> > +{
> > +   struct server_data *server = user_data;
> > +
> > +   DBG("");
> > +
> > +   if (server == NULL)
> > +           return FALSE;
> > +
> > +   destroy_server(server);
> > +
> > +   return FALSE;
> > +}
> > +
> > +static struct server_data *create_server(const char *interface,
> > +                                   const char *domain, const char *server,
> > +                                   int protocol)
> > +{
> > +   struct server_data *data;
> > +   struct sockaddr_in sin;
> > +   int sk, type, ret;
> > +
> > +   DBG("interface %s server %s", interface, server);
> > +
> > +   switch (protocol) {
> > +   case IPPROTO_UDP:
> > +           type = SOCK_DGRAM;
> > +           break;
> > +
> > +   case IPPROTO_TCP:
> > +           type = SOCK_STREAM;
> > +           break;
> > +
> > +   default:
> > +           return NULL;
> > +   }
> > +
> > +   data = find_server(interface, domain, server, protocol);
> > +   if (data) {
> > +           if (data->watch > 0)
> > +                   g_source_remove(data->watch);
> > +           data->watch = g_io_add_watch(data->channel,
> > +                   G_IO_OUT | G_IO_IN | G_IO_HUP | G_IO_NVAL | G_IO_ERR,
> > +                                           tcp_server_event, data);
> > +           return data;
> > +   }
> > +
> > +   sk = socket(AF_INET, type, protocol);
> > +   if (sk < 0) {
> > +           connman_error("Failed to create server %s socket", server);
> > +           return NULL;
> > +   }
> > +
> > +   if (interface != NULL) {
> > +           if (setsockopt(sk, SOL_SOCKET, SO_BINDTODEVICE,
> > +                           interface, strlen(interface) + 1) < 0) {
> > +                   connman_error("Failed to bind server %s "
> > +                                           "to interface %s",
> > +                                                   server, interface);
> > +                   close(sk);
> > +                   return NULL;
> > +           }
> > +   }
> > +
> > +   data = g_try_new0(struct server_data, 1);
> > +   if (data == NULL) {
> > +           connman_error("Failed to allocate server %s data", server);
> > +           close(sk);
> > +           return NULL;
> > +   }
> > +
> > +   data->channel = g_io_channel_unix_new(sk);
> > +   if (data->channel == NULL) {
> > +           connman_error("Failed to create server %s channel", server);
> > +           close(sk);
> > +           g_free(data);
> > +           return NULL;
> > +   }
> > +
> > +   g_io_channel_set_close_on_unref(data->channel, TRUE);
> > +
> > +   if (protocol == IPPROTO_TCP) {
> > +           g_io_channel_set_flags(data->channel, G_IO_FLAG_NONBLOCK,
> NULL);
> > +           data->watch = g_io_add_watch(data->channel,
> > +                   G_IO_OUT | G_IO_IN | G_IO_HUP | G_IO_NVAL | G_IO_ERR,
> > +                                           tcp_server_event, data);
> > +           data->timeout = g_timeout_add_seconds(30, tcp_idle_timeout,
> > +                                                           data);
> > +   } else
> > +           data->watch = g_io_add_watch(data->channel, G_IO_IN,
> > +                                           udp_server_event, data);
> > +
> > +   data->interface = g_strdup(interface);
> > +   data->domain = g_strdup(domain);
> > +   data->server = g_strdup(server);
> > +   data->protocol = protocol;
> > +
> > +   memset(&sin, 0, sizeof(sin));
> > +   sin.sin_family = AF_INET;
> > +   sin.sin_port = htons(53);
> > +   sin.sin_addr.s_addr = inet_addr(server);
> > +
> > +   ret = connect(sk, (struct sockaddr *) &sin, sizeof(sin));
> > +   if (ret < 0) {
> > +           if ((protocol == IPPROTO_TCP && errno != EINPROGRESS) ||
> > +                           protocol == IPPROTO_UDP) {
> > +                   connman_error("Failed to connect to server %s", server);
> > +                   close(sk);
> > +                   g_free(data);
> > +                   return NULL;
> > +           }
> > +   }
> > +
> > +   if (protocol == IPPROTO_UDP) {
> > +           /* Enable new servers by default */
> > +           data->enabled = TRUE;
> > +           connman_info("Adding DNS server %s", data->server);
> > +
> > +           server_list = g_slist_append(server_list, data);
> > +
> > +           return data;
> > +   }
> > +
> > +   return NULL;
> > +}
> > +
> > +static gboolean resolv(struct request_data *req,
> > +                           gpointer request, gpointer name)
> > +{
> > +   GSList *list;
> > +
> > +   for (list = server_list; list; list = list->next) {
> > +           struct server_data *data = list->data;
> > +
> > +           DBG("server %s domain %s enabled %d",
> > +                           data->server, data->domain, data->enabled);
> > +
> > +           if (data->enabled == FALSE)
> > +                   continue;
> > +
> > +           if (ns_resolv(data, req, request, name) < 0)
> > +                   continue;
> >     }
> >
> >     return TRUE;
> > @@ -450,32 +743,35 @@
> >     if (g_str_equal(server, "127.0.0.1") == TRUE)
> >             return -ENODEV;
> >
> > -   data = create_server(interface, domain, server);
> > +   data = create_server(interface, domain, server, IPPROTO_UDP);
> >     if (data == NULL)
> >             return -EIO;
> >
> > -   server_list = g_slist_append(server_list, data);
> > -
> >     return 0;
> > }
> >
> > -static int dnsproxy_remove(const char *interface, const char *domain,
> > -                                                   const char *server)
> > +static void remove_server(const char *interface, const char *domain,
> > +                   const char *server, int protocol)
> > {
> >     struct server_data *data;
> >
> > +   data = find_server(interface, domain, server, protocol);
> > +   if (data == NULL)
> > +           return;
> > +
> > +   destroy_server(data);
> > +}
> > +
> > +static int dnsproxy_remove(const char *interface, const char *domain,
> > +                                                   const char *server)
> > +{
> >     DBG("interface %s server %s", interface, server);
> >
> >     if (g_str_equal(server, "127.0.0.1") == TRUE)
> >             return -ENODEV;
> >
> > -   data = find_server(interface, domain, server);
> > -   if (data == NULL)
> > -           return 0;
> > -
> > -   server_list = g_slist_remove(server_list, data);
> > -
> > -   destroy_server(data);
> > +   remove_server(interface, domain, server, IPPROTO_UDP);
> > +   remove_server(interface, domain, server, IPPROTO_TCP);
> >
> >     return 0;
> > }
> > @@ -637,28 +933,121 @@
> >     return 0;
> > }
> >
> > -static void send_response(int sk, unsigned char *buf, int len,
> > -                           const struct sockaddr *to, socklen_t tolen)
> > +static gboolean tcp_listener_event(GIOChannel *channel, GIOCondition
> condition,
> > +                                                   gpointer user_data)
> > {
> > -   struct domain_hdr *hdr = (void *) buf;
> > -   int err;
> > +   unsigned char buf[768];
> > +   char query[512];
> > +   struct request_data *req;
> > +   struct server_data *server;
> > +   int sk, client_sk, len, err;
> > +   struct sockaddr client_addr;
> > +   socklen_t client_addr_len;
> > +   GSList *list;
> >
> > -   if (len < 12)
> > -           return;
> > +   DBG("condition 0x%x", condition);
> >
> > -   DBG("id 0x%04x qr %d opcode %d", hdr->id, hdr->qr, hdr->opcode);
> > +   if (condition & (G_IO_NVAL | G_IO_ERR | G_IO_HUP)) {
> > +           if (tcp_listener_watch > 0)
> > +                   g_source_remove(tcp_listener_watch);
> > +           tcp_listener_watch = 0;
> >
> > -   hdr->qr = 1;
> > -   hdr->rcode = 2;
> > +           connman_error("Error with TCP listener channel");
> >
> > -   hdr->ancount = 0;
> > -   hdr->nscount = 0;
> > -   hdr->arcount = 0;
> > +           return FALSE;
> > +   }
> >
> > -   err = sendto(sk, buf, len, 0, to, tolen);
> > +   sk = g_io_channel_unix_get_fd(channel);
> > +
> > +   client_addr_len = sizeof(struct sockaddr);
> > +   client_sk = accept(sk, &client_addr, &client_addr_len);
> > +   if (client_sk < 0) {
> > +           connman_error("Accept failure on TCP listener");
> > +           tcp_listener_watch = 0;
> > +           return FALSE;
> > +   }
> > +
> > +   len = recv(client_sk, buf, sizeof(buf), 0);
> > +   if (len < 2)
> > +           return TRUE;
> > +
> > +   DBG("Received %d bytes (id 0x%04x)", len, buf[2] | buf[3] << 8);
> > +
> > +   err = parse_request(buf + 2, len - 2, query, sizeof(query));
> > +   if (err < 0 || (g_slist_length(server_list) == 0 &&
> > +                           connman_ondemand_connected())) {
> > +           send_response(client_sk, buf, len, NULL, 0, IPPROTO_TCP);
> > +           return TRUE;
> > +   }
> > +
> > +   req = g_try_new0(struct request_data, 1);
> > +   if (req == NULL)
> > +           return TRUE;
> > +
> > +   memcpy(&req->sin, (struct sockaddr_in *)&client_addr, sizeof(req->sin));
> > +   req->client_sk = client_sk;
> > +   req->protocol = IPPROTO_TCP;
> > +   req->len = client_addr_len;
> > +
> > +   request_id += 2;
> > +   if (request_id == 0x0000 || request_id == 0xffff)
> > +           request_id += 2;
> > +
> > +   req->srcid = buf[2] | (buf[3] << 8);
> > +   req->dstid = request_id;
> > +   req->altid = request_id + 1;
> > +   req->request_len = len;
> > +
> > +   buf[2] = req->dstid & 0xff;
> > +   buf[3] = req->dstid >> 8;
> > +
> > +   req->numserv = 0;
> > +   request_list = g_slist_append(request_list, req);
> > +
> > +   for (list = server_list; list; list = list->next) {
> > +           struct server_data *data = list->data;
> > +
> > +           if (data->protocol != IPPROTO_UDP || data->enabled == FALSE)
> > +                   continue;
> > +
> > +           server = create_server(data->interface, data->domain,
> > +                                   data->server, IPPROTO_TCP);
> > +
> > +           /*
> > +            * If server is NULL, we're not connected yet.
> > +            * Copy the relevant buffers and continue with
> > +            * the next nameserver.
> > +            * The request will actually be sent once we're
> > +            * properly connected over TCP to this nameserver.
> > +            */
> > +           if (server == NULL) {
> > +                   req->request = g_try_malloc0(req->request_len);
> > +                   if (req->request == NULL)
> > +                           return TRUE;
> > +
> > +                   memcpy(req->request, buf, req->request_len);
> > +
> > +                   req->name = g_try_malloc0(sizeof(query));
> > +                   if (req->name == NULL) {
> > +                           g_free(req->request);
> > +                           return TRUE;
> > +                   }
> > +                   memcpy(req->name, query, sizeof(query));
> > +
> > +                   continue;
> > +           }
> > +
> > +           if (req->timeout > 0)
> > +                   g_source_remove(req->timeout);
> > +
> > +           req->timeout = g_timeout_add_seconds(30, request_timeout, req);
> > +           ns_resolv(server, req, buf, query);
> > +   }
> > +
> > +   return TRUE;
> > }
> >
> > -static gboolean listener_event(GIOChannel *channel, GIOCondition
> condition,
> > +static gboolean udp_listener_event(GIOChannel *channel, GIOCondition
> condition,
> >                                                     gpointer user_data)
> > {
> >     unsigned char buf[768];
> > @@ -669,8 +1058,8 @@
> >     int sk, err, len;
> >
> >     if (condition & (G_IO_NVAL | G_IO_ERR | G_IO_HUP)) {
> > -           connman_error("Error with listener channel");
> > -           listener_watch = 0;
> > +           connman_error("Error with UDP listener channel");
> > +           udp_listener_watch = 0;
> >             return FALSE;
> >     }
> >
> > @@ -687,7 +1076,8 @@
> >     err = parse_request(buf, len, query, sizeof(query));
> >     if (err < 0 || (g_slist_length(server_list) == 0 &&
> >                             connman_ondemand_connected())) {
> > -           send_response(sk, buf, len, (struct sockaddr *) &sin, size);
> > +           send_response(sk, buf, len, (struct sockaddr *) &sin, size,
> > +                           IPPROTO_UDP);
> >             return TRUE;
> >     }
> >
> > @@ -696,6 +1086,8 @@
> >             return TRUE;
> >
> >     memcpy(&req->sin, &sin, sizeof(sin));
> > +   req->client_sk = 0;
> > +   req->protocol = IPPROTO_UDP;
> >     req->len = size;
> >
> >     request_id += 2;
> > @@ -737,29 +1129,47 @@
> >             return TRUE;
> >     }
> >
> > +
> > +   req->numserv = 0;
> > +   req->timeout = g_timeout_add_seconds(5, request_timeout, req);
> > +   request_list = g_slist_append(request_list, req);
> > +
> >     return resolv(req, buf, query);
> > }
> >
> > -static int create_listener(void)
> > +static int create_dns_listener(int protocol)
> > {
> > -   const char *ifname = "lo";
> > +   GIOChannel *channel;
> > +   const char *ifname = "lo", *proto;
> >     struct sockaddr_in sin;
> > -   int sk;
> > +   int sk, type;
> >
> >     DBG("");
> >
> > -   sk = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
> > +   switch (protocol) {
> > +   case IPPROTO_UDP:
> > +           proto = "UDP";
> > +           type = SOCK_DGRAM;
> > +           break;
> > +
> > +   case IPPROTO_TCP:
> > +           proto = "TCP";
> > +           type = SOCK_STREAM;
> > +           break;
> > +
> > +   default:
> > +           return -EINVAL;
> > +   }
> > +
> > +   sk = socket(AF_INET, type, protocol);
> >     if (sk < 0) {
> > -           connman_error("Failed to create listener socket");
> > +           connman_error("Failed to create %s listener socket", proto);
> >             return -EIO;
> >     }
> >
> > -   //setsockopt(sk, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
> > -   //setsockopt(sk, SOL_IP, IP_PKTINFO, &opt, sizeof(opt));
> > -
> >     if (setsockopt(sk, SOL_SOCKET, SO_BINDTODEVICE,
> >                                     ifname, strlen(ifname) + 1) < 0) {
> > -           connman_error("Failed to bind listener interface");
> > +           connman_error("Failed to bind %s listener interface", proto);
> >             close(sk);
> >             return -EIO;
> >     }
> > @@ -768,25 +1178,75 @@
> >     sin.sin_family = AF_INET;
> >     sin.sin_port = htons(53);
> >     sin.sin_addr.s_addr = inet_addr("127.0.0.1");
> > -   //sin.sin_addr.s_addr = INADDR_ANY;
> > +   sin.sin_addr.s_addr = htonl(INADDR_ANY);
> >
> >     if (bind(sk, (struct sockaddr *) &sin, sizeof(sin)) < 0) {
> > -           connman_error("Failed to bind listener socket");
> > +           connman_error("Failed to bind %s listener socket", proto);
> > +           close(sk);
> > +           return -EIO;
> > +   }
> > +
> > +   if (protocol == IPPROTO_TCP && listen(sk, 10) < 0) {
> > +           connman_error("Failed to listen on TCP socket");
> >             close(sk);
> >             return -EIO;
> >     }
> >
> > -   listener_channel = g_io_channel_unix_new(sk);
> > -   if (listener_channel == NULL) {
> > -           connman_error("Failed to create listener channel");
> > +   channel = g_io_channel_unix_new(sk);
> > +   if (channel == NULL) {
> > +           connman_error("Failed to create %s listener channel", proto);
> >             close(sk);
> >             return -EIO;
> >     }
> >
> > -   g_io_channel_set_close_on_unref(listener_channel, TRUE);
> > +   g_io_channel_set_close_on_unref(channel, TRUE);
> > +
> > +   if (protocol == IPPROTO_TCP) {
> > +           tcp_listener_channel = channel;
> > +           tcp_listener_watch = g_io_add_watch(channel,
> > +                                   G_IO_IN, tcp_listener_event, NULL);
> > +   } else {
> > +           udp_listener_channel = channel;
> > +           udp_listener_watch = g_io_add_watch(channel,
> > +                                   G_IO_IN, udp_listener_event, NULL);
> > +   }
> > +
> > +   return 0;
> > +}
> > +
> > +static void destroy_udp_listener(void)
> > +{
> > +   DBG("");
> > +
> > +   if (udp_listener_watch > 0)
> > +           g_source_remove(udp_listener_watch);
> > +
> > +   g_io_channel_unref(udp_listener_channel);
> > +}
> > +
> > +static void destroy_tcp_listener(void)
> > +{
> > +   DBG("");
> >
> > -   listener_watch = g_io_add_watch(listener_channel, G_IO_IN,
> > -                                                   listener_event, NULL);
> > +   if (tcp_listener_watch > 0)
> > +           g_source_remove(tcp_listener_watch);
> > +
> > +   g_io_channel_unref(tcp_listener_channel);
> > +}
> > +
> > +static int create_listener(void)
> > +{
> > +   int err;
> > +
> > +   err = create_dns_listener(IPPROTO_UDP);
> > +   if (err < 0)
> > +           return err;
> > +
> > +   err = create_dns_listener(IPPROTO_TCP);
> > +   if (err < 0) {
> > +           destroy_udp_listener();
> > +           return err;
> > +   }
> >
> >     connman_resolver_append("lo", NULL, "127.0.0.1");
> >
> > @@ -797,13 +1257,8 @@
> > {
> >     GSList *list;
> >
> > -   DBG("");
> > -
> >     connman_resolver_remove_all("lo");
> >
> > -   if (listener_watch > 0)
> > -           g_source_remove(listener_watch);
> > -
> >     for (list = request_pending_list; list; list = list->next) {
> >             struct request_data *req = list->data;
> >
> > @@ -836,7 +1291,8 @@
> >     g_slist_free(request_list);
> >     request_list = NULL;
> >
> > -   g_io_channel_unref(listener_channel);
> > +   destroy_tcp_listener();
> > +   destroy_udp_listener();
> > }
> >
> > static int dnsproxy_init(void)
> > --- plugins/supplicant.c
> > +++ plugins/supplicant.c
> > @@ -2189,15 +2189,9 @@
> >
> >     connman_info("%s scanning %s", task->ifname,
> >                             scanning == TRUE ? "started" : "finished");
> > -}
> > -
> > -static gboolean delayed_scan(gpointer user_data)
> > -{
> > -   struct supplicant_task *task = user_data;
> >
> > -   supplicant_scan(task->device);
> > -
> > -   return FALSE;
> > +   if (scanning == TRUE)
> > +           task->scanning = TRUE;
> > }
> >
> > static void state_change(struct supplicant_task *task, DBusMessage *msg)
> > @@ -2293,13 +2287,7 @@
> >                             task_connect(task);
> >                     } else
> >                             task->network = NULL;
> > -           } else {
> > -                   if (task->state == WPA_DISCONNECTED)
> > -                           g_timeout_add_seconds(10, delayed_scan, task);
> > -
> > -                   remove_network(task);
> >             }
> > -
> >             break;
> >
> >     default:
> > @@ -2522,6 +2510,25 @@
> >     return 0;
> > }
> >
> > +void supplicant_remove_network(struct connman_network *network)
> > +{
> > +   struct supplicant_task *task;
> > +   int index;
> > +
> > +   DBG("network %p", network);
> > +
> > +   index = connman_network_get_index(network);
> > +
> > +   task = find_task_by_index(index);
> > +   if (task == NULL)
> > +           return;
> > +
> > +   if (task->network != network)
> > +           return;
> > +
> > +   remove_network(task);
> > +}
> > +
> > static void supplicant_activate(DBusConnection *conn)
> > {
> >     DBusMessage *message;
> > --- plugins/supplicant.h
> > +++ plugins/supplicant.h
> > @@ -37,3 +37,5 @@
> >
> > int supplicant_connect(struct connman_network *network);
> > int supplicant_disconnect(struct connman_network *network);
> > +
> > +void supplicant_remove_network(struct connman_network *network);
> > --- plugins/wifi.c
> > +++ plugins/wifi.c
> > @@ -62,6 +62,8 @@
> > static void network_remove(struct connman_network *network)
> > {
> >     DBG("network %p", network);
> > +
> > +   supplicant_remove_network(network);
> > }
> >
> > static int network_connect(struct connman_network *network)
> > --- src/inet.c
> > +++ src/inet.c
> > @@ -420,7 +420,7 @@
> > {
> >     enum connman_device_mode mode =
> CONNMAN_DEVICE_MODE_UNKNOWN;
> >     enum connman_device_type type;
> > -   struct connman_device *device;
> > +   struct connman_device *device = NULL;
> >     char *devname, *ident = NULL;
> >     char *addr = NULL, *name = NULL, *node = NULL;
> >
> > @@ -459,6 +459,11 @@
> >             break;
> >     }
> >
> > +   if (g_strcmp0(addr, "00:00:00:00:00:00") == 0) {
> > +           connman_info("Wrong address ignoring interface %s ", devname);
> > +           goto done;
> > +   }
> > +
> >     device = connman_device_create(name, type);
> >     if (device == NULL)
> >             goto done;
> > --- src/manager.c
> > +++ src/manager.c
> > @@ -224,8 +224,8 @@
> >
> >     DBG("conn %p", conn);
> >
> > -   dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &path,
> > -                         DBUS_TYPE_INVALID);
> > +   dbus_message_get_args(msg, NULL, DBUS_TYPE_OBJECT_PATH, &path,
> > +                                                   DBUS_TYPE_INVALID);
> >
> >     if (__connman_security_check_privilege(msg,
> >                             CONNMAN_SECURITY_PRIVILEGE_MODIFY) < 0)
> > @@ -657,7 +657,7 @@
> >     { "GetState",          "",      "s",     get_state          },
> >     { "CreateProfile",     "s",     "o",     create_profile     },
> >     { "RemoveProfile",     "o",     "",      remove_profile     },
> > -   { "RemoveProvider",    "s",     "",      remove_provider    },
> > +   { "RemoveProvider",    "o",     "",      remove_provider    },
> >     { "RequestScan",       "s",     "",      request_scan       },
> >     { "EnableTechnology",  "s",     "",      enable_technology,
> >                                             G_DBUS_METHOD_FLAG_ASYNC },
> > --- src/provider.c
> > +++ src/provider.c
> > @@ -216,18 +216,30 @@
> > int __connman_provider_remove(const char *path)
> > {
> >     struct connman_provider *provider;
> > +   GHashTableIter iter;
> > +   gpointer value, key;
> >
> >     DBG("path %s", path);
> >
> > -   provider = g_hash_table_lookup(provider_hash, path);
> > -   if (provider == NULL) {
> > -           DBG("patch %s not found", path);
> > -           return -ENXIO;
> > -   }
> > +   g_hash_table_iter_init(&iter, provider_hash);
> > +   while (g_hash_table_iter_next(&iter, &key, &value) == TRUE) {
> > +           const char *srv_path;
> > +           provider = value;
> > +
> > +           if (provider->vpn_service == NULL)
> > +                   continue;
> >
> > -   g_hash_table_remove(provider_hash, path);
> > +           srv_path = __connman_service_get_path(provider->vpn_service);
> > +
> > +           if (g_strcmp0(srv_path, path) == 0) {
> > +                   DBG("Removing VPN %s", provider->identifier);
> > +                   g_hash_table_remove(provider_hash,
> > +                                           provider->identifier);
> > +                   return 0;
> > +           }
> > +   }
> >
> > -   return 0;
> > +   return -ENXIO;
> > }
> >
> > static int set_connected(struct connman_provider *provider,
> > --- src/resolver.c
> > +++ src/resolver.c
> > @@ -389,8 +389,7 @@
> >     unsigned int count;
> >     mode_t old_umask;
> >
> > -   content = g_string_new("# Generated by Connection Manager\n"
> > -                                           "options edns0\n");
> > +   content = g_string_new("# Generated by Connection Manager\n");
> >
> >     /*
> >      * Nameservers are added in reverse so that the most recently
> > --- test/disconnect-vpn
> > +++ test/disconnect-vpn
> > @@ -4,7 +4,7 @@
> > import dbus
> >
> > if (len(sys.argv) < 2):
> > -   print "Usage: %s <provider name> " % (sys.argv[0])
> > +   print "Usage: %s <VPN service path> " % (sys.argv[0])
> >     sys.exit(1)
> >
> > bus = dbus.SystemBus()
> > @@ -18,5 +18,4 @@
> >
> > manager.RemoveProvider(sys.argv[1])
> >
> > -print "remove path is %s" %(path)
> >
> >
> > ++++++ connman.yaml
> > --- connman.yaml
> > +++ connman.yaml
> > @@ -1,6 +1,6 @@
> > Name: connman
> > Summary: Connection Manager
> > -Version: 0.60.3
> > +Version: 0.60.5
> > Release: 1
> > Group: System/Networking
> > License: GPLv2
> >
> > _______________________________________________
> > Meego-commits mailing list
> > [email protected]
> > http://lists.meego.com/listinfo/meego-commits

_______________________________________________
MeeGo-packaging mailing list
[email protected]
http://lists.meego.com/listinfo/meego-packaging

Reply via email to