]> git.ipfire.org Git - thirdparty/dhcpcd.git/commitdiff
Remove the send/recv structures from dhcpcd context and allocate
authorRoy Marples <roy@marples.name>
Sun, 17 Feb 2019 09:36:11 +0000 (09:36 +0000)
committerRoy Marples <roy@marples.name>
Sun, 17 Feb 2019 09:36:11 +0000 (09:36 +0000)
on stack as and when required.
Rather than peaking and checking for truncation for receiving,
just allocate a large enough buffer upfront.

src/common.c
src/common.h
src/dhcp6.c
src/dhcpcd.c
src/dhcpcd.h
src/if-bsd.c
src/if-linux.c
src/if-sun.c
src/ipv6.c
src/ipv6nd.c

index 6d06604d8ea4294343faf243feed7d056021ebe3..0214af2c22293a5de5c012c94670a81fc63975c9 100644 (file)
@@ -200,51 +200,3 @@ read_hwaddr_aton(uint8_t **data, const char *path)
        fclose(fp);
        return len;
 }
-
-ssize_t
-recvmsg_realloc(int fd, struct msghdr *msg, int flags)
-{
-       struct iovec *iov;
-       ssize_t slen;
-       size_t len;
-       void *n;
-
-       assert(msg != NULL);
-       assert(msg->msg_iov != NULL && msg->msg_iovlen > 0);
-       assert((flags & (MSG_PEEK | MSG_TRUNC)) == 0);
-
-       /* Assume we are reallocing the last iovec. */
-       iov = &msg->msg_iov[msg->msg_iovlen - 1];
-
-       for (;;) {
-               /* Passing MSG_TRUNC should return the actual size needed. */
-               slen = recvmsg(fd, msg, flags | MSG_PEEK | MSG_TRUNC);
-               if (slen == -1)
-                       return -1;
-               if (!(msg->msg_flags & MSG_TRUNC))
-                       break;
-
-               len = (size_t)slen;
-
-               /* Some kernels return the size of the receive buffer
-                * on truncation, not the actual size needed.
-                * So grow the buffer and try again. */
-               if (iov->iov_len == len)
-                       len++;
-               else if (iov->iov_len > len)
-                       break;
-               len = roundup(len, IOVEC_BUFSIZ);
-               if ((n = realloc(iov->iov_base, len)) == NULL)
-                       return -1;
-               iov->iov_base = n;
-               iov->iov_len = len;
-       }
-
-       slen = recvmsg(fd, msg, flags);
-       if (slen != -1 && msg->msg_flags & MSG_TRUNC) {
-               /* This should not be possible ... */
-               errno = ENOBUFS;
-               return -1;
-       }
-       return slen;
-}
index 713dd1d326112a8d35da779f0f0f62bd74b6c02b..8dfd251cc46a7d4b73c79203410b99aa5adfc83c 100644 (file)
@@ -181,6 +181,4 @@ ssize_t addvard(char ***, const char *, const char *, size_t);
 const char *hwaddr_ntoa(const void *, size_t, char *, size_t);
 size_t hwaddr_aton(uint8_t *, const char *);
 size_t read_hwaddr_aton(uint8_t **, const char *);
-
-ssize_t recvmsg_realloc(int, struct msghdr *, int);
 #endif
index b5b035f23dad138df60962544146210d4361064c..c50efb66af0b4ab72ee723eb085fcbab0bad0bb0 100644 (file)
@@ -168,7 +168,7 @@ static const char * const dhcp6_statuses[] = {
        "No Prefix Available"
 };
 
-static void dhcp6_bind(struct interface *, const char *);
+static void dhcp6_bind(struct interface *, const char *, const char *);
 static void dhcp6_failinform(void *);
 static int dhcp6_listen(struct dhcpcd_ctx *, struct ipv6_addr *);
 static void dhcp6_recvaddr(void *);
@@ -1157,9 +1157,12 @@ dhcp6_update_auth(struct interface *ifp, struct dhcp6_message *m, size_t len)
 static int
 dhcp6_sendmessage(struct interface *ifp, void (*callback)(void *))
 {
-       struct dhcp6_state *state;
-       struct dhcpcd_ctx *ctx;
-       struct sockaddr_in6 dst;
+       struct dhcp6_state *state = D6_STATE(ifp);
+       struct dhcpcd_ctx *ctx = ifp->ctx;
+       struct sockaddr_in6 dst = {
+           .sin6_family = AF_INET6,
+           .sin6_port = htons(DHCP6_SERVER_PORT),
+       };
        struct timespec RTprev;
        double rnd;
        time_t ms;
@@ -1168,18 +1171,22 @@ dhcp6_sendmessage(struct interface *ifp, void (*callback)(void *))
        const struct in6_addr alldhcp = IN6ADDR_LINKLOCAL_ALLDHCP_INIT;
        struct ipv6_addr *lla;
        int s;
+       struct iovec iov = {
+           .iov_base = state->send, .iov_len = state->send_len,
+       };
+       unsigned char ctl[CMSG_SPACE(sizeof(struct in6_pktinfo))] = { 0 };
+       struct msghdr msg = {
+           .msg_name = &dst, .msg_namelen = sizeof(dst),
+           .msg_iov = &iov, .msg_iovlen = 1,
+       };
 
        if (!callback && ifp->carrier <= LINK_DOWN)
                return 0;
 
-       memset(&dst, 0, sizeof(dst));
-       dst.sin6_family = AF_INET6;
-       dst.sin6_port = htons(DHCP6_SERVER_PORT);
 #ifdef HAVE_SA_LEN
        dst.sin6_len = sizeof(dst);
 #endif
 
-       state = D6_STATE(ifp);
        lla = ipv6_linklocal(ifp);
        /* We need to ensure we have sufficient scope to unicast the address */
        /* XXX FIXME: We should check any added addresses we have like from
@@ -1280,7 +1287,7 @@ logsend:
                /* Wait the initial delay */
                if (state->IMD != 0) {
                        state->IMD = 0;
-                       eloop_timeout_add_tv(ifp->ctx->eloop,
+                       eloop_timeout_add_tv(ctx->eloop,
                            &state->RT, callback, ifp);
                        return 0;
                }
@@ -1301,31 +1308,21 @@ logsend:
        }
 #endif
 
-       ctx = ifp->ctx;
-       ctx->sndhdr.msg_name = (void *)&dst;
-       ctx->sndhdr.msg_iov[0].iov_base = state->send;
-       ctx->sndhdr.msg_iov[0].iov_len = state->send_len;
-
        /* Set the outbound interface */
        if (IN6_ARE_ADDR_EQUAL(&dst.sin6_addr, &alldhcp)) {
                struct cmsghdr *cm;
-               struct in6_pktinfo pi;
+               struct in6_pktinfo pi = { .ipi6_ifindex = ifp->index };
 
                dst.sin6_scope_id = ifp->index;
-               cm = CMSG_FIRSTHDR(&ctx->sndhdr);
+               msg.msg_control = ctl;
+               msg.msg_controllen = sizeof(ctl);
+               cm = CMSG_FIRSTHDR(&msg);
                if (cm == NULL) /* unlikely */
                        return -1;
                cm->cmsg_level = IPPROTO_IPV6;
                cm->cmsg_type = IPV6_PKTINFO;
                cm->cmsg_len = CMSG_LEN(sizeof(pi));
-               memset(&pi, 0, sizeof(pi));
-               pi.ipi6_ifindex = ifp->index;
                memcpy(CMSG_DATA(cm), &pi, sizeof(pi));
-       } else {
-               /* Remove the control buffer as we're not dictating
-                * which interface to use for outgoing messages. */
-               ctx->sndhdr.msg_control = NULL;
-               ctx->sndhdr.msg_controllen = 0;
        }
 
        if (ctx->dhcp6_fd != -1)
@@ -1337,7 +1334,7 @@ logsend:
                return -1;
        }
 
-       if (sendmsg(s, &ctx->sndhdr, 0) == -1) {
+       if (sendmsg(s, &msg, 0) == -1) {
                logerr("%s: %s: sendmsg", __func__, ifp->name);
                /* Allow DHCPv6 to continue .... the errors
                 * would be rate limited by the protocol.
@@ -1345,19 +1342,13 @@ logsend:
                 * associate with an access point. */
        }
 
-       /* Restore the control buffer assignment. */
-       if (!IN6_ARE_ADDR_EQUAL(&dst.sin6_addr, &alldhcp)) {
-               ctx->sndhdr.msg_control = ctx->sndbuf;
-               ctx->sndhdr.msg_controllen = sizeof(ctx->sndbuf);
-       }
-
        state->RTC++;
        if (callback) {
                if (state->MRC == 0 || state->RTC < state->MRC)
-                       eloop_timeout_add_tv(ifp->ctx->eloop,
+                       eloop_timeout_add_tv(ctx->eloop,
                            &state->RT, callback, ifp);
                else if (state->MRC != 0 && state->MRCcallback)
-                       eloop_timeout_add_tv(ifp->ctx->eloop,
+                       eloop_timeout_add_tv(ctx->eloop,
                            &state->RT, state->MRCcallback, ifp);
                else
                        logwarnx("%s: sent %d times with no reply",
@@ -1650,7 +1641,7 @@ dhcp6_fail(struct interface *ifp)
                break;
        }
 
-       dhcp6_bind(ifp, NULL);
+       dhcp6_bind(ifp, NULL, NULL);
 
        switch (state->state) {
        case DH6S_BOUND:
@@ -2927,7 +2918,7 @@ dhcp6_find_delegates(struct interface *ifp)
 #endif
 
 static void
-dhcp6_bind(struct interface *ifp, const char *op)
+dhcp6_bind(struct interface *ifp, const char *op, const char *sfrom)
 {
        struct dhcp6_state *state = D6_STATE(ifp);
        bool has_new = false;
@@ -2943,8 +2934,7 @@ dhcp6_bind(struct interface *ifp, const char *op)
        }
        lognewinfo = has_new ? loginfox : logdebugx;
        if (op != NULL)
-               lognewinfo("%s: %s received from %s",
-                   ifp->name, op, ifp->ctx->sfrom);
+               lognewinfo("%s: %s received from %s", ifp->name, op, sfrom);
 
        state->reason = NULL;
        if (state->state != DH6S_ITIMEDOUT)
@@ -3176,7 +3166,8 @@ dhcp6_bind(struct interface *ifp, const char *op)
 }
 
 static void
-dhcp6_recvif(struct interface *ifp, struct dhcp6_message *r, size_t len)
+dhcp6_recvif(struct interface *ifp, const char *sfrom,
+    struct dhcp6_message *r, size_t len)
 {
        struct dhcpcd_ctx *ctx;
        size_t i;
@@ -3211,8 +3202,7 @@ dhcp6_recvif(struct interface *ifp, struct dhcp6_message *r, size_t len)
        }
 
        if (dhcp6_findmoption(r, len, D6_OPTION_SERVERID, NULL) == NULL) {
-               logdebugx("%s: no DHCPv6 server ID from %s",
-                   ifp->name, ctx->sfrom);
+               logdebugx("%s: no DHCPv6 server ID from %s", ifp->name, sfrom);
                return;
        }
 
@@ -3225,14 +3215,14 @@ dhcp6_recvif(struct interface *ifp, struct dhcp6_message *r, size_t len)
                    !dhcp6_findmoption(r, len, (uint16_t)opt->option, NULL))
                {
                        logwarnx("%s: reject DHCPv6 (no option %s) from %s",
-                           ifp->name, opt->var, ctx->sfrom);
+                           ifp->name, opt->var, sfrom);
                        return;
                }
                if (has_option_mask(ifo->rejectmask6, opt->option) &&
                    dhcp6_findmoption(r, len, (uint16_t)opt->option, NULL))
                {
                        logwarnx("%s: reject DHCPv6 (option %s) from %s",
-                           ifp->name, opt->var, ctx->sfrom);
+                           ifp->name, opt->var, sfrom);
                        return;
                }
        }
@@ -3245,7 +3235,7 @@ dhcp6_recvif(struct interface *ifp, struct dhcp6_message *r, size_t len)
                    (uint8_t *)r, len, 6, r->type, auth, auth_len) == NULL)
                {
                        logerr("%s: authentication failed from %s",
-                           ifp->name, ctx->sfrom);
+                           ifp->name, sfrom);
                        return;
                }
                if (state->auth.token)
@@ -3256,11 +3246,10 @@ dhcp6_recvif(struct interface *ifp, struct dhcp6_message *r, size_t len)
        } else if (ifo->auth.options & DHCPCD_AUTH_SEND) {
                if (ifo->auth.options & DHCPCD_AUTH_REQUIRE) {
                        logerr("%s: no authentication from %s",
-                           ifp->name, ctx->sfrom);
+                           ifp->name, sfrom);
                        return;
                }
-               logwarnx("%s: no authentication from %s",
-                   ifp->name, ctx->sfrom);
+               logwarnx("%s: no authentication from %s", ifp->name, sfrom);
        }
 #endif
 
@@ -3274,8 +3263,7 @@ dhcp6_recvif(struct interface *ifp, struct dhcp6_message *r, size_t len)
                                return;
                        break;
                case DH6S_CONFIRM:
-                       if (dhcp6_validatelease(ifp, r, len,
-                                               ctx->sfrom, NULL) == -1)
+                       if (dhcp6_validatelease(ifp, r, len, sfrom, NULL) == -1)
                        {
                                dhcp6_startdiscover(ifp);
                                return;
@@ -3297,8 +3285,7 @@ dhcp6_recvif(struct interface *ifp, struct dhcp6_message *r, size_t len)
                case DH6S_REQUEST: /* FALLTHROUGH */
                case DH6S_RENEW: /* FALLTHROUGH */
                case DH6S_REBIND:
-                       if (dhcp6_validatelease(ifp, r, len,
-                           ctx->sfrom, NULL) == -1)
+                       if (dhcp6_validatelease(ifp, r, len, sfrom, NULL) == -1)
                        {
                                /*
                                 * If we can't use the lease, fallback to
@@ -3366,7 +3353,7 @@ dhcp6_recvif(struct interface *ifp, struct dhcp6_message *r, size_t len)
                                logerrx("%s: invalid INF_MAX_RT %u",
                                    ifp->name, max_rt);
                }
-               if (dhcp6_validatelease(ifp, r, len, ctx->sfrom, NULL) == -1)
+               if (dhcp6_validatelease(ifp, r, len, sfrom, NULL) == -1)
                        return;
                break;
        case DHCP6_RECONFIGURE:
@@ -3374,12 +3361,12 @@ dhcp6_recvif(struct interface *ifp, struct dhcp6_message *r, size_t len)
                if (auth == NULL) {
 #endif
                        logerrx("%s: unauthenticated %s from %s",
-                           ifp->name, op, ctx->sfrom);
+                           ifp->name, op, sfrom);
                        if (ifo->auth.options & DHCPCD_AUTH_REQUIRE)
                                return;
 #ifdef AUTH
                }
-               loginfox("%s: %s from %s", ifp->name, op, ctx->sfrom);
+               loginfox("%s: %s from %s", ifp->name, op, sfrom);
                o = dhcp6_findmoption(r, len, D6_OPTION_RECONF_MSG, &ol);
                if (o == NULL) {
                        logerrx("%s: missing Reconfigure Message option",
@@ -3456,10 +3443,10 @@ dhcp6_recvif(struct interface *ifp, struct dhcp6_message *r, size_t len)
                        ia = TAILQ_FIRST(&state->addrs);
                if (ia == NULL)
                        loginfox("%s: ADV (no address) from %s",
-                           ifp->name, ctx->sfrom);
+                           ifp->name, sfrom);
                else
                        loginfox("%s: ADV %s from %s",
-                           ifp->name, ia->saddr, ctx->sfrom);
+                           ifp->name, ia->saddr, sfrom);
                if (ifp->ctx->options & DHCPCD_TEST)
                        break;
                dhcp6_startrequest(ifp);
@@ -3467,33 +3454,44 @@ dhcp6_recvif(struct interface *ifp, struct dhcp6_message *r, size_t len)
        }
        }
 
-       dhcp6_bind(ifp, op);
+       dhcp6_bind(ifp, op, sfrom);
 }
 
 static void
 dhcp6_recv(struct dhcpcd_ctx *ctx, struct ipv6_addr *ia)
 {
+       struct sockaddr_in6 from;
+       unsigned char buf[64 * 1024]; /* Maximum UDP message size */
+       struct iovec iov = {
+               .iov_base = buf,
+               .iov_len = sizeof(buf),
+       };
+       unsigned char ctl[CMSG_SPACE(sizeof(struct in6_pktinfo))] = { 0 };
+       struct msghdr msg = {
+           .msg_name = &from, .msg_namelen = sizeof(from),
+           .msg_iov = &iov, .msg_iovlen = 1,
+           .msg_control = ctl, .msg_controllen = sizeof(ctl),
+       };
        int s;
        size_t len;
        ssize_t bytes;
+       char sfrom[INET6_ADDRSTRLEN];
        struct interface *ifp;
        struct dhcp6_message *r;
        const struct dhcp6_state *state;
        uint8_t *o;
        uint16_t ol;
 
-       ctx->rcvhdr.msg_controllen = CMSG_SPACE(sizeof(struct in6_pktinfo));
        s = ia != NULL ? ia->dhcp6_fd : ctx->dhcp6_fd;
-       bytes = recvmsg_realloc(s, &ctx->rcvhdr, 0);
+       bytes = recvmsg(s, &msg, 0);
        if (bytes == -1) {
-               logerr("%s: recvmsg_realloc", __func__);
+               logerr(__func__);
                return;
        }
        len = (size_t)bytes;
-       ctx->sfrom = inet_ntop(AF_INET6, &ctx->from.sin6_addr,
-           ctx->ntopbuf, sizeof(ctx->ntopbuf));
+       inet_ntop(AF_INET6, &from.sin6_addr, sfrom, sizeof(sfrom));
        if (len < sizeof(struct dhcp6_message)) {
-               logerrx("DHCPv6 packet too short from %s", ctx->sfrom);
+               logerrx("DHCPv6 packet too short from %s", sfrom);
                return;
        }
 
@@ -3504,9 +3502,9 @@ dhcp6_recv(struct dhcpcd_ctx *ctx, struct ipv6_addr *ia)
                struct in6_pktinfo pi;
 
                pi.ipi6_ifindex = 0;
-               for (cm = (struct cmsghdr *)CMSG_FIRSTHDR(&ctx->rcvhdr);
+               for (cm = (struct cmsghdr *)CMSG_FIRSTHDR(&msg);
                    cm;
-                   cm = (struct cmsghdr *)CMSG_NXTHDR(&ctx->rcvhdr, cm))
+                   cm = (struct cmsghdr *)CMSG_NXTHDR(&msg, cm))
                {
                        if (cm->cmsg_level != IPPROTO_IPV6)
                                continue;
@@ -3519,7 +3517,7 @@ dhcp6_recv(struct dhcpcd_ctx *ctx, struct ipv6_addr *ia)
                }
                if (pi.ipi6_ifindex == 0) {
                        logerrx("DHCPv6 reply did not contain index from %s",
-                           ctx->sfrom);
+                           sfrom);
                        return;
                }
 
@@ -3529,35 +3527,35 @@ dhcp6_recv(struct dhcpcd_ctx *ctx, struct ipv6_addr *ia)
                }
                if (ifp == NULL) {
                        logerrx("DHCPv6 reply for unexpected interface from %s",
-                           ctx->sfrom);
+                           sfrom);
                        return;
                }
        }
 
-       r = (struct dhcp6_message *)ctx->rcvhdr.msg_iov[0].iov_base;
+       r = (struct dhcp6_message *)buf;
        o = dhcp6_findmoption(r, len, D6_OPTION_CLIENTID, &ol);
        if (o == NULL || ol != ctx->duid_len ||
            memcmp(o, ctx->duid, ol) != 0)
        {
                logdebugx("%s: incorrect client ID from %s",
-                   ifp->name, ctx->sfrom);
+                   ifp->name, sfrom);
                return;
        }
 
        if (dhcp6_findmoption(r, len, D6_OPTION_SERVERID, NULL) == NULL) {
                logdebugx("%s: no DHCPv6 server ID from %s",
-                   ifp->name, ctx->sfrom);
+                   ifp->name, sfrom);
                return;
        }
 
        if (r->type == DHCP6_RECONFIGURE) {
                logdebugx("%s: RECONFIGURE6 recv from %s,"
                    " sending to all interfaces",
-                   ifp->name, ctx->sfrom);
+                   ifp->name, sfrom);
                TAILQ_FOREACH(ifp, ctx->ifaces, next) {
                        state = D6_CSTATE(ifp);
                        if (state != NULL && state->send != NULL)
-                               dhcp6_recvif(ifp, r, len);
+                               dhcp6_recvif(ifp, sfrom, r, len);
                }
                return;
        }
@@ -3591,7 +3589,7 @@ dhcp6_recv(struct dhcpcd_ctx *ctx, struct ipv6_addr *ia)
                                    state->send->xid[0],
                                    state->send->xid[1],
                                    state->send->xid[2],
-                                   ctx->sfrom);
+                                   sfrom);
                        return;
                }
                logdebugx("%s: redirecting DHCP6 message to %s",
@@ -3599,7 +3597,7 @@ dhcp6_recv(struct dhcpcd_ctx *ctx, struct ipv6_addr *ia)
                ifp = ifp1;
        }
 
-       dhcp6_recvif(ifp, r, len);
+       dhcp6_recvif(ifp, sfrom, r, len);
 }
 
 static void
index 6fe60ea197a56988fb065de589e1129d90ea0fd0..6d86baa460c218968d1abedc793e750b3de812f2 100644 (file)
@@ -2143,7 +2143,6 @@ exit1:
 #endif
        dev_stop(&ctx);
        eloop_free(ctx.eloop);
-       free(ctx.iov[0].iov_base);
 
        if (ctx.options & DHCPCD_STARTED && !(ctx.options & DHCPCD_FORKED))
                loginfox(PACKAGE " exited");
index 3957700655b18beaa3b9d3d9cd1ef9ae4fe43b4a..b135f1b7b8d57c41c1f3ee284d35cf5e38dbf0ec 100644 (file)
@@ -149,7 +149,6 @@ struct dhcpcd_ctx {
        int link_fd;
        int seq;        /* route message sequence no */
        int sseq;       /* successful seq no sent */
-       struct iovec iov[1];    /* generic iovec buffer */
 
 #ifdef USE_SIGNALS
        sigset_t sigset;
@@ -184,15 +183,6 @@ struct dhcpcd_ctx {
        uint8_t *secret;
        size_t secret_len;
 
-       unsigned char ctlbuf[IP6BUFLEN];
-       struct sockaddr_in6 from;
-       struct msghdr sndhdr;
-       struct iovec sndiov[1];
-       unsigned char sndbuf[CMSG_SPACE(sizeof(struct in6_pktinfo))];
-       struct msghdr rcvhdr;
-       char ntopbuf[INET6_ADDRSTRLEN];
-       const char *sfrom;
-
        int nd_fd;
        struct ra_head *ra_routers;
 
index 0fe6d200183c74aa74a300a87f0deddf9bfdb7fd..f638c641840a914509114c7ba0c899fc7867b69f 100644 (file)
@@ -1229,18 +1229,19 @@ if_dispatch(struct dhcpcd_ctx *ctx, const struct rt_msghdr *rtm)
 int
 if_handlelink(struct dhcpcd_ctx *ctx)
 {
-       struct msghdr msg;
+       union {
+               struct rt_msghdr rtmsg;
+               unsigned char buf[2048];
+       } u;
+       struct iovec iov = { .iov_base = u.buf, .iov_len = sizeof(u) };
+       struct msghdr msg = { .msg_iov = &iov, .msg_iovlen = 1 };
        ssize_t len;
 
-       memset(&msg, 0, sizeof(msg));
-       msg.msg_iov = ctx->iov;
-       msg.msg_iovlen = 1;
-
-       len = recvmsg_realloc(ctx->link_fd, &msg, 0);
+       len = recvmsg(ctx->link_fd, &msg, 0);
        if (len == -1)
                return -1;
        if (len != 0)
-               if_dispatch(ctx, ctx->iov[0].iov_base);
+               if_dispatch(ctx, &u.rtmsg);
        return 0;
 }
 
index 99d3ed6ad6bd76f719028c0742fd4af823dcb0af..1e55d672da587eba1671135690ab28cae6848897 100644 (file)
@@ -105,7 +105,6 @@ int if_getssid_wext(const char *ifname, uint8_t *ssid);
 struct priv {
        int route_fd;
        uint32_t route_pid;
-       struct iovec sndrcv_iov[1];
 };
 
 /* We need this to send a broadcast for InfiniBand.
@@ -346,7 +345,6 @@ if_closesockets_os(struct dhcpcd_ctx *ctx)
 
        if (ctx->priv != NULL) {
                priv = (struct priv *)ctx->priv;
-               free(priv->sndrcv_iov[0].iov_base);
                close(priv->route_fd);
        }
 }
@@ -356,21 +354,18 @@ get_netlink(struct dhcpcd_ctx *ctx, struct iovec *iov,
     struct interface *ifp, int fd, int flags,
     int (*callback)(struct dhcpcd_ctx *, struct interface *, struct nlmsghdr *))
 {
-       struct msghdr msg;
-       struct sockaddr_nl nladdr;
+       struct sockaddr_nl nladdr = { .nl_pid = 0 };
+       struct msghdr msg = {
+           .msg_name = &nladdr, .msg_namelen = sizeof(nladdr),
+           .msg_iov = iov, .msg_iovlen = 1,
+       };
        ssize_t len;
        struct nlmsghdr *nlm;
        int r;
        unsigned int again;
 
-       memset(&msg, 0, sizeof(msg));
-       msg.msg_name = &nladdr;
-       msg.msg_namelen = sizeof(nladdr);
-       memset(&nladdr, 0, sizeof(nladdr));
-       msg.msg_iov = iov;
-       msg.msg_iovlen = 1;
 recv_again:
-       if ((len = recvmsg_realloc(fd, &msg, flags)) == -1)
+       if ((len = recvmsg(fd, &msg, flags)) == -1)
                return -1;
        if (len == 0)
                return 0;
@@ -816,8 +811,13 @@ link_netlink(struct dhcpcd_ctx *ctx, struct interface *ifp,
 int
 if_handlelink(struct dhcpcd_ctx *ctx)
 {
+       unsigned char buf[16 * 1024];
+       struct iovec iov = {
+               .iov_base = buf,
+               .iov_len = sizeof(buf),
+       };
 
-       return get_netlink(ctx, ctx->iov, NULL,
+       return get_netlink(ctx, &iov, NULL,
            ctx->link_fd, MSG_DONTWAIT, &link_netlink);
 }
 
@@ -827,12 +827,12 @@ send_netlink(struct dhcpcd_ctx *ctx, struct interface *ifp,
     int (*callback)(struct dhcpcd_ctx *, struct interface *, struct nlmsghdr *))
 {
        int s, r;
-       struct sockaddr_nl snl;
-       struct iovec iov[1];
-       struct msghdr msg;
-
-       memset(&snl, 0, sizeof(snl));
-       snl.nl_family = AF_NETLINK;
+       struct sockaddr_nl snl = { .nl_family = AF_NETLINK };
+       struct iovec iov = { .iov_base = hdr, .iov_len = hdr->nlmsg_len };
+       struct msghdr msg = {
+           .msg_name = &snl, .msg_namelen = sizeof(snl),
+           .msg_iov = &iov, .msg_iovlen = 1
+       };
 
        if (protocol == NETLINK_ROUTE) {
                struct priv *priv;
@@ -844,22 +844,17 @@ send_netlink(struct dhcpcd_ctx *ctx, struct interface *ifp,
                        return -1;
        }
 
-       memset(&msg, 0, sizeof(msg));
-       msg.msg_name = &snl;
-       msg.msg_namelen = sizeof(snl);
-       memset(&iov, 0, sizeof(iov));
-       iov[0].iov_base = hdr;
-       iov[0].iov_len = hdr->nlmsg_len;
-       msg.msg_iov = iov;
-       msg.msg_iovlen = 1;
        /* Request a reply */
        hdr->nlmsg_flags |= NLM_F_ACK;
        hdr->nlmsg_seq = (uint32_t)++ctx->seq;
        if (sendmsg(s, &msg, 0) != -1) {
-               struct priv *priv;
+               unsigned char buf[16 * 1024];
+               struct iovec riov = {
+                       .iov_base = buf,
+                       .iov_len = sizeof(buf),
+               };
 
-               priv = (struct priv *)ctx->priv;
-               r = get_netlink(ctx, priv->sndrcv_iov, ifp, s, 0, callback);
+               r = get_netlink(ctx, &riov, ifp, s, 0, callback);
        } else
                r = -1;
        if (protocol != NETLINK_ROUTE)
@@ -1304,17 +1299,15 @@ _if_initrt(struct dhcpcd_ctx *ctx, __unused struct interface *ifp,
 int
 if_initrt(struct dhcpcd_ctx *ctx, int af)
 {
-       struct nlmr nlm;
+       struct nlmr nlm = {
+           .hdr.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg)),
+           .hdr.nlmsg_type = RTM_GETROUTE,
+           .hdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_MATCH,
+           .rt.rtm_table = RT_TABLE_MAIN,
+           .rt.rtm_family = (unsigned char)af,
+       };
 
        rt_headclear(&ctx->kroutes, af);
-
-       memset(&nlm, 0, sizeof(nlm));
-       nlm.hdr.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg));
-       nlm.hdr.nlmsg_type = RTM_GETROUTE;
-       nlm.hdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_MATCH;
-       nlm.rt.rtm_table = RT_TABLE_MAIN;
-       nlm.rt.rtm_family = (unsigned char)af;
-
        return send_netlink(ctx, NULL, NETLINK_ROUTE, &nlm.hdr, &_if_initrt);
 }
 
@@ -1401,7 +1394,7 @@ bpf_read(struct interface *ifp, int s, void *data, size_t len,
        };
        struct msghdr msg = { .msg_iov = &iov, .msg_iovlen = 1 };
 #ifdef PACKET_AUXDATA
-       unsigned char cmsgbuf[CMSG_LEN(sizeof(struct tpacket_auxdata))];
+       unsigned char cmsgbuf[CMSG_LEN(sizeof(struct tpacket_auxdata))] = { 0 };
        struct cmsghdr *cmsg;
        struct tpacket_auxdata *aux;
 #endif
index d7c2e9c60ea9926970fb4036ffad5e2fe33b7dc9..76111f4e95425005b44998749d93087590eab46c 100644 (file)
@@ -752,17 +752,18 @@ if_dispatch(struct dhcpcd_ctx *ctx, const struct rt_msghdr *rtm)
 int
 if_handlelink(struct dhcpcd_ctx *ctx)
 {
-       struct msghdr msg;
+       union {
+               struct rt_msghdr rtmsg;
+               unsigned char buf[2048];
+       } u;
+       struct iovec iov = { .iov_base = u.buf, .iov_len = sizeof(u) };
+       struct msghdr msg = { .msg_iov = &iov, .msg_iovlen = 1 };
        ssize_t len;
 
-       memset(&msg, 0, sizeof(msg));
-       msg.msg_iov = ctx->iov;
-       msg.msg_iovlen = 1;
-
-       if ((len = recvmsg_realloc(ctx->link_fd, &msg, 0)) == -1)
+       if ((len = recvmsg(ctx->link_fd, &msg, 0)) == -1)
                return -1;
        if (len != 0)
-               if_dispatch(ctx, ctx->iov[0].iov_base);
+               if_dispatch(ctx, &u.rtmsg);
        return 0;
 }
 
index 62ce9cc611a438d31f37fe0baf4efc0b6aec8ec6..d7c73c223c874abd37e7035ea42911871639b64a 100644 (file)
@@ -129,29 +129,14 @@ int
 ipv6_init(struct dhcpcd_ctx *ctx)
 {
 
-       if (ctx->sndhdr.msg_iovlen == 1)
+       if (ctx->ra_routers != NULL)
                return 0;
 
-       if (ctx->ra_routers == NULL) {
-               ctx->ra_routers = malloc(sizeof(*ctx->ra_routers));
-               if (ctx->ra_routers == NULL)
-                       return -1;
-       }
+       ctx->ra_routers = malloc(sizeof(*ctx->ra_routers));
+       if (ctx->ra_routers == NULL)
+               return -1;
        TAILQ_INIT(ctx->ra_routers);
 
-       ctx->sndhdr.msg_namelen = sizeof(struct sockaddr_in6);
-       ctx->sndhdr.msg_iov = ctx->sndiov;
-       ctx->sndhdr.msg_iovlen = 1;
-       ctx->sndhdr.msg_control = ctx->sndbuf;
-       ctx->sndhdr.msg_controllen = sizeof(ctx->sndbuf);
-       ctx->rcvhdr.msg_name = &ctx->from;
-       ctx->rcvhdr.msg_namelen = sizeof(ctx->from);
-       ctx->rcvhdr.msg_iov = ctx->iov;
-       ctx->rcvhdr.msg_iovlen = 1;
-       ctx->rcvhdr.msg_control = ctx->ctlbuf;
-       // controllen is set at recieve
-       //ctx->rcvhdr.msg_controllen = sizeof(ctx->rcvbuf);
-
        ctx->nd_fd = -1;
        ctx->dhcp6_fd = -1;
        return 0;
index 5a248486c9ce0dc323fdb2fa6c22990160ca3476..7f67287ced86fba0c810375b72d298db3c880ff6 100644 (file)
@@ -274,10 +274,17 @@ ipv6nd_sendrsprobe(void *arg)
 {
        struct interface *ifp = arg;
        struct dhcpcd_ctx *ctx;
-       struct rs_state *state;
-       struct sockaddr_in6 dst;
+       struct rs_state *state = RS_STATE(ifp);
+       struct sockaddr_in6 dst = { .sin6_family = AF_INET6 };
+       struct iovec iov = { .iov_base = state->rs, .iov_len = state->rslen };
+       unsigned char ctl[CMSG_SPACE(sizeof(struct in6_pktinfo))] = { 0 };
+       struct msghdr msg = {
+           .msg_name = &dst, .msg_namelen = sizeof(dst),
+           .msg_iov = &iov, .msg_iovlen = 1,
+           .msg_control = ctl, .msg_controllen = sizeof(ctl),
+       };
        struct cmsghdr *cm;
-       struct in6_pktinfo pi;
+       struct in6_pktinfo pi = { .ipi6_ifindex = ifp->index };
 
        if (ipv6_linklocal(ifp) == NULL) {
                logdebugx("%s: delaying Router Solicitation for LL address",
@@ -286,8 +293,6 @@ ipv6nd_sendrsprobe(void *arg)
                return;
        }
 
-       memset(&dst, 0, sizeof(dst));
-       dst.sin6_family = AF_INET6;
 #ifdef HAVE_SA_LEN
        dst.sin6_len = sizeof(dst);
 #endif
@@ -297,25 +302,19 @@ ipv6nd_sendrsprobe(void *arg)
                return;
        }
 
-       state = RS_STATE(ifp);
        ctx = ifp->ctx;
-       ctx->sndhdr.msg_name = (void *)&dst;
-       ctx->sndhdr.msg_iov[0].iov_base = state->rs;
-       ctx->sndhdr.msg_iov[0].iov_len = state->rslen;
 
        /* Set the outbound interface */
-       cm = CMSG_FIRSTHDR(&ctx->sndhdr);
+       cm = CMSG_FIRSTHDR(&msg);
        if (cm == NULL) /* unlikely */
                return;
        cm->cmsg_level = IPPROTO_IPV6;
        cm->cmsg_type = IPV6_PKTINFO;
        cm->cmsg_len = CMSG_LEN(sizeof(pi));
-       memset(&pi, 0, sizeof(pi));
-       pi.ipi6_ifindex = ifp->index;
        memcpy(CMSG_DATA(cm), &pi, sizeof(pi));
 
        logdebugx("%s: sending Router Solicitation", ifp->name);
-       if (sendmsg(ctx->nd_fd, &ctx->sndhdr, 0) == -1) {
+       if (sendmsg(ctx->nd_fd, &msg, 0) == -1) {
                logerr(__func__);
                /* Allow IPv6ND to continue .... at most a few errors
                 * would be logged.
@@ -341,41 +340,42 @@ ipv6nd_sendadvertisement(void *arg)
        struct ipv6_addr *ia = arg;
        struct interface *ifp = ia->iface;
        struct dhcpcd_ctx *ctx = ifp->ctx;
-       struct sockaddr_in6 dst;
+       struct sockaddr_in6 dst = {
+           .sin6_family = AF_INET6,
+           .sin6_scope_id = ifp->index,
+       };
+       struct iovec iov = { .iov_base = ia->na, .iov_len = ia->na_len };
+       unsigned char ctl[CMSG_SPACE(sizeof(struct in6_pktinfo))] = { 0 };
+       struct msghdr msg = {
+           .msg_name = &dst, .msg_namelen = sizeof(dst),
+           .msg_iov = &iov, .msg_iovlen = 1,
+           .msg_control = ctl, .msg_controllen = sizeof(ctl),
+       };
        struct cmsghdr *cm;
-       struct in6_pktinfo pi;
+       struct in6_pktinfo pi = { .ipi6_ifindex = ifp->index };
        const struct rs_state *state = RS_CSTATE(ifp);
 
        if (state == NULL || ifp->carrier <= LINK_DOWN)
                goto freeit;
 
-       memset(&dst, 0, sizeof(dst));
-       dst.sin6_family = AF_INET6;
 #ifdef SIN6_LEN
        dst.sin6_len = sizeof(dst);
 #endif
-       dst.sin6_scope_id = ifp->index;
        if (inet_pton(AF_INET6, ALLNODES, &dst.sin6_addr) != 1) {
                logerr(__func__);
                return;
        }
 
-       ctx->sndhdr.msg_name = (void *)&dst;
-       ctx->sndhdr.msg_iov[0].iov_base = ia->na;
-       ctx->sndhdr.msg_iov[0].iov_len = ia->na_len;
-
        /* Set the outbound interface. */
-       cm = CMSG_FIRSTHDR(&ctx->sndhdr);
+       cm = CMSG_FIRSTHDR(&msg);
        assert(cm != NULL);
        cm->cmsg_level = IPPROTO_IPV6;
        cm->cmsg_type = IPV6_PKTINFO;
        cm->cmsg_len = CMSG_LEN(sizeof(pi));
-       memset(&pi, 0, sizeof(pi));
-       pi.ipi6_ifindex = ifp->index;
        memcpy(CMSG_DATA(cm), &pi, sizeof(pi));
 
        logdebugx("%s: sending NA for %s", ifp->name, ia->saddr);
-       if (sendmsg(ctx->nd_fd, &ctx->sndhdr, 0) == -1)
+       if (sendmsg(ctx->nd_fd, &msg, 0) == -1)
                logerr(__func__);
 
        if (++ia->na_count < MAX_NEIGHBOR_ADVERTISEMENT) {
@@ -872,8 +872,9 @@ dhcp6_start(__unused struct interface *ifp, __unused enum DH6S init_state)
 #endif
 
 static void
-ipv6nd_handlera(struct dhcpcd_ctx *ctx, struct interface *ifp,
-    struct icmp6_hdr *icp, size_t len, int hoplimit)
+ipv6nd_handlera(struct dhcpcd_ctx *ctx,
+    const struct sockaddr_in6 *from, const char *sfrom,
+    struct interface *ifp, struct icmp6_hdr *icp, size_t len, int hoplimit)
 {
        size_t i, olen;
        struct nd_router_advert *nd_ra;
@@ -895,33 +896,29 @@ ipv6nd_handlera(struct dhcpcd_ctx *ctx, struct interface *ifp,
 
        if (ifp == NULL) {
 #ifdef DEBUG_RS
-               logdebugx("RA for unexpected interface from %s",
-                   ctx->sfrom);
+               logdebugx("RA for unexpected interface from %s", sfrom);
 #endif
                return;
        }
 
        if (len < sizeof(struct nd_router_advert)) {
-               logerrx("IPv6 RA packet too short from %s", ctx->sfrom);
+               logerrx("IPv6 RA packet too short from %s", sfrom);
                return;
        }
 
        /* RFC 4861 7.1.2 */
        if (hoplimit != 255) {
-               logerrx("invalid hoplimit(%d) in RA from %s",
-                   hoplimit, ctx->sfrom);
+               logerrx("invalid hoplimit(%d) in RA from %s", hoplimit, sfrom);
                return;
        }
-
-       if (!IN6_IS_ADDR_LINKLOCAL(&ctx->from.sin6_addr)) {
-               logerrx("RA from non local address %s", ctx->sfrom);
+       if (!IN6_IS_ADDR_LINKLOCAL(&from->sin6_addr)) {
+               logerrx("RA from non local address %s", sfrom);
                return;
        }
 
        if (!(ifp->options->options & DHCPCD_IPV6RS)) {
 #ifdef DEBUG_RS
-               logerrx("%s: unexpected RA from %s",
-                   ifp->name, ctx->sfrom);
+               logerrx("%s: unexpected RA from %s", ifp->name, sfrom);
 #endif
                return;
        }
@@ -930,20 +927,20 @@ ipv6nd_handlera(struct dhcpcd_ctx *ctx, struct interface *ifp,
        if (ipv6_linklocal(ifp) == NULL) {
 #ifdef DEBUG_RS
                logdebugx("%s: received RA from %s (no link-local)",
-                   ifp->name, ctx->sfrom);
+                   ifp->name, sfrom);
 #endif
                return;
        }
 
-       if (ipv6_iffindaddr(ifp, &ctx->from.sin6_addr, IN6_IFF_TENTATIVE)) {
+       if (ipv6_iffindaddr(ifp, &from->sin6_addr, IN6_IFF_TENTATIVE)) {
                logdebugx("%s: ignoring RA from ourself %s",
-                   ifp->name, ctx->sfrom);
+                   ifp->name, sfrom);
                return;
        }
 
        TAILQ_FOREACH(rap, ctx->ra_routers, next) {
                if (ifp == rap->iface &&
-                   IN6_ARE_ADDR_EQUAL(&rap->from, &ctx->from.sin6_addr))
+                   IN6_ARE_ADDR_EQUAL(&rap->from, &from->sin6_addr))
                        break;
        }
 
@@ -968,8 +965,8 @@ ipv6nd_handlera(struct dhcpcd_ctx *ctx, struct interface *ifp,
                        return;
                }
                rap->iface = ifp;
-               rap->from = ctx->from.sin6_addr;
-               strlcpy(rap->sfrom, ctx->sfrom, sizeof(rap->sfrom));
+               rap->from = from->sin6_addr;
+               strlcpy(rap->sfrom, sfrom, sizeof(rap->sfrom));
                TAILQ_INIT(&rap->addrs);
                new_rap = true;
        } else
@@ -991,8 +988,7 @@ ipv6nd_handlera(struct dhcpcd_ctx *ctx, struct interface *ifp,
         * in accordance with the own prefix times which would result in too
         * much needless log spam. */
        logfunc = new_rap ? loginfox : logdebugx,
-       logfunc("%s: Router Advertisement from %s",
-           ifp->name, ctx->sfrom);
+       logfunc("%s: Router Advertisement from %s", ifp->name, rap->sfrom);
 
        clock_gettime(CLOCK_MONOTONIC, &rap->acquired);
        rap->flags = nd_ra->nd_ra_flags_reserved;
@@ -1053,10 +1049,10 @@ ipv6nd_handlera(struct dhcpcd_ctx *ctx, struct interface *ifp,
                        }
                        if (dho != NULL)
                                logwarnx("%s: reject RA (option %s) from %s",
-                                   ifp->name, dho->var, ctx->sfrom);
+                                   ifp->name, dho->var, rap->sfrom);
                        else
                                logwarnx("%s: reject RA (option %d) from %s",
-                                   ifp->name, ndo.nd_opt_type, ctx->sfrom);
+                                   ifp->name, ndo.nd_opt_type, rap->sfrom);
                        if (new_rap)
                                ipv6nd_removefreedrop_ra(rap, 0, 0);
                        else
@@ -1196,7 +1192,7 @@ ipv6nd_handlera(struct dhcpcd_ctx *ctx, struct interface *ifp,
                    dho->option))
                {
                        logwarnx("%s: reject RA (no option %s) from %s",
-                           ifp->name, dho->var, ctx->sfrom);
+                           ifp->name, dho->var, rap->sfrom);
                        if (new_rap)
                                ipv6nd_removefreedrop_ra(rap, 0, 0);
                        else
@@ -1584,8 +1580,8 @@ ipv6nd_drop(struct interface *ifp)
 }
 
 static void
-ipv6nd_handlena(struct dhcpcd_ctx *ctx, struct interface *ifp,
-    struct icmp6_hdr *icp, size_t len, int hoplimit)
+ipv6nd_handlena(struct dhcpcd_ctx *ctx, const char *sfrom,
+    struct interface *ifp, struct icmp6_hdr *icp, size_t len, int hoplimit)
 {
        struct nd_neighbor_advert *nd_na;
        struct in6_addr nd_na_target;
@@ -1596,22 +1592,20 @@ ipv6nd_handlena(struct dhcpcd_ctx *ctx, struct interface *ifp,
 
        if (ifp == NULL) {
 #ifdef DEBUG_NS
-               logdebugx("NA for unexpected interface from %s",
-                   ctx->sfrom);
+               logdebugx("NA for unexpected interface from %s", sfrom);
 #endif
                return;
        }
 
        if ((size_t)len < sizeof(struct nd_neighbor_advert)) {
-               logerrx("%s: IPv6 NA too short from %s",
-                   ifp->name, ctx->sfrom);
+               logerrx("%s: IPv6 NA too short from %s", ifp->name, sfrom);
                return;
        }
 
        /* RFC 4861 7.1.2 */
        if (hoplimit != 255) {
                logerrx("invalid hoplimit(%d) in NA from %s",
-                   hoplimit, ctx->sfrom);
+                   hoplimit, sfrom);
                return;
        }
 
@@ -1625,7 +1619,7 @@ ipv6nd_handlena(struct dhcpcd_ctx *ctx, struct interface *ifp,
        memcpy(&nd_na_target, &nd_na->nd_na_target, sizeof(nd_na_target));
        if (IN6_IS_ADDR_MULTICAST(&nd_na_target)) {
                logerrx("%s: NA multicast address %s (%s)",
-                   ifp->name, taddr, ctx->sfrom);
+                   ifp->name, taddr, sfrom);
                return;
        }
 
@@ -1637,20 +1631,20 @@ ipv6nd_handlena(struct dhcpcd_ctx *ctx, struct interface *ifp,
        if (rap == NULL) {
 #ifdef DEBUG_NS
                logdebugx("%s: unexpected NA from %s for %s",
-                   ifp->name, ctx->sfrom, taddr);
+                   ifp->name, sfrom, taddr);
 #endif
                return;
        }
 
 #ifdef DEBUG_NS
        logdebugx("%s: %sNA for %s from %s",
-           ifp->name, is_solicited ? "solicited " : "", taddr, ctx->sfrom);
+           ifp->name, is_solicited ? "solicited " : "", taddr, sfrom);
 #endif
 
        /* Node is no longer a router, so remove it from consideration */
        if (!is_router && !rap->expired) {
                loginfox("%s: %s not a router (%s)",
-                   ifp->name, taddr, ctx->sfrom);
+                   ifp->name, taddr, sfrom);
                rap->expired = 1;
                rt_build(ifp->ctx,  AF_INET6);
                script_runreason(ifp, "ROUTERADVERT");
@@ -1665,33 +1659,43 @@ static void
 ipv6nd_handledata(void *arg)
 {
        struct dhcpcd_ctx *ctx;
+       struct sockaddr_in6 from;
+       unsigned char buf[64 * 1024]; /* Maximum ICMPv6 size */
+       struct iovec iov = {
+               .iov_base = buf,
+               .iov_len = sizeof(buf),
+       };
+       unsigned char ctl[CMSG_SPACE(sizeof(struct in6_pktinfo)) + CMSG_SPACE(sizeof(int))] = { 0 };
+       struct msghdr msg = {
+           .msg_name = &from, .msg_namelen = sizeof(from),
+           .msg_iov = &iov, .msg_iovlen = 1,
+           .msg_control = ctl, .msg_controllen = sizeof(ctl),
+       };
        ssize_t len;
        struct cmsghdr *cm;
+       char sfrom[INET6_ADDRSTRLEN];
        int hoplimit;
        struct in6_pktinfo pkt;
        struct icmp6_hdr *icp;
        struct interface *ifp;
 
        ctx = arg;
-       ctx->rcvhdr.msg_controllen = CMSG_SPACE(sizeof(struct in6_pktinfo)) +
-           CMSG_SPACE(sizeof(int));
-       len = recvmsg_realloc(ctx->nd_fd, &ctx->rcvhdr, 0);
+       len = recvmsg(ctx->nd_fd, &msg, 0);
        if (len == -1) {
                logerr(__func__);
                return;
        }
-       ctx->sfrom = inet_ntop(AF_INET6, &ctx->from.sin6_addr,
-           ctx->ntopbuf, INET6_ADDRSTRLEN);
+       inet_ntop(AF_INET6, &from.sin6_addr, sfrom, sizeof(sfrom));
        if ((size_t)len < sizeof(struct icmp6_hdr)) {
-               logerrx("IPv6 ICMP packet too short from %s", ctx->sfrom);
+               logerrx("IPv6 ICMP packet too short from %s", sfrom);
                return;
        }
 
        pkt.ipi6_ifindex = 0;
        hoplimit = 0;
-       for (cm = (struct cmsghdr *)CMSG_FIRSTHDR(&ctx->rcvhdr);
+       for (cm = (struct cmsghdr *)CMSG_FIRSTHDR(&msg);
             cm;
-            cm = (struct cmsghdr *)CMSG_NXTHDR(&ctx->rcvhdr, cm))
+            cm = (struct cmsghdr *)CMSG_NXTHDR(&msg, cm))
        {
                if (cm->cmsg_level != IPPROTO_IPV6)
                        continue;
@@ -1708,7 +1712,7 @@ ipv6nd_handledata(void *arg)
        }
 
        if (pkt.ipi6_ifindex == 0) {
-               logerrx("IPv6 RA/NA did not contain index from %s", ctx->sfrom);
+               logerrx("IPv6 RA/NA did not contain index from %s", sfrom);
                return;
        }
 
@@ -1724,22 +1728,22 @@ ipv6nd_handledata(void *arg)
            !(ifp->options->options & DHCPCD_IPV6)))
                return;
 
-       icp = (struct icmp6_hdr *)ctx->rcvhdr.msg_iov[0].iov_base;
+       icp = (struct icmp6_hdr *)buf;
        if (icp->icmp6_code == 0) {
                switch(icp->icmp6_type) {
                        case ND_NEIGHBOR_ADVERT:
-                               ipv6nd_handlena(ctx, ifp, icp, (size_t)len,
-                                  hoplimit);
+                               ipv6nd_handlena(ctx, sfrom,
+                                   ifp, icp, (size_t)len, hoplimit);
                                return;
                        case ND_ROUTER_ADVERT:
-                               ipv6nd_handlera(ctx, ifp, icp, (size_t)len,
-                                  hoplimit);
+                               ipv6nd_handlera(ctx, &from, sfrom,
+                                   ifp, icp, (size_t)len, hoplimit);
                                return;
                }
        }
 
        logerrx("invalid IPv6 type %d or code %d from %s",
-           icp->icmp6_type, icp->icmp6_code, ctx->sfrom);
+           icp->icmp6_type, icp->icmp6_code, sfrom);
 }
 
 static void