Implemented reply to fe80::/64 NgbSol, debugged a v4/v6 buffer choice
[6bed4] / peer.c
1 /* 6bed4/peer.c -- Peer-to-Peer IPv6-anywhere with 6bed4 -- peer.c
2  *
3  * This is an implementation of neighbour and router discovery over a
4  * tunnel that packs IPv6 inside UDP/IPv4.  This tunnel mechanism is
5  * so efficient that the server administrators need not mind if it is
6  * distributed widely.
7  *
8  * From: Rick van Rein <rick@openfortress.nl>
9  */
10
11
12 #include <stdlib.h>
13 #include <stdbool.h>
14 #include <stdint.h>
15 #include <stdio.h>
16 #include <errno.h>
17 #include <unistd.h>
18 #include <string.h>
19 #include <getopt.h>
20 #include <fcntl.h>
21
22 #include <syslog.h>
23 #ifndef LOG_PERROR
24 #define LOG_PERROR LOG_CONS             /* LOG_PERROR is non-POSIX, LOG_CONS is */
25 #endif
26
27 #include <sys/types.h>
28 #include <sys/socket.h>
29 #include <sys/time.h>
30 #include <sys/select.h>
31 #include <sys/ioctl.h>
32
33 #include <netinet/in.h>
34 #include <netinet/ip.h>
35 #include <netinet/ip6.h>
36 #include <netinet/udp.h>
37 #include <netinet/icmp6.h>
38 #include <arpa/inet.h>
39
40 #include <asm/types.h>
41 #include <linux/if.h>
42 #include <linux/if_tun.h>
43 #include <linux/if_ether.h>
44 #include <linux/netlink.h>
45 #include <linux/rtnetlink.h>
46
47 /* The following will initially fail, due to an IANA obligation to avoid
48  * default builds with non-standard options.
49  */
50 #include "nonstd.h"
51
52
53 #define MTU 1280
54
55 typedef enum {
56         METRIC_LOW,
57         METRIC_MEDIUM,
58         METRIC_HIGH
59 } metric_t;
60
61 /*
62  * The HAVE_SETUP_TUNNEL variable is used to determine whether absense of
63  * the -t option leads to an error, or to an attempt to setup the tunnel.
64  * The setup_tunnel() function used for that is defined per platform, such
65  * as for LINUX.  Remember to maintain the manpage's optionality for -t.
66  */
67 #undef HAVE_SETUP_TUNNEL
68
69
70 /* Global variables */
71
72 char *program;
73
74 int rtsox = -1;
75 int v4sox = -1;
76 int v6sox = -1;
77 int v4mcast = -1;
78
79 uint8_t v4qos = 0;              /* Current QoS setting on UDP/IPv4 socket */
80 uint32_t v6tc = 0;              /* Current QoS used by the IPv6 socket */
81 uint8_t v4ttl = 64;             /* Default TTL setting on UDP/IPv4 socket */
82 int v4ttl_mcast = -1;           /* Multicast TTL for LAN explorations */
83
84 char *v4server = NULL;
85 char *v6server = NULL;
86 char v6prefix [INET6_ADDRSTRLEN];
87 uint8_t v6lladdr [6];
88
89 const uint8_t v6listen_linklocal [16] = { 0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
90 uint8_t v6listen_linklocal_complete [16] = { 0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
91
92 struct sockaddr_nl rtname;
93 struct sockaddr_nl rtkernel;
94
95 struct sockaddr_in  v4name;
96 struct sockaddr_in  v4peer;
97 struct sockaddr_in6 v6name;
98
99 struct sockaddr_in v4bind;
100 struct sockaddr_in v4allnodes;
101
102 struct in6_addr v6listen;
103 //TODO:NEEDNOT// struct in6_addr v6listen_complete;
104 struct in_addr  v4listen;
105
106
107 struct {
108         struct ethhdr eth;
109         union {
110                 struct {
111                         struct ip6_hdr v6hdr;
112                         uint8_t data [MTU - sizeof (struct ip6_hdr)];
113                 } idata;
114                 struct {
115                         struct ip6_hdr v6hdr;
116                         struct icmp6_hdr v6icmphdr;
117                 } ndata;
118         } udata;
119 } __attribute__((packed)) v4data6;
120
121 #define v4ether         (v4data6.eth)
122 #define v4data          ((uint8_t *) &v4data6.udata)
123 #define v4hdr6          (&v4data6.udata.idata.v6hdr)
124 #define v4src6          (&v4data6.udata.idata.v6hdr.ip6_src)
125 #define v4dst6          (&v4data6.udata.idata.v6hdr.ip6_dst)
126
127 #define v4v6plen        (v4data6.udata.ndata.v6hdr.ip6_plen)
128 #define v4v6nexthdr     (v4data6.udata.ndata.v6hdr.ip6_nxt)
129 #define v4v6hoplimit    (v4data6.udata.ndata.v6hdr.ip6_hops)
130
131 #define v4icmp6         (&v4data6.udata.ndata.v6icmphdr)
132 #define v4v6icmpdata    (v4data6.udata.ndata.v6icmphdr.icmp6_data8)
133 #define v4v6icmptype    (v4data6.udata.ndata.v6icmphdr.icmp6_type)
134 #define v4v6icmpcode    (v4data6.udata.ndata.v6icmphdr.icmp6_code)
135 #define v4v6icmpcksum   (v4data6.udata.ndata.v6icmphdr.icmp6_cksum)
136 #define v4v6ndtarget    (&v4data6.udata.ndata.v6icmphdr.icmp6_data8 [4])
137
138
139 struct {
140         struct ethhdr eth;
141         union {
142                 uint8_t data [MTU];
143                 struct {
144                         struct ip6_hdr v6hdr;
145                         struct icmp6_hdr v6icmp;
146                 } __attribute__((packed)) ndata;
147         } udata;
148 }  __attribute__((packed)) v6data6;
149
150 #define v6ether         (v6data6.eth)
151 #define v6data          (v6data6.udata.data)
152 #define v6hdr6          (&v6data6.udata.ndata.v6hdr)
153 #define v6hops          (v6data6.udata.ndata.v6hdr.ip6_hops)
154 #define v6type          (v6data6.udata.ndata.v6hdr.ip6_nxt)
155 #define v6plen          (v6data6.udata.ndata.v6hdr.ip6_plen)
156 #define v6src6          (&v6data6.udata.ndata.v6hdr.ip6_src)
157 #define v6dst6          (&v6data6.udata.ndata.v6hdr.ip6_dst)
158 #define v6icmp6type     (v6data6.udata.ndata.v6icmp.icmp6_type)
159 #define v6icmp6code     (v6data6.udata.ndata.v6icmp.icmp6_code)
160 #define v6icmp6data     (v6data6.udata.ndata.v6icmp.icmp6_data8)
161 #define v6icmp6csum     (v6data6.udata.ndata.v6icmp.icmp6_cksum)
162 #define v6ndtarget      (&v6data6.udata.ndata.v6icmp.icmp6_data16[2])
163
164
165 /* Structure for tasks in neighbor discovery queues
166  */
167 struct ndqueue {
168         struct ndqueue *next;
169         struct timeval tv;
170         struct in6_addr source;
171         struct in6_addr target;
172         uint8_t source_lladdr [6];
173         uint8_t todo_lancast, todo_direct;
174 };
175
176 /* Round-robin queue for regular tasks, starting at previous value */
177 struct ndqueue *ndqueue = NULL;
178 struct ndqueue *freequeue = NULL;
179 uint32_t freequeue_items = 100;
180
181 /* The time for the next scheduled maintenance: routersol or keepalive.
182  * The milliseconds are always 0 for maintenance tasks.
183  */
184 time_t maintenance_time_sec;
185 time_t maintenance_time_cycle = 0;
186 time_t maintenance_time_cycle_max = 30;
187 bool got_lladdr = false;
188 time_t keepalive_period = 30;
189 time_t keepalive_ttl = -1;
190
191 /* The network packet structure of a 6bed4 Router Solicitation */
192
193 uint8_t ipv6_router_solicitation [] = {
194         // IPv6 header
195         0x60, 0x00, 0x00, 0x00,
196         16 / 256, 16 % 256, IPPROTO_ICMPV6, 255,
197         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,          // unspecd src
198         0xff, 0x02, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x02, // all-rtr tgt
199         // ICMPv6 header: router solicitation
200         ND_ROUTER_SOLICIT, 0, 0x7a, 0xae,       // Checksum courtesy of WireShark :)
201         // ICMPv6 body: reserved
202         0, 0, 0, 0,
203         // ICMPv6 option: source link layer address 0x0001 (end-aligned)
204         0x01, 0x01, 0, 0, 0, 0, 0x00, 0x01,
205 };
206
207 uint8_t ipv6_defaultrouter_neighbor_advertisement [] = {
208         // IPv6 header
209         0x60, 0x00, 0x00, 0x00,
210         32 / 256, 32 % 256, IPPROTO_ICMPV6, 255,
211         0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   // src is default router
212         0xff, 0x02, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x01,// dst is all-nodes multicast, portable?
213         // ICMPv6 header: neighbor solicitation
214         ND_NEIGHBOR_ADVERT, 0, 0x36, 0xf2,              // Checksum courtesy of WireShark :)
215         // ICMPv6 Neighbor Advertisement: flags
216         0x40, 0, 0, 0,
217         // Target: fe80::
218         0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   // the targeted neighbor
219         // ICMPv6 option: target link layer address
220         2, 1,
221         UDP_PORT_6BED4 % 256, UDP_PORT_6BED4 / 256,
222         SERVER_6BED4_IPV4_INT0, SERVER_6BED4_IPV4_INT1, SERVER_6BED4_IPV4_INT2, SERVER_6BED4_IPV4_INT3
223 };
224
225 uint8_t router_linklocal_address [] = {
226         0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x00, 0x00,
227 };
228
229 //TODO// Complete with the if-id of the 6bed4 Router:
230 uint8_t router_linklocal_address_complete [] = {
231         0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x00, 0x00,
232 };
233
234 uint8_t democlient_linklocal_address [] = {
235         0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x00, 0x01,
236 };
237
238 uint8_t allnodes_linklocal_address [] = {
239         0xff, 0x02, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x00, 0x01,
240 };
241
242 uint8_t allrouters_linklocal_address [] = {
243         0xff, 0x02, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x00, 0x02,
244 };
245
246 uint8_t solicitednodes_linklocal_prefix [13] = {
247         0xff, 0x02, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x01, 0xff
248 };
249
250 bool default_route = false;
251
252 bool foreground = false;
253
254 bool log_to_stderr = false;
255
256 bool multicast = true;
257
258
259 /*
260  *
261  * Driver routines
262  *
263  */
264
265 #ifdef LINUX
266 #define HAVE_SETUP_TUNNEL
267 static struct ifreq ifreq;
268 static bool have_tunnel = false;
269 /* Implement the setup_tunnel() command for Linux.
270  * Return true on success, false on failure.
271  */
272 bool setup_tunnel (void) {
273         if (v6sox == -1) {
274                 v6sox = open ("/dev/net/tun", O_RDWR);
275         }
276         if (v6sox == -1) {
277                 syslog (LOG_ERR, "%s: Failed to access tunnel driver on /dev/net/tun: %s\n", program, strerror (errno));
278                 return 0;
279         }
280         bool ok = true;
281         int flags = fcntl (v6sox, F_GETFL, 0);
282         if (flags == -1) {
283                 syslog (LOG_CRIT, "Failed to retrieve flags for the tunnel file descriptor: %s\n", strerror (errno));
284                 ok = false;
285         }
286         if (!have_tunnel) {
287                 memset (&ifreq, 0, sizeof (ifreq));
288                 strncpy (ifreq.ifr_name, "6bed4", IFNAMSIZ);
289                 ifreq.ifr_flags = IFF_TAP | IFF_NO_PI;
290                 if (ok && (ioctl (v6sox, TUNSETIFF, (void *) &ifreq) == -1)) {
291                         syslog (LOG_CRIT, "Failed to set interface name: %s\n", strerror (errno));
292                         ok = false;
293                 } else {
294                         have_tunnel = ok;
295                 }
296                 ifreq.ifr_name [IFNAMSIZ] = 0;
297                 ifreq.ifr_ifindex = if_nametoindex (ifreq.ifr_name);
298 syslog (LOG_DEBUG, "Found Interface Index %d for name %s\n", ifreq.ifr_ifindex, ifreq.ifr_name);
299                 ok = ok & (ifreq.ifr_ifindex != 0);
300         }
301         char cmd [512+1];
302 #if 0
303         snprintf (cmd, 512, "/sbin/ip addr add fe80::1 dev %s scope link", ifreq.ifr_name);
304         if (ok && system (cmd) != 0) {
305                 ok = false;
306         }
307 #endif 
308         snprintf (cmd, 512, "/sbin/sysctl -q -w net.ipv6.conf.%s.forwarding=0", ifreq.ifr_name);
309         if (ok && system (cmd) != 0) {
310                 ok = false;
311         }
312         snprintf (cmd, 512, "/sbin/sysctl -q -w net.ipv6.conf.%s.accept_dad=0", ifreq.ifr_name);
313         if (ok && system (cmd) != 0) {
314                 ok = false;
315         }
316         if (!ok) {
317                 close (v6sox);  /* This removes the tunnel interface */
318                 v6sox = -1;
319         }
320         return ok;
321 }
322 bool setup_tunnel_address (void) {
323         bool ok = have_tunnel;
324         char cmd [512+1];
325         // snprintf (cmd, 512, "/sbin/ifconfig %s hw ether 98:1e:53:a4:cf:6e", ifreq.ifr_name, MTU);
326         snprintf (cmd, 512, "/sbin/ip link set %s address %02x:%02x:%02x:%02x:%02x:%02x", ifreq.ifr_name, v6lladdr [0], v6lladdr [1], v6lladdr [2], v6lladdr [3], v6lladdr [4], v6lladdr [5]);
327         if (ok && system (cmd) != 0) {
328 syslog (LOG_CRIT, "Bad news!\n");
329                 ok = false;
330         }
331         snprintf (cmd, 512, "/sbin/ip link set %s up mtu %d", ifreq.ifr_name, MTU);
332         if (ok && system (cmd) != 0) {
333                 ok = false;
334         }
335 #ifdef TODO_BELIEVE_THAT_ROUTES_SHOULD_BE_ADDED_STATICALLY
336         snprintf (cmd, 512, "/sbin/ip -6 route add 2001:610:188:2001::/64 mtu 1280 dev %s", ifreq.ifr_name);
337         if (ok && system (cmd) != 0) {
338                 ok = false;
339         }
340 #endif
341 #ifdef TODO_COMPENSATE_FOR_AUTOCONFIG
342         snprintf (cmd, 512, "/sbin/ip -6 addr add %s/64 dev %s", v6prefix, ifreq.ifr_name);
343         if (ok && system (cmd) != 0) {
344                 ok = false;
345         }
346 #endif
347 #if 0
348         if (default_route) {
349                 snprintf (cmd, 512, "/sbin/ip -6 route add default via fe80:: dev %s", ifreq.ifr_name);
350                 if (ok && system (cmd) != 0) {
351                         ok = false;
352                 }
353         }
354 #endif
355         return ok;
356 }
357 #endif /* LINUX */
358
359
360 /*
361  *
362  * Utility functions
363  *
364  */
365
366
367 /* Look for an entry in the 50ms-cycled Neighbor Discovery queue.
368  * Match the target address.  Return the entry found, or NULL.
369  */
370 struct ndqueue *findqueue (struct in6_addr *target) {
371         struct ndqueue *ndq = ndqueue;
372         if (ndq) {
373                 do {
374                         if (memcmp (target, &ndq->target, 16) == 0) {
375                                 return ndq;
376                         }
377                         ndq = ndq->next;
378                 } while (ndq != ndqueue);
379         }
380         return NULL;
381 }
382
383 /* Enter an item in the 50ms-cycled Neighbor Discovery queue.
384  * Retrieve its storage space from the free queue.
385  * TODO: Avoid double entries by looking up entries first -> "requeue?"
386  */
387 static int TODO_qlen;
388 void enqueue (struct in6_addr *target, struct in6_addr *v6src, uint8_t *source_lladdr) {
389         //
390         // Refuse to create double entries
391         if (findqueue (target)) {
392                 return;
393         }
394         //
395         // Allocate a free item to enqueue
396         struct ndqueue *new = freequeue;
397         if (!new) {
398                 // Temporarily overflown with ND -> drop the request
399                 return;
400         }
401 char tgt [INET6_ADDRSTRLEN]; inet_ntop (AF_INET6, target, tgt, sizeof (tgt));
402 syslog (LOG_DEBUG, "Queue++ => %d, looking for %s\n", ++TODO_qlen, tgt);
403         freequeue = freequeue->next;
404         //
405         // Setup the new entry with target details
406         memcpy (&new->target, target, sizeof (new->target));
407         memcpy (&new->source, v6src, sizeof (new->source));
408         memcpy (&new->source_lladdr, source_lladdr, sizeof (new->source_lladdr));
409         new->todo_lancast = (v4mcast == -1)? 0: 2;
410         new->todo_direct = 3;
411         //
412         // Time the new item to run instantly
413         new->tv.tv_sec = 0;
414         //
415         // Enqueue the new item in front of the queue
416         if (ndqueue) {
417                 new->next = ndqueue->next;
418                 ndqueue->next = new;
419         } else {
420                 new->next = new;
421                 ndqueue = new;
422         }
423 }
424
425 /* Remove an item from the 50ms-cycled Neighbor Discovery queue.
426  * Enter its storage space in the free queue.
427  */
428 void dequeue (struct ndqueue *togo) {
429         struct ndqueue *prev = ndqueue;
430         do {
431                 if (prev->next == togo) {
432                         if (togo->next != togo) {
433                                 prev->next = togo->next;
434                                 if (ndqueue == togo) {
435                                         ndqueue = togo->next;
436                                 }
437                         } else {
438                                 // Must be the only queued item
439                                 ndqueue = NULL;
440                         }
441                         togo->next = freequeue;
442                         freequeue = togo;
443 syslog (LOG_DEBUG, "Queue-- => %d\n", --TODO_qlen);
444                         return;
445                 }
446                 prev = prev->next;
447         } while (prev != ndqueue);
448 }
449
450
451 /*
452  * Calculate the ICMPv6 checksum field
453  */
454 uint16_t icmp6_checksum (uint8_t *ipv6hdr, size_t payloadlen) {
455         uint16_t plenword = htons (payloadlen);
456         uint16_t nxthword = htons (IPPROTO_ICMPV6);
457         uint16_t *areaptr [] = { (uint16_t *) &ipv6hdr [8], (uint16_t *) &ipv6hdr [24], &plenword, &nxthword, (uint16_t *) &ipv6hdr [40], (uint16_t *) &ipv6hdr [40 + 4] };
458         uint8_t areawords [] = { 8, 8, 1, 1, 1, payloadlen/2 - 2 };
459         uint32_t csum = 0;
460         u_int8_t i, j;
461         for (i=0; i < 6; i++) {
462                 uint16_t *area = areaptr [i];
463                 for (j=0; j<areawords [i]; j++) {
464                         csum += ntohs (area [j]);
465                 }
466         }
467         csum = (csum & 0xffff) + (csum >> 16);
468         csum = (csum & 0xffff) + (csum >> 16);
469         csum = htons (~csum);
470         return csum;
471 }
472
473
474 /*
475  * Send a Redirect reply.  This is in response to a v4v6data message,
476  * and is directed straight at the origin's address but sent with a
477  * lower metric.
478  *
479  * Note: Although the packet arrived in v4data6, the reply is built
480  *       in v6data6 and sent from there as though it had come from
481  *       the IPv6 stack.
482  */
483 void redirect_reply (uint8_t *ngbc_llremote, metric_t ngbc_metric) {
484         void handle_6to4_plain_unicast (const ssize_t pktlen, const uint8_t *lladdr);
485         v6icmp6type = ND_REDIRECT;
486         v6icmp6code = 0;
487         v6icmp6data [0] =
488         v6icmp6data [1] =
489         v6icmp6data [2] =
490         v6icmp6data [3] = 0;            // Reserved
491         memcpy (v6icmp6data + 4, &v6listen, 16);
492                                         // Target IPv6 address
493         switch (ngbc_metric) {
494                                         // Destination Address suggestion
495         case METRIC_LOW:
496                 //
497                 // Redirect to the local-subnet IPv4 address
498                 memcpy (v6icmp6data + 4 + 16, v6listen_linklocal, 8);
499                 v6icmp6data [4 + 16 + 8 ] = v4peer.sin_port & 0x00ff;
500                 v6icmp6data [4 + 16 + 9 ] = v4peer.sin_port >> 8;
501                 memcpy (v6icmp6data + 4 + 16 + 12, &v4peer.sin_addr, 4);
502                 v6icmp6data [4 + 16 + 10] = v4v6icmpdata [4 + 16 + 12];
503                 v6icmp6data [4 + 16 + 11] = 0xff;
504                 v6icmp6data [4 + 16 + 12] = 0xfe;
505                 break;
506         case METRIC_MEDIUM:
507                 memcpy (v6icmp6data + 4 + 16, v6listen_linklocal_complete, 16);
508                 break;
509         case METRIC_HIGH:
510         default:
511                 return;         /* no cause for Redirect, drop */
512         }
513         v6type = IPPROTO_ICMPV6;
514         v6plen = htons (8 + 16 + 16);
515         memcpy (v6src6, &v6listen, 16);
516         memcpy (v6dst6, v4src6, 16);
517         v6icmp6csum = icmp6_checksum ((uint8_t *) v4hdr6, 8 + 16 + 16);
518         handle_6to4_plain_unicast (sizeof (struct ethhdr) + 40 + 8 + 16 + 16, ngbc_llremote);
519
520
521
522 /* Append the current prefix to an ICMPv6 message.  Incoming optidx
523  * and return values signify original and new offset for ICMPv6 options.
524  * The endlife parameter must be set to obtain zero lifetimes, thus
525  * instructing the tunnel client to stop using an invalid prefix.
526  */
527 size_t icmp6_prefix (size_t optidx, uint8_t endlife) {
528         v6icmp6data [optidx++] = 3;     // Type
529         v6icmp6data [optidx++] = 4;     // Length
530         v6icmp6data [optidx++] = 64;    // This is a /64 prefix
531 #ifndef COMPENSATE_FOR_AUTOCONF
532         v6icmp6data [optidx++] = 0xc0;  // L=1, A=1, Reserved1=0
533 #else
534         //TODO// Temporary fix: "ip -6 addr add .../64 dev 6bed4"
535         v6icmp6data [optidx++] = 0x80;  // L=1, A=0, Reserved1=0
536 #endif
537         memset (v6icmp6data + optidx, endlife? 0x00: 0xff, 8);
538         optidx += 8;
539                                         // Valid Lifetime: Zero / Infinite
540                                         // Preferred Lifetime: Zero / Infinite
541         memset (v6icmp6data + optidx, 0, 4);
542         optidx += 4;
543                                         // Reserved2=0
544         memcpy (v6icmp6data + optidx + 0, &v6listen, 8);
545         memset (v6icmp6data + optidx + 8, 0, 8);
546                                         // Set IPv6 prefix
547         optidx += 16;
548         return optidx;
549 }
550
551
552 /*
553  * Construct a Neighbor Advertisement message, providing the
554  * Public 6bed4 Service as the link-local address.
555  *
556  * This is done immediately when the IPv6 stack requests the link-local
557  * address for fe80:: through Router Solicition.  In addition, it is the
558  * fallback response used when attempts to contact the remote peer at its
559  * direct IPv4 address and UDP port (its 6bed4 address) fails repeatedly.
560  *
561  * This routine is called with info==NULL to respond to an fe80::
562  * Neighbor Solicitation, otherwise with an info pointer containing
563  * a target IPv6 address to service.
564  */
565 void advertise_6bed4_public_service (struct ndqueue *info) {
566         if (info) {
567                 memcpy (v6ether.h_dest, info->source_lladdr, 6);
568         } else {
569                 memcpy (v6ether.h_dest, v6ether.h_source, 6);
570         }
571         memcpy (v6ether.h_source, SERVER_6BED4_PORT_IPV4_MACSTR, 6);
572         memcpy (v6data, ipv6_defaultrouter_neighbor_advertisement, 8);
573         if (info) {
574                 memcpy (v6dst6, &info->source, 16);
575         } else {
576                 memcpy (v6dst6, v6src6, 16);
577         }
578         if (info) {
579                 memcpy (v6src6, &info->target, 16);
580         } else {
581                 memcpy (v6src6, router_linklocal_address_complete, 16);
582         }
583         //TODO:OVERWROTE// memcpy (v6data + 8, ipv6_defaultrouter_neighbor_advertisement + 8, 16);
584         memcpy (v6data + 8 + 16 + 16, ipv6_defaultrouter_neighbor_advertisement + 8 + 16 + 16, sizeof (ipv6_defaultrouter_neighbor_advertisement) - 8 - 16 - 16);
585         if (info) {
586                 // Overwrite target only for queued requests
587                 memcpy (&v6icmp6data [4], &info->target, 16);
588         }
589         v6icmp6csum = icmp6_checksum ((uint8_t *) v6hdr6, 32);
590         int sent = write (v6sox, &v6data6, sizeof (struct ethhdr) + sizeof (ipv6_defaultrouter_neighbor_advertisement));
591         if (info) {
592                 syslog (LOG_DEBUG, "TODO: Neighbor Discovery failed to contact directly -- standard response provided\n");
593         } else {
594                 syslog (LOG_DEBUG, "TODO: Neighbor Discovery for Public 6bed4 Service -- standard response provided\n");
595         }
596 }
597
598
599 /*
600  * Test if the provided IPv6 address matches the prefix used for 6bed4.
601  */
602 static inline bool prefix_6bed4 (struct in6_addr *ip6) {
603         return memcmp (&v6listen, ip6->s6_addr, 8) == 0;
604 }
605
606
607 /*
608  * Validate the originator's IPv6 address.  It should match the
609  * UDP/IPv4 coordinates of the receiving 6bed4 socket.  Also,
610  * the /64 prefix must match that of v6listen.
611  */
612 bool validate_originator (struct sockaddr_in *sin, struct in6_addr *ip6) {
613         if ((sin->sin_addr.s_addr == v4peer.sin_addr.s_addr) && (sin->sin_port == v4peer.sin_port)) {
614                 return true;
615         }
616         uint16_t port = ntohs (sin->sin_port);
617         uint32_t addr = ntohl (sin->sin_addr.s_addr);
618 if (memcmp (ip6, v6listen_linklocal, 8) != 0)
619         if (!prefix_6bed4 (ip6)) {
620                 return false;
621         }
622         if ((port % 256) != (ip6->s6_addr [8] ^ 0x02)) {
623                 return false;
624         }
625         if ((port / 256) != ip6->s6_addr [9]) {
626                 return false;
627         }
628         if ((addr >> 24) != ip6->s6_addr [10]) {
629                 return false;
630         }
631         if ((addr & 0x00ffffff) != (htonl (ip6->s6_addr32 [3]) & 0x00ffffff)) {
632                 return false;
633         }
634         return true;
635 }
636
637
638 /*
639  * Translate a Link-Local Address to its metric.  The metrics are
640  * numbered so that a higher number indicates a more costly path
641  * over which to connect.  The values of the metric should not be
642  * published, but be treated as an opaque value with a complete
643  * ordering (that is: <, <=, >=, > relations) defined on it.
644  */
645 metric_t lladdr_metric (uint8_t *lladdr) {
646         uint32_t ipv4 = * (uint32_t *) (lladdr + 2);
647         //
648         // Metric 2: The 6bed4 Router address
649         if (ipv4 == v4peer.sin_addr.s_addr) {
650                 return METRIC_HIGH;
651         }
652         //
653         // Metric 0: Private Addresses, as per RFC 1918
654         if ((ipv4 & 0xff000000) == 0x0a000000) {
655                 return METRIC_LOW;      /* 10.0.0./8 */
656         }
657         if ((ipv4 & 0xffff0000) == 0xc0a80000) {
658                 return METRIC_LOW;      /* 192.168.0.0/16 */
659         }
660         if ((ipv4 & 0xfff00000) == 0xac100000) {
661                 return METRIC_LOW;      /* 172.16.0.0/12 */
662         }
663         //
664         // Metric 1: Direct IPv4 contact is any other address
665         //           Correctness should be checked elsewhere
666         return METRIC_MEDIUM;
667 }
668
669
670 /*
671  * Retrieve the Link-Local Address, if any, for a given 6bed4 Peer.
672  * Return true on success, false on failure to find it.  The lladdr
673  * parameter is only overwritten in case of success.
674  *
675  * Obviously, there is a point where it is more efficient to not
676  * lookup the cache for every request, but to cache it locally
677  * and limit the lookup frequency.  This low-traffic optimal version
678  * is used here for initial simplicity, and because this is a peer
679  * daemon and a reference implementation.  But who knows what people
680  * will submit as patches...
681  *
682  * Note: This code is specific to Linux, but note that BSD also has a
683  *       NetLink concept, so it may port without needing to resort to
684  *       shell commands running slowly in separate processes.
685  * Note: The interface for Linux is under-documented.  Work may be
686  *       needed to handle exception situations, such as going over
687  *       invisible boundaries on the number of neighbours.  Similarly,
688  *       the use of alignment macros is rather unclear.  This is not
689  *       how I prefer to write code, but it's the best I can do now.
690  */
691 bool lookup_neighbor (uint8_t *ipv6, uint8_t *lladdr) {
692         struct mymsg {
693                 struct nlmsghdr hd;
694                 struct ndmsg nd;
695                 uint8_t arg [16384];
696         } msg;
697         memset (&msg, 0, sizeof (struct nlmsghdr) + sizeof (struct ndmsg));
698         msg.hd.nlmsg_len = NLMSG_LENGTH (sizeof (msg.nd));
699         msg.hd.nlmsg_type = RTM_GETNEIGH;
700         msg.hd.nlmsg_flags = NLM_F_REQUEST | NLM_F_ROOT /* | NLM_F_MATCH */;
701         msg.hd.nlmsg_pid = rtname.nl_pid;
702         msg.nd.ndm_family = AF_INET6;
703         msg.nd.ndm_state = NUD_REACHABLE | NUD_DELAY | NUD_PROBE | NUD_PERMANENT | NUD_STALE;   // Ignored by the kernel?
704         msg.nd.ndm_ifindex = ifreq.ifr_ifindex; // Ignored by the kernel?
705         // How to select an IPv6 address?  Ignored by the kernel?
706 #if 0
707         struct rtattr *ra1 = (struct rtattr *) (((char *) &msg) + sizeof (struct nlmsghdr) + sizeof (struct ndmsg));
708         ra1->rta_type = NDA_DST;        // lookup IPv6 address
709         ra1->rta_len = RTA_LENGTH(16);
710         msg.hd.nlmsg_len = NLMSG_ALIGN (msg.hd.nlmsg_len) + RTA_LENGTH (16);
711         memcpy (RTA_DATA (ra1), ipv6, 16);
712 #endif
713         if (send (rtsox, &msg, msg.hd.nlmsg_len, MSG_DONTWAIT) == -1) {
714                 return false;
715         }
716         ssize_t recvlen;
717         uint16_t pos = 0;
718 { char buf [INET6_ADDRSTRLEN]; inet_ntop (AF_INET6, ipv6, buf, sizeof (buf)); syslog (LOG_DEBUG, "Looking up v6addr %s\n", buf); }
719         while (recvlen = recv (rtsox, ((char *) &msg) + pos, sizeof (msg) - pos, MSG_DONTWAIT), recvlen > 0) {
720 syslog (LOG_DEBUG, "Message of %d bytes from neighbor cache, total is now %d\n", recvlen, pos + recvlen);
721                 recvlen += pos;
722                 pos = 0;
723                 struct mymsg *resp;
724                 while (resp = (struct mymsg *) (((char *) &msg) + pos),
725                                 (pos + sizeof (struct nlmsghdr) <= recvlen) &&
726                                 (pos + resp->hd.nlmsg_len <= recvlen)) {
727                         bool ok = true, match = false;
728                         uint8_t *result = NULL;
729                         if (resp->hd.nlmsg_type == NLMSG_DONE) {
730                                 return false;
731                         } else if (resp->hd.nlmsg_type != RTM_NEWNEIGH) {
732                                 syslog (LOG_ERR, "Kernel sent an unexpected nlmsg_type 0x%02x, ending neighbor interpretation\n", resp->hd.nlmsg_type);
733                                 ok = false;
734                         } else if (resp->nd.ndm_ifindex != ifreq.ifr_ifindex) {
735                                 ok = false;
736                         } else if (resp->nd.ndm_family != AF_INET6) {
737                                 syslog (LOG_ERR, "Kernel reported unknown neighbor family %d\n", resp->nd.ndm_family);
738                                 ok = false;
739                         } else
740                         if (!(resp->nd.ndm_state & (NUD_REACHABLE | NUD_DELAY | NUD_PROBE | NUD_PERMANENT | NUD_STALE))) {
741                                 ok = false;
742                         }
743                         struct rtattr *ra = (struct rtattr *) ((char *) &resp + pos + sizeof (struct nlmsghdr) + sizeof (struct ndmsg) + 8);
744                         ssize_t rapos = 0;
745                         while (ok && (rapos + ra->rta_len <= resp->hd.nlmsg_len)) {
746                                 switch (ra->rta_type) {
747                                 case NDA_DST:
748 { char buf [INET6_ADDRSTRLEN]; inet_ntop (AF_INET6, RTA_DATA (ra), buf, sizeof (buf)); syslog (LOG_DEBUG, "Comparing against %s\n", buf); }
749                                         if (memcmp (ipv6, RTA_DATA (ra), 16) == 0) {
750                                                 match = true;
751                                         }
752                                         break;
753                                 case NDA_LLADDR:
754                                         result = RTA_DATA (ra);
755                                         break;
756                                 case NDA_PROBES:
757                                 case NDA_CACHEINFO:
758                                 default:
759                                         break;  /* not of interest, skip */
760                                 }
761                                 rapos += ((ra->rta_len - 1) | 0x00000003) + 1;
762                                 ra = (struct rtattr *) (((char *) ra) + (((ra->rta_len - 1) | 0x0000003) + 1));
763                         }
764                         if (ok && match && result) {
765                                 memcpy (lladdr, result, 6);
766                                 return true;    /* Yippy! Erfolg! */
767                         }
768                         pos += resp->hd.nlmsg_len;
769                 }
770                 // Copy remaining partial message to the beginning, continue from there
771                 memcpy (&msg, ((char *) &msg) + pos, recvlen - pos);
772                 pos = recvlen - pos;
773         }
774         return false;
775 }
776
777
778 /*
779  * Major packet processing functions
780  */
781
782
783 /* Handle the IPv4 message pointed at by msg, checking if (TODO:HUH?) the IPv4:port
784  * data matches the lower half of the IPv6 sender address.  Drop silently
785  * if this is not the case.  TODO: or send ICMP?
786  */
787 void handle_4to6_plain (ssize_t v4datalen, struct sockaddr_in *sin) {
788         //
789         // Send the unwrapped IPv6 message out over v6sox
790         v4ether.h_proto = htons (ETH_P_IPV6);
791         memcpy (v4ether.h_dest,   v6lladdr, 6);
792         v4ether.h_source [0] = ntohs (sin->sin_port) % 256;
793         v4ether.h_source [1] = ntohs (sin->sin_port) / 256;
794         memcpy (v4ether.h_source + 2, &sin->sin_addr, 4);
795 syslog (LOG_INFO, "Writing IPv6, result = %d\n",
796         write (v6sox, &v4data6, sizeof (struct ethhdr) + v4datalen)
797 )
798         ;
799 }
800
801
802 /* Handle the IPv4 message pointed at by msg as a neighbouring command.
803  *
804  * Type Code    ICMPv6 meaning                  Handling
805  * ---- ----    -----------------------------   ----------------------------
806  * 133  0       Router Solicitation             Ignore
807  * 134  0       Router Advertisement            Setup Tunnel with Prefix
808  * 135  0       Neighbour Solicitation          Send Neighbour Advertisement
809  * 136  0       Neighbour Advertisement         Ignore
810  * 137  0       Redirect                        Ignore
811  */
812 void handle_4to6_nd (struct sockaddr_in *sin, ssize_t v4ngbcmdlen) {
813         uint16_t srclinklayer;
814         uint8_t *destprefix = NULL;
815 #ifdef TODO_DEPRECATED
816         uint8_t *destlladdr = NULL;
817 #endif
818         struct ndqueue *ndq;
819         if (v4ngbcmdlen < sizeof (struct ip6_hdr) + sizeof (struct icmp6_hdr)) {
820                 return;
821         }
822         //
823         if (v4v6icmpcode != 0) {
824                 return;
825         }
826         if (icmp6_checksum (v4data, v4ngbcmdlen - sizeof (struct ip6_hdr)) != v4v6icmpcksum) {
827                 return;
828         }
829         //
830         // Approved.  Perform neighbourly courtesy.
831         switch (v4v6icmptype) {
832         case ND_ROUTER_SOLICIT:
833                 return;         /* this is not a router, drop */
834         case ND_ROUTER_ADVERT:
835                 //
836                 // Validate Router Advertisement
837                 if (ntohs (v4v6plen) < sizeof (struct icmp6_hdr) + 16) {
838                         return;   /* strange length, drop */
839                 }
840                 if (v4v6icmpdata [1] & 0x80 != 0x00) {
841                         return;   /* indecent proposal to use DHCPv6, drop */
842                 }
843                 if (memcmp (v4src6, router_linklocal_address, 16) != 0) {
844                         return;   /* not from router, drop */
845                 }
846                 if (memcmp (v4dst6, democlient_linklocal_address, 8) != 0) {
847                         return;   /* no address setup for me, drop */
848                 }
849                 if ((v4dst6->s6_addr [11] != 0xff) || (v4dst6->s6_addr [12] != 0xfe)) {
850                         return;   /* funny interface identifier, drop */
851                 }
852                 if (v4dst6->s6_addr [8] & 0x01) {
853                         syslog (LOG_WARNING, "TODO: Ignoring (by accepting) an odd public UDP port revealed in a Router Advertisement -- this could cause confusion with multicast traffic\n");
854                 }
855                 size_t rdofs = 12;
856                 //TODO:+4_WRONG?// while (rdofs <= ntohs (v4v6plen) + 4) { ... }
857                 while (rdofs + 4 < ntohs (v4v6plen)) {
858                         if (v4v6icmpdata [rdofs + 1] == 0) {
859                                 return;   /* zero length option */
860                         }
861 #ifdef TODO_DEPRACATED
862                         if ((v4v6icmpdata [rdofs + 0] == ND_OPT_DESTINATION_LINKADDR) && (v4v6icmpdata [rdofs + 1] == 1)) {
863                                 if (v4v6icmpdata [rdofs + 2] & 0x01) {
864                                         syslog (LOG_WARNING, "TODO: Ignoring an odd UDP port offered in a Router Advertisement over 6bed4\n");
865                                 }
866                                 syslog (LOG_INFO, "TODO: Set tunnel link-local address to %02x:%02x:%02x:%02x:%02x:%02x\n", v4v6icmpdata [rdofs + 2], v4v6icmpdata [rdofs + 3], v4v6icmpdata [rdofs + 4], v4v6icmpdata [rdofs + 5], v4v6icmpdata [rdofs + 6], v4v6icmpdata [rdofs + 7]);
867                                 destlladdr = &v4v6icmpdata [rdofs + 2];
868                                 /* continue with next option */
869                         } else
870 #endif
871                         if (v4v6icmpdata [rdofs + 0] != ND_OPT_PREFIX_INFORMATION) {
872                                 /* skip to next option */
873                         } else if (v4v6icmpdata [rdofs + 1] != 4) {
874                                 return;   /* bad length field */
875                         } else if (rdofs + (v4v6icmpdata [rdofs + 1] << 3) > ntohs (v4v6plen) + 4) {
876                                 return;   /* out of packet length */
877                         } else if (v4v6icmpdata [rdofs + 3] & 0xc0 != 0xc0) {
878                                 /* no on-link autoconfig prefix */
879                         } else if (v4v6icmpdata [rdofs + 2] != 64) {
880                                 return;
881                         } else {
882                                 destprefix = &v4v6icmpdata [rdofs + 16];
883                         }
884                         rdofs += (v4v6icmpdata [rdofs + 1] << 3);
885                 }
886 #ifdef TODO_DEPRECATED
887                 if (destprefix && destlladdr) {
888                         memcpy (v6lladdr, destlladdr, 6);
889                         memcpy (&v6listen.s6_addr [0], destprefix, 8);
890                         v6listen.s6_addr [8] = destlladdr [0] ^ 0x02;
891                         v6listen.s6_addr [9] = destlladdr [1];
892                         v6listen.s6_addr [10] = destlladdr [2];
893                         v6listen.s6_addr [11] = 0xff;
894                         v6listen.s6_addr [12] = 0xfe;
895                         v6listen.s6_addr [13] = destlladdr [3];
896                         v6listen.s6_addr [14] = destlladdr [4];
897                         v6listen.s6_addr [15] = destlladdr [5];
898                         inet_ntop (AF_INET6,
899                                 &v6listen,
900                                 v6prefix,
901                                 sizeof (v6prefix));
902                         syslog (LOG_INFO, "%s: Assigning address %s to tunnel\n", program, v6prefix);
903                         if (!setup_tunnel_address ()) {
904                                 syslog (LOG_CRIT, "Failed to setup tunnel address\n");
905                                 exit (1);
906                         }
907                         got_lladdr = true;
908                         maintenance_time_cycle = maintenance_time_cycle_max;
909                         maintenance_time_sec = time (NULL) + maintenance_time_cycle;
910                 }
911 #else
912                 if (destprefix) {
913                         memcpy (v6listen.s6_addr + 0, destprefix, 8);
914                         memcpy (v6listen.s6_addr + 8, v4dst6->s6_addr + 8, 8);
915                         memcpy (v6listen_linklocal_complete, v4dst6, 16);
916                         v6lladdr [0] = v6listen_linklocal_complete [8] ^ 0x02;
917                         v6lladdr [1] = v6listen_linklocal_complete [9];
918                         v6lladdr [2] = v6listen_linklocal_complete [10];
919                         v6lladdr [3] = v6listen_linklocal_complete [13];
920                         v6lladdr [4] = v6listen_linklocal_complete [14];
921                         v6lladdr [5] = v6listen_linklocal_complete [15];
922                         inet_ntop (AF_INET6,
923                                 &v6listen,
924                                 v6prefix,
925                                 sizeof (v6prefix));
926                         syslog (LOG_INFO, "%s: Assigning address %s to tunnel\n", program, v6prefix);
927                         setup_tunnel_address ();  //TODO// parameters?
928                         got_lladdr = true;
929                         maintenance_time_cycle = maintenance_time_cycle_max;
930                         maintenance_time_sec = time (NULL) + maintenance_time_cycle;
931                 }
932 #endif
933                 return;
934         case ND_NEIGHBOR_SOLICIT:
935                 //
936                 // Validate Neigbour Solicitation (trivial)
937                 //
938                 // Replicate the message over the IPv6 Link (like plain IPv6)
939                 if (v4ngbcmdlen < 24) {
940                         return;         /* too short, drop */
941                 }
942                 syslog (LOG_DEBUG, "%s: Replicating Neighbor Solicatation from 6bed4 to the IPv6 Link\n", program);
943 char buf [INET6_ADDRSTRLEN]; uint8_t ll [6]; if ((memcmp (v4src6, v6listen_linklocal, 8) != 0) && (memcmp (v4src6, &v6listen, 8) != 0)) { inet_ntop (AF_INET6, v4src6, buf, sizeof (buf)); syslog (LOG_DEBUG, "Source IPv6 address %s from wrong origin\n"); } else { uint8_t pfaddr [16]; memcpy (pfaddr, v6listen.s6_addr, 8); memcpy (pfaddr + 8, v4src6->s6_addr + 8, 8); inet_ntop (AF_INET6, pfaddr, buf, sizeof (buf)); if (lookup_neighbor (pfaddr, ll)) { syslog (LOG_DEBUG, "Source IPv6 %s has Link-Local Address %02x:%02x:%02x:%02x:%02x:%02x with metric %d\n", buf, ll [0], ll [1], ll [2], ll [3], ll [4], ll [5], lladdr_metric (ll)); } else { syslog (LOG_DEBUG, "Source IPv6 %s is unknown to me\n", buf); } }
944 uint8_t optofs = 4 + 16;
945 #if 0
946 uint8_t *srcll = NULL;  /* TODO -- use 6bed4 Network sender instead! */
947 while ((40 + 4 + optofs + 2 < v4ngbcmdlen) && (40 + 4 + optofs + 8 * v4v6icmpdata [optofs + 1] <= v4ngbcmdlen)) {
948 if (v4v6icmpdata [optofs] == 1) {
949 srcll = v4v6icmpdata + optofs + 2;
950 }
951 optofs += 8 * v4v6icmpdata [optofs + 1];
952 }
953 if (srcll) { syslog (LOG_DEBUG, "ND-contained Source Link-Layer Address %02x:%02x:%02x:%02x:%02x:%02x has metric %d\n", srcll [0], srcll [1], srcll [2], srcll [3], srcll [4], srcll [5], lladdr_metric (srcll)); }
954 #endif
955                 //
956                 // We should attach a Source Link-Layer Address, but
957                 // we cannot automatically trust the one provided remotely.
958                 // Also, we want to detect if routes differ, and handle it.
959                 //
960                 // 0. if no entry in the ngb.cache
961                 //    then use 6bed4 server in ND, initiate ngb.sol to src.ll
962                 //         impl: use 6bed4-server lladdr, set highest metric
963                 // 1. if metric (ngb.cache) < metric (src.ll)
964                 //    then retain ngb.cache, send Redirect to source
965                 // 2. if metric (ngb.cache) > metric (src.ll)
966                 //    then retain ngb.cache, initiate ngb.sol to src.ll
967                 // 3. if metric (ngb.cache) == metric (src.ll)
968                 //    then retain ngb.cache
969                 //
970                 uint8_t src_lladdr [6];
971                 src_lladdr [0] = ntohs (v4name.sin_port) & 0x00ff;
972                 src_lladdr [1] = ntohs (v4name.sin_port) >> 8;
973                 memcpy (src_lladdr + 2, &v4name.sin_addr, 4);
974                 metric_t src_metric = lladdr_metric (src_lladdr);
975                 v4v6icmpdata [4+16+0] = 1;      /* Option: Source LLaddr */
976                 v4v6icmpdata [4+16+1] = 1;      /* Length: 1x 8 bytes */
977                 uint8_t *ngbc_lladdr = v4v6icmpdata + 4+16+2;
978                 uint8_t ngbc_ipv6 [16];
979                 if (memcmp (v4src6, v6listen_linklocal, 8)) {
980                         memcpy (ngbc_ipv6 + 0, &v6listen, 8);
981                         memcpy (ngbc_ipv6 + 8, v4src6 + 8, 8);
982                 } else {
983                         memcpy (ngbc_ipv6, v4src6, 16);
984                 }
985                 bool ngbc_cached = lookup_neighbor (ngbc_ipv6, ngbc_lladdr);
986                 metric_t ngbc_metric;
987                 if (ngbc_cached) {
988                         ngbc_metric = lladdr_metric (ngbc_lladdr);
989                 } else {
990                         ngbc_metric = METRIC_HIGH; /* trigger local ngbsol */
991                         memcpy (ngbc_lladdr, SERVER_6BED4_PORT_IPV4_MACSTR, 6);
992 syslog (LOG_DEBUG, "Failed to find neighbor in cache, initialising it with the high metric\n");
993                 }
994                 syslog (LOG_DEBUG, "Metric analysis: source lladdr %02x:%02x:%02x:%02x:%02x:%02x metric %d, neighbor cache lladdr %02x:%02x:%02x:%02x:%02x:%02x metric %d\n", src_lladdr [0], src_lladdr [1], src_lladdr [2], src_lladdr [3], src_lladdr [4], src_lladdr [5], src_metric, ngbc_lladdr [0], ngbc_lladdr [1], ngbc_lladdr [2], ngbc_lladdr [3], ngbc_lladdr [4], ngbc_lladdr [5], ngbc_metric);
995                 //
996                 // Replicate the ngb.sol with the selected ngbc-lladdr
997                 v4v6icmpcksum = icmp6_checksum ((uint8_t *) v4hdr6, 8 + 16 + 8);
998                 handle_4to6_plain (40 + 24 + 8, &v4name);
999                 //
1000                 // If needed, initiate Neigbor Solicitation to the source
1001                 // Note: Also when !ngbc_cached as the router is then cached
1002                 if (ngbc_metric > src_metric) {
1003 syslog (LOG_DEBUG, "Trying to find the more direct route that the remote peer seems to be using\n");
1004                         enqueue ((struct in6_addr *) v4src6, &v6listen, v6lladdr);
1005                 }
1006                 //
1007                 // If needed, ask the source to redo Neighbor Solicitation
1008                 if (ngbc_metric < src_metric) {
1009 syslog (LOG_DEBUG, "Redirecting the remote peer to the more efficient route that I am using\n");
1010                         redirect_reply (ngbc_lladdr, ngbc_metric);
1011                 }
1012                 return;
1013         case ND_NEIGHBOR_ADVERT:
1014                 //
1015                 // Process Neighbor Advertisement coming in over 6bed4
1016                 // First, make sure it is against an item in the ndqueue
1017                 ndq = findqueue ((struct in6_addr *) v4v6ndtarget);
1018                 if (!ndq) {
1019                         // Ignore advertisement -- it may be an attack
1020                         return;
1021                 }
1022                 // Remove the matching item from the ndqueue
1023                 dequeue (ndq);
1024                 // Replicate the Neigbor Advertisement over the IPv6 Link (like plain IPv6)
1025                 v4v6icmpdata [0] |= 0xe0;       /* Router, Solicited, Override */
1026                 v4v6icmpdata [20] = 2;          /* Target Link-Layer Address */
1027                 v4v6icmpdata [21] = 1;          /* Length: 1x 8 bytes */
1028                 v4v6icmpdata [22] = ntohs (v4name.sin_port) % 256;
1029                 v4v6icmpdata [23] = ntohs (v4name.sin_port) / 256;
1030                 memcpy (v4v6icmpdata + 24, &v4name.sin_addr, 4);
1031                 v4v6plen = htons (24 + 8);
1032                 v4v6icmpcksum = icmp6_checksum ((uint8_t *) v4hdr6, 24 + 8);
1033                 handle_4to6_plain (sizeof (struct ip6_hdr) + 24 + 8, &v4name);
1034                 return;
1035         case ND_REDIRECT:
1036                 //
1037                 // Redirect indicates that a more efficient bypass exists than
1038                 // the currently used route.  The remote peer has established
1039                 // this and wants to share that information to retain a
1040                 // symmetric communication, which is helpful in keeping holes
1041                 // in NAT and firewalls open.
1042                 //
1043                 //TODO// BE EXTREMELY SELECTIVE BEFORE ACCEPTING REDIRECT!!!
1044                 //TODO:NOTYET// enqueue ((struct in6_addr *) v4v6ndtarget, &v6listen, v6lladdr);
1045                 return;
1046         }
1047 }
1048
1049
1050 /* Receive a tunnel package, and route it to either the handler for the
1051  * tunnel protocol, or to the handler that checks and then unpacks the
1052  * contained IPv6.
1053  */
1054 void handle_4to6 (int v4in) {
1055         uint8_t buf [1501];
1056         ssize_t buflen;
1057         socklen_t adrlen = sizeof (v4name);
1058         //
1059         // Receive IPv4 package, which may be tunneled or a tunnel request
1060         buflen = recvfrom (v4in,
1061                         v4data, MTU,
1062                         MSG_DONTWAIT,
1063                         (struct sockaddr *) &v4name, &adrlen
1064                 );
1065         if (buflen == -1) {
1066                 syslog (LOG_INFO, "%s: WARNING: Error receiving IPv4-side package: %s\n",
1067                                 program, strerror (errno));
1068                 return;         /* receiving error, drop */
1069         }
1070         if (buflen <= sizeof (struct ip6_hdr)) {
1071                 return;         /* received too little data, drop */
1072         }
1073         if ((v4data [0] & 0xf0) != 0x60) {
1074                 return;         /* not an IPv6 packet, drop */
1075         }
1076         if (!validate_originator (&v4name, v4src6)) {
1077                 return;         /* source appears fake, drop */
1078         }
1079         /*
1080          * Distinguish types of traffic:
1081          * Non-plain, Plain Unicast, Plain Multicast
1082          */
1083         if ((v4v6nexthdr == IPPROTO_ICMPV6) &&
1084                         (v4v6icmptype >= 133) && (v4v6icmptype <= 137)) {
1085                 //
1086                 // Not Plain: Router Adv/Sol, Neighbor Adv/Sol, Redirect
1087                 if (v4v6hoplimit != 255) {
1088                         return;
1089                 }
1090                 handle_4to6_nd (&v4name, buflen);
1091         } else {
1092                 //
1093                 // Plain Unicast or Plain Multicast (both may enter)
1094                 if (v4v6hoplimit-- <= 1) {
1095                         return;
1096                 }
1097                 handle_4to6_plain (buflen, &v4name);
1098         }
1099 }
1100
1101
1102 /*
1103  * Relay an IPv6 package to 6bed4, using the link-local address as it
1104  * is found in the Ethernet header.  Trust the local IPv6 stack to have
1105  * properly obtained this destination address through Neighbor Discovery
1106  * over 6bed4.
1107  */
1108 void handle_6to4_plain_unicast (const ssize_t pktlen, const uint8_t *lladdr) {
1109         struct sockaddr_in v4dest;
1110         memset (&v4dest, 0, sizeof (v4dest));
1111         v4dest.sin_family = AF_INET;
1112         v4dest.sin_port = htons (lladdr [0] | (lladdr [1] << 8));
1113         memcpy (&v4dest.sin_addr, lladdr + 2, 4);
1114         if (v6tc != (v6hdr6->ip6_vfc & htonl (0x0ff00000))) {
1115                 v6tc = v6hdr6->ip6_vfc & htonl (0x0ff00000);
1116                 v4qos = (ntohl (v6hdr6->ip6_vfc) & 0x0ff00000) >> 24;
1117                 if (setsockopt (v4sox, IPPROTO_IP, IP_TOS, &v4qos, sizeof (v4qos)) == -1) {
1118                         syslog (LOG_ERR, "Failed to switch IPv4 socket to QoS setting 0x%02x\n", v4qos);
1119                 }
1120         }
1121         syslog (LOG_DEBUG, "%s: Sending IPv6-UDP-IPv4 to %d.%d.%d.%d:%d, result = %d\n", program,
1122         ((uint8_t *) &v4dest.sin_addr.s_addr) [0],
1123         ((uint8_t *) &v4dest.sin_addr.s_addr) [1],
1124         ((uint8_t *) &v4dest.sin_addr.s_addr) [2],
1125         ((uint8_t *) &v4dest.sin_addr.s_addr) [3],
1126         ntohs (v4dest.sin_port),
1127                 sendto (v4sox,
1128                                 v6data,
1129                                 pktlen - sizeof (struct ethhdr),
1130                                 MSG_DONTWAIT,
1131                                 (struct sockaddr *) &v4dest,
1132                                 sizeof (struct sockaddr_in))
1133         )
1134                                 ;
1135 }
1136
1137
1138 /*
1139  * Handle a request for Neighbor Discovery over the 6bed4 Link.
1140  */
1141 void handle_6to4_nd (ssize_t pktlen) {
1142         uint8_t lldest [6];
1143         //
1144         // Validate ICMPv6 message -- trivial, trust local generation
1145         //
1146         // Handle the message dependent on its type
1147         switch (v6icmp6type) {
1148         case ND_ROUTER_SOLICIT:
1149                 v6icmp6type = ND_ROUTER_ADVERT;
1150                 v6icmp6code = 0;
1151                 v6icmp6data [0] = 0;            // Cur Hop Limit: unspec
1152                 v6icmp6data [1] = 0x18;         // M=0, O=0,
1153                                                 // H=0, Prf=11=Low
1154                                                 // Reserved=0
1155                 //TODO: wire says 0x44 for router_adv.flags
1156                 size_t writepos = 2;
1157                 memset (v6icmp6data + writepos,
1158                                 default_route? 0xff: 0x00,
1159                                 2);             // Router Lifetime
1160                 writepos += 2;
1161                 memcpy (v6icmp6data + writepos,
1162                                 "\x00\x00\x80\x00",
1163                                 4);             // Reachable Time: 32s
1164                 writepos += 4;
1165                 memcpy (v6icmp6data + writepos,
1166                                 "\x00\x00\x01\x00",
1167                                 4);             // Retrans Timer: .25s
1168                 writepos += 4;
1169                 writepos = icmp6_prefix (writepos, 0);
1170                 v6plen = htons (4 + writepos);
1171                 memcpy (v6dst6, v6src6, 16);
1172                 memcpy (v6src6, v6listen_linklocal_complete, 16);
1173                 v6icmp6csum = icmp6_checksum ((uint8_t *) v6hdr6, 4 + writepos);
1174                 v6ether.h_proto = htons (ETH_P_IPV6);
1175                 memcpy (v6ether.h_dest, v6ether.h_source, 6);
1176                 memcpy (v6ether.h_source, v6lladdr, 6);
1177                 syslog (LOG_INFO, "Replying Router Advertisement to the IPv6 Link, result = %d\n",
1178                         write (v6sox, &v6data6, sizeof (struct ethhdr) + sizeof (struct ip6_hdr) + 4 + writepos)
1179                 )
1180                         ;
1181                 break;
1182         case ND_ROUTER_ADVERT:
1183                 return;         /* the IPv6 Link is no router, drop */
1184         case ND_NEIGHBOR_SOLICIT:
1185                 //
1186                 // Neighbor Solicitation is treated depending on its kind:
1187                 //  - the 6bed4 Router address is answered immediately
1188                 //  - discovery for the local IPv6 address is dropped
1189                 //  - discovery for fe80::/64 addresses is answered
1190                 //  - other peers start a process in the ndqueue
1191                 if ((memcmp (v6ndtarget, router_linklocal_address, 16) == 0) ||
1192                     (memcmp (v6ndtarget, router_linklocal_address_complete, 16) == 0)) {
1193                         advertise_6bed4_public_service (NULL);
1194                 } else if (memcmp (v6ndtarget, &v6listen, 16) == 0) {
1195                         return;         /* yes you are unique, drop */
1196                 } else if (memcmp (v6ndtarget, v6listen_linklocal, 8) == 0) {
1197                         //
1198                         // Construct response for fe80::/64
1199                         v6icmp6type = ND_NEIGHBOR_ADVERT;
1200                         v6icmp6data [0] = 0x60; /* Solicited, Override */
1201                         v6icmp6data [20] = 2;   /* Target Link-Layer Address */
1202                         v6icmp6data [21] = 1;   /* Length is 1x 8 bytes */
1203                         v6icmp6data [22] = v6icmp6data [12] ^ 0x02;
1204                         v6icmp6data [23] = v6icmp6data [13];
1205                         v6icmp6data [24] = v6icmp6data [14];
1206                         v6icmp6data [25] = v6icmp6data [17];
1207                         v6icmp6data [26] = v6icmp6data [18];
1208                         v6icmp6data [27] = v6icmp6data [19];
1209                         v6plen = htons (4 + 28);
1210                         memcpy (v6dst6, v6src6, 16);
1211                         memcpy (v6src6, &v6listen, 16);
1212                         memcpy (v6ether.h_dest, v6ether.h_source, 6);
1213                         memcpy (v6ether.h_source, v6lladdr, 6);
1214                         v6icmp6csum = icmp6_checksum ((uint8_t *) v6hdr6, 4 + 28);
1215 syslog (LOG_DEBUG, "Sending trivial reply to fe80::/64 type query\n");
1216                         write (v6sox, &v6data6, sizeof (struct ethhdr) + sizeof (struct ip6_hdr) + 4 + 28);
1217                         return;
1218                 } else {
1219                         enqueue ((struct in6_addr *) v6ndtarget, (struct in6_addr *) v6src6, v6ether.h_source);
1220                 }
1221                 break;
1222         case ND_NEIGHBOR_ADVERT:
1223                 lldest [0] = v6dst6->s6_addr [8] ^ 0x02;
1224                 lldest [1] = v6dst6->s6_addr [9];
1225                 lldest [2] = v6dst6->s6_addr [10];
1226                 lldest [3] = v6dst6->s6_addr [13];
1227                 lldest [4] = v6dst6->s6_addr [14];
1228                 lldest [5] = v6dst6->s6_addr [15];
1229                 handle_6to4_plain_unicast (pktlen, lldest);
1230                 break;
1231         case ND_REDIRECT:
1232                 //TODO:NOT_IMPLEMENTED_YET:ND_REDIRECT_FROM_6BED4//
1233                 //
1234                 // Redirect indicates that a more efficient bypass exists than
1235                 // the currently used route.  The remote peer has established
1236                 // this and wants to share that information to retain a
1237                 // symmetric communication, which is helpful in keeping holes
1238                 // in NAT and firewalls open.
1239                 //
1240                 return;
1241         }
1242 }
1243
1244
1245 /*
1246  * Receive an IPv6 package, check its address and pickup IPv4 address and
1247  * port, then package it as a tunnel message and forward it to IPv4:port.
1248  * Rely on the proper formatting of the incoming IPv6 packet, as it is
1249  * locally generated.
1250  */
1251 void handle_6to4 (void) {
1252         //
1253         // Receive the IPv6 package and ensure a consistent size
1254         size_t rawlen = read (v6sox, &v6data6, sizeof (v6data6));
1255         if (rawlen == -1) {
1256                 return;         /* failure to read, drop */
1257         }
1258         if (rawlen < sizeof (struct ethhdr) + sizeof (struct ip6_hdr) + 1) {
1259                 return;         /* packet too small, drop */
1260         }
1261         if (v6ether.h_proto != htons (ETH_P_IPV6)) {
1262                 return;         /* not IPv6, drop */
1263         }
1264 //TODO// syslog (LOG_DEBUG, "Packet from IPv6 stack, target %02x:%02x:%02x:%02x:%02x:%02x\n", v6ether.h_dest [0], v6ether.h_dest [1], v6ether.h_dest [2], v6ether.h_dest [3], v6ether.h_dest [4], v6ether.h_dest [5]);
1265         //
1266         // Ignore messages from the IPv6 stack to itself
1267         if (memcmp (v6ether.h_dest, v6ether.h_source, 6) == 0) {
1268                 syslog (LOG_DEBUG, "TODO: Self-to-self messaging in IPv6 stack ignored\n");
1269                 return;
1270         }
1271         /*
1272          * Distinguish types of traffic:
1273          * Non-plain, Plain Unicast, Plain Multicast
1274          */
1275         if ((v6type == IPPROTO_ICMPV6) &&
1276                         (v6icmp6type >= 133) && (v6icmp6type <= 137)) {
1277                 //
1278                 // Not Plain: Router Adv/Sol, Neighbor Adv/Sol, Redirect
1279                 handle_6to4_nd (rawlen);
1280         } else if ((v6dst6->s6_addr [0] != 0xff) && !(v6dst6->s6_addr [8] & 0x01)) {
1281                 //
1282                 // Plain Unicast
1283                 if (v6hops-- <= 1) {
1284                         return;
1285                 }
1286 syslog (LOG_DEBUG, "Forwarding plain unicast from IPv6 to 6bed4\n");
1287                 handle_6to4_plain_unicast (rawlen, v6ether.h_dest);
1288         } else {
1289                 //
1290                 // Plain Multicast
1291                 //TODO:IGNORE_MULTICAST//
1292                 //TODO// syslog (LOG_DEBUG, "%s: Plain multicast from 6bed4 Link to 6bed4 Network is not supported\n", program);
1293         }
1294 }
1295
1296
1297 /*
1298  * Send a single Neighbor Solicitation message over 6bed4.  This will
1299  * be sent to the given 6bed4 address, and is usually part of a series
1300  * of attempts to find a short-cut route to the 6bed4 peer.
1301  */
1302 void solicit_6bed4_neighbor (const struct ndqueue *info, const uint8_t *addr6bed4) {
1303         memcpy (v6src6, &info->source, 16);
1304         memcpy (v6dst6, &info->target, 16);
1305         v6type = IPPROTO_ICMPV6;
1306         v6hops = 255;
1307         v6icmp6type = ND_NEIGHBOR_SOLICIT;
1308         v6icmp6code = 0;
1309         v6icmp6data [0] =
1310         v6icmp6data [1] =
1311         v6icmp6data [2] =
1312         v6icmp6data [3] = 0x00;
1313         memcpy (v6icmp6data + 4, &info->target, 16);
1314         v6icmp6data [20] = 1;   // option type is Source Link-Layer Address
1315         v6icmp6data [21] = 1;   // option length is 1x 8 bytes
1316         memcpy (v6icmp6data + 22, v6lladdr, 6);
1317         uint16_t pktlen = sizeof (struct ip6_hdr) + 4 + 28;
1318         //OLD// v6icmp6csum = icmp6_checksum ((uint8_t *) v6hdr6, 28 + 8);
1319         v6plen = htons (4 + 28);
1320         v6icmp6csum = icmp6_checksum ((uint8_t *) v6hdr6, 4 + 28);
1321         handle_6to4_plain_unicast (sizeof (struct ip6_hdr) + 8 + 28 + 10, addr6bed4);
1322         //TODO// Why these +8 and +10 are needed, I don't know yet!
1323 }
1324
1325
1326 /*
1327  * Find a neighbor's 6bed4 address.  This is coordinated by the ndqueue,
1328  * which schedules such tasks and makes them repeat.  Furthermore, a few
1329  * attempts may be scheduled on the local network before attempts
1330  * shift to the direct target IPv4/UDP addresses.  Of course the local
1331  * network will only be scheduled if the public IPv4 address matches
1332  * the one for the local node.
1333  *
1334  * This process is dequeued by reverse Neighbor Advertisements.  If none
1335  * comes back in spite of the various Neighbor Solicitations sent, then
1336  * the final action is to send a Neighbor Advertisement to the host with
1337  * the Public 6bed4 Service as its target of last resort.  In case of
1338  * this last resort, the process is not continued any further; the
1339  * return value indicates whether the queue entry should be kept for
1340  * another round.
1341  */
1342 bool chase_neighbor_6bed4_address (struct ndqueue *info) {
1343         uint8_t addr6bed4 [6];
1344         static const uint8_t addr6bed4_lancast [8] = {
1345                 UDP_PORT_6BED4 % 256, UDP_PORT_6BED4 / 256,
1346                 224, 0, 0, 1
1347         };
1348         if (info->todo_lancast > 0) {
1349                 // Attempt 1. Send to LAN multicast address (same public IP)
1350                 info->todo_lancast--;
1351                 solicit_6bed4_neighbor (info, addr6bed4_lancast);
1352                 return true;
1353         } else if (info->todo_direct > 0) {
1354                 // Attempt 2. Send to target's direct IP address / UDP port
1355                 info->todo_direct--;
1356                 addr6bed4 [0] = info->target.s6_addr [8] ^ 0x02;
1357                 addr6bed4 [1] = info->target.s6_addr [9];
1358                 addr6bed4 [2] = info->target.s6_addr [10];
1359                 addr6bed4 [3] = info->target.s6_addr [13];
1360                 addr6bed4 [4] = info->target.s6_addr [14];
1361                 addr6bed4 [5] = info->target.s6_addr [15];
1362                 solicit_6bed4_neighbor (info, addr6bed4);
1363                 return true;
1364         } else {
1365                 // Attempt 3. Respond with Public 6bed4 Service
1366                 syslog (LOG_INFO, "%s: Failed to find a bypass, passing back the 6bed4 Router\n", program);
1367                 advertise_6bed4_public_service (info);
1368                 return false;
1369         }
1370 }
1371
1372
1373 /*
1374  * Perform Router Solicitation.  This is the usual mechanism that is used
1375  * on ethernet links as well, except that the 6bed4 permits fixed interface
1376  * identifiers; for this client, the interface identifier will be 0x0001.
1377  * The router always has interface identifier 0x0000 but it will now be
1378  * addressed at the all-routers IPv6 address 0xff02::2 with the general
1379  * source IPv6 address ::
1380  */
1381 void solicit_router (void) {
1382         v4name.sin_family = AF_INET;
1383         memcpy (&v4name.sin_addr.s_addr, &v4listen, 4);
1384         v4name.sin_port = htons (UDP_PORT_6BED4);
1385         int done = 0;
1386         int secs = 1;
1387 // syslog (LOG_DEBUG, "%s: Sending RouterSolicitation-IPv6-UDP-IPv4 to %d.%d.%d.%d:%d, result = %d\n", program,
1388 // ((uint8_t *) &v4name.sin_addr.s_addr) [0],
1389 // ((uint8_t *) &v4name.sin_addr.s_addr) [1],
1390 // ((uint8_t *) &v4name.sin_addr.s_addr) [2],
1391 // ((uint8_t *) &v4name.sin_addr.s_addr) [3],
1392 // ntohs (v4name.sin_port),
1393 (
1394         sendto (v4sox,
1395                         ipv6_router_solicitation,
1396                         sizeof (ipv6_router_solicitation),
1397                         MSG_DONTWAIT,
1398                         (struct sockaddr *) &v4name, sizeof (v4name)));
1399 }
1400
1401
1402 /*
1403  * Send a KeepAlive message.  This is an UDP/IPv4 message with no contents.
1404  * The router will not respond, but that is okay; outgoing traffic is the
1405  * way to keep holes in NAT and firewalls open.
1406  */
1407 void keepalive (void) {
1408         v4name.sin_family = AF_INET;
1409         memcpy (&v4name.sin_addr.s_addr, &v4listen, 4);
1410         v4name.sin_port = htons (UDP_PORT_6BED4);
1411         int done = 0;
1412         int secs = 1;
1413         setsockopt (v4sox, IPPROTO_IP, IP_TTL, &keepalive_ttl, sizeof (keepalive_ttl));
1414         sendto (v4sox,
1415                         "",
1416                         0,
1417                         MSG_DONTWAIT,
1418                         (struct sockaddr *) &v4name, sizeof (v4name));
1419         setsockopt (v4sox, IPPROTO_IP, IP_TTL, &v4ttl, sizeof (v4ttl));
1420 }
1421
1422
1423 /* Regular maintenance is a routine that runs regularly to do one of two
1424  * generic tasks: either it sends Router Solicitation messages to the
1425  * Public 6bed4 Service, or it sends an empty UDP message somewhat in its
1426  * direction to keep NAT/firewall holes open.
1427  */
1428 void regular_maintenance (void) {
1429         if (!got_lladdr) {
1430                 solicit_router ();
1431                 maintenance_time_cycle <<= 1;
1432                 maintenance_time_cycle += 1;
1433                 if (maintenance_time_cycle > maintenance_time_cycle_max) {
1434                         maintenance_time_cycle = maintenance_time_cycle_max;
1435                 }
1436                 syslog (LOG_INFO, "Sent Router Advertisement to Public 6bed4 Service, next attempt in %d seconds\n", maintenance_time_cycle);
1437         } else {
1438                 syslog (LOG_INFO, "Sending a KeepAlive message (empty UDP) to the 6bed4 Router\n");
1439                 keepalive ();
1440                 maintenance_time_cycle = maintenance_time_cycle_max;
1441         }
1442         maintenance_time_sec = time (NULL) + maintenance_time_cycle;
1443 }
1444
1445
1446 /* Run the daemon core code, passing information between IPv4 and IPv6 and
1447  * responding to tunnel requests if so requested.
1448  */
1449 void run_daemon (void) {
1450         fd_set io;
1451         bool keep;
1452         maintenance_time_sec = 0;       // trigger Router Solicitation
1453         FD_ZERO (&io);
1454         FD_SET (v4sox, &io);
1455         FD_SET (v6sox, &io);
1456         int nfds = (v4sox < v6sox)? (v6sox + 1): (v4sox + 1);
1457         if (v4mcast != -1) {
1458                 FD_SET (v4mcast, &io);
1459                 if (v4mcast >= nfds) {
1460                         nfds = v4mcast + 1;
1461                 }
1462         }
1463         while (1) {
1464                 struct timeval tout;
1465                 struct timeval now;
1466                 gettimeofday (&now, NULL);
1467                 if (maintenance_time_sec <= now.tv_sec) {
1468                         regular_maintenance ();
1469                 }
1470                 tout.tv_sec = maintenance_time_sec - now.tv_sec;
1471                 tout.tv_usec = 0;
1472                 while (ndqueue && (
1473                                 ((ndqueue->next->tv.tv_sec == now.tv_sec)
1474                                   && (ndqueue->next->tv.tv_usec <= now.tv_usec))
1475                                 || (ndqueue->next->tv.tv_sec < now.tv_sec))) {
1476                         //
1477                         // Run the entry's handler code
1478                         syslog (LOG_DEBUG, "Queue at %d.%03d: Timed for %d.%03d", now.tv_sec, now.tv_usec / 1000, ndqueue->next->tv.tv_sec, ndqueue->next->tv.tv_usec / 1000);
1479                         keep = chase_neighbor_6bed4_address (ndqueue->next);
1480                         if (!keep) {
1481                                 dequeue (ndqueue->next);
1482                                 continue;
1483                         }
1484                         //
1485                         // Make ndqueue point to the entry to run
1486                         ndqueue = ndqueue->next;
1487                         //
1488                         // Add 50ms to the running time
1489                         if (now.tv_usec < 950000) {
1490                                 ndqueue->tv.tv_usec = now.tv_usec +   50000;
1491                                 ndqueue->tv.tv_sec  = now.tv_sec  + 0;
1492                         } else {
1493                                 ndqueue->tv.tv_usec = now.tv_usec -  950000;
1494                                 ndqueue->tv.tv_sec  = now.tv_sec  + 1;
1495                         }
1496                 }
1497                 if (ndqueue && ((ndqueue->next->tv.tv_sec - now.tv_sec) < tout.tv_sec)) {
1498                         tout.tv_sec  = ndqueue->next->tv.tv_sec  - now.tv_sec ;
1499                         tout.tv_usec = ndqueue->next->tv.tv_usec - now.tv_usec;
1500                         if (tout.tv_usec < 0) {
1501                                 tout.tv_usec += 1000000;
1502                                 tout.tv_sec  -= 1;
1503                         }
1504                 }
1505                 if (select (nfds, &io, NULL, NULL, &tout) == -1) {
1506                         syslog (LOG_ERR, "Select failed: %s\n", strerror (errno));
1507                 }
1508                 if (FD_ISSET (v4sox, &io)) {
1509 syslog (LOG_DEBUG, "Got unicast input\n");
1510                         handle_4to6 (v4sox);
1511                 } else {
1512                         FD_SET (v4sox, &io);
1513                 }
1514                 if (FD_ISSET (v6sox, &io)) {
1515                         handle_6to4 ();
1516                 } else {
1517                         FD_SET (v6sox, &io);
1518                 }
1519                 if (v4mcast != -1) {
1520                         if (FD_ISSET (v4mcast, &io)) {
1521 syslog (LOG_DEBUG, "WOW: Got multicast input\n");
1522                                 handle_4to6 (v4mcast);
1523                         } else {
1524                                 FD_SET (v4mcast, &io);
1525                         }
1526                 }
1527 //fflush (stdout);
1528         }
1529 }
1530
1531
1532 /* Option descriptive data structures */
1533
1534 char *short_opt = "s:t:dl:p:r:k:feh";
1535
1536 struct option long_opt [] = {
1537         { "v4server", 1, NULL, 's' },
1538         { "tundev", 1, NULL, 't' },
1539         { "default-route", 0, NULL, 'd' },
1540         { "listen", 1, NULL, 'l' },
1541         { "port", 1, NULL, 'p' },
1542         { "radius-multicast", 1, NULL, 'r' },
1543         { "foreground", 0, NULL, 'f' },
1544         { "fork-not", 0, NULL, 'f' },
1545         { "keepalive", 1, NULL, 'k' },
1546         { "keepalive-period-ttl", 1, NULL, 'k' },
1547         { "error-console", 0, NULL, 'e' },
1548         { "help", 0, NULL, 'h' },
1549         { NULL, 0, NULL, 0 }    /* Array termination */
1550 };
1551
1552
1553 /* Parse commandline arguments (and start to process them).
1554  * Return 1 on success, 0 on failure.
1555  */
1556 int process_args (int argc, char *argv []) {
1557         int ok = 1;
1558         int help = 0;
1559         int done = 0;
1560         unsigned long tmpport;
1561         char *endarg;
1562         default_route = false;
1563         while (!done) {
1564                 switch (getopt_long (argc, argv, short_opt, long_opt, NULL)) {
1565                 case -1:
1566                         done = 1;
1567                         if (optind != argc) {
1568                                 fprintf (stderr, "%s: Extra arguments not permitted: %s...\n", program, argv [optind]);
1569                                 ok = 0;
1570                         }
1571                         break;
1572                 case 's':
1573                         if (v4sox != -1) {
1574                                 ok = 0;
1575                                 fprintf (stderr, "%s: You can only specify a single server address\n");
1576                                 continue;
1577                         }
1578                         v4server = optarg;
1579                         if (inet_pton (AF_INET, optarg, &v4peer.sin_addr) <= 0) {
1580                                 ok = 0;
1581                                 fprintf (stderr, "%s: Failed to parse IPv4 address %s\n", program, optarg);
1582                                 break;
1583                         }
1584                         memcpy (&v4listen, &v4peer.sin_addr, 4);
1585                         v4sox = socket (AF_INET, SOCK_DGRAM, 0);
1586                         if (v4sox == -1) {
1587                                 ok = 0;
1588                                 fprintf (stderr, "%s: Failed to allocate UDPv4 socket: %s\n", program, strerror (errno));
1589                                 break;
1590                         }
1591                         break;
1592                 case 't':
1593                         if (v6sox != -1) {
1594                                 ok = 0;
1595                                 fprintf (stderr, "%s: Multiple -t arguments are not permitted\n");
1596                                 break;
1597                         }
1598                         v6sox = open (optarg, O_RDWR);
1599                         if (v6sox == -1) {
1600                                 ok = 0;
1601                                 fprintf (stderr, "%s: Failed to open tunnel device %s: %s\n", program, optarg, strerror (errno));
1602                                 break;
1603                         }
1604                         break;
1605                 case 'd':
1606                         if (default_route) {
1607                                 fprintf (stderr, "%s: You can only request default route setup once\n", program);
1608                                 exit (1);
1609                         }
1610                         default_route = true;
1611                         break;
1612                 case 'l':
1613                         if (inet_pton (AF_INET, optarg, &v4bind.sin_addr.s_addr) != 1) {
1614                                 fprintf (stderr, "%s: IPv4 address %s is not valid\n", program, optarg);
1615                                 exit (1);
1616                         }
1617                         break;
1618                 case 'p':
1619                         tmpport = strtoul (optarg, &endarg, 10);
1620                         if ((*endarg) || (tmpport > 65535)) {
1621                                 fprintf (stderr, "%s: UDP port number %s is not valid\n", program, optarg);
1622                                 exit (1);
1623                         }
1624                         if (tmpport & 0x0001) {
1625                                 fprintf (stderr, "%s: UDP port number %d is odd, which is not permitted\n", program, tmpport);
1626                                 exit (1);
1627                         }
1628                         v4bind.sin_port = htons (tmpport);
1629                         break;
1630                 case 'f':
1631                         if (foreground) {
1632                                 fprintf (stderr, "%s: You can only request foreground operation once\n", program);
1633                                 exit (1);
1634                         }
1635                         foreground = true;
1636                         break;
1637                 case 'e':
1638                         if (log_to_stderr) {
1639                                 fprintf (stderr, "%s: You can only specify logging to stderr once\n", program);
1640                                 exit (1);
1641                         }
1642                         log_to_stderr = true;
1643                         break;
1644                 case 'r':
1645                         if (v4ttl_mcast != -1) {
1646                                 fprintf (stderr, "%s: You can set the radius for multicast once\n", program);
1647                                 exit (1);
1648                         }
1649                         char *zero;
1650                         long setting = strtol(optarg, &zero, 10);
1651                         if (*zero || (setting < 0) || (setting > 255)) {
1652                                 fprintf (stderr, "%s: Multicast radius must be a number in the range 0 to 255, inclusive, not %s\n", program, optarg);
1653                                 exit (1);
1654                         }
1655                         v4ttl_mcast = setting;
1656                         break;
1657                 case 'k':
1658                         if (keepalive_ttl != -1) {
1659                                 fprintf (stderr, "%s: You can only set the keepalive period and TTL once\n", program);
1660                                 exit (1);
1661                         }
1662                         char *rest;
1663                         keepalive_period = strtol (optarg, &rest, 10);
1664                         if (*rest == ',') {
1665                                 rest++;
1666                                 keepalive_ttl = strtol (rest, &rest, 10);
1667                                 if ((keepalive_ttl < 0) || (keepalive_ttl > 255)) {
1668                                         fprintf (stderr, "%s: The keepalive TTL must be in the range 0 to 255, inclusive\n", program);
1669                                         exit (1);
1670                                 }
1671                         } else {
1672                                 keepalive_ttl = 3;
1673                         }
1674                         if (*rest) {
1675                                 fprintf (stderr, "%s: The format for keepalive configuration is 'period,ttl' or just 'period', but not %s\n", program, optarg);
1676                                 exit (1);
1677                         }
1678                         break;
1679                 default:
1680                         ok = 0;
1681                         help = 1;
1682                         /* continue into 'h' to produce usage information */
1683                 case 'h':
1684                         help = 1;
1685                         break;
1686                 }
1687                 if (help || !ok) {
1688                         done = 1;
1689                 }
1690         }
1691         if (help) {
1692 #ifdef HAVE_SETUP_TUNNEL
1693                 fprintf (stderr, "Usage: %s [-d] [-t /dev/tunX]\n       %s -h\n", program, program);
1694 #else
1695                 fprintf (stderr, "Usage: %s [-d] -t /dev/tunX\n       %s -h\n", program, program);
1696 #endif
1697                 return 0;
1698         }
1699         if (!ok) {
1700                 return 0;
1701         }
1702         if (keepalive_ttl != -1) {
1703                 maintenance_time_cycle_max = keepalive_period;
1704         } else {
1705                 keepalive_ttl = 3;
1706         }
1707 #ifdef HAVE_SETUP_TUNNEL
1708         if (v6sox == -1) {
1709                 if (geteuid () != 0) {
1710                         fprintf (stderr, "%s: You should be root, or use -t to specify an accessible tunnel device\n", program);
1711                         return false;
1712                 } else {
1713                         return setup_tunnel ();
1714                 }
1715         }
1716 #else /* ! HAVE_SETUP_TUNNEL */
1717         if (v6sox == -1) {
1718                 fprintf (stderr, "%s: You must specify a tunnel device with -t that is accessible to you\n", program);
1719                 return 0;
1720         }
1721 #endif /* HAVE_SETUP_TUNNEL */
1722         return ok;
1723 }
1724
1725
1726 /* The main program parses commandline arguments and forks off the daemon
1727  */
1728 int main (int argc, char *argv []) {
1729         //
1730         // Initialise
1731         program = strrchr (argv [0], '/');
1732         if (program) {
1733                 program++;
1734         } else {
1735                 program = argv [0];
1736         }
1737         memset (&v4name, 0, sizeof (v4name));
1738         memset (&v4peer, 0, sizeof (v4peer));
1739         memset (&v6name, 0, sizeof (v6name));
1740         v4name.sin_family  = AF_INET ;
1741         v4peer.sin_family  = AF_INET ;
1742         v6name.sin6_family = AF_INET6;
1743         // Fixed public server data, IPv4 and UDP:
1744         v4server = SERVER_6BED4_IPV4_TXT;
1745         v4peer.sin_addr.s_addr = htonl (SERVER_6BED4_IPV4_INT32);
1746         v4name.sin_port = htons (UDP_PORT_6BED4);
1747         v4peer.sin_port = htons (UDP_PORT_6BED4);
1748         memcpy (&v4listen, &v4peer.sin_addr, 4);
1749         memset (&v4bind, 0, sizeof (v4bind));
1750         v4bind.sin_family = AF_INET;
1751         //
1752         // Parse commandline arguments
1753         if (!process_args (argc, argv)) {
1754                 exit (1);
1755         }
1756         //
1757         // Construct the 6bed4 Router's complete link-layer address
1758         router_linklocal_address_complete [8] = (ntohs (v4peer.sin_port) % 256) ^ 0x02;
1759         router_linklocal_address_complete [9] = ntohs (v4peer.sin_port) / 256;
1760         router_linklocal_address_complete [10] = ntohl (v4peer.sin_addr.s_addr) >> 24;
1761         router_linklocal_address_complete [11] = 0xff;
1762         router_linklocal_address_complete [12] = 0xfe;
1763         memcpy (router_linklocal_address_complete + 13, &((uint8_t *) &v4peer.sin_addr) [1], 3);
1764         //
1765         // Open the syslog channel
1766         openlog (program, LOG_NDELAY | LOG_PID | ( log_to_stderr? LOG_PERROR: 0), LOG_DAEMON);
1767         //
1768         // Create memory for the freequeue buffer
1769         freequeue = calloc (freequeue_items, sizeof (struct ndqueue));
1770         if (!freequeue) {
1771                 syslog (LOG_CRIT, "%d: Failed to allocate %d queue items\n", program, freequeue_items);
1772                 exit (1);
1773         }
1774         int i;
1775         for (i = 1; i < freequeue_items; i++) {
1776                 freequeue [i].next = &freequeue [i-1];
1777         }
1778         freequeue = &freequeue [freequeue_items - 1];
1779         //
1780         // Create socket for normal outgoing (and return) 6bed4 traffic
1781         if (v4sox == -1) {
1782                 v4sox = socket (AF_INET, SOCK_DGRAM, 0);
1783                 if (v4sox == -1) {
1784                         syslog (LOG_CRIT, "%s: Failed to open a local IPv4 socket -- does your system still support IPv4?\n", program);
1785                         exit (1);
1786                 }
1787         }
1788         struct sockaddr_in tmpaddr;
1789         memset (&tmpaddr, 0, sizeof (tmpaddr));
1790         tmpaddr.sin_family = AF_INET;
1791         srand (getpid ());
1792         uint16_t portn = rand () & 0x3ffe;
1793         uint16_t port0 = portn + 16384;
1794         //TODO// Move port iteration + allocation to separate function
1795         while (portn < port0) {
1796                 tmpaddr.sin_port = htons ((portn & 0x3ffe) + 49152);
1797                 if (bind (v4sox, (struct sockaddr *) &tmpaddr, sizeof (tmpaddr)) == 0) {
1798                         break;
1799                 }
1800                 portn += 2;
1801         }
1802         if (portn < port0) {
1803                 syslog (LOG_DEBUG, "Bound to UDP port %d\n", ntohs (tmpaddr.sin_port));
1804         } else {
1805                 fprintf (stderr, "%s: All even dynamic ports rejected binding: %s\n", program, strerror (errno));
1806                 exit (1);
1807         }
1808         //
1809         // Setup fragmentation, QoS and TTL options
1810         u_int yes = 1;
1811         u_int no = 0;
1812 #ifdef IP_DONTFRAG
1813         if (setsockopt (v4sox, IPPROTO_IP, IP_DONTFRAG, no, sizeof (no)) == -1) {
1814                 syslog (LOG_ERR, "Failed to permit fragmentation -- not all peers may be accessible with MTU 1280");
1815         }
1816 #else
1817 #warning "Target system lacks support for controlling packet fragmentation"
1818 #endif
1819         socklen_t soxlen = sizeof (v4qos);
1820         if (getsockopt (v4sox, IPPROTO_IP, IP_TOS, &v4qos, &soxlen) == -1) {
1821                 syslog (LOG_ERR, "Quality of Service is not supported by the IPv4-side socket");
1822                 v4qos = 0;
1823         }
1824         v6tc = htonl (v4qos << 20);
1825         soxlen = sizeof (v4ttl);
1826         if (getsockopt (v4sox, IPPROTO_IP, IP_TTL, &v4ttl, &soxlen) == -1) {
1827                 syslog (LOG_ERR, "Time To Live cannot be varied on the IPv4 socket");
1828                 v4ttl = 64;
1829         }
1830         //
1831         // Bind to the IPv4 all-nodes local multicast address
1832         memset (&v4allnodes, 0, sizeof (v4allnodes));
1833         v4allnodes.sin_family = AF_INET;
1834         v4allnodes.sin_port = htons (UDP_PORT_6BED4);
1835         v4allnodes.sin_addr.s_addr = htonl ( INADDR_ANY );
1836         if (multicast) {
1837                 v4mcast = socket (AF_INET, SOCK_DGRAM, 0);
1838                 if (v4mcast != -1) {
1839                         struct ip_mreq mreq;
1840                         mreq.imr_multiaddr.s_addr = htonl ( (224L << 24) | 1L);
1841                         mreq.imr_multiaddr.s_addr = htonl ( INADDR_ANY );
1842                         if (bind (v4mcast, (struct sockaddr *) &v4allnodes, sizeof (v4allnodes)) != 0) {
1843                                 close (v4mcast);
1844                                 v4mcast = -1;
1845                                 syslog (LOG_ERR, "No LAN bypass: Failed to bind to IPv4 all-nodes: %s\n", strerror (errno));
1846                         } else if (setsockopt (v4mcast, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof (yes)) == -1) {
1847                                 close (v4mcast);
1848                                 v4mcast = -1;
1849                                 sysctl (LOG_ERR, "No LAN bypass: Failed to share multicast port: %s\n", strerror (errno));
1850                         } else if (setsockopt (v4mcast, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof (mreq)) == -1) {
1851                                 close (v4mcast);
1852                                 v4mcast = -1;
1853                                 sysctl (LOG_ERR, "No LAN bypass: Failed to setup multicast: %s\n", strerror (errno));
1854                         } else if ((v4ttl_mcast != -1) && (setsockopt (v4mcast, IPPROTO_IP, IP_MULTICAST_TTL, &v4ttl_mcast, sizeof (v4ttl_mcast)) == -1)) {
1855                                 close (v4mcast);
1856                                 v4mcast = -1;
1857                                 sysctl (LOG_ERR, "No LAN bypass: Failed to configure the multicast radius: %s\n", strerror (errno));
1858                         }
1859 #if 0
1860                         if (bind (v4mcast, (struct sockaddr *) &v4allnodes, sizeof (v4allnodes)) != 0) {
1861                                 close (v4mcast);
1862                                 v4mcast = -1;
1863                                 syslog (LOG_ERR, "%s: No LAN bypass: Failed to bind to IPv4 all-nodes\n", program);
1864                         } else if (listen (v4mcast, 10) != 0) {
1865                                 close (v4mcast);
1866                                 v4mcast = -1;
1867                                 syslog (LOG_ERR, "%s: No LAN bypass: Failed to listen to IPv4 all-nodes\n", program);
1868                         }
1869 #endif
1870                 }
1871         } else {
1872                 syslog (LOG_INFO, "%s: No LAN bypass: Not desired\n");
1873         }
1874         //
1875         // Construct an rtnetlink socket for neighbor cache interaction
1876         rtsox = socket (PF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
1877         if (rtsox == -1) {
1878                 syslog (LOG_CRIT, "Failed to gain access to the neighbor cache: %s\n", strerror (errno));
1879                 exit (1);
1880         }
1881         memset (&rtname,   0, sizeof (rtname  ));
1882         memset (&rtkernel, 0, sizeof (rtkernel));
1883         rtname.nl_family = rtkernel.nl_family = AF_NETLINK;
1884         rtname.nl_pid = getpid ();
1885         if (bind (rtsox, (struct sockaddr *) &rtname, sizeof (rtname)) == -1) {
1886                 syslog (LOG_CRIT, "Failed to bind to the neighbor cache socket: %s\n", strerror (errno));
1887                 exit (1);
1888         }
1889         if (connect (rtsox, (struct sockaddr *) &rtkernel, sizeof (rtkernel)) == -1) {
1890                 syslog (LOG_CRIT, "Failed to connect to the neighbor cachr in the kernel; %s\n", strerror (errno));
1891                 exit (1);
1892         }
1893 { uint8_t testll [6];
1894 uint8_t test_address [] = { 0xfe, 0x80, 0,0,0,0,0,0, 0xc2, 0x25, 0x06, 0xff, 0xfe, 0xb0, 0x7e, 0xa6 };
1895 if (lookup_neighbor (test_address, testll)) {
1896 syslog (LOG_INFO, "Successfully retrieved LL: %02x:%02x:%02x:%02x:%02x:%02x\n", testll [0], testll [1], testll [2], testll [3], testll [4], testll [5]);
1897 } else { syslog (LOG_INFO, "Failed to find LL\n"); } }
1898         //
1899         // If port and/or listen arguments were provided, bind to them
1900         if ((v4bind.sin_addr.s_addr != INADDR_ANY) || (v4bind.sin_port != 0)) {
1901                 if (bind (v4sox, (struct sockaddr *) &v4bind, sizeof (v4bind)) != 0) {
1902                         syslog (LOG_CRIT, "%s: Failed to bind to local socket -- did you specify both address and port?\n", program);
1903                         exit (1);
1904                 }
1905         }
1906         //
1907         // Run the daemon
1908         if (foreground) {
1909                 run_daemon ();
1910         } else {
1911                 if (setsid () != -1) {
1912                         syslog (LOG_CRIT, "%s: Failure to detach from parent session: %s\n", program, strerror (errno));
1913                         exit (1);
1914                 }
1915                 switch (fork ()) {
1916                 case -1:
1917                         syslog (LOG_CRIT, "%s: Failure to fork daemon process: %s\n", program, strerror (errno));
1918                         exit (1);
1919                 case 0:
1920                         close (0);
1921                         if (! log_to_stderr) {
1922                                 close (1);
1923                                 close (2);
1924                         }
1925                         run_daemon ();
1926                         break;
1927                 default:
1928                         break;
1929                 }
1930         }
1931         //
1932         // Report successful creation of the daemon
1933         closelog ();
1934         exit (0);
1935 }
1936