Module Name: src
Committed By: roy
Date: Wed Apr 17 23:35:35 UTC 2019
Modified Files:
src/external/bsd/dhcpcd/dist/src: dhcp.c dhcp6.c dhcpcd.c if-bsd.c
if-options.c ipv6nd.c
Log Message:
Sync
To generate a diff of this commit:
cvs rdiff -u -r1.16 -r1.17 src/external/bsd/dhcpcd/dist/src/dhcp.c
cvs rdiff -u -r1.4 -r1.5 src/external/bsd/dhcpcd/dist/src/dhcp6.c \
src/external/bsd/dhcpcd/dist/src/if-bsd.c \
src/external/bsd/dhcpcd/dist/src/ipv6nd.c
cvs rdiff -u -r1.17 -r1.18 src/external/bsd/dhcpcd/dist/src/dhcpcd.c
cvs rdiff -u -r1.12 -r1.13 src/external/bsd/dhcpcd/dist/src/if-options.c
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/external/bsd/dhcpcd/dist/src/dhcp.c
diff -u src/external/bsd/dhcpcd/dist/src/dhcp.c:1.16 src/external/bsd/dhcpcd/dist/src/dhcp.c:1.17
--- src/external/bsd/dhcpcd/dist/src/dhcp.c:1.16 Thu Feb 7 21:37:36 2019
+++ src/external/bsd/dhcpcd/dist/src/dhcp.c Wed Apr 17 23:35:34 2019
@@ -86,9 +86,9 @@
#define IPDEFTTL 64 /* RFC1340 */
#endif
-/* NetBSD-7 has an incomplete IP_PKTINFO implementation. */
-#if defined(__NetBSD_Version__) && __NetBSD_Version__ < 800000000
-#undef IP_PKTINFO
+/* Support older systems with different defines */
+#if !defined(IP_RECVPKTINFO) && defined(IP_PKTINFO)
+#define IP_RECVPKTINFO IP_PKTINFO
#endif
/* Assert the correct structure size for on wire */
@@ -129,6 +129,9 @@ static void dhcp_arp_conflicted(struct a
#endif
static void dhcp_handledhcp(struct interface *, struct bootp *, size_t,
const struct in_addr *);
+#ifdef IP_PKTINFO
+static void dhcp_handleifudp(void *);
+#endif
static int dhcp_initstate(struct interface *);
void
@@ -447,7 +450,7 @@ decode_rfc3442_rt(struct rt_head *routes
memcpy(&gateway.s_addr, p, 4);
p += 4;
- /* A host route is normally set by having the
+ /* An on-link host route is normally set by having the
* gateway match the destination or assigned address */
if (gateway.s_addr == dest.s_addr ||
(gateway.s_addr == bootp->yiaddr ||
@@ -455,17 +458,14 @@ decode_rfc3442_rt(struct rt_head *routes
{
gateway.s_addr = INADDR_ANY;
netmask.s_addr = INADDR_BROADCAST;
- rt->rt_flags = RTF_HOST;
}
+ if (netmask.s_addr == INADDR_BROADCAST)
+ rt->rt_flags = RTF_HOST;
sa_in_init(&rt->rt_dest, &dest);
sa_in_init(&rt->rt_netmask, &netmask);
sa_in_init(&rt->rt_gateway, &gateway);
- /* If CIDR is 32 then it's a host route. */
- if (cidr == 32)
- rt->rt_flags = RTF_HOST;
-
TAILQ_INSERT_TAIL(routes, rt, rt_next);
n++;
}
@@ -638,7 +638,7 @@ get_option_routes(struct rt_head *routes
if ((rt = rt_new(ifp)) == NULL)
return -1;
- /* A host route is normally set by having the
+ /* A on-link host route is normally set by having the
* gateway match the destination or assigned address */
if (gateway.s_addr == dest.s_addr ||
(gateway.s_addr == bootp->yiaddr ||
@@ -646,12 +646,15 @@ get_option_routes(struct rt_head *routes
{
gateway.s_addr = INADDR_ANY;
netmask.s_addr = INADDR_BROADCAST;
- rt->rt_flags = RTF_HOST;
} else
netmask.s_addr = route_netmask(dest.s_addr);
+ if (netmask.s_addr == INADDR_BROADCAST)
+ rt->rt_flags = RTF_HOST;
+
sa_in_init(&rt->rt_dest, &dest);
sa_in_init(&rt->rt_netmask, &netmask);
sa_in_init(&rt->rt_gateway, &gateway);
+
TAILQ_INSERT_TAIL(routes, rt, rt_next);
n++;
}
@@ -1587,6 +1590,11 @@ dhcp_close(struct interface *ifp)
state->bpf_fd = -1;
state->bpf_flags |= BPF_EOF;
}
+ if (state->udp_fd != -1) {
+ eloop_event_delete(ifp->ctx->eloop, state->udp_fd);
+ close(state->udp_fd);
+ state->udp_fd = -1;
+ }
state->interval = 0;
}
@@ -1604,11 +1612,15 @@ dhcp_openudp(struct interface *ifp)
n = 1;
if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &n, sizeof(n)) == -1)
goto eexit;
+#ifdef IP_RECVPKTINFO
+ if (setsockopt(s, IPPROTO_IP, IP_RECVPKTINFO, &n, sizeof(n)) == -1)
+ goto eexit;
+#endif
memset(&sin, 0, sizeof(sin));
sin.sin_family = AF_INET;
sin.sin_port = htons(BOOTPC);
if (ifp) {
- struct dhcp_state *state = D_STATE(ifp);
+ const struct dhcp_state *state = D_CSTATE(ifp);
if (state->addr)
sin.sin_addr.s_addr = state->addr->addr.s_addr;
@@ -1699,12 +1711,8 @@ dhcp_sendudp(struct interface *ifp, stru
struct msghdr msg;
struct sockaddr_in sin;
struct iovec iov[1];
+ struct dhcp_state *state = D_STATE(ifp);
ssize_t r;
-#ifdef IP_PKTINFO
- uint8_t cmsg[CMSG_SPACE(sizeof(struct in_pktinfo))];
- struct cmsghdr *cm;
- struct in_pktinfo ipi;
-#endif
iov[0].iov_base = data;
iov[0].iov_len = len;
@@ -1723,29 +1731,15 @@ dhcp_sendudp(struct interface *ifp, stru
msg.msg_iov = iov;
msg.msg_iovlen = 1;
-#ifdef IP_PKTINFO
- /* Set the outbound interface */
- msg.msg_control = cmsg;
- msg.msg_controllen = sizeof(cmsg);
-
- memset(&ipi, 0, sizeof(ipi));
- ipi.ipi_ifindex = ifp->index;
- cm = CMSG_FIRSTHDR(&msg);
- if (cm == NULL) {
- errno = ESRCH;
- return -1;
+ s = state->udp_fd;
+ if (s == -1) {
+ s = dhcp_openudp(ifp);
+ if (s == -1)
+ return -1;
}
- cm->cmsg_level = IPPROTO_IP;
- cm->cmsg_type = IP_PKTINFO;
- cm->cmsg_len = CMSG_LEN(sizeof(ipi));
- memcpy(CMSG_DATA(cm), &ipi, sizeof(ipi));
-#endif
-
- s = dhcp_openudp(ifp);
- if (s == -1)
- return -1;
r = sendmsg(s, &msg, 0);
- close(s);
+ if (state->udp_fd == -1)
+ close(s);
return r;
}
@@ -1803,7 +1797,7 @@ send_message(struct interface *ifp, uint
else
to.s_addr = INADDR_ANY;
- /* If unicasting, try and void sending by BPF so we don't
+ /* If unicasting, try and avoid sending by BPF so we don't
* use a L2 broadcast. */
if (to.s_addr != INADDR_ANY && to.s_addr != INADDR_BROADCAST) {
if (dhcp_sendudp(ifp, &to, bootp, len) != -1)
@@ -2068,11 +2062,6 @@ dhcp_arp_probed(struct arp_state *astate
return;
}
arp_free(astate);
-#ifdef KERNEL_RFC5227
- /* As arping is finished, close the ARP socket.
- * The kernel will handle ACD from here. */
- arp_close(ifp);
-#endif
dhcpcd_startinterface(ifp);
return;
}
@@ -2150,11 +2139,6 @@ dhcp_arp_conflicted(struct arp_state *as
return;
}
arp_free(astate);
-#ifdef KERNEL_RFC5227
- /* As arping is finished, close the ARP socket.
- * The kernel will handle ACD from here. */
- arp_close(ifp);
-#endif
eloop_timeout_delete(ifp->ctx->eloop, NULL, ifp);
dhcpcd_startinterface(ifp);
return;
@@ -2209,11 +2193,22 @@ dhcp_arp_conflicted(struct arp_state *as
return;
}
}
+
+static void
+dhcp_arp_announced(struct arp_state *state)
+{
+
+// TODO: DHCP addresses handle ACD?
+//#ifdef KERNEL_RFC5227
+ arp_free(state);
+//#endif
+}
#endif
void
dhcp_bind(struct interface *ifp)
{
+ struct dhcpcd_ctx *ctx = ifp->ctx;
struct dhcp_state *state = D_STATE(ifp);
struct if_options *ifo = ifp->options;
struct dhcp_lease *lease = &state->lease;
@@ -2289,10 +2284,10 @@ dhcp_bind(struct interface *ifp)
lease->leasetime);
}
}
- if (ifp->ctx->options & DHCPCD_TEST) {
+ if (ctx->options & DHCPCD_TEST) {
state->reason = "TEST";
script_runreason(ifp, state->reason);
- eloop_exit(ifp->ctx->eloop, EXIT_SUCCESS);
+ eloop_exit(ctx->eloop, EXIT_SUCCESS);
return;
}
if (state->reason == NULL) {
@@ -2311,26 +2306,42 @@ dhcp_bind(struct interface *ifp)
if (lease->leasetime == ~0U)
lease->renewaltime = lease->rebindtime = lease->leasetime;
else {
- eloop_timeout_add_sec(ifp->ctx->eloop,
+ eloop_timeout_add_sec(ctx->eloop,
(time_t)lease->renewaltime, dhcp_startrenew, ifp);
- eloop_timeout_add_sec(ifp->ctx->eloop,
+ eloop_timeout_add_sec(ctx->eloop,
(time_t)lease->rebindtime, dhcp_rebind, ifp);
- eloop_timeout_add_sec(ifp->ctx->eloop,
+ eloop_timeout_add_sec(ctx->eloop,
(time_t)lease->leasetime, dhcp_expire, ifp);
logdebugx("%s: renew in %"PRIu32" seconds, rebind in %"PRIu32
" seconds",
ifp->name, lease->renewaltime, lease->rebindtime);
}
state->state = DHS_BOUND;
- /* Re-apply the filter because we need to accept any XID anymore. */
- if (bpf_bootp(ifp, state->bpf_fd) == -1)
- logerr(__func__); /* try to continue */
if (!state->lease.frominfo &&
!(ifo->options & (DHCPCD_INFORM | DHCPCD_STATIC)))
if (write_lease(ifp, state->new, state->new_len) == -1)
logerr(__func__);
ipv4_applyaddr(ifp);
+
+#ifdef IP_PKTINFO
+ /* Close the BPF filter as we can now receive the DHCP renew messages
+ * on a UDP socket. */
+ if (state->udp_fd == -1 ||
+ (state->old != NULL && state->old->yiaddr != state->new->yiaddr))
+ {
+ dhcp_close(ifp);
+ /* If not in master mode, open an address specific socket. */
+ if (ctx->udp_fd == -1) {
+ state->udp_fd = dhcp_openudp(ifp);
+ if (state->udp_fd == -1)
+ logerr(__func__);
+ else
+ eloop_event_add(ctx->eloop,
+ state->udp_fd, dhcp_handleifudp, ifp);
+ }
+ }
+#endif
}
static void
@@ -2384,6 +2395,20 @@ dhcp_message_new(struct bootp **bootp,
}
#ifdef ARP
+static struct arp_state *
+dhcp_arp_new(struct interface *ifp, struct in_addr *addr)
+{
+ struct arp_state *astate;
+ astate = arp_new(ifp, addr);
+ if (astate == NULL)
+ return NULL;
+
+ astate->probed_cb = dhcp_arp_probed;
+ astate->conflicted_cb = dhcp_arp_conflicted;
+ astate->announced_cb = dhcp_arp_announced;
+ return astate;
+}
+
static int
dhcp_arp_address(struct interface *ifp)
{
@@ -2400,10 +2425,9 @@ dhcp_arp_address(struct interface *ifp)
/* If the interface already has the address configured
* then we can't ARP for duplicate detection. */
ia = ipv4_iffindaddr(ifp, &addr, NULL);
- if ((astate = arp_new(ifp, &addr)) == NULL)
+ astate = dhcp_arp_new(ifp, &addr);
+ if (astate == NULL)
return -1;
- astate->probed_cb = dhcp_arp_probed;
- astate->conflicted_cb = dhcp_arp_conflicted;
#ifdef IN_IFF_TENTATIVE
if (ia == NULL || ia->addr_flags & IN_IFF_NOTUSEABLE) {
@@ -2440,7 +2464,8 @@ static void
dhcp_arp_bind(struct interface *ifp)
{
- if (dhcp_arp_address(ifp) == 1)
+ if (ifp->ctx->options & DHCPCD_TEST ||
+ dhcp_arp_address(ifp) == 1)
dhcp_bind(ifp);
}
#endif
@@ -2879,14 +2904,11 @@ dhcp_handledhcp(struct interface *ifp, s
#define LOGDHCP(l, m) \
log_dhcp((l), (m), ifp, bootp, bootp_len, from, 1)
- /* Handled in our BPF filter. */
-#if 0
if (bootp->op != BOOTREPLY) {
logdebugx("%s: op (%d) is not BOOTREPLY",
ifp->name, bootp->op);
return;
}
-#endif
if (state->xid != ntohl(bootp->xid)) {
if (state->state != DHS_BOUND && state->state != DHS_NONE)
@@ -3190,6 +3212,7 @@ dhcp_handledhcp(struct interface *ifp, s
state->reason = "TEST";
script_runreason(ifp, state->reason);
eloop_exit(ifp->ctx->eloop, EXIT_SUCCESS);
+ state->bpf_flags |= BPF_EOF;
return;
}
eloop_timeout_delete(ifp->ctx->eloop, send_discover, ifp);
@@ -3337,6 +3360,30 @@ valid_udp_packet(void *data, size_t data
}
static void
+dhcp_handlebootp(struct interface *ifp, struct bootp *bootp, size_t len,
+ struct in_addr *from)
+{
+ size_t v;
+
+ /* udp_len must be correct because the values are checked in
+ * valid_udp_packet(). */
+ if (len < offsetof(struct bootp, vend)) {
+ logerrx("%s: truncated packet (%zu) from %s",
+ ifp->name, len, inet_ntoa(*from));
+ return;
+ }
+ /* To make our IS_DHCP macro easy, ensure the vendor
+ * area has at least 4 octets. */
+ v = len - offsetof(struct bootp, vend);
+ while (v < 4) {
+ bootp->vend[v++] = '\0';
+ len++;
+ }
+
+ dhcp_handledhcp(ifp, bootp, len, from);
+}
+
+static void
dhcp_handlepacket(struct interface *ifp, uint8_t *data, size_t len)
{
struct bootp *bootp;
@@ -3370,22 +3417,7 @@ dhcp_handlepacket(struct interface *ifp,
* dhcpcd can work fine without the vendor area being sent.
*/
bootp = get_udp_data(data, &udp_len);
- /* udp_len must be correct because the values are checked in
- * valid_udp_packet(). */
- if (udp_len < offsetof(struct bootp, vend)) {
- logerrx("%s: truncated packet (%zu) from %s",
- ifp->name, udp_len, inet_ntoa(from));
- return;
- }
- /* To make our IS_DHCP macro easy, ensure the vendor
- * area has at least 4 octets. */
- len = udp_len - offsetof(struct bootp, vend);
- while (len < 4) {
- bootp->vend[len++] = '\0';
- udp_len++;
- }
-
- dhcp_handledhcp(ifp, bootp, udp_len, &from);
+ dhcp_handlebootp(ifp, bootp, udp_len, &from);
}
static void
@@ -3421,23 +3453,76 @@ dhcp_readpacket(void *arg)
}
static void
-dhcp_handleudp(void *arg)
+dhcp_readudp(struct dhcpcd_ctx *ctx, struct interface *ifp)
{
- struct dhcpcd_ctx *ctx;
- uint8_t buffer[MTU_MAX];
+ struct sockaddr_in from;
+ unsigned char buf[10 * 1024]; /* Maximum MTU */
+ struct iovec iov = {
+ .iov_base = buf,
+ .iov_len = sizeof(buf),
+ };
+#ifdef IP_PKTINFO
+ unsigned char ctl[CMSG_SPACE(sizeof(struct in_pktinfo))] = { 0 };
+ char sfrom[INET_ADDRSTRLEN];
+#endif
+ struct msghdr msg = {
+ .msg_name = &from, .msg_namelen = sizeof(from),
+ .msg_iov = &iov, .msg_iovlen = 1,
+#ifdef IP_PKTINFO
+ .msg_control = ctl, .msg_controllen = sizeof(ctl),
+#endif
+ };
+ int s;
+ ssize_t bytes;
- ctx = arg;
+ if (ifp != NULL) {
+ const struct dhcp_state *state = D_CSTATE(ifp);
- /* Just read what's in the UDP fd and discard it as we always read
- * from the raw fd */
- if (read(ctx->udp_fd, buffer, sizeof(buffer)) == -1) {
+ s = state->udp_fd;
+ } else
+ s = ctx->udp_fd;
+
+ bytes = recvmsg(s, &msg, 0);
+ if (bytes == -1) {
logerr(__func__);
- eloop_event_delete(ctx->eloop, ctx->udp_fd);
- close(ctx->udp_fd);
- ctx->udp_fd = -1;
+ return;
}
+
+#ifdef IP_PKTINFO
+ inet_ntop(AF_INET, &from.sin_addr, sfrom, sizeof(sfrom));
+
+ if (ifp == NULL) {
+ ifp = if_findifpfromcmsg(ctx, &msg, NULL);
+ if (ifp == NULL) {
+ logerr(__func__);
+ return;
+ }
+ }
+
+ dhcp_handlebootp(ifp, (struct bootp *)buf, (size_t)bytes,
+ &from.sin_addr);
+#endif
}
+static void
+dhcp_handleudp(void *arg)
+{
+ struct dhcpcd_ctx *ctx = arg;
+
+ dhcp_readudp(ctx, NULL);
+}
+
+#ifdef IP_PKTINFO
+static void
+dhcp_handleifudp(void *arg)
+{
+ struct interface *ifp = arg;
+
+ dhcp_readudp(ifp->ctx, ifp);
+
+}
+#endif
+
static int
dhcp_openbpf(struct interface *ifp)
{
@@ -3547,6 +3632,7 @@ dhcp_initstate(struct interface *ifp)
state->state = DHS_NONE;
/* 0 is a valid fd, so init to -1 */
state->bpf_fd = -1;
+ state->udp_fd = -1;
#ifdef ARPING
state->arping_index = -1;
#endif
@@ -3676,12 +3762,9 @@ dhcp_start1(void *arg)
if (ifo->arping_len && state->arping_index < ifo->arping_len) {
struct arp_state *astate;
- astate = arp_new(ifp, NULL);
- if (astate) {
- astate->probed_cb = dhcp_arp_probed;
- astate->conflicted_cb = dhcp_arp_conflicted;
+ astate = dhcp_arp_new(ifp, NULL);
+ if (astate)
dhcp_arp_probed(astate);
- }
return;
}
#endif
@@ -3691,13 +3774,11 @@ dhcp_start1(void *arg)
return;
}
- if (ifo->options & DHCPCD_DHCP && dhcp_openbpf(ifp) == -1)
- return;
-
if (ifo->options & DHCPCD_INFORM) {
dhcp_inform(ifp);
return;
}
+
if (ifp->hwlen == 0 && ifo->clientid[0] == '\0') {
logwarnx("%s: needs a clientid to configure", ifp->name);
dhcp_drop(ifp, "FAIL");
Index: src/external/bsd/dhcpcd/dist/src/dhcp6.c
diff -u src/external/bsd/dhcpcd/dist/src/dhcp6.c:1.4 src/external/bsd/dhcpcd/dist/src/dhcp6.c:1.5
--- src/external/bsd/dhcpcd/dist/src/dhcp6.c:1.4 Thu Feb 7 21:37:36 2019
+++ src/external/bsd/dhcpcd/dist/src/dhcp6.c Wed Apr 17 23:35:34 2019
@@ -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 *);
@@ -797,8 +797,7 @@ dhcp6_makemessage(struct interface *ifp)
m = state->new;
ml = state->new_len;
}
- unicast = NULL;
- /* Depending on state, get the unicast address */
+
switch(state->state) {
case DH6S_INIT: /* FALLTHROUGH */
case DH6S_DISCOVER:
@@ -806,7 +805,6 @@ dhcp6_makemessage(struct interface *ifp)
break;
case DH6S_REQUEST:
type = DHCP6_REQUEST;
- unicast = dhcp6_findmoption(m, ml, D6_OPTION_UNICAST, &uni_len);
break;
case DH6S_CONFIRM:
type = DHCP6_CONFIRM;
@@ -816,20 +814,33 @@ dhcp6_makemessage(struct interface *ifp)
break;
case DH6S_RENEW:
type = DHCP6_RENEW;
- unicast = dhcp6_findmoption(m, ml, D6_OPTION_UNICAST, &uni_len);
break;
case DH6S_INFORM:
type = DHCP6_INFORMATION_REQ;
break;
case DH6S_RELEASE:
type = DHCP6_RELEASE;
- unicast = dhcp6_findmoption(m, ml, D6_OPTION_UNICAST, &uni_len);
break;
default:
errno = EINVAL;
return -1;
}
+ switch(state->state) {
+ case DH6S_REQUEST: /* FALLTHROUGH */
+ case DH6S_RENEW: /* FALLTHROUGH */
+ case DH6S_RELEASE:
+ if (has_option_mask(ifo->nomask6, D6_OPTION_UNICAST)) {
+ unicast = NULL;
+ break;
+ }
+ unicast = dhcp6_findmoption(m, ml, D6_OPTION_UNICAST, &uni_len);
+ break;
+ default:
+ unicast = NULL;
+ break;
+ }
+
/* In non master mode we listen and send from fixed addresses.
* We should try and match an address we have to unicast to,
* but for now this is the safest policy. */
@@ -1157,9 +1168,12 @@ dhcp6_update_auth(struct interface *ifp,
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 +1182,22 @@ dhcp6_sendmessage(struct interface *ifp,
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 +1298,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 +1319,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 +1345,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 +1353,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 +1652,7 @@ dhcp6_fail(struct interface *ifp)
break;
}
- dhcp6_bind(ifp, NULL);
+ dhcp6_bind(ifp, NULL, NULL);
switch (state->state) {
case DH6S_BOUND:
@@ -1911,13 +1913,16 @@ static int
dhcp6_checkstatusok(const struct interface *ifp,
struct dhcp6_message *m, uint8_t *p, size_t len)
{
+ struct dhcp6_state *state;
uint8_t *opt;
uint16_t opt_len, code;
size_t mlen;
void * (*f)(void *, size_t, uint16_t, uint16_t *), *farg;
char buf[32], *sbuf;
const char *status;
+ logfunc_t *logfunc;
+ state = D6_STATE(ifp);
f = p ? dhcp6_findoption : dhcp6_findmoption;
if (p)
farg = p;
@@ -1925,6 +1930,7 @@ dhcp6_checkstatusok(const struct interfa
farg = m;
if ((opt = f(farg, len, D6_OPTION_STATUS_CODE, &opt_len)) == NULL) {
//logdebugx("%s: no status", ifp->name);
+ state->lerror = 0;
return 0;
}
@@ -1934,8 +1940,10 @@ dhcp6_checkstatusok(const struct interfa
}
memcpy(&code, opt, sizeof(code));
code = ntohs(code);
- if (code == D6_STATUS_OK)
+ if (code == D6_STATUS_OK) {
+ state->lerror = 0;
return 1;
+ }
/* Anything after the code is a message. */
opt += sizeof(code);
@@ -1958,8 +1966,13 @@ dhcp6_checkstatusok(const struct interfa
status = sbuf;
}
- logerrx("%s: DHCPv6 REPLY: %s", ifp->name, status);
+ if (state->lerror == code || state->state == DH6S_INIT)
+ logfunc = logdebugx;
+ else
+ logfunc = logerrx;
+ logfunc("%s: DHCPv6 REPLY: %s", ifp->name, status);
free(sbuf);
+ state->lerror = code;
return -1;
}
@@ -2927,7 +2940,7 @@ dhcp6_find_delegates(struct interface *i
#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 +2956,7 @@ dhcp6_bind(struct interface *ifp, const
}
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 +3188,8 @@ dhcp6_bind(struct interface *ifp, const
}
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 +3224,7 @@ dhcp6_recvif(struct interface *ifp, stru
}
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 +3237,14 @@ dhcp6_recvif(struct interface *ifp, stru
!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 +3257,7 @@ dhcp6_recvif(struct interface *ifp, stru
(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 +3268,10 @@ dhcp6_recvif(struct interface *ifp, stru
} 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 +3285,7 @@ dhcp6_recvif(struct interface *ifp, stru
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 +3307,7 @@ dhcp6_recvif(struct interface *ifp, stru
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 +3375,7 @@ dhcp6_recvif(struct interface *ifp, stru
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 +3383,12 @@ dhcp6_recvif(struct interface *ifp, stru
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 +3465,10 @@ dhcp6_recvif(struct interface *ifp, stru
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,97 +3476,81 @@ dhcp6_recvif(struct interface *ifp, stru
}
}
- 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;
}
if (ia != NULL)
ifp = ia->iface;
else {
- struct cmsghdr *cm;
- struct in6_pktinfo pi;
-
- pi.ipi6_ifindex = 0;
- for (cm = (struct cmsghdr *)CMSG_FIRSTHDR(&ctx->rcvhdr);
- cm;
- cm = (struct cmsghdr *)CMSG_NXTHDR(&ctx->rcvhdr, cm))
- {
- if (cm->cmsg_level != IPPROTO_IPV6)
- continue;
- switch(cm->cmsg_type) {
- case IPV6_PKTINFO:
- if (cm->cmsg_len == CMSG_LEN(sizeof(pi)))
- memcpy(&pi, CMSG_DATA(cm), sizeof(pi));
- break;
- }
- }
- if (pi.ipi6_ifindex == 0) {
- logerrx("DHCPv6 reply did not contain index from %s",
- ctx->sfrom);
- return;
- }
-
- TAILQ_FOREACH(ifp, ctx->ifaces, next) {
- if (ifp->index == (unsigned int)pi.ipi6_ifindex)
- break;
- }
+ ifp = if_findifpfromcmsg(ctx, &msg, NULL);
if (ifp == NULL) {
- logerrx("DHCPv6 reply for unexpected interface from %s",
- ctx->sfrom);
+ logerr(__func__);
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 +3584,7 @@ dhcp6_recv(struct dhcpcd_ctx *ctx, struc
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 +3592,7 @@ dhcp6_recv(struct dhcpcd_ctx *ctx, struc
ifp = ifp1;
}
- dhcp6_recvif(ifp, r, len);
+ dhcp6_recvif(ifp, sfrom, r, len);
}
static void
@@ -3812,6 +3805,7 @@ dhcp6_start(struct interface *ifp, enum
gogogo:
state->state = init_state;
+ state->lerror = 0;
dhcp_set_leasefile(state->leasefile, sizeof(state->leasefile),
AF_INET6, ifp);
if (ipv6_linklocal(ifp) == NULL) {
@@ -3831,18 +3825,20 @@ dhcp6_reboot(struct interface *ifp)
struct dhcp6_state *state;
state = D6_STATE(ifp);
- if (state) {
- switch (state->state) {
- case DH6S_BOUND:
- dhcp6_startrebind(ifp);
- break;
- case DH6S_INFORMED:
- dhcp6_startinform(ifp);
- break;
- default:
- dhcp6_startdiscover(ifp);
- break;
- }
+ if (state == NULL)
+ return;
+
+ state->lerror = 0;
+ switch (state->state) {
+ case DH6S_BOUND:
+ dhcp6_startrebind(ifp);
+ break;
+ case DH6S_INFORMED:
+ dhcp6_startinform(ifp);
+ break;
+ default:
+ dhcp6_startdiscover(ifp);
+ break;
}
}
Index: src/external/bsd/dhcpcd/dist/src/if-bsd.c
diff -u src/external/bsd/dhcpcd/dist/src/if-bsd.c:1.4 src/external/bsd/dhcpcd/dist/src/if-bsd.c:1.5
--- src/external/bsd/dhcpcd/dist/src/if-bsd.c:1.4 Thu Feb 7 21:37:36 2019
+++ src/external/bsd/dhcpcd/dist/src/if-bsd.c Wed Apr 17 23:35:34 2019
@@ -99,14 +99,20 @@
#endif
#ifdef INET6
-static void
-ifa_scope(struct sockaddr_in6 *, unsigned int);
+static void ifa_setscope(struct sockaddr_in6 *, unsigned int);
+static unsigned int ifa_getscope(const struct sockaddr_in6 *);
#endif
struct priv {
int pf_inet6_fd;
};
+struct rtm
+{
+ struct rt_msghdr hdr;
+ char buffer[sizeof(struct sockaddr_storage) * RTAX_MAX];
+};
+
int
if_init(__unused struct interface *iface)
{
@@ -418,9 +424,13 @@ if_findsa(struct dhcpcd_ctx *ctx, const
case AF_INET6:
{
const struct sockaddr_in6 *sin;
+ unsigned int scope;
struct ipv6_addr *ia;
sin = (const void *)sa;
+ scope = ifa_getscope(sin);
+ if (scope != 0)
+ return if_findindex(ctx->ifaces, scope);
if ((ia = ipv6_findmaskaddr(ctx, &sin->sin6_addr)))
return ia->iface;
break;
@@ -458,11 +468,7 @@ int
if_route(unsigned char cmd, const struct rt *rt)
{
struct dhcpcd_ctx *ctx;
- struct rtm
- {
- struct rt_msghdr hdr;
- char buffer[sizeof(struct sockaddr_storage) * RTAX_MAX];
- } rtmsg;
+ struct rtm rtmsg;
struct rt_msghdr *rtm = &rtmsg.hdr;
char *bp = rtmsg.buffer;
struct sockaddr_dl sdl;
@@ -577,7 +583,7 @@ if_route(unsigned char cmd, const struct
if_copysa(&gateway.sa, &rt->rt_gateway);
#ifdef INET6
if (gateway.sa.sa_family == AF_INET6)
- ifa_scope(&gateway.sin6, rt->rt_ifp->index);
+ ifa_setscope(&gateway.sin6, rt->rt_ifp->index);
#endif
ADDSA(&gateway.sa);
}
@@ -605,19 +611,27 @@ if_copyrt(struct dhcpcd_ctx *ctx, struct
{
const struct sockaddr *rti_info[RTAX_MAX];
- if (~rtm->rtm_addrs & (RTA_DST | RTA_GATEWAY))
+ if (~rtm->rtm_addrs & (RTA_DST | RTA_GATEWAY)) {
+ errno = EINVAL;
return -1;
+ }
#ifdef RTF_CLONED
- if (rtm->rtm_flags & RTF_CLONED)
+ if (rtm->rtm_flags & RTF_CLONED) {
+ errno = ENOTSUP;
return -1;
+ }
#endif
#ifdef RTF_LOCAL
- if (rtm->rtm_flags & RTF_LOCAL)
+ if (rtm->rtm_flags & RTF_LOCAL) {
+ errno = ENOTSUP;
return -1;
+ }
#endif
#ifdef RTF_BROADCAST
- if (rtm->rtm_flags & RTF_BROADCAST)
+ if (rtm->rtm_flags & RTF_BROADCAST) {
+ errno = ENOTSUP;
return -1;
+ }
#endif
get_addrs(rtm->rtm_addrs, rtm + 1, rti_info);
@@ -688,7 +702,7 @@ if_initrt(struct dhcpcd_ctx *ctx, int af
rtm = (void *)p;
if (if_copyrt(ctx, &rt, rtm) == 0) {
rt.rt_dflags |= RTDF_INIT;
- rt_recvrt(RTM_ADD, &rt);
+ rt_recvrt(RTM_ADD, &rt, rtm->rtm_pid);
}
}
free(buf);
@@ -751,7 +765,7 @@ if_addrflags(const struct interface *ifp
#ifdef INET6
static void
-ifa_scope(struct sockaddr_in6 *sin, unsigned int ifindex)
+ifa_setscope(struct sockaddr_in6 *sin, unsigned int ifindex)
{
#ifdef __KAME__
@@ -771,6 +785,23 @@ ifa_scope(struct sockaddr_in6 *sin, unsi
#endif
}
+static unsigned int
+ifa_getscope(const struct sockaddr_in6 *sin)
+{
+#ifdef __KAME__
+ uint16_t scope;
+#endif
+
+ if (!IN6_IS_ADDR_LINKLOCAL(&sin->sin6_addr))
+ return 0;
+#ifdef __KAME__
+ memcpy(&scope, &sin->sin6_addr.s6_addr[2], sizeof(scope));
+ return (unsigned int)ntohs(scope);
+#else
+ return (unsigned int)sin->sin6_scope_id;
+#endif
+}
+
int
if_address6(unsigned char cmd, const struct ipv6_addr *ia)
{
@@ -810,7 +841,7 @@ if_address6(unsigned char cmd, const str
}
ADDADDR(&ifa.ifra_addr, &ia->addr);
- ifa_scope(&ifa.ifra_addr, ia->iface->index);
+ ifa_setscope(&ifa.ifra_addr, ia->iface->index);
ipv6_mask(&mask, ia->prefix_len);
ADDADDR(&ifa.ifra_prefixmask, &mask);
@@ -887,7 +918,7 @@ if_addrflags6(const struct interface *if
strlcpy(ifr6.ifr_name, ifp->name, sizeof(ifr6.ifr_name));
ifr6.ifr_addr.sin6_family = AF_INET6;
ifr6.ifr_addr.sin6_addr = *addr;
- ifa_scope(&ifr6.ifr_addr, ifp->index);
+ ifa_setscope(&ifr6.ifr_addr, ifp->index);
priv = (struct priv *)ifp->ctx->priv;
if (ioctl(priv->pf_inet6_fd, SIOCGIFAFLAG_IN6, &ifr6) != -1)
flags = ifr6.ifr_ifru.ifru_flags6;
@@ -908,7 +939,7 @@ if_getlifetime6(struct ipv6_addr *ia)
strlcpy(ifr6.ifr_name, ia->iface->name, sizeof(ifr6.ifr_name));
ifr6.ifr_addr.sin6_family = AF_INET6;
ifr6.ifr_addr.sin6_addr = ia->addr;
- ifa_scope(&ifr6.ifr_addr, ia->iface->index);
+ ifa_setscope(&ifr6.ifr_addr, ia->iface->index);
priv = (struct priv *)ia->iface->ctx->priv;
if (ioctl(priv->pf_inet6_fd, SIOCGIFALIFETIME_IN6, &ifr6) == -1)
return -1;
@@ -1010,7 +1041,7 @@ if_rtm(struct dhcpcd_ctx *ctx, const str
}
#endif
- rt_recvrt(rtm->rtm_type, &rt);
+ rt_recvrt(rtm->rtm_type, &rt, rtm->rtm_pid);
}
static void
@@ -1095,7 +1126,7 @@ if_ifa(struct dhcpcd_ctx *ctx, const str
ifra.ifra_addr.sin_len = sizeof(ifra.ifra_addr);
ifra.ifra_addr.sin_addr = addr;
if (ioctl(ctx->pf_inet_fd, SIOCGIFALIAS, &ifra) == -1) {
- if (errno != EADDRNOTAVAIL)
+ if (errno != ENXIO && errno != EADDRNOTAVAIL)
logerr("%s: SIOCGIFALIAS", __func__);
if (ifam->ifam_type != RTM_DELADDR)
break;
@@ -1229,18 +1260,16 @@ if_dispatch(struct dhcpcd_ctx *ctx, cons
int
if_handlelink(struct dhcpcd_ctx *ctx)
{
- struct msghdr msg;
+ struct rtm rtm;
+ struct iovec iov = { .iov_base = &rtm, .iov_len = sizeof(rtm) };
+ 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, &rtm.hdr);
return 0;
}
Index: src/external/bsd/dhcpcd/dist/src/ipv6nd.c
diff -u src/external/bsd/dhcpcd/dist/src/ipv6nd.c:1.4 src/external/bsd/dhcpcd/dist/src/ipv6nd.c:1.5
--- src/external/bsd/dhcpcd/dist/src/ipv6nd.c:1.4 Thu Feb 7 21:37:36 2019
+++ src/external/bsd/dhcpcd/dist/src/ipv6nd.c Wed Apr 17 23:35:35 2019
@@ -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 *i
#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,
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,
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,
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,
* 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,
}
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,
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,
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,
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,
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,81 +1659,63 @@ 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;
- int hoplimit;
- struct in6_pktinfo pkt;
+ char sfrom[INET6_ADDRSTRLEN];
+ int hoplimit = 0;
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);
- cm;
- cm = (struct cmsghdr *)CMSG_NXTHDR(&ctx->rcvhdr, cm))
- {
- if (cm->cmsg_level != IPPROTO_IPV6)
- continue;
- switch(cm->cmsg_type) {
- case IPV6_PKTINFO:
- if (cm->cmsg_len == CMSG_LEN(sizeof(pkt)))
- memcpy(&pkt, CMSG_DATA(cm), sizeof(pkt));
- break;
- case IPV6_HOPLIMIT:
- if (cm->cmsg_len == CMSG_LEN(sizeof(int)))
- memcpy(&hoplimit, CMSG_DATA(cm), sizeof(int));
- break;
- }
- }
-
- if (pkt.ipi6_ifindex == 0) {
- logerrx("IPv6 RA/NA did not contain index from %s", ctx->sfrom);
+ ifp = if_findifpfromcmsg(ctx, &msg, &hoplimit);
+ if (ifp == NULL) {
+ logerr(__func__);
return;
}
- /* Find the receiving interface */
- TAILQ_FOREACH(ifp, ctx->ifaces, next) {
- if (ifp->index == (unsigned int)pkt.ipi6_ifindex)
- break;
- }
-
/* Don't do anything if the user hasn't configured it. */
- if (ifp != NULL &&
- (ifp->active != IF_ACTIVE_USER ||
- !(ifp->options->options & DHCPCD_IPV6)))
+ if (ifp->active != IF_ACTIVE_USER ||
+ !(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
Index: src/external/bsd/dhcpcd/dist/src/dhcpcd.c
diff -u src/external/bsd/dhcpcd/dist/src/dhcpcd.c:1.17 src/external/bsd/dhcpcd/dist/src/dhcpcd.c:1.18
--- src/external/bsd/dhcpcd/dist/src/dhcpcd.c:1.17 Thu Feb 7 21:37:36 2019
+++ src/external/bsd/dhcpcd/dist/src/dhcpcd.c Wed Apr 17 23:35:34 2019
@@ -54,6 +54,7 @@ const char dhcpcd_copyright[] = "Copyrig
#include "dev.h"
#include "dhcp-common.h"
#include "dhcpcd.h"
+#include "dhcp.h"
#include "dhcp6.h"
#include "duid.h"
#include "eloop.h"
@@ -978,7 +979,12 @@ dhcpcd_prestartinterface(void *arg)
if ((!(ifp->ctx->options & DHCPCD_MASTER) ||
ifp->options->options & DHCPCD_IF_UP) &&
- if_up(ifp) == -1)
+ if_up(ifp) == -1
+#ifdef __sun
+ /* Interface could not yet be plumbed. */
+ && errno != ENXIO
+#endif
+ )
logerr("%s: %s", __func__, ifp->name);
if (ifp->options->options & DHCPCD_LINK &&
@@ -1606,9 +1612,6 @@ main(int argc, char **argv)
ctx.cffile = CONFIG;
ctx.control_fd = ctx.control_unpriv_fd = ctx.link_fd = -1;
ctx.pf_inet_fd = -1;
-#ifdef IFLR_ACTIVE
- ctx.pf_link_fd = -1;
-#endif
TAILQ_INIT(&ctx.control_fds);
#ifdef PLUGIN_DEV
@@ -2142,7 +2145,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: src/external/bsd/dhcpcd/dist/src/if-options.c
diff -u src/external/bsd/dhcpcd/dist/src/if-options.c:1.12 src/external/bsd/dhcpcd/dist/src/if-options.c:1.13
--- src/external/bsd/dhcpcd/dist/src/if-options.c:1.12 Thu Feb 7 21:37:36 2019
+++ src/external/bsd/dhcpcd/dist/src/if-options.c Wed Apr 17 23:35:34 2019
@@ -207,11 +207,12 @@ const struct option cf_options[] = {
{NULL, 0, NULL, '\0'}
};
+static const char *default_script = SCRIPT;
+
static char *
-add_environ(struct if_options *ifo, const char *value, int uniq)
+add_environ(char ***array, const char *value, int uniq)
{
- char **newlist;
- char **lst = ifo->environ;
+ char **newlist, **list = *array;
size_t i = 0, l, lv;
char *match = NULL, *p, *n;
@@ -229,8 +230,8 @@ add_environ(struct if_options *ifo, cons
*p++ = '\0';
l = strlen(match);
- while (lst && lst[i]) {
- if (match && strncmp(lst[i], match, l) == 0) {
+ while (list && list[i]) {
+ if (match && strncmp(list[i], match, l) == 0) {
if (uniq) {
n = strdup(value);
if (n == NULL) {
@@ -238,25 +239,25 @@ add_environ(struct if_options *ifo, cons
free(match);
return NULL;
}
- free(lst[i]);
- lst[i] = n;
+ free(list[i]);
+ list[i] = n;
} else {
/* Append a space and the value to it */
- l = strlen(lst[i]);
+ l = strlen(list[i]);
lv = strlen(p);
- n = realloc(lst[i], l + lv + 2);
+ n = realloc(list[i], l + lv + 2);
if (n == NULL) {
logerr(__func__);
free(match);
return NULL;
}
- lst[i] = n;
- lst[i][l] = ' ';
- memcpy(lst[i] + l + 1, p, lv);
- lst[i][l + lv + 1] = '\0';
+ list[i] = n;
+ list[i][l] = ' ';
+ memcpy(list[i] + l + 1, p, lv);
+ list[i][l + lv + 1] = '\0';
}
free(match);
- return lst[i];
+ return list[i];
}
i++;
}
@@ -267,7 +268,7 @@ add_environ(struct if_options *ifo, cons
logerr(__func__);
return NULL;
}
- newlist = reallocarray(lst, i + 2, sizeof(char *));
+ newlist = reallocarray(list, i + 2, sizeof(char *));
if (newlist == NULL) {
logerr(__func__);
free(n);
@@ -275,26 +276,31 @@ add_environ(struct if_options *ifo, cons
}
newlist[i] = n;
newlist[i + 1] = NULL;
- ifo->environ = newlist;
+ *array = newlist;
return newlist[i];
}
-#define parse_string(buf, len, arg) parse_string_hwaddr(buf, len, arg, 0)
+#define PARSE_STRING 0
+#define PARSE_STRING_NULL 1
+#define PARSE_HWADDR 2
+#define parse_string(a, b, c) parse_str((a), (b), (c), PARSE_STRING)
+#define parse_hwaddr(a, b, c) parse_str((a), (b), (c), PARSE_HWADDR)
static ssize_t
-parse_string_hwaddr(char *sbuf, size_t slen, const char *str, int clid)
+parse_str(char *sbuf, size_t slen, const char *str, int flags)
{
size_t l;
- const char *p;
- int i, punt_last = 0;
+ const char *p, *end;
+ int i;
char c[4], cmd;
+ end = str + strlen(str);
/* If surrounded by quotes then it's a string */
if (*str == '"') {
- str++;
- l = strlen(str);
- p = str + l - 1;
- if (*p == '"')
- punt_last = 1;
+ p = end - 1;
+ if (*p == '"') {
+ str++;
+ end = p;
+ }
} else {
l = (size_t)hwaddr_aton(NULL, str);
if ((ssize_t) l != -1 && l > 1) {
@@ -311,13 +317,13 @@ parse_string_hwaddr(char *sbuf, size_t s
l = 0;
/* If processing a string on the clientid, first byte should be
* 0 to indicate a non hardware type */
- if (clid && *str) {
+ if (flags == PARSE_HWADDR && *str) {
if (sbuf)
*sbuf++ = 0;
l++;
}
c[3] = '\0';
- while (*str) {
+ while (str < end) {
if (++l > slen && sbuf) {
errno = ENOBUFS;
return -1;
@@ -385,11 +391,8 @@ parse_string_hwaddr(char *sbuf, size_t s
str++;
}
}
- if (punt_last) {
- if (sbuf)
- *--sbuf = '\0';
- l--;
- }
+ if (flags == PARSE_STRING_NULL && sbuf)
+ *sbuf = '\0';
return (ssize_t)l;
}
@@ -654,7 +657,7 @@ parse_option(struct dhcpcd_ctx *ctx, con
int e, i, t;
long l;
unsigned long u;
- char *p = NULL, *bp, *fp, *np, **nconf;
+ char *p = NULL, *bp, *fp, *np;
ssize_t s;
struct in_addr addr, addr2;
in_addr_t *naddr;
@@ -708,17 +711,33 @@ parse_option(struct dhcpcd_ctx *ctx, con
break;
case 'c':
ARG_REQUIRED;
- free(ifo->script);
- ifo->script = strdup(arg);
- if (ifo->script == NULL)
+ if (ifo->script != default_script)
+ free(ifo->script);
+ s = parse_str(NULL, 0, arg, PARSE_STRING_NULL);
+ if (s == 0) {
+ ifo->script = NULL;
+ break;
+ }
+ dl = (size_t)s;
+ if (s == -1 || (ifo->script = malloc(dl)) == NULL) {
+ ifo->script = NULL;
logerr(__func__);
+ return -1;
+ }
+ parse_str(ifo->script, dl, arg, PARSE_STRING_NULL);
+ if (ifo->script[0] == '\0' ||
+ strcmp(ifo->script, "/dev/null") == 0)
+ {
+ free(ifo->script);
+ ifo->script = NULL;
+ }
break;
case 'd':
ifo->options |= DHCPCD_DEBUG;
break;
case 'e':
ARG_REQUIRED;
- add_environ(ifo, arg, 1);
+ add_environ(&ifo->environ, arg, 1);
break;
case 'h':
if (!arg) {
@@ -969,7 +988,7 @@ parse_option(struct dhcpcd_ctx *ctx, con
return -1;
}
snprintf(p, dl, "skip_hooks=%s", arg);
- add_environ(ifo, p, 0);
+ add_environ(&ifo->environ, p, 0);
free(p);
break;
case 'D':
@@ -1006,8 +1025,8 @@ parse_option(struct dhcpcd_ctx *ctx, con
/* Strings have a type of 0 */;
ifo->clientid[1] = 0;
if (arg)
- s = parse_string_hwaddr((char *)ifo->clientid + 1,
- CLIENTID_MAX_LEN, arg, 1);
+ s = parse_hwaddr((char *)ifo->clientid + 1,
+ CLIENTID_MAX_LEN, arg);
else
s = 0;
if (s == -1) {
@@ -1112,6 +1131,7 @@ parse_option(struct dhcpcd_ctx *ctx, con
sa_in_init(&rt->rt_gateway, &addr3);
TAILQ_INSERT_TAIL(&ifo->routes, rt, rt_next);
*fp = ' ';
+ add_environ(&ifo->config, arg, 0);
} else if (strncmp(arg, "routers=", strlen("routers=")) == 0) {
if (parse_addr(&addr, NULL, p) == -1)
return -1;
@@ -1122,6 +1142,7 @@ parse_option(struct dhcpcd_ctx *ctx, con
sa_in_init(&rt->rt_netmask, &addr2);
sa_in_init(&rt->rt_gateway, &addr);
TAILQ_INSERT_TAIL(&ifo->routes, rt, rt_next);
+ add_environ(&ifo->config, arg, 0);
} else if (strncmp(arg, "interface_mtu=",
strlen("interface_mtu=")) == 0 ||
strncmp(arg, "mtu=", strlen("mtu=")) == 0)
@@ -1149,40 +1170,8 @@ parse_option(struct dhcpcd_ctx *ctx, con
} else
ifo->req_prefix_len = 128;
}
- } else {
- dl = 0;
- if (ifo->config != NULL) {
- while (ifo->config[dl] != NULL) {
- if (strncmp(ifo->config[dl], arg,
- (size_t)(p - arg)) == 0)
- {
- p = strdup(arg);
- if (p == NULL) {
- logerr(__func__);
- return -1;
- }
- free(ifo->config[dl]);
- ifo->config[dl] = p;
- return 1;
- }
- dl++;
- }
- }
- p = strdup(arg);
- if (p == NULL) {
- logerr(__func__);
- return -1;
- }
- nconf = reallocarray(ifo->config, dl+2, sizeof(char *));
- if (nconf == NULL) {
- logerr(__func__);
- free(p);
- return -1;
- }
- ifo->config = nconf;
- ifo->config[dl] = p;
- ifo->config[dl + 1] = NULL;
- }
+ } else
+ add_environ(&ifo->config, arg, 1);
break;
case 'W':
if (parse_addr(&addr, &addr2, arg) != 0)
@@ -2277,6 +2266,7 @@ default_config(struct dhcpcd_ctx *ctx)
ifo->options |= DHCPCD_IF_UP | DHCPCD_LINK | DHCPCD_INITIAL_DELAY;
ifo->timeout = DEFAULT_TIMEOUT;
ifo->reboot = DEFAULT_REBOOT;
+ ifo->script = UNCONST(default_script);
ifo->metric = -1;
ifo->auth.options |= DHCPCD_AUTH_REQUIRE;
TAILQ_INIT(&ifo->routes);
@@ -2626,7 +2616,8 @@ free_options(struct dhcpcd_ctx *ctx, str
free(ifo->config);
}
rt_headclear0(ctx, &ifo->routes, AF_UNSPEC);
- free(ifo->script);
+ if (ifo->script != default_script)
+ free(ifo->script);
free(ifo->arping);
free(ifo->blacklist);
free(ifo->fallback);