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.
This commit is contained in:
parent
61a48b0fb6
commit
44175bd77c
@ -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);
|
||||
|
25
src/ndhc.c
25
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);
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user