UDPInterface_admin.c 16 KB

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