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 }