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.10 2001/06/04 11:14:35 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[0]));
84 /* Lookup destination address */
86 subnet = lookup_subnet_mac((mac_t *)(&packet->data[6]));
90 if(debug_lvl >= DEBUG_TRAFFIC)
92 syslog(LOG_WARNING, _("Cannot route packet: unknown destination address %x:%x:%x:%x:%x:%x"),
103 return subnet->owner;
106 connection_t *route_ipv4(vpn_packet_t *packet)
111 dest = ntohl(*((unsigned long*)(&packet->data[30])));
113 subnet = lookup_subnet_ipv4(&dest);
117 if(debug_lvl >= DEBUG_TRAFFIC)
119 syslog(LOG_WARNING, _("Cannot route packet: unknown destination address %d.%d.%d.%d"),
120 packet->data[30], packet->data[31], packet->data[32], packet->data[33]);
126 return subnet->owner;
129 connection_t *route_ipv6(vpn_packet_t *packet)
132 if(debug_lvl > DEBUG_NOTHING)
134 syslog(LOG_WARNING, _("Cannot route packet: IPv6 routing not yet implemented"));
140 void route_arp(vpn_packet_t *packet)
142 struct ether_arp *arp;
144 unsigned char ipbuf[4];
147 /* This routine generates replies to ARP requests.
148 You don't need to set NOARP flag on the interface anymore (which is broken on FreeBSD).
149 Most of the code here is taken from choparp.c by Takamichi Tateoka (tree@mma.club.uec.ac.jp)
152 arp = (struct ether_arp *)(packet->data + 14);
154 /* Check if this is a valid ARP request */
156 if(ntohs(arp->arp_hrd) != ARPHRD_ETHER ||
157 ntohs(arp->arp_pro) != ETHERTYPE_IP ||
158 (int) (arp->arp_hln) != ETHER_ADDR_LEN ||
159 (int) (arp->arp_pln) != 4 ||
160 ntohs(arp->arp_op) != ARPOP_REQUEST )
162 if(debug_lvl > DEBUG_TRAFFIC)
164 syslog(LOG_WARNING, _("Cannot route packet: received unknown type ARP request"));
169 /* Check if the IP address exists on the VPN */
171 dest = ntohl(*((unsigned long*)(arp->arp_tpa)));
172 subnet = lookup_subnet_ipv4(&dest);
176 if(debug_lvl >= DEBUG_TRAFFIC)
178 syslog(LOG_WARNING, _("Cannot route packet: ARP request for unknown address %d.%d.%d.%d"),
179 arp->arp_tpa[0], arp->arp_tpa[1], arp->arp_tpa[2], arp->arp_tpa[3]);
185 /* Check if it is for our own subnet */
187 if(subnet->owner == myself)
188 return; /* silently ignore */
190 memcpy(packet->data, packet->data + ETHER_ADDR_LEN, ETHER_ADDR_LEN); /* copy destination address */
191 packet->data[ETHER_ADDR_LEN*2 - 1] ^= 0xFF; /* mangle source address so it looks like it's not from us */
193 memcpy(ipbuf, arp->arp_tpa, 4); /* save protocol addr */
194 memcpy(arp->arp_tpa, arp->arp_spa, 4); /* swap destination and source protocol address */
195 memcpy(arp->arp_spa, ipbuf, 4); /* ... */
197 memcpy(arp->arp_tha, arp->arp_sha, 10); /* set target hard/proto addr */
198 memcpy(arp->arp_sha, packet->data + ETHER_ADDR_LEN, ETHER_ADDR_LEN); /* add fake source hard addr */
199 arp->arp_op = htons(ARPOP_REPLY);
201 accept_packet(packet);
205 void route_outgoing(vpn_packet_t *packet)
207 unsigned short int type;
211 /* FIXME: multicast? */
216 type = ntohs(*((unsigned short*)(&packet->data[12])));
220 cl = route_ipv4(packet);
223 cl = route_ipv6(packet);
229 if(debug_lvl >= DEBUG_TRAFFIC)
231 syslog(LOG_WARNING, _("Cannot route packet: unknown type %hx"), type);
236 send_packet(cl, packet);
240 cl = route_mac(myself, packet);
242 send_packet(cl, packet);
246 for(node = connection_tree->head; node; node = node->next)
248 cl = (connection_t *)node->data;
249 if(cl->status.active)
250 send_packet(cl, packet);
256 void route_incoming(connection_t *source, vpn_packet_t *packet)
261 memcpy(packet->data, mymac.net.mac.address.x, 6);
264 learn_mac(source, (mac_t *)(&packet->data[0]));
268 accept_packet(packet);