X-Git-Url: https://tinc-vpn.org/git/browse?a=blobdiff_plain;f=src%2Fnet_packet.c;h=6d417471952c727ded010c48a1413d6fee433916;hb=e16ade874d08f82481dca7302b98305bcfbe27cf;hp=ecdcfe203e9b7e39937d9832c99d2aa56c4aa26b;hpb=66f325f4674e70d83744626f3b8dda6760f8d613;p=tinc diff --git a/src/net_packet.c b/src/net_packet.c index ecdcfe20..6d417471 100644 --- a/src/net_packet.c +++ b/src/net_packet.c @@ -144,14 +144,14 @@ static void send_mtu_probe_handler(void *data) { randomize(packet.data + 14, len - 14); packet.len = len; packet.priority = 0; - n->status.broadcast = i >= 4 && n->mtuprobes <= 10 && n->prevedge; + n->status.send_locally = i >= 4 && n->mtuprobes <= 10 && n->prevedge; logger(DEBUG_TRAFFIC, LOG_INFO, "Sending MTU probe length %d to %s (%s)", len, n->name, n->hostname); send_udppacket(n, &packet); } - n->status.broadcast = false; + n->status.send_locally = false; n->probe_counter = 0; gettimeofday(&n->probe_time, NULL); @@ -378,7 +378,7 @@ static void receive_udppacket(node_t *n, vpn_packet_t *inpkt) { return; } - if(!cipher_active(n->incipher)) { + if(!n->status.validkey) { logger(DEBUG_TRAFFIC, LOG_DEBUG, "Got packet from %s (%s) but he hasn't got our key yet", n->name, n->hostname); return; } @@ -544,6 +544,18 @@ static void send_sptps_packet(node_t *n, vpn_packet_t *origpkt) { return; } +static void adapt_socket(const sockaddr_t *sa, int *sock) { + /* Make sure we have a suitable socket for the chosen address */ + if(listen_socket[*sock].sa.sa.sa_family != sa->sa.sa_family) { + for(int i = 0; i < listen_sockets; i++) { + if(listen_socket[i].sa.sa.sa_family == sa->sa.sa_family) { + *sock = i; + break; + } + } + } +} + static void choose_udp_address(const node_t *n, const sockaddr_t **sa, int *sock) { /* Latest guess */ *sa = &n->address; @@ -582,18 +594,32 @@ static void choose_udp_address(const node_t *n, const sockaddr_t **sa, int *sock *sock = rand() % listen_sockets; } - /* Make sure we have a suitable socket for the chosen address */ - if(listen_socket[*sock].sa.sa.sa_family != (*sa)->sa.sa_family) { - for(int i = 0; i < listen_sockets; i++) { - if(listen_socket[i].sa.sa.sa_family == (*sa)->sa.sa_family) { - *sock = i; - break; - } + adapt_socket(*sa, sock); +} + +static void choose_local_address(const node_t *n, const sockaddr_t **sa, int *sock) { + /* Pick one of the edges from this node at random, then use its local address. */ + + int i = 0; + int j = rand() % n->edge_tree->count; + edge_t *candidate = NULL; + + for splay_each(edge_t, e, n->edge_tree) { + if(i++ == j) { + candidate = e; + break; } } -} -static void choose_broadcast_address(const node_t *n, const sockaddr_t **sa, int *sock) { + if (candidate && candidate->local_address.sa.sa_family) { + *sa = &candidate->local_address; + *sock = rand() % listen_sockets; + adapt_socket(*sa, sock); + return; + } + + /* No candidate? Use broadcasts instead. */ + static sockaddr_t broadcast_ipv4 = { .in = { .sin_family = AF_INET, @@ -733,8 +759,8 @@ static void send_udppacket(node_t *n, vpn_packet_t *origpkt) { const sockaddr_t *sa; int sock; - if(n->status.broadcast) - choose_broadcast_address(n, &sa, &sock); + if(n->status.send_locally) + choose_local_address(n, &sa, &sock); else choose_udp_address(n, &sa, &sock); @@ -744,7 +770,7 @@ static void send_udppacket(node_t *n, vpn_packet_t *origpkt) { priority = origpriority; logger(DEBUG_TRAFFIC, LOG_DEBUG, "Setting outgoing packet priority to %d", priority); if(setsockopt(listen_socket[n->sock].udp.fd, SOL_IP, IP_TOS, &priority, sizeof(priority))) /* SO_PRIORITY doesn't seem to work */ - logger(DEBUG_ALWAYS, LOG_ERR, "System call `%s' failed: %s", "setsockopt", strerror(errno)); + logger(DEBUG_ALWAYS, LOG_ERR, "System call `%s' failed: %s", "setsockopt", sockstrerror(sockerrno)); } #endif @@ -785,8 +811,8 @@ bool send_sptps_data(void *handle, uint8_t type, const char *data, size_t len) { const sockaddr_t *sa; int sock; - if(to->status.broadcast) - choose_broadcast_address(to, &sa, &sock); + if(to->status.send_locally) + choose_local_address(to, &sa, &sock); else choose_udp_address(to, &sa, &sock);