int main() { printInfo(); volatile uint64_t b = 0x0123456789abcdef; volatile uint64_t sb = 0xefcdab8967452301; volatile uint32_t a = 0x01234567; volatile uint32_t sa = 0x67452301; volatile uint16_t c = 0xcabe; volatile uint16_t sc = 0xbeca; if (!Endian_isBigEndian()) { Assert_true(c == Endian_bigEndianToHost16(sc)); Assert_true(c == Endian_hostToBigEndian16(sc)); Assert_true(c == Endian_hostToLittleEndian16(c)); Assert_true(c == Endian_littleEndianToHost16(c)); Assert_true(a == Endian_bigEndianToHost32(sa)); Assert_true(a == Endian_hostToBigEndian32(sa)); Assert_true(a == Endian_hostToLittleEndian32(a)); Assert_true(a == Endian_littleEndianToHost32(a)); Assert_true(b == Endian_bigEndianToHost64(sb)); Assert_true(b == Endian_hostToBigEndian64(sb)); Assert_true(b == Endian_hostToLittleEndian64(b)); Assert_true(b == Endian_littleEndianToHost64(b)); } else { Assert_true(c == Endian_bigEndianToHost16(c)); Assert_true(c == Endian_hostToBigEndian16(c)); Assert_true(c == Endian_hostToLittleEndian16(sc)); Assert_true(c == Endian_littleEndianToHost16(sc)); Assert_true(a == Endian_bigEndianToHost32(a)); Assert_true(a == Endian_hostToBigEndian32(a)); Assert_true(a == Endian_hostToLittleEndian32(sa)); Assert_true(a == Endian_littleEndianToHost32(sa)); Assert_true(b == Endian_bigEndianToHost64(b)); Assert_true(b == Endian_hostToBigEndian64(b)); Assert_true(b == Endian_hostToLittleEndian64(sb)); Assert_true(b == Endian_littleEndianToHost64(sb)); } Assert_true(b == Endian_byteSwap64(sb)); Assert_true(a == Endian_byteSwap32(sa)); Assert_true(c == Endian_byteSwap16(sc)); return 0; }
/** * When we send a message it goes into the CryptoAuth. * for the content level crypto then it goes to outgoingFromCryptoAuth then comes here. * Message is aligned on the beginning of the crypto header, ip6 header must be reapplied. */ static inline uint8_t outgoingFromMe(struct Message* message, struct Ducttape* context) { // Need to set the length field to take into account // the crypto headers which are hidden under the ipv6 packet. context->ip6Header->payloadLength_be = Endian_hostToBigEndian16(message->length); Message_shift(message, Headers_IP6Header_SIZE); // If this message is addressed to us, it means the cryptoauth kicked back a response // message when we asked it to decrypt a message for us and the ipv6 addresses need to // be flipped to send it back to the other node. if (isForMe(message, context)) { struct Headers_IP6Header* ip6 = (struct Headers_IP6Header*) message->bytes; Assert_true(context->ip6Header == ip6); Bits_memcpyConst(ip6->destinationAddr, ip6->sourceAddr, 16); Bits_memcpyConst(ip6->sourceAddr, &context->myAddr.ip6.bytes, 16); // It came from me... context->routerAddress = context->myAddr.ip6.bytes; } else { Bits_memcpyConst(message->bytes, context->ip6Header, Headers_IP6Header_SIZE); } // Forward this call to core() which will check it's validity // and since it's not to us, forward it to the correct node. return core(message, context); }
/** * When we send a message it goes into the CryptoAuth. * for the content level crypto then it goes to outgoingFromCryptoAuth then comes here. * Message is aligned on the beginning of the CryptoAuth header. */ static inline uint8_t outgoingFromMe(struct Message* message, struct Ducttape_MessageHeader* dtHeader, struct SessionManager_Session* session, struct Ducttape_pvt* context) { // Move back to the beginning of the ip6Header behind the crypto. Message_shift(message, Headers_IP6Header_SIZE); struct Headers_IP6Header* header = (struct Headers_IP6Header*) message->bytes; if (!Bits_memcmp(header->destinationAddr, context->myAddr.ip6.bytes, 16)) { // This happens when an empty connect-to-me packet is sent to us, // CryptoAuth is called with a message and instead of returning a decrypted message // to send to the TUN, it outputs a message to send back down the wire but the // header is still the same. // these messages are always empty so we just flip the source and destination around // and send it back. Bits_memcpyConst(header->destinationAddr, header->sourceAddr, 16); Bits_memcpyConst(header->sourceAddr, context->myAddr.ip6.bytes, 16); } else { // sanity check. Assert_true(!Bits_memcmp(header->sourceAddr, context->myAddr.ip6.bytes, 16)); } // Need to set the length field to take into account // the crypto headers which are hidden under the ipv6 packet. header->payloadLength_be = Endian_hostToBigEndian16(message->length - Headers_IP6Header_SIZE); // Forward this call to core() which will check its validity // and since it's not to us, forward it to the correct node. return core(message, dtHeader, session, context); }
void TestFramework_craftIPHeader(struct Message* msg, uint8_t srcAddr[16], uint8_t destAddr[16]) { Message_shift(msg, Headers_IP6Header_SIZE, NULL); struct Headers_IP6Header* ip = (struct Headers_IP6Header*) msg->bytes; ip->versionClassAndFlowLabel = 0; ip->flowLabelLow_be = 0; ip->payloadLength_be = Endian_hostToBigEndian16(msg->length - Headers_IP6Header_SIZE); ip->nextHeader = 123; // made up number ip->hopLimit = 255; Bits_memcpy(ip->sourceAddr, srcAddr, 16); Bits_memcpy(ip->destinationAddr, destAddr, 16); Headers_setIpVersion(ip); }
static uint8_t sendMessage(struct Message* message, struct Interface* ethIf) { struct ETHInterface* context = Identity_cast((struct ETHInterface*) ethIf); struct sockaddr_ll addr; Bits_memcpyConst(&addr, &context->addrBase, sizeof(struct sockaddr_ll)); Message_pop(message, addr.sll_addr, 8); /* Cut down on the noise uint8_t buff[sizeof(addr) * 2 + 1] = {0}; Hex_encode(buff, sizeof(buff), (uint8_t*)&addr, sizeof(addr)); Log_debug(context->logger, "Sending ethernet frame to [%s]", buff); */ // Check if we will have to pad the message and pad if necessary. int pad = 0; for (int length = message->length; length+2 < MIN_PACKET_SIZE; length += 8) { pad++; } if (pad > 0) { int length = message->length; Message_shift(message, pad*8); Bits_memset(message->bytes, 0, pad*8); Bits_memmove(message->bytes, &message->bytes[pad*8], length); } Assert_true(pad < 8); uint16_t padAndId_be = Endian_hostToBigEndian16((context->id << 3) | pad); Message_push(message, &padAndId_be, 2); if (sendto(context->socket, message->bytes, message->length, 0, (struct sockaddr*) &addr, sizeof(struct sockaddr_ll)) < 0) { switch (errno) { case EMSGSIZE: return Error_OVERSIZE_MESSAGE; case ENOBUFS: case EAGAIN: return Error_LINK_LIMIT_EXCEEDED; default:; Log_info(context->logger, "Got error sending to socket [%s]", strerror(errno)); } } return 0; }
int main() { char* pingBenc = "d1:q4:ping4:txid4:abcde"; struct Allocator* alloc = MallocAllocator_new(1<<22); struct TestFramework* tf = TestFramework_setUp("0123456789abcdefghijklmnopqrstuv", alloc, NULL); struct Ducttape_pvt* dt = Identity_cast((struct Ducttape_pvt*) tf->ducttape); struct Allocator* allocator = MallocAllocator_new(85000); uint16_t buffLen = sizeof(struct Ducttape_IncomingForMe) + 8 + strlen(pingBenc); uint8_t* buff = allocator->calloc(buffLen, 1, allocator); struct Headers_SwitchHeader* sh = (struct Headers_SwitchHeader*) buff; sh->label_be = Endian_hostToBigEndian64(4); struct Headers_IP6Header* ip6 = (struct Headers_IP6Header*) &sh[1]; uint8_t herPublicKey[32]; Base32_decode(herPublicKey, 32, (uint8_t*) "0z5tscp8td1sc6cv4htp7jbls79ltqxw9pbg190x0kbm1lguqtx0", 52); AddressCalc_addressForPublicKey(ip6->sourceAddr, herPublicKey); struct Headers_UDPHeader* udp = (struct Headers_UDPHeader*) &ip6[1]; ip6->hopLimit = 0; ip6->nextHeader = 17; udp->sourceAndDestPorts = 0; udp->length_be = Endian_hostToBigEndian16(strlen(pingBenc)); strncpy((char*)(udp + 1), pingBenc, strlen(pingBenc)); dt->switchInterface.receiveMessage = catchResponse; dt->switchInterface.receiverContext = NULL; // bad checksum udp->checksum_be = 1; struct Message m = { .bytes = buff, .length = buffLen, .padding = 0 }; Ducttape_injectIncomingForMe(&m, &dt->public, herPublicKey); Assert_always(!dt->switchInterface.receiverContext); // zero checksum udp->checksum_be = 0; struct Message m2 = { .bytes = buff, .length = buffLen, .padding = 0 }; Ducttape_injectIncomingForMe(&m2, &dt->public, herPublicKey); Assert_always(dt->switchInterface.receiverContext); // good checksum udp->checksum_be = Checksum_udpIp6(ip6->sourceAddr, (uint8_t*) udp, strlen(pingBenc) + Headers_UDPHeader_SIZE); struct Message m3 = { .bytes = buff, .length = buffLen, .padding = 0 }; Ducttape_injectIncomingForMe(&m3, &dt->public, herPublicKey); Assert_always(dt->switchInterface.receiverContext); }
static int handleOutgoing(struct DHTMessage* dmessage, void* vcontext) { struct Ducttape_pvt* context = Identity_check((struct Ducttape_pvt*) vcontext); // Sending a message to yourself? // Short circuit because setting up a CA session with yourself causes problems. if (!Bits_memcmp(dmessage->address->key, context->myAddr.key, 32)) { struct Allocator* alloc = Allocator_child(context->alloc); Allocator_adopt(alloc, dmessage->binMessage->alloc); incomingDHT(dmessage->binMessage, dmessage->address, context); Allocator_free(alloc); return 0; } struct Message* msg = dmessage->binMessage; { Message_push(msg, (&(struct Headers_UDPHeader) { .srcPort_be = 0, .destPort_be = 0, .length_be = Endian_hostToBigEndian16(msg->length), .checksum_be = 0, }), Headers_UDPHeader_SIZE, NULL); }
static int handleOutgoing(struct DHTMessage* dmessage, void* vcontext) { struct Ducttape* context = (struct Ducttape*) vcontext; struct Message message = { .length = dmessage->length, .bytes = (uint8_t*) dmessage->bytes, .padding = 512 }; Message_shift(&message, Headers_UDPHeader_SIZE); struct Headers_UDPHeader* uh = (struct Headers_UDPHeader*) message.bytes; uh->sourceAndDestPorts = 0; uh->length_be = Endian_hostToBigEndian16(dmessage->length); uh->checksum_be = 0; uint16_t payloadLength = message.length; Message_shift(&message, Headers_IP6Header_SIZE); struct Headers_IP6Header* header = (struct Headers_IP6Header*) message.bytes; header->versionClassAndFlowLabel = 0; header->flowLabelLow_be = 0; header->nextHeader = 17; header->hopLimit = 0; header->payloadLength_be = Endian_hostToBigEndian16(payloadLength); Bits_memcpyConst(header->sourceAddr, context->myAddr.ip6.bytes, Address_SEARCH_TARGET_SIZE); Bits_memcpyConst(header->destinationAddr, dmessage->address->ip6.bytes, Address_SEARCH_TARGET_SIZE); context->ip6Header = header; context->switchHeader = NULL; sendToRouter(dmessage->address, &message, context); return 0; } // Aligned on the beginning of the content. static inline bool isRouterTraffic(struct Message* message, struct Headers_IP6Header* ip6) { if (ip6->nextHeader != 17 || ip6->hopLimit != 0) { return false; } struct Headers_UDPHeader* uh = (struct Headers_UDPHeader*) message->bytes; return message->length >= Headers_UDPHeader_SIZE && uh->sourceAndDestPorts == 0 && (int) Endian_bigEndianToHost16(uh->length_be) == message->length - Headers_UDPHeader_SIZE; } /** * Message which is for us, message is aligned on the beginning of the content. * this is called from core() which calls through an interfaceMap. */ static inline uint8_t incomingForMe(struct Message* message, struct Ducttape* context, uint8_t herPubKey[32]) { struct Address addr; AddressCalc_addressForPublicKey(addr.ip6.bytes, herPubKey); if (memcmp(addr.ip6.bytes, context->ip6Header->sourceAddr, 16)) { #ifdef Log_DEBUG uint8_t keyAddr[40]; Address_printIp(keyAddr, &addr); Bits_memcpyConst(addr.ip6.bytes, context->ip6Header->sourceAddr, 16); uint8_t srcAddr[40]; Address_printIp(srcAddr, &addr); Log_debug2(context->logger, "Dropped packet because source address is not same as key.\n" " %s source addr\n" " %s hash of key\n", srcAddr, keyAddr); #endif return Error_INVALID; } if (message->length == 0) { #ifdef Log_WARN uint8_t keyAddr[40]; uint8_t ipv6Hex[80]; Address_printIp(keyAddr, &addr); Hex_encode(ipv6Hex, 80, (uint8_t*) context->ip6Header, 40); Log_warn2(context->logger, "Got ipv6 packet from %s which has no content!\nIPv6 Header: [%s]", keyAddr, ipv6Hex); #endif return Error_INVALID; } if (isRouterTraffic(message, context->ip6Header)) { // Shift off the UDP header. Message_shift(message, -Headers_UDPHeader_SIZE); addr.path = Endian_bigEndianToHost64(context->switchHeader->label_be); Bits_memcpyConst(addr.key, herPubKey, 32); return incomingDHT(message, &addr, context); } // RouterModule_addNode(&addr, context->routerModule); if (!context->routerIf) { Log_warn(context->logger, "Dropping message because there is no router interface configured.\n"); return Error_UNDELIVERABLE; } // Now write a message to the TUN device. // Need to move the ipv6 header forward up to the content because there's a crypto header // between the ipv6 header and the content which just got eaten. Message_shift(message, Headers_IP6Header_SIZE); uint16_t sizeDiff = message->bytes - (uint8_t*)context->ip6Header; if (sizeDiff) { context->ip6Header->payloadLength_be = Endian_hostToBigEndian16( Endian_bigEndianToHost16(context->ip6Header->payloadLength_be) - sizeDiff); memmove(message->bytes, context->ip6Header, Headers_IP6Header_SIZE); } context->routerIf->sendMessage(message, context->routerIf); return Error_NONE; } uint8_t Ducttape_injectIncomingForMe(struct Message* message, struct Ducttape* context, uint8_t herPublicKey[32]) { struct Headers_SwitchHeader sh; Bits_memcpyConst(&sh, message->bytes, Headers_SwitchHeader_SIZE); context->switchHeader = &sh; Message_shift(message, -Headers_SwitchHeader_SIZE); struct Headers_IP6Header ip6; Bits_memcpyConst(&ip6, message->bytes, Headers_IP6Header_SIZE); context->ip6Header = &ip6; Message_shift(message, -Headers_IP6Header_SIZE); return incomingForMe(message, context, herPublicKey); } /** * Send a message to another switch. * Switchheader will precede the message. */ static inline uint8_t sendToSwitch(struct Message* message, struct Headers_SwitchHeader* destinationSwitchHeader, struct Ducttape* context) { Message_shift(message, Headers_SwitchHeader_SIZE); struct Headers_SwitchHeader* switchHeaderLocation = (struct Headers_SwitchHeader*) message->bytes; if (destinationSwitchHeader != switchHeaderLocation) { memmove(message->bytes, destinationSwitchHeader, Headers_SwitchHeader_SIZE); } return context->switchInterface.receiveMessage(message, &context->switchInterface); }
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));
static int handleOutgoing(struct DHTMessage* dmessage, void* vcontext) { struct Ducttape_pvt* context = Identity_cast((struct Ducttape_pvt*) vcontext); struct Message message = { .length = dmessage->length, .bytes = (uint8_t*) dmessage->bytes, .padding = 512, .capacity = DHTMessage_MAX_SIZE }; Message_shift(&message, Headers_UDPHeader_SIZE); struct Headers_UDPHeader* uh = (struct Headers_UDPHeader*) message.bytes; uh->sourceAndDestPorts = 0; uh->length_be = Endian_hostToBigEndian16(dmessage->length); uh->checksum_be = 0; uint16_t payloadLength = message.length; Message_shift(&message, Headers_IP6Header_SIZE); struct Headers_IP6Header* header = (struct Headers_IP6Header*) message.bytes; header->versionClassAndFlowLabel = 0; header->flowLabelLow_be = 0; header->nextHeader = 17; header->hopLimit = 0; header->payloadLength_be = Endian_hostToBigEndian16(payloadLength); Bits_memcpyConst(header->sourceAddr, context->myAddr.ip6.bytes, Address_SEARCH_TARGET_SIZE); Bits_memcpyConst(header->destinationAddr, dmessage->address->ip6.bytes, Address_SEARCH_TARGET_SIZE); #ifdef Log_DEBUG Assert_true(!((uintptr_t)dmessage->bytes % 4) || !"alignment fault"); #endif uh->checksum_be = Checksum_udpIp6(header->sourceAddr, (uint8_t*) uh, message.length - Headers_IP6Header_SIZE); struct Ducttape_MessageHeader* dtHeader = getDtHeader(&message, true); dtHeader->ip6Header = header; dtHeader->switchLabel = dmessage->address->path; struct SessionManager_Session* session = SessionManager_getSession(dmessage->address->ip6.bytes, dmessage->address->key, context->sm); if (session->version == Version_DEFAULT_ASSUMPTION && dmessage->replyTo) { int64_t* verPtr = Dict_getInt(dmessage->replyTo->asDict, String_CONST("p")); session->version = (verPtr) ? *verPtr : Version_DEFAULT_ASSUMPTION; } if (session->version == Version_DEFAULT_ASSUMPTION) { struct Node* n = RouterModule_getNode(dmessage->address->path, context->routerModule); if (n) { n->version = session->version = (n->version > session->version) ? n->version : session->version; } } sendToRouter(&message, dtHeader, session, context); return 0; } // Aligned on the beginning of the content. static inline bool isRouterTraffic(struct Message* message, struct Headers_IP6Header* ip6) { if (ip6->nextHeader != 17 || ip6->hopLimit != 0) { return false; } struct Headers_UDPHeader* uh = (struct Headers_UDPHeader*) message->bytes; return message->length >= Headers_UDPHeader_SIZE && uh->sourceAndDestPorts == 0 && (int) Endian_bigEndianToHost16(uh->length_be) == (message->length - Headers_UDPHeader_SIZE); } #define debugHandles(logger, session, message, ...) \ do { \ uint8_t ip[40]; \ AddrTools_printIp(ip, session->ip6); \ Log_debug(logger, "ver[%u] send[%d] recv[%u] ip[%s] " message, \ session->version, \ Endian_hostToBigEndian32(session->sendHandle_be), \ Endian_hostToBigEndian32(session->receiveHandle_be), \ ip, \ __VA_ARGS__); \ } while (0) //CHECKFILES_IGNORE expecting a ; #define debugHandles0(logger, session, message) \ debugHandles(logger, session, message "%s", "") #define debugHandlesAndLabel(logger, session, label, message, ...) \ do { \ uint8_t path[20]; \ AddrTools_printPath(path, label); \ debugHandles(logger, session, "path[%s] " message, path, __VA_ARGS__); \ } while (0) //CHECKFILES_IGNORE expecting a ; #define debugHandlesAndLabel0(logger, session, label, message) \ debugHandlesAndLabel(logger, session, label, "%s", message) /** * Message which is for us, message is aligned on the beginning of the content. * this is called from core() which calls through an interfaceMap. */ static inline uint8_t incomingForMe(struct Message* message, struct Ducttape_MessageHeader* dtHeader, struct SessionManager_Session* session, struct Ducttape_pvt* context, uint8_t herPublicKey[32]) { struct Address addr; Bits_memcpyConst(addr.ip6.bytes, session->ip6, 16); //AddressCalc_addressForPublicKey(addr.ip6.bytes, herPubKey); if (Bits_memcmp(addr.ip6.bytes, dtHeader->ip6Header->sourceAddr, 16)) { #ifdef Log_DEBUG uint8_t keyAddr[40]; Address_printIp(keyAddr, &addr); Bits_memcpyConst(addr.ip6.bytes, dtHeader->ip6Header->sourceAddr, 16); uint8_t srcAddr[40]; Address_printIp(srcAddr, &addr); Log_debug(context->logger, "Dropped packet because source address is not same as key.\n" " %s source addr\n" " %s hash of key\n", srcAddr, keyAddr); #endif return Error_INVALID; } if (isRouterTraffic(message, dtHeader->ip6Header)) { // Check the checksum. struct Headers_UDPHeader* uh = (struct Headers_UDPHeader*) message->bytes; if (Checksum_udpIp6(dtHeader->ip6Header->sourceAddr, (uint8_t*)uh, message->length)) { #ifdef Log_DEBUG uint8_t keyAddr[40]; Address_printIp(keyAddr, &addr); Log_debug(context->logger, "Router packet with incorrect checksum, from [%s]", keyAddr); #endif return Error_INVALID; } // Shift off the UDP header. Message_shift(message, -Headers_UDPHeader_SIZE); addr.path = Endian_bigEndianToHost64(dtHeader->switchHeader->label_be); Bits_memcpyConst(addr.key, herPublicKey, 32); return incomingDHT(message, &addr, context); } if (!context->userIf) { Log_warn(context->logger, "Dropping message because there is no router interface configured.\n"); return Error_UNDELIVERABLE; } // prevent router advertizement schenanigans if (dtHeader->ip6Header->hopLimit == 255) { dtHeader->ip6Header->hopLimit--; } // Now write a message to the TUN device. // Need to move the ipv6 header forward up to the content because there's a crypto header // between the ipv6 header and the content which just got eaten. Message_shift(message, Headers_IP6Header_SIZE); uint16_t sizeDiff = message->bytes - (uint8_t*)dtHeader->ip6Header; if (sizeDiff) { dtHeader->ip6Header->payloadLength_be = Endian_hostToBigEndian16( Endian_bigEndianToHost16(dtHeader->ip6Header->payloadLength_be) - sizeDiff); Bits_memmoveConst(message->bytes, dtHeader->ip6Header, Headers_IP6Header_SIZE); } TUNMessageType_push(message, Ethernet_TYPE_IP6); context->userIf->sendMessage(message, context->userIf); return Error_NONE; } uint8_t Ducttape_injectIncomingForMe(struct Message* message, struct Ducttape* dt, uint8_t herPublicKey[32]) { struct Ducttape_pvt* context = Identity_cast((struct Ducttape_pvt*)dt); struct Ducttape_MessageHeader* dtHeader = getDtHeader(message, true); struct Headers_SwitchHeader sh; Bits_memcpyConst(&sh, message->bytes, Headers_SwitchHeader_SIZE); dtHeader->switchHeader = &sh; Message_shift(message, -Headers_SwitchHeader_SIZE); struct Headers_IP6Header ip6; Bits_memcpyConst(&ip6, message->bytes, Headers_IP6Header_SIZE); dtHeader->ip6Header = &ip6; Message_shift(message, -Headers_IP6Header_SIZE); struct SessionManager_Session s; AddressCalc_addressForPublicKey(s.ip6, herPublicKey); s.version = Version_CURRENT_PROTOCOL; return incomingForMe(message, dtHeader, &s, context, herPublicKey); } /** * Send a message to another switch. * Switchheader will precede the message. */ static inline uint8_t sendToSwitch(struct Message* message, struct Ducttape_MessageHeader* dtHeader, struct SessionManager_Session* session, struct Ducttape_pvt* context) { uint64_t label = dtHeader->switchLabel; if (CryptoAuth_getState(&session->iface) >= CryptoAuth_HANDSHAKE3) { debugHandlesAndLabel0(context->logger, session, label, "layer2 sending run message"); uint32_t sendHandle_be = session->sendHandle_be; #ifdef Version_2_COMPAT if (session->version < 3) { sendHandle_be |= HANDLE_FLAG_BIT_be; } #endif Message_push(message, &sendHandle_be, 4); } else { debugHandlesAndLabel0(context->logger, session, label, "layer2 sending start message"); #ifdef Version_2_COMPAT if (session->version < 3) { Message_push(message, &session->receiveHandle_be, 4); } #endif } Message_shift(message, Headers_SwitchHeader_SIZE); Assert_true(message->bytes == (uint8_t*)dtHeader->switchHeader); return context->switchInterface.receiveMessage(message, &context->switchInterface); }
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; }
static Iface_DEFUN sendMessage(struct Message* msg, struct Iface* iface) { struct ETHInterface_pvt* ctx = Identity_containerOf(iface, struct ETHInterface_pvt, pub.generic.iface); struct Sockaddr* sa = (struct Sockaddr*) msg->bytes; Assert_true(msg->length >= Sockaddr_OVERHEAD); Assert_true(sa->addrLen <= ETHInterface_Sockaddr_SIZE); struct ETHInterface_Sockaddr sockaddr = { .generic = { .addrLen = 0 } }; Message_pop(msg, &sockaddr, sa->addrLen, NULL); struct sockaddr_ll addr; Bits_memcpy(&addr, &ctx->addrBase, sizeof(struct sockaddr_ll)); if (sockaddr.generic.flags & Sockaddr_flags_BCAST) { Bits_memset(addr.sll_addr, 0xff, 6); } else { Bits_memcpy(addr.sll_addr, sockaddr.mac, 6); } struct ETHInterface_Header hdr = { .version = ETHInterface_CURRENT_VERSION, .zero = 0, .length_be = Endian_hostToBigEndian16(msg->length + ETHInterface_Header_SIZE), .fc00_be = Endian_hostToBigEndian16(0xfc00) }; Message_push(msg, &hdr, ETHInterface_Header_SIZE, NULL); struct Except* eh = NULL; sendMessageInternal(msg, &addr, ctx, eh); return NULL; } static void handleEvent2(struct ETHInterface_pvt* context, struct Allocator* messageAlloc) { struct Message* msg = Message_new(MAX_PACKET_SIZE, PADDING, messageAlloc); struct sockaddr_ll addr; uint32_t addrLen = sizeof(struct sockaddr_ll); // Knock it out of alignment by 2 bytes so that it will be // aligned when the idAndPadding is shifted off. Message_shift(msg, 2, NULL); int rc = recvfrom(context->socket, msg->bytes, msg->length, 0, (struct sockaddr*) &addr, &addrLen); if (rc < ETHInterface_Header_SIZE) { Log_debug(context->logger, "Failed to receive eth frame"); return; } Assert_true(msg->length >= rc); msg->length = rc; //Assert_true(addrLen == SOCKADDR_LL_LEN); struct ETHInterface_Header hdr; Message_pop(msg, &hdr, ETHInterface_Header_SIZE, NULL); // here we could put a switch statement to handle different versions differently. if (hdr.version != ETHInterface_CURRENT_VERSION) { Log_debug(context->logger, "DROP unknown version"); return; } uint16_t reportedLength = Endian_bigEndianToHost16(hdr.length_be); reportedLength -= ETHInterface_Header_SIZE; if (msg->length != reportedLength) { if (msg->length < reportedLength) { Log_debug(context->logger, "DROP size field is larger than frame"); return; } msg->length = reportedLength; } if (hdr.fc00_be != Endian_hostToBigEndian16(0xfc00)) { Log_debug(context->logger, "DROP bad magic"); return; } struct ETHInterface_Sockaddr sockaddr = { .zero = 0 }; Bits_memcpy(sockaddr.mac, addr.sll_addr, 6); sockaddr.generic.addrLen = ETHInterface_Sockaddr_SIZE; if (addr.sll_pkttype == PACKET_BROADCAST) { sockaddr.generic.flags |= Sockaddr_flags_BCAST; } Message_push(msg, &sockaddr, ETHInterface_Sockaddr_SIZE, NULL); Assert_true(!((uintptr_t)msg->bytes % 4) && "Alignment fault"); Iface_send(&context->pub.generic.iface, msg); } static void handleEvent(void* vcontext) { struct ETHInterface_pvt* context = Identity_check((struct ETHInterface_pvt*) vcontext); struct Allocator* messageAlloc = Allocator_child(context->pub.generic.alloc); handleEvent2(context, messageAlloc); Allocator_free(messageAlloc); } List* ETHInterface_listDevices(struct Allocator* alloc, struct Except* eh) { List* out = List_new(alloc); #ifndef android struct ifaddrs* ifaddr = NULL; if (getifaddrs(&ifaddr) || ifaddr == NULL) { Except_throw(eh, "getifaddrs() -> errno:%d [%s]", errno, strerror(errno)); } for (struct ifaddrs* ifa = ifaddr; ifa; ifa = ifa->ifa_next) { if (ifa->ifa_addr && ifa->ifa_addr->sa_family == AF_PACKET) { List_addString(out, String_new(ifa->ifa_name, alloc), alloc); } } freeifaddrs(ifaddr); #endif return out; } static int closeSocket(struct Allocator_OnFreeJob* j) { struct ETHInterface_pvt* ctx = Identity_check((struct ETHInterface_pvt*) j->userData); close(ctx->socket); return 0; } struct ETHInterface* ETHInterface_new(struct EventBase* eventBase, const char* bindDevice, struct Allocator* alloc, struct Except* exHandler, struct Log* logger) { struct ETHInterface_pvt* ctx = Allocator_calloc(alloc, sizeof(struct ETHInterface_pvt), 1); Identity_set(ctx); ctx->pub.generic.iface.send = sendMessage; ctx->pub.generic.alloc = alloc; ctx->logger = logger; struct ifreq ifr = { .ifr_ifindex = 0 }; ctx->socket = socket(AF_PACKET, SOCK_DGRAM, Ethernet_TYPE_CJDNS); if (ctx->socket == -1) { Except_throw(exHandler, "call to socket() failed. [%s]", strerror(errno)); } Allocator_onFree(alloc, closeSocket, ctx); CString_strncpy(ifr.ifr_name, bindDevice, IFNAMSIZ - 1); ctx->ifName = String_new(bindDevice, alloc); if (ioctl(ctx->socket, SIOCGIFINDEX, &ifr) == -1) { Except_throw(exHandler, "failed to find interface index [%s]", strerror(errno)); } ctx->ifindex = ifr.ifr_ifindex; if (ioctl(ctx->socket, SIOCGIFFLAGS, &ifr) < 0) { Except_throw(exHandler, "ioctl(SIOCGIFFLAGS) [%s]", strerror(errno)); } if (!((ifr.ifr_flags & IFF_UP) && (ifr.ifr_flags & IFF_RUNNING))) { Log_info(logger, "Bringing up interface [%s]", ifr.ifr_name); ifr.ifr_flags |= IFF_UP | IFF_RUNNING; if (ioctl(ctx->socket, SIOCSIFFLAGS, &ifr) < 0) { Except_throw(exHandler, "ioctl(SIOCSIFFLAGS) [%s]", strerror(errno)); } } ctx->addrBase = (struct sockaddr_ll) { .sll_family = AF_PACKET, .sll_protocol = Ethernet_TYPE_CJDNS, .sll_ifindex = ctx->ifindex, .sll_hatype = ARPHRD_ETHER, .sll_pkttype = PACKET_OTHERHOST, .sll_halen = ETH_ALEN }; if (bind(ctx->socket, (struct sockaddr*) &ctx->addrBase, sizeof(struct sockaddr_ll))) { Except_throw(exHandler, "call to bind() failed [%s]", strerror(errno)); } Socket_makeNonBlocking(ctx->socket); Event_socketRead(handleEvent, ctx, ctx->socket, eventBase, alloc, exHandler); return &ctx->pub; }
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; }
int main() { // This is valid benc but it takes over 75k of memory (on an amd64) // to build a structure representing it. char* evilBenc = "d1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:a" "d1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:a" "d1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:a" "d1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:a" "d1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:a" "d1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:a" "d1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:a" "d1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:a" "d1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:a" "d1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:a" "d1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:a" "d1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:a" "d1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:a" "d1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:a" "d1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:a" "d1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:a" "d1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:a" "d1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:a" "d1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:a" "d1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:a" "d1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:a" "d1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:a" "d1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:a" "d1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:a" "d1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:a" "d1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:a" "d1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:a" "d1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:a" "d1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:a" "d1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:a" "d1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:a" "d1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:a" "3:lol" "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee" "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee" "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee" "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee" "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee" "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee" "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee" "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee"; struct Ducttape* dt = TestFramework_setUp(); struct Allocator* allocator = MallocAllocator_new(85000); uint16_t buffLen = sizeof(struct Ducttape_IncomingForMe) + 8 + strlen(evilBenc); uint8_t* buff = allocator->calloc(buffLen, 1, allocator); struct Headers_IP6Header* ip6 = (struct Headers_IP6Header*) (buff + Headers_SwitchHeader_SIZE); uint8_t* herPublicKey = (uint8_t*) "0123456789abcdefghijklmnopqrstuv"; AddressCalc_addressForPublicKey(ip6->sourceAddr, herPublicKey); struct Headers_UDPHeader* udp = (struct Headers_UDPHeader*) (ip6 + 1); ip6->hopLimit = 0; ip6->nextHeader = 17; udp->sourceAndDestPorts = 0; udp->length_be = Endian_hostToBigEndian16(strlen(evilBenc)); strncpy((char*)(udp + 1), evilBenc, strlen(evilBenc)); struct Message m = { .bytes = buff, .length = buffLen, .padding = 0 }; Ducttape_injectIncomingForMe(&m, dt, herPublicKey); }
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 {
int main() { AddressCalc_addressForPublicKey(nodeCjdnsIp6, fakePubKey); struct Allocator* alloc = MallocAllocator_new(1<<20); struct Writer* w = FileWriter_new(stdout, alloc); struct Log* logger = WriterLog_new(w, alloc); struct Random* rand = Random_new(alloc, logger, NULL); struct EventBase* eb = EventBase_new(alloc); struct IpTunnel* ipTun = IpTunnel_new(logger, eb, alloc, rand, NULL); struct Sockaddr_storage ip6ToGive; Sockaddr_parse("fd01:0101:0101:0101:0101:0101:0101:0101", &ip6ToGive); IpTunnel_allowConnection(fakePubKey, &ip6ToGive.addr, NULL, 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, IpTunnel_PacketInfoHeader_SIZE, NULL); struct IpTunnel_PacketInfoHeader* pi = (struct IpTunnel_PacketInfoHeader*) message->bytes; Bits_memcpyConst(pi->nodeIp6Addr, nodeCjdnsIp6, 16); Bits_memcpyConst(pi->nodeKey, fakePubKey, 32); *checksum = Checksum_udpIp6(ip->sourceAddr, (uint8_t*) uh, length); ipTun->nodeInterface.receiveMessage = responseWithIpCallback; ipTun->nodeInterface.sendMessage(message, &ipTun->nodeInterface); Assert_true(called); called = 0; // Now create a message for someone else. Message_shift(message, Headers_UDPHeader_SIZE + Headers_IP6Header_SIZE + IpTunnel_PacketInfoHeader_SIZE, NULL); Bits_memcpyConst(ip->sourceAddr, fakeIp6ToGive, 16); // This can't be zero. Bits_memset(ip->destinationAddr, 1, 16); ipTun->tunInterface.receiveMessage = messageToTun; ipTun->nodeInterface.sendMessage(message, &ipTun->nodeInterface); Assert_true(called); Allocator_free(alloc); return 0; }
static uint16_t completeChecksum(uint32_t state) { return Endian_hostToBigEndian16(~state & 0xFFFF); }