}
}
+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)
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 *);
/* 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;
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)
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;
}
}