1829d1a776d2fc5124c1701da541079d0e17da6b3tuexen/*-
2829d1a776d2fc5124c1701da541079d0e17da6b3tuexen * Copyright (c) 1982, 1986, 1988, 1993
3829d1a776d2fc5124c1701da541079d0e17da6b3tuexen *      The Regents of the University of California.
4829d1a776d2fc5124c1701da541079d0e17da6b3tuexen * All rights reserved.
5829d1a776d2fc5124c1701da541079d0e17da6b3tuexen *
6829d1a776d2fc5124c1701da541079d0e17da6b3tuexen * Redistribution and use in source and binary forms, with or without
7829d1a776d2fc5124c1701da541079d0e17da6b3tuexen * modification, are permitted provided that the following conditions
8829d1a776d2fc5124c1701da541079d0e17da6b3tuexen * are met:
9829d1a776d2fc5124c1701da541079d0e17da6b3tuexen * 1. Redistributions of source code must retain the above copyright
10829d1a776d2fc5124c1701da541079d0e17da6b3tuexen *    notice, this list of conditions and the following disclaimer.
11829d1a776d2fc5124c1701da541079d0e17da6b3tuexen * 2. Redistributions in binary form must reproduce the above copyright
12829d1a776d2fc5124c1701da541079d0e17da6b3tuexen *    notice, this list of conditions and the following disclaimer in the
13829d1a776d2fc5124c1701da541079d0e17da6b3tuexen *    documentation and/or other materials provided with the distribution.
14829d1a776d2fc5124c1701da541079d0e17da6b3tuexen * 3. Neither the name of the University nor the names of its contributors
15829d1a776d2fc5124c1701da541079d0e17da6b3tuexen *    may be used to endorse or promote products derived from this software
16829d1a776d2fc5124c1701da541079d0e17da6b3tuexen *    without specific prior written permission.
17829d1a776d2fc5124c1701da541079d0e17da6b3tuexen *
18829d1a776d2fc5124c1701da541079d0e17da6b3tuexen * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
19829d1a776d2fc5124c1701da541079d0e17da6b3tuexen * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20829d1a776d2fc5124c1701da541079d0e17da6b3tuexen * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21829d1a776d2fc5124c1701da541079d0e17da6b3tuexen * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
22829d1a776d2fc5124c1701da541079d0e17da6b3tuexen * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23829d1a776d2fc5124c1701da541079d0e17da6b3tuexen * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24829d1a776d2fc5124c1701da541079d0e17da6b3tuexen * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25829d1a776d2fc5124c1701da541079d0e17da6b3tuexen * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26829d1a776d2fc5124c1701da541079d0e17da6b3tuexen * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27829d1a776d2fc5124c1701da541079d0e17da6b3tuexen * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28829d1a776d2fc5124c1701da541079d0e17da6b3tuexen * SUCH DAMAGE.
29829d1a776d2fc5124c1701da541079d0e17da6b3tuexen *
30829d1a776d2fc5124c1701da541079d0e17da6b3tuexen */
31829d1a776d2fc5124c1701da541079d0e17da6b3tuexen
32bca1dae6587a640359abee04337c0463b0a3893tuexen/*
33bca1dae6587a640359abee04337c0463b0a3893tuexen *  __Userspace__ version of /usr/src/sys/kern/kern_mbuf.c
34bca1dae6587a640359abee04337c0463b0a3893tuexen *  We are initializing two zones for Mbufs and Clusters.
3542d0ec7a8a09fcaa90b491d267245606c7caa7edtuexen *
36bca1dae6587a640359abee04337c0463b0a3893tuexen */
37bca1dae6587a640359abee04337c0463b0a3893tuexen
38bca1dae6587a640359abee04337c0463b0a3893tuexen#include <stdio.h>
39bca1dae6587a640359abee04337c0463b0a3893tuexen#include <string.h>
40bca1dae6587a640359abee04337c0463b0a3893tuexen/* #include <sys/param.h> This defines MSIZE 256 */
41bca1dae6587a640359abee04337c0463b0a3893tuexen#if !defined(SCTP_SIMPLE_ALLOCATOR)
42bca1dae6587a640359abee04337c0463b0a3893tuexen#include "umem.h"
43bca1dae6587a640359abee04337c0463b0a3893tuexen#endif
44bca1dae6587a640359abee04337c0463b0a3893tuexen#include "user_mbuf.h"
45bca1dae6587a640359abee04337c0463b0a3893tuexen#include "user_environment.h"
46bca1dae6587a640359abee04337c0463b0a3893tuexen#include "user_atomic.h"
47a1d7a8516e4d5b2136c5bb3d49aeac80271a36b0tuexen#include "netinet/sctp_pcb.h"
48bca1dae6587a640359abee04337c0463b0a3893tuexen
49bca1dae6587a640359abee04337c0463b0a3893tuexenstruct mbstat mbstat;
50bca1dae6587a640359abee04337c0463b0a3893tuexen#define KIPC_MAX_LINKHDR        4       /* int: max length of link header (see sys/sysclt.h) */
51c7108437de5af4d0b9f9a24979710b39197ec6cetuexen#define KIPC_MAX_PROTOHDR	5	/* int: max length of network header (see sys/sysclt.h)*/
52c7108437de5af4d0b9f9a24979710b39197ec6cetuexenint max_linkhdr = KIPC_MAX_LINKHDR;
53c7108437de5af4d0b9f9a24979710b39197ec6cetuexenint max_protohdr = KIPC_MAX_PROTOHDR; /* Size of largest protocol layer header. */
54bca1dae6587a640359abee04337c0463b0a3893tuexen
55bca1dae6587a640359abee04337c0463b0a3893tuexen/*
56bca1dae6587a640359abee04337c0463b0a3893tuexen * Zones from which we allocate.
57bca1dae6587a640359abee04337c0463b0a3893tuexen */
58bca1dae6587a640359abee04337c0463b0a3893tuexensctp_zone_t	zone_mbuf;
59bca1dae6587a640359abee04337c0463b0a3893tuexensctp_zone_t	zone_clust;
60bca1dae6587a640359abee04337c0463b0a3893tuexensctp_zone_t	zone_ext_refcnt;
61bca1dae6587a640359abee04337c0463b0a3893tuexen
6242d0ec7a8a09fcaa90b491d267245606c7caa7edtuexen/* __Userspace__ clust_mb_args will be passed as callback data to mb_ctor_clust
63bca1dae6587a640359abee04337c0463b0a3893tuexen * and mb_dtor_clust.
64bca1dae6587a640359abee04337c0463b0a3893tuexen * Note: I had to use struct clust_args as an encapsulation for an mbuf pointer.
65bca1dae6587a640359abee04337c0463b0a3893tuexen * struct mbuf * clust_mb_args; does not work.
66bca1dae6587a640359abee04337c0463b0a3893tuexen */
67bca1dae6587a640359abee04337c0463b0a3893tuexenstruct clust_args clust_mb_args;
68bca1dae6587a640359abee04337c0463b0a3893tuexen
69bca1dae6587a640359abee04337c0463b0a3893tuexen
70bca1dae6587a640359abee04337c0463b0a3893tuexen/* __Userspace__
71bca1dae6587a640359abee04337c0463b0a3893tuexen * Local prototypes.
72bca1dae6587a640359abee04337c0463b0a3893tuexen */
73bca1dae6587a640359abee04337c0463b0a3893tuexenstatic int	mb_ctor_mbuf(void *, void *, int);
74bca1dae6587a640359abee04337c0463b0a3893tuexenstatic int      mb_ctor_clust(void *, void *, int);
75bca1dae6587a640359abee04337c0463b0a3893tuexenstatic void	mb_dtor_mbuf(void *,  void *);
76bca1dae6587a640359abee04337c0463b0a3893tuexenstatic void	mb_dtor_clust(void *, void *);
77bca1dae6587a640359abee04337c0463b0a3893tuexen
78bca1dae6587a640359abee04337c0463b0a3893tuexen
79bca1dae6587a640359abee04337c0463b0a3893tuexen/***************** Functions taken from user_mbuf.h *************/
80bca1dae6587a640359abee04337c0463b0a3893tuexen
81bca1dae6587a640359abee04337c0463b0a3893tuexenstatic int mbuf_constructor_dup(struct mbuf *m, int pkthdr, short type)
82bca1dae6587a640359abee04337c0463b0a3893tuexen{
83bca1dae6587a640359abee04337c0463b0a3893tuexen	int flags = pkthdr;
84bca1dae6587a640359abee04337c0463b0a3893tuexen	if (type == MT_NOINIT)
85bca1dae6587a640359abee04337c0463b0a3893tuexen		return (0);
8642d0ec7a8a09fcaa90b491d267245606c7caa7edtuexen
87bca1dae6587a640359abee04337c0463b0a3893tuexen	m->m_next = NULL;
88bca1dae6587a640359abee04337c0463b0a3893tuexen	m->m_nextpkt = NULL;
89bca1dae6587a640359abee04337c0463b0a3893tuexen	m->m_len = 0;
90bca1dae6587a640359abee04337c0463b0a3893tuexen	m->m_flags = flags;
91bca1dae6587a640359abee04337c0463b0a3893tuexen	m->m_type = type;
92bca1dae6587a640359abee04337c0463b0a3893tuexen	if (flags & M_PKTHDR) {
93bca1dae6587a640359abee04337c0463b0a3893tuexen		m->m_data = m->m_pktdat;
94bca1dae6587a640359abee04337c0463b0a3893tuexen		m->m_pkthdr.rcvif = NULL;
95bca1dae6587a640359abee04337c0463b0a3893tuexen		m->m_pkthdr.len = 0;
96bca1dae6587a640359abee04337c0463b0a3893tuexen		m->m_pkthdr.header = NULL;
97bca1dae6587a640359abee04337c0463b0a3893tuexen		m->m_pkthdr.csum_flags = 0;
98bca1dae6587a640359abee04337c0463b0a3893tuexen		m->m_pkthdr.csum_data = 0;
99bca1dae6587a640359abee04337c0463b0a3893tuexen		m->m_pkthdr.tso_segsz = 0;
100bca1dae6587a640359abee04337c0463b0a3893tuexen		m->m_pkthdr.ether_vtag = 0;
101bca1dae6587a640359abee04337c0463b0a3893tuexen		SLIST_INIT(&m->m_pkthdr.tags);
102bca1dae6587a640359abee04337c0463b0a3893tuexen	} else
103bca1dae6587a640359abee04337c0463b0a3893tuexen		m->m_data = m->m_dat;
10442d0ec7a8a09fcaa90b491d267245606c7caa7edtuexen
105bca1dae6587a640359abee04337c0463b0a3893tuexen	return (0);
106bca1dae6587a640359abee04337c0463b0a3893tuexen}
107bca1dae6587a640359abee04337c0463b0a3893tuexen
108bca1dae6587a640359abee04337c0463b0a3893tuexen/* __Userspace__ */
109bca1dae6587a640359abee04337c0463b0a3893tuexenstruct mbuf *
110bca1dae6587a640359abee04337c0463b0a3893tuexenm_get(int how, short type)
111bca1dae6587a640359abee04337c0463b0a3893tuexen{
112bca1dae6587a640359abee04337c0463b0a3893tuexen	struct mbuf *mret;
1139b332c241dd6df73b563594af7c334e23f5e42b8t#if defined(SCTP_SIMPLE_ALLOCATOR)
1149b332c241dd6df73b563594af7c334e23f5e42b8t	struct mb_args mbuf_mb_args;
1159b332c241dd6df73b563594af7c334e23f5e42b8t
116bca1dae6587a640359abee04337c0463b0a3893tuexen	/* The following setter function is not yet being enclosed within
117bca1dae6587a640359abee04337c0463b0a3893tuexen	 * #if USING_MBUF_CONSTRUCTOR - #endif, until I have thoroughly tested
118bca1dae6587a640359abee04337c0463b0a3893tuexen	 * mb_dtor_mbuf. See comment there
119bca1dae6587a640359abee04337c0463b0a3893tuexen	 */
1209b332c241dd6df73b563594af7c334e23f5e42b8t	mbuf_mb_args.flags = 0;
1219b332c241dd6df73b563594af7c334e23f5e42b8t	mbuf_mb_args.type = type;
1229b332c241dd6df73b563594af7c334e23f5e42b8t#endif
12342d0ec7a8a09fcaa90b491d267245606c7caa7edtuexen	/* Mbuf master zone, zone_mbuf, has already been
124bca1dae6587a640359abee04337c0463b0a3893tuexen	 * created in mbuf_init() */
125bca1dae6587a640359abee04337c0463b0a3893tuexen	mret = SCTP_ZONE_GET(zone_mbuf, struct mbuf);
126bca1dae6587a640359abee04337c0463b0a3893tuexen#if defined(SCTP_SIMPLE_ALLOCATOR)
127bca1dae6587a640359abee04337c0463b0a3893tuexen	mb_ctor_mbuf(mret, &mbuf_mb_args, 0);
128bca1dae6587a640359abee04337c0463b0a3893tuexen#endif
129bca1dae6587a640359abee04337c0463b0a3893tuexen	/*mret =  ((struct mbuf *)umem_cache_alloc(zone_mbuf, UMEM_DEFAULT));*/
13042d0ec7a8a09fcaa90b491d267245606c7caa7edtuexen
131bca1dae6587a640359abee04337c0463b0a3893tuexen	/* There are cases when an object available in the current CPU's
132bca1dae6587a640359abee04337c0463b0a3893tuexen	 * loaded magazine and in those cases the object's constructor is not applied.
133bca1dae6587a640359abee04337c0463b0a3893tuexen	 * If that is the case, then we are duplicating constructor initialization here,
134bca1dae6587a640359abee04337c0463b0a3893tuexen	 * so that the mbuf is properly constructed before returning it.
135bca1dae6587a640359abee04337c0463b0a3893tuexen	 */
136bca1dae6587a640359abee04337c0463b0a3893tuexen	if (mret) {
137bca1dae6587a640359abee04337c0463b0a3893tuexen#if USING_MBUF_CONSTRUCTOR
138bca1dae6587a640359abee04337c0463b0a3893tuexen		if (! (mret->m_type == type) ) {
139bca1dae6587a640359abee04337c0463b0a3893tuexen			mbuf_constructor_dup(mret, 0, type);
140bca1dae6587a640359abee04337c0463b0a3893tuexen		}
14142d0ec7a8a09fcaa90b491d267245606c7caa7edtuexen#else
142bca1dae6587a640359abee04337c0463b0a3893tuexen		mbuf_constructor_dup(mret, 0, type);
143bca1dae6587a640359abee04337c0463b0a3893tuexen#endif
14442d0ec7a8a09fcaa90b491d267245606c7caa7edtuexen
145bca1dae6587a640359abee04337c0463b0a3893tuexen	}
146bca1dae6587a640359abee04337c0463b0a3893tuexen	return mret;
147bca1dae6587a640359abee04337c0463b0a3893tuexen}
148bca1dae6587a640359abee04337c0463b0a3893tuexen
149bca1dae6587a640359abee04337c0463b0a3893tuexen
150bca1dae6587a640359abee04337c0463b0a3893tuexen/* __Userspace__ */
151bca1dae6587a640359abee04337c0463b0a3893tuexenstruct mbuf *
152bca1dae6587a640359abee04337c0463b0a3893tuexenm_gethdr(int how, short type)
153bca1dae6587a640359abee04337c0463b0a3893tuexen{
154bca1dae6587a640359abee04337c0463b0a3893tuexen	struct mbuf *mret;
1559b332c241dd6df73b563594af7c334e23f5e42b8t#if defined(SCTP_SIMPLE_ALLOCATOR)
1569b332c241dd6df73b563594af7c334e23f5e42b8t	struct mb_args mbuf_mb_args;
1579b332c241dd6df73b563594af7c334e23f5e42b8t
158bca1dae6587a640359abee04337c0463b0a3893tuexen	/* The following setter function is not yet being enclosed within
159bca1dae6587a640359abee04337c0463b0a3893tuexen	 * #if USING_MBUF_CONSTRUCTOR - #endif, until I have thoroughly tested
160bca1dae6587a640359abee04337c0463b0a3893tuexen	 * mb_dtor_mbuf. See comment there
161bca1dae6587a640359abee04337c0463b0a3893tuexen	 */
1629b332c241dd6df73b563594af7c334e23f5e42b8t	mbuf_mb_args.flags = M_PKTHDR;
1639b332c241dd6df73b563594af7c334e23f5e42b8t	mbuf_mb_args.type = type;
1649b332c241dd6df73b563594af7c334e23f5e42b8t#endif
165bca1dae6587a640359abee04337c0463b0a3893tuexen	mret = SCTP_ZONE_GET(zone_mbuf, struct mbuf);
166bca1dae6587a640359abee04337c0463b0a3893tuexen#if defined(SCTP_SIMPLE_ALLOCATOR)
167bca1dae6587a640359abee04337c0463b0a3893tuexen	mb_ctor_mbuf(mret, &mbuf_mb_args, 0);
168bca1dae6587a640359abee04337c0463b0a3893tuexen#endif
169bca1dae6587a640359abee04337c0463b0a3893tuexen	/*mret = ((struct mbuf *)umem_cache_alloc(zone_mbuf, UMEM_DEFAULT));*/
170bca1dae6587a640359abee04337c0463b0a3893tuexen	/* There are cases when an object available in the current CPU's
171bca1dae6587a640359abee04337c0463b0a3893tuexen	 * loaded magazine and in those cases the object's constructor is not applied.
172bca1dae6587a640359abee04337c0463b0a3893tuexen	 * If that is the case, then we are duplicating constructor initialization here,
173bca1dae6587a640359abee04337c0463b0a3893tuexen	 * so that the mbuf is properly constructed before returning it.
174bca1dae6587a640359abee04337c0463b0a3893tuexen	 */
175bca1dae6587a640359abee04337c0463b0a3893tuexen	if (mret) {
176bca1dae6587a640359abee04337c0463b0a3893tuexen#if USING_MBUF_CONSTRUCTOR
177bca1dae6587a640359abee04337c0463b0a3893tuexen		if (! ((mret->m_flags & M_PKTHDR) && (mret->m_type == type)) ) {
178bca1dae6587a640359abee04337c0463b0a3893tuexen			mbuf_constructor_dup(mret, M_PKTHDR, type);
179bca1dae6587a640359abee04337c0463b0a3893tuexen		}
180bca1dae6587a640359abee04337c0463b0a3893tuexen#else
181bca1dae6587a640359abee04337c0463b0a3893tuexen		mbuf_constructor_dup(mret, M_PKTHDR, type);
182bca1dae6587a640359abee04337c0463b0a3893tuexen#endif
183bca1dae6587a640359abee04337c0463b0a3893tuexen	}
184bca1dae6587a640359abee04337c0463b0a3893tuexen	return mret;
185bca1dae6587a640359abee04337c0463b0a3893tuexen}
186bca1dae6587a640359abee04337c0463b0a3893tuexen
187bca1dae6587a640359abee04337c0463b0a3893tuexen/* __Userspace__ */
188bca1dae6587a640359abee04337c0463b0a3893tuexenstruct mbuf *
189bca1dae6587a640359abee04337c0463b0a3893tuexenm_free(struct mbuf *m)
190bca1dae6587a640359abee04337c0463b0a3893tuexen{
19142d0ec7a8a09fcaa90b491d267245606c7caa7edtuexen
192bca1dae6587a640359abee04337c0463b0a3893tuexen	struct mbuf *n = m->m_next;
19342d0ec7a8a09fcaa90b491d267245606c7caa7edtuexen
194bca1dae6587a640359abee04337c0463b0a3893tuexen	if (m->m_flags & M_EXT)
195bca1dae6587a640359abee04337c0463b0a3893tuexen		mb_free_ext(m);
196bca1dae6587a640359abee04337c0463b0a3893tuexen	else if ((m->m_flags & M_NOFREE) == 0) {
197bca1dae6587a640359abee04337c0463b0a3893tuexen#if defined(SCTP_SIMPLE_ALLOCATOR)
1989b332c241dd6df73b563594af7c334e23f5e42b8t		mb_dtor_mbuf(m, NULL);
199bca1dae6587a640359abee04337c0463b0a3893tuexen#endif
200bca1dae6587a640359abee04337c0463b0a3893tuexen		SCTP_ZONE_FREE(zone_mbuf, m);
201bca1dae6587a640359abee04337c0463b0a3893tuexen	}
202bca1dae6587a640359abee04337c0463b0a3893tuexen		/*umem_cache_free(zone_mbuf, m);*/
203bca1dae6587a640359abee04337c0463b0a3893tuexen	return (n);
204bca1dae6587a640359abee04337c0463b0a3893tuexen}
205bca1dae6587a640359abee04337c0463b0a3893tuexen
206bca1dae6587a640359abee04337c0463b0a3893tuexen
207bca1dae6587a640359abee04337c0463b0a3893tuexenstatic int clust_constructor_dup(caddr_t m_clust, struct mbuf* m)
208bca1dae6587a640359abee04337c0463b0a3893tuexen{
209bca1dae6587a640359abee04337c0463b0a3893tuexen	u_int *refcnt;
210bca1dae6587a640359abee04337c0463b0a3893tuexen	int type, size;
21142d0ec7a8a09fcaa90b491d267245606c7caa7edtuexen
212bca1dae6587a640359abee04337c0463b0a3893tuexen	/* Assigning cluster of MCLBYTES. TODO: Add jumbo frame functionality */
213bca1dae6587a640359abee04337c0463b0a3893tuexen	type = EXT_CLUSTER;
214bca1dae6587a640359abee04337c0463b0a3893tuexen	size = MCLBYTES;
21542d0ec7a8a09fcaa90b491d267245606c7caa7edtuexen
216bca1dae6587a640359abee04337c0463b0a3893tuexen	refcnt = SCTP_ZONE_GET(zone_ext_refcnt, u_int);
217bca1dae6587a640359abee04337c0463b0a3893tuexen	/*refcnt = (u_int *)umem_cache_alloc(zone_ext_refcnt, UMEM_DEFAULT);*/
218bca1dae6587a640359abee04337c0463b0a3893tuexen	if (refcnt == NULL) {
219bca1dae6587a640359abee04337c0463b0a3893tuexen#if !defined(SCTP_SIMPLE_ALLOCATOR)
220bca1dae6587a640359abee04337c0463b0a3893tuexen		umem_reap();
221bca1dae6587a640359abee04337c0463b0a3893tuexen#endif
222bca1dae6587a640359abee04337c0463b0a3893tuexen		refcnt = SCTP_ZONE_GET(zone_ext_refcnt, u_int);
223bca1dae6587a640359abee04337c0463b0a3893tuexen		/*refcnt = (u_int *)umem_cache_alloc(zone_ext_refcnt, UMEM_DEFAULT);*/
224bca1dae6587a640359abee04337c0463b0a3893tuexen	}
225bca1dae6587a640359abee04337c0463b0a3893tuexen	*refcnt = 1;
226bca1dae6587a640359abee04337c0463b0a3893tuexen	if (m != NULL) {
227bca1dae6587a640359abee04337c0463b0a3893tuexen		m->m_ext.ext_buf = (caddr_t)m_clust;
228bca1dae6587a640359abee04337c0463b0a3893tuexen		m->m_data = m->m_ext.ext_buf;
229bca1dae6587a640359abee04337c0463b0a3893tuexen		m->m_flags |= M_EXT;
230bca1dae6587a640359abee04337c0463b0a3893tuexen		m->m_ext.ext_free = NULL;
231bca1dae6587a640359abee04337c0463b0a3893tuexen		m->m_ext.ext_args = NULL;
23242d0ec7a8a09fcaa90b491d267245606c7caa7edtuexen		m->m_ext.ext_size = size;
233bca1dae6587a640359abee04337c0463b0a3893tuexen		m->m_ext.ext_type = type;
234bca1dae6587a640359abee04337c0463b0a3893tuexen		m->m_ext.ref_cnt = refcnt;
235bca1dae6587a640359abee04337c0463b0a3893tuexen	}
23642d0ec7a8a09fcaa90b491d267245606c7caa7edtuexen
237bca1dae6587a640359abee04337c0463b0a3893tuexen	return (0);
238bca1dae6587a640359abee04337c0463b0a3893tuexen}
239bca1dae6587a640359abee04337c0463b0a3893tuexen
240bca1dae6587a640359abee04337c0463b0a3893tuexen
241bca1dae6587a640359abee04337c0463b0a3893tuexen
242bca1dae6587a640359abee04337c0463b0a3893tuexen/* __Userspace__ */
243bca1dae6587a640359abee04337c0463b0a3893tuexenvoid
244bca1dae6587a640359abee04337c0463b0a3893tuexenm_clget(struct mbuf *m, int how)
245bca1dae6587a640359abee04337c0463b0a3893tuexen{
246bca1dae6587a640359abee04337c0463b0a3893tuexen	caddr_t mclust_ret;
2479b332c241dd6df73b563594af7c334e23f5e42b8t#if defined(SCTP_SIMPLE_ALLOCATOR)
2489b332c241dd6df73b563594af7c334e23f5e42b8t	struct clust_args clust_mb_args;
2499b332c241dd6df73b563594af7c334e23f5e42b8t#endif
250a1d7a8516e4d5b2136c5bb3d49aeac80271a36b0tuexen	if (m->m_flags & M_EXT) {
251e7eb46f39b8bfc4b5ed9b708232c1c669c06842bt		SCTPDBG(SCTP_DEBUG_USR, "%s: %p mbuf already has cluster\n", __func__, (void *)m);
252a1d7a8516e4d5b2136c5bb3d49aeac80271a36b0tuexen	}
253bca1dae6587a640359abee04337c0463b0a3893tuexen	m->m_ext.ext_buf = (char *)NULL;
2549b332c241dd6df73b563594af7c334e23f5e42b8t#if defined(SCTP_SIMPLE_ALLOCATOR)
2559b332c241dd6df73b563594af7c334e23f5e42b8t	clust_mb_args.parent_mbuf = m;
256bca1dae6587a640359abee04337c0463b0a3893tuexen#endif
257bca1dae6587a640359abee04337c0463b0a3893tuexen	mclust_ret = SCTP_ZONE_GET(zone_clust, char);
258bca1dae6587a640359abee04337c0463b0a3893tuexen#if defined(SCTP_SIMPLE_ALLOCATOR)
259bca1dae6587a640359abee04337c0463b0a3893tuexen	mb_ctor_clust(mclust_ret, &clust_mb_args, 0);
260bca1dae6587a640359abee04337c0463b0a3893tuexen#endif
261bca1dae6587a640359abee04337c0463b0a3893tuexen	/*mclust_ret = umem_cache_alloc(zone_clust, UMEM_DEFAULT);*/
26242d0ec7a8a09fcaa90b491d267245606c7caa7edtuexen	/*
263bca1dae6587a640359abee04337c0463b0a3893tuexen	 On a cluster allocation failure, call umem_reap() and retry.
264bca1dae6587a640359abee04337c0463b0a3893tuexen	 */
26542d0ec7a8a09fcaa90b491d267245606c7caa7edtuexen
2667d0ed644a4f9767589413cdaaa4026d1ef1140e7tuexen	if (mclust_ret == NULL) {
267bca1dae6587a640359abee04337c0463b0a3893tuexen#if !defined(SCTP_SIMPLE_ALLOCATOR)
268bca1dae6587a640359abee04337c0463b0a3893tuexen	/*	mclust_ret = SCTP_ZONE_GET(zone_clust, char);
269bca1dae6587a640359abee04337c0463b0a3893tuexen		mb_ctor_clust(mclust_ret, &clust_mb_args, 0);
270bca1dae6587a640359abee04337c0463b0a3893tuexen#else*/
271bca1dae6587a640359abee04337c0463b0a3893tuexen		umem_reap();
272bca1dae6587a640359abee04337c0463b0a3893tuexen		mclust_ret = SCTP_ZONE_GET(zone_clust, char);
273bca1dae6587a640359abee04337c0463b0a3893tuexen#endif
274bca1dae6587a640359abee04337c0463b0a3893tuexen		/*mclust_ret = umem_cache_alloc(zone_clust, UMEM_DEFAULT);*/
2757d0ed644a4f9767589413cdaaa4026d1ef1140e7tuexen		if (NULL == mclust_ret) {
276a1d7a8516e4d5b2136c5bb3d49aeac80271a36b0tuexen			SCTPDBG(SCTP_DEBUG_USR, "Memory allocation failure in %s\n", __func__);
277bca1dae6587a640359abee04337c0463b0a3893tuexen		}
278bca1dae6587a640359abee04337c0463b0a3893tuexen	}
27942d0ec7a8a09fcaa90b491d267245606c7caa7edtuexen
280bca1dae6587a640359abee04337c0463b0a3893tuexen#if USING_MBUF_CONSTRUCTOR
281bca1dae6587a640359abee04337c0463b0a3893tuexen	if ((m->m_ext.ext_buf == NULL)) {
282bca1dae6587a640359abee04337c0463b0a3893tuexen		clust_constructor_dup(mclust_ret, m);
283bca1dae6587a640359abee04337c0463b0a3893tuexen	}
284bca1dae6587a640359abee04337c0463b0a3893tuexen#else
285bca1dae6587a640359abee04337c0463b0a3893tuexen	clust_constructor_dup(mclust_ret, m);
286bca1dae6587a640359abee04337c0463b0a3893tuexen#endif
287bca1dae6587a640359abee04337c0463b0a3893tuexen}
288bca1dae6587a640359abee04337c0463b0a3893tuexen
289bca1dae6587a640359abee04337c0463b0a3893tuexen/*
290bca1dae6587a640359abee04337c0463b0a3893tuexen * Unlink a tag from the list of tags associated with an mbuf.
291bca1dae6587a640359abee04337c0463b0a3893tuexen */
292bca1dae6587a640359abee04337c0463b0a3893tuexenstatic __inline void
293bca1dae6587a640359abee04337c0463b0a3893tuexenm_tag_unlink(struct mbuf *m, struct m_tag *t)
294bca1dae6587a640359abee04337c0463b0a3893tuexen{
29542d0ec7a8a09fcaa90b491d267245606c7caa7edtuexen
296bca1dae6587a640359abee04337c0463b0a3893tuexen	SLIST_REMOVE(&m->m_pkthdr.tags, t, m_tag, m_tag_link);
297bca1dae6587a640359abee04337c0463b0a3893tuexen}
298bca1dae6587a640359abee04337c0463b0a3893tuexen
299bca1dae6587a640359abee04337c0463b0a3893tuexen/*
300bca1dae6587a640359abee04337c0463b0a3893tuexen * Reclaim resources associated with a tag.
301bca1dae6587a640359abee04337c0463b0a3893tuexen */
302bca1dae6587a640359abee04337c0463b0a3893tuexenstatic __inline void
303bca1dae6587a640359abee04337c0463b0a3893tuexenm_tag_free(struct m_tag *t)
304bca1dae6587a640359abee04337c0463b0a3893tuexen{
30542d0ec7a8a09fcaa90b491d267245606c7caa7edtuexen
306bca1dae6587a640359abee04337c0463b0a3893tuexen	(*t->m_tag_free)(t);
307bca1dae6587a640359abee04337c0463b0a3893tuexen}
308bca1dae6587a640359abee04337c0463b0a3893tuexen
309bca1dae6587a640359abee04337c0463b0a3893tuexen/*
310bca1dae6587a640359abee04337c0463b0a3893tuexen * Set up the contents of a tag.  Note that this does not fill in the free
311bca1dae6587a640359abee04337c0463b0a3893tuexen * method; the caller is expected to do that.
312bca1dae6587a640359abee04337c0463b0a3893tuexen *
313bca1dae6587a640359abee04337c0463b0a3893tuexen * XXX probably should be called m_tag_init, but that was already taken.
314bca1dae6587a640359abee04337c0463b0a3893tuexen */
315bca1dae6587a640359abee04337c0463b0a3893tuexenstatic __inline void
316bca1dae6587a640359abee04337c0463b0a3893tuexenm_tag_setup(struct m_tag *t, u_int32_t cookie, int type, int len)
317bca1dae6587a640359abee04337c0463b0a3893tuexen{
31842d0ec7a8a09fcaa90b491d267245606c7caa7edtuexen
319bca1dae6587a640359abee04337c0463b0a3893tuexen	t->m_tag_id = type;
320bca1dae6587a640359abee04337c0463b0a3893tuexen	t->m_tag_len = len;
321bca1dae6587a640359abee04337c0463b0a3893tuexen	t->m_tag_cookie = cookie;
322bca1dae6587a640359abee04337c0463b0a3893tuexen}
323bca1dae6587a640359abee04337c0463b0a3893tuexen
324bca1dae6587a640359abee04337c0463b0a3893tuexen/************ End functions from user_mbuf.h  ******************/
325bca1dae6587a640359abee04337c0463b0a3893tuexen
326bca1dae6587a640359abee04337c0463b0a3893tuexen
327bca1dae6587a640359abee04337c0463b0a3893tuexen
328bca1dae6587a640359abee04337c0463b0a3893tuexen/************ End functions to substitute umem_cache_alloc and umem_cache_free **************/
329bca1dae6587a640359abee04337c0463b0a3893tuexen
33042d0ec7a8a09fcaa90b491d267245606c7caa7edtuexen/* __Userspace__
331bca1dae6587a640359abee04337c0463b0a3893tuexen * TODO: mbuf_init must be called in the initialization routines
33242d0ec7a8a09fcaa90b491d267245606c7caa7edtuexen * of userspace stack.
333bca1dae6587a640359abee04337c0463b0a3893tuexen */
334bca1dae6587a640359abee04337c0463b0a3893tuexenvoid
335bca1dae6587a640359abee04337c0463b0a3893tuexenmbuf_init(void *dummy)
336bca1dae6587a640359abee04337c0463b0a3893tuexen{
337bca1dae6587a640359abee04337c0463b0a3893tuexen
338bca1dae6587a640359abee04337c0463b0a3893tuexen	/*
33942d0ec7a8a09fcaa90b491d267245606c7caa7edtuexen	 * __Userspace__Configure UMA zones for Mbufs and Clusters.
340bca1dae6587a640359abee04337c0463b0a3893tuexen	 * (TODO: m_getcl() - using packet secondary zone).
34142d0ec7a8a09fcaa90b491d267245606c7caa7edtuexen	 * There is no provision for trash_init and trash_fini in umem.
34242d0ec7a8a09fcaa90b491d267245606c7caa7edtuexen	 *
343bca1dae6587a640359abee04337c0463b0a3893tuexen	 */
344bca1dae6587a640359abee04337c0463b0a3893tuexen /* zone_mbuf = umem_cache_create(MBUF_MEM_NAME, MSIZE, 0,
34542d0ec7a8a09fcaa90b491d267245606c7caa7edtuexen				mb_ctor_mbuf, mb_dtor_mbuf, NULL,
346bca1dae6587a640359abee04337c0463b0a3893tuexen				&mbuf_mb_args,
347bca1dae6587a640359abee04337c0463b0a3893tuexen				NULL, 0);
348bca1dae6587a640359abee04337c0463b0a3893tuexen	zone_mbuf = umem_cache_create(MBUF_MEM_NAME, MSIZE, 0, NULL, NULL, NULL, NULL, NULL, 0);*/
349bca1dae6587a640359abee04337c0463b0a3893tuexen#if defined(SCTP_SIMPLE_ALLOCATOR)
350bca1dae6587a640359abee04337c0463b0a3893tuexen	SCTP_ZONE_INIT(zone_mbuf, MBUF_MEM_NAME, MSIZE, 0);
351bca1dae6587a640359abee04337c0463b0a3893tuexen#else
352bca1dae6587a640359abee04337c0463b0a3893tuexen	zone_mbuf = umem_cache_create(MBUF_MEM_NAME, MSIZE, 0,
3539b332c241dd6df73b563594af7c334e23f5e42b8t	                              mb_ctor_mbuf, mb_dtor_mbuf, NULL,
3549b332c241dd6df73b563594af7c334e23f5e42b8t	                              NUULL,
3559b332c241dd6df73b563594af7c334e23f5e42b8t	                              NULL, 0);
356bca1dae6587a640359abee04337c0463b0a3893tuexen#endif
357bca1dae6587a640359abee04337c0463b0a3893tuexen	/*zone_ext_refcnt = umem_cache_create(MBUF_EXTREFCNT_MEM_NAME, sizeof(u_int), 0,
35842d0ec7a8a09fcaa90b491d267245606c7caa7edtuexen				NULL, NULL, NULL,
359bca1dae6587a640359abee04337c0463b0a3893tuexen				NULL,
360bca1dae6587a640359abee04337c0463b0a3893tuexen				NULL, 0);*/
361bca1dae6587a640359abee04337c0463b0a3893tuexen	SCTP_ZONE_INIT(zone_ext_refcnt, MBUF_EXTREFCNT_MEM_NAME, sizeof(u_int), 0);
36242d0ec7a8a09fcaa90b491d267245606c7caa7edtuexen
363bca1dae6587a640359abee04337c0463b0a3893tuexen  /*zone_clust = umem_cache_create(MBUF_CLUSTER_MEM_NAME, MCLBYTES, 0,
364bca1dae6587a640359abee04337c0463b0a3893tuexen				 mb_ctor_clust, mb_dtor_clust, NULL,
365bca1dae6587a640359abee04337c0463b0a3893tuexen				 &clust_mb_args,
366bca1dae6587a640359abee04337c0463b0a3893tuexen				 NULL, 0);
367bca1dae6587a640359abee04337c0463b0a3893tuexen	zone_clust = umem_cache_create(MBUF_CLUSTER_MEM_NAME, MCLBYTES, 0, NULL, NULL, NULL, NULL, NULL,0);*/
368bca1dae6587a640359abee04337c0463b0a3893tuexen#if defined(SCTP_SIMPLE_ALLOCATOR)
369bca1dae6587a640359abee04337c0463b0a3893tuexen	SCTP_ZONE_INIT(zone_clust, MBUF_CLUSTER_MEM_NAME, MCLBYTES, 0);
370bca1dae6587a640359abee04337c0463b0a3893tuexen#else
371bca1dae6587a640359abee04337c0463b0a3893tuexen	zone_clust = umem_cache_create(MBUF_CLUSTER_MEM_NAME, MCLBYTES, 0,
372bca1dae6587a640359abee04337c0463b0a3893tuexen								   mb_ctor_clust, mb_dtor_clust, NULL,
373bca1dae6587a640359abee04337c0463b0a3893tuexen								   &clust_mb_args,
374bca1dae6587a640359abee04337c0463b0a3893tuexen								   NULL, 0);
375bca1dae6587a640359abee04337c0463b0a3893tuexen#endif
376bca1dae6587a640359abee04337c0463b0a3893tuexen
377bca1dae6587a640359abee04337c0463b0a3893tuexen	/* uma_prealloc() goes here... */
378bca1dae6587a640359abee04337c0463b0a3893tuexen
379bca1dae6587a640359abee04337c0463b0a3893tuexen	/* __Userspace__ Add umem_reap here for low memory situation?
380bca1dae6587a640359abee04337c0463b0a3893tuexen	 *
381bca1dae6587a640359abee04337c0463b0a3893tuexen	 */
38242d0ec7a8a09fcaa90b491d267245606c7caa7edtuexen
383bca1dae6587a640359abee04337c0463b0a3893tuexen
384bca1dae6587a640359abee04337c0463b0a3893tuexen	/*
385bca1dae6587a640359abee04337c0463b0a3893tuexen	 * [Re]set counters and local statistics knobs.
38642d0ec7a8a09fcaa90b491d267245606c7caa7edtuexen	 *
387bca1dae6587a640359abee04337c0463b0a3893tuexen	 */
38842d0ec7a8a09fcaa90b491d267245606c7caa7edtuexen
389bca1dae6587a640359abee04337c0463b0a3893tuexen	mbstat.m_mbufs = 0;
390bca1dae6587a640359abee04337c0463b0a3893tuexen	mbstat.m_mclusts = 0;
391bca1dae6587a640359abee04337c0463b0a3893tuexen	mbstat.m_drain = 0;
392bca1dae6587a640359abee04337c0463b0a3893tuexen	mbstat.m_msize = MSIZE;
393bca1dae6587a640359abee04337c0463b0a3893tuexen	mbstat.m_mclbytes = MCLBYTES;
394bca1dae6587a640359abee04337c0463b0a3893tuexen	mbstat.m_minclsize = MINCLSIZE;
395bca1dae6587a640359abee04337c0463b0a3893tuexen	mbstat.m_mlen = MLEN;
396bca1dae6587a640359abee04337c0463b0a3893tuexen	mbstat.m_mhlen = MHLEN;
397bca1dae6587a640359abee04337c0463b0a3893tuexen	mbstat.m_numtypes = MT_NTYPES;
398bca1dae6587a640359abee04337c0463b0a3893tuexen
399bca1dae6587a640359abee04337c0463b0a3893tuexen	mbstat.m_mcfail = mbstat.m_mpfail = 0;
400bca1dae6587a640359abee04337c0463b0a3893tuexen	mbstat.sf_iocnt = 0;
401bca1dae6587a640359abee04337c0463b0a3893tuexen	mbstat.sf_allocwait = mbstat.sf_allocfail = 0;
40242d0ec7a8a09fcaa90b491d267245606c7caa7edtuexen
403bca1dae6587a640359abee04337c0463b0a3893tuexen}
404bca1dae6587a640359abee04337c0463b0a3893tuexen
405bca1dae6587a640359abee04337c0463b0a3893tuexen
406bca1dae6587a640359abee04337c0463b0a3893tuexen
407bca1dae6587a640359abee04337c0463b0a3893tuexen/*
408bca1dae6587a640359abee04337c0463b0a3893tuexen * __Userspace__
409bca1dae6587a640359abee04337c0463b0a3893tuexen *
410bca1dae6587a640359abee04337c0463b0a3893tuexen * Constructor for Mbuf master zone. We have a different constructor
411bca1dae6587a640359abee04337c0463b0a3893tuexen * for allocating the cluster.
412bca1dae6587a640359abee04337c0463b0a3893tuexen *
413bca1dae6587a640359abee04337c0463b0a3893tuexen * The 'arg' pointer points to a mb_args structure which
414bca1dae6587a640359abee04337c0463b0a3893tuexen * contains call-specific information required to support the
415bca1dae6587a640359abee04337c0463b0a3893tuexen * mbuf allocation API.  See user_mbuf.h.
416bca1dae6587a640359abee04337c0463b0a3893tuexen *
417bca1dae6587a640359abee04337c0463b0a3893tuexen * The flgs parameter below can be UMEM_DEFAULT or UMEM_NOFAIL depending on what
418bca1dae6587a640359abee04337c0463b0a3893tuexen * was passed when umem_cache_alloc was called.
419bca1dae6587a640359abee04337c0463b0a3893tuexen * TODO: Use UMEM_NOFAIL in umem_cache_alloc and also define a failure handler
420bca1dae6587a640359abee04337c0463b0a3893tuexen * and call umem_nofail_callback(my_failure_handler) in the stack initialization routines
42142d0ec7a8a09fcaa90b491d267245606c7caa7edtuexen * The advantage of using UMEM_NOFAIL is that we don't have to check if umem_cache_alloc
422bca1dae6587a640359abee04337c0463b0a3893tuexen * was successful or not. The failure handler would take care of it, if we use the UMEM_NOFAIL
423bca1dae6587a640359abee04337c0463b0a3893tuexen * flag.
42442d0ec7a8a09fcaa90b491d267245606c7caa7edtuexen *
425bca1dae6587a640359abee04337c0463b0a3893tuexen * NOTE Ref: http://docs.sun.com/app/docs/doc/819-2243/6n4i099p2?l=en&a=view&q=umem_zalloc)
426bca1dae6587a640359abee04337c0463b0a3893tuexen * The umem_nofail_callback() function sets the **process-wide** UMEM_NOFAIL callback.
427bca1dae6587a640359abee04337c0463b0a3893tuexen * It also mentions that umem_nofail_callback is Evolving.
42842d0ec7a8a09fcaa90b491d267245606c7caa7edtuexen *
429bca1dae6587a640359abee04337c0463b0a3893tuexen */
430bca1dae6587a640359abee04337c0463b0a3893tuexenstatic int
431bca1dae6587a640359abee04337c0463b0a3893tuexenmb_ctor_mbuf(void *mem, void *arg, int flgs)
432bca1dae6587a640359abee04337c0463b0a3893tuexen{
43342d0ec7a8a09fcaa90b491d267245606c7caa7edtuexen#if USING_MBUF_CONSTRUCTOR
434bca1dae6587a640359abee04337c0463b0a3893tuexen	struct mbuf *m;
435bca1dae6587a640359abee04337c0463b0a3893tuexen	struct mb_args *args;
436bca1dae6587a640359abee04337c0463b0a3893tuexen
437bca1dae6587a640359abee04337c0463b0a3893tuexen	int flags;
438bca1dae6587a640359abee04337c0463b0a3893tuexen	short type;
439bca1dae6587a640359abee04337c0463b0a3893tuexen
440bca1dae6587a640359abee04337c0463b0a3893tuexen	m = (struct mbuf *)mem;
441bca1dae6587a640359abee04337c0463b0a3893tuexen	args = (struct mb_args *)arg;
442bca1dae6587a640359abee04337c0463b0a3893tuexen	flags = args->flags;
443bca1dae6587a640359abee04337c0463b0a3893tuexen	type = args->type;
444bca1dae6587a640359abee04337c0463b0a3893tuexen
445bca1dae6587a640359abee04337c0463b0a3893tuexen	/*
44642d0ec7a8a09fcaa90b491d267245606c7caa7edtuexen	 * The mbuf is initialized later.
44742d0ec7a8a09fcaa90b491d267245606c7caa7edtuexen	 *
448bca1dae6587a640359abee04337c0463b0a3893tuexen	 */
449bca1dae6587a640359abee04337c0463b0a3893tuexen	if (type == MT_NOINIT)
450bca1dae6587a640359abee04337c0463b0a3893tuexen		return (0);
451bca1dae6587a640359abee04337c0463b0a3893tuexen
452bca1dae6587a640359abee04337c0463b0a3893tuexen	m->m_next = NULL;
453bca1dae6587a640359abee04337c0463b0a3893tuexen	m->m_nextpkt = NULL;
454bca1dae6587a640359abee04337c0463b0a3893tuexen	m->m_len = 0;
455bca1dae6587a640359abee04337c0463b0a3893tuexen	m->m_flags = flags;
456bca1dae6587a640359abee04337c0463b0a3893tuexen	m->m_type = type;
457bca1dae6587a640359abee04337c0463b0a3893tuexen	if (flags & M_PKTHDR) {
458bca1dae6587a640359abee04337c0463b0a3893tuexen		m->m_data = m->m_pktdat;
459bca1dae6587a640359abee04337c0463b0a3893tuexen		m->m_pkthdr.rcvif = NULL;
460bca1dae6587a640359abee04337c0463b0a3893tuexen		m->m_pkthdr.len = 0;
461bca1dae6587a640359abee04337c0463b0a3893tuexen		m->m_pkthdr.header = NULL;
462bca1dae6587a640359abee04337c0463b0a3893tuexen		m->m_pkthdr.csum_flags = 0;
463bca1dae6587a640359abee04337c0463b0a3893tuexen		m->m_pkthdr.csum_data = 0;
464bca1dae6587a640359abee04337c0463b0a3893tuexen		m->m_pkthdr.tso_segsz = 0;
465bca1dae6587a640359abee04337c0463b0a3893tuexen		m->m_pkthdr.ether_vtag = 0;
466bca1dae6587a640359abee04337c0463b0a3893tuexen		SLIST_INIT(&m->m_pkthdr.tags);
467bca1dae6587a640359abee04337c0463b0a3893tuexen	} else
468bca1dae6587a640359abee04337c0463b0a3893tuexen		m->m_data = m->m_dat;
469bca1dae6587a640359abee04337c0463b0a3893tuexen#endif
470bca1dae6587a640359abee04337c0463b0a3893tuexen	return (0);
471bca1dae6587a640359abee04337c0463b0a3893tuexen}
472bca1dae6587a640359abee04337c0463b0a3893tuexen
473bca1dae6587a640359abee04337c0463b0a3893tuexen
474bca1dae6587a640359abee04337c0463b0a3893tuexen/*
475bca1dae6587a640359abee04337c0463b0a3893tuexen * __Userspace__
476bca1dae6587a640359abee04337c0463b0a3893tuexen * The Mbuf master zone destructor.
477bca1dae6587a640359abee04337c0463b0a3893tuexen * This would be called in response to umem_cache_destroy
478bca1dae6587a640359abee04337c0463b0a3893tuexen * TODO: Recheck if this is what we want to do in this destructor.
479bca1dae6587a640359abee04337c0463b0a3893tuexen * (Note: the number of times mb_dtor_mbuf is called is equal to the
480bca1dae6587a640359abee04337c0463b0a3893tuexen * number of individual mbufs allocated from zone_mbuf.
481bca1dae6587a640359abee04337c0463b0a3893tuexen */
482bca1dae6587a640359abee04337c0463b0a3893tuexenstatic void
483bca1dae6587a640359abee04337c0463b0a3893tuexenmb_dtor_mbuf(void *mem, void *arg)
484bca1dae6587a640359abee04337c0463b0a3893tuexen{
485bca1dae6587a640359abee04337c0463b0a3893tuexen	struct mbuf *m;
486bca1dae6587a640359abee04337c0463b0a3893tuexen
487bca1dae6587a640359abee04337c0463b0a3893tuexen	m = (struct mbuf *)mem;
4889b332c241dd6df73b563594af7c334e23f5e42b8t	if ((m->m_flags & M_PKTHDR) != 0) {
489bca1dae6587a640359abee04337c0463b0a3893tuexen		m_tag_delete_chain(m, NULL);
490c7108437de5af4d0b9f9a24979710b39197ec6cetuexen	}
491bca1dae6587a640359abee04337c0463b0a3893tuexen}
492bca1dae6587a640359abee04337c0463b0a3893tuexen
493bca1dae6587a640359abee04337c0463b0a3893tuexen
494bca1dae6587a640359abee04337c0463b0a3893tuexen/* __Userspace__
495bca1dae6587a640359abee04337c0463b0a3893tuexen * The Cluster zone constructor.
496bca1dae6587a640359abee04337c0463b0a3893tuexen *
497bca1dae6587a640359abee04337c0463b0a3893tuexen * Here the 'arg' pointer points to the Mbuf which we
498bca1dae6587a640359abee04337c0463b0a3893tuexen * are configuring cluster storage for.  If 'arg' is
499bca1dae6587a640359abee04337c0463b0a3893tuexen * empty we allocate just the cluster without setting
500bca1dae6587a640359abee04337c0463b0a3893tuexen * the mbuf to it.  See mbuf.h.
501bca1dae6587a640359abee04337c0463b0a3893tuexen */
502bca1dae6587a640359abee04337c0463b0a3893tuexenstatic int
503bca1dae6587a640359abee04337c0463b0a3893tuexenmb_ctor_clust(void *mem, void *arg, int flgs)
504bca1dae6587a640359abee04337c0463b0a3893tuexen{
50542d0ec7a8a09fcaa90b491d267245606c7caa7edtuexen
50642d0ec7a8a09fcaa90b491d267245606c7caa7edtuexen#if USING_MBUF_CONSTRUCTOR
507bca1dae6587a640359abee04337c0463b0a3893tuexen	struct mbuf *m;
508bca1dae6587a640359abee04337c0463b0a3893tuexen	struct clust_args * cla;
509bca1dae6587a640359abee04337c0463b0a3893tuexen	u_int *refcnt;
510bca1dae6587a640359abee04337c0463b0a3893tuexen	int type, size;
511bca1dae6587a640359abee04337c0463b0a3893tuexen	sctp_zone_t zone;
51242d0ec7a8a09fcaa90b491d267245606c7caa7edtuexen
513bca1dae6587a640359abee04337c0463b0a3893tuexen	/* Assigning cluster of MCLBYTES. TODO: Add jumbo frame functionality */
514bca1dae6587a640359abee04337c0463b0a3893tuexen	type = EXT_CLUSTER;
515bca1dae6587a640359abee04337c0463b0a3893tuexen	zone = zone_clust;
516bca1dae6587a640359abee04337c0463b0a3893tuexen	size = MCLBYTES;
517bca1dae6587a640359abee04337c0463b0a3893tuexen
518bca1dae6587a640359abee04337c0463b0a3893tuexen	cla = (struct clust_args *)arg;
519bca1dae6587a640359abee04337c0463b0a3893tuexen	m = cla->parent_mbuf;
520bca1dae6587a640359abee04337c0463b0a3893tuexen
521bca1dae6587a640359abee04337c0463b0a3893tuexen	refcnt = SCTP_ZONE_GET(zone_ext_refcnt, u_int);
522bca1dae6587a640359abee04337c0463b0a3893tuexen	/*refcnt = (u_int *)umem_cache_alloc(zone_ext_refcnt, UMEM_DEFAULT);*/
523bca1dae6587a640359abee04337c0463b0a3893tuexen	*refcnt = 1;
524bca1dae6587a640359abee04337c0463b0a3893tuexen
525bca1dae6587a640359abee04337c0463b0a3893tuexen	if (m != NULL) {
526bca1dae6587a640359abee04337c0463b0a3893tuexen		m->m_ext.ext_buf = (caddr_t)mem;
527bca1dae6587a640359abee04337c0463b0a3893tuexen		m->m_data = m->m_ext.ext_buf;
528bca1dae6587a640359abee04337c0463b0a3893tuexen		m->m_flags |= M_EXT;
529bca1dae6587a640359abee04337c0463b0a3893tuexen		m->m_ext.ext_free = NULL;
530bca1dae6587a640359abee04337c0463b0a3893tuexen		m->m_ext.ext_args = NULL;
53142d0ec7a8a09fcaa90b491d267245606c7caa7edtuexen		m->m_ext.ext_size = size;
532bca1dae6587a640359abee04337c0463b0a3893tuexen		m->m_ext.ext_type = type;
533bca1dae6587a640359abee04337c0463b0a3893tuexen		m->m_ext.ref_cnt = refcnt;
534bca1dae6587a640359abee04337c0463b0a3893tuexen	}
535bca1dae6587a640359abee04337c0463b0a3893tuexen#endif
536bca1dae6587a640359abee04337c0463b0a3893tuexen	return (0);
537bca1dae6587a640359abee04337c0463b0a3893tuexen}
538bca1dae6587a640359abee04337c0463b0a3893tuexen
539bca1dae6587a640359abee04337c0463b0a3893tuexen/* __Userspace__ */
540bca1dae6587a640359abee04337c0463b0a3893tuexenstatic void
541bca1dae6587a640359abee04337c0463b0a3893tuexenmb_dtor_clust(void *mem, void *arg)
542bca1dae6587a640359abee04337c0463b0a3893tuexen{
54342d0ec7a8a09fcaa90b491d267245606c7caa7edtuexen
544bca1dae6587a640359abee04337c0463b0a3893tuexen  /* mem is of type caddr_t.  In sys/types.h we have typedef char * caddr_t;  */
545bca1dae6587a640359abee04337c0463b0a3893tuexen  /* mb_dtor_clust is called at time of umem_cache_destroy() (the number of times
54642d0ec7a8a09fcaa90b491d267245606c7caa7edtuexen   * mb_dtor_clust is called is equal to the number of individual mbufs allocated
547bca1dae6587a640359abee04337c0463b0a3893tuexen   * from zone_clust. Similarly for mb_dtor_mbuf).
548bca1dae6587a640359abee04337c0463b0a3893tuexen   * At this point the following:
549bca1dae6587a640359abee04337c0463b0a3893tuexen   *  struct mbuf *m;
550bca1dae6587a640359abee04337c0463b0a3893tuexen   *   m = (struct mbuf *)arg;
551bca1dae6587a640359abee04337c0463b0a3893tuexen   *  assert (*(m->m_ext.ref_cnt) == 0); is not meaningful since  m->m_ext.ref_cnt = NULL;
552bca1dae6587a640359abee04337c0463b0a3893tuexen   *  has been done in mb_free_ext().
553bca1dae6587a640359abee04337c0463b0a3893tuexen   */
554bca1dae6587a640359abee04337c0463b0a3893tuexen
555bca1dae6587a640359abee04337c0463b0a3893tuexen}
556bca1dae6587a640359abee04337c0463b0a3893tuexen
557bca1dae6587a640359abee04337c0463b0a3893tuexen
558bca1dae6587a640359abee04337c0463b0a3893tuexen
559bca1dae6587a640359abee04337c0463b0a3893tuexen
560bca1dae6587a640359abee04337c0463b0a3893tuexen/* Unlink and free a packet tag. */
561bca1dae6587a640359abee04337c0463b0a3893tuexenvoid
562bca1dae6587a640359abee04337c0463b0a3893tuexenm_tag_delete(struct mbuf *m, struct m_tag *t)
563bca1dae6587a640359abee04337c0463b0a3893tuexen{
564e7eb46f39b8bfc4b5ed9b708232c1c669c06842bt	KASSERT(m && t, ("m_tag_delete: null argument, m %p t %p", (void *)m, (void *)t));
565bca1dae6587a640359abee04337c0463b0a3893tuexen	m_tag_unlink(m, t);
566bca1dae6587a640359abee04337c0463b0a3893tuexen	m_tag_free(t);
567bca1dae6587a640359abee04337c0463b0a3893tuexen}
568bca1dae6587a640359abee04337c0463b0a3893tuexen
569bca1dae6587a640359abee04337c0463b0a3893tuexen
570bca1dae6587a640359abee04337c0463b0a3893tuexen/* Unlink and free a packet tag chain, starting from given tag. */
571bca1dae6587a640359abee04337c0463b0a3893tuexenvoid
572bca1dae6587a640359abee04337c0463b0a3893tuexenm_tag_delete_chain(struct mbuf *m, struct m_tag *t)
573bca1dae6587a640359abee04337c0463b0a3893tuexen{
57442d0ec7a8a09fcaa90b491d267245606c7caa7edtuexen
575bca1dae6587a640359abee04337c0463b0a3893tuexen	struct m_tag *p, *q;
576bca1dae6587a640359abee04337c0463b0a3893tuexen
577c7108437de5af4d0b9f9a24979710b39197ec6cetuexen	KASSERT(m, ("m_tag_delete_chain: null mbuf"));
578bca1dae6587a640359abee04337c0463b0a3893tuexen	if (t != NULL)
579bca1dae6587a640359abee04337c0463b0a3893tuexen		p = t;
580bca1dae6587a640359abee04337c0463b0a3893tuexen	else
581bca1dae6587a640359abee04337c0463b0a3893tuexen		p = SLIST_FIRST(&m->m_pkthdr.tags);
582bca1dae6587a640359abee04337c0463b0a3893tuexen	if (p == NULL)
583bca1dae6587a640359abee04337c0463b0a3893tuexen		return;
584bca1dae6587a640359abee04337c0463b0a3893tuexen	while ((q = SLIST_NEXT(p, m_tag_link)) != NULL)
585bca1dae6587a640359abee04337c0463b0a3893tuexen		m_tag_delete(m, q);
586bca1dae6587a640359abee04337c0463b0a3893tuexen	m_tag_delete(m, p);
587bca1dae6587a640359abee04337c0463b0a3893tuexen}
588bca1dae6587a640359abee04337c0463b0a3893tuexen
589bca1dae6587a640359abee04337c0463b0a3893tuexen#if 0
590bca1dae6587a640359abee04337c0463b0a3893tuexenstatic void
591bca1dae6587a640359abee04337c0463b0a3893tuexensctp_print_mbuf_chain(struct mbuf *m)
592bca1dae6587a640359abee04337c0463b0a3893tuexen{
593e7eb46f39b8bfc4b5ed9b708232c1c669c06842bt	SCTP_DEBUG_USR(SCTP_DEBUG_USR, "Printing mbuf chain %p.\n", (void *)m);
594bca1dae6587a640359abee04337c0463b0a3893tuexen	for(; m; m=m->m_next) {
595e7eb46f39b8bfc4b5ed9b708232c1c669c06842bt		SCTP_DEBUG_USR(SCTP_DEBUG_USR, "%p: m_len = %ld, m_type = %x, m_next = %p.\n", (void *)m, m->m_len, m->m_type, (void *)m->m_next);
596bca1dae6587a640359abee04337c0463b0a3893tuexen		if (m->m_flags & M_EXT)
597e7eb46f39b8bfc4b5ed9b708232c1c669c06842bt			SCTP_DEBUG_USR(SCTP_DEBUG_USR, "%p: extend_size = %d, extend_buffer = %p, ref_cnt = %d.\n", (void *)m, m->m_ext.ext_size, (void *)m->m_ext.ext_buf, *(m->m_ext.ref_cnt));
59842d0ec7a8a09fcaa90b491d267245606c7caa7edtuexen	}
599bca1dae6587a640359abee04337c0463b0a3893tuexen}
600bca1dae6587a640359abee04337c0463b0a3893tuexen#endif
601bca1dae6587a640359abee04337c0463b0a3893tuexen
602bca1dae6587a640359abee04337c0463b0a3893tuexen/*
603bca1dae6587a640359abee04337c0463b0a3893tuexen * Free an entire chain of mbufs and associated external buffers, if
604bca1dae6587a640359abee04337c0463b0a3893tuexen * applicable.
605bca1dae6587a640359abee04337c0463b0a3893tuexen */
606bca1dae6587a640359abee04337c0463b0a3893tuexenvoid
607bca1dae6587a640359abee04337c0463b0a3893tuexenm_freem(struct mbuf *mb)
608bca1dae6587a640359abee04337c0463b0a3893tuexen{
609bca1dae6587a640359abee04337c0463b0a3893tuexen	while (mb != NULL)
610bca1dae6587a640359abee04337c0463b0a3893tuexen		mb = m_free(mb);
611bca1dae6587a640359abee04337c0463b0a3893tuexen}
612bca1dae6587a640359abee04337c0463b0a3893tuexen
613bca1dae6587a640359abee04337c0463b0a3893tuexen/*
614bca1dae6587a640359abee04337c0463b0a3893tuexen * __Userspace__
61542d0ec7a8a09fcaa90b491d267245606c7caa7edtuexen * clean mbufs with M_EXT storage attached to them
616bca1dae6587a640359abee04337c0463b0a3893tuexen * if the reference count hits 1.
617bca1dae6587a640359abee04337c0463b0a3893tuexen */
618bca1dae6587a640359abee04337c0463b0a3893tuexenvoid
619bca1dae6587a640359abee04337c0463b0a3893tuexenmb_free_ext(struct mbuf *m)
620bca1dae6587a640359abee04337c0463b0a3893tuexen{
62142d0ec7a8a09fcaa90b491d267245606c7caa7edtuexen
622bca1dae6587a640359abee04337c0463b0a3893tuexen	int skipmbuf;
62342d0ec7a8a09fcaa90b491d267245606c7caa7edtuexen
624c7108437de5af4d0b9f9a24979710b39197ec6cetuexen	KASSERT((m->m_flags & M_EXT) == M_EXT, ("%s: M_EXT not set", __func__));
625c7108437de5af4d0b9f9a24979710b39197ec6cetuexen	KASSERT(m->m_ext.ref_cnt != NULL, ("%s: ref_cnt not set", __func__));
626bca1dae6587a640359abee04337c0463b0a3893tuexen
627bca1dae6587a640359abee04337c0463b0a3893tuexen	/*
628bca1dae6587a640359abee04337c0463b0a3893tuexen	 * check if the header is embedded in the cluster
62942d0ec7a8a09fcaa90b491d267245606c7caa7edtuexen	 */
630bca1dae6587a640359abee04337c0463b0a3893tuexen	skipmbuf = (m->m_flags & M_NOFREE);
631bca1dae6587a640359abee04337c0463b0a3893tuexen
63242d0ec7a8a09fcaa90b491d267245606c7caa7edtuexen	/* Free the external attached storage if this
63342d0ec7a8a09fcaa90b491d267245606c7caa7edtuexen	 * mbuf is the only reference to it.
634bca1dae6587a640359abee04337c0463b0a3893tuexen	 *__Userspace__ TODO: jumbo frames
63542d0ec7a8a09fcaa90b491d267245606c7caa7edtuexen	 *
636bca1dae6587a640359abee04337c0463b0a3893tuexen	*/
637c7108437de5af4d0b9f9a24979710b39197ec6cetuexen	/* NOTE: We had the same code that SCTP_DECREMENT_AND_CHECK_REFCOUNT
638c7108437de5af4d0b9f9a24979710b39197ec6cetuexen	         reduces to here before but the IPHONE malloc commit had changed
639c7108437de5af4d0b9f9a24979710b39197ec6cetuexen	         this to compare to 0 instead of 1 (see next line).  Why?
640c7108437de5af4d0b9f9a24979710b39197ec6cetuexen	        . .. this caused a huge memory leak in Linux.
641c7108437de5af4d0b9f9a24979710b39197ec6cetuexen	*/
642bca1dae6587a640359abee04337c0463b0a3893tuexen#ifdef IPHONE
643c7108437de5af4d0b9f9a24979710b39197ec6cetuexen	if (atomic_fetchadd_int(m->m_ext.ref_cnt, -1) == 0)
644bca1dae6587a640359abee04337c0463b0a3893tuexen#else
645c7108437de5af4d0b9f9a24979710b39197ec6cetuexen	if (SCTP_DECREMENT_AND_CHECK_REFCOUNT(m->m_ext.ref_cnt))
646bca1dae6587a640359abee04337c0463b0a3893tuexen#endif
647c7108437de5af4d0b9f9a24979710b39197ec6cetuexen	{
648bca1dae6587a640359abee04337c0463b0a3893tuexen		if (m->m_ext.ext_type == EXT_CLUSTER){
649bca1dae6587a640359abee04337c0463b0a3893tuexen#if defined(SCTP_SIMPLE_ALLOCATOR)
650bca1dae6587a640359abee04337c0463b0a3893tuexen			mb_dtor_clust(m->m_ext.ext_buf, &clust_mb_args);
651bca1dae6587a640359abee04337c0463b0a3893tuexen#endif
652bca1dae6587a640359abee04337c0463b0a3893tuexen			SCTP_ZONE_FREE(zone_clust, m->m_ext.ext_buf);
653bca1dae6587a640359abee04337c0463b0a3893tuexen			SCTP_ZONE_FREE(zone_ext_refcnt, (u_int*)m->m_ext.ref_cnt);
654bca1dae6587a640359abee04337c0463b0a3893tuexen			m->m_ext.ref_cnt = NULL;
655bca1dae6587a640359abee04337c0463b0a3893tuexen		}
656c7108437de5af4d0b9f9a24979710b39197ec6cetuexen	}
65742d0ec7a8a09fcaa90b491d267245606c7caa7edtuexen
658bca1dae6587a640359abee04337c0463b0a3893tuexen	if (skipmbuf)
659bca1dae6587a640359abee04337c0463b0a3893tuexen		return;
660bca1dae6587a640359abee04337c0463b0a3893tuexen
66142d0ec7a8a09fcaa90b491d267245606c7caa7edtuexen
662bca1dae6587a640359abee04337c0463b0a3893tuexen	/* __Userspace__ Also freeing the storage for ref_cnt
663bca1dae6587a640359abee04337c0463b0a3893tuexen	 * Free this mbuf back to the mbuf zone with all m_ext
664bca1dae6587a640359abee04337c0463b0a3893tuexen	 * information purged.
665bca1dae6587a640359abee04337c0463b0a3893tuexen	 */
666bca1dae6587a640359abee04337c0463b0a3893tuexen	m->m_ext.ext_buf = NULL;
667bca1dae6587a640359abee04337c0463b0a3893tuexen	m->m_ext.ext_free = NULL;
668bca1dae6587a640359abee04337c0463b0a3893tuexen	m->m_ext.ext_args = NULL;
669bca1dae6587a640359abee04337c0463b0a3893tuexen	m->m_ext.ref_cnt = NULL;
670bca1dae6587a640359abee04337c0463b0a3893tuexen	m->m_ext.ext_size = 0;
671bca1dae6587a640359abee04337c0463b0a3893tuexen	m->m_ext.ext_type = 0;
672bca1dae6587a640359abee04337c0463b0a3893tuexen	m->m_flags &= ~M_EXT;
673bca1dae6587a640359abee04337c0463b0a3893tuexen#if defined(SCTP_SIMPLE_ALLOCATOR)
6749b332c241dd6df73b563594af7c334e23f5e42b8t	mb_dtor_mbuf(m, NULL);
675bca1dae6587a640359abee04337c0463b0a3893tuexen#endif
676bca1dae6587a640359abee04337c0463b0a3893tuexen	SCTP_ZONE_FREE(zone_mbuf, m);
67742d0ec7a8a09fcaa90b491d267245606c7caa7edtuexen
678bca1dae6587a640359abee04337c0463b0a3893tuexen	/*umem_cache_free(zone_mbuf, m);*/
679bca1dae6587a640359abee04337c0463b0a3893tuexen}
680bca1dae6587a640359abee04337c0463b0a3893tuexen
681bca1dae6587a640359abee04337c0463b0a3893tuexen/*
682bca1dae6587a640359abee04337c0463b0a3893tuexen * "Move" mbuf pkthdr from "from" to "to".
683bca1dae6587a640359abee04337c0463b0a3893tuexen * "from" must have M_PKTHDR set, and "to" must be empty.
684bca1dae6587a640359abee04337c0463b0a3893tuexen */
685bca1dae6587a640359abee04337c0463b0a3893tuexenvoid
686bca1dae6587a640359abee04337c0463b0a3893tuexenm_move_pkthdr(struct mbuf *to, struct mbuf *from)
687bca1dae6587a640359abee04337c0463b0a3893tuexen{
688bca1dae6587a640359abee04337c0463b0a3893tuexen
689bca1dae6587a640359abee04337c0463b0a3893tuexen	to->m_flags = (from->m_flags & M_COPYFLAGS) | (to->m_flags & M_EXT);
690bca1dae6587a640359abee04337c0463b0a3893tuexen	if ((to->m_flags & M_EXT) == 0)
691bca1dae6587a640359abee04337c0463b0a3893tuexen		to->m_data = to->m_pktdat;
692bca1dae6587a640359abee04337c0463b0a3893tuexen	to->m_pkthdr = from->m_pkthdr;		/* especially tags */
693bca1dae6587a640359abee04337c0463b0a3893tuexen	SLIST_INIT(&from->m_pkthdr.tags);	/* purge tags from src */
694bca1dae6587a640359abee04337c0463b0a3893tuexen	from->m_flags &= ~M_PKTHDR;
695bca1dae6587a640359abee04337c0463b0a3893tuexen}
696bca1dae6587a640359abee04337c0463b0a3893tuexen
697bca1dae6587a640359abee04337c0463b0a3893tuexen
698bca1dae6587a640359abee04337c0463b0a3893tuexen/*
699bca1dae6587a640359abee04337c0463b0a3893tuexen * Rearange an mbuf chain so that len bytes are contiguous
700bca1dae6587a640359abee04337c0463b0a3893tuexen * and in the data area of an mbuf (so that mtod and dtom
701bca1dae6587a640359abee04337c0463b0a3893tuexen * will work for a structure of size len).  Returns the resulting
702bca1dae6587a640359abee04337c0463b0a3893tuexen * mbuf chain on success, frees it and returns null on failure.
703bca1dae6587a640359abee04337c0463b0a3893tuexen * If there is room, it will add up to max_protohdr-len extra bytes to the
704bca1dae6587a640359abee04337c0463b0a3893tuexen * contiguous region in an attempt to avoid being called next time.
705bca1dae6587a640359abee04337c0463b0a3893tuexen */
706bca1dae6587a640359abee04337c0463b0a3893tuexenstruct mbuf *
707bca1dae6587a640359abee04337c0463b0a3893tuexenm_pullup(struct mbuf *n, int len)
708bca1dae6587a640359abee04337c0463b0a3893tuexen{
709bca1dae6587a640359abee04337c0463b0a3893tuexen	struct mbuf *m;
710bca1dae6587a640359abee04337c0463b0a3893tuexen	int count;
711bca1dae6587a640359abee04337c0463b0a3893tuexen	int space;
712bca1dae6587a640359abee04337c0463b0a3893tuexen
713bca1dae6587a640359abee04337c0463b0a3893tuexen	/*
714bca1dae6587a640359abee04337c0463b0a3893tuexen	 * If first mbuf has no cluster, and has room for len bytes
715bca1dae6587a640359abee04337c0463b0a3893tuexen	 * without shifting current data, pullup into it,
716bca1dae6587a640359abee04337c0463b0a3893tuexen	 * otherwise allocate a new mbuf to prepend to the chain.
717bca1dae6587a640359abee04337c0463b0a3893tuexen	 */
718bca1dae6587a640359abee04337c0463b0a3893tuexen	if ((n->m_flags & M_EXT) == 0 &&
719bca1dae6587a640359abee04337c0463b0a3893tuexen	    n->m_data + len < &n->m_dat[MLEN] && n->m_next) {
72007961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen		if (n->m_len >= len)
721bca1dae6587a640359abee04337c0463b0a3893tuexen			return (n);
722bca1dae6587a640359abee04337c0463b0a3893tuexen		m = n;
723bca1dae6587a640359abee04337c0463b0a3893tuexen		n = n->m_next;
724bca1dae6587a640359abee04337c0463b0a3893tuexen		len -= m->m_len;
725bca1dae6587a640359abee04337c0463b0a3893tuexen	} else {
726bca1dae6587a640359abee04337c0463b0a3893tuexen		if (len > MHLEN)
727bca1dae6587a640359abee04337c0463b0a3893tuexen			goto bad;
728218d5d0df143e859e241afb12d6aaa1e4969d714t		MGET(m, M_NOWAIT, n->m_type);
729bca1dae6587a640359abee04337c0463b0a3893tuexen		if (m == NULL)
730bca1dae6587a640359abee04337c0463b0a3893tuexen			goto bad;
731bca1dae6587a640359abee04337c0463b0a3893tuexen		m->m_len = 0;
732bca1dae6587a640359abee04337c0463b0a3893tuexen		if (n->m_flags & M_PKTHDR)
733bca1dae6587a640359abee04337c0463b0a3893tuexen			M_MOVE_PKTHDR(m, n);
734bca1dae6587a640359abee04337c0463b0a3893tuexen	}
735bca1dae6587a640359abee04337c0463b0a3893tuexen	space = &m->m_dat[MLEN] - (m->m_data + m->m_len);
736bca1dae6587a640359abee04337c0463b0a3893tuexen	do {
737bca1dae6587a640359abee04337c0463b0a3893tuexen		count = min(min(max(len, max_protohdr), space), n->m_len);
738bca1dae6587a640359abee04337c0463b0a3893tuexen		bcopy(mtod(n, caddr_t), mtod(m, caddr_t) + m->m_len,
739bca1dae6587a640359abee04337c0463b0a3893tuexen		  (u_int)count);
740bca1dae6587a640359abee04337c0463b0a3893tuexen		len -= count;
741bca1dae6587a640359abee04337c0463b0a3893tuexen		m->m_len += count;
742bca1dae6587a640359abee04337c0463b0a3893tuexen		n->m_len -= count;
743bca1dae6587a640359abee04337c0463b0a3893tuexen		space -= count;
744bca1dae6587a640359abee04337c0463b0a3893tuexen		if (n->m_len)
745bca1dae6587a640359abee04337c0463b0a3893tuexen			n->m_data += count;
746bca1dae6587a640359abee04337c0463b0a3893tuexen		else
747bca1dae6587a640359abee04337c0463b0a3893tuexen			n = m_free(n);
748bca1dae6587a640359abee04337c0463b0a3893tuexen	} while (len > 0 && n);
749bca1dae6587a640359abee04337c0463b0a3893tuexen	if (len > 0) {
750bca1dae6587a640359abee04337c0463b0a3893tuexen		(void) m_free(m);
751bca1dae6587a640359abee04337c0463b0a3893tuexen		goto bad;
752bca1dae6587a640359abee04337c0463b0a3893tuexen	}
753bca1dae6587a640359abee04337c0463b0a3893tuexen	m->m_next = n;
754bca1dae6587a640359abee04337c0463b0a3893tuexen	return (m);
755bca1dae6587a640359abee04337c0463b0a3893tuexenbad:
756bca1dae6587a640359abee04337c0463b0a3893tuexen	m_freem(n);
75707961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen	mbstat.m_mpfail++;	/* XXX: No consistency. */
758bca1dae6587a640359abee04337c0463b0a3893tuexen	return (NULL);
759bca1dae6587a640359abee04337c0463b0a3893tuexen}
760bca1dae6587a640359abee04337c0463b0a3893tuexen
761bca1dae6587a640359abee04337c0463b0a3893tuexen
76207961c43dc77daf1aa2b3258312d943f0eaa8b38tuexenstatic struct mbuf *
76307961c43dc77daf1aa2b3258312d943f0eaa8b38tuexenm_dup1(struct mbuf *m, int off, int len, int wait)
76407961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen{
765965e9dceb266b9896f53449746275e02b67e04b3tuexen	struct mbuf *n = NULL;
76607961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen	int copyhdr;
76707961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen
76807961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen	if (len > MCLBYTES)
76907961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen		return NULL;
77007961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen	if (off == 0 && (m->m_flags & M_PKTHDR) != 0)
77107961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen		copyhdr = 1;
77207961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen	else
77307961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen		copyhdr = 0;
77407961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen	if (len >= MINCLSIZE) {
7754c82d43c909753945d3f4f3fdcad271c2d8728eftuexen		if (copyhdr == 1) {
7764c82d43c909753945d3f4f3fdcad271c2d8728eftuexen			m_clget(n, wait); /* TODO: include code for copying the header */
7774c82d43c909753945d3f4f3fdcad271c2d8728eftuexen			m_dup_pkthdr(n, m, wait);
7784c82d43c909753945d3f4f3fdcad271c2d8728eftuexen		} else
7794c82d43c909753945d3f4f3fdcad271c2d8728eftuexen			m_clget(n, wait);
78007961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen	} else {
78107961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen		if (copyhdr == 1)
78207961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen			n = m_gethdr(wait, m->m_type);
78307961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen		else
78407961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen			n = m_get(wait, m->m_type);
78507961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen	}
78607961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen	if (!n)
78707961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen		return NULL; /* ENOBUFS */
78807961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen
78907961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen	if (copyhdr && !m_dup_pkthdr(n, m, wait)) {
79007961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen		m_free(n);
79107961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen		return NULL;
79207961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen	}
79307961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen	m_copydata(m, off, len, mtod(n, caddr_t));
79407961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen	n->m_len = len;
79507961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen	return n;
79607961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen}
79707961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen
79807961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen
79907961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen/* Taken from sys/kern/uipc_mbuf2.c */
80007961c43dc77daf1aa2b3258312d943f0eaa8b38tuexenstruct mbuf *
80107961c43dc77daf1aa2b3258312d943f0eaa8b38tuexenm_pulldown(struct mbuf *m, int off, int len, int *offp)
80207961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen{
80307961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen	struct mbuf *n, *o;
80407961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen	int hlen, tlen, olen;
80507961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen	int writable;
80607961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen
80707961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen	/* check invalid arguments. */
808edd4507cda024159552eb3574f9ba93766ea33d8tuexen	KASSERT(m, ("m == NULL in m_pulldown()"));
80907961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen	if (len > MCLBYTES) {
81007961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen		m_freem(m);
81107961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen		return NULL;    /* impossible */
81207961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen	}
81307961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen
81407961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen#ifdef PULLDOWN_DEBUG
81507961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen	{
81607961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen		struct mbuf *t;
817a1d7a8516e4d5b2136c5bb3d49aeac80271a36b0tuexen		SCTP_DEBUG_USR(SCTP_DEBUG_USR, "before:");
81807961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen		for (t = m; t; t = t->m_next)
819a1d7a8516e4d5b2136c5bb3d49aeac80271a36b0tuexen			SCTP_DEBUG_USR(SCTP_DEBUG_USR, " %d", t->m_len);
820a1d7a8516e4d5b2136c5bb3d49aeac80271a36b0tuexen		SCTP_DEBUG_USR(SCTP_DEBUG_USR, "\n");
82107961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen	}
82207961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen#endif
82307961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen	n = m;
82407961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen	while (n != NULL && off > 0) {
82507961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen		if (n->m_len > off)
82607961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen			break;
82707961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen		off -= n->m_len;
82807961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen		n = n->m_next;
82907961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen	}
83007961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen	/* be sure to point non-empty mbuf */
83107961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen	while (n != NULL && n->m_len == 0)
83207961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen		n = n->m_next;
83307961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen	if (!n) {
83407961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen		m_freem(m);
83507961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen		return NULL;    /* mbuf chain too short */
83607961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen	}
83707961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen
83807961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen	writable = 0;
83907961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen	if ((n->m_flags & M_EXT) == 0 ||
84007961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen	    (n->m_ext.ext_type == EXT_CLUSTER && M_WRITABLE(n)))
84107961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen		writable = 1;
84207961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen
84307961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen	/*
84407961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen	 * the target data is on <n, off>.
84507961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen	 * if we got enough data on the mbuf "n", we're done.
84607961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen	 */
84707961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen	if ((off == 0 || offp) && len <= n->m_len - off && writable)
84807961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen		goto ok;
84907961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen
85007961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen	/*
85107961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen	 * when len <= n->m_len - off and off != 0, it is a special case.
85207961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen	 * len bytes from <n, off> sits in single mbuf, but the caller does
85307961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen	 * not like the starting position (off).
85407961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen	 * chop the current mbuf into two pieces, set off to 0.
85507961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen	 */
85607961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen	if (len <= n->m_len - off) {
857218d5d0df143e859e241afb12d6aaa1e4969d714t		o = m_dup1(n, off, n->m_len - off, M_NOWAIT);
85807961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen		if (o == NULL) {
85907961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen			m_freem(m);
86007961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen		return NULL;    /* ENOBUFS */
86107961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen		}
86207961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen		n->m_len = off;
86307961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen		o->m_next = n->m_next;
86407961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen		n->m_next = o;
86507961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen		n = n->m_next;
86607961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen		off = 0;
86707961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen		goto ok;
86807961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen	}
86907961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen	/*
87007961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen	 * we need to take hlen from <n, off> and tlen from <n->m_next, 0>,
87107961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen	 * and construct contiguous mbuf with m_len == len.
87207961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen	 * note that hlen + tlen == len, and tlen > 0.
87307961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen	 */
87407961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen	hlen = n->m_len - off;
87507961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen	tlen = len - hlen;
87607961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen
87707961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen	/*
87807961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen	 * ensure that we have enough trailing data on mbuf chain.
87907961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen	 * if not, we can do nothing about the chain.
88007961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen	 */
88107961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen	olen = 0;
88207961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen	for (o = n->m_next; o != NULL; o = o->m_next)
88307961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen		olen += o->m_len;
88407961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen	if (hlen + olen < len) {
88507961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen		m_freem(m);
88607961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen		return NULL;    /* mbuf chain too short */
88707961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen	}
88807961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen
88907961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen	/*
89007961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen	 * easy cases first.
89107961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen	 * we need to use m_copydata() to get data from <n->m_next, 0>.
89207961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen	 */
89307961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen	if ((off == 0 || offp) && M_TRAILINGSPACE(n) >= tlen
89407961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen	    && writable) {
89507961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen		m_copydata(n->m_next, 0, tlen, mtod(n, caddr_t) + n->m_len);
89607961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen		n->m_len += tlen;
89707961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen		m_adj(n->m_next, tlen);
89807961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen		goto ok;
89907961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen	}
90007961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen
90107961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen	if ((off == 0 || offp) && M_LEADINGSPACE(n->m_next) >= hlen
90207961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen	    && writable) {
90307961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen		n->m_next->m_data -= hlen;
90407961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen		n->m_next->m_len += hlen;
90507961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen		bcopy(mtod(n, caddr_t) + off, mtod(n->m_next, caddr_t), hlen);
90607961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen		n->m_len -= hlen;
90707961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen		n = n->m_next;
90807961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen		off = 0;
90907961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen		goto ok;
91007961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen	}
91107961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen
91207961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen	/*
91307961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen	 * now, we need to do the hard way.  don't m_copy as there's no room
91407961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen	 * on both end.
91507961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen	 */
91607961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen	if (len > MLEN)
917218d5d0df143e859e241afb12d6aaa1e4969d714t		m_clget(o, M_NOWAIT);
918218d5d0df143e859e241afb12d6aaa1e4969d714t		/* o = m_getcl(M_NOWAIT, m->m_type, 0);*/
91907961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen	else
920218d5d0df143e859e241afb12d6aaa1e4969d714t		o = m_get(M_NOWAIT, m->m_type);
92107961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen	if (!o) {
92207961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen		m_freem(m);
92307961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen		return NULL;    /* ENOBUFS */
92407961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen	}
92507961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen	/* get hlen from <n, off> into <o, 0> */
92607961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen	o->m_len = hlen;
92707961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen	bcopy(mtod(n, caddr_t) + off, mtod(o, caddr_t), hlen);
92807961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen	n->m_len -= hlen;
92907961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen	/* get tlen from <n->m_next, 0> into <o, hlen> */
93007961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen	m_copydata(n->m_next, 0, tlen, mtod(o, caddr_t) + o->m_len);
93107961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen	o->m_len += tlen;
93207961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen	m_adj(n->m_next, tlen);
93307961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen	o->m_next = n->m_next;
93407961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen	n->m_next = o;
93507961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen	n = o;
93607961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen	off = 0;
93707961c43dc77daf1aa2b3258312d943f0eaa8b38tuexenok:
93807961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen#ifdef PULLDOWN_DEBUG
93907961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen	{
94007961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen		struct mbuf *t;
941a1d7a8516e4d5b2136c5bb3d49aeac80271a36b0tuexen		SCTP_DEBUG_USR(SCTP_DEBUG_USR, "after:");
94207961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen		for (t = m; t; t = t->m_next)
943a1d7a8516e4d5b2136c5bb3d49aeac80271a36b0tuexen			SCTP_DEBUG_USR(SCTP_DEBUG_USR, "%c%d", t == n ? '*' : ' ', t->m_len);
944a1d7a8516e4d5b2136c5bb3d49aeac80271a36b0tuexen		SCTP_DEBUG_USR(SCTP_DEBUG_USR, " (off=%d)\n", off);
94507961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen	}
94607961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen#endif
94707961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen	if (offp)
94807961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen		*offp = off;
94907961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen	return n;
95007961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen}
95107961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen
952bca1dae6587a640359abee04337c0463b0a3893tuexen/*
953bca1dae6587a640359abee04337c0463b0a3893tuexen * Attach the the cluster from *m to *n, set up m_ext in *n
954bca1dae6587a640359abee04337c0463b0a3893tuexen * and bump the refcount of the cluster.
955bca1dae6587a640359abee04337c0463b0a3893tuexen */
956bca1dae6587a640359abee04337c0463b0a3893tuexenstatic void
957bca1dae6587a640359abee04337c0463b0a3893tuexenmb_dupcl(struct mbuf *n, struct mbuf *m)
958bca1dae6587a640359abee04337c0463b0a3893tuexen{
959c7108437de5af4d0b9f9a24979710b39197ec6cetuexen	KASSERT((m->m_flags & M_EXT) == M_EXT, ("%s: M_EXT not set", __func__));
960c7108437de5af4d0b9f9a24979710b39197ec6cetuexen	KASSERT(m->m_ext.ref_cnt != NULL, ("%s: ref_cnt not set", __func__));
961c7108437de5af4d0b9f9a24979710b39197ec6cetuexen	KASSERT((n->m_flags & M_EXT) == 0, ("%s: M_EXT set", __func__));
962bca1dae6587a640359abee04337c0463b0a3893tuexen
963bca1dae6587a640359abee04337c0463b0a3893tuexen	if (*(m->m_ext.ref_cnt) == 1)
964a1d7a8516e4d5b2136c5bb3d49aeac80271a36b0tuexen		*(m->m_ext.ref_cnt) += 1;
965bca1dae6587a640359abee04337c0463b0a3893tuexen	else
966a1d7a8516e4d5b2136c5bb3d49aeac80271a36b0tuexen		atomic_add_int(m->m_ext.ref_cnt, 1);
967bca1dae6587a640359abee04337c0463b0a3893tuexen	n->m_ext.ext_buf = m->m_ext.ext_buf;
968bca1dae6587a640359abee04337c0463b0a3893tuexen	n->m_ext.ext_free = m->m_ext.ext_free;
969bca1dae6587a640359abee04337c0463b0a3893tuexen	n->m_ext.ext_args = m->m_ext.ext_args;
970bca1dae6587a640359abee04337c0463b0a3893tuexen	n->m_ext.ext_size = m->m_ext.ext_size;
971bca1dae6587a640359abee04337c0463b0a3893tuexen	n->m_ext.ref_cnt = m->m_ext.ref_cnt;
972bca1dae6587a640359abee04337c0463b0a3893tuexen	n->m_ext.ext_type = m->m_ext.ext_type;
973bca1dae6587a640359abee04337c0463b0a3893tuexen	n->m_flags |= M_EXT;
974bca1dae6587a640359abee04337c0463b0a3893tuexen}
975bca1dae6587a640359abee04337c0463b0a3893tuexen
976bca1dae6587a640359abee04337c0463b0a3893tuexen
977bca1dae6587a640359abee04337c0463b0a3893tuexen/*
978bca1dae6587a640359abee04337c0463b0a3893tuexen * Make a copy of an mbuf chain starting "off0" bytes from the beginning,
979bca1dae6587a640359abee04337c0463b0a3893tuexen * continuing for "len" bytes.  If len is M_COPYALL, copy to end of mbuf.
980218d5d0df143e859e241afb12d6aaa1e4969d714t * The wait parameter is a choice of M_TRYWAIT/M_NOWAIT from caller.
981bca1dae6587a640359abee04337c0463b0a3893tuexen * Note that the copy is read-only, because clusters are not copied,
982bca1dae6587a640359abee04337c0463b0a3893tuexen * only their reference counts are incremented.
983bca1dae6587a640359abee04337c0463b0a3893tuexen */
984bca1dae6587a640359abee04337c0463b0a3893tuexen
985bca1dae6587a640359abee04337c0463b0a3893tuexenstruct mbuf *
986bca1dae6587a640359abee04337c0463b0a3893tuexenm_copym(struct mbuf *m, int off0, int len, int wait)
987bca1dae6587a640359abee04337c0463b0a3893tuexen{
988bca1dae6587a640359abee04337c0463b0a3893tuexen	struct mbuf *n, **np;
989bca1dae6587a640359abee04337c0463b0a3893tuexen	int off = off0;
990bca1dae6587a640359abee04337c0463b0a3893tuexen	struct mbuf *top;
991bca1dae6587a640359abee04337c0463b0a3893tuexen	int copyhdr = 0;
992bca1dae6587a640359abee04337c0463b0a3893tuexen
993c7108437de5af4d0b9f9a24979710b39197ec6cetuexen	KASSERT(off >= 0, ("m_copym, negative off %d", off));
994c7108437de5af4d0b9f9a24979710b39197ec6cetuexen	KASSERT(len >= 0, ("m_copym, negative len %d", len));
99542d0ec7a8a09fcaa90b491d267245606c7caa7edtuexen
996bca1dae6587a640359abee04337c0463b0a3893tuexen	if (off == 0 && m->m_flags & M_PKTHDR)
997bca1dae6587a640359abee04337c0463b0a3893tuexen		copyhdr = 1;
998bca1dae6587a640359abee04337c0463b0a3893tuexen	while (off > 0) {
999c7108437de5af4d0b9f9a24979710b39197ec6cetuexen		KASSERT(m != NULL, ("m_copym, offset > size of mbuf chain"));
1000bca1dae6587a640359abee04337c0463b0a3893tuexen		if (off < m->m_len)
1001bca1dae6587a640359abee04337c0463b0a3893tuexen			break;
1002bca1dae6587a640359abee04337c0463b0a3893tuexen		off -= m->m_len;
1003bca1dae6587a640359abee04337c0463b0a3893tuexen		m = m->m_next;
1004bca1dae6587a640359abee04337c0463b0a3893tuexen	}
1005bca1dae6587a640359abee04337c0463b0a3893tuexen	np = &top;
1006bca1dae6587a640359abee04337c0463b0a3893tuexen	top = 0;
1007bca1dae6587a640359abee04337c0463b0a3893tuexen	while (len > 0) {
1008bca1dae6587a640359abee04337c0463b0a3893tuexen		if (m == NULL) {
1009c7108437de5af4d0b9f9a24979710b39197ec6cetuexen			KASSERT(len == M_COPYALL, ("m_copym, length > size of mbuf chain"));
1010c7108437de5af4d0b9f9a24979710b39197ec6cetuexen			break;
1011bca1dae6587a640359abee04337c0463b0a3893tuexen		}
1012bca1dae6587a640359abee04337c0463b0a3893tuexen		if (copyhdr)
1013bca1dae6587a640359abee04337c0463b0a3893tuexen			MGETHDR(n, wait, m->m_type);
1014bca1dae6587a640359abee04337c0463b0a3893tuexen		else
1015bca1dae6587a640359abee04337c0463b0a3893tuexen			MGET(n, wait, m->m_type);
1016bca1dae6587a640359abee04337c0463b0a3893tuexen		*np = n;
1017bca1dae6587a640359abee04337c0463b0a3893tuexen		if (n == NULL)
1018bca1dae6587a640359abee04337c0463b0a3893tuexen			goto nospace;
1019bca1dae6587a640359abee04337c0463b0a3893tuexen		if (copyhdr) {
1020bca1dae6587a640359abee04337c0463b0a3893tuexen			if (!m_dup_pkthdr(n, m, wait))
1021bca1dae6587a640359abee04337c0463b0a3893tuexen				goto nospace;
1022bca1dae6587a640359abee04337c0463b0a3893tuexen			if (len == M_COPYALL)
1023bca1dae6587a640359abee04337c0463b0a3893tuexen				n->m_pkthdr.len -= off0;
1024bca1dae6587a640359abee04337c0463b0a3893tuexen			else
1025bca1dae6587a640359abee04337c0463b0a3893tuexen				n->m_pkthdr.len = len;
1026bca1dae6587a640359abee04337c0463b0a3893tuexen			copyhdr = 0;
1027bca1dae6587a640359abee04337c0463b0a3893tuexen		}
1028bca1dae6587a640359abee04337c0463b0a3893tuexen		n->m_len = min(len, m->m_len - off);
1029bca1dae6587a640359abee04337c0463b0a3893tuexen		if (m->m_flags & M_EXT) {
1030bca1dae6587a640359abee04337c0463b0a3893tuexen			n->m_data = m->m_data + off;
1031bca1dae6587a640359abee04337c0463b0a3893tuexen			mb_dupcl(n, m);
1032bca1dae6587a640359abee04337c0463b0a3893tuexen		} else
1033bca1dae6587a640359abee04337c0463b0a3893tuexen			bcopy(mtod(m, caddr_t)+off, mtod(n, caddr_t),
1034bca1dae6587a640359abee04337c0463b0a3893tuexen			    (u_int)n->m_len);
1035bca1dae6587a640359abee04337c0463b0a3893tuexen		if (len != M_COPYALL)
1036bca1dae6587a640359abee04337c0463b0a3893tuexen			len -= n->m_len;
1037bca1dae6587a640359abee04337c0463b0a3893tuexen		off = 0;
1038bca1dae6587a640359abee04337c0463b0a3893tuexen		m = m->m_next;
1039bca1dae6587a640359abee04337c0463b0a3893tuexen		np = &n->m_next;
1040bca1dae6587a640359abee04337c0463b0a3893tuexen	}
1041bca1dae6587a640359abee04337c0463b0a3893tuexen	if (top == NULL)
1042bca1dae6587a640359abee04337c0463b0a3893tuexen            mbstat.m_mcfail++;	/* XXX: No consistency. */
1043bca1dae6587a640359abee04337c0463b0a3893tuexen
1044bca1dae6587a640359abee04337c0463b0a3893tuexen	return (top);
1045bca1dae6587a640359abee04337c0463b0a3893tuexennospace:
1046bca1dae6587a640359abee04337c0463b0a3893tuexen	m_freem(top);
1047bca1dae6587a640359abee04337c0463b0a3893tuexen	mbstat.m_mcfail++;	/* XXX: No consistency. */
1048bca1dae6587a640359abee04337c0463b0a3893tuexen	return (NULL);
1049bca1dae6587a640359abee04337c0463b0a3893tuexen}
1050bca1dae6587a640359abee04337c0463b0a3893tuexen
1051bca1dae6587a640359abee04337c0463b0a3893tuexen
1052bca1dae6587a640359abee04337c0463b0a3893tuexenint
1053bca1dae6587a640359abee04337c0463b0a3893tuexenm_tag_copy_chain(struct mbuf *to, struct mbuf *from, int how)
1054bca1dae6587a640359abee04337c0463b0a3893tuexen{
1055bca1dae6587a640359abee04337c0463b0a3893tuexen	struct m_tag *p, *t, *tprev = NULL;
1056bca1dae6587a640359abee04337c0463b0a3893tuexen
1057e7eb46f39b8bfc4b5ed9b708232c1c669c06842bt	KASSERT(to && from, ("m_tag_copy_chain: null argument, to %p from %p", (void *)to, (void *)from));
1058bca1dae6587a640359abee04337c0463b0a3893tuexen	m_tag_delete_chain(to, NULL);
1059bca1dae6587a640359abee04337c0463b0a3893tuexen	SLIST_FOREACH(p, &from->m_pkthdr.tags, m_tag_link) {
1060bca1dae6587a640359abee04337c0463b0a3893tuexen		t = m_tag_copy(p, how);
1061bca1dae6587a640359abee04337c0463b0a3893tuexen		if (t == NULL) {
1062bca1dae6587a640359abee04337c0463b0a3893tuexen			m_tag_delete_chain(to, NULL);
1063bca1dae6587a640359abee04337c0463b0a3893tuexen			return 0;
1064bca1dae6587a640359abee04337c0463b0a3893tuexen		}
1065bca1dae6587a640359abee04337c0463b0a3893tuexen		if (tprev == NULL)
1066bca1dae6587a640359abee04337c0463b0a3893tuexen			SLIST_INSERT_HEAD(&to->m_pkthdr.tags, t, m_tag_link);
1067bca1dae6587a640359abee04337c0463b0a3893tuexen		else
1068bca1dae6587a640359abee04337c0463b0a3893tuexen			SLIST_INSERT_AFTER(tprev, t, m_tag_link);
1069bca1dae6587a640359abee04337c0463b0a3893tuexen		tprev = t;
1070bca1dae6587a640359abee04337c0463b0a3893tuexen	}
1071bca1dae6587a640359abee04337c0463b0a3893tuexen	return 1;
1072bca1dae6587a640359abee04337c0463b0a3893tuexen}
1073bca1dae6587a640359abee04337c0463b0a3893tuexen
1074bca1dae6587a640359abee04337c0463b0a3893tuexen/*
1075bca1dae6587a640359abee04337c0463b0a3893tuexen * Duplicate "from"'s mbuf pkthdr in "to".
1076bca1dae6587a640359abee04337c0463b0a3893tuexen * "from" must have M_PKTHDR set, and "to" must be empty.
1077bca1dae6587a640359abee04337c0463b0a3893tuexen * In particular, this does a deep copy of the packet tags.
1078bca1dae6587a640359abee04337c0463b0a3893tuexen */
1079bca1dae6587a640359abee04337c0463b0a3893tuexenint
1080bca1dae6587a640359abee04337c0463b0a3893tuexenm_dup_pkthdr(struct mbuf *to, struct mbuf *from, int how)
1081bca1dae6587a640359abee04337c0463b0a3893tuexen{
1082bca1dae6587a640359abee04337c0463b0a3893tuexen
1083bca1dae6587a640359abee04337c0463b0a3893tuexen	to->m_flags = (from->m_flags & M_COPYFLAGS) | (to->m_flags & M_EXT);
1084bca1dae6587a640359abee04337c0463b0a3893tuexen	if ((to->m_flags & M_EXT) == 0)
1085bca1dae6587a640359abee04337c0463b0a3893tuexen		to->m_data = to->m_pktdat;
1086bca1dae6587a640359abee04337c0463b0a3893tuexen	to->m_pkthdr = from->m_pkthdr;
1087bca1dae6587a640359abee04337c0463b0a3893tuexen	SLIST_INIT(&to->m_pkthdr.tags);
1088bca1dae6587a640359abee04337c0463b0a3893tuexen	return (m_tag_copy_chain(to, from, MBTOM(how)));
1089bca1dae6587a640359abee04337c0463b0a3893tuexen}
1090bca1dae6587a640359abee04337c0463b0a3893tuexen
1091bca1dae6587a640359abee04337c0463b0a3893tuexen/* Copy a single tag. */
1092bca1dae6587a640359abee04337c0463b0a3893tuexenstruct m_tag *
1093bca1dae6587a640359abee04337c0463b0a3893tuexenm_tag_copy(struct m_tag *t, int how)
1094bca1dae6587a640359abee04337c0463b0a3893tuexen{
1095bca1dae6587a640359abee04337c0463b0a3893tuexen	struct m_tag *p;
1096bca1dae6587a640359abee04337c0463b0a3893tuexen
1097c7108437de5af4d0b9f9a24979710b39197ec6cetuexen	KASSERT(t, ("m_tag_copy: null tag"));
1098bca1dae6587a640359abee04337c0463b0a3893tuexen	p = m_tag_alloc(t->m_tag_cookie, t->m_tag_id, t->m_tag_len, how);
1099bca1dae6587a640359abee04337c0463b0a3893tuexen	if (p == NULL)
1100bca1dae6587a640359abee04337c0463b0a3893tuexen		return (NULL);
1101bca1dae6587a640359abee04337c0463b0a3893tuexen	bcopy(t + 1, p + 1, t->m_tag_len); /* Copy the data */
1102bca1dae6587a640359abee04337c0463b0a3893tuexen	return p;
1103bca1dae6587a640359abee04337c0463b0a3893tuexen}
1104bca1dae6587a640359abee04337c0463b0a3893tuexen
1105bca1dae6587a640359abee04337c0463b0a3893tuexen/* Get a packet tag structure along with specified data following. */
1106bca1dae6587a640359abee04337c0463b0a3893tuexenstruct m_tag *
1107bca1dae6587a640359abee04337c0463b0a3893tuexenm_tag_alloc(u_int32_t cookie, int type, int len, int wait)
1108bca1dae6587a640359abee04337c0463b0a3893tuexen{
1109bca1dae6587a640359abee04337c0463b0a3893tuexen	struct m_tag *t;
1110bca1dae6587a640359abee04337c0463b0a3893tuexen
1111bca1dae6587a640359abee04337c0463b0a3893tuexen	if (len < 0)
1112bca1dae6587a640359abee04337c0463b0a3893tuexen		return NULL;
1113bca1dae6587a640359abee04337c0463b0a3893tuexen	t = malloc(len + sizeof(struct m_tag));
1114bca1dae6587a640359abee04337c0463b0a3893tuexen	if (t == NULL)
1115bca1dae6587a640359abee04337c0463b0a3893tuexen		return NULL;
1116bca1dae6587a640359abee04337c0463b0a3893tuexen	m_tag_setup(t, cookie, type, len);
1117bca1dae6587a640359abee04337c0463b0a3893tuexen	t->m_tag_free = m_tag_free_default;
1118bca1dae6587a640359abee04337c0463b0a3893tuexen	return t;
1119bca1dae6587a640359abee04337c0463b0a3893tuexen}
1120bca1dae6587a640359abee04337c0463b0a3893tuexen
1121bca1dae6587a640359abee04337c0463b0a3893tuexen/* Free a packet tag. */
1122bca1dae6587a640359abee04337c0463b0a3893tuexenvoid
1123bca1dae6587a640359abee04337c0463b0a3893tuexenm_tag_free_default(struct m_tag *t)
1124bca1dae6587a640359abee04337c0463b0a3893tuexen{
1125bca1dae6587a640359abee04337c0463b0a3893tuexen  free(t);
1126bca1dae6587a640359abee04337c0463b0a3893tuexen}
1127bca1dae6587a640359abee04337c0463b0a3893tuexen
1128bca1dae6587a640359abee04337c0463b0a3893tuexen/*
1129bca1dae6587a640359abee04337c0463b0a3893tuexen * Copy data from a buffer back into the indicated mbuf chain,
1130bca1dae6587a640359abee04337c0463b0a3893tuexen * starting "off" bytes from the beginning, extending the mbuf
1131bca1dae6587a640359abee04337c0463b0a3893tuexen * chain if necessary.
1132bca1dae6587a640359abee04337c0463b0a3893tuexen */
1133bca1dae6587a640359abee04337c0463b0a3893tuexenvoid
1134a89a6767416760e852d85b2db374f6eebc4e93d7tuexenm_copyback(struct mbuf *m0, int off, int len, caddr_t cp)
1135bca1dae6587a640359abee04337c0463b0a3893tuexen{
1136bca1dae6587a640359abee04337c0463b0a3893tuexen	int mlen;
1137bca1dae6587a640359abee04337c0463b0a3893tuexen	struct mbuf *m = m0, *n;
1138bca1dae6587a640359abee04337c0463b0a3893tuexen	int totlen = 0;
1139bca1dae6587a640359abee04337c0463b0a3893tuexen
1140bca1dae6587a640359abee04337c0463b0a3893tuexen	if (m0 == NULL)
1141bca1dae6587a640359abee04337c0463b0a3893tuexen		return;
1142bca1dae6587a640359abee04337c0463b0a3893tuexen	while (off > (mlen = m->m_len)) {
1143bca1dae6587a640359abee04337c0463b0a3893tuexen		off -= mlen;
1144bca1dae6587a640359abee04337c0463b0a3893tuexen		totlen += mlen;
1145bca1dae6587a640359abee04337c0463b0a3893tuexen		if (m->m_next == NULL) {
1146218d5d0df143e859e241afb12d6aaa1e4969d714t			n = m_get(M_NOWAIT, m->m_type);
1147bca1dae6587a640359abee04337c0463b0a3893tuexen			if (n == NULL)
1148bca1dae6587a640359abee04337c0463b0a3893tuexen				goto out;
1149bca1dae6587a640359abee04337c0463b0a3893tuexen			bzero(mtod(n, caddr_t), MLEN);
1150bca1dae6587a640359abee04337c0463b0a3893tuexen			n->m_len = min(MLEN, len + off);
1151bca1dae6587a640359abee04337c0463b0a3893tuexen			m->m_next = n;
1152bca1dae6587a640359abee04337c0463b0a3893tuexen		}
1153bca1dae6587a640359abee04337c0463b0a3893tuexen		m = m->m_next;
1154bca1dae6587a640359abee04337c0463b0a3893tuexen	}
1155bca1dae6587a640359abee04337c0463b0a3893tuexen	while (len > 0) {
1156bca1dae6587a640359abee04337c0463b0a3893tuexen		mlen = min (m->m_len - off, len);
1157bca1dae6587a640359abee04337c0463b0a3893tuexen		bcopy(cp, off + mtod(m, caddr_t), (u_int)mlen);
1158bca1dae6587a640359abee04337c0463b0a3893tuexen		cp += mlen;
1159bca1dae6587a640359abee04337c0463b0a3893tuexen		len -= mlen;
1160bca1dae6587a640359abee04337c0463b0a3893tuexen		mlen += off;
1161bca1dae6587a640359abee04337c0463b0a3893tuexen		off = 0;
1162bca1dae6587a640359abee04337c0463b0a3893tuexen		totlen += mlen;
1163bca1dae6587a640359abee04337c0463b0a3893tuexen		if (len == 0)
1164bca1dae6587a640359abee04337c0463b0a3893tuexen			break;
1165bca1dae6587a640359abee04337c0463b0a3893tuexen		if (m->m_next == NULL) {
1166218d5d0df143e859e241afb12d6aaa1e4969d714t			n = m_get(M_NOWAIT, m->m_type);
1167bca1dae6587a640359abee04337c0463b0a3893tuexen			if (n == NULL)
1168bca1dae6587a640359abee04337c0463b0a3893tuexen				break;
1169bca1dae6587a640359abee04337c0463b0a3893tuexen			n->m_len = min(MLEN, len);
1170bca1dae6587a640359abee04337c0463b0a3893tuexen			m->m_next = n;
1171bca1dae6587a640359abee04337c0463b0a3893tuexen		}
1172bca1dae6587a640359abee04337c0463b0a3893tuexen		m = m->m_next;
1173bca1dae6587a640359abee04337c0463b0a3893tuexen	}
1174bca1dae6587a640359abee04337c0463b0a3893tuexenout:	if (((m = m0)->m_flags & M_PKTHDR) && (m->m_pkthdr.len < totlen))
1175bca1dae6587a640359abee04337c0463b0a3893tuexen		m->m_pkthdr.len = totlen;
1176bca1dae6587a640359abee04337c0463b0a3893tuexen}
1177bca1dae6587a640359abee04337c0463b0a3893tuexen
1178bca1dae6587a640359abee04337c0463b0a3893tuexen
1179bca1dae6587a640359abee04337c0463b0a3893tuexen/*
1180bca1dae6587a640359abee04337c0463b0a3893tuexen * Lesser-used path for M_PREPEND:
1181bca1dae6587a640359abee04337c0463b0a3893tuexen * allocate new mbuf to prepend to chain,
1182bca1dae6587a640359abee04337c0463b0a3893tuexen * copy junk along.
1183bca1dae6587a640359abee04337c0463b0a3893tuexen */
1184bca1dae6587a640359abee04337c0463b0a3893tuexenstruct mbuf *
1185bca1dae6587a640359abee04337c0463b0a3893tuexenm_prepend(struct mbuf *m, int len, int how)
1186bca1dae6587a640359abee04337c0463b0a3893tuexen{
1187bca1dae6587a640359abee04337c0463b0a3893tuexen	struct mbuf *mn;
1188bca1dae6587a640359abee04337c0463b0a3893tuexen
1189bca1dae6587a640359abee04337c0463b0a3893tuexen	if (m->m_flags & M_PKTHDR)
1190bca1dae6587a640359abee04337c0463b0a3893tuexen		MGETHDR(mn, how, m->m_type);
1191bca1dae6587a640359abee04337c0463b0a3893tuexen	else
1192bca1dae6587a640359abee04337c0463b0a3893tuexen		MGET(mn, how, m->m_type);
1193bca1dae6587a640359abee04337c0463b0a3893tuexen	if (mn == NULL) {
1194bca1dae6587a640359abee04337c0463b0a3893tuexen		m_freem(m);
1195bca1dae6587a640359abee04337c0463b0a3893tuexen		return (NULL);
1196bca1dae6587a640359abee04337c0463b0a3893tuexen	}
1197bca1dae6587a640359abee04337c0463b0a3893tuexen	if (m->m_flags & M_PKTHDR)
1198bca1dae6587a640359abee04337c0463b0a3893tuexen		M_MOVE_PKTHDR(mn, m);
1199bca1dae6587a640359abee04337c0463b0a3893tuexen	mn->m_next = m;
1200bca1dae6587a640359abee04337c0463b0a3893tuexen	m = mn;
1201bca1dae6587a640359abee04337c0463b0a3893tuexen	if(m->m_flags & M_PKTHDR) {
1202bca1dae6587a640359abee04337c0463b0a3893tuexen		if (len < MHLEN)
1203bca1dae6587a640359abee04337c0463b0a3893tuexen			MH_ALIGN(m, len);
1204bca1dae6587a640359abee04337c0463b0a3893tuexen	} else {
120542d0ec7a8a09fcaa90b491d267245606c7caa7edtuexen		if (len < MLEN)
1206bca1dae6587a640359abee04337c0463b0a3893tuexen			M_ALIGN(m, len);
1207bca1dae6587a640359abee04337c0463b0a3893tuexen	}
1208bca1dae6587a640359abee04337c0463b0a3893tuexen	m->m_len = len;
1209bca1dae6587a640359abee04337c0463b0a3893tuexen	return (m);
1210bca1dae6587a640359abee04337c0463b0a3893tuexen}
1211bca1dae6587a640359abee04337c0463b0a3893tuexen
1212bca1dae6587a640359abee04337c0463b0a3893tuexen/*
1213bca1dae6587a640359abee04337c0463b0a3893tuexen * Copy data from an mbuf chain starting "off" bytes from the beginning,
1214bca1dae6587a640359abee04337c0463b0a3893tuexen * continuing for "len" bytes, into the indicated buffer.
1215bca1dae6587a640359abee04337c0463b0a3893tuexen */
1216bca1dae6587a640359abee04337c0463b0a3893tuexenvoid
1217bca1dae6587a640359abee04337c0463b0a3893tuexenm_copydata(const struct mbuf *m, int off, int len, caddr_t cp)
1218bca1dae6587a640359abee04337c0463b0a3893tuexen{
1219bca1dae6587a640359abee04337c0463b0a3893tuexen	u_int count;
1220bca1dae6587a640359abee04337c0463b0a3893tuexen
1221c7108437de5af4d0b9f9a24979710b39197ec6cetuexen	KASSERT(off >= 0, ("m_copydata, negative off %d", off));
1222c7108437de5af4d0b9f9a24979710b39197ec6cetuexen	KASSERT(len >= 0, ("m_copydata, negative len %d", len));
1223bca1dae6587a640359abee04337c0463b0a3893tuexen	while (off > 0) {
1224c7108437de5af4d0b9f9a24979710b39197ec6cetuexen		KASSERT(m != NULL, ("m_copydata, offset > size of mbuf chain"));
1225bca1dae6587a640359abee04337c0463b0a3893tuexen		if (off < m->m_len)
1226bca1dae6587a640359abee04337c0463b0a3893tuexen			break;
1227bca1dae6587a640359abee04337c0463b0a3893tuexen		off -= m->m_len;
1228bca1dae6587a640359abee04337c0463b0a3893tuexen		m = m->m_next;
1229bca1dae6587a640359abee04337c0463b0a3893tuexen	}
1230bca1dae6587a640359abee04337c0463b0a3893tuexen	while (len > 0) {
1231c7108437de5af4d0b9f9a24979710b39197ec6cetuexen		KASSERT(m != NULL, ("m_copydata, length > size of mbuf chain"));
1232bca1dae6587a640359abee04337c0463b0a3893tuexen		count = min(m->m_len - off, len);
1233bca1dae6587a640359abee04337c0463b0a3893tuexen		bcopy(mtod(m, caddr_t) + off, cp, count);
1234bca1dae6587a640359abee04337c0463b0a3893tuexen		len -= count;
1235bca1dae6587a640359abee04337c0463b0a3893tuexen		cp += count;
1236bca1dae6587a640359abee04337c0463b0a3893tuexen		off = 0;
1237bca1dae6587a640359abee04337c0463b0a3893tuexen		m = m->m_next;
1238bca1dae6587a640359abee04337c0463b0a3893tuexen	}
1239bca1dae6587a640359abee04337c0463b0a3893tuexen}
1240bca1dae6587a640359abee04337c0463b0a3893tuexen
1241bca1dae6587a640359abee04337c0463b0a3893tuexen
1242bca1dae6587a640359abee04337c0463b0a3893tuexen/*
1243bca1dae6587a640359abee04337c0463b0a3893tuexen * Concatenate mbuf chain n to m.
1244bca1dae6587a640359abee04337c0463b0a3893tuexen * Both chains must be of the same type (e.g. MT_DATA).
1245bca1dae6587a640359abee04337c0463b0a3893tuexen * Any m_pkthdr is not updated.
1246bca1dae6587a640359abee04337c0463b0a3893tuexen */
1247bca1dae6587a640359abee04337c0463b0a3893tuexenvoid
1248bca1dae6587a640359abee04337c0463b0a3893tuexenm_cat(struct mbuf *m, struct mbuf *n)
1249bca1dae6587a640359abee04337c0463b0a3893tuexen{
1250c7108437de5af4d0b9f9a24979710b39197ec6cetuexen	while (m->m_next)
1251c7108437de5af4d0b9f9a24979710b39197ec6cetuexen		m = m->m_next;
1252c7108437de5af4d0b9f9a24979710b39197ec6cetuexen	while (n) {
1253c7108437de5af4d0b9f9a24979710b39197ec6cetuexen		if (m->m_flags & M_EXT ||
1254c7108437de5af4d0b9f9a24979710b39197ec6cetuexen		    m->m_data + m->m_len + n->m_len >= &m->m_dat[MLEN]) {
1255c7108437de5af4d0b9f9a24979710b39197ec6cetuexen			/* just join the two chains */
1256c7108437de5af4d0b9f9a24979710b39197ec6cetuexen			m->m_next = n;
1257c7108437de5af4d0b9f9a24979710b39197ec6cetuexen			return;
1258c7108437de5af4d0b9f9a24979710b39197ec6cetuexen		}
1259c7108437de5af4d0b9f9a24979710b39197ec6cetuexen		/* splat the data from one into the other */
1260c7108437de5af4d0b9f9a24979710b39197ec6cetuexen		bcopy(mtod(n, caddr_t), mtod(m, caddr_t) + m->m_len, (u_int)n->m_len);
1261c7108437de5af4d0b9f9a24979710b39197ec6cetuexen		m->m_len += n->m_len;
1262c7108437de5af4d0b9f9a24979710b39197ec6cetuexen		n = m_free(n);
1263c7108437de5af4d0b9f9a24979710b39197ec6cetuexen	}
1264bca1dae6587a640359abee04337c0463b0a3893tuexen}
1265bca1dae6587a640359abee04337c0463b0a3893tuexen
1266bca1dae6587a640359abee04337c0463b0a3893tuexen
1267bca1dae6587a640359abee04337c0463b0a3893tuexenvoid
1268bca1dae6587a640359abee04337c0463b0a3893tuexenm_adj(struct mbuf *mp, int req_len)
1269bca1dae6587a640359abee04337c0463b0a3893tuexen{
1270bca1dae6587a640359abee04337c0463b0a3893tuexen	int len = req_len;
1271bca1dae6587a640359abee04337c0463b0a3893tuexen	struct mbuf *m;
1272bca1dae6587a640359abee04337c0463b0a3893tuexen	int count;
1273bca1dae6587a640359abee04337c0463b0a3893tuexen
1274bca1dae6587a640359abee04337c0463b0a3893tuexen	if ((m = mp) == NULL)
1275bca1dae6587a640359abee04337c0463b0a3893tuexen		return;
1276bca1dae6587a640359abee04337c0463b0a3893tuexen	if (len >= 0) {
1277bca1dae6587a640359abee04337c0463b0a3893tuexen		/*
1278bca1dae6587a640359abee04337c0463b0a3893tuexen		 * Trim from head.
1279bca1dae6587a640359abee04337c0463b0a3893tuexen		 */
1280bca1dae6587a640359abee04337c0463b0a3893tuexen		while (m != NULL && len > 0) {
1281bca1dae6587a640359abee04337c0463b0a3893tuexen			if (m->m_len <= len) {
1282bca1dae6587a640359abee04337c0463b0a3893tuexen				len -= m->m_len;
1283bca1dae6587a640359abee04337c0463b0a3893tuexen				m->m_len = 0;
1284bca1dae6587a640359abee04337c0463b0a3893tuexen				m = m->m_next;
1285bca1dae6587a640359abee04337c0463b0a3893tuexen			} else {
1286bca1dae6587a640359abee04337c0463b0a3893tuexen				m->m_len -= len;
1287bca1dae6587a640359abee04337c0463b0a3893tuexen				m->m_data += len;
1288bca1dae6587a640359abee04337c0463b0a3893tuexen				len = 0;
1289bca1dae6587a640359abee04337c0463b0a3893tuexen			}
1290bca1dae6587a640359abee04337c0463b0a3893tuexen		}
1291bca1dae6587a640359abee04337c0463b0a3893tuexen		m = mp;
1292bca1dae6587a640359abee04337c0463b0a3893tuexen		if (mp->m_flags & M_PKTHDR)
1293bca1dae6587a640359abee04337c0463b0a3893tuexen			m->m_pkthdr.len -= (req_len - len);
1294bca1dae6587a640359abee04337c0463b0a3893tuexen	} else {
1295bca1dae6587a640359abee04337c0463b0a3893tuexen		/*
1296bca1dae6587a640359abee04337c0463b0a3893tuexen		 * Trim from tail.  Scan the mbuf chain,
1297bca1dae6587a640359abee04337c0463b0a3893tuexen		 * calculating its length and finding the last mbuf.
1298bca1dae6587a640359abee04337c0463b0a3893tuexen		 * If the adjustment only affects this mbuf, then just
1299bca1dae6587a640359abee04337c0463b0a3893tuexen		 * adjust and return.  Otherwise, rescan and truncate
1300bca1dae6587a640359abee04337c0463b0a3893tuexen		 * after the remaining size.
1301bca1dae6587a640359abee04337c0463b0a3893tuexen		 */
1302bca1dae6587a640359abee04337c0463b0a3893tuexen		len = -len;
1303bca1dae6587a640359abee04337c0463b0a3893tuexen		count = 0;
1304bca1dae6587a640359abee04337c0463b0a3893tuexen		for (;;) {
1305bca1dae6587a640359abee04337c0463b0a3893tuexen			count += m->m_len;
1306bca1dae6587a640359abee04337c0463b0a3893tuexen			if (m->m_next == (struct mbuf *)0)
1307bca1dae6587a640359abee04337c0463b0a3893tuexen				break;
1308bca1dae6587a640359abee04337c0463b0a3893tuexen			m = m->m_next;
1309bca1dae6587a640359abee04337c0463b0a3893tuexen		}
1310bca1dae6587a640359abee04337c0463b0a3893tuexen		if (m->m_len >= len) {
1311bca1dae6587a640359abee04337c0463b0a3893tuexen			m->m_len -= len;
1312bca1dae6587a640359abee04337c0463b0a3893tuexen			if (mp->m_flags & M_PKTHDR)
1313bca1dae6587a640359abee04337c0463b0a3893tuexen				mp->m_pkthdr.len -= len;
1314bca1dae6587a640359abee04337c0463b0a3893tuexen			return;
1315bca1dae6587a640359abee04337c0463b0a3893tuexen		}
1316bca1dae6587a640359abee04337c0463b0a3893tuexen		count -= len;
1317bca1dae6587a640359abee04337c0463b0a3893tuexen		if (count < 0)
1318bca1dae6587a640359abee04337c0463b0a3893tuexen			count = 0;
1319bca1dae6587a640359abee04337c0463b0a3893tuexen		/*
1320bca1dae6587a640359abee04337c0463b0a3893tuexen		 * Correct length for chain is "count".
1321bca1dae6587a640359abee04337c0463b0a3893tuexen		 * Find the mbuf with last data, adjust its length,
1322bca1dae6587a640359abee04337c0463b0a3893tuexen		 * and toss data from remaining mbufs on chain.
1323bca1dae6587a640359abee04337c0463b0a3893tuexen		 */
1324bca1dae6587a640359abee04337c0463b0a3893tuexen		m = mp;
1325bca1dae6587a640359abee04337c0463b0a3893tuexen		if (m->m_flags & M_PKTHDR)
1326bca1dae6587a640359abee04337c0463b0a3893tuexen			m->m_pkthdr.len = count;
1327bca1dae6587a640359abee04337c0463b0a3893tuexen		for (; m; m = m->m_next) {
1328bca1dae6587a640359abee04337c0463b0a3893tuexen			if (m->m_len >= count) {
1329bca1dae6587a640359abee04337c0463b0a3893tuexen				m->m_len = count;
1330bca1dae6587a640359abee04337c0463b0a3893tuexen				if (m->m_next != NULL) {
1331bca1dae6587a640359abee04337c0463b0a3893tuexen					m_freem(m->m_next);
1332bca1dae6587a640359abee04337c0463b0a3893tuexen					m->m_next = NULL;
1333bca1dae6587a640359abee04337c0463b0a3893tuexen				}
1334bca1dae6587a640359abee04337c0463b0a3893tuexen				break;
1335bca1dae6587a640359abee04337c0463b0a3893tuexen			}
1336bca1dae6587a640359abee04337c0463b0a3893tuexen			count -= m->m_len;
1337bca1dae6587a640359abee04337c0463b0a3893tuexen		}
1338bca1dae6587a640359abee04337c0463b0a3893tuexen	}
1339bca1dae6587a640359abee04337c0463b0a3893tuexen}
1340bca1dae6587a640359abee04337c0463b0a3893tuexen
1341bca1dae6587a640359abee04337c0463b0a3893tuexen
1342bca1dae6587a640359abee04337c0463b0a3893tuexen/* m_split is used within sctp_handle_cookie_echo. */
1343bca1dae6587a640359abee04337c0463b0a3893tuexen
1344bca1dae6587a640359abee04337c0463b0a3893tuexen/*
1345bca1dae6587a640359abee04337c0463b0a3893tuexen * Partition an mbuf chain in two pieces, returning the tail --
1346bca1dae6587a640359abee04337c0463b0a3893tuexen * all but the first len0 bytes.  In case of failure, it returns NULL and
1347bca1dae6587a640359abee04337c0463b0a3893tuexen * attempts to restore the chain to its original state.
1348bca1dae6587a640359abee04337c0463b0a3893tuexen *
1349bca1dae6587a640359abee04337c0463b0a3893tuexen * Note that the resulting mbufs might be read-only, because the new
1350bca1dae6587a640359abee04337c0463b0a3893tuexen * mbuf can end up sharing an mbuf cluster with the original mbuf if
1351bca1dae6587a640359abee04337c0463b0a3893tuexen * the "breaking point" happens to lie within a cluster mbuf. Use the
1352bca1dae6587a640359abee04337c0463b0a3893tuexen * M_WRITABLE() macro to check for this case.
1353bca1dae6587a640359abee04337c0463b0a3893tuexen */
1354bca1dae6587a640359abee04337c0463b0a3893tuexenstruct mbuf *
1355bca1dae6587a640359abee04337c0463b0a3893tuexenm_split(struct mbuf *m0, int len0, int wait)
1356bca1dae6587a640359abee04337c0463b0a3893tuexen{
1357bca1dae6587a640359abee04337c0463b0a3893tuexen	struct mbuf *m, *n;
1358bca1dae6587a640359abee04337c0463b0a3893tuexen	u_int len = len0, remain;
1359bca1dae6587a640359abee04337c0463b0a3893tuexen
1360bca1dae6587a640359abee04337c0463b0a3893tuexen	/* MBUF_CHECKSLEEP(wait); */
1361968138a650335b8836df7433026face9535f9641t	for (m = m0; m && (int)len > m->m_len; m = m->m_next)
1362bca1dae6587a640359abee04337c0463b0a3893tuexen		len -= m->m_len;
1363bca1dae6587a640359abee04337c0463b0a3893tuexen	if (m == NULL)
1364bca1dae6587a640359abee04337c0463b0a3893tuexen		return (NULL);
1365bca1dae6587a640359abee04337c0463b0a3893tuexen	remain = m->m_len - len;
1366bca1dae6587a640359abee04337c0463b0a3893tuexen	if (m0->m_flags & M_PKTHDR) {
1367bca1dae6587a640359abee04337c0463b0a3893tuexen		MGETHDR(n, wait, m0->m_type);
1368bca1dae6587a640359abee04337c0463b0a3893tuexen		if (n == NULL)
1369bca1dae6587a640359abee04337c0463b0a3893tuexen			return (NULL);
1370bca1dae6587a640359abee04337c0463b0a3893tuexen		n->m_pkthdr.rcvif = m0->m_pkthdr.rcvif;
1371bca1dae6587a640359abee04337c0463b0a3893tuexen		n->m_pkthdr.len = m0->m_pkthdr.len - len0;
1372bca1dae6587a640359abee04337c0463b0a3893tuexen		m0->m_pkthdr.len = len0;
1373bca1dae6587a640359abee04337c0463b0a3893tuexen		if (m->m_flags & M_EXT)
1374bca1dae6587a640359abee04337c0463b0a3893tuexen			goto extpacket;
1375bca1dae6587a640359abee04337c0463b0a3893tuexen		if (remain > MHLEN) {
1376bca1dae6587a640359abee04337c0463b0a3893tuexen			/* m can't be the lead packet */
1377bca1dae6587a640359abee04337c0463b0a3893tuexen			MH_ALIGN(n, 0);
1378bca1dae6587a640359abee04337c0463b0a3893tuexen			n->m_next = m_split(m, len, wait);
1379bca1dae6587a640359abee04337c0463b0a3893tuexen			if (n->m_next == NULL) {
1380bca1dae6587a640359abee04337c0463b0a3893tuexen				(void) m_free(n);
1381bca1dae6587a640359abee04337c0463b0a3893tuexen				return (NULL);
1382bca1dae6587a640359abee04337c0463b0a3893tuexen			} else {
1383bca1dae6587a640359abee04337c0463b0a3893tuexen				n->m_len = 0;
1384bca1dae6587a640359abee04337c0463b0a3893tuexen				return (n);
1385bca1dae6587a640359abee04337c0463b0a3893tuexen			}
1386bca1dae6587a640359abee04337c0463b0a3893tuexen		} else
1387bca1dae6587a640359abee04337c0463b0a3893tuexen			MH_ALIGN(n, remain);
1388bca1dae6587a640359abee04337c0463b0a3893tuexen	} else if (remain == 0) {
1389bca1dae6587a640359abee04337c0463b0a3893tuexen		n = m->m_next;
1390bca1dae6587a640359abee04337c0463b0a3893tuexen		m->m_next = NULL;
1391bca1dae6587a640359abee04337c0463b0a3893tuexen		return (n);
1392bca1dae6587a640359abee04337c0463b0a3893tuexen	} else {
1393bca1dae6587a640359abee04337c0463b0a3893tuexen		MGET(n, wait, m->m_type);
1394bca1dae6587a640359abee04337c0463b0a3893tuexen		if (n == NULL)
1395bca1dae6587a640359abee04337c0463b0a3893tuexen			return (NULL);
1396bca1dae6587a640359abee04337c0463b0a3893tuexen		M_ALIGN(n, remain);
1397bca1dae6587a640359abee04337c0463b0a3893tuexen	}
1398bca1dae6587a640359abee04337c0463b0a3893tuexenextpacket:
1399bca1dae6587a640359abee04337c0463b0a3893tuexen	if (m->m_flags & M_EXT) {
1400bca1dae6587a640359abee04337c0463b0a3893tuexen		n->m_data = m->m_data + len;
1401bca1dae6587a640359abee04337c0463b0a3893tuexen		mb_dupcl(n, m);
1402bca1dae6587a640359abee04337c0463b0a3893tuexen	} else {
1403bca1dae6587a640359abee04337c0463b0a3893tuexen		bcopy(mtod(m, caddr_t) + len, mtod(n, caddr_t), remain);
1404bca1dae6587a640359abee04337c0463b0a3893tuexen	}
1405bca1dae6587a640359abee04337c0463b0a3893tuexen	n->m_len = remain;
1406bca1dae6587a640359abee04337c0463b0a3893tuexen	m->m_len = len;
1407bca1dae6587a640359abee04337c0463b0a3893tuexen	n->m_next = m->m_next;
1408bca1dae6587a640359abee04337c0463b0a3893tuexen	m->m_next = NULL;
1409bca1dae6587a640359abee04337c0463b0a3893tuexen	return (n);
1410bca1dae6587a640359abee04337c0463b0a3893tuexen}
1411bca1dae6587a640359abee04337c0463b0a3893tuexen
1412bca1dae6587a640359abee04337c0463b0a3893tuexen
1413bca1dae6587a640359abee04337c0463b0a3893tuexen
1414bca1dae6587a640359abee04337c0463b0a3893tuexen
14159cf3035a03978648d38588875628f98f41deb0cetuexenint
14169cf3035a03978648d38588875628f98f41deb0cetuexenpack_send_buffer(caddr_t buffer, struct mbuf* mb){
14179cf3035a03978648d38588875628f98f41deb0cetuexen
14189cf3035a03978648d38588875628f98f41deb0cetuexen	int count_to_copy;
14199cf3035a03978648d38588875628f98f41deb0cetuexen	int total_count_copied = 0;
14209cf3035a03978648d38588875628f98f41deb0cetuexen	int offset = 0;
1421bca1dae6587a640359abee04337c0463b0a3893tuexen
1422c7108437de5af4d0b9f9a24979710b39197ec6cetuexen	do {
14239cf3035a03978648d38588875628f98f41deb0cetuexen		count_to_copy = mb->m_len;
14249cf3035a03978648d38588875628f98f41deb0cetuexen		bcopy(mtod(mb, caddr_t), buffer+offset, count_to_copy);
14259cf3035a03978648d38588875628f98f41deb0cetuexen		offset += count_to_copy;
14269cf3035a03978648d38588875628f98f41deb0cetuexen		total_count_copied += count_to_copy;
14279cf3035a03978648d38588875628f98f41deb0cetuexen		mb = mb->m_next;
1428c7108437de5af4d0b9f9a24979710b39197ec6cetuexen	} while(mb);
1429bca1dae6587a640359abee04337c0463b0a3893tuexen
14309cf3035a03978648d38588875628f98f41deb0cetuexen	return (total_count_copied);
1431bca1dae6587a640359abee04337c0463b0a3893tuexen}
1432