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 __conn |