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 "interface/tuntap/SocketWrapper.h"
17 #include "util/platform/Sockaddr.h"
18 #include "memory/Allocator.h"
19 #include "util/Assert.h"
20 #include "util/Identity.h"
21 #include "wire/Ethernet.h"
22 #include "wire/Headers.h"
23 #include "wire/Message.h"
24 #include "wire/Error.h"
25
26 struct SocketWrapper_pvt
27 {
28 struct SocketWrapper pub;
29 struct Log* logger;
30 Identity
31 };
32
incomingFromSocket(struct Message * msg,struct Iface * externalIf)33 static Iface_DEFUN incomingFromSocket(struct Message* msg, struct Iface* externalIf)
34 {
35 struct SocketWrapper_pvt* ctx =
36 Identity_containerOf(externalIf, struct SocketWrapper_pvt, pub.externalIf);
37
38 if (!ctx->pub.internalIf.connectedIf) {
39 Log_debug(ctx->logger, "DROP message for socket not inited");
40 return NULL;
41 }
42
43 // get ess packet type
44 uint8_t type = Er_assert(Message_epop8h(msg));
45 Log_debug(ctx->logger, "Packet type [%d]", type);
46
47 if (type == SocketWrapper_TYPE_TUN_PACKET) {
48 // skip tun packet length
49 Er_assert(Message_epop32be(msg));
50 return Iface_next(&ctx->pub.internalIf, msg);
51 }
52
53 // skip all other types
54 return NULL;
55 }
56
incomingFromUs(struct Message * msg,struct Iface * internalIf)57 static Iface_DEFUN incomingFromUs(struct Message* msg, struct Iface* internalIf)
58 {
59 struct SocketWrapper_pvt* ctx =
60 Identity_containerOf(internalIf, struct SocketWrapper_pvt, pub.internalIf);
61
62 if (!ctx->pub.externalIf.connectedIf) {
63 Log_debug(ctx->logger, "DROP message for socket not inited");
64 return NULL;
65 }
66
67 // send payload length
68 Er_assert(Message_epush32be(msg, msg->length));
69 // mark this as a normal tun packet
70 Er_assert(Message_epush8(msg, SocketWrapper_TYPE_TUN_PACKET));
71
72 return Iface_next(&ctx->pub.externalIf, msg);
73 }
74
SocketWrapper_new(struct Allocator * alloc,struct Log * log)75 struct SocketWrapper* SocketWrapper_new(struct Allocator* alloc, struct Log* log)
76 {
77 struct SocketWrapper_pvt* context =
78 Allocator_calloc(alloc, sizeof(struct SocketWrapper_pvt), 1);
79 Identity_set(context);
80 context->pub.externalIf.send = incomingFromSocket;
81 context->pub.internalIf.send = incomingFromUs;
82 context->logger = log;
83
84 return &context->pub;
85 }
86
Er_DEFUN(void SocketWrapper_addAddress (struct Iface * rawSocketIf,uint8_t * ipv6Addr,struct Log * logger,struct Allocator * alloc))87 Er_DEFUN(void SocketWrapper_addAddress(struct Iface* rawSocketIf,
88 uint8_t* ipv6Addr,
89 struct Log* logger,
90 struct Allocator* alloc))
91 {
92 size_t len = 16 /* IPv6 Address length */ + 1 /* Type prefix length */;
93 struct Message* out = Message_new(0, len, alloc);
94 Er(Message_epush(out, ipv6Addr, 16));
95 Er(Message_epush8(out, SocketWrapper_TYPE_CONF_ADD_IPV6_ADDRESS));
96
97 Iface_send(rawSocketIf, out);
98 Er_ret();
99 }
100
Er_DEFUN(void SocketWrapper_setMTU (struct Iface * rawSocketIf,uint32_t mtu,struct Log * logger,struct Allocator * alloc))101 Er_DEFUN(void SocketWrapper_setMTU(struct Iface* rawSocketIf,
102 uint32_t mtu,
103 struct Log* logger,
104 struct Allocator* alloc))
105 {
106 size_t len = 4 /* MTU var size */ + 1 /* Type prefix length */;
107 struct Message* out = Message_new(0, len, alloc);
108 Er(Message_epush32be(out, mtu));
109 Er(Message_epush8(out, SocketWrapper_TYPE_CONF_SET_MTU));
110
111 Iface_send(rawSocketIf, out);
112 Er_ret();
113 }