diff options
-rw-r--r-- | src/ipcpd/shim-udp/main.c | 194 | ||||
-rw-r--r-- | src/ipcpd/shim-udp/shim_udp_messages.proto | 5 | ||||
-rw-r--r-- | src/irmd/main.c | 37 | ||||
-rw-r--r-- | src/lib/dev.c | 13 | ||||
-rw-r--r-- | src/lib/sockets.c | 3 |
5 files changed, 189 insertions, 63 deletions
diff --git a/src/ipcpd/shim-udp/main.c b/src/ipcpd/shim-udp/main.c index 1284a0e5..1e58a8fc 100644 --- a/src/ipcpd/shim-udp/main.c +++ b/src/ipcpd/shim-udp/main.c @@ -158,6 +158,7 @@ static int shim_ap_init(char * ap_name) rw_lock_init(&_ap_instance->flows_lock); pthread_mutex_init(&_ap_instance->fd_set_lock, NULL); + return 0; } @@ -228,7 +229,7 @@ static ssize_t ipcp_udp_flow_write(int fd, void * buf, size_t count) e.index = index; - rw_lock_wrlock(&_ap_instance->flows_lock); + rw_lock_rdlock(&_ap_instance->flows_lock); e.port_id = _ap_instance->flows[fd].port_id; @@ -304,6 +305,45 @@ struct ipcp_udp_data * ipcp_udp_data_create() return udp_data; } +static void set_fd(int fd) +{ + bool fd_wait = true; + + pthread_mutex_lock(&_ap_instance->fd_set_lock); + + _ap_instance->fd_set_sync = true; + FD_SET(fd, &shim_data(_ipcp)->flow_fd_s); + + pthread_mutex_unlock(&_ap_instance->fd_set_lock); + + while (fd_wait) { + sched_yield(); + pthread_mutex_lock(&_ap_instance->fd_set_lock); + fd_wait = _ap_instance->fd_set_sync; + pthread_mutex_unlock(&_ap_instance->fd_set_lock); + } +} + +static void clr_fd(int fd) +{ + bool fd_wait = true; + + pthread_mutex_lock(&_ap_instance->fd_set_lock); + + _ap_instance->fd_set_sync = true; + FD_CLR(fd, &shim_data(_ipcp)->flow_fd_s); + + pthread_mutex_unlock(&_ap_instance->fd_set_lock); + + while (fd_wait) { + sched_yield(); + pthread_mutex_lock(&_ap_instance->fd_set_lock); + fd_wait = _ap_instance->fd_set_sync; + pthread_mutex_unlock(&_ap_instance->fd_set_lock); + } +} + + static int send_shim_udp_msg(shim_udp_msg_t * msg, uint32_t dst_ip_addr) { @@ -360,7 +400,7 @@ static int ipcp_udp_port_alloc(uint32_t dst_ip_addr, return send_shim_udp_msg(&msg, dst_ip_addr); } -static int ipcp_udp_port_alloc_resp(uint32_t ip_addr, +static int ipcp_udp_port_alloc_resp(uint32_t dst_ip_addr, uint16_t src_udp_port, uint16_t dst_udp_port, int response) @@ -374,7 +414,18 @@ static int ipcp_udp_port_alloc_resp(uint32_t ip_addr, msg.has_response = true; msg.response = response; - return send_shim_udp_msg(&msg, ip_addr); + return send_shim_udp_msg(&msg, dst_ip_addr); +} + +static int ipcp_udp_port_dealloc(uint32_t dst_ip_addr, + uint16_t src_udp_port) +{ + shim_udp_msg_t msg = SHIM_UDP_MSG__INIT; + + msg.code = SHIM_UDP_MSG_CODE__FLOW_DEALLOC; + msg.src_udp_port = src_udp_port; + + return send_shim_udp_msg(&msg, dst_ip_addr); } static int ipcp_udp_port_req(struct sockaddr_in * c_saddr, @@ -464,9 +515,9 @@ static int ipcp_udp_port_alloc_reply(int src_udp_port, int dst_udp_port, int response) { - int fd = -1; - int ret = 0; - int port_id = -1; + int fd = -1; + int ret = 0; + int port_id = -1; struct sockaddr_in t_saddr; socklen_t t_saddr_len = sizeof(t_saddr); @@ -536,12 +587,55 @@ static int ipcp_udp_port_alloc_reply(int src_udp_port, } LOG_INFO("Flow allocation completed, UDP ports: (%d, %d).", - ntohs(src_udp_port), ntohs(dst_udp_port)); + ntohs(dst_udp_port), ntohs(src_udp_port)); return ret; } +static int ipcp_udp_flow_dealloc_req(int udp_port) +{ + int fd = -1; + int port_id = -1; + + struct shm_ap_rbuff * rb; + + rw_lock_rdlock(&_ipcp->state_lock); + rw_lock_wrlock(&_ap_instance->flows_lock); + + fd = udp_port_to_fd(udp_port); + if (fd < 0) { + rw_lock_unlock(&_ap_instance->flows_lock); + rw_lock_unlock(&_ipcp->state_lock); + LOG_DBGF("Could not find flow on UDP port %d.", + ntohs(udp_port)); + return 0; + } + + clr_fd(fd); + + _ap_instance->flows[fd].state = FLOW_NULL; + port_id = _ap_instance->flows[fd].port_id; + _ap_instance->flows[fd].port_id = -1; + rb = _ap_instance->flows[fd].rb; + _ap_instance->flows[fd].rb = NULL; + + rw_lock_unlock(&_ap_instance->flows_lock); + + if (rb != NULL) + shm_ap_rbuff_close(rb); + + rw_lock_unlock(&_ipcp->state_lock); + + ipcp_flow_dealloc(0, port_id); + + close(fd); + + LOG_DBGF("Flow with port_id %d deallocated.", port_id); + + return 0; +} + static void * ipcp_udp_listener() { uint8_t buf[SHIM_UDP_MSG_SIZE]; @@ -598,6 +692,9 @@ static void * ipcp_udp_listener() msg->dst_udp_port, msg->response); break; + case SHIM_UDP_MSG_CODE__FLOW_DEALLOC: + ipcp_udp_flow_dealloc_req(msg->src_udp_port); + break; default: LOG_ERR("Unknown message received %d.", msg->code); shim_udp_msg__free_unpacked(msg, NULL); @@ -1123,7 +1220,6 @@ static int ipcp_udp_flow_alloc(pid_t n_pid, int fd; struct hostent * h; uint32_t ip_addr = 0; - bool fd_wait = true; #ifdef CONFIG_OUROBOROS_ENABLE_DNS uint32_t dns_addr = 0; #endif @@ -1220,19 +1316,7 @@ static int ipcp_udp_flow_alloc(pid_t n_pid, rw_lock_rdlock(&_ipcp->state_lock); rw_lock_wrlock(&_ap_instance->flows_lock); - pthread_mutex_lock(&_ap_instance->fd_set_lock); - - _ap_instance->fd_set_sync = true; - FD_SET(fd, &shim_data(_ipcp)->flow_fd_s); - - pthread_mutex_unlock(&_ap_instance->fd_set_lock); - - while (fd_wait) { - sched_yield(); - pthread_mutex_lock(&_ap_instance->fd_set_lock); - fd_wait = _ap_instance->fd_set_sync; - pthread_mutex_unlock(&_ap_instance->fd_set_lock); - } + set_fd(fd); _ap_instance->flows[fd].port_id = port_id; _ap_instance->flows[fd].state = FLOW_PENDING; @@ -1250,7 +1334,7 @@ static int ipcp_udp_flow_alloc(pid_t n_pid, rw_lock_rdlock(&_ipcp->state_lock); rw_lock_wrlock(&_ap_instance->flows_lock); - FD_CLR(fd, &shim_data(_ipcp)->flow_fd_s); + clr_fd(fd); _ap_instance->flows[fd].port_id = -1; _ap_instance->flows[fd].state = FLOW_NULL; @@ -1275,7 +1359,6 @@ static int ipcp_udp_flow_alloc_resp(pid_t n_pid, struct sockaddr_in f_saddr; struct sockaddr_in r_saddr; socklen_t len = sizeof(r_saddr); - bool fd_wait = true; if (response) return 0; @@ -1291,7 +1374,7 @@ static int ipcp_udp_flow_alloc_resp(pid_t n_pid, rw_lock_unlock(&_ap_instance->flows_lock); rw_lock_unlock(&_ipcp->state_lock); LOG_DBGF("Could not find flow with port_id %d.", port_id); - return 0; + return -1; } if (_ap_instance->flows[fd].state != FLOW_PENDING) { @@ -1308,23 +1391,21 @@ static int ipcp_udp_flow_alloc_resp(pid_t n_pid, _ap_instance->flows[fd].port_id = -1; rw_lock_unlock(&_ap_instance->flows_lock); rw_lock_unlock(&_ipcp->state_lock); - return 0; + return -1; } rw_lock_unlock(&_ap_instance->flows_lock); rw_lock_unlock(&_ipcp->state_lock); if (getsockname(fd, (struct sockaddr *) &f_saddr, &len) < 0) { - rw_lock_unlock(&_ipcp->state_lock); - LOG_DBGF("Flow with port_id %d has no peer.", port_id); - return 0; - }; + LOG_DBGF("Flow with port_id %d has no socket.", port_id); + return -1; + } if (getpeername(fd, (struct sockaddr *) &r_saddr, &len) < 0) { - rw_lock_unlock(&_ipcp->state_lock); LOG_DBGF("Flow with port_id %d has no peer.", port_id); - return 0; - }; + return -1; + } rw_lock_rdlock(&_ipcp->state_lock); rw_lock_wrlock(&_ap_instance->flows_lock); @@ -1332,19 +1413,7 @@ static int ipcp_udp_flow_alloc_resp(pid_t n_pid, _ap_instance->flows[fd].state = FLOW_ALLOCATED; _ap_instance->flows[fd].rb = rb; - pthread_mutex_lock(&_ap_instance->fd_set_lock); - - _ap_instance->fd_set_sync = true; - FD_SET(fd, &shim_data(_ipcp)->flow_fd_s); - - pthread_mutex_unlock(&_ap_instance->fd_set_lock); - - while (fd_wait) { - sched_yield(); - pthread_mutex_lock(&_ap_instance->fd_set_lock); - fd_wait = _ap_instance->fd_set_sync; - pthread_mutex_unlock(&_ap_instance->fd_set_lock); - } + set_fd(fd); rw_lock_unlock(&_ap_instance->flows_lock); rw_lock_unlock(&_ipcp->state_lock); @@ -1360,7 +1429,7 @@ static int ipcp_udp_flow_alloc_resp(pid_t n_pid, shm_ap_rbuff_close(_ap_instance->flows[fd].rb); _ap_instance->flows[fd].rb = NULL; - FD_CLR(fd, &shim_data(_ipcp)->flow_fd_s); + clr_fd(fd); rw_lock_unlock(&_ap_instance->flows_lock); rw_lock_unlock(&_ipcp->state_lock); @@ -1377,9 +1446,10 @@ static int ipcp_udp_flow_alloc_resp(pid_t n_pid, static int ipcp_udp_flow_dealloc(int port_id) { int fd = -1; + int remote_udp = -1; struct shm_ap_rbuff * rb; - - LOG_DBGF("Deallocating flow with port_id %d.", port_id); + struct sockaddr_in r_saddr; + socklen_t r_saddr_len = sizeof(r_saddr); rw_lock_rdlock(&_ipcp->state_lock); rw_lock_wrlock(&_ap_instance->flows_lock); @@ -1393,17 +1463,41 @@ static int ipcp_udp_flow_dealloc(int port_id) } _ap_instance->flows[fd].state = FLOW_NULL; - _ap_instance->flows[fd].port_id = 0; + _ap_instance->flows[fd].port_id = -1; rb = _ap_instance->flows[fd].rb; _ap_instance->flows[fd].rb = NULL; - FD_CLR(fd, &shim_data(_ipcp)->flow_fd_s); + clr_fd(fd); rw_lock_unlock(&_ap_instance->flows_lock); if (rb != NULL) shm_ap_rbuff_close(rb); + if (getpeername(fd, (struct sockaddr *) &r_saddr, &r_saddr_len) < 0) { + rw_lock_unlock(&_ipcp->state_lock); + LOG_DBGF("Flow with port_id %d has no peer.", port_id); + close(fd); + return 0; + } + + remote_udp = r_saddr.sin_port; + r_saddr.sin_port = LISTEN_PORT; + + if (connect(fd, (struct sockaddr *) &r_saddr, sizeof(r_saddr)) < 0) { + rw_lock_unlock(&_ipcp->state_lock); + close(fd); + return 0 ; + } + + if (ipcp_udp_port_dealloc(r_saddr.sin_addr.s_addr, + remote_udp) < 0) { + LOG_DBGF("Could not notify remote."); + rw_lock_unlock(&_ipcp->state_lock); + close(fd); + return 0; + } + rw_lock_unlock(&_ipcp->state_lock); close(fd); diff --git a/src/ipcpd/shim-udp/shim_udp_messages.proto b/src/ipcpd/shim-udp/shim_udp_messages.proto index 1d054f1f..a15fc18c 100644 --- a/src/ipcpd/shim-udp/shim_udp_messages.proto +++ b/src/ipcpd/shim-udp/shim_udp_messages.proto @@ -1,6 +1,7 @@ enum shim_udp_msg_code { - FLOW_REQ = 1; - FLOW_REPLY = 2; + FLOW_REQ = 1; + FLOW_REPLY = 2; + FLOW_DEALLOC = 3; }; message shim_udp_msg { diff --git a/src/irmd/main.c b/src/irmd/main.c index 28f82751..f1993960 100644 --- a/src/irmd/main.c +++ b/src/irmd/main.c @@ -318,11 +318,6 @@ static int reg_name_entry_destroy(struct reg_name_entry * e) free(e->name); instance_name_destroy(e->api); - if (e->req_ap_name != NULL) - free(e->req_ap_name); - if (e->req_ae_name != NULL) - free(e->req_ae_name); - free(e); e = NULL; @@ -389,7 +384,6 @@ static int reg_name_entry_del_name(char * name) return 0; list_del(&e->next); - reg_name_entry_destroy(e); return 0; @@ -821,6 +815,7 @@ static struct port_map_entry * flow_accept(pid_t pid, LOG_DBGF("Unregistered AP calling accept()."); return NULL; } + if (rne->accept) { rw_lock_unlock(&instance->reg_lock); rw_lock_unlock(&instance->state_lock); @@ -1016,6 +1011,12 @@ static int flow_alloc_res(int port_id) return -1; } + if (e->state == FLOW_NULL) { + rw_lock_unlock(&instance->flows_lock); + rw_lock_unlock(&instance->state_lock); + return -1; + } + if (e->state == FLOW_ALLOCATED) { rw_lock_unlock(&instance->flows_lock); rw_lock_unlock(&instance->state_lock); @@ -1105,6 +1106,7 @@ static struct port_map_entry * flow_req_arr(pid_t pid, { struct reg_name_entry * rne; struct port_map_entry * pme; + bool acc_wait = true; pme = malloc(sizeof(*pme)); if (pme == NULL) { @@ -1133,13 +1135,19 @@ static struct port_map_entry * flow_req_arr(pid_t pid, pme->n_pid = rne->api->id; - rne->req_ap_name = strdup(ap_name); - rne->req_ae_name = strdup(ae_name); - list_add(&pme->next, &instance->port_map); pthread_mutex_lock(&rne->acc_lock); + rne->req_ap_name = ap_name; + rne->req_ae_name = ae_name; + + if (rne->accept == false) { + pthread_mutex_unlock(&rne->acc_lock); + LOG_WARN("This AP is not accepting flow allocations."); + return NULL; + } + rne->flow_arrived = 0; pthread_mutex_unlock(&rne->acc_lock); @@ -1147,6 +1155,13 @@ static struct port_map_entry * flow_req_arr(pid_t pid, if (pthread_cond_signal(&rne->acc_signal)) LOG_ERR("Failed to send signal."); + while (acc_wait) { + sched_yield(); + pthread_mutex_lock(&rne->acc_lock); + acc_wait = (rne->flow_arrived != -1); + pthread_mutex_unlock(&rne->acc_lock); + } + rw_lock_unlock(&instance->flows_lock); rw_lock_unlock(&instance->reg_lock); rw_lock_unlock(&instance->state_lock); @@ -1202,6 +1217,8 @@ static int flow_dealloc_ipcp(int port_id) return 0; } + bmp_release(instance->port_ids, port_id); + list_del(&e->next); rw_lock_unlock(&instance->flows_lock); @@ -1245,8 +1262,10 @@ static void irm_destroy(struct irm * irm) struct port_map_entry * e = list_entry(h, struct port_map_entry, next); + list_del(&e->next); free(e); + } if (irm->dum != NULL) diff --git a/src/lib/dev.c b/src/lib/dev.c index 63cf92f7..d332a27f 100644 --- a/src/lib/dev.c +++ b/src/lib/dev.c @@ -202,6 +202,7 @@ int ap_reg(char ** difs, rw_lock_wrlock(&_ap_instance->flows_lock); fd = bmp_allocate(_ap_instance->fds); + _ap_instance->flows[fd].port_id = -1; rw_lock_unlock(&_ap_instance->flows_lock); rw_lock_unlock(&_ap_instance->data_lock); @@ -299,8 +300,12 @@ int flow_accept(int fd, rw_lock_rdlock(&_ap_instance->data_lock); rw_lock_wrlock(&_ap_instance->flows_lock); - cfd = bmp_allocate(_ap_instance->fds); + if (!bmp_is_id_valid(_ap_instance->fds, cfd)) { + rw_lock_unlock(&_ap_instance->flows_lock); + rw_lock_unlock(&_ap_instance->data_lock); + return -1; + } _ap_instance->flows[cfd].rb = shm_ap_rbuff_open(recv_msg->pid); if (_ap_instance->flows[cfd].rb == NULL) { @@ -405,7 +410,11 @@ int flow_alloc(char * dst_name, rw_lock_wrlock(&_ap_instance->flows_lock); fd = bmp_allocate(_ap_instance->fds); - + if (!bmp_is_id_valid(_ap_instance->fds, fd)) { + rw_lock_unlock(&_ap_instance->flows_lock); + rw_lock_unlock(&_ap_instance->data_lock); + return -1; + } _ap_instance->flows[fd].rb = shm_ap_rbuff_open(recv_msg->pid); if (_ap_instance->flows[fd].rb == NULL) { bmp_release(_ap_instance->fds, fd); diff --git a/src/lib/sockets.c b/src/lib/sockets.c index 4f777805..6c51e916 100644 --- a/src/lib/sockets.c +++ b/src/lib/sockets.c @@ -50,6 +50,7 @@ int client_socket_open(char * file_name) (struct sockaddr *) &serv_addr, sizeof(serv_addr))) { LOG_ERR("Failed to connect to daemon"); + close(sockfd); return -1; } @@ -83,11 +84,13 @@ int server_socket_open(char * file_name) (struct sockaddr *) &serv_addr, sizeof(serv_addr))) { LOG_ERR("Failed to bind socket"); + close(sockfd); return -1; } if (listen(sockfd, 0)) { LOG_ERR("Failed to listen to socket"); + close(sockfd); return -1; } |