1 /* vim: set expandtab ts=4 sw=4: */
2 /*
3  * You may redistribute this program and/or modify it under the terms of
4  * the GNU General Public License as published by the Free Software Foundation,
5  * either version 3 of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
14  */
15 #include "interface/Iface.h"
16 #include "memory/Allocator.h"
17 #include "util/Identity.h"
18 #include "net/TUNAdapter.h"
19 #include "wire/DataHeader.h"
20 #include "wire/RouteHeader.h"
21 #include "wire/Headers.h"
22 #include "interface/tuntap/TUNMessageType.h"
23 #include "wire/Ethernet.h"
24 #include "crypto/AddressCalc.h"
25 #include "util/Defined.h"
26 #include "util/AddrTools.h"
27 
28 struct TUNAdapter_pvt
29 {
30     struct TUNAdapter pub;
31     struct Log* log;
32     uint8_t myIp6[16];
33     Identity
34 };
35 
incomingFromTunIf(struct Message * msg,struct Iface * tunIf)36 static Iface_DEFUN incomingFromTunIf(struct Message* msg, struct Iface* tunIf)
37 {
38     struct TUNAdapter_pvt* ud = Identity_containerOf(tunIf, struct TUNAdapter_pvt, pub.tunIf);
39 
40     uint16_t ethertype = Er_assert(TUNMessageType_pop(msg));
41 
42     int version = Headers_getIpVersion(msg->bytes);
43     if ((ethertype == Ethernet_TYPE_IP4 && version != 4)
44         || (ethertype == Ethernet_TYPE_IP6 && version != 6))
45     {
46         Log_debug(ud->log, "DROP packet because ip version [%d] "
47                   "doesn't match ethertype [%u].", version, Endian_bigEndianToHost16(ethertype));
48         return NULL;
49     }
50 
51     if (ethertype == Ethernet_TYPE_IP4) {
52         return Iface_next(&ud->pub.ipTunnelIf, msg);
53     }
54     if (ethertype != Ethernet_TYPE_IP6) {
55         Log_debug(ud->log, "DROP packet unknown ethertype [%u]",
56                   Endian_bigEndianToHost16(ethertype));
57         return NULL;
58     }
59 
60     if (msg->length < Headers_IP6Header_SIZE) {
61         Log_debug(ud->log, "DROP runt");
62         return NULL;
63     }
64 
65     struct Headers_IP6Header* header = (struct Headers_IP6Header*) msg->bytes;
66     if (!AddressCalc_validAddress(header->destinationAddr)) {
67         return Iface_next(&ud->pub.ipTunnelIf, msg);
68     }
69     if (Bits_memcmp(header->sourceAddr, ud->myIp6, 16)) {
70         if (Defined(Log_DEBUG)) {
71             uint8_t expectedSource[40];
72             AddrTools_printIp(expectedSource, ud->myIp6);
73             uint8_t packetSource[40];
74             AddrTools_printIp(packetSource, header->sourceAddr);
75             Log_debug(ud->log,
76                       "DROP packet from [%s] because all messages must have source address [%s]",
77                       packetSource, expectedSource);
78         }
79         return NULL;
80     }
81     if (!Bits_memcmp(header->destinationAddr, ud->myIp6, 16)) {
82         // I'm Gonna Sit Right Down and Write Myself a Letter
83         Er_assert(TUNMessageType_push(msg, ethertype));
84         return Iface_next(tunIf, msg);
85     }
86 
87     // first move the dest addr to the right place.
88     Bits_memmove(header->destinationAddr - DataHeader_SIZE, header->destinationAddr, 16);
89 
90     Er_assert(Message_eshift(msg, DataHeader_SIZE + RouteHeader_SIZE - Headers_IP6Header_SIZE));
91     struct RouteHeader* rh = (struct RouteHeader*) msg->bytes;
92 
93     struct DataHeader* dh = (struct DataHeader*) &rh[1];
94     Bits_memset(dh, 0, DataHeader_SIZE);
95     DataHeader_setContentType(dh, header->nextHeader);
96     DataHeader_setVersion(dh, DataHeader_CURRENT_VERSION);
97 
98     // Other than the ipv6 addr at the end, everything is zeros right down the line.
99     Bits_memset(rh, 0, RouteHeader_SIZE - 16);
100 
101     return Iface_next(&ud->pub.upperDistributorIf, msg);
102 }
103 
sendToTunIf(struct Message * msg,struct TUNAdapter_pvt * ud)104 static Iface_DEFUN sendToTunIf(struct Message* msg, struct TUNAdapter_pvt* ud)
105 {
106     if (!ud->pub.tunIf.connectedIf) {
107         Log_debug(ud->log, "DROP message for tun because no device is defined");
108         return NULL;
109     }
110     return Iface_next(&ud->pub.tunIf, msg);
111 }
112 
incomingFromIpTunnelIf(struct Message * msg,struct Iface * ipTunnelIf)113 static Iface_DEFUN incomingFromIpTunnelIf(struct Message* msg, struct Iface* ipTunnelIf)
114 {
115     struct TUNAdapter_pvt* ud =
116         Identity_containerOf(ipTunnelIf, struct TUNAdapter_pvt, pub.ipTunnelIf);
117     return sendToTunIf(msg, ud);
118 }
119 
incomingFromUpperDistributorIf(struct Message * msg,struct Iface * upperDistributorIf)120 static Iface_DEFUN incomingFromUpperDistributorIf(struct Message* msg,
121                                                   struct Iface* upperDistributorIf)
122 {
123     struct TUNAdapter_pvt* ud =
124         Identity_containerOf(upperDistributorIf, struct TUNAdapter_pvt, pub.upperDistributorIf);
125     Assert_true(msg->length >= RouteHeader_SIZE + DataHeader_SIZE);
126     struct RouteHeader* hdr = (struct RouteHeader*) msg->bytes;
127     struct DataHeader* dh = (struct DataHeader*) &hdr[1];
128     enum ContentType type = DataHeader_getContentType(dh);
129     Assert_true(type <= ContentType_IP6_MAX);
130 
131     // Shift ip address into destination slot.
132     Bits_memmove(hdr->ip6 + DataHeader_SIZE - 16, hdr->ip6, 16);
133     // put my address as destination.
134     Bits_memcpy(&hdr->ip6[DataHeader_SIZE], ud->myIp6, 16);
135 
136     Er_assert(Message_eshift(msg, Headers_IP6Header_SIZE - DataHeader_SIZE - RouteHeader_SIZE));
137     struct Headers_IP6Header* ip6 = (struct Headers_IP6Header*) msg->bytes;
138     Bits_memset(ip6, 0, Headers_IP6Header_SIZE - 32);
139     Headers_setIpVersion(ip6);
140     ip6->payloadLength_be = Endian_bigEndianToHost16(msg->length - Headers_IP6Header_SIZE);
141     ip6->nextHeader = type;
142     ip6->hopLimit = 42;
143     Er_assert(TUNMessageType_push(msg, Ethernet_TYPE_IP6));
144     return sendToTunIf(msg, ud);
145 }
146 
TUNAdapter_new(struct Allocator * allocator,struct Log * log,uint8_t myIp6[16])147 struct TUNAdapter* TUNAdapter_new(struct Allocator* allocator, struct Log* log, uint8_t myIp6[16])
148 {
149     struct Allocator* alloc = Allocator_child(allocator);
150     struct TUNAdapter_pvt* out = Allocator_calloc(alloc, sizeof(struct TUNAdapter_pvt), 1);
151     out->pub.tunIf.send = incomingFromTunIf;
152     out->pub.ipTunnelIf.send = incomingFromIpTunnelIf;
153     out->pub.upperDistributorIf.send = incomingFromUpperDistributorIf;
154     out->log = log;
155     Identity_set(out);
156     Bits_memcpy(out->myIp6, myIp6, 16);
157     return &out->pub;
158 }
159