X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=src%2Frtnl.c;h=4e7ef4d5be0c169dfaeae522ba2373f574660c94;hb=89077bfd2abf7984027552c8cee223a0c6dab57c;hp=39afb12b6f5aa4e77ae8f638eef20448840a5468;hpb=3866231ce4dd27533e086490b84b5363d788721d;p=framework%2Fconnectivity%2Fconnman.git diff --git a/src/rtnl.c b/src/rtnl.c index 39afb12..4e7ef4d 100644 --- a/src/rtnl.c +++ b/src/rtnl.c @@ -2,7 +2,7 @@ * * Connection Manager * - * Copyright (C) 2007-2010 Intel Corporation. All rights reserved. + * Copyright (C) 2007-2012 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 @@ -90,16 +90,7 @@ static connman_bool_t ether_blacklisted(const char *name) if (name == NULL) return TRUE; - /* virtual interface from VMware */ - if (g_str_has_prefix(name, "vmnet") == TRUE) - return TRUE; - - /* virtual interface from VirtualBox */ - if (g_str_has_prefix(name, "vboxnet") == TRUE) - return TRUE; - - /* virtual interface from Virtual Machine Manager */ - if (g_str_has_prefix(name, "virbr") == TRUE) + if (__connman_device_isfiltered(name) == TRUE) return TRUE; return FALSE; @@ -291,7 +282,9 @@ static void trigger_rtnl(int index, void *user_data) } if (rtnl->newgateway) { - const char *gateway = __connman_ipconfig_get_gateway_from_index(index); + const char *gateway = + __connman_ipconfig_get_gateway_from_index(index, + CONNMAN_IPCONFIG_TYPE_ALL); if (gateway != NULL) rtnl->newgateway(index, gateway); @@ -601,6 +594,20 @@ static void process_newaddr(unsigned char family, unsigned char prefixlen, __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. + */ + char *interface = connman_inet_ifname(index); + + __connman_resolver_redo_servers(interface); + + g_free(interface); + } } static void process_deladdr(unsigned char family, unsigned char prefixlen, @@ -1173,22 +1180,22 @@ static const char **rtnl_nd_opt_dnssl(struct nd_opt_hdr *opt, guint32 *lifetime) static void rtnl_newnduseropt(struct nlmsghdr *hdr) { struct nduseroptmsg *msg = (struct nduseroptmsg *) NLMSG_DATA(hdr); - struct nd_opt_hdr *opt = (void *)&msg[1]; + struct nd_opt_hdr *opt; guint32 lifetime = -1; const char **domains = NULL; struct in6_addr *servers = NULL; - int nr_servers = 0; + int i, nr_servers = 0; int msglen = msg->nduseropt_opts_len; char *interface; - DBG("family %02x index %x len %04x type %02x code %02x", - msg->nduseropt_family, msg->nduseropt_ifindex, - msg->nduseropt_opts_len, msg->nduseropt_icmp_type, - msg->nduseropt_icmp_code); + DBG("family %d index %d len %d type %d code %d", + msg->nduseropt_family, msg->nduseropt_ifindex, + msg->nduseropt_opts_len, msg->nduseropt_icmp_type, + msg->nduseropt_icmp_code); if (msg->nduseropt_family != AF_INET6 || - msg->nduseropt_icmp_type != ND_ROUTER_ADVERT || - msg->nduseropt_icmp_code != 0) + msg->nduseropt_icmp_type != ND_ROUTER_ADVERT || + msg->nduseropt_icmp_code != 0) return; interface = connman_inet_ifname(msg->nduseropt_ifindex); @@ -1196,40 +1203,37 @@ static void rtnl_newnduseropt(struct nlmsghdr *hdr) return; for (opt = (void *)&msg[1]; - msglen >= 2 && msglen >= opt->nd_opt_len && opt->nd_opt_len; - msglen -= opt->nd_opt_len, - opt = ((void *)opt) + opt->nd_opt_len*8) { - - DBG("nd opt type %d len %d\n", - opt->nd_opt_type, opt->nd_opt_len); + msglen > 0; + msglen -= opt->nd_opt_len * 8, + opt = ((void *)opt) + opt->nd_opt_len*8) { - if (opt->nd_opt_type == 25) - servers = rtnl_nd_opt_rdnss(opt, &lifetime, - &nr_servers); - else if (opt->nd_opt_type == 31) - domains = rtnl_nd_opt_dnssl(opt, &lifetime); - } + DBG("remaining %d nd opt type %d len %d\n", + msglen, opt->nd_opt_type, opt->nd_opt_len); - if (nr_servers) { - int i, j; - char buf[40]; + if (opt->nd_opt_type == 25) { /* ND_OPT_RDNSS */ + char buf[40]; - for (i = 0; i < nr_servers; i++) { - if (!inet_ntop(AF_INET6, servers + i, buf, sizeof(buf))) - continue; + servers = rtnl_nd_opt_rdnss(opt, &lifetime, + &nr_servers); + for (i = 0; i < nr_servers; i++) { + if (!inet_ntop(AF_INET6, servers + i, buf, + sizeof(buf))) + continue; - if (domains == NULL || domains[0] == NULL) { connman_resolver_append_lifetime(interface, NULL, buf, lifetime); - continue; } - for (j = 0; domains[j]; j++) + } else if (opt->nd_opt_type == 31) { /* ND_OPT_DNSSL */ + g_free(domains); + + domains = rtnl_nd_opt_dnssl(opt, &lifetime); + for (i = 0; domains != NULL && domains[i] != NULL; i++) connman_resolver_append_lifetime(interface, - domains[j], - buf, lifetime); + domains[i], NULL, lifetime); } } + g_free(domains); g_free(interface); } @@ -1251,6 +1255,8 @@ static const char *type2string(uint16_t type) return "NEWLINK"; case RTM_DELLINK: return "DELLINK"; + case RTM_GETADDR: + return "GETADDR"; case RTM_NEWADDR: return "NEWADDR"; case RTM_DELADDR: @@ -1352,10 +1358,11 @@ static void rtnl_message(void *buf, size_t len) if (!NLMSG_OK(hdr, len)) break; - DBG("%s len %d type %d flags 0x%04x seq %d", + DBG("%s len %d type %d flags 0x%04x seq %d pid %d", type2string(hdr->nlmsg_type), hdr->nlmsg_len, hdr->nlmsg_type, - hdr->nlmsg_flags, hdr->nlmsg_seq); + hdr->nlmsg_flags, hdr->nlmsg_seq, + hdr->nlmsg_pid); switch (hdr->nlmsg_type) { case NLMSG_NOOP: @@ -1401,27 +1408,37 @@ static gboolean netlink_event(GIOChannel *chan, GIOCondition cond, gpointer data) { unsigned char buf[4096]; - gsize len; - GIOStatus status; + struct sockaddr_nl nladdr; + socklen_t addr_len = sizeof(nladdr); + ssize_t status; + int fd; if (cond & (G_IO_NVAL | G_IO_HUP | G_IO_ERR)) return FALSE; memset(buf, 0, sizeof(buf)); + memset(&nladdr, 0, sizeof(nladdr)); - status = g_io_channel_read_chars(chan, (gchar *) buf, - sizeof(buf), &len, NULL); + fd = g_io_channel_unix_get_fd(chan); - switch (status) { - case G_IO_STATUS_NORMAL: - break; - case G_IO_STATUS_AGAIN: - return TRUE; - default: + status = recvfrom(fd, buf, sizeof(buf), 0, + (struct sockaddr *) &nladdr, &addr_len); + if (status < 0) { + if (errno == EINTR || errno == EAGAIN) + return TRUE; + + return FALSE; + } + + if (status == 0) return FALSE; + + if (nladdr.nl_pid != 0) { /* not sent by kernel, ignore */ + DBG("Received msg from %u, ignoring it", nladdr.nl_pid); + return TRUE; } - rtnl_message(buf, len); + rtnl_message(buf, status); return TRUE; }