From: Roy Marples Date: Fri, 12 Nov 2010 16:33:45 +0000 (+0000) Subject: Support RTM_CHGADDR in NetBSD-6 for detecting link layer address changes. X-Git-Tag: v5.2.9~6 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=8349d72adfe5e25ca691fdb9ce26263d34fe2753;p=thirdparty%2Fdhcpcd.git Support RTM_CHGADDR in NetBSD-6 for detecting link layer address changes. --- diff --git a/dhcpcd.c b/dhcpcd.c index 54acd1fa..a0860e39 100644 --- 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) diff --git a/dhcpcd.h b/dhcpcd.h index 61979eb4..ec324746 100644 --- 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 *); diff --git a/if-bsd.c b/if-bsd.c index 86748ffc..b1b555ff 100644 --- 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; } }