net: tcp2: Add support for a IPv6

In order to support IPv4/IPv6, work with packet through
net_pkt_ip_hdr_len(), net_pkt_ip_opts_len() which account
for IPv4/IPv6, IPv4 options and IPv6 extension headers.

Signed-off-by: Oleg Zhurakivskyy <oleg.zhurakivskyy@intel.com>
This commit is contained in:
Oleg Zhurakivskyy 2020-02-26 17:38:45 +02:00 committed by Jukka Rissanen
commit f5c1ee03b8

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2018-2019 Intel Corporation * Copyright (c) 2018-2020 Intel Corporation
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
@ -31,6 +31,7 @@ static K_MEM_SLAB_DEFINE(tcp_conns_slab, sizeof(struct tcp),
NET_BUF_POOL_DEFINE(tcp_nbufs, 64/*count*/, CONFIG_NET_BUF_DATA_SIZE, 0, NULL); NET_BUF_POOL_DEFINE(tcp_nbufs, 64/*count*/, CONFIG_NET_BUF_DATA_SIZE, 0, NULL);
static void tcp_in(struct tcp *conn, struct net_pkt *pkt); static void tcp_in(struct tcp *conn, struct net_pkt *pkt);
static size_t tcp_data_len(struct net_pkt *pkt);
int (*tcp_send_cb)(struct net_pkt *pkt) = NULL; int (*tcp_send_cb)(struct net_pkt *pkt) = NULL;
@ -77,40 +78,19 @@ static void tcp_nbufs_unreserve(struct tcp *conn)
NET_DBG("%zu->%zu", rsv_bytes_old, conn->rsv_bytes); NET_DBG("%zu->%zu", rsv_bytes_old, conn->rsv_bytes);
} }
/* TODO: IPv4 options may enlarge the IPv4 header */
static struct tcphdr *th_get(struct net_pkt *pkt) static struct tcphdr *th_get(struct net_pkt *pkt)
{ {
struct tcphdr *th = NULL; NET_PKT_DATA_ACCESS_DEFINE(th_access, struct tcphdr);
ssize_t len;
if (pkt == NULL) { net_pkt_cursor_init(pkt);
goto out; net_pkt_set_overwrite(pkt, true);
}
len = net_pkt_get_len(pkt); /* net_pkt_ip_hdr_len(), net_pkt_ip_opts_len() account for IPv4/IPv6 */
switch (pkt->family) { net_pkt_skip(pkt, net_pkt_ip_hdr_len(pkt) +
case AF_INET: net_pkt_ip_opts_len(pkt));
if (len < (sizeof(struct net_ipv4_hdr) +
sizeof(struct tcphdr))) { return net_pkt_get_data(pkt, &th_access);
NET_WARN("Undersized IPv4 packet: %zd byte(s)", len);
goto out;
}
th = (struct tcphdr *)(ip_get(pkt) + 1);
break;
case AF_INET6:
if (len < (sizeof(struct net_ipv6_hdr) +
sizeof(struct tcphdr))) {
NET_WARN("Undersized IPv6 packet: %zd byte(s)", len);
goto out;
}
th = (struct tcphdr *)((u8_t *)ip6_get(pkt) + 1);
break;
default:
break;
}
out:
return th;
} }
static size_t tcp_endpoint_len(sa_family_t af) static size_t tcp_endpoint_len(sa_family_t af)
@ -238,14 +218,8 @@ static const char *tcp_th(struct net_pkt *pkt)
" Ack=%u", th_ack(th)); " Ack=%u", th_ack(th));
} }
{ len += snprintk(buf + len, BUF_SIZE - len,
struct net_ipv4_hdr *ip = ip_get(pkt); " Len=%ld", (long)tcp_data_len(pkt));
ssize_t data_len = ntohs(ip->len) -
(sizeof(*ip) + th->th_off * 4);
len += snprintk(buf + len, BUF_SIZE - len,
" Len=%ld", (long int)data_len);
}
end: end:
#undef BUF_SIZE #undef BUF_SIZE
return buf; return buf;
@ -570,12 +544,13 @@ end:
static size_t tcp_data_len(struct net_pkt *pkt) static size_t tcp_data_len(struct net_pkt *pkt)
{ {
struct net_ipv4_hdr *ip = ip_get(pkt);
struct tcphdr *th = th_get(pkt); struct tcphdr *th = th_get(pkt);
u8_t off = th->th_off; size_t tcp_options_len = (th->th_off - 5) * 4;
ssize_t len = ntohs(ip->len) - sizeof(*ip) - off * 4; ssize_t len = net_pkt_get_len(pkt) - net_pkt_ip_hdr_len(pkt) -
net_pkt_ip_opts_len(pkt) - sizeof(*th) - tcp_options_len;
if (off > 5 && false == tcp_options_check((th + 1), (off - 5) * 4)) { if (tcp_options_len && tcp_options_check((th + 1), tcp_options_len)
== false) {
len = 0; len = 0;
} }
@ -584,7 +559,6 @@ static size_t tcp_data_len(struct net_pkt *pkt)
static size_t tcp_data_get(struct tcp *conn, struct net_pkt *pkt) static size_t tcp_data_get(struct tcp *conn, struct net_pkt *pkt)
{ {
struct net_ipv4_hdr *ip = ip_get(pkt);
struct tcphdr *th = th_get(pkt); struct tcphdr *th = th_get(pkt);
ssize_t len = tcp_data_len(pkt); ssize_t len = tcp_data_len(pkt);
@ -598,7 +572,7 @@ static size_t tcp_data_get(struct tcp *conn, struct net_pkt *pkt)
buf = tcp_malloc(len); buf = tcp_malloc(len);
net_pkt_skip(pkt, sizeof(*ip) + th->th_off * 4); net_pkt_skip(pkt, th->th_off * 4);
net_pkt_read(pkt, buf, len); net_pkt_read(pkt, buf, len);
@ -615,7 +589,8 @@ static size_t tcp_data_get(struct tcp *conn, struct net_pkt *pkt)
net_pkt_cursor_init(up); net_pkt_cursor_init(up);
net_pkt_set_overwrite(up, true); net_pkt_set_overwrite(up, true);
net_pkt_skip(up, 40);
net_pkt_skip(up, net_pkt_get_len(up) - len);
net_context_packet_received( net_context_packet_received(
(struct net_conn *)conn->context->conn_handler, (struct net_conn *)conn->context->conn_handler,