Masquerading for TCP and UDP requires a new checksum; added it differentially
authorRick van Rein <rick@openfortress.nl>
Fri, 22 Sep 2017 23:23:24 +0000 (01:23 +0200)
committerRick van Rein <rick@openfortress.nl>
Fri, 22 Sep 2017 23:24:40 +0000 (01:24 +0200)
6bed4router.c
6bed4router.man
HISTORY [deleted file]
HISTORY.MD [new file with mode: 0644]
LICENSE [deleted file]
LICENSE.MD [new file with mode: 0644]
PREFIXES [deleted file]
PREFIXES.MD [new file with mode: 0644]
README.MD [new file with mode: 0644]

index e001a68..e2a131f 100644 (file)
@@ -78,7 +78,7 @@
 struct my_sctphdr {
        uint16_t source, dest;
        uint32_t vtag;
-       uint32_t checksum;
+       uint32_t cksum;
 };
 
 char *program;
@@ -113,15 +113,11 @@ struct {
                struct {
                        struct ip6_hdr v6hdr;
                        union {
-                               struct icmp6_hdr v6icmphdr;
+                               struct icmp6_hdr  v6icmphdr;
                                struct my_sctphdr v6sctphdr;
-                               struct tcphdr  v6tcphdr ;
-                               struct udphdr  v6udphdr ;
+                               struct tcphdr     v6tcphdr ;
+                               struct udphdr     v6udphdr ;
                        } adata;
-                       struct icmp6_hdr v6icmphdr;
-                       struct my_sctphdr v6sctphdr;
-                       struct tcphdr  v6tcphdr ;
-                       struct udphdr  v6udphdr ;
                } ndata;
        } udata;
 } v4data6;
@@ -132,11 +128,11 @@ struct {
 #define v4src6         (&v4data6.udata.idata.v6hdr.ip6_src)
 #define v4dst6         (&v4data6.udata.idata.v6hdr.ip6_dst)
 
+#define v4v6payload    ((uint16_t *) &v4data6.udata.ndata.adata)
 #define v4v6plen       ( v4data6.udata.ndata.v6hdr.ip6_plen)
 #define v4v6nexthdr    ( v4data6.udata.ndata.v6hdr.ip6_nxt)
 #define v4v6hoplimit   ( v4data6.udata.ndata.v6hdr.ip6_hops)
 
-#define v4icmp6                (&v4data6.udata.ndata.adata.v6icmphdr)
 #define v4v6icmpdata   ( v4data6.udata.ndata.adata.v6icmphdr.icmp6_data8)
 #define v4v6icmptype   ( v4data6.udata.ndata.adata.v6icmphdr.icmp6_type)
 #define v4v6icmpcode   ( v4data6.udata.ndata.adata.v6icmphdr.icmp6_code)
@@ -144,12 +140,15 @@ struct {
 
 #define v4v6sctpsrcport        ( v4data6.udata.ndata.adata.v6sctphdr.source)
 #define v4v6sctpdstport        ( v4data6.udata.ndata.adata.v6sctphdr.dest)
+#define v4v6sctpcksum  ( v4data6.udata.ndata.adata.v6sctphdr.cksum)
 
 #define v4v6tcpsrcport ( v4data6.udata.ndata.adata.v6tcphdr.source)
 #define v4v6tcpdstport ( v4data6.udata.ndata.adata.v6tcphdr.dest)
+#define v4v6tcpcksum   ( v4data6.udata.ndata.adata.v6tcphdr.check)
 
 #define v4v6udpsrcport ( v4data6.udata.ndata.adata.v6udphdr.source)
 #define v4v6udpdstport ( v4data6.udata.ndata.adata.v6udphdr.dest)
+#define v4v6udpcksum   ( v4data6.udata.ndata.adata.v6udphdr.check)
 
 #define v4ngbsoltarget (&v4data6.udata.ndata.adata.v6icmphdr.icmp6_data8 [4])
 
@@ -158,21 +157,35 @@ struct {
        struct tun_pi tun;
        union {
                uint8_t data [MTU];
-               struct ip6_hdr v6hdr;
-               struct icmp6_hdr v6icmp;
+               struct {
+                       struct ip6_hdr v6hdr;
+                       union {
+                               struct icmp6_hdr  v6icmphdr;
+                               struct my_sctphdr v6sctphdr;
+                               struct tcphdr     v6tcphdr ;
+                               struct udphdr     v6udphdr ;
+                       } adata;
+               } ndata;
        } udata;
        uint8_t zero;
 } v6data6;
 
 #define v6tuncmd       ( v6data6.tun)
 #define v6data         ( v6data6.udata.data)
-#define v6hdr6         (&v6data6.udata.v6hdr)
-#define v6src6         (&v6data6.udata.v6hdr.ip6_src)
-#define v6dst6         (&v6data6.udata.v6hdr.ip6_dst)
-#define v6hoplimit     ( v6data6.udata.v6hdr.ip6_hops)
+#define v6hdr6         (&v6data6.udata.ndata.v6hdr)
+#define v6src6         (&v6data6.udata.ndata.v6hdr.ip6_src)
+#define v6dst6         (&v6data6.udata.ndata.v6hdr.ip6_dst)
+#define v6hoplimit     ( v6data6.udata.ndata.v6hdr.ip6_hops)
+#define v6nexthdr      ( v6data6.udata.ndata.v6hdr.ip6_nxt)
 
-#define v6nexthdr      ( v6data6.udata.v6hdr.ip6_nxt)
-#define v6icmptype     ( v6data6.udata.v6icmp.icmp6_type)
+#define v6icmptype     ( v6data6.udata.ndata.adata.v6icmphdr.icmp6_type)
+#define v6icmpcksum    ( v6data6.udata.ndata.adata.v6icmphdr.icmp6_cksum)
+
+#define v6sctpcksum    ( v6data6.udata.ndata.adata.v6sctphdr.cksum)
+
+#define v6tcpcksum     ( v6data6.udata.ndata.adata.v6tcphdr.check)
+
+#define v6udpcksum     ( v6data6.udata.ndata.adata.v6udphdr.check)
 
 
 uint8_t router_linklocal_address [] = {
@@ -292,11 +305,14 @@ void addr_6bed4 (struct in6_addr *dst_ip6, uint16_t lanip) {
 
 /* Calculate the ICMPv6 checksum field
  */
-uint16_t icmp6_checksum (size_t payloadlen) {
-       uint16_t plenword = htons (payloadlen);
+uint16_t icmp6_checksum (struct in6_addr *src6, struct in6_addr *dst6,
+                               uint16_t *payload, size_t payloadlen) {
+       uint16_t plenword = htons (payloadlen); // our ICMPv6 is small
        uint16_t nxthword = htons (IPPROTO_ICMPV6);
-       uint16_t *area [] = { (uint16_t *) v4src6, (uint16_t *) v4dst6, &plenword, &nxthword, (uint16_t *) v4icmp6, (uint16_t *) v4v6icmpdata };
-       uint8_t areawords [] = { 8, 8, 1, 1, 1, payloadlen/2 - 2 };
+       uint16_t *area [] = { src6->s6_addr16, dst6->s6_addr16,
+                               &plenword, &nxthword,
+                               payload, &payload [2] };
+       uint8_t areawords [] = { 8, 8, 1, 1, 1, (payloadlen >> 1) - 2 };
        uint32_t csum = 0;
        u_int8_t i, j;
        for (i=0; i < 6; i++) {
@@ -311,6 +327,29 @@ uint16_t icmp6_checksum (size_t payloadlen) {
 }
 
 
+/* Mangle a packet by replacing an IPv6 address, correcting the checksum.
+ * In all of ICMPv6, UDPv6, TCPv6, SCTPv6, the checksumming is a 1's cpl
+ * of a sum of 16-bit words; the position of the words don't matter and
+ * we can subtract the old address' words and add the new address' words.
+ * Or, as a result of the one's complement, the opposite.  There is some
+ * inclusion of the top half of a 32-bit sum, but that is also neutral.
+ */
+void masquerade_address (struct in6_addr *var,
+                       const struct in6_addr *new,
+                       uint16_t *csum_field) {
+       int32_t csum = ntohs (~*csum_field);
+       uint8_t i;
+       for (i=0; i<8; i++) {
+               csum -= ntohs (var->s6_addr16 [i]);
+               var->s6_addr16 [i] = new->s6_addr16 [i];
+               csum += ntohs (var->s6_addr16 [i]);
+       }
+       csum = (csum & 0xffff) + (csum >> 16);
+       csum = (csum & 0xffff) + (csum >> 16);
+       *csum_field = htons (~csum);
+}
+
+
 /* Send an ICMPv6 reply.  This is constructed at the tunnel end, from
  * the incoming message.  The parameter indicates how many bytes the
  * ICMPv6 package counts after the ICMPv6 header.  It must be 4 (mod 8).
@@ -331,7 +370,8 @@ void icmp6_reply (size_t icmp6bodylen) {
                        : allnodes_linklocal_address,
                16);
        memcpy (v4src6, router_linklocal_address, 16);
-       v4v6icmpcksum = icmp6_checksum (ntohs (v4v6plen));
+       v4v6icmpcksum = icmp6_checksum (v4src6, v4dst6,
+                               v4v6payload, ntohs (v4v6plen));
        //
        // Send the message to the IPv4 originator port
 printf ("Sending ICMPv6-IPv6-UDP-IPv4 to %d.%d.%d.%d:%d, result = %zd\n",
@@ -532,7 +572,9 @@ void handle_4to6_nd (ssize_t v4ngbcmdlen) {
        if (v4v6icmpcode != 0) {
                return;
        }
-       if (icmp6_checksum (v4ngbcmdlen - sizeof (struct ip6_hdr)) != v4v6icmpcksum) {
+       if (icmp6_checksum (v4src6, v4dst6,
+                               v4v6payload, v4ngbcmdlen-sizeof (struct ip6_hdr)
+                       ) != v4v6icmpcksum) {
                return;
        }
        //
@@ -610,23 +652,30 @@ void handle_4to6_masquerading (ssize_t v4datalen) {
        fprintf (stderr, "Traffic to 6bed4router may be fit for masquerading\n");
        uint16_t *portpairs = NULL;
        uint16_t numpairs = 0;
-       uint16_t port;
+       uint16_t port = 0;
+       uint16_t *csum_field = NULL;
        switch (v4v6nexthdr) {
+#ifdef CHECKSUM_SCTP_WOULD_BE_LIKE_FOR_OTHERS
        case IPPROTO_SCTP:
                portpairs = masqportpairs [0];  // 's'
                numpairs  = num_masqportpairs [0];
                port = ntohs (v4v6sctpdstport);
+               csum_field = &v4v6sctpcksum;
                break;
+#endif
        case IPPROTO_TCP:
                portpairs = masqportpairs [1];  // 't'
                numpairs  = num_masqportpairs [1];
                port = ntohs (v4v6tcpdstport);
+               csum_field = &v4v6tcpcksum;
                break;
        case IPPROTO_UDP:
                portpairs = masqportpairs [2];  // 'u'
                numpairs  = num_masqportpairs [2];
                port = ntohs (v4v6udpdstport);
+               csum_field = &v4v6udpcksum;
                break;
+       //TODO// ICMPv6
        default:
                break;
        }
@@ -636,7 +685,9 @@ void handle_4to6_masquerading (ssize_t v4datalen) {
                        //
                        // Replace masqueraded address by 6bed4router's
                        fprintf (stderr, "DEBUG: Passing traffic to masquerading address number %d\n", portpairs [2]);
-                       memcpy (v4dst6, masqhost [portpairs [2]], 16);
+                       masquerade_address (v4dst6,
+                               (struct in6_addr *) masqhost [portpairs [2]],
+                               csum_field);
                        //
                        // Forward immediately, and return from this function
 printf ("Writing Masqueraded IPv6, result = %zd\n",
@@ -792,9 +843,33 @@ printf ("Received plain unicast IPv6 data, flags=0x%04x, proto=0x%04x\n", v6tunc
        for (mqh=0; mqh<num_masqhost; mqh++) {
                if (memcmp (v6src6, masqhost [mqh], 16) == 0) {
 printf ("Masqueraded sender address in 6to4 set to the client's 6bed4router address\n");
-                       memcpy (v6src6, v6dst6, 15);
-                       v6src6->s6_addr [15] &= 0xc0;
-                       v6src6->s6_addr [16]  = 0x00;
+                       uint16_t *csum_field = NULL;
+                       struct in6_addr masq_src;
+                       switch (v6nexthdr) {
+#ifdef CHECKSUM_SCTP_WOULD_BE_LIKE_FOR_OTHERS
+                       case IPPROTO_SCTP:
+                               csum_field = &v6sctpcksum;
+                               break;
+#endif
+                       case IPPROTO_TCP:
+                               csum_field = &v6tcpcksum;
+                               break;
+                       case IPPROTO_UDP:
+                               csum_field = &v6udpcksum;
+                               break;
+                       case IPPROTO_ICMPV6:
+                               csum_field = &v6icmpcksum;
+                               break;
+                       default:
+                               continue;
+                       }
+                       //
+                       // Construct v6src6 from v6dst6, ending in 14 zero bits
+                       memcpy (&masq_src, v6dst6, 16);
+                       masq_src.s6_addr16 [7] &= htons (0xc000);
+                       fprintf (stderr, "Masquerading cksum.old = 0x%04x, ", ntohs (*csum_field));
+                       masquerade_address (v6src6, &masq_src, csum_field);
+                       fprintf (stderr, "cksum.new = 0x%04x\n", ntohs (*csum_field));
                        break;
                }
        }
@@ -849,13 +924,14 @@ fflush (stdout);
 
 /* Option descriptive data structures */
 
-char *short_opt = "l:L:d:ht:u:s:m:";
+char *short_opt = "l:L:d:hit:u:s:m:";
 
 struct option long_opt [] = {
        { "v4listen", 1, NULL, 'l' },
        { "v6prefix", 1, NULL, 'L' },
        { "tundev", 1, NULL, 'd' },
        { "help", 0, NULL, 'h' },
+       { "icmp", 0, NULL, 'i' },
        { "tcp", 1, NULL, 't' },
        { "udp", 1, NULL, 'u' },
        { "sctp", 1, NULL, 's' },
@@ -923,7 +999,7 @@ int process_args (int argc, char *argv []) {
                        v6server = strdup (optarg);
                        *slash64 = '/';
                        v6prefix = optarg;
-                       if (!v6server || inet_pton (AF_INET6, v6server, &v6listen) <= 0) {
+                       if (!v6server || (inet_pton (AF_INET6, v6server, &v6listen) <= 0)) {
                                ok = 0;
                                fprintf (stderr, "%s: Failed to parse IPv6 prefix %s\n", program, optarg);
                                break;
@@ -953,6 +1029,7 @@ int process_args (int argc, char *argv []) {
                        // Masqueraded port (range) for SCTP, TCP, UDP
                        //TODO// Should we support ICMPv6 as well? [honeypots]
                        if (num_masqhost == 0) {
+                               //TODO// Reference v6listen instead of ::1
                                inet_pton (AF_INET6, "::1", masqhost [0]);
                                num_masqhost = 1;
                        }
index 5e18f28..db939a7 100644 (file)
@@ -15,7 +15,7 @@
 6bed4router \- server-side daemon for 6bed4 service
 .SH SYNOPSYS
 .B 6bed4router
-[\fB\-d\fR \fI/dev/tunX\fR] \fB\-l\fR \fIv4addr\fR \fB\-L\fR \fIv6prefix/64\fR [\fB\-m\fR/\fBs\fR/\fBt\fR/\fBu\fR \fI...\fR]
+[\fB\-d\fR \fI/dev/tunX\fR] \fB\-l\fR \fIv4addr\fR \fB\-L\fR \fIv6prefix/64\fR [\fB\-m\fR/\fB\-i\fR/\fBs\fR/\fBt\fR/\fBu\fR \fI...\fR]
 .PP
 .B 6bed4router
 [\fB\-h\fR]
@@ -128,11 +128,18 @@ authentication services to honeypots.
 \fB\-udp\fR \fIport\fR[\fB:\fIport\fR]
 Apply the masquerading port or port range for SCTP, TCP or UDP to the
 masquerading host set by the last preceding \fB\-\-masqhost\fR option,
-or use \fB::1\fR
+or use the tunnel's IPv6-side address
 if none was set yet.  Ports that have been previously bound will not make it,
 so it is possible to first relay a port with \fB\-t 22\fR to a service and
 then pass the rest to a honeypot with \fB\-t 1:65535\fR.
 .TP
+\fB\-i\fR
+Apply masquerading for ICMPv6 to the masquerading host set by the last
+preceding \fB\-\-masqhost\fR option, or use the tunnel's IPv6-side address
+if none was set yet.  The ICMPv6 messages with a special meaning to 6bed4
+are exempted (Router and Neighbor Solicitation and Advertisement, as well
+as Redirect) but other messages will be masqueraded.
+.TP
 \fB\-h\fR
 .TP
 \fB\-\-help\fR
diff --git a/HISTORY b/HISTORY
deleted file mode 100644 (file)
index 95fd512..0000000
--- a/HISTORY
+++ /dev/null
@@ -1,10 +0,0 @@
-1. Initially, this was "pubtsp", a public version of the Tunnel Setup Protocol.
-2. Then, the branch pubtsp-plus-autoconf was created
-3. The pubtsp-plus-autoconf branch was enhanced with autoconfiguration support
-DONE_UP_TO_HERE
-4. The branch autoconf was created
-5. Specifics for TSP were removed from the autoconf branch
-6. The master branch (with pubtsp-pnly support) was renamed to pubtsp
-7. The autoconf branch became the new master branch
-8. The original public-tsp branch was left as is
-9. The new branch structure is published as a new project named 6bed4
diff --git a/HISTORY.MD b/HISTORY.MD
new file mode 100644 (file)
index 0000000..95fd512
--- /dev/null
@@ -0,0 +1,10 @@
+1. Initially, this was "pubtsp", a public version of the Tunnel Setup Protocol.
+2. Then, the branch pubtsp-plus-autoconf was created
+3. The pubtsp-plus-autoconf branch was enhanced with autoconfiguration support
+DONE_UP_TO_HERE
+4. The branch autoconf was created
+5. Specifics for TSP were removed from the autoconf branch
+6. The master branch (with pubtsp-pnly support) was renamed to pubtsp
+7. The autoconf branch became the new master branch
+8. The original public-tsp branch was left as is
+9. The new branch structure is published as a new project named 6bed4
diff --git a/LICENSE b/LICENSE
deleted file mode 100644 (file)
index ee68100..0000000
--- a/LICENSE
+++ /dev/null
@@ -1,29 +0,0 @@
-Copyright (c) 2010, OpenFortress, as the creator of 0cpm technology
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-
-* Redistributions of source code must retain the above copyright notice,
-  this list of conditions and the following disclaimer.
-
-* Redistributions in binary form must reproduce the above copyright notice,
-  this list of conditions and the following disclaimer in the documentation
-  and/or other materials provided with the distribution.
-
-* Neither the names of OpenFortress, 0cpm or Rick van Rein, nor the
-  names of its contributors may be used to endorse or promote products
-  derived from this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
-LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGE.
diff --git a/LICENSE.MD b/LICENSE.MD
new file mode 100644 (file)
index 0000000..0f48b2d
--- /dev/null
@@ -0,0 +1,29 @@
+Copyright (c) 2010-2017, OpenFortress, as the creator of 0cpm technology
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright notice,
+  this list of conditions and the following disclaimer.
+
+* Redistributions in binary form must reproduce the above copyright notice,
+  this list of conditions and the following disclaimer in the documentation
+  and/or other materials provided with the distribution.
+
+* Neither the names of OpenFortress, 0cpm or Rick van Rein, nor the
+  names of its contributors may be used to endorse or promote products
+  derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
diff --git a/PREFIXES b/PREFIXES
deleted file mode 100644 (file)
index 88dcc86..0000000
--- a/PREFIXES
+++ /dev/null
@@ -1,131 +0,0 @@
-6BED4 PREFIXES AND PROMISES
-===========================
-
-> *6bed4 works over a globally registered prefix TBD1 and a standard
-> UDP port TBD2.  But there can be alternatives that route through the
-> same 6bed4 infrastructure.*
-
-
-Facilitation by 6bed4
----------------------
-
-The 6bed4 facilities are as follows:
-
-  * The prefix of the address may or may not be globally routable.  This is
-    impartial to 6bed4, but not necessarily for its users.  Locally routable
-    addresses can serve internal purposes (which is a vague term) including
-    (potentially large) peer-to-peer networks.  Global routability means that
-    anyone can route to the IPv6 endpoing addresses of 6bed4 peers, possibly
-    going through the 6bed4router.
-
-  * The prefix may also help to learn about the capability of an address for
-    opportunistic peering.  This capability must apply to both the sender and
-    recipient for a frame, because any NAT traversal must be kept open, thus
-    requiring a bidirectional UDP stream.  Note that no assumptions may be
-    made in general about remote nodes, other than the recognition of globally
-    defined prefix capabilities.
-
-  * The top-half of the address contains a fallback server, which can be used
-    when direct contact between peers is not possible.  Without this, it is
-    still possible to communicate with a configured fallback server, but peers
-    will only keep NAT open towards their own fallback server.  As a result,
-    the fallback server is a necessary hop between peers, and not finding a
-    peer's fallback server in their IPv6 address top half could lead to failure
-    to connect.  Because of this, communication can only be done locally.
-
-  * The lower half of the address contains a peer's public IPv4 address and
-    UDP port.  This information can be used for opportunistic peering, with
-    the option of the fallback server to deal with unroutable situations
-    between direct peers.  Port numbers 0 in the lower half can never be
-    used meaningfully in a 6bed4 address, so their handling is undefined.
-
-So, when the top-half has no room for the fallback server's IP address, then
-it can only be used on one 6bed4router (or on a cluster, but certainly not
-globally).
-
-
-Candidate Prefixes
-------------------
-
-The following prefixes spring to mind for use with 6bed4:
-
-  * TBD1::/32 is the perfect prefix for 6bed4.  It supports the top-half and
-    bottom-half structures, and is globally defined to do so.
-
-  * fc64:<netid>:<ipv4>::/64 may be used for 6bed4 as well.  The <netid> could
-    be varied to indicate different applications, so the prefix is as for 6bed4,
-    the fc64:<netid>::/32 prefix.  The fc00::/8 prefix indicates locally unique
-    addresses.  Since this also limits the scope, any connection between such
-    nets may be read as an indication that they are on the same local net and
-    the interpretation may therefore be assumed.  This is true for all fc00::/8
-    addresses, but we suggest leaving room for other uses by setting fc64::/8
-    specifically for the 6bed4 interpretation of the remainder of the address.
-    Note that fd00::/8 also covers unique local addresses, but it is followed
-    by random bits, so no policy can be applied without breaking standards
-    (and software).  Note that fc00::/8 is a local scoped name space, but it
-    is possible to connect 6bed4peers behind different fallback servers.  It
-    is simply a matter of distribution of addresses whether two peers will be
-    able to communicate.  We believe this scheme is perfect for peer-to-peer
-    operations, especially with the use of IPsec.
-
-  * Native IPv6 /48 or /64 prefixes may be used, but they will not facilitate
-    the top-half.  Sometimes the native use of native addresses may compete
-    with use in a 6bed4router; this is especially true when only one /64 is
-    available.  In this case, the undefined behaviour of port 0 in the lower
-    half may be used to bypass native traffic to a natively connected service.
-    Other than this, any 6bed4peer collecting these addresses can do anything;
-    native addresses can be reached, opportunistic connections to peers are
-    possible and even the native services using port 0 would work.  The one
-    thing that is impossible, as with fc64::/16, is that independent
-    6bed4router processes can serve the same prefix and have their 6bedpeer
-    clients reach each other; this is due to the lacking fallback server in
-    the top half.
-
-  * 2002:<ipv4>::/48 is based on the 6to4 prefix 2002::/16, but instead of
-    using the peer's address and relying on the ability to pass IPv6 directly
-    over IPv4, the 6bed4router can be used as an intermediate.  The place of
-    the <ipv4> address is different than after the /32 of normal 6bed4
-    addresses, but this is easily inferred from the prefix.  So, it is quite
-    possible to interpret <ipv4> as the fallback server.  What is not safe
-    to assume though, is that the underlying portion is a 6bed4 address.  To
-    allow for that, we define a "special SLA value" be64, as a hint that the
-    lower half may be interpreted for opportunistic peering.
-    TODO: This breaks with traditions... NOT FIT FOR A FORMAL SPEC
-
-
-
-Implementation
---------------
-
-The 6bed4router accepts multiple prefixes, simply by issuing more than one
-`-L` prefix.  Each of these will be provided to the 6bed4peers in Router
-Advertisements, after having completed them to a /114 prefix length.
-When a 6bed4peer receives such prefixes, it should configure them all,
-after setting its preference(s) of <lanip> in the last 14 bits.
-
-The sizes of the various prefixes vary.  The following things are added
-when possible:
-
-  * the fallback server IPv4 address, when at least 32 bits are available;
-  * the literal value be64, to fill up any remaining 16 bits
-
-This format works for prefixes of sizes 16, 32, 48 and 64:
-
-  * xxxx::/16 becomes top half xxxx:<ipv4>:be64::/64
-  * xxxx:yyyy::/32 becomes top half xxxx:yyyy:<ipv4>::/64
-  * xxxx:yyyy:zzzz::/48 becomes top half xxxx:yyyy:zzzz:be64::/64
-  * xxxx:yyyy:zzzz:wwww::/64 is unaltered
-
-Specifically for the indicated candidate prefixes:
-
-  * TBD1::/32 becomes top half TBD1:<ipv4>::/64
-  * fc64:<netid>::/32 becomes top half fc64:<netid>:<ipv4>::/64
-  * xxxx:yyyy:zzzz::/48 becomes top half xxxx:yyyy:zzzz:be64::/64
-  * xxxx:yyyy:zzzz:wwww::/64 is unaltered
-  * 2002::/16 becomes top half 2002:<ipv4>:be64::/64
-
-These do all support routing based on the bottom half.  Furthermore:
-
-  * The fallback server appearing as <ipv4> in the top half enables unrelated 6bed4router connectivity
-  * The rules for global routing determine whether the addresses can communicate with native IPv6 addresses
-
diff --git a/PREFIXES.MD b/PREFIXES.MD
new file mode 100644 (file)
index 0000000..88dcc86
--- /dev/null
@@ -0,0 +1,131 @@
+6BED4 PREFIXES AND PROMISES
+===========================
+
+> *6bed4 works over a globally registered prefix TBD1 and a standard
+> UDP port TBD2.  But there can be alternatives that route through the
+> same 6bed4 infrastructure.*
+
+
+Facilitation by 6bed4
+---------------------
+
+The 6bed4 facilities are as follows:
+
+  * The prefix of the address may or may not be globally routable.  This is
+    impartial to 6bed4, but not necessarily for its users.  Locally routable
+    addresses can serve internal purposes (which is a vague term) including
+    (potentially large) peer-to-peer networks.  Global routability means that
+    anyone can route to the IPv6 endpoing addresses of 6bed4 peers, possibly
+    going through the 6bed4router.
+
+  * The prefix may also help to learn about the capability of an address for
+    opportunistic peering.  This capability must apply to both the sender and
+    recipient for a frame, because any NAT traversal must be kept open, thus
+    requiring a bidirectional UDP stream.  Note that no assumptions may be
+    made in general about remote nodes, other than the recognition of globally
+    defined prefix capabilities.
+
+  * The top-half of the address contains a fallback server, which can be used
+    when direct contact between peers is not possible.  Without this, it is
+    still possible to communicate with a configured fallback server, but peers
+    will only keep NAT open towards their own fallback server.  As a result,
+    the fallback server is a necessary hop between peers, and not finding a
+    peer's fallback server in their IPv6 address top half could lead to failure
+    to connect.  Because of this, communication can only be done locally.
+
+  * The lower half of the address contains a peer's public IPv4 address and
+    UDP port.  This information can be used for opportunistic peering, with
+    the option of the fallback server to deal with unroutable situations
+    between direct peers.  Port numbers 0 in the lower half can never be
+    used meaningfully in a 6bed4 address, so their handling is undefined.
+
+So, when the top-half has no room for the fallback server's IP address, then
+it can only be used on one 6bed4router (or on a cluster, but certainly not
+globally).
+
+
+Candidate Prefixes
+------------------
+
+The following prefixes spring to mind for use with 6bed4:
+
+  * TBD1::/32 is the perfect prefix for 6bed4.  It supports the top-half and
+    bottom-half structures, and is globally defined to do so.
+
+  * fc64:<netid>:<ipv4>::/64 may be used for 6bed4 as well.  The <netid> could
+    be varied to indicate different applications, so the prefix is as for 6bed4,
+    the fc64:<netid>::/32 prefix.  The fc00::/8 prefix indicates locally unique
+    addresses.  Since this also limits the scope, any connection between such
+    nets may be read as an indication that they are on the same local net and
+    the interpretation may therefore be assumed.  This is true for all fc00::/8
+    addresses, but we suggest leaving room for other uses by setting fc64::/8
+    specifically for the 6bed4 interpretation of the remainder of the address.
+    Note that fd00::/8 also covers unique local addresses, but it is followed
+    by random bits, so no policy can be applied without breaking standards
+    (and software).  Note that fc00::/8 is a local scoped name space, but it
+    is possible to connect 6bed4peers behind different fallback servers.  It
+    is simply a matter of distribution of addresses whether two peers will be
+    able to communicate.  We believe this scheme is perfect for peer-to-peer
+    operations, especially with the use of IPsec.
+
+  * Native IPv6 /48 or /64 prefixes may be used, but they will not facilitate
+    the top-half.  Sometimes the native use of native addresses may compete
+    with use in a 6bed4router; this is especially true when only one /64 is
+    available.  In this case, the undefined behaviour of port 0 in the lower
+    half may be used to bypass native traffic to a natively connected service.
+    Other than this, any 6bed4peer collecting these addresses can do anything;
+    native addresses can be reached, opportunistic connections to peers are
+    possible and even the native services using port 0 would work.  The one
+    thing that is impossible, as with fc64::/16, is that independent
+    6bed4router processes can serve the same prefix and have their 6bedpeer
+    clients reach each other; this is due to the lacking fallback server in
+    the top half.
+
+  * 2002:<ipv4>::/48 is based on the 6to4 prefix 2002::/16, but instead of
+    using the peer's address and relying on the ability to pass IPv6 directly
+    over IPv4, the 6bed4router can be used as an intermediate.  The place of
+    the <ipv4> address is different than after the /32 of normal 6bed4
+    addresses, but this is easily inferred from the prefix.  So, it is quite
+    possible to interpret <ipv4> as the fallback server.  What is not safe
+    to assume though, is that the underlying portion is a 6bed4 address.  To
+    allow for that, we define a "special SLA value" be64, as a hint that the
+    lower half may be interpreted for opportunistic peering.
+    TODO: This breaks with traditions... NOT FIT FOR A FORMAL SPEC
+
+
+
+Implementation
+--------------
+
+The 6bed4router accepts multiple prefixes, simply by issuing more than one
+`-L` prefix.  Each of these will be provided to the 6bed4peers in Router
+Advertisements, after having completed them to a /114 prefix length.
+When a 6bed4peer receives such prefixes, it should configure them all,
+after setting its preference(s) of <lanip> in the last 14 bits.
+
+The sizes of the various prefixes vary.  The following things are added
+when possible:
+
+  * the fallback server IPv4 address, when at least 32 bits are available;
+  * the literal value be64, to fill up any remaining 16 bits
+
+This format works for prefixes of sizes 16, 32, 48 and 64:
+
+  * xxxx::/16 becomes top half xxxx:<ipv4>:be64::/64
+  * xxxx:yyyy::/32 becomes top half xxxx:yyyy:<ipv4>::/64
+  * xxxx:yyyy:zzzz::/48 becomes top half xxxx:yyyy:zzzz:be64::/64
+  * xxxx:yyyy:zzzz:wwww::/64 is unaltered
+
+Specifically for the indicated candidate prefixes:
+
+  * TBD1::/32 becomes top half TBD1:<ipv4>::/64
+  * fc64:<netid>::/32 becomes top half fc64:<netid>:<ipv4>::/64
+  * xxxx:yyyy:zzzz::/48 becomes top half xxxx:yyyy:zzzz:be64::/64
+  * xxxx:yyyy:zzzz:wwww::/64 is unaltered
+  * 2002::/16 becomes top half 2002:<ipv4>:be64::/64
+
+These do all support routing based on the bottom half.  Furthermore:
+
+  * The fallback server appearing as <ipv4> in the top half enables unrelated 6bed4router connectivity
+  * The rules for global routing determine whether the addresses can communicate with native IPv6 addresses
+
diff --git a/README.MD b/README.MD
new file mode 100644 (file)
index 0000000..d809345
--- /dev/null
+++ b/README.MD
@@ -0,0 +1,51 @@
+# IPv6 Everywhere with 6bed4
+
+> *The 6bed4 tunnel and peer-to-peer toolkit enables IPv6 everywhere.
+> It connects programs and hosts over UDP/IPv4.  It tries hard to setup
+> connections as direct peer-to-peer connections, but may fall back to
+> a server failing this.*
+
+The intention of 6bed4 is to assure protocol designers of the availability
+of IPv6 on all nodes that run their protocol.  For instance, a designer
+of a peer-to-peer search application should be able to connect to peers
+over IPv6, thereby bypassing many problems resulting from NAT.  One might
+say that IPv6 is used to encapsulate all problems with NAT traversal.
+
+
+## Status
+
+This code is **WORK IN PROGRESS**, while we are finalising our 6bed4
+Internet Draft.
+
+
+## Programs
+
+The `6bed4peer` program runs an interface over which IPv6 routing is
+available, and for which up to 16383 local extensions can be allocated
+and made available over a tunnel interface.
+
+The `6bed4node` program is an extended `6bed4peer` in that it does not
+provide a network interface but a network service that offers IPv6
+addresses over a standard network interface, though this requires a few
+extra programs like `radvd` and possibly a DHCPv6 server.  In this case,
+programs can use native IPv6 network stacks.  A typical use case for the
+`6bed4node` is on a network router, such as one of the OpenWRT routers.
+
+The `6bed4router` program runs as a fallback router.  Even when it could
+be considered a server program, it is faithful to the idea of peer-to-peer
+communication in the sense that multiple of these routers can collaborate
+to connect `6bed4peer` programs.  A user can choose which router to use,
+although this
+[depends on the prefix](PREFIXES.MD)
+used.  We have arranged for public 6bed4 service at 145.136.0.1 port 25790.
+
+**TODO:** 6bed4node remains to be done.
+
+**TODO:** A socket-replacing library would be useful.
+
+For use with Java, we have **TODO:** Android6bed4 and Socket6bed4.
+
+
+## Usage
+
+TODO