From f36814b152f3a8d6a47e94f3735df507e52147a4 Mon Sep 17 00:00:00 2001 From: emanuele-f Date: Sat, 8 Jun 2019 19:54:46 +0200 Subject: [PATCH] Implement query peer to try p2p during send When a lot of monodirection traffic is sent, p2p can be hard to enstablish because a reply is needed in order to start the registration. Now a sending peer can query the peer information via the supernode. This is based on the following commits: - https://github.com/meyerd/n2n/commit/1236f37a70487b16c7269770e86b6e9e268cbb5e - https://github.com/meyerd/n2n/commit/ad2d41651006beb180ea35d4e9bd2b98ca7386cf - https://github.com/meyerd/n2n/commit/534867129916deb19bd20d669f8ac96e8cfcdc4f - https://github.com/meyerd/n2n/commit/b2806dcde821445f4c5d3e5500a1f5dc40890622 --- edge_utils.c | 90 +++++++++++++++++++++++++++++++- n2n.h | 4 +- n2n_wire.h | 139 +++++++++++++++++++++++++------------------------ sn.c | 142 ++++++++++++++++++++++++++++++++------------------- wire.c | 99 +++++++++++++++++++++++++++-------- 5 files changed, 330 insertions(+), 144 deletions(-) diff --git a/edge_utils.c b/edge_utils.c index 831745f..d93a785 100644 --- a/edge_utils.c +++ b/edge_utils.c @@ -405,7 +405,8 @@ static void register_with_new_peer(n2n_edge_t * eee, } register_with_local_peers(eee); - } + } else + scan->sock = *peer; } /* ************************************** */ @@ -656,6 +657,32 @@ static void send_register_super(n2n_edge_t * eee, /* ************************************** */ +/** Send a QUERY_PEER packet to the current supernode. */ +static void send_query_peer( n2n_edge_t * eee, + const n2n_mac_t dstMac) { + uint8_t pktbuf[N2N_PKT_BUF_SIZE]; + size_t idx; + n2n_common_t cmn = {0}; + n2n_QUERY_PEER_t query = {{0}}; + + cmn.ttl=N2N_DEFAULT_TTL; + cmn.pc = n2n_query_peer; + cmn.flags = 0; + memcpy( cmn.community, eee->conf.community_name, N2N_COMMUNITY_SIZE ); + + idx=0; + encode_mac( query.srcMac, &idx, eee->device.mac_addr ); + idx=0; + encode_mac( query.targetMac, &idx, dstMac ); + + idx=0; + encode_QUERY_PEER( pktbuf, &idx, &cmn, &query ); + + traceEvent( TRACE_DEBUG, "send QUERY_PEER to supernode" ); + + sendto_sock( eee->udp_sock, pktbuf, idx, &(eee->supernode) ); +} + /** Send a REGISTER packet to another edge. */ static void send_register(n2n_edge_t * eee, const n2n_sock_t * remote_peer, @@ -1076,6 +1103,37 @@ static int is_ethMulticast(const void * buf, size_t bufsize) { /* ************************************** */ +static int check_query_peer_info(n2n_edge_t *eee, time_t now, n2n_mac_t mac) { + struct peer_info *scan = eee->pending_peers; + + while(scan != NULL) { + if(memcmp(scan->mac_addr, mac, N2N_MAC_SIZE) == 0) + break; + + scan = scan->next; + } + + if(!scan) { + scan = calloc(1, sizeof(struct peer_info)); + + memcpy(scan->mac_addr, mac, N2N_MAC_SIZE); + scan->timeout = REGISTER_SUPER_INTERVAL_DFL; /* TODO: should correspond to the peer supernode registration timeout */ + update_peer_seen(scan, now); /* Don't change this it marks the pending peer for removal. */ + + peer_list_add(&(eee->pending_peers), scan); + } + + if(now - scan->last_sent_query > REGISTER_SUPER_INTERVAL_DFL) { + send_query_peer(eee, scan->mac_addr); + scan->last_sent_query = now; + return(0); + } + + return(1); +} + +/* ************************************** */ + /* @return 1 if destination is a peer, 0 if destination is supernode */ static int find_peer_destination(n2n_edge_t * eee, n2n_mac_t mac_address, @@ -1129,6 +1187,8 @@ static int find_peer_destination(n2n_edge_t * eee, traceEvent(TRACE_DEBUG, "P2P Peer [MAC=%02X:%02X:%02X:%02X:%02X:%02X] not found, using supernode", mac_address[0] & 0xFF, mac_address[1] & 0xFF, mac_address[2] & 0xFF, mac_address[3] & 0xFF, mac_address[4] & 0xFF, mac_address[5] & 0xFF); + + check_query_peer_info(eee, now, mac_address); } traceEvent(TRACE_DEBUG, "find_peer_address (%s) -> [%s]", @@ -1174,7 +1234,7 @@ static int send_packet(n2n_edge_t * eee, /* ************************************** */ /** A layer-2 packet was received at the tunnel and needs to be sent via UDP. */ -void send_packet2net(n2n_edge_t * eee, +static void send_packet2net(n2n_edge_t * eee, uint8_t *tap_pkt, size_t len) { ipstr_t ip_buf; n2n_mac_t destMac; @@ -1517,6 +1577,32 @@ static void readFromIPSocket(n2n_edge_t * eee, int in_sock) { traceEvent(TRACE_WARNING, "Rx REGISTER_SUPER_ACK with no outstanding REGISTER_SUPER."); } break; + } case MSG_TYPE_PEER_INFO: { + n2n_PEER_INFO_t pi; + struct peer_info * scan; + decode_PEER_INFO( &pi, &cmn, udp_buf, &rem, &idx ); + + if(!is_valid_peer_sock(&pi.sock)) { + char sockbuf[64]; + + traceEvent(TRACE_DEBUG, "Skip invalid PEER_INFO %s [%s]", + sock_to_cstr(sockbuf, &pi.sock), + macaddr_str(mac_buf1, pi.mac) ); + break; + } + + scan = find_peer_by_mac( eee->pending_peers, pi.mac ); + if (scan) { + scan->sock = pi.sock; + traceEvent(TRACE_INFO, "Rx PEER_INFO on %s", + macaddr_str(mac_buf1, pi.mac) ); + send_register(eee, &scan->sock, scan->mac_addr); + } else { + traceEvent(TRACE_INFO, "Rx PEER_INFO unknown peer %s", + macaddr_str(mac_buf1, pi.mac) ); + } + + break; } default: /* Not a known message type */ diff --git a/n2n.h b/n2n.h index f37bf15..8904b71 100644 --- a/n2n.h +++ b/n2n.h @@ -150,6 +150,8 @@ typedef struct tuntap_dev { #define MSG_TYPE_REGISTER_SUPER_ACK 6 #define MSG_TYPE_REGISTER_SUPER_NAK 7 #define MSG_TYPE_FEDERATION 8 +#define MSG_TYPE_PEER_INFO 9 +#define MSG_TYPE_QUERY_PEER 10 /* Set N2N_COMPRESSION_ENABLED to 0 to disable lzo1x compression of ethernet * frames. Doing this will break compatibility with the standard n2n packet @@ -174,6 +176,7 @@ struct peer_info { int timeout; time_t last_seen; time_t last_p2p; + time_t last_sent_query; }; #define N2N_EDGE_SN_HOST_SIZE 48 @@ -298,5 +301,4 @@ int quick_edge_init(char *device_name, char *community_name, char *supernode_ip_address_port, int *keep_on_running); -void send_packet2net(n2n_edge_t * eee, uint8_t *tap_pkt, size_t len); #endif /* _N2N_H_ */ diff --git a/n2n_wire.h b/n2n_wire.h index 0ca6fca..daa9359 100644 --- a/n2n_wire.h +++ b/n2n_wire.h @@ -61,7 +61,9 @@ typedef enum n2n_pc n2n_register_super=5, /* Register edge to supernode */ n2n_register_super_ack=6, /* ACK from supernode to edge */ n2n_register_super_nak=7, /* NAK from supernode to edge - registration refused */ - n2n_federation=8 /* Not used by edge */ + n2n_federation=8, /* Not used by edge */ + n2n_peer_info=9, /* Send info on a peer from sn to edge */ + n2n_query_peer=10 /* ask supernode for info on a peer */ } n2n_pc_t; #define N2N_FLAGS_OPTIONS 0x0080 @@ -84,91 +86,74 @@ typedef enum n2n_pc #define N2N_EINVAL -3 #define N2N_ENOSPACE -4 -struct n2n_sock +typedef struct n2n_sock { uint8_t family; /* AF_INET or AF_INET6; or 0 if invalid */ uint16_t port; /* host order */ - union + union { uint8_t v6[IPV6_SIZE]; /* byte sequence */ uint8_t v4[IPV4_SIZE]; /* byte sequence */ } addr; -}; +} n2n_sock_t; -typedef struct n2n_sock n2n_sock_t; - -struct n2n_auth +typedef struct n2n_auth { uint16_t scheme; /* What kind of auth */ uint16_t toksize; /* Size of auth token */ uint8_t token[N2N_AUTH_TOKEN_SIZE]; /* Auth data interpreted based on scheme */ -}; +} n2n_auth_t; -typedef struct n2n_auth n2n_auth_t; - - -struct n2n_common +typedef struct n2n_common { /* int version; */ uint8_t ttl; uint8_t pc; uint16_t flags; n2n_community_t community; -}; +} n2n_common_t; -typedef struct n2n_common n2n_common_t; - -struct n2n_REGISTER +typedef struct n2n_REGISTER { n2n_cookie_t cookie; /* Link REGISTER and REGISTER_ACK */ n2n_mac_t srcMac; /* MAC of registering party */ n2n_mac_t dstMac; /* MAC of target edge */ n2n_sock_t sock; /* REVISIT: unused? */ -}; +} n2n_REGISTER_t; -typedef struct n2n_REGISTER n2n_REGISTER_t; - -struct n2n_REGISTER_ACK +typedef struct n2n_REGISTER_ACK { n2n_cookie_t cookie; /* Return cookie from REGISTER */ n2n_mac_t srcMac; /* MAC of acknowledging party (supernode or edge) */ n2n_mac_t dstMac; /* Reflected MAC of registering edge from REGISTER */ n2n_sock_t sock; /* Supernode's view of edge socket (IP Addr, port) */ -}; +} n2n_REGISTER_ACK_t; -typedef struct n2n_REGISTER_ACK n2n_REGISTER_ACK_t; - -struct n2n_PACKET +typedef struct n2n_PACKET { n2n_mac_t srcMac; n2n_mac_t dstMac; n2n_sock_t sock; uint16_t transform; -}; - -typedef struct n2n_PACKET n2n_PACKET_t; - +} n2n_PACKET_t; /* Linked with n2n_register_super in n2n_pc_t. Only from edge to supernode. */ -struct n2n_REGISTER_SUPER +typedef struct n2n_REGISTER_SUPER { n2n_cookie_t cookie; /* Link REGISTER_SUPER and REGISTER_SUPER_ACK */ n2n_mac_t edgeMac; /* MAC to register with edge sending socket */ n2n_auth_t auth; /* Authentication scheme and tokens */ -}; - -typedef struct n2n_REGISTER_SUPER n2n_REGISTER_SUPER_t; - +} n2n_REGISTER_SUPER_t; /* Linked with n2n_register_super_ack in n2n_pc_t. Only from supernode to edge. */ -struct n2n_REGISTER_SUPER_ACK +typedef struct n2n_REGISTER_SUPER_ACK { n2n_cookie_t cookie; /* Return cookie from REGISTER_SUPER */ n2n_mac_t edgeMac; /* MAC registered to edge sending socket */ uint16_t lifetime; /* How long the registration will live */ n2n_sock_t sock; /* Sending sockets associated with edgeMac */ - /* The packet format provides additional supernode definitions here. + /* The packet format provides additional supernode definitions here. * uint8_t count, then for each count there is one * n2n_sock_t. */ @@ -177,30 +162,31 @@ struct n2n_REGISTER_SUPER_ACK * non-zero then sn_bak is valid. */ n2n_sock_t sn_bak; /* Socket of the first backup supernode */ -}; - -typedef struct n2n_REGISTER_SUPER_ACK n2n_REGISTER_SUPER_ACK_t; +} n2n_REGISTER_SUPER_ACK_t; /* Linked with n2n_register_super_ack in n2n_pc_t. Only from supernode to edge. */ -struct n2n_REGISTER_SUPER_NAK +typedef struct n2n_REGISTER_SUPER_NAK { n2n_cookie_t cookie; /* Return cookie from REGISTER_SUPER */ -}; +} n2n_REGISTER_SUPER_NAK_t; -typedef struct n2n_REGISTER_SUPER_NAK n2n_REGISTER_SUPER_NAK_t; - - - -struct n2n_buf +typedef struct n2n_PEER_INFO { - uint8_t * data; - size_t size; -}; + uint16_t aflags; + n2n_mac_t mac; + n2n_sock_t sock; +} n2n_PEER_INFO_t; + +typedef struct n2n_QUERY_PEER +{ + n2n_mac_t srcMac; + n2n_mac_t targetMac; +} n2n_QUERY_PEER_t; typedef struct n2n_buf n2n_buf_t; -int encode_uint8( uint8_t * base, +int encode_uint8( uint8_t * base, size_t * idx, const uint8_t v ); @@ -209,7 +195,7 @@ int decode_uint8( uint8_t * out, size_t * rem, size_t * idx ); -int encode_uint16( uint8_t * base, +int encode_uint16( uint8_t * base, size_t * idx, const uint16_t v ); @@ -218,7 +204,7 @@ int decode_uint16( uint16_t * out, size_t * rem, size_t * idx ); -int encode_uint32( uint8_t * base, +int encode_uint32( uint8_t * base, size_t * idx, const uint32_t v ); @@ -227,9 +213,9 @@ int decode_uint32( uint32_t * out, size_t * rem, size_t * idx ); -int encode_buf( uint8_t * base, +int encode_buf( uint8_t * base, size_t * idx, - const void * p, + const void * p, size_t s); int decode_buf( uint8_t * out, @@ -238,7 +224,7 @@ int decode_buf( uint8_t * out, size_t * rem, size_t * idx ); -int encode_mac( uint8_t * base, +int encode_mac( uint8_t * base, size_t * idx, const n2n_mac_t m ); @@ -247,7 +233,7 @@ int decode_mac( uint8_t * out, /* of size N2N_MAC_SIZE. This clearer than passin size_t * rem, size_t * idx ); -int encode_common( uint8_t * base, +int encode_common( uint8_t * base, size_t * idx, const n2n_common_t * common ); @@ -256,7 +242,7 @@ int decode_common( n2n_common_t * out, size_t * rem, size_t * idx ); -int encode_sock( uint8_t * base, +int encode_sock( uint8_t * base, size_t * idx, const n2n_sock_t * sock ); @@ -265,9 +251,9 @@ int decode_sock( n2n_sock_t * sock, size_t * rem, size_t * idx ); -int encode_REGISTER( uint8_t * base, +int encode_REGISTER( uint8_t * base, size_t * idx, - const n2n_common_t * common, + const n2n_common_t * common, const n2n_REGISTER_t * reg ); int decode_REGISTER( n2n_REGISTER_t * pkt, @@ -276,9 +262,9 @@ int decode_REGISTER( n2n_REGISTER_t * pkt, size_t * rem, size_t * idx ); -int encode_REGISTER_SUPER( uint8_t * base, +int encode_REGISTER_SUPER( uint8_t * base, size_t * idx, - const n2n_common_t * common, + const n2n_common_t * common, const n2n_REGISTER_SUPER_t * reg ); int decode_REGISTER_SUPER( n2n_REGISTER_SUPER_t * pkt, @@ -287,9 +273,9 @@ int decode_REGISTER_SUPER( n2n_REGISTER_SUPER_t * pkt, size_t * rem, size_t * idx ); -int encode_REGISTER_ACK( uint8_t * base, +int encode_REGISTER_ACK( uint8_t * base, size_t * idx, - const n2n_common_t * common, + const n2n_common_t * common, const n2n_REGISTER_ACK_t * reg ); int decode_REGISTER_ACK( n2n_REGISTER_ACK_t * pkt, @@ -309,13 +295,13 @@ int decode_REGISTER_SUPER_ACK( n2n_REGISTER_SUPER_ACK_t * reg, size_t * rem, size_t * idx ); -int fill_sockaddr( struct sockaddr * addr, - size_t addrlen, +int fill_sockaddr( struct sockaddr * addr, + size_t addrlen, const n2n_sock_t * sock ); -int encode_PACKET( uint8_t * base, +int encode_PACKET( uint8_t * base, size_t * idx, - const n2n_common_t * common, + const n2n_common_t * common, const n2n_PACKET_t * pkt ); int decode_PACKET( n2n_PACKET_t * pkt, @@ -324,5 +310,26 @@ int decode_PACKET( n2n_PACKET_t * pkt, size_t * rem, size_t * idx ); +int encode_PEER_INFO( uint8_t * base, + size_t * idx, + const n2n_common_t * common, + const n2n_PEER_INFO_t * pkt ); + +int decode_PEER_INFO( n2n_PEER_INFO_t * pkt, + const n2n_common_t * cmn, /* info on how to interpret it */ + const uint8_t * base, + size_t * rem, + size_t * idx ); + +int encode_QUERY_PEER( uint8_t * base, + size_t * idx, + const n2n_common_t * common, + const n2n_QUERY_PEER_t * pkt ); + +int decode_QUERY_PEER( n2n_QUERY_PEER_t * pkt, + const n2n_common_t * cmn, /* info on how to interpret it */ + const uint8_t * base, + size_t * rem, + size_t * idx ); #endif /* #if !defined( N2N_WIRE_H_ ) */ diff --git a/sn.c b/sn.c index 3e46c04..e49e8d5 100644 --- a/sn.c +++ b/sn.c @@ -60,13 +60,13 @@ struct n2n_allowed_communities { static struct n2n_allowed_communities *allowed_communities = NULL; -static int try_forward(n2n_sn_t * sss, +static int try_forward(n2n_sn_t * sss, const n2n_common_t * cmn, const n2n_mac_t dstMac, const uint8_t * pktbuf, size_t pktsize); -static int try_broadcast(n2n_sn_t * sss, +static int try_broadcast(n2n_sn_t * sss, const n2n_common_t * cmn, const n2n_mac_t srcMac, const uint8_t * pktbuf, @@ -123,7 +123,7 @@ static uint16_t reg_lifetime(n2n_sn_t * sss) { /** Update the edge table with the details of the edge which contacted the * supernode. */ -static int update_edge(n2n_sn_t * sss, +static int update_edge(n2n_sn_t * sss, const n2n_mac_t edgeMac, const n2n_community_t community, const n2n_sock_t * sender_sock, @@ -184,9 +184,9 @@ static int update_edge(n2n_sn_t * sss, * * @return -1 on error otherwise number of bytes sent */ -static ssize_t sendto_sock(n2n_sn_t * sss, - const n2n_sock_t * sock, - const uint8_t * pktbuf, +static ssize_t sendto_sock(n2n_sn_t * sss, + const n2n_sock_t * sock, + const uint8_t * pktbuf, size_t pktsize) { n2n_sock_str_t sockbuf; @@ -203,7 +203,7 @@ static ssize_t sendto_sock(n2n_sn_t * sss, pktsize, sock_to_cstr(sockbuf, sock)); - return sendto(sss->sock, pktbuf, pktsize, 0, + return sendto(sss->sock, pktbuf, pktsize, 0, (const struct sockaddr *)&udpsock, sizeof(struct sockaddr_in)); } else @@ -219,7 +219,7 @@ static ssize_t sendto_sock(n2n_sn_t * sss, /** Try to forward a message to a unicast MAC. If the MAC is unknown then * broadcast to all edges in the destination community. */ -static int try_forward(n2n_sn_t * sss, +static int try_forward(n2n_sn_t * sss, const n2n_common_t * cmn, const n2n_mac_t dstMac, const uint8_t * pktbuf, @@ -260,7 +260,7 @@ static int try_forward(n2n_sn_t * sss, /* Not a known MAC so drop. */ } - + return 0; } @@ -270,7 +270,7 @@ static int try_forward(n2n_sn_t * sss, * This will send the exact same datagram to zero or more edges registered to * the supernode. */ -static int try_broadcast(n2n_sn_t * sss, +static int try_broadcast(n2n_sn_t * sss, const n2n_common_t * cmn, const n2n_mac_t srcMac, const uint8_t * pktbuf, @@ -283,14 +283,14 @@ static int try_broadcast(n2n_sn_t * sss, traceEvent(TRACE_DEBUG, "try_broadcast"); scan = sss->edges; - while(scan != NULL) + while(scan != NULL) { if(0 == (memcmp(scan->community_name, cmn->community, sizeof(n2n_community_t))) && (0 != memcmp(srcMac, scan->mac_addr, sizeof(n2n_mac_t)))) /* REVISIT: exclude if the destination socket is where the packet came from. */ { int data_sent_len; - + data_sent_len = sendto_sock(sss, &(scan->sock), pktbuf, pktsize); if(data_sent_len != pktsize) @@ -302,7 +302,7 @@ static int try_broadcast(n2n_sn_t * sss, macaddr_str(mac_buf, scan->mac_addr), strerror(errno)); } - else + else { ++(sss->stats.broadcast); traceEvent(TRACE_DEBUG, "multicast %lu to [%s] %s", @@ -314,14 +314,14 @@ static int try_broadcast(n2n_sn_t * sss, scan = scan->next; } /* while */ - + return 0; } -static int process_mgmt(n2n_sn_t * sss, +static int process_mgmt(n2n_sn_t * sss, const struct sockaddr_in * sender_sock, - const uint8_t * mgmt_buf, + const uint8_t * mgmt_buf, size_t mgmt_size, time_t now) { @@ -331,46 +331,46 @@ static int process_mgmt(n2n_sn_t * sss, traceEvent(TRACE_DEBUG, "process_mgmt"); - ressize += snprintf(resbuf+ressize, N2N_SN_PKTBUF_SIZE-ressize, + ressize += snprintf(resbuf+ressize, N2N_SN_PKTBUF_SIZE-ressize, "----------------\n"); - ressize += snprintf(resbuf+ressize, N2N_SN_PKTBUF_SIZE-ressize, + ressize += snprintf(resbuf+ressize, N2N_SN_PKTBUF_SIZE-ressize, "uptime %lu\n", (now - sss->start_time)); - ressize += snprintf(resbuf+ressize, N2N_SN_PKTBUF_SIZE-ressize, - "edges %u\n", + ressize += snprintf(resbuf+ressize, N2N_SN_PKTBUF_SIZE-ressize, + "edges %u\n", (unsigned int)peer_list_size(sss->edges)); - ressize += snprintf(resbuf+ressize, N2N_SN_PKTBUF_SIZE-ressize, - "errors %u\n", + ressize += snprintf(resbuf+ressize, N2N_SN_PKTBUF_SIZE-ressize, + "errors %u\n", (unsigned int)sss->stats.errors); - ressize += snprintf(resbuf+ressize, N2N_SN_PKTBUF_SIZE-ressize, - "reg_sup %u\n", + ressize += snprintf(resbuf+ressize, N2N_SN_PKTBUF_SIZE-ressize, + "reg_sup %u\n", (unsigned int)sss->stats.reg_super); - ressize += snprintf(resbuf+ressize, N2N_SN_PKTBUF_SIZE-ressize, - "reg_nak %u\n", + ressize += snprintf(resbuf+ressize, N2N_SN_PKTBUF_SIZE-ressize, + "reg_nak %u\n", (unsigned int)sss->stats.reg_super_nak); - ressize += snprintf(resbuf+ressize, N2N_SN_PKTBUF_SIZE-ressize, + ressize += snprintf(resbuf+ressize, N2N_SN_PKTBUF_SIZE-ressize, "fwd %u\n", (unsigned int) sss->stats.fwd); - ressize += snprintf(resbuf+ressize, N2N_SN_PKTBUF_SIZE-ressize, + ressize += snprintf(resbuf+ressize, N2N_SN_PKTBUF_SIZE-ressize, "broadcast %u\n", (unsigned int) sss->stats.broadcast); - ressize += snprintf(resbuf+ressize, N2N_SN_PKTBUF_SIZE-ressize, - "last fwd %lu sec ago\n", + ressize += snprintf(resbuf+ressize, N2N_SN_PKTBUF_SIZE-ressize, + "last fwd %lu sec ago\n", (long unsigned int)(now - sss->stats.last_fwd)); - ressize += snprintf(resbuf+ressize, N2N_SN_PKTBUF_SIZE-ressize, + ressize += snprintf(resbuf+ressize, N2N_SN_PKTBUF_SIZE-ressize, "last reg %lu sec ago\n", (long unsigned int) (now - sss->stats.last_reg_super)); - r = sendto(sss->mgmt_sock, resbuf, ressize, 0/*flags*/, + r = sendto(sss->mgmt_sock, resbuf, ressize, 0/*flags*/, (struct sockaddr *)sender_sock, sizeof(struct sockaddr_in)); if(r <= 0) @@ -390,13 +390,13 @@ static int process_mgmt(n2n_sn_t * sss, static int allowed_n2n_community(n2n_common_t *cmn) { if(allowed_communities != NULL) { struct n2n_allowed_communities *c; - + HASH_FIND_STR(allowed_communities, (const char*)cmn->community, c); return((c == NULL) ? 0 : 1); } else { /* If no allowed community is defined, all communities are allowed */ } - + return(1); } @@ -408,18 +408,18 @@ static int load_allowed_n2n_communities(char *path) { FILE *fd = fopen(path, "r"); struct n2n_allowed_communities *s, *tmp; uint32_t num_communities = 0; - + if(fd == NULL) { traceEvent(TRACE_WARNING, "File %s not found", path); return -1; } - + HASH_ITER(hh, allowed_communities, s, tmp) free(s); - + while((line = fgets(buffer, sizeof(buffer), fd)) != NULL) { int len = strlen(line); - + if((len < 2) || line[0] == '#') continue; @@ -431,7 +431,7 @@ static int load_allowed_n2n_communities(char *path) { } else break; } - + s = (struct n2n_allowed_communities*)malloc(sizeof(struct n2n_allowed_communities)); if(s != NULL) { @@ -448,16 +448,16 @@ static int load_allowed_n2n_communities(char *path) { traceEvent(TRACE_NORMAL, "Loaded %u communities from %s", num_communities, path); - + return(0); } /** Examine a datagram and determine what to do with it. * */ -static int process_udp(n2n_sn_t * sss, +static int process_udp(n2n_sn_t * sss, const struct sockaddr_in * sender_sock, - const uint8_t * udp_buf, + const uint8_t * udp_buf, size_t udp_size, time_t now) { @@ -508,7 +508,7 @@ static int process_udp(n2n_sn_t * sss, /* pkt will be modified in place and recoded to an output of potentially * different size due to addition of the socket.*/ - n2n_PACKET_t pkt; + n2n_PACKET_t pkt; n2n_common_t cmn2; uint8_t encbuf[N2N_SN_PKTBUF_SIZE]; size_t encx=0; @@ -576,7 +576,7 @@ static int process_udp(n2n_sn_t * sss, decode_REGISTER(®, &cmn, udp_buf, &rem, &idx); unicast = (0 == is_multi_broadcast(reg.dstMac)); - + if(unicast) { traceEvent(TRACE_DEBUG, "Rx REGISTER %s -> %s %s", macaddr_str(mac_buf, reg.srcMac), @@ -624,7 +624,7 @@ static int process_udp(n2n_sn_t * sss, uint8_t ackbuf[N2N_SN_PKTBUF_SIZE]; size_t encx=0; - /* Edge requesting registration with us. */ + /* Edge requesting registration with us. */ sss->stats.last_reg_super=now; ++(sss->stats.reg_super); decode_REGISTER_SUPER(®, &cmn, udp_buf, &rem, &idx); @@ -660,7 +660,7 @@ static int process_udp(n2n_sn_t * sss, encode_REGISTER_SUPER_ACK(ackbuf, &encx, &cmn2, &ack); - sendto(sss->sock, ackbuf, encx, 0, + sendto(sss->sock, ackbuf, encx, 0, (struct sockaddr *)sender_sock, sizeof(struct sockaddr_in)); traceEvent(TRACE_DEBUG, "Tx REGISTER_SUPER_ACK for %s [%s]", @@ -670,6 +670,42 @@ static int process_udp(n2n_sn_t * sss, traceEvent(TRACE_INFO, "Discarded registration: unallowed community '%s'", (char*)cmn.community); break; + } case MSG_TYPE_QUERY_PEER: { + n2n_QUERY_PEER_t query; + uint8_t encbuf[N2N_SN_PKTBUF_SIZE]; + size_t encx=0; + n2n_common_t cmn2; + n2n_PEER_INFO_t pi; + struct peer_info *scan; + + decode_QUERY_PEER( &query, &cmn, udp_buf, &rem, &idx ); + + traceEvent( TRACE_DEBUG, "Rx QUERY_PEER from %s for %s", + macaddr_str( mac_buf, query.srcMac ), + macaddr_str( mac_buf2, query.targetMac ) ); + + scan = find_peer_by_mac( sss->edges, query.targetMac ); + if (scan) { + cmn2.ttl = N2N_DEFAULT_TTL; + cmn2.pc = n2n_peer_info; + cmn2.flags = N2N_FLAGS_FROM_SUPERNODE; + memcpy( cmn2.community, cmn.community, sizeof(n2n_community_t) ); + + pi.aflags = 0; + memcpy( pi.mac, query.targetMac, sizeof(n2n_mac_t) ); + pi.sock = scan->sock; + + encode_PEER_INFO( encbuf, &encx, &cmn2, &pi ); + + sendto( sss->sock, encbuf, encx, 0, + (struct sockaddr *)sender_sock, sizeof(struct sockaddr_in) ); + + traceEvent( TRACE_DEBUG, "Tx PEER_INFO to %s", + macaddr_str( mac_buf, query.srcMac ) ); + } else { + traceEvent( TRACE_DEBUG, "Ignoring QUERY_PEER for unknown edge %s", + macaddr_str( mac_buf, query.targetMac ) ); + } } default: /* Not a known message type */ @@ -720,11 +756,11 @@ static int setOption(int optkey, char *_optarg, n2n_sn_t *sss) { case 'l': /* local-port */ sss->lport = atoi(_optarg); break; - + case 'c': /* community file */ load_allowed_n2n_communities(optarg); break; - + case 'f': /* foreground */ sss->daemon = 0; break; @@ -778,7 +814,7 @@ static char *trim(char *s) { while(isspace(s[0]) || (s[0] == '"') || (s[0] == '\'')) s++; - + if(s[0] == 0) return s; end = &s[strlen(s) - 1]; @@ -861,9 +897,9 @@ static void dump_registrations(int signo) { char buf[32]; time_t now = time(NULL); u_int num = 0; - + traceEvent(TRACE_NORMAL, "===================================="); - + while(list != NULL) { if(list->sock.family == AF_INET) traceEvent(TRACE_NORMAL, "[id: %u][MAC: %s][edge: %u.%u.%u.%u:%u][community: %s][last seen: %u sec ago]", @@ -910,7 +946,7 @@ int main(int argc, char * const argv[]) { #if defined(N2N_HAVE_DAEMON) if(sss_node.daemon) { useSyslog=1; /* traceEvent output now goes to syslog. */ - + if(-1 == daemon(0, 0)) { traceEvent(TRACE_ERROR, "Failed to become daemon."); exit(-5); @@ -940,7 +976,7 @@ int main(int argc, char * const argv[]) { #ifndef WIN32 signal(SIGHUP, dump_registrations); #endif - + return run_loop(&sss_node); } diff --git a/wire.c b/wire.c index e21d321..e2f2974 100644 --- a/wire.c +++ b/wire.c @@ -29,7 +29,7 @@ #include "n2n_wire.h" #include -int encode_uint8( uint8_t * base, +int encode_uint8( uint8_t * base, size_t * idx, const uint8_t v ) { @@ -51,7 +51,7 @@ int decode_uint8( uint8_t * out, return 1; } -int encode_uint16( uint8_t * base, +int encode_uint16( uint8_t * base, size_t * idx, const uint16_t v ) { @@ -75,7 +75,7 @@ int decode_uint16( uint16_t * out, return 2; } -int encode_uint32( uint8_t * base, +int encode_uint32( uint8_t * base, size_t * idx, const uint32_t v ) { @@ -103,9 +103,9 @@ int decode_uint32( uint32_t * out, return 4; } -int encode_buf( uint8_t * base, +int encode_buf( uint8_t * base, size_t * idx, - const void * p, + const void * p, size_t s) { memcpy( (base + (*idx)), p, s ); @@ -130,7 +130,7 @@ int decode_buf( uint8_t * out, -int encode_mac( uint8_t * base, +int encode_mac( uint8_t * base, size_t * idx, const n2n_mac_t m ) { @@ -147,7 +147,7 @@ int decode_mac( uint8_t * out, /* of size N2N_MAC_SIZE. This clearer than passin -int encode_common( uint8_t * base, +int encode_common( uint8_t * base, size_t * idx, const n2n_common_t * common ) { @@ -160,7 +160,7 @@ int encode_common( uint8_t * base, encode_uint16( base, idx, flags ); encode_buf( base, idx, common->community, N2N_COMMUNITY_SIZE ); - + return -1; } @@ -177,7 +177,7 @@ int decode_common( n2n_common_t * out, { return -1; } - + decode_uint8( &(out->ttl), base, rem, idx ); decode_uint16( &(out->flags), base, rem, idx ); out->pc = ( out->flags & N2N_FLAGS_TYPE_MASK ); @@ -189,14 +189,14 @@ int decode_common( n2n_common_t * out, } -int encode_sock( uint8_t * base, +int encode_sock( uint8_t * base, size_t * idx, const n2n_sock_t * sock ) { int retval=0; uint16_t f; - switch (sock->family) + switch (sock->family) { case AF_INET: { @@ -229,7 +229,7 @@ int decode_sock( n2n_sock_t * sock, { size_t * idx0=idx; uint16_t f=0; - + decode_uint16( &f, base, rem, idx ); if( f & 0x8000 ) @@ -251,9 +251,9 @@ int decode_sock( n2n_sock_t * sock, return (idx-idx0); } -int encode_REGISTER( uint8_t * base, +int encode_REGISTER( uint8_t * base, size_t * idx, - const n2n_common_t * common, + const n2n_common_t * common, const n2n_REGISTER_t * reg ) { int retval=0; @@ -289,9 +289,9 @@ int decode_REGISTER( n2n_REGISTER_t * reg, return retval; } -int encode_REGISTER_SUPER( uint8_t * base, +int encode_REGISTER_SUPER( uint8_t * base, size_t * idx, - const n2n_common_t * common, + const n2n_common_t * common, const n2n_REGISTER_SUPER_t * reg ) { int retval=0; @@ -320,9 +320,9 @@ int decode_REGISTER_SUPER( n2n_REGISTER_SUPER_t * reg, return retval; } -int encode_REGISTER_ACK( uint8_t * base, +int encode_REGISTER_ACK( uint8_t * base, size_t * idx, - const n2n_common_t * common, + const n2n_common_t * common, const n2n_REGISTER_ACK_t * reg ) { int retval=0; @@ -413,8 +413,8 @@ int decode_REGISTER_SUPER_ACK( n2n_REGISTER_SUPER_ACK_t * reg, return retval; } -int fill_sockaddr( struct sockaddr * addr, - size_t addrlen, +int fill_sockaddr( struct sockaddr * addr, + size_t addrlen, const n2n_sock_t * sock ) { int retval=-1; @@ -435,9 +435,9 @@ int fill_sockaddr( struct sockaddr * addr, } -int encode_PACKET( uint8_t * base, +int encode_PACKET( uint8_t * base, size_t * idx, - const n2n_common_t * common, + const n2n_common_t * common, const n2n_PACKET_t * pkt ) { int retval=0; @@ -475,3 +475,58 @@ int decode_PACKET( n2n_PACKET_t * pkt, return retval; } +int encode_PEER_INFO( uint8_t * base, + size_t * idx, + const n2n_common_t * common, + const n2n_PEER_INFO_t * pkt ) +{ + int retval=0; + retval += encode_common( base, idx, common ); + retval += encode_uint16( base, idx, pkt->aflags ); + retval += encode_mac( base, idx, pkt->mac ); + retval += encode_sock( base, idx, &pkt->sock ); + + return retval; +} + +int decode_PEER_INFO( n2n_PEER_INFO_t * pkt, + const n2n_common_t * cmn, /* info on how to interpret it */ + const uint8_t * base, + size_t * rem, + size_t * idx ) +{ + size_t retval=0; + memset( pkt, 0, sizeof(n2n_PEER_INFO_t) ); + retval += decode_uint16( &(pkt->aflags), base, rem, idx ); + retval += decode_mac( pkt->mac, base, rem, idx ); + retval += decode_sock( &pkt->sock, base, rem, idx ); + + return retval; +} + +int encode_QUERY_PEER( uint8_t * base, + size_t * idx, + const n2n_common_t * common, + const n2n_QUERY_PEER_t * pkt ) +{ + int retval=0; + retval += encode_common( base, idx, common ); + retval += encode_mac( base, idx, pkt->srcMac ); + retval += encode_mac( base, idx, pkt->targetMac ); + + return retval; +} + +int decode_QUERY_PEER( n2n_QUERY_PEER_t * pkt, + const n2n_common_t * cmn, /* info on how to interpret it */ + const uint8_t * base, + size_t * rem, + size_t * idx ) +{ + size_t retval=0; + memset( pkt, 0, sizeof(n2n_QUERY_PEER_t) ); + retval += decode_mac( pkt->srcMac, base, rem, idx ); + retval += decode_mac( pkt->targetMac, base, rem, idx ); + + return retval; +}