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