Add the Forwarding option.
[oweals/tinc.git] / src / route.c
index 87f08ce9e40d855f0633ea7ff08cb4f7eedc2b5c..1f91db9729588d128848cbc2951118555c8ad6c5 100644 (file)
@@ -1,7 +1,7 @@
 /*
     route.c -- routing
     Copyright (C) 2000-2005 Ivo Timmermans,
-                  2000-2009 Guus Sliepen <guus@tinc-vpn.org>
+                  2000-2010 Guus Sliepen <guus@tinc-vpn.org>
 
     This program is free software; you can redistribute it and/or modify
     it under the terms of the GNU General Public License as published by
@@ -33,6 +33,7 @@
 #include "utils.h"
 
 rmode_t routing_mode = RMODE_ROUTER;
+fmode_t forwarding_mode = FMODE_INTERNAL;
 bool priorityinheritance = false;
 int macexpire = 600;
 bool overwrite_mac = false;
@@ -94,9 +95,13 @@ static bool checklength(node_t *source, vpn_packet_t *packet, length_t length) {
 }
 
 static void clamp_mss(const node_t *source, const node_t *via, vpn_packet_t *packet) {
-       if(!via || via == myself || !(via->options & OPTION_CLAMP_MSS))
+       if(!source || !via || !(via->options & OPTION_CLAMP_MSS))
                return;
 
+       uint16_t mtu = source->mtu;
+       if(via != myself && via->mtu < mtu)
+               mtu = via->mtu;
+
        /* Find TCP header */
        int start = 0;
        uint16_t type = packet->data[12] << 8 | packet->data[13];
@@ -140,7 +145,7 @@ static void clamp_mss(const node_t *source, const node_t *via, vpn_packet_t *pac
 
                /* Found it */
                uint16_t oldmss = packet->data[start + 22 + i] << 8 | packet->data[start + 23 + i];
-               uint16_t newmss = via->mtu - start - 20;
+               uint16_t newmss = mtu - start - 20;
                uint16_t csum = packet->data[start + 16] << 8 | packet->data[start + 17];
 
                if(oldmss <= newmss)
@@ -379,7 +384,10 @@ static void route_ipv4_unicast(node_t *source, vpn_packet_t *packet) {
        }
 
        if(!subnet->owner->status.reachable)
-               route_ipv4_unreachable(source, packet, ICMP_DEST_UNREACH, ICMP_NET_UNREACH);
+               return route_ipv4_unreachable(source, packet, ICMP_DEST_UNREACH, ICMP_NET_UNREACH);
+
+       if(forwarding_mode == FMODE_OFF && source != myself && subnet->owner != myself)
+               return route_ipv4_unreachable(source, packet, ICMP_DEST_UNREACH, ICMP_NET_ANO);
 
        if(priorityinheritance)
                packet->priority = packet->data[15];
@@ -527,7 +535,10 @@ static void route_ipv6_unicast(node_t *source, vpn_packet_t *packet) {
        }
 
        if(!subnet->owner->status.reachable)
-               route_ipv6_unreachable(source, packet, ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_NOROUTE);
+               return route_ipv6_unreachable(source, packet, ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_NOROUTE);
+
+       if(forwarding_mode == FMODE_OFF && source != myself && subnet->owner != myself)
+               return route_ipv6_unreachable(source, packet, ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_ADMIN);
 
        via = (subnet->owner->via == myself) ? subnet->owner->nexthop : subnet->owner->via;
        
@@ -792,6 +803,9 @@ static void route_mac(node_t *source, vpn_packet_t *packet) {
                return;
        }
 
+       if(forwarding_mode == FMODE_OFF && source != myself && subnet->owner != myself)
+               return;
+
        // Handle packets larger than PMTU
 
        node_t *via = (subnet->owner->via == myself) ? subnet->owner->nexthop : subnet->owner->via;
@@ -820,6 +834,11 @@ static void route_mac(node_t *source, vpn_packet_t *packet) {
 }
 
 void route(node_t *source, vpn_packet_t *packet) {
+       if(forwarding_mode == FMODE_KERNEL) {
+               send_packet(myself, packet);
+               return;
+       }
+
        if(!checklength(source, packet, ether_size))
                return;