1/*	$KAME: uipc_mbuf2.c,v 1.31 2001/11/28 11:08:53 itojun Exp $	*/
2/*	$NetBSD: uipc_mbuf.c,v 1.40 1999/04/01 00:23:25 thorpej Exp $	*/
3
4/*-
5 * Copyright (C) 1999 WIDE Project.
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 *    notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 *    notice, this list of conditions and the following disclaimer in the
15 *    documentation and/or other materials provided with the distribution.
16 * 3. Neither the name of the project nor the names of its contributors
17 *    may be used to endorse or promote products derived from this software
18 *    without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 */
32/*-
33 * Copyright (c) 1982, 1986, 1988, 1991, 1993
34 *	The Regents of the University of California.  All rights reserved.
35 *
36 * Redistribution and use in source and binary forms, with or without
37 * modification, are permitted provided that the following conditions
38 * are met:
39 * 1. Redistributions of source code must retain the above copyright
40 *    notice, this list of conditions and the following disclaimer.
41 * 2. Redistributions in binary form must reproduce the above copyright
42 *    notice, this list of conditions and the following disclaimer in the
43 *    documentation and/or other materials provided with the distribution.
44 * 4. Neither the name of the University nor the names of its contributors
45 *    may be used to endorse or promote products derived from this software
46 *    without specific prior written permission.
47 *
48 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
49 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
50 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
51 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
52 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
53 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
54 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
55 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
56 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
57 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
58 * SUCH DAMAGE.
59 *
60 *	@(#)uipc_mbuf.c	8.4 (Berkeley) 2/14/95
61 */
62
63#include <sys/cdefs.h>
64__FBSDID("$FreeBSD: stable/11/sys/kern/uipc_mbuf2.c 312441 2017-01-19 23:42:51Z rpokala $");
65
66/*#define PULLDOWN_DEBUG*/
67
68#ifdef __HAIKU__
69#define FBSD_DRIVER
70#endif
71
72#include <sys/param.h>
73#include <sys/systm.h>
74#include <sys/kernel.h>
75#include <sys/lock.h>
76#include <sys/malloc.h>
77#include <sys/mbuf.h>
78#include <sys/mutex.h>
79
80#include <security/mac/mac_framework.h>
81
82static MALLOC_DEFINE(M_PACKET_TAGS, MBUF_TAG_MEM_NAME,
83    "packet-attached information");
84
85/* can't call it m_dup(), as freebsd[34] uses m_dup() with different arg */
86static struct mbuf *m_dup1(struct mbuf *, int, int, int);
87
88/*
89 * ensure that [off, off + len) is contiguous on the mbuf chain "m".
90 * packet chain before "off" is kept untouched.
91 * if offp == NULL, the target will start at <retval, 0> on resulting chain.
92 * if offp != NULL, the target will start at <retval, *offp> on resulting chain.
93 *
94 * on error return (NULL return value), original "m" will be freed.
95 *
96 * XXX: M_TRAILINGSPACE/M_LEADINGSPACE only permitted on writable ext_buf.
97 */
98struct mbuf *
99m_pulldown(struct mbuf *m, int off, int len, int *offp)
100{
101	struct mbuf *n, *o;
102	int hlen, tlen, olen;
103	int writable;
104
105	/* check invalid arguments. */
106	if (m == NULL)
107		panic("m == NULL in m_pulldown()");
108	if (len > MCLBYTES) {
109		m_freem(m);
110		return NULL;	/* impossible */
111	}
112
113#ifdef PULLDOWN_DEBUG
114    {
115	struct mbuf *t;
116	printf("before:");
117	for (t = m; t; t = t->m_next)
118		printf(" %d", t->m_len);
119	printf("\n");
120    }
121#endif
122	n = m;
123	while (n != NULL && off > 0) {
124		if (n->m_len > off)
125			break;
126		off -= n->m_len;
127		n = n->m_next;
128	}
129	/* be sure to point non-empty mbuf */
130	while (n != NULL && n->m_len == 0)
131		n = n->m_next;
132	if (!n) {
133		m_freem(m);
134		return NULL;	/* mbuf chain too short */
135	}
136
137	/*
138	 * The following comment is dated but still partially applies:
139	 *
140	 * XXX: This code is flawed because it considers a "writable" mbuf
141	 *      data region to require all of the following:
142	 *	  (i) mbuf _has_ to have M_EXT set; if it is just a regular
143	 *	      mbuf, it is still not considered "writable."
144	 *	  (ii) since mbuf has M_EXT, the ext_type _has_ to be
145	 *	       EXT_CLUSTER. Anything else makes it non-writable.
146	 *	  (iii) M_WRITABLE() must evaluate true.
147	 *      Ideally, the requirement should only be (iii).
148	 *
149	 * If we're writable, we're sure we're writable, because the ref. count
150	 * cannot increase from 1, as that would require possession of mbuf
151	 * n by someone else (which is impossible). However, if we're _not_
152	 * writable, we may eventually become writable )if the ref. count drops
153	 * to 1), but we'll fail to notice it unless we re-evaluate
154	 * M_WRITABLE(). For now, we only evaluate once at the beginning and
155	 * live with this.
156	 */
157	writable = 0;
158	if ((n->m_flags & M_EXT) == 0 ||
159	    (n->m_ext.ext_type == EXT_CLUSTER && M_WRITABLE(n)))
160		writable = 1;
161
162	/*
163	 * the target data is on <n, off>.
164	 * if we got enough data on the mbuf "n", we're done.
165	 */
166	if ((off == 0 || offp) && len <= n->m_len - off)
167		goto ok;
168
169	/*
170	 * when len <= n->m_len - off and off != 0, it is a special case.
171	 * len bytes from <n, off> sits in single mbuf, but the caller does
172	 * not like the starting position (off).
173	 * chop the current mbuf into two pieces, set off to 0.
174	 */
175	if (len <= n->m_len - off) {
176		o = m_dup1(n, off, n->m_len - off, M_NOWAIT);
177		if (o == NULL) {
178			m_freem(m);
179			return NULL;	/* ENOBUFS */
180		}
181		n->m_len = off;
182		o->m_next = n->m_next;
183		n->m_next = o;
184		n = n->m_next;
185		off = 0;
186		goto ok;
187	}
188
189	/*
190	 * we need to take hlen from <n, off> and tlen from <n->m_next, 0>,
191	 * and construct contiguous mbuf with m_len == len.
192	 * note that hlen + tlen == len, and tlen > 0.
193	 */
194	hlen = n->m_len - off;
195	tlen = len - hlen;
196
197	/*
198	 * ensure that we have enough trailing data on mbuf chain.
199	 * if not, we can do nothing about the chain.
200	 */
201	olen = 0;
202	for (o = n->m_next; o != NULL; o = o->m_next)
203		olen += o->m_len;
204	if (hlen + olen < len) {
205		m_freem(m);
206		return NULL;	/* mbuf chain too short */
207	}
208
209	/*
210	 * easy cases first.
211	 * we need to use m_copydata() to get data from <n->m_next, 0>.
212	 */
213	if ((off == 0 || offp) && M_TRAILINGSPACE(n) >= tlen
214	 && writable) {
215		m_copydata(n->m_next, 0, tlen, mtod(n, caddr_t) + n->m_len);
216		n->m_len += tlen;
217		m_adj(n->m_next, tlen);
218		goto ok;
219	}
220	if ((off == 0 || offp) && M_LEADINGSPACE(n->m_next) >= hlen
221	 && writable) {
222		n->m_next->m_data -= hlen;
223		n->m_next->m_len += hlen;
224		bcopy(mtod(n, caddr_t) + off, mtod(n->m_next, caddr_t), hlen);
225		n->m_len -= hlen;
226		n = n->m_next;
227		off = 0;
228		goto ok;
229	}
230
231	/*
232	 * now, we need to do the hard way.  don't m_copy as there's no room
233	 * on both end.
234	 */
235	if (len > MLEN)
236		o = m_getcl(M_NOWAIT, m->m_type, 0);
237	else
238		o = m_get(M_NOWAIT, m->m_type);
239	if (!o) {
240		m_freem(m);
241		return NULL;	/* ENOBUFS */
242	}
243	/* get hlen from <n, off> into <o, 0> */
244	o->m_len = hlen;
245	bcopy(mtod(n, caddr_t) + off, mtod(o, caddr_t), hlen);
246	n->m_len -= hlen;
247	/* get tlen from <n->m_next, 0> into <o, hlen> */
248	m_copydata(n->m_next, 0, tlen, mtod(o, caddr_t) + o->m_len);
249	o->m_len += tlen;
250	m_adj(n->m_next, tlen);
251	o->m_next = n->m_next;
252	n->m_next = o;
253	n = o;
254	off = 0;
255
256ok:
257#ifdef PULLDOWN_DEBUG
258    {
259	struct mbuf *t;
260	printf("after:");
261	for (t = m; t; t = t->m_next)
262		printf("%c%d", t == n ? '*' : ' ', t->m_len);
263	printf(" (off=%d)\n", off);
264    }
265#endif
266	if (offp)
267		*offp = off;
268	return n;
269}
270
271static struct mbuf *
272m_dup1(struct mbuf *m, int off, int len, int wait)
273{
274	struct mbuf *n;
275	int copyhdr;
276
277	if (len > MCLBYTES)
278		return NULL;
279	if (off == 0 && (m->m_flags & M_PKTHDR) != 0)
280		copyhdr = 1;
281	else
282		copyhdr = 0;
283	if (len >= MINCLSIZE) {
284		if (copyhdr == 1)
285			n = m_getcl(wait, m->m_type, M_PKTHDR);
286		else
287			n = m_getcl(wait, m->m_type, 0);
288	} else {
289		if (copyhdr == 1)
290			n = m_gethdr(wait, m->m_type);
291		else
292			n = m_get(wait, m->m_type);
293	}
294	if (!n)
295		return NULL; /* ENOBUFS */
296
297	if (copyhdr && !m_dup_pkthdr(n, m, wait)) {
298		m_free(n);
299		return NULL;
300	}
301	m_copydata(m, off, len, mtod(n, caddr_t));
302	n->m_len = len;
303	return n;
304}
305
306/* Free a packet tag. */
307void
308m_tag_free_default(struct m_tag *t)
309{
310#ifdef MAC
311	if (t->m_tag_id == PACKET_TAG_MACLABEL)
312		mac_mbuf_tag_destroy(t);
313#endif
314	free(t, M_PACKET_TAGS);
315}
316
317/* Get a packet tag structure along with specified data following. */
318struct m_tag *
319m_tag_alloc(uint32_t cookie, int type, int len, int wait)
320{
321	struct m_tag *t;
322
323	MBUF_CHECKSLEEP(wait);
324	if (len < 0)
325		return NULL;
326	t = malloc(len + sizeof(struct m_tag), M_PACKET_TAGS, wait);
327	if (t == NULL)
328		return NULL;
329	m_tag_setup(t, cookie, type, len);
330	t->m_tag_free = m_tag_free_default;
331	return t;
332}
333
334/* Unlink and free a packet tag. */
335void
336m_tag_delete(struct mbuf *m, struct m_tag *t)
337{
338
339	KASSERT(m && t, ("m_tag_delete: null argument, m %p t %p", m, t));
340	m_tag_unlink(m, t);
341	m_tag_free(t);
342}
343
344/* Unlink and free a packet tag chain, starting from given tag. */
345void
346m_tag_delete_chain(struct mbuf *m, struct m_tag *t)
347{
348	struct m_tag *p, *q;
349
350	KASSERT(m, ("m_tag_delete_chain: null mbuf"));
351	if (t != NULL)
352		p = t;
353	else
354		p = SLIST_FIRST(&m->m_pkthdr.tags);
355	if (p == NULL)
356		return;
357	while ((q = SLIST_NEXT(p, m_tag_link)) != NULL)
358		m_tag_delete(m, q);
359	m_tag_delete(m, p);
360}
361
362/*
363 * Strip off all tags that would normally vanish when
364 * passing through a network interface.  Only persistent
365 * tags will exist after this; these are expected to remain
366 * so long as the mbuf chain exists, regardless of the
367 * path the mbufs take.
368 */
369void
370m_tag_delete_nonpersistent(struct mbuf *m)
371{
372	struct m_tag *p, *q;
373
374	SLIST_FOREACH_SAFE(p, &m->m_pkthdr.tags, m_tag_link, q)
375		if ((p->m_tag_id & MTAG_PERSISTENT) == 0)
376			m_tag_delete(m, p);
377}
378
379/* Find a tag, starting from a given position. */
380struct m_tag *
381m_tag_locate(struct mbuf *m, uint32_t cookie, int type, struct m_tag *t)
382{
383	struct m_tag *p;
384
385	KASSERT(m, ("m_tag_locate: null mbuf"));
386	if (t == NULL)
387		p = SLIST_FIRST(&m->m_pkthdr.tags);
388	else
389		p = SLIST_NEXT(t, m_tag_link);
390	while (p != NULL) {
391		if (p->m_tag_cookie == cookie && p->m_tag_id == type)
392			return p;
393		p = SLIST_NEXT(p, m_tag_link);
394	}
395	return NULL;
396}
397
398/* Copy a single tag. */
399struct m_tag *
400m_tag_copy(struct m_tag *t, int how)
401{
402	struct m_tag *p;
403
404	MBUF_CHECKSLEEP(how);
405	KASSERT(t, ("m_tag_copy: null tag"));
406	p = m_tag_alloc(t->m_tag_cookie, t->m_tag_id, t->m_tag_len, how);
407	if (p == NULL)
408		return (NULL);
409#ifdef MAC
410	/*
411	 * XXXMAC: we should probably pass off the initialization, and
412	 * copying here?  can we hide that PACKET_TAG_MACLABEL is
413	 * special from the mbuf code?
414	 */
415	if (t->m_tag_id == PACKET_TAG_MACLABEL) {
416		if (mac_mbuf_tag_init(p, how) != 0) {
417			m_tag_free(p);
418			return (NULL);
419		}
420		mac_mbuf_tag_copy(t, p);
421	} else
422#endif
423		bcopy(t + 1, p + 1, t->m_tag_len); /* Copy the data */
424	return p;
425}
426
427/*
428 * Copy two tag chains. The destination mbuf (to) loses any attached
429 * tags even if the operation fails. This should not be a problem, as
430 * m_tag_copy_chain() is typically called with a newly-allocated
431 * destination mbuf.
432 */
433int
434m_tag_copy_chain(struct mbuf *to, const struct mbuf *from, int how)
435{
436	struct m_tag *p, *t, *tprev = NULL;
437
438	MBUF_CHECKSLEEP(how);
439	KASSERT(to && from,
440		("m_tag_copy_chain: null argument, to %p from %p", to, from));
441	m_tag_delete_chain(to, NULL);
442	SLIST_FOREACH(p, &from->m_pkthdr.tags, m_tag_link) {
443		t = m_tag_copy(p, how);
444		if (t == NULL) {
445			m_tag_delete_chain(to, NULL);
446			return 0;
447		}
448		if (tprev == NULL)
449			SLIST_INSERT_HEAD(&to->m_pkthdr.tags, t, m_tag_link);
450		else
451			SLIST_INSERT_AFTER(tprev, t, m_tag_link);
452		tprev = t;
453	}
454	return 1;
455}
456