[meego-commits] 8568: Changes to MeeGo:1.1:Core/connman
Rolla Selbak
no_reply at build.meego.com
Mon Oct 18 06:53:38 UTC 2010
Hi,
I have made the following changes to connman in project MeeGo:1.1:Core. Please review and accept ASAP.
Thank You,
Rolla Selbak
[This message was auto-generated]
---
Request #8568:
submit: MeeGo:1.1:Core:Testing/connman(r2) -> MeeGo:1.1:Core/connman
Message:
Promote from MeeGo:1.1:Core:Testing
State: new 2010-10-17T23:53:36 rolla
Comment: None
changes files:
--------------
--- connman.changes
+++ connman.changes
@@ -0,0 +1,3 @@
+* Sat Oct 09 2010 Martin Xu <martin.xu at intel.com> - 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
More information about the MeeGo-commits
mailing list