This much works fine... suppose I need to hook it up to actually *use*
the nameservers it finds rather than just printing debug messages about
them.... any comments?

diff --git a/src/rtnl.c b/src/rtnl.c
index 1993493..89296b5 100644
--- a/src/rtnl.c
+++ b/src/rtnl.c
@@ -30,6 +30,7 @@
 #include <sys/ioctl.h>
 #include <arpa/inet.h>
 #include <netinet/ether.h>
+#include <netinet/icmp6.h>
 #include <net/if_arp.h>
 #include <linux/if.h>
 #include <linux/netlink.h>
@@ -1020,6 +1021,57 @@ static void rtnl_delroute(struct nlmsghdr *hdr)
                                                msg, RTM_PAYLOAD(hdr));
 }
 
+static void add_rdnss_server(guint32 lifetime, char *server)
+{
+       DBG("lifetime %d server %s", lifetime, server);
+}
+
+static void rtnl_nd_opt_rdnss(struct nd_opt_hdr *opt)
+{
+       guint32 *optint = (void *)opt;
+       guint32 lifetime;
+       char buf[80];
+       int i;
+
+       if (opt->nd_opt_len < 3)
+               return;
+
+       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)))
+                       add_rdnss_server(lifetime, buf);
+       }
+}
+
+static void rtnl_newnduseropt(struct nlmsghdr *hdr)
+{
+       struct nduseroptmsg *msg = (struct nduseroptmsg *) NLMSG_DATA(hdr);
+       struct nd_opt_hdr *opt = (void *)&msg[1];
+       int msglen = msg->nduseropt_opts_len;
+
+       DBG("family %02x len %04x type %02x code %02x",
+           msg->nduseropt_family, 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)
+               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);
+
+               if (opt->nd_opt_type == 25)
+                       rtnl_nd_opt_rdnss(opt);
+       }
+}
+
 static const char *type2string(uint16_t type)
 {
        switch (type) {
@@ -1047,6 +1099,8 @@ static const char *type2string(uint16_t type)
                return "NEWROUTE";
        case RTM_DELROUTE:
                return "DELROUTE";
+       case RTM_NEWNDUSEROPT:
+               return "NEWNDUSEROPT";
        default:
                return "UNKNOWN";
        }
@@ -1171,6 +1225,9 @@ static void rtnl_message(void *buf, size_t len)
                case RTM_DELROUTE:
                        rtnl_delroute(hdr);
                        break;
+               case RTM_NEWNDUSEROPT:
+                       rtnl_newnduseropt(hdr);
+                       break;
                }
 
                len -= hdr->nlmsg_len;
@@ -1351,7 +1408,8 @@ int __connman_rtnl_init(void)
        memset(&addr, 0, sizeof(addr));
        addr.nl_family = AF_NETLINK;
        addr.nl_groups = RTMGRP_LINK | RTMGRP_IPV4_IFADDR | RTMGRP_IPV4_ROUTE |
-                               RTMGRP_IPV6_IFADDR | RTMGRP_IPV6_ROUTE;
+                               RTMGRP_IPV6_IFADDR | RTMGRP_IPV6_ROUTE |
+                               (1<<(RTNLGRP_ND_USEROPT-1));
 
        if (bind(sk, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
                close(sk);

-- 
dwmw2

_______________________________________________
connman mailing list
[email protected]
http://lists.connman.net/listinfo/connman

Reply via email to