along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id: route.c,v 1.1.2.27 2002/03/01 14:25:10 guus Exp $
+ $Id: route.c,v 1.1.2.31 2002/03/11 13:56:00 guus Exp $
*/
#include "config.h"
#else
#include <net/ethernet.h>
#endif
+#include <netinet/ip6.h>
+#include <netinet/icmp6.h>
#include <netinet/if_ether.h>
#include <utils.h>
#include <xalloc.h>
int macexpire = 600;
subnet_t mymac;
+#ifdef HAVE_FREEBSD
+#define s6_addr16 __u6_addr.__u6_addr16
+#endif
+
void learn_mac(mac_t *address)
{
subnet_t *subnet;
cp
for(node = myself->subnet_tree->head; node; node = next)
{
+ next = node->next;
s = (subnet_t *)node->data;
if(s->type == SUBNET_MAC && s->net.mac.lastseen && s->net.mac.lastseen + macexpire < now)
{
return subnet->owner;
}
+node_t *route_neighborsol(vpn_packet_t *packet)
+{
+ struct ip6_hdr *hdr;
+ struct nd_neighbor_solicit *ns;
+ subnet_t *subnet;
+cp
+ hdr = (struct ip6_hdr *)(packet->data + 14);
+ ns = (struct nd_neighbor_solicit *)(packet->data + 14 + sizeof(struct ip6_hdr));
+
+ /* First, snatch the source address from the neighbor solicitation packet */
+
+ memcpy(mymac.net.mac.address.x, packet->data + 6, 6);
+
+ /* Check if this is a valid neighbor solicitation request */
+
+ if(ns->nd_ns_hdr.icmp6_type != ND_NEIGHBOR_SOLICIT)
+ {
+ if(debug_lvl > DEBUG_TRAFFIC)
+ {
+ syslog(LOG_WARNING, _("Cannot route packet: received unknown type neighbor solicitation request"));
+ }
+ return;
+ }
+
+ /* Check if the IPv6 address exists on the VPN */
+
+ subnet = lookup_subnet_ipv6((ipv6_t *)&ns->nd_ns_target);
+
+ if(!subnet)
+ {
+ if(debug_lvl >= DEBUG_TRAFFIC)
+ {
+ syslog(LOG_WARNING, _("Cannot route packet: neighbor solicitation request for unknown address %hx:%hx:%hx:%hx:%hx:%hx:%hx:%hx"),
+ ntohs(ns->nd_ns_target.s6_addr16[0]), ntohs(ns->nd_ns_target.s6_addr16[1]), ntohs(ns->nd_ns_target.s6_addr16[2]), ntohs(ns->nd_ns_target.s6_addr16[3]),
+ ntohs(ns->nd_ns_target.s6_addr16[4]), ntohs(ns->nd_ns_target.s6_addr16[5]), ntohs(ns->nd_ns_target.s6_addr16[6]), ntohs(ns->nd_ns_target.s6_addr16[7]));
+ }
+
+ return NULL;
+ }
+
+ /* Check if it is for our own subnet */
+
+ if(subnet->owner == myself)
+ return NULL; /* silently ignore */
+
+ /* Forward to destination */
+
+ return subnet->owner;
+cp
+}
+
void route_arp(vpn_packet_t *packet)
{
struct ether_arp *arp;
return;
}
- /* Check if the IP address exists on the VPN */
+ /* Check if the IPv4 address exists on the VPN */
subnet = lookup_subnet_ipv4((ipv4_t *)arp->arp_tpa);
void route_outgoing(vpn_packet_t *packet)
{
unsigned short int type;
- node_t *n;
+ node_t *n = NULL;
cp
/* FIXME: multicast? */
break;
case 0x86DD:
n = route_ipv6(packet);
+ if(!n && packet->data[0] == 0x33 && packet->data[1] == 0x33 && packet->data[2] == 0xff)
+ n = route_neighborsol(packet);
break;
case 0x0806:
route_arp(packet);
{
case RMODE_ROUTER:
{
- node_t *n;
+ node_t *n = NULL;
+ unsigned short int type;
- n = route_ipv4(packet);
+ type = ntohs(*((unsigned short*)(&packet->data[12])));
+ switch(type)
+ {
+ case 0x0800:
+ n = route_ipv4(packet);
+ break;
+ case 0x86DD:
+ n = route_ipv6(packet);
+ break;
+ default:
+ n = myself;
+ break;
+ }
if(n)
{