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