more sockaddr generalization (#1028)

This commit is contained in:
Logan oos Even 2022-06-27 22:21:03 +02:00 committed by GitHub
parent 439dfc6886
commit 95cfbca5a9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 94 additions and 92 deletions

View File

@ -751,7 +751,11 @@ typedef struct sn_stats {
typedef struct node_supernode_association { typedef struct node_supernode_association {
n2n_mac_t mac; /* mac address of an edge */ 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 */ time_t last_seen; /* time mark to keep track of purging requirements */
UT_hash_handle hh; /* makes this structure hashable */ UT_hash_handle hh; /* makes this structure hashable */
@ -796,9 +800,12 @@ struct sn_community_regular_expression {
typedef struct n2n_tcp_connection { typedef struct n2n_tcp_connection {
int socket_fd; /* file descriptor for tcp socket */ int socket_fd; /* file descriptor for tcp socket */
struct sockaddr sock; /* network order 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 expected; /* number of bytes expected to be read */
uint16_t position; /* current position in the buffer */ 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 */ uint8_t buffer[N2N_PKT_BUF_SIZE + sizeof(uint16_t)]; /* buffer for data collected from tcp socket incl. prepended length */

View File

@ -417,7 +417,6 @@ void readFromMgmtSocket (n2n_edge_t *eee) {
ssize_t recvlen; ssize_t recvlen;
/* ssize_t sendlen; */ /* ssize_t sendlen; */
mgmt_req_t req; mgmt_req_t req;
socklen_t i;
size_t msg_len; size_t msg_len;
time_t now; time_t now;
struct peer_info *peer, *tmpPeer; struct peer_info *peer, *tmpPeer;
@ -438,11 +437,11 @@ void readFromMgmtSocket (n2n_edge_t *eee) {
req.mgmt_sock = eee->udp_mgmt_sock; req.mgmt_sock = eee->udp_mgmt_sock;
req.keep_running = eee->keep_running; req.keep_running = eee->keep_running;
req.mgmt_password_hash = eee->conf.mgmt_password_hash; req.mgmt_password_hash = eee->conf.mgmt_password_hash;
req.sock_len = sizeof(req.sas);
now = time(NULL); now = time(NULL);
i = sizeof(req.sender_sock);
recvlen = recvfrom(eee->udp_mgmt_sock, udp_buf, N2N_PKT_BUF_SIZE, 0 /*flags*/, 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) { if(recvlen < 0) {
traceEvent(TRACE_WARNING, "mgmt recvfrom failed: %d - %s", errno, strerror(errno)); 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 : ""); (peer->last_seen) ? time_buf : "");
sendto(eee->udp_mgmt_sock, udp_buf, msg_len, 0, 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; msg_len = 0;
} }
@ -570,7 +569,7 @@ void readFromMgmtSocket (n2n_edge_t *eee) {
(peer->last_seen) ? time_buf : ""); (peer->last_seen) ? time_buf : "");
sendto(eee->udp_mgmt_sock, udp_buf, msg_len, 0, 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; msg_len = 0;
} }
@ -596,7 +595,7 @@ void readFromMgmtSocket (n2n_edge_t *eee) {
(peer->uptime) ? uptime_buf : ""); (peer->uptime) ? uptime_buf : "");
sendto(eee->udp_mgmt_sock, udp_buf, msg_len, 0, 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; msg_len = 0;
} }
@ -643,5 +642,5 @@ void readFromMgmtSocket (n2n_edge_t *eee) {
"\nType \"help\" to see more commands.\n\n"); "\nType \"help\" to see more commands.\n\n");
sendto(eee->udp_mgmt_sock, udp_buf, msg_len, 0, 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);
} }

View File

@ -21,7 +21,7 @@ int getTraceLevel ();
ssize_t send_reply (mgmt_req_t *req, strbuf_t *buf, size_t msg_len) { ssize_t send_reply (mgmt_req_t *req, strbuf_t *buf, size_t msg_len) {
// TODO: better error handling (counters?) // TODO: better error handling (counters?)
return sendto(req->mgmt_sock, buf->str, msg_len, 0, 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) { size_t gen_json_1str (strbuf_t *buf, char *tag, char *_type, char *key, char *val) {

View File

@ -39,7 +39,11 @@ typedef struct mgmt_req {
char *argv0; char *argv0;
char *argv; char *argv;
char tag[10]; 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; } mgmt_req_t;
/* /*

View File

@ -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, 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, const uint8_t *mgmt_buf,
size_t mgmt_size) { size_t mgmt_size) {
ssize_t r = sendto(sss->mgmt_sock, (void *)mgmt_buf, mgmt_size, 0 /*flags*/, 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) { if(r <= 0) {
++(sss->stats.errors); ++(sss->stats.errors);
@ -272,7 +272,7 @@ static int sendto_mgmt (n2n_sn_t *sss,
} }
int process_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, char *mgmt_buf,
size_t mgmt_size, size_t mgmt_size,
time_t now) { time_t now) {
@ -297,7 +297,8 @@ int process_mgmt (n2n_sn_t *sss,
req.mgmt_sock = sss->mgmt_sock; req.mgmt_sock = sss->mgmt_sock;
req.keep_running = sss->keep_running; req.keep_running = sss->keep_running;
req.mgmt_password_hash = sss->mgmt_password_hash; 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 */ /* avoid parsing any uninitialized junk from the stack */
mgmt_buf[mgmt_size] = 0; mgmt_buf[mgmt_size] = 0;
@ -309,7 +310,7 @@ int process_mgmt (n2n_sn_t *sss,
"\thelp | This help message\n" "\thelp | This help message\n"
"\treload_communities | Reloads communities and user's public keys\n" "\treload_communities | Reloads communities and user's public keys\n"
"\t<enter> | Display status and statistics\n"); "\t<enter> | 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 */ return 0; /* no status output afterwards */
} }
@ -317,7 +318,7 @@ int process_mgmt (n2n_sn_t *sss,
if(!sss->community_file) { if(!sss->community_file) {
ressize += snprintf(resbuf + ressize, N2N_SN_PKTBUF_SIZE - ressize, ressize += snprintf(resbuf + ressize, N2N_SN_PKTBUF_SIZE - ressize,
"No community file provided (-c command line option)\n"); "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 */ return 0; /* no status output afterwards */
} }
traceEvent(TRACE_NORMAL, "'reload_communities' command"); traceEvent(TRACE_NORMAL, "'reload_communities' command");
@ -325,12 +326,12 @@ int process_mgmt (n2n_sn_t *sss,
if(load_allowed_sn_community(sss)) { if(load_allowed_sn_community(sss)) {
ressize += snprintf(resbuf + ressize, N2N_SN_PKTBUF_SIZE - ressize, ressize += snprintf(resbuf + ressize, N2N_SN_PKTBUF_SIZE - ressize,
"Error while re-loading community file (not found or no valid content)\n"); "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 */ return 0; /* no status output afterwards */
} }
ressize += snprintf(resbuf + ressize, N2N_SN_PKTBUF_SIZE - ressize, ressize += snprintf(resbuf + ressize, N2N_SN_PKTBUF_SIZE - ressize,
"OK.\n"); "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 */ return 0; /* no status output afterwards */
} }
@ -357,7 +358,7 @@ int process_mgmt (n2n_sn_t *sss,
"%s '%s'\n", "%s '%s'\n",
(community->is_federation) ? "FEDERATION" : ((community->purgeable == UNPURGEABLE) ? "FIXED NAME COMMUNITY" : "COMMUNITY"), (community->is_federation) ? "FEDERATION" : ((community->purgeable == UNPURGEABLE) ? "FIXED NAME COMMUNITY" : "COMMUNITY"),
(community->is_federation) ? "-/-" : 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; ressize = 0;
num = 0; num = 0;
@ -373,7 +374,7 @@ int process_mgmt (n2n_sn_t *sss,
peer->dev_desc, peer->dev_desc,
(peer->last_seen) ? time_buf : ""); (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; ressize = 0;
} }
} }
@ -418,7 +419,7 @@ int process_mgmt (n2n_sn_t *sss,
"last reg %lu sec ago\n\n", "last reg %lu sec ago\n\n",
(long unsigned int) (now - sss->stats.last_reg_super)); (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; return 0;
} }

View File

@ -57,13 +57,13 @@ static int sort_communities (n2n_sn_t *sss,
time_t now); time_t now);
int process_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, char *mgmt_buf,
size_t mgmt_size, size_t mgmt_size,
time_t now); time_t now);
static int process_udp (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, const SOCKET socket_fd,
uint8_t *udp_buf, uint8_t *udp_buf,
size_t udp_size, size_t udp_size,
@ -700,7 +700,7 @@ static int try_forward (n2n_sn_t * sss,
if(assoc) { if(assoc) {
traceEvent(TRACE_DEBUG, "found mac address associated with a known supernode, forwarding packet to that supernode"); traceEvent(TRACE_DEBUG, "found mac address associated with a known supernode, forwarding packet to that supernode");
sendto_sock(sss, sss->sock, sendto_sock(sss, sss->sock,
(const struct sockaddr*)&(assoc->sock), &(assoc->sock),
pktbuf, pktsize); pktbuf, pktsize);
} else { } else {
// forwarding packet to all federated supernodes // 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, 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) { time_t now) {
node_supernode_association_t *assoc; 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); HASH_FIND(hh, comm->assoc, edgeMac, sizeof(n2n_mac_t), assoc);
if(!assoc) { if(!assoc) {
// create a new association // 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) { if(assoc) {
memcpy(&(assoc->mac), edgeMac, sizeof(n2n_mac_t)); 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; assoc->last_seen = now;
HASH_ADD(hh, comm->assoc, mac, sizeof(n2n_mac_t), assoc); HASH_ADD(hh, comm->assoc, mac, sizeof(n2n_mac_t), assoc);
} else { } else {
// already there, update socket and time only // 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; assoc->last_seen = now;
} }
} }
@ -1509,7 +1511,7 @@ static int sort_communities (n2n_sn_t *sss,
* *
*/ */
static int process_udp (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, const SOCKET socket_fd,
uint8_t * udp_buf, uint8_t * udp_buf,
size_t udp_size, size_t udp_size,
@ -1522,10 +1524,10 @@ static int process_udp (n2n_sn_t * sss,
uint8_t from_supernode; uint8_t from_supernode;
peer_info_t *sn = NULL; peer_info_t *sn = NULL;
n2n_sock_t sender; n2n_sock_t sender;
n2n_sock_t *orig_sender;
macstr_t mac_buf; macstr_t mac_buf;
macstr_t mac_buf2; macstr_t mac_buf2;
n2n_sock_str_t sockbuf; 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) */ 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; struct sn_community *comm, *tmp;
@ -1534,9 +1536,12 @@ static int process_udp (n2n_sn_t * sss,
int skip_add; int skip_add;
time_t any_time = 0; time_t any_time = 0;
traceEvent(TRACE_DEBUG, "processing incoming UDP packet [len: %lu][sender: %s:%u]", memset(&sender, 0, sizeof(n2n_sock_t));
udp_size, intoa(ntohl(sender_sock->sin_addr.s_addr), buf, sizeof(buf)), fill_n2nsock(&sender, sender_sock);
ntohs(sender_sock->sin_port)); 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. /* 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 * 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; from_supernode = cmn.flags & N2N_FLAGS_FROM_SUPERNODE;
if(from_supernode) { if(from_supernode) {
skip_add = SN_ADD_SKIP; 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 */ /* We are going to add socket even if it was not there before */
cmn2.flags |= N2N_FLAGS_SOCKET | N2N_FLAGS_FROM_SUPERNODE; 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; rec_buf = encbuf;
/* Re-encode the header. */ /* 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 */ /* We are going to add socket even if it was not there before */
cmn2.flags |= N2N_FLAGS_SOCKET | N2N_FLAGS_FROM_SUPERNODE; cmn2.flags |= N2N_FLAGS_SOCKET | N2N_FLAGS_FROM_SUPERNODE;
fill_n2nsock(&reg.sock, (struct sockaddr*)sender_sock); memcpy(&reg.sock, &sender, sizeof(sender));
/* Re-encode the header. */ /* Re-encode the header. */
encode_REGISTER(encbuf, &encx, &cmn2, &reg); encode_REGISTER(encbuf, &encx, &cmn2, &reg);
@ -1960,7 +1960,7 @@ static int process_udp (n2n_sn_t * sss,
ack.lifetime = reg_lifetime(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) */ /* Add sender's data to federation (or update it) */
if(comm->is_federation == IS_FEDERATION) { 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); 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", traceEvent(TRACE_DEBUG, "Tx REGISTER_SUPER_NAK for %s",
macaddr_str(mac_buf, reg.edgeMac)); macaddr_str(mac_buf, reg.edgeMac));
@ -2041,7 +2041,7 @@ static int process_udp (n2n_sn_t * sss,
// NULL comm and from_supernode parameter) // NULL comm and from_supernode parameter)
// exception: do not forward auto ip draw // exception: do not forward auto ip draw
if(!is_null_mac(reg.edgeMac)) { if(!is_null_mac(reg.edgeMac)) {
fill_n2nsock(&reg.sock, (struct sockaddr*)sender_sock); memcpy(&reg.sock, &sender, sizeof(sender));
cmn2.pc = n2n_register_super; cmn2.pc = n2n_register_super;
encode_REGISTER_SUPER(ackbuf, &encx, &cmn2, &reg); encode_REGISTER_SUPER(ackbuf, &encx, &cmn2, &reg);
@ -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]", traceEvent(TRACE_DEBUG, "Tx REGISTER_SUPER_ACK for %s [%s]",
macaddr_str(mac_buf, reg.edgeMac), macaddr_str(mac_buf, reg.edgeMac),
@ -2108,7 +2108,7 @@ static int process_udp (n2n_sn_t * sss,
} else { } else {
// this is an edge with valid authentication registering with another supernode, so ... // this is an edge with valid authentication registering with another supernode, so ...
// 1- ... associate it with that other supernode // 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) // 2- ... we can delete it from regular list if present (can happen)
HASH_FIND_PEER(comm->edges, reg.edgeMac, peer); HASH_FIND_PEER(comm->edges, reg.edgeMac, peer);
if(peer != NULL) { if(peer != NULL) {
@ -2179,17 +2179,10 @@ static int process_udp (n2n_sn_t * sss,
n2n_sock_str_t sockbuf1; n2n_sock_str_t sockbuf1;
n2n_sock_str_t sockbuf2; n2n_sock_str_t sockbuf2;
macstr_t mac_buf1; macstr_t mac_buf1;
n2n_sock_t sender;
n2n_sock_t *orig_sender;
int i; int i;
uint8_t dec_tmpbuf[REG_SUPER_ACK_PAYLOAD_SPACE]; uint8_t dec_tmpbuf[REG_SUPER_ACK_PAYLOAD_SPACE];
n2n_REGISTER_SUPER_ACK_payload_t *payload; 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)); memset(&ack, 0, sizeof(n2n_REGISTER_SUPER_ACK_t));
if(!comm) { if(!comm) {
@ -2268,10 +2261,6 @@ static int process_udp (n2n_sn_t * sss,
struct peer_info *peer; struct peer_info *peer;
n2n_sock_str_t sockbuf; n2n_sock_str_t sockbuf;
macstr_t mac_buf; 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)); 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.mac, query.targetMac, sizeof(n2n_mac_t));
memcpy(pi.srcMac, sss->mac_addr, 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); 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", traceEvent(TRACE_DEBUG, "Tx PONG to %s",
macaddr_str(mac_buf, query.srcMac)); macaddr_str(mac_buf, query.srcMac));
@ -2448,7 +2437,7 @@ static int process_udp (n2n_sn_t * sss,
time_stamp()); time_stamp());
} }
// back to sender, be it edge or supernode (which will forward to edge) // 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", traceEvent(TRACE_DEBUG, "Tx PEER_INFO to %s",
macaddr_str(mac_buf, query.srcMac)); macaddr_str(mac_buf, query.srcMac));
@ -2508,7 +2497,7 @@ static int process_udp (n2n_sn_t * sss,
if(peer != NULL) { if(peer != NULL) {
if((comm->is_federation == IS_NO_FEDERATION) && (!is_null_mac(pi.srcMac))) { 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) // 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, // 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) // 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 // external udp
if(FD_ISSET(sss->sock, &socket_mask)) { if(FD_ISSET(sss->sock, &socket_mask)) {
struct sockaddr_in sender_sock; struct sockaddr_storage sas;
socklen_t i; 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*/, 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) if((bread < 0)
#ifdef WIN32 #ifdef WIN32
@ -2622,7 +2611,7 @@ int run_sn_loop (n2n_sn_t *sss) {
// we have a datagram to process... // we have a datagram to process...
if(bread > 0) { if(bread > 0) {
// ...and the datagram has data (not just a header) // ...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; continue;
if(FD_ISSET(conn->socket_fd, &socket_mask)) { 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, bread = recvfrom(conn->socket_fd,
conn->buffer + conn->position, conn->expected - conn->position, 0 /*flags*/, conn->buffer + conn->position, conn->expected - conn->position, 0 /*flags*/,
(struct sockaddr *)&sender_sock, (socklen_t *)&i); sender_sock, &ss_size);
if(bread <= 0) { 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)); traceEvent(TRACE_DEBUG, "recvfrom() returns %d and sees errno %d (%s)", bread, errno, strerror(errno));
#ifdef WIN32 #ifdef WIN32
traceEvent(TRACE_DEBUG, "WSAGetLastError(): %u", WSAGetLastError()); 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 // the prepended length has been read, preparing for the packet
conn->expected += be16toh(*(uint16_t*)(conn->buffer)); conn->expected += be16toh(*(uint16_t*)(conn->buffer));
if(conn->expected > N2N_SN_PKTBUF_SIZE) { 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"); traceEvent(TRACE_DEBUG, "too many bytes in tcp packet expected");
close_tcp_connection(sss, conn); close_tcp_connection(sss, conn);
continue; continue;
} }
} else { } else {
// full packet read, handle it // 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); conn->buffer + sizeof(uint16_t), conn->position - sizeof(uint16_t), now);
// reset, await new prepended length // reset, await new prepended length
@ -2693,42 +2681,45 @@ int run_sn_loop (n2n_sn_t *sss) {
// accept new incoming tcp connection // accept new incoming tcp connection
if(FD_ISSET(sss->tcp_sock, &socket_mask)) { if(FD_ISSET(sss->tcp_sock, &socket_mask)) {
struct sockaddr_in sender_sock; struct sockaddr_storage sas;
socklen_t i; 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) { 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) { 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) { if(conn) {
conn->socket_fd = tmp_sock; 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->inactive = 0;
conn->expected = sizeof(uint16_t); conn->expected = sizeof(uint16_t);
conn->position = 0; conn->position = 0;
HASH_ADD_INT(sss->tcp_connections, socket_fd, conn); HASH_ADD_INT(sss->tcp_connections, socket_fd, conn);
traceEvent(TRACE_INFO, "accepted incoming TCP connection from [%s]", 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 { } else {
// no space to store the socket for a new connection, close immediately // 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", 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 */ #endif /* N2N_HAVE_TCP */
// handle management port input // handle management port input
if(FD_ISSET(sss->mgmt_sock, &socket_mask)) { if(FD_ISSET(sss->mgmt_sock, &socket_mask)) {
struct sockaddr_in sender_sock; struct sockaddr_storage sas;
size_t i; 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*/, 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) { if(bread <= 0) {
traceEvent(TRACE_ERROR, "recvfrom() failed %d errno %d (%s)", bread, errno, strerror(errno)); traceEvent(TRACE_ERROR, "recvfrom() failed %d errno %d (%s)", bread, errno, strerror(errno));
*sss->keep_running = 0; *sss->keep_running = 0;
@ -2736,7 +2727,7 @@ int run_sn_loop (n2n_sn_t *sss) {
} }
// we have a datagram to process // 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 { } else {