diff --git a/src/arp.c b/src/arp.c index 466cafa..7d746ec 100644 --- a/src/arp.c +++ b/src/arp.c @@ -257,8 +257,14 @@ static int arp_send(struct client_state_t *cs, struct arpMsg *arp) return -1; } - ssize_t r = safe_sendto(cs->arpFd, (const char *)arp, sizeof *arp, - 0, (struct sockaddr *)&addr, sizeof addr); + ssize_t r; + if (!check_carrier(cs->arpFd)) { + log_error("%s: (%s) carrier down; sendto would fail", + client_config.interface, __func__); + goto carrier_down; + } + r = safe_sendto(cs->arpFd, (const char *)arp, sizeof *arp, 0, + (struct sockaddr *)&addr, sizeof addr); if (r < 0 || (size_t)r != sizeof *arp) { if (r < 0) log_error("%s: (%s) sendto failed: %s", @@ -266,6 +272,7 @@ static int arp_send(struct client_state_t *cs, struct arpMsg *arp) else log_error("%s: (%s) sendto short write: %z < %zu", client_config.interface, __func__, r, sizeof *arp); +carrier_down: arp_reopen_fd(cs); return -1; } diff --git a/src/dhcp.c b/src/dhcp.c index 13e7f13..98a2b2a 100644 --- a/src/dhcp.c +++ b/src/dhcp.c @@ -31,6 +31,7 @@ #include #include #include +#include #include #include #include @@ -107,6 +108,11 @@ static ssize_t send_dhcp_unicast(struct client_state_t *cs, } size_t payload_len = sizeof *payload - (sizeof payload->options - 1 - endloc); + if (!check_carrier(fd)) { + log_error("%s: (%s) carrier down; write would fail", + client_config.interface, __func__); + goto out_fd; + } ret = safe_write(fd, (const char *)payload, payload_len); if (ret < 0 || (size_t)ret != payload_len) log_error("%s: (%s) write failed: %d", client_config.interface, @@ -224,6 +230,22 @@ static ssize_t get_raw_packet(struct client_state_t *cs, return l; } +int check_carrier(int fd) +{ + struct ifreq ifr; + memset(&ifr, 0, sizeof ifr); + memcpy(ifr.ifr_name, client_config.interface, + sizeof client_config.interface); + if (ioctl(fd, SIOCGIFFLAGS, &ifr) == -1) { + log_error("%s: (%s) ioctl failed: %s", client_config.interface, + __func__, strerror(errno)); + return 0; + } + if ((ifr.ifr_flags & IFF_RUNNING) && (ifr.ifr_flags & IFF_UP)) + return 1; + return 0; +} + // Broadcast a DHCP message using a raw socket. static ssize_t send_dhcp_raw(struct dhcpmsg *payload) { @@ -282,6 +304,11 @@ static ssize_t send_dhcp_raw(struct dhcpmsg *payload) .sll_halen = 6, }; memcpy(da.sll_addr, "\xff\xff\xff\xff\xff\xff", 6); + if (!check_carrier(fd)) { + log_error("%s: (%s) carrier down; sendto would fail", + client_config.interface, __func__); + goto carrier_down; + } ret = safe_sendto(fd, (const char *)&iudmsg, iud_len, 0, (struct sockaddr *)&da, sizeof da); if (ret < 0 || (size_t)ret != iud_len) { @@ -292,6 +319,7 @@ static ssize_t send_dhcp_raw(struct dhcpmsg *payload) log_error("%s: (%s) sendto short write: %z < %zu", client_config.interface, __func__, ret, iud_len); } +carrier_down: close(fd); return ret; } diff --git a/src/dhcp.h b/src/dhcp.h index 50e54cc..0bf9a14 100644 --- a/src/dhcp.h +++ b/src/dhcp.h @@ -91,4 +91,6 @@ ssize_t send_rebind(struct client_state_t *cs); ssize_t send_decline(struct client_state_t *cs, uint32_t server); ssize_t send_release(struct client_state_t *cs); +int check_carrier(int fd); + #endif diff --git a/src/seccomp.c b/src/seccomp.c index f896f1d..f20c52f 100644 --- a/src/seccomp.c +++ b/src/seccomp.c @@ -83,6 +83,11 @@ int enforce_seccomp_ndhc(void) ALLOW_SYSCALL(mmap), ALLOW_SYSCALL(munmap), + // For checking to see if the interface carrier is up. Should be + // removed in favor of synchronous requests to ifchd, but it will + // work for now. + ALLOW_SYSCALL(ioctl), + ALLOW_SYSCALL(rt_sigreturn), #ifdef __NR_sigreturn ALLOW_SYSCALL(sigreturn),