3 Copyright (C) 2000,2001 Ivo Timmermans <itimmermans@bigfoot.com>,
4 2000,2001 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.21 2001/11/16 17:40:50 zarq Exp $
26 #include <sys/param.h>
28 #include <sys/socket.h>
29 #include <netinet/in.h>
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 %hhx:%hhx:%hhx:%hhx:%hhx:%hhx"),
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;
108 if(debug_lvl >= DEBUG_TRAFFIC)
115 return subnet->owner;
118 node_t *route_ip(vpn_packet_t *packet)
120 struct addrinfo *dest;
124 memcpy(&dest, &packet->data[30], 0);
126 subnet = lookup_subnet_ip(&dest);
130 if(debug_lvl >= DEBUG_TRAFFIC)
132 syslog(LOG_WARNING, _("Cannot route packet: unknown IP destination address"));
138 return subnet->owner;
141 void route_arp(vpn_packet_t *packet)
143 struct ether_arp *arp;
145 unsigned char ipbuf[4];
146 struct addrinfo *dest;
148 /* First, snatch the source address from the ARP packet */
150 memcpy(mymac.net.mac.address.x, packet->data + 6, 6);
152 /* This routine generates replies to ARP requests.
153 You don't need to set NOARP flag on the interface anymore (which is broken on FreeBSD).
154 Most of the code here is taken from choparp.c by Takamichi Tateoka (tree@mma.club.uec.ac.jp)
157 arp = (struct ether_arp *)(packet->data + 14);
159 /* Check if this is a valid ARP request */
161 if(ntohs(arp->arp_hrd) != ARPHRD_ETHER ||
162 ntohs(arp->arp_pro) != ETHERTYPE_IP ||
163 (int) (arp->arp_hln) != ETHER_ADDR_LEN ||
164 (int) (arp->arp_pln) != 4 ||
165 ntohs(arp->arp_op) != ARPOP_REQUEST )
167 if(debug_lvl > DEBUG_TRAFFIC)
169 syslog(LOG_WARNING, _("Cannot route packet: received unknown type ARP request"));
174 /* Check if the IP address exists on the VPN */
176 dest = ntohl(*((unsigned long*)(arp->arp_tpa)));
177 subnet = lookup_subnet_ip(&dest);
181 if(debug_lvl >= DEBUG_TRAFFIC)
183 syslog(LOG_WARNING, _("Cannot route packet: ARP request for unknown address %d.%d.%d.%d"),
184 arp->arp_tpa[0], arp->arp_tpa[1], arp->arp_tpa[2], arp->arp_tpa[3]);
190 /* Check if it is for our own subnet */
192 if(subnet->owner == myself)
193 return; /* silently ignore */
195 memcpy(packet->data, packet->data + ETHER_ADDR_LEN, ETHER_ADDR_LEN); /* copy destination address */
196 packet->data[ETHER_ADDR_LEN*2 - 1] ^= 0xFF; /* mangle source address so it looks like it's not from us */
198 memcpy(ipbuf, arp->arp_tpa, 4); /* save protocol addr */
199 memcpy(arp->arp_tpa, arp->arp_spa, 4); /* swap destination and source protocol address */
200 memcpy(arp->arp_spa, ipbuf, 4); /* ... */
202 memcpy(arp->arp_tha, arp->arp_sha, 10); /* set target hard/proto addr */
203 memcpy(arp->arp_sha, packet->data + ETHER_ADDR_LEN, ETHER_ADDR_LEN); /* add fake source hard addr */
204 arp->arp_op = htons(ARPOP_REPLY);
206 write_packet(packet);
210 void route_outgoing(vpn_packet_t *packet)
212 unsigned short int type;
215 /* FIXME: multicast? */
220 type = ntohs(*((unsigned short*)(&packet->data[12])));
224 n = route_ipv4(packet);
227 n = route_ipv6(packet);
233 if(debug_lvl >= DEBUG_TRAFFIC)
235 syslog(LOG_WARNING, _("Cannot route packet: unknown type %hx"), type);
240 send_packet(n, packet);
244 n = route_mac(packet);
246 send_packet(n, packet);
248 broadcast_packet(myself, packet);
252 broadcast_packet(myself, packet);
257 void route_incoming(node_t *source, vpn_packet_t *packet)
262 memcpy(packet->data, mymac.net.mac.address.x, 6); /* Override destination address to make the kernel accept it */
263 write_packet(packet);
269 subnet = lookup_subnet_mac((mac_t *)(&packet->data[0]));
273 if(subnet->owner == myself)
274 write_packet(packet);
276 send_packet(subnet->owner, packet);
280 broadcast_packet(source, packet);
281 write_packet(packet);
286 broadcast_packet(source, packet); /* Spread it on */
287 write_packet(packet);