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