diff options
Diffstat (limited to 'src/ipcpd/shim-udp/main.c')
-rw-r--r-- | src/ipcpd/shim-udp/main.c | 85 |
1 files changed, 52 insertions, 33 deletions
diff --git a/src/ipcpd/shim-udp/main.c b/src/ipcpd/shim-udp/main.c index c90b47a2..eff0bd94 100644 --- a/src/ipcpd/shim-udp/main.c +++ b/src/ipcpd/shim-udp/main.c @@ -28,7 +28,6 @@ #include <ouroboros/dev.h> #include <ouroboros/ipcp-dev.h> #include <ouroboros/fqueue.h> -#include <ouroboros/fcntl.h> #include <ouroboros/errno.h> #include <ouroboros/logs.h> @@ -453,7 +452,6 @@ static void * ipcp_udp_sdu_reader(void * o) continue; flags = fcntl(skfd, F_GETFL, 0); fcntl(skfd, F_SETFL, flags | O_NONBLOCK); - fd = udp_data.uf_to_fd[skfd]; n = sizeof(r_saddr); if ((n = recvfrom(skfd, &buf, @@ -463,7 +461,14 @@ static void * ipcp_udp_sdu_reader(void * o) (unsigned *) &n)) <= 0) continue; + pthread_rwlock_rdlock(&ipcpi.state_lock); + pthread_rwlock_rdlock(&udp_data.flows_lock); + + fd = udp_data.uf_to_fd[skfd]; flow_write(fd, buf, n); + + pthread_rwlock_unlock(&udp_data.flows_lock); + pthread_rwlock_unlock(&ipcpi.state_lock); } } @@ -478,11 +483,16 @@ static void * ipcp_udp_sdu_loop(void * o) (void) o; - while (true) { - if (flow_event_wait(udp_data.np1_flows, - udp_data.fq, - &timeout) == -ETIMEDOUT) - continue; + while (flow_event_wait(udp_data.np1_flows, udp_data.fq, &timeout)) { + pthread_rwlock_rdlock(&ipcpi.state_lock); + + if (ipcp_get_state() != IPCP_ENROLLED) { + pthread_rwlock_unlock(&ipcpi.state_lock); + return (void *) -1; /* -ENOTENROLLED */ + } + + + pthread_rwlock_rdlock(&udp_data.flows_lock); while ((fd = fqueue_next(udp_data.fq)) >= 0) { if (ipcp_flow_read(fd, &sdb)) { @@ -490,19 +500,18 @@ static void * ipcp_udp_sdu_loop(void * o) continue; } - pthread_rwlock_rdlock(&ipcpi.state_lock); - pthread_rwlock_rdlock(&udp_data.flows_lock); - if (send(udp_data.fd_to_uf[fd].skfd, shm_du_buff_head(sdb), shm_du_buff_tail(sdb) - shm_du_buff_head(sdb), 0) < 0) LOG_ERR("Failed to send SDU."); - pthread_rwlock_unlock(&udp_data.flows_lock); - pthread_rwlock_unlock(&ipcpi.state_lock); + ipcp_flow_del(sdb); + } + - ipcp_flow_del(sdb); } + pthread_rwlock_unlock(&udp_data.flows_lock); + pthread_rwlock_unlock(&ipcpi.state_lock); } return (void *) 1; @@ -519,7 +528,11 @@ void ipcp_sig_handler(int sig, siginfo_t * info, void * c) if (info->si_pid == irmd_api) { pthread_rwlock_wrlock(&ipcpi.state_lock); - ipcp_set_state(IPCP_SHUTDOWN); + if (ipcp_get_state() == IPCP_INIT) + ipcp_set_state(IPCP_NULL); + + if (ipcp_get_state() == IPCP_ENROLLED) + ipcp_set_state(IPCP_SHUTDOWN); pthread_rwlock_unlock(&ipcpi.state_lock); } @@ -539,9 +552,6 @@ static int ipcp_udp_bootstrap(struct dif_config * conf) assert(conf); assert(conf->type == THIS_TYPE); - /* this IPCP doesn't need to maintain its dif_name */ - free(conf->dif_name); - if (inet_ntop(AF_INET, &conf->ip_addr, ipstr, @@ -624,6 +634,9 @@ static int ipcp_udp_bootstrap(struct dif_config * conf) pthread_rwlock_unlock(&ipcpi.state_lock); + /* this IPCP doesn't need to maintain its dif_name */ + free(conf->dif_name); + LOG_DBG("Bootstrapped shim IPCP over UDP with api %d.", getpid()); LOG_DBG("Bound to IP address %s.", ipstr); LOG_DBG("DNS server address is %s.", dnsstr); @@ -945,8 +958,8 @@ static int ipcp_udp_flow_alloc(int fd, LOG_DBG("Allocating flow to %s.", dst_name); - if (dst_name == NULL || src_ae_name == NULL) - return -1; + assert(dst_name); + assert(src_ae_name); if (strlen(dst_name) > 255 || strlen(src_ae_name) > 255) { @@ -1098,32 +1111,36 @@ static int ipcp_udp_flow_dealloc(int fd) ipcp_flow_fini(fd); - flow_set_del(udp_data.np1_flows, fd); - pthread_rwlock_rdlock(&ipcpi.state_lock); + + if (ipcp_get_state() != IPCP_ENROLLED) { + pthread_rwlock_unlock(&ipcpi.state_lock); + LOG_DBG("Won't register with non-enrolled IPCP."); + return -1; /* -ENOTENROLLED */ + } + pthread_rwlock_wrlock(&udp_data.flows_lock); + flow_set_del(udp_data.np1_flows, fd); + skfd = udp_data.fd_to_uf[fd].skfd; udp_data.uf_to_fd[skfd] = -1; udp_data.fd_to_uf[fd].udp = -1; udp_data.fd_to_uf[fd].skfd = -1; + close(skfd); + pthread_rwlock_unlock(&udp_data.flows_lock); pthread_rwlock_rdlock(&udp_data.flows_lock); clr_fd(skfd); - pthread_rwlock_unlock(&udp_data.flows_lock); - pthread_rwlock_wrlock(&udp_data.flows_lock); - - close(skfd); + flow_dealloc(fd); pthread_rwlock_unlock(&udp_data.flows_lock); pthread_rwlock_unlock(&ipcpi.state_lock); - flow_dealloc(fd); - LOG_DBG("Flow with fd %d deallocated.", fd); return 0; @@ -1197,13 +1214,15 @@ int main(int argc, char * argv[]) ipcp_fini(); - pthread_cancel(udp_data.handler); - pthread_cancel(udp_data.sdu_reader); - pthread_cancel(udp_data.sduloop); - pthread_join(udp_data.sduloop, NULL); - pthread_join(udp_data.handler, NULL); - pthread_join(udp_data.sdu_reader, NULL); + if (ipcp_get_state() == IPCP_SHUTDOWN) { + pthread_cancel(udp_data.handler); + pthread_cancel(udp_data.sdu_reader); + pthread_cancel(udp_data.sduloop); + pthread_join(udp_data.sduloop, NULL); + pthread_join(udp_data.handler, NULL); + pthread_join(udp_data.sdu_reader, NULL); + } udp_data_fini(); |