xref: /xnu-8796.101.5/bsd/net/pf_pbuf.c (revision aca3beaa3dfbd42498b42c5e5ce20a938e6554e5)
1*aca3beaaSApple OSS Distributions /*
2*aca3beaaSApple OSS Distributions  * Copyright (c) 2016-2022 Apple Inc. All rights reserved.
3*aca3beaaSApple OSS Distributions  *
4*aca3beaaSApple OSS Distributions  * @APPLE_LICENSE_HEADER_START@
5*aca3beaaSApple OSS Distributions  *
6*aca3beaaSApple OSS Distributions  * This file contains Original Code and/or Modifications of Original Code
7*aca3beaaSApple OSS Distributions  * as defined in and that are subject to the Apple Public Source License
8*aca3beaaSApple OSS Distributions  * Version 2.0 (the 'License'). You may not use this file except in
9*aca3beaaSApple OSS Distributions  * compliance with the License. Please obtain a copy of the License at
10*aca3beaaSApple OSS Distributions  * http://www.opensource.apple.com/apsl/ and read it before using this
11*aca3beaaSApple OSS Distributions  * file.
12*aca3beaaSApple OSS Distributions  *
13*aca3beaaSApple OSS Distributions  * The Original Code and all software distributed under the License are
14*aca3beaaSApple OSS Distributions  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15*aca3beaaSApple OSS Distributions  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16*aca3beaaSApple OSS Distributions  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17*aca3beaaSApple OSS Distributions  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18*aca3beaaSApple OSS Distributions  * Please see the License for the specific language governing rights and
19*aca3beaaSApple OSS Distributions  * limitations under the License.
20*aca3beaaSApple OSS Distributions  *
21*aca3beaaSApple OSS Distributions  * @APPLE_LICENSE_HEADER_END@
22*aca3beaaSApple OSS Distributions  */
23*aca3beaaSApple OSS Distributions 
24*aca3beaaSApple OSS Distributions #include <sys/cdefs.h>
25*aca3beaaSApple OSS Distributions #include <sys/systm.h>
26*aca3beaaSApple OSS Distributions #include <sys/param.h>
27*aca3beaaSApple OSS Distributions #include <sys/types.h>
28*aca3beaaSApple OSS Distributions #include <sys/mcache.h>
29*aca3beaaSApple OSS Distributions #include <kern/kern_types.h>
30*aca3beaaSApple OSS Distributions #include <net/pf_pbuf.h>
31*aca3beaaSApple OSS Distributions #include <net/pfvar.h>
32*aca3beaaSApple OSS Distributions #include <netinet/in.h>
33*aca3beaaSApple OSS Distributions 
34*aca3beaaSApple OSS Distributions void
pbuf_init_mbuf(pbuf_t * pbuf,struct mbuf * m,struct ifnet * ifp)35*aca3beaaSApple OSS Distributions pbuf_init_mbuf(pbuf_t *pbuf, struct mbuf *m, struct ifnet *ifp)
36*aca3beaaSApple OSS Distributions {
37*aca3beaaSApple OSS Distributions 	VERIFY((m->m_flags & M_PKTHDR) != 0);
38*aca3beaaSApple OSS Distributions 
39*aca3beaaSApple OSS Distributions 	pbuf->pb_type = PBUF_TYPE_MBUF;
40*aca3beaaSApple OSS Distributions 	pbuf->pb_mbuf = m;
41*aca3beaaSApple OSS Distributions 	pbuf->pb_ifp = ifp;
42*aca3beaaSApple OSS Distributions 	pbuf->pb_next = NULL;
43*aca3beaaSApple OSS Distributions 	pbuf_sync(pbuf);
44*aca3beaaSApple OSS Distributions }
45*aca3beaaSApple OSS Distributions 
46*aca3beaaSApple OSS Distributions void
pbuf_init_memory(pbuf_t * pbuf,const struct pbuf_memory * mp,struct ifnet * ifp)47*aca3beaaSApple OSS Distributions pbuf_init_memory(pbuf_t *pbuf, const struct pbuf_memory *mp, struct ifnet *ifp)
48*aca3beaaSApple OSS Distributions {
49*aca3beaaSApple OSS Distributions 	pbuf->pb_type = PBUF_TYPE_MEMORY;
50*aca3beaaSApple OSS Distributions 	pbuf->pb_memory = *mp;
51*aca3beaaSApple OSS Distributions 	pbuf->pb_ifp = ifp;
52*aca3beaaSApple OSS Distributions 	pbuf->pb_next = NULL;
53*aca3beaaSApple OSS Distributions 	pbuf_sync(pbuf);
54*aca3beaaSApple OSS Distributions }
55*aca3beaaSApple OSS Distributions 
56*aca3beaaSApple OSS Distributions void
pbuf_destroy(pbuf_t * pbuf)57*aca3beaaSApple OSS Distributions pbuf_destroy(pbuf_t *pbuf)
58*aca3beaaSApple OSS Distributions {
59*aca3beaaSApple OSS Distributions 	if (pbuf->pb_type == PBUF_TYPE_MBUF) {
60*aca3beaaSApple OSS Distributions 		if (pbuf->pb_mbuf) {
61*aca3beaaSApple OSS Distributions 			m_freem(pbuf->pb_mbuf);
62*aca3beaaSApple OSS Distributions 			pbuf->pb_mbuf = NULL;
63*aca3beaaSApple OSS Distributions 		}
64*aca3beaaSApple OSS Distributions 	} else if (pbuf->pb_type == PBUF_TYPE_MEMORY) {
65*aca3beaaSApple OSS Distributions 		VERIFY(pbuf->pb_memory.pm_buffer != NULL);
66*aca3beaaSApple OSS Distributions 		(void) (pbuf->pb_memory.pm_action)(&pbuf->pb_memory,
67*aca3beaaSApple OSS Distributions 		    PBUF_ACTION_DESTROY);
68*aca3beaaSApple OSS Distributions 	} else {
69*aca3beaaSApple OSS Distributions 		VERIFY(pbuf->pb_type == PBUF_TYPE_ZOMBIE);
70*aca3beaaSApple OSS Distributions 	}
71*aca3beaaSApple OSS Distributions 
72*aca3beaaSApple OSS Distributions 	memset(pbuf, 0, sizeof(*pbuf));
73*aca3beaaSApple OSS Distributions }
74*aca3beaaSApple OSS Distributions 
75*aca3beaaSApple OSS Distributions void
pbuf_sync(pbuf_t * pbuf)76*aca3beaaSApple OSS Distributions pbuf_sync(pbuf_t *pbuf)
77*aca3beaaSApple OSS Distributions {
78*aca3beaaSApple OSS Distributions 	if (pbuf->pb_type == PBUF_TYPE_MBUF) {
79*aca3beaaSApple OSS Distributions 		struct mbuf *m = pbuf->pb_mbuf;
80*aca3beaaSApple OSS Distributions 
81*aca3beaaSApple OSS Distributions 		VERIFY(m != NULL);
82*aca3beaaSApple OSS Distributions 		VERIFY(m->m_flags & M_PKTHDR);
83*aca3beaaSApple OSS Distributions 
84*aca3beaaSApple OSS Distributions 		pbuf->pb_data = mtod(m, void *);
85*aca3beaaSApple OSS Distributions 		pbuf->pb_packet_len = m->m_pkthdr.len;
86*aca3beaaSApple OSS Distributions 		pbuf->pb_contig_len = m->m_len;
87*aca3beaaSApple OSS Distributions 		pbuf->pb_csum_flags = &m->m_pkthdr.csum_flags;
88*aca3beaaSApple OSS Distributions 		pbuf->pb_csum_data = &m->m_pkthdr.csum_data;
89*aca3beaaSApple OSS Distributions 		pbuf->pb_proto = &m->m_pkthdr.pkt_proto;
90*aca3beaaSApple OSS Distributions 		pbuf->pb_flowsrc = &m->m_pkthdr.pkt_flowsrc;
91*aca3beaaSApple OSS Distributions 		pbuf->pb_flowid = &m->m_pkthdr.pkt_flowid;
92*aca3beaaSApple OSS Distributions 		pbuf->pb_flow_gencnt = &m->m_pkthdr.comp_gencnt;
93*aca3beaaSApple OSS Distributions 		pbuf->pb_flags = &m->m_pkthdr.pkt_flags;
94*aca3beaaSApple OSS Distributions 		pbuf->pb_pftag = m_pftag(m);
95*aca3beaaSApple OSS Distributions 		pbuf->pb_pf_fragtag = pf_find_fragment_tag(m);
96*aca3beaaSApple OSS Distributions 		ASSERT((pbuf->pb_pf_fragtag == NULL) ||
97*aca3beaaSApple OSS Distributions 		    (pbuf->pb_pftag->pftag_flags & PF_TAG_REASSEMBLED));
98*aca3beaaSApple OSS Distributions 	} else if (pbuf->pb_type == PBUF_TYPE_MEMORY) {
99*aca3beaaSApple OSS Distributions 		struct pbuf_memory *nm = &pbuf->pb_memory;
100*aca3beaaSApple OSS Distributions 
101*aca3beaaSApple OSS Distributions 		VERIFY(nm->pm_buffer != NULL);
102*aca3beaaSApple OSS Distributions 		VERIFY(nm->pm_buffer_len != 0);
103*aca3beaaSApple OSS Distributions 		VERIFY(nm->pm_len != 0);
104*aca3beaaSApple OSS Distributions 		VERIFY(nm->pm_len <= nm->pm_buffer_len);
105*aca3beaaSApple OSS Distributions 		VERIFY(nm->pm_offset < nm->pm_len);
106*aca3beaaSApple OSS Distributions 
107*aca3beaaSApple OSS Distributions 		pbuf->pb_data = &nm->pm_buffer[nm->pm_offset];
108*aca3beaaSApple OSS Distributions 		pbuf->pb_packet_len = nm->pm_len;
109*aca3beaaSApple OSS Distributions 		pbuf->pb_contig_len = nm->pm_len;
110*aca3beaaSApple OSS Distributions 		pbuf->pb_csum_flags = &nm->pm_csum_flags;
111*aca3beaaSApple OSS Distributions 		pbuf->pb_csum_data = &nm->pm_csum_data;
112*aca3beaaSApple OSS Distributions 		pbuf->pb_proto = &nm->pm_proto;
113*aca3beaaSApple OSS Distributions 		pbuf->pb_flowsrc = &nm->pm_flowsrc;
114*aca3beaaSApple OSS Distributions 		pbuf->pb_flowid = &nm->pm_flowid;
115*aca3beaaSApple OSS Distributions 		pbuf->pb_flow_gencnt = &nm->pm_flow_gencnt;
116*aca3beaaSApple OSS Distributions 		pbuf->pb_flags = &nm->pm_flags;
117*aca3beaaSApple OSS Distributions 		pbuf->pb_pftag = &nm->pm_pftag;
118*aca3beaaSApple OSS Distributions 		pbuf->pb_pf_fragtag = &nm->pm_pf_fragtag;
119*aca3beaaSApple OSS Distributions 	} else {
120*aca3beaaSApple OSS Distributions 		panic("%s: bad pb_type: %d", __func__, pbuf->pb_type);
121*aca3beaaSApple OSS Distributions 	}
122*aca3beaaSApple OSS Distributions }
123*aca3beaaSApple OSS Distributions 
124*aca3beaaSApple OSS Distributions struct mbuf *
pbuf_to_mbuf(pbuf_t * pbuf,boolean_t release_ptr)125*aca3beaaSApple OSS Distributions pbuf_to_mbuf(pbuf_t *pbuf, boolean_t release_ptr)
126*aca3beaaSApple OSS Distributions {
127*aca3beaaSApple OSS Distributions 	struct mbuf *m = NULL;
128*aca3beaaSApple OSS Distributions 
129*aca3beaaSApple OSS Distributions 	pbuf_sync(pbuf);
130*aca3beaaSApple OSS Distributions 
131*aca3beaaSApple OSS Distributions 	if (pbuf->pb_type == PBUF_TYPE_MBUF) {
132*aca3beaaSApple OSS Distributions 		m = pbuf->pb_mbuf;
133*aca3beaaSApple OSS Distributions 		if (release_ptr) {
134*aca3beaaSApple OSS Distributions 			pbuf->pb_mbuf = NULL;
135*aca3beaaSApple OSS Distributions 		}
136*aca3beaaSApple OSS Distributions 	} else if (pbuf->pb_type == PBUF_TYPE_MEMORY) {
137*aca3beaaSApple OSS Distributions 		boolean_t fragtag = FALSE;
138*aca3beaaSApple OSS Distributions 
139*aca3beaaSApple OSS Distributions 		if (pbuf->pb_packet_len > (u_int)MHLEN) {
140*aca3beaaSApple OSS Distributions 			if (pbuf->pb_packet_len > (u_int)MCLBYTES) {
141*aca3beaaSApple OSS Distributions 				printf("%s: packet too big for cluster (%u)\n",
142*aca3beaaSApple OSS Distributions 				    __func__, pbuf->pb_packet_len);
143*aca3beaaSApple OSS Distributions 				return NULL;
144*aca3beaaSApple OSS Distributions 			}
145*aca3beaaSApple OSS Distributions 			m = m_getcl(M_WAITOK, MT_DATA, M_PKTHDR);
146*aca3beaaSApple OSS Distributions 		} else {
147*aca3beaaSApple OSS Distributions 			m = m_gethdr(M_DONTWAIT, MT_DATA);
148*aca3beaaSApple OSS Distributions 		}
149*aca3beaaSApple OSS Distributions 		if (m == NULL) {
150*aca3beaaSApple OSS Distributions 			goto done;
151*aca3beaaSApple OSS Distributions 		}
152*aca3beaaSApple OSS Distributions 
153*aca3beaaSApple OSS Distributions 		m_copyback(m, 0, pbuf->pb_packet_len, pbuf->pb_data);
154*aca3beaaSApple OSS Distributions 		m->m_pkthdr.csum_flags = *pbuf->pb_csum_flags;
155*aca3beaaSApple OSS Distributions 		m->m_pkthdr.csum_data = *pbuf->pb_csum_data;
156*aca3beaaSApple OSS Distributions 		m->m_pkthdr.pkt_proto = *pbuf->pb_proto;
157*aca3beaaSApple OSS Distributions 		m->m_pkthdr.pkt_flowsrc = *pbuf->pb_flowsrc;
158*aca3beaaSApple OSS Distributions 		m->m_pkthdr.pkt_flowid = *pbuf->pb_flowid;
159*aca3beaaSApple OSS Distributions 		m->m_pkthdr.comp_gencnt = *pbuf->pb_flow_gencnt;
160*aca3beaaSApple OSS Distributions 		m->m_pkthdr.pkt_flags = *pbuf->pb_flags;
161*aca3beaaSApple OSS Distributions 
162*aca3beaaSApple OSS Distributions 		if (pbuf->pb_pftag != NULL) {
163*aca3beaaSApple OSS Distributions 			struct pf_mtag *pftag = m_pftag(m);
164*aca3beaaSApple OSS Distributions 
165*aca3beaaSApple OSS Distributions 			ASSERT(pftag != NULL);
166*aca3beaaSApple OSS Distributions 			*pftag = *pbuf->pb_pftag;
167*aca3beaaSApple OSS Distributions 			fragtag =
168*aca3beaaSApple OSS Distributions 			    ((pftag->pftag_flags & PF_TAG_REASSEMBLED) != 0);
169*aca3beaaSApple OSS Distributions 		}
170*aca3beaaSApple OSS Distributions 
171*aca3beaaSApple OSS Distributions 		if (fragtag && pbuf->pb_pf_fragtag != NULL) {
172*aca3beaaSApple OSS Distributions 			if (pf_copy_fragment_tag(m, pbuf->pb_pf_fragtag,
173*aca3beaaSApple OSS Distributions 			    M_NOWAIT) == NULL) {
174*aca3beaaSApple OSS Distributions 				m_freem(m);
175*aca3beaaSApple OSS Distributions 				m = NULL;
176*aca3beaaSApple OSS Distributions 				goto done;
177*aca3beaaSApple OSS Distributions 			}
178*aca3beaaSApple OSS Distributions 		}
179*aca3beaaSApple OSS Distributions 	}
180*aca3beaaSApple OSS Distributions 
181*aca3beaaSApple OSS Distributions done:
182*aca3beaaSApple OSS Distributions 	if (release_ptr) {
183*aca3beaaSApple OSS Distributions 		pbuf_destroy(pbuf);
184*aca3beaaSApple OSS Distributions 	}
185*aca3beaaSApple OSS Distributions 	return m;
186*aca3beaaSApple OSS Distributions }
187*aca3beaaSApple OSS Distributions 
188*aca3beaaSApple OSS Distributions struct mbuf *
pbuf_clone_to_mbuf(pbuf_t * pbuf)189*aca3beaaSApple OSS Distributions pbuf_clone_to_mbuf(pbuf_t *pbuf)
190*aca3beaaSApple OSS Distributions {
191*aca3beaaSApple OSS Distributions 	struct mbuf *m = NULL;
192*aca3beaaSApple OSS Distributions 
193*aca3beaaSApple OSS Distributions 	pbuf_sync(pbuf);
194*aca3beaaSApple OSS Distributions 
195*aca3beaaSApple OSS Distributions 	if (pbuf->pb_type == PBUF_TYPE_MBUF) {
196*aca3beaaSApple OSS Distributions 		m = m_copy(pbuf->pb_mbuf, 0, M_COPYALL);
197*aca3beaaSApple OSS Distributions 	} else if (pbuf->pb_type == PBUF_TYPE_MEMORY) {
198*aca3beaaSApple OSS Distributions 		m = pbuf_to_mbuf(pbuf, FALSE);
199*aca3beaaSApple OSS Distributions 	} else {
200*aca3beaaSApple OSS Distributions 		panic("%s: bad pb_type: %d", __func__, pbuf->pb_type);
201*aca3beaaSApple OSS Distributions 	}
202*aca3beaaSApple OSS Distributions 
203*aca3beaaSApple OSS Distributions 	return m;
204*aca3beaaSApple OSS Distributions }
205*aca3beaaSApple OSS Distributions 
206*aca3beaaSApple OSS Distributions void *
pbuf_ensure_writable(pbuf_t * pbuf,size_t len)207*aca3beaaSApple OSS Distributions pbuf_ensure_writable(pbuf_t *pbuf, size_t len)
208*aca3beaaSApple OSS Distributions {
209*aca3beaaSApple OSS Distributions 	if (pbuf->pb_type == PBUF_TYPE_MBUF) {
210*aca3beaaSApple OSS Distributions 		struct mbuf *m = pbuf->pb_mbuf;
211*aca3beaaSApple OSS Distributions 
212*aca3beaaSApple OSS Distributions 		if (m_makewritable(&pbuf->pb_mbuf, 0, len, M_DONTWAIT)) {
213*aca3beaaSApple OSS Distributions 			return NULL;
214*aca3beaaSApple OSS Distributions 		}
215*aca3beaaSApple OSS Distributions 
216*aca3beaaSApple OSS Distributions 		if (pbuf->pb_mbuf == NULL) {
217*aca3beaaSApple OSS Distributions 			pbuf_destroy(pbuf);
218*aca3beaaSApple OSS Distributions 			return NULL;
219*aca3beaaSApple OSS Distributions 		}
220*aca3beaaSApple OSS Distributions 
221*aca3beaaSApple OSS Distributions 		if (m != pbuf->pb_mbuf) {
222*aca3beaaSApple OSS Distributions 			pbuf_sync(pbuf);
223*aca3beaaSApple OSS Distributions 		}
224*aca3beaaSApple OSS Distributions 	} else if (pbuf->pb_type != PBUF_TYPE_MEMORY) {
225*aca3beaaSApple OSS Distributions 		panic("%s: bad pb_type: %d", __func__, pbuf->pb_type);
226*aca3beaaSApple OSS Distributions 	}
227*aca3beaaSApple OSS Distributions 
228*aca3beaaSApple OSS Distributions 	return pbuf->pb_data;
229*aca3beaaSApple OSS Distributions }
230*aca3beaaSApple OSS Distributions 
231*aca3beaaSApple OSS Distributions void *
pbuf_resize_segment(pbuf_t * pbuf,int off,int olen,int nlen)232*aca3beaaSApple OSS Distributions pbuf_resize_segment(pbuf_t *pbuf, int off, int olen, int nlen)
233*aca3beaaSApple OSS Distributions {
234*aca3beaaSApple OSS Distributions 	void *rv = NULL;
235*aca3beaaSApple OSS Distributions 
236*aca3beaaSApple OSS Distributions 	VERIFY(off >= 0);
237*aca3beaaSApple OSS Distributions 	VERIFY((u_int)off <= pbuf->pb_packet_len);
238*aca3beaaSApple OSS Distributions 
239*aca3beaaSApple OSS Distributions 	if (pbuf->pb_type == PBUF_TYPE_MBUF) {
240*aca3beaaSApple OSS Distributions 		struct mbuf *m, *n;
241*aca3beaaSApple OSS Distributions 
242*aca3beaaSApple OSS Distributions 		VERIFY(pbuf->pb_mbuf != NULL);
243*aca3beaaSApple OSS Distributions 
244*aca3beaaSApple OSS Distributions 		m = pbuf->pb_mbuf;
245*aca3beaaSApple OSS Distributions 
246*aca3beaaSApple OSS Distributions 		if (off > 0) {
247*aca3beaaSApple OSS Distributions 			/* Split the mbuf chain at the specified boundary */
248*aca3beaaSApple OSS Distributions 			if ((n = m_split(m, off, M_DONTWAIT)) == NULL) {
249*aca3beaaSApple OSS Distributions 				return NULL;
250*aca3beaaSApple OSS Distributions 			}
251*aca3beaaSApple OSS Distributions 		} else {
252*aca3beaaSApple OSS Distributions 			n = m;
253*aca3beaaSApple OSS Distributions 		}
254*aca3beaaSApple OSS Distributions 
255*aca3beaaSApple OSS Distributions 		/* Trim old length */
256*aca3beaaSApple OSS Distributions 		m_adj(n, olen);
257*aca3beaaSApple OSS Distributions 
258*aca3beaaSApple OSS Distributions 		/* Prepend new length */
259*aca3beaaSApple OSS Distributions 		if (M_PREPEND(n, nlen, M_DONTWAIT, 0) == NULL) {
260*aca3beaaSApple OSS Distributions 			/* mbuf is freed by M_PREPEND in this case */
261*aca3beaaSApple OSS Distributions 			pbuf->pb_mbuf = NULL;
262*aca3beaaSApple OSS Distributions 			pbuf_destroy(pbuf);
263*aca3beaaSApple OSS Distributions 			return NULL;
264*aca3beaaSApple OSS Distributions 		}
265*aca3beaaSApple OSS Distributions 
266*aca3beaaSApple OSS Distributions 		rv = mtod(n, void *);
267*aca3beaaSApple OSS Distributions 
268*aca3beaaSApple OSS Distributions 		if (off > 0) {
269*aca3beaaSApple OSS Distributions 			/* Merge the two chains */
270*aca3beaaSApple OSS Distributions 			int mlen;
271*aca3beaaSApple OSS Distributions 
272*aca3beaaSApple OSS Distributions 			mlen = n->m_pkthdr.len;
273*aca3beaaSApple OSS Distributions 			m_cat(m, n);
274*aca3beaaSApple OSS Distributions 			m->m_pkthdr.len += mlen;
275*aca3beaaSApple OSS Distributions 		} else {
276*aca3beaaSApple OSS Distributions 			/* The new mbuf becomes the packet header */
277*aca3beaaSApple OSS Distributions 			pbuf->pb_mbuf = n;
278*aca3beaaSApple OSS Distributions 		}
279*aca3beaaSApple OSS Distributions 
280*aca3beaaSApple OSS Distributions 		pbuf_sync(pbuf);
281*aca3beaaSApple OSS Distributions 	} else if (pbuf->pb_type == PBUF_TYPE_MEMORY) {
282*aca3beaaSApple OSS Distributions 		struct pbuf_memory *nm = &pbuf->pb_memory;
283*aca3beaaSApple OSS Distributions 		u_int true_offset, move_len;
284*aca3beaaSApple OSS Distributions 		int delta_len;
285*aca3beaaSApple OSS Distributions 		uint8_t *psrc, *pdst;
286*aca3beaaSApple OSS Distributions 
287*aca3beaaSApple OSS Distributions 		delta_len = nlen - olen;
288*aca3beaaSApple OSS Distributions 		VERIFY(nm->pm_offset + (nm->pm_len + delta_len) <=
289*aca3beaaSApple OSS Distributions 		    nm->pm_buffer_len);
290*aca3beaaSApple OSS Distributions 
291*aca3beaaSApple OSS Distributions 		true_offset = (u_int)off + nm->pm_offset;
292*aca3beaaSApple OSS Distributions 		rv = &nm->pm_buffer[true_offset];
293*aca3beaaSApple OSS Distributions 		psrc = &nm->pm_buffer[true_offset + (u_int)olen];
294*aca3beaaSApple OSS Distributions 		pdst = &nm->pm_buffer[true_offset + (u_int)nlen];
295*aca3beaaSApple OSS Distributions 		move_len = pbuf->pb_packet_len - ((u_int)off + olen);
296*aca3beaaSApple OSS Distributions 		memmove(pdst, psrc, move_len);
297*aca3beaaSApple OSS Distributions 
298*aca3beaaSApple OSS Distributions 		nm->pm_len += delta_len;
299*aca3beaaSApple OSS Distributions 
300*aca3beaaSApple OSS Distributions 		VERIFY((nm->pm_len + nm->pm_offset) <= nm->pm_buffer_len);
301*aca3beaaSApple OSS Distributions 
302*aca3beaaSApple OSS Distributions 		pbuf_sync(pbuf);
303*aca3beaaSApple OSS Distributions 	} else {
304*aca3beaaSApple OSS Distributions 		panic("pbuf_csum_flags_get: bad pb_type: %d", pbuf->pb_type);
305*aca3beaaSApple OSS Distributions 	}
306*aca3beaaSApple OSS Distributions 	return rv;
307*aca3beaaSApple OSS Distributions }
308*aca3beaaSApple OSS Distributions 
309*aca3beaaSApple OSS Distributions void *
pbuf_contig_segment(pbuf_t * pbuf,int off,int len)310*aca3beaaSApple OSS Distributions pbuf_contig_segment(pbuf_t *pbuf, int off, int len)
311*aca3beaaSApple OSS Distributions {
312*aca3beaaSApple OSS Distributions 	void *rv = NULL;
313*aca3beaaSApple OSS Distributions 
314*aca3beaaSApple OSS Distributions 	VERIFY(off >= 0);
315*aca3beaaSApple OSS Distributions 	VERIFY(len >= 0);
316*aca3beaaSApple OSS Distributions 	VERIFY((u_int)(off + len) <= pbuf->pb_packet_len);
317*aca3beaaSApple OSS Distributions 
318*aca3beaaSApple OSS Distributions 	/*
319*aca3beaaSApple OSS Distributions 	 * Note: If this fails, then the pbuf is destroyed. This is a
320*aca3beaaSApple OSS Distributions 	 * side-effect of m_pulldown().
321*aca3beaaSApple OSS Distributions 	 *
322*aca3beaaSApple OSS Distributions 	 * PF expects this behaviour so it's not a real problem.
323*aca3beaaSApple OSS Distributions 	 */
324*aca3beaaSApple OSS Distributions 	if (pbuf->pb_type == PBUF_TYPE_MBUF) {
325*aca3beaaSApple OSS Distributions 		struct mbuf *n;
326*aca3beaaSApple OSS Distributions 		int moff;
327*aca3beaaSApple OSS Distributions 
328*aca3beaaSApple OSS Distributions 		n = m_pulldown(pbuf->pb_mbuf, off, len, &moff);
329*aca3beaaSApple OSS Distributions 		if (n == NULL) {
330*aca3beaaSApple OSS Distributions 			/* mbuf is freed by m_pulldown() in this case */
331*aca3beaaSApple OSS Distributions 			pbuf->pb_mbuf = NULL;
332*aca3beaaSApple OSS Distributions 			pbuf_destroy(pbuf);
333*aca3beaaSApple OSS Distributions 			return NULL;
334*aca3beaaSApple OSS Distributions 		}
335*aca3beaaSApple OSS Distributions 
336*aca3beaaSApple OSS Distributions 		pbuf_sync(pbuf);
337*aca3beaaSApple OSS Distributions 
338*aca3beaaSApple OSS Distributions 		rv = (void *)(mtod(n, uint8_t *) + moff);
339*aca3beaaSApple OSS Distributions 	} else if (pbuf->pb_type == PBUF_TYPE_MEMORY) {
340*aca3beaaSApple OSS Distributions 		/*
341*aca3beaaSApple OSS Distributions 		 * This always succeeds since memory pbufs are fully contig.
342*aca3beaaSApple OSS Distributions 		 */
343*aca3beaaSApple OSS Distributions 		rv = (void *)(uintptr_t)(((uint8_t *)pbuf->pb_data)[off]);
344*aca3beaaSApple OSS Distributions 	} else {
345*aca3beaaSApple OSS Distributions 		panic("%s: bad pb_type: %d", __func__, pbuf->pb_type);
346*aca3beaaSApple OSS Distributions 	}
347*aca3beaaSApple OSS Distributions 
348*aca3beaaSApple OSS Distributions 	return rv;
349*aca3beaaSApple OSS Distributions }
350*aca3beaaSApple OSS Distributions 
351*aca3beaaSApple OSS Distributions void
pbuf_copy_back(pbuf_t * pbuf,int off,int len,void * src)352*aca3beaaSApple OSS Distributions pbuf_copy_back(pbuf_t *pbuf, int off, int len, void *src)
353*aca3beaaSApple OSS Distributions {
354*aca3beaaSApple OSS Distributions 	VERIFY(off >= 0);
355*aca3beaaSApple OSS Distributions 	VERIFY(len >= 0);
356*aca3beaaSApple OSS Distributions 	VERIFY((u_int)(off + len) <= pbuf->pb_packet_len);
357*aca3beaaSApple OSS Distributions 
358*aca3beaaSApple OSS Distributions 	if (pbuf->pb_type == PBUF_TYPE_MBUF) {
359*aca3beaaSApple OSS Distributions 		m_copyback(pbuf->pb_mbuf, off, len, src);
360*aca3beaaSApple OSS Distributions 	} else if (pbuf->pb_type == PBUF_TYPE_MEMORY) {
361*aca3beaaSApple OSS Distributions 		if (len) {
362*aca3beaaSApple OSS Distributions 			memcpy(&((uint8_t *)pbuf->pb_data)[off], src, len);
363*aca3beaaSApple OSS Distributions 		}
364*aca3beaaSApple OSS Distributions 	} else {
365*aca3beaaSApple OSS Distributions 		panic("%s: bad pb_type: %d", __func__, pbuf->pb_type);
366*aca3beaaSApple OSS Distributions 	}
367*aca3beaaSApple OSS Distributions }
368*aca3beaaSApple OSS Distributions 
369*aca3beaaSApple OSS Distributions void
pbuf_copy_data(pbuf_t * pbuf,int off,int len,void * dst)370*aca3beaaSApple OSS Distributions pbuf_copy_data(pbuf_t *pbuf, int off, int len, void *dst)
371*aca3beaaSApple OSS Distributions {
372*aca3beaaSApple OSS Distributions 	VERIFY(off >= 0);
373*aca3beaaSApple OSS Distributions 	VERIFY(len >= 0);
374*aca3beaaSApple OSS Distributions 	VERIFY((u_int)(off + len) <= pbuf->pb_packet_len);
375*aca3beaaSApple OSS Distributions 
376*aca3beaaSApple OSS Distributions 	if (pbuf->pb_type == PBUF_TYPE_MBUF) {
377*aca3beaaSApple OSS Distributions 		m_copydata(pbuf->pb_mbuf, off, len, dst);
378*aca3beaaSApple OSS Distributions 	} else if (pbuf->pb_type == PBUF_TYPE_MEMORY) {
379*aca3beaaSApple OSS Distributions 		if (len) {
380*aca3beaaSApple OSS Distributions 			memcpy(dst, &((uint8_t *)pbuf->pb_data)[off], len);
381*aca3beaaSApple OSS Distributions 		}
382*aca3beaaSApple OSS Distributions 	} else {
383*aca3beaaSApple OSS Distributions 		panic("%s: bad pb_type: %d", __func__, pbuf->pb_type);
384*aca3beaaSApple OSS Distributions 	}
385*aca3beaaSApple OSS Distributions }
386*aca3beaaSApple OSS Distributions 
387*aca3beaaSApple OSS Distributions uint16_t
pbuf_inet_cksum(const pbuf_t * pbuf,uint32_t nxt,uint32_t off,uint32_t len)388*aca3beaaSApple OSS Distributions pbuf_inet_cksum(const pbuf_t *pbuf, uint32_t nxt, uint32_t off, uint32_t len)
389*aca3beaaSApple OSS Distributions {
390*aca3beaaSApple OSS Distributions 	uint16_t sum = 0;
391*aca3beaaSApple OSS Distributions 
392*aca3beaaSApple OSS Distributions 	if (pbuf->pb_type == PBUF_TYPE_MBUF) {
393*aca3beaaSApple OSS Distributions 		sum = inet_cksum(pbuf->pb_mbuf, nxt, off, len);
394*aca3beaaSApple OSS Distributions 	} else if (pbuf->pb_type == PBUF_TYPE_MEMORY) {
395*aca3beaaSApple OSS Distributions 		sum = inet_cksum_buffer(pbuf->pb_data, nxt, off, len);
396*aca3beaaSApple OSS Distributions 	} else {
397*aca3beaaSApple OSS Distributions 		panic("%s: bad pb_type: %d", __func__, pbuf->pb_type);
398*aca3beaaSApple OSS Distributions 	}
399*aca3beaaSApple OSS Distributions 
400*aca3beaaSApple OSS Distributions 	return sum;
401*aca3beaaSApple OSS Distributions }
402*aca3beaaSApple OSS Distributions 
403*aca3beaaSApple OSS Distributions uint16_t
pbuf_inet6_cksum(const pbuf_t * pbuf,uint32_t nxt,uint32_t off,uint32_t len)404*aca3beaaSApple OSS Distributions pbuf_inet6_cksum(const pbuf_t *pbuf, uint32_t nxt, uint32_t off, uint32_t len)
405*aca3beaaSApple OSS Distributions {
406*aca3beaaSApple OSS Distributions 	uint16_t sum = 0;
407*aca3beaaSApple OSS Distributions 
408*aca3beaaSApple OSS Distributions 	if (pbuf->pb_type == PBUF_TYPE_MBUF) {
409*aca3beaaSApple OSS Distributions 		sum = inet6_cksum(pbuf->pb_mbuf, nxt, off, len);
410*aca3beaaSApple OSS Distributions 	} else if (pbuf->pb_type == PBUF_TYPE_MEMORY) {
411*aca3beaaSApple OSS Distributions 		sum = inet6_cksum_buffer(pbuf->pb_data, nxt, off, len);
412*aca3beaaSApple OSS Distributions 	} else {
413*aca3beaaSApple OSS Distributions 		panic("%s: bad pb_type: %d", __func__, pbuf->pb_type);
414*aca3beaaSApple OSS Distributions 	}
415*aca3beaaSApple OSS Distributions 
416*aca3beaaSApple OSS Distributions 	return sum;
417*aca3beaaSApple OSS Distributions }
418*aca3beaaSApple OSS Distributions 
419*aca3beaaSApple OSS Distributions mbuf_svc_class_t
pbuf_get_service_class(const pbuf_t * pbuf)420*aca3beaaSApple OSS Distributions pbuf_get_service_class(const pbuf_t *pbuf)
421*aca3beaaSApple OSS Distributions {
422*aca3beaaSApple OSS Distributions 	if (pbuf->pb_type == PBUF_TYPE_MBUF) {
423*aca3beaaSApple OSS Distributions 		return m_get_service_class(pbuf->pb_mbuf);
424*aca3beaaSApple OSS Distributions 	}
425*aca3beaaSApple OSS Distributions 
426*aca3beaaSApple OSS Distributions 	VERIFY(pbuf->pb_type == PBUF_TYPE_MEMORY);
427*aca3beaaSApple OSS Distributions 
428*aca3beaaSApple OSS Distributions 	return MBUF_SC_BE;
429*aca3beaaSApple OSS Distributions }
430*aca3beaaSApple OSS Distributions 
431*aca3beaaSApple OSS Distributions void *
pbuf_get_packet_buffer_address(const pbuf_t * pbuf)432*aca3beaaSApple OSS Distributions pbuf_get_packet_buffer_address(const pbuf_t *pbuf)
433*aca3beaaSApple OSS Distributions {
434*aca3beaaSApple OSS Distributions 	VERIFY(pbuf != NULL);
435*aca3beaaSApple OSS Distributions 
436*aca3beaaSApple OSS Distributions 	if (pbuf->pb_type == PBUF_TYPE_MBUF) {
437*aca3beaaSApple OSS Distributions 		return pbuf->pb_mbuf;
438*aca3beaaSApple OSS Distributions 	} else {
439*aca3beaaSApple OSS Distributions 		return pbuf->pb_memory.pm_buffer;
440*aca3beaaSApple OSS Distributions 	}
441*aca3beaaSApple OSS Distributions }
442