+static const size_t ether_size = sizeof(struct ether_header);
+static const size_t arp_size = sizeof(struct ether_arp);
+static const size_t ip_size = sizeof(struct ip);
+static const size_t icmp_size = sizeof(struct icmp) - sizeof(struct ip);
+static const size_t ip6_size = sizeof(struct ip6_hdr);
+static const size_t icmp6_size = sizeof(struct icmp6_hdr);
+static const size_t ns_size = sizeof(struct nd_neighbor_solicit);
+static const size_t opt_size = sizeof(struct nd_opt_hdr);
+#define max(a, b) ((a) > (b) ? (a) : (b))
+
+/* RFC 1071 */
+
+static uint16_t inet_checksum(void *data, int len, uint16_t prevsum) {
+ uint16_t *p = data;
+ uint32_t checksum = prevsum ^ 0xFFFF;
+
+ while(len >= 2) {
+ checksum += *p++;
+ len -= 2;
+ }
+
+ if(len)
+ checksum += *(uint8_t *)p;
+
+ while(checksum >> 16)
+ checksum = (checksum & 0xFFFF) + (checksum >> 16);
+
+ return ~checksum;
+}
+
+static bool ratelimit(int frequency) {
+ static time_t lasttime = 0;
+ static int count = 0;
+
+ if(lasttime == now) {
+ if(++count > frequency)
+ return true;
+ } else {
+ lasttime = now;
+ count = 0;
+ }
+
+ return false;
+}
+
+static bool checklength(node_t *source, vpn_packet_t *packet, length_t length) {
+ if(packet->len < length) {
+ ifdebug(TRAFFIC) logger(LOG_WARNING, "Got too short packet from %s (%s)", source->name, source->hostname);
+ return false;
+ } else
+ return true;
+}
+
+void clamp_mss(node_t *source, node_t *via, vpn_packet_t *packet) {
+ int i;
+ int len = ((packet->data[46] >> 4) - 5) * 4;
+
+ for(int i = 0; i < len;) {
+ if(packet->data[54 + i] == 0)
+ break;
+
+ if(packet->data[54 + i] == 1) {
+ i++;
+ continue;
+ }
+
+ if(i > len - 2 || i > len - packet->data[55 + i])
+ break;
+
+ if(packet->data[54 + i] != 2) {
+ if(packet->data[55 + i] < 2)
+ break;
+ i += packet->data[55 + i];
+ continue;
+ }
+
+ if(packet->data[55] != 4)
+ break;
+
+ uint16_t oldmss = packet->data[56 + i] << 8 | packet->data[57 + i];
+ uint16_t newmss = via->mtu - 54;
+ uint16_t csum = packet->data[50] << 8 | packet->data[51];
+
+ if(oldmss <= newmss)
+ break;
+
+ ifdebug(TRAFFIC) logger(LOG_INFO, "Clamping MSS of packet from %s to %s to %d", source->name, via->name, newmss);
+
+ packet->data[56 + i] = newmss >> 8;
+ packet->data[57 + i] = newmss & 0xff;
+ csum ^= 0xffff;
+ csum -= oldmss;
+ csum += newmss;
+ csum ^= 0xffff;
+ packet->data[50] = csum >> 8;
+ packet->data[51] = csum & 0xff;
+ break;
+ }
+}