static uint8_t outgoingFromCryptoAuth(struct Message* message, struct Interface* iface) { struct Context* context = (struct Context*) iface->senderContext; int layer = context->layer; context->layer = INVALID_LAYER; if (layer == INNER_LAYER) { return outgoingFromMe(message, context); } else if (layer == OUTER_LAYER) { return sendToSwitch(message, context->switchHeader, context); } assert(false); }
static inline int incomingFromRouter(struct Message* message, struct Ducttape_MessageHeader* dtHeader, struct SessionManager_Session* session, struct Ducttape_pvt* context) { uint8_t* pubKey = CryptoAuth_getHerPublicKey(&session->iface); if (!validEncryptedIP6(message)) { // Not valid cjdns IPv6, we'll try it as an IPv4 or ICANN-IPv6 packet // and check if we have an agreement with the node who sent it. Message_shift(message, IpTunnel_PacketInfoHeader_SIZE); struct IpTunnel_PacketInfoHeader* header = (struct IpTunnel_PacketInfoHeader*) message->bytes; uint8_t* addr = session->ip6; Bits_memcpyConst(header->nodeIp6Addr, addr, 16); Bits_memcpyConst(header->nodeKey, pubKey, 32); struct Interface* ipTun = &context->ipTunnel->nodeInterface; return ipTun->sendMessage(message, ipTun); } struct Address srcAddr = { .path = Endian_bigEndianToHost64(dtHeader->switchHeader->label_be) }; Bits_memcpyConst(srcAddr.key, pubKey, 32); //Log_debug(context->logger, "Got message from router.\n"); int ret = core(message, dtHeader, session, context); struct Node* n = RouterModule_getNode(srcAddr.path, context->routerModule); if (!n) { Address_getPrefix(&srcAddr); RouterModule_addNode(context->routerModule, &srcAddr, session->version); } else { n->reach += 1; RouterModule_updateReach(n, context->routerModule); } return ret; } static uint8_t incomingFromCryptoAuth(struct Message* message, struct Interface* iface) { struct Ducttape_pvt* context = Identity_cast((struct Ducttape_pvt*) iface->receiverContext); struct Ducttape_MessageHeader* dtHeader = getDtHeader(message, false); enum Ducttape_SessionLayer layer = dtHeader->layer; dtHeader->layer = Ducttape_SessionLayer_INVALID; struct SessionManager_Session* session = SessionManager_sessionForHandle(dtHeader->receiveHandle, context->sm); if (!session) { // This should never happen but there's no strong preventitive. Log_info(context->logger, "SESSION DISAPPEARED!"); return 0; } // If the packet came from a new session, put the send handle in the session. if (CryptoAuth_getState(iface) < CryptoAuth_ESTABLISHED) { // If this is true then the incoming message is definitely a handshake. if (message->length < 4) { debugHandles0(context->logger, session, "runt"); return Error_INVALID; } if (layer == Ducttape_SessionLayer_OUTER) { #ifdef Version_2_COMPAT if (dtHeader->currentSessionVersion >= 3) { session->version = dtHeader->currentSessionVersion; #endif Message_pop(message, &session->sendHandle_be, 4); #ifdef Version_2_COMPAT } else { session->sendHandle_be = dtHeader->currentSessionSendHandle_be; } #endif } else { // inner layer, always grab the handle Message_pop(message, &session->sendHandle_be, 4); debugHandles0(context->logger, session, "New session, incoming layer3"); } } switch (layer) { case Ducttape_SessionLayer_OUTER: return incomingFromRouter(message, dtHeader, session, context); case Ducttape_SessionLayer_INNER: return incomingForMe(message, dtHeader, session, context, CryptoAuth_getHerPublicKey(iface)); default: Assert_always(false); } // never reached. return 0; } static uint8_t outgoingFromCryptoAuth(struct Message* message, struct Interface* iface) { struct Ducttape_pvt* context = Identity_cast((struct Ducttape_pvt*) iface->senderContext); struct Ducttape_MessageHeader* dtHeader = getDtHeader(message, false); struct SessionManager_Session* session = SessionManager_sessionForHandle(dtHeader->receiveHandle, context->sm); enum Ducttape_SessionLayer layer = dtHeader->layer; dtHeader->layer = Ducttape_SessionLayer_INVALID; if (!session) { // This should never happen but there's no strong preventitive. Log_info(context->logger, "SESSION DISAPPEARED!"); return 0; } if (layer == Ducttape_SessionLayer_OUTER) { return sendToSwitch(message, dtHeader, session, context); } else if (layer == Ducttape_SessionLayer_INNER) { Log_debug(context->logger, "Sending layer3 message"); return outgoingFromMe(message, dtHeader, session, context); } else { Assert_true(0); } } /** * Handle an incoming control message from a switch. * * @param context the ducttape context. * @param message the control message, this should be alligned on the beginning of the content, * that is to say, after the end of the switch header. * @param switchHeader the header. * @param switchIf the interface which leads to the switch. */ static uint8_t handleControlMessage(struct Ducttape_pvt* context, struct Message* message, struct Headers_SwitchHeader* switchHeader, struct Interface* switchIf) { uint8_t labelStr[20]; uint64_t label = Endian_bigEndianToHost64(switchHeader->label_be); AddrTools_printPath(labelStr, label); if (message->length < Control_HEADER_SIZE) { Log_info(context->logger, "dropped runt ctrl packet from [%s]", labelStr); return Error_NONE; } struct Control* ctrl = (struct Control*) message->bytes; if (Checksum_engine(message->bytes, message->length)) { Log_info(context->logger, "ctrl packet from [%s] with invalid checksum.", labelStr); return Error_NONE; } bool pong = false; if (ctrl->type_be == Control_ERROR_be) { if (message->length < Control_Error_MIN_SIZE) { Log_info(context->logger, "dropped runt error packet from [%s]", labelStr); return Error_NONE; } uint64_t path = Endian_bigEndianToHost64(switchHeader->label_be); RouterModule_brokenPath(path, context->routerModule); uint8_t causeType = Headers_getMessageType(&ctrl->content.error.cause); if (causeType == Headers_SwitchHeader_TYPE_CONTROL) { if (message->length < Control_Error_MIN_SIZE + Control_HEADER_SIZE) { Log_info(context->logger, "error packet from [%s] containing runt cause packet", labelStr); return Error_NONE; } struct Control* causeCtrl = (struct Control*) &(&ctrl->content.error.cause)[1]; if (causeCtrl->type_be != Control_PING_be) { Log_info(context->logger, "error packet from [%s] caused by [%s] packet ([%u])", labelStr, Control_typeString(causeCtrl->type_be), Endian_bigEndianToHost16(causeCtrl->type_be)); } else { if (LabelSplicer_isOneHop(label) && ctrl->content.error.errorType_be == Endian_hostToBigEndian32(Error_UNDELIVERABLE)) { // this is our own InterfaceController complaining // because the node isn't responding to pings. return Error_NONE; } Log_debug(context->logger, "error packet from [%s] in response to ping, err [%u], length: [%u].", labelStr, Endian_bigEndianToHost32(ctrl->content.error.errorType_be), message->length); // errors resulting from pings are forwarded back to the pinger. pong = true; } } else if (causeType != Headers_SwitchHeader_TYPE_DATA) { Log_info(context->logger, "error packet from [%s] containing cause of unknown type [%u]", labelStr, causeType); } else { Log_info(context->logger, "error packet from [%s], error type [%u]", labelStr, Endian_bigEndianToHost32(ctrl->content.error.errorType_be)); } } else if (ctrl->type_be == Control_PONG_be) { pong = true; } else if (ctrl->type_be == Control_PING_be) { Message_shift(message, -Control_HEADER_SIZE); if (message->length < Control_Ping_MIN_SIZE) { Log_info(context->logger, "dropped runt ping"); return Error_INVALID; } struct Control_Ping* ping = (struct Control_Ping*) message->bytes; ping->magic = Control_Pong_MAGIC; ping->version_be = Endian_hostToBigEndian32(Version_CURRENT_PROTOCOL); Message_shift(message, Control_HEADER_SIZE); ctrl->type_be = Control_PONG_be; ctrl->checksum_be = 0; ctrl->checksum_be = Checksum_engine(message->bytes, message->length); Message_shift(message, Headers_SwitchHeader_SIZE); Log_info(context->logger, "got switch ping from [%s]", labelStr); switchIf->receiveMessage(message, switchIf); } else { Log_info(context->logger, "control packet of unknown type from [%s], type [%d]", labelStr, Endian_bigEndianToHost16(ctrl->type_be)); } if (pong && context->pub.switchPingerIf.receiveMessage) { // Shift back over the header Message_shift(message, Headers_SwitchHeader_SIZE); context->pub.switchPingerIf.receiveMessage( message, &context->pub.switchPingerIf); } return Error_NONE; }
void udp_in(struct finsFrame* ff) { PRINT_DEBUG("UDP_in has been just called"); /* read the FDF and make sure everything is correct*/ if (ff->dataOrCtrl != 0) { // release FDF here PRINT_ERROR("it is not data"); return; } if (ff->dataFrame.directionFlag != 0) { // release FDF here PRINT_ERROR("wrong direction"); return; } if (ff->destinationID != UDPID) { // release FDF here PRINT_ERROR("wrong destination ID"); return; } /* point to the necessary data in the FDF */ struct udp_packet* packet = (struct udp_packet*)ff->dataFrame.pdu; struct udp_metadata_parsed* meta = (struct udp_metadata_parsed*)ff->dataFrame.metaData; /* begins checking the UDP packets integrity */ if (meta->u_pslen != htons(packet->u_len)) { PRINT_DEBUG("UDP length:%u", packet->u_len); udpStat.mismatchingLengths++; udpStat.totalBadDatagrams ++; PRINT_ERROR("wrong length"); return; } if (meta->u_prcl != UDP_PROTOCOL) { udpStat.wrongProtocol++; udpStat.totalBadDatagrams++; PRINT_ERROR("it is not UDP segment, I wont parse it"); return; } /* the packet is does not have an "Ignore checksum" value and fails the checksum, it is thrown away */ if (packet->u_cksum != IGNORE_CHEKSUM ){ if(UDP_checksum(packet, meta) != 0) { udpStat.badChecksum++; udpStat.totalBadDatagrams ++; PRINT_ERROR("checksum ERROR"); return; } }else{ udpStat.noChecksum++; } /* put the header into the meta data*/ meta->u_destPort = packet->u_dst; meta->u_srcPort = packet->u_src; /* construct a FDF to send to the sockets */ ff->dataFrame.pdu += U_HEADER_LEN; struct finsFrame newFF; newFF = create_ff(DATA, UP, SOCKETSTUBID, ((int)(ff->dataFrame.pdu) - U_HEADER_LEN), (ff->dataFrame.pdu), (unsigned char*)meta); sendToSwitch(&newFF); }
void udp_out(struct finsFrame* ff) { struct finsFrame* newFF; struct udp_metadata_parsed parsed_meta; /* read the FDF and make sure everything is correct*/ if (ff->dataOrCtrl != DATA) { // release FDF here return; } if (ff->dataFrame.directionFlag != DOWN) { // release FDF here return; } if (ff->destinationID.id != UDPID) { // release FDF here return; } PRINT_DEBUG("UDP_out"); print_finsFrame(ff); struct udp_header packet; struct udp_packet check_packet; u_char test[100]; metadata* meta = (ff->dataFrame).metaData; u_char *udp_dataunit = (u_char *)malloc( (ff->dataFrame).pduLength + U_HEADER_LEN ); /** constructs the UDP packet from the FDF and the meta data */ PRINT_DEBUG("%d", ff->dataFrame.pduLength); uint32_t dstbuf; uint32_t srcbuf; uint32_t dstip; uint32_t srcip; PRINT_DEBUG("UDP_out"); metadata_readFromElement(meta,"dstport",&dstbuf); metadata_readFromElement(meta,"srcport",&srcbuf); metadata_readFromElement(meta,"dstip",&dstip); metadata_readFromElement(meta,"srcip",&srcip); /** fixing the values because of the conflict between uint16 type and * the 32 bit META_INT_TYPE */ packet.u_dst = dstbuf; packet.u_src = srcbuf; PRINT_DEBUG("%d, %d", (packet.u_dst),(packet.u_src)); (packet.u_dst) = htons(packet.u_dst); (packet.u_src) = htons(packet.u_src); /* calculates the UDP length by adding the UDP header length to the length of the data */ int packet_length; packet_length= ( ((ff->dataFrame).pduLength) + U_HEADER_LEN );; packet.u_len = htons( ((ff->dataFrame).pduLength) + U_HEADER_LEN ); /** TODO ignore the checksum for now * Will be fixed later */ /** Invalidation disabled value = 0xfed2*/ parsed_meta.u_destPort = htons( packet.u_dst); parsed_meta.u_srcPort = htons( packet.u_src); parsed_meta.u_IPdst = htonl( dstip); parsed_meta.u_IPsrc = htonl( dstip); parsed_meta.u_pslen = htons( packet_length); parsed_meta.u_prcl = htons( UDP_PROTOCOL); packet.u_cksum = 0; memcpy(&check_packet,&packet,U_HEADER_LEN); memcpy(&check_packet,ff->dataFrame.pdu,ff->dataFrame.pduLength); packet.u_cksum = UDP_checksum(&check_packet,&parsed_meta); /* stores a value of zero in the checksum field so that it can be calculated */ PRINT_DEBUG("%d,%d,%d,%d", packet.u_src,packet.u_dst,packet.u_len,packet.u_cksum); // packet.u_cksum = UDP_checksum(&packet, meta); /* calculates ands stores the real checksum in the checksum field */ /* need to be careful in the line ^ above ^, the metadata needs to have the source and destination IPS in order to calculate the checksum */ //printf("The checksum Value is %d", packet.u_cksum); int i=0; while (i < ff->dataFrame.pduLength) { PRINT_DEBUG("%d",ff->dataFrame.pdu[i]); i++; } PRINT_DEBUG("UDP_out"); memcpy(udp_dataunit, &packet, U_HEADER_LEN); /* copies the UDP packet into the memory that has been allocated for the PDU */ // PRINT_DEBUG("%d, %d",(ff->dataFrame).pdu, ff->dataFrame.pduLength); memcpy(udp_dataunit + U_HEADER_LEN ,(ff->dataFrame).pdu, ff->dataFrame.pduLength); /* moves the pointer 8 bytes to account for those empty 8 bytes*/; // PRINT_DEBUG("%d",packet.u_len); /** memcpy(test, udp_dataunit, packet_length); test [packet_length] = '\0'; i=0; while (i < packet_length) { PRINT_DEBUG("%d",test[i]); i++; } //free (ff->dataFrame.pdu); PRINT_DEBUG("%s",test); PRINT_DEBUG("%d",udp_dataunit); */ ff->dataFrame.pdu = udp_dataunit; /* creates a new FDF to be sent out */ PRINT_DEBUG("%d",ff->dataFrame.pdu); PRINT_DEBUG("UDP_out"); newFF = create_ff(DATA, DOWN, IPV4ID, packet_length, ff->dataFrame.pdu, ff->dataFrame.metaData); PRINT_DEBUG("%d",newFF->dataFrame.pdu); print_finsFrame(newFF); udpStat.totalSent++; PRINT_DEBUG("UDP_out"); sendToSwitch(newFF); }