From 44175bd77c8f6ff0202a3420cdb6c0a9deb42f9c Mon Sep 17 00:00:00 2001 From: "Nicholas J. Kain" Date: Sat, 14 Feb 2015 16:49:50 -0500 Subject: [PATCH] Make ifch requests synchronous just like sockd requests. This change paves the way for allowing ifch to notify the core ndhc about failures. It would be far too difficult to reason about the state machine if the requests to ifch were asynchronous. Currently ndhc assumes that ifch requests never fail, but this is not always true because of eg, rfkill. --- src/ifchange.c | 33 +++++++++++++++++++++++++++------ src/ndhc.c | 25 +------------------------ src/ndhc.h | 1 - 3 files changed, 28 insertions(+), 31 deletions(-) diff --git a/src/ifchange.c b/src/ifchange.c index abd1390..0dcf4bc 100644 --- a/src/ifchange.c +++ b/src/ifchange.c @@ -192,16 +192,37 @@ static int ifchd_cmd(char b[static 1], size_t bl, uint8_t *od, return -1; } -static void ifchwrite(struct client_state_t cs[static 1], - const char buf[static 1], size_t count) +static int ifchwrite(const char buf[static 1], size_t count) { - cs->ifchWorking = 1; ssize_t r = safe_write(ifchSock[0], buf, count); if (r < 0 || (size_t)r != count) { log_error("%s: (%s) write failed: %d", client_config.interface); - return; + return -1; } log_line("%s: Sent to ifchd: '%s'", client_config.interface, buf); + char data[256], control[256]; + struct iovec iov = { + .iov_base = data, + .iov_len = sizeof data - 1, + }; + struct msghdr msg = { + .msg_iov = &iov, + .msg_iovlen = 1, + .msg_control = control, + .msg_controllen = sizeof control + }; + r = safe_recvmsg(ifchSock[0], &msg, 0); + if (r == 0) { + // Remote end hung up. + exit(EXIT_SUCCESS); + } else if (r < 0) { + suicide("%s: (%s) recvmsg failed: %s", client_config.interface, + __func__, strerror(errno)); + } + data[iov.iov_len] = '\0'; + if (r == 1 && data[0] == '+') + return 0; + return -1; } void ifchange_deconfig(struct client_state_t cs[static 1]) @@ -214,7 +235,7 @@ void ifchange_deconfig(struct client_state_t cs[static 1]) snprintf(buf, sizeof buf, "ip4:0.0.0.0,255.255.255.255;"); log_line("%s: Resetting IP configuration.", client_config.interface); - ifchwrite(cs, buf, strlen(buf)); + ifchwrite(buf, strlen(buf)); memset(&cfg_packet, 0, sizeof cfg_packet); } @@ -318,7 +339,7 @@ void ifchange_bind(struct client_state_t cs[static 1], bo += send_cmd(buf + bo, sizeof buf - bo, packet, DCODE_MTU); bo += send_cmd(buf + bo, sizeof buf - bo, packet, DCODE_WINS); if (bo) - ifchwrite(cs, buf, bo); + ifchwrite(buf, bo); cs->ifDeconfig = 0; memcpy(&cfg_packet, packet, sizeof cfg_packet); diff --git a/src/ndhc.c b/src/ndhc.c index e9511e5..0adb4bf 100644 --- a/src/ndhc.c +++ b/src/ndhc.c @@ -74,7 +74,6 @@ #include "rfkill.h" struct client_state_t cs = { - .ifchWorking = 0, .ifDeconfig = 0, .init = 1, .epollFd = -1, @@ -260,25 +259,7 @@ static void fail_if_state_dir_dne(void) suicide("state_dir path '%s' does not specify a directory", state_dir); } -static void handle_ifch_message(void) -{ - char c; - ssize_t r = safe_recv(ifchSock[0], &c, sizeof c, MSG_DONTWAIT); - if (r == 0) { - // Remote end hung up. - exit(EXIT_SUCCESS); - } else if (r < 0) { - if (errno == EAGAIN || errno == EWOULDBLOCK) - return; - suicide("%s: (%s) error reading from ifch -> ndhc socket: %s", - client_config.interface, __func__, strerror(errno)); - } - - if (c == '+') - cs.ifchWorking = 0; -} - -#define NDHC_NUM_EP_FDS 8 +#define NDHC_NUM_EP_FDS 7 static void do_ndhc_work(void) { struct epoll_event events[NDHC_NUM_EP_FDS]; @@ -295,7 +276,6 @@ static void do_ndhc_work(void) setup_signals_ndhc(); epoll_add(cs.epollFd, cs.nlFd); - epoll_add(cs.epollFd, ifchSock[0]); epoll_add(cs.epollFd, ifchStream[0]); epoll_add(cs.epollFd, sockdStream[0]); if (client_config.enable_rfkill && cs.rfkillFd != -1) @@ -326,9 +306,6 @@ static void do_ndhc_work(void) } else if (fd == cs.nlFd) { if (events[i].events & EPOLLIN) handle_nl_message(&cs); - } else if (fd == ifchSock[0]) { - if (events[i].events & EPOLLIN) - handle_ifch_message(); } else if (fd == ifchStream[0]) { if (events[i].events & (EPOLLHUP|EPOLLERR|EPOLLRDHUP)) exit(EXIT_FAILURE); diff --git a/src/ndhc.h b/src/ndhc.h index 17b95ed..a669a89 100644 --- a/src/ndhc.h +++ b/src/ndhc.h @@ -38,7 +38,6 @@ struct client_state_t { int dhcpState; int arpPrevState; int ifsPrevState; - int ifchWorking; // ifch is performing interface changes. int ifDeconfig; // Set if the interface has already been deconfigured. int epollFd, signalFd, listenFd, arpFd, nlFd, rfkillFd; int nlPortId;