Remember ToS/Diffserv priority for each socket individually.
[oweals/tinc.git] / src / net_packet.c
index 1efc60dd76b4455660b79ea3ee8d24e228380c14..e67857cc4865b6c60d2d52ee6c36a47d44dbf011 100644 (file)
@@ -1,7 +1,7 @@
 /*
     net_packet.c -- Handles in- and outgoing VPN packets
     Copyright (C) 1998-2005 Ivo Timmermans,
-                  2000-2013 Guus Sliepen <guus@tinc-vpn.org>
+                  2000-2014 Guus Sliepen <guus@tinc-vpn.org>
                   2010      Timothy Redaelli <timothy@redaelli.eu>
                   2010      Brandon Black <blblack@gmail.com>
 
@@ -269,7 +269,7 @@ static bool try_mac(const node_t *n, const vpn_packet_t *inpkt) {
 
        HMAC(n->indigest, n->inkey, n->inkeylength, (unsigned char *) &inpkt->seqno, inpkt->len - n->inmaclength, (unsigned char *)hmac, NULL);
 
-       return !memcmp(hmac, (char *) &inpkt->seqno + inpkt->len - n->inmaclength, n->inmaclength);
+       return !memcmp_constant_time(hmac, (char *) &inpkt->seqno + inpkt->len - n->inmaclength, n->inmaclength);
 }
 
 static void receive_udppacket(node_t *n, vpn_packet_t *inpkt) {
@@ -302,7 +302,7 @@ static void receive_udppacket(node_t *n, vpn_packet_t *inpkt) {
                HMAC(n->indigest, n->inkey, n->inkeylength,
                         (unsigned char *) &inpkt->seqno, inpkt->len, (unsigned char *)hmac, NULL);
 
-               if(memcmp(hmac, (char *) &inpkt->seqno + inpkt->len, n->inmaclength)) {
+               if(memcmp_constant_time(hmac, (char *) &inpkt->seqno + inpkt->len, n->inmaclength)) {
                        ifdebug(TRAFFIC) logger(LOG_DEBUG, "Got unauthenticated packet from %s (%s)",
                                           n->name, n->hostname);
                        return;
@@ -394,6 +394,9 @@ static void receive_udppacket(node_t *n, vpn_packet_t *inpkt) {
 void receive_tcppacket(connection_t *c, const char *buffer, int len) {
        vpn_packet_t outpkt;
 
+       if(len > sizeof outpkt.data)
+               return;
+
        outpkt.len = len;
        if(c->options & OPTION_TCPONLY)
                outpkt.priority = 0;
@@ -412,9 +415,6 @@ static void send_udppacket(node_t *n, vpn_packet_t *origpkt) {
        vpn_packet_t *outpkt;
        int origlen;
        int outlen, outpad;
-#if defined(SOL_IP) && defined(IP_TOS)
-       static int priority = 0;
-#endif
        int origpriority;
 
        if(!n->status.reachable) {
@@ -546,15 +546,27 @@ static void send_udppacket(node_t *n, vpn_packet_t *origpkt) {
                sock = n->sock;
        }
 
+       if(priorityinheritance && origpriority != listen_socket[n->sock].priority) {
+               listen_socket[n->sock].priority = origpriority;
+               switch(listen_socket[n->sock].sa.sa.sa_family) {
 #if defined(SOL_IP) && defined(IP_TOS)
-       if(priorityinheritance && origpriority != priority
-          && listen_socket[n->sock].sa.sa.sa_family == AF_INET) {
-               priority = origpriority;
-               ifdebug(TRAFFIC) logger(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 */
-                       logger(LOG_ERR, "System call `%s' failed: %s", "setsockopt", strerror(errno));
-       }
+               case AF_INET:
+                       ifdebug(TRAFFIC) logger(LOG_DEBUG, "Setting IPv4 outgoing packet priority to %d", origpriority);
+                       if(setsockopt(listen_socket[n->sock].udp, SOL_IP, IP_TOS, &origpriority, sizeof(origpriority))) /* SO_PRIORITY doesn't seem to work */
+                               logger(LOG_ERR, "System call `%s' failed: %s", "setsockopt", strerror(errno));
+                       break;
+#endif
+#if defined(IPPROTO_IPV6) && defined(IPV6_TCLASS)
+               case AF_INET6:
+                       ifdebug(TRAFFIC) logger(LOG_DEBUG, "Setting IPv6 outgoing packet priority to %d", origpriority);
+                       if(setsockopt(listen_socket[n->sock].udp, IPPROTO_IPV6, IPV6_TCLASS, &origpriority, sizeof(origpriority)))
+                               logger(LOG_ERR, "System call `%s' failed: %s", "setsockopt", strerror(errno));
+                       break;
 #endif
+               default:
+                       break;
+               }
+       }
 
        if(sendto(listen_socket[sock].udp, (char *) &inpkt->seqno, inpkt->len, 0, sa, sl) < 0 && !sockwouldblock(sockerrno)) {
                if(sockmsgsize(sockerrno)) {
@@ -647,7 +659,7 @@ void broadcast_packet(const node_t *from, vpn_packet_t *packet) {
                        for(node = node_udp_tree->head; node; node = node->next) {
                                n = node->data;
 
-                               if(n->status.reachable && ((n->via == myself && n->nexthop == n) || n->via == n))
+                               if(n->status.reachable && n != myself && ((n->via == myself && n->nexthop == n) || n->via == n))
                                        send_packet(n, packet);
                        }
                        break;
@@ -661,7 +673,6 @@ static node_t *try_harder(const sockaddr_t *from, const vpn_packet_t *pkt) {
        avl_node_t *node;
        edge_t *e;
        node_t *n = NULL;
-       bool hard = false;
        static time_t last_hard_try = 0;
 
        for(node = edge_weight_tree->head; node; node = node->next) {
@@ -670,11 +681,8 @@ static node_t *try_harder(const sockaddr_t *from, const vpn_packet_t *pkt) {
                if(e->to == myself)
                        continue;
 
-               if(sockaddrcmp_noport(from, &e->address)) {
-                       if(last_hard_try == now)
-                               continue;
-                       hard = true;
-               }
+               if(last_hard_try == now && sockaddrcmp_noport(from, &e->address))
+                       continue;
 
                if(!try_mac(e->to, pkt))
                        continue;
@@ -683,9 +691,6 @@ static node_t *try_harder(const sockaddr_t *from, const vpn_packet_t *pkt) {
                break;
        }
 
-       if(hard)
-               last_hard_try = now;
-
        last_hard_try = now;
        return n;
 }