From 95cfbca5a9549e5dea1d1d498b9510e5c560fe88 Mon Sep 17 00:00:00 2001 From: Logan oos Even <46396513+Logan007@users.noreply.github.com> Date: Mon, 27 Jun 2022 22:21:03 +0200 Subject: [PATCH] more sockaddr generalization (#1028) --- include/n2n_typedefs.h | 15 +++-- src/edge_management.c | 13 ++--- src/management.c | 2 +- src/management.h | 6 +- src/sn_management.c | 23 ++++---- src/sn_utils.c | 127 +++++++++++++++++++---------------------- 6 files changed, 94 insertions(+), 92 deletions(-) diff --git a/include/n2n_typedefs.h b/include/n2n_typedefs.h index ad61c85..36bb67e 100644 --- a/include/n2n_typedefs.h +++ b/include/n2n_typedefs.h @@ -751,7 +751,11 @@ typedef struct sn_stats { typedef struct node_supernode_association { n2n_mac_t mac; /* mac address of an edge */ - const struct sockaddr_in sock; /* network order socket of that edge's supernode */ + socklen_t sock_len; /* amount of actually used space (of the following) */ + union { + struct sockaddr sock; /* network order socket of that edge's supernode */ + struct sockaddr_storage sas; /* the actual memory for it, sockaddr can be too small */ + }; time_t last_seen; /* time mark to keep track of purging requirements */ UT_hash_handle hh; /* makes this structure hashable */ @@ -796,9 +800,12 @@ struct sn_community_regular_expression { typedef struct n2n_tcp_connection { - int socket_fd; /* file descriptor for tcp socket */ - struct sockaddr sock; /* network order socket */ - + int socket_fd; /* file descriptor for tcp socket */ + socklen_t sock_len; /* amount of actually used space (of the following) */ + union { + struct sockaddr sock; /* network order socket */ + struct sockaddr_storage sas; /* memory for it, can be longer than sockaddr */ + }; uint16_t expected; /* number of bytes expected to be read */ uint16_t position; /* current position in the buffer */ uint8_t buffer[N2N_PKT_BUF_SIZE + sizeof(uint16_t)]; /* buffer for data collected from tcp socket incl. prepended length */ diff --git a/src/edge_management.c b/src/edge_management.c index 2956af4..42b78fa 100644 --- a/src/edge_management.c +++ b/src/edge_management.c @@ -417,7 +417,6 @@ void readFromMgmtSocket (n2n_edge_t *eee) { ssize_t recvlen; /* ssize_t sendlen; */ mgmt_req_t req; - socklen_t i; size_t msg_len; time_t now; struct peer_info *peer, *tmpPeer; @@ -438,11 +437,11 @@ void readFromMgmtSocket (n2n_edge_t *eee) { req.mgmt_sock = eee->udp_mgmt_sock; req.keep_running = eee->keep_running; req.mgmt_password_hash = eee->conf.mgmt_password_hash; + req.sock_len = sizeof(req.sas); now = time(NULL); - i = sizeof(req.sender_sock); recvlen = recvfrom(eee->udp_mgmt_sock, udp_buf, N2N_PKT_BUF_SIZE, 0 /*flags*/, - (struct sockaddr *) &req.sender_sock, (socklen_t *) &i); + &req.sender_sock, &req.sock_len); if(recvlen < 0) { traceEvent(TRACE_WARNING, "mgmt recvfrom failed: %d - %s", errno, strerror(errno)); @@ -546,7 +545,7 @@ void readFromMgmtSocket (n2n_edge_t *eee) { (peer->last_seen) ? time_buf : ""); sendto(eee->udp_mgmt_sock, udp_buf, msg_len, 0, - (struct sockaddr *) &req.sender_sock, sizeof(struct sockaddr_in)); + &req.sender_sock, req.sock_len); msg_len = 0; } @@ -570,7 +569,7 @@ void readFromMgmtSocket (n2n_edge_t *eee) { (peer->last_seen) ? time_buf : ""); sendto(eee->udp_mgmt_sock, udp_buf, msg_len, 0, - (struct sockaddr *) &req.sender_sock, sizeof(struct sockaddr_in)); + &req.sender_sock, req.sock_len); msg_len = 0; } @@ -596,7 +595,7 @@ void readFromMgmtSocket (n2n_edge_t *eee) { (peer->uptime) ? uptime_buf : ""); sendto(eee->udp_mgmt_sock, udp_buf, msg_len, 0, - (struct sockaddr *) &req.sender_sock, sizeof(struct sockaddr_in)); + &req.sender_sock, req.sock_len); msg_len = 0; } @@ -643,5 +642,5 @@ void readFromMgmtSocket (n2n_edge_t *eee) { "\nType \"help\" to see more commands.\n\n"); sendto(eee->udp_mgmt_sock, udp_buf, msg_len, 0, - (struct sockaddr *) &req.sender_sock, sizeof(struct sockaddr_in)); + &req.sender_sock, req.sock_len); } diff --git a/src/management.c b/src/management.c index 0413731..5a27dcf 100644 --- a/src/management.c +++ b/src/management.c @@ -21,7 +21,7 @@ int getTraceLevel (); ssize_t send_reply (mgmt_req_t *req, strbuf_t *buf, size_t msg_len) { // TODO: better error handling (counters?) return sendto(req->mgmt_sock, buf->str, msg_len, 0, - (struct sockaddr *) &req->sender_sock, sizeof(struct sockaddr_in)); + &req->sender_sock, req->sock_len); } size_t gen_json_1str (strbuf_t *buf, char *tag, char *_type, char *key, char *val) { diff --git a/src/management.h b/src/management.h index 80a829d..3dc542d 100644 --- a/src/management.h +++ b/src/management.h @@ -39,7 +39,11 @@ typedef struct mgmt_req { char *argv0; char *argv; char tag[10]; - struct sockaddr_in sender_sock; + socklen_t sock_len; + union { + struct sockaddr sender_sock; + struct sockaddr_storage sas; // memory for the socket, actual socket can be longer than sockaddr + }; } mgmt_req_t; /* diff --git a/src/sn_management.c b/src/sn_management.c index db9ac84..61c94b9 100644 --- a/src/sn_management.c +++ b/src/sn_management.c @@ -255,12 +255,12 @@ static void handleMgmtJson (mgmt_req_t *req, char *udp_buf, const int recvlen) { } static int sendto_mgmt (n2n_sn_t *sss, - const struct sockaddr_in *sender_sock, + const struct sockaddr *sender_sock, socklen_t sock_size, const uint8_t *mgmt_buf, size_t mgmt_size) { ssize_t r = sendto(sss->mgmt_sock, (void *)mgmt_buf, mgmt_size, 0 /*flags*/, - (struct sockaddr *)sender_sock, sizeof (struct sockaddr_in)); + sender_sock, sock_size); if(r <= 0) { ++(sss->stats.errors); @@ -272,7 +272,7 @@ static int sendto_mgmt (n2n_sn_t *sss, } int process_mgmt (n2n_sn_t *sss, - const struct sockaddr_in *sender_sock, + const struct sockaddr *sender_sock, socklen_t sock_size, char *mgmt_buf, size_t mgmt_size, time_t now) { @@ -297,7 +297,8 @@ int process_mgmt (n2n_sn_t *sss, req.mgmt_sock = sss->mgmt_sock; req.keep_running = sss->keep_running; req.mgmt_password_hash = sss->mgmt_password_hash; - memcpy(&req.sender_sock, sender_sock, sizeof(req.sender_sock)); + memcpy(&req.sender_sock, sender_sock, sock_size); + req.sock_len = sock_size; /* avoid parsing any uninitialized junk from the stack */ mgmt_buf[mgmt_size] = 0; @@ -309,7 +310,7 @@ int process_mgmt (n2n_sn_t *sss, "\thelp | This help message\n" "\treload_communities | Reloads communities and user's public keys\n" "\t | Display status and statistics\n"); - sendto_mgmt(sss, sender_sock, (const uint8_t *) resbuf, ressize); + sendto_mgmt(sss, sender_sock, sock_size, (const uint8_t *) resbuf, ressize); return 0; /* no status output afterwards */ } @@ -317,7 +318,7 @@ int process_mgmt (n2n_sn_t *sss, if(!sss->community_file) { ressize += snprintf(resbuf + ressize, N2N_SN_PKTBUF_SIZE - ressize, "No community file provided (-c command line option)\n"); - sendto_mgmt(sss, sender_sock, (const uint8_t *) resbuf, ressize); + sendto_mgmt(sss, sender_sock, sock_size, (const uint8_t *) resbuf, ressize); return 0; /* no status output afterwards */ } traceEvent(TRACE_NORMAL, "'reload_communities' command"); @@ -325,12 +326,12 @@ int process_mgmt (n2n_sn_t *sss, if(load_allowed_sn_community(sss)) { ressize += snprintf(resbuf + ressize, N2N_SN_PKTBUF_SIZE - ressize, "Error while re-loading community file (not found or no valid content)\n"); - sendto_mgmt(sss, sender_sock, (const uint8_t *) resbuf, ressize); + sendto_mgmt(sss, sender_sock, sock_size, (const uint8_t *) resbuf, ressize); return 0; /* no status output afterwards */ } ressize += snprintf(resbuf + ressize, N2N_SN_PKTBUF_SIZE - ressize, "OK.\n"); - sendto_mgmt(sss, sender_sock, (const uint8_t *) resbuf, ressize); + sendto_mgmt(sss, sender_sock, sock_size, (const uint8_t *) resbuf, ressize); return 0; /* no status output afterwards */ } @@ -357,7 +358,7 @@ int process_mgmt (n2n_sn_t *sss, "%s '%s'\n", (community->is_federation) ? "FEDERATION" : ((community->purgeable == UNPURGEABLE) ? "FIXED NAME COMMUNITY" : "COMMUNITY"), (community->is_federation) ? "-/-" : community->community); - sendto_mgmt(sss, sender_sock, (const uint8_t *) resbuf, ressize); + sendto_mgmt(sss, sender_sock, sock_size, (const uint8_t *) resbuf, ressize); ressize = 0; num = 0; @@ -373,7 +374,7 @@ int process_mgmt (n2n_sn_t *sss, peer->dev_desc, (peer->last_seen) ? time_buf : ""); - sendto_mgmt(sss, sender_sock, (const uint8_t *) resbuf, ressize); + sendto_mgmt(sss, sender_sock, sock_size, (const uint8_t *) resbuf, ressize); ressize = 0; } } @@ -418,7 +419,7 @@ int process_mgmt (n2n_sn_t *sss, "last reg %lu sec ago\n\n", (long unsigned int) (now - sss->stats.last_reg_super)); - sendto_mgmt(sss, sender_sock, (const uint8_t *) resbuf, ressize); + sendto_mgmt(sss, sender_sock, sock_size, (const uint8_t *) resbuf, ressize); return 0; } diff --git a/src/sn_utils.c b/src/sn_utils.c index 55fb318..f35e499 100644 --- a/src/sn_utils.c +++ b/src/sn_utils.c @@ -57,13 +57,13 @@ static int sort_communities (n2n_sn_t *sss, time_t now); int process_mgmt (n2n_sn_t *sss, - const struct sockaddr_in *sender_sock, - char *mgmt_buf, - size_t mgmt_size, - time_t now); + const struct sockaddr *sender_sock, socklen_t sock_size, + char *mgmt_buf, + size_t mgmt_size, + time_t now); static int process_udp (n2n_sn_t *sss, - const struct sockaddr_in *sender_sock, + const struct sockaddr *sender_sock, socklen_t sock_size, const SOCKET socket_fd, uint8_t *udp_buf, size_t udp_size, @@ -700,7 +700,7 @@ static int try_forward (n2n_sn_t * sss, if(assoc) { traceEvent(TRACE_DEBUG, "found mac address associated with a known supernode, forwarding packet to that supernode"); sendto_sock(sss, sss->sock, - (const struct sockaddr*)&(assoc->sock), + &(assoc->sock), pktbuf, pktsize); } else { // forwarding packet to all federated supernodes @@ -876,7 +876,7 @@ void sn_term (n2n_sn_t *sss) { } void update_node_supernode_association (struct sn_community *comm, - n2n_mac_t *edgeMac, const struct sockaddr_in *sender_sock, + n2n_mac_t *edgeMac, const struct sockaddr *sender_sock, socklen_t sock_size, time_t now) { node_supernode_association_t *assoc; @@ -884,15 +884,17 @@ void update_node_supernode_association (struct sn_community *comm, HASH_FIND(hh, comm->assoc, edgeMac, sizeof(n2n_mac_t), assoc); if(!assoc) { // create a new association - assoc = (node_supernode_association_t*)malloc(sizeof(node_supernode_association_t)); + assoc = (node_supernode_association_t*)calloc(1, sizeof(node_supernode_association_t)); if(assoc) { memcpy(&(assoc->mac), edgeMac, sizeof(n2n_mac_t)); - memcpy((struct sockaddr_in*)&(assoc->sock), sender_sock, sizeof(struct sockaddr_in)); + memcpy(&(assoc->sock), sender_sock, sock_size); + assoc->sock_len = sock_size; assoc->last_seen = now; HASH_ADD(hh, comm->assoc, mac, sizeof(n2n_mac_t), assoc); } else { // already there, update socket and time only - memcpy((struct sockaddr_in*)&(assoc->sock), sender_sock, sizeof(struct sockaddr_in)); + memcpy(&(assoc->sock), sender_sock, sock_size); + assoc->sock_len = sock_size; assoc->last_seen = now; } } @@ -1509,7 +1511,7 @@ static int sort_communities (n2n_sn_t *sss, * */ static int process_udp (n2n_sn_t * sss, - const struct sockaddr_in *sender_sock, + const struct sockaddr *sender_sock, socklen_t sock_size, const SOCKET socket_fd, uint8_t * udp_buf, size_t udp_size, @@ -1522,10 +1524,10 @@ static int process_udp (n2n_sn_t * sss, uint8_t from_supernode; peer_info_t *sn = NULL; n2n_sock_t sender; + n2n_sock_t *orig_sender; macstr_t mac_buf; macstr_t mac_buf2; n2n_sock_str_t sockbuf; - char buf[32]; uint8_t hash_buf[16] = {0}; /* always size of 16 (max) despite the actual value of N2N_REG_SUP_HASH_CHECK_LEN (<= 16) */ struct sn_community *comm, *tmp; @@ -1534,9 +1536,12 @@ static int process_udp (n2n_sn_t * sss, int skip_add; time_t any_time = 0; - traceEvent(TRACE_DEBUG, "processing incoming UDP packet [len: %lu][sender: %s:%u]", - udp_size, intoa(ntohl(sender_sock->sin_addr.s_addr), buf, sizeof(buf)), - ntohs(sender_sock->sin_port)); + memset(&sender, 0, sizeof(n2n_sock_t)); + fill_n2nsock(&sender, sender_sock); + orig_sender = &sender; + + traceEvent(TRACE_DEBUG, "processing incoming UDP packet [len: %lu][sender: %s]", + udp_size, sock_to_cstr(sockbuf, &sender)); /* check if header is unencrypted. the following check is around 99.99962 percent reliable. * it heavily relies on the structure of packet's common part @@ -1652,11 +1657,6 @@ static int process_udp (n2n_sn_t * sss, } } - /* REVISIT: when UDP/IPv6 is supported we will need a flag to indicate which - * IP transport version the packet arrived on. May need to UDP sockets. */ - memset(&sender, 0, sizeof(n2n_sock_t)); - fill_n2nsock(&sender, (struct sockaddr*)sender_sock); - from_supernode = cmn.flags & N2N_FLAGS_FROM_SUPERNODE; if(from_supernode) { skip_add = SN_ADD_SKIP; @@ -1718,7 +1718,7 @@ static int process_udp (n2n_sn_t * sss, /* We are going to add socket even if it was not there before */ cmn2.flags |= N2N_FLAGS_SOCKET | N2N_FLAGS_FROM_SUPERNODE; - fill_n2nsock(&pkt.sock, (struct sockaddr*)sender_sock); + memcpy(&pkt.sock, &sender, sizeof(sender)); rec_buf = encbuf; /* Re-encode the header. */ @@ -1801,7 +1801,7 @@ static int process_udp (n2n_sn_t * sss, /* We are going to add socket even if it was not there before */ cmn2.flags |= N2N_FLAGS_SOCKET | N2N_FLAGS_FROM_SUPERNODE; - fill_n2nsock(®.sock, (struct sockaddr*)sender_sock); + memcpy(®.sock, &sender, sizeof(sender)); /* Re-encode the header. */ encode_REGISTER(encbuf, &encx, &cmn2, ®); @@ -1960,7 +1960,7 @@ static int process_udp (n2n_sn_t * sss, ack.lifetime = reg_lifetime(sss); - fill_n2nsock(&ack.sock, (struct sockaddr*)sender_sock); + memcpy(&ack.sock, &sender, sizeof(sender)); /* Add sender's data to federation (or update it) */ if(comm->is_federation == IS_FEDERATION) { @@ -2029,7 +2029,7 @@ static int process_udp (n2n_sn_t * sss, encode_buf(ackbuf, &encx, hash_buf /* no matter what content */, N2N_REG_SUP_HASH_CHECK_LEN); } } - sendto_sock(sss, socket_fd, (struct sockaddr *)sender_sock, ackbuf, encx); + sendto_sock(sss, socket_fd, sender_sock, ackbuf, encx); traceEvent(TRACE_DEBUG, "Tx REGISTER_SUPER_NAK for %s", macaddr_str(mac_buf, reg.edgeMac)); @@ -2041,7 +2041,7 @@ static int process_udp (n2n_sn_t * sss, // NULL comm and from_supernode parameter) // exception: do not forward auto ip draw if(!is_null_mac(reg.edgeMac)) { - fill_n2nsock(®.sock, (struct sockaddr*)sender_sock); + memcpy(®.sock, &sender, sizeof(sender)); cmn2.pc = n2n_register_super; encode_REGISTER_SUPER(ackbuf, &encx, &cmn2, ®); @@ -2100,7 +2100,7 @@ static int process_udp (n2n_sn_t * sss, } } - sendto_sock(sss, socket_fd, (struct sockaddr *)sender_sock, ackbuf, encx); + sendto_sock(sss, socket_fd, sender_sock, ackbuf, encx); traceEvent(TRACE_DEBUG, "Tx REGISTER_SUPER_ACK for %s [%s]", macaddr_str(mac_buf, reg.edgeMac), @@ -2108,7 +2108,7 @@ static int process_udp (n2n_sn_t * sss, } else { // this is an edge with valid authentication registering with another supernode, so ... // 1- ... associate it with that other supernode - update_node_supernode_association(comm, &(reg.edgeMac), sender_sock, now); + update_node_supernode_association(comm, &(reg.edgeMac), sender_sock, sock_size, now); // 2- ... we can delete it from regular list if present (can happen) HASH_FIND_PEER(comm->edges, reg.edgeMac, peer); if(peer != NULL) { @@ -2179,17 +2179,10 @@ static int process_udp (n2n_sn_t * sss, n2n_sock_str_t sockbuf1; n2n_sock_str_t sockbuf2; macstr_t mac_buf1; - n2n_sock_t sender; - n2n_sock_t *orig_sender; int i; uint8_t dec_tmpbuf[REG_SUPER_ACK_PAYLOAD_SPACE]; n2n_REGISTER_SUPER_ACK_payload_t *payload; - memset(&sender, 0, sizeof(n2n_sock_t)); - fill_n2nsock(&sender, (struct sockaddr*)sender_sock); - - orig_sender = &sender; - memset(&ack, 0, sizeof(n2n_REGISTER_SUPER_ACK_t)); if(!comm) { @@ -2268,10 +2261,6 @@ static int process_udp (n2n_sn_t * sss, struct peer_info *peer; n2n_sock_str_t sockbuf; macstr_t mac_buf; - n2n_sock_t sender; - - memset(&sender, 0, sizeof(n2n_sock_t)); - fill_n2nsock(&sender, (struct sockaddr*)sender_sock); memset(&nak, 0, sizeof(n2n_REGISTER_SUPER_NAK_t)); @@ -2389,7 +2378,7 @@ static int process_udp (n2n_sn_t * sss, memcpy(pi.mac, query.targetMac, sizeof(n2n_mac_t)); memcpy(pi.srcMac, sss->mac_addr, sizeof(n2n_mac_t)); - fill_n2nsock(&pi.sock, (struct sockaddr*)sender_sock); + memcpy(&pi.sock, &sender, sizeof(sender)); pi.load = sn_selection_criterion_gather_data(sss); @@ -2406,7 +2395,7 @@ static int process_udp (n2n_sn_t * sss, } } - sendto_sock(sss, socket_fd, (struct sockaddr *)sender_sock, encbuf, encx); + sendto_sock(sss, socket_fd, sender_sock, encbuf, encx); traceEvent(TRACE_DEBUG, "Tx PONG to %s", macaddr_str(mac_buf, query.srcMac)); @@ -2448,7 +2437,7 @@ static int process_udp (n2n_sn_t * sss, time_stamp()); } // back to sender, be it edge or supernode (which will forward to edge) - sendto_sock(sss, socket_fd, (struct sockaddr *)sender_sock, encbuf, encx); + sendto_sock(sss, socket_fd, sender_sock, encbuf, encx); traceEvent(TRACE_DEBUG, "Tx PEER_INFO to %s", macaddr_str(mac_buf, query.srcMac)); @@ -2508,7 +2497,7 @@ static int process_udp (n2n_sn_t * sss, if(peer != NULL) { if((comm->is_federation == IS_NO_FEDERATION) && (!is_null_mac(pi.srcMac))) { // snoop on the information to use for supernode forwarding (do not wait until first remote REGISTER_SUPER) - update_node_supernode_association(comm, &(pi.mac), sender_sock, now); + update_node_supernode_association(comm, &(pi.mac), sender_sock, sock_size, now); // this is a PEER_INFO for one of the edges conencted to this supernode, forward, // i.e. re-assemble (memcpy of udpbuf to encbuf could be sufficient as well) @@ -2597,12 +2586,12 @@ int run_sn_loop (n2n_sn_t *sss) { // external udp if(FD_ISSET(sss->sock, &socket_mask)) { - struct sockaddr_in sender_sock; - socklen_t i; + struct sockaddr_storage sas; + struct sockaddr *sender_sock = (struct sockaddr*)&sas; + socklen_t ss_size = sizeof(sas); - i = sizeof(sender_sock); bread = recvfrom(sss->sock, (void *)pktbuf, N2N_SN_PKTBUF_SIZE, 0 /*flags*/, - (struct sockaddr *)&sender_sock, (socklen_t *)&i); + sender_sock, &ss_size); if((bread < 0) #ifdef WIN32 @@ -2622,7 +2611,7 @@ int run_sn_loop (n2n_sn_t *sss) { // we have a datagram to process... if(bread > 0) { // ...and the datagram has data (not just a header) - process_udp(sss, &sender_sock, sss->sock, pktbuf, bread, now); + process_udp(sss, sender_sock, ss_size, sss->sock, pktbuf, bread, now); } } @@ -2640,17 +2629,16 @@ int run_sn_loop (n2n_sn_t *sss) { continue; if(FD_ISSET(conn->socket_fd, &socket_mask)) { + struct sockaddr_storage sas; + struct sockaddr *sender_sock = (struct sockaddr*)&sas; + socklen_t ss_size = sizeof(sas); - struct sockaddr_in sender_sock; - socklen_t i; - - i = sizeof(sender_sock); bread = recvfrom(conn->socket_fd, conn->buffer + conn->position, conn->expected - conn->position, 0 /*flags*/, - (struct sockaddr *)&sender_sock, (socklen_t *)&i); + sender_sock, &ss_size); if(bread <= 0) { - traceEvent(TRACE_INFO, "closing tcp connection to [%s]", sock_to_cstr(sockbuf, (n2n_sock_t*)&sender_sock)); + traceEvent(TRACE_INFO, "closing tcp connection to [%s]", sock_to_cstr(sockbuf, (n2n_sock_t*)sender_sock)); traceEvent(TRACE_DEBUG, "recvfrom() returns %d and sees errno %d (%s)", bread, errno, strerror(errno)); #ifdef WIN32 traceEvent(TRACE_DEBUG, "WSAGetLastError(): %u", WSAGetLastError()); @@ -2665,14 +2653,14 @@ int run_sn_loop (n2n_sn_t *sss) { // the prepended length has been read, preparing for the packet conn->expected += be16toh(*(uint16_t*)(conn->buffer)); if(conn->expected > N2N_SN_PKTBUF_SIZE) { - traceEvent(TRACE_INFO, "closing tcp connection to [%s]", sock_to_cstr(sockbuf, (n2n_sock_t*)&sender_sock)); + traceEvent(TRACE_INFO, "closing tcp connection to [%s]", sock_to_cstr(sockbuf, (n2n_sock_t*)sender_sock)); traceEvent(TRACE_DEBUG, "too many bytes in tcp packet expected"); close_tcp_connection(sss, conn); continue; } } else { // full packet read, handle it - process_udp(sss, (struct sockaddr_in*)&(conn->sock), conn->socket_fd, + process_udp(sss, &(conn->sock), conn->sock_len, conn->socket_fd, conn->buffer + sizeof(uint16_t), conn->position - sizeof(uint16_t), now); // reset, await new prepended length @@ -2693,42 +2681,45 @@ int run_sn_loop (n2n_sn_t *sss) { // accept new incoming tcp connection if(FD_ISSET(sss->tcp_sock, &socket_mask)) { - struct sockaddr_in sender_sock; - socklen_t i; + struct sockaddr_storage sas; + struct sockaddr *sender_sock = (struct sockaddr*)&sas; + socklen_t ss_size = sizeof(sas); - i = sizeof(sender_sock); if((HASH_COUNT(sss->tcp_connections) + 4) < FD_SETSIZE) { - tmp_sock = accept(sss->tcp_sock, (struct sockaddr *)&sender_sock, (socklen_t *)&i); + tmp_sock = accept(sss->tcp_sock, sender_sock, &ss_size); + // REVISIT: should we error out if ss_size returns bigger than before? can this ever happen? if(tmp_sock >= 0) { - conn = (n2n_tcp_connection_t*)malloc(sizeof(n2n_tcp_connection_t)); + conn = (n2n_tcp_connection_t*)calloc(1, sizeof(n2n_tcp_connection_t)); if(conn) { conn->socket_fd = tmp_sock; - memcpy(&(conn->sock), &sender_sock, sizeof(struct sockaddr_in)); + memcpy(&(conn->sock), sender_sock, ss_size); + conn->sock_len = ss_size; conn->inactive = 0; conn->expected = sizeof(uint16_t); conn->position = 0; HASH_ADD_INT(sss->tcp_connections, socket_fd, conn); traceEvent(TRACE_INFO, "accepted incoming TCP connection from [%s]", - sock_to_cstr(sockbuf, (n2n_sock_t*)&sender_sock)); + sock_to_cstr(sockbuf, (n2n_sock_t*)sender_sock)); } } } else { // no space to store the socket for a new connection, close immediately traceEvent(TRACE_DEBUG, "denied incoming TCP connection from [%s] due to max connections limit hit", - sock_to_cstr(sockbuf, (n2n_sock_t*)&sender_sock)); + sock_to_cstr(sockbuf, (n2n_sock_t*)sender_sock)); } } #endif /* N2N_HAVE_TCP */ // handle management port input if(FD_ISSET(sss->mgmt_sock, &socket_mask)) { - struct sockaddr_in sender_sock; - size_t i; + struct sockaddr_storage sas; + struct sockaddr *sender_sock = (struct sockaddr*)&sas; + socklen_t ss_size = sizeof(sas); - i = sizeof(sender_sock); bread = recvfrom(sss->mgmt_sock, (void *)pktbuf, N2N_SN_PKTBUF_SIZE, 0 /*flags*/, - (struct sockaddr *)&sender_sock, (socklen_t *)&i); + sender_sock, &ss_size); + // REVISIT: should we error out if ss_size returns bigger than before? can this ever happen? if(bread <= 0) { traceEvent(TRACE_ERROR, "recvfrom() failed %d errno %d (%s)", bread, errno, strerror(errno)); *sss->keep_running = 0; @@ -2736,7 +2727,7 @@ int run_sn_loop (n2n_sn_t *sss) { } // we have a datagram to process - process_mgmt(sss, &sender_sock, (char *)pktbuf, bread, now); + process_mgmt(sss, sender_sock, ss_size, (char *)pktbuf, bread, now); } } else {