} while (0)
#ifndef CLLADDR
-# define CLLADDR(s) ((const char *)((s)->sdl_data + (s)->sdl_nlen))
+# define CLLADDR(s) (const void *)((s)->sdl_data + (s)->sdl_nlen)
#endif
struct priv {
}
static void
-get_addrs(int type, char *cp, struct sockaddr **sa)
+get_addrs(int type, uint8_t *cp, struct sockaddr **sa)
{
int i;
static int
if_copyrt(struct dhcpcd_ctx *ctx, struct rt *rt, struct rt_msghdr *rtm)
{
- char *cp;
+ uint8_t *ap;
struct sockaddr *sa, *rti_info[RTAX_MAX];
- cp = (void *)(rtm + 1);
- sa = (void *)cp;
+ ap = (void *)(rtm + 1);
+ sa = (void *)ap;
if (sa->sa_family != AF_INET)
return -1;
if (~rtm->rtm_addrs & (RTA_DST | RTA_GATEWAY))
return -1;
#endif
- get_addrs(rtm->rtm_addrs, cp, rti_info);
+ get_addrs(rtm->rtm_addrs, ap, rti_info);
memset(rt, 0, sizeof(*rt));
rt->flags = (unsigned int)rtm->rtm_flags;
COPYOUT(rt->dest, rti_info[RTAX_DST]);
static int
if_copyrt6(struct dhcpcd_ctx *ctx, struct rt6 *rt, struct rt_msghdr *rtm)
{
- char *cp;
+ uint8_t *ap;
struct sockaddr *sa, *rti_info[RTAX_MAX];
- cp = (void *)(rtm + 1);
- sa = (void *)cp;
+ ap = (void *)(rtm + 1);
+ sa = (void *)ap;
if (sa->sa_family != AF_INET6)
return -1;
if (~rtm->rtm_addrs & (RTA_DST | RTA_GATEWAY))
return -1;
#endif
- get_addrs(rtm->rtm_addrs, cp, rti_info);
+ get_addrs(rtm->rtm_addrs, ap, rti_info);
memset(rt, 0, sizeof(*rt));
rt->flags = (unsigned int)rtm->rtm_flags;
COPYOUT6(rt->dest, rti_info[RTAX_DST]);
}
#endif
-int
-if_handlelink(struct dhcpcd_ctx *ctx)
+static void
+if_announce(struct dhcpcd_ctx *ctx, struct if_announcemsghdr *ifan)
+{
+
+ switch(ifan->ifan_what) {
+ case IFAN_ARRIVAL:
+ dhcpcd_handleinterface(ctx, 1, ifan->ifan_name);
+ break;
+ case IFAN_DEPARTURE:
+ dhcpcd_handleinterface(ctx, -1, ifan->ifan_name);
+ break;
+ }
+}
+
+static void
+if_ifinfo(struct dhcpcd_ctx *ctx, struct if_msghdr *ifm)
{
- /* route and ifwatchd like a msg buf size of 2048 */
- char msg[2048], *p, *e, *cp;
- ssize_t bytes;
- struct rt_msghdr *rtm;
- struct if_announcemsghdr *ifan;
- struct if_msghdr *ifm;
- struct ifa_msghdr *ifam;
- struct sockaddr *sa, *rti_info[RTAX_MAX];
- int len;
- struct sockaddr_dl sdl;
struct interface *ifp;
+ int state;
+
+ if ((ifp = if_findindex(ctx->ifaces, ifm->ifm_index)) == NULL)
+ return;
+ switch (ifm->ifm_data.ifi_link_state) {
+ case LINK_STATE_DOWN:
+ state = LINK_DOWN;
+ break;
+ case LINK_STATE_UP:
+ state = LINK_UP;
+ break;
+ default:
+ /* handle_carrier will re-load the interface flags and check for
+ * IFF_RUNNING as some drivers that don't handle link state also
+ * don't set IFF_RUNNING when this routing message is generated.
+ * As such, it is a race ...*/
+ state = LINK_UNKNOWN;
+ break;
+ }
+ dhcpcd_handlecarrier(ctx, state,
+ (unsigned int)ifm->ifm_flags, ifp->name);
+}
+
+static void
+if_rtm(struct dhcpcd_ctx *ctx, struct rt_msghdr *rtm)
+{
+ struct sockaddr *sa;
+
+ /* Ignore messages generated by us */
+ if (rtm->rtm_pid == getpid()) {
+ ctx->options &= ~DHCPCD_RTM_PPID;
+ return;
+ }
+
+ /* Ignore messages sent by the parent after forking */
+ if ((ctx->options &
+ (DHCPCD_RTM_PPID | DHCPCD_DAEMONISED)) ==
+ (DHCPCD_RTM_PPID | DHCPCD_DAEMONISED) &&
+ rtm->rtm_pid == ctx->ppid)
+ {
+ /* If this is the last successful message sent,
+ * clear the check flag as it's possible another
+ * process could re-use the same pid and also
+ * manipulate therouting table. */
+ if (rtm->rtm_seq == ctx->pseq)
+ ctx->options &= ~DHCPCD_RTM_PPID;
+ return;
+ }
+
+ sa = (void *)(rtm + 1);
+ switch (sa->sa_family) {
#ifdef INET
- struct rt rt;
+ case AF_INET:
+ {
+ struct rt rt;
+
+ if (if_copyrt(ctx, &rt, rtm) == 0)
+ ipv4_handlert(ctx, rtm->rtm_type, &rt, 0);
+ break;
+ }
#endif
#ifdef INET6
- struct rt6 rt6;
- struct in6_addr ia6, mask6;
- struct sockaddr_in6 *sin6;
-#endif
-#if (defined(INET) && defined(IN_IFF_TENTATIVE)) || defined(INET6)
- int ifa_flags;
-#endif
+ case AF_INET6:
+ {
+ struct rt6 rt6;
- if ((bytes = read(ctx->link_fd, msg, sizeof(msg))) == -1)
- return -1;
- e = msg + bytes;
- for (p = msg; p < e; p += rtm->rtm_msglen) {
- rtm = (void *)p;
- switch(rtm->rtm_type) {
-#ifdef RTM_IFANNOUNCE
- case RTM_IFANNOUNCE:
- ifan = (void *)p;
- switch(ifan->ifan_what) {
- case IFAN_ARRIVAL:
- dhcpcd_handleinterface(ctx, 1,
- ifan->ifan_name);
- break;
- case IFAN_DEPARTURE:
- dhcpcd_handleinterface(ctx, -1,
- ifan->ifan_name);
- break;
- }
+ if (~rtm->rtm_addrs & (RTA_DST | RTA_GATEWAY))
break;
-#endif
- case RTM_IFINFO:
- ifm = (void *)p;
- ifp = if_findindex(ctx->ifaces, ifm->ifm_index);
- if (ifp == NULL)
- break;
- switch (ifm->ifm_data.ifi_link_state) {
- case LINK_STATE_DOWN:
- len = LINK_DOWN;
- break;
- case LINK_STATE_UP:
- len = LINK_UP;
- break;
- default:
- /* handle_carrier will re-load
- * the interface flags and check for
- * IFF_RUNNING as some drivers that
- * don't handle link state also don't
- * set IFF_RUNNING when this routing
- * message is generated.
- * As such, it is a race ...*/
- len = LINK_UNKNOWN;
- break;
- }
- dhcpcd_handlecarrier(ctx, len,
- (unsigned int)ifm->ifm_flags, ifp->name);
+ /*
+ * BSD announces host routes.
+ * As such, we should be notified of reachability by its
+ * existance with a hardware address.
+ */
+ if (rtm->rtm_flags & (RTF_HOST)) {
+ uint8_t *ap;
+ struct sockaddr *rti_info[RTAX_MAX];
+ struct in6_addr dst6;
+ struct sockaddr_dl sdl;
+
+ ap = (void *)(rtm + 1);
+ get_addrs(rtm->rtm_addrs, ap, rti_info);
+ COPYOUT6(dst6, rti_info[RTAX_DST]);
+ DESCOPE(&dst6);
+ if (rti_info[RTAX_GATEWAY]->sa_family == AF_LINK)
+ memcpy(&sdl, rti_info[RTAX_GATEWAY],
+ sizeof(sdl));
+ else
+ sdl.sdl_alen = 0;
+ ipv6nd_neighbour(ctx, &dst6,
+ rtm->rtm_type != RTM_DELETE && sdl.sdl_alen ?
+ IPV6ND_REACHABLE : 0);
break;
- case RTM_ADD:
- case RTM_CHANGE:
- case RTM_DELETE:
- /* Ignore messages generated by us */
- if (rtm->rtm_pid == getpid()) {
- ctx->options &= ~DHCPCD_RTM_PPID;
- continue;
- }
- /* Ignore messages sent by the parent after forking */
- if ((ctx->options &
- (DHCPCD_RTM_PPID | DHCPCD_DAEMONISED)) ==
- (DHCPCD_RTM_PPID | DHCPCD_DAEMONISED) &&
- rtm->rtm_pid == ctx->ppid)
- {
- /* If this is the last successful message sent,
- * clear the check flag as it's possible another
- * process could re-use the same pid and also
- * manipulate therouting table. */
- if (rtm->rtm_seq == ctx->pseq)
- ctx->options &= ~DHCPCD_RTM_PPID;
- continue;
- }
- cp = (void *)(rtm + 1);
- sa = (void *)cp;
- switch (sa->sa_family) {
-#ifdef INET
- case AF_INET:
- if (if_copyrt(ctx, &rt, rtm) == 0)
- ipv4_handlert(ctx, rtm->rtm_type,&rt,0);
- break;
-#endif
-#ifdef INET6
- case AF_INET6:
- if (~rtm->rtm_addrs & (RTA_DST | RTA_GATEWAY))
- break;
- /*
- * BSD caches host routes in the
- * routing table.
- * As such, we should be notified of
- * reachability by its existance
- * with a hardware address
- */
- if (rtm->rtm_flags & (RTF_HOST)) {
- get_addrs(rtm->rtm_addrs, cp, rti_info);
- COPYOUT6(ia6, rti_info[RTAX_DST]);
- DESCOPE(&ia6);
- if (rti_info[RTAX_GATEWAY]->sa_family
- == AF_LINK)
- memcpy(&sdl,
- rti_info[RTAX_GATEWAY],
- sizeof(sdl));
- else
- sdl.sdl_alen = 0;
- ipv6nd_neighbour(ctx, &ia6,
- rtm->rtm_type != RTM_DELETE &&
- sdl.sdl_alen ?
- IPV6ND_REACHABLE : 0);
- break;
- }
+ }
- if (if_copyrt6(ctx, &rt6, rtm) == 0)
- ipv6_handlert(ctx, rtm->rtm_type, &rt6);
- break;
+ if (if_copyrt6(ctx, &rt6, rtm) == 0)
+ ipv6_handlert(ctx, rtm->rtm_type, &rt6);
+ break;
+ }
#endif
- }
- break;
-#ifdef RTM_CHGADDR
- case RTM_CHGADDR: /* FALLTHROUGH */
-#endif
- case RTM_DELADDR: /* FALLTHROUGH */
- case RTM_NEWADDR:
- /* XXX We have no way of knowing who generated these
- * messages wich truely sucks because we want to
- * avoid listening to our own delete messages. */
- ifam = (void *)p;
- ifp = if_findindex(ctx->ifaces, ifam->ifam_index);
- if (ifp == NULL)
- break;
- cp = (void *)(ifam + 1);
- get_addrs(ifam->ifam_addrs, cp, rti_info);
- if (rti_info[RTAX_IFA] == NULL)
- break;
- switch (rti_info[RTAX_IFA]->sa_family) {
- case AF_LINK:
+ }
+}
+
+static void
+if_ifa(struct dhcpcd_ctx *ctx, struct ifa_msghdr *ifam)
+{
+ struct interface *ifp;
+ uint8_t *cp;
+ struct sockaddr *rti_info[RTAX_MAX];
+
+ /* XXX We have no way of knowing who generated these
+ * messages wich truely sucks because we want to
+ * avoid listening to our own delete messages. */
+ if ((ifp = if_findindex(ctx->ifaces, ifam->ifam_index)) == NULL)
+ return;
+ cp = (void *)(ifam + 1);
+ get_addrs(ifam->ifam_addrs, cp, rti_info);
+ if (rti_info[RTAX_IFA] == NULL)
+ return;
+ switch (rti_info[RTAX_IFA]->sa_family) {
+ case AF_LINK:
+ {
+ struct sockaddr_dl sdl;
+
#ifdef RTM_CHGADDR
- if (rtm->rtm_type != RTM_CHGADDR)
- break;
+ if (ifam->ifam_type != RTM_CHGADDR)
+ break;
#else
- if (rtm->rtm_type != RTM_NEWADDR)
- break;
-#endif
- memcpy(&sdl, rti_info[RTAX_IFA],
- rti_info[RTAX_IFA]->sa_len);
- dhcpcd_handlehwaddr(ctx, ifp->name,
- (const unsigned char*)CLLADDR(&sdl),
- sdl.sdl_alen);
- break;
+ if (ifam->ifam_type != RTM_NEWADDR)
+ break;
+#endif
+ memcpy(&sdl, rti_info[RTAX_IFA], rti_info[RTAX_IFA]->sa_len);
+ dhcpcd_handlehwaddr(ctx, ifp->name, CLLADDR(&sdl),sdl.sdl_alen);
+ break;
+ }
#ifdef INET
- case AF_INET:
- case 255: /* FIXME: Why 255? */
- COPYOUT(rt.dest, rti_info[RTAX_IFA]);
- COPYOUT(rt.mask, rti_info[RTAX_NETMASK]);
- COPYOUT(rt.gate, rti_info[RTAX_BRD]);
- if (rtm->rtm_type == RTM_NEWADDR) {
- ifa_flags = if_addrflags(&rt.dest, ifp);
- if (ifa_flags == -1)
- break;
- } else
- ifa_flags = 0;
- ipv4_handleifa(ctx, rtm->rtm_type,
- NULL, ifp->name,
- &rt.dest, &rt.mask, &rt.gate, ifa_flags);
+ case AF_INET:
+ case 255: /* FIXME: Why 255? */
+ {
+ struct in_addr addr, mask, bcast;
+ int flags;
+
+ COPYOUT(addr, rti_info[RTAX_IFA]);
+ COPYOUT(mask, rti_info[RTAX_NETMASK]);
+ COPYOUT(bcast, rti_info[RTAX_BRD]);
+ if (ifam->ifam_type == RTM_NEWADDR) {
+ if ((flags = if_addrflags(&addr, ifp)) == -1)
break;
+ } else
+ flags = 0;
+ ipv4_handleifa(ctx, ifam->ifam_type, NULL, ifp->name,
+ &addr, &mask, &bcast, flags);
+ break;
+ }
#endif
#ifdef INET6
- case AF_INET6:
- sin6 = (void *)rti_info[RTAX_IFA];
- ia6 = sin6->sin6_addr;
- DESCOPE(&ia6);
- sin6 = (void *)rti_info[RTAX_NETMASK];
- mask6 = sin6->sin6_addr;
- DESCOPE(&mask6);
- if (rtm->rtm_type == RTM_NEWADDR) {
- ifa_flags = if_addrflags6(&ia6, ifp);
- if (ifa_flags == -1)
- break;
- } else
- ifa_flags = 0;
- ipv6_handleifa(ctx, rtm->rtm_type, NULL,
- ifp->name, &ia6, ipv6_prefixlen(&mask6),
- ifa_flags);
+ case AF_INET6:
+ {
+ struct in6_addr addr6, mask6;
+ struct sockaddr_in6 *sin6;
+ int flags;
+
+ sin6 = (void *)rti_info[RTAX_IFA];
+ addr6 = sin6->sin6_addr;
+ DESCOPE(&addr6);
+ sin6 = (void *)rti_info[RTAX_NETMASK];
+ mask6 = sin6->sin6_addr;
+ DESCOPE(&mask6);
+ if (ifam->ifam_type == RTM_NEWADDR) {
+ if ((flags = if_addrflags6(&addr6, ifp)) == -1)
break;
+ } else
+ flags = 0;
+ ipv6_handleifa(ctx, ifam->ifam_type, NULL,
+ ifp->name, &addr6, ipv6_prefixlen(&mask6), flags);
+ break;
+ }
#endif
- }
- break;
- }
+ }
+}
+
+static void
+if_dispatch(struct dhcpcd_ctx *ctx, struct rt_msghdr *rtm)
+{
+
+ switch(rtm->rtm_type) {
+#ifdef RTM_IFANNOUNCE
+ case RTM_IFANNOUNCE:
+ if_announce(ctx, (void *)rtm);
+ break;
+#endif
+ case RTM_IFINFO:
+ if_ifinfo(ctx, (void *)rtm);
+ break;
+ case RTM_ADD: /* FALLTHROUGH */
+ case RTM_CHANGE: /* FALLTHROUGH */
+ case RTM_DELETE:
+ if_rtm(ctx, (void *)rtm);
+ break;
+#ifdef RTM_CHGADDR
+ case RTM_CHGADDR: /* FALLTHROUGH */
+#endif
+ case RTM_DELADDR: /* FALLTHROUGH */
+ case RTM_NEWADDR:
+ if_ifa(ctx, (void *)rtm);
+ break;
+ }
+}
+
+int
+if_handlelink(struct dhcpcd_ctx *ctx)
+{
+ /* route and ifwatchd like a msg buf size of 2048 */
+ uint8_t buf[2048], *p, *e;
+ size_t msglen;
+ ssize_t bytes;
+
+ if ((bytes = read(ctx->link_fd, buf, sizeof(buf))) == -1)
+ return -1;
+ e = buf + bytes;
+ for (p = buf; p < e; p += msglen) {
+ msglen = ((struct rt_msghdr *)p)->rtm_msglen;
+ if_dispatch(ctx, (struct rt_msghdr *)p);
}
return 0;
}