From 0541ad29664165bece2a7957d02a188f9bafb73b Mon Sep 17 00:00:00 2001 From: bluhm Date: Thu, 28 Jul 2022 22:05:39 +0000 Subject: [PATCH] Checking the fragment flags of an incoming IP packet does not need the mutex for the fragment list. Move this code before the critical section. Use ISSET() to make clear which flags are checked. OK mvs@ --- sys/netinet/ip_input.c | 39 ++++++++++++++++++++------------------- 1 file changed, 20 insertions(+), 19 deletions(-) diff --git a/sys/netinet/ip_input.c b/sys/netinet/ip_input.c index 8ec2807459d..91765d2bab3 100644 --- a/sys/netinet/ip_input.c +++ b/sys/netinet/ip_input.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ip_input.c,v 1.374 2022/07/25 23:19:34 bluhm Exp $ */ +/* $OpenBSD: ip_input.c,v 1.375 2022/07/28 22:05:39 bluhm Exp $ */ /* $NetBSD: ip_input.c,v 1.30 1996/03/16 23:53:58 christos Exp $ */ /* @@ -583,13 +583,13 @@ ip_fragcheck(struct mbuf **mp, int *offp) hlen = ip->ip_hl << 2; /* - * If offset or IP_MF are set, must reassemble. + * If offset or more fragments are set, must reassemble. * Otherwise, nothing need be done. * (We could look in the reassembly queue to see * if the packet was previously fragmented, * but it's not worth the time; just let them time out.) */ - if (ip->ip_off &~ htons(IP_DF | IP_RF)) { + if (ISSET(ip->ip_off, htons(IP_OFFMASK | IP_MF))) { if ((*mp)->m_flags & M_EXT) { /* XXX */ if ((*mp = m_pullup(*mp, hlen)) == NULL) { ipstat_inc(ips_toosmall); @@ -598,27 +598,13 @@ ip_fragcheck(struct mbuf **mp, int *offp) ip = mtod(*mp, struct ip *); } - mtx_enter(&ipq_mutex); - - /* - * Look for queue of fragments - * of this datagram. - */ - LIST_FOREACH(fp, &ipq, ipq_q) { - if (ip->ip_id == fp->ipq_id && - ip->ip_src.s_addr == fp->ipq_src.s_addr && - ip->ip_dst.s_addr == fp->ipq_dst.s_addr && - ip->ip_p == fp->ipq_p) - break; - } - /* * Adjust ip_len to not reflect header, * set ipqe_mff if more fragments are expected, * convert offset of this to bytes. */ ip->ip_len = htons(ntohs(ip->ip_len) - hlen); - mff = (ip->ip_off & htons(IP_MF)) != 0; + mff = ISSET(ip->ip_off, htons(IP_MF)); if (mff) { /* * Make sure that fragments have a data length @@ -627,11 +613,26 @@ ip_fragcheck(struct mbuf **mp, int *offp) if (ntohs(ip->ip_len) == 0 || (ntohs(ip->ip_len) & 0x7) != 0) { ipstat_inc(ips_badfrags); - goto bad; + m_freemp(mp); + return IPPROTO_DONE; } } ip->ip_off = htons(ntohs(ip->ip_off) << 3); + mtx_enter(&ipq_mutex); + + /* + * Look for queue of fragments + * of this datagram. + */ + LIST_FOREACH(fp, &ipq, ipq_q) { + if (ip->ip_id == fp->ipq_id && + ip->ip_src.s_addr == fp->ipq_src.s_addr && + ip->ip_dst.s_addr == fp->ipq_dst.s_addr && + ip->ip_p == fp->ipq_p) + break; + } + /* * If datagram marked as having more fragments * or if this is not the first fragment, -- 2.20.1