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:
		| @@ -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; | ||||||
|   | |||||||
| @@ -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(); | ||||||
|   | |||||||
							
								
								
									
										49
									
								
								src/ndhc.c
									
									
									
									
									
								
							
							
						
						
									
										49
									
								
								src/ndhc.c
									
									
									
									
									
								
							| @@ -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(); | ||||||
|   | |||||||
| @@ -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]; | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user