Module Name: src
Committed By: roy
Date: Tue Sep 19 19:19:21 UTC 2017
Modified Files:
src/external/bsd/dhcpcd/dist: .gitignore
src/external/bsd/dhcpcd/dist/src: bpf.c dhcp.c dhcpcd.c if-options.c
Log Message:
Sync
To generate a diff of this commit:
cvs rdiff -u -r1.3 -r1.4 src/external/bsd/dhcpcd/dist/.gitignore
cvs rdiff -u -r1.3 -r1.4 src/external/bsd/dhcpcd/dist/src/bpf.c
cvs rdiff -u -r1.2 -r1.3 src/external/bsd/dhcpcd/dist/src/dhcp.c
cvs rdiff -u -r1.4 -r1.5 src/external/bsd/dhcpcd/dist/src/dhcpcd.c \
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/.gitignore
diff -u src/external/bsd/dhcpcd/dist/.gitignore:1.3 src/external/bsd/dhcpcd/dist/.gitignore:1.4
--- src/external/bsd/dhcpcd/dist/.gitignore:1.3 Fri Mar 31 20:53:55 2017
+++ src/external/bsd/dhcpcd/dist/.gitignore Tue Sep 19 19:19:21 2017
@@ -24,5 +24,8 @@ hooks/50-ypbind
# Ignore distribution
dhcpcd*.xz*
+# Ignore swap files
+*.swp
+
# Ignore Coverity
cov-int
Index: src/external/bsd/dhcpcd/dist/src/bpf.c
diff -u src/external/bsd/dhcpcd/dist/src/bpf.c:1.3 src/external/bsd/dhcpcd/dist/src/bpf.c:1.4
--- src/external/bsd/dhcpcd/dist/src/bpf.c:1.3 Fri Apr 14 09:56:32 2017
+++ src/external/bsd/dhcpcd/dist/src/bpf.c Tue Sep 19 19:19:21 2017
@@ -166,7 +166,9 @@ bpf_open(struct interface *ifp, int (*fi
if (ioctl(fd, BIOCGBLEN, &ibuf_len) == -1)
goto eexit;
buf_len = (size_t)ibuf_len;
- state = IPV4_STATE(ifp);
+ state = ipv4_getstate(ifp);
+ if (state == NULL)
+ goto eexit;
if (state->buffer_size != buf_len) {
void *nb;
@@ -241,7 +243,7 @@ next:
return bytes;
}
- return bytes;
+ /* NOTREACHED */
}
int
@@ -295,6 +297,9 @@ bpf_close(struct interface *ifp, int fd)
return close(fd);
}
+/* Normally this is needed by bootp.
+ * Once that uses this again, the ARP guard here can be removed. */
+#ifdef ARP
static unsigned int
bpf_cmp_hwaddr(struct bpf_insn *bpf, size_t bpf_len, size_t off,
bool equal, uint8_t *hwaddr, size_t hwaddr_len)
@@ -378,6 +383,7 @@ bpf_cmp_hwaddr(struct bpf_insn *bpf, siz
return (unsigned int)(bp - bpf);
}
+#endif
#ifdef ARP
@@ -589,6 +595,7 @@ static const struct bpf_insn bpf_bootp_f
BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, BOOTREPLY, 1, 0),
BPF_STMT(BPF_RET + BPF_K, 0),
};
+
#define BPF_BOOTP_FILTER_LEN __arraycount(bpf_bootp_filter)
#define BPF_BOOTP_CHADDR_LEN ((BOOTP_CHADDR_LEN / 4) * 3)
#define BPF_BOOTP_XID_LEN 4 /* BOUND check is 4 instructions */
@@ -599,7 +606,9 @@ static const struct bpf_insn bpf_bootp_f
int
bpf_bootp(struct interface *ifp, int fd)
{
+#if 0
const struct dhcp_state *state = D_CSTATE(ifp);
+#endif
struct bpf_insn bpf[BPF_BOOTP_LEN];
struct bpf_insn *bp;
@@ -622,6 +631,8 @@ bpf_bootp(struct interface *ifp, int fd)
memcpy(bp, bpf_bootp_filter, sizeof(bpf_bootp_filter));
bp += BPF_BOOTP_FILTER_LEN;
+ /* These checks won't work when same IP exists on other interfaces. */
+#if 0
if (ifp->hwlen <= sizeof(((struct bootp *)0)->chaddr))
bp += bpf_cmp_hwaddr(bp, BPF_BOOTP_CHADDR_LEN,
offsetof(struct bootp, chaddr),
@@ -654,6 +665,7 @@ bpf_bootp(struct interface *ifp, int fd)
BPF_SET_STMT(bp, BPF_RET + BPF_K, 0);
bp++;
}
+#endif
/* All passed, return the packet
* (Frame length in M0, IP length in M2). */
Index: src/external/bsd/dhcpcd/dist/src/dhcp.c
diff -u src/external/bsd/dhcpcd/dist/src/dhcp.c:1.2 src/external/bsd/dhcpcd/dist/src/dhcp.c:1.3
--- src/external/bsd/dhcpcd/dist/src/dhcp.c:1.2 Tue Sep 5 11:58:55 2017
+++ src/external/bsd/dhcpcd/dist/src/dhcp.c Tue Sep 19 19:19:21 2017
@@ -118,10 +118,13 @@ static const char * const dhcp_params[]
NULL
};
-static int dhcp_open(struct interface *);
+static int dhcp_openbpf(struct interface *);
#ifdef ARP
static void dhcp_arp_conflicted(struct arp_state *, const struct arp_msg *);
#endif
+static void dhcp_handledhcp(struct interface *, struct bootp *, size_t,
+ const struct in_addr *);
+static int dhcp_initstate(struct interface *);
void
dhcp_printoptions(const struct dhcpcd_ctx *ctx,
@@ -483,7 +486,7 @@ decode_rfc3361(const uint8_t *data, size
switch (enc) {
case 0:
if ((r = decode_rfc1035(NULL, 0, data, dl)) > 0) {
- l = (size_t)r;
+ l = (size_t)r + 1;
sip = malloc(l);
if (sip == NULL)
return 0;
@@ -697,7 +700,7 @@ dhcp_get_routes(struct rt_head *routes,
{
const struct dhcp_state *state;
- if ((state = D_CSTATE(ifp)) == NULL || state->state != DHS_BOUND)
+ if ((state = D_CSTATE(ifp)) == NULL || !(state->added & STATE_ADDED))
return 0;
return get_option_routes(routes, ifp, state->new, state->new_len);
}
@@ -1527,11 +1530,14 @@ dhcp_new_xid(struct interface *ifp)
else
state->xid = arc4random();
+ /* We can't do this when sharing leases across interfaes */
+#if 0
/* As the XID changes, re-apply the filter. */
if (state->bpf_fd != -1) {
if (bpf_bootp(ifp, state->bpf_fd) == -1)
logerr(__func__); /* try to continue */
}
+#endif
}
void
@@ -1672,17 +1678,11 @@ send_message(struct interface *ifp, uint
struct if_options *ifo = ifp->options;
struct bootp *bootp;
struct bootp_pkt *udp;
- size_t len;
+ size_t len, ulen;
ssize_t r;
struct in_addr from, to;
- struct ipv4_addr *iap;
struct timespec tv;
- int s;
-#ifdef IN_IFF_NOTUSEABLE
- struct ipv4_addr *ia;
-#endif
- s = -1;
if (!callback) {
/* No carrier? Don't bother sending the packet. */
if (ifp->carrier == LINK_DOWN)
@@ -1714,91 +1714,51 @@ send_message(struct interface *ifp, uint
timespec_to_double(&tv));
}
- if (dhcp_open(ifp) == -1)
+ if (dhcp_openbpf(ifp) == -1)
return;
- iap = state->addr;
- if (state->added && !(state->added & STATE_FAKE) &&
- state->addr != NULL && state->new != NULL &&
-#ifdef IN_IFF_NOTUSEABLE
- ((ia = ipv4_iffindaddr(ifp, &state->addr->addr, NULL)) &&
- !(ia->addr_flags & IN_IFF_NOTUSEABLE)) &&
-#endif
- (state->lease.server.s_addr ||
- ifp->options->options & DHCPCD_INFORM) &&
- IS_DHCP(state->new))
- {
- s = dhcp_openudp(ifp);
- if (s == -1) {
- if (errno != EADDRINUSE)
- logerr("%s: dhcp_openudp", ifp->name);
- /* We cannot renew */
- state->addr = NULL;
- }
- }
-
r = make_message(&bootp, ifp, type);
- state->addr = iap;
if (r == -1)
goto fail;
len = (size_t)r;
from.s_addr = bootp->ciaddr;
- if (s != -1 && from.s_addr != INADDR_ANY)
+ if (from.s_addr != INADDR_ANY)
to.s_addr = state->lease.server.s_addr;
else
to.s_addr = INADDR_ANY;
- if (to.s_addr && to.s_addr != INADDR_BROADCAST) {
- struct sockaddr_in sin;
-
- memset(&sin, 0, sizeof(sin));
- sin.sin_family = AF_INET;
- sin.sin_addr.s_addr = to.s_addr;
- sin.sin_port = htons(BOOTPS);
- r = sendto(s, (uint8_t *)bootp, len, 0,
- (struct sockaddr *)&sin, sizeof(sin));
- if (r == -1)
- logerr("%s: dhcp_sendpacket", ifp->name);
+ udp = dhcp_makeudppacket(&ulen, (uint8_t *)bootp, len, from, to);
+ if (udp == NULL) {
+ logerr("%s: dhcp_makeudppacket", ifp->name);
+ r = 0;
} else {
- size_t ulen;
-
- udp = dhcp_makeudppacket(&ulen, (uint8_t *)bootp, len, from,to);
- if (udp == NULL) {
- logerr("%s: dhcp_makeudppacket", ifp->name);
- r = 0;
- } else {
- r = bpf_send(ifp, state->bpf_fd,
- ETHERTYPE_IP, (uint8_t *)udp, ulen);
- free(udp);
- }
- /* If we failed to send a raw packet this normally means
- * we don't have the ability to work beneath the IP layer
- * for this interface.
- * As such we remove it from consideration without actually
- * stopping the interface. */
- if (r == -1) {
- logerr("%s: if_sendraw", ifp->name);
- switch(errno) {
- case ENETDOWN:
- case ENETRESET:
- case ENETUNREACH:
- case ENOBUFS:
- break;
- default:
- if (!(ifp->ctx->options & DHCPCD_TEST))
- dhcp_drop(ifp, "FAIL");
- dhcp_free(ifp);
- eloop_timeout_delete(ifp->ctx->eloop,
- NULL, ifp);
- callback = NULL;
- }
+ r = bpf_send(ifp, state->bpf_fd,
+ ETHERTYPE_IP, (uint8_t *)udp, ulen);
+ free(udp);
+ }
+ /* If we failed to send a raw packet this normally means
+ * we don't have the ability to work beneath the IP layer
+ * for this interface.
+ * As such we remove it from consideration without actually
+ * stopping the interface. */
+ if (r == -1) {
+ logerr("%s: if_sendraw", ifp->name);
+ switch(errno) {
+ case ENETDOWN:
+ case ENETRESET:
+ case ENETUNREACH:
+ case ENOBUFS:
+ break;
+ default:
+ if (!(ifp->ctx->options & DHCPCD_TEST))
+ dhcp_drop(ifp, "FAIL");
+ eloop_timeout_delete(ifp->ctx->eloop,
+ NULL, ifp);
+ callback = NULL;
}
}
free(bootp);
fail:
- if (s != -1)
- close(s);
-
/* Even if we fail to send a packet we should continue as we are
* as our failure timeouts will change out codepath when needed. */
if (callback)
@@ -1915,9 +1875,10 @@ dhcp_expire1(struct interface *ifp)
dhcp_drop(ifp, "EXPIRE");
unlink(state->leasefile);
state->interval = 0;
- dhcp_discover(ifp);
-
+ if (!(ifp->options->options & DHCPCD_LINK) || ifp->carrier != LINK_DOWN)
+ dhcp_discover(ifp);
}
+
static void
dhcp_expire(void *arg)
{
@@ -1932,7 +1893,7 @@ dhcp_expire(void *arg)
dhcp_expire1(ifp);
}
-#ifdef ARP
+#if defined(ARP) || defined(IN_IFF_DUPLICATED)
static void
dhcp_decline(struct interface *ifp)
{
@@ -2096,7 +2057,6 @@ dhcp_arp_conflicted(struct arp_state *as
dhcp_arp_probed(astate);
return;
}
- dhcp_close(ifp);
arp_free(astate);
#ifdef KERNEL_RFC5227
/* As arping is finished, close the ARP socket.
@@ -2126,9 +2086,11 @@ dhcp_arp_conflicted(struct arp_state *as
astate->failed = astate->addr;
arp_report_conflicted(astate, amsg);
unlink(state->leasefile);
+#ifdef ARP
if (!(ifp->options->options & DHCPCD_STATIC) &&
!state->lease.frominfo)
dhcp_decline(ifp);
+#endif
#ifdef IN_IFF_DUPLICATED
if ((ia = ipv4_iffindaddr(ifp, &astate->addr, NULL)) != NULL)
ipv4_deladdr(ia, 1);
@@ -2346,7 +2308,7 @@ dhcp_arp_address(struct interface *ifp)
state->offer->ciaddr : state->offer->yiaddr;
/* If the interface already has the address configured
* then we can't ARP for duplicate detection. */
- ia = ipv4_findaddr(ifp->ctx, &addr);
+ ia = ipv4_iffindaddr(ifp, &addr, NULL);
if ((astate = arp_new(ifp, &addr)) == NULL)
return -1;
astate->probed_cb = dhcp_arp_probed;
@@ -2489,7 +2451,7 @@ dhcp_reboot_newopts(struct interface *if
struct if_options *ifo;
struct dhcp_state *state = D_STATE(ifp);
- if (state == NULL)
+ if (state == NULL || state->state == DHS_NONE)
return;
ifo = ifp->options;
if ((ifo->options & (DHCPCD_INFORM | DHCPCD_STATIC) &&
@@ -2508,7 +2470,7 @@ dhcp_reboot(struct interface *ifp)
struct if_options *ifo;
struct dhcp_state *state = D_STATE(ifp);
- if (state == NULL)
+ if (state == NULL || state->state == DHS_NONE)
return;
ifo = ifp->options;
state->state = DHS_REBOOT;
@@ -2571,7 +2533,7 @@ dhcp_drop(struct interface *ifp, const c
state = D_STATE(ifp);
/* dhcp_start may just have been called and we don't yet have a state
* but we do have a timeout, so punt it. */
- if (state == NULL) {
+ if (state == NULL || state->state == DHS_NONE) {
eloop_timeout_delete(ifp->ctx->eloop, NULL, ifp);
return;
}
@@ -2610,9 +2572,8 @@ dhcp_drop(struct interface *ifp, const c
#ifdef AUTH
dhcp_auth_reset(&state->auth);
#endif
- dhcp_close(ifp);
- state->state = DHS_INIT;
+ state->state = DHS_NONE;
free(state->offer);
state->offer = NULL;
state->offer_len = 0;
@@ -2642,17 +2603,20 @@ blacklisted_ip(const struct if_options *
return 0;
}
-static int
+#define WHTLST_NONE 0
+#define WHTLST_MATCH 1
+#define WHTLST_NOMATCH 2
+static unsigned int
whitelisted_ip(const struct if_options *ifo, in_addr_t addr)
{
size_t i;
if (ifo->whitelist_len == 0)
- return -1;
+ return WHTLST_NONE;
for (i = 0; i < ifo->whitelist_len; i += 2)
if (ifo->whitelist[i] == (addr & ifo->whitelist[i + 1]))
- return 1;
- return 0;
+ return WHTLST_MATCH;
+ return WHTLST_NOMATCH;
}
static void
@@ -2723,6 +2687,33 @@ log_dhcp(logfunc_t *logfunc, const char
free(a);
}
+/* If we're sharing the same IP address with another interface on the
+ * same network, we may receive the DHCP reply on the wrong interface.
+ * Try and re-direct it here. */
+static void
+dhcp_redirect_dhcp(struct interface *ifp, struct bootp *bootp, size_t bootp_len,
+ const struct in_addr *from)
+{
+ struct interface *ifn;
+ const struct dhcp_state *state;
+ uint32_t xid;
+
+ xid = ntohl(bootp->xid);
+ TAILQ_FOREACH(ifn, ifp->ctx->ifaces, next) {
+ state = D_CSTATE(ifn);
+ if (state == NULL || state->state == DHS_NONE)
+ continue;
+ if (state->xid != xid)
+ continue;
+ if (ifn->hwlen <= sizeof(bootp->chaddr) &&
+ memcmp(bootp->chaddr, ifn->hwaddr, ifn->hwlen))
+ continue;
+ logdebugx("%s: redirecting DHCP message to %s",
+ ifp->name, ifn->name);
+ dhcp_handledhcp(ifn, bootp, bootp_len, from);
+ }
+}
+
static void
dhcp_handledhcp(struct interface *ifp, struct bootp *bootp, size_t bootp_len,
const struct in_addr *from)
@@ -2755,6 +2746,16 @@ dhcp_handledhcp(struct interface *ifp, s
ifp->name, bootp->op);
return;
}
+#endif
+
+ if (state->xid != ntohl(bootp->xid)) {
+ if (state->state != DHS_BOUND && state->state != DHS_NONE)
+ logdebugx("%s: wrong xid 0x%x (expecting 0x%x) from %s",
+ ifp->name, ntohl(bootp->xid), state->xid,
+ inet_ntoa(*from));
+ dhcp_redirect_dhcp(ifp, bootp, bootp_len, from);
+ return;
+ }
if (ifp->hwlen <= sizeof(bootp->chaddr) &&
memcmp(bootp->chaddr, ifp->hwaddr, ifp->hwlen))
@@ -2765,9 +2766,28 @@ dhcp_handledhcp(struct interface *ifp, s
ifp->name, ntohl(bootp->xid),
hwaddr_ntoa(bootp->chaddr, sizeof(bootp->chaddr),
buf, sizeof(buf)));
+ dhcp_redirect_dhcp(ifp, bootp, bootp_len, from);
return;
}
-#endif
+
+ if (!ifp->active)
+ return;
+
+ i = whitelisted_ip(ifp->options, from->s_addr);
+ switch (i) {
+ case WHTLST_NOMATCH:
+ logwarnx("%s: non whitelisted DHCP packet from %s",
+ ifp->name, inet_ntoa(*from));
+ return;
+ case WHTLST_MATCH:
+ break;
+ case WHTLST_NONE:
+ if (blacklisted_ip(ifp->options, from->s_addr) == 1) {
+ logwarnx("%s: blacklisted DHCP packet from %s",
+ ifp->name, inet_ntoa(*from));
+ return;
+ }
+ }
/* We may have found a BOOTP server */
if (get_option_uint8(ifp->ctx, &type,
@@ -2847,17 +2867,6 @@ dhcp_handledhcp(struct interface *ifp, s
return;
}
- /* Handled in our BPF filter. */
-#if 0
- /* Ensure it's the right transaction */
- if (state->xid != ntohl(bootp->xid)) {
- logdebugx("%s: wrong xid 0x%x (expecting 0x%x) from %s",
- ifp->name, ntohl(bootp->xid), state->xid,
- inet_ntoa(*from));
- return;
- }
-#endif
-
if (state->state == DHS_PROBE) {
/* Ignore any DHCP messages whilst probing a lease to bind. */
LOGDHCP(logdebugx, "probing, ignoring");
@@ -2952,7 +2961,9 @@ dhcp_handledhcp(struct interface *ifp, s
case 0:
LOGDHCP(logwarnx, "IPv4LL disabled from");
ipv4ll_drop(ifp);
+#ifdef ARP
arp_drop(ifp);
+#endif
break;
case 1:
LOGDHCP(logwarnx, "IPv4LL enabled from");
@@ -3184,7 +3195,6 @@ dhcp_handlepacket(struct interface *ifp,
{
struct bootp *bootp;
struct in_addr from;
- int i;
size_t udp_len;
const struct dhcp_state *state = D_CSTATE(ifp);
@@ -3194,16 +3204,6 @@ dhcp_handlepacket(struct interface *ifp,
ifp->name, inet_ntoa(from));
return;
}
- i = whitelisted_ip(ifp->options, from.s_addr);
- if (i == 0) {
- logwarnx("%s: non whitelisted DHCP packet from %s",
- ifp->name, inet_ntoa(from));
- return;
- } else if (i != 1 && blacklisted_ip(ifp->options, from.s_addr) == 1) {
- logwarnx("%s: blacklisted DHCP packet from %s",
- ifp->name, inet_ntoa(from));
- return;
- }
if (ifp->flags & IFF_POINTOPOINT &&
(state->addr == NULL || state->addr->brd.s_addr != from.s_addr))
{
@@ -3253,8 +3253,10 @@ dhcp_readpacket(void *arg)
while (!(flags & BPF_EOF)) {
bytes = bpf_read(ifp, state->bpf_fd, buf, sizeof(buf), &flags);
if (bytes == -1) {
- logerr(__func__);
- dhcp_close(ifp);
+ if (state->state != DHS_NONE) {
+ logerr("%s: %s", __func__, ifp->name);
+ dhcp_close(ifp);
+ }
return;
}
dhcp_handlepacket(ifp, buf, (size_t)bytes, flags);
@@ -3284,7 +3286,7 @@ dhcp_handleudp(void *arg)
static int
-dhcp_open(struct interface *ifp)
+dhcp_openbpf1(struct interface *ifp, bool logerror)
{
struct dhcp_state *state;
@@ -3297,8 +3299,8 @@ dhcp_open(struct interface *ifp)
/* May as well disable IPv4 entirely at
* this point as we really need it. */
ifp->options->options &= ~DHCPCD_IPV4;
- } else
- logerr(__func__);
+ } else if (logerror)
+ logerr("%s: %s", __func__, ifp->name);
return -1;
}
eloop_event_add(ifp->ctx->eloop,
@@ -3307,6 +3309,28 @@ dhcp_open(struct interface *ifp)
return 0;
}
+/* This blows chunks.
+ * Because we may (although unlikely) get the same IP address
+ * across different interfaces we need to open a BPF socket
+ * on ALL interfaces as thanks to ARP magic we might get the
+ * DHCP reply on a different interface. */
+static int
+dhcp_openbpf(struct interface *ifp)
+{
+ struct interface *ifn;
+ int r, o;
+
+ r = -1;
+ TAILQ_FOREACH(ifn, ifp->ctx->ifaces, next) {
+ if (dhcp_initstate(ifn) == -1)
+ continue;
+ o = dhcp_openbpf1(ifn, ifn == ifp);
+ if (ifn == ifp)
+ r = o;
+ }
+ return r;
+}
+
int
dhcp_dump(struct interface *ifp)
{
@@ -3339,14 +3363,16 @@ dhcp_free(struct interface *ifp)
struct dhcpcd_ctx *ctx;
dhcp_close(ifp);
+#ifdef ARP
arp_drop(ifp);
+#endif
if (state) {
+ state->state = DHS_NONE;
free(state->old);
free(state->new);
free(state->offer);
free(state->clientid);
free(state);
- ifp->if_data[IF_DATA_DHCP] = NULL;
}
ctx = ifp->ctx;
@@ -3354,7 +3380,8 @@ dhcp_free(struct interface *ifp)
* close the global socket and release resources */
if (ctx->ifaces) {
TAILQ_FOREACH(ifp, ctx->ifaces, next) {
- if (D_STATE(ifp))
+ state = D_STATE(ifp);
+ if (state != NULL && state->state != DHS_NONE)
break;
}
}
@@ -3371,29 +3398,46 @@ dhcp_free(struct interface *ifp)
}
static int
-dhcp_init(struct interface *ifp)
+dhcp_initstate(struct interface *ifp)
{
struct dhcp_state *state;
- const struct if_options *ifo;
- uint8_t len;
- char buf[(sizeof(ifo->clientid) - 1) * 3];
state = D_STATE(ifp);
- if (state == NULL) {
- ifp->if_data[IF_DATA_DHCP] = calloc(1, sizeof(*state));
- state = D_STATE(ifp);
- if (state == NULL)
- return -1;
- /* 0 is a valid fd, so init to -1 */
- state->bpf_fd = -1;
+ if (state != NULL)
+ return 0;
+
+ ifp->if_data[IF_DATA_DHCP] = calloc(1, sizeof(*state));
+ state = D_STATE(ifp);
+ if (state == NULL)
+ return -1;
+ state->state = DHS_NONE;
+ /* 0 is a valid fd, so init to -1 */
+ state->bpf_fd = -1;
#ifdef ARPING
- state->arping_index = -1;
+ state->arping_index = -1;
#endif
+ return 1;
+}
+
+static int
+dhcp_init(struct interface *ifp)
+{
+ struct dhcp_state *state;
+ const struct if_options *ifo;
+ uint8_t len;
+ char buf[(sizeof(ifo->clientid) - 1) * 3];
+ int r;
+
+ r = dhcp_initstate(ifp);
+ if (r == -1)
+ return -1;
+ else if (r == 1) {
/* Now is a good time to find IPv4 routes */
if_initrt(ifp->ctx, AF_INET);
}
+ state = D_STATE(ifp);
state->state = DHS_INIT;
state->reason = "PREINIT";
state->nakoff = 0;
@@ -3513,7 +3557,7 @@ dhcp_start1(void *arg)
return;
}
- if (ifo->options & DHCPCD_DHCP && dhcp_open(ifp) == -1)
+ if (ifo->options & DHCPCD_DHCP && dhcp_openbpf(ifp) == -1)
return;
if (ifo->options & DHCPCD_INFORM) {
@@ -3709,15 +3753,22 @@ dhcp_start(struct interface *ifp)
void
dhcp_abort(struct interface *ifp)
{
-#ifdef ARPING
struct dhcp_state *state;
state = D_STATE(ifp);
+#ifdef ARPING
if (state != NULL)
state->arping_index = -1;
#endif
eloop_timeout_delete(ifp->ctx->eloop, dhcp_start1, ifp);
+
+ if (state != NULL && state->added) {
+ rt_build(ifp->ctx, AF_INET);
+#ifdef ARP
+ arp_announceaddr(ifp->ctx, &state->addr->addr);
+#endif
+ }
}
void
@@ -3730,7 +3781,7 @@ dhcp_handleifa(int cmd, struct ipv4_addr
ifp = ia->iface;
state = D_STATE(ifp);
- if (state == NULL)
+ if (state == NULL || state->state == DHS_NONE)
return;
if (cmd == RTM_DELADDR) {
Index: src/external/bsd/dhcpcd/dist/src/dhcpcd.c
diff -u src/external/bsd/dhcpcd/dist/src/dhcpcd.c:1.4 src/external/bsd/dhcpcd/dist/src/dhcpcd.c:1.5
--- src/external/bsd/dhcpcd/dist/src/dhcpcd.c:1.4 Wed May 10 11:03:44 2017
+++ src/external/bsd/dhcpcd/dist/src/dhcpcd.c Tue Sep 19 19:19:21 2017
@@ -368,7 +368,9 @@ dhcpcd_drop(struct interface *ifp, int s
ipv6_drop(ifp);
ipv4ll_drop(ifp);
dhcp_drop(ifp, stop ? "STOP" : "EXPIRE");
+#ifdef ARP
arp_drop(ifp);
+#endif
}
static void
@@ -532,8 +534,10 @@ configure_interface1(struct interface *i
ifo->ia->ia_type = D6_OPTION_IA_NA;
memcpy(ifo->ia->iaid, ifo->iaid, sizeof(ifo->iaid));
memset(&ifo->ia->addr, 0, sizeof(ifo->ia->addr));
+#ifndef SMALL
ifo->ia->sla = NULL;
ifo->ia->sla_len = 0;
+#endif
}
} else {
size_t i;
@@ -647,10 +651,12 @@ dhcpcd_initstate2(struct interface *ifp,
} else
ifo = ifp->options;
+#ifdef INET6
if (ifo->options & DHCPCD_IPV6 && ipv6_init(ifp->ctx) == -1) {
logerr(__func__);
ifo->options &= ~DHCPCD_IPV6;
}
+#endif
}
static void
@@ -715,10 +721,10 @@ dhcpcd_handlecarrier(struct dhcpcd_ctx *
ifp->carrier = LINK_DOWN;
script_runreason(ifp, "NOCARRIER");
#ifdef NOCARRIER_PRESERVE_IP
+#ifdef ARP
arp_drop(ifp);
+#endif
dhcp_abort(ifp);
- if_sortinterfaces(ctx);
- ipv4_preferanother(ifp);
ipv6nd_expire(ifp, 0);
#else
dhcpcd_drop(ifp, 0);
@@ -858,16 +864,19 @@ dhcpcd_startinterface(void *arg)
ifo->options &= ~DHCPCD_IPV6;
}
if (ifo->options & DHCPCD_IPV6) {
- ipv6_startstatic(ifp);
+ if (ifp->active == IF_ACTIVE_USER) {
+ ipv6_startstatic(ifp);
- if (ifo->options & DHCPCD_IPV6RS)
- ipv6nd_startrs(ifp);
+ if (ifo->options & DHCPCD_IPV6RS)
+ ipv6nd_startrs(ifp);
+ }
if (ifo->options & DHCPCD_DHCP6)
dhcp6_find_delegates(ifp);
- if (!(ifo->options & DHCPCD_IPV6RS) ||
- ifo->options & (DHCPCD_IA_FORCED | DHCPCD_INFORM6))
+ if ((!(ifo->options & DHCPCD_IPV6RS) ||
+ ifo->options & (DHCPCD_IA_FORCED | DHCPCD_INFORM6)) &&
+ ifp->active == IF_ACTIVE_USER)
{
ssize_t nolease;
@@ -897,7 +906,7 @@ dhcpcd_startinterface(void *arg)
}
#ifdef INET
- if (ifo->options & DHCPCD_IPV4) {
+ if (ifo->options & DHCPCD_IPV4 && ifp->active == IF_ACTIVE_USER) {
/* Ensure we have an IPv4 state before starting DHCP */
if (ipv4_getstate(ifp) != NULL)
dhcp_start(ifp);
@@ -1072,6 +1081,9 @@ dhcpcd_handlehwaddr(struct dhcpcd_ctx *c
if (ifp == NULL)
return;
+ if (!if_valid_hwaddr(hwaddr, hwlen))
+ hwlen = 0;
+
if (hwlen > sizeof(ifp->hwaddr)) {
errno = ENOBUFS;
logerr("%s: %s", __func__, ifp->name);
@@ -1131,7 +1143,7 @@ reconf_reboot(struct dhcpcd_ctx *ctx, in
}
if (oi != argc && i == argc)
continue;
- if (ifp->active) {
+ if (ifp->active == IF_ACTIVE_USER) {
if (action)
if_reboot(ifp, argc, argv);
else
@@ -1836,7 +1848,7 @@ printpidfile:
if (ctx.ifc == 1 && !(ctx.options & DHCPCD_BACKGROUND))
ctx.options |= DHCPCD_WAITIP;
- /* Start handling kernel messages for interfaces, addreses and
+ /* Start handling kernel messages for interfaces, addresses and
* routes. */
eloop_event_add(ctx.eloop, ctx.link_fd, dhcpcd_handlelink, &ctx);
Index: src/external/bsd/dhcpcd/dist/src/if-options.c
diff -u src/external/bsd/dhcpcd/dist/src/if-options.c:1.4 src/external/bsd/dhcpcd/dist/src/if-options.c:1.5
--- src/external/bsd/dhcpcd/dist/src/if-options.c:1.4 Wed May 10 11:03:44 2017
+++ src/external/bsd/dhcpcd/dist/src/if-options.c Tue Sep 19 19:19:21 2017
@@ -673,8 +673,10 @@ parse_option(struct dhcpcd_ctx *ctx, con
size_t sl;
struct if_ia *ia;
uint8_t iaid[4];
+#ifndef SMALL
struct if_sla *sla, *slap;
#endif
+#endif
dop = NULL;
dop_len = NULL;
@@ -1317,12 +1319,17 @@ parse_option(struct dhcpcd_ctx *ctx, con
/* FALLTHROUGH */
case O_IA_PD:
if (i == 0) {
+#ifdef SMALL
+ logwarnx("%s: IA_PD not compiled in", ifname);
+ return -1;
+#else
if (ifname == NULL) {
logerr("IA PD must belong in an "
"interface block");
return -1;
}
i = D6_OPTION_IA_PD;
+#endif
}
if (ifname == NULL && arg) {
logerrx("IA with IAID must belong in an "
@@ -1405,12 +1412,15 @@ parse_option(struct dhcpcd_ctx *ctx, con
}
}
}
+#ifndef SMALL
ia->sla_max = 0;
ia->sla_len = 0;
ia->sla = NULL;
+#endif
}
if (ia->ia_type != D6_OPTION_IA_PD)
break;
+#ifndef SMALL
for (p = fp; p; p = fp) {
fp = strwhite(p);
if (fp) {
@@ -1531,6 +1541,7 @@ err_sla:
ia->sla_len--;
return -1;
#endif
+#endif
case O_HOSTNAME_SHORT:
ifo->options |= DHCPCD_HOSTNAME | DHCPCD_HOSTNAME_SHORT;
break;
@@ -2615,7 +2626,7 @@ free_options(struct if_options *ifo)
free_dhcp_opt_embenc(opt);
free(ifo->vivso_override);
-#ifdef INET6
+#if defined(INET6) && !defined(SMALL)
for (; ifo->ia_len > 0; ifo->ia_len--)
free(ifo->ia[ifo->ia_len - 1].sla);
#endif