Hi,

ip_fragment() and ip6_fragment() do nearly the same thing, but they
are implemented differently.

The idea of this diff is to move things around.  Then only differences
from the IP standards but not in coding style remain.  This allows
to compare both functions easily.

In IPv4 assume that m_pkthdr is correct and take the length from
the, like in IPv6.

ok?

bluhm

Index: netinet/ip_output.c
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/sys/netinet/ip_output.c,v
retrieving revision 1.381
diff -u -p -r1.381 ip_output.c
--- netinet/ip_output.c 25 May 2022 19:48:46 -0000      1.381
+++ netinet/ip_output.c 11 Aug 2022 07:33:20 -0000
@@ -677,73 +677,78 @@ ip_output_ipsec_send(struct tdb *tdb, st
 #endif /* IPSEC */
 
 int
-ip_fragment(struct mbuf *m, struct mbuf_list *fml, struct ifnet *ifp,
+ip_fragment(struct mbuf *m0, struct mbuf_list *fml, struct ifnet *ifp,
     u_long mtu)
 {
-       struct ip *ip, *mhip;
-       struct mbuf *m0;
-       int len, hlen, off;
-       int mhlen, firstlen;
+       struct mbuf *m;
+       struct ip *ip;
+       int firstlen, hlen, tlen, len, off;
        int error;
 
        ml_init(fml);
-       ml_enqueue(fml, m);
+       ml_enqueue(fml, m0);
 
-       ip = mtod(m, struct ip *);
+       ip = mtod(m0, struct ip *);
        hlen = ip->ip_hl << 2;
+       tlen = m0->m_pkthdr.len;
        len = (mtu - hlen) &~ 7;
        if (len < 8) {
                error = EMSGSIZE;
                goto bad;
        }
+       firstlen = len;
 
        /*
         * If we are doing fragmentation, we can't defer TCP/UDP
         * checksumming; compute the checksum and clear the flag.
         */
-       in_proto_cksum_out(m, NULL);
-       firstlen = len;
+       in_proto_cksum_out(m0, NULL);
 
        /*
         * Loop through length of segment after first fragment,
         * make new header and copy data of each part and link onto chain.
         */
-       m0 = m;
-       mhlen = sizeof (struct ip);
-       for (off = hlen + len; off < ntohs(ip->ip_len); off += len) {
+       for (off = hlen + firstlen; off < tlen; off += len) {
+               struct ip *mhip;
+               int mhlen;
+
                MGETHDR(m, M_DONTWAIT, MT_HEADER);
                if (m == NULL) {
                        error = ENOBUFS;
                        goto bad;
                }
                ml_enqueue(fml, m);
+
                if ((error = m_dup_pkthdr(m, m0, M_DONTWAIT)) != 0)
                        goto bad;
                m->m_data += max_linkhdr;
                mhip = mtod(m, struct ip *);
                *mhip = *ip;
-               if (hlen > sizeof (struct ip)) {
-                       mhlen = ip_optcopy(ip, mhip) + sizeof (struct ip);
+               if (hlen > sizeof(struct ip)) {
+                       mhlen = ip_optcopy(ip, mhip) + sizeof(struct ip);
                        mhip->ip_hl = mhlen >> 2;
-               }
+               } else
+                       mhlen = sizeof(struct ip);
                m->m_len = mhlen;
+
                mhip->ip_off = ((off - hlen) >> 3) +
                    (ntohs(ip->ip_off) & ~IP_MF);
                if (ip->ip_off & htons(IP_MF))
                        mhip->ip_off |= IP_MF;
-               if (off + len >= ntohs(ip->ip_len))
-                       len = ntohs(ip->ip_len) - off;
+               if (off + len >= tlen)
+                       len = tlen - off;
                else
                        mhip->ip_off |= IP_MF;
-               mhip->ip_len = htons((u_int16_t)(len + mhlen));
+               mhip->ip_off = htons(mhip->ip_off);
+
+               m->m_pkthdr.len = mhlen + len;
+               mhip->ip_len = htons(m->m_pkthdr.len);
                m->m_next = m_copym(m0, off, len, M_NOWAIT);
                if (m->m_next == NULL) {
                        error = ENOBUFS;
                        goto bad;
                }
-               m->m_pkthdr.len = mhlen + len;
-               m->m_pkthdr.ph_ifidx = 0;
-               mhip->ip_off = htons((u_int16_t)mhip->ip_off);
+
                mhip->ip_sum = 0;
                if (in_ifcap_cksum(m, ifp, IFCAP_CSUM_IPv4))
                        m->m_pkthdr.csum_flags |= M_IPV4_CSUM_OUT;
@@ -752,15 +757,16 @@ ip_fragment(struct mbuf *m, struct mbuf_
                        mhip->ip_sum = in_cksum(m, mhlen);
                }
        }
+
        /*
         * Update first fragment by trimming what's been copied out
         * and updating header, then send each fragment (in order).
         */
        m = m0;
-       m_adj(m, hlen + firstlen - ntohs(ip->ip_len));
-       m->m_pkthdr.len = hlen + firstlen;
-       ip->ip_len = htons((u_int16_t)m->m_pkthdr.len);
+       m_adj(m, hlen + firstlen - tlen);
        ip->ip_off |= htons(IP_MF);
+       ip->ip_len = htons(m->m_pkthdr.len);
+
        ip->ip_sum = 0;
        if (in_ifcap_cksum(m, ifp, IFCAP_CSUM_IPv4))
                m->m_pkthdr.csum_flags |= M_IPV4_CSUM_OUT;
Index: netinet6/ip6_output.c
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/sys/netinet6/ip6_output.c,v
retrieving revision 1.270
diff -u -p -r1.270 ip6_output.c
--- netinet6/ip6_output.c       8 Aug 2022 23:00:51 -0000       1.270
+++ netinet6/ip6_output.c       11 Aug 2022 07:33:20 -0000
@@ -793,30 +793,31 @@ int
 ip6_fragment(struct mbuf *m0, struct mbuf_list *fml, int hlen,
     u_char nextproto, u_long mtu)
 {
-       struct mbuf     *m, *m_frgpart;
-       struct ip6_hdr  *mhip6;
-       struct ip6_frag *ip6f;
-       u_int32_t        id;
-       int              tlen, len, off;
-       int              error;
+       struct mbuf *m;
+       struct ip6_hdr *ip6;
+       u_int32_t id;
+       int tlen, len, off;
+       int error;
 
        ml_init(fml);
 
+       ip6 = mtod(m0, struct ip6_hdr *);
        tlen = m0->m_pkthdr.len;
        len = (mtu - hlen - sizeof(struct ip6_frag)) & ~7;
        if (len < 8) {
                error = EMSGSIZE;
                goto bad;
        }
-
        id = htonl(ip6_randomid());
 
        /*
-        * Loop through length of segment after first fragment,
+        * Loop through length of segment,
         * make new header and copy data of each part and link onto chain.
         */
        for (off = hlen; off < tlen; off += len) {
                struct mbuf *mlast;
+               struct ip6_hdr *mhip6;
+               struct ip6_frag *ip6f;
 
                MGETHDR(m, M_DONTWAIT, MT_HEADER);
                if (m == NULL) {
@@ -824,29 +825,33 @@ ip6_fragment(struct mbuf *m0, struct mbu
                        goto bad;
                }
                ml_enqueue(fml, m);
+
                if ((error = m_dup_pkthdr(m, m0, M_DONTWAIT)) != 0)
                        goto bad;
                m->m_data += max_linkhdr;
                mhip6 = mtod(m, struct ip6_hdr *);
-               *mhip6 = *mtod(m0, struct ip6_hdr *);
-               m->m_len = sizeof(*mhip6);
+               *mhip6 = *ip6;
+               m->m_len = sizeof(struct ip6_hdr);
+
                if ((error = ip6_insertfraghdr(m0, m, hlen, &ip6f)) != 0)
                        goto bad;
-               ip6f->ip6f_offlg = htons((u_int16_t)((off - hlen) & ~7));
+               ip6f->ip6f_offlg = htons((off - hlen) & ~7);
                if (off + len >= tlen)
                        len = tlen - off;
                else
                        ip6f->ip6f_offlg |= IP6F_MORE_FRAG;
-               mhip6->ip6_plen = htons((u_int16_t)(len + hlen +
-                   sizeof(*ip6f) - sizeof(struct ip6_hdr)));
-               if ((m_frgpart = m_copym(m0, off, len, M_DONTWAIT)) == NULL) {
+
+               m->m_pkthdr.len = hlen + sizeof(struct ip6_frag) + len;
+               mhip6->ip6_plen = htons(m->m_pkthdr.len -
+                   sizeof(struct ip6_hdr));
+               for (mlast = m; mlast->m_next; mlast = mlast->m_next)
+                       ;
+               mlast->m_next = m_copym(m0, off, len, M_DONTWAIT);
+               if (mlast->m_next == NULL) {
                        error = ENOBUFS;
                        goto bad;
                }
-               for (mlast = m; mlast->m_next; mlast = mlast->m_next)
-                       ;
-               mlast->m_next = m_frgpart;
-               m->m_pkthdr.len = len + hlen + sizeof(*ip6f);
+
                ip6f->ip6f_reserved = 0;
                ip6f->ip6f_ident = id;
                ip6f->ip6f_nxt = nextproto;

Reply via email to