From mboxrd@z Thu Jan 1 00:00:00 1970 Authentication-Results: passt.top; dmarc=none (p=none dis=none) header.from=gibson.dropbear.id.au Authentication-Results: passt.top; dkim=pass (2048-bit key; secure) header.d=gibson.dropbear.id.au header.i=@gibson.dropbear.id.au header.a=rsa-sha256 header.s=202410 header.b=W/g19TTO; dkim-atps=neutral Received: from mail.ozlabs.org (mail.ozlabs.org [IPv6:2404:9400:2221:ea00::3]) by passt.top (Postfix) with ESMTPS id 5F2795A061D for ; Tue, 12 Nov 2024 05:06:31 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gibson.dropbear.id.au; s=202410; t=1731384378; bh=NP8v6jbtWLvcrV3FBESxSlUSpQqp18qhPGBvSqYyNwc=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=W/g19TTONxba5bTZz+19tXfMSw0NvKCH4x0tl0Hkq9vgaFjfD7c0scxNEkbfEgeNA H6SkQvWF1fXGaSvfINGOAwHbra6v8NpWHngfxPTUKWpJPY/yXFu7rz92mygFNh7K4r OJKuZ0TyhI/fiXEckEWCqmo8QYRXOk1vdohhNgEQaJXb5We08niU70dZYV78zwiJaq XXhpoVNvmOc8EIg84crXZGX4XVtKLPqgPqpcP/iviZQ/SQEWrIOts9in0I9Nt9rowK WmwZcgZNlAxImaAvpEuOnnIF4n0k9v7JmWl7aJ3am3UsgpiffsC92LCFOL0ESFdJ9F OPVXnQZj8eiPQ== Received: by gandalf.ozlabs.org (Postfix, from userid 1007) id 4XnXsQ2G5nz4xSQ; Tue, 12 Nov 2024 15:06:18 +1100 (AEDT) From: David Gibson To: Stefano Brivio , passt-dev@passt.top Subject: [PATCH 3/6] ndp: Split out helpers for sending specific NDP message types Date: Tue, 12 Nov 2024 15:06:15 +1100 Message-ID: <20241112040618.1804081-4-david@gibson.dropbear.id.au> X-Mailer: git-send-email 2.47.0 In-Reply-To: <20241112040618.1804081-1-david@gibson.dropbear.id.au> References: <20241112040618.1804081-1-david@gibson.dropbear.id.au> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Message-ID-Hash: YZW3UI3DB3EGDRLV77P3UE6DWJQQWP6M X-Message-ID-Hash: YZW3UI3DB3EGDRLV77P3UE6DWJQQWP6M 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 the large ndp() function responds to all NDP messages we handle, both parsing the message as necessary and sending the response. Split out the code to construct and send specific message types into ndp_na() (to send NA messages) and ndp_ra() (to send RA messages). As well as breaking up an excessively large function, this is a first step to being able to send unsolicited NDP messages. While we're there, remove a slighty ugly goto. Signed-off-by: David Gibson --- ndp.c | 136 +++++++++++++++++++++++++++++++++------------------------- 1 file changed, 78 insertions(+), 58 deletions(-) diff --git a/ndp.c b/ndp.c index fa1b67a..e876c34 100644 --- a/ndp.c +++ b/ndp.c @@ -186,16 +186,13 @@ static void ndp_send(const struct ctx *c, const struct in6_addr *dst, } /** - * ndp() - Check for NDP solicitations, reply as needed + * ndp_na() - Send an NDP Neighbour Advertisement (NA) message * @c: Execution context - * @ih: ICMPv6 header - * @saddr: Source IPv6 address - * @p: Packet pool - * - * Return: 0 if not handled here, 1 if handled, -1 on failure + * @dst: IPv6 address to send the NA to + * @addr: IPv6 address to advertise */ -int ndp(const struct ctx *c, const struct icmp6hdr *ih, - const struct in6_addr *saddr, const struct pool *p) +static void ndp_na(const struct ctx *c, const struct in6_addr *dst, + const void *addr) { struct ndp_na na = { .ih = { @@ -212,6 +209,20 @@ int ndp(const struct ctx *c, const struct icmp6hdr *ih, }, } }; + + memcpy(&na.target_addr, addr, sizeof(na.target_addr)); + memcpy(na.target_l2_addr.mac, c->our_tap_mac, ETH_ALEN); + + ndp_send(c, dst, &na, sizeof(na)); +} + +/** + * ndp_ra() - Send an NDP Router Advertisement (RA) message + * @c: Execution context + * @dst: IPv6 address to send the RA to + */ +static void ndp_ra(const struct ctx *c, const struct in6_addr *dst) +{ struct ndp_ra ra = { .ih = { .icmp6_type = RA, @@ -238,58 +249,28 @@ int ndp(const struct ctx *c, const struct icmp6hdr *ih, }, }, }; + unsigned char *ptr = NULL; - if (ih->icmp6_type < RS || ih->icmp6_type > NA) - return 0; - - if (c->no_ndp) - return 1; - - if (ih->icmp6_type == NS) { - const struct ndp_ns *ns = - packet_get(p, 0, 0, sizeof(struct ndp_ns), NULL); + memcpy(&ra.prefix, &c->ip6.addr, sizeof(ra.prefix)); - if (!ns) - return -1; + ptr = &ra.var[0]; - if (IN6_IS_ADDR_UNSPECIFIED(saddr)) - return 1; - - info("NDP: received NS, sending NA"); - - memcpy(&na.target_addr, &ns->target_addr, - sizeof(na.target_addr)); - memcpy(na.target_l2_addr.mac, c->our_tap_mac, ETH_ALEN); + if (c->mtu != -1) { + struct opt_mtu *mtu = (struct opt_mtu *)ptr; + *mtu = (struct opt_mtu) { + .header = { + .type = OPT_MTU, + .len = 1, + }, + .value = htonl(c->mtu), + }; + ptr += sizeof(struct opt_mtu); + } - ndp_send(c, saddr, &na, sizeof(struct ndp_na)); - } else if (ih->icmp6_type == RS) { - unsigned char *ptr = NULL; + if (!c->no_dhcp_dns) { size_t dns_s_len = 0; int i, n; - if (c->no_ra) - return 1; - - info("NDP: received RS, sending RA"); - memcpy(&ra.prefix, &c->ip6.addr, sizeof(ra.prefix)); - - ptr = &ra.var[0]; - - if (c->mtu != -1) { - struct opt_mtu *mtu = (struct opt_mtu *)ptr; - *mtu = (struct opt_mtu) { - .header = { - .type = OPT_MTU, - .len = 1, - }, - .value = htonl(c->mtu), - }; - ptr += sizeof(struct opt_mtu); - } - - if (c->no_dhcp_dns) - goto dns_done; - for (n = 0; !IN6_IS_ADDR_UNSPECIFIED(&c->ip6.dns[n]); n++); if (n) { struct opt_rdnss *rdnss = (struct opt_rdnss *)ptr; @@ -305,7 +286,7 @@ int ndp(const struct ctx *c, const struct icmp6hdr *ih, sizeof(rdnss->dns[i])); } ptr += offsetof(struct opt_rdnss, dns) + - i * sizeof(rdnss->dns[0]); + i * sizeof(rdnss->dns[0]); for (n = 0; *c->dns_search[n].n; n++) dns_s_len += strlen(c->dns_search[n].n) + 2; @@ -329,7 +310,7 @@ int ndp(const struct ctx *c, const struct icmp6hdr *ih, *(ptr++) = '.'; len = sizeof(dnssl->domains) - - (ptr - dnssl->domains); + (ptr - dnssl->domains); strncpy((char *)ptr, c->dns_search[i].n, len); for (dot = (char *)ptr - 1; *dot; dot++) { @@ -343,11 +324,50 @@ int ndp(const struct ctx *c, const struct icmp6hdr *ih, memset(ptr, 0, 8 - dns_s_len % 8); /* padding */ ptr += 8 - dns_s_len % 8; } + } -dns_done: - memcpy(&ra.source_ll.mac, c->our_tap_mac, ETH_ALEN); + memcpy(&ra.source_ll.mac, c->our_tap_mac, ETH_ALEN); - ndp_send(c, saddr, &ra, ptr - (unsigned char *)&ra); + ndp_send(c, dst, &ra, ptr - (unsigned char *)&ra); +} + +/** + * ndp() - Check for NDP solicitations, reply as needed + * @c: Execution context + * @ih: ICMPv6 header + * @saddr: Source IPv6 address + * @p: Packet pool + * + * Return: 0 if not handled here, 1 if handled, -1 on failure + */ +int ndp(const struct ctx *c, const struct icmp6hdr *ih, + const struct in6_addr *saddr, const struct pool *p) +{ + if (ih->icmp6_type < RS || ih->icmp6_type > NA) + return 0; + + if (c->no_ndp) + return 1; + + if (ih->icmp6_type == NS) { + const struct ndp_ns *ns = + packet_get(p, 0, 0, sizeof(struct ndp_ns), NULL); + + if (!ns) + return -1; + + if (IN6_IS_ADDR_UNSPECIFIED(saddr)) + return 1; + + info("NDP: received NS, sending NA"); + + ndp_na(c, saddr, &ns->target_addr); + } else if (ih->icmp6_type == RS) { + if (c->no_ra) + return 1; + + info("NDP: received RS, sending RA"); + ndp_ra(c, saddr); } return 1; -- 2.47.0