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