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.12 2001/06/05 16:31:59 guus Exp $
26 #include <sys/param.h>
28 #include <sys/socket.h>
29 #include <netinet/in.h>
30 #include <net/ethernet.h>
31 #include <netinet/if_ether.h>
37 #include "net/ethernet.h"
38 #include "netinet/if_ether.h"
39 #include "connection.h"
45 int routing_mode = RMODE_ROUTER;
48 void learn_mac(connection_t *source, mac_t *address)
52 subnet = lookup_subnet_mac(address);
56 subnet = new_subnet();
57 subnet->type = SUBNET_MAC;
58 // subnet->lasttime = gettimeofday();
59 memcpy(&subnet->net.mac.address, address, sizeof(mac_t));
60 subnet_add(source, subnet);
62 if(debug_lvl >= DEBUG_TRAFFIC)
64 syslog(LOG_DEBUG, _("Learned new MAC address %x:%x:%x:%x:%x:%x from %s (%s)"),
71 source->name, source->hostname);
76 connection_t *route_mac(connection_t *source, vpn_packet_t *packet)
80 /* Learn source address */
82 learn_mac(source, (mac_t *)(&packet->data[6]));
84 /* Lookup destination address */
86 subnet = lookup_subnet_mac((mac_t *)(&packet->data[0]));
94 connection_t *route_ipv4(vpn_packet_t *packet)
99 dest = ntohl(*((unsigned long*)(&packet->data[30])));
101 subnet = lookup_subnet_ipv4(&dest);
105 if(debug_lvl >= DEBUG_TRAFFIC)
107 syslog(LOG_WARNING, _("Cannot route packet: unknown destination address %d.%d.%d.%d"),
108 packet->data[30], packet->data[31], packet->data[32], packet->data[33]);
114 return subnet->owner;
117 connection_t *route_ipv6(vpn_packet_t *packet)
120 if(debug_lvl > DEBUG_NOTHING)
122 syslog(LOG_WARNING, _("Cannot route packet: IPv6 routing not yet implemented"));
128 void route_arp(vpn_packet_t *packet)
130 struct ether_arp *arp;
132 unsigned char ipbuf[4];
135 /* First, snatch the source address from the ARP packet */
137 memcpy(mymac.net.mac.address.x, packet->data + 6, 6);
139 /* This routine generates replies to ARP requests.
140 You don't need to set NOARP flag on the interface anymore (which is broken on FreeBSD).
141 Most of the code here is taken from choparp.c by Takamichi Tateoka (tree@mma.club.uec.ac.jp)
144 arp = (struct ether_arp *)(packet->data + 14);
146 /* Check if this is a valid ARP request */
148 if(ntohs(arp->arp_hrd) != ARPHRD_ETHER ||
149 ntohs(arp->arp_pro) != ETHERTYPE_IP ||
150 (int) (arp->arp_hln) != ETHER_ADDR_LEN ||
151 (int) (arp->arp_pln) != 4 ||
152 ntohs(arp->arp_op) != ARPOP_REQUEST )
154 if(debug_lvl > DEBUG_TRAFFIC)
156 syslog(LOG_WARNING, _("Cannot route packet: received unknown type ARP request"));
161 /* Check if the IP address exists on the VPN */
163 dest = ntohl(*((unsigned long*)(arp->arp_tpa)));
164 subnet = lookup_subnet_ipv4(&dest);
168 if(debug_lvl >= DEBUG_TRAFFIC)
170 syslog(LOG_WARNING, _("Cannot route packet: ARP request for unknown address %d.%d.%d.%d"),
171 arp->arp_tpa[0], arp->arp_tpa[1], arp->arp_tpa[2], arp->arp_tpa[3]);
177 /* Check if it is for our own subnet */
179 if(subnet->owner == myself)
180 return; /* silently ignore */
182 memcpy(packet->data, packet->data + ETHER_ADDR_LEN, ETHER_ADDR_LEN); /* copy destination address */
183 packet->data[ETHER_ADDR_LEN*2 - 1] ^= 0xFF; /* mangle source address so it looks like it's not from us */
185 memcpy(ipbuf, arp->arp_tpa, 4); /* save protocol addr */
186 memcpy(arp->arp_tpa, arp->arp_spa, 4); /* swap destination and source protocol address */
187 memcpy(arp->arp_spa, ipbuf, 4); /* ... */
189 memcpy(arp->arp_tha, arp->arp_sha, 10); /* set target hard/proto addr */
190 memcpy(arp->arp_sha, packet->data + ETHER_ADDR_LEN, ETHER_ADDR_LEN); /* add fake source hard addr */
191 arp->arp_op = htons(ARPOP_REPLY);
193 accept_packet(packet);
197 void route_outgoing(vpn_packet_t *packet)
199 unsigned short int type;
202 /* FIXME: multicast? */
207 type = ntohs(*((unsigned short*)(&packet->data[12])));
211 cl = route_ipv4(packet);
214 cl = route_ipv6(packet);
220 if(debug_lvl >= DEBUG_TRAFFIC)
222 syslog(LOG_WARNING, _("Cannot route packet: unknown type %hx"), type);
227 send_packet(cl, packet);
231 cl = route_mac(myself, packet);
233 send_packet(cl, packet);
235 broadcast_packet(myself, packet);
239 broadcast_packet(myself, packet);
244 void route_incoming(connection_t *source, vpn_packet_t *packet)
249 memcpy(packet->data, mymac.net.mac.address.x, 6); /* Override destination address to make the kernel accept it */
252 if((packet->data[0] & packet->data[1]) == 0xFF) /* Broadcast? */
253 broadcast_packet(source, packet); /* If yes, spread it on */
255 learn_mac(source, (mac_t *)(&packet->data[6]));
258 broadcast_packet(source,packet); /* Spread it on */
262 accept_packet(packet);