From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from gandalf.ozlabs.org (gandalf.ozlabs.org [150.107.74.76]) by passt.top (Postfix) with ESMTPS id C9C505A0279 for ; Thu, 21 Dec 2023 07:53:36 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gibson.dropbear.id.au; s=202312; t=1703141610; bh=5dD8Fr6dmgGcOBSYHgUUJjSk113aW84rsnKojfm0sz4=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=RvHyehheY86L39DvKSOSk49I5NfGehvkANbTmk+qX6UXi8w154GStpadhxKeHo95l ILP8pxoyELRUy+Rnc7wNnL9M4EOWUOT5RSnbags9FXkIZJftGtzIJF5TaXlokRz5tp Wr7lkAV+84fTiMhBzGhY/Yp68aoLc++pXATikkQjKT17n3AhStm2duyAA2iD3ktKyR FdGvuqRGJGAXAbLIU4VuCUD54dIUmtuZXQhG50IAS/BG8KIpgGP/rq3EJTAmcx7FD/ KbzBTBLTY/KcDSYDZRSdlpKY8ndhAb8IDLL1LEba/ezULrFfv0Csfd4b1pKQMe0ixT 9fB2Xist6LGcg== Received: by gandalf.ozlabs.org (Postfix, from userid 1007) id 4Swh3G5Dwfz4xSX; Thu, 21 Dec 2023 17:53:30 +1100 (AEDT) From: David Gibson To: Stefano Brivio , passt-dev@passt.top Subject: [PATCH v2 09/12] icmp: Consolidate icmp_sock_handler() with icmpv6_sock_handler() Date: Thu, 21 Dec 2023 17:53:24 +1100 Message-ID: <20231221065327.1307827-10-david@gibson.dropbear.id.au> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20231221065327.1307827-1-david@gibson.dropbear.id.au> References: <20231221065327.1307827-1-david@gibson.dropbear.id.au> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Message-ID-Hash: PTIDX6DM622OXBEKPNCR6VDOG5CCPH4V X-Message-ID-Hash: PTIDX6DM622OXBEKPNCR6VDOG5CCPH4V X-MailFrom: dgibson@gandalf.ozlabs.org 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: 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: Currently we have separate handlers for ICMP and ICMPv6 ping replies. Although there are a number of points of difference, with some creative refactoring we can combine these together sensibly. Although it doesn't save a vast amount of code, it does make it clearer that we're performing basically the same steps for each case. Signed-off-by: David Gibson --- icmp.c | 90 ++++++++++++++++++++++----------------------------------- icmp.h | 3 +- passt.c | 4 +-- 3 files changed, 37 insertions(+), 60 deletions(-) diff --git a/icmp.c b/icmp.c index f6c744a..b26c61f 100644 --- a/icmp.c +++ b/icmp.c @@ -57,85 +57,63 @@ struct icmp_id_sock { static struct icmp_id_sock icmp_id_map[IP_VERSIONS][ICMP_NUM_IDS]; /** - * icmp_sock_handler() - Handle new data from IPv4 ICMP socket + * icmp_sock_handler() - Handle new data from ICMP or ICMPv6 socket * @c: Execution context + * @af: Address family (AF_INET or AF_INET6) * @ref: epoll reference */ -void icmp_sock_handler(const struct ctx *c, union epoll_ref ref) +void icmp_sock_handler(const struct ctx *c, int af, union epoll_ref ref) { + struct icmp_id_sock *const id_map = af == AF_INET + ? &icmp_id_map[V4][ref.icmp.id] : &icmp_id_map[V6][ref.icmp.id]; + const char *const pname = af == AF_INET ? "ICMP" : "ICMPv6"; char buf[USHRT_MAX]; - struct icmphdr *ih = (struct icmphdr *)buf; - struct sockaddr_in sr; + union { + struct sockaddr sa; + struct sockaddr_in sa4; + struct sockaddr_in6 sa6; + } sr; socklen_t sl = sizeof(sr); - uint16_t seq, id; + uint16_t seq; ssize_t n; if (c->no_icmp) return; - n = recvfrom(ref.fd, buf, sizeof(buf), 0, (struct sockaddr *)&sr, &sl); + n = recvfrom(ref.fd, buf, sizeof(buf), 0, &sr.sa, &sl); if (n < 0) return; - seq = ntohs(ih->un.echo.sequence); - - /* Adjust the packet to have the ID the guest was using, rather than the - * host chosen value */ - id = ref.icmp.id; - ih->un.echo.id = htons(id); + if (af == AF_INET) { + struct icmphdr *ih4 = (struct icmphdr *)buf; - if (c->mode == MODE_PASTA) { - if (icmp_id_map[V4][id].seq == seq) - return; + /* Adjust packet back to guest-side ID */ + ih4->un.echo.id = htons(ref.icmp.id); + seq = ntohs(ih4->un.echo.sequence); + } else if (af == AF_INET6) { + struct icmp6hdr *ih6 = (struct icmp6hdr *)buf; - icmp_id_map[V4][id].seq = seq; + /* Adjust packet back to guest-side ID */ + ih6->icmp6_identifier = htons(ref.icmp.id); + seq = ntohs(ih6->icmp6_sequence); + } else { + ASSERT(0); } - debug("ICMP: echo reply to tap, ID: %i, seq: %i", id, seq); - - tap_icmp4_send(c, sr.sin_addr, tap_ip4_daddr(c), buf, n); -} - -/** - * icmpv6_sock_handler() - Handle new data from ICMPv6 socket - * @c: Execution context - * @ref: epoll reference - */ -void icmpv6_sock_handler(const struct ctx *c, union epoll_ref ref) -{ - char buf[USHRT_MAX]; - struct icmp6hdr *ih = (struct icmp6hdr *)buf; - struct sockaddr_in6 sr; - socklen_t sl = sizeof(sr); - uint16_t seq, id; - ssize_t n; - - if (c->no_icmp) - return; - - n = recvfrom(ref.fd, buf, sizeof(buf), 0, (struct sockaddr *)&sr, &sl); - if (n < 0) - return; - - seq = ntohs(ih->icmp6_sequence); - - /* Adjust the packet to have the ID the guest was using, rather than the - * host chosen value */ - id = ref.icmp.id; - ih->icmp6_identifier = htons(id); - - /* In PASTA mode, we'll get any reply we send, discard them. */ if (c->mode == MODE_PASTA) { - if (icmp_id_map[V6][id].seq == seq) + if (id_map->seq == seq) return; - icmp_id_map[V6][id].seq = seq; + id_map->seq = seq; } - debug("ICMPv6: echo reply to tap, ID: %i, seq: %i", id, seq); - - tap_icmp6_send(c, &sr.sin6_addr, - tap_ip6_daddr(c, &sr.sin6_addr), buf, n); + debug("%s: echo reply to tap, ID: %"PRIu16", seq: %"PRIu16, pname, + ref.icmp.id, seq); + if (af == AF_INET) + tap_icmp4_send(c, sr.sa4.sin_addr, tap_ip4_daddr(c), buf, n); + else if (af == AF_INET6) + tap_icmp6_send(c, &sr.sa6.sin6_addr, + tap_ip6_daddr(c, &sr.sa6.sin6_addr), buf, n); } /** diff --git a/icmp.h b/icmp.h index 4096c65..0083597 100644 --- a/icmp.h +++ b/icmp.h @@ -10,8 +10,7 @@ struct ctx; -void icmp_sock_handler(const struct ctx *c, union epoll_ref ref); -void icmpv6_sock_handler(const struct ctx *c, union epoll_ref ref); +void icmp_sock_handler(const struct ctx *c, int af, union epoll_ref ref); int icmp_tap_handler(const struct ctx *c, uint8_t pif, int af, const void *saddr, const void *daddr, const struct pool *p, const struct timespec *now); diff --git a/passt.c b/passt.c index d315438..44d3a0b 100644 --- a/passt.c +++ b/passt.c @@ -392,10 +392,10 @@ loop: udp_sock_handler(&c, ref, eventmask, &now); break; case EPOLL_TYPE_ICMP: - icmp_sock_handler(&c, ref); + icmp_sock_handler(&c, AF_INET, ref); break; case EPOLL_TYPE_ICMPV6: - icmpv6_sock_handler(&c, ref); + icmp_sock_handler(&c, AF_INET6, ref); break; default: /* Can't happen */ -- 2.43.0