
On 2023/5/11 00:59, Dmitrii Merkurev wrote:
Add TCP/IP6 related headers and reuse refactored TCP/IP implementation
Signed-off-by: Dmitrii Merkurev dimorinny@google.com Cc: Ying-Chun Liu (PaulLiu) paul.liu@linaro.org Cc: Simon Glass sjg@chromium.org Сс: Joe Hershberger joe.hershberger@ni.com Сс: Ramon Fried rfried.dev@gmail.com
include/net/tcp6.h | 106 +++++++++++++++++++++++++++++++++++++++++++++ include/net6.h | 14 ++++++ net/Makefile | 1 + net/net.c | 6 +++ net/net6.c | 72 +++++++++++++++++++++++++----- net/tcp6.c | 99 ++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 288 insertions(+), 10 deletions(-) create mode 100644 include/net/tcp6.h create mode 100644 net/tcp6.c
diff --git a/include/net/tcp6.h b/include/net/tcp6.h new file mode 100644 index 0000000000..3db125ecc5 --- /dev/null +++ b/include/net/tcp6.h @@ -0,0 +1,106 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/*
- Copyright (C) 2022 The Android Open Source Project
- */
+#ifndef __TCP6_H__ +#define __TCP6_H__
+#if defined(CONFIG_PROT_TCP)
+#include <net6.h> +#include <net/tcp.h>
+/**
- typedef rxhand_tcp6_f() - An incoming TCP IPv6 packet handler.
- @pkt: pointer to the application packet
- @dport: destination TCP port
- @sip: source IP6 address
- @sport: source TCP port
- @tcp_seq_num: TCP sequential number
- @tcp_ack_num: TCP acknowledgment number
- @action: TCP packet type (SYN, ACK, FIN, etc)
- */
+typedef void rxhand_tcp6_f(uchar *pkt, u16 dport,
struct in6_addr sip, u16 sport,
u32 tcp_seq_num, u32 tcp_ack_num,
u8 action, unsigned int len);
+/**
- struct ip6_tcp_hdr_o - IP6 + TCP header + TCP options
- @ip_hdr: IP6 + TCP header
- @tcp_hdr: TCP header
- @tcp_o: TCP options
- @end: end of IP6/TCP header
- */
+struct ip6_tcp_hdr_o {
- struct ip6_hdr ip_hdr;
- struct tcp_hdr tcp_hdr;
- struct tcp_hdr_o tcp_o;
- u8 end;
+} __packed;
+#define IP6_TCP_O_SIZE (sizeof(struct ip6_tcp_hdr_o))
+/**
- struct ip6_tcp_hdr_s - IP6 + TCP header + TCP options
- @ip_hdr: IP6 + TCP header
- @tcp_hdr: TCP header
- @t_opt: TCP Timestamp Option
- @sack_v: TCP SACK Option
- @end: end of options
- */
+struct ip6_tcp_hdr_s {
- struct ip6_hdr ip_hdr;
- struct tcp_hdr tcp_hdr;
- struct tcp_t_opt t_opt;
- struct tcp_sack_v sack_v;
- u8 end;
+} __packed;
+#define IP6_TCP_SACK_SIZE (sizeof(struct ip6_tcp_hdr_s))
+/**
- union tcp6_build_pkt - union for building TCP/IP6 packet.
- @ip: IP6 and TCP header plus TCP options
- @sack: IP6 and TCP header plus SACK options
- @raw: buffer
- */
+union tcp6_build_pkt {
- struct ip6_tcp_hdr_o ip;
- struct ip6_tcp_hdr_s sack;
- uchar raw[1600];
+} __packed;
+/**
- net_set_tcp6_handler6() - set application TCP6 packet handler
- @param f pointer to callback function
- */
+void net_set_tcp_handler6(rxhand_tcp6_f *f);
+/**
- net_set_tcp_header6() - set
- @pkt: pointer to IP6/TCP headers
- @dport: destination TCP port
- @sport: source TCP port
- @payload_len: payload length
- @action: TCP packet type (SYN, ACK, FIN, etc)
- @tcp_seq_num: TCP sequential number
- @tcp_ack_num: TCP acknowledgment number
- returns TCP header size
- */
+int net_set_tcp_header6(uchar *pkt, u16 dport, u16 sport, int payload_len,
u8 action, u32 tcp_seq_num, u32 tcp_ack_num);
+void net_set_tcp_handler6(rxhand_tcp6_f *f);
+/**
- rxhand_tcp6() - handle incoming IP6 TCP packet
- @param b pointer to IP6/TCP packet builder struct
- @param len full packet length
- */
+void rxhand_tcp6(union tcp6_build_pkt *b, unsigned int len);
+#endif // CONFIG_PROT_TCP +#endif // __TCP6_H__ diff --git a/include/net6.h b/include/net6.h index beafc05338..fa926f07ac 100644 --- a/include/net6.h +++ b/include/net6.h @@ -344,6 +344,20 @@ int ip6_add_hdr(uchar *xip, struct in6_addr *src, struct in6_addr *dest, int net_send_udp_packet6(uchar *ether, struct in6_addr *dest, int dport, int sport, int len);
+/**
- net_send_tcp_packet6() - Make up TCP packet and send it
- @payload_len: TCP payload length
- @dport: destination port
- @sport: source port
- @action: TCP flag (SYN, ACL, PUSH, etc)
- @tcp_seq_num: TCP sequence number
- @tcp_ack_num: TCP ackno
- Return: 0 if send successfully, -1 otherwise
- */
+int net_send_tcp_packet6(int payload_len, int dport, int sport, u8 action,
u32 tcp_seq_num, u32 tcp_ack_num);
- /**
- net_ip6_handler() - Handle IPv6 packet
diff --git a/net/Makefile b/net/Makefile index 3e2d061338..002b0f68a2 100644 --- a/net/Makefile +++ b/net/Makefile @@ -32,6 +32,7 @@ obj-$(CONFIG_TCP_FUNCTION_FASTBOOT) += fastboot_tcp.o obj-$(CONFIG_CMD_WOL) += wol.o obj-$(CONFIG_PROT_UDP) += udp.o obj-$(CONFIG_PROT_TCP) += tcp.o +obj-$(CONFIG_IPV6) += tcp6.o obj-$(CONFIG_CMD_WGET) += wget.o
# Disable this warning as it is triggered by: diff --git a/net/net.c b/net/net.c index 0b68bf7b13..9ef290dc41 100644 --- a/net/net.c +++ b/net/net.c @@ -92,6 +92,7 @@ #include <log.h> #include <net.h> #include <net6.h> +#include <net/tcp6.h> #include <ndisc.h> #include <net/fastboot_udp.h> #include <net/fastboot_tcp.h> @@ -386,6 +387,9 @@ static void net_clear_handlers(void) net_set_udp_handler(NULL); net_set_arp_handler(NULL); net_set_timeout_handler(0, NULL); +#if defined(CONFIG_IPV6) && defined(CONFIG_PROT_TCP)
- net_set_tcp_handler6(NULL);
+#endif }
static void net_cleanup_loop(void) @@ -916,7 +920,9 @@ int net_send_ip_packet(uchar *ether, struct in_addr dest, int dport, int sport, { uchar *pkt; int eth_hdr_size; +#if defined(CONFIG_PROT_TCP) int ip_tcp_hdr_size; +#endif int pkt_hdr_size;
/* make sure the net_tx_packet is initialized (net_init() was called) */ diff --git a/net/net6.c b/net/net6.c index e395b930b0..575726766e 100644 --- a/net/net6.c +++ b/net/net6.c @@ -14,6 +14,7 @@ #include <malloc.h> #include <net.h> #include <net6.h> +#include <net/tcp6.h> #include <ndisc.h>
/* NULL IPv6 address */ @@ -350,11 +351,17 @@ int net_send_ip_packet6(uchar *ether, struct in6_addr *dest, int dport, int spor u32 tcp_ack_num) { uchar *pkt;
- int pkt_hdr_size; int eth_hdr_size;
+#if defined(CONFIG_PROT_UDP) || defined(CONFIG_PROT_TCP) int ip_hdr_size; +#endif +#if defined(CONFIG_PROT_UDP) int udp_hdr_size; +#endif +#if defined(CONFIG_PROT_TCP) int tcp_hdr_size;
- int pkt_hdr_size;
+#endif
if (!net_tx_packet) return -1; @@ -362,8 +369,8 @@ int net_send_ip_packet6(uchar *ether, struct in6_addr *dest, int dport, int spor pkt = (uchar *)net_tx_packet;
eth_hdr_size = net_set_ether(pkt, ether, PROT_IP6);
- pkt_hdr_size += eth_hdr_size;
- pkt = eth_hdr_size;
pkt_hdr_size = eth_hdr_size;
pkt += eth_hdr_size;
switch (proto) { #if defined(CONFIG_PROT_UDP)
@@ -377,6 +384,18 @@ int net_send_ip_packet6(uchar *ether, struct in6_addr *dest, int dport, int spor pkt_hdr_size += udp_hdr_size; pkt += udp_hdr_size; break; +#endif +#if defined(CONFIG_PROT_TCP)
- case IPPROTO_TCP:
tcp_hdr_size = net_set_tcp_header6(pkt, dport, sport,
payload_len, action, tcp_seq_num,
tcp_ack_num);
ip_hdr_size = ip6_add_hdr(pkt, &net_ip6, dest, IPPROTO_TCP, 64,
tcp_hdr_size + payload_len);
pkt_hdr_size += ip_hdr_size + tcp_hdr_size;
pkt += ip_hdr_size + tcp_hdr_size;
#endif default: return -EINVAL;break;
@@ -411,11 +430,25 @@ int net_send_udp_packet6(uchar *ether, struct in6_addr *dest, int dport, return net_send_ip_packet6(ether, dest, dport, sport, len, IPPROTO_UDP, 0, 0, 0); }
+int net_send_tcp_packet6(int payload_len, int dport, int sport, u8 action,
u32 tcp_seq_num, u32 tcp_ack_num)
+{
- return net_send_ip_packet6(net_server_ethaddr, &net_server_ip6, dport,
sport, payload_len, IPPROTO_TCP, action,
tcp_seq_num, tcp_ack_num);
+}
- int net_ip6_handler(struct ethernet_hdr *et, struct ip6_hdr *ip6, int len) {
- struct in_addr zero_ip = {.s_addr = 0 }; struct icmp6hdr *icmp;
+#if defined(CONFIG_PROT_UDP)
- struct in_addr zero_ip = {.s_addr = 0 }; struct udp_hdr *udp;
+#endif +#if defined(CONFIG_PROT_TCP)
- union tcp6_build_pkt *tcp_headers;
- struct tcp_hdr *tcp;
+#endif u16 csum; u16 csum_p; u16 hlen; @@ -454,6 +487,7 @@ int net_ip6_handler(struct ethernet_hdr *et, struct ip6_hdr *ip6, int len) break; } break; +#if defined(CONFIG_PROT_UDP) case IPPROTO_UDP: udp = (struct udp_hdr *)(((uchar *)ip6) + IP6_HDR_SIZE); csum = udp->udp_xsum; @@ -468,13 +502,31 @@ int net_ip6_handler(struct ethernet_hdr *et, struct ip6_hdr *ip6, int len) return -EINVAL;
/* IP header OK. Pass the packet to the current handler. */
net_get_udp_handler()((uchar *)ip6 + IP6_HDR_SIZE +
UDP_HDR_SIZE,
ntohs(udp->udp_dst),
zero_ip,
ntohs(udp->udp_src),
ntohs(udp->udp_len) - 8);
net_get_udp_handler()((uchar *)ip6 + IP6_HDR_SIZE + UDP_HDR_SIZE,
ntohs(udp->udp_dst),
zero_ip,
ntohs(udp->udp_src),
ntohs(udp->udp_len) - 8);
break;
+#endif +#if defined(CONFIG_PROT_TCP)
- case IPPROTO_TCP:
tcp = (struct tcp_hdr *)(((uchar *)ip6) + IP6_HDR_SIZE);
csum = tcp->tcp_xsum;
hlen = ntohs(ip6->payload_len);
tcp->tcp_xsum = 0;
/* checksum */
csum_p = csum_partial((u8 *)tcp, hlen, 0);
tcp->tcp_xsum = csum_ipv6_magic(&ip6->saddr, &ip6->daddr,
hlen, IPPROTO_TCP, csum_p);
if (csum != tcp->tcp_xsum)
return -EINVAL;
tcp_headers = (union tcp6_build_pkt *)ip6;
break;rxhand_tcp6(tcp_headers, len);
+#endif default: return -EINVAL; } diff --git a/net/tcp6.c b/net/tcp6.c new file mode 100644 index 0000000000..09b2190db7 --- /dev/null +++ b/net/tcp6.c @@ -0,0 +1,99 @@ +// SPDX-License-Identifier: GPL-2.0+ +/*
- Copyright (C) 2022 The Android Open Source Project
- */
+#if defined(CONFIG_PROT_TCP)
+#include <common.h> +#include <net/tcp.h> +#include <net/tcp6.h> +#include <net6.h>
+static rxhand_tcp6_f *tcp6_packet_handler;
+static void dummy_handler(uchar *pkt, u16 dport,
struct in6_addr sip, u16 sport,
u32 tcp_seq_num, u32 tcp_ack_num,
u8 action, unsigned int len)
+{ +}
+void net_set_tcp_handler6(rxhand_tcp6_f *f) +{
- if (!f)
tcp6_packet_handler = dummy_handler;
- else
tcp6_packet_handler = f;
+}
+int net_set_tcp_header6(uchar *pkt, u16 dport, u16 sport, int payload_len,
u8 action, u32 tcp_seq_num, u32 tcp_ack_num)
+{
- union tcp6_build_pkt *b = (union tcp6_build_pkt *)pkt;
- int tcp_hdr_len;
- int pkt_len;
- u16 csum;
- pkt_len = IP6_HDR_SIZE;
- tcp_hdr_len = net_set_tcp_header_common(&b->ip.tcp_hdr, &b->ip.tcp_o,
&b->sack.t_opt, &b->sack.sack_v,
dport, sport, payload_len, action,
tcp_seq_num, tcp_ack_num);
- pkt_len += tcp_hdr_len;
- pkt_len += payload_len;
- csum = csum_partial((u8 *)&b->ip.tcp_hdr, tcp_hdr_len + payload_len, 0);
- b->ip.tcp_hdr.tcp_xsum = csum_ipv6_magic(&net_ip6, &net_server_ip6,
tcp_hdr_len + payload_len,
IPPROTO_TCP, csum);
- return tcp_hdr_len;
+}
+void rxhand_tcp6(union tcp6_build_pkt *b, unsigned int len) +{
- int tcp_len = len - IP6_HDR_SIZE;
- u8 tcp_action = TCP_DATA;
- u32 tcp_seq_num, tcp_ack_num;
- u32 res_tcp_seq_num, res_tcp_ack_num;
- int tcp_hdr_len, payload_len;
- net_copy_ip6(&net_server_ip6, &b->ip.ip_hdr.saddr);
- tcp_hdr_len = GET_TCP_HDR_LEN_IN_BYTES(b->ip.tcp_hdr.tcp_hlen);
- payload_len = tcp_len - tcp_hdr_len;
- if (tcp_hdr_len > TCP_HDR_SIZE)
tcp_parse_options((uchar *)b + IP6_HDR_SIZE + TCP_HDR_SIZE,
tcp_hdr_len - TCP_HDR_SIZE);
- tcp_seq_num = ntohl(b->ip.tcp_hdr.tcp_seq);
- tcp_ack_num = ntohl(b->ip.tcp_hdr.tcp_ack);
- tcp_action = tcp_state_machine(b->ip.tcp_hdr.tcp_flags,
tcp_seq_num, &res_tcp_seq_num, &res_tcp_ack_num,
payload_len);
- if ((tcp_action & TCP_PUSH) || payload_len > 0) {
debug_cond(DEBUG_DEV_PKT,
"TCP Notify (action=%x, Seq=%u,Ack=%u,Pay%d)\n",
tcp_action, tcp_seq_num, tcp_ack_num, payload_len);
(*tcp6_packet_handler) ((uchar *)b + len - payload_len, b->ip.tcp_hdr.tcp_dst,
b->ip.ip_hdr.saddr, b->ip.tcp_hdr.tcp_src, tcp_seq_num,
tcp_ack_num, tcp_action, payload_len);
- } else if (tcp_action != TCP_DATA) {
debug_cond(DEBUG_DEV_PKT,
"TCP Action (action=%x,Seq=%u,Ack=%u,Pay=%d)\n",
tcp_action, res_tcp_seq_num, res_tcp_ack_num, payload_len);
net_send_tcp_packet6(0, ntohs(b->ip.tcp_hdr.tcp_src),
ntohs(b->ip.tcp_hdr.tcp_dst),
(tcp_action & (~TCP_PUSH)),
res_tcp_seq_num, res_tcp_ack_num);
- }
+}
+#endif // CONFIG_PROT_TCP
Reviewed-by: Ying-Chun Liu (PaulLiu) paul.liu@linaro.org