3 Copyright (C) 2000-2002 Ivo Timmermans <itimmermans@bigfoot.com>,
4 2000-2002 Guus Sliepen <guus@sliepen.warande.net>
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.
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.
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.
20 $Id: route.c,v 1.1.2.25 2002/03/01 12:26:56 guus Exp $
25 #if defined(HAVE_FREEBSD) || defined(HAVE_OPENBSD)
26 #include <sys/param.h>
28 #include <sys/socket.h>
29 #include <netinet/in.h>
30 #if defined(HAVE_SOLARIS) || defined(HAVE_OPENBSD)
32 #define ETHER_ADDR_LEN 6
34 #include <net/ethernet.h>
36 #include <netinet/if_ether.h>
45 #include "connection.h"
53 int routing_mode = RMODE_ROUTER;
54 int priorityinheritance = 0;
57 void learn_mac(mac_t *address)
63 subnet = lookup_subnet_mac(address);
65 /* If we don't know this MAC address yet, store it */
67 if(!subnet || subnet->owner!=myself)
69 if(debug_lvl >= DEBUG_TRAFFIC)
70 syslog(LOG_INFO, _("Learned new MAC address %hx:%hx:%hx:%hx:%hx:%hx"),
71 address->x[0], address->x[1], address->x[2], address->x[3], address->x[4], address->x[5]);
73 subnet = new_subnet();
74 subnet->type = SUBNET_MAC;
75 memcpy(&subnet->net.mac.address, address, sizeof(mac_t));
76 subnet_add(myself, subnet);
78 /* And tell all other tinc daemons it's our MAC */
80 for(node = connection_tree->head; node; node = node->next)
82 c = (connection_t *)node->data;
84 send_add_subnet(c, subnet);
89 node_t *route_mac(vpn_packet_t *packet)
93 /* Learn source address */
95 learn_mac((mac_t *)(&packet->data[6]));
97 /* Lookup destination address */
99 subnet = lookup_subnet_mac((mac_t *)(&packet->data[0]));
102 return subnet->owner;
107 node_t *route_ipv4(vpn_packet_t *packet)
111 if(priorityinheritance)
112 packet->priority = packet->data[15];
114 subnet = lookup_subnet_ipv4((ipv4_t *)&packet->data[30]);
118 if(debug_lvl >= DEBUG_TRAFFIC)
120 syslog(LOG_WARNING, _("Cannot route packet: unknown IPv4 destination address %d.%d.%d.%d"),
121 packet->data[30], packet->data[31], packet->data[32], packet->data[33]);
127 return subnet->owner;
130 node_t *route_ipv6(vpn_packet_t *packet)
134 subnet = lookup_subnet_ipv6((ipv6_t *)&packet->data[38]);
138 if(debug_lvl >= DEBUG_TRAFFIC)
140 syslog(LOG_WARNING, _("Cannot route packet: unknown IPv6 destination address %hx:%hx:%hx:%hx:%hx:%hx:%hx:%hx"),
141 ntohs(*(short unsigned int *)&packet->data[38]),
142 ntohs(*(short unsigned int *)&packet->data[40]),
143 ntohs(*(short unsigned int *)&packet->data[42]),
144 ntohs(*(short unsigned int *)&packet->data[44]),
145 ntohs(*(short unsigned int *)&packet->data[46]),
146 ntohs(*(short unsigned int *)&packet->data[48]),
147 ntohs(*(short unsigned int *)&packet->data[50]),
148 ntohs(*(short unsigned int *)&packet->data[52]));
154 return subnet->owner;
157 void route_arp(vpn_packet_t *packet)
159 struct ether_arp *arp;
161 unsigned char ipbuf[4];
163 /* First, snatch the source address from the ARP packet */
165 memcpy(mymac.net.mac.address.x, packet->data + 6, 6);
167 /* This routine generates replies to ARP requests.
168 You don't need to set NOARP flag on the interface anymore (which is broken on FreeBSD).
169 Most of the code here is taken from choparp.c by Takamichi Tateoka (tree@mma.club.uec.ac.jp)
172 arp = (struct ether_arp *)(packet->data + 14);
174 /* Check if this is a valid ARP request */
176 if(ntohs(arp->arp_hrd) != ARPHRD_ETHER ||
177 ntohs(arp->arp_pro) != ETHERTYPE_IP ||
178 (int) (arp->arp_hln) != ETHER_ADDR_LEN ||
179 (int) (arp->arp_pln) != 4 ||
180 ntohs(arp->arp_op) != ARPOP_REQUEST )
182 if(debug_lvl > DEBUG_TRAFFIC)
184 syslog(LOG_WARNING, _("Cannot route packet: received unknown type ARP request"));
189 /* Check if the IP address exists on the VPN */
191 subnet = lookup_subnet_ipv4((ipv4_t *)arp->arp_tpa);
195 if(debug_lvl >= DEBUG_TRAFFIC)
197 syslog(LOG_WARNING, _("Cannot route packet: ARP request for unknown address %d.%d.%d.%d"),
198 arp->arp_tpa[0], arp->arp_tpa[1], arp->arp_tpa[2], arp->arp_tpa[3]);
204 /* Check if it is for our own subnet */
206 if(subnet->owner == myself)
207 return; /* silently ignore */
209 memcpy(packet->data, packet->data + ETHER_ADDR_LEN, ETHER_ADDR_LEN); /* copy destination address */
210 packet->data[ETHER_ADDR_LEN*2 - 1] ^= 0xFF; /* mangle source address so it looks like it's not from us */
212 memcpy(ipbuf, arp->arp_tpa, 4); /* save protocol addr */
213 memcpy(arp->arp_tpa, arp->arp_spa, 4); /* swap destination and source protocol address */
214 memcpy(arp->arp_spa, ipbuf, 4); /* ... */
216 memcpy(arp->arp_tha, arp->arp_sha, 10); /* set target hard/proto addr */
217 memcpy(arp->arp_sha, packet->data + ETHER_ADDR_LEN, ETHER_ADDR_LEN); /* add fake source hard addr */
218 arp->arp_op = htons(ARPOP_REPLY);
220 write_packet(packet);
224 void route_outgoing(vpn_packet_t *packet)
226 unsigned short int type;
229 /* FIXME: multicast? */
234 type = ntohs(*((unsigned short*)(&packet->data[12])));
238 n = route_ipv4(packet);
241 n = route_ipv6(packet);
247 if(debug_lvl >= DEBUG_TRAFFIC)
249 syslog(LOG_WARNING, _("Cannot route packet: unknown type %hx"), type);
254 send_packet(n, packet);
258 n = route_mac(packet);
260 send_packet(n, packet);
262 broadcast_packet(myself, packet);
266 broadcast_packet(myself, packet);
271 void route_incoming(node_t *source, vpn_packet_t *packet)
279 n = route_ipv4(packet);
285 memcpy(packet->data, mymac.net.mac.address.x, 6);
286 write_packet(packet);
289 send_packet(n, packet);
297 subnet = lookup_subnet_mac((mac_t *)(&packet->data[0]));
301 if(subnet->owner == myself)
302 write_packet(packet);
304 send_packet(subnet->owner, packet);
308 broadcast_packet(source, packet);
309 write_packet(packet);
314 broadcast_packet(source, packet); /* Spread it on */
315 write_packet(packet);