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/BSDMessageTypeWrapper.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/Message.h"
23 #include "wire/Error.h"
24
25 /**
26 * OSX and BSD is expect you to send the platform dependent address family type
27 * rather than the ethertype, this InterfaceWrapper converts AF_INET and AF_INET6 to the
28 * corrisponding ethertypes and back.
29 */
30
31 struct BSDMessageTypeWrapper_pvt
32 {
33 struct BSDMessageTypeWrapper pub;
34 uint16_t afInet_be;
35 uint16_t afInet6_be;
36 struct Log* logger;
37 Identity
38 };
39
receiveMessage(struct Message * msg,struct Iface * wireSide)40 static Iface_DEFUN receiveMessage(struct Message* msg, struct Iface* wireSide)
41 {
42 struct BSDMessageTypeWrapper_pvt* ctx =
43 Identity_containerOf(wireSide, struct BSDMessageTypeWrapper_pvt, pub.wireSide);
44
45 if (msg->length < 4) { return NULL; }
46
47 uint16_t afType_be = ((uint16_t*) msg->bytes)[1];
48 uint16_t ethertype = 0;
49 if (afType_be == ctx->afInet_be) {
50 ethertype = Ethernet_TYPE_IP4;
51 } else if (afType_be == ctx->afInet6_be) {
52 ethertype = Ethernet_TYPE_IP6;
53 } else {
54 Log_debug(ctx->logger, "Message of unhandled aftype [0x%04x]",
55 Endian_bigEndianToHost16(afType_be));
56 return NULL;
57 }
58 ((uint16_t*) msg->bytes)[0] = 0;
59 ((uint16_t*) msg->bytes)[1] = ethertype;
60
61 return Iface_next(&ctx->pub.inside, msg);
62 }
63
sendMessage(struct Message * msg,struct Iface * inside)64 static Iface_DEFUN sendMessage(struct Message* msg, struct Iface* inside)
65 {
66 struct BSDMessageTypeWrapper_pvt* ctx =
67 Identity_containerOf(inside, struct BSDMessageTypeWrapper_pvt, pub.inside);
68
69 Assert_true(msg->length >= 4);
70
71 uint16_t ethertype = ((uint16_t*) msg->bytes)[1];
72 uint16_t afType_be = 0;
73 if (ethertype == Ethernet_TYPE_IP6) {
74 afType_be = ctx->afInet6_be;
75 } else if (ethertype == Ethernet_TYPE_IP4) {
76 afType_be = ctx->afInet_be;
77 } else {
78 Assert_true(!"Unsupported ethertype");
79 }
80 ((uint16_t*) msg->bytes)[0] = 0;
81 ((uint16_t*) msg->bytes)[1] = afType_be;
82
83 return Iface_next(&ctx->pub.wireSide, msg);
84 }
85
BSDMessageTypeWrapper_new(struct Allocator * alloc,struct Log * log)86 struct BSDMessageTypeWrapper* BSDMessageTypeWrapper_new(struct Allocator* alloc, struct Log* log)
87 {
88 struct BSDMessageTypeWrapper_pvt* context =
89 Allocator_calloc(alloc, sizeof(struct BSDMessageTypeWrapper_pvt), 1);
90 Identity_set(context);
91 context->pub.wireSide.send = receiveMessage;
92 context->pub.inside.send = sendMessage;
93 context->afInet6_be = Endian_hostToBigEndian16(Sockaddr_AF_INET6);
94 context->afInet_be = Endian_hostToBigEndian16(Sockaddr_AF_INET);
95 context->logger = log;
96
97 return &context->pub;
98 }
99