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.11 2001/06/05 16:09:55 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 /* This routine generates replies to ARP requests.
136 You don't need to set NOARP flag on the interface anymore (which is broken on FreeBSD).
137 Most of the code here is taken from choparp.c by Takamichi Tateoka (tree@mma.club.uec.ac.jp)
140 arp = (struct ether_arp *)(packet->data + 14);
142 /* Check if this is a valid ARP request */
144 if(ntohs(arp->arp_hrd) != ARPHRD_ETHER ||
145 ntohs(arp->arp_pro) != ETHERTYPE_IP ||
146 (int) (arp->arp_hln) != ETHER_ADDR_LEN ||
147 (int) (arp->arp_pln) != 4 ||
148 ntohs(arp->arp_op) != ARPOP_REQUEST )
150 if(debug_lvl > DEBUG_TRAFFIC)
152 syslog(LOG_WARNING, _("Cannot route packet: received unknown type ARP request"));
157 /* Check if the IP address exists on the VPN */
159 dest = ntohl(*((unsigned long*)(arp->arp_tpa)));
160 subnet = lookup_subnet_ipv4(&dest);
164 if(debug_lvl >= DEBUG_TRAFFIC)
166 syslog(LOG_WARNING, _("Cannot route packet: ARP request for unknown address %d.%d.%d.%d"),
167 arp->arp_tpa[0], arp->arp_tpa[1], arp->arp_tpa[2], arp->arp_tpa[3]);
173 /* Check if it is for our own subnet */
175 if(subnet->owner == myself)
176 return; /* silently ignore */
178 memcpy(packet->data, packet->data + ETHER_ADDR_LEN, ETHER_ADDR_LEN); /* copy destination address */
179 packet->data[ETHER_ADDR_LEN*2 - 1] ^= 0xFF; /* mangle source address so it looks like it's not from us */
181 memcpy(ipbuf, arp->arp_tpa, 4); /* save protocol addr */
182 memcpy(arp->arp_tpa, arp->arp_spa, 4); /* swap destination and source protocol address */
183 memcpy(arp->arp_spa, ipbuf, 4); /* ... */
185 memcpy(arp->arp_tha, arp->arp_sha, 10); /* set target hard/proto addr */
186 memcpy(arp->arp_sha, packet->data + ETHER_ADDR_LEN, ETHER_ADDR_LEN); /* add fake source hard addr */
187 arp->arp_op = htons(ARPOP_REPLY);
189 accept_packet(packet);
193 void route_outgoing(vpn_packet_t *packet)
195 unsigned short int type;
198 /* FIXME: multicast? */
203 type = ntohs(*((unsigned short*)(&packet->data[12])));
207 cl = route_ipv4(packet);
210 cl = route_ipv6(packet);
216 if(debug_lvl >= DEBUG_TRAFFIC)
218 syslog(LOG_WARNING, _("Cannot route packet: unknown type %hx"), type);
223 send_packet(cl, packet);
227 cl = route_mac(myself, packet);
229 send_packet(cl, packet);
231 broadcast_packet(myself, packet);
235 broadcast_packet(myself, packet);
240 void route_incoming(connection_t *source, vpn_packet_t *packet)
245 memcpy(packet->data, mymac.net.mac.address.x, 6); /* Override destination address to make the kernel accept it */
248 if((packet->data[0] & packet->data[1]) == 0xFF) /* Broadcast? */
249 broadcast_packet(source, packet); /* If yes, spread it on */
251 learn_mac(source, (mac_t *)(&packet->data[6]));
254 broadcast_packet(source,packet); /* Spread it on */
258 accept_packet(packet);