diff options
author | David Woodhouse <dwmw2@infradead.org> | 2010-12-17 22:31:30 +0000 |
---|---|---|
committer | Samuel Ortiz <sameo@linux.intel.com> | 2010-12-21 16:55:05 +0100 |
commit | 5254c601b9a89660f901bb1927e3b80e8adc7bc0 (patch) | |
tree | 1cddd770d846bc2548747a43be6317664ac7ae10 /src/rtnl.c | |
parent | 1339c2b9108c95d65b1eb2ada00c64be76008e5d (diff) | |
download | connman-5254c601b9a89660f901bb1927e3b80e8adc7bc0.tar.gz connman-5254c601b9a89660f901bb1927e3b80e8adc7bc0.tar.bz2 connman-5254c601b9a89660f901bb1927e3b80e8adc7bc0.zip |
rtnl: Refactor RDNSS support so we can support DNSSL
Rather than registering the new nameserver as we hit the RDNSS option,
gather all the information first and then register the nameservers
after the loop.
That way, we can gather the search domains while we're looping, and
provide them when we register the nameservers.
Diffstat (limited to 'src/rtnl.c')
-rw-r--r-- | src/rtnl.c | 43 |
1 files changed, 28 insertions, 15 deletions
@@ -1024,32 +1024,33 @@ static void rtnl_delroute(struct nlmsghdr *hdr) msg, RTM_PAYLOAD(hdr)); } -static void rtnl_nd_opt_rdnss(char *interface, struct nd_opt_hdr *opt) +static void *rtnl_nd_opt_rdnss(struct nd_opt_hdr *opt, guint32 *lifetime, + int *nr_servers) { guint32 *optint = (void *)opt; - guint32 lifetime; - char buf[80]; - int i; if (opt->nd_opt_len < 3) - return; + return NULL; - lifetime = ntohl(optint[1]); - if (!lifetime) - return; + if (*lifetime > ntohl(optint[1])) + *lifetime = ntohl(optint[1]); - optint += 2; - for (i = 0; i < opt->nd_opt_len / 2; i++, optint += 4) { - if (inet_ntop(AF_INET6, optint, buf, sizeof(buf))) - connman_resolver_append_lifetime(interface, NULL, - buf, lifetime); - } + /* nd_opt_len is in units of 8 bytes. The header is 1 unit (8 bytes) + and each address is another 2 units (16 bytes). + So the number of addresses (given rounding) is nd_opt_len/2 */ + *nr_servers = opt->nd_opt_len / 2; + + /* And they start 8 bytes into the packet, or two guint32s in. */ + return optint + 2; } static void rtnl_newnduseropt(struct nlmsghdr *hdr) { struct nduseroptmsg *msg = (struct nduseroptmsg *) NLMSG_DATA(hdr); struct nd_opt_hdr *opt = (void *)&msg[1]; + guint32 lifetime = -1; + struct in6_addr *servers; + int nr_servers = 0; int msglen = msg->nduseropt_opts_len; char *interface; @@ -1076,7 +1077,19 @@ static void rtnl_newnduseropt(struct nlmsghdr *hdr) opt->nd_opt_type, opt->nd_opt_len); if (opt->nd_opt_type == 25) - rtnl_nd_opt_rdnss(interface, opt); + servers = rtnl_nd_opt_rdnss(opt, &lifetime, + &nr_servers); + } + + if (nr_servers) { + int i; + char buf[40]; + + for (i = 0; i < nr_servers; i++) { + if (inet_ntop(AF_INET6, servers + i, buf, sizeof(buf))) + connman_resolver_append_lifetime(interface, + NULL, buf, lifetime); + } } g_free(interface); } |