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.22 2002/02/10 21:57:54 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;
56 void learn_mac(mac_t *address)
62 subnet = lookup_subnet_mac(address);
64 /* If we don't know this MAC address yet, store it */
66 if(!subnet || subnet->owner!=myself)
68 if(debug_lvl >= DEBUG_TRAFFIC)
69 syslog(LOG_INFO, _("Learned new MAC address %hx:%hx:%hx:%hx:%hx:%hx"),
70 address->x[0], address->x[1], address->x[2], address->x[3], address->x[4], address->x[5]);
72 subnet = new_subnet();
73 subnet->type = SUBNET_MAC;
74 memcpy(&subnet->net.mac.address, address, sizeof(mac_t));
75 subnet_add(myself, subnet);
77 /* And tell all other tinc daemons it's our MAC */
79 for(node = connection_tree->head; node; node = node->next)
81 c = (connection_t *)node->data;
83 send_add_subnet(c, subnet);
88 node_t *route_mac(vpn_packet_t *packet)
92 /* Learn source address */
94 learn_mac((mac_t *)(&packet->data[6]));
96 /* Lookup destination address */
98 subnet = lookup_subnet_mac((mac_t *)(&packet->data[0]));
101 return subnet->owner;
106 node_t *route_ipv4(vpn_packet_t *packet)
112 /* The other form gives bus errors on a SparcStation 20. */
113 dest = ((packet->data[30] * 0x100 + packet->data[31]) * 0x100 + packet->data[32]) * 0x100 + packet->data[33];
115 dest = ntohl(*((unsigned long*)(&packet->data[30])));
118 subnet = lookup_subnet_ipv4(&dest);
122 if(debug_lvl >= DEBUG_TRAFFIC)
124 syslog(LOG_WARNING, _("Cannot route packet: unknown destination address %d.%d.%d.%d"),
125 packet->data[30], packet->data[31], packet->data[32], packet->data[33]);
131 return subnet->owner;
134 node_t *route_ipv6(vpn_packet_t *packet)
138 subnet = lookup_subnet_ipv6((ipv6_t *)&packet->data[38]);
142 if(debug_lvl >= DEBUG_TRAFFIC)
144 syslog(LOG_WARNING, _("Cannot route packet: unknown IPv6 destination address %hx:%hx:%hx:%hx:%hx:%hx:%hx:%hx"),
145 ntohs(*(short unsigned int *)&packet->data[38]),
146 ntohs(*(short unsigned int *)&packet->data[40]),
147 ntohs(*(short unsigned int *)&packet->data[42]),
148 ntohs(*(short unsigned int *)&packet->data[44]),
149 ntohs(*(short unsigned int *)&packet->data[46]),
150 ntohs(*(short unsigned int *)&packet->data[48]),
151 ntohs(*(short unsigned int *)&packet->data[50]),
152 ntohs(*(short unsigned int *)&packet->data[52]));
158 return subnet->owner;
161 void route_arp(vpn_packet_t *packet)
163 struct ether_arp *arp;
165 unsigned char ipbuf[4];
168 /* First, snatch the source address from the ARP packet */
170 memcpy(mymac.net.mac.address.x, packet->data + 6, 6);
172 /* This routine generates replies to ARP requests.
173 You don't need to set NOARP flag on the interface anymore (which is broken on FreeBSD).
174 Most of the code here is taken from choparp.c by Takamichi Tateoka (tree@mma.club.uec.ac.jp)
177 arp = (struct ether_arp *)(packet->data + 14);
179 /* Check if this is a valid ARP request */
181 if(ntohs(arp->arp_hrd) != ARPHRD_ETHER ||
182 ntohs(arp->arp_pro) != ETHERTYPE_IP ||
183 (int) (arp->arp_hln) != ETHER_ADDR_LEN ||
184 (int) (arp->arp_pln) != 4 ||
185 ntohs(arp->arp_op) != ARPOP_REQUEST )
187 if(debug_lvl > DEBUG_TRAFFIC)
189 syslog(LOG_WARNING, _("Cannot route packet: received unknown type ARP request"));
194 /* Check if the IP address exists on the VPN */
196 dest = ntohl(*((unsigned long*)(arp->arp_tpa)));
197 subnet = lookup_subnet_ipv4(&dest);
201 if(debug_lvl >= DEBUG_TRAFFIC)
203 syslog(LOG_WARNING, _("Cannot route packet: ARP request for unknown address %d.%d.%d.%d"),
204 arp->arp_tpa[0], arp->arp_tpa[1], arp->arp_tpa[2], arp->arp_tpa[3]);
210 /* Check if it is for our own subnet */
212 if(subnet->owner == myself)
213 return; /* silently ignore */
215 memcpy(packet->data, packet->data + ETHER_ADDR_LEN, ETHER_ADDR_LEN); /* copy destination address */
216 packet->data[ETHER_ADDR_LEN*2 - 1] ^= 0xFF; /* mangle source address so it looks like it's not from us */
218 memcpy(ipbuf, arp->arp_tpa, 4); /* save protocol addr */
219 memcpy(arp->arp_tpa, arp->arp_spa, 4); /* swap destination and source protocol address */
220 memcpy(arp->arp_spa, ipbuf, 4); /* ... */
222 memcpy(arp->arp_tha, arp->arp_sha, 10); /* set target hard/proto addr */
223 memcpy(arp->arp_sha, packet->data + ETHER_ADDR_LEN, ETHER_ADDR_LEN); /* add fake source hard addr */
224 arp->arp_op = htons(ARPOP_REPLY);
226 write_packet(packet);
230 void route_outgoing(vpn_packet_t *packet)
232 unsigned short int type;
235 /* FIXME: multicast? */
240 type = ntohs(*((unsigned short*)(&packet->data[12])));
244 n = route_ipv4(packet);
247 n = route_ipv6(packet);
253 if(debug_lvl >= DEBUG_TRAFFIC)
255 syslog(LOG_WARNING, _("Cannot route packet: unknown type %hx"), type);
260 send_packet(n, packet);
264 n = route_mac(packet);
266 send_packet(n, packet);
268 broadcast_packet(myself, packet);
272 broadcast_packet(myself, packet);
277 void route_incoming(node_t *source, vpn_packet_t *packet)
282 memcpy(packet->data, mymac.net.mac.address.x, 6); /* Override destination address to make the kernel accept it */
283 write_packet(packet);
289 subnet = lookup_subnet_mac((mac_t *)(&packet->data[0]));
293 if(subnet->owner == myself)
294 write_packet(packet);
296 send_packet(subnet->owner, packet);
300 broadcast_packet(source, packet);
301 write_packet(packet);
306 broadcast_packet(source, packet); /* Spread it on */
307 write_packet(packet);