+static void route_mac(node_t *source, vpn_packet_t *packet) {
+ subnet_t *subnet;
+ mac_t dest;
+
+ /* Learn source address */
+
+ if(source == myself) {
+ mac_t src;
+ memcpy(&src, &packet->data[6], sizeof src);
+ learn_mac(&src);
+ }
+
+ /* Lookup destination address */
+
+ memcpy(&dest, &packet->data[0], sizeof dest);
+ subnet = lookup_subnet_mac(NULL, &dest);
+
+ if(!subnet) {
+ broadcast_packet(source, packet);
+ return;
+ }
+
+ if(subnet->owner == source) {
+ ifdebug(TRAFFIC) logger(LOG_WARNING, "Packet looping back to %s (%s)!", source->name, source->hostname);
+ 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;
+
+ if(directonly && subnet->owner != via)
+ return;
+
+ if(via && packet->len > via->mtu && via != myself) {
+ ifdebug(TRAFFIC) logger(LOG_INFO, "Packet for %s (%s) length %d larger than MTU %d", subnet->owner->name, subnet->owner->hostname, packet->len, via->mtu);
+ uint16_t type = packet->data[12] << 8 | packet->data[13];
+ if(type == ETH_P_IP && packet->len > 590) {
+ if(packet->data[20] & 0x40) {
+ packet->len = via->mtu;
+ route_ipv4_unreachable(source, packet, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED);
+ } else {
+ fragment_ipv4_packet(via, packet);
+ }
+ return;
+ } else if(type == ETH_P_IPV6 && packet->len > 1294) {
+ packet->len = via->mtu;
+ route_ipv6_unreachable(source, packet, ICMP6_PACKET_TOO_BIG, 0);
+ return;
+ }
+ }
+
+ clamp_mss(source, via, packet);
+
+ send_packet(subnet->owner, packet);
+}
+
+static void send_pcap(vpn_packet_t *packet) {
+ pcap = false;
+ for(splay_node_t *node = connection_tree->head; node; node = node->next) {
+ connection_t *c = node->data;
+ if(!c->status.pcap)
+ continue;
+ else
+ pcap = true;
+ if(send_request(c, "%d %d %d", CONTROL, REQ_PCAP, packet->len))
+ send_meta(c, (char *)packet->data, packet->len);
+ }
+}
+
+void route(node_t *source, vpn_packet_t *packet) {
+ if(pcap)
+ send_pcap(packet);
+
+ if(forwarding_mode == FMODE_KERNEL && source != myself) {
+ send_packet(myself, packet);
+ return;
+ }