summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authortaesubkim <taesub.kim@samsung.com>2016-04-26 15:47:01 +0900
committertaesubkim <taesub.kim@samsung.com>2016-04-26 16:14:46 +0900
commit22633ced6225d294ce8483efbf2b39ea0c0c1b65 (patch)
tree8c5f2312feec413068a18e57a80321b31b4f7b74 /src
parentbcae74da8fa2958b3fec9153fc33e41f0e0317bf (diff)
downloadconnman-22633ced6225d294ce8483efbf2b39ea0c0c1b65.tar.gz
connman-22633ced6225d294ce8483efbf2b39ea0c0c1b65.tar.bz2
connman-22633ced6225d294ce8483efbf2b39ea0c0c1b65.zip
Imported Upstream version 1.29upstream/1.29
Change-Id: I2958446c35966d9ed72df0120b80561be7d89f54 Signed-off-by: Taesub Kim <taesub.kim@samsung.com>
Diffstat (limited to 'src')
-rw-r--r--src/agent-connman.c29
-rw-r--r--src/agent.c13
-rw-r--r--src/config.c6
-rw-r--r--src/connection.c12
-rw-r--r--src/connman.h12
-rw-r--r--src/connman.service.in5
-rw-r--r--src/counter.c5
-rw-r--r--src/dhcp.c13
-rw-r--r--src/dhcpv6.c75
-rw-r--r--src/dnsproxy.c92
-rw-r--r--src/inotify.c30
-rw-r--r--src/ipconfig.c102
-rw-r--r--src/ipv6pd.c6
-rw-r--r--src/main.c3
-rw-r--r--src/net.connman.service.in2
-rw-r--r--src/network.c261
-rw-r--r--src/ntp.c2
-rw-r--r--src/peer.c99
-rw-r--r--src/proxy.c8
-rw-r--r--src/resolver.c8
-rw-r--r--src/rfkill.c32
-rw-r--r--src/rtnl.c39
-rw-r--r--src/service.c139
-rw-r--r--src/shared/sha1.c189
-rw-r--r--src/shared/sha1.h33
-rw-r--r--src/technology.c47
-rw-r--r--src/util.c88
-rw-r--r--src/wispr.c2
28 files changed, 675 insertions, 677 deletions
diff --git a/src/agent-connman.c b/src/agent-connman.c
index b2049a3d..84404510 100644
--- a/src/agent-connman.c
+++ b/src/agent-connman.c
@@ -79,8 +79,10 @@ static void request_input_passphrase_reply(DBusMessage *reply, void *user_data)
int name_len = 0;
DBusMessageIter iter, dict;
- if (!reply)
- goto out;
+ if (!reply) {
+ error = CONNMAN_ERROR_INTERFACE ".OperationAborted";
+ goto done;
+ }
if (dbus_message_get_type(reply) == DBUS_MESSAGE_TYPE_ERROR) {
error = dbus_message_get_error_name(reply);
@@ -160,7 +162,7 @@ done:
values_received, name, name_len,
identity, passphrase, wps, wpspin,
error, passphrase_reply->user_data);
-out:
+
g_free(passphrase_reply);
}
@@ -365,8 +367,10 @@ static void request_input_login_reply(DBusMessage *reply, void *user_data)
char *key;
DBusMessageIter iter, dict;
- if (!reply)
- goto out;
+ if (!reply) {
+ error = CONNMAN_ERROR_INTERFACE ".OperationAborted";
+ goto done;
+ }
if (dbus_message_get_type(reply) == DBUS_MESSAGE_TYPE_ERROR) {
error = dbus_message_get_error_name(reply);
@@ -414,7 +418,7 @@ done:
username_password_reply->service, values_received,
NULL, 0, username, password, FALSE, NULL, error,
username_password_reply->user_data);
-out:
+
g_free(username_password_reply);
}
@@ -582,6 +586,11 @@ static void request_browser_reply(DBusMessage *reply, void *user_data)
bool result = false;
const char *error = NULL;
+ if (!reply) {
+ error = CONNMAN_ERROR_INTERFACE ".OperationAborted";
+ goto done;
+ }
+
if (dbus_message_get_type(reply) == DBUS_MESSAGE_TYPE_ERROR) {
error = dbus_message_get_error_name(reply);
goto done;
@@ -674,8 +683,10 @@ static void request_peer_authorization_reply(DBusMessage *reply,
char *wpspin = NULL;
char *key;
- if (!reply)
- goto out;
+ if (!reply) {
+ error = CONNMAN_ERROR_INTERFACE ".OperationAborted";
+ goto done;
+ }
if (dbus_message_get_type(reply) == DBUS_MESSAGE_TYPE_ERROR) {
error = dbus_message_get_error_name(reply);
@@ -716,7 +727,7 @@ static void request_peer_authorization_reply(DBusMessage *reply,
done:
auth_reply->peer_callback(auth_reply->peer, choice_done, wpspin,
error, auth_reply->user_data);
-out:
+
g_free(auth_reply);
}
diff --git a/src/agent.c b/src/agent.c
index a3400262..bdeb0e71 100644
--- a/src/agent.c
+++ b/src/agent.c
@@ -502,7 +502,7 @@ void connman_agent_cancel(void *user_context)
g_hash_table_iter_init(&iter, agent_hash);
while (g_hash_table_iter_next(&iter, &key, &value)) {
- GList *list;
+ GList *list, *next;
struct connman_agent *agent = value;
/*
@@ -512,6 +512,8 @@ void connman_agent_cancel(void *user_context)
while (list) {
struct connman_agent_request *request = list->data;
+ next = list->next;
+
if (request && request->user_context &&
request->user_context ==
user_context) {
@@ -521,10 +523,11 @@ void connman_agent_cancel(void *user_context)
agent_request_free(request);
- agent->queue = list->next;
- list = g_list_delete_link(list, list);
- } else
- list = list->next;
+ agent->queue = g_list_delete_link(agent->queue,
+ list);
+ }
+
+ list = next;
}
/*
diff --git a/src/config.c b/src/config.c
index 93a788a1..a4c117e1 100644
--- a/src/config.c
+++ b/src/config.c
@@ -891,7 +891,7 @@ static void config_notify_handler(struct inotify_event *event,
return;
}
- if (event->mask & IN_CREATE)
+ if (event->mask & IN_CREATE || event->mask & IN_MOVED_TO)
create_config(ident);
if (event->mask & IN_MODIFY) {
@@ -1435,12 +1435,14 @@ static void generate_random_string(char *str, int length)
{
uint8_t val;
int i;
+ uint64_t rand;
memset(str, '\0', length);
for (i = 0; i < length-1; i++) {
do {
- val = (uint8_t)(random() % 122);
+ __connman_util_get_random(&rand);
+ val = (uint8_t)(rand % 122);
if (val < 48)
val += 48;
} while((val > 57 && val < 65) || (val > 90 && val < 97));
diff --git a/src/connection.c b/src/connection.c
index 8fe97258..aa4e1c05 100644
--- a/src/connection.c
+++ b/src/connection.c
@@ -401,13 +401,9 @@ static struct gateway_data *add_gateway(struct connman_service *service,
data->ipv4_gateway = old->ipv4_gateway;
old->ipv4_gateway = NULL;
}
- } else {
- /*
- * Only take a ref if we are adding new stuff to hash.
- */
- connman_service_ref(service);
}
+ connman_service_ref(data->service);
g_hash_table_replace(gateway_hash, service, data);
return data;
@@ -708,6 +704,8 @@ static void remove_gateway(gpointer user_data)
g_free(data->ipv6_gateway);
}
+ connman_service_unref(data->service);
+
g_free(data);
}
@@ -999,9 +997,7 @@ void __connman_connection_gateway_remove(struct connman_service *service,
(data->ipv4_gateway && !data->ipv6_gateway
&& do_ipv4) ||
(data->ipv6_gateway && !data->ipv4_gateway
- && do_ipv6)
- ) {
- connman_service_unref(service);
+ && do_ipv6)) {
g_hash_table_remove(gateway_hash, service);
} else
DBG("Not yet removing gw ipv4 %p/%d ipv6 %p/%d",
diff --git a/src/connman.h b/src/connman.h
index da012152..cbd88d88 100644
--- a/src/connman.h
+++ b/src/connman.h
@@ -338,7 +338,7 @@ void __connman_ipconfig_newlink(int index, unsigned short type,
unsigned short mtu,
struct rtnl_link_stats *stats);
void __connman_ipconfig_dellink(int index, struct rtnl_link_stats *stats);
-void __connman_ipconfig_newaddr(int index, int family, const char *label,
+int __connman_ipconfig_newaddr(int index, int family, const char *label,
unsigned char prefixlen, const char *address);
void __connman_ipconfig_deladdr(int index, int family, const char *label,
unsigned char prefixlen, const char *address);
@@ -451,6 +451,7 @@ typedef void (* dhcpv6_cb) (struct connman_network *network,
typedef void (* dhcp_cb) (struct connman_ipconfig *ipconfig,
struct connman_network *opt_network,
bool success, gpointer data);
+char *__connman_dhcp_get_server_address(struct connman_ipconfig *ipconfig);
int __connman_dhcp_start(struct connman_ipconfig *ipconfig,
struct connman_network *network, dhcp_cb callback,
gpointer user_data);
@@ -586,9 +587,8 @@ int __connman_network_connect(struct connman_network *network);
int __connman_network_disconnect(struct connman_network *network);
int __connman_network_clear_ipconfig(struct connman_network *network,
struct connman_ipconfig *ipconfig);
-int __connman_network_set_ipconfig(struct connman_network *network,
- struct connman_ipconfig *ipconfig_ipv4,
- struct connman_ipconfig *ipconfig_ipv6);
+int __connman_network_enable_ipconfig(struct connman_network *network,
+ struct connman_ipconfig *ipconfig);
const char *__connman_network_get_type(struct connman_network *network);
const char *__connman_network_get_group(struct connman_network *network);
@@ -1034,3 +1034,7 @@ void __connman_nfacct_cleanup(void);
int __connman_machine_init(void);
void __connman_machine_cleanup(void);
+
+int __connman_util_get_random(uint64_t *val);
+int __connman_util_init(void);
+void __connman_util_cleanup(void);
diff --git a/src/connman.service.in b/src/connman.service.in
index 7b6195e9..ba4dedd7 100644
--- a/src/connman.service.in
+++ b/src/connman.service.in
@@ -2,13 +2,14 @@
Description=Connection service
Requires=dbus.socket
After=dbus.socket
-Before=remote-fs.target
+Before=remote-fs-pre.target
+Wants=remote-fs-pre.target
[Service]
Type=dbus
BusName=net.connman
Restart=on-failure
-ExecStart=@prefix@/sbin/connmand -n
+ExecStart=@sbindir@/connmand -n
StandardOutput=null
[Install]
diff --git a/src/counter.c b/src/counter.c
index 06e5daff..8ea6205b 100644
--- a/src/counter.c
+++ b/src/counter.c
@@ -133,8 +133,11 @@ void __connman_counter_send_usage(const char *path,
struct connman_counter *counter;
counter = g_hash_table_lookup(counter_table, path);
- if (!counter)
+ if (!counter) {
+ if (message)
+ dbus_message_unref(message);
return;
+ }
dbus_message_set_destination(message, counter->owner);
dbus_message_set_path(message, counter->path);
diff --git a/src/dhcp.c b/src/dhcp.c
index 505d9f06..09f462bf 100644
--- a/src/dhcp.c
+++ b/src/dhcp.c
@@ -582,6 +582,17 @@ static int dhcp_release(struct connman_dhcp *dhcp)
return 0;
}
+char *__connman_dhcp_get_server_address(struct connman_ipconfig *ipconfig)
+{
+ struct connman_dhcp *dhcp;
+
+ dhcp = g_hash_table_lookup(ipconfig_table, ipconfig);
+ if (!dhcp)
+ return NULL;
+
+ return g_dhcp_client_get_server_address(dhcp->dhcp_client);
+}
+
int __connman_dhcp_start(struct connman_ipconfig *ipconfig,
struct connman_network *network, dhcp_cb callback,
gpointer user_data)
@@ -672,4 +683,6 @@ void __connman_dhcp_cleanup(void)
g_hash_table_destroy(ipconfig_table);
ipconfig_table = NULL;
+
+ dhcp_cleanup_random();
}
diff --git a/src/dhcpv6.c b/src/dhcpv6.c
index 5f8029f1..bdb3b987 100644
--- a/src/dhcpv6.c
+++ b/src/dhcpv6.c
@@ -105,25 +105,37 @@ static void clear_timer(struct connman_dhcpv6 *dhcp)
}
}
-static inline float get_random(void)
+static inline guint get_random(void)
{
- return (rand() % 200 - 100) / 1000.0;
+ uint64_t val;
+
+ __connman_util_get_random(&val);
+
+ /* Make sure the value is always positive so strip MSB */
+ return ((uint32_t)val) >> 1;
+}
+
+static guint compute_random(guint val)
+{
+ return val - val / 10 +
+ (get_random() % (2 * 1000)) * val / 10 / 1000;
}
/* Calculate a random delay, RFC 3315 chapter 14 */
/* RT and MRT are milliseconds */
static guint calc_delay(guint RT, guint MRT)
{
- float delay = get_random();
- float rt = RT * (2 + delay);
+ if (MRT && (RT > MRT / 2))
+ RT = compute_random(MRT);
+ else
+ RT += compute_random(RT);
- if (rt > MRT)
- rt = MRT * (1 + delay);
-
- if (rt < 0)
- rt = MRT;
+ return RT;
+}
- return (guint)rt;
+static guint initial_rt(guint timeout)
+{
+ return compute_random(timeout);
}
static void free_prefix(gpointer data)
@@ -1095,7 +1107,7 @@ static void re_cb(enum request_type req_type, GDHCPClient *dhcp_client,
if (!option) {
switch (req_type) {
case REQ_REQUEST:
- dhcpv6_request(dhcp, true);
+ do_resend_request(dhcp);
break;
case REQ_REBIND:
dhcpv6_rebind(dhcp);
@@ -1220,7 +1232,7 @@ static gboolean start_rebind(gpointer user_data)
if (check_restart(dhcp) < 0)
return FALSE;
- dhcp->RT = REB_TIMEOUT * (1 + get_random());
+ dhcp->RT = initial_rt(REB_TIMEOUT);
DBG("rebind initial RT timeout %d msec", dhcp->RT);
@@ -1387,7 +1399,7 @@ static gboolean start_renew(gpointer user_data)
{
struct connman_dhcpv6 *dhcp = user_data;
- dhcp->RT = REN_TIMEOUT * (1 + get_random());
+ dhcp->RT = initial_rt(REN_TIMEOUT);
DBG("renew initial RT timeout %d msec", dhcp->RT);
@@ -1585,7 +1597,7 @@ static gboolean start_info_req(gpointer user_data)
struct connman_dhcpv6 *dhcp = user_data;
/* Set the retransmission timeout, RFC 3315 chapter 14 */
- dhcp->RT = INF_TIMEOUT * (1 + get_random());
+ dhcp->RT = initial_rt(INF_TIMEOUT);
DBG("info initial RT timeout %d msec", dhcp->RT);
@@ -1601,6 +1613,7 @@ int __connman_dhcpv6_start_info(struct connman_network *network,
{
struct connman_dhcpv6 *dhcp;
int delay;
+ uint64_t rand;
DBG("");
@@ -1626,7 +1639,8 @@ int __connman_dhcpv6_start_info(struct connman_network *network,
g_hash_table_replace(network_table, network, dhcp);
/* Initial timeout, RFC 3315, 18.1.5 */
- delay = rand() % 1000;
+ __connman_util_get_random(&rand);
+ delay = rand % 1000;
dhcp->timeout = g_timeout_add(delay, start_info_req, dhcp);
@@ -1650,7 +1664,7 @@ static void advertise_cb(GDHCPClient *dhcp_client, gpointer user_data)
return;
}
- dhcp->RT = REQ_TIMEOUT * (1 + get_random());
+ dhcp->RT = initial_rt(REQ_TIMEOUT);
DBG("request initial RT timeout %d msec", dhcp->RT);
dhcp->timeout = g_timeout_add(dhcp->RT, timeout_request, dhcp);
@@ -1668,9 +1682,16 @@ static void solicitation_cb(GDHCPClient *dhcp_client, gpointer user_data)
clear_timer(dhcp);
- do_dad(dhcp_client, dhcp);
-
g_dhcpv6_client_clear_retransmit(dhcp_client);
+
+ if (g_dhcpv6_client_get_status(dhcp_client) != 0) {
+ if (dhcp->callback)
+ dhcp->callback(dhcp->network,
+ CONNMAN_DHCPV6_STATUS_FAIL, NULL);
+ return;
+ }
+
+ do_dad(dhcp_client, dhcp);
}
static gboolean timeout_solicitation(gpointer user_data)
@@ -1761,7 +1782,7 @@ static gboolean start_solicitation(gpointer user_data)
struct connman_dhcpv6 *dhcp = user_data;
/* Set the retransmission timeout, RFC 3315 chapter 14 */
- dhcp->RT = SOL_TIMEOUT * (1 + get_random());
+ dhcp->RT = initial_rt(SOL_TIMEOUT);
DBG("solicit initial RT timeout %d msec", dhcp->RT);
@@ -1778,6 +1799,7 @@ int __connman_dhcpv6_start(struct connman_network *network,
struct connman_service *service;
struct connman_dhcpv6 *dhcp;
int delay;
+ uint64_t rand;
DBG("");
@@ -1807,7 +1829,8 @@ int __connman_dhcpv6_start(struct connman_network *network,
g_hash_table_replace(network_table, network, dhcp);
/* Initial timeout, RFC 3315, 17.1.2 */
- delay = rand() % 1000;
+ __connman_util_get_random(&rand);
+ delay = rand % 1000;
/*
* Start from scratch.
@@ -2171,7 +2194,7 @@ static gboolean start_pd_rebind(gpointer user_data)
if (check_pd_restart(dhcp) < 0)
return FALSE;
- dhcp->RT = REB_TIMEOUT * (1 + get_random());
+ dhcp->RT = initial_rt(REB_TIMEOUT);
DBG("rebind initial RT timeout %d msec", dhcp->RT);
@@ -2223,7 +2246,7 @@ static gboolean start_pd_rebind_with_confirm(gpointer user_data)
{
struct connman_dhcpv6 *dhcp = user_data;
- dhcp->RT = CNF_TIMEOUT * (1 + get_random());
+ dhcp->RT = initial_rt(CNF_TIMEOUT);
DBG("rebind with confirm initial RT timeout %d msec", dhcp->RT);
@@ -2260,7 +2283,7 @@ static gboolean start_pd_renew(gpointer user_data)
{
struct connman_dhcpv6 *dhcp = user_data;
- dhcp->RT = REN_TIMEOUT * (1 + get_random());
+ dhcp->RT = initial_rt(REN_TIMEOUT);
DBG("renew initial RT timeout %d msec", dhcp->RT);
@@ -2476,7 +2499,7 @@ static void advertise_pd_cb(GDHCPClient *dhcp_client, gpointer user_data)
return;
}
- dhcp->RT = REQ_TIMEOUT * (1 + get_random());
+ dhcp->RT = initial_rt(REQ_TIMEOUT);
DBG("request initial RT timeout %d msec", dhcp->RT);
dhcp->timeout = g_timeout_add(dhcp->RT, timeout_pd_request, dhcp);
@@ -2531,7 +2554,7 @@ static gboolean start_pd_solicitation(gpointer user_data)
struct connman_dhcpv6 *dhcp = user_data;
/* Set the retransmission timeout, RFC 3315 chapter 14 */
- dhcp->RT = SOL_TIMEOUT * (1 + get_random());
+ dhcp->RT = initial_rt(SOL_TIMEOUT);
DBG("solicit initial RT timeout %d msec", dhcp->RT);
@@ -2640,8 +2663,6 @@ int __connman_dhcpv6_init(void)
{
DBG("");
- srand(time(NULL));
-
network_table = g_hash_table_new_full(g_direct_hash, g_direct_equal,
NULL, remove_network);
diff --git a/src/dnsproxy.c b/src/dnsproxy.c
index bdd7fd5c..cf3490c4 100644
--- a/src/dnsproxy.c
+++ b/src/dnsproxy.c
@@ -215,10 +215,15 @@ static GSList *request_list = NULL;
static GHashTable *listener_table = NULL;
static time_t next_refresh;
static GHashTable *partial_tcp_req_table;
+static guint cache_timer = 0;
static guint16 get_id(void)
{
- return random();
+ uint64_t rand;
+
+ __connman_util_get_random(&rand);
+
+ return rand;
}
static int protocol_offset(int protocol)
@@ -526,6 +531,8 @@ static void destroy_request_data(struct request_data *req)
static gboolean request_timeout(gpointer user_data)
{
struct request_data *req = user_data;
+ struct sockaddr *sa;
+ int sk;
if (!req)
return FALSE;
@@ -533,47 +540,38 @@ static gboolean request_timeout(gpointer user_data)
DBG("id 0x%04x", req->srcid);
request_list = g_slist_remove(request_list, req);
- req->numserv--;
- if (req->resplen > 0 && req->resp) {
- int sk, err;
+ if (req->protocol == IPPROTO_UDP) {
+ sk = get_req_udp_socket(req);
+ sa = &req->sa;
+ } else if (req->protocol == IPPROTO_TCP) {
+ sk = req->client_sk;
+ sa = NULL;
+ } else
+ goto out;
- if (req->protocol == IPPROTO_UDP) {
- sk = get_req_udp_socket(req);
- if (sk < 0)
- return FALSE;
+ if (req->resplen > 0 && req->resp) {
+ /*
+ * Here we have received at least one reply (probably telling
+ * "not found" result), so send that back to client instead
+ * of more fatal server failed error.
+ */
+ if (sk >= 0)
+ sendto(sk, req->resp, req->resplen, MSG_NOSIGNAL,
+ sa, req->sa_len);
- err = sendto(sk, req->resp, req->resplen, MSG_NOSIGNAL,
- &req->sa, req->sa_len);
- } else {
- sk = req->client_sk;
- err = send(sk, req->resp, req->resplen, MSG_NOSIGNAL);
- if (err < 0)
- close(sk);
- }
- if (err < 0)
- return FALSE;
- } else if (req->request && req->numserv == 0) {
+ } else if (req->request) {
+ /*
+ * There was not reply from server at all.
+ */
struct domain_hdr *hdr;
- 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 + protocol_offset(req->protocol));
+ hdr->id = req->srcid;
- hdr = (void *) (req->request);
- hdr->id = req->srcid;
-
- sk = get_req_udp_socket(req);
- if (sk >= 0)
- send_response(sk, req->request,
- req->request_len, &req->sa,
- req->sa_len, IPPROTO_UDP);
- }
+ if (sk >= 0)
+ send_response(sk, req->request, req->request_len,
+ sa, req->sa_len, req->protocol);
}
/*
@@ -586,6 +584,7 @@ static gboolean request_timeout(gpointer user_data)
GINT_TO_POINTER(req->client_sk));
}
+out:
req->timeout = 0;
destroy_request_data(req);
@@ -764,6 +763,8 @@ static void cache_element_destroy(gpointer value)
static gboolean try_remove_cache(gpointer user_data)
{
+ cache_timer = 0;
+
if (__sync_fetch_and_sub(&cache_refcount, 1) == 1) {
DBG("No cache users, removing it.");
@@ -2204,8 +2205,8 @@ static void destroy_server(struct server_data *server)
* without any good reason. The small delay allows the new RDNSS to
* create a new DNS server instance and the refcount does not go to 0.
*/
- if (cache)
- g_timeout_add_seconds(3, try_remove_cache, NULL);
+ if (cache && !cache_timer)
+ cache_timer = g_timeout_add_seconds(3, try_remove_cache, NULL);
g_free(server);
}
@@ -3460,6 +3461,9 @@ static bool udp_listener_event(GIOChannel *channel, GIOCondition condition,
return true;
}
+ req->name = g_strdup(query);
+ req->request = g_malloc(len);
+ memcpy(req->request, buf, len);
req->timeout = g_timeout_add_seconds(5, request_timeout, req);
request_list = g_slist_append(request_list, req);
@@ -3829,8 +3833,6 @@ int __connman_dnsproxy_init(void)
DBG("");
- srandom(time(NULL));
-
listener_table = g_hash_table_new_full(g_direct_hash, g_direct_equal,
NULL, g_free);
@@ -3862,6 +3864,16 @@ void __connman_dnsproxy_cleanup(void)
{
DBG("");
+ if (cache_timer) {
+ g_source_remove(cache_timer);
+ cache_timer = 0;
+ }
+
+ if (cache) {
+ g_hash_table_destroy(cache);
+ cache = NULL;
+ }
+
connman_notifier_unregister(&dnsproxy_notifier);
g_hash_table_foreach(listener_table, remove_listener, NULL);
diff --git a/src/inotify.c b/src/inotify.c
index 1ab3807c..c251c6ff 100644
--- a/src/inotify.c
+++ b/src/inotify.c
@@ -35,6 +35,8 @@
#include "connman.h"
struct connman_inotify {
+ unsigned int refcount;
+
GIOChannel *channel;
uint watch;
int wd;
@@ -42,13 +44,30 @@ struct connman_inotify {
GSList *list;
};
+static void cleanup_inotify(gpointer user_data);
+
+static void connman_inotify_ref(struct connman_inotify *i)
+{
+ __sync_fetch_and_add(&i->refcount, 1);
+}
+
+static void connman_inotify_unref(gpointer data)
+{
+ struct connman_inotify *i = data;
+
+ if (__sync_fetch_and_sub(&i->refcount, 1) != 1)
+ return;
+
+ cleanup_inotify(data);
+}
+
static GHashTable *inotify_hash;
static gboolean inotify_data(GIOChannel *channel, GIOCondition cond,
gpointer user_data)
{
struct connman_inotify *inotify = user_data;
- char buffer[256];
+ char buffer[sizeof(struct inotify_event) + NAME_MAX + 1];
char *next_event;
gsize bytes_read;
GIOStatus status;
@@ -60,7 +79,7 @@ static gboolean inotify_data(GIOChannel *channel, GIOCondition cond,
}
status = g_io_channel_read_chars(channel, buffer,
- sizeof(buffer) -1, &bytes_read, NULL);
+ sizeof(buffer), &bytes_read, NULL);
switch (status) {
case G_IO_STATUS_NORMAL:
@@ -75,6 +94,8 @@ static gboolean inotify_data(GIOChannel *channel, GIOCondition cond,
next_event = buffer;
+ connman_inotify_ref(inotify);
+
while (bytes_read > 0) {
struct inotify_event *event;
gchar *ident;
@@ -102,6 +123,8 @@ static gboolean inotify_data(GIOChannel *channel, GIOCondition cond,
}
}
+ connman_inotify_unref(inotify);
+
return TRUE;
}
@@ -179,6 +202,7 @@ int connman_inotify_register(const char *path, inotify_event_cb callback)
if (!inotify)
return -ENOMEM;
+ inotify->refcount = 1;
inotify->wd = -1;
err = create_watch(path, inotify);
@@ -225,7 +249,7 @@ int __connman_inotify_init(void)
DBG("");
inotify_hash = g_hash_table_new_full(g_str_hash, g_str_equal,
- g_free, cleanup_inotify);
+ g_free, connman_inotify_unref);
return 0;
}
diff --git a/src/ipconfig.c b/src/ipconfig.c
index ae70745f..f8c148be 100644
--- a/src/ipconfig.c
+++ b/src/ipconfig.c
@@ -45,8 +45,6 @@ struct connman_ipconfig {
int index;
enum connman_ipconfig_type type;
- struct connman_ipconfig *origin;
-
const struct connman_ipconfig_ops *ops;
void *ops_data;
@@ -135,6 +133,7 @@ const char *__connman_ipconfig_type2string(enum connman_ipconfig_type type)
{
switch (type) {
case CONNMAN_IPCONFIG_TYPE_UNKNOWN:
+ case CONNMAN_IPCONFIG_TYPE_ALL:
return "unknown";
case CONNMAN_IPCONFIG_TYPE_IPV4:
return "IPv4";
@@ -445,12 +444,9 @@ static void update_stats(struct connman_ipdevice *ipdevice,
if (!ipdevice->config_ipv4 && !ipdevice->config_ipv6)
return;
- if (ipdevice->config_ipv4)
- service = __connman_ipconfig_get_data(ipdevice->config_ipv4);
- else if (ipdevice->config_ipv6)
- service = __connman_ipconfig_get_data(ipdevice->config_ipv6);
- else
- return;
+ service = __connman_service_lookup_from_index(ipdevice->index);
+
+ DBG("service %p", service);
if (!service)
return;
@@ -642,7 +638,7 @@ static inline gint check_duplicate_address(gconstpointer a, gconstpointer b)
return g_strcmp0(addr1->local, addr2->local);
}
-void __connman_ipconfig_newaddr(int index, int family, const char *label,
+int __connman_ipconfig_newaddr(int index, int family, const char *label,
unsigned char prefixlen, const char *address)
{
struct connman_ipdevice *ipdevice;
@@ -655,11 +651,11 @@ void __connman_ipconfig_newaddr(int index, int family, const char *label,
ipdevice = g_hash_table_lookup(ipdevice_hash, GINT_TO_POINTER(index));
if (!ipdevice)
- return;
+ return -ENXIO;
ipaddress = connman_ipaddress_alloc(family);
if (!ipaddress)
- return;
+ return -ENOMEM;
ipaddress->prefixlen = prefixlen;
ipaddress->local = g_strdup(address);
@@ -667,7 +663,7 @@ void __connman_ipconfig_newaddr(int index, int family, const char *label,
if (g_slist_find_custom(ipdevice->address_list, ipaddress,
check_duplicate_address)) {
connman_ipaddress_free(ipaddress);
- return;
+ return -EALREADY;
}
if (family == AF_INET)
@@ -675,7 +671,7 @@ void __connman_ipconfig_newaddr(int index, int family, const char *label,
else if (family == AF_INET6)
type = CONNMAN_IPCONFIG_TYPE_IPV6;
else
- return;
+ return -EINVAL;
ipdevice->address_list = g_slist_prepend(ipdevice->address_list,
ipaddress);
@@ -698,7 +694,7 @@ void __connman_ipconfig_newaddr(int index, int family, const char *label,
goto out;
if ((ipdevice->flags & (IFF_RUNNING | IFF_LOWER_UP)) != (IFF_RUNNING | IFF_LOWER_UP))
- return;
+ goto out;
for (list = g_list_first(ipconfig_list); list;
list = g_list_next(list)) {
@@ -719,6 +715,7 @@ void __connman_ipconfig_newaddr(int index, int family, const char *label,
out:
g_free(ifname);
+ return 0;
}
void __connman_ipconfig_deladdr(int index, int family, const char *label,
@@ -1253,11 +1250,6 @@ void __connman_ipconfig_unref_debug(struct connman_ipconfig *ipconfig,
__connman_ipconfig_set_ops(ipconfig, NULL);
- if (ipconfig->origin && ipconfig->origin != ipconfig) {
- __connman_ipconfig_unref(ipconfig->origin);
- ipconfig->origin = NULL;
- }
-
connman_ipaddress_free(ipconfig->system);
connman_ipaddress_free(ipconfig->address);
g_free(ipconfig->last_dhcp_address);
@@ -1302,9 +1294,6 @@ int __connman_ipconfig_get_index(struct connman_ipconfig *ipconfig)
if (!ipconfig)
return -1;
- if (ipconfig->origin)
- return ipconfig->origin->index;
-
return ipconfig->index;
}
@@ -2128,6 +2117,7 @@ int __connman_ipconfig_set_config(struct connman_ipconfig *ipconfig,
type = AF_INET6;
break;
case CONNMAN_IPCONFIG_TYPE_UNKNOWN:
+ case CONNMAN_IPCONFIG_TYPE_ALL:
type = -1;
break;
}
@@ -2217,6 +2207,7 @@ int __connman_ipconfig_load(struct connman_ipconfig *ipconfig,
ipconfig->method = CONNMAN_IPCONFIG_METHOD_AUTO;
break;
case CONNMAN_IPCONFIG_TYPE_UNKNOWN:
+ case CONNMAN_IPCONFIG_TYPE_ALL:
ipconfig->method = CONNMAN_IPCONFIG_METHOD_OFF;
break;
}
@@ -2256,42 +2247,59 @@ int __connman_ipconfig_load(struct connman_ipconfig *ipconfig,
g_free(method);
g_free(key);
- key = g_strdup_printf("%snetmask_prefixlen", prefix);
- ipconfig->address->prefixlen = g_key_file_get_integer(
+ switch (ipconfig->method) {
+ case CONNMAN_IPCONFIG_METHOD_UNKNOWN:
+ case CONNMAN_IPCONFIG_METHOD_OFF:
+ break;
+
+ case CONNMAN_IPCONFIG_METHOD_FIXED:
+ case CONNMAN_IPCONFIG_METHOD_MANUAL:
+
+ key = g_strdup_printf("%snetmask_prefixlen", prefix);
+ ipconfig->address->prefixlen = g_key_file_get_integer(
keyfile, identifier, key, NULL);
- g_free(key);
+ g_free(key);
- key = g_strdup_printf("%slocal_address", prefix);
- g_free(ipconfig->address->local);
- ipconfig->address->local = g_key_file_get_string(
+ key = g_strdup_printf("%slocal_address", prefix);
+ g_free(ipconfig->address->local);
+ ipconfig->address->local = g_key_file_get_string(
keyfile, identifier, key, NULL);
- g_free(key);
+ g_free(key);
- key = g_strdup_printf("%speer_address", prefix);
- g_free(ipconfig->address->peer);
- ipconfig->address->peer = g_key_file_get_string(
+ key = g_strdup_printf("%speer_address", prefix);
+ g_free(ipconfig->address->peer);
+ ipconfig->address->peer = g_key_file_get_string(
keyfile, identifier, key, NULL);
- g_free(key);
+ g_free(key);
- key = g_strdup_printf("%sbroadcast_address", prefix);
- g_free(ipconfig->address->broadcast);
- ipconfig->address->broadcast = g_key_file_get_string(
+ key = g_strdup_printf("%sbroadcast_address", prefix);
+ g_free(ipconfig->address->broadcast);
+ ipconfig->address->broadcast = g_key_file_get_string(
keyfile, identifier, key, NULL);
- g_free(key);
+ g_free(key);
- key = g_strdup_printf("%sgateway", prefix);
- g_free(ipconfig->address->gateway);
- ipconfig->address->gateway = g_key_file_get_string(
+ key = g_strdup_printf("%sgateway", prefix);
+ g_free(ipconfig->address->gateway);
+ ipconfig->address->gateway = g_key_file_get_string(
keyfile, identifier, key, NULL);
- g_free(key);
+ g_free(key);
+ break;
+
+ case CONNMAN_IPCONFIG_METHOD_DHCP:
+
+ key = g_strdup_printf("%sDHCP.LastAddress", prefix);
+ str = g_key_file_get_string(keyfile, identifier, key, NULL);
+ if (str) {
+ g_free(ipconfig->last_dhcp_address);
+ ipconfig->last_dhcp_address = str;
+ }
+ g_free(key);
+
+ break;
- key = g_strdup_printf("%sDHCP.LastAddress", prefix);
- str = g_key_file_get_string(keyfile, identifier, key, NULL);
- if (str) {
- g_free(ipconfig->last_dhcp_address);
- ipconfig->last_dhcp_address = str;
+ case CONNMAN_IPCONFIG_METHOD_AUTO:
+ break;
}
- g_free(key);
return 0;
}
diff --git a/src/ipv6pd.c b/src/ipv6pd.c
index 5ecda389..0d221f07 100644
--- a/src/ipv6pd.c
+++ b/src/ipv6pd.c
@@ -165,8 +165,10 @@ static void cleanup(void)
timer_uplink = 0;
}
- g_hash_table_destroy(timer_hash);
- timer_hash = NULL;
+ if (timer_hash) {
+ g_hash_table_destroy(timer_hash);
+ timer_hash = NULL;
+ }
if (prefixes) {
g_slist_free_full(prefixes, g_free);
diff --git a/src/main.c b/src/main.c
index 21d1e06f..1c179912 100644
--- a/src/main.c
+++ b/src/main.c
@@ -639,6 +639,7 @@ int main(int argc, char *argv[])
else
config_init(option_config);
+ __connman_util_init();
__connman_inotify_init();
__connman_technology_init();
__connman_notifier_init();
@@ -729,6 +730,7 @@ int main(int argc, char *argv[])
__connman_technology_cleanup();
__connman_inotify_cleanup();
+ __connman_util_cleanup();
__connman_dbus_cleanup();
__connman_log_cleanup(option_backtrace);
@@ -747,6 +749,7 @@ int main(int argc, char *argv[])
g_strfreev(connman_settings.tethering_technologies);
g_free(option_debug);
+ g_free(option_wifi);
return 0;
}
diff --git a/src/net.connman.service.in b/src/net.connman.service.in
index e76969bc..f7f6a7c0 100644
--- a/src/net.connman.service.in
+++ b/src/net.connman.service.in
@@ -1,5 +1,5 @@
[D-BUS Service]
Name=net.connman
-Exec=@prefix@/sbin/connmand -n
+Exec=@sbindir@/connmand -n
User=root
SystemdService=connman.service
diff --git a/src/network.c b/src/network.c
index b388995f..badb7702 100644
--- a/src/network.c
+++ b/src/network.c
@@ -153,10 +153,6 @@ static void dhcp_success(struct connman_network *network)
if (!service)
goto err;
- connman_network_set_associating(network, false);
-
- network->connecting = false;
-
ipconfig_ipv4 = __connman_service_get_ip4config(service);
DBG("lease acquired for ipconfig %p", ipconfig_ipv4);
@@ -188,9 +184,6 @@ static void dhcp_failure(struct connman_network *network)
if (!service)
return;
- connman_network_set_associating(network, false);
- network->connecting = false;
-
ipconfig_ipv4 = __connman_service_get_ip4config(service);
DBG("lease lost for ipconfig %p", ipconfig_ipv4);
@@ -206,55 +199,24 @@ static void dhcp_callback(struct connman_ipconfig *ipconfig,
struct connman_network *network,
bool success, gpointer data)
{
+ network->connecting = false;
+
if (success)
dhcp_success(network);
else
dhcp_failure(network);
}
-static int set_connected_fixed(struct connman_network *network)
-{
- struct connman_service *service;
- struct connman_ipconfig *ipconfig_ipv4;
- int err;
-
- DBG("");
-
- service = connman_service_lookup_from_network(network);
-
- ipconfig_ipv4 = __connman_service_get_ip4config(service);
-
- set_configuration(network, CONNMAN_IPCONFIG_TYPE_IPV4);
-
- network->connecting = false;
-
- connman_network_set_associating(network, false);
-
- err = __connman_ipconfig_address_add(ipconfig_ipv4);
- if (err < 0)
- goto err;
-
- err = __connman_ipconfig_gateway_add(ipconfig_ipv4);
- if (err < 0)
- goto err;
-
- return 0;
-
-err:
- connman_network_set_error(network,
- CONNMAN_NETWORK_ERROR_CONFIGURE_FAIL);
-
- return err;
-}
-
-static void set_connected_manual(struct connman_network *network)
+static int set_connected_manual(struct connman_network *network)
{
+ int err = 0;
struct connman_service *service;
struct connman_ipconfig *ipconfig;
- int err;
DBG("network %p", network);
+ network->connecting = false;
+
service = connman_service_lookup_from_network(network);
ipconfig = __connman_service_get_ip4config(service);
@@ -262,8 +224,6 @@ static void set_connected_manual(struct connman_network *network)
if (!__connman_ipconfig_get_local(ipconfig))
__connman_service_read_ip4config(service);
- set_configuration(network, CONNMAN_IPCONFIG_TYPE_IPV4);
-
err = __connman_ipconfig_address_add(ipconfig);
if (err < 0)
goto err;
@@ -272,16 +232,8 @@ static void set_connected_manual(struct connman_network *network)
if (err < 0)
goto err;
- network->connecting = false;
-
- connman_network_set_associating(network, false);
-
- return;
-
err:
- connman_network_set_error(network,
- CONNMAN_NETWORK_ERROR_CONFIGURE_FAIL);
- return;
+ return err;
}
static int set_connected_dhcp(struct connman_network *network)
@@ -292,8 +244,6 @@ static int set_connected_dhcp(struct connman_network *network)
DBG("network %p", network);
- set_configuration(network, CONNMAN_IPCONFIG_TYPE_IPV4);
-
service = connman_service_lookup_from_network(network);
ipconfig_ipv4 = __connman_service_get_ip4config(service);
@@ -342,6 +292,8 @@ static int manual_ipv6_set(struct connman_network *network,
connman_device_set_disconnected(network->device, false);
+ connman_network_set_associating(network, false);
+
network->connecting = false;
return 0;
@@ -349,6 +301,8 @@ static int manual_ipv6_set(struct connman_network *network,
static void stop_dhcpv6(struct connman_network *network)
{
+ network->connecting = false;
+
__connman_dhcpv6_stop(network);
}
@@ -386,8 +340,6 @@ static int dhcpv6_set_addresses(struct connman_network *network)
if (!service)
goto err;
- connman_network_set_associating(network, false);
-
network->connecting = false;
ipconfig_ipv6 = __connman_service_get_ip6config(service);
@@ -395,10 +347,6 @@ static int dhcpv6_set_addresses(struct connman_network *network)
if (err < 0)
goto err;
- err = __connman_ipconfig_gateway_add(ipconfig_ipv6);
- if (err < 0)
- goto err;
-
return 0;
err:
@@ -511,6 +459,8 @@ static void check_dhcpv6(struct nd_router_advert *reply,
if (service) {
connman_service_create_ip6config(service, network->index);
+ connman_network_set_associating(network, false);
+
__connman_service_ipconfig_indicate_state(service,
CONNMAN_SERVICE_STATE_CONFIGURATION,
CONNMAN_IPCONFIG_TYPE_IPV6);
@@ -519,10 +469,16 @@ static void check_dhcpv6(struct nd_router_advert *reply,
/*
* We do stateful/stateless DHCPv6 if router advertisement says so.
*/
- if (reply->nd_ra_flags_reserved & ND_RA_FLAG_MANAGED)
+ if (reply->nd_ra_flags_reserved & ND_RA_FLAG_MANAGED) {
__connman_dhcpv6_start(network, prefixes, dhcpv6_callback);
- else if (reply->nd_ra_flags_reserved & ND_RA_FLAG_OTHER)
- __connman_dhcpv6_start_info(network, dhcpv6_info_callback);
+ } else {
+ if (reply->nd_ra_flags_reserved & ND_RA_FLAG_OTHER)
+ __connman_dhcpv6_start_info(network,
+ dhcpv6_info_callback);
+
+ g_slist_free_full(prefixes, g_free);
+ network->connecting = false;
+ }
connman_network_unref(network);
}
@@ -602,8 +558,6 @@ static void autoconf_ipv6_set(struct connman_network *network)
connman_device_set_disconnected(network->device, false);
- network->connecting = false;
-
service = connman_service_lookup_from_network(network);
if (!service)
return;
@@ -612,6 +566,8 @@ static void autoconf_ipv6_set(struct connman_network *network)
if (!ipconfig)
return;
+ __connman_ipconfig_enable_ipv6(ipconfig);
+
__connman_ipconfig_address_remove(ipconfig);
index = __connman_ipconfig_get_index(ipconfig);
@@ -626,13 +582,13 @@ static void autoconf_ipv6_set(struct connman_network *network)
static void set_connected(struct connman_network *network)
{
struct connman_ipconfig *ipconfig_ipv4, *ipconfig_ipv6;
- enum connman_ipconfig_method ipv4_method, ipv6_method;
struct connman_service *service;
- int ret;
if (network->connected)
return;
+ connman_network_set_associating(network, false);
+
network->connected = true;
service = connman_service_lookup_from_network(network);
@@ -643,56 +599,8 @@ static void set_connected(struct connman_network *network)
DBG("service %p ipv4 %p ipv6 %p", service, ipconfig_ipv4,
ipconfig_ipv6);
- ipv4_method = __connman_ipconfig_get_method(ipconfig_ipv4);
- ipv6_method = __connman_ipconfig_get_method(ipconfig_ipv6);
-
- DBG("method ipv4 %d ipv6 %d", ipv4_method, ipv6_method);
-
- switch (ipv6_method) {
- case CONNMAN_IPCONFIG_METHOD_UNKNOWN:
- case CONNMAN_IPCONFIG_METHOD_OFF:
- break;
- case CONNMAN_IPCONFIG_METHOD_DHCP:
- case CONNMAN_IPCONFIG_METHOD_AUTO:
- autoconf_ipv6_set(network);
- break;
- case CONNMAN_IPCONFIG_METHOD_FIXED:
- case CONNMAN_IPCONFIG_METHOD_MANUAL:
- ret = manual_ipv6_set(network, ipconfig_ipv6);
- if (ret != 0) {
- connman_network_set_error(network,
- CONNMAN_NETWORK_ERROR_ASSOCIATE_FAIL);
- return;
- }
- break;
- }
-
- switch (ipv4_method) {
- case CONNMAN_IPCONFIG_METHOD_UNKNOWN:
- case CONNMAN_IPCONFIG_METHOD_OFF:
- case CONNMAN_IPCONFIG_METHOD_AUTO:
- return;
- case CONNMAN_IPCONFIG_METHOD_FIXED:
- if (set_connected_fixed(network) < 0) {
- connman_network_set_error(network,
- CONNMAN_NETWORK_ERROR_ASSOCIATE_FAIL);
- return;
- }
- return;
- case CONNMAN_IPCONFIG_METHOD_MANUAL:
- set_connected_manual(network);
- return;
- case CONNMAN_IPCONFIG_METHOD_DHCP:
- if (set_connected_dhcp(network) < 0) {
- connman_network_set_error(network,
- CONNMAN_NETWORK_ERROR_ASSOCIATE_FAIL);
- return;
- }
- }
-
- network->connecting = false;
-
- connman_network_set_associating(network, false);
+ __connman_network_enable_ipconfig(network, ipconfig_ipv4);
+ __connman_network_enable_ipconfig(network, ipconfig_ipv6);
}
static void set_disconnected(struct connman_network *network)
@@ -1139,14 +1047,21 @@ void connman_network_set_index(struct connman_network *network, int index)
goto done;
ipconfig = __connman_service_get_ip4config(service);
- if (!ipconfig)
- goto done;
+ if (ipconfig) {
+ __connman_ipconfig_set_index(ipconfig, index);
+
+ DBG("index %d service %p ip4config %p", network->index,
+ service, ipconfig);
+ }
+
+ ipconfig = __connman_service_get_ip6config(service);
+ if (ipconfig) {
+ __connman_ipconfig_set_index(ipconfig, index);
- /* If index changed, the index of ipconfig must be reset. */
- __connman_ipconfig_set_index(ipconfig, index);
+ DBG("index %d service %p ip6config %p", network->index,
+ service, ipconfig);
+ }
- DBG("index %d service %p ip4config %p", network->index,
- service, ipconfig);
done:
network->index = index;
}
@@ -1594,26 +1509,6 @@ int __connman_network_disconnect(struct connman_network *network)
return err;
}
-static int manual_ipv4_set(struct connman_network *network,
- struct connman_ipconfig *ipconfig)
-{
- struct connman_service *service;
- int err;
-
- service = connman_service_lookup_from_network(network);
- if (!service)
- return -EINVAL;
-
- err = __connman_ipconfig_address_add(ipconfig);
- if (err < 0) {
- connman_network_set_error(network,
- CONNMAN_NETWORK_ERROR_CONFIGURE_FAIL);
- return err;
- }
-
- return __connman_ipconfig_gateway_add(ipconfig);
-}
-
int __connman_network_clear_ipconfig(struct connman_network *network,
struct connman_ipconfig *ipconfig)
{
@@ -1658,58 +1553,88 @@ int __connman_network_clear_ipconfig(struct connman_network *network,
return 0;
}
-int __connman_network_set_ipconfig(struct connman_network *network,
- struct connman_ipconfig *ipconfig_ipv4,
- struct connman_ipconfig *ipconfig_ipv6)
+int __connman_network_enable_ipconfig(struct connman_network *network,
+ struct connman_ipconfig *ipconfig)
{
+ int r = 0;
+ enum connman_ipconfig_type type;
enum connman_ipconfig_method method;
- int ret;
- if (!network)
+ if (!network || !ipconfig)
return -EINVAL;
- if (ipconfig_ipv6) {
- method = __connman_ipconfig_get_method(ipconfig_ipv6);
+ type = __connman_ipconfig_get_config_type(ipconfig);
+
+ switch (type) {
+ case CONNMAN_IPCONFIG_TYPE_UNKNOWN:
+ case CONNMAN_IPCONFIG_TYPE_ALL:
+ return -ENOSYS;
+
+ case CONNMAN_IPCONFIG_TYPE_IPV6:
+ set_configuration(network, type);
+
+ method = __connman_ipconfig_get_method(ipconfig);
+
+ DBG("ipv6 ipconfig method %d", method);
switch (method) {
case CONNMAN_IPCONFIG_METHOD_UNKNOWN:
+ break;
+
case CONNMAN_IPCONFIG_METHOD_OFF:
+ __connman_ipconfig_disable_ipv6(ipconfig);
break;
+
case CONNMAN_IPCONFIG_METHOD_AUTO:
autoconf_ipv6_set(network);
break;
+
case CONNMAN_IPCONFIG_METHOD_FIXED:
case CONNMAN_IPCONFIG_METHOD_MANUAL:
- ret = manual_ipv6_set(network, ipconfig_ipv6);
- if (ret != 0) {
- connman_network_set_error(network,
- CONNMAN_NETWORK_ERROR_ASSOCIATE_FAIL);
- return ret;
- }
+ r = manual_ipv6_set(network, ipconfig);
break;
+
case CONNMAN_IPCONFIG_METHOD_DHCP:
+ r = -ENOSYS;
break;
}
- }
- if (ipconfig_ipv4) {
- method = __connman_ipconfig_get_method(ipconfig_ipv4);
+ break;
+
+ case CONNMAN_IPCONFIG_TYPE_IPV4:
+ set_configuration(network, type);
+
+ method = __connman_ipconfig_get_method(ipconfig);
+
+ DBG("ipv4 ipconfig method %d", method);
switch (method) {
case CONNMAN_IPCONFIG_METHOD_UNKNOWN:
case CONNMAN_IPCONFIG_METHOD_OFF:
- case CONNMAN_IPCONFIG_METHOD_FIXED:
+ break;
+
case CONNMAN_IPCONFIG_METHOD_AUTO:
- return -EINVAL;
+ r = -ENOSYS;
+ break;
+
+ case CONNMAN_IPCONFIG_METHOD_FIXED:
case CONNMAN_IPCONFIG_METHOD_MANUAL:
- return manual_ipv4_set(network, ipconfig_ipv4);
+ r = set_connected_manual(network);
+ break;
+
case CONNMAN_IPCONFIG_METHOD_DHCP:
- return __connman_dhcp_start(ipconfig_ipv4,
- network, dhcp_callback, NULL);
+ r = set_connected_dhcp(network);
+ break;
}
+
+ break;
}
- return 0;
+ if (r < 0)
+ connman_network_set_error(network,
+ CONNMAN_NETWORK_ERROR_CONFIGURE_FAIL);
+
+ return r;
}
int connman_network_set_ipaddress(struct connman_network *network,
diff --git a/src/ntp.c b/src/ntp.c
index b4fe63aa..abb2caa2 100644
--- a/src/ntp.c
+++ b/src/ntp.c
@@ -208,6 +208,8 @@ static void send_packet(int fd, const char *server, uint32_t timeout)
static gboolean next_poll(gpointer user_data)
{
+ poll_id = 0;
+
if (!timeserver || transmit_fd == 0)
return FALSE;
diff --git a/src/peer.c b/src/peer.c
index caff70c8..206b799b 100644
--- a/src/peer.c
+++ b/src/peer.c
@@ -27,6 +27,7 @@
#include <ctype.h>
#include <gdbus.h>
#include <gdhcp/gdhcp.h>
+#include <netinet/if_ether.h>
#include <connman/agent.h>
@@ -54,6 +55,7 @@ struct connman_peer {
int refcount;
struct connman_device *device;
struct connman_device *sub_device;
+ unsigned char *iface_address[ETH_ALEN];
char *identifier;
char *name;
char *path;
@@ -64,9 +66,12 @@ struct connman_peer {
bool connection_master;
struct connman_ippool *ip_pool;
GDHCPServer *dhcp_server;
+ uint32_t lease_ip;
GSList *services;
};
+static void settings_changed(struct connman_peer *peer);
+
static void stop_dhcp_server(struct connman_peer *peer)
{
DBG("");
@@ -79,6 +84,7 @@ static void stop_dhcp_server(struct connman_peer *peer)
if (peer->ip_pool)
__connman_ippool_unref(peer->ip_pool);
peer->ip_pool = NULL;
+ peer->lease_ip = 0;
}
static void dhcp_server_debug(const char *str, void *data)
@@ -86,6 +92,24 @@ static void dhcp_server_debug(const char *str, void *data)
connman_info("%s: %s\n", (const char *) data, str);
}
+static void lease_added(unsigned char *mac, uint32_t ip)
+{
+ GList *list, *start;
+
+ start = list = g_hash_table_get_values(peers_table);
+ for (; list; list = list->next) {
+ struct connman_peer *temp = list->data;
+
+ if (!memcmp(temp->iface_address, mac, ETH_ALEN)) {
+ temp->lease_ip = ip;
+ settings_changed(temp);
+ break;
+ }
+ }
+
+ g_list_free(start);
+}
+
static gboolean dhcp_server_started(gpointer data)
{
struct connman_peer *peer = data;
@@ -146,6 +170,8 @@ static int start_dhcp_server(struct connman_peer *peer)
g_dhcp_server_set_option(peer->dhcp_server, G_DHCP_DNS_SERVER, NULL);
g_dhcp_server_set_ip_range(peer->dhcp_server, start_ip, end_ip);
+ g_dhcp_server_set_lease_added_cb(peer->dhcp_server, lease_added);
+
err = g_dhcp_server_start(peer->dhcp_server);
if (err < 0)
goto error;
@@ -253,39 +279,43 @@ static bool allow_property_changed(struct connman_peer *peer)
return true;
}
-static void append_dhcp_server_ipv4(DBusMessageIter *iter, void *user_data)
+static void append_ipv4(DBusMessageIter *iter, void *user_data)
{
struct connman_peer *peer = user_data;
- const char *str = "dhcp";
- const char *gateway;
- const char *subnet;
+ char trans[INET_ADDRSTRLEN+1] = {};
+ const char *local = "";
+ const char *remote = "";
+ char *dhcp = NULL;
- if (!peer->ip_pool)
+ if (!is_connected(peer))
return;
- gateway = __connman_ippool_get_gateway(peer->ip_pool);
- subnet = __connman_ippool_get_subnet_mask(peer->ip_pool);
+ if (peer->connection_master) {
+ struct in_addr addr;
- connman_dbus_dict_append_basic(iter, "Method", DBUS_TYPE_STRING, &str);
- connman_dbus_dict_append_basic(iter, "Address",
- DBUS_TYPE_STRING, &gateway);
- connman_dbus_dict_append_basic(iter, "Netmask",
- DBUS_TYPE_STRING, &subnet);
- connman_dbus_dict_append_basic(iter, "Gateway",
- DBUS_TYPE_STRING, &gateway);
-}
+ addr.s_addr = peer->lease_ip;
+ inet_ntop(AF_INET, &addr, trans, INET_ADDRSTRLEN);
-static void append_ipv4(DBusMessageIter *iter, void *user_data)
-{
- struct connman_peer *peer = user_data;
+ local = __connman_ippool_get_gateway(peer->ip_pool);
+ remote = trans;
+ } else if (peer->ipconfig) {
+ local = __connman_ipconfig_get_local(peer->ipconfig);
- if (!is_connected(peer))
- return;
+ remote = __connman_ipconfig_get_gateway(peer->ipconfig);
+ if (!remote) {
+ remote = dhcp = __connman_dhcp_get_server_address(
+ peer->ipconfig);
+ if (!dhcp)
+ remote = "";
+ }
+ }
- if (peer->connection_master)
- append_dhcp_server_ipv4(iter, peer);
- else if (peer->ipconfig)
- __connman_ipconfig_append_ipv4(peer->ipconfig, iter);
+ connman_dbus_dict_append_basic(iter, "Local",
+ DBUS_TYPE_STRING, &local);
+ connman_dbus_dict_append_basic(iter, "Remote",
+ DBUS_TYPE_STRING, &remote);
+ if (dhcp)
+ g_free(dhcp);
}
static void append_peer_service(DBusMessageIter *iter,
@@ -725,6 +755,13 @@ void connman_peer_set_name(struct connman_peer *peer, const char *name)
peer->name = g_strdup(name);
}
+void connman_peer_set_iface_address(struct connman_peer *peer,
+ const unsigned char *iface_address)
+{
+ memset(peer->iface_address, 0, ETH_ALEN);
+ memcpy(peer->iface_address, iface_address, ETH_ALEN);
+}
+
void connman_peer_set_device(struct connman_peer *peer,
struct connman_device *device)
{
@@ -885,6 +922,10 @@ int connman_peer_set_state(struct connman_peer *peer,
peer->state = new_state;
state_changed(peer);
+ if (peer->state == CONNMAN_PEER_STATE_READY ||
+ peer->state == CONNMAN_PEER_STATE_DISCONNECT)
+ settings_changed(peer);
+
return 0;
}
@@ -976,7 +1017,8 @@ static void peer_ip_bound(struct connman_ipconfig *ipconfig,
DBG("%s ip bound", ifname);
- settings_changed(peer);
+ if (peer->state == CONNMAN_PEER_STATE_READY)
+ settings_changed(peer);
connman_peer_set_state(peer, CONNMAN_PEER_STATE_READY);
}
@@ -987,7 +1029,8 @@ static void peer_ip_release(struct connman_ipconfig *ipconfig,
DBG("%s ip release", ifname);
- settings_changed(peer);
+ if (peer->state == CONNMAN_PEER_STATE_READY)
+ settings_changed(peer);
}
static const struct connman_ipconfig_ops peer_ip_ops = {
@@ -1151,6 +1194,10 @@ void __connman_peer_cleanup(void)
{
DBG("");
+ g_hash_table_destroy(peers_notify->remove);
+ g_hash_table_destroy(peers_notify->add);
+ g_free(peers_notify);
+
g_hash_table_destroy(peers_table);
peers_table = NULL;
dbus_connection_unref(connection);
diff --git a/src/proxy.c b/src/proxy.c
index 0d1a25ab..f331de92 100644
--- a/src/proxy.c
+++ b/src/proxy.c
@@ -44,6 +44,9 @@ struct proxy_lookup {
static void remove_lookup(struct proxy_lookup *lookup)
{
+ if (lookup->watch > 0)
+ g_source_remove(lookup->watch);
+
lookup_list = g_slist_remove(lookup_list, lookup);
connman_service_unref(lookup->service);
@@ -150,11 +153,6 @@ void connman_proxy_lookup_cancel(unsigned int token)
}
if (lookup) {
- if (lookup->watch > 0) {
- g_source_remove(lookup->watch);
- lookup->watch = 0;
- }
-
if (lookup->proxy &&
lookup->proxy->cancel_lookup)
lookup->proxy->cancel_lookup(lookup->service,
diff --git a/src/resolver.c b/src/resolver.c
index 01e7c0e0..652f4fd9 100644
--- a/src/resolver.c
+++ b/src/resolver.c
@@ -608,14 +608,6 @@ int __connman_resolver_redo_servers(int index)
*/
__connman_dnsproxy_remove(entry->index, entry->domain,
entry->server);
- /*
- * Remove also the resolver timer for the old server entry.
- * A new timer will be set for the new server entry
- * when the next Router Advertisement message arrives
- * with RDNSS/DNSSL settings.
- */
- g_source_remove(entry->timeout);
- entry->timeout = 0;
__connman_dnsproxy_append(entry->index, entry->domain,
entry->server);
diff --git a/src/rfkill.c b/src/rfkill.c
index 960cfea7..2bfb0928 100644
--- a/src/rfkill.c
+++ b/src/rfkill.c
@@ -153,14 +153,14 @@ static gboolean rfkill_event(GIOChannel *chan, GIOCondition cond, gpointer data)
return TRUE;
}
-static GIOChannel *channel = NULL;
+static guint watch = 0;
int __connman_rfkill_block(enum connman_service_type type, bool block)
{
uint8_t rfkill_type;
struct rfkill_event event;
ssize_t len;
- int fd, err;
+ int fd, err = 0;
DBG("type %d block %d", type, block);
@@ -170,7 +170,7 @@ int __connman_rfkill_block(enum connman_service_type type, bool block)
fd = open("/dev/rfkill", O_RDWR | O_CLOEXEC);
if (fd < 0)
- return fd;
+ return -errno;
memset(&event, 0, sizeof(event));
event.op = RFKILL_OP_CHANGE_ALL;
@@ -179,10 +179,9 @@ int __connman_rfkill_block(enum connman_service_type type, bool block)
len = write(fd, &event, sizeof(event));
if (len < 0) {
+ err = -errno;
connman_error("Failed to change RFKILL state");
- err = len;
- } else
- err = 0;
+ }
close(fd);
@@ -191,6 +190,7 @@ int __connman_rfkill_block(enum connman_service_type type, bool block)
int __connman_rfkill_init(void)
{
+ GIOChannel *channel;
GIOFlags flags;
int fd;
@@ -215,21 +215,21 @@ int __connman_rfkill_init(void)
/* Process current RFKILL events sent on device open */
while (rfkill_process(channel) == G_IO_STATUS_NORMAL);
- g_io_add_watch(channel, G_IO_IN | G_IO_NVAL | G_IO_HUP | G_IO_ERR,
- rfkill_event, NULL);
+ watch = g_io_add_watch(channel,
+ G_IO_IN | G_IO_NVAL | G_IO_HUP | G_IO_ERR,
+ rfkill_event, NULL);
+
+ g_io_channel_unref(channel);
- return 0;
+ return watch ? 0 : -EIO;
}
void __connman_rfkill_cleanup(void)
{
DBG("");
- if (!channel)
- return;
-
- g_io_channel_shutdown(channel, TRUE, NULL);
- g_io_channel_unref(channel);
-
- channel = NULL;
+ if (watch) {
+ g_source_remove(watch);
+ watch = 0;
+ }
}
diff --git a/src/rtnl.c b/src/rtnl.c
index a46aa284..d1b851fe 100644
--- a/src/rtnl.c
+++ b/src/rtnl.c
@@ -170,6 +170,9 @@ static void read_uevent(struct interface_data *interface)
} else if (strcmp(line + 8, "gadget") == 0) {
interface->service_type = CONNMAN_SERVICE_TYPE_GADGET;
interface->device_type = CONNMAN_DEVICE_TYPE_GADGET;
+ } else if (strcmp(line + 8, "vlan") == 0) {
+ interface->service_type = CONNMAN_SERVICE_TYPE_ETHERNET;
+ interface->device_type = CONNMAN_DEVICE_TYPE_ETHERNET;
} else {
interface->service_type = CONNMAN_SERVICE_TYPE_UNKNOWN;
@@ -612,17 +615,18 @@ static void process_newaddr(unsigned char family, unsigned char prefixlen,
if (!inet_ntop(family, src, ip_string, INET6_ADDRSTRLEN))
return;
- __connman_ipconfig_newaddr(index, family, label,
- prefixlen, ip_string);
-
- if (family == AF_INET6) {
- /*
- * Re-create RDNSS configured servers if there are any
- * for this interface. This is done because we might
- * have now properly configured interface with proper
- * autoconfigured address.
- */
- __connman_resolver_redo_servers(index);
+ if (__connman_ipconfig_newaddr(index, family, label,
+ prefixlen, ip_string) >= 0) {
+ if (family == AF_INET6) {
+ /*
+ * Re-create RDNSS configured servers if there
+ * are any for this interface. This is done
+ * because we might have now properly
+ * configured interface with proper
+ * autoconfigured address.
+ */
+ __connman_resolver_redo_servers(index);
+ }
}
}
@@ -1083,6 +1087,8 @@ static void rtnl_route(struct nlmsghdr *hdr)
static bool is_route_rtmsg(struct rtmsg *msg)
{
+ if (msg->rtm_flags & RTM_F_CLONED)
+ return false;
if (msg->rtm_table != RT_TABLE_MAIN)
return false;
@@ -1291,6 +1297,7 @@ static const char *type2string(uint16_t type)
}
static GIOChannel *channel = NULL;
+static guint channel_watch = 0;
struct rtnl_request {
struct nlmsghdr hdr;
@@ -1621,8 +1628,9 @@ int __connman_rtnl_init(void)
g_io_channel_set_encoding(channel, NULL, NULL);
g_io_channel_set_buffered(channel, FALSE);
- g_io_add_watch(channel, G_IO_IN | G_IO_NVAL | G_IO_HUP | G_IO_ERR,
- netlink_event, NULL);
+ channel_watch = g_io_add_watch(channel,
+ G_IO_IN | G_IO_NVAL | G_IO_HUP | G_IO_ERR,
+ netlink_event, NULL);
return 0;
}
@@ -1672,6 +1680,11 @@ void __connman_rtnl_cleanup(void)
g_slist_free(request_list);
request_list = NULL;
+ if (channel_watch) {
+ g_source_remove(channel_watch);
+ channel_watch = 0;
+ }
+
g_io_channel_shutdown(channel, TRUE, NULL);
g_io_channel_unref(channel);
diff --git a/src/service.c b/src/service.c
index 87a2f2cd..29a632e1 100644
--- a/src/service.c
+++ b/src/service.c
@@ -1227,14 +1227,18 @@ static void add_nameserver_route(int family, int index, char *nameserver,
static void nameserver_add_routes(int index, char **nameservers,
const char *gw)
{
- int i, family;
+ int i, ns_family, gw_family;
+
+ gw_family = connman_inet_check_ipaddress(gw);
+ if (gw_family < 0)
+ return;
for (i = 0; nameservers[i]; i++) {
- family = connman_inet_check_ipaddress(nameservers[i]);
- if (family < 0)
+ ns_family = connman_inet_check_ipaddress(nameservers[i]);
+ if (ns_family < 0 || ns_family != gw_family)
continue;
- add_nameserver_route(family, index, nameservers[i], gw);
+ add_nameserver_route(ns_family, index, nameservers[i], gw);
}
}
@@ -2870,7 +2874,6 @@ int __connman_service_set_passphrase(struct connman_service *service,
if (service->network)
connman_network_set_string(service->network, "WiFi.Passphrase",
service->passphrase);
- service_save(service);
return 0;
}
@@ -2883,16 +2886,6 @@ const char *__connman_service_get_passphrase(struct connman_service *service)
return service->passphrase;
}
-static void clear_passphrase(struct connman_service *service)
-{
- g_free(service->passphrase);
- service->passphrase = NULL;
-
- if (service->network)
- connman_network_set_string(service->network, "WiFi.Passphrase",
- service->passphrase);
-}
-
static DBusMessage *get_properties(DBusConnection *conn,
DBusMessage *msg, void *user_data)
{
@@ -3413,10 +3406,13 @@ static DBusMessage *set_property(DBusConnection *conn,
if (err < 0) {
if (is_connected_state(service, state) ||
- is_connecting_state(service, state))
- __connman_network_set_ipconfig(service->network,
- service->ipconfig_ipv4,
- service->ipconfig_ipv6);
+ is_connecting_state(service, state)) {
+ __connman_network_enable_ipconfig(service->network,
+ service->ipconfig_ipv4);
+ __connman_network_enable_ipconfig(service->network,
+ service->ipconfig_ipv6);
+ }
+
return __connman_error_failed(msg, -err);
}
@@ -3425,10 +3421,12 @@ static DBusMessage *set_property(DBusConnection *conn,
else
ipv6_configuration_changed(service);
- if (is_connecting(service) || is_connected(service))
- __connman_network_set_ipconfig(service->network,
- service->ipconfig_ipv4,
- service->ipconfig_ipv6);
+ if (is_connecting(service) || is_connected(service)) {
+ __connman_network_enable_ipconfig(service->network,
+ service->ipconfig_ipv4);
+ __connman_network_enable_ipconfig(service->network,
+ service->ipconfig_ipv6);
+ }
service_save(service);
} else
@@ -3450,14 +3448,14 @@ static void set_error(struct connman_service *service,
if (!service->path)
return;
+ if (!allow_property_changed(service))
+ return;
+
str = error2string(service->error);
if (!str)
str = "";
- if (!allow_property_changed(service))
- return;
-
connman_dbus_property_changed_basic(service->path,
CONNMAN_SERVICE_INTERFACE, "Error",
DBUS_TYPE_STRING, &str);
@@ -4807,6 +4805,11 @@ bool __connman_service_is_connected_state(struct connman_service *service,
return is_connected_state(service, service->state_ipv4);
case CONNMAN_IPCONFIG_TYPE_IPV6:
return is_connected_state(service, service->state_ipv6);
+ case CONNMAN_IPCONFIG_TYPE_ALL:
+ return is_connected_state(service,
+ CONNMAN_IPCONFIG_TYPE_IPV4) &&
+ is_connected_state(service,
+ CONNMAN_IPCONFIG_TYPE_IPV6);
}
return false;
@@ -5299,6 +5302,8 @@ static int service_indicate_state(struct connman_service *service)
break;
case CONNMAN_SERVICE_STATE_READY:
+ set_error(service, CONNMAN_SERVICE_ERROR_UNKNOWN);
+
if (service->new_service &&
__connman_stats_service_register(service) == 0) {
/*
@@ -5365,6 +5370,7 @@ static int service_indicate_state(struct connman_service *service)
break;
case CONNMAN_SERVICE_STATE_DISCONNECT:
+ set_error(service, CONNMAN_SERVICE_ERROR_UNKNOWN);
reply_pending(service, ECONNABORTED);
@@ -5409,9 +5415,6 @@ static int service_indicate_state(struct connman_service *service)
break;
}
- if (new_state != CONNMAN_SERVICE_STATE_FAILURE)
- set_error(service, CONNMAN_SERVICE_ERROR_UNKNOWN);
-
service_list_sort();
__connman_connection_update_gateway();
@@ -5439,17 +5442,10 @@ int __connman_service_indicate_error(struct connman_service *service,
if (!service)
return -EINVAL;
- set_error(service, error);
-
- /*
- * Supplicant does not always return invalid key error for
- * WPA-EAP so clear the credentials always.
- */
- if (service->error == CONNMAN_SERVICE_ERROR_INVALID_KEY ||
- service->security == CONNMAN_SERVICE_SECURITY_8021X)
- clear_passphrase(service);
+ if (service->state == CONNMAN_SERVICE_STATE_FAILURE)
+ return -EALREADY;
- __connman_service_set_agent_identity(service, NULL);
+ set_error(service, error);
__connman_service_ipconfig_indicate_state(service,
CONNMAN_SERVICE_STATE_FAILURE,
@@ -5653,7 +5649,7 @@ int __connman_service_ipconfig_indicate_state(struct connman_service *service,
enum connman_ipconfig_type type)
{
struct connman_ipconfig *ipconfig = NULL;
- enum connman_service_state *old_state;
+ enum connman_service_state old_state;
enum connman_ipconfig_method method;
if (!service)
@@ -5661,16 +5657,17 @@ int __connman_service_ipconfig_indicate_state(struct connman_service *service,
switch (type) {
case CONNMAN_IPCONFIG_TYPE_UNKNOWN:
+ case CONNMAN_IPCONFIG_TYPE_ALL:
return -EINVAL;
case CONNMAN_IPCONFIG_TYPE_IPV4:
- old_state = &service->state_ipv4;
+ old_state = service->state_ipv4;
ipconfig = service->ipconfig_ipv4;
break;
case CONNMAN_IPCONFIG_TYPE_IPV6:
- old_state = &service->state_ipv6;
+ old_state = service->state_ipv6;
ipconfig = service->ipconfig_ipv6;
break;
@@ -5680,12 +5677,12 @@ int __connman_service_ipconfig_indicate_state(struct connman_service *service,
return -EINVAL;
/* Any change? */
- if (*old_state == new_state)
+ if (old_state == new_state)
return -EALREADY;
DBG("service %p (%s) old state %d (%s) new state %d (%s) type %d (%s)",
service, service ? service->identifier : NULL,
- *old_state, state2string(*old_state),
+ old_state, state2string(old_state),
new_state, state2string(new_state),
type, __connman_ipconfig_type2string(type));
@@ -5732,14 +5729,17 @@ int __connman_service_ipconfig_indicate_state(struct connman_service *service,
break;
case CONNMAN_IPCONFIG_METHOD_FIXED:
- case CONNMAN_IPCONFIG_METHOD_MANUAL:
- case CONNMAN_IPCONFIG_METHOD_DHCP:
- case CONNMAN_IPCONFIG_METHOD_AUTO:
+ case CONNMAN_IPCONFIG_METHOD_MANUAL:
+ case CONNMAN_IPCONFIG_METHOD_DHCP:
+ case CONNMAN_IPCONFIG_METHOD_AUTO:
break;
}
- *old_state = new_state;
+ if (type == CONNMAN_IPCONFIG_TYPE_IPV4)
+ service->state_ipv4 = new_state;
+ else
+ service->state_ipv6 = new_state;
update_nameservers(service);
@@ -5839,6 +5839,9 @@ static int service_connect(struct connman_service *service)
case CONNMAN_SERVICE_SECURITY_PSK:
case CONNMAN_SERVICE_SECURITY_WPA:
case CONNMAN_SERVICE_SECURITY_RSN:
+ if (service->error == CONNMAN_SERVICE_ERROR_INVALID_KEY)
+ return -ENOKEY;
+
if (!service->passphrase) {
if (!service->network)
return -EOPNOTSUPP;
@@ -5865,9 +5868,10 @@ static int service_connect(struct connman_service *service)
* missing. Agent provided credentials can be used as
* fallback if needed.
*/
- if ((!service->identity &&
+ if (((!service->identity &&
!service->agent_identity) ||
- !service->passphrase)
+ !service->passphrase) ||
+ service->error == CONNMAN_SERVICE_ERROR_INVALID_KEY)
return -ENOKEY;
break;
@@ -5962,16 +5966,15 @@ int __connman_service_connect(struct connman_service *service,
err = service_connect(service);
service->connect_reason = reason;
- if (err >= 0) {
- set_error(service, CONNMAN_SERVICE_ERROR_UNKNOWN);
+
+ if (err >= 0)
return 0;
- }
if (err == -EINPROGRESS) {
if (service->timeout == 0)
service->timeout = g_timeout_add_seconds(
CONNECT_TIMEOUT, connect_timeout, service);
- set_error(service, CONNMAN_SERVICE_ERROR_UNKNOWN);
+
return -EINPROGRESS;
}
@@ -6729,8 +6732,32 @@ struct connman_service * __connman_service_create_from_network(struct connman_ne
if (service->favorite) {
device = connman_network_get_device(service->network);
- if (device && !connman_device_get_scanning(device))
- __connman_service_auto_connect(CONNMAN_SERVICE_CONNECT_REASON_AUTO);
+ if (device && !connman_device_get_scanning(device)) {
+
+ switch (service->type) {
+ case CONNMAN_SERVICE_TYPE_UNKNOWN:
+ case CONNMAN_SERVICE_TYPE_SYSTEM:
+ case CONNMAN_SERVICE_TYPE_P2P:
+ break;
+
+ case CONNMAN_SERVICE_TYPE_GADGET:
+ case CONNMAN_SERVICE_TYPE_ETHERNET:
+ if (service->autoconnect) {
+ __connman_service_connect(service,
+ CONNMAN_SERVICE_CONNECT_REASON_AUTO);
+ break;
+ }
+
+ /* fall through */
+ case CONNMAN_SERVICE_TYPE_BLUETOOTH:
+ case CONNMAN_SERVICE_TYPE_GPS:
+ case CONNMAN_SERVICE_TYPE_VPN:
+ case CONNMAN_SERVICE_TYPE_WIFI:
+ case CONNMAN_SERVICE_TYPE_CELLULAR:
+ __connman_service_auto_connect(CONNMAN_SERVICE_CONNECT_REASON_AUTO);
+ break;
+ }
+ }
}
__connman_notifier_service_add(service, service->name);
diff --git a/src/shared/sha1.c b/src/shared/sha1.c
deleted file mode 100644
index e67b020d..00000000
--- a/src/shared/sha1.c
+++ /dev/null
@@ -1,189 +0,0 @@
-/*
- *
- * Connection Manager
- *
- * Copyright (C) 2012 Intel Corporation. All rights reserved.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- *
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <string.h>
-
-#include <glib.h>
-
-#include "src/shared/sha1.h"
-
-#define SHA1_MAC_LEN 20
-
-static void __hmac_sha1(GChecksum *checksum, const void *key, size_t key_len,
- const void *data, size_t data_len, void *output)
-{
- unsigned char ipad[64];
- unsigned char opad[64];
- unsigned char digest[SHA1_MAC_LEN];
- size_t length;
- int i;
-
- /* if key is longer than 64 bytes reset it to key=SHA1(key) */
- if (key_len > 64) {
- g_checksum_update(checksum, key, key_len);
- length = sizeof(digest);
- g_checksum_get_digest(checksum, digest, &length);
-
- g_checksum_reset(checksum);
-
- key = digest;
- key_len = SHA1_MAC_LEN;
- }
-
- /* start out by storing key in pads */
- memset(ipad, 0, sizeof(ipad));
- memset(opad, 0, sizeof(opad));
- memcpy(ipad, key, key_len);
- memcpy(opad, key, key_len);
-
- /* XOR key with ipad and opad values */
- for (i = 0; i < 64; i++) {
- ipad[i] ^= 0x36;
- opad[i] ^= 0x5c;
- }
-
- /* perform inner SHA1 */
- g_checksum_update(checksum, ipad, sizeof(ipad));
- g_checksum_update(checksum, data, data_len);
- length = sizeof(digest);
- g_checksum_get_digest(checksum, digest, &length);
-
- g_checksum_reset(checksum);
-
- /* perform outer SHA1 */
- g_checksum_update(checksum, opad, sizeof(opad));
- g_checksum_update(checksum, digest, length);
- length = sizeof(digest);
- g_checksum_get_digest(checksum, output, &length);
-
- g_checksum_reset(checksum);
-}
-
-int hmac_sha1(const void *key, size_t key_len,
- const void *data, size_t data_len, void *output, size_t size)
-{
- GChecksum *checksum;
-
- checksum = g_checksum_new(G_CHECKSUM_SHA1);
-
- __hmac_sha1(checksum, key, key_len, data, data_len, output);
-
- g_checksum_free(checksum);
-
- return 0;
-}
-
-static void F(GChecksum *checksum, const char *password, size_t password_len,
- const char *salt, size_t salt_len,
- unsigned int iterations, unsigned int count,
- unsigned char *digest)
-{
- unsigned char tmp1[SHA1_MAC_LEN];
- unsigned char tmp2[SHA1_MAC_LEN];
- unsigned char buf[36];
- unsigned int i, j;
-
- memcpy(buf, salt, salt_len);
- buf[salt_len + 0] = (count >> 24) & 0xff;
- buf[salt_len + 1] = (count >> 16) & 0xff;
- buf[salt_len + 2] = (count >> 8) & 0xff;
- buf[salt_len + 3] = count & 0xff;
-
- __hmac_sha1(checksum, password, password_len,
- buf, salt_len + 4, tmp1);
- memcpy(digest, tmp1, SHA1_MAC_LEN);
-
- for (i = 1; i < iterations; i++) {
- __hmac_sha1(checksum, password, password_len,
- tmp1, SHA1_MAC_LEN, tmp2);
- memcpy(tmp1, tmp2, SHA1_MAC_LEN);
-
- for (j = 0; j < SHA1_MAC_LEN; j++)
- digest[j] ^= tmp2[j];
- }
-}
-
-int pbkdf2_sha1(const void *password, size_t password_len,
- const void *salt, size_t salt_len,
- unsigned int iterations, void *output, size_t size)
-{
- GChecksum *checksum;
- unsigned char *ptr = output;
- unsigned char digest[SHA1_MAC_LEN];
- unsigned int i;
-
- checksum = g_checksum_new(G_CHECKSUM_SHA1);
-
- for (i = 1; size > 0; i++) {
- size_t len;
-
- F(checksum, password, password_len, salt, salt_len,
- iterations, i, digest);
-
- len = size > SHA1_MAC_LEN ? SHA1_MAC_LEN : size;
- memcpy(ptr, digest, len);
-
- ptr += len;
- size -= len;
- }
-
- g_checksum_free(checksum);
-
- return 0;
-}
-
-int prf_sha1(const void *key, size_t key_len,
- const void *prefix, size_t prefix_len,
- const void *data, size_t data_len, void *output, size_t size)
-{
- GChecksum *checksum;
- unsigned char input[1024];
- size_t input_len;
- unsigned int i, offset = 0;
-
- checksum = g_checksum_new(G_CHECKSUM_SHA1);
-
- memcpy(input, prefix, prefix_len);
- input[prefix_len] = 0;
-
- memcpy(input + prefix_len + 1, data, data_len);
- input[prefix_len + 1 + data_len] = 0;
-
- input_len = prefix_len + 1 + data_len + 1;
-
- for (i = 0; i < (size + 19) / 20; i++) {
- __hmac_sha1(checksum, key, key_len, input, input_len,
- output + offset);
-
- offset += 20;
- input[input_len - 1]++;
- }
-
- g_checksum_free(checksum);
-
- return 0;
-}
diff --git a/src/shared/sha1.h b/src/shared/sha1.h
deleted file mode 100644
index 0c0c6d19..00000000
--- a/src/shared/sha1.h
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- *
- * Connection Manager
- *
- * Copyright (C) 2012 Intel Corporation. All rights reserved.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- *
- */
-
-int hmac_sha1(const void *key, size_t key_len,
- const void *data, size_t data_len, void *output, size_t size);
-
-int pbkdf2_sha1(const void *password, size_t password_len,
- const void *salt, size_t salt_len,
- unsigned int iterations, void *output, size_t size);
-
-int prf_sha1(const void *key, size_t key_len,
- const void *prefix, size_t prefix_len,
- const void *data, size_t data_len, void *output, size_t size);
diff --git a/src/technology.c b/src/technology.c
index d80d9e6d..55303a0c 100644
--- a/src/technology.c
+++ b/src/technology.c
@@ -84,6 +84,9 @@ struct connman_technology {
static GSList *driver_list = NULL;
+static int technology_enabled(struct connman_technology *technology);
+static int technology_disabled(struct connman_technology *technology);
+
static gint compare_priority(gconstpointer a, gconstpointer b)
{
const struct connman_technology_driver *driver1 = a;
@@ -615,19 +618,27 @@ static gboolean technology_pending_reply(gpointer user_data)
static int technology_affect_devices(struct connman_technology *technology,
bool enable_device)
{
+ int err = 0, err_dev;
GSList *list;
- int err = -ENXIO;
- if (technology->type == CONNMAN_SERVICE_TYPE_P2P)
+ if (technology->type == CONNMAN_SERVICE_TYPE_P2P) {
+ if (enable_device)
+ __connman_technology_enabled(technology->type);
+ else
+ __connman_technology_disabled(technology->type);
return 0;
+ }
for (list = technology->device_list; list; list = list->next) {
struct connman_device *device = list->data;
if (enable_device)
- err = __connman_device_enable(device);
+ err_dev = __connman_device_enable(device);
else
- err = __connman_device_disable(device);
+ err_dev = __connman_device_disable(device);
+
+ if (err_dev < 0 && err_dev != -EALREADY)
+ err = err_dev;
}
return err;
@@ -1186,13 +1197,6 @@ static struct connman_technology *technology_get(enum connman_service_type type)
technology->type = type;
technology->path = g_strdup_printf("%s/technology/%s",
CONNMAN_PATH, str);
- if (type == CONNMAN_SERVICE_TYPE_P2P) {
- struct connman_technology *wifi;
-
- wifi = technology_find(CONNMAN_SERVICE_TYPE_WIFI);
- if (wifi)
- technology->enabled = wifi->enabled;
- }
technology_load(technology);
technology_list = g_slist_prepend(technology_list, technology);
@@ -1211,7 +1215,20 @@ static struct connman_technology *technology_get(enum connman_service_type type)
return NULL;
}
- DBG("technology %p", technology);
+ if (type == CONNMAN_SERVICE_TYPE_P2P) {
+ struct connman_technology *wifi;
+ bool enable;
+
+ enable = technology->enable_persistent;
+
+ wifi = technology_find(CONNMAN_SERVICE_TYPE_WIFI);
+ if (enable && wifi)
+ enable = wifi->enabled;
+
+ technology_affect_devices(technology, enable);
+ }
+
+ DBG("technology %p %s", technology, get_name(technology->type));
return technology;
}
@@ -1797,6 +1814,12 @@ void __connman_technology_cleanup(void)
{
DBG("");
+ while (technology_list) {
+ struct connman_technology *technology = technology_list->data;
+ technology_list = g_slist_remove(technology_list, technology);
+ technology_put(technology);
+ }
+
g_hash_table_destroy(rfkill_list);
dbus_connection_unref(connection);
diff --git a/src/util.c b/src/util.c
new file mode 100644
index 00000000..da32cc55
--- /dev/null
+++ b/src/util.c
@@ -0,0 +1,88 @@
+/*
+ *
+ * Connection Manager
+ *
+ * Copyright (C) 2014 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <stdint.h>
+#include <unistd.h>
+#include <errno.h>
+#include <stdlib.h>
+
+#include "connman.h"
+
+#define URANDOM "/dev/urandom"
+
+int f = -1;
+
+int __connman_util_get_random(uint64_t *val)
+{
+ int r = 0;
+
+ if (!val)
+ return -EINVAL;
+
+ if (read(f, val, sizeof(uint64_t)) < 0) {
+ r = -errno;
+ connman_warn_once("Could not read from "URANDOM);
+ *val = random();
+ }
+
+ return r;
+}
+
+int __connman_util_init(void)
+{
+ int r = 0;
+
+ if (f > 0)
+ return 0;
+
+ f = open(URANDOM, O_RDONLY);
+ if (f < 0) {
+ r = -errno;
+ connman_warn("Could not open "URANDOM);
+ srandom(time(NULL));
+ } else {
+ uint64_t val;
+
+ r = __connman_util_get_random(&val);
+ if (r < 0)
+ srandom(time(NULL));
+ else
+ srandom(val);
+ }
+
+ return r;
+}
+
+void __connman_util_cleanup(void)
+{
+ if (f > 0)
+ close(f);
+
+ f = -1;
+}
diff --git a/src/wispr.c b/src/wispr.c
index c4fcd60b..ef4bdaba 100644
--- a/src/wispr.c
+++ b/src/wispr.c
@@ -143,6 +143,7 @@ static void free_wispr_routes(struct connman_wispr_portal_context *wp_context)
route->address);
break;
case CONNMAN_IPCONFIG_TYPE_UNKNOWN:
+ case CONNMAN_IPCONFIG_TYPE_ALL:
break;
}
@@ -487,6 +488,7 @@ static bool wispr_route_request(const char *address, int ai_family,
gateway);
break;
case CONNMAN_IPCONFIG_TYPE_UNKNOWN:
+ case CONNMAN_IPCONFIG_TYPE_ALL:
break;
}