Use a socketpair rather than a pair of pipes for communication between

ndhc and ifch, similar to sockd.  A single pipe is also maintained so
that SIGPIPE can bound the lifetime of an orphaned ifch process.
This commit is contained in:
Nicholas J. Kain 2014-04-07 03:44:02 -04:00
parent e2ee728982
commit 5fa2030bab
4 changed files with 22 additions and 43 deletions

View File

@ -187,7 +187,7 @@ static int ifchd_cmd(char *b, size_t bl, uint8_t *od, ssize_t ol, uint8_t code)
static void pipewrite(struct client_state_t *cs, const char *buf, size_t count) static void pipewrite(struct client_state_t *cs, const char *buf, size_t count)
{ {
cs->ifchWorking = 1; cs->ifchWorking = 1;
ssize_t r = safe_write(pToIfchW, buf, count); ssize_t r = safe_write(ifchSock[0], buf, count);
if (r < 0 || (size_t)r != count) { if (r < 0 || (size_t)r != count) {
log_error("%s: (%s) write failed: %d", client_config.interface); log_error("%s: (%s) write failed: %d", client_config.interface);
return; return;

View File

@ -307,7 +307,7 @@ static void signal_dispatch(void)
static void inform_execute(char c) static void inform_execute(char c)
{ {
ssize_t r = safe_write(pToNdhcW, &c, sizeof c); ssize_t r = safe_write(ifchSock[1], &c, sizeof c);
if (r == 0) { if (r == 0) {
// Remote end hung up. // Remote end hung up.
exit(EXIT_SUCCESS); exit(EXIT_SUCCESS);
@ -321,7 +321,7 @@ static void process_client_pipe(void)
char buf[MAX_BUF]; char buf[MAX_BUF];
memset(buf, '\0', sizeof buf); memset(buf, '\0', sizeof buf);
ssize_t r = safe_read(pToIfchR, buf, sizeof buf - 1); ssize_t r = safe_recv(ifchSock[1], buf, sizeof buf - 1, MSG_DONTWAIT);
if (r == 0) { if (r == 0) {
// Remote end hung up. // Remote end hung up.
exit(EXIT_SUCCESS); exit(EXIT_SUCCESS);
@ -354,7 +354,7 @@ static void do_ifch_work(void)
memset(cl.namesvrs, 0, sizeof cl.namesvrs); memset(cl.namesvrs, 0, sizeof cl.namesvrs);
memset(cl.domains, 0, sizeof cl.domains); memset(cl.domains, 0, sizeof cl.domains);
epoll_add(epollfd, pToIfchR); epoll_add(epollfd, ifchSock[1]);
epoll_add(epollfd, signalFd); epoll_add(epollfd, signalFd);
for (;;) { for (;;) {
@ -367,7 +367,7 @@ static void do_ifch_work(void)
} }
for (int i = 0; i < r; ++i) { for (int i = 0; i < r; ++i) {
int fd = events[i].data.fd; int fd = events[i].data.fd;
if (fd == pToIfchR) if (fd == ifchSock[1])
process_client_pipe(); process_client_pipe();
else if (fd == signalFd) else if (fd == signalFd)
signal_dispatch(); signal_dispatch();

View File

@ -241,7 +241,7 @@ static void fail_if_state_dir_dne(void)
static void handle_ifch_message(void) static void handle_ifch_message(void)
{ {
char c; char c;
ssize_t r = safe_read(pToNdhcR, &c, sizeof c); ssize_t r = safe_recv(ifchSock[0], &c, sizeof c, MSG_DONTWAIT);
if (r == 0) { if (r == 0) {
// Remote end hung up. // Remote end hung up.
exit(EXIT_SUCCESS); exit(EXIT_SUCCESS);
@ -273,7 +273,7 @@ static void do_ndhc_work(void)
setup_signals_ndhc(); setup_signals_ndhc();
epoll_add(cs.epollFd, cs.nlFd); epoll_add(cs.epollFd, cs.nlFd);
epoll_add(cs.epollFd, pToNdhcR); epoll_add(cs.epollFd, ifchSock[0]);
set_listen_raw(&cs); set_listen_raw(&cs);
nowts = curms(); nowts = curms();
goto jumpstart; goto jumpstart;
@ -296,7 +296,7 @@ static void do_ndhc_work(void)
handle_arp_response(&cs); handle_arp_response(&cs);
else if (fd == cs.nlFd) else if (fd == cs.nlFd)
handle_nl_message(&cs); handle_nl_message(&cs);
else if (fd == pToNdhcR) else if (fd == ifchSock[0])
handle_ifch_message(); handle_ifch_message();
else else
suicide("epoll_wait: unknown fd"); suicide("epoll_wait: unknown fd");
@ -336,39 +336,20 @@ char resolv_conf_d[PATH_MAX] = "";
static char pidfile[PATH_MAX] = PID_FILE_DEFAULT; static char pidfile[PATH_MAX] = PID_FILE_DEFAULT;
static uid_t ndhc_uid = 0; static uid_t ndhc_uid = 0;
static gid_t ndhc_gid = 0; static gid_t ndhc_gid = 0;
int ifchSock[2];
int pToNdhcR; int ifchPipe[2];
int pToNdhcW;
int pToIfchR;
int pToIfchW;
int sockdSock[2]; int sockdSock[2];
int sockdPipe[2]; int sockdPipe[2];
static void create_ifch_ipc_pipes(void) { static void create_ifch_ipc_pipes(void) {
int niPipe[2]; if (pipe(ifchPipe))
int inPipe[2]; suicide("FATAL - can't create ndhc/ifch pipe: %s", strerror(errno));
if (socketpair(AF_UNIX, SOCK_DGRAM, 0, ifchSock) < 0)
if (pipe2(niPipe, 0)) suicide("FATAL - can't create ndhc/ifch socket: %s", strerror(errno));
suicide("FATAL - can't create ndhc -> ndhc-ifch pipe: %s",
strerror(errno));
if (fcntl(niPipe[0], F_SETFL, fcntl(niPipe[0], F_GETFL) | O_NONBLOCK) < 0)
suicide("FATAL - failed to set ndhc -> ndhc-ifch read-side nonblocking: %s",
strerror(errno));
pToNdhcR = niPipe[0];
pToNdhcW = niPipe[1];
if (pipe2(inPipe, 0))
suicide("FATAL - can't create ndhc-ifch -> ndhc pipe: %s",
strerror(errno));
if (fcntl(inPipe[0], F_SETFL, fcntl(inPipe[0], F_GETFL) | O_NONBLOCK) < 0)
suicide("FATAL - failed to set ndhc-ifch -> ndhc read-side nonblocking: %s",
strerror(errno));
pToIfchR = inPipe[0];
pToIfchW = inPipe[1];
} }
static void create_sockd_ipc_pipes(void) { static void create_sockd_ipc_pipes(void) {
if (pipe2(sockdPipe, 0)) if (pipe(sockdPipe))
suicide("FATAL - can't create ndhc/sockd pipe: %s", strerror(errno)); suicide("FATAL - can't create ndhc/sockd pipe: %s", strerror(errno));
if (socketpair(AF_UNIX, SOCK_DGRAM, 0, sockdSock) < 0) if (socketpair(AF_UNIX, SOCK_DGRAM, 0, sockdSock) < 0)
suicide("FATAL - can't create ndhc/sockd socket: %s", strerror(errno)); suicide("FATAL - can't create ndhc/sockd socket: %s", strerror(errno));
@ -379,14 +360,14 @@ static void spawn_ifch(void)
create_ifch_ipc_pipes(); create_ifch_ipc_pipes();
pid_t ifch_pid = fork(); pid_t ifch_pid = fork();
if (ifch_pid == 0) { if (ifch_pid == 0) {
close(pToNdhcR); close(ifchSock[0]);
close(pToIfchW); close(ifchPipe[0]);
// Don't share the RNG state with the master process. // Don't share the RNG state with the master process.
nk_random_u32_init(&cs.rnd32_state); nk_random_u32_init(&cs.rnd32_state);
ifch_main(); ifch_main();
} else if (ifch_pid > 0) { } else if (ifch_pid > 0) {
close(pToIfchR); close(ifchSock[1]);
close(pToNdhcW); close(ifchPipe[1]);
} else } else
suicide("failed to fork ndhc-ifch: %s", strerror(errno)); suicide("failed to fork ndhc-ifch: %s", strerror(errno));
} }
@ -396,8 +377,8 @@ static void spawn_sockd(void)
create_sockd_ipc_pipes(); create_sockd_ipc_pipes();
pid_t sockd_pid = fork(); pid_t sockd_pid = fork();
if (sockd_pid == 0) { if (sockd_pid == 0) {
close(sockdPipe[0]);
close(sockdSock[0]); close(sockdSock[0]);
close(sockdPipe[0]);
// Don't share the RNG state with the master process. // Don't share the RNG state with the master process.
nk_random_u32_init(&cs.rnd32_state); nk_random_u32_init(&cs.rnd32_state);
sockd_main(); sockd_main();

View File

@ -67,10 +67,8 @@ struct client_config_t {
extern struct client_config_t client_config; extern struct client_config_t client_config;
extern int pToIfchR; extern int ifchSock[2];
extern int pToIfchW; extern int ifchPipe[2];
extern int pToNdhcR;
extern int pToNdhcW;
extern int sockdSock[2]; extern int sockdSock[2];
extern int sockdPipe[2]; extern int sockdPipe[2];
extern char state_dir[PATH_MAX]; extern char state_dir[PATH_MAX];