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