X-Git-Url: https://tinc-vpn.org/git/browse?a=blobdiff_plain;f=src%2Fnet_packet.c;h=81ca70a4c97031a6f13664770592d67b150d92ca;hb=6bc5d626a8726fc23365ee705761a3c666a08ad4;hp=dbf361fd38fe2c41b4484763045d266545c7be84;hpb=f57129ce3439f3826c12f15feb5df05e5ad8cab9;p=tinc diff --git a/src/net_packet.c b/src/net_packet.c index dbf361fd..81ca70a4 100644 --- a/src/net_packet.c +++ b/src/net_packet.c @@ -77,7 +77,7 @@ bool localdiscovery = false; which will be broadcast to the local network. */ -static void send_mtu_probe_handler(int fd, short events, void *data) { +static void send_mtu_probe_handler(void *data) { node_t *n = data; int timeout = 1; @@ -151,24 +151,38 @@ static void send_mtu_probe_handler(int fd, short events, void *data) { } end: - event_add(&n->mtuevent, &(struct timeval){timeout, rand() % 100000}); + timeout_set(&n->mtutimeout, &(struct timeval){timeout, rand() % 100000}); } void send_mtu_probe(node_t *n) { - if(!timeout_initialized(&n->mtuevent)) - timeout_set(&n->mtuevent, send_mtu_probe_handler, n); - send_mtu_probe_handler(0, 0, n); + timeout_add(&n->mtutimeout, send_mtu_probe_handler, n, &(struct timeval){1, 0}); + send_mtu_probe_handler(n); } static void mtu_probe_h(node_t *n, vpn_packet_t *packet, length_t len) { logger(DEBUG_TRAFFIC, LOG_INFO, "Got MTU probe length %d from %s (%s)", packet->len, n->name, n->hostname); if(!packet->data[0]) { + /* It's a probe request, send back a reply */ + packet->data[0] = 1; + + /* Temporarily set udp_confirmed, so that the reply is sent + back exactly the way it came in. */ + + bool udp_confirmed = n->status.udp_confirmed; + n->status.udp_confirmed = true; send_udppacket(n, packet); + n->status.udp_confirmed = udp_confirmed; } else { + /* It's a valid reply: now we know bidirectional communication + is possible using the address and socket that the reply + packet used. */ + n->status.udp_confirmed = true; + /* If we haven't established the PMTU yet, restart the discovery process. */ + if(n->mtuprobes > 30) { if(n->minmtu) n->mtuprobes = 30; @@ -176,6 +190,8 @@ static void mtu_probe_h(node_t *n, vpn_packet_t *packet, length_t len) { n->mtuprobes = 1; } + /* If applicable, raise the minimum supported MTU */ + if(len > n->maxmtu) len = n->maxmtu; if(n->minmtu < len) @@ -447,24 +463,28 @@ static void choose_udp_address(const node_t *n, const sockaddr_t **sa, int *sock if(n->status.udp_confirmed) return; - /* Otherwise, go through the list of known addresses of - this node. The first address we try is always the - one in n->address; that could be set to the node's - reflexive UDP address discovered during key - exchange. The other known addresses are those found - in edges to this node. */ + /* Send every third packet to n->address; that could be set + to the node's reflexive UDP address discovered during key + exchange. */ + static int x = 0; + if(++x >= 3) { + x = 0; + return; + } + + /* Otherwise, address are found in edges to this node. + So we pick a random edge and a random socket. */ int i = 0; int j = rand() % n->edge_tree->count; edge_t *candidate = NULL; - for splay_each(edge_t, e, edge_weight_tree) { - if(e->to != n) - continue; - i++; - if(!candidate || i == j) - candidate = e; + for splay_each(edge_t, e, n->edge_tree) { + if(i++ == j) { + candidate = e->reverse; + break; + } } if(candidate) { @@ -536,15 +556,13 @@ static void send_udppacket(node_t *n, vpn_packet_t *origpkt) { /* Make sure we have a valid key */ if(!n->status.validkey) { - time_t now = time(NULL); - logger(DEBUG_TRAFFIC, LOG_INFO, "No valid key known yet for %s (%s), forwarding via TCP", n->name, n->hostname); - if(n->last_req_key + 10 <= now) { + if(n->last_req_key + 10 <= now.tv_sec) { send_req_key(n); - n->last_req_key = now; + n->last_req_key = now.tv_sec; } send_tcppacket(n->nexthop->connection, origpkt); @@ -623,12 +641,12 @@ static void send_udppacket(node_t *n, vpn_packet_t *origpkt) { && listen_socket[n->sock].sa.sa.sa_family == AF_INET) { priority = origpriority; logger(DEBUG_TRAFFIC, LOG_DEBUG, "Setting outgoing packet priority to %d", priority); - if(setsockopt(listen_socket[n->sock].udp, SOL_IP, IP_TOS, &priority, sizeof(priority))) /* SO_PRIORITY doesn't seem to work */ + 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)); } #endif - if(sendto(listen_socket[sock].udp, (char *) &inpkt->seqno, inpkt->len, 0, &sa->sa, SALEN(sa->sa)) < 0 && !sockwouldblock(sockerrno)) { + if(sendto(listen_socket[sock].udp.fd, (char *) &inpkt->seqno, inpkt->len, 0, &sa->sa, SALEN(sa->sa)) < 0 && !sockwouldblock(sockerrno)) { if(sockmsgsize(sockerrno)) { if(n->maxmtu >= origlen) n->maxmtu = origlen - 1; @@ -665,7 +683,7 @@ bool send_sptps_data(void *handle, uint8_t type, const char *data, size_t len) { choose_udp_address(to, &sa, &sock); - if(sendto(listen_socket[sock].udp, data, len, 0, &sa->sa, SALEN(sa->sa)) < 0 && !sockwouldblock(sockerrno)) { + if(sendto(listen_socket[sock].udp.fd, data, len, 0, &sa->sa, SALEN(sa->sa)) < 0 && !sockwouldblock(sockerrno)) { if(sockmsgsize(sockerrno)) { if(to->maxmtu >= len) to->maxmtu = len - 1; @@ -848,14 +866,13 @@ static node_t *try_harder(const sockaddr_t *from, const vpn_packet_t *pkt) { node_t *n = NULL; bool hard = false; static time_t last_hard_try = 0; - time_t now = time(NULL); for splay_each(edge_t, e, edge_weight_tree) { if(!e->to->status.reachable || e->to == myself) continue; if(sockaddrcmp_noport(from, &e->address)) { - if(last_hard_try == now) + if(last_hard_try == now.tv_sec) continue; hard = true; } @@ -868,13 +885,14 @@ static node_t *try_harder(const sockaddr_t *from, const vpn_packet_t *pkt) { } if(hard) - last_hard_try = now; + last_hard_try = now.tv_sec; - last_hard_try = now; + last_hard_try = now.tv_sec; return n; } -void handle_incoming_vpn_data(int sock, short events, void *data) { +void handle_incoming_vpn_data(void *data, int flags) { + listen_socket_t *ls = data; vpn_packet_t pkt; char *hostname; sockaddr_t from = {{0}}; @@ -882,7 +900,7 @@ void handle_incoming_vpn_data(int sock, short events, void *data) { node_t *n; int len; - len = recvfrom(sock, (char *) &pkt.seqno, MAXSIZE, 0, &from.sa, &fromlen); + len = recvfrom(ls->udp.fd, (char *) &pkt.seqno, MAXSIZE, 0, &from.sa, &fromlen); if(len <= 0 || len > MAXSIZE) { if(!sockwouldblock(sockerrno)) @@ -910,12 +928,12 @@ void handle_incoming_vpn_data(int sock, short events, void *data) { return; } - n->sock = (intptr_t)data; + n->sock = ls - listen_socket; receive_udppacket(n, &pkt); } -void handle_device_data(int sock, short events, void *data) { +void handle_device_data(void *data, int flags) { vpn_packet_t packet; packet.priority = 0;