From 6bdfdf6be49bcb3da8820caac5afadabeed5fb4c Mon Sep 17 00:00:00 2001 From: fengdaolong Date: Sun, 16 Aug 2020 22:34:41 +0800 Subject: [PATCH] Enhanced edge management console function. 1. Edge can view the IP address and socket information of the connected tap adapter through the management console (127.0.0.1:5644); 2. Repair two memory leaks; 3. Fix several code errors and redundant logic; --- include/n2n_wire.h | 1 + src/edge.c | 2 +- src/edge_utils.c | 669 ++++++++++++++++++++++++--------------------- src/sn_utils.c | 16 +- src/wire.c | 64 ++--- 5 files changed, 403 insertions(+), 349 deletions(-) diff --git a/include/n2n_wire.h b/include/n2n_wire.h index 0ebc714..e58f708 100644 --- a/include/n2n_wire.h +++ b/include/n2n_wire.h @@ -125,6 +125,7 @@ typedef struct n2n_REGISTER n2n_mac_t srcMac; /**< MAC of registering party */ n2n_mac_t dstMac; /**< MAC of target edge */ n2n_sock_t sock; /**< REVISIT: unused? */ + n2n_ip_subnet_t dev_addr; /**< IP address of the tuntap adapter. */ } n2n_REGISTER_t; typedef struct n2n_REGISTER_ACK diff --git a/src/edge.c b/src/edge.c index 037c2f3..1f2423e 100644 --- a/src/edge.c +++ b/src/edge.c @@ -978,9 +978,9 @@ int main(int argc, char* argv[]) { #endif /* Cleanup */ - edge_term(eee); edge_term_conf(&eee->conf); tuntap_close(&eee->device); + edge_term(eee); return(rc); } diff --git a/src/edge_utils.c b/src/edge_utils.c index 0e2820c..3389f22 100644 --- a/src/edge_utils.c +++ b/src/edge_utils.c @@ -27,19 +27,24 @@ static HEAP_ALLOC(wrkmem, LZO1X_1_MEM_COMPRESS); static const char * supernode_ip(const n2n_edge_t * eee); static void send_register(n2n_edge_t *eee, const n2n_sock_t *remote_peer, const n2n_mac_t peer_mac); -static void check_peer_registration_needed(n2n_edge_t * eee, - uint8_t from_supernode, - const n2n_mac_t mac, - const n2n_sock_t * peer); + +static void check_peer_registration_needed(n2n_edge_t *eee, + uint8_t from_supernode, + const n2n_mac_t mac, + const n2n_ip_subnet_t *dev_addr, + const n2n_sock_t *peer); + static int edge_init_sockets(n2n_edge_t *eee, int udp_local_port, int mgmt_port, uint8_t tos); static int edge_init_routes(n2n_edge_t *eee, n2n_route_t *routes, uint16_t num_routes); static void edge_cleanup_routes(n2n_edge_t *eee); static int supernode2addr(n2n_sock_t * sn, const n2n_sn_name_t addrIn); -static void check_known_peer_sock_change(n2n_edge_t * eee, - uint8_t from_supernode, - const n2n_mac_t mac, - const n2n_sock_t * peer, - time_t when); + +static void check_known_peer_sock_change(n2n_edge_t *eee, + uint8_t from_supernode, + const n2n_mac_t mac, + const n2n_ip_subnet_t *dev_addr, + const n2n_sock_t *peer, + time_t when); /* ************************************** */ @@ -447,107 +452,113 @@ static void register_with_local_peers(n2n_edge_t * eee) { * * Called from the main loop when Rx a packet for our device mac. */ -static void register_with_new_peer(n2n_edge_t * eee, - uint8_t from_supernode, - const n2n_mac_t mac, - const n2n_sock_t * peer) { - /* REVISIT: purge of pending_peers not yet done. */ - struct peer_info * scan; - macstr_t mac_buf; - n2n_sock_str_t sockbuf; +static void register_with_new_peer(n2n_edge_t *eee, + uint8_t from_supernode, + const n2n_mac_t mac, + const n2n_ip_subnet_t *dev_addr, + const n2n_sock_t *peer) { + /* REVISIT: purge of pending_peers not yet done. */ + struct peer_info *scan; + macstr_t mac_buf; + n2n_sock_str_t sockbuf; - HASH_FIND_PEER(eee->pending_peers, mac, scan); + HASH_FIND_PEER(eee->pending_peers, mac, scan); - /* NOTE: pending_peers are purged periodically with purge_expired_registrations */ - if(scan == NULL) { - scan = calloc(1, sizeof(struct peer_info)); + /* NOTE: pending_peers are purged periodically with purge_expired_registrations */ + if (scan == NULL) { + scan = calloc(1, sizeof(struct peer_info)); - memcpy(scan->mac_addr, mac, N2N_MAC_SIZE); - scan->sock = *peer; - scan->timeout = REGISTER_SUPER_INTERVAL_DFL; /* TODO: should correspond to the peer supernode registration timeout */ - scan->last_seen = time(NULL); /* Don't change this it marks the pending peer for removal. */ - scan->last_valid_time_stamp = initial_time_stamp (); + memcpy(scan->mac_addr, mac, N2N_MAC_SIZE); + scan->sock = *peer; + scan->timeout = eee->conf.register_interval; /* TODO: should correspond to the peer supernode registration timeout */ + scan->last_valid_time_stamp = initial_time_stamp(); - HASH_ADD_PEER(eee->pending_peers, scan); + HASH_ADD_PEER(eee->pending_peers, scan); - traceEvent(TRACE_DEBUG, "=== new pending %s -> %s", - macaddr_str(mac_buf, scan->mac_addr), - sock_to_cstr(sockbuf, &(scan->sock))); + traceEvent(TRACE_DEBUG, "=== new pending %s -> %s", + macaddr_str(mac_buf, scan->mac_addr), + sock_to_cstr(sockbuf, &(scan->sock))); - traceEvent(TRACE_DEBUG, "Pending peers list size=%u", - HASH_COUNT(eee->pending_peers)); + traceEvent(TRACE_DEBUG, "Pending peers list size=%u", + HASH_COUNT(eee->pending_peers)); - /* trace Sending REGISTER */ - if(from_supernode) { - /* UDP NAT hole punching through supernode. Send to peer first(punch local UDP hole) - * and then ask supernode to forward. Supernode then ask peer to ack. Some nat device - * drop and block ports with incoming UDP packet if out-come traffic does not exist. - * So we can alternatively set TTL so that the packet sent to peer never really reaches - * The register_ttl is basically nat level + 1. Set it to 1 means host like DMZ. - */ - if(eee->conf.register_ttl == 1) { - /* We are DMZ host or port is directly accessible. Just let peer to send back the ack */ + /* trace Sending REGISTER */ + if (from_supernode) { + /* UDP NAT hole punching through supernode. Send to peer first(punch local UDP hole) + * and then ask supernode to forward. Supernode then ask peer to ack. Some nat device + * drop and block ports with incoming UDP packet if out-come traffic does not exist. + * So we can alternatively set TTL so that the packet sent to peer never really reaches + * The register_ttl is basically nat level + 1. Set it to 1 means host like DMZ. + */ + if (eee->conf.register_ttl == 1) { + /* We are DMZ host or port is directly accessible. Just let peer to send back the ack */ #ifndef WIN32 - } else if(eee->conf.register_ttl > 1) { - /* Setting register_ttl usually implies that the edge knows the internal net topology - * clearly, we can apply aggressive port prediction to support incoming Symmetric NAT - */ - int curTTL = 0; - socklen_t lenTTL = sizeof(int); - n2n_sock_t sock = scan->sock; - int alter = 16; /* TODO: set by command line or more reliable prediction method */ + } else if (eee->conf.register_ttl > 1) { + /* Setting register_ttl usually implies that the edge knows the internal net topology + * clearly, we can apply aggressive port prediction to support incoming Symmetric NAT + */ + int curTTL = 0; + socklen_t lenTTL = sizeof(int); + n2n_sock_t sock = scan->sock; + int alter = 16; /* TODO: set by command line or more reliable prediction method */ - getsockopt(eee->udp_sock, IPPROTO_IP, IP_TTL, (void *)(char *)&curTTL, &lenTTL); - setsockopt(eee->udp_sock, IPPROTO_IP, IP_TTL, - (void *)(char *)&eee->conf.register_ttl, - sizeof(eee->conf.register_ttl)); - for (; alter > 0; alter--, sock.port++) - { - send_register(eee, &sock, mac); - } - setsockopt(eee->udp_sock, IPPROTO_IP, IP_TTL, (void *)(char *)&curTTL, sizeof(curTTL)); + getsockopt(eee->udp_sock, IPPROTO_IP, IP_TTL, (void *) (char *) &curTTL, &lenTTL); + setsockopt(eee->udp_sock, IPPROTO_IP, IP_TTL, + (void *) (char *) &eee->conf.register_ttl, + sizeof(eee->conf.register_ttl)); + for (; alter > 0; alter--, sock.port++) { + send_register(eee, &sock, mac); + } + setsockopt(eee->udp_sock, IPPROTO_IP, IP_TTL, (void *) (char *) &curTTL, sizeof(curTTL)); #endif - } else { /* eee->conf.register_ttl <= 0 */ - /* Normal STUN */ - send_register(eee, &(scan->sock), mac); - } - send_register(eee, &(eee->supernode), mac); - } else { - /* P2P register, send directly */ - send_register(eee, &(scan->sock), mac); - } + } else { /* eee->conf.register_ttl <= 0 */ + /* Normal STUN */ + send_register(eee, &(scan->sock), mac); + } + send_register(eee, &(eee->supernode), mac); + } else { + /* P2P register, send directly */ + send_register(eee, &(scan->sock), mac); + } - register_with_local_peers(eee); - } else - scan->sock = *peer; + register_with_local_peers(eee); + } else{ + scan->sock = *peer; + } + scan->last_seen = time(NULL); + if(dev_addr != NULL){ + memcpy(&(scan->dev_addr), dev_addr, sizeof(n2n_ip_subnet_t)); + } } + /* ************************************** */ /** Update the last_seen time for this peer, or get registered. */ -static void check_peer_registration_needed(n2n_edge_t * eee, - uint8_t from_supernode, - const n2n_mac_t mac, - const n2n_sock_t * peer) { - struct peer_info *scan; +static void check_peer_registration_needed(n2n_edge_t *eee, + uint8_t from_supernode, + const n2n_mac_t mac, + const n2n_ip_subnet_t *dev_addr, + const n2n_sock_t *peer) { + struct peer_info *scan; - HASH_FIND_PEER(eee->known_peers, mac, scan); + HASH_FIND_PEER(eee->known_peers, mac, scan); - if(scan == NULL) { - /* Not in known_peers - start the REGISTER process. */ - register_with_new_peer(eee, from_supernode, mac, peer); - } else { - /* Already in known_peers. */ - time_t now = time(NULL); + if (scan == NULL) { + /* Not in known_peers - start the REGISTER process. */ + register_with_new_peer(eee, from_supernode, mac, dev_addr, peer); + } else { + /* Already in known_peers. */ + time_t now = time(NULL); - if(!from_supernode) - scan->last_p2p = now; + if (!from_supernode) + scan->last_p2p = now; - if((now - scan->last_seen) > 0 /* >= 1 sec */) { - /* Don't register too often */ - check_known_peer_sock_change(eee, from_supernode, mac, peer, now); - } - } + if ((now - scan->last_seen) > 0 /* >= 1 sec */) { + /* Don't register too often */ + check_known_peer_sock_change(eee, from_supernode, mac, dev_addr, peer, now); + } + } } /* ************************************** */ @@ -631,46 +642,47 @@ static const n2n_mac_t null_mac = {0, 0, 0, 0, 0, 0}; /** Check if a known peer socket has changed and possibly register again. */ -static void check_known_peer_sock_change(n2n_edge_t * eee, - uint8_t from_supernode, - const n2n_mac_t mac, - const n2n_sock_t * peer, - time_t when) { - struct peer_info *scan; - n2n_sock_str_t sockbuf1; - n2n_sock_str_t sockbuf2; /* don't clobber sockbuf1 if writing two addresses to trace */ - macstr_t mac_buf; +static void check_known_peer_sock_change(n2n_edge_t *eee, + uint8_t from_supernode, + const n2n_mac_t mac, + const n2n_ip_subnet_t *dev_addr, + const n2n_sock_t *peer, + time_t when) { + struct peer_info *scan; + n2n_sock_str_t sockbuf1; + n2n_sock_str_t sockbuf2; /* don't clobber sockbuf1 if writing two addresses to trace */ + macstr_t mac_buf; - if(is_empty_ip_address(peer)) - return; + if (is_empty_ip_address(peer)) + return; - if(!memcmp(mac, broadcast_mac, N2N_MAC_SIZE)) - return; + if (!memcmp(mac, broadcast_mac, N2N_MAC_SIZE)) + return; - /* Search the peer in known_peers */ - HASH_FIND_PEER(eee->known_peers, mac, scan); + /* Search the peer in known_peers */ + HASH_FIND_PEER(eee->known_peers, mac, scan); - if(!scan) - /* Not in known_peers */ - return; + if (!scan) + /* Not in known_peers */ + return; - if(!sock_equal(&(scan->sock), peer)) { - if(!from_supernode) { - /* This is a P2P packet */ - traceEvent(TRACE_NORMAL, "Peer changed %s: %s -> %s", - macaddr_str(mac_buf, scan->mac_addr), - sock_to_cstr(sockbuf1, &(scan->sock)), - sock_to_cstr(sockbuf2, peer)); - /* The peer has changed public socket. It can no longer be assumed to be reachable. */ - HASH_DEL(eee->known_peers, scan); - free(scan); + if (!sock_equal(&(scan->sock), peer)) { + if (!from_supernode) { + /* This is a P2P packet */ + traceEvent(TRACE_NORMAL, "Peer changed %s: %s -> %s", + macaddr_str(mac_buf, scan->mac_addr), + sock_to_cstr(sockbuf1, &(scan->sock)), + sock_to_cstr(sockbuf2, peer)); + /* The peer has changed public socket. It can no longer be assumed to be reachable. */ + HASH_DEL(eee->known_peers, scan); + free(scan); - register_with_new_peer(eee, from_supernode, mac, peer); - } else { - /* Don't worry about what the supernode reports, it could be seeing a different socket. */ - } - } else - scan->last_seen = when; + register_with_new_peer(eee, from_supernode, mac, dev_addr, peer); + } else { + /* Don't worry about what the supernode reports, it could be seeing a different socket. */ + } + } else + scan->last_seen = when; } /* ************************************** */ @@ -840,8 +852,11 @@ static void send_register(n2n_edge_t * eee, idx=0; encode_mac(reg.dstMac, &idx, peer_mac); } + reg.dev_addr.net_addr = ntohl(eee->device.ip_addr); + reg.dev_addr.net_bitlen = mask2bitlen(ntohl(eee->device.device_mask)); - idx=0; + + idx=0; encode_REGISTER(pktbuf, &idx, &cmn, ®); traceEvent(TRACE_INFO, "Send REGISTER to %s", @@ -976,13 +991,12 @@ static const char * supernode_ip(const n2n_edge_t * eee) { /** A PACKET has arrived containing an encapsulated ethernet datagram - usually * encrypted. */ static int handle_PACKET(n2n_edge_t * eee, - const n2n_common_t * cmn, + const uint8_t from_supernode, const n2n_PACKET_t * pkt, const n2n_sock_t * orig_sender, uint8_t * payload, size_t psize) { ssize_t data_sent_len; - uint8_t from_supernode; uint8_t * eth_payload=NULL; int retval = -1; time_t now; @@ -997,8 +1011,6 @@ static int handle_PACKET(n2n_edge_t * eee, (unsigned int)psize, (unsigned int)pkt->transform); /* hexdump(payload, psize); */ - from_supernode= cmn->flags & N2N_FLAGS_FROM_SUPERNODE; - if(from_supernode) { if(!memcmp(pkt->dstMac, broadcast_mac, N2N_MAC_SIZE)) @@ -1013,9 +1025,6 @@ static int handle_PACKET(n2n_edge_t * eee, eee->last_p2p=now; } - /* Update the sender in peer table entry */ - check_peer_registration_needed(eee, from_supernode, pkt->srcMac, orig_sender); - /* Handle transform. */ { uint8_t decodebuf[N2N_PKT_BUF_SIZE]; @@ -1134,185 +1143,223 @@ static int handle_PACKET(n2n_edge_t * eee, /* ************************************** */ + +#ifndef WIN32 + +static char *get_ip_from_arp(dec_ip_str_t buf, const n2n_mac_t req_mac) { + FILE *fd; + dec_ip_str_t ip_str = {'\0'}; + char dev_str[N2N_IFNAMSIZ] = {'\0'}; + macstr_t mac_str = {'\0'}; + n2n_mac_t mac = {'\0'}; + + strncpy(buf, "0.0.0.0", N2N_NETMASK_STR_SIZE - 1); + + if (0 == memcmp(null_mac, req_mac, sizeof(n2n_mac_t))){ + traceEvent(TRACE_DEBUG, "MAC address is null."); + return buf; + } + + if (!(fd = fopen("/proc/net/arp", "r"))) { + traceEvent(TRACE_ERROR, "Could not open arp table. [%d]: %s", errno, strerror(errno)); + return buf; + } + + while (!feof(fd) && fgetc(fd) != '\n'); + while (!feof(fd) && (fscanf(fd, " %15[0-9.] %*s %*s %17[A-Fa-f0-9:] %*s %15s", ip_str, mac_str, dev_str) == 3)) { + str2mac(mac, mac_str); + if (0 == memcmp(mac, req_mac, sizeof(n2n_mac_t))) { + strncpy(buf, ip_str, N2N_NETMASK_STR_SIZE - 1); + break; + } + } + fclose(fd); + return buf; +} + +#endif + + /** Read a datagram from the management UDP socket and take appropriate * action. */ -static void readFromMgmtSocket(n2n_edge_t * eee, int * keep_running) { - uint8_t udp_buf[N2N_PKT_BUF_SIZE]; /* Compete UDP packet */ - ssize_t recvlen; - /* ssize_t sendlen; */ - struct sockaddr_in sender_sock; - socklen_t i; - size_t msg_len; - time_t now; - n2n_sock_str_t sockbuf; - macstr_t mac_buf; - struct peer_info *peer, *tmpPeer; - dec_ip_bit_str_t ip_bit_str = {'\0'}; - uint32_t num = 0; - - now = time(NULL); - i = sizeof(sender_sock); - recvlen = recvfrom(eee->udp_mgmt_sock, udp_buf, N2N_PKT_BUF_SIZE, 0/*flags*/, - (struct sockaddr *)&sender_sock, (socklen_t*)&i); - - if(recvlen < 0) - { - traceEvent(TRACE_ERROR, "mgmt recvfrom failed with %s", strerror(errno)); - - return; /* failed to receive data from UDP */ - } - - if(recvlen >= 4) - { - if(0 == memcmp(udp_buf, "stop", 4)) - { - traceEvent(TRACE_ERROR, "stop command received."); - *keep_running = 0; - return; - } - - if(0 == memcmp(udp_buf, "help", 4)) - { - msg_len=0; - setTraceLevel(getTraceLevel()+1); - - msg_len += snprintf((char *)(udp_buf+msg_len), (N2N_PKT_BUF_SIZE-msg_len), - "Help for edge management console:\n" - " stop Gracefully exit edge\n" - " help This help message\n" - " +verb Increase verbosity of logging\n" - " -verb Decrease verbosity of logging\n" - " Display statistics\n\n"); - - sendto(eee->udp_mgmt_sock, udp_buf, msg_len, 0/*flags*/, - (struct sockaddr *)&sender_sock, sizeof(struct sockaddr_in)); - - return; - } - - } - - if(recvlen >= 5) - { - if(0 == memcmp(udp_buf, "+verb", 5)) - { - msg_len=0; - setTraceLevel(getTraceLevel()+1); - - traceEvent(TRACE_ERROR, "+verb traceLevel=%u", (unsigned int)getTraceLevel()); - msg_len += snprintf((char *)(udp_buf+msg_len), (N2N_PKT_BUF_SIZE-msg_len), - "> +OK traceLevel=%u\n", (unsigned int)getTraceLevel()); - - sendto(eee->udp_mgmt_sock, udp_buf, msg_len, 0/*flags*/, - (struct sockaddr *)&sender_sock, sizeof(struct sockaddr_in)); - - return; - } - - if(0 == memcmp(udp_buf, "-verb", 5)) - { - msg_len=0; - - if(getTraceLevel() > 0) - { - setTraceLevel(getTraceLevel()-1); - msg_len += snprintf((char *)(udp_buf+msg_len), (N2N_PKT_BUF_SIZE-msg_len), - "> -OK traceLevel=%u\n", getTraceLevel()); - } - else - { - msg_len += snprintf((char *)(udp_buf+msg_len), (N2N_PKT_BUF_SIZE-msg_len), - "> -NOK traceLevel=%u\n", getTraceLevel()); - } - - traceEvent(TRACE_ERROR, "-verb traceLevel=%u", (unsigned int)getTraceLevel()); - - sendto(eee->udp_mgmt_sock, udp_buf, msg_len, 0/*flags*/, - (struct sockaddr *)&sender_sock, sizeof(struct sockaddr_in)); - return; - } - } - - traceEvent(TRACE_DEBUG, "mgmt status rq"); - - msg_len=0; - msg_len += snprintf((char*)&udp_buf[msg_len], (N2N_PKT_BUF_SIZE-msg_len), - "STATISTICS FOR EDGE\n"); - msg_len += snprintf((char*)&udp_buf[msg_len], N2N_SN_PKTBUF_SIZE - msg_len, - "community: %s\n", eee->conf.community_name); - - msg_len += snprintf((char*)&udp_buf[msg_len], N2N_SN_PKTBUF_SIZE - msg_len, - "\tid tun_tap MAC edge last_seen\n"); - msg_len += snprintf((char*)&udp_buf[msg_len], N2N_SN_PKTBUF_SIZE - msg_len, - "--- pending peers -------------------------------------------------------------------\n"); - - sendto(eee->udp_mgmt_sock, udp_buf, msg_len, 0/*flags*/, - (struct sockaddr *)&sender_sock, sizeof(struct sockaddr_in)); - msg_len = 0; - - HASH_ITER(hh, eee->pending_peers, peer, tmpPeer) { - msg_len += snprintf((char*)&udp_buf[msg_len], N2N_SN_PKTBUF_SIZE - msg_len, - "\t%-4u %-18s %-17s %-21s %lu\n", - ++num, ip_subnet_to_str(ip_bit_str, &peer->dev_addr), - macaddr_str(mac_buf, peer->mac_addr), - sock_to_cstr(sockbuf, &(peer->sock)), now - peer->last_seen); - - sendto(eee->udp_mgmt_sock, udp_buf, msg_len, 0/*flags*/, - (struct sockaddr *)&sender_sock, sizeof(struct sockaddr_in)); - msg_len = 0; - } - - msg_len += snprintf((char*)&udp_buf[msg_len], N2N_SN_PKTBUF_SIZE - msg_len, - "--- known peers ---------------------------------------------------------------------\n"); - - HASH_ITER(hh, eee->known_peers, peer, tmpPeer) { - msg_len += snprintf((char*)&udp_buf[msg_len], N2N_SN_PKTBUF_SIZE - msg_len, - "\t%-4u %-18s %-17s %-21s %lu\n", - ++num, ip_subnet_to_str(ip_bit_str, &peer->dev_addr), - macaddr_str(mac_buf, peer->mac_addr), - sock_to_cstr(sockbuf, &(peer->sock)), now - peer->last_seen); - - sendto(eee->udp_mgmt_sock, udp_buf, msg_len, 0/*flags*/, - (struct sockaddr *)&sender_sock, sizeof(struct sockaddr_in)); - msg_len = 0; - } - - msg_len += snprintf((char*)&udp_buf[msg_len], N2N_SN_PKTBUF_SIZE - msg_len, - "-------------------------------------------------------------------------------------\n"); - - msg_len += snprintf((char *)(udp_buf+msg_len), (N2N_PKT_BUF_SIZE-msg_len), - "uptime %lu\n", - time(NULL) - eee->start_time); - - msg_len += snprintf((char *)(udp_buf+msg_len), (N2N_PKT_BUF_SIZE-msg_len), - "paths super:%u,%u p2p:%u,%u\n", - (unsigned int)eee->stats.tx_sup, - (unsigned int)eee->stats.rx_sup, - (unsigned int)eee->stats.tx_p2p, - (unsigned int)eee->stats.rx_p2p); - - msg_len += snprintf((char *)(udp_buf+msg_len), (N2N_PKT_BUF_SIZE-msg_len), - "transop |%6u|%6u|\n", - (unsigned int)eee->transop.tx_cnt, - (unsigned int)eee->transop.rx_cnt); - - msg_len += snprintf((char *)(udp_buf+msg_len), (N2N_PKT_BUF_SIZE-msg_len), - "peers pend:%u full:%u\n", - HASH_COUNT(eee->pending_peers), - HASH_COUNT(eee->known_peers)); - - msg_len += snprintf((char *)(udp_buf+msg_len), (N2N_PKT_BUF_SIZE-msg_len), - "last super:%lu(%ld sec ago) p2p:%lu(%ld sec ago)\n", - eee->last_sup, (now-eee->last_sup), eee->last_p2p, - (now-eee->last_p2p)); - - traceEvent(TRACE_DEBUG, "mgmt status sending: %s", udp_buf); +static void readFromMgmtSocket(n2n_edge_t *eee, int *keep_running) { + char udp_buf[N2N_PKT_BUF_SIZE]; /* Compete UDP packet */ + ssize_t recvlen; + /* ssize_t sendlen; */ + struct sockaddr_in sender_sock; + socklen_t i; + size_t msg_len; + time_t now; + struct peer_info *peer, *tmpPeer; + macstr_t mac_buf; + /* dec_ip_bit_str_t ip_bit_str = {'\0'}; */ + /* dec_ip_str_t ip_str = {'\0'}; */ + in_addr_t net; + n2n_sock_str_t sockbuf; + uint32_t num_pending_peers = 0; + uint32_t num_known_peers = 0; + uint32_t num = 0; - /* sendlen = */ sendto(eee->udp_mgmt_sock, udp_buf, msg_len, 0/*flags*/, - (struct sockaddr *)&sender_sock, sizeof(struct sockaddr_in)); + now = time(NULL); + i = sizeof(sender_sock); + recvlen = recvfrom(eee->udp_mgmt_sock, udp_buf, N2N_PKT_BUF_SIZE, 0/*flags*/, + (struct sockaddr *) &sender_sock, (socklen_t *) &i); + + if (recvlen < 0) { + traceEvent(TRACE_ERROR, "mgmt recvfrom failed with %s", strerror(errno)); + return; /* failed to receive data from UDP */ + } + + if ((0 == memcmp(udp_buf, "help", 4)) || (0 == memcmp(udp_buf, "?", 1))) { + msg_len = 0; + + msg_len += snprintf((char *) (udp_buf + msg_len), (N2N_PKT_BUF_SIZE - msg_len), + "Help for edge management console:\n" + "\tstop | Gracefully exit edge\n" + "\thelp | This help message\n" + "\t+verb | Increase verbosity of logging\n" + "\t-verb | Decrease verbosity of logging\n" + "\t | Display statistics\n\n"); + + sendto(eee->udp_mgmt_sock, udp_buf, msg_len, 0/*flags*/, + (struct sockaddr *) &sender_sock, sizeof(struct sockaddr_in)); + + return; + } + + if (0 == memcmp(udp_buf, "stop", 4)) { + traceEvent(TRACE_ERROR, "stop command received."); + *keep_running = 0; + return; + } + + if (0 == memcmp(udp_buf, "+verb", 5)) { + msg_len = 0; + setTraceLevel(getTraceLevel() + 1); + + traceEvent(TRACE_ERROR, "+verb traceLevel=%u", (unsigned int) getTraceLevel()); + msg_len += snprintf((char *) (udp_buf + msg_len), (N2N_PKT_BUF_SIZE - msg_len), + "> +OK traceLevel=%u\n", (unsigned int) getTraceLevel()); + + sendto(eee->udp_mgmt_sock, udp_buf, msg_len, 0/*flags*/, + (struct sockaddr *) &sender_sock, sizeof(struct sockaddr_in)); + + return; + } + + if (0 == memcmp(udp_buf, "-verb", 5)) { + msg_len = 0; + + if (getTraceLevel() > 0) { + setTraceLevel(getTraceLevel() - 1); + msg_len += snprintf((char *) (udp_buf + msg_len), (N2N_PKT_BUF_SIZE - msg_len), + "> -OK traceLevel=%u\n", getTraceLevel()); + } else { + msg_len += snprintf((char *) (udp_buf + msg_len), (N2N_PKT_BUF_SIZE - msg_len), + "> -NOK traceLevel=%u\n", getTraceLevel()); + } + + traceEvent(TRACE_ERROR, "-verb traceLevel=%u", (unsigned int) getTraceLevel()); + + sendto(eee->udp_mgmt_sock, udp_buf, msg_len, 0/*flags*/, + (struct sockaddr *) &sender_sock, sizeof(struct sockaddr_in)); + return; + } + + traceEvent(TRACE_DEBUG, "mgmt status rq"); + + msg_len = 0; + msg_len += snprintf((char *) (udp_buf + msg_len), (N2N_PKT_BUF_SIZE - msg_len), + "community: %s\n", + eee->conf.community_name); + msg_len += snprintf((char *) (udp_buf + msg_len), (N2N_PKT_BUF_SIZE - msg_len), + " id tun_tap MAC edge last_seen\n"); + msg_len += snprintf((char *) (udp_buf + msg_len), (N2N_PKT_BUF_SIZE - msg_len), + "------------------------------------------------------------------------------\n"); + + msg_len += snprintf((char *) (udp_buf + msg_len), (N2N_PKT_BUF_SIZE - msg_len), + "supernode_forward:\n"); + num = 0; + HASH_ITER(hh, eee->pending_peers, peer, tmpPeer) { + ++num_pending_peers; + if(peer->dev_addr.net_addr == 0) continue; + net = htonl(peer->dev_addr.net_addr); + msg_len += snprintf((char *) (udp_buf + msg_len), (N2N_PKT_BUF_SIZE - msg_len), + " %-4u %-15s %-17s %-21s %lu\n", + ++num, inet_ntoa(*(struct in_addr *) &net), + macaddr_str(mac_buf, peer->mac_addr), + sock_to_cstr(sockbuf, &(peer->sock)), now - peer->last_seen); + + sendto(eee->udp_mgmt_sock, udp_buf, msg_len, 0/*flags*/, + (struct sockaddr *) &sender_sock, sizeof(struct sockaddr_in)); + msg_len = 0; + } + + msg_len += snprintf((char *) (udp_buf + msg_len), (N2N_PKT_BUF_SIZE - msg_len), + "peer_to_peer:\n"); + num = 0; + HASH_ITER(hh, eee->known_peers, peer, tmpPeer) { + ++num_known_peers; + if(peer->dev_addr.net_addr == 0) continue; + net = htonl(peer->dev_addr.net_addr); + msg_len += snprintf((char *) (udp_buf + msg_len), (N2N_PKT_BUF_SIZE - msg_len), + " %-4u %-15s %-17s %-21s %lu\n", + ++num, inet_ntoa(*(struct in_addr *) &net), + macaddr_str(mac_buf, peer->mac_addr), + sock_to_cstr(sockbuf, &(peer->sock)), now - peer->last_seen); + + sendto(eee->udp_mgmt_sock, udp_buf, msg_len, 0/*flags*/, + (struct sockaddr *) &sender_sock, sizeof(struct sockaddr_in)); + msg_len = 0; + } + + msg_len += snprintf((char *) (udp_buf + msg_len), (N2N_PKT_BUF_SIZE - msg_len), + "------------------------------------------------------------------------------\n"); + + msg_len += snprintf((char *) (udp_buf + msg_len), (N2N_PKT_BUF_SIZE - msg_len), + "uptime %lu | ", + time(NULL) - eee->start_time); + + msg_len += snprintf((char *) (udp_buf + msg_len), (N2N_PKT_BUF_SIZE - msg_len), + "pend_peers %u | ", + num_pending_peers); + + msg_len += snprintf((char *) (udp_buf + msg_len), (N2N_PKT_BUF_SIZE - msg_len), + "known_peers %u | ", + num_known_peers); + + msg_len += snprintf((char *) (udp_buf + msg_len), (N2N_PKT_BUF_SIZE - msg_len), + "transop %u,%u\n", + (unsigned int) eee->transop.tx_cnt, + (unsigned int) eee->transop.rx_cnt); + + msg_len += snprintf((char *) (udp_buf + msg_len), (N2N_PKT_BUF_SIZE - msg_len), + "super %u,%u | ", + (unsigned int) eee->stats.tx_sup, + (unsigned int) eee->stats.rx_sup); + + msg_len += snprintf((char *) (udp_buf + msg_len), (N2N_PKT_BUF_SIZE - msg_len), + "p2p %u,%u\n", + (unsigned int) eee->stats.tx_p2p, + (unsigned int) eee->stats.rx_p2p); + + msg_len += snprintf((char *) (udp_buf + msg_len), (N2N_PKT_BUF_SIZE - msg_len), + "last_super %ld sec ago | ", + (now - eee->last_sup)); + + msg_len += snprintf((char *) (udp_buf + msg_len), (N2N_PKT_BUF_SIZE - msg_len), + "last_p2p %ld sec ago\n", + (now - eee->last_p2p)); + + msg_len += snprintf((char *) (udp_buf + msg_len), (N2N_PKT_BUF_SIZE - msg_len), + "\nType \"help\" to see more commands.\n\n"); + + /* sendlen = */ sendto(eee->udp_mgmt_sock, udp_buf, msg_len, 0/*flags*/, + (struct sockaddr *) &sender_sock, sizeof(struct sockaddr_in)); } + /* ************************************** */ static int check_query_peer_info(n2n_edge_t *eee, time_t now, n2n_mac_t mac) { @@ -1324,14 +1371,15 @@ static int check_query_peer_info(n2n_edge_t *eee, time_t now, n2n_mac_t mac) { 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 */ + scan->timeout = eee->conf.register_interval; /* TODO: should correspond to the peer supernode registration timeout */ scan->last_seen = now; /* Don't change this it marks the pending peer for removal. */ scan->last_valid_time_stamp = initial_time_stamp (); HASH_ADD_PEER(eee->pending_peers, scan); } - if(now - scan->last_sent_query > REGISTER_SUPER_INTERVAL_DFL) { + if(now - scan->last_sent_query > eee->conf.register_interval) { + send_register(eee, &(eee->supernode), mac); send_query_peer(eee, scan->mac_addr); scan->last_sent_query = now; return(0); @@ -1748,7 +1796,10 @@ void readFromIPSocket(n2n_edge_t * eee, int in_sock) { sock_to_cstr(sockbuf2, orig_sender), sock_to_cstr(sockbuf1, &sender), recvlen); } - handle_PACKET(eee, &cmn, &pkt, orig_sender, udp_buf+idx, recvlen-idx); + /* Update the sender in peer table entry */ + check_peer_registration_needed(eee, from_supernode, pkt.srcMac, NULL, orig_sender); + + handle_PACKET(eee, from_supernode, &pkt, orig_sender, udp_buf+idx, recvlen-idx); break; } case MSG_TYPE_REGISTER: @@ -1800,7 +1851,7 @@ void readFromIPSocket(n2n_edge_t * eee, int in_sock) { sock_to_cstr(sockbuf1, &sender), sock_to_cstr(sockbuf2, orig_sender)); } - check_peer_registration_needed(eee, from_supernode, reg.srcMac, orig_sender); + check_peer_registration_needed(eee, from_supernode, reg.srcMac, ®.dev_addr, orig_sender); break; } case MSG_TYPE_REGISTER_ACK: diff --git a/src/sn_utils.c b/src/sn_utils.c index 08be497..ade2892 100644 --- a/src/sn_utils.c +++ b/src/sn_utils.c @@ -474,9 +474,9 @@ static int process_mgmt(n2n_sn_t *sss, traceEvent(TRACE_DEBUG, "process_mgmt"); ressize += snprintf(resbuf + ressize, N2N_SN_PKTBUF_SIZE - ressize, - "\tid tun_tap MAC edge last_seen\n"); + " id tun_tap MAC edge last_seen\n"); ressize += snprintf(resbuf + ressize, N2N_SN_PKTBUF_SIZE - ressize, - "-------------------------------------------------------------------------------------\n"); + "---------------------------------------------------------------------------------\n"); HASH_ITER(hh, sss->communities, community, tmp) { num_edges += HASH_COUNT(community->edges); ressize += snprintf(resbuf + ressize, N2N_SN_PKTBUF_SIZE - ressize, @@ -487,7 +487,7 @@ static int process_mgmt(n2n_sn_t *sss, num = 0; HASH_ITER(hh, community->edges, peer, tmpPeer) { ressize += snprintf(resbuf + ressize, N2N_SN_PKTBUF_SIZE - ressize, - "\t%-4u %-18s %-17s %-21s %lu\n", + " %-4u %-18s %-17s %-21s %lu\n", ++num, ip_subnet_to_str(ip_bit_str, &peer->dev_addr), macaddr_str(mac_buf, peer->mac_addr), sock_to_cstr(sockbuf, &(peer->sock)), now - peer->last_seen); @@ -497,7 +497,7 @@ static int process_mgmt(n2n_sn_t *sss, } } ressize += snprintf(resbuf + ressize, N2N_SN_PKTBUF_SIZE - ressize, - "-------------------------------------------------------------------------------------\n"); + "---------------------------------------------------------------------------------\n"); ressize += snprintf(resbuf + ressize, N2N_SN_PKTBUF_SIZE - ressize, "uptime %lu | ", (now - sss->start_time)); @@ -530,7 +530,7 @@ static int process_mgmt(n2n_sn_t *sss, "cur_cmnts %u\n", HASH_COUNT(sss->communities)); ressize += snprintf(resbuf + ressize, N2N_SN_PKTBUF_SIZE - ressize, - "last fwd %lu sec ago\n", + "last_fwd %lu sec ago | ", (long unsigned int) (now - sss->stats.last_fwd)); ressize += snprintf(resbuf + ressize, N2N_SN_PKTBUF_SIZE - ressize, @@ -811,10 +811,10 @@ static int process_udp(n2n_sn_t * sss, reg.sock.port = ntohs(sender_sock->sin_port); memcpy(reg.sock.addr.v4, &(sender_sock->sin_addr.s_addr), IPV4_SIZE); - rec_buf = encbuf; + /* Re-encode the header. */ + encode_REGISTER(encbuf, &encx, &cmn2, ®); - /* Re-encode the header. */ - encode_REGISTER(encbuf, &encx, &cmn2, ®); + rec_buf = encbuf; } else { /* Already from a supernode. Nothing to modify, just pass to * destination. */ diff --git a/src/wire.c b/src/wire.c index 66bb771..e80054b 100644 --- a/src/wire.c +++ b/src/wire.c @@ -251,42 +251,44 @@ int decode_sock( n2n_sock_t * sock, return (idx-idx0); } -int encode_REGISTER( uint8_t * base, - size_t * idx, - const n2n_common_t * common, - const n2n_REGISTER_t * reg ) -{ - int retval=0; - retval += encode_common( base, idx, common ); - retval += encode_buf( base, idx, reg->cookie, N2N_COOKIE_SIZE ); - retval += encode_mac( base, idx, reg->srcMac ); - retval += encode_mac( base, idx, reg->dstMac ); - if ( 0 != reg->sock.family ) - { - retval += encode_sock( base, idx, &(reg->sock) ); - } - return retval; +int encode_REGISTER(uint8_t *base, + size_t *idx, + const n2n_common_t *common, + const n2n_REGISTER_t *reg) { + int retval = 0; + retval += encode_common(base, idx, common); + retval += encode_buf(base, idx, reg->cookie, N2N_COOKIE_SIZE); + retval += encode_mac(base, idx, reg->srcMac); + retval += encode_mac(base, idx, reg->dstMac); + if (0 != reg->sock.family) { + retval += encode_sock(base, idx, &(reg->sock)); + } + retval += encode_uint32(base, idx, reg->dev_addr.net_addr); + retval += encode_uint8(base, idx, reg->dev_addr.net_bitlen); + + return retval; } -int decode_REGISTER( n2n_REGISTER_t * reg, - 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( reg, 0, sizeof(n2n_REGISTER_t) ); - retval += decode_buf( reg->cookie, N2N_COOKIE_SIZE, base, rem, idx ); - retval += decode_mac( reg->srcMac, base, rem, idx ); - retval += decode_mac( reg->dstMac, base, rem, idx ); - if ( cmn->flags & N2N_FLAGS_SOCKET ) - { - retval += decode_sock( &(reg->sock), base, rem, idx ); - } +int decode_REGISTER(n2n_REGISTER_t *reg, + 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(reg, 0, sizeof(n2n_REGISTER_t)); + retval += decode_buf(reg->cookie, N2N_COOKIE_SIZE, base, rem, idx); + retval += decode_mac(reg->srcMac, base, rem, idx); + retval += decode_mac(reg->dstMac, base, rem, idx); - return retval; + if (cmn->flags & N2N_FLAGS_SOCKET) { + retval += decode_sock(&(reg->sock), base, rem, idx); + } + retval += decode_uint32(&(reg->dev_addr.net_addr), base, rem, idx); + retval += decode_uint8(&(reg->dev_addr.net_bitlen), base, rem, idx); + + return retval; }