diff options
author | Zhang zhengguang <zhengguang.zhang@intel.com> | 2014-07-17 10:37:39 +0800 |
---|---|---|
committer | Zhang zhengguang <zhengguang.zhang@intel.com> | 2014-07-17 10:37:39 +0800 |
commit | 1b9d0a62f59bb48c8deb2f0b98d9acdffdd9abe7 (patch) | |
tree | 6e991827d28537f7f40f20786c2354fd04a9fdad /src | |
parent | fbe905ab58ecc31fe64c410c5f580cadc30e7f04 (diff) | |
download | connman-1b9d0a62f59bb48c8deb2f0b98d9acdffdd9abe7.tar.gz connman-1b9d0a62f59bb48c8deb2f0b98d9acdffdd9abe7.tar.bz2 connman-1b9d0a62f59bb48c8deb2f0b98d9acdffdd9abe7.zip |
Imported Upstream version 1.24upstream/1.24
Diffstat (limited to 'src')
59 files changed, 10209 insertions, 5911 deletions
@@ -77,21 +77,23 @@ static int tunnel_create(struct in_addr *addr) p.iph.protocol = IPPROTO_IPV6; p.iph.saddr = addr->s_addr; p.iph.ttl = 64; - strncpy(p.name, "tun6to4", IFNAMSIZ); + strncpy(p.name, "tun6to4", sizeof(p.name) - 1); - strncpy(ifr.ifr_name, "sit0", IFNAMSIZ); + strncpy(ifr.ifr_name, "sit0", sizeof(ifr.ifr_name) - 1); ifr.ifr_ifru.ifru_data = (void *)&p; fd = socket(AF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0); + if (fd < 0) + return -errno; ret = ioctl(fd, SIOCADDTUNNEL, &ifr); if (ret) connman_error("add tunnel %s failed: %s", ifr.ifr_name, strerror(errno)); close(fd); - return ret; + return -ret; } -static void tunnel_destroy() +static void tunnel_destroy(void) { struct ip_tunnel_parm p; struct ifreq ifr; @@ -109,9 +111,9 @@ static void tunnel_destroy() p.iph.version = 4; p.iph.ihl = 5; p.iph.protocol = IPPROTO_IPV6; - strncpy(p.name, "tun6to4", IFNAMSIZ); + strncpy(p.name, "tun6to4", sizeof(p.name) - 1); - strncpy(ifr.ifr_name, "tun6to4", IFNAMSIZ); + strncpy(ifr.ifr_name, "tun6to4", sizeof(ifr.ifr_name) - 1); ifr.ifr_ifru.ifru_data = (void *)&p; fd = socket(AF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0); if (fd < 0) { @@ -133,7 +135,7 @@ static void tunnel_destroy() tunnel_ip_address = NULL; } -static int tunnel_add_route() +static int tunnel_add_route(void) { struct __connman_inet_rtnl_handle rth; struct in6_addr addr6; @@ -231,12 +233,12 @@ static gboolean unref_web(gpointer user_data) return FALSE; } -static gboolean web_result(GWebResult *result, gpointer user_data) +static bool web_result(GWebResult *result, gpointer user_data) { guint16 status; if (web_request_id == 0) - return FALSE; + return false; status = g_web_result_get_status(result); @@ -251,7 +253,7 @@ static gboolean web_result(GWebResult *result, gpointer user_data) g_timeout_add_seconds(1, unref_web, NULL); - return FALSE; + return false; } static void web_debug(const char *str, void *data) @@ -303,7 +305,7 @@ static void tun_newlink(unsigned flags, unsigned change, void *user_data) } web = g_web_new(index); - if (web == NULL) { + if (!web) { tunnel_destroy(); return; } @@ -384,7 +386,7 @@ static void receive_rs_reply(struct nd_router_advert *reply, /* We try to create tunnel if autoconfiguration did not work i.e., * we did not receive any reply to router solicitation message. */ - if (reply == NULL && inet_aton(address, &ip4addr) != 0) + if (!reply && inet_aton(address, &ip4addr) != 0) init_6to4(&ip4addr); g_free(address); @@ -406,15 +408,15 @@ int __connman_6to4_probe(struct connman_service *service) if (tunnel_created || tunnel_pending) return 0; - if (service == NULL) + if (!service) return -1; ip4config = __connman_service_get_ip4config(service); - if (ip4config == NULL) + if (!ip4config) return -1; ip6config = __connman_service_get_ip6config(service); - if (ip6config == NULL) + if (!ip6config) return -1; method = __connman_ipconfig_get_method(ip6config); @@ -422,7 +424,7 @@ int __connman_6to4_probe(struct connman_service *service) return -1; address = __connman_ipconfig_get_local(ip4config); - if (address == NULL) + if (!address) return -1; if (inet_aton(address, &ip4addr) == 0) @@ -455,11 +457,11 @@ void __connman_6to4_remove(struct connman_ipconfig *ip4config) DBG("tunnel ip address %s", tunnel_ip_address); - if (ip4config == NULL) + if (!ip4config) return; address = __connman_ipconfig_get_local(ip4config); - if (address == NULL) + if (!address) return; if (g_strcmp0(address, tunnel_ip_address) != 0) @@ -473,14 +475,14 @@ int __connman_6to4_check(struct connman_ipconfig *ip4config) { const char *address; - if (ip4config == NULL || tunnel_created == 0 || + if (!ip4config || tunnel_created == 0 || tunnel_pending == 1) return -1; DBG("tunnel ip address %s", tunnel_ip_address); address = __connman_ipconfig_get_local(ip4config); - if (address == NULL) + if (!address) return -1; if (g_strcmp0(address, tunnel_ip_address) == 0) diff --git a/src/agent-connman.c b/src/agent-connman.c index 9ccba72e..ab538f38 100644 --- a/src/agent-connman.c +++ b/src/agent-connman.c @@ -2,7 +2,7 @@ * * Connection Manager * - * Copyright (C) 2012 Intel Corporation. All rights reserved. + * Copyright (C) 2012-2013 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 @@ -34,7 +34,7 @@ #include "connman.h" -static connman_bool_t check_reply_has_dict(DBusMessage *reply) +static bool check_reply_has_dict(DBusMessage *reply) { const char *signature = DBUS_TYPE_ARRAY_AS_STRING DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING @@ -42,8 +42,8 @@ static connman_bool_t check_reply_has_dict(DBusMessage *reply) DBUS_TYPE_VARIANT_AS_STRING DBUS_DICT_ENTRY_END_CHAR_AS_STRING; - if (dbus_message_has_signature(reply, signature) == TRUE) - return TRUE; + if (dbus_message_has_signature(reply, signature)) + return true; connman_warn("Reply %s to %s from %s has wrong signature %s", signature, @@ -51,7 +51,7 @@ static connman_bool_t check_reply_has_dict(DBusMessage *reply) dbus_message_get_sender(reply), dbus_message_get_signature(reply)); - return FALSE; + return false; } struct request_input_reply { @@ -63,8 +63,8 @@ struct request_input_reply { static void request_input_passphrase_reply(DBusMessage *reply, void *user_data) { struct request_input_reply *passphrase_reply = user_data; - connman_bool_t values_received = FALSE; - connman_bool_t wps = FALSE; + bool values_received = false; + bool wps = false; const char *error = NULL; char *identity = NULL; char *passphrase = NULL; @@ -74,15 +74,18 @@ static void request_input_passphrase_reply(DBusMessage *reply, void *user_data) int name_len = 0; DBusMessageIter iter, dict; + if (!reply) + goto out; + if (dbus_message_get_type(reply) == DBUS_MESSAGE_TYPE_ERROR) { error = dbus_message_get_error_name(reply); goto done; } - if (check_reply_has_dict(reply) == FALSE) + if (!check_reply_has_dict(reply)) goto done; - values_received = TRUE; + values_received = true; dbus_message_iter_init(reply, &iter); dbus_message_iter_recurse(&iter, &dict); @@ -105,13 +108,14 @@ static void request_input_passphrase_reply(DBusMessage *reply, void *user_data) } else if (g_str_equal(key, "Passphrase")) { dbus_message_iter_next(&entry); - if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_VARIANT) + if (dbus_message_iter_get_arg_type(&entry) + != DBUS_TYPE_VARIANT) break; dbus_message_iter_recurse(&entry, &value); dbus_message_iter_get_basic(&value, &passphrase); } else if (g_str_equal(key, "WPS")) { - wps = TRUE; + wps = true; dbus_message_iter_next(&entry); if (dbus_message_iter_get_arg_type(&entry) @@ -152,6 +156,8 @@ done: identity, passphrase, wps, wpspin, error, passphrase_reply->user_data); + +out: g_free(passphrase_reply); } @@ -161,14 +167,14 @@ static void request_input_append_alternates(DBusMessageIter *iter, const char *str = user_data; char **alternates, **alternative; - if (str == NULL) + if (!str) return; alternates = g_strsplit(str, ",", 0); - if (alternates == NULL) + if (!alternates) return; - for (alternative = alternates; *alternative != NULL; alternative++) + for (alternative = alternates; *alternative; alternative++) dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, alternative); @@ -204,9 +210,9 @@ static void request_input_append_passphrase(DBusMessageIter *iter, case CONNMAN_SERVICE_SECURITY_8021X: phase2 = __connman_service_get_phase2(service); - if (phase2 != NULL && ( - g_str_has_suffix(phase2, "GTC") == TRUE || - g_str_has_suffix(phase2, "OTP") == TRUE)) + if (phase2 && ( + g_str_has_suffix(phase2, "GTC") || + g_str_has_suffix(phase2, "OTP"))) value = "response"; else value = "passphrase"; @@ -222,7 +228,7 @@ static void request_input_append_passphrase(DBusMessageIter *iter, connman_dbus_dict_append_basic(iter, "Requirement", DBUS_TYPE_STRING, &value); - if (__connman_service_wps_enabled(service) == TRUE) { + if (__connman_service_wps_enabled(service)) { connman_dbus_dict_append_array(iter, "Alternates", DBUS_TYPE_STRING, request_input_append_alternates, @@ -310,12 +316,12 @@ static void previous_passphrase_handler(DBusMessageIter *iter, network = __connman_service_get_network(service); data.passphrase = connman_network_get_string(network, "WiFi.PinWPS"); - if (connman_network_get_bool(network, "WiFi.UseWPS") == TRUE && - data.passphrase != NULL) { + if (connman_network_get_bool(network, "WiFi.UseWPS") && + data.passphrase) { data.type = "wpspin"; } else { data.passphrase = __connman_service_get_passphrase(service); - if (data.passphrase == NULL) + if (!data.passphrase) return; security = __connman_service_get_security(service); @@ -342,21 +348,24 @@ static void request_input_login_reply(DBusMessage *reply, void *user_data) { struct request_input_reply *username_password_reply = user_data; const char *error = NULL; - connman_bool_t values_received = FALSE; + bool values_received = false; char *username = NULL; char *password = NULL; char *key; DBusMessageIter iter, dict; + if (!reply) + goto out; + if (dbus_message_get_type(reply) == DBUS_MESSAGE_TYPE_ERROR) { error = dbus_message_get_error_name(reply); goto done; } - if (check_reply_has_dict(reply) == FALSE) + if (!check_reply_has_dict(reply)) goto done; - values_received = TRUE; + values_received = true; dbus_message_iter_init(reply, &iter); dbus_message_iter_recurse(&iter, &dict); @@ -395,11 +404,14 @@ done: username, password, FALSE, NULL, error, username_password_reply->user_data); + +out: g_free(username_password_reply); } int __connman_agent_request_passphrase_input(struct connman_service *service, - authentication_cb_t callback, void *user_data) + authentication_cb_t callback, + const char *dbus_sender, void *user_data) { DBusMessage *message; const char *path, *agent_sender, *agent_path; @@ -407,16 +419,20 @@ int __connman_agent_request_passphrase_input(struct connman_service *service, DBusMessageIter dict; struct request_input_reply *passphrase_reply; int err; + void *agent; - connman_agent_get_info(&agent_sender, &agent_path); + agent = connman_agent_get_info(dbus_sender, &agent_sender, + &agent_path); - if (service == NULL || agent_path == NULL || callback == NULL) + DBG("agent %p service %p path %s", agent, service, agent_path); + + if (!service || !agent || !agent_path || !callback) return -ESRCH; message = dbus_message_new_method_call(agent_sender, agent_path, CONNMAN_AGENT_INTERFACE, "RequestInput"); - if (message == NULL) + if (!message) return -ENOMEM; dbus_message_iter_init_append(message, &iter); @@ -443,20 +459,19 @@ int __connman_agent_request_passphrase_input(struct connman_service *service, if (__connman_service_get_security(service) != CONNMAN_SERVICE_SECURITY_NONE) { connman_dbus_dict_append_dict(&dict, "Passphrase", - request_input_append_passphrase, service); + request_input_append_passphrase, service); previous_passphrase_handler(&dict, service); } - if (__connman_service_wps_enabled(service) == TRUE) { - connman_dbus_dict_append_dict(&dict, "WPS", + if (__connman_service_wps_enabled(service)) + connman_dbus_dict_append_dict(&dict, "WPS", request_input_append_wps, NULL); - } connman_dbus_dict_close(&iter, &dict); passphrase_reply = g_try_new0(struct request_input_reply, 1); - if (passphrase_reply == NULL) { + if (!passphrase_reply) { dbus_message_unref(message); return -ENOMEM; } @@ -468,7 +483,7 @@ int __connman_agent_request_passphrase_input(struct connman_service *service, err = connman_agent_queue_message(service, message, connman_timeout_input_request(), request_input_passphrase_reply, - passphrase_reply); + passphrase_reply, agent); if (err < 0 && err != -EBUSY) { DBG("error %d sending agent message", err); @@ -491,16 +506,17 @@ int __connman_agent_request_login_input(struct connman_service *service, DBusMessageIter dict; struct request_input_reply *username_password_reply; int err; + void *agent; - connman_agent_get_info(&agent_sender, &agent_path); + agent = connman_agent_get_info(NULL, &agent_sender, &agent_path); - if (service == NULL || agent_path == NULL || callback == NULL) + if (!service || !agent || !agent_path || !callback) return -ESRCH; message = dbus_message_new_method_call(agent_sender, agent_path, CONNMAN_AGENT_INTERFACE, "RequestInput"); - if (message == NULL) + if (!message) return -ENOMEM; dbus_message_iter_init_append(message, &iter); @@ -520,7 +536,7 @@ int __connman_agent_request_login_input(struct connman_service *service, connman_dbus_dict_close(&iter, &dict); username_password_reply = g_try_new0(struct request_input_reply, 1); - if (username_password_reply == NULL) { + if (!username_password_reply) { dbus_message_unref(message); return -ENOMEM; } @@ -531,7 +547,8 @@ int __connman_agent_request_login_input(struct connman_service *service, err = connman_agent_queue_message(service, message, connman_timeout_input_request(), - request_input_login_reply, username_password_reply); + request_input_login_reply, username_password_reply, + agent); if (err < 0 && err != -EBUSY) { DBG("error %d sending agent request", err); dbus_message_unref(message); @@ -553,7 +570,7 @@ struct request_browser_reply_data { static void request_browser_reply(DBusMessage *reply, void *user_data) { struct request_browser_reply_data *browser_reply_data = user_data; - connman_bool_t result = FALSE; + bool result = false; const char *error = NULL; if (dbus_message_get_type(reply) == DBUS_MESSAGE_TYPE_ERROR) { @@ -561,7 +578,7 @@ static void request_browser_reply(DBusMessage *reply, void *user_data) goto done; } - result = TRUE; + result = true; done: browser_reply_data->callback(browser_reply_data->service, result, @@ -578,19 +595,20 @@ int __connman_agent_request_browser(struct connman_service *service, DBusMessageIter iter; const char *path, *agent_sender, *agent_path; int err; + void *agent; - connman_agent_get_info(&agent_sender, &agent_path); + agent = connman_agent_get_info(NULL, &agent_sender, &agent_path); - if (service == NULL || agent_path == NULL || callback == NULL) + if (!service || !agent || !agent_path || !callback) return -ESRCH; - if (url == NULL) + if (!url) url = ""; message = dbus_message_new_method_call(agent_sender, agent_path, CONNMAN_AGENT_INTERFACE, "RequestBrowser"); - if (message == NULL) + if (!message) return -ENOMEM; dbus_message_iter_init_append(message, &iter); @@ -601,7 +619,7 @@ int __connman_agent_request_browser(struct connman_service *service, dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &url); browser_reply_data = g_try_new0(struct request_browser_reply_data, 1); - if (browser_reply_data == NULL) { + if (!browser_reply_data) { dbus_message_unref(message); return -ENOMEM; } @@ -612,7 +630,8 @@ int __connman_agent_request_browser(struct connman_service *service, err = connman_agent_queue_message(service, message, connman_timeout_browser_launch(), - request_browser_reply, browser_reply_data); + request_browser_reply, browser_reply_data, + agent); if (err < 0 && err != -EBUSY) { DBG("error %d sending browser request", err); diff --git a/src/agent.c b/src/agent.c index 5c3bd28c..37cf5247 100644 --- a/src/agent.c +++ b/src/agent.c @@ -2,7 +2,7 @@ * * Connection Manager * - * Copyright (C) 2007-2012 Intel Corporation. All rights reserved. + * Copyright (C) 2007-2013 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 @@ -33,12 +33,25 @@ #include "connman.h" +#define agent_ref(agent) \ + agent_ref_debug(agent, __FILE__, __LINE__, __func__) +#define agent_unref(agent) \ + agent_unref_debug(agent, __FILE__, __LINE__, __func__) + static DBusConnection *connection = NULL; -static guint agent_watch = 0; -static gchar *agent_path = NULL; -static gchar *agent_sender = NULL; +static GHashTable *agent_hash = NULL; +static struct connman_agent *default_agent = NULL; struct connman_agent { + int refcount; + char *owner; + char *path; + struct connman_agent_request *pending; + GList *queue; /* queued requests for this agent */ + guint watch; +}; + +struct connman_agent_request { void *user_context; void *user_data; DBusMessage *msg; @@ -48,119 +61,150 @@ struct connman_agent { struct connman_agent_driver *driver; }; -static GList *agent_queue = NULL; -static struct connman_agent *agent_request = NULL; static GSList *driver_list = NULL; -void connman_agent_get_info(const char **sender, const char **path) +void *connman_agent_get_info(const char *dbus_sender, const char **sender, + const char **path) { - *sender = agent_sender; - *path = agent_path; + struct connman_agent *agent; + + if (!dbus_sender) + agent = default_agent; + else { + agent = g_hash_table_lookup(agent_hash, dbus_sender); + if (!agent) + agent = default_agent; + } + + if (agent) { + if (sender) + *sender = agent->owner; + if (path) + *path = agent->path; + } else { + if (sender) + *sender = NULL; + if (path) + *path = NULL; + } + + return agent; } -static void agent_data_free(struct connman_agent *data) +static void agent_request_free(struct connman_agent_request *request) { - if (data == NULL) + if (!request) return; - if (data->user_context != NULL) { - if (data->driver != NULL && data->driver->context_unref != NULL) - data->driver->context_unref(data->user_context); + + if (request->user_context) { + if (request->driver && request->driver->context_unref) + request->driver->context_unref(request->user_context); + } + + if (request->msg) + dbus_message_unref(request->msg); + + if (request->call) { + dbus_pending_call_cancel(request->call); + dbus_pending_call_unref(request->call); } - if (data->msg != NULL) - dbus_message_unref(data->msg); - if (data->call != NULL) - dbus_pending_call_cancel(data->call); - g_free(data); + g_free(request); +} + +static void agent_finalize_pending(struct connman_agent *agent, + DBusMessage *reply) +{ + struct connman_agent_request *pending = agent->pending; + if (pending) { + agent->pending = NULL; + pending->callback(reply, pending->user_data); + agent_request_free(pending); + } } static void agent_receive_message(DBusPendingCall *call, void *user_data); -static int agent_send_next_request(void) +static int agent_send_next_request(struct connman_agent *agent) { - if (agent_request != NULL) + if (agent->pending) return -EBUSY; - if (agent_queue == NULL) + if (!agent->queue) return 0; - agent_request = agent_queue->data; - agent_queue = g_list_remove(agent_queue, agent_request); + agent->pending = agent->queue->data; + agent->queue = g_list_remove(agent->queue, agent->pending); + + if (!agent->pending->msg) + goto fail; - if (dbus_connection_send_with_reply(connection, agent_request->msg, - &agent_request->call, - agent_request->timeout) == FALSE) + if (!dbus_connection_send_with_reply(connection, agent->pending->msg, + &agent->pending->call, + agent->pending->timeout)) goto fail; - if (agent_request->call == NULL) + if (!agent->pending->call) goto fail; - if (dbus_pending_call_set_notify(agent_request->call, - agent_receive_message, agent_request, NULL) == FALSE) + if (!dbus_pending_call_set_notify(agent->pending->call, + agent_receive_message, + agent, NULL)) goto fail; - dbus_message_unref(agent_request->msg); - agent_request->msg = NULL; + dbus_message_unref(agent->pending->msg); + agent->pending->msg = NULL; return 0; fail: - agent_data_free(agent_request); - agent_request = NULL; + agent_finalize_pending(agent, NULL); return -ESRCH; } -static int agent_send_cancel(struct connman_agent *agent) +static int send_cancel_request(struct connman_agent *agent, + struct connman_agent_request *request) { DBusMessage *message; - if (agent_sender == NULL || agent == NULL || agent->driver == NULL) - return 0; + DBG("send cancel req to %s %s", agent->owner, agent->path); - message = dbus_message_new_method_call(agent_sender, agent_path, - agent->driver->interface, "Cancel"); - if (message != NULL) { - dbus_message_set_no_reply(message, TRUE); - g_dbus_send_message(connection, message); - return 0; + message = dbus_message_new_method_call(agent->owner, + agent->path, + request->driver->interface, + "Cancel"); + if (!message) { + connman_error("Couldn't allocate D-Bus message"); + return -ENOMEM; } - connman_warn("Failed to send Cancel message to agent"); - return -ESRCH; + g_dbus_send_message(connection, message); + return 0; } static void agent_receive_message(DBusPendingCall *call, void *user_data) { - struct connman_agent *queue_data = user_data; + struct connman_agent *agent = user_data; DBusMessage *reply; int err; - DBG("waiting for %p received %p", agent_request, queue_data); - - if (agent_request != queue_data) { - connman_error("Agent callback expected %p got %p", - agent_request, queue_data); - return; - } + DBG("agent %p req %p", agent, agent->pending); reply = dbus_pending_call_steal_reply(call); dbus_pending_call_unref(call); - queue_data->call = NULL; + agent->pending->call = NULL; if (dbus_message_is_error(reply, - "org.freedesktop.DBus.Error.Timeout") == TRUE || + "org.freedesktop.DBus.Error.Timeout") || dbus_message_is_error(reply, - "org.freedesktop.DBus.Error.TimedOut") == TRUE) { - agent_send_cancel(queue_data->user_context); + "org.freedesktop.DBus.Error.TimedOut")) { + send_cancel_request(agent, agent->pending); } - queue_data->callback(reply, queue_data->user_data); + agent_finalize_pending(agent, reply); dbus_message_unref(reply); - agent_data_free(queue_data); - agent_request = NULL; - - err = agent_send_next_request(); - if (err < 0) + err = agent_send_next_request(agent); + if (err < 0 && err != -EBUSY) DBG("send next request failed (%s/%d)", strerror(-err), -err); } @@ -171,23 +215,25 @@ static struct connman_agent_driver *get_driver(void) int connman_agent_queue_message(void *user_context, DBusMessage *msg, int timeout, - agent_queue_cb callback, void *user_data) + agent_queue_cb callback, void *user_data, + void *agent_data) { - struct connman_agent *queue_data; + struct connman_agent_request *queue_data; struct connman_agent_driver *driver; + struct connman_agent *agent = agent_data; int err; - if (user_context == NULL || callback == NULL) + if (!user_context || !callback) return -EBADMSG; - queue_data = g_new0(struct connman_agent, 1); - if (queue_data == NULL) + queue_data = g_new0(struct connman_agent_request, 1); + if (!queue_data) return -ENOMEM; driver = get_driver(); DBG("driver %p", driver); - if (driver != NULL && driver->context_ref != NULL) { + if (driver && driver->context_ref) { queue_data->user_context = driver->context_ref(user_context); queue_data->driver = driver; } else @@ -197,103 +243,97 @@ int connman_agent_queue_message(void *user_context, queue_data->timeout = timeout; queue_data->callback = callback; queue_data->user_data = user_data; - agent_queue = g_list_append(agent_queue, queue_data); + agent->queue = g_list_append(agent->queue, queue_data); - err = agent_send_next_request(); - if (err < 0) + err = agent_send_next_request(agent); + if (err < 0 && err != -EBUSY) DBG("send next request failed (%s/%d)", strerror(-err), -err); return err; } -void connman_agent_cancel(void *user_context) +static void set_default_agent(void) { - GList *item, *next; - struct connman_agent *queued_req; - int err; - - DBG("context %p", user_context); - - item = agent_queue; - - while (item != NULL) { - next = g_list_next(item); - queued_req = item->data; - - if (queued_req->user_context == user_context || - user_context == NULL) { - agent_data_free(queued_req); - agent_queue = g_list_delete_link(agent_queue, item); - } - - item = next; - } + struct connman_agent *agent = NULL; + GHashTableIter iter; + gpointer key, value; - if (agent_request == NULL) + if (default_agent) return; - if (agent_request->user_context != user_context && - user_context != NULL) - return; - - agent_send_cancel(agent_request); + g_hash_table_iter_init(&iter, agent_hash); + if (g_hash_table_iter_next(&iter, &key, &value)) + agent = value; - agent_data_free(agent_request); - agent_request = NULL; + if (agent) + DBG("default agent set to %s %s", agent->owner, agent->path); + else + DBG("default agent cleared"); - err = agent_send_next_request(); - if (err < 0) - DBG("send next request failed (%s/%d)", strerror(-err), -err); + default_agent = agent; } -static void agent_free(void) +static void agent_disconnect(DBusConnection *conn, void *user_data) { - if (agent_watch > 0) - g_dbus_remove_watch(connection, agent_watch); + struct connman_agent *agent = user_data; - agent_watch = 0; + DBG("agent %s disconnected", agent->owner); - g_free(agent_sender); - agent_sender = NULL; - - g_free(agent_path); - agent_path = NULL; + if (agent->watch > 0) { + g_dbus_remove_watch(conn, agent->watch); + agent->watch = 0; + } - connman_agent_cancel(NULL); + g_hash_table_remove(agent_hash, agent->owner); } -static void agent_disconnect(DBusConnection *conn, void *data) +static struct connman_agent *agent_ref_debug(struct connman_agent *agent, + const char *file, int line, const char *caller) { - DBG("data %p", data); - agent_free(); + DBG("%p ref %d by %s:%d:%s()", agent, agent->refcount + 1, + file, line, caller); + + __sync_fetch_and_add(&agent->refcount, 1); + + return agent; } -int connman_agent_register(const char *sender, const char *path) +static struct connman_agent *agent_create(const char *name, const char *path) { - DBG("sender %s path %s", sender, path); - if (agent_path != NULL) - return -EEXIST; + struct connman_agent *agent; - agent_sender = g_strdup(sender); - agent_path = g_strdup(path); + agent = g_new0(struct connman_agent, 1); - agent_watch = g_dbus_add_disconnect_watch(connection, sender, - agent_disconnect, NULL, NULL); + agent->owner = g_strdup(name); + agent->path = g_strdup(path); - return 0; + agent->watch = g_dbus_add_disconnect_watch(connection, + name, agent_disconnect, + agent, NULL); + + return agent_ref(agent); } -int connman_agent_unregister(const char *sender, const char *path) +int connman_agent_register(const char *sender, const char *path) { + struct connman_agent *agent; + DBG("sender %s path %s", sender, path); - if (agent_path == NULL) - return -ESRCH; + agent = g_hash_table_lookup(agent_hash, sender); + if (agent) + return -EEXIST; + + agent = agent_create(sender, path); + if (!agent) + return -EINVAL; - if (agent_watch > 0) - g_dbus_remove_watch(connection, agent_watch); + DBG("agent %s", agent->owner); - agent_free(); + g_hash_table_replace(agent_hash, agent->owner, agent); + + if (!default_agent) + set_default_agent(); return 0; } @@ -307,15 +347,15 @@ struct report_error_data { static void report_error_reply(DBusMessage *reply, void *user_data) { struct report_error_data *report_error = user_data; - gboolean retry = FALSE; + bool retry = false; const char *dbus_err; if (dbus_message_get_type(reply) == DBUS_MESSAGE_TYPE_ERROR) { dbus_err = dbus_message_get_error_name(reply); - if (dbus_err != NULL && + if (dbus_err && strcmp(dbus_err, CONNMAN_AGENT_INTERFACE ".Error.Retry") == 0) - retry = TRUE; + retry = true; } report_error->callback(report_error->user_context, retry, @@ -325,21 +365,27 @@ static void report_error_reply(DBusMessage *reply, void *user_data) int connman_agent_report_error(void *user_context, const char *path, const char *error, - report_error_cb_t callback, void *user_data) + report_error_cb_t callback, + const char *dbus_sender, void *user_data) { DBusMessage *message; DBusMessageIter iter; struct report_error_data *report_error; + struct connman_agent *agent; int err; - if (user_context == NULL || agent_path == NULL || error == NULL || - callback == NULL) + agent = connman_agent_get_info(dbus_sender, NULL, NULL); + + DBG("agent %p sender %s context %p path %s", agent, + dbus_sender, user_context, agent ? agent->path : "-"); + + if (!user_context || !agent || !agent->path || !error || !callback) return -ESRCH; - message = dbus_message_new_method_call(agent_sender, agent_path, + message = dbus_message_new_method_call(agent->owner, agent->path, CONNMAN_AGENT_INTERFACE, "ReportError"); - if (message == NULL) + if (!message) return -ENOMEM; dbus_message_iter_init_append(message, &iter); @@ -350,7 +396,7 @@ int connman_agent_report_error(void *user_context, const char *path, DBUS_TYPE_STRING, &error); report_error = g_try_new0(struct report_error_data, 1); - if (report_error == NULL) { + if (!report_error) { dbus_message_unref(message); return -ENOMEM; } @@ -361,7 +407,8 @@ int connman_agent_report_error(void *user_context, const char *path, err = connman_agent_queue_message(user_context, message, connman_timeout_input_request(), - report_error_reply, report_error); + report_error_reply, report_error, + agent); if (err < 0 && err != -EBUSY) { DBG("error %d sending error request", err); g_free(report_error); @@ -400,6 +447,143 @@ int connman_agent_driver_register(struct connman_agent_driver *driver) return 0; } +static void release_driver(void) +{ + connman_agent_driver_unregister(get_driver()); +} + +static void cancel_all_requests(struct connman_agent *agent) +{ + GList *list; + + DBG("request %p pending %p", agent->pending, agent->queue); + + if (agent->pending) { + if (agent->pending->call) + send_cancel_request(agent, agent->pending); + + agent_finalize_pending(agent, NULL); + } + + for (list = agent->queue; list; list = list->next) { + struct connman_agent_request *request = list->data; + + if (!request) + continue; + + request->callback(NULL, request->user_data); + agent_request_free(request); + } + + g_list_free(agent->queue); + agent->queue = NULL; +} + +void connman_agent_cancel(void *user_context) +{ + GHashTableIter iter; + gpointer key, value; + int err; + + DBG("context %p", user_context); + + g_hash_table_iter_init(&iter, agent_hash); + while (g_hash_table_iter_next(&iter, &key, &value)) { + GList *list; + struct connman_agent *agent = value; + + /* + * Cancel all the pending requests to a given agent and service + */ + list = agent->queue; + while (list) { + struct connman_agent_request *request = list->data; + + if (request && request->user_context && + request->user_context == + user_context) { + DBG("cancel pending %p", request); + + request->callback(NULL, request->user_data); + + agent_request_free(request); + + agent->queue = list->next; + list = g_list_delete_link(list, list); + } else + list = list->next; + } + + /* + * If there is a request from client to a given service, + * we need to cancel it. + */ + if (agent->pending && agent->pending->user_context && + agent->pending->user_context == user_context) { + DBG("cancel request %p", agent->pending); + + if (agent->pending->call) + send_cancel_request(agent, agent->pending); + + agent_finalize_pending(agent, NULL); + + err = agent_send_next_request(agent); + if (err < 0 && err != -EBUSY) + DBG("send next request failed (%s/%d)", + strerror(-err), -err); + } + } +} + +static void agent_unref_debug(struct connman_agent *agent, + const char *file, int line, const char *caller) +{ + DBG("%p ref %d by %s:%d:%s()", agent, agent->refcount - 1, + file, line, caller); + + if (__sync_fetch_and_sub(&agent->refcount, 1) != 1) + return; + + cancel_all_requests(agent); + + g_free(agent->owner); + g_free(agent->path); + + if (agent == default_agent) { + default_agent = NULL; + set_default_agent(); + } + + g_free(agent); +} + +static void agent_release(struct connman_agent *agent, const char *interface) +{ + DBusMessage *message; + + DBG("release agent %s %s", agent->owner, agent->path); + + message = dbus_message_new_method_call(agent->owner, agent->path, + interface, "Release"); + if (message == NULL) { + connman_error("Couldn't allocate D-Bus message"); + return; + } + + dbus_message_set_no_reply(message, TRUE); + g_dbus_send_message(connection, message); +} + +static void release_agents(void) +{ + GHashTableIter iter; + gpointer key, value; + + g_hash_table_iter_init(&iter, agent_hash); + while (g_hash_table_iter_next(&iter, &key, &value)) + agent_release(value, get_driver()->interface); +} + /** * connman_agent_driver_unregister: * @driver: Agent driver definition @@ -410,47 +594,46 @@ void connman_agent_driver_unregister(struct connman_agent_driver *driver) { GSList *list; - if (driver == NULL) + if (!driver) return; DBG("Unregistering driver %p name %s", driver, driver->name); - if (agent_sender == NULL && agent_path == NULL) - goto out; + release_agents(); for (list = driver_list; list; list = list->next) { - DBusMessage *message; - if (driver != list->data) continue; - DBG("Sending release to %s path %s iface %s", agent_sender, - agent_path, driver->interface); + g_hash_table_remove_all(agent_hash); + break; + } - message = dbus_message_new_method_call(agent_sender, agent_path, - driver->interface, "Release"); - if (message != NULL) { - dbus_message_set_no_reply(message, TRUE); - g_dbus_send_message(connection, message); - } + driver_list = g_slist_remove(driver_list, driver); +} - agent_free(); +static void agent_destroy(gpointer data) +{ + struct connman_agent *agent = data; - /* - * ATM agent_free() unsets the agent_sender and agent_path - * variables so we can unregister only once. - * This needs proper fix later. - */ - break; + DBG("agent %s req %p", agent->owner, agent->pending); + + if (agent->watch > 0) { + g_dbus_remove_watch(connection, agent->watch); + agent->watch = 0; } -out: - driver_list = g_slist_remove(driver_list, driver); + agent_unref(agent); } -static void release_all_agents(void) +int connman_agent_unregister(const char *sender, const char *path) { - connman_agent_driver_unregister(get_driver()); + DBG("sender %s path %s", sender, path); + + if (!g_hash_table_remove(agent_hash, sender)) + return -ESRCH; + + return 0; } int __connman_agent_init(void) @@ -458,8 +641,13 @@ int __connman_agent_init(void) DBG(""); connection = connman_dbus_get_connection(); - if (connection == NULL) - return -1; + if (!connection) + return -EINVAL; + + agent_hash = g_hash_table_new_full(g_str_hash, g_str_equal, + NULL, agent_destroy); + if (!agent_hash) + return -ENOMEM; return 0; } @@ -468,13 +656,12 @@ void __connman_agent_cleanup(void) { DBG(""); - if (connection == NULL) + if (!connection) return; - if (agent_watch > 0) - g_dbus_remove_watch(connection, agent_watch); + g_hash_table_destroy(agent_hash); - release_all_agents(); + release_driver(); dbus_connection_unref(connection); connection = NULL; diff --git a/src/bridge.c b/src/bridge.c index e46cdda6..034fa139 100644 --- a/src/bridge.c +++ b/src/bridge.c @@ -2,8 +2,8 @@ * * Connection Manager * - * Copyright (C) 2007-2012 Intel Corporation. All rights reserved. - * Copyright (C) 2012 BMW Car IT GmbH. All rights reserved. + * Copyright (C) 2007-2013 Intel Corporation. All rights reserved. + * Copyright (C) 2012-2013 BMW Car IT GmbH. 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 @@ -46,14 +46,14 @@ static int set_forward_delay(const char *name, unsigned int delay) forward_delay_path = g_strdup_printf("/sys/class/net/%s/bridge/forward_delay", name); - if (forward_delay_path == NULL) + if (!forward_delay_path) return -ENOMEM; f = fopen(forward_delay_path, "r+"); g_free(forward_delay_path); - if (f == NULL) + if (!f) return -errno; fprintf(f, "%d", delay); @@ -111,8 +111,8 @@ int __connman_bridge_remove(const char *name) return 0; } -int __connman_bridge_enable(const char *name, const char *gateway, - const char *broadcast) +int __connman_bridge_enable(const char *name, const char *ip_address, + int prefix_len, const char *broadcast) { int err, index; @@ -121,8 +121,8 @@ int __connman_bridge_enable(const char *name, const char *gateway, return index; err = __connman_inet_modify_address(RTM_NEWADDR, - NLM_F_REPLACE | NLM_F_ACK, index, AF_INET, - gateway, NULL, 24, broadcast); + NLM_F_REPLACE | NLM_F_ACK, index, AF_INET, + ip_address, NULL, prefix_len, broadcast); if (err < 0) return err; diff --git a/src/clock.c b/src/clock.c index 2ce61d9e..0fde2c34 100644 --- a/src/clock.c +++ b/src/clock.c @@ -2,7 +2,7 @@ * * Connection Manager * - * Copyright (C) 2007-2012 Intel Corporation. All rights reserved. + * Copyright (C) 2007-2013 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 @@ -96,7 +96,7 @@ static void clock_properties_load(void) enum timezone_updates timezone_value; keyfile = __connman_storage_load_global(); - if (keyfile == NULL) + if (!keyfile) return; str = g_key_file_get_string(keyfile, "global", "TimeUpdates", NULL); @@ -125,17 +125,17 @@ static void clock_properties_save(void) const char *str; keyfile = __connman_storage_load_global(); - if (keyfile == NULL) + if (!keyfile) keyfile = g_key_file_new(); str = time_updates2string(time_updates_config); - if (str != NULL) + if (str) g_key_file_set_string(keyfile, "global", "TimeUpdates", str); else g_key_file_remove_key(keyfile, "global", "TimeUpdates", NULL); str = timezone_updates2string(timezone_updates_config); - if (str != NULL) + if (str) g_key_file_set_string(keyfile, "global", "TimezoneUpdates", str); else @@ -157,10 +157,10 @@ static void append_timeservers(DBusMessageIter *iter, void *user_data) int i; char **timeservers = __connman_timeserver_system_get(); - if (timeservers == NULL) + if (!timeservers) return; - for (i = 0; timeservers[i] != NULL; i++) { + for (i = 0; timeservers[i]; i++) { dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, ×ervers[i]); } @@ -179,7 +179,7 @@ static DBusMessage *get_properties(DBusConnection *conn, DBG("conn %p", conn); reply = dbus_message_new_method_return(msg); - if (reply == NULL) + if (!reply) return NULL; dbus_message_iter_init_append(reply, &array); @@ -194,16 +194,16 @@ static DBusMessage *get_properties(DBusConnection *conn, } str = time_updates2string(time_updates_config); - if (str != NULL) + if (str) connman_dbus_dict_append_basic(&dict, "TimeUpdates", DBUS_TYPE_STRING, &str); - if (timezone_config != NULL) + if (timezone_config) connman_dbus_dict_append_basic(&dict, "Timezone", DBUS_TYPE_STRING, &timezone_config); str = timezone_updates2string(timezone_updates_config); - if (str != NULL) + if (str) connman_dbus_dict_append_basic(&dict, "TimezoneUpdates", DBUS_TYPE_STRING, &str); @@ -224,7 +224,7 @@ static DBusMessage *set_property(DBusConnection *conn, DBG("conn %p", conn); - if (dbus_message_iter_init(msg, &iter) == FALSE) + if (!dbus_message_iter_init(msg, &iter)) return __connman_error_invalid_arguments(msg); if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING) @@ -240,7 +240,7 @@ static DBusMessage *set_property(DBusConnection *conn, type = dbus_message_iter_get_arg_type(&value); - if (g_str_equal(name, "Time") == TRUE) { + if (g_str_equal(name, "Time")) { struct timeval tv; dbus_uint64_t newval; @@ -261,7 +261,7 @@ static DBusMessage *set_property(DBusConnection *conn, connman_dbus_property_changed_basic(CONNMAN_MANAGER_PATH, CONNMAN_CLOCK_INTERFACE, "Time", DBUS_TYPE_UINT64, &newval); - } else if (g_str_equal(name, "TimeUpdates") == TRUE) { + } else if (g_str_equal(name, "TimeUpdates")) { const char *strval; enum time_updates newval; @@ -283,7 +283,7 @@ static DBusMessage *set_property(DBusConnection *conn, connman_dbus_property_changed_basic(CONNMAN_MANAGER_PATH, CONNMAN_CLOCK_INTERFACE, "TimeUpdates", DBUS_TYPE_STRING, &strval); - } else if (g_str_equal(name, "Timezone") == TRUE) { + } else if (g_str_equal(name, "Timezone")) { const char *strval; if (type != DBUS_TYPE_STRING) @@ -295,8 +295,8 @@ static DBusMessage *set_property(DBusConnection *conn, dbus_message_iter_get_basic(&value, &strval); if (__connman_timezone_change(strval) < 0) - return __connman_error_invalid_arguments(msg); - } else if (g_str_equal(name, "TimezoneUpdates") == TRUE) { + return __connman_error_invalid_arguments(msg); + } else if (g_str_equal(name, "TimezoneUpdates")) { const char *strval; enum timezone_updates newval; @@ -318,7 +318,7 @@ static DBusMessage *set_property(DBusConnection *conn, connman_dbus_property_changed_basic(CONNMAN_MANAGER_PATH, CONNMAN_CLOCK_INTERFACE, "TimezoneUpdates", DBUS_TYPE_STRING, &strval); - } else if (g_str_equal(name, "Timeservers") == TRUE) { + } else if (g_str_equal(name, "Timeservers")) { DBusMessageIter entry; char **str = NULL; GSList *list = NULL; @@ -344,10 +344,10 @@ static DBusMessage *set_property(DBusConnection *conn, dbus_message_iter_next(&entry); } - if (list != NULL) { + if (list) { str = g_new0(char *, count+1); - while (list != NULL) { + while (list) { count--; str[count] = list->data; list = g_slist_delete_link(list, list); @@ -356,7 +356,7 @@ static DBusMessage *set_property(DBusConnection *conn, __connman_timeserver_system_set(str); - if (str != NULL) + if (str) g_strfreev(str); connman_dbus_property_changed_array(CONNMAN_MANAGER_PATH, @@ -393,7 +393,7 @@ void __connman_clock_update_timezone(void) g_free(timezone_config); timezone_config = __connman_timezone_lookup(); - if (timezone_config == NULL) + if (!timezone_config) return; connman_dbus_property_changed_basic(CONNMAN_MANAGER_PATH, @@ -406,7 +406,7 @@ int __connman_clock_init(void) DBG(""); connection = connman_dbus_get_connection(); - if (connection == NULL) + if (!connection) return -1; __connman_timezone_init(); @@ -426,7 +426,7 @@ void __connman_clock_cleanup(void) { DBG(""); - if (connection == NULL) + if (!connection) return; g_dbus_unregister_interface(connection, CONNMAN_MANAGER_PATH, diff --git a/src/config.c b/src/config.c index e5c9c7ec..330ae817 100644 --- a/src/config.c +++ b/src/config.c @@ -2,7 +2,7 @@ * * Connection Manager * - * Copyright (C) 2007-2012 Intel Corporation. All rights reserved. + * Copyright (C) 2007-2013 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 @@ -55,8 +55,8 @@ struct connman_config_service { GSList *service_identifiers; char *config_ident; /* file prefix */ char *config_entry; /* entry name */ - connman_bool_t hidden; - connman_bool_t virtual; + bool hidden; + bool virtual; char *virtual_file; char *ipv4_address; char *ipv4_netmask; @@ -81,7 +81,7 @@ struct connman_config { static GHashTable *config_table = NULL; -static connman_bool_t cleanup = FALSE; +static bool cleanup = false; /* Definition of possible strings in the .config files */ #define CONFIG_KEY_NAME "Name" @@ -162,38 +162,40 @@ static void unregister_service(gpointer data) char *service_id; GSList *list; - if (cleanup == TRUE) + if (cleanup) goto free_only; connman_info("Removing service configuration %s", config_service->ident); - if (config_service->virtual == TRUE) + if (config_service->virtual) goto free_only; - for (list = config_service->service_identifiers; list != NULL; + for (list = config_service->service_identifiers; list; list = list->next) { service_id = list->data; service = __connman_service_lookup_from_ident(service_id); - if (service != NULL) { - __connman_service_set_immutable(service, FALSE); + if (service) { + __connman_service_set_immutable(service, false); __connman_service_set_config(service, NULL, NULL); __connman_service_remove(service); /* - * Ethernet service cannot be removed by + * Ethernet or gadget service cannot be removed by * __connman_service_remove() so reset the ipconfig * here. */ if (connman_service_get_type(service) == - CONNMAN_SERVICE_TYPE_ETHERNET) { + CONNMAN_SERVICE_TYPE_ETHERNET || + connman_service_get_type(service) == + CONNMAN_SERVICE_TYPE_GADGET) { __connman_service_disconnect(service); __connman_service_reset_ipconfig(service, CONNMAN_IPCONFIG_TYPE_IPV4, NULL, NULL); __connman_service_reset_ipconfig(service, CONNMAN_IPCONFIG_TYPE_IPV6, NULL, NULL); - __connman_service_set_ignore(service, TRUE); + __connman_service_set_ignore(service, true); /* * After these operations, user needs to @@ -203,7 +205,7 @@ static void unregister_service(gpointer data) } } - if (__connman_storage_remove_service(service_id) == FALSE) + if (!__connman_storage_remove_service(service_id)) DBG("Could not remove all files for service %s", service_id); } @@ -247,7 +249,7 @@ static void check_keys(GKeyFile *keyfile, const char *group, gsize nb_avail_keys, i, j; avail_keys = g_key_file_get_keys(keyfile, group, &nb_avail_keys, NULL); - if (avail_keys == NULL) + if (!avail_keys) return; /* @@ -259,7 +261,7 @@ static void check_keys(GKeyFile *keyfile, const char *group, if (g_strcmp0(avail_keys[i], possible_keys[j]) == 0) break; - if (possible_keys[j] == NULL) + if (!possible_keys[j]) connman_warn("Unknown configuration key %s in [%s]", avail_keys[i], group); } @@ -313,11 +315,11 @@ static int parse_address(const char *address_str, int address_family, char **route; route = g_strsplit(address_str, "/", 0); - if (route == NULL) + if (!route) return -EINVAL; addr_str = route[0]; - if (addr_str == NULL || addr_str[0] == '\0') { + if (!addr_str || addr_str[0] == '\0') { err = -EINVAL; goto out; } @@ -326,20 +328,17 @@ static int parse_address(const char *address_str, int address_family, goto out; mask_str = route[1]; - if (mask_str == NULL || mask_str[0] == '\0') { + if (!mask_str || mask_str[0] == '\0') { err = -EINVAL; goto out; } gw_str = route[2]; - if (gw_str == NULL || gw_str[0] == '\0') { - err = -EINVAL; - goto out; + if (gw_str && gw_str[0]) { + if ((err = check_family(gw_str, address_family)) < 0) + goto out; } - if ((err = check_family(gw_str, address_family)) < 0) - goto out; - g_free(*address); *address = g_strdup(addr_str); @@ -349,7 +348,10 @@ static int parse_address(const char *address_str, int address_family, g_free(*gateway); *gateway = g_strdup(gw_str); - DBG("address %s/%s via %s", *address, *netmask, *gateway); + if (*gateway) + DBG("address %s/%s via %s", *address, *netmask, *gateway); + else + DBG("address %s/%s", *address, *netmask); out: g_strfreev(route); @@ -357,19 +359,19 @@ out: return err; } -static connman_bool_t check_address(char *address_str, char **address) +static bool check_address(char *address_str, char **address) { if (g_ascii_strcasecmp(address_str, "auto") == 0 || g_ascii_strcasecmp(address_str, "dhcp") == 0 || g_ascii_strcasecmp(address_str, "off") == 0) { *address = address_str; - return FALSE; + return false; } - return TRUE; + return true; } -static connman_bool_t load_service_generic(GKeyFile *keyfile, +static bool load_service_generic(GKeyFile *keyfile, const char *group, struct connman_config *config, struct connman_config_service *service) { @@ -377,8 +379,8 @@ static connman_bool_t load_service_generic(GKeyFile *keyfile, char **strlist; gsize length; - str = g_key_file_get_string(keyfile, group, SERVICE_KEY_IPv4, NULL); - if (str != NULL && check_address(str, &service->ipv4_address) == TRUE) { + str = __connman_config_get_string(keyfile, group, SERVICE_KEY_IPv4, NULL); + if (str && check_address(str, &service->ipv4_address)) { mask = NULL; if (parse_address(str, AF_INET, &service->ipv4_address, @@ -389,7 +391,7 @@ static connman_bool_t load_service_generic(GKeyFile *keyfile, goto err; } - if (g_strrstr(mask, ".") == NULL) { + if (!g_strrstr(mask, ".")) { /* We have netmask length */ in_addr_t addr; struct in_addr netmask_in; @@ -412,8 +414,8 @@ static connman_bool_t load_service_generic(GKeyFile *keyfile, g_free(str); } - str = g_key_file_get_string(keyfile, group, SERVICE_KEY_IPv6, NULL); - if (str != NULL && check_address(str, &service->ipv6_address) == TRUE) { + str = __connman_config_get_string(keyfile, group, SERVICE_KEY_IPv6, NULL); + if (str && check_address(str, &service->ipv6_address)) { long int value; char *ptr; @@ -437,29 +439,29 @@ static connman_bool_t load_service_generic(GKeyFile *keyfile, g_free(str); } - str = g_key_file_get_string(keyfile, group, SERVICE_KEY_IPv6_PRIVACY, + str = __connman_config_get_string(keyfile, group, SERVICE_KEY_IPv6_PRIVACY, NULL); - if (str != NULL) { + if (str) { g_free(service->ipv6_privacy); service->ipv6_privacy = str; } - str = g_key_file_get_string(keyfile, group, SERVICE_KEY_MAC, NULL); - if (str != NULL) { + str = __connman_config_get_string(keyfile, group, SERVICE_KEY_MAC, NULL); + if (str) { g_free(service->mac); service->mac = str; } - str = g_key_file_get_string(keyfile, group, SERVICE_KEY_DOMAIN, NULL); - if (str != NULL) { + str = __connman_config_get_string(keyfile, group, SERVICE_KEY_DOMAIN, NULL); + if (str) { g_free(service->domain_name); service->domain_name = str; } - strlist = g_key_file_get_string_list(keyfile, group, + strlist = __connman_config_get_string_list(keyfile, group, SERVICE_KEY_NAMESERVERS, &length, NULL); - if (strlist != NULL) { + if (strlist) { if (length != 0) { g_strfreev(service->nameservers); service->nameservers = strlist; @@ -467,10 +469,10 @@ static connman_bool_t load_service_generic(GKeyFile *keyfile, g_strfreev(strlist); } - strlist = g_key_file_get_string_list(keyfile, group, + strlist = __connman_config_get_string_list(keyfile, group, SERVICE_KEY_SEARCH_DOMAINS, &length, NULL); - if (strlist != NULL) { + if (strlist) { if (length != 0) { g_strfreev(service->search_domains); service->search_domains = strlist; @@ -478,10 +480,10 @@ static connman_bool_t load_service_generic(GKeyFile *keyfile, g_strfreev(strlist); } - strlist = g_key_file_get_string_list(keyfile, group, + strlist = __connman_config_get_string_list(keyfile, group, SERVICE_KEY_TIMESERVERS, &length, NULL); - if (strlist != NULL) { + if (strlist) { if (length != 0) { g_strfreev(service->timeservers); service->timeservers = strlist; @@ -489,7 +491,7 @@ static connman_bool_t load_service_generic(GKeyFile *keyfile, g_strfreev(strlist); } - return TRUE; + return true; err: g_free(service->ident); @@ -502,39 +504,39 @@ err: g_free(service->mac); g_free(service); - return FALSE; + return false; } -static connman_bool_t load_service(GKeyFile *keyfile, const char *group, +static bool load_service(GKeyFile *keyfile, const char *group, struct connman_config *config) { struct connman_config_service *service; const char *ident; char *str, *hex_ssid; - gboolean service_created = FALSE; + bool service_created = false; /* Strip off "service_" prefix */ ident = group + 8; if (strlen(ident) < 1) - return FALSE; + return false; /* Verify that provided keys are good */ check_keys(keyfile, group, service_possible_keys); service = g_hash_table_lookup(config->service_table, ident); - if (service == NULL) { + if (!service) { service = g_try_new0(struct connman_config_service, 1); - if (service == NULL) - return FALSE; + if (!service) + return false; service->ident = g_strdup(ident); - service_created = TRUE; + service_created = true; } - str = g_key_file_get_string(keyfile, group, SERVICE_KEY_TYPE, NULL); - if (str != NULL) { + str = __connman_config_get_string(keyfile, group, SERVICE_KEY_TYPE, NULL); + if (str) { g_free(service->type); service->type = str; } else { @@ -543,8 +545,8 @@ static connman_bool_t load_service(GKeyFile *keyfile, const char *group, goto err; } - if (load_service_generic(keyfile, group, config, service) == FALSE) - return FALSE; + if (!load_service_generic(keyfile, group, config, service)) + return false; if (g_strcmp0(str, "ethernet") == 0) { service->config_ident = g_strdup(config->ident); @@ -553,24 +555,24 @@ static connman_bool_t load_service(GKeyFile *keyfile, const char *group, g_hash_table_insert(config->service_table, service->ident, service); - return 0; + return true; } - str = g_key_file_get_string(keyfile, group, SERVICE_KEY_NAME, NULL); - if (str != NULL) { + str = __connman_config_get_string(keyfile, group, SERVICE_KEY_NAME, NULL); + if (str) { g_free(service->name); service->name = str; } - hex_ssid = g_key_file_get_string(keyfile, group, SERVICE_KEY_SSID, + hex_ssid = __connman_config_get_string(keyfile, group, SERVICE_KEY_SSID, NULL); - if (hex_ssid != NULL) { + if (hex_ssid) { char *ssid; unsigned int i, j = 0, hex; size_t hex_ssid_len = strlen(hex_ssid); ssid = g_try_malloc0(hex_ssid_len / 2); - if (ssid == NULL) { + if (!ssid) { g_free(hex_ssid); goto err; } @@ -590,13 +592,13 @@ static connman_bool_t load_service(GKeyFile *keyfile, const char *group, g_free(service->ssid); service->ssid = ssid; service->ssid_len = hex_ssid_len / 2; - } else if (service->name != NULL) { + } else if (service->name) { char *ssid; unsigned int ssid_len; ssid_len = strlen(service->name); ssid = g_try_malloc0(ssid_len); - if (ssid == NULL) + if (!ssid) goto err; memcpy(ssid, service->name, ssid_len); @@ -605,59 +607,59 @@ static connman_bool_t load_service(GKeyFile *keyfile, const char *group, service->ssid_len = ssid_len; } - str = g_key_file_get_string(keyfile, group, SERVICE_KEY_EAP, NULL); - if (str != NULL) { + str = __connman_config_get_string(keyfile, group, SERVICE_KEY_EAP, NULL); + if (str) { g_free(service->eap); service->eap = str; } - str = g_key_file_get_string(keyfile, group, SERVICE_KEY_CA_CERT, NULL); - if (str != NULL) { + str = __connman_config_get_string(keyfile, group, SERVICE_KEY_CA_CERT, NULL); + if (str) { g_free(service->ca_cert_file); service->ca_cert_file = str; } - str = g_key_file_get_string(keyfile, group, SERVICE_KEY_CL_CERT, NULL); - if (str != NULL) { + str = __connman_config_get_string(keyfile, group, SERVICE_KEY_CL_CERT, NULL); + if (str) { g_free(service->client_cert_file); service->client_cert_file = str; } - str = g_key_file_get_string(keyfile, group, SERVICE_KEY_PRV_KEY, NULL); - if (str != NULL) { + str = __connman_config_get_string(keyfile, group, SERVICE_KEY_PRV_KEY, NULL); + if (str) { g_free(service->private_key_file); service->private_key_file = str; } - str = g_key_file_get_string(keyfile, group, + str = __connman_config_get_string(keyfile, group, SERVICE_KEY_PRV_KEY_PASS, NULL); - if (str != NULL) { + if (str) { g_free(service->private_key_passphrase); service->private_key_passphrase = str; } - str = g_key_file_get_string(keyfile, group, + str = __connman_config_get_string(keyfile, group, SERVICE_KEY_PRV_KEY_PASS_TYPE, NULL); - if (str != NULL) { + if (str) { g_free(service->private_key_passphrase_type); service->private_key_passphrase_type = str; } - str = g_key_file_get_string(keyfile, group, SERVICE_KEY_IDENTITY, NULL); - if (str != NULL) { + str = __connman_config_get_string(keyfile, group, SERVICE_KEY_IDENTITY, NULL); + if (str) { g_free(service->identity); service->identity = str; } - str = g_key_file_get_string(keyfile, group, SERVICE_KEY_PHASE2, NULL); - if (str != NULL) { + str = __connman_config_get_string(keyfile, group, SERVICE_KEY_PHASE2, NULL); + if (str) { g_free(service->phase2); service->phase2 = str; } - str = g_key_file_get_string(keyfile, group, SERVICE_KEY_PASSPHRASE, + str = __connman_config_get_string(keyfile, group, SERVICE_KEY_PASSPHRASE, NULL); - if (str != NULL) { + if (str) { g_free(service->passphrase); service->passphrase = str; } @@ -665,7 +667,7 @@ static connman_bool_t load_service(GKeyFile *keyfile, const char *group, service->config_ident = g_strdup(config->ident); service->config_entry = g_strdup_printf("service_%s", service->ident); - service->hidden = g_key_file_get_boolean(keyfile, group, + service->hidden = __connman_config_get_bool(keyfile, group, SERVICE_KEY_HIDDEN, NULL); if (service_created) @@ -674,10 +676,10 @@ static connman_bool_t load_service(GKeyFile *keyfile, const char *group, connman_info("Adding service configuration %s", service->ident); - return TRUE; + return true; err: - if (service_created == TRUE) { + if (service_created) { g_free(service->ident); g_free(service->type); g_free(service->name); @@ -685,23 +687,23 @@ err: g_free(service); } - return FALSE; + return false; } -static connman_bool_t load_service_from_keyfile(GKeyFile *keyfile, +static bool load_service_from_keyfile(GKeyFile *keyfile, struct connman_config *config) { - connman_bool_t found = FALSE; + bool found = false; char **groups; int i; groups = g_key_file_get_groups(keyfile, NULL); - for (i = 0; groups[i] != NULL; i++) { - if (g_str_has_prefix(groups[i], "service_") == FALSE) + for (i = 0; groups[i]; i++) { + if (!g_str_has_prefix(groups[i], "service_")) continue; - if (load_service(keyfile, groups[i], config) == TRUE) - found = TRUE; + if (load_service(keyfile, groups[i], config)) + found = true; } g_strfreev(groups); @@ -717,25 +719,27 @@ static int load_config(struct connman_config *config) DBG("config %p", config); keyfile = __connman_storage_load_config(config->ident); - if (keyfile == NULL) + if (!keyfile) return -EIO; + g_key_file_set_list_separator(keyfile, ','); + /* Verify keys validity of the global section */ check_keys(keyfile, "global", config_possible_keys); - str = g_key_file_get_string(keyfile, "global", CONFIG_KEY_NAME, NULL); - if (str != NULL) { + str = __connman_config_get_string(keyfile, "global", CONFIG_KEY_NAME, NULL); + if (str) { g_free(config->name); config->name = str; } - str = g_key_file_get_string(keyfile, "global", CONFIG_KEY_DESC, NULL); - if (str != NULL) { + str = __connman_config_get_string(keyfile, "global", CONFIG_KEY_DESC, NULL); + if (str) { g_free(config->description); config->description = str; } - if (load_service_from_keyfile(keyfile, config) == FALSE) + if (!load_service_from_keyfile(keyfile, config)) connman_warn("Config file %s/%s.config does not contain any " "configuration that can be provisioned!", STORAGEDIR, config->ident); @@ -751,11 +755,11 @@ static struct connman_config *create_config(const char *ident) DBG("ident %s", ident); - if (g_hash_table_lookup(config_table, ident) != NULL) + if (g_hash_table_lookup(config_table, ident)) return NULL; config = g_try_new0(struct connman_config, 1); - if (config == NULL) + if (!config) return NULL; config->ident = g_strdup(ident); @@ -770,18 +774,18 @@ static struct connman_config *create_config(const char *ident) return config; } -static connman_bool_t validate_ident(const char *ident) +static bool validate_ident(const char *ident) { unsigned int i; - if (ident == NULL) - return FALSE; + if (!ident) + return false; for (i = 0; i < strlen(ident); i++) - if (g_ascii_isprint(ident[i]) == FALSE) - return FALSE; + if (!g_ascii_isprint(ident[i])) + return false; - return TRUE; + return true; } static int read_configs(void) @@ -791,31 +795,31 @@ static int read_configs(void) DBG(""); dir = g_dir_open(STORAGEDIR, 0, NULL); - if (dir != NULL) { + if (dir) { const gchar *file; - while ((file = g_dir_read_name(dir)) != NULL) { + while ((file = g_dir_read_name(dir))) { GString *str; gchar *ident; - if (g_str_has_suffix(file, ".config") == FALSE) + if (!g_str_has_suffix(file, ".config")) continue; ident = g_strrstr(file, ".config"); - if (ident == NULL) + if (!ident) continue; str = g_string_new_len(file, ident - file); - if (str == NULL) + if (!str) continue; ident = g_string_free(str, FALSE); - if (validate_ident(ident) == TRUE) { + if (validate_ident(ident)) { struct connman_config *config; config = create_config(ident); - if (config != NULL) + if (config) load_config(config); } else { connman_error("Invalid config ident %s", ident); @@ -834,19 +838,19 @@ static void config_notify_handler(struct inotify_event *event, { char *ext; - if (ident == NULL) + if (!ident) return; - if (g_str_has_suffix(ident, ".config") == FALSE) + if (!g_str_has_suffix(ident, ".config")) return; ext = g_strrstr(ident, ".config"); - if (ext == NULL) + if (!ext) return; *ext = '\0'; - if (validate_ident(ident) == FALSE) { + if (!validate_ident(ident)) { connman_error("Invalid config ident %s", ident); return; } @@ -858,7 +862,7 @@ static void config_notify_handler(struct inotify_event *event, struct connman_config *config; config = g_hash_table_lookup(config_table, ident); - if (config != NULL) { + if (config) { int ret; g_hash_table_remove_all(config->service_table); @@ -896,14 +900,61 @@ void __connman_config_cleanup(void) { DBG(""); - cleanup = TRUE; + cleanup = true; connman_inotify_unregister(STORAGEDIR, config_notify_handler); g_hash_table_destroy(config_table); config_table = NULL; - cleanup = FALSE; + cleanup = false; +} + +char *__connman_config_get_string(GKeyFile *key_file, + const char *group_name, const char *key, GError **error) +{ + char *str = g_key_file_get_string(key_file, group_name, key, error); + if (!str) + return NULL; + + return g_strchomp(str); +} + +char **__connman_config_get_string_list(GKeyFile *key_file, + const char *group_name, const char *key, gsize *length, GError **error) +{ + char **p; + char **strlist = g_key_file_get_string_list(key_file, group_name, key, + length, error); + if (!strlist) + return NULL; + + p = strlist; + while (*p) { + *p = g_strstrip(*p); + p++; + } + + return strlist; +} + +bool __connman_config_get_bool(GKeyFile *key_file, + const char *group_name, const char *key, GError **error) +{ + char *valstr; + bool val = false; + + valstr = g_key_file_get_value(key_file, group_name, key, error); + if (!valstr) + return false; + + valstr = g_strchomp(valstr); + if (strcmp(valstr, "true") == 0 || strcmp(valstr, "1") == 0) + val = true; + + g_free(valstr); + + return val; } static char *config_pem_fsid(const char *pem_file) @@ -912,7 +963,7 @@ static char *config_pem_fsid(const char *pem_file) unsigned *fsid = (unsigned *) &buf.f_fsid; unsigned long long fsid64; - if (pem_file == NULL) + if (!pem_file) return NULL; if (statfs(pem_file, &buf) < 0) { @@ -926,44 +977,43 @@ static char *config_pem_fsid(const char *pem_file) return g_strdup_printf("%llx", fsid64); } -static void provision_service_wifi(gpointer key, - struct connman_config_service *config, +static void provision_service_wifi(struct connman_config_service *config, struct connman_service *service, struct connman_network *network, const void *ssid, unsigned int ssid_len) { - if (config->eap != NULL) + if (config->eap) __connman_service_set_string(service, "EAP", config->eap); - if (config->identity != NULL) + if (config->identity) __connman_service_set_string(service, "Identity", config->identity); - if (config->ca_cert_file != NULL) + if (config->ca_cert_file) __connman_service_set_string(service, "CACertFile", config->ca_cert_file); - if (config->client_cert_file != NULL) + if (config->client_cert_file) __connman_service_set_string(service, "ClientCertFile", config->client_cert_file); - if (config->private_key_file != NULL) + if (config->private_key_file) __connman_service_set_string(service, "PrivateKeyFile", config->private_key_file); if (g_strcmp0(config->private_key_passphrase_type, "fsid") == 0 && - config->private_key_file != NULL) { + config->private_key_file) { char *fsid; fsid = config_pem_fsid(config->private_key_file); - if (fsid == NULL) + if (!fsid) return; g_free(config->private_key_passphrase); config->private_key_passphrase = fsid; } - if (config->private_key_passphrase != NULL) { + if (config->private_key_passphrase) { __connman_service_set_string(service, "PrivateKeyPassphrase", config->private_key_passphrase); /* @@ -975,13 +1025,14 @@ static void provision_service_wifi(gpointer key, */ } - if (config->phase2 != NULL) + if (config->phase2) __connman_service_set_string(service, "Phase2", config->phase2); - if (config->passphrase != NULL) - __connman_service_set_string(service, "Passphrase", config->passphrase); + if (config->passphrase) + __connman_service_set_string(service, "Passphrase", + config->passphrase); - if (config->hidden == TRUE) + if (config->hidden) __connman_service_set_hidden(service); } @@ -994,7 +1045,8 @@ static gboolean remove_virtual_config(gpointer user_data) { struct connect_virtual *virtual = user_data; - __connman_service_connect(virtual->service); + __connman_service_connect(virtual->service, + CONNMAN_SERVICE_CONNECT_REASON_AUTO); g_hash_table_remove(config_table, virtual->vfile); g_free(virtual); @@ -1002,11 +1054,9 @@ static gboolean remove_virtual_config(gpointer user_data) return FALSE; } -static void provision_service(gpointer key, gpointer value, - gpointer user_data) +static int try_provision_service(struct connman_config_service *config, + struct connman_service *service) { - struct connman_service *service = user_data; - struct connman_config_service *config = value; struct connman_network *network; const void *service_id; enum connman_service_type type; @@ -1016,32 +1066,36 @@ static void provision_service(gpointer key, gpointer value, type = connman_service_get_type(service); if (type == CONNMAN_SERVICE_TYPE_WIFI && g_strcmp0(config->type, "wifi") != 0) - return; + return -ENOENT; if (type == CONNMAN_SERVICE_TYPE_ETHERNET && g_strcmp0(config->type, "ethernet") != 0) - return; + return -ENOENT; + + if (type == CONNMAN_SERVICE_TYPE_GADGET && + g_strcmp0(config->type, "gadget") != 0) + return -ENOENT; DBG("service %p ident %s", service, __connman_service_get_ident(service)); network = __connman_service_get_network(service); - if (network == NULL) { + if (!network) { connman_error("Service has no network set"); - return; + return -EINVAL; } DBG("network %p ident %s", network, connman_network_get_identifier(network)); - if (config->mac != NULL) { + if (config->mac) { struct connman_device *device; const char *device_addr; device = connman_network_get_device(network); - if (device == NULL) { + if (!device) { connman_error("Network device is missing"); - return; + return -ENODEV; } device_addr = connman_device_get_string(device, "Address"); @@ -1049,26 +1103,26 @@ static void provision_service(gpointer key, gpointer value, DBG("wants %s has %s", config->mac, device_addr); if (g_ascii_strcasecmp(device_addr, config->mac) != 0) - return; + return -ENOENT; } if (g_strcmp0(config->type, "wifi") == 0 && type == CONNMAN_SERVICE_TYPE_WIFI) { ssid = connman_network_get_blob(network, "WiFi.SSID", &ssid_len); - if (ssid == NULL) { + if (!ssid) { connman_error("Network SSID not set"); - return; + return -EINVAL; } - if (config->ssid == NULL || ssid_len != config->ssid_len) - return; + if (!config->ssid || ssid_len != config->ssid_len) + return -ENOENT; if (memcmp(config->ssid, ssid, ssid_len) != 0) - return; + return -ENOENT; } - if (config->ipv6_address == NULL) { + if (!config->ipv6_address) { connman_network_set_ipv6_method(network, CONNMAN_IPCONFIG_METHOD_AUTO); } else if (g_ascii_strcasecmp(config->ipv6_address, "off") == 0) { @@ -1081,15 +1135,14 @@ static void provision_service(gpointer key, gpointer value, } else { struct connman_ipaddress *address; - if (config->ipv6_prefix_length == 0 || - config->ipv6_gateway == NULL) { - DBG("IPv6 prefix or gateway missing"); - return; + if (config->ipv6_prefix_length == 0) { + DBG("IPv6 prefix missing"); + return -EINVAL; } address = connman_ipaddress_alloc(AF_INET6); - if (address == NULL) - return; + if (!address) + return -ENOENT; connman_ipaddress_set_ipv6(address, config->ipv6_address, config->ipv6_prefix_length, @@ -1105,16 +1158,16 @@ static void provision_service(gpointer key, gpointer value, connman_ipaddress_free(address); } - if (config->ipv6_privacy != NULL) { + if (config->ipv6_privacy) { struct connman_ipconfig *ipconfig; ipconfig = __connman_service_get_ip6config(service); - if (ipconfig != NULL) + if (ipconfig) __connman_ipconfig_ipv6_set_privacy(ipconfig, config->ipv6_privacy); } - if (config->ipv4_address == NULL) { + if (!config->ipv4_address) { connman_network_set_ipv4_method(network, CONNMAN_IPCONFIG_METHOD_DHCP); } else if (g_ascii_strcasecmp(config->ipv4_address, "off") == 0) { @@ -1127,15 +1180,14 @@ static void provision_service(gpointer key, gpointer value, } else { struct connman_ipaddress *address; - if (config->ipv4_netmask == 0 || - config->ipv4_gateway == NULL) { - DBG("IPv4 netmask or gateway missing"); - return; + if (!config->ipv4_netmask) { + DBG("IPv4 netmask missing"); + return -EINVAL; } address = connman_ipaddress_alloc(AF_INET); - if (address == NULL) - return; + if (!address) + return -ENOENT; connman_ipaddress_set_ipv4(address, config->ipv4_address, config->ipv4_netmask, @@ -1158,48 +1210,49 @@ static void provision_service(gpointer key, gpointer value, g_slist_prepend(config->service_identifiers, g_strdup(service_id)); - if (config->virtual == FALSE) - __connman_service_set_immutable(service, TRUE); + if (!config->virtual) + __connman_service_set_immutable(service, true); - __connman_service_set_favorite_delayed(service, TRUE, TRUE); + __connman_service_set_favorite_delayed(service, true, true); __connman_service_set_config(service, config->config_ident, config->config_entry); - if (config->domain_name != NULL) + if (config->domain_name) __connman_service_set_domainname(service, config->domain_name); - if (config->nameservers != NULL) { + if (config->nameservers) { int i; __connman_service_nameserver_clear(service); - for (i = 0; config->nameservers[i] != NULL; i++) { + for (i = 0; config->nameservers[i]; i++) { __connman_service_nameserver_append(service, - config->nameservers[i], FALSE); + config->nameservers[i], false); } } - if (config->search_domains != NULL) + if (config->search_domains) __connman_service_set_search_domains(service, config->search_domains); - if (config->timeservers != NULL) + if (config->timeservers) __connman_service_set_timeservers(service, config->timeservers); if (g_strcmp0(config->type, "wifi") == 0 && type == CONNMAN_SERVICE_TYPE_WIFI) { - provision_service_wifi(key, config, service, network, + provision_service_wifi(config, service, network, ssid, ssid_len); } else - __connman_service_connect(service); + __connman_service_connect(service, + CONNMAN_SERVICE_CONNECT_REASON_AUTO); __connman_service_mark_dirty(); - __connman_service_save(service); + __connman_service_load_modifiable(service); - if (config->virtual == TRUE) { + if (config->virtual) { struct connect_virtual *virtual; virtual = g_malloc0(sizeof(struct connect_virtual)); @@ -1208,34 +1261,47 @@ static void provision_service(gpointer key, gpointer value, g_timeout_add(0, remove_virtual_config, virtual); } else - __connman_service_auto_connect(); + __connman_service_auto_connect(CONNMAN_SERVICE_CONNECT_REASON_AUTO); + + return 0; +} + +static int find_and_provision_service(struct connman_service *service) +{ + GHashTableIter iter, iter_service; + gpointer value, key, value_service, key_service; + + g_hash_table_iter_init(&iter, config_table); + + while (g_hash_table_iter_next(&iter, &key, &value)) { + struct connman_config *config = value; + + g_hash_table_iter_init(&iter_service, config->service_table); + while (g_hash_table_iter_next(&iter_service, &key_service, + &value_service)) { + if (!try_provision_service(value_service, service)) + return 0; + } + } + + return -ENOENT; } int __connman_config_provision_service(struct connman_service *service) { enum connman_service_type type; - GHashTableIter iter; - gpointer value, key; - /* For now only WiFi and Ethernet services are supported */ + /* For now only WiFi, Gadget and Ethernet services are supported */ type = connman_service_get_type(service); DBG("service %p type %d", service, type); if (type != CONNMAN_SERVICE_TYPE_WIFI && - type != CONNMAN_SERVICE_TYPE_ETHERNET) + type != CONNMAN_SERVICE_TYPE_ETHERNET && + type != CONNMAN_SERVICE_TYPE_GADGET) return -ENOSYS; - g_hash_table_iter_init(&iter, config_table); - - while (g_hash_table_iter_next(&iter, &key, &value) == TRUE) { - struct connman_config *config = value; - - g_hash_table_foreach(config->service_table, - provision_service, service); - } - - return 0; + return find_and_provision_service(service); } int __connman_config_provision_service_ident(struct connman_service *service, @@ -1245,20 +1311,21 @@ int __connman_config_provision_service_ident(struct connman_service *service, struct connman_config *config; int ret = 0; - /* For now only WiFi and Ethernet services are supported */ + /* For now only WiFi, Gadget and Ethernet services are supported */ type = connman_service_get_type(service); DBG("service %p type %d", service, type); if (type != CONNMAN_SERVICE_TYPE_WIFI && - type != CONNMAN_SERVICE_TYPE_ETHERNET) + type != CONNMAN_SERVICE_TYPE_ETHERNET && + type != CONNMAN_SERVICE_TYPE_GADGET) return -ENOSYS; config = g_hash_table_lookup(config_table, ident); - if (config != NULL) { + if (config) { GHashTableIter iter; gpointer value, key; - gboolean found = FALSE; + bool found = false; g_hash_table_iter_init(&iter, config->service_table); @@ -1266,9 +1333,9 @@ int __connman_config_provision_service_ident(struct connman_service *service, * Check if we need to remove individual service if it * is missing from config file. */ - if (file != NULL && entry != NULL) { + if (file && entry) { while (g_hash_table_iter_next(&iter, &key, - &value) == TRUE) { + &value)) { struct connman_config_service *config_service; config_service = value; @@ -1281,14 +1348,14 @@ int __connman_config_provision_service_ident(struct connman_service *service, entry) != 0) continue; - found = TRUE; + found = true; break; } DBG("found %d ident %s file %s entry %s", found, ident, file, entry); - if (found == FALSE) { + if (!found) { /* * The entry+8 will skip "service_" prefix */ @@ -1298,8 +1365,7 @@ int __connman_config_provision_service_ident(struct connman_service *service, } } - g_hash_table_foreach(config->service_table, - provision_service, service); + find_and_provision_service(service); } return ret; @@ -1337,16 +1403,16 @@ int connman_config_provision_mutable_service(GKeyFile *keyfile) vfile = g_strdup_printf("service_mutable_%s.config", rstr); config = create_config(vfile); - if (config == NULL) + if (!config) return -ENOMEM; - if (load_service_from_keyfile(keyfile, config) == FALSE) + if (!load_service_from_keyfile(keyfile, config)) goto error; group = g_key_file_get_start_group(keyfile); service_config = g_hash_table_lookup(config->service_table, group+8); - if (service_config == NULL) + if (!service_config) goto error; /* Specific to non file based config: */ @@ -1355,7 +1421,7 @@ int connman_config_provision_mutable_service(GKeyFile *keyfile) g_free(service_config->config_entry); service_config->config_entry = NULL; - service_config->virtual = TRUE; + service_config->virtual = true; service_config->virtual_file = vfile; __connman_service_provision_changed(vfile); @@ -1381,35 +1447,35 @@ struct connman_config_entry **connman_config_get_entries(const char *type) int i = 0, count; g_hash_table_iter_init(&iter_file, config_table); - while (g_hash_table_iter_next(&iter_file, &key, &value) == TRUE) { + while (g_hash_table_iter_next(&iter_file, &key, &value)) { struct connman_config *config_file = value; count = g_hash_table_size(config_file->service_table); entries = g_try_realloc(entries, (i + count + 1) * sizeof(struct connman_config_entry *)); - if (entries == NULL) + if (!entries) return NULL; g_hash_table_iter_init(&iter_config, config_file->service_table); while (g_hash_table_iter_next(&iter_config, &key, - &value) == TRUE) { + &value)) { struct connman_config_service *config = value; - if (type != NULL && + if (type && g_strcmp0(config->type, type) != 0) continue; entries[i] = g_try_new0(struct connman_config_entry, 1); - if (entries[i] == NULL) + if (!entries[i]) goto cleanup; entries[i]->ident = g_strdup(config->ident); entries[i]->name = g_strdup(config->name); entries[i]->ssid = g_try_malloc0(config->ssid_len + 1); - if (entries[i]->ssid == NULL) + if (!entries[i]->ssid) goto cleanup; memcpy(entries[i]->ssid, config->ssid, @@ -1421,10 +1487,10 @@ struct connman_config_entry **connman_config_get_entries(const char *type) } } - if (entries != NULL) { + if (entries) { entries = g_try_realloc(entries, (i + 1) * sizeof(struct connman_config_entry *)); - if (entries == NULL) + if (!entries) return NULL; entries[i] = NULL; @@ -1443,7 +1509,7 @@ void connman_config_free_entries(struct connman_config_entry **entries) { int i; - if (entries == NULL) + if (!entries) return; for (i = 0; entries[i]; i++) { @@ -1456,3 +1522,31 @@ void connman_config_free_entries(struct connman_config_entry **entries) g_free(entries); return; } + +bool __connman_config_address_provisioned(const char *address, + const char *netmask) +{ + GHashTableIter iter, siter; + gpointer value, key, svalue, skey; + + if (!address || !netmask) + return false; + + g_hash_table_iter_init(&iter, config_table); + + while (g_hash_table_iter_next(&iter, &key, &value)) { + struct connman_config *config = value; + + g_hash_table_iter_init(&siter, config->service_table); + while (g_hash_table_iter_next(&siter, &skey, &svalue)) { + struct connman_config_service *service = svalue; + + if (!g_strcmp0(address, service->ipv4_address) && + !g_strcmp0(netmask, + service->ipv4_netmask)) + return true; + } + } + + return false; +} diff --git a/src/connection.c b/src/connection.c index c7b1f620..e98ccb5c 100644 --- a/src/connection.c +++ b/src/connection.c @@ -2,8 +2,8 @@ * * Connection Manager * - * Copyright (C) 2007-2012 Intel Corporation. All rights reserved. - * Copyright (C) 2011 BMW Car IT GmbH. All rights reserved. + * Copyright (C) 2007-2013 Intel Corporation. All rights reserved. + * Copyright (C) 2011-2013 BMW Car IT GmbH. 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 @@ -33,11 +33,11 @@ #include "connman.h" struct gateway_config { - gboolean active; + bool active; char *gateway; /* VPN extra data */ - gboolean vpn; + bool vpn; char *vpn_ip; int vpn_phy_index; char *vpn_phy_ip; @@ -49,7 +49,7 @@ struct gateway_data { unsigned int order; struct gateway_config *ipv4_gateway; struct gateway_config *ipv6_gateway; - connman_bool_t default_checked; + bool default_checked; }; static GHashTable *gateway_hash = NULL; @@ -59,22 +59,22 @@ static struct gateway_config *find_gateway(int index, const char *gateway) GHashTableIter iter; gpointer value, key; - if (gateway == NULL) + if (!gateway) return NULL; g_hash_table_iter_init(&iter, gateway_hash); - while (g_hash_table_iter_next(&iter, &key, &value) == TRUE) { + while (g_hash_table_iter_next(&iter, &key, &value)) { struct gateway_data *data = value; - if (data->ipv4_gateway != NULL && data->index == index && + if (data->ipv4_gateway && data->index == index && g_str_equal(data->ipv4_gateway->gateway, - gateway) == TRUE) + gateway)) return data->ipv4_gateway; - if (data->ipv6_gateway != NULL && data->index == index && + if (data->ipv6_gateway && data->index == index && g_str_equal(data->ipv6_gateway->gateway, - gateway) == TRUE) + gateway)) return data->ipv6_gateway; } @@ -86,19 +86,19 @@ static struct gateway_data *lookup_gateway_data(struct gateway_config *config) GHashTableIter iter; gpointer value, key; - if (config == NULL) + if (!config) return NULL; g_hash_table_iter_init(&iter, gateway_hash); - while (g_hash_table_iter_next(&iter, &key, &value) == TRUE) { + while (g_hash_table_iter_next(&iter, &key, &value)) { struct gateway_data *data = value; - if (data->ipv4_gateway != NULL && + if (data->ipv4_gateway && data->ipv4_gateway == config) return data; - if (data->ipv6_gateway != NULL && + if (data->ipv6_gateway && data->ipv6_gateway == config) return data; } @@ -111,22 +111,22 @@ static struct gateway_data *find_vpn_gateway(int index, const char *gateway) GHashTableIter iter; gpointer value, key; - if (gateway == NULL) + if (!gateway) return NULL; g_hash_table_iter_init(&iter, gateway_hash); - while (g_hash_table_iter_next(&iter, &key, &value) == TRUE) { + while (g_hash_table_iter_next(&iter, &key, &value)) { struct gateway_data *data = value; - if (data->ipv4_gateway != NULL && data->index == index && + if (data->ipv4_gateway && data->index == index && g_str_equal(data->ipv4_gateway->gateway, - gateway) == TRUE) + gateway)) return data; - if (data->ipv6_gateway != NULL && data->index == index && + if (data->ipv6_gateway && data->index == index && g_str_equal(data->ipv6_gateway->gateway, - gateway) == TRUE) + gateway)) return data; } @@ -152,7 +152,7 @@ static void get_gateway_cb(const char *gateway, int index, void *user_data) params->vpn_index, params->vpn_gateway); data = find_vpn_gateway(params->vpn_index, params->vpn_gateway); - if (data == NULL) { + if (!data) { DBG("Cannot find VPN link route, index %d addr %s", params->vpn_index, params->vpn_gateway); goto out; @@ -199,18 +199,18 @@ static void set_vpn_routes(struct gateway_data *new_gateway, } else return; - if (config != NULL) { + if (config) { int index = __connman_ipconfig_get_index(ipconfig); struct get_gateway_params *params; - config->vpn = TRUE; - if (peer != NULL) + config->vpn = true; + if (peer) config->vpn_ip = g_strdup(peer); - else if (gateway != NULL) + else if (gateway) config->vpn_ip = g_strdup(gateway); params = g_try_malloc(sizeof(struct get_gateway_params)); - if (params == NULL) + if (!params) return; params->vpn_index = index; @@ -222,7 +222,7 @@ static void set_vpn_routes(struct gateway_data *new_gateway, __connman_inet_get_route(gateway, get_gateway_cb, params); } - if (active_gateway == NULL) + if (!active_gateway) return; if (type == CONNMAN_IPCONFIG_TYPE_IPV4) { @@ -232,7 +232,7 @@ static void set_vpn_routes(struct gateway_data *new_gateway, * the VPN. The route might already exist depending * on network topology. */ - if (active_gateway->ipv4_gateway == NULL) + if (!active_gateway->ipv4_gateway) return; DBG("active gw %s", active_gateway->ipv4_gateway->gateway); @@ -248,7 +248,7 @@ static void set_vpn_routes(struct gateway_data *new_gateway, } else if (type == CONNMAN_IPCONFIG_TYPE_IPV6) { - if (active_gateway->ipv6_gateway == NULL) + if (!active_gateway->ipv6_gateway) return; DBG("active gw %s", active_gateway->ipv6_gateway->gateway); @@ -268,17 +268,17 @@ static int del_routes(struct gateway_data *data, enum connman_ipconfig_type type) { int status4 = 0, status6 = 0; - int do_ipv4 = FALSE, do_ipv6 = FALSE; + bool do_ipv4 = false, do_ipv6 = false; if (type == CONNMAN_IPCONFIG_TYPE_IPV4) - do_ipv4 = TRUE; + do_ipv4 = true; else if (type == CONNMAN_IPCONFIG_TYPE_IPV6) - do_ipv6 = TRUE; + do_ipv6 = true; else - do_ipv4 = do_ipv6 = TRUE; + do_ipv4 = do_ipv6 = true; - if (do_ipv4 == TRUE && data->ipv4_gateway != NULL) { - if (data->ipv4_gateway->vpn == TRUE) { + if (do_ipv4 && data->ipv4_gateway) { + if (data->ipv4_gateway->vpn) { status4 = connman_inet_clear_gateway_address( data->index, data->ipv4_gateway->vpn_ip); @@ -296,8 +296,8 @@ static int del_routes(struct gateway_data *data, } } - if (do_ipv6 == TRUE && data->ipv6_gateway != NULL) { - if (data->ipv6_gateway->vpn == TRUE) { + if (do_ipv6 && data->ipv6_gateway) { + if (data->ipv6_gateway->vpn) { status6 = connman_inet_clear_ipv6_gateway_address( data->index, data->ipv6_gateway->vpn_ip); @@ -320,20 +320,20 @@ static int del_routes(struct gateway_data *data, static int disable_gateway(struct gateway_data *data, enum connman_ipconfig_type type) { - gboolean active = FALSE; + bool active = false; if (type == CONNMAN_IPCONFIG_TYPE_IPV4) { - if (data->ipv4_gateway != NULL) + if (data->ipv4_gateway) active = data->ipv4_gateway->active; } else if (type == CONNMAN_IPCONFIG_TYPE_IPV6) { - if (data->ipv6_gateway != NULL) + if (data->ipv6_gateway) active = data->ipv6_gateway->active; } else - active = TRUE; + active = true; DBG("type %d active %d", type, active); - if (active == TRUE) + if (active) return del_routes(data, type); return 0; @@ -346,17 +346,17 @@ static struct gateway_data *add_gateway(struct connman_service *service, struct gateway_data *data, *old; struct gateway_config *config; - if (gateway == NULL || strlen(gateway) == 0) + if (!gateway || strlen(gateway) == 0) return NULL; data = g_try_new0(struct gateway_data, 1); - if (data == NULL) + if (!data) return NULL; data->index = index; config = g_try_new0(struct gateway_config, 1); - if (config == NULL) { + if (!config) { g_free(data); return NULL; } @@ -364,9 +364,9 @@ static struct gateway_data *add_gateway(struct connman_service *service, config->gateway = g_strdup(gateway); config->vpn_ip = NULL; config->vpn_phy_ip = NULL; - config->vpn = FALSE; + config->vpn = false; config->vpn_phy_index = -1; - config->active = FALSE; + config->active = false; if (type == CONNMAN_IPCONFIG_TYPE_IPV4) data->ipv4_gateway = config; @@ -390,7 +390,7 @@ static struct gateway_data *add_gateway(struct connman_service *service, * from old gateway settings. */ old = g_hash_table_lookup(gateway_hash, service); - if (old != NULL) { + if (old) { DBG("Replacing gw %p ipv4 %p ipv6 %p", old, old->ipv4_gateway, old->ipv6_gateway); disable_gateway(old, type); @@ -418,22 +418,22 @@ static void set_default_gateway(struct gateway_data *data, { int index; int status4 = 0, status6 = 0; - int do_ipv4 = FALSE, do_ipv6 = FALSE; + bool do_ipv4 = false, do_ipv6 = false; if (type == CONNMAN_IPCONFIG_TYPE_IPV4) - do_ipv4 = TRUE; + do_ipv4 = true; else if (type == CONNMAN_IPCONFIG_TYPE_IPV6) - do_ipv6 = TRUE; + do_ipv6 = true; else - do_ipv4 = do_ipv6 = TRUE; + do_ipv4 = do_ipv6 = true; DBG("type %d gateway ipv4 %p ipv6 %p", type, data->ipv4_gateway, data->ipv6_gateway); - if (do_ipv4 == TRUE && data->ipv4_gateway != NULL && - data->ipv4_gateway->vpn == TRUE) { + if (do_ipv4 && data->ipv4_gateway && + data->ipv4_gateway->vpn) { connman_inet_set_gateway_interface(data->index); - data->ipv4_gateway->active = TRUE; + data->ipv4_gateway->active = true; DBG("set %p index %d vpn %s index %d phy %s", data, data->index, data->ipv4_gateway->vpn_ip, @@ -445,10 +445,10 @@ static void set_default_gateway(struct gateway_data *data, return; } - if (do_ipv6 == TRUE && data->ipv6_gateway != NULL && - data->ipv6_gateway->vpn == TRUE) { + if (do_ipv6 && data->ipv6_gateway && + data->ipv6_gateway->vpn) { connman_inet_set_ipv6_gateway_interface(data->index); - data->ipv6_gateway->active = TRUE; + data->ipv6_gateway->active = true; DBG("set %p index %d vpn %s index %d phy %s", data, data->index, data->ipv6_gateway->vpn_ip, @@ -462,7 +462,7 @@ static void set_default_gateway(struct gateway_data *data, index = __connman_service_get_index(data->service); - if (do_ipv4 == TRUE && data->ipv4_gateway != NULL && + if (do_ipv4 && data->ipv4_gateway && g_strcmp0(data->ipv4_gateway->gateway, "0.0.0.0") == 0) { if (connman_inet_set_gateway_interface(index) < 0) @@ -470,7 +470,7 @@ static void set_default_gateway(struct gateway_data *data, goto done; } - if (do_ipv6 == TRUE && data->ipv6_gateway != NULL && + if (do_ipv6 && data->ipv6_gateway && g_strcmp0(data->ipv6_gateway->gateway, "::") == 0) { if (connman_inet_set_ipv6_gateway_interface(index) < 0) @@ -478,13 +478,13 @@ static void set_default_gateway(struct gateway_data *data, goto done; } - if (do_ipv6 == TRUE && data->ipv6_gateway != NULL) - status6 = connman_inet_set_ipv6_gateway_address(index, - data->ipv6_gateway->gateway); + if (do_ipv6 && data->ipv6_gateway) + status6 = __connman_inet_add_default_to_table(RT_TABLE_MAIN, + index, data->ipv6_gateway->gateway); - if (do_ipv4 == TRUE && data->ipv4_gateway != NULL) - status4 = connman_inet_set_gateway_address(index, - data->ipv4_gateway->gateway); + if (do_ipv4 && data->ipv4_gateway) + status4 = __connman_inet_add_default_to_table(RT_TABLE_MAIN, + index, data->ipv4_gateway->gateway); if (status4 < 0 || status6 < 0) return; @@ -497,22 +497,22 @@ static void unset_default_gateway(struct gateway_data *data, enum connman_ipconfig_type type) { int index; - int do_ipv4 = FALSE, do_ipv6 = FALSE; + bool do_ipv4 = false, do_ipv6 = false; if (type == CONNMAN_IPCONFIG_TYPE_IPV4) - do_ipv4 = TRUE; + do_ipv4 = true; else if (type == CONNMAN_IPCONFIG_TYPE_IPV6) - do_ipv6 = TRUE; + do_ipv6 = true; else - do_ipv4 = do_ipv6 = TRUE; + do_ipv4 = do_ipv6 = true; DBG("type %d gateway ipv4 %p ipv6 %p", type, data->ipv4_gateway, data->ipv6_gateway); - if (do_ipv4 == TRUE && data->ipv4_gateway != NULL && - data->ipv4_gateway->vpn == TRUE) { + if (do_ipv4 && data->ipv4_gateway && + data->ipv4_gateway->vpn) { connman_inet_clear_gateway_interface(data->index); - data->ipv4_gateway->active = FALSE; + data->ipv4_gateway->active = false; DBG("unset %p index %d vpn %s index %d phy %s", data, data->index, data->ipv4_gateway->vpn_ip, @@ -522,10 +522,10 @@ static void unset_default_gateway(struct gateway_data *data, return; } - if (do_ipv6 == TRUE && data->ipv6_gateway != NULL && - data->ipv6_gateway->vpn == TRUE) { + if (do_ipv6 && data->ipv6_gateway && + data->ipv6_gateway->vpn) { connman_inet_clear_ipv6_gateway_interface(data->index); - data->ipv6_gateway->active = FALSE; + data->ipv6_gateway->active = false; DBG("unset %p index %d vpn %s index %d phy %s", data, data->index, data->ipv6_gateway->vpn_ip, @@ -537,25 +537,25 @@ static void unset_default_gateway(struct gateway_data *data, index = __connman_service_get_index(data->service); - if (do_ipv4 == TRUE && data->ipv4_gateway != NULL && + if (do_ipv4 && data->ipv4_gateway && g_strcmp0(data->ipv4_gateway->gateway, "0.0.0.0") == 0) { connman_inet_clear_gateway_interface(index); return; } - if (do_ipv6 == TRUE && data->ipv6_gateway != NULL && + if (do_ipv6 && data->ipv6_gateway && g_strcmp0(data->ipv6_gateway->gateway, "::") == 0) { connman_inet_clear_ipv6_gateway_interface(index); return; } - if (do_ipv6 == TRUE && data->ipv6_gateway != NULL) + if (do_ipv6 && data->ipv6_gateway) connman_inet_clear_ipv6_gateway_address(index, data->ipv6_gateway->gateway); - if (do_ipv4 == TRUE && data->ipv4_gateway != NULL) + if (do_ipv4 && data->ipv4_gateway) connman_inet_clear_gateway_address(index, data->ipv4_gateway->gateway); } @@ -569,10 +569,10 @@ static struct gateway_data *find_default_gateway(void) g_hash_table_iter_init(&iter, gateway_hash); - while (g_hash_table_iter_next(&iter, &key, &value) == TRUE) { + while (g_hash_table_iter_next(&iter, &key, &value)) { struct gateway_data *data = value; - if (found == NULL || data->order > order) { + if (!found || data->order > order) { found = data; order = data->order; @@ -583,48 +583,48 @@ static struct gateway_data *find_default_gateway(void) return found; } -static gboolean choose_default_gateway(struct gateway_data *data, +static bool choose_default_gateway(struct gateway_data *data, struct gateway_data *candidate) { - gboolean downgraded = FALSE; + bool downgraded = false; /* * If the current default is not active, then we mark * this one as default. If the other one is already active * we mark this one as non default. */ - if (data->ipv4_gateway != NULL) { - if (candidate->ipv4_gateway != NULL && - candidate->ipv4_gateway->active == FALSE) { + if (data->ipv4_gateway) { + if (candidate->ipv4_gateway && + !candidate->ipv4_gateway->active) { DBG("ipv4 downgrading %p", candidate); unset_default_gateway(candidate, CONNMAN_IPCONFIG_TYPE_IPV4); } - if (candidate->ipv4_gateway != NULL && - candidate->ipv4_gateway->active == TRUE && + if (candidate->ipv4_gateway && + candidate->ipv4_gateway->active && candidate->order > data->order) { DBG("ipv4 downgrading this %p", data); unset_default_gateway(data, CONNMAN_IPCONFIG_TYPE_IPV4); - downgraded = TRUE; + downgraded = true; } } - if (data->ipv6_gateway != NULL) { - if (candidate->ipv6_gateway != NULL && - candidate->ipv6_gateway->active == FALSE) { + if (data->ipv6_gateway) { + if (candidate->ipv6_gateway && + !candidate->ipv6_gateway->active) { DBG("ipv6 downgrading %p", candidate); unset_default_gateway(candidate, CONNMAN_IPCONFIG_TYPE_IPV6); } - if (candidate->ipv6_gateway != NULL && - candidate->ipv6_gateway->active == TRUE && + if (candidate->ipv6_gateway && + candidate->ipv6_gateway->active && candidate->order > data->order) { DBG("ipv6 downgrading this %p", data); unset_default_gateway(data, CONNMAN_IPCONFIG_TYPE_IPV6); - downgraded = TRUE; + downgraded = true; } } @@ -637,15 +637,15 @@ static void connection_newgateway(int index, const char *gateway) struct gateway_data *data; GHashTableIter iter; gpointer value, key; - gboolean found = FALSE; + bool found = false; DBG("index %d gateway %s", index, gateway); config = find_gateway(index, gateway); - if (config == NULL) + if (!config) return; - config->active = TRUE; + config->active = true; /* * It is possible that we have two default routes atm @@ -653,10 +653,10 @@ static void connection_newgateway(int index, const char *gateway) * same time. */ data = lookup_gateway_data(config); - if (data == NULL) + if (!data) return; - if (data->default_checked == TRUE) + if (data->default_checked) return; /* @@ -666,26 +666,26 @@ static void connection_newgateway(int index, const char *gateway) g_hash_table_iter_init(&iter, gateway_hash); - while (g_hash_table_iter_next(&iter, &key, &value) == TRUE) { + while (g_hash_table_iter_next(&iter, &key, &value)) { struct gateway_data *candidate = value; if (candidate == data) continue; found = choose_default_gateway(data, candidate); - if (found == TRUE) + if (found) break; } - if (found == FALSE) { - if (data->ipv4_gateway != NULL) + if (!found) { + if (data->ipv4_gateway) set_default_gateway(data, CONNMAN_IPCONFIG_TYPE_IPV4); - if (data->ipv6_gateway != NULL) + if (data->ipv6_gateway) set_default_gateway(data, CONNMAN_IPCONFIG_TYPE_IPV6); } - data->default_checked = TRUE; + data->default_checked = true; } static void remove_gateway(gpointer user_data) @@ -694,14 +694,14 @@ static void remove_gateway(gpointer user_data) DBG("gateway ipv4 %p ipv6 %p", data->ipv4_gateway, data->ipv6_gateway); - if (data->ipv4_gateway != NULL) { + if (data->ipv4_gateway) { g_free(data->ipv4_gateway->gateway); g_free(data->ipv4_gateway->vpn_ip); g_free(data->ipv4_gateway->vpn_phy_ip); g_free(data->ipv4_gateway); } - if (data->ipv6_gateway != NULL) { + if (data->ipv6_gateway) { g_free(data->ipv6_gateway->gateway); g_free(data->ipv6_gateway->vpn_ip); g_free(data->ipv6_gateway->vpn_phy_ip); @@ -719,11 +719,11 @@ static void connection_delgateway(int index, const char *gateway) DBG("index %d gateway %s", index, gateway); config = find_gateway(index, gateway); - if (config != NULL) - config->active = FALSE; + if (config) + config->active = false; data = find_default_gateway(); - if (data != NULL) + if (data) set_default_gateway(data, CONNMAN_IPCONFIG_TYPE_ALL); } @@ -742,15 +742,15 @@ static struct gateway_data *find_active_gateway(void) g_hash_table_iter_init(&iter, gateway_hash); - while (g_hash_table_iter_next(&iter, &key, &value) == TRUE) { + while (g_hash_table_iter_next(&iter, &key, &value)) { struct gateway_data *data = value; - if (data->ipv4_gateway != NULL && - data->ipv4_gateway->active == TRUE) + if (data->ipv4_gateway && + data->ipv4_gateway->active) return data; - if (data->ipv6_gateway != NULL && - data->ipv6_gateway->active == TRUE) + if (data->ipv6_gateway && + data->ipv6_gateway->active) return data; } @@ -766,7 +766,7 @@ static void update_order(void) g_hash_table_iter_init(&iter, gateway_hash); - while (g_hash_table_iter_next(&iter, &key, &value) == TRUE) { + while (g_hash_table_iter_next(&iter, &key, &value)) { struct gateway_data *data = value; data->order = __connman_service_get_order(data->service); @@ -779,16 +779,16 @@ void __connman_connection_gateway_activate(struct connman_service *service, struct gateway_data *data = NULL; data = g_hash_table_lookup(gateway_hash, service); - if (data == NULL) + if (!data) return; DBG("gateway %p/%p type %d", data->ipv4_gateway, data->ipv6_gateway, type); if (type == CONNMAN_IPCONFIG_TYPE_IPV4) - data->ipv4_gateway->active = TRUE; + data->ipv4_gateway->active = true; else if (type == CONNMAN_IPCONFIG_TYPE_IPV6) - data->ipv6_gateway->active = TRUE; + data->ipv6_gateway->active = true; } static void add_host_route(int family, int index, const char *gateway, @@ -859,17 +859,17 @@ int __connman_connection_gateway_add(struct connman_service *service, * gateway for ipv4 is 0.0.0.0 and for ipv6 is ::, meaning the * interface */ - if (gateway == NULL && type == CONNMAN_IPCONFIG_TYPE_IPV4) + if (!gateway && type == CONNMAN_IPCONFIG_TYPE_IPV4) gateway = "0.0.0.0"; - if (gateway == NULL && type == CONNMAN_IPCONFIG_TYPE_IPV6) + if (!gateway && type == CONNMAN_IPCONFIG_TYPE_IPV6) gateway = "::"; DBG("service %p index %d gateway %s vpn ip %s type %d", service, index, gateway, peer, type); new_gateway = add_gateway(service, index, gateway, type); - if (new_gateway == NULL) + if (!new_gateway) return -EINVAL; active_gateway = find_active_gateway(); @@ -878,7 +878,7 @@ int __connman_connection_gateway_add(struct connman_service *service, active_gateway ? active_gateway->index : -1, new_gateway); if (type == CONNMAN_IPCONFIG_TYPE_IPV4 && - new_gateway->ipv4_gateway != NULL) { + new_gateway->ipv4_gateway) { add_host_route(AF_INET, index, gateway, service_type); __connman_service_nameserver_add_routes(service, new_gateway->ipv4_gateway->gateway); @@ -886,7 +886,7 @@ int __connman_connection_gateway_add(struct connman_service *service, } if (type == CONNMAN_IPCONFIG_TYPE_IPV6 && - new_gateway->ipv6_gateway != NULL) { + new_gateway->ipv6_gateway) { add_host_route(AF_INET6, index, gateway, service_type); __connman_service_nameserver_add_routes(service, new_gateway->ipv6_gateway->gateway); @@ -900,34 +900,32 @@ int __connman_connection_gateway_add(struct connman_service *service, } else { if (type == CONNMAN_IPCONFIG_TYPE_IPV4 && - new_gateway->ipv4_gateway != NULL) - new_gateway->ipv4_gateway->vpn = FALSE; + new_gateway->ipv4_gateway) + new_gateway->ipv4_gateway->vpn = false; if (type == CONNMAN_IPCONFIG_TYPE_IPV6 && - new_gateway->ipv6_gateway != NULL) - new_gateway->ipv6_gateway->vpn = FALSE; + new_gateway->ipv6_gateway) + new_gateway->ipv6_gateway->vpn = false; } - if (active_gateway == NULL) { + if (!active_gateway) { set_default_gateway(new_gateway, type); goto done; } if (type == CONNMAN_IPCONFIG_TYPE_IPV4 && - new_gateway->ipv4_gateway != NULL && - new_gateway->ipv4_gateway->vpn == TRUE) { - if (__connman_service_is_split_routing(new_gateway->service) == - FALSE) + new_gateway->ipv4_gateway && + new_gateway->ipv4_gateway->vpn) { + if (!__connman_service_is_split_routing(new_gateway->service)) connman_inet_clear_gateway_address( active_gateway->index, active_gateway->ipv4_gateway->gateway); } if (type == CONNMAN_IPCONFIG_TYPE_IPV6 && - new_gateway->ipv6_gateway != NULL && - new_gateway->ipv6_gateway->vpn == TRUE) { - if (__connman_service_is_split_routing(new_gateway->service) == - FALSE) + new_gateway->ipv6_gateway && + new_gateway->ipv6_gateway->vpn) { + if (!__connman_service_is_split_routing(new_gateway->service)) connman_inet_clear_ipv6_gateway_address( active_gateway->index, active_gateway->ipv6_gateway->gateway); @@ -950,29 +948,29 @@ void __connman_connection_gateway_remove(struct connman_service *service, enum connman_ipconfig_type type) { struct gateway_data *data = NULL; - gboolean set_default4 = FALSE, set_default6 = FALSE; - int do_ipv4 = FALSE, do_ipv6 = FALSE; + bool set_default4 = false, set_default6 = false; + bool do_ipv4 = false, do_ipv6 = false; int err; DBG("service %p type %d", service, type); if (type == CONNMAN_IPCONFIG_TYPE_IPV4) - do_ipv4 = TRUE; + do_ipv4 = true; else if (type == CONNMAN_IPCONFIG_TYPE_IPV6) - do_ipv6 = TRUE; + do_ipv6 = true; else - do_ipv4 = do_ipv6 = TRUE; + do_ipv4 = do_ipv6 = true; __connman_service_nameserver_del_routes(service, type); data = g_hash_table_lookup(gateway_hash, service); - if (data == NULL) + if (!data) return; - if (do_ipv4 == TRUE && data->ipv4_gateway != NULL) + if (do_ipv4 && data->ipv4_gateway) set_default4 = data->ipv4_gateway->vpn; - if (do_ipv6 == TRUE && data->ipv6_gateway != NULL) + if (do_ipv6 && data->ipv6_gateway) set_default6 = data->ipv6_gateway->vpn; DBG("ipv4 gateway %s ipv6 gateway %s vpn %d/%d", @@ -980,14 +978,15 @@ void __connman_connection_gateway_remove(struct connman_service *service, data->ipv6_gateway ? data->ipv6_gateway->gateway : "<null>", set_default4, set_default6); - if (do_ipv4 == TRUE && data->ipv4_gateway != NULL && - data->ipv4_gateway->vpn == TRUE && data->index >= 0) - connman_inet_del_host_route(data->index, + if (do_ipv4 && data->ipv4_gateway && + data->ipv4_gateway->vpn && data->index >= 0) + connman_inet_del_host_route(data->ipv4_gateway->vpn_phy_index, data->ipv4_gateway->gateway); - if (do_ipv6 == TRUE && data->ipv6_gateway != NULL && - data->ipv6_gateway->vpn == TRUE && data->index >= 0) - connman_inet_del_ipv6_host_route(data->index, + if (do_ipv6 && data->ipv6_gateway && + data->ipv6_gateway->vpn && data->index >= 0) + connman_inet_del_ipv6_host_route( + data->ipv6_gateway->vpn_phy_index, data->ipv6_gateway->gateway); err = disable_gateway(data, type); @@ -997,10 +996,10 @@ void __connman_connection_gateway_remove(struct connman_service *service, * settings are to be removed. */ if (do_ipv4 == do_ipv6 || - (data->ipv4_gateway != NULL && data->ipv6_gateway == NULL - && do_ipv4 == TRUE) || - (data->ipv6_gateway != NULL && data->ipv4_gateway == NULL - && do_ipv6 == TRUE) + (data->ipv4_gateway && !data->ipv6_gateway + && do_ipv4) || + (data->ipv6_gateway && !data->ipv4_gateway + && do_ipv6) ) { connman_service_unref(service); g_hash_table_remove(gateway_hash, service); @@ -1016,19 +1015,19 @@ void __connman_connection_gateway_remove(struct connman_service *service, */ if (set_default4 || set_default6 || err < 0) { data = find_default_gateway(); - if (data != NULL) + if (data) set_default_gateway(data, type); } } -gboolean __connman_connection_update_gateway(void) +bool __connman_connection_update_gateway(void) { struct gateway_data *default_gateway; - gboolean updated = FALSE; + bool updated = false; GHashTableIter iter; gpointer value, key; - if (gateway_hash == NULL) + if (!gateway_hash) return updated; update_order(); @@ -1045,30 +1044,30 @@ gboolean __connman_connection_update_gateway(void) */ g_hash_table_iter_init(&iter, gateway_hash); - while (g_hash_table_iter_next(&iter, &key, &value) == TRUE) { + while (g_hash_table_iter_next(&iter, &key, &value)) { struct gateway_data *active_gateway = value; if (active_gateway == default_gateway) continue; - if (active_gateway->ipv4_gateway != NULL && - active_gateway->ipv4_gateway->active == TRUE) { + if (active_gateway->ipv4_gateway && + active_gateway->ipv4_gateway->active) { unset_default_gateway(active_gateway, CONNMAN_IPCONFIG_TYPE_IPV4); - updated = TRUE; + updated = true; } - if (active_gateway->ipv6_gateway != NULL && - active_gateway->ipv6_gateway->active == TRUE) { + if (active_gateway->ipv6_gateway && + active_gateway->ipv6_gateway->active) { unset_default_gateway(active_gateway, CONNMAN_IPCONFIG_TYPE_IPV6); - updated = TRUE; + updated = true; } } - if (updated && default_gateway != NULL) { + if (updated && default_gateway) { if (default_gateway->ipv4_gateway) set_default_gateway(default_gateway, CONNMAN_IPCONFIG_TYPE_IPV4); @@ -1088,14 +1087,14 @@ int __connman_connection_get_vpn_index(int phy_index) g_hash_table_iter_init(&iter, gateway_hash); - while (g_hash_table_iter_next(&iter, &key, &value) == TRUE) { + while (g_hash_table_iter_next(&iter, &key, &value)) { struct gateway_data *data = value; - if (data->ipv4_gateway != NULL && + if (data->ipv4_gateway && data->ipv4_gateway->vpn_phy_index == phy_index) return data->index; - if (data->ipv6_gateway != NULL && + if (data->ipv6_gateway && data->ipv6_gateway->vpn_phy_index == phy_index) return data->index; } @@ -1130,7 +1129,7 @@ void __connman_connection_cleanup(void) g_hash_table_iter_init(&iter, gateway_hash); - while (g_hash_table_iter_next(&iter, &key, &value) == TRUE) { + while (g_hash_table_iter_next(&iter, &key, &value)) { struct gateway_data *data = value; disable_gateway(data, CONNMAN_IPCONFIG_TYPE_ALL); diff --git a/src/connman.h b/src/connman.h index 75f136fb..24db5f8d 100644 --- a/src/connman.h +++ b/src/connman.h @@ -2,7 +2,7 @@ * * Connection Manager * - * Copyright (C) 2007-2012 Intel Corporation. All rights reserved. + * Copyright (C) 2007-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 @@ -19,6 +19,8 @@ * */ +#include <stdbool.h> + #include <glib.h> #define CONNMAN_API_SUBJECT_TO_CHANGE @@ -26,7 +28,9 @@ #include <connman/dbus.h> dbus_bool_t __connman_dbus_append_objpath_dict_array(DBusMessage *msg, - connman_dbus_append_cb_t function, void *user_data); + connman_dbus_append_cb_t function, void *user_data); +dbus_bool_t __connman_dbus_append_objpath_array(DBusMessage *msg, + connman_dbus_append_cb_t function, void *user_data); int __connman_dbus_init(DBusConnection *conn); void __connman_dbus_cleanup(void); @@ -51,8 +55,6 @@ DBusMessage *__connman_error_operation_timeout(DBusMessage *msg); DBusMessage *__connman_error_invalid_service(DBusMessage *msg); DBusMessage *__connman_error_invalid_property(DBusMessage *msg); -#include <connman/types.h> - int __connman_manager_init(void); void __connman_manager_cleanup(void); @@ -93,16 +95,17 @@ void __connman_agent_cancel(struct connman_service *service); int __connman_service_add_passphrase(struct connman_service *service, const gchar *passphrase); typedef void (* authentication_cb_t) (struct connman_service *service, - connman_bool_t values_received, + bool values_received, const char *name, int name_len, const char *identifier, const char *secret, - gboolean wps, const char *wpspin, + bool wps, const char *wpspin, const char *error, void *user_data); typedef void (* browser_authentication_cb_t) (struct connman_service *service, - connman_bool_t authentication_done, + bool authentication_done, const char *error, void *user_data); int __connman_agent_request_passphrase_input(struct connman_service *service, - authentication_cb_t callback, void *user_data); + authentication_cb_t callback, + const char *dbus_sender, void *user_data); int __connman_agent_request_login_input(struct connman_service *service, authentication_cb_t callback, void *user_data); int __connman_agent_request_browser(struct connman_service *service, @@ -112,9 +115,9 @@ int __connman_agent_request_browser(struct connman_service *service, #include <connman/log.h> int __connman_log_init(const char *program, const char *debug, - connman_bool_t detach, connman_bool_t backtrace, + gboolean detach, gboolean backtrace, const char *program_name, const char *program_version); -void __connman_log_cleanup(connman_bool_t backtrace); +void __connman_log_cleanup(gboolean backtrace); void __connman_log_enable(struct connman_debug_desc *start, struct connman_debug_desc *stop); @@ -141,6 +144,7 @@ int __connman_inet_modify_address(int cmd, int flags, int index, int family, unsigned char prefixlen, const char *broadcast); int __connman_inet_get_interface_address(int index, int family, void *address); +int __connman_inet_get_interface_ll_address(int index, int family, void *address); #include <netinet/ip6.h> #include <netinet/icmp6.h> @@ -150,8 +154,25 @@ typedef void (*__connman_inet_rs_cb_t) (struct nd_router_advert *reply, int __connman_inet_ipv6_send_rs(int index, int timeout, __connman_inet_rs_cb_t callback, void *user_data); +int __connman_inet_ipv6_send_ra(int index, struct in6_addr *src_addr, + GSList *prefixes, int router_lifetime); -int __connman_refresh_rs_ipv6(struct connman_network *network, int index); +typedef void (*__connman_inet_ns_cb_t) (struct nd_neighbor_advert *reply, + unsigned int length, + struct in6_addr *addr, + void *user_data); +int __connman_inet_ipv6_do_dad(int index, int timeout_ms, + struct in6_addr *addr, + __connman_inet_ns_cb_t callback, void *user_data); + +typedef void (*__connman_inet_recv_rs_cb_t) (struct nd_router_solicit *reply, + unsigned int length, void *user_data); +int __connman_inet_ipv6_start_recv_rs(int index, + __connman_inet_recv_rs_cb_t callback, + void *user_data, void **context); +void __connman_inet_ipv6_stop_recv_rs(void *context); + +int __connman_network_refresh_rs_ipv6(struct connman_network *network, int index); GSList *__connman_inet_ipv6_get_prefixes(struct nd_router_advert *hdr, unsigned int length); @@ -200,9 +221,16 @@ int __connman_inet_rtnl_addattr_l(struct nlmsghdr *n, size_t max_length, int __connman_inet_rtnl_addattr32(struct nlmsghdr *n, size_t maxlen, int type, __u32 data); +int __connman_inet_add_fwmark_rule(uint32_t table_id, int family, uint32_t fwmark); +int __connman_inet_del_fwmark_rule(uint32_t table_id, int family, uint32_t fwmark); +int __connman_inet_add_default_to_table(uint32_t table_id, int ifindex, const char *gateway); +int __connman_inet_del_default_from_table(uint32_t table_id, int ifindex, const char *gateway); +int __connman_inet_get_address_netmask(int ifindex, + struct sockaddr_in *address, struct sockaddr_in *netmask); + #include <connman/resolver.h> -int __connman_resolver_init(connman_bool_t dnsproxy); +int __connman_resolver_init(gboolean dnsproxy); void __connman_resolver_cleanup(void); int __connman_resolvfile_append(int index, const char *domain, const char *server); int __connman_resolvfile_remove(int index, const char *domain, const char *server); @@ -220,9 +248,9 @@ GKeyFile *__connman_storage_open_service(const char *ident); int __connman_storage_save_service(GKeyFile *keyfile, const char *ident); GKeyFile *__connman_storage_load_provider(const char *identifier); void __connman_storage_save_provider(GKeyFile *keyfile, const char *identifier); -gboolean __connman_storage_remove_provider(const char *identifier); +bool __connman_storage_remove_provider(const char *identifier); char **__connman_storage_get_providers(void); -gboolean __connman_storage_remove_service(const char *service_id); +bool __connman_storage_remove_service(const char *service_id); int __connman_detect_init(void); void __connman_detect_cleanup(void); @@ -249,14 +277,14 @@ struct connman_ipaddress { }; struct connman_ipconfig_ops { - void (*up) (struct connman_ipconfig *ipconfig); - void (*down) (struct connman_ipconfig *ipconfig); - void (*lower_up) (struct connman_ipconfig *ipconfig); - void (*lower_down) (struct connman_ipconfig *ipconfig); - void (*ip_bound) (struct connman_ipconfig *ipconfig); - void (*ip_release) (struct connman_ipconfig *ipconfig); - void (*route_set) (struct connman_ipconfig *ipconfig); - void (*route_unset) (struct connman_ipconfig *ipconfig); + void (*up) (struct connman_ipconfig *ipconfig, const char *ifname); + void (*down) (struct connman_ipconfig *ipconfig, const char *ifname); + void (*lower_up) (struct connman_ipconfig *ipconfig, const char *ifname); + void (*lower_down) (struct connman_ipconfig *ipconfig, const char *ifname); + void (*ip_bound) (struct connman_ipconfig *ipconfig, const char *ifname); + void (*ip_release) (struct connman_ipconfig *ipconfig, const char *ifname); + void (*route_set) (struct connman_ipconfig *ipconfig, const char *ifname); + void (*route_unset) (struct connman_ipconfig *ipconfig, const char *ifname); }; struct connman_ipconfig *__connman_ipconfig_create(int index, @@ -278,7 +306,6 @@ void *__connman_ipconfig_get_data(struct connman_ipconfig *ipconfig); void __connman_ipconfig_set_data(struct connman_ipconfig *ipconfig, void *data); int __connman_ipconfig_get_index(struct connman_ipconfig *ipconfig); -const char *__connman_ipconfig_get_ifname(struct connman_ipconfig *ipconfig); void __connman_ipconfig_set_ops(struct connman_ipconfig *ipconfig, const struct connman_ipconfig_ops *ops); @@ -329,7 +356,7 @@ void __connman_ipconfig_set_prefixlen(struct connman_ipconfig *ipconfig, unsigne int __connman_ipconfig_enable(struct connman_ipconfig *ipconfig); int __connman_ipconfig_disable(struct connman_ipconfig *ipconfig); -connman_bool_t __connman_ipconfig_is_usable(struct connman_ipconfig *ipconfig); +bool __connman_ipconfig_is_usable(struct connman_ipconfig *ipconfig); const char *__connman_ipconfig_method2string(enum connman_ipconfig_method method); const char *__connman_ipconfig_type2string(enum connman_ipconfig_type type); @@ -364,14 +391,18 @@ const char *__connman_ipconfig_get_proxy_autoconfig(struct connman_ipconfig *ipc void __connman_ipconfig_set_dhcp_address(struct connman_ipconfig *ipconfig, const char *address); char *__connman_ipconfig_get_dhcp_address(struct connman_ipconfig *ipconfig); +void __connman_ipconfig_set_dhcpv6_prefixes(struct connman_ipconfig *ipconfig, + char **prefixes); +char **__connman_ipconfig_get_dhcpv6_prefixes(struct connman_ipconfig *ipconfig); int __connman_ipconfig_load(struct connman_ipconfig *ipconfig, GKeyFile *keyfile, const char *identifier, const char *prefix); int __connman_ipconfig_save(struct connman_ipconfig *ipconfig, GKeyFile *keyfile, const char *identifier, const char *prefix); -gboolean __connman_ipconfig_ipv6_privacy_enabled(struct connman_ipconfig *ipconfig); +bool __connman_ipconfig_ipv6_privacy_enabled(struct connman_ipconfig *ipconfig); int __connman_ipconfig_ipv6_set_privacy(struct connman_ipconfig *ipconfig, const char *value); +bool __connman_ipconfig_ipv6_is_enabled(struct connman_ipconfig *ipconfig); int __connman_ipconfig_set_rp_filter(); void __connman_ipconfig_unset_rp_filter(int old_value); @@ -394,8 +425,17 @@ GSList *__connman_timeserver_get_all(struct connman_service *service); int __connman_timeserver_sync(struct connman_service *service); void __connman_timeserver_sync_next(); +enum __connman_dhcpv6_status { + CONNMAN_DHCPV6_STATUS_FAIL = 0, + CONNMAN_DHCPV6_STATUS_SUCCEED = 1, + CONNMAN_DHCPV6_STATUS_RESTART = 2, +}; + +typedef void (* dhcpv6_cb) (struct connman_network *network, + enum __connman_dhcpv6_status status, gpointer data); + typedef void (* dhcp_cb) (struct connman_network *network, - connman_bool_t success); + bool success, gpointer data); int __connman_dhcp_start(struct connman_network *network, dhcp_cb callback); void __connman_dhcp_stop(struct connman_network *network); int __connman_dhcp_init(void); @@ -403,14 +443,20 @@ void __connman_dhcp_cleanup(void); int __connman_dhcpv6_init(void); void __connman_dhcpv6_cleanup(void); int __connman_dhcpv6_start_info(struct connman_network *network, - dhcp_cb callback); + dhcpv6_cb callback); void __connman_dhcpv6_stop(struct connman_network *network); int __connman_dhcpv6_start(struct connman_network *network, - GSList *prefixes, dhcp_cb callback); + GSList *prefixes, dhcpv6_cb callback); int __connman_dhcpv6_start_renew(struct connman_network *network, - dhcp_cb callback); + dhcpv6_cb callback); int __connman_dhcpv6_start_release(struct connman_network *network, - dhcp_cb callback); + dhcpv6_cb callback); +int __connman_dhcpv6_start_pd(int index, GSList *prefixes, dhcpv6_cb callback); +void __connman_dhcpv6_stop_pd(int index); +int __connman_dhcpv6_start_pd_renew(struct connman_network *network, + dhcpv6_cb callback); +int __connman_dhcpv6_start_pd_release(struct connman_network *network, + dhcpv6_cb callback); int __connman_ipv4_init(void); void __connman_ipv4_cleanup(void); @@ -426,7 +472,7 @@ void __connman_connection_gateway_remove(struct connman_service *service, enum connman_ipconfig_type type); int __connman_connection_get_vpn_index(int phy_index); -gboolean __connman_connection_update_gateway(void); +bool __connman_connection_update_gateway(void); void __connman_connection_gateway_activate(struct connman_service *service, enum connman_ipconfig_type type); @@ -452,28 +498,29 @@ int __connman_technology_add_device(struct connman_device *device); int __connman_technology_remove_device(struct connman_device *device); int __connman_technology_enabled(enum connman_service_type type); int __connman_technology_disabled(enum connman_service_type type); -int __connman_technology_set_offlinemode(connman_bool_t offlinemode); -connman_bool_t __connman_technology_get_offlinemode(void); +int __connman_technology_set_offlinemode(bool offlinemode); +bool __connman_technology_get_offlinemode(void); void __connman_technology_set_connected(enum connman_service_type type, - connman_bool_t connected); + bool connected); int __connman_technology_add_rfkill(unsigned int index, enum connman_service_type type, - connman_bool_t softblock, - connman_bool_t hardblock); + bool softblock, + bool hardblock); int __connman_technology_update_rfkill(unsigned int index, enum connman_service_type type, - connman_bool_t softblock, - connman_bool_t hardblock); + bool softblock, + bool hardblock); int __connman_technology_remove_rfkill(unsigned int index, enum connman_service_type type); void __connman_technology_scan_started(struct connman_device *device); -void __connman_technology_scan_stopped(struct connman_device *device); +void __connman_technology_scan_stopped(struct connman_device *device, + enum connman_service_type type); void __connman_technology_add_interface(enum connman_service_type type, - int index, const char *name, const char *ident); + int index, const char *ident); void __connman_technology_remove_interface(enum connman_service_type type, - int index, const char *name, const char *ident); + int index, const char *ident); void __connman_technology_notify_regdom_by_device(struct connman_device *device, int result, const char *alpha2); @@ -490,9 +537,9 @@ int __connman_device_request_scan(enum connman_service_type type); int __connman_device_request_hidden_scan(struct connman_device *device, const char *ssid, unsigned int ssid_len, const char *identity, const char *passphrase, - gpointer user_data); + const char *security, void *user_data); -connman_bool_t __connman_device_isfiltered(const char *devname); +bool __connman_device_isfiltered(const char *devname); void __connman_device_set_network(struct connman_device *device, struct connman_network *network); @@ -502,17 +549,13 @@ int __connman_device_enable(struct connman_device *device); int __connman_device_disable(struct connman_device *device); int __connman_device_disconnect(struct connman_device *device); -connman_bool_t __connman_device_has_driver(struct connman_device *device); - -void __connman_device_set_reconnect(struct connman_device *device, - connman_bool_t reconnect); -connman_bool_t __connman_device_get_reconnect(struct connman_device *device); +bool __connman_device_has_driver(struct connman_device *device); const char *__connman_device_get_type(struct connman_device *device); int __connman_rfkill_init(void); void __connman_rfkill_cleanup(void); -int __connman_rfkill_block(enum connman_service_type type, connman_bool_t block); +int __connman_rfkill_block(enum connman_service_type type, bool block); #include <connman/network.h> @@ -533,16 +576,28 @@ int __connman_network_set_ipconfig(struct connman_network *network, const char *__connman_network_get_type(struct connman_network *network); const char *__connman_network_get_group(struct connman_network *network); const char *__connman_network_get_ident(struct connman_network *network); -connman_bool_t __connman_network_get_weakness(struct connman_network *network); +bool __connman_network_get_weakness(struct connman_network *network); int __connman_config_init(); void __connman_config_cleanup(void); -int __connman_config_load_service(GKeyFile *keyfile, const char *group, connman_bool_t persistent); +int __connman_config_load_service(GKeyFile *keyfile, const char *group, + bool persistent); int __connman_config_provision_service(struct connman_service *service); int __connman_config_provision_service_ident(struct connman_service *service, const char *ident, const char *file, const char *entry); +char *__connman_config_get_string(GKeyFile *key_file, + const char *group_name, const char *key, GError **error); + +char **__connman_config_get_string_list(GKeyFile *key_file, + const char *group_name, const char *key, gsize *length, GError **error); + +bool __connman_config_get_bool(GKeyFile *key_file, + const char *group_name, const char *key, GError **error); +bool __connman_config_address_provisioned(const char *address, + const char *netmask); + int __connman_tethering_init(void); void __connman_tethering_cleanup(void); @@ -553,13 +608,17 @@ void __connman_tethering_set_disabled(void); int __connman_private_network_request(DBusMessage *msg, const char *owner); int __connman_private_network_release(const char *path); +int __connman_ipv6pd_setup(const char *bridge); +void __connman_ipv6pd_cleanup(void); + #include <connman/provider.h> -connman_bool_t __connman_provider_check_routes(struct connman_provider *provider); +bool __connman_provider_check_routes(struct connman_provider *provider); int __connman_provider_append_user_route(struct connman_provider *provider, int family, const char *network, const char *netmask); void __connman_provider_append_properties(struct connman_provider *provider, DBusMessageIter *iter); void __connman_provider_list(DBusMessageIter *iter, void *user_data); +bool __connman_provider_is_immutable(struct connman_provider *provider); int __connman_provider_create_and_connect(DBusMessage *msg); const char * __connman_provider_get_ident(struct connman_provider *provider); int __connman_provider_indicate_state(struct connman_provider *provider, @@ -575,6 +634,7 @@ int __connman_provider_init(void); int __connman_service_init(void); void __connman_service_cleanup(void); +int __connman_service_load_modifiable(struct connman_service *service); void __connman_service_list_struct(DBusMessageIter *iter); @@ -582,6 +642,7 @@ struct connman_service *__connman_service_lookup_from_index(int index); struct connman_service *__connman_service_lookup_from_ident(const char *identifier); struct connman_service *__connman_service_create_from_network(struct connman_network *network); struct connman_service *__connman_service_create_from_provider(struct connman_provider *provider); +bool __connman_service_index_is_default(int index); struct connman_service *__connman_service_get_default(void); void __connman_service_update_from_network(struct connman_network *network); void __connman_service_remove_from_network(struct connman_network *network); @@ -594,29 +655,31 @@ struct connman_ipconfig *__connman_service_get_ip6config( struct connman_service *service); struct connman_ipconfig *__connman_service_get_ipconfig( struct connman_service *service, int family); -connman_bool_t __connman_service_is_connected_state(struct connman_service *service, +bool __connman_service_is_connected_state(struct connman_service *service, enum connman_ipconfig_type type); const char *__connman_service_get_ident(struct connman_service *service); const char *__connman_service_get_path(struct connman_service *service); +const char *__connman_service_get_name(struct connman_service *service); unsigned int __connman_service_get_order(struct connman_service *service); +enum connman_service_state __connman_service_get_state(struct connman_service *service); void __connman_service_update_ordering(void); struct connman_network *__connman_service_get_network(struct connman_service *service); enum connman_service_security __connman_service_get_security(struct connman_service *service); const char *__connman_service_get_phase2(struct connman_service *service); -connman_bool_t __connman_service_wps_enabled(struct connman_service *service); +bool __connman_service_wps_enabled(struct connman_service *service); int __connman_service_set_favorite(struct connman_service *service, - connman_bool_t favorite); + bool favorite); int __connman_service_set_favorite_delayed(struct connman_service *service, - connman_bool_t favorite, - gboolean delay_ordering); + bool favorite, + bool delay_ordering); int __connman_service_set_immutable(struct connman_service *service, - connman_bool_t immutable); + bool immutable); int __connman_service_set_ignore(struct connman_service *service, - connman_bool_t ignore); -void __connman_service_set_userconnect(struct connman_service *service, - connman_bool_t userconnect); + bool ignore); void __connman_service_set_search_domains(struct connman_service *service, char **domains); +void __connman_service_update_search_domains(struct connman_service *service, + char **domains); void __connman_service_set_string(struct connman_service *service, const char *key, const char *value); @@ -634,12 +697,14 @@ int __connman_service_indicate_error(struct connman_service *service, int __connman_service_clear_error(struct connman_service *service); int __connman_service_indicate_default(struct connman_service *service); -int __connman_service_connect(struct connman_service *service); +int __connman_service_connect(struct connman_service *service, + enum connman_service_connect_reason reason); int __connman_service_disconnect(struct connman_service *service); int __connman_service_disconnect_all(void); -void __connman_service_auto_connect(void); -gboolean __connman_service_remove(struct connman_service *service); -connman_bool_t __connman_service_is_provider_pending(struct connman_service *service); +void __connman_service_set_active_session(bool enable, GSList *list); +void __connman_service_auto_connect(enum connman_service_connect_reason reason); +bool __connman_service_remove(struct connman_service *service); +bool __connman_service_is_provider_pending(struct connman_service *service); void __connman_service_set_provider_pending(struct connman_service *service, DBusMessage *msg); void __connman_service_set_hidden_data(struct connman_service *service, @@ -657,9 +722,9 @@ const char *__connman_service_type2string(enum connman_service_type type); enum connman_service_type __connman_service_string2type(const char *str); int __connman_service_nameserver_append(struct connman_service *service, - const char *nameserver, gboolean is_auto); + const char *nameserver, bool is_auto); int __connman_service_nameserver_remove(struct connman_service *service, - const char *nameserver, gboolean is_auto); + const char *nameserver, bool is_auto); void __connman_service_nameserver_clear(struct connman_service *service); void __connman_service_nameserver_add_routes(struct connman_service *service, const char *gw); @@ -675,13 +740,16 @@ void __connman_service_timeserver_changed(struct connman_service *service, GSList *ts_list); void __connman_service_set_pac(struct connman_service *service, const char *pac); -connman_bool_t __connman_service_is_hidden(struct connman_service *service); -connman_bool_t __connman_service_is_split_routing(struct connman_service *service); +bool __connman_service_is_hidden(struct connman_service *service); +bool __connman_service_is_split_routing(struct connman_service *service); +bool __connman_service_index_is_split_routing(int index); int __connman_service_get_index(struct connman_service *service); void __connman_service_set_hidden(struct connman_service *service); +void __connman_service_set_hostname(struct connman_service *service, + const char *hostname); +const char *__connman_service_get_hostname(struct connman_service *service); void __connman_service_set_domainname(struct connman_service *service, const char *domainname); -const char *__connman_service_get_domainname(struct connman_service *service); const char *__connman_service_get_nameserver(struct connman_service *service); void __connman_service_set_proxy_autoconfig(struct connman_service *service, const char *url); @@ -693,8 +761,6 @@ void __connman_service_set_agent_identity(struct connman_service *service, int __connman_service_set_passphrase(struct connman_service *service, const char *passphrase); const char *__connman_service_get_passphrase(struct connman_service *service); -void __connman_service_set_agent_passphrase(struct connman_service *service, - const char *agent_passphrase); int __connman_service_reset_ipconfig(struct connman_service *service, enum connman_ipconfig_type type, DBusMessageIter *array, enum connman_service_state *new_state); @@ -708,17 +774,20 @@ void __connman_service_notify(struct connman_service *service, int __connman_service_counter_register(const char *counter); void __connman_service_counter_unregister(const char *counter); +#include <connman/peer.h> + +int __connman_peer_init(void); +void __connman_peer_cleanup(void); + +void __connman_peer_list_struct(DBusMessageIter *array); + #include <connman/session.h> typedef void (* service_iterate_cb) (struct connman_service *service, - const char *name, - enum connman_service_state state, void *user_data); int __connman_service_iterate_services(service_iterate_cb cb, void *user_data); -void __connman_service_session_inc(struct connman_service *service); -connman_bool_t __connman_service_session_dec(struct connman_service *service); void __connman_service_mark_dirty(); void __connman_service_save(struct connman_service *service); @@ -737,7 +806,7 @@ void __connman_notifier_enter_online(enum connman_service_type type); void __connman_notifier_leave_online(enum connman_service_type type); void __connman_notifier_connect(enum connman_service_type type); void __connman_notifier_disconnect(enum connman_service_type type); -void __connman_notifier_offlinemode(connman_bool_t enabled); +void __connman_notifier_offlinemode(bool enabled); void __connman_notifier_default_changed(struct connman_service *service); void __connman_notifier_proxy_changed(struct connman_service *service); void __connman_notifier_service_state_changed(struct connman_service *service, @@ -745,7 +814,7 @@ void __connman_notifier_service_state_changed(struct connman_service *service, void __connman_notifier_ipconfig_changed(struct connman_service *service, struct connman_ipconfig *ipconfig); -connman_bool_t __connman_notifier_is_connected(void); +bool __connman_notifier_is_connected(void); const char *__connman_notifier_get_state(void); #include <connman/rtnl.h> @@ -760,8 +829,7 @@ unsigned int __connman_rtnl_update_interval_remove(unsigned int interval); int __connman_rtnl_request_update(void); int __connman_rtnl_send(const void *buf, size_t len); -connman_bool_t __connman_session_mode(); -void __connman_session_set_mode(connman_bool_t enable); +bool __connman_session_policy_autoconnect(enum connman_service_connect_reason reason); int __connman_session_create(DBusMessage *msg); int __connman_session_destroy(DBusMessage *msg); @@ -786,10 +854,10 @@ void __connman_stats_cleanup(void); int __connman_stats_service_register(struct connman_service *service); void __connman_stats_service_unregister(struct connman_service *service); int __connman_stats_update(struct connman_service *service, - connman_bool_t roaming, + bool roaming, struct connman_stats_data *data); int __connman_stats_get(struct connman_service *service, - connman_bool_t roaming, + bool roaming, struct connman_stats_data *data); int __connman_iptables_dump(const char *table_name); @@ -871,8 +939,8 @@ void __connman_ippool_deladdr(int index, const char *address, int __connman_bridge_create(const char *name); int __connman_bridge_remove(const char *name); -int __connman_bridge_enable(const char *name, const char *gateway, - const char *broadcast); +int __connman_bridge_enable(const char *name, const char *ip_address, + int prefix_len, const char *broadcast); int __connman_bridge_disable(const char *name); int __connman_nat_init(void); @@ -892,6 +960,39 @@ int __connman_firewall_add_rule(struct firewall_context *ctx, const char *rule_fmt, ...); int __connman_firewall_enable(struct firewall_context *ctx); int __connman_firewall_disable(struct firewall_context *ctx); +bool __connman_firewall_is_up(void); int __connman_firewall_init(void); void __connman_firewall_cleanup(void); + +typedef int (* connman_nfacct_flush_cb_t) (unsigned int error, void *user_data); + +int __connman_nfacct_flush(connman_nfacct_flush_cb_t cb, void *user_data); + +struct nfacct_context; + +typedef void (* connman_nfacct_enable_cb_t) (unsigned int error, + struct nfacct_context *ctx, + void *user_data); +typedef void (* connman_nfacct_disable_cb_t) (unsigned int error, + struct nfacct_context *ctx, + void *user_data); +typedef void (* connman_nfacct_stats_cb_t) (struct nfacct_context *ctx, + uint64_t packets, + uint64_t bytes, + void *user_data); + +struct nfacct_context *__connman_nfacct_create_context(void); +void __connman_nfacct_destroy_context(struct nfacct_context *ctx); + +int __connman_nfacct_add(struct nfacct_context *ctx, const char *name, + connman_nfacct_stats_cb_t cb, + void *user_data); +int __connman_nfacct_enable(struct nfacct_context *ctx, + connman_nfacct_enable_cb_t cb, + void *user_data); +int __connman_nfacct_disable(struct nfacct_context *ctx, + connman_nfacct_disable_cb_t cb, + void *user_data); + +void __connman_nfacct_cleanup(void); diff --git a/src/connman.service.in b/src/connman.service.in index 2e9e4d53..7b6195e9 100644 --- a/src/connman.service.in +++ b/src/connman.service.in @@ -1,6 +1,8 @@ [Unit] Description=Connection service -After=syslog.target +Requires=dbus.socket +After=dbus.socket +Before=remote-fs.target [Service] Type=dbus diff --git a/src/counter.c b/src/counter.c index 76d91d48..06e5daff 100644 --- a/src/counter.c +++ b/src/counter.c @@ -75,11 +75,11 @@ int __connman_counter_register(const char *owner, const char *path, DBG("owner %s path %s interval %u", owner, path, interval); counter = g_hash_table_lookup(counter_table, path); - if (counter != NULL) + if (counter) return -EEXIST; counter = g_try_new0(struct connman_counter, 1); - if (counter == NULL) + if (!counter) return -ENOMEM; counter->owner = g_strdup(owner); @@ -112,7 +112,7 @@ int __connman_counter_unregister(const char *owner, const char *path) DBG("owner %s path %s", owner, path); counter = g_hash_table_lookup(counter_table, path); - if (counter == NULL) + if (!counter) return -ESRCH; if (g_strcmp0(owner, counter->owner) != 0) @@ -133,7 +133,7 @@ void __connman_counter_send_usage(const char *path, struct connman_counter *counter; counter = g_hash_table_lookup(counter_table, path); - if (counter == NULL) + if (!counter) return; dbus_message_set_destination(message, counter->owner); @@ -157,7 +157,7 @@ static void release_counter(gpointer key, gpointer value, gpointer user_data) message = dbus_message_new_method_call(counter->owner, counter->path, CONNMAN_COUNTER_INTERFACE, "Release"); - if (message == NULL) + if (!message) return; dbus_message_set_no_reply(message, TRUE); @@ -170,7 +170,7 @@ int __connman_counter_init(void) DBG(""); connection = connman_dbus_get_connection(); - if (connection == NULL) + if (!connection) return -1; counter_table = g_hash_table_new_full(g_str_hash, g_str_equal, @@ -185,7 +185,7 @@ void __connman_counter_cleanup(void) { DBG(""); - if (connection == NULL) + if (!connection) return; g_hash_table_foreach(counter_table, release_counter, NULL); @@ -33,7 +33,7 @@ dbus_bool_t connman_dbus_validate_ident(const char *ident) { unsigned int i; - if (ident == NULL) + if (!ident) return FALSE; for (i = 0; i < strlen(ident); i++) { @@ -54,13 +54,13 @@ char *connman_dbus_encode_string(const char *value) GString *str; unsigned int i, size; - if (value == NULL) + if (!value) return NULL; size = strlen(value); str = g_string_new(NULL); - if (str == NULL) + if (!str) return NULL; for (i = 0; i < size; i++) { @@ -183,11 +183,13 @@ void connman_dbus_property_append_array(DBusMessageIter *iter, switch (type) { case DBUS_TYPE_STRING: - variant_sig = DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_STRING_AS_STRING; + variant_sig = DBUS_TYPE_ARRAY_AS_STRING + DBUS_TYPE_STRING_AS_STRING; array_sig = DBUS_TYPE_STRING_AS_STRING; break; case DBUS_TYPE_OBJECT_PATH: - variant_sig = DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_OBJECT_PATH_AS_STRING; + variant_sig = DBUS_TYPE_ARRAY_AS_STRING + DBUS_TYPE_OBJECT_PATH_AS_STRING; array_sig = DBUS_TYPE_OBJECT_PATH_AS_STRING; break; case DBUS_TYPE_DICT_ENTRY: @@ -234,11 +236,11 @@ dbus_bool_t connman_dbus_property_changed_basic(const char *path, DBusMessage *signal; DBusMessageIter iter; - if (path == NULL) + if (!path) return FALSE; signal = dbus_message_new_signal(path, interface, "PropertyChanged"); - if (signal == NULL) + if (!signal) return FALSE; dbus_message_iter_init_append(signal, &iter); @@ -256,11 +258,11 @@ dbus_bool_t connman_dbus_property_changed_dict(const char *path, DBusMessage *signal; DBusMessageIter iter; - if (path == NULL) + if (!path) return FALSE; signal = dbus_message_new_signal(path, interface, "PropertyChanged"); - if (signal == NULL) + if (!signal) return FALSE; dbus_message_iter_init_append(signal, &iter); @@ -278,11 +280,11 @@ dbus_bool_t connman_dbus_property_changed_array(const char *path, DBusMessage *signal; DBusMessageIter iter; - if (path == NULL) + if (!path) return FALSE; signal = dbus_message_new_signal(path, interface, "PropertyChanged"); - if (signal == NULL) + if (!signal) return FALSE; dbus_message_iter_init_append(signal, &iter); @@ -301,13 +303,13 @@ dbus_bool_t connman_dbus_setting_changed_basic(const char *owner, DBusMessage *msg; DBusMessageIter array, dict; - if (owner == NULL || path == NULL) + if (!owner || !path) return FALSE; msg = dbus_message_new_method_call(owner, path, CONNMAN_NOTIFICATION_INTERFACE, "Update"); - if (msg == NULL) + if (!msg) return FALSE; dbus_message_iter_init_append(msg, &array); @@ -330,13 +332,13 @@ dbus_bool_t connman_dbus_setting_changed_dict(const char *owner, DBusMessage *msg; DBusMessageIter array, dict; - if (owner == NULL || path == NULL) + if (!owner || !path) return FALSE; msg = dbus_message_new_method_call(owner, path, CONNMAN_NOTIFICATION_INTERFACE, "Update"); - if (msg == NULL) + if (!msg) return FALSE; dbus_message_iter_init_append(msg, &array); @@ -359,13 +361,13 @@ dbus_bool_t connman_dbus_setting_changed_array(const char *owner, DBusMessage *msg; DBusMessageIter array, dict; - if (owner == NULL || path == NULL) + if (!owner || !path) return FALSE; msg = dbus_message_new_method_call(owner, path, CONNMAN_NOTIFICATION_INTERFACE, "Update"); - if (msg == NULL) + if (!msg) return FALSE; dbus_message_iter_init_append(msg, &array); @@ -385,7 +387,7 @@ dbus_bool_t __connman_dbus_append_objpath_dict_array(DBusMessage *msg, { DBusMessageIter iter, array; - if (msg == NULL || function == NULL) + if (!msg || !function) return FALSE; dbus_message_iter_init_append(msg, &iter); @@ -406,6 +408,25 @@ dbus_bool_t __connman_dbus_append_objpath_dict_array(DBusMessage *msg, return TRUE; } +dbus_bool_t __connman_dbus_append_objpath_array(DBusMessage *msg, + connman_dbus_append_cb_t function, void *user_data) +{ + DBusMessageIter iter, array; + + if (!msg || !function) + return FALSE; + + dbus_message_iter_init_append(msg, &iter); + dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, + DBUS_TYPE_OBJECT_PATH_AS_STRING, &array); + + function(&array, user_data); + + dbus_message_iter_close_container(&iter, &array); + + return TRUE; +} + struct callback_data { void *cb; void *user_data; @@ -419,7 +440,7 @@ static void get_connection_unix_user_reply(DBusPendingCall *call, DBusMessageIter iter; DBusMessage *reply; int err = 0; - unsigned int uid; + unsigned int uid = 0; reply = dbus_pending_call_steal_reply(call); @@ -429,7 +450,7 @@ static void get_connection_unix_user_reply(DBusPendingCall *call, goto done; } - if (dbus_message_has_signature(reply, "u") == FALSE) { + if (!dbus_message_has_signature(reply, "u")) { DBG("Message signature is wrong"); err = -EINVAL; goto done; @@ -457,7 +478,7 @@ int connman_dbus_get_connection_unix_user(DBusConnection *connection, int err; data = g_try_new0(struct callback_data, 1); - if (data == NULL) { + if (!data) { DBG("Can't allocate data structure"); return -ENOMEM; } @@ -465,7 +486,7 @@ int connman_dbus_get_connection_unix_user(DBusConnection *connection, msg = dbus_message_new_method_call(DBUS_SERVICE_DBUS, DBUS_PATH_DBUS, DBUS_INTERFACE_DBUS, "GetConnectionUnixUser"); - if (msg == NULL) { + if (!msg) { DBG("Can't allocate new message"); err = -ENOMEM; goto err; @@ -474,14 +495,13 @@ int connman_dbus_get_connection_unix_user(DBusConnection *connection, dbus_message_append_args(msg, DBUS_TYPE_STRING, &bus_name, DBUS_TYPE_INVALID); - if (dbus_connection_send_with_reply(connection, msg, - &call, -1) == FALSE) { + if (!dbus_connection_send_with_reply(connection, msg, &call, -1)) { DBG("Failed to execute method call"); err = -EINVAL; goto err; } - if (call == NULL) { + if (!call) { DBG("D-Bus connection not available"); err = -EINVAL; goto err; @@ -522,7 +542,7 @@ static unsigned char *parse_context(DBusMessage *msg) return NULL; ctx = g_try_malloc0(size + 1); - if (ctx == NULL) + if (!ctx) return NULL; p = ctx; @@ -555,7 +575,7 @@ static void selinux_get_context_reply(DBusPendingCall *call, void *user_data) goto done; } - if (dbus_message_has_signature(reply, "ay") == FALSE) { + if (!dbus_message_has_signature(reply, "ay")) { DBG("Message signature is wrong"); err = -EINVAL; goto done; @@ -583,11 +603,11 @@ int connman_dbus_get_selinux_context(DBusConnection *connection, DBusMessage *msg = NULL; int err; - if (func == NULL) + if (!func) return -EINVAL; data = g_try_new0(struct callback_data, 1); - if (data == NULL) { + if (!data) { DBG("Can't allocate data structure"); return -ENOMEM; } @@ -595,7 +615,7 @@ int connman_dbus_get_selinux_context(DBusConnection *connection, msg = dbus_message_new_method_call(DBUS_SERVICE_DBUS, DBUS_PATH_DBUS, DBUS_INTERFACE_DBUS, "GetConnectionSELinuxSecurityContext"); - if (msg == NULL) { + if (!msg) { DBG("Can't allocate new message"); err = -ENOMEM; goto err; @@ -604,14 +624,13 @@ int connman_dbus_get_selinux_context(DBusConnection *connection, dbus_message_append_args(msg, DBUS_TYPE_STRING, &service, DBUS_TYPE_INVALID); - if (dbus_connection_send_with_reply(connection, msg, - &call, -1) == FALSE) { + if (!dbus_connection_send_with_reply(connection, msg, &call, -1)) { DBG("Failed to execute method call"); err = -EINVAL; goto err; } - if (call == NULL) { + if (!call) { DBG("D-Bus connection not available"); err = -EINVAL; goto err; @@ -636,7 +655,7 @@ err: DBusConnection *connman_dbus_get_connection(void) { - if (connection == NULL) + if (!connection) return NULL; return dbus_connection_ref(connection); diff --git a/src/detect.c b/src/detect.c index 5bf44af1..6c039206 100644 --- a/src/detect.c +++ b/src/detect.c @@ -2,7 +2,7 @@ * * Connection Manager * - * Copyright (C) 2007-2012 Intel Corporation. All rights reserved. + * Copyright (C) 2007-2013 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 @@ -67,11 +67,11 @@ static void detect_newlink(unsigned short type, int index, } device = find_device(index); - if (device != NULL) + if (device) return; device = connman_device_create_from_index(index); - if (device == NULL) + if (!device) return; if (connman_device_register(device) < 0) { @@ -90,7 +90,7 @@ static void detect_dellink(unsigned short type, int index, DBG("type %d index %d", type, index); device = find_device(index); - if (device == NULL) + if (!device) return; device_list = g_slist_remove(device_list, device); diff --git a/src/device.c b/src/device.c index 5feeee12..a97d790e 100644 --- a/src/device.c +++ b/src/device.c @@ -2,7 +2,7 @@ * * Connection Manager * - * Copyright (C) 2007-2012 Intel Corporation. All rights reserved. + * Copyright (C) 2007-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 @@ -48,18 +48,18 @@ struct connman_device { int refcount; enum connman_device_type type; enum connman_pending_type powered_pending; /* Indicates a pending - enable/disable request */ - connman_bool_t powered; - connman_bool_t scanning; - connman_bool_t disconnected; - connman_bool_t reconnect; + * enable/disable + * request + */ + bool powered; + bool scanning; + bool disconnected; char *name; char *node; char *address; char *interface; char *ident; char *path; - char *devname; int index; guint pending_timeout; @@ -127,7 +127,8 @@ static const char *type2string(enum connman_device_type type) return NULL; } -enum connman_service_type __connman_device_get_service_type(struct connman_device *device) +enum connman_service_type __connman_device_get_service_type( + struct connman_device *device) { enum connman_device_type type = connman_device_get_type(device); @@ -181,7 +182,7 @@ int __connman_device_enable(struct connman_device *device) if (device->powered_pending == PENDING_ENABLE) return -EALREADY; - if (device->powered_pending == PENDING_NONE && device->powered == TRUE) + if (device->powered_pending == PENDING_NONE && device->powered) return -EALREADY; device->powered_pending = PENDING_ENABLE; @@ -192,13 +193,13 @@ int __connman_device_enable(struct connman_device *device) * Invoke the callback */ if (err == 0) { - connman_device_set_powered(device, TRUE); + connman_device_set_powered(device, true); goto done; } if (err == -EALREADY) { /* If device is already powered, but connman is not updated */ - connman_device_set_powered(device, TRUE); + connman_device_set_powered(device, true); goto done; } /* @@ -219,9 +220,6 @@ int __connman_device_disable(struct connman_device *device) DBG("device %p", device); - if (!device->driver || !device->driver->disable) - return -EOPNOTSUPP; - /* Ongoing power enable request */ if (device->powered_pending == PENDING_ENABLE) return -EBUSY; @@ -229,25 +227,27 @@ int __connman_device_disable(struct connman_device *device) if (device->powered_pending == PENDING_DISABLE) return -EALREADY; - if (device->powered_pending == PENDING_NONE && device->powered == FALSE) + if (device->powered_pending == PENDING_NONE && !device->powered) return -EALREADY; device->powered_pending = PENDING_DISABLE; - device->reconnect = FALSE; if (device->network) { struct connman_service *service = connman_service_lookup_from_network(device->network); - if (service != NULL) + if (service) __connman_service_disconnect(service); else - connman_network_set_connected(device->network, FALSE); + connman_network_set_connected(device->network, false); } + if (!device->driver || !device->driver->disable) + return -EOPNOTSUPP; + err = device->driver->disable(device); if (err == 0 || err == -EALREADY) { - connman_device_set_powered(device, FALSE); + connman_device_set_powered(device, false); goto done; } @@ -264,10 +264,10 @@ static void probe_driver(struct connman_device_driver *driver) DBG("driver %p name %s", driver, driver->name); - for (list = device_list; list != NULL; list = list->next) { + for (list = device_list; list; list = list->next) { struct connman_device *device = list->data; - if (device->driver != NULL) + if (device->driver) continue; if (driver->type != device->type) @@ -302,7 +302,7 @@ static void remove_driver(struct connman_device_driver *driver) DBG("driver %p name %s", driver, driver->name); - for (list = device_list; list != NULL; list = list->next) { + for (list = device_list; list; list = list->next) { struct connman_device *device = list->data; if (device->driver == driver) @@ -310,12 +310,12 @@ static void remove_driver(struct connman_device_driver *driver) } } -connman_bool_t __connman_device_has_driver(struct connman_device *device) +bool __connman_device_has_driver(struct connman_device *device) { - if (device == NULL || device->driver == NULL) - return FALSE; + if (!device || !device->driver) + return false; - return TRUE; + return true; } static GSList *driver_list = NULL; @@ -385,7 +385,6 @@ static void device_destruct(struct connman_device *device) g_free(device->address); g_free(device->interface); g_free(device->path); - g_free(device->devname); g_free(device->last_network); @@ -412,7 +411,7 @@ struct connman_device *connman_device_create(const char *node, DBG("node %s type %d", node, type); device = g_try_new0(struct connman_device, 1); - if (device == NULL) + if (!device) return NULL; DBG("device %p", device); @@ -521,15 +520,12 @@ int connman_device_get_index(struct connman_device *device) void connman_device_set_interface(struct connman_device *device, const char *interface) { - g_free(device->devname); - device->devname = g_strdup(interface); - g_free(device->interface); device->interface = g_strdup(interface); - if (device->name == NULL) { + if (!device->name) { const char *str = type2description(device->type); - if (str != NULL && device->interface != NULL) + if (str && device->interface) device->name = g_strdup_printf("%s (%s)", str, device->interface); } @@ -562,7 +558,7 @@ const char *connman_device_get_ident(struct connman_device *device) * Change power state of device */ int connman_device_set_powered(struct connman_device *device, - connman_bool_t powered) + bool powered) { enum connman_service_type type; @@ -579,36 +575,39 @@ int connman_device_set_powered(struct connman_device *device, type = __connman_device_get_service_type(device); - if (device->powered == FALSE) { + if (!device->powered) { __connman_technology_disabled(type); return 0; } __connman_technology_enabled(type); - connman_device_set_disconnected(device, FALSE); - device->scanning = FALSE; + connman_device_set_disconnected(device, false); + device->scanning = false; if (device->driver && device->driver->scan) - device->driver->scan(device, NULL, 0, NULL, NULL, NULL); + device->driver->scan(CONNMAN_SERVICE_TYPE_UNKNOWN, device, + NULL, 0, NULL, NULL, NULL, NULL); return 0; } -connman_bool_t connman_device_get_powered(struct connman_device *device) +bool connman_device_get_powered(struct connman_device *device) { return device->powered; } -static int device_scan(struct connman_device *device) +static int device_scan(enum connman_service_type type, + struct connman_device *device) { if (!device->driver || !device->driver->scan) return -EOPNOTSUPP; - if (device->powered == FALSE) + if (!device->powered) return -ENOLINK; - return device->driver->scan(device, NULL, 0, NULL, NULL, NULL); + return device->driver->scan(type, device, NULL, 0, + NULL, NULL, NULL, NULL); } int __connman_device_disconnect(struct connman_device *device) @@ -618,14 +617,14 @@ int __connman_device_disconnect(struct connman_device *device) DBG("device %p", device); - connman_device_set_disconnected(device, TRUE); + connman_device_set_disconnected(device, true); g_hash_table_iter_init(&iter, device->networks); - while (g_hash_table_iter_next(&iter, &key, &value) == TRUE) { + while (g_hash_table_iter_next(&iter, &key, &value)) { struct connman_network *network = value; - if (connman_network_get_connecting(network) == TRUE) { + if (connman_network_get_connecting(network)) { /* * Skip network in the process of connecting. * This is a workaround for WiFi networks serviced @@ -647,32 +646,11 @@ int __connman_device_disconnect(struct connman_device *device) return 0; } -int connman_device_disconnect_service(struct connman_device *device) -{ - DBG("device %p", device); - - device->reconnect = FALSE; - - if (device->network) { - struct connman_service *service = - connman_service_lookup_from_network(device->network); - - if (service != NULL) - __connman_service_disconnect(service); - else - connman_network_set_connected(device->network, FALSE); - } - - return 0; -} - int connman_device_reconnect_service(struct connman_device *device) { DBG("device %p", device); - device->reconnect = TRUE; - - __connman_service_auto_connect(); + __connman_service_auto_connect(CONNMAN_SERVICE_CONNECT_REASON_AUTO); return 0; } @@ -682,7 +660,7 @@ static void mark_network_available(gpointer key, gpointer value, { struct connman_network *network = value; - connman_network_set_available(network, TRUE); + connman_network_set_available(network, true); } static void mark_network_unavailable(gpointer key, gpointer value, @@ -690,11 +668,11 @@ static void mark_network_unavailable(gpointer key, gpointer value, { struct connman_network *network = value; - if (connman_network_get_connected(network) == TRUE || - connman_network_get_connecting(network) == TRUE) + if (connman_network_get_connected(network) || + connman_network_get_connecting(network)) return; - connman_network_set_available(network, FALSE); + connman_network_set_available(network, false); } static gboolean remove_unavailable_network(gpointer key, gpointer value, @@ -702,10 +680,10 @@ static gboolean remove_unavailable_network(gpointer key, gpointer value, { struct connman_network *network = value; - if (connman_network_get_connected(network) == TRUE) + if (connman_network_get_connected(network)) return FALSE; - if (connman_network_get_available(network) == TRUE) + if (connman_network_get_available(network)) return FALSE; return TRUE; @@ -717,7 +695,7 @@ void __connman_device_cleanup_networks(struct connman_device *device) remove_unavailable_network, NULL); } -connman_bool_t connman_device_get_scanning(struct connman_device *device) +bool connman_device_get_scanning(struct connman_device *device) { return device->scanning; } @@ -736,7 +714,7 @@ void connman_device_reset_scanning(struct connman_device *device) * Change scanning state of device */ int connman_device_set_scanning(struct connman_device *device, - connman_bool_t scanning) + enum connman_service_type type, bool scanning) { DBG("device %p scanning %d", device, scanning); @@ -748,7 +726,7 @@ int connman_device_set_scanning(struct connman_device *device, device->scanning = scanning; - if (scanning == TRUE) { + if (scanning) { __connman_technology_scan_started(device); g_hash_table_foreach(device->networks, @@ -759,9 +737,9 @@ int connman_device_set_scanning(struct connman_device *device, __connman_device_cleanup_networks(device); - __connman_technology_scan_stopped(device); + __connman_technology_scan_stopped(device, type); - __connman_service_auto_connect(); + __connman_service_auto_connect(CONNMAN_SERVICE_CONNECT_REASON_AUTO); return 0; } @@ -774,7 +752,7 @@ int connman_device_set_scanning(struct connman_device *device, * Change disconnected state of device (only for device with networks) */ int connman_device_set_disconnected(struct connman_device *device, - connman_bool_t disconnected) + bool disconnected) { DBG("device %p disconnected %d", device, disconnected); @@ -792,7 +770,7 @@ int connman_device_set_disconnected(struct connman_device *device, * * Get device disconnected state */ -connman_bool_t connman_device_get_disconnected(struct connman_device *device) +bool connman_device_get_disconnected(struct connman_device *device) { return device->disconnected; } @@ -810,16 +788,16 @@ int connman_device_set_string(struct connman_device *device, { DBG("device %p key %s value %s", device, key, value); - if (g_str_equal(key, "Address") == TRUE) { + if (g_str_equal(key, "Address")) { g_free(device->address); device->address = g_strdup(value); - } else if (g_str_equal(key, "Name") == TRUE) { + } else if (g_str_equal(key, "Name")) { g_free(device->name); device->name = g_strdup(value); - } else if (g_str_equal(key, "Node") == TRUE) { + } else if (g_str_equal(key, "Node")) { g_free(device->node); device->node = g_strdup(value); - } else if (g_str_equal(key, "Path") == TRUE) { + } else if (g_str_equal(key, "Path")) { g_free(device->path); device->path = g_strdup(value); } else { @@ -841,15 +819,15 @@ const char *connman_device_get_string(struct connman_device *device, { DBG("device %p key %s", device, key); - if (g_str_equal(key, "Address") == TRUE) + if (g_str_equal(key, "Address")) return device->address; - else if (g_str_equal(key, "Name") == TRUE) + else if (g_str_equal(key, "Name")) return device->name; - else if (g_str_equal(key, "Node") == TRUE) + else if (g_str_equal(key, "Node")) return device->node; - else if (g_str_equal(key, "Interface") == TRUE) + else if (g_str_equal(key, "Interface")) return device->interface; - else if (g_str_equal(key, "Path") == TRUE) + else if (g_str_equal(key, "Path")) return device->path; return NULL; @@ -869,7 +847,7 @@ int connman_device_add_network(struct connman_device *device, DBG("device %p network %p", device, network); - if (identifier == NULL) + if (!identifier) return -EINVAL; connman_network_ref(network); @@ -911,7 +889,7 @@ int connman_device_remove_network(struct connman_device *device, DBG("device %p network %p", device, network); - if (network == NULL) + if (!network) return 0; identifier = connman_network_get_identifier(network); @@ -920,23 +898,18 @@ int connman_device_remove_network(struct connman_device *device, return 0; } -void connman_device_remove_all_networks(struct connman_device *device) -{ - g_hash_table_remove_all(device->networks); -} - void __connman_device_set_network(struct connman_device *device, struct connman_network *network) { const char *name; - if (device == NULL) + if (!device) return; if (device->network == network) return; - if (network != NULL) { + if (network) { name = connman_network_get_string(network, "Name"); g_free(device->last_network); device->last_network = g_strdup(name); @@ -950,26 +923,14 @@ void __connman_device_set_network(struct connman_device *device, } } -void __connman_device_set_reconnect(struct connman_device *device, - connman_bool_t reconnect) -{ - device->reconnect = reconnect; -} - -connman_bool_t __connman_device_get_reconnect( - struct connman_device *device) -{ - return device->reconnect; -} - -static gboolean match_driver(struct connman_device *device, +static bool match_driver(struct connman_device *device, struct connman_device_driver *driver) { if (device->type == driver->type || driver->type == CONNMAN_DEVICE_TYPE_UNKNOWN) - return TRUE; + return true; - return FALSE; + return false; } /** @@ -984,13 +945,13 @@ int connman_device_register(struct connman_device *device) DBG("device %p name %s", device, device->name); - if (device->driver != NULL) + if (device->driver) return -EALREADY; for (list = driver_list; list; list = list->next) { struct connman_device_driver *driver = list->data; - if (match_driver(device, driver) == FALSE) + if (!match_driver(device, driver)) continue; DBG("driver %p name %s", driver, driver->name); @@ -1001,7 +962,7 @@ int connman_device_register(struct connman_device *device) } } - if (device->driver == NULL) + if (!device->driver) return 0; return __connman_technology_add_device(device); @@ -1017,7 +978,7 @@ void connman_device_unregister(struct connman_device *device) { DBG("device %p name %s", device, device->name); - if (device->driver == NULL) + if (!device->driver) return; remove_device(device); @@ -1051,7 +1012,7 @@ struct connman_device *__connman_device_find_device( { GSList *list; - for (list = device_list; list != NULL; list = list->next) { + for (list = device_list; list; list = list->next) { struct connman_device *device = list->data; enum connman_service_type service_type = __connman_device_get_service_type(device); @@ -1069,7 +1030,7 @@ struct connman_device *connman_device_find_by_index(int index) { GSList *list; - for (list = device_list; list != NULL; list = list->next) { + for (list = device_list; list; list = list->next) { struct connman_device *device = list->data; if (device->index == index) return device; @@ -1088,10 +1049,10 @@ struct connman_device *connman_device_find_by_index(int index) int connman_device_set_regdom(struct connman_device *device, const char *alpha2) { - if (device->driver == NULL || device->driver->set_regdom == NULL) + if (!device->driver || !device->driver->set_regdom) return -ENOTSUP; - if (device->powered == FALSE) + if (!device->powered) return -EINVAL; return device->driver->set_regdom(device, alpha2); @@ -1112,7 +1073,7 @@ void connman_device_regdom_notify(struct connman_device *device, int __connman_device_request_scan(enum connman_service_type type) { - connman_bool_t success = FALSE; + bool success = false; int last_err = -ENOSYS; GSList *list; int err; @@ -1128,29 +1089,33 @@ int __connman_device_request_scan(enum connman_service_type type) case CONNMAN_SERVICE_TYPE_GADGET: return -EOPNOTSUPP; case CONNMAN_SERVICE_TYPE_WIFI: + case CONNMAN_SERVICE_TYPE_P2P: break; } - for (list = device_list; list != NULL; list = list->next) { + for (list = device_list; list; list = list->next) { struct connman_device *device = list->data; enum connman_service_type service_type = __connman_device_get_service_type(device); - if (service_type != CONNMAN_SERVICE_TYPE_UNKNOWN && - service_type != type) { - continue; + if (service_type != CONNMAN_SERVICE_TYPE_UNKNOWN) { + if (type == CONNMAN_SERVICE_TYPE_P2P) { + if (service_type != CONNMAN_SERVICE_TYPE_WIFI) + continue; + } else if (service_type != type) + continue; } - err = device_scan(device); + err = device_scan(type, device); if (err == 0 || err == -EALREADY || err == -EINPROGRESS) { - success = TRUE; + success = true; } else { last_err = err; DBG("device %p err %d", device, err); } } - if (success == TRUE) + if (success) return 0; return last_err; @@ -1159,19 +1124,17 @@ int __connman_device_request_scan(enum connman_service_type type) int __connman_device_request_hidden_scan(struct connman_device *device, const char *ssid, unsigned int ssid_len, const char *identity, const char *passphrase, - void *user_data) + const char *security, void *user_data) { DBG("device %p", device); - if (device == NULL || device->driver == NULL || - device->driver->scan == NULL) + if (!device || !device->driver || + !device->driver->scan) return -EINVAL; - if (device->scanning == TRUE) - return -EALREADY; - - return device->driver->scan(device, ssid, ssid_len, - identity, passphrase, user_data); + return device->driver->scan(CONNMAN_SERVICE_TYPE_UNKNOWN, + device, ssid, ssid_len, identity, + passphrase, security, user_data); } static char *index2ident(int index, const char *prefix) @@ -1274,10 +1237,10 @@ struct connman_device *connman_device_create_from_index(int index) return NULL; devname = connman_inet_ifname(index); - if (devname == NULL) + if (!devname) return NULL; - if (__connman_device_isfiltered(devname) == TRUE) { + if (__connman_device_isfiltered(devname)) { connman_info("Ignoring interface %s (filtered)", devname); g_free(devname); return NULL; @@ -1305,7 +1268,7 @@ struct connman_device *connman_device_create_from_index(int index) } device = connman_device_create(name, type); - if (device == NULL) + if (!device) goto done; switch (type) { @@ -1330,7 +1293,7 @@ struct connman_device *connman_device_create_from_index(int index) connman_device_set_index(device, index); connman_device_set_interface(device, devname); - if (ident != NULL) { + if (ident) { connman_device_set_ident(device, ident); g_free(ident); } @@ -1345,57 +1308,57 @@ done: return device; } -connman_bool_t __connman_device_isfiltered(const char *devname) +bool __connman_device_isfiltered(const char *devname) { char **pattern; char **blacklisted_interfaces; - gboolean match; + bool match; - if (device_filter == NULL) + if (!device_filter) goto nodevice; - for (pattern = device_filter, match = FALSE; *pattern; pattern++) { - if (g_pattern_match_simple(*pattern, devname) == TRUE) { - match = TRUE; + for (pattern = device_filter, match = false; *pattern; pattern++) { + if (g_pattern_match_simple(*pattern, devname)) { + match = true; break; } } - if (match == FALSE) { + if (!match) { DBG("ignoring device %s (match)", devname); - return TRUE; + return true; } nodevice: - if (g_pattern_match_simple("dummy*", devname) == TRUE) { + if (g_pattern_match_simple("dummy*", devname)) { DBG("ignoring dummy networking devices"); - return TRUE; + return true; } - if (nodevice_filter == NULL) + if (!nodevice_filter) goto list; for (pattern = nodevice_filter; *pattern; pattern++) { - if (g_pattern_match_simple(*pattern, devname) == TRUE) { + if (g_pattern_match_simple(*pattern, devname)) { DBG("ignoring device %s (no match)", devname); - return TRUE; + return true; } } list: blacklisted_interfaces = connman_setting_get_string_list("NetworkInterfaceBlacklist"); - if (blacklisted_interfaces == NULL) - return FALSE; + if (!blacklisted_interfaces) + return false; for (pattern = blacklisted_interfaces; *pattern; pattern++) { - if (g_str_has_prefix(devname, *pattern) == TRUE) { + if (g_str_has_prefix(devname, *pattern)) { DBG("ignoring device %s (blacklist)", devname); - return TRUE; + return true; } } - return FALSE; + return false; } static void cleanup_devices(void) @@ -1418,21 +1381,41 @@ static void cleanup_devices(void) interfaces = __connman_inet_get_running_interfaces(); - if (interfaces == NULL) + if (!interfaces) return; - for (i = 0; interfaces[i] != NULL; i++) { - connman_bool_t filtered; + for (i = 0; interfaces[i]; i++) { + bool filtered; int index; + struct sockaddr_in sin_addr, sin_mask; filtered = __connman_device_isfiltered(interfaces[i]); - if (filtered == TRUE) + if (filtered) continue; index = connman_inet_ifindex(interfaces[i]); if (index < 0) continue; + if (!__connman_inet_get_address_netmask(index, &sin_addr, + &sin_mask)) { + char *address = g_strdup(inet_ntoa(sin_addr.sin_addr)); + char *netmask = g_strdup(inet_ntoa(sin_mask.sin_addr)); + + if (__connman_config_address_provisioned(address, + netmask)) { + DBG("Skip %s which is already provisioned " + "with %s/%s", interfaces[i], address, + netmask); + g_free(address); + g_free(netmask); + continue; + } + + g_free(address); + g_free(netmask); + } + DBG("cleaning up %s index %d", interfaces[i], index); connman_inet_ifdown(index); @@ -1450,10 +1433,10 @@ int __connman_device_init(const char *device, const char *nodevice) { DBG(""); - if (device != NULL) + if (device) device_filter = g_strsplit(device, ",", -1); - if (nodevice != NULL) + if (nodevice) nodevice_filter = g_strsplit(nodevice, ",", -1); cleanup_devices(); @@ -2,7 +2,7 @@ * * Connection Manager * - * Copyright (C) 2007-2012 Intel Corporation. All rights reserved. + * Copyright (C) 2007-2013 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 @@ -36,6 +36,8 @@ #include "connman.h" +#define RATE_LIMIT_INTERVAL 60 /* delay between successive attempts */ + struct connman_dhcp { struct connman_network *network; dhcp_cb callback; @@ -44,10 +46,16 @@ struct connman_dhcp { char **timeservers; char *pac; + unsigned int timeout; + + GDHCPClient *ipv4ll_client; GDHCPClient *dhcp_client; + char *ipv4ll_debug_prefix; + char *dhcp_debug_prefix; }; static GHashTable *network_table; +static bool ipv4ll_running; static void dhcp_free(struct connman_dhcp *dhcp) { @@ -58,6 +66,8 @@ static void dhcp_free(struct connman_dhcp *dhcp) dhcp->nameservers = NULL; dhcp->timeservers = NULL; dhcp->pac = NULL; + + g_free(dhcp); } /** @@ -72,7 +82,7 @@ static void dhcp_free(struct connman_dhcp *dhcp) * service state due to the IP configuration change implied by this * invalidation. */ -static void dhcp_invalidate(struct connman_dhcp *dhcp, connman_bool_t callback) +static void dhcp_invalidate(struct connman_dhcp *dhcp, bool callback) { struct connman_service *service; struct connman_ipconfig *ipconfig; @@ -80,33 +90,33 @@ static void dhcp_invalidate(struct connman_dhcp *dhcp, connman_bool_t callback) DBG("dhcp %p callback %u", dhcp, callback); - if (dhcp == NULL) + if (!dhcp) return; service = connman_service_lookup_from_network(dhcp->network); - if (service == NULL) - goto out; + if (!service) + return; ipconfig = __connman_service_get_ip4config(service); - if (ipconfig == NULL) - goto out; + if (!ipconfig) + return; __connman_6to4_remove(ipconfig); __connman_service_set_domainname(service, NULL); __connman_service_set_pac(service, NULL); - if (dhcp->timeservers != NULL) { - for (i = 0; dhcp->timeservers[i] != NULL; i++) { + if (dhcp->timeservers) { + for (i = 0; dhcp->timeservers[i]; i++) { __connman_service_timeserver_remove(service, dhcp->timeservers[i]); } } - if (dhcp->nameservers != NULL) { - for (i = 0; dhcp->nameservers[i] != NULL; i++) { + if (dhcp->nameservers) { + for (i = 0; dhcp->nameservers[i]; i++) { __connman_service_nameserver_remove(service, - dhcp->nameservers[i], FALSE); + dhcp->nameservers[i], false); } } @@ -121,26 +131,125 @@ static void dhcp_invalidate(struct connman_dhcp *dhcp, connman_bool_t callback) __connman_ipconfig_set_gateway(ipconfig, NULL); __connman_ipconfig_set_prefixlen(ipconfig, 0); - if (dhcp->callback != NULL && callback) - dhcp->callback(dhcp->network, FALSE); - -out: - dhcp_free(dhcp); + if (dhcp->callback && callback) + dhcp->callback(dhcp->network, false, NULL); } static void dhcp_valid(struct connman_dhcp *dhcp) { - if (dhcp->callback != NULL) - dhcp->callback(dhcp->network, TRUE); + if (dhcp->callback) + dhcp->callback(dhcp->network, true, NULL); +} + +static void dhcp_debug(const char *str, void *data) +{ + connman_info("%s: %s", (const char *) data, str); +} + +static void ipv4ll_stop_client(struct connman_dhcp *dhcp) +{ + if (!dhcp->ipv4ll_client) + return; + + g_dhcp_client_stop(dhcp->ipv4ll_client); + g_dhcp_client_unref(dhcp->ipv4ll_client); + dhcp->ipv4ll_client = NULL; + ipv4ll_running = false; + + g_free(dhcp->ipv4ll_debug_prefix); + dhcp->ipv4ll_debug_prefix = NULL; +} + +static void ipv4ll_lost_cb(GDHCPClient *dhcp_client, gpointer user_data); +static void ipv4ll_available_cb(GDHCPClient *ipv4ll_client, gpointer user_data); + +static int ipv4ll_start_client(struct connman_dhcp *dhcp) +{ + GDHCPClient *ipv4ll_client; + GDHCPClientError error; + const char *hostname; + int index; + int err; + + if (dhcp->ipv4ll_client) + return -EALREADY; + + index = connman_network_get_index(dhcp->network); + + ipv4ll_client = g_dhcp_client_new(G_DHCP_IPV4LL, index, &error); + if (error != G_DHCP_CLIENT_ERROR_NONE) + return -EINVAL; + + if (getenv("CONNMAN_DHCP_DEBUG")) { + dhcp->ipv4ll_debug_prefix = g_strdup_printf("IPv4LL index %d", + index); + g_dhcp_client_set_debug(ipv4ll_client, dhcp_debug, + dhcp->ipv4ll_debug_prefix); + } + + g_dhcp_client_set_id(ipv4ll_client); + + hostname = connman_utsname_get_hostname(); + if (hostname) + g_dhcp_client_set_send(ipv4ll_client, G_DHCP_HOST_NAME, + hostname); + + g_dhcp_client_register_event(ipv4ll_client, + G_DHCP_CLIENT_EVENT_IPV4LL_LOST, ipv4ll_lost_cb, dhcp); + + g_dhcp_client_register_event(ipv4ll_client, + G_DHCP_CLIENT_EVENT_IPV4LL_AVAILABLE, + ipv4ll_available_cb, dhcp); + + dhcp->ipv4ll_client = ipv4ll_client; + + err = g_dhcp_client_start(dhcp->ipv4ll_client, NULL); + if (err < 0) { + ipv4ll_stop_client(dhcp); + return err; + } + + ipv4ll_running = true; + return 0; +} + +static gboolean dhcp_retry_cb(gpointer user_data) +{ + struct connman_dhcp *dhcp = user_data; + struct connman_service *service; + struct connman_ipconfig *ipconfig; + + dhcp->timeout = 0; + + service = connman_service_lookup_from_network(dhcp->network); + ipconfig = __connman_service_get_ip4config(service); + + g_dhcp_client_start(dhcp->dhcp_client, + __connman_ipconfig_get_dhcp_address(ipconfig)); + + return FALSE; } static void no_lease_cb(GDHCPClient *dhcp_client, gpointer user_data) { struct connman_dhcp *dhcp = user_data; + int err; - DBG("No lease available"); + DBG("No lease available ipv4ll %d client %p", ipv4ll_running, + dhcp->ipv4ll_client); - dhcp_invalidate(dhcp, TRUE); + dhcp->timeout = g_timeout_add_seconds(RATE_LIMIT_INTERVAL, + dhcp_retry_cb, + dhcp); + if (ipv4ll_running) + return; + + err = ipv4ll_start_client(dhcp); + if (err < 0) + DBG("Cannot start ipv4ll client (%d/%s)", err, strerror(-err)); + + /* Only notify upper layer if we have a problem */ + dhcp_invalidate(dhcp, !ipv4ll_running); } static void lease_lost_cb(GDHCPClient *dhcp_client, gpointer user_data) @@ -149,7 +258,8 @@ static void lease_lost_cb(GDHCPClient *dhcp_client, gpointer user_data) DBG("Lease lost"); - dhcp_invalidate(dhcp, TRUE); + /* Upper layer will decide what to do, e.g. nothing or retry. */ + dhcp_invalidate(dhcp, true); } static void ipv4ll_lost_cb(GDHCPClient *dhcp_client, gpointer user_data) @@ -158,27 +268,32 @@ static void ipv4ll_lost_cb(GDHCPClient *dhcp_client, gpointer user_data) DBG("Lease lost"); - dhcp_invalidate(dhcp, TRUE); -} + ipv4ll_stop_client(dhcp); + /* + * Since we lost our IPv4LL configuration we might as notify + * the upper layers. + */ + dhcp_invalidate(dhcp, true); +} -static gboolean compare_string_arrays(char **array_a, char **array_b) +static bool compare_string_arrays(char **array_a, char **array_b) { int i; - if (array_a == NULL || array_b == NULL) - return FALSE; + if (!array_a || !array_b) + return false; if (g_strv_length(array_a) != g_strv_length(array_b)) - return FALSE; + return false; - for (i = 0; array_a[i] != NULL && - array_b[i] != NULL; i++) { + for (i = 0; array_a[i] && + array_b[i]; i++) { if (g_strcmp0(array_a[i], array_b[i]) != 0) - return FALSE; + return false; } - return TRUE; + return true; } static void lease_available_cb(GDHCPClient *dhcp_client, gpointer user_data) @@ -187,25 +302,29 @@ static void lease_available_cb(GDHCPClient *dhcp_client, gpointer user_data) GList *list, *option = NULL; char *address, *netmask = NULL, *gateway = NULL; const char *c_address, *c_gateway; - char *domainname = NULL, *hostname = NULL; char **nameservers, **timeservers, *pac = NULL; int ns_entries; struct connman_ipconfig *ipconfig; struct connman_service *service; unsigned char prefixlen, c_prefixlen; - gboolean ip_change; + bool ip_change; int i; DBG("Lease available"); + if (dhcp->ipv4ll_client) { + ipv4ll_stop_client(dhcp); + dhcp_invalidate(dhcp, false); + } + service = connman_service_lookup_from_network(dhcp->network); - if (service == NULL) { + if (!service) { connman_error("Can not lookup service"); return; } ipconfig = __connman_service_get_ip4config(service); - if (ipconfig == NULL) { + if (!ipconfig) { connman_error("Could not lookup ipconfig"); return; } @@ -220,11 +339,11 @@ static void lease_available_cb(GDHCPClient *dhcp_client, gpointer user_data) DBG("last address %s", address); option = g_dhcp_client_get_option(dhcp_client, G_DHCP_SUBNET); - if (option != NULL) + if (option) netmask = g_strdup(option->data); option = g_dhcp_client_get_option(dhcp_client, G_DHCP_ROUTER); - if (option != NULL) + if (option) gateway = g_strdup(option->data); prefixlen = __connman_ipaddress_netmask_prefix_len(netmask); @@ -233,83 +352,78 @@ static void lease_available_cb(GDHCPClient *dhcp_client, gpointer user_data) DBG("c_address %s", c_address); - if (address != NULL && c_address != NULL && - g_strcmp0(address, c_address) != 0) - ip_change = TRUE; - else if (gateway != NULL && c_gateway != NULL && - g_strcmp0(gateway, c_gateway) != 0) - ip_change = TRUE; + if (address && c_address && g_strcmp0(address, c_address) != 0) + ip_change = true; + else if (gateway && c_gateway && g_strcmp0(gateway, c_gateway) != 0) + ip_change = true; else if (prefixlen != c_prefixlen) - ip_change = TRUE; - else if (c_address == NULL || c_gateway == NULL) - ip_change = TRUE; + ip_change = true; + else if (!c_address || !c_gateway) + ip_change = true; else - ip_change = FALSE; + ip_change = false; option = g_dhcp_client_get_option(dhcp_client, G_DHCP_DNS_SERVER); ns_entries = g_list_length(option); nameservers = g_try_new0(char *, ns_entries + 1); - if (nameservers != NULL) { + if (nameservers) { for (i = 0, list = option; list; list = list->next, i++) nameservers[i] = g_strdup(list->data); nameservers[ns_entries] = NULL; } option = g_dhcp_client_get_option(dhcp_client, G_DHCP_DOMAIN_NAME); - if (option != NULL) - domainname = g_strdup(option->data); - - if (connman_setting_get_bool("AllowHostnameUpdates") == TRUE) { - option = g_dhcp_client_get_option(dhcp_client, - G_DHCP_HOST_NAME); - if (option != NULL) - hostname = g_strdup(option->data); - } + if (option) + __connman_service_set_domainname(service, option->data); + + option = g_dhcp_client_get_option(dhcp_client, G_DHCP_HOST_NAME); + if (option) + __connman_service_set_hostname(service, option->data); option = g_dhcp_client_get_option(dhcp_client, G_DHCP_NTP_SERVER); ns_entries = g_list_length(option); timeservers = g_try_new0(char *, ns_entries + 1); - if (timeservers != NULL) { + if (timeservers) { for (i = 0, list = option; list; list = list->next, i++) timeservers[i] = g_strdup(list->data); timeservers[ns_entries] = NULL; } option = g_dhcp_client_get_option(dhcp_client, 252); - if (option != NULL) + if (option) pac = g_strdup(option->data); __connman_ipconfig_set_method(ipconfig, CONNMAN_IPCONFIG_METHOD_DHCP); - if (ip_change == TRUE) { + if (ip_change) { __connman_ipconfig_set_local(ipconfig, address); __connman_ipconfig_set_prefixlen(ipconfig, prefixlen); __connman_ipconfig_set_gateway(ipconfig, gateway); } - if (compare_string_arrays(nameservers, dhcp->nameservers) == FALSE) { - if (dhcp->nameservers != NULL) { - for (i = 0; dhcp->nameservers[i] != NULL; i++) { + if (!compare_string_arrays(nameservers, dhcp->nameservers)) { + if (dhcp->nameservers) { + for (i = 0; dhcp->nameservers[i]; i++) { __connman_service_nameserver_remove(service, - dhcp->nameservers[i], FALSE); + dhcp->nameservers[i], false); } g_strfreev(dhcp->nameservers); } dhcp->nameservers = nameservers; - for (i = 0; dhcp->nameservers != NULL && - dhcp->nameservers[i] != NULL; i++) { + for (i = 0; dhcp->nameservers && + dhcp->nameservers[i]; i++) { __connman_service_nameserver_append(service, - dhcp->nameservers[i], FALSE); + dhcp->nameservers[i], false); } } else { g_strfreev(nameservers); } - if (compare_string_arrays(timeservers, dhcp->timeservers) == FALSE) { - if (dhcp->timeservers != NULL) { - for (i = 0; dhcp->timeservers[i] != NULL; i++) { + if (!compare_string_arrays(timeservers, dhcp->timeservers)) { + if (dhcp->timeservers) { + for (i = 0; dhcp->timeservers[i]; i++) { __connman_service_timeserver_remove(service, dhcp->timeservers[i]); } @@ -318,8 +432,8 @@ static void lease_available_cb(GDHCPClient *dhcp_client, gpointer user_data) dhcp->timeservers = timeservers; - for (i = 0; dhcp->timeservers != NULL && - dhcp->timeservers[i] != NULL; i++) { + for (i = 0; dhcp->timeservers && + dhcp->timeservers[i]; i++) { __connman_service_timeserver_append(service, dhcp->timeservers[i]); } @@ -334,15 +448,7 @@ static void lease_available_cb(GDHCPClient *dhcp_client, gpointer user_data) __connman_service_set_pac(service, dhcp->pac); } - __connman_service_set_domainname(service, domainname); - - if (domainname != NULL) - __connman_utsname_set_domainname(domainname); - - if (hostname != NULL) - __connman_utsname_set_hostname(hostname); - - if (ip_change == TRUE) + if (ip_change) dhcp_valid(dhcp); __connman_6to4_probe(service); @@ -350,11 +456,9 @@ static void lease_available_cb(GDHCPClient *dhcp_client, gpointer user_data) g_free(address); g_free(netmask); g_free(gateway); - g_free(domainname); - g_free(hostname); } -static void ipv4ll_available_cb(GDHCPClient *dhcp_client, gpointer user_data) +static void ipv4ll_available_cb(GDHCPClient *ipv4ll_client, gpointer user_data) { struct connman_dhcp *dhcp = user_data; char *address, *netmask; @@ -365,15 +469,15 @@ static void ipv4ll_available_cb(GDHCPClient *dhcp_client, gpointer user_data) DBG("IPV4LL available"); service = connman_service_lookup_from_network(dhcp->network); - if (service == NULL) + if (!service) return; ipconfig = __connman_service_get_ip4config(service); - if (ipconfig == NULL) + if (!ipconfig) return; - address = g_dhcp_client_get_address(dhcp_client); - netmask = g_dhcp_client_get_netmask(dhcp_client); + address = g_dhcp_client_get_address(ipv4ll_client); + netmask = g_dhcp_client_get_netmask(ipv4ll_client); prefixlen = __connman_ipaddress_netmask_prefix_len(netmask); @@ -388,15 +492,9 @@ static void ipv4ll_available_cb(GDHCPClient *dhcp_client, gpointer user_data) g_free(netmask); } -static void dhcp_debug(const char *str, void *data) -{ - connman_info("%s: %s\n", (const char *) data, str); -} - -static int dhcp_request(struct connman_dhcp *dhcp) +static int dhcp_initialize(struct connman_dhcp *dhcp) { struct connman_service *service; - struct connman_ipconfig *ipconfig; GDHCPClient *dhcp_client; GDHCPClientError error; const char *hostname; @@ -410,13 +508,22 @@ static int dhcp_request(struct connman_dhcp *dhcp) if (error != G_DHCP_CLIENT_ERROR_NONE) return -EINVAL; - if (getenv("CONNMAN_DHCP_DEBUG")) - g_dhcp_client_set_debug(dhcp_client, dhcp_debug, "DHCP"); + if (getenv("CONNMAN_DHCP_DEBUG")) { + dhcp->dhcp_debug_prefix = g_strdup_printf("DHCP index %d", + index); + g_dhcp_client_set_debug(dhcp_client, dhcp_debug, + dhcp->dhcp_debug_prefix); + } g_dhcp_client_set_id(dhcp_client); - hostname = connman_utsname_get_hostname(); - if (hostname != NULL) + service = connman_service_lookup_from_network(dhcp->network); + + hostname = __connman_service_get_hostname(service); + if (!hostname) + hostname = connman_utsname_get_hostname(); + + if (hostname) g_dhcp_client_set_send(dhcp_client, G_DHCP_HOST_NAME, hostname); g_dhcp_client_set_request(dhcp_client, G_DHCP_HOST_NAME); @@ -432,89 +539,92 @@ static int dhcp_request(struct connman_dhcp *dhcp) lease_available_cb, dhcp); g_dhcp_client_register_event(dhcp_client, - G_DHCP_CLIENT_EVENT_IPV4LL_AVAILABLE, - ipv4ll_available_cb, dhcp); - - g_dhcp_client_register_event(dhcp_client, G_DHCP_CLIENT_EVENT_LEASE_LOST, lease_lost_cb, dhcp); g_dhcp_client_register_event(dhcp_client, - G_DHCP_CLIENT_EVENT_IPV4LL_LOST, ipv4ll_lost_cb, dhcp); - - g_dhcp_client_register_event(dhcp_client, G_DHCP_CLIENT_EVENT_NO_LEASE, no_lease_cb, dhcp); dhcp->dhcp_client = dhcp_client; - service = connman_service_lookup_from_network(dhcp->network); - ipconfig = __connman_service_get_ip4config(service); - - /* - * Clear the addresses at startup so that lease callback will - * take the lease and set ip address properly. - */ - __connman_ipconfig_clear_address(ipconfig); - - return g_dhcp_client_start(dhcp_client, - __connman_ipconfig_get_dhcp_address(ipconfig)); + return 0; } static int dhcp_release(struct connman_dhcp *dhcp) { DBG("dhcp %p", dhcp); - if (dhcp->dhcp_client == NULL) - return 0; + if (dhcp->timeout > 0) + g_source_remove(dhcp->timeout); - g_dhcp_client_stop(dhcp->dhcp_client); - g_dhcp_client_unref(dhcp->dhcp_client); + if (dhcp->dhcp_client) { + g_dhcp_client_stop(dhcp->dhcp_client); + g_dhcp_client_unref(dhcp->dhcp_client); + } dhcp->dhcp_client = NULL; - return 0; -} + g_free(dhcp->dhcp_debug_prefix); + dhcp->dhcp_debug_prefix = NULL; -static void remove_network(gpointer user_data) -{ - struct connman_dhcp *dhcp = user_data; - - DBG("dhcp %p", dhcp); + ipv4ll_stop_client(dhcp); - dhcp_invalidate(dhcp, FALSE); - dhcp_release(dhcp); - - g_free(dhcp); + return 0; } int __connman_dhcp_start(struct connman_network *network, dhcp_cb callback) { + struct connman_service *service; + struct connman_ipconfig *ipconfig; + const char *last_addr = NULL; struct connman_dhcp *dhcp; DBG(""); - dhcp = g_try_new0(struct connman_dhcp, 1); - if (dhcp == NULL) - return -ENOMEM; + service = connman_service_lookup_from_network(network); + if (!service) + return -EINVAL; - dhcp->network = network; - dhcp->callback = callback; + ipconfig = __connman_service_get_ip4config(service); + if (ipconfig) + last_addr = __connman_ipconfig_get_dhcp_address(ipconfig); + + dhcp = g_hash_table_lookup(network_table, network); + if (!dhcp) { - connman_network_ref(network); + dhcp = g_try_new0(struct connman_dhcp, 1); + if (!dhcp) + return -ENOMEM; - g_hash_table_replace(network_table, network, dhcp); + dhcp->network = network; + connman_network_ref(network); - return dhcp_request(dhcp); + g_hash_table_insert(network_table, network, dhcp); + + dhcp_initialize(dhcp); + } + + dhcp->callback = callback; + + return g_dhcp_client_start(dhcp->dhcp_client, last_addr); } void __connman_dhcp_stop(struct connman_network *network) { - DBG(""); + struct connman_dhcp *dhcp; + + DBG("network_table %p network %p", network_table, network); - if (network_table == NULL) + if (!network_table) return; - if (g_hash_table_remove(network_table, network) == TRUE) + dhcp = g_hash_table_lookup(network_table, network); + if (dhcp) { + g_hash_table_remove(network_table, network); connman_network_unref(network); + dhcp_release(dhcp); + dhcp_invalidate(dhcp, false); + dhcp_free(dhcp); + } } int __connman_dhcp_init(void) @@ -522,7 +632,7 @@ int __connman_dhcp_init(void) DBG(""); network_table = g_hash_table_new_full(g_direct_hash, g_direct_equal, - NULL, remove_network); + NULL, NULL); return 0; } diff --git a/src/dhcpv6.c b/src/dhcpv6.c index bff57d44..2ede854e 100644 --- a/src/dhcpv6.c +++ b/src/dhcpv6.c @@ -2,7 +2,7 @@ * * Connection Manager * - * Copyright (C) 2012 Intel Corporation. All rights reserved. + * Copyright (C) 2012-2013 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 @@ -26,6 +26,7 @@ #include <errno.h> #include <string.h> #include <stdlib.h> +#include <net/if.h> #include <connman/ipconfig.h> #include <connman/storage.h> @@ -54,11 +55,18 @@ #define CNF_TIMEOUT (1 * 1000) #define CNF_MAX_RT (4 * 1000) #define CNF_MAX_RD (10 * 1000) +#define DEC_TIMEOUT (1 * 1000) +#define DEC_MAX_RC 5 +enum request_type { + REQ_REQUEST = 1, + REQ_REBIND = 2, + REQ_RENEW = 3, +}; struct connman_dhcpv6 { struct connman_network *network; - dhcp_cb callback; + dhcpv6_cb callback; char **nameservers; char **timeservers; @@ -68,16 +76,21 @@ struct connman_dhcpv6 { guint timeout; /* operation timeout in msec */ guint MRD; /* max operation timeout in msec */ guint RT; /* in msec */ - gboolean use_ta; /* set to TRUE if IPv6 privacy is enabled */ - GSList *prefixes; /* network prefixes from radvd */ + bool use_ta; /* set to TRUE if IPv6 privacy is enabled */ + GSList *prefixes; /* network prefixes from radvd or dhcpv6 pd */ int request_count; /* how many times REQUEST have been sent */ - gboolean stateless; /* TRUE if stateless DHCPv6 is used */ - gboolean started; /* TRUE if we have DHCPv6 started */ + bool stateless; /* TRUE if stateless DHCPv6 is used */ + bool started; /* TRUE if we have DHCPv6 started */ }; static GHashTable *network_table; +static GHashTable *network_pd_table; -static int dhcpv6_request(struct connman_dhcpv6 *dhcp, gboolean add_addresses); +static int dhcpv6_request(struct connman_dhcpv6 *dhcp, bool add_addresses); +static int dhcpv6_pd_request(struct connman_dhcpv6 *dhcp); +static gboolean start_solicitation(gpointer user_data); +static int dhcpv6_renew(struct connman_dhcpv6 *dhcp); +static int dhcpv6_rebind(struct connman_dhcpv6 *dhcp); static void clear_timer(struct connman_dhcpv6 *dhcp) { @@ -92,7 +105,7 @@ static void clear_timer(struct connman_dhcpv6 *dhcp) } } -static inline float get_random() +static inline float get_random(void) { return (rand() % 200 - 100) / 1000.0; } @@ -113,7 +126,7 @@ static guint calc_delay(guint RT, guint MRT) return (guint)rt; } -static void free_prefix(gpointer data, gpointer user_data) +static void free_prefix(gpointer data) { g_free(data); } @@ -125,27 +138,26 @@ static void dhcpv6_free(struct connman_dhcpv6 *dhcp) dhcp->nameservers = NULL; dhcp->timeservers = NULL; - dhcp->started = FALSE; + dhcp->started = false; - g_slist_foreach(dhcp->prefixes, free_prefix, NULL); - g_slist_free(dhcp->prefixes); + g_slist_free_full(dhcp->prefixes, free_prefix); } -static gboolean compare_string_arrays(char **array_a, char **array_b) +static bool compare_string_arrays(char **array_a, char **array_b) { int i; - if (array_a == NULL || array_b == NULL) - return FALSE; + if (!array_a || !array_b) + return false; if (g_strv_length(array_a) != g_strv_length(array_b)) - return FALSE; + return false; - for (i = 0; array_a[i] != NULL && array_b[i] != NULL; i++) + for (i = 0; array_a[i] && array_b[i]; i++) if (g_strcmp0(array_a[i], array_b[i]) != 0) - return FALSE; + return false; - return TRUE; + return true; } static void dhcpv6_debug(const char *str, void *data) @@ -158,7 +170,7 @@ static gchar *convert_to_hex(unsigned char *buf, int len) gchar *ret = g_try_malloc(len * 2 + 1); int i; - for (i = 0; ret != NULL && i < len; i++) + for (i = 0; ret && i < len; i++) g_snprintf(ret + i * 2, 3, "%02x", buf[i]); return ret; @@ -181,17 +193,17 @@ static int set_duid(struct connman_service *service, ident = __connman_service_get_ident(service); keyfile = connman_storage_load_service(ident); - if (keyfile == NULL) + if (!keyfile) return -EINVAL; hex_duid = g_key_file_get_string(keyfile, ident, "IPv6.DHCP.DUID", NULL); - if (hex_duid != NULL) { + if (hex_duid) { unsigned int i, j = 0, hex; size_t hex_duid_len = strlen(hex_duid); duid = g_try_malloc0(hex_duid_len / 2); - if (duid == NULL) { + if (!duid) { g_key_file_free(keyfile); g_free(hex_duid); return -ENOMEM; @@ -215,7 +227,7 @@ static int set_duid(struct connman_service *service, } hex_duid = convert_to_hex(duid, duid_len); - if (hex_duid == NULL) { + if (!hex_duid) { g_key_file_free(keyfile); return -ENOMEM; } @@ -265,6 +277,10 @@ static void clear_callbacks(GDHCPClient *dhcp_client) NULL, NULL); g_dhcp_client_register_event(dhcp_client, + G_DHCP_CLIENT_EVENT_DECLINE, + NULL, NULL); + + g_dhcp_client_register_event(dhcp_client, G_DHCP_CLIENT_EVENT_INFORMATION_REQ, NULL, NULL); } @@ -280,7 +296,7 @@ static void info_req_cb(GDHCPClient *dhcp_client, gpointer user_data) DBG("dhcpv6 information-request %p", dhcp); service = connman_service_lookup_from_network(dhcp->network); - if (service == NULL) { + if (!service) { connman_error("Can not lookup service"); return; } @@ -291,27 +307,27 @@ static void info_req_cb(GDHCPClient *dhcp_client, gpointer user_data) entries = g_list_length(option); nameservers = g_try_new0(char *, entries + 1); - if (nameservers != NULL) { + if (nameservers) { for (i = 0, list = option; list; list = list->next, i++) nameservers[i] = g_strdup(list->data); } - if (compare_string_arrays(nameservers, dhcp->nameservers) == FALSE) { - if (dhcp->nameservers != NULL) { - for (i = 0; dhcp->nameservers[i] != NULL; i++) + if (!compare_string_arrays(nameservers, dhcp->nameservers)) { + if (dhcp->nameservers) { + for (i = 0; dhcp->nameservers[i]; i++) __connman_service_nameserver_remove(service, dhcp->nameservers[i], - FALSE); + false); g_strfreev(dhcp->nameservers); } dhcp->nameservers = nameservers; - for (i = 0; dhcp->nameservers != NULL && - dhcp->nameservers[i] != NULL; i++) + for (i = 0; dhcp->nameservers && + dhcp->nameservers[i]; i++) __connman_service_nameserver_append(service, dhcp->nameservers[i], - FALSE); + false); } else g_strfreev(nameservers); @@ -320,14 +336,14 @@ static void info_req_cb(GDHCPClient *dhcp_client, gpointer user_data) entries = g_list_length(option); timeservers = g_try_new0(char *, entries + 1); - if (timeservers != NULL) { + if (timeservers) { for (i = 0, list = option; list; list = list->next, i++) timeservers[i] = g_strdup(list->data); } - if (compare_string_arrays(timeservers, dhcp->timeservers) == FALSE) { - if (dhcp->timeservers != NULL) { - for (i = 0; dhcp->timeservers[i] != NULL; i++) + if (!compare_string_arrays(timeservers, dhcp->timeservers)) { + if (dhcp->timeservers) { + for (i = 0; dhcp->timeservers[i]; i++) __connman_service_timeserver_remove(service, dhcp->timeservers[i]); g_strfreev(dhcp->timeservers); @@ -335,17 +351,20 @@ static void info_req_cb(GDHCPClient *dhcp_client, gpointer user_data) dhcp->timeservers = timeservers; - for (i = 0; dhcp->timeservers != NULL && - dhcp->timeservers[i] != NULL; i++) + for (i = 0; dhcp->timeservers && + dhcp->timeservers[i]; i++) __connman_service_timeserver_append(service, dhcp->timeservers[i]); } else g_strfreev(timeservers); - if (dhcp->callback != NULL) { + if (dhcp->callback) { uint16_t status = g_dhcpv6_client_get_status(dhcp_client); - dhcp->callback(dhcp->network, status == 0 ? TRUE : FALSE); + dhcp->callback(dhcp->network, status == 0 ? + CONNMAN_DHCPV6_STATUS_SUCCEED : + CONNMAN_DHCPV6_STATUS_FAIL, + NULL); } } @@ -370,7 +389,7 @@ static int dhcpv6_info_request(struct connman_dhcpv6 *dhcp) g_dhcp_client_set_debug(dhcp_client, dhcpv6_debug, "DHCPv6"); service = connman_service_lookup_from_network(dhcp->network); - if (service == NULL) { + if (!service) { clear_timer(dhcp); g_dhcp_client_unref(dhcp_client); return -EINVAL; @@ -412,11 +431,14 @@ static int check_ipv6_addr_prefix(GSList *prefixes, char *address) 0xF0, 0xE0, 0xC0, 0x80 }; int left, count, i, plen; - if (slash == NULL) + if (!slash) continue; prefix = g_strndup(prefix, slash - prefix); len = strtol(slash + 1, NULL, 10); + if (len < 3 || len > 128) + break; + plen = 128 - len; count = plen / 8; @@ -445,54 +467,62 @@ static int check_ipv6_addr_prefix(GSList *prefixes, char *address) return ret; } -static int set_addresses(GDHCPClient *dhcp_client, +static int set_other_addresses(GDHCPClient *dhcp_client, struct connman_dhcpv6 *dhcp) { struct connman_service *service; - struct connman_ipconfig *ipconfig; int entries, i; GList *option, *list; char **nameservers, **timeservers; - const char *c_address; - char *address = NULL; service = connman_service_lookup_from_network(dhcp->network); - if (service == NULL) { + if (!service) { connman_error("Can not lookup service"); return -EINVAL; } - ipconfig = __connman_service_get_ip6config(service); - if (ipconfig == NULL) { - connman_error("Could not lookup ip6config"); - return -EINVAL; + /* + * Check domains before nameservers so that the nameserver append + * function will update domain list in service.c + */ + option = g_dhcp_client_get_option(dhcp_client, G_DHCPV6_DOMAIN_LIST); + entries = g_list_length(option); + if (entries > 0) { + char **domains = g_try_new0(char *, entries + 1); + if (domains) { + for (i = 0, list = option; list; + list = list->next, i++) + domains[i] = g_strdup(list->data); + __connman_service_update_search_domains(service, domains); + g_strfreev(domains); + } } option = g_dhcp_client_get_option(dhcp_client, G_DHCPV6_DNS_SERVERS); entries = g_list_length(option); nameservers = g_try_new0(char *, entries + 1); - if (nameservers != NULL) { + if (nameservers) { for (i = 0, list = option; list; list = list->next, i++) nameservers[i] = g_strdup(list->data); } - if (compare_string_arrays(nameservers, dhcp->nameservers) == FALSE) { - if (dhcp->nameservers != NULL) { - for (i = 0; dhcp->nameservers[i] != NULL; i++) + if (!compare_string_arrays(nameservers, dhcp->nameservers)) { + if (dhcp->nameservers) { + for (i = 0; dhcp->nameservers[i]; i++) __connman_service_nameserver_remove(service, dhcp->nameservers[i], - FALSE); + false); g_strfreev(dhcp->nameservers); } dhcp->nameservers = nameservers; - for (i = 0; dhcp->nameservers != NULL && - dhcp->nameservers[i] != NULL; i++) + for (i = 0; dhcp->nameservers && + dhcp->nameservers[i]; i++) __connman_service_nameserver_append(service, dhcp->nameservers[i], - FALSE); + false); } else g_strfreev(nameservers); @@ -501,14 +531,14 @@ static int set_addresses(GDHCPClient *dhcp_client, entries = g_list_length(option); timeservers = g_try_new0(char *, entries + 1); - if (timeservers != NULL) { + if (timeservers) { for (i = 0, list = option; list; list = list->next, i++) timeservers[i] = g_strdup(list->data); } - if (compare_string_arrays(timeservers, dhcp->timeservers) == FALSE) { - if (dhcp->timeservers != NULL) { - for (i = 0; dhcp->timeservers[i] != NULL; i++) + if (!compare_string_arrays(timeservers, dhcp->timeservers)) { + if (dhcp->timeservers) { + for (i = 0; dhcp->timeservers[i]; i++) __connman_service_timeserver_remove(service, dhcp->timeservers[i]); g_strfreev(dhcp->timeservers); @@ -516,33 +546,90 @@ static int set_addresses(GDHCPClient *dhcp_client, dhcp->timeservers = timeservers; - for (i = 0; dhcp->timeservers != NULL && - dhcp->timeservers[i] != NULL; i++) + for (i = 0; dhcp->timeservers && + dhcp->timeservers[i]; i++) __connman_service_timeserver_append(service, dhcp->timeservers[i]); } else g_strfreev(timeservers); + return 0; +} - option = g_dhcp_client_get_option(dhcp_client, G_DHCPV6_IA_NA); - if (option != NULL) - address = g_strdup(option->data); - else { - option = g_dhcp_client_get_option(dhcp_client, G_DHCPV6_IA_TA); - if (option != NULL) - address = g_strdup(option->data); - } +static GSList *copy_prefixes(GSList *prefixes) +{ + GSList *list, *copy = NULL; + + for (list = prefixes; list; list = list->next) + copy = g_slist_prepend(copy, g_strdup(list->data)); + + return copy; +} + +/* + * Helper struct for doing DAD (duplicate address detection). + * It is refcounted and freed after all reply's to neighbor + * discovery request are received. + */ +struct own_address { + int refcount; + + int ifindex; + GDHCPClient *dhcp_client; + struct connman_ipconfig *ipconfig; + GSList *prefixes; + dhcpv6_cb callback; + + GSList *dad_failed; + GSList *dad_succeed; +}; + +static void free_own_address(struct own_address *data) +{ + g_dhcp_client_unref(data->dhcp_client); + __connman_ipconfig_unref(data->ipconfig); + g_slist_free_full(data->prefixes, free_prefix); + g_slist_free_full(data->dad_failed, g_free); + g_slist_free_full(data->dad_succeed, g_free); + + g_free(data); +} + +static struct own_address *ref_own_address(struct own_address *address) +{ + DBG("%p ref %d", address, address->refcount + 1); + + __sync_fetch_and_add(&address->refcount, 1); + + return address; +} + +static void unref_own_address(struct own_address *address) +{ + if (!address) + return; + + DBG("%p ref %d", address, address->refcount - 1); + + if (__sync_fetch_and_sub(&address->refcount, 1) != 1) + return; + + free_own_address(address); +} + +static void set_address(int ifindex, struct connman_ipconfig *ipconfig, + GSList *prefixes, char *address) +{ + const char *c_address; c_address = __connman_ipconfig_get_local(ipconfig); - if (address != NULL && - ((c_address != NULL && - g_strcmp0(address, c_address) != 0) || - (c_address == NULL))) { + if (address && ((c_address && g_strcmp0(address, c_address) != 0) || + !c_address)) { int prefix_len; /* Is this prefix part of the subnet we are suppose to use? */ - prefix_len = check_ipv6_addr_prefix(dhcp->prefixes, address); + prefix_len = check_ipv6_addr_prefix(prefixes, address); __connman_ipconfig_set_local(ipconfig, address); __connman_ipconfig_set_prefixlen(ipconfig, prefix_len); @@ -550,39 +637,480 @@ static int set_addresses(GDHCPClient *dhcp_client, DBG("new address %s/%d", address, prefix_len); __connman_ipconfig_set_dhcp_address(ipconfig, address); - __connman_service_save(service); + __connman_service_save( + __connman_service_lookup_from_index(ifindex)); } +} - g_free(address); - return 0; +/* + * Helper struct that is used when waiting a reply to DECLINE message. + */ +struct decline_cb_data { + GDHCPClient *dhcp_client; + dhcpv6_cb callback; + int ifindex; + guint timeout; +}; + +static void decline_reply_callback(struct decline_cb_data *data) +{ + struct connman_network *network; + struct connman_service *service; + + service = __connman_service_lookup_from_index(data->ifindex); + network = __connman_service_get_network(service); + + if (data->callback) + data->callback(network, CONNMAN_DHCPV6_STATUS_RESTART, NULL); + + g_dhcp_client_unref(data->dhcp_client); +} + +static gboolean decline_timeout(gpointer user_data) +{ + struct decline_cb_data *data = user_data; + + DBG("ifindex %d", data->ifindex); + + /* + * We ignore all DECLINE replies that are received after the timeout + */ + g_dhcp_client_register_event(data->dhcp_client, + G_DHCP_CLIENT_EVENT_DECLINE, + NULL, NULL); + + decline_reply_callback(data); + + g_free(data); + + return FALSE; +} + +static void decline_cb(GDHCPClient *dhcp_client, gpointer user_data) +{ + struct decline_cb_data *data = user_data; + + DBG("ifindex %d", data->ifindex); + + g_dhcpv6_client_clear_retransmit(dhcp_client); + + if (data->timeout) + g_source_remove(data->timeout); + + decline_reply_callback(data); + + g_free(data); +} + +static int dhcpv6_decline(GDHCPClient *dhcp_client, int ifindex, + dhcpv6_cb callback, GSList *failed) +{ + struct decline_cb_data *data; + GList *option; + int code; + + DBG("dhcp_client %p", dhcp_client); + + g_dhcp_client_clear_requests(dhcp_client); + + g_dhcpv6_client_clear_send(dhcp_client, G_DHCPV6_ORO); + + g_dhcp_client_set_request(dhcp_client, G_DHCPV6_CLIENTID); + g_dhcp_client_set_request(dhcp_client, G_DHCPV6_SERVERID); + + option = g_dhcp_client_get_option(dhcp_client, G_DHCPV6_IA_NA); + if (!option) { + option = g_dhcp_client_get_option(dhcp_client, G_DHCPV6_IA_TA); + if (option) + code = G_DHCPV6_IA_TA; + else + return -EINVAL; + } else + code = G_DHCPV6_IA_NA; + + g_dhcpv6_client_clear_send(dhcp_client, code); + + g_dhcpv6_client_set_ias(dhcp_client, ifindex, code, NULL, NULL, + failed); + + clear_callbacks(dhcp_client); + + data = g_try_new(struct decline_cb_data, 1); + if (!data) + return -ENOMEM; + + data->ifindex = ifindex; + data->callback = callback; + data->dhcp_client = g_dhcp_client_ref(dhcp_client); + data->timeout = g_timeout_add(DEC_TIMEOUT, decline_timeout, data); + + g_dhcp_client_register_event(dhcp_client, G_DHCP_CLIENT_EVENT_DECLINE, + decline_cb, data); + + return g_dhcp_client_start(dhcp_client, NULL); +} + +static void dad_reply(struct nd_neighbor_advert *reply, + unsigned int length, struct in6_addr *addr, void *user_data) +{ + struct own_address *data = user_data; + GSList *list; + char address[INET6_ADDRSTRLEN]; + enum __connman_dhcpv6_status status = CONNMAN_DHCPV6_STATUS_FAIL; + + inet_ntop(AF_INET6, addr, address, INET6_ADDRSTRLEN); + + DBG("user %p reply %p len %d address %s index %d data %p", user_data, + reply, length, address, data->ifindex, data); + + if (!reply) { + if (length == 0) + DBG("DAD succeed for %s", address); + else + DBG("DAD cannot be done for %s", address); + + data->dad_succeed = g_slist_prepend(data->dad_succeed, + g_strdup(address)); + + } else { + DBG("DAD failed for %s", address); + + data->dad_failed = g_slist_prepend(data->dad_failed, + g_strdup(address)); + } + + /* + * If refcount == 1 then we got the final reply and can continue. + */ + if (data->refcount > 1) + return; + + for (list = data->dad_succeed; list; list = list->next) + set_address(data->ifindex, data->ipconfig, data->prefixes, + list->data); + + if (data->dad_failed) { + dhcpv6_decline(data->dhcp_client, data->ifindex, + data->callback, data->dad_failed); + } else { + if (data->dad_succeed) + status = CONNMAN_DHCPV6_STATUS_SUCCEED; + + if (data->callback) { + struct connman_network *network; + struct connman_service *service; + + service = __connman_service_lookup_from_index( + data->ifindex); + network = __connman_service_get_network(service); + data->callback(network, status, NULL); + } + } + + unref_own_address(data); +} + +/* + * Is the kernel configured to do DAD? If 0, then do not do DAD. + * See also RFC 4862 chapter 5.4 about DupAddrDetectTransmits + */ +static int dad_transmits(int ifindex) +{ + char name[IF_NAMESIZE]; + gchar *path; + int value = 1; + FILE *f; + + if (!if_indextoname(ifindex, name)) + return value; + + path = g_strdup_printf("/proc/sys/net/ipv6/conf/%s/dad_transmits", + name); + + if (!path) + return value; + + f = fopen(path, "r"); + + g_free(path); + + if (f) { + if (fscanf(f, "%d", &value) < 0) + value = 1; + + fclose(f); + } + + return value; +} + +static void do_dad(GDHCPClient *dhcp_client, struct connman_dhcpv6 *dhcp) +{ + struct connman_service *service; + struct connman_ipconfig *ipconfig; + int ifindex; + GList *option, *list; + struct own_address *user_data; + + option = g_dhcp_client_get_option(dhcp_client, G_DHCPV6_IA_NA); + if (!option) + option = g_dhcp_client_get_option(dhcp_client, G_DHCPV6_IA_TA); + + /* + * Even if we didn't had any addresses, just try to set + * the other options. + */ + set_other_addresses(dhcp_client, dhcp); + + if (!option) { + DBG("Skip DAD as no addresses found in reply"); + if (dhcp->callback) + dhcp->callback(dhcp->network, + CONNMAN_DHCPV6_STATUS_SUCCEED, NULL); + + return; + } + + ifindex = connman_network_get_index(dhcp->network); + + DBG("index %d", ifindex); + + service = connman_service_lookup_from_network(dhcp->network); + if (!service) { + connman_error("Can not lookup service for index %d", ifindex); + goto error; + } + + ipconfig = __connman_service_get_ip6config(service); + if (!ipconfig) { + connman_error("Could not lookup ip6config for index %d", + ifindex); + goto error; + } + + if (!dad_transmits(ifindex)) { + DBG("Skip DAD because of kernel configuration"); + + for (list = option; list; list = list->next) + set_address(ifindex, ipconfig, dhcp->prefixes, + option->data); + + if (dhcp->callback) + dhcp->callback(dhcp->network, + CONNMAN_DHCPV6_STATUS_SUCCEED, NULL); + + return; + } + + if (g_list_length(option) == 0) { + DBG("No addresses when doing DAD"); + if (dhcp->callback) + dhcp->callback(dhcp->network, + CONNMAN_DHCPV6_STATUS_SUCCEED, NULL); + + return; + } + + user_data = g_try_new0(struct own_address, 1); + if (!user_data) + goto error; + + user_data->refcount = 0; + user_data->ifindex = ifindex; + user_data->dhcp_client = g_dhcp_client_ref(dhcp_client); + user_data->ipconfig = __connman_ipconfig_ref(ipconfig); + user_data->prefixes = copy_prefixes(dhcp->prefixes); + user_data->callback = dhcp->callback; + + /* + * We send one neighbor discovery request / address + * and after all checks are done, then report the status + * via dhcp callback. + */ + + for (list = option; list; list = list->next) { + char *address = option->data; + struct in6_addr addr; + int ret; + + ref_own_address(user_data); + + if (inet_pton(AF_INET6, address, &addr) < 0) { + DBG("Invalid IPv6 address %s %d/%s", address, + -errno, strerror(errno)); + goto fail; + } + + DBG("user %p address %s client %p ipconfig %p prefixes %p", + user_data, address, + user_data->dhcp_client, user_data->ipconfig, + user_data->prefixes); + + ret = __connman_inet_ipv6_do_dad(ifindex, 1000, + &addr, + dad_reply, + user_data); + if (ret < 0) { + DBG("Could not send neighbor solicitation for %s", + address); + dad_reply(NULL, -1, &addr, user_data); + } else { + DBG("Sent neighbor solicitation %d bytes", ret); + } + } + + return; + +fail: + unref_own_address(user_data); + +error: + if (dhcp->callback) + dhcp->callback(dhcp->network, CONNMAN_DHCPV6_STATUS_FAIL, + NULL); } -static void re_cb(GDHCPClient *dhcp_client, gpointer user_data) +static gboolean timeout_request_resend(gpointer user_data) { struct connman_dhcpv6 *dhcp = user_data; - uint16_t status; - int ret; - ret = set_addresses(dhcp_client, dhcp); + if (dhcp->request_count >= REQ_MAX_RC) { + DBG("max request retry attempts %d", dhcp->request_count); + dhcp->request_count = 0; + if (dhcp->callback) + dhcp->callback(dhcp->network, + CONNMAN_DHCPV6_STATUS_FAIL, NULL); + return FALSE; + } - status = g_dhcpv6_client_get_status(dhcp_client); + dhcp->request_count++; + + dhcp->RT = calc_delay(dhcp->RT, REQ_MAX_RT); + DBG("request resend RT timeout %d msec", dhcp->RT); + dhcp->timeout = g_timeout_add(dhcp->RT, timeout_request_resend, dhcp); - DBG("dhcpv6 cb msg %p ret %d status %d", dhcp, ret, status); + g_dhcpv6_client_set_retransmit(dhcp->dhcp_client); - if (ret < 0) { - if (dhcp->callback != NULL) - dhcp->callback(dhcp->network, FALSE); + g_dhcp_client_start(dhcp->dhcp_client, NULL); + + return FALSE; +} + +static gboolean request_resend(gpointer user_data) +{ + struct connman_dhcpv6 *dhcp = user_data; + + g_dhcpv6_client_set_retransmit(dhcp->dhcp_client); + + dhcp->RT = calc_delay(dhcp->RT, REQ_MAX_RT); + DBG("request resend RT timeout %d msec", dhcp->RT); + dhcp->timeout = g_timeout_add(dhcp->RT, timeout_request_resend, dhcp); + + dhcpv6_request(dhcp, true); + + return FALSE; +} + +static void do_resend_request(struct connman_dhcpv6 *dhcp) +{ + if (dhcp->request_count >= REQ_MAX_RC) { + DBG("max request retry attempts %d", dhcp->request_count); + dhcp->request_count = 0; + if (dhcp->callback) + dhcp->callback(dhcp->network, + CONNMAN_DHCPV6_STATUS_FAIL, NULL); return; } + dhcp->request_count++; + + dhcp->RT = calc_delay(dhcp->RT, REQ_MAX_RT); + DBG("resending request after %d msec", dhcp->RT); + dhcp->timeout = g_timeout_add(dhcp->RT, request_resend, dhcp); +} + +static void re_cb(enum request_type req_type, GDHCPClient *dhcp_client, + gpointer user_data) +{ + struct connman_dhcpv6 *dhcp = user_data; + uint16_t status; + + clear_timer(dhcp); + + status = g_dhcpv6_client_get_status(dhcp_client); + + DBG("dhcpv6 cb msg %p status %d", dhcp, status); + + /* + * RFC 3315, 18.1.8 handle the resend if error + */ if (status == G_DHCPV6_ERROR_BINDING) { - /* RFC 3315, 18.1.8 */ - dhcpv6_request(dhcp, FALSE); + dhcpv6_request(dhcp, false); + } else if (status == G_DHCPV6_ERROR_MCAST) { + switch (req_type) { + case REQ_REQUEST: + dhcpv6_request(dhcp, true); + break; + case REQ_REBIND: + dhcpv6_rebind(dhcp); + break; + case REQ_RENEW: + dhcpv6_renew(dhcp); + break; + } + } else if (status == G_DHCPV6_ERROR_LINK) { + if (req_type == REQ_REQUEST) { + g_dhcp_client_unref(dhcp->dhcp_client); + start_solicitation(dhcp); + } else { + if (dhcp->callback) + dhcp->callback(dhcp->network, + CONNMAN_DHCPV6_STATUS_FAIL, NULL); + } + } else if (status == G_DHCPV6_ERROR_FAILURE) { + if (req_type == REQ_REQUEST) { + /* Rate limit the resend of request message */ + do_resend_request(dhcp); + } else { + if (dhcp->callback) + dhcp->callback(dhcp->network, + CONNMAN_DHCPV6_STATUS_FAIL, NULL); + } } else { - if (dhcp->callback != NULL) + + /* + * If we did not got any addresses, then re-send + * a request. + */ + GList *option; + + option = g_dhcp_client_get_option(dhcp->dhcp_client, + G_DHCPV6_IA_NA); + if (!option) { + option = g_dhcp_client_get_option(dhcp->dhcp_client, + G_DHCPV6_IA_TA); + if (!option) { + switch (req_type) { + case REQ_REQUEST: + dhcpv6_request(dhcp, true); + break; + case REQ_REBIND: + dhcpv6_rebind(dhcp); + break; + case REQ_RENEW: + dhcpv6_renew(dhcp); + break; + } + return; + } + } + + if (status == G_DHCPV6_ERROR_SUCCESS) + do_dad(dhcp_client, dhcp); + else if (dhcp->callback) dhcp->callback(dhcp->network, - status == 0 ? TRUE : FALSE); + CONNMAN_DHCPV6_STATUS_FAIL, NULL); } } @@ -590,11 +1118,9 @@ static void rebind_cb(GDHCPClient *dhcp_client, gpointer user_data) { DBG(""); - g_dhcpv6_client_reset_rebind(dhcp_client); - g_dhcpv6_client_reset_renew(dhcp_client); g_dhcpv6_client_clear_retransmit(dhcp_client); - re_cb(dhcp_client, user_data); + re_cb(REQ_REBIND, dhcp_client, user_data); } static int dhcpv6_rebind(struct connman_dhcpv6 *dhcp) @@ -617,8 +1143,8 @@ static int dhcpv6_rebind(struct connman_dhcpv6 *dhcp) g_dhcpv6_client_set_ia(dhcp_client, connman_network_get_index(dhcp->network), - dhcp->use_ta == TRUE ? G_DHCPV6_IA_TA : G_DHCPV6_IA_NA, - NULL, NULL, FALSE, NULL); + dhcp->use_ta ? G_DHCPV6_IA_TA : G_DHCPV6_IA_NA, + NULL, NULL, TRUE, NULL); clear_callbacks(dhcp_client); @@ -634,8 +1160,9 @@ static gboolean dhcpv6_restart(gpointer user_data) { struct connman_dhcpv6 *dhcp = user_data; - if (dhcp->callback != NULL) - dhcp->callback(dhcp->network, FALSE); + if (dhcp->callback) + dhcp->callback(dhcp->network, CONNMAN_DHCPV6_STATUS_FAIL, + NULL); return FALSE; } @@ -649,10 +1176,10 @@ static int check_restart(struct connman_dhcpv6 *dhcp) time_t current, expired; g_dhcpv6_client_get_timeouts(dhcp->dhcp_client, NULL, NULL, - NULL, NULL, &expired); + NULL, &expired); current = time(NULL); - if (current > expired) { + if (current >= expired) { DBG("expired by %d secs", (int)(current - expired)); g_timeout_add(0, dhcpv6_restart, dhcp); @@ -687,6 +1214,9 @@ static gboolean start_rebind(gpointer user_data) { struct connman_dhcpv6 *dhcp = user_data; + if (check_restart(dhcp) < 0) + return FALSE; + dhcp->RT = REB_TIMEOUT * (1 + get_random()); DBG("rebind initial RT timeout %d msec", dhcp->RT); @@ -702,13 +1232,14 @@ static void request_cb(GDHCPClient *dhcp_client, gpointer user_data) { DBG(""); + g_dhcpv6_client_reset_request(dhcp_client); g_dhcpv6_client_clear_retransmit(dhcp_client); - re_cb(dhcp_client, user_data); + re_cb(REQ_REQUEST, dhcp_client, user_data); } static int dhcpv6_request(struct connman_dhcpv6 *dhcp, - gboolean add_addresses) + bool add_addresses) { GDHCPClient *dhcp_client; uint32_t T1, T2; @@ -728,10 +1259,10 @@ static int dhcpv6_request(struct connman_dhcpv6 *dhcp, g_dhcpv6_client_set_oro(dhcp_client, 3, G_DHCPV6_DNS_SERVERS, G_DHCPV6_DOMAIN_LIST, G_DHCPV6_SNTP_SERVERS); - g_dhcpv6_client_get_timeouts(dhcp_client, &T1, &T2, NULL, NULL, NULL); + g_dhcpv6_client_get_timeouts(dhcp_client, &T1, &T2, NULL, NULL); g_dhcpv6_client_set_ia(dhcp_client, connman_network_get_index(dhcp->network), - dhcp->use_ta == TRUE ? G_DHCPV6_IA_TA : G_DHCPV6_IA_NA, + dhcp->use_ta ? G_DHCPV6_IA_TA : G_DHCPV6_IA_NA, &T1, &T2, add_addresses, NULL); clear_callbacks(dhcp_client); @@ -751,8 +1282,9 @@ static gboolean timeout_request(gpointer user_data) if (dhcp->request_count >= REQ_MAX_RC) { DBG("max request retry attempts %d", dhcp->request_count); dhcp->request_count = 0; - if (dhcp->callback != NULL) - dhcp->callback(dhcp->network, FALSE); + if (dhcp->callback) + dhcp->callback(dhcp->network, + CONNMAN_DHCPV6_STATUS_FAIL, NULL); return FALSE; } @@ -773,10 +1305,9 @@ static void renew_cb(GDHCPClient *dhcp_client, gpointer user_data) { DBG(""); - g_dhcpv6_client_reset_renew(dhcp_client); g_dhcpv6_client_clear_retransmit(dhcp_client); - re_cb(dhcp_client, user_data); + re_cb(REQ_RENEW, dhcp_client, user_data); } static int dhcpv6_renew(struct connman_dhcpv6 *dhcp) @@ -799,10 +1330,10 @@ static int dhcpv6_renew(struct connman_dhcpv6 *dhcp) g_dhcpv6_client_set_oro(dhcp_client, 3, G_DHCPV6_DNS_SERVERS, G_DHCPV6_DOMAIN_LIST, G_DHCPV6_SNTP_SERVERS); - g_dhcpv6_client_get_timeouts(dhcp_client, &T1, &T2, NULL, NULL, NULL); + g_dhcpv6_client_get_timeouts(dhcp_client, &T1, &T2, NULL, NULL); g_dhcpv6_client_set_ia(dhcp_client, connman_network_get_index(dhcp->network), - dhcp->use_ta == TRUE ? G_DHCPV6_IA_TA : G_DHCPV6_IA_NA, + dhcp->use_ta ? G_DHCPV6_IA_TA : G_DHCPV6_IA_NA, &T1, &T2, TRUE, NULL); clear_callbacks(dhcp_client); @@ -818,10 +1349,23 @@ static int dhcpv6_renew(struct connman_dhcpv6 *dhcp) static gboolean timeout_renew(gpointer user_data) { struct connman_dhcpv6 *dhcp = user_data; + time_t last_rebind, current; + uint32_t T2; if (check_restart(dhcp) < 0) return FALSE; + g_dhcpv6_client_get_timeouts(dhcp->dhcp_client, NULL, &T2, + &last_rebind, NULL); + current = time(NULL); + if ((unsigned)current >= (unsigned)last_rebind + T2) { + /* + * Do rebind instead if past T2 + */ + start_rebind(dhcp); + return FALSE; + } + dhcp->RT = calc_delay(dhcp->RT, REN_MAX_RT); DBG("renew RT timeout %d msec", dhcp->RT); @@ -851,14 +1395,14 @@ static gboolean start_renew(gpointer user_data) } int __connman_dhcpv6_start_renew(struct connman_network *network, - dhcp_cb callback) + dhcpv6_cb callback) { struct connman_dhcpv6 *dhcp; uint32_t T1, T2; - time_t last_renew, last_rebind, current, expired; + time_t started, current, expired; dhcp = g_hash_table_lookup(network_table, network); - if (dhcp == NULL) + if (!dhcp) return -ENOENT; DBG("network %p dhcp %p", network, dhcp); @@ -866,12 +1410,12 @@ int __connman_dhcpv6_start_renew(struct connman_network *network, clear_timer(dhcp); g_dhcpv6_client_get_timeouts(dhcp->dhcp_client, &T1, &T2, - &last_renew, &last_rebind, &expired); + &started, &expired); current = time(NULL); - DBG("T1 %u T2 %u expires %lu current %lu", T1, T2, - (unsigned long)expired, current); + DBG("T1 %u T2 %u expires %lu current %lu started %lu", T1, T2, + (unsigned long)expired, current, started); if (T1 == 0xffffffff) /* RFC 3315, 22.4 */ @@ -883,35 +1427,34 @@ int __connman_dhcpv6_start_renew(struct connman_network *network, */ T1 = 1800; + dhcp->callback = callback; + /* RFC 3315, 18.1.4, start solicit if expired */ - if (current > expired) { - DBG("expired by %d secs", (int)(current - expired)); - return -ETIMEDOUT; - } + if (check_restart(dhcp) < 0) + return 0; - dhcp->callback = callback; + if (T2 != 0xffffffff && T2 > 0) { + if ((unsigned)current >= (unsigned)started + T2) { + /* RFC 3315, chapter 18.1.3, start rebind */ + DBG("rebind after %d secs", T2); - if (T2 != 0xffffffff && T2 > 0 && - (unsigned)current > (unsigned)last_rebind + T2) { - int timeout; + dhcp->timeout = g_timeout_add_seconds(T2, start_rebind, + dhcp); - /* RFC 3315, chapter 18.1.3, start rebind */ - if ((unsigned)current > (unsigned)last_renew + T1) - timeout = 0; - else - timeout = last_renew - current + T1; + } else if ((unsigned)current < (unsigned)started + T1) { + DBG("renew after %d secs", T1); - /* - * If we just did a renew, do not restart the rebind - * immediately. - */ - dhcp->timeout = g_timeout_add_seconds(timeout, start_rebind, - dhcp); - } else { - DBG("renew after %d secs", T1); + dhcp->timeout = g_timeout_add_seconds(T1, start_renew, + dhcp); + } else { + DBG("rebind after %d secs", T2 - T1); - dhcp->timeout = g_timeout_add_seconds(T1, start_renew, dhcp); + dhcp->timeout = g_timeout_add_seconds(T2 - T1, + start_rebind, + dhcp); + } } + return 0; } @@ -921,28 +1464,28 @@ static void release_cb(GDHCPClient *dhcp_client, gpointer user_data) } int __connman_dhcpv6_start_release(struct connman_network *network, - dhcp_cb callback) + dhcpv6_cb callback) { struct connman_dhcpv6 *dhcp; GDHCPClient *dhcp_client; - if (network_table == NULL) + if (!network_table) return 0; /* we are already released */ dhcp = g_hash_table_lookup(network_table, network); - if (dhcp == NULL) + if (!dhcp) return -ENOENT; DBG("network %p dhcp %p client %p stateless %d", network, dhcp, dhcp->dhcp_client, dhcp->stateless); - if (dhcp->stateless == TRUE) + if (dhcp->stateless) return -EINVAL; clear_timer(dhcp); dhcp_client = dhcp->dhcp_client; - if (dhcp_client == NULL) { + if (!dhcp_client) { /* * We had started the DHCPv6 handshaking i.e., we have called * __connman_dhcpv6_start() but it has not yet sent @@ -961,7 +1504,7 @@ int __connman_dhcpv6_start_release(struct connman_network *network, g_dhcpv6_client_set_ia(dhcp_client, connman_network_get_index(dhcp->network), - dhcp->use_ta == TRUE ? G_DHCPV6_IA_TA : G_DHCPV6_IA_NA, + dhcp->use_ta ? G_DHCPV6_IA_TA : G_DHCPV6_IA_NA, NULL, NULL, TRUE, NULL); clear_callbacks(dhcp_client); @@ -991,7 +1534,7 @@ static int dhcpv6_release(struct connman_dhcpv6 *dhcp) dhcpv6_free(dhcp); - if (dhcp->dhcp_client == NULL) + if (!dhcp->dhcp_client) return 0; g_dhcp_client_stop(dhcp->dhcp_client); @@ -1047,27 +1590,27 @@ static gboolean start_info_req(gpointer user_data) } int __connman_dhcpv6_start_info(struct connman_network *network, - dhcp_cb callback) + dhcpv6_cb callback) { struct connman_dhcpv6 *dhcp; int delay; DBG(""); - if (network_table != NULL) { + if (network_table) { dhcp = g_hash_table_lookup(network_table, network); - if (dhcp != NULL && dhcp->started == TRUE) + if (dhcp && dhcp->started) return -EBUSY; } dhcp = g_try_new0(struct connman_dhcpv6, 1); - if (dhcp == NULL) + if (!dhcp) return -ENOMEM; dhcp->network = network; dhcp->callback = callback; - dhcp->stateless = TRUE; - dhcp->started = TRUE; + dhcp->stateless = true; + dhcp->started = true; connman_network_ref(network); @@ -1094,8 +1637,9 @@ static void advertise_cb(GDHCPClient *dhcp_client, gpointer user_data) g_dhcpv6_client_clear_retransmit(dhcp_client); if (g_dhcpv6_client_get_status(dhcp_client) != 0) { - if (dhcp->callback != NULL) - dhcp->callback(dhcp->network, FALSE); + if (dhcp->callback) + dhcp->callback(dhcp->network, + CONNMAN_DHCPV6_STATUS_FAIL, NULL); return; } @@ -1105,7 +1649,7 @@ static void advertise_cb(GDHCPClient *dhcp_client, gpointer user_data) dhcp->request_count = 1; - dhcpv6_request(dhcp, TRUE); + dhcpv6_request(dhcp, true); } static void solicitation_cb(GDHCPClient *dhcp_client, gpointer user_data) @@ -1117,7 +1661,7 @@ static void solicitation_cb(GDHCPClient *dhcp_client, gpointer user_data) clear_timer(dhcp); - set_addresses(dhcp_client, dhcp); + do_dad(dhcp_client, dhcp); g_dhcpv6_client_clear_retransmit(dhcp_client); } @@ -1161,7 +1705,7 @@ static int dhcpv6_solicitation(struct connman_dhcpv6 *dhcp) g_dhcp_client_set_debug(dhcp_client, dhcpv6_debug, "DHCPv6"); service = connman_service_lookup_from_network(dhcp->network); - if (service == NULL) { + if (!service) { clear_timer(dhcp); g_dhcp_client_unref(dhcp_client); return -EINVAL; @@ -1187,7 +1731,7 @@ static int dhcpv6_solicitation(struct connman_dhcpv6 *dhcp) dhcp->use_ta = __connman_ipconfig_ipv6_privacy_enabled(ipconfig_ipv6); g_dhcpv6_client_set_ia(dhcp_client, index, - dhcp->use_ta == TRUE ? G_DHCPV6_IA_TA : G_DHCPV6_IA_NA, + dhcp->use_ta ? G_DHCPV6_IA_TA : G_DHCPV6_IA_NA, NULL, NULL, FALSE, NULL); clear_callbacks(dhcp_client); @@ -1230,8 +1774,6 @@ static void confirm_cb(GDHCPClient *dhcp_client, gpointer user_data) clear_timer(dhcp); - set_addresses(dhcp_client, dhcp); - g_dhcpv6_client_clear_retransmit(dhcp_client); /* @@ -1240,8 +1782,9 @@ static void confirm_cb(GDHCPClient *dhcp_client, gpointer user_data) if (status != 0) { g_dhcp_client_unref(dhcp->dhcp_client); start_solicitation(dhcp); - } else if (dhcp->callback != NULL) - dhcp->callback(dhcp->network, TRUE); + } else { + do_dad(dhcp_client, dhcp); + } } static int dhcpv6_confirm(struct connman_dhcpv6 *dhcp) @@ -1266,7 +1809,7 @@ static int dhcpv6_confirm(struct connman_dhcpv6 *dhcp) g_dhcp_client_set_debug(dhcp_client, dhcpv6_debug, "DHCPv6"); service = connman_service_lookup_from_network(dhcp->network); - if (service == NULL) { + if (!service) { clear_timer(dhcp); g_dhcp_client_unref(dhcp_client); return -EINVAL; @@ -1281,18 +1824,12 @@ static int dhcpv6_confirm(struct connman_dhcpv6 *dhcp) g_dhcp_client_set_request(dhcp_client, G_DHCPV6_CLIENTID); g_dhcp_client_set_request(dhcp_client, G_DHCPV6_RAPID_COMMIT); - g_dhcp_client_set_request(dhcp_client, G_DHCPV6_DNS_SERVERS); - g_dhcp_client_set_request(dhcp_client, G_DHCPV6_DOMAIN_LIST); - g_dhcp_client_set_request(dhcp_client, G_DHCPV6_SNTP_SERVERS); - - g_dhcpv6_client_set_oro(dhcp_client, 3, G_DHCPV6_DNS_SERVERS, - G_DHCPV6_DOMAIN_LIST, G_DHCPV6_SNTP_SERVERS); ipconfig_ipv6 = __connman_service_get_ip6config(service); dhcp->use_ta = __connman_ipconfig_ipv6_privacy_enabled(ipconfig_ipv6); g_dhcpv6_client_set_ia(dhcp_client, index, - dhcp->use_ta == TRUE ? G_DHCPV6_IA_TA : G_DHCPV6_IA_NA, + dhcp->use_ta ? G_DHCPV6_IA_TA : G_DHCPV6_IA_NA, NULL, NULL, TRUE, __connman_ipconfig_get_dhcp_address(ipconfig_ipv6)); @@ -1336,8 +1873,9 @@ static gboolean timeout_max_confirm(gpointer user_data) g_dhcpv6_client_clear_retransmit(dhcp->dhcp_client); - if (dhcp->callback != NULL) - dhcp->callback(dhcp->network, FALSE); + if (dhcp->callback) + dhcp->callback(dhcp->network, CONNMAN_DHCPV6_STATUS_FAIL, + NULL); return FALSE; } @@ -1360,7 +1898,7 @@ static gboolean start_confirm(gpointer user_data) } int __connman_dhcpv6_start(struct connman_network *network, - GSList *prefixes, dhcp_cb callback) + GSList *prefixes, dhcpv6_cb callback) { struct connman_service *service; struct connman_ipconfig *ipconfig_ipv6; @@ -1370,24 +1908,24 @@ int __connman_dhcpv6_start(struct connman_network *network, DBG(""); - if (network_table != NULL) { + if (network_table) { dhcp = g_hash_table_lookup(network_table, network); - if (dhcp != NULL && dhcp->started == TRUE) + if (dhcp && dhcp->started) return -EBUSY; } service = connman_service_lookup_from_network(network); - if (service == NULL) + if (!service) return -EINVAL; dhcp = g_try_new0(struct connman_dhcpv6, 1); - if (dhcp == NULL) + if (!dhcp) return -ENOMEM; dhcp->network = network; dhcp->callback = callback; dhcp->prefixes = prefixes; - dhcp->started = TRUE; + dhcp->started = true; connman_network_ref(network); @@ -1401,7 +1939,7 @@ int __connman_dhcpv6_start(struct connman_network *network, ipconfig_ipv6 = __connman_service_get_ip6config(service); last_address = __connman_ipconfig_get_dhcp_address(ipconfig_ipv6); - if (prefixes != NULL && last_address != NULL && + if (prefixes && last_address && check_ipv6_addr_prefix(prefixes, last_address) != 128) { /* @@ -1424,10 +1962,810 @@ void __connman_dhcpv6_stop(struct connman_network *network) { DBG(""); - if (network_table == NULL) + if (!network_table) return; - if (g_hash_table_remove(network_table, network) == TRUE) + if (g_hash_table_remove(network_table, network)) + connman_network_unref(network); +} + +static int save_prefixes(struct connman_ipconfig *ipconfig, + GSList *prefixes) +{ + GSList *list; + int i = 0, count = g_slist_length(prefixes); + char **array; + + if (count == 0) + return 0; + + array = g_try_new0(char *, count + 1); + if (!array) + return -ENOMEM; + + for (list = prefixes; list; list = list->next) { + char *elem, addr_str[INET6_ADDRSTRLEN]; + GDHCPIAPrefix *prefix = list->data; + + elem = g_strdup_printf("%s/%d", inet_ntop(AF_INET6, + &prefix->prefix, addr_str, INET6_ADDRSTRLEN), + prefix->prefixlen); + if (!elem) { + g_strfreev(array); + return -ENOMEM; + } + + array[i++] = elem; + } + + __connman_ipconfig_set_dhcpv6_prefixes(ipconfig, array); + return 0; +} + +static GSList *load_prefixes(struct connman_ipconfig *ipconfig) +{ + int i; + GSList *list = NULL; + char **array = __connman_ipconfig_get_dhcpv6_prefixes(ipconfig); + + if (!array) + return NULL; + + for (i = 0; array[i]; i++) { + GDHCPIAPrefix *prefix; + long int value; + char *ptr, **elems = g_strsplit(array[i], "/", 0); + + if (!elems) + return list; + + value = strtol(elems[1], &ptr, 10); + if (ptr != elems[1] && *ptr == '\0' && value <= 128) { + struct in6_addr addr; + + if (inet_pton(AF_INET6, elems[0], &addr) == 1) { + prefix = g_try_new0(GDHCPIAPrefix, 1); + if (!prefix) { + g_strfreev(elems); + return list; + } + memcpy(&prefix->prefix, &addr, + sizeof(struct in6_addr)); + prefix->prefixlen = value; + + list = g_slist_prepend(list, prefix); + } + } + + g_strfreev(elems); + } + + return list; +} + +static GDHCPIAPrefix *copy_prefix(gpointer data) +{ + GDHCPIAPrefix *copy, *prefix = data; + + copy = g_try_new(GDHCPIAPrefix, 1); + if (!copy) + return NULL; + + memcpy(copy, prefix, sizeof(GDHCPIAPrefix)); + + return copy; +} + +static GSList *copy_and_convert_prefixes(GList *prefixes) +{ + GSList *copy = NULL; + GList *list; + + for (list = prefixes; list; list = list->next) + copy = g_slist_prepend(copy, copy_prefix(list->data)); + + return copy; +} + +static int set_prefixes(GDHCPClient *dhcp_client, struct connman_dhcpv6 *dhcp) +{ + if (dhcp->prefixes) + g_slist_free_full(dhcp->prefixes, free_prefix); + + dhcp->prefixes = + copy_and_convert_prefixes(g_dhcp_client_get_option(dhcp_client, + G_DHCPV6_IA_PD)); + + DBG("Got %d prefix", g_slist_length(dhcp->prefixes)); + + if (dhcp->callback) { + uint16_t status = g_dhcpv6_client_get_status(dhcp_client); + if (status == G_DHCPV6_ERROR_NO_PREFIX) + dhcp->callback(dhcp->network, + CONNMAN_DHCPV6_STATUS_FAIL, NULL); + else { + struct connman_service *service; + struct connman_ipconfig *ipconfig; + int ifindex = connman_network_get_index(dhcp->network); + + service = __connman_service_lookup_from_index(ifindex); + if (service) { + ipconfig = __connman_service_get_ip6config( + service); + save_prefixes(ipconfig, dhcp->prefixes); + __connman_service_save(service); + } + + dhcp->callback(dhcp->network, + CONNMAN_DHCPV6_STATUS_SUCCEED, dhcp->prefixes); + } + } else { + g_slist_free_full(dhcp->prefixes, free_prefix); + dhcp->prefixes = NULL; + } + + return 0; +} + +static void re_pd_cb(GDHCPClient *dhcp_client, gpointer user_data) +{ + struct connman_dhcpv6 *dhcp = user_data; + uint16_t status; + int ret; + + status = g_dhcpv6_client_get_status(dhcp_client); + + DBG("dhcpv6 cb msg %p status %d", dhcp, status); + + if (status == G_DHCPV6_ERROR_BINDING) { + /* RFC 3315, 18.1.8 */ + dhcpv6_pd_request(dhcp); + } else { + ret = set_prefixes(dhcp_client, dhcp); + if (ret < 0) { + if (dhcp->callback) + dhcp->callback(dhcp->network, + CONNMAN_DHCPV6_STATUS_FAIL, NULL); + return; + } + } +} + +static void rebind_pd_cb(GDHCPClient *dhcp_client, gpointer user_data) +{ + DBG(""); + + g_dhcpv6_client_clear_retransmit(dhcp_client); + + re_pd_cb(dhcp_client, user_data); +} + +static GDHCPClient *create_pd_client(struct connman_dhcpv6 *dhcp, int *err) +{ + GDHCPClient *dhcp_client; + GDHCPClientError error; + struct connman_service *service; + int index, ret; + uint32_t iaid; + + index = connman_network_get_index(dhcp->network); + + dhcp_client = g_dhcp_client_new(G_DHCP_IPV6, index, &error); + if (error != G_DHCP_CLIENT_ERROR_NONE) { + *err = -EINVAL; + return NULL; + } + + if (getenv("CONNMAN_DHCPV6_DEBUG")) + g_dhcp_client_set_debug(dhcp_client, dhcpv6_debug, "DHCPv6:PD"); + + service = connman_service_lookup_from_network(dhcp->network); + if (!service) { + g_dhcp_client_unref(dhcp_client); + *err = -EINVAL; + return NULL; + } + + ret = set_duid(service, dhcp->network, dhcp_client, index); + if (ret < 0) { + g_dhcp_client_unref(dhcp_client); + *err = ret; + return NULL; + } + + g_dhcpv6_client_create_iaid(dhcp_client, index, (unsigned char *)&iaid); + g_dhcpv6_client_set_iaid(dhcp_client, iaid); + + return dhcp_client; +} + +static int dhcpv6_pd_rebind(struct connman_dhcpv6 *dhcp) +{ + GDHCPClient *dhcp_client; + uint32_t T1, T2; + + DBG("dhcp %p", dhcp); + + if (!dhcp->dhcp_client) { + /* + * We skipped the solicitation phase + */ + int err; + + dhcp->dhcp_client = create_pd_client(dhcp, &err); + if (!dhcp->dhcp_client) { + clear_timer(dhcp); + return err; + } + } + + dhcp_client = dhcp->dhcp_client; + + g_dhcp_client_clear_requests(dhcp_client); + + g_dhcp_client_set_request(dhcp_client, G_DHCPV6_CLIENTID); + g_dhcp_client_set_request(dhcp_client, G_DHCPV6_DNS_SERVERS); + g_dhcp_client_set_request(dhcp_client, G_DHCPV6_SNTP_SERVERS); + + g_dhcpv6_client_get_timeouts(dhcp_client, &T1, &T2, NULL, NULL); + g_dhcpv6_client_set_pd(dhcp_client, &T1, &T2, dhcp->prefixes); + + clear_callbacks(dhcp_client); + + g_dhcp_client_register_event(dhcp_client, G_DHCP_CLIENT_EVENT_REBIND, + rebind_pd_cb, dhcp); + + return g_dhcp_client_start(dhcp_client, NULL); +} + +static void renew_pd_cb(GDHCPClient *dhcp_client, gpointer user_data) +{ + DBG(""); + + g_dhcpv6_client_clear_retransmit(dhcp_client); + + re_pd_cb(dhcp_client, user_data); +} + +static int dhcpv6_pd_renew(struct connman_dhcpv6 *dhcp) +{ + GDHCPClient *dhcp_client; + uint32_t T1, T2; + + DBG("dhcp %p", dhcp); + + dhcp_client = dhcp->dhcp_client; + + g_dhcp_client_clear_requests(dhcp_client); + + g_dhcp_client_set_request(dhcp_client, G_DHCPV6_CLIENTID); + g_dhcp_client_set_request(dhcp_client, G_DHCPV6_SERVERID); + g_dhcp_client_set_request(dhcp_client, G_DHCPV6_DNS_SERVERS); + g_dhcp_client_set_request(dhcp_client, G_DHCPV6_SNTP_SERVERS); + + g_dhcpv6_client_get_timeouts(dhcp_client, &T1, &T2, NULL, NULL); + g_dhcpv6_client_set_pd(dhcp_client, &T1, &T2, dhcp->prefixes); + + clear_callbacks(dhcp_client); + + g_dhcp_client_register_event(dhcp_client, G_DHCP_CLIENT_EVENT_RENEW, + renew_pd_cb, dhcp); + + return g_dhcp_client_start(dhcp_client, NULL); +} + +/* + * Check if we need to restart the solicitation procedure. This + * is done if all the prefixes have expired. + */ +static int check_pd_restart(struct connman_dhcpv6 *dhcp) +{ + time_t current, expired; + + g_dhcpv6_client_get_timeouts(dhcp->dhcp_client, NULL, NULL, + NULL, &expired); + current = time(NULL); + + if (current > expired) { + DBG("expired by %d secs", (int)(current - expired)); + + g_timeout_add(0, dhcpv6_restart, dhcp); + + return -ETIMEDOUT; + } + + return 0; +} + +static gboolean timeout_pd_rebind(gpointer user_data) +{ + struct connman_dhcpv6 *dhcp = user_data; + + if (check_pd_restart(dhcp) < 0) + return FALSE; + + dhcp->RT = calc_delay(dhcp->RT, REB_MAX_RT); + + DBG("rebind RT timeout %d msec", dhcp->RT); + + dhcp->timeout = g_timeout_add(dhcp->RT, timeout_pd_rebind, dhcp); + + g_dhcpv6_client_set_retransmit(dhcp->dhcp_client); + + g_dhcp_client_start(dhcp->dhcp_client, NULL); + + return FALSE; +} + +static gboolean start_pd_rebind(gpointer user_data) +{ + struct connman_dhcpv6 *dhcp = user_data; + + if (check_pd_restart(dhcp) < 0) + return FALSE; + + dhcp->RT = REB_TIMEOUT * (1 + get_random()); + + DBG("rebind initial RT timeout %d msec", dhcp->RT); + + dhcp->timeout = g_timeout_add(dhcp->RT, timeout_pd_rebind, dhcp); + + dhcpv6_pd_rebind(dhcp); + + return FALSE; +} + +static gboolean timeout_pd_rebind_confirm(gpointer user_data) +{ + struct connman_dhcpv6 *dhcp = user_data; + + dhcp->RT = calc_delay(dhcp->RT, CNF_MAX_RT); + + DBG("rebind with confirm RT timeout %d msec", dhcp->RT); + + dhcp->timeout = g_timeout_add(dhcp->RT, + timeout_pd_rebind_confirm, dhcp); + + g_dhcpv6_client_set_retransmit(dhcp->dhcp_client); + + g_dhcp_client_start(dhcp->dhcp_client, NULL); + + return FALSE; +} + +static gboolean timeout_pd_max_confirm(gpointer user_data) +{ + struct connman_dhcpv6 *dhcp = user_data; + + dhcp->MRD = 0; + + clear_timer(dhcp); + + DBG("rebind with confirm max retransmit duration timeout"); + + g_dhcpv6_client_clear_retransmit(dhcp->dhcp_client); + + if (dhcp->callback) + dhcp->callback(dhcp->network, + CONNMAN_DHCPV6_STATUS_FAIL, NULL); + + return FALSE; +} + +static gboolean start_pd_rebind_with_confirm(gpointer user_data) +{ + struct connman_dhcpv6 *dhcp = user_data; + + dhcp->RT = CNF_TIMEOUT * (1 + get_random()); + + DBG("rebind with confirm initial RT timeout %d msec", dhcp->RT); + + dhcp->timeout = g_timeout_add(dhcp->RT, + timeout_pd_rebind_confirm, dhcp); + dhcp->MRD = g_timeout_add(CNF_MAX_RD, timeout_pd_max_confirm, dhcp); + + dhcpv6_pd_rebind(dhcp); + + return FALSE; +} + +static gboolean timeout_pd_renew(gpointer user_data) +{ + struct connman_dhcpv6 *dhcp = user_data; + + if (check_pd_restart(dhcp) < 0) + return FALSE; + + dhcp->RT = calc_delay(dhcp->RT, REN_MAX_RT); + + DBG("renew RT timeout %d msec", dhcp->RT); + + dhcp->timeout = g_timeout_add(dhcp->RT, timeout_renew, dhcp); + + g_dhcpv6_client_set_retransmit(dhcp->dhcp_client); + + g_dhcp_client_start(dhcp->dhcp_client, NULL); + + return FALSE; +} + +static gboolean start_pd_renew(gpointer user_data) +{ + struct connman_dhcpv6 *dhcp = user_data; + + dhcp->RT = REN_TIMEOUT * (1 + get_random()); + + DBG("renew initial RT timeout %d msec", dhcp->RT); + + dhcp->timeout = g_timeout_add(dhcp->RT, timeout_pd_renew, dhcp); + + dhcpv6_pd_renew(dhcp); + + return FALSE; +} + +int __connman_dhcpv6_start_pd_renew(struct connman_network *network, + dhcpv6_cb callback) +{ + struct connman_dhcpv6 *dhcp; + uint32_t T1, T2; + time_t started, current, expired; + + dhcp = g_hash_table_lookup(network_pd_table, network); + if (!dhcp) + return -ENOENT; + + DBG("network %p dhcp %p", network, dhcp); + + clear_timer(dhcp); + + g_dhcpv6_client_get_timeouts(dhcp->dhcp_client, &T1, &T2, + &started, &expired); + + current = time(NULL); + + DBG("T1 %u T2 %u expires %lu current %lu started %lu", T1, T2, + expired, current, started); + + if (T1 == 0xffffffff) + /* RFC 3633, ch 9 */ + return 0; + + if (T1 == 0) + /* RFC 3633, ch 9 + * Client can choose the timeout. + */ + T1 = 120; + + dhcp->callback = callback; + + /* RFC 3315, 18.1.4, start solicit if expired */ + if (check_pd_restart(dhcp) < 0) + return 0; + + if (T2 != 0xffffffff && T2 > 0) { + if ((unsigned)current >= (unsigned)started + T2) { + /* RFC 3315, chapter 18.1.3, start rebind */ + DBG("rebind after %d secs", T2); + + dhcp->timeout = g_timeout_add_seconds(T2, + start_pd_rebind, + dhcp); + + } else if ((unsigned)current < (unsigned)started + T1) { + DBG("renew after %d secs", T1); + + dhcp->timeout = g_timeout_add_seconds(T1, + start_pd_renew, + dhcp); + } else { + DBG("rebind after %d secs", T2 - T1); + + dhcp->timeout = g_timeout_add_seconds(T2 - T1, + start_pd_rebind, + dhcp); + } + } + + return 0; +} + +static void release_pd_cb(GDHCPClient *dhcp_client, gpointer user_data) +{ + DBG(""); +} + +int __connman_dhcpv6_start_pd_release(struct connman_network *network, + dhcpv6_cb callback) +{ + struct connman_dhcpv6 *dhcp; + GDHCPClient *dhcp_client; + uint32_t T1, T2; + + if (!network_table) + return 0; /* we are already released */ + + dhcp = g_hash_table_lookup(network_pd_table, network); + if (!dhcp) + return -ENOENT; + + DBG("network %p dhcp %p client %p", network, dhcp, dhcp->dhcp_client); + + clear_timer(dhcp); + + dhcp_client = dhcp->dhcp_client; + if (!dhcp_client) { + DBG("DHCPv6 PD was not started"); + return 0; + } + + g_dhcp_client_clear_requests(dhcp_client); + g_dhcp_client_clear_values(dhcp_client); + + g_dhcp_client_set_request(dhcp_client, G_DHCPV6_CLIENTID); + g_dhcp_client_set_request(dhcp_client, G_DHCPV6_SERVERID); + + g_dhcpv6_client_get_timeouts(dhcp_client, &T1, &T2, NULL, NULL); + g_dhcpv6_client_set_pd(dhcp_client, &T1, &T2, dhcp->prefixes); + + clear_callbacks(dhcp_client); + + g_dhcp_client_register_event(dhcp_client, G_DHCP_CLIENT_EVENT_RELEASE, + release_pd_cb, dhcp); + + dhcp->dhcp_client = dhcp_client; + + return g_dhcp_client_start(dhcp_client, NULL); +} + +static gboolean timeout_pd_request(gpointer user_data) +{ + struct connman_dhcpv6 *dhcp = user_data; + + if (dhcp->request_count >= REQ_MAX_RC) { + DBG("max request retry attempts %d", dhcp->request_count); + dhcp->request_count = 0; + if (dhcp->callback) + dhcp->callback(dhcp->network, + CONNMAN_DHCPV6_STATUS_FAIL, NULL); + return FALSE; + } + + dhcp->request_count++; + + dhcp->RT = calc_delay(dhcp->RT, REQ_MAX_RT); + DBG("request RT timeout %d msec", dhcp->RT); + dhcp->timeout = g_timeout_add(dhcp->RT, timeout_pd_request, dhcp); + + g_dhcpv6_client_set_retransmit(dhcp->dhcp_client); + + g_dhcp_client_start(dhcp->dhcp_client, NULL); + + return FALSE; +} + +static void request_pd_cb(GDHCPClient *dhcp_client, gpointer user_data) +{ + struct connman_dhcpv6 *dhcp = user_data; + uint16_t status; + + DBG(""); + + g_dhcpv6_client_clear_retransmit(dhcp_client); + + status = g_dhcpv6_client_get_status(dhcp_client); + + DBG("dhcpv6 pd cb msg %p status %d", dhcp, status); + + if (status == G_DHCPV6_ERROR_BINDING) { + /* RFC 3315, 18.1.8 */ + dhcpv6_pd_request(dhcp); + } else { + set_prefixes(dhcp_client, dhcp); + } +} + +static int dhcpv6_pd_request(struct connman_dhcpv6 *dhcp) +{ + GDHCPClient *dhcp_client; + uint32_t T1 = 0, T2 = 0; + + DBG("dhcp %p", dhcp); + + dhcp_client = dhcp->dhcp_client; + + g_dhcp_client_clear_requests(dhcp_client); + + g_dhcp_client_set_request(dhcp_client, G_DHCPV6_CLIENTID); + g_dhcp_client_set_request(dhcp_client, G_DHCPV6_SERVERID); + g_dhcp_client_set_request(dhcp_client, G_DHCPV6_DNS_SERVERS); + g_dhcp_client_set_request(dhcp_client, G_DHCPV6_SNTP_SERVERS); + + g_dhcpv6_client_get_timeouts(dhcp_client, &T1, &T2, NULL, NULL); + g_dhcpv6_client_set_pd(dhcp_client, &T1, &T2, dhcp->prefixes); + + clear_callbacks(dhcp_client); + + g_dhcp_client_register_event(dhcp_client, G_DHCP_CLIENT_EVENT_REQUEST, + request_pd_cb, dhcp); + + return g_dhcp_client_start(dhcp_client, NULL); +} + +static void advertise_pd_cb(GDHCPClient *dhcp_client, gpointer user_data) +{ + struct connman_dhcpv6 *dhcp = user_data; + + DBG("dhcpv6 advertise pd msg %p", dhcp); + + clear_timer(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; + } + + dhcp->RT = REQ_TIMEOUT * (1 + get_random()); + DBG("request initial RT timeout %d msec", dhcp->RT); + dhcp->timeout = g_timeout_add(dhcp->RT, timeout_pd_request, dhcp); + + dhcp->request_count = 1; + + dhcpv6_pd_request(dhcp); +} + +static void solicitation_pd_cb(GDHCPClient *dhcp_client, gpointer user_data) +{ + /* + * This callback is here so that g_dhcp_client_start() + * will enter the proper L3 mode. + */ + DBG("DHCPv6 %p solicitation msg received, ignoring it", user_data); +} + +static int dhcpv6_pd_solicitation(struct connman_dhcpv6 *dhcp) +{ + GDHCPClient *dhcp_client; + int ret; + + DBG("dhcp %p", dhcp); + + dhcp_client = create_pd_client(dhcp, &ret); + if (!dhcp_client) { + clear_timer(dhcp); + return ret; + } + + g_dhcp_client_set_request(dhcp_client, G_DHCPV6_CLIENTID); + + g_dhcpv6_client_set_pd(dhcp_client, NULL, NULL, NULL); + + clear_callbacks(dhcp_client); + + g_dhcp_client_register_event(dhcp_client, + G_DHCP_CLIENT_EVENT_ADVERTISE, + advertise_pd_cb, dhcp); + + g_dhcp_client_register_event(dhcp_client, + G_DHCP_CLIENT_EVENT_SOLICITATION, + solicitation_pd_cb, dhcp); + + dhcp->dhcp_client = dhcp_client; + + return g_dhcp_client_start(dhcp_client, NULL); +} + +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()); + + DBG("solicit initial RT timeout %d msec", dhcp->RT); + + dhcp->timeout = g_timeout_add(dhcp->RT, timeout_solicitation, dhcp); + + dhcpv6_pd_solicitation(dhcp); + + return FALSE; +} + +int __connman_dhcpv6_start_pd(int index, GSList *prefixes, dhcpv6_cb callback) +{ + struct connman_service *service; + struct connman_network *network; + struct connman_dhcpv6 *dhcp; + + if (index < 0) + return 0; + + DBG("index %d", index); + + service = __connman_service_lookup_from_index(index); + if (!service) + return -EINVAL; + + network = __connman_service_get_network(service); + if (!network) + return -EINVAL; + + if (network_pd_table) { + dhcp = g_hash_table_lookup(network_pd_table, network); + if (dhcp && dhcp->started) + return -EBUSY; + } + + dhcp = g_try_new0(struct connman_dhcpv6, 1); + if (!dhcp) + return -ENOMEM; + + dhcp->network = network; + dhcp->callback = callback; + dhcp->started = true; + + if (!prefixes) { + /* + * Try to load the earlier prefixes if caller did not supply + * any that we could use. + */ + struct connman_ipconfig *ipconfig; + ipconfig = __connman_service_get_ip6config(service); + + dhcp->prefixes = load_prefixes(ipconfig); + } else + dhcp->prefixes = prefixes; + + connman_network_ref(network); + + DBG("replace network %p dhcp %p", network, dhcp); + + g_hash_table_replace(network_pd_table, network, dhcp); + + if (!dhcp->prefixes) { + /* + * Refresh start, try to get prefixes. + */ + start_pd_solicitation(dhcp); + } else { + /* + * We used to have prefixes, try to use them again. + * We need to use timeouts from confirm msg, RFC 3633, ch 12.1 + */ + start_pd_rebind_with_confirm(dhcp); + } + + return 0; +} + +void __connman_dhcpv6_stop_pd(int index) +{ + struct connman_service *service; + struct connman_network *network; + + if (index < 0) + return; + + DBG("index %d", index); + + if (!network_pd_table) + return; + + service = __connman_service_lookup_from_index(index); + if (!service) + return; + + network = __connman_service_get_network(service); + if (!network) + return; + + __connman_dhcpv6_start_pd_release(network, NULL); + + if (g_hash_table_remove(network_pd_table, network)) connman_network_unref(network); } @@ -1440,6 +2778,9 @@ int __connman_dhcpv6_init(void) network_table = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, remove_network); + network_pd_table = g_hash_table_new_full(g_direct_hash, g_direct_equal, + NULL, remove_network); + return 0; } @@ -1449,4 +2790,7 @@ void __connman_dhcpv6_cleanup(void) g_hash_table_destroy(network_table); network_table = NULL; + + g_hash_table_destroy(network_pd_table); + network_pd_table = NULL; } diff --git a/src/dnsproxy.c b/src/dnsproxy.c index 9030a355..7232b987 100644 --- a/src/dnsproxy.c +++ b/src/dnsproxy.c @@ -2,7 +2,7 @@ * * Connection Manager * - * Copyright (C) 2007-2012 Intel Corporation. All rights reserved. + * Copyright (C) 2007-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 @@ -93,8 +93,8 @@ struct server_data { GIOChannel *channel; guint watch; guint timeout; - gboolean enabled; - gboolean connected; + bool enabled; + bool connected; struct partial_reply *incoming_reply; }; @@ -120,7 +120,7 @@ struct request_data { gpointer resp; gsize resplen; struct listener_data *ifdata; - gboolean append_domain; + bool append_domain; }; struct listener_data { @@ -164,7 +164,7 @@ struct cache_data { struct cache_entry { char *key; - int want_refresh; + bool want_refresh; int hits; struct cache_data *ipv4; struct cache_data *ipv6; @@ -216,7 +216,7 @@ static GHashTable *listener_table = NULL; static time_t next_refresh; static GHashTable *partial_tcp_req_table; -static guint16 get_id() +static guint16 get_id(void) { return random(); } @@ -283,16 +283,16 @@ static struct server_data *find_server(int index, struct server_data *data = list->data; if (index < 0 && data->index < 0 && - g_str_equal(data->server, server) == TRUE && + g_str_equal(data->server, server) && data->protocol == protocol) return data; if (index < 0 || - data->index < 0 || data->server == NULL) + data->index < 0 || !data->server) continue; if (data->index == index && - g_str_equal(data->server, server) == TRUE && + g_str_equal(data->server, server) && data->protocol == protocol) return data; } @@ -315,26 +315,26 @@ static void refresh_dns_entry(struct cache_entry *entry, char *name) { int age = 1; - if (ipv4_resolve == NULL) { + if (!ipv4_resolve) { ipv4_resolve = g_resolv_new(0); g_resolv_set_address_family(ipv4_resolve, AF_INET); g_resolv_add_nameserver(ipv4_resolve, "127.0.0.1", 53, 0); } - if (ipv6_resolve == NULL) { + if (!ipv6_resolve) { ipv6_resolve = g_resolv_new(0); g_resolv_set_address_family(ipv6_resolve, AF_INET6); g_resolv_add_nameserver(ipv6_resolve, "::1", 53, 0); } - if (entry->ipv4 == NULL) { + if (!entry->ipv4) { DBG("Refresing A record for %s", name); g_resolv_lookup_hostname(ipv4_resolve, name, dummy_resolve_func, NULL); age = 4; } - if (entry->ipv6 == NULL) { + if (!entry->ipv6) { DBG("Refresing AAAA record for %s", name); g_resolv_lookup_hostname(ipv6_resolve, name, dummy_resolve_func, NULL); @@ -505,7 +505,7 @@ static int get_req_udp_socket(struct request_data *req) else channel = req->ifdata->udp6_listener_channel; - if (channel == NULL) + if (!channel) return -1; return g_io_channel_unix_get_fd(channel); @@ -526,7 +526,7 @@ static gboolean request_timeout(gpointer user_data) { struct request_data *req = user_data; - if (req == NULL) + if (!req) return FALSE; DBG("id 0x%04x", req->srcid); @@ -534,7 +534,7 @@ static gboolean request_timeout(gpointer user_data) request_list = g_slist_remove(request_list, req); req->numserv--; - if (req->resplen > 0 && req->resp != NULL) { + if (req->resplen > 0 && req->resp) { int sk, err; if (req->protocol == IPPROTO_UDP) { @@ -599,11 +599,11 @@ static int append_query(unsigned char *buf, unsigned int size, DBG("query %s domain %s", query, domain); - while (query != NULL) { + while (query) { const char *tmp; tmp = strchr(query, '.'); - if (tmp == NULL) { + if (!tmp) { len = strlen(query); if (len == 0) break; @@ -620,11 +620,11 @@ static int append_query(unsigned char *buf, unsigned int size, query = tmp + 1; } - while (domain != NULL) { + while (domain) { const char *tmp; tmp = strchr(domain, '.'); - if (tmp == NULL) { + if (!tmp) { len = strlen(domain); if (len == 0) break; @@ -646,16 +646,16 @@ static int append_query(unsigned char *buf, unsigned int size, return ptr - buf; } -static gboolean cache_check_is_valid(struct cache_data *data, +static bool cache_check_is_valid(struct cache_data *data, time_t current_time) { - if (data == NULL) - return FALSE; + if (!data) + return false; if (data->cache_until < current_time) - return FALSE; + return false; - return TRUE; + return true; } /* @@ -665,7 +665,7 @@ static void cache_enforce_validity(struct cache_entry *entry) { time_t current_time = time(NULL); - if (cache_check_is_valid(entry->ipv4, current_time) == FALSE + if (!cache_check_is_valid(entry->ipv4, current_time) && entry->ipv4) { DBG("cache timeout \"%s\" type A", entry->key); g_free(entry->ipv4->data); @@ -674,7 +674,7 @@ static void cache_enforce_validity(struct cache_entry *entry) } - if (cache_check_is_valid(entry->ipv6, current_time) == FALSE + if (!cache_check_is_valid(entry->ipv6, current_time) && entry->ipv6) { DBG("cache timeout \"%s\" type AAAA", entry->key); g_free(entry->ipv6->data); @@ -687,32 +687,31 @@ static uint16_t cache_check_validity(char *question, uint16_t type, struct cache_entry *entry) { time_t current_time = time(NULL); - int want_refresh = 0; + bool want_refresh = false; /* * if we have a popular entry, we want a refresh instead of * total destruction of the entry. */ if (entry->hits > 2) - want_refresh = 1; + want_refresh = true; cache_enforce_validity(entry); switch (type) { case 1: /* IPv4 */ - if (cache_check_is_valid(entry->ipv4, current_time) == FALSE) { + if (!cache_check_is_valid(entry->ipv4, current_time)) { DBG("cache %s \"%s\" type A", entry->ipv4 ? "timeout" : "entry missing", question); if (want_refresh) - entry->want_refresh = 1; + entry->want_refresh = true; /* * We do not remove cache entry if there is still * valid IPv6 entry found in the cache. */ - if (cache_check_is_valid(entry->ipv6, current_time) - == FALSE && want_refresh == FALSE) { + if (!cache_check_is_valid(entry->ipv6, current_time) && !want_refresh) { g_hash_table_remove(cache, question); type = 0; } @@ -720,15 +719,14 @@ static uint16_t cache_check_validity(char *question, uint16_t type, break; case 28: /* IPv6 */ - if (cache_check_is_valid(entry->ipv6, current_time) == FALSE) { + if (!cache_check_is_valid(entry->ipv6, current_time)) { DBG("cache %s \"%s\" type AAAA", entry->ipv6 ? "timeout" : "entry missing", question); if (want_refresh) - entry->want_refresh = 1; + entry->want_refresh = true; - if (cache_check_is_valid(entry->ipv4, current_time) - == FALSE && want_refresh == FALSE) { + if (!cache_check_is_valid(entry->ipv4, current_time) && !want_refresh) { g_hash_table_remove(cache, question); type = 0; } @@ -743,15 +741,15 @@ static void cache_element_destroy(gpointer value) { struct cache_entry *entry = value; - if (entry == NULL) + if (!entry) return; - if (entry->ipv4 != NULL) { + if (entry->ipv4) { g_free(entry->ipv4->data); g_free(entry->ipv4); } - if (entry->ipv6 != NULL) { + if (entry->ipv6) { g_free(entry->ipv6->data); g_free(entry->ipv6); } @@ -775,7 +773,7 @@ static gboolean try_remove_cache(gpointer user_data) return FALSE; } -static void create_cache() +static void create_cache(void) { if (__sync_fetch_and_add(&cache_refcount, 1) == 0) cache = g_hash_table_new_full(g_str_hash, @@ -792,7 +790,7 @@ static struct cache_entry *cache_check(gpointer request, int *qtype, int proto) uint16_t type; int offset, proto_offset; - if (request == NULL) + if (!request) return NULL; proto_offset = protocol_offset(proto); @@ -809,13 +807,13 @@ static struct cache_entry *cache_check(gpointer request, int *qtype, int proto) if (type != 1 && type != 28) return NULL; - if (cache == NULL) { + if (!cache) { create_cache(); return NULL; } entry = g_hash_table_lookup(cache, question); - if (entry == NULL) + if (!entry) return NULL; type = cache_check_validity(question, type, entry); @@ -852,7 +850,7 @@ static int get_name(int counter, if (offset >= max - pkt) return -ENOBUFS; - if (*end == NULL) + if (!*end) *end = p + 2; return get_name(counter + 1, pkt, pkt + offset, max, @@ -882,7 +880,7 @@ static int get_name(int counter, p += label_len + 1; - if (*end == NULL) + if (!*end) *end = p; if (p >= max) @@ -916,7 +914,7 @@ static int parse_rr(unsigned char *buf, unsigned char *start, rr = (void *) (*end); - if (rr == NULL) + if (!rr) return -EINVAL; *type = ntohs(rr->type); @@ -944,19 +942,19 @@ static int parse_rr(unsigned char *buf, unsigned char *start, return 0; } -static gboolean check_alias(GSList *aliases, char *name) +static bool check_alias(GSList *aliases, char *name) { GSList *list; - if (aliases != NULL) { + if (aliases) { for (list = aliases; list; list = list->next) { int len = strlen((char *)list->data); if (strncmp((char *)list->data, name, len) == 0) - return TRUE; + return true; } } - return FALSE; + return false; } static int parse_response(unsigned char *buf, int buflen, @@ -1007,6 +1005,8 @@ static int parse_response(unsigned char *buf, int buflen, *response_len = 0; *answers = 0; + memset(name, 0, sizeof(name)); + /* * We have a bunch of answers (like A, AAAA, CNAME etc) to * A or AAAA question. We traverse the answers and parse the @@ -1120,8 +1120,8 @@ static int parse_response(unsigned char *buf, int buflen, /* * We found correct type (A or AAAA) */ - if (check_alias(aliases, name) == TRUE || - (aliases == NULL && strncmp(question, name, + if (check_alias(aliases, name) || + (!aliases && strncmp(question, name, qlen) == 0)) { /* * We found an alias or the name of the rr @@ -1176,7 +1176,7 @@ static gboolean cache_check_entry(gpointer key, gpointer value, * remove both from the cache. */ - if (entry->ipv4 != NULL && entry->ipv4->timeout > 0) { + if (entry->ipv4 && entry->ipv4->timeout > 0) { max_timeout = entry->ipv4->cache_until; if (max_timeout > data->max_timeout) data->max_timeout = max_timeout; @@ -1185,7 +1185,7 @@ static gboolean cache_check_entry(gpointer key, gpointer value, return TRUE; } - if (entry->ipv6 != NULL && entry->ipv6->timeout > 0) { + if (entry->ipv6 && entry->ipv6->timeout > 0) { max_timeout = entry->ipv6->cache_until; if (max_timeout > data->max_timeout) data->max_timeout = max_timeout; @@ -1257,7 +1257,7 @@ static gboolean cache_invalidate_entry(gpointer key, gpointer value, /* if anything is not expired, mark the entry for refresh */ if (entry->hits > 0 && (entry->ipv4 || entry->ipv6)) - entry->want_refresh = 1; + entry->want_refresh = true; /* delete the cached data */ if (entry->ipv4) { @@ -1289,7 +1289,7 @@ static void cache_invalidate(void) { DBG("Invalidating the DNS cache %p", cache); - if (cache == NULL) + if (!cache) return; g_hash_table_foreach_remove(cache, cache_invalidate_entry, NULL); @@ -1300,15 +1300,15 @@ static void cache_refresh_entry(struct cache_entry *entry) cache_enforce_validity(entry); - if (entry->hits > 2 && entry->ipv4 == NULL) - entry->want_refresh = 1; - if (entry->hits > 2 && entry->ipv6 == NULL) - entry->want_refresh = 1; + if (entry->hits > 2 && !entry->ipv4) + entry->want_refresh = true; + if (entry->hits > 2 && !entry->ipv6) + entry->want_refresh = true; if (entry->want_refresh) { char *c; char dns_name[NS_MAXDNAME + 1]; - entry->want_refresh = 0; + entry->want_refresh = false; /* turn a DNS name into a hostname with dots */ strncpy(dns_name, entry->key, NS_MAXDNAME); @@ -1335,7 +1335,7 @@ static void cache_refresh_iterator(gpointer key, gpointer value, static void cache_refresh(void) { - if (cache == NULL) + if (!cache) return; g_hash_table_foreach(cache, cache_refresh_iterator, NULL); @@ -1378,7 +1378,7 @@ static int cache_update(struct server_data *srv, unsigned char *msg, unsigned char response[NS_MAXDNAME + 1]; unsigned char *ptr; unsigned int rsplen; - gboolean new_entry = TRUE; + bool new_entry = true; time_t current_time; if (cache_size >= MAX_CACHE_SIZE) { @@ -1404,6 +1404,9 @@ static int cache_update(struct server_data *srv, unsigned char *msg, if (hdr->rcode != 0) return 0; + if (!cache) + create_cache(); + rsplen = sizeof(response) - 1; question[sizeof(question) - 1] = '\0'; @@ -1420,16 +1423,12 @@ static int cache_update(struct server_data *srv, unsigned char *msg, if ((err == -ENOMSG || err == -ENOBUFS) && reply_query_type(msg + offset, msg_len - offset) == 28) { - if (cache == NULL) { - create_cache(); - entry = NULL; - } else - entry = g_hash_table_lookup(cache, question); - if (entry && entry->ipv4 && entry->ipv6 == NULL) { + entry = g_hash_table_lookup(cache, question); + if (entry && entry->ipv4 && !entry->ipv6) { int cache_offset = 0; data = g_try_new(struct cache_data, 1); - if (data == NULL) + if (!data) return -ENOMEM; data->inserted = entry->ipv4->inserted; data->type = type; @@ -1471,20 +1470,20 @@ static int cache_update(struct server_data *srv, unsigned char *msg, * records for the same name. */ entry = g_hash_table_lookup(cache, question); - if (entry == NULL) { + if (!entry) { entry = g_try_new(struct cache_entry, 1); - if (entry == NULL) + if (!entry) return -ENOMEM; data = g_try_new(struct cache_data, 1); - if (data == NULL) { + if (!data) { g_free(entry); return -ENOMEM; } entry->key = g_strdup(question); entry->ipv4 = entry->ipv6 = NULL; - entry->want_refresh = 0; + entry->want_refresh = false; entry->hits = 0; if (type == 1) @@ -1492,14 +1491,14 @@ static int cache_update(struct server_data *srv, unsigned char *msg, else entry->ipv6 = data; } else { - if (type == 1 && entry->ipv4 != NULL) + if (type == 1 && entry->ipv4) return 0; - if (type == 28 && entry->ipv6 != NULL) + if (type == 28 && entry->ipv6) return 0; data = g_try_new(struct cache_data, 1); - if (data == NULL) + if (!data) return -ENOMEM; if (type == 1) @@ -1515,7 +1514,7 @@ static int cache_update(struct server_data *srv, unsigned char *msg, if (entry->hits < 0) entry->hits = 0; - new_entry = FALSE; + new_entry = false; } if (ttl < MIN_CACHE_TTL) @@ -1543,7 +1542,7 @@ static int cache_update(struct server_data *srv, unsigned char *msg, data->cache_until = round_down_ttl(current_time + ttl, ttl); - if (data->data == NULL) { + if (!data->data) { g_free(entry->key); g_free(data); g_free(entry); @@ -1574,7 +1573,7 @@ static int cache_update(struct server_data *srv, unsigned char *msg, memcpy(ptr + offset + 12 + qlen + 1 + sizeof(struct domain_question), response, rsplen); - if (new_entry == TRUE) { + if (new_entry) { g_hash_table_replace(cache, entry->key, entry); cache_size++; } @@ -1601,7 +1600,7 @@ static int ns_resolv(struct server_data *server, struct request_data *req, struct cache_entry *entry; entry = cache_check(request, &type, req->protocol); - if (entry != NULL) { + if (entry) { int ttl_left = 0; struct cache_data *data; @@ -1616,16 +1615,19 @@ static int ns_resolv(struct server_data *server, struct request_data *req, entry->hits++; } - if (data != NULL && req->protocol == IPPROTO_TCP) { + if (data && req->protocol == IPPROTO_TCP) { send_cached_response(req->client_sk, data->data, data->data_len, NULL, 0, IPPROTO_TCP, req->srcid, data->answers, ttl_left); return 1; } - if (data != NULL && req->protocol == IPPROTO_UDP) { + if (data && req->protocol == IPPROTO_UDP) { int udp_sk = get_req_udp_socket(req); + if (udp_sk < 0) + return -EIO; + send_cached_response(udp_sk, data->data, data->data_len, &req->sa, req->sa_len, IPPROTO_UDP, req->srcid, data->answers, @@ -1650,11 +1652,11 @@ static int ns_resolv(struct server_data *server, struct request_data *req, /* If we have more than one dot, we don't add domains */ dot = strchr(lookup, '.'); - if (dot != NULL && dot != lookup + strlen(lookup) - 1) + if (dot && dot != lookup + strlen(lookup) - 1) return 0; - if (server->domains != NULL && server->domains->data != NULL) - req->append_domain = TRUE; + if (server->domains && server->domains->data) + req->append_domain = true; for (list = server->domains; list; list = list->next) { char *domain; @@ -1664,7 +1666,7 @@ static int ns_resolv(struct server_data *server, struct request_data *req, domain = list->data; - if (domain == NULL) + if (!domain) continue; offset = protocol_offset(server->protocol); @@ -1712,6 +1714,176 @@ static int ns_resolv(struct server_data *server, struct request_data *req, return 0; } +static char *convert_label(char *start, char *end, char *ptr, char *uptr, + int remaining_len, int *used_comp, int *used_uncomp) +{ + int pos, comp_pos; + char name[NS_MAXLABEL]; + + pos = dn_expand((u_char *)start, (u_char *)end, (u_char *)ptr, + name, NS_MAXLABEL); + if (pos < 0) { + DBG("uncompress error [%d/%s]", errno, strerror(errno)); + goto out; + } + + /* + * We need to compress back the name so that we get back to internal + * label presentation. + */ + comp_pos = dn_comp(name, (u_char *)uptr, remaining_len, NULL, NULL); + if (comp_pos < 0) { + DBG("compress error [%d/%s]", errno, strerror(errno)); + goto out; + } + + *used_comp = pos; + *used_uncomp = comp_pos; + + return ptr; + +out: + return NULL; +} + +static char *uncompress(int16_t field_count, char *start, char *end, + char *ptr, char *uncompressed, int uncomp_len, + char **uncompressed_ptr) +{ + char *uptr = *uncompressed_ptr; /* position in result buffer */ + + DBG("count %d ptr %p end %p uptr %p", field_count, ptr, end, uptr); + + while (field_count-- > 0 && ptr < end) { + int dlen; /* data field length */ + int ulen; /* uncompress length */ + int pos; /* position in compressed string */ + char name[NS_MAXLABEL]; /* tmp label */ + uint16_t dns_type, dns_class; + + pos = dn_expand((const u_char *)start, (u_char *)end, + (u_char *)ptr, name, NS_MAXLABEL); + if (pos < 0) { + DBG("uncompress error [%d/%s]", errno, + strerror(errno)); + goto out; + } + + /* + * Copy the uncompressed resource record, type, class and \0 to + * tmp buffer. + */ + + ulen = strlen(name); + *uptr++ = ulen; + strncpy(uptr, name, uncomp_len - (uptr - uncompressed)); + + DBG("pos %d ulen %d left %d name %s", pos, ulen, + (int)(uncomp_len - (uptr - uncompressed)), uptr); + + uptr += ulen; + *uptr++ = '\0'; + + ptr += pos; + + /* + * We copy also the fixed portion of the result (type, class, + * ttl, address length and the address) + */ + memcpy(uptr, ptr, NS_RRFIXEDSZ); + + dns_type = uptr[0] << 8 | uptr[1]; + dns_class = uptr[2] << 8 | uptr[3]; + + if (dns_class != ns_c_in) + goto out; + + ptr += NS_RRFIXEDSZ; + uptr += NS_RRFIXEDSZ; + + /* + * Then the variable portion of the result (data length). + * Typically this portion is also compressed + * so we need to uncompress it also when necessary. + */ + if (dns_type == ns_t_cname) { + int comp_pos; + + if (!convert_label(start, end, ptr, uptr, + uncomp_len - (uptr - uncompressed), + &pos, &comp_pos)) + goto out; + + uptr[-2] = comp_pos << 8; + uptr[-1] = comp_pos & 0xff; + + uptr += comp_pos; + ptr += pos; + + } else if (dns_type == ns_t_a || dns_type == ns_t_aaaa) { + dlen = uptr[-2] << 8 | uptr[-1]; + + if (ptr + dlen > end) { + DBG("data len %d too long", dlen); + goto out; + } + + memcpy(uptr, ptr, dlen); + uptr += dlen; + ptr += dlen; + + } else if (dns_type == ns_t_soa) { + int comp_pos; + int total_len = 0; + char *len_ptr; + + /* Primary name server expansion */ + if (!convert_label(start, end, ptr, uptr, + uncomp_len - (uptr - uncompressed), + &pos, &comp_pos)) + goto out; + + total_len += comp_pos; + len_ptr = &uptr[-2]; + ptr += pos; + uptr += comp_pos; + + /* Responsible authority's mailbox */ + if (!convert_label(start, end, ptr, uptr, + uncomp_len - (uptr - uncompressed), + &pos, &comp_pos)) + goto out; + + total_len += comp_pos; + ptr += pos; + uptr += comp_pos; + + /* + * Copy rest of the soa fields (serial number, + * refresh interval, retry interval, expiration + * limit and minimum ttl). They are 20 bytes long. + */ + memcpy(uptr, ptr, 20); + uptr += 20; + ptr += 20; + total_len += 20; + + /* + * Finally fix the length of the data part + */ + len_ptr[0] = total_len << 8; + len_ptr[1] = total_len & 0xff; + } + + *uncompressed_ptr = uptr; + } + + return ptr; + +out: + return NULL; +} + static int forward_dns_reply(unsigned char *reply, int reply_len, int protocol, struct server_data *data) { @@ -1728,7 +1900,7 @@ static int forward_dns_reply(unsigned char *reply, int reply_len, int protocol, DBG("Received %d bytes (id 0x%04x)", reply_len, dns_id); req = find_request(dns_id); - if (req == NULL) + if (!req) return -EINVAL; DBG("req %p dstid 0x%04x altid 0x%04x rcode %d", @@ -1739,70 +1911,163 @@ static int forward_dns_reply(unsigned char *reply, int reply_len, int protocol, req->numresp++; - if (hdr->rcode == 0 || req->resp == NULL) { + if (hdr->rcode == 0 || !req->resp) { + unsigned char *new_reply = NULL; /* * If the domain name was append * remove it before forwarding the reply. + * If there were more than one question, then this + * domain name ripping can be hairy so avoid that + * and bail out in that that case. + * + * The reason we are doing this magic is that if the + * user's DNS client tries to resolv hostname without + * domain part, it also expects to get the result without + * a domain name part. */ - if (req->append_domain == TRUE) { - unsigned int domain_len = 0; - unsigned char *ptr; - uint8_t host_len; - unsigned int header_len; + if (req->append_domain && ntohs(hdr->qdcount) == 1) { + uint16_t domain_len = 0; + uint16_t header_len; + uint16_t dns_type, dns_class; + uint8_t host_len, dns_type_pos; + char uncompressed[NS_MAXDNAME], *uptr; + char *ptr, *eom = (char *)reply + reply_len; /* * ptr points to the first char of the hostname. * ->hostname.domain.net */ header_len = offset + sizeof(struct domain_hdr); - ptr = reply + header_len; + ptr = (char *)reply + header_len; + host_len = *ptr; if (host_len > 0) - domain_len = strnlen((const char *)ptr + 1 + - host_len, + domain_len = strnlen(ptr + 1 + host_len, reply_len - header_len); - - DBG("host len %d domain len %d", host_len, domain_len); + /* + * If the query type is anything other than A or AAAA, + * then bail out and pass the message as is. + * We only want to deal with IPv4 or IPv6 addresses. + */ + dns_type_pos = host_len + 1 + domain_len + 1; + + dns_type = ptr[dns_type_pos] << 8 | + ptr[dns_type_pos + 1]; + dns_class = ptr[dns_type_pos + 2] << 8 | + ptr[dns_type_pos + 3]; + if (dns_type != ns_t_a && dns_type != ns_t_aaaa && + dns_class != ns_c_in) { + DBG("Pass msg dns type %d class %d", + dns_type, dns_class); + goto pass; + } /* * Remove the domain name and replace it by the end * of reply. Check if the domain is really there - * before trying to copy the data. The domain_len can - * be 0 because if the original query did not contain - * a domain name, then we are sending two packets, - * first without the domain name and the second packet - * with domain name. The append_domain is set to true - * even if we sent the first packet without domain - * name. In this case we end up in this branch. + * before trying to copy the data. We also need to + * uncompress the answers if necessary. + * The domain_len can be 0 because if the original + * query did not contain a domain name, then we are + * sending two packets, first without the domain name + * and the second packet with domain name. + * The append_domain is set to true even if we sent + * the first packet without domain name. In this + * case we end up in this branch. */ if (domain_len > 0) { + int len = host_len + 1; + + /* + * First copy host (without domain name) into + * tmp buffer. + */ + uptr = &uncompressed[0]; + memcpy(uptr, ptr, len); + + uptr[len] = '\0'; /* host termination */ + uptr += len + 1; + + /* + * Copy type and class fields of the question. + */ + ptr += len + domain_len + 1; + memcpy(uptr, ptr, NS_QFIXEDSZ); + + /* + * ptr points to answers after this + */ + ptr += NS_QFIXEDSZ; + uptr += NS_QFIXEDSZ; + + /* + * We then uncompress the result to buffer + * so that we can rip off the domain name + * part from the question. First answers, + * then name server (authority) information, + * and finally additional record info. + */ + + ptr = uncompress(ntohs(hdr->ancount), + (char *)reply + offset, eom, + ptr, uncompressed, NS_MAXDNAME, + &uptr); + if (ptr == NULL) + goto out; + + ptr = uncompress(ntohs(hdr->nscount), + (char *)reply + offset, eom, + ptr, uncompressed, NS_MAXDNAME, + &uptr); + if (ptr == NULL) + goto out; + + ptr = uncompress(ntohs(hdr->arcount), + (char *)reply + offset, eom, + ptr, uncompressed, NS_MAXDNAME, + &uptr); + if (ptr == NULL) + goto out; + /* - * Note that we must use memmove() here, - * because the memory areas can overlap. + * Because we have now uncompressed the answers + * we must create a bigger buffer to hold all + * that data. */ - memmove(ptr + host_len + 1, - ptr + host_len + domain_len + 1, - reply_len - header_len - domain_len); - reply_len = reply_len - domain_len; + new_reply = g_try_malloc(header_len + + uptr - uncompressed); + if (!new_reply) + return -ENOMEM; + + memcpy(new_reply, reply, header_len); + memcpy(new_reply + header_len, uncompressed, + uptr - uncompressed); + + reply = new_reply; + reply_len = header_len + uptr - uncompressed; } } + pass: g_free(req->resp); req->resplen = 0; req->resp = g_try_malloc(reply_len); - if (req->resp == NULL) + if (!req->resp) return -ENOMEM; memcpy(req->resp, reply, reply_len); req->resplen = reply_len; cache_update(data, reply, reply_len); + + g_free(new_reply); } +out: if (hdr->rcode > 0 && req->numresp < req->numserv) return -EINVAL; @@ -1810,8 +2075,12 @@ static int forward_dns_reply(unsigned char *reply, int reply_len, int protocol, if (protocol == IPPROTO_UDP) { sk = get_req_udp_socket(req); - err = sendto(sk, req->resp, req->resplen, 0, - &req->sa, req->sa_len); + if (sk < 0) { + errno = -EIO; + err = -EIO; + } else + err = sendto(sk, req->resp, req->resplen, 0, + &req->sa, req->sa_len); } else { sk = req->client_sk; err = send(sk, req->resp, req->resplen, MSG_NOSIGNAL); @@ -1843,7 +2112,7 @@ static void server_destroy_socket(struct server_data *data) data->timeout = 0; } - if (data->channel != NULL) { + if (data->channel) { g_io_channel_shutdown(data->channel, TRUE, NULL); g_io_channel_unref(data->channel); data->channel = NULL; @@ -1855,10 +2124,8 @@ static void server_destroy_socket(struct server_data *data) static void destroy_server(struct server_data *server) { - GList *list; - DBG("index %d server %s sock %d", server->index, server->server, - server->channel != NULL ? + server->channel ? g_io_channel_unix_get_fd(server->channel): -1); server_list = g_slist_remove(server_list, server); @@ -1868,12 +2135,7 @@ static void destroy_server(struct server_data *server) DBG("Removing DNS server %s", server->server); g_free(server->server); - for (list = server->domains; list; list = list->next) { - char *domain = list->data; - - server->domains = g_list_remove(server->domains, domain); - g_free(domain); - } + g_list_free_full(server->domains, g_free); g_free(server->server_addr); /* @@ -1945,7 +2207,7 @@ hangup: if (req->protocol == IPPROTO_UDP) continue; - if (req->request == NULL) + if (!req->request) continue; /* @@ -1972,12 +2234,12 @@ hangup: if ((condition & G_IO_OUT) && !server->connected) { GSList *list; GList *domains; - int no_request_sent = TRUE; + bool no_request_sent = true; struct server_data *udp_server; udp_server = find_server(server->index, server->server, IPPROTO_UDP); - if (udp_server != NULL) { + if (udp_server) { for (domains = udp_server->domains; domains; domains = domains->next) { char *dom = domains->data; @@ -1990,7 +2252,7 @@ hangup: } } - server->connected = TRUE; + server->connected = true; server_list = g_slist_append(server_list, server); if (server->timeout > 0) { @@ -2027,7 +2289,7 @@ hangup: continue; } - no_request_sent = FALSE; + no_request_sent = false; if (req->timeout > 0) g_source_remove(req->timeout); @@ -2037,7 +2299,7 @@ hangup: list = list->next; } - if (no_request_sent == TRUE) { + if (no_request_sent) { destroy_server(server); return FALSE; } @@ -2115,7 +2377,7 @@ static gboolean tcp_idle_timeout(gpointer user_data) DBG(""); - if (server == NULL) + if (!server) return FALSE; destroy_server(server); @@ -2145,7 +2407,7 @@ static int server_create_socket(struct server_data *data) DBG("sk %d", sk); interface = connman_inet_ifname(data->index); - if (interface != NULL) { + if (interface) { if (setsockopt(sk, SOL_SOCKET, SO_BINDTODEVICE, interface, strlen(interface) + 1) < 0) { @@ -2162,7 +2424,7 @@ static int server_create_socket(struct server_data *data) } data->channel = g_io_channel_unix_new(sk); - if (data->channel == NULL) { + if (!data->channel) { connman_error("Failed to create server %s channel", data->server); close(sk); @@ -2213,7 +2475,7 @@ static struct server_data *create_server(int index, DBG("index %d server %s", index, server); data = g_try_new0(struct server_data, 1); - if (data == NULL) { + if (!data) { connman_error("Failed to allocate server %s data", server); return NULL; } @@ -2269,7 +2531,7 @@ static struct server_data *create_server(int index, connman_error("Wrong address family %d", rp->ai_family); break; } - if (data->server_addr == NULL) { + if (!data->server_addr) { freeaddrinfo(rp); destroy_server(data); return NULL; @@ -2283,9 +2545,12 @@ static struct server_data *create_server(int index, } if (protocol == IPPROTO_UDP) { - /* Enable new servers by default */ - data->enabled = TRUE; - DBG("Adding DNS server %s", data->server); + if (__connman_service_index_is_default(data->index) || + __connman_service_index_is_split_routing( + data->index)) { + data->enabled = true; + DBG("Adding DNS server %s", data->server); + } server_list = g_slist_append(server_list, data); } @@ -2293,7 +2558,7 @@ static struct server_data *create_server(int index, return data; } -static gboolean resolv(struct request_data *req, +static bool resolv(struct request_data *req, gpointer request, gpointer name) { GSList *list; @@ -2308,10 +2573,10 @@ static gboolean resolv(struct request_data *req, DBG("server %s enabled %d", data->server, data->enabled); - if (data->enabled == FALSE) + if (!data->enabled) continue; - if (data->channel == NULL && data->protocol == IPPROTO_UDP) { + if (!data->channel && data->protocol == IPPROTO_UDP) { if (server_create_socket(data) < 0) { DBG("socket creation failed while resolving"); continue; @@ -2319,10 +2584,10 @@ static gboolean resolv(struct request_data *req, } if (ns_resolv(data, req, request, name) > 0) - return TRUE; + return true; } - return FALSE; + return false; } static void append_domain(int index, const char *domain) @@ -2331,14 +2596,14 @@ static void append_domain(int index, const char *domain) DBG("index %d domain %s", index, domain); - if (domain == NULL) + if (!domain) return; for (list = server_list; list; list = list->next) { struct server_data *data = list->data; GList *dom_list; char *dom; - gboolean dom_found = FALSE; + bool dom_found = false; if (data->index < 0) continue; @@ -2351,12 +2616,12 @@ static void append_domain(int index, const char *domain) dom = dom_list->data; if (g_str_equal(dom, domain)) { - dom_found = TRUE; + dom_found = true; break; } } - if (dom_found == FALSE) { + if (!dom_found) { data->domains = g_list_append(data->domains, g_strdup(domain)); } @@ -2370,29 +2635,29 @@ int __connman_dnsproxy_append(int index, const char *domain, DBG("index %d server %s", index, server); - if (server == NULL && domain == NULL) + if (!server && !domain) return -EINVAL; - if (server == NULL) { + if (!server) { append_domain(index, domain); return 0; } - if (g_str_equal(server, "127.0.0.1") == TRUE) + if (g_str_equal(server, "127.0.0.1")) return -ENODEV; - if (g_str_equal(server, "::1") == TRUE) + if (g_str_equal(server, "::1")) return -ENODEV; data = find_server(index, server, IPPROTO_UDP); - if (data != NULL) { + if (data) { append_domain(index, domain); return 0; } data = create_server(index, domain, server, IPPROTO_UDP); - if (data == NULL) + if (!data) return -EIO; return 0; @@ -2404,7 +2669,7 @@ static void remove_server(int index, const char *domain, struct server_data *data; data = find_server(index, server, protocol); - if (data == NULL) + if (!data) return; destroy_server(data); @@ -2415,13 +2680,13 @@ int __connman_dnsproxy_remove(int index, const char *domain, { DBG("index %d server %s", index, server); - if (server == NULL) + if (!server) return -EINVAL; - if (g_str_equal(server, "127.0.0.1") == TRUE) + if (g_str_equal(server, "127.0.0.1")) return -ENODEV; - if (g_str_equal(server, "::1") == TRUE) + if (g_str_equal(server, "::1")) return -ENODEV; remove_server(index, domain, server, IPPROTO_UDP); @@ -2440,7 +2705,7 @@ void __connman_dnsproxy_flush(void) list = list->next; - if (resolv(req, req->request, req->name) == TRUE) { + if (resolv(req, req->request, req->name)) { /* * A cached result was sent, * so the request can be released @@ -2457,7 +2722,7 @@ void __connman_dnsproxy_flush(void) } } -static void dnsproxy_offline_mode(connman_bool_t enabled) +static void dnsproxy_offline_mode(bool enabled) { GSList *list; @@ -2466,14 +2731,14 @@ static void dnsproxy_offline_mode(connman_bool_t enabled) for (list = server_list; list; list = list->next) { struct server_data *data = list->data; - if (enabled == FALSE) { + if (!enabled) { DBG("Enabling DNS server %s", data->server); - data->enabled = TRUE; + data->enabled = true; cache_invalidate(); cache_refresh(); } else { DBG("Disabling DNS server %s", data->server); - data->enabled = FALSE; + data->enabled = false; cache_invalidate(); } } @@ -2489,9 +2754,9 @@ static void dnsproxy_default_changed(struct connman_service *service) /* DNS has changed, invalidate the cache */ cache_invalidate(); - if (service == NULL) { + if (!service) { /* When no services are active, then disable DNS proxying */ - dnsproxy_offline_mode(TRUE); + dnsproxy_offline_mode(true); return; } @@ -2504,10 +2769,10 @@ static void dnsproxy_default_changed(struct connman_service *service) if (data->index == index) { DBG("Enabling DNS server %s", data->server); - data->enabled = TRUE; + data->enabled = true; } else { DBG("Disabling DNS server %s", data->server); - data->enabled = FALSE; + data->enabled = false; } } @@ -2596,10 +2861,10 @@ static int parse_request(unsigned char *buf, int len, static void client_reset(struct tcp_partial_client_data *client) { - if (client == NULL) + if (!client) return; - if (client->channel != NULL) { + if (client->channel) { DBG("client %d closing", g_io_channel_unix_get_fd(client->channel)); @@ -2628,7 +2893,7 @@ static unsigned int get_msg_len(unsigned char *buf) return buf[0]<<8 | buf[1]; } -static gboolean read_tcp_data(struct tcp_partial_client_data *client, +static bool read_tcp_data(struct tcp_partial_client_data *client, void *client_addr, socklen_t client_addr_len, int read_len) { @@ -2637,7 +2902,8 @@ static gboolean read_tcp_data(struct tcp_partial_client_data *client, int client_sk, err; unsigned int msg_len; GSList *list; - int waiting_for_connect = FALSE, qtype = 0; + bool waiting_for_connect = false; + int qtype = 0; struct cache_entry *entry; client_sk = g_io_channel_unix_get_fd(client->channel); @@ -2647,7 +2913,7 @@ static gboolean read_tcp_data(struct tcp_partial_client_data *client, client_sk, client->buf_end); g_hash_table_remove(partial_tcp_req_table, GINT_TO_POINTER(client_sk)); - return FALSE; + return false; } DBG("client %d received %d bytes", client_sk, read_len); @@ -2655,14 +2921,14 @@ static gboolean read_tcp_data(struct tcp_partial_client_data *client, client->buf_end += read_len; if (client->buf_end < 2) - return TRUE; + return true; msg_len = get_msg_len(client->buf); if (msg_len > TCP_MAX_BUF_LEN) { DBG("client %d sent too much data %d", client_sk, msg_len); g_hash_table_remove(partial_tcp_req_table, GINT_TO_POINTER(client_sk)); - return FALSE; + return false; } read_another: @@ -2673,7 +2939,7 @@ read_another: DBG("client %d still missing %d bytes", client_sk, msg_len + 2 - client->buf_end); - return TRUE; + return true; } DBG("client %d all data %d received", client_sk, msg_len); @@ -2683,12 +2949,12 @@ read_another: if (err < 0 || (g_slist_length(server_list) == 0)) { send_response(client_sk, client->buf, msg_len + 2, NULL, 0, IPPROTO_TCP); - return TRUE; + return true; } req = g_try_new0(struct request_data, 1); - if (req == NULL) - return TRUE; + if (!req) + return true; memcpy(&req->sa, client_addr, client_addr_len); req->sa_len = client_addr_len; @@ -2706,14 +2972,14 @@ read_another: req->numserv = 0; req->ifdata = client->ifdata; - req->append_domain = FALSE; + req->append_domain = false; /* * Check if the answer is found in the cache before * creating sockets to the server. */ entry = cache_check(client->buf, &qtype, IPPROTO_TCP); - if (entry != NULL) { + if (entry) { int ttl_left = 0; struct cache_data *data; @@ -2723,7 +2989,7 @@ read_another: else data = entry->ipv6; - if (data != NULL) { + if (data) { ttl_left = data->valid_until - time(NULL); entry->hits++; @@ -2740,22 +3006,22 @@ read_another: for (list = server_list; list; list = list->next) { struct server_data *data = list->data; - if (data->protocol != IPPROTO_UDP || data->enabled == FALSE) + if (data->protocol != IPPROTO_UDP || !data->enabled) continue; - if(create_server(data->index, NULL, - data->server, IPPROTO_TCP) == NULL) + if (!create_server(data->index, NULL, data->server, + IPPROTO_TCP)) continue; - waiting_for_connect = TRUE; + waiting_for_connect = true; } - if (waiting_for_connect == FALSE) { + if (!waiting_for_connect) { /* No server is waiting for connect */ send_response(client_sk, client->buf, req->request_len, NULL, 0, IPPROTO_TCP); g_free(req); - return TRUE; + return true; } /* @@ -2765,7 +3031,7 @@ read_another: * properly connected over TCP to the nameserver. */ req->request = g_try_malloc0(req->request_len); - if (req->request == NULL) { + if (!req->request) { send_response(client_sk, client->buf, req->request_len, NULL, 0, IPPROTO_TCP); g_free(req); @@ -2774,7 +3040,7 @@ read_another: memcpy(req->request, client->buf, req->request_len); req->name = g_try_malloc0(sizeof(query)); - if (req->name == NULL) { + if (!req->name) { send_response(client_sk, client->buf, req->request_len, NULL, 0, IPPROTO_TCP); g_free(req->request); @@ -2824,7 +3090,7 @@ out: client->timeout = 0; } - return TRUE; + return true; } static gboolean tcp_client_event(GIOChannel *channel, GIOCondition condition, @@ -2896,7 +3162,7 @@ static gboolean client_timeout(gpointer user_data) return FALSE; } -static gboolean tcp_listener_event(GIOChannel *channel, GIOCondition condition, +static bool tcp_listener_event(GIOChannel *channel, GIOCondition condition, struct listener_data *ifdata, int family, guint *listener_watch) { @@ -2922,7 +3188,7 @@ static gboolean tcp_listener_event(GIOChannel *channel, GIOCondition condition, connman_error("Error with TCP listener channel"); - return FALSE; + return false; } sk = g_io_channel_unix_get_fd(channel); @@ -2945,23 +3211,25 @@ static gboolean tcp_listener_event(GIOChannel *channel, GIOCondition condition, DBG("client %d accepted", client_sk); } else { DBG("No data to read from master %d, waiting.", sk); - return TRUE; + return true; } if (client_sk < 0) { connman_error("Accept failure on TCP listener"); *listener_watch = 0; - return FALSE; + return false; } fcntl(client_sk, F_SETFL, O_NONBLOCK); client = g_hash_table_lookup(partial_tcp_req_table, GINT_TO_POINTER(client_sk)); - if (client == NULL) { + if (!client) { client = g_try_new0(struct tcp_partial_client_data, 1); - if (client == NULL) - return FALSE; + if (!client) { + close(client_sk); + return false; + } g_hash_table_insert(partial_tcp_req_table, GINT_TO_POINTER(client_sk), @@ -2981,10 +3249,10 @@ static gboolean tcp_listener_event(GIOChannel *channel, GIOCondition condition, DBG("client %d already exists %p", client_sk, client); } - if (client->buf == NULL) { + if (!client->buf) { client->buf = g_try_malloc(TCP_MAX_BUF_LEN); - if (client->buf == NULL) - return FALSE; + if (!client->buf) + return false; } memset(client->buf, 0, TCP_MAX_BUF_LEN); client->buf_end = 0; @@ -3003,20 +3271,20 @@ static gboolean tcp_listener_event(GIOChannel *channel, GIOCondition condition, if (len < 0) { if (errno == EAGAIN || errno == EWOULDBLOCK) { DBG("client %d no data to read, waiting", client_sk); - return TRUE; + return true; } DBG("client %d cannot read errno %d/%s", client_sk, -errno, strerror(errno)); g_hash_table_remove(partial_tcp_req_table, GINT_TO_POINTER(client_sk)); - return TRUE; + return true; } if (len < 2) { DBG("client %d not enough data to read, waiting", client_sk); client->buf_end += len; - return TRUE; + return true; } msg_len = get_msg_len(client->buf); @@ -3025,7 +3293,7 @@ static gboolean tcp_listener_event(GIOChannel *channel, GIOCondition condition, client_sk, msg_len); g_hash_table_remove(partial_tcp_req_table, GINT_TO_POINTER(client_sk)); - return TRUE; + return true; } /* @@ -3037,7 +3305,7 @@ static gboolean tcp_listener_event(GIOChannel *channel, GIOCondition condition, client_sk, len, msg_len + 2, msg_len + 2 - len); client->buf_end += len; - return TRUE; + return true; } return read_tcp_data(client, client_addr, *client_addr_len, len); @@ -3061,7 +3329,7 @@ static gboolean tcp6_listener_event(GIOChannel *channel, GIOCondition condition, &ifdata->tcp6_listener_watch); } -static gboolean udp_listener_event(GIOChannel *channel, GIOCondition condition, +static bool udp_listener_event(GIOChannel *channel, GIOCondition condition, struct listener_data *ifdata, int family, guint *listener_watch) { @@ -3079,7 +3347,7 @@ static gboolean udp_listener_event(GIOChannel *channel, GIOCondition condition, if (condition & (G_IO_NVAL | G_IO_ERR | G_IO_HUP)) { connman_error("Error with UDP listener channel"); *listener_watch = 0; - return FALSE; + return false; } sk = g_io_channel_unix_get_fd(channel); @@ -3095,7 +3363,7 @@ static gboolean udp_listener_event(GIOChannel *channel, GIOCondition condition, memset(client_addr, 0, *client_addr_len); len = recvfrom(sk, buf, sizeof(buf), 0, client_addr, client_addr_len); if (len < 2) - return TRUE; + return true; DBG("Received %d bytes (id 0x%04x)", len, buf[0] | buf[1] << 8); @@ -3103,12 +3371,12 @@ static gboolean udp_listener_event(GIOChannel *channel, GIOCondition condition, if (err < 0 || (g_slist_length(server_list) == 0)) { send_response(sk, buf, len, client_addr, *client_addr_len, IPPROTO_UDP); - return TRUE; + return true; } req = g_try_new0(struct request_data, 1); - if (req == NULL) - return TRUE; + if (!req) + return true; memcpy(&req->sa, client_addr, *client_addr_len); req->sa_len = *client_addr_len; @@ -3126,18 +3394,18 @@ static gboolean udp_listener_event(GIOChannel *channel, GIOCondition condition, req->numserv = 0; req->ifdata = ifdata; - req->append_domain = FALSE; + req->append_domain = false; - if (resolv(req, buf, query) == TRUE) { + if (resolv(req, buf, query)) { /* a cached result was sent, so the request can be released */ g_free(req); - return TRUE; + return true; } req->timeout = g_timeout_add_seconds(5, request_timeout, req); request_list = g_slist_append(request_list, req); - return TRUE; + return true; } static gboolean udp4_listener_event(GIOChannel *channel, GIOCondition condition, @@ -3200,7 +3468,7 @@ static GIOChannel *get_listener(int family, int protocol, int index) } interface = connman_inet_ifname(index); - if (interface == NULL || setsockopt(sk, SOL_SOCKET, SO_BINDTODEVICE, + if (!interface || setsockopt(sk, SOL_SOCKET, SO_BINDTODEVICE, interface, strlen(interface) + 1) < 0) { connman_error("Failed to bind %s listener interface " @@ -3266,7 +3534,7 @@ static GIOChannel *get_listener(int family, int protocol, int index) } channel = g_io_channel_unix_new(sk); - if (channel == NULL) { + if (!channel) { connman_error("Failed to create %s listener channel", proto); close(sk); return NULL; @@ -3293,7 +3561,7 @@ static int create_dns_listener(int protocol, struct listener_data *ifdata) if (protocol == IPPROTO_TCP) { ifdata->tcp4_listener_channel = get_listener(AF_INET, protocol, ifdata->index); - if (ifdata->tcp4_listener_channel != NULL) + if (ifdata->tcp4_listener_channel) ifdata->tcp4_listener_watch = g_io_add_watch(ifdata->tcp4_listener_channel, G_IO_IN, tcp4_listener_event, @@ -3303,7 +3571,7 @@ static int create_dns_listener(int protocol, struct listener_data *ifdata) ifdata->tcp6_listener_channel = get_listener(AF_INET6, protocol, ifdata->index); - if (ifdata->tcp6_listener_channel != NULL) + if (ifdata->tcp6_listener_channel) ifdata->tcp6_listener_watch = g_io_add_watch(ifdata->tcp6_listener_channel, G_IO_IN, tcp6_listener_event, @@ -3313,7 +3581,7 @@ static int create_dns_listener(int protocol, struct listener_data *ifdata) } else { ifdata->udp4_listener_channel = get_listener(AF_INET, protocol, ifdata->index); - if (ifdata->udp4_listener_channel != NULL) + if (ifdata->udp4_listener_channel) ifdata->udp4_listener_watch = g_io_add_watch(ifdata->udp4_listener_channel, G_IO_IN, udp4_listener_event, @@ -3323,7 +3591,7 @@ static int create_dns_listener(int protocol, struct listener_data *ifdata) ifdata->udp6_listener_channel = get_listener(AF_INET6, protocol, ifdata->index); - if (ifdata->udp6_listener_channel != NULL) + if (ifdata->udp6_listener_channel) ifdata->udp6_listener_watch = g_io_add_watch(ifdata->udp6_listener_channel, G_IO_IN, udp6_listener_event, @@ -3345,9 +3613,9 @@ static void destroy_udp_listener(struct listener_data *ifdata) if (ifdata->udp6_listener_watch > 0) g_source_remove(ifdata->udp6_listener_watch); - if (ifdata->udp4_listener_channel != NULL) + if (ifdata->udp4_listener_channel) g_io_channel_unref(ifdata->udp4_listener_channel); - if (ifdata->udp6_listener_channel != NULL) + if (ifdata->udp6_listener_channel) g_io_channel_unref(ifdata->udp6_listener_channel); } @@ -3360,9 +3628,9 @@ static void destroy_tcp_listener(struct listener_data *ifdata) if (ifdata->tcp6_listener_watch > 0) g_source_remove(ifdata->tcp6_listener_watch); - if (ifdata->tcp4_listener_channel != NULL) + if (ifdata->tcp4_listener_channel) g_io_channel_unref(ifdata->tcp4_listener_channel); - if (ifdata->tcp6_listener_channel != NULL) + if (ifdata->tcp6_listener_channel) g_io_channel_unref(ifdata->tcp6_listener_channel); } @@ -3429,14 +3697,14 @@ int __connman_dnsproxy_add_listener(int index) if (index < 0) return -EINVAL; - if (listener_table == NULL) + if (!listener_table) return -ENOENT; - if (g_hash_table_lookup(listener_table, GINT_TO_POINTER(index)) != NULL) + if (g_hash_table_lookup(listener_table, GINT_TO_POINTER(index))) return 0; ifdata = g_try_new0(struct listener_data, 1); - if (ifdata == NULL) + if (!ifdata) return -ENOMEM; ifdata->index = index; @@ -3467,11 +3735,11 @@ void __connman_dnsproxy_remove_listener(int index) DBG("index %d", index); - if (listener_table == NULL) + if (!listener_table) return; ifdata = g_hash_table_lookup(listener_table, GINT_TO_POINTER(index)); - if (ifdata == NULL) + if (!ifdata) return; destroy_listener(ifdata); diff --git a/src/eduroam.config b/src/eduroam.config new file mode 100644 index 00000000..768b7b40 --- /dev/null +++ b/src/eduroam.config @@ -0,0 +1,5 @@ +[service_eduroam] +Type = wifi +Name = eduroam +EAP = peap +Phase2 = MSCHAPV2 diff --git a/src/error.c b/src/error.c index 955b4b88..4f24ae25 100644 --- a/src/error.c +++ b/src/error.c @@ -2,7 +2,7 @@ * * Connection Manager * - * Copyright (C) 2007-2012 Intel Corporation. All rights reserved. + * Copyright (C) 2007-2013 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 diff --git a/src/firewall.c b/src/firewall.c index c235d861..90c3d3c1 100644 --- a/src/firewall.c +++ b/src/firewall.c @@ -57,6 +57,8 @@ struct firewall_context { static GSList *managed_tables; +static bool firewall_is_up; + static int chain_to_index(const char *chain_name) { if (!g_strcmp0(builtin_chains[NF_IP_PRE_ROUTING], chain_name)) @@ -75,7 +77,7 @@ static int chain_to_index(const char *chain_name) static int managed_chain_to_index(const char *chain_name) { - if (g_str_has_prefix(chain_name, CHAIN_PREFIX) == FALSE) + if (!g_str_has_prefix(chain_name, CHAIN_PREFIX)) return -1; return chain_to_index(chain_name + strlen(CHAIN_PREFIX)); @@ -146,7 +148,7 @@ static int insert_managed_rule(const char *table_name, goto out; } - for (list = managed_tables; list != NULL; list = list->next) { + for (list = managed_tables; list; list = list->next) { mtable = list->data; if (g_strcmp0(mtable->name, table_name) == 0) @@ -155,7 +157,7 @@ static int insert_managed_rule(const char *table_name, mtable = NULL; } - if (mtable == NULL) { + if (!mtable) { mtable = g_new0(struct connman_managed_table, 1); mtable->name = g_strdup(table_name); @@ -203,7 +205,7 @@ static int delete_managed_rule(const char *table_name, err = __connman_iptables_delete(table_name, managed_chain, rule_spec); - for (list = managed_tables; list != NULL; list = list->next) { + for (list = managed_tables; list; list = list->next) { mtable = list->data; if (g_strcmp0(mtable->name, table_name) == 0) @@ -212,7 +214,7 @@ static int delete_managed_rule(const char *table_name, mtable = NULL; } - if (mtable == NULL) { + if (!mtable) { err = -ENOENT; goto out; } @@ -297,7 +299,7 @@ static int firewall_disable(GList *rules) GList *list; int err; - for (list = rules; list != NULL; list = g_list_previous(list)) { + for (list = rules; list; list = g_list_previous(list)) { rule = list->data; err = delete_managed_rule(rule->table, @@ -325,7 +327,7 @@ int __connman_firewall_enable(struct firewall_context *ctx) GList *list; int err; - for (list = g_list_first(ctx->rules); list != NULL; + for (list = g_list_first(ctx->rules); list; list = g_list_next(list)) { rule = list->data; @@ -341,6 +343,8 @@ int __connman_firewall_enable(struct firewall_context *ctx) goto err; } + firewall_is_up = true; + return 0; err: @@ -356,6 +360,11 @@ int __connman_firewall_disable(struct firewall_context *ctx) return firewall_disable(g_list_last(ctx->rules)); } +bool __connman_firewall_is_up(void) +{ + return firewall_is_up; +} + static void iterate_chains_cb(const char *chain_name, void *user_data) { GSList **chains = user_data; @@ -377,7 +386,7 @@ static void flush_table(const char *table_name) __connman_iptables_iterate_chains(table_name, iterate_chains_cb, &chains); - for (list = chains; list != NULL; list = list->next) { + for (list = chains; list; list = list->next) { id = GPOINTER_TO_INT(list->data); managed_chain = g_strdup_printf("%s%s", CHAIN_PREFIX, @@ -417,7 +426,17 @@ static void flush_table(const char *table_name) static void flush_all_tables(void) { - /* Flush the tables ConnMan might have modified */ + /* Flush the tables ConnMan might have modified + * But do so if only ConnMan has done something with + * iptables */ + + if (!g_file_test("/proc/net/ip_tables_names", + G_FILE_TEST_EXISTS | G_FILE_TEST_IS_REGULAR)) { + firewall_is_up = false; + return; + } + + firewall_is_up = true; flush_table("filter"); flush_table("mangle"); @@ -2,7 +2,7 @@ * * Connection Manager * - * Copyright (C) 2007-2012 Intel Corporation. All rights reserved. + * Copyright (C) 2007-2013 Intel Corporation. All rights reserved. * Copyright (C) 2003-2005 Go-Core Project * Copyright (C) 2003-2006 Helsinki University of Technology * @@ -46,8 +46,10 @@ #include <linux/if_tun.h> #include <ctype.h> #include <ifaddrs.h> +#include <linux/fib_rules.h> #include "connman.h" +#include <gdhcp/gdhcp.h> #define NLMSG_TAIL(nmsg) \ ((struct rtattr *) (((uint8_t*) (nmsg)) + \ @@ -96,7 +98,7 @@ int __connman_inet_modify_address(int cmd, int flags, "prefixlen %hhu broadcast %s", cmd, flags, index, family, address, peer, prefixlen, broadcast); - if (address == NULL) + if (!address) return -EINVAL; if (family != AF_INET && family != AF_INET6) @@ -121,13 +123,13 @@ int __connman_inet_modify_address(int cmd, int flags, if (inet_pton(AF_INET, address, &ipv4_addr) < 1) return -1; - if (broadcast != NULL) + if (broadcast) inet_pton(AF_INET, broadcast, &ipv4_bcast); else ipv4_bcast.s_addr = ipv4_addr.s_addr | htonl(0xfffffffflu >> prefixlen); - if (peer != NULL) { + if (peer) { if (inet_pton(AF_INET, peer, &ipv4_dest) < 1) return -1; @@ -193,7 +195,7 @@ int connman_inet_ifindex(const char *name) struct ifreq ifr; int sk, err; - if (name == NULL) + if (!name) return -1; sk = socket(PF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0); @@ -201,7 +203,7 @@ int connman_inet_ifindex(const char *name) return -1; memset(&ifr, 0, sizeof(ifr)); - strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); + strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name) - 1); err = ioctl(sk, SIOCGIFINDEX, &ifr); @@ -334,7 +336,7 @@ int connman_inet_ifdown(int index) } memset(&addr_ifr, 0, sizeof(addr_ifr)); - memcpy(&addr_ifr.ifr_name, &ifr.ifr_name, sizeof(ifr.ifr_name)); + memcpy(&addr_ifr.ifr_name, &ifr.ifr_name, sizeof(ifr.ifr_name) - 1); addr = (struct sockaddr_in *)&addr_ifr.ifr_addr; addr->sin_family = AF_INET; if (ioctl(sk, SIOCSIFADDR, &addr_ifr) < 0) @@ -358,9 +360,9 @@ done: return err; } -connman_bool_t connman_inet_is_cfg80211(int index) +bool connman_inet_is_cfg80211(int index) { - connman_bool_t result = FALSE; + bool result = false; char phy80211_path[PATH_MAX]; struct stat st; struct ifreq ifr; @@ -368,7 +370,7 @@ connman_bool_t connman_inet_is_cfg80211(int index) sk = socket(PF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0); if (sk < 0) - return FALSE; + return false; memset(&ifr, 0, sizeof(ifr)); ifr.ifr_ifindex = index; @@ -380,7 +382,7 @@ connman_bool_t connman_inet_is_cfg80211(int index) "/sys/class/net/%s/phy80211", ifr.ifr_name); if (stat(phy80211_path, &st) == 0 && (st.st_mode & S_IFDIR)) - result = TRUE; + result = true; done: close(sk); @@ -401,7 +403,7 @@ int connman_inet_set_ipv6_address(int index, unsigned char prefix_len; const char *address; - if (ipaddress->local == NULL) + if (!ipaddress->local) return 0; prefix_len = ipaddress->prefixlen; @@ -426,7 +428,7 @@ int connman_inet_set_address(int index, struct connman_ipaddress *ipaddress) unsigned char prefix_len; const char *address, *broadcast, *peer; - if (ipaddress->local == NULL) + if (!ipaddress->local) return -1; prefix_len = ipaddress->prefixlen; @@ -454,6 +456,9 @@ int connman_inet_clear_ipv6_address(int index, const char *address, DBG("index %d address %s prefix_len %d", index, address, prefix_len); + if (!address) + return -EINVAL; + err = __connman_inet_modify_address(RTM_DELADDR, 0, index, AF_INET6, address, NULL, prefix_len, NULL); if (err < 0) { @@ -477,6 +482,9 @@ int connman_inet_clear_address(int index, struct connman_ipaddress *ipaddress) DBG("index %d address %s prefix_len %d", index, address, prefix_len); + if (!address) + return -EINVAL; + err = __connman_inet_modify_address(RTM_DELADDR, 0, index, AF_INET, address, peer, prefix_len, broadcast); if (err < 0) { @@ -529,9 +537,9 @@ int connman_inet_add_network_route(int index, const char *host, memset(&rt, 0, sizeof(rt)); rt.rt_flags = RTF_UP; - if (gateway != NULL) + if (gateway) rt.rt_flags |= RTF_GATEWAY; - if (netmask == NULL) + if (!netmask) rt.rt_flags |= RTF_HOST; memset(&addr, 0, sizeof(addr)); @@ -541,7 +549,7 @@ int connman_inet_add_network_route(int index, const char *host, memset(&addr, 0, sizeof(addr)); addr.sin_family = AF_INET; - if (gateway != NULL) + if (gateway) addr.sin_addr.s_addr = inet_addr(gateway); else addr.sin_addr.s_addr = INADDR_ANY; @@ -550,7 +558,7 @@ int connman_inet_add_network_route(int index, const char *host, memset(&addr, 0, sizeof(addr)); addr.sin_family = AF_INET; addr.sin_addr.s_addr = INADDR_ANY; - if (netmask != NULL) + if (netmask) addr.sin_addr.s_addr = inet_addr(netmask); else addr.sin_addr.s_addr = INADDR_ANY; @@ -628,7 +636,7 @@ int connman_inet_del_ipv6_network_route(int index, const char *host, DBG("index %d host %s", index, host); - if (host == NULL) + if (!host) return -EINVAL; memset(&rt, 0, sizeof(rt)); @@ -678,7 +686,7 @@ int connman_inet_add_ipv6_network_route(int index, const char *host, DBG("index %d host %s gateway %s", index, host, gateway); - if (host == NULL) + if (!host) return -EINVAL; memset(&rt, 0, sizeof(rt)); @@ -692,7 +700,7 @@ int connman_inet_add_ipv6_network_route(int index, const char *host, rt.rtmsg_flags = RTF_UP | RTF_HOST; - if (gateway != NULL) { + if (gateway) { rt.rtmsg_flags |= RTF_GATEWAY; inet_pton(AF_INET6, gateway, &rt.rtmsg_gateway); } @@ -725,47 +733,6 @@ int connman_inet_add_ipv6_host_route(int index, const char *host, return connman_inet_add_ipv6_network_route(index, host, gateway, 128); } -int connman_inet_set_ipv6_gateway_address(int index, const char *gateway) -{ - struct in6_rtmsg rt; - int sk, err = 0; - - DBG("index %d gateway %s", index, gateway); - - if (gateway == NULL) - return -EINVAL; - - memset(&rt, 0, sizeof(rt)); - - if (inet_pton(AF_INET6, gateway, &rt.rtmsg_gateway) < 0) { - err = -errno; - goto out; - } - - rt.rtmsg_flags = RTF_UP | RTF_GATEWAY; - rt.rtmsg_metric = 1; - rt.rtmsg_dst_len = 0; - rt.rtmsg_ifindex = index; - - sk = socket(AF_INET6, SOCK_DGRAM | SOCK_CLOEXEC, 0); - if (sk < 0) { - err = -errno; - goto out; - } - - if (ioctl(sk, SIOCADDRT, &rt) < 0 && errno != EEXIST) - err = -errno; - - close(sk); - -out: - if (err < 0) - connman_error("Set default IPv6 gateway error (%s)", - strerror(-err)); - - return err; -} - int connman_inet_clear_ipv6_gateway_address(int index, const char *gateway) { struct in6_rtmsg rt; @@ -773,7 +740,7 @@ int connman_inet_clear_ipv6_gateway_address(int index, const char *gateway) DBG("index %d gateway %s", index, gateway); - if (gateway == NULL) + if (!gateway) return -EINVAL; memset(&rt, 0, sizeof(rt)); @@ -807,63 +774,6 @@ out: return err; } -int connman_inet_set_gateway_address(int index, const char *gateway) -{ - struct ifreq ifr; - struct rtentry rt; - struct sockaddr_in addr; - int sk, err = 0; - - DBG("index %d gateway %s", index, gateway); - - sk = socket(PF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0); - if (sk < 0) { - err = -errno; - goto out; - } - - memset(&ifr, 0, sizeof(ifr)); - ifr.ifr_ifindex = index; - - if (ioctl(sk, SIOCGIFNAME, &ifr) < 0) { - err = -errno; - close(sk); - goto out; - } - - DBG("ifname %s", ifr.ifr_name); - - memset(&rt, 0, sizeof(rt)); - rt.rt_flags = RTF_UP | RTF_GATEWAY; - - memset(&addr, 0, sizeof(addr)); - addr.sin_family = AF_INET; - addr.sin_addr.s_addr = INADDR_ANY; - memcpy(&rt.rt_dst, &addr, sizeof(rt.rt_dst)); - - memset(&addr, 0, sizeof(addr)); - addr.sin_family = AF_INET; - addr.sin_addr.s_addr = inet_addr(gateway); - memcpy(&rt.rt_gateway, &addr, sizeof(rt.rt_gateway)); - - memset(&addr, 0, sizeof(addr)); - addr.sin_family = AF_INET; - addr.sin_addr.s_addr = INADDR_ANY; - memcpy(&rt.rt_genmask, &addr, sizeof(rt.rt_genmask)); - - if (ioctl(sk, SIOCADDRT, &rt) < 0 && errno != EEXIST) - err = -errno; - - close(sk); - -out: - if (err < 0) - connman_error("Setting default gateway route failed (%s)", - strerror(-err)); - - return err; -} - int connman_inet_set_gateway_interface(int index) { struct ifreq ifr; @@ -1131,7 +1041,7 @@ out: return err; } -connman_bool_t connman_inet_compare_subnet(int index, const char *host) +bool connman_inet_compare_subnet(int index, const char *host) { struct ifreq ifr; struct in_addr _host_addr; @@ -1141,8 +1051,8 @@ connman_bool_t connman_inet_compare_subnet(int index, const char *host) DBG("host %s", host); - if (host == NULL) - return FALSE; + if (!host) + return false; if (inet_aton(host, &_host_addr) == 0) return -1; @@ -1150,19 +1060,19 @@ connman_bool_t connman_inet_compare_subnet(int index, const char *host) sk = socket(PF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0); if (sk < 0) - return FALSE; + return false; memset(&ifr, 0, sizeof(ifr)); ifr.ifr_ifindex = index; if (ioctl(sk, SIOCGIFNAME, &ifr) < 0) { close(sk); - return FALSE; + return false; } if (ioctl(sk, SIOCGIFNETMASK, &ifr) < 0) { close(sk); - return FALSE; + return false; } netmask = (struct sockaddr_in *)&ifr.ifr_netmask; @@ -1170,7 +1080,7 @@ connman_bool_t connman_inet_compare_subnet(int index, const char *host) if (ioctl(sk, SIOCGIFADDR, &ifr) < 0) { close(sk); - return FALSE; + return false; } close(sk); @@ -1186,7 +1096,7 @@ int connman_inet_remove_from_bridge(int index, const char *bridge) struct ifreq ifr; int sk, err = 0; - if (bridge == NULL) + if (!bridge) return -EINVAL; sk = socket(AF_INET, SOCK_STREAM | SOCK_CLOEXEC, 0); @@ -1196,7 +1106,7 @@ int connman_inet_remove_from_bridge(int index, const char *bridge) } memset(&ifr, 0, sizeof(ifr)); - strncpy(ifr.ifr_name, bridge, IFNAMSIZ - 1); + strncpy(ifr.ifr_name, bridge, sizeof(ifr.ifr_name) - 1); ifr.ifr_ifindex = index; if (ioctl(sk, SIOCBRDELIF, &ifr) < 0) @@ -1217,7 +1127,7 @@ int connman_inet_add_to_bridge(int index, const char *bridge) struct ifreq ifr; int sk, err = 0; - if (bridge == NULL) + if (!bridge) return -EINVAL; sk = socket(AF_INET, SOCK_STREAM | SOCK_CLOEXEC, 0); @@ -1227,7 +1137,7 @@ int connman_inet_add_to_bridge(int index, const char *bridge) } memset(&ifr, 0, sizeof(ifr)); - strncpy(ifr.ifr_name, bridge, IFNAMSIZ - 1); + strncpy(ifr.ifr_name, bridge, sizeof(ifr.ifr_name) - 1); ifr.ifr_ifindex = index; if (ioctl(sk, SIOCBRADDIF, &ifr) < 0) @@ -1272,7 +1182,7 @@ int connman_inet_setup_tunnel(char *tunnel, int mtu) __u32 mask; __u32 flags; - if (tunnel == NULL) + if (!tunnel) return -EINVAL; sk = socket(AF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0); @@ -1286,7 +1196,7 @@ int connman_inet_setup_tunnel(char *tunnel, int mtu) goto done; memset(&ifr, 0, sizeof(ifr)); - strncpy(ifr.ifr_name, tunnel, IFNAMSIZ); + strncpy(ifr.ifr_name, tunnel, sizeof(ifr.ifr_name) - 1); err = ioctl(sk, SIOCGIFFLAGS, &ifr); if (err) goto done; @@ -1342,11 +1252,15 @@ int connman_inet_create_tunnel(char **iface) return fd; } -struct rs_cb_data { +/* + * This callback struct is used when sending router and neighbor + * solicitation and advertisement messages. + */ +struct xs_cb_data { GIOChannel *channel; - __connman_inet_rs_cb_t callback; + void *callback; struct sockaddr_in6 addr; - guint rs_timeout; + guint timeout; guint watch_id; void *user_data; }; @@ -1361,16 +1275,16 @@ static const struct in6_addr in6addr_all_nodes_mc = IN6ADDR_ALL_NODES_MC_INIT; static const struct in6_addr in6addr_all_routers_mc = IN6ADDR_ALL_ROUTERS_MC_INIT; -static void rs_cleanup(struct rs_cb_data *data) +static void xs_cleanup(struct xs_cb_data *data) { - if (data->channel != NULL) { + if (data->channel) { g_io_channel_shutdown(data->channel, TRUE, NULL); g_io_channel_unref(data->channel); data->channel = NULL; } - if (data->rs_timeout > 0) - g_source_remove(data->rs_timeout); + if (data->timeout > 0) + g_source_remove(data->timeout); if (data->watch_id > 0) g_source_remove(data->watch_id); @@ -1380,18 +1294,20 @@ static void rs_cleanup(struct rs_cb_data *data) static gboolean rs_timeout_cb(gpointer user_data) { - struct rs_cb_data *data = user_data; + struct xs_cb_data *data = user_data; DBG("user data %p", user_data); - if (data == NULL) + if (!data) return FALSE; - if (data->callback != NULL) - data->callback(NULL, 0, data->user_data); + if (data->callback) { + __connman_inet_rs_cb_t cb = data->callback; + cb(NULL, 0, data->user_data); + } - data->rs_timeout = 0; - rs_cleanup(data); + data->timeout = 0; + xs_cleanup(data); return FALSE; } @@ -1401,10 +1317,11 @@ static int icmpv6_recv(int fd, gpointer user_data) struct iovec iov; unsigned char chdr[CMSG_BUF_LEN]; unsigned char buf[1540]; - struct rs_cb_data *data = user_data; + struct xs_cb_data *data = user_data; struct nd_router_advert *hdr; struct sockaddr_in6 saddr; ssize_t len; + __connman_inet_rs_cb_t cb = data->callback; DBG(""); @@ -1413,6 +1330,7 @@ static int icmpv6_recv(int fd, gpointer user_data) mhdr.msg_name = (void *)&saddr; mhdr.msg_namelen = sizeof(struct sockaddr_in6); + mhdr.msg_flags = 0; mhdr.msg_iov = &iov; mhdr.msg_iovlen = 1; mhdr.msg_control = (void *)chdr; @@ -1420,8 +1338,8 @@ static int icmpv6_recv(int fd, gpointer user_data) len = recvmsg(fd, &mhdr, 0); if (len < 0) { - data->callback(NULL, 0, data->user_data); - rs_cleanup(data); + cb(NULL, 0, data->user_data); + xs_cleanup(data); return -errno; } @@ -1431,14 +1349,13 @@ static int icmpv6_recv(int fd, gpointer user_data) if (hdr->nd_ra_code != 0) return 0; - data->callback(hdr, len, data->user_data); - rs_cleanup(data); + cb(hdr, len, data->user_data); + xs_cleanup(data); return len; } -static gboolean icmpv6_event(GIOChannel *chan, GIOCondition cond, - gpointer data) +static gboolean icmpv6_event(GIOChannel *chan, GIOCondition cond, gpointer data) { int fd, ret; @@ -1456,7 +1373,8 @@ static gboolean icmpv6_event(GIOChannel *chan, GIOCondition cond, } /* Adapted from RFC 1071 "C" Implementation Example */ -static uint16_t csum(const void *phdr, const void *data, socklen_t datalen) +static uint16_t csum(const void *phdr, const void *data, socklen_t datalen, + const void *extra_data, socklen_t extra_datalen) { register unsigned long sum = 0; socklen_t count; @@ -1477,13 +1395,25 @@ static uint16_t csum(const void *phdr, const void *data, socklen_t datalen) count -= 2; } + if (extra_data) { + count = extra_datalen; + addr = (uint16_t *)extra_data; + + while (count > 1) { + sum += *(addr++); + count -= 2; + } + } + while (sum >> 16) sum = (sum & 0xffff) + (sum >> 16); return (uint16_t)~sum; } -static int ndisc_send_unspec(int type, int oif, const struct in6_addr *dest) +static int ndisc_send_unspec(int type, int oif, const struct in6_addr *dest, + const struct in6_addr *source, + unsigned char *buf, size_t len, uint16_t lifetime) { struct _phdr { struct in6_addr src; @@ -1499,16 +1429,17 @@ static int ndisc_send_unspec(int type, int oif, const struct in6_addr *dest) struct icmp6_hdr icmp; struct nd_neighbor_solicit ns; struct nd_router_solicit rs; + struct nd_router_advert ra; } i; } frame; struct msghdr msgh; struct cmsghdr *cmsg; struct in6_pktinfo *pinfo; - struct sockaddr_in6 dst; + struct sockaddr_in6 dst, src; char cbuf[CMSG_SPACE(sizeof(*pinfo))]; - struct iovec iov; - int fd, datalen, ret; + struct iovec iov[2]; + int fd, datalen, ret, iovlen = 1; DBG(""); @@ -1519,35 +1450,60 @@ static int ndisc_send_unspec(int type, int oif, const struct in6_addr *dest) memset(&frame, 0, sizeof(frame)); memset(&dst, 0, sizeof(dst)); - datalen = sizeof(frame.i.rs); /* 8, csum() safe */ + if (type == ND_ROUTER_SOLICIT) + datalen = sizeof(frame.i.rs); /* 8, csum() safe */ + else if (type == ND_ROUTER_ADVERT) { + datalen = sizeof(frame.i.ra); /* 16, csum() safe */ + frame.i.ra.nd_ra_router_lifetime = htons(lifetime); + } else if (type == ND_NEIGHBOR_SOLICIT) { + datalen = sizeof(frame.i.ns); /* 24, csum() safe */ + memcpy(&frame.i.ns.nd_ns_target, buf, sizeof(struct in6_addr)); + } else { + close(fd); + return -EINVAL; + } + dst.sin6_addr = *dest; + if (source) + src.sin6_addr = *source; + else + src.sin6_addr = in6addr_any; + /* Fill in the IPv6 header */ frame.ip.ip6_vfc = 0x60; - frame.ip.ip6_plen = htons(datalen); + frame.ip.ip6_plen = htons(datalen + len); frame.ip.ip6_nxt = IPPROTO_ICMPV6; frame.ip.ip6_hlim = 255; frame.ip.ip6_dst = dst.sin6_addr; + frame.ip.ip6_src = src.sin6_addr; /* all other fields are already set to zero */ /* Prepare pseudo header for csum */ memset(&phdr, 0, sizeof(phdr)); phdr.dst = dst.sin6_addr; - phdr.plen = htonl(datalen); + phdr.src = src.sin6_addr; + phdr.plen = htonl(datalen + len); phdr.nxt = IPPROTO_ICMPV6; /* Fill in remaining ICMP header fields */ frame.i.icmp.icmp6_type = type; - frame.i.icmp.icmp6_cksum = csum(&phdr, &frame.i, datalen); + frame.i.icmp.icmp6_cksum = csum(&phdr, &frame.i, datalen, buf, len); - iov.iov_base = &frame; - iov.iov_len = sizeof(frame.ip) + datalen; + iov[0].iov_base = &frame; + iov[0].iov_len = sizeof(frame.ip) + datalen; + + if (buf) { + iov[1].iov_base = buf; + iov[1].iov_len = len; + iovlen = 2; + } dst.sin6_family = AF_INET6; msgh.msg_name = &dst; msgh.msg_namelen = sizeof(dst); - msgh.msg_iov = &iov; - msgh.msg_iovlen = 1; + msgh.msg_iov = iov; + msgh.msg_iovlen = iovlen; msgh.msg_flags = 0; memset(cbuf, 0, CMSG_SPACE(sizeof(*pinfo))); @@ -1597,39 +1553,49 @@ static int if_mc_group(int sock, int ifindex, const struct in6_addr *mc_addr, ret = setsockopt(sock, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, &val, sizeof(int)); + if (ret < 0) { + ret = -errno; + DBG("Cannot set IPV6_MULTICAST_LOOP %d/%s", ret, + strerror(-ret)); + return ret; + } - if (ret < 0) + ret = setsockopt(sock, IPPROTO_IPV6, cmd, &mreq, sizeof(mreq)); + if (ret < 0) { + ret = -errno; + DBG("Cannot set option %d %d/%s", cmd, ret, strerror(-ret)); return ret; + } - return setsockopt(sock, IPPROTO_IPV6, cmd, &mreq, sizeof(mreq)); + return 0; } int __connman_inet_ipv6_send_rs(int index, int timeout, __connman_inet_rs_cb_t callback, void *user_data) { - struct rs_cb_data *data; + struct xs_cb_data *data; struct icmp6_filter filter; struct in6_addr solicit; struct in6_addr dst = in6addr_all_routers_mc; int sk; - DBG(""); - if (timeout <= 0) return -EINVAL; - data = g_try_malloc0(sizeof(struct rs_cb_data)); - if (data == NULL) + data = g_try_malloc0(sizeof(struct xs_cb_data)); + if (!data) return -ENOMEM; data->callback = callback; data->user_data = user_data; - data->rs_timeout = g_timeout_add_seconds(timeout, rs_timeout_cb, data); + data->timeout = g_timeout_add_seconds(timeout, rs_timeout_cb, data); sk = socket(AF_INET6, SOCK_RAW | SOCK_CLOEXEC, IPPROTO_ICMPV6); if (sk < 0) return -errno; + DBG("sock %d", sk); + ICMP6_FILTER_SETBLOCKALL(&filter); ICMP6_FILTER_SETPASS(ND_ROUTER_ADVERT, &filter); @@ -1650,11 +1616,399 @@ int __connman_inet_ipv6_send_rs(int index, int timeout, G_IO_IN | G_IO_NVAL | G_IO_HUP | G_IO_ERR, icmpv6_event, data); - ndisc_send_unspec(ND_ROUTER_SOLICIT, index, &dst); + ndisc_send_unspec(ND_ROUTER_SOLICIT, index, &dst, NULL, NULL, 0, 0); + + return 0; +} + +static inline void ipv6_addr_advert_mult(const struct in6_addr *addr, + struct in6_addr *advert) +{ + ipv6_addr_set(advert, htonl(0xFF020000), 0, htonl(0x2), + htonl(0xFF000000) | addr->s6_addr32[3]); +} + +#define MSG_SIZE_SEND 1452 + +static int inc_len(int len, int inc) +{ + if (len > MSG_SIZE_SEND) + return -EINVAL; + + len += inc; + return len; +} + +int __connman_inet_ipv6_send_ra(int index, struct in6_addr *src_addr, + GSList *prefixes, int router_lifetime) +{ + GSList *list; + struct in6_addr src, *source; + struct in6_addr dst = in6addr_all_nodes_mc; + GDHCPIAPrefix *prefix; + unsigned char buf[MSG_SIZE_SEND]; + char addr_str[INET6_ADDRSTRLEN]; + int sk, err = 0; + int len, count = 0; + + if (!prefixes) + return -EINVAL; + + sk = socket(AF_INET6, SOCK_RAW | SOCK_CLOEXEC, IPPROTO_ICMPV6); + if (sk < 0) + return -errno; + + if (!src_addr) { + __connman_inet_get_interface_ll_address(index, AF_INET6, &src); + source = &src; + } else + source = src_addr; + + DBG("sock %d index %d prefixes %p src %s lifetime %d", sk, index, + prefixes, inet_ntop(AF_INET6, source, addr_str, + INET6_ADDRSTRLEN), + router_lifetime); + + memset(buf, 0, MSG_SIZE_SEND); + len = 0; + + for (list = prefixes; list; list = list->next) { + struct nd_opt_prefix_info *pinfo; + + prefix = list->data; + pinfo = (struct nd_opt_prefix_info *)(buf + len); + + len = inc_len(len, sizeof(*pinfo)); + if (len < 0) { + err = len; + goto out; + } + + pinfo->nd_opt_pi_type = ND_OPT_PREFIX_INFORMATION; + pinfo->nd_opt_pi_len = 4; + pinfo->nd_opt_pi_prefix_len = prefix->prefixlen; + pinfo->nd_opt_pi_flags_reserved = ND_OPT_PI_FLAG_ONLINK; + pinfo->nd_opt_pi_flags_reserved |= ND_OPT_PI_FLAG_AUTO; + if (router_lifetime > 0) { + pinfo->nd_opt_pi_valid_time = htonl(prefix->valid); + pinfo->nd_opt_pi_preferred_time = + htonl(prefix->preferred); + } + pinfo->nd_opt_pi_reserved2 = 0; + + memcpy(&pinfo->nd_opt_pi_prefix, &prefix->prefix, + sizeof(struct in6_addr)); + + DBG("[%d] index %d prefix %s/%d", count, index, + inet_ntop(AF_INET6, &prefix->prefix, addr_str, + INET6_ADDRSTRLEN), prefix->prefixlen); + + count++; + } + + if (count > 0) { + err = ndisc_send_unspec(ND_ROUTER_ADVERT, index, &dst, source, + buf, len, router_lifetime); + if (err < 0) + DBG("cannot send RA %d/%s", err, strerror(-err)); + } + +out: + close(sk); + return err; +} + +void __connman_inet_ipv6_stop_recv_rs(void *context) +{ + if (!context) + return; + + xs_cleanup(context); +} + +static int icmpv6_rs_recv(int fd, gpointer user_data) +{ + struct msghdr mhdr; + struct iovec iov; + unsigned char chdr[CMSG_BUF_LEN]; + unsigned char buf[1540]; + struct xs_cb_data *data = user_data; + struct nd_router_solicit *hdr; + struct sockaddr_in6 saddr; + ssize_t len; + __connman_inet_recv_rs_cb_t cb = data->callback; + + DBG(""); + + iov.iov_len = sizeof(buf); + iov.iov_base = buf; + + mhdr.msg_name = (void *)&saddr; + mhdr.msg_namelen = sizeof(struct sockaddr_in6); + mhdr.msg_flags = 0; + mhdr.msg_iov = &iov; + mhdr.msg_iovlen = 1; + mhdr.msg_control = (void *)chdr; + mhdr.msg_controllen = CMSG_BUF_LEN; + + len = recvmsg(fd, &mhdr, 0); + if (len < 0) { + cb(NULL, 0, data->user_data); + return -errno; + } + + hdr = (struct nd_router_solicit *)buf; + DBG("code %d len %zd hdr %zd", hdr->nd_rs_code, len, + sizeof(struct nd_router_solicit)); + if (hdr->nd_rs_code != 0) + return 0; + + cb(hdr, len, data->user_data); + return len; +} + +static gboolean icmpv6_rs_event(GIOChannel *chan, GIOCondition cond, + gpointer data) +{ + int fd, ret; + + DBG(""); + + if (cond & (G_IO_NVAL | G_IO_HUP | G_IO_ERR)) + return FALSE; + + fd = g_io_channel_unix_get_fd(chan); + ret = icmpv6_rs_recv(fd, data); + if (ret == 0) + return TRUE; + + return FALSE; +} + +int __connman_inet_ipv6_start_recv_rs(int index, + __connman_inet_recv_rs_cb_t callback, + void *user_data, + void **context) +{ + struct xs_cb_data *data; + struct icmp6_filter filter; + char addr_str[INET6_ADDRSTRLEN]; + int sk, err; + + data = g_try_malloc0(sizeof(struct xs_cb_data)); + if (!data) + return -ENOMEM; + + data->callback = callback; + data->user_data = user_data; + + sk = socket(AF_INET6, SOCK_RAW | SOCK_CLOEXEC, IPPROTO_ICMPV6); + if (sk < 0) { + g_free(data); + return -errno; + } + + DBG("sock %d", sk); + + ICMP6_FILTER_SETBLOCKALL(&filter); + ICMP6_FILTER_SETPASS(ND_ROUTER_SOLICIT, &filter); + + setsockopt(sk, IPPROTO_ICMPV6, ICMP6_FILTER, &filter, + sizeof(struct icmp6_filter)); + + err = if_mc_group(sk, index, &in6addr_all_routers_mc, IPV6_JOIN_GROUP); + if (err < 0) + DBG("Cannot join mc %s %d/%s", inet_ntop(AF_INET6, + &in6addr_all_routers_mc, addr_str, INET6_ADDRSTRLEN), + err, strerror(-err)); + + data->channel = g_io_channel_unix_new(sk); + g_io_channel_set_close_on_unref(data->channel, TRUE); + + g_io_channel_set_encoding(data->channel, NULL, NULL); + g_io_channel_set_buffered(data->channel, FALSE); + + data->watch_id = g_io_add_watch(data->channel, + G_IO_IN | G_IO_NVAL | G_IO_HUP | G_IO_ERR, + icmpv6_rs_event, data); + + *context = data; return 0; } +static gboolean ns_timeout_cb(gpointer user_data) +{ + struct xs_cb_data *data = user_data; + + DBG("user data %p", user_data); + + if (!data) + return FALSE; + + if (data->callback) { + __connman_inet_ns_cb_t cb = data->callback; + cb(NULL, 0, &data->addr.sin6_addr, data->user_data); + } + + data->timeout = 0; + xs_cleanup(data); + return FALSE; +} + +static int icmpv6_nd_recv(int fd, gpointer user_data) +{ + struct msghdr mhdr; + struct iovec iov; + unsigned char chdr[CMSG_BUF_LEN]; + unsigned char buf[1540]; + struct xs_cb_data *data = user_data; + struct nd_neighbor_advert *hdr; + struct sockaddr_in6 saddr; + ssize_t len; + __connman_inet_ns_cb_t cb = data->callback; + + DBG(""); + + iov.iov_len = sizeof(buf); + iov.iov_base = buf; + + mhdr.msg_name = (void *)&saddr; + mhdr.msg_namelen = sizeof(struct sockaddr_in6); + mhdr.msg_flags = 0; + mhdr.msg_iov = &iov; + mhdr.msg_iovlen = 1; + mhdr.msg_control = (void *)chdr; + mhdr.msg_controllen = CMSG_BUF_LEN; + + len = recvmsg(fd, &mhdr, 0); + if (len < 0) { + cb(NULL, 0, &data->addr.sin6_addr, data->user_data); + xs_cleanup(data); + return -errno; + } + + hdr = (struct nd_neighbor_advert *)buf; + DBG("code %d len %zd hdr %zd", hdr->nd_na_code, len, + sizeof(struct nd_neighbor_advert)); + if (hdr->nd_na_code != 0) + return 0; + + /* + * We can receive any neighbor advertisement so we need to check if the + * packet was meant for us and ignore the packet otherwise. + */ + if (memcmp(&data->addr.sin6_addr, &hdr->nd_na_target, + sizeof(struct in6_addr))) + return 0; + + cb(hdr, len, &data->addr.sin6_addr, data->user_data); + xs_cleanup(data); + + return len; +} + +static gboolean icmpv6_nd_event(GIOChannel *chan, GIOCondition cond, + gpointer data) +{ + int fd, ret; + + DBG(""); + + if (cond & (G_IO_NVAL | G_IO_HUP | G_IO_ERR)) + return FALSE; + + fd = g_io_channel_unix_get_fd(chan); + ret = icmpv6_nd_recv(fd, data); + if (ret == 0) + return TRUE; + + return FALSE; +} + +int __connman_inet_ipv6_do_dad(int index, int timeout_ms, + struct in6_addr *addr, + __connman_inet_ns_cb_t callback, + void *user_data) +{ + struct xs_cb_data *data; + struct icmp6_filter filter; + struct in6_addr solicit; + int sk, err, val = 1; + + if (timeout_ms <= 0) + return -EINVAL; + + data = g_try_malloc0(sizeof(struct xs_cb_data)); + if (!data) + return -ENOMEM; + + data->callback = callback; + data->user_data = user_data; + data->timeout = g_timeout_add_full(G_PRIORITY_DEFAULT, + (guint)timeout_ms, + ns_timeout_cb, + data, + NULL); + memcpy(&data->addr.sin6_addr, addr, sizeof(struct in6_addr)); + + sk = socket(AF_INET6, SOCK_RAW | SOCK_CLOEXEC, IPPROTO_ICMPV6); + if (sk < 0) + return -errno; + + DBG("sock %d", sk); + + ICMP6_FILTER_SETBLOCKALL(&filter); + ICMP6_FILTER_SETPASS(ND_NEIGHBOR_ADVERT, &filter); + + setsockopt(sk, IPPROTO_ICMPV6, ICMP6_FILTER, &filter, + sizeof(struct icmp6_filter)); + + if (setsockopt(sk, IPPROTO_IPV6, IPV6_RECVPKTINFO, + &val, sizeof(val)) < 0) { + err = -errno; + DBG("Cannot set IPV6_RECVPKTINFO %d/%s", err, + strerror(-err)); + close(sk); + return err; + } + + if (setsockopt(sk, IPPROTO_IPV6, IPV6_RECVHOPLIMIT, + &val, sizeof(val)) < 0) { + err = -errno; + DBG("Cannot set IPV6_RECVHOPLIMIT %d/%s", err, + strerror(-err)); + close(sk); + return err; + } + + val = 0; + setsockopt(sk, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, &val, sizeof(val)); + + ipv6_addr_solict_mult(addr, &solicit); + if_mc_group(sk, index, &in6addr_all_nodes_mc, IPV6_JOIN_GROUP); + if_mc_group(sk, index, &solicit, IPV6_JOIN_GROUP); + + data->channel = g_io_channel_unix_new(sk); + g_io_channel_set_close_on_unref(data->channel, TRUE); + + g_io_channel_set_encoding(data->channel, NULL, NULL); + g_io_channel_set_buffered(data->channel, FALSE); + + data->watch_id = g_io_add_watch(data->channel, + G_IO_IN | G_IO_NVAL | G_IO_HUP | G_IO_ERR, + icmpv6_nd_event, data); + + err = ndisc_send_unspec(ND_NEIGHBOR_SOLICIT, index, &solicit, NULL, + (unsigned char *)addr, 0, 0); + if (err < 0) { + DBG("Cannot send NS %d/%s", err, strerror(-err)); + xs_cleanup(data); + } + + return err; +} + GSList *__connman_inet_ipv6_get_prefixes(struct nd_router_advert *hdr, unsigned int length) { @@ -1686,7 +2040,7 @@ GSList *__connman_inet_ipv6_get_prefixes(struct nd_router_advert *hdr, pinfo = (struct nd_opt_prefix_info *)pos; prefix = inet_ntop(AF_INET6, &pinfo->nd_opt_pi_prefix, prefix_str, INET6_ADDRSTRLEN); - if (prefix == NULL) + if (!prefix) break; str = g_strdup_printf("%s/%d", prefix, @@ -1759,7 +2113,7 @@ static int get_dest_addr(int family, int index, char *buf, int len) return -errno; } - if (inet_ntop(family, addr, buf, len) == NULL) { + if (!inet_ntop(family, addr, buf, len)) { DBG("error %d/%s", errno, strerror(errno)); return -errno; } @@ -1854,7 +2208,7 @@ static void inet_rtnl_cleanup(struct inet_rtnl_cb_data *data) { struct __connman_inet_rtnl_handle *rth = data->rtnl; - if (data->channel != NULL) { + if (data->channel) { g_io_channel_shutdown(data->channel, TRUE, NULL); g_io_channel_unref(data->channel); data->channel = NULL; @@ -1868,7 +2222,7 @@ static void inet_rtnl_cleanup(struct inet_rtnl_cb_data *data) if (data->watch_id > 0) g_source_remove(data->watch_id); - if (rth != NULL) { + if (rth) { __connman_inet_rtnl_close(rth); g_free(rth); } @@ -1882,10 +2236,10 @@ static gboolean inet_rtnl_timeout_cb(gpointer user_data) DBG("user data %p", user_data); - if (data == NULL) + if (!data) return FALSE; - if (data->callback != NULL) + if (data->callback) data->callback(NULL, data->user_data); data->rtnl_timeout = 0; @@ -2006,9 +2360,9 @@ int __connman_inet_rtnl_talk(struct __connman_inet_rtnl_handle *rtnl, n->nlmsg_seq = seq = ++rtnl->seq; - if (callback != NULL) { + if (callback) { data = g_try_malloc0(sizeof(struct inet_rtnl_cb_data)); - if (data == NULL) + if (!data) return -ENOMEM; data->callback = callback; @@ -2031,9 +2385,10 @@ int __connman_inet_rtnl_talk(struct __connman_inet_rtnl_handle *rtnl, err = sendto(rtnl->fd, &rtnl->req.n, rtnl->req.n.nlmsg_len, 0, (struct sockaddr *) &nladdr, sizeof(nladdr)); - DBG("handle %p len %d err %d", rtnl, rtnl->req.n.nlmsg_len, err); + DBG("handle %p len %d", rtnl, rtnl->req.n.nlmsg_len); if (err < 0) { - connman_error("Can not talk to rtnetlink"); + connman_error("Can not talk to rtnetlink err %d %s", + -errno, strerror(errno)); return -errno; } @@ -2105,7 +2460,7 @@ static void get_route_cb(struct nlmsghdr *answer, void *user_data) DBG("answer %p data %p", answer, user_data); - if (answer == NULL) + if (!answer) goto out; len = answer->nlmsg_len; @@ -2126,10 +2481,10 @@ static void get_route_cb(struct nlmsghdr *answer, void *user_data) parse_rtattr(tb, RTA_MAX, RTM_RTA(r), len); - if (tb[RTA_OIF] != NULL) + if (tb[RTA_OIF]) index = *(int *)RTA_DATA(tb[RTA_OIF]); - if (tb[RTA_GATEWAY] != NULL) + if (tb[RTA_GATEWAY]) addr = inet_ntop(r->rtm_family, RTA_DATA(tb[RTA_GATEWAY]), abuf, sizeof(abuf)); @@ -2137,7 +2492,7 @@ static void get_route_cb(struct nlmsghdr *answer, void *user_data) DBG("addr %s index %d user %p", addr, index, data->user_data); out: - if (data != NULL && data->callback != NULL) + if (data && data->callback) data->callback(addr, index, data->user_data); g_free(data); @@ -2158,7 +2513,7 @@ int __connman_inet_get_route(const char *dest_address, DBG("dest %s", dest_address); - if (dest_address == NULL) + if (!dest_address) return -EINVAL; memset(&hints, 0, sizeof(hints)); @@ -2170,7 +2525,7 @@ int __connman_inet_get_route(const char *dest_address, return -EINVAL; rth = g_try_malloc0(sizeof(struct __connman_inet_rtnl_handle)); - if (rth == NULL) { + if (!rth) { freeaddrinfo(rp); return -ENOMEM; } @@ -2197,7 +2552,7 @@ int __connman_inet_get_route(const char *dest_address, goto fail; data = g_try_malloc(sizeof(struct get_route_cb_data)); - if (data == NULL) { + if (!data) { err = -ENOMEM; goto done; } @@ -2242,7 +2597,7 @@ int connman_inet_check_ipaddress(const char *host) } /* Check routine modified from ics-dhcp 4.2.3-P2 */ -connman_bool_t connman_inet_check_hostname(const char *ptr, size_t len) +bool connman_inet_check_hostname(const char *ptr, size_t len) { const char *p; @@ -2250,7 +2605,7 @@ connman_bool_t connman_inet_check_hostname(const char *ptr, size_t len) * Not empty or complete length not over 255 characters. */ if ((len == 0) || (len > 256)) - return FALSE; + return false; /* * Consists of [[:alnum:]-]+ labels separated by [.] @@ -2263,7 +2618,7 @@ connman_bool_t connman_inet_check_hostname(const char *ptr, size_t len) * Not allowed at begin or end of a label. */ if (((p - ptr) == 0) || (len == 0) || (p[1] == '.')) - return FALSE; + return false; } else if (*p == '.') { /* @@ -2273,7 +2628,7 @@ connman_bool_t connman_inet_check_hostname(const char *ptr, size_t len) size_t d = p - ptr; if ((d <= 0) || (d >= 64)) - return FALSE; + return false; ptr = p + 1; /* Jump to the next label */ @@ -2281,11 +2636,11 @@ connman_bool_t connman_inet_check_hostname(const char *ptr, size_t len) /* * Also numbers at the begin are fine */ - return FALSE; + return false; } } - return TRUE; + return true; } char **__connman_inet_get_running_interfaces(void) @@ -2310,7 +2665,7 @@ char **__connman_inet_get_running_interfaces(void) * calls. */ ifr = g_try_malloc0(ifc.ifc_len * 2); - if (ifr == NULL) + if (!ifr) goto error; ifc.ifc_req = ifr; @@ -2321,7 +2676,7 @@ char **__connman_inet_get_running_interfaces(void) numif = ifc.ifc_len / sizeof(struct ifreq); result = g_try_malloc0((numif + 1) * sizeof(char *)); - if (result == NULL) + if (!result) goto error; close(sk); @@ -2366,16 +2721,16 @@ error: return NULL; } -connman_bool_t connman_inet_is_ipv6_supported() +bool connman_inet_is_ipv6_supported() { int sk; sk = socket(PF_INET6, SOCK_DGRAM | SOCK_CLOEXEC, 0); if (sk < 0) - return FALSE; + return false; close(sk); - return TRUE; + return true; } int __connman_inet_get_interface_address(int index, int family, void *address) @@ -2384,7 +2739,7 @@ int __connman_inet_get_interface_address(int index, int family, void *address) int err = -ENOENT; char name[IF_NAMESIZE]; - if (if_indextoname(index, name) == NULL) + if (!if_indextoname(index, name)) return -EINVAL; DBG("index %d interface %s", index, name); @@ -2395,8 +2750,8 @@ int __connman_inet_get_interface_address(int index, int family, void *address) return err; } - for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) { - if (ifa->ifa_addr == NULL) + for (ifa = ifaddr; ifa; ifa = ifa->ifa_next) { + if (!ifa->ifa_addr) continue; if (strncmp(ifa->ifa_name, name, IF_NAMESIZE) == 0 && @@ -2431,3 +2786,237 @@ out: freeifaddrs(ifaddr); return err; } + +static int iprule_modify(int cmd, int family, uint32_t table_id, + uint32_t fwmark) +{ + struct __connman_inet_rtnl_handle rth; + int ret; + + memset(&rth, 0, sizeof(rth)); + + rth.req.n.nlmsg_type = cmd; + rth.req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg)); + rth.req.n.nlmsg_flags = NLM_F_REQUEST; + rth.req.u.r.rt.rtm_family = family; + rth.req.u.r.rt.rtm_protocol = RTPROT_BOOT; + rth.req.u.r.rt.rtm_scope = RT_SCOPE_UNIVERSE; + rth.req.u.r.rt.rtm_table = table_id; + rth.req.u.r.rt.rtm_type = RTN_UNSPEC; + rth.req.u.r.rt.rtm_flags = 0; + + if (cmd == RTM_NEWRULE) { + rth.req.n.nlmsg_flags |= NLM_F_CREATE|NLM_F_EXCL; + rth.req.u.r.rt.rtm_type = RTN_UNICAST; + } + + __connman_inet_rtnl_addattr32(&rth.req.n, sizeof(rth.req), + FRA_FWMARK, fwmark); + + if (table_id < 256) { + rth.req.u.r.rt.rtm_table = table_id; + } else { + rth.req.u.r.rt.rtm_table = RT_TABLE_UNSPEC; + __connman_inet_rtnl_addattr32(&rth.req.n, sizeof(rth.req), + FRA_TABLE, table_id); + } + + if (rth.req.u.r.rt.rtm_family == AF_UNSPEC) + rth.req.u.r.rt.rtm_family = AF_INET; + + ret = __connman_inet_rtnl_open(&rth); + if (ret < 0) + goto done; + + ret = __connman_inet_rtnl_send(&rth, &rth.req.n); + +done: + __connman_inet_rtnl_close(&rth); + + return ret; +} + +int __connman_inet_add_fwmark_rule(uint32_t table_id, int family, uint32_t fwmark) +{ + /* ip rule add fwmark 9876 table 1234 */ + + return iprule_modify(RTM_NEWRULE, family, table_id, fwmark); +} + +int __connman_inet_del_fwmark_rule(uint32_t table_id, int family, uint32_t fwmark) +{ + return iprule_modify(RTM_DELRULE, family, table_id, fwmark); +} + +static int iproute_default_modify(int cmd, uint32_t table_id, int ifindex, + const char *gateway) +{ + struct __connman_inet_rtnl_handle rth; + unsigned char buf[sizeof(struct in6_addr)]; + int ret, len; + int family = connman_inet_check_ipaddress(gateway); + + switch (family) { + case AF_INET: + len = 4; + break; + case AF_INET6: + len = 16; + break; + default: + return -EINVAL; + } + + ret = inet_pton(family, gateway, buf); + if (ret <= 0) + return -EINVAL; + + memset(&rth, 0, sizeof(rth)); + + rth.req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg)); + rth.req.n.nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL; + rth.req.n.nlmsg_type = cmd; + rth.req.u.r.rt.rtm_family = family; + rth.req.u.r.rt.rtm_table = RT_TABLE_MAIN; + rth.req.u.r.rt.rtm_scope = RT_SCOPE_NOWHERE; + rth.req.u.r.rt.rtm_protocol = RTPROT_BOOT; + rth.req.u.r.rt.rtm_scope = RT_SCOPE_UNIVERSE; + rth.req.u.r.rt.rtm_type = RTN_UNICAST; + + __connman_inet_rtnl_addattr_l(&rth.req.n, sizeof(rth.req), RTA_GATEWAY, + buf, len); + if (table_id < 256) { + rth.req.u.r.rt.rtm_table = table_id; + } else { + rth.req.u.r.rt.rtm_table = RT_TABLE_UNSPEC; + __connman_inet_rtnl_addattr32(&rth.req.n, sizeof(rth.req), + RTA_TABLE, table_id); + } + + __connman_inet_rtnl_addattr32(&rth.req.n, sizeof(rth.req), + RTA_OIF, ifindex); + + ret = __connman_inet_rtnl_open(&rth); + if (ret < 0) + goto done; + + ret = __connman_inet_rtnl_send(&rth, &rth.req.n); + +done: + __connman_inet_rtnl_close(&rth); + + return ret; +} + +int __connman_inet_add_default_to_table(uint32_t table_id, int ifindex, + const char *gateway) +{ + /* ip route add default via 1.2.3.4 dev wlan0 table 1234 */ + + return iproute_default_modify(RTM_NEWROUTE, table_id, ifindex, gateway); +} + +int __connman_inet_del_default_from_table(uint32_t table_id, int ifindex, + const char *gateway) +{ + /* ip route del default via 1.2.3.4 dev wlan0 table 1234 */ + + return iproute_default_modify(RTM_DELROUTE, table_id, ifindex, gateway); +} + +int __connman_inet_get_interface_ll_address(int index, int family, + void *address) +{ + struct ifaddrs *ifaddr, *ifa; + int err = -ENOENT; + char name[IF_NAMESIZE]; + + if (!if_indextoname(index, name)) + return -EINVAL; + + DBG("index %d interface %s", index, name); + + if (getifaddrs(&ifaddr) < 0) { + err = -errno; + DBG("Cannot get addresses err %d/%s", err, strerror(-err)); + return err; + } + + for (ifa = ifaddr; ifa; ifa = ifa->ifa_next) { + if (!ifa->ifa_addr) + continue; + + if (strncmp(ifa->ifa_name, name, IF_NAMESIZE) == 0 && + ifa->ifa_addr->sa_family == family) { + if (family == AF_INET) { + struct sockaddr_in *in4 = (struct sockaddr_in *) + ifa->ifa_addr; + if (in4->sin_addr.s_addr == INADDR_ANY) + continue; + if ((in4->sin_addr.s_addr & IN_CLASSB_NET) != + ((in_addr_t) 0xa9fe0000)) + continue; + memcpy(address, &in4->sin_addr, + sizeof(struct in_addr)); + } else if (family == AF_INET6) { + struct sockaddr_in6 *in6 = + (struct sockaddr_in6 *)ifa->ifa_addr; + if (memcmp(&in6->sin6_addr, &in6addr_any, + sizeof(struct in6_addr)) == 0) + continue; + if (!IN6_IS_ADDR_LINKLOCAL(&in6->sin6_addr)) + continue; + + memcpy(address, &in6->sin6_addr, + sizeof(struct in6_addr)); + } else { + err = -EINVAL; + goto out; + } + + err = 0; + break; + } + } + +out: + freeifaddrs(ifaddr); + return err; +} + +int __connman_inet_get_address_netmask(int ifindex, + struct sockaddr_in *address, + struct sockaddr_in *netmask) +{ + int sk, ret = -EINVAL; + struct ifreq ifr; + + DBG("index %d", ifindex); + + sk = socket(PF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0); + if (sk < 0) + return -EINVAL; + + memset(&ifr, 0, sizeof(ifr)); + ifr.ifr_ifindex = ifindex; + + if (ioctl(sk, SIOCGIFNAME, &ifr) < 0) + goto out; + + if (ioctl(sk, SIOCGIFNETMASK, &ifr) < 0) + goto out; + + memcpy(netmask, (struct sockaddr_in *)&ifr.ifr_netmask, + sizeof(struct sockaddr_in)); + + if (ioctl(sk, SIOCGIFADDR, &ifr) < 0) + goto out; + + memcpy(address, (struct sockaddr_in *)&ifr.ifr_addr, + sizeof(struct sockaddr_in)); + ret = 0; + +out: + close(sk); + return ret; +} diff --git a/src/inotify.c b/src/inotify.c index f451f1c0..72ba6f68 100644 --- a/src/inotify.c +++ b/src/inotify.c @@ -3,7 +3,7 @@ * Connection Manager * * Copyright (C) 2007-2012 Intel Corporation. All rights reserved. - * Copyright (C) 2012 BMW Car IT GmbH. All rights reserved. + * Copyright (C) 2012-2013 BMW Car IT GmbH. 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 @@ -95,7 +95,7 @@ static gboolean inotify_data(GIOChannel *channel, GIOCondition cond, next_event += len; bytes_read -= len; - for (list = inotify->list; list != NULL; list = list->next) { + for (list = inotify->list; list; list = list->next) { inotify_event_cb callback = list->data; (*callback)(event, ident); @@ -125,7 +125,7 @@ static int create_watch(const char *path, struct connman_inotify *inotify) } inotify->channel = g_io_channel_unix_new(fd); - if (inotify->channel == NULL) { + if (!inotify->channel) { connman_error("Creation of inotify channel failed"); inotify_rm_watch(fd, inotify->wd); inotify->wd = 0; @@ -149,7 +149,7 @@ static void remove_watch(struct connman_inotify *inotify) { int fd; - if (inotify->channel == NULL) + if (!inotify->channel) return; if (inotify->watch > 0) @@ -168,15 +168,15 @@ int connman_inotify_register(const char *path, inotify_event_cb callback) struct connman_inotify *inotify; int err; - if (callback == NULL) + if (!callback) return -EINVAL; inotify = g_hash_table_lookup(inotify_hash, path); - if (inotify != NULL) + if (inotify) goto update; inotify = g_try_new0(struct connman_inotify, 1); - if (inotify == NULL) + if (!inotify) return -ENOMEM; inotify->wd = -1; @@ -210,11 +210,11 @@ void connman_inotify_unregister(const char *path, inotify_event_cb callback) struct connman_inotify *inotify; inotify = g_hash_table_lookup(inotify_hash, path); - if (inotify == NULL) + if (!inotify) return; inotify->list = g_slist_remove(inotify->list, callback); - if (inotify->list != NULL) + if (inotify->list) return; g_hash_table_remove(inotify_hash, path); diff --git a/src/ipaddress.c b/src/ipaddress.c index f66bb674..57f9435d 100644 --- a/src/ipaddress.c +++ b/src/ipaddress.c @@ -2,7 +2,7 @@ * * Connection Manager * - * Copyright (C) 2007-2012 Intel Corporation. All rights reserved. + * Copyright (C) 2007-2013 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 @@ -38,7 +38,7 @@ struct connman_ipaddress *connman_ipaddress_alloc(int family) struct connman_ipaddress *ipaddress; ipaddress = g_try_new0(struct connman_ipaddress, 1); - if (ipaddress == NULL) + if (!ipaddress) return NULL; ipaddress->family = family; @@ -53,7 +53,7 @@ struct connman_ipaddress *connman_ipaddress_alloc(int family) void connman_ipaddress_free(struct connman_ipaddress *ipaddress) { - if (ipaddress == NULL) + if (!ipaddress) return; g_free(ipaddress->broadcast); @@ -69,7 +69,7 @@ unsigned char __connman_ipaddress_netmask_prefix_len(const char *netmask) in_addr_t mask; in_addr_t host; - if (netmask == NULL) + if (!netmask) return 32; mask = inet_network(netmask); @@ -86,19 +86,19 @@ unsigned char __connman_ipaddress_netmask_prefix_len(const char *netmask) return bits; } -static gboolean check_ipv6_address(const char *address) +static bool check_ipv6_address(const char *address) { unsigned char buf[sizeof(struct in6_addr)]; int err; - if (address == NULL) - return FALSE; + if (!address) + return false; err = inet_pton(AF_INET6, address, buf); if (err > 0) - return TRUE; + return true; - return FALSE; + return false; } int connman_ipaddress_set_ipv6(struct connman_ipaddress *ipaddress, @@ -106,10 +106,10 @@ int connman_ipaddress_set_ipv6(struct connman_ipaddress *ipaddress, unsigned char prefix_length, const char *gateway) { - if (ipaddress == NULL) + if (!ipaddress) return -EINVAL; - if (check_ipv6_address(address) == FALSE) + if (!check_ipv6_address(address)) return -EINVAL; DBG("prefix_len %d address %s gateway %s", @@ -131,7 +131,7 @@ int connman_ipaddress_set_ipv6(struct connman_ipaddress *ipaddress, int connman_ipaddress_set_ipv4(struct connman_ipaddress *ipaddress, const char *address, const char *netmask, const char *gateway) { - if (ipaddress == NULL) + if (!ipaddress) return -EINVAL; ipaddress->family = AF_INET; @@ -150,7 +150,7 @@ int connman_ipaddress_set_ipv4(struct connman_ipaddress *ipaddress, void connman_ipaddress_set_peer(struct connman_ipaddress *ipaddress, const char *peer) { - if (ipaddress == NULL) + if (!ipaddress) return; g_free(ipaddress->peer); @@ -159,7 +159,7 @@ void connman_ipaddress_set_peer(struct connman_ipaddress *ipaddress, void connman_ipaddress_clear(struct connman_ipaddress *ipaddress) { - if (ipaddress == NULL) + if (!ipaddress) return; ipaddress->prefixlen = 0; @@ -185,7 +185,7 @@ void connman_ipaddress_clear(struct connman_ipaddress *ipaddress) void connman_ipaddress_copy_address(struct connman_ipaddress *ipaddress, struct connman_ipaddress *source) { - if (ipaddress == NULL || source == NULL) + if (!ipaddress || !source) return; ipaddress->family = source->family; diff --git a/src/ipconfig.c b/src/ipconfig.c index 694cc614..b23df160 100644 --- a/src/ipconfig.c +++ b/src/ipconfig.c @@ -2,7 +2,7 @@ * * Connection Manager * - * Copyright (C) 2007-2012 Intel Corporation. All rights reserved. + * Copyright (C) 2007-2013 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 @@ -50,18 +50,18 @@ struct connman_ipconfig { const struct connman_ipconfig_ops *ops; void *ops_data; - connman_bool_t enabled; + bool enabled; enum connman_ipconfig_method method; struct connman_ipaddress *address; struct connman_ipaddress *system; int ipv6_privacy_config; char *last_dhcp_address; + char **last_dhcpv6_prefixes; }; struct connman_ipdevice { int index; - char *ifname; unsigned short type; unsigned int flags; char *address; @@ -84,17 +84,17 @@ struct connman_ipdevice { struct connman_ipconfig *config_ipv4; struct connman_ipconfig *config_ipv6; - gboolean ipv6_enabled; + bool ipv6_enabled; int ipv6_privacy; }; static GHashTable *ipdevice_hash = NULL; static GList *ipconfig_list = NULL; -static connman_bool_t is_ipv6_supported = FALSE; +static bool is_ipv6_supported = false; void __connman_ipconfig_clear_address(struct connman_ipconfig *ipconfig) { - if (ipconfig == NULL) + if (!ipconfig) return; connman_ipaddress_clear(ipconfig->address); @@ -175,27 +175,27 @@ static const char *scope2str(unsigned char scope) return ""; } -static gboolean get_ipv6_state(gchar *ifname) +static bool get_ipv6_state(gchar *ifname) { int disabled; gchar *path; FILE *f; - gboolean enabled = FALSE; + bool enabled = false; - if (ifname == NULL) + if (!ifname) path = g_strdup("/proc/sys/net/ipv6/conf/all/disable_ipv6"); else path = g_strdup_printf( "/proc/sys/net/ipv6/conf/%s/disable_ipv6", ifname); - if (path == NULL) + if (!path) return enabled; f = fopen(path, "r"); g_free(path); - if (f != NULL) { + if (f) { if (fscanf(f, "%d", &disabled) > 0) enabled = !disabled; fclose(f); @@ -204,28 +204,28 @@ static gboolean get_ipv6_state(gchar *ifname) return enabled; } -static void set_ipv6_state(gchar *ifname, gboolean enable) +static void set_ipv6_state(gchar *ifname, bool enable) { gchar *path; FILE *f; - if (ifname == NULL) + if (!ifname) path = g_strdup("/proc/sys/net/ipv6/conf/all/disable_ipv6"); else path = g_strdup_printf( "/proc/sys/net/ipv6/conf/%s/disable_ipv6", ifname); - if (path == NULL) + if (!path) return; f = fopen(path, "r+"); g_free(path); - if (f == NULL) + if (!f) return; - if (enable == FALSE) + if (!enable) fprintf(f, "1"); else fprintf(f, "0"); @@ -239,20 +239,20 @@ static int get_ipv6_privacy(gchar *ifname) FILE *f; int value; - if (ifname == NULL) + if (!ifname) return 0; path = g_strdup_printf("/proc/sys/net/ipv6/conf/%s/use_tempaddr", ifname); - if (path == NULL) + if (!path) return 0; f = fopen(path, "r"); g_free(path); - if (f == NULL) + if (!f) return 0; if (fscanf(f, "%d", &value) <= 0) @@ -271,13 +271,13 @@ static void set_ipv6_privacy(gchar *ifname, int value) gchar *path; FILE *f; - if (ifname == NULL) + if (!ifname) return; path = g_strdup_printf("/proc/sys/net/ipv6/conf/%s/use_tempaddr", ifname); - if (path == NULL) + if (!path) return; if (value < 0) @@ -287,21 +287,21 @@ static void set_ipv6_privacy(gchar *ifname, int value) g_free(path); - if (f == NULL) + if (!f) return; fprintf(f, "%d", value); fclose(f); } -static int get_rp_filter() +static int get_rp_filter(void) { FILE *f; int value = -EINVAL, tmp; f = fopen("/proc/sys/net/ipv4/conf/all/rp_filter", "r"); - if (f != NULL) { + if (f) { if (fscanf(f, "%d", &tmp) == 1) value = tmp; fclose(f); @@ -316,7 +316,7 @@ static void set_rp_filter(int value) f = fopen("/proc/sys/net/ipv4/conf/all/rp_filter", "r+"); - if (f == NULL) + if (!f) return; fprintf(f, "%d", value); @@ -348,27 +348,48 @@ void __connman_ipconfig_unset_rp_filter(int old_value) connman_info("rp_filter restored to %d", old_value); } -gboolean __connman_ipconfig_ipv6_privacy_enabled(struct connman_ipconfig *ipconfig) +bool __connman_ipconfig_ipv6_privacy_enabled(struct connman_ipconfig *ipconfig) { - if (ipconfig == NULL) - return FALSE; + if (!ipconfig) + return false; return ipconfig->ipv6_privacy_config == 0 ? FALSE : TRUE; } +bool __connman_ipconfig_ipv6_is_enabled(struct connman_ipconfig *ipconfig) +{ + struct connman_ipdevice *ipdevice; + char *ifname; + bool ret; + + if (!ipconfig) + return false; + + ipdevice = g_hash_table_lookup(ipdevice_hash, + GINT_TO_POINTER(ipconfig->index)); + if (!ipdevice) + return false; + + ifname = connman_inet_ifname(ipconfig->index); + ret = get_ipv6_state(ifname); + g_free(ifname); + + return ret; +} + static void free_ipdevice(gpointer data) { struct connman_ipdevice *ipdevice = data; + char *ifname = connman_inet_ifname(ipdevice->index); - connman_info("%s {remove} index %d", ipdevice->ifname, - ipdevice->index); + connman_info("%s {remove} index %d", ifname, ipdevice->index); - if (ipdevice->config_ipv4 != NULL) { + if (ipdevice->config_ipv4) { __connman_ipconfig_unref(ipdevice->config_ipv4); ipdevice->config_ipv4 = NULL; } - if (ipdevice->config_ipv6 != NULL) { + if (ipdevice->config_ipv6) { __connman_ipconfig_unref(ipdevice->config_ipv6); ipdevice->config_ipv6 = NULL; } @@ -380,10 +401,10 @@ static void free_ipdevice(gpointer data) g_free(ipdevice->address); - set_ipv6_state(ipdevice->ifname, ipdevice->ipv6_enabled); - set_ipv6_privacy(ipdevice->ifname, ipdevice->ipv6_privacy); + set_ipv6_state(ifname, ipdevice->ipv6_enabled); + set_ipv6_privacy(ifname, ipdevice->ipv6_privacy); - g_free(ipdevice->ifname); + g_free(ifname); g_free(ipdevice); } @@ -409,19 +430,19 @@ static void __connman_ipconfig_lower_down(struct connman_ipdevice *ipdevice) } static void update_stats(struct connman_ipdevice *ipdevice, - struct rtnl_link_stats *stats) + const char *ifname, struct rtnl_link_stats *stats) { struct connman_service *service; if (stats->rx_packets == 0 && stats->tx_packets == 0) return; - connman_info("%s {RX} %u packets %u bytes", ipdevice->ifname, + connman_info("%s {RX} %u packets %u bytes", ifname, stats->rx_packets, stats->rx_bytes); - connman_info("%s {TX} %u packets %u bytes", ipdevice->ifname, + connman_info("%s {TX} %u packets %u bytes", ifname, stats->tx_packets, stats->tx_bytes); - if (ipdevice->config_ipv4 == NULL && ipdevice->config_ipv6 == NULL) + if (!ipdevice->config_ipv4 && !ipdevice->config_ipv6) return; if (ipdevice->config_ipv4) @@ -431,7 +452,7 @@ static void update_stats(struct connman_ipdevice *ipdevice, else return; - if (service == NULL) + if (!service) return; ipdevice->rx_packets = stats->rx_packets; @@ -456,78 +477,69 @@ void __connman_ipconfig_newlink(int index, unsigned short type, struct rtnl_link_stats *stats) { struct connman_ipdevice *ipdevice; - GList *list; + GList *list, *ipconfig_copy; GString *str; - gboolean up = FALSE, down = FALSE; - gboolean lower_up = FALSE, lower_down = FALSE; + bool up = false, down = false; + bool lower_up = false, lower_down = false; + char *ifname; DBG("index %d", index); if (type == ARPHRD_LOOPBACK) return; - ipdevice = g_hash_table_lookup(ipdevice_hash, GINT_TO_POINTER(index)); - if (ipdevice != NULL) { - char *ifname = connman_inet_ifname(index); - if (g_strcmp0(ipdevice->ifname, ifname) != 0) { - DBG("interface name changed %s -> %s", - ipdevice->ifname, ifname); - - g_free(ipdevice->ifname); - ipdevice->ifname = ifname; - } else - g_free(ifname); + ifname = connman_inet_ifname(index); + ipdevice = g_hash_table_lookup(ipdevice_hash, GINT_TO_POINTER(index)); + if (ipdevice) goto update; - } ipdevice = g_try_new0(struct connman_ipdevice, 1); - if (ipdevice == NULL) - return; + if (!ipdevice) + goto out; ipdevice->index = index; - ipdevice->ifname = connman_inet_ifname(index); ipdevice->type = type; - ipdevice->ipv6_enabled = get_ipv6_state(ipdevice->ifname); - ipdevice->ipv6_privacy = get_ipv6_privacy(ipdevice->ifname); + ipdevice->ipv6_enabled = get_ipv6_state(ifname); + ipdevice->ipv6_privacy = get_ipv6_privacy(ifname); ipdevice->address = g_strdup(address); g_hash_table_insert(ipdevice_hash, GINT_TO_POINTER(index), ipdevice); - connman_info("%s {create} index %d type %d <%s>", ipdevice->ifname, + connman_info("%s {create} index %d type %d <%s>", ifname, index, type, type2str(type)); update: ipdevice->mtu = mtu; - update_stats(ipdevice, stats); + update_stats(ipdevice, ifname, stats); if (flags == ipdevice->flags) - return; + goto out; if ((ipdevice->flags & IFF_UP) != (flags & IFF_UP)) { if (flags & IFF_UP) - up = TRUE; + up = true; else - down = TRUE; + down = true; } if ((ipdevice->flags & (IFF_RUNNING | IFF_LOWER_UP)) != (flags & (IFF_RUNNING | IFF_LOWER_UP))) { if ((flags & (IFF_RUNNING | IFF_LOWER_UP)) == (IFF_RUNNING | IFF_LOWER_UP)) - lower_up = TRUE; + lower_up = true; else if ((flags & (IFF_RUNNING | IFF_LOWER_UP)) == 0) - lower_down = TRUE; + lower_down = true; } ipdevice->flags = flags; str = g_string_new(NULL); - if (str == NULL) - return; + if (!str) + goto out; if (flags & IFF_UP) g_string_append(str, "UP"); @@ -540,50 +552,59 @@ update: if (flags & IFF_LOWER_UP) g_string_append(str, ",LOWER_UP"); - connman_info("%s {update} flags %u <%s>", ipdevice->ifname, - flags, str->str); + connman_info("%s {update} flags %u <%s>", ifname, flags, str->str); g_string_free(str, TRUE); - for (list = g_list_first(ipconfig_list); list; + ipconfig_copy = g_list_copy(ipconfig_list); + + for (list = g_list_first(ipconfig_copy); list; list = g_list_next(list)) { struct connman_ipconfig *ipconfig = list->data; if (index != ipconfig->index) continue; - if (ipconfig->ops == NULL) + if (!ipconfig->ops) continue; - if (up == TRUE && ipconfig->ops->up) - ipconfig->ops->up(ipconfig); - if (lower_up == TRUE && ipconfig->ops->lower_up) - ipconfig->ops->lower_up(ipconfig); + if (up && ipconfig->ops->up) + ipconfig->ops->up(ipconfig, ifname); + if (lower_up && ipconfig->ops->lower_up) + ipconfig->ops->lower_up(ipconfig, ifname); - if (lower_down == TRUE && ipconfig->ops->lower_down) - ipconfig->ops->lower_down(ipconfig); - if (down == TRUE && ipconfig->ops->down) - ipconfig->ops->down(ipconfig); + if (lower_down && ipconfig->ops->lower_down) + ipconfig->ops->lower_down(ipconfig, ifname); + if (down && ipconfig->ops->down) + ipconfig->ops->down(ipconfig, ifname); } + g_list_free(ipconfig_copy); + if (lower_up) __connman_ipconfig_lower_up(ipdevice); if (lower_down) __connman_ipconfig_lower_down(ipdevice); + +out: + g_free(ifname); } void __connman_ipconfig_dellink(int index, struct rtnl_link_stats *stats) { struct connman_ipdevice *ipdevice; GList *list; + char *ifname; DBG("index %d", index); ipdevice = g_hash_table_lookup(ipdevice_hash, GINT_TO_POINTER(index)); - if (ipdevice == NULL) + if (!ipdevice) return; - update_stats(ipdevice, stats); + ifname = connman_inet_ifname(index); + + update_stats(ipdevice, ifname, stats); for (list = g_list_first(ipconfig_list); list; list = g_list_next(list)) { @@ -594,15 +615,17 @@ void __connman_ipconfig_dellink(int index, struct rtnl_link_stats *stats) ipconfig->index = -1; - if (ipconfig->ops == NULL) + if (!ipconfig->ops) continue; if (ipconfig->ops->lower_down) - ipconfig->ops->lower_down(ipconfig); + ipconfig->ops->lower_down(ipconfig, ifname); if (ipconfig->ops->down) - ipconfig->ops->down(ipconfig); + ipconfig->ops->down(ipconfig, ifname); } + g_free(ifname); + __connman_ipconfig_lower_down(ipdevice); g_hash_table_remove(ipdevice_hash, GINT_TO_POINTER(index)); @@ -626,15 +649,16 @@ void __connman_ipconfig_newaddr(int index, int family, const char *label, struct connman_ipaddress *ipaddress; enum connman_ipconfig_type type; GList *list; + char *ifname; DBG("index %d", index); ipdevice = g_hash_table_lookup(ipdevice_hash, GINT_TO_POINTER(index)); - if (ipdevice == NULL) + if (!ipdevice) return; ipaddress = connman_ipaddress_alloc(family); - if (ipaddress == NULL) + if (!ipaddress) return; ipaddress->prefixlen = prefixlen; @@ -656,21 +680,22 @@ void __connman_ipconfig_newaddr(int index, int family, const char *label, ipdevice->address_list = g_slist_prepend(ipdevice->address_list, ipaddress); + ifname = connman_inet_ifname(index); connman_info("%s {add} address %s/%u label %s family %d", - ipdevice->ifname, address, prefixlen, label, family); + ifname, address, prefixlen, label, family); if (type == CONNMAN_IPCONFIG_TYPE_IPV4) __connman_ippool_newaddr(index, address, prefixlen); - if (ipdevice->config_ipv4 != NULL && family == AF_INET) + if (ipdevice->config_ipv4 && family == AF_INET) connman_ipaddress_copy_address(ipdevice->config_ipv4->system, ipaddress); - else if (ipdevice->config_ipv6 != NULL && family == AF_INET6) + else if (ipdevice->config_ipv6 && family == AF_INET6) connman_ipaddress_copy_address(ipdevice->config_ipv6->system, ipaddress); else - return; + goto out; if ((ipdevice->flags & (IFF_RUNNING | IFF_LOWER_UP)) != (IFF_RUNNING | IFF_LOWER_UP)) return; @@ -685,12 +710,15 @@ void __connman_ipconfig_newaddr(int index, int family, const char *label, if (type != ipconfig->type) continue; - if (ipconfig->ops == NULL) + if (!ipconfig->ops) continue; if (ipconfig->ops->ip_bound) - ipconfig->ops->ip_bound(ipconfig); + ipconfig->ops->ip_bound(ipconfig, ifname); } + +out: + g_free(ifname); } void __connman_ipconfig_deladdr(int index, int family, const char *label, @@ -700,15 +728,16 @@ void __connman_ipconfig_deladdr(int index, int family, const char *label, struct connman_ipaddress *ipaddress; enum connman_ipconfig_type type; GList *list; + char *ifname; DBG("index %d", index); ipdevice = g_hash_table_lookup(ipdevice_hash, GINT_TO_POINTER(index)); - if (ipdevice == NULL) + if (!ipdevice) return; ipaddress = find_ipaddress(ipdevice, prefixlen, address); - if (ipaddress == NULL) + if (!ipaddress) return; if (family == AF_INET) @@ -727,14 +756,15 @@ void __connman_ipconfig_deladdr(int index, int family, const char *label, connman_ipaddress_clear(ipaddress); g_free(ipaddress); - connman_info("%s {del} address %s/%u label %s", ipdevice->ifname, + ifname = connman_inet_ifname(index); + connman_info("%s {del} address %s/%u label %s", ifname, address, prefixlen, label); if ((ipdevice->flags & (IFF_RUNNING | IFF_LOWER_UP)) != (IFF_RUNNING | IFF_LOWER_UP)) - return; + goto out; if (g_slist_length(ipdevice->address_list) > 0) - return; + goto out; for (list = g_list_first(ipconfig_list); list; list = g_list_next(list)) { @@ -746,25 +776,31 @@ void __connman_ipconfig_deladdr(int index, int family, const char *label, if (type != ipconfig->type) continue; - if (ipconfig->ops == NULL) + if (!ipconfig->ops) continue; if (ipconfig->ops->ip_release) - ipconfig->ops->ip_release(ipconfig); + ipconfig->ops->ip_release(ipconfig, ifname); } + +out: + g_free(ifname); } void __connman_ipconfig_newroute(int index, int family, unsigned char scope, const char *dst, const char *gateway) { struct connman_ipdevice *ipdevice; + char *ifname; DBG("index %d", index); ipdevice = g_hash_table_lookup(ipdevice_hash, GINT_TO_POINTER(index)); - if (ipdevice == NULL) + if (!ipdevice) return; + ifname = connman_inet_ifname(index); + if (scope == 0 && (g_strcmp0(dst, "0.0.0.0") == 0 || g_strcmp0(dst, "::") == 0)) { GList *config_list; @@ -775,8 +811,8 @@ void __connman_ipconfig_newroute(int index, int family, unsigned char scope, g_free(ipdevice->ipv6_gateway); ipdevice->ipv6_gateway = g_strdup(gateway); - if (ipdevice->config_ipv6 != NULL && - ipdevice->config_ipv6->system != NULL) { + if (ipdevice->config_ipv6 && + ipdevice->config_ipv6->system) { g_free(ipdevice->config_ipv6->system->gateway); ipdevice->config_ipv6->system->gateway = g_strdup(gateway); @@ -786,14 +822,14 @@ void __connman_ipconfig_newroute(int index, int family, unsigned char scope, g_free(ipdevice->ipv4_gateway); ipdevice->ipv4_gateway = g_strdup(gateway); - if (ipdevice->config_ipv4 != NULL && - ipdevice->config_ipv4->system != NULL) { + if (ipdevice->config_ipv4 && + ipdevice->config_ipv4->system) { g_free(ipdevice->config_ipv4->system->gateway); ipdevice->config_ipv4->system->gateway = g_strdup(gateway); } } else - return; + goto out; for (config_list = g_list_first(ipconfig_list); config_list; config_list = g_list_next(config_list)) { @@ -805,30 +841,35 @@ void __connman_ipconfig_newroute(int index, int family, unsigned char scope, if (type != ipconfig->type) continue; - if (ipconfig->ops == NULL) + if (!ipconfig->ops) continue; if (ipconfig->ops->route_set) - ipconfig->ops->route_set(ipconfig); + ipconfig->ops->route_set(ipconfig, ifname); } } connman_info("%s {add} route %s gw %s scope %u <%s>", - ipdevice->ifname, dst, gateway, - scope, scope2str(scope)); + ifname, dst, gateway, scope, scope2str(scope)); + +out: + g_free(ifname); } void __connman_ipconfig_delroute(int index, int family, unsigned char scope, const char *dst, const char *gateway) { struct connman_ipdevice *ipdevice; + char *ifname; DBG("index %d", index); ipdevice = g_hash_table_lookup(ipdevice_hash, GINT_TO_POINTER(index)); - if (ipdevice == NULL) + if (!ipdevice) return; + ifname = connman_inet_ifname(index); + if (scope == 0 && (g_strcmp0(dst, "0.0.0.0") == 0 || g_strcmp0(dst, "::") == 0)) { GList *config_list; @@ -839,8 +880,8 @@ void __connman_ipconfig_delroute(int index, int family, unsigned char scope, g_free(ipdevice->ipv6_gateway); ipdevice->ipv6_gateway = NULL; - if (ipdevice->config_ipv6 != NULL && - ipdevice->config_ipv6->system != NULL) { + if (ipdevice->config_ipv6 && + ipdevice->config_ipv6->system) { g_free(ipdevice->config_ipv6->system->gateway); ipdevice->config_ipv6->system->gateway = NULL; } @@ -849,13 +890,13 @@ void __connman_ipconfig_delroute(int index, int family, unsigned char scope, g_free(ipdevice->ipv4_gateway); ipdevice->ipv4_gateway = NULL; - if (ipdevice->config_ipv4 != NULL && - ipdevice->config_ipv4->system != NULL) { + if (ipdevice->config_ipv4 && + ipdevice->config_ipv4->system) { g_free(ipdevice->config_ipv4->system->gateway); ipdevice->config_ipv4->system->gateway = NULL; } } else - return; + goto out; for (config_list = g_list_first(ipconfig_list); config_list; config_list = g_list_next(config_list)) { @@ -867,17 +908,19 @@ void __connman_ipconfig_delroute(int index, int family, unsigned char scope, if (type != ipconfig->type) continue; - if (ipconfig->ops == NULL) + if (!ipconfig->ops) continue; if (ipconfig->ops->route_unset) - ipconfig->ops->route_unset(ipconfig); + ipconfig->ops->route_unset(ipconfig, ifname); } } connman_info("%s {del} route %s gw %s scope %u <%s>", - ipdevice->ifname, dst, gateway, - scope, scope2str(scope)); + ifname, dst, gateway, scope, scope2str(scope)); + +out: + g_free(ifname); } void __connman_ipconfig_foreach(void (*function) (int index, void *user_data), @@ -886,7 +929,7 @@ void __connman_ipconfig_foreach(void (*function) (int index, void *user_data), GList *list, *keys; keys = g_hash_table_get_keys(ipdevice_hash); - if (keys == NULL) + if (!keys) return; for (list = g_list_first(keys); list; list = g_list_next(list)) { @@ -909,7 +952,7 @@ unsigned short __connman_ipconfig_get_type_from_index(int index) struct connman_ipdevice *ipdevice; ipdevice = g_hash_table_lookup(ipdevice_hash, GINT_TO_POINTER(index)); - if (ipdevice == NULL) + if (!ipdevice) return ARPHRD_VOID; return ipdevice->type; @@ -920,7 +963,7 @@ unsigned int __connman_ipconfig_get_flags_from_index(int index) struct connman_ipdevice *ipdevice; ipdevice = g_hash_table_lookup(ipdevice_hash, GINT_TO_POINTER(index)); - if (ipdevice == NULL) + if (!ipdevice) return 0; return ipdevice->flags; @@ -932,24 +975,24 @@ const char *__connman_ipconfig_get_gateway_from_index(int index, struct connman_ipdevice *ipdevice; ipdevice = g_hash_table_lookup(ipdevice_hash, GINT_TO_POINTER(index)); - if (ipdevice == NULL) + if (!ipdevice) return NULL; if (type != CONNMAN_IPCONFIG_TYPE_IPV6) { - if (ipdevice->ipv4_gateway != NULL) + if (ipdevice->ipv4_gateway) return ipdevice->ipv4_gateway; - if (ipdevice->config_ipv4 != NULL && - ipdevice->config_ipv4->address != NULL) + if (ipdevice->config_ipv4 && + ipdevice->config_ipv4->address) return ipdevice->config_ipv4->address->gateway; } if (type != CONNMAN_IPCONFIG_TYPE_IPV4) { - if (ipdevice->ipv6_gateway != NULL) + if (ipdevice->ipv6_gateway) return ipdevice->ipv6_gateway; - if (ipdevice->config_ipv6 != NULL && - ipdevice->config_ipv6->address != NULL) + if (ipdevice->config_ipv6 && + ipdevice->config_ipv6->address) return ipdevice->config_ipv6->address->gateway; } @@ -963,15 +1006,16 @@ void __connman_ipconfig_set_index(struct connman_ipconfig *ipconfig, int index) const char *__connman_ipconfig_get_local(struct connman_ipconfig *ipconfig) { - if (ipconfig->address == NULL) + if (!ipconfig->address) return NULL; return ipconfig->address->local; } -void __connman_ipconfig_set_local(struct connman_ipconfig *ipconfig, const char *address) +void __connman_ipconfig_set_local(struct connman_ipconfig *ipconfig, + const char *address) { - if (ipconfig->address == NULL) + if (!ipconfig->address) return; g_free(ipconfig->address->local); @@ -980,15 +1024,16 @@ void __connman_ipconfig_set_local(struct connman_ipconfig *ipconfig, const char const char *__connman_ipconfig_get_peer(struct connman_ipconfig *ipconfig) { - if (ipconfig->address == NULL) + if (!ipconfig->address) return NULL; return ipconfig->address->peer; } -void __connman_ipconfig_set_peer(struct connman_ipconfig *ipconfig, const char *address) +void __connman_ipconfig_set_peer(struct connman_ipconfig *ipconfig, + const char *address) { - if (ipconfig->address == NULL) + if (!ipconfig->address) return; g_free(ipconfig->address->peer); @@ -997,15 +1042,16 @@ void __connman_ipconfig_set_peer(struct connman_ipconfig *ipconfig, const char * const char *__connman_ipconfig_get_broadcast(struct connman_ipconfig *ipconfig) { - if (ipconfig->address == NULL) + if (!ipconfig->address) return NULL; return ipconfig->address->broadcast; } -void __connman_ipconfig_set_broadcast(struct connman_ipconfig *ipconfig, const char *broadcast) +void __connman_ipconfig_set_broadcast(struct connman_ipconfig *ipconfig, + const char *broadcast) { - if (ipconfig->address == NULL) + if (!ipconfig->address) return; g_free(ipconfig->address->broadcast); @@ -1014,17 +1060,18 @@ void __connman_ipconfig_set_broadcast(struct connman_ipconfig *ipconfig, const c const char *__connman_ipconfig_get_gateway(struct connman_ipconfig *ipconfig) { - if (ipconfig->address == NULL) + if (!ipconfig->address) return NULL; return ipconfig->address->gateway; } -void __connman_ipconfig_set_gateway(struct connman_ipconfig *ipconfig, const char *gateway) +void __connman_ipconfig_set_gateway(struct connman_ipconfig *ipconfig, + const char *gateway) { DBG(""); - if (ipconfig->address == NULL) + if (!ipconfig->address) return; g_free(ipconfig->address->gateway); ipconfig->address->gateway = g_strdup(gateway); @@ -1036,11 +1083,11 @@ int __connman_ipconfig_gateway_add(struct connman_ipconfig *ipconfig) DBG(""); - if (ipconfig->address == NULL) + if (!ipconfig->address) return -EINVAL; service = __connman_service_lookup_from_index(ipconfig->index); - if (service == NULL) + if (!service) return -EINVAL; __connman_connection_gateway_remove(service, ipconfig->type); @@ -1065,21 +1112,22 @@ void __connman_ipconfig_gateway_remove(struct connman_ipconfig *ipconfig) DBG(""); service = __connman_service_lookup_from_index(ipconfig->index); - if (service != NULL) + if (service) __connman_connection_gateway_remove(service, ipconfig->type); } unsigned char __connman_ipconfig_get_prefixlen(struct connman_ipconfig *ipconfig) { - if (ipconfig->address == NULL) + if (!ipconfig->address) return 0; return ipconfig->address->prefixlen; } -void __connman_ipconfig_set_prefixlen(struct connman_ipconfig *ipconfig, unsigned char prefixlen) +void __connman_ipconfig_set_prefixlen(struct connman_ipconfig *ipconfig, + unsigned char prefixlen) { - if (ipconfig->address == NULL) + if (!ipconfig->address) return; ipconfig->address->prefixlen = prefixlen; @@ -1093,26 +1141,26 @@ static struct connman_ipconfig *create_ipv6config(int index) DBG("index %d", index); ipv6config = g_try_new0(struct connman_ipconfig, 1); - if (ipv6config == NULL) + if (!ipv6config) return NULL; ipv6config->refcount = 1; ipv6config->index = index; - ipv6config->enabled = FALSE; + ipv6config->enabled = false; ipv6config->type = CONNMAN_IPCONFIG_TYPE_IPV6; - if (is_ipv6_supported == FALSE) + if (!is_ipv6_supported) ipv6config->method = CONNMAN_IPCONFIG_METHOD_OFF; else ipv6config->method = CONNMAN_IPCONFIG_METHOD_AUTO; ipdevice = g_hash_table_lookup(ipdevice_hash, GINT_TO_POINTER(index)); - if (ipdevice != NULL) + if (ipdevice) ipv6config->ipv6_privacy_config = ipdevice->ipv6_privacy; ipv6config->address = connman_ipaddress_alloc(AF_INET6); - if (ipv6config->address == NULL) { + if (!ipv6config->address) { g_free(ipv6config); return NULL; } @@ -1143,17 +1191,17 @@ struct connman_ipconfig *__connman_ipconfig_create(int index, DBG("index %d", index); ipconfig = g_try_new0(struct connman_ipconfig, 1); - if (ipconfig == NULL) + if (!ipconfig) return NULL; ipconfig->refcount = 1; ipconfig->index = index; - ipconfig->enabled = FALSE; + ipconfig->enabled = false; ipconfig->type = CONNMAN_IPCONFIG_TYPE_IPV4; ipconfig->address = connman_ipaddress_alloc(AF_INET); - if (ipconfig->address == NULL) { + if (!ipconfig->address) { g_free(ipconfig); return NULL; } @@ -1193,7 +1241,7 @@ __connman_ipconfig_ref_debug(struct connman_ipconfig *ipconfig, void __connman_ipconfig_unref_debug(struct connman_ipconfig *ipconfig, const char *file, int line, const char *caller) { - if (ipconfig == NULL) + if (!ipconfig) return; DBG("%p ref %d by %s:%d:%s()", ipconfig, ipconfig->refcount - 1, @@ -1207,7 +1255,7 @@ void __connman_ipconfig_unref_debug(struct connman_ipconfig *ipconfig, __connman_ipconfig_set_ops(ipconfig, NULL); - if (ipconfig->origin != NULL && ipconfig->origin != ipconfig) { + if (ipconfig->origin && ipconfig->origin != ipconfig) { __connman_ipconfig_unref(ipconfig->origin); ipconfig->origin = NULL; } @@ -1215,6 +1263,7 @@ void __connman_ipconfig_unref_debug(struct connman_ipconfig *ipconfig, connman_ipaddress_free(ipconfig->system); connman_ipaddress_free(ipconfig->address); g_free(ipconfig->last_dhcp_address); + g_strfreev(ipconfig->last_dhcpv6_prefixes); g_free(ipconfig); } @@ -1226,7 +1275,7 @@ void __connman_ipconfig_unref_debug(struct connman_ipconfig *ipconfig, */ void *__connman_ipconfig_get_data(struct connman_ipconfig *ipconfig) { - if (ipconfig == NULL) + if (!ipconfig) return NULL; return ipconfig->ops_data; @@ -1252,40 +1301,16 @@ void __connman_ipconfig_set_data(struct connman_ipconfig *ipconfig, void *data) */ int __connman_ipconfig_get_index(struct connman_ipconfig *ipconfig) { - if (ipconfig == NULL) + if (!ipconfig) return -1; - if (ipconfig->origin != NULL) + if (ipconfig->origin) return ipconfig->origin->index; return ipconfig->index; } /** - * connman_ipconfig_get_ifname: - * @ipconfig: ipconfig structure - * - * Get interface name - */ -const char *__connman_ipconfig_get_ifname(struct connman_ipconfig *ipconfig) -{ - struct connman_ipdevice *ipdevice; - - if (ipconfig == NULL) - return NULL; - - if (ipconfig->index < 0) - return NULL; - - ipdevice = g_hash_table_lookup(ipdevice_hash, - GINT_TO_POINTER(ipconfig->index)); - if (ipdevice == NULL) - return NULL; - - return ipdevice->ifname; -} - -/** * connman_ipconfig_set_ops: * @ipconfig: ipconfig structure * @ops: operation callbacks @@ -1313,9 +1338,10 @@ int __connman_ipconfig_set_method(struct connman_ipconfig *ipconfig, return 0; } -enum connman_ipconfig_method __connman_ipconfig_get_method(struct connman_ipconfig *ipconfig) +enum connman_ipconfig_method __connman_ipconfig_get_method( + struct connman_ipconfig *ipconfig) { - if (ipconfig == NULL) + if (!ipconfig) return CONNMAN_IPCONFIG_METHOD_UNKNOWN; return ipconfig->method; @@ -1350,7 +1376,7 @@ int __connman_ipconfig_address_remove(struct connman_ipconfig *ipconfig) DBG(""); - if (ipconfig == NULL) + if (!ipconfig) return 0; DBG("method %d", ipconfig->method); @@ -1378,7 +1404,7 @@ int __connman_ipconfig_address_unset(struct connman_ipconfig *ipconfig) DBG(""); - if (ipconfig == NULL) + if (!ipconfig) return 0; DBG("method %d", ipconfig->method); @@ -1415,12 +1441,12 @@ int __connman_ipconfig_set_proxy_autoconfig(struct connman_ipconfig *ipconfig, DBG("ipconfig %p", ipconfig); - if (ipconfig == NULL || ipconfig->index < 0) + if (!ipconfig || ipconfig->index < 0) return -ENODEV; ipdevice = g_hash_table_lookup(ipdevice_hash, GINT_TO_POINTER(ipconfig->index)); - if (ipdevice == NULL) + if (!ipdevice) return -ENXIO; g_free(ipdevice->pac); @@ -1435,12 +1461,12 @@ const char *__connman_ipconfig_get_proxy_autoconfig(struct connman_ipconfig *ipc DBG("ipconfig %p", ipconfig); - if (ipconfig == NULL || ipconfig->index < 0) + if (!ipconfig || ipconfig->index < 0) return NULL; ipdevice = g_hash_table_lookup(ipdevice_hash, GINT_TO_POINTER(ipconfig->index)); - if (ipdevice == NULL) + if (!ipdevice) return NULL; return ipdevice->pac; @@ -1449,7 +1475,7 @@ const char *__connman_ipconfig_get_proxy_autoconfig(struct connman_ipconfig *ipc void __connman_ipconfig_set_dhcp_address(struct connman_ipconfig *ipconfig, const char *address) { - if (ipconfig == NULL) + if (!ipconfig) return; g_free(ipconfig->last_dhcp_address); @@ -1458,47 +1484,74 @@ void __connman_ipconfig_set_dhcp_address(struct connman_ipconfig *ipconfig, char *__connman_ipconfig_get_dhcp_address(struct connman_ipconfig *ipconfig) { - if (ipconfig == NULL) + if (!ipconfig) return NULL; return ipconfig->last_dhcp_address; } +void __connman_ipconfig_set_dhcpv6_prefixes(struct connman_ipconfig *ipconfig, + char **prefixes) +{ + if (!ipconfig) + return; + + g_strfreev(ipconfig->last_dhcpv6_prefixes); + ipconfig->last_dhcpv6_prefixes = prefixes; +} + +char **__connman_ipconfig_get_dhcpv6_prefixes(struct connman_ipconfig *ipconfig) +{ + if (!ipconfig) + return NULL; + + return ipconfig->last_dhcpv6_prefixes; +} + static void disable_ipv6(struct connman_ipconfig *ipconfig) { struct connman_ipdevice *ipdevice; + char *ifname; DBG(""); ipdevice = g_hash_table_lookup(ipdevice_hash, GINT_TO_POINTER(ipconfig->index)); - if (ipdevice == NULL) + if (!ipdevice) return; - set_ipv6_state(ipdevice->ifname, FALSE); + ifname = connman_inet_ifname(ipconfig->index); + + set_ipv6_state(ifname, false); + + g_free(ifname); } static void enable_ipv6(struct connman_ipconfig *ipconfig) { struct connman_ipdevice *ipdevice; + char *ifname; DBG(""); ipdevice = g_hash_table_lookup(ipdevice_hash, GINT_TO_POINTER(ipconfig->index)); - if (ipdevice == NULL) + if (!ipdevice) return; + ifname = connman_inet_ifname(ipconfig->index); + if (ipconfig->method == CONNMAN_IPCONFIG_METHOD_AUTO) - set_ipv6_privacy(ipdevice->ifname, - ipconfig->ipv6_privacy_config); + set_ipv6_privacy(ifname, ipconfig->ipv6_privacy_config); + + set_ipv6_state(ifname, true); - set_ipv6_state(ipdevice->ifname, TRUE); + g_free(ifname); } void __connman_ipconfig_enable_ipv6(struct connman_ipconfig *ipconfig) { - if (ipconfig == NULL || ipconfig->type != CONNMAN_IPCONFIG_TYPE_IPV6) + if (!ipconfig || ipconfig->type != CONNMAN_IPCONFIG_TYPE_IPV6) return; enable_ipv6(ipconfig); @@ -1506,21 +1559,21 @@ void __connman_ipconfig_enable_ipv6(struct connman_ipconfig *ipconfig) void __connman_ipconfig_disable_ipv6(struct connman_ipconfig *ipconfig) { - if (ipconfig == NULL || ipconfig->type != CONNMAN_IPCONFIG_TYPE_IPV6) + if (!ipconfig || ipconfig->type != CONNMAN_IPCONFIG_TYPE_IPV6) return; disable_ipv6(ipconfig); } -connman_bool_t __connman_ipconfig_is_usable(struct connman_ipconfig *ipconfig) +bool __connman_ipconfig_is_usable(struct connman_ipconfig *ipconfig) { - if (ipconfig == NULL) - return FALSE; + if (!ipconfig) + return false; switch (ipconfig->method) { case CONNMAN_IPCONFIG_METHOD_UNKNOWN: case CONNMAN_IPCONFIG_METHOD_OFF: - return FALSE; + return false; case CONNMAN_IPCONFIG_METHOD_AUTO: case CONNMAN_IPCONFIG_METHOD_FIXED: case CONNMAN_IPCONFIG_METHOD_DHCP: @@ -1528,24 +1581,25 @@ connman_bool_t __connman_ipconfig_is_usable(struct connman_ipconfig *ipconfig) break; } - return TRUE; + return true; } int __connman_ipconfig_enable(struct connman_ipconfig *ipconfig) { struct connman_ipdevice *ipdevice; - gboolean up = FALSE, down = FALSE; - gboolean lower_up = FALSE, lower_down = FALSE; + bool up = false, down = false; + bool lower_up = false, lower_down = false; enum connman_ipconfig_type type; + char *ifname; DBG("ipconfig %p", ipconfig); - if (ipconfig == NULL || ipconfig->index < 0) + if (!ipconfig || ipconfig->index < 0) return -ENODEV; ipdevice = g_hash_table_lookup(ipdevice_hash, GINT_TO_POINTER(ipconfig->index)); - if (ipdevice == NULL) + if (!ipdevice) return -ENXIO; if (ipconfig->type == CONNMAN_IPCONFIG_TYPE_IPV4) { @@ -1559,10 +1613,10 @@ int __connman_ipconfig_enable(struct connman_ipconfig *ipconfig) } else return -EINVAL; - ipconfig->enabled = TRUE; + ipconfig->enabled = true; if (type == CONNMAN_IPCONFIG_TYPE_IPV4 && - ipdevice->config_ipv4 != NULL) { + ipdevice->config_ipv4) { ipconfig_list = g_list_remove(ipconfig_list, ipdevice->config_ipv4); @@ -1572,7 +1626,7 @@ int __connman_ipconfig_enable(struct connman_ipconfig *ipconfig) } if (type == CONNMAN_IPCONFIG_TYPE_IPV6 && - ipdevice->config_ipv6 != NULL) { + ipdevice->config_ipv6) { ipconfig_list = g_list_remove(ipconfig_list, ipdevice->config_ipv6); @@ -1591,25 +1645,29 @@ int __connman_ipconfig_enable(struct connman_ipconfig *ipconfig) ipconfig_list = g_list_append(ipconfig_list, ipconfig); if (ipdevice->flags & IFF_UP) - up = TRUE; + up = true; else - down = TRUE; + down = true; if ((ipdevice->flags & (IFF_RUNNING | IFF_LOWER_UP)) == (IFF_RUNNING | IFF_LOWER_UP)) - lower_up = TRUE; + lower_up = true; else if ((ipdevice->flags & (IFF_RUNNING | IFF_LOWER_UP)) == 0) - lower_down = TRUE; + lower_down = true; - if (up == TRUE && ipconfig->ops->up) - ipconfig->ops->up(ipconfig); - if (lower_up == TRUE && ipconfig->ops->lower_up) - ipconfig->ops->lower_up(ipconfig); + ifname = connman_inet_ifname(ipconfig->index); - if (lower_down == TRUE && ipconfig->ops->lower_down) - ipconfig->ops->lower_down(ipconfig); - if (down == TRUE && ipconfig->ops->down) - ipconfig->ops->down(ipconfig); + if (up && ipconfig->ops->up) + ipconfig->ops->up(ipconfig, ifname); + if (lower_up && ipconfig->ops->lower_up) + ipconfig->ops->lower_up(ipconfig, ifname); + + if (lower_down && ipconfig->ops->lower_down) + ipconfig->ops->lower_down(ipconfig, ifname); + if (down && ipconfig->ops->down) + ipconfig->ops->down(ipconfig, ifname); + + g_free(ifname); return 0; } @@ -1620,18 +1678,18 @@ int __connman_ipconfig_disable(struct connman_ipconfig *ipconfig) DBG("ipconfig %p", ipconfig); - if (ipconfig == NULL || ipconfig->index < 0) + if (!ipconfig || ipconfig->index < 0) return -ENODEV; ipdevice = g_hash_table_lookup(ipdevice_hash, GINT_TO_POINTER(ipconfig->index)); - if (ipdevice == NULL) + if (!ipdevice) return -ENXIO; - if (ipdevice->config_ipv4 == NULL && ipdevice->config_ipv6 == NULL) + if (!ipdevice->config_ipv4 && !ipdevice->config_ipv6) return -EINVAL; - ipconfig->enabled = FALSE; + ipconfig->enabled = false; if (ipdevice->config_ipv4 == ipconfig) { ipconfig_list = g_list_remove(ipconfig_list, ipconfig); @@ -1700,10 +1758,8 @@ static const char *privacy2string(int privacy) return "disabled"; else if (privacy == 1) return "enabled"; - else if (privacy > 1) + else return "prefered"; - - return "disabled"; } static int string2privacy(const char *privacy) @@ -1712,6 +1768,8 @@ static int string2privacy(const char *privacy) return 0; else if (g_strcmp0(privacy, "enabled") == 0) return 1; + else if (g_strcmp0(privacy, "preferred") == 0) + return 2; else if (g_strcmp0(privacy, "prefered") == 0) return 2; else @@ -1723,7 +1781,7 @@ int __connman_ipconfig_ipv6_set_privacy(struct connman_ipconfig *ipconfig, { int privacy; - if (ipconfig == NULL) + if (!ipconfig) return -EINVAL; DBG("ipconfig %p privacy %s", ipconfig, value); @@ -1749,7 +1807,7 @@ void __connman_ipconfig_append_ipv4(struct connman_ipconfig *ipconfig, return; str = __connman_ipconfig_method2string(ipconfig->method); - if (str == NULL) + if (!str) return; connman_dbus_dict_append_basic(iter, "Method", DBUS_TYPE_STRING, &str); @@ -1770,10 +1828,10 @@ void __connman_ipconfig_append_ipv4(struct connman_ipconfig *ipconfig, break; } - if (append_addr == NULL) + if (!append_addr) return; - if (append_addr->local != NULL) { + if (append_addr->local) { in_addr_t addr; struct in_addr netmask; char *mask; @@ -1788,7 +1846,7 @@ void __connman_ipconfig_append_ipv4(struct connman_ipconfig *ipconfig, DBUS_TYPE_STRING, &mask); } - if (append_addr->gateway != NULL) + if (append_addr->gateway) connman_dbus_dict_append_basic(iter, "Gateway", DBUS_TYPE_STRING, &append_addr->gateway); } @@ -1806,10 +1864,10 @@ void __connman_ipconfig_append_ipv6(struct connman_ipconfig *ipconfig, return; str = __connman_ipconfig_method2string(ipconfig->method); - if (str == NULL) + if (!str) return; - if (ipconfig_ipv4 != NULL && + if (ipconfig_ipv4 && ipconfig->method == CONNMAN_IPCONFIG_METHOD_AUTO) { if (__connman_6to4_check(ipconfig_ipv4) == 1) str = "6to4"; @@ -1833,10 +1891,10 @@ void __connman_ipconfig_append_ipv6(struct connman_ipconfig *ipconfig, break; } - if (append_addr == NULL) + if (!append_addr) return; - if (append_addr->local != NULL) { + if (append_addr->local) { connman_dbus_dict_append_basic(iter, "Address", DBUS_TYPE_STRING, &append_addr->local); connman_dbus_dict_append_basic(iter, "PrefixLength", @@ -1844,7 +1902,7 @@ void __connman_ipconfig_append_ipv6(struct connman_ipconfig *ipconfig, &append_addr->prefixlen); } - if (append_addr->gateway != NULL) + if (append_addr->gateway) connman_dbus_dict_append_basic(iter, "Gateway", DBUS_TYPE_STRING, &append_addr->gateway); @@ -1861,7 +1919,7 @@ void __connman_ipconfig_append_ipv6config(struct connman_ipconfig *ipconfig, DBG(""); str = __connman_ipconfig_method2string(ipconfig->method); - if (str == NULL) + if (!str) return; connman_dbus_dict_append_basic(iter, "Method", DBUS_TYPE_STRING, &str); @@ -1877,10 +1935,10 @@ void __connman_ipconfig_append_ipv6config(struct connman_ipconfig *ipconfig, break; } - if (ipconfig->address == NULL) + if (!ipconfig->address) return; - if (ipconfig->address->local != NULL) { + if (ipconfig->address->local) { connman_dbus_dict_append_basic(iter, "Address", DBUS_TYPE_STRING, &ipconfig->address->local); connman_dbus_dict_append_basic(iter, "PrefixLength", @@ -1888,7 +1946,7 @@ void __connman_ipconfig_append_ipv6config(struct connman_ipconfig *ipconfig, &ipconfig->address->prefixlen); } - if (ipconfig->address->gateway != NULL) + if (ipconfig->address->gateway) connman_dbus_dict_append_basic(iter, "Gateway", DBUS_TYPE_STRING, &ipconfig->address->gateway); @@ -1905,7 +1963,7 @@ void __connman_ipconfig_append_ipv4config(struct connman_ipconfig *ipconfig, DBG(""); str = __connman_ipconfig_method2string(ipconfig->method); - if (str == NULL) + if (!str) return; connman_dbus_dict_append_basic(iter, "Method", DBUS_TYPE_STRING, &str); @@ -1921,10 +1979,10 @@ void __connman_ipconfig_append_ipv4config(struct connman_ipconfig *ipconfig, break; } - if (ipconfig->address == NULL) + if (!ipconfig->address) return; - if (ipconfig->address->local != NULL) { + if (ipconfig->address->local) { in_addr_t addr; struct in_addr netmask; char *mask; @@ -1939,7 +1997,7 @@ void __connman_ipconfig_append_ipv4config(struct connman_ipconfig *ipconfig, DBUS_TYPE_STRING, &mask); } - if (ipconfig->address->gateway != NULL) + if (ipconfig->address->gateway) connman_dbus_dict_append_basic(iter, "Gateway", DBUS_TYPE_STRING, &ipconfig->address->gateway); } @@ -1981,7 +2039,7 @@ int __connman_ipconfig_set_config(struct connman_ipconfig *ipconfig, type = dbus_message_iter_get_arg_type(&value); - if (g_str_equal(key, "Method") == TRUE) { + if (g_str_equal(key, "Method")) { const char *str; if (type != DBUS_TYPE_STRING) @@ -1989,12 +2047,12 @@ int __connman_ipconfig_set_config(struct connman_ipconfig *ipconfig, dbus_message_iter_get_basic(&value, &str); method = __connman_ipconfig_string2method(str); - } else if (g_str_equal(key, "Address") == TRUE) { + } else if (g_str_equal(key, "Address")) { if (type != DBUS_TYPE_STRING) return -EINVAL; dbus_message_iter_get_basic(&value, &address); - } else if (g_str_equal(key, "PrefixLength") == TRUE) { + } else if (g_str_equal(key, "PrefixLength")) { if (type != DBUS_TYPE_BYTE) return -EINVAL; @@ -2002,17 +2060,17 @@ int __connman_ipconfig_set_config(struct connman_ipconfig *ipconfig, if (prefix_length < 0 || prefix_length > 128) return -EINVAL; - } else if (g_str_equal(key, "Netmask") == TRUE) { + } else if (g_str_equal(key, "Netmask")) { if (type != DBUS_TYPE_STRING) return -EINVAL; dbus_message_iter_get_basic(&value, &netmask); - } else if (g_str_equal(key, "Gateway") == TRUE) { + } else if (g_str_equal(key, "Gateway")) { if (type != DBUS_TYPE_STRING) return -EINVAL; dbus_message_iter_get_basic(&value, &gateway); - } else if (g_str_equal(key, "Privacy") == TRUE) { + } else if (g_str_equal(key, "Privacy")) { if (type != DBUS_TYPE_STRING) return -EINVAL; @@ -2044,7 +2102,7 @@ int __connman_ipconfig_set_config(struct connman_ipconfig *ipconfig, return -EOPNOTSUPP; ipconfig->method = method; - if (privacy_string != NULL) + if (privacy_string) ipconfig->ipv6_privacy_config = privacy; enable_ipv6(ipconfig); break; @@ -2062,12 +2120,12 @@ int __connman_ipconfig_set_config(struct connman_ipconfig *ipconfig, break; } - if ((address != NULL && connman_inet_check_ipaddress(address) + if ((address && connman_inet_check_ipaddress(address) != type) || - (netmask != NULL && + (netmask && connman_inet_check_ipaddress(netmask) != type) || - (gateway != NULL && + (gateway && connman_inet_check_ipaddress(gateway) != type)) return -EINVAL; @@ -2105,14 +2163,17 @@ void __connman_ipconfig_append_ethernet(struct connman_ipconfig *ipconfig, ipdevice = g_hash_table_lookup(ipdevice_hash, GINT_TO_POINTER(ipconfig->index)); - if (ipdevice == NULL) + if (!ipdevice) return; - if (ipdevice->ifname != NULL) + if (ipconfig->index >= 0) { + char *ifname = connman_inet_ifname(ipconfig->index); connman_dbus_dict_append_basic(iter, "Interface", - DBUS_TYPE_STRING, &ipdevice->ifname); + DBUS_TYPE_STRING, &ifname); + g_free(ifname); + } - if (ipdevice->address != NULL) + if (ipdevice->address) connman_dbus_dict_append_basic(iter, "Address", DBUS_TYPE_STRING, &ipdevice->address); @@ -2132,7 +2193,7 @@ int __connman_ipconfig_load(struct connman_ipconfig *ipconfig, key = g_strdup_printf("%smethod", prefix); method = g_key_file_get_string(keyfile, identifier, key, NULL); - if (method == NULL) { + if (!method) { switch (ipconfig->type) { case CONNMAN_IPCONFIG_TYPE_IPV4: ipconfig->method = CONNMAN_IPCONFIG_METHOD_DHCP; @@ -2151,16 +2212,30 @@ int __connman_ipconfig_load(struct connman_ipconfig *ipconfig, ipconfig->method = CONNMAN_IPCONFIG_METHOD_OFF; if (ipconfig->type == CONNMAN_IPCONFIG_TYPE_IPV6) { + gsize length; + char *pprefix; + if (ipconfig->method == CONNMAN_IPCONFIG_METHOD_AUTO || ipconfig->method == CONNMAN_IPCONFIG_METHOD_MANUAL) { char *privacy; - char *pprefix = g_strdup_printf("%sprivacy", prefix); + + pprefix = g_strdup_printf("%sprivacy", prefix); privacy = g_key_file_get_string(keyfile, identifier, pprefix, NULL); ipconfig->ipv6_privacy_config = string2privacy(privacy); g_free(pprefix); g_free(privacy); } + + pprefix = g_strdup_printf("%sDHCP.LastPrefixes", prefix); + ipconfig->last_dhcpv6_prefixes = + g_key_file_get_string_list(keyfile, identifier, pprefix, + &length, NULL); + if (ipconfig->last_dhcpv6_prefixes && length == 0) { + g_free(ipconfig->last_dhcpv6_prefixes); + ipconfig->last_dhcpv6_prefixes = NULL; + } + g_free(pprefix); } g_free(method); @@ -2172,28 +2247,32 @@ int __connman_ipconfig_load(struct connman_ipconfig *ipconfig, g_free(key); 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); 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); 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); 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); key = g_strdup_printf("%sDHCP.LastAddress", prefix); str = g_key_file_get_string(keyfile, identifier, key, NULL); - if (str != NULL) { + if (str) { g_free(ipconfig->last_dhcp_address); ipconfig->last_dhcp_address = str; } @@ -2208,13 +2287,15 @@ int __connman_ipconfig_save(struct connman_ipconfig *ipconfig, const char *method; char *key; - DBG("ipconfig %p identifier %s", ipconfig, identifier); - method = __connman_ipconfig_method2string(ipconfig->method); - key = g_strdup_printf("%smethod", prefix); - g_key_file_set_string(keyfile, identifier, key, method); - g_free(key); + DBG("ipconfig %p identifier %s method %s", ipconfig, identifier, + method); + if (method) { + key = g_strdup_printf("%smethod", prefix); + g_key_file_set_string(keyfile, identifier, key, method); + g_free(key); + } if (ipconfig->type == CONNMAN_IPCONFIG_TYPE_IPV6) { const char *privacy; @@ -2224,13 +2305,26 @@ int __connman_ipconfig_save(struct connman_ipconfig *ipconfig, g_free(key); key = g_strdup_printf("%sDHCP.LastAddress", prefix); - if (ipconfig->last_dhcp_address != NULL && + if (ipconfig->last_dhcp_address && strlen(ipconfig->last_dhcp_address) > 0) g_key_file_set_string(keyfile, identifier, key, ipconfig->last_dhcp_address); else g_key_file_remove_key(keyfile, identifier, key, NULL); g_free(key); + + key = g_strdup_printf("%sDHCP.LastPrefixes", prefix); + if (ipconfig->last_dhcpv6_prefixes && + ipconfig->last_dhcpv6_prefixes[0]) { + guint len = + g_strv_length(ipconfig->last_dhcpv6_prefixes); + + g_key_file_set_string_list(keyfile, identifier, key, + (const gchar **)ipconfig->last_dhcpv6_prefixes, + len); + } else + g_key_file_remove_key(keyfile, identifier, key, NULL); + g_free(key); } switch (ipconfig->method) { @@ -2239,7 +2333,7 @@ int __connman_ipconfig_save(struct connman_ipconfig *ipconfig, break; case CONNMAN_IPCONFIG_METHOD_DHCP: key = g_strdup_printf("%sDHCP.LastAddress", prefix); - if (ipconfig->last_dhcp_address != NULL && + if (ipconfig->last_dhcp_address && strlen(ipconfig->last_dhcp_address) > 0) g_key_file_set_string(keyfile, identifier, key, ipconfig->last_dhcp_address); @@ -2260,25 +2354,25 @@ int __connman_ipconfig_save(struct connman_ipconfig *ipconfig, g_free(key); key = g_strdup_printf("%slocal_address", prefix); - if (ipconfig->address->local != NULL) + if (ipconfig->address->local) g_key_file_set_string(keyfile, identifier, key, ipconfig->address->local); g_free(key); key = g_strdup_printf("%speer_address", prefix); - if (ipconfig->address->peer != NULL) + if (ipconfig->address->peer) g_key_file_set_string(keyfile, identifier, key, ipconfig->address->peer); g_free(key); key = g_strdup_printf("%sbroadcast_address", prefix); - if (ipconfig->address->broadcast != NULL) + if (ipconfig->address->broadcast) g_key_file_set_string(keyfile, identifier, key, ipconfig->address->broadcast); g_free(key); key = g_strdup_printf("%sgateway", prefix); - if (ipconfig->address->gateway != NULL) + if (ipconfig->address->gateway) g_key_file_set_string(keyfile, identifier, key, ipconfig->address->gateway); g_free(key); diff --git a/src/ippool.c b/src/ippool.c index ba613fb1..558e9662 100644 --- a/src/ippool.c +++ b/src/ippool.c @@ -2,8 +2,8 @@ * * Connection Manager * - * Copyright (C) 2007-2012 Intel Corporation. All rights reserved. - * Copyright (C) 2012 BMW Car IT GmbH. All rights reserved. + * Copyright (C) 2007-2013 Intel Corporation. All rights reserved. + * Copyright (C) 2012-2013 BMW Car IT GmbH. 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 @@ -24,7 +24,6 @@ #include <config.h> #endif -#include <getopt.h> #include <stdlib.h> #include <stdio.h> #include <string.h> @@ -82,7 +81,7 @@ __connman_ippool_ref_debug(struct connman_ippool *pool, void __connman_ippool_unref_debug(struct connman_ippool *pool, const char *file, int line, const char *caller) { - if (pool == NULL) + if (!pool) return; DBG("%p ref %d by %s:%d:%s()", pool, pool->refcount - 1, @@ -170,7 +169,7 @@ static uint32_t get_free_block(unsigned int size) struct address_info *info; uint32_t block; GSList *list; - connman_bool_t collision; + bool collision; /* * Instead starting always from the 16 bit block, we start @@ -188,17 +187,17 @@ static uint32_t get_free_block(unsigned int size) block = next_block(last_block); do { - collision = FALSE; - for (list = allocated_blocks; list != NULL; list = list->next) { + collision = false; + for (list = allocated_blocks; list; list = list->next) { info = list->data; if (info->start <= block && block <= info->end) { - collision = TRUE; + collision = true; break; } } - if (collision == FALSE) + if (!collision) return block; block = next_block(block); @@ -211,7 +210,7 @@ static struct address_info *lookup_info(int index, uint32_t start) { GSList *list; - for (list = allocated_blocks; list != NULL; list = list->next) { + for (list = allocated_blocks; list; list = list->next) { struct address_info *info = list->data; if (info->index == index && info->start == start) @@ -221,7 +220,7 @@ static struct address_info *lookup_info(int index, uint32_t start) return NULL; } -static connman_bool_t is_private_address(uint32_t address) +static bool is_private_address(uint32_t address) { unsigned int a, b; @@ -230,9 +229,9 @@ static connman_bool_t is_private_address(uint32_t address) if (a == 10 || (a == 192 && b == 168) || (a == 172 && (b >= 16 && b <= 31))) - return TRUE; + return true; - return FALSE; + return false; } void __connman_ippool_newaddr(int index, const char *address, @@ -247,7 +246,7 @@ void __connman_ippool_newaddr(int index, const char *address, return; start = ntohl(inp.s_addr); - if (is_private_address(start) == FALSE) + if (!is_private_address(start)) return; if (prefixlen >= 32) @@ -259,11 +258,11 @@ void __connman_ippool_newaddr(int index, const char *address, end = start | ~mask; info = lookup_info(index, start); - if (info != NULL) + if (info) goto update; info = g_try_new0(struct address_info, 1); - if (info == NULL) + if (!info) return; info->index = index; @@ -275,7 +274,7 @@ void __connman_ippool_newaddr(int index, const char *address, update: info->use_count = info->use_count + 1; - if (info->use_count > 1 || info->pool != NULL) { + if (info->use_count > 1 || info->pool) { /* * We need only to check for the first IP in a block for * collisions. @@ -283,16 +282,16 @@ update: return; } - for (list = allocated_blocks; list != NULL; list = list->next) { + for (list = allocated_blocks; list; list = list->next) { it = list->data; if (it == info) continue; - if (!(it->start <= info->start || info->start <= it->end)) + if (!(info->start >= it->start && info->start <= it->end)) continue; - if (it->pool != NULL && it->pool->collision_cb != NULL) + if (it->pool && it->pool->collision_cb) it->pool->collision_cb(it->pool, it->pool->user_data); return; @@ -310,27 +309,28 @@ void __connman_ippool_deladdr(int index, const char *address, return; start = ntohl(inp.s_addr); - if (is_private_address(start) == FALSE) + if (!is_private_address(start)) return; mask = ~(0xffffffff >> prefixlen); start = start & mask; info = lookup_info(index, start); - if (info == NULL) { + if (!info) { /* In theory this should never happen */ connman_error("Inconsistent IP pool management (start not found)"); return; } info->use_count = info->use_count - 1; - if (info->pool != NULL) + if (info->pool) return; if (info->use_count > 0) return; allocated_blocks = g_slist_remove(allocated_blocks, info); + g_free(info); } struct connman_ippool *__connman_ippool_create(int index, @@ -361,11 +361,11 @@ struct connman_ippool *__connman_ippool_create(int index, } pool = g_try_new0(struct connman_ippool, 1); - if (pool == NULL) + if (!pool) return NULL; info = g_try_new0(struct address_info, 1); - if (info == NULL) { + if (!info) { g_free(pool); return NULL; } @@ -427,7 +427,7 @@ static void pool_free(gpointer data) { struct connman_ippool *pool = data; - if (pool->info != NULL) { + if (pool->info) { allocated_blocks = g_slist_remove(allocated_blocks, pool->info); g_free(pool->info); } @@ -463,7 +463,7 @@ void __connman_ippool_cleanup(void) g_hash_table_destroy(pool_hash); pool_hash = NULL; - g_slist_free(allocated_blocks); + g_slist_free_full(allocated_blocks, g_free); last_block = 0; allocated_blocks = NULL; } diff --git a/src/iptables.c b/src/iptables.c index 9584e126..8d583eae 100644 --- a/src/iptables.c +++ b/src/iptables.c @@ -2,7 +2,7 @@ * * Connection Manager * - * Copyright (C) 2007-2012 Intel Corporation. All rights reserved. + * Copyright (C) 2007-2013 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 @@ -35,6 +35,7 @@ #include <linux/netfilter_ipv4/ip_tables.h> #include "connman.h" +#include "src/shared/util.h" /* * Some comments on how the iptables API works (some of them from the @@ -175,10 +176,10 @@ struct connman_iptables { }; static GHashTable *table_hash = NULL; -static gboolean debug_enabled = FALSE; +static bool debug_enabled = false; typedef int (*iterate_entries_cb_t)(struct ipt_entry *entry, int builtin, - unsigned int hook,size_t size, + unsigned int hook, size_t size, unsigned int offset, void *user_data); static unsigned int next_hook_entry_index(unsigned int *valid_hooks) @@ -233,9 +234,8 @@ static int iterate_entries(struct ipt_entry *entries, if (h == NF_INET_NUMHOOKS) hook = h; - if (h < NF_INET_NUMHOOKS && underflow[h] <= offset) { + if (h < NF_INET_NUMHOOKS && underflow[h] <= offset) h = next_hook_entry_index(&valid_hooks); - } err = cb(entry, builtin, hook, size, offset, user_data); if (err < 0) @@ -274,18 +274,18 @@ static int target_to_verdict(const char *target_name) return 0; } -static gboolean is_builtin_target(const char *target_name) +static bool is_builtin_target(const char *target_name) { if (!g_strcmp0(target_name, LABEL_ACCEPT) || !g_strcmp0(target_name, LABEL_DROP) || !g_strcmp0(target_name, LABEL_QUEUE) || !g_strcmp0(target_name, LABEL_RETURN)) - return TRUE; + return true; - return FALSE; + return false; } -static gboolean is_jump(struct connman_iptables_entry *e) +static bool is_jump(struct connman_iptables_entry *e) { struct xt_entry_target *target; @@ -312,7 +312,7 @@ static gboolean is_jump(struct connman_iptables_entry *e) return false; } -static gboolean is_fallthrough(struct connman_iptables_entry *e) +static bool is_fallthrough(struct connman_iptables_entry *e) { struct xt_entry_target *target; @@ -327,7 +327,7 @@ static gboolean is_fallthrough(struct connman_iptables_entry *e) return false; } -static gboolean is_chain(struct connman_iptables *table, +static bool is_chain(struct connman_iptables *table, struct connman_iptables_entry *e) { struct ipt_entry *entry; @@ -335,13 +335,13 @@ static gboolean is_chain(struct connman_iptables *table, entry = e->entry; if (e->builtin >= 0) - return TRUE; + return true; target = ipt_get_target(entry); if (!g_strcmp0(target->u.user.name, IPT_ERROR_TARGET)) - return TRUE; + return true; - return FALSE; + return false; } static GList *find_chain_head(struct connman_iptables *table, @@ -379,7 +379,7 @@ static GList *find_chain_tail(struct connman_iptables *table, GList *chain_head, *list; chain_head = find_chain_head(table, chain_name); - if (chain_head == NULL) + if (!chain_head) return NULL; /* Then we look for the next chain */ @@ -420,7 +420,7 @@ static void update_offsets(struct connman_iptables *table) static void update_targets_reference(struct connman_iptables *table, struct connman_iptables_entry *entry_before, struct connman_iptables_entry *modified_entry, - gboolean is_removing) + bool is_removing) { struct connman_iptables_entry *tmp; struct xt_standard_target *t; @@ -437,7 +437,7 @@ static void update_targets_reference(struct connman_iptables *table, t = (struct xt_standard_target *)ipt_get_target(tmp->entry); - if (is_removing == TRUE) { + if (is_removing) { if (t->verdict >= entry_before->offset) t->verdict -= offset; } else { @@ -447,7 +447,8 @@ static void update_targets_reference(struct connman_iptables *table, } if (is_fallthrough(modified_entry)) { - t = (struct xt_standard_target *) ipt_get_target(modified_entry->entry); + t = (struct xt_standard_target *) + ipt_get_target(modified_entry->entry); t->verdict = entry_before->offset + modified_entry->entry->target_offset + @@ -463,11 +464,11 @@ static int iptables_add_entry(struct connman_iptables *table, { struct connman_iptables_entry *e, *entry_before; - if (table == NULL) + if (!table) return -1; e = g_try_malloc0(sizeof(struct connman_iptables_entry)); - if (e == NULL) + if (!e) return -1; e->entry = entry; @@ -477,7 +478,7 @@ static int iptables_add_entry(struct connman_iptables *table, table->num_entries++; table->size += entry->next_offset; - if (before == NULL) { + if (!before) { e->offset = table->size - entry->next_offset; return 0; @@ -489,7 +490,7 @@ static int iptables_add_entry(struct connman_iptables *table, * We've just appended/insterted a new entry. All references * should be bumped accordingly. */ - update_targets_reference(table, entry_before, e, FALSE); + update_targets_reference(table, entry_before, e, false); update_offsets(table); @@ -546,11 +547,11 @@ static int iptables_flush_chain(struct connman_iptables *table, DBG("table %s chain %s", table->name, name); chain_head = find_chain_head(table, name); - if (chain_head == NULL) + if (!chain_head) return -EINVAL; chain_tail = find_chain_tail(table, name); - if (chain_tail == NULL) + if (!chain_tail) return -EINVAL; entry = chain_head->data; @@ -605,13 +606,13 @@ static int iptables_add_chain(struct connman_iptables *table, */ /* head entry */ - entry_head_size = sizeof(struct ipt_entry) + - sizeof(struct error_target); + entry_head_size = ALIGN(sizeof(struct ipt_entry)) + + ALIGN(sizeof(struct error_target)); entry_head = g_try_malloc0(entry_head_size); - if (entry_head == NULL) + if (!entry_head) goto err_head; - entry_head->target_offset = sizeof(struct ipt_entry); + entry_head->target_offset = ALIGN(sizeof(struct ipt_entry)); entry_head->next_offset = entry_head_size; error = (struct error_target *) entry_head->elems; @@ -623,13 +624,13 @@ static int iptables_add_chain(struct connman_iptables *table, goto err_head; /* tail entry */ - entry_return_size = sizeof(struct ipt_entry) + - sizeof(struct ipt_standard_target); + entry_return_size = ALIGN(sizeof(struct ipt_entry))+ + ALIGN(sizeof(struct ipt_standard_target)); entry_return = g_try_malloc0(entry_return_size); - if (entry_return == NULL) + if (!entry_return) goto err; - entry_return->target_offset = sizeof(struct ipt_entry); + entry_return->target_offset = ALIGN(sizeof(struct ipt_entry)); entry_return->next_offset = entry_return_size; standard = (struct ipt_standard_target *) entry_return->elems; @@ -659,7 +660,7 @@ static int iptables_delete_chain(struct connman_iptables *table, DBG("table %s chain %s", table->name, name); chain_head = find_chain_head(table, name); - if (chain_head == NULL) + if (!chain_head) return -EINVAL; entry = chain_head->data; @@ -669,7 +670,7 @@ static int iptables_delete_chain(struct connman_iptables *table, return -EINVAL; chain_tail = find_chain_tail(table, name); - if (chain_tail == NULL) + if (!chain_tail) return -EINVAL; /* Chain must be flushed */ @@ -695,27 +696,28 @@ static struct ipt_entry *new_rule(struct ipt_ip *ip, size_t match_size, target_size; match_size = 0; - for (tmp_xt_rm = xt_rm; tmp_xt_rm != NULL; tmp_xt_rm = tmp_xt_rm->next) + for (tmp_xt_rm = xt_rm; tmp_xt_rm; tmp_xt_rm = tmp_xt_rm->next) match_size += tmp_xt_rm->match->m->u.match_size; if (xt_t) - target_size = ALIGN(xt_t->t->u.target_size); + target_size = xt_t->t->u.target_size; else target_size = ALIGN(sizeof(struct xt_standard_target)); - new_entry = g_try_malloc0(sizeof(struct ipt_entry) + target_size + - match_size); - if (new_entry == NULL) + new_entry = g_try_malloc0(ALIGN(sizeof(struct ipt_entry)) + + target_size + match_size); + if (!new_entry) return NULL; memcpy(&new_entry->ip, ip, sizeof(struct ipt_ip)); - new_entry->target_offset = sizeof(struct ipt_entry) + match_size; - new_entry->next_offset = sizeof(struct ipt_entry) + target_size + - match_size; + new_entry->target_offset = ALIGN(sizeof(struct ipt_entry)) + + match_size; + new_entry->next_offset = ALIGN(sizeof(struct ipt_entry)) + + target_size + match_size; match_size = 0; - for (tmp_xt_rm = xt_rm; tmp_xt_rm != NULL; + for (tmp_xt_rm = xt_rm; tmp_xt_rm; tmp_xt_rm = tmp_xt_rm->next) { memcpy(new_entry->elems + match_size, tmp_xt_rm->match->m, tmp_xt_rm->match->m->u.match_size); @@ -739,7 +741,7 @@ static void update_hooks(struct connman_iptables *table, GList *chain_head, struct connman_iptables_entry *head, *e; int builtin; - if (chain_head == NULL) + if (!chain_head) return; head = chain_head->data; @@ -767,22 +769,22 @@ static struct ipt_entry *prepare_rule_inclusion(struct connman_iptables *table, const char *target_name, struct xtables_target *xt_t, int *builtin, struct xtables_rule_match *xt_rm, - connman_bool_t insert) + bool insert) { GList *chain_tail, *chain_head; struct ipt_entry *new_entry; struct connman_iptables_entry *head; chain_head = find_chain_head(table, chain_name); - if (chain_head == NULL) + if (!chain_head) return NULL; chain_tail = find_chain_tail(table, chain_name); - if (chain_tail == NULL) + if (!chain_tail) return NULL; new_entry = new_rule(ip, target_name, xt_t, xt_rm); - if (new_entry == NULL) + if (!new_entry) return NULL; update_hooks(table, chain_head, new_entry); @@ -795,7 +797,7 @@ static struct ipt_entry *prepare_rule_inclusion(struct connman_iptables *table, head = chain_head->data; if (head->builtin < 0) *builtin = -1; - else if (insert == TRUE || chain_head == chain_tail->prev) { + else if (insert || chain_head == chain_tail->prev) { *builtin = head->builtin; head->builtin = -1; } @@ -816,12 +818,12 @@ static int iptables_append_rule(struct connman_iptables *table, DBG("table %s chain %s", table->name, chain_name); chain_tail = find_chain_tail(table, chain_name); - if (chain_tail == NULL) + if (!chain_tail) return -EINVAL; new_entry = prepare_rule_inclusion(table, ip, chain_name, - target_name, xt_t, &builtin, xt_rm, FALSE); - if (new_entry == NULL) + target_name, xt_t, &builtin, xt_rm, false); + if (!new_entry) return -EINVAL; ret = iptables_add_entry(table, new_entry, chain_tail->prev, builtin); @@ -844,12 +846,12 @@ static int iptables_insert_rule(struct connman_iptables *table, DBG("table %s chain %s", table->name, chain_name); chain_head = find_chain_head(table, chain_name); - if (chain_head == NULL) + if (!chain_head) return -EINVAL; new_entry = prepare_rule_inclusion(table, ip, chain_name, - target_name, xt_t, &builtin, xt_rm, TRUE); - if (new_entry == NULL) + target_name, xt_t, &builtin, xt_rm, true); + if (!new_entry) return -EINVAL; if (builtin == -1) @@ -862,33 +864,33 @@ static int iptables_insert_rule(struct connman_iptables *table, return ret; } -static gboolean is_same_ipt_entry(struct ipt_entry *i_e1, +static bool is_same_ipt_entry(struct ipt_entry *i_e1, struct ipt_entry *i_e2) { if (memcmp(&i_e1->ip, &i_e2->ip, sizeof(struct ipt_ip)) != 0) - return FALSE; + return false; if (i_e1->target_offset != i_e2->target_offset) - return FALSE; + return false; if (i_e1->next_offset != i_e2->next_offset) - return FALSE; + return false; - return TRUE; + return true; } -static gboolean is_same_target(struct xt_entry_target *xt_e_t1, +static bool is_same_target(struct xt_entry_target *xt_e_t1, struct xt_entry_target *xt_e_t2) { unsigned int i; - if (xt_e_t1 == NULL || xt_e_t2 == NULL) - return FALSE; + if (!xt_e_t1 || !xt_e_t2) + return false; if (g_strcmp0(xt_e_t1->u.user.name, "") == 0 && g_strcmp0(xt_e_t2->u.user.name, "") == 0) { /* fallthrough */ - return TRUE; + return true; } else if (g_strcmp0(xt_e_t1->u.user.name, IPT_STANDARD_TARGET) == 0) { struct xt_standard_target *xt_s_t1; struct xt_standard_target *xt_s_t2; @@ -897,48 +899,48 @@ static gboolean is_same_target(struct xt_entry_target *xt_e_t1, xt_s_t2 = (struct xt_standard_target *) xt_e_t2; if (xt_s_t1->verdict != xt_s_t2->verdict) - return FALSE; + return false; } else { if (xt_e_t1->u.target_size != xt_e_t2->u.target_size) - return FALSE; + return false; if (g_strcmp0(xt_e_t1->u.user.name, xt_e_t2->u.user.name) != 0) - return FALSE; + return false; for (i = 0; i < xt_e_t1->u.target_size - sizeof(struct xt_standard_target); i++) { if ((xt_e_t1->data[i] ^ xt_e_t2->data[i]) != 0) - return FALSE; + return false; } } - return TRUE; + return true; } -static gboolean is_same_match(struct xt_entry_match *xt_e_m1, +static bool is_same_match(struct xt_entry_match *xt_e_m1, struct xt_entry_match *xt_e_m2) { unsigned int i; - if (xt_e_m1 == NULL || xt_e_m2 == NULL) - return FALSE; + if (!xt_e_m1 || !xt_e_m2) + return false; if (xt_e_m1->u.match_size != xt_e_m2->u.match_size) - return FALSE; + return false; if (xt_e_m1->u.user.revision != xt_e_m2->u.user.revision) - return FALSE; + return false; if (g_strcmp0(xt_e_m1->u.user.name, xt_e_m2->u.user.name) != 0) - return FALSE; + return false; for (i = 0; i < xt_e_m1->u.match_size - sizeof(struct xt_entry_match); i++) { if ((xt_e_m1->data[i] ^ xt_e_m2->data[i]) != 0) - return FALSE; + return false; } - return TRUE; + return true; } static GList *find_existing_rule(struct connman_iptables *table, @@ -956,23 +958,23 @@ static GList *find_existing_rule(struct connman_iptables *table, int builtin; chain_head = find_chain_head(table, chain_name); - if (chain_head == NULL) + if (!chain_head) return NULL; chain_tail = find_chain_tail(table, chain_name); - if (chain_tail == NULL) + if (!chain_tail) return NULL; if (!xt_t && !matches) return NULL; entry_test = new_rule(ip, target_name, xt_t, xt_rm); - if (entry_test == NULL) + if (!entry_test) return NULL; - if (xt_t != NULL) + if (xt_t) xt_e_t = ipt_get_target(entry_test); - if (matches != NULL) + if (matches) xt_e_m = (struct xt_entry_match *)entry_test->elems; entry = chain_head->data; @@ -990,10 +992,10 @@ static GList *find_existing_rule(struct connman_iptables *table, tmp = list->data; tmp_e = tmp->entry; - if (is_same_ipt_entry(entry_test, tmp_e) == FALSE) + if (!is_same_ipt_entry(entry_test, tmp_e)) continue; - if (xt_t != NULL) { + if (xt_t) { struct xt_entry_target *tmp_xt_e_t; tmp_xt_e_t = ipt_get_target(tmp_e); @@ -1002,7 +1004,7 @@ static GList *find_existing_rule(struct connman_iptables *table, continue; } - if (matches != NULL) { + if (matches) { struct xt_entry_match *tmp_xt_e_m; tmp_xt_e_m = (struct xt_entry_match *)tmp_e->elems; @@ -1039,16 +1041,16 @@ static int iptables_delete_rule(struct connman_iptables *table, removed = 0; chain_head = find_chain_head(table, chain_name); - if (chain_head == NULL) + if (!chain_head) return -EINVAL; chain_tail = find_chain_tail(table, chain_name); - if (chain_tail == NULL) + if (!chain_tail) return -EINVAL; list = find_existing_rule(table, ip, chain_name, target_name, xt_t, matches, xt_rm); - if (list == NULL) + if (!list) return -EINVAL; entry = chain_head->data; @@ -1071,14 +1073,14 @@ static int iptables_delete_rule(struct connman_iptables *table, } entry = list->data; - if (entry == NULL) + if (!entry) return -EINVAL; /* We have deleted a rule, * all references should be bumped accordingly */ - if (list->next != NULL) + if (list->next) update_targets_reference(table, list->next->data, - list->data, TRUE); + list->data, true); removed += remove_table_entry(table, entry); @@ -1111,7 +1113,7 @@ static int iptables_change_policy(struct connman_iptables *table, } chain_head = find_chain_head(table, chain_name); - if (chain_head == NULL) + if (!chain_head) return -EINVAL; entry = chain_head->data; @@ -1119,7 +1121,7 @@ static int iptables_change_policy(struct connman_iptables *table, return -EINVAL; chain_tail = find_chain_tail(table, chain_name); - if (chain_tail == NULL) + if (!chain_tail) return -EINVAL; entry = chain_tail->prev->data; @@ -1139,14 +1141,14 @@ static struct ipt_replace *iptables_blob(struct connman_iptables *table) unsigned char *entry_index; r = g_try_malloc0(sizeof(struct ipt_replace) + table->size); - if (r == NULL) + if (!r) return NULL; memset(r, 0, sizeof(*r) + table->size); r->counters = g_try_malloc0(sizeof(struct xt_counters) * table->old_entries); - if (r->counters == NULL) { + if (!r->counters) { g_free(r); return NULL; } @@ -1184,14 +1186,14 @@ static void dump_ip(struct ipt_entry *entry) if (strlen(ip->outiface)) DBG("\tout %s", ip->outiface); - if (inet_ntop(AF_INET, &ip->src, ip_string, INET6_ADDRSTRLEN) != NULL && - inet_ntop(AF_INET, &ip->smsk, - ip_mask, INET6_ADDRSTRLEN) != NULL) + if (inet_ntop(AF_INET, &ip->src, ip_string, INET6_ADDRSTRLEN) && + inet_ntop(AF_INET, &ip->smsk, ip_mask, + INET6_ADDRSTRLEN)) DBG("\tsrc %s/%s", ip_string, ip_mask); - if (inet_ntop(AF_INET, &ip->dst, ip_string, INET6_ADDRSTRLEN) != NULL && - inet_ntop(AF_INET, &ip->dmsk, - ip_mask, INET6_ADDRSTRLEN) != NULL) + if (inet_ntop(AF_INET, &ip->dst, ip_string, INET6_ADDRSTRLEN) && + inet_ntop(AF_INET, &ip->dmsk, ip_mask, + INET6_ADDRSTRLEN)) DBG("\tdst %s/%s", ip_string, ip_mask); } @@ -1237,16 +1239,16 @@ static void dump_target(struct ipt_entry *entry) xt_t = xtables_find_target(IPT_STANDARD_TARGET, XTF_LOAD_MUST_SUCCEED); - if(xt_t->print != NULL) + if (xt_t->print) xt_t->print(NULL, target, 1); } else { xt_t = xtables_find_target(target->u.user.name, XTF_TRY_LOAD); - if (xt_t == NULL) { + if (!xt_t) { DBG("\ttarget %s", target->u.user.name); return; } - if(xt_t->print != NULL) { + if (xt_t->print) { DBG("\ttarget "); xt_t->print(NULL, target, 1); } @@ -1270,10 +1272,10 @@ static void dump_match(struct ipt_entry *entry) return; xt_m = xtables_find_match(match->u.user.name, XTF_TRY_LOAD, NULL); - if (xt_m == NULL) + if (!xt_m) goto out; - if(xt_m->print != NULL) { + if (xt_m->print) { DBG("\tmatch "); xt_m->print(NULL, match, 1); @@ -1378,18 +1380,29 @@ static void dump_ipt_replace(struct ipt_replace *repl) static int iptables_get_entries(struct connman_iptables *table) { socklen_t entry_size; + int err; entry_size = sizeof(struct ipt_get_entries) + table->info->size; - return getsockopt(table->ipt_sock, IPPROTO_IP, IPT_SO_GET_ENTRIES, + err = getsockopt(table->ipt_sock, IPPROTO_IP, IPT_SO_GET_ENTRIES, table->blob_entries, &entry_size); + if (err < 0) + return -errno; + + return 0; } static int iptables_replace(struct connman_iptables *table, struct ipt_replace *r) { - return setsockopt(table->ipt_sock, IPPROTO_IP, IPT_SO_SET_REPLACE, r, - sizeof(*r) + r->size); + int err; + + err = setsockopt(table->ipt_sock, IPPROTO_IP, IPT_SO_SET_REPLACE, r, + sizeof(*r) + r->size); + if (err < 0) + return -errno; + + return 0; } static int add_entry(struct ipt_entry *entry, int builtin, unsigned int hook, @@ -1399,7 +1412,7 @@ static int add_entry(struct ipt_entry *entry, int builtin, unsigned int hook, struct ipt_entry *new_entry; new_entry = g_try_malloc0(entry->next_offset); - if (new_entry == NULL) + if (!new_entry) return -ENOMEM; memcpy(new_entry, entry, entry->next_offset); @@ -1412,7 +1425,7 @@ static void table_cleanup(struct connman_iptables *table) GList *list; struct connman_iptables_entry *entry; - if (table == NULL) + if (!table) return; if (table->ipt_sock >= 0) @@ -1444,7 +1457,7 @@ static struct connman_iptables *iptables_init(const char *table_name) DBG("ip_tables module loading gives error but trying anyway"); module = g_strconcat("iptable_", table_name, NULL); - if (module == NULL) + if (!module) return NULL; if (xtables_insmod(module, NULL, TRUE) != 0) @@ -1453,11 +1466,11 @@ static struct connman_iptables *iptables_init(const char *table_name) g_free(module); table = g_try_new0(struct connman_iptables, 1); - if (table == NULL) + if (!table) return NULL; table->info = g_try_new0(struct ipt_getinfo, 1); - if (table->info == NULL) + if (!table->info) goto err; table->ipt_sock = socket(AF_INET, SOCK_RAW | SOCK_CLOEXEC, IPPROTO_RAW); @@ -1475,7 +1488,7 @@ static struct connman_iptables *iptables_init(const char *table_name) table->blob_entries = g_try_malloc0(sizeof(struct ipt_get_entries) + table->info->size); - if (table->blob_entries == NULL) + if (!table->blob_entries) goto err; g_stpcpy(table->blob_entries->name, table_name); @@ -1498,7 +1511,7 @@ static struct connman_iptables *iptables_init(const char *table_name) table->info->underflow, table->blob_entries->size, add_entry, table); - if (debug_enabled == TRUE) + if (debug_enabled) dump_table(table); return table; @@ -1539,19 +1552,19 @@ static struct xtables_target *prepare_target(struct connman_iptables *table, const char *target_name) { struct xtables_target *xt_t = NULL; - gboolean is_builtin, is_user_defined; + bool is_builtin, is_user_defined; GList *chain_head = NULL; size_t target_size; - is_builtin = FALSE; - is_user_defined = FALSE; + is_builtin = false; + is_user_defined = false; if (is_builtin_target(target_name)) - is_builtin = TRUE; + is_builtin = true; else { chain_head = find_chain_head(table, target_name); - if (chain_head != NULL && chain_head->next != NULL) - is_user_defined = TRUE; + if (chain_head && chain_head->next) + is_user_defined = true; } if (is_builtin || is_user_defined) @@ -1560,13 +1573,13 @@ static struct xtables_target *prepare_target(struct connman_iptables *table, else xt_t = xtables_find_target(target_name, XTF_TRY_LOAD); - if (xt_t == NULL) + if (!xt_t) return NULL; target_size = ALIGN(sizeof(struct ipt_entry_target)) + xt_t->size; xt_t->t = g_try_malloc0(target_size); - if (xt_t->t == NULL) + if (!xt_t->t) return NULL; xt_t->t->u.target_size = target_size; @@ -1577,27 +1590,22 @@ static struct xtables_target *prepare_target(struct connman_iptables *table, target = (struct xt_standard_target *)(xt_t->t); g_stpcpy(target->target.u.user.name, IPT_STANDARD_TARGET); - if (is_builtin == TRUE) + if (is_builtin) target->verdict = target_to_verdict(target_name); - else if (is_user_defined == TRUE) { + else if (is_user_defined) { struct connman_iptables_entry *target_rule; - if (chain_head == NULL) { - g_free(xt_t->t); - return NULL; - } - target_rule = chain_head->next->data; target->verdict = target_rule->offset; } } else { g_stpcpy(xt_t->t->u.user.name, target_name); xt_t->t->u.user.revision = xt_t->revision; - if (xt_t->init != NULL) + if (xt_t->init) xt_t->init(xt_t->t); } - if (xt_t->x6_options != NULL) + if (xt_t->x6_options) iptables_globals.opts = xtables_options_xfrm( iptables_globals.orig_opts, @@ -1612,7 +1620,7 @@ static struct xtables_target *prepare_target(struct connman_iptables *table, xt_t->extra_opts, &xt_t->option_offset); - if (iptables_globals.opts == NULL) { + if (!iptables_globals.opts) { g_free(xt_t->t); xt_t = NULL; } @@ -1627,24 +1635,24 @@ static struct xtables_match *prepare_matches(struct connman_iptables *table, struct xtables_match *xt_m; size_t match_size; - if (match_name == NULL) + if (!match_name) return NULL; xt_m = xtables_find_match(match_name, XTF_LOAD_MUST_SUCCEED, xt_rm); match_size = ALIGN(sizeof(struct ipt_entry_match)) + xt_m->size; xt_m->m = g_try_malloc0(match_size); - if (xt_m->m == NULL) + if (!xt_m->m) return NULL; xt_m->m->u.match_size = match_size; g_stpcpy(xt_m->m->u.user.name, xt_m->name); xt_m->m->u.user.revision = xt_m->revision; - if (xt_m->init != NULL) + if (xt_m->init) xt_m->init(xt_m->m); - if (xt_m->x6_options != NULL) + if (xt_m->x6_options) iptables_globals.opts = xtables_options_xfrm( iptables_globals.orig_opts, @@ -1659,7 +1667,7 @@ static struct xtables_match *prepare_matches(struct connman_iptables *table, xt_m->extra_opts, &xt_m->option_offset); - if (iptables_globals.opts == NULL) { + if (!iptables_globals.opts) { g_free(xt_m->m); if (xt_m == xt_m->next) @@ -1671,7 +1679,8 @@ static struct xtables_match *prepare_matches(struct connman_iptables *table, return xt_m; } -static int parse_ip_and_mask(const char *str, struct in_addr *ip, struct in_addr *mask) +static int parse_ip_and_mask(const char *str, struct in_addr *ip, + struct in_addr *mask) { char **tokens; uint32_t prefixlength; @@ -1679,7 +1688,7 @@ static int parse_ip_and_mask(const char *str, struct in_addr *ip, struct in_addr int err; tokens = g_strsplit(str, "/", 2); - if (tokens == NULL) + if (!tokens) return -1; if (!inet_pton(AF_INET, tokens[0], ip)) { @@ -1687,7 +1696,7 @@ static int parse_ip_and_mask(const char *str, struct in_addr *ip, struct in_addr goto out; } - if (tokens[1] != NULL) { + if (tokens[1]) { prefixlength = strtol(tokens[1], NULL, 10); if (prefixlength > 31) { err = -1; @@ -1712,15 +1721,15 @@ static struct connman_iptables *get_table(const char *table_name) { struct connman_iptables *table; - if (table_name == NULL) + if (!table_name) table_name = "filter"; table = g_hash_table_lookup(table_hash, table_name); - if (table != NULL) + if (table) return table; table = iptables_init(table_name); - if (table == NULL) + if (!table) return NULL; table->name = g_strdup(table_name); @@ -1752,7 +1761,7 @@ static int prepare_getopt_args(const char *str, struct parse_context *ctx) /* Don't forget the last NULL entry */ ctx->argv = g_try_malloc0((ctx->argc + 1) * sizeof(char *)); - if (ctx->argv == NULL) { + if (!ctx->argv) { g_strfreev(tokens); return -ENOMEM; } @@ -1770,19 +1779,19 @@ static int prepare_getopt_args(const char *str, struct parse_context *ctx) return 0; } -static int parse_xt_modules(int c, connman_bool_t invert, +static int parse_xt_modules(int c, bool invert, struct parse_context *ctx) { struct xtables_match *m; struct xtables_rule_match *rm; - for (rm = ctx->xt_rm; rm != NULL; rm = rm->next) { + for (rm = ctx->xt_rm; rm; rm = rm->next) { if (rm->completed != 0) continue; m = rm->match; - if (m->x6_parse == NULL && m->parse == NULL) + if (!m->x6_parse && !m->parse) continue; if (c < (int) m->option_offset || @@ -1793,10 +1802,10 @@ static int parse_xt_modules(int c, connman_bool_t invert, xtables_option_mpcall(c, ctx->argv, invert, m, NULL); } - if (ctx->xt_t == NULL) + if (!ctx->xt_t) return 0; - if (ctx->xt_t->x6_parse == NULL && ctx->xt_t->parse == NULL) + if (!ctx->xt_t->x6_parse && !ctx->xt_t->parse) return 0; if (c < (int) ctx->xt_t->option_offset || @@ -1813,10 +1822,10 @@ static int final_check_xt_modules(struct parse_context *ctx) { struct xtables_rule_match *rm; - for (rm = ctx->xt_rm; rm != NULL; rm = rm->next) + for (rm = ctx->xt_rm; rm; rm = rm->next) xtables_option_mfcall(rm->match); - if (ctx->xt_t != NULL) + if (ctx->xt_t) xtables_option_tfcall(ctx->xt_t); return 0; @@ -1902,11 +1911,11 @@ static int parse_rule_spec(struct connman_iptables *table, * of libxtables is found. */ struct xtables_match *xt_m; - connman_bool_t invert = FALSE; + bool invert = false; int len, c, err; ctx->ip = g_try_new0(struct ipt_ip, 1); - if (ctx->ip == NULL) + if (!ctx->ip) return -ENOMEM; /* @@ -1972,7 +1981,7 @@ static int parse_rule_spec(struct connman_iptables *table, case 'm': /* Matches */ xt_m = prepare_matches(table, &ctx->xt_rm, optarg); - if (xt_m == NULL) { + if (!xt_m) { err = -EINVAL; goto out; } @@ -1982,7 +1991,7 @@ static int parse_rule_spec(struct connman_iptables *table, case 'j': /* Target */ ctx->xt_t = prepare_target(table, optarg); - if (ctx->xt_t == NULL) { + if (!ctx->xt_t) { err = -EINVAL; goto out; } @@ -1990,7 +1999,7 @@ static int parse_rule_spec(struct connman_iptables *table, break; case 1: if (optarg[0] == '!' && optarg[1] == '\0') { - invert = TRUE; + invert = true; /* Remove the '!' from the optarg */ optarg[0] = '\0'; @@ -2011,7 +2020,7 @@ static int parse_rule_spec(struct connman_iptables *table, break; } - invert = FALSE; + invert = false; } err = final_check_xt_modules(ctx); @@ -2033,10 +2042,10 @@ static void reset_xtables(void) * Clear all flags because the flags are only valid * for one rule. */ - for (xt_m = xtables_matches; xt_m != NULL; xt_m = xt_m->next) + for (xt_m = xtables_matches; xt_m; xt_m = xt_m->next) xt_m->mflags = 0; - for (xt_t = xtables_targets; xt_t != NULL; xt_t = xt_t->next) { + for (xt_t = xtables_targets; xt_t; xt_t = xt_t->next) { xt_t->tflags = 0; xt_t->used = 0; } @@ -2060,12 +2069,12 @@ static void cleanup_parse_context(struct parse_context *ctx) g_strfreev(ctx->argv); g_free(ctx->ip); - if (ctx->xt_t != NULL) { + if (ctx->xt_t) { g_free(ctx->xt_t->t); ctx->xt_t->t = NULL; } - for (list = ctx->xt_m; list != NULL; list = list->next) { + for (list = ctx->xt_m; list; list = list->next) { struct xtables_match *xt_m = list->data; g_free(xt_m->m); @@ -2077,8 +2086,8 @@ static void cleanup_parse_context(struct parse_context *ctx) } g_list_free(ctx->xt_m); - for (tmp = NULL, rm = ctx->xt_rm; rm != NULL; rm = rm->next) { - if (tmp != NULL) + for (tmp = NULL, rm = ctx->xt_rm; rm; rm = rm->next) { + if (tmp) g_free(tmp); tmp = rm; } @@ -2094,7 +2103,7 @@ int __connman_iptables_dump(const char *table_name) DBG("-t %s -L", table_name); table = get_table(table_name); - if (table == NULL) + if (!table) return -EINVAL; dump_table(table); @@ -2110,7 +2119,7 @@ int __connman_iptables_new_chain(const char *table_name, DBG("-t %s -N %s", table_name, chain); table = get_table(table_name); - if (table == NULL) + if (!table) return -EINVAL; return iptables_add_chain(table, chain); @@ -2124,7 +2133,7 @@ int __connman_iptables_delete_chain(const char *table_name, DBG("-t %s -X %s", table_name, chain); table = get_table(table_name); - if (table == NULL) + if (!table) return -EINVAL; return iptables_delete_chain(table, chain); @@ -2138,7 +2147,7 @@ int __connman_iptables_flush_chain(const char *table_name, DBG("-t %s -F %s", table_name, chain); table = get_table(table_name); - if (table == NULL) + if (!table) return -EINVAL; return iptables_flush_chain(table, chain); @@ -2153,7 +2162,7 @@ int __connman_iptables_change_policy(const char *table_name, DBG("-t %s -F %s", table_name, chain); table = get_table(table_name); - if (table == NULL) + if (!table) return -EINVAL; return iptables_change_policy(table, chain, policy); @@ -2169,7 +2178,7 @@ int __connman_iptables_append(const char *table_name, int err; ctx = g_try_new0(struct parse_context, 1); - if (ctx == NULL) + if (!ctx) return -ENOMEM; DBG("-t %s -A %s %s", table_name, chain, rule_spec); @@ -2179,7 +2188,7 @@ int __connman_iptables_append(const char *table_name, goto out; table = get_table(table_name); - if (table == NULL) { + if (!table) { err = -EINVAL; goto out; } @@ -2188,7 +2197,7 @@ int __connman_iptables_append(const char *table_name, if (err < 0) goto out; - if (ctx->xt_t == NULL) + if (!ctx->xt_t) target_name = NULL; else target_name = ctx->xt_t->name; @@ -2212,7 +2221,7 @@ int __connman_iptables_insert(const char *table_name, int err; ctx = g_try_new0(struct parse_context, 1); - if (ctx == NULL) + if (!ctx) return -ENOMEM; DBG("-t %s -I %s %s", table_name, chain, rule_spec); @@ -2222,7 +2231,7 @@ int __connman_iptables_insert(const char *table_name, goto out; table = get_table(table_name); - if (table == NULL) { + if (!table) { err = -EINVAL; goto out; } @@ -2231,7 +2240,7 @@ int __connman_iptables_insert(const char *table_name, if (err < 0) goto out; - if (ctx->xt_t == NULL) + if (!ctx->xt_t) target_name = NULL; else target_name = ctx->xt_t->name; @@ -2255,7 +2264,7 @@ int __connman_iptables_delete(const char *table_name, int err; ctx = g_try_new0(struct parse_context, 1); - if (ctx == NULL) + if (!ctx) return -ENOMEM; DBG("-t %s -D %s %s", table_name, chain, rule_spec); @@ -2265,7 +2274,7 @@ int __connman_iptables_delete(const char *table_name, goto out; table = get_table(table_name); - if (table == NULL) { + if (!table) { err = -EINVAL; goto out; } @@ -2274,7 +2283,7 @@ int __connman_iptables_delete(const char *table_name, if (err < 0) goto out; - if (ctx->xt_t == NULL) + if (!ctx->xt_t) target_name = NULL; else target_name = ctx->xt_t->name; @@ -2298,12 +2307,12 @@ int __connman_iptables_commit(const char *table_name) DBG("%s", table_name); table = g_hash_table_lookup(table_hash, table_name); - if (table == NULL) + if (!table) return -EINVAL; repl = iptables_blob(table); - if (debug_enabled == TRUE) + if (debug_enabled) dump_ipt_replace(repl); err = iptables_replace(table, repl); @@ -2312,7 +2321,7 @@ int __connman_iptables_commit(const char *table_name) g_free(repl); if (err < 0) - return err; + return err; g_hash_table_remove(table_hash, table_name); @@ -2340,7 +2349,7 @@ static int iterate_chains_cb(struct ipt_entry *entry, int builtin, target = ipt_get_target(entry); if (!g_strcmp0(target->u.user.name, IPT_ERROR_TARGET)) - (*cb)((const char*)target->data, cbd->user_data); + (*cb)((const char *)target->data, cbd->user_data); else if (builtin >= 0) (*cb)(hooknames[builtin], cbd->user_data); @@ -2355,7 +2364,7 @@ int __connman_iptables_iterate_chains(const char *table_name, struct connman_iptables *table; table = get_table(table_name); - if (table == NULL) + if (!table) return -EINVAL; iterate_entries(table->blob_entries->entrytable, @@ -2375,7 +2384,7 @@ int __connman_iptables_init(void) DBG(""); if (getenv("CONNMAN_IPTABLES_DEBUG")) - debug_enabled = TRUE; + debug_enabled = true; table_hash = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, remove_table); diff --git a/src/ipv6pd.c b/src/ipv6pd.c new file mode 100644 index 00000000..5ecda389 --- /dev/null +++ b/src/ipv6pd.c @@ -0,0 +1,383 @@ +/* + * + * Connection Manager + * + * Copyright (C) 2013 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 <errno.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <unistd.h> +#include <stdio.h> + +#include "connman.h" + +#include <gdhcp/gdhcp.h> + +#define DEFAULT_ROUTER_LIFETIME 180 /* secs */ +#define DEFAULT_RA_INTERVAL 120 /* secs */ + +static int bridge_index = -1; +static guint timer_uplink; +static guint timer_ra; +static char *default_interface; +static GSList *prefixes; +static GHashTable *timer_hash; +static void *rs_context; + +static int setup_prefix_delegation(struct connman_service *service); +static void dhcpv6_callback(struct connman_network *network, + enum __connman_dhcpv6_status status, gpointer data); + +static int enable_ipv6_forward(bool enable) +{ + FILE *f; + + f = fopen("/proc/sys/net/ipv6/ip_forward", "r+"); + if (!f) + return -errno; + + if (enable) + fprintf(f, "1"); + else + fprintf(f, "0"); + + fclose(f); + + return 0; +} + +static gboolean send_ra(gpointer data) +{ + __connman_inet_ipv6_send_ra(bridge_index, NULL, prefixes, + DEFAULT_ROUTER_LIFETIME); + + return TRUE; +} + +static void start_ra(int ifindex, GSList *prefix) +{ + if (prefixes) + g_slist_free_full(prefixes, g_free); + + prefixes = g_dhcpv6_copy_prefixes(prefix); + + enable_ipv6_forward(true); + + if (timer_ra > 0) + g_source_remove(timer_ra); + + send_ra(NULL); + + timer_ra = g_timeout_add_seconds(DEFAULT_RA_INTERVAL, send_ra, NULL); +} + +static void stop_ra(int ifindex) +{ + __connman_inet_ipv6_send_ra(ifindex, NULL, prefixes, 0); + + if (timer_ra > 0) { + g_source_remove(timer_ra); + timer_ra = 0; + } + + enable_ipv6_forward(false); + + if (prefixes) { + g_slist_free_full(prefixes, g_free); + prefixes = NULL; + } +} + +static void rs_received(struct nd_router_solicit *reply, + unsigned int length, void *user_data) +{ + GDHCPIAPrefix *prefix; + GSList *list; + + if (!prefixes) + return; + + DBG(""); + + for (list = prefixes; list; list = list->next) { + prefix = list->data; + + prefix->valid -= time(NULL) - prefix->expire; + prefix->preferred -= time(NULL) - prefix->expire; + } + + __connman_inet_ipv6_send_ra(bridge_index, NULL, prefixes, + DEFAULT_ROUTER_LIFETIME); +} + +static gboolean do_setup(gpointer data) +{ + int ret; + + timer_uplink = 0; + + if (!default_interface) + DBG("No uplink connection, retrying prefix delegation"); + + ret = setup_prefix_delegation(__connman_service_get_default()); + if (ret < 0 && ret != -EINPROGRESS) + return TRUE; /* delegation error, try again */ + + return FALSE; +} + +static void dhcpv6_renew_callback(struct connman_network *network, + enum __connman_dhcpv6_status status, + gpointer data) +{ + DBG("network %p status %d data %p", network, status, data); + + if (status == CONNMAN_DHCPV6_STATUS_SUCCEED) + dhcpv6_callback(network, status, data); + else + setup_prefix_delegation(__connman_service_get_default()); +} + +static void cleanup(void) +{ + if (timer_uplink != 0) { + g_source_remove(timer_uplink); + timer_uplink = 0; + } + + g_hash_table_destroy(timer_hash); + timer_hash = NULL; + + if (prefixes) { + g_slist_free_full(prefixes, g_free); + prefixes = NULL; + } +} + +static void dhcpv6_callback(struct connman_network *network, + enum __connman_dhcpv6_status status, gpointer data) +{ + GSList *prefix_list = data; + + DBG("network %p status %d data %p", network, status, data); + + if (status == CONNMAN_DHCPV6_STATUS_FAIL) { + DBG("Prefix delegation request failed"); + cleanup(); + return; + } + + if (!prefix_list) { + DBG("No prefixes, retrying"); + if (timer_uplink == 0) + timer_uplink = g_timeout_add_seconds(10, do_setup, + NULL); + return; + } + + /* + * After we have got a list of prefixes, we can start to send router + * advertisements (RA) to tethering interface. + */ + start_ra(bridge_index, prefix_list); + + if (__connman_dhcpv6_start_pd_renew(network, + dhcpv6_renew_callback) == -ETIMEDOUT) + dhcpv6_renew_callback(network, CONNMAN_DHCPV6_STATUS_FAIL, + NULL); +} + +static int setup_prefix_delegation(struct connman_service *service) +{ + struct connman_ipconfig *ipconfig; + char *interface; + int err = 0, ifindex; + + if (!service) { + /* + * We do not have uplink connection. We just wait until + * default interface is updated. + */ + return -EINPROGRESS; + } + + interface = connman_service_get_interface(service); + + DBG("interface %s bridge_index %d", interface, bridge_index); + + if (default_interface) { + stop_ra(bridge_index); + + ifindex = connman_inet_ifindex(default_interface); + __connman_dhcpv6_stop_pd(ifindex); + } + + g_free(default_interface); + + ipconfig = __connman_service_get_ip6config(service); + if (!__connman_ipconfig_ipv6_is_enabled(ipconfig)) { + g_free(interface); + default_interface = NULL; + return -EPFNOSUPPORT; + } + + default_interface = interface; + + if (default_interface) { + ifindex = connman_inet_ifindex(default_interface); + + /* + * Try to get a IPv6 prefix so we can start to advertise it. + */ + err = __connman_dhcpv6_start_pd(ifindex, prefixes, + dhcpv6_callback); + if (err < 0) + DBG("prefix delegation %d/%s", err, strerror(-err)); + } + + return err; +} + +static void cleanup_timer(gpointer user_data) +{ + guint timer = GPOINTER_TO_UINT(user_data); + + g_source_remove(timer); +} + +static void update_default_interface(struct connman_service *service) +{ + setup_prefix_delegation(service); +} + +static void update_ipconfig(struct connman_service *service, + struct connman_ipconfig *ipconfig) +{ + if (!service || service != __connman_service_get_default()) + return; + + if (ipconfig != __connman_service_get_ip6config(service)) + return; + + if (!__connman_ipconfig_ipv6_is_enabled(ipconfig)) { + if (default_interface) { + int ifindex; + + ifindex = connman_inet_ifindex(default_interface); + __connman_dhcpv6_stop_pd(ifindex); + + g_free(default_interface); + default_interface = NULL; + } + + DBG("No IPv6 support for interface index %d", + __connman_ipconfig_get_index(ipconfig)); + return; + } + + /* + * Did we had PD activated already? If not, then start it. + */ + if (!default_interface) { + DBG("IPv6 ipconfig %p changed for interface index %d", ipconfig, + __connman_ipconfig_get_index(ipconfig)); + + setup_prefix_delegation(service); + } +} + +static struct connman_notifier pd_notifier = { + .name = "IPv6 prefix delegation", + .default_changed = update_default_interface, + .ipconfig_changed = update_ipconfig, +}; + +int __connman_ipv6pd_setup(const char *bridge) +{ + struct connman_service *service; + int err; + + if (!connman_inet_is_ipv6_supported()) + return -EPFNOSUPPORT; + + if (bridge_index >= 0) { + DBG("Prefix delegation already running"); + return -EALREADY; + } + + err = connman_notifier_register(&pd_notifier); + if (err < 0) + return err; + + bridge_index = connman_inet_ifindex(bridge); + + timer_hash = g_hash_table_new_full(g_direct_hash, g_direct_equal, + NULL, cleanup_timer); + + err = __connman_inet_ipv6_start_recv_rs(bridge_index, rs_received, + NULL, &rs_context); + if (err < 0) + DBG("Cannot receive router solicitation %d/%s", + err, strerror(-err)); + + service = __connman_service_get_default(); + if (service) { + /* + * We have an uplink connection already, try to use it. + */ + return setup_prefix_delegation(service); + } + + /* + * The prefix delegation is started after have got the uplink + * connection up i.e., when the default service is setup in which + * case the update_default_interface() will be called. + */ + return -EINPROGRESS; +} + +void __connman_ipv6pd_cleanup(void) +{ + int ifindex; + + if (!connman_inet_is_ipv6_supported()) + return; + + connman_notifier_unregister(&pd_notifier); + + __connman_inet_ipv6_stop_recv_rs(rs_context); + rs_context = NULL; + + cleanup(); + + stop_ra(bridge_index); + + if (default_interface) { + ifindex = connman_inet_ifindex(default_interface); + __connman_dhcpv6_stop_pd(ifindex); + g_free(default_interface); + default_interface = NULL; + } + + bridge_index = -1; +} @@ -2,7 +2,7 @@ * * Connection Manager * - * Copyright (C) 2007-2012 Intel Corporation. All rights reserved. + * Copyright (C) 2007-2013 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 @@ -119,7 +119,7 @@ static void print_backtrace(unsigned int offset) int pathlen; pid_t pid; - if (program_exec == NULL) + if (!program_exec) return; pathlen = strlen(program_path); @@ -179,7 +179,7 @@ static void print_backtrace(unsigned int offset) if (written < 0) break; - len = read(infd[0], buf, sizeof(buf)); + len = read(infd[0], buf, sizeof(buf) - 1); if (len < 0) break; @@ -243,23 +243,23 @@ extern struct connman_debug_desc __stop___debug[]; static gchar **enabled = NULL; -static connman_bool_t is_enabled(struct connman_debug_desc *desc) +static bool is_enabled(struct connman_debug_desc *desc) { int i; - if (enabled == NULL) - return FALSE; + if (!enabled) + return false; - for (i = 0; enabled[i] != NULL; i++) { - if (desc->name != NULL && g_pattern_match_simple(enabled[i], - desc->name) == TRUE) - return TRUE; - if (desc->file != NULL && g_pattern_match_simple(enabled[i], - desc->file) == TRUE) - return TRUE; + for (i = 0; enabled[i]; i++) { + if (desc->name && g_pattern_match_simple(enabled[i], + desc->name)) + return true; + if (desc->file && g_pattern_match_simple(enabled[i], + desc->file)) + return true; } - return FALSE; + return false; } void __connman_log_enable(struct connman_debug_desc *start, @@ -268,7 +268,7 @@ void __connman_log_enable(struct connman_debug_desc *start, struct connman_debug_desc *desc; const char *name = NULL, *file = NULL; - if (start == NULL || stop == NULL) + if (!start || !stop) return; for (desc = start; desc < stop; desc++) { @@ -278,21 +278,21 @@ void __connman_log_enable(struct connman_debug_desc *start, continue; } - if (file != NULL || name != NULL) { + if (file || name) { if (g_strcmp0(desc->file, file) == 0) { - if (desc->name == NULL) + if (!desc->name) desc->name = name; } else file = NULL; } - if (is_enabled(desc) == TRUE) + if (is_enabled(desc)) desc->flags |= CONNMAN_DEBUG_FLAG_PRINT; } } int __connman_log_init(const char *program, const char *debug, - connman_bool_t detach, connman_bool_t backtrace, + gboolean detach, gboolean backtrace, const char *program_name, const char *program_version) { static char path[PATH_MAX]; @@ -301,15 +301,15 @@ int __connman_log_init(const char *program, const char *debug, program_exec = program; program_path = getcwd(path, sizeof(path)); - if (debug != NULL) + if (debug) enabled = g_strsplit_set(debug, ":, ", 0); __connman_log_enable(__start___debug, __stop___debug); - if (detach == FALSE) + if (!detach) option |= LOG_PERROR; - if (backtrace == TRUE) + if (backtrace) signal_setup(signal_handler); openlog(basename(program), option, LOG_DAEMON); @@ -319,13 +319,13 @@ int __connman_log_init(const char *program, const char *debug, return 0; } -void __connman_log_cleanup(connman_bool_t backtrace) +void __connman_log_cleanup(gboolean backtrace) { syslog(LOG_INFO, "Exit"); closelog(); - if (backtrace == TRUE) + if (backtrace) signal_setup(SIG_DFL); g_strfreev(enabled); @@ -2,7 +2,7 @@ * * Connection Manager * - * Copyright (C) 2007-2012 Intel Corporation. All rights reserved. + * Copyright (C) 2007-2013 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 @@ -39,8 +39,8 @@ #include "connman.h" -#define DEFAULT_INPUT_REQUEST_TIMEOUT 120 * 1000 -#define DEFAULT_BROWSER_LAUNCH_TIMEOUT 300 * 1000 +#define DEFAULT_INPUT_REQUEST_TIMEOUT (120 * 1000) +#define DEFAULT_BROWSER_LAUNCH_TIMEOUT (300 * 1000) #define MAINFILE "main.conf" #define CONFIGMAINFILE CONFIGDIR "/" MAINFILE @@ -56,11 +56,12 @@ static char *default_blacklist[] = { "vmnet", "vboxnet", "virbr", + "ifb", NULL }; static struct { - connman_bool_t bg_scan; + bool bg_scan; char **pref_timeservers; unsigned int *auto_connect; unsigned int *preferred_techs; @@ -68,12 +69,12 @@ static struct { unsigned int timeout_inputreq; unsigned int timeout_browserlaunch; char **blacklisted_interfaces; - connman_bool_t allow_hostname_updates; - connman_bool_t single_tech; + bool allow_hostname_updates; + bool single_tech; char **tethering_technologies; - connman_bool_t persistent_tethering_mode; + bool persistent_tethering_mode; } connman_settings = { - .bg_scan = TRUE, + .bg_scan = true, .pref_timeservers = NULL, .auto_connect = NULL, .preferred_techs = NULL, @@ -81,10 +82,10 @@ static struct { .timeout_inputreq = DEFAULT_INPUT_REQUEST_TIMEOUT, .timeout_browserlaunch = DEFAULT_BROWSER_LAUNCH_TIMEOUT, .blacklisted_interfaces = NULL, - .allow_hostname_updates = TRUE, - .single_tech = FALSE, + .allow_hostname_updates = true, + .single_tech = false, .tethering_technologies = NULL, - .persistent_tethering_mode = FALSE, + .persistent_tethering_mode = false, }; #define CONF_BG_SCAN "BackgroundScanning" @@ -146,13 +147,12 @@ static uint *parse_service_types(char **str_list, gsize len) enum connman_service_type type; type_list = g_try_new0(unsigned int, len + 1); - if (type_list == NULL) + if (!type_list) return NULL; i = 0; j = 0; - while (str_list[i] != NULL) - { + while (str_list[i]) { type = __connman_service_string2type(str_list[i]); if (type != CONNMAN_SERVICE_TYPE_UNKNOWN) { @@ -162,6 +162,8 @@ static uint *parse_service_types(char **str_list, gsize len) i += 1; } + type_list[j] = CONNMAN_SERVICE_TYPE_UNKNOWN; + return type_list; } @@ -171,12 +173,12 @@ static char **parse_fallback_nameservers(char **nameservers, gsize len) int i, j; servers = g_try_new0(char *, len + 1); - if (servers == NULL) + if (!servers) return NULL; i = 0; j = 0; - while (nameservers[i] != NULL) { + while (nameservers[i]) { if (connman_inet_check_ipaddress(nameservers[i]) > 0) { servers[j] = g_strdup(nameservers[i]); j += 1; @@ -192,12 +194,12 @@ static void check_config(GKeyFile *config) char **keys; int j; - if (config == NULL) + if (!config) return; keys = g_key_file_get_groups(config, NULL); - for (j = 0; keys != NULL && keys[j] != NULL; j++) { + for (j = 0; keys && keys[j]; j++) { if (g_strcmp0(keys[j], "General") != 0) connman_warn("Unknown group %s in %s", keys[j], MAINFILE); @@ -207,18 +209,18 @@ static void check_config(GKeyFile *config) keys = g_key_file_get_keys(config, "General", NULL, NULL); - for (j = 0; keys != NULL && keys[j] != NULL; j++) { - connman_bool_t found; + for (j = 0; keys && keys[j]; j++) { + bool found; int i; - found = FALSE; - for (i = 0; supported_options[i] != NULL; i++) { + found = false; + for (i = 0; supported_options[i]; i++) { if (g_strcmp0(keys[j], supported_options[i]) == 0) { - found = TRUE; + found = true; break; } } - if (found == FALSE && supported_options[i] == NULL) + if (!found && !supported_options[i]) connman_warn("Unknown option %s in %s", keys[j], MAINFILE); } @@ -229,7 +231,7 @@ static void check_config(GKeyFile *config) static void parse_config(GKeyFile *config) { GError *error = NULL; - gboolean boolean; + bool boolean; char **timeservers; char **interfaces; char **str_list; @@ -237,7 +239,7 @@ static void parse_config(GKeyFile *config) gsize len; int timeout; - if (config == NULL) { + if (!config) { connman_settings.auto_connect = parse_service_types(default_auto_connect, 3); connman_settings.blacklisted_interfaces = @@ -249,22 +251,22 @@ static void parse_config(GKeyFile *config) boolean = g_key_file_get_boolean(config, "General", CONF_BG_SCAN, &error); - if (error == NULL) + if (!error) connman_settings.bg_scan = boolean; g_clear_error(&error); - timeservers = g_key_file_get_string_list(config, "General", + timeservers = __connman_config_get_string_list(config, "General", CONF_PREF_TIMESERVERS, NULL, &error); - if (error == NULL) + if (!error) connman_settings.pref_timeservers = timeservers; g_clear_error(&error); - str_list = g_key_file_get_string_list(config, "General", + str_list = __connman_config_get_string_list(config, "General", CONF_AUTO_CONNECT, &len, &error); - if (error == NULL) + if (!error) connman_settings.auto_connect = parse_service_types(str_list, len); else @@ -275,10 +277,10 @@ static void parse_config(GKeyFile *config) g_clear_error(&error); - str_list = g_key_file_get_string_list(config, "General", + str_list = __connman_config_get_string_list(config, "General", CONF_PREFERRED_TECHS, &len, &error); - if (error == NULL) + if (!error) connman_settings.preferred_techs = parse_service_types(str_list, len); @@ -286,10 +288,10 @@ static void parse_config(GKeyFile *config) g_clear_error(&error); - str_list = g_key_file_get_string_list(config, "General", + str_list = __connman_config_get_string_list(config, "General", CONF_FALLBACK_NAMESERVERS, &len, &error); - if (error == NULL) + if (!error) connman_settings.fallback_nameservers = parse_fallback_nameservers(str_list, len); @@ -299,22 +301,22 @@ static void parse_config(GKeyFile *config) timeout = g_key_file_get_integer(config, "General", CONF_TIMEOUT_INPUTREQ, &error); - if (error == NULL && timeout >= 0) + if (!error && timeout >= 0) connman_settings.timeout_inputreq = timeout * 1000; g_clear_error(&error); timeout = g_key_file_get_integer(config, "General", CONF_TIMEOUT_BROWSERLAUNCH, &error); - if (error == NULL && timeout >= 0) + if (!error && timeout >= 0) connman_settings.timeout_browserlaunch = timeout * 1000; g_clear_error(&error); - interfaces = g_key_file_get_string_list(config, "General", + interfaces = __connman_config_get_string_list(config, "General", CONF_BLACKLISTED_INTERFACES, &len, &error); - if (error == NULL) + if (!error) connman_settings.blacklisted_interfaces = interfaces; else connman_settings.blacklisted_interfaces = @@ -322,33 +324,33 @@ static void parse_config(GKeyFile *config) g_clear_error(&error); - boolean = g_key_file_get_boolean(config, "General", + boolean = __connman_config_get_bool(config, "General", CONF_ALLOW_HOSTNAME_UPDATES, &error); - if (error == NULL) + if (!error) connman_settings.allow_hostname_updates = boolean; g_clear_error(&error); - boolean = g_key_file_get_boolean(config, "General", + boolean = __connman_config_get_bool(config, "General", CONF_SINGLE_TECH, &error); - if (error == NULL) + if (!error) connman_settings.single_tech = boolean; g_clear_error(&error); - tethering = g_key_file_get_string_list(config, "General", + tethering = __connman_config_get_string_list(config, "General", CONF_TETHERING_TECHNOLOGIES, &len, &error); - if (error == NULL) + if (!error) connman_settings.tethering_technologies = tethering; g_clear_error(&error); - boolean = g_key_file_get_boolean(config, "General", + boolean = __connman_config_get_bool(config, "General", CONF_PERSISTENT_TETHERING_MODE, &error); - if (error == NULL) + if (!error) connman_settings.persistent_tethering_mode = boolean; g_clear_error(&error); @@ -361,7 +363,7 @@ static int config_init(const char *file) config = load_config(file); check_config(config); parse_config(config); - if (config != NULL) + if (config) g_key_file_free(config); return 0; @@ -458,7 +460,7 @@ static gboolean option_dnsproxy = TRUE; static gboolean option_backtrace = TRUE; static gboolean option_version = FALSE; -static gboolean parse_debug(const char *key, const char *value, +static bool parse_debug(const char *key, const char *value, gpointer user_data, GError **error) { if (value) @@ -466,7 +468,7 @@ static gboolean parse_debug(const char *key, const char *value, else option_debug = g_strdup("*"); - return TRUE; + return true; } static GOptionEntry options[] = { @@ -503,7 +505,7 @@ static GOptionEntry options[] = { const char *connman_option_get_string(const char *key) { if (g_strcmp0(key, "wifi") == 0) { - if (option_wifi == NULL) + if (!option_wifi) return "nl80211,wext"; else return option_wifi; @@ -512,35 +514,35 @@ const char *connman_option_get_string(const char *key) return NULL; } -connman_bool_t connman_setting_get_bool(const char *key) +bool connman_setting_get_bool(const char *key) { - if (g_str_equal(key, CONF_BG_SCAN) == TRUE) + if (g_str_equal(key, CONF_BG_SCAN)) return connman_settings.bg_scan; - if (g_str_equal(key, CONF_ALLOW_HOSTNAME_UPDATES) == TRUE) + if (g_str_equal(key, CONF_ALLOW_HOSTNAME_UPDATES)) return connman_settings.allow_hostname_updates; - if (g_str_equal(key, CONF_SINGLE_TECH) == TRUE) + if (g_str_equal(key, CONF_SINGLE_TECH)) return connman_settings.single_tech; - if (g_str_equal(key, CONF_PERSISTENT_TETHERING_MODE) == TRUE) + if (g_str_equal(key, CONF_PERSISTENT_TETHERING_MODE)) return connman_settings.persistent_tethering_mode; - return FALSE; + return false; } char **connman_setting_get_string_list(const char *key) { - if (g_str_equal(key, CONF_PREF_TIMESERVERS) == TRUE) + if (g_str_equal(key, CONF_PREF_TIMESERVERS)) return connman_settings.pref_timeservers; - if (g_str_equal(key, CONF_FALLBACK_NAMESERVERS) == TRUE) + if (g_str_equal(key, CONF_FALLBACK_NAMESERVERS)) return connman_settings.fallback_nameservers; - if (g_str_equal(key, CONF_BLACKLISTED_INTERFACES) == TRUE) + if (g_str_equal(key, CONF_BLACKLISTED_INTERFACES)) return connman_settings.blacklisted_interfaces; - if (g_str_equal(key, CONF_TETHERING_TECHNOLOGIES) == TRUE) + if (g_str_equal(key, CONF_TETHERING_TECHNOLOGIES)) return connman_settings.tethering_technologies; return NULL; @@ -548,20 +550,22 @@ char **connman_setting_get_string_list(const char *key) unsigned int *connman_setting_get_uint_list(const char *key) { - if (g_str_equal(key, CONF_AUTO_CONNECT) == TRUE) + if (g_str_equal(key, CONF_AUTO_CONNECT)) return connman_settings.auto_connect; - if (g_str_equal(key, CONF_PREFERRED_TECHS) == TRUE) + if (g_str_equal(key, CONF_PREFERRED_TECHS)) return connman_settings.preferred_techs; return NULL; } -unsigned int connman_timeout_input_request(void) { +unsigned int connman_timeout_input_request(void) +{ return connman_settings.timeout_inputreq; } -unsigned int connman_timeout_browser_launch(void) { +unsigned int connman_timeout_browser_launch(void) +{ return connman_settings.timeout_browserlaunch; } @@ -573,16 +577,11 @@ int main(int argc, char *argv[]) DBusError err; guint signal; -#ifdef NEED_THREADS - if (g_thread_supported() == FALSE) - g_thread_init(NULL); -#endif - context = g_option_context_new(NULL); g_option_context_add_main_entries(context, options, NULL); - if (g_option_context_parse(context, &argc, &argv, &error) == FALSE) { - if (error != NULL) { + if (!g_option_context_parse(context, &argc, &argv, &error)) { + if (error) { g_printerr("%s\n", error->message); g_error_free(error); } else @@ -592,24 +591,18 @@ int main(int argc, char *argv[]) g_option_context_free(context); - if (option_version == TRUE) { + if (option_version) { printf("%s\n", VERSION); exit(0); } - if (option_detach == TRUE) { + if (option_detach) { if (daemon(0, 0)) { perror("Can't start daemon"); exit(1); } } - if (mkdir(STATEDIR, S_IRUSR | S_IWUSR | S_IXUSR | - S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH) < 0) { - if (errno != EEXIST) - perror("Failed to create state directory"); - } - if (mkdir(STORAGEDIR, S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH) < 0) { if (errno != EEXIST) @@ -620,20 +613,13 @@ int main(int argc, char *argv[]) main_loop = g_main_loop_new(NULL, FALSE); -#ifdef NEED_THREADS - if (dbus_threads_init_default() == FALSE) { - fprintf(stderr, "Can't init usage of threads\n"); - exit(1); - } -#endif - signal = setup_signalfd(); dbus_error_init(&err); conn = g_dbus_setup_bus(DBUS_BUS_SYSTEM, CONNMAN_SERVICE, &err); - if (conn == NULL) { - if (dbus_error_is_set(&err) == TRUE) { + if (!conn) { + if (dbus_error_is_set(&err)) { fprintf(stderr, "%s\n", err.message); dbus_error_free(&err); } else @@ -648,7 +634,7 @@ int main(int argc, char *argv[]) __connman_dbus_init(conn); - if (option_config == NULL) + if (!option_config) config_init(CONFIGMAINFILE); else config_init(option_config); @@ -658,8 +644,10 @@ int main(int argc, char *argv[]) __connman_notifier_init(); __connman_agent_init(); __connman_service_init(); + __connman_peer_init(); __connman_provider_init(); __connman_network_init(); + __connman_config_init(); __connman_device_init(option_device, option_nodevice); __connman_ippool_init(); @@ -669,7 +657,6 @@ int main(int argc, char *argv[]) __connman_tethering_init(); __connman_counter_init(); __connman_manager_init(); - __connman_config_init(); __connman_stats_init(); __connman_clock_init(); @@ -706,7 +693,6 @@ int main(int argc, char *argv[]) __connman_wispr_cleanup(); __connman_wpad_cleanup(); __connman_dhcpv6_cleanup(); - __connman_dhcp_cleanup(); __connman_session_cleanup(); __connman_plugin_cleanup(); __connman_provider_cleanup(); @@ -730,7 +716,9 @@ int main(int argc, char *argv[]) __connman_ippool_cleanup(); __connman_device_cleanup(); __connman_network_cleanup(); + __connman_dhcp_cleanup(); __connman_service_cleanup(); + __connman_peer_cleanup(); __connman_agent_cleanup(); __connman_ipconfig_cleanup(); __connman_notifier_cleanup(); @@ -745,7 +733,7 @@ int main(int argc, char *argv[]) g_main_loop_unref(main_loop); - if (connman_settings.pref_timeservers != NULL) + if (connman_settings.pref_timeservers) g_strfreev(connman_settings.pref_timeservers); g_free(connman_settings.auto_connect); diff --git a/src/main.conf b/src/main.conf index b8b3239b..93c7a501 100644 --- a/src/main.conf +++ b/src/main.conf @@ -27,8 +27,8 @@ # domain names, IPv4 and IPv6 addresses. # FallbackTimeservers = -# List of fallback nameservers separated by "," appended -# to the list of nameservers given by the service. The +# List of fallback nameservers separated by "," used if no +# nameservers are otherwise provided by the service. The # nameserver entries must be in numeric format, host # names are ignored. # FallbackNameservers = @@ -57,8 +57,8 @@ # Found interfaces will be compared to the list and will # not be handled by connman, if their first characters # match any of the list entries. Default value is -# vmnet,vboxnet,virbr. -# NetworkInterfaceBlacklist = vmnet,vboxnet,virbr +# vmnet,vboxnet,virbr,ifb. +# NetworkInterfaceBlacklist = vmnet,vboxnet,virbr,ifb # Allow connman to change the system hostname. This can # happen for example if we receive DHCP hostname option. diff --git a/src/manager.c b/src/manager.c index e56f2e13..b31ab4c7 100644 --- a/src/manager.c +++ b/src/manager.c @@ -2,7 +2,7 @@ * * Connection Manager * - * Copyright (C) 2007-2012 Intel Corporation. All rights reserved. + * Copyright (C) 2007-2013 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 @@ -31,21 +31,21 @@ #include "connman.h" -static connman_bool_t connman_state_idle; -static DBusMessage *session_mode_pending = NULL; +static bool connman_state_idle; +static dbus_bool_t sessionmode; static DBusMessage *get_properties(DBusConnection *conn, DBusMessage *msg, void *data) { DBusMessage *reply; DBusMessageIter array, dict; - connman_bool_t offlinemode, sessionmode; + dbus_bool_t offlinemode; const char *str; DBG("conn %p", conn); reply = dbus_message_new_method_return(msg); - if (reply == NULL) + if (!reply) return NULL; dbus_message_iter_init_append(reply, &array); @@ -60,7 +60,6 @@ static DBusMessage *get_properties(DBusConnection *conn, connman_dbus_dict_append_basic(&dict, "OfflineMode", DBUS_TYPE_BOOLEAN, &offlinemode); - sessionmode = __connman_session_mode(); connman_dbus_dict_append_basic(&dict, "SessionMode", DBUS_TYPE_BOOLEAN, &sessionmode); @@ -79,7 +78,7 @@ static DBusMessage *set_property(DBusConnection *conn, DBG("conn %p", conn); - if (dbus_message_iter_init(msg, &iter) == FALSE) + if (!dbus_message_iter_init(msg, &iter)) return __connman_error_invalid_arguments(msg); if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING) @@ -95,8 +94,8 @@ static DBusMessage *set_property(DBusConnection *conn, type = dbus_message_iter_get_arg_type(&value); - if (g_str_equal(name, "OfflineMode") == TRUE) { - connman_bool_t offlinemode; + if (g_str_equal(name, "OfflineMode")) { + dbus_bool_t offlinemode; if (type != DBUS_TYPE_BOOLEAN) return __connman_error_invalid_arguments(msg); @@ -104,24 +103,13 @@ static DBusMessage *set_property(DBusConnection *conn, dbus_message_iter_get_basic(&value, &offlinemode); __connman_technology_set_offlinemode(offlinemode); - } else if (g_str_equal(name, "SessionMode") == TRUE) { - connman_bool_t sessionmode; + } else if (g_str_equal(name, "SessionMode")) { if (type != DBUS_TYPE_BOOLEAN) return __connman_error_invalid_arguments(msg); dbus_message_iter_get_basic(&value, &sessionmode); - if (session_mode_pending != NULL) - return __connman_error_in_progress(msg); - - __connman_session_set_mode(sessionmode); - - if (sessionmode == TRUE && connman_state_idle == FALSE) { - session_mode_pending = dbus_message_ref(msg); - return NULL; - } - } else return __connman_error_invalid_property(msg); @@ -141,7 +129,7 @@ static DBusMessage *get_technologies(DBusConnection *conn, DBG(""); reply = dbus_message_new_method_return(msg); - if (reply == NULL) + if (!reply) return NULL; __connman_dbus_append_objpath_dict_array(reply, @@ -170,28 +158,15 @@ static DBusMessage *remove_provider(DBusConnection *conn, static DBusConnection *connection = NULL; -static void session_mode_notify(void) -{ - DBusMessage *reply; - - reply = g_dbus_create_reply(session_mode_pending, DBUS_TYPE_INVALID); - g_dbus_send_message(connection, reply); - - dbus_message_unref(session_mode_pending); - session_mode_pending = NULL; -} - -static void idle_state(connman_bool_t idle) +static void idle_state(bool idle) { DBG("idle %d", idle); connman_state_idle = idle; - if (connman_state_idle == FALSE || session_mode_pending == NULL) + if (!connman_state_idle) return; - - session_mode_notify(); } static struct connman_notifier technology_notifier = { @@ -211,7 +186,7 @@ static DBusMessage *get_services(DBusConnection *conn, DBusMessage *reply; reply = dbus_message_new_method_return(msg); - if (reply == NULL) + if (!reply) return NULL; __connman_dbus_append_objpath_dict_array(reply, @@ -220,6 +195,25 @@ static DBusMessage *get_services(DBusConnection *conn, return reply; } +static void append_peer_structs(DBusMessageIter *iter, void *user_data) +{ + __connman_peer_list_struct(iter); +} + +static DBusMessage *get_peers(DBusConnection *conn, + DBusMessage *msg, void *data) +{ + DBusMessage *reply; + + reply = dbus_message_new_method_return(msg); + if (!reply) + return NULL; + + __connman_dbus_append_objpath_dict_array(reply, + append_peer_structs, NULL); + return reply; +} + static DBusMessage *connect_provider(DBusConnection *conn, DBusMessage *msg, void *data) { @@ -227,13 +221,6 @@ static DBusMessage *connect_provider(DBusConnection *conn, DBG("conn %p", conn); - if (__connman_session_mode() == TRUE) { - connman_info("Session mode enabled: " - "direct provider connect disabled"); - - return __connman_error_failed(msg, EINVAL); - } - err = __connman_provider_create_and_connect(msg); if (err < 0) return __connman_error_failed(msg, -err); @@ -409,6 +396,9 @@ static const GDBusMethodTable manager_methods[] = { { GDBUS_METHOD("GetServices", NULL, GDBUS_ARGS({ "services", "a(oa{sv})" }), get_services) }, + { GDBUS_METHOD("GetPeers", + NULL, GDBUS_ARGS({ "peers", "a(oa{sv})" }), + get_peers) }, { GDBUS_DEPRECATED_ASYNC_METHOD("ConnectProvider", GDBUS_ARGS({ "provider", "a{sv}" }), GDBUS_ARGS({ "path", "o" }), @@ -456,6 +446,9 @@ static const GDBusSignalTable manager_signals[] = { { GDBUS_SIGNAL("ServicesChanged", GDBUS_ARGS({ "changed", "a(oa{sv})" }, { "removed", "ao" })) }, + { GDBUS_SIGNAL("PeersChanged", + GDBUS_ARGS({ "changed", "a(oa{sv})" }, + { "removed", "ao" })) }, { }, }; @@ -464,7 +457,7 @@ int __connman_manager_init(void) DBG(""); connection = connman_dbus_get_connection(); - if (connection == NULL) + if (!connection) return -1; if (connman_notifier_register(&technology_notifier) < 0) @@ -475,7 +468,7 @@ int __connman_manager_init(void) manager_methods, manager_signals, NULL, NULL, NULL); - connman_state_idle = TRUE; + connman_state_idle = true; return 0; } @@ -484,12 +477,9 @@ void __connman_manager_cleanup(void) { DBG(""); - if (connection == NULL) + if (!connection) return; - if (session_mode_pending != NULL) - dbus_message_unref(session_mode_pending); - connman_notifier_unregister(&technology_notifier); g_dbus_unregister_interface(connection, CONNMAN_MANAGER_PATH, @@ -35,19 +35,20 @@ static GHashTable *nat_hash; struct connman_nat { char *address; unsigned char prefixlen; + struct firewall_context *fw; char *interface; }; -static int enable_ip_forward(connman_bool_t enable) +static int enable_ip_forward(bool enable) { FILE *f; f = fopen("/proc/sys/net/ipv4/ip_forward", "r+"); - if (f == NULL) + if (!f) return -errno; - if (enable == TRUE) + if (enable) fprintf(f, "1"); else fprintf(f, "0"); @@ -65,7 +66,7 @@ static int enable_nat(struct connman_nat *nat) g_free(nat->interface); nat->interface = g_strdup(default_interface); - if (nat->interface == NULL) + if (!nat->interface) return 0; /* Enable masquerading */ @@ -73,33 +74,23 @@ static int enable_nat(struct connman_nat *nat) nat->address, nat->prefixlen, nat->interface); - err = __connman_iptables_append("nat", "POSTROUTING", cmd); + + err = __connman_firewall_add_rule(nat->fw, "nat", + "POSTROUTING", cmd); g_free(cmd); if (err < 0) return err; - return __connman_iptables_commit("nat"); + return __connman_firewall_enable(nat->fw); } static void disable_nat(struct connman_nat *nat) { - char *cmd; - int err; - - if (nat->interface == NULL) + if (!nat->interface) return; /* Disable masquerading */ - cmd = g_strdup_printf("-s %s/%d -o %s -j MASQUERADE", - nat->address, - nat->prefixlen, - nat->interface); - err = __connman_iptables_delete("nat", "POSTROUTING", cmd); - g_free(cmd); - if (err < 0) - return; - - __connman_iptables_commit("nat"); + __connman_firewall_disable(nat->fw); } int __connman_nat_enable(const char *name, const char *address, @@ -109,18 +100,18 @@ int __connman_nat_enable(const char *name, const char *address, int err; if (g_hash_table_size(nat_hash) == 0) { - err = enable_ip_forward(TRUE); + err = enable_ip_forward(true); if (err < 0) return err; } nat = g_try_new0(struct connman_nat, 1); - if (nat == NULL) { - if (g_hash_table_size(nat_hash) == 0) - enable_ip_forward(FALSE); + if (!nat) + goto err; - return -ENOMEM; - } + nat->fw = __connman_firewall_create(); + if (!nat->fw) + goto err; nat->address = g_strdup(address); nat->prefixlen = prefixlen; @@ -128,6 +119,18 @@ int __connman_nat_enable(const char *name, const char *address, g_hash_table_replace(nat_hash, g_strdup(name), nat); return enable_nat(nat); + +err: + if (nat) { + if (nat->fw) + __connman_firewall_destroy(nat->fw); + g_free(nat); + } + + if (g_hash_table_size(nat_hash) == 0) + enable_ip_forward(false); + + return -ENOMEM; } void __connman_nat_disable(const char *name) @@ -135,7 +138,7 @@ void __connman_nat_disable(const char *name) struct connman_nat *nat; nat = g_hash_table_lookup(nat_hash, name); - if (nat == NULL) + if (!nat) return; disable_nat(nat); @@ -143,7 +146,7 @@ void __connman_nat_disable(const char *name) g_hash_table_remove(nat_hash, name); if (g_hash_table_size(nat_hash) == 0) - enable_ip_forward(FALSE); + enable_ip_forward(false); } static void update_default_interface(struct connman_service *service) @@ -162,7 +165,7 @@ static void update_default_interface(struct connman_service *service) g_hash_table_iter_init(&iter, nat_hash); - while (g_hash_table_iter_next(&iter, &key, &value) == TRUE) { + while (g_hash_table_iter_next(&iter, &key, &value)) { const char *name = key; struct connman_nat *nat = value; @@ -184,6 +187,7 @@ static void cleanup_nat(gpointer data) { struct connman_nat *nat = data; + __connman_firewall_destroy(nat->fw); g_free(nat->address); g_free(nat->interface); g_free(nat); diff --git a/src/net.connman.service.in b/src/net.connman.service.in new file mode 100644 index 00000000..0bb1e8b9 --- /dev/null +++ b/src/net.connman.service.in @@ -0,0 +1,5 @@ +[D-BUS Service] +Name=net.connman +Exec=@prefix@/sbin/connman -n +User=root +SystemdService=connman.service diff --git a/src/network.c b/src/network.c index 6a926cbc..160bd061 100644 --- a/src/network.c +++ b/src/network.c @@ -2,7 +2,7 @@ * * Connection Manager * - * Copyright (C) 2007-2012 Intel Corporation. All rights reserved. + * Copyright (C) 2007-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 @@ -47,9 +47,9 @@ static GSList *driver_list = NULL; struct connman_network { int refcount; enum connman_network_type type; - connman_bool_t available; - connman_bool_t connected; - connman_bool_t roaming; + bool available; + bool connected; + bool roaming; uint8_t strength; uint16_t frequency; char *identifier; @@ -64,8 +64,8 @@ struct connman_network { struct connman_network_driver *driver; void *driver_data; - connman_bool_t connecting; - connman_bool_t associating; + bool connecting; + bool associating; struct connman_device *device; @@ -76,7 +76,6 @@ struct connman_network { unsigned short channel; char *security; char *passphrase; - char *agent_passphrase; char *eap; char *identity; char *agent_identity; @@ -85,8 +84,8 @@ struct connman_network { char *private_key_path; char *private_key_passphrase; char *phase2_auth; - connman_bool_t wps; - connman_bool_t use_wps; + bool wps; + bool use_wps; char *pin_wps; } wifi; @@ -100,6 +99,8 @@ static const char *type2string(enum connman_network_type type) break; case CONNMAN_NETWORK_TYPE_ETHERNET: return "ethernet"; + case CONNMAN_NETWORK_TYPE_GADGET: + return "gadget"; case CONNMAN_NETWORK_TYPE_WIFI: return "wifi"; case CONNMAN_NETWORK_TYPE_BLUETOOTH_PAN: @@ -112,14 +113,14 @@ static const char *type2string(enum connman_network_type type) return NULL; } -static gboolean match_driver(struct connman_network *network, +static bool match_driver(struct connman_network *network, struct connman_network_driver *driver) { if (network->type == driver->type || driver->type == CONNMAN_NETWORK_TYPE_UNKNOWN) - return TRUE; + return true; - return FALSE; + return false; } static void set_configuration(struct connman_network *network, @@ -129,12 +130,12 @@ static void set_configuration(struct connman_network *network, DBG("network %p", network); - if (network->device == NULL) + if (!network->device) return; __connman_device_set_network(network->device, network); - connman_device_set_disconnected(network->device, FALSE); + connman_device_set_disconnected(network->device, false); service = connman_service_lookup_from_network(network); __connman_service_ipconfig_indicate_state(service, @@ -149,14 +150,20 @@ static void dhcp_success(struct connman_network *network) int err; service = connman_service_lookup_from_network(network); - if (service == NULL) + if (!service) goto err; - connman_network_set_associating(network, FALSE); + connman_network_set_associating(network, false); - network->connecting = FALSE; + network->connecting = false; ipconfig_ipv4 = __connman_service_get_ip4config(service); + + DBG("lease acquired for ipconfig %p", ipconfig_ipv4); + + if (!ipconfig_ipv4) + return; + err = __connman_ipconfig_address_add(ipconfig_ipv4); if (err < 0) goto err; @@ -175,22 +182,30 @@ err: static void dhcp_failure(struct connman_network *network) { struct connman_service *service; + struct connman_ipconfig *ipconfig_ipv4; service = connman_service_lookup_from_network(network); - if (service == NULL) + if (!service) return; - __connman_service_ipconfig_indicate_state(service, - CONNMAN_SERVICE_STATE_IDLE, - CONNMAN_IPCONFIG_TYPE_IPV4); + connman_network_set_associating(network, false); + network->connecting = false; + + ipconfig_ipv4 = __connman_service_get_ip4config(service); + + DBG("lease lost for ipconfig %p", ipconfig_ipv4); + + if (!ipconfig_ipv4) + return; + + __connman_ipconfig_address_remove(ipconfig_ipv4); + __connman_ipconfig_gateway_remove(ipconfig_ipv4); } static void dhcp_callback(struct connman_network *network, - connman_bool_t success) + bool success, gpointer data) { - DBG("success %d", success); - - if (success == TRUE) + if (success) dhcp_success(network); else dhcp_failure(network); @@ -210,9 +225,9 @@ static int set_connected_fixed(struct connman_network *network) set_configuration(network, CONNMAN_IPCONFIG_TYPE_IPV4); - network->connecting = FALSE; + network->connecting = false; - connman_network_set_associating(network, FALSE); + connman_network_set_associating(network, false); err = __connman_ipconfig_address_add(ipconfig_ipv4); if (err < 0) @@ -243,7 +258,7 @@ static void set_connected_manual(struct connman_network *network) ipconfig = __connman_service_get_ip4config(service); - if (__connman_ipconfig_get_local(ipconfig) == NULL) + if (!__connman_ipconfig_get_local(ipconfig)) __connman_service_read_ip4config(service); set_configuration(network, CONNMAN_IPCONFIG_TYPE_IPV4); @@ -256,9 +271,9 @@ static void set_connected_manual(struct connman_network *network) if (err < 0) goto err; - network->connecting = FALSE; + network->connecting = false; - connman_network_set_associating(network, FALSE); + connman_network_set_associating(network, false); return; @@ -294,10 +309,10 @@ static int manual_ipv6_set(struct connman_network *network, DBG("network %p ipv6 %p", network, ipconfig_ipv6); service = connman_service_lookup_from_network(network); - if (service == NULL) + if (!service) return -EINVAL; - if (__connman_ipconfig_get_local(ipconfig_ipv6) == NULL) + if (!__connman_ipconfig_get_local(ipconfig_ipv6)) __connman_service_read_ip6config(service); __connman_ipconfig_enable_ipv6(ipconfig_ipv6); @@ -318,9 +333,9 @@ static int manual_ipv6_set(struct connman_network *network, __connman_device_set_network(network->device, network); - connman_device_set_disconnected(network->device, FALSE); + connman_device_set_disconnected(network->device, false); - network->connecting = FALSE; + network->connecting = false; return 0; } @@ -331,9 +346,10 @@ static void stop_dhcpv6(struct connman_network *network) } static void dhcpv6_release_callback(struct connman_network *network, - connman_bool_t success) + enum __connman_dhcpv6_status status, + gpointer data) { - DBG("success %d", success); + DBG("status %d", status); stop_dhcpv6(network); } @@ -345,26 +361,27 @@ static void release_dhcpv6(struct connman_network *network) } static void dhcpv6_info_callback(struct connman_network *network, - connman_bool_t success) + enum __connman_dhcpv6_status status, + gpointer data) { - DBG("success %d", success); + DBG("status %d", status); stop_dhcpv6(network); } -static gboolean dhcpv6_set_addresses(struct connman_network *network) +static int dhcpv6_set_addresses(struct connman_network *network) { struct connman_service *service; struct connman_ipconfig *ipconfig_ipv6; int err = -EINVAL; service = connman_service_lookup_from_network(network); - if (service == NULL) + if (!service) goto err; - connman_network_set_associating(network, FALSE); + connman_network_set_associating(network, false); - network->connecting = FALSE; + network->connecting = false; ipconfig_ipv6 = __connman_service_get_ip6config(service); err = __connman_ipconfig_address_add(ipconfig_ipv6); @@ -385,7 +402,7 @@ err: static void autoconf_ipv6_set(struct connman_network *network); static void dhcpv6_callback(struct connman_network *network, - connman_bool_t success); + enum __connman_dhcpv6_status status, gpointer data); /* * Have a separate callback for renew so that we do not do autoconf @@ -393,25 +410,30 @@ static void dhcpv6_callback(struct connman_network *network, * DHCPv6 solicitation. */ static void dhcpv6_renew_callback(struct connman_network *network, - connman_bool_t success) + enum __connman_dhcpv6_status status, + gpointer data) { - if (success == TRUE) - dhcpv6_callback(network, success); - else { + switch (status) { + case CONNMAN_DHCPV6_STATUS_SUCCEED: + dhcpv6_callback(network, status, data); + break; + case CONNMAN_DHCPV6_STATUS_FAIL: + case CONNMAN_DHCPV6_STATUS_RESTART: stop_dhcpv6(network); /* restart and do solicit again. */ autoconf_ipv6_set(network); + break; } } static void dhcpv6_callback(struct connman_network *network, - connman_bool_t success) + enum __connman_dhcpv6_status status, gpointer data) { - DBG("success %d", success); + DBG("status %d", status); /* Start the renew process if necessary */ - if (success == TRUE) { + if (status == CONNMAN_DHCPV6_STATUS_SUCCEED) { if (dhcpv6_set_addresses(network) < 0) { stop_dhcpv6(network); @@ -420,7 +442,13 @@ static void dhcpv6_callback(struct connman_network *network, if (__connman_dhcpv6_start_renew(network, dhcpv6_renew_callback) == -ETIMEDOUT) - dhcpv6_renew_callback(network, FALSE); + dhcpv6_renew_callback(network, + CONNMAN_DHCPV6_STATUS_FAIL, + data); + + } else if (status == CONNMAN_DHCPV6_STATUS_RESTART) { + stop_dhcpv6(network); + autoconf_ipv6_set(network); } else stop_dhcpv6(network); } @@ -433,7 +461,7 @@ static void check_dhcpv6(struct nd_router_advert *reply, DBG("reply %p", reply); - if (reply == NULL) { + if (!reply) { /* * Router solicitation message seem to get lost easily so * try to send it again. @@ -456,7 +484,7 @@ static void check_dhcpv6(struct nd_router_advert *reply, * If we were disconnected while waiting router advertisement, * we just quit and do not start DHCPv6 */ - if (network->connected == FALSE) { + if (!network->connected) { connman_network_unref(network); return; } @@ -481,7 +509,7 @@ static void receive_refresh_rs_reply(struct nd_router_advert *reply, DBG("reply %p", reply); - if (reply == NULL) { + if (!reply) { /* * Router solicitation message seem to get lost easily so * try to send it again. @@ -505,7 +533,8 @@ static void receive_refresh_rs_reply(struct nd_router_advert *reply, return; } -int __connman_refresh_rs_ipv6(struct connman_network *network, int index) +int __connman_network_refresh_rs_ipv6(struct connman_network *network, + int index) { int ret = 0; @@ -546,16 +575,16 @@ static void autoconf_ipv6_set(struct connman_network *network) __connman_device_set_network(network->device, network); - connman_device_set_disconnected(network->device, FALSE); + connman_device_set_disconnected(network->device, false); - network->connecting = FALSE; + network->connecting = false; service = connman_service_lookup_from_network(network); - if (service == NULL) + if (!service) return; ipconfig = __connman_service_get_ip6config(service); - if (ipconfig == NULL) + if (!ipconfig) return; index = __connman_ipconfig_get_index(ipconfig); @@ -574,10 +603,10 @@ static void set_connected(struct connman_network *network) struct connman_service *service; int ret; - if (network->connected == TRUE) + if (network->connected) return; - network->connected = TRUE; + network->connected = true; service = connman_service_lookup_from_network(network); @@ -634,9 +663,9 @@ static void set_connected(struct connman_network *network) } } - network->connecting = FALSE; + network->connecting = false; - connman_network_set_associating(network, FALSE); + connman_network_set_associating(network, false); } static void set_disconnected(struct connman_network *network) @@ -646,11 +675,6 @@ static void set_disconnected(struct connman_network *network) enum connman_service_state state; struct connman_service *service; - if (network->connected == FALSE) - return; - - network->connected = FALSE; - service = connman_service_lookup_from_network(network); ipconfig_ipv4 = __connman_service_get_ip4config(service); @@ -672,28 +696,30 @@ static void set_disconnected(struct connman_network *network) __connman_device_set_network(network->device, NULL); - switch (ipv6_method) { - case CONNMAN_IPCONFIG_METHOD_UNKNOWN: - case CONNMAN_IPCONFIG_METHOD_OFF: - case CONNMAN_IPCONFIG_METHOD_FIXED: - case CONNMAN_IPCONFIG_METHOD_MANUAL: - break; - case CONNMAN_IPCONFIG_METHOD_DHCP: - case CONNMAN_IPCONFIG_METHOD_AUTO: - release_dhcpv6(network); - break; - } + if (network->connected) { + switch (ipv6_method) { + case CONNMAN_IPCONFIG_METHOD_UNKNOWN: + case CONNMAN_IPCONFIG_METHOD_OFF: + case CONNMAN_IPCONFIG_METHOD_FIXED: + case CONNMAN_IPCONFIG_METHOD_MANUAL: + break; + case CONNMAN_IPCONFIG_METHOD_DHCP: + case CONNMAN_IPCONFIG_METHOD_AUTO: + release_dhcpv6(network); + break; + } - switch (ipv4_method) { - case CONNMAN_IPCONFIG_METHOD_UNKNOWN: - case CONNMAN_IPCONFIG_METHOD_OFF: - case CONNMAN_IPCONFIG_METHOD_AUTO: - case CONNMAN_IPCONFIG_METHOD_FIXED: - case CONNMAN_IPCONFIG_METHOD_MANUAL: - break; - case CONNMAN_IPCONFIG_METHOD_DHCP: - __connman_dhcp_stop(network); - break; + switch (ipv4_method) { + case CONNMAN_IPCONFIG_METHOD_UNKNOWN: + case CONNMAN_IPCONFIG_METHOD_OFF: + case CONNMAN_IPCONFIG_METHOD_AUTO: + case CONNMAN_IPCONFIG_METHOD_FIXED: + case CONNMAN_IPCONFIG_METHOD_MANUAL: + break; + case CONNMAN_IPCONFIG_METHOD_DHCP: + __connman_dhcp_stop(network); + break; + } } /* @@ -717,21 +743,23 @@ static void set_disconnected(struct connman_network *network) CONNMAN_SERVICE_STATE_DISCONNECT, CONNMAN_IPCONFIG_TYPE_IPV6); - __connman_connection_gateway_remove(service, - CONNMAN_IPCONFIG_TYPE_ALL); + if (network->connected) { + __connman_connection_gateway_remove(service, + CONNMAN_IPCONFIG_TYPE_ALL); - __connman_ipconfig_address_unset(ipconfig_ipv4); - __connman_ipconfig_address_unset(ipconfig_ipv6); + __connman_ipconfig_address_unset(ipconfig_ipv4); + __connman_ipconfig_address_unset(ipconfig_ipv6); - /* - * Special handling for IPv6 autoconfigured address. - * The simplest way to remove autoconfigured routes is to - * disable IPv6 temporarily so that kernel will do the cleanup - * automagically. - */ - if (ipv6_method == CONNMAN_IPCONFIG_METHOD_AUTO) { - __connman_ipconfig_disable_ipv6(ipconfig_ipv6); - __connman_ipconfig_enable_ipv6(ipconfig_ipv6); + /* + * Special handling for IPv6 autoconfigured address. + * The simplest way to remove autoconfigured routes is to + * disable IPv6 temporarily so that kernel will do the cleanup + * automagically. + */ + if (ipv6_method == CONNMAN_IPCONFIG_METHOD_AUTO) { + __connman_ipconfig_disable_ipv6(ipconfig_ipv6); + __connman_ipconfig_enable_ipv6(ipconfig_ipv6); + } } __connman_service_ipconfig_indicate_state(service, @@ -742,9 +770,10 @@ static void set_disconnected(struct connman_network *network) CONNMAN_SERVICE_STATE_IDLE, CONNMAN_IPCONFIG_TYPE_IPV6); - network->connecting = FALSE; + network->connecting = false; + network->connected = false; - connman_network_set_associating(network, FALSE); + connman_network_set_associating(network, false); } @@ -756,13 +785,13 @@ static int network_probe(struct connman_network *network) DBG("network %p name %s", network, network->name); - if (network->driver != NULL) + if (network->driver) return -EALREADY; for (list = driver_list; list; list = list->next) { driver = list->data; - if (match_driver(network, driver) == FALSE) { + if (!match_driver(network, driver)) { driver = NULL; continue; } @@ -775,10 +804,10 @@ static int network_probe(struct connman_network *network) driver = NULL; } - if (driver == NULL) + if (!driver) return -ENODEV; - if (network->group == NULL) + if (!network->group) return -EINVAL; switch (network->type) { @@ -786,12 +815,13 @@ static int network_probe(struct connman_network *network) case CONNMAN_NETWORK_TYPE_VENDOR: return 0; case CONNMAN_NETWORK_TYPE_ETHERNET: + case CONNMAN_NETWORK_TYPE_GADGET: case CONNMAN_NETWORK_TYPE_BLUETOOTH_PAN: case CONNMAN_NETWORK_TYPE_BLUETOOTH_DUN: case CONNMAN_NETWORK_TYPE_CELLULAR: case CONNMAN_NETWORK_TYPE_WIFI: network->driver = driver; - if (__connman_service_create_from_network(network) == NULL) { + if (!__connman_service_create_from_network(network)) { network->driver = NULL; return -EINVAL; } @@ -804,10 +834,10 @@ static void network_remove(struct connman_network *network) { DBG("network %p name %s", network, network->name); - if (network->driver == NULL) + if (!network->driver) return; - if (network->connected == TRUE) + if (network->connected) set_disconnected(network); switch (network->type) { @@ -815,11 +845,12 @@ static void network_remove(struct connman_network *network) case CONNMAN_NETWORK_TYPE_VENDOR: break; case CONNMAN_NETWORK_TYPE_ETHERNET: + case CONNMAN_NETWORK_TYPE_GADGET: case CONNMAN_NETWORK_TYPE_BLUETOOTH_PAN: case CONNMAN_NETWORK_TYPE_BLUETOOTH_DUN: case CONNMAN_NETWORK_TYPE_CELLULAR: case CONNMAN_NETWORK_TYPE_WIFI: - if (network->group != NULL) { + if (network->group) { __connman_service_remove_from_network(network); g_free(network->group); @@ -838,17 +869,17 @@ static void network_change(struct connman_network *network) { DBG("network %p name %s", network, network->name); - if (network->connected == FALSE) + if (!network->connected) return; - connman_device_set_disconnected(network->device, TRUE); + connman_device_set_disconnected(network->device, true); if (network->driver && network->driver->disconnect) { network->driver->disconnect(network); return; } - network->connected = FALSE; + network->connected = false; } static void probe_driver(struct connman_network_driver *driver) @@ -857,10 +888,10 @@ static void probe_driver(struct connman_network_driver *driver) DBG("driver %p name %s", driver, driver->name); - for (list = network_list; list != NULL; list = list->next) { + for (list = network_list; list; list = list->next) { struct connman_network *network = list->data; - if (network->driver != NULL) + if (network->driver) continue; if (driver->type != network->type) @@ -879,7 +910,7 @@ static void remove_driver(struct connman_network_driver *driver) DBG("driver %p name %s", driver, driver->name); - for (list = network_list; list != NULL; list = list->next) { + for (list = network_list; list; list = list->next) { struct connman_network *network = list->data; if (network->driver == driver) @@ -938,7 +969,6 @@ static void network_destruct(struct connman_network *network) g_free(network->wifi.mode); g_free(network->wifi.security); g_free(network->wifi.passphrase); - g_free(network->wifi.agent_passphrase); g_free(network->wifi.eap); g_free(network->wifi.identity); g_free(network->wifi.agent_identity); @@ -977,7 +1007,7 @@ struct connman_network *connman_network_create(const char *identifier, DBG("identifier %s type %d", identifier, type); network = g_try_new0(struct connman_network, 1); - if (network == NULL) + if (!network) return NULL; DBG("network %p", network); @@ -986,7 +1016,7 @@ struct connman_network *connman_network_create(const char *identifier, ident = g_strdup(identifier); - if (ident == NULL) { + if (!ident) { g_free(network); return NULL; } @@ -1048,7 +1078,8 @@ const char *__connman_network_get_type(struct connman_network *network) * * Get type of network */ -enum connman_network_type connman_network_get_type(struct connman_network *network) +enum connman_network_type connman_network_get_type( + struct connman_network *network) { return network->type; } @@ -1077,11 +1108,11 @@ void connman_network_set_index(struct connman_network *network, int index) struct connman_ipconfig *ipconfig; service = connman_service_lookup_from_network(network); - if (service == NULL) + if (!service) goto done; ipconfig = __connman_service_get_ip4config(service); - if (ipconfig == NULL) + if (!ipconfig) goto done; /* If index changed, the index of ipconfig must be reset. */ @@ -1119,6 +1150,7 @@ void connman_network_set_group(struct connman_network *network, case CONNMAN_NETWORK_TYPE_VENDOR: return; case CONNMAN_NETWORK_TYPE_ETHERNET: + case CONNMAN_NETWORK_TYPE_GADGET: case CONNMAN_NETWORK_TYPE_BLUETOOTH_PAN: case CONNMAN_NETWORK_TYPE_BLUETOOTH_DUN: case CONNMAN_NETWORK_TYPE_CELLULAR: @@ -1127,12 +1159,12 @@ void connman_network_set_group(struct connman_network *network, } if (g_strcmp0(network->group, group) == 0) { - if (group != NULL) + if (group) __connman_service_update_from_network(network); return; } - if (network->group != NULL) { + if (network->group) { __connman_service_remove_from_network(network); g_free(network->group); @@ -1140,7 +1172,7 @@ void connman_network_set_group(struct connman_network *network, network->group = g_strdup(group); - if (network->group != NULL) + if (network->group) network_probe(network); } @@ -1157,34 +1189,33 @@ const char *connman_network_get_group(struct connman_network *network) const char *__connman_network_get_ident(struct connman_network *network) { - if (network->device == NULL) + if (!network->device) return NULL; return connman_device_get_ident(network->device); } -connman_bool_t __connman_network_get_weakness(struct connman_network *network) +bool __connman_network_get_weakness(struct connman_network *network) { switch (network->type) { case CONNMAN_NETWORK_TYPE_UNKNOWN: case CONNMAN_NETWORK_TYPE_VENDOR: case CONNMAN_NETWORK_TYPE_ETHERNET: + case CONNMAN_NETWORK_TYPE_GADGET: case CONNMAN_NETWORK_TYPE_BLUETOOTH_PAN: case CONNMAN_NETWORK_TYPE_BLUETOOTH_DUN: case CONNMAN_NETWORK_TYPE_CELLULAR: break; case CONNMAN_NETWORK_TYPE_WIFI: - if (g_strcmp0(network->wifi.mode, "adhoc") == 0) - return TRUE; if (network->strength > 0 && network->strength < 20) - return TRUE; + return true; break; } - return FALSE; + return false; } -connman_bool_t connman_network_get_connecting(struct connman_network *network) +bool connman_network_get_connecting(struct connman_network *network) { return network->connecting; } @@ -1197,7 +1228,7 @@ connman_bool_t connman_network_get_connecting(struct connman_network *network) * Change availability state of network (in range) */ int connman_network_set_available(struct connman_network *network, - connman_bool_t available) + bool available) { DBG("network %p available %d", network, available); @@ -1215,7 +1246,7 @@ int connman_network_set_available(struct connman_network *network, * * Get network available setting */ -connman_bool_t connman_network_get_available(struct connman_network *network) +bool connman_network_get_available(struct connman_network *network) { return network->available; } @@ -1228,7 +1259,7 @@ connman_bool_t connman_network_get_available(struct connman_network *network) * Change associating state of network */ int connman_network_set_associating(struct connman_network *network, - connman_bool_t associating) + bool associating) { DBG("network %p associating %d", network, associating); @@ -1237,7 +1268,7 @@ int connman_network_set_associating(struct connman_network *network, network->associating = associating; - if (associating == TRUE) { + if (associating) { struct connman_service *service; service = connman_service_lookup_from_network(network); @@ -1299,11 +1330,11 @@ void connman_network_set_ipv4_method(struct connman_network *network, struct connman_ipconfig *ipconfig; service = connman_service_lookup_from_network(network); - if (service == NULL) + if (!service) return; ipconfig = __connman_service_get_ip4config(service); - if (ipconfig == NULL) + if (!ipconfig) return; __connman_ipconfig_set_method(ipconfig, method); @@ -1316,11 +1347,11 @@ void connman_network_set_ipv6_method(struct connman_network *network, struct connman_ipconfig *ipconfig; service = connman_service_lookup_from_network(network); - if (service == NULL) + if (!service) return; ipconfig = __connman_service_get_ip6config(service); - if (ipconfig == NULL) + if (!ipconfig) return; __connman_ipconfig_set_method(ipconfig, method); @@ -1331,8 +1362,8 @@ void connman_network_set_error(struct connman_network *network, { DBG("network %p error %d", network, error); - network->connecting = FALSE; - network->associating = FALSE; + network->connecting = false; + network->associating = false; switch (error) { case CONNMAN_NETWORK_ERROR_UNKNOWN: @@ -1360,10 +1391,10 @@ void connman_network_clear_error(struct connman_network *network) DBG("network %p", network); - if (network == NULL) + if (!network) return; - if (network->connecting == TRUE || network->associating == TRUE) + if (network->connecting || network->associating) return; service = connman_service_lookup_from_network(network); @@ -1378,14 +1409,14 @@ void connman_network_clear_error(struct connman_network *network) * Change connected state of network */ int connman_network_set_connected(struct connman_network *network, - connman_bool_t connected) + bool connected) { DBG("network %p connected %d/%d connecting %d associating %d", network, network->connected, connected, network->connecting, network->associating); - if ((network->connecting == TRUE || network->associating == TRUE) && - connected == FALSE) { + if ((network->connecting || network->associating) && + !connected) { connman_network_set_error(network, CONNMAN_NETWORK_ERROR_CONNECT_FAIL); if (__connman_network_disconnect(network) == 0) @@ -1395,7 +1426,7 @@ int connman_network_set_connected(struct connman_network *network, if (network->connected == connected) return -EALREADY; - if (connected == FALSE) + if (!connected) set_disconnected(network); else set_connected(network); @@ -1409,7 +1440,7 @@ int connman_network_set_connected(struct connman_network *network, * * Get network connection status */ -connman_bool_t connman_network_get_connected(struct connman_network *network) +bool connman_network_get_connected(struct connman_network *network) { return network->connected; } @@ -1420,14 +1451,14 @@ connman_bool_t connman_network_get_connected(struct connman_network *network) * * Get network associating status */ -connman_bool_t connman_network_get_associating(struct connman_network *network) +bool connman_network_get_associating(struct connman_network *network) { return network->associating; } void connman_network_clear_hidden(void *user_data) { - if (user_data == NULL) + if (!user_data) return; DBG("user_data %p", user_data); @@ -1442,7 +1473,7 @@ void connman_network_clear_hidden(void *user_data) } int connman_network_connect_hidden(struct connman_network *network, - char *identity, char* passphrase, void *user_data) + char *identity, char *passphrase, void *user_data) { int err = 0; struct connman_service *service; @@ -1451,15 +1482,13 @@ int connman_network_connect_hidden(struct connman_network *network, DBG("network %p service %p user_data %p", network, service, user_data); - if (service == NULL) { - err = -EINVAL; - goto out; - } + if (!service) + return -EINVAL; - if (identity != NULL) + if (identity) __connman_service_set_agent_identity(service, identity); - if (passphrase != NULL) + if (passphrase) err = __connman_service_add_passphrase(service, passphrase); if (err == -ENOKEY) { @@ -1468,9 +1497,9 @@ int connman_network_connect_hidden(struct connman_network *network, goto out; } else { __connman_service_set_hidden(service); - __connman_service_set_userconnect(service, TRUE); __connman_service_set_hidden_data(service, user_data); - return __connman_service_connect(service); + return __connman_service_connect(service, + CONNMAN_SERVICE_CONNECT_REASON_USER); } out: @@ -1490,32 +1519,31 @@ int __connman_network_connect(struct connman_network *network) DBG("network %p", network); - if (network->connected == TRUE) + if (network->connected) return -EISCONN; - if (network->connecting == TRUE || network->associating == TRUE) + if (network->connecting || network->associating) return -EALREADY; - if (network->driver == NULL) + if (!network->driver) return -EUNATCH; - if (network->driver->connect == NULL) + if (!network->driver->connect) return -ENOSYS; - if (network->device == NULL) + if (!network->device) return -ENODEV; - network->connecting = TRUE; + network->connecting = true; __connman_device_disconnect(network->device); err = network->driver->connect(network); if (err < 0) { if (err == -EINPROGRESS) - connman_network_set_associating(network, TRUE); - else { - network->connecting = FALSE; - } + connman_network_set_associating(network, true); + else + network->connecting = false; return err; } @@ -1533,24 +1561,23 @@ int __connman_network_connect(struct connman_network *network) */ int __connman_network_disconnect(struct connman_network *network) { - int err; + int err = 0; DBG("network %p", network); - if (network->connected == FALSE && network->connecting == FALSE && - network->associating == FALSE) + if (!network->connected && !network->connecting && + !network->associating) return -ENOTCONN; - if (network->driver == NULL) + if (!network->driver) return -EUNATCH; - if (network->driver->disconnect == NULL) - return -ENOSYS; + network->connecting = false; - network->connecting = FALSE; + if (network->driver->disconnect) + err = network->driver->disconnect(network); - err = network->driver->disconnect(network); - if (err == 0) + if (err != -EINPROGRESS) set_disconnected(network); return err; @@ -1563,7 +1590,7 @@ static int manual_ipv4_set(struct connman_network *network, int err; service = connman_service_lookup_from_network(network); - if (service == NULL) + if (!service) return -EINVAL; err = __connman_ipconfig_address_add(ipconfig); @@ -1584,7 +1611,7 @@ int __connman_network_clear_ipconfig(struct connman_network *network, enum connman_ipconfig_type type; service = connman_service_lookup_from_network(network); - if (service == NULL) + if (!service) return -EINVAL; method = __connman_ipconfig_get_method(ipconfig); @@ -1625,7 +1652,7 @@ int __connman_network_set_ipconfig(struct connman_network *network, enum connman_ipconfig_method method; int ret; - if (network == NULL) + if (!network) return -EINVAL; if (ipconfig_ipv6) { @@ -1680,11 +1707,11 @@ int connman_network_set_ipaddress(struct connman_network *network, DBG("network %p", network); service = connman_service_lookup_from_network(network); - if (service == NULL) + if (!service) return -EINVAL; ipconfig = __connman_service_get_ipconfig(service, ipaddress->family); - if (ipconfig == NULL) + if (!ipconfig) return -EINVAL; __connman_ipconfig_set_local(ipconfig, ipaddress->local); @@ -1706,19 +1733,19 @@ int connman_network_set_nameservers(struct connman_network *network, DBG("network %p nameservers %s", network, nameservers); service = connman_service_lookup_from_network(network); - if (service == NULL) + if (!service) return -EINVAL; __connman_service_nameserver_clear(service); - if (nameservers == NULL) + if (!nameservers) return 0; nameservers_array = g_strsplit(nameservers, " ", 0); - for (i = 0; nameservers_array[i] != NULL; i++) { + for (i = 0; nameservers_array[i]; i++) { __connman_service_nameserver_append(service, - nameservers_array[i], FALSE); + nameservers_array[i], false); } g_strfreev(nameservers_array); @@ -1734,7 +1761,7 @@ int connman_network_set_domain(struct connman_network *network, DBG("network %p domain %s", network, domain); service = connman_service_lookup_from_network(network); - if (service == NULL) + if (!service) return -EINVAL; __connman_service_set_domainname(service, domain); @@ -1829,49 +1856,46 @@ int connman_network_set_string(struct connman_network *network, if (g_strcmp0(key, "Name") == 0) return connman_network_set_name(network, value); - if (g_str_equal(key, "Path") == TRUE) { + if (g_str_equal(key, "Path")) { g_free(network->path); network->path = g_strdup(value); - } else if (g_str_equal(key, "Node") == TRUE) { + } else if (g_str_equal(key, "Node")) { g_free(network->node); network->node = g_strdup(value); - } else if (g_str_equal(key, "WiFi.Mode") == TRUE) { + } else if (g_str_equal(key, "WiFi.Mode")) { g_free(network->wifi.mode); network->wifi.mode = g_strdup(value); - } else if (g_str_equal(key, "WiFi.Security") == TRUE) { + } else if (g_str_equal(key, "WiFi.Security")) { g_free(network->wifi.security); network->wifi.security = g_strdup(value); - } else if (g_str_equal(key, "WiFi.Passphrase") == TRUE) { + } else if (g_str_equal(key, "WiFi.Passphrase")) { g_free(network->wifi.passphrase); network->wifi.passphrase = g_strdup(value); - } else if (g_str_equal(key, "WiFi.AgentPassphrase") == TRUE) { - g_free(network->wifi.agent_passphrase); - network->wifi.agent_passphrase = g_strdup(value); - } else if (g_str_equal(key, "WiFi.EAP") == TRUE) { + } else if (g_str_equal(key, "WiFi.EAP")) { g_free(network->wifi.eap); network->wifi.eap = g_strdup(value); - } else if (g_str_equal(key, "WiFi.Identity") == TRUE) { + } else if (g_str_equal(key, "WiFi.Identity")) { g_free(network->wifi.identity); network->wifi.identity = g_strdup(value); - } else if (g_str_equal(key, "WiFi.AgentIdentity") == TRUE) { + } else if (g_str_equal(key, "WiFi.AgentIdentity")) { g_free(network->wifi.agent_identity); network->wifi.agent_identity = g_strdup(value); - } else if (g_str_equal(key, "WiFi.CACertFile") == TRUE) { + } else if (g_str_equal(key, "WiFi.CACertFile")) { g_free(network->wifi.ca_cert_path); network->wifi.ca_cert_path = g_strdup(value); - } else if (g_str_equal(key, "WiFi.ClientCertFile") == TRUE) { + } else if (g_str_equal(key, "WiFi.ClientCertFile")) { g_free(network->wifi.client_cert_path); network->wifi.client_cert_path = g_strdup(value); - } else if (g_str_equal(key, "WiFi.PrivateKeyFile") == TRUE) { + } else if (g_str_equal(key, "WiFi.PrivateKeyFile")) { g_free(network->wifi.private_key_path); network->wifi.private_key_path = g_strdup(value); - } else if (g_str_equal(key, "WiFi.PrivateKeyPassphrase") == TRUE) { + } else if (g_str_equal(key, "WiFi.PrivateKeyPassphrase")) { g_free(network->wifi.private_key_passphrase); network->wifi.private_key_passphrase = g_strdup(value); - } else if (g_str_equal(key, "WiFi.Phase2") == TRUE) { + } else if (g_str_equal(key, "WiFi.Phase2")) { g_free(network->wifi.phase2_auth); network->wifi.phase2_auth = g_strdup(value); - } else if (g_str_equal(key, "WiFi.PinWPS") == TRUE) { + } else if (g_str_equal(key, "WiFi.PinWPS")) { g_free(network->wifi.pin_wps); network->wifi.pin_wps = g_strdup(value); } else { @@ -1893,37 +1917,35 @@ const char *connman_network_get_string(struct connman_network *network, { DBG("network %p key %s", network, key); - if (g_str_equal(key, "Path") == TRUE) + if (g_str_equal(key, "Path")) return network->path; - else if (g_str_equal(key, "Name") == TRUE) + else if (g_str_equal(key, "Name")) return network->name; - else if (g_str_equal(key, "Node") == TRUE) + else if (g_str_equal(key, "Node")) return network->node; - else if (g_str_equal(key, "WiFi.Mode") == TRUE) + else if (g_str_equal(key, "WiFi.Mode")) return network->wifi.mode; - else if (g_str_equal(key, "WiFi.Security") == TRUE) + else if (g_str_equal(key, "WiFi.Security")) return network->wifi.security; - else if (g_str_equal(key, "WiFi.Passphrase") == TRUE) + else if (g_str_equal(key, "WiFi.Passphrase")) return network->wifi.passphrase; - else if (g_str_equal(key, "WiFi.AgentPassphrase") == TRUE) - return network->wifi.agent_passphrase; - else if (g_str_equal(key, "WiFi.EAP") == TRUE) + else if (g_str_equal(key, "WiFi.EAP")) return network->wifi.eap; - else if (g_str_equal(key, "WiFi.Identity") == TRUE) + else if (g_str_equal(key, "WiFi.Identity")) return network->wifi.identity; - else if (g_str_equal(key, "WiFi.AgentIdentity") == TRUE) + else if (g_str_equal(key, "WiFi.AgentIdentity")) return network->wifi.agent_identity; - else if (g_str_equal(key, "WiFi.CACertFile") == TRUE) + else if (g_str_equal(key, "WiFi.CACertFile")) return network->wifi.ca_cert_path; - else if (g_str_equal(key, "WiFi.ClientCertFile") == TRUE) + else if (g_str_equal(key, "WiFi.ClientCertFile")) return network->wifi.client_cert_path; - else if (g_str_equal(key, "WiFi.PrivateKeyFile") == TRUE) + else if (g_str_equal(key, "WiFi.PrivateKeyFile")) return network->wifi.private_key_path; - else if (g_str_equal(key, "WiFi.PrivateKeyPassphrase") == TRUE) + else if (g_str_equal(key, "WiFi.PrivateKeyPassphrase")) return network->wifi.private_key_passphrase; - else if (g_str_equal(key, "WiFi.Phase2") == TRUE) + else if (g_str_equal(key, "WiFi.Phase2")) return network->wifi.phase2_auth; - else if (g_str_equal(key, "WiFi.PinWPS") == TRUE) + else if (g_str_equal(key, "WiFi.PinWPS")) return network->wifi.pin_wps; return NULL; @@ -1938,7 +1960,7 @@ const char *connman_network_get_string(struct connman_network *network, * Set boolean value for specific key */ int connman_network_set_bool(struct connman_network *network, - const char *key, connman_bool_t value) + const char *key, bool value) { DBG("network %p key %s value %d", network, key, value); @@ -1959,19 +1981,19 @@ int connman_network_set_bool(struct connman_network *network, * * Get boolean value for specific key */ -connman_bool_t connman_network_get_bool(struct connman_network *network, +bool connman_network_get_bool(struct connman_network *network, const char *key) { DBG("network %p key %s", network, key); - if (g_str_equal(key, "Roaming") == TRUE) + if (g_str_equal(key, "Roaming")) return network->roaming; - else if (g_str_equal(key, "WiFi.WPS") == TRUE) + else if (g_str_equal(key, "WiFi.WPS")) return network->wifi.wps; - else if (g_str_equal(key, "WiFi.UseWPS") == TRUE) + else if (g_str_equal(key, "WiFi.UseWPS")) return network->wifi.use_wps; - return FALSE; + return false; } /** @@ -1988,10 +2010,10 @@ int connman_network_set_blob(struct connman_network *network, { DBG("network %p key %s size %d", network, key, size); - if (g_str_equal(key, "WiFi.SSID") == TRUE) { + if (g_str_equal(key, "WiFi.SSID")) { g_free(network->wifi.ssid); network->wifi.ssid = g_try_malloc(size); - if (network->wifi.ssid != NULL) { + if (network->wifi.ssid) { memcpy(network->wifi.ssid, data, size); network->wifi.ssid_len = size; } else @@ -2016,8 +2038,8 @@ const void *connman_network_get_blob(struct connman_network *network, { DBG("network %p key %s", network, key); - if (g_str_equal(key, "WiFi.SSID") == TRUE) { - if (size != NULL) + if (g_str_equal(key, "WiFi.SSID")) { + if (size) *size = network->wifi.ssid_len; return network->wifi.ssid; } @@ -2031,12 +2053,12 @@ void __connman_network_set_device(struct connman_network *network, if (network->device == device) return; - if (network->device != NULL) + if (network->device) network_remove(network); network->device = device; - if (network->device != NULL) + if (network->device) network_probe(network); } @@ -2081,6 +2103,7 @@ void connman_network_update(struct connman_network *network) case CONNMAN_NETWORK_TYPE_VENDOR: return; case CONNMAN_NETWORK_TYPE_ETHERNET: + case CONNMAN_NETWORK_TYPE_GADGET: case CONNMAN_NETWORK_TYPE_BLUETOOTH_PAN: case CONNMAN_NETWORK_TYPE_BLUETOOTH_DUN: case CONNMAN_NETWORK_TYPE_CELLULAR: @@ -2088,7 +2111,7 @@ void connman_network_update(struct connman_network *network) break; } - if (network->group != NULL) + if (network->group) __connman_service_update_from_network(network); } diff --git a/src/notifier.c b/src/notifier.c index 623b970b..5ba53242 100644 --- a/src/notifier.c +++ b/src/notifier.c @@ -2,7 +2,7 @@ * * Connection Manager * - * Copyright (C) 2007-2012 Intel Corporation. All rights reserved. + * Copyright (C) 2007-2013 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 @@ -73,46 +73,44 @@ void connman_notifier_unregister(struct connman_notifier *notifier) notifier_list = g_slist_remove(notifier_list, notifier); } -#define MAX_TECHNOLOGIES 10 +static int connected[MAX_CONNMAN_SERVICE_TYPES]; +static int online[MAX_CONNMAN_SERVICE_TYPES]; -static int connected[MAX_TECHNOLOGIES]; -static int online[MAX_TECHNOLOGIES]; - -static connman_bool_t notifier_is_online(void) +static bool notifier_is_online(void) { unsigned int i; __sync_synchronize(); - for (i = 0; i < MAX_TECHNOLOGIES; i++) { + for (i = 0; i < MAX_CONNMAN_SERVICE_TYPES; i++) { if (online[i] > 0) - return TRUE; + return true; } - return FALSE; + return false; } -connman_bool_t __connman_notifier_is_connected(void) +bool __connman_notifier_is_connected(void) { unsigned int i; __sync_synchronize(); - for (i = 0; i < MAX_TECHNOLOGIES; i++) { + for (i = 0; i < MAX_CONNMAN_SERVICE_TYPES; i++) { if (connected[i] > 0) - return TRUE; + return true; } - return FALSE; + return false; } static const char *evaluate_notifier_state(void) { - if (notifier_is_online() == TRUE) + if (notifier_is_online()) return "online"; - if (__connman_notifier_is_connected() == TRUE) + if (__connman_notifier_is_connected()) return "ready"; - if ( __connman_technology_get_offlinemode() == TRUE) + if (__connman_technology_get_offlinemode()) return "offline"; return "idle"; @@ -148,17 +146,18 @@ void __connman_notifier_connect(enum connman_service_type type) case CONNMAN_SERVICE_TYPE_SYSTEM: case CONNMAN_SERVICE_TYPE_GPS: case CONNMAN_SERVICE_TYPE_VPN: - case CONNMAN_SERVICE_TYPE_GADGET: return; case CONNMAN_SERVICE_TYPE_ETHERNET: + case CONNMAN_SERVICE_TYPE_GADGET: case CONNMAN_SERVICE_TYPE_WIFI: case CONNMAN_SERVICE_TYPE_BLUETOOTH: case CONNMAN_SERVICE_TYPE_CELLULAR: + case CONNMAN_SERVICE_TYPE_P2P: break; } if (__sync_fetch_and_add(&connected[type], 1) == 0) { - __connman_technology_set_connected(type, TRUE); + __connman_technology_set_connected(type, true); state_changed(); } } @@ -194,19 +193,20 @@ void __connman_notifier_disconnect(enum connman_service_type type) case CONNMAN_SERVICE_TYPE_SYSTEM: case CONNMAN_SERVICE_TYPE_GPS: case CONNMAN_SERVICE_TYPE_VPN: - case CONNMAN_SERVICE_TYPE_GADGET: return; case CONNMAN_SERVICE_TYPE_ETHERNET: + case CONNMAN_SERVICE_TYPE_GADGET: case CONNMAN_SERVICE_TYPE_WIFI: case CONNMAN_SERVICE_TYPE_BLUETOOTH: case CONNMAN_SERVICE_TYPE_CELLULAR: + case CONNMAN_SERVICE_TYPE_P2P: break; } if (__sync_fetch_and_sub(&connected[type], 1) != 1) return; - __connman_technology_set_connected(type, FALSE); + __connman_technology_set_connected(type, false); state_changed(); } @@ -239,7 +239,7 @@ void __connman_notifier_service_remove(struct connman_service *service) { GSList *list; - if (g_hash_table_lookup(service_hash, service) != NULL) { + if (g_hash_table_lookup(service_hash, service)) { /* * This is a tempory check for consistency. It can be * removed when there are no reports for the following @@ -279,7 +279,7 @@ static void offlinemode_changed(dbus_bool_t enabled) DBUS_TYPE_BOOLEAN, &enabled); } -void __connman_notifier_offlinemode(connman_bool_t enabled) +void __connman_notifier_offlinemode(bool enabled) { GSList *list; @@ -296,7 +296,7 @@ void __connman_notifier_offlinemode(connman_bool_t enabled) } } -static void notify_idle_state(connman_bool_t idle) +static void notify_idle_state(bool idle) { GSList *list; @@ -315,7 +315,7 @@ void __connman_notifier_service_state_changed(struct connman_service *service, { GSList *list; unsigned int old_size; - connman_bool_t found; + bool found; for (list = notifier_list; list; list = list->next) { struct connman_notifier *notifier = list->data; @@ -325,31 +325,31 @@ void __connman_notifier_service_state_changed(struct connman_service *service, } old_size = g_hash_table_size(service_hash); - found = g_hash_table_lookup(service_hash, service) != NULL; + found = g_hash_table_lookup(service_hash, service); switch (state) { case CONNMAN_SERVICE_STATE_UNKNOWN: case CONNMAN_SERVICE_STATE_FAILURE: case CONNMAN_SERVICE_STATE_DISCONNECT: case CONNMAN_SERVICE_STATE_IDLE: - if (found == FALSE) + if (!found) break; g_hash_table_remove(service_hash, service); if (old_size == 1) - notify_idle_state(TRUE); + notify_idle_state(true); break; case CONNMAN_SERVICE_STATE_ASSOCIATION: case CONNMAN_SERVICE_STATE_CONFIGURATION: case CONNMAN_SERVICE_STATE_READY: case CONNMAN_SERVICE_STATE_ONLINE: - if (found == TRUE) + if (found) break; g_hash_table_insert(service_hash, service, service); if (old_size == 0) - notify_idle_state(FALSE); + notify_idle_state(false); break; } @@ -2,7 +2,7 @@ * * Connection Manager * - * Copyright (C) 2007-2012 Intel Corporation. All rights reserved. + * Copyright (C) 2007-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 @@ -93,6 +93,9 @@ struct ntp_msg { #define NTP_FLAG_MD_CONTROL 6 #define NTP_FLAG_MD_PRIVATE 7 +#define NTP_FLAG_VN_VER3 3 +#define NTP_FLAG_VN_VER4 4 + #define NTP_FLAGS_ENCODE(li, vn, md) ((uint8_t)( \ (((li) & NTP_FLAG_LI_MASK) << NTP_FLAG_LI_SHIFT) | \ (((vn) & NTP_FLAG_VN_MASK) << NTP_FLAG_VN_SHIFT) | \ @@ -114,15 +117,16 @@ static struct timespec mtx_time; static int transmit_fd = 0; static char *timeserver = NULL; +static struct sockaddr_in timeserver_addr; static gint poll_id = 0; static gint timeout_id = 0; static guint retries = 0; -static void send_packet(int fd, const char *server); +static void send_packet(int fd, const char *server, uint32_t timeout); static void next_server(void) { - if (timeserver != NULL) { + if (timeserver) { g_free(timeserver); timeserver = NULL; } @@ -132,17 +136,19 @@ static void next_server(void) static gboolean send_timeout(gpointer user_data) { - DBG("send timeout (retries %d)", retries); + uint32_t timeout = GPOINTER_TO_UINT(user_data); + + DBG("send timeout %u (retries %d)", timeout, retries); if (retries++ == NTP_SEND_RETRIES) next_server(); else - send_packet(transmit_fd, timeserver); + send_packet(transmit_fd, timeserver, timeout << 1); return FALSE; } -static void send_packet(int fd, const char *server) +static void send_packet(int fd, const char *server, uint32_t timeout) { struct ntp_msg msg; struct sockaddr_in addr; @@ -156,7 +162,8 @@ static void send_packet(int fd, const char *server) * msg.precision = (int)log2(ts.tv_sec + (ts.tv_nsec * 1.0e-9)); */ memset(&msg, 0, sizeof(msg)); - msg.flags = NTP_FLAGS_ENCODE(NTP_FLAG_LI_NOTINSYNC, 4, NTP_FLAG_MD_CLIENT); + msg.flags = NTP_FLAGS_ENCODE(NTP_FLAG_LI_NOTINSYNC, NTP_FLAG_VN_VER4, + NTP_FLAG_MD_CLIENT); msg.poll = 4; // min msg.poll = 10; // max msg.precision = NTP_PRECISION_S; @@ -190,28 +197,31 @@ static void send_packet(int fd, const char *server) } /* - * Add a retry timeout of two seconds to retry the existing + * Add an exponential retry timeout to retry the existing * request. After a set number of retries, we'll fallback to * trying another server. */ - timeout_id = g_timeout_add_seconds(NTP_SEND_TIMEOUT, send_timeout, NULL); + timeout_id = g_timeout_add_seconds(timeout, send_timeout, + GUINT_TO_POINTER(timeout)); } static gboolean next_poll(gpointer user_data) { - if (timeserver == NULL || transmit_fd == 0) + if (!timeserver || transmit_fd == 0) return FALSE; - send_packet(transmit_fd, timeserver); + send_packet(transmit_fd, timeserver, NTP_SEND_TIMEOUT); return FALSE; } static void reset_timeout(void) { - if (timeout_id > 0) + if (timeout_id > 0) { g_source_remove(timeout_id); + timeout_id = 0; + } retries = 0; } @@ -229,7 +239,7 @@ static void decode_msg(void *base, size_t len, struct timeval *tv, return; } - if (tv == NULL) { + if (!tv) { connman_error("Invalid packet timestamp from time server"); return; } @@ -246,6 +256,17 @@ static void decode_msg(void *base, size_t len, struct timeval *tv, msg->rootdisp.seconds, msg->rootdisp.fraction); DBG("reference : 0x%04x", msg->refid); + if (!msg->stratum) { + /* RFC 4330 ch 8 Kiss-of-Death packet */ + uint32_t code = ntohl(msg->refid); + + connman_info("Skipping server %s KoD code %c%c%c%c", + timeserver, code >> 24, code >> 16 & 0xff, + code >> 8 & 0xff, code & 0xff); + next_server(); + return; + } + transmit_delay = LOGTOD(msg->poll); if (NTP_FLAGS_LI_DECODE(msg->flags) == NTP_FLAG_LI_NOTINSYNC) { @@ -253,9 +274,15 @@ static void decode_msg(void *base, size_t len, struct timeval *tv, return; } - if (NTP_FLAGS_VN_DECODE(msg->flags) != 4) { - DBG("unsupported version %d", NTP_FLAGS_VN_DECODE(msg->flags)); - return; + + if (NTP_FLAGS_VN_DECODE(msg->flags) != NTP_FLAG_VN_VER4) { + if (NTP_FLAGS_VN_DECODE(msg->flags) == NTP_FLAG_VN_VER3) { + DBG("requested version %d, accepting version %d", + NTP_FLAG_VN_VER4, NTP_FLAGS_VN_DECODE(msg->flags)); + } else { + DBG("unsupported version %d", NTP_FLAGS_VN_DECODE(msg->flags)); + return; + } } if (NTP_FLAGS_MD_DECODE(msg->flags) != NTP_FLAG_MD_SERVER) { @@ -335,6 +362,7 @@ static gboolean received_data(GIOChannel *channel, GIOCondition condition, gpointer user_data) { unsigned char buf[128]; + struct sockaddr_in sender_addr; struct msghdr msg; struct iovec iov; struct cmsghdr *cmsg; @@ -360,11 +388,17 @@ static gboolean received_data(GIOChannel *channel, GIOCondition condition, msg.msg_iovlen = 1; msg.msg_control = aux; msg.msg_controllen = sizeof(aux); + msg.msg_name = &sender_addr; + msg.msg_namelen = sizeof(sender_addr); len = recvmsg(fd, &msg, MSG_DONTWAIT); if (len < 0) return TRUE; + if (timeserver_addr.sin_addr.s_addr != sender_addr.sin_addr.s_addr) + /* only accept messages from the timeserver */ + return TRUE; + tv = NULL; clock_gettime(CLOCK_MONOTONIC, &mrx_time); @@ -390,7 +424,7 @@ static void start_ntp(char *server) struct sockaddr_in addr; int tos = IPTOS_LOWDELAY, timestamp = 1; - if (server == NULL) + if (!server) return; DBG("server %s", server); @@ -427,7 +461,7 @@ static void start_ntp(char *server) } channel = g_io_channel_unix_new(transmit_fd); - if (channel == NULL) { + if (!channel) { close(transmit_fd); return; } @@ -444,20 +478,21 @@ static void start_ntp(char *server) g_io_channel_unref(channel); send: - send_packet(transmit_fd, server); + send_packet(transmit_fd, server, NTP_SEND_TIMEOUT); } int __connman_ntp_start(char *server) { DBG("%s", server); - if (server == NULL) + if (!server) return -EINVAL; - if (timeserver != NULL) + if (timeserver) g_free(timeserver); timeserver = g_strdup(server); + timeserver_addr.sin_addr.s_addr = inet_addr(server); start_ntp(timeserver); @@ -468,10 +503,12 @@ void __connman_ntp_stop() { DBG(""); - if (poll_id > 0) + if (poll_id > 0) { g_source_remove(poll_id); + poll_id = 0; + } - reset_timeout(); + reset_timeout(); if (channel_watch > 0) { g_source_remove(channel_watch); @@ -479,7 +516,7 @@ void __connman_ntp_stop() transmit_fd = 0; } - if (timeserver != NULL) { + if (timeserver) { g_free(timeserver); timeserver = NULL; } diff --git a/src/peer.c b/src/peer.c new file mode 100644 index 00000000..ce3b582e --- /dev/null +++ b/src/peer.c @@ -0,0 +1,317 @@ +/* + * + * 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 <errno.h> +#include <gdbus.h> + +#include "connman.h" + +static DBusConnection *connection = NULL; + +static GHashTable *peers_table = NULL; + +struct connman_peer { + char *identifier; + char *name; + char *path; +}; + +static void peer_free(gpointer data) +{ + struct connman_peer *peer = data; + connman_peer_destroy(peer); +} + +static void append_properties(DBusMessageIter *iter, struct connman_peer *peer) +{ + const char *state = "disconnected"; + DBusMessageIter dict; + + connman_dbus_dict_open(iter, &dict); + + connman_dbus_dict_append_basic(&dict, "State", + DBUS_TYPE_STRING, &state); + connman_dbus_dict_append_basic(&dict, "Name", + DBUS_TYPE_STRING, &peer->name); + connman_dbus_dict_append_dict(&dict, "IPv4", NULL, NULL); + + connman_dbus_dict_close(iter, &dict); +} + +static DBusMessage *get_peer_properties(DBusConnection *conn, + DBusMessage *msg, void *data) +{ + struct connman_peer *peer = data; + DBusMessageIter dict; + DBusMessage *reply; + + reply = dbus_message_new_method_return(msg); + if (!reply) + return NULL; + + dbus_message_iter_init_append(reply, &dict); + append_properties(&dict, peer); + + return reply; +} + +static void append_peer_struct(gpointer key, gpointer value, + gpointer user_data) +{ + DBusMessageIter *array = user_data; + struct connman_peer *peer = value; + DBusMessageIter entry; + + dbus_message_iter_open_container(array, DBUS_TYPE_STRUCT, + NULL, &entry); + dbus_message_iter_append_basic(&entry, DBUS_TYPE_OBJECT_PATH, + &peer->path); + append_properties(&entry, peer); + dbus_message_iter_close_container(array, &entry); +} + +struct _peers_notify { + int id; + GHashTable *add; + GHashTable *remove; +} *peers_notify; + +static void append_existing_and_new_peers(gpointer key, + gpointer value, gpointer user_data) +{ + struct connman_peer *peer = value; + DBusMessageIter *iter = user_data; + DBusMessageIter entry; + + if (g_hash_table_lookup(peers_notify->add, peer->path)) { + DBG("new %s", peer->path); + + append_peer_struct(key, value, user_data); + g_hash_table_remove(peers_notify->add, peer->path); + } else { + DBG("existing %s", peer->path); + + dbus_message_iter_open_container(iter, DBUS_TYPE_STRUCT, + NULL, &entry); + dbus_message_iter_append_basic(&entry, DBUS_TYPE_OBJECT_PATH, + &peer->path); + dbus_message_iter_close_container(iter, &entry); + } +} + +static void peer_append_all(DBusMessageIter *iter, void *user_data) +{ + g_hash_table_foreach(peers_table, append_existing_and_new_peers, iter); +} + +static void append_removed(gpointer key, gpointer value, gpointer user_data) +{ + DBusMessageIter *iter = user_data; + char *objpath = key; + + DBG("removed %s", objpath); + dbus_message_iter_append_basic(iter, DBUS_TYPE_OBJECT_PATH, &objpath); +} + +static void peer_append_removed(DBusMessageIter *iter, void *user_data) +{ + g_hash_table_foreach(peers_notify->remove, append_removed, iter); +} + +static gboolean peer_send_changed(gpointer data) +{ + DBusMessage *signal; + + DBG(""); + + peers_notify->id = 0; + + signal = dbus_message_new_signal(CONNMAN_MANAGER_PATH, + CONNMAN_MANAGER_INTERFACE, "PeersChanged"); + if (!signal) + return FALSE; + + __connman_dbus_append_objpath_dict_array(signal, + peer_append_all, NULL); + __connman_dbus_append_objpath_array(signal, + peer_append_removed, NULL); + + dbus_connection_send(connection, signal, NULL); + dbus_message_unref(signal); + + g_hash_table_remove_all(peers_notify->remove); + g_hash_table_remove_all(peers_notify->add); + + return FALSE; +} + +static void peer_schedule_changed(void) +{ + if (peers_notify->id != 0) + return; + + peers_notify->id = g_timeout_add(100, peer_send_changed, NULL); +} + +static void peer_added(struct connman_peer *peer) +{ + DBG("peer %p", peer); + + g_hash_table_remove(peers_notify->remove, peer->path); + g_hash_table_replace(peers_notify->add, peer->path, peer); + + peer_schedule_changed(); +} + +static void peer_removed(struct connman_peer *peer) +{ + DBG("peer %p", peer); + + g_hash_table_remove(peers_notify->add, peer->path); + g_hash_table_replace(peers_notify->remove, g_strdup(peer->path), NULL); + + peer_schedule_changed(); +} + +struct connman_peer *connman_peer_create(const char *identifier) +{ + struct connman_peer *peer; + + peer = g_malloc0(sizeof(struct connman_peer)); + peer->identifier = g_strdup_printf("peer_%s", identifier); + + return peer; +} + +void connman_peer_destroy(struct connman_peer *peer) +{ + if (!peer) + return; + + if (peer->path) { + peer_removed(peer); + g_dbus_unregister_interface(connection, peer->path, + CONNMAN_PEER_INTERFACE); + g_free(peer->path); + } + + g_free(peer->identifier); + g_free(peer->name); + + g_free(peer); +} + +void connman_peer_set_name(struct connman_peer *peer, const char *name) +{ + g_free(peer->name); + peer->name = g_strdup(name); +} + +static const GDBusMethodTable peer_methods[] = { + { GDBUS_METHOD("GetProperties", + NULL, GDBUS_ARGS({ "properties", "a{sv}" }), + get_peer_properties) }, + { GDBUS_ASYNC_METHOD("Connect", NULL, NULL, NULL) }, + { GDBUS_METHOD("Disconnect", NULL, NULL, NULL) }, + { }, +}; + +static const GDBusSignalTable peer_signals[] = { + { GDBUS_SIGNAL("PropertyChanged", + GDBUS_ARGS({ "name", "s" }, { "value", "v" })) }, + { }, +}; + +int connman_peer_register(struct connman_peer *peer) +{ + DBG("peer %p", peer); + + if (peer->path) + return -EALREADY; + + peer->path = g_strdup_printf("%s/peer/%s", CONNMAN_PATH, + peer->identifier); + DBG("path %s", peer->path); + + g_hash_table_insert(peers_table, peer->identifier, peer); + + g_dbus_register_interface(connection, peer->path, + CONNMAN_PEER_INTERFACE, + peer_methods, peer_signals, + NULL, peer, NULL); + peer_added(peer); + + return 0; +} + +void connman_peer_unregister(struct connman_peer *peer) +{ + DBG("peer %p", peer); + + if (peer->path) + g_hash_table_remove(peers_table, peer->identifier); + else + connman_peer_destroy(peer); +} + +struct connman_peer *connman_peer_get(const char *identifier) +{ + char *ident = g_strdup_printf("peer_%s", identifier); + struct connman_peer *peer; + + peer = g_hash_table_lookup(peers_table, ident); + g_free(ident); + + return peer; +} + +void __connman_peer_list_struct(DBusMessageIter *array) +{ + g_hash_table_foreach(peers_table, append_peer_struct, array); +} + +int __connman_peer_init(void) +{ + DBG(""); + + connection = connman_dbus_get_connection(); + + peers_table = g_hash_table_new_full(g_str_hash, g_str_equal, + NULL, peer_free); + + peers_notify = g_new0(struct _peers_notify, 1); + peers_notify->add = g_hash_table_new(g_str_hash, g_str_equal); + peers_notify->remove = g_hash_table_new_full(g_str_hash, g_str_equal, + g_free, NULL); + return 0; +} + +void __connman_peer_cleanup(void) +{ + DBG(""); + + g_hash_table_destroy(peers_table); + dbus_connection_unref(connection); +} diff --git a/src/plugin.c b/src/plugin.c index adf8525b..7d730582 100644 --- a/src/plugin.c +++ b/src/plugin.c @@ -33,22 +33,11 @@ #include "connman.h" -/* - * Plugins that are using libraries with threads and their own mainloop - * will crash on exit. This is a bug inside these libraries, but there is - * nothing much that can be done about it. - */ -#ifdef NEED_THREADS -#define PLUGINFLAG (RTLD_NOW | RTLD_NODELETE) -#else -#define PLUGINFLAG (RTLD_NOW) -#endif - static GSList *plugins = NULL; struct connman_plugin { void *handle; - gboolean active; + bool active; struct connman_plugin_desc *desc; }; @@ -60,35 +49,35 @@ static gint compare_priority(gconstpointer a, gconstpointer b) return plugin2->desc->priority - plugin1->desc->priority; } -static gboolean add_plugin(void *handle, struct connman_plugin_desc *desc) +static bool add_plugin(void *handle, struct connman_plugin_desc *desc) { struct connman_plugin *plugin; - if (desc->init == NULL) - return FALSE; + if (!desc->init) + return false; - if (g_str_equal(desc->version, CONNMAN_VERSION) == FALSE) { + if (!g_str_equal(desc->version, CONNMAN_VERSION)) { connman_error("Invalid version %s for %s", desc->version, desc->description); - return FALSE; + return false; } plugin = g_try_new0(struct connman_plugin, 1); - if (plugin == NULL) - return FALSE; + if (!plugin) + return false; plugin->handle = handle; - plugin->active = FALSE; + plugin->active = false; plugin->desc = desc; __connman_log_enable(desc->debug_start, desc->debug_stop); plugins = g_slist_insert_sorted(plugins, plugin, compare_priority); - return TRUE; + return true; } -static gboolean check_plugin(struct connman_plugin_desc *desc, +static bool check_plugin(struct connman_plugin_desc *desc, char **patterns, char **excludes) { if (excludes) { @@ -97,7 +86,7 @@ static gboolean check_plugin(struct connman_plugin_desc *desc, break; if (*excludes) { connman_info("Excluding %s", desc->description); - return FALSE; + return false; } } @@ -107,11 +96,11 @@ static gboolean check_plugin(struct connman_plugin_desc *desc, break; if (!*patterns) { connman_info("Ignoring %s", desc->description); - return FALSE; + return false; } } - return TRUE; + return true; } #include <builtin.h> @@ -135,27 +124,26 @@ int __connman_plugin_init(const char *pattern, const char *exclude) excludes = g_strsplit_set(exclude, ":, ", -1); for (i = 0; __connman_builtin[i]; i++) { - if (check_plugin(__connman_builtin[i], - patterns, excludes) == FALSE) + if (!check_plugin(__connman_builtin[i], patterns, excludes)) continue; add_plugin(NULL, __connman_builtin[i]); } dir = g_dir_open(PLUGINDIR, 0, NULL); - if (dir != NULL) { - while ((file = g_dir_read_name(dir)) != NULL) { + if (dir) { + while ((file = g_dir_read_name(dir))) { void *handle; struct connman_plugin_desc *desc; - if (g_str_has_prefix(file, "lib") == TRUE || - g_str_has_suffix(file, ".so") == FALSE) + if (g_str_has_prefix(file, "lib") || + !g_str_has_suffix(file, ".so")) continue; filename = g_build_filename(PLUGINDIR, file, NULL); - handle = dlopen(filename, PLUGINFLAG); - if (handle == NULL) { + handle = dlopen(filename, RTLD_NOW); + if (!handle) { connman_error("Can't load %s: %s", filename, dlerror()); g_free(filename); @@ -165,19 +153,19 @@ int __connman_plugin_init(const char *pattern, const char *exclude) g_free(filename); desc = dlsym(handle, "connman_plugin_desc"); - if (desc == NULL) { + if (!desc) { connman_error("Can't load symbol: %s", dlerror()); dlclose(handle); continue; } - if (check_plugin(desc, patterns, excludes) == FALSE) { + if (!check_plugin(desc, patterns, excludes)) { dlclose(handle); continue; } - if (add_plugin(handle, desc) == FALSE) + if (!add_plugin(handle, desc)) dlclose(handle); } @@ -190,7 +178,7 @@ int __connman_plugin_init(const char *pattern, const char *exclude) if (plugin->desc->init() < 0) continue; - plugin->active = TRUE; + plugin->active = true; } g_strfreev(patterns); @@ -208,10 +196,10 @@ void __connman_plugin_cleanup(void) for (list = plugins; list; list = list->next) { struct connman_plugin *plugin = list->data; - if (plugin->active == TRUE && plugin->desc->exit) + if (plugin->active && plugin->desc->exit) plugin->desc->exit(); - if (plugin->handle != NULL) + if (plugin->handle) dlclose(plugin->handle); g_free(plugin); diff --git a/src/provider.c b/src/provider.c index 1c360172..693552ee 100644 --- a/src/provider.c +++ b/src/provider.c @@ -2,7 +2,7 @@ * * Connection Manager * - * Copyright (C) 2007-2012 Intel Corporation. All rights reserved. + * Copyright (C) 2007-2013 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 @@ -40,6 +40,7 @@ static GSList *driver_list = NULL; struct connman_provider { int refcount; + bool immutable; struct connman_service *vpn_service; int index; char *identifier; @@ -53,22 +54,22 @@ void __connman_provider_append_properties(struct connman_provider *provider, { const char *host, *domain, *type; - if (provider->driver == NULL || provider->driver->get_property == NULL) + if (!provider->driver || !provider->driver->get_property) return; host = provider->driver->get_property(provider, "Host"); domain = provider->driver->get_property(provider, "Domain"); type = provider->driver->get_property(provider, "Type"); - if (host != NULL) + if (host) connman_dbus_dict_append_basic(iter, "Host", DBUS_TYPE_STRING, &host); - if (domain != NULL) + if (domain) connman_dbus_dict_append_basic(iter, "Domain", DBUS_TYPE_STRING, &domain); - if (type != NULL) + if (type) connman_dbus_dict_append_basic(iter, "Type", DBUS_TYPE_STRING, &type); } @@ -87,7 +88,7 @@ connman_provider_ref_debug(struct connman_provider *provider, static void provider_remove(struct connman_provider *provider) { - if (provider->driver != NULL) { + if (provider->driver) { provider->driver->remove(provider); provider->driver = NULL; } @@ -131,12 +132,12 @@ int connman_provider_disconnect(struct connman_provider *provider) DBG("provider %p", provider); - if (provider->driver != NULL && provider->driver->disconnect != NULL) + if (provider->driver && provider->driver->disconnect) err = provider->driver->disconnect(provider); else return -EOPNOTSUPP; - if (provider->vpn_service != NULL) + if (provider->vpn_service) provider_indicate_state(provider, CONNMAN_SERVICE_STATE_DISCONNECT); @@ -169,9 +170,9 @@ int __connman_provider_connect(struct connman_provider *provider) DBG("provider %p", provider); - if (provider->driver != NULL && provider->driver->connect != NULL) { + if (provider->driver && provider->driver->connect) err = provider->driver->connect(provider); - } else + else return -EOPNOTSUPP; if (err < 0) { @@ -196,11 +197,11 @@ int __connman_provider_remove_by_path(const char *path) DBG("path %s", path); g_hash_table_iter_init(&iter, provider_hash); - while (g_hash_table_iter_next(&iter, &key, &value) == TRUE) { + while (g_hash_table_iter_next(&iter, &key, &value)) { const char *srv_path; provider = value; - if (provider->vpn_service == NULL) + if (!provider->vpn_service) continue; srv_path = __connman_service_get_path(provider->vpn_service); @@ -223,18 +224,18 @@ int __connman_provider_remove_by_path(const char *path) } static int set_connected(struct connman_provider *provider, - connman_bool_t connected) + bool connected) { struct connman_service *service = provider->vpn_service; struct connman_ipconfig *ipconfig; - if (service == NULL) + if (!service) return -ENODEV; ipconfig = __connman_service_get_ipconfig(service, provider->family); - if (connected == TRUE) { - if (ipconfig == NULL) { + if (connected) { + if (!ipconfig) { provider_indicate_state(provider, CONNMAN_SERVICE_STATE_FAILURE); return -EIO; @@ -246,12 +247,12 @@ static int set_connected(struct connman_provider *provider, provider_indicate_state(provider, CONNMAN_SERVICE_STATE_READY); - if (provider->driver != NULL && provider->driver->set_routes) + if (provider->driver && provider->driver->set_routes) provider->driver->set_routes(provider, CONNMAN_PROVIDER_ROUTE_ALL); } else { - if (ipconfig != NULL) { + if (ipconfig) { provider_indicate_state(provider, CONNMAN_SERVICE_STATE_DISCONNECT); __connman_ipconfig_gateway_remove(ipconfig); @@ -267,19 +268,19 @@ static int set_connected(struct connman_provider *provider, int connman_provider_set_state(struct connman_provider *provider, enum connman_provider_state state) { - if (provider == NULL || provider->vpn_service == NULL) + if (!provider || !provider->vpn_service) return -EINVAL; switch (state) { case CONNMAN_PROVIDER_STATE_UNKNOWN: return -EINVAL; case CONNMAN_PROVIDER_STATE_IDLE: - return set_connected(provider, FALSE); + return set_connected(provider, false); case CONNMAN_PROVIDER_STATE_CONNECT: return provider_indicate_state(provider, CONNMAN_SERVICE_STATE_ASSOCIATION); case CONNMAN_PROVIDER_STATE_READY: - return set_connected(provider, TRUE); + return set_connected(provider, true); case CONNMAN_PROVIDER_STATE_DISCONNECT: return provider_indicate_state(provider, CONNMAN_SERVICE_STATE_DISCONNECT); @@ -317,17 +318,17 @@ int connman_provider_indicate_error(struct connman_provider *provider, int connman_provider_create_service(struct connman_provider *provider) { - if (provider->vpn_service != NULL) { - connman_bool_t connected; + if (provider->vpn_service) { + bool connected; connected = __connman_service_is_connected_state( provider->vpn_service, CONNMAN_IPCONFIG_TYPE_IPV4); - if (connected == TRUE) + if (connected) return -EALREADY; connected = __connman_service_is_connected_state( provider->vpn_service, CONNMAN_IPCONFIG_TYPE_IPV6); - if (connected == TRUE) + if (connected) return -EALREADY; return 0; @@ -336,7 +337,7 @@ int connman_provider_create_service(struct connman_provider *provider) provider->vpn_service = __connman_service_create_from_provider(provider); - if (provider->vpn_service == NULL) { + if (!provider->vpn_service) { connman_warn("service creation failed for provider %s", provider->identifier); @@ -347,17 +348,24 @@ int connman_provider_create_service(struct connman_provider *provider) return 0; } +bool __connman_provider_is_immutable(struct connman_provider *provider) + +{ + if (provider) + return provider->immutable; + + return false; +} + int connman_provider_set_immutable(struct connman_provider *provider, - connman_bool_t immutable) + bool immutable) { - if (provider == NULL) + if (!provider) return -EINVAL; - if (provider->vpn_service == NULL) - return -ESRCH; + provider->immutable = immutable; - return __connman_service_set_immutable(provider->vpn_service, - immutable); + return 0; } static struct connman_provider *provider_lookup(const char *identifier) @@ -374,15 +382,15 @@ static void connection_ready(DBusMessage *msg, int error_code, void *user_data) if (error_code != 0) { reply = __connman_error_failed(msg, -error_code); - if (g_dbus_send_message(connection, reply) == FALSE) + if (!g_dbus_send_message(connection, reply)) DBG("reply %p send failed", reply); } else { const char *path; struct connman_provider *provider; provider = provider_lookup(identifier); - if (provider == NULL) { - reply = __connman_error_failed(msg, -EINVAL); + if (!provider) { + reply = __connman_error_failed(msg, EINVAL); g_dbus_send_message(connection, reply); return; } @@ -399,11 +407,11 @@ int __connman_provider_create_and_connect(DBusMessage *msg) { struct connman_provider_driver *driver; - if (driver_list == NULL) + if (!driver_list) return -EINVAL; driver = driver_list->data; - if (driver == NULL || driver->create == NULL) + if (!driver || !driver->create) return -EINVAL; DBG("msg %p", msg); @@ -411,9 +419,9 @@ int __connman_provider_create_and_connect(DBusMessage *msg) return driver->create(msg, connection_ready); } -const char * __connman_provider_get_ident(struct connman_provider *provider) +const char *__connman_provider_get_ident(struct connman_provider *provider) { - if (provider == NULL) + if (!provider) return NULL; return provider->identifier; @@ -422,7 +430,7 @@ const char * __connman_provider_get_ident(struct connman_provider *provider) int connman_provider_set_string(struct connman_provider *provider, const char *key, const char *value) { - if (provider->driver != NULL && provider->driver->set_property) + if (provider->driver && provider->driver->set_property) return provider->driver->set_property(provider, key, value); return 0; @@ -431,22 +439,22 @@ int connman_provider_set_string(struct connman_provider *provider, const char *connman_provider_get_string(struct connman_provider *provider, const char *key) { - if (provider->driver != NULL && provider->driver->get_property) + if (provider->driver && provider->driver->get_property) return provider->driver->get_property(provider, key); return NULL; } -connman_bool_t +bool __connman_provider_check_routes(struct connman_provider *provider) { - if (provider == NULL) - return FALSE; + if (!provider) + return false; - if (provider->driver != NULL && provider->driver->check_routes) + if (provider->driver && provider->driver->check_routes) return provider->driver->check_routes(provider); - return FALSE; + return false; } void *connman_provider_get_data(struct connman_provider *provider) @@ -466,16 +474,16 @@ void connman_provider_set_index(struct connman_provider *provider, int index) DBG(""); - if (service == NULL) + if (!service) return; ipconfig = __connman_service_get_ip4config(service); - if (ipconfig == NULL) { + if (!ipconfig) { connman_service_create_ip4config(service, index); ipconfig = __connman_service_get_ip4config(service); - if (ipconfig == NULL) { + if (!ipconfig) { DBG("Couldnt create ipconfig"); goto done; } @@ -486,11 +494,11 @@ void connman_provider_set_index(struct connman_provider *provider, int index) ipconfig = __connman_service_get_ip6config(service); - if (ipconfig == NULL) { + if (!ipconfig) { connman_service_create_ip6config(service, index); ipconfig = __connman_service_get_ip6config(service); - if (ipconfig == NULL) { + if (!ipconfig) { DBG("Couldnt create ipconfig for IPv6"); goto done; } @@ -515,7 +523,7 @@ int connman_provider_set_ipaddress(struct connman_provider *provider, ipconfig = __connman_service_get_ipconfig(provider->vpn_service, ipaddress->family); - if (ipconfig == NULL) + if (!ipconfig) return -EINVAL; provider->family = ipaddress->family; @@ -552,7 +560,7 @@ int connman_provider_set_domain(struct connman_provider *provider, } int connman_provider_set_nameservers(struct connman_provider *provider, - char * const * nameservers) + char * const *nameservers) { int i; @@ -560,12 +568,12 @@ int connman_provider_set_nameservers(struct connman_provider *provider, __connman_service_nameserver_clear(provider->vpn_service); - if (nameservers == NULL) + if (!nameservers) return 0; - for (i = 0; nameservers[i] != NULL; i++) + for (i = 0; nameservers[i]; i++) __connman_service_nameserver_append(provider->vpn_service, - nameservers[i], FALSE); + nameservers[i], false); return 0; } @@ -576,7 +584,7 @@ static void unregister_provider(gpointer data) DBG("provider %p service %p", provider, provider->vpn_service); - if (provider->vpn_service != NULL) { + if (provider->vpn_service) { connman_service_unref(provider->vpn_service); provider->vpn_service = NULL; } @@ -619,11 +627,11 @@ static void provider_disconnect_all(gpointer key, gpointer value, connman_provider_disconnect(provider); } -static void provider_offline_mode(connman_bool_t enabled) +static void provider_offline_mode(bool enabled) { DBG("enabled %d", enabled); - if (enabled == TRUE) + if (enabled) g_hash_table_foreach(provider_hash, provider_disconnect_all, NULL); @@ -642,7 +650,7 @@ static struct connman_provider *provider_new(void) struct connman_provider *provider; provider = g_try_new0(struct connman_provider, 1); - if (provider == NULL) + if (!provider) return NULL; provider->refcount = 1; @@ -658,11 +666,11 @@ struct connman_provider *connman_provider_get(const char *identifier) struct connman_provider *provider; provider = g_hash_table_lookup(provider_hash, identifier); - if (provider != NULL) + if (provider) return provider; provider = provider_new(); - if (provider == NULL) + if (!provider) return NULL; DBG("provider %p", provider); @@ -686,7 +694,7 @@ static struct connman_provider *provider_get(int index) g_hash_table_iter_init(&iter, provider_hash); - while (g_hash_table_iter_next(&iter, &key, &value) == TRUE) { + while (g_hash_table_iter_next(&iter, &key, &value)) { struct connman_provider *provider = value; if (provider->index == index) @@ -702,7 +710,7 @@ static void provider_service_changed(struct connman_service *service, struct connman_provider *provider; int vpn_index, service_index; - if (service == NULL) + if (!service) return; switch (state) { @@ -730,7 +738,7 @@ static void provider_service_changed(struct connman_service *service, return; provider = provider_get(vpn_index); - if (provider == NULL) + if (!provider) return; DBG("disconnect %p index %d", provider, vpn_index); diff --git a/src/proxy.c b/src/proxy.c index b6775b67..0d1a25ab 100644 --- a/src/proxy.c +++ b/src/proxy.c @@ -69,7 +69,7 @@ static gboolean lookup_callback(gpointer user_data) struct proxy_lookup *lookup = user_data; GSList *list; - if (lookup == NULL) + if (!lookup) return FALSE; lookup->watch = 0; @@ -77,14 +77,14 @@ static gboolean lookup_callback(gpointer user_data) for (list = driver_list; list; list = list->next) { struct connman_proxy_driver *proxy = list->data; - if (proxy->request_lookup == NULL) + if (!proxy->request_lookup) continue; lookup->proxy = proxy; break; } - if (lookup->proxy == NULL || + if (!lookup->proxy || lookup->proxy->request_lookup(lookup->service, lookup->url) < 0) { @@ -106,11 +106,11 @@ unsigned int connman_proxy_lookup(const char *interface, const char *url, DBG("interface %s url %s", interface, url); - if (interface == NULL) + if (!interface) return 0; lookup = g_try_new0(struct proxy_lookup, 1); - if (lookup == NULL) + if (!lookup) return 0; lookup->token = next_lookup_token++; @@ -149,14 +149,14 @@ void connman_proxy_lookup_cancel(unsigned int token) lookup = NULL; } - if (lookup != NULL) { + if (lookup) { if (lookup->watch > 0) { g_source_remove(lookup->watch); lookup->watch = 0; } - if (lookup->proxy != NULL && - lookup->proxy->cancel_lookup != NULL) + if (lookup->proxy && + lookup->proxy->cancel_lookup) lookup->proxy->cancel_lookup(lookup->service, lookup->url); @@ -165,7 +165,7 @@ void connman_proxy_lookup_cancel(unsigned int token) } void connman_proxy_driver_lookup_notify(struct connman_service *service, - const char *url, const char *result) + const char *url, const char *result) { GSList *list, *matches = NULL; @@ -185,7 +185,7 @@ void connman_proxy_driver_lookup_notify(struct connman_service *service, } } - if (matches != NULL) + if (matches) remove_lookups(matches); } diff --git a/src/resolver.c b/src/resolver.c index b965778b..01e7c0e0 100644 --- a/src/resolver.c +++ b/src/resolver.c @@ -2,7 +2,7 @@ * * Connection Manager * - * Copyright (C) 2007-2012 Intel Corporation. All rights reserved. + * Copyright (C) 2007-2013 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 @@ -54,7 +54,7 @@ struct entry_data { }; static GSList *entry_list = NULL; -static connman_bool_t dnsproxy_enabled = FALSE; +static bool dnsproxy_enabled = false; struct resolvfile_entry { int index; @@ -168,7 +168,7 @@ int __connman_resolvfile_append(int index, const char *domain, return -ENOENT; entry = g_try_new0(struct resolvfile_entry, 1); - if (entry == NULL) + if (!entry) return -ENOMEM; entry->index = index; @@ -193,7 +193,7 @@ int __connman_resolvfile_remove(int index, const char *domain, if (index >= 0 && entry->index != index) continue; - if (domain != NULL && g_strcmp0(entry->domain, domain) != 0) + if (domain && g_strcmp0(entry->domain, domain) != 0) continue; if (g_strcmp0(entry->server, server) != 0) @@ -207,6 +207,57 @@ int __connman_resolvfile_remove(int index, const char *domain, return resolvfile_export(); } +static void append_fallback_nameservers(void) +{ + GSList *list; + + for (list = entry_list; list; list = list->next) { + struct entry_data *entry = list->data; + + if (entry->index >= 0 && entry->server) + return; + } + + for (list = entry_list; list; list = list->next) { + struct entry_data *entry = list->data; + + if (entry->index != -1 || !entry->server) + continue; + + DBG("index %d server %s", entry->index, entry->server); + + if (dnsproxy_enabled) { + __connman_dnsproxy_append(entry->index, entry->domain, + entry->server); + } else { + __connman_resolvfile_append(entry->index, + entry->domain, entry->server); + } + } +} + +static void remove_fallback_nameservers(void) +{ + GSList *list; + + for (list = entry_list; list; list = list->next) { + struct entry_data *entry = list->data; + + if (entry->index >= 0 || !entry->server) + continue; + + DBG("index %d server %s", entry->index, entry->server); + + if (dnsproxy_enabled) { + __connman_dnsproxy_remove(entry->index, entry->domain, + entry->server); + } else { + __connman_resolvfile_remove(entry->index, + entry->domain, entry->server); + } + } +} + static void remove_entries(GSList *entries) { GSList *list; @@ -216,7 +267,7 @@ static void remove_entries(GSList *entries) entry_list = g_slist_remove(entry_list, entry); - if (dnsproxy_enabled == TRUE) { + if (dnsproxy_enabled) { __connman_dnsproxy_remove(entry->index, entry->domain, entry->server); } else { @@ -247,9 +298,9 @@ static gboolean resolver_expire_cb(gpointer user_data) if (entry->index >= 0) { struct connman_service *service; service = __connman_service_lookup_from_index(entry->index); - if (service != NULL) + if (service) __connman_service_nameserver_remove(service, - entry->server, TRUE); + entry->server, true); } remove_entries(list); @@ -277,12 +328,12 @@ static gboolean resolver_refresh_cb(gpointer user_data) if (entry->index >= 0) { service = __connman_service_lookup_from_index(entry->index); - if (service != NULL) { + if (service) { /* * Send Router Solicitation to refresh RDNSS entries * before their lifetime expires */ - __connman_refresh_rs_ipv6( + __connman_network_refresh_rs_ipv6( __connman_service_get_network(service), entry->index); } @@ -300,11 +351,11 @@ static int append_resolver(int index, const char *domain, DBG("index %d domain %s server %s lifetime %d flags %d", index, domain, server, lifetime, flags); - if (server == NULL && domain == NULL) + if (!server && !domain) return -EINVAL; entry = g_try_new0(struct entry_data, 1); - if (entry == NULL) + if (!entry) return -ENOMEM; entry->index = index; @@ -313,7 +364,7 @@ static int append_resolver(int index, const char *domain, entry->flags = flags; entry->lifetime = lifetime; - if (server != NULL) + if (server) entry->family = connman_inet_check_ipaddress(server); if (lifetime) { @@ -330,17 +381,21 @@ static int append_resolver(int index, const char *domain, * We update the service only for those nameservers * that are automagically added via netlink (lifetime > 0) */ - if (server != NULL && entry->index >= 0) { + if (server && entry->index >= 0) { struct connman_service *service; service = __connman_service_lookup_from_index(entry->index); - if (service != NULL) + if (service) __connman_service_nameserver_append(service, - server, TRUE); + server, true); } } + + if (entry->index >= 0 && entry->server) + remove_fallback_nameservers(); + entry_list = g_slist_append(entry_list, entry); - if (dnsproxy_enabled == TRUE) + if (dnsproxy_enabled) __connman_dnsproxy_append(entry->index, domain, server); else __connman_resolvfile_append(entry->index, domain, server); @@ -363,7 +418,7 @@ int connman_resolver_append(int index, const char *domain, DBG("index %d domain %s server %s", index, domain, server); - if (server == NULL && domain == NULL) + if (!server && !domain) return -EINVAL; for (list = entry_list; list; list = list->next) { @@ -374,8 +429,13 @@ int connman_resolver_append(int index, const char *domain, if (entry->index == index && g_strcmp0(entry->domain, domain) == 0 && - g_strcmp0(entry->server, server) == 0) + g_strcmp0(entry->server, server) == 0) { + if (dnsproxy_enabled) + __connman_dnsproxy_append(entry->index, domain, + server); + return -EEXIST; + } } return append_resolver(index, domain, server, 0, 0); @@ -399,7 +459,7 @@ int connman_resolver_append_lifetime(int index, const char *domain, DBG("index %d domain %s server %s lifetime %d", index, domain, server, lifetime); - if (server == NULL && domain == NULL) + if (!server && !domain) return -EINVAL; for (list = entry_list; list; list = list->next) { @@ -462,7 +522,7 @@ int connman_resolver_remove(int index, const char *domain, const char *server) break; } - if (matches == NULL) + if (!matches) return -ENOENT; remove_entries(matches); @@ -494,7 +554,7 @@ int connman_resolver_remove_all(int index) matches = g_slist_prepend(matches, entry); } - if (matches == NULL) + if (!matches) return -ENOENT; remove_entries(matches); @@ -509,7 +569,9 @@ int connman_resolver_remove_all(int index) */ void connman_resolver_flush(void) { - if (dnsproxy_enabled == TRUE) + append_fallback_nameservers(); + + if (dnsproxy_enabled) __connman_dnsproxy_flush(); return; @@ -519,7 +581,7 @@ int __connman_resolver_redo_servers(int index) { GSList *list; - if (dnsproxy_enabled == FALSE) + if (!dnsproxy_enabled) return 0; DBG("index %d", index); @@ -578,14 +640,14 @@ static void free_resolvfile(gpointer data) g_free(entry); } -int __connman_resolver_init(connman_bool_t dnsproxy) +int __connman_resolver_init(gboolean dnsproxy) { int i; char **ns; DBG("dnsproxy %d", dnsproxy); - if (dnsproxy == FALSE) + if (!dnsproxy) return 0; if (__connman_dnsproxy_init() < 0) { @@ -593,10 +655,10 @@ int __connman_resolver_init(connman_bool_t dnsproxy) return 0; } - dnsproxy_enabled = TRUE; + dnsproxy_enabled = true; ns = connman_setting_get_string_list("FallbackNameservers"); - for (i = 0; ns != NULL && ns[i] != NULL; i += 1) { + for (i = 0; ns && ns[i]; i += 1) { DBG("server %s", ns[i]); append_resolver(-1, NULL, ns[i], 0, RESOLVER_FLAG_PUBLIC); } @@ -608,7 +670,7 @@ void __connman_resolver_cleanup(void) { DBG(""); - if (dnsproxy_enabled == TRUE) + if (dnsproxy_enabled) __connman_dnsproxy_cleanup(); else { GList *list; diff --git a/src/rfkill.c b/src/rfkill.c index e21b2a15..960cfea7 100644 --- a/src/rfkill.c +++ b/src/rfkill.c @@ -2,7 +2,7 @@ * * Connection Manager * - * Copyright (C) 2007-2012 Intel Corporation. All rights reserved. + * Copyright (C) 2007-2013 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 @@ -88,6 +88,7 @@ static enum rfkill_type convert_service_type(enum connman_service_type type) case CONNMAN_SERVICE_TYPE_ETHERNET: case CONNMAN_SERVICE_TYPE_VPN: case CONNMAN_SERVICE_TYPE_GADGET: + case CONNMAN_SERVICE_TYPE_P2P: case CONNMAN_SERVICE_TYPE_UNKNOWN: return NUM_RFKILL_TYPES; } @@ -141,8 +142,7 @@ static GIOStatus rfkill_process(GIOChannel *chan) return status; } -static gboolean rfkill_event(GIOChannel *chan, - GIOCondition cond, gpointer data) +static gboolean rfkill_event(GIOChannel *chan, GIOCondition cond, gpointer data) { if (cond & (G_IO_NVAL | G_IO_HUP | G_IO_ERR)) return FALSE; @@ -155,7 +155,7 @@ static gboolean rfkill_event(GIOChannel *chan, static GIOChannel *channel = NULL; -int __connman_rfkill_block(enum connman_service_type type, connman_bool_t block) +int __connman_rfkill_block(enum connman_service_type type, bool block) { uint8_t rfkill_type; struct rfkill_event event; @@ -225,7 +225,7 @@ void __connman_rfkill_cleanup(void) { DBG(""); - if (channel == NULL) + if (!channel) return; g_io_channel_shutdown(channel, TRUE, NULL); @@ -2,7 +2,7 @@ * * Connection Manager * - * Copyright (C) 2007-2012 Intel Corporation. All rights reserved. + * Copyright (C) 2007-2013 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 @@ -65,7 +65,6 @@ static guint update_timeout = 0; struct interface_data { int index; - char *name; char *ident; enum connman_service_type service_type; enum connman_device_type device_type; @@ -78,53 +77,54 @@ static void free_interface(gpointer data) struct interface_data *interface = data; __connman_technology_remove_interface(interface->service_type, - interface->index, interface->name, interface->ident); + interface->index, interface->ident); g_free(interface->ident); - g_free(interface->name); g_free(interface); } -static connman_bool_t ether_blacklisted(const char *name) +static bool ether_blacklisted(const char *name) { - if (name == NULL) - return TRUE; + if (!name) + return true; - if (__connman_device_isfiltered(name) == TRUE) - return TRUE; + if (__connman_device_isfiltered(name)) + return true; - return FALSE; + return false; } -static connman_bool_t wext_interface(char *ifname) +static bool wext_interface(char *ifname) { struct iwreq wrq; int fd, err; fd = socket(PF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0); if (fd < 0) - return FALSE; + return false; memset(&wrq, 0, sizeof(wrq)); - strncpy(wrq.ifr_name, ifname, IFNAMSIZ); + strncpy(wrq.ifr_name, ifname, sizeof(wrq.ifr_name) - 1); err = ioctl(fd, SIOCGIWNAME, &wrq); close(fd); if (err < 0) - return FALSE; + return false; - return TRUE; + return true; } static void read_uevent(struct interface_data *interface) { - char *filename, line[128]; - connman_bool_t found_devtype; + char *filename, *name, line[128]; + bool found_devtype; FILE *f; - if (ether_blacklisted(interface->name) == TRUE) { + name = connman_inet_ifname(interface->index); + + if (ether_blacklisted(name)) { interface->service_type = CONNMAN_SERVICE_TYPE_UNKNOWN; interface->device_type = CONNMAN_DEVICE_TYPE_UNKNOWN; } else { @@ -132,29 +132,31 @@ static void read_uevent(struct interface_data *interface) interface->device_type = CONNMAN_DEVICE_TYPE_ETHERNET; } - filename = g_strdup_printf("/sys/class/net/%s/uevent", - interface->name); + filename = g_strdup_printf("/sys/class/net/%s/uevent", name); f = fopen(filename, "re"); g_free(filename); - if (f == NULL) - return; + if (!f) { + interface->service_type = CONNMAN_SERVICE_TYPE_UNKNOWN; + interface->device_type = CONNMAN_DEVICE_TYPE_UNKNOWN; + goto out; + } - found_devtype = FALSE; + found_devtype = false; while (fgets(line, sizeof(line), f)) { char *pos; pos = strchr(line, '\n'); - if (pos == NULL) + if (!pos) continue; pos[0] = '\0'; if (strncmp(line, "DEVTYPE=", 8) != 0) continue; - found_devtype = TRUE; + found_devtype = true; if (strcmp(line + 8, "wlan") == 0) { interface->service_type = CONNMAN_SERVICE_TYPE_WIFI; @@ -178,16 +180,18 @@ static void read_uevent(struct interface_data *interface) fclose(f); if (found_devtype) - return; + goto out; /* We haven't got a DEVTYPE, let's check if it's a wireless device */ - if (wext_interface(interface->name)) { + if (wext_interface(name)) { interface->service_type = CONNMAN_SERVICE_TYPE_WIFI; interface->device_type = CONNMAN_DEVICE_TYPE_WIFI; - connman_error("%s runs an unsupported 802.11 driver", - interface->name); + connman_error("%s runs an unsupported 802.11 driver", name); } + +out: + g_free(name); } enum connman_device_type __connman_rtnl_get_device_type(int index) @@ -196,7 +200,7 @@ enum connman_device_type __connman_rtnl_get_device_type(int index) interface = g_hash_table_lookup(interface_list, GINT_TO_POINTER(index)); - if (interface == NULL) + if (!interface) return CONNMAN_DEVICE_TYPE_UNKNOWN; return interface->device_type; @@ -218,7 +222,7 @@ unsigned int connman_rtnl_add_newlink_watch(int index, struct watch_data *watch; watch = g_try_new0(struct watch_data, 1); - if (watch == NULL) + if (!watch) return 0; watch->id = ++watch_id; @@ -283,7 +287,7 @@ static void trigger_rtnl(int index, void *user_data) __connman_ipconfig_get_gateway_from_index(index, CONNMAN_IPCONFIG_TYPE_ALL); - if (gateway != NULL) + if (gateway) rtnl->newgateway(index, gateway); } } @@ -353,7 +357,7 @@ static const char *operstate2str(unsigned char operstate) return ""; } -static connman_bool_t extract_link(struct ifinfomsg *msg, int bytes, +static bool extract_link(struct ifinfomsg *msg, int bytes, struct ether_addr *address, const char **ifname, unsigned int *mtu, unsigned char *operstate, struct rtnl_link_stats *stats) @@ -364,41 +368,40 @@ static connman_bool_t extract_link(struct ifinfomsg *msg, int bytes, attr = RTA_NEXT(attr, bytes)) { switch (attr->rta_type) { case IFLA_ADDRESS: - if (address != NULL) + if (address) memcpy(address, RTA_DATA(attr), ETH_ALEN); break; case IFLA_IFNAME: - if (ifname != NULL) + if (ifname) *ifname = RTA_DATA(attr); break; case IFLA_MTU: - if (mtu != NULL) + if (mtu) *mtu = *((unsigned int *) RTA_DATA(attr)); break; case IFLA_STATS: - if (stats != NULL) + if (stats) memcpy(stats, RTA_DATA(attr), sizeof(struct rtnl_link_stats)); break; case IFLA_OPERSTATE: - if (operstate != NULL) + if (operstate) *operstate = *((unsigned char *) RTA_DATA(attr)); break; case IFLA_LINKMODE: break; case IFLA_WIRELESS: - return FALSE; + return false; } } - return TRUE; + return true; } static void process_newlink(unsigned short type, int index, unsigned flags, unsigned change, struct ifinfomsg *msg, int bytes) { struct ether_addr address = {{ 0, 0, 0, 0, 0, 0 }}; - struct ether_addr compare = {{ 0, 0, 0, 0, 0, 0 }}; struct rtnl_link_stats stats; unsigned char operstate = 0xff; struct interface_data *interface; @@ -408,8 +411,7 @@ static void process_newlink(unsigned short type, int index, unsigned flags, GSList *list; memset(&stats, 0, sizeof(stats)); - if (extract_link(msg, bytes, &address, &ifname, &mtu, &operstate, - &stats) == FALSE) + if (!extract_link(msg, bytes, &address, &ifname, &mtu, &operstate, &stats)) return; snprintf(ident, 13, "%02x%02x%02x%02x%02x%02x", @@ -428,6 +430,12 @@ static void process_newlink(unsigned short type, int index, unsigned flags, address.ether_addr_octet[4], address.ether_addr_octet[5]); + if (flags & IFF_SLAVE) { + connman_info("%s {newlink} ignoring slave, index %d address %s", + ifname, index, str); + return; + } + switch (type) { case ARPHRD_ETHER: case ARPHRD_LOOPBACK: @@ -439,9 +447,8 @@ static void process_newlink(unsigned short type, int index, unsigned flags, break; } - if (memcmp(&address, &compare, ETH_ALEN) != 0) - connman_info("%s {newlink} index %d address %s mtu %u", - ifname, index, str, mtu); + connman_info("%s {newlink} index %d address %s mtu %u", + ifname, index, str, mtu); if (operstate != 0xff) connman_info("%s {newlink} index %d operstate %u <%s>", @@ -449,10 +456,9 @@ static void process_newlink(unsigned short type, int index, unsigned flags, operstate2str(operstate)); interface = g_hash_table_lookup(interface_list, GINT_TO_POINTER(index)); - if (interface == NULL) { + if (!interface) { interface = g_new0(struct interface_data, 1); interface->index = index; - interface->name = g_strdup(ifname); interface->ident = g_strdup(ident); g_hash_table_insert(interface_list, @@ -476,9 +482,9 @@ static void process_newlink(unsigned short type, int index, unsigned flags, * __connman_technology_add_interface() expects the * technology to be there already. */ - if (interface != NULL) + if (interface) __connman_technology_add_interface(interface->service_type, - interface->index, interface->name, interface->ident); + interface->index, interface->ident); for (list = watch_list; list; list = list->next) { struct watch_data *watch = list->data; @@ -500,8 +506,7 @@ static void process_dellink(unsigned short type, int index, unsigned flags, GSList *list; memset(&stats, 0, sizeof(stats)); - if (extract_link(msg, bytes, NULL, &ifname, NULL, &operstate, - &stats) == FALSE) + if (!extract_link(msg, bytes, NULL, &ifname, NULL, &operstate, &stats)) return; if (operstate != 0xff) @@ -519,6 +524,8 @@ static void process_dellink(unsigned short type, int index, unsigned flags, switch (type) { case ARPHRD_ETHER: case ARPHRD_LOOPBACK: + case ARPHDR_PHONET_PIPE: + case ARPHRD_PPP: case ARPHRD_NONE: __connman_ipconfig_dellink(index, &stats); break; @@ -539,19 +546,19 @@ static void extract_ipv4_addr(struct ifaddrmsg *msg, int bytes, attr = RTA_NEXT(attr, bytes)) { switch (attr->rta_type) { case IFA_ADDRESS: - if (address != NULL) + if (address) *address = *((struct in_addr *) RTA_DATA(attr)); break; case IFA_LOCAL: - if (local != NULL) + if (local) *local = *((struct in_addr *) RTA_DATA(attr)); break; case IFA_BROADCAST: - if (broadcast != NULL) + if (broadcast) *broadcast = *((struct in_addr *) RTA_DATA(attr)); break; case IFA_LABEL: - if (label != NULL) + if (label) *label = RTA_DATA(attr); break; } @@ -568,11 +575,11 @@ static void extract_ipv6_addr(struct ifaddrmsg *msg, int bytes, attr = RTA_NEXT(attr, bytes)) { switch (attr->rta_type) { case IFA_ADDRESS: - if (addr != NULL) + if (addr) *addr = *((struct in6_addr *) RTA_DATA(attr)); break; case IFA_LOCAL: - if (local != NULL) + if (local) *local = *((struct in6_addr *) RTA_DATA(attr)); break; } @@ -582,18 +589,17 @@ static void extract_ipv6_addr(struct ifaddrmsg *msg, int bytes, static void process_newaddr(unsigned char family, unsigned char prefixlen, int index, struct ifaddrmsg *msg, int bytes) { + struct in_addr ipv4_addr = { INADDR_ANY }; + struct in6_addr ipv6_address, ipv6_local; const char *label = NULL; void *src; char ip_string[INET6_ADDRSTRLEN]; if (family == AF_INET) { - struct in_addr ipv4_addr = { INADDR_ANY }; extract_ipv4_addr(msg, bytes, &label, &ipv4_addr, NULL, NULL); src = &ipv4_addr; } else if (family == AF_INET6) { - struct in6_addr ipv6_address, ipv6_local; - extract_ipv6_addr(msg, bytes, &ipv6_address, &ipv6_local); if (IN6_IS_ADDR_LINKLOCAL(&ipv6_address)) return; @@ -603,7 +609,7 @@ static void process_newaddr(unsigned char family, unsigned char prefixlen, return; } - if (inet_ntop(family, src, ip_string, INET6_ADDRSTRLEN) == NULL) + if (!inet_ntop(family, src, ip_string, INET6_ADDRSTRLEN)) return; __connman_ipconfig_newaddr(index, family, label, @@ -623,18 +629,16 @@ static void process_newaddr(unsigned char family, unsigned char prefixlen, static void process_deladdr(unsigned char family, unsigned char prefixlen, int index, struct ifaddrmsg *msg, int bytes) { + struct in_addr ipv4_addr = { INADDR_ANY }; + struct in6_addr ipv6_address, ipv6_local; const char *label = NULL; void *src; char ip_string[INET6_ADDRSTRLEN]; if (family == AF_INET) { - struct in_addr ipv4_addr = { INADDR_ANY }; - extract_ipv4_addr(msg, bytes, &label, &ipv4_addr, NULL, NULL); src = &ipv4_addr; } else if (family == AF_INET6) { - struct in6_addr ipv6_address, ipv6_local; - extract_ipv6_addr(msg, bytes, &ipv6_address, &ipv6_local); if (IN6_IS_ADDR_LINKLOCAL(&ipv6_address)) return; @@ -644,7 +648,7 @@ static void process_deladdr(unsigned char family, unsigned char prefixlen, return; } - if (inet_ntop(family, src, ip_string, INET6_ADDRSTRLEN) == NULL) + if (!inet_ntop(family, src, ip_string, INET6_ADDRSTRLEN)) return; __connman_ipconfig_deladdr(index, family, label, @@ -661,15 +665,15 @@ static void extract_ipv4_route(struct rtmsg *msg, int bytes, int *index, attr = RTA_NEXT(attr, bytes)) { switch (attr->rta_type) { case RTA_DST: - if (dst != NULL) + if (dst) *dst = *((struct in_addr *) RTA_DATA(attr)); break; case RTA_GATEWAY: - if (gateway != NULL) + if (gateway) *gateway = *((struct in_addr *) RTA_DATA(attr)); break; case RTA_OIF: - if (index != NULL) + if (index) *index = *((int *) RTA_DATA(attr)); break; } @@ -686,16 +690,16 @@ static void extract_ipv6_route(struct rtmsg *msg, int bytes, int *index, attr = RTA_NEXT(attr, bytes)) { switch (attr->rta_type) { case RTA_DST: - if (dst != NULL) + if (dst) *dst = *((struct in6_addr *) RTA_DATA(attr)); break; case RTA_GATEWAY: - if (gateway != NULL) + if (gateway) *gateway = *((struct in6_addr *) RTA_DATA(attr)); break; case RTA_OIF: - if (index != NULL) + if (index) *index = *((int *) RTA_DATA(attr)); break; } @@ -947,6 +951,9 @@ static void rtnl_newlink(struct nlmsghdr *hdr) rtnl_link(hdr); + if (hdr->nlmsg_type == IFLA_WIRELESS) + connman_warn_once("Obsolete WEXT WiFi driver detected"); + process_newlink(msg->ifi_type, msg->ifi_index, msg->ifi_flags, msg->ifi_change, msg, IFA_PAYLOAD(hdr)); } @@ -1074,20 +1081,20 @@ static void rtnl_route(struct nlmsghdr *hdr) } } -static connman_bool_t is_route_rtmsg(struct rtmsg *msg) +static bool is_route_rtmsg(struct rtmsg *msg) { if (msg->rtm_table != RT_TABLE_MAIN) - return FALSE; + return false; if (msg->rtm_protocol != RTPROT_BOOT && msg->rtm_protocol != RTPROT_KERNEL) - return FALSE; + return false; if (msg->rtm_type != RTN_UNICAST) - return FALSE; + return false; - return TRUE; + return true; } static void rtnl_newroute(struct nlmsghdr *hdr) @@ -1238,7 +1245,7 @@ static void rtnl_newnduseropt(struct nlmsghdr *hdr) g_free(domains); domains = rtnl_nd_opt_dnssl(opt, &lifetime); - for (i = 0; domains != NULL && domains[i] != NULL; i++) + for (i = 0; domains && domains[i]; i++) connman_resolver_append_lifetime(index, domains[i], NULL, lifetime); } @@ -1344,13 +1351,13 @@ static int process_response(guint32 seq) DBG("seq %d", seq); req = find_request(seq); - if (req != NULL) { + if (req) { request_list = g_slist_remove(request_list, req); g_free(req); } req = g_slist_nth_data(request_list, 0); - if (req == NULL) + if (!req) return 0; return send_request(req); @@ -1413,8 +1420,7 @@ static void rtnl_message(void *buf, size_t len) } } -static gboolean netlink_event(GIOChannel *chan, - GIOCondition cond, gpointer data) +static gboolean netlink_event(GIOChannel *chan, GIOCondition cond, gpointer data) { unsigned char buf[4096]; struct sockaddr_nl nladdr; @@ -1459,7 +1465,7 @@ static int send_getlink(void) DBG(""); req = g_try_malloc0(RTNL_REQUEST_SIZE); - if (req == NULL) + if (!req) return -ENOMEM; req->hdr.nlmsg_len = RTNL_REQUEST_SIZE; @@ -1479,7 +1485,7 @@ static int send_getaddr(void) DBG(""); req = g_try_malloc0(RTNL_REQUEST_SIZE); - if (req == NULL) + if (!req) return -ENOMEM; req->hdr.nlmsg_len = RTNL_REQUEST_SIZE; @@ -1499,7 +1505,7 @@ static int send_getroute(void) DBG(""); req = g_try_malloc0(RTNL_REQUEST_SIZE); - if (req == NULL) + if (!req) return -ENOMEM; req->hdr.nlmsg_len = RTNL_REQUEST_SIZE; @@ -1570,7 +1576,7 @@ unsigned int __connman_rtnl_update_interval_remove(unsigned int interval) update_list = g_slist_remove(update_list, GINT_TO_POINTER(interval)); - if (update_list != NULL) + if (update_list) min = GPOINTER_TO_UINT(g_slist_nth_data(update_list, 0)); if (min > update_interval) diff --git a/src/service.c b/src/service.c index 9c4f3fbc..cbca669e 100644 --- a/src/service.c +++ b/src/service.c @@ -2,7 +2,7 @@ * * Connection Manager * - * Copyright (C) 2007-2012 Intel Corporation. All rights reserved. + * Copyright (C) 2007-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 @@ -45,26 +45,26 @@ static GList *service_list = NULL; static GHashTable *service_hash = NULL; static GSList *counter_list = NULL; static unsigned int autoconnect_timeout = 0; +static unsigned int vpn_autoconnect_timeout = 0; static struct connman_service *current_default = NULL; -static connman_bool_t services_dirty = FALSE; +static bool services_dirty = false; struct connman_stats { - connman_bool_t valid; - connman_bool_t enabled; + bool valid; + bool enabled; struct connman_stats_data data_last; struct connman_stats_data data; GTimer *timer; }; struct connman_stats_counter { - connman_bool_t append_all; + bool append_all; struct connman_stats stats; struct connman_stats stats_roaming; }; struct connman_service { int refcount; - int session_usage_count; char *identifier; char *path; enum connman_service_type type; @@ -73,19 +73,18 @@ struct connman_service { enum connman_service_state state_ipv4; enum connman_service_state state_ipv6; enum connman_service_error error; + enum connman_service_connect_reason connect_reason; uint8_t strength; - connman_bool_t favorite; - connman_bool_t immutable; - connman_bool_t hidden; - connman_bool_t ignore; - connman_bool_t autoconnect; - connman_bool_t userconnect; + bool favorite; + bool immutable; + bool hidden; + bool ignore; + bool autoconnect; GTimeVal modified; unsigned int order; char *name; char *passphrase; - char *agent_passphrase; - connman_bool_t roaming; + bool roaming; struct connman_ipconfig *ipconfig_ipv4; struct connman_ipconfig *ipconfig_ipv6; struct connman_network *network; @@ -94,6 +93,7 @@ struct connman_service { char **nameservers_config; char **nameservers_auto; char **domains; + char *hostname; char *domainname; char **timeservers; char **timeservers_config; @@ -117,16 +117,16 @@ struct connman_service { char **proxies; char **excludes; char *pac; - connman_bool_t wps; + bool wps; int online_check_count; - connman_bool_t do_split_routing; - connman_bool_t new_service; - connman_bool_t hidden_service; + bool do_split_routing; + bool new_service; + bool hidden_service; char *config_file; char *config_entry; }; -static connman_bool_t allow_property_changed(struct connman_service *service); +static bool allow_property_changed(struct connman_service *service); static struct connman_ipconfig *create_ip4config(struct connman_service *service, int index, enum connman_ipconfig_method method); @@ -144,7 +144,7 @@ static void compare_path(gpointer value, gpointer user_data) struct connman_service *service = value; struct find_data *data = user_data; - if (data->service != NULL) + if (data->service) return; if (g_strcmp0(service->path, data->path) == 0) @@ -162,6 +162,23 @@ static struct connman_service *find_service(const char *path) return data.service; } +static const char *reason2string(enum connman_service_connect_reason reason) +{ + + switch (reason) { + case CONNMAN_SERVICE_CONNECT_REASON_NONE: + return "none"; + case CONNMAN_SERVICE_CONNECT_REASON_USER: + return "user"; + case CONNMAN_SERVICE_CONNECT_REASON_AUTO: + return "auto"; + case CONNMAN_SERVICE_CONNECT_REASON_SESSION: + return "session"; + } + + return "unknown"; +} + const char *__connman_service_type2string(enum connman_service_type type) { switch (type) { @@ -183,6 +200,8 @@ const char *__connman_service_type2string(enum connman_service_type type) return "vpn"; case CONNMAN_SERVICE_TYPE_GADGET: return "gadget"; + case CONNMAN_SERVICE_TYPE_P2P: + return "p2p"; } return NULL; @@ -190,7 +209,7 @@ const char *__connman_service_type2string(enum connman_service_type type) enum connman_service_type __connman_service_string2type(const char *str) { - if (str == NULL) + if (!str) return CONNMAN_SERVICE_TYPE_UNKNOWN; if (strcmp(str, "ethernet") == 0) @@ -209,6 +228,8 @@ enum connman_service_type __connman_service_string2type(const char *str) return CONNMAN_SERVICE_TYPE_GPS; if (strcmp(str, "system") == 0) return CONNMAN_SERVICE_TYPE_SYSTEM; + if (strcmp(str, "p2p") == 0) + return CONNMAN_SERVICE_TYPE_P2P; return CONNMAN_SERVICE_TYPE_UNKNOWN; } @@ -321,67 +342,120 @@ static enum connman_service_proxy_method string2proxymethod(const char *method) return CONNMAN_SERVICE_PROXY_METHOD_UNKNOWN; } +int __connman_service_load_modifiable(struct connman_service *service) +{ + GKeyFile *keyfile; + GError *error = NULL; + gchar *str; + bool autoconnect; + + DBG("service %p", service); + + keyfile = connman_storage_load_service(service->identifier); + if (!keyfile) + return -EIO; + + switch (service->type) { + case CONNMAN_SERVICE_TYPE_UNKNOWN: + case CONNMAN_SERVICE_TYPE_SYSTEM: + case CONNMAN_SERVICE_TYPE_GPS: + case CONNMAN_SERVICE_TYPE_P2P: + break; + case CONNMAN_SERVICE_TYPE_VPN: + service->do_split_routing = g_key_file_get_boolean(keyfile, + service->identifier, "SplitRouting", NULL); + /* fall through */ + case CONNMAN_SERVICE_TYPE_WIFI: + case CONNMAN_SERVICE_TYPE_GADGET: + case CONNMAN_SERVICE_TYPE_BLUETOOTH: + case CONNMAN_SERVICE_TYPE_CELLULAR: + case CONNMAN_SERVICE_TYPE_ETHERNET: + autoconnect = g_key_file_get_boolean(keyfile, + service->identifier, "AutoConnect", &error); + if (!error) + service->autoconnect = autoconnect; + g_clear_error(&error); + break; + } + + str = g_key_file_get_string(keyfile, + service->identifier, "Modified", NULL); + if (str) { + g_time_val_from_iso8601(str, &service->modified); + g_free(str); + } + + g_key_file_free(keyfile); + + return 0; +} + static int service_load(struct connman_service *service) { GKeyFile *keyfile; GError *error = NULL; gsize length; gchar *str; - connman_bool_t autoconnect; + bool autoconnect; unsigned int ssid_len; int err = 0; DBG("service %p", service); keyfile = connman_storage_load_service(service->identifier); - if (keyfile == NULL) { - service->new_service = TRUE; + if (!keyfile) { + service->new_service = true; return -EIO; } else - service->new_service = FALSE; + service->new_service = false; switch (service->type) { case CONNMAN_SERVICE_TYPE_UNKNOWN: case CONNMAN_SERVICE_TYPE_SYSTEM: case CONNMAN_SERVICE_TYPE_GPS: - case CONNMAN_SERVICE_TYPE_GADGET: + case CONNMAN_SERVICE_TYPE_P2P: break; case CONNMAN_SERVICE_TYPE_VPN: service->do_split_routing = g_key_file_get_boolean(keyfile, service->identifier, "SplitRouting", NULL); + autoconnect = g_key_file_get_boolean(keyfile, + service->identifier, "AutoConnect", &error); + if (!error) + service->autoconnect = autoconnect; + g_clear_error(&error); break; case CONNMAN_SERVICE_TYPE_WIFI: - if (service->name == NULL) { + if (!service->name) { gchar *name; name = g_key_file_get_string(keyfile, service->identifier, "Name", NULL); - if (name != NULL) { + if (name) { g_free(service->name); service->name = name; } - if (service->network != NULL) + if (service->network) connman_network_set_name(service->network, name); } if (service->network && - connman_network_get_blob(service->network, - "WiFi.SSID", &ssid_len) == NULL) { + !connman_network_get_blob(service->network, + "WiFi.SSID", &ssid_len)) { gchar *hex_ssid; hex_ssid = g_key_file_get_string(keyfile, service->identifier, "SSID", NULL); - if (hex_ssid != NULL) { + if (hex_ssid) { gchar *ssid; unsigned int i, j = 0, hex; size_t hex_ssid_len = strlen(hex_ssid); ssid = g_try_malloc0(hex_ssid_len / 2); - if (ssid == NULL) { + if (!ssid) { g_free(hex_ssid); err = -ENOMEM; goto done; @@ -400,6 +474,7 @@ static int service_load(struct connman_service *service) } /* fall through */ + case CONNMAN_SERVICE_TYPE_GADGET: case CONNMAN_SERVICE_TYPE_BLUETOOTH: case CONNMAN_SERVICE_TYPE_CELLULAR: service->favorite = g_key_file_get_boolean(keyfile, @@ -407,8 +482,8 @@ static int service_load(struct connman_service *service) str = g_key_file_get_string(keyfile, service->identifier, "Failure", NULL); - if (str != NULL) { - if (service->favorite == FALSE) + if (str) { + if (!service->favorite) service->state_ipv4 = service->state_ipv6 = CONNMAN_SERVICE_STATE_FAILURE; service->error = string2error(str); @@ -419,7 +494,7 @@ static int service_load(struct connman_service *service) case CONNMAN_SERVICE_TYPE_ETHERNET: autoconnect = g_key_file_get_boolean(keyfile, service->identifier, "AutoConnect", &error); - if (error == NULL) + if (!error) service->autoconnect = autoconnect; g_clear_error(&error); break; @@ -427,71 +502,71 @@ static int service_load(struct connman_service *service) str = g_key_file_get_string(keyfile, service->identifier, "Modified", NULL); - if (str != NULL) { + if (str) { g_time_val_from_iso8601(str, &service->modified); g_free(str); } str = g_key_file_get_string(keyfile, service->identifier, "Passphrase", NULL); - if (str != NULL) { + if (str) { g_free(service->passphrase); service->passphrase = str; } - if (service->ipconfig_ipv4 != NULL) + if (service->ipconfig_ipv4) __connman_ipconfig_load(service->ipconfig_ipv4, keyfile, service->identifier, "IPv4."); - if (service->ipconfig_ipv6 != NULL) + if (service->ipconfig_ipv6) __connman_ipconfig_load(service->ipconfig_ipv6, keyfile, service->identifier, "IPv6."); service->nameservers_config = g_key_file_get_string_list(keyfile, service->identifier, "Nameservers", &length, NULL); - if (service->nameservers_config != NULL && length == 0) { + if (service->nameservers_config && length == 0) { g_strfreev(service->nameservers_config); service->nameservers_config = NULL; } service->timeservers_config = g_key_file_get_string_list(keyfile, service->identifier, "Timeservers", &length, NULL); - if (service->timeservers_config != NULL && length == 0) { + if (service->timeservers_config && length == 0) { g_strfreev(service->timeservers_config); service->timeservers_config = NULL; } service->domains = g_key_file_get_string_list(keyfile, service->identifier, "Domains", &length, NULL); - if (service->domains != NULL && length == 0) { + if (service->domains && length == 0) { g_strfreev(service->domains); service->domains = NULL; } str = g_key_file_get_string(keyfile, service->identifier, "Proxy.Method", NULL); - if (str != NULL) + if (str) service->proxy_config = string2proxymethod(str); g_free(str); service->proxies = g_key_file_get_string_list(keyfile, service->identifier, "Proxy.Servers", &length, NULL); - if (service->proxies != NULL && length == 0) { + if (service->proxies && length == 0) { g_strfreev(service->proxies); service->proxies = NULL; } service->excludes = g_key_file_get_string_list(keyfile, service->identifier, "Proxy.Excludes", &length, NULL); - if (service->excludes != NULL && length == 0) { + if (service->excludes && length == 0) { g_strfreev(service->excludes); service->excludes = NULL; } str = g_key_file_get_string(keyfile, service->identifier, "Proxy.URL", NULL); - if (str != NULL) { + if (str) { g_free(service->pac); service->pac = str; } @@ -515,14 +590,14 @@ static int service_save(struct connman_service *service) DBG("service %p new %d", service, service->new_service); - if (service->new_service == TRUE) + if (service->new_service) return -ESRCH; keyfile = __connman_storage_open_service(service->identifier); - if (keyfile == NULL) + if (!keyfile) return -EIO; - if (service->name != NULL) + if (service->name) g_key_file_set_string(keyfile, service->identifier, "Name", service->name); @@ -530,11 +605,14 @@ static int service_save(struct connman_service *service) case CONNMAN_SERVICE_TYPE_UNKNOWN: case CONNMAN_SERVICE_TYPE_SYSTEM: case CONNMAN_SERVICE_TYPE_GPS: - case CONNMAN_SERVICE_TYPE_GADGET: + case CONNMAN_SERVICE_TYPE_P2P: break; case CONNMAN_SERVICE_TYPE_VPN: g_key_file_set_boolean(keyfile, service->identifier, "SplitRouting", service->do_split_routing); + if (service->favorite) + g_key_file_set_boolean(keyfile, service->identifier, + "AutoConnect", service->autoconnect); break; case CONNMAN_SERVICE_TYPE_WIFI: if (service->network) { @@ -544,13 +622,13 @@ static int service_save(struct connman_service *service) ssid = connman_network_get_blob(service->network, "WiFi.SSID", &ssid_len); - if (ssid != NULL && ssid_len > 0 && ssid[0] != '\0') { + if (ssid && ssid_len > 0 && ssid[0] != '\0') { char *identifier = service->identifier; GString *ssid_str; unsigned int i; ssid_str = g_string_sized_new(ssid_len * 2); - if (ssid_str == NULL) { + if (!ssid_str) { err = -ENOMEM; goto done; } @@ -571,6 +649,7 @@ static int service_save(struct connman_service *service) } /* fall through */ + case CONNMAN_SERVICE_TYPE_GADGET: case CONNMAN_SERVICE_TYPE_BLUETOOTH: case CONNMAN_SERVICE_TYPE_CELLULAR: g_key_file_set_boolean(keyfile, service->identifier, @@ -579,7 +658,7 @@ static int service_save(struct connman_service *service) if (service->state_ipv4 == CONNMAN_SERVICE_STATE_FAILURE || service->state_ipv6 == CONNMAN_SERVICE_STATE_FAILURE) { const char *failure = error2string(service->error); - if (failure != NULL) + if (failure) g_key_file_set_string(keyfile, service->identifier, "Failure", failure); @@ -590,35 +669,35 @@ static int service_save(struct connman_service *service) /* fall through */ case CONNMAN_SERVICE_TYPE_ETHERNET: - if (service->favorite == TRUE) + if (service->favorite) g_key_file_set_boolean(keyfile, service->identifier, "AutoConnect", service->autoconnect); break; } str = g_time_val_to_iso8601(&service->modified); - if (str != NULL) { + if (str) { g_key_file_set_string(keyfile, service->identifier, "Modified", str); g_free(str); } - if (service->passphrase != NULL && strlen(service->passphrase) > 0) + if (service->passphrase && strlen(service->passphrase) > 0) g_key_file_set_string(keyfile, service->identifier, "Passphrase", service->passphrase); else g_key_file_remove_key(keyfile, service->identifier, "Passphrase", NULL); - if (service->ipconfig_ipv4 != NULL) + if (service->ipconfig_ipv4) __connman_ipconfig_save(service->ipconfig_ipv4, keyfile, service->identifier, "IPv4."); - if (service->ipconfig_ipv6 != NULL) + if (service->ipconfig_ipv6) __connman_ipconfig_save(service->ipconfig_ipv6, keyfile, service->identifier, "IPv6."); - if (service->nameservers_config != NULL) { + if (service->nameservers_config) { guint len = g_strv_length(service->nameservers_config); g_key_file_set_string_list(keyfile, service->identifier, @@ -628,7 +707,7 @@ static int service_save(struct connman_service *service) g_key_file_remove_key(keyfile, service->identifier, "Nameservers", NULL); - if (service->timeservers_config != NULL) { + if (service->timeservers_config) { guint len = g_strv_length(service->timeservers_config); g_key_file_set_string_list(keyfile, service->identifier, @@ -638,7 +717,7 @@ static int service_save(struct connman_service *service) g_key_file_remove_key(keyfile, service->identifier, "Timeservers", NULL); - if (service->domains != NULL) { + if (service->domains) { guint len = g_strv_length(service->domains); g_key_file_set_string_list(keyfile, service->identifier, @@ -649,11 +728,11 @@ static int service_save(struct connman_service *service) "Domains", NULL); cst_str = proxymethod2string(service->proxy_config); - if (cst_str != NULL) + if (cst_str) g_key_file_set_string(keyfile, service->identifier, "Proxy.Method", cst_str); - if (service->proxies != NULL) { + if (service->proxies) { guint len = g_strv_length(service->proxies); g_key_file_set_string_list(keyfile, service->identifier, @@ -663,7 +742,7 @@ static int service_save(struct connman_service *service) g_key_file_remove_key(keyfile, service->identifier, "Proxy.Servers", NULL); - if (service->excludes != NULL) { + if (service->excludes) { guint len = g_strv_length(service->excludes); g_key_file_set_string_list(keyfile, service->identifier, @@ -673,22 +752,22 @@ static int service_save(struct connman_service *service) g_key_file_remove_key(keyfile, service->identifier, "Proxy.Excludes", NULL); - if (service->pac != NULL && strlen(service->pac) > 0) + if (service->pac && strlen(service->pac) > 0) g_key_file_set_string(keyfile, service->identifier, "Proxy.URL", service->pac); else g_key_file_remove_key(keyfile, service->identifier, "Proxy.URL", NULL); - if (service->hidden_service == TRUE) + if (service->hidden_service) g_key_file_set_boolean(keyfile, service->identifier, "Hidden", TRUE); - if (service->config_file != NULL && strlen(service->config_file) > 0) + if (service->config_file && strlen(service->config_file) > 0) g_key_file_set_string(keyfile, service->identifier, "Config.file", service->config_file); - if (service->config_entry != NULL && + if (service->config_entry && strlen(service->config_entry) > 0) g_key_file_set_string(keyfile, service->identifier, "Config.ident", service->config_entry); @@ -703,6 +782,9 @@ done: void __connman_service_save(struct connman_service *service) { + if (!service) + return; + service_save(service); } @@ -793,14 +875,14 @@ done: return result; } -static connman_bool_t is_connecting_state(struct connman_service *service, +static bool is_connecting_state(struct connman_service *service, enum connman_service_state state) { switch (state) { case CONNMAN_SERVICE_STATE_UNKNOWN: case CONNMAN_SERVICE_STATE_IDLE: case CONNMAN_SERVICE_STATE_FAILURE: - if (service->network != NULL) + if (service->network) return connman_network_get_connecting(service->network); case CONNMAN_SERVICE_STATE_DISCONNECT: case CONNMAN_SERVICE_STATE_READY: @@ -808,13 +890,13 @@ static connman_bool_t is_connecting_state(struct connman_service *service, break; case CONNMAN_SERVICE_STATE_ASSOCIATION: case CONNMAN_SERVICE_STATE_CONFIGURATION: - return TRUE; + return true; } - return FALSE; + return false; } -static connman_bool_t is_connected_state(const struct connman_service *service, +static bool is_connected_state(const struct connman_service *service, enum connman_service_state state) { switch (state) { @@ -827,13 +909,13 @@ static connman_bool_t is_connected_state(const struct connman_service *service, break; case CONNMAN_SERVICE_STATE_READY: case CONNMAN_SERVICE_STATE_ONLINE: - return TRUE; + return true; } - return FALSE; + return false; } -static connman_bool_t is_idle_state(const struct connman_service *service, +static bool is_idle_state(const struct connman_service *service, enum connman_service_state state) { switch (state) { @@ -846,31 +928,24 @@ static connman_bool_t is_idle_state(const struct connman_service *service, case CONNMAN_SERVICE_STATE_FAILURE: break; case CONNMAN_SERVICE_STATE_IDLE: - return TRUE; + return true; } - return FALSE; + return false; } -static connman_bool_t is_connecting(struct connman_service *service) +static bool is_connecting(struct connman_service *service) { return is_connecting_state(service, service->state); } -static connman_bool_t is_connected(struct connman_service *service) +static bool is_connected(struct connman_service *service) { return is_connected_state(service, service->state); } static int nameserver_get_index(struct connman_service *service) { - int index; - - index = __connman_service_get_index(service); - - if (index < 0) - return -1; - switch (combine_state(service->state_ipv4, service->state_ipv6)) { case CONNMAN_SERVICE_STATE_UNKNOWN: case CONNMAN_SERVICE_STATE_IDLE: @@ -884,7 +959,7 @@ static int nameserver_get_index(struct connman_service *service) break; } - return index; + return __connman_service_get_index(service); } static void remove_nameservers(struct connman_service *service, @@ -892,7 +967,7 @@ static void remove_nameservers(struct connman_service *service, { int i; - if (ns == NULL) + if (!ns) return; if (index < 0) @@ -901,7 +976,7 @@ static void remove_nameservers(struct connman_service *service, if (index < 0) return; - for (i = 0; ns[i] != NULL; i++) + for (i = 0; ns[i]; i++) connman_resolver_remove(index, NULL, ns[i]); } @@ -910,7 +985,7 @@ static void remove_searchdomains(struct connman_service *service, { int i; - if (sd == NULL) + if (!sd) return; if (index < 0) @@ -919,13 +994,29 @@ static void remove_searchdomains(struct connman_service *service, if (index < 0) return; - for (i = 0; sd[i] != NULL; i++) + for (i = 0; sd[i]; i++) connman_resolver_remove(index, sd[i], NULL); } +static bool nameserver_available(struct connman_service *service, char *ns) +{ + int family; + + family = connman_inet_check_ipaddress(ns); + + if (family == AF_INET) + return is_connected_state(service, service->state_ipv4); + + if (family == AF_INET6) + return is_connected_state(service, service->state_ipv6); + + return false; +} + static void update_nameservers(struct connman_service *service) { int index; + char *ns; index = __connman_service_get_index(service); if (index < 0) @@ -946,7 +1037,7 @@ static void update_nameservers(struct connman_service *service) break; } - if (service->nameservers_config != NULL) { + if (service->nameservers_config) { int i; remove_nameservers(service, index, service->nameservers); @@ -954,21 +1045,29 @@ static void update_nameservers(struct connman_service *service) i = g_strv_length(service->nameservers_config); while (i != 0) { i--; - connman_resolver_append(index, NULL, - service->nameservers_config[i]); + + ns = service->nameservers_config[i]; + + if (nameserver_available(service, ns)) + connman_resolver_append(index, NULL, ns); } - } else if (service->nameservers != NULL) { + } else if (service->nameservers) { int i; + remove_nameservers(service, index, service->nameservers); + i = g_strv_length(service->nameservers); while (i != 0) { i--; - connman_resolver_append(index, NULL, - service->nameservers[i]); + + ns = service->nameservers[i]; + + if (nameserver_available(service, ns)) + connman_resolver_append(index, NULL, ns); } } - if (service->domains != NULL) { + if (service->domains) { char *searchdomains[2] = {NULL, NULL}; int i; @@ -981,7 +1080,7 @@ static void update_nameservers(struct connman_service *service) connman_resolver_append(index, service->domains[i], NULL); } - } else if (service->domainname != NULL) + } else if (service->domainname) connman_resolver_append(index, service->domainname, NULL); connman_resolver_flush(); @@ -993,26 +1092,26 @@ static void update_nameservers(struct connman_service *service) * for details) and not through service.c */ int __connman_service_nameserver_append(struct connman_service *service, - const char *nameserver, gboolean is_auto) + const char *nameserver, bool is_auto) { char **nameservers; int len, i; DBG("service %p nameserver %s auto %d", service, nameserver, is_auto); - if (nameserver == NULL) + if (!nameserver) return -EINVAL; - if (is_auto == TRUE) + if (is_auto) nameservers = service->nameservers_auto; else nameservers = service->nameservers; - for (i = 0; nameservers != NULL && nameservers[i] != NULL; i++) + for (i = 0; nameservers && nameservers[i]; i++) if (g_strcmp0(nameservers[i], nameserver) == 0) return -EEXIST; - if (nameservers != NULL) { + if (nameservers) { len = g_strv_length(nameservers); nameservers = g_try_renew(char *, nameservers, len + 2); } else { @@ -1020,16 +1119,16 @@ int __connman_service_nameserver_append(struct connman_service *service, nameservers = g_try_new0(char *, len + 2); } - if (nameservers == NULL) + if (!nameservers) return -ENOMEM; nameservers[len] = g_strdup(nameserver); - if (nameservers[len] == NULL) + if (!nameservers[len]) return -ENOMEM; nameservers[len + 1] = NULL; - if (is_auto == TRUE) { + if (is_auto) { service->nameservers_auto = nameservers; } else { service->nameservers = nameservers; @@ -1040,39 +1139,39 @@ int __connman_service_nameserver_append(struct connman_service *service, } int __connman_service_nameserver_remove(struct connman_service *service, - const char *nameserver, gboolean is_auto) + const char *nameserver, bool is_auto) { char **servers, **nameservers; - gboolean found = FALSE; + bool found = false; int len, i, j; DBG("service %p nameserver %s auto %d", service, nameserver, is_auto); - if (nameserver == NULL) + if (!nameserver) return -EINVAL; - if (is_auto == TRUE) + if (is_auto) nameservers = service->nameservers_auto; else nameservers = service->nameservers; - if (nameservers == NULL) + if (!nameservers) return 0; - for (i = 0; nameservers != NULL && nameservers[i] != NULL; i++) + for (i = 0; nameservers && nameservers[i]; i++) if (g_strcmp0(nameservers[i], nameserver) == 0) { - found = TRUE; + found = true; break; } - if (found == FALSE) + if (!found) return 0; len = g_strv_length(nameservers); if (len == 1) { g_strfreev(nameservers); - if (is_auto == TRUE) + if (is_auto) service->nameservers_auto = NULL; else service->nameservers = NULL; @@ -1081,13 +1180,13 @@ int __connman_service_nameserver_remove(struct connman_service *service, } servers = g_try_new0(char *, len); - if (servers == NULL) + if (!servers) return -ENOMEM; for (i = 0, j = 0; i < len; i++) { if (g_strcmp0(nameservers[i], nameserver) != 0) { servers[j] = g_strdup(nameservers[i]); - if (servers[j] == NULL) + if (!servers[j]) return -ENOMEM; j++; } @@ -1097,7 +1196,7 @@ int __connman_service_nameserver_remove(struct connman_service *service, g_strfreev(nameservers); nameservers = servers; - if (is_auto == TRUE) { + if (is_auto) { service->nameservers_auto = nameservers; } else { service->nameservers = nameservers; @@ -1120,7 +1219,7 @@ static void add_nameserver_route(int family, int index, char *nameserver, { switch (family) { case AF_INET: - if (connman_inet_compare_subnet(index, nameserver) == TRUE) + if (connman_inet_compare_subnet(index, nameserver)) break; if (connman_inet_add_host_route(index, nameserver, gw) < 0) @@ -1142,7 +1241,7 @@ static void nameserver_add_routes(int index, char **nameservers, { int i, family; - for (i = 0; nameservers[i] != NULL; i++) { + for (i = 0; nameservers[i]; i++) { family = connman_inet_check_ipaddress(nameservers[i]); if (family < 0) continue; @@ -1156,7 +1255,7 @@ static void nameserver_del_routes(int index, char **nameservers, { int i, family; - for (i = 0; nameservers[i] != NULL; i++) { + for (i = 0; nameservers[i]; i++) { family = connman_inet_check_ipaddress(nameservers[i]); if (family < 0) continue; @@ -1179,23 +1278,20 @@ static void nameserver_del_routes(int index, char **nameservers, void __connman_service_nameserver_add_routes(struct connman_service *service, const char *gw) { - int index = -1; + int index; - if (service == NULL) + if (!service) return; - if (service->network != NULL) - index = connman_network_get_index(service->network); - else if (service->provider != NULL) - index = connman_provider_get_index(service->provider); + index = __connman_service_get_index(service); - if (service->nameservers_config != NULL) { + if (service->nameservers_config) { /* * Configured nameserver takes preference over the * discoverd nameserver gathered from DHCP, VPN, etc. */ nameserver_add_routes(index, service->nameservers_config, gw); - } else if (service->nameservers != NULL) { + } else if (service->nameservers) { /* * We add nameservers host routes for nameservers that * are not on our subnet. For those who are, the subnet @@ -1210,32 +1306,29 @@ void __connman_service_nameserver_add_routes(struct connman_service *service, void __connman_service_nameserver_del_routes(struct connman_service *service, enum connman_ipconfig_type type) { - int index = -1; + int index; - if (service == NULL) + if (!service) return; - if (service->network != NULL) - index = connman_network_get_index(service->network); - else if (service->provider != NULL) - index = connman_provider_get_index(service->provider); + index = __connman_service_get_index(service); - if (service->nameservers_config != NULL) + if (service->nameservers_config) nameserver_del_routes(index, service->nameservers_config, type); - else if (service->nameservers != NULL) + else if (service->nameservers) nameserver_del_routes(index, service->nameservers, type); } static struct connman_stats *stats_get(struct connman_service *service) { - if (service->roaming == TRUE) + if (service->roaming) return &service->stats_roaming; else return &service->stats; } -static connman_bool_t stats_enabled(struct connman_service *service) +static bool stats_enabled(struct connman_service *service) { struct connman_stats *stats = stats_get(service); @@ -1248,10 +1341,10 @@ static void stats_start(struct connman_service *service) DBG("service %p", service); - if (stats->timer == NULL) + if (!stats->timer) return; - stats->enabled = TRUE; + stats->enabled = true; stats->data_last.time = stats->data.time; g_timer_start(stats->timer); @@ -1264,10 +1357,10 @@ static void stats_stop(struct connman_service *service) DBG("service %p", service); - if (stats->timer == NULL) + if (!stats->timer) return; - if (stats->enabled == FALSE) + if (!stats->enabled) return; g_timer_stop(stats->timer); @@ -1275,7 +1368,7 @@ static void stats_stop(struct connman_service *service) seconds = g_timer_elapsed(stats->timer, NULL); stats->data.time = stats->data_last.time + seconds; - stats->enabled = FALSE; + stats->enabled = false; } static void reset_stats(struct connman_service *service) @@ -1283,7 +1376,7 @@ static void reset_stats(struct connman_service *service) DBG("service %p", service); /* home */ - service->stats.valid = FALSE; + service->stats.valid = false; service->stats.data.rx_packets = 0; service->stats.data.tx_packets = 0; @@ -1299,7 +1392,7 @@ static void reset_stats(struct connman_service *service) g_timer_reset(service->stats.timer); /* roaming */ - service->stats_roaming.valid = FALSE; + service->stats_roaming.valid = false; service->stats_roaming.data.rx_packets = 0; service->stats_roaming.data.tx_packets = 0; @@ -1319,17 +1412,29 @@ struct connman_service *__connman_service_get_default(void) { struct connman_service *service; - if (service_list == NULL) + if (!service_list) return NULL; service = service_list->data; - if (is_connected(service) == FALSE) + if (!is_connected(service)) return NULL; return service; } +bool __connman_service_index_is_default(int index) +{ + struct connman_service *service; + + if (index < 0) + return false; + + service = __connman_service_get_default(); + + return __connman_service_get_index(service) == index; +} + static void default_changed(void) { struct connman_service *service = __connman_service_get_default(); @@ -1337,10 +1442,23 @@ static void default_changed(void) if (service == current_default) return; + DBG("current default %p %s", current_default, + current_default ? current_default->identifier : ""); + DBG("new default %p %s", service, service ? service->identifier : ""); + __connman_service_timeserver_changed(current_default, NULL); current_default = service; + if (service) { + if (service->hostname && + connman_setting_get_bool("AllowHostnameUpdates")) + __connman_utsname_set_hostname(service->hostname); + + if (service->domainname) + __connman_utsname_set_domainname(service->domainname); + } + __connman_notifier_default_changed(service); } @@ -1351,10 +1469,10 @@ static void state_changed(struct connman_service *service) __connman_notifier_service_state_changed(service, service->state); str = state2string(service->state); - if (str == NULL) + if (!str) return; - if (allow_property_changed(service) == FALSE) + if (!allow_property_changed(service)) return; connman_dbus_property_changed_basic(service->path, @@ -1367,7 +1485,7 @@ static void strength_changed(struct connman_service *service) if (service->strength == 0) return; - if (allow_property_changed(service) == FALSE) + if (!allow_property_changed(service)) return; connman_dbus_property_changed_basic(service->path, @@ -1377,54 +1495,66 @@ static void strength_changed(struct connman_service *service) static void favorite_changed(struct connman_service *service) { - if (service->path == NULL) + dbus_bool_t favorite; + + if (!service->path) return; - if (allow_property_changed(service) == FALSE) + if (!allow_property_changed(service)) return; + favorite = service->favorite; connman_dbus_property_changed_basic(service->path, CONNMAN_SERVICE_INTERFACE, "Favorite", - DBUS_TYPE_BOOLEAN, &service->favorite); + DBUS_TYPE_BOOLEAN, &favorite); } static void immutable_changed(struct connman_service *service) { - if (service->path == NULL) + dbus_bool_t immutable; + + if (!service->path) return; - if (allow_property_changed(service) == FALSE) + if (!allow_property_changed(service)) return; + immutable = service->immutable; connman_dbus_property_changed_basic(service->path, CONNMAN_SERVICE_INTERFACE, "Immutable", - DBUS_TYPE_BOOLEAN, &service->immutable); + DBUS_TYPE_BOOLEAN, &immutable); } static void roaming_changed(struct connman_service *service) { - if (service->path == NULL) + dbus_bool_t roaming; + + if (!service->path) return; - if (allow_property_changed(service) == FALSE) + if (!allow_property_changed(service)) return; + roaming = service->roaming; connman_dbus_property_changed_basic(service->path, CONNMAN_SERVICE_INTERFACE, "Roaming", - DBUS_TYPE_BOOLEAN, &service->roaming); + DBUS_TYPE_BOOLEAN, &roaming); } static void autoconnect_changed(struct connman_service *service) { - if (service->path == NULL) + dbus_bool_t autoconnect; + + if (!service->path) return; - if (allow_property_changed(service) == FALSE) + if (!allow_property_changed(service)) return; + autoconnect = service->autoconnect; connman_dbus_property_changed_basic(service->path, CONNMAN_SERVICE_INTERFACE, "AutoConnect", - DBUS_TYPE_BOOLEAN, &service->autoconnect); + DBUS_TYPE_BOOLEAN, &autoconnect); } static void append_security(DBusMessageIter *iter, void *user_data) @@ -1433,7 +1563,7 @@ static void append_security(DBusMessageIter *iter, void *user_data) const char *str; str = security2string(service->security); - if (str != NULL) + if (str) dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &str); @@ -1442,14 +1572,14 @@ static void append_security(DBusMessageIter *iter, void *user_data) * are configured as open or no security, so filter * appropriately. */ - if (service->wps == TRUE) { + if (service->wps) { switch (service->security) { case CONNMAN_SERVICE_SECURITY_PSK: case CONNMAN_SERVICE_SECURITY_WPA: case CONNMAN_SERVICE_SECURITY_RSN: str = "wps"; dbus_message_iter_append_basic(iter, - DBUS_TYPE_STRING, &str); + DBUS_TYPE_STRING, &str); break; case CONNMAN_SERVICE_SECURITY_UNKNOWN: case CONNMAN_SERVICE_SECURITY_NONE: @@ -1464,10 +1594,10 @@ static void append_ethernet(DBusMessageIter *iter, void *user_data) { struct connman_service *service = user_data; - if (service->ipconfig_ipv4 != NULL) + if (service->ipconfig_ipv4) __connman_ipconfig_append_ethernet(service->ipconfig_ipv4, iter); - else if (service->ipconfig_ipv6 != NULL) + else if (service->ipconfig_ipv6) __connman_ipconfig_append_ethernet(service->ipconfig_ipv6, iter); } @@ -1476,13 +1606,10 @@ static void append_ipv4(DBusMessageIter *iter, void *user_data) { struct connman_service *service = user_data; - DBG("ipv4 %p state %s", service->ipconfig_ipv4, - state2string(service->state_ipv4)); - - if (is_connected_state(service, service->state_ipv4) == FALSE) + if (!is_connected_state(service, service->state_ipv4)) return; - if (service->ipconfig_ipv4 != NULL) + if (service->ipconfig_ipv4) __connman_ipconfig_append_ipv4(service->ipconfig_ipv4, iter); } @@ -1490,13 +1617,10 @@ static void append_ipv6(DBusMessageIter *iter, void *user_data) { struct connman_service *service = user_data; - DBG("ipv6 %p state %s", service->ipconfig_ipv6, - state2string(service->state_ipv6)); - - if (is_connected_state(service, service->state_ipv6) == FALSE) + if (!is_connected_state(service, service->state_ipv6)) return; - if (service->ipconfig_ipv6 != NULL) + if (service->ipconfig_ipv6) __connman_ipconfig_append_ipv6(service->ipconfig_ipv6, iter, service->ipconfig_ipv4); } @@ -1505,7 +1629,7 @@ static void append_ipv4config(DBusMessageIter *iter, void *user_data) { struct connman_service *service = user_data; - if (service->ipconfig_ipv4 != NULL) + if (service->ipconfig_ipv4) __connman_ipconfig_append_ipv4config(service->ipconfig_ipv4, iter); } @@ -1514,20 +1638,25 @@ static void append_ipv6config(DBusMessageIter *iter, void *user_data) { struct connman_service *service = user_data; - if (service->ipconfig_ipv6 != NULL) + if (service->ipconfig_ipv6) __connman_ipconfig_append_ipv6config(service->ipconfig_ipv6, iter); } -static void append_nameservers(DBusMessageIter *iter, char **servers) +static void append_nameservers(DBusMessageIter *iter, + struct connman_service *service, char **servers) { int i; + bool available = true; - DBG("%p", servers); + for (i = 0; servers[i]; i++) { + if (service) + available = nameserver_available(service, servers[i]); - for (i = 0; servers[i] != NULL; i++) { - DBG("servers[%d] %s", i, servers[i]); - dbus_message_iter_append_basic(iter, + DBG("servers[%d] %s available %d", i, servers[i], available); + + if (available) + dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &servers[i]); } } @@ -1536,18 +1665,30 @@ static void append_dns(DBusMessageIter *iter, void *user_data) { struct connman_service *service = user_data; - if (is_connected(service) == FALSE) + if (!is_connected(service)) return; - if (service->nameservers_config != NULL) { - append_nameservers(iter, service->nameservers_config); + if (service->nameservers_config) { + append_nameservers(iter, service, service->nameservers_config); return; } else { - if (service->nameservers != NULL) - append_nameservers(iter, service->nameservers); + if (service->nameservers) + append_nameservers(iter, service, + service->nameservers); + + if (service->nameservers_auto) + append_nameservers(iter, service, + service->nameservers_auto); + + if (!service->nameservers && !service->nameservers_auto) { + char **ns; - if (service->nameservers_auto != NULL) - append_nameservers(iter, service->nameservers_auto); + DBG("append fallback nameservers"); + + ns = connman_setting_get_string_list("FallbackNameservers"); + if (ns) + append_nameservers(iter, service, ns); + } } } @@ -1555,20 +1696,20 @@ static void append_dnsconfig(DBusMessageIter *iter, void *user_data) { struct connman_service *service = user_data; - if (service->nameservers_config == NULL) + if (!service->nameservers_config) return; - append_nameservers(iter, service->nameservers_config); + append_nameservers(iter, NULL, service->nameservers_config); } static void append_ts(DBusMessageIter *iter, void *user_data) { GSList *list = user_data; - while (list != NULL) { + while (list) { char *timeserver = list->data; - if (timeserver != NULL) + if (timeserver) dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, ×erver); @@ -1581,7 +1722,7 @@ static void append_tsconfig(DBusMessageIter *iter, void *user_data) struct connman_service *service = user_data; int i; - if (service->timeservers_config == NULL) + if (!service->timeservers_config) return; for (i = 0; service->timeservers_config[i]; i++) { @@ -1596,7 +1737,7 @@ static void append_domainconfig(DBusMessageIter *iter, void *user_data) struct connman_service *service = user_data; int i; - if (service->domains == NULL) + if (!service->domains) return; for (i = 0; service->domains[i]; i++) @@ -1608,13 +1749,13 @@ static void append_domain(DBusMessageIter *iter, void *user_data) { struct connman_service *service = user_data; - if (is_connected(service) == FALSE && - is_connecting(service) == FALSE) + if (!is_connected(service) && + !is_connecting(service)) return; - if (service->domains != NULL) + if (service->domains) append_domainconfig(iter, user_data); - else if (service->domainname != NULL) + else if (service->domainname) dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &service->domainname); } @@ -1624,7 +1765,7 @@ static void append_proxies(DBusMessageIter *iter, void *user_data) struct connman_service *service = user_data; int i; - if (service->proxies == NULL) + if (!service->proxies) return; for (i = 0; service->proxies[i]; i++) @@ -1637,7 +1778,7 @@ static void append_excludes(DBusMessageIter *iter, void *user_data) struct connman_service *service = user_data; int i; - if (service->excludes == NULL) + if (!service->excludes) return; for (i = 0; service->excludes[i]; i++) @@ -1653,9 +1794,7 @@ static void append_proxy(DBusMessageIter *iter, void *user_data) const char *method = proxymethod2string( CONNMAN_SERVICE_PROXY_METHOD_DIRECT); - DBG(""); - - if (is_connected(service) == FALSE) + if (!is_connected(service)) return; proxy = connman_service_get_proxy_method(service); @@ -1676,17 +1815,17 @@ static void append_proxy(DBusMessageIter *iter, void *user_data) break; case CONNMAN_SERVICE_PROXY_METHOD_AUTO: /* Maybe DHCP, or WPAD, has provided an url for a pac file */ - if (service->ipconfig_ipv4 != NULL) + if (service->ipconfig_ipv4) pac = __connman_ipconfig_get_proxy_autoconfig( service->ipconfig_ipv4); - else if (service->ipconfig_ipv6 != NULL) + else if (service->ipconfig_ipv6) pac = __connman_ipconfig_get_proxy_autoconfig( service->ipconfig_ipv6); - if (service->pac == NULL && pac == NULL) + if (!service->pac && !pac) goto done; - if (service->pac != NULL) + if (service->pac) pac = service->pac; connman_dbus_dict_append_basic(iter, "URL", @@ -1715,18 +1854,18 @@ static void append_proxyconfig(DBusMessageIter *iter, void *user_data) case CONNMAN_SERVICE_PROXY_METHOD_DIRECT: break; case CONNMAN_SERVICE_PROXY_METHOD_MANUAL: - if (service->proxies != NULL) + if (service->proxies) connman_dbus_dict_append_array(iter, "Servers", DBUS_TYPE_STRING, append_proxies, service); - if (service->excludes != NULL) + if (service->excludes) connman_dbus_dict_append_array(iter, "Excludes", DBUS_TYPE_STRING, append_excludes, service); break; case CONNMAN_SERVICE_PROXY_METHOD_AUTO: - if (service->pac != NULL) + if (service->pac) connman_dbus_dict_append_basic(iter, "URL", DBUS_TYPE_STRING, &service->pac); break; @@ -1742,12 +1881,10 @@ static void append_provider(DBusMessageIter *iter, void *user_data) { struct connman_service *service = user_data; - DBG("%p %p", service, service->provider); - - if (is_connected(service) == FALSE) + if (!is_connected(service)) return; - if (service->provider != NULL) + if (service->provider) __connman_provider_append_properties(service->provider, iter); } @@ -1757,7 +1894,7 @@ static void settings_changed(struct connman_service *service, { enum connman_ipconfig_type type; - if (allow_property_changed(service) == FALSE) + if (!allow_property_changed(service)) return; type = __connman_ipconfig_get_config_type(ipconfig); @@ -1776,7 +1913,7 @@ static void settings_changed(struct connman_service *service, static void ipv4_configuration_changed(struct connman_service *service) { - if (allow_property_changed(service) == FALSE) + if (!allow_property_changed(service)) return; connman_dbus_property_changed_dict(service->path, @@ -1788,7 +1925,7 @@ static void ipv4_configuration_changed(struct connman_service *service) static void ipv6_configuration_changed(struct connman_service *service) { - if (allow_property_changed(service) == FALSE) + if (!allow_property_changed(service)) return; connman_dbus_property_changed_dict(service->path, @@ -1800,7 +1937,7 @@ static void ipv6_configuration_changed(struct connman_service *service) static void dns_changed(struct connman_service *service) { - if (allow_property_changed(service) == FALSE) + if (!allow_property_changed(service)) return; connman_dbus_property_changed_array(service->path, @@ -1810,7 +1947,7 @@ static void dns_changed(struct connman_service *service) static void dns_configuration_changed(struct connman_service *service) { - if (allow_property_changed(service) == FALSE) + if (!allow_property_changed(service)) return; connman_dbus_property_changed_array(service->path, @@ -1823,7 +1960,7 @@ static void dns_configuration_changed(struct connman_service *service) static void domain_changed(struct connman_service *service) { - if (allow_property_changed(service) == FALSE) + if (!allow_property_changed(service)) return; connman_dbus_property_changed_array(service->path, @@ -1833,7 +1970,7 @@ static void domain_changed(struct connman_service *service) static void domain_configuration_changed(struct connman_service *service) { - if (allow_property_changed(service) == FALSE) + if (!allow_property_changed(service)) return; connman_dbus_property_changed_array(service->path, @@ -1844,7 +1981,7 @@ static void domain_configuration_changed(struct connman_service *service) static void proxy_changed(struct connman_service *service) { - if (allow_property_changed(service) == FALSE) + if (!allow_property_changed(service)) return; connman_dbus_property_changed_dict(service->path, @@ -1854,7 +1991,7 @@ static void proxy_changed(struct connman_service *service) static void proxy_configuration_changed(struct connman_service *service) { - if (allow_property_changed(service) == FALSE) + if (!allow_property_changed(service)) return; connman_dbus_property_changed_dict(service->path, @@ -1866,7 +2003,7 @@ static void proxy_configuration_changed(struct connman_service *service) static void timeservers_configuration_changed(struct connman_service *service) { - if (allow_property_changed(service) == FALSE) + if (!allow_property_changed(service)) return; connman_dbus_property_changed_array(service->path, @@ -1878,7 +2015,7 @@ static void timeservers_configuration_changed(struct connman_service *service) static void link_changed(struct connman_service *service) { - if (allow_property_changed(service) == FALSE) + if (!allow_property_changed(service)) return; connman_dbus_property_changed_dict(service->path, @@ -1889,7 +2026,7 @@ static void link_changed(struct connman_service *service) static void stats_append_counters(DBusMessageIter *dict, struct connman_stats_data *stats, struct connman_stats_data *counters, - connman_bool_t append_all) + bool append_all) { if (counters->rx_packets != stats->rx_packets || append_all) { counters->rx_packets = stats->rx_packets; @@ -1949,7 +2086,7 @@ static void stats_append_counters(DBusMessageIter *dict, static void stats_append(struct connman_service *service, const char *counter, struct connman_stats_counter *counters, - connman_bool_t append_all) + bool append_all) { DBusMessageIter array, dict; DBusMessage *msg; @@ -1957,7 +2094,7 @@ static void stats_append(struct connman_service *service, DBG("service %p counter %s", service, counter); msg = dbus_message_new(DBUS_MESSAGE_TYPE_METHOD_CALL); - if (msg == NULL) + if (!msg) return; dbus_message_append_args(msg, DBUS_TYPE_OBJECT_PATH, @@ -1997,7 +2134,7 @@ static void stats_update(struct connman_service *service, DBG("service %p", service); - if (stats->valid == TRUE) { + if (stats->valid) { data->rx_packets += rx_packets - data_last->rx_packets; data->tx_packets += @@ -2015,7 +2152,7 @@ static void stats_update(struct connman_service *service, data->tx_dropped += tx_dropped - data_last->tx_dropped; } else { - stats->valid = TRUE; + stats->valid = true; } data_last->rx_packets = rx_packets; @@ -2044,10 +2181,10 @@ void __connman_service_notify(struct connman_service *service, struct connman_stats_data *data; int err; - if (service == NULL) + if (!service) return; - if (is_connected(service) == FALSE) + if (!is_connected(service)) return; stats_update(service, @@ -2068,7 +2205,7 @@ void __connman_service_notify(struct connman_service *service, counters = value; stats_append(service, counter, counters, counters->append_all); - counters->append_all = FALSE; + counters->append_all = false; } } @@ -2082,14 +2219,14 @@ int __connman_service_counter_register(const char *counter) counter_list = g_slist_prepend(counter_list, (gpointer)counter); - for (list = service_list; list != NULL; list = list->next) { + for (list = service_list; list; list = list->next) { service = list->data; counters = g_try_new0(struct connman_stats_counter, 1); - if (counters == NULL) + if (!counters) return -ENOMEM; - counters->append_all = TRUE; + counters->append_all = true; g_hash_table_replace(service->counter_table, (gpointer)counter, counters); @@ -2105,7 +2242,7 @@ void __connman_service_counter_unregister(const char *counter) DBG("counter %s", counter); - for (list = service_list; list != NULL; list = list->next) { + for (list = service_list; list; list = list->next) { service = list->data; g_hash_table_remove(service->counter_table, counter); @@ -2118,42 +2255,24 @@ int __connman_service_iterate_services(service_iterate_cb cb, void *user_data) { GList *list; - for (list = service_list; list != NULL; list = list->next) { + for (list = service_list; list; list = list->next) { struct connman_service *service = list->data; - cb(service, service->name, service->state, user_data); + cb(service, user_data); } return 0; } -void __connman_service_session_inc(struct connman_service *service) -{ - DBG("service %p ref count %d", service, - service->session_usage_count + 1); - - __sync_fetch_and_add(&service->session_usage_count, 1); -} - -connman_bool_t __connman_service_session_dec(struct connman_service *service) -{ - DBG("service %p ref count %d", service, - service->session_usage_count - 1); - - if (__sync_fetch_and_sub(&service->session_usage_count, 1) != 1) - return FALSE; - - return TRUE; -} - static void append_properties(DBusMessageIter *dict, dbus_bool_t limited, struct connman_service *service) { + dbus_bool_t val; const char *str; GSList *list; str = __connman_service_type2string(service->type); - if (str != NULL) + if (str) connman_dbus_dict_append_basic(dict, "Type", DBUS_TYPE_STRING, &str); @@ -2161,12 +2280,12 @@ static void append_properties(DBusMessageIter *dict, dbus_bool_t limited, DBUS_TYPE_STRING, append_security, service); str = state2string(service->state); - if (str != NULL) + if (str) connman_dbus_dict_append_basic(dict, "State", DBUS_TYPE_STRING, &str); str = error2string(service->error); - if (str != NULL) + if (str) connman_dbus_dict_append_basic(dict, "Error", DBUS_TYPE_STRING, &str); @@ -2174,20 +2293,23 @@ static void append_properties(DBusMessageIter *dict, dbus_bool_t limited, connman_dbus_dict_append_basic(dict, "Strength", DBUS_TYPE_BYTE, &service->strength); + val = service->favorite; connman_dbus_dict_append_basic(dict, "Favorite", - DBUS_TYPE_BOOLEAN, &service->favorite); + DBUS_TYPE_BOOLEAN, &val); + val = service->immutable; connman_dbus_dict_append_basic(dict, "Immutable", - DBUS_TYPE_BOOLEAN, &service->immutable); + DBUS_TYPE_BOOLEAN, &val); - if (service->favorite == TRUE) - connman_dbus_dict_append_basic(dict, "AutoConnect", - DBUS_TYPE_BOOLEAN, &service->autoconnect); + if (service->favorite) + val = service->autoconnect; else - connman_dbus_dict_append_basic(dict, "AutoConnect", - DBUS_TYPE_BOOLEAN, &service->favorite); + val = service->favorite; + + connman_dbus_dict_append_basic(dict, "AutoConnect", + DBUS_TYPE_BOOLEAN, &val); - if (service->name != NULL) + if (service->name) connman_dbus_dict_append_basic(dict, "Name", DBUS_TYPE_STRING, &service->name); @@ -2196,11 +2318,12 @@ static void append_properties(DBusMessageIter *dict, dbus_bool_t limited, case CONNMAN_SERVICE_TYPE_SYSTEM: case CONNMAN_SERVICE_TYPE_GPS: case CONNMAN_SERVICE_TYPE_VPN: - case CONNMAN_SERVICE_TYPE_GADGET: + case CONNMAN_SERVICE_TYPE_P2P: break; case CONNMAN_SERVICE_TYPE_CELLULAR: + val = service->roaming; connman_dbus_dict_append_basic(dict, "Roaming", - DBUS_TYPE_BOOLEAN, &service->roaming); + DBUS_TYPE_BOOLEAN, &val); connman_dbus_dict_append_dict(dict, "Ethernet", append_ethernet, service); @@ -2208,6 +2331,7 @@ static void append_properties(DBusMessageIter *dict, dbus_bool_t limited, case CONNMAN_SERVICE_TYPE_WIFI: case CONNMAN_SERVICE_TYPE_ETHERNET: case CONNMAN_SERVICE_TYPE_BLUETOOTH: + case CONNMAN_SERVICE_TYPE_GADGET: connman_dbus_dict_append_dict(dict, "Ethernet", append_ethernet, service); break; @@ -2270,7 +2394,7 @@ static void append_struct_service(DBusMessageIter *iter, &service->path); connman_dbus_dict_open(&entry, &dict); - if (function != NULL) + if (function) function(&dict, service); connman_dbus_dict_close(&entry, &dict); @@ -2289,7 +2413,7 @@ static void append_struct(gpointer value, gpointer user_data) struct connman_service *service = value; DBusMessageIter *iter = user_data; - if (service->path == NULL) + if (!service->path) return; append_struct_service(iter, append_dict_properties, service); @@ -2300,25 +2424,39 @@ void __connman_service_list_struct(DBusMessageIter *iter) g_list_foreach(service_list, append_struct, iter); } -connman_bool_t __connman_service_is_hidden(struct connman_service *service) +bool __connman_service_is_hidden(struct connman_service *service) { return service->hidden; } -connman_bool_t +bool __connman_service_is_split_routing(struct connman_service *service) { return service->do_split_routing; } +bool __connman_service_index_is_split_routing(int index) +{ + struct connman_service *service; + + if (index < 0) + return false; + + service = __connman_service_lookup_from_index(index); + if (!service) + return false; + + return __connman_service_is_split_routing(service); +} + int __connman_service_get_index(struct connman_service *service) { - if (service == NULL) + if (!service) return -1; - if (service->network != NULL) + if (service->network) return connman_network_get_index(service->network); - else if (service->provider != NULL) + else if (service->provider) return connman_provider_get_index(service->provider); return -1; @@ -2326,16 +2464,34 @@ int __connman_service_get_index(struct connman_service *service) void __connman_service_set_hidden(struct connman_service *service) { - if (service == NULL || service->hidden == TRUE) + if (!service || service->hidden) return; - service->hidden_service = TRUE; + service->hidden_service = true; +} + +void __connman_service_set_hostname(struct connman_service *service, + const char *hostname) +{ + if (!service || service->hidden) + return; + + g_free(service->hostname); + service->hostname = g_strdup(hostname); +} + +const char *__connman_service_get_hostname(struct connman_service *service) +{ + if (!service) + return NULL; + + return service->hostname; } void __connman_service_set_domainname(struct connman_service *service, const char *domainname) { - if (service == NULL || service->hidden == TRUE) + if (!service || service->hidden) return; g_free(service->domainname); @@ -2346,10 +2502,10 @@ void __connman_service_set_domainname(struct connman_service *service, const char *connman_service_get_domainname(struct connman_service *service) { - if (service == NULL) + if (!service) return NULL; - if (service->domains != NULL) + if (service->domains) return service->domains[0]; else return service->domainname; @@ -2357,23 +2513,23 @@ const char *connman_service_get_domainname(struct connman_service *service) char **connman_service_get_nameservers(struct connman_service *service) { - if (service == NULL) + if (!service) return NULL; - if (service->nameservers_config != NULL) + if (service->nameservers_config) return g_strdupv(service->nameservers_config); - else if (service->nameservers != NULL || - service->nameservers_auto != NULL) { + else if (service->nameservers || + service->nameservers_auto) { int len = 0, len_auto = 0, i; char **nameservers; - if (service->nameservers != NULL) + if (service->nameservers) len = g_strv_length(service->nameservers); - if (service->nameservers_auto != NULL) + if (service->nameservers_auto) len_auto = g_strv_length(service->nameservers_auto); nameservers = g_try_new0(char *, len + len_auto + 1); - if (nameservers == NULL) + if (!nameservers) return NULL; for (i = 0; i < len; i++) @@ -2386,12 +2542,12 @@ char **connman_service_get_nameservers(struct connman_service *service) return nameservers; } - return NULL; + return g_strdupv(connman_setting_get_string_list("FallbackNameservers")); } char **connman_service_get_timeservers_config(struct connman_service *service) { - if (service == NULL) + if (!service) return NULL; return service->timeservers_config; @@ -2399,19 +2555,16 @@ char **connman_service_get_timeservers_config(struct connman_service *service) char **connman_service_get_timeservers(struct connman_service *service) { - if (service == NULL) + if (!service) return NULL; - if (service->timeservers != NULL) - return service->timeservers; - - return NULL; + return service->timeservers; } void connman_service_set_proxy_method(struct connman_service *service, enum connman_service_proxy_method method) { - if (service == NULL || service->hidden == TRUE) + if (!service || service->hidden) return; service->proxy = method; @@ -2425,12 +2578,12 @@ void connman_service_set_proxy_method(struct connman_service *service, enum connman_service_proxy_method connman_service_get_proxy_method( struct connman_service *service) { - if (service == NULL) + if (!service) return CONNMAN_SERVICE_PROXY_METHOD_UNKNOWN; if (service->proxy_config != CONNMAN_SERVICE_PROXY_METHOD_UNKNOWN) { if (service->proxy_config == CONNMAN_SERVICE_PROXY_METHOD_AUTO && - service->pac == NULL) + !service->pac) return service->proxy; return service->proxy_config; @@ -2451,7 +2604,7 @@ char **connman_service_get_proxy_excludes(struct connman_service *service) const char *connman_service_get_proxy_url(struct connman_service *service) { - if (service == NULL) + if (!service) return NULL; return service->pac; @@ -2460,7 +2613,7 @@ const char *connman_service_get_proxy_url(struct connman_service *service) void __connman_service_set_proxy_autoconfig(struct connman_service *service, const char *url) { - if (service == NULL || service->hidden == TRUE) + if (!service || service->hidden) return; service->proxy = CONNMAN_SERVICE_PROXY_METHOD_AUTO; @@ -2483,7 +2636,7 @@ void __connman_service_set_proxy_autoconfig(struct connman_service *service, const char *connman_service_get_proxy_autoconfig(struct connman_service *service) { - if (service == NULL) + if (!service) return NULL; if (service->ipconfig_ipv4) @@ -2500,13 +2653,13 @@ void __connman_service_set_timeservers(struct connman_service *service, { int i; - if (service == NULL) + if (!service) return; g_strfreev(service->timeservers); service->timeservers = NULL; - for (i = 0; timeservers != NULL && timeservers[i] != NULL; i++) + for (i = 0; timeservers && timeservers[i]; i++) __connman_service_timeserver_append(service, timeservers[i]); } @@ -2517,13 +2670,13 @@ int __connman_service_timeserver_append(struct connman_service *service, DBG("service %p timeserver %s", service, timeserver); - if (timeserver == NULL) + if (!timeserver) return -EINVAL; - if (service->timeservers != NULL) { + if (service->timeservers) { int i; - for (i = 0; service->timeservers[i] != NULL; i++) + for (i = 0; service->timeservers[i]; i++) if (g_strcmp0(service->timeservers[i], timeserver) == 0) return -EEXIST; @@ -2535,7 +2688,7 @@ int __connman_service_timeserver_append(struct connman_service *service, service->timeservers = g_try_new0(char *, len + 2); } - if (service->timeservers == NULL) + if (!service->timeservers) return -ENOMEM; service->timeservers[len] = g_strdup(timeserver); @@ -2552,14 +2705,14 @@ int __connman_service_timeserver_remove(struct connman_service *service, DBG("service %p timeserver %s", service, timeserver); - if (timeserver == NULL) + if (!timeserver) return -EINVAL; - if (service->timeservers == NULL) + if (!service->timeservers) return 0; - for (i = 0; service->timeservers != NULL && - service->timeservers[i] != NULL; i++) + for (i = 0; service->timeservers && + service->timeservers[i]; i++) if (g_strcmp0(service->timeservers[i], timeserver) == 0) { found = 1; break; @@ -2578,13 +2731,13 @@ int __connman_service_timeserver_remove(struct connman_service *service, } servers = g_try_new0(char *, len); - if (servers == NULL) + if (!servers) return -ENOMEM; for (i = 0, j = 0; i < len; i++) { if (g_strcmp0(service->timeservers[i], timeserver) != 0) { servers[j] = g_strdup(service->timeservers[i]); - if (servers[j] == NULL) + if (!servers[j]) return -ENOMEM; j++; } @@ -2600,10 +2753,10 @@ int __connman_service_timeserver_remove(struct connman_service *service, void __connman_service_timeserver_changed(struct connman_service *service, GSList *ts_list) { - if (service == NULL) + if (!service) return; - if (allow_property_changed(service) == FALSE) + if (!allow_property_changed(service)) return; connman_dbus_property_changed_array(service->path, @@ -2614,7 +2767,7 @@ void __connman_service_timeserver_changed(struct connman_service *service, void __connman_service_set_pac(struct connman_service *service, const char *pac) { - if (service->hidden == TRUE) + if (service->hidden) return; g_free(service->pac); service->pac = g_strdup(pac); @@ -2625,13 +2778,13 @@ void __connman_service_set_pac(struct connman_service *service, void __connman_service_set_identity(struct connman_service *service, const char *identity) { - if (service->immutable || service->hidden == TRUE) + if (service->immutable || service->hidden) return; g_free(service->identity); service->identity = g_strdup(identity); - if (service->network != NULL) + if (service->network) connman_network_set_string(service->network, "WiFi.Identity", service->identity); @@ -2640,12 +2793,12 @@ void __connman_service_set_identity(struct connman_service *service, void __connman_service_set_agent_identity(struct connman_service *service, const char *agent_identity) { - if (service->hidden == TRUE) + if (service->hidden) return; g_free(service->agent_identity); service->agent_identity = g_strdup(agent_identity); - if (service->network != NULL) + if (service->network) connman_network_set_string(service->network, "WiFi.AgentIdentity", service->agent_identity); @@ -2658,12 +2811,12 @@ static int check_passphrase(struct connman_service *service, guint i; gsize length; - if (passphrase == NULL) { + if (!passphrase) { /* * This will prevent __connman_service_set_passphrase() to * wipe the passphrase out in case of -ENOKEY error for a * favorite service. */ - if (service->favorite == TRUE) + if (service->favorite) return 1; else return 0; @@ -2713,7 +2866,7 @@ int __connman_service_set_passphrase(struct connman_service *service, { int err = 0; - if (service->immutable == TRUE || service->hidden == TRUE) + if (service->immutable || service->hidden) return -EINVAL; err = check_passphrase(service, service->security, passphrase); @@ -2722,7 +2875,7 @@ int __connman_service_set_passphrase(struct connman_service *service, g_free(service->passphrase); service->passphrase = g_strdup(passphrase); - if (service->network != NULL) + if (service->network) connman_network_set_string(service->network, "WiFi.Passphrase", service->passphrase); @@ -2734,26 +2887,12 @@ int __connman_service_set_passphrase(struct connman_service *service, const char *__connman_service_get_passphrase(struct connman_service *service) { - if (service == NULL) + if (!service) return NULL; return service->passphrase; } -void __connman_service_set_agent_passphrase(struct connman_service *service, - const char *agent_passphrase) -{ - if (service->hidden == TRUE) - return; - g_free(service->agent_passphrase); - service->agent_passphrase = g_strdup(agent_passphrase); - - if (service->network != NULL) - connman_network_set_string(service->network, - "WiFi.AgentPassphrase", - service->agent_passphrase); -} - static DBusMessage *get_properties(DBusConnection *conn, DBusMessage *msg, void *user_data) { @@ -2764,7 +2903,7 @@ static DBusMessage *get_properties(DBusConnection *conn, DBG("service %p", service); reply = dbus_message_new_method_return(msg); - if (reply == NULL) + if (!reply) return NULL; dbus_message_iter_init_append(reply, &array); @@ -2809,7 +2948,7 @@ static int update_proxy_configuration(struct connman_service *service, type = dbus_message_iter_get_arg_type(&variant); - if (g_str_equal(key, "Method") == TRUE) { + if (g_str_equal(key, "Method")) { const char *val; if (type != DBUS_TYPE_STRING) @@ -2817,19 +2956,19 @@ static int update_proxy_configuration(struct connman_service *service, dbus_message_iter_get_basic(&variant, &val); method = string2proxymethod(val); - } else if (g_str_equal(key, "URL") == TRUE) { + } else if (g_str_equal(key, "URL")) { if (type != DBUS_TYPE_STRING) goto error; dbus_message_iter_get_basic(&variant, &url); - } else if (g_str_equal(key, "Servers") == TRUE) { + } else if (g_str_equal(key, "Servers")) { DBusMessageIter str_array; if (type != DBUS_TYPE_ARRAY) goto error; servers_str = g_string_new(NULL); - if (servers_str == NULL) + if (!servers_str) goto error; dbus_message_iter_recurse(&variant, &str_array); @@ -2848,14 +2987,14 @@ static int update_proxy_configuration(struct connman_service *service, dbus_message_iter_next(&str_array); } - } else if (g_str_equal(key, "Excludes") == TRUE) { + } else if (g_str_equal(key, "Excludes")) { DBusMessageIter str_array; if (type != DBUS_TYPE_ARRAY) goto error; excludes_str = g_string_new(NULL); - if (excludes_str == NULL) + if (!excludes_str) goto error; dbus_message_iter_recurse(&variant, &str_array); @@ -2883,10 +3022,10 @@ static int update_proxy_configuration(struct connman_service *service, case CONNMAN_SERVICE_PROXY_METHOD_DIRECT: break; case CONNMAN_SERVICE_PROXY_METHOD_MANUAL: - if (servers_str == NULL && service->proxies == NULL) + if (!servers_str && !service->proxies) goto error; - if (servers_str != NULL) { + if (servers_str) { g_strfreev(service->proxies); if (servers_str->len > 0) @@ -2896,7 +3035,7 @@ static int update_proxy_configuration(struct connman_service *service, service->proxies = NULL; } - if (excludes_str != NULL) { + if (excludes_str) { g_strfreev(service->excludes); if (excludes_str->len > 0) @@ -2906,14 +3045,14 @@ static int update_proxy_configuration(struct connman_service *service, service->excludes = NULL; } - if (service->proxies == NULL) + if (!service->proxies) method = CONNMAN_SERVICE_PROXY_METHOD_DIRECT; break; case CONNMAN_SERVICE_PROXY_METHOD_AUTO: g_free(service->pac); - if (url != NULL && strlen(url) > 0) + if (url && strlen(url) > 0) service->pac = g_strdup(url); else service->pac = NULL; @@ -2929,10 +3068,10 @@ static int update_proxy_configuration(struct connman_service *service, goto error; } - if (servers_str != NULL) + if (servers_str) g_string_free(servers_str, TRUE); - if (excludes_str != NULL) + if (excludes_str) g_string_free(excludes_str, TRUE); service->proxy_config = method; @@ -2940,10 +3079,10 @@ static int update_proxy_configuration(struct connman_service *service, return 0; error: - if (servers_str != NULL) + if (servers_str) g_string_free(servers_str, TRUE); - if (excludes_str != NULL) + if (excludes_str) g_string_free(excludes_str, TRUE); return -EINVAL; @@ -2969,7 +3108,7 @@ int __connman_service_reset_ipconfig(struct connman_service *service, } else return -EINVAL; - if (ipconfig == NULL) + if (!ipconfig) return -ENXIO; old_method = __connman_ipconfig_get_method(ipconfig); @@ -2981,7 +3120,7 @@ int __connman_service_reset_ipconfig(struct connman_service *service, else new_ipconfig = create_ip6config(service, index); - if (array != NULL) { + if (array) { err = __connman_ipconfig_set_config(new_ipconfig, array); if (err < 0) { __connman_ipconfig_unref(new_ipconfig); @@ -2996,25 +3135,24 @@ int __connman_service_reset_ipconfig(struct connman_service *service, __connman_network_clear_ipconfig(service->network, ipconfig); __connman_ipconfig_unref(ipconfig); - if (type == CONNMAN_IPCONFIG_TYPE_IPV4) { + if (type == CONNMAN_IPCONFIG_TYPE_IPV4) service->ipconfig_ipv4 = new_ipconfig; - } else if (type == CONNMAN_IPCONFIG_TYPE_IPV6) { + else if (type == CONNMAN_IPCONFIG_TYPE_IPV6) service->ipconfig_ipv6 = new_ipconfig; - } __connman_ipconfig_enable(new_ipconfig); - if (new_state != NULL && new_method != old_method) { + if (new_state && new_method != old_method) { if (type == CONNMAN_IPCONFIG_TYPE_IPV4) *new_state = service->state_ipv4; else *new_state = service->state_ipv6; - __connman_service_auto_connect(); + __connman_service_auto_connect(CONNMAN_SERVICE_CONNECT_REASON_AUTO); } DBG("err %d ipconfig %p type %d method %d state %s", err, new_ipconfig, type, new_method, - new_state == NULL ? "-" : state2string(*new_state)); + !new_state ? "-" : state2string(*new_state)); return err; } @@ -3029,7 +3167,7 @@ static DBusMessage *set_property(DBusConnection *conn, DBG("service %p", service); - if (dbus_message_iter_init(msg, &iter) == FALSE) + if (!dbus_message_iter_init(msg, &iter)) return __connman_error_invalid_arguments(msg); if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING) @@ -3045,13 +3183,13 @@ static DBusMessage *set_property(DBusConnection *conn, type = dbus_message_iter_get_arg_type(&value); - if (g_str_equal(name, "AutoConnect") == TRUE) { - connman_bool_t autoconnect; + if (g_str_equal(name, "AutoConnect")) { + dbus_bool_t autoconnect; if (type != DBUS_TYPE_BOOLEAN) return __connman_error_invalid_arguments(msg); - if (service->favorite == FALSE) + if (!service->favorite) return __connman_error_invalid_service(msg); dbus_message_iter_get_basic(&value, &autoconnect); @@ -3063,30 +3201,28 @@ static DBusMessage *set_property(DBusConnection *conn, autoconnect_changed(service); - if (autoconnect == TRUE) - __connman_service_auto_connect(); + if (autoconnect) + __connman_service_auto_connect(CONNMAN_SERVICE_CONNECT_REASON_AUTO); service_save(service); - } else if (g_str_equal(name, "Nameservers.Configuration") == TRUE) { + } else if (g_str_equal(name, "Nameservers.Configuration")) { DBusMessageIter entry; GString *str; int index; const char *gw; - if (service->immutable == TRUE) + if (__connman_provider_is_immutable(service->provider) || + service->immutable) return __connman_error_not_supported(msg); if (type != DBUS_TYPE_ARRAY) return __connman_error_invalid_arguments(msg); str = g_string_new(NULL); - if (str == NULL) + if (!str) return __connman_error_invalid_arguments(msg); - if (service->type == CONNMAN_SERVICE_TYPE_VPN) - index = connman_provider_get_index(service->provider); - else - index = connman_network_get_index(service->network); + index = __connman_service_get_index(service); gw = __connman_ipconfig_get_gateway_from_index(index, CONNMAN_IPCONFIG_TYPE_ALL); @@ -3137,12 +3273,12 @@ static DBusMessage *set_property(DBusConnection *conn, CONNMAN_IPCONFIG_TYPE_IPV6); service_save(service); - } else if (g_str_equal(name, "Timeservers.Configuration") == TRUE) { + } else if (g_str_equal(name, "Timeservers.Configuration")) { DBusMessageIter entry; GSList *list = NULL; int count = 0; - if (service->immutable == TRUE) + if (service->immutable) return __connman_error_not_supported(msg); if (type != DBUS_TYPE_ARRAY) @@ -3168,10 +3304,10 @@ static DBusMessage *set_property(DBusConnection *conn, g_strfreev(service->timeservers_config); service->timeservers_config = NULL; - if (list != NULL) { + if (list) { service->timeservers_config = g_new0(char *, count+1); - while (list != NULL) { + while (list) { count--; service->timeservers_config[count] = list->data; list = g_slist_delete_link(list, list); @@ -3184,18 +3320,18 @@ static DBusMessage *set_property(DBusConnection *conn, if (service == __connman_service_get_default()) __connman_timeserver_sync(service); - } else if (g_str_equal(name, "Domains.Configuration") == TRUE) { + } else if (g_str_equal(name, "Domains.Configuration")) { DBusMessageIter entry; GString *str; - if (service->immutable == TRUE) + if (service->immutable) return __connman_error_not_supported(msg); if (type != DBUS_TYPE_ARRAY) return __connman_error_invalid_arguments(msg); str = g_string_new(NULL); - if (str == NULL) + if (!str) return __connman_error_invalid_arguments(msg); dbus_message_iter_recurse(&value, &entry); @@ -3225,10 +3361,10 @@ static DBusMessage *set_property(DBusConnection *conn, domain_changed(service); service_save(service); - } else if (g_str_equal(name, "Proxy.Configuration") == TRUE) { + } else if (g_str_equal(name, "Proxy.Configuration")) { int err; - if (service->immutable == TRUE) + if (service->immutable) return __connman_error_not_supported(msg); if (type != DBUS_TYPE_ARRAY) @@ -3244,7 +3380,7 @@ static DBusMessage *set_property(DBusConnection *conn, __connman_notifier_proxy_changed(service); service_save(service); - } else if (g_str_equal(name, "IPv4.Configuration") == TRUE || + } else if (g_str_equal(name, "IPv4.Configuration") || g_str_equal(name, "IPv6.Configuration")) { enum connman_service_state state = @@ -3253,16 +3389,17 @@ static DBusMessage *set_property(DBusConnection *conn, CONNMAN_IPCONFIG_TYPE_UNKNOWN; int err = 0; - if (service->immutable == TRUE) + if (service->type == CONNMAN_SERVICE_TYPE_VPN || + service->immutable) return __connman_error_not_supported(msg); DBG("%s", name); - if (service->ipconfig_ipv4 == NULL && - service->ipconfig_ipv6 == NULL) + if (!service->ipconfig_ipv4 && + !service->ipconfig_ipv6) return __connman_error_invalid_property(msg); - if (g_str_equal(name, "IPv4.Configuration") == TRUE) + if (g_str_equal(name, "IPv4.Configuration")) type = CONNMAN_IPCONFIG_TYPE_IPV4; else type = CONNMAN_IPCONFIG_TYPE_IPV6; @@ -3306,15 +3443,15 @@ static void set_error(struct connman_service *service, service->error = error; - if (service->path == NULL) + if (!service->path) return; str = error2string(service->error); - if (str == NULL) + if (!str) str = ""; - if (allow_property_changed(service) == FALSE) + if (!allow_property_changed(service)) return; connman_dbus_property_changed_basic(service->path, @@ -3322,14 +3459,6 @@ static void set_error(struct connman_service *service, DBUS_TYPE_STRING, &str); } -static void set_idle(struct connman_service *service) -{ - service->state = service->state_ipv4 = service->state_ipv6 = - CONNMAN_SERVICE_STATE_IDLE; - set_error(service, CONNMAN_SERVICE_ERROR_UNKNOWN); - state_changed(service); -} - static DBusMessage *clear_property(DBusConnection *conn, DBusMessage *msg, void *user_data) { @@ -3341,8 +3470,8 @@ static DBusMessage *clear_property(DBusConnection *conn, dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &name, DBUS_TYPE_INVALID); - if (g_str_equal(name, "Error") == TRUE) { - set_idle(service); + if (g_str_equal(name, "Error")) { + set_error(service, CONNMAN_SERVICE_ERROR_UNKNOWN); g_get_current_time(&service->modified); service_save(service); @@ -3352,34 +3481,102 @@ static DBusMessage *clear_property(DBusConnection *conn, return g_dbus_create_reply(msg, DBUS_TYPE_INVALID); } -static connman_bool_t is_ipconfig_usable(struct connman_service *service) +static bool is_ipconfig_usable(struct connman_service *service) { - if (__connman_ipconfig_is_usable(service->ipconfig_ipv4) == FALSE && - __connman_ipconfig_is_usable(service->ipconfig_ipv6) - == FALSE) - return FALSE; + if (!__connman_ipconfig_is_usable(service->ipconfig_ipv4) && + !__connman_ipconfig_is_usable(service->ipconfig_ipv6)) + return false; - return TRUE; + return true; } -static connman_bool_t is_ignore(struct connman_service *service) +static bool is_ignore(struct connman_service *service) { - if (service->autoconnect == FALSE) - return TRUE; + if (!service->autoconnect) + return true; - if (service->roaming == TRUE) - return TRUE; + if (service->roaming) + return true; - if (service->ignore == TRUE) - return TRUE; + if (service->ignore) + return true; if (service->state == CONNMAN_SERVICE_STATE_FAILURE) - return TRUE; + return true; - if (is_ipconfig_usable(service) == FALSE) - return TRUE; + if (!is_ipconfig_usable(service)) + return true; - return FALSE; + return false; +} + +static void disconnect_on_last_session(enum connman_service_type type) +{ + GList *list; + + for (list = service_list; list; list = list->next) { + struct connman_service *service = list->data; + + if (service->type != type) + continue; + + if (service->connect_reason != CONNMAN_SERVICE_CONNECT_REASON_SESSION) + continue; + + __connman_service_disconnect(service); + return; + } +} + +static int active_sessions[MAX_CONNMAN_SERVICE_TYPES] = {}; +static int active_count = 0; + +void __connman_service_set_active_session(bool enable, GSList *list) +{ + if (!list) + return; + + if (enable) + active_count++; + else + active_count--; + + while (list != NULL) { + enum connman_service_type type = GPOINTER_TO_INT(list->data); + + switch (type) { + case CONNMAN_SERVICE_TYPE_ETHERNET: + case CONNMAN_SERVICE_TYPE_WIFI: + case CONNMAN_SERVICE_TYPE_BLUETOOTH: + case CONNMAN_SERVICE_TYPE_CELLULAR: + case CONNMAN_SERVICE_TYPE_GADGET: + if (enable) + active_sessions[type]++; + else + active_sessions[type]--; + break; + + case CONNMAN_SERVICE_TYPE_UNKNOWN: + case CONNMAN_SERVICE_TYPE_SYSTEM: + case CONNMAN_SERVICE_TYPE_GPS: + case CONNMAN_SERVICE_TYPE_VPN: + case CONNMAN_SERVICE_TYPE_P2P: + break; + } + + if (active_sessions[type] == 0) + disconnect_on_last_session(type); + + list = g_slist_next(list); + } + + DBG("eth %d wifi %d bt %d cellular %d gadget %d sessions %d", + active_sessions[CONNMAN_SERVICE_TYPE_ETHERNET], + active_sessions[CONNMAN_SERVICE_TYPE_WIFI], + active_sessions[CONNMAN_SERVICE_TYPE_BLUETOOTH], + active_sessions[CONNMAN_SERVICE_TYPE_CELLULAR], + active_sessions[CONNMAN_SERVICE_TYPE_GADGET], + active_count); } struct preferred_tech_data { @@ -3401,25 +3598,26 @@ static void preferred_tech_add_by_type(gpointer data, gpointer user_data) } } -static GList* preferred_tech_list_get(void) +static GList *preferred_tech_list_get(void) { unsigned int *tech_array; struct preferred_tech_data tech_data = { 0, }; int i; tech_array = connman_setting_get_uint_list("PreferredTechnologies"); - if (tech_array == NULL) + if (!tech_array) return NULL; - if (connman_setting_get_bool("SingleConnectedTechnology") == TRUE) { + if (connman_setting_get_bool("SingleConnectedTechnology")) { GList *list; - for (list = service_list; list != NULL; list = list->next) { + for (list = service_list; list; list = list->next) { struct connman_service *service = list->data; - if (is_connected(service) == FALSE) + if (!is_connected(service)) break; - if (service->userconnect == TRUE) { + if (service->connect_reason == + CONNMAN_SERVICE_CONNECT_REASON_USER) { DBG("service %p name %s is user connected", service, service->name); return NULL; @@ -3436,87 +3634,162 @@ static GList* preferred_tech_list_get(void) return tech_data.preferred_list; } -static connman_bool_t auto_connect_service(GList *services, - connman_bool_t preferred) +static bool auto_connect_service(GList *services, + enum connman_service_connect_reason reason, + bool preferred) { struct connman_service *service = NULL; + bool ignore[MAX_CONNMAN_SERVICE_TYPES] = { }; + bool autoconnecting = false; GList *list; - for (list = services; list != NULL; list = list->next) { + DBG("preferred %d sessions %d reason %s", preferred, active_count, + reason2string(reason)); + + ignore[CONNMAN_SERVICE_TYPE_VPN] = true; + + for (list = services; list; list = list->next) { service = list->data; - if (service->pending != NULL) - return TRUE; + if (ignore[service->type]) { + DBG("service %p type %s ignore", service, + __connman_service_type2string(service->type)); + continue; + } + + if (service->pending || + is_connecting(service) || + is_connected(service)) { + if (!active_count) + return true; - if (is_connecting(service) == TRUE) - return TRUE; + ignore[service->type] = true; + autoconnecting = true; - if (service->favorite == FALSE) { - if (preferred == TRUE) - goto next_service; - return FALSE; + DBG("service %p type %s busy", service, + __connman_service_type2string(service->type)); + + continue; } - if (is_connected(service) == TRUE) - return TRUE; + if (!service->favorite) { + if (preferred) + continue; - if (is_ignore(service) == FALSE && service->state == - CONNMAN_SERVICE_STATE_IDLE) - break; + return autoconnecting; + } - next_service: - service = NULL; - } + if (is_ignore(service) || service->state != + CONNMAN_SERVICE_STATE_IDLE) + continue; - if (service != NULL) { + if (autoconnecting && !active_sessions[service->type]) { + DBG("service %p type %s has no users", service, + __connman_service_type2string(service->type)); + continue; + } DBG("service %p %s %s", service, service->name, - (preferred == TRUE)? "preferred": "auto"); + (preferred) ? "preferred" : reason2string(reason)); + + __connman_service_connect(service, reason); - service->userconnect = FALSE; - __connman_service_connect(service); - return TRUE; + if (!active_count) + return true; + + ignore[service->type] = true; } - return FALSE; + + return autoconnecting; } static gboolean run_auto_connect(gpointer data) { - GList *list = NULL, *preferred_tech; + enum connman_service_connect_reason reason = GPOINTER_TO_UINT(data); + bool autoconnecting = false; + GList *preferred_tech; autoconnect_timeout = 0; DBG(""); preferred_tech = preferred_tech_list_get(); - if (preferred_tech != NULL) - list = preferred_tech; - - if (list == NULL || auto_connect_service(list, TRUE) == FALSE) - list = service_list; - - if (list != NULL) - auto_connect_service(list, FALSE); - - if (preferred_tech != NULL) + if (preferred_tech) { + autoconnecting = auto_connect_service(preferred_tech, reason, + true); g_list_free(preferred_tech); + } + + if (!autoconnecting || active_count) + auto_connect_service(service_list, reason, false); return FALSE; } -void __connman_service_auto_connect(void) +void __connman_service_auto_connect(enum connman_service_connect_reason reason) { DBG(""); - if (__connman_session_mode() == TRUE) { - DBG("Session mode enabled: auto connect disabled"); + if (autoconnect_timeout != 0) return; + + if (!__connman_session_policy_autoconnect(reason)) + return; + + autoconnect_timeout = g_timeout_add_seconds(0, run_auto_connect, + GUINT_TO_POINTER(reason)); +} + +static gboolean run_vpn_auto_connect(gpointer data) { + GList *list; + bool need_split = false; + + vpn_autoconnect_timeout = 0; + + for (list = service_list; list; list = list->next) { + struct connman_service *service = list->data; + int res; + + if (service->type != CONNMAN_SERVICE_TYPE_VPN) + continue; + + if (is_connected(service) || is_connecting(service)) { + if (!service->do_split_routing) + need_split = true; + continue; + } + + if (is_ignore(service) || !service->favorite) + continue; + + if (need_split && !service->do_split_routing) { + DBG("service %p no split routing", service); + continue; + } + + DBG("service %p %s %s", service, service->name, + service->do_split_routing ? + "split routing" : ""); + + res = __connman_service_connect(service, + CONNMAN_SERVICE_CONNECT_REASON_AUTO); + if (res < 0 && res != -EINPROGRESS) + continue; + + if (!service->do_split_routing) + need_split = true; } - if (autoconnect_timeout != 0) + return FALSE; +} + +static void vpn_auto_connect(void) +{ + if (vpn_autoconnect_timeout) return; - autoconnect_timeout = g_timeout_add_seconds(0, run_auto_connect, NULL); + vpn_autoconnect_timeout = + g_timeout_add_seconds(0, run_vpn_auto_connect, NULL); } static void remove_timeout(struct connman_service *service) @@ -3530,18 +3803,18 @@ static void remove_timeout(struct connman_service *service) void __connman_service_reply_dbus_pending(DBusMessage *pending, int error, const char *path) { - if (pending != NULL) { + if (pending) { if (error > 0) { DBusMessage *reply; reply = __connman_error_failed(pending, error); - if (reply != NULL) + if (reply) g_dbus_send_message(connection, reply); } else { const char *sender; sender = dbus_message_get_interface(pending); - if (path == NULL) + if (!path) path = dbus_message_get_path(pending); DBG("sender %s path %s", sender, path); @@ -3563,35 +3836,35 @@ static void reply_pending(struct connman_service *service, int error) { remove_timeout(service); - if (service->pending != NULL) { + if (service->pending) { __connman_service_reply_dbus_pending(service->pending, error, NULL); service->pending = NULL; } - if (service->provider_pending != NULL) { + if (service->provider_pending) { __connman_service_reply_dbus_pending(service->provider_pending, error, service->path); service->provider_pending = NULL; } } -connman_bool_t +bool __connman_service_is_provider_pending(struct connman_service *service) { - if (service == NULL) - return FALSE; + if (!service) + return false; - if (service->provider_pending != NULL) - return TRUE; + if (service->provider_pending) + return true; - return FALSE; + return false; } void __connman_service_set_provider_pending(struct connman_service *service, DBusMessage *msg) { - if (service->provider_pending != NULL) { + if (service->provider_pending) { DBG("service %p provider pending msg %p already exists", service, service->provider_pending); return; @@ -3603,7 +3876,7 @@ void __connman_service_set_provider_pending(struct connman_service *service, static void check_pending_msg(struct connman_service *service) { - if (service->pending == NULL) + if (!service->pending) return; DBG("service %p pending msg %p already exists", service, @@ -3618,7 +3891,7 @@ void __connman_service_set_hidden_data(struct connman_service *service, DBG("service %p pending %p", service, pending); - if (pending == NULL) + if (!pending) return; check_pending_msg(service); @@ -3639,15 +3912,15 @@ void __connman_service_return_error(struct connman_service *service, static gboolean connect_timeout(gpointer user_data) { struct connman_service *service = user_data; - connman_bool_t autoconnect = FALSE; + bool autoconnect = false; DBG("service %p", service); service->timeout = 0; - if (service->network != NULL) + if (service->network) __connman_network_disconnect(service->network); - else if (service->provider != NULL) + else if (service->provider) connman_provider_disconnect(service->provider); __connman_ipconfig_disable(service->ipconfig_ipv4); @@ -3655,17 +3928,17 @@ static gboolean connect_timeout(gpointer user_data) __connman_stats_service_unregister(service); - if (service->pending != NULL) { + if (service->pending) { DBusMessage *reply; reply = __connman_error_operation_timeout(service->pending); - if (reply != NULL) + if (reply) g_dbus_send_message(connection, reply); dbus_message_unref(service->pending); service->pending = NULL; } else - autoconnect = TRUE; + autoconnect = true; __connman_service_ipconfig_indicate_state(service, CONNMAN_SERVICE_STATE_FAILURE, @@ -3674,77 +3947,50 @@ static gboolean connect_timeout(gpointer user_data) CONNMAN_SERVICE_STATE_FAILURE, CONNMAN_IPCONFIG_TYPE_IPV6); - if (autoconnect == TRUE && service->userconnect == FALSE) - __connman_service_auto_connect(); + if (autoconnect && + service->connect_reason != + CONNMAN_SERVICE_CONNECT_REASON_USER) + __connman_service_auto_connect(CONNMAN_SERVICE_CONNECT_REASON_AUTO); return FALSE; } -static void set_reconnect_state(struct connman_service *service, - connman_bool_t reconnect) -{ - struct connman_device *device; - - if (service->network == NULL) - return; - - device = connman_network_get_device(service->network); - if (device == NULL) - return; - - __connman_device_set_reconnect(device, reconnect); -} - -static connman_bool_t get_reconnect_state(struct connman_service *service) -{ - struct connman_device *device; - - if (service->network == NULL) - return FALSE; - - device = connman_network_get_device(service->network); - if (device == NULL) - return FALSE; - - return __connman_device_get_reconnect(device); -} - -static connman_bool_t is_interface_available(struct connman_service *service, +static bool is_interface_available(struct connman_service *service, struct connman_service *other_service) { unsigned int index = 0, other_index = 0; - if (service->ipconfig_ipv4 != NULL) + if (service->ipconfig_ipv4) index = __connman_ipconfig_get_index(service->ipconfig_ipv4); - else if (service->ipconfig_ipv6 != NULL) + else if (service->ipconfig_ipv6) index = __connman_ipconfig_get_index(service->ipconfig_ipv6); - if (other_service->ipconfig_ipv4 != NULL) + if (other_service->ipconfig_ipv4) other_index = __connman_ipconfig_get_index( other_service->ipconfig_ipv4); - else if (other_service->ipconfig_ipv6 != NULL) + else if (other_service->ipconfig_ipv6) other_index = __connman_ipconfig_get_index( other_service->ipconfig_ipv6); if (index > 0 && other_index != index) - return TRUE; + return true; - return FALSE; + return false; } static DBusMessage *connect_service(DBusConnection *conn, DBusMessage *msg, void *user_data) { struct connman_service *service = user_data; + int err = 0; GList *list; - int err; DBG("service %p", service); - if (service->pending != NULL) + if (service->pending) return __connman_error_in_progress(msg); - for (list = service_list; list != NULL; list = list->next) { + for (list = service_list; list; list = list->next) { struct connman_service *temp = list->data; /* @@ -3752,47 +3998,35 @@ static DBusMessage *connect_service(DBusConnection *conn, * interfaces for a given technology type (like having * more than one wifi card). */ - if (service->type == temp->type && - is_connecting(temp) == TRUE && - is_interface_available(service, - temp) == FALSE) { - if (temp->pending != NULL) - __connman_service_return_error(temp, - ECONNABORTED, - NULL); + if (!is_connecting(temp) && !is_connected(temp)) + break; - err = __connman_service_disconnect(temp); - if (err < 0 && err != -EINPROGRESS) - return __connman_error_in_progress(msg); - else { - set_idle(temp); - break; - } + if (service->type != temp->type) + continue; + + if(!is_interface_available(service, temp)) { + if (__connman_service_disconnect(temp) == -EINPROGRESS) + err = -EINPROGRESS; } } + if (err == -EINPROGRESS) + return __connman_error_in_progress(msg); - service->ignore = FALSE; - - service->userconnect = TRUE; + service->ignore = false; service->pending = dbus_message_ref(msg); - set_reconnect_state(service, FALSE); - - err = __connman_service_connect(service); - if (err < 0) { - if (service->pending == NULL) - return NULL; + err = __connman_service_connect(service, + CONNMAN_SERVICE_CONNECT_REASON_USER); - if (err != -EINPROGRESS) { - dbus_message_unref(service->pending); - service->pending = NULL; + if (err == -EINPROGRESS) + return NULL; - return __connman_error_failed(msg, -err); - } + dbus_message_unref(service->pending); + service->pending = NULL; - return NULL; - } + if (err < 0) + return __connman_error_failed(msg, -err); return g_dbus_create_reply(msg, DBUS_TYPE_INVALID); } @@ -3805,11 +4039,7 @@ static DBusMessage *disconnect_service(DBusConnection *conn, DBG("service %p", service); - reply_pending(service, ECONNABORTED); - - service->ignore = TRUE; - - set_reconnect_state(service, FALSE); + service->ignore = true; err = __connman_service_disconnect(service); if (err < 0) { @@ -3820,28 +4050,25 @@ static DBusMessage *disconnect_service(DBusConnection *conn, return g_dbus_create_reply(msg, DBUS_TYPE_INVALID); } -gboolean __connman_service_remove(struct connman_service *service) +bool __connman_service_remove(struct connman_service *service) { - if (service->type == CONNMAN_SERVICE_TYPE_ETHERNET) - return FALSE; + if (service->type == CONNMAN_SERVICE_TYPE_ETHERNET || + service->type == CONNMAN_SERVICE_TYPE_GADGET) + return false; - if (service->immutable == TRUE || service->hidden == TRUE) - return FALSE; + if (service->immutable || service->hidden || + __connman_provider_is_immutable(service->provider)) + return false; - if (service->favorite == FALSE && service->state != + if (!service->favorite && service->state != CONNMAN_SERVICE_STATE_FAILURE) - return FALSE; - - set_reconnect_state(service, FALSE); + return false; __connman_service_disconnect(service); g_free(service->passphrase); service->passphrase = NULL; - g_free(service->agent_passphrase); - service->agent_passphrase = NULL; - g_free(service->identity); service->identity = NULL; @@ -3851,13 +4078,13 @@ gboolean __connman_service_remove(struct connman_service *service) g_free(service->eap); service->eap = NULL; - set_idle(service); + service->error = CONNMAN_SERVICE_ERROR_UNKNOWN; - __connman_service_set_favorite(service, FALSE); + __connman_service_set_favorite(service, false); service_save(service); - return TRUE; + return true; } static DBusMessage *remove_service(DBusConnection *conn, @@ -3867,13 +4094,13 @@ static DBusMessage *remove_service(DBusConnection *conn, DBG("service %p", service); - if (__connman_service_remove(service) == FALSE) + if (!__connman_service_remove(service)) return __connman_error_not_supported(msg); return g_dbus_create_reply(msg, DBUS_TYPE_INVALID); } -static gboolean check_suitable_state(enum connman_service_state a, +static bool check_suitable_state(enum connman_service_state a, enum connman_service_state b) { /* @@ -3884,14 +4111,14 @@ static gboolean check_suitable_state(enum connman_service_state a, b == CONNMAN_SERVICE_STATE_READY) || (b == CONNMAN_SERVICE_STATE_ONLINE && a == CONNMAN_SERVICE_STATE_READY)) - return TRUE; + return true; return a == b; } static void downgrade_state(struct connman_service *service) { - if (service == NULL) + if (!service) return; DBG("service %p state4 %d state6 %d", service, service->state_ipv4, @@ -3913,13 +4140,14 @@ static void apply_relevant_default_downgrade(struct connman_service *service) struct connman_service *def_service; def_service = __connman_service_get_default(); - if (def_service == NULL) + if (!def_service) return; if (def_service == service && def_service->state == CONNMAN_SERVICE_STATE_ONLINE) { def_service->state = CONNMAN_SERVICE_STATE_READY; __connman_notifier_leave_online(def_service->type); + state_changed(def_service); } } @@ -3946,7 +4174,7 @@ static void switch_default_service(struct connman_service *default_service, static DBusMessage *move_service(DBusConnection *conn, DBusMessage *msg, void *user_data, - gboolean before) + bool before) { struct connman_service *service = user_data; struct connman_service *target; @@ -3959,11 +4187,11 @@ static DBusMessage *move_service(DBusConnection *conn, dbus_message_get_args(msg, NULL, DBUS_TYPE_OBJECT_PATH, &path, DBUS_TYPE_INVALID); - if (service->favorite == FALSE) + if (!service->favorite) return __connman_error_not_supported(msg); target = find_service(path); - if (target == NULL || target->favorite == FALSE || target == service) + if (!target || !target->favorite || target == service) return __connman_error_invalid_service(msg); if (target->type == CONNMAN_SERVICE_TYPE_VPN) { @@ -3971,19 +4199,18 @@ static DBusMessage *move_service(DBusConnection *conn, * We only allow VPN route splitting if there are * routes defined for a given VPN. */ - if (__connman_provider_check_routes(target->provider) - == FALSE) { + if (!__connman_provider_check_routes(target->provider)) { connman_info("Cannot move service. " "No routes defined for provider %s", __connman_provider_get_ident(target->provider)); return __connman_error_invalid_service(msg); } - target->do_split_routing = TRUE; + target->do_split_routing = true; } else - target->do_split_routing = FALSE; + target->do_split_routing = false; - service->do_split_routing = FALSE; + service->do_split_routing = false; target4 = __connman_ipconfig_get_method(target->ipconfig_ipv4); target6 = __connman_ipconfig_get_method(target->ipconfig_ipv6); @@ -4004,32 +4231,32 @@ static DBusMessage *move_service(DBusConnection *conn, */ if (target4 == CONNMAN_IPCONFIG_METHOD_OFF) { if (service6 != CONNMAN_IPCONFIG_METHOD_OFF) { - if (check_suitable_state(target->state_ipv6, - service->state_ipv6) == FALSE) + if (!check_suitable_state(target->state_ipv6, + service->state_ipv6)) return __connman_error_invalid_service(msg); } } if (target6 == CONNMAN_IPCONFIG_METHOD_OFF) { if (service4 != CONNMAN_IPCONFIG_METHOD_OFF) { - if (check_suitable_state(target->state_ipv4, - service->state_ipv4) == FALSE) + if (!check_suitable_state(target->state_ipv4, + service->state_ipv4)) return __connman_error_invalid_service(msg); } } if (service4 == CONNMAN_IPCONFIG_METHOD_OFF) { if (target6 != CONNMAN_IPCONFIG_METHOD_OFF) { - if (check_suitable_state(target->state_ipv6, - service->state_ipv6) == FALSE) + if (!check_suitable_state(target->state_ipv6, + service->state_ipv6)) return __connman_error_invalid_service(msg); } } if (service6 == CONNMAN_IPCONFIG_METHOD_OFF) { if (target4 != CONNMAN_IPCONFIG_METHOD_OFF) { - if (check_suitable_state(target->state_ipv4, - service->state_ipv4) == FALSE) + if (!check_suitable_state(target->state_ipv4, + service->state_ipv4)) return __connman_error_invalid_service(msg); } } @@ -4044,7 +4271,7 @@ static DBusMessage *move_service(DBusConnection *conn, * the service which goes up, needs to recompute its state which * is triggered via downgrading it - if relevant - to state ready. */ - if (before == TRUE) + if (before) switch_default_service(target, service); else switch_default_service(service, target); @@ -4057,13 +4284,13 @@ static DBusMessage *move_service(DBusConnection *conn, static DBusMessage *move_before(DBusConnection *conn, DBusMessage *msg, void *user_data) { - return move_service(conn, msg, user_data, TRUE); + return move_service(conn, msg, user_data, true); } static DBusMessage *move_after(DBusConnection *conn, DBusMessage *msg, void *user_data) { - return move_service(conn, msg, user_data, FALSE); + return move_service(conn, msg, user_data, false); } static DBusMessage *reset_counters(DBusConnection *conn, @@ -4087,12 +4314,12 @@ static void service_append_added_foreach(gpointer data, gpointer user_data) struct connman_service *service = data; DBusMessageIter *iter = user_data; - if (service == NULL || service->path == NULL) { + if (!service || !service->path) { DBG("service %p or path is NULL", service); return; } - if (g_hash_table_lookup(services_notify->add, service->path) != NULL) { + if (g_hash_table_lookup(services_notify->add, service->path)) { DBG("new %s", service->path); append_struct(service, iter); @@ -4118,10 +4345,14 @@ static void append_removed(gpointer key, gpointer value, gpointer user_data) dbus_message_iter_append_basic(iter, DBUS_TYPE_OBJECT_PATH, &objpath); } +static void service_append_removed(DBusMessageIter *iter, void *user_data) +{ + g_hash_table_foreach(services_notify->remove, append_removed, iter); +} + static gboolean service_send_changed(gpointer data) { DBusMessage *signal; - DBusMessageIter iter, array; DBG(""); @@ -4129,19 +4360,13 @@ static gboolean service_send_changed(gpointer data) signal = dbus_message_new_signal(CONNMAN_MANAGER_PATH, CONNMAN_MANAGER_INTERFACE, "ServicesChanged"); - if (signal == NULL) + if (!signal) return FALSE; __connman_dbus_append_objpath_dict_array(signal, - service_append_ordered, NULL); - - dbus_message_iter_init_append(signal, &iter); - dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, - DBUS_TYPE_OBJECT_PATH_AS_STRING, &array); - - g_hash_table_foreach(services_notify->remove, append_removed, &array); - - dbus_message_iter_close_container(&iter, &array); + service_append_ordered, NULL); + __connman_dbus_append_objpath_array(signal, + service_append_removed, NULL); dbus_connection_send(connection, signal, NULL); dbus_message_unref(signal); @@ -4174,7 +4399,7 @@ static void service_schedule_removed(struct connman_service *service) { DBG("service %p %s", service, service->path); - if (service == NULL || service->path == NULL) { + if (!service || !service->path) { DBG("service %p or path is NULL", service); return; } @@ -4186,15 +4411,15 @@ static void service_schedule_removed(struct connman_service *service) service_schedule_changed(); } -static connman_bool_t allow_property_changed(struct connman_service *service) +static bool allow_property_changed(struct connman_service *service) { if (g_hash_table_lookup_extended(services_notify->add, service->path, - NULL, NULL) == TRUE) { + NULL, NULL)) { DBG("no property updates for service %p", service); - return FALSE; + return false; } - return TRUE; + return true; } static const GDBusMethodTable service_methods[] = { @@ -4245,7 +4470,7 @@ static void service_free(gpointer user_data) service->path = NULL; - if (path != NULL) { + if (path) { __connman_connection_update_gateway(); g_dbus_unregister_interface(connection, path, @@ -4255,23 +4480,23 @@ static void service_free(gpointer user_data) g_hash_table_destroy(service->counter_table); - if (service->network != NULL) { + if (service->network) { __connman_network_disconnect(service->network); connman_network_unref(service->network); service->network = NULL; } - if (service->provider != NULL) + if (service->provider) connman_provider_unref(service->provider); - if (service->ipconfig_ipv4 != NULL) { + if (service->ipconfig_ipv4) { __connman_ipconfig_set_ops(service->ipconfig_ipv4, NULL); __connman_ipconfig_set_data(service->ipconfig_ipv4, NULL); __connman_ipconfig_unref(service->ipconfig_ipv4); service->ipconfig_ipv4 = NULL; } - if (service->ipconfig_ipv6 != NULL) { + if (service->ipconfig_ipv6) { __connman_ipconfig_set_ops(service->ipconfig_ipv6, NULL); __connman_ipconfig_set_data(service->ipconfig_ipv6, NULL); __connman_ipconfig_unref(service->ipconfig_ipv6); @@ -4287,11 +4512,11 @@ static void service_free(gpointer user_data) g_strfreev(service->proxies); g_strfreev(service->excludes); + g_free(service->hostname); g_free(service->domainname); g_free(service->pac); g_free(service->name); g_free(service->passphrase); - g_free(service->agent_passphrase); g_free(service->identifier); g_free(service->eap); g_free(service->identity); @@ -4304,24 +4529,27 @@ static void service_free(gpointer user_data) g_free(service->config_file); g_free(service->config_entry); - if (service->stats.timer != NULL) + if (service->stats.timer) g_timer_destroy(service->stats.timer); - if (service->stats_roaming.timer != NULL) + if (service->stats_roaming.timer) g_timer_destroy(service->stats_roaming.timer); + if (current_default == service) + current_default = NULL; + g_free(service); } static void stats_init(struct connman_service *service) { /* home */ - service->stats.valid = FALSE; - service->stats.enabled = FALSE; + service->stats.valid = false; + service->stats.enabled = false; service->stats.timer = g_timer_new(); /* roaming */ - service->stats_roaming.valid = FALSE; - service->stats_roaming.enabled = FALSE; + service->stats_roaming.valid = false; + service->stats_roaming.enabled = false; service->stats_roaming.timer = g_timer_new(); } @@ -4330,7 +4558,6 @@ static void service_initialize(struct connman_service *service) DBG("service %p", service); service->refcount = 1; - service->session_usage_count = 0; service->error = CONNMAN_SERVICE_ERROR_UNKNOWN; @@ -4341,13 +4568,13 @@ static void service_initialize(struct connman_service *service) service->state_ipv4 = CONNMAN_SERVICE_STATE_UNKNOWN; service->state_ipv6 = CONNMAN_SERVICE_STATE_UNKNOWN; - service->favorite = FALSE; - service->immutable = FALSE; - service->hidden = FALSE; + service->favorite = false; + service->immutable = false; + service->hidden = false; - service->ignore = FALSE; + service->ignore = false; - service->userconnect = FALSE; + service->connect_reason = CONNMAN_SERVICE_CONNECT_REASON_NONE; service->order = 0; @@ -4355,7 +4582,7 @@ static void service_initialize(struct connman_service *service) service->provider = NULL; - service->wps = FALSE; + service->wps = false; } /** @@ -4374,7 +4601,7 @@ struct connman_service *connman_service_create(void) struct connman_service *service; service = g_try_new0(struct connman_service, 1); - if (service == NULL) + if (!service) return NULL; DBG("service %p", service); @@ -4386,13 +4613,13 @@ struct connman_service *connman_service_create(void) counter = list->data; counters = g_try_new0(struct connman_stats_counter, 1); - if (counters == NULL) { + if (!counters) { g_hash_table_destroy(service->counter_table); g_free(service); return NULL; } - counters->append_all = TRUE; + counters->append_all = true; g_hash_table_replace(service->counter_table, (gpointer)counter, counters); @@ -4439,7 +4666,6 @@ void connman_service_unref_debug(struct connman_service *service, service_list = g_list_remove(service_list, service); - reply_pending(service, ECONNABORTED); __connman_service_disconnect(service); g_hash_table_remove(service_hash, service->identifier); @@ -4450,15 +4676,24 @@ static gint service_compare(gconstpointer a, gconstpointer b) struct connman_service *service_a = (void *) a; struct connman_service *service_b = (void *) b; enum connman_service_state state_a, state_b; + bool a_connected, b_connected; + gint strength; state_a = service_a->state; state_b = service_b->state; + a_connected = is_connected(service_a); + b_connected = is_connected(service_b); - if (state_a != state_b) { - gboolean a_connected = is_connected(service_a); - gboolean b_connected = is_connected(service_b); + if (a_connected && b_connected) { + if (service_a->order > service_b->order) + return -1; + + if (service_a->order < service_b->order) + return 1; + } - if (a_connected == TRUE && b_connected == TRUE) { + if (state_a != state_b) { + if (a_connected && b_connected) { /* We prefer online over ready state */ if (state_a == CONNMAN_SERVICE_STATE_ONLINE) return -1; @@ -4467,47 +4702,69 @@ static gint service_compare(gconstpointer a, gconstpointer b) return 1; } - if (a_connected == TRUE) + if (a_connected) return -1; - if (b_connected == TRUE) + if (b_connected) return 1; - if (is_connecting(service_a) == TRUE) + if (is_connecting(service_a)) return -1; - if (is_connecting(service_b) == TRUE) + if (is_connecting(service_b)) return 1; } - if (service_a->order > service_b->order) + if (service_a->favorite && !service_b->favorite) return -1; - if (service_a->order < service_b->order) + if (!service_a->favorite && service_b->favorite) return 1; - if (service_a->favorite == TRUE && service_b->favorite == FALSE) - return -1; + if (service_a->type != service_b->type) { - if (service_a->favorite == FALSE && service_b->favorite == TRUE) - return 1; + if (service_a->type == CONNMAN_SERVICE_TYPE_ETHERNET) + return -1; + if (service_b->type == CONNMAN_SERVICE_TYPE_ETHERNET) + return 1; - if (service_a->type != service_b->type) { - switch (service_a->type) { - case CONNMAN_SERVICE_TYPE_UNKNOWN: - case CONNMAN_SERVICE_TYPE_SYSTEM: - case CONNMAN_SERVICE_TYPE_ETHERNET: - case CONNMAN_SERVICE_TYPE_GPS: - case CONNMAN_SERVICE_TYPE_VPN: - case CONNMAN_SERVICE_TYPE_GADGET: - break; - case CONNMAN_SERVICE_TYPE_WIFI: + if (service_a->type == CONNMAN_SERVICE_TYPE_WIFI) + return -1; + if (service_b->type == CONNMAN_SERVICE_TYPE_WIFI) return 1; - case CONNMAN_SERVICE_TYPE_BLUETOOTH: - case CONNMAN_SERVICE_TYPE_CELLULAR: + + if (service_a->type == CONNMAN_SERVICE_TYPE_CELLULAR) return -1; - } + if (service_b->type == CONNMAN_SERVICE_TYPE_CELLULAR) + return 1; + + if (service_a->type == CONNMAN_SERVICE_TYPE_BLUETOOTH) + return -1; + if (service_b->type == CONNMAN_SERVICE_TYPE_BLUETOOTH) + return 1; + + if (service_a->type == CONNMAN_SERVICE_TYPE_VPN) + return -1; + if (service_b->type == CONNMAN_SERVICE_TYPE_VPN) + return 1; + + if (service_a->type == CONNMAN_SERVICE_TYPE_GADGET) + return -1; + if (service_b->type == CONNMAN_SERVICE_TYPE_GADGET) + return 1; } - return (gint) service_b->strength - (gint) service_a->strength; + strength = (gint) service_b->strength - (gint) service_a->strength; + if (strength) + return strength; + + return g_strcmp0(service_a->name, service_b->name); +} + +static void service_list_sort(void) +{ + if (service_list && service_list->next) { + service_list = g_list_sort(service_list, service_compare); + service_schedule_changed(); + } } /** @@ -4518,7 +4775,7 @@ static gint service_compare(gconstpointer a, gconstpointer b) */ enum connman_service_type connman_service_get_type(struct connman_service *service) { - if (service == NULL) + if (!service) return CONNMAN_SERVICE_TYPE_UNKNOWN; return service->type; @@ -4534,26 +4791,10 @@ char *connman_service_get_interface(struct connman_service *service) { int index; - if (service == NULL) + if (!service) return NULL; - if (service->type == CONNMAN_SERVICE_TYPE_VPN) { - if (service->ipconfig_ipv4) - index = __connman_ipconfig_get_index( - service->ipconfig_ipv4); - else if (service->ipconfig_ipv6) - index = __connman_ipconfig_get_index( - service->ipconfig_ipv6); - else - return NULL; - - return connman_inet_ifname(index); - } - - if (service->network == NULL) - return NULL; - - index = connman_network_get_index(service->network); + index = __connman_service_get_index(service); return connman_inet_ifname(index); } @@ -4567,7 +4808,7 @@ char *connman_service_get_interface(struct connman_service *service) struct connman_network * __connman_service_get_network(struct connman_service *service) { - if (service == NULL) + if (!service) return NULL; return service->network; @@ -4576,7 +4817,7 @@ __connman_service_get_network(struct connman_service *service) struct connman_ipconfig * __connman_service_get_ip4config(struct connman_service *service) { - if (service == NULL) + if (!service) return NULL; return service->ipconfig_ipv4; @@ -4585,7 +4826,7 @@ __connman_service_get_ip4config(struct connman_service *service) struct connman_ipconfig * __connman_service_get_ip6config(struct connman_service *service) { - if (service == NULL) + if (!service) return NULL; return service->ipconfig_ipv6; @@ -4603,11 +4844,11 @@ __connman_service_get_ipconfig(struct connman_service *service, int family) } -connman_bool_t __connman_service_is_connected_state(struct connman_service *service, +bool __connman_service_is_connected_state(struct connman_service *service, enum connman_ipconfig_type type) { - if (service == NULL) - return FALSE; + if (!service) + return false; switch (type) { case CONNMAN_IPCONFIG_TYPE_UNKNOWN: @@ -4618,11 +4859,12 @@ connman_bool_t __connman_service_is_connected_state(struct connman_service *serv return is_connected_state(service, service->state_ipv6); } - return FALSE; + return false; } -enum connman_service_security __connman_service_get_security(struct connman_service *service) +enum connman_service_security __connman_service_get_security( + struct connman_service *service) { - if (service == NULL) + if (!service) return CONNMAN_SERVICE_SECURITY_UNKNOWN; return service->security; @@ -4630,24 +4872,24 @@ enum connman_service_security __connman_service_get_security(struct connman_serv const char *__connman_service_get_phase2(struct connman_service *service) { - if (service == NULL) + if (!service) return NULL; return service->phase2; } -connman_bool_t __connman_service_wps_enabled(struct connman_service *service) +bool __connman_service_wps_enabled(struct connman_service *service) { - if (service == NULL) - return FALSE; + if (!service) + return false; return service->wps; } -void __connman_service_mark_dirty() - { - services_dirty = TRUE; - } +void __connman_service_mark_dirty(void) +{ + services_dirty = true; +} /** * __connman_service_set_favorite_delayed: @@ -4658,10 +4900,10 @@ void __connman_service_mark_dirty() * Change the favorite setting of service */ int __connman_service_set_favorite_delayed(struct connman_service *service, - connman_bool_t favorite, - gboolean delay_ordering) + bool favorite, + bool delay_ordering) { - if (service->hidden == TRUE) + if (service->hidden) return -EOPNOTSUPP; if (service->favorite == favorite) @@ -4669,18 +4911,14 @@ int __connman_service_set_favorite_delayed(struct connman_service *service, service->favorite = favorite; - if (delay_ordering == FALSE) - service->order = __connman_service_get_order(service); + if (!delay_ordering) + __connman_service_get_order(service); favorite_changed(service); - if (delay_ordering == FALSE) { + if (!delay_ordering) { - if (service_list->next != NULL) { - service_list = g_list_sort(service_list, - service_compare); - service_schedule_changed(); - } + service_list_sort(); __connman_connection_update_gateway(); } @@ -4696,21 +4934,26 @@ int __connman_service_set_favorite_delayed(struct connman_service *service, * Change the favorite setting of service */ int __connman_service_set_favorite(struct connman_service *service, - connman_bool_t favorite) + bool favorite) { return __connman_service_set_favorite_delayed(service, favorite, - FALSE); + false); } -connman_bool_t connman_service_get_favorite(struct connman_service *service) +bool connman_service_get_favorite(struct connman_service *service) { - return service->favorite; + return service->favorite; +} + +bool connman_service_get_autoconnect(struct connman_service *service) +{ + return service->autoconnect; } int __connman_service_set_immutable(struct connman_service *service, - connman_bool_t immutable) + bool immutable) { - if (service->hidden == TRUE) + if (service->hidden) return -EOPNOTSUPP; if (service->immutable == immutable) @@ -4724,9 +4967,9 @@ int __connman_service_set_immutable(struct connman_service *service, } int __connman_service_set_ignore(struct connman_service *service, - connman_bool_t ignore) + bool ignore) { - if (service == NULL) + if (!service) return -EINVAL; service->ignore = ignore; @@ -4737,42 +4980,35 @@ int __connman_service_set_ignore(struct connman_service *service, void __connman_service_set_string(struct connman_service *service, const char *key, const char *value) { - if (service->hidden == TRUE) + if (service->hidden) return; - if (g_str_equal(key, "EAP") == TRUE) { + if (g_str_equal(key, "EAP")) { g_free(service->eap); service->eap = g_strdup(value); - } else if (g_str_equal(key, "Identity") == TRUE) { + } else if (g_str_equal(key, "Identity")) { g_free(service->identity); service->identity = g_strdup(value); - } else if (g_str_equal(key, "CACertFile") == TRUE) { + } else if (g_str_equal(key, "CACertFile")) { g_free(service->ca_cert_file); service->ca_cert_file = g_strdup(value); - } else if (g_str_equal(key, "ClientCertFile") == TRUE) { + } else if (g_str_equal(key, "ClientCertFile")) { g_free(service->client_cert_file); service->client_cert_file = g_strdup(value); - } else if (g_str_equal(key, "PrivateKeyFile") == TRUE) { + } else if (g_str_equal(key, "PrivateKeyFile")) { g_free(service->private_key_file); service->private_key_file = g_strdup(value); - } else if (g_str_equal(key, "PrivateKeyPassphrase") == TRUE) { + } else if (g_str_equal(key, "PrivateKeyPassphrase")) { g_free(service->private_key_passphrase); service->private_key_passphrase = g_strdup(value); - } else if (g_str_equal(key, "Phase2") == TRUE) { + } else if (g_str_equal(key, "Phase2")) { g_free(service->phase2); service->phase2 = g_strdup(value); - } else if (g_str_equal(key, "Passphrase") == TRUE) { + } else if (g_str_equal(key, "Passphrase")) { g_free(service->passphrase); service->passphrase = g_strdup(value); } } -void __connman_service_set_userconnect(struct connman_service *service, - connman_bool_t userconnect) -{ - if (service != NULL) - service->userconnect = userconnect; -} - void __connman_service_set_search_domains(struct connman_service *service, char **domains) { @@ -4782,7 +5018,7 @@ void __connman_service_set_search_domains(struct connman_service *service, if (index < 0) return; - if (service->domains != NULL) { + if (service->domains) { remove_searchdomains(service, index, service->domains); g_strfreev(service->domains); @@ -4792,24 +5028,37 @@ void __connman_service_set_search_domains(struct connman_service *service, } } +/* + * This variant is used when domain search list is updated via + * dhcp and in that case the service is not yet fully connected so + * we cannot do same things as what the set() variant is doing. + */ +void __connman_service_update_search_domains(struct connman_service *service, + char **domains) +{ + g_strfreev(service->domains); + service->domains = g_strdupv(domains); +} + static void service_complete(struct connman_service *service) { reply_pending(service, EIO); - if (service->userconnect == FALSE) - __connman_service_auto_connect(); + if (service->connect_reason != CONNMAN_SERVICE_CONNECT_REASON_USER) + __connman_service_auto_connect(service->connect_reason); g_get_current_time(&service->modified); service_save(service); } -static void report_error_cb(void *user_context, gboolean retry, +static void report_error_cb(void *user_context, bool retry, void *user_data) { struct connman_service *service = user_context; - if (retry == TRUE) - __connman_service_connect(service); + if (retry) + __connman_service_connect(service, + CONNMAN_SERVICE_CONNECT_REASON_USER); else { /* It is not relevant to stay on Failure state * when failing is due to wrong user input */ @@ -4828,12 +5077,10 @@ int __connman_service_add_passphrase(struct connman_service *service, switch (service->security) { case CONNMAN_SERVICE_SECURITY_WEP: case CONNMAN_SERVICE_SECURITY_PSK: - err = __connman_service_set_passphrase(service, passphrase); - break; case CONNMAN_SERVICE_SECURITY_8021X: - __connman_service_set_agent_passphrase(service, - passphrase); + err = __connman_service_set_passphrase(service, passphrase); break; + case CONNMAN_SERVICE_SECURITY_UNKNOWN: case CONNMAN_SERVICE_SECURITY_NONE: case CONNMAN_SERVICE_SECURITY_WPA: @@ -4852,7 +5099,7 @@ static int check_wpspin(struct connman_service *service, const char *wpspin) int length; guint i; - if (wpspin == NULL) + if (!wpspin) return 0; length = strlen(wpspin); @@ -4879,53 +5126,56 @@ static int check_wpspin(struct connman_service *service, const char *wpspin) return 0; } -static void request_input_cb (struct connman_service *service, - connman_bool_t values_received, +static void request_input_cb(struct connman_service *service, + bool values_received, const char *name, int name_len, const char *identity, const char *passphrase, - gboolean wps, const char *wpspin, + bool wps, const char *wpspin, const char *error, void *user_data) { struct connman_device *device; + const char *security; int err = 0; - DBG ("RequestInput return, %p", service); + DBG("RequestInput return, %p", service); - if (error != NULL) { + if (error) { DBG("error: %s", error); if (g_strcmp0(error, "net.connman.Agent.Error.Canceled") == 0) { err = -EINVAL; - if (service->hidden == TRUE) + if (service->hidden) __connman_service_return_error(service, ECANCELED, user_data); goto done; } else { - if (service->hidden == TRUE) + if (service->hidden) __connman_service_return_error(service, ETIMEDOUT, user_data); } } - if (service->hidden == TRUE && name_len > 0 && name_len <= 32) { + if (service->hidden && name_len > 0 && name_len <= 32) { device = connman_network_get_device(service->network); + security = connman_network_get_string(service->network, + "WiFi.Security"); err = __connman_device_request_hidden_scan(device, name, name_len, identity, passphrase, - user_data); + security, user_data); if (err < 0) __connman_service_return_error(service, -err, user_data); } - if (values_received == FALSE || service->hidden == TRUE) { + if (!values_received || service->hidden) { err = -EINVAL; goto done; } - if (wps == TRUE && service->network != NULL) { + if (wps && service->network) { err = check_wpspin(service, wpspin); if (err < 0) goto done; @@ -4933,10 +5183,10 @@ static void request_input_cb (struct connman_service *service, connman_network_set_bool(service->network, "WiFi.UseWPS", wps); } - if (identity != NULL) + if (identity) __connman_service_set_agent_identity(service, identity); - if (passphrase != NULL) + if (passphrase) err = __connman_service_add_passphrase(service, passphrase); done: @@ -4944,11 +5194,9 @@ static void request_input_cb (struct connman_service *service, /* We forget any previous error. */ set_error(service, CONNMAN_SERVICE_ERROR_UNKNOWN); - __connman_service_connect(service); + __connman_service_connect(service, + CONNMAN_SERVICE_CONNECT_REASON_USER); - /* Never cache agent provided credentials */ - __connman_service_set_agent_identity(service, NULL); - __connman_service_set_agent_passphrase(service, NULL); } else if (err == -ENOKEY) { __connman_service_indicate_error(service, CONNMAN_SERVICE_ERROR_INVALID_KEY); @@ -4957,7 +5205,7 @@ static void request_input_cb (struct connman_service *service, * when failing is due to wrong user input */ service->state = CONNMAN_SERVICE_STATE_IDLE; - if (service->hidden == FALSE) { + if (!service->hidden) { /* * If there was a real error when requesting * hidden scan, then that error is returned already @@ -4978,10 +5226,10 @@ static void downgrade_connected_services(void) struct connman_service *up_service; GList *list; - for (list = service_list; list != NULL; list = list->next) { + for (list = service_list; list; list = list->next) { up_service = list->data; - if (is_connected(up_service) == FALSE) + if (!is_connected(up_service)) continue; if (up_service->state == CONNMAN_SERVICE_STATE_ONLINE) @@ -4998,12 +5246,12 @@ static int service_update_preferred_order(struct connman_service *default_servic unsigned int *tech_array; int i; - if (default_service == NULL || default_service == new_service || - default_service->state != new_state ) + if (!default_service || default_service == new_service || + default_service->state != new_state) return 0; tech_array = connman_setting_get_uint_list("PreferredTechnologies"); - if (tech_array != NULL) { + if (tech_array) { for (i = 0; tech_array[i] != 0; i += 1) { if (default_service->type == tech_array[i]) @@ -5029,10 +5277,10 @@ static void single_connected_tech(struct connman_service *allowed) DBG("keeping %p %s", allowed, allowed->path); - for (iter = service_list; iter != NULL; iter = iter->next) { + for (iter = service_list; iter; iter = iter->next) { service = iter->data; - if (is_connected(service) == FALSE) + if (!is_connected(service)) break; if (service == allowed) @@ -5041,7 +5289,7 @@ static void single_connected_tech(struct connman_service *allowed) services = g_slist_prepend(services, service); } - for (list = services; list != NULL; list = list->next) { + for (list = services; list; list = list->next) { service = list->data; DBG("disconnecting %p %s", service, service->path); @@ -5051,13 +5299,21 @@ static void single_connected_tech(struct connman_service *allowed) g_slist_free(services); } +static const char *get_dbus_sender(struct connman_service *service) +{ + if (!service->pending) + return NULL; + + return dbus_message_get_sender(service->pending); +} + static int service_indicate_state(struct connman_service *service) { enum connman_service_state old_state, new_state; struct connman_service *def_service; int result; - if (service == NULL) + if (!service) return -EINVAL; old_state = service->state; @@ -5090,63 +5346,55 @@ static int service_indicate_state(struct connman_service *service) if (new_state == CONNMAN_SERVICE_STATE_IDLE && old_state != CONNMAN_SERVICE_STATE_DISCONNECT) { - reply_pending(service, ECONNABORTED); __connman_service_disconnect(service); } if (new_state == CONNMAN_SERVICE_STATE_CONFIGURATION) { - if (service->new_service == FALSE && + if (!service->new_service && __connman_stats_service_register(service) == 0) { /* * For new services the statistics are updated after * we have successfully connected. */ - __connman_stats_get(service, FALSE, + __connman_stats_get(service, false, &service->stats.data); - __connman_stats_get(service, TRUE, + __connman_stats_get(service, true, &service->stats_roaming.data); } } - if (new_state == CONNMAN_SERVICE_STATE_IDLE) { - connman_bool_t reconnect; - - reconnect = get_reconnect_state(service); - if (reconnect == TRUE) - __connman_service_auto_connect(); - } - if (new_state == CONNMAN_SERVICE_STATE_READY) { enum connman_ipconfig_method method; - if (service->new_service == TRUE && + if (service->new_service && __connman_stats_service_register(service) == 0) { /* * This is normally done after configuring state * but for new service do this after we have connected * successfully. */ - __connman_stats_get(service, FALSE, + __connman_stats_get(service, false, &service->stats.data); - __connman_stats_get(service, TRUE, + __connman_stats_get(service, true, &service->stats_roaming.data); } - service->new_service = FALSE; + service->new_service = false; - service_update_preferred_order(def_service, service, new_state); + default_changed(); + + def_service = __connman_service_get_default(); - set_reconnect_state(service, TRUE); + service_update_preferred_order(def_service, service, new_state); - __connman_service_set_favorite(service, TRUE); + __connman_service_set_favorite(service, true); reply_pending(service, 0); g_get_current_time(&service->modified); service_save(service); - update_nameservers(service); dns_changed(service); domain_changed(service); proxy_changed(service); @@ -5156,7 +5404,7 @@ static int service_indicate_state(struct connman_service *service) if (service->type == CONNMAN_SERVICE_TYPE_WIFI && connman_network_get_bool(service->network, - "WiFi.UseWPS") == TRUE) { + "WiFi.UseWPS")) { const char *pass; pass = connman_network_get_string(service->network, @@ -5165,26 +5413,25 @@ static int service_indicate_state(struct connman_service *service) __connman_service_set_passphrase(service, pass); connman_network_set_bool(service->network, - "WiFi.UseWPS", FALSE); + "WiFi.UseWPS", false); } - default_changed(); - method = __connman_ipconfig_get_method(service->ipconfig_ipv6); if (method == CONNMAN_IPCONFIG_METHOD_OFF) __connman_ipconfig_disable_ipv6( service->ipconfig_ipv6); - if (connman_setting_get_bool("SingleConnectedTechnology") - == TRUE) + if (connman_setting_get_bool("SingleConnectedTechnology")) single_connected_tech(service); + else if (service->type != CONNMAN_SERVICE_TYPE_VPN) + vpn_auto_connect(); } else if (new_state == CONNMAN_SERVICE_STATE_DISCONNECT) { def_service = __connman_service_get_default(); - if (__connman_notifier_is_connected() == FALSE && - def_service != NULL && - def_service->provider != NULL) + if (!__connman_notifier_is_connected() && + def_service && + def_service->provider) connman_provider_disconnect(def_service->provider); default_changed(); @@ -5193,38 +5440,44 @@ static int service_indicate_state(struct connman_service *service) __connman_wpad_stop(service); - update_nameservers(service); dns_changed(service); domain_changed(service); proxy_changed(service); - __connman_notifier_disconnect(service->type); - /* * Previous services which are connected and which states * are set to online should reset relevantly ipconfig_state * to ready so wispr/portal will be rerun on those */ downgrade_connected_services(); + + __connman_service_auto_connect(CONNMAN_SERVICE_CONNECT_REASON_AUTO); } if (new_state == CONNMAN_SERVICE_STATE_FAILURE) { - if (service->userconnect == TRUE && + + if (service->connect_reason == CONNMAN_SERVICE_CONNECT_REASON_USER && connman_agent_report_error(service, service->path, error2string(service->error), - report_error_cb, NULL) == -EINPROGRESS) + report_error_cb, + get_dbus_sender(service), + NULL) == -EINPROGRESS) return 0; service_complete(service); } else set_error(service, CONNMAN_SERVICE_ERROR_UNKNOWN); - if (service_list->next != NULL) { - service_list = g_list_sort(service_list, service_compare); - service_schedule_changed(); - } + service_list_sort(); __connman_connection_update_gateway(); + if ((old_state == CONNMAN_SERVICE_STATE_ONLINE && + new_state != CONNMAN_SERVICE_STATE_READY) || + (old_state == CONNMAN_SERVICE_STATE_READY && + new_state != CONNMAN_SERVICE_STATE_ONLINE)) { + __connman_notifier_disconnect(service->type); + } + if (new_state == CONNMAN_SERVICE_STATE_ONLINE) { __connman_notifier_enter_online(service->type); default_changed(); @@ -5238,14 +5491,21 @@ int __connman_service_indicate_error(struct connman_service *service, { DBG("service %p error %d", service, error); - if (service == NULL) + if (!service) return -EINVAL; set_error(service, error); - if (service->error == CONNMAN_SERVICE_ERROR_INVALID_KEY) + /* + * 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) __connman_service_set_passphrase(service, NULL); + __connman_service_set_agent_identity(service, NULL); + __connman_service_ipconfig_indicate_state(service, CONNMAN_SERVICE_STATE_FAILURE, CONNMAN_IPCONFIG_TYPE_IPV4); @@ -5259,7 +5519,7 @@ int __connman_service_clear_error(struct connman_service *service) { DBG("service %p", service); - if (service == NULL) + if (!service) return -EINVAL; if (service->state != CONNMAN_SERVICE_STATE_FAILURE) @@ -5269,9 +5529,6 @@ int __connman_service_clear_error(struct connman_service *service) CONNMAN_SERVICE_STATE_UNKNOWN; set_error(service, CONNMAN_SERVICE_ERROR_UNKNOWN); - if (service->favorite == TRUE) - set_reconnect_state(service, TRUE); - __connman_service_ipconfig_indicate_state(service, CONNMAN_SERVICE_STATE_IDLE, CONNMAN_IPCONFIG_TYPE_IPV6); @@ -5291,7 +5548,16 @@ int __connman_service_clear_error(struct connman_service *service) int __connman_service_indicate_default(struct connman_service *service) { - DBG("service %p", service); + DBG("service %p state %s", service, state2string(service->state)); + + if (!is_connected(service)) { + /* + * If service is not yet fully connected, then we must not + * change the default yet. The default gw will be changed + * after the service state is in ready. + */ + return -EINPROGRESS; + } default_changed(); @@ -5302,7 +5568,7 @@ enum connman_service_state __connman_service_ipconfig_get_state( struct connman_service *service, enum connman_ipconfig_type type) { - if (service == NULL) + if (!service) return CONNMAN_SERVICE_STATE_UNKNOWN; if (type == CONNMAN_IPCONFIG_TYPE_IPV4) @@ -5327,7 +5593,7 @@ static void check_proxy_setup(struct connman_service *service) if (service->proxy_config != CONNMAN_SERVICE_PROXY_METHOD_UNKNOWN && (service->proxy_config != CONNMAN_SERVICE_PROXY_METHOD_AUTO || - service->pac != NULL)) + service->pac)) goto done; if (__connman_wpad_start(service) < 0) { @@ -5352,7 +5618,7 @@ static int connected_networks_count; static int original_rp_filter; static void service_rp_filter(struct connman_service *service, - gboolean connected) + bool connected) { enum connman_ipconfig_method method; @@ -5369,7 +5635,7 @@ static void service_rp_filter(struct connman_service *service, break; } - if (connected == TRUE) { + if (connected) { if (connected_networks_count == 1) { int filter_value; filter_value = __connman_ipconfig_set_rp_filter(); @@ -5398,8 +5664,13 @@ static void service_rp_filter(struct connman_service *service, static gboolean redo_wispr(gpointer user_data) { struct connman_service *service = user_data; + int refcount = service->refcount - 1; - DBG(""); + connman_service_unref(service); + if (refcount == 0) { + DBG("Service %p already removed", service); + return FALSE; + } __connman_wispr_start(service, CONNMAN_IPCONFIG_TYPE_IPV6); @@ -5427,7 +5698,7 @@ int __connman_service_online_check_failed(struct connman_service *service, * necessary IPv6 router advertisement messages that might have * DNS data etc. */ - g_timeout_add_seconds(1, redo_wispr, service); + g_timeout_add_seconds(1, redo_wispr, connman_service_ref(service)); return EAGAIN; } @@ -5438,9 +5709,9 @@ int __connman_service_ipconfig_indicate_state(struct connman_service *service, { struct connman_ipconfig *ipconfig = NULL; enum connman_service_state old_state; - int ret; + enum connman_ipconfig_method method; - if (service == NULL) + if (!service) return -EINVAL; if (type == CONNMAN_IPCONFIG_TYPE_IPV4) { @@ -5451,7 +5722,7 @@ int __connman_service_ipconfig_indicate_state(struct connman_service *service, ipconfig = service->ipconfig_ipv6; } - if (ipconfig == NULL) + if (!ipconfig) return -EINVAL; /* Any change? */ @@ -5475,11 +5746,9 @@ int __connman_service_ipconfig_indicate_state(struct connman_service *service, __connman_ipconfig_enable(ipconfig); break; case CONNMAN_SERVICE_STATE_READY: - update_nameservers(service); - if (type == CONNMAN_IPCONFIG_TYPE_IPV4) { check_proxy_setup(service); - service_rp_filter(service, TRUE); + service_rp_filter(service, true); } else { service->online_check_count = 1; __connman_wispr_start(service, type); @@ -5492,48 +5761,42 @@ int __connman_service_ipconfig_indicate_state(struct connman_service *service, return -EINVAL; if (type == CONNMAN_IPCONFIG_TYPE_IPV4) - service_rp_filter(service, FALSE); + service_rp_filter(service, false); break; case CONNMAN_SERVICE_STATE_FAILURE: break; } - /* We keep that state */ - if (type == CONNMAN_IPCONFIG_TYPE_IPV4) - service->state_ipv4 = new_state; - else if (type == CONNMAN_IPCONFIG_TYPE_IPV6) - service->state_ipv6 = new_state; - - ret = service_indicate_state(service); - - /* - * If the ipconfig method is OFF, then we set the state to IDLE - * so that it will not affect the combined state in the future. + /* Keep that state, but if the ipconfig method is OFF, then we set + the state to IDLE so that it will not affect the combined state + in the future. */ if (type == CONNMAN_IPCONFIG_TYPE_IPV4) { - enum connman_ipconfig_method method; method = __connman_ipconfig_get_method(service->ipconfig_ipv4); + if (method == CONNMAN_IPCONFIG_METHOD_OFF || - method == CONNMAN_IPCONFIG_METHOD_UNKNOWN) { - service->state_ipv4 = CONNMAN_SERVICE_STATE_IDLE; - ret = service_indicate_state(service); - } + method == CONNMAN_IPCONFIG_METHOD_UNKNOWN) + new_state = CONNMAN_SERVICE_STATE_IDLE; + + service->state_ipv4 = new_state; } else if (type == CONNMAN_IPCONFIG_TYPE_IPV6) { - enum connman_ipconfig_method method; method = __connman_ipconfig_get_method(service->ipconfig_ipv6); + if (method == CONNMAN_IPCONFIG_METHOD_OFF || - method == CONNMAN_IPCONFIG_METHOD_UNKNOWN) { - service->state_ipv6 = CONNMAN_SERVICE_STATE_IDLE; - ret = service_indicate_state(service); - } + method == CONNMAN_IPCONFIG_METHOD_UNKNOWN) + new_state = CONNMAN_SERVICE_STATE_IDLE; + + service->state_ipv6 = new_state; } - return ret; + update_nameservers(service); + + return service_indicate_state(service); } -static connman_bool_t prepare_network(struct connman_service *service) +static bool prepare_network(struct connman_service *service) { enum connman_network_type type; unsigned int ssid_len; @@ -5543,56 +5806,57 @@ static connman_bool_t prepare_network(struct connman_service *service) switch (type) { case CONNMAN_NETWORK_TYPE_UNKNOWN: case CONNMAN_NETWORK_TYPE_VENDOR: - return FALSE; + return false; case CONNMAN_NETWORK_TYPE_WIFI: - if (connman_network_get_blob(service->network, "WiFi.SSID", - &ssid_len) == NULL) - return FALSE; + if (!connman_network_get_blob(service->network, "WiFi.SSID", + &ssid_len)) + return false; - if (service->passphrase != NULL) + if (service->passphrase) connman_network_set_string(service->network, "WiFi.Passphrase", service->passphrase); break; case CONNMAN_NETWORK_TYPE_ETHERNET: + case CONNMAN_NETWORK_TYPE_GADGET: case CONNMAN_NETWORK_TYPE_BLUETOOTH_PAN: case CONNMAN_NETWORK_TYPE_BLUETOOTH_DUN: case CONNMAN_NETWORK_TYPE_CELLULAR: break; } - return TRUE; + return true; } static void prepare_8021x(struct connman_service *service) { - if (service->eap != NULL) + if (service->eap) connman_network_set_string(service->network, "WiFi.EAP", service->eap); - if (service->identity != NULL) + if (service->identity) connman_network_set_string(service->network, "WiFi.Identity", service->identity); - if (service->ca_cert_file != NULL) + if (service->ca_cert_file) connman_network_set_string(service->network, "WiFi.CACertFile", service->ca_cert_file); - if (service->client_cert_file != NULL) + if (service->client_cert_file) connman_network_set_string(service->network, "WiFi.ClientCertFile", service->client_cert_file); - if (service->private_key_file != NULL) + if (service->private_key_file) connman_network_set_string(service->network, "WiFi.PrivateKeyFile", service->private_key_file); - if (service->private_key_passphrase != NULL) + if (service->private_key_passphrase) connman_network_set_string(service->network, "WiFi.PrivateKeyPassphrase", service->private_key_passphrase); - if (service->phase2 != NULL) + if (service->phase2) connman_network_set_string(service->network, "WiFi.Phase2", service->phase2); } @@ -5601,16 +5865,17 @@ static int service_connect(struct connman_service *service) { int err; - if (service->hidden == TRUE) + if (service->hidden) return -EPERM; switch (service->type) { case CONNMAN_SERVICE_TYPE_UNKNOWN: case CONNMAN_SERVICE_TYPE_SYSTEM: case CONNMAN_SERVICE_TYPE_GPS: - case CONNMAN_SERVICE_TYPE_GADGET: + case CONNMAN_SERVICE_TYPE_P2P: return -EINVAL; case CONNMAN_SERVICE_TYPE_ETHERNET: + case CONNMAN_SERVICE_TYPE_GADGET: case CONNMAN_SERVICE_TYPE_BLUETOOTH: case CONNMAN_SERVICE_TYPE_CELLULAR: case CONNMAN_SERVICE_TYPE_VPN: @@ -5624,28 +5889,26 @@ 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->passphrase == NULL) { - if (service->network == NULL) + if (!service->passphrase) { + if (!service->network) return -EOPNOTSUPP; - if (service->wps == FALSE || - connman_network_get_bool( - service->network, - "WiFi.UseWPS") == FALSE) + if (!service->wps || + !connman_network_get_bool(service->network, "WiFi.UseWPS")) return -ENOKEY; } else if (service->error == CONNMAN_SERVICE_ERROR_INVALID_KEY) return -ENOKEY; break; case CONNMAN_SERVICE_SECURITY_8021X: - if (service->eap == NULL) + if (!service->eap) return -EINVAL; /* * never request credentials if using EAP-TLS * (EAP-TLS networks need to be fully provisioned) */ - if (g_str_equal(service->eap, "tls") == TRUE) + if (g_str_equal(service->eap, "tls")) break; /* @@ -5653,10 +5916,9 @@ static int service_connect(struct connman_service *service) * missing. Agent provided credentials can be used as * fallback if needed. */ - if ((service->identity == NULL && - service->agent_identity == NULL) || - (service->passphrase == NULL && - service->agent_passphrase == NULL)) + if ((!service->identity && + !service->agent_identity) || + !service->passphrase) return -ENOKEY; break; @@ -5664,8 +5926,8 @@ static int service_connect(struct connman_service *service) break; } - if (service->network != NULL) { - if (prepare_network(service) == FALSE) + if (service->network) { + if (!prepare_network(service)) return -EINVAL; switch (service->security) { @@ -5682,9 +5944,9 @@ static int service_connect(struct connman_service *service) } if (__connman_stats_service_register(service) == 0) { - __connman_stats_get(service, FALSE, + __connman_stats_get(service, false, &service->stats.data); - __connman_stats_get(service, TRUE, + __connman_stats_get(service, true, &service->stats_roaming.data); } @@ -5695,7 +5957,7 @@ static int service_connect(struct connman_service *service) err = __connman_network_connect(service->network); } else if (service->type == CONNMAN_SERVICE_TYPE_VPN && - service->provider != NULL) + service->provider) err = __connman_provider_connect(service->provider); else return -EOPNOTSUPP; @@ -5711,32 +5973,36 @@ static int service_connect(struct connman_service *service) return err; } - -int __connman_service_connect(struct connman_service *service) +int __connman_service_connect(struct connman_service *service, + enum connman_service_connect_reason reason) { int err; - DBG("service %p state %s", service, state2string(service->state)); + DBG("service %p state %s connect reason %s -> %s", + service, state2string(service->state), + reason2string(service->connect_reason), + reason2string(reason)); - if (is_connected(service) == TRUE) + if (is_connected(service)) return -EISCONN; - if (is_connecting(service) == TRUE) + if (is_connecting(service)) return -EALREADY; switch (service->type) { case CONNMAN_SERVICE_TYPE_UNKNOWN: case CONNMAN_SERVICE_TYPE_SYSTEM: case CONNMAN_SERVICE_TYPE_GPS: - case CONNMAN_SERVICE_TYPE_GADGET: + case CONNMAN_SERVICE_TYPE_P2P: return -EINVAL; default: - if (is_ipconfig_usable(service) == FALSE) + if (!is_ipconfig_usable(service)) return -ENOLINK; err = service_connect(service); } + service->connect_reason = reason; if (err >= 0) { set_error(service, CONNMAN_SERVICE_ERROR_UNKNOWN); return 0; @@ -5750,13 +6016,13 @@ int __connman_service_connect(struct connman_service *service) return -EINPROGRESS; } - if (service->network != NULL) + if (service->network) __connman_network_disconnect(service->network); else if (service->type == CONNMAN_SERVICE_TYPE_VPN && - service->provider != NULL) + service->provider) connman_provider_disconnect(service->provider); - if (service->userconnect == TRUE) { + if (service->connect_reason == CONNMAN_SERVICE_CONNECT_REASON_USER) { if (err == -ENOKEY || err == -EPERM) { DBusMessage *pending = NULL; @@ -5766,14 +6032,16 @@ int __connman_service_connect(struct connman_service *service) * after the real hidden network is connected or * connection failed. */ - if (service->hidden == TRUE) { + if (service->hidden) { pending = service->pending; service->pending = NULL; } err = __connman_agent_request_passphrase_input(service, - request_input_cb, pending); - if (service->hidden == TRUE && err != -EINPROGRESS) + request_input_cb, + get_dbus_sender(service), + pending); + if (service->hidden && err != -EINPROGRESS) service->pending = pending; return err; @@ -5790,14 +6058,17 @@ int __connman_service_disconnect(struct connman_service *service) DBG("service %p", service); - service->userconnect = FALSE; + service->connect_reason = CONNMAN_SERVICE_CONNECT_REASON_NONE; + service->proxy = CONNMAN_SERVICE_PROXY_METHOD_UNKNOWN; connman_agent_cancel(service); - if (service->network != NULL) { + reply_pending(service, ECONNABORTED); + + if (service->network) { err = __connman_network_disconnect(service->network); } else if (service->type == CONNMAN_SERVICE_TYPE_VPN && - service->provider != NULL) + service->provider) err = connman_provider_disconnect(service->provider); else return -EOPNOTSUPP; @@ -5836,21 +6107,19 @@ int __connman_service_disconnect_all(void) DBG(""); - for (iter = service_list; iter != NULL; iter = iter->next) { + for (iter = service_list; iter; iter = iter->next) { service = iter->data; - if (is_connected(service) == FALSE) + if (!is_connected(service)) break; services = g_slist_prepend(services, service); } - for (list = services; list != NULL; list = list->next) { + for (list = services; list; list = list->next) { struct connman_service *service = list->data; - service->ignore = TRUE; - - set_reconnect_state(service, FALSE); + service->ignore = true; __connman_service_disconnect(service); } @@ -5902,14 +6171,10 @@ int __connman_service_provision_changed(const char *ident) * Because the provision_changed() might have set some services * as favorite, we must sort the sequence now. */ - if (services_dirty == TRUE) { - services_dirty = FALSE; + if (services_dirty) { + services_dirty = false; - if (service_list->next != NULL) { - service_list = g_list_sort(service_list, - service_compare); - service_schedule_changed(); - } + service_list_sort(); __connman_connection_update_gateway(); } @@ -5920,7 +6185,7 @@ int __connman_service_provision_changed(const char *ident) void __connman_service_set_config(struct connman_service *service, const char *file_id, const char *entry) { - if (service == NULL) + if (!service) return; g_free(service->config_file); @@ -5941,13 +6206,13 @@ static struct connman_service *service_get(const char *identifier) struct connman_service *service; service = g_hash_table_lookup(service_hash, identifier); - if (service != NULL) { + if (service) { connman_service_ref(service); return service; } service = connman_service_create(); - if (service == NULL) + if (!service) return NULL; DBG("service %p", service); @@ -5966,7 +6231,7 @@ static int service_register(struct connman_service *service) { DBG("service %p", service); - if (service->path != NULL) + if (service->path) return -EALREADY; service->path = g_strdup_printf("%s/service/%s", CONNMAN_PATH, @@ -5974,74 +6239,75 @@ static int service_register(struct connman_service *service) DBG("path %s", service->path); - __connman_config_provision_service(service); - - service_load(service); + if (__connman_config_provision_service(service) < 0) + service_load(service); g_dbus_register_interface(connection, service->path, CONNMAN_SERVICE_INTERFACE, service_methods, service_signals, NULL, service, NULL); - if (service_list->next != NULL) { - service_list = g_list_sort(service_list, service_compare); - service_schedule_changed(); - } + service_list_sort(); __connman_connection_update_gateway(); return 0; } -static void service_up(struct connman_ipconfig *ipconfig) +static void service_up(struct connman_ipconfig *ipconfig, + const char *ifname) { struct connman_service *service = __connman_ipconfig_get_data(ipconfig); - DBG("%s up", __connman_ipconfig_get_ifname(ipconfig)); + DBG("%s up", ifname); link_changed(service); - service->stats.valid = FALSE; - service->stats_roaming.valid = FALSE; + service->stats.valid = false; + service->stats_roaming.valid = false; } -static void service_down(struct connman_ipconfig *ipconfig) +static void service_down(struct connman_ipconfig *ipconfig, + const char *ifname) { - DBG("%s down", __connman_ipconfig_get_ifname(ipconfig)); + DBG("%s down", ifname); } -static void service_lower_up(struct connman_ipconfig *ipconfig) +static void service_lower_up(struct connman_ipconfig *ipconfig, + const char *ifname) { struct connman_service *service = __connman_ipconfig_get_data(ipconfig); - DBG("%s lower up", __connman_ipconfig_get_ifname(ipconfig)); + DBG("%s lower up", ifname); stats_start(service); } -static void service_lower_down(struct connman_ipconfig *ipconfig) +static void service_lower_down(struct connman_ipconfig *ipconfig, + const char *ifname) { struct connman_service *service = __connman_ipconfig_get_data(ipconfig); - DBG("%s lower down", __connman_ipconfig_get_ifname(ipconfig)); + DBG("%s lower down", ifname); - if (is_idle_state(service, service->state_ipv4) == FALSE) + if (!is_idle_state(service, service->state_ipv4)) __connman_ipconfig_disable(service->ipconfig_ipv4); - if (is_idle_state(service, service->state_ipv6) == FALSE) + if (!is_idle_state(service, service->state_ipv6)) __connman_ipconfig_disable(service->ipconfig_ipv6); stats_stop(service); service_save(service); } -static void service_ip_bound(struct connman_ipconfig *ipconfig) +static void service_ip_bound(struct connman_ipconfig *ipconfig, + const char *ifname) { struct connman_service *service = __connman_ipconfig_get_data(ipconfig); enum connman_ipconfig_method method = CONNMAN_IPCONFIG_METHOD_UNKNOWN; enum connman_ipconfig_type type = CONNMAN_IPCONFIG_TYPE_UNKNOWN; - DBG("%s ip bound", __connman_ipconfig_get_ifname(ipconfig)); + DBG("%s ip bound", ifname); type = __connman_ipconfig_get_config_type(ipconfig); method = __connman_ipconfig_get_method(ipconfig); @@ -6058,13 +6324,14 @@ static void service_ip_bound(struct connman_ipconfig *ipconfig) settings_changed(service, ipconfig); } -static void service_ip_release(struct connman_ipconfig *ipconfig) +static void service_ip_release(struct connman_ipconfig *ipconfig, + const char *ifname) { struct connman_service *service = __connman_ipconfig_get_data(ipconfig); enum connman_ipconfig_method method = CONNMAN_IPCONFIG_METHOD_UNKNOWN; enum connman_ipconfig_type type = CONNMAN_IPCONFIG_TYPE_UNKNOWN; - DBG("%s ip release", __connman_ipconfig_get_ifname(ipconfig)); + DBG("%s ip release", ifname); type = __connman_ipconfig_get_config_type(ipconfig); method = __connman_ipconfig_get_method(ipconfig); @@ -6087,11 +6354,12 @@ static void service_ip_release(struct connman_ipconfig *ipconfig) settings_changed(service, ipconfig); } -static void service_route_changed(struct connman_ipconfig *ipconfig) +static void service_route_changed(struct connman_ipconfig *ipconfig, + const char *ifname) { struct connman_service *service = __connman_ipconfig_get_data(ipconfig); - DBG("%s route changed", __connman_ipconfig_get_ifname(ipconfig)); + DBG("%s route changed", ifname); settings_changed(service, ipconfig); } @@ -6114,7 +6382,7 @@ static struct connman_ipconfig *create_ip4config(struct connman_service *service ipconfig_ipv4 = __connman_ipconfig_create(index, CONNMAN_IPCONFIG_TYPE_IPV4); - if (ipconfig_ipv4 == NULL) + if (!ipconfig_ipv4) return NULL; __connman_ipconfig_set_method(ipconfig_ipv4, method); @@ -6133,7 +6401,7 @@ static struct connman_ipconfig *create_ip6config(struct connman_service *service ipconfig_ipv6 = __connman_ipconfig_create(index, CONNMAN_IPCONFIG_TYPE_IPV6); - if (ipconfig_ipv6 == NULL) + if (!ipconfig_ipv6) return NULL; __connman_ipconfig_set_data(ipconfig_ipv6, service); @@ -6147,11 +6415,11 @@ void __connman_service_read_ip4config(struct connman_service *service) { GKeyFile *keyfile; - if (service->ipconfig_ipv4 == NULL) + if (!service->ipconfig_ipv4) return; keyfile = connman_storage_load_service(service->identifier); - if (keyfile == NULL) + if (!keyfile) return; __connman_ipconfig_load(service->ipconfig_ipv4, keyfile, @@ -6165,7 +6433,7 @@ void connman_service_create_ip4config(struct connman_service *service, { DBG("ipv4 %p", service->ipconfig_ipv4); - if (service->ipconfig_ipv4 != NULL) + if (service->ipconfig_ipv4) return; service->ipconfig_ipv4 = create_ip4config(service, index, @@ -6177,11 +6445,11 @@ void __connman_service_read_ip6config(struct connman_service *service) { GKeyFile *keyfile; - if (service->ipconfig_ipv6 == NULL) + if (!service->ipconfig_ipv6) return; keyfile = connman_storage_load_service(service->identifier); - if (keyfile == NULL) + if (!keyfile) return; __connman_ipconfig_load(service->ipconfig_ipv6, keyfile, @@ -6195,7 +6463,7 @@ void connman_service_create_ip6config(struct connman_service *service, { DBG("ipv6 %p", service->ipconfig_ipv6); - if (service->ipconfig_ipv6 != NULL) + if (service->ipconfig_ipv6) return; service->ipconfig_ipv6 = create_ip6config(service, index); @@ -6215,17 +6483,15 @@ struct connman_service *connman_service_lookup_from_network(struct connman_netwo const char *ident, *group; char *name; - DBG("network %p", network); - - if (network == NULL) + if (!network) return NULL; ident = __connman_network_get_ident(network); - if (ident == NULL) + if (!ident) return NULL; group = connman_network_get_group(network); - if (group == NULL) + if (!group) return NULL; name = g_strdup_printf("%s_%s_%s", @@ -6241,7 +6507,7 @@ struct connman_service *__connman_service_lookup_from_index(int index) struct connman_service *service; GList *list; - for (list = service_list; list != NULL; list = list->next) { + for (list = service_list; list; list = list->next) { service = list->data; if (__connman_ipconfig_get_index(service->ipconfig_ipv4) @@ -6271,34 +6537,46 @@ const char *__connman_service_get_path(struct connman_service *service) return service->path; } +const char *__connman_service_get_name(struct connman_service *service) +{ + return service->name; +} + +enum connman_service_state __connman_service_get_state(struct connman_service *service) +{ + return service->state; +} + unsigned int __connman_service_get_order(struct connman_service *service) { - if (service == NULL) + unsigned int order = 0; + + if (!service) return 0; - if (service->favorite == FALSE) { - service->order = 0; - goto done; - } + service->order = 0; + + if (!service->favorite) + return 0; if (service == service_list->data) - service->order = 1; - else if (service->type == CONNMAN_SERVICE_TYPE_VPN && - service->do_split_routing == FALSE) + order = 1; + + if (service->type == CONNMAN_SERVICE_TYPE_VPN && + !service->do_split_routing) { service->order = 10; - else - service->order = 0; + order = 10; + } DBG("service %p name %s order %d split %d", service, service->name, - service->order, service->do_split_routing); + order, service->do_split_routing); -done: - return service->order; + return order; } void __connman_service_update_ordering(void) { - if (service_list != NULL && service_list->next != NULL) + if (service_list && service_list->next) service_list = g_list_sort(service_list, service_compare); } @@ -6319,6 +6597,8 @@ static enum connman_service_type convert_network_type(struct connman_network *ne return CONNMAN_SERVICE_TYPE_BLUETOOTH; case CONNMAN_NETWORK_TYPE_CELLULAR: return CONNMAN_SERVICE_TYPE_CELLULAR; + case CONNMAN_NETWORK_TYPE_GADGET: + return CONNMAN_SERVICE_TYPE_GADGET; } return CONNMAN_SERVICE_TYPE_UNKNOWN; @@ -6326,19 +6606,19 @@ static enum connman_service_type convert_network_type(struct connman_network *ne static enum connman_service_security convert_wifi_security(const char *security) { - if (security == NULL) + if (!security) return CONNMAN_SERVICE_SECURITY_UNKNOWN; - else if (g_str_equal(security, "none") == TRUE) + else if (g_str_equal(security, "none")) return CONNMAN_SERVICE_SECURITY_NONE; - else if (g_str_equal(security, "wep") == TRUE) + else if (g_str_equal(security, "wep")) return CONNMAN_SERVICE_SECURITY_WEP; - else if (g_str_equal(security, "psk") == TRUE) + else if (g_str_equal(security, "psk")) return CONNMAN_SERVICE_SECURITY_PSK; - else if (g_str_equal(security, "ieee8021x") == TRUE) + else if (g_str_equal(security, "ieee8021x")) return CONNMAN_SERVICE_SECURITY_8021X; - else if (g_str_equal(security, "wpa") == TRUE) + else if (g_str_equal(security, "wpa")) return CONNMAN_SERVICE_SECURITY_WPA; - else if (g_str_equal(security, "rsn") == TRUE) + else if (g_str_equal(security, "rsn")) return CONNMAN_SERVICE_SECURITY_RSN; else return CONNMAN_SERVICE_SECURITY_UNKNOWN; @@ -6352,21 +6632,21 @@ static void update_from_network(struct connman_service *service, DBG("service %p network %p", service, network); - if (is_connected(service) == TRUE) + if (is_connected(service)) return; - if (is_connecting(service) == TRUE) + if (is_connecting(service)) return; str = connman_network_get_string(network, "Name"); - if (str != NULL) { + if (str) { g_free(service->name); service->name = g_strdup(str); - service->hidden = FALSE; + service->hidden = false; } else { g_free(service->name); service->name = NULL; - service->hidden = TRUE; + service->hidden = true; } service->strength = connman_network_get_strength(network); @@ -6386,20 +6666,17 @@ static void update_from_network(struct connman_service *service, if (service->type == CONNMAN_SERVICE_TYPE_WIFI) service->wps = connman_network_get_bool(network, "WiFi.WPS"); - if (service->strength > strength && service->network != NULL) { + if (service->strength > strength && service->network) { connman_network_unref(service->network); service->network = connman_network_ref(network); strength_changed(service); } - if (service->network == NULL) + if (!service->network) service->network = connman_network_ref(network); - if (service_list->next != NULL) { - service_list = g_list_sort(service_list, service_compare); - service_schedule_changed(); - } + service_list_sort(); } /** @@ -6419,15 +6696,15 @@ struct connman_service * __connman_service_create_from_network(struct connman_ne DBG("network %p", network); - if (network == NULL) + if (!network) return NULL; ident = __connman_network_get_ident(network); - if (ident == NULL) + if (!ident) return NULL; group = connman_network_get_group(network); - if (group == NULL) + if (!group) return NULL; name = g_strdup_printf("%s_%s_%s", @@ -6435,13 +6712,13 @@ struct connman_service * __connman_service_create_from_network(struct connman_ne service = service_get(name); g_free(name); - if (service == NULL) + if (!service) return NULL; - if (__connman_network_get_weakness(network) == TRUE) + if (__connman_network_get_weakness(network)) return service; - if (service->path != NULL) { + if (service->path) { update_from_network(service, network); __connman_connection_update_gateway(); return service; @@ -6450,11 +6727,11 @@ struct connman_service * __connman_service_create_from_network(struct connman_ne service->type = convert_network_type(network); auto_connect_types = connman_setting_get_uint_list("DefaultAutoConnectTechnologies"); - service->autoconnect = FALSE; - for (i = 0; auto_connect_types != NULL && + service->autoconnect = false; + for (i = 0; auto_connect_types && auto_connect_types[i] != 0; i++) { if (service->type == auto_connect_types[i]) { - service->autoconnect = TRUE; + service->autoconnect = true; break; } } @@ -6468,9 +6745,10 @@ struct connman_service * __connman_service_create_from_network(struct connman_ne case CONNMAN_SERVICE_TYPE_GADGET: case CONNMAN_SERVICE_TYPE_WIFI: case CONNMAN_SERVICE_TYPE_CELLULAR: + case CONNMAN_SERVICE_TYPE_P2P: break; case CONNMAN_SERVICE_TYPE_ETHERNET: - service->favorite = TRUE; + service->favorite = true; break; } @@ -6481,19 +6759,19 @@ struct connman_service * __connman_service_create_from_network(struct connman_ne index = connman_network_get_index(network); - if (service->ipconfig_ipv4 == NULL) + if (!service->ipconfig_ipv4) service->ipconfig_ipv4 = create_ip4config(service, index, CONNMAN_IPCONFIG_METHOD_DHCP); - if (service->ipconfig_ipv6 == NULL) + if (!service->ipconfig_ipv6) service->ipconfig_ipv6 = create_ip6config(service, index); service_register(service); - if (service->favorite == TRUE) { + if (service->favorite) { device = connman_network_get_device(service->network); - if (device && connman_device_get_scanning(device) == FALSE) - __connman_service_auto_connect(); + if (device && !connman_device_get_scanning(device)) + __connman_service_auto_connect(CONNMAN_SERVICE_CONNECT_REASON_AUTO); } __connman_notifier_service_add(service, service->name); @@ -6504,20 +6782,18 @@ struct connman_service * __connman_service_create_from_network(struct connman_ne void __connman_service_update_from_network(struct connman_network *network) { - connman_bool_t need_sort = FALSE; + bool need_sort = false; struct connman_service *service; uint8_t strength; - connman_bool_t roaming; + bool roaming; const char *name; - connman_bool_t stats_enable; - - DBG("network %p", network); + bool stats_enable; service = connman_service_lookup_from_network(network); - if (service == NULL) + if (!service) return; - if (service->network == NULL) + if (!service->network) return; name = connman_network_get_string(service->network, "Name"); @@ -6525,7 +6801,7 @@ void __connman_service_update_from_network(struct connman_network *network) g_free(service->name); service->name = g_strdup(name); - if (allow_property_changed(service) == TRUE) + if (allow_property_changed(service)) connman_dbus_property_changed_basic(service->path, CONNMAN_SERVICE_INTERFACE, "Name", DBUS_TYPE_STRING, &service->name); @@ -6539,7 +6815,7 @@ void __connman_service_update_from_network(struct connman_network *network) goto roaming; service->strength = strength; - need_sort = TRUE; + need_sort = true; strength_changed(service); @@ -6549,24 +6825,20 @@ roaming: goto sorting; stats_enable = stats_enabled(service); - if (stats_enable == TRUE) + if (stats_enable) stats_stop(service); service->roaming = roaming; - need_sort = TRUE; + need_sort = true; - if (stats_enable == TRUE) + if (stats_enable) stats_start(service); roaming_changed(service); sorting: - if (need_sort == TRUE) { - if (service_list->next != NULL) { - service_list = g_list_sort(service_list, - service_compare); - service_schedule_changed(); - } + if (need_sort) { + service_list_sort(); } } @@ -6574,13 +6846,14 @@ void __connman_service_remove_from_network(struct connman_network *network) { struct connman_service *service; - DBG("network %p", network); - service = connman_service_lookup_from_network(network); - if (service == NULL) + + DBG("network %p service %p", network, service); + + if (!service) return; - service->ignore = TRUE; + service->ignore = true; __connman_connection_gateway_remove(service, CONNMAN_IPCONFIG_TYPE_ALL); @@ -6605,42 +6878,42 @@ __connman_service_create_from_provider(struct connman_provider *provider) DBG("provider %p", provider); ident = __connman_provider_get_ident(provider); - if (ident == NULL) + if (!ident) return NULL; name = g_strdup_printf("vpn_%s", ident); service = service_get(name); g_free(name); - if (service == NULL) + if (!service) return NULL; service->type = CONNMAN_SERVICE_TYPE_VPN; service->provider = connman_provider_ref(provider); - service->autoconnect = FALSE; - service->userconnect = TRUE; + service->autoconnect = false; + service->favorite = true; service->state_ipv4 = service->state_ipv6 = CONNMAN_SERVICE_STATE_IDLE; service->state = combine_state(service->state_ipv4, service->state_ipv6); str = connman_provider_get_string(provider, "Name"); - if (str != NULL) { + if (str) { g_free(service->name); service->name = g_strdup(str); - service->hidden = FALSE; + service->hidden = false; } else { g_free(service->name); service->name = NULL; - service->hidden = TRUE; + service->hidden = true; } service->strength = 0; - if (service->ipconfig_ipv4 == NULL) + if (!service->ipconfig_ipv4) service->ipconfig_ipv4 = create_ip4config(service, index, CONNMAN_IPCONFIG_METHOD_MANUAL); - if (service->ipconfig_ipv6 == NULL) + if (!service->ipconfig_ipv6) service->ipconfig_ipv6 = create_ip6config(service, index); service_register(service); @@ -6651,7 +6924,7 @@ __connman_service_create_from_provider(struct connman_provider *provider) return service; } -static void remove_unprovisioned_services() +static void remove_unprovisioned_services(void) { gchar **services; GKeyFile *keyfile, *configkeyfile; @@ -6659,29 +6932,29 @@ static void remove_unprovisioned_services() int i = 0; services = connman_storage_get_services(); - if (services == NULL) + if (!services) return; - for (;services[i] != NULL; i++) { + for (; services[i]; i++) { file = section = NULL; keyfile = configkeyfile = NULL; keyfile = connman_storage_load_service(services[i]); - if (keyfile == NULL) + if (!keyfile) continue; file = g_key_file_get_string(keyfile, services[i], "Config.file", NULL); - if (file == NULL) + if (!file) goto next; section = g_key_file_get_string(keyfile, services[i], "Config.ident", NULL); - if (section == NULL) + if (!section) goto next; configkeyfile = __connman_storage_load_config(file); - if (configkeyfile == NULL) { + if (!configkeyfile) { /* * Config file is missing, remove the provisioned * service. @@ -6690,7 +6963,7 @@ static void remove_unprovisioned_services() goto next; } - if (g_key_file_has_group(configkeyfile, section) == FALSE) + if (!g_key_file_has_group(configkeyfile, section)) /* * Config section is missing, remove the provisioned * service. @@ -6698,10 +6971,10 @@ static void remove_unprovisioned_services() __connman_storage_remove_service(services[i]); next: - if (keyfile != NULL) + if (keyfile) g_key_file_free(keyfile); - if (configkeyfile != NULL) + if (configkeyfile) g_key_file_free(configkeyfile); g_free(section); @@ -6777,11 +7050,18 @@ void __connman_service_cleanup(void) { DBG(""); + if (vpn_autoconnect_timeout) { + g_source_remove(vpn_autoconnect_timeout); + vpn_autoconnect_timeout = 0; + } + if (autoconnect_timeout != 0) { g_source_remove(autoconnect_timeout); autoconnect_timeout = 0; } + connman_agent_driver_unregister(&agent_driver); + g_list_free(service_list); service_list = NULL; @@ -6799,7 +7079,5 @@ void __connman_service_cleanup(void) } g_free(services_notify); - connman_agent_driver_unregister(&agent_driver); - dbus_connection_unref(connection); } diff --git a/src/session.c b/src/session.c index 6d3827b7..00ef3696 100644 --- a/src/session.c +++ b/src/session.c @@ -2,8 +2,8 @@ * * Connection Manager * - * Copyright (C) 2007-2012 Intel Corporation. All rights reserved. - * Copyright (C) 2011 BWM CarIT GmbH. All rights reserved. + * Copyright (C) 2007-2014 Intel Corporation. All rights reserved. + * Copyright (C) 2011-2014 BWM CarIT GmbH. 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 @@ -34,24 +34,10 @@ static DBusConnection *connection; static GHashTable *session_hash; -static connman_bool_t sessionmode; +static GHashTable *service_hash; static struct connman_session *ecall_session; -static GSList *policy_list; - -enum connman_session_trigger { - CONNMAN_SESSION_TRIGGER_UNKNOWN = 0, - CONNMAN_SESSION_TRIGGER_SETTING = 1, - CONNMAN_SESSION_TRIGGER_CONNECT = 2, - CONNMAN_SESSION_TRIGGER_DISCONNECT = 3, - CONNMAN_SESSION_TRIGGER_SERVICE = 4, - CONNMAN_SESSION_TRIGGER_ECALL = 5, -}; - -enum connman_session_reason { - CONNMAN_SESSION_REASON_UNKNOWN = 0, - CONNMAN_SESSION_REASON_CONNECT = 1, - CONNMAN_SESSION_REASON_FREE_RIDE = 2, -}; +static uint32_t session_mark = 256; +static struct firewall_context *global_firewall = NULL; enum connman_session_state { CONNMAN_SESSION_STATE_DISCONNECTED = 0, @@ -59,23 +45,9 @@ enum connman_session_state { CONNMAN_SESSION_STATE_ONLINE = 2, }; -struct service_entry { - struct connman_session *session; - /* track why this service was selected */ - enum connman_session_reason reason; - enum connman_service_state state; - const char *name; - struct connman_service *service; - char *ifname; - const char *bearer; - GSList *pending_timeouts; -}; - struct session_info { struct connman_session_config config; enum connman_session_state state; - struct service_entry *entry; - enum connman_session_reason reason; }; struct connman_session { @@ -84,52 +56,41 @@ struct connman_session { char *notify_path; guint notify_watch; - struct connman_session_policy *policy; - - connman_bool_t append_all; + bool active; + bool append_all; struct session_info *info; struct session_info *info_last; + struct connman_service *service; + struct connman_service *service_last; struct connman_session_config *policy_config; GSList *user_allowed_bearers; - connman_bool_t ecall; + bool ecall; - GList *service_list; - GHashTable *service_hash; + enum connman_session_id_type id_type; + struct firewall_context *fw; + uint32_t mark; + int index; + char *gateway; + bool policy_routing; }; -static const char *trigger2string(enum connman_session_trigger trigger) -{ - switch (trigger) { - case CONNMAN_SESSION_TRIGGER_UNKNOWN: - break; - case CONNMAN_SESSION_TRIGGER_SETTING: - return "setting"; - case CONNMAN_SESSION_TRIGGER_CONNECT: - return "connect"; - case CONNMAN_SESSION_TRIGGER_DISCONNECT: - return "disconnect"; - case CONNMAN_SESSION_TRIGGER_SERVICE: - return "service"; - case CONNMAN_SESSION_TRIGGER_ECALL: - return "ecall"; - } +struct connman_service_info { + struct connman_service *service; + GSList *sessions; +}; - return NULL; -} +static struct connman_session_policy *policy; +static void session_activate(struct connman_session *session); +static void session_deactivate(struct connman_session *session); +static void update_session_state(struct connman_session *session); -static const char *reason2string(enum connman_session_reason reason) +static void cleanup_service(gpointer data) { - switch (reason) { - case CONNMAN_SESSION_REASON_UNKNOWN: - return "unknown"; - case CONNMAN_SESSION_REASON_CONNECT: - return "connect"; - case CONNMAN_SESSION_REASON_FREE_RIDE: - return "free-ride"; - } + struct connman_service_info *info = data; - return NULL; + g_slist_free(info->sessions); + g_free(info); } static const char *state2string(enum connman_session_state state) @@ -196,14 +157,14 @@ static int bearer2service(const char *bearer, enum connman_service_type *type) *type = CONNMAN_SERVICE_TYPE_ETHERNET; else if (g_strcmp0(bearer, "wifi") == 0) *type = CONNMAN_SERVICE_TYPE_WIFI; + else if (g_strcmp0(bearer, "gadget") == 0) + *type = CONNMAN_SERVICE_TYPE_GADGET; else if (g_strcmp0(bearer, "bluetooth") == 0) *type = CONNMAN_SERVICE_TYPE_BLUETOOTH; else if (g_strcmp0(bearer, "cellular") == 0) *type = CONNMAN_SERVICE_TYPE_CELLULAR; else if (g_strcmp0(bearer, "vpn") == 0) *type = CONNMAN_SERVICE_TYPE_VPN; - else if (g_strcmp0(bearer, "*") == 0) - *type = CONNMAN_SERVICE_TYPE_UNKNOWN; else return -EINVAL; @@ -215,6 +176,8 @@ static char *service2bearer(enum connman_service_type type) switch (type) { case CONNMAN_SERVICE_TYPE_ETHERNET: return "ethernet"; + case CONNMAN_SERVICE_TYPE_GADGET: + return "gadget"; case CONNMAN_SERVICE_TYPE_WIFI: return "wifi"; case CONNMAN_SERVICE_TYPE_BLUETOOTH: @@ -223,30 +186,220 @@ static char *service2bearer(enum connman_service_type type) return "cellular"; case CONNMAN_SERVICE_TYPE_VPN: return "vpn"; - case CONNMAN_SERVICE_TYPE_UNKNOWN: - return "*"; case CONNMAN_SERVICE_TYPE_SYSTEM: case CONNMAN_SERVICE_TYPE_GPS: - case CONNMAN_SERVICE_TYPE_GADGET: + case CONNMAN_SERVICE_TYPE_P2P: + case CONNMAN_SERVICE_TYPE_UNKNOWN: return ""; } return ""; } +static int init_firewall(void) +{ + struct firewall_context *fw; + int err; + + if (global_firewall) + return 0; + + fw = __connman_firewall_create(); + + err = __connman_firewall_add_rule(fw, "mangle", "INPUT", + "-j CONNMARK --restore-mark"); + if (err < 0) + goto err; + + err = __connman_firewall_add_rule(fw, "mangle", "POSTROUTING", + "-j CONNMARK --save-mark"); + if (err < 0) + goto err; + + err = __connman_firewall_enable(fw); + if (err < 0) + goto err; + + global_firewall = fw; + + return 0; + +err: + __connman_firewall_destroy(fw); + + return err; +} + +static void cleanup_firewall(void) +{ + if (!global_firewall) + return; + + __connman_firewall_disable(global_firewall); + __connman_firewall_destroy(global_firewall); +} + +static int init_firewall_session(struct connman_session *session) +{ + struct firewall_context *fw; + int err; + + if (session->policy_config->id_type == CONNMAN_SESSION_ID_TYPE_UNKNOWN) + return 0; + + DBG(""); + + err = init_firewall(); + if (err < 0) + return err; + + fw = __connman_firewall_create(); + if (!fw) + return -ENOMEM; + + switch (session->policy_config->id_type) { + case CONNMAN_SESSION_ID_TYPE_UID: + err = __connman_firewall_add_rule(fw, "mangle", "OUTPUT", + "-m owner --uid-owner %s -j MARK --set-mark %d", + session->policy_config->id, + session->mark); + break; + case CONNMAN_SESSION_ID_TYPE_GID: + err = __connman_firewall_add_rule(fw, "mangle", "OUTPUT", + "-m owner --gid-owner %s -j MARK --set-mark %d", + session->policy_config->id, + session->mark); + break; + case CONNMAN_SESSION_ID_TYPE_LSM: + default: + err = -EINVAL; + } + + if (err < 0) + goto err; + + session->id_type = session->policy_config->id_type; + + err = __connman_firewall_enable(fw); + if (err) + goto err; + + session->fw = fw; + + return 0; + +err: + __connman_firewall_destroy(fw); + + return err; +} + +static void cleanup_firewall_session(struct connman_session *session) +{ + if (!session->fw) + return; + + __connman_firewall_disable(session->fw); + __connman_firewall_destroy(session->fw); + + session->fw = NULL; +} + +static int init_routing_table(struct connman_session *session) +{ + int err; + + if (session->policy_config->id_type == CONNMAN_SESSION_ID_TYPE_UNKNOWN) + return 0; + + DBG(""); + + err = __connman_inet_add_fwmark_rule(session->mark, + AF_INET, session->mark); + if (err < 0) + return err; + + err = __connman_inet_add_fwmark_rule(session->mark, + AF_INET6, session->mark); + if (err < 0) + __connman_inet_del_fwmark_rule(session->mark, + AF_INET, session->mark); + session->policy_routing = true; + + return err; +} + +static void del_default_route(struct connman_session *session) +{ + if (!session->gateway) + return; + + DBG("index %d routing table %d default gateway %s", + session->index, session->mark, session->gateway); + + __connman_inet_del_default_from_table(session->mark, + session->index, session->gateway); + g_free(session->gateway); + session->gateway = NULL; + session->index = -1; +} + +static void add_default_route(struct connman_session *session) +{ + struct connman_ipconfig *ipconfig; + int err; + + if (!session->service) + return; + + ipconfig = __connman_service_get_ip4config(session->service); + session->index = __connman_ipconfig_get_index(ipconfig); + session->gateway = g_strdup(__connman_ipconfig_get_gateway(ipconfig)); + + DBG("index %d routing table %d default gateway %s", + session->index, session->mark, session->gateway); + + err = __connman_inet_add_default_to_table(session->mark, + session->index, session->gateway); + if (err < 0) + DBG("session %p %s", session, strerror(-err)); +} + +static void cleanup_routing_table(struct connman_session *session) +{ + DBG(""); + + if (session->policy_routing) { + __connman_inet_del_fwmark_rule(session->mark, + AF_INET6, session->mark); + + __connman_inet_del_fwmark_rule(session->mark, + AF_INET, session->mark); + session->policy_routing = false; + } + + del_default_route(session); +} + +static void update_routing_table(struct connman_session *session) +{ + del_default_route(session); + add_default_route(session); +} + static void destroy_policy_config(struct connman_session *session) { - if (session->policy == NULL) { + if (!policy) { g_free(session->policy_config); return; } - (*session->policy->destroy)(session); + policy->destroy(session); } static void free_session(struct connman_session *session) { - if (session == NULL) + if (!session) return; if (session->notify_watch > 0) @@ -259,158 +412,123 @@ static void free_session(struct connman_session *session) g_free(session->notify_path); g_free(session->info); g_free(session->info_last); + g_free(session->gateway); g_free(session); } +static void set_active_session(struct connman_session *session, bool enable) +{ + + if (policy && policy->session_changed) + policy->session_changed(session, enable, + session->info->config.allowed_bearers); + + __connman_service_set_active_session(enable, + session->info->config.allowed_bearers); +} + static void cleanup_session(gpointer user_data) { struct connman_session *session = user_data; - struct session_info *info = session->info; DBG("remove %s", session->session_path); - g_slist_free(session->user_allowed_bearers); - if (session->service_hash != NULL) - g_hash_table_destroy(session->service_hash); - g_list_free(session->service_list); - - if (info->entry != NULL && - info->entry->reason == CONNMAN_SESSION_REASON_CONNECT) { - __connman_service_disconnect(info->entry->service); - } - - free_session(session); -} + cleanup_routing_table(session); + cleanup_firewall_session(session); -static int assign_policy_plugin(struct connman_session *session) -{ - if (session->policy != NULL) - return -EALREADY; + if (session->active) + set_active_session(session, false); - if (policy_list == NULL) - return 0; + session_deactivate(session); + update_session_state(session); - session->policy = policy_list->data; + g_slist_free(session->user_allowed_bearers); - return 0; + free_session(session); } -struct user_config { +struct creation_data { DBusMessage *pending; + struct connman_session *session; + /* user config */ enum connman_session_type type; GSList *allowed_bearers; }; -static void cleanup_user_config(struct user_config *user_config) +static void cleanup_creation_data(struct creation_data *creation_data) { - if (user_config == NULL) + if (!creation_data) return; - if (user_config->pending != NULL) - dbus_message_unref(user_config->pending); + if (creation_data->pending) + dbus_message_unref(creation_data->pending); - g_slist_free(user_config->allowed_bearers); - g_free(user_config); + g_slist_free(creation_data->allowed_bearers); + g_free(creation_data); } static int create_policy_config(struct connman_session *session, connman_session_config_func_t cb, - struct user_config *user_config) + struct creation_data *creation_data) { struct connman_session_config *config; - if (session->policy == NULL) { + if (!policy) { config = connman_session_create_default_config(); - if (config == NULL) { + if (!config) { free_session(session); - cleanup_user_config(user_config); + cleanup_creation_data(creation_data); return -ENOMEM; } - return cb(session, config, user_config, 0); + return cb(session, config, creation_data, 0); } - return (*session->policy->create)(session, cb, user_config); + return policy->create(session, cb, creation_data); } -static void probe_policy(struct connman_session_policy *policy) +int connman_session_policy_register(struct connman_session_policy *plugin) { + if (policy) + return -EINVAL; - GHashTableIter iter; - gpointer key, value; - struct connman_session *session; - - DBG("policy %p name %s", policy, policy->name); + if (!plugin->create || !plugin->destroy) + return -EINVAL; - g_hash_table_iter_init(&iter, session_hash); + DBG("name %s", plugin->name); - while (g_hash_table_iter_next(&iter, &key, &value) == TRUE) { - session = value; + policy = plugin; - if (session->policy != NULL) - continue; - - assign_policy_plugin(session); - } + return 0; } -static void remove_policy(struct connman_session_policy *policy) +void connman_session_policy_unregister(struct connman_session_policy *plugin) { - GHashTableIter iter; - gpointer key, value; - struct connman_session *session; - - if (session_hash == NULL) + if (plugin != policy) return; - DBG("policy %p name %s", policy, policy->name); - - g_hash_table_iter_init(&iter, session_hash); - - while (g_hash_table_iter_next(&iter, &key, &value) == TRUE) { - session = value; - - if (session->policy != policy) - continue; - - session->policy = NULL; - assign_policy_plugin(session); - } -} - -static gint compare_priority(gconstpointer a, gconstpointer b) -{ - const struct connman_session_policy *policy1 = a; - const struct connman_session_policy *policy2 = b; - - return policy2->priority - policy1->priority; -} - - -int connman_session_policy_register(struct connman_session_policy *policy) -{ DBG("name %s", policy->name); - if (policy->create == NULL || policy->destroy == NULL) - return -EINVAL; - - policy_list = g_slist_insert_sorted(policy_list, policy, - compare_priority); - - probe_policy(policy); - - return 0; + policy = NULL; } -void connman_session_policy_unregister(struct connman_session_policy *policy) -{ - DBG("name %s", policy->name); +static int default_bearers[] = { + CONNMAN_SERVICE_TYPE_ETHERNET, + CONNMAN_SERVICE_TYPE_WIFI, + CONNMAN_SERVICE_TYPE_BLUETOOTH, + CONNMAN_SERVICE_TYPE_CELLULAR, + CONNMAN_SERVICE_TYPE_GADGET, +}; - policy_list = g_slist_remove(policy_list, policy); +static void add_default_bearer_types(GSList **list) +{ + unsigned int i; - remove_policy(policy); + for (i = 0; i < G_N_ELEMENTS(default_bearers); i++) + *list = g_slist_append(*list, + GINT_TO_POINTER(default_bearers[i])); } void connman_session_set_default_config(struct connman_session_config *config) @@ -425,8 +543,7 @@ void connman_session_set_default_config(struct connman_session_config *config) config->ecall = FALSE; g_slist_free(config->allowed_bearers); - config->allowed_bearers = g_slist_prepend(NULL, - GINT_TO_POINTER(CONNMAN_SERVICE_TYPE_UNKNOWN)); + add_default_bearer_types(&config->allowed_bearers); } struct connman_session_config *connman_session_create_default_config(void) @@ -463,6 +580,11 @@ int connman_session_parse_bearers(const char *token, GSList **list) if (g_strcmp0(token, "") == 0) return 0; + if (g_strcmp0(token, "*") == 0) { + add_default_bearer_types(list); + return 0; + } + err = bearer2service(token, &bearer); if (err < 0) return err; @@ -506,58 +628,40 @@ static int parse_bearers(DBusMessageIter *iter, GSList **list) return 0; } -static int filter_bearer(GSList *policy_bearers, +static void filter_bearer(GSList *policy_bearers, enum connman_service_type bearer, GSList **list) { enum connman_service_type policy; GSList *it; - if (policy_bearers == NULL) - return 0; + if (!policy_bearers) + return; - for (it = policy_bearers; it != NULL; it = it->next) { + for (it = policy_bearers; it; it = it->next) { policy = GPOINTER_TO_INT(it->data); - if (bearer == CONNMAN_SERVICE_TYPE_UNKNOWN) { - bearer = policy; - goto clone; - } - - if (policy != CONNMAN_SERVICE_TYPE_UNKNOWN && policy != bearer) + if (policy != bearer) continue; - goto clone; + *list = g_slist_append(*list, GINT_TO_POINTER(bearer)); + return; } - - *list = NULL; - - return 0; - -clone: - *list = g_slist_append(*list, GINT_TO_POINTER(bearer)); - - return 0; } -static int apply_policy_on_bearers(GSList *policy_bearers, GSList *bearers, +static void apply_policy_on_bearers(GSList *policy_bearers, GSList *bearers, GSList **list) { enum connman_service_type bearer; GSList *it; - int err; *list = NULL; - for (it = bearers; it != NULL; it = it->next) { + for (it = bearers; it; it = it->next) { bearer = GPOINTER_TO_INT(it->data); - err = filter_bearer(policy_bearers, bearer, list); - if (err < 0) - return err; + filter_bearer(policy_bearers, bearer, list); } - - return 0; } const char *connman_session_get_owner(struct connman_session *session) @@ -571,12 +675,12 @@ static void append_allowed_bearers(DBusMessageIter *iter, void *user_data) GSList *list; for (list = info->config.allowed_bearers; - list != NULL; list = list->next) { + list; list = list->next) { enum connman_service_type bearer = GPOINTER_TO_INT(list->data); const char *name = __connman_service_type2string(bearer); - if (name == NULL) - name = "*"; + if (!name) + name = ""; dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &name); @@ -588,16 +692,15 @@ static void append_ipconfig_ipv4(DBusMessageIter *iter, void *user_data) struct connman_service *service = user_data; struct connman_ipconfig *ipconfig_ipv4; - if (service == NULL) + if (!service) return; - if (__connman_service_is_connected_state(service, - CONNMAN_IPCONFIG_TYPE_IPV4) == FALSE) { + if (!__connman_service_is_connected_state(service, + CONNMAN_IPCONFIG_TYPE_IPV4)) return; - } ipconfig_ipv4 = __connman_service_get_ip4config(service); - if (ipconfig_ipv4 == NULL) + if (!ipconfig_ipv4) return; __connman_ipconfig_append_ipv4(ipconfig_ipv4, iter); @@ -608,17 +711,16 @@ static void append_ipconfig_ipv6(DBusMessageIter *iter, void *user_data) struct connman_service *service = user_data; struct connman_ipconfig *ipconfig_ipv4, *ipconfig_ipv6; - if (service == NULL) + if (!service) return; - if (__connman_service_is_connected_state(service, - CONNMAN_IPCONFIG_TYPE_IPV6) == FALSE) { + if (!__connman_service_is_connected_state(service, + CONNMAN_IPCONFIG_TYPE_IPV6)) return; - } ipconfig_ipv4 = __connman_service_get_ip4config(service); ipconfig_ipv6 = __connman_service_get_ip6config(service); - if (ipconfig_ipv6 == NULL) + if (!ipconfig_ipv6) return; __connman_ipconfig_append_ipv6(ipconfig_ipv6, iter, ipconfig_ipv4); @@ -630,10 +732,12 @@ static void append_notify(DBusMessageIter *dict, struct session_info *info = session->info; struct session_info *info_last = session->info_last; struct connman_service *service; - const char *name, *ifname, *bearer; + enum connman_service_type type; + const char *name, *bearer; + char *ifname; + int idx; - if (session->append_all == TRUE || - info->state != info_last->state) { + if (session->append_all || info->state != info_last->state) { const char *state = state2string(info->state); connman_dbus_dict_append_basic(dict, "State", @@ -642,18 +746,23 @@ static void append_notify(DBusMessageIter *dict, info_last->state = info->state; } - if (session->append_all == TRUE || - info->entry != info_last->entry) { - if (info->entry == NULL) { - name = ""; - ifname = ""; + if (session->append_all || session->service != session->service_last) { + if (session->service) { + service = session->service; + name = __connman_service_get_name(service); + idx = __connman_service_get_index(service); + + ifname = connman_inet_ifname(idx); + if (!ifname) + ifname = g_strdup(""); + + type = connman_service_get_type(service); + bearer = service2bearer(type); + } else { service = NULL; + name = ""; + ifname = g_strdup(""); bearer = ""; - } else { - name = info->entry->name; - ifname = info->entry->ifname; - service = info->entry->service; - bearer = info->entry->bearer; } connman_dbus_dict_append_basic(dict, "Name", @@ -676,10 +785,12 @@ static void append_notify(DBusMessageIter *dict, DBUS_TYPE_STRING, &bearer); - info_last->entry = info->entry; + g_free(ifname); + + session->service_last = session->service; } - if (session->append_all == TRUE || + if (session->append_all || info->config.type != info_last->config.type) { const char *type = type2string(info->config.type); @@ -689,7 +800,7 @@ static void append_notify(DBusMessageIter *dict, info_last->config.type = info->config.type; } - if (session->append_all == TRUE || + if (session->append_all || info->config.allowed_bearers != info_last->config.allowed_bearers) { connman_dbus_dict_append_array(dict, "AllowedBearers", DBUS_TYPE_STRING, @@ -698,53 +809,29 @@ static void append_notify(DBusMessageIter *dict, info_last->config.allowed_bearers = info->config.allowed_bearers; } - session->append_all = FALSE; + session->append_all = false; } -static connman_bool_t is_type_matching_state(enum connman_session_state *state, - enum connman_session_type type) -{ - switch (type) { - case CONNMAN_SESSION_TYPE_UNKNOWN: - return FALSE; - case CONNMAN_SESSION_TYPE_ANY: - return TRUE; - case CONNMAN_SESSION_TYPE_LOCAL: - if (*state >= CONNMAN_SESSION_STATE_CONNECTED) { - *state = CONNMAN_SESSION_STATE_CONNECTED; - return TRUE; - } - - break; - case CONNMAN_SESSION_TYPE_INTERNET: - if (*state == CONNMAN_SESSION_STATE_ONLINE) - return TRUE; - break; - } - - return FALSE; -} - -static connman_bool_t compute_notifiable_changes(struct connman_session *session) +static bool compute_notifiable_changes(struct connman_session *session) { struct session_info *info_last = session->info_last; struct session_info *info = session->info; - if (session->append_all == TRUE) - return TRUE; + if (session->append_all) + return true; if (info->state != info_last->state) - return TRUE; + return true; - if (info->entry != info_last->entry && + if (session->service != session->service_last && info->state >= CONNMAN_SESSION_STATE_CONNECTED) - return TRUE; + return true; if (info->config.allowed_bearers != info_last->config.allowed_bearers || info->config.type != info_last->config.type) - return TRUE; + return true; - return FALSE; + return false; } static gboolean session_notify(gpointer user_data) @@ -753,7 +840,7 @@ static gboolean session_notify(gpointer user_data) DBusMessage *msg; DBusMessageIter array, dict; - if (compute_notifiable_changes(session) == FALSE) + if (!compute_notifiable_changes(session)) return FALSE; DBG("session %p owner %s notify_path %s", session, @@ -762,7 +849,7 @@ static gboolean session_notify(gpointer user_data) msg = dbus_message_new_method_call(session->owner, session->notify_path, CONNMAN_NOTIFICATION_INTERFACE, "Update"); - if (msg == NULL) + if (!msg) return FALSE; dbus_message_iter_init_append(msg, &array); @@ -779,651 +866,16 @@ static gboolean session_notify(gpointer user_data) static void ipconfig_ipv4_changed(struct connman_session *session) { - struct session_info *info = session->info; - connman_dbus_setting_changed_dict(session->owner, session->notify_path, "IPv4", append_ipconfig_ipv4, - info->entry->service); + session->service); } static void ipconfig_ipv6_changed(struct connman_session *session) { - struct session_info *info = session->info; - connman_dbus_setting_changed_dict(session->owner, session->notify_path, "IPv6", append_ipconfig_ipv6, - info->entry->service); -} - -static connman_bool_t service_type_match(struct connman_session *session, - struct connman_service *service) -{ - struct session_info *info = session->info; - GSList *list; - - for (list = info->config.allowed_bearers; - list != NULL; list = list->next) { - enum connman_service_type bearer = GPOINTER_TO_INT(list->data); - enum connman_service_type service_type; - - if (bearer == CONNMAN_SERVICE_TYPE_UNKNOWN) - return TRUE; - - service_type = connman_service_get_type(service); - if (bearer == service_type) - return TRUE; - } - - return FALSE; -} - -static connman_bool_t service_match(struct connman_session *session, - struct connman_service *service) -{ - if (service_type_match(session, service) == FALSE) - return FALSE; - - return TRUE; -} - -static int service_type_weight(enum connman_service_type type) -{ - /* - * The session doesn't care which service - * to use. Nevertheless we have to sort them - * according their type. The ordering is - * - * 1. Ethernet - * 2. Bluetooth - * 3. WiFi - * 4. Cellular - */ - - switch (type) { - case CONNMAN_SERVICE_TYPE_ETHERNET: - return 4; - case CONNMAN_SERVICE_TYPE_BLUETOOTH: - return 3; - case CONNMAN_SERVICE_TYPE_WIFI: - return 2; - case CONNMAN_SERVICE_TYPE_CELLULAR: - return 1; - case CONNMAN_SERVICE_TYPE_UNKNOWN: - case CONNMAN_SERVICE_TYPE_SYSTEM: - case CONNMAN_SERVICE_TYPE_GPS: - case CONNMAN_SERVICE_TYPE_VPN: - case CONNMAN_SERVICE_TYPE_GADGET: - break; - } - - return 0; -} - -static gint sort_allowed_bearers(struct connman_service *service_a, - struct connman_service *service_b, - struct connman_session *session) -{ - struct session_info *info = session->info; - GSList *list; - enum connman_service_type type_a, type_b; - int weight_a, weight_b; - - type_a = connman_service_get_type(service_a); - type_b = connman_service_get_type(service_b); - - for (list = info->config.allowed_bearers; - list != NULL; list = list->next) { - enum connman_service_type bearer = GPOINTER_TO_INT(list->data); - - if (bearer == CONNMAN_SERVICE_TYPE_UNKNOWN) { - if (type_a != type_b) { - weight_a = service_type_weight(type_a); - weight_b = service_type_weight(type_b); - - if (weight_a > weight_b) - return -1; - - if (weight_a < weight_b) - return 1; - - return 0; - } - } - - if (type_a == bearer && type_b == bearer) - return 0; - - if (type_a == bearer && type_b != bearer) - return -1; - - if (type_a != bearer && type_b == bearer) - return 1; - } - - return 0; -} - -static gint sort_services(gconstpointer a, gconstpointer b, gpointer user_data) -{ - struct service_entry *entry_a = (void *)a; - struct service_entry *entry_b = (void *)b; - struct connman_session *session = user_data; - - return sort_allowed_bearers(entry_a->service, entry_b->service, - session); -} - -static enum connman_session_state service_to_session_state(enum connman_service_state state) -{ - switch (state) { - case CONNMAN_SERVICE_STATE_UNKNOWN: - case CONNMAN_SERVICE_STATE_IDLE: - case CONNMAN_SERVICE_STATE_ASSOCIATION: - case CONNMAN_SERVICE_STATE_CONFIGURATION: - case CONNMAN_SERVICE_STATE_DISCONNECT: - case CONNMAN_SERVICE_STATE_FAILURE: - break; - case CONNMAN_SERVICE_STATE_READY: - return CONNMAN_SESSION_STATE_CONNECTED; - case CONNMAN_SERVICE_STATE_ONLINE: - return CONNMAN_SESSION_STATE_ONLINE; - } - - return CONNMAN_SESSION_STATE_DISCONNECTED; -} - -static connman_bool_t is_connected(enum connman_service_state state) -{ - switch (state) { - case CONNMAN_SERVICE_STATE_UNKNOWN: - case CONNMAN_SERVICE_STATE_IDLE: - case CONNMAN_SERVICE_STATE_ASSOCIATION: - case CONNMAN_SERVICE_STATE_CONFIGURATION: - case CONNMAN_SERVICE_STATE_DISCONNECT: - case CONNMAN_SERVICE_STATE_FAILURE: - break; - case CONNMAN_SERVICE_STATE_READY: - case CONNMAN_SERVICE_STATE_ONLINE: - return TRUE; - } - - return FALSE; -} - -static connman_bool_t is_connecting(enum connman_service_state state) -{ - switch (state) { - case CONNMAN_SERVICE_STATE_UNKNOWN: - case CONNMAN_SERVICE_STATE_IDLE: - break; - case CONNMAN_SERVICE_STATE_ASSOCIATION: - case CONNMAN_SERVICE_STATE_CONFIGURATION: - return TRUE; - case CONNMAN_SERVICE_STATE_DISCONNECT: - case CONNMAN_SERVICE_STATE_FAILURE: - case CONNMAN_SERVICE_STATE_READY: - case CONNMAN_SERVICE_STATE_ONLINE: - break; - } - - return FALSE; -} - -static connman_bool_t explicit_connect(enum connman_session_reason reason) -{ - switch (reason) { - case CONNMAN_SESSION_REASON_UNKNOWN: - case CONNMAN_SESSION_REASON_FREE_RIDE: - break; - case CONNMAN_SESSION_REASON_CONNECT: - return TRUE; - } - - return FALSE; -} - -static connman_bool_t explicit_disconnect(struct session_info *info) -{ - if (info->entry == NULL) - return FALSE; - - DBG("reason %s service %p state %d", - reason2string(info->entry->reason), - info->entry->service, info->entry->state); - - if (info->entry->reason == CONNMAN_SESSION_REASON_UNKNOWN) - return FALSE; - - if (explicit_connect(info->entry->reason) == FALSE) - return FALSE; - - if (__connman_service_session_dec(info->entry->service) == FALSE) - return FALSE; - - return TRUE; -} - -struct pending_data { - unsigned int timeout; - struct service_entry *entry; - gboolean (*cb)(gpointer); -}; - -static void pending_timeout_free(gpointer data, gpointer user_data) -{ - struct pending_data *pending = data; - - DBG("pending %p timeout %d", pending, pending->timeout); - g_source_remove(pending->timeout); - g_free(pending); -} - -static void pending_timeout_remove_all(struct service_entry *entry) -{ - DBG(""); - - g_slist_foreach(entry->pending_timeouts, pending_timeout_free, NULL); - g_slist_free(entry->pending_timeouts); - entry->pending_timeouts = NULL; -} - -static gboolean pending_timeout_cb(gpointer data) -{ - struct pending_data *pending = data; - struct service_entry *entry = pending->entry; - gboolean ret; - - DBG("pending %p timeout %d", pending, pending->timeout); - - ret = pending->cb(pending->entry); - if (ret == FALSE) { - entry->pending_timeouts = - g_slist_remove(entry->pending_timeouts, - pending); - g_free(pending); - } - return ret; -} - -static connman_bool_t pending_timeout_add(unsigned int seconds, - gboolean (*cb)(gpointer), - struct service_entry *entry) -{ - struct pending_data *pending = g_try_new0(struct pending_data, 1); - - if (pending == NULL || cb == NULL || entry == NULL) { - g_free(pending); - return FALSE; - } - - pending->cb = cb; - pending->entry = entry; - pending->timeout = g_timeout_add_seconds(seconds, pending_timeout_cb, - pending); - entry->pending_timeouts = g_slist_prepend(entry->pending_timeouts, - pending); - - DBG("pending %p entry %p timeout id %d", pending, entry, - pending->timeout); - - return TRUE; -} - -static gboolean call_disconnect(gpointer user_data) -{ - struct service_entry *entry = user_data; - struct connman_service *service = entry->service; - - /* - * TODO: We should mark this entry as pending work. In case - * disconnect fails we just unassign this session from the - * service and can't do anything later on it - */ - DBG("disconnect service %p", service); - __connman_service_disconnect(service); - - return FALSE; -} - -static gboolean call_connect(gpointer user_data) -{ - struct service_entry *entry = user_data; - struct connman_service *service = entry->service; - - DBG("connect service %p", service); - __connman_service_connect(service); - - return FALSE; -} - -static void deselect_service(struct session_info *info) -{ - struct service_entry *entry; - connman_bool_t disconnect, connected; - - DBG(""); - - if (info->entry == NULL) - return; - - disconnect = explicit_disconnect(info); - - connected = is_connecting(info->entry->state) == TRUE || - is_connected(info->entry->state) == TRUE; - - info->state = CONNMAN_SESSION_STATE_DISCONNECTED; - info->entry->reason = CONNMAN_SESSION_REASON_UNKNOWN; - - entry = info->entry; - info->entry = NULL; - - DBG("disconnect %d connected %d", disconnect, connected); - - if (disconnect == TRUE && connected == TRUE) - pending_timeout_add(0, call_disconnect, entry); -} - -static void deselect_and_disconnect(struct connman_session *session) -{ - struct session_info *info = session->info; - - deselect_service(info); - - info->reason = CONNMAN_SESSION_REASON_FREE_RIDE; -} - -static void select_connected_service(struct session_info *info, - struct service_entry *entry) -{ - enum connman_session_state state; - - state = service_to_session_state(entry->state); - if (is_type_matching_state(&state, info->config.type) == FALSE) - return; - - info->state = state; - - info->entry = entry; - info->entry->reason = info->reason; - - if (explicit_connect(info->reason) == FALSE) - return; - - __connman_service_session_inc(info->entry->service); -} - -static void select_offline_service(struct session_info *info, - struct service_entry *entry) -{ - if (explicit_connect(info->reason) == FALSE) - return; - - info->state = service_to_session_state(entry->state); - - info->entry = entry; - info->entry->reason = info->reason; - - __connman_service_session_inc(info->entry->service); - pending_timeout_add(0, call_connect, entry); -} - -static void select_service(struct session_info *info, - struct service_entry *entry) -{ - DBG("service %p", entry->service); - - if (is_connected(entry->state) == TRUE) - select_connected_service(info, entry); - else - select_offline_service(info, entry); -} - -static void select_and_connect(struct connman_session *session, - enum connman_session_reason reason) -{ - struct session_info *info = session->info; - struct service_entry *entry = NULL; - GList *list; - - DBG("session %p reason %s", session, reason2string(reason)); - - info->reason = reason; - - for (list = session->service_list; list != NULL; list = list->next) { - entry = list->data; - - switch (entry->state) { - case CONNMAN_SERVICE_STATE_ASSOCIATION: - case CONNMAN_SERVICE_STATE_CONFIGURATION: - case CONNMAN_SERVICE_STATE_READY: - case CONNMAN_SERVICE_STATE_ONLINE: - case CONNMAN_SERVICE_STATE_IDLE: - case CONNMAN_SERVICE_STATE_DISCONNECT: - select_service(info, entry); - return; - case CONNMAN_SERVICE_STATE_UNKNOWN: - case CONNMAN_SERVICE_STATE_FAILURE: - break; - } - } -} - -static struct service_entry *create_service_entry(struct connman_session * session, - struct connman_service *service, - const char *name, - enum connman_service_state state) -{ - struct service_entry *entry; - enum connman_service_type type; - int idx; - - entry = g_try_new0(struct service_entry, 1); - if (entry == NULL) - return entry; - - entry->reason = CONNMAN_SESSION_REASON_UNKNOWN; - entry->state = state; - if (name != NULL) - entry->name = name; - else - entry->name = ""; - entry->service = service; - - idx = __connman_service_get_index(entry->service); - entry->ifname = connman_inet_ifname(idx); - if (entry->ifname == NULL) - entry->ifname = g_strdup(""); - - type = connman_service_get_type(entry->service); - entry->bearer = service2bearer(type); - - entry->session = session; - - return entry; -} - -static void iterate_service_cb(struct connman_service *service, - const char *name, - enum connman_service_state state, - void *user_data) -{ - struct connman_session *session = user_data; - struct service_entry *entry; - - if (service_match(session, service) == FALSE) - return; - - entry = create_service_entry(session, service, name, state); - if (entry == NULL) - return; - - g_hash_table_replace(session->service_hash, service, entry); -} - -static void destroy_service_entry(gpointer data) -{ - struct service_entry *entry = data; - struct session_info *info = entry->session->info; - struct connman_session *session; - - if (info != NULL && info->entry == entry) { - session = entry->session; - deselect_and_disconnect(session); - } - - pending_timeout_remove_all(entry); - g_free(entry->ifname); - - g_free(entry); -} - -static void populate_service_list(struct connman_session *session) -{ - GHashTableIter iter; - gpointer key, value; - - session->service_hash = - g_hash_table_new_full(g_direct_hash, g_direct_equal, - NULL, destroy_service_entry); - __connman_service_iterate_services(iterate_service_cb, session); - - g_hash_table_iter_init(&iter, session->service_hash); - - while (g_hash_table_iter_next(&iter, &key, &value) == TRUE) { - struct service_entry *entry = value; - - DBG("service %p type %s name %s", entry->service, - service2bearer(connman_service_get_type(entry->service)), - entry->name); - session->service_list = g_list_prepend(session->service_list, - entry); - } - - session->service_list = g_list_sort_with_data(session->service_list, - sort_services, session); -} - -static void session_changed(struct connman_session *session, - enum connman_session_trigger trigger) -{ - struct session_info *info = session->info; - struct session_info *info_last = session->info_last; - struct connman_service *service; - struct service_entry *entry = NULL, *entry_last = NULL; - GHashTable *service_hash_last; - - /* - * TODO: This only a placeholder for the 'real' algorithm to - * play a bit around. So we are going to improve it step by step. - */ - - DBG("session %p trigger %s reason %s", session, trigger2string(trigger), - reason2string(info->reason)); - - if (info->entry != NULL) { - enum connman_session_state state; - - state = service_to_session_state(info->entry->state); - - if (is_type_matching_state(&state, info->config.type) == TRUE) - info->state = state; - } - - switch (trigger) { - case CONNMAN_SESSION_TRIGGER_UNKNOWN: - DBG("ignore session changed event"); - return; - case CONNMAN_SESSION_TRIGGER_SETTING: - if (info->config.allowed_bearers != info_last->config.allowed_bearers) { - - service_hash_last = session->service_hash; - g_list_free(session->service_list); - session->service_list = NULL; - - if (info->entry != NULL) - service = info->entry->service; - else - service = NULL; - - populate_service_list(session); - - if (info->entry != NULL) { - entry_last = g_hash_table_lookup( - service_hash_last, - info->entry->service); - entry = g_hash_table_lookup( - session->service_hash, - service); - } - - if (entry == NULL && entry_last != NULL) { - /* - * The currently selected service is - * not part of this session anymore. - */ - deselect_and_disconnect(session); - } - - g_hash_table_destroy(service_hash_last); - } - - if (info->config.type != info_last->config.type) { - if (info->state >= CONNMAN_SESSION_STATE_CONNECTED && - is_type_matching_state(&info->state, - info->config.type) == FALSE) - deselect_and_disconnect(session); - } - - if (info->state == CONNMAN_SESSION_STATE_DISCONNECTED) { - select_and_connect(session, - CONNMAN_SESSION_REASON_FREE_RIDE); - } - - break; - case CONNMAN_SESSION_TRIGGER_ECALL: - /* - * For the time beeing we fallback to normal connect - * strategy. - */ - case CONNMAN_SESSION_TRIGGER_CONNECT: - if (info->state >= CONNMAN_SESSION_STATE_CONNECTED) { - if (info->entry->reason == CONNMAN_SESSION_REASON_CONNECT) - break; - info->entry->reason = CONNMAN_SESSION_REASON_CONNECT; - __connman_service_session_inc(info->entry->service); - break; - } - - if (info->entry != NULL && - is_connecting(info->entry->state) == TRUE) { - break; - } - - select_and_connect(session, - CONNMAN_SESSION_REASON_CONNECT); - - break; - case CONNMAN_SESSION_TRIGGER_DISCONNECT: - deselect_and_disconnect(session); - - break; - case CONNMAN_SESSION_TRIGGER_SERVICE: - if (info->entry != NULL && - (is_connecting(info->entry->state) == TRUE || - is_connected(info->entry->state) == TRUE)) { - break; - } - - deselect_and_disconnect(session); - - if (info->reason == CONNMAN_SESSION_REASON_FREE_RIDE) { - select_and_connect(session, info->reason); - } - - break; - } - - session_notify(session); + session->service); } int connman_session_config_update(struct connman_session *session) @@ -1439,16 +891,33 @@ int connman_session_config_update(struct connman_session *session) * might have changed. We can still optimize this later. */ - err = apply_policy_on_bearers( + if (session->id_type != session->policy_config->id_type) { + cleanup_firewall_session(session); + err = init_firewall_session(session); + if (err < 0) { + connman_session_destroy(session); + return err; + } + + session->id_type = session->policy_config->id_type; + } + + apply_policy_on_bearers( session->policy_config->allowed_bearers, session->user_allowed_bearers, &allowed_bearers); - if (err < 0) - return err; + + if (session->active) + set_active_session(session, false); + + session->active = false; + session_deactivate(session); g_slist_free(info->config.allowed_bearers); info->config.allowed_bearers = allowed_bearers; + session_activate(session); + info->config.type = apply_policy_on_type( session->policy_config->type, info->config.type); @@ -1456,12 +925,12 @@ int connman_session_config_update(struct connman_session *session) info->config.roaming_policy = session->policy_config->roaming_policy; info->config.ecall = session->policy_config->ecall; - if (info->config.ecall == TRUE) + if (info->config.ecall) ecall_session = session; info->config.priority = session->policy_config->priority; - session_changed(session, CONNMAN_SESSION_TRIGGER_SETTING); + session_notify(session); return 0; } @@ -1473,14 +942,21 @@ static DBusMessage *connect_session(DBusConnection *conn, DBG("session %p", session); - if (ecall_session != NULL) { - if (ecall_session->ecall == TRUE && ecall_session != session) + if (ecall_session) { + if (ecall_session->ecall && ecall_session != session) return __connman_error_failed(msg, EBUSY); - session->ecall = TRUE; - session_changed(session, CONNMAN_SESSION_TRIGGER_ECALL); - } else - session_changed(session, CONNMAN_SESSION_TRIGGER_CONNECT); + session->ecall = true; + } + + if (!session->active) { + session->active = true; + set_active_session(session, true); + } + + session_activate(session); + + __connman_service_auto_connect(CONNMAN_SERVICE_CONNECT_REASON_SESSION); return g_dbus_create_reply(msg, DBUS_TYPE_INVALID); } @@ -1492,14 +968,20 @@ static DBusMessage *disconnect_session(DBusConnection *conn, DBG("session %p", session); - if (ecall_session != NULL) { - if (ecall_session->ecall == TRUE && ecall_session != session) + if (ecall_session) { + if (ecall_session->ecall && ecall_session != session) return __connman_error_failed(msg, EBUSY); - session->ecall = FALSE; + session->ecall = false; } - session_changed(session, CONNMAN_SESSION_TRIGGER_DISCONNECT); + if (session->active) { + session->active = false; + set_active_session(session, false); + } + + session_deactivate(session); + update_session_state(session); return g_dbus_create_reply(msg, DBUS_TYPE_INVALID); } @@ -1516,7 +998,7 @@ static DBusMessage *change_session(DBusConnection *conn, int err; DBG("session %p", session); - if (dbus_message_iter_init(msg, &iter) == FALSE) + if (!dbus_message_iter_init(msg, &iter)) return __connman_error_invalid_arguments(msg); if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING) @@ -1532,27 +1014,32 @@ static DBusMessage *change_session(DBusConnection *conn, switch (dbus_message_iter_get_arg_type(&value)) { case DBUS_TYPE_ARRAY: - if (g_str_equal(name, "AllowedBearers") == TRUE) { + if (g_str_equal(name, "AllowedBearers")) { err = parse_bearers(&value, &allowed_bearers); if (err < 0) - return __connman_error_failed(msg, err); + return __connman_error_failed(msg, -err); + + if (session->active) + set_active_session(session, false); + + session->active = false; + session_deactivate(session); g_slist_free(info->config.allowed_bearers); session->user_allowed_bearers = allowed_bearers; - err = apply_policy_on_bearers( + apply_policy_on_bearers( session->policy_config->allowed_bearers, session->user_allowed_bearers, &info->config.allowed_bearers); - if (err < 0) - return __connman_error_failed(msg, err); + session_activate(session); } else { goto err; } break; case DBUS_TYPE_STRING: - if (g_str_equal(name, "ConnectionType") == TRUE) { + if (g_str_equal(name, "ConnectionType")) { dbus_message_iter_get_basic(&value, &val); info->config.type = apply_policy_on_type( session->policy_config->type, @@ -1565,7 +1052,7 @@ static DBusMessage *change_session(DBusConnection *conn, goto err; } - session_changed(session, CONNMAN_SESSION_TRIGGER_SETTING); + session_notify(session); return g_dbus_create_reply(msg, DBUS_TYPE_INVALID); @@ -1590,7 +1077,7 @@ static void release_session(gpointer key, gpointer value, gpointer user_data) session->notify_path, CONNMAN_NOTIFICATION_INTERFACE, "Release"); - if (message == NULL) + if (!message) return; dbus_message_set_no_reply(message, TRUE); @@ -1608,8 +1095,6 @@ static int session_disconnect(struct connman_session *session) g_dbus_unregister_interface(connection, session->session_path, CONNMAN_SESSION_INTERFACE); - deselect_and_disconnect(session); - g_hash_table_remove(session_hash, session->session_path); return 0; @@ -1631,7 +1116,7 @@ static DBusMessage *destroy_session(DBusConnection *conn, DBG("session %p", session); - if (ecall_session != NULL && ecall_session != session) + if (ecall_session && ecall_session != session) return __connman_error_failed(msg, EBUSY); session_disconnect(session); @@ -1650,86 +1135,93 @@ static const GDBusMethodTable session_methods[] = { { }, }; -static int session_create_cb(struct connman_session *session, +static int session_policy_config_cb(struct connman_session *session, struct connman_session_config *config, void *user_data, int err) { - DBusMessage *reply; - struct user_config *user_config = user_data; + struct creation_data *creation_data = user_data; struct session_info *info, *info_last; + DBusMessage *reply; DBG("session %p config %p", session, config); - if (err != 0) - goto out; + if (err < 0) + goto err; session->policy_config = config; + session->mark = session_mark++; + session->index = -1; + + err = init_firewall_session(session); + if (err < 0) + goto err; + + err = init_routing_table(session); + if (err < 0) + goto err; + info = session->info; info_last = session->info_last; - if (session->policy_config->ecall == TRUE) + if (session->policy_config->ecall) ecall_session = session; info->state = CONNMAN_SESSION_STATE_DISCONNECTED; info->config.type = apply_policy_on_type( session->policy_config->type, - user_config->type); + creation_data->type); info->config.priority = session->policy_config->priority; info->config.roaming_policy = session->policy_config->roaming_policy; - info->entry = NULL; - session->user_allowed_bearers = user_config->allowed_bearers; - user_config->allowed_bearers = NULL; + session->user_allowed_bearers = creation_data->allowed_bearers; + creation_data->allowed_bearers = NULL; - err = apply_policy_on_bearers( + apply_policy_on_bearers( session->policy_config->allowed_bearers, session->user_allowed_bearers, &info->config.allowed_bearers); - if (err < 0) - goto out; g_hash_table_replace(session_hash, session->session_path, session); DBG("add %s", session->session_path); - if (g_dbus_register_interface(connection, session->session_path, + if (!g_dbus_register_interface(connection, session->session_path, CONNMAN_SESSION_INTERFACE, - session_methods, NULL, - NULL, session, NULL) == FALSE) { + session_methods, NULL, NULL, + session, NULL)) { connman_error("Failed to register %s", session->session_path); g_hash_table_remove(session_hash, session->session_path); err = -EINVAL; - goto out; + goto err; } - reply = g_dbus_create_reply(user_config->pending, + reply = g_dbus_create_reply(creation_data->pending, DBUS_TYPE_OBJECT_PATH, &session->session_path, DBUS_TYPE_INVALID); g_dbus_send_message(connection, reply); - user_config->pending = NULL; - - populate_service_list(session); + creation_data->pending = NULL; info_last->state = info->state; info_last->config.priority = info->config.priority; info_last->config.roaming_policy = info->config.roaming_policy; - info_last->entry = info->entry; info_last->config.allowed_bearers = info->config.allowed_bearers; - session->append_all = TRUE; + session->append_all = true; - session_changed(session, CONNMAN_SESSION_TRIGGER_SETTING); + cleanup_creation_data(creation_data); -out: - if (err < 0) { - reply = __connman_error_failed(user_config->pending, -err); - g_dbus_send_message(connection, reply); + session_activate(session); - free_session(session); - } + return 0; + +err: + reply = __connman_error_failed(creation_data->pending, -err); + g_dbus_send_message(connection, reply); + creation_data->pending = NULL; - cleanup_user_config(user_config); + cleanup_session(session); + cleanup_creation_data(creation_data); return err; } @@ -1740,16 +1232,17 @@ int __connman_session_create(DBusMessage *msg) char *session_path = NULL; DBusMessageIter iter, array; struct connman_session *session = NULL; - struct user_config *user_config = NULL; - connman_bool_t user_allowed_bearers = FALSE; - connman_bool_t user_connection_type = FALSE; - int err; + struct creation_data *creation_data = NULL; + bool user_allowed_bearers = false; + bool user_connection_type = false; + int err, i; + char *str; owner = dbus_message_get_sender(msg); DBG("owner %s", owner); - if (ecall_session != NULL && ecall_session->ecall == TRUE) { + if (ecall_session && ecall_session->ecall) { /* * If there is an emergency call already going on, * ignore session creation attempt @@ -1758,13 +1251,13 @@ int __connman_session_create(DBusMessage *msg) goto err; } - user_config = g_try_new0(struct user_config, 1); - if (user_config == NULL) { + creation_data = g_try_new0(struct creation_data, 1); + if (!creation_data) { err = -ENOMEM; goto err; } - user_config->pending = dbus_message_ref(msg); + creation_data->pending = dbus_message_ref(msg); dbus_message_iter_init(msg, &iter); dbus_message_iter_recurse(&iter, &array); @@ -1781,25 +1274,25 @@ int __connman_session_create(DBusMessage *msg) switch (dbus_message_iter_get_arg_type(&value)) { case DBUS_TYPE_ARRAY: - if (g_str_equal(key, "AllowedBearers") == TRUE) { + if (g_str_equal(key, "AllowedBearers")) { err = parse_bearers(&value, - &user_config->allowed_bearers); + &creation_data->allowed_bearers); if (err < 0) goto err; - user_allowed_bearers = TRUE; + user_allowed_bearers = true; } else { err = -EINVAL; goto err; } break; case DBUS_TYPE_STRING: - if (g_str_equal(key, "ConnectionType") == TRUE) { + if (g_str_equal(key, "ConnectionType")) { dbus_message_iter_get_basic(&value, &val); - user_config->type = + creation_data->type = connman_session_parse_connection_type(val); - user_connection_type = TRUE; + user_connection_type = true; } else { err = -EINVAL; goto err; @@ -1814,36 +1307,40 @@ int __connman_session_create(DBusMessage *msg) * * For AllowedBearers this is '*', ... */ - if (user_allowed_bearers == FALSE) { - user_config->allowed_bearers = - g_slist_append(NULL, - GINT_TO_POINTER(CONNMAN_SERVICE_TYPE_UNKNOWN)); - if (user_config->allowed_bearers == NULL) { + if (!user_allowed_bearers) { + add_default_bearer_types(&creation_data->allowed_bearers); + if (!creation_data->allowed_bearers) { err = -ENOMEM; goto err; } } /* ... and for ConnectionType it is 'any'. */ - if (user_connection_type == FALSE) - user_config->type = CONNMAN_SESSION_TYPE_ANY; + if (!user_connection_type) + creation_data->type = CONNMAN_SESSION_TYPE_ANY; dbus_message_iter_next(&iter); dbus_message_iter_get_basic(&iter, ¬ify_path); - if (notify_path == NULL) { + if (!notify_path) { err = -EINVAL; goto err; } - session_path = g_strdup_printf("/sessions%s", notify_path); - if (session_path == NULL) { + str = g_strdup(owner); + for (i = 0; str[i] != '\0'; i++) + if (str[i] == ':' || str[i] == '.') + str[i] = '_'; + session_path = g_strdup_printf("/sessions/%s%s", str, notify_path); + g_free(str); + + if (!session_path) { err = -ENOMEM; goto err; } session = g_hash_table_lookup(session_hash, session_path); - if (session != NULL) { + if (session) { g_free(session_path); session = NULL; err = -EEXIST; @@ -1851,22 +1348,23 @@ int __connman_session_create(DBusMessage *msg) } session = g_try_new0(struct connman_session, 1); - if (session == NULL) { + if (!session) { g_free(session_path); err = -ENOMEM; goto err; } + creation_data->session = session; session->session_path = session_path; session->info = g_try_new0(struct session_info, 1); - if (session->info == NULL) { + if (!session->info) { err = -ENOMEM; goto err; } session->info_last = g_try_new0(struct session_info, 1); - if (session->info_last == NULL) { + if (!session->info_last) { err = -ENOMEM; goto err; } @@ -1877,11 +1375,8 @@ int __connman_session_create(DBusMessage *msg) g_dbus_add_disconnect_watch(connection, session->owner, owner_disconnect, session, NULL); - err = assign_policy_plugin(session); - if (err < 0) - goto err; - - err = create_policy_config(session, session_create_cb, user_config); + err = create_policy_config(session, session_policy_config_cb, + creation_data); if (err < 0 && err != -EINPROGRESS) return err; @@ -1892,10 +1387,18 @@ err: free_session(session); - cleanup_user_config(user_config); + cleanup_creation_data(creation_data); return err; } +bool __connman_session_policy_autoconnect(enum connman_service_connect_reason reason) +{ + if (!policy || !policy->autoconnect) + return true; + + return policy->autoconnect(reason); +} + void connman_session_destroy(struct connman_session *session) { DBG("session %p", session); @@ -1914,11 +1417,11 @@ int __connman_session_destroy(DBusMessage *msg) dbus_message_get_args(msg, NULL, DBUS_TYPE_OBJECT_PATH, &session_path, DBUS_TYPE_INVALID); - if (session_path == NULL) + if (!session_path) return -EINVAL; session = g_hash_table_lookup(session_hash, session_path); - if (session == NULL) + if (!session) return -EINVAL; if (g_strcmp0(owner, session->owner) != 0) @@ -1929,111 +1432,241 @@ int __connman_session_destroy(DBusMessage *msg) return 0; } -connman_bool_t __connman_session_mode() +int connman_session_connect(struct connman_service *service) { - return sessionmode; + DBG("service %p name %s", service, __connman_service_get_name(service)); + + return __connman_service_connect(service, + CONNMAN_SERVICE_CONNECT_REASON_SESSION); } -void __connman_session_set_mode(connman_bool_t enable) +int connman_session_disconnect(struct connman_service *service) { - DBG("enable %d", enable); + DBG("service %p", service); - if (sessionmode != enable) { - sessionmode = enable; + return __connman_service_disconnect(service); +} - connman_dbus_property_changed_basic(CONNMAN_MANAGER_PATH, - CONNMAN_MANAGER_INTERFACE, "SessionMode", - DBUS_TYPE_BOOLEAN, &sessionmode); +static enum connman_session_state service_to_session_state( + enum connman_service_state state) +{ + switch (state) { + case CONNMAN_SERVICE_STATE_UNKNOWN: + case CONNMAN_SERVICE_STATE_IDLE: + case CONNMAN_SERVICE_STATE_ASSOCIATION: + case CONNMAN_SERVICE_STATE_CONFIGURATION: + case CONNMAN_SERVICE_STATE_DISCONNECT: + case CONNMAN_SERVICE_STATE_FAILURE: + break; + case CONNMAN_SERVICE_STATE_READY: + return CONNMAN_SESSION_STATE_CONNECTED; + case CONNMAN_SERVICE_STATE_ONLINE: + return CONNMAN_SESSION_STATE_ONLINE; } - if (sessionmode == TRUE) - __connman_service_disconnect_all(); + return CONNMAN_SESSION_STATE_DISCONNECTED; } -static void service_add(struct connman_service *service, - const char *name) +static void update_session_state(struct connman_session *session) { - GHashTableIter iter; - gpointer key, value; - struct connman_session *session; - struct service_entry *entry; + enum connman_service_state service_state; + enum connman_session_state state = CONNMAN_SESSION_STATE_DISCONNECTED; - DBG("service %p", service); + if (session->service) { + service_state = __connman_service_get_state(session->service); + state = service_to_session_state(service_state); + session->info->state = state; + } + session->info->state = state; - g_hash_table_iter_init(&iter, session_hash); + DBG("session %p state %s", session, state2string(state)); - while (g_hash_table_iter_next(&iter, &key, &value) == TRUE) { - session = value; - - if (service_match(session, service) == FALSE) - continue; + update_routing_table(session); + session_notify(session); +} - entry = create_service_entry(session, service, name, - CONNMAN_SERVICE_STATE_IDLE); - if (entry == NULL) - continue; +static bool session_match_service(struct connman_session *session, + struct connman_service *service) +{ + enum connman_service_type bearer_type; + enum connman_service_type service_type; + GSList *list; - session->service_list = g_list_insert_sorted_with_data( - session->service_list, entry, sort_services, session); + if (policy && policy->allowed) + return policy->allowed(session, service); - g_hash_table_replace(session->service_hash, service, entry); + for (list = session->info->config.allowed_bearers; list; list = list->next) { + bearer_type = GPOINTER_TO_INT(list->data); + service_type = connman_service_get_type(service); - session_changed(session, CONNMAN_SESSION_TRIGGER_SERVICE); + if (bearer_type == service_type) + return true; } + + return false; } -static void service_remove(struct connman_service *service) +static bool is_session_connected(struct connman_session *session, + enum connman_service_state state) + { + switch (state) { + case CONNMAN_SERVICE_STATE_UNKNOWN: + case CONNMAN_SERVICE_STATE_IDLE: + case CONNMAN_SERVICE_STATE_ASSOCIATION: + case CONNMAN_SERVICE_STATE_CONFIGURATION: + case CONNMAN_SERVICE_STATE_DISCONNECT: + case CONNMAN_SERVICE_STATE_FAILURE: + break; + case CONNMAN_SERVICE_STATE_READY: + if (session->info->config.type == CONNMAN_SESSION_TYPE_INTERNET) + return false; + case CONNMAN_SERVICE_STATE_ONLINE: + return true; + } + return false; +} + +static void session_activate(struct connman_session *session) +{ GHashTableIter iter; gpointer key, value; - struct connman_session *session; - struct session_info *info; - DBG("service %p", service); + if (!service_hash) + return; + + g_hash_table_iter_init(&iter, service_hash); + while (g_hash_table_iter_next(&iter, &key, &value)) { + struct connman_service_info *info = value; + enum connman_service_state state; + + state = __connman_service_get_state(info->service); + + if (is_session_connected(session, state) && + session_match_service(session, info->service)) { + DBG("session %p add service %p", session, info->service); + + info->sessions = g_slist_prepend(info->sessions, + session); + session->service = info->service; + update_session_state(session); + + return; + } + } + + session_notify(session); +} + +static void session_deactivate(struct connman_session *session) +{ + struct connman_service_info *info; + + if (!service_hash) + return; + + if (!session->service) + return; + + info = g_hash_table_lookup(service_hash, session->service); + if (!info) + return; + + info->sessions = g_slist_remove(info->sessions, session); + session->service = NULL; + + session->info->state = CONNMAN_SESSION_STATE_DISCONNECTED; +} + +static void handle_service_state_online(struct connman_service *service, + enum connman_service_state state, + struct connman_service_info *info) +{ + GHashTableIter iter; + gpointer key, value; g_hash_table_iter_init(&iter, session_hash); + while (g_hash_table_iter_next(&iter, &key, &value)) { + struct connman_session *session = value; + bool connected; - while (g_hash_table_iter_next(&iter, &key, &value) == TRUE) { - struct service_entry *entry; - session = value; - info = session->info; + connected = is_session_connected(session, state); - entry = g_hash_table_lookup(session->service_hash, service); - if (entry == NULL) - continue; + if (session->service == service) { + if (!connected) { + DBG("session %p remove service %p", session, service); + info->sessions = g_slist_remove(info->sessions, + session); + session->service = NULL; + update_session_state(session); + } + } else if (connected && session_match_service(session, service)) { + DBG("session %p add service %p", session, service); - session->service_list = g_list_remove(session->service_list, - entry); + info->sessions = g_slist_prepend(info->sessions, + session); + session->service = service; + update_session_state(session); + } + } +} + +static void handle_service_state_offline(struct connman_service *service, + struct connman_service_info *info) +{ + GSList *list; - g_hash_table_remove(session->service_hash, service); + for (list = info->sessions; list; list = list->next) { + struct connman_session *session = list->data; - if (info->entry != NULL && info->entry->service == service) - info->entry = NULL; - session_changed(session, CONNMAN_SESSION_TRIGGER_SERVICE); + if (session->service != service) { + connman_warn("session %p should have session %p assigned", + session, service); + continue; + } + + DBG("session %p remove service %p", session, service); + + session->service = NULL; + update_session_state(session); } } + static void service_state_changed(struct connman_service *service, - enum connman_service_state state) + enum connman_service_state state) { - GHashTableIter iter; - gpointer key, value; + struct connman_service_info *info; DBG("service %p state %d", service, state); - g_hash_table_iter_init(&iter, session_hash); + info = g_hash_table_lookup(service_hash, service); - while (g_hash_table_iter_next(&iter, &key, &value) == TRUE) { - struct connman_session *session = value; - struct service_entry *entry; + switch (state) { + case CONNMAN_SERVICE_STATE_UNKNOWN: + case CONNMAN_SERVICE_STATE_IDLE: + case CONNMAN_SERVICE_STATE_ASSOCIATION: + case CONNMAN_SERVICE_STATE_CONFIGURATION: + case CONNMAN_SERVICE_STATE_FAILURE: + case CONNMAN_SERVICE_STATE_DISCONNECT: + if (!info) + return; + + handle_service_state_offline(service, info); - entry = g_hash_table_lookup(session->service_hash, service); - if (entry != NULL) - entry->state = state; + g_hash_table_remove(service_hash, service); - session_changed(session, - CONNMAN_SESSION_TRIGGER_SERVICE); + return; + case CONNMAN_SERVICE_STATE_READY: + case CONNMAN_SERVICE_STATE_ONLINE: + if (!info) { + info = g_new0(struct connman_service_info, 1); + g_hash_table_replace(service_hash, service, info); + } + + info->service = service; + handle_service_state_online(service, state, info); } } @@ -2052,14 +1685,16 @@ static void ipconfig_changed(struct connman_service *service, g_hash_table_iter_init(&iter, session_hash); - while (g_hash_table_iter_next(&iter, &key, &value) == TRUE) { + while (g_hash_table_iter_next(&iter, &key, &value)) { session = value; info = session->info; if (info->state == CONNMAN_SESSION_STATE_DISCONNECTED) continue; - if (info->entry != NULL && info->entry->service == service) { + if (session->service && session->service == service) { + update_routing_table(session); + if (type == CONNMAN_IPCONFIG_TYPE_IPV4) ipconfig_ipv4_changed(session); else if (type == CONNMAN_IPCONFIG_TYPE_IPV6) @@ -2070,8 +1705,6 @@ static void ipconfig_changed(struct connman_service *service, static struct connman_notifier session_notifier = { .name = "session", - .service_add = service_add, - .service_remove = service_remove, .service_state_changed = service_state_changed, .ipconfig_changed = ipconfig_changed, }; @@ -2083,7 +1716,7 @@ int __connman_session_init(void) DBG(""); connection = connman_dbus_get_connection(); - if (connection == NULL) + if (!connection) return -1; err = connman_notifier_register(&session_notifier); @@ -2095,7 +1728,14 @@ int __connman_session_init(void) session_hash = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, cleanup_session); - sessionmode = FALSE; + service_hash = g_hash_table_new_full(g_direct_hash, g_direct_equal, + NULL, cleanup_service); + if (__connman_firewall_is_up()) { + err = init_firewall(); + if (err < 0) + return err; + } + return 0; } @@ -2103,14 +1743,18 @@ void __connman_session_cleanup(void) { DBG(""); - if (connection == NULL) + if (!connection) return; + cleanup_firewall(); + connman_notifier_unregister(&session_notifier); g_hash_table_foreach(session_hash, release_session, NULL); g_hash_table_destroy(session_hash); session_hash = NULL; + g_hash_table_destroy(service_hash); + service_hash = NULL; dbus_connection_unref(connection); } diff --git a/src/shared/debugfs.c b/src/shared/debugfs.c deleted file mode 100644 index f522c518..00000000 --- a/src/shared/debugfs.c +++ /dev/null @@ -1,66 +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 <stdio.h> -#include <stdbool.h> -#include <string.h> -#include <limits.h> - -#include "src/shared/debugfs.h" - -#define STRINGIFY(x) STRINGIFY_ARG(x) -#define STRINGIFY_ARG(x) #x - -const char *debugfs_get_path(void) -{ - static char path[PATH_MAX + 1]; - static bool found = false; - char type[100]; - FILE *fp; - - if (found) - return path; - - fp = fopen("/proc/mounts", "r"); - if (!fp) - return NULL; - - while (fscanf(fp, "%*s %" STRINGIFY(PATH_MAX) "s %99s %*s %*d %*d\n", - path, type) == 2) { - if (!strcmp(type, "debugfs")) { - found = true; - break; - } - } - - fclose(fp); - - if (!found) - return NULL; - - return path; -} diff --git a/src/shared/debugfs.h b/src/shared/debugfs.h deleted file mode 100644 index 7f41ca7f..00000000 --- a/src/shared/debugfs.h +++ /dev/null @@ -1,24 +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 - * - */ - -const char *debugfs_get_path(void); diff --git a/src/shared/netlink.c b/src/shared/netlink.c new file mode 100644 index 00000000..d72294cc --- /dev/null +++ b/src/shared/netlink.c @@ -0,0 +1,666 @@ +/* + * + * Connection Manager + * + * Copyright (C) 2011-2012 Intel Corporation. All rights reserved. + * Copyright (C) 2013 BWM CarIT GmbH. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser 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 + * + */ + +/* + * This file is a copy from ELL which has been ported to use GLib's + * data structures. + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <string.h> +#include <unistd.h> +#include <sys/socket.h> +#include <linux/netlink.h> + +#include <gdbus.h> + +#include "src/shared/util.h" +#include "src/shared/netlink.h" + +#ifndef SOL_NETLINK +#define SOL_NETLINK 270 +#endif + +struct command { + unsigned int id; + uint32_t seq; + uint32_t len; + netlink_command_func_t handler; + netlink_destroy_func_t destroy; + void *user_data; +}; + +struct notify { + uint32_t group; + netlink_notify_func_t handler; + netlink_destroy_func_t destroy; + void *user_data; +}; + +struct netlink_info { + uint32_t pid; + GIOChannel *channel; + uint32_t next_seq; + GQueue *command_queue; + GHashTable *command_pending; + GHashTable *command_lookup; + unsigned int next_command_id; + GHashTable *notify_groups; + GHashTable *notify_lookup; + unsigned int next_notify_id; + netlink_debug_func_t debug_handler; + netlink_destroy_func_t debug_destroy; + void *debug_data; +}; + + +static void destroy_command(struct command *command) +{ + if (command->destroy) + command->destroy(command->user_data); + + g_free(command); +} + +static void destroy_notify(struct notify *notify) +{ + if (notify->destroy) + notify->destroy(notify->user_data); + + g_free(notify); +} + +static gboolean can_write_data(GIOChannel *chan, + GIOCondition cond, gpointer user_data) +{ + struct netlink_info *netlink = user_data; + struct command *command; + struct sockaddr_nl addr; + const void *data; + ssize_t written; + int sk; + + command = g_queue_pop_head(netlink->command_queue); + if (!command) + return FALSE; + + sk = g_io_channel_unix_get_fd(chan); + + memset(&addr, 0, sizeof(addr)); + addr.nl_family = AF_NETLINK; + addr.nl_pid = 0; + + data = ((void *) command) + NLMSG_ALIGN(sizeof(struct command)); + + written = sendto(sk, data, command->len, 0, + (struct sockaddr *) &addr, sizeof(addr)); + if (written < 0 || (uint32_t) written != command->len) { + g_hash_table_remove(netlink->command_lookup, + GUINT_TO_POINTER(command->id)); + destroy_command(command); + return FALSE; + } + + util_hexdump('<', data, command->len, + netlink->debug_handler, netlink->debug_data); + + g_hash_table_replace(netlink->command_pending, + GUINT_TO_POINTER(command->seq), command); + + return g_queue_get_length(netlink->command_queue) > 0; +} + +static void do_notify(gpointer key, gpointer value, gpointer user_data) +{ + struct nlmsghdr *nlmsg = user_data; + struct notify *notify = value; + + if (notify->handler) { + notify->handler(nlmsg->nlmsg_type, NLMSG_DATA(nlmsg), + nlmsg->nlmsg_len - NLMSG_HDRLEN, notify->user_data); + } +} + +static void process_broadcast(struct netlink_info *netlink, uint32_t group, + struct nlmsghdr *nlmsg) +{ + GHashTable *notify_list; + + notify_list = g_hash_table_lookup(netlink->notify_groups, + GUINT_TO_POINTER(group)); + if (!notify_list) + return; + + g_hash_table_foreach(notify_list, do_notify, nlmsg); +} + +static void process_message(struct netlink_info *netlink, + struct nlmsghdr *nlmsg) +{ + const void *data = nlmsg; + struct command *command; + + command = g_hash_table_lookup(netlink->command_pending, + GUINT_TO_POINTER(nlmsg->nlmsg_seq)); + if (!command) + return; + + g_hash_table_remove(netlink->command_pending, + GUINT_TO_POINTER(nlmsg->nlmsg_seq)); + + if (!command->handler) + goto done; + + if (nlmsg->nlmsg_type < NLMSG_MIN_TYPE) { + const struct nlmsgerr *err; + + switch (nlmsg->nlmsg_type) { + case NLMSG_ERROR: + err = data + NLMSG_HDRLEN; + + command->handler(-err->error, 0, NULL, 0, + command->user_data); + break; + } + } else { + command->handler(0, nlmsg->nlmsg_type, data + NLMSG_HDRLEN, + nlmsg->nlmsg_len - NLMSG_HDRLEN, + command->user_data); + } + +done: + g_hash_table_remove(netlink->command_lookup, + GUINT_TO_POINTER(command->id)); + + destroy_command(command); +} + +static void process_multi(struct netlink_info *netlink, struct nlmsghdr *nlmsg) +{ + const void *data = nlmsg; + struct command *command; + + command = g_hash_table_lookup(netlink->command_pending, + GUINT_TO_POINTER(nlmsg->nlmsg_seq)); + if (!command) + return; + + if (!command->handler) + goto done; + + if (nlmsg->nlmsg_type < NLMSG_MIN_TYPE) { + const struct nlmsgerr *err; + + switch (nlmsg->nlmsg_type) { + case NLMSG_DONE: + case NLMSG_ERROR: + err = data + NLMSG_HDRLEN; + + command->handler(-err->error, 0, NULL, 0, + command->user_data); + break; + } + } else { + command->handler(0, nlmsg->nlmsg_type, data + NLMSG_HDRLEN, + nlmsg->nlmsg_len - NLMSG_HDRLEN, + command->user_data); + return; + } + +done: + g_hash_table_remove(netlink->command_pending, + GUINT_TO_POINTER(nlmsg->nlmsg_seq)); + + g_hash_table_remove(netlink->command_lookup, + GUINT_TO_POINTER(command->id)); + + destroy_command(command); +} + +static gboolean can_read_data(GIOChannel *chan, + GIOCondition cond, gpointer data) +{ + struct netlink_info *netlink = data; + struct cmsghdr *cmsg; + struct msghdr msg; + struct iovec iov; + struct nlmsghdr *nlmsg; + unsigned char buffer[4096]; + unsigned char control[32]; + uint32_t group = 0; + ssize_t len; + int sk; + + sk = g_io_channel_unix_get_fd(chan); + + iov.iov_base = buffer; + iov.iov_len = sizeof(buffer); + + memset(&msg, 0, sizeof(msg)); + msg.msg_iov = &iov; + msg.msg_iovlen = 1; + msg.msg_control = control; + msg.msg_controllen = sizeof(control); + + len = recvmsg(sk, &msg, 0); + if (len < 0) + return FALSE; + + util_hexdump('>', buffer, len, netlink->debug_handler, + netlink->debug_data); + + for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; + cmsg = CMSG_NXTHDR(&msg, cmsg)) { + struct nl_pktinfo *pktinfo; + + if (cmsg->cmsg_level != SOL_NETLINK) + continue; + + if (cmsg->cmsg_type != NETLINK_PKTINFO) + continue; + + pktinfo = (void *) CMSG_DATA(cmsg); + + group = pktinfo->group; + } + + for (nlmsg = iov.iov_base; NLMSG_OK(nlmsg, (uint32_t) len); + nlmsg = NLMSG_NEXT(nlmsg, len)) { + if (group > 0 && nlmsg->nlmsg_seq == 0) { + process_broadcast(netlink, group, nlmsg); + continue; + } + + if (nlmsg->nlmsg_pid != netlink->pid) + continue; + + if (nlmsg->nlmsg_flags & NLM_F_MULTI) + process_multi(netlink, nlmsg); + else + process_message(netlink, nlmsg); + } + + return TRUE; +} + +static gboolean netlink_event(GIOChannel *chan, + GIOCondition cond, gpointer data) +{ + if (cond & (G_IO_NVAL | G_IO_HUP | G_IO_ERR)) + return FALSE; + + return TRUE; +} + +static int create_netlink_socket(int protocol, uint32_t *pid) +{ + struct sockaddr_nl addr; + socklen_t addrlen = sizeof(addr); + int sk, pktinfo = 1; + + sk = socket(PF_NETLINK, SOCK_DGRAM | SOCK_CLOEXEC | SOCK_NONBLOCK, + protocol); + if (sk < 0) + return -1; + + memset(&addr, 0, sizeof(addr)); + addr.nl_family = AF_NETLINK; + + if (bind(sk, (struct sockaddr *) &addr, sizeof(addr)) < 0) { + close(sk); + return -1; + } + + if (getsockname(sk, (struct sockaddr *) &addr, &addrlen) < 0) { + close(sk); + return -1; + } + + if (setsockopt(sk, SOL_NETLINK, NETLINK_PKTINFO, + &pktinfo, sizeof(pktinfo)) < 0) { + close(sk); + return -1; + } + + if (pid) + *pid = addr.nl_pid; + + return sk; +} + +struct netlink_info *netlink_new(int protocol) +{ + struct netlink_info *netlink; + int sk; + + netlink = g_try_new0(struct netlink_info, 1); + if (!netlink) + return NULL; + + netlink->next_seq = 1; + netlink->next_command_id = 1; + netlink->next_notify_id = 1; + + sk = create_netlink_socket(protocol, &netlink->pid); + if (sk < 0) { + g_free(netlink); + return NULL; + } + + netlink->channel = g_io_channel_unix_new(sk); + g_io_channel_set_close_on_unref(netlink->channel, TRUE); + + g_io_channel_set_encoding(netlink->channel, NULL, NULL); + g_io_channel_set_buffered(netlink->channel, FALSE); + + g_io_add_watch(netlink->channel, G_IO_IN, can_read_data, netlink); + g_io_add_watch(netlink->channel, G_IO_NVAL | G_IO_HUP | G_IO_ERR, + netlink_event, netlink); + + netlink->command_queue = g_queue_new(); + netlink->command_pending = g_hash_table_new(g_direct_hash, + g_direct_equal); + netlink->command_lookup = g_hash_table_new(g_direct_hash, + g_direct_equal); + + netlink->notify_groups = g_hash_table_new(g_direct_hash, + g_direct_equal); + netlink->notify_lookup = g_hash_table_new(g_direct_hash, + g_direct_equal); + + return netlink; +} + +static gboolean cleanup_notify(gpointer key, gpointer value, gpointer user_data) +{ + struct notify *notify = value; + + destroy_notify(notify); + + return TRUE; + +} + +static gboolean cleanup_notify_group(gpointer key, gpointer value, + gpointer user_data) +{ + GHashTable *notify_list = value; + + g_hash_table_foreach_remove(notify_list, cleanup_notify, user_data); + g_hash_table_destroy(notify_list); + + return TRUE; +} + +static gboolean cleanup_command(gpointer key, gpointer value, + gpointer user_data) +{ + struct command *command = value; + + destroy_command(command); + + return TRUE; +} + +void netlink_destroy(struct netlink_info *netlink) +{ + g_hash_table_destroy(netlink->notify_lookup); + + g_hash_table_foreach_remove(netlink->notify_groups, + cleanup_notify_group, NULL); + g_hash_table_destroy(netlink->notify_groups); + + g_queue_free(netlink->command_queue); + + g_hash_table_destroy(netlink->command_pending); + + g_hash_table_foreach_remove(netlink->command_lookup, + cleanup_command, NULL); + g_hash_table_destroy(netlink->command_lookup); + + g_io_channel_shutdown(netlink->channel, TRUE, NULL); + g_io_channel_unref(netlink->channel); + + g_free(netlink); +} + +unsigned int netlink_send(struct netlink_info *netlink, + uint16_t type, uint16_t flags, const void *data, + uint32_t len, netlink_command_func_t function, + void *user_data, netlink_destroy_func_t destroy) +{ + struct command *command; + struct nlmsghdr *nlmsg; + size_t size; + + if (!netlink) + return 0; + + if (!netlink->command_queue || + !netlink->command_pending || + !netlink->command_lookup) + return 0; + + size = NLMSG_ALIGN(sizeof(struct command)) + + NLMSG_HDRLEN + NLMSG_ALIGN(len); + + command = g_try_malloc0(size); + if (!command) + return 0; + + command->handler = function; + command->destroy = destroy; + command->user_data = user_data; + + command->id = netlink->next_command_id; + + g_hash_table_replace(netlink->command_lookup, + GUINT_TO_POINTER(command->id), command); + + command->seq = netlink->next_seq++; + command->len = NLMSG_HDRLEN + NLMSG_ALIGN(len); + + nlmsg = ((void *) command) + NLMSG_ALIGN(sizeof(struct command)); + + nlmsg->nlmsg_len = command->len; + nlmsg->nlmsg_type = type; + nlmsg->nlmsg_flags = NLM_F_REQUEST | flags; + nlmsg->nlmsg_seq = command->seq; + nlmsg->nlmsg_pid = netlink->pid; + + if (data && len > 0) + memcpy(((void *) nlmsg) + NLMSG_HDRLEN, data, len); + + g_queue_push_tail(netlink->command_queue, command); + + netlink->next_command_id++; + + /* Arm IOChannel to call can_write_data in case it is not armed yet. */ + if (g_queue_get_length(netlink->command_queue) == 1) + g_io_add_watch(netlink->channel, G_IO_OUT, can_write_data, + netlink); + + return command->id; +} + +bool netlink_cancel(struct netlink_info *netlink, unsigned int id) +{ + struct command *command; + + if (!netlink || id == 0) + return false; + + if (!netlink->command_queue || + !netlink->command_pending || + !netlink->command_lookup) + return false; + + command = g_hash_table_lookup(netlink->command_lookup, + GUINT_TO_POINTER(id)); + if (!command) + return false; + + g_hash_table_remove(netlink->command_lookup, GUINT_TO_POINTER(id)); + + if (!g_queue_remove(netlink->command_queue, command)) { + g_hash_table_remove(netlink->command_pending, + GUINT_TO_POINTER(command->seq)); + } + + destroy_command(command); + + return true; +} + +static bool add_membership(struct netlink_info *netlink, uint32_t group) +{ + int sk, value = group; + + sk = g_io_channel_unix_get_fd(netlink->channel); + + if (setsockopt(sk, SOL_NETLINK, NETLINK_ADD_MEMBERSHIP, + &value, sizeof(value)) < 0) + return false; + + return true; +} + +static bool drop_membership(struct netlink_info *netlink, uint32_t group) +{ + int sk, value = group; + + sk = g_io_channel_unix_get_fd(netlink->channel); + + if (setsockopt(sk, SOL_NETLINK, NETLINK_DROP_MEMBERSHIP, + &value, sizeof(value)) < 0) + return false; + + return true; +} + +unsigned int netlink_register(struct netlink_info *netlink, + uint32_t group, netlink_notify_func_t function, + void *user_data, netlink_destroy_func_t destroy) +{ + GHashTable *notify_list; + struct notify *notify; + unsigned int id; + + if (!netlink) + return 0; + + if (!netlink->notify_groups || !netlink->notify_lookup) + return 0; + + notify_list = g_hash_table_lookup(netlink->notify_groups, + GUINT_TO_POINTER(group)); + if (!notify_list) { + notify_list = g_hash_table_new(g_direct_hash, g_direct_equal); + if (!notify_list) + return 0; + + g_hash_table_replace(netlink->notify_groups, + GUINT_TO_POINTER(group), notify_list); + } + + notify = g_new(struct notify, 1); + + notify->group = group; + notify->handler = function; + notify->destroy = destroy; + notify->user_data = user_data; + + id = netlink->next_notify_id; + + g_hash_table_replace(netlink->notify_lookup, + GUINT_TO_POINTER(id), notify_list); + g_hash_table_replace(notify_list, GUINT_TO_POINTER(id), notify); + + if (g_hash_table_size(notify_list) == 1) { + if (add_membership(netlink, notify->group) == false) + goto remove_notify; + } + + netlink->next_notify_id++; + + return id; + +remove_notify: + g_hash_table_remove(notify_list, GUINT_TO_POINTER(id)); + g_hash_table_remove(netlink->notify_lookup, GUINT_TO_POINTER(id)); + g_free(notify); + + return 0; +} + +bool netlink_unregister(struct netlink_info *netlink, unsigned int id) +{ + GHashTable *notify_list; + struct notify *notify; + + if (!netlink || id == 0) + return false; + + if (!netlink->notify_groups || !netlink->notify_lookup) + return false; + + notify_list = g_hash_table_lookup(netlink->notify_lookup, + GUINT_TO_POINTER(id)); + + if (!notify_list) + return false; + + g_hash_table_remove(netlink->notify_lookup, GUINT_TO_POINTER(id)); + + notify = g_hash_table_lookup(notify_list, GUINT_TO_POINTER(id)); + if (!notify) + return false; + + g_hash_table_remove(notify_list, GUINT_TO_POINTER(id)); + + if (g_hash_table_size(notify_list) == 0) + drop_membership(netlink, notify->group); + + destroy_notify(notify); + + return true; +} + +bool netlink_set_debug(struct netlink_info *netlink, + netlink_debug_func_t function, + void *user_data, netlink_destroy_func_t destroy) +{ + if (!netlink) + return false; + + if (netlink->debug_destroy) + netlink->debug_destroy(netlink->debug_data); + + netlink->debug_handler = function; + netlink->debug_destroy = destroy; + netlink->debug_data = user_data; + + return true; +} diff --git a/src/shared/netlink.h b/src/shared/netlink.h new file mode 100644 index 00000000..62bb3e01 --- /dev/null +++ b/src/shared/netlink.h @@ -0,0 +1,53 @@ +/* + * + * Connection Manager + * + * Copyright (C) 2011-2012 Intel Corporation. All rights reserved. + * Copyright (C) 2013 BMW Car IT GbmH. + * + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1 as published by the Free Software Foundation. + * + * 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 + * + */ + +#include <stdint.h> +#include <stdbool.h> + +typedef void (*netlink_debug_func_t) (const char *str, void *user_data); +typedef void (*netlink_command_func_t) (unsigned int error, + uint16_t type, const void *data, + uint32_t len, void *user_data); +typedef void (*netlink_notify_func_t) (uint16_t type, const void *data, + uint32_t len, void *user_data); +typedef void (*netlink_destroy_func_t) (void *user_data); + +struct netlink_info; + +struct netlink_info *netlink_new(int protocol); +void netlink_destroy(struct netlink_info *netlink); + +unsigned int netlink_send(struct netlink_info *netlink, + uint16_t type, uint16_t flags, const void *data, + uint32_t len, netlink_command_func_t function, + void *user_data, netlink_destroy_func_t destroy); +bool netlink_cancel(struct netlink_info *netlink, unsigned int id); + +unsigned int netlink_register(struct netlink_info *netlink, + uint32_t group, netlink_notify_func_t function, + void *user_data, netlink_destroy_func_t destroy); +bool netlink_unregister(struct netlink_info *netlink, unsigned int id); + +bool netlink_set_debug(struct netlink_info *netlink, + netlink_debug_func_t function, + void *user_data, netlink_destroy_func_t destroy); diff --git a/src/shared/util.h b/src/shared/util.h index cb81fc57..293fb3a4 100644 --- a/src/shared/util.h +++ b/src/shared/util.h @@ -21,6 +21,8 @@ * */ +#include <glib.h> + typedef void (*util_debug_func_t)(const char *str, void *user_data); void util_debug(util_debug_func_t function, void *user_data, @@ -29,3 +31,20 @@ void util_debug(util_debug_func_t function, void *user_data, void util_hexdump(const char dir, const unsigned char *buf, size_t len, util_debug_func_t function, void *user_data); + +struct cb_data { + void *cb; + void *user_data; + void *data; +}; + +static inline struct cb_data *cb_data_new(void *cb, void *user_data) +{ + struct cb_data *ret; + + ret = g_new0(struct cb_data, 1); + ret->cb = cb; + ret->user_data = user_data; + + return ret; +} diff --git a/src/stats.c b/src/stats.c index 828c1ef8..df5ab4eb 100644 --- a/src/stats.c +++ b/src/stats.c @@ -125,7 +125,7 @@ struct stats_iter { struct stats_record *it; }; -GHashTable *stats_hash = NULL; +static GHashTable *stats_hash = NULL; static struct stats_file_header *get_hdr(struct stats_file *file) { @@ -219,7 +219,7 @@ static void stats_free(gpointer user_data) { struct stats_file *file = user_data; - if (file == NULL) + if (!file) return; msync(file->addr, file->len, MS_SYNC); @@ -230,12 +230,12 @@ static void stats_free(gpointer user_data) TFR(close(file->fd)); file->fd = -1; - if (file->history_name != NULL) { + if (file->history_name) { g_free(file->history_name); file->history_name = NULL; } - if (file->name != NULL) { + if (file->name) { g_free(file->name); file->name = NULL; } @@ -295,7 +295,7 @@ static int stats_file_remap(struct stats_file *file, size_t size) return -errno; } - if (file->addr == NULL) { + if (!file->addr) { /* * Though the buffer is not shared between processes, we still * have to take MAP_SHARED because MAP_PRIVATE does not @@ -472,18 +472,18 @@ static struct stats_record *process_file(struct stats_iter *iter, home = NULL; roaming = NULL; - if (cur == NULL) + if (!cur) cur = get_next_record(iter); next = get_next_record(iter); - while (next != NULL) { + while (next) { GDate date_cur; GDate date_next; - int append; + bool append; - append = FALSE; + append = false; - if (cur->roaming == TRUE) + if (cur->roaming) roaming = cur; else home = cur; @@ -503,24 +503,24 @@ static struct stats_record *process_file(struct stats_iter *iter, day_next = g_date_get_day(&date_next); if (day_cur == day_next && month_cur != month_next) { - append = TRUE; + append = true; } else if (day_cur < account_period_offset && day_next >= account_period_offset) { - append = TRUE; + append = true; } } else { /* day period size */ if (g_date_days_between(&date_cur, &date_next) > 0) - append = TRUE; + append = true; } - if (append == TRUE) { - if (home != NULL) { + if (append) { + if (home) { append_record(temp_file, home); home = NULL; } - if (roaming != NULL) { + if (roaming) { append_record(temp_file, roaming); roaming = NULL; } @@ -562,7 +562,7 @@ static int summarize(struct stats_file *data_file, /* Now process history file */ cur = NULL; - if (history_file != NULL) { + if (history_file) { history_iter.file = history_file; history_iter.begin = get_iterator_begin(history_iter.file); history_iter.end = get_iterator_end(history_iter.file); @@ -582,9 +582,9 @@ static int summarize(struct stats_file *data_file, * Ensure date_file records are newer than the history_file * record */ - if (cur != NULL) { + if (cur) { next = get_next_record(&data_iter); - while (next != NULL && cur->ts > next->ts) + while (next && cur->ts > next->ts) next = get_next_record(&data_iter); } @@ -593,7 +593,7 @@ static int summarize(struct stats_file *data_file, &date_change_step_size, data_file->account_period_offset); - if (cur != NULL) + if (cur) append_record(temp_file, cur); return 0; @@ -677,9 +677,9 @@ int __connman_stats_service_register(struct connman_service *service) DBG("service %p", service); file = g_hash_table_lookup(stats_hash, service); - if (file == NULL) { + if (!file) { file = g_try_new0(struct stats_file, 1); - if (file == NULL) + if (!file) return -ENOMEM; g_hash_table_insert(stats_hash, service, file); @@ -692,7 +692,7 @@ int __connman_stats_service_register(struct connman_service *service) /* If the dir doesn't exist, create it */ if (!g_file_test(dir, G_FILE_TEST_IS_DIR)) { - if(mkdir(dir, MODE) < 0) { + if (mkdir(dir, MODE) < 0) { if (errno != EEXIST) { g_free(dir); @@ -737,7 +737,7 @@ void __connman_stats_service_unregister(struct connman_service *service) } int __connman_stats_update(struct connman_service *service, - connman_bool_t roaming, + bool roaming, struct connman_stats_data *data) { struct stats_file *file; @@ -745,7 +745,7 @@ int __connman_stats_update(struct connman_service *service, int err; file = g_hash_table_lookup(stats_hash, service); - if (file == NULL) + if (!file) return -EEXIST; if (file->len < file->max_len && @@ -772,7 +772,7 @@ int __connman_stats_update(struct connman_service *service, next->roaming = roaming; memcpy(&next->data, data, sizeof(struct connman_stats_data)); - if (roaming != TRUE) + if (!roaming) set_home(file, next); else set_roaming(file, next); @@ -783,22 +783,22 @@ int __connman_stats_update(struct connman_service *service, } int __connman_stats_get(struct connman_service *service, - connman_bool_t roaming, + bool roaming, struct connman_stats_data *data) { struct stats_file *file; struct stats_record *rec; file = g_hash_table_lookup(stats_hash, service); - if (file == NULL) + if (!file) return -EEXIST; - if (roaming != TRUE) + if (!roaming) rec = file->home; else rec = file->roaming; - if (rec != NULL) { + if (rec) { memcpy(data, &rec->data, sizeof(struct connman_stats_data)); } diff --git a/src/storage.c b/src/storage.c index 1ceafb99..7d031303 100644 --- a/src/storage.c +++ b/src/storage.c @@ -2,7 +2,7 @@ * * Connection Manager * - * Copyright (C) 2007-2012 Intel Corporation. All rights reserved. + * Copyright (C) 2007-2013 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 @@ -92,7 +92,7 @@ GKeyFile *__connman_storage_load_global(void) GKeyFile *keyfile = NULL; pathname = g_strdup_printf("%s/%s", STORAGEDIR, SETTINGS); - if(pathname == NULL) + if (!pathname) return NULL; keyfile = storage_load(pathname); @@ -108,7 +108,7 @@ int __connman_storage_save_global(GKeyFile *keyfile) int ret; pathname = g_strdup_printf("%s/%s", STORAGEDIR, SETTINGS); - if(pathname == NULL) + if (!pathname) return -ENOMEM; ret = storage_save(keyfile, pathname); @@ -123,7 +123,7 @@ void __connman_storage_delete_global(void) gchar *pathname; pathname = g_strdup_printf("%s/%s", STORAGEDIR, SETTINGS); - if(pathname == NULL) + if (!pathname) return; storage_delete(pathname); @@ -137,7 +137,7 @@ GKeyFile *__connman_storage_load_config(const char *ident) GKeyFile *keyfile = NULL; pathname = g_strdup_printf("%s/%s.config", STORAGEDIR, ident); - if(pathname == NULL) + if (!pathname) return NULL; keyfile = storage_load(pathname); @@ -153,7 +153,7 @@ GKeyFile *__connman_storage_load_provider_config(const char *ident) GKeyFile *keyfile = NULL; pathname = g_strdup_printf("%s/%s.config", VPN_STORAGEDIR, ident); - if (pathname == NULL) + if (!pathname) return NULL; keyfile = storage_load(pathname); @@ -169,7 +169,7 @@ GKeyFile *__connman_storage_open_service(const char *service_id) GKeyFile *keyfile = NULL; pathname = g_strdup_printf("%s/%s/%s", STORAGEDIR, service_id, SETTINGS); - if(pathname == NULL) + if (!pathname) return NULL; keyfile = storage_load(pathname); @@ -196,7 +196,7 @@ gchar **connman_storage_get_services(void) int ret; dir = opendir(STORAGEDIR); - if (dir == NULL) + if (!dir) return NULL; result = g_string_new(NULL); @@ -248,7 +248,7 @@ GKeyFile *connman_storage_load_service(const char *service_id) GKeyFile *keyfile = NULL; pathname = g_strdup_printf("%s/%s/%s", STORAGEDIR, service_id, SETTINGS); - if(pathname == NULL) + if (!pathname) return NULL; keyfile = storage_load(pathname); @@ -263,12 +263,12 @@ int __connman_storage_save_service(GKeyFile *keyfile, const char *service_id) gchar *pathname, *dirname; dirname = g_strdup_printf("%s/%s", STORAGEDIR, service_id); - if(dirname == NULL) + if (!dirname) return -ENOMEM; /* If the dir doesn't exist, create it */ if (!g_file_test(dirname, G_FILE_TEST_IS_DIR)) { - if(mkdir(dirname, MODE) < 0) { + if (mkdir(dirname, MODE) < 0) { if (errno != EEXIST) { g_free(dirname); return -errno; @@ -287,67 +287,67 @@ int __connman_storage_save_service(GKeyFile *keyfile, const char *service_id) return ret; } -static gboolean remove_file(const char *service_id, const char *file) +static bool remove_file(const char *service_id, const char *file) { gchar *pathname; - gboolean ret = FALSE; + bool ret = false; pathname = g_strdup_printf("%s/%s/%s", STORAGEDIR, service_id, file); - if(pathname == NULL) - return FALSE; + if (!pathname) + return false; - if (g_file_test(pathname, G_FILE_TEST_EXISTS) == FALSE) { - ret = TRUE; - } else if (g_file_test(pathname, G_FILE_TEST_IS_REGULAR) == TRUE) { + if (!g_file_test(pathname, G_FILE_TEST_EXISTS)) { + ret = true; + } else if (g_file_test(pathname, G_FILE_TEST_IS_REGULAR)) { unlink(pathname); - ret = TRUE; + ret = true; } g_free(pathname); return ret; } -static gboolean remove_dir(const char *service_id) +static bool remove_dir(const char *service_id) { gchar *pathname; - gboolean ret = FALSE; + bool ret = false; pathname = g_strdup_printf("%s/%s", STORAGEDIR, service_id); - if(pathname == NULL) - return FALSE; + if (!pathname) + return false; - if (g_file_test(pathname, G_FILE_TEST_EXISTS) == FALSE) { - ret = TRUE; - } else if (g_file_test(pathname, G_FILE_TEST_IS_DIR) == TRUE) { + if (!g_file_test(pathname, G_FILE_TEST_EXISTS)) { + ret = true; + } else if (g_file_test(pathname, G_FILE_TEST_IS_DIR)) { rmdir(pathname); - ret = TRUE; + ret = true; } g_free(pathname); return ret; } -gboolean __connman_storage_remove_service(const char *service_id) +bool __connman_storage_remove_service(const char *service_id) { - gboolean removed; + bool removed; /* Remove service configuration file */ removed = remove_file(service_id, SETTINGS); - if (removed == FALSE) - return FALSE; + if (!removed) + return false; /* Remove the statistics file also */ removed = remove_file(service_id, "data"); - if (removed == FALSE) - return FALSE; + if (!removed) + return false; removed = remove_dir(service_id); - if (removed == FALSE) - return FALSE; + if (!removed) + return false; DBG("Removed service dir %s/%s", STORAGEDIR, service_id); - return TRUE; + return true; } GKeyFile *__connman_storage_load_provider(const char *identifier) @@ -357,7 +357,7 @@ GKeyFile *__connman_storage_load_provider(const char *identifier) pathname = g_strdup_printf("%s/%s_%s/%s", STORAGEDIR, "provider", identifier, SETTINGS); - if (pathname == NULL) + if (!pathname) return NULL; keyfile = storage_load(pathname); @@ -372,10 +372,10 @@ void __connman_storage_save_provider(GKeyFile *keyfile, const char *identifier) dirname = g_strdup_printf("%s/%s_%s", STORAGEDIR, "provider", identifier); - if (dirname == NULL) + if (!dirname) return; - if (g_file_test(dirname, G_FILE_TEST_IS_DIR) == FALSE && + if (!g_file_test(dirname, G_FILE_TEST_IS_DIR) && mkdir(dirname, MODE) < 0) { g_free(dirname); return; @@ -388,39 +388,39 @@ void __connman_storage_save_provider(GKeyFile *keyfile, const char *identifier) g_free(pathname); } -static gboolean remove_all(const char *id) +static bool remove_all(const char *id) { - gboolean removed; + bool removed; remove_file(id, SETTINGS); remove_file(id, "data"); removed = remove_dir(id); - if (removed == FALSE) - return FALSE; + if (!removed) + return false; - return TRUE; + return true; } -gboolean __connman_storage_remove_provider(const char *identifier) +bool __connman_storage_remove_provider(const char *identifier) { - gboolean removed; + bool removed; gchar *id; id = g_strdup_printf("%s_%s", "provider", identifier); - if (id == NULL) - return FALSE; + if (!id) + return false; - if (remove_all(id) == TRUE) + if (remove_all(id)) DBG("Removed provider dir %s/%s", STORAGEDIR, id); g_free(id); id = g_strdup_printf("%s_%s", "vpn", identifier); - if (id == NULL) - return FALSE; + if (!id) + return false; - if ((removed = remove_all(id)) == TRUE) + if ((removed = remove_all(id))) DBG("Removed vpn dir %s/%s", STORAGEDIR, id); g_free(id); @@ -441,7 +441,7 @@ gchar **__connman_storage_get_providers(void) GSList *iter; dir = opendir(STORAGEDIR); - if (dir == NULL) + if (!dir) return NULL; while ((d = readdir(dir))) { @@ -465,8 +465,8 @@ gchar **__connman_storage_get_providers(void) closedir(dir); providers = g_try_new0(char *, num + 1); - for (iter = list; iter != NULL; iter = g_slist_next(iter)) { - if (providers != NULL) + for (iter = list; iter; iter = g_slist_next(iter)) { + if (providers) providers[i] = iter->data; else g_free(iter->data); @@ -102,7 +102,7 @@ struct connman_task *connman_task_create(const char *program) DBG(""); task = g_try_new0(struct connman_task, 1); - if (task == NULL) + if (!task) return NULL; counter = __sync_fetch_and_add(&task_counter, 1); @@ -167,7 +167,7 @@ int connman_task_add_argument(struct connman_task *task, DBG("task %p arg %s", task, name); - if (name == NULL) + if (!name) return -EINVAL; str = g_strdup(name); @@ -175,7 +175,7 @@ int connman_task_add_argument(struct connman_task *task, va_start(ap, format); - if (format != NULL) { + if (format) { str = g_strdup_vprintf(format, ap); g_ptr_array_add(task->argv, str); } @@ -202,7 +202,7 @@ int connman_task_add_variable(struct connman_task *task, DBG("task %p key %s", task, key); - if (key == NULL) + if (!key) return -EINVAL; va_start(ap, format); @@ -234,7 +234,7 @@ int connman_task_set_notify(struct connman_task *task, const char *member, DBG("task %p", task); notify = g_try_new0(struct notify_data, 1); - if (notify == NULL) + if (!notify) return -ENOMEM; notify->func = function; @@ -293,7 +293,7 @@ int connman_task_run(struct connman_task *task, int *stdin_fd, int *stdout_fd, int *stderr_fd) { GSpawnFlags flags = G_SPAWN_DO_NOT_REAP_CHILD; - gboolean result; + bool result; char **argv, **envp; DBG("task %p", task); @@ -301,20 +301,20 @@ int connman_task_run(struct connman_task *task, if (task->pid > 0) return -EALREADY; - if (stdout_fd == NULL) + if (!stdout_fd) flags |= G_SPAWN_STDOUT_TO_DEV_NULL; - if (stderr_fd == NULL) + if (!stderr_fd) flags |= G_SPAWN_STDERR_TO_DEV_NULL; task->exit_func = function; task->exit_data = user_data; - if (g_ptr_array_index(task->argv, task->argv->len - 1) != NULL) + if (g_ptr_array_index(task->argv, task->argv->len - 1)) g_ptr_array_add(task->argv, NULL); - if (task->envp->len == 0 || g_ptr_array_index(task->envp, - task->envp->len - 1) != NULL) { + if (task->envp->len == 0 || + g_ptr_array_index(task->envp, task->envp->len - 1)) { if (g_hash_table_size(task->notify) > 0) { const char *busname; char *str; @@ -340,7 +340,7 @@ int connman_task_run(struct connman_task *task, result = g_spawn_async_with_pipes(NULL, argv, envp, flags, task_setup, task, &task->pid, stdin_fd, stdout_fd, stderr_fd, NULL); - if (result == FALSE) { + if (!result) { connman_error("Failed to spawn %s", argv[0]); return -EIO; } @@ -419,39 +419,38 @@ static DBusHandlerResult task_filter(DBusConnection *conn, if (dbus_message_get_type(message) != DBUS_MESSAGE_TYPE_METHOD_CALL) return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; - if (dbus_message_has_interface(message, - CONNMAN_TASK_INTERFACE) == FALSE) + if (!dbus_message_has_interface(message, CONNMAN_TASK_INTERFACE)) return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; path = dbus_message_get_path(message); - if (path == NULL) + if (!path) return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; task = g_hash_table_lookup(task_hash, path); - if (task == NULL) + if (!task) return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; member = dbus_message_get_member(message); - if (member == NULL) + if (!member) goto send_reply; notify = g_hash_table_lookup(task->notify, member); - if (notify == NULL) + if (!notify) goto send_reply; if (notify->func) reply = notify->func(task, message, notify->data); send_reply: - if (dbus_message_get_no_reply(message) == FALSE && - reply == NULL) { + if (!dbus_message_get_no_reply(message) && + !reply) { reply = dbus_message_new_method_return(message); - if (reply == NULL) + if (!reply) return DBUS_HANDLER_RESULT_NEED_MEMORY; } - if (reply != NULL) { + if (reply) { dbus_connection_send(conn, reply, NULL); dbus_message_unref(reply); diff --git a/src/technology.c b/src/technology.c index 632f7164..d80d9e6d 100644 --- a/src/technology.c +++ b/src/technology.c @@ -2,7 +2,7 @@ * * Connection Manager * - * Copyright (C) 2007-2012 Intel Corporation. All rights reserved. + * Copyright (C) 2007-2013 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 @@ -41,13 +41,13 @@ static GSList *technology_list = NULL; static GSList *techless_device_list = NULL; static GHashTable *rfkill_list; -static connman_bool_t global_offlinemode; +static bool global_offlinemode; struct connman_rfkill { unsigned int index; enum connman_service_type type; - connman_bool_t softblock; - connman_bool_t hardblock; + bool softblock; + bool hardblock; }; struct connman_technology { @@ -55,19 +55,19 @@ struct connman_technology { enum connman_service_type type; char *path; GSList *device_list; - connman_bool_t enabled; + bool enabled; char *regdom; - connman_bool_t connected; + bool connected; - connman_bool_t tethering; - connman_bool_t tethering_persistent; /* Tells the save status, needed + bool tethering; + bool tethering_persistent; /* Tells the save status, needed * as offline mode might set * tethering OFF. */ char *tethering_ident; char *tethering_passphrase; - connman_bool_t enable_persistent; /* Save the tech state */ + bool enable_persistent; /* Save the tech state */ GSList *driver_list; @@ -76,10 +76,10 @@ struct connman_technology { GSList *scan_pending; - connman_bool_t rfkill_driven; - connman_bool_t softblocked; - connman_bool_t hardblocked; - connman_bool_t dbus_registered; + bool rfkill_driven; + bool softblocked; + bool hardblocked; + bool dbus_registered; }; static GSList *driver_list = NULL; @@ -103,7 +103,7 @@ static void rfkill_check(gpointer key, gpointer value, gpointer user_data) rfkill->softblock, rfkill->hardblock); } -connman_bool_t +bool connman_technology_is_tethering_allowed(enum connman_service_type type) { static char *allowed_default[] = { "wifi", "bluetooth", "gadget", @@ -112,100 +112,19 @@ connman_technology_is_tethering_allowed(enum connman_service_type type) char **allowed; int i; - if (type_str == NULL) - return FALSE; + if (!type_str) + return false; allowed = connman_setting_get_string_list("TetheringTechnologies"); - if (allowed == NULL) + if (!allowed) allowed = allowed_default; - for (i = 0; allowed[i] != NULL; i++) { + for (i = 0; allowed[i]; i++) { if (g_strcmp0(allowed[i], type_str) == 0) - return TRUE; + return true; } - return FALSE; -} - -/** - * connman_technology_driver_register: - * @driver: Technology driver definition - * - * Register a new technology driver - * - * Returns: %0 on success - */ -int connman_technology_driver_register(struct connman_technology_driver *driver) -{ - GSList *list; - struct connman_device *device; - enum connman_service_type type; - - DBG("Registering %s driver", driver->name); - - driver_list = g_slist_insert_sorted(driver_list, driver, - compare_priority); - - /* - * Check for technology less devices if this driver - * can service any of them. - */ - for (list = techless_device_list; list != NULL; list = list->next) { - device = list->data; - - type = __connman_device_get_service_type(device); - if (type != driver->type) - continue; - - techless_device_list = g_slist_remove(techless_device_list, - device); - - __connman_technology_add_device(device); - } - - /* Check for orphaned rfkill switches. */ - g_hash_table_foreach(rfkill_list, rfkill_check, - GINT_TO_POINTER(driver->type)); - - return 0; -} - -/** - * connman_technology_driver_unregister: - * @driver: Technology driver definition - * - * Remove a previously registered technology driver - */ -void connman_technology_driver_unregister(struct connman_technology_driver *driver) -{ - GSList *list, *tech_drivers; - struct connman_technology *technology; - struct connman_technology_driver *current; - - DBG("Unregistering driver %p name %s", driver, driver->name); - - for (list = technology_list; list; list = list->next) { - technology = list->data; - - for (tech_drivers = technology->driver_list; - tech_drivers != NULL; - tech_drivers = g_slist_next(tech_drivers)) { - - current = tech_drivers->data; - if (driver != current) - continue; - - if (driver->remove != NULL) - driver->remove(technology); - - technology->driver_list = - g_slist_remove(technology->driver_list, driver); - - break; - } - } - - driver_list = g_slist_remove(driver_list, driver); + return false; } static const char *get_name(enum connman_service_type type) @@ -215,8 +134,9 @@ static const char *get_name(enum connman_service_type type) case CONNMAN_SERVICE_TYPE_SYSTEM: case CONNMAN_SERVICE_TYPE_GPS: case CONNMAN_SERVICE_TYPE_VPN: - case CONNMAN_SERVICE_TYPE_GADGET: break; + case CONNMAN_SERVICE_TYPE_GADGET: + return "Gadget"; case CONNMAN_SERVICE_TYPE_ETHERNET: return "Wired"; case CONNMAN_SERVICE_TYPE_WIFI: @@ -225,6 +145,8 @@ static const char *get_name(enum connman_service_type type) return "Bluetooth"; case CONNMAN_SERVICE_TYPE_CELLULAR: return "Cellular"; + case CONNMAN_SERVICE_TYPE_P2P: + return "P2P"; } return NULL; @@ -234,15 +156,19 @@ static void technology_save(struct connman_technology *technology) { GKeyFile *keyfile; gchar *identifier; + const char *name = get_name(technology->type); - DBG("technology %p", technology); + DBG("technology %p type %d name %s", technology, technology->type, + name); + if (!name) + return; keyfile = __connman_storage_load_global(); - if (keyfile == NULL) + if (!keyfile) keyfile = g_key_file_new(); - identifier = g_strdup_printf("%s", get_name(technology->type)); - if (identifier == NULL) + identifier = g_strdup_printf("%s", name); + if (!identifier) goto done; g_key_file_set_boolean(keyfile, identifier, "Enable", @@ -251,12 +177,12 @@ static void technology_save(struct connman_technology *technology) g_key_file_set_boolean(keyfile, identifier, "Tethering", technology->tethering_persistent); - if (technology->tethering_ident != NULL) + if (technology->tethering_ident) g_key_file_set_string(keyfile, identifier, "Tethering.Identifier", technology->tethering_ident); - if (technology->tethering_passphrase != NULL) + if (technology->tethering_passphrase) g_key_file_set_string(keyfile, identifier, "Tethering.Passphrase", technology->tethering_passphrase); @@ -273,7 +199,7 @@ done: static void tethering_changed(struct connman_technology *technology) { - connman_bool_t tethering = technology->tethering; + dbus_bool_t tethering = technology->tethering; connman_dbus_property_changed_basic(technology->path, CONNMAN_TECHNOLOGY_INTERFACE, "Tethering", @@ -283,10 +209,8 @@ static void tethering_changed(struct connman_technology *technology) } void connman_technology_tethering_notify(struct connman_technology *technology, - connman_bool_t enabled) + bool enabled) { - GSList *list; - DBG("technology %p enabled %u", technology, enabled); if (technology->tethering == enabled) @@ -296,21 +220,14 @@ void connman_technology_tethering_notify(struct connman_technology *technology, tethering_changed(technology); - if (enabled == TRUE) + if (enabled) __connman_tethering_set_enabled(); - else { - for (list = technology_list; list; list = list->next) { - struct connman_technology *other_tech = list->data; - if (other_tech->tethering == TRUE) - break; - } - if (list == NULL) - __connman_tethering_set_disabled(); - } + else + __connman_tethering_set_disabled(); } static int set_tethering(struct connman_technology *technology, - connman_bool_t enabled) + bool enabled) { int result = -EOPNOTSUPP; int err; @@ -321,22 +238,22 @@ static int set_tethering(struct connman_technology *technology, passphrase = technology->tethering_passphrase; __sync_synchronize(); - if (technology->enabled == FALSE) + if (!technology->enabled) return -EACCES; bridge = __connman_tethering_get_bridge(); - if (bridge == NULL) + if (!bridge) return -EOPNOTSUPP; if (technology->type == CONNMAN_SERVICE_TYPE_WIFI && - (ident == NULL || passphrase == NULL)) + (!ident || !passphrase)) return -EINVAL; - for (tech_drivers = technology->driver_list; tech_drivers != NULL; + for (tech_drivers = technology->driver_list; tech_drivers; tech_drivers = g_slist_next(tech_drivers)) { struct connman_technology_driver *driver = tech_drivers->data; - if (driver == NULL || driver->set_tethering == NULL) + if (!driver || !driver->set_tethering) continue; err = driver->set_tethering(technology, ident, passphrase, @@ -359,7 +276,7 @@ void connman_technology_regdom_notify(struct connman_technology *technology, { DBG(""); - if (alpha2 == NULL) + if (!alpha2) connman_error("Failed to set regulatory domain"); else DBG("Regulatory domain set to %s", alpha2); @@ -393,13 +310,13 @@ int connman_technology_set_regdom(const char *alpha2) if (set_regdom_by_device(technology, alpha2) != 0) { for (tech_drivers = technology->driver_list; - tech_drivers != NULL; + tech_drivers; tech_drivers = g_slist_next(tech_drivers)) { struct connman_technology_driver *driver = tech_drivers->data; - if (driver->set_regdom != NULL) + if (driver->set_regdom) driver->set_regdom(technology, alpha2); } } @@ -424,27 +341,27 @@ static struct connman_technology *technology_find(enum connman_service_type type return NULL; } -connman_bool_t connman_technology_get_wifi_tethering(const char **ssid, +bool connman_technology_get_wifi_tethering(const char **ssid, const char **psk) { struct connman_technology *technology; - if (ssid == NULL || psk == NULL) - return FALSE; + if (!ssid || !psk) + return false; *ssid = *psk = NULL; technology = technology_find(CONNMAN_SERVICE_TYPE_WIFI); - if (technology == NULL) - return FALSE; + if (!technology) + return false; - if (technology->tethering == FALSE) - return FALSE; + if (!technology->tethering) + return false; *ssid = technology->tethering_ident; *psk = technology->tethering_passphrase; - return TRUE; + return true; } static void free_rfkill(gpointer data) @@ -459,48 +376,48 @@ static void technology_load(struct connman_technology *technology) GKeyFile *keyfile; gchar *identifier; GError *error = NULL; - connman_bool_t enable, need_saving = FALSE; + bool enable, need_saving = false; DBG("technology %p", technology); keyfile = __connman_storage_load_global(); /* Fallback on disabling technology if file not found. */ - if (keyfile == NULL) { + if (!keyfile) { if (technology->type == CONNMAN_SERVICE_TYPE_ETHERNET) /* We enable ethernet by default */ - technology->enable_persistent = TRUE; + technology->enable_persistent = true; else - technology->enable_persistent = FALSE; + technology->enable_persistent = false; return; } identifier = g_strdup_printf("%s", get_name(technology->type)); - if (identifier == NULL) + if (!identifier) goto done; enable = g_key_file_get_boolean(keyfile, identifier, "Enable", &error); - if (error == NULL) + if (!error) technology->enable_persistent = enable; else { if (technology->type == CONNMAN_SERVICE_TYPE_ETHERNET) - technology->enable_persistent = TRUE; + technology->enable_persistent = true; else - technology->enable_persistent = FALSE; + technology->enable_persistent = false; - need_saving = TRUE; + need_saving = true; g_clear_error(&error); } enable = g_key_file_get_boolean(keyfile, identifier, "Tethering", &error); - if (error == NULL) + if (!error) technology->tethering_persistent = enable; else { - need_saving = TRUE; + need_saving = true; g_clear_error(&error); } - if (need_saving == TRUE) + if (need_saving) technology_save(technology); technology->tethering_ident = g_key_file_get_string(keyfile, @@ -516,17 +433,17 @@ done: return; } -connman_bool_t __connman_technology_get_offlinemode(void) +bool __connman_technology_get_offlinemode(void) { return global_offlinemode; } -static void connman_technology_save_offlinemode() +static void connman_technology_save_offlinemode(void) { GKeyFile *keyfile; keyfile = __connman_storage_load_global(); - if (keyfile == NULL) + if (!keyfile) keyfile = g_key_file_new(); g_key_file_set_boolean(keyfile, "global", @@ -539,21 +456,21 @@ static void connman_technology_save_offlinemode() return; } -static connman_bool_t connman_technology_load_offlinemode() +static bool connman_technology_load_offlinemode(void) { GKeyFile *keyfile; GError *error = NULL; - connman_bool_t offlinemode; + bool offlinemode; /* If there is a error, we enable offlinemode */ keyfile = __connman_storage_load_global(); - if (keyfile == NULL) - return FALSE; + if (!keyfile) + return false; offlinemode = g_key_file_get_boolean(keyfile, "global", "OfflineMode", &error); - if (error != NULL) { - offlinemode = FALSE; + if (error) { + offlinemode = false; g_clear_error(&error); } @@ -566,39 +483,43 @@ static void append_properties(DBusMessageIter *iter, struct connman_technology *technology) { DBusMessageIter dict; + dbus_bool_t val; const char *str; connman_dbus_dict_open(iter, &dict); str = get_name(technology->type); - if (str != NULL) + if (str) connman_dbus_dict_append_basic(&dict, "Name", DBUS_TYPE_STRING, &str); str = __connman_service_type2string(technology->type); - if (str != NULL) + if (str) connman_dbus_dict_append_basic(&dict, "Type", DBUS_TYPE_STRING, &str); __sync_synchronize(); + val = technology->enabled; connman_dbus_dict_append_basic(&dict, "Powered", DBUS_TYPE_BOOLEAN, - &technology->enabled); + &val); + val = technology->connected; connman_dbus_dict_append_basic(&dict, "Connected", DBUS_TYPE_BOOLEAN, - &technology->connected); + &val); + val = technology->tethering; connman_dbus_dict_append_basic(&dict, "Tethering", DBUS_TYPE_BOOLEAN, - &technology->tethering); + &val); - if (technology->tethering_ident != NULL) + if (technology->tethering_ident) connman_dbus_dict_append_basic(&dict, "TetheringIdentifier", DBUS_TYPE_STRING, &technology->tethering_ident); - if (technology->tethering_passphrase != NULL) + if (technology->tethering_passphrase) connman_dbus_dict_append_basic(&dict, "TetheringPassphrase", DBUS_TYPE_STRING, &technology->tethering_passphrase); @@ -613,7 +534,7 @@ static void technology_added_signal(struct connman_technology *technology) signal = dbus_message_new_signal(CONNMAN_MANAGER_PATH, CONNMAN_MANAGER_INTERFACE, "TechnologyAdded"); - if (signal == NULL) + if (!signal) return; dbus_message_iter_init_append(signal, &iter); @@ -641,7 +562,7 @@ static DBusMessage *get_properties(DBusConnection *conn, DBusMessageIter iter; reply = dbus_message_new_method_return(message); - if (reply == NULL) + if (!reply) return NULL; dbus_message_iter_init_append(reply, &iter); @@ -658,9 +579,9 @@ void __connman_technology_list_struct(DBusMessageIter *array) for (list = technology_list; list; list = list->next) { struct connman_technology *technology = list->data; - if (technology->path == NULL || - (technology->rfkill_driven == TRUE && - technology->hardblocked == TRUE)) + if (!technology->path || + (technology->rfkill_driven && + technology->hardblocked)) continue; dbus_message_iter_open_container(array, DBUS_TYPE_STRUCT, @@ -678,9 +599,9 @@ static gboolean technology_pending_reply(gpointer user_data) DBusMessage *reply; /* Power request timedout, send ETIMEDOUT. */ - if (technology->pending_reply != NULL) { + if (technology->pending_reply) { reply = __connman_error_failed(technology->pending_reply, ETIMEDOUT); - if (reply != NULL) + if (reply) g_dbus_send_message(connection, reply); dbus_message_unref(technology->pending_reply); @@ -692,15 +613,18 @@ static gboolean technology_pending_reply(gpointer user_data) } static int technology_affect_devices(struct connman_technology *technology, - connman_bool_t enable_device) + bool enable_device) { GSList *list; - int err = 0; + int err = -ENXIO; + + if (technology->type == CONNMAN_SERVICE_TYPE_P2P) + return 0; for (list = technology->device_list; list; list = list->next) { struct connman_device *device = list->data; - if (enable_device == TRUE) + if (enable_device) err = __connman_device_enable(device); else err = __connman_device_disable(device); @@ -709,6 +633,68 @@ static int technology_affect_devices(struct connman_technology *technology, return err; } +static void powered_changed(struct connman_technology *technology) +{ + dbus_bool_t enabled; + + if (!technology->dbus_registered) + return; + + if (technology->pending_reply) { + g_dbus_send_reply(connection, + technology->pending_reply, DBUS_TYPE_INVALID); + dbus_message_unref(technology->pending_reply); + technology->pending_reply = NULL; + + g_source_remove(technology->pending_timeout); + technology->pending_timeout = 0; + } + + __sync_synchronize(); + enabled = technology->enabled; + connman_dbus_property_changed_basic(technology->path, + CONNMAN_TECHNOLOGY_INTERFACE, "Powered", + DBUS_TYPE_BOOLEAN, &enabled); +} + +static void enable_tethering(struct connman_technology *technology) +{ + int ret; + + if (!connman_setting_get_bool("PersistentTetheringMode")) + return; + + ret = set_tethering(technology, true); + if (ret < 0 && ret != -EALREADY) + DBG("Cannot enable tethering yet for %s (%d/%s)", + get_name(technology->type), + -ret, strerror(-ret)); +} + +static int technology_enabled(struct connman_technology *technology) +{ + __sync_synchronize(); + if (technology->enabled) + return -EALREADY; + + technology->enabled = true; + + if (technology->type == CONNMAN_SERVICE_TYPE_WIFI) { + struct connman_technology *p2p; + + p2p = technology_find(CONNMAN_SERVICE_TYPE_P2P); + if (p2p && !p2p->enabled && p2p->enable_persistent) + technology_enabled(p2p); + } + + if (technology->tethering_persistent) + enable_tethering(technology); + + powered_changed(technology); + + return 0; +} + static int technology_enable(struct connman_technology *technology) { int err = 0; @@ -717,27 +703,50 @@ static int technology_enable(struct connman_technology *technology) DBG("technology %p enable", technology); __sync_synchronize(); - if (technology->enabled == TRUE) + + if (technology->type == CONNMAN_SERVICE_TYPE_P2P) { + struct connman_technology *wifi; + + wifi = technology_find(CONNMAN_SERVICE_TYPE_WIFI); + if (wifi && wifi->enabled) + return technology_enabled(technology); + return 0; + } + + if (technology->enabled) return -EALREADY; - if (technology->pending_reply != NULL) + if (technology->pending_reply) return -EBUSY; - if (connman_setting_get_bool("PersistentTetheringMode") == TRUE && - technology->tethering == TRUE) - set_tethering(technology, TRUE); + if (connman_setting_get_bool("PersistentTetheringMode") && + technology->tethering) + set_tethering(technology, true); - if (technology->rfkill_driven == TRUE) - err = __connman_rfkill_block(technology->type, FALSE); + if (technology->rfkill_driven) + err = __connman_rfkill_block(technology->type, false); - err_dev = technology_affect_devices(technology, TRUE); + err_dev = technology_affect_devices(technology, true); - if (technology->rfkill_driven == FALSE) + if (!technology->rfkill_driven) err = err_dev; return err; } +static int technology_disabled(struct connman_technology *technology) +{ + __sync_synchronize(); + if (!technology->enabled) + return -EALREADY; + + technology->enabled = false; + + powered_changed(technology); + + return 0; +} + static int technology_disable(struct connman_technology *technology) { int err; @@ -745,35 +754,49 @@ static int technology_disable(struct connman_technology *technology) DBG("technology %p disable", technology); __sync_synchronize(); - if (technology->enabled == FALSE) + + if (technology->type == CONNMAN_SERVICE_TYPE_P2P) { + technology->enable_persistent = false; + return technology_disabled(technology); + } else if (technology->type == CONNMAN_SERVICE_TYPE_WIFI) { + struct connman_technology *p2p; + + p2p = technology_find(CONNMAN_SERVICE_TYPE_P2P); + if (p2p && p2p->enabled) { + p2p->enable_persistent = true; + technology_disabled(p2p); + } + } + + if (!technology->enabled) return -EALREADY; - if (technology->pending_reply != NULL) + if (technology->pending_reply) return -EBUSY; - if (technology->tethering == TRUE) - set_tethering(technology, FALSE); + if (technology->tethering) + set_tethering(technology, false); - err = technology_affect_devices(technology, FALSE); + err = technology_affect_devices(technology, false); - if (technology->rfkill_driven == TRUE) - err = __connman_rfkill_block(technology->type, TRUE); + if (technology->rfkill_driven) + err = __connman_rfkill_block(technology->type, true); return err; } static DBusMessage *set_powered(struct connman_technology *technology, - DBusMessage *msg, connman_bool_t powered) + DBusMessage *msg, bool powered) { DBusMessage *reply = NULL; int err = 0; - if (technology->rfkill_driven && technology->hardblocked == TRUE) { + if (technology->rfkill_driven && technology->hardblocked) { err = -EACCES; goto make_reply; } - if (powered == TRUE) + if (powered) err = technology_enable(technology); else err = technology_disable(technology); @@ -789,7 +812,7 @@ make_reply: technology->pending_timeout = g_timeout_add_seconds(10, technology_pending_reply, technology); } else if (err == -EALREADY) { - if (powered == TRUE) + if (powered) reply = __connman_error_already_enabled(msg); else reply = __connman_error_already_disabled(msg); @@ -811,7 +834,7 @@ static DBusMessage *set_property(DBusConnection *conn, DBG("conn %p", conn); - if (dbus_message_iter_init(msg, &iter) == FALSE) + if (!dbus_message_iter_init(msg, &iter)) return __connman_error_invalid_arguments(msg); if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING) @@ -829,15 +852,14 @@ static DBusMessage *set_property(DBusConnection *conn, DBG("property %s", name); - if (g_str_equal(name, "Tethering") == TRUE) { + if (g_str_equal(name, "Tethering")) { + dbus_bool_t tethering; int err; - connman_bool_t tethering; if (type != DBUS_TYPE_BOOLEAN) return __connman_error_invalid_arguments(msg); - if (connman_technology_is_tethering_allowed(technology->type) - == FALSE) { + if (!connman_technology_is_tethering_allowed(technology->type)) { DBG("%s tethering not allowed by config file", __connman_service_type2string(technology->type)); return __connman_error_not_supported(msg); @@ -846,7 +868,7 @@ static DBusMessage *set_property(DBusConnection *conn, dbus_message_iter_get_basic(&value, &tethering); if (technology->tethering == tethering) { - if (tethering == FALSE) + if (!tethering) return __connman_error_already_disabled(msg); else return __connman_error_already_enabled(msg); @@ -860,7 +882,7 @@ static DBusMessage *set_property(DBusConnection *conn, technology_save(technology); - } else if (g_str_equal(name, "TetheringIdentifier") == TRUE) { + } else if (g_str_equal(name, "TetheringIdentifier")) { const char *str; dbus_message_iter_get_basic(&value, &str); @@ -882,7 +904,7 @@ static DBusMessage *set_property(DBusConnection *conn, DBUS_TYPE_STRING, &technology->tethering_ident); } - } else if (g_str_equal(name, "TetheringPassphrase") == TRUE) { + } else if (g_str_equal(name, "TetheringPassphrase")) { const char *str; dbus_message_iter_get_basic(&value, &str); @@ -904,8 +926,8 @@ static DBusMessage *set_property(DBusConnection *conn, DBUS_TYPE_STRING, &technology->tethering_passphrase); } - } else if (g_str_equal(name, "Powered") == TRUE) { - connman_bool_t enable; + } else if (g_str_equal(name, "Powered")) { + dbus_bool_t enable; if (type != DBUS_TYPE_BOOLEAN) return __connman_error_invalid_arguments(msg); @@ -925,7 +947,7 @@ static void reply_scan_pending(struct connman_technology *technology, int err) DBG("technology %p err %d", technology, err); - while (technology->scan_pending != NULL) { + while (technology->scan_pending) { DBusMessage *msg = technology->scan_pending->data; DBG("reply to %s", dbus_message_get_sender(msg)); @@ -948,22 +970,21 @@ void __connman_technology_scan_started(struct connman_device *device) DBG("device %p", device); } -void __connman_technology_scan_stopped(struct connman_device *device) +void __connman_technology_scan_stopped(struct connman_device *device, + enum connman_service_type type) { int count = 0; struct connman_technology *technology; - enum connman_service_type type; GSList *list; - type = __connman_device_get_service_type(device); technology = technology_find(type); DBG("technology %p device %p", technology, device); - if (technology == NULL) + if (!technology) return; - for (list = technology->device_list; list != NULL; list = list->next) { + for (list = technology->device_list; list; list = list->next) { struct connman_device *other_device = list->data; if (device == other_device) @@ -972,7 +993,7 @@ void __connman_technology_scan_stopped(struct connman_device *device) if (__connman_device_get_service_type(other_device) != type) continue; - if (connman_device_get_scanning(other_device) == TRUE) + if (connman_device_get_scanning(other_device)) count += 1; } @@ -983,7 +1004,7 @@ void __connman_technology_scan_stopped(struct connman_device *device) void __connman_technology_notify_regdom_by_device(struct connman_device *device, int result, const char *alpha2) { - connman_bool_t regdom_set = FALSE; + bool regdom_set = false; struct connman_technology *technology; enum connman_service_type type; GSList *tech_drivers; @@ -991,25 +1012,25 @@ void __connman_technology_notify_regdom_by_device(struct connman_device *device, type = __connman_device_get_service_type(device); technology = technology_find(type); - if (technology == NULL) + if (!technology) return; if (result < 0) { for (tech_drivers = technology->driver_list; - tech_drivers != NULL; + tech_drivers; tech_drivers = g_slist_next(tech_drivers)) { struct connman_technology_driver *driver = tech_drivers->data; - if (driver->set_regdom != NULL) { + if (driver->set_regdom) { driver->set_regdom(technology, alpha2); - regdom_set = TRUE; + regdom_set = true; } } - if (regdom_set == FALSE) + if (!regdom_set) alpha2 = NULL; } @@ -1021,7 +1042,7 @@ static DBusMessage *scan(DBusConnection *conn, DBusMessage *msg, void *data) struct connman_technology *technology = data; int err; - DBG ("technology %p request from %s", technology, + DBG("technology %p request from %s", technology, dbus_message_get_sender(msg)); dbus_message_ref(msg); @@ -1052,25 +1073,72 @@ static const GDBusSignalTable technology_signals[] = { { }, }; -static gboolean technology_dbus_register(struct connman_technology *technology) +static bool technology_dbus_register(struct connman_technology *technology) { - if (technology->dbus_registered == TRUE || - (technology->rfkill_driven == TRUE && - technology->hardblocked == TRUE)) - return TRUE; - - if (g_dbus_register_interface(connection, technology->path, - CONNMAN_TECHNOLOGY_INTERFACE, - technology_methods, technology_signals, - NULL, technology, NULL) == FALSE) { + if (technology->dbus_registered || + (technology->rfkill_driven && + technology->hardblocked)) + return true; + + if (!g_dbus_register_interface(connection, technology->path, + CONNMAN_TECHNOLOGY_INTERFACE, + technology_methods, technology_signals, + NULL, technology, NULL)) { connman_error("Failed to register %s", technology->path); - return FALSE; + return false; } technology_added_signal(technology); - technology->dbus_registered = TRUE; + technology->dbus_registered = true; + + return true; +} + +static void technology_dbus_unregister(struct connman_technology *technology) +{ + if (!technology->dbus_registered) + return; + + technology_removed_signal(technology); + g_dbus_unregister_interface(connection, technology->path, + CONNMAN_TECHNOLOGY_INTERFACE); - return TRUE; + technology->dbus_registered = false; +} + +static void technology_put(struct connman_technology *technology) +{ + DBG("technology %p", technology); + + if (__sync_sub_and_fetch(&technology->refcount, 1) > 0) + return; + + reply_scan_pending(technology, -EINTR); + + while (technology->driver_list) { + struct connman_technology_driver *driver; + + driver = technology->driver_list->data; + + if (driver->remove) + driver->remove(technology); + + technology->driver_list = + g_slist_delete_link(technology->driver_list, + technology->driver_list); + } + + technology_list = g_slist_remove(technology_list, technology); + + technology_dbus_unregister(technology); + + g_slist_free(technology->device_list); + + g_free(technology->path); + g_free(technology->regdom); + g_free(technology->tethering_ident); + g_free(technology->tethering_passphrase); + g_free(technology); } static struct connman_technology *technology_get(enum connman_service_type type) @@ -1084,12 +1152,13 @@ static struct connman_technology *technology_get(enum connman_service_type type) DBG("type %d", type); str = __connman_service_type2string(type); - if (str == NULL) + if (!str) return NULL; technology = technology_find(type); - if (technology != NULL) { - __sync_fetch_and_add(&technology->refcount, 1); + if (technology) { + if (type != CONNMAN_SERVICE_TYPE_P2P) + __sync_fetch_and_add(&technology->refcount, 1); return technology; } @@ -1103,121 +1172,139 @@ static struct connman_technology *technology_get(enum connman_service_type type) } } - if (tech_drivers == NULL) { + if (!tech_drivers) { DBG("No matching drivers found for %s.", __connman_service_type2string(type)); return NULL; } technology = g_try_new0(struct connman_technology, 1); - if (technology == NULL) + if (!technology) return NULL; technology->refcount = 1; - - technology->rfkill_driven = FALSE; - technology->softblocked = FALSE; - technology->hardblocked = FALSE; - technology->type = type; technology->path = g_strdup_printf("%s/technology/%s", CONNMAN_PATH, str); + if (type == CONNMAN_SERVICE_TYPE_P2P) { + struct connman_technology *wifi; - technology->device_list = NULL; - - technology->pending_reply = NULL; - - technology_load(technology); - - if (technology_dbus_register(technology) == FALSE) { - g_free(technology); - return NULL; + wifi = technology_find(CONNMAN_SERVICE_TYPE_WIFI); + if (wifi) + technology->enabled = wifi->enabled; } + technology_load(technology); technology_list = g_slist_prepend(technology_list, technology); - technology->driver_list = tech_drivers; - for (list = tech_drivers; list != NULL; list = g_slist_next(list)) { + for (list = tech_drivers; list; list = list->next) { driver = list->data; - if (driver->probe != NULL && driver->probe(technology) < 0) + if (driver->probe && driver->probe(technology) < 0) DBG("Driver probe failed for technology %p", technology); } + if (!technology_dbus_register(technology)) { + technology_put(technology); + return NULL; + } + DBG("technology %p", technology); return technology; } -static void technology_dbus_unregister(struct connman_technology *technology) +int connman_technology_driver_register(struct connman_technology_driver *driver) { - if (technology->dbus_registered == FALSE) - return; + GSList *list; + struct connman_device *device; + enum connman_service_type type; - technology_removed_signal(technology); - g_dbus_unregister_interface(connection, technology->path, - CONNMAN_TECHNOLOGY_INTERFACE); + for (list = driver_list; list; list = list->next) { + if (list->data == driver) + goto exist; + } - technology->dbus_registered = FALSE; -} + DBG("Registering %s driver", driver->name); -static void technology_put(struct connman_technology *technology) -{ - DBG("technology %p", technology); + driver_list = g_slist_insert_sorted(driver_list, driver, + compare_priority); - if (__sync_sub_and_fetch(&technology->refcount, 1) > 0) - return; + /* + * Check for technology less devices if this driver + * can service any of them. + */ + for (list = techless_device_list; list; list = list->next) { + device = list->data; - reply_scan_pending(technology, -EINTR); + type = __connman_device_get_service_type(device); + if (type != driver->type) + continue; - while (technology->driver_list != NULL) { - struct connman_technology_driver *driver; + techless_device_list = g_slist_remove(techless_device_list, + device); - driver = technology->driver_list->data; + __connman_technology_add_device(device); + } - if (driver->remove != NULL) - driver->remove(technology); + /* Check for orphaned rfkill switches. */ + g_hash_table_foreach(rfkill_list, rfkill_check, + GINT_TO_POINTER(driver->type)); - technology->driver_list = - g_slist_delete_link(technology->driver_list, - technology->driver_list); +exist: + if (driver->type == CONNMAN_SERVICE_TYPE_P2P) { + if (!technology_get(CONNMAN_SERVICE_TYPE_P2P)) + return -ENOMEM; } - technology_list = g_slist_remove(technology_list, technology); + return 0; +} - technology_dbus_unregister(technology); +void connman_technology_driver_unregister(struct connman_technology_driver *driver) +{ + GSList *list, *tech_drivers; + struct connman_technology *technology; + struct connman_technology_driver *current; - g_slist_free(technology->device_list); + DBG("Unregistering driver %p name %s", driver, driver->name); - g_free(technology->path); - g_free(technology->regdom); - g_free(technology->tethering_ident); - g_free(technology->tethering_passphrase); - g_free(technology); -} + for (list = technology_list; list; list = list->next) { + technology = list->data; -static void enable_tethering(struct connman_technology *technology) -{ - int ret; + for (tech_drivers = technology->driver_list; tech_drivers; + tech_drivers = g_slist_next(tech_drivers)) { + current = tech_drivers->data; + if (driver != current) + continue; - if (connman_setting_get_bool("PersistentTetheringMode") == FALSE) - return; + if (driver->remove) + driver->remove(technology); - ret = set_tethering(technology, TRUE); - if (ret < 0 && ret != -EALREADY) - DBG("Cannot enable tethering yet for %s (%d/%s)", - get_name(technology->type), - -ret, strerror(-ret)); + technology->driver_list = + g_slist_remove(technology->driver_list, + driver); + break; + } + } + + driver_list = g_slist_remove(driver_list, driver); + + if (driver->type == CONNMAN_SERVICE_TYPE_P2P) { + technology = technology_find(CONNMAN_SERVICE_TYPE_P2P); + if (technology) + technology_put(technology); + } } void __connman_technology_add_interface(enum connman_service_type type, - int index, const char *name, const char *ident) + int index, const char *ident) { struct connman_technology *technology; GSList *tech_drivers; struct connman_technology_driver *driver; + char *name; switch (type) { case CONNMAN_SERVICE_TYPE_UNKNOWN: @@ -1230,22 +1317,24 @@ void __connman_technology_add_interface(enum connman_service_type type, case CONNMAN_SERVICE_TYPE_GPS: case CONNMAN_SERVICE_TYPE_VPN: case CONNMAN_SERVICE_TYPE_GADGET: + case CONNMAN_SERVICE_TYPE_P2P: break; } + name = connman_inet_ifname(index); connman_info("Adding interface %s [ %s ]", name, __connman_service_type2string(type)); technology = technology_find(type); - if (technology == NULL) - return; + if (!technology) + goto out; - for (tech_drivers = technology->driver_list; tech_drivers != NULL; + for (tech_drivers = technology->driver_list; tech_drivers; tech_drivers = g_slist_next(tech_drivers)) { driver = tech_drivers->data; - if(driver->add_interface != NULL) + if (driver->add_interface) driver->add_interface(technology, index, name, ident); } @@ -1253,16 +1342,20 @@ void __connman_technology_add_interface(enum connman_service_type type, * At this point we can try to enable tethering automatically as * now the interfaces are set properly. */ - if (technology->tethering_persistent == TRUE) + if (technology->tethering_persistent) enable_tethering(technology); + +out: + g_free(name); } void __connman_technology_remove_interface(enum connman_service_type type, - int index, const char *name, const char *ident) + int index, const char *ident) { struct connman_technology *technology; GSList *tech_drivers; struct connman_technology_driver *driver; + char *name; switch (type) { case CONNMAN_SERVICE_TYPE_UNKNOWN: @@ -1275,22 +1368,25 @@ void __connman_technology_remove_interface(enum connman_service_type type, case CONNMAN_SERVICE_TYPE_GPS: case CONNMAN_SERVICE_TYPE_VPN: case CONNMAN_SERVICE_TYPE_GADGET: + case CONNMAN_SERVICE_TYPE_P2P: break; } + name = connman_inet_ifname(index); connman_info("Remove interface %s [ %s ]", name, __connman_service_type2string(type)); + g_free(name); technology = technology_find(type); - if (technology == NULL) + if (!technology) return; - for (tech_drivers = technology->driver_list; tech_drivers != NULL; + for (tech_drivers = technology->driver_list; tech_drivers; tech_drivers = g_slist_next(tech_drivers)) { driver = tech_drivers->data; - if(driver->remove_interface != NULL) + if (driver->remove_interface) driver->remove_interface(technology, index); } } @@ -1305,7 +1401,7 @@ int __connman_technology_add_device(struct connman_device *device) DBG("device %p type %s", device, get_name(type)); technology = technology_get(type); - if (technology == NULL) { + if (!technology) { /* * Since no driver can be found for this device at the moment we * add it to the techless device list. @@ -1317,8 +1413,8 @@ int __connman_technology_add_device(struct connman_device *device) } __sync_synchronize(); - if (technology->rfkill_driven == TRUE) { - if (technology->enabled == TRUE) + if (technology->rfkill_driven) { + if (technology->enabled) __connman_device_enable(device); else __connman_device_disable(device); @@ -1326,8 +1422,8 @@ int __connman_technology_add_device(struct connman_device *device) goto done; } - if (technology->enable_persistent == TRUE && - global_offlinemode == FALSE) { + if (technology->enable_persistent && + !global_offlinemode) { int err = __connman_device_enable(device); /* * connman_technology_add_device() calls __connman_device_enable() @@ -1339,7 +1435,7 @@ int __connman_technology_add_device(struct connman_device *device) __connman_technology_enabled(type); } /* if technology persistent state is offline */ - if (technology->enable_persistent == FALSE) + if (!technology->enable_persistent) __connman_device_disable(device); done: @@ -1359,7 +1455,7 @@ int __connman_technology_remove_device(struct connman_device *device) type = __connman_device_get_service_type(device); technology = technology_find(type); - if (technology == NULL) { + if (!technology) { techless_device_list = g_slist_remove(techless_device_list, device); return -ENXIO; @@ -1368,65 +1464,28 @@ int __connman_technology_remove_device(struct connman_device *device) technology->device_list = g_slist_remove(technology->device_list, device); - if (technology->tethering == TRUE) - set_tethering(technology, FALSE); + if (technology->tethering) + set_tethering(technology, false); technology_put(technology); return 0; } -static void powered_changed(struct connman_technology *technology) -{ - if (technology->dbus_registered == FALSE) - return; - - if (technology->pending_reply != NULL) { - g_dbus_send_reply(connection, - technology->pending_reply, DBUS_TYPE_INVALID); - dbus_message_unref(technology->pending_reply); - technology->pending_reply = NULL; - - g_source_remove(technology->pending_timeout); - technology->pending_timeout = 0; - } - - __sync_synchronize(); - connman_dbus_property_changed_basic(technology->path, - CONNMAN_TECHNOLOGY_INTERFACE, "Powered", - DBUS_TYPE_BOOLEAN, &technology->enabled); -} - -static int technology_enabled(struct connman_technology *technology) -{ - __sync_synchronize(); - if (technology->enabled == TRUE) - return -EALREADY; - - technology->enabled = TRUE; - - if (technology->tethering_persistent == TRUE) - enable_tethering(technology); - - powered_changed(technology); - - return 0; -} - int __connman_technology_enabled(enum connman_service_type type) { struct connman_technology *technology; technology = technology_find(type); - if (technology == NULL) + if (!technology) return -ENXIO; DBG("technology %p type %s rfkill %d enabled %d", technology, get_name(type), technology->rfkill_driven, technology->enabled); - if (technology->rfkill_driven == TRUE) { - if (technology->tethering_persistent == TRUE) + if (technology->rfkill_driven) { + if (technology->tethering_persistent) enable_tethering(technology); return 0; } @@ -1434,42 +1493,29 @@ int __connman_technology_enabled(enum connman_service_type type) return technology_enabled(technology); } -static int technology_disabled(struct connman_technology *technology) -{ - __sync_synchronize(); - if (technology->enabled == FALSE) - return -EALREADY; - - technology->enabled = FALSE; - - powered_changed(technology); - - return 0; -} - int __connman_technology_disabled(enum connman_service_type type) { struct connman_technology *technology; GSList *list; technology = technology_find(type); - if (technology == NULL) + if (!technology) return -ENXIO; - if (technology->rfkill_driven == TRUE) + if (technology->rfkill_driven) return 0; - for (list = technology->device_list; list != NULL; list = list->next) { + for (list = technology->device_list; list; list = list->next) { struct connman_device *device = list->data; - if (connman_device_get_powered(device) == TRUE) + if (connman_device_get_powered(device)) return 0; } return technology_disabled(technology); } -int __connman_technology_set_offlinemode(connman_bool_t offlinemode) +int __connman_technology_set_offlinemode(bool offlinemode) { GSList *list; int err = -EINVAL, enabled_tech_count = 0; @@ -1497,6 +1543,9 @@ int __connman_technology_set_offlinemode(connman_bool_t offlinemode) if (offlinemode) err = technology_disable(technology); else { + if (technology->hardblocked) + continue; + if (technology->enable_persistent) { err = technology_enable(technology); enabled_tech_count++; @@ -1515,30 +1564,32 @@ int __connman_technology_set_offlinemode(connman_bool_t offlinemode) } void __connman_technology_set_connected(enum connman_service_type type, - connman_bool_t connected) + bool connected) { struct connman_technology *technology; + dbus_bool_t val; technology = technology_find(type); - if (technology == NULL) + if (!technology) return; DBG("technology %p connected %d", technology, connected); technology->connected = connected; + val = connected; connman_dbus_property_changed_basic(technology->path, CONNMAN_TECHNOLOGY_INTERFACE, "Connected", - DBUS_TYPE_BOOLEAN, &connected); + DBUS_TYPE_BOOLEAN, &val); } -static connman_bool_t technology_apply_rfkill_change(struct connman_technology *technology, - connman_bool_t softblock, - connman_bool_t hardblock, - connman_bool_t new_rfkill) +static bool technology_apply_rfkill_change(struct connman_technology *technology, + bool softblock, + bool hardblock, + bool new_rfkill) { - gboolean hardblock_changed = FALSE; - gboolean apply = TRUE; + bool hardblock_changed = false; + bool apply = true; GList *start, *list; DBG("technology %p --> %d/%d vs %d/%d", @@ -1548,53 +1599,58 @@ static connman_bool_t technology_apply_rfkill_change(struct connman_technology * if (technology->hardblocked == hardblock) goto softblock_change; - if (!(new_rfkill == TRUE && hardblock == FALSE)) { + if (!(new_rfkill && !hardblock)) { start = g_hash_table_get_values(rfkill_list); - for (list = start; list != NULL; list = list->next) { + for (list = start; list; list = list->next) { struct connman_rfkill *rfkill = list->data; if (rfkill->type != technology->type) continue; if (rfkill->hardblock != hardblock) - apply = FALSE; + apply = false; } g_list_free(start); } - if (apply == FALSE) + if (!apply) goto softblock_change; technology->hardblocked = hardblock; - hardblock_changed = TRUE; + hardblock_changed = true; softblock_change: - if (apply == FALSE && technology->softblocked != softblock) - apply = TRUE; + if (!apply && technology->softblocked != softblock) + apply = true; - if (apply == FALSE) + if (!apply) return technology->hardblocked; technology->softblocked = softblock; - if (technology->hardblocked == TRUE || - technology->softblocked == TRUE) { + if (technology->hardblocked || + technology->softblocked) { if (technology_disabled(technology) != -EALREADY) - technology_affect_devices(technology, FALSE); - } else if (technology->hardblocked == FALSE && - technology->softblocked == FALSE) { + technology_affect_devices(technology, false); + } else if (!technology->hardblocked && + !technology->softblocked) { if (technology_enabled(technology) != -EALREADY) - technology_affect_devices(technology, TRUE); + technology_affect_devices(technology, true); } - if (hardblock_changed == TRUE) { - if (technology->hardblocked == TRUE) { + if (hardblock_changed) { + if (technology->hardblocked) { DBG("%s is switched off.", get_name(technology->type)); technology_dbus_unregister(technology); - } else + } else { + DBG("%s is switched on.", get_name(technology->type)); technology_dbus_register(technology); + + if (global_offlinemode) + __connman_rfkill_block(technology->type, true); + } } return technology->hardblocked; @@ -1602,8 +1658,8 @@ softblock_change: int __connman_technology_add_rfkill(unsigned int index, enum connman_service_type type, - connman_bool_t softblock, - connman_bool_t hardblock) + bool softblock, + bool hardblock) { struct connman_technology *technology; struct connman_rfkill *rfkill; @@ -1612,11 +1668,11 @@ int __connman_technology_add_rfkill(unsigned int index, softblock, hardblock); rfkill = g_hash_table_lookup(rfkill_list, GINT_TO_POINTER(index)); - if (rfkill != NULL) + if (rfkill) goto done; rfkill = g_try_new0(struct connman_rfkill, 1); - if (rfkill == NULL) + if (!rfkill) return -ENOMEM; rfkill->index = index; @@ -1629,36 +1685,37 @@ int __connman_technology_add_rfkill(unsigned int index, done: technology = technology_get(type); /* If there is no driver for this type, ignore it. */ - if (technology == NULL) + if (!technology) return -ENXIO; - technology->rfkill_driven = TRUE; + technology->rfkill_driven = true; /* If hardblocked, there is no need to handle softblocked state */ if (technology_apply_rfkill_change(technology, - softblock, hardblock, TRUE) == TRUE) + softblock, hardblock, true)) + return 0; + + if (global_offlinemode) return 0; /* * Depending on softblocked state we unblock/block according to * offlinemode and persistente state. */ - if (technology->softblocked == TRUE && - global_offlinemode == FALSE && - technology->enable_persistent == TRUE) - return __connman_rfkill_block(type, FALSE); - else if (technology->softblocked == FALSE && - (global_offlinemode == TRUE || - technology->enable_persistent == FALSE)) - return __connman_rfkill_block(type, TRUE); + if (technology->softblocked && + technology->enable_persistent) + return __connman_rfkill_block(type, false); + else if (!technology->softblocked && + !technology->enable_persistent) + return __connman_rfkill_block(type, true); return 0; } int __connman_technology_update_rfkill(unsigned int index, enum connman_service_type type, - connman_bool_t softblock, - connman_bool_t hardblock) + bool softblock, + bool hardblock) { struct connman_technology *technology; struct connman_rfkill *rfkill; @@ -1666,7 +1723,7 @@ int __connman_technology_update_rfkill(unsigned int index, DBG("index %u soft %u hard %u", index, softblock, hardblock); rfkill = g_hash_table_lookup(rfkill_list, GINT_TO_POINTER(index)); - if (rfkill == NULL) + if (!rfkill) return -ENXIO; if (rfkill->softblock == softblock && @@ -1678,27 +1735,17 @@ int __connman_technology_update_rfkill(unsigned int index, technology = technology_find(type); /* If there is no driver for this type, ignore it. */ - if (technology == NULL) + if (!technology) return -ENXIO; - /* If hardblocked, there is no need to handle softblocked state */ - if (technology_apply_rfkill_change(technology, - softblock, hardblock, FALSE) == TRUE) - return 0; + technology_apply_rfkill_change(technology, softblock, hardblock, + false); - if (global_offlinemode == TRUE) - return 0; - - /* - * Depending on softblocked state we unblock/block according to - * persistent state. - */ - if (technology->softblocked == TRUE && - technology->enable_persistent == TRUE) - return __connman_rfkill_block(type, FALSE); - else if (technology->softblocked == FALSE && - technology->enable_persistent == FALSE) - return __connman_rfkill_block(type, TRUE); + if (technology->hardblocked) + DBG("%s hardblocked", get_name(technology->type)); + else + DBG("%s is%s softblocked", get_name(technology->type), + technology->softblocked ? "" : " not"); return 0; } @@ -1712,17 +1759,17 @@ int __connman_technology_remove_rfkill(unsigned int index, DBG("index %u", index); rfkill = g_hash_table_lookup(rfkill_list, GINT_TO_POINTER(index)); - if (rfkill == NULL) + if (!rfkill) return -ENXIO; g_hash_table_remove(rfkill_list, GINT_TO_POINTER(index)); technology = technology_find(type); - if (technology == NULL) + if (!technology) return -ENXIO; technology_apply_rfkill_change(technology, - technology->softblocked, !technology->hardblocked, FALSE); + technology->softblocked, !technology->hardblocked, false); technology_put(technology); diff --git a/src/tethering.c b/src/tethering.c index 7042040c..c7e17f5d 100644 --- a/src/tethering.c +++ b/src/tethering.c @@ -2,7 +2,7 @@ * * Connection Manager * - * Copyright (C) 2007-2012 Intel Corporation. All rights reserved. + * Copyright (C) 2007-2013 Intel Corporation. All rights reserved. * Copyright (C) 2011 ProFUSION embedded systems * * This program is free software; you can redistribute it and/or modify @@ -133,7 +133,7 @@ static void dhcp_server_error(GDHCPServerError error) } static GDHCPServer *dhcp_server_start(const char *bridge, - const char *router, const char* subnet, + const char *router, const char *subnet, const char *start_ip, const char *end_ip, unsigned int lease_time, const char *dns) { @@ -148,7 +148,7 @@ static GDHCPServer *dhcp_server_start(const char *bridge, return NULL; dhcp_server = g_dhcp_server_new(G_DHCP_IPV4, index, &error); - if (dhcp_server == NULL) { + if (!dhcp_server) { dhcp_server_error(error); return NULL; } @@ -168,7 +168,7 @@ static GDHCPServer *dhcp_server_start(const char *bridge, static void dhcp_server_stop(GDHCPServer *server) { - if (server == NULL) + if (!server) return; g_dhcp_server_unref(server); @@ -176,6 +176,7 @@ static void dhcp_server_stop(GDHCPServer *server) static void tethering_restart(struct connman_ippool *pool, void *user_data) { + DBG("pool %p", pool); __connman_tethering_set_disabled(); __connman_tethering_set_enabled(); } @@ -207,7 +208,7 @@ void __connman_tethering_set_enabled(void) index = connman_inet_ifindex(BRIDGE_NAME); dhcp_ippool = __connman_ippool_create(index, 2, 252, tethering_restart, NULL); - if (dhcp_ippool == NULL) { + if (!dhcp_ippool) { connman_error("Fail to create IP pool"); __connman_bridge_remove(BRIDGE_NAME); __sync_fetch_and_sub(&tethering_enabled, 1); @@ -220,7 +221,9 @@ void __connman_tethering_set_enabled(void) start_ip = __connman_ippool_get_start_ip(dhcp_ippool); end_ip = __connman_ippool_get_end_ip(dhcp_ippool); - err = __connman_bridge_enable(BRIDGE_NAME, gateway, broadcast); + err = __connman_bridge_enable(BRIDGE_NAME, gateway, + __connman_ipaddress_netmask_prefix_len(subnet_mask), + broadcast); if (err < 0 && err != -EALREADY) { __connman_ippool_unref(dhcp_ippool); __connman_bridge_remove(BRIDGE_NAME); @@ -229,12 +232,12 @@ void __connman_tethering_set_enabled(void) } ns = connman_setting_get_string_list("FallbackNameservers"); - if (ns != NULL) { - if (ns[0] != NULL) { + if (ns) { + if (ns[0]) { g_free(private_network_primary_dns); private_network_primary_dns = g_strdup(ns[0]); } - if (ns[1] != NULL) { + if (ns[1]) { g_free(private_network_secondary_dns); private_network_secondary_dns = g_strdup(ns[1]); } @@ -256,7 +259,7 @@ void __connman_tethering_set_enabled(void) gateway, subnet_mask, start_ip, end_ip, 24 * 3600, dns); - if (tethering_dhcp_server == NULL) { + if (!tethering_dhcp_server) { __connman_bridge_disable(BRIDGE_NAME); __connman_ippool_unref(dhcp_ippool); __connman_bridge_remove(BRIDGE_NAME); @@ -264,9 +267,22 @@ void __connman_tethering_set_enabled(void) return; } - prefixlen = - __connman_ipaddress_netmask_prefix_len(subnet_mask); - __connman_nat_enable(BRIDGE_NAME, start_ip, prefixlen); + prefixlen = __connman_ipaddress_netmask_prefix_len(subnet_mask); + err = __connman_nat_enable(BRIDGE_NAME, start_ip, prefixlen); + if (err < 0) { + connman_error("Cannot enable NAT %d/%s", err, strerror(-err)); + dhcp_server_stop(tethering_dhcp_server); + __connman_bridge_disable(BRIDGE_NAME); + __connman_ippool_unref(dhcp_ippool); + __connman_bridge_remove(BRIDGE_NAME); + __sync_fetch_and_sub(&tethering_enabled, 1); + return; + } + + err = __connman_ipv6pd_setup(BRIDGE_NAME); + if (err < 0 && err != -EINPROGRESS) + DBG("Cannot setup IPv6 prefix delegation %d/%s", err, + strerror(-err)); DBG("tethering started"); } @@ -277,12 +293,14 @@ void __connman_tethering_set_disabled(void) DBG("enabled %d", tethering_enabled - 1); - index = connman_inet_ifindex(BRIDGE_NAME); - __connman_dnsproxy_remove_listener(index); - if (__sync_fetch_and_sub(&tethering_enabled, 1) != 1) return; + __connman_ipv6pd_cleanup(); + + index = connman_inet_ifindex(BRIDGE_NAME); + __connman_dnsproxy_remove_listener(index); + __connman_nat_disable(BRIDGE_NAME); dhcp_server_stop(tethering_dhcp_server); @@ -351,11 +369,11 @@ static void setup_tun_interface(unsigned int flags, unsigned change, DBUS_TYPE_STRING, &server_ip); connman_dbus_dict_append_basic(&dict, "PeerIPv4", DBUS_TYPE_STRING, &peer_ip); - if (pn->primary_dns != NULL) + if (pn->primary_dns) connman_dbus_dict_append_basic(&dict, "PrimaryDNS", DBUS_TYPE_STRING, &pn->primary_dns); - if (pn->secondary_dns != NULL) + if (pn->secondary_dns) connman_dbus_dict_append_basic(&dict, "SecondaryDNS", DBUS_TYPE_STRING, &pn->secondary_dns); @@ -451,7 +469,7 @@ int __connman_private_network_request(DBusMessage *msg, const char *owner) err = connman_inet_set_mtu(index, DEFAULT_MTU); pn = g_try_new0(struct connman_private_network, 1); - if (pn == NULL) { + if (!pn) { err = -ENOMEM; goto error; } @@ -462,14 +480,14 @@ int __connman_private_network_request(DBusMessage *msg, const char *owner) owner_disconnect, pn, NULL); pn->msg = msg; pn->reply = dbus_message_new_method_return(pn->msg); - if (pn->reply == NULL) + if (!pn->reply) goto error; pn->fd = fd; pn->interface = iface; pn->index = index; pn->pool = __connman_ippool_create(pn->index, 1, 1, ippool_disconnect, pn); - if (pn->pool == NULL) { + if (!pn->pool) { errno = -ENOMEM; goto error; } @@ -497,7 +515,7 @@ int __connman_private_network_release(const char *path) struct connman_private_network *pn; pn = g_hash_table_lookup(pn_hash, path); - if (pn == NULL) + if (!pn) return -EACCES; g_hash_table_remove(pn_hash, path); @@ -511,7 +529,7 @@ int __connman_tethering_init(void) tethering_enabled = 0; connection = connman_dbus_get_connection(); - if (connection == NULL) + if (!connection) return -EFAULT; pn_hash = g_hash_table_new_full(g_str_hash, g_str_equal, @@ -522,10 +540,10 @@ int __connman_tethering_init(void) void __connman_tethering_cleanup(void) { - DBG(""); + DBG("enabled %d", tethering_enabled); __sync_synchronize(); - if (tethering_enabled == 0) { + if (tethering_enabled > 0) { if (tethering_dhcp_server) dhcp_server_stop(tethering_dhcp_server); __connman_bridge_disable(BRIDGE_NAME); @@ -533,7 +551,7 @@ void __connman_tethering_cleanup(void) __connman_nat_disable(BRIDGE_NAME); } - if (connection == NULL) + if (!connection) return; g_hash_table_destroy(pn_hash); diff --git a/src/timeserver.c b/src/timeserver.c index f3c1220d..d41fa404 100644 --- a/src/timeserver.c +++ b/src/timeserver.c @@ -2,7 +2,7 @@ * * Connection Manager * - * Copyright (C) 2007-2012 Intel Corporation. All rights reserved. + * Copyright (C) 2007-2013 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 @@ -51,10 +51,10 @@ static void save_timeservers(char **servers) int cnt; keyfile = __connman_storage_load_global(); - if (keyfile == NULL) + if (!keyfile) keyfile = g_key_file_new(); - for (cnt = 0; servers != NULL && servers[cnt] != NULL; cnt++); + for (cnt = 0; servers && servers[cnt]; cnt++); g_key_file_set_string_list(keyfile, "global", "Timeservers", (const gchar **)servers, cnt); @@ -66,13 +66,13 @@ static void save_timeservers(char **servers) return; } -static char **load_timeservers() +static char **load_timeservers(void) { GKeyFile *keyfile; char **servers = NULL; keyfile = __connman_storage_load_global(); - if (keyfile == NULL) + if (!keyfile) return NULL; servers = g_key_file_get_string_list(keyfile, "global", @@ -83,14 +83,15 @@ static char **load_timeservers() return servers; } -static void resolv_result(GResolvResultStatus status, char **results, gpointer user_data) +static void resolv_result(GResolvResultStatus status, char **results, + gpointer user_data) { int i; DBG("status %d", status); if (status == G_RESOLV_RESULT_STATUS_SUCCESS) { - if (results != NULL) { + if (results) { for (i = 0; results[i]; i++) { DBG("result[%d]: %s", i, results[i]); if (i == 0) @@ -121,7 +122,7 @@ static void resolv_result(GResolvResultStatus status, char **results, gpointer u */ void __connman_timeserver_sync_next() { - if (ts_current != NULL) { + if (ts_current) { g_free(ts_current); ts_current = NULL; } @@ -129,7 +130,7 @@ void __connman_timeserver_sync_next() __connman_ntp_stop(); /* Get the 1st server in the list */ - if (ts_list == NULL) + if (!ts_list) return; ts_current = ts_list->data; @@ -158,10 +159,10 @@ GSList *__connman_timeserver_add_list(GSList *server_list, { GSList *list = server_list; - if (timeserver == NULL) + if (!timeserver) return server_list; - while (list != NULL) { + while (list) { char *existing_server = list->data; if (strcmp(timeserver, existing_server) == 0) return server_list; @@ -192,7 +193,7 @@ GSList *__connman_timeserver_get_all(struct connman_service *service) service_ts_config = connman_service_get_timeservers_config(service); /* First add Service Timeservers.Configuration to the list */ - for (i = 0; service_ts_config != NULL && service_ts_config[i] != NULL; + for (i = 0; service_ts_config && service_ts_config[i]; i++) list = __connman_timeserver_add_list(list, service_ts_config[i]); @@ -200,24 +201,24 @@ GSList *__connman_timeserver_get_all(struct connman_service *service) service_ts = connman_service_get_timeservers(service); /* First add Service Timeservers via DHCP to the list */ - for (i = 0; service_ts != NULL && service_ts[i] != NULL; i++) + for (i = 0; service_ts && service_ts[i]; i++) list = __connman_timeserver_add_list(list, service_ts[i]); network = __connman_service_get_network(service); - if (network != NULL) { + if (network) { index = connman_network_get_index(network); service_gw = __connman_ipconfig_get_gateway_from_index(index, CONNMAN_IPCONFIG_TYPE_ALL); /* Then add Service Gateway to the list */ - if (service_gw != NULL) + if (service_gw) list = __connman_timeserver_add_list(list, service_gw); } /* Then add Global Timeservers to the list */ timeservers = load_timeservers(); - for (i = 0; timeservers != NULL && timeservers[i] != NULL; i++) + for (i = 0; timeservers && timeservers[i]; i++) list = __connman_timeserver_add_list(list, timeservers[i]); g_strfreev(timeservers); @@ -225,19 +226,19 @@ GSList *__connman_timeserver_get_all(struct connman_service *service) fallback_ts = connman_setting_get_string_list("FallbackTimeservers"); /* Lastly add the fallback servers */ - for (i = 0; fallback_ts != NULL && fallback_ts[i] != NULL; i++) + for (i = 0; fallback_ts && fallback_ts[i]; i++) list = __connman_timeserver_add_list(list, fallback_ts[i]); return g_slist_reverse(list); } -static gboolean ts_recheck(void *user_data) +static gboolean ts_recheck(gpointer user_data) { GSList *ts; ts = __connman_timeserver_get_all(__connman_service_get_default()); - if (ts == NULL) { + if (!ts) { DBG("timeservers disabled"); return TRUE; @@ -268,7 +269,7 @@ static void ts_recheck_disable(void) g_source_remove(ts_recheck_id); ts_recheck_id = 0; - if (ts_current != NULL) { + if (ts_current) { g_free(ts_current); ts_current = NULL; } @@ -291,15 +292,15 @@ int __connman_timeserver_sync(struct connman_service *default_service) { struct connman_service *service; - if (default_service != NULL) + if (default_service) service = default_service; else service = __connman_service_get_default(); - if (service == NULL) + if (!service) return -EINVAL; - if (resolv == NULL) + if (!resolv) return 0; /* * Before we start creating the new timeserver list we must stop @@ -319,14 +320,14 @@ int __connman_timeserver_sync(struct connman_service *default_service) __connman_service_timeserver_changed(service, ts_list); - if (ts_list == NULL) { + if (!ts_list) { DBG("No timeservers set."); return 0; } ts_recheck_enable(); - __connman_timeserver_sync_next(); + __connman_timeserver_sync_next(); return 0; } @@ -343,21 +344,21 @@ static int timeserver_start(struct connman_service *service) return -EINVAL; nameservers = connman_service_get_nameservers(service); - if (nameservers == NULL) + if (!nameservers) return -EINVAL; /* Stop an already ongoing resolution, if there is one */ - if (resolv != NULL && resolv_id > 0) + if (resolv && resolv_id > 0) g_resolv_cancel_lookup(resolv, resolv_id); /* get rid of the old resolver */ - if (resolv != NULL) { + if (resolv) { g_resolv_unref(resolv); resolv = NULL; } resolv = g_resolv_new(i); - if (resolv == NULL) { + if (!resolv) { g_strfreev(nameservers); return -ENOMEM; } @@ -365,7 +366,7 @@ static int timeserver_start(struct connman_service *service) if (getenv("CONNMAN_RESOLV_DEBUG")) g_resolv_set_debug(resolv, resolv_debug, "RESOLV"); - for (i = 0; nameservers[i] != NULL; i++) + for (i = 0; nameservers[i]; i++) g_resolv_add_nameserver(resolv, nameservers[i], 53, 0); g_strfreev(nameservers); @@ -373,11 +374,11 @@ static int timeserver_start(struct connman_service *service) return __connman_timeserver_sync(service); } -static void timeserver_stop() +static void timeserver_stop(void) { DBG(" "); - if (resolv != NULL) { + if (resolv) { g_resolv_unref(resolv); resolv = NULL; } @@ -410,7 +411,7 @@ char **__connman_timeserver_system_get() static void default_changed(struct connman_service *default_service) { - if (default_service != NULL) + if (default_service) timeserver_start(default_service); else timeserver_stop(); diff --git a/src/timezone.c b/src/timezone.c index 2b556c28..e346b11a 100644 --- a/src/timezone.c +++ b/src/timezone.c @@ -60,7 +60,7 @@ static char *read_key_file(const char *pathname, const char *key) } map = mmap(0, st.st_size, PROT_READ, MAP_SHARED, fd, 0); - if (map == NULL || map == MAP_FAILED) { + if (!map || map == MAP_FAILED) { close(fd); return NULL; } @@ -81,25 +81,25 @@ static char *read_key_file(const char *pathname, const char *key) } ptr = memchr(ptr + 1, key[0], ptrlen - 1); - if (ptr == NULL) + if (!ptr) break; ptrlen = st.st_size - (ptr - map); } - if (ptr != NULL) { + if (ptr) { char *end, *val; ptrlen = st.st_size - (ptr - map); end = memchr(ptr, '\n', ptrlen); - if (end != NULL) + if (end) ptrlen = end - ptr; val = memchr(ptr, '"', ptrlen); - if (val != NULL) { + if (val) { end = memchr(val + 1, '"', end - val - 1); - if (end != NULL) + if (end) str = g_strndup(val + 1, end - val - 1); else str = NULL; @@ -137,10 +137,10 @@ static int compare_file(void *src_map, struct stat *src_st, } dst_map = mmap(0, dst_st.st_size, PROT_READ, MAP_SHARED, fd, 0); - if (dst_map == NULL || dst_map == MAP_FAILED) { + if (!dst_map || dst_map == MAP_FAILED) { close(fd); return -1; - } + } result = memcmp(src_map, dst_map, src_st->st_size); @@ -160,14 +160,14 @@ static char *find_origin(void *src_map, struct stat *src_st, struct stat buf; int ret; - if (subpath == NULL) - strncpy(pathname, basepath, sizeof(pathname)); + if (!subpath) + strncpy(pathname, basepath, sizeof(pathname) - 1); else snprintf(pathname, sizeof(pathname), "%s/%s", basepath, subpath); dir = opendir(pathname); - if (dir == NULL) + if (!dir) return NULL; while ((d = readdir(dir))) { @@ -179,7 +179,7 @@ static char *find_origin(void *src_map, struct stat *src_st, switch (d->d_type) { case DT_REG: - if (subpath == NULL) + if (!subpath) snprintf(pathname, PATH_MAX, "%s/%s", basepath, d->d_name); else @@ -206,14 +206,14 @@ static char *find_origin(void *src_map, struct stat *src_st, continue; /* fall through */ case DT_DIR: - if (subpath == NULL) + if (!subpath) strncpy(pathname, d->d_name, sizeof(pathname)); else snprintf(pathname, sizeof(pathname), "%s/%s", subpath, d->d_name); str = find_origin(src_map, src_st, basepath, pathname); - if (str != NULL) { + if (str) { closedir(dir); return str; } @@ -248,14 +248,14 @@ char *__connman_timezone_lookup(void) if (S_ISREG(st.st_mode)) { map = mmap(0, st.st_size, PROT_READ, MAP_SHARED, fd, 0); - if (map == NULL || map == MAP_FAILED) { + if (!map || map == MAP_FAILED) { g_free(zone); zone = NULL; goto done; } - if (zone != NULL) { + if (zone) { char pathname[PATH_MAX]; snprintf(pathname, PATH_MAX, "%s/%s", @@ -267,7 +267,7 @@ char *__connman_timezone_lookup(void) } } - if (zone == NULL) + if (!zone) zone = find_origin(map, &st, USR_SHARE_ZONEINFO, NULL); munmap(map, st.st_size); @@ -331,7 +331,7 @@ int __connman_timezone_change(const char *zone) } map = mmap(0, st.st_size, PROT_READ, MAP_SHARED, fd, 0); - if (map == NULL || map == MAP_FAILED) { + if (!map || map == MAP_FAILED) { close(fd); return -EIO; } @@ -415,7 +415,7 @@ int __connman_timezone_init(void) return -EIO; channel = g_io_channel_unix_new(fd); - if (channel == NULL) { + if (!channel) { close(fd); return -EIO; } diff --git a/src/utsname.c b/src/utsname.c index 1451c748..1dd5e0f2 100644 --- a/src/utsname.c +++ b/src/utsname.c @@ -85,11 +85,11 @@ const char *connman_utsname_get_hostname(void) DBG("driver %p name %s", driver, driver->name); - if (driver->get_hostname == NULL) + if (!driver->get_hostname) continue; hostname = driver->get_hostname(); - if (hostname != NULL) + if (hostname) return hostname; } @@ -107,7 +107,7 @@ int __connman_utsname_set_hostname(const char *hostname) DBG("driver %p name %s", driver, driver->name); - if (driver->set_hostname == NULL) + if (!driver->set_hostname) continue; if (driver->set_hostname(hostname) == 0) @@ -128,7 +128,7 @@ int __connman_utsname_set_domainname(const char *domainname) DBG("driver %p name %s", driver, driver->name); - if (driver->set_domainname == NULL) + if (!driver->set_domainname) continue; if (driver->set_domainname(domainname) == 0) diff --git a/src/wispr.c b/src/wispr.c index 94800948..dcce93cc 100644 --- a/src/wispr.c +++ b/src/wispr.c @@ -2,7 +2,7 @@ * * Connection Manager * - * Copyright (C) 2007-2012 Intel Corporation. All rights reserved. + * Copyright (C) 2007-2013 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 @@ -34,7 +34,7 @@ #define STATUS_URL_IPV6 "http://ipv6.connman.net/online/status.html" struct connman_wispr_message { - gboolean has_error; + bool has_error; const char *current_element; int message_type; int response_code; @@ -92,7 +92,7 @@ struct connman_wispr_portal { struct connman_wispr_portal_context *ipv6_context; }; -static gboolean wispr_portal_web_result(GWebResult *result, gpointer user_data); +static bool wispr_portal_web_result(GWebResult *result, gpointer user_data); static GHashTable *wispr_portal_list = NULL; @@ -100,7 +100,7 @@ static void connman_wispr_message_init(struct connman_wispr_message *msg) { DBG(""); - msg->has_error = FALSE; + msg->has_error = false; msg->current_element = NULL; msg->message_type = -1; @@ -127,13 +127,13 @@ static void connman_wispr_message_init(struct connman_wispr_message *msg) static void free_wispr_routes(struct connman_wispr_portal_context *wp_context) { - while (wp_context->route_list != NULL) { + while (wp_context->route_list) { struct wispr_route *route = wp_context->route_list->data; DBG("free route to %s if %d type %d", route->address, route->if_index, wp_context->type); - switch(wp_context->type) { + switch (wp_context->type) { case CONNMAN_IPCONFIG_TYPE_IPV4: connman_inet_del_host_route(route->if_index, route->address); @@ -155,14 +155,15 @@ static void free_wispr_routes(struct connman_wispr_portal_context *wp_context) } } -static void free_connman_wispr_portal_context(struct connman_wispr_portal_context *wp_context) +static void free_connman_wispr_portal_context( + struct connman_wispr_portal_context *wp_context) { DBG("context %p", wp_context); - if (wp_context == NULL) + if (!wp_context) return; - if (wp_context->wispr_portal != NULL) { + if (wp_context->wispr_portal) { if (wp_context->wispr_portal->ipv4_context == wp_context) wp_context->wispr_portal->ipv4_context = NULL; @@ -179,12 +180,12 @@ static void free_connman_wispr_portal_context(struct connman_wispr_portal_contex if (wp_context->timeout > 0) g_source_remove(wp_context->timeout); - if (wp_context->web != NULL) + if (wp_context->web) g_web_unref(wp_context->web); g_free(wp_context->redirect_url); - if (wp_context->wispr_parser != NULL) + if (wp_context->wispr_parser) g_web_parser_unref(wp_context->wispr_parser); connman_wispr_message_init(&wp_context->wispr_msg); @@ -209,7 +210,7 @@ static void free_connman_wispr_portal(gpointer data) DBG(""); - if (wispr_portal == NULL) + if (!wispr_portal) return; free_connman_wispr_portal_context(wispr_portal->ipv4_context); @@ -326,12 +327,11 @@ static void xml_wispr_text_handler(GMarkupParseContext *context, struct connman_wispr_message *msg = user_data; int i; - if (msg->current_element == NULL) + if (!msg->current_element) return; for (i = 0; wispr_element_map[i].str; i++) { - if (g_str_equal(wispr_element_map[i].str, - msg->current_element) == FALSE) + if (!g_str_equal(wispr_element_map[i].str, msg->current_element)) continue; switch (wispr_element_map[i].element) { @@ -380,7 +380,7 @@ static void xml_wispr_error_handler(GMarkupParseContext *context, { struct connman_wispr_message *msg = user_data; - msg->has_error = TRUE; + msg->has_error = true; } static const GMarkupParser xml_wispr_parser_handlers = { @@ -395,7 +395,7 @@ static void xml_wispr_parser_callback(const char *str, gpointer user_data) { struct connman_wispr_portal_context *wp_context = user_data; GMarkupParseContext *parser_context = NULL; - gboolean result; + bool result; DBG(""); @@ -405,7 +405,7 @@ static void xml_wispr_parser_callback(const char *str, gpointer user_data) result = g_markup_parse_context_parse(parser_context, str, strlen(str), NULL); - if (result == TRUE) + if (result) g_markup_parse_context_end_parse(parser_context, NULL); g_markup_parse_context_free(parser_context); @@ -434,19 +434,19 @@ static void portal_manage_status(GWebResult *result, /* We currently don't do anything with this info */ if (g_web_result_get_header(result, "X-ConnMan-Client-IP", - &str) == TRUE) + &str)) connman_info("Client-IP: %s", str); if (g_web_result_get_header(result, "X-ConnMan-Client-Country", - &str) == TRUE) + &str)) connman_info("Client-Country: %s", str); if (g_web_result_get_header(result, "X-ConnMan-Client-Region", - &str) == TRUE) + &str)) connman_info("Client-Region: %s", str); if (g_web_result_get_header(result, "X-ConnMan-Client-Timezone", - &str) == TRUE) + &str)) connman_info("Client-Timezone: %s", str); free_connman_wispr_portal_context(wp_context); @@ -455,7 +455,7 @@ static void portal_manage_status(GWebResult *result, CONNMAN_SERVICE_STATE_ONLINE, type); } -static gboolean wispr_route_request(const char *address, int ai_family, +static bool wispr_route_request(const char *address, int ai_family, int if_index, gpointer user_data) { int result = -1; @@ -468,16 +468,16 @@ static gboolean wispr_route_request(const char *address, int ai_family, DBG("address %s if %d gw %s", address, if_index, gateway); - if (gateway == NULL) - return FALSE; + if (!gateway) + return false; route = g_try_new0(struct wispr_route, 1); if (route == 0) { DBG("could not create struct"); - return FALSE; + return false; } - switch(wp_context->type) { + switch (wp_context->type) { case CONNMAN_IPCONFIG_TYPE_IPV4: result = connman_inet_add_host_route(if_index, address, gateway); @@ -492,17 +492,18 @@ static gboolean wispr_route_request(const char *address, int ai_family, if (result < 0) { g_free(route); - return FALSE; + return false; } route->address = g_strdup(address); route->if_index = if_index; wp_context->route_list = g_slist_prepend(wp_context->route_list, route); - return TRUE; + return true; } -static void wispr_portal_request_portal(struct connman_wispr_portal_context *wp_context) +static void wispr_portal_request_portal( + struct connman_wispr_portal_context *wp_context) { DBG(""); @@ -516,7 +517,7 @@ static void wispr_portal_request_portal(struct connman_wispr_portal_context *wp_ wispr_portal_error(wp_context); } -static gboolean wispr_input(const guint8 **data, gsize *length, +static bool wispr_input(const guint8 **data, gsize *length, gpointer user_data) { struct connman_wispr_portal_context *wp_context = user_data; @@ -544,21 +545,21 @@ static gboolean wispr_input(const guint8 **data, gsize *length, *data = (guint8 *) wp_context->wispr_formdata; *length = count; - return FALSE; + return false; } static void wispr_portal_browser_reply_cb(struct connman_service *service, - connman_bool_t authentication_done, + bool authentication_done, const char *error, void *user_data) { struct connman_wispr_portal_context *wp_context = user_data; DBG(""); - if (service == NULL || wp_context == NULL) + if (!service || !wp_context) return; - if (authentication_done == FALSE) { + if (!authentication_done) { wispr_portal_error(wp_context); free_wispr_routes(wp_context); return; @@ -569,17 +570,17 @@ static void wispr_portal_browser_reply_cb(struct connman_service *service, } static void wispr_portal_request_wispr_login(struct connman_service *service, - connman_bool_t success, + bool success, const char *ssid, int ssid_len, const char *username, const char *password, - gboolean wps, const char *wpspin, + bool wps, const char *wpspin, const char *error, void *user_data) { struct connman_wispr_portal_context *wp_context = user_data; DBG(""); - if (error != NULL) { + if (error) { if (g_strcmp0(error, "net.connman.Agent.Error.LaunchBrowser") == 0) { if (__connman_agent_request_browser(service, @@ -608,7 +609,7 @@ static void wispr_portal_request_wispr_login(struct connman_service *service, connman_wispr_message_init(&wp_context->wispr_msg); } -static gboolean wispr_manage_message(GWebResult *result, +static bool wispr_manage_message(GWebResult *result, struct connman_wispr_portal_context *wp_context) { DBG("Message type: %s (%d)", @@ -618,21 +619,21 @@ static gboolean wispr_manage_message(GWebResult *result, response_code_to_string(wp_context->wispr_msg.response_code), wp_context->wispr_msg.response_code); - if (wp_context->wispr_msg.access_procedure != NULL) + if (wp_context->wispr_msg.access_procedure) DBG("Access procedure: %s", wp_context->wispr_msg.access_procedure); - if (wp_context->wispr_msg.access_location != NULL) + if (wp_context->wispr_msg.access_location) DBG("Access location: %s", wp_context->wispr_msg.access_location); - if (wp_context->wispr_msg.location_name != NULL) + if (wp_context->wispr_msg.location_name) DBG("Location name: %s", wp_context->wispr_msg.location_name); - if (wp_context->wispr_msg.login_url != NULL) + if (wp_context->wispr_msg.login_url) DBG("Login URL: %s", wp_context->wispr_msg.login_url); - if (wp_context->wispr_msg.abort_login_url != NULL) + if (wp_context->wispr_msg.abort_login_url) DBG("Abort login URL: %s", wp_context->wispr_msg.abort_login_url); - if (wp_context->wispr_msg.logoff_url != NULL) + if (wp_context->wispr_msg.logoff_url) DBG("Logoff URL: %s", wp_context->wispr_msg.logoff_url); switch (wp_context->wispr_msg.message_type) { @@ -645,6 +646,8 @@ static gboolean wispr_manage_message(GWebResult *result, wispr_portal_request_wispr_login, wp_context) != -EINPROGRESS) wispr_portal_error(wp_context); + else + return true; break; case 120: /* Falling down */ @@ -663,7 +666,7 @@ static gboolean wispr_manage_message(GWebResult *result, wispr_portal_request_portal(wp_context); - return TRUE; + return true; } else wispr_portal_error(wp_context); @@ -672,10 +675,10 @@ static gboolean wispr_manage_message(GWebResult *result, break; } - return FALSE; + return false; } -static gboolean wispr_portal_web_result(GWebResult *result, gpointer user_data) +static bool wispr_portal_web_result(GWebResult *result, gpointer user_data) { struct connman_wispr_portal_context *wp_context = user_data; const char *redirect = NULL; @@ -692,13 +695,13 @@ static gboolean wispr_portal_web_result(GWebResult *result, gpointer user_data) if (length > 0) { g_web_parser_feed_data(wp_context->wispr_parser, chunk, length); - return TRUE; + return true; } g_web_parser_end_data(wp_context->wispr_parser); if (wp_context->wispr_msg.message_type >= 0) { - if (wispr_manage_message(result, wp_context) == TRUE) + if (wispr_manage_message(result, wp_context)) goto done; } } @@ -713,20 +716,19 @@ static gboolean wispr_portal_web_result(GWebResult *result, gpointer user_data) break; if (g_web_result_get_header(result, "X-ConnMan-Status", - &str) == TRUE) { + &str)) { portal_manage_status(result, wp_context); - return FALSE; - } - else + return false; + } else __connman_agent_request_browser(wp_context->service, wispr_portal_browser_reply_cb, wp_context->redirect_url, wp_context); break; case 302: - if (g_web_supports_tls() == FALSE || - g_web_result_get_header(result, "Location", - &redirect) == FALSE) { + if (!g_web_supports_tls() || + !g_web_result_get_header(result, "Location", + &redirect)) { __connman_agent_request_browser(wp_context->service, wispr_portal_browser_reply_cb, @@ -749,7 +751,7 @@ static gboolean wispr_portal_web_result(GWebResult *result, gpointer user_data) wp_context->type) == 0) { wispr_portal_error(wp_context); free_connman_wispr_portal_context(wp_context); - return FALSE; + return false; } break; @@ -761,7 +763,7 @@ static gboolean wispr_portal_web_result(GWebResult *result, gpointer user_data) wp_context->request_id = 0; done: wp_context->wispr_msg.message_type = -1; - return FALSE; + return false; } static void proxy_callback(const char *proxy, void *user_data) @@ -770,13 +772,18 @@ static void proxy_callback(const char *proxy, void *user_data) DBG("proxy %s", proxy); - if (wp_context == NULL) + if (!wp_context) return; wp_context->token = 0; - if (proxy != NULL && g_strcmp0(proxy, "DIRECT") != 0) + if (proxy && g_strcmp0(proxy, "DIRECT") != 0) { + if (g_str_has_prefix(proxy, "PROXY")) { + proxy += 5; + for (; *proxy == ' ' && *proxy != '\0'; proxy++); + } g_web_set_proxy(wp_context->web, proxy); + } g_web_set_accept(wp_context->web, NULL); g_web_set_user_agent(wp_context->web, "ConnMan/%s wispr", VERSION); @@ -823,17 +830,18 @@ static int wispr_portal_detect(struct connman_wispr_portal_context *wp_context) case CONNMAN_SERVICE_TYPE_WIFI: case CONNMAN_SERVICE_TYPE_BLUETOOTH: case CONNMAN_SERVICE_TYPE_CELLULAR: + case CONNMAN_SERVICE_TYPE_GADGET: break; case CONNMAN_SERVICE_TYPE_UNKNOWN: case CONNMAN_SERVICE_TYPE_SYSTEM: case CONNMAN_SERVICE_TYPE_GPS: case CONNMAN_SERVICE_TYPE_VPN: - case CONNMAN_SERVICE_TYPE_GADGET: + case CONNMAN_SERVICE_TYPE_P2P: return -EOPNOTSUPP; } interface = connman_service_get_interface(wp_context->service); - if (interface == NULL) + if (!interface) return -EINVAL; DBG("interface %s", interface); @@ -846,14 +854,14 @@ static int wispr_portal_detect(struct connman_wispr_portal_context *wp_context) } nameservers = connman_service_get_nameservers(wp_context->service); - if (nameservers == NULL) { + if (!nameservers) { DBG("Could not get nameservers"); err = -EINVAL; goto done; } wp_context->web = g_web_new(if_index); - if (wp_context->web == NULL) { + if (!wp_context->web) { DBG("Could not set up GWeb"); err = -ENOMEM; goto done; @@ -870,7 +878,7 @@ static int wispr_portal_detect(struct connman_wispr_portal_context *wp_context) wp_context->status_url = STATUS_URL_IPV6; } - for (i = 0; nameservers[i] != NULL; i++) + for (i = 0; nameservers[i]; i++) g_web_add_nameserver(wp_context->web, nameservers[i]); proxy_method = connman_service_get_proxy_method(wp_context->service); @@ -906,7 +914,7 @@ int __connman_wispr_start(struct connman_service *service, DBG("service %p", service); - if (wispr_portal_list == NULL) + if (!wispr_portal_list) return -EINVAL; index = __connman_service_get_index(service); @@ -915,9 +923,9 @@ int __connman_wispr_start(struct connman_service *service, wispr_portal = g_hash_table_lookup(wispr_portal_list, GINT_TO_POINTER(index)); - if (wispr_portal == NULL) { + if (!wispr_portal) { wispr_portal = g_try_new0(struct connman_wispr_portal, 1); - if (wispr_portal == NULL) + if (!wispr_portal) return -ENOMEM; g_hash_table_replace(wispr_portal_list, @@ -932,11 +940,11 @@ int __connman_wispr_start(struct connman_service *service, return -EINVAL; /* If there is already an existing context, we wipe it */ - if (wp_context != NULL) + if (wp_context) free_connman_wispr_portal_context(wp_context); wp_context = create_wispr_portal_context(); - if (wp_context == NULL) + if (!wp_context) return -ENOMEM; wp_context->service = service; @@ -957,7 +965,7 @@ void __connman_wispr_stop(struct connman_service *service) DBG("service %p", service); - if (wispr_portal_list == NULL) + if (!wispr_portal_list) return; index = __connman_service_get_index(service); @@ -53,7 +53,7 @@ static void free_wpad(gpointer data) g_strfreev(wpad->addrlist); g_free(wpad->hostname); - g_free(wpad); + g_free(wpad); } static void download_pac(struct connman_wpad *wpad, const char *target) @@ -72,7 +72,7 @@ static void wpad_result(GResolvResultStatus status, if (status == G_RESOLV_RESULT_STATUS_SUCCESS) { char *url; - if (results == NULL || g_strv_length(results) == 0) + if (!results || g_strv_length(results) == 0) goto failed; url = g_strdup_printf("http://%s/wpad.dat", wpad->hostname); @@ -80,7 +80,7 @@ static void wpad_result(GResolvResultStatus status, __connman_service_set_proxy_autoconfig(wpad->service, url); wpad->addrlist = g_strdupv(results); - if (wpad->addrlist != NULL) + if (wpad->addrlist) download_pac(wpad, "wpad.dat"); g_free(url); @@ -97,10 +97,10 @@ static void wpad_result(GResolvResultStatus status, goto failed; ptr = strchr(hostname + 5, '.'); - if (ptr == NULL || strlen(ptr) < 2) + if (!ptr || strlen(ptr) < 2) goto failed; - if (strchr(ptr + 1, '.') == NULL) + if (!strchr(ptr + 1, '.')) goto failed; wpad->hostname = g_strdup_printf("wpad.%s", ptr + 1); @@ -131,7 +131,7 @@ int __connman_wpad_start(struct connman_service *service) DBG("service %p", service); - if (wpad_list == NULL) + if (!wpad_list) return -EINVAL; index = __connman_service_get_index(service); @@ -139,22 +139,22 @@ int __connman_wpad_start(struct connman_service *service) return -EINVAL; domainname = connman_service_get_domainname(service); - if (domainname == NULL) + if (!domainname) return -EINVAL; nameservers = connman_service_get_nameservers(service); - if (nameservers == NULL) + if (!nameservers) return -EINVAL; wpad = g_try_new0(struct connman_wpad, 1); - if (wpad == NULL) { + if (!wpad) { g_strfreev(nameservers); return -ENOMEM; } wpad->service = service; wpad->resolv = g_resolv_new(index); - if (wpad->resolv == NULL) { + if (!wpad->resolv) { g_strfreev(nameservers); g_free(wpad); return -ENOMEM; @@ -163,7 +163,7 @@ int __connman_wpad_start(struct connman_service *service) if (getenv("CONNMAN_RESOLV_DEBUG")) g_resolv_set_debug(wpad->resolv, resolv_debug, "RESOLV"); - for (i = 0; nameservers[i] != NULL; i++) + for (i = 0; nameservers[i]; i++) g_resolv_add_nameserver(wpad->resolv, nameservers[i], 53, 0); g_strfreev(nameservers); @@ -187,14 +187,14 @@ void __connman_wpad_stop(struct connman_service *service) DBG("service %p", service); - if (wpad_list == NULL) + if (!wpad_list) return; index = __connman_service_get_index(service); if (index < 0) return; - if (g_hash_table_remove(wpad_list, GINT_TO_POINTER(index)) == TRUE) + if (g_hash_table_remove(wpad_list, GINT_TO_POINTER(index))) connman_service_unref(service); } |