From b8b2183060fe0cc2af9bdd8fcae1d092dc6ae092 Mon Sep 17 00:00:00 2001 From: Hamish Coleman Date: Sat, 19 Oct 2024 12:26:11 +1100 Subject: [PATCH 01/12] Make processing flow easier to comprehend with reordering --- src/edge_utils.c | 779 ++++++++++++++++++++++++----------------------- 1 file changed, 395 insertions(+), 384 deletions(-) diff --git a/src/edge_utils.c b/src/edge_utils.c index 122d02f..ef7b944 100644 --- a/src/edge_utils.c +++ b/src/edge_utils.c @@ -2383,473 +2383,484 @@ void process_udp (struct n3n_runtime_data *eee, const struct sockaddr *sender_so } } - if(0 == memcmp(cmn.community, eee->conf.community_name, N2N_COMMUNITY_SIZE)) { - switch(msg_type) { - case MSG_TYPE_PACKET: { - /* process PACKET - most frequent so first in list. */ - n2n_PACKET_t pkt; - - decode_PACKET(&pkt, &cmn, udp_buf, &rem, &idx); - - if(eee->conf.header_encryption == HEADER_ENCRYPTION_ENABLED) { - if(!find_peer_time_stamp_and_verify( - eee->pending_peers, - eee->known_peers, - sn, - pkt.srcMac, - stamp, - TIME_STAMP_ALLOW_JITTER)) { - traceEvent(TRACE_DEBUG, "dropped PACKET due to time stamp error"); - return; - } - } + if(0 != memcmp(cmn.community, eee->conf.community_name, N2N_COMMUNITY_SIZE)) { + // The community in the packet is not matching ours - if(!eee->last_sup) { - // drop packets received before first registration with supernode - traceEvent(TRACE_DEBUG, "dropped PACKET recevied before first registration with supernode"); - return; - } + if(from_supernode) { + traceEvent(TRACE_INFO, "received packet with unknown community"); + // TODO: + // stats.errors.community.supernode ++; + } else { + traceEvent(TRACE_INFO, "ignoring packet with unknown community"); + // TODO: + // stats.errors.community.other ++; + } - if(!from_supernode) { - /* This is a P2P packet from the peer. We purge a pending - * registration towards the possibly nat-ted peer address as we now have - * a valid channel. We still use check_peer_registration_needed in - * handle_PACKET to double check this. - */ - traceEvent(TRACE_DEBUG, "[p2p] from %s", - macaddr_str(mac_buf1, pkt.srcMac)); - find_and_remove_peer(&eee->pending_peers, pkt.srcMac); - } else { - /* [PsP] : edge Peer->Supernode->edge Peer */ + return; + } - if(is_valid_peer_sock(&pkt.sock)) - orig_sender = &(pkt.sock); + switch(msg_type) { + case MSG_TYPE_PACKET: { + /* process PACKET - most frequent so first in list. */ + n2n_PACKET_t pkt; - traceEvent(TRACE_DEBUG, "[pSp] from %s via [%s]", - macaddr_str(mac_buf1, pkt.srcMac), - sock_to_cstr(sockbuf1, &sender)); - } + decode_PACKET(&pkt, &cmn, udp_buf, &rem, &idx); - /* Update the sender in peer table entry */ - check_peer_registration_needed(eee, from_supernode, via_multicast, - pkt.srcMac, - // REVISIT: also consider PORT_REG_COOKIEs when implemented - from_supernode ? N2N_FORWARDED_REG_COOKIE : N2N_REGULAR_REG_COOKIE, - NULL, NULL, orig_sender); + if(eee->conf.header_encryption == HEADER_ENCRYPTION_ENABLED) { + if(!find_peer_time_stamp_and_verify( + eee->pending_peers, + eee->known_peers, + sn, + pkt.srcMac, + stamp, + TIME_STAMP_ALLOW_JITTER)) { + traceEvent(TRACE_DEBUG, "dropped PACKET due to time stamp error"); + return; + } + } - handle_PACKET(eee, from_supernode, &pkt, orig_sender, udp_buf + idx, udp_size - idx); - break; + if(!eee->last_sup) { + // drop packets received before first registration with supernode + traceEvent(TRACE_DEBUG, "dropped PACKET recevied before first registration with supernode"); + return; } - case MSG_TYPE_REGISTER: { - /* Another edge is registering with us */ - n2n_REGISTER_t reg; + if(!from_supernode) { + /* This is a P2P packet from the peer. We purge a pending + * registration towards the possibly nat-ted peer address as we now have + * a valid channel. We still use check_peer_registration_needed in + * handle_PACKET to double check this. + */ + traceEvent(TRACE_DEBUG, "[p2p] from %s", + macaddr_str(mac_buf1, pkt.srcMac)); + find_and_remove_peer(&eee->pending_peers, pkt.srcMac); + } else { + /* [PsP] : edge Peer->Supernode->edge Peer */ - decode_REGISTER(®, &cmn, udp_buf, &rem, &idx); + if(is_valid_peer_sock(&pkt.sock)) + orig_sender = &(pkt.sock); - via_multicast &= is_null_mac(reg.dstMac); + traceEvent(TRACE_DEBUG, "[pSp] from %s via [%s]", + macaddr_str(mac_buf1, pkt.srcMac), + sock_to_cstr(sockbuf1, &sender)); + } - if(eee->conf.header_encryption == HEADER_ENCRYPTION_ENABLED) { - if(!find_peer_time_stamp_and_verify( - eee->pending_peers, - eee->known_peers, - sn, - reg.srcMac, - stamp, - via_multicast ? TIME_STAMP_ALLOW_JITTER : TIME_STAMP_NO_JITTER)) { - traceEvent(TRACE_DEBUG, "dropped REGISTER due to time stamp error"); - return; - } - } + /* Update the sender in peer table entry */ + check_peer_registration_needed(eee, from_supernode, via_multicast, + pkt.srcMac, + // REVISIT: also consider PORT_REG_COOKIEs when implemented + from_supernode ? N2N_FORWARDED_REG_COOKIE : N2N_REGULAR_REG_COOKIE, + NULL, NULL, orig_sender); - if(is_valid_peer_sock(®.sock)) - orig_sender = &(reg.sock); + handle_PACKET(eee, from_supernode, &pkt, orig_sender, udp_buf + idx, udp_size - idx); + break; + } - if(via_multicast && !memcmp(reg.srcMac, eee->device.mac_addr, N2N_MAC_SIZE)) { - traceEvent(TRACE_DEBUG, "skipping REGISTER from self"); - break; - } + case MSG_TYPE_REGISTER: { + /* Another edge is registering with us */ + n2n_REGISTER_t reg; - if(!via_multicast && memcmp(reg.dstMac, eee->device.mac_addr, N2N_MAC_SIZE)) { - traceEvent(TRACE_DEBUG, "skipping REGISTER for other peer"); - break; - } + decode_REGISTER(®, &cmn, udp_buf, &rem, &idx); - if(!from_supernode) { - /* This is a P2P registration from the peer. We purge a pending - * registration towards the possibly nat-ted peer address as we now have - * a valid channel. We still use check_peer_registration_needed below - * to double check this. - */ - traceEvent(TRACE_INFO, "[p2p] Rx REGISTER from %s [%s]%s", - macaddr_str(mac_buf1, reg.srcMac), - sock_to_cstr(sockbuf1, &sender), - (reg.cookie & N2N_LOCAL_REG_COOKIE) ? " (local)" : ""); - find_and_remove_peer(&eee->pending_peers, reg.srcMac); - - /* NOTE: only ACK to peers */ - send_register_ack(eee, orig_sender, ®); - } else { - traceEvent(TRACE_INFO, "[pSp] Rx REGISTER from %s [%s] to %s via [%s]", - macaddr_str(mac_buf1, reg.srcMac), sock_to_cstr(sockbuf2, orig_sender), - macaddr_str(mac_buf2, reg.dstMac), sock_to_cstr(sockbuf1, &sender)); + via_multicast &= is_null_mac(reg.dstMac); + + if(eee->conf.header_encryption == HEADER_ENCRYPTION_ENABLED) { + if(!find_peer_time_stamp_and_verify( + eee->pending_peers, + eee->known_peers, + sn, + reg.srcMac, + stamp, + via_multicast ? TIME_STAMP_ALLOW_JITTER : TIME_STAMP_NO_JITTER)) { + traceEvent(TRACE_DEBUG, "dropped REGISTER due to time stamp error"); + return; } + } + + if(is_valid_peer_sock(®.sock)) + orig_sender = &(reg.sock); - check_peer_registration_needed(eee, from_supernode, via_multicast, - reg.srcMac, reg.cookie, ®.dev_addr, (const n2n_desc_t*)®.dev_desc, orig_sender); + if(via_multicast && !memcmp(reg.srcMac, eee->device.mac_addr, N2N_MAC_SIZE)) { + traceEvent(TRACE_DEBUG, "skipping REGISTER from self"); break; } - case MSG_TYPE_REGISTER_ACK: { - /* Peer edge is acknowledging our register request */ - n2n_REGISTER_ACK_t ra; - - decode_REGISTER_ACK(&ra, &cmn, udp_buf, &rem, &idx); - - if(eee->conf.header_encryption == HEADER_ENCRYPTION_ENABLED) { - if(!find_peer_time_stamp_and_verify( - eee->pending_peers, - eee->known_peers, - sn, - ra.srcMac, - stamp, - TIME_STAMP_NO_JITTER)) { - traceEvent(TRACE_DEBUG, "dropped REGISTER_ACK due to time stamp error"); - return; - } - } - - if(is_valid_peer_sock(&ra.sock)) - orig_sender = &(ra.sock); + if(!via_multicast && memcmp(reg.dstMac, eee->device.mac_addr, N2N_MAC_SIZE)) { + traceEvent(TRACE_DEBUG, "skipping REGISTER for other peer"); + break; + } - traceEvent(TRACE_INFO, "Rx REGISTER_ACK from %s [%s] to %s via [%s]%s", - macaddr_str(mac_buf1, ra.srcMac), - sock_to_cstr(sockbuf2, orig_sender), - macaddr_str(mac_buf2, ra.dstMac), + if(!from_supernode) { + /* This is a P2P registration from the peer. We purge a pending + * registration towards the possibly nat-ted peer address as we now have + * a valid channel. We still use check_peer_registration_needed below + * to double check this. + */ + traceEvent(TRACE_INFO, "[p2p] Rx REGISTER from %s [%s]%s", + macaddr_str(mac_buf1, reg.srcMac), sock_to_cstr(sockbuf1, &sender), - (ra.cookie & N2N_LOCAL_REG_COOKIE) ? " (local)" : ""); + (reg.cookie & N2N_LOCAL_REG_COOKIE) ? " (local)" : ""); + find_and_remove_peer(&eee->pending_peers, reg.srcMac); - peer_set_p2p_confirmed(eee, ra.srcMac, - ra.cookie, - &sender, now); - break; + /* NOTE: only ACK to peers */ + send_register_ack(eee, orig_sender, ®); + } else { + traceEvent(TRACE_INFO, "[pSp] Rx REGISTER from %s [%s] to %s via [%s]", + macaddr_str(mac_buf1, reg.srcMac), sock_to_cstr(sockbuf2, orig_sender), + macaddr_str(mac_buf2, reg.dstMac), sock_to_cstr(sockbuf1, &sender)); } - case MSG_TYPE_REGISTER_SUPER_ACK: { - n2n_REGISTER_SUPER_ACK_t ra; - uint8_t tmpbuf[REG_SUPER_ACK_PAYLOAD_SPACE]; - int i; - int skip_add; + check_peer_registration_needed(eee, from_supernode, via_multicast, + reg.srcMac, reg.cookie, ®.dev_addr, (const n2n_desc_t*)®.dev_desc, orig_sender); + break; + } - if(!(eee->sn_wait)) { - traceEvent(TRACE_DEBUG, "Rx REGISTER_SUPER_ACK with no outstanding REGISTER_SUPER"); + case MSG_TYPE_REGISTER_ACK: { + /* Peer edge is acknowledging our register request */ + n2n_REGISTER_ACK_t ra; + + decode_REGISTER_ACK(&ra, &cmn, udp_buf, &rem, &idx); + + if(eee->conf.header_encryption == HEADER_ENCRYPTION_ENABLED) { + if(!find_peer_time_stamp_and_verify( + eee->pending_peers, + eee->known_peers, + sn, + ra.srcMac, + stamp, + TIME_STAMP_NO_JITTER)) { + traceEvent(TRACE_DEBUG, "dropped REGISTER_ACK due to time stamp error"); return; } + } - // FIXME: fix decode_* functions to not need memsets - memset(&ra, 0, sizeof(ra)); - decode_REGISTER_SUPER_ACK(&ra, &cmn, udp_buf, &rem, &idx, tmpbuf); - - if(eee->conf.header_encryption == HEADER_ENCRYPTION_ENABLED) { - if(!find_peer_time_stamp_and_verify( - eee->pending_peers, - eee->known_peers, - sn, - ra.srcMac, - stamp, - TIME_STAMP_NO_JITTER)) { - traceEvent(TRACE_DEBUG, "dropped REGISTER_SUPER_ACK due to time stamp error"); - return; - } - } + if(is_valid_peer_sock(&ra.sock)) + orig_sender = &(ra.sock); - // hash check (user/pw auth only) - if(eee->conf.shared_secret) { - speck_128_encrypt(hash_buf, (speck_context_t*)eee->conf.shared_secret_ctx); - if(memcmp(hash_buf, udp_buf + udp_size - N2N_REG_SUP_HASH_CHECK_LEN /* length is has already been checked */, N2N_REG_SUP_HASH_CHECK_LEN)) { - traceEvent(TRACE_INFO, "Rx REGISTER_SUPER_ACK with wrong hash"); - return; - } - } + traceEvent(TRACE_INFO, "Rx REGISTER_ACK from %s [%s] to %s via [%s]%s", + macaddr_str(mac_buf1, ra.srcMac), + sock_to_cstr(sockbuf2, orig_sender), + macaddr_str(mac_buf2, ra.dstMac), + sock_to_cstr(sockbuf1, &sender), + (ra.cookie & N2N_LOCAL_REG_COOKIE) ? " (local)" : ""); + + peer_set_p2p_confirmed(eee, ra.srcMac, + ra.cookie, + &sender, now); + break; + } - if(ra.cookie != eee->curr_sn->last_cookie) { - traceEvent(TRACE_INFO, "Rx REGISTER_SUPER_ACK with wrong or old cookie"); + case MSG_TYPE_REGISTER_SUPER_ACK: { + n2n_REGISTER_SUPER_ACK_t ra; + uint8_t tmpbuf[REG_SUPER_ACK_PAYLOAD_SPACE]; + int i; + int skip_add; + + if(!(eee->sn_wait)) { + traceEvent(TRACE_DEBUG, "Rx REGISTER_SUPER_ACK with no outstanding REGISTER_SUPER"); + return; + } + + // FIXME: fix decode_* functions to not need memsets + memset(&ra, 0, sizeof(ra)); + decode_REGISTER_SUPER_ACK(&ra, &cmn, udp_buf, &rem, &idx, tmpbuf); + + if(eee->conf.header_encryption == HEADER_ENCRYPTION_ENABLED) { + if(!find_peer_time_stamp_and_verify( + eee->pending_peers, + eee->known_peers, + sn, + ra.srcMac, + stamp, + TIME_STAMP_NO_JITTER)) { + traceEvent(TRACE_DEBUG, "dropped REGISTER_SUPER_ACK due to time stamp error"); return; } + } - if(handle_remote_auth(eee, sn, &(ra.auth))) { - traceEvent(TRACE_INFO, "Rx REGISTER_SUPER_ACK with wrong or old response to challenge"); - if(eee->conf.shared_secret) { - traceEvent(TRACE_NORMAL, "Rx REGISTER_SUPER_ACK with wrong or old response to challenge, maybe indicating wrong federation public key (-P)"); - } + // hash check (user/pw auth only) + if(eee->conf.shared_secret) { + speck_128_encrypt(hash_buf, (speck_context_t*)eee->conf.shared_secret_ctx); + if(memcmp(hash_buf, udp_buf + udp_size - N2N_REG_SUP_HASH_CHECK_LEN /* length is has already been checked */, N2N_REG_SUP_HASH_CHECK_LEN)) { + traceEvent(TRACE_INFO, "Rx REGISTER_SUPER_ACK with wrong hash"); return; } + } - if(is_valid_peer_sock(&ra.sock)) - orig_sender = &(ra.sock); - - traceEvent(TRACE_INFO, "Rx REGISTER_SUPER_ACK from %s [%s] (external %s) with %u attempts left", - macaddr_str(mac_buf1, ra.srcMac), - sock_to_cstr(sockbuf1, &sender), - sock_to_cstr(sockbuf2, orig_sender), - (unsigned int)eee->sup_attempts); + if(ra.cookie != eee->curr_sn->last_cookie) { + traceEvent(TRACE_INFO, "Rx REGISTER_SUPER_ACK with wrong or old cookie"); + return; + } - if(is_null_mac(eee->curr_sn->mac_addr)) { - HASH_DEL(eee->conf.supernodes, eee->curr_sn); - memcpy(&eee->curr_sn->mac_addr, ra.srcMac, N2N_MAC_SIZE); - HASH_ADD_PEER(eee->conf.supernodes, eee->curr_sn); + if(handle_remote_auth(eee, sn, &(ra.auth))) { + traceEvent(TRACE_INFO, "Rx REGISTER_SUPER_ACK with wrong or old response to challenge"); + if(eee->conf.shared_secret) { + traceEvent(TRACE_NORMAL, "Rx REGISTER_SUPER_ACK with wrong or old response to challenge, maybe indicating wrong federation public key (-P)"); } + return; + } - n2n_REGISTER_SUPER_ACK_payload_t *payload; - payload = (n2n_REGISTER_SUPER_ACK_payload_t*)tmpbuf; - - // from here on, 'sn' gets used differently - for(i = 0; i < ra.num_sn; i++) { - n2n_sock_t payload_sock; - skip_add = SN_ADD; - - // bugfix for https://github.com/ntop/n2n/issues/1029 - // REVISIT: best to be removed with 4.0 - idx = 0; - rem = sizeof(payload->sock); - decode_sock_payload(&payload_sock, payload->sock, &rem, &idx); - - sn = add_sn_to_list_by_mac_or_sock(&(eee->conf.supernodes), &payload_sock, payload->mac, &skip_add); - - if(skip_add == SN_ADD_ADDED) { - // TODO: could just avoid adding the special string - // with the hostname when we are adding a supernode - // discovered from the reg packet - sn->hostname = calloc(1, N2N_EDGE_SN_HOST_SIZE); - if(sn->hostname != NULL) { - char ip_tmp[N2N_EDGE_SN_HOST_SIZE]; - - inet_ntop(payload_sock.family, - (payload_sock.family == AF_INET) ? (void*)&(payload_sock.addr.v4) : (void*)&(payload_sock.addr.v6), - sn->hostname, N2N_EDGE_SN_HOST_SIZE - 1); - sprintf(ip_tmp, "%s:%u", (char*)sn->hostname, (uint16_t)(payload_sock.port)); - memcpy(sn->hostname, ip_tmp, sizeof(ip_tmp)); - } - sn->last_seen = 0; /* as opposed to payload handling in supernode */ - traceEvent( - TRACE_NORMAL, - "supernode '%s' added to the list of supernodes.", - peer_info_get_hostname(sn) - ); - } - // shift to next payload entry - payload++; - } + if(is_valid_peer_sock(&ra.sock)) + orig_sender = &(ra.sock); - if(eee->conf.tuntap_ip_mode == TUNTAP_IP_MODE_SN_ASSIGN) { - if((ra.dev_addr.net_addr != 0) && (ra.dev_addr.net_bitlen != 0)) { - eee->conf.tuntap_v4.net_addr = htonl(ra.dev_addr.net_addr); - eee->conf.tuntap_v4.net_bitlen = ra.dev_addr.net_bitlen; - } - } + traceEvent(TRACE_INFO, "Rx REGISTER_SUPER_ACK from %s [%s] (external %s) with %u attempts left", + macaddr_str(mac_buf1, ra.srcMac), + sock_to_cstr(sockbuf1, &sender), + sock_to_cstr(sockbuf2, orig_sender), + (unsigned int)eee->sup_attempts); - eee->sn_wait = 0; - reset_sup_attempts(eee); /* refresh because we got a response */ - - // update last_sup only on 'real' REGISTER_SUPER_ACKs, not on bootstrap ones (own MAC address - // still null_mac) this allows reliable in/out PACKET drop if not really registered with a supernode yet - if(!is_null_mac(eee->device.mac_addr)) { - if(!eee->last_sup) { - // indicates first successful connection between the edge and a supernode - traceEvent(TRACE_NORMAL, "[OK] edge <<< ================ >>> supernode"); - // send gratuitous ARP only upon first registration with supernode - send_grat_arps(eee); + if(is_null_mac(eee->curr_sn->mac_addr)) { + HASH_DEL(eee->conf.supernodes, eee->curr_sn); + memcpy(&eee->curr_sn->mac_addr, ra.srcMac, N2N_MAC_SIZE); + HASH_ADD_PEER(eee->conf.supernodes, eee->curr_sn); + } + + n2n_REGISTER_SUPER_ACK_payload_t *payload; + payload = (n2n_REGISTER_SUPER_ACK_payload_t*)tmpbuf; + + // from here on, 'sn' gets used differently + for(i = 0; i < ra.num_sn; i++) { + n2n_sock_t payload_sock; + skip_add = SN_ADD; + + // bugfix for https://github.com/ntop/n2n/issues/1029 + // REVISIT: best to be removed with 4.0 + idx = 0; + rem = sizeof(payload->sock); + decode_sock_payload(&payload_sock, payload->sock, &rem, &idx); + + sn = add_sn_to_list_by_mac_or_sock(&(eee->conf.supernodes), &payload_sock, payload->mac, &skip_add); + + if(skip_add == SN_ADD_ADDED) { + // TODO: could just avoid adding the special string + // with the hostname when we are adding a supernode + // discovered from the reg packet + sn->hostname = calloc(1, N2N_EDGE_SN_HOST_SIZE); + if(sn->hostname != NULL) { + char ip_tmp[N2N_EDGE_SN_HOST_SIZE]; + + inet_ntop(payload_sock.family, + (payload_sock.family == AF_INET) ? (void*)&(payload_sock.addr.v4) : (void*)&(payload_sock.addr.v6), + sn->hostname, N2N_EDGE_SN_HOST_SIZE - 1); + sprintf(ip_tmp, "%s:%u", (char*)sn->hostname, (uint16_t)(payload_sock.port)); + memcpy(sn->hostname, ip_tmp, sizeof(ip_tmp)); } - eee->last_sup = now; + sn->last_seen = 0; /* as opposed to payload handling in supernode */ + traceEvent( + TRACE_NORMAL, + "supernode '%s' added to the list of supernodes.", + peer_info_get_hostname(sn) + ); } + // shift to next payload entry + payload++; + } - // NOTE: the register_interval should be chosen by the edge node based on its NAT configuration. - // eee->conf.register_interval = ra.lifetime; + if(eee->conf.tuntap_ip_mode == TUNTAP_IP_MODE_SN_ASSIGN) { + if((ra.dev_addr.net_addr != 0) && (ra.dev_addr.net_bitlen != 0)) { + eee->conf.tuntap_v4.net_addr = htonl(ra.dev_addr.net_addr); + eee->conf.tuntap_v4.net_bitlen = ra.dev_addr.net_bitlen; + } + } - if(eee->cb.sn_registration_updated && !is_null_mac(eee->device.mac_addr)) - eee->cb.sn_registration_updated(eee, now, &sender); + eee->sn_wait = 0; + reset_sup_attempts(eee); /* refresh because we got a response */ - break; + // update last_sup only on 'real' REGISTER_SUPER_ACKs, not on bootstrap ones (own MAC address + // still null_mac) this allows reliable in/out PACKET drop if not really registered with a supernode yet + if(!is_null_mac(eee->device.mac_addr)) { + if(!eee->last_sup) { + // indicates first successful connection between the edge and a supernode + traceEvent(TRACE_NORMAL, "[OK] edge <<< ================ >>> supernode"); + // send gratuitous ARP only upon first registration with supernode + send_grat_arps(eee); + } + eee->last_sup = now; } - case MSG_TYPE_REGISTER_SUPER_NAK: { + // NOTE: the register_interval should be chosen by the edge node based on its NAT configuration. + // eee->conf.register_interval = ra.lifetime; - n2n_REGISTER_SUPER_NAK_t nak; + if(eee->cb.sn_registration_updated && !is_null_mac(eee->device.mac_addr)) + eee->cb.sn_registration_updated(eee, now, &sender); - if(!(eee->sn_wait)) { - traceEvent(TRACE_DEBUG, "Rx REGISTER_SUPER_NAK with no outstanding REGISTER_SUPER"); - return; - } + break; + } - // FIXME: fix decode_* functions to not need memsets - memset(&nak, 0, sizeof(nak)); - decode_REGISTER_SUPER_NAK(&nak, &cmn, udp_buf, &rem, &idx); - - if(eee->conf.header_encryption == HEADER_ENCRYPTION_ENABLED) { - if(!find_peer_time_stamp_and_verify( - eee->pending_peers, - eee->known_peers, - sn, - nak.srcMac, - stamp, - TIME_STAMP_NO_JITTER)) { - traceEvent(TRACE_DEBUG, "dropped REGISTER_SUPER_NAK due to time stamp error"); - return; - } - } + case MSG_TYPE_REGISTER_SUPER_NAK: { - if(nak.cookie != eee->curr_sn->last_cookie) { - traceEvent(TRACE_DEBUG, "Rx REGISTER_SUPER_NAK with wrong or old cookie"); + n2n_REGISTER_SUPER_NAK_t nak; + + if(!(eee->sn_wait)) { + traceEvent(TRACE_DEBUG, "Rx REGISTER_SUPER_NAK with no outstanding REGISTER_SUPER"); + return; + } + + // FIXME: fix decode_* functions to not need memsets + memset(&nak, 0, sizeof(nak)); + decode_REGISTER_SUPER_NAK(&nak, &cmn, udp_buf, &rem, &idx); + + if(eee->conf.header_encryption == HEADER_ENCRYPTION_ENABLED) { + if(!find_peer_time_stamp_and_verify( + eee->pending_peers, + eee->known_peers, + sn, + nak.srcMac, + stamp, + TIME_STAMP_NO_JITTER)) { + traceEvent(TRACE_DEBUG, "dropped REGISTER_SUPER_NAK due to time stamp error"); return; } + } - // REVISIT: authenticate the NAK packet really originating from the supernode along the auth token. - // this must follow a different scheme because it needs to prove authenticity although the - // edge-provided credentials are wrong + if(nak.cookie != eee->curr_sn->last_cookie) { + traceEvent(TRACE_DEBUG, "Rx REGISTER_SUPER_NAK with wrong or old cookie"); + return; + } - traceEvent(TRACE_INFO, "Rx REGISTER_SUPER_NAK"); + // REVISIT: authenticate the NAK packet really originating from the supernode along the auth token. + // this must follow a different scheme because it needs to prove authenticity although the + // edge-provided credentials are wrong - if((memcmp(nak.srcMac, eee->device.mac_addr, sizeof(n2n_mac_t))) == 0) { - if(eee->conf.shared_secret) { - traceEvent(TRACE_ERROR, "authentication error, username or password not recognized by supernode"); - } else { - traceEvent(TRACE_ERROR, "authentication error, MAC or IP address already in use or not released yet by supernode"); - } - // REVISIT: the following portion is too harsh, repeated error warning should be sufficient until it eventually is resolved, - // preventing de-auth attacks - /* exit(1); this is too harsh, repeated error warning should be sufficient until it eventually is resolved, preventing de-auth attacks - } else { - HASH_FIND_PEER(eee->known_peers, nak.srcMac, peer); - if(peer != NULL) { - HASH_DEL(eee->known_peers, peer); - } - HASH_FIND_PEER(eee->pending_peers, nak.srcMac, scan); - if(scan != NULL) { - HASH_DEL(eee->pending_peers, scan); - } */ + traceEvent(TRACE_INFO, "Rx REGISTER_SUPER_NAK"); + + if((memcmp(nak.srcMac, eee->device.mac_addr, sizeof(n2n_mac_t))) == 0) { + if(eee->conf.shared_secret) { + traceEvent(TRACE_ERROR, "authentication error, username or password not recognized by supernode"); + } else { + traceEvent(TRACE_ERROR, "authentication error, MAC or IP address already in use or not released yet by supernode"); } - break; + // REVISIT: the following portion is too harsh, repeated error warning should be sufficient until it eventually is resolved, + // preventing de-auth attacks + /* exit(1); this is too harsh, repeated error warning should be sufficient until it eventually is resolved, preventing de-auth attacks + } else { + HASH_FIND_PEER(eee->known_peers, nak.srcMac, peer); + if(peer != NULL) { + HASH_DEL(eee->known_peers, peer); + } + HASH_FIND_PEER(eee->pending_peers, nak.srcMac, scan); + if(scan != NULL) { + HASH_DEL(eee->pending_peers, scan); + } */ } + break; + } - case MSG_TYPE_PEER_INFO: { + case MSG_TYPE_PEER_INFO: { - n2n_PEER_INFO_t pi; - struct peer_info * scan; - int skip_add; + n2n_PEER_INFO_t pi; + struct peer_info * scan; + int skip_add; - decode_PEER_INFO(&pi, &cmn, udp_buf, &rem, &idx); + decode_PEER_INFO(&pi, &cmn, udp_buf, &rem, &idx); - if(eee->conf.header_encryption == HEADER_ENCRYPTION_ENABLED) { - if(!find_peer_time_stamp_and_verify( - eee->pending_peers, - eee->known_peers, - sn, - null_mac, - stamp, - TIME_STAMP_ALLOW_JITTER)) { - traceEvent(TRACE_DEBUG, "dropped PEER_INFO due to time stamp error"); - return; - } + if(eee->conf.header_encryption == HEADER_ENCRYPTION_ENABLED) { + if(!find_peer_time_stamp_and_verify( + eee->pending_peers, + eee->known_peers, + sn, + null_mac, + stamp, + TIME_STAMP_ALLOW_JITTER)) { + traceEvent(TRACE_DEBUG, "dropped PEER_INFO due to time stamp error"); + return; } + } + + if((cmn.flags & N2N_FLAGS_SOCKET) && !is_valid_peer_sock(&pi.sock)) { + traceEvent(TRACE_DEBUG, "skip invalid PEER_INFO from %s [%s]", + macaddr_str(mac_buf1, pi.mac), + sock_to_cstr(sockbuf1, &pi.sock)); + break; + } + + if(is_null_mac(pi.mac)) { + // PONG - answer to PING (QUERY_PEER_INFO with null mac) + skip_add = SN_ADD_SKIP; + scan = add_sn_to_list_by_mac_or_sock(&(eee->conf.supernodes), &sender, pi.srcMac, &skip_add); + if(scan != NULL) { + eee->sn_pong = 1; + scan->last_seen = now; + scan->uptime = pi.uptime; + memcpy(scan->version, pi.version, sizeof(n2n_version_t)); + /* The data type depends on the actual selection strategy that has been chosen. */ + SN_SELECTION_CRITERION_DATA_TYPE sn_sel_tmp = pi.load; + sn_selection_criterion_calculate(eee, scan, &sn_sel_tmp); + + traceEvent(TRACE_INFO, "Rx PONG from supernode %s version '%s'", + macaddr_str(mac_buf1, pi.srcMac), + pi.version); - if((cmn.flags & N2N_FLAGS_SOCKET) && !is_valid_peer_sock(&pi.sock)) { - traceEvent(TRACE_DEBUG, "skip invalid PEER_INFO from %s [%s]", - macaddr_str(mac_buf1, pi.mac), - sock_to_cstr(sockbuf1, &pi.sock)); break; } + } else { + // regular PEER_INFO + HASH_FIND_PEER(eee->pending_peers, pi.mac, scan); + if(!scan) + // just in case the remote edge has been upgraded by the REG/ACK mechanism in the meantime + HASH_FIND_PEER(eee->known_peers, pi.mac, scan); - if(is_null_mac(pi.mac)) { - // PONG - answer to PING (QUERY_PEER_INFO with null mac) - skip_add = SN_ADD_SKIP; - scan = add_sn_to_list_by_mac_or_sock(&(eee->conf.supernodes), &sender, pi.srcMac, &skip_add); - if(scan != NULL) { - eee->sn_pong = 1; - scan->last_seen = now; - scan->uptime = pi.uptime; - memcpy(scan->version, pi.version, sizeof(n2n_version_t)); - /* The data type depends on the actual selection strategy that has been chosen. */ - SN_SELECTION_CRITERION_DATA_TYPE sn_sel_tmp = pi.load; - sn_selection_criterion_calculate(eee, scan, &sn_sel_tmp); - - traceEvent(TRACE_INFO, "Rx PONG from supernode %s version '%s'", - macaddr_str(mac_buf1, pi.srcMac), - pi.version); - - break; - } - } else { - // regular PEER_INFO - HASH_FIND_PEER(eee->pending_peers, pi.mac, scan); - if(!scan) - // just in case the remote edge has been upgraded by the REG/ACK mechanism in the meantime - HASH_FIND_PEER(eee->known_peers, pi.mac, scan); - - if(scan) { - scan->sock = pi.sock; + if(scan) { + scan->sock = pi.sock; - traceEvent(TRACE_INFO, "Rx PEER_INFO %s can be found at [%s]", - macaddr_str(mac_buf1, pi.mac), - sock_to_cstr(sockbuf1, &pi.sock)); + traceEvent(TRACE_INFO, "Rx PEER_INFO %s can be found at [%s]", + macaddr_str(mac_buf1, pi.mac), + sock_to_cstr(sockbuf1, &pi.sock)); - if(cmn.flags & N2N_FLAGS_SOCKET) { - scan->preferred_sock = pi.preferred_sock; - send_register(eee, &scan->preferred_sock, scan->mac_addr, N2N_LOCAL_REG_COOKIE); + if(cmn.flags & N2N_FLAGS_SOCKET) { + scan->preferred_sock = pi.preferred_sock; + send_register(eee, &scan->preferred_sock, scan->mac_addr, N2N_LOCAL_REG_COOKIE); - traceEvent(TRACE_INFO, "%s has preferred local socket at [%s]", - macaddr_str(mac_buf1, pi.mac), - sock_to_cstr(sockbuf1, &pi.preferred_sock)); - } + traceEvent(TRACE_INFO, "%s has preferred local socket at [%s]", + macaddr_str(mac_buf1, pi.mac), + sock_to_cstr(sockbuf1, &pi.preferred_sock)); + } - send_register(eee, &scan->sock, scan->mac_addr, N2N_REGULAR_REG_COOKIE); + send_register(eee, &scan->sock, scan->mac_addr, N2N_REGULAR_REG_COOKIE); - } else { - traceEvent(TRACE_INFO, "Rx PEER_INFO unknown peer %s", - macaddr_str(mac_buf1, pi.mac)); - } + } else { + traceEvent(TRACE_INFO, "Rx PEER_INFO unknown peer %s", + macaddr_str(mac_buf1, pi.mac)); } - break; } + break; + } - case MSG_TYPE_RE_REGISTER_SUPER: { - - if(eee->conf.header_encryption == HEADER_ENCRYPTION_ENABLED) { - if(!find_peer_time_stamp_and_verify( - eee->pending_peers, - eee->known_peers, - sn, - null_mac, - stamp, - TIME_STAMP_NO_JITTER)) { - traceEvent(TRACE_DEBUG, "dropped RE_REGISTER due to time stamp error"); - return; - } - } - - // only accept in user/pw mode for immediate re-registration because the new - // key is required for continous traffic flow, in other modes edge will realize - // changes with regular recurring REGISTER_SUPER - if(!eee->conf.shared_secret) { - traceEvent(TRACE_DEBUG, "dropped RE_REGISTER_SUPER as not in user/pw auth mode"); + case MSG_TYPE_RE_REGISTER_SUPER: { + + if(eee->conf.header_encryption == HEADER_ENCRYPTION_ENABLED) { + if(!find_peer_time_stamp_and_verify( + eee->pending_peers, + eee->known_peers, + sn, + null_mac, + stamp, + TIME_STAMP_NO_JITTER)) { + traceEvent(TRACE_DEBUG, "dropped RE_REGISTER due to time stamp error"); return; } + } - traceEvent(TRACE_INFO, "Rx RE_REGISTER_SUPER"); + // only accept in user/pw mode for immediate re-registration because the new + // key is required for continous traffic flow, in other modes edge will realize + // changes with regular recurring REGISTER_SUPER + if(!eee->conf.shared_secret) { + traceEvent(TRACE_DEBUG, "dropped RE_REGISTER_SUPER as not in user/pw auth mode"); + return; + } - eee->sn_wait = 2; /* immediately */ + traceEvent(TRACE_INFO, "Rx RE_REGISTER_SUPER"); - break; - } + eee->sn_wait = 2; /* immediately */ - default: - /* Not a known message type */ - traceEvent(TRACE_INFO, "unable to handle packet type %d: ignored", (signed int)msg_type); - return; - } /* switch(msg_type) */ - } else if(from_supernode) /* if(community match) */ - traceEvent(TRACE_INFO, "received packet with unknown community"); - else - traceEvent(TRACE_INFO, "ignoring packet with unknown community"); + break; + } + + default: + /* Not a known message type */ + traceEvent(TRACE_INFO, "unable to handle packet type %d: ignored", (signed int)msg_type); + return; + } /* switch(msg_type) */ } From bcaaa1c2e99e31087c170eb53b61d494f19d006d Mon Sep 17 00:00:00 2001 From: Hamish Coleman Date: Sat, 19 Oct 2024 12:45:13 +1100 Subject: [PATCH 02/12] Start cleaning up the packet type definitions --- include/n2n_typedefs.h | 43 +++++++++++++++++++++--------------------- 1 file changed, 22 insertions(+), 21 deletions(-) diff --git a/include/n2n_typedefs.h b/include/n2n_typedefs.h index e9fc0b5..6e0ae0f 100644 --- a/include/n2n_typedefs.h +++ b/include/n2n_typedefs.h @@ -94,6 +94,23 @@ struct ether_hdr { typedef struct ether_hdr ether_hdr_t; +enum PACK_STRUCT n3n_pc { + n2n_ping = 0, /* Not used */ + n2n_register = 1, /* Register edge to edge */ + n2n_deregister = 2, /* Deregister this edge */ + n2n_packet = 3, /* PACKET data content */ + n2n_register_ack = 4, /* ACK of a registration from edge to edge */ + n2n_register_super = 5, /* Register edge to supernode */ + n2n_unregister_super = 6, /* Deregister edge from supernode */ + n2n_register_super_ack = 7, /* ACK from supernode to edge */ + n2n_register_super_nak = 8, /* NAK from supernode to edge - registration refused */ + n2n_federation = 9, /* Not used by edge */ + n2n_peer_info = 10, /* Send info on a peer from sn to edge */ + n2n_query_peer = 11, /* ask supernode for info on a peer */ + n2n_re_register_super = 12 /* ask edge to re-register with supernode */ +}; + + #if defined(_MSC_VER) || defined(__MINGW32__) #pragma pack(pop) #endif @@ -139,22 +156,6 @@ typedef u_short sa_family_t; typedef char n2n_sn_name_t[N2N_EDGE_SN_HOST_SIZE]; -typedef enum n2n_pc { - n2n_ping = 0, /* Not used */ - n2n_register = 1, /* Register edge to edge */ - n2n_deregister = 2, /* Deregister this edge */ - n2n_packet = 3, /* PACKET data content */ - n2n_register_ack = 4, /* ACK of a registration from edge to edge */ - n2n_register_super = 5, /* Register edge to supernode */ - n2n_unregister_super = 6, /* Deregister edge from supernode */ - n2n_register_super_ack = 7, /* ACK from supernode to edge */ - n2n_register_super_nak = 8, /* NAK from supernode to edge - registration refused */ - n2n_federation = 9, /* Not used by edge */ - n2n_peer_info = 10, /* Send info on a peer from sn to edge */ - n2n_query_peer = 11, /* ask supernode for info on a peer */ - n2n_re_register_super = 12 /* ask edge to re-register with supernode */ -} n2n_pc_t; - // This one bit higher than the largest used flag value. It is used in the // header encryption detection heuristic and is not a flag itself #define N2N_FLAGS_OPTIONS_MAX 0x0080 @@ -230,7 +231,7 @@ typedef struct n2n_common { /* int version; */ uint8_t ttl; - uint8_t pc; + enum n3n_pc pc; uint16_t flags; n2n_community_t community; } n2n_common_t; @@ -259,7 +260,7 @@ typedef struct n2n_PACKET { uint8_t compression; } n2n_PACKET_t; -/* Linked with n2n_register_super in n2n_pc_t. Only from edge to supernode. */ +/* Linked with n2n_register_super via enum n3n_pc. Only from edge to supernode. */ 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 */ @@ -271,7 +272,7 @@ typedef struct n2n_REGISTER_SUPER { } n2n_REGISTER_SUPER_t; -/* Linked with n2n_register_super_ack in n2n_pc_t. Only from supernode to edge. */ +/* Linked with n2n_register_super_ack via enum n3n_pc. Only from supernode to edge. */ typedef struct n2n_REGISTER_SUPER_ACK { n2n_cookie_t cookie; /**< Return cookie from REGISTER_SUPER */ n2n_mac_t srcMac; /**< MAC of answering supernode */ @@ -291,7 +292,7 @@ typedef struct n2n_REGISTER_SUPER_ACK { } n2n_REGISTER_SUPER_ACK_t; -/* Linked with n2n_register_super_ack in n2n_pc_t. Only from supernode to edge. */ +/* Linked with n2n_register_super_ack via enum n3n_pc. Only from supernode to edge. */ typedef struct n2n_REGISTER_SUPER_NAK { n2n_cookie_t cookie; /* Return cookie from REGISTER_SUPER */ n2n_mac_t srcMac; @@ -309,7 +310,7 @@ typedef struct n2n_REGISTER_SUPER_ACK_payload { } n2n_REGISTER_SUPER_ACK_payload_t; -/* Linked with n2n_unregister_super in n2n_pc_t. */ +/* Linked with n2n_unregister_super via enum n3n_pc. */ typedef struct n2n_UNREGISTER_SUPER { n2n_auth_t auth; n2n_mac_t srcMac; From 6556f03cffe9a6bc1f79d1dabd24482a00320161 Mon Sep 17 00:00:00 2001 From: Hamish Coleman Date: Sat, 19 Oct 2024 13:10:59 +1100 Subject: [PATCH 03/12] Remove duplicated packet type definitions Having two almost identical lists - and worse, using both sets for values at different points in the code made it significantly more difficult to track where packets were being generated or processed. --- include/n2n_define.h | 15 --------------- include/n2n_typedefs.h | 41 +++++++++++++++++++++-------------------- src/edge_utils.c | 12 ++++++------ src/sn_utils.c | 18 ++++++++++-------- tools/n3n-benchmark.c | 2 +- tools/n3n-decode.c | 22 +++++++++++----------- tools/tests-transform.c | 2 +- tools/tests-wire.c | 6 +++--- 8 files changed, 53 insertions(+), 65 deletions(-) diff --git a/include/n2n_define.h b/include/n2n_define.h index 5db7d5e..23f2e16 100644 --- a/include/n2n_define.h +++ b/include/n2n_define.h @@ -19,21 +19,6 @@ #ifndef _N2N_DEFINE_H_ #define _N2N_DEFINE_H_ -/* N2N packet header indicators. */ -#define MSG_TYPE_REGISTER 1 -#define MSG_TYPE_DEREGISTER 2 // unused -#define MSG_TYPE_PACKET 3 -#define MSG_TYPE_REGISTER_ACK 4 -#define MSG_TYPE_REGISTER_SUPER 5 -#define MSG_TYPE_UNREGISTER_SUPER 6 -#define MSG_TYPE_REGISTER_SUPER_ACK 7 -#define MSG_TYPE_REGISTER_SUPER_NAK 8 -#define MSG_TYPE_FEDERATION 9 // unused -#define MSG_TYPE_PEER_INFO 10 -#define MSG_TYPE_QUERY_PEER 11 -#define MSG_TYPE_RE_REGISTER_SUPER 12 -#define MSG_TYPE_MAX_TYPE 12 - /* Max available space to add supernodes' informations (sockets and MACs) in REGISTER_SUPER_ACK * Field sizes of REGISTER_SUPER_ACK as used in encode/decode fucntions in src/wire.c */ diff --git a/include/n2n_typedefs.h b/include/n2n_typedefs.h index 6e0ae0f..f29563e 100644 --- a/include/n2n_typedefs.h +++ b/include/n2n_typedefs.h @@ -94,22 +94,23 @@ struct ether_hdr { typedef struct ether_hdr ether_hdr_t; -enum PACK_STRUCT n3n_pc { - n2n_ping = 0, /* Not used */ - n2n_register = 1, /* Register edge to edge */ - n2n_deregister = 2, /* Deregister this edge */ - n2n_packet = 3, /* PACKET data content */ - n2n_register_ack = 4, /* ACK of a registration from edge to edge */ - n2n_register_super = 5, /* Register edge to supernode */ - n2n_unregister_super = 6, /* Deregister edge from supernode */ - n2n_register_super_ack = 7, /* ACK from supernode to edge */ - n2n_register_super_nak = 8, /* NAK from supernode to edge - registration refused */ - n2n_federation = 9, /* Not used by edge */ - n2n_peer_info = 10, /* Send info on a peer from sn to edge */ - n2n_query_peer = 11, /* ask supernode for info on a peer */ - n2n_re_register_super = 12 /* ask edge to re-register with supernode */ +/* N2N packet header indicators. */ +enum PACK_STRUCT n3n_msg_type { + MSG_TYPE_PING = 0, /* Not used */ + MSG_TYPE_REGISTER = 1, /* Register edge to edge */ + MSG_TYPE_DEREGISTER = 2, /* UNUSED */ + MSG_TYPE_PACKET = 3, /* PACKET data content */ + MSG_TYPE_REGISTER_ACK = 4, /* ACK of a registration peer to peer */ + MSG_TYPE_REGISTER_SUPER = 5, /* Register edge to supernode */ + MSG_TYPE_UNREGISTER_SUPER = 6, /* Deregister edge from supernode */ + MSG_TYPE_REGISTER_SUPER_ACK = 7, /* ACK from sn to edge */ + MSG_TYPE_REGISTER_SUPER_NAK = 8, /* NAK from sn to edge - reg refused */ + MSG_TYPE_FEDERATION = 9, /* UNUSED */ + MSG_TYPE_PEER_INFO = 10, /* Send info on a peer (sn to edge) */ + MSG_TYPE_QUERY_PEER = 11, /* ask supernode for info on a peer */ + MSG_TYPE_RE_REGISTER_SUPER = 12 /* ask edge to re-register with sn */ }; - +#define MSG_TYPE_MAX_TYPE 12 #if defined(_MSC_VER) || defined(__MINGW32__) #pragma pack(pop) @@ -231,7 +232,7 @@ typedef struct n2n_common { /* int version; */ uint8_t ttl; - enum n3n_pc pc; + enum n3n_msg_type pc; uint16_t flags; n2n_community_t community; } n2n_common_t; @@ -260,7 +261,7 @@ typedef struct n2n_PACKET { uint8_t compression; } n2n_PACKET_t; -/* Linked with n2n_register_super via enum n3n_pc. Only from edge to supernode. */ +/* Linked with n2n_register_super via enum n3n_msg_type. Only from edge to supernode. */ 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 */ @@ -272,7 +273,7 @@ typedef struct n2n_REGISTER_SUPER { } n2n_REGISTER_SUPER_t; -/* Linked with n2n_register_super_ack via enum n3n_pc. Only from supernode to edge. */ +/* Linked with n2n_register_super_ack via enum n3n_msg_type. Only from supernode to edge. */ typedef struct n2n_REGISTER_SUPER_ACK { n2n_cookie_t cookie; /**< Return cookie from REGISTER_SUPER */ n2n_mac_t srcMac; /**< MAC of answering supernode */ @@ -292,7 +293,7 @@ typedef struct n2n_REGISTER_SUPER_ACK { } n2n_REGISTER_SUPER_ACK_t; -/* Linked with n2n_register_super_ack via enum n3n_pc. Only from supernode to edge. */ +/* Linked with n2n_register_super_ack via enum n3n_msg_type. Only from supernode to edge. */ typedef struct n2n_REGISTER_SUPER_NAK { n2n_cookie_t cookie; /* Return cookie from REGISTER_SUPER */ n2n_mac_t srcMac; @@ -310,7 +311,7 @@ typedef struct n2n_REGISTER_SUPER_ACK_payload { } n2n_REGISTER_SUPER_ACK_payload_t; -/* Linked with n2n_unregister_super via enum n3n_pc. */ +/* Linked with n2n_unregister_super via enum n3n_msg_type. */ typedef struct n2n_UNREGISTER_SUPER { n2n_auth_t auth; n2n_mac_t srcMac; diff --git a/src/edge_utils.c b/src/edge_utils.c index ef7b944..1c0ddb5 100644 --- a/src/edge_utils.c +++ b/src/edge_utils.c @@ -1234,7 +1234,7 @@ void send_query_peer (struct n3n_runtime_data * eee, int n_o_skip_sn = 0; cmn.ttl = N2N_DEFAULT_TTL; - cmn.pc = n2n_query_peer; + cmn.pc = MSG_TYPE_QUERY_PEER; cmn.flags = 0; memcpy(cmn.community, eee->conf.community_name, N2N_COMMUNITY_SIZE); @@ -1313,7 +1313,7 @@ void send_register_super (struct n3n_runtime_data *eee) { memset(®, 0, sizeof(reg)); cmn.ttl = N2N_DEFAULT_TTL; - cmn.pc = n2n_register_super; + cmn.pc = MSG_TYPE_REGISTER_SUPER; if(eee->conf.preferred_sock.family == (uint8_t)AF_INVALID) { cmn.flags = 0; } else { @@ -1368,7 +1368,7 @@ static void send_unregister_super (struct n3n_runtime_data *eee) { memset(&unreg, 0, sizeof(unreg)); cmn.ttl = N2N_DEFAULT_TTL; - cmn.pc = n2n_unregister_super; + cmn.pc = MSG_TYPE_UNREGISTER_SUPER; cmn.flags = 0; memcpy(cmn.community, eee->conf.community_name, N2N_COMMUNITY_SIZE); get_local_auth(eee, &(unreg.auth)); @@ -1465,7 +1465,7 @@ static void send_register (struct n3n_runtime_data * eee, memset(&cmn, 0, sizeof(cmn)); memset(®, 0, sizeof(reg)); cmn.ttl = N2N_DEFAULT_TTL; - cmn.pc = n2n_register; + cmn.pc = MSG_TYPE_REGISTER; cmn.flags = 0; memcpy(cmn.community, eee->conf.community_name, N2N_COMMUNITY_SIZE); @@ -1516,7 +1516,7 @@ static void send_register_ack (struct n3n_runtime_data * eee, // FIXME: fix encode_* functions to not need memsets memset(&cmn, 0, sizeof(cmn)); cmn.ttl = N2N_DEFAULT_TTL; - cmn.pc = n2n_register_ack; + cmn.pc = MSG_TYPE_REGISTER_ACK; cmn.flags = 0; memcpy(cmn.community, eee->conf.community_name, N2N_COMMUNITY_SIZE); @@ -2103,7 +2103,7 @@ void edge_send_packet2net (struct n3n_runtime_data * eee, // FIXME: fix encode_* functions to not need memsets memset(&cmn, 0, sizeof(cmn)); cmn.ttl = N2N_DEFAULT_TTL; - cmn.pc = n2n_packet; + cmn.pc = MSG_TYPE_PACKET; cmn.flags = 0; /* no options, not from supernode, no socket */ memcpy(cmn.community, eee->conf.community_name, N2N_COMMUNITY_SIZE); diff --git a/src/sn_utils.c b/src/sn_utils.c index 5445371..24c77e8 100644 --- a/src/sn_utils.c +++ b/src/sn_utils.c @@ -209,7 +209,7 @@ void send_re_register_super (struct n3n_runtime_data *sss) { if(comm->allowed_users) { // prepare cmn.ttl = N2N_DEFAULT_TTL; - cmn.pc = n2n_re_register_super; + cmn.pc = MSG_TYPE_RE_REGISTER_SUPER; cmn.flags = N2N_FLAGS_FROM_SUPERNODE; memcpy(cmn.community, comm->community, N2N_COMMUNITY_SIZE); @@ -1488,7 +1488,7 @@ static int re_register_and_purge_supernodes (struct n3n_runtime_data *sss, struc memset(®, 0, sizeof(reg)); cmn.ttl = N2N_DEFAULT_TTL; - cmn.pc = n2n_register_super; + cmn.pc = MSG_TYPE_REGISTER_SUPER; cmn.flags = N2N_FLAGS_FROM_SUPERNODE; memcpy(cmn.community, comm->community, N2N_COMMUNITY_SIZE); @@ -1657,6 +1657,8 @@ static int process_udp (struct n3n_runtime_data * sss, traceEvent(TRACE_DEBUG, "dropped a packet too short to be valid"); return -1; } + // FIXME: if this is using be16toh then it is doing wire processing and + // should be located in wire.c with the rest of the wire processing. if((udp_buf[23] == (uint8_t)0x00) // null terminated community name && (udp_buf[00] == N2N_PKT_VERSION) // correct packet version && ((be16toh(*(uint16_t*)&(udp_buf[02])) & N2N_FLAGS_TYPE_MASK) <= MSG_TYPE_MAX_TYPE) // message type @@ -2070,7 +2072,7 @@ static int process_udp (struct n3n_runtime_data * sss, } cmn2.ttl = N2N_DEFAULT_TTL; - cmn2.pc = n2n_register_super_ack; + cmn2.pc = MSG_TYPE_REGISTER_SUPER_ACK; cmn2.flags = N2N_FLAGS_SOCKET | N2N_FLAGS_FROM_SUPERNODE; memcpy(cmn2.community, cmn.community, sizeof(n2n_community_t)); @@ -2148,7 +2150,7 @@ static int process_udp (struct n3n_runtime_data * sss, if(ret_value == update_edge_auth_fail) { // send REGISTER_SUPER_NAK - cmn2.pc = n2n_register_super_nak; + cmn2.pc = MSG_TYPE_REGISTER_SUPER_NAK; nak.cookie = reg.cookie; memcpy(nak.srcMac, reg.edgeMac, sizeof(n2n_mac_t)); @@ -2177,7 +2179,7 @@ static int process_udp (struct n3n_runtime_data * sss, if(!is_null_mac(reg.edgeMac)) { memcpy(®.sock, &sender, sizeof(sender)); - cmn2.pc = n2n_register_super; + cmn2.pc = MSG_TYPE_REGISTER_SUPER; encode_REGISTER_SUPER(ackbuf, &encx, &cmn2, ®); if(comm->header_encryption == HEADER_ENCRYPTION_ENABLED) { @@ -2216,7 +2218,7 @@ static int process_udp (struct n3n_runtime_data * sss, // send REGISTER_SUPER_ACK encx = 0; - cmn2.pc = n2n_register_super_ack; + cmn2.pc = MSG_TYPE_REGISTER_SUPER_ACK; encode_REGISTER_SUPER_ACK(ackbuf, &encx, &cmn2, &ack, payload_buf); @@ -2536,7 +2538,7 @@ static int process_udp (struct n3n_runtime_data * sss, macaddr_str(mac_buf, query.srcMac)); cmn2.ttl = N2N_DEFAULT_TTL; - cmn2.pc = n2n_peer_info; + cmn2.pc = MSG_TYPE_PEER_INFO; cmn2.flags = N2N_FLAGS_FROM_SUPERNODE; memcpy(cmn2.community, cmn.community, sizeof(n2n_community_t)); @@ -2582,7 +2584,7 @@ static int process_udp (struct n3n_runtime_data * sss, HASH_FIND_PEER(comm->edges, query.targetMac, scan); if(scan) { cmn2.ttl = N2N_DEFAULT_TTL; - cmn2.pc = n2n_peer_info; + cmn2.pc = MSG_TYPE_PEER_INFO; cmn2.flags = N2N_FLAGS_FROM_SUPERNODE; memcpy(cmn2.community, cmn.community, sizeof(n2n_community_t)); diff --git a/tools/n3n-benchmark.c b/tools/n3n-benchmark.c index 64a95c9..6c871b0 100644 --- a/tools/n3n-benchmark.c +++ b/tools/n3n-benchmark.c @@ -281,7 +281,7 @@ static ssize_t do_encode_packet ( uint8_t * pktbuf, size_t bufsize, const n2n_co memset( &cmn, 0, sizeof(cmn) ); cmn.ttl = N2N_DEFAULT_TTL; - cmn.pc = n2n_packet; + cmn.pc = MSG_TYPE_PACKET; cmn.flags=0; /* no options, not from supernode, no socket */ memcpy( cmn.community, c, N2N_COMMUNITY_SIZE ); diff --git a/tools/n3n-decode.c b/tools/n3n-decode.c index 68aa1f1..2cacf23 100644 --- a/tools/n3n-decode.c +++ b/tools/n3n-decode.c @@ -206,19 +206,19 @@ static int run_packet_loop () { } switch(common.pc) { - case n2n_ping: - case n2n_register: - case n2n_deregister: - case n2n_register_ack: - case n2n_register_super: - case n2n_register_super_ack: - case n2n_register_super_nak: - case n2n_federation: - case n2n_peer_info: - case n2n_query_peer: + case MSG_TYPE_PING: + case MSG_TYPE_REGISTER: + case MSG_TYPE_DEREGISTER: + case MSG_TYPE_REGISTER_ACK: + case MSG_TYPE_REGISTER_SUPER: + case MSG_TYPE_REGISTER_SUPER_ACK: + case MSG_TYPE_REGISTER_SUPER_NAK: + case MSG_TYPE_FEDERATION: + case MSG_TYPE_PEER_INFO: + case MSG_TYPE_QUERY_PEER: write_packet(packet, &header); break; - case n2n_packet: + case MSG_TYPE_PACKET: decode_PACKET(&pkt, &common, packet, &rem, &idx); decode_encrypted_packet(packet, &header, &pkt, idx); break; diff --git a/tools/tests-transform.c b/tools/tests-transform.c index d685626..71faa0d 100644 --- a/tools/tests-transform.c +++ b/tools/tests-transform.c @@ -195,7 +195,7 @@ static ssize_t do_encode_packet ( uint8_t * pktbuf, size_t bufsize, const n2n_co memset( &cmn, 0, sizeof(cmn) ); cmn.ttl = N2N_DEFAULT_TTL; - cmn.pc = n2n_packet; + cmn.pc = MSG_TYPE_PACKET; cmn.flags=0; /* no options, not from supernode, no socket */ memcpy( cmn.community, c, N2N_COMMUNITY_SIZE ); diff --git a/tools/tests-wire.c b/tools/tests-wire.c index 2b76c2a..3b9a8af 100644 --- a/tools/tests-wire.c +++ b/tools/tests-wire.c @@ -88,7 +88,7 @@ void print_common (char *test_name, n2n_common_t *common) { void test_REGISTER (n2n_common_t *common) { char *test_name = "REGISTER"; - common->pc = n2n_register; + common->pc = MSG_TYPE_REGISTER; printf("%s: common.pc = %i\n", test_name, common->pc); n2n_REGISTER_t reg; @@ -123,7 +123,7 @@ void test_REGISTER (n2n_common_t *common) { void test_REGISTER_SUPER (n2n_common_t *common) { char *test_name = "REGISTER_SUPER"; - common->pc = n2n_register_super; + common->pc = MSG_TYPE_REGISTER_SUPER; printf("%s: common.pc = %i\n", test_name, common->pc); n2n_REGISTER_SUPER_t reg; @@ -162,7 +162,7 @@ void test_REGISTER_SUPER (n2n_common_t *common) { void test_UNREGISTER_SUPER (n2n_common_t *common) { char *test_name = "UNREGISTER_SUPER"; - common->pc = n2n_unregister_super; + common->pc = MSG_TYPE_UNREGISTER_SUPER; printf("%s: common.pc = %i\n", test_name, common->pc); n2n_UNREGISTER_SUPER_t unreg; From 4185c4d5a10b2e407926206164f5072cdadf3ebe Mon Sep 17 00:00:00 2001 From: Hamish Coleman Date: Sat, 19 Oct 2024 13:19:02 +1100 Subject: [PATCH 04/12] Make processing flow easier to comprehend with reordering --- src/sn_utils.c | 138 +++++++++++++++++++++++++------------------------ 1 file changed, 70 insertions(+), 68 deletions(-) diff --git a/src/sn_utils.c b/src/sn_utils.c index 24c77e8..4629f5d 100644 --- a/src/sn_utils.c +++ b/src/sn_utils.c @@ -2169,58 +2169,21 @@ static int process_udp (struct n3n_runtime_data * sss, traceEvent(TRACE_DEBUG, "Tx REGISTER_SUPER_NAK for %s", macaddr_str(mac_buf, reg.edgeMac)); - } else { - // if this is not already from a supernode ... - // and not from federation, ... - if((!(cmn.flags & N2N_FLAGS_FROM_SUPERNODE)) || (!(cmn.flags & N2N_FLAGS_SOCKET))) { - // ... forward to all other supernodes (note try_broadcast()'s behavior with - // NULL comm and from_supernode parameter) - // exception: do not forward auto ip draw - if(!is_null_mac(reg.edgeMac)) { - memcpy(®.sock, &sender, sizeof(sender)); - - cmn2.pc = MSG_TYPE_REGISTER_SUPER; - encode_REGISTER_SUPER(ackbuf, &encx, &cmn2, ®); - - if(comm->header_encryption == HEADER_ENCRYPTION_ENABLED) { - packet_header_encrypt(ackbuf, encx, encx, - comm->header_encryption_ctx_static, comm->header_iv_ctx_static, - time_stamp()); - // if user-password-auth - if(comm->allowed_users) { - // append an encrypted packet hash - pearson_hash_128(hash_buf, ackbuf, encx); - // same 'user' as above - speck_128_encrypt(hash_buf, (speck_context_t*)user->shared_secret_ctx); - encode_buf(ackbuf, &encx, hash_buf, N2N_REG_SUP_HASH_CHECK_LEN); - } - } - try_broadcast(sss, NULL, &cmn, reg.edgeMac, from_supernode, ackbuf, encx, now); - } - - // dynamic key time handling if appropriate - ack.key_time = 0; - if(comm->is_federation) { - if(reg.key_time > sss->dynamic_key_time) { - traceEvent(TRACE_DEBUG, "setting new key time"); - // have all edges re_register (using old dynamic key) - send_re_register_super(sss); - // set new key time - sss->dynamic_key_time = reg.key_time; - // calculate new dynamic keys for all communities - calculate_dynamic_keys(sss); - // force re-register with all supernodes - re_register_and_purge_supernodes(sss, sss->federation, &any_time, now, 1 /* forced */); - } - ack.key_time = sss->dynamic_key_time; - } + break; + } - // send REGISTER_SUPER_ACK - encx = 0; - cmn2.pc = MSG_TYPE_REGISTER_SUPER_ACK; + // if this is not already from a supernode ... + // and not from federation, ... + if((!(cmn.flags & N2N_FLAGS_FROM_SUPERNODE)) || (!(cmn.flags & N2N_FLAGS_SOCKET))) { + // ... forward to all other supernodes (note try_broadcast()'s behavior with + // NULL comm and from_supernode parameter) + // exception: do not forward auto ip draw + if(!is_null_mac(reg.edgeMac)) { + memcpy(®.sock, &sender, sizeof(sender)); - encode_REGISTER_SUPER_ACK(ackbuf, &encx, &cmn2, &ack, payload_buf); + cmn2.pc = MSG_TYPE_REGISTER_SUPER; + encode_REGISTER_SUPER(ackbuf, &encx, &cmn2, ®); if(comm->header_encryption == HEADER_ENCRYPTION_ENABLED) { packet_header_encrypt(ackbuf, encx, encx, @@ -2236,26 +2199,65 @@ static int process_udp (struct n3n_runtime_data * sss, } } - sendto_sock(sss, socket_fd, sender_sock, ackbuf, encx); + try_broadcast(sss, NULL, &cmn, reg.edgeMac, from_supernode, ackbuf, encx, now); + } - traceEvent(TRACE_DEBUG, "Tx REGISTER_SUPER_ACK for %s [%s]", - macaddr_str(mac_buf, reg.edgeMac), - sock_to_cstr(sockbuf, &(ack.sock))); - } else { - // this is an edge with valid authentication registering with another supernode, so ... - // 1- ... associate it with that other supernode - update_node_supernode_association(comm, &(reg.edgeMac), sender_sock, sock_size, now); - // 2- ... we can delete it from regular list if present (can happen) - HASH_FIND_PEER(comm->edges, reg.edgeMac, peer); - if(peer != NULL) { - if((peer->socket_fd != sss->sock) && (peer->socket_fd >= 0)) { - n2n_tcp_connection_t *conn; - HASH_FIND_INT(sss->tcp_connections, &(peer->socket_fd), conn); - close_tcp_connection(sss, conn); /* also deletes the peer */ - } else { - HASH_DEL(comm->edges, peer); - free(peer); - } + // dynamic key time handling if appropriate + ack.key_time = 0; + if(comm->is_federation) { + if(reg.key_time > sss->dynamic_key_time) { + traceEvent(TRACE_DEBUG, "setting new key time"); + // have all edges re_register (using old dynamic key) + send_re_register_super(sss); + // set new key time + sss->dynamic_key_time = reg.key_time; + // calculate new dynamic keys for all communities + calculate_dynamic_keys(sss); + // force re-register with all supernodes + re_register_and_purge_supernodes(sss, sss->federation, &any_time, now, 1 /* forced */); + } + ack.key_time = sss->dynamic_key_time; + } + + // send REGISTER_SUPER_ACK + encx = 0; + cmn2.pc = MSG_TYPE_REGISTER_SUPER_ACK; + + encode_REGISTER_SUPER_ACK(ackbuf, &encx, &cmn2, &ack, payload_buf); + + if(comm->header_encryption == HEADER_ENCRYPTION_ENABLED) { + packet_header_encrypt(ackbuf, encx, encx, + comm->header_encryption_ctx_static, comm->header_iv_ctx_static, + time_stamp()); + // if user-password-auth + if(comm->allowed_users) { + // append an encrypted packet hash + pearson_hash_128(hash_buf, ackbuf, encx); + // same 'user' as above + speck_128_encrypt(hash_buf, (speck_context_t*)user->shared_secret_ctx); + encode_buf(ackbuf, &encx, hash_buf, N2N_REG_SUP_HASH_CHECK_LEN); + } + } + + sendto_sock(sss, socket_fd, sender_sock, ackbuf, encx); + + traceEvent(TRACE_DEBUG, "Tx REGISTER_SUPER_ACK for %s [%s]", + macaddr_str(mac_buf, reg.edgeMac), + sock_to_cstr(sockbuf, &(ack.sock))); + } else { + // this is an edge with valid authentication registering with another supernode, so ... + // 1- ... associate it with that other supernode + update_node_supernode_association(comm, &(reg.edgeMac), sender_sock, sock_size, now); + // 2- ... we can delete it from regular list if present (can happen) + HASH_FIND_PEER(comm->edges, reg.edgeMac, peer); + if(peer != NULL) { + if((peer->socket_fd != sss->sock) && (peer->socket_fd >= 0)) { + n2n_tcp_connection_t *conn; + HASH_FIND_INT(sss->tcp_connections, &(peer->socket_fd), conn); + close_tcp_connection(sss, conn); /* also deletes the peer */ + } else { + HASH_DEL(comm->edges, peer); + free(peer); } } } From 1b7821abd6b96d1bc2127e50c56949ee3475ac10 Mon Sep 17 00:00:00 2001 From: Hamish Coleman Date: Sat, 19 Oct 2024 13:22:48 +1100 Subject: [PATCH 05/12] Continue clarification with early function exits where possible --- src/sn_utils.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/sn_utils.c b/src/sn_utils.c index 4629f5d..608edbe 100644 --- a/src/sn_utils.c +++ b/src/sn_utils.c @@ -1875,7 +1875,7 @@ static int process_udp (struct n3n_runtime_data * sss, } else { try_broadcast(sss, comm, &cmn, pkt.srcMac, from_supernode, rec_buf, encx, now); } - break; + return 0; } case MSG_TYPE_REGISTER: { @@ -1947,12 +1947,12 @@ static int process_udp (struct n3n_runtime_data * sss, } else { traceEvent(TRACE_ERROR, "Rx REGISTER with multicast destination"); } - break; + return 0; } case MSG_TYPE_REGISTER_ACK: { traceEvent(TRACE_DEBUG, "Rx REGISTER_ACK (not implemented) should not be via supernode"); - break; + return 0; } case MSG_TYPE_REGISTER_SUPER: { @@ -2170,7 +2170,7 @@ static int process_udp (struct n3n_runtime_data * sss, traceEvent(TRACE_DEBUG, "Tx REGISTER_SUPER_NAK for %s", macaddr_str(mac_buf, reg.edgeMac)); - break; + return 0; } // if this is not already from a supernode ... @@ -2262,7 +2262,7 @@ static int process_udp (struct n3n_runtime_data * sss, } } - break; + return 0; } case MSG_TYPE_UNREGISTER_SUPER: { @@ -2314,7 +2314,7 @@ static int process_udp (struct n3n_runtime_data * sss, } } } - break; + return 0; } case MSG_TYPE_REGISTER_SUPER_ACK: { @@ -2367,7 +2367,7 @@ static int process_udp (struct n3n_runtime_data * sss, scan->last_seen = now; } else { traceEvent(TRACE_DEBUG, "dropped REGISTER_SUPER_ACK due to an unknown supernode"); - break; + return 0; } if(ack.cookie == scan->last_cookie) { @@ -2409,7 +2409,7 @@ static int process_udp (struct n3n_runtime_data * sss, } else { traceEvent(TRACE_INFO, "Rx REGISTER_SUPER_ACK with wrong or old cookie"); } - break; + return 0; } case MSG_TYPE_REGISTER_SUPER_NAK: { @@ -2479,7 +2479,7 @@ static int process_udp (struct n3n_runtime_data * sss, } } } - break; + return 0; } case MSG_TYPE_QUERY_PEER: { @@ -2636,7 +2636,7 @@ static int process_udp (struct n3n_runtime_data * sss, } } } - break; + return 0; } case MSG_TYPE_PEER_INFO: { @@ -2692,7 +2692,7 @@ static int process_udp (struct n3n_runtime_data * sss, sendto_peer(sss, peer, encbuf, encx); } } - break; + return 0; } default: From 63b81df34565a2fa625222d0aaff17df788ef037 Mon Sep 17 00:00:00 2001 From: Hamish Coleman Date: Sat, 19 Oct 2024 13:36:31 +1100 Subject: [PATCH 06/12] Clarify control flow with early exits --- src/sn_utils.c | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/src/sn_utils.c b/src/sn_utils.c index 608edbe..c7aabbd 100644 --- a/src/sn_utils.c +++ b/src/sn_utils.c @@ -1228,11 +1228,14 @@ static int update_edge (struct n3n_runtime_data *sss, traceEvent(TRACE_INFO, "created edge %s ==> %s", macaddr_str(mac_buf, reg->edgeMac), sock_to_cstr(sockbuf, sender_sock)); + + scan->last_seen = now; + return update_edge_new_sn; } - ret = update_edge_new_sn; + return update_edge_new_sn; } else { traceEvent(TRACE_INFO, "authentication failed"); - ret = update_edge_auth_fail; + return update_edge_auth_fail; } } else { /* Known */ @@ -1253,7 +1256,8 @@ static int update_edge (struct n3n_runtime_data *sss, traceEvent(TRACE_INFO, "updated edge %s ==> %s", macaddr_str(mac_buf, reg->edgeMac), sock_to_cstr(sockbuf, sender_sock)); - ret = update_edge_sock_change; + scan->last_seen = now; + return update_edge_sock_change; } else { scan->last_cookie = reg->cookie; @@ -1261,19 +1265,16 @@ static int update_edge (struct n3n_runtime_data *sss, macaddr_str(mac_buf, reg->edgeMac), sock_to_cstr(sockbuf, sender_sock)); - ret = update_edge_no_change; + scan->last_seen = now; + return update_edge_no_change; } } else { traceEvent(TRACE_INFO, "authentication failed"); - ret = update_edge_auth_fail; + return update_edge_auth_fail; } } - if((scan != NULL) && (ret != update_edge_auth_fail)) { - scan->last_seen = now; - } - - return ret; + return 0; } From da2f23167e27bcf2a1579097db95267be8405e96 Mon Sep 17 00:00:00 2001 From: Hamish Coleman Date: Sat, 19 Oct 2024 13:49:35 +1100 Subject: [PATCH 07/12] Reduce verbosity of a fairly regular check --- src/edge_utils.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/edge_utils.c b/src/edge_utils.c index 1c0ddb5..5152e21 100644 --- a/src/edge_utils.c +++ b/src/edge_utils.c @@ -3175,11 +3175,16 @@ int run_edge_loop (struct n3n_runtime_data *eee) { } #endif + // TODO: + // - a static ip address mode + // - a notifier so we dont need to poll for changes + // - ipv6 support + // - multi-homing support if((eee->conf.tuntap_ip_mode == TUNTAP_IP_MODE_DHCP) && ((now - lastIfaceCheck) > IFACE_UPDATE_INTERVAL)) { uint32_t old_ip = eee->device.ip_addr; - traceEvent(TRACE_NORMAL, "re-checking dynamic IP address"); + traceEvent(TRACE_INFO, "re-checking dynamic IP address"); tuntap_get_address(&(eee->device)); lastIfaceCheck = now; From ac79ce32f622d31a7c54258bcc996fafb806464c Mon Sep 17 00:00:00 2001 From: Hamish Coleman Date: Sat, 19 Oct 2024 13:54:58 +1100 Subject: [PATCH 08/12] Increase information logged for authentication error --- src/edge_utils.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/edge_utils.c b/src/edge_utils.c index 5152e21..1aa6b7d 100644 --- a/src/edge_utils.c +++ b/src/edge_utils.c @@ -2725,6 +2725,14 @@ void process_udp (struct n3n_runtime_data *eee, const struct sockaddr *sender_so traceEvent(TRACE_INFO, "Rx REGISTER_SUPER_NAK"); if((memcmp(nak.srcMac, eee->device.mac_addr, sizeof(n2n_mac_t))) == 0) { + macstr_t buf_src; + macstr_t buf_dev; + traceEvent( + TRACE_ERROR, + "auth error: %s != %s", + macaddr_str(buf_src, nak.srcMac), + macaddr_str(buf_dev, eee->device.mac_addr) + ); if(eee->conf.shared_secret) { traceEvent(TRACE_ERROR, "authentication error, username or password not recognized by supernode"); } else { From c5d41b44d4f5b0aec42e065a146909c25421b209 Mon Sep 17 00:00:00 2001 From: Hamish Coleman Date: Sat, 19 Oct 2024 14:03:57 +1100 Subject: [PATCH 09/12] Increase logged info for auto process --- src/sn_utils.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/sn_utils.c b/src/sn_utils.c index c7aabbd..1edd775 100644 --- a/src/sn_utils.c +++ b/src/sn_utils.c @@ -1045,6 +1045,12 @@ static uint16_t reg_lifetime (struct n3n_runtime_data *sss) { static int auth_edge (const n2n_auth_t *present, const n2n_auth_t *presented, n2n_auth_t *answer, struct sn_community *community) { sn_user_t *user = NULL; + traceEvent( + TRACE_INFO, + "token scheme present=%i, presented=%i", + present->scheme, + presented->scheme + ); if(present->scheme == n2n_auth_none) { // n2n_auth_none scheme (set at supernode if cli option '-M') @@ -1090,6 +1096,7 @@ static int auth_edge (const n2n_auth_t *present, const n2n_auth_t *presented, n2 } // if not successful earlier: failure + traceEvent(TRACE_INFO, "auth default fail"); return -1; } @@ -1113,9 +1120,11 @@ static int handle_remote_auth (struct n3n_runtime_data *sss, const n2n_auth_t *r struct sn_community *community) { sn_user_t *user = NULL; + traceEvent(TRACE_INFO, "token scheme %i", remote_auth->scheme); if((NULL == community->allowed_users) != (remote_auth->scheme != n2n_auth_user_password)) { // received token's scheme does not match expected scheme + traceEvent(TRACE_INFO, "token scheme mismatch"); return -1; } @@ -1156,6 +1165,7 @@ static int handle_remote_auth (struct n3n_runtime_data *sss, const n2n_auth_t *r } // if not successful earlier: failure + traceEvent(TRACE_INFO, "auth default fail"); return -1; } @@ -1175,7 +1185,6 @@ static int update_edge (struct n3n_runtime_data *sss, macstr_t mac_buf; n2n_sock_str_t sockbuf; struct peer_info *scan, *iter, *tmp; - int ret; traceEvent(TRACE_DEBUG, "update_edge for %s [%s]", macaddr_str(mac_buf, reg->edgeMac), From 1b2bc796e6eed96d23ebf4c385c8bc934dee1290 Mon Sep 17 00:00:00 2001 From: Hamish Coleman Date: Sat, 19 Oct 2024 14:12:20 +1100 Subject: [PATCH 10/12] Disable macos codecov reports --- .github/workflows/tests.yml | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 1e7e461..3a0fb87 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -206,8 +206,11 @@ jobs: # name: coverage # path: coverage - - name: Upload data to codecov - uses: codecov/codecov-action@v3 + # Now the codecov on a mac fails with + # Error: spawn Unknown system error -86 + # I guess mac people just dont like coverage + # - name: Upload data to codecov + # uses: codecov/codecov-action@v3 test_windows: name: Test Windows From 111bc71e691cdad1ccf91848fe22c63dd906330d Mon Sep 17 00:00:00 2001 From: Hamish Coleman Date: Sat, 19 Oct 2024 14:54:21 +1100 Subject: [PATCH 11/12] Fix bug in jsonrpc handling --- libs/connslot/jsonrpc.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libs/connslot/jsonrpc.c b/libs/connslot/jsonrpc.c index 2369b39..996ea37 100644 --- a/libs/connslot/jsonrpc.c +++ b/libs/connslot/jsonrpc.c @@ -16,6 +16,10 @@ char *json_find_field(char *haystack, char *field) { // field must include the start and end doublequotes + if (!haystack) { + return NULL; + } + char *p = strstr(haystack, field); if (!p) { return NULL; From afd5acc4225111324e23f0927ab04282e5b80865 Mon Sep 17 00:00:00 2001 From: Hamish Coleman Date: Sat, 19 Oct 2024 15:53:39 +1100 Subject: [PATCH 12/12] Check that the peer object is not too old to use This is an attempt to fix the auth/reconnect issue. --- src/edge_utils.c | 6 ++---- src/peer_info.c | 24 ++++++++++++++++++++++++ src/peer_info.h | 1 + src/sn_utils.c | 8 +++++++- 4 files changed, 34 insertions(+), 5 deletions(-) diff --git a/src/edge_utils.c b/src/edge_utils.c index 1aa6b7d..9be89b3 100644 --- a/src/edge_utils.c +++ b/src/edge_utils.c @@ -2726,12 +2726,10 @@ void process_udp (struct n3n_runtime_data *eee, const struct sockaddr *sender_so if((memcmp(nak.srcMac, eee->device.mac_addr, sizeof(n2n_mac_t))) == 0) { macstr_t buf_src; - macstr_t buf_dev; traceEvent( TRACE_ERROR, - "auth error: %s != %s", - macaddr_str(buf_src, nak.srcMac), - macaddr_str(buf_dev, eee->device.mac_addr) + "auth error: mac %s", + macaddr_str(buf_src, nak.srcMac) ); if(eee->conf.shared_secret) { traceEvent(TRACE_ERROR, "authentication error, username or password not recognized by supernode"); diff --git a/src/peer_info.c b/src/peer_info.c index 43cc9f6..d5ca9e7 100644 --- a/src/peer_info.c +++ b/src/peer_info.c @@ -98,6 +98,28 @@ void peer_info_free (struct peer_info *p) { free(p); } +/* + * If the peer is still valid, returns it. + * If the peer has timed out, frees it and returns NULL + * Used after a HASH_FIND_PEER to validate the found peer + */ +struct peer_info* peer_info_validate (struct peer_info **list, struct peer_info *p) { + if(!p) { + return NULL; + } + if(!p->purgeable) { + return p; + } + time_t now = time(NULL); + if(p->last_seen >= now - REGISTRATION_TIMEOUT) { + return p; + } + HASH_DEL(*list, p); + mgmt_event_post(N3N_EVENT_PEER,N3N_EVENT_PEER_PURGE,p); + peer_info_free(p); + return NULL; +} + inline char *peer_info_get_hostname (struct peer_info *p) { return p->hostname; } @@ -120,6 +142,8 @@ size_t purge_peer_list (struct peer_info **peer_list, } HASH_ITER(hh, *peer_list, scan, tmp) { + // TODO: untangle the tcp_connections usage and use + // peer_info_validate() as the core of this loop if(scan->purgeable && scan->last_seen < purge_before) { if((scan->socket_fd >=0) && (scan->socket_fd != socket_not_to_close)) { if(tcp_connections) { diff --git a/src/peer_info.h b/src/peer_info.h index f8ab87a..7d5290b 100644 --- a/src/peer_info.h +++ b/src/peer_info.h @@ -48,6 +48,7 @@ typedef struct peer_info peer_info_t; void peer_info_init (struct peer_info *, const n2n_mac_t mac); struct peer_info* peer_info_malloc (const n2n_mac_t mac); void peer_info_free (struct peer_info *); +struct peer_info* peer_info_validate (struct peer_info **, struct peer_info *); char *peer_info_get_hostname (struct peer_info *); diff --git a/src/sn_utils.c b/src/sn_utils.c index 1edd775..99915df 100644 --- a/src/sn_utils.c +++ b/src/sn_utils.c @@ -1195,7 +1195,11 @@ static int update_edge (struct n3n_runtime_data *sss, // if unknown, make sure it is also not known by IP address if(NULL == scan) { HASH_ITER(hh,comm->edges,iter,tmp) { - // TODO: needs ipv6 support + // TODO: + // - needs ipv6 support + // - I suspect that this can leak TCP connections + // - convert to using a peer_info_*() call for manipulating the + // peer info lists if(iter->dev_addr.net_addr == reg->dev_addr.net_addr) { scan = iter; HASH_DEL(comm->edges, scan); @@ -1206,6 +1210,8 @@ static int update_edge (struct n3n_runtime_data *sss, } } + scan = peer_info_validate(&comm->edges, scan); + if(NULL == scan) { /* Not known */ if(handle_remote_auth(sss, &(reg->auth), answer_auth, comm) == 0) {