+ subnet_t *subnet;
+
+ cp();
+
+ subnet = lookup_subnet_ipv6((ipv6_t *) &packet->data[38]);
+
+ if(!subnet) {
+ ifdebug(TRAFFIC) logger(LOG_WARNING, _("Cannot route packet from %s (%s): unknown IPv6 destination address %hx:%hx:%hx:%hx:%hx:%hx:%hx:%hx"),
+ source->name, source->hostname,
+ ntohs(*(uint16_t *) &packet->data[38]),
+ ntohs(*(uint16_t *) &packet->data[40]),
+ ntohs(*(uint16_t *) &packet->data[42]),
+ ntohs(*(uint16_t *) &packet->data[44]),
+ ntohs(*(uint16_t *) &packet->data[46]),
+ ntohs(*(uint16_t *) &packet->data[48]),
+ ntohs(*(uint16_t *) &packet->data[50]),
+ ntohs(*(uint16_t *) &packet->data[52]));
+
+ route_ipv6_unreachable(source, packet, ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_ADDR);
+ return;
+ }
+
+ if(subnet->owner == source) {
+ ifdebug(TRAFFIC) logger(LOG_WARNING, _("Packet looping back to %s (%s)!"), source->name, source->hostname);
+ return;
+ }
+
+ if(!subnet->owner->status.reachable)
+ route_ipv6_unreachable(source, packet, ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_NOROUTE);
+
+ if(subnet->owner->options & OPTION_PMTU_DISCOVERY && packet->len > subnet->owner->mtu && subnet->owner != myself) {
+ ifdebug(TRAFFIC) logger(LOG_INFO, _("Packet for %s (%s) length %d larger than MTU %d"), subnet->owner->name, subnet->owner->hostname, packet->len, subnet->owner->mtu);
+ packet->len = subnet->owner->mtu;
+ route_ipv6_unreachable(source, packet, ICMP6_PACKET_TOO_BIG, 0);
+ return;
+ }
+
+ send_packet(subnet->owner, packet);
+}
+
+/* RFC 2461 */
+
+static void route_neighborsol(node_t *source, vpn_packet_t *packet)
+{
+ struct ip6_hdr ip6;
+ struct nd_neighbor_solicit ns;
+ struct nd_opt_hdr opt;