Added -x|--xlate <port> option
[6bed4] / src / 6bed4router.c
1 /* 6bed4/router.c -- traffic forwarding daemon for public TSP service
2  *
3  * This is an implementation of the profile that makes TSP service publicly
4  * usable, that is without authentication.  However to avoid abuse of such
5  * a service, it is not anonymous -- IPv6 addresses contain the IPv4 address
6  * and port.
7  *
8  * This is an implementation of neighbour and router discovery over a
9  * tunnel that packs IPv6 inside UDP/IPv4.  This tunnel mechanism is
10  * targeted specifically at embedded devices that are to function on
11  * any network, including IPv4-only, while being designed as IPv6-only
12  * devices with a fallback to this tunnel.
13  *
14  * Interestingly, as a side-effect of this design the router daemon can be
15  * stateless.  Any further requirements that are stateful are most likely
16  * filtering, and that can be solved in stateful firewall configuration.
17  *
18  * The intention of TSP is to enable IPv4-only hosts to connecto to
19  * IPv6 services; the public TSP profile adds to that the ability to
20  * do it in a temporary manner.
21  *
22  * TODO: Should we translate ICMPv4 --> ICMPv6?
23  *
24  * From: Rick van Rein <rick@openfortress.nl>
25  */
26
27
28 #include <stddef.h>
29 #include <stdlib.h>
30 #include <stdint.h>
31 #include <stdio.h>
32 #include <stdbool.h>
33
34 #include <errno.h>
35 #include <unistd.h>
36 #include <string.h>
37 #include <getopt.h>
38 #include <fcntl.h>
39
40 #include <sys/types.h>
41 #include <sys/socket.h>
42 #include <sys/time.h>
43 #include <sys/select.h>
44 #include <sys/ioctl.h>
45
46 #include <netinet/in.h>
47 #include <netinet/ip.h>
48 #include <netinet/ip6.h>
49 #include <netinet/tcp.h>
50 #include <netinet/udp.h>
51 #include <netinet/icmp6.h>
52 #include <arpa/inet.h>
53
54 #include <linux/if.h>
55 #include <linux/if_tun.h>
56 #include <linux/if_ether.h>
57
58
59 /* The following will initially fail, due to an IANA obligation to avoid
60  * default builds with non-standard options.
61  */
62 #include "nonstd.h"
63
64
65 #define MTU 1280
66
67 /*
68  * The HAVE_SETUP_TUNNEL variable is used to determine whether absense of
69  * the -d option leads to an error, or to an attempt to setup the tunnel.
70  * The setup_tunnel() function used for that is defined per platform, such
71  * as for LINUX.  Remember to maintain the manpage's optionality for -d.
72  */
73 #undef HAVE_SETUP_TUNNEL
74
75
76 /* Global variables */
77
78 /* SCTP structures are far from standardised, so we define our own header */
79 struct my_sctphdr {
80         uint16_t source, dest;
81         uint32_t vtag;
82         uint32_t cksum;
83 };
84
85 char *program;
86
87 int v4sox = -1;
88 int v6sox = -1;
89
90 char *v4server = NULL;
91 char *v6server = NULL;
92 char *v6prefix = NULL;
93
94 const uint8_t v6listen_linklocal [16] = { 0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
95 uint8_t v6listen_linklocal_complete [16] = { 0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
96
97 uint8_t lladdr_6bed4 [6];
98
99 struct sockaddr_in6 v6name;
100 struct sockaddr_in  v4name;
101 struct sockaddr_in  v4name_xlate;
102
103 struct in6_addr v6listen;
104 struct in6_addr v6listen_complete;
105 struct in_addr  v4listen;
106
107
108 struct {
109         struct tun_pi tun;
110         union {
111                 struct {
112                         struct ip6_hdr v6hdr;
113                         uint8_t data [MTU - sizeof (struct ip6_hdr)];
114                 } idata;
115                 struct v4frame {
116                         struct ip6_hdr v6hdr;
117                         union {
118                                 struct icmp6_hdr  v6icmphdr;
119                                 struct my_sctphdr v6sctphdr;
120                                 struct tcphdr     v6tcphdr ;
121                                 struct udphdr     v6udphdr ;
122                                 struct {
123                                         struct udphdr     v6udphdr;
124                                         struct my_sctphdr v6sctphdr;
125                                 } tdata;
126                         } adata;
127                 } ndata;
128         } udata;
129 } v4data6;
130
131 #define v4tunpi6        ( v4data6.tun)
132 #define v4data          ((uint8_t *) &v4data6.udata)
133 #define v4hdr6          (&v4data6.udata.idata.v6hdr)
134 #define v4src6          (&v4data6.udata.idata.v6hdr.ip6_src)
135 #define v4dst6          (&v4data6.udata.idata.v6hdr.ip6_dst)
136
137 #define v4v6payload     ((uint16_t *) &v4data6.udata.ndata.adata)
138 #define v4v6plen        ( v4data6.udata.ndata.v6hdr.ip6_plen)
139 #define v4v6nexthdr     ( v4data6.udata.ndata.v6hdr.ip6_nxt)
140 #define v4v6hoplimit    ( v4data6.udata.ndata.v6hdr.ip6_hops)
141
142 #define v4v6icmpdata    ( v4data6.udata.ndata.adata.v6icmphdr.icmp6_data8)
143 #define v4v6icmptype    ( v4data6.udata.ndata.adata.v6icmphdr.icmp6_type)
144 #define v4v6icmpcode    ( v4data6.udata.ndata.adata.v6icmphdr.icmp6_code)
145 #define v4v6icmpcksum   ( v4data6.udata.ndata.adata.v6icmphdr.icmp6_cksum)
146
147 #define v4v6sctpofs     (offsetof (struct v4frame,adata.v6sctphdr))
148 #define v4v6sctpsrcport ( v4data6.udata.ndata.adata.v6sctphdr.source)
149 #define v4v6sctpdstport ( v4data6.udata.ndata.adata.v6sctphdr.dest)
150 #define v4v6sctpcksum   ( v4data6.udata.ndata.adata.v6sctphdr.cksum)
151
152 #define v4v6tunsctpofs  (offsetof (struct v4frame,adata.tdata.v6sctphdr))
153 #define v4v6tunsctpsrcport ( v4data6.udata.ndata.adata.tdata.v6sctphdr.source)
154 #define v4v6tunsctpdstport ( v4data6.udata.ndata.adata.tdata.v6sctphdr.dest)
155 #define v4v6tunsctpcksum   ( v4data6.udata.ndata.adata.tdata.v6sctphdr.cksum)
156
157 #define v4v6tcpsrcport  ( v4data6.udata.ndata.adata.v6tcphdr.source)
158 #define v4v6tcpdstport  ( v4data6.udata.ndata.adata.v6tcphdr.dest)
159 #define v4v6tcpcksum    ( v4data6.udata.ndata.adata.v6tcphdr.check)
160
161 #define v4v6udpsrcport  ( v4data6.udata.ndata.adata.v6udphdr.source)
162 #define v4v6udpdstport  ( v4data6.udata.ndata.adata.v6udphdr.dest)
163 #define v4v6udpcksum    ( v4data6.udata.ndata.adata.v6udphdr.check)
164
165 #define v4ngbsoltarget  (&v4data6.udata.ndata.adata.v6icmphdr.icmp6_data8 [4])
166
167
168 struct {
169         struct tun_pi tun;
170         union {
171                 uint8_t data [MTU];
172                 struct v6frame {
173                         struct ip6_hdr v6hdr;
174                         union {
175                                 struct icmp6_hdr  v6icmphdr;
176                                 struct my_sctphdr v6sctphdr;
177                                 struct tcphdr     v6tcphdr ;
178                                 struct udphdr     v6udphdr ;
179                                 struct {
180                                         struct udphdr     v6udphdr;
181                                         struct my_sctphdr v6sctphdr;
182                                 } tdata;
183                         } adata;
184                 } ndata;
185         } udata;
186         uint8_t zero;
187 } v6data6;
188
189 #define v6tuncmd        ( v6data6.tun)
190 #define v6data          ( v6data6.udata.data)
191 #define v6hdr6          (&v6data6.udata.ndata.v6hdr)
192 #define v6src6          (&v6data6.udata.ndata.v6hdr.ip6_src)
193 #define v6dst6          (&v6data6.udata.ndata.v6hdr.ip6_dst)
194 #define v6hoplimit      ( v6data6.udata.ndata.v6hdr.ip6_hops)
195 #define v6nexthdr       ( v6data6.udata.ndata.v6hdr.ip6_nxt)
196
197 #define v6icmptype      ( v6data6.udata.ndata.adata.v6icmphdr.icmp6_type)
198 #define v6icmpcksum     ( v6data6.udata.ndata.adata.v6icmphdr.icmp6_cksum)
199
200 #define v6sctpcksum     ( v6data6.udata.ndata.adata.v6sctphdr.cksum)
201 #define v6tunsctpcksum  ( v6data6.udata.ndata.adata.tdata.v6sctphdr.cksum)
202
203 #define v6sctpofs       (offsetof(struct v6frame,adata.v6sctphdr))
204 #define v6tunsctpofs    (offsetof(struct v6frame,adata.tdata.v6sctphdr))
205
206 #define v6tcpcksum      ( v6data6.udata.ndata.adata.v6tcphdr.check)
207
208 #define v6udpcksum      ( v6data6.udata.ndata.adata.v6udphdr.check)
209 #define v6udpdstport    ( v6data6.udata.ndata.adata.v6udphdr.dest)
210 #define v6udpsrcport    ( v6data6.udata.ndata.adata.v6udphdr.source)
211
212
213 uint8_t router_linklocal_address [] = {
214         0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x00, 0x00,
215 };
216
217 uint8_t democlient_linklocal_address [] = {
218         0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x00, 0x01,
219 };
220
221 uint8_t allnodes_linklocal_address [] = {
222         0xff, 0x02, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x00, 0x01,
223 };
224
225 uint8_t allrouters_linklocal_address [] = {
226         0xff, 0x02, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x00, 0x02,
227 };
228
229
230
231 #ifndef MAXNUM_MASQHOST
232 #define MAXNUM_MASQHOST 4
233 #endif
234
235 uint16_t num_masqhost = 0;
236 uint8_t masqhost [MAXNUM_MASQHOST][16];
237
238 // ports for 's', 't', 'u' -- SCTP, TCP, UDP have increasing numbers
239
240 #ifndef MAXNUM_PORTPAIRS
241 #define MAXNUM_PORTPAIRS 10
242 #endif
243
244 // masqportpairs holds triples <lowport,highport,masqhostnr>
245 uint16_t num_masqportpairs [3] = { 0, 0, 0 };
246 uint16_t masqportpairs [3][3*MAXNUM_PORTPAIRS];
247
248 // same for ICMPv6
249 uint16_t icmp_num_portpairs = 0;
250 uint16_t icmp_portpairs [3] = { 1, 1, 0 };
251
252
253
254 /*
255  *
256  * Driver routines
257  *
258  */
259
260 #ifndef INTERFACE_NAME_6BED4
261 #define INTERFACE_NAME_6BED4 "6bed4"
262 #endif
263
264 #ifdef LINUX
265 #define HAVE_SETUP_TUNNEL
266 /* Implement the setup_tunnel() command for Linux.
267  * Return 1 on success, 0 on failure.
268  */
269 int setup_tunnel (void) {
270         v6sox = open ("/dev/net/tun", O_RDWR);
271         if (v6sox == -1) {
272                 fprintf (stderr, "%s: Failed to access tunnel driver on /dev/net/tun: %s\n", program, strerror (errno));
273                 return 0;
274         }
275         int ok = 1;
276         struct ifreq ifreq;
277         memset (&ifreq, 0, sizeof (ifreq));
278         strncpy (ifreq.ifr_name, INTERFACE_NAME_6BED4, IFNAMSIZ);
279         ifreq.ifr_flags = IFF_TUN;
280         if (ok && (ioctl (v6sox, TUNSETIFF, (void *) &ifreq) == -1)) {
281                 ok = 0;
282         }
283         ifreq.ifr_name [IFNAMSIZ] = 0;
284         char cmd [512+1];
285         snprintf (cmd, 512, "/sbin/ip -6 addr flush dev %s", ifreq.ifr_name);
286         if (ok && system (cmd) != 0) {
287                 ok = 0;
288         }
289         snprintf (cmd, 512, "/sbin/ip addr add fe80::0 dev %s scope link", ifreq.ifr_name);
290         if (ok && system (cmd) != 0) {
291                 ok = 0;
292         }
293         snprintf (cmd, 512, "/sbin/ip -6 addr add %s dev %s", v6prefix, ifreq.ifr_name);
294         if (ok && system (cmd) != 0) {
295                 ok = 0;
296         }
297         snprintf (cmd, 512, "/sbin/ip link set %s up mtu 1280", ifreq.ifr_name);
298         if (ok && system (cmd) != 0) {
299                 ok = 0;
300         }
301         if (!ok) {
302                 close (v6sox);  /* This removes the tunnel interface */
303                 fprintf (stderr, "Failed to setup tunnel \"%s\"\n", INTERFACE_NAME_6BED4);
304         }
305         return ok;
306 }
307 #endif /* LINUX */
308
309
310 /*
311  *
312  * Utility functions
313  *
314  */
315
316
317 /* Produce an IPv6 address following the 6bed4 structures.
318  *  - The top half is taken from v6listen
319  *  - The bottom contains IPv4 address and port from v4name
320  *  - The last 14 bits are filled with the lanip parameter
321  */
322 void addr_6bed4 (struct in6_addr *dst_ip6, uint16_t lanip) {
323         memcpy (&dst_ip6->s6_addr [0], &v6listen, 8);
324         dst_ip6->s6_addr32 [2] = v4name.sin_addr.s_addr;
325         dst_ip6->s6_addr16 [6] = v4name.sin_port;
326         dst_ip6->s6_addr  [14] = ((dst_ip6->s6_addr [8] & 0x03) << 6)
327                                | ((lanip >> 8) & 0x3f);
328         dst_ip6->s6_addr  [15] = (lanip & 0xff);
329         dst_ip6->s6_addr  [8] &= 0xfc;
330 }
331
332 /* Calculate the ICMPv6 checksum field
333  */
334 uint16_t icmp6_checksum (struct in6_addr *src6, struct in6_addr *dst6,
335                                 uint16_t *payload, size_t payloadlen) {
336         uint16_t plenword = htons (payloadlen); // our ICMPv6 is small
337         uint16_t nxthword = htons (IPPROTO_ICMPV6);
338         uint16_t *area [] = { src6->s6_addr16, dst6->s6_addr16,
339                                 &plenword, &nxthword,
340                                 payload, &payload [2] };
341         uint8_t areawords [] = { 8, 8, 1, 1, 1, (payloadlen >> 1) - 2 };
342         uint32_t csum = 0;
343         u_int8_t i, j;
344         for (i=0; i < 6; i++) {
345                 for (j=0; j<areawords [i]; j++) {
346                         csum += ntohs (area [i] [j]);
347                 }
348         }
349         csum = (csum & 0xffff) + (csum >> 16);
350         csum = (csum & 0xffff) + (csum >> 16);
351         csum = htons (~csum);
352         return csum;
353 }
354
355
356 /* Mangle a packet by replacing an IPv6 address, correcting the checksum.
357  * In all of ICMPv6, UDPv6, TCPv6, SCTPv6, the checksumming is a 1's cpl
358  * of a sum of 16-bit words; the position of the words don't matter and
359  * we can subtract the old address' words and add the new address' words.
360  * Or, as a result of the one's complement, the opposite.  There is some
361  * inclusion of the top half of a 32-bit sum, but that is also neutral.
362  */
363 void masquerade_address (struct in6_addr *var,
364                         const struct in6_addr *new,
365                         uint16_t *csum_field) {
366         int32_t csum = ntohs (~*csum_field);
367         uint8_t i;
368         for (i=0; i<8; i++) {
369                 csum -= ntohs (var->s6_addr16 [i]);
370                 var->s6_addr16 [i] = new->s6_addr16 [i];
371                 csum += ntohs (var->s6_addr16 [i]);
372         }
373         csum = (csum & 0xffff) + (csum >> 16);
374         csum = (csum & 0xffff) + (csum >> 16);
375         *csum_field = htons (~csum);
376 }
377
378
379 /* Send an ICMPv6 reply.  This is constructed at the tunnel end, from
380  * the incoming message.  The parameter indicates how many bytes the
381  * ICMPv6 package counts after the ICMPv6 header.  It must be 4 (mod 8).
382  *
383  * Actions: v4/udp src becomes dest, set v4/udp/v6 src, len, cksum, send.
384  *          reply is always to v4src6, except that if it starts with
385  *          0x00,0x00 it will be replaced with allnodes_linklocal_address.
386  */
387 void icmp6_reply (size_t icmp6bodylen) {
388         v4v6hoplimit = 255;
389         if ((icmp6bodylen & 0x07) != 4) {
390                 return;   /* illegal length, drop */
391         }
392         v4v6plen = htons (icmp6bodylen + 4);
393         memcpy (v4dst6,
394                 (v4src6->s6_addr16 [0])
395                         ? (uint8_t *) v4src6
396                         : allnodes_linklocal_address,
397                 16);
398         memcpy (v4src6, router_linklocal_address, 16);
399         v4v6icmpcksum = icmp6_checksum (v4src6, v4dst6,
400                                 v4v6payload, ntohs (v4v6plen));
401         //
402         // Send the message to the IPv4 originator port
403 printf ("Sending ICMPv6-IPv6-UDP-IPv4 to %d.%d.%d.%d:%d, result = %zd\n",
404 ((uint8_t *) &v4name.sin_addr.s_addr) [0],
405 ((uint8_t *) &v4name.sin_addr.s_addr) [1],
406 ((uint8_t *) &v4name.sin_addr.s_addr) [2],
407 ((uint8_t *) &v4name.sin_addr.s_addr) [3],
408 ntohs (v4name.sin_port),
409         sendto (v4sox,
410                         v4data,
411                         sizeof (struct ip6_hdr) + 4 + icmp6bodylen,
412                         MSG_DONTWAIT,
413                         (struct sockaddr *) &v4name, sizeof (v4name)));
414 }
415
416
417 /* Append the current prefix to an ICMPv6 message.  Incoming optidx
418  * and return values signify original and new offset for ICMPv6 options.
419  * The endlife parameter must be set to obtain zero lifetimes, thus
420  * instructing the tunnel client to stop using an invalid prefix.
421  */
422 size_t icmp6_prefix (size_t optidx, uint8_t endlife) {
423         v4v6icmpdata [optidx++] = 3;    // Type
424         v4v6icmpdata [optidx++] = 4;    // Length
425         v4v6icmpdata [optidx++] = 114;  // This is a /114 prefix
426         v4v6icmpdata [optidx++] = 0xc0; // L=1, A=1, Reserved1=0
427         memset (v4v6icmpdata + optidx, endlife? 0x00: 0xff, 8);
428         optidx += 8;
429                                         // Valid Lifetime: Zero / Infinite
430                                         // Preferred Lifetime: Zero / Infinite
431         memset (v4v6icmpdata + optidx, 0, 4);
432         optidx += 4;
433                                         // Reserved2=0
434         addr_6bed4 ((struct in6_addr *) (v4v6icmpdata + optidx), 0);
435                                         // Set IPv6 prefix
436         optidx += 16;
437         return optidx;
438 }
439
440
441 /*
442  * TODO: DEPRECATED
443  *
444  * Append a Destination Link-Layer Address Option to an ICMPv6
445  * message.  The address is comprised from the remote's UDP port
446  * and IPv4 address, as seen by the router.  They are supplied
447  * in that order, in network byte order.  The resulting address
448  * is 6 bytes, but even though that makes it look like a MAC
449  * address, it really is another beast.
450  * Note that no effort is made in the router to recognise the
451  * "illegal port number" 0x3333 -- the client needs a message
452  * and will recognise it and act on it.
453  */
454 size_t icmp6_dest_linkaddr (size_t optidx) {
455         uint8_t typelen [2] = { ND_OPT_DESTINATION_LINKADDR, 1 };
456         memcpy (v4v6icmpdata + optidx + 0, &typelen, 2);
457         v4v6icmpdata [optidx + 2] = ntohs (v4name.sin_port) & 0xff;
458         v4v6icmpdata [optidx + 3] = ntohs (v4name.sin_port) >> 8;
459         memcpy (v4v6icmpdata + optidx + 4, &v4name.sin_addr, 4);
460         optidx += 8;
461         return optidx;
462 }
463
464
465 /*
466  * Test if an address is a local override.  This function is compiled-in
467  * to support hosts with a /64 from their own ISP and nothing more; they
468  * need to access local IPv6 addresses.  We rely on the 6bed4 port being
469  * 0 to decide that an address cannot be anything but a local override.
470  * Define LOCAL_OVERRIDES_PORT0 to enable this feature.
471  */
472 #ifdef LOCAL_OVERRIDES_PORT0
473 static inline bool is_local_override (struct in6_addr *ip6) {
474         return (ip6->s6_addr16 [6] == 0) && (memcmp (ip6->s6_addr, &v6listen, 8) == 0);
475 }
476 #else
477 #define is_local_override(_) false
478 #endif
479
480
481 /*
482  * Test if the provided IPv6 address matches the prefix used for 6bed4.
483  *TODO: This is oversimplistic, it only cares for the Hetzner /64
484  */
485 static inline bool is_6bed4 (struct in6_addr *ip6) {
486         return memcmp (&v6listen, ip6->s6_addr, 8) == 0;
487 }
488
489 /* Test if the provided IPv6 address matches the fc64::/16 prefix.
490  * If so, the traffic may be bounced using 6bed4 traffic, but it
491  * must not be relayed to the native IPv6 side.
492  * TODO: Perhaps allow only configured <netid>, so fc64:<netid>::/32
493  */
494 static inline bool is_fc64 (struct in6_addr *ip6) {
495         return ip6->s6_addr16 [0] == htons (0xfc64);
496 }
497
498 /* Test if the src and destination share the same /114 and the destination
499  * fills up the rest with zero bits; in other words, test that this is a
500  * package targeted from a 6bed4peer node to its 6bed4router.  This is used
501  * to distinguish special ICMPv6 messages, as well as masquerading targets.
502  */
503 static inline bool is_mine (struct in6_addr *src6, struct in6_addr *dst6) {
504         return ((dst6->s6_addr [15] == 0x00)
505                 && ((dst6->s6_addr [14] & 0x3f) == 0x00)
506                 && (memcmp (dst6->s6_addr, src6->s6_addr, 14) == 0));
507 }
508
509
510 /*
511  * Validate the originator's IPv6 address.  It should match the
512  * UDP/IPv4 coordinates of the receiving 6bed4 socket.  Also,
513  * the /64 prefix (but not the /114 prefix!) must match v6listen.
514  */
515 bool validate_originator (struct in6_addr *ip6) {
516         uint32_t addr;
517         //
518         // Require non-local top halves to match our v6listen_linklocal address
519         // We will enforce our own fallback address (and fc64:<netid>::/32)
520         if (memcmp (ip6, v6listen_linklocal, 8) != 0) {
521                 if (memcmp (&v6listen, ip6->s6_addr, 8) != 0) {
522                         return false;
523                 }
524         }
525         //
526         // Require the sender port to appear in its IPv6 address
527         if (v4name.sin_port != ip6->s6_addr16 [6]) {
528                 return false;
529         }
530         //
531         // Require the sender address to appear in its IPv6 address
532         addr = ntohl (ip6->s6_addr32 [2]) & 0xfcffffff;
533         addr |= ((uint32_t) (ip6->s6_addr [14] & 0xc0)) << (24-6);
534         if (addr != ntohl (v4name.sin_addr.s_addr)) {
535                 return false;
536         }
537         //
538         // We passed with flying colours
539         return true;
540 }
541
542
543
544 /*
545  * Major packet processing functions
546  */
547
548
549 /*
550  * Respond to a Router Solicitation received over the 6bed4 Network.
551  */
552 void handle_6bed4_router_solicit (void) {
553         struct in6_addr observed;
554         v4v6icmptype = ND_ROUTER_ADVERT;
555         v4v6icmpdata [0] = 0;                   // Cur Hop Limit: unspec
556         v4v6icmpdata [1] = 0x18;                // M=0, O=0
557                                                 // H=0, Prf=11=Low
558                                                 // Reserved=0
559 // TODO: wire says 0x44 for router_adv.flags
560         size_t writepos = 2;
561         memset (v4v6icmpdata+writepos, 0xff, 2+4+4);
562                                         // Router Lifetime: max, 18.2h
563                                         // Reachable Time: max
564                                         // Retrans Timer: max
565         writepos += 2+4+4;
566         writepos = icmp6_prefix (writepos, 0);
567         icmp6_reply (writepos);
568 }
569
570
571 /* Handle the IPv4 message pointed at by msg as a neighbouring command.
572  *
573  * Type Code    ICMPv6 meaning                  Handling
574  * ---- ----    -----------------------------   ----------------------------
575  * 133  0       Router Solicitation             Send Router Advertisement
576  * 134  0       Router Advertisement            Ignore
577  * 135  0       Neighbour Solicitation          Send Neighbour Advertisement
578  * 136  0       Neighbour Advertisement         Ignore
579  * 137  0       Redirect                        Ignore
580  */
581 void handle_4to6_nd (ssize_t v4ngbcmdlen) {
582         uint16_t srclinklayer;
583         if (v4ngbcmdlen < sizeof (struct ip6_hdr) + sizeof (struct icmp6_hdr)) {
584                 return;
585         }
586         if (v4v6icmpcode != 0) {
587                 return;
588         }
589         if (icmp6_checksum (v4src6, v4dst6,
590                                 v4v6payload, v4ngbcmdlen-sizeof (struct ip6_hdr)
591                         ) != v4v6icmpcksum) {
592                 return;
593         }
594         //
595         // Approved.  Perform neighbourly courtesy.
596         switch (v4v6icmptype) {
597         case ND_ROUTER_SOLICIT:
598                 //
599                 // Validate Router Solicitation
600                 srclinklayer = 0;
601                 if (v4ngbcmdlen == sizeof (struct ip6_hdr) + 8 + 8) {
602                         // One option is possible, the source link-layer address
603                         if (v4v6icmpdata [4] != 1 || v4v6icmpdata [5] != 1) {
604                                 break;   /* bad opton, ignore */
605                         }
606                         // The source link-layer address is end-aligned
607                         srclinklayer = (v4v6icmpdata [10] << 8) | v4v6icmpdata [11];
608                         if (srclinklayer == 0) {
609                                 break;   /* illegal, ignore */
610                         }
611                 } else if (v4ngbcmdlen == sizeof (struct ip6_hdr) + 8) {
612                         srclinklayer = 0;   /* set for latter filling */
613                 } else {
614                         break;   /* illegal length, drop */
615                 }
616                 //
617                 // Having accepted the Router Advertisement, respond
618                 handle_6bed4_router_solicit ();
619                 break;
620         case ND_NEIGHBOR_SOLICIT:
621                 //
622                 // Validate Neigbour Solicitation
623                 if (!validate_originator (v4src6)) {
624                         break;  /* bad source address, drop */
625                 }
626                 if ((v4ngbcmdlen != sizeof (struct ip6_hdr) + 24) &&
627                     (v4ngbcmdlen != sizeof (struct ip6_hdr) + 24 + 8)) {
628                         break;   /* funny length, drop */
629                 }
630                 if ((memcmp (v4ngbsoltarget, v6listen_linklocal, 16) != 0) &&
631                     (memcmp (v4ngbsoltarget, v6listen_linklocal_complete, 16) != 0) &&
632                     (memcmp (v4ngbsoltarget, &v6listen_complete, 16) != 0)) {
633                         break;  /* target not known here, drop */
634                 }
635                 //
636                 // Construct Neigbour Advertisement
637                 v4v6icmptype = ND_NEIGHBOR_ADVERT;
638                 v4v6icmpdata [0] = 0xc0;
639                 v4v6icmpdata [1] =
640                 v4v6icmpdata [2] =
641                 v4v6icmpdata [3] = 0x00;        // R=1, S=1, O=1, Reserved=0
642                 memcpy (v4v6icmpdata +  4, &v6listen_complete, 16);
643                 // Append option: the target link-layer address
644                 // Note: wire does not include target link-layer address
645                 v4v6icmpdata [20] = 2;          // Type: Target Link-Layer Addr
646                 v4v6icmpdata [21] = 1;          // Length: 1x 8 bytes
647                 memcpy (v4v6icmpdata + 22, lladdr_6bed4, 6);
648                 icmp6_reply (28);       // 28 is the ICMPv6 response length
649                 break;
650         case ND_ROUTER_ADVERT:
651         case ND_NEIGHBOR_ADVERT:
652         case ND_REDIRECT:
653                 break;   /* drop */
654         }
655 }
656
657
658 /*
659  * Forward a message to the masquerading target, or drop it.  This is done
660  * with non-6bed4 packets that are sent from a 6bed4peer node to its
661  * 6bed4router address; see is_mine() for the definition.  The general idea
662  * is that the address that is to be masqueraded can later be reconstructed
663  * from the 6bed4peer's address.
664  */
665 void handle_4to6_masquerading (ssize_t v4datalen) {
666         fprintf (stderr, "Traffic to 6bed4router may be fit for masquerading\n");
667         uint16_t *portpairs = NULL;
668         uint16_t numpairs = 0;
669         uint16_t port = 0;
670         uint16_t *csum_field = NULL;
671         uint16_t sctp_offset = 0;
672         uint16_t skip_csum;
673         switch (v4v6nexthdr) {
674         case IPPROTO_SCTP:
675                 portpairs = masqportpairs [0];  // 's'
676                 numpairs  = num_masqportpairs [0];
677                 port = ntohs (v4v6sctpdstport);
678                 csum_field = &skip_csum;
679                 sctp_offset = v4v6sctpofs;
680                 break;
681         case IPPROTO_TCP:
682                 portpairs = masqportpairs [1];  // 't'
683                 numpairs  = num_masqportpairs [1];
684                 port = ntohs (v4v6tcpdstport);
685                 csum_field = &v4v6tcpcksum;
686                 break;
687         case IPPROTO_UDP:
688                 portpairs = masqportpairs [2];  // 'u'
689                 numpairs  = num_masqportpairs [2];
690                 port = ntohs (v4v6udpdstport);
691                 csum_field = &v4v6udpcksum;
692                 if ((port == 9899) && (v4v6udpsrcport == v4v6udpdstport)) {
693                         // SCTP tunneled over UDP (keep csum_field)
694                         portpairs = masqportpairs [0];
695                         numpairs = num_masqportpairs [0];
696                         port = ntohs (v4v6tunsctpdstport);
697                         sctp_offset = v4v6tunsctpofs;
698                 }
699                 break;
700         case IPPROTO_ICMPV6:
701                 portpairs = icmp_portpairs;
702                 numpairs = icmp_num_portpairs;
703                 port = icmp_portpairs [0];
704                 csum_field = &v4v6icmpcksum;
705                 break;
706         default:
707                 return;
708         }
709         fprintf (stderr, "DEBUG: Looking for masquerading of port %d in %d entries\n", port, numpairs);
710         while (numpairs-- > 0) {
711                 if ((port >= portpairs [0]) && (port <= portpairs [1])) {
712                         //
713                         // Replace masqueraded address by 6bed4router's
714                         fprintf (stderr, "DEBUG: Passing traffic to masquerading address number %d\n", portpairs [2]);
715                         masquerade_address (v4dst6,
716                                 (struct in6_addr *) masqhost [portpairs [2]],
717                                 csum_field);
718                         if (sctp_offset > 0) {
719                                 //TODO// Recompute SCTP's CRC-32 checksum
720                                 // recompute_sctp_checksum (ip6hdr, sctp_offset, framelen);
721                                 //BUT: SCTP checksum does not use pseudo IPhdr
722                                 //SO:  Address masquerading goes undetected :-D
723                         }
724                         //
725                         // Forward immediately, and return from this function
726 printf ("Writing Masqueraded IPv6, result = %zd\n",
727                         write (v6sox, &v4data6, sizeof (struct tun_pi) + v4datalen));
728                         return;
729                 }
730                 portpairs += 3;
731         }
732         //
733         // Silently skip the offered packet
734 }
735
736
737 /* 
738  * Forward a message received over the 6bed4 Network over IPv6.
739  * Note that existing checksums will work well, as only the
740  * Hop Limit has been altered, and this is not part of the
741  * checksum calculations.
742  */
743 void handle_4to6_plain_unicast (ssize_t v4datalen) {
744 printf ("Writing IPv6, result = %zd\n",
745         write (v6sox, &v4data6, sizeof (struct tun_pi) + v4datalen));
746 }
747
748
749 /*
750  * Forward a 6bed4 message to another 6bed4 destination address.
751  * Local address prefixes fc64:<netid>:<ipv4>::/64 are also relayed.
752  * Note that existing checksums will work well, as only the
753  * Hop Limit has been altered, and this is not part of the
754  * checksum calculations.
755  */
756 void relay_4to4_plain_unicast (uint8_t* data, ssize_t v4datalen, struct in6_addr *ip6) {
757         v4name.sin_port = htons (ip6->s6_addr [12] << 8 | ip6->s6_addr [13]);
758         uint8_t *addr = (uint8_t *) &v4name.sin_addr.s_addr;
759         addr [0] = (ip6->s6_addr [8] & 0xfc) | ip6->s6_addr [14] >> 6;
760         memcpy (addr + 1, ip6->s6_addr + 9, 3);
761 printf ("Relaying over 6bed4 Network to %d.%d.%d.%d:%d, result = %zd\n",
762 ((uint8_t *) &v4name.sin_addr.s_addr) [0],
763 ((uint8_t *) &v4name.sin_addr.s_addr) [1],
764 ((uint8_t *) &v4name.sin_addr.s_addr) [2],
765 ((uint8_t *) &v4name.sin_addr.s_addr) [3],
766 ntohs (v4name.sin_port),
767         sendto (v4sox,
768                         data, v4datalen,
769                         MSG_DONTWAIT,
770                         (struct sockaddr *) &v4name, sizeof (v4name)));
771 }
772
773
774 /* Receive a tunnel package, and route it to either the handler for the
775  * tunnel protocol, or to the handler that checks and then unpacks the
776  * contained IPv6.
777  */
778 void handle_4to6 (void) {
779         uint8_t buf [1501];
780         ssize_t buflen;
781         socklen_t adrlen = sizeof (v4name);
782         //
783         // Receive IPv4 package, which may be tunneled or a tunnel request
784         buflen = recvfrom (v4sox,
785                         v4data, MTU,
786                         MSG_DONTWAIT,
787                         (struct sockaddr *) &v4name, &adrlen
788                 );
789         if (buflen == -1) {
790                 printf ("%s: Error receiving IPv4-side package: %s",
791                                 program, strerror (errno));
792                 return;
793         }
794         if (buflen < sizeof (struct ip6_hdr)) {
795                 return;
796         }
797         if ((v4data [0] & 0xf0) != 0x60) {
798                 // Not an IPv6 packet
799                 return;
800         }
801         //
802         // Handle the tunneled IPv6 package (dependent on its class)
803         if ((v4v6nexthdr == IPPROTO_ICMPV6) &&
804                         (v4v6icmptype >= 133) && (v4v6icmptype <= 137)) {
805                 //
806                 // Not Plain: Router Adv/Sol, Neighbor Adv/Sol, Redirect
807                 if (v4v6hoplimit != 255) {
808                         return;
809                 }
810                 handle_4to6_nd (buflen);
811         } else if (is_mine (v4src6, v4dst6)) {
812                 handle_4to6_masquerading (buflen);
813         } else if ((v4dst6->s6_addr [0] != 0xff) && !(v4dst6->s6_addr [8] & 0x01)) {
814                 //
815                 // Plain Unicast
816                 if (is_local_override (v4dst6)) {
817                         // Accept 6bed4 clients, but not forged IPv6 senders
818                         if (!validate_originator (v4src6)) {
819                                 return;
820                         }
821                         handle_4to6_plain_unicast (buflen);
822                 } else if (validate_originator (v4src6)) {
823                         if (v4v6hoplimit-- <= 1) {
824                                 return;
825                         }
826                         if (is_6bed4 (v4dst6) || is_fc64 (v4dst6)) {
827                                 relay_4to4_plain_unicast (v4data, buflen, v4dst6);
828                         } else {
829                                 handle_4to6_plain_unicast (buflen);
830                         }
831                 } else if (is_6bed4 (v4src6)) {
832                         // The sender must not have kept NAT/firewall holes
833                         // open and should be instructed about a change in
834                         // its 6bed4 Link-Local Address.
835                         handle_6bed4_router_solicit ();
836                 }
837         } else {
838                 //
839                 // Plain Multicast
840                 //OPTIONAL// validate_originator, hoplimit, relay_mcast.
841                 return;
842         }
843 }
844
845
846 /* Receive an IPv6 package, check its address and pickup IPv4 address and
847  * port, then package it as a tunnel message and forward it to IPv4:port.
848  */
849 void handle_6to4 (void) {
850         uint16_t mqh;
851         //
852         // Receive the IPv6 package and ensure a consistent size
853         size_t rawlen = read (v6sox, &v6data6, sizeof (v6data6));
854         if (rawlen == -1) {
855                 return;         /* error reading, drop */
856         }
857         if (rawlen < sizeof (struct tun_pi) + sizeof (struct ip6_hdr) + 1) {
858                 return;         /* too small, drop */
859         }
860         if (v6tuncmd.proto != htons (ETH_P_IPV6)) {
861                 return;         /* no IPv6, drop */
862         }
863         if ((v6nexthdr == IPPROTO_ICMPV6) &&
864                         (v6icmptype >= 133) && (v6icmptype <= 137)) {
865                 return;         /* not plain IPv6, drop */
866         }
867         if (v6hoplimit-- <= 1) {
868                 // TODO: Send back an ICMPv6 error message
869                 return;         /* hop limit exceeded, drop */
870         }
871         if ((v6dst6->s6_addr [0] == 0xff) /* TODO:UDP_PORT_NOT_YET_FORCED_TO_EVEN || (v6dst6->s6_addr [8] & 0x01) */ ) {
872 printf ("Received multicast IPv6 data, flags=0x%04x, proto=0x%04x\n", v6tuncmd.flags, v6tuncmd.proto);
873                 //OPTIONAL// handle_6to4_plain_multicast ()
874                 return;         /* multicast, drop */
875         }
876 printf ("Received plain unicast IPv6 data, flags=0x%04x, proto=0x%04x\n", v6tuncmd.flags, v6tuncmd.proto);
877         //
878         // Replace masqueraded addresses configured with -m and its default ::1
879         //TODO// Better use the port number to find the find the masqhost
880         for (mqh=0; mqh<num_masqhost; mqh++) {
881                 if (memcmp (v6src6, masqhost [mqh], 16) == 0) {
882 printf ("Masqueraded sender address in 6to4 set to the client's 6bed4router address\n");
883                         uint16_t *csum_field = NULL;
884                         uint16_t fake_csum;
885                         struct in6_addr masq_src;
886                         uint16_t sctp_offset = 0;
887                         switch (v6nexthdr) {
888                         case IPPROTO_SCTP:
889                                 csum_field = &fake_csum;
890                                 sctp_offset = v6sctpofs;
891                                 break;
892                         case IPPROTO_TCP:
893                                 csum_field = &v6tcpcksum;
894                                 break;
895                         case IPPROTO_UDP:
896                                 csum_field = &v6udpcksum;
897                                 if ((v6udpsrcport == v6udpdstport) &&
898                                                 (v6udpsrcport == htons (9899))) {
899                                         // SCTP tunneled over UDP
900                                         sctp_offset = v6tunsctpofs;
901                                 }
902                                 break;
903                         case IPPROTO_ICMPV6:
904                                 csum_field = &v6icmpcksum;
905                                 break;
906                         default:
907                                 continue;
908                         }
909                         //
910                         // Construct v6src6 from v6dst6, ending in 14 zero bits
911                         memcpy (&masq_src, v6dst6, 16);
912                         masq_src.s6_addr16 [7] &= htons (0xc000);
913                         fprintf (stderr, "Masquerading cksum.old = 0x%04x, ", ntohs (*csum_field));
914                         masquerade_address (v6src6, &masq_src, csum_field);
915                         if (sctp_offset > 0) {
916                                 //TODO// Recompute SCTP's CRC-32 checksum
917                                 // recompute_sctp_checksum (ip6hdr, sctp_offset, framelen);
918                                 //BUT: SCTP checksum does not use pseudo IPhdr
919                                 //SO:  Address masquerading goes undetected :-D
920                         }
921                         fprintf (stderr, "cksum.new = 0x%04x\n", ntohs (*csum_field));
922                         break;
923                 }
924         }
925         //
926         // Ensure that the incoming IPv6 address is properly formatted
927         // Note that this avoids access to ::1/128, fe80::/10, fec0::/10
928 #ifndef TODO_PERMIT_BOUNCE_FOR_32BIT_PREFIX
929         if (memcmp (v6dst6, &v6listen, 8) != 0) {
930                 return;
931         }
932 #else
933         if (v6dst6->s6_addr32 [0] != v6listen.s6_addr32 [0]) {
934                 // Mismatch /32 so this is not going to fly (anywhere)
935                 return;
936         } else if (v6dst6->s6_addr32 [1] != v6listen.s6_addr32 [1]) {
937                 // Match /32 but mismatch /64 -- relay to proper fallback
938                 // that fc64::/16 is not welcome in 6to4 processing
939                 //TODO//OVER_6bed4// relay_6to6_plain_unicast (v6data, rawlen - sizeof (struct tun_pi), v6dst6);
940         }
941 #endif
942         //
943         // Harvest socket address data from destination IPv6, then send
944         relay_4to4_plain_unicast (v6data, rawlen - sizeof (struct tun_pi), v6dst6);
945 }
946
947
948 /* Run the daemon core code, passing information between IPv4 and IPv6 and
949  * responding to tunnel requests if so requested.
950  */
951 void run_daemon (void) {
952         fd_set io;
953         FD_ZERO (&io);
954         FD_SET (v4sox, &io);
955         FD_SET (v6sox, &io);
956         int nfds = (v4sox < v6sox)? (v6sox + 1): (v4sox + 1);
957         while (1) {
958                 select (nfds, &io, NULL, NULL, NULL);
959                 if (FD_ISSET (v4sox, &io)) {
960                         handle_4to6 ();
961                 } else {
962                         FD_SET (v4sox, &io);
963                 }
964                 if (FD_ISSET (v6sox, &io)) {
965                         handle_6to4 ();
966                 } else {
967                         FD_SET (v6sox, &io);
968                 }
969 fflush (stdout);
970         }
971 }
972
973
974 /* Option descriptive data structures */
975
976 char *short_opt = "l:L:d:hit:u:s:m:x:";
977
978 struct option long_opt [] = {
979         { "v4listen", 1, NULL, 'l' },
980         { "v6prefix", 1, NULL, 'L' },
981         { "tundev", 1, NULL, 'd' },
982         { "help", 0, NULL, 'h' },
983         { "icmp", 0, NULL, 'i' },
984         { "tcp", 1, NULL, 't' },
985         { "udp", 1, NULL, 'u' },
986         { "sctp", 1, NULL, 's' },
987         { "masqhost", 1, NULL, 'm' },
988         { "xlate", 1, NULL, 'x' },
989         // { "fallback4", 1 NULL, 'f' },
990         // { "fallback6", 1, NULL, 'F' },
991         { NULL, 0, NULL, 0 }    /* Array termination */
992 };
993
994 /* Parse commandline arguments (and start to process them).
995  * Return 1 on success, 0 on failure.
996  */
997 int process_args (int argc, char *argv []) {
998         int ok = 1;
999         int help = (argc == 1);
1000         int done = 0;
1001         int opt;
1002         while (!done) {
1003                 switch (opt = getopt_long (argc, argv, short_opt, long_opt, NULL)) {
1004                 case -1:
1005                         done = 1;
1006                         if (optind != argc) {
1007                                 fprintf (stderr, "%s: Extra arguments not permitted: %s...\n", program, argv [optind]);
1008                                 ok = 0;
1009                         }
1010                         break;
1011                 case 'l':
1012                         if (v4name.sin_family != 0) {
1013                                 ok = 0;
1014                                 fprintf (stderr, "%s: Only one -l argument is permitted\n", program);
1015                                 break;
1016                         }
1017                         v4name.sin_family = AF_INET;
1018                         v4server = optarg;
1019                         if (inet_pton (AF_INET, optarg, &v4name.sin_addr) <= 0) {
1020                                 ok = 0;
1021                                 fprintf (stderr, "%s: Failed to parse IPv4 address %s\n", program, optarg);
1022                                 break;
1023                         }
1024                         memcpy (&v4listen, &v4name.sin_addr, 4);
1025                         break;
1026                 case 'x':
1027                         if (v4name_xlate.sin_family != 0) {
1028                                 ok = 0;
1029                                 fprintf (stderr, "%s: At most one -x argument is permitted\n", program);
1030                                 break;
1031                         }
1032                         v4name_xlate.sin_family = AF_INET;
1033                         ((uint8_t *) &v4name_xlate.sin_addr.s_addr) [0] = 127;
1034                         ((uint8_t *) &v4name_xlate.sin_addr.s_addr) [1] = 0;
1035                         ((uint8_t *) &v4name_xlate.sin_addr.s_addr) [2] = 0;
1036                         ((uint8_t *) &v4name_xlate.sin_addr.s_addr) [3] = 1;
1037                         int port = atoi (optarg);
1038                         if ((port <= 0) || (port > 65535)) {
1039                                 ok = 0;
1040                                 fprintf (stderr, "%s: Port number for -x out of range\n", program);
1041                                 break;
1042                         }
1043                         v4name_xlate.sin_port = htons (port);
1044                         break;
1045                 case 'L':
1046                         if (v6server) {
1047                                 ok = 0;
1048                                 fprintf (stderr, "%s: Only one -L argument is permitted\n", program);
1049                                 break;
1050                         }
1051                         char *slash64 = strchr (optarg, '/');
1052                         if (!slash64 || strcmp (slash64, "/64") != 0) {
1053                                 ok = 0;
1054                                 fprintf (stderr, "%s: The -L argument must be an explicit /64 prefix and not %s\n", program, slash64? slash64: "implied");
1055                                 break;
1056                         }
1057                         *slash64 = 0;
1058                         v6server = strdup (optarg);
1059                         *slash64 = '/';
1060                         v6prefix = optarg;
1061                         if (!v6server || (inet_pton (AF_INET6, v6server, &v6listen) <= 0)) {
1062                                 ok = 0;
1063                                 fprintf (stderr, "%s: Failed to parse IPv6 prefix %s\n", program, optarg);
1064                                 break;
1065                         }
1066                         if (v6listen.s6_addr32 [2] || v6listen.s6_addr32 [3]) {
1067                                 ok = 0;
1068                                 fprintf (stderr, "%s: IPv6 prefix contains bits beyond its /64 prefix: %s\n", program, optarg);
1069                                 break;
1070                         }
1071                         break;
1072                 case 'd':
1073                         if (v6sox != -1) {
1074                                 ok = 0;
1075                                 fprintf (stderr, "%s: Multiple -d arguments are not permitted\n", program);
1076                                 break;
1077                         }
1078                         v6sox = open (optarg, O_RDWR);
1079                         if (v6sox == -1) {
1080                                 ok = 0;
1081                                 fprintf (stderr, "%s: Failed to open tunnel device %s: %s\n", program, optarg, strerror (errno));
1082                                 break;
1083                         }
1084                         break;
1085                 case 's':
1086                 case 't':
1087                 case 'u':
1088                 case 'i':
1089                         // Masqueraded port (range) for SCTP, TCP, UDP
1090                         //TODO// Should we support ICMPv6 as well? [honeypots]
1091                         if (num_masqhost == 0) {
1092                                 //TODO// Reference v6listen instead of ::1
1093                                 inet_pton (AF_INET6, "::1", masqhost [0]);
1094                                 num_masqhost = 1;
1095                         }
1096                         // Temporary variables in local scope
1097                         if (opt == 'i') {
1098                                 if (icmp_num_portpairs > 0) {
1099                                         fprintf (stderr, "%s: Only one ICMP masquerading setting is possible\n", program);
1100                                         ok = 0;
1101                                         break;
1102                                 }
1103                                 icmp_portpairs [2] = num_masqhost - 1;
1104                                 icmp_num_portpairs++;
1105                         } else {
1106                                 unsigned long fromport, toport;
1107                                 uint16_t *portpairs;
1108                                 errno = 0;
1109                                 if (*optarg != ':') {
1110                                         fromport = strtoul (optarg, &optarg, 10);
1111                                 } else {
1112                                         fromport = 1;
1113                                 }
1114                                 if (*optarg != ':') {
1115                                         toport = fromport;
1116                                 } else if (*++optarg) {
1117                                         toport = strtoul (optarg, &optarg, 10);
1118                                 } else {
1119                                         toport = 65535;
1120                                 }
1121                                 if (errno || *optarg) {
1122                                         fprintf (stderr, "%s: Failed to parse port or port:port\n", program);
1123                                         ok = 0;
1124                                         break;
1125                                 }
1126                                 if ((fromport < 1) || (fromport > toport) || (toport > 65535)) {
1127                                         fprintf (stderr, "%s: Invalid port or port range\n", program);
1128                                         ok = 0;
1129                                         break;
1130                                 }
1131                                 if (++num_masqportpairs [opt-'s'] >= MAXNUM_PORTPAIRS) {
1132                                         fprintf (stderr, "%s: You cannot define so many ports / port pairs\n", program);
1133                                         ok = 0;
1134                                         break;
1135                                 }
1136                                 portpairs = &masqportpairs [opt-'s'][3*(num_masqportpairs [opt-'s']-1)];
1137                                 portpairs [0] = fromport;
1138                                 portpairs [1] = toport;
1139                                 portpairs [2] = num_masqhost-1;
1140                         }
1141                         break;
1142                 case 'm':
1143                         // Masqueraded host for TCP, UDP, SCTP (default is ::1)
1144                         if (++num_masqhost >= MAXNUM_MASQHOST) {
1145                                 fprintf (stderr, "%s: No more than %d masquering hosts can be specified\n", program, MAXNUM_MASQHOST);
1146                                 ok = 0;
1147                                 break;
1148                         }
1149                         if (inet_pton (AF_INET6, optarg, masqhost [num_masqhost]) != 1) {
1150                                 fprintf (stderr, "%s: Unsupported masquerading host \"%s\"\n", program, optarg);
1151                                 ok = 0;
1152                                 break;
1153                         }
1154                         num_masqhost++;
1155                         break;
1156                 // case 'f':
1157                 // case 'F':
1158                 //      // Fallback addresses for IPv4, IPv6
1159                 //      ok = 0; //TODO:IMPLEMENT//
1160                 //      help = 1;
1161                 //      break;
1162                 default:
1163                         ok = 0;
1164                         /* continue into 'h' to produce usage information */
1165                 case 'h':
1166                         help = 1;
1167                         break;
1168                 }
1169                 if (help || !ok) {
1170                         done = 1;
1171                 }
1172         }
1173         if (help) {
1174 #ifdef HAVE_SETUP_TUNNEL
1175                 fprintf (stderr, "Usage: %s [-d /dev/tunX] -l <v4server> -L <v6prefix>/64 [-x <port>]\n       %s -h\n", program, program);
1176                 fprintf (stderr, "\tUse -s|-t|-u to masquerade a port (range) to last -m host or ::1\n");
1177 #else
1178                 fprintf (stderr, "Usage: %s -d /dev/tunX -l <v4server> -L <v6prefix>/64\n       %s -h\n", program, program);
1179                 fprintf (stderr, "\tUse -s|-t|-u to masquerade a port (range) to last -m host of ::1\n");
1180 #endif
1181                 return ok;
1182         }
1183         if (v4name.sin_family == 0) {
1184                 fprintf (stderr, "%s: Use -l to specify an IPv4 address for the tunnel interface\n", program);
1185                 return 0;
1186         }
1187         if (v4name_xlate.sin_family == 0) {
1188                 memcpy (&v4name_xlate, &v4name, sizeof (v4name_xlate));
1189         } else {
1190                 v4server = "127.0.0.1";
1191         }
1192         v4sox = socket (AF_INET, SOCK_DGRAM, 0);
1193         if (v4sox == -1) {
1194                 fprintf (stderr, "%s: Failed to allocate UDPv4 socket: %s\n", program, strerror (errno));
1195                 return 0;
1196         }
1197         if (bind (v4sox, (struct sockaddr *) &v4name_xlate, sizeof (v4name_xlate)) != 0) {
1198                 fprintf (stderr, "%s: Failed to bind to UDPv4 %s:%d: %s\n", program, v4server, ntohs (v4name_xlate.sin_port), strerror (errno));
1199                 ok = 0;
1200         }
1201         if (!ok) {
1202                 return 0;
1203         }
1204 #ifdef HAVE_SETUP_TUNNEL
1205         if (v6sox == -1) {
1206                 if (geteuid () != 0) {
1207                         fprintf (stderr, "%s: You should be root, or use -d to specify an accessible tunnel device\n", program);
1208                         return 0;
1209                 }
1210                 ok = setup_tunnel ();
1211         }
1212         if (!v6server) {
1213                 fprintf (stderr, "%s: Use -L to specify a /64 prefix on the IPv6 side\n", program);
1214                 return 0;
1215         }
1216 #else /* ! HAVE_SETUP_TUNNEL */
1217         if (v6sox == -1) {
1218                 fprintf (stderr, "%s: You must specify a tunnel device with -d that is accessible to you\n", program);
1219                 return 0;
1220         }
1221 #endif /* HAVE_SETUP_TUNNEL */
1222         return ok;
1223 }
1224
1225
1226 /* The main program parses commandline arguments and forks off the daemon
1227  */
1228 int main (int argc, char *argv []) {
1229         //
1230         // Initialise
1231         program = argv [0];
1232         memset (&v6name      , 0, sizeof (v6name      ));
1233         memset (&v4name      , 0, sizeof (v4name      ));
1234         memset (&v4name_xlate, 0, sizeof (v4name_xlate));
1235         v6name.sin6_family = AF_INET6;
1236         v4name.sin_port = htons (UDP_PORT_6BED4);   /* 6BED4 standard port */
1237         v4tunpi6.flags = 0;
1238         v4tunpi6.proto = htons (ETH_P_IPV6);
1239         //
1240         // Parse commandline arguments
1241         if (!process_args (argc, argv)) {
1242                 exit (1);
1243         }
1244         //
1245         // Setup a few addresses for later comparison/reproduction
1246         //  * lladdr_6bed4 is the 6bed4 Link-Local Address
1247         //  * v6listen_complete is the router's full IPv6 address (with if-id)
1248         //  * v6listen_linklocal_complete is fe80::/64 plus the router's if-id
1249         // A few others have already been setup at this time
1250         //  * v6listen is the router's 6bed4 prefix ending in 64 zero bits
1251         //  * v6listen_linklocal is the address fe80::/128
1252         //
1253         lladdr_6bed4 [0] = UDP_PORT_6BED4 & 0xff;
1254         lladdr_6bed4 [1] = UDP_PORT_6BED4 >> 8;
1255         memcpy (lladdr_6bed4 + 2, (uint8_t *) &v4name.sin_addr, 4);
1256         addr_6bed4 (&v6listen_complete, 0);
1257
1258         memcpy (v6listen_linklocal_complete, v6listen_linklocal, 8);
1259         memcpy (v6listen_linklocal_complete + 8, &v6listen_complete.s6_addr [8], 8);
1260 printf ("LISTEN lladdr_6bed4 = %02x:%02x:%02x:%02x:%02x:%02x\n", lladdr_6bed4 [0], lladdr_6bed4 [1], lladdr_6bed4 [2], lladdr_6bed4 [3], lladdr_6bed4 [4], lladdr_6bed4 [5]);
1261 printf ("LISTEN v6listen = %x:%x:%x:%x:%x:%x:%x:%x\n", htons (v6listen.s6_addr16 [0]), htons (v6listen.s6_addr16 [1]), htons (v6listen.s6_addr16 [2]), htons (v6listen.s6_addr16 [3]), htons (v6listen.s6_addr16 [4]), htons (v6listen.s6_addr16 [5]), htons (v6listen.s6_addr16 [6]), htons (v6listen.s6_addr16 [7]));
1262 printf ("LISTEN v6listen_complete = %x:%x:%x:%x:%x:%x:%x:%x\n", htons (v6listen_complete.s6_addr16 [0]), htons (v6listen_complete.s6_addr16 [1]), htons (v6listen_complete.s6_addr16 [2]), htons (v6listen_complete.s6_addr16 [3]), htons (v6listen_complete.s6_addr16 [4]), htons (v6listen_complete.s6_addr16 [5]), htons (v6listen_complete.s6_addr16 [6]), htons (v6listen_complete.s6_addr16 [7]));
1263 printf ("LISTEN v6listen_linklocal = %x:%x:%x:%x:%x:%x:%x:%x\n", htons (((uint16_t *) v6listen_linklocal) [0]), htons (((uint16_t *) v6listen_linklocal) [1]), htons (((uint16_t *) v6listen_linklocal) [2]), htons (((uint16_t *) v6listen_linklocal) [3]), htons (((uint16_t *) v6listen_linklocal) [4]), htons (((uint16_t *) v6listen_linklocal) [5]), htons (((uint16_t *) v6listen_linklocal) [6]), htons (((uint16_t *) v6listen_linklocal) [7]));
1264 printf ("LISTEN v6listen_linklocal_complete = %x:%x:%x:%x:%x:%x:%x:%x\n", htons (((uint16_t *) v6listen_linklocal_complete) [0]), htons (((uint16_t *) v6listen_linklocal_complete) [1]), htons (((uint16_t *) v6listen_linklocal_complete) [2]), htons (((uint16_t *) v6listen_linklocal_complete) [3]), htons (((uint16_t *) v6listen_linklocal_complete) [4]), htons (((uint16_t *) v6listen_linklocal_complete) [5]), htons (((uint16_t *) v6listen_linklocal_complete) [6]), htons (((uint16_t *) v6listen_linklocal_complete) [7]));
1265         //
1266         // Start the main daemon process
1267 #ifdef SKIP_TESTING_KLUDGE_IN_FOREGROUND
1268         switch (fork ()) {
1269         case -1:                /* Error forking */
1270                 fprintf (stderr, "%s: Failed to fork: %s\n", program, strerror (errno));
1271                 exit (1);
1272         case 0:                 /* Child process */
1273                 close (0);
1274                 //TODO: tmp.support for ^printf// close (1);
1275                 close (2);
1276                 setsid ();
1277                 run_daemon ();
1278                 break;
1279         default:                /* Parent process */
1280                 close (v4sox);
1281                 close (v6sox);
1282                 break;
1283         }
1284 #else
1285         run_daemon ();
1286 #endif
1287         //
1288         // Report successful creation of the daemon
1289         return 0;
1290 }