/** * 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); }
/** * Messages with content encrypted and header decrypted are sent here to be forwarded. * they may come from us, or from another node and may be to us or to any other node. * Message is aligned on the beginning of the ipv6 header. */ static inline int core(struct Message* message, struct Ducttape_MessageHeader* dtHeader, struct SessionManager_Session* session, struct Ducttape_pvt* context) { struct Headers_IP6Header* ip6Header = (struct Headers_IP6Header*) message->bytes; dtHeader->ip6Header = ip6Header; if (isForMe(message, context)) { Message_shift(message, -Headers_IP6Header_SIZE); if (Bits_memcmp(session->ip6, ip6Header->sourceAddr, 16)) { // triple encrypted // This call goes to incomingForMe() struct SessionManager_Session* session = SessionManager_getSession(ip6Header->sourceAddr, NULL, context->sm); #ifdef Log_DEBUG uint8_t addr[40]; AddrTools_printIp(addr, ip6Header->sourceAddr); Log_debug(context->logger, "Incoming layer3 message, ostensibly from [%s]", addr); #endif dtHeader->receiveHandle = Endian_bigEndianToHost32(session->receiveHandle_be); dtHeader->layer = Ducttape_SessionLayer_INNER; return session->iface.receiveMessage(message, &session->iface); } else { // double encrypted, inner layer plaintext. // The session is still set from the router-to-router traffic and that is the one we use // to determine the node's id. return incomingForMe(message, dtHeader, session, context, CryptoAuth_getHerPublicKey(&session->iface)); } } if (ip6Header->hopLimit == 0) { Log_debug(context->logger, "dropped message because hop limit has been exceeded.\n"); // TODO: send back an error message in response. return Error_UNDELIVERABLE; } ip6Header->hopLimit--; struct SessionManager_Session* nextHopSession = NULL; if (!dtHeader->nextHopReceiveHandle || !dtHeader->switchLabel) { struct Node* n = RouterModule_lookup(ip6Header->destinationAddr, context->routerModule); if (n) { nextHopSession = SessionManager_getSession(n->address.ip6.bytes, n->address.key, context->sm); dtHeader->switchLabel = n->address.path; } } else { nextHopSession = SessionManager_sessionForHandle(dtHeader->nextHopReceiveHandle, context->sm); } if (nextHopSession) { #ifdef Log_DEBUG struct Address addr; Bits_memcpyConst(addr.ip6.bytes, nextHopSession->ip6, 16); addr.path = dtHeader->switchLabel; uint8_t nhAddr[60]; Address_print(nhAddr, &addr); if (Bits_memcmp(ip6Header->destinationAddr, addr.ip6.bytes, 16)) { // Potentially forwarding for ourselves. struct Address destination; Bits_memcpyConst(destination.ip6.bytes, ip6Header->destinationAddr, 16); uint8_t ipAddr[40]; Address_printIp(ipAddr, &destination); Log_debug(context->logger, "Forwarding data to %s via %s\n", ipAddr, nhAddr); } else { // Definitely forwarding on behalf of someone else. Log_debug(context->logger, "Forwarding data to %s (last hop)\n", nhAddr); } #endif return sendToRouter(message, dtHeader, nextHopSession, context); } #ifdef Log_INFO struct Address destination; Bits_memcpyConst(destination.ip6.bytes, ip6Header->destinationAddr, 16); uint8_t ipAddr[40]; Address_printIp(ipAddr, &destination); Log_info(context->logger, "Dropped message because this node is the closest known " "node to the destination %s.", ipAddr); #endif return Error_UNDELIVERABLE; }
/** * Messages with content encrypted and header decrypted are sent here to be forwarded. * they may come from us, or from another node and may be to us or to any other node. * Message is aligned on the beginning of the ipv6 header. */ static inline int core(struct Message* message, struct Ducttape* context) { context->ip6Header = (struct Headers_IP6Header*) message->bytes; if (isForMe(message, context)) { Message_shift(message, -Headers_IP6Header_SIZE); if (memcmp(context->routerAddress, context->ip6Header->sourceAddr, 16)) { // triple encrypted // This call goes to incomingForMe() context->layer = INNER_LAYER; context->session = SessionManager_getSession(context->ip6Header->sourceAddr, NULL, context->sm); return context->session->receiveMessage(message, context->session); } else { // double encrypted, inner layer plaintext. // The session is still set from the router-to-router traffic and that is the one we use // to determine the node's id. return incomingForMe(message, context, CryptoAuth_getHerPublicKey(context->session)); } } if (context->ip6Header->hopLimit == 0) { Log_debug(context->logger, "dropped message because hop limit has been exceeded.\n"); // TODO: send back an error message in response. return Error_UNDELIVERABLE; } context->ip6Header->hopLimit--; struct Address* ft = context->forwardTo; context->forwardTo = NULL; if (!ft) { struct Node* bestNext = RouterModule_lookup(context->ip6Header->destinationAddr, context->routerModule); if (bestNext) { ft = &bestNext->address; } } if (ft) { #ifdef Log_DEBUG uint8_t nhAddr[60]; Address_print(nhAddr, ft); if (memcmp(context->ip6Header->destinationAddr, ft->ip6.bytes, 16)) { // Potentially forwarding for ourselves. struct Address destination; Bits_memcpyConst(destination.ip6.bytes, context->ip6Header->destinationAddr, 16); uint8_t ipAddr[40]; Address_printIp(ipAddr, &destination); Log_debug2(context->logger, "Forwarding data to %s via %s\n", ipAddr, nhAddr); } else { // Definitely forwarding on behalf of someone else. Log_debug1(context->logger, "Forwarding data to %s (last hop)\n", nhAddr); } #endif return sendToRouter(ft, message, context); } Log_debug(context->logger, "Dropped message because this node is the closest known " "node to the destination.\n"); return Error_UNDELIVERABLE; }
/** * Messages with content encrypted and header decrypted are sent here to be forwarded. * they may come from us, or from another node and may be to us or to any other node. * Message is aligned on the beginning of the ipv6 header. */ static inline int core(struct Message* message, struct Context* context) { context->ip6Header = (struct Headers_IP6Header*) message->bytes; if (!validIP6(message)) { Log_debug(context->logger, "Dropping message because of invalid ipv6 header.\n"); return Error_INVALID; } // Do this here and check for 1 hop, not 0 because we want to differentiate between single // hop traffic and routed traffic as single hop traffic doesn't need 2 layers of crypto. if (context->ip6Header->hopLimit == 1) { Log_debug(context->logger, "dropped message because hop limit has been exceeded.\n"); // TODO: send back an error message in response. return Error_UNDELIVERABLE; } if (isForMe(message, context)) { Message_shift(message, -Headers_IP6Header_SIZE); if (context->ip6Header->hopLimit != 0) { // triple encrypted // This call goes to incomingForMe() context->layer = INNER_LAYER; context->session = SessionManager_getSession(context->ip6Header->sourceAddr, NULL, context->sm); return context->session->receiveMessage(message, context->session); } else { // double encrypted, inner layer plaintext. // The session is still set from the router-to-router traffic and that is the one we use // to determine the node's id. return incomingForMe(message, context); } } if (context->ip6Header->hopLimit == 0) { Log_debug(context->logger, "0 hop message not addressed to us, broken route.\n"); return 0; } context->ip6Header->hopLimit--; struct Address* ft = context->forwardTo; context->forwardTo = NULL; if (!ft) { struct Node* bestNext = RouterModule_getBest(context->ip6Header->destinationAddr, context->routerModule); if (bestNext) { ft = &bestNext->address; } } if (ft) { #ifdef Log_DEBUG uint8_t nhAddr[60]; Address_print(nhAddr, ft); if (memcmp(context->ip6Header->destinationAddr, ft->ip6.bytes, 16)) { // Potentially forwarding for ourselves. struct Address destination; memcpy(destination.ip6.bytes, context->ip6Header->destinationAddr, 16); uint8_t ipAddr[40]; Address_printIp(ipAddr, &destination); Log_debug2(context->logger, "Forwarding data to %s via %s\n", ipAddr, nhAddr); } else { // Definitely forwarding on behalf of someone else. Log_debug1(context->logger, "Forwarding data to %s (last hop)\n", nhAddr); } #endif return sendToRouter(ft, message, context); } Log_debug(context->logger, "Dropped message because this node is the closest known " "node to the destination.\n"); return Error_UNDELIVERABLE; }