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