]> git.ipfire.org Git - thirdparty/dhcpcd.git/commitdiff
Support RTM_CHGADDR in NetBSD-6 for detecting link layer address changes.
authorRoy Marples <roy@marples.name>
Fri, 12 Nov 2010 16:33:45 +0000 (16:33 +0000)
committerRoy Marples <roy@marples.name>
Fri, 12 Nov 2010 16:33:45 +0000 (16:33 +0000)
dhcpcd.c
dhcpcd.h
if-bsd.c

index 54acd1fa23ceacb68d736e1c0af5b498fe8099b3..a0860e393dbf487483bc603a8be64d28b46aa1f6 100644 (file)
--- a/dhcpcd.c
+++ b/dhcpcd.c
@@ -1281,6 +1281,41 @@ handle_interface(int action, const char *ifname)
        }
 }
 
+void
+handle_hwaddr(const char *ifname, unsigned char *hwaddr, size_t hwlen)
+{
+       struct interface *ifp;
+       struct if_options *ifo;
+
+       for (ifp = ifaces; ifp; ifp = ifp->next)
+               if (strcmp(ifp->name, ifname) == 0 && ifp->hwlen <= hwlen) {
+                       ifo = ifp->state->options;
+                       if (!(ifo->options &
+                           (DHCPCD_INFORM | DHCPCD_STATIC | DHCPCD_CLIENTID))
+                           && ifp->state->new != NULL &&
+                           ifp->state->new->cookie == htonl(MAGIC_COOKIE))
+                       {
+                               syslog(LOG_INFO,
+                                   "%s: expiring for new hardware address",
+                                   ifp->name);
+                               drop_config(ifp, "EXPIRE");
+                       }
+                       memcpy(ifp->hwaddr, hwaddr, hwlen);
+                       ifp->hwlen = hwlen;
+                       if (!(ifo->options &
+                           (DHCPCD_INFORM | DHCPCD_STATIC | DHCPCD_CLIENTID)))
+                       {
+                               syslog(LOG_DEBUG, "%s: using hwaddr %s",
+                                   ifp->name,
+                                   hwaddr_ntoa(ifp->hwaddr, ifp->hwlen));
+                               ifp->state->interval = 0;
+                               ifp->state->nakoff = 1;
+                               start_interface(ifp);
+                       }
+               }
+       free(hwaddr);
+}
+
 void
 handle_ifa(int type, const char *ifname,
     struct in_addr *addr, struct in_addr *net, struct in_addr *dst)
index 61979eb40466993764c39450c1fb5e977a0043bf..ec3247466b41c6a7966c5d2e1f9c1d33aa35ece2 100644 (file)
--- a/dhcpcd.h
+++ b/dhcpcd.h
@@ -123,6 +123,7 @@ extern struct interface *ifaces;
 struct interface *find_interface(const char *);
 int handle_args(struct fd_list *, int, char **);
 void handle_interface(int, const char *);
+void handle_hwaddr(const char *, unsigned char *, size_t);
 void handle_ifa(int, const char *,
     struct in_addr *, struct in_addr *, struct in_addr *);
 void handle_exit_timeout(void *);
index 86748ffc6a611ad89e1f07961483169e3a4641be..b1b555ff1d1a50bb4cfd9eb53f3f036e60d7ea65 100644 (file)
--- a/if-bsd.c
+++ b/if-bsd.c
@@ -65,9 +65,7 @@
 
 /* FIXME: Why do we need to check for sa_family 255 */
 #define COPYOUT(sin, sa)                                                     \
-       sin.s_addr = ((sa) != NULL && ((sa)->sa_family == AF_INET ||          \
-               (sa)->sa_family == 255))                                      \
-           ?                                                                 \
+       sin.s_addr = ((sa) != NULL) ?                                         \
            (((struct sockaddr_in *)(void *)sa)->sin_addr).s_addr : 0
 
 static int r_fd = -1;
@@ -317,6 +315,10 @@ manage_link(int fd)
        struct rt rt;
        struct sockaddr *sa, *rti_info[RTAX_MAX];
        int len;
+#ifdef RTM_CHGADDR
+       struct sockaddr_dl sdl;
+       unsigned char *hwaddr;
+#endif
 
        for (;;) {
                if (ioctl(fd, FIONREAD, &len) == -1)
@@ -376,17 +378,41 @@ manage_link(int fd)
                                COPYOUT(rt.gate, rti_info[RTAX_GATEWAY]);
                                route_deleted(&rt);
                                break;
-                       case RTM_DELADDR:
+#ifdef RTM_CHGADDR
+                       case RTM_CHGADDR:       /* FALLTHROUGH */
+#endif
+                       case RTM_DELADDR:       /* FALLTHROUGH */
                        case RTM_NEWADDR:
                                ifam = (struct ifa_msghdr *)(void *)p;
+                               if (!if_indextoname(ifam->ifam_index, ifname))
+                                       break;
                                cp = (char *)(void *)(ifam + 1);
                                get_addrs(ifam->ifam_addrs, cp, rti_info);
-                               COPYOUT(rt.dest, rti_info[RTAX_IFA]);
-                               COPYOUT(rt.net, rti_info[RTAX_NETMASK]);
-                               COPYOUT(rt.gate, rti_info[RTAX_BRD]);
-                               if (if_indextoname(ifam->ifam_index, ifname))
+                               if (rti_info[RTAX_IFA] == NULL)
+                                       break;
+                               switch (rti_info[RTAX_IFA]->sa_family) {
+#ifdef RTM_CHGADDR
+                               case AF_LINK:
+                                       if (rtm->rtm_type != RTM_CHGADDR)
+                                               break;
+                                       memcpy(&sdl, rti_info[RTAX_IFA],
+                                           rti_info[RTAX_IFA]->sa_len);
+                                       hwaddr = xmalloc(sdl.sdl_alen);
+                                       memcpy(hwaddr, LLADDR(&sdl),
+                                           sdl.sdl_alen);
+                                       handle_hwaddr(ifname, hwaddr,
+                                           sdl.sdl_alen);
+                                       break;
+#endif
+                               case AF_INET:
+                               case 255: /* FIXME: Why 255? */
+                                       COPYOUT(rt.dest, rti_info[RTAX_IFA]);
+                                       COPYOUT(rt.net, rti_info[RTAX_NETMASK]);
+                                       COPYOUT(rt.gate, rti_info[RTAX_BRD]);
                                        handle_ifa(rtm->rtm_type, ifname,
                                            &rt.dest, &rt.net, &rt.gate);
+                                       break;
+                               }
                                break;
                        }
                }