/** * If we don't know her key, the handshake has to be done backwards. * Reverse handshake requests are signaled by sending a non-obfuscated zero nonce. */ static uint8_t genReverseHandshake(struct Message* message, struct CryptoAuth_Wrapper* wrapper, union Headers_CryptoAuth* header) { reset(wrapper); Message_shift(message, -Headers_CryptoAuth_SIZE, NULL); // Buffer the packet so it can be sent ASAP if (wrapper->bufferedMessage != NULL) { // Not exactly a drop but a message is not going to reach the destination. cryptoAuthDebug0(wrapper, "DROP Expelled a message because a session has not yet been setup"); Allocator_free(wrapper->bufferedMessage->alloc); } cryptoAuthDebug0(wrapper, "Buffered a message"); struct Allocator* bmalloc = Allocator_child(wrapper->externalInterface.allocator); wrapper->bufferedMessage = Message_clone(message, bmalloc); Assert_ifParanoid(wrapper->nextNonce == 0); Message_shift(message, Headers_CryptoAuth_SIZE, NULL); header = (union Headers_CryptoAuth*) message->bytes; header->nonce = UINT32_MAX; message->length = Headers_CryptoAuth_SIZE; // sessionState must be 0, auth and 24 byte nonce are garbaged and public key is set // now garbage the authenticator and the encrypted key which are not used. Random_bytes(wrapper->context->rand, (uint8_t*) &header->handshake.authenticator, 48); // This is a special packet which the user should never see. Headers_setSetupPacket(&header->handshake.auth, 1); return wrapper->wrappedInterface->sendMessage(message, wrapper->wrappedInterface); }
/** * If we don't know her key, the handshake has to be done backwards. * Reverse handshake requests are signaled by sending a non-obfuscated zero nonce. */ static uint8_t genReverseHandshake(struct Message* message, struct Wrapper* wrapper, union Headers_CryptoAuth* header) { wrapper->nextNonce = 0; Message_shift(message, -Headers_CryptoAuth_SIZE); // Buffer the packet so it can be sent ASAP if (wrapper->bufferedMessage == NULL) { Log_debug(wrapper->context->logger, "Buffered a message.\n"); wrapper->bufferedMessage = Message_clone(message, wrapper->externalInterface.allocator); assert(wrapper->nextNonce == 0); } else { Log_debug(wrapper->context->logger, "Expelled a message because a session has not yet been setup.\n"); Message_copyOver(wrapper->bufferedMessage, message, wrapper->externalInterface.allocator); assert(wrapper->nextNonce == 0); } wrapper->hasBufferedMessage = true; Message_shift(message, Headers_CryptoAuth_SIZE); header = (union Headers_CryptoAuth*) message->bytes; header->nonce = UINT32_MAX; message->length = Headers_CryptoAuth_SIZE; // sessionState must be 0, auth and 24 byte nonce are garbaged and public key is set // now garbage the authenticator and the encrypted key which are not used. randombytes((uint8_t*) &header->handshake.authenticator, 48); return wrapper->wrappedInterface->sendMessage(message, wrapper->wrappedInterface); }
static uint8_t responseWithIpCallback(struct Message* message, struct Interface* iface) { struct IpTunnel_PacketInfoHeader* pi = (struct IpTunnel_PacketInfoHeader*) message->bytes; Assert_true(!Bits_memcmp(nodeCjdnsIp6, pi->nodeIp6Addr, 16)); Assert_true(!Bits_memcmp(fakePubKey, pi->nodeKey, 32)); Message_shift(message, -IpTunnel_PacketInfoHeader_SIZE, NULL); struct Headers_IP6Header* ip = (struct Headers_IP6Header*) message->bytes; Assert_true(Headers_getIpVersion(ip) == 6); uint16_t length = Endian_bigEndianToHost16(ip->payloadLength_be); Assert_true(length + Headers_IP6Header_SIZE == message->length); Assert_true(ip->nextHeader == 17); Assert_true(Bits_isZero(ip->sourceAddr, 32)); Message_shift(message, -Headers_IP6Header_SIZE, NULL); struct Headers_UDPHeader* uh = (struct Headers_UDPHeader*) message->bytes; Assert_true(!Checksum_udpIp6(ip->sourceAddr, message->bytes, length)); Assert_true(uh->srcPort_be == 0); Assert_true(uh->destPort_be == 0); Assert_true(Endian_bigEndianToHost16(uh->length_be) + Headers_UDPHeader_SIZE == length); Message_shift(message, -Headers_UDPHeader_SIZE, NULL); char* expectedResponse = "d" "9:addresses" "d" "3:ip6" "16:\xfd\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1" "e" "4:txid" "4:abcd" "e"; Assert_true(message->length == (int32_t) CString_strlen(expectedResponse)); Assert_true(!Bits_memcmp(message->bytes, expectedResponse, message->length)); called = 1; return 0; }
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 uint8_t receiveMessage(struct Message* received, struct Interface* interface) { struct CryptoAuth_Wrapper* wrapper = Identity_cast((struct CryptoAuth_Wrapper*) interface->receiverContext); union Headers_CryptoAuth* header = (union Headers_CryptoAuth*) received->bytes; if (received->length < (wrapper->authenticatePackets ? 20 : 4)) { cryptoAuthDebug0(wrapper, "Dropped runt"); return Error_UNDERSIZE_MESSAGE; } Assert_true(received->padding >= 12 || "need at least 12 bytes of padding in incoming message"); #ifdef Log_DEBUG Assert_true(!((uintptr_t)received->bytes % 4) || !"alignment fault"); #endif Message_shift(received, -4); uint32_t nonce = Endian_bigEndianToHost32(header->nonce); if (wrapper->nextNonce < 5) { if (nonce > 3 && nonce != UINT32_MAX && knowHerKey(wrapper)) { cryptoAuthDebug(wrapper, "Trying final handshake step, nonce=%u\n", nonce); uint8_t secret[32]; getSharedSecret(secret, wrapper->secret, wrapper->tempKey, NULL, wrapper->context->logger); // We'll optimistically advance the nextNonce value because decryptMessage() // passes the message on to the upper level and if this message causes a // response, we want the CA to be in ESTABLISHED state. // if the decryptMessage() call fails, we CryptoAuth_reset() it back. wrapper->nextNonce += 3; if (decryptMessage(wrapper, nonce, received, secret)) { cryptoAuthDebug0(wrapper, "Final handshake step succeeded"); Bits_memcpyConst(wrapper->secret, secret, 32); return callReceivedMessage(wrapper, received); } CryptoAuth_reset(&wrapper->externalInterface); cryptoAuthDebug0(wrapper, "Final handshake step failed"); return Error_UNDELIVERABLE; } } else if (nonce > 4) { if (decryptMessage(wrapper, nonce, received, wrapper->secret)) { return callReceivedMessage(wrapper, received); } else { cryptoAuthDebug0(wrapper, "Failed to decrypt message"); return Error_UNDELIVERABLE; } } else { cryptoAuthDebug0(wrapper, "Received handshake message during established connection"); } Message_shift(received, 4); return decryptHandshake(wrapper, nonce, received, header); }
/** 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 = Headers_SwitchHeader_SIZE; if (CryptoAuth_getState(&session->iface) < CryptoAuth_HANDSHAKE3) { // Bug 104, see Version.h #ifdef Version_2_COMPAT if (session->version >= 3) { #endif // 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); #ifdef Version_2_COMPAT } else { // Otherwise it will be added on the other side. safeDistance += 4; } #endif safeDistance += Headers_CryptoAuth_SIZE; } else { // 16 for the authenticator, 4 for the nonce and 4 for the handle safeDistance += 24; } Message_shift(message, safeDistance); if (dtHeader->switchHeader) { if (message->bytes != (uint8_t*)dtHeader->switchHeader) { Bits_memmoveConst(message->bytes, dtHeader->switchHeader, Headers_SwitchHeader_SIZE); dtHeader->switchHeader = (struct Headers_SwitchHeader*) message->bytes; } } else { dtHeader->switchHeader = (struct Headers_SwitchHeader*) message->bytes; Bits_memset(dtHeader->switchHeader, 0, Headers_SwitchHeader_SIZE); } Message_shift(message, -safeDistance); 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 session->iface.sendMessage(message, &session->iface); }
static struct Ducttape_MessageHeader* getDtHeader(struct Message* message, bool init) { int padding = message->padding; Assert_true(padding > Ducttape_MessageHeader_SIZE); Message_shift(message, padding); struct Ducttape_MessageHeader* dtHeader = (struct Ducttape_MessageHeader*) message->bytes; Message_shift(message, -padding); if (init) { Bits_memset(dtHeader, 0, Ducttape_MessageHeader_SIZE); Identity_set(dtHeader); } else { Identity_check(dtHeader); } return dtHeader; }
/** * send message via pipe to core process */ static void sendToCore(struct Message* message, uint32_t connNumber, struct AngelContext* context) { Message_shift(message, 4); Bits_memcpyConst(message->bytes, &connNumber, 4); //Log_debug(context->logger, "sending Message to core"); context->coreIface->sendMessage(message, context->coreIface); }
static Iface_DEFUN incomingFromUpperDistributorIf(struct Message* msg, struct Iface* upperDistributorIf) { struct TUNAdapter_pvt* ud = Identity_containerOf(upperDistributorIf, struct TUNAdapter_pvt, pub.upperDistributorIf); Assert_true(msg->length >= RouteHeader_SIZE + DataHeader_SIZE); struct RouteHeader* hdr = (struct RouteHeader*) msg->bytes; struct DataHeader* dh = (struct DataHeader*) &hdr[1]; enum ContentType type = DataHeader_getContentType(dh); Assert_true(type <= ContentType_IP6_RAW); // Shift ip address into destination slot. Bits_memmoveConst(&hdr->ip6[DataHeader_SIZE - 16], hdr->ip6, 16); // put my address as destination. Bits_memcpyConst(&hdr->ip6[DataHeader_SIZE], ud->myIp6, 16); Message_shift(msg, Headers_IP6Header_SIZE - DataHeader_SIZE - RouteHeader_SIZE, NULL); struct Headers_IP6Header* ip6 = (struct Headers_IP6Header*) msg->bytes; Bits_memset(ip6, 0, Headers_IP6Header_SIZE - 32); Headers_setIpVersion(ip6); ip6->payloadLength_be = Endian_bigEndianToHost16(msg->length - Headers_IP6Header_SIZE); ip6->nextHeader = type; ip6->hopLimit = 42; TUNMessageType_push(msg, Ethernet_TYPE_IP6, NULL); return sendToTunIf(msg, ud); }
void Sign_signMsg(uint8_t keyPair[64], struct Message* msg, struct Random* rand) { // az is set to the secret key followed by another secret value // which since we don't have a secret seed in this algorithm is just the // hash of the secret key and 32 bytes of random uint8_t az[64]; uint8_t r[64]; ge_p3 R; uint8_t hram[64]; Bits_memcpy(az, keyPair, 32); Random_bytes(rand, &az[32], 32); crypto_hash_sha512(az,az,64); Bits_memcpy(az, keyPair, 32); az[0] &= 248; az[31] &= 63; az[31] |= 64; // hash message + secret number Message_push(msg, &az[32], 32, NULL); crypto_hash_sha512(r, msg->bytes, msg->length); // Replace secret number with public key Bits_memcpy(msg->bytes, &keyPair[32], 32); // push pointMul(r) to message sc_reduce(r); ge_scalarmult_base(&R,r); Message_shift(msg, 32, NULL); ge_p3_tobytes(msg->bytes,&R); crypto_hash_sha512(hram, msg->bytes, msg->length); sc_reduce(hram); sc_muladd(&msg->bytes[32], hram, az, r); }
uint8_t incomingTunA(struct Message* msg, struct Interface* iface) { Message_shift(msg, -Headers_IP6Header_SIZE); printf("Message from TUN in node A [%s]\n", msg->bytes); *((int*)iface->senderContext) = TUNA; 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); }
uint16_t TUNMessageType_pop_BSD(struct Message* message) { Message_shift(message, -4); uint16_t afType_be = ((uint16_t*) message->bytes)[-1]; return (afType_be == AF_INET6_BE) ? Ethernet_TYPE_IP6 : Ethernet_TYPE_IP4; }
/** * Incoming message from someone we don't know, maybe someone responding to a beacon? * expects: [ struct LLAddress ][ content ] */ static Iface_DEFUN handleUnexpectedIncoming(struct Message* msg, struct InterfaceController_Iface_pvt* ici) { struct InterfaceController_pvt* ic = ici->ic; struct Sockaddr* lladdr = (struct Sockaddr*) msg->bytes; Message_shift(msg, -lladdr->addrLen, NULL); if (msg->length < CryptoHeader_SIZE) { return NULL; } struct Allocator* epAlloc = Allocator_child(ici->alloc); lladdr = Sockaddr_clone(lladdr, epAlloc); Assert_true(!((uintptr_t)msg->bytes % 4) && "alignment fault"); struct Peer* ep = Allocator_calloc(epAlloc, sizeof(struct Peer), 1); Identity_set(ep); ep->alloc = epAlloc; ep->ici = ici; ep->lladdr = lladdr; ep->alloc = epAlloc; ep->peerLink = PeerLink_new(ic->eventBase, epAlloc); struct CryptoHeader* ch = (struct CryptoHeader*) msg->bytes; ep->caSession = CryptoAuth_newSession(ic->ca, epAlloc, ch->publicKey, true, "outer"); if (CryptoAuth_decrypt(ep->caSession, msg)) { // If the first message is a dud, drop all state for this peer. // probably some random crap that wandered in the socket. Allocator_free(epAlloc); return NULL; } Assert_true(!Bits_isZero(ep->caSession->herPublicKey, 32)); Assert_true(Map_EndpointsBySockaddr_indexForKey(&lladdr, &ici->peerMap) == -1); int index = Map_EndpointsBySockaddr_put(&lladdr, &ep, &ici->peerMap); Assert_true(index >= 0); ep->handle = ici->peerMap.handles[index]; Allocator_onFree(epAlloc, closeInterface, ep); ep->state = InterfaceController_PeerState_UNAUTHENTICATED; ep->isIncomingConnection = true; ep->switchIf.send = sendFromSwitch; if (SwitchCore_addInterface(ic->switchCore, &ep->switchIf, epAlloc, &ep->addr.path)) { Log_debug(ic->logger, "handleUnexpectedIncoming() SwitchCore out of space"); Allocator_free(epAlloc); return NULL; } // We want the node to immedietly be pinged but we don't want it to appear unresponsive because // the pinger will only ping every (PING_INTERVAL * 8) so we set timeOfLastMessage to // (now - pingAfterMilliseconds - 1) so it will be considered a "lazy node". ep->timeOfLastMessage = Time_currentTimeMilliseconds(ic->eventBase) - ic->pingAfterMilliseconds - 1; Bits_memcpy(ep->addr.key, ep->caSession->herPublicKey, 32); Bits_memcpy(ep->addr.ip6.bytes, ep->caSession->herIp6, 16); Log_info(ic->logger, "Added peer [%s] from incoming message", Address_toString(&ep->addr, msg->alloc)->bytes); return receivedPostCryptoAuth(msg, ep, ic); }
void TUNMessageType_push_BSD(struct Message* message, uint16_t ethertype) { uint16_t afType_be = (ethertype == Ethernet_TYPE_IP6) ? AF_INET6_BE : AF_INET_BE; Message_shift(message, 4); ((uint16_t*) message->bytes)[0] = 0; ((uint16_t*) message->bytes)[1] = afType_be; }
uint8_t incomingTunA(struct Message* msg, struct Interface* iface) { Assert_true(TUNMessageType_pop(msg) == Ethernet_TYPE_IP6); Message_shift(msg, -Headers_IP6Header_SIZE); printf("Message from TUN in node A [%s]\n", msg->bytes); *((int*)iface->senderContext) = TUNA; return 0; }
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 uint8_t receiveMessage(struct Message* received, struct Interface* interface) { struct CryptoAuth_Wrapper* wrapper = (struct CryptoAuth_Wrapper*) interface->receiverContext; union Headers_CryptoAuth* header = (union Headers_CryptoAuth*) received->bytes; if (received->length < (wrapper->authenticatePackets ? 20 : 4)) { Log_debug(wrapper->context->logger, "Dropped runt"); return Error_UNDERSIZE_MESSAGE; } Assert_true(received->padding >= 12 || "need at least 12 bytes of padding in incoming message"); #ifdef Log_DEBUG Assert_true(!((uintptr_t)received->bytes % 4) || !"alignment fault"); #endif Message_shift(received, -4); uint32_t nonce = Endian_bigEndianToHost32(header->nonce); if (wrapper->nextNonce < 5) { if (nonce > 3 && nonce != UINT32_MAX && knowHerKey(wrapper)) { Log_debug(wrapper->context->logger, "@%p Trying final handshake step, nonce=%u\n", (void*) wrapper, nonce); uint8_t secret[32]; getSharedSecret(secret, wrapper->secret, wrapper->tempKey, NULL, wrapper->context->logger); if (decryptMessage(wrapper, nonce, received, secret)) { Log_debug(wrapper->context->logger, "Final handshake step succeeded.\n"); wrapper->nextNonce += 3; Bits_memcpyConst(wrapper->secret, secret, 32); return Error_NONE; } CryptoAuth_reset(&wrapper->externalInterface); Log_debug(wrapper->context->logger, "Final handshake step failed.\n"); } } else if (nonce > 2 && decryptMessage(wrapper, nonce, received, wrapper->secret)) { // If decryptMessage returns false then we will try the packet as a handshake. return Error_NONE; } else { Log_debug(wrapper->context->logger, "Decryption failed, trying message as a handshake.\n"); } Message_shift(received, 4); return decryptHandshake(wrapper, nonce, received, header); }
static void popSockaddr(struct Message* msg, struct Sockaddr_storage* ss) { uint64_t length = 0; Message_pop(msg, &length, 8, NULL); Message_shift(msg, 8, NULL); Assert_true(length >= Sockaddr_OVERHEAD); Assert_true(length <= sizeof(struct Sockaddr_storage)); Message_pop(msg, ss, length, NULL); }
static Iface_DEFUN incomingTunB(struct Message* msg, struct Iface* tunB) { struct TwoNodes* tn = Identity_containerOf(tunB, struct TwoNodes, tunB); Assert_true(TUNMessageType_pop(msg, NULL) == Ethernet_TYPE_IP6); Message_shift(msg, -Headers_IP6Header_SIZE, NULL); printf("Message from TUN in node B [%s]\n", msg->bytes); tn->messageFrom = TUNB; return 0; }
static void pushRouteDataHeaders(struct Context* ctx, struct Message* message) { 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, ctx->ipv6, 16); Bits_memcpy(rh->publicKey, ctx->pubKey, 32); DataHeader_setContentType(dh, ContentType_IPTUN); }
static Iface_DEFUN responseWithIpCallback(struct Message* message, struct Iface* iface) { struct Context* ctx = Identity_check(((struct IfaceContext*)iface)->ctx); struct RouteHeader* rh = (struct RouteHeader*) message->bytes; Assert_true(!Bits_memcmp(ctx->ipv6, rh->ip6, 16)); Assert_true(!Bits_memcmp(ctx->pubKey, rh->publicKey, 32)); Message_shift(message, -(RouteHeader_SIZE + DataHeader_SIZE), NULL); struct Headers_IP6Header* ip = (struct Headers_IP6Header*) message->bytes; Assert_true(Headers_getIpVersion(ip) == 6); uint16_t length = Endian_bigEndianToHost16(ip->payloadLength_be); Assert_true(length + Headers_IP6Header_SIZE == message->length); Assert_true(ip->nextHeader == 17); Assert_true(Bits_isZero(ip->sourceAddr, 32)); Message_shift(message, -Headers_IP6Header_SIZE, NULL); struct Headers_UDPHeader* uh = (struct Headers_UDPHeader*) message->bytes; Assert_true(!Checksum_udpIp6(ip->sourceAddr, message->bytes, length)); Assert_true(uh->srcPort_be == 0); Assert_true(uh->destPort_be == 0); Assert_true(Endian_bigEndianToHost16(uh->length_be) + Headers_UDPHeader_SIZE == length); Message_shift(message, -Headers_UDPHeader_SIZE, NULL); struct Allocator* alloc = Allocator_child(ctx->alloc); char* messageContent = Escape_getEscaped(message->bytes, message->length, alloc); char* expectedContent = Escape_getEscaped(ctx->expectedResponse->bytes, ctx->expectedResponse->len, alloc); Log_debug(ctx->log, "Response: [%s]", messageContent); Log_debug(ctx->log, "Expected: [%s]", expectedContent); Allocator_free(alloc); // We can't check that the message is an exact match because the padding depends on the // alignment of the output but we can make sure the right content is there... // Message should start with "d0000" (with some number of zeros) Assert_true((int)ctx->expectedResponse->len == message->length); Assert_true(!Bits_memcmp(message->bytes, ctx->expectedResponse->bytes, message->length)); ctx->called |= 2; return NULL; }
static Iface_DEFUN incomingTunA(struct Message* msg, struct Iface* tunA) { struct TwoNodes* tn = Identity_containerOf(tunA, struct TwoNodes, tunA); Assert_true(TUNMessageType_pop(msg, NULL) == Ethernet_TYPE_IP6); Message_shift(msg, -Headers_IP6Header_SIZE, NULL); uint8_t buff[1024]; Hex_encode(buff, 1024, msg->bytes, msg->length); printf("Message from TUN in node A [%s] [%d] [%s]\n", msg->bytes, msg->length, buff); tn->messageFrom = TUNA; return 0; }
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 Iface_DEFUN incomingFromUs(struct Message* message, struct Iface* internalIf) { struct TUNInterface_Illumos_pvt* ctx = Identity_containerOf(internalIf, struct TUNInterface_Illumos_pvt, internalIf); Message_shift(message, -4, NULL); uint16_t ethertype = ((uint16_t*) message->bytes)[-1]; if (ethertype != Ethernet_TYPE_IP6 && ethertype != Ethernet_TYPE_IP4) { Assert_true(!"Unsupported ethertype"); } return Iface_next(&ctx->externalIf, message); }
static Iface_DEFUN responseWithIpCallback(struct Message* message, struct Iface* iface) { struct RouteHeader* rh = (struct RouteHeader*) message->bytes; Assert_true(!Bits_memcmp(nodeCjdnsIp6, rh->ip6, 16)); Assert_true(!Bits_memcmp(fakePubKey, rh->publicKey, 32)); Message_shift(message, -(RouteHeader_SIZE + DataHeader_SIZE), NULL); struct Headers_IP6Header* ip = (struct Headers_IP6Header*) message->bytes; Assert_true(Headers_getIpVersion(ip) == 6); uint16_t length = Endian_bigEndianToHost16(ip->payloadLength_be); Assert_true(length + Headers_IP6Header_SIZE == message->length); Assert_true(ip->nextHeader == 17); Assert_true(Bits_isZero(ip->sourceAddr, 32)); Message_shift(message, -Headers_IP6Header_SIZE, NULL); struct Headers_UDPHeader* uh = (struct Headers_UDPHeader*) message->bytes; Assert_true(!Checksum_udpIp6(ip->sourceAddr, message->bytes, length)); Assert_true(uh->srcPort_be == 0); Assert_true(uh->destPort_be == 0); Assert_true(Endian_bigEndianToHost16(uh->length_be) + Headers_UDPHeader_SIZE == length); Message_shift(message, -Headers_UDPHeader_SIZE, NULL); // We can't check that the message is an exact match because the padding depends on the // alignment of the output but we can make sure the right content is there... // Message should start with "d0000" (with some number of zeros) char* expectedResponse = "9:addresses" "d" "3:ip6" "16:\xfd\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1" "9:ip6Prefix" "i128e" "e" "4:txid" "4:abcd" "e"; Assert_true(message->length >= (int32_t) CString_strlen(expectedResponse)); Assert_true(CString_strstr(message->bytes, expectedResponse)); called |= 2; return 0; }
static Iface_DEFUN messageToTun(struct Message* msg, struct Iface* iface) { struct Context* ctx = Identity_check(((struct IfaceContext*)iface)->ctx); uint16_t type = TUNMessageType_pop(msg, NULL); if (type == Ethernet_TYPE_IP6) { struct Headers_IP6Header* ip = (struct Headers_IP6Header*) msg->bytes; Assert_true(Headers_getIpVersion(ip) == 6); Assert_true(!Bits_memcmp(ip->sourceAddr, ctx->sendingAddress, 16)); Message_shift(msg, -Headers_IP6Header_SIZE, NULL); ctx->called |= 4; } else if (type == Ethernet_TYPE_IP4) { struct Headers_IP4Header* ip = (struct Headers_IP4Header*) msg->bytes; Assert_true(Headers_getIpVersion(ip) == 4); Assert_true(!Bits_memcmp(ip->sourceAddr, ctx->sendingAddress, 4)); Message_shift(msg, -Headers_IP4Header_SIZE, NULL); ctx->called |= 1; } else { Assert_failure("unrecognized message type %u", (unsigned int)type); } Assert_true(msg->length == 12 && CString_strcmp(msg->bytes, "hello world") == 0); return 0; }
static Iface_DEFUN sendNode(struct Message* msg, struct Address* addr, uint32_t metric, struct Pathfinder_pvt* pf) { Message_reset(msg); Message_shift(msg, PFChan_Node_SIZE, NULL); nodeForAddress((struct PFChan_Node*) msg->bytes, addr, metric); if (addr->path == UINT64_MAX) { ((struct PFChan_Node*) msg->bytes)->path_be = 0; } Message_push32(msg, PFChan_Pathfinder_NODE, NULL); return Iface_next(&pf->pub.eventIf, msg); }
static Iface_DEFUN handleError(struct Message* msg, struct ControlHandler_pvt* ch, uint64_t label, uint8_t* labelStr) { if (msg->length < handleError_MIN_SIZE) { Log_info(ch->log, "DROP runt error packet from [%s]", labelStr); return NULL; } Message_shift(msg, SwitchHeader_SIZE + 4, NULL); Message_push32(msg, 0xffffffff, NULL); Message_push32(msg, PFChan_Core_SWITCH_ERR, NULL); return Iface_next(&ch->eventIf, msg); }