ETHInterface_admin.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267
  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/ETHInterface_admin.h"
  16. #include "interface/ETHInterface.h"
  17. #include "benc/Int.h"
  18. #include "admin/Admin.h"
  19. #include "crypto/Key.h"
  20. #include "exception/Jmp.h"
  21. #include "memory/Allocator.h"
  22. #include "net/InterfaceController.h"
  23. #include "util/AddrTools.h"
  24. #include "util/Identity.h"
  25. #define ArrayList_TYPE struct ETHInterface
  26. #define ArrayList_NAME ETHInterface
  27. #include "util/ArrayList.h"
  28. struct Context
  29. {
  30. struct EventBase* eventBase;
  31. struct Allocator* alloc;
  32. struct Log* logger;
  33. struct Admin* admin;
  34. struct InterfaceController* ic;
  35. struct ArrayList_ETHInterface* ifaces;
  36. Identity
  37. };
  38. static struct ETHInterface* getIface(struct Context* ctx,
  39. Dict* args,
  40. String* txid,
  41. struct Allocator* requestAlloc,
  42. uint32_t* ifNumP)
  43. {
  44. int64_t* interfaceNumber = Dict_getIntC(args, "interfaceNumber");
  45. uint32_t ifNum = (interfaceNumber) ? ((uint32_t) *interfaceNumber) : 0;
  46. if (ifNumP) { *ifNumP = ifNum; }
  47. struct ETHInterface* ethIf = ArrayList_ETHInterface_get(ctx->ifaces, ifNum);
  48. if (!ethIf) {
  49. Dict* out = Dict_new(requestAlloc);
  50. Dict_putStringCC(out, "error", "no such interface for interfaceNumber", requestAlloc);
  51. Admin_sendMessage(out, txid, ctx->admin);
  52. }
  53. return ethIf;
  54. }
  55. static void beginConnection(Dict* args,
  56. void* vcontext,
  57. String* txid,
  58. struct Allocator* requestAlloc)
  59. {
  60. struct Context* ctx = Identity_check((struct Context*) vcontext);
  61. String* password = Dict_getStringC(args, "password");
  62. String* login = Dict_getStringC(args, "login");
  63. String* publicKey = Dict_getStringC(args, "publicKey");
  64. String* macAddress = Dict_getStringC(args, "macAddress");
  65. int64_t* interfaceNumber = Dict_getIntC(args, "interfaceNumber");
  66. uint32_t ifNum = (interfaceNumber) ? ((uint32_t) *interfaceNumber) : 0;
  67. String* peerName = Dict_getStringC(args, "peerName");
  68. char* error = "none";
  69. uint8_t pkBytes[32];
  70. struct ETHInterface_Sockaddr sockaddr = {
  71. .generic = {
  72. .addrLen = ETHInterface_Sockaddr_SIZE
  73. }
  74. };
  75. if (Key_parse(publicKey, pkBytes, NULL)) {
  76. error = "invalid publicKey";
  77. } else if (macAddress->len < 17 || AddrTools_parseMac(sockaddr.mac, macAddress->bytes)) {
  78. error = "invalid macAddress";
  79. } else {
  80. int ret = InterfaceController_bootstrapPeer(
  81. ctx->ic, ifNum, pkBytes, &sockaddr.generic, password, login, peerName, ctx->alloc);
  82. if (ret == InterfaceController_bootstrapPeer_BAD_IFNUM) {
  83. error = "invalid interfaceNumber";
  84. } else if (ret == InterfaceController_bootstrapPeer_BAD_KEY) {
  85. error = "invalid publicKey";
  86. } else if (ret == InterfaceController_bootstrapPeer_OUT_OF_SPACE) {
  87. error = "no more space to register with the switch.";
  88. } else if (ret) {
  89. error = "InterfaceController_bootstrapPeer(internal_error)";
  90. }
  91. }
  92. Dict* out = Dict_new(requestAlloc);
  93. Dict_putStringC(out, "error", String_new(error, requestAlloc), requestAlloc);
  94. Admin_sendMessage(out, txid, ctx->admin);
  95. }
  96. static void newInterface(Dict* args, void* vcontext, String* txid, struct Allocator* requestAlloc)
  97. {
  98. struct Context* const ctx = Identity_check((struct Context*) vcontext);
  99. String* const bindDevice = Dict_getStringC(args, "bindDevice");
  100. struct Allocator* const alloc = Allocator_child(ctx->alloc);
  101. struct ETHInterface* ethIf = NULL;
  102. struct Jmp jmp;
  103. Jmp_try(jmp) {
  104. ethIf = ETHInterface_new(
  105. ctx->eventBase, bindDevice->bytes, alloc, &jmp.handler, ctx->logger);
  106. } Jmp_catch {
  107. Dict* out = Dict_new(requestAlloc);
  108. Dict_putStringCC(out, "error", jmp.message, requestAlloc);
  109. Admin_sendMessage(out, txid, ctx->admin);
  110. Allocator_free(alloc);
  111. return;
  112. }
  113. String* ifname = String_printf(requestAlloc, "ETH/%s", bindDevice->bytes);
  114. struct InterfaceController_Iface* ici = InterfaceController_newIface(ctx->ic, ifname, alloc);
  115. Iface_plumb(&ici->addrIf, &ethIf->generic.iface);
  116. while (ici->ifNum > ctx->ifaces->length) {
  117. ArrayList_ETHInterface_add(ctx->ifaces, NULL);
  118. }
  119. ArrayList_ETHInterface_put(ctx->ifaces, ici->ifNum, ethIf);
  120. Dict* out = Dict_new(requestAlloc);
  121. Dict_putStringCC(out, "error", "none", requestAlloc);
  122. Dict_putIntC(out, "interfaceNumber", ici->ifNum, requestAlloc);
  123. Admin_sendMessage(out, txid, ctx->admin);
  124. }
  125. static void beacon(Dict* args, void* vcontext, String* txid, struct Allocator* requestAlloc)
  126. {
  127. int64_t* stateP = Dict_getIntC(args, "state");
  128. int64_t* ifNumP = Dict_getIntC(args, "interfaceNumber");
  129. uint32_t ifNum = (ifNumP) ? ((uint32_t) *ifNumP) : 0;
  130. uint32_t state = (stateP) ? ((uint32_t) *stateP) : 0xffffffff;
  131. struct Context* ctx = Identity_check((struct Context*) vcontext);
  132. char* error = NULL;
  133. int ret = InterfaceController_beaconState(ctx->ic, ifNum, state);
  134. if (ret == InterfaceController_beaconState_NO_SUCH_IFACE) {
  135. error = "invalid interfaceNumber";
  136. } else if (ret == InterfaceController_beaconState_INVALID_STATE) {
  137. error = "invalid state";
  138. } else if (ret) {
  139. error = "internal";
  140. }
  141. if (error) {
  142. Dict* out = Dict_new(requestAlloc);
  143. Dict_putStringCC(out, "error", error, requestAlloc);
  144. Admin_sendMessage(out, txid, ctx->admin);
  145. return;
  146. }
  147. char* stateStr = "disabled";
  148. if (state == InterfaceController_beaconState_newState_ACCEPT) {
  149. stateStr = "accepting";
  150. } else if (state == InterfaceController_beaconState_newState_SEND) {
  151. stateStr = "sending and accepting";
  152. }
  153. Dict out = Dict_CONST(
  154. String_CONST("error"), String_OBJ(String_CONST("none")), Dict_CONST(
  155. String_CONST("state"), Int_OBJ(state), Dict_CONST(
  156. String_CONST("stateName"), String_OBJ(String_CONST(stateStr)), NULL
  157. )));
  158. Admin_sendMessage(&out, txid, ctx->admin);
  159. }
  160. static void listDevices(Dict* args, void* vcontext, String* txid, struct Allocator* requestAlloc)
  161. {
  162. struct Context* ctx = Identity_check((struct Context*) vcontext);
  163. List* devices = NULL;
  164. struct Jmp jmp;
  165. Jmp_try(jmp) {
  166. devices = ETHInterface_listDevices(requestAlloc, &jmp.handler);
  167. } Jmp_catch {
  168. Dict* out = Dict_new(requestAlloc);
  169. Dict_putStringCC(out, "error", jmp.message, requestAlloc);
  170. Admin_sendMessage(out, txid, ctx->admin);
  171. return;
  172. }
  173. Dict* out = Dict_new(requestAlloc);
  174. Dict_putStringCC(out, "error", "none", requestAlloc);
  175. Dict_putListC(out, "devices", devices, requestAlloc);
  176. Admin_sendMessage(out, txid, ctx->admin);
  177. }
  178. static void timestampPackets(
  179. Dict* args, void* vcontext, String* txid, struct Allocator* requestAlloc)
  180. {
  181. struct Context* ctx = Identity_check((struct Context*) vcontext);
  182. struct ETHInterface* ethIf = getIface(ctx, args, txid, requestAlloc, NULL);
  183. if (!ethIf) { return; }
  184. int64_t* enable = Dict_getIntC(args, "enable");
  185. bool enabled;
  186. if (!enable) {
  187. enabled = ETHInterface_timestampPackets(ethIf, false);
  188. if (enabled) {
  189. ETHInterface_timestampPackets(ethIf, true);
  190. }
  191. } else {
  192. enabled = ETHInterface_timestampPackets(ethIf, *enable);
  193. }
  194. Dict* out = Dict_new(requestAlloc);
  195. Dict_putStringCC(out, "error", "none", requestAlloc);
  196. Dict_putIntC(out, "enabled", enabled, requestAlloc);
  197. Admin_sendMessage(out, txid, ctx->admin);
  198. }
  199. void ETHInterface_admin_register(struct EventBase* base,
  200. struct Allocator* alloc,
  201. struct Log* logger,
  202. struct Admin* admin,
  203. struct InterfaceController* ic)
  204. {
  205. struct Context* ctx = Allocator_clone(alloc, (&(struct Context) {
  206. .eventBase = base,
  207. .alloc = alloc,
  208. .logger = logger,
  209. .admin = admin,
  210. .ic = ic
  211. }));
  212. Identity_set(ctx);
  213. ctx->ifaces = ArrayList_ETHInterface_new(alloc);
  214. Admin_registerFunction("ETHInterface_new", newInterface, ctx, true,
  215. ((struct Admin_FunctionArg[]) {
  216. { .name = "bindDevice", .required = 1, .type = "String" }
  217. }), admin);
  218. Admin_registerFunction("ETHInterface_beginConnection",
  219. beginConnection, ctx, true, ((struct Admin_FunctionArg[]) {
  220. { .name = "interfaceNumber", .required = 0, .type = "Int" },
  221. { .name = "password", .required = 0, .type = "String" },
  222. { .name = "publicKey", .required = 1, .type = "String" },
  223. { .name = "macAddress", .required = 1, .type = "String" },
  224. { .name = "login", .required = 0, .type = "String" }
  225. }), admin);
  226. Admin_registerFunction("ETHInterface_beacon", beacon, ctx, true,
  227. ((struct Admin_FunctionArg[]) {
  228. { .name = "interfaceNumber", .required = 0, .type = "Int" },
  229. { .name = "state", .required = 0, .type = "Int" }
  230. }), admin);
  231. Admin_registerFunction("ETHInterface_listDevices", listDevices, ctx, true, NULL, admin);
  232. Admin_registerFunction("ETHInterface_timestampPackets", timestampPackets, ctx, true,
  233. ((struct Admin_FunctionArg[]) {
  234. { .name = "interfaceNumber", .required = 0, .type = "Int" },
  235. { .name = "enable", .required = 0, .type = "Int" }
  236. }), admin);
  237. }