static void adminDisconnectPeer(Dict* args, void* vcontext, String* txid, struct Allocator* requestAlloc) { struct Context* context = Identity_check((struct Context*)vcontext); String* pubkeyString = Dict_getString(args, String_CONST("pubkey")); // parse the key uint8_t pubkey[32]; uint8_t addr[16]; int error = Key_parse(pubkeyString, pubkey, addr); char* errorMsg = NULL; if (error) { errorMsg = "bad key"; } else { // try to remove the peer if the key is valid error = InterfaceController_disconnectPeer(context->ic,pubkey); if (error) { errorMsg = "no peer found for that key"; } } Dict* response = Dict_new(requestAlloc); Dict_putInt(response, String_CONST("success"), error ? 0 : 1, requestAlloc); if (error) { Dict_putString(response, String_CONST("error"), String_CONST(errorMsg), requestAlloc); } Admin_sendMessage(response, txid, context->admin); }
static void allowConnection(Dict* args, void* vcontext, String* txid) { struct Context* context = (struct Context*) vcontext; String* publicKeyOfAuthorizedNode = Dict_getString(args, String_CONST("publicKeyOfAuthorizedNode")); String* ip6Address = Dict_getString(args, String_CONST("ip6Address")); String* ip4Address = Dict_getString(args, String_CONST("ip4Address")); uint8_t pubKey[32]; uint8_t ip6Addr[16]; uint8_t ip6ToGive[16]; uint8_t ip4ToGive[4]; char* error; int ret; if (!ip6Address && !ip4Address) { error = "Must specify ip6Address or ip4Address"; } else if ((ret = Key_parse(publicKeyOfAuthorizedNode, pubKey, ip6Addr)) != 0) { error = Key_parse_strerror(ret); } else if (ip6Address && evutil_inet_pton(AF_INET6, ip6Address->bytes, ip6ToGive) < 1) { error = "malformed ip6Address"; } else if (ip4Address && evutil_inet_pton(AF_INET, ip4Address->bytes, ip4ToGive) < 1) { error = "malformed ip4Address"; } else { int conn = IpTunnel_allowConnection(pubKey, (ip6Address) ? ip6ToGive : NULL, (ip4Address) ? ip4ToGive : NULL, context->ipTun); sendResponse(conn, txid, context->admin); return; } sendError(error, txid, context->admin); }
int main(int argc, char** argv) { if (argc < 2) { return usage(argv[0]); } uint8_t keyBytes[32]; uint8_t ip6Bytes[16]; String key = { .bytes = argv[1], .len = strlen(argv[1]) }; int ret = Key_parse(&key, keyBytes, ip6Bytes); switch (ret) { case Key_parse_TOO_SHORT: fprintf(stderr, "ERROR: Key_parse_TOO_SHORT\n"); return 1; case Key_parse_MALFORMED: fprintf(stderr, "ERROR: Key_parse_MALFORMED\n"); return 1; case Key_parse_DECODE_FAILED: fprintf(stderr, "ERROR: Key_parse_DECODE_FAILED\n"); return 1; case Key_parse_INVALID: fprintf(stderr, "ERROR: Key_parse_INVALID\n"); return 1; case 0: break; default: fprintf(stderr, "ERROR: unknown error [%d]\n", ret); return 1; } uint8_t output[40] = {0}; AddrTools_printIp(output, ip6Bytes); printf("%s\n", output); return 0; }
static void adminResetPeering(Dict* args, void* vcontext, String* txid, struct Allocator* requestAlloc) { struct Context* context = Identity_check((struct Context*)vcontext); String* pubkeyString = Dict_getStringC(args, "pubkey"); int error = 0; char* errorMsg = NULL; if (pubkeyString) { // parse the key uint8_t pubkey[32]; uint8_t addr[16]; error = Key_parse(pubkeyString, pubkey, addr); if (error) { errorMsg = "bad key"; } else { InterfaceController_resetPeering(context->ic, pubkey); } } else { // reset all InterfaceController_resetPeering(context->ic, NULL); } Dict* response = Dict_new(requestAlloc); Dict_putIntC(response, "success", error ? 0 : 1, requestAlloc); if (error) { Dict_putStringCC(response, "error", errorMsg, requestAlloc); } Admin_sendMessage(response, txid, context->admin); }
static void allowConnection(Dict* args, void* vcontext, String* txid, struct Allocator* requestAlloc) { struct Context* context = (struct Context*) vcontext; String* publicKeyOfAuthorizedNode = Dict_getString(args, String_CONST("publicKeyOfAuthorizedNode")); String* ip6Address = Dict_getString(args, String_CONST("ip6Address")); int64_t* ip6Prefix = Dict_getInt(args, String_CONST("ip6Prefix")); String* ip4Address = Dict_getString(args, String_CONST("ip4Address")); int64_t* ip4Prefix = Dict_getInt(args, String_CONST("ip4Prefix")); uint8_t pubKey[32]; uint8_t ip6Addr[16]; struct Sockaddr_storage ip6ToGive; struct Sockaddr_storage ip4ToGive; char* error; int ret; if (!ip6Address && !ip4Address) { error = "Must specify ip6Address or ip4Address"; } else if ((ret = Key_parse(publicKeyOfAuthorizedNode, pubKey, ip6Addr)) != 0) { error = Key_parse_strerror(ret); } else if (ip6Prefix && !ip6Address) { error = "Must specify ip6Address with ip6Prefix"; } else if (ip6Prefix && (*ip6Prefix > 128 || *ip6Prefix < 0)) { error = "ip6Prefix out of range: must be 0 to 128"; } else if (ip4Prefix && (*ip4Prefix > 32 || *ip4Prefix < 0)) { error = "ip4Prefix out of range: must be 0 to 32"; } else if (ip4Prefix && !ip4Address) { error = "Must specify ip4Address with ip4Prefix"; } else if (ip6Address && (Sockaddr_parse(ip6Address->bytes, &ip6ToGive) || Sockaddr_getFamily(&ip6ToGive.addr) != Sockaddr_AF_INET6)) { error = "malformed ip6Address"; } else if (ip4Address && (Sockaddr_parse(ip4Address->bytes, &ip4ToGive) || Sockaddr_getFamily(&ip4ToGive.addr) != Sockaddr_AF_INET)) { error = "malformed ip4Address"; } else { int conn = IpTunnel_allowConnection(pubKey, (ip6Address) ? &ip6ToGive.addr : NULL, (ip6Prefix) ? (uint8_t) (*ip6Prefix) : 0, (ip4Address) ? &ip4ToGive.addr : NULL, (ip4Prefix) ? (uint8_t) (*ip4Prefix) : 0, context->ipTun); sendResponse(conn, txid, context->admin); return; } sendError(error, txid, context->admin); }
static void beginConnection(Dict* args, void* vcontext, String* txid) { struct Context* ctx = vcontext; String* password = Dict_getString(args, String_CONST("password")); String* publicKey = Dict_getString(args, String_CONST("publicKey")); String* address = Dict_getString(args, String_CONST("address")); int64_t* interfaceNumber = Dict_getInt(args, String_CONST("interfaceNumber")); uint32_t ifNum = (interfaceNumber) ? ((uint32_t) *interfaceNumber) : 0; String* error = NULL; uint8_t pkBytes[32]; int ret; if (ctx->ifCount == 0) { error = String_CONST("no interfaces are setup, call UDPInterface_new() first"); } else if (interfaceNumber && (*interfaceNumber >= ctx->ifCount || *interfaceNumber < 0)) { error = String_CONST("invalid interfaceNumber"); } else if ((ret = Key_parse(publicKey, pkBytes, NULL))) { error = String_CONST(Key_parse_strerror(ret)); } else { struct UDPInterface* udpif = ctx->ifaces[ifNum]; switch (UDPInterface_beginConnection(address->bytes, pkBytes, password, udpif)) { case UDPInterface_beginConnection_OUT_OF_SPACE: error = String_CONST("no more space to register with the switch."); break; case UDPInterface_beginConnection_BAD_KEY: error = String_CONST("invalid cjdns public key."); break; case UDPInterface_beginConnection_BAD_ADDRESS: error = String_CONST("unable to parse ip address and port."); break; case UDPInterface_beginConnection_ADDRESS_MISMATCH: error = String_CONST("different address type than this socket is bound to."); break; case 0: error = String_CONST("none"); break; default: error = String_CONST("unknown error"); } } Dict out = Dict_CONST(String_CONST("error"), String_OBJ(error), NULL); Admin_sendMessage(&out, txid, ctx->admin); }
static void connectTo(Dict* args, void* vcontext, String* txid) { struct Context* context = vcontext; String* publicKeyOfNodeToConnectTo = Dict_getString(args, String_CONST("publicKeyOfNodeToConnectTo")); uint8_t pubKey[32]; uint8_t ip6[16]; int ret; if ((ret = Key_parse(publicKeyOfNodeToConnectTo, pubKey, ip6)) != 0) { sendError(Key_parse_strerror(ret), txid, context->admin); return; } int conn = IpTunnel_connectTo(pubKey, context->ipTun); sendResponse(conn, txid, context->admin); }
static void beginConnection(Dict* args, void* vcontext, String* txid, struct Allocator* requestAlloc) { struct Context* ctx = vcontext; String* password = Dict_getString(args, String_CONST("password")); String* publicKey = Dict_getString(args, String_CONST("publicKey")); String* address = Dict_getString(args, String_CONST("address")); int64_t* interfaceNumber = Dict_getInt(args, String_CONST("interfaceNumber")); uint32_t ifNum = (interfaceNumber) ? ((uint32_t) *interfaceNumber) : 0; String* peerName = Dict_getString(args, String_CONST("peerName")); String* error = NULL; Log_debug(ctx->logger, "Peering with [%s]", publicKey->bytes); struct Sockaddr_storage ss; uint8_t pkBytes[32]; int ret; if (interfaceNumber && *interfaceNumber < 0) { error = String_CONST("negative interfaceNumber"); } else if ((ret = Key_parse(publicKey, pkBytes, NULL))) { error = String_CONST(Key_parse_strerror(ret)); } else if (Sockaddr_parse(address->bytes, &ss)) { error = String_CONST("unable to parse ip address and port."); } else if (Sockaddr_getFamily(&ss.addr) != Sockaddr_getFamily(ctx->udpIf->addr)) { error = String_CONST("different address type than this socket is bound to."); } else { struct Sockaddr* addr = &ss.addr; char* addrPtr = NULL; int addrLen = Sockaddr_getAddress(&ss.addr, &addrPtr); Assert_true(addrLen > 0); struct Allocator* tempAlloc = Allocator_child(ctx->alloc); if (Bits_isZero(addrPtr, addrLen)) { // unspec'd address, convert to loopback if (Sockaddr_getFamily(addr) == Sockaddr_AF_INET) { addr = Sockaddr_clone(Sockaddr_LOOPBACK, tempAlloc); } else if (Sockaddr_getFamily(addr) == Sockaddr_AF_INET6) { addr = Sockaddr_clone(Sockaddr_LOOPBACK6, tempAlloc); } else { Assert_failure("Sockaddr which is not AF_INET nor AF_INET6"); } Sockaddr_setPort(addr, Sockaddr_getPort(&ss.addr)); } int ret = InterfaceController_bootstrapPeer( ctx->ic, ifNum, pkBytes, addr, password, peerName, ctx->alloc); Allocator_free(tempAlloc); if (ret) { switch(ret) { case InterfaceController_bootstrapPeer_BAD_IFNUM: error = String_CONST("no such interface for interfaceNumber"); break; case InterfaceController_bootstrapPeer_BAD_KEY: error = String_CONST("invalid cjdns public key."); break; case InterfaceController_bootstrapPeer_OUT_OF_SPACE: error = String_CONST("no more space to register with the switch."); break; default: error = String_CONST("unknown error"); break; } } else { error = String_CONST("none"); } } Dict out = Dict_CONST(String_CONST("error"), String_OBJ(error), NULL); Admin_sendMessage(&out, txid, ctx->admin); }