// This is directly called from SwitchCore, message is not encrypted. static uint8_t sendFromSwitch(struct Message* msg, struct Interface* switchIf) { struct InterfaceController_Peer* ep = Identity_check((struct InterfaceController_Peer*) switchIf); ep->bytesOut += msg->length; struct InterfaceController_pvt* ic = ifcontrollerForPeer(ep); uint8_t ret; uint64_t now = Time_currentTimeMilliseconds(ic->eventBase); if (now - ep->timeOfLastMessage > ic->unresponsiveAfterMilliseconds) { // TODO(cjd): This is a hack because if the time of last message exceeds the // unresponsive time, we need to send back an error and that means // mangling the message which would otherwise be in the queue. struct Allocator* tempAlloc = Allocator_child(ic->allocator); struct Message* toSend = Message_clone(msg, tempAlloc); ret = Interface_sendMessage(ep->cryptoAuthIf, toSend); Allocator_free(tempAlloc); } else { ret = Interface_sendMessage(ep->cryptoAuthIf, msg); } // If this node is unresponsive then return an error. if (ret || now - ep->timeOfLastMessage > ic->unresponsiveAfterMilliseconds) { return ret ? ret : Error_UNDELIVERABLE; } else { /* Way way way too much noise Log_debug(ic->logger, "Sending to neighbor, last message from this node was [%u] ms ago.", (now - ep->timeOfLastMessage)); */ } return Error_NONE; }
/** @return a string representing the address and port to connect to. */ static void initAngel(struct Pipe* asClientPipe, struct Interface* asCoreIface, char* asCorePipeName, struct EventBase* eventBase, struct Log* logger, struct Allocator* alloc, struct Random* rand) { Dict admin = Dict_CONST( String_CONST("bind"), String_OBJ(String_CONST("127.0.0.1")), Dict_CONST( String_CONST("corePipeName"), String_OBJ(String_CONST(asCorePipeName)), Dict_CONST( String_CONST("pass"), String_OBJ(String_CONST("abcd")), NULL ))); Dict message = Dict_CONST( String_CONST("admin"), Dict_OBJ(&admin), NULL ); struct Allocator* tempAlloc = Allocator_child(alloc); struct Message* toAngel = Message_new(0, 1024, tempAlloc); BencMessageWriter_write(&message, toAngel, NULL); Log_info(logger, "Writing intial configuration to angel on [%s]", asClientPipe->name); Interface_sendMessage(&asClientPipe->iface, toAngel); // This is client->angel->core data, we can throw this away. //struct Message* angelToCore = InterfaceWaiter_waitForData(asCoreIface, eventBase, tempAlloc, NULL); // unterminated string //Log_info(logger, "Init message from angel to core: [%s]", angelToCore->bytes); // Send response on behalf of core. Dict* coreToAngelResp = Dict_new(tempAlloc); Dict_putString(coreToAngelResp, String_CONST("error"), String_CONST("none"), tempAlloc); struct Message* coreToAngelMsg = Message_new(0, 256, tempAlloc); BencMessageWriter_write(coreToAngelResp, coreToAngelMsg, NULL); Interface_sendMessage(asCoreIface, coreToAngelMsg); // This is angel->client data, it will tell us which port was bound. struct Message* angelToClient = InterfaceWaiter_waitForData(&asClientPipe->iface, eventBase, tempAlloc, NULL); uint8_t lastByte = angelToClient->bytes[angelToClient->length-1]; angelToClient->bytes[angelToClient->length-1] = '\0'; printf("Response from angel to client: [%s%c]\n", angelToClient->bytes, (char)lastByte); Allocator_free(tempAlloc); return; }
// This is directly called from SwitchCore, message is not encrypted. static uint8_t sendFromSwitch(struct Message* msg, struct Interface* switchIf) { struct IFCPeer* ep = Identity_cast((struct IFCPeer*) switchIf); ep->bytesOut += msg->length; // This sucks but cryptoauth trashes the content when it encrypts // and we need to be capable of sending back a coherent error message. uint8_t top[255]; uint8_t* messageBytes = msg->bytes; uint16_t padding = msg->padding; uint16_t len = (msg->length < 255) ? msg->length : 255; Bits_memcpy(top, msg->bytes, len); struct Context* ic = ifcontrollerForPeer(ep); uint8_t ret; uint64_t now = Time_currentTimeMilliseconds(ic->eventBase); if (now - ep->timeOfLastMessage > ic->unresponsiveAfterMilliseconds) { // XXX: This is a hack because if the time of last message exceeds the // unresponsive time, we need to send back an error and that means // mangling the message which would otherwise be in the queue. struct Allocator* tempAlloc = Allocator_child(ic->allocator); struct Message* toSend = Message_clone(msg, tempAlloc); ret = Interface_sendMessage(ep->cryptoAuthIf, toSend); Allocator_free(tempAlloc); } else { ret = Interface_sendMessage(ep->cryptoAuthIf, msg); } // If this node is unresponsive then return an error. if (ret || now - ep->timeOfLastMessage > ic->unresponsiveAfterMilliseconds) { msg->bytes = messageBytes; msg->padding = padding; msg->length = len; Bits_memcpy(msg->bytes, top, len); return ret ? ret : Error_UNDELIVERABLE; } else { /* Way way way too much noise Log_debug(ic->logger, "Sending to neighbor, last message from this node was [%u] ms ago.", (now - ep->timeOfLastMessage)); */ } return Error_NONE; }
static uint8_t sendMessage(struct Message* message, struct Interface* iface) { struct AddrInterfaceAdapter_pvt* context = Identity_cast((struct AddrInterfaceAdapter_pvt*) iface); Message_shift(message, -(context->pub.addr->addrLen), NULL); return Interface_sendMessage(context->wrapped, message); }
static inline uint8_t incomingDHT(struct Message* message, struct Address* addr, struct Ducttape_pvt* context) { struct DHTMessage dht = { .address = addr, .binMessage = message, .allocator = message->alloc }; DHTModuleRegistry_handleIncoming(&dht, context->registry); // TODO(cjd): return something meaningful. return Error_NONE; } /** Header must not be encrypted and must be aligned on the beginning of the ipv6 header. */ static inline uint8_t sendToRouter(struct Message* message, struct Ducttape_MessageHeader* dtHeader, struct SessionManager_Session* session, struct Ducttape_pvt* context) { int safeDistance = SwitchHeader_SIZE; CryptoAuth_resetIfTimeout(session->internal); if (CryptoAuth_getState(session->internal) < CryptoAuth_HANDSHAKE3) { // Put the handle into the message so that it's authenticated. // see: sendToSwitch() //Log_debug(context->logger, "Sending receive handle under CryptoAuth"); Message_push(message, &session->receiveHandle_be, 4, NULL); safeDistance += CryptoHeader_SIZE; } else { // 16 for the authenticator, 4 for the nonce and 4 for the handle safeDistance += 24; } Message_shift(message, safeDistance, NULL); if (dtHeader->switchHeader) { if (message->bytes != (uint8_t*)dtHeader->switchHeader) { Bits_memmoveConst(message->bytes, dtHeader->switchHeader, SwitchHeader_SIZE); dtHeader->switchHeader = (struct SwitchHeader*) message->bytes; } } else { dtHeader->switchHeader = (struct SwitchHeader*) message->bytes; Bits_memset(dtHeader->switchHeader, 0, SwitchHeader_SIZE); } Message_shift(message, -safeDistance, NULL); SwitchHeader_setVersion(dtHeader->switchHeader, SwitchHeader_CURRENT_VERSION); SwitchHeader_setLabelShift(dtHeader->switchHeader, 0); dtHeader->switchHeader->label_be = Endian_hostToBigEndian64(dtHeader->switchLabel); // This comes out in outgoingFromCryptoAuth() then sendToSwitch() dtHeader->receiveHandle = Endian_bigEndianToHost32(session->receiveHandle_be); dtHeader->layer = Ducttape_SessionLayer_OUTER; return Interface_sendMessage(session->internal, message); }
static void sendHello(void* vctx) { struct TUNTools_pvt* ctx = Identity_check((struct TUNTools_pvt*) vctx); struct Message* msg; Message_STACK(msg, 0, 64); Message_push(msg, "Hello World", 12, NULL); Message_push(msg, ctx->dest, ctx->dest->addrLen, NULL); Interface_sendMessage(&ctx->iface->generic, msg); }
static uint8_t sendMessage(struct Message* message, struct Interface* iface) { struct TUNInterface_Illumos_pvt* ctx = Identity_check((struct TUNInterface_Illumos_pvt*)iface); Message_shift(message, -4); uint16_t ethertype = ((uint16_t*) message->bytes)[-1]; if (ethertype != Ethernet_TYPE_IP6 && ethertype != Ethernet_TYPE_IP4) { Assert_true(!"Unsupported ethertype"); } return Interface_sendMessage(&ctx->pipe->iface, message); }
static uint8_t sendMessage(struct Message* msg, struct Interface* iface) { struct SessionManager_Session_pvt* ss = Identity_check((struct SessionManager_Session_pvt*)iface); uint64_t timeOfLastOut = ss->pub.timeOfLastOut; ss->pub.timeOfLastOut = Time_currentTimeMilliseconds(ss->sm->eventBase); int prevState = ss->pub.cryptoAuthState; ss->pub.cryptoAuthState = CryptoAuth_getState(ss->pub.internal); if ((ss->pub.timeOfLastOut - timeOfLastOut) > STATE_UPDATE_TIME || prevState != ss->pub.cryptoAuthState) { stateChange(ss, ss->pub.timeOfLastIn, timeOfLastOut, prevState); } return Interface_sendMessage(&ss->sm->iface, msg); }
static int sendResponse(struct Message* msg, struct Ethernet* eth, struct Headers_IP6Header* ip6, struct NDPServer_pvt* ns) { Bits_memcpyConst(ip6->destinationAddr, ip6->sourceAddr, 16); Bits_memcpyConst(ip6->sourceAddr, UNICAST_ADDR, 16); ip6->hopLimit = 255; struct NDPHeader_RouterAdvert* adv = (struct NDPHeader_RouterAdvert*) msg->bytes; adv->checksum = Checksum_icmp6(ip6->sourceAddr, msg->bytes, msg->length); Message_push(msg, ip6, sizeof(struct Headers_IP6Header), NULL); // Eth Message_push(msg, eth, sizeof(struct Ethernet), NULL); struct Ethernet* ethP = (struct Ethernet*) msg->bytes; Bits_memcpyConst(ethP->destAddr, eth->srcAddr, 6); Bits_memcpyConst(ethP->srcAddr, eth->destAddr, 6); printf("responding\n"); Interface_sendMessage(ns->wrapped, msg); return 1; }
int main(int argc, char** argv) { #ifdef Log_KEYS fprintf(stderr, "Log_LEVEL = KEYS, EXPECT TO SEE PRIVATE KEYS IN YOUR LOGS!\n"); #endif if (argc < 2) { // Fall through. } else if (!CString_strcmp("angel", argv[1])) { return AngelInit_main(argc, argv); } else if (!CString_strcmp("core", argv[1])) { return Core_main(argc, argv); } Assert_ifParanoid(argc > 0); struct Except* eh = NULL; // Allow it to allocate 8MB struct Allocator* allocator = MallocAllocator_new(1<<23); struct Random* rand = Random_new(allocator, NULL, eh); struct EventBase* eventBase = EventBase_new(allocator); if (argc == 2) { // one argument if ((CString_strcmp(argv[1], "--help") == 0) || (CString_strcmp(argv[1], "-h") == 0)) { return usage(allocator, argv[0]); } else if (CString_strcmp(argv[1], "--genconf") == 0) { return genconf(rand); } else if (CString_strcmp(argv[1], "--pidfile") == 0) { // deprecated fprintf(stderr, "'--pidfile' option is deprecated.\n"); return 0; } else if (CString_strcmp(argv[1], "--reconf") == 0) { // Performed after reading the configuration } else if (CString_strcmp(argv[1], "--bench") == 0) { return benchmark(); } else if ((CString_strcmp(argv[1], "--version") == 0) || (CString_strcmp(argv[1], "-v") == 0)) { printf("Cjdns protocol version: %d\n", Version_CURRENT_PROTOCOL); return 0; } else if (CString_strcmp(argv[1], "--cleanconf") == 0) { // Performed after reading configuration } else if (CString_strcmp(argv[1], "--nobg") == 0) { // Performed while reading configuration } else { fprintf(stderr, "%s: unrecognized option '%s'\n", argv[0], argv[1]); fprintf(stderr, "Try `%s --help' for more information.\n", argv[0]); return -1; } } else if (argc > 2) { // more than one argument? fprintf(stderr, "%s: too many arguments [%s]\n", argv[0], argv[1]); fprintf(stderr, "Try `%s --help' for more information.\n", argv[0]); // because of '--pidfile $filename'? if (CString_strcmp(argv[1], "--pidfile") == 0) { fprintf(stderr, "\n'--pidfile' option is deprecated.\n"); } return -1; } if (isatty(STDIN_FILENO)) { // We were started from a terminal // The chances an user wants to type in a configuration // bij hand are pretty slim so we show him the usage return usage(allocator, argv[0]); } else { // We assume stdin is a configuration file and that we should // start routing } struct Reader* stdinReader = FileReader_new(stdin, allocator); Dict config; if (JsonBencSerializer_get()->parseDictionary(stdinReader, allocator, &config)) { fprintf(stderr, "Failed to parse configuration.\n"); return -1; } if (argc == 2 && CString_strcmp(argv[1], "--cleanconf") == 0) { struct Writer* stdoutWriter = FileWriter_new(stdout, allocator); JsonBencSerializer_get()->serializeDictionary(stdoutWriter, &config); printf("\n"); return 0; } int forceNoBackground = 0; if (argc == 2 && CString_strcmp(argv[1], "--nobg") == 0) { forceNoBackground = 1; } struct Writer* logWriter = FileWriter_new(stdout, allocator); struct Log* logger = WriterLog_new(logWriter, allocator); // --------------------- Get Admin --------------------- // Dict* configAdmin = Dict_getDict(&config, String_CONST("admin")); String* adminPass = Dict_getString(configAdmin, String_CONST("password")); String* adminBind = Dict_getString(configAdmin, String_CONST("bind")); if (!adminPass) { adminPass = String_newBinary(NULL, 32, allocator); Random_base32(rand, (uint8_t*) adminPass->bytes, 32); adminPass->len = CString_strlen(adminPass->bytes); } if (!adminBind) { Except_throw(eh, "You must specify admin.bind in the cjdroute.conf file."); } // --------------------- Welcome to cjdns ---------------------- // char* archInfo = ArchInfo_describe(ArchInfo_detect(), allocator); char* sysInfo = SysInfo_describe(SysInfo_detect(), allocator); Log_info(logger, "Cjdns %s %s", archInfo, sysInfo); // --------------------- Check for running instance --------------------- // Log_info(logger, "Checking for running instance..."); checkRunningInstance(allocator, eventBase, adminBind, adminPass, logger, eh); // --------------------- Setup Pipes to Angel --------------------- // char angelPipeName[64] = "client-angel-"; Random_base32(rand, (uint8_t*)angelPipeName+13, 31); Assert_ifParanoid(EventBase_eventCount(eventBase) == 0); struct Pipe* angelPipe = Pipe_named(angelPipeName, eventBase, eh, allocator); Assert_ifParanoid(EventBase_eventCount(eventBase) == 2); angelPipe->logger = logger; char* args[] = { "angel", angelPipeName, NULL }; // --------------------- Spawn Angel --------------------- // String* privateKey = Dict_getString(&config, String_CONST("privateKey")); char* corePath = Process_getPath(allocator); if (!corePath) { Except_throw(eh, "Can't find a usable cjdns core executable, " "make sure it is in the same directory as cjdroute"); } if (!privateKey) { Except_throw(eh, "Need to specify privateKey."); } Log_info(logger, "Forking angel to background."); Process_spawn(corePath, args, eventBase, allocator); // --------------------- Get user for angel to setuid() ---------------------- // String* securityUser = NULL; List* securityConf = Dict_getList(&config, String_CONST("security")); for (int i = 0; securityConf && i < List_size(securityConf); i++) { securityUser = Dict_getString(List_getDict(securityConf, i), String_CONST("setuser")); if (securityUser) { int64_t* ea = Dict_getInt(List_getDict(securityConf, i), String_CONST("exemptAngel")); if (ea && *ea) { securityUser = NULL; } break; } } // --------------------- Pre-Configure Angel ------------------------- // Dict* preConf = Dict_new(allocator); Dict* adminPreConf = Dict_new(allocator); Dict_putDict(preConf, String_CONST("admin"), adminPreConf, allocator); Dict_putString(adminPreConf, String_CONST("core"), String_new(corePath, allocator), allocator); Dict_putString(preConf, String_CONST("privateKey"), privateKey, allocator); Dict_putString(adminPreConf, String_CONST("bind"), adminBind, allocator); Dict_putString(adminPreConf, String_CONST("pass"), adminPass, allocator); if (securityUser) { Dict_putString(adminPreConf, String_CONST("user"), securityUser, allocator); } Dict* logging = Dict_getDict(&config, String_CONST("logging")); if (logging) { Dict_putDict(preConf, String_CONST("logging"), logging, allocator); } struct Message* toAngelMsg = Message_new(0, 1024, allocator); BencMessageWriter_write(preConf, toAngelMsg, eh); Interface_sendMessage(&angelPipe->iface, toAngelMsg); Log_debug(logger, "Sent [%d] bytes to angel process", toAngelMsg->length); // --------------------- Get Response from Angel --------------------- // struct Message* fromAngelMsg = InterfaceWaiter_waitForData(&angelPipe->iface, eventBase, allocator, eh); Dict* responseFromAngel = BencMessageReader_read(fromAngelMsg, allocator, eh); // --------------------- Get Admin Addr/Port/Passwd --------------------- // Dict* responseFromAngelAdmin = Dict_getDict(responseFromAngel, String_CONST("admin")); adminBind = Dict_getString(responseFromAngelAdmin, String_CONST("bind")); if (!adminBind) { Except_throw(eh, "didn't get address and port back from angel"); } struct Sockaddr_storage adminAddr; if (Sockaddr_parse(adminBind->bytes, &adminAddr)) { Except_throw(eh, "Unable to parse [%s] as an ip address port, eg: 127.0.0.1:11234", adminBind->bytes); } // sanity check, Pipe_named() creates 2 events, see above. Assert_ifParanoid(EventBase_eventCount(eventBase) == 2); // --------------------- Configuration ------------------------- // Configurator_config(&config, &adminAddr.addr, adminPass, eventBase, logger, allocator); // --------------------- noBackground ------------------------ // int64_t* noBackground = Dict_getInt(&config, String_CONST("noBackground")); if (forceNoBackground || (noBackground && *noBackground)) { EventBase_beginLoop(eventBase); } //Allocator_free(allocator); return 0; }
static uint8_t sendMessage(struct Message* message, struct Interface* iface) { struct PacketHeaderToUDPAddrInterface_pvt* context = Identity_check((struct PacketHeaderToUDPAddrInterface_pvt*) iface); struct Sockaddr_storage ss; Message_pop(message, &ss, context->pub.addr->addrLen, NULL); struct Sockaddr* addr = &ss.addr; struct Headers_UDPHeader udp; udp.srcPort_be = Endian_hostToBigEndian16(Sockaddr_getPort(context->pub.addr)); udp.destPort_be = Endian_hostToBigEndian16(Sockaddr_getPort(addr)); udp.length_be = Endian_hostToBigEndian16(message->length + Headers_UDPHeader_SIZE); udp.checksum_be = 0; Message_push(message, &udp, sizeof(struct Headers_UDPHeader), NULL); struct Headers_IP6Header ip = { .nextHeader = 17, .hopLimit = 255, }; ip.payloadLength_be = Endian_hostToBigEndian16(message->length); Headers_setIpVersion(&ip); uint8_t* addrPtr = NULL; Assert_true(Sockaddr_getAddress(addr, &addrPtr) == 16); Bits_memcpyConst(ip.destinationAddr, addrPtr, 16); Assert_true(Sockaddr_getAddress(context->pub.addr, &addrPtr) == 16); Bits_memcpyConst(ip.sourceAddr, addrPtr, 16); uint16_t checksum = Checksum_udpIp6(ip.sourceAddr, message->bytes, message->length); ((struct Headers_UDPHeader*)message->bytes)->checksum_be = checksum; Message_push(message, &ip, sizeof(struct Headers_IP6Header), NULL); return Interface_sendMessage(context->wrapped, message); } static uint8_t receiveMessage(struct Message* message, struct Interface* iface) { struct PacketHeaderToUDPAddrInterface_pvt* context = Identity_check((struct PacketHeaderToUDPAddrInterface_pvt*) iface->receiverContext); if (message->length < Headers_IP6Header_SIZE + Headers_UDPHeader_SIZE) { // runt return Error_NONE; } struct Headers_IP6Header* ip = (struct Headers_IP6Header*) message->bytes; // udp if (ip->nextHeader != 17) { return Error_NONE; } struct Allocator* alloc = Allocator_child(message->alloc); struct Sockaddr* addr = Sockaddr_clone(context->pub.addr, alloc); uint8_t* addrPtr = NULL; Assert_true(Sockaddr_getAddress(addr, &addrPtr) == 16); Bits_memcpyConst(addrPtr, ip->sourceAddr, 16); struct Headers_UDPHeader* udp = (struct Headers_UDPHeader*) (&ip[1]); Sockaddr_setPort(addr, Endian_bigEndianToHost16(udp->srcPort_be)); if (Sockaddr_getPort(context->pub.addr) != Endian_bigEndianToHost16(udp->destPort_be)) { // not the right port return Error_NONE; } Message_shift(message, -(Headers_IP6Header_SIZE + Headers_UDPHeader_SIZE), NULL); Message_push(message, addr, addr->addrLen, NULL); return Interface_receiveMessage(&context->pub.generic, message); } struct AddrInterface* PacketHeaderToUDPAddrInterface_new(struct Interface* toWrap, struct Allocator* alloc, struct Sockaddr* addr) { struct PacketHeaderToUDPAddrInterface_pvt* context = Allocator_malloc(alloc, sizeof(struct PacketHeaderToUDPAddrInterface_pvt)); Bits_memcpyConst(context, (&(struct PacketHeaderToUDPAddrInterface_pvt) { .pub = { .generic = { .sendMessage = sendMessage, .senderContext = context, .allocator = alloc } }, .wrapped = toWrap }), sizeof(struct PacketHeaderToUDPAddrInterface_pvt));
/** @return a string representing the address and port to connect to. */ static void initAngel(struct Pipe* asClientPipe, struct Interface* asCoreIface, char* asCorePipeName, struct EventBase* eventBase, struct Log* logger, struct Allocator* alloc, struct Random* rand) { Dict admin = Dict_CONST( String_CONST("bind"), String_OBJ(String_CONST("127.0.0.1")), Dict_CONST( String_CONST("corePipeName"), String_OBJ(String_CONST(asCorePipeName)), Dict_CONST( String_CONST("pass"), String_OBJ(String_CONST("abcd")), NULL ))); Dict message = Dict_CONST( String_CONST("admin"), Dict_OBJ(&admin), NULL ); struct Allocator* tempAlloc = Allocator_child(alloc); #define BUFFER_SZ 1023 uint8_t buff[BUFFER_SZ + 1] = {0}; struct Writer* w = ArrayWriter_new(buff, BUFFER_SZ, tempAlloc); StandardBencSerializer_get()->serializeDictionary(w, &message); struct Message* toAngel = Allocator_malloc(tempAlloc, sizeof(struct Message) + w->bytesWritten); toAngel->bytes = (uint8_t*) (&toAngel[1]); toAngel->length = toAngel->capacity = w->bytesWritten; toAngel->padding = 0; toAngel->alloc = tempAlloc; Bits_memcpy(toAngel->bytes, buff, toAngel->length); Log_info(logger, "Writing intial configuration to angel on [%s] config: [%s]", asClientPipe->name, buff); Interface_sendMessage(&asClientPipe->iface, toAngel); // This is client->angel->core data, we can throw this away. //struct Message* angelToCore = InterfaceWaiter_waitForData(asCoreIface, eventBase, tempAlloc, NULL); // unterminated string //Log_info(logger, "Init message from angel to core: [%s]", angelToCore->bytes); // Send response on behalf of core. char* coreToAngelResponse = " PADDING " "d" "5:error" "4:none" "e"; struct Message* m = &(struct Message) { .bytes = (uint8_t*) coreToAngelResponse, .length = strlen(coreToAngelResponse), .padding = 0, .capacity = strlen(coreToAngelResponse) }; Message_shift(m, -24, NULL); m = Message_clone(m, tempAlloc); Interface_sendMessage(asCoreIface, m); // This is angel->client data, it will tell us which port was bound. struct Message* angelToClient = InterfaceWaiter_waitForData(&asClientPipe->iface, eventBase, tempAlloc, NULL); printf("Response from angel to client: [%s]\n", angelToClient->bytes); Allocator_free(tempAlloc); return; }
static uint8_t sendMessage(struct Message* msg, struct Interface* iface) { struct Aligner_pvt* al = Identity_check((struct Aligner_pvt*)iface); alignMessage(msg, al->alignmentBytes); return Interface_sendMessage(al->wrapped, msg); }
static int tryRouterSolicitation(struct Message* msg, struct Ethernet* eth, struct Headers_IP6Header* ip6, struct NDPServer_pvt* ns) { if (msg->length < NDPHeader_RouterSolicitation_SIZE) { return 0; } struct NDPHeader_RouterSolicitation* sol = (struct NDPHeader_RouterSolicitation*)msg->bytes; if (sol->oneThirtyThree != 133 || sol->zero != 0) { printf("wrong type/code for router solicitation\n"); return 0; } if (ns->pub.prefixLen < 1 || ns->pub.prefixLen > 128) { printf("address prefix not set\n"); return 0; } if (Bits_memcmp(ip6->destinationAddr, UNICAST_ADDR, 16) && Bits_memcmp(ip6->destinationAddr, ALL_ROUTERS, 16)) { printf("wrong address for router solicitation\n"); return 0; } // now we're committed. Message_shift(msg, -msg->length, NULL); // Prefix option struct NDPHeader_RouterAdvert_PrefixOpt prefix = { .three = 3, .four = 4, .bits = 0, .validLifetimeSeconds_be = 0xffffffffu, .preferredLifetimeSeconds_be = 0xffffffffu, .reservedTwo = 0 }; Bits_memcpyConst(prefix.prefix, ns->pub.advertisePrefix, 16); prefix.prefixLen = ns->pub.prefixLen; Message_push(msg, &prefix, sizeof(struct NDPHeader_RouterAdvert_PrefixOpt), NULL); // NDP message struct NDPHeader_RouterAdvert adv = { .oneThirtyFour = 134, .zero = 0, .checksum = 0, .currentHopLimit = 0, .bits = 0, .routerLifetime_be = Endian_hostToBigEndian16(10), .reachableTime_be = 0, .retransTime_be = 0 }; Message_push(msg, &adv, sizeof(struct NDPHeader_RouterAdvert), NULL); sendResponse(msg, eth, ip6, ns); return 1; } static int tryNeighborSolicitation(struct Message* msg, struct Ethernet* eth, struct Headers_IP6Header* ip6, struct NDPServer_pvt* ns) { if (msg->length < NDPHeader_RouterSolicitation_SIZE) { return 0; } struct NDPHeader_NeighborSolicitation* sol = (struct NDPHeader_NeighborSolicitation*)msg->bytes; if (sol->oneThirtyFive != 135 || sol->zero != 0) { printf("wrong type/code for neighbor solicitation\n"); return 0; } if (Bits_memcmp(ip6->destinationAddr, UNICAST_ADDR, 16) && Bits_memcmp(ip6->destinationAddr, MULTICAST_ADDR, 13)) { printf("wrong address for neighbor solicitation\n"); return 0; } // now we're committed. Message_shift(msg, -msg->length, NULL); struct NDPHeader_NeighborAdvert_MacOpt macOpt = { .two = 2, .one = 1 }; Bits_memcpyConst(macOpt.mac, eth->destAddr, 6); Message_push(msg, &macOpt, sizeof(struct NDPHeader_NeighborAdvert_MacOpt), NULL); struct NDPHeader_NeighborAdvert na = { .oneThirtySix = 136, .zero = 0, .checksum = 0, .bits = NDPHeader_NeighborAdvert_bits_ROUTER | NDPHeader_NeighborAdvert_bits_SOLICITED | NDPHeader_NeighborAdvert_bits_OVERRIDE }; Bits_memcpyConst(na.targetAddr, UNICAST_ADDR, 16); Message_push(msg, &na, sizeof(struct NDPHeader_NeighborAdvert), NULL); sendResponse(msg, eth, ip6, ns); return 1; } static uint8_t receiveMessage(struct Message* msg, struct Interface* iface) { struct NDPServer_pvt* ns = Identity_cast((struct NDPServer_pvt*)iface->receiverContext); if (msg->length < Ethernet_SIZE + Headers_IP6Header_SIZE) { return Interface_receiveMessage(&ns->pub.generic, msg); } struct Ethernet* eth = (struct Ethernet*) msg->bytes; struct Headers_IP6Header* ip6 = (struct Headers_IP6Header*) (ð[1]); if (eth->ethertype != Ethernet_TYPE_IP6 || ip6->nextHeader != 58 /* ICMPv6 */) { return Interface_receiveMessage(&ns->pub.generic, msg); } // store the eth and ip6 headers so they don't get clobbered struct Ethernet storedEth; Message_pop(msg, &storedEth, sizeof(struct Ethernet), NULL); struct Headers_IP6Header storedIp6; Message_pop(msg, &storedIp6, sizeof(struct Headers_IP6Header), NULL); if (!tryNeighborSolicitation(msg, &storedEth, &storedIp6, ns) && !tryRouterSolicitation(msg, &storedEth, &storedIp6, ns)) { Message_push(msg, &storedIp6, sizeof(struct Headers_IP6Header), NULL); Message_push(msg, &storedEth, sizeof(struct Ethernet), NULL); return Interface_receiveMessage(&ns->pub.generic, msg); } // responding happens in sendResponse.. return 0; } static uint8_t sendMessage(struct Message* msg, struct Interface* iface) { struct NDPServer_pvt* ns = Identity_cast((struct NDPServer_pvt*)iface); return Interface_sendMessage(ns->wrapped, msg); } struct NDPServer* NDPServer_new(struct Interface* external, struct Allocator* alloc) { struct NDPServer_pvt* out = Allocator_calloc(alloc, sizeof(struct NDPServer_pvt), 1); out->wrapped = external; Identity_set(out); InterfaceWrapper_wrap(external, sendMessage, receiveMessage, &out->pub.generic); return &out->pub; }
/** * Input: * { * "admin": { * "core": "/path/to/core/binary", * "bind": "127.0.0.1:12345", * "pass": "******", * "user": "******" * } * } * for example: * d5:admind4:core30:./build/admin/angel/cjdns-core4:bind15:127.0.0.1:123454:pass4:abcdee * * Pre-existing core mode: * { * "admin": { * "core": { * "fromCore": 12, * "toCore": 14 * }, * "bind": "127.0.0.1:12345", * "pass": "******", * "user": "******" * } * } * * If "core" is a dictionary, the angel will behave as though the core is already spawned and * it will read from the core on the file descriptor given by "fromCore" and write to the file * given by "toCore". * * "user" is optional, if set the angel will setuid() that user's uid. */ int AngelInit_main(int argc, char** argv) { struct Except* eh = NULL; struct Allocator* alloc = MallocAllocator_new(1<<21); struct Writer* logWriter = FileWriter_new(stdout, alloc); struct Log* logger = WriterLog_new(logWriter, alloc); struct Random* rand = Random_new(alloc, logger, eh); MallocAllocator_setCanary(alloc, (long)Random_int64(rand)); struct Allocator* tempAlloc = Allocator_child(alloc); struct EventBase* eventBase = EventBase_new(alloc); struct Pipe* clientPipe = getClientPipe(argc, argv, eventBase, eh, alloc); clientPipe->logger = logger; Log_debug(logger, "Getting pre-configuration from client"); struct Message* preConf = InterfaceWaiter_waitForData(&clientPipe->iface, eventBase, alloc, eh); Log_debug(logger, "Finished getting pre-configuration from client"); struct Reader* reader = ArrayReader_new(preConf->bytes, preConf->length, tempAlloc); Dict config; if (StandardBencSerializer_get()->parseDictionary(reader, tempAlloc, &config)) { Except_raise(eh, -1, "Failed to parse configuration."); } Dict* admin = Dict_getDict(&config, String_CONST("admin")); String* core = Dict_getString(admin, String_CONST("core")); String* bind = Dict_getString(admin, String_CONST("bind")); String* pass = Dict_getString(admin, String_CONST("pass")); String* user = Dict_getString(admin, String_CONST("user")); String* corePipeName = Dict_getString(admin, String_CONST("corePipeName")); if (!bind || !pass || (!core && !corePipeName)) { Except_raise(eh, -1, "missing configuration params in preconfig. [%s]", preConf->bytes); } if (!corePipeName) { char name[32] = {0}; Random_base32(rand, (uint8_t*)name, 31); corePipeName = String_new(name, tempAlloc); } struct Pipe* corePipe = Pipe_named(corePipeName->bytes, eventBase, eh, alloc); corePipe->logger = logger; corePipe->onClose = coreDied; struct Interface* coreIface = FramingInterface_new(65535, &corePipe->iface, alloc); if (core) { Log_info(logger, "Initializing core [%s]", core->bytes); initCore(core->bytes, corePipeName, eventBase, alloc, eh); } Log_debug(logger, "Sending pre-configuration to core."); sendConfToCore(coreIface, tempAlloc, &config, eh, logger); struct Message* coreResponse = InterfaceWaiter_waitForData(coreIface, eventBase, tempAlloc, eh); Interface_sendMessage(&clientPipe->iface, coreResponse); #ifdef Log_KEYS uint8_t lastChar = coreResponse->bytes[coreResponse->length-1]; coreResponse->bytes[coreResponse->length-1] = 0; Log_keys(logger, "Sent [%s%c] to client.", coreResponse->bytes, lastChar); coreResponse->bytes[coreResponse->length-1] = lastChar; #endif if (user) { setUser(user->bytes, logger, eh); } Allocator_free(tempAlloc); Angel_start(coreIface, eventBase, logger, alloc); return 0; }
uint32_t handle = hermes->requestSet.handles[index]; req->handle = handle; uint8_t handleHex[9]; Hex_encode(handleHex, 9, (uint8_t*)&handle, 4); Dict_putString(message, String_CONST("txid"), String_CONST((char*)handleHex), reqAlloc); struct Message* m = Message_new(0, 1024, reqAlloc); BencMessageWriter_write(message, m, eh); // Remove the txid string so there is not a dangling pointer in the message. Dict_remove(message, String_CONST("txid")); Log_debug(hermes->logger, "Sending [%d] bytes to angel", m->length); int ret = Interface_sendMessage(hermes->iface, m); if (ret) { Except_throw(eh, "Failed to send message to angel [%d]", ret); } // Use interval as defensive programming // the Allocator_free() in the timeout callback deactivates it. Timeout_setInterval(timeout, req, REQ_TIMEOUT, hermes->eventBase, reqAlloc); } struct Hermes* Hermes_new(struct Interface* angelIface, struct EventBase* eventBase, struct Log* logger, struct Allocator* alloc) { struct Hermes* out = Allocator_clone(alloc, (&(struct Hermes) {