From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by passt.top (Postfix) with ESMTP id 7B7295A027F for ; Thu, 29 Feb 2024 18:00:02 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1709226001; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=HrkYzcPExhxDgIEW5jEMD2hpDfn4frrviPE/ZxVjX3A=; b=EZ1EGaaVaiAN+dhVPDbKCq6Uo7YCef2aI+elQnV/H9lVLW8XyOEuqRHWDZ1GRPvdAvXlj5 C0iAUmZiAPldey2ZMZq/Tpk6Zp6LARPHRwTxGHnxeiqWABkLJ1ntDsTRi028doBI1NXjFd xxI8sSwS5i1JzqrWLGmhl/QOgFJSFnI= Received: from mimecast-mx02.redhat.com (mx-ext.redhat.com [66.187.233.73]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-460-kmw5qxTZMf2zuBlHM94Q1g-1; Thu, 29 Feb 2024 11:59:57 -0500 X-MC-Unique: kmw5qxTZMf2zuBlHM94Q1g-1 Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.rdu2.redhat.com [10.11.54.6]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 4FB223C1494B; Thu, 29 Feb 2024 16:59:57 +0000 (UTC) Received: from virtlab218.virt.lab.eng.bos.redhat.com (virtlab218.virt.lab.eng.bos.redhat.com [10.19.152.190]) by smtp.corp.redhat.com (Postfix) with ESMTP id 3264D2166B5E; Thu, 29 Feb 2024 16:59:57 +0000 (UTC) From: Laurent Vivier To: passt-dev@passt.top Subject: [PATCH v4 4/8] util: move IP stuff from util.[ch] to ip.[ch] Date: Thu, 29 Feb 2024 17:59:51 +0100 Message-ID: <20240229165955.829476-5-lvivier@redhat.com> In-Reply-To: <20240229165955.829476-1-lvivier@redhat.com> References: <20240229165955.829476-1-lvivier@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.11.54.6 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Transfer-Encoding: 8bit Content-Type: text/plain; charset="US-ASCII"; x-default=true Message-ID-Hash: NAZLRYWYD7CL425RLURESHKSWHJINUCD X-Message-ID-Hash: NAZLRYWYD7CL425RLURESHKSWHJINUCD X-MailFrom: lvivier@redhat.com X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; emergency; loop; banned-address; member-moderation; nonmember-moderation; administrivia; implicit-dest; max-recipients; max-size; news-moderation; no-subject; digests; suspicious-header CC: Laurent Vivier , David Gibson X-Mailman-Version: 3.3.8 Precedence: list List-Id: Development discussion and patches for passt Archived-At: Archived-At: List-Archive: List-Archive: List-Help: List-Owner: List-Post: List-Subscribe: List-Unsubscribe: Introduce ip.[ch] file to encapsulate IP protocol handling functions and structures. Modify various files to include the new header ip.h when it's needed. Signed-off-by: Laurent Vivier Reviewed-by: David Gibson --- Notes: v4: - rebase v3: - rewrap rationale - add David's R-b v2: - update rationale and comments Makefile | 10 +++--- conf.c | 1 + dhcp.c | 1 + flow.c | 1 + fwd.c | 1 + icmp.c | 1 + inany.c | 1 + ip.c | 72 +++++++++++++++++++++++++++++++++++++++++++ ip.h | 86 ++++++++++++++++++++++++++++++++++++++++++++++++++++ ndp.c | 1 + qrap.c | 1 + tap.c | 1 + tcp.c | 1 + tcp_splice.c | 1 + udp.c | 1 + util.c | 55 --------------------------------- util.h | 76 ---------------------------------------------- 17 files changed, 175 insertions(+), 136 deletions(-) create mode 100644 ip.c create mode 100644 ip.h diff --git a/Makefile b/Makefile index 8f9669413530..2735797a054c 100644 --- a/Makefile +++ b/Makefile @@ -45,8 +45,8 @@ FLAGS += -DVERSION=\"$(VERSION)\" FLAGS += -DDUAL_STACK_SOCKETS=$(DUAL_STACK_SOCKETS) PASST_SRCS = arch.c arp.c checksum.c conf.c dhcp.c dhcpv6.c flow.c fwd.c \ - icmp.c igmp.c inany.c iov.c isolation.c lineread.c log.c mld.c ndp.c \ - netlink.c packet.c passt.c pasta.c pcap.c pif.c tap.c tcp.c \ + icmp.c igmp.c inany.c iov.c ip.c isolation.c lineread.c log.c mld.c \ + ndp.c netlink.c packet.c passt.c pasta.c pcap.c pif.c tap.c tcp.c \ tcp_splice.c udp.c util.c QRAP_SRCS = qrap.c SRCS = $(PASST_SRCS) $(QRAP_SRCS) @@ -54,9 +54,9 @@ SRCS = $(PASST_SRCS) $(QRAP_SRCS) MANPAGES = passt.1 pasta.1 qrap.1 PASST_HEADERS = arch.h arp.h checksum.h conf.h dhcp.h dhcpv6.h flow.h fwd.h \ - flow_table.h icmp.h inany.h iov.h isolation.h lineread.h log.h ndp.h \ - netlink.h packet.h passt.h pasta.h pcap.h pif.h siphash.h tap.h tcp.h \ - tcp_conn.h tcp_splice.h udp.h util.h + flow_table.h icmp.h inany.h iov.h ip.h isolation.h lineread.h log.h \ + ndp.h netlink.h packet.h passt.h pasta.h pcap.h pif.h siphash.h tap.h \ + tcp.h tcp_conn.h tcp_splice.h udp.h util.h HEADERS = $(PASST_HEADERS) seccomp.h C := \#include \nstruct tcp_info x = { .tcpi_snd_wnd = 0 }; diff --git a/conf.c b/conf.c index e630140def5b..4a783b8b1410 100644 --- a/conf.c +++ b/conf.c @@ -35,6 +35,7 @@ #include #include "util.h" +#include "ip.h" #include "passt.h" #include "netlink.h" #include "udp.h" diff --git a/dhcp.c b/dhcp.c index 110772867632..ff4834a3dce9 100644 --- a/dhcp.c +++ b/dhcp.c @@ -25,6 +25,7 @@ #include #include "util.h" +#include "ip.h" #include "checksum.h" #include "packet.h" #include "passt.h" diff --git a/flow.c b/flow.c index d7974d59974c..5bb24ccf1504 100644 --- a/flow.c +++ b/flow.c @@ -11,6 +11,7 @@ #include #include "util.h" +#include "ip.h" #include "passt.h" #include "siphash.h" #include "inany.h" diff --git a/fwd.c b/fwd.c index 09650b26db11..a235d1315cd6 100644 --- a/fwd.c +++ b/fwd.c @@ -21,6 +21,7 @@ #include #include "util.h" +#include "ip.h" #include "fwd.h" #include "passt.h" #include "lineread.h" diff --git a/icmp.c b/icmp.c index fb2fcafc8b86..49d6dd922212 100644 --- a/icmp.c +++ b/icmp.c @@ -33,6 +33,7 @@ #include "packet.h" #include "util.h" +#include "ip.h" #include "passt.h" #include "tap.h" #include "log.h" diff --git a/inany.c b/inany.c index 1c165b144817..c8479a755818 100644 --- a/inany.c +++ b/inany.c @@ -13,6 +13,7 @@ #include #include "util.h" +#include "ip.h" #include "siphash.h" #include "inany.h" diff --git a/ip.c b/ip.c new file mode 100644 index 000000000000..2cc7f6548aff --- /dev/null +++ b/ip.c @@ -0,0 +1,72 @@ +// SPDX-License-Identifier: GPL-2.0-or-later + +/* PASST - Plug A Simple Socket Transport + * for qemu/UNIX domain socket mode + * + * PASTA - Pack A Subtle Tap Abstraction + * for network namespace/tap device mode + * + * ip.c - IP related functions + * + * Copyright (c) 2020-2021 Red Hat GmbH + * Author: Stefano Brivio + */ + +#include +#include "util.h" +#include "ip.h" + +#define IPV6_NH_OPT(nh) \ + ((nh) == 0 || (nh) == 43 || (nh) == 44 || (nh) == 50 || \ + (nh) == 51 || (nh) == 60 || (nh) == 135 || (nh) == 139 || \ + (nh) == 140 || (nh) == 253 || (nh) == 254) + +/** + * ipv6_l4hdr() - Find pointer to L4 header in IPv6 packet and extract protocol + * @p: Packet pool, packet number @idx has IPv6 header at @offset + * @idx: Index of packet in pool + * @offset: Pre-calculated IPv6 header offset + * @proto: Filled with L4 protocol number + * @dlen: Data length (payload excluding header extensions), set on return + * + * Return: pointer to L4 header, NULL if not found + */ +char *ipv6_l4hdr(const struct pool *p, int idx, size_t offset, uint8_t *proto, + size_t *dlen) +{ + const struct ipv6_opt_hdr *o; + const struct ipv6hdr *ip6h; + char *base; + int hdrlen; + uint8_t nh; + + base = packet_get(p, idx, 0, 0, NULL); + ip6h = packet_get(p, idx, offset, sizeof(*ip6h), dlen); + if (!ip6h) + return NULL; + + offset += sizeof(*ip6h); + + nh = ip6h->nexthdr; + if (!IPV6_NH_OPT(nh)) + goto found; + + while ((o = packet_get_try(p, idx, offset, sizeof(*o), dlen))) { + nh = o->nexthdr; + hdrlen = (o->hdrlen + 1) * 8; + + if (IPV6_NH_OPT(nh)) + offset += hdrlen; + else + goto found; + } + + return NULL; + +found: + if (nh == 59) + return NULL; + + *proto = nh; + return base + offset; +} diff --git a/ip.h b/ip.h new file mode 100644 index 000000000000..9be47783a11e --- /dev/null +++ b/ip.h @@ -0,0 +1,86 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later + * Copyright (c) 2021 Red Hat GmbH + * Author: Stefano Brivio + */ + +#ifndef IP_H +#define IP_H + +#include +#include + +#define IN4_IS_ADDR_UNSPECIFIED(a) \ + (((struct in_addr *)(a))->s_addr == htonl_constant(INADDR_ANY)) +#define IN4_IS_ADDR_BROADCAST(a) \ + (((struct in_addr *)(a))->s_addr == htonl_constant(INADDR_BROADCAST)) +#define IN4_IS_ADDR_LOOPBACK(a) \ + (ntohl(((struct in_addr *)(a))->s_addr) >> IN_CLASSA_NSHIFT == IN_LOOPBACKNET) +#define IN4_IS_ADDR_MULTICAST(a) \ + (IN_MULTICAST(ntohl(((struct in_addr *)(a))->s_addr))) +#define IN4_ARE_ADDR_EQUAL(a, b) \ + (((struct in_addr *)(a))->s_addr == ((struct in_addr *)b)->s_addr) +#define IN4ADDR_LOOPBACK_INIT \ + { .s_addr = htonl_constant(INADDR_LOOPBACK) } +#define IN4ADDR_ANY_INIT \ + { .s_addr = htonl_constant(INADDR_ANY) } + +#define L2_BUF_IP4_INIT(proto) \ + { \ + .version = 4, \ + .ihl = 5, \ + .tos = 0, \ + .tot_len = 0, \ + .id = 0, \ + .frag_off = 0, \ + .ttl = 0xff, \ + .protocol = (proto), \ + .saddr = 0, \ + .daddr = 0, \ + } +#define L2_BUF_IP4_PSUM(proto) ((uint32_t)htons_constant(0x4500) + \ + (uint32_t)htons_constant(0xff00 | (proto))) + +#define L2_BUF_IP6_INIT(proto) \ + { \ + .priority = 0, \ + .version = 6, \ + .flow_lbl = { 0 }, \ + .payload_len = 0, \ + .nexthdr = (proto), \ + .hop_limit = 255, \ + .saddr = IN6ADDR_ANY_INIT, \ + .daddr = IN6ADDR_ANY_INIT, \ + } + +struct ipv6hdr { +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wpedantic" +#if __BYTE_ORDER == __BIG_ENDIAN + uint8_t version:4, + priority:4; +#else + uint8_t priority:4, + version:4; +#endif +#pragma GCC diagnostic pop + uint8_t flow_lbl[3]; + + uint16_t payload_len; + uint8_t nexthdr; + uint8_t hop_limit; + + struct in6_addr saddr; + struct in6_addr daddr; +}; + +struct ipv6_opt_hdr { + uint8_t nexthdr; + uint8_t hdrlen; + /* + * TLV encoded option data follows. + */ +} __attribute__((packed)); /* required for some archs */ + +char *ipv6_l4hdr(const struct pool *p, int idx, size_t offset, uint8_t *proto, + size_t *dlen); +#endif /* IP_H */ diff --git a/ndp.c b/ndp.c index 4c85ab8bcaee..c58f4b222b76 100644 --- a/ndp.c +++ b/ndp.c @@ -28,6 +28,7 @@ #include "checksum.h" #include "util.h" +#include "ip.h" #include "passt.h" #include "tap.h" #include "log.h" diff --git a/qrap.c b/qrap.c index 97f350a4bf0b..d59670621731 100644 --- a/qrap.c +++ b/qrap.c @@ -32,6 +32,7 @@ #include #include "util.h" +#include "ip.h" #include "passt.h" #include "arp.h" diff --git a/tap.c b/tap.c index 3a666212923e..d35d8944fc41 100644 --- a/tap.c +++ b/tap.c @@ -45,6 +45,7 @@ #include "checksum.h" #include "util.h" +#include "ip.h" #include "iov.h" #include "passt.h" #include "arp.h" diff --git a/tcp.c b/tcp.c index 560d1d49def1..e0588f92e65f 100644 --- a/tcp.c +++ b/tcp.c @@ -290,6 +290,7 @@ #include "checksum.h" #include "util.h" +#include "ip.h" #include "passt.h" #include "tap.h" #include "siphash.h" diff --git a/tcp_splice.c b/tcp_splice.c index 4957abb81cde..d066112cd645 100644 --- a/tcp_splice.c +++ b/tcp_splice.c @@ -49,6 +49,7 @@ #include #include "util.h" +#include "ip.h" #include "passt.h" #include "log.h" #include "tcp_splice.h" diff --git a/udp.c b/udp.c index cb7c31f74403..26774df7018c 100644 --- a/udp.c +++ b/udp.c @@ -113,6 +113,7 @@ #include "checksum.h" #include "util.h" +#include "ip.h" #include "siphash.h" #include "inany.h" #include "passt.h" diff --git a/util.c b/util.c index 81449b789b62..bac5a53489f2 100644 --- a/util.c +++ b/util.c @@ -32,61 +32,6 @@ #include "packet.h" #include "log.h" -#define IPV6_NH_OPT(nh) \ - ((nh) == 0 || (nh) == 43 || (nh) == 44 || (nh) == 50 || \ - (nh) == 51 || (nh) == 60 || (nh) == 135 || (nh) == 139 || \ - (nh) == 140 || (nh) == 253 || (nh) == 254) - -/** - * ipv6_l4hdr() - Find pointer to L4 header in IPv6 packet and extract protocol - * @p: Packet pool, packet number @idx has IPv6 header at @offset - * @idx: Index of packet in pool - * @offset: Pre-calculated IPv6 header offset - * @proto: Filled with L4 protocol number - * @dlen: Data length (payload excluding header extensions), set on return - * - * Return: pointer to L4 header, NULL if not found - */ -char *ipv6_l4hdr(const struct pool *p, int idx, size_t offset, uint8_t *proto, - size_t *dlen) -{ - const struct ipv6_opt_hdr *o; - const struct ipv6hdr *ip6h; - char *base; - int hdrlen; - uint8_t nh; - - base = packet_get(p, idx, 0, 0, NULL); - ip6h = packet_get(p, idx, offset, sizeof(*ip6h), dlen); - if (!ip6h) - return NULL; - - offset += sizeof(*ip6h); - - nh = ip6h->nexthdr; - if (!IPV6_NH_OPT(nh)) - goto found; - - while ((o = packet_get_try(p, idx, offset, sizeof(*o), dlen))) { - nh = o->nexthdr; - hdrlen = (o->hdrlen + 1) * 8; - - if (IPV6_NH_OPT(nh)) - offset += hdrlen; - else - goto found; - } - - return NULL; - -found: - if (nh == 59) - return NULL; - - *proto = nh; - return base + offset; -} - /** * sock_l4() - Create and bind socket for given L4, add to epoll list * @c: Execution context diff --git a/util.h b/util.h index 55513490890a..25e54a778478 100644 --- a/util.h +++ b/util.h @@ -110,22 +110,6 @@ #define htonl_constant(x) (__bswap_constant_32(x)) #endif -#define IN4_IS_ADDR_UNSPECIFIED(a) \ - (((struct in_addr *)(a))->s_addr == htonl_constant(INADDR_ANY)) -#define IN4_IS_ADDR_BROADCAST(a) \ - (((struct in_addr *)(a))->s_addr == htonl_constant(INADDR_BROADCAST)) -#define IN4_IS_ADDR_LOOPBACK(a) \ - (ntohl(((struct in_addr *)(a))->s_addr) >> IN_CLASSA_NSHIFT == IN_LOOPBACKNET) -#define IN4_IS_ADDR_MULTICAST(a) \ - (IN_MULTICAST(ntohl(((struct in_addr *)(a))->s_addr))) -#define IN4_ARE_ADDR_EQUAL(a, b) \ - (((struct in_addr *)(a))->s_addr == ((struct in_addr *)b)->s_addr) -#define IN4ADDR_LOOPBACK_INIT \ - { .s_addr = htonl_constant(INADDR_LOOPBACK) } -#define IN4ADDR_ANY_INIT \ - { .s_addr = htonl_constant(INADDR_ANY) } - - #define NS_FN_STACK_SIZE (RLIMIT_STACK_VAL * 1024 / 8) int do_clone(int (*fn)(void *), char *stack_area, size_t stack_size, int flags, void *arg); @@ -138,34 +122,6 @@ int do_clone(int (*fn)(void *), char *stack_area, size_t stack_size, int flags, (void *)(arg)); \ } while (0) -#define L2_BUF_IP4_INIT(proto) \ - { \ - .version = 4, \ - .ihl = 5, \ - .tos = 0, \ - .tot_len = 0, \ - .id = 0, \ - .frag_off = 0, \ - .ttl = 0xff, \ - .protocol = (proto), \ - .saddr = 0, \ - .daddr = 0, \ - } -#define L2_BUF_IP4_PSUM(proto) ((uint32_t)htons_constant(0x4500) + \ - (uint32_t)htons_constant(0xff00 | (proto))) - -#define L2_BUF_IP6_INIT(proto) \ - { \ - .priority = 0, \ - .version = 6, \ - .flow_lbl = { 0 }, \ - .payload_len = 0, \ - .nexthdr = (proto), \ - .hop_limit = 255, \ - .saddr = IN6ADDR_ANY_INIT, \ - .daddr = IN6ADDR_ANY_INIT, \ - } - #define RCVBUF_BIG (2UL * 1024 * 1024) #define SNDBUF_BIG (4UL * 1024 * 1024) #define SNDBUF_SMALL (128UL * 1024) @@ -173,45 +129,13 @@ int do_clone(int (*fn)(void *), char *stack_area, size_t stack_size, int flags, #include #include #include -#include #include "packet.h" struct ctx; -struct ipv6hdr { -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wpedantic" -#if __BYTE_ORDER == __BIG_ENDIAN - uint8_t version:4, - priority:4; -#else - uint8_t priority:4, - version:4; -#endif -#pragma GCC diagnostic pop - uint8_t flow_lbl[3]; - - uint16_t payload_len; - uint8_t nexthdr; - uint8_t hop_limit; - - struct in6_addr saddr; - struct in6_addr daddr; -}; - -struct ipv6_opt_hdr { - uint8_t nexthdr; - uint8_t hdrlen; - /* - * TLV encoded option data follows. - */ -} __attribute__((packed)); /* required for some archs */ - /* cppcheck-suppress funcArgNamesDifferent */ __attribute__ ((weak)) int ffsl(long int i) { return __builtin_ffsl(i); } -char *ipv6_l4hdr(const struct pool *p, int idx, size_t offset, uint8_t *proto, - size_t *dlen); int sock_l4(const struct ctx *c, sa_family_t af, uint8_t proto, const void *bind_addr, const char *ifname, uint16_t port, uint32_t data); -- 2.42.0