static uint8_t receiveMessageTUN(struct Message* msg, struct Interface* iface) { receivedMessageTUNCount++; uint16_t ethertype = TUNMessageType_pop(msg, NULL); if (ethertype != Ethernet_TYPE_IP6) { printf("Spurious packet with ethertype [%04x]\n", Endian_bigEndianToHost16(ethertype)); return 0; } struct Headers_IP6Header* header = (struct Headers_IP6Header*) msg->bytes; if (msg->length != Headers_IP6Header_SIZE + Headers_UDPHeader_SIZE + 12) { int type = (msg->length >= Headers_IP6Header_SIZE) ? header->nextHeader : -1; printf("Message of unexpected length [%u] ip6->nextHeader: [%d]\n", msg->length, type); return 0; } if (Bits_memcmp(header->destinationAddr, testAddrB, 16)) { return 0; } if (Bits_memcmp(header->sourceAddr, testAddrA, 16)) { return 0; } Bits_memcpyConst(header->destinationAddr, testAddrA, 16); Bits_memcpyConst(header->sourceAddr, testAddrB, 16); TUNMessageType_push(msg, ethertype, NULL); return iface->sendMessage(msg, iface); }
Iface_DEFUN TUNTools_genericIP6Echo(struct Message* msg, struct TUNTools* tt) { uint16_t ethertype = TUNMessageType_pop(msg, NULL); if (ethertype != Ethernet_TYPE_IP6) { Log_debug(tt->log, "Spurious packet with ethertype [%04x]\n", Endian_bigEndianToHost16(ethertype)); return 0; } struct Headers_IP6Header* header = (struct Headers_IP6Header*) msg->bytes; if (msg->length != Headers_IP6Header_SIZE + Headers_UDPHeader_SIZE + 12) { int type = (msg->length >= Headers_IP6Header_SIZE) ? header->nextHeader : -1; Log_debug(tt->log, "Message of unexpected length [%u] ip6->nextHeader: [%d]\n", msg->length, type); return 0; } uint8_t* address; Sockaddr_getAddress(tt->tunDestAddr, &address); Assert_true(!Bits_memcmp(header->destinationAddr, address, 16)); Sockaddr_getAddress(tt->udpBindTo, &address); Assert_true(!Bits_memcmp(header->sourceAddr, address, 16)); Sockaddr_getAddress(tt->udpBindTo, &address); Bits_memcpy(header->destinationAddr, address, 16); Sockaddr_getAddress(tt->tunDestAddr, &address); Bits_memcpy(header->sourceAddr, address, 16); TUNMessageType_push(msg, ethertype, NULL); return Iface_next(&tt->tunIface, msg); }
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 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 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 messageToTun(struct Message* message, struct Interface* iface) { Assert_true(TUNMessageType_pop(message, NULL) == Ethernet_TYPE_IP6); 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_memcmp(ip->sourceAddr, fakeIp6ToGive, 16)); called = 1; return 0; }
static Iface_DEFUN sendMessage(struct Message* msg, struct Iface* internal) { struct TAPWrapper_pvt* tw = Identity_containerOf(internal, struct TAPWrapper_pvt, pub.internal); uint16_t etherType = TUNMessageType_pop(msg, NULL); struct Ethernet eth = { .ethertype = etherType }; Bits_memcpyConst(eth.srcAddr, TAPWrapper_LOCAL_MAC, Ethernet_ADDRLEN); Bits_memcpyConst(eth.destAddr, tw->pub.peerAddress, Ethernet_ADDRLEN); if (Bits_isZero(tw->pub.peerAddress, Ethernet_ADDRLEN)) { Log_debug(tw->log, "DROP Packet because peers MAC is not yet known"); return NULL; } Message_push(msg, ð, sizeof(struct Ethernet), NULL); // struct Ethernet contains 2 bytes of padding at the beginning. Message_shift(msg, -2, NULL); return Iface_next(&tw->external, msg); }
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 uint8_t receiveMessageTUN(struct Message* msg, struct Interface* iface) { receivedMessageTUNCount++; uint16_t ethertype = TUNMessageType_pop(msg); if (ethertype != Ethernet_TYPE_IP4) { printf("Spurious packet with ethertype [%u]\n", Endian_bigEndianToHost16(ethertype)); return 0; } struct Headers_IP4Header* header = (struct Headers_IP4Header*) msg->bytes; Assert_always(msg->length == Headers_IP4Header_SIZE + Headers_UDPHeader_SIZE + 12); Assert_always(!Bits_memcmp(header->destAddr, testAddrB, 4)); Assert_always(!Bits_memcmp(header->sourceAddr, testAddrA, 4)); Bits_memcpyConst(header->destAddr, testAddrA, 4); Bits_memcpyConst(header->sourceAddr, testAddrB, 4); TUNMessageType_push(msg, ethertype); return iface->sendMessage(msg, iface); }
static Iface_DEFUN incomingFromTunIf(struct Message* msg, struct Iface* tunIf) { struct TUNAdapter_pvt* ud = Identity_containerOf(tunIf, struct TUNAdapter_pvt, pub.tunIf); uint16_t ethertype = TUNMessageType_pop(msg, NULL); int version = Headers_getIpVersion(msg->bytes); if ((ethertype == Ethernet_TYPE_IP4 && version != 4) || (ethertype == Ethernet_TYPE_IP6 && version != 6)) { Log_debug(ud->log, "DROP packet because ip version [%d] " "doesn't match ethertype [%u].", version, Endian_bigEndianToHost16(ethertype)); return NULL; } if (ethertype == Ethernet_TYPE_IP4) { return Iface_next(&ud->pub.ipTunnelIf, msg); } if (ethertype != Ethernet_TYPE_IP6) { Log_debug(ud->log, "DROP packet unknown ethertype [%u]", Endian_bigEndianToHost16(ethertype)); return NULL; } if (msg->length < Headers_IP6Header_SIZE) { Log_debug(ud->log, "DROP runt"); return NULL; } struct Headers_IP6Header* header = (struct Headers_IP6Header*) msg->bytes; if (!AddressCalc_validAddress(header->destinationAddr)) { return Iface_next(&ud->pub.ipTunnelIf, msg); } if (Bits_memcmp(header->sourceAddr, ud->myIp6, 16)) { if (Defined(Log_DEBUG)) { uint8_t expectedSource[40]; AddrTools_printIp(expectedSource, ud->myIp6); uint8_t packetSource[40]; AddrTools_printIp(packetSource, header->sourceAddr); Log_debug(ud->log, "DROP packet from [%s] because all messages must have source address [%s]", packetSource, expectedSource); } return NULL; } if (!Bits_memcmp(header->destinationAddr, ud->myIp6, 16)) { // I'm Gonna Sit Right Down and Write Myself a Letter TUNMessageType_push(msg, ethertype, NULL); return Iface_next(tunIf, msg); } if (!Bits_memcmp(header->destinationAddr, "\xfc\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x01", 16)) { return Iface_next(&ud->pub.magicIf, msg); } // first move the dest addr to the right place. Bits_memmoveConst(&header->destinationAddr[-DataHeader_SIZE], header->destinationAddr, 16); Message_shift(msg, DataHeader_SIZE + RouteHeader_SIZE - Headers_IP6Header_SIZE, NULL); struct RouteHeader* rh = (struct RouteHeader*) msg->bytes; struct DataHeader* dh = (struct DataHeader*) &rh[1]; Bits_memset(dh, 0, DataHeader_SIZE); DataHeader_setContentType(dh, header->nextHeader); DataHeader_setVersion(dh, DataHeader_CURRENT_VERSION); // Other than the ipv6 addr at the end, everything is zeros right down the line. Bits_memset(rh, 0, RouteHeader_SIZE - 16); return Iface_next(&ud->pub.upperDistributorIf, msg); }
// Called by the TUN device. static inline uint8_t incomingFromTun(struct Message* message, struct Interface* iface) { struct Ducttape_pvt* context = Identity_cast((struct Ducttape_pvt*) iface->receiverContext); uint16_t ethertype = TUNMessageType_pop(message); struct Headers_IP6Header* header = (struct Headers_IP6Header*) message->bytes; int version = Headers_getIpVersion(message->bytes); if ((ethertype == Ethernet_TYPE_IP4 && version != 4) || (ethertype == Ethernet_TYPE_IP6 && version != 6)) { Log_warn(context->logger, "dropped packet because ip version [%d] " "doesn't match ethertype [%u].", version, Endian_bigEndianToHost16(ethertype)); return Error_INVALID; } if (ethertype != Ethernet_TYPE_IP6 || !AddressCalc_validAddress(header->sourceAddr)) { return context->ipTunnel->tunInterface.sendMessage(message, &context->ipTunnel->tunInterface); } if (Bits_memcmp(header->sourceAddr, context->myAddr.ip6.bytes, 16)) { uint8_t expectedSource[40]; AddrTools_printIp(expectedSource, context->myAddr.ip6.bytes); uint8_t packetSource[40]; AddrTools_printIp(packetSource, header->sourceAddr); Log_warn(context->logger, "dropped packet from [%s] because all messages must have source address [%s]", (char*) packetSource, (char*) expectedSource); return Error_INVALID; } if (!Bits_memcmp(header->destinationAddr, context->myAddr.ip6.bytes, 16)) { // I'm Gonna Sit Right Down and Write Myself a Letter TUNMessageType_push(message, ethertype); iface->sendMessage(message, iface); return Error_NONE; } struct Ducttape_MessageHeader* dtHeader = getDtHeader(message, true); struct Node* bestNext = RouterModule_lookup(header->destinationAddr, context->routerModule); struct SessionManager_Session* nextHopSession; if (bestNext) { nextHopSession = SessionManager_getSession(bestNext->address.ip6.bytes, bestNext->address.key, context->sm); bestNext->version = nextHopSession->version = (bestNext->version > nextHopSession->version) ? bestNext->version : nextHopSession->version; dtHeader->switchLabel = bestNext->address.path; dtHeader->nextHopReceiveHandle = Endian_bigEndianToHost32(nextHopSession->receiveHandle_be); if (!Bits_memcmp(header->destinationAddr, bestNext->address.ip6.bytes, 16)) { // Direct send, skip the innermost layer of encryption. #ifdef Log_DEBUG uint8_t nhAddr[60]; Address_print(nhAddr, &bestNext->address); Log_debug(context->logger, "Forwarding data to %s (last hop)\n", nhAddr); #endif return sendToRouter(message, dtHeader, nextHopSession, context); } // else { the message will need to be 3 layer encrypted but since we already did a lookup // of the best node to forward to, we can skip doing another lookup by storing a pointer // to that node in the context (bestNext). } else { #ifdef Log_WARN uint8_t thisAddr[40]; uint8_t destAddr[40]; AddrTools_printIp(thisAddr, context->myAddr.ip6.bytes); AddrTools_printIp(destAddr, header->destinationAddr); Log_warn(context->logger, "Dropped message from TUN because this node [%s] is closest to dest [%s]", thisAddr, destAddr); #endif return Error_UNDELIVERABLE; } #ifdef Log_DEBUG uint8_t destAddr[40]; AddrTools_printIp(destAddr, header->destinationAddr); uint8_t nhAddr[60]; Address_print(nhAddr, &bestNext->address); Log_debug(context->logger, "Sending to [%s] via [%s]", destAddr, nhAddr); #endif struct SessionManager_Session* session = SessionManager_getSession(header->destinationAddr, NULL, context->sm); // Copy the IP6 header back from where the CA header will be placed. // this is a mess. // We can't just copy the header to a safe place because the CryptoAuth // might buffer the message and send a connect-to-me packet and when the // hello packet comes in return, the CA will send the message and the header // needs to be in the message buffer. // // The CryptoAuth may send a 120 byte CA header and it might only send a 4 byte // nonce and 16 byte authenticator depending on its state. if (CryptoAuth_getState(&session->iface) < CryptoAuth_HANDSHAKE3) { // shift, copy, shift because shifting asserts that there is enough buffer space. Message_shift(message, Headers_CryptoAuth_SIZE + 4); Bits_memcpyConst(message->bytes, header, Headers_IP6Header_SIZE); Message_shift(message, -(Headers_IP6Header_SIZE + Headers_CryptoAuth_SIZE + 4)); // now push the receive handle *under* the CA header. Message_push(message, &session->receiveHandle_be, 4); debugHandles0(context->logger, session, "layer3 sending start message"); } else { // shift, copy, shift because shifting asserts that there is enough buffer space. Message_shift(message, 20); Bits_memmoveConst(message->bytes, header, Headers_IP6Header_SIZE); Message_shift(message, -(20 + Headers_IP6Header_SIZE)); debugHandles0(context->logger, session, "layer3 sending run message"); } // This comes out at outgoingFromCryptoAuth() then outgoingFromMe() dtHeader->receiveHandle = Endian_bigEndianToHost32(session->receiveHandle_be); dtHeader->layer = Ducttape_SessionLayer_INNER; return session->iface.sendMessage(message, &session->iface); }