Example #1
0
static uint8_t receiveMessage(struct Message* msg, struct Interface* iface)
{
    struct Aligner_pvt* al = Identity_check((struct Aligner_pvt*)iface->receiverContext);
    alignMessage(msg, al->alignmentBytes);
    Interface_receiveMessage(&al->pub.generic, msg);
    return 0;
}
Example #2
0
static uint8_t receiveMessage(struct Message* message, struct Interface* iface)
{
    struct AddrInterfaceAdapter_pvt* context =
        Identity_cast((struct AddrInterfaceAdapter_pvt*) iface->receiverContext);

    Message_push(message, context->pub.addr, context->pub.addr->addrLen, NULL);
    return Interface_receiveMessage(&context->pub.generic, message);
}
Example #3
0
// Incoming message which has passed through the cryptoauth and needs to be forwarded to the switch.
static uint8_t receivedAfterCryptoAuth(struct Message* msg, struct Interface* cryptoAuthIf)
{
    struct InterfaceController_Peer* ep =
        Identity_check((struct InterfaceController_Peer*) cryptoAuthIf->receiverContext);
    struct InterfaceController_pvt* ic = ifcontrollerForPeer(ep);

    // nonce added by the CryptoAuth session.
    Message_pop(msg, NULL, 4, NULL);

    ep->bytesIn += msg->length;

    int caState = CryptoAuth_getState(cryptoAuthIf);
    if (ep->state < InterfaceController_PeerState_ESTABLISHED) {
        // EP states track CryptoAuth states...
        ep->state = caState;
        if (caState == CryptoAuth_ESTABLISHED) {
            moveEndpointIfNeeded(ep, ic);
        } else {
            // prevent some kinds of nasty things which could be done with packet replay.
            // This is checking the message switch header and will drop it unless the label
            // directs it to *this* router.
            if (msg->length < 8 || msg->bytes[7] != 1) {
                Log_info(ic->logger, "DROP message because CA is not established.");
                return Error_NONE;
            } else {
                // When a "server" gets a new connection from a "client" the router doesn't
                // know about that client so if the client sends a packet to the server, the
                // server will be unable to handle it until the client has sent inter-router
                // communication to the server. Here we will ping the client so when the
                // server gets the ping response, it will insert the client into its table
                // and know its version.

                // prevent DoS by limiting the number of times this can be called per second
                // limit it to 7, this will affect innocent packets but it doesn't matter much
                // since this is mostly just an optimization and for keeping the tests happy.
                if ((ep->pingCount + 1) % 7) {
                    sendPing(ep);
                }
            }
        }
    } else if (ep->state == InterfaceController_PeerState_UNRESPONSIVE
        && caState == CryptoAuth_ESTABLISHED)
    {
        ep->state = InterfaceController_PeerState_ESTABLISHED;
    } else {
        ep->timeOfLastMessage = Time_currentTimeMilliseconds(ic->eventBase);
    }

    Identity_check(ep);
    Assert_true(!(msg->capacity % 4));
    return Interface_receiveMessage(&ep->switchIf, msg);
}
Example #4
0
static uint8_t receiveMessage(struct Message* message, struct Interface* iface)
{
    struct TUNInterface_Illumos_pvt* ctx =
        Identity_check((struct TUNInterface_Illumos_pvt*)iface->receiverContext);

    if (message->length < 4) {
        return Error_NONE;
    }

    Message_shift(message, 4);
    ((uint16_t*) message->bytes)[0] = 0;
    ((uint16_t*) message->bytes)[1] = ethertypeForPacketType(message->bytes[4]);

    return Interface_receiveMessage(&ctx->generic, message);
}
Example #5
0
static uint8_t receiveMessage(struct Message* msg, struct Interface* iface)
{
    struct SessionManager_Session_pvt* ss =
        Identity_check((struct SessionManager_Session_pvt*)iface->receiverContext);

    // nonce added by CryptoAuth
    Message_pop(msg, NULL, 4, NULL);

    uint64_t timeOfLastIn = ss->pub.timeOfLastIn;
    ss->pub.timeOfLastIn = Time_currentTimeMilliseconds(ss->sm->eventBase);
    int prevState = ss->pub.cryptoAuthState;
    ss->pub.cryptoAuthState = CryptoAuth_getState(ss->pub.internal);
    if ((ss->pub.timeOfLastIn - timeOfLastIn) > STATE_UPDATE_TIME
        || prevState != ss->pub.cryptoAuthState)
    {
        stateChange(ss, timeOfLastIn, ss->pub.timeOfLastOut, prevState);
    }

    return Interface_receiveMessage(&ss->sm->iface, msg);
}
Example #6
0
int main()
{
    struct Allocator* mainAlloc = MallocAllocator_new(1<<20);
    struct Log* log = FileWriterLog_new(stdout, mainAlloc);
    struct Random* rand = Random_new(mainAlloc, log, NULL);
    struct Context* ctx = Allocator_malloc(mainAlloc, sizeof(struct Context));
    Identity_set(ctx);

    struct Interface iface = { .sendMessage = NULL };
    struct Interface* fi = FramingInterface_new(4096, &iface, mainAlloc);
    fi->receiveMessage = messageOut;
    fi->receiverContext = ctx;

    for (int i = 0; i < CYCLES; i++) {
        struct Allocator* alloc = Allocator_child(mainAlloc);
        // max frame size must be at least 5 so that at least 1 byte of data is sent.
        int maxFrameSize = ( Random_uint32(rand) % (MAX_FRAME_SZ - 1) ) + 1;
        int maxMessageSize = ( Random_uint32(rand) % (MAX_MSG_SZ - MIN_MSG_SZ) ) + MIN_MSG_SZ;
        Log_debug(log, "maxFrameSize[%d] maxMessageSize[%d]", maxFrameSize, maxMessageSize);
        ctx->alloc = alloc;
        ctx->messages = NULL;
        ctx->messageCount = 0;
        ctx->currentMessage = 0;

        // Create one huge message, then create lots of little frames inside of it
        // then split it up in random places and send the sections to the framing
        // interface.
        struct Message* msg = Message_new(WORK_BUFF_SZ, 0, alloc);

        Assert_true(WORK_BUFF_SZ == msg->length);
        Random_bytes(rand, msg->bytes, msg->length);
        Message_shift(msg, -WORK_BUFF_SZ, NULL);

        for (;;) {
            int len = Random_uint32(rand) % maxFrameSize;
            if (!len) {
                len++;
            }
            if (msg->padding < len + 4) {
                break;
            }
            Message_shift(msg, len, NULL);

            ctx->messageCount++;
            ctx->messages =
                Allocator_realloc(alloc, ctx->messages, ctx->messageCount * sizeof(char*));
            struct Message* om = ctx->messages[ctx->messageCount-1] = Message_new(len, 0, alloc);
            Bits_memcpy(om->bytes, msg->bytes, len);

            Message_push32(msg, len, NULL);
        }

        do {
            int nextMessageSize = Random_uint32(rand) % maxMessageSize;
            if (!nextMessageSize) {
                nextMessageSize++;
            }
            if (nextMessageSize > msg->length) {
                nextMessageSize = msg->length;
            }
            struct Allocator* msgAlloc = Allocator_child(alloc);
            struct Message* m = Message_new(nextMessageSize, 0, msgAlloc);
            Message_pop(msg, m->bytes, nextMessageSize, NULL);
            Interface_receiveMessage(&iface, m);
            Allocator_free(msgAlloc);
        } while (msg->length);

        Assert_true(ctx->messageCount == ctx->currentMessage);

        Allocator_free(alloc);
    }

    return 0;
}
static uint8_t sendMessage(struct Message* message, struct Interface* iface)
{
    struct PacketHeaderToUDPAddrInterface_pvt* context =
        Identity_check((struct PacketHeaderToUDPAddrInterface_pvt*) iface);

    struct Sockaddr_storage ss;
    Message_pop(message, &ss, context->pub.addr->addrLen, NULL);
    struct Sockaddr* addr = &ss.addr;

    struct Headers_UDPHeader udp;
    udp.srcPort_be = Endian_hostToBigEndian16(Sockaddr_getPort(context->pub.addr));
    udp.destPort_be = Endian_hostToBigEndian16(Sockaddr_getPort(addr));
    udp.length_be = Endian_hostToBigEndian16(message->length + Headers_UDPHeader_SIZE);
    udp.checksum_be = 0;
    Message_push(message, &udp, sizeof(struct Headers_UDPHeader), NULL);

    struct Headers_IP6Header ip = {
        .nextHeader = 17,
        .hopLimit = 255,
    };
    ip.payloadLength_be = Endian_hostToBigEndian16(message->length);
    Headers_setIpVersion(&ip);
    uint8_t* addrPtr = NULL;
    Assert_true(Sockaddr_getAddress(addr, &addrPtr) == 16);
    Bits_memcpyConst(ip.destinationAddr, addrPtr, 16);
    Assert_true(Sockaddr_getAddress(context->pub.addr, &addrPtr) == 16);
    Bits_memcpyConst(ip.sourceAddr, addrPtr, 16);

    uint16_t checksum = Checksum_udpIp6(ip.sourceAddr, message->bytes, message->length);
    ((struct Headers_UDPHeader*)message->bytes)->checksum_be = checksum;

    Message_push(message, &ip, sizeof(struct Headers_IP6Header), NULL);

    return Interface_sendMessage(context->wrapped, message);
}

static uint8_t receiveMessage(struct Message* message, struct Interface* iface)
{
    struct PacketHeaderToUDPAddrInterface_pvt* context =
        Identity_check((struct PacketHeaderToUDPAddrInterface_pvt*) iface->receiverContext);

    if (message->length < Headers_IP6Header_SIZE + Headers_UDPHeader_SIZE) {
        // runt
        return Error_NONE;
    }

    struct Headers_IP6Header* ip = (struct Headers_IP6Header*) message->bytes;

    // udp
    if (ip->nextHeader != 17) {
        return Error_NONE;
    }

    struct Allocator* alloc = Allocator_child(message->alloc);
    struct Sockaddr* addr = Sockaddr_clone(context->pub.addr, alloc);
    uint8_t* addrPtr = NULL;
    Assert_true(Sockaddr_getAddress(addr, &addrPtr) == 16);
    Bits_memcpyConst(addrPtr, ip->sourceAddr, 16);

    struct Headers_UDPHeader* udp = (struct Headers_UDPHeader*) (&ip[1]);
    Sockaddr_setPort(addr, Endian_bigEndianToHost16(udp->srcPort_be));

    if (Sockaddr_getPort(context->pub.addr) != Endian_bigEndianToHost16(udp->destPort_be)) {
        // not the right port
        return Error_NONE;
    }

    Message_shift(message, -(Headers_IP6Header_SIZE + Headers_UDPHeader_SIZE), NULL);
    Message_push(message, addr, addr->addrLen, NULL);

    return Interface_receiveMessage(&context->pub.generic, message);
}

struct AddrInterface* PacketHeaderToUDPAddrInterface_new(struct Interface* toWrap,
                                                         struct Allocator* alloc,
                                                         struct Sockaddr* addr)
{
    struct PacketHeaderToUDPAddrInterface_pvt* context =
        Allocator_malloc(alloc, sizeof(struct PacketHeaderToUDPAddrInterface_pvt));

    Bits_memcpyConst(context, (&(struct PacketHeaderToUDPAddrInterface_pvt) {
        .pub = {
            .generic = {
                .sendMessage = sendMessage,
                .senderContext = context,
                .allocator = alloc
            }
        },
        .wrapped = toWrap
    }), sizeof(struct PacketHeaderToUDPAddrInterface_pvt));
Example #8
0
static int tryRouterSolicitation(struct Message* msg,
                                 struct Ethernet* eth,
                                 struct Headers_IP6Header* ip6,
                                 struct NDPServer_pvt* ns)
{
    if (msg->length < NDPHeader_RouterSolicitation_SIZE) {
        return 0;
    }
    struct NDPHeader_RouterSolicitation* sol = (struct NDPHeader_RouterSolicitation*)msg->bytes;

    if (sol->oneThirtyThree != 133 || sol->zero != 0) {
printf("wrong type/code for router solicitation\n");
        return 0;
    }

    if (ns->pub.prefixLen < 1 || ns->pub.prefixLen > 128) {
printf("address prefix not set\n");
        return 0;
    }

    if (Bits_memcmp(ip6->destinationAddr, UNICAST_ADDR, 16)
        && Bits_memcmp(ip6->destinationAddr, ALL_ROUTERS, 16))
    {
printf("wrong address for router solicitation\n");
        return 0;
    }

    // now we're committed.
    Message_shift(msg, -msg->length, NULL);

    // Prefix option
    struct NDPHeader_RouterAdvert_PrefixOpt prefix = {
        .three = 3,
        .four = 4,
        .bits = 0,
        .validLifetimeSeconds_be = 0xffffffffu,
        .preferredLifetimeSeconds_be = 0xffffffffu,
        .reservedTwo = 0
    };
    Bits_memcpyConst(prefix.prefix, ns->pub.advertisePrefix, 16);
    prefix.prefixLen = ns->pub.prefixLen;
    Message_push(msg, &prefix, sizeof(struct NDPHeader_RouterAdvert_PrefixOpt), NULL);

    // NDP message
    struct NDPHeader_RouterAdvert adv = {
        .oneThirtyFour = 134,
        .zero = 0,
        .checksum = 0,
        .currentHopLimit = 0,
        .bits = 0,
        .routerLifetime_be = Endian_hostToBigEndian16(10),
        .reachableTime_be = 0,
        .retransTime_be = 0
    };
    Message_push(msg, &adv, sizeof(struct NDPHeader_RouterAdvert), NULL);

    sendResponse(msg, eth, ip6, ns);
    return 1;
}

static int tryNeighborSolicitation(struct Message* msg,
                                   struct Ethernet* eth,
                                   struct Headers_IP6Header* ip6,
                                   struct NDPServer_pvt* ns)
{
    if (msg->length < NDPHeader_RouterSolicitation_SIZE) {
        return 0;
    }
    struct NDPHeader_NeighborSolicitation* sol = (struct NDPHeader_NeighborSolicitation*)msg->bytes;

    if (sol->oneThirtyFive != 135 || sol->zero != 0) {
printf("wrong type/code for neighbor solicitation\n");
        return 0;
    }

    if (Bits_memcmp(ip6->destinationAddr, UNICAST_ADDR, 16)
        && Bits_memcmp(ip6->destinationAddr, MULTICAST_ADDR, 13))
    {
printf("wrong address for neighbor solicitation\n");
        return 0;
    }

    // now we're committed.
    Message_shift(msg, -msg->length, NULL);

    struct NDPHeader_NeighborAdvert_MacOpt macOpt = {
        .two = 2,
        .one = 1
    };
    Bits_memcpyConst(macOpt.mac, eth->destAddr, 6);
    Message_push(msg, &macOpt, sizeof(struct NDPHeader_NeighborAdvert_MacOpt), NULL);

    struct NDPHeader_NeighborAdvert na = {
        .oneThirtySix = 136,
        .zero = 0,
        .checksum = 0,
        .bits = NDPHeader_NeighborAdvert_bits_ROUTER
            | NDPHeader_NeighborAdvert_bits_SOLICITED
            | NDPHeader_NeighborAdvert_bits_OVERRIDE
    };
    Bits_memcpyConst(na.targetAddr, UNICAST_ADDR, 16);
    Message_push(msg, &na, sizeof(struct NDPHeader_NeighborAdvert), NULL);

    sendResponse(msg, eth, ip6, ns);
    return 1;
}

static uint8_t receiveMessage(struct Message* msg, struct Interface* iface)
{
    struct NDPServer_pvt* ns = Identity_cast((struct NDPServer_pvt*)iface->receiverContext);

    if (msg->length < Ethernet_SIZE + Headers_IP6Header_SIZE) {
        return Interface_receiveMessage(&ns->pub.generic, msg);
    }

    struct Ethernet* eth = (struct Ethernet*) msg->bytes;
    struct Headers_IP6Header* ip6 = (struct Headers_IP6Header*) (&eth[1]);

    if (eth->ethertype != Ethernet_TYPE_IP6 || ip6->nextHeader != 58 /* ICMPv6 */) {
        return Interface_receiveMessage(&ns->pub.generic, msg);
    }

    // store the eth and ip6 headers so they don't get clobbered
    struct Ethernet storedEth;
    Message_pop(msg, &storedEth, sizeof(struct Ethernet), NULL);

    struct Headers_IP6Header storedIp6;
    Message_pop(msg, &storedIp6, sizeof(struct Headers_IP6Header), NULL);

    if (!tryNeighborSolicitation(msg, &storedEth, &storedIp6, ns)
        && !tryRouterSolicitation(msg, &storedEth, &storedIp6, ns))
    {
        Message_push(msg, &storedIp6, sizeof(struct Headers_IP6Header), NULL);
        Message_push(msg, &storedEth, sizeof(struct Ethernet), NULL);
        return Interface_receiveMessage(&ns->pub.generic, msg);
    }
    // responding happens in sendResponse..
    return 0;
}

static uint8_t sendMessage(struct Message* msg, struct Interface* iface)
{
    struct NDPServer_pvt* ns = Identity_cast((struct NDPServer_pvt*)iface);
    return Interface_sendMessage(ns->wrapped, msg);
}

struct NDPServer* NDPServer_new(struct Interface* external, struct Allocator* alloc)
{
    struct NDPServer_pvt* out = Allocator_calloc(alloc, sizeof(struct NDPServer_pvt), 1);
    out->wrapped = external;
    Identity_set(out);
    InterfaceWrapper_wrap(external, sendMessage, receiveMessage, &out->pub.generic);
    return &out->pub;
}