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 "util/events/libuv/UvWrapper.h"
16 #include "benc/StringList.h"
17 #include "interface/UDPInterface.h"
18 #include "wire/Message.h"
19 #include "util/events/UDPAddrIface.h"
20 #include "util/GlobalConfig.h"
21 
22 #define ArrayList_TYPE struct Sockaddr
23 #define ArrayList_NAME Sockaddr
24 #include "util/ArrayList.h"
25 
26 struct UDPInterface_pvt
27 {
28     struct UDPInterface pub;
29     struct Log* log;
30     struct Allocator* allocator;
31 
32     struct Allocator* bcastAddrAlloc;
33     struct ArrayList_Sockaddr* bcastAddrs;
34 
35     struct Allocator* bcastIfaceAlloc;
36     struct StringList* bcastIfaces;
37 
38     struct UDPAddrIface* commIf;
39     struct UDPAddrIface* bcastIf;
40 
41     struct GlobalConfig* globalConf;
42 
43     struct Iface commSock;
44     struct Iface bcastSock;
45     uint16_t beaconPort_be;
46     uint16_t commPort_be;
47 
48     Identity
49 };
50 
mkBcastAddr(uint16_t beaconPort_be,uv_interface_address_t * iface,struct Allocator * alloc)51 static struct Sockaddr* mkBcastAddr(
52     uint16_t beaconPort_be,
53     uv_interface_address_t* iface,
54     struct Allocator* alloc)
55 {
56     struct sockaddr_in bcast4 = {
57         .sin_family = AF_INET,
58         .sin_port = beaconPort_be,
59         .sin_addr = {
60             .s_addr =
61                 (
62                     iface->address.address4.sin_addr.s_addr &
63                     iface->netmask.netmask4.sin_addr.s_addr
64                 ) | ~iface->netmask.netmask4.sin_addr.s_addr
65         }
66     };
67     return Sockaddr_fromNative(&bcast4, sizeof(struct sockaddr_in), alloc);
68 }
69 
updateBcastAddrs(struct UDPInterface_pvt * ctx)70 static int updateBcastAddrs(struct UDPInterface_pvt* ctx)
71 {
72     bool all = false;
73     for (int i = 0; ctx->bcastIfaces && i < ctx->bcastIfaces->length; i++) {
74         String* iface = StringList_get(ctx->bcastIfaces, i);
75         if (String_equals(iface, String_CONST("all"))) { all = true; }
76     }
77     uv_interface_address_t* interfaces;
78     int count;
79     int res = uv_interface_addresses(&interfaces, &count);
80     if (res) {
81         Log_info(ctx->log, "uv_interface_addresses failed [%s]", uv_strerror(-res));
82         return -1;
83     }
84 
85     if (ctx->bcastAddrAlloc) { Allocator_free(ctx->bcastAddrAlloc); }
86     struct Allocator* alloc = ctx->bcastAddrAlloc = Allocator_child(ctx->allocator);
87     ctx->bcastAddrs = ArrayList_Sockaddr_new(alloc);
88 
89     String* tunDev = GlobalConfig_getTunName(ctx->globalConf);
90 
91     for (int i = 0; i < count; i++) {
92         if (interfaces[i].is_internal) { continue; }
93         if (interfaces[i].address.address4.sin_family != AF_INET) { continue; }
94         if (tunDev && !CString_strncmp(interfaces[i].name, tunDev->bytes, tunDev->len)) {
95             continue;
96         }
97         struct Sockaddr* addr = mkBcastAddr(ctx->beaconPort_be, &interfaces[i], alloc);
98         if (!all) {
99             String* addrStr = String_new(Sockaddr_print(addr, alloc), alloc);
100             bool found = false;
101             for (int j = 0; ctx->bcastIfaces && j < ctx->bcastIfaces->length; j++) {
102                 String* iface = StringList_get(ctx->bcastIfaces, j);
103                 if (String_equals(iface, addrStr)) { found = true; }
104                 if (String_equals(iface, String_CONST(interfaces[i].name))) { found = true; }
105             }
106             if (!found) { continue; }
107         }
108         ArrayList_Sockaddr_add(ctx->bcastAddrs, addr);
109     }
110     uv_free_interface_addresses(interfaces, count);
111     return 0;
112 }
113 
sendPacket(struct Message * m,struct Iface * iface)114 static Iface_DEFUN sendPacket(struct Message* m, struct Iface* iface)
115 {
116     struct UDPInterface_pvt* ctx =
117         Identity_containerOf(iface, struct UDPInterface_pvt, pub.generic.iface);
118 
119     Assert_true(m->length > Sockaddr_OVERHEAD);
120     struct Sockaddr* sa = (struct Sockaddr*) m->bytes;
121     Assert_true(m->length > sa->addrLen);
122 
123     // Regular traffic
124     if (!(sa->flags & Sockaddr_flags_BCAST)) { return Iface_next(&ctx->commSock, m); }
125 
126     if (updateBcastAddrs(ctx)) {
127         return NULL;
128     }
129 
130     // bcast
131     struct UDPInterface_BroadcastHeader hdr = {
132         .fffffffc_be = Endian_hostToBigEndian32(0xfffffffc),
133         .version = UDPInterface_CURRENT_VERSION,
134         .zero = 0,
135         .commPort_be = ctx->commPort_be
136     };
137     Er_assert(Message_eshift(m, -sa->addrLen));
138     Er_assert(Message_epush(m, &hdr, UDPInterface_BroadcastHeader_SIZE));
139 
140     for (int i = 0; i < ctx->bcastAddrs->length; i++) {
141         struct Allocator* tmpAlloc = Allocator_child(ctx->allocator);
142         struct Message* mm = Message_clone(m, tmpAlloc);
143         struct Sockaddr* addr = ArrayList_Sockaddr_get(ctx->bcastAddrs, i);
144         Er_assert(Message_epush(mm, addr, addr->addrLen));
145         Iface_send(&ctx->bcastSock, mm);
146         Allocator_free(tmpAlloc);
147     }
148 
149     return NULL;
150 }
151 
fromCommSock(struct Message * m,struct Iface * iface)152 static Iface_DEFUN fromCommSock(struct Message* m, struct Iface* iface)
153 {
154     struct UDPInterface_pvt* ctx =
155         Identity_containerOf(iface, struct UDPInterface_pvt, commSock);
156     return Iface_next(&ctx->pub.generic.iface, m);
157 }
158 
fromBcastSock(struct Message * m,struct Iface * iface)159 static Iface_DEFUN fromBcastSock(struct Message* m, struct Iface* iface)
160 {
161     struct UDPInterface_pvt* ctx =
162         Identity_containerOf(iface, struct UDPInterface_pvt, bcastSock);
163 
164     if (m->length < UDPInterface_BroadcastHeader_SIZE + Sockaddr_OVERHEAD) {
165         Log_debug(ctx->log, "DROP runt bcast");
166         return NULL;
167     }
168 
169     struct Sockaddr_storage ss;
170     Er_assert(Message_epop(m, &ss, Sockaddr_OVERHEAD));
171     if (m->length < UDPInterface_BroadcastHeader_SIZE + ss.addr.addrLen - Sockaddr_OVERHEAD) {
172         Log_debug(ctx->log, "DROP runt bcast");
173         return NULL;
174     }
175     Er_assert(Message_epop(m, &ss.nativeAddr, ss.addr.addrLen - Sockaddr_OVERHEAD));
176 
177     struct UDPInterface_BroadcastHeader hdr;
178     Er_assert(Message_epop(m, &hdr, UDPInterface_BroadcastHeader_SIZE));
179 
180     if (hdr.fffffffc_be != Endian_hostToBigEndian32(0xfffffffc)) {
181         Log_debug(ctx->log, "DROP bcast bad magic, expected 0xfffffffc got [%08x]",
182             Endian_bigEndianToHost32(hdr.fffffffc_be));
183         return NULL;
184     }
185 
186     if (hdr.version != UDPInterface_CURRENT_VERSION) {
187         Log_debug(ctx->log, "DROP bcast bad version [%u]", hdr.version);
188         return NULL;
189     }
190 
191     if (hdr.zero) {
192         Log_debug(ctx->log, "DROP bcast malformed (zero not zero)");
193         return NULL;
194     }
195 
196     uint16_t commPort = Endian_bigEndianToHost16(hdr.commPort_be);
197 
198     // Fake that it came from the communication port
199     Sockaddr_setPort(&ss.addr, commPort);
200     ss.addr.flags |= Sockaddr_flags_BCAST;
201 
202     Er_assert(Message_epush(m, &ss.addr, ss.addr.addrLen));
203 
204     return Iface_next(&ctx->pub.generic.iface, m);
205 }
206 
Er_DEFUN(struct UDPInterface * UDPInterface_new (struct EventBase * eventBase,struct Sockaddr * bindAddr,uint16_t beaconPort,struct Allocator * alloc,struct Log * logger,struct GlobalConfig * globalConf))207 Er_DEFUN(struct UDPInterface* UDPInterface_new(struct EventBase* eventBase,
208                                       struct Sockaddr* bindAddr,
209                                       uint16_t beaconPort,
210                                       struct Allocator* alloc,
211                                       struct Log* logger,
212                                       struct GlobalConfig* globalConf))
213 {
214     if (beaconPort && Sockaddr_getFamily(bindAddr) != Sockaddr_AF_INET) {
215         Er_raise(alloc, "UDP broadcast only supported by ipv4.");
216     }
217     if (beaconPort && Sockaddr_getPort(bindAddr) == beaconPort) {
218         Er_raise(alloc, "UDP broadcast port must be different from communication port.");
219     }
220 
221     struct UDPAddrIface* uai = Er(UDPAddrIface_new(eventBase, bindAddr, alloc, logger));
222 
223     uint16_t commPort = Sockaddr_getPort(uai->generic.addr);
224 
225     struct UDPInterface_pvt* context = Allocator_calloc(alloc, sizeof(struct UDPInterface_pvt), 1);
226     Identity_set(context);
227     context->log = logger;
228     context->allocator = alloc;
229     context->beaconPort_be = Endian_hostToBigEndian16(beaconPort);
230     context->commPort_be = Endian_hostToBigEndian16(commPort);
231     context->pub.generic.addr = uai->generic.addr;
232     context->pub.generic.alloc = alloc;
233     context->pub.generic.iface.send = sendPacket;
234     context->commSock.send = fromCommSock;
235     context->bcastSock.send = fromBcastSock;
236     context->commIf = uai;
237     context->globalConf = globalConf;
238     Iface_plumb(&uai->generic.iface, &context->commSock);
239 
240     if (beaconPort) {
241         struct Sockaddr* bcastAddr = Sockaddr_clone(bindAddr, alloc);
242         Sockaddr_setPort(bcastAddr, beaconPort);
243         struct UDPAddrIface* bcast =
244             Er(UDPAddrIface_new(eventBase, bcastAddr, alloc, logger));
245         UDPAddrIface_setBroadcast(bcast, 1);
246         Iface_plumb(&bcast->generic.iface, &context->bcastSock);
247         context->bcastIf = bcast;
248     }
249 
250     Er_ret(&context->pub);
251 }
252 
Er_DEFUN(List * UDPInterface_listDevices (struct Allocator * alloc))253 Er_DEFUN(List* UDPInterface_listDevices(struct Allocator* alloc))
254 {
255     List* out = List_new(alloc);
256     uv_interface_address_t* interfaces;
257     int count;
258     int res = uv_interface_addresses(&interfaces, &count);
259     if (res) { Er_raise(alloc, "uv_interface_addresses failed [%s]", uv_strerror(-res)); }
260 
261     for (int i = 0; i < count; i++) {
262         if (interfaces[i].is_internal) { continue; }
263         if (interfaces[i].address.address4.sin_family != AF_INET) { continue; }
264         List_addString(out, String_new(interfaces[i].name, alloc), alloc);
265     }
266     uv_free_interface_addresses(interfaces, count);
267     Er_ret(out);
268 }
269 
UDPInterface_setBroadcastDevices(struct UDPInterface * udpif,List * devices)270 void UDPInterface_setBroadcastDevices(struct UDPInterface* udpif, List* devices)
271 {
272     struct UDPInterface_pvt* ctx = Identity_check((struct UDPInterface_pvt*) udpif);
273     if (ctx->bcastIfaceAlloc) { Allocator_free(ctx->bcastIfaceAlloc); }
274     struct Allocator* alloc = ctx->bcastIfaceAlloc = Allocator_child(ctx->allocator);
275     struct StringList* bcastIfaces = ctx->bcastIfaces = StringList_new(alloc);
276     int len = List_size(devices);
277     for (uint32_t i = 0; i < (unsigned) len; i++) {
278         String* dev = List_getString(devices, i);
279         StringList_add(bcastIfaces, String_clone(dev, alloc));
280     }
281 }
282 
UDPInterface_getBroadcastDevices(struct UDPInterface * udpif,struct Allocator * alloc)283 List* UDPInterface_getBroadcastDevices(struct UDPInterface* udpif, struct Allocator* alloc)
284 {
285     struct UDPInterface_pvt* ctx = Identity_check((struct UDPInterface_pvt*) udpif);
286     List* out = List_new(alloc);
287     for (int i = 0; ctx->bcastIfaces && i < ctx->bcastIfaces->length; i++) {
288         List_addString(out, StringList_get(ctx->bcastIfaces, i), alloc);
289     }
290     return out;
291 }
292 
UDPInterface_getBroadcastAddrs(struct UDPInterface * udpif,struct Allocator * alloc)293 List* UDPInterface_getBroadcastAddrs(struct UDPInterface* udpif, struct Allocator* alloc)
294 {
295     struct UDPInterface_pvt* ctx = Identity_check((struct UDPInterface_pvt*) udpif);
296     List* out = List_new(alloc);
297     if (updateBcastAddrs(ctx)) {
298         // TODO(cjd): There should be some way to return the fact that there was an error
299         return out;
300     }
301     for (int i = 0; i < ctx->bcastAddrs->length; i++) {
302         char* addr = Sockaddr_print(ArrayList_Sockaddr_get(ctx->bcastAddrs, i), alloc);
303         List_addStringC(out, addr, alloc);
304     }
305     return out;
306 }
307 
UDPInterface_setDSCP(struct UDPInterface * udpif,uint8_t dscp)308 int UDPInterface_setDSCP(struct UDPInterface* udpif, uint8_t dscp)
309 {
310     struct UDPInterface_pvt* ctx = Identity_check((struct UDPInterface_pvt*) udpif);
311     int res = UDPAddrIface_setDSCP(ctx->commIf, dscp);
312     if (res) { return res; }
313     if (ctx->bcastIf) { return UDPAddrIface_setDSCP(ctx->bcastIf, dscp); }
314     return 0;
315 }
316 
UDPInterface_getFd(struct UDPInterface * udpif)317 int UDPInterface_getFd(struct UDPInterface* udpif)
318 {
319     struct UDPInterface_pvt* ctx = Identity_check((struct UDPInterface_pvt*) udpif);
320     return UDPAddrIface_getFd(ctx->commIf);
321 }