/* vim: set expandtab ts=4 sw=4: */ /* * You may redistribute this program and/or modify it under the terms of * the GNU General Public License as published by the Free Software Foundation, * either version 3 of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "admin/Admin.h" #include "admin/angel/Angel.h" #include "benc/Int.h" #include "benc/String.h" #include "exception/Jmp.h" #include "memory/Allocator.h" #include "util/platform/netdev/NetDev.h" #include "interface/addressable/AddrIfaceAdapter.h" #ifdef HAS_ETH_INTERFACE #include "interface/ETHInterface.h" #endif #include "util/events/EventBase.h" #include "util/log/Log.h" #include "util/Identity.h" #include struct AngelContext { struct Iface* coreIface; struct EventBase* eventBase; struct Allocator* alloc; struct Log* logger; struct Admin* admin; Identity }; static void adminExit(Dict* args, void* vcontext, String* txid, struct Allocator* requestAlloc) { struct AngelContext* ctx = Identity_check((struct AngelContext*) vcontext); Log_info(ctx->logger, "Got request to exit"); Dict d = Dict_CONST(String_CONST("error"), String_OBJ(String_CONST("none")), NULL); Admin_sendMessage(&d, txid, ctx->admin); exit(0); } static void adminAddIp2(char* interfaceName, struct Sockaddr* addr, int prefixLen, String* txid, struct Allocator* tempAlloc, struct AngelContext* ctx) { struct Jmp j; Jmp_try(j) { NetDev_addAddress(interfaceName, addr, prefixLen, NULL, &j.handler); } Jmp_catch { Dict d = Dict_CONST( String_CONST("error"), String_OBJ(String_CONST(j.message)), NULL ); Admin_sendMessage(&d, txid, ctx->admin); return; } Dict d = Dict_CONST( String_CONST("error"), String_OBJ(String_CONST("none")), NULL ); Admin_sendMessage(&d, txid, ctx->admin); } static void adminAddIp(Dict* args, void* vcontext, String* txid, struct Allocator* requestAlloc) { struct AngelContext* ctx = Identity_check((struct AngelContext*) vcontext); String* interfaceName = Dict_getString(args, String_CONST("interfaceName")); String* address = Dict_getString(args, String_CONST("address")); int64_t* prefixLenP = Dict_getInt(args, String_CONST("prefixLen")); int prefixLen = *prefixLenP; Log_info(ctx->logger, "Got request to set IP"); struct Sockaddr_storage ss; if (Sockaddr_parse(address->bytes, &ss)) { Dict d = Dict_CONST( String_CONST("error"), String_OBJ(String_CONST("Failed to parse addesss")), NULL ); Admin_sendMessage(&d, txid, ctx->admin); } else { struct Allocator* tempAlloc = Allocator_child(ctx->alloc); adminAddIp2(interfaceName->bytes, &ss.addr, prefixLen, txid, tempAlloc, ctx); Allocator_free(tempAlloc); } } #ifdef HAS_ETH_INTERFACE static void ethListDevices(Dict* args, void* vcontext, String* txid, struct Allocator* requestAlloc) { struct AngelContext* ctx = Identity_check((struct AngelContext*) vcontext); List* devices = NULL; struct Jmp jmp; Jmp_try(jmp) { devices = ETHInterface_listDevices(requestAlloc, &jmp.handler); } Jmp_catch { Dict* out = Dict_new(requestAlloc); Dict_putString(out, String_CONST("error"), String_CONST(jmp.message), requestAlloc); Admin_sendMessage(out, txid, ctx->admin); return; } Dict* out = Dict_new(requestAlloc); Dict_putString(out, String_CONST("error"), String_CONST("none"), requestAlloc); Dict_putList(out, String_CONST("devices"), devices, requestAlloc); Admin_sendMessage(out, txid, ctx->admin); } #endif void Angel_start(struct Iface* coreIface, struct EventBase* eventBase, struct Log* logger, struct Allocator* alloc) { struct AngelContext ctx = { .eventBase = eventBase, .logger = logger, .coreIface = coreIface, .alloc = alloc }; Identity_set(&ctx); struct AddrIfaceAdapter* addrIfAdapt = AddrIfaceAdapter_new(alloc); Iface_plumb(&addrIfAdapt->inputIf, coreIface); // this is inside of a pipe so the password is unimportant. String* passwd = String_new("null", alloc); ctx.admin = Admin_new(&addrIfAdapt->generic, NULL, eventBase, passwd); Admin_registerFunction("Angel_exit", adminExit, &ctx, false, NULL, ctx.admin); #ifdef HAS_ETH_INTERFACE Admin_registerFunction( "ETHInterface_listDevices", ethListDevices, &ctx, false, NULL, ctx.admin); #endif Admin_registerFunction("Angel_addIp", adminAddIp, &ctx, false, ((struct Admin_FunctionArg[]) { { .name = "interfaceName", .required = 1, .type = "String" }, { .name = "address", .required = 1, .type = "String" }, { .name = "prefixLen", .required = 1, .type = "Int" } }), ctx.admin); EventBase_beginLoop(eventBase); }