diff -urN -x '*.info*' tinc-1.0.8-org/src/net_packet.c tinc-1.0.8/src/net_packet.c --- tinc-1.0.8-org/src/net_packet.c 2006-12-16 12:46:40.000000000 +0100 @@ -452,6 +453,7 @@ { avl_node_t *node; connection_t *c; + uint16_t type; cp(); @@ -464,8 +466,21 @@ for(node = connection_tree->head; node; node = node->next) { c = node->data; - if(c->status.active && c->status.mst && c != from->nexthop->connection) + if(c->status.active && c->status.mst && c != from->nexthop->connection) { + if(c->node->mtu < packet->len) { + ifdebug(TRAFFIC) logger(LOG_INFO, _("Packet for %s (%s) length %d larger than MTU %d"), c->node->name, c->node->hostname, packet->len, c->node->mtu); + + type = ntohs(*((uint16_t *)(&packet->data[12]))); + + if(type == ETH_P_IP) { + if(!(packet->data[20] & 0x40)) { + fragment_ipv4_packet(c->node, packet); + continue; + } + } + } send_packet(c->node, packet); + } } } diff -urN -x '*.info*' tinc-1.0.8-org/src/route.c tinc-1.0.8/src/route.c --- tinc-1.0.8-org/src/route.c 2006-08-10 00:31:33.000000000 +0200 +++ tinc-1.0.8/src/route.c 2007-07-06 08:57:28.000000000 +0200 @@ -163,6 +163,7 @@ static void route_mac(node_t *source, vpn_packet_t *packet) { subnet_t *subnet; + uint16_t type; mac_t dest; cp(); @@ -191,12 +195,35 @@ return; } + if(packet->len > subnet->owner->mtu) { + 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); + + type = ntohs(*((uint16_t *)(&packet->data[12]))); + + if(type == ETH_P_IP) { + + if(packet->data[20] & 0x40) { + packet->len = subnet->owner->mtu; + logger(LOG_DEBUG, _("Sending ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED to %s"), source->hostname); + memcpy(&packet->data[0], &packet->data[6], sizeof(mac_t)); + memcpy(&packet->data[6], &dest, sizeof(mac_t)); + route_ipv4_unreachable(source, packet, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED); + } else { + fragment_ipv4_packet(subnet->owner, packet); + } + + return; + } + + // else ? + } + send_packet(subnet->owner, packet); } /* RFC 792 */ -static void route_ipv4_unreachable(node_t *source, vpn_packet_t *packet, uint8_t type, uint8_t code) +void route_ipv4_unreachable(node_t *source, vpn_packet_t *packet, uint8_t type, uint8_t code) { struct ip ip = {0}; struct icmp icmp = {0}; @@ -268,7 +295,7 @@ /* RFC 791 */ -static void fragment_ipv4_packet(node_t *dest, vpn_packet_t *packet) { +void fragment_ipv4_packet(node_t *dest, vpn_packet_t *packet) { struct ip ip; vpn_packet_t fragment; int len, maxlen, todo; diff -urN -x '*.info*' tinc-1.0.8-org/src/route.h tinc-1.0.8/src/route.h --- tinc-1.0.8-org/src/route.h 2006-04-26 15:53:05.000000000 +0200 +++ tinc-1.0.8/src/route.h 2007-07-06 08:57:08.000000000 +0200 @@ -42,4 +42,7 @@ extern void age_subnets(void); extern void route(struct node_t *, struct vpn_packet_t *); +extern void route_ipv4_unreachable(node_t *source, vpn_packet_t *packet, uint8_t type, uint8_t code); +extern void fragment_ipv4_packet(node_t *dest, vpn_packet_t *packet); + #endif /* __TINC_ROUTE_H__ */