added preferred socket handling (-e) (#765)

This commit is contained in:
Logan oos Even 2021-09-09 14:07:29 +05:45 committed by GitHub
parent 05e6579038
commit 7fa0cc1e0a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 216 additions and 84 deletions

5
edge.8
View File

@ -44,6 +44,11 @@ TOS for packets, e.g. 0x48 for SSH like priority
enable PMTU discovery, it can reduce fragmentation but
causes connections to stall if not properly supported
.TP
\fB\-e \fR<\fIlocal ip\fR>
advertises the provided local IP address as preferred,
useful if multicast peer detection is not available, e.g.
disabled on routers
.TP
\fB\-S1\fR ... \fB\-S2\fR
do not connect p2p, always use the supernode,
\-S1 = via UDP, \-S2 = via TCP

View File

@ -165,7 +165,8 @@ enum skip_add{SN_ADD = 0, SN_ADD_SKIP = 1, SN_ADD_ADDED = 2};
#define N2N_PRIVATE_PUBLIC_KEY_SIZE 32
#define N2N_USER_KEY_LINE_STARTER '*'
#define N2N_MAC_SIZE 6
#define N2N_COOKIE_SIZE 4
#define N2N_REGULAR_REG_COOKIE 0x00000000
#define N2N_LOCAL_REG_COOKIE 0x00000001
#define N2N_DESC_SIZE 16
#define N2N_PKT_BUF_SIZE 2048
#define N2N_SOCKBUF_SIZE 64 /* string representation of INET or INET6 sockets */

View File

@ -20,19 +20,12 @@
#define _N2N_TYPEDEFS_H_
typedef uint8_t n2n_community_t[N2N_COMMUNITY_SIZE];
typedef uint8_t n2n_private_public_key_t[N2N_PRIVATE_PUBLIC_KEY_SIZE];
typedef uint8_t n2n_mac_t[N2N_MAC_SIZE];
typedef uint8_t n2n_cookie_t[N2N_COOKIE_SIZE];
typedef uint8_t n2n_desc_t[N2N_DESC_SIZE];
typedef char n2n_sock_str_t[N2N_SOCKBUF_SIZE]; /* tracing string buffer */
// those are definitely not typedefs (with a view to the filename) but neither are they defines
static const n2n_mac_t broadcast_mac = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
static const n2n_mac_t multicast_mac = { 0x01, 0x00, 0x5E, 0x00, 0x00, 0x00 }; /* First 3 bytes are meaningful */
static const n2n_mac_t ipv6_multicast_mac = { 0x33, 0x33, 0x00, 0x00, 0x00, 0x00 }; /* First 2 bytes are meaningful */
static const n2n_mac_t null_mac = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
typedef uint8_t n2n_community_t[N2N_COMMUNITY_SIZE];
typedef uint8_t n2n_private_public_key_t[N2N_PRIVATE_PUBLIC_KEY_SIZE];
typedef uint8_t n2n_mac_t[N2N_MAC_SIZE];
typedef uint32_t n2n_cookie_t;
typedef uint8_t n2n_desc_t[N2N_DESC_SIZE];
typedef char n2n_sock_str_t[N2N_SOCKBUF_SIZE]; /* tracing string buffer */
#if defined(_MSC_VER) || defined(__MINGW32__)
@ -125,6 +118,14 @@ typedef unsigned long in_addr_t;
#pragma pack(push,1)
#endif
// those are definitely not typedefs (with a view to the filename) but neither are they defines
static const n2n_mac_t broadcast_mac = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
static const n2n_mac_t multicast_mac = { 0x01, 0x00, 0x5E, 0x00, 0x00, 0x00 }; /* First 3 bytes are meaningful */
static const n2n_mac_t ipv6_multicast_mac = { 0x33, 0x33, 0x00, 0x00, 0x00, 0x00 }; /* First 2 bytes are meaningful */
static const n2n_mac_t null_mac = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
#define ETH_ADDR_LEN 6
struct ether_hdr {
@ -328,7 +329,7 @@ typedef struct n2n_REGISTER {
n2n_cookie_t cookie; /**< Link REGISTER and REGISTER_ACK */
n2n_mac_t srcMac; /**< MAC of registering party */
n2n_mac_t dstMac; /**< MAC of target edge */
n2n_sock_t sock; /**< REVISIT: unused? */
n2n_sock_t sock; /**< Supernode's view of edge socket OR edge's preferred local socket */
n2n_ip_subnet_t dev_addr; /**< IP address of the tuntap adapter. */
n2n_desc_t dev_desc; /**< Hint description correlated with the edge */
} n2n_REGISTER_t;
@ -408,6 +409,7 @@ typedef struct n2n_PEER_INFO {
n2n_mac_t srcMac;
n2n_mac_t mac;
n2n_sock_t sock;
n2n_sock_t preferred_sock;
SN_SELECTION_CRITERION_DATA_TYPE data;
} n2n_PEER_INFO_t;
@ -426,6 +428,8 @@ struct peer_info {
n2n_desc_t dev_desc;
n2n_sock_t sock;
SOCKET socket_fd;
n2n_sock_t preferred_sock;
time_t last_local_reg;
n2n_cookie_t last_cookie;
n2n_auth_t auth;
int timeout;
@ -647,6 +651,7 @@ typedef struct n2n_edge_conf {
int register_interval; /**< Interval for supernode registration, also used for UDP NAT hole punching. */
int register_ttl; /**< TTL for registration packet when UDP NAT hole punching through supernode. */
in_addr_t bind_address; /**< The address to bind to if provided (-b) */
n2n_sock_t preferred_sock; /**< propagated local sock for better p2p in LAN (-e) */
int local_port;
int mgmt_port;
uint8_t connect_tcp; /** connection to supernode 0 = UDP; 1 = TCP */

View File

@ -91,6 +91,15 @@ int decode_mac (n2n_mac_t out,
size_t * rem,
size_t * idx);
int encode_cookie (uint8_t * base,
size_t * idx,
const n2n_cookie_t c);
int decode_cookie (n2n_cookie_t * out,
const uint8_t * base,
size_t * rem,
size_t * idx);
int encode_common (uint8_t * base,
size_t * idx,
const n2n_common_t * common);

View File

@ -178,7 +178,7 @@ static void help (int level) {
"[-H] "
"[-z<compression>] "
"\n "
"[-S<level of solitude>] "
"[-e <preferred local IP address>] [-S<level of solitude>]"
"\n\n tap device and "
"[-a [static:|dhcp:]<tap IP address>[/<cidr suffix>]] "
"\n overlay network "
@ -254,6 +254,8 @@ static void help (int level) {
printf(" -D | enable PMTU discovery, it can reduce fragmentation but\n"
" | causes connections to stall if not properly supported\n");
#endif
printf(" -e <local ip> | advertises the provided local IP address as preferred,\n"
" | useful if multicast peer detection is not available\n");
printf(" -S1 ... -S2 | do not connect p2p, always use the supernode,\n"
" | -S1 = via UDP"
@ -612,6 +614,25 @@ static int setOption (int optkey, char *optargument, n2n_tuntap_priv_config_t *e
break;
}
case 'e': {
if(optargument) {
in_addr_t address_tmp = inet_addr(optargument);
memcpy(&(conf->preferred_sock.addr.v4), &(address_tmp), IPV4_SIZE);
if(address_tmp == INADDR_NONE) {
traceEvent(TRACE_WARNING, "bad address for preferred local socket, skipping");
conf->preferred_sock.family = AF_INVALID;
break;
} else {
conf->preferred_sock.family = AF_INET;
// port is set after parsing all cli parameters
}
}
break;
}
case 't': {
conf->mgmt_port = atoi(optargument);
break;
@ -747,7 +768,11 @@ static int loadFromCLI (int argc, char *argv[], n2n_edge_conf_t *conf, n2n_tunta
u_char c;
while ((c = getopt_long(argc, argv,
<<<<<<< HEAD
"k:a:c:Eu:g:m:M:s:d:l:p:fvhrt:i:I:J:P:S::DL:z::A::Hn:R:"
=======
"k:a:b:c:Eu:g:m:M:s:d:l:p:fvhrt:i:I:J:P:S::DL:z::A::Hn:R:e:"
>>>>>>> 9772d7b (first draft)
#ifdef __linux__
"T:"
#endif
@ -1042,6 +1067,18 @@ int main (int argc, char* argv[]) {
if(conf.encrypt_key && !strcmp((char*)conf.community_name, conf.encrypt_key))
traceEvent(TRACE_WARNING, "community and encryption key must differ, otherwise security will be compromised");
// so far, preferred local sock (-e) only works with a fixed port provided (-p)
if(conf.preferred_sock.family != AF_INVALID) {
conf.preferred_sock.port = conf.local_port;
if(conf.local_port == 0) {
traceEvent(TRACE_WARNING, "preferred local socket requires a port to be provided (-p), skipping");
conf.preferred_sock.family = AF_INVALID;
in_addr_t address_tmp = INADDR_NONE;
memcpy(&(conf.preferred_sock.addr.v4), &(address_tmp), IPV4_SIZE);
}
}
if((eee = edge_init(&conf, &rc)) == NULL) {
traceEvent(TRACE_ERROR, "failed in edge_init");
exit(1);

View File

@ -31,12 +31,13 @@ int resolve_check (n2n_resolve_parameter_t *param, uint8_t resolution_request, t
int resolve_cancel_thread (n2n_resolve_parameter_t *param);
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 send_register (n2n_edge_t *eee, const n2n_sock_t *remote_peer, const n2n_mac_t peer_mac, n2n_cookie_t cookie);
static void check_peer_registration_needed (n2n_edge_t *eee,
uint8_t from_supernode,
uint8_t via_multicast,
const n2n_mac_t mac,
const n2n_cookie_t cookie,
const n2n_ip_subnet_t *dev_addr,
const n2n_desc_t *dev_desc,
const n2n_sock_t *peer);
@ -59,23 +60,23 @@ static void check_known_peer_sock_change (n2n_edge_t *eee,
int edge_verify_conf (const n2n_edge_conf_t *conf) {
if(conf->community_name[0] == 0)
return(-1);
return -1;
// REVISIT: are the following two conditions equal? if so, remove one. but note that sn_num is used elsewhere
if(conf->sn_num == 0)
return(-2);
return -2;
if(HASH_COUNT(conf->supernodes) == 0)
return(-5);
return -5;
if(conf->register_interval < 1)
return(-3);
return -3;
if(((conf->encrypt_key == NULL) && (conf->transop_id != N2N_TRANSFORM_ID_NULL)) ||
((conf->encrypt_key != NULL) && (conf->transop_id == N2N_TRANSFORM_ID_NULL)))
return(-4);
return -4;
return(0);
return 0;
}
@ -530,7 +531,7 @@ static void register_with_local_peers (n2n_edge_t * eee) {
/* send registration to the local multicast group */
traceEvent(TRACE_DEBUG, "registering with multicast group %s:%u",
N2N_MULTICAST_GROUP, N2N_MULTICAST_PORT);
send_register(eee, &(eee->multicast_peer), NULL);
send_register(eee, &(eee->multicast_peer), NULL, N2N_LOCAL_REG_COOKIE);
}
#else
traceEvent(TRACE_DEBUG, "multicast peers discovery is disabled, skipping");
@ -627,18 +628,18 @@ static void register_with_new_peer (n2n_edge_t *eee,
(void *) (char *) &eee->conf.register_ttl,
sizeof(eee->conf.register_ttl));
for(; alter > 0; alter--, sock.port++) {
send_register(eee, &sock, mac);
send_register(eee, &sock, mac, N2N_REGULAR_REG_COOKIE);
}
setsockopt(eee->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, &(scan->sock), mac, N2N_REGULAR_REG_COOKIE);
}
send_register(eee, &(eee->curr_sn->sock), mac);
send_register(eee, &(eee->curr_sn->sock), mac, N2N_REGULAR_REG_COOKIE);
} else {
/* P2P register, send directly */
send_register(eee, &(scan->sock), mac);
send_register(eee, &(scan->sock), mac, N2N_REGULAR_REG_COOKIE);
}
register_with_local_peers(eee);
} else{
@ -659,6 +660,7 @@ static void check_peer_registration_needed (n2n_edge_t *eee,
uint8_t from_supernode,
uint8_t via_multicast,
const n2n_mac_t mac,
const n2n_cookie_t cookie,
const n2n_ip_subnet_t *dev_addr,
const n2n_desc_t *dev_desc,
const n2n_sock_t *peer) {
@ -671,10 +673,13 @@ static void check_peer_registration_needed (n2n_edge_t *eee,
if(scan == NULL ) {
scan = find_peer_by_sock(peer, eee->known_peers);
// MAC change
if(scan) {
HASH_DEL(eee->known_peers, scan);
memcpy(scan->mac_addr, mac, sizeof(n2n_mac_t));
HASH_ADD_PEER(eee->known_peers, scan);
// reset last_local_reg to allow re-registration
scan->last_local_reg = 0;
}
}
@ -691,12 +696,14 @@ static void check_peer_registration_needed (n2n_edge_t *eee,
if(via_multicast)
scan->local = 1;
if((now - scan->last_seen) > 0 /* >= 1 sec */) {
if(((now - scan->last_seen) > 0 /* >= 1 sec */)
||(cookie == N2N_LOCAL_REG_COOKIE)) {
/* Don't register too often */
check_known_peer_sock_change(eee, from_supernode, via_multicast, mac, dev_addr, dev_desc, peer, now);
}
}
}
/* ************************************** */
@ -706,6 +713,7 @@ static void check_peer_registration_needed (n2n_edge_t *eee,
*/
static void peer_set_p2p_confirmed (n2n_edge_t * eee,
const n2n_mac_t mac,
const n2n_cookie_t cookie,
const n2n_sock_t * peer,
time_t now) {
@ -716,6 +724,9 @@ static void peer_set_p2p_confirmed (n2n_edge_t * eee,
HASH_FIND_PEER(eee->pending_peers, mac, scan);
if(scan == NULL) {
scan = find_peer_by_sock(peer, eee->pending_peers);
// in case of MAC change, reset last_local_reg to allow re-registration
if(scan)
scan->last_local_reg = 0;
}
if(scan) {
@ -727,12 +738,20 @@ static void peer_set_p2p_confirmed (n2n_edge_t * eee,
free(scan);
scan = scan_tmp;
memcpy(scan->mac_addr, mac, sizeof(n2n_mac_t));
// in case of MAC change, reset last_local_reg to allow re-registration
scan->last_local_reg = 0;
} else {
scan->sock = *peer;
// ignore regular ACKs's socket update for a while if we have recently received a local (!) ACK
if(((now - scan->last_local_reg) > REGISTRATION_TIMEOUT)
||(cookie == N2N_LOCAL_REG_COOKIE)) {
scan->sock = *peer;
}
}
HASH_ADD_PEER(eee->known_peers, scan);
scan->last_p2p = now;
if(cookie == N2N_LOCAL_REG_COOKIE)
scan->last_local_reg = now;
traceEvent(TRACE_DEBUG, "p2p connection established: %s [%s]",
macaddr_str(mac_buf, mac),
@ -1159,12 +1178,17 @@ void send_register_super (n2n_edge_t *eee) {
cmn.ttl = N2N_DEFAULT_TTL;
cmn.pc = n2n_register_super;
cmn.flags = 0;
if(eee->conf.preferred_sock.family == (uint8_t)AF_INVALID) {
cmn.flags = 0;
} else {
cmn.flags = N2N_FLAGS_SOCKET;
memcpy(&(reg.sock), &(eee->conf.preferred_sock), sizeof(n2n_sock_t));
}
memcpy(cmn.community, eee->conf.community_name, N2N_COMMUNITY_SIZE);
memrnd(eee->curr_sn->last_cookie, N2N_COOKIE_SIZE);
eee->curr_sn->last_cookie = n2n_rand();
memcpy(reg.cookie, eee->curr_sn->last_cookie, N2N_COOKIE_SIZE);
reg.cookie = eee->curr_sn->last_cookie;
reg.dev_addr.net_addr = ntohl(eee->device.ip_addr);
reg.dev_addr.net_bitlen = mask2bitlen(ntohl(eee->device.device_mask));
memcpy(reg.dev_desc, eee->conf.dev_desc, N2N_DESC_SIZE);
@ -1282,7 +1306,8 @@ static int sort_supernodes (n2n_edge_t *eee, time_t now) {
/** Send a REGISTER packet to another edge. */
static void send_register (n2n_edge_t * eee,
const n2n_sock_t * remote_peer,
const n2n_mac_t peer_mac) {
const n2n_mac_t peer_mac,
const n2n_cookie_t cookie) {
uint8_t pktbuf[N2N_PKT_BUF_SIZE];
size_t idx;
@ -1303,8 +1328,7 @@ static void send_register (n2n_edge_t * eee,
cmn.flags = 0;
memcpy(cmn.community, eee->conf.community_name, N2N_COMMUNITY_SIZE);
idx = 0;
encode_uint32(reg.cookie, &idx, 123456789);
reg.cookie = cookie;
idx = 0;
encode_mac(reg.srcMac, &idx, eee->device.mac_addr);
@ -1358,7 +1382,7 @@ static void send_register_ack (n2n_edge_t * eee,
memcpy(cmn.community, eee->conf.community_name, N2N_COMMUNITY_SIZE);
memset(&ack, 0, sizeof(ack));
memcpy(ack.cookie, reg->cookie, N2N_COOKIE_SIZE);
ack.cookie = reg->cookie;
memcpy(ack.srcMac, eee->device.mac_addr, N2N_MAC_SIZE);
memcpy(ack.dstMac, reg->srcMac, N2N_MAC_SIZE);
@ -1510,7 +1534,7 @@ void update_supernode_reg (n2n_edge_t * eee, time_t now) {
if(eee->sn_wait == 1)
HASH_ITER(hh, eee->known_peers, peer, tmp_peer)
if((now - peer->last_seen) > REGISTER_SUPER_INTERVAL_DFL)
send_register(eee, &(peer->sock), peer->mac_addr);
send_register(eee, &(peer->sock), peer->mac_addr, N2N_REGULAR_REG_COOKIE);
eee->sn_wait = 1;
@ -1961,7 +1985,7 @@ static int check_query_peer_info (n2n_edge_t *eee, time_t now, n2n_mac_t mac) {
}
if(now - scan->last_sent_query > eee->conf.register_interval) {
send_register(eee, &(eee->curr_sn->sock), mac);
send_register(eee, &(eee->curr_sn->sock), mac, N2N_REGULAR_REG_COOKIE);
send_query_peer(eee, scan->mac_addr);
scan->last_sent_query = now;
return(0);
@ -2123,7 +2147,6 @@ void edge_send_packet2net (n2n_edge_t * eee,
memcpy(pkt.srcMac, eee->device.mac_addr, N2N_MAC_SIZE);
memcpy(pkt.dstMac, destMac, N2N_MAC_SIZE);
pkt.sock.family = 0; /* do not encode sock */
pkt.transform = tx_transop_idx;
// compression needs to be tried before encode_PACKET is called for compression indication gets encoded there
@ -2430,7 +2453,7 @@ void process_udp (n2n_edge_t *eee, const struct sockaddr_in *sender_sock, const
/* Update the sender in peer table entry */
check_peer_registration_needed(eee, from_supernode, via_multicast,
pkt.srcMac, NULL, NULL, orig_sender);
pkt.srcMac, N2N_REGULAR_REG_COOKIE, NULL, NULL, orig_sender);
handle_PACKET(eee, from_supernode, &pkt, orig_sender, udp_buf + idx, udp_size - idx);
break;
@ -2471,9 +2494,10 @@ void process_udp (n2n_edge_t *eee, const struct sockaddr_in *sender_sock, const
* a valid channel. We still use check_peer_registration_needed below
* to double check this.
*/
traceEvent(TRACE_INFO, "[p2p] Rx REGISTER from %s [%s]",
traceEvent(TRACE_INFO, "[p2p] Rx REGISTER from %s [%s]%s",
macaddr_str(mac_buf1, reg.srcMac),
sock_to_cstr(sockbuf1, &sender));
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 */
@ -2485,7 +2509,7 @@ void process_udp (n2n_edge_t *eee, const struct sockaddr_in *sender_sock, const
}
check_peer_registration_needed(eee, from_supernode, via_multicast,
reg.srcMac, &reg.dev_addr, (const n2n_desc_t*)&reg.dev_desc, orig_sender);
reg.srcMac, reg.cookie, &reg.dev_addr, (const n2n_desc_t*)&reg.dev_desc, orig_sender);
break;
}
@ -2505,13 +2529,17 @@ void process_udp (n2n_edge_t *eee, const struct sockaddr_in *sender_sock, const
if(is_valid_peer_sock(&ra.sock))
orig_sender = &(ra.sock);
traceEvent(TRACE_INFO, "Rx REGISTER_ACK from %s [%s] to %s via [%s]",
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));
sock_to_cstr(sockbuf1, &sender),
(ra.cookie == N2N_LOCAL_REG_COOKIE) ? " (local)" : "");
peer_set_p2p_confirmed(eee, ra.srcMac, &sender, now);
peer_set_p2p_confirmed(eee, ra.srcMac,
ra.cookie,
&sender, now);
break;
}
@ -2548,7 +2576,7 @@ void process_udp (n2n_edge_t *eee, const struct sockaddr_in *sender_sock, const
}
}
if(memcmp(ra.cookie, eee->curr_sn->last_cookie, N2N_COOKIE_SIZE)) {
if(ra.cookie != eee->curr_sn->last_cookie) {
traceEvent(TRACE_INFO, "Rx REGISTER_SUPER_ACK with wrong or old cookie");
return;
}
@ -2655,7 +2683,7 @@ void process_udp (n2n_edge_t *eee, const struct sockaddr_in *sender_sock, const
}
}
if(memcmp(nak.cookie, eee->curr_sn->last_cookie, N2N_COOKIE_SIZE)) {
if(nak.cookie != eee->curr_sn->last_cookie) {
traceEvent(TRACE_DEBUG, "Rx REGISTER_SUPER_NAK with wrong or old cookie");
return;
}
@ -2730,11 +2758,21 @@ void process_udp (n2n_edge_t *eee, const struct sockaddr_in *sender_sock, const
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));
send_register(eee, &scan->sock, scan->mac_addr);
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));
}
send_register(eee, &scan->sock, scan->mac_addr, N2N_REGULAR_REG_COOKIE);
} else {
traceEvent(TRACE_INFO, "Rx PEER_INFO unknown peer %s",
@ -3550,6 +3588,7 @@ void edge_init_conf_defaults (n2n_edge_conf_t *conf) {
conf->bind_address = INADDR_ANY; /* any address */
conf->local_port = 0 /* any port */;
conf->preferred_sock.family = AF_INVALID;
conf->mgmt_port = N2N_EDGE_MGMT_PORT; /* 5644 by default */
conf->transop_id = N2N_TRANSFORM_ID_NULL;
conf->header_encryption = HEADER_ENCRYPTION_NONE;

View File

@ -38,6 +38,7 @@ static int sendto_mgmt (n2n_sn_t *sss,
static uint16_t reg_lifetime (n2n_sn_t *sss);
static int update_edge (n2n_sn_t *sss,
const n2n_common_t* cmn,
const n2n_REGISTER_SUPER_t* reg,
struct sn_community *comm,
const n2n_sock_t *sender_sock,
@ -982,6 +983,7 @@ static int handle_remote_auth (n2n_sn_t *sss, const n2n_auth_t *remote_auth,
switch(remote_auth->scheme) {
// we do not handle n2n_auth_none because the edge always edge always uses either id or user/password
// auth_none is sn-internal only (skipping MAC/IP address spoofing protection)
case n2n_auth_none:
case n2n_auth_simple_id:
// zero_token answer
memset(answer_auth, 0, sizeof(n2n_auth_t));
@ -1020,6 +1022,7 @@ static int handle_remote_auth (n2n_sn_t *sss, const n2n_auth_t *remote_auth,
/** Update the edge table with the details of the edge which contacted the
* supernode. */
static int update_edge (n2n_sn_t *sss,
const n2n_common_t* cmn,
const n2n_REGISTER_SUPER_t* reg,
struct sn_community *comm,
const n2n_sock_t *sender_sock,
@ -1063,8 +1066,13 @@ static int update_edge (n2n_sn_t *sss,
memcpy((char*)scan->dev_desc, reg->dev_desc, N2N_DESC_SIZE);
memcpy(&(scan->sock), sender_sock, sizeof(n2n_sock_t));
scan->socket_fd = socket_fd;
memcpy(&(scan->last_cookie), reg->cookie, sizeof(N2N_COOKIE_SIZE));
scan->last_cookie = reg->cookie;
scan->last_valid_time_stamp = initial_time_stamp();
// eventually, store edge's preferred local socket from REGISTER_SUPER
if(cmn->flags & N2N_FLAGS_SOCKET)
memcpy(&scan->preferred_sock, &reg->sock, sizeof(n2n_sock_t));
else
scan->preferred_sock.family = AF_INVALID;
// store the submitted auth token
memcpy(&(scan->auth), &(reg->auth), sizeof(n2n_auth_t));
@ -1090,14 +1098,19 @@ static int update_edge (n2n_sn_t *sss,
if(!sock_equal(sender_sock, &(scan->sock))) {
memcpy(&(scan->sock), sender_sock, sizeof(n2n_sock_t));
scan->socket_fd = socket_fd;
memcpy(&(scan->last_cookie), reg->cookie, sizeof(N2N_COOKIE_SIZE));
scan->last_cookie = reg->cookie;
// eventually, update edge's preferred local socket from REGISTER_SUPER
if(cmn->flags & N2N_FLAGS_SOCKET)
memcpy(&scan->preferred_sock, &reg->sock, sizeof(n2n_sock_t));
else
scan->preferred_sock.family = AF_INVALID;
traceEvent(TRACE_INFO, "updated edge %s ==> %s",
macaddr_str(mac_buf, reg->edgeMac),
sock_to_cstr(sockbuf, sender_sock));
ret = update_edge_sock_change;
} else {
memcpy(&(scan->last_cookie), reg->cookie, sizeof(N2N_COOKIE_SIZE));
scan->last_cookie = reg->cookie;
traceEvent(TRACE_DEBUG, "edge unchanged %s ==> %s",
macaddr_str(mac_buf, reg->edgeMac),
@ -1355,9 +1368,8 @@ static int re_register_and_purge_supernodes (n2n_sn_t *sss, struct sn_community
cmn.flags = N2N_FLAGS_FROM_SUPERNODE;
memcpy(cmn.community, comm->community, N2N_COMMUNITY_SIZE);
memrnd(cookie, N2N_COOKIE_SIZE);
memcpy(reg.cookie, cookie, N2N_COOKIE_SIZE);
memcpy(peer->last_cookie, cookie, N2N_COOKIE_SIZE);
reg.cookie = n2n_rand();
peer->last_cookie = reg.cookie;
reg.dev_addr.net_addr = ntohl(peer->dev_addr.net_addr);
reg.dev_addr.net_bitlen = mask2bitlen(ntohl(peer->dev_addr.net_bitlen));
@ -2075,7 +2087,7 @@ static int process_udp (n2n_sn_t * sss,
cmn2.flags = N2N_FLAGS_SOCKET | N2N_FLAGS_FROM_SUPERNODE;
memcpy(cmn2.community, cmn.community, sizeof(n2n_community_t));
memcpy(&(ack.cookie), &(reg.cookie), sizeof(n2n_cookie_t));
ack.cookie = reg.cookie;
memcpy(ack.srcMac, sss->mac_addr, sizeof(n2n_mac_t));
if(comm->is_federation != IS_FEDERATION) { /* alternatively, do not send zero tap ip address in federation REGISTER_SUPER */
@ -2115,7 +2127,7 @@ static int process_udp (n2n_sn_t * sss,
skip--;
continue;
}
if(peer->sock.family == AF_INVALID)
if(peer->sock.family == (uint8_t)AF_INVALID)
continue; /* do not add unresolved supernodes to payload */
if(memcmp(&(peer->sock), &(ack.sock), sizeof(n2n_sock_t)) == 0) continue; /* a supernode doesn't add itself to the payload */
if((now - peer->last_seen) >= LAST_SEEN_SN_NEW) continue; /* skip long-time-not-seen supernodes.
@ -2136,18 +2148,18 @@ static int process_udp (n2n_sn_t * sss,
// check authentication
ret_value = update_edge_no_change;
if(comm->is_federation != IS_FEDERATION) { /* REVISIT: auth among supernodes is not implemented yet */
if(cmn.flags & N2N_FLAGS_SOCKET) {
ret_value = update_edge(sss, &reg, comm, &(ack.sock), socket_fd, &(ack.auth), SN_ADD_SKIP, now);
if(cmn.flags & N2N_FLAGS_FROM_SUPERNODE) {
ret_value = update_edge(sss, &cmn, &reg, comm, &(ack.sock), socket_fd, &(ack.auth), SN_ADD_SKIP, now);
} else {
// do not add in case of null mac (edge asking for ip address)
ret_value = update_edge(sss, &reg, comm, &(ack.sock), socket_fd, &(ack.auth), is_null_mac(reg.edgeMac) ? SN_ADD_SKIP : SN_ADD, now);
ret_value = update_edge(sss, &cmn, &reg, comm, &(ack.sock), socket_fd, &(ack.auth), is_null_mac(reg.edgeMac) ? SN_ADD_SKIP : SN_ADD, now);
}
}
if(ret_value == update_edge_auth_fail) {
// send REGISTER_SUPER_NAK
cmn2.pc = n2n_register_super_nak;
memcpy(&(nak.cookie), &(reg.cookie), sizeof(n2n_cookie_t));
nak.cookie = reg.cookie;
memcpy(nak.srcMac, reg.edgeMac, sizeof(n2n_mac_t));
encode_REGISTER_SUPER_NAK(ackbuf, &encx, &cmn2, &nak);
@ -2166,8 +2178,9 @@ static int process_udp (n2n_sn_t * sss,
traceEvent(TRACE_DEBUG, "Tx REGISTER_SUPER_NAK for %s",
macaddr_str(mac_buf, reg.edgeMac));
} else {
// if this is not already forwarded from a supernode, ...
if(!(cmn.flags & N2N_FLAGS_SOCKET)) {
// 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
@ -2360,7 +2373,7 @@ static int process_udp (n2n_sn_t * sss,
break;
}
if(0 == memcmp(ack.cookie, scan->last_cookie, N2N_COOKIE_SIZE)) {
if(ack.cookie == scan->last_cookie) {
payload = (n2n_REGISTER_SUPER_ACK_payload_t *)dec_tmpbuf;
for(i = 0; i < ack.num_sn; i++) {
@ -2568,6 +2581,10 @@ static int process_udp (n2n_sn_t * sss,
memcpy(pi.srcMac, query.srcMac, sizeof(n2n_mac_t));
memcpy(pi.mac, query.targetMac, sizeof(n2n_mac_t));
pi.sock = scan->sock;
if(scan->preferred_sock.family != (uint8_t)AF_INVALID) {
cmn2.flags |= N2N_FLAGS_SOCKET;
pi.preferred_sock = scan->preferred_sock;
}
encode_PEER_INFO(encbuf, &encx, &cmn2, &pi);

View File

@ -171,15 +171,14 @@ int decode_buf (uint8_t * out,
}
int encode_mac (uint8_t * base,
int encode_mac (uint8_t * base, /* n2n_mac_t is typedefed array type which is always passed by reference */
size_t * idx,
const n2n_mac_t m) {
return encode_buf(base, idx, m, N2N_MAC_SIZE);
}
int decode_mac (n2n_mac_t out, /* n2n_mac_t is typedefed array type which is always passed by reference */
int decode_mac (n2n_mac_t out,
const uint8_t * base,
size_t * rem,
size_t * idx) {
@ -187,6 +186,20 @@ int decode_mac (n2n_mac_t out, /* n2n_mac_t is typedefed array type which is alw
return decode_buf(out, N2N_MAC_SIZE, base, rem, idx);
}
int encode_cookie (uint8_t * base,
size_t * idx,
const n2n_cookie_t c) {
return encode_uint32(base, idx, c);
}
int decode_cookie (n2n_cookie_t * out, /* cookies are typedef'd as uint32_t which needs to correspond to this code */
const uint8_t * base,
size_t * rem,
size_t * idx) {
return decode_uint32(out, base, rem, idx);
}
int encode_common (uint8_t * base,
@ -300,10 +313,10 @@ int encode_REGISTER (uint8_t *base,
int retval = 0;
retval += encode_common(base, idx, common);
retval += encode_buf(base, idx, reg->cookie, N2N_COOKIE_SIZE);
retval += encode_cookie(base, idx, reg->cookie);
retval += encode_mac(base, idx, reg->srcMac);
retval += encode_mac(base, idx, reg->dstMac);
if(0 != reg->sock.family) {
if(common->flags & N2N_FLAGS_SOCKET) {
retval += encode_sock(base, idx, &(reg->sock));
}
retval += encode_uint32(base, idx, reg->dev_addr.net_addr);
@ -323,7 +336,7 @@ int decode_REGISTER (n2n_REGISTER_t *reg,
size_t retval = 0;
memset(reg, 0, sizeof(n2n_REGISTER_t));
retval += decode_buf(reg->cookie, N2N_COOKIE_SIZE, base, rem, idx);
retval += decode_cookie(&reg->cookie, 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) {
@ -345,9 +358,9 @@ int encode_REGISTER_SUPER (uint8_t *base,
int retval = 0;
retval += encode_common(base, idx, common);
retval += encode_buf(base, idx, reg->cookie, N2N_COOKIE_SIZE);
retval += encode_cookie(base, idx, reg->cookie);
retval += encode_mac(base, idx, reg->edgeMac);
if(0 != reg->sock.family) {
if(common->flags & N2N_FLAGS_SOCKET) {
retval += encode_sock(base, idx, &(reg->sock));
}
retval += encode_uint32(base, idx, reg->dev_addr.net_addr);
@ -371,7 +384,7 @@ int decode_REGISTER_SUPER (n2n_REGISTER_SUPER_t *reg,
size_t retval = 0;
memset(reg, 0, sizeof(n2n_REGISTER_SUPER_t));
retval += decode_buf(reg->cookie, N2N_COOKIE_SIZE, base, rem, idx);
retval += decode_cookie(&reg->cookie, base, rem, idx);
retval += decode_mac(reg->edgeMac, base, rem, idx);
if(cmn->flags & N2N_FLAGS_SOCKET) {
retval += decode_sock(&(reg->sock), base, rem, idx);
@ -431,14 +444,14 @@ int encode_REGISTER_ACK (uint8_t *base,
int retval = 0;
retval += encode_common(base, idx, common);
retval += encode_buf(base, idx, reg->cookie, N2N_COOKIE_SIZE);
retval += encode_cookie(base, idx, reg->cookie);
retval += encode_mac(base, idx, reg->dstMac);
retval += encode_mac(base, idx, reg->srcMac);
/* The socket in REGISTER_ACK is the socket from which the REGISTER
* arrived. This is sent back to the sender so it knows what its public
* socket is. */
if(0 != reg->sock.family) {
if(common->flags & N2N_FLAGS_SOCKET) {
retval += encode_sock(base, idx, &(reg->sock));
}
@ -455,7 +468,7 @@ int decode_REGISTER_ACK (n2n_REGISTER_ACK_t *reg,
size_t retval = 0;
memset(reg, 0, sizeof(n2n_REGISTER_ACK_t));
retval += decode_buf(reg->cookie, N2N_COOKIE_SIZE, base, rem, idx);
retval += decode_cookie(&reg->cookie, base, rem, idx);
retval += decode_mac(reg->dstMac, base, rem, idx);
retval += decode_mac(reg->srcMac, base, rem, idx);
@ -479,7 +492,7 @@ int encode_REGISTER_SUPER_ACK (uint8_t *base,
int retval = 0;
retval += encode_common(base, idx, common);
retval += encode_buf(base, idx, reg->cookie, N2N_COOKIE_SIZE);
retval += encode_cookie(base, idx, reg->cookie);
retval += encode_mac(base, idx, reg->srcMac);
retval += encode_uint32(base, idx, reg->dev_addr.net_addr);
retval += encode_uint8(base, idx, reg->dev_addr.net_bitlen);
@ -510,7 +523,7 @@ int decode_REGISTER_SUPER_ACK (n2n_REGISTER_SUPER_ACK_t *reg,
size_t retval = 0;
memset(reg, 0, sizeof(n2n_REGISTER_SUPER_ACK_t));
retval += decode_buf(reg->cookie, N2N_COOKIE_SIZE, base, rem, idx);
retval += decode_cookie(&reg->cookie, base, rem, idx);
retval += decode_mac(reg->srcMac, 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);
@ -541,7 +554,7 @@ int encode_REGISTER_SUPER_NAK (uint8_t *base,
int retval = 0;
retval += encode_common(base, idx, common);
retval += encode_buf(base, idx, nak->cookie, N2N_COOKIE_SIZE);
retval += encode_cookie(base, idx, nak->cookie);
retval += encode_mac(base, idx, nak->srcMac);
retval += encode_uint16(base, idx, nak->auth.scheme);
@ -561,7 +574,7 @@ int decode_REGISTER_SUPER_NAK (n2n_REGISTER_SUPER_NAK_t *nak,
size_t retval = 0;
memset(nak, 0, sizeof(n2n_REGISTER_SUPER_NAK_t));
retval += decode_buf(nak->cookie, N2N_COOKIE_SIZE, base, rem, idx);
retval += decode_cookie(&nak->cookie, base, rem, idx);
retval += decode_mac(nak->srcMac, base, rem, idx);
retval += decode_uint16(&(nak->auth.scheme), base, rem, idx);
@ -602,7 +615,7 @@ int encode_PACKET (uint8_t * base,
retval += encode_common(base, idx, common);
retval += encode_mac(base, idx, pkt->srcMac);
retval += encode_mac(base, idx, pkt->dstMac);
if(0 != pkt->sock.family) {
if(common->flags & N2N_FLAGS_SOCKET) {
retval += encode_sock(base, idx, &(pkt->sock));
}
retval += encode_uint8(base, idx, pkt->compression);
@ -637,16 +650,19 @@ int decode_PACKET (n2n_PACKET_t * pkt,
int encode_PEER_INFO (uint8_t *base,
size_t *idx,
const n2n_common_t *common,
const n2n_common_t *cmn,
const n2n_PEER_INFO_t *pkt) {
int retval = 0;
retval += encode_common(base, idx, common);
retval += encode_common(base, idx, cmn);
retval += encode_uint16(base, idx, pkt->aflags);
retval += encode_mac(base, idx, pkt->srcMac);
retval += encode_mac(base, idx, pkt->mac);
retval += encode_sock(base, idx, &pkt->sock);
if(cmn->flags & N2N_FLAGS_SOCKET) {
retval += encode_sock(base, idx, &pkt->preferred_sock);
}
retval += encode_buf(base, idx, &pkt->data, sizeof(SN_SELECTION_CRITERION_DATA_TYPE));
return retval;
@ -666,6 +682,9 @@ int decode_PEER_INFO (n2n_PEER_INFO_t *pkt,
retval += decode_mac(pkt->srcMac, base, rem, idx);
retval += decode_mac(pkt->mac, base, rem, idx);
retval += decode_sock(&pkt->sock, base, rem, idx);
if(cmn->flags & N2N_FLAGS_SOCKET) {
retval += decode_sock(&pkt->preferred_sock, base, rem, idx);
}
retval += decode_buf((uint8_t*)&pkt->data, sizeof(SN_SELECTION_CRITERION_DATA_TYPE), base, rem, idx);
return retval;