From e874373dcd4f364aea3003ebaedde4bb456713b8 Mon Sep 17 00:00:00 2001 From: "Nicholas J. Kain" Date: Sun, 15 Feb 2015 02:50:29 -0500 Subject: [PATCH] Check link carrier via ifch and netlink instead of ioctl. Thus, ioctl can once again be removed from the ndhc seccomp whitelist. --- src/arp.c | 2 +- src/dhcp.c | 20 ++------------------ src/dhcp.h | 2 -- src/ifchange.c | 8 ++++++++ src/ifchange.h | 1 + src/ifchd-parse.rl | 4 +++- src/ifchd.h | 3 ++- src/ifset.c | 21 +++++++++++++++++++++ src/ifset.h | 1 + src/seccomp.c | 5 ----- 10 files changed, 39 insertions(+), 28 deletions(-) diff --git a/src/arp.c b/src/arp.c index e4086c6..d6532d5 100644 --- a/src/arp.c +++ b/src/arp.c @@ -261,7 +261,7 @@ static int arp_send(struct client_state_t cs[static 1], return ret; } - if (!check_carrier(cs->arpFd)) { + if (check_carrier()) { log_error("%s: (%s) carrier down; sendto would fail", client_config.interface, __func__); ret = -99; diff --git a/src/dhcp.c b/src/dhcp.c index 5c877fe..25a2cfc 100644 --- a/src/dhcp.c +++ b/src/dhcp.c @@ -108,7 +108,7 @@ static ssize_t send_dhcp_unicast(struct client_state_t cs[static 1], } size_t payload_len = sizeof *payload - (sizeof payload->options - 1 - endloc); - if (!check_carrier(fd)) { + if (check_carrier()) { log_error("%s: (%s) carrier down; write would fail", client_config.interface, __func__); ret = -99; @@ -228,22 +228,6 @@ static ssize_t get_raw_packet(struct client_state_t cs[static 1], 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[static 1]) { @@ -302,7 +286,7 @@ static ssize_t send_dhcp_raw(struct dhcpmsg payload[static 1]) .sll_halen = 6, }; memcpy(da.sll_addr, "\xff\xff\xff\xff\xff\xff", 6); - if (!check_carrier(fd)) { + if (check_carrier()) { log_error("%s: (%s) carrier down; sendto would fail", client_config.interface, __func__); ret = -99; diff --git a/src/dhcp.h b/src/dhcp.h index 399ea77..bd92e96 100644 --- a/src/dhcp.h +++ b/src/dhcp.h @@ -91,6 +91,4 @@ ssize_t send_rebind(struct client_state_t cs[static 1]); ssize_t send_decline(struct client_state_t cs[static 1], uint32_t server); ssize_t send_release(struct client_state_t cs[static 1]); -int check_carrier(int fd); - #endif diff --git a/src/ifchange.c b/src/ifchange.c index b855572..e110e13 100644 --- a/src/ifchange.c +++ b/src/ifchange.c @@ -225,6 +225,14 @@ static int ifchwrite(const char buf[static 1], size_t count) return -1; } +// Returns 0 if there is a carrier, -1 if not. +int check_carrier(void) +{ + char buf[256]; + snprintf(buf, sizeof buf, "carrier:;"); + return ifchwrite(buf, strlen(buf)); +} + int ifchange_deconfig(struct client_state_t cs[static 1]) { char buf[256]; diff --git a/src/ifchange.h b/src/ifchange.h index f3abc94..fa0137b 100644 --- a/src/ifchange.h +++ b/src/ifchange.h @@ -29,6 +29,7 @@ #ifndef IFCHANGE_H_ #define IFCHANGE_H_ +int check_carrier(void); int ifchange_bind(struct client_state_t cs[static 1], struct dhcpmsg packet[static 1]); int ifchange_deconfig(struct client_state_t cs[static 1]); diff --git a/src/ifchd-parse.rl b/src/ifchd-parse.rl index da0f623..7212a7a 100644 --- a/src/ifchd-parse.rl +++ b/src/ifchd-parse.rl @@ -141,6 +141,7 @@ static int perform_ip4set(const char buf[static 1], size_t len) case STATE_MTU: cmdf |= perform_mtu(tb, arg_len); break; case STATE_NTPSVR: cmdf |= perform_ntpsrv(tb, arg_len); break; case STATE_WINS: cmdf |= perform_wins(tb, arg_len); break; + case STATE_CARRIER: cmdf |= perform_carrier(); break; default: log_line("error: invalid state in dispatch_work"); return -99; @@ -170,8 +171,9 @@ static int perform_ip4set(const char buf[static 1], size_t len) cmd_s32 = ('tzone:' % { cl.state = STATE_TIMEZONE; }) s32_arg; cmd_u16 = ('mtu:' % { cl.state = STATE_MTU; }) u16_arg; cmd_u8 = ('ipttl:' % { cl.state = STATE_IPTTL; }) u8_arg; + cmd_none = ('carrier:' % { cl.state = STATE_CARRIER; }) terminator; - command = (cmd_ip|cmd_ip4set|cmd_iplist|cmd_str|cmd_s32|cmd_u16|cmd_u8); + command = (cmd_ip|cmd_ip4set|cmd_iplist|cmd_str|cmd_s32|cmd_u16|cmd_u8|cmd_none); main := (command > Reset)+; }%% diff --git a/src/ifchd.h b/src/ifchd.h index 8f29413..221eb9b 100644 --- a/src/ifchd.h +++ b/src/ifchd.h @@ -16,7 +16,8 @@ enum ifchd_states { STATE_IPTTL, STATE_MTU, STATE_NTPSVR, - STATE_WINS + STATE_WINS, + STATE_CARRIER, }; #include diff --git a/src/ifset.c b/src/ifset.c index 7a01050..4ba64b1 100644 --- a/src/ifset.c +++ b/src/ifset.c @@ -327,6 +327,27 @@ static int link_flags_get(int fd, uint32_t flags[static 1]) return -4; } +int perform_carrier(void) +{ + int ret = -1; + uint32_t flags; + int fd = socket(AF_NETLINK, SOCK_DGRAM | SOCK_NONBLOCK, NETLINK_ROUTE); + if (fd < 0) { + log_error("%s: (%s) netlink socket open failed: %s", + client_config.interface, __func__, strerror(errno)); + goto fail; + } + + if (link_flags_get(fd, &flags) < 0) + goto fail_fd;; + if ((flags & IFF_RUNNING) && (flags & IFF_UP)) + ret = 0; +fail_fd: + close(fd); +fail: + return ret; +} + static int link_set_flags(int fd, uint32_t flags) { uint32_t oldflags; diff --git a/src/ifset.h b/src/ifset.h index 0c20207..49d807f 100644 --- a/src/ifset.h +++ b/src/ifset.h @@ -28,6 +28,7 @@ #ifndef NJK_IFSET_H_ #define NJK_IFSET_H_ +int perform_carrier(void); int perform_ifup(void); int perform_ip_subnet_bcast(const char str_ipaddr[static 1], const char str_subnet[static 1], diff --git a/src/seccomp.c b/src/seccomp.c index f20c52f..f896f1d 100644 --- a/src/seccomp.c +++ b/src/seccomp.c @@ -83,11 +83,6 @@ 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),