Rolla:
This commit is used to fix BMC #7497 ( - broken DNS) mentioned by Gavin. Please 
help to accepted it. Thanks! ;-)

> -----Original Message-----
> From: [email protected]
> [mailto:[email protected]] On Behalf Of Martin Xu
> Sent: Monday, October 18, 2010 10:15 AM
> To: [email protected]
> Subject: [meego-commits] 8559: Changes to
> MeeGo:1.1:Core:Testing/connman
>
> 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 #8559:
>
>   submit:
> home:martin:branches:MeeGo:1.1:Core:Testing/connman(r2)(cleanup) ->
> MeeGo:1.1:Core:Testing/connman
>
>
> Message:
>     upgrade to 0.60.5 to fix BMC #8474
>
> State:   new          2010-10-17T19:15:28 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
> +
>
> 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