+static struct event age_subnets_event;
+
+/* 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;
+ time_t now = time(NULL);
+
+ 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;
+}
+
+static void swap_mac_addresses(vpn_packet_t *packet) {
+ mac_t tmp;
+ memcpy(&tmp, &packet->data[0], sizeof tmp);
+ memcpy(&packet->data[0], &packet->data[6], sizeof tmp);
+ memcpy(&packet->data[6], &tmp, sizeof tmp);
+}
+
+static void age_subnets(int fd, short events, void *data)
+{
+ subnet_t *s;
+ connection_t *c;
+ splay_node_t *node, *next, *node2;
+ bool left = false;
+ time_t now = time(NULL);
+
+ cp();
+
+ for(node = myself->subnet_tree->head; node; node = next) {
+ next = node->next;
+ s = node->data;
+ if(s->expires && s->expires < now) {
+ ifdebug(TRAFFIC) {
+ char netstr[MAXNETSTR];
+ if(net2str(netstr, sizeof netstr, s))
+ logger(LOG_INFO, _("Subnet %s expired"), netstr);
+ }
+
+ for(node2 = connection_tree->head; node2; node2 = node2->next) {
+ c = node2->data;
+ if(c->status.active)
+ send_del_subnet(c, s);
+ }
+
+ subnet_del(myself, s);
+ } else {
+ if(s->expires)
+ left = true;
+ }
+ }
+
+ if(left)
+ event_add(&age_subnets_event, &(struct timeval){10, 0});
+}
+
+static void learn_mac(mac_t *address)