Пример #1
0
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);
}
Пример #2
0
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;
}
Пример #3
0
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);
}
Пример #4
0
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);
}