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