Fix compiler warning.
[tinc] / src / route.c
index 2c3cc0d..9a555de 100644 (file)
@@ -17,7 +17,7 @@
     along with this program; if not, write to the Free Software
     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 
-    $Id: route.c,v 1.1.2.11 2001/06/05 16:09:55 guus Exp $
+    $Id: route.c,v 1.1.2.15 2001/07/01 09:21:14 guus Exp $
 */
 
 #include "config.h"
 #endif
 #include <sys/socket.h>
 #include <netinet/in.h>
-#include <net/ethernet.h>
+#ifdef HAVE_SOLARIS
+ #include <netinet/if.h>
+ #define ETHER_ADDR_LEN 6
+#else
+ #include <net/ethernet.h>
+#endif
 #include <netinet/if_ether.h>
 #include <utils.h>
 #include <xalloc.h>
 #include <syslog.h>
+#include <string.h>
+
+#include <avl_tree.h>
 
 #include "net.h"
-#include "net/ethernet.h"
-#include "netinet/if_ether.h"
 #include "connection.h"
 #include "subnet.h"
 #include "route.h"
+#include "protocol.h"
 
 #include "system.h"
 
 int routing_mode = RMODE_ROUTER;
 subnet_t mymac;
 
-void learn_mac(connection_t *source, mac_t *address)
+void learn_mac(mac_t *address)
 {
   subnet_t *subnet;
+  avl_node_t *node;
+  connection_t *p;
 cp
   subnet = lookup_subnet_mac(address);
+
+  /* If we don't know this MAC address yet, store it */
   
-  if(!subnet)
+  if(!subnet || subnet->owner!=myself)
     {
+      if(debug_lvl >= DEBUG_TRAFFIC)
+        syslog(LOG_INFO, _("Learned new MAC address %hhx:%hhx:%hhx:%hhx:%hhx:%hhx"),
+               address->x[0], address->x[1], address->x[2], address->x[3],  address->x[4], address->x[5]);
+               
       subnet = new_subnet();
       subnet->type = SUBNET_MAC;
-//      subnet->lasttime = gettimeofday();
       memcpy(&subnet->net.mac.address, address, sizeof(mac_t));
-      subnet_add(source, subnet);
+      subnet_add(myself, subnet);
 
-      if(debug_lvl >= DEBUG_TRAFFIC)
+      /* And tell all other tinc daemons it's our MAC */
+      
+      for(node = connection_tree->head; node; node = node->next)
         {
-          syslog(LOG_DEBUG, _("Learned new MAC address %x:%x:%x:%x:%x:%x from %s (%s)"),
-               address->x[0],
-               address->x[1],
-               address->x[2],
-               address->x[3],
-               address->x[4],
-               address->x[5],
-               source->name, source->hostname);
+          p = (connection_t *)node->data;
+          if(p->status.meta && p->status.active && p!= myself)
+            send_add_subnet(p, subnet);
         }
     }
 }
 
-connection_t *route_mac(connection_t *source, vpn_packet_t *packet)
+connection_t *route_mac(vpn_packet_t *packet)
 {
   subnet_t *subnet;
 cp
   /* Learn source address */
 
-  learn_mac(source, (mac_t *)(&packet->data[6]));
+  learn_mac((mac_t *)(&packet->data[6]));
   
   /* Lookup destination address */
     
@@ -132,6 +143,10 @@ void route_arp(vpn_packet_t *packet)
   unsigned char ipbuf[4];
   ipv4_t dest;
 cp
+  /* First, snatch the source address from the ARP packet */
+
+  memcpy(mymac.net.mac.address.x, packet->data + 6, 6);
+
   /* This routine generates replies to ARP requests.
      You don't need to set NOARP flag on the interface anymore (which is broken on FreeBSD).
      Most of the code here is taken from choparp.c by Takamichi Tateoka (tree@mma.club.uec.ac.jp)
@@ -224,7 +239,7 @@ cp
          break;
         
       case RMODE_SWITCH:
-        cl = route_mac(myself, packet);
+        cl = route_mac(packet);
         if(cl)
           send_packet(cl, packet);
         else
@@ -243,17 +258,31 @@ void route_incoming(connection_t *source, vpn_packet_t *packet)
     {
       case RMODE_ROUTER:
         memcpy(packet->data, mymac.net.mac.address.x, 6);      /* Override destination address to make the kernel accept it */
+        accept_packet(packet);
         break;
       case RMODE_SWITCH:
-        if((packet->data[0] & packet->data[1]) == 0xFF)                /* Broadcast? */
-          broadcast_packet(source, packet);                    /* If yes, spread it on */
-        else
-          learn_mac(source, (mac_t *)(&packet->data[6]));
+        {
+          subnet_t *subnet;
+
+          subnet = lookup_subnet_mac((mac_t *)(&packet->data[0]));
+
+          if(subnet)
+            {
+              if(subnet->owner == myself)
+                accept_packet(packet);
+              else
+                send_packet(subnet->owner, packet);
+            }
+          else
+            {
+              broadcast_packet(source, packet);
+              accept_packet(packet);
+            }
+          }
         break;
       case RMODE_HUB:
         broadcast_packet(source,packet);                       /* Spread it on */
+        accept_packet(packet);
         break;
     }
-  
-  accept_packet(packet);
 }