static void ipsp_recv(struct bt_l2cap_chan *chan, struct net_buf *buf) { struct bt_context *ctxt = CHAN_CTXT(chan); struct net_pkt *pkt; NET_DBG("Incoming data channel %p len %zu", chan, net_buf_frags_len(buf)); /* Get packet for bearer / protocol related data */ pkt = net_pkt_get_reserve_rx(0, K_FOREVER); /* Set destination address */ net_pkt_ll_dst(pkt)->addr = ctxt->src.val; net_pkt_ll_dst(pkt)->len = sizeof(ctxt->src); net_pkt_ll_dst(pkt)->type = NET_LINK_BLUETOOTH; /* Set source address */ net_pkt_ll_src(pkt)->addr = ctxt->dst.val; net_pkt_ll_src(pkt)->len = sizeof(ctxt->dst); net_pkt_ll_src(pkt)->type = NET_LINK_BLUETOOTH; /* Add data buffer as fragment of RX buffer, take a reference while * doing so since L2CAP will unref the buffer after return. */ net_pkt_frag_add(pkt, net_buf_ref(buf)); if (net_recv_data(ctxt->iface, pkt) < 0) { NET_DBG("Packet dropped by NET stack"); net_pkt_unref(pkt); } }
static inline struct net_pkt *prepare_arp_request(struct net_if *iface, struct net_pkt *req, struct net_eth_addr *addr) { struct net_pkt *pkt; struct net_buf *frag; struct net_arp_hdr *hdr, *req_hdr; struct net_eth_hdr *eth, *eth_req; pkt = net_pkt_get_reserve_rx(sizeof(struct net_eth_hdr), K_FOREVER); if (!pkt) { goto fail; } frag = net_pkt_get_frag(pkt, K_FOREVER); if (!frag) { goto fail; } net_pkt_frag_add(pkt, frag); net_pkt_set_iface(pkt, iface); hdr = NET_ARP_HDR(pkt); eth = NET_ETH_HDR(pkt); req_hdr = NET_ARP_HDR(req); eth_req = NET_ETH_HDR(req); eth->type = htons(NET_ETH_PTYPE_ARP); memset(ð->dst.addr, 0xff, sizeof(struct net_eth_addr)); memcpy(ð->src.addr, addr, sizeof(struct net_eth_addr)); hdr->hwtype = htons(NET_ARP_HTYPE_ETH); hdr->protocol = htons(NET_ETH_PTYPE_IP); hdr->hwlen = sizeof(struct net_eth_addr); hdr->protolen = sizeof(struct in_addr); hdr->opcode = htons(NET_ARP_REQUEST); memset(&hdr->dst_hwaddr.addr, 0x00, sizeof(struct net_eth_addr)); memcpy(&hdr->src_hwaddr.addr, addr, sizeof(struct net_eth_addr)); net_ipaddr_copy(&hdr->src_ipaddr, &req_hdr->src_ipaddr); net_ipaddr_copy(&hdr->dst_ipaddr, &req_hdr->dst_ipaddr); net_buf_add(frag, sizeof(struct net_arp_hdr)); return pkt; fail: net_pkt_unref(pkt); return NULL; }
static int send_response(struct zoap_packet *request, u8_t response_code) { struct net_pkt *pkt; struct net_buf *frag; struct zoap_packet response; u8_t code, type; u16_t id; int r; code = zoap_header_get_code(request); type = zoap_header_get_type(request); id = zoap_header_get_id(request); printk("*******\n"); printk("type: %u code %u id %u\n", type, code, id); printk("*******\n"); pkt = net_pkt_get_reserve(&zoap_pkt_slab, 0, K_NO_WAIT); if (!pkt) { return -ENOMEM; } frag = net_buf_alloc(&zoap_data_pool, K_NO_WAIT); if (!frag) { return -ENOMEM; } net_pkt_frag_add(pkt, frag); r = zoap_packet_init(&response, pkt); if (r < 0) { return -EINVAL; } zoap_header_set_version(&response, 1); zoap_header_set_type(&response, ZOAP_TYPE_ACK); zoap_header_set_code(&response, response_code); zoap_header_set_id(&response, id); do { r = mbedtls_ssl_write(curr_ctx, frag->data, frag->len); } while (r == MBEDTLS_ERR_SSL_WANT_READ || r == MBEDTLS_ERR_SSL_WANT_WRITE); if (r >= 0) { r = 0; } net_pkt_unref(pkt); return r; }
static bool send_ipv4_udp_msg(struct net_if *iface, struct in_addr *src, struct in_addr *dst, u16_t src_port, u16_t dst_port, struct ud *ud, bool expect_failure) { struct net_pkt *pkt; struct net_buf *frag; int ret; pkt = net_pkt_get_reserve_tx(0, K_FOREVER); frag = net_pkt_get_frag(pkt, K_FOREVER); net_pkt_frag_add(pkt, frag); net_pkt_set_iface(pkt, iface); net_pkt_set_ll_reserve(pkt, net_buf_headroom(frag)); setup_ipv4_udp(pkt, src, dst, src_port, dst_port); ret = net_recv_data(iface, pkt); if (ret < 0) { printk("Cannot recv pkt %p, ret %d\n", pkt, ret); zassert_true(0, "exiting"); } if (k_sem_take(&recv_lock, TIMEOUT)) { /**TESTPOINT: Check for failure*/ zassert_true(expect_failure, "Timeout, packet not received"); return true; } /* Check that the returned user data is the same as what was given * as a parameter. */ if (ud != returned_ud && !expect_failure) { printk("IPv4 wrong user data %p returned, expected %p\n", returned_ud, ud); zassert_true(0, "exiting"); } return !fail; }
static struct net_pkt *build_reply_pkt(const char *name, struct net_context *context, struct net_pkt *pkt) { struct net_pkt *reply_pkt; struct net_buf *tmp; int header_len, recv_len, reply_len; printk("%s received %d bytes", name, net_pkt_appdatalen(pkt)); reply_pkt = net_pkt_get_tx(context, K_FOREVER); recv_len = net_pkt_get_len(pkt); tmp = pkt->frags; /* Remove frag link so original pkt can be unrefed */ pkt->frags = NULL; /* First fragment will contain IP header so move the data * down in order to get rid of it. */ header_len = net_pkt_appdata(pkt) - tmp->data; /* After this pull, the tmp->data points directly to application * data. */ net_buf_pull(tmp, header_len); /* Add the entire chain into reply */ net_pkt_frag_add(reply_pkt, tmp); reply_len = net_pkt_get_len(reply_pkt); printk("Received %d bytes, sending %d bytes", recv_len - header_len, reply_len); return reply_pkt; }
static inline int slip_input_byte(struct slip_context *slip, unsigned char c) { switch (slip->state) { case STATE_GARBAGE: if (c == SLIP_END) { slip->state = STATE_OK; } return 0; case STATE_ESC: if (c == SLIP_ESC_END) { c = SLIP_END; } else if (c == SLIP_ESC_ESC) { c = SLIP_ESC; } else { slip->state = STATE_GARBAGE; SLIP_STATS(slip->garbage++); return 0; } slip->state = STATE_OK; break; case STATE_OK: if (c == SLIP_ESC) { slip->state = STATE_ESC; return 0; } if (c == SLIP_END) { slip->state = STATE_OK; slip->first = false; if (slip->rx) { return 1; } return 0; } if (slip->first && !slip->rx) { /* Must have missed buffer allocation on first byte. */ return 0; } if (!slip->first) { slip->first = true; slip->rx = net_pkt_get_reserve_rx(0, K_NO_WAIT); if (!slip->rx) { SYS_LOG_ERR("[%p] cannot allocate pkt", slip); return 0; } slip->last = net_pkt_get_frag(slip->rx, K_NO_WAIT); if (!slip->last) { SYS_LOG_ERR("[%p] cannot allocate 1st data frag", slip); net_pkt_unref(slip->rx); slip->rx = NULL; return 0; } net_pkt_frag_add(slip->rx, slip->last); slip->ptr = net_pkt_ip_data(slip->rx); } break; } /* It is possible that slip->last is not set during the startup * of the device. If this happens do not continue and overwrite * some random memory. */ if (!slip->last) { return 0; } if (!net_buf_tailroom(slip->last)) { /* We need to allocate a new fragment */ struct net_buf *frag; frag = net_pkt_get_reserve_rx_data(0, K_NO_WAIT); if (!frag) { SYS_LOG_ERR("[%p] cannot allocate next data frag", slip); net_pkt_unref(slip->rx); slip->rx = NULL; slip->last = NULL; return 0; } net_buf_frag_insert(slip->last, frag); slip->last = frag; slip->ptr = slip->last->data; } /* The net_buf_add_u8() cannot add data to ll header so we need * a way to do it. */ if (slip->ptr < slip->last->data) { *slip->ptr = c; } else { slip->ptr = net_buf_add_u8(slip->last, c); } slip->ptr++; return 0; }
static void test_fragment_split(void) { #define TEST_FRAG_COUNT (FRAG_COUNT - 2) #define FRAGA (FRAG_COUNT - 2) #define FRAGB (FRAG_COUNT - 1) struct net_pkt *pkt; struct net_buf *frags[FRAG_COUNT], *frag, *frag_a, *frag_b; int i, total, split_a, split_b; int ret, frag_size; memset(frags, 0, FRAG_COUNT * sizeof(void *)); pkt = net_pkt_get_reserve_rx(0, K_FOREVER); frag = NULL; for (i = 0, total = 0; i < TEST_FRAG_COUNT; i++) { frags[i] = net_pkt_get_reserve_rx_data(12, K_FOREVER); if (frag) { net_buf_frag_add(frag, frags[i]); } frag = frags[i]; /* Copy some test data in front of the fragment */ memcpy(net_buf_add(frags[i], sizeof(frag_data)), frag_data, sizeof(frag_data)); total++; } if (total != TEST_FRAG_COUNT) { printk("There should be %d fragments but was %d\n", TEST_FRAG_COUNT, total); zassert_true(false, "Frags missing"); } frag_size = frags[0]->size; zassert_true(frag_size > 0, "Invalid frag size"); net_pkt_frag_add(pkt, frags[0]); frag_a = frags[FRAGA]; frag_b = frags[FRAGB]; zassert_is_null(frag_a, "frag_a is not NULL"); zassert_is_null(frag_b, "frag_b is not NULL"); split_a = frag_size * 2 / 3; split_b = frag_size - split_a; zassert_true(split_a > 0, "A size is 0"); zassert_true(split_a > split_b, "A is smaller than B"); /* Test some error cases first */ ret = net_pkt_split(NULL, NULL, 1024, &frag_a, &frag_b, K_NO_WAIT); zassert_equal(ret, -EINVAL, "Invalid buf pointers"); ret = net_pkt_split(pkt, pkt->frags, CONFIG_NET_BUF_DATA_SIZE + 1, &frag_a, &frag_b, K_NO_WAIT); zassert_equal(ret, 0, "Split failed"); ret = net_pkt_split(pkt, pkt->frags, split_a, &frag_a, &frag_b, K_NO_WAIT); zassert_equal(ret, 0, "Cannot split frag"); if (frag_a->len != split_a) { printk("Frag_a len %d not %d\n", frag_a->len, split_a); zassert_equal(frag_a->len, split_a, "Frag_a len wrong"); } if (frag_b->len != split_b) { printk("Frag_b len %d not %d\n", frag_b->len, split_b); zassert_true(false, "Frag_b len wrong"); } zassert_false(memcmp(pkt->frags->data, frag_a->data, split_a), "Frag_a data mismatch"); zassert_false(memcmp(pkt->frags->data + split_a, frag_b->data, split_b), "Frag_b data mismatch"); }
static void test_fragment_compact(void) { struct net_pkt *pkt; struct net_buf *frags[FRAG_COUNT], *frag; int i, bytes, total, count; pkt = net_pkt_get_reserve_rx(0, K_FOREVER); frag = NULL; for (i = 0, total = 0; i < FRAG_COUNT; i++) { frags[i] = net_pkt_get_reserve_rx_data(12, K_FOREVER); if (frag) { net_buf_frag_add(frag, frags[i]); } frag = frags[i]; /* Copy character test data in front of the fragment */ memcpy(net_buf_add(frags[i], sizeof(test_data)), test_data, sizeof(test_data)); /* Followed by bytes of zeroes */ memset(net_buf_add(frags[i], sizeof(test_data)), 0, sizeof(test_data)); total++; } if (total != FRAG_COUNT) { printk("There should be %d fragments but was %d\n", FRAG_COUNT, total); zassert_true(false, "Invalid fragment count"); } DBG("step 1\n"); pkt->frags = net_buf_frag_add(pkt->frags, frags[0]); bytes = net_pkt_get_len(pkt); if (bytes != FRAG_COUNT * sizeof(test_data) * 2) { printk("Compact test failed, fragments had %d bytes but " "should have had %zd\n", bytes, FRAG_COUNT * sizeof(test_data) * 2); zassert_true(false, "Invalid fragment bytes"); } zassert_false(net_pkt_is_compact(pkt), "The pkt is definitely not compact"); DBG("step 2\n"); net_pkt_compact(pkt); zassert_true(net_pkt_is_compact(pkt), "The pkt should be in compact form"); DBG("step 3\n"); /* Try compacting again, nothing should happen */ net_pkt_compact(pkt); zassert_true(net_pkt_is_compact(pkt), "The pkt should be compacted now"); total = calc_fragments(pkt); /* Add empty fragment at the end and compact, the last fragment * should be removed. */ frag = net_pkt_get_reserve_rx_data(0, K_FOREVER); net_pkt_frag_add(pkt, frag); count = calc_fragments(pkt); DBG("step 4\n"); net_pkt_compact(pkt); i = calc_fragments(pkt); if (count != (i + 1)) { printk("Last fragment removal failed, chain should have %d " "fragments but had %d\n", i-1, i); zassert_true(false, "Last frag rm fails"); } if (i != total) { printk("Fragments missing, expecting %d but got %d\n", total, i); zassert_true(false, "Frags missing"); } /* Add two empty fragments at the end and compact, the last two * fragment should be removed. */ frag = net_pkt_get_reserve_rx_data(0, K_FOREVER); net_pkt_frag_add(pkt, frag); frag = net_pkt_get_reserve_rx_data(0, K_FOREVER); net_pkt_frag_add(pkt, frag); count = calc_fragments(pkt); DBG("step 5\n"); net_pkt_compact(pkt); i = calc_fragments(pkt); if (count != (i + 2)) { printk("Last two fragment removal failed, chain should have " "%d fragments but had %d\n", i-2, i); zassert_true(false, "Last two frag rm fails"); } if (i != total) { printk("Fragments missing, expecting %d but got %d\n", total, i); zassert_true(false, "Frags missing"); } /* Add empty fragment at the beginning and at the end, and then * compact, the two fragment should be removed. */ frag = net_pkt_get_reserve_rx_data(0, K_FOREVER); net_pkt_frag_insert(pkt, frag); frag = net_pkt_get_reserve_rx_data(0, K_FOREVER); net_pkt_frag_add(pkt, frag); count = calc_fragments(pkt); DBG("step 6\n"); net_pkt_compact(pkt); i = calc_fragments(pkt); if (count != (i + 2)) { printk("Two fragment removal failed, chain should have " "%d fragments but had %d\n", i-2, i); zassert_true(false, "Two frag rm fails"); } if (i != total) { printk("Fragments missing, expecting %d but got %d\n", total, i); zassert_true(false, "Frags missing"); } DBG("test_fragment_compact passed\n"); }
static void test_ipv6_multi_frags(void) { struct net_pkt *pkt; struct net_buf *frag; struct ipv6_hdr *ipv6; struct udp_hdr *udp; int bytes, remaining = strlen(example_data), pos = 0; /* Example of multi fragment scenario with IPv6 */ pkt = net_pkt_get_reserve_rx(0, K_FOREVER); frag = net_pkt_get_reserve_rx_data(LL_RESERVE, K_FOREVER); /* Place the IP + UDP header in the first fragment */ if (!net_buf_tailroom(frag)) { ipv6 = (struct ipv6_hdr *)(frag->data); udp = (struct udp_hdr *)((void *)ipv6 + sizeof(*ipv6)); if (net_buf_tailroom(frag) < sizeof(ipv6)) { printk("Not enough space for IPv6 header, " "needed %zd bytes, has %zd bytes\n", sizeof(ipv6), net_buf_tailroom(frag)); zassert_true(false, "No space for IPv6 header"); } net_buf_add(frag, sizeof(ipv6)); if (net_buf_tailroom(frag) < sizeof(udp)) { printk("Not enough space for UDP header, " "needed %zd bytes, has %zd bytes\n", sizeof(udp), net_buf_tailroom(frag)); zassert_true(false, "No space for UDP header"); } net_pkt_set_appdata(pkt, (void *)udp + sizeof(*udp)); net_pkt_set_appdatalen(pkt, 0); } net_pkt_frag_add(pkt, frag); /* Put some data to rest of the fragments */ frag = net_pkt_get_reserve_rx_data(LL_RESERVE, K_FOREVER); if (net_buf_tailroom(frag) - (CONFIG_NET_BUF_DATA_SIZE - LL_RESERVE)) { printk("Invalid number of bytes available in the buf, " "should be 0 but was %zd - %d\n", net_buf_tailroom(frag), CONFIG_NET_BUF_DATA_SIZE - LL_RESERVE); zassert_true(false, "Invalid byte count"); } if (((int)net_buf_tailroom(frag) - remaining) > 0) { printk("We should have been out of space now, " "tailroom %zd user data len %zd\n", net_buf_tailroom(frag), strlen(example_data)); zassert_true(false, "Still space"); } while (remaining > 0) { int copy; bytes = net_buf_tailroom(frag); copy = remaining > bytes ? bytes : remaining; memcpy(net_buf_add(frag, copy), &example_data[pos], copy); DBG("Remaining %d left %d copy %d\n", remaining, bytes, copy); pos += bytes; remaining -= bytes; if (net_buf_tailroom(frag) - (bytes - copy)) { printk("There should have not been any tailroom left, " "tailroom %zd\n", net_buf_tailroom(frag) - (bytes - copy)); zassert_true(false, "There is still tailroom left"); } net_pkt_frag_add(pkt, frag); if (remaining > 0) { frag = net_pkt_get_reserve_rx_data(LL_RESERVE, K_FOREVER); } } bytes = net_pkt_get_len(pkt); if (bytes != strlen(example_data)) { printk("Invalid number of bytes in message, %zd vs %d\n", strlen(example_data), bytes); zassert_true(false, "Invalid number of bytes"); } /* Normally one should not unref the fragment list like this * because it will leave the pkt->frags pointing to already * freed fragment. */ net_pkt_frag_unref(pkt->frags); zassert_not_null(pkt->frags, "Frag list empty"); pkt->frags = NULL; /* to prevent double free */ net_pkt_unref(pkt); }
static void test_pkt_read_write_insert(void) { struct net_buf *read_frag; struct net_buf *temp_frag; struct net_pkt *pkt; struct net_buf *frag; u8_t read_data[100]; u16_t read_pos; u16_t len; u16_t pos; /* Example of multi fragment read, append and skip APS's */ pkt = net_pkt_get_reserve_rx(0, K_FOREVER); net_pkt_set_ll_reserve(pkt, LL_RESERVE); frag = net_pkt_get_reserve_rx_data(net_pkt_ll_reserve(pkt), K_FOREVER); net_pkt_frag_add(pkt, frag); /* 1) Offset is with in input fragment. * Write app data after IPv6 and UDP header. (If the offset is after * IPv6 + UDP header size, api will create empty space till offset * and write data). */ frag = net_pkt_write(pkt, frag, NET_IPV6UDPH_LEN, &pos, 10, (u8_t *)sample_data, K_FOREVER); zassert_false(!frag || pos != 58, "Usecase 1: Write failed"); read_frag = net_frag_read(frag, NET_IPV6UDPH_LEN, &read_pos, 10, read_data); zassert_false(!read_frag && read_pos == 0xffff, "Usecase 1: Read failed"); zassert_false(memcmp(read_data, sample_data, 10), "Usecase 1: Read data mismatch"); /* 2) Write IPv6 and UDP header at offset 0. (Empty space is created * already in Usecase 1, just need to fill the header, at this point * there shouldn't be any length change). */ frag = net_pkt_write(pkt, frag, 0, &pos, NET_IPV6UDPH_LEN, (u8_t *)sample_data, K_FOREVER); zassert_false(!frag || pos != 48, "Usecase 2: Write failed"); read_frag = net_frag_read(frag, 0, &read_pos, NET_IPV6UDPH_LEN, read_data); zassert_false(!read_frag && read_pos == 0xffff, "Usecase 2: Read failed"); zassert_false(memcmp(read_data, sample_data, NET_IPV6UDPH_LEN), "Usecase 2: Read data mismatch"); net_pkt_unref(pkt); pkt = net_pkt_get_reserve_rx(0, K_FOREVER); net_pkt_set_ll_reserve(pkt, LL_RESERVE); /* 3) Offset is in next to next fragment. * Write app data after 2 fragments. (If the offset far away, api will * create empty fragments(space) till offset and write data). */ frag = net_pkt_write(pkt, pkt->frags, 200, &pos, 10, (u8_t *)sample_data + 10, K_FOREVER); zassert_not_null(frag, "Usecase 3: Write failed"); read_frag = net_frag_read(frag, pos - 10, &read_pos, 10, read_data); zassert_false(!read_frag && read_pos == 0xffff, "Usecase 3: Read failed"); zassert_false(memcmp(read_data, sample_data + 10, 10), "Usecase 3: Read data mismatch"); /* 4) Offset is in next to next fragment (overwrite). * Write app data after 2 fragments. (Space is already available from * Usecase 3, this scenatio doesn't create any space, it just overwrites * the existing data. */ frag = net_pkt_write(pkt, pkt->frags, 190, &pos, 10, (u8_t *)sample_data, K_FOREVER); zassert_not_null(frag, "Usecase 4: Write failed"); read_frag = net_frag_read(frag, pos - 10, &read_pos, 20, read_data); zassert_false(!read_frag && read_pos == 0xffff, "Usecase 4: Read failed"); zassert_false(memcmp(read_data, sample_data, 20), "Usecase 4: Read data mismatch"); net_pkt_unref(pkt); /* 5) Write 20 bytes in fragment which has only 10 bytes space. * API should overwrite on first 10 bytes and create extra 10 bytes * and write there. */ pkt = net_pkt_get_reserve_rx(0, K_FOREVER); net_pkt_set_ll_reserve(pkt, LL_RESERVE); frag = net_pkt_get_reserve_rx_data(net_pkt_ll_reserve(pkt), K_FOREVER); net_pkt_frag_add(pkt, frag); /* Create 10 bytes space. */ net_buf_add(frag, 10); frag = net_pkt_write(pkt, frag, 0, &pos, 20, (u8_t *)sample_data, K_FOREVER); zassert_false(!frag && pos != 20, "Usecase 5: Write failed"); read_frag = net_frag_read(frag, 0, &read_pos, 20, read_data); zassert_false(!read_frag && read_pos == 0xffff, "Usecase 5: Read failed"); zassert_false(memcmp(read_data, sample_data, 20), "USecase 5: Read data mismatch"); net_pkt_unref(pkt); /* 6) First fragment is full, second fragment has 10 bytes tail room, * third fragment has 5 bytes. * Write data (30 bytes) in second fragment where offset is 10 bytes * before the tailroom. * So it should overwrite 10 bytes and create space for another 10 * bytes and write data. Third fragment 5 bytes overwritten and space * for 5 bytes created. */ pkt = net_pkt_get_reserve_rx(0, K_FOREVER); net_pkt_set_ll_reserve(pkt, LL_RESERVE); /* First fragment make it fully occupied. */ frag = net_pkt_get_reserve_rx_data(net_pkt_ll_reserve(pkt), K_FOREVER); net_pkt_frag_add(pkt, frag); len = net_buf_tailroom(frag); net_buf_add(frag, len); /* 2nd fragment last 10 bytes tailroom, rest occupied */ frag = net_pkt_get_reserve_rx_data(net_pkt_ll_reserve(pkt), K_FOREVER); net_pkt_frag_add(pkt, frag); len = net_buf_tailroom(frag); net_buf_add(frag, len - 10); read_frag = temp_frag = frag; read_pos = frag->len - 10; /* 3rd fragment, only 5 bytes occupied */ frag = net_pkt_get_reserve_rx_data(net_pkt_ll_reserve(pkt), K_FOREVER); net_pkt_frag_add(pkt, frag); net_buf_add(frag, 5); temp_frag = net_pkt_write(pkt, temp_frag, temp_frag->len - 10, &pos, 30, (u8_t *) sample_data, K_FOREVER); zassert_not_null(temp_frag, "Use case 6: Write failed"); read_frag = net_frag_read(read_frag, read_pos, &read_pos, 30, read_data); zassert_false(!read_frag && read_pos == 0xffff, "Usecase 6: Read failed"); zassert_false(memcmp(read_data, sample_data, 30), "Usecase 6: Read data mismatch"); net_pkt_unref(pkt); /* 7) Offset is with in input fragment. * Write app data after IPv6 and UDP header. (If the offset is after * IPv6 + UDP header size, api will create empty space till offset * and write data). Insert some app data after IPv6 + UDP header * before first set of app data. */ pkt = net_pkt_get_reserve_rx(0, K_FOREVER); net_pkt_set_ll_reserve(pkt, LL_RESERVE); /* First fragment make it fully occupied. */ frag = net_pkt_get_reserve_rx_data(net_pkt_ll_reserve(pkt), K_FOREVER); net_pkt_frag_add(pkt, frag); frag = net_pkt_write(pkt, frag, NET_IPV6UDPH_LEN, &pos, 10, (u8_t *)sample_data + 10, K_FOREVER); zassert_false(!frag || pos != 58, "Usecase 7: Write failed"); read_frag = net_frag_read(frag, NET_IPV6UDPH_LEN, &read_pos, 10, read_data); zassert_false(!read_frag && read_pos == 0xffff, "Usecase 7: Read failed"); zassert_false(memcmp(read_data, sample_data + 10, 10), "Usecase 7: Read data mismatch"); zassert_true(net_pkt_insert(pkt, frag, NET_IPV6UDPH_LEN, 10, (u8_t *)sample_data, K_FOREVER), "Usecase 7: Insert failed"); read_frag = net_frag_read(frag, NET_IPV6UDPH_LEN, &read_pos, 20, read_data); zassert_false(!read_frag && read_pos == 0xffff, "Usecase 7: Read after failed"); zassert_false(memcmp(read_data, sample_data, 20), "Usecase 7: Read data mismatch after insertion"); /* Insert data outside input fragment length, error case. */ zassert_false(net_pkt_insert(pkt, frag, 70, 10, (u8_t *)sample_data, K_FOREVER), "Usecase 7: False insert failed"); net_pkt_unref(pkt); /* 8) Offset is with in input fragment. * Write app data after IPv6 and UDP header. (If the offset is after * IPv6 + UDP header size, api will create empty space till offset * and write data). Insert some app data after IPv6 + UDP header * before first set of app data. Insertion data is long which will * take two fragments. */ pkt = net_pkt_get_reserve_rx(0, K_FOREVER); net_pkt_set_ll_reserve(pkt, LL_RESERVE); /* First fragment make it fully occupied. */ frag = net_pkt_get_reserve_rx_data(net_pkt_ll_reserve(pkt), K_FOREVER); net_pkt_frag_add(pkt, frag); frag = net_pkt_write(pkt, frag, NET_IPV6UDPH_LEN, &pos, 10, (u8_t *)sample_data + 60, K_FOREVER); zassert_false(!frag || pos != 58, "Usecase 8: Write failed"); read_frag = net_frag_read(frag, NET_IPV6UDPH_LEN, &read_pos, 10, read_data); zassert_false(!read_frag && read_pos == 0xffff, "Usecase 8: Read failed"); zassert_false(memcmp(read_data, sample_data + 60, 10), "Usecase 8: Read data mismatch"); zassert_true(net_pkt_insert(pkt, frag, NET_IPV6UDPH_LEN, 60, (u8_t *)sample_data, K_FOREVER), "Usecase 8: Insert failed"); read_frag = net_frag_read(frag, NET_IPV6UDPH_LEN, &read_pos, 70, read_data); zassert_false(!read_frag && read_pos == 0xffff, "Usecase 8: Read after failed"); zassert_false(memcmp(read_data, sample_data, 70), "Usecase 8: Read data mismatch after insertion"); net_pkt_unref(pkt); DBG("test_pkt_read_write_insert passed\n"); }
static void test_pkt_read_append(void) { int remaining = strlen(sample_data); u8_t verify_rw_short[sizeof(test_rw_short)]; u8_t verify_rw_long[sizeof(test_rw_long)]; struct net_pkt *pkt; struct net_buf *frag; struct net_buf *tfrag; struct ipv6_hdr *ipv6; struct udp_hdr *udp; u8_t data[10]; int pos = 0; int bytes; u16_t off; u16_t tpos; u16_t fail_pos; /* Example of multi fragment read, append and skip APS's */ pkt = net_pkt_get_reserve_rx(0, K_FOREVER); frag = net_pkt_get_reserve_rx_data(LL_RESERVE, K_FOREVER); /* Place the IP + UDP header in the first fragment */ if (!net_buf_tailroom(frag)) { ipv6 = (struct ipv6_hdr *)(frag->data); udp = (struct udp_hdr *)((void *)ipv6 + sizeof(*ipv6)); if (net_buf_tailroom(frag) < sizeof(ipv6)) { printk("Not enough space for IPv6 header, " "needed %zd bytes, has %zd bytes\n", sizeof(ipv6), net_buf_tailroom(frag)); zassert_true(false, "No space for IPv6 header"); } net_buf_add(frag, sizeof(ipv6)); if (net_buf_tailroom(frag) < sizeof(udp)) { printk("Not enough space for UDP header, " "needed %zd bytes, has %zd bytes\n", sizeof(udp), net_buf_tailroom(frag)); zassert_true(false, "No space for UDP header"); } net_pkt_set_appdata(pkt, (void *)udp + sizeof(*udp)); net_pkt_set_appdatalen(pkt, 0); } net_pkt_frag_add(pkt, frag); /* Put some data to rest of the fragments */ frag = net_pkt_get_reserve_rx_data(LL_RESERVE, K_FOREVER); if (net_buf_tailroom(frag) - (CONFIG_NET_BUF_DATA_SIZE - LL_RESERVE)) { printk("Invalid number of bytes available in the buf, " "should be 0 but was %zd - %d\n", net_buf_tailroom(frag), CONFIG_NET_BUF_DATA_SIZE - LL_RESERVE); zassert_true(false, "Invalid number of bytes avail"); } if (((int)net_buf_tailroom(frag) - remaining) > 0) { printk("We should have been out of space now, " "tailroom %zd user data len %zd\n", net_buf_tailroom(frag), strlen(sample_data)); zassert_true(false, "Not out of space"); } while (remaining > 0) { int copy; bytes = net_buf_tailroom(frag); copy = remaining > bytes ? bytes : remaining; memcpy(net_buf_add(frag, copy), &sample_data[pos], copy); DBG("Remaining %d left %d copy %d\n", remaining, bytes, copy); pos += bytes; remaining -= bytes; if (net_buf_tailroom(frag) - (bytes - copy)) { printk("There should have not been any tailroom left, " "tailroom %zd\n", net_buf_tailroom(frag) - (bytes - copy)); zassert_true(false, "Still tailroom left"); } net_pkt_frag_add(pkt, frag); if (remaining > 0) { frag = net_pkt_get_reserve_rx_data(LL_RESERVE, K_FOREVER); } } bytes = net_pkt_get_len(pkt); if (bytes != strlen(sample_data)) { printk("Invalid number of bytes in message, %zd vs %d\n", strlen(sample_data), bytes); zassert_true(false, "Message size wrong"); } /* Failure cases */ /* Invalid buffer */ tfrag = net_frag_skip(NULL, 10, &fail_pos, 10); zassert_true(!tfrag && fail_pos == 0xffff, "Invalid case NULL buffer"); /* Invalid: Skip more than a buffer length.*/ tfrag = net_buf_frag_last(pkt->frags); tfrag = net_frag_skip(tfrag, tfrag->len - 1, &fail_pos, tfrag->len + 2); if (!(!tfrag && fail_pos == 0xffff)) { printk("Invalid case offset %d length to skip %d," "frag length %d\n", tfrag->len - 1, tfrag->len + 2, tfrag->len); zassert_true(false, "Invalid offset"); } /* Invalid offset */ tfrag = net_buf_frag_last(pkt->frags); tfrag = net_frag_skip(tfrag, tfrag->len + 10, &fail_pos, 10); if (!(!tfrag && fail_pos == 0xffff)) { printk("Invalid case offset %d length to skip %d," "frag length %d\n", tfrag->len + 10, 10, tfrag->len); zassert_true(false, "Invalid offset"); } /* Valid cases */ /* Offset is more than single fragment length */ /* Get the first data fragment */ tfrag = pkt->frags; tfrag = tfrag->frags; off = tfrag->len; tfrag = net_frag_read(tfrag, off + 10, &tpos, 10, data); if (!tfrag || memcmp(sample_data + off + 10, data, 10)) { printk("Failed to read from offset %d, frag length %d " "read length %d\n", tfrag->len + 10, tfrag->len, 10); zassert_true(false, "Fail offset read"); } /* Skip till end of all fragments */ /* Get the first data fragment */ tfrag = pkt->frags; tfrag = tfrag->frags; tfrag = net_frag_skip(tfrag, 0, &tpos, strlen(sample_data)); zassert_true(!tfrag && tpos == 0, "Invalid skip till end of all fragments"); /* Short data test case */ /* Test case scenario: * 1) Cache the current fragment and offset * 2) Append short data * 3) Append short data again * 4) Skip first short data from cached frag or offset * 5) Read short data and compare */ tfrag = net_buf_frag_last(pkt->frags); off = tfrag->len; zassert_true(net_pkt_append_all(pkt, (u16_t)sizeof(test_rw_short), test_rw_short, K_FOREVER), "net_pkt_append failed"); zassert_true(net_pkt_append_all(pkt, (u16_t)sizeof(test_rw_short), test_rw_short, K_FOREVER), "net_pkt_append failed"); tfrag = net_frag_skip(tfrag, off, &tpos, (u16_t)sizeof(test_rw_short)); zassert_not_null(tfrag, "net_frag_skip failed"); tfrag = net_frag_read(tfrag, tpos, &tpos, (u16_t)sizeof(test_rw_short), verify_rw_short); zassert_true(!tfrag && tpos == 0, "net_frag_read failed"); zassert_false(memcmp(test_rw_short, verify_rw_short, sizeof(test_rw_short)), "net_frag_read failed with mismatch data"); /* Long data test case */ /* Test case scenario: * 1) Cache the current fragment and offset * 2) Append long data * 3) Append long data again * 4) Skip first long data from cached frag or offset * 5) Read long data and compare */ tfrag = net_buf_frag_last(pkt->frags); off = tfrag->len; zassert_true(net_pkt_append_all(pkt, (u16_t)sizeof(test_rw_long), test_rw_long, K_FOREVER), "net_pkt_append failed"); zassert_true(net_pkt_append_all(pkt, (u16_t)sizeof(test_rw_long), test_rw_long, K_FOREVER), "net_pkt_append failed"); tfrag = net_frag_skip(tfrag, off, &tpos, (u16_t)sizeof(test_rw_long)); zassert_not_null(tfrag, "net_frag_skip failed"); tfrag = net_frag_read(tfrag, tpos, &tpos, (u16_t)sizeof(test_rw_long), verify_rw_long); zassert_true(!tfrag && tpos == 0, "net_frag_read failed"); zassert_false(memcmp(test_rw_long, verify_rw_long, sizeof(test_rw_long)), "net_frag_read failed with mismatch data"); net_pkt_unref(pkt); DBG("test_pkt_read_append passed\n"); }
static int piggyback_get(struct zoap_resource *resource, struct zoap_packet *request, const struct sockaddr *from) { struct net_pkt *pkt; struct net_buf *frag; struct zoap_packet response; u8_t *payload, code, type; u16_t len, id; int r; code = zoap_header_get_code(request); type = zoap_header_get_type(request); id = zoap_header_get_id(request); printk("*******\n"); printk("type: %u code %u id %u\n", type, code, id); printk("*******\n"); pkt = net_pkt_get_reserve(&zoap_pkt_slab, 0, K_NO_WAIT); if (!pkt) { return -ENOMEM; } frag = net_buf_alloc(&zoap_data_pool, K_NO_WAIT); if (!frag) { return -ENOMEM; } net_pkt_frag_add(pkt, frag); r = zoap_packet_init(&response, pkt); if (r < 0) { return -EINVAL; } zoap_header_set_version(&response, 1); zoap_header_set_type(&response, ZOAP_TYPE_ACK); zoap_header_set_code(&response, ZOAP_RESPONSE_CODE_CONTENT); zoap_header_set_id(&response, id); payload = zoap_packet_get_payload(&response, &len); if (!payload) { return -EINVAL; } /* The response that coap-client expects */ r = snprintk((char *)payload, len, "Type: %u\nCode: %u\nMID: %u\n", type, code, id); if (r < 0 || r > len) { return -EINVAL; } r = zoap_packet_set_used(&response, r); if (r) { return -EINVAL; } do { r = mbedtls_ssl_write(curr_ctx, frag->data, frag->len); } while (r == MBEDTLS_ERR_SSL_WANT_READ || r == MBEDTLS_ERR_SSL_WANT_WRITE); if (r >= 0) { r = 0; } net_pkt_unref(pkt); return r; }
static struct net_pkt *build_reply_pkt(const char *name, struct net_context *context, struct net_pkt *pkt) { struct net_pkt *reply_pkt; struct net_buf *frag, *tmp; int header_len, recv_len, reply_len; NET_INFO("%s received %d bytes", name, net_pkt_appdatalen(pkt)); if (net_pkt_appdatalen(pkt) == 0) { return NULL; } reply_pkt = net_pkt_get_tx(context, K_FOREVER); NET_ASSERT(reply_pkt); recv_len = net_pkt_get_len(pkt); tmp = pkt->frags; /* First fragment will contain IP header so move the data * down in order to get rid of it. */ header_len = net_pkt_appdata(pkt) - tmp->data; NET_ASSERT(header_len < CONFIG_NET_BUF_DATA_SIZE); /* After this pull, the tmp->data points directly to application * data. */ net_buf_pull(tmp, header_len); while (tmp) { frag = net_pkt_get_data(context, K_FOREVER); if (!net_buf_headroom(tmp)) { /* If there is no link layer headers in the * received fragment, then get rid of that also * in the sending fragment. We end up here * if MTU is larger than fragment size, this * is typical for ethernet. */ net_buf_push(frag, net_buf_headroom(frag)); frag->len = 0; /* to make fragment empty */ /* Make sure to set the reserve so that * in sending side we add the link layer * header if needed. */ net_pkt_set_ll_reserve(reply_pkt, 0); } NET_ASSERT(net_buf_tailroom(frag) >= tmp->len); memcpy(net_buf_add(frag, tmp->len), tmp->data, tmp->len); net_pkt_frag_add(reply_pkt, frag); tmp = net_pkt_frag_del(pkt, NULL, tmp); } reply_len = net_pkt_get_len(reply_pkt); NET_ASSERT_INFO((recv_len - header_len) == reply_len, "Received %d bytes, sending %d bytes", recv_len - header_len, reply_len); return reply_pkt; }
struct net_pkt * ieee802154_create_mac_cmd_frame(struct ieee802154_context *ctx, enum ieee802154_cfi type, struct ieee802154_frame_params *params) { struct ieee802154_fcf_seq *fs; struct net_pkt *pkt; struct net_buf *frag; u8_t *p_buf; pkt = net_pkt_get_reserve_tx(0, K_FOREVER); if (!pkt) { return NULL; } frag = net_pkt_get_frag(pkt, K_FOREVER); if (!frag) { goto error; } net_pkt_frag_add(pkt, frag); p_buf = net_pkt_ll(pkt); fs = generate_fcf_grounds(&p_buf, type == IEEE802154_CFI_BEACON_REQUEST ? false : ctx->ack_requested); fs->fc.frame_type = IEEE802154_FRAME_TYPE_MAC_COMMAND; fs->sequence = ctx->sequence; if (!cfi_to_fs_settings(type, fs, params)) { goto error; } p_buf = generate_addressing_fields(ctx, fs, params, p_buf); /* Let's insert the cfi */ ((struct ieee802154_command *)p_buf)->cfi = type; /* In MAC command, we consider ll header being the mhr. * Rest will be the MAC command itself. This will proove * to be easy to handle afterwards to point directly to MAC * command space, in order to fill-in its content. */ net_pkt_set_ll_reserve(pkt, p_buf - net_pkt_ll(pkt)); net_buf_pull(frag, net_pkt_ll_reserve(pkt)); /* Thus setting the right MAC command length * Now up to the caller to fill-in this space relevantly. * See ieee802154_mac_command() helper. */ frag->len = mac_command_length(type); dbg_print_fs(fs); return pkt; error: net_pkt_unref(pkt); return NULL; }
void dtls_server(void) { int len, ret = 0; struct udp_context ctx; struct dtls_timing_context timer; struct zoap_packet zpkt; struct net_pkt *pkt; struct net_buf *frag; mbedtls_ssl_cookie_ctx cookie_ctx; mbedtls_entropy_context entropy; mbedtls_ctr_drbg_context ctr_drbg; mbedtls_ssl_context ssl; mbedtls_ssl_config conf; mbedtls_ctr_drbg_init(&ctr_drbg); mbedtls_platform_set_printf(printk); #if defined(MBEDTLS_DEBUG_C) mbedtls_debug_set_threshold(DEBUG_THRESHOLD); #endif /* * Initialize and setup */ mbedtls_ssl_init(&ssl); mbedtls_ssl_config_init(&conf); mbedtls_entropy_init(&entropy); mbedtls_entropy_add_source(&entropy, entropy_source, NULL, MBEDTLS_ENTROPY_MAX_GATHER, MBEDTLS_ENTROPY_SOURCE_STRONG); ret = mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &entropy, (const unsigned char *)pers, strlen(pers)); if (ret != 0) { mbedtls_printf(" failed!\n" " mbedtls_ctr_drbg_seed returned -0x%x\n", -ret); goto exit; } ret = mbedtls_ssl_config_defaults(&conf, MBEDTLS_SSL_IS_SERVER, MBEDTLS_SSL_TRANSPORT_DATAGRAM, MBEDTLS_SSL_PRESET_DEFAULT); if (ret != 0) { mbedtls_printf(" failed!\n" " mbedtls_ssl_config_defaults returned -0x%x\n", -ret); goto exit; } /* Modify this to change the default timeouts for the DTLS handshake */ /* mbedtls_ssl_conf_handshake_timeout( &conf, min, max ); */ mbedtls_ssl_conf_rng(&conf, mbedtls_ctr_drbg_random, &ctr_drbg); mbedtls_ssl_conf_dbg(&conf, my_debug, NULL); #if defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C) mbedtls_memory_buffer_alloc_init(heap, sizeof(heap)); #endif ret = mbedtls_ssl_cookie_setup(&cookie_ctx, mbedtls_ctr_drbg_random, &ctr_drbg); if (ret != 0) { mbedtls_printf(" failed!\n" " mbedtls_ssl_cookie_setup returned -0x%x\n", -ret); goto exit; } mbedtls_ssl_conf_dtls_cookies(&conf, mbedtls_ssl_cookie_write, mbedtls_ssl_cookie_check, &cookie_ctx); ret = mbedtls_ssl_setup(&ssl, &conf); if (ret != 0) { mbedtls_printf(" failed!\n" " mbedtls_ssl_setup returned -0x%x\n", -ret); goto exit; } ret = udp_init(&ctx); if (ret != 0) { mbedtls_printf(" failed!\n udp_init returned 0x%x\n", ret); goto exit; } reset: mbedtls_ssl_session_reset(&ssl); #if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) ret = mbedtls_ssl_conf_psk(&conf, psk, strlen(psk), psk_id, strlen(psk_id)); if (ret != 0) { mbedtls_printf(" failed!\n mbedtls_ssl_conf_psk" " returned -0x%04X\n", -ret); goto exit; } #endif mbedtls_ssl_set_timer_cb(&ssl, &timer, dtls_timing_set_delay, dtls_timing_get_delay); mbedtls_ssl_set_bio(&ssl, &ctx, udp_tx, udp_rx, NULL); /* For HelloVerifyRequest cookies */ ctx.client_id = (char)ctx.remaining; ret = mbedtls_ssl_set_client_transport_id(&ssl, &ctx.client_id, sizeof(char)); if (ret != 0) { mbedtls_printf(" failed!\n" " mbedtls_ssl_set_client_transport_id()" " returned -0x%x\n", -ret); goto exit; } curr_ctx = &ssl; do { ret = mbedtls_ssl_handshake(&ssl); } while (ret == MBEDTLS_ERR_SSL_WANT_READ || ret == MBEDTLS_ERR_SSL_WANT_WRITE); if (ret == MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED) { ret = 0; goto reset; } if (ret != 0) { mbedtls_printf(" failed!\n" " mbedtls_ssl_handshake returned -0x%x\n", -ret); goto reset; } do { /* Read the request */ pkt = net_pkt_get_reserve(&zoap_pkt_slab, 0, K_NO_WAIT); if (!pkt) { mbedtls_printf("Could not get packet from slab\n"); goto exit; } frag = net_buf_alloc(&zoap_data_pool, K_NO_WAIT); if (!frag) { mbedtls_printf("Could not get frag from pool\n"); goto exit; } net_pkt_frag_add(pkt, frag); len = ZOAP_BUF_SIZE - 1; memset(frag->data, 0, ZOAP_BUF_SIZE); ret = mbedtls_ssl_read(&ssl, frag->data, len); if (ret == MBEDTLS_ERR_SSL_WANT_READ || ret == MBEDTLS_ERR_SSL_WANT_WRITE) { continue; } if (ret <= 0) { net_pkt_unref(pkt); switch (ret) { case MBEDTLS_ERR_SSL_TIMEOUT: mbedtls_printf(" timeout\n"); goto reset; case MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY: mbedtls_printf(" connection was closed" " gracefully\n"); goto close_notify; default: mbedtls_printf(" mbedtls_ssl_read" " returned -0x%x\n", -ret); goto reset; } } len = ret; frag->len = len; ret = zoap_packet_parse(&zpkt, pkt); if (ret) { mbedtls_printf("Could not parse packet\n"); goto exit; } ret = zoap_handle_request(&zpkt, resources, (const struct sockaddr *)&ssl); if (ret < 0) { mbedtls_printf("No handler for such request (%d)\n", ret); } net_pkt_unref(pkt); } while (1); close_notify: /* No error checking, the connection might be closed already */ do { ret = mbedtls_ssl_close_notify(&ssl); } while (ret == MBEDTLS_ERR_SSL_WANT_WRITE); ret = 0; mbedtls_printf(" done\n"); goto reset; exit: mbedtls_ssl_free(&ssl); mbedtls_ssl_config_free(&conf); mbedtls_ctr_drbg_free(&ctr_drbg); mbedtls_entropy_free(&entropy); }
static int query_get(struct zoap_resource *resource, struct zoap_packet *request, const struct sockaddr *from) { struct zoap_option options[4]; struct net_pkt *pkt; struct net_buf *frag; struct zoap_packet response; u8_t *payload, code, type; u16_t len, id; int i, r; code = zoap_header_get_code(request); type = zoap_header_get_type(request); id = zoap_header_get_id(request); r = zoap_find_options(request, ZOAP_OPTION_URI_QUERY, options, 4); if (r <= 0) { return -EINVAL; } printk("*******\n"); printk("type: %u code %u id %u\n", type, code, id); printk("num queries: %d\n", r); for (i = 0; i < r; i++) { char str[16]; if (options[i].len + 1 > sizeof(str)) { printk("Unexpected length of query: " "%d (expected %zu)\n", options[i].len, sizeof(str)); break; } memcpy(str, options[i].value, options[i].len); str[options[i].len] = '\0'; printk("query[%d]: %s\n", i + 1, str); } printk("*******\n"); pkt = net_pkt_get_reserve(&zoap_pkt_slab, 0, K_NO_WAIT); if (!pkt) { return -ENOMEM; } frag = net_buf_alloc(&zoap_data_pool, K_NO_WAIT); if (!frag) { return -ENOMEM; } net_pkt_frag_add(pkt, frag); r = zoap_packet_init(&response, pkt); if (r < 0) { return -EINVAL; } /* FIXME: Could be that zoap_packet_init() sets some defaults */ zoap_header_set_version(&response, 1); zoap_header_set_type(&response, ZOAP_TYPE_ACK); zoap_header_set_code(&response, ZOAP_RESPONSE_CODE_CONTENT); zoap_header_set_id(&response, id); payload = zoap_packet_get_payload(&response, &len); if (!payload) { return -EINVAL; } /* The response that coap-client expects */ r = snprintk((char *)payload, len, "Type: %u\nCode: %u\nMID: %u\n", type, code, id); if (r < 0 || r > len) { return -EINVAL; } r = zoap_packet_set_used(&response, r); if (r) { return -EINVAL; } do { r = mbedtls_ssl_write(curr_ctx, frag->data, frag->len); } while (r == MBEDTLS_ERR_SSL_WANT_READ || r == MBEDTLS_ERR_SSL_WANT_WRITE); if (r >= 0) { r = 0; } net_pkt_unref(pkt); return r; }
static bool run_tests(void) { struct net_pkt *pkt, *pkt2; struct net_buf *frag; struct net_if *iface; struct net_if_addr *ifaddr; struct net_arp_hdr *arp_hdr; struct net_ipv4_hdr *ipv4; struct net_eth_hdr *eth_hdr; int len; struct in_addr dst = { { { 192, 168, 0, 2 } } }; struct in_addr dst_far = { { { 10, 11, 12, 13 } } }; struct in_addr dst_far2 = { { { 172, 16, 14, 186 } } }; struct in_addr src = { { { 192, 168, 0, 1 } } }; struct in_addr netmask = { { { 255, 255, 255, 0 } } }; struct in_addr gw = { { { 192, 168, 0, 42 } } }; net_arp_init(); iface = net_if_get_default(); net_if_ipv4_set_gw(iface, &gw); net_if_ipv4_set_netmask(iface, &netmask); /* Unicast test */ ifaddr = net_if_ipv4_addr_add(iface, &src, NET_ADDR_MANUAL, 0); ifaddr->addr_state = NET_ADDR_PREFERRED; /* Application data for testing */ pkt = net_pkt_get_reserve_tx(sizeof(struct net_eth_hdr), K_FOREVER); if (!pkt) { printk("Out of mem TX\n"); return false; } frag = net_pkt_get_frag(pkt, K_FOREVER); if (!frag) { printk("Out of mem DATA\n"); return false; } net_pkt_frag_add(pkt, frag); net_pkt_set_iface(pkt, iface); setup_eth_header(iface, pkt, &hwaddr, NET_ETH_PTYPE_IP); len = strlen(app_data); if (net_pkt_ll_reserve(pkt) != sizeof(struct net_eth_hdr)) { printk("LL reserve invalid, should be %zd was %d\n", sizeof(struct net_eth_hdr), net_pkt_ll_reserve(pkt)); return false; } ipv4 = (struct net_ipv4_hdr *)net_buf_add(frag, sizeof(struct net_ipv4_hdr)); net_ipaddr_copy(&ipv4->src, &src); net_ipaddr_copy(&ipv4->dst, &dst); memcpy(net_buf_add(frag, len), app_data, len); pkt2 = net_arp_prepare(pkt); /* pkt2 is the ARP packet and pkt is the IPv4 packet and it was * stored in ARP table. */ if (pkt2 == pkt) { /* The packets cannot be the same as the ARP cache has * still room for the pkt. */ printk("ARP cache should still have free space\n"); return false; } if (!pkt2) { printk("ARP pkt is empty\n"); return false; } /* The ARP cache should now have a link to pending net_pkt * that is to be sent after we have got an ARP reply. */ if (!pkt->frags) { printk("Pending pkt fragment is NULL\n"); return false; } pending_pkt = pkt; /* pkt2 should contain the arp header, verify it */ if (memcmp(net_pkt_ll(pkt2), net_eth_broadcast_addr(), sizeof(struct net_eth_addr))) { printk("ARP ETH dest address invalid\n"); net_hexdump("ETH dest wrong ", net_pkt_ll(pkt2), sizeof(struct net_eth_addr)); net_hexdump("ETH dest correct", (u8_t *)net_eth_broadcast_addr(), sizeof(struct net_eth_addr)); return false; } if (memcmp(net_pkt_ll(pkt2) + sizeof(struct net_eth_addr), iface->link_addr.addr, sizeof(struct net_eth_addr))) { printk("ARP ETH source address invalid\n"); net_hexdump("ETH src correct", iface->link_addr.addr, sizeof(struct net_eth_addr)); net_hexdump("ETH src wrong ", net_pkt_ll(pkt2) + sizeof(struct net_eth_addr), sizeof(struct net_eth_addr)); return false; } arp_hdr = NET_ARP_HDR(pkt2); eth_hdr = NET_ETH_HDR(pkt2); if (eth_hdr->type != htons(NET_ETH_PTYPE_ARP)) { printk("ETH type 0x%x, should be 0x%x\n", eth_hdr->type, htons(NET_ETH_PTYPE_ARP)); return false; } if (arp_hdr->hwtype != htons(NET_ARP_HTYPE_ETH)) { printk("ARP hwtype 0x%x, should be 0x%x\n", arp_hdr->hwtype, htons(NET_ARP_HTYPE_ETH)); return false; } if (arp_hdr->protocol != htons(NET_ETH_PTYPE_IP)) { printk("ARP protocol 0x%x, should be 0x%x\n", arp_hdr->protocol, htons(NET_ETH_PTYPE_IP)); return false; } if (arp_hdr->hwlen != sizeof(struct net_eth_addr)) { printk("ARP hwlen 0x%x, should be 0x%zx\n", arp_hdr->hwlen, sizeof(struct net_eth_addr)); return false; } if (arp_hdr->protolen != sizeof(struct in_addr)) { printk("ARP IP addr len 0x%x, should be 0x%zx\n", arp_hdr->protolen, sizeof(struct in_addr)); return false; } if (arp_hdr->opcode != htons(NET_ARP_REQUEST)) { printk("ARP opcode 0x%x, should be 0x%x\n", arp_hdr->opcode, htons(NET_ARP_REQUEST)); return false; } if (!net_ipv4_addr_cmp(&arp_hdr->dst_ipaddr, &NET_IPV4_HDR(pkt)->dst)) { char out[sizeof("xxx.xxx.xxx.xxx")]; snprintk(out, sizeof(out), "%s", net_sprint_ipv4_addr(&arp_hdr->dst_ipaddr)); printk("ARP IP dest invalid %s, should be %s", out, net_sprint_ipv4_addr(&NET_IPV4_HDR(pkt)->dst)); return false; } if (!net_ipv4_addr_cmp(&arp_hdr->src_ipaddr, &NET_IPV4_HDR(pkt)->src)) { char out[sizeof("xxx.xxx.xxx.xxx")]; snprintk(out, sizeof(out), "%s", net_sprint_ipv4_addr(&arp_hdr->src_ipaddr)); printk("ARP IP src invalid %s, should be %s", out, net_sprint_ipv4_addr(&NET_IPV4_HDR(pkt)->src)); return false; } /* We could have send the new ARP request but for this test we * just free it. */ net_pkt_unref(pkt2); if (pkt->ref != 2) { printk("ARP cache should own the original packet\n"); return false; } /* Then a case where target is not in the same subnet */ net_ipaddr_copy(&ipv4->dst, &dst_far); pkt2 = net_arp_prepare(pkt); if (pkt2 == pkt) { printk("ARP cache should not find anything\n"); return false; } if (!pkt2) { printk("ARP pkt2 is empty\n"); return false; } arp_hdr = NET_ARP_HDR(pkt2); if (!net_ipv4_addr_cmp(&arp_hdr->dst_ipaddr, &iface->ipv4.gw)) { char out[sizeof("xxx.xxx.xxx.xxx")]; snprintk(out, sizeof(out), "%s", net_sprint_ipv4_addr(&arp_hdr->dst_ipaddr)); printk("ARP IP dst invalid %s, should be %s\n", out, net_sprint_ipv4_addr(&iface->ipv4.gw)); return false; } net_pkt_unref(pkt2); /* Try to find the same destination again, this should fail as there * is a pending request in ARP cache. */ net_ipaddr_copy(&ipv4->dst, &dst_far); /* Make sure prepare will not free the pkt because it will be * needed in the later test case. */ net_pkt_ref(pkt); pkt2 = net_arp_prepare(pkt); if (!pkt2) { printk("ARP cache is not sending the request again\n"); return false; } net_pkt_unref(pkt2); /* Try to find the different destination, this should fail too * as the cache table should be full. */ net_ipaddr_copy(&ipv4->dst, &dst_far2); /* Make sure prepare will not free the pkt because it will be * needed in the next test case. */ net_pkt_ref(pkt); pkt2 = net_arp_prepare(pkt); if (!pkt2) { printk("ARP cache did not send a req\n"); return false; } /* Restore the original address so that following test case can * work properly. */ net_ipaddr_copy(&ipv4->dst, &dst); /* The arp request packet is now verified, create an arp reply. * The previous value of pkt is stored in arp table and is not lost. */ pkt = net_pkt_get_reserve_rx(sizeof(struct net_eth_hdr), K_FOREVER); if (!pkt) { printk("Out of mem RX reply\n"); return false; } printk("%d pkt %p\n", __LINE__, pkt); frag = net_pkt_get_frag(pkt, K_FOREVER); if (!frag) { printk("Out of mem DATA reply\n"); return false; } printk("%d frag %p\n", __LINE__, frag); net_pkt_frag_add(pkt, frag); net_pkt_set_iface(pkt, iface); arp_hdr = NET_ARP_HDR(pkt); net_buf_add(frag, sizeof(struct net_arp_hdr)); net_ipaddr_copy(&arp_hdr->dst_ipaddr, &dst); net_ipaddr_copy(&arp_hdr->src_ipaddr, &src); pkt2 = prepare_arp_reply(iface, pkt, &hwaddr); if (!pkt2) { printk("ARP reply generation failed."); return false; } /* The pending packet should now be sent */ switch (net_arp_input(pkt2)) { case NET_OK: case NET_CONTINUE: break; case NET_DROP: break; } /* Yielding so that network interface TX thread can proceed. */ k_yield(); if (send_status < 0) { printk("ARP reply was not sent\n"); return false; } if (pkt->ref != 1) { printk("ARP cache should no longer own the original packet\n"); return false; } net_pkt_unref(pkt); /* Then feed in ARP request */ pkt = net_pkt_get_reserve_rx(sizeof(struct net_eth_hdr), K_FOREVER); if (!pkt) { printk("Out of mem RX request\n"); return false; } frag = net_pkt_get_frag(pkt, K_FOREVER); if (!frag) { printk("Out of mem DATA request\n"); return false; } net_pkt_frag_add(pkt, frag); net_pkt_set_iface(pkt, iface); send_status = -EINVAL; arp_hdr = NET_ARP_HDR(pkt); net_buf_add(frag, sizeof(struct net_arp_hdr)); net_ipaddr_copy(&arp_hdr->dst_ipaddr, &src); net_ipaddr_copy(&arp_hdr->src_ipaddr, &dst); setup_eth_header(iface, pkt, &hwaddr, NET_ETH_PTYPE_ARP); pkt2 = prepare_arp_request(iface, pkt, &hwaddr); if (!pkt2) { printk("ARP request generation failed."); return false; } req_test = true; switch (net_arp_input(pkt2)) { case NET_OK: case NET_CONTINUE: break; case NET_DROP: break; } /* Yielding so that network interface TX thread can proceed. */ k_yield(); if (send_status < 0) { printk("ARP req was not sent\n"); return false; } net_pkt_unref(pkt); printk("Network ARP checks passed\n"); return true; }
static void test_fragment_copy(void) { struct net_pkt *pkt, *new_pkt; struct net_buf *frag, *new_frag; struct ipv6_hdr *ipv6; struct udp_hdr *udp; size_t orig_len, reserve; int pos; pkt = net_pkt_get_reserve_rx(0, K_FOREVER); frag = net_pkt_get_reserve_rx_data(LL_RESERVE, K_FOREVER); /* Place the IP + UDP header in the first fragment */ if (net_buf_tailroom(frag)) { ipv6 = (struct ipv6_hdr *)(frag->data); udp = (struct udp_hdr *)((void *)ipv6 + sizeof(*ipv6)); if (net_buf_tailroom(frag) < sizeof(*ipv6)) { printk("Not enough space for IPv6 header, " "needed %zd bytes, has %zd bytes\n", sizeof(ipv6), net_buf_tailroom(frag)); zassert_true(false, "No space for IPv6 header"); } net_buf_add(frag, sizeof(*ipv6)); if (net_buf_tailroom(frag) < sizeof(*udp)) { printk("Not enough space for UDP header, " "needed %zd bytes, has %zd bytes\n", sizeof(udp), net_buf_tailroom(frag)); zassert_true(false, "No space for UDP header"); } net_buf_add(frag, sizeof(*udp)); memcpy(net_buf_add(frag, 15), example_data, 15); net_pkt_set_appdata(pkt, (void *)udp + sizeof(*udp) + 15); net_pkt_set_appdatalen(pkt, 0); } net_pkt_frag_add(pkt, frag); orig_len = net_pkt_get_len(pkt); DBG("Total copy data len %zd\n", orig_len); linearize(pkt, buf_orig, orig_len); /* Then copy a fragment list to a new fragment list. * Reserve some space in front of the buffers. */ reserve = sizeof(struct ipv6_hdr) + sizeof(struct icmp_hdr); new_frag = net_pkt_copy_all(pkt, reserve, K_FOREVER); zassert_not_null(new_frag, "Cannot copy fragment list"); new_pkt = net_pkt_get_reserve_tx(0, K_FOREVER); new_pkt->frags = net_buf_frag_add(new_pkt->frags, new_frag); DBG("Total new data len %zd\n", net_pkt_get_len(new_pkt)); if ((net_pkt_get_len(pkt) + reserve) != net_pkt_get_len(new_pkt)) { int diff; diff = net_pkt_get_len(new_pkt) - reserve - net_pkt_get_len(pkt); printk("Fragment list missing data, %d bytes not copied " "(%zd vs %zd)\n", diff, net_pkt_get_len(pkt) + reserve, net_pkt_get_len(new_pkt)); zassert_true(false, "Frag list missing"); } if (net_pkt_get_len(new_pkt) != (orig_len + sizeof(struct ipv6_hdr) + sizeof(struct icmp_hdr))) { printk("Fragment list missing data, new pkt len %zd " "should be %zd\n", net_pkt_get_len(new_pkt), orig_len + sizeof(struct ipv6_hdr) + sizeof(struct icmp_hdr)); zassert_true(false, "Frag list missing data"); } linearize(new_pkt, buf_copy, sizeof(buf_copy)); zassert_true(memcmp(buf_orig, buf_copy, sizeof(buf_orig)), "Buffer copy failed, buffers are same"); pos = memcmp(buf_orig, buf_copy + sizeof(struct ipv6_hdr) + sizeof(struct icmp_hdr), orig_len); if (pos) { printk("Buffer copy failed at pos %d\n", pos); zassert_true(false, "Buf copy failed"); } }