Fix protocol version check for type 2 MTU probe replies.
[tinc] / src / net_packet.c
index 6d41747..b9f1957 100644 (file)
@@ -54,8 +54,7 @@ static char lzo_wrkmem[LZO1X_999_MEM_COMPRESS > LZO1X_1_MEM_COMPRESS ? LZO1X_999
 static void send_udppacket(node_t *, vpn_packet_t *);
 
 unsigned replaywin = 16;
-bool localdiscovery = false;
-sockaddr_t localdiscovery_address;
+bool localdiscovery = true;
 
 #define MAX_SEQNO 1073741824
 
@@ -183,7 +182,7 @@ static void mtu_probe_h(node_t *n, vpn_packet_t *packet, length_t len) {
                /* It's a probe request, send back a reply */
 
                /* Type 2 probe replies were introduced in protocol 17.3 */
-               if ((n->options >> 24) == 3) {
+               if ((n->options >> 24) >= 3) {
                        uint8_t* data = packet->data;
                        *data++ = 2;
                        uint16_t len16 = htons(len); memcpy(data, &len16, 2); data += 2;
@@ -361,7 +360,6 @@ static void receive_udppacket(node_t *n, vpn_packet_t *inpkt) {
        vpn_packet_t pkt1, pkt2;
        vpn_packet_t *pkt[] = { &pkt1, &pkt2, &pkt1, &pkt2 };
        int nextpkt = 0;
-       vpn_packet_t *outpkt = pkt[0];
        size_t outlen;
 
        if(n->status.sptps) {
@@ -403,7 +401,7 @@ static void receive_udppacket(node_t *n, vpn_packet_t *inpkt) {
        /* Decrypt the packet */
 
        if(cipher_active(n->incipher)) {
-               outpkt = pkt[nextpkt++];
+               vpn_packet_t *outpkt = pkt[nextpkt++];
                outlen = MAXSIZE;
 
                if(!cipher_decrypt(n->incipher, &inpkt->seqno, inpkt->len, &outpkt->seqno, &outlen, true)) {
@@ -460,7 +458,7 @@ static void receive_udppacket(node_t *n, vpn_packet_t *inpkt) {
        length_t origlen = inpkt->len;
 
        if(n->incompression) {
-               outpkt = pkt[nextpkt++];
+               vpn_packet_t *outpkt = pkt[nextpkt++];
 
                if((outpkt->len = uncompress_packet(outpkt->data, inpkt->data, inpkt->len, n->incompression)) < 0) {
                        logger(DEBUG_TRAFFIC, LOG_ERR, "Error while uncompressing packet from %s (%s)",
@@ -598,6 +596,8 @@ static void choose_udp_address(const node_t *n, const sockaddr_t **sa, int *sock
 }
 
 static void choose_local_address(const node_t *n, const sockaddr_t **sa, int *sock) {
+       *sa = NULL;
+
        /* Pick one of the edges from this node at random, then use its local address. */
 
        int i = 0;
@@ -615,46 +615,6 @@ static void choose_local_address(const node_t *n, const sockaddr_t **sa, int *so
                *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,
-                       .sin_addr.s_addr = -1,
-               }
-       };
-
-       static sockaddr_t broadcast_ipv6 = {
-               .in6 = {
-                       .sin6_family = AF_INET6,
-                       .sin6_addr.s6_addr[0x0] = 0xff,
-                       .sin6_addr.s6_addr[0x1] = 0x02,
-                       .sin6_addr.s6_addr[0xf] = 0x01,
-               }
-       };
-
-       *sock = rand() % listen_sockets;
-
-       if(listen_socket[*sock].sa.sa.sa_family == AF_INET6) {
-               if(localdiscovery_address.sa.sa_family == AF_INET6) {
-                       localdiscovery_address.in6.sin6_port = n->prevedge->address.in.sin_port;
-                       *sa = &localdiscovery_address;
-               } else {
-                       broadcast_ipv6.in6.sin6_port = n->prevedge->address.in.sin_port;
-                       broadcast_ipv6.in6.sin6_scope_id = listen_socket[*sock].sa.in6.sin6_scope_id;
-                       *sa = &broadcast_ipv6;
-               }
-       } else {
-               if(localdiscovery_address.sa.sa_family == AF_INET) {
-                       localdiscovery_address.in.sin_port = n->prevedge->address.in.sin_port;
-                       *sa = &localdiscovery_address;
-               } else {
-                       broadcast_ipv4.in.sin_port = n->prevedge->address.in.sin_port;
-                       *sa = &broadcast_ipv4;
-               }
        }
 }
 
@@ -668,8 +628,8 @@ static void send_udppacket(node_t *n, vpn_packet_t *origpkt) {
        size_t outlen;
 #if defined(SOL_IP) && defined(IP_TOS)
        static int priority = 0;
-#endif
        int origpriority = origpkt->priority;
+#endif
 
        if(!n->status.reachable) {
                logger(DEBUG_TRAFFIC, LOG_INFO, "Trying to send UDP packet to unreachable node %s (%s)", n->name, n->hostname);
@@ -756,12 +716,12 @@ static void send_udppacket(node_t *n, vpn_packet_t *origpkt) {
 
        /* Send the packet */
 
-       const sockaddr_t *sa;
+       const sockaddr_t *sa = NULL;
        int sock;
 
        if(n->status.send_locally)
                choose_local_address(n, &sa, &sock);
-       else
+       if(!sa)
                choose_udp_address(n, &sa, &sock);
 
 #if defined(SOL_IP) && defined(IP_TOS)
@@ -808,12 +768,12 @@ bool send_sptps_data(void *handle, uint8_t type, const char *data, size_t len) {
 
        /* Otherwise, send the packet via UDP */
 
-       const sockaddr_t *sa;
+       const sockaddr_t *sa = NULL;
        int sock;
 
        if(to->status.send_locally)
                choose_local_address(to, &sa, &sock);
-       else
+       if(!sa)
                choose_udp_address(to, &sa, &sock);
 
        if(sendto(listen_socket[sock].udp.fd, data, len, 0, &sa->sa, SALEN(sa->sa)) < 0 && !sockwouldblock(sockerrno)) {
@@ -976,7 +936,7 @@ void broadcast_packet(const node_t *from, vpn_packet_t *packet) {
                // usually distributes the sending of broadcast packets over all nodes.
                case BMODE_MST:
                        for list_each(connection_t, c, connection_list)
-                               if(c->status.active && c->status.mst && c != from->nexthop->connection)
+                               if(c->edge && c->status.mst && c != from->nexthop->connection)
                                        send_packet(c->node, packet);
                        break;