+ /* Copy first part of original contents to ICMP message */
+
+ memmove(DATA(packet) + ether_size + ip6_size + icmp6_size, DATA(packet) + ether_size, pseudo.length);
+
+ /* Fill in IPv6 header */
+
+ ip6.ip6_flow = htonl(0x60000000UL);
+ ip6.ip6_plen = htons(icmp6_size + pseudo.length);
+ ip6.ip6_nxt = IPPROTO_ICMPV6;
+ ip6.ip6_hlim = 255;
+ ip6.ip6_src = pseudo.ip6_src;
+ ip6.ip6_dst = pseudo.ip6_dst;
+
+ /* Fill in ICMP header */
+
+ icmp6.icmp6_type = type;
+ icmp6.icmp6_code = code;
+ icmp6.icmp6_cksum = 0;
+
+ /* Create pseudo header */
+
+ pseudo.length = htonl(icmp6_size + pseudo.length);
+ pseudo.next = htonl(IPPROTO_ICMPV6);
+
+ /* Generate checksum */
+
+ checksum = inet_checksum(&pseudo, sizeof(pseudo), 0xFFFF);
+ checksum = inet_checksum(&icmp6, icmp6_size, checksum);
+ checksum = inet_checksum(DATA(packet) + ether_size + ip6_size + icmp6_size, ntohl(pseudo.length) - icmp6_size, checksum);
+
+ icmp6.icmp6_cksum = checksum;
+
+ /* Copy structs on stack back to packet */
+
+ memcpy(DATA(packet) + ether_size, &ip6, ip6_size);
+ memcpy(DATA(packet) + ether_size + ip6_size, &icmp6, icmp6_size);
+
+ packet->len = ether_size + ip6_size + ntohl(pseudo.length);
+
+ send_packet(source, packet);
+}
+
+static bool do_decrement_ttl(node_t *source, vpn_packet_t *packet) {
+ uint16_t type = DATA(packet)[12] << 8 | DATA(packet)[13];
+ length_t ethlen = ether_size;
+
+ if(type == ETH_P_8021Q) {
+ type = DATA(packet)[16] << 8 | DATA(packet)[17];
+ ethlen += 4;