]> git.ipfire.org Git - thirdparty/dhcpcd.git/commitdiff
Linux can now detect address addition and removal too.
authorRoy Marples <roy@marples.name>
Thu, 19 Mar 2009 22:27:13 +0000 (22:27 +0000)
committerRoy Marples <roy@marples.name>
Thu, 19 Mar 2009 22:27:13 +0000 (22:27 +0000)
dhcpcd.c
if-linux.c

index 1805265c4f5dca0123a9091efe395505ac6f0273..53952259afe9a3983a07c8dece2c557fa9144632 100644 (file)
--- a/dhcpcd.c
+++ b/dhcpcd.c
@@ -1192,7 +1192,7 @@ handle_ifa(int type, const char *ifname,
 static void
 handle_link(_unused void *arg)
 {
-       if (manage_link(linkfd))
+       if (manage_link(linkfd) == -1)
                syslog(LOG_ERR, "manage_link: %m");
 }
 
index 8c9c945cbc2acd20719b49122b5989327179d268..ad58e2a92569284a2c094cc2f585e8bc1752bb11 100644 (file)
@@ -94,7 +94,7 @@ open_link_socket(void)
        struct sockaddr_nl snl;
 
        memset(&snl, 0, sizeof(snl));
-       snl.nl_groups = RTMGRP_LINK | RTMGRP_IPV4_ROUTE;
+       snl.nl_groups = RTMGRP_LINK | RTMGRP_IPV4_ROUTE | RTMGRP_IPV4_IFADDR;
        return _open_link_socket(&snl);
 }
 
@@ -155,7 +155,7 @@ err_netlink(struct nlmsghdr *nlm)
 }
 
 static int
-link_delroute(struct nlmsghdr *nlm)
+link_route(struct nlmsghdr *nlm)
 {
        int len, idx, metric;
        struct rtattr *rta;
@@ -163,6 +163,9 @@ link_delroute(struct nlmsghdr *nlm)
        struct rt rt;
        char ifn[IF_NAMESIZE + 1];
 
+       if (nlm->nlmsg_type != RTM_DELROUTE)
+               return 0;
+
        len = nlm->nlmsg_len - sizeof(*nlm);
        if ((size_t)len < sizeof(*rtm)) {
                errno = EBADMSG;
@@ -211,6 +214,55 @@ link_delroute(struct nlmsghdr *nlm)
        return 1;
 }
 
+static int
+link_addr(struct nlmsghdr *nlm)
+{
+       int len;
+       struct rtattr *rta;
+       struct ifaddrmsg *ifa;
+       struct in_addr addr, net, dest;
+       char ifn[IF_NAMESIZE + 1];
+       struct interface *iface;
+
+       if (nlm->nlmsg_type != RTM_DELADDR && nlm->nlmsg_type != RTM_NEWADDR)
+               return 0;
+
+       len = nlm->nlmsg_len - sizeof(*nlm);
+       if ((size_t)len < sizeof(*ifa)) {
+               errno = EBADMSG;
+               return -1;
+       }
+       if (nlm->nlmsg_pid == (uint32_t)getpid())
+               return 1;
+       ifa = NLMSG_DATA(nlm);
+       if (if_indextoname(ifa->ifa_index, ifn) == NULL)
+               return -1;
+       iface = find_interface(ifn);
+       if (iface == NULL)
+               return 1;
+       rta = (struct rtattr *) IFA_RTA(ifa);
+       len = NLMSG_PAYLOAD(nlm, sizeof(*ifa));
+       addr.s_addr = dest.s_addr = INADDR_ANY;
+       inet_cidrtoaddr(ifa->ifa_prefixlen, &net);
+       while (RTA_OK(rta, len)) {
+               switch (rta->rta_type) {
+               case IFA_ADDRESS:
+                       if (iface->flags & IFF_POINTOPOINT) {
+                               memcpy(&dest.s_addr, RTA_DATA(rta),
+                                   sizeof(addr.s_addr));
+                       }
+                       break;
+               case IFA_LOCAL:
+                       memcpy(&addr.s_addr, RTA_DATA(rta),
+                           sizeof(addr.s_addr));
+                       break;
+               }
+               rta = RTA_NEXT(rta, len);
+       }
+       handle_ifa(nlm->nlmsg_type, ifn, &addr, &net, &dest);
+       return 1;
+}
+
 static int
 link_netlink(struct nlmsghdr *nlm)
 {
@@ -219,8 +271,12 @@ link_netlink(struct nlmsghdr *nlm)
        struct ifinfomsg *ifi;
        char ifn[IF_NAMESIZE + 1];
 
-       if (nlm->nlmsg_type == RTM_DELROUTE)
-               return link_delroute(nlm);
+       len = link_route(nlm);
+       if (len != 0)
+               return len;
+       len = link_addr(nlm);
+       if (len != 0)
+               return len;
 
        if (nlm->nlmsg_type != RTM_NEWLINK && nlm->nlmsg_type != RTM_DELLINK)
                return 0;