Home | History | Annotate | Line # | Download | only in netipsec
ipsec_mbuf.c revision 1.5.6.1
      1  1.5.6.1      kent /*	$NetBSD: ipsec_mbuf.c,v 1.5.6.1 2005/04/29 11:29:34 kent Exp $	*/
      2      1.4   thorpej /*-
      3      1.4   thorpej  * Copyright (c) 2002, 2003 Sam Leffler, Errno Consulting
      4      1.4   thorpej  * All rights reserved.
      5      1.4   thorpej  *
      6      1.4   thorpej  * Redistribution and use in source and binary forms, with or without
      7      1.4   thorpej  * modification, are permitted provided that the following conditions
      8      1.4   thorpej  * are met:
      9      1.4   thorpej  * 1. Redistributions of source code must retain the above copyright
     10      1.4   thorpej  *    notice, this list of conditions and the following disclaimer.
     11      1.4   thorpej  * 2. Redistributions in binary form must reproduce the above copyright
     12      1.4   thorpej  *    notice, this list of conditions and the following disclaimer in the
     13      1.4   thorpej  *    documentation and/or other materials provided with the distribution.
     14      1.4   thorpej  *
     15      1.4   thorpej  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
     16      1.4   thorpej  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     17      1.4   thorpej  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     18      1.4   thorpej  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
     19      1.4   thorpej  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     20      1.4   thorpej  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     21      1.4   thorpej  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     22      1.4   thorpej  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     23      1.4   thorpej  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     24      1.4   thorpej  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     25      1.4   thorpej  * SUCH DAMAGE.
     26      1.4   thorpej  *
     27      1.4   thorpej  * $FreeBSD: /repoman/r/ncvs/src/sys/netipsec/ipsec_mbuf.c,v 1.5.2.2 2003/03/28 20:32:53 sam Exp $
     28      1.4   thorpej  */
     29      1.1  jonathan 
     30      1.1  jonathan #include <sys/cdefs.h>
     31  1.5.6.1      kent __KERNEL_RCSID(0, "$NetBSD: ipsec_mbuf.c,v 1.5.6.1 2005/04/29 11:29:34 kent Exp $");
     32      1.1  jonathan 
     33      1.1  jonathan /*
     34      1.1  jonathan  * IPsec-specific mbuf routines.
     35      1.1  jonathan  */
     36      1.1  jonathan 
     37      1.3  jonathan #ifdef __FreeBSD__
     38      1.1  jonathan #include "opt_param.h"
     39      1.3  jonathan #endif
     40      1.1  jonathan 
     41      1.1  jonathan #include <sys/param.h>
     42      1.1  jonathan #include <sys/systm.h>
     43      1.1  jonathan #include <sys/mbuf.h>
     44      1.1  jonathan #include <sys/socket.h>
     45      1.1  jonathan 
     46      1.1  jonathan #include <net/route.h>
     47      1.1  jonathan #include <netinet/in.h>
     48      1.1  jonathan 
     49      1.1  jonathan #include <netipsec/ipsec.h>
     50      1.5  jonathan #include <netipsec/ipsec_var.h>
     51      1.1  jonathan 
     52      1.1  jonathan #include <netipsec/ipsec_osdep.h>
     53      1.1  jonathan #include <net/net_osdep.h>
     54      1.1  jonathan 
     55      1.1  jonathan extern	struct mbuf *m_getptr(struct mbuf *, int, int *);
     56      1.1  jonathan 
     57      1.1  jonathan /*
     58      1.1  jonathan  * Create a writable copy of the mbuf chain.  While doing this
     59      1.1  jonathan  * we compact the chain with a goal of producing a chain with
     60      1.1  jonathan  * at most two mbufs.  The second mbuf in this chain is likely
     61      1.1  jonathan  * to be a cluster.  The primary purpose of this work is to create
     62      1.1  jonathan  * a writable packet for encryption, compression, etc.  The
     63      1.1  jonathan  * secondary goal is to linearize the data so the data can be
     64      1.1  jonathan  * passed to crypto hardware in the most efficient manner possible.
     65      1.1  jonathan  */
     66      1.1  jonathan struct mbuf *
     67      1.1  jonathan m_clone(struct mbuf *m0)
     68      1.1  jonathan {
     69      1.1  jonathan 	struct mbuf *m, *mprev;
     70      1.1  jonathan 	struct mbuf *n, *mfirst, *mlast;
     71      1.1  jonathan 	int len, off;
     72      1.1  jonathan 
     73      1.1  jonathan 	IPSEC_ASSERT(m0 != NULL, ("m_clone: null mbuf"));
     74      1.1  jonathan 
     75      1.1  jonathan 	mprev = NULL;
     76      1.1  jonathan 	for (m = m0; m != NULL; m = mprev->m_next) {
     77      1.1  jonathan 		/*
     78      1.1  jonathan 		 * Regular mbufs are ignored unless there's a cluster
     79      1.1  jonathan 		 * in front of it that we can use to coalesce.  We do
     80      1.1  jonathan 		 * the latter mainly so later clusters can be coalesced
     81      1.1  jonathan 		 * also w/o having to handle them specially (i.e. convert
     82      1.1  jonathan 		 * mbuf+cluster -> cluster).  This optimization is heavily
     83      1.1  jonathan 		 * influenced by the assumption that we're running over
     84      1.1  jonathan 		 * Ethernet where MCLBYTES is large enough that the max
     85      1.1  jonathan 		 * packet size will permit lots of coalescing into a
     86      1.1  jonathan 		 * single cluster.  This in turn permits efficient
     87      1.1  jonathan 		 * crypto operations, especially when using hardware.
     88      1.1  jonathan 		 */
     89      1.1  jonathan 		if ((m->m_flags & M_EXT) == 0) {
     90      1.1  jonathan 			if (mprev && (mprev->m_flags & M_EXT) &&
     91      1.1  jonathan 			    m->m_len <= M_TRAILINGSPACE(mprev)) {
     92      1.1  jonathan 				/* XXX: this ignores mbuf types */
     93      1.1  jonathan 				memcpy(mtod(mprev, caddr_t) + mprev->m_len,
     94      1.1  jonathan 				       mtod(m, caddr_t), m->m_len);
     95      1.1  jonathan 				mprev->m_len += m->m_len;
     96      1.1  jonathan 				mprev->m_next = m->m_next;	/* unlink from chain */
     97      1.1  jonathan 				m_free(m);			/* reclaim mbuf */
     98      1.1  jonathan 				newipsecstat.ips_mbcoalesced++;
     99      1.1  jonathan 			} else {
    100      1.1  jonathan 				mprev = m;
    101      1.1  jonathan 			}
    102      1.1  jonathan 			continue;
    103      1.1  jonathan 		}
    104      1.1  jonathan 		/*
    105      1.1  jonathan 		 * Writable mbufs are left alone (for now).  Note
    106      1.1  jonathan 		 * that for 4.x systems it's not possible to identify
    107      1.1  jonathan 		 * whether or not mbufs with external buffers are
    108      1.1  jonathan 		 * writable unless they use clusters.
    109      1.1  jonathan 		 */
    110      1.1  jonathan 		if (M_EXT_WRITABLE(m)) {
    111      1.1  jonathan 			mprev = m;
    112      1.1  jonathan 			continue;
    113      1.1  jonathan 		}
    114      1.1  jonathan 
    115      1.1  jonathan 		/*
    116      1.1  jonathan 		 * Not writable, replace with a copy or coalesce with
    117      1.1  jonathan 		 * the previous mbuf if possible (since we have to copy
    118      1.1  jonathan 		 * it anyway, we try to reduce the number of mbufs and
    119      1.1  jonathan 		 * clusters so that future work is easier).
    120      1.1  jonathan 		 */
    121      1.1  jonathan 		IPSEC_ASSERT(m->m_flags & M_EXT,
    122      1.1  jonathan 			("m_clone: m_flags 0x%x", m->m_flags));
    123      1.1  jonathan 		/* NB: we only coalesce into a cluster or larger */
    124      1.1  jonathan 		if (mprev != NULL && (mprev->m_flags & M_EXT) &&
    125      1.1  jonathan 		    m->m_len <= M_TRAILINGSPACE(mprev)) {
    126      1.1  jonathan 			/* XXX: this ignores mbuf types */
    127      1.1  jonathan 			memcpy(mtod(mprev, caddr_t) + mprev->m_len,
    128      1.1  jonathan 			       mtod(m, caddr_t), m->m_len);
    129      1.1  jonathan 			mprev->m_len += m->m_len;
    130      1.1  jonathan 			mprev->m_next = m->m_next;	/* unlink from chain */
    131      1.1  jonathan 			m_free(m);			/* reclaim mbuf */
    132      1.1  jonathan 			newipsecstat.ips_clcoalesced++;
    133      1.1  jonathan 			continue;
    134      1.1  jonathan 		}
    135      1.1  jonathan 
    136      1.1  jonathan 		/*
    137      1.1  jonathan 		 * Allocate new space to hold the copy...
    138      1.1  jonathan 		 */
    139      1.1  jonathan 		/* XXX why can M_PKTHDR be set past the first mbuf? */
    140      1.1  jonathan 		if (mprev == NULL && (m->m_flags & M_PKTHDR)) {
    141      1.1  jonathan 			/*
    142      1.1  jonathan 			 * NB: if a packet header is present we must
    143      1.1  jonathan 			 * allocate the mbuf separately from any cluster
    144      1.1  jonathan 			 * because M_MOVE_PKTHDR will smash the data
    145      1.1  jonathan 			 * pointer and drop the M_EXT marker.
    146      1.1  jonathan 			 */
    147      1.1  jonathan 			MGETHDR(n, M_DONTWAIT, m->m_type);
    148      1.1  jonathan 			if (n == NULL) {
    149      1.1  jonathan 				m_freem(m0);
    150      1.1  jonathan 				return (NULL);
    151      1.1  jonathan 			}
    152      1.1  jonathan 			M_MOVE_PKTHDR(n, m);
    153      1.1  jonathan 			MCLGET(n, M_DONTWAIT);
    154      1.1  jonathan 			if ((n->m_flags & M_EXT) == 0) {
    155      1.1  jonathan 				m_free(n);
    156      1.1  jonathan 				m_freem(m0);
    157      1.1  jonathan 				return (NULL);
    158      1.1  jonathan 			}
    159      1.1  jonathan 		} else {
    160      1.1  jonathan 			n = m_getcl(M_DONTWAIT, m->m_type, m->m_flags);
    161      1.1  jonathan 			if (n == NULL) {
    162      1.1  jonathan 				m_freem(m0);
    163      1.1  jonathan 				return (NULL);
    164      1.1  jonathan 			}
    165      1.1  jonathan 		}
    166      1.1  jonathan 		/*
    167      1.1  jonathan 		 * ... and copy the data.  We deal with jumbo mbufs
    168      1.1  jonathan 		 * (i.e. m_len > MCLBYTES) by splitting them into
    169      1.1  jonathan 		 * clusters.  We could just malloc a buffer and make
    170      1.1  jonathan 		 * it external but too many device drivers don't know
    171      1.1  jonathan 		 * how to break up the non-contiguous memory when
    172      1.1  jonathan 		 * doing DMA.
    173      1.1  jonathan 		 */
    174      1.1  jonathan 		len = m->m_len;
    175      1.1  jonathan 		off = 0;
    176      1.1  jonathan 		mfirst = n;
    177      1.1  jonathan 		mlast = NULL;
    178      1.1  jonathan 		for (;;) {
    179      1.1  jonathan 			int cc = min(len, MCLBYTES);
    180      1.1  jonathan 			memcpy(mtod(n, caddr_t), mtod(m, caddr_t) + off, cc);
    181      1.1  jonathan 			n->m_len = cc;
    182      1.1  jonathan 			if (mlast != NULL)
    183      1.1  jonathan 				mlast->m_next = n;
    184  1.5.6.1      kent 			mlast = n;
    185      1.1  jonathan 			newipsecstat.ips_clcopied++;
    186      1.1  jonathan 
    187      1.1  jonathan 			len -= cc;
    188      1.1  jonathan 			if (len <= 0)
    189      1.1  jonathan 				break;
    190      1.1  jonathan 			off += cc;
    191      1.1  jonathan 
    192      1.1  jonathan 			n = m_getcl(M_DONTWAIT, m->m_type, m->m_flags);
    193      1.1  jonathan 			if (n == NULL) {
    194      1.1  jonathan 				m_freem(mfirst);
    195      1.1  jonathan 				m_freem(m0);
    196      1.1  jonathan 				return (NULL);
    197      1.1  jonathan 			}
    198      1.1  jonathan 		}
    199  1.5.6.1      kent 		n->m_next = m->m_next;
    200      1.1  jonathan 		if (mprev == NULL)
    201      1.1  jonathan 			m0 = mfirst;		/* new head of chain */
    202      1.1  jonathan 		else
    203      1.1  jonathan 			mprev->m_next = mfirst;	/* replace old mbuf */
    204      1.1  jonathan 		m_free(m);			/* release old mbuf */
    205      1.1  jonathan 		mprev = mfirst;
    206      1.1  jonathan 	}
    207      1.1  jonathan 	return (m0);
    208      1.1  jonathan }
    209      1.1  jonathan 
    210      1.1  jonathan /*
    211      1.1  jonathan  * Make space for a new header of length hlen at skip bytes
    212      1.1  jonathan  * into the packet.  When doing this we allocate new mbufs only
    213      1.1  jonathan  * when absolutely necessary.  The mbuf where the new header
    214      1.1  jonathan  * is to go is returned together with an offset into the mbuf.
    215      1.1  jonathan  * If NULL is returned then the mbuf chain may have been modified;
    216      1.1  jonathan  * the caller is assumed to always free the chain.
    217      1.1  jonathan  */
    218      1.1  jonathan struct mbuf *
    219      1.1  jonathan m_makespace(struct mbuf *m0, int skip, int hlen, int *off)
    220      1.1  jonathan {
    221      1.1  jonathan 	struct mbuf *m;
    222      1.1  jonathan 	unsigned remain;
    223      1.1  jonathan 
    224      1.1  jonathan 	IPSEC_ASSERT(m0 != NULL, ("m_dmakespace: null mbuf"));
    225      1.1  jonathan 	IPSEC_ASSERT(hlen < MHLEN, ("m_makespace: hlen too big: %u", hlen));
    226      1.1  jonathan 
    227      1.1  jonathan 	for (m = m0; m && skip > m->m_len; m = m->m_next)
    228      1.1  jonathan 		skip -= m->m_len;
    229      1.1  jonathan 	if (m == NULL)
    230      1.1  jonathan 		return (NULL);
    231      1.1  jonathan 	/*
    232      1.1  jonathan 	 * At this point skip is the offset into the mbuf m
    233      1.1  jonathan 	 * where the new header should be placed.  Figure out
    234      1.1  jonathan 	 * if there's space to insert the new header.  If so,
    235      1.1  jonathan 	 * and copying the remainder makese sense then do so.
    236      1.1  jonathan 	 * Otherwise insert a new mbuf in the chain, splitting
    237      1.1  jonathan 	 * the contents of m as needed.
    238      1.1  jonathan 	 */
    239      1.1  jonathan 	remain = m->m_len - skip;		/* data to move */
    240      1.1  jonathan 	if (hlen > M_TRAILINGSPACE(m)) {
    241      1.1  jonathan 		struct mbuf *n;
    242      1.1  jonathan 
    243      1.1  jonathan 		/* XXX code doesn't handle clusters XXX */
    244      1.1  jonathan 		IPSEC_ASSERT(remain < MLEN,
    245      1.1  jonathan 			("m_makespace: remainder too big: %u", remain));
    246      1.1  jonathan 		/*
    247      1.1  jonathan 		 * Not enough space in m, split the contents
    248      1.1  jonathan 		 * of m, inserting new mbufs as required.
    249      1.1  jonathan 		 *
    250      1.1  jonathan 		 * NB: this ignores mbuf types.
    251      1.1  jonathan 		 */
    252      1.1  jonathan 		MGET(n, M_DONTWAIT, MT_DATA);
    253      1.1  jonathan 		if (n == NULL)
    254      1.1  jonathan 			return (NULL);
    255      1.1  jonathan 		n->m_next = m->m_next;		/* splice new mbuf */
    256      1.1  jonathan 		m->m_next = n;
    257      1.1  jonathan 		newipsecstat.ips_mbinserted++;
    258      1.1  jonathan 		if (hlen <= M_TRAILINGSPACE(m) + remain) {
    259      1.1  jonathan 			/*
    260      1.1  jonathan 			 * New header fits in the old mbuf if we copy
    261      1.1  jonathan 			 * the remainder; just do the copy to the new
    262      1.1  jonathan 			 * mbuf and we're good to go.
    263      1.1  jonathan 			 */
    264      1.1  jonathan 			memcpy(mtod(n, caddr_t),
    265      1.1  jonathan 			       mtod(m, caddr_t) + skip, remain);
    266      1.1  jonathan 			n->m_len = remain;
    267      1.1  jonathan 			m->m_len = skip + hlen;
    268      1.1  jonathan 			*off = skip;
    269      1.1  jonathan 		} else {
    270      1.1  jonathan 			/*
    271      1.1  jonathan 			 * No space in the old mbuf for the new header.
    272      1.1  jonathan 			 * Make space in the new mbuf and check the
    273      1.1  jonathan 			 * remainder'd data fits too.  If not then we
    274      1.1  jonathan 			 * must allocate an additional mbuf (yech).
    275      1.1  jonathan 			 */
    276      1.1  jonathan 			n->m_len = 0;
    277      1.1  jonathan 			if (remain + hlen > M_TRAILINGSPACE(n)) {
    278      1.1  jonathan 				struct mbuf *n2;
    279      1.1  jonathan 
    280      1.1  jonathan 				MGET(n2, M_DONTWAIT, MT_DATA);
    281      1.1  jonathan 				/* NB: new mbuf is on chain, let caller free */
    282      1.1  jonathan 				if (n2 == NULL)
    283      1.1  jonathan 					return (NULL);
    284      1.1  jonathan 				n2->m_len = 0;
    285      1.1  jonathan 				memcpy(mtod(n2, caddr_t),
    286      1.1  jonathan 				       mtod(m, caddr_t) + skip, remain);
    287      1.1  jonathan 				n2->m_len = remain;
    288      1.1  jonathan 				/* splice in second mbuf */
    289      1.1  jonathan 				n2->m_next = n->m_next;
    290      1.1  jonathan 				n->m_next = n2;
    291      1.1  jonathan 				newipsecstat.ips_mbinserted++;
    292      1.1  jonathan 			} else {
    293      1.1  jonathan 				memcpy(mtod(n, caddr_t) + hlen,
    294      1.1  jonathan 				       mtod(m, caddr_t) + skip, remain);
    295      1.1  jonathan 				n->m_len += remain;
    296      1.1  jonathan 			}
    297      1.1  jonathan 			m->m_len -= remain;
    298      1.1  jonathan 			n->m_len += hlen;
    299      1.1  jonathan 			m = n;			/* header is at front ... */
    300      1.1  jonathan 			*off = 0;		/* ... of new mbuf */
    301      1.1  jonathan 		}
    302      1.1  jonathan 	} else {
    303      1.1  jonathan 		/*
    304      1.1  jonathan 		 * Copy the remainder to the back of the mbuf
    305      1.1  jonathan 		 * so there's space to write the new header.
    306      1.1  jonathan 		 */
    307      1.1  jonathan 		/* XXX can this be memcpy? does it handle overlap? */
    308      1.1  jonathan 		ovbcopy(mtod(m, caddr_t) + skip,
    309      1.1  jonathan 			mtod(m, caddr_t) + skip + hlen, remain);
    310      1.1  jonathan 		m->m_len += hlen;
    311      1.1  jonathan 		*off = skip;
    312      1.1  jonathan 	}
    313      1.1  jonathan 	m0->m_pkthdr.len += hlen;		/* adjust packet length */
    314      1.1  jonathan 	return m;
    315      1.1  jonathan }
    316      1.1  jonathan 
    317      1.1  jonathan /*
    318      1.1  jonathan  * m_pad(m, n) pads <m> with <n> bytes at the end. The packet header
    319      1.1  jonathan  * length is updated, and a pointer to the first byte of the padding
    320      1.1  jonathan  * (which is guaranteed to be all in one mbuf) is returned.
    321      1.1  jonathan  */
    322      1.1  jonathan caddr_t
    323      1.1  jonathan m_pad(struct mbuf *m, int n)
    324      1.1  jonathan {
    325      1.1  jonathan 	register struct mbuf *m0, *m1;
    326      1.1  jonathan 	register int len, pad;
    327      1.1  jonathan 	caddr_t retval;
    328      1.1  jonathan 
    329      1.1  jonathan 	if (n <= 0) {  /* No stupid arguments. */
    330      1.1  jonathan 		DPRINTF(("m_pad: pad length invalid (%d)\n", n));
    331      1.1  jonathan 		m_freem(m);
    332      1.1  jonathan 		return NULL;
    333      1.1  jonathan 	}
    334      1.1  jonathan 
    335      1.1  jonathan 	len = m->m_pkthdr.len;
    336      1.1  jonathan 	pad = n;
    337      1.1  jonathan 	m0 = m;
    338      1.1  jonathan 
    339      1.1  jonathan 	while (m0->m_len < len) {
    340      1.1  jonathan IPSEC_ASSERT(m0->m_next != NULL, ("m_pad: m0 null, len %u m_len %u", len, m0->m_len));/*XXX*/
    341      1.1  jonathan 		len -= m0->m_len;
    342      1.1  jonathan 		m0 = m0->m_next;
    343      1.1  jonathan 	}
    344      1.1  jonathan 
    345      1.1  jonathan 	if (m0->m_len != len) {
    346      1.1  jonathan 		DPRINTF(("m_pad: length mismatch (should be %d instead of %d)\n",
    347      1.1  jonathan 		    m->m_pkthdr.len, m->m_pkthdr.len + m0->m_len - len));
    348      1.1  jonathan 
    349      1.1  jonathan 		m_freem(m);
    350      1.1  jonathan 		return NULL;
    351      1.1  jonathan 	}
    352      1.1  jonathan 
    353      1.1  jonathan 	/* Check for zero-length trailing mbufs, and find the last one. */
    354      1.1  jonathan 	for (m1 = m0; m1->m_next; m1 = m1->m_next) {
    355      1.1  jonathan 		if (m1->m_next->m_len != 0) {
    356      1.1  jonathan 			DPRINTF(("m_pad: length mismatch (should be %d "
    357      1.1  jonathan 			    "instead of %d)\n",
    358      1.1  jonathan 			    m->m_pkthdr.len,
    359      1.1  jonathan 			    m->m_pkthdr.len + m1->m_next->m_len));
    360      1.1  jonathan 
    361      1.1  jonathan 			m_freem(m);
    362      1.1  jonathan 			return NULL;
    363      1.1  jonathan 		}
    364      1.1  jonathan 
    365      1.1  jonathan 		m0 = m1->m_next;
    366      1.1  jonathan 	}
    367      1.1  jonathan 
    368      1.1  jonathan 	if (pad > M_TRAILINGSPACE(m0)) {
    369      1.1  jonathan 		/* Add an mbuf to the chain. */
    370      1.1  jonathan 		MGET(m1, M_DONTWAIT, MT_DATA);
    371      1.1  jonathan 		if (m1 == 0) {
    372      1.1  jonathan 			m_freem(m0);
    373      1.1  jonathan 			DPRINTF(("m_pad: unable to get extra mbuf\n"));
    374      1.1  jonathan 			return NULL;
    375      1.1  jonathan 		}
    376      1.1  jonathan 
    377      1.1  jonathan 		m0->m_next = m1;
    378      1.1  jonathan 		m0 = m1;
    379      1.1  jonathan 		m0->m_len = 0;
    380      1.1  jonathan 	}
    381      1.1  jonathan 
    382      1.1  jonathan 	retval = m0->m_data + m0->m_len;
    383      1.1  jonathan 	m0->m_len += pad;
    384      1.1  jonathan 	m->m_pkthdr.len += pad;
    385      1.1  jonathan 
    386      1.1  jonathan 	return retval;
    387      1.1  jonathan }
    388      1.1  jonathan 
    389      1.1  jonathan /*
    390      1.1  jonathan  * Remove hlen data at offset skip in the packet.  This is used by
    391      1.1  jonathan  * the protocols strip protocol headers and associated data (e.g. IV,
    392      1.1  jonathan  * authenticator) on input.
    393      1.1  jonathan  */
    394      1.1  jonathan int
    395      1.1  jonathan m_striphdr(struct mbuf *m, int skip, int hlen)
    396      1.1  jonathan {
    397      1.1  jonathan 	struct mbuf *m1;
    398      1.1  jonathan 	int roff;
    399      1.1  jonathan 
    400      1.1  jonathan 	/* Find beginning of header */
    401      1.1  jonathan 	m1 = m_getptr(m, skip, &roff);
    402      1.1  jonathan 	if (m1 == NULL)
    403      1.1  jonathan 		return (EINVAL);
    404      1.1  jonathan 
    405      1.1  jonathan 	/* Remove the header and associated data from the mbuf. */
    406      1.1  jonathan 	if (roff == 0) {
    407      1.1  jonathan 		/* The header was at the beginning of the mbuf */
    408      1.1  jonathan 		newipsecstat.ips_input_front++;
    409      1.1  jonathan 		m_adj(m1, hlen);
    410      1.1  jonathan 		if ((m1->m_flags & M_PKTHDR) == 0)
    411      1.1  jonathan 			m->m_pkthdr.len -= hlen;
    412      1.1  jonathan 	} else if (roff + hlen >= m1->m_len) {
    413      1.1  jonathan 		struct mbuf *mo;
    414      1.1  jonathan 
    415      1.1  jonathan 		/*
    416      1.1  jonathan 		 * Part or all of the header is at the end of this mbuf,
    417      1.1  jonathan 		 * so first let's remove the remainder of the header from
    418      1.1  jonathan 		 * the beginning of the remainder of the mbuf chain, if any.
    419      1.1  jonathan 		 */
    420      1.1  jonathan 		newipsecstat.ips_input_end++;
    421      1.1  jonathan 		if (roff + hlen > m1->m_len) {
    422      1.1  jonathan 			/* Adjust the next mbuf by the remainder */
    423      1.1  jonathan 			m_adj(m1->m_next, roff + hlen - m1->m_len);
    424      1.1  jonathan 
    425      1.1  jonathan 			/* The second mbuf is guaranteed not to have a pkthdr... */
    426      1.1  jonathan 			m->m_pkthdr.len -= (roff + hlen - m1->m_len);
    427      1.1  jonathan 		}
    428      1.1  jonathan 
    429      1.1  jonathan 		/* Now, let's unlink the mbuf chain for a second...*/
    430      1.1  jonathan 		mo = m1->m_next;
    431      1.1  jonathan 		m1->m_next = NULL;
    432      1.1  jonathan 
    433      1.1  jonathan 		/* ...and trim the end of the first part of the chain...sick */
    434      1.1  jonathan 		m_adj(m1, -(m1->m_len - roff));
    435      1.1  jonathan 		if ((m1->m_flags & M_PKTHDR) == 0)
    436      1.1  jonathan 			m->m_pkthdr.len -= (m1->m_len - roff);
    437      1.1  jonathan 
    438      1.1  jonathan 		/* Finally, let's relink */
    439      1.1  jonathan 		m1->m_next = mo;
    440      1.1  jonathan 	} else {
    441      1.1  jonathan 		/*
    442      1.1  jonathan 		 * The header lies in the "middle" of the mbuf; copy
    443      1.1  jonathan 		 * the remainder of the mbuf down over the header.
    444      1.1  jonathan 		 */
    445      1.1  jonathan 		newipsecstat.ips_input_middle++;
    446      1.2  jonathan 		ovbcopy(mtod(m1, u_char *) + roff + hlen,
    447      1.1  jonathan 		      mtod(m1, u_char *) + roff,
    448      1.1  jonathan 		      m1->m_len - (roff + hlen));
    449      1.1  jonathan 		m1->m_len -= hlen;
    450      1.1  jonathan 		m->m_pkthdr.len -= hlen;
    451      1.1  jonathan 	}
    452      1.1  jonathan 	return (0);
    453      1.1  jonathan }
    454      1.1  jonathan 
    455      1.1  jonathan /*
    456      1.1  jonathan  * Diagnostic routine to check mbuf alignment as required by the
    457      1.1  jonathan  * crypto device drivers (that use DMA).
    458      1.1  jonathan  */
    459      1.1  jonathan void
    460      1.1  jonathan m_checkalignment(const char* where, struct mbuf *m0, int off, int len)
    461      1.1  jonathan {
    462      1.1  jonathan 	int roff;
    463      1.1  jonathan 	struct mbuf *m = m_getptr(m0, off, &roff);
    464      1.1  jonathan 	caddr_t addr;
    465      1.1  jonathan 
    466      1.1  jonathan 	if (m == NULL)
    467      1.1  jonathan 		return;
    468      1.1  jonathan 	printf("%s (off %u len %u): ", where, off, len);
    469      1.1  jonathan 	addr = mtod(m, caddr_t) + roff;
    470      1.1  jonathan 	do {
    471      1.1  jonathan 		int mlen;
    472      1.1  jonathan 
    473      1.1  jonathan 		if (((uintptr_t) addr) & 3) {
    474      1.1  jonathan 			printf("addr misaligned %p,", addr);
    475      1.1  jonathan 			break;
    476      1.1  jonathan 		}
    477      1.1  jonathan 		mlen = m->m_len;
    478      1.1  jonathan 		if (mlen > len)
    479      1.1  jonathan 			mlen = len;
    480      1.1  jonathan 		len -= mlen;
    481      1.1  jonathan 		if (len && (mlen & 3)) {
    482      1.1  jonathan 			printf("len mismatch %u,", mlen);
    483      1.1  jonathan 			break;
    484      1.1  jonathan 		}
    485      1.1  jonathan 		m = m->m_next;
    486      1.1  jonathan 		addr = m ? mtod(m, caddr_t) : NULL;
    487      1.1  jonathan 	} while (m && len > 0);
    488      1.1  jonathan 	for (m = m0; m; m = m->m_next)
    489      1.1  jonathan 		printf(" [%p:%u]", mtod(m, caddr_t), m->m_len);
    490      1.1  jonathan 	printf("\n");
    491      1.1  jonathan }
    492