git: abb8b02550c3 - main - icmp6: make icmp6_notify_error() more readable

From: Gleb Smirnoff <glebius_at_FreeBSD.org>
Date: Thu, 22 Oct 2026 03:31:27 UTC
The branch main has been updated by glebius:

URL: https://cgit.FreeBSD.org/src/commit/?id=abb8b02550c3313d846c15167755f699388a4731

commit abb8b02550c3313d846c15167755f699388a4731
Author:     Gleb Smirnoff <glebius@FreeBSD.org>
AuthorDate: 2026-10-21 20:49:17 +0000
Commit:     Gleb Smirnoff <glebius@FreeBSD.org>
CommitDate: 2026-10-22 03:29:37 +0000

    icmp6: make icmp6_notify_error() more readable
    
    Remove a level of indentation, improve line breaks, remove single use
    variables.  No functional change.
---
 sys/netinet6/icmp6.c | 291 ++++++++++++++++++++++++---------------------------
 1 file changed, 139 insertions(+), 152 deletions(-)

diff --git a/sys/netinet6/icmp6.c b/sys/netinet6/icmp6.c
index f171af3fa5ef..0958b21de404 100644
--- a/sys/netinet6/icmp6.c
+++ b/sys/netinet6/icmp6.c
@@ -891,11 +891,17 @@ icmp6_input(struct mbuf **mp, int *offp, int proto)
 static int
 icmp6_notify_error(struct mbuf **mp, int off, int icmp6len)
 {
+	struct sockaddr_in6 icmp6src, icmp6dst;
+	struct ip6ctlparam ip6cp;
 	struct mbuf *m;
 	struct icmp6_hdr *icmp6;
 	struct ip6_hdr *eip6;
-	u_int32_t notifymtu;
-	struct sockaddr_in6 icmp6src, icmp6dst;
+	struct ip6_frag *fh;
+	struct ip6_rthdr *rth;
+	struct ip6_rthdr0 *rth0;
+	uint32_t notifymtu;
+	int eoff, rthlen;
+	uint8_t nxt;
 
 	m = *mp;
 	*mp = NULL;	/* Consumed in most cases. */
@@ -915,171 +921,152 @@ icmp6_notify_error(struct mbuf **mp, int off, int icmp6len)
 	bzero(&icmp6dst, sizeof(icmp6dst));
 
 	/* Detect the upper level protocol */
-	{
-		u_int8_t nxt = eip6->ip6_nxt;
-		int eoff = off + sizeof(struct icmp6_hdr) +
-		    sizeof(struct ip6_hdr);
-		struct ip6ctlparam ip6cp;
-		int icmp6type = icmp6->icmp6_type;
-		struct ip6_frag *fh;
-		struct ip6_rthdr *rth;
-		struct ip6_rthdr0 *rth0;
-		int rthlen;
-
-		while (1) { /* XXX: should avoid infinite loop explicitly? */
-			struct ip6_ext *eh;
-
-			switch (nxt) {
-			case IPPROTO_HOPOPTS:
-			case IPPROTO_DSTOPTS:
-			case IPPROTO_AH:
-				if ((m = m_pullup(m, eoff +
-				    sizeof(struct ip6_ext))) == NULL) {
-					IP6STAT_INC(ip6s_exthdrtoolong);
-					return (-1);
-				}
-				eh = (struct ip6_ext *)
-				    (mtod(m, char *) + eoff);
-				if (nxt == IPPROTO_AH)
-					eoff += (eh->ip6e_len + 2) << 2;
-				else
-					eoff += (eh->ip6e_len + 1) << 3;
-				nxt = eh->ip6e_nxt;
-				break;
-			case IPPROTO_ROUTING:
-				/*
-				 * When the erroneous packet contains a
-				 * routing header, we should examine the
-				 * header to determine the final destination.
-				 * Otherwise, we can't properly update
-				 * information that depends on the final
-				 * destination (e.g. path MTU).
-				 */
-				if ((m = m_pullup(m, eoff + sizeof(*rth))) ==
-				    NULL) {
+	nxt = eip6->ip6_nxt;
+	eoff = off + sizeof(struct icmp6_hdr) + sizeof(struct ip6_hdr);
+
+	while (1) { /* XXX: should avoid infinite loop explicitly? */
+		struct ip6_ext *eh;
+
+		switch (nxt) {
+		case IPPROTO_HOPOPTS:
+		case IPPROTO_DSTOPTS:
+		case IPPROTO_AH:
+			if ((m = m_pullup(m, eoff +
+			    sizeof(struct ip6_ext))) == NULL) {
+				IP6STAT_INC(ip6s_exthdrtoolong);
+				return (-1);
+			}
+			eh = (struct ip6_ext *)(mtod(m, char *) + eoff);
+			if (nxt == IPPROTO_AH)
+				eoff += (eh->ip6e_len + 2) << 2;
+			else
+				eoff += (eh->ip6e_len + 1) << 3;
+			nxt = eh->ip6e_nxt;
+			break;
+		case IPPROTO_ROUTING:
+			/*
+			 * When the erroneous packet contains a routing header,
+			 * we should examine the header to determine the final
+			 * destination.  Otherwise, we can't properly update
+			 * information that depends on the final destination
+			 * (e.g. path MTU).
+			 */
+			if ((m = m_pullup(m, eoff + sizeof(*rth))) == NULL) {
+				IP6STAT_INC(ip6s_exthdrtoolong);
+				return (-1);
+			}
+			rth = (struct ip6_rthdr *)(mtod(m, char *) + eoff);
+			rthlen = (rth->ip6r_len + 1) << 3;
+			/*
+			 * XXX: currently there is no officially defined type
+			 * other than type-0.  Note that if the segment left
+			 * field is 0, all intermediate hops must have been
+			 * passed.
+			 */
+			if (rth->ip6r_segleft &&
+			    rth->ip6r_type == IPV6_RTHDR_TYPE_0) {
+				int hops;
+
+				if ((m = m_pullup(m, eoff + rthlen)) == NULL) {
 					IP6STAT_INC(ip6s_exthdrtoolong);
 					return (-1);
 				}
-				rth = (struct ip6_rthdr *)
+				rth0 = (struct ip6_rthdr0 *)
 				    (mtod(m, char *) + eoff);
-				rthlen = (rth->ip6r_len + 1) << 3;
-				/*
-				 * XXX: currently there is no
-				 * officially defined type other
-				 * than type-0.
-				 * Note that if the segment left field
-				 * is 0, all intermediate hops must
-				 * have been passed.
-				 */
-				if (rth->ip6r_segleft &&
-				    rth->ip6r_type == IPV6_RTHDR_TYPE_0) {
-					int hops;
-
-					if ((m = m_pullup(m, eoff + rthlen)) ==
-					    NULL) {
-						IP6STAT_INC(ip6s_exthdrtoolong);
-						return (-1);
-					}
-					rth0 = (struct ip6_rthdr0 *)
-					    (mtod(m, char *) + eoff);
-
-					/* just ignore a bogus header */
-					if ((rth0->ip6r0_len % 2) == 0 &&
-					    (hops = rth0->ip6r0_len/2))
-						icmp6dst.sin6_addr = *((struct in6_addr *)(rth0 + 1) + (hops - 1));
-				}
-				eoff += rthlen;
-				nxt = rth->ip6r_nxt;
-				break;
-			case IPPROTO_FRAGMENT:
-				if ((m = m_pullup(m, eoff +
-				    sizeof(struct ip6_frag))) == NULL) {
-					IP6STAT_INC(ip6s_exthdrtoolong);
-					return (-1);
-				}
-				fh = (struct ip6_frag *)(mtod(m, char *) +
-				    eoff);
-				/*
-				 * Data after a fragment header is meaningless
-				 * unless it is the first fragment, but
-				 * we'll go to the notify label for path MTU
-				 * discovery.
-				 */
-				if (fh->ip6f_offlg & IP6F_OFF_MASK)
-					goto notify;
 
-				eoff += sizeof(struct ip6_frag);
-				nxt = fh->ip6f_nxt;
-				break;
-			default:
-				/*
-				 * This case includes ESP and the No Next
-				 * Header.  In such cases going to the notify
-				 * label does not have any meaning
-				 * (i.e. ctlfunc will be NULL), but we go
-				 * anyway since we might have to update
-				 * path MTU information.
-				 */
-				goto notify;
+				/* just ignore a bogus header */
+				if ((rth0->ip6r0_len % 2) == 0 &&
+				    (hops = rth0->ip6r0_len/2))
+					icmp6dst.sin6_addr = *((struct in6_addr *)(rth0 + 1) + (hops - 1));
+			}
+			eoff += rthlen;
+			nxt = rth->ip6r_nxt;
+			break;
+		case IPPROTO_FRAGMENT:
+			if ((m = m_pullup(m, eoff +
+			    sizeof(struct ip6_frag))) == NULL) {
+				IP6STAT_INC(ip6s_exthdrtoolong);
+				return (-1);
 			}
+			fh = (struct ip6_frag *)(mtod(m, char *) + eoff);
+			/*
+			 * Data after a fragment header is meaningless unless
+			 * it is the first fragment, but we'll go to the notify
+			 * label for path MTU discovery.
+			 */
+			if (fh->ip6f_offlg & IP6F_OFF_MASK)
+				goto notify;
+
+			eoff += sizeof(struct ip6_frag);
+			nxt = fh->ip6f_nxt;
+			break;
+		default:
+			/*
+			 * This case includes ESP and the No Next Header.  In
+			 * such cases going to the notify label does not have
+			 * any meaning (i.e. ctlfunc will be NULL), but we go
+			 * anyway since we might have to update path MTU
+			 * information.
+			 */
+			goto notify;
 		}
-	  notify:
-		icmp6 = (struct icmp6_hdr *)(mtod(m, char *) + off);
+	}
 
-		/*
-		 * retrieve parameters from the inner IPv6 header, and convert
-		 * them into sockaddr structures.
-		 * XXX: there is no guarantee that the source or destination
-		 * addresses of the inner packet are in the same scope as
-		 * the addresses of the icmp packet.  But there is no other
-		 * way to determine the zone.
-		 */
-		eip6 = (struct ip6_hdr *)(icmp6 + 1);
+notify:
+	icmp6 = (struct icmp6_hdr *)(mtod(m, char *) + off);
 
-		/*
-		 * Protocol layers can't do anything useful with unspecified
-		 * addresses.
-		 */
-		if (IN6_IS_ADDR_UNSPECIFIED(&eip6->ip6_src) ||
-		    IN6_IS_ADDR_UNSPECIFIED(&eip6->ip6_dst))
-			goto freeit;
+	/*
+	 * Retrieve parameters from the inner IPv6 header, and convert them
+	 * into sockaddr structures.
+	 * XXX: there is no guarantee that the source or destination addresses
+	 * of the inner packet are in the same scope as the addresses of the
+	 * icmp packet.  But there is no other way to determine the zone.
+	 */
+	eip6 = (struct ip6_hdr *)(icmp6 + 1);
 
-		icmp6dst.sin6_len = sizeof(struct sockaddr_in6);
-		icmp6dst.sin6_family = AF_INET6;
-		if (IN6_IS_ADDR_UNSPECIFIED(&icmp6dst.sin6_addr))
-			icmp6dst.sin6_addr = eip6->ip6_dst;
-		if (in6_setscope(&icmp6dst.sin6_addr, m->m_pkthdr.rcvif, NULL))
-			goto freeit;
-		bzero(&icmp6src, sizeof(icmp6src));
-		icmp6src.sin6_len = sizeof(struct sockaddr_in6);
-		icmp6src.sin6_family = AF_INET6;
-		icmp6src.sin6_addr = eip6->ip6_src;
-		if (in6_setscope(&icmp6src.sin6_addr, m->m_pkthdr.rcvif, NULL))
-			goto freeit;
-		icmp6src.sin6_flowinfo =
-		    (eip6->ip6_flow & IPV6_FLOWLABEL_MASK);
-
-		ip6cp.ip6c_m = m;
-		ip6cp.ip6c_icmp6 = icmp6;
-		ip6cp.ip6c_ip6 = (struct ip6_hdr *)(icmp6 + 1);
-		ip6cp.ip6c_off = eoff;
-		ip6cp.ip6c_finaldst = &icmp6dst;
-		ip6cp.ip6c_src = &icmp6src;
-		ip6cp.ip6c_nxt = nxt;
-
-		if (icmp6type == ICMP6_PACKET_TOO_BIG) {
-			notifymtu = ntohl(icmp6->icmp6_mtu);
-			ip6cp.ip6c_cmdarg = (void *)&notifymtu;
-			icmp6_mtudisc_update(&ip6cp);
-		}
+	/*
+	 * Protocol layers can't do anything useful with unspecified addresses.
+	 */
+	if (IN6_IS_ADDR_UNSPECIFIED(&eip6->ip6_src) ||
+	    IN6_IS_ADDR_UNSPECIFIED(&eip6->ip6_dst))
+		goto freeit;
 
-		if (ip6_ctlprotox[nxt] != NULL)
-			ip6_ctlprotox[nxt](&ip6cp);
+	icmp6dst.sin6_len = sizeof(struct sockaddr_in6);
+	icmp6dst.sin6_family = AF_INET6;
+	if (IN6_IS_ADDR_UNSPECIFIED(&icmp6dst.sin6_addr))
+		icmp6dst.sin6_addr = eip6->ip6_dst;
+	if (in6_setscope(&icmp6dst.sin6_addr, m->m_pkthdr.rcvif, NULL))
+		goto freeit;
+	bzero(&icmp6src, sizeof(icmp6src));
+	icmp6src.sin6_len = sizeof(struct sockaddr_in6);
+	icmp6src.sin6_family = AF_INET6;
+	icmp6src.sin6_addr = eip6->ip6_src;
+	if (in6_setscope(&icmp6src.sin6_addr, m->m_pkthdr.rcvif, NULL))
+		goto freeit;
+	icmp6src.sin6_flowinfo =
+	    (eip6->ip6_flow & IPV6_FLOWLABEL_MASK);
+
+	ip6cp.ip6c_m = m;
+	ip6cp.ip6c_icmp6 = icmp6;
+	ip6cp.ip6c_ip6 = (struct ip6_hdr *)(icmp6 + 1);
+	ip6cp.ip6c_off = eoff;
+	ip6cp.ip6c_finaldst = &icmp6dst;
+	ip6cp.ip6c_src = &icmp6src;
+	ip6cp.ip6c_nxt = nxt;
+
+	if (icmp6->icmp6_type == ICMP6_PACKET_TOO_BIG) {
+		notifymtu = ntohl(icmp6->icmp6_mtu);
+		ip6cp.ip6c_cmdarg = (void *)&notifymtu;
+		icmp6_mtudisc_update(&ip6cp);
 	}
+
+	if (ip6_ctlprotox[nxt] != NULL)
+		ip6_ctlprotox[nxt](&ip6cp);
+
 	*mp = m;
 	return (0);
 
-  freeit:
+freeit:
 	m_freem(m);
 	return (-1);
 }