This will allow us to abort any BPF read loop if it's reset.
While here, delay restarting DHCP slightly to allow privsep builds
to recover the same error.
Fixes #481.
if (bpf == NULL)
return NULL;
bpf->bpf_ifp = ifp;
+ bpf->bpf_flags = BPF_EOF;
/* /dev/bpf is a cloner on modern kernels */
bpf->bpf_fd = open("/dev/bpf", BPF_OPEN_FLAGS);
/* Get the required BPF buffer length from the kernel. */
if (ioctl(bpf->bpf_fd, BIOCGBLEN, &ibuf_len) == -1)
goto eexit;
+
bpf->bpf_size = (size_t)ibuf_len;
bpf->bpf_buffer = malloc(bpf->bpf_size);
if (bpf->bpf_buffer == NULL)
goto eexit;
+
return bpf;
eexit:
{
struct interface *ifp = astate->iface;
struct dhcp_state *state = D_STATE(ifp);
+ unsigned int delay;
if (!(ifp->options->options & (DHCPCD_INFORM | DHCPCD_STATIC)))
dhcp_decline(ifp);
dhcp_drop(ifp, "EXPIRED");
dhcp_unlink(ifp->ctx, state->leasefile);
- dhcp_start1(ifp);
+
+ // Delay restarting to give time for the BPF ARP process to exit
+ // as we may spawn a new one with a different filter fairly quickly
+ delay = MSEC_PER_SEC +
+ (arc4random_uniform(MSEC_PER_SEC * 2) - MSEC_PER_SEC);
+ eloop_timeout_add_msec(ifp->ctx->eloop, delay, dhcp_start1, ifp);
}
#endif
if (bpf == NULL)
return NULL;
bpf->bpf_ifp = ifp;
+ bpf->bpf_flags = BPF_EOF;
/* Allocate a suitably large buffer for a single packet. */
bpf->bpf_size = ETH_FRAME_LEN;