route_ipv4 and route_ipv6 replaced by route_ip.
[tinc] / src / route.c
index 3d48887..8df8128 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.10 2001/06/04 11:14:35 guus Exp $
+    $Id: route.c,v 1.1.2.21 2001/11/16 17:40:50 zarq Exp $
 */
 
 #include "config.h"
 #endif
 #include <sys/socket.h>
 #include <netinet/in.h>
-#include <net/ethernet.h>
+#ifdef HAVE_SOLARIS
+ #include <net/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 "device.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 *c;
 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);
+          c = (connection_t *)node->data;
+          if(c->status.active)
+            send_add_subnet(c, subnet);
         }
     }
 }
 
-connection_t *route_mac(connection_t *source, vpn_packet_t *packet)
+node_t *route_mac(vpn_packet_t *packet)
 {
   subnet_t *subnet;
 cp
   /* Learn source address */
 
-  learn_mac(source, (mac_t *)(&packet->data[0]));
+  learn_mac((mac_t *)(&packet->data[6]));
   
   /* Lookup destination address */
     
-  subnet = lookup_subnet_mac((mac_t *)(&packet->data[6]));
+  subnet = lookup_subnet_mac((mac_t *)(&packet->data[0]));
+
+  if(subnet)
+    return subnet->owner;
+  else
+    return NULL;
+}
 
   if(!subnet)
     {
       if(debug_lvl >= DEBUG_TRAFFIC)
         {
-          syslog(LOG_WARNING, _("Cannot route packet: unknown destination address %x:%x:%x:%x:%x:%x"),
-                 packet->data[6],
-                 packet->data[7],
-                 packet->data[8],
-                 packet->data[9],
-                 packet->data[10],
-                 packet->data[11]);
-        } 
+        }
+
       return NULL;
     }
-cp  
+cp
   return subnet->owner;  
 }
 
-connection_t *route_ipv4(vpn_packet_t *packet)
+node_t *route_ip(vpn_packet_t *packet)
 {
-  ipv4_t dest;
+  struct addrinfo *dest;
   subnet_t *subnet;
 cp
-  dest = ntohl(*((unsigned long*)(&packet->data[30])));
-  
-  subnet = lookup_subnet_ipv4(&dest);
+#warning FIXME
+  memcpy(&dest, &packet->data[30], 0);
 
+  subnet = lookup_subnet_ip(&dest);
+cp
   if(!subnet)
     {
       if(debug_lvl >= DEBUG_TRAFFIC)
         {
-          syslog(LOG_WARNING, _("Cannot route packet: unknown destination address %d.%d.%d.%d"),
-                 packet->data[30], packet->data[31], packet->data[32], packet->data[33]);
+          syslog(LOG_WARNING, _("Cannot route packet: unknown IP destination address"));
         }
 
       return NULL;
@@ -126,24 +138,17 @@ cp
   return subnet->owner;  
 }
 
-connection_t *route_ipv6(vpn_packet_t *packet)
-{
-cp
-  if(debug_lvl > DEBUG_NOTHING)
-    {
-      syslog(LOG_WARNING, _("Cannot route packet: IPv6 routing not yet implemented"));
-    } 
-cp
-  return NULL;
-}
-
 void route_arp(vpn_packet_t *packet)
 {
   struct ether_arp *arp;
   subnet_t *subnet;
   unsigned char ipbuf[4];
-  ipv4_t dest;
+  struct addrinfo *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)
@@ -167,9 +172,9 @@ cp
     }
 
   /* Check if the IP address exists on the VPN */
-
+#warning FIXME
   dest = ntohl(*((unsigned long*)(arp->arp_tpa)));
-  subnet = lookup_subnet_ipv4(&dest);
+  subnet = lookup_subnet_ip(&dest);
 
   if(!subnet)
     {
@@ -198,15 +203,14 @@ cp
   memcpy(arp->arp_sha, packet->data + ETHER_ADDR_LEN, ETHER_ADDR_LEN); /* add fake source hard addr */
   arp->arp_op = htons(ARPOP_REPLY);
   
-  accept_packet(packet);
+  write_packet(packet);
 cp
 }
 
 void route_outgoing(vpn_packet_t *packet)
 {
   unsigned short int type;
-  avl_node_t *node;
-  connection_t *cl;
+  node_t *n;
 cp
   /* FIXME: multicast? */
 
@@ -217,10 +221,10 @@ cp
         switch(type)
           {
             case 0x0800:
-              cl = route_ipv4(packet);
+              n = route_ipv4(packet);
               break;
             case 0x86DD:
-              cl = route_ipv6(packet);
+              n = route_ipv6(packet);
               break;
             case 0x0806:
               route_arp(packet);
@@ -232,38 +236,55 @@ cp
                 }
               return;
            }
-         if(cl)
-           send_packet(cl, packet);
+         if(n)
+           send_packet(n, packet);
          break;
         
       case RMODE_SWITCH:
-        cl = route_mac(myself, packet);
-        if(cl)
-          send_packet(cl, packet);
+        n = route_mac(packet);
+        if(n)
+          send_packet(n, packet);
+        else
+          broadcast_packet(myself, packet);
         break;
         
       case RMODE_HUB:
-        for(node = connection_tree->head; node; node = node->next)
-          {
-            cl = (connection_t *)node->data;
-            if(cl->status.active)
-              send_packet(cl, packet);
-          }
+        broadcast_packet(myself, packet);
         break;
     }
 }
 
-void route_incoming(connection_t *source, vpn_packet_t *packet)
+void route_incoming(node_t *source, vpn_packet_t *packet)
 {
   switch(routing_mode)
     {
       case RMODE_ROUTER:
-        memcpy(packet->data, mymac.net.mac.address.x, 6);
+        memcpy(packet->data, mymac.net.mac.address.x, 6);      /* Override destination address to make the kernel accept it */
+        write_packet(packet);
         break;
       case RMODE_SWITCH:
-        learn_mac(source, (mac_t *)(&packet->data[0]));
+        {
+          subnet_t *subnet;
+
+          subnet = lookup_subnet_mac((mac_t *)(&packet->data[0]));
+
+          if(subnet)
+            {
+              if(subnet->owner == myself)
+                write_packet(packet);
+              else
+                send_packet(subnet->owner, packet);
+            }
+          else
+            {
+              broadcast_packet(source, packet);
+              write_packet(packet);
+            }
+          }
+        break;
+      case RMODE_HUB:
+        broadcast_packet(source, packet);                      /* Spread it on */
+        write_packet(packet);
         break;
     }
-  
-  accept_packet(packet);
 }