3264d56003b6b8d6b4848a34c4dd97b68611aa87
[tinc] / src / route.c
1 /*
2     route.c -- routing
3     Copyright (C) 2000,2001 Ivo Timmermans <itimmermans@bigfoot.com>,
4                   2000,2001 Guus Sliepen <guus@sliepen.warande.net>
5
6     This program is free software; you can redistribute it and/or modify
7     it under the terms of the GNU General Public License as published by
8     the Free Software Foundation; either version 2 of the License, or
9     (at your option) any later version.
10
11     This program is distributed in the hope that it will be useful,
12     but WITHOUT ANY WARRANTY; without even the implied warranty of
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14     GNU General Public License for more details.
15
16     You should have received a copy of the GNU General Public License
17     along with this program; if not, write to the Free Software
18     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19
20     $Id: route.c,v 1.1.2.8 2001/05/25 11:54:28 guus Exp $
21 */
22
23 #include "config.h"
24
25 #include <netinet/in.h>
26 #include <utils.h>
27 #include <xalloc.h>
28 #include <syslog.h>
29
30 #include "net.h"
31 #include "connection.h"
32 #include "subnet.h"
33 #include "route.h"
34
35 #include "system.h"
36
37 int routing_mode = RMODE_ROUTER;
38 subnet_t mymac;
39
40 void learn_mac(connection_t *source, mac_t *address)
41 {
42   subnet_t *subnet;
43 cp
44   subnet = lookup_subnet_mac(address);
45   
46   if(!subnet)
47     {
48       subnet = new_subnet();
49       subnet->type = SUBNET_MAC;
50 //      subnet->lasttime = gettimeofday();
51       memcpy(&subnet->net.mac.address, address, sizeof(mac_t));
52       subnet_add(source, subnet);
53
54       if(debug_lvl >= DEBUG_TRAFFIC)
55         {
56           syslog(LOG_DEBUG, _("Learned new MAC address %x:%x:%x:%x:%x:%x from %s (%s)"),
57                address->x[0],
58                address->x[1],
59                address->x[2],
60                address->x[3],
61                address->x[4],
62                address->x[5],
63                source->name, source->hostname);
64         }
65     }
66 }
67
68 connection_t *route_mac(connection_t *source, vpn_packet_t *packet)
69 {
70   subnet_t *subnet;
71 cp
72   /* Learn source address */
73
74   learn_mac(source, (mac_t *)(&packet->data[0]));
75   
76   /* Lookup destination address */
77     
78   subnet = lookup_subnet_mac((mac_t *)(&packet->data[6]));
79
80   if(!subnet)
81     {
82       if(debug_lvl >= DEBUG_TRAFFIC)
83         {
84           syslog(LOG_WARNING, _("Cannot route packet: unknown destination address %x:%x:%x:%x:%x:%x"),
85                  packet->data[6],
86                  packet->data[7],
87                  packet->data[8],
88                  packet->data[9],
89                  packet->data[10],
90                  packet->data[11]);
91         } 
92       return NULL;
93     }
94 cp  
95   return subnet->owner;  
96 }
97
98 connection_t *route_ipv4(vpn_packet_t *packet)
99 {
100   ipv4_t dest;
101   subnet_t *subnet;
102 cp
103   dest = ntohl(*((unsigned long*)(&packet->data[30])));
104   
105   subnet = lookup_subnet_ipv4(&dest);
106
107   if(!subnet)
108     {
109       if(debug_lvl >= DEBUG_TRAFFIC)
110         {
111           syslog(LOG_WARNING, _("Cannot route packet: unknown destination address %d.%d.%d.%d"),
112                  packet->data[30], packet->data[31], packet->data[32], packet->data[33]);
113         }
114
115       return NULL;
116     }
117 cp
118   return subnet->owner;  
119 }
120
121 connection_t *route_ipv6(vpn_packet_t *packet)
122 {
123 cp
124   if(debug_lvl > DEBUG_NOTHING)
125     {
126       syslog(LOG_WARNING, _("Cannot route packet: IPv6 routing not yet implemented"));
127     } 
128 cp
129   return NULL;
130 }
131
132 void route_outgoing(vpn_packet_t *packet)
133 {
134   unsigned short int type;
135   avl_node_t *node;
136   connection_t *cl;
137 cp
138   /* FIXME: multicast? */
139
140   switch(routing_mode)
141     {
142       case RMODE_ROUTER:
143         type = ntohs(*((unsigned short*)(&packet->data[12])));
144         switch(type)
145           {
146             case 0x0800:
147               cl = route_ipv4(packet);
148               break;
149             case 0x86DD:
150               cl = route_ipv6(packet);
151               break;
152             default:
153               if(debug_lvl >= DEBUG_TRAFFIC)
154                 {
155                   syslog(LOG_WARNING, _("Cannot route packet: unknown type %hx"), type);
156                 }
157               return;
158            }
159          if(cl)
160            send_packet(cl, packet);
161          break;
162         
163       case RMODE_SWITCH:
164         cl = route_mac(myself, packet);
165         if(cl)
166           send_packet(cl, packet);
167         break;
168         
169       case RMODE_HUB:
170         for(node = connection_tree->head; node; node = node->next)
171           {
172             cl = (connection_t *)node->data;
173             if(cl->status.active)
174               send_packet(cl, packet);
175           }
176         break;
177     }
178 }
179
180 void route_incoming(connection_t *source, vpn_packet_t *packet)
181 {
182   switch(routing_mode)
183     {
184       case RMODE_ROUTER:
185         memcpy(packet->data, mymac.net.mac.address.x, 6);
186         break;
187       case RMODE_SWITCH:
188         learn_mac(source, (mac_t *)(&packet->data[0]));
189         break;
190     }
191   
192   accept_packet(packet);
193 }