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 "benc/Int.h"
16 #include "admin/Admin.h"
17 #include "memory/Allocator.h"
18 #include "net/InterfaceController.h"
19 #include "util/events/EventBase.h"
20 #include "util/events/FakeNetwork.h"
21 #include "util/platform/Sockaddr.h"
22 #include "crypto/Key.h"
23 #include "interface/UDPInterface_admin.h"
24 #include "interface/UDPInterface.h"
25 #include "util/Identity.h"
26 
27 #define ArrayList_TYPE struct UDPInterface
28 #define ArrayList_NAME UDPInterface
29 #include "util/ArrayList.h"
30 
31 struct Context
32 {
33     struct EventBase* eventBase;
34     struct Allocator* alloc;
35     struct Log* logger;
36     struct Admin* admin;
37     struct ArrayList_UDPInterface* ifaces;
38     struct InterfaceController* ic;
39     struct FakeNetwork* fakeNet;
40     struct GlobalConfig* globalConf;
41     Identity
42 };
43 
getIface(struct Context * ctx,Dict * args,String * txid,struct Allocator * requestAlloc,uint32_t * ifNumP)44 static struct UDPInterface* getIface(struct Context* ctx,
45                                      Dict* args,
46                                      String* txid,
47                                      struct Allocator* requestAlloc,
48                                      uint32_t* ifNumP)
49 {
50     int64_t* interfaceNumber = Dict_getIntC(args, "interfaceNumber");
51     uint32_t ifNum = (interfaceNumber) ? ((uint32_t) *interfaceNumber) : 0;
52     if (ifNumP) { *ifNumP = ifNum; }
53     struct UDPInterface* udpif = ArrayList_UDPInterface_get(ctx->ifaces, ifNum);
54     if (!udpif) {
55         Dict* out = Dict_new(requestAlloc);
56         Dict_putStringCC(out, "error", "no such interface for interfaceNumber", requestAlloc);
57         Admin_sendMessage(out, txid, ctx->admin);
58     }
59     return udpif;
60 }
61 
beginConnection(Dict * args,void * vcontext,String * txid,struct Allocator * requestAlloc)62 static void beginConnection(Dict* args,
63                             void* vcontext,
64                             String* txid,
65                             struct Allocator* requestAlloc)
66 {
67     struct Context* ctx = Identity_check((struct Context*) vcontext);
68 
69     uint32_t ifNum = 0;
70     struct UDPInterface* udpIf = getIface(ctx, args, txid, requestAlloc, &ifNum);
71     if (!udpIf) { return; }
72 
73     String* password = Dict_getStringC(args, "password");
74     String* login = Dict_getStringC(args, "login");
75     String* publicKey = Dict_getStringC(args, "publicKey");
76     String* address = Dict_getStringC(args, "address");
77     String* peerName = Dict_getStringC(args, "peerName");
78     char* error = NULL;
79 
80     Log_debug(ctx->logger, "Peering with [%s]", publicKey->bytes);
81 
82     struct Sockaddr_storage ss;
83     uint8_t pkBytes[32];
84     int ret;
85     if ((ret = Key_parse(publicKey, pkBytes, NULL))) {
86         error = Key_parse_strerror(ret);
87 
88     } else if (Sockaddr_parse(address->bytes, &ss)) {
89         error = "unable to parse ip address and port.";
90 
91     } else if (Sockaddr_getFamily(&ss.addr) != Sockaddr_getFamily(udpIf->generic.addr)) {
92         error = "different address type than this socket is bound to.";
93 
94     } else {
95 
96         struct Sockaddr* addr = &ss.addr;
97         char* addrPtr = NULL;
98         int addrLen = Sockaddr_getAddress(&ss.addr, &addrPtr);
99         Assert_true(addrLen > 0);
100         struct Allocator* tempAlloc = Allocator_child(ctx->alloc);
101         if (Bits_isZero(addrPtr, addrLen)) {
102             // unspec'd address, convert to loopback
103             if (Sockaddr_getFamily(addr) == Sockaddr_AF_INET) {
104                 addr = Sockaddr_clone(Sockaddr_LOOPBACK, tempAlloc);
105             } else if (Sockaddr_getFamily(addr) == Sockaddr_AF_INET6) {
106                 addr = Sockaddr_clone(Sockaddr_LOOPBACK6, tempAlloc);
107             } else {
108                 Assert_failure("Sockaddr which is not AF_INET nor AF_INET6");
109             }
110             Sockaddr_setPort(addr, Sockaddr_getPort(&ss.addr));
111         }
112 
113         int ret = InterfaceController_bootstrapPeer(
114             ctx->ic, ifNum, pkBytes, addr, password, login, peerName, ctx->alloc);
115 
116         Allocator_free(tempAlloc);
117 
118         if (ret) {
119             switch(ret) {
120                 case InterfaceController_bootstrapPeer_BAD_IFNUM:
121                     // Should never happen, should be caught in getIface()
122                     error = "interface deregistered";
123                     break;
124 
125                 case InterfaceController_bootstrapPeer_BAD_KEY:
126                     error = "invalid cjdns public key.";
127                     break;
128 
129                 case InterfaceController_bootstrapPeer_OUT_OF_SPACE:
130                     error = "no more space to register with the switch.";
131                     break;
132 
133                 default:
134                     error = "unknown error";
135                     break;
136             }
137         } else {
138             error = "none";
139         }
140     }
141 
142     Dict* out = Dict_new(requestAlloc);
143     Dict_putStringCC(out, "error", error, requestAlloc);
144     Admin_sendMessage(out, txid, ctx->admin);
145 }
146 
setupLibuvUDP(struct Context * ctx,struct Sockaddr * addr,uint16_t beaconPort,uint8_t dscp,String * txid,struct Allocator * alloc)147 static struct UDPInterface* setupLibuvUDP(struct Context* ctx,
148                                        struct Sockaddr* addr,
149                                        uint16_t beaconPort,
150                                        uint8_t dscp,
151                                        String* txid,
152                                        struct Allocator* alloc)
153 {
154     struct Er_Ret* er = NULL;
155     struct UDPInterface* udpIf = Er_check(&er, UDPInterface_new(
156         ctx->eventBase, addr, beaconPort, alloc, ctx->logger, ctx->globalConf));
157     if (er) {
158         Dict* out = Dict_new(alloc);
159         Dict_putStringCC(out, "error", er->message, alloc);
160         Admin_sendMessage(out, txid, ctx->admin);
161         Allocator_free(alloc);
162         return NULL;
163     } else if (dscp) {
164         if (UDPInterface_setDSCP(udpIf, dscp)) {
165             Log_warn(ctx->logger, "Set DSCP failed");
166         }
167     }
168     return udpIf;
169 }
170 
newInterface2(struct Context * ctx,struct Sockaddr * addr,uint8_t dscp,String * txid,struct Allocator * requestAlloc,uint16_t beaconPort)171 static void newInterface2(struct Context* ctx,
172                           struct Sockaddr* addr,
173                           uint8_t dscp,
174                           String* txid,
175                           struct Allocator* requestAlloc,
176                           uint16_t beaconPort)
177 {
178     struct Allocator* const alloc = Allocator_child(ctx->alloc);
179     struct UDPInterface* udpif = setupLibuvUDP(ctx, addr, beaconPort, dscp, txid, alloc);
180     if (!udpif) { return; }
181 
182     String* name = String_printf(requestAlloc, "UDP/IPv%d/%s",
183         (Sockaddr_getFamily(addr) == Sockaddr_AF_INET ? 4 : 6),
184         Sockaddr_print(addr, requestAlloc));
185 
186     struct InterfaceController_Iface* ici =
187         InterfaceController_newIface(ctx->ic, name, alloc);
188     Iface_plumb(&ici->addrIf, &udpif->generic.iface);
189     ArrayList_UDPInterface_put(ctx->ifaces, ici->ifNum, udpif);
190 
191     Dict* out = Dict_new(requestAlloc);
192     Dict_putStringCC(out, "error", "none", requestAlloc);
193     Dict_putIntC(out, "interfaceNumber", ici->ifNum, requestAlloc);
194     char* printedAddr = Sockaddr_print(udpif->generic.addr, requestAlloc);
195     Dict_putStringCC(out,
196                    "bindAddress",
197                    printedAddr,
198                    requestAlloc);
199 
200     Admin_sendMessage(out, txid, ctx->admin);
201 }
202 
newInterface(Dict * args,void * vcontext,String * txid,struct Allocator * requestAlloc)203 static void newInterface(Dict* args, void* vcontext, String* txid, struct Allocator* requestAlloc)
204 {
205     struct Context* ctx = Identity_check((struct Context*) vcontext);
206     String* bindAddress = Dict_getStringC(args, "bindAddress");
207     int64_t* dscpValue = Dict_getIntC(args, "dscp");
208     uint8_t dscp = dscpValue ? ((uint8_t) *dscpValue) : 0;
209     int64_t* beaconPort_p = Dict_getIntC(args, "beaconPort");
210     uint16_t beaconPort = beaconPort_p ? ((uint16_t) *beaconPort_p) : 0;
211     struct Sockaddr_storage addr;
212     if (Sockaddr_parse((bindAddress) ? bindAddress->bytes : "0.0.0.0", &addr)) {
213         Dict out = Dict_CONST(
214             String_CONST("error"), String_OBJ(String_CONST("Failed to parse address")), NULL
215         );
216         Admin_sendMessage(&out, txid, ctx->admin);
217         return;
218     }
219     newInterface2(ctx, &addr.addr, dscp, txid, requestAlloc, beaconPort);
220 }
221 
listDevices(Dict * args,void * vcontext,String * txid,struct Allocator * requestAlloc)222 static void listDevices(Dict* args, void* vcontext, String* txid, struct Allocator* requestAlloc)
223 {
224     struct Context* ctx = Identity_check((struct Context*) vcontext);
225     Dict* out = Dict_new(requestAlloc);
226     struct Er_Ret* er = NULL;
227     List* list = Er_check(&er, UDPInterface_listDevices(requestAlloc));
228     if (er) {
229         Dict_putStringCC(out, "error", er->message, requestAlloc);
230     } else {
231         Dict_putListC(out, "ret", list, requestAlloc);
232     }
233     Admin_sendMessage(out, txid, ctx->admin);
234 }
235 
setBroadcastDevices(Dict * args,void * vcontext,String * txid,struct Allocator * requestAlloc)236 static void setBroadcastDevices(
237     Dict* args, void* vcontext, String* txid, struct Allocator* requestAlloc)
238 {
239     struct Context* ctx = Identity_check((struct Context*) vcontext);
240     struct UDPInterface* udpif = getIface(ctx, args, txid, requestAlloc, NULL);
241     if (!udpif) { return; }
242     UDPInterface_setBroadcastDevices(udpif, Dict_getListC(args, "devices"));
243     Dict* out = Dict_new(requestAlloc);
244     Dict_putStringCC(out, "error", "none", requestAlloc);
245     Admin_sendMessage(out, txid, ctx->admin);
246 }
247 
getBroadcastDevices(Dict * args,void * vcontext,String * txid,struct Allocator * requestAlloc)248 static void getBroadcastDevices(
249     Dict* args, void* vcontext, String* txid, struct Allocator* requestAlloc)
250 {
251     struct Context* ctx = Identity_check((struct Context*) vcontext);
252     struct UDPInterface* udpif = getIface(ctx, args, txid, requestAlloc, NULL);
253     if (!udpif) { return; }
254     Dict* out = Dict_new(requestAlloc);
255     Dict_putStringCC(out, "error", "none", requestAlloc);
256     List* devices = UDPInterface_getBroadcastDevices(udpif, requestAlloc);
257     Dict_putListC(out, "devices", devices, requestAlloc);
258     Admin_sendMessage(out, txid, ctx->admin);
259 }
260 
getBroadcastAddrs(Dict * args,void * vcontext,String * txid,struct Allocator * requestAlloc)261 static void getBroadcastAddrs(
262     Dict* args, void* vcontext, String* txid, struct Allocator* requestAlloc)
263 {
264     struct Context* ctx = Identity_check((struct Context*) vcontext);
265     struct UDPInterface* udpif = getIface(ctx, args, txid, requestAlloc, NULL);
266     if (!udpif) { return; }
267     Dict* out = Dict_new(requestAlloc);
268     Dict_putStringCC(out, "error", "none", requestAlloc);
269     List* addrs = UDPInterface_getBroadcastAddrs(udpif, requestAlloc);
270     Dict_putListC(out, "addrs", addrs, requestAlloc);
271     Admin_sendMessage(out, txid, ctx->admin);
272 }
273 
beacon(Dict * args,void * vcontext,String * txid,struct Allocator * requestAlloc)274 static void beacon(Dict* args, void* vcontext, String* txid, struct Allocator* requestAlloc)
275 {
276     int64_t* stateP = Dict_getIntC(args, "state");
277     int64_t* ifNumP = Dict_getIntC(args, "interfaceNumber");
278     uint32_t ifNum = (ifNumP) ? ((uint32_t) *ifNumP) : 0;
279     uint32_t state = (stateP) ? ((uint32_t) *stateP) : 0xffffffff;
280     struct Context* ctx = Identity_check((struct Context*) vcontext);
281 
282     char* error = NULL;
283     int ret = InterfaceController_beaconState(ctx->ic, ifNum, state);
284     if (ret == InterfaceController_beaconState_NO_SUCH_IFACE) {
285         error = "invalid interfaceNumber";
286     } else if (ret == InterfaceController_beaconState_INVALID_STATE) {
287         error = "invalid state";
288     } else if (ret) {
289         error = "internal";
290     }
291 
292     if (error) {
293         Dict* out = Dict_new(requestAlloc);
294         Dict_putStringCC(out, "error", error, requestAlloc);
295         Admin_sendMessage(out, txid, ctx->admin);
296         return;
297     }
298 
299     char* stateStr = "disabled";
300     if (state == InterfaceController_beaconState_newState_ACCEPT) {
301         stateStr = "accepting";
302     } else if (state == InterfaceController_beaconState_newState_SEND) {
303         stateStr = "sending and accepting";
304     }
305 
306     Dict out = Dict_CONST(
307         String_CONST("error"), String_OBJ(String_CONST("none")), Dict_CONST(
308         String_CONST("state"), Int_OBJ(state), Dict_CONST(
309         String_CONST("stateName"), String_OBJ(String_CONST(stateStr)), NULL
310     )));
311     Admin_sendMessage(&out, txid, ctx->admin);
312 }
313 
getFd(Dict * args,void * vcontext,String * txid,struct Allocator * requestAlloc)314 static void getFd(Dict* args, void* vcontext, String* txid, struct Allocator* requestAlloc)
315 {
316     struct Context* ctx = Identity_check((struct Context*) vcontext);
317     struct UDPInterface* udpif = getIface(ctx, args, txid, requestAlloc, NULL);
318     if (!udpif) {
319         return;
320     }
321     int fd = UDPInterface_getFd(udpif);
322     Dict* out = Dict_new(requestAlloc);
323     Dict_putIntC(out, "fd", fd, requestAlloc);
324     Dict_putStringCC(out, "error", "none", requestAlloc);
325     Admin_sendMessage(out, txid, ctx->admin);
326 }
327 
UDPInterface_admin_register(struct EventBase * base,struct Allocator * alloc,struct Log * logger,struct Admin * admin,struct InterfaceController * ic,struct FakeNetwork * fakeNet,struct GlobalConfig * globalConf)328 void UDPInterface_admin_register(struct EventBase* base,
329                                  struct Allocator* alloc,
330                                  struct Log* logger,
331                                  struct Admin* admin,
332                                  struct InterfaceController* ic,
333                                  struct FakeNetwork* fakeNet,
334                                  struct GlobalConfig* globalConf)
335 {
336     struct Context* ctx = Allocator_clone(alloc, (&(struct Context) {
337         .eventBase = base,
338         .alloc = alloc,
339         .logger = logger,
340         .admin = admin,
341         .ic = ic,
342         .fakeNet = fakeNet,
343         .globalConf = globalConf
344     }));
345     Identity_set(ctx);
346     ctx->ifaces = ArrayList_UDPInterface_new(alloc);
347 
348     Admin_registerFunction("UDPInterface_new", newInterface, ctx, true,
349         ((struct Admin_FunctionArg[]) {
350             { .name = "bindAddress", .required = 0, .type = "String" },
351             { .name = "dscp", .required = 0, .type = "Int" },
352             { .name = "beaconPort", .required = 0, .type = "Int" }
353         }), admin);
354 
355     Admin_registerFunction("UDPInterface_beginConnection", beginConnection, ctx, true,
356         ((struct Admin_FunctionArg[]) {
357             { .name = "interfaceNumber", .required = 0, .type = "Int" },
358             { .name = "password", .required = 0, .type = "String" },
359             { .name = "publicKey", .required = 1, .type = "String" },
360             { .name = "address", .required = 1, .type = "String" },
361             { .name = "login", .required = 0, .type = "String" },
362             { .name = "peerName", .required = 0, .type = "String" }
363         }), admin);
364 
365     Admin_registerFunction("UDPInterface_listDevices", listDevices, ctx, true, NULL, admin);
366 
367     Admin_registerFunction("UDPInterface_setBroadcastDevices", setBroadcastDevices, ctx, true,
368         ((struct Admin_FunctionArg[]) {
369             { .name = "interfaceNumber", .required = 0, .type = "Int" },
370             { .name = "devices", .required = 1, .type = "List" }
371         }), admin);
372 
373     Admin_registerFunction("UDPInterface_getBroadcastDevices", getBroadcastDevices, ctx, true,
374         ((struct Admin_FunctionArg[]) {
375             { .name = "interfaceNumber", .required = 0, .type = "Int" }
376         }), admin);
377 
378     Admin_registerFunction("UDPInterface_getBroadcastAddrs", getBroadcastAddrs, ctx, true,
379         ((struct Admin_FunctionArg[]) {
380             { .name = "interfaceNumber", .required = 0, .type = "Int" }
381         }), admin);
382 
383     Admin_registerFunction("UDPInterface_beacon", beacon, ctx, true,
384         ((struct Admin_FunctionArg[]) {
385             { .name = "interfaceNumber", .required = 0, .type = "Int" },
386             { .name = "state", .required = 0, .type = "Int" }
387         }), admin);
388 
389     Admin_registerFunction("UDPInterface_getFd", getFd, ctx, true,
390         ((struct Admin_FunctionArg[]) {
391             { .name = "interfaceNumber", .required = 0, .type = "Int" },
392         }), admin);
393 }
394