Beispiel #1
0
static int pico_ipv4_checksum(struct pico_frame *f)
{
    struct pico_ipv4_hdr *hdr = (struct pico_ipv4_hdr *) f->net_hdr;
    if (!hdr)
        return -1;

    hdr->crc = 0;
    hdr->crc = short_be(pico_checksum(hdr, f->net_len));
    return 0;
}
Beispiel #2
0
static int pico_icmp4_checksum(struct pico_frame *f)
{
  struct pico_icmp4_hdr *hdr = (struct pico_icmp4_hdr *) f->transport_hdr;
  if (!hdr) {
    pico_err = PICO_ERR_EINVAL;
    return -1;
  }
  hdr->crc = 0;
  hdr->crc = short_be(pico_checksum(hdr, f->transport_len));
  return 0;
}
Beispiel #3
0
static inline int pico_ipv4_crc_check(struct pico_frame *f)
{
    uint16_t checksum_invalid = 1;
    struct pico_ipv4_hdr *hdr = (struct pico_ipv4_hdr *) f->net_hdr;

    checksum_invalid = short_be(pico_checksum(hdr, f->net_len));
    if (checksum_invalid) {
        dbg("IP: checksum failed!\n");
        pico_frame_discard(f);
        return 0;
    }

    return 1;
}
Beispiel #4
0
END_TEST

#ifdef PICO_SUPPORT_CRC_FAULTY_UNIT_TEST
START_TEST (test_crc_check)
{
    uint8_t buffer[64] = {
        0x45, 0x00, 0x00, 0x40,                  /* start of IP hdr */
        0x91, 0xc3, 0x40, 0x00,
        0x40, 0x11, 0x24, 0xcf,                  /* last 2 bytes are CRC */
        0xc0, 0xa8, 0x01, 0x66,
        0xc0, 0xa8, 0x01, 0x64,                  /* end of IP hdr */
        0x15, 0xb3, 0x1F, 0x90,                  /* start of UDP/TCP hdr */
        0x00, 0x2c, 0x27, 0x22,                  /* end of UDP hdr */
        0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00,
        0x00, 0x0b, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00,                  /* end of TCP hdr */
        0x01, 0x23, 0x45, 0x67,                  /* start of data */
        0x89, 0xab, 0xcd, 0xef,
        0xc0, 0xca, 0xc0, 0x1a
    };
    struct pico_frame *f = NULL;
    struct pico_ipv4_hdr *hdr = (struct pico_ipv4_hdr *) buffer;
    struct pico_udp_hdr *udp_hdr = NULL;
    struct pico_tcp_hdr *tcp_hdr = NULL;
    uint32_t *f_usage_count = NULL;
    uint8_t *f_buffer = NULL;
    int ret = -1;

    printf("START CRC TEST\n");
    pico_stack_init();

    /* IPv4 CRC unit tests */
    /* Allocated memory will not be freed when pico_ipv4_crc_check fails */
    f = calloc(1, sizeof(struct pico_frame));
    f_usage_count = calloc(1, sizeof(uint32_t));
    f_buffer = calloc(1, sizeof(uint8_t));
    f->net_hdr = buffer;
    f->net_len = PICO_SIZE_IP4HDR;
    f->transport_hdr = buffer + PICO_SIZE_IP4HDR;
    f->transport_len = sizeof(buffer) - PICO_SIZE_IP4HDR;
    f->usage_count = f_usage_count;
    f->buffer = f_buffer;
    *(f->usage_count) = 512;

    hdr->crc = 0;
    printf(">>>>>>>>>>>>>>>>>>>>> CRC VALUE = %X\n", pico_checksum(hdr, PICO_SIZE_IP4HDR));
    hdr->crc = short_be(0x24CF); /* Make check pass */
    ret = pico_ipv4_crc_check(f);
    fail_if(ret == 0, "correct IPv4 checksum got rejected\n");
    hdr->crc = short_be(0x8899); /* Make check fail */
    ret = pico_ipv4_crc_check(f);
    fail_if(ret == 1, "incorrect IPv4 checksum got accepted\n");

    /* UDP CRC unit tests */
    /* Allocated memory will be freed when pico_transport_crc_check fails */
    f = calloc(1, sizeof(struct pico_frame));
    f_usage_count = calloc(1, sizeof(uint32_t));
    f_buffer = calloc(1, sizeof(uint8_t));
    f->net_hdr = buffer;
    f->transport_hdr = buffer + PICO_SIZE_IP4HDR;
    f->transport_len = sizeof(buffer) - PICO_SIZE_IP4HDR;
    f->usage_count = f_usage_count;
    f->buffer = f_buffer;
    *(f->usage_count) = 1;
    hdr->proto = 0x11; /* UDP */
    hdr->crc = short_be(0x24cf); /* Set IPv4 CRC correct */
    udp_hdr = (struct pico_udp_hdr *) f->transport_hdr;

    /* udp_hdr->crc = 0; */
    /* printf(">>>>>>>>>>>>>>>>>>>>> UDP CRC VALUE = %X\n", pico_udp_checksum_ipv4(f)); */
    ret = pico_transport_crc_check(f);
    fail_if(ret == 0, "correct UDP checksum got rejected\n");
    udp_hdr->crc = 0;
    ret = pico_transport_crc_check(f);
    fail_if(ret == 0, "UDP checksum of 0 did not get ignored\n");
    udp_hdr->crc = short_be(0x8899); /* Make check fail */
    ret = pico_transport_crc_check(f);
    fail_if(ret == 1, "incorrect UDP checksum got accepted\n");

    /* TCP CRC unit tests */
    /* Allocated memory will be freed when pico_transport_crc_check fails */
    f = calloc(1, sizeof(struct pico_frame));
    f_usage_count = calloc(1, sizeof(uint32_t));
    f_buffer = calloc(1, sizeof(uint8_t));
    f->net_hdr = buffer;
    f->transport_hdr = buffer + PICO_SIZE_IP4HDR;
    f->transport_len = sizeof(buffer) - PICO_SIZE_IP4HDR;
    f->usage_count = f_usage_count;
    f->buffer = f_buffer;
    *(f->usage_count) = 1;
    hdr->proto = 0x06; /* TCP */
    hdr->crc = short_be(0x24cf); /* Set IPv4 CRC correct */
    tcp_hdr = (struct pico_tcp_hdr *) f->transport_hdr;
    tcp_hdr->seq = long_be(0x002c2722); /* Set sequence number correct */

    /* tcp_hdr = 0; */
    /* printf(">>>>>>>>>>>>>>>>>>>>> TCP CRC VALUE = %X\n", pico_tcp_checksum_ipv4(f)); */
    tcp_hdr->crc = short_be(0x0016); /* Set correct TCP CRC */
    ret = pico_transport_crc_check(f);
    fail_if(ret == 0, "correct TCP checksum got rejected\n");
    tcp_hdr->crc = short_be(0x8899); /* Make check fail */
    ret = pico_transport_crc_check(f);
    fail_if(ret == 1, "incorrect TCP checksum got accepted\n");
}
Beispiel #5
0
END_TEST


START_TEST (test_icmp4_incoming_ping)
{
    int bufferlen = 76;
    uint8_t buffer[76] = {
        0x45, 0x00, 0x00, 0x4c,
        0x91, 0xc3, 0x40, 0x00,
        0x40, 0x01, 0x24, 0xd0,
        0xc0, 0xa8, 0x01, 0x66,
        0xc0, 0xa8, 0x01, 0x64,
        0x08, 0x00, 0x66, 0x3c,
        0x91, 0xc2, 0x01, 0x01,
        0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00
    };
    int buffer2len = 76;
    int len;
    int cntr = 0;
    uint8_t buffer2[bufferlen];
    struct pico_ip4 local = {
        .addr = long_be(0xc0a80164)
    };
    struct pico_ip4 netmask = {
        .addr = long_be(0xffffff00)
    };
    struct mock_device*mock;
    struct pico_ipv4_hdr *hdr = (struct pico_ipv4_hdr *) buffer;
    printf("*********************** starting %s * \n", __func__);

    pico_stack_init();

    mock = pico_mock_create(NULL);
    fail_if(mock == NULL, "No device created");

    pico_ipv4_link_add(mock->dev, local, netmask);

    hdr->crc = 0;
    hdr->crc = short_be(pico_checksum(hdr, PICO_SIZE_IP4HDR));
    pico_mock_network_write(mock, buffer, bufferlen);
    /* check if it is received */
    pico_stack_tick();
    pico_stack_tick();
    pico_stack_tick();
    pico_stack_tick();
    pico_stack_tick();
    pico_stack_tick();


    len = pico_mock_network_read(mock, buffer2, buffer2len);
    /* inspect it */

    while(cntr < len) {
        printf("0x%02x ", buffer2[cntr]);
        cntr++;
        if(cntr % 4 == 0)
            printf("\n");
    }
    fail_unless(len == buffer2len, "ping reply lenght does not match, expected len: %d, got: %d", buffer2len, len);
    fail_unless(mock_ip_protocol(mock, buffer2, len) == 1);
    fail_unless(mock_icmp_type(mock, buffer2, len) == 0);
    fail_unless(mock_icmp_code(mock, buffer2, len) == 0);
    fail_unless(pico_checksum(buffer2 + 20, len - 20) == 0);

}
END_TEST

START_TEST (test_icmp4_unreachable_send)
{
    struct pico_ip4 local = {
        .addr = long_be(0x0a280064)
    };
    struct pico_ip4 netmask = {
        .addr = long_be(0xffffff00)
    };
    struct mock_device*mock;
    int len = 0;
    int bufferlen = 80;
    uint8_t buffer2[bufferlen];

    uint8_t buffer[32] = {
        0x45, 0x00, 0x00, 0x20,  0x91, 0xc0, 0x40, 0x00,
        0x40, 0x11, 0x94, 0xb4,  0x0a, 0x28, 0x00, 0x05,
        0x0a, 0x28, 0x00, 0x04,  0x15, 0xb3, 0x15, 0xb3,
        0x00, 0x0c, 0x00, 0x00,  'e', 'l', 'l', 'o'
    };

    /* fake packet with bad upper-layer-protocol */
    uint8_t buffer3[20] = {
        0x45, 0x00, 0x00, 0x14,  0x91, 0xc0, 0x40, 0x00,
        0x40, 0xff, 0x94, 0xb4,  0x0a, 0x28, 0x00, 0x05,
        0x0a, 0x28, 0x00, 0x04
    };

    struct pico_frame*f = PICO_ZALLOC(sizeof(struct pico_frame));
    uint8_t nullbuf[8] = {};
    printf("*********************** starting %s * \n", __func__);

    f->net_hdr = buffer;
    f->buffer = buffer;

    pico_stack_init();

    mock = pico_mock_create(NULL);
    fail_if(mock == NULL, "No device created");

    pico_ipv4_link_add(mock->dev, local, netmask);


    fail_if(pico_icmp4_dest_unreachable(f));
    pico_stack_tick();
    pico_stack_tick();
    pico_stack_tick();

    len = pico_mock_network_read(mock, buffer2, bufferlen);

    fail_unless(len == 56);
    fail_unless(mock_ip_protocol(mock, buffer2, len) == 1);
    fail_unless(mock_icmp_type(mock, buffer2, len) == 3); /* destination unreachable */
    fail_unless(mock_icmp_code(mock, buffer2, len) == 1); /* host unreachable */
    fail_unless(pico_checksum(buffer2 + 20, len - 20) == 0);


    fail_if(pico_icmp4_port_unreachable(f));
    pico_stack_tick();
    pico_stack_tick();
    pico_stack_tick();

    len = pico_mock_network_read(mock, buffer2, bufferlen);

    fail_unless(len == 56);
    fail_unless(mock_ip_protocol(mock, buffer2, len) == 1);
    fail_unless(mock_icmp_type(mock, buffer2, len) == 3); /* destination unreachable */
    fail_unless(mock_icmp_code(mock, buffer2, len) == 3); /* port unreachable */
    fail_unless(pico_checksum(buffer2 + 20, len - 20) == 0);


    fail_if(pico_icmp4_proto_unreachable(f));
    pico_stack_tick();
    pico_stack_tick();
    pico_stack_tick();

    len = pico_mock_network_read(mock, buffer2, bufferlen);

    fail_unless(len == 56);
    fail_unless(mock_ip_protocol(mock, buffer2, len) == 1);
    fail_unless(mock_icmp_type(mock, buffer2, len) == 3); /* destination unreachable */
    fail_unless(mock_icmp_code(mock, buffer2, len) == 2); /* proto unreachable */
    fail_unless(pico_checksum(buffer2 + 20, len - 20) == 0);


    fail_if(pico_icmp4_ttl_expired(f));
    pico_stack_tick();
    pico_stack_tick();
    pico_stack_tick();

    len = pico_mock_network_read(mock, buffer2, bufferlen);

    fail_unless(len == 56);
    fail_unless(mock_ip_protocol(mock, buffer2, len) == 1);
    fail_unless(mock_icmp_type(mock, buffer2, len) == 11); /* ttl expired */
    fail_unless(mock_icmp_code(mock, buffer2, len) == 0);
    fail_unless(pico_checksum(buffer2 + 20, len - 20) == 0);

    f->net_hdr = buffer3;
    f->buffer = buffer3;

    fail_if(pico_icmp4_proto_unreachable(f));
    pico_stack_tick();
    pico_stack_tick();
    pico_stack_tick();

    len = pico_mock_network_read(mock, buffer2, bufferlen);

    fail_unless(len == 56);
    fail_unless(mock_ip_protocol(mock, buffer2, len) == 1);
    fail_unless(mock_icmp_type(mock, buffer2, len) == 3); /* destination unreachable */
    fail_unless(mock_icmp_code(mock, buffer2, len) == 2); /* proto unreachable */
    fail_unless(pico_checksum(buffer2 + 20, len - 20) == 0);

#ifdef NOPE
    /* I don't know what was the intention, but the buffer is shorter than 48 bytes... */
    fail_if(memcmp(buffer + 48, nullbuf, 8) == 0); /* there was no data */
#endif
}
END_TEST

int icmp4_socket_unreach_status = 0;
void icmp4_unreach_socket_cb(uint16_t ev, struct pico_socket *s)
{
    if (ev == PICO_SOCK_EV_ERR) {
        icmp4_socket_unreach_status = 1;
    }
}

START_TEST (test_icmp4_unreachable_recv)
{
    struct pico_ip4 local = {
        .addr = long_be(0x0a280064)
    };
    struct pico_ip4 remote = {
        .addr = long_be(0x0a280065)
    };
    struct pico_ip4 netmask = {
        .addr = long_be(0xffffff00)
    };
    struct mock_device*mock;
    struct pico_socket*sock;
    uint16_t port = short_be(7777);

    /* put a host unreachable in the queue, run a few stack ticks */
    uint8_t buffer[] = {
        0x45, 0x00, 0x00, 0x20,
        0x91, 0xc0, 0x40, 0x00,
        0x40, 0x01, 0x94, 0xb4,
        0x0a, 0x28, 0x00, 0x65,
        0x0a, 0x28, 0x00, 0x64,
        0x03, 0x01, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00,

        0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00,
    };
    struct pico_ipv4_hdr *hdr = (struct pico_ipv4_hdr *) buffer;

    printf("*********************** starting %s * \n", __func__);
    pico_stack_init();

    mock = pico_mock_create(NULL);
    fail_if(mock == NULL, "No device created");

    pico_ipv4_link_add(mock->dev, local, netmask);

    /* open a socket */
    sock = pico_socket_open(PICO_PROTO_IPV4, PICO_PROTO_TCP, &icmp4_unreach_socket_cb);
    fail_if(sock == NULL);
    fail_if(pico_socket_bind(sock, &local, &port));
    pico_socket_connect(sock, &remote, port);
    pico_socket_write(sock, "fooo", 4);
    /* see if my callback was called with the proper code */

    pico_stack_tick();
    pico_stack_tick();
    pico_stack_tick();
    /* filling in the IP header and first 8 bytes */
    hdr->crc = 0;
    hdr->crc = short_be(pico_checksum(hdr, PICO_SIZE_IP4HDR));
    printf("read %d bytes\n", pico_mock_network_read(mock, buffer + 28, 28));

    printf("wrote %d bytes\n", pico_mock_network_write(mock, buffer, 56));
    pico_stack_tick();
    pico_stack_tick();
    pico_stack_tick();
    fail_unless(icmp4_socket_unreach_status == 1);
}
END_TEST