diff --git a/src/net_packet.c b/src/net_packet.c index 2a5ae86f..138949a5 100644 --- a/src/net_packet.c +++ b/src/net_packet.c @@ -1255,8 +1255,12 @@ void send_packet(node_t *n, vpn_packet_t *packet) { // If it's for myself, write it to the tun/tap device. if(n == myself) { - if(overwrite_mac) + if(overwrite_mac) { memcpy(DATA(packet), mymac.x, ETH_ALEN); + // Use an arbitrary fake source address. + memcpy(DATA(packet) + ETH_ALEN, DATA(packet), ETH_ALEN); + DATA(packet)[ETH_ALEN * 2 - 1] ^= 0xFF; + } n->out_packets++; n->out_bytes += packet->len; devops.write(packet); diff --git a/src/node.c b/src/node.c index 9597aaf8..d428ddae 100644 --- a/src/node.c +++ b/src/node.c @@ -34,8 +34,7 @@ splay_tree_t *node_tree; static splay_tree_t *node_id_tree; -static hash_t *node_udp_cache; -static hash_t *node_id_cache; +static splay_tree_t *node_udp_tree; node_t *myself; @@ -47,16 +46,21 @@ static int node_id_compare(const node_t *a, const node_t *b) { return memcmp(&a->id, &b->id, sizeof(node_id_t)); } +static int node_udp_compare(const node_t *a, const node_t *b) { + int result = sockaddrcmp(&a->address, &b->address); + if (result) + return result; + return (a->name && b->name) ? strcmp(a->name, b->name) : 0; +} + void init_nodes(void) { node_tree = splay_alloc_tree((splay_compare_t) node_compare, (splay_action_t) free_node); node_id_tree = splay_alloc_tree((splay_compare_t) node_id_compare, NULL); - node_udp_cache = hash_alloc(0x100, sizeof(sockaddr_t)); - node_id_cache = hash_alloc(0x100, sizeof(node_id_t)); + node_udp_tree = splay_alloc_tree((splay_compare_t) node_udp_compare, NULL); } void exit_nodes(void) { - hash_free(node_id_cache); - hash_free(node_udp_cache); + splay_delete_tree(node_udp_tree); splay_delete_tree(node_id_tree); splay_delete_tree(node_tree); } @@ -116,8 +120,7 @@ void node_add(node_t *n) { } void node_del(node_t *n) { - hash_delete(node_udp_cache, &n->address); - hash_delete(node_id_cache, &n->id); + splay_delete(node_udp_tree, n); for splay_each(subnet_t, s, n->subnet_tree) subnet_del(n, s); @@ -139,19 +142,13 @@ node_t *lookup_node(char *name) { } node_t *lookup_node_id(const node_id_t *id) { - node_t *n = hash_search(node_id_cache, id); - if(!n) { - node_t tmp = {.id = *id}; - n = splay_search(node_id_tree, &tmp); - if(n) - hash_insert(node_id_cache, id, n); - } - - return n; + node_t n = {.id = *id}; + return splay_search(node_id_tree, &n); } node_t *lookup_node_udp(const sockaddr_t *sa) { - return hash_search(node_udp_cache, sa); + node_t tmp = {.address = *sa}; + return splay_search(node_udp_tree, &tmp); } void update_node_udp(node_t *n, const sockaddr_t *sa) { @@ -160,7 +157,7 @@ void update_node_udp(node_t *n, const sockaddr_t *sa) { return; } - hash_delete(node_udp_cache, &n->address); + splay_delete(node_udp_tree, n); if(sa) { n->address = *sa; @@ -171,7 +168,7 @@ void update_node_udp(node_t *n, const sockaddr_t *sa) { break; } } - hash_insert(node_udp_cache, sa, n); + splay_insert(node_udp_tree, n); free(n->hostname); n->hostname = sockaddr2hostname(&n->address); logger(DEBUG_PROTOCOL, LOG_DEBUG, "UDP address of %s set to %s", n->name, n->hostname); diff --git a/src/route.c b/src/route.c index 9f7e1508..04a0b5b6 100644 --- a/src/route.c +++ b/src/route.c @@ -837,15 +837,13 @@ static void route_arp(node_t *source, vpn_packet_t *packet) { if(subnet->owner == myself) return; /* silently ignore */ - memcpy(DATA(packet), DATA(packet) + ETH_ALEN, ETH_ALEN); /* copy destination address */ - DATA(packet)[ETH_ALEN * 2 - 1] ^= 0xFF; /* mangle source address so it looks like it's not from us */ - memcpy(&addr, arp.arp_tpa, sizeof addr); /* save protocol addr */ memcpy(arp.arp_tpa, arp.arp_spa, sizeof addr); /* swap destination and source protocol address */ memcpy(arp.arp_spa, &addr, sizeof addr); /* ... */ memcpy(arp.arp_tha, arp.arp_sha, ETH_ALEN); /* set target hard/proto addr */ - memcpy(arp.arp_sha, DATA(packet) + ETH_ALEN, ETH_ALEN); /* add fake source hard addr */ + memcpy(arp.arp_sha, DATA(packet) + ETH_ALEN, ETH_ALEN); /* set source hard/proto addr */ + arp.arp_sha[ETH_ALEN - 1] ^= 0xFF; /* for consistency with route_packet() */ arp.arp_op = htons(ARPOP_REPLY); /* Copy structs on stack back to packet */