]>
git.saurik.com Git - apple/xnu.git/blob - bsd/net/pf_pbuf.c
2 * Copyright (c) 2016-2018 Apple Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
21 * @APPLE_LICENSE_HEADER_END@
24 #include <sys/cdefs.h>
25 #include <sys/systm.h>
26 #include <sys/param.h>
27 #include <sys/types.h>
28 #include <sys/mcache.h>
29 #include <kern/kern_types.h>
30 #include <net/pf_pbuf.h>
31 #include <net/pfvar.h>
32 #include <netinet/in.h>
35 pbuf_init_mbuf(pbuf_t
*pbuf
, struct mbuf
*m
, struct ifnet
*ifp
)
37 VERIFY((m
->m_flags
& M_PKTHDR
) != 0);
39 pbuf
->pb_type
= PBUF_TYPE_MBUF
;
47 pbuf_init_memory(pbuf_t
*pbuf
, const struct pbuf_memory
*mp
, struct ifnet
*ifp
)
49 pbuf
->pb_type
= PBUF_TYPE_MEMORY
;
50 pbuf
->pb_memory
= *mp
;
57 pbuf_destroy(pbuf_t
*pbuf
)
59 if (pbuf
->pb_type
== PBUF_TYPE_MBUF
) {
61 m_freem(pbuf
->pb_mbuf
);
64 } else if (pbuf
->pb_type
== PBUF_TYPE_MEMORY
) {
65 VERIFY(pbuf
->pb_memory
.pm_buffer
!= NULL
);
66 (void) (pbuf
->pb_memory
.pm_action
)(&pbuf
->pb_memory
,
69 VERIFY(pbuf
->pb_type
== PBUF_TYPE_ZOMBIE
);
72 memset(pbuf
, 0, sizeof(*pbuf
));
76 pbuf_sync(pbuf_t
*pbuf
)
78 if (pbuf
->pb_type
== PBUF_TYPE_MBUF
) {
79 struct mbuf
*m
= pbuf
->pb_mbuf
;
82 VERIFY(m
->m_flags
& M_PKTHDR
);
84 pbuf
->pb_data
= mtod(m
, void *);
85 pbuf
->pb_packet_len
= m
->m_pkthdr
.len
;
86 pbuf
->pb_contig_len
= m
->m_len
;
87 pbuf
->pb_csum_flags
= &m
->m_pkthdr
.csum_flags
;
88 pbuf
->pb_csum_data
= &m
->m_pkthdr
.csum_data
;
89 pbuf
->pb_proto
= &m
->m_pkthdr
.pkt_proto
;
90 pbuf
->pb_flowsrc
= &m
->m_pkthdr
.pkt_flowsrc
;
91 pbuf
->pb_flowid
= &m
->m_pkthdr
.pkt_flowid
;
92 pbuf
->pb_flags
= &m
->m_pkthdr
.pkt_flags
;
93 pbuf
->pb_pftag
= m_pftag(m
);
94 pbuf
->pb_pf_fragtag
= pf_find_fragment_tag(m
);
95 ASSERT((pbuf
->pb_pf_fragtag
== NULL
) ||
96 (pbuf
->pb_pftag
->pftag_flags
& PF_TAG_REASSEMBLED
));
97 } else if (pbuf
->pb_type
== PBUF_TYPE_MEMORY
) {
98 struct pbuf_memory
*nm
= &pbuf
->pb_memory
;
100 VERIFY(nm
->pm_buffer
!= NULL
);
101 VERIFY(nm
->pm_buffer_len
!= 0);
102 VERIFY(nm
->pm_len
!= 0);
103 VERIFY(nm
->pm_len
<= nm
->pm_buffer_len
);
104 VERIFY(nm
->pm_offset
< nm
->pm_len
);
106 pbuf
->pb_data
= &nm
->pm_buffer
[nm
->pm_offset
];
107 pbuf
->pb_packet_len
= nm
->pm_len
;
108 pbuf
->pb_contig_len
= nm
->pm_len
;
109 pbuf
->pb_csum_flags
= &nm
->pm_csum_flags
;
110 pbuf
->pb_csum_data
= &nm
->pm_csum_data
;
111 pbuf
->pb_proto
= &nm
->pm_proto
;
112 pbuf
->pb_flowsrc
= &nm
->pm_flowsrc
;
113 pbuf
->pb_flowid
= &nm
->pm_flowid
;
114 pbuf
->pb_flags
= &nm
->pm_flags
;
115 pbuf
->pb_pftag
= &nm
->pm_pftag
;
116 pbuf
->pb_pf_fragtag
= &nm
->pm_pf_fragtag
;
118 panic("%s: bad pb_type: %d", __func__
, pbuf
->pb_type
);
123 pbuf_to_mbuf(pbuf_t
*pbuf
, boolean_t release_ptr
)
125 struct mbuf
*m
= NULL
;
129 if (pbuf
->pb_type
== PBUF_TYPE_MBUF
) {
132 pbuf
->pb_mbuf
= NULL
;
134 } else if (pbuf
->pb_type
== PBUF_TYPE_MEMORY
) {
135 boolean_t fragtag
= FALSE
;
137 if (pbuf
->pb_packet_len
> (u_int
)MHLEN
) {
138 if (pbuf
->pb_packet_len
> (u_int
)MCLBYTES
) {
139 printf("%s: packet too big for cluster (%u)\n",
140 __func__
, pbuf
->pb_packet_len
);
143 m
= m_getcl(M_WAITOK
, MT_DATA
, M_PKTHDR
);
145 m
= m_gethdr(M_DONTWAIT
, MT_DATA
);
151 m_copyback(m
, 0, pbuf
->pb_packet_len
, pbuf
->pb_data
);
152 m
->m_pkthdr
.csum_flags
= *pbuf
->pb_csum_flags
;
153 m
->m_pkthdr
.csum_data
= *pbuf
->pb_csum_data
;
154 m
->m_pkthdr
.pkt_proto
= *pbuf
->pb_proto
;
155 m
->m_pkthdr
.pkt_flowsrc
= *pbuf
->pb_flowsrc
;
156 m
->m_pkthdr
.pkt_flowid
= *pbuf
->pb_flowid
;
157 m
->m_pkthdr
.pkt_flags
= *pbuf
->pb_flags
;
159 if (pbuf
->pb_pftag
!= NULL
) {
160 struct pf_mtag
*pftag
= m_pftag(m
);
162 ASSERT(pftag
!= NULL
);
163 *pftag
= *pbuf
->pb_pftag
;
165 ((pftag
->pftag_flags
& PF_TAG_REASSEMBLED
) != 0);
168 if (fragtag
&& pbuf
->pb_pf_fragtag
!= NULL
) {
169 if (pf_copy_fragment_tag(m
, pbuf
->pb_pf_fragtag
,
186 pbuf_clone_to_mbuf(pbuf_t
*pbuf
)
188 struct mbuf
*m
= NULL
;
192 if (pbuf
->pb_type
== PBUF_TYPE_MBUF
) {
193 m
= m_copy(pbuf
->pb_mbuf
, 0, M_COPYALL
);
194 } else if (pbuf
->pb_type
== PBUF_TYPE_MEMORY
) {
195 m
= pbuf_to_mbuf(pbuf
, FALSE
);
197 panic("%s: bad pb_type: %d", __func__
, pbuf
->pb_type
);
204 pbuf_ensure_writable(pbuf_t
*pbuf
, size_t len
)
206 if (pbuf
->pb_type
== PBUF_TYPE_MBUF
) {
207 struct mbuf
*m
= pbuf
->pb_mbuf
;
209 if (m_makewritable(&pbuf
->pb_mbuf
, 0, len
, M_DONTWAIT
)) {
213 if (pbuf
->pb_mbuf
== NULL
) {
218 if (m
!= pbuf
->pb_mbuf
) {
221 } else if (pbuf
->pb_type
!= PBUF_TYPE_MEMORY
) {
222 panic("%s: bad pb_type: %d", __func__
, pbuf
->pb_type
);
225 return pbuf
->pb_data
;
229 pbuf_resize_segment(pbuf_t
*pbuf
, int off
, int olen
, int nlen
)
234 VERIFY((u_int
)off
<= pbuf
->pb_packet_len
);
236 if (pbuf
->pb_type
== PBUF_TYPE_MBUF
) {
239 VERIFY(pbuf
->pb_mbuf
!= NULL
);
244 /* Split the mbuf chain at the specified boundary */
245 if ((n
= m_split(m
, off
, M_DONTWAIT
)) == NULL
) {
252 /* Trim old length */
255 /* Prepend new length */
256 if (M_PREPEND(n
, nlen
, M_DONTWAIT
, 0) == NULL
) {
260 rv
= mtod(n
, void *);
263 /* Merge the two chains */
266 mlen
= n
->m_pkthdr
.len
;
268 m
->m_pkthdr
.len
+= mlen
;
270 /* The new mbuf becomes the packet header */
275 } else if (pbuf
->pb_type
== PBUF_TYPE_MEMORY
) {
276 struct pbuf_memory
*nm
= &pbuf
->pb_memory
;
277 u_int true_offset
, move_len
;
279 uint8_t *psrc
, *pdst
;
281 delta_len
= nlen
- olen
;
282 VERIFY(nm
->pm_offset
+ (nm
->pm_len
+ delta_len
) <=
285 true_offset
= (u_int
)off
+ nm
->pm_offset
;
286 rv
= &nm
->pm_buffer
[true_offset
];
287 psrc
= &nm
->pm_buffer
[true_offset
+ (u_int
)olen
];
288 pdst
= &nm
->pm_buffer
[true_offset
+ (u_int
)nlen
];
289 move_len
= pbuf
->pb_packet_len
- ((u_int
)off
+ olen
);
290 memmove(pdst
, psrc
, move_len
);
292 nm
->pm_len
+= delta_len
;
294 VERIFY((nm
->pm_len
+ nm
->pm_offset
) <= nm
->pm_buffer_len
);
298 panic("pbuf_csum_flags_get: bad pb_type: %d", pbuf
->pb_type
);
304 pbuf_contig_segment(pbuf_t
*pbuf
, int off
, int len
)
310 VERIFY((u_int
)(off
+ len
) <= pbuf
->pb_packet_len
);
313 * Note: If this fails, then the pbuf is destroyed. This is a
314 * side-effect of m_pulldown().
316 * PF expects this behaviour so it's not a real problem.
318 if (pbuf
->pb_type
== PBUF_TYPE_MBUF
) {
322 n
= m_pulldown(pbuf
->pb_mbuf
, off
, len
, &moff
);
324 /* mbuf is freed by m_pulldown() in this case */
325 pbuf
->pb_mbuf
= NULL
;
332 rv
= (void *)(mtod(n
, uint8_t *) + moff
);
333 } else if (pbuf
->pb_type
== PBUF_TYPE_MEMORY
) {
335 * This always succeeds since memory pbufs are fully contig.
337 rv
= (void *)(uintptr_t)(((uint8_t *)pbuf
->pb_data
)[off
]);
339 panic("%s: bad pb_type: %d", __func__
, pbuf
->pb_type
);
346 pbuf_copy_back(pbuf_t
*pbuf
, int off
, int len
, void *src
)
350 VERIFY((u_int
)(off
+ len
) <= pbuf
->pb_packet_len
);
352 if (pbuf
->pb_type
== PBUF_TYPE_MBUF
) {
353 m_copyback(pbuf
->pb_mbuf
, off
, len
, src
);
354 } else if (pbuf
->pb_type
== PBUF_TYPE_MEMORY
) {
356 memcpy(&((uint8_t *)pbuf
->pb_data
)[off
], src
, len
);
359 panic("%s: bad pb_type: %d", __func__
, pbuf
->pb_type
);
364 pbuf_copy_data(pbuf_t
*pbuf
, int off
, int len
, void *dst
)
368 VERIFY((u_int
)(off
+ len
) <= pbuf
->pb_packet_len
);
370 if (pbuf
->pb_type
== PBUF_TYPE_MBUF
) {
371 m_copydata(pbuf
->pb_mbuf
, off
, len
, dst
);
372 } else if (pbuf
->pb_type
== PBUF_TYPE_MEMORY
) {
374 memcpy(dst
, &((uint8_t *)pbuf
->pb_data
)[off
], len
);
377 panic("%s: bad pb_type: %d", __func__
, pbuf
->pb_type
);
382 pbuf_inet_cksum(const pbuf_t
*pbuf
, uint32_t nxt
, uint32_t off
, uint32_t len
)
386 if (pbuf
->pb_type
== PBUF_TYPE_MBUF
) {
387 sum
= inet_cksum(pbuf
->pb_mbuf
, nxt
, off
, len
);
388 } else if (pbuf
->pb_type
== PBUF_TYPE_MEMORY
) {
389 sum
= inet_cksum_buffer(pbuf
->pb_data
, nxt
, off
, len
);
391 panic("%s: bad pb_type: %d", __func__
, pbuf
->pb_type
);
398 pbuf_inet6_cksum(const pbuf_t
*pbuf
, uint32_t nxt
, uint32_t off
, uint32_t len
)
402 if (pbuf
->pb_type
== PBUF_TYPE_MBUF
) {
403 sum
= inet6_cksum(pbuf
->pb_mbuf
, nxt
, off
, len
);
404 } else if (pbuf
->pb_type
== PBUF_TYPE_MEMORY
) {
405 sum
= inet6_cksum_buffer(pbuf
->pb_data
, nxt
, off
, len
);
407 panic("%s: bad pb_type: %d", __func__
, pbuf
->pb_type
);
414 pbuf_get_service_class(const pbuf_t
*pbuf
)
416 if (pbuf
->pb_type
== PBUF_TYPE_MBUF
) {
417 return m_get_service_class(pbuf
->pb_mbuf
);
420 VERIFY(pbuf
->pb_type
== PBUF_TYPE_MEMORY
);