+ node_t *via;
+ ipv4_t dest;
+
+ memcpy(&dest, &DATA(packet)[30], sizeof dest);
+ subnet = lookup_subnet_ipv4(&dest);
+
+ if(!subnet) {
+ logger(DEBUG_TRAFFIC, LOG_WARNING, "Cannot route packet from %s (%s): unknown IPv4 destination address %d.%d.%d.%d",
+ source->name, source->hostname,
+ dest.x[0],
+ dest.x[1],
+ dest.x[2],
+ dest.x[3]);
+
+ route_ipv4_unreachable(source, packet, ether_size, ICMP_DEST_UNREACH, ICMP_NET_UNKNOWN);
+ return;
+ }
+
+ if (!subnet->owner) {
+ route_broadcast(source, packet);
+ return;
+ }
+
+ if(subnet->owner == source) {
+ logger(DEBUG_TRAFFIC, LOG_WARNING, "Packet looping back to %s (%s)!", source->name, source->hostname);
+ return;
+ }
+
+ if(!subnet->owner->status.reachable)
+ return route_ipv4_unreachable(source, packet, ether_size, ICMP_DEST_UNREACH, ICMP_NET_UNREACH);
+
+ if(forwarding_mode == FMODE_OFF && source != myself && subnet->owner != myself)
+ return route_ipv4_unreachable(source, packet, ether_size, ICMP_DEST_UNREACH, ICMP_NET_ANO);
+
+ if(decrement_ttl && source != myself && subnet->owner != myself)
+ if(!do_decrement_ttl(source, packet))
+ return;
+
+ if(priorityinheritance)
+ packet->priority = DATA(packet)[15];
+
+ via = (subnet->owner->via == myself) ? subnet->owner->nexthop : subnet->owner->via;
+
+ if(via == source) {
+ logger(DEBUG_TRAFFIC, LOG_ERR, "Routing loop for packet from %s (%s)!", source->name, source->hostname);
+ return;
+ }
+
+ if(directonly && subnet->owner != via)
+ return route_ipv4_unreachable(source, packet, ether_size, ICMP_DEST_UNREACH, ICMP_NET_ANO);
+
+ if(via && packet->len > MAX(via->mtu, 590) && via != myself) {
+ logger(DEBUG_TRAFFIC, LOG_INFO, "Packet for %s (%s) length %d larger than MTU %d", subnet->owner->name, subnet->owner->hostname, packet->len, via->mtu);
+ if(DATA(packet)[20] & 0x40) {
+ packet->len = MAX(via->mtu, 590);
+ route_ipv4_unreachable(source, packet, ether_size, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED);
+ } else {
+ fragment_ipv4_packet(via, packet, ether_size);
+ }
+
+ return;
+ }
+
+ clamp_mss(source, via, packet);
+
+ send_packet(subnet->owner, packet);
+}
+
+static void route_neighborsol(node_t *source, vpn_packet_t *packet);
+
+static void route_ipv6(node_t *source, vpn_packet_t *packet) {
+ if(!checklength(source, packet, ether_size + ip6_size))
+ return;