static void initTunfd(Dict* args, void* vcontext, String* txid, struct Allocator* requestAlloc) { struct Context* ctx = Identity_check((struct Context*) vcontext); struct Jmp jmp; Jmp_try(jmp) { int64_t* tunfd = Dict_getInt(args, String_CONST("tunfd")); int64_t* tuntype = Dict_getInt(args, String_CONST("type")); if (!tunfd || *tunfd < 0) { String* error = String_printf(requestAlloc, "Invalid tunfd"); sendResponse(error, ctx->admin, txid, requestAlloc); return; } int fileno = *tunfd; int type = (*tuntype) ? *tuntype : FileNo_Type_NORMAL; struct Pipe* p = Pipe_forFiles(fileno, fileno, ctx->base, &jmp.handler, ctx->alloc); p->logger = ctx->logger; if (type == FileNo_Type_ANDROID) { struct AndroidWrapper* aw = AndroidWrapper_new(ctx->alloc, ctx->logger); Iface_plumb(&aw->externalIf, &p->iface); Iface_plumb(&aw->internalIf, &ctx->nc->tunAdapt->tunIf); } else { Iface_plumb(&p->iface, &ctx->nc->tunAdapt->tunIf); } sendResponse(String_CONST("none"), ctx->admin, txid, requestAlloc); } Jmp_catch { String* error = String_printf(requestAlloc, "Failed to configure tunnel [%s]", jmp.message); sendResponse(error, ctx->admin, txid, requestAlloc); return; } }
void Core_init(struct Allocator* alloc, struct Log* logger, struct EventBase* eventBase, uint8_t privateKey[32], struct Admin* admin, struct Random* rand, struct Except* eh, struct FakeNetwork* fakeNet, bool noSec) { struct Security* sec = NULL; if (!noSec) { sec = Security_new(alloc, logger, eventBase); } struct NetCore* nc = NetCore_new(privateKey, alloc, eventBase, rand, logger); struct IpTunnel* ipTunnel = IpTunnel_new(logger, eventBase, alloc, rand); Iface_plumb(&nc->tunAdapt->ipTunnelIf, &ipTunnel->tunInterface); Iface_plumb(&nc->upper->ipTunnelIf, &ipTunnel->nodeInterface); // The link between the Pathfinder and the core needs to be asynchronous. struct Pathfinder* pf = Pathfinder_register(alloc, logger, eventBase, rand, admin); struct ASynchronizer* pfAsync = ASynchronizer_new(alloc, eventBase, logger); Iface_plumb(&pfAsync->ifA, &pf->eventIf); EventEmitter_regPathfinderIface(nc->ee, &pfAsync->ifB); // ------------------- Register RPC functions ----------------------- // InterfaceController_admin_register(nc->ifController, admin, alloc); SwitchPinger_admin_register(nc->sp, admin, alloc); UDPInterface_admin_register(eventBase, alloc, logger, admin, nc->ifController, fakeNet); #ifdef HAS_ETH_INTERFACE ETHInterface_admin_register(eventBase, alloc, logger, admin, nc->ifController); #endif AuthorizedPasswords_init(admin, nc->ca, alloc); Admin_registerFunction("ping", adminPing, admin, false, NULL, admin); if (!noSec) { Security_admin_register(alloc, logger, sec, admin); } IpTunnel_admin_register(ipTunnel, admin, alloc); SessionManager_admin_register(nc->sm, admin, alloc); Allocator_admin_register(alloc, admin); struct Context* ctx = Allocator_calloc(alloc, sizeof(struct Context), 1); Identity_set(ctx); ctx->alloc = alloc; ctx->admin = admin; ctx->logger = logger; ctx->base = eventBase; ctx->ipTunnel = ipTunnel; ctx->nc = nc; Admin_registerFunction("Core_exit", adminExit, ctx, true, NULL, admin); Admin_registerFunction("Core_pid", adminPid, admin, false, NULL, admin); Admin_registerFunction("Core_initTunnel", initTunnel, ctx, true, ((struct Admin_FunctionArg[]) { { .name = "desiredTunName", .required = 0, .type = "String" } }), admin);
void TestFramework_linkNodes(struct TestFramework* client, struct TestFramework* server, bool beacon) { // ifaceA is the client, ifaceB is the server struct TestFramework_Link* link = Allocator_calloc(client->alloc, sizeof(struct TestFramework_Link), 1); Identity_set(link); link->clientIf.send = sendClient; link->serverIf.send = sendServer; link->client = client; link->server = server; struct InterfaceController_Iface* clientIci = InterfaceController_newIface( client->nc->ifController, String_CONST("client"), client->alloc); link->clientIfNum = clientIci->ifNum; Iface_plumb(&link->clientIf, &clientIci->addrIf); struct InterfaceController_Iface* serverIci = InterfaceController_newIface( server->nc->ifController, String_CONST("server"), server->alloc); link->serverIfNum = serverIci->ifNum; Iface_plumb(&link->serverIf, &serverIci->addrIf); if (beacon) { int ret = InterfaceController_beaconState(client->nc->ifController, link->clientIfNum, InterfaceController_beaconState_newState_ACCEPT); Assert_true(!ret); ret = InterfaceController_beaconState(server->nc->ifController, link->serverIfNum, InterfaceController_beaconState_newState_SEND); Assert_true(!ret); } else { // Except that it has an authorizedPassword added. CryptoAuth_addUser(String_CONST("abcdefg123"), String_CONST("TEST"), server->nc->ca); // Client has pubKey and passwd for the server. InterfaceController_bootstrapPeer(client->nc->ifController, link->clientIfNum, server->publicKey, Sockaddr_LOOPBACK, String_CONST("abcdefg123"), NULL, NULL, client->alloc); } }
static void initTunnel2(String* desiredDeviceName, struct Context* ctx, uint8_t addressPrefix, struct Except* eh) { Log_debug(ctx->logger, "Initializing TUN device [%s]", (desiredDeviceName) ? desiredDeviceName->bytes : "<auto>"); char assignedTunName[TUNInterface_IFNAMSIZ]; char* desiredName = (desiredDeviceName) ? desiredDeviceName->bytes : NULL; struct Iface* tun = TUNInterface_new( desiredName, assignedTunName, 0, ctx->base, ctx->logger, eh, ctx->alloc); Iface_plumb(tun, &ctx->nc->tunAdapt->tunIf); IpTunnel_setTunName(assignedTunName, ctx->ipTunnel); struct Sockaddr* myAddr = Sockaddr_fromBytes(ctx->nc->myAddress->ip6.bytes, Sockaddr_AF_INET6, ctx->alloc); myAddr->prefix = addressPrefix; myAddr->flags |= Sockaddr_flags_PREFIX; NetDev_addAddress(assignedTunName, myAddr, ctx->logger, eh); NetDev_setMTU(assignedTunName, DEFAULT_MTU, ctx->logger, eh); }
static void newInterface2(struct Context* ctx, struct Sockaddr* addr, String* txid, struct Allocator* requestAlloc) { struct Allocator* const alloc = Allocator_child(ctx->alloc); struct UDPAddrIface* udpIf = NULL; struct Jmp jmp; Jmp_try(jmp) { udpIf = UDPAddrIface_new(ctx->eventBase, addr, alloc, &jmp.handler, ctx->logger); } Jmp_catch { String* errStr = String_CONST(jmp.message); Dict out = Dict_CONST(String_CONST("error"), String_OBJ(errStr), NULL); Admin_sendMessage(&out, txid, ctx->admin); Allocator_free(alloc); return; } struct AddrIface* ai = ctx->udpIf = &udpIf->generic; struct InterfaceController_Iface* ici = InterfaceController_newIface(ctx->ic, String_CONST("UDP"), alloc); Iface_plumb(&ici->addrIf, &ai->iface); Dict* out = Dict_new(requestAlloc); Dict_putString(out, String_CONST("error"), String_CONST("none"), requestAlloc); Dict_putInt(out, String_CONST("interfaceNumber"), ici->ifNum, requestAlloc); char* printedAddr = Sockaddr_print(ai->addr, requestAlloc); Dict_putString(out, String_CONST("bindAddress"), String_CONST(printedAddr), requestAlloc); Admin_sendMessage(out, txid, ctx->admin); }
struct TAPWrapper* TAPWrapper_new(struct Iface* external, struct Log* log, struct Allocator* alloc) { struct TAPWrapper_pvt* out = Allocator_calloc(alloc, sizeof(struct TAPWrapper_pvt), 1); Identity_set(out); out->log = log; out->external.send = receiveMessage; out->pub.internal.send = sendMessage; Iface_plumb(external, &out->external); return &out->pub; }
static void start(struct Allocator* alloc, struct Log* logger, struct EventBase* base, struct Random* rand, RunTest* runTest) { struct TestFramework* a = TestFramework_setUp("\xad\x7e\xa3\x26\xaa\x01\x94\x0a\x25\xbc\x9e\x01\x26\x22\xdb\x69" "\x4f\xd9\xb4\x17\x7c\xf3\xf8\x91\x16\xf3\xcf\xe8\x5c\x80\xe1\x4a", alloc, base, rand, logger); //"publicKey": "kmzm4w0kj9bswd5qmx74nu7kusv5pj40vcsmp781j6xxgpd59z00.k", //"ipv6": "fc41:94b5:0925:7ba9:3959:11ab:a006:367a", struct TestFramework* b = TestFramework_setUp("\xd8\x54\x3e\x70\xb9\xae\x7c\x41\xbc\x18\xa4\x9a\x9c\xee\xca\x9c" "\xdc\x45\x01\x96\x6b\xbd\x7e\x76\xcf\x3a\x9f\xbc\x12\xed\x8b\xb4", alloc, base, rand, logger); //"publicKey": "vz21tg07061s8v9mckrvgtfds7j2u5lst8cwl6nqhp81njrh5wg0.k", //"ipv6": "fc1f:5b96:e1c5:625d:afde:2523:a7fa:383a", struct TwoNodes* out = Allocator_calloc(alloc, sizeof(struct TwoNodes), 1); Identity_set(out); out->tunB.send = incomingTunB; out->tunA.send = incomingTunA; Iface_plumb(&out->tunB, b->tunIf); Iface_plumb(&out->tunA, a->tunIf); out->nodeB = b; out->nodeA = a; out->logger = logger; out->checkLinkageTimeout = Timeout_setInterval(checkLinkage, out, 1, base, alloc); out->base = base; out->startTime = Time_currentTimeMilliseconds(base); out->runTest = runTest; Log_debug(a->logger, "Waiting for nodes to link asynchronously..."); }
void TUNTools_echoTest(struct Sockaddr* udpBindTo, struct Sockaddr* tunDestAddr, TUNTools_Callback tunMessageHandler, struct Iface* tun, struct EventBase* base, struct Log* logger, struct Allocator* allocator) { struct Allocator* alloc = Allocator_child(allocator); struct AddrIface* udp = setupUDP(base, udpBindTo, alloc, logger); struct Sockaddr* dest = Sockaddr_clone(udp->addr, alloc); uint8_t* tunDestAddrBytes = NULL; uint8_t* udpDestPointer = NULL; int len = Sockaddr_getAddress(dest, &udpDestPointer); Assert_true(len && len == Sockaddr_getAddress(tunDestAddr, &tunDestAddrBytes)); Bits_memcpy(udpDestPointer, tunDestAddrBytes, len); struct TUNTools_pvt* ctx = Allocator_calloc(alloc, sizeof(struct TUNTools_pvt), 1); Identity_set(ctx); ctx->pub.udpIface.send = receiveMessageUDP; ctx->pub.tunIface.send = receiveMessageTUN; Iface_plumb(&ctx->pub.udpIface, &udp->iface); Iface_plumb(&ctx->pub.tunIface, tun); ctx->pub.cb = tunMessageHandler; ctx->pub.tunDestAddr = Sockaddr_clone(dest, alloc); ctx->pub.udpBindTo = Sockaddr_clone(udpBindTo, alloc); ctx->pub.alloc = alloc; ctx->pub.log = logger; ctx->pub.base = base; Timeout_setInterval(sendHello, ctx, 1000, base, alloc); Timeout_setTimeout(fail, NULL, 10000, base, alloc); EventBase_beginLoop(base); }
struct TestFramework* TestFramework_setUp(char* privateKey, struct Allocator* allocator, struct EventBase* base, struct Random* rand, struct Log* logger) { if (!logger) { struct Writer* logwriter = FileWriter_new(stdout, allocator); logger = WriterLog_new(logwriter, allocator); } if (!rand) { rand = Random_new(allocator, logger, NULL); } if (!base) { base = EventBase_new(allocator); } uint64_t pks[4]; if (!privateKey) { Random_longs(rand, pks, 4); privateKey = (char*)pks; } struct NetCore* nc = NetCore_new(privateKey, allocator, base, rand, logger); struct Pathfinder* pf = Pathfinder_register(allocator, logger, base, rand, NULL); struct ASynchronizer* pfAsync = ASynchronizer_new(allocator, base, logger); Iface_plumb(&pfAsync->ifA, &pf->eventIf); EventEmitter_regPathfinderIface(nc->ee, &pfAsync->ifB); struct TestFramework* tf = Allocator_calloc(allocator, sizeof(struct TestFramework), 1); Identity_set(tf); tf->alloc = allocator; tf->rand = rand; tf->eventBase = base; tf->logger = logger; tf->nc = nc; tf->tunIf = &nc->tunAdapt->tunIf; tf->publicKey = nc->myAddress->key; tf->ip = nc->myAddress->ip6.bytes; tf->pathfinder = pf; return tf; }
void EventEmitter_regPathfinderIface(struct EventEmitter* emitter, struct Iface* iface) { struct EventEmitter_pvt* ee = Identity_check((struct EventEmitter_pvt*) emitter); struct Allocator* alloc = Allocator_child(ee->alloc); struct Pathfinder* pf = Allocator_calloc(alloc, sizeof(struct Pathfinder), 1); pf->ee = ee; pf->iface.send = incomingFromPathfinder; pf->alloc = alloc; Iface_plumb(&pf->iface, iface); Identity_set(pf); int i = 0; for (; i < ee->pathfinders->length; i++) { struct Pathfinder* xpf = ArrayList_Pathfinders_get(ee->pathfinders, i); if (!xpf) { break; } } pf->pathfinderId = ArrayList_Pathfinders_put(ee->pathfinders, i, pf); }
struct NetCore* NetCore_new(uint8_t* privateKey, struct Allocator* allocator, struct EventBase* base, struct Random* rand, struct Log* log) { struct Allocator* alloc = Allocator_child(allocator); struct NetCore* nc = Allocator_calloc(alloc, sizeof(struct NetCore), 1); nc->alloc = alloc; nc->base = base; nc->rand = rand; nc->log = log; struct CryptoAuth* ca = nc->ca = CryptoAuth_new(alloc, privateKey, base, log, rand); struct EventEmitter* ee = nc->ee = EventEmitter_new(alloc, log, ca->publicKey); struct Address* myAddress = nc->myAddress = Allocator_calloc(alloc, sizeof(struct Address), 1); Bits_memcpy(myAddress->key, ca->publicKey, 32); Address_getPrefix(myAddress); myAddress->protocolVersion = Version_CURRENT_PROTOCOL; myAddress->path = 1; // lower half struct SwitchCore* switchCore = nc->switchCore = SwitchCore_new(log, alloc, base); struct SwitchAdapter* switchAdapter = nc->switchAdapter = SwitchAdapter_new(alloc, log); Iface_plumb(&switchAdapter->switchIf, switchCore->routerIf); struct ControlHandler* controlHandler = nc->controlHandler = ControlHandler_new(alloc, log, ee, ca->publicKey); Iface_plumb(&controlHandler->coreIf, &switchAdapter->controlIf); struct SwitchPinger* sp = nc->sp = SwitchPinger_new(base, rand, log, myAddress, alloc); Iface_plumb(&controlHandler->switchPingerIf, &sp->controlHandlerIf); nc->ifController = InterfaceController_new(ca, switchCore, log, base, sp, rand, alloc, ee); // session manager struct SessionManager* sm = nc->sm = SessionManager_new(alloc, base, ca, rand, log, ee); Iface_plumb(&switchAdapter->sessionManagerIf, &sm->switchIf); // upper half struct UpperDistributor* upper = nc->upper = UpperDistributor_new(alloc, log, ee, myAddress); Iface_plumb(&sm->insideIf, &upper->sessionManagerIf); struct TUNAdapter* tunAdapt = nc->tunAdapt = TUNAdapter_new(alloc, log, myAddress->ip6.bytes); Iface_plumb(&tunAdapt->upperDistributorIf, &upper->tunAdapterIf); return nc; }
struct Iface* TUNInterface_new(const char* interfaceName, char assignedInterfaceName[TUNInterface_IFNAMSIZ], int isTapMode, struct EventBase* base, struct Log* logger, struct Except* eh, struct Allocator* alloc) { char deviceFile[TUNInterface_IFNAMSIZ]; if (isTapMode) { Except_throw(eh, "tap mode not supported on this platform"); } // We are on FreeBSD so we just need to read /dev/tunxx to create the tun interface if (interfaceName) { snprintf(deviceFile,TUNInterface_IFNAMSIZ,"/dev/%s",interfaceName); } else { snprintf(deviceFile,TUNInterface_IFNAMSIZ,"%s","/dev/tun"); } // Open the descriptor int tunFd = open(deviceFile, O_RDWR); //Get the resulting device name const char* assignedDevname; assignedDevname = fdevname(tunFd); // Extract the number eg: 0 from tun0 int ppa = 0; for (uint32_t i = 0; i < strlen(assignedDevname); i++) { if (isdigit(assignedDevname[i])) { ppa = atoi(assignedDevname+i); break; } } if (tunFd < 0 || ppa < 0 ) { int err = errno; close(tunFd); char* error = NULL; if (tunFd < 0) { error = "open(\"/dev/tun\")"; } else if (ppa < 0) { error = "fdevname/getting number from fdevname"; } Except_throw(eh, "%s [%s]", error, strerror(err)); } // Since devices are numbered rather than named, it's not possible to have tun0 and cjdns0 // so we'll skip the pretty names and call everything tunX if (assignedInterfaceName) { snprintf(assignedInterfaceName, TUNInterface_IFNAMSIZ, "tun%d", ppa); } char* error = NULL; // We want to send IPv6 through our tun device, so we need to be able to specify "ethertype" int tunhead = 1; if (ioctl(tunFd,TUNSIFHEAD,&tunhead) == -1) { error = "TUNSIFHEAD"; } if (error) { int err = errno; close(tunFd); Except_throw(eh, "%s [%s]", error, strerror(err)); } struct Pipe* p = Pipe_forFiles(tunFd, tunFd, base, eh, alloc); struct BSDMessageTypeWrapper* bmtw = BSDMessageTypeWrapper_new(alloc, logger); Iface_plumb(&p->iface, &bmtw->wireSide); return &bmtw->inside; }
static void testAddr(struct Context* ctx, char* addr4, int prefix4, int alloc4, char* addr6, int prefix6, int alloc6) { struct Allocator* alloc = Allocator_child(ctx->alloc); struct IpTunnel* ipTun = IpTunnel_new(ctx->log, ctx->base, alloc, ctx->rand, NULL); struct Sockaddr* sa4 = NULL; struct Sockaddr_storage ip6ToGive; struct Sockaddr_storage ip4ToGive; if (addr4) { Assert_true(!Sockaddr_parse(addr4, &ip4ToGive)); sa4 = &ip4ToGive.addr; Assert_true(Sockaddr_getFamily(sa4) == Sockaddr_AF_INET); } struct Sockaddr* sa6 = NULL; if (addr6) { Assert_true(!Sockaddr_parse(addr6, &ip6ToGive)); sa6 = &ip6ToGive.addr; Assert_true(Sockaddr_getFamily(sa6) == Sockaddr_AF_INET6); } IpTunnel_allowConnection(ctx->pubKey, sa6, prefix6, alloc6, sa4, prefix4, alloc4, ipTun); struct Message* msg = Message_new(64, 512, alloc); const char* requestForAddresses = "d" "1:q" "21:IpTunnel_getAddresses" "4:txid" "4:abcd" "e"; CString_strcpy(msg->bytes, requestForAddresses); msg->length = CString_strlen(requestForAddresses); Message_push(msg, NULL, Headers_UDPHeader_SIZE, NULL); struct Headers_UDPHeader* uh = (struct Headers_UDPHeader*) msg->bytes; uh->length_be = Endian_hostToBigEndian16(msg->length - Headers_UDPHeader_SIZE); uint16_t* checksum = &((struct Headers_UDPHeader*) msg->bytes)->checksum_be; *checksum = 0; uint32_t length = msg->length; // Because of old reasons, we need to have at least an empty IPv6 header Message_push(msg, NULL, Headers_IP6Header_SIZE, NULL); struct Headers_IP6Header* ip = (struct Headers_IP6Header*) msg->bytes; Headers_setIpVersion(ip); ip->payloadLength_be = Endian_hostToBigEndian16(msg->length - Headers_IP6Header_SIZE); ip->nextHeader = 17; *checksum = Checksum_udpIp6(ip->sourceAddr, (uint8_t*) uh, length); pushRouteDataHeaders(ctx, msg); struct IfaceContext* nodeIf = Allocator_calloc(alloc, sizeof(struct IfaceContext), 1); nodeIf->ctx = ctx; nodeIf->iface.send = responseWithIpCallback; struct IfaceContext* tunIf = Allocator_calloc(alloc, sizeof(struct IfaceContext), 1); tunIf->ctx = ctx; tunIf->iface.send = messageToTun; Iface_plumb(&nodeIf->iface, &ipTun->nodeInterface); Iface_plumb(&tunIf->iface, &ipTun->tunInterface); ctx->expectedResponse = getExpectedResponse(sa4, prefix4, alloc4, sa6, prefix6, alloc6, alloc); Iface_send(&nodeIf->iface, msg); Assert_true(ctx->called == 2); ctx->called = 0; if (sa4) { uint8_t* addrBytes = NULL; Assert_true(Sockaddr_getAddress(sa4, &addrBytes) == 4); uint32_t addr; Bits_memcpy(&addr, addrBytes, 4); addr = Endian_bigEndianToHost32(addr); // Send from the address specified Assert_true(trySend4(alloc, addr, &nodeIf->iface, ctx)); if (alloc4 < 32) { // Send from another (random) address in the prefix uint32_t flip = Random_uint32(ctx->rand) >> alloc4; if (prefix4 != 32) { Assert_true(trySend4(alloc, addr ^ flip, &nodeIf->iface, ctx)); } else { // If netSize is not specified, we do not allow multi-address Assert_true(!trySend4(alloc, addr ^ flip, &nodeIf->iface, ctx)); } } else {
struct Iface* TUNInterface_new(const char* interfaceName, char assignedInterfaceName[TUNInterface_IFNAMSIZ], int isTapMode, struct EventBase* base, struct Log* logger, struct Except* eh, struct Allocator* alloc) { if (isTapMode) { Except_throw(eh, "tap mode not supported on this platform"); } int maxNameSize = (IFNAMSIZ < TUNInterface_IFNAMSIZ) ? IFNAMSIZ : TUNInterface_IFNAMSIZ; int tunUnit = 0; /* allocate dynamically by default */ if (interfaceName) { int parsedUnit = 0; if (sscanf(interfaceName, "utun%i", &parsedUnit) != 1 || parsedUnit < 0) { Except_throw(eh, "Invalid utun device %s", interfaceName); } tunUnit = parsedUnit + 1; /* device number used is unit - 1*/ } Log_info(logger, "Initializing utun interface: %s\n", (interfaceName ? interfaceName : "auto")); int tunFd = socket(PF_SYSTEM, SOCK_DGRAM, SYSPROTO_CONTROL); if (tunFd < 0) { Except_throw(eh, "socket(PF_SYSTEM, SOCK_DGRAM, SYSPROTO_CONTROL) [%s]", strerror(errno)); } /* get the utun control id */ struct ctl_info info; memset(&info, 0, sizeof(info)); strncpy(info.ctl_name, APPLE_UTUN_CONTROL, strlen(APPLE_UTUN_CONTROL)); if (ioctl(tunFd, CTLIOCGINFO, &info) < 0) { int err = errno; close(tunFd); Except_throw(eh, "getting utun device id [%s]", strerror(err)); } /* connect the utun device */ struct sockaddr_ctl addr; addr.sc_id = info.ctl_id; addr.sc_len = sizeof(addr); addr.sc_family = AF_SYSTEM; addr.ss_sysaddr = AF_SYS_CONTROL; addr.sc_unit = tunUnit; if (connect(tunFd, (struct sockaddr*)&addr, sizeof(addr)) < 0) { int err = errno; close(tunFd); Except_throw(eh, "connecting to utun device [%s]", strerror(err)); } char assignedIfName[TUNInterface_IFNAMSIZ]; if (!assignedInterfaceName) { assignedInterfaceName = assignedIfName; } /* retrieve the assigned utun interface name */ if (getsockopt(tunFd, SYSPROTO_CONTROL, UTUN_OPT_IFNAME, assignedInterfaceName, (uint32_t*) &maxNameSize) >= 0) { Log_info(logger, "Initialized utun interface [%s]\n", assignedInterfaceName); } else { int err = errno; close(tunFd); Except_throw(eh, "getting utun interface name [%s]", strerror(err)); } struct Pipe* p = Pipe_forFiles(tunFd, tunFd, base, eh, alloc); struct BSDMessageTypeWrapper* bmtw = BSDMessageTypeWrapper_new(alloc, logger); Iface_plumb(&p->iface, &bmtw->wireSide); return &bmtw->inside; }
int main() { AddressCalc_addressForPublicKey(nodeCjdnsIp6, fakePubKey); struct Allocator* alloc = MallocAllocator_new(1<<20); struct Log* logger = FileWriterLog_new(stdout, alloc); struct Random* rand = Random_new(alloc, logger, NULL); struct EventBase* eb = EventBase_new(alloc); struct IpTunnel* ipTun = IpTunnel_new(logger, eb, alloc, rand); struct Sockaddr_storage ip6ToGive; Sockaddr_parse("fd01:0101:0101:0101:0101:0101:0101:0101", &ip6ToGive); IpTunnel_allowConnection(fakePubKey, &ip6ToGive.addr, 0, NULL, 0, ipTun); struct Message* message; Message_STACK(message, 64, 512); message->alloc = alloc; const char* requestForAddresses = "d" "1:q" "21:IpTunnel_getAddresses" "4:txid" "4:abcd" "e"; CString_strcpy((char*)message->bytes, requestForAddresses); message->length = CString_strlen(requestForAddresses); Message_shift(message, Headers_UDPHeader_SIZE, NULL); struct Headers_UDPHeader* uh = (struct Headers_UDPHeader*) message->bytes; uh->srcPort_be = 0; uh->destPort_be = 0; uh->length_be = Endian_hostToBigEndian16(message->length - Headers_UDPHeader_SIZE); uint16_t* checksum = &uh->checksum_be; *checksum = 0; uint32_t length = message->length; Message_shift(message, Headers_IP6Header_SIZE, NULL); struct Headers_IP6Header* ip = (struct Headers_IP6Header*) message->bytes; ip->versionClassAndFlowLabel = 0; ip->flowLabelLow_be = 0; ip->payloadLength_be = Endian_hostToBigEndian16(length); ip->nextHeader = 17; ip->hopLimit = 255; Bits_memset(ip->sourceAddr, 0, 32); Headers_setIpVersion(ip); Message_shift(message, RouteHeader_SIZE + DataHeader_SIZE, NULL); struct RouteHeader* rh = (struct RouteHeader*) message->bytes; struct DataHeader* dh = (struct DataHeader*) &rh[1]; Bits_memset(rh, 0, RouteHeader_SIZE + DataHeader_SIZE); Bits_memcpy(rh->ip6, nodeCjdnsIp6, 16); Bits_memcpy(rh->publicKey, fakePubKey, 32); DataHeader_setContentType(dh, ContentType_IPTUN); *checksum = Checksum_udpIp6(ip->sourceAddr, (uint8_t*) uh, length); int origCap = message->capacity; int origLen = message->length; struct Iface nodeIface = { .send = responseWithIpCallback }; Iface_plumb(&nodeIface, &ipTun->nodeInterface); struct Iface tunIface = { .send = messageToTun }; Iface_plumb(&tunIface, &ipTun->tunInterface); Iface_send(&nodeIface, message); Assert_true(called == 2); called = 0; // This is a hack, reusing the message will cause breakage if IpTunnel is refactored. Message_reset(message); Message_shift(message, origCap, NULL); message->length = origLen; Bits_memcpy(ip->sourceAddr, fakeIp6ToGive, 16); // This can't be zero. Bits_memset(ip->destinationAddr, 1, 16); Iface_send(&nodeIface, message); Assert_true(called == 1); Allocator_free(alloc); return 0; }
static void switching(struct Context* ctx) { Log_info(ctx->log, "Setting up salsa20/poly1305 benchmark (encryption and decryption only)"); struct Allocator* alloc = Allocator_child(ctx->alloc);; struct SwitchingContext* sc = Allocator_calloc(alloc, sizeof(struct SwitchingContext), 1); Identity_set(sc); sc->benchmarkCtx = ctx; sc->aliceIf.send = aliceToBob; sc->bobIf.send = bobToAlice; sc->aliceCtrlIf.send = aliceCtrlRecv; struct NetCore* alice = NetCore_new(SECRETA, alloc, ctx->base, ctx->rand, ctx->log); struct InterfaceController_Iface* aliceIci = InterfaceController_newIface(alice->ifController, String_CONST("alice"), alloc); Iface_plumb(&sc->aliceIf, &aliceIci->addrIf); struct NetCore* bob = NetCore_new(SECRETB, alloc, ctx->base, ctx->rand, ctx->log); struct InterfaceController_Iface* bobIci = InterfaceController_newIface(bob->ifController, String_CONST("bob"), alloc); Iface_plumb(&sc->bobIf, &bobIci->addrIf); CryptoAuth_addUser(String_CONST("abcdefg123"), 1, String_CONST("TEST"), bob->ca); // Client has pubKey and passwd for the server. int ret = InterfaceController_bootstrapPeer(alice->ifController, aliceIci->ifNum, bob->ca->publicKey, Sockaddr_LOOPBACK, String_CONST("abcdefg123"), alloc); Assert_true(!ret); Iface_unplumb(alice->switchAdapter->controlIf.connectedIf, &alice->switchAdapter->controlIf); Iface_plumb(&alice->switchAdapter->controlIf, &sc->aliceCtrlIf); struct Message* msg = Message_new(Control_Ping_MIN_SIZE + Control_Header_SIZE, 256, alloc); struct Control_Header* ch = (struct Control_Header*) msg->bytes; struct Control_Ping* ping = (struct Control_Ping*) &ch[1]; ping->version_be = Endian_hostToBigEndian32(Version_CURRENT_PROTOCOL); Message_push32(msg, 0xffffffff, NULL); uint32_t* handle_be = (uint32_t*)msg->bytes; Message_push(msg, NULL, SwitchHeader_SIZE, NULL); struct SwitchHeader* sh = (struct SwitchHeader*) msg->bytes; // TODO(cjd): this will fail with a different encoding scheme sh->label_be = Endian_hostToBigEndian64(0x13); for (int i = 1; i < 6; i++) { ping->magic = Control_Ping_MAGIC; ch->type_be = Control_PING_be; ch->checksum_be = 0; ch->checksum_be = Checksum_engine((void*)ch, Control_Ping_MIN_SIZE + Control_Header_SIZE); Iface_send(&sc->aliceCtrlIf, msg); Assert_true(sc->msgCount == i); Assert_true(msg->bytes == (void*)sh); Assert_true(ping->magic == Control_Pong_MAGIC); Assert_true(ch->type_be = Control_PONG_be); Assert_true(!Checksum_engine((void*)ch, Control_Ping_MIN_SIZE + Control_Header_SIZE)); } *handle_be = 0xfffffff0; int count = 1000000; begin(ctx, "Switching", count, "packets"); for (int i = 0; i < count; i++) { sh->versionAndLabelShift = SwitchHeader_CURRENT_VERSION << 6; Iface_send(&sc->aliceCtrlIf, msg); Assert_true(msg->bytes == (void*)sh); } done(ctx); Log_info(ctx->log, "DONE"); Allocator_free(alloc); }