]>
git.saurik.com Git - apple/xnu.git/blob - bsd/net/pf_pbuf.c
2 * Copyright (c) 2016-2017 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 <netinet/in.h>
34 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
)
50 pbuf
->pb_type
= PBUF_TYPE_MEMORY
;
51 pbuf
->pb_memory
= *mp
;
58 pbuf_destroy(pbuf_t
*pbuf
)
61 if (pbuf
->pb_type
== PBUF_TYPE_MBUF
) {
63 m_freem(pbuf
->pb_mbuf
);
67 if (pbuf
->pb_type
== PBUF_TYPE_MEMORY
) {
68 VERIFY(pbuf
->pb_memory
.pm_buffer
!= NULL
);
69 (void) (pbuf
->pb_memory
.pm_action
)(&pbuf
->pb_memory
,
72 VERIFY(pbuf
->pb_type
== PBUF_TYPE_ZOMBIE
);
75 memset(pbuf
, 0, sizeof(*pbuf
));
79 pbuf_sync(pbuf_t
*pbuf
)
82 if (pbuf
->pb_type
== PBUF_TYPE_MBUF
) {
83 struct mbuf
*m
= pbuf
->pb_mbuf
;
86 VERIFY(m
->m_flags
& M_PKTHDR
);
88 pbuf
->pb_data
= mtod(m
, void *);
89 pbuf
->pb_packet_len
= m
->m_pkthdr
.len
;
90 pbuf
->pb_contig_len
= m
->m_len
;
91 pbuf
->pb_csum_flags
= &m
->m_pkthdr
.csum_flags
;
92 pbuf
->pb_csum_data
= &m
->m_pkthdr
.csum_data
;
93 pbuf
->pb_proto
= &m
->m_pkthdr
.pkt_proto
;
94 pbuf
->pb_flowsrc
= &m
->m_pkthdr
.pkt_flowsrc
;
95 pbuf
->pb_flowid
= &m
->m_pkthdr
.pkt_flowid
;
96 pbuf
->pb_flags
= &m
->m_pkthdr
.pkt_flags
;
97 pbuf
->pb_pftag
= m_pftag(m
);
99 if (pbuf
->pb_type
== PBUF_TYPE_MEMORY
) {
100 struct pbuf_memory
*nm
= &pbuf
->pb_memory
;
102 VERIFY(nm
->pm_buffer
!= NULL
);
103 VERIFY(nm
->pm_buffer_len
!= 0);
104 VERIFY(nm
->pm_len
!= 0);
105 VERIFY(nm
->pm_len
<= nm
->pm_buffer_len
);
106 VERIFY(nm
->pm_offset
< nm
->pm_len
);
108 pbuf
->pb_data
= &nm
->pm_buffer
[nm
->pm_offset
];
109 pbuf
->pb_packet_len
= nm
->pm_len
;
110 pbuf
->pb_contig_len
= nm
->pm_len
;
111 pbuf
->pb_csum_flags
= &nm
->pm_csum_flags
;
112 pbuf
->pb_csum_data
= &nm
->pm_csum_data
;
113 pbuf
->pb_proto
= &nm
->pm_proto
;
114 pbuf
->pb_flowsrc
= &nm
->pm_flowsrc
;
115 pbuf
->pb_flowid
= &nm
->pm_flowid
;
116 pbuf
->pb_flags
= &nm
->pm_flags
;
117 pbuf
->pb_pftag
= &nm
->pm_pftag
;
119 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
;
136 if (pbuf
->pb_type
== PBUF_TYPE_MEMORY
) {
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
);
150 m_copyback(m
, 0, pbuf
->pb_packet_len
, pbuf
->pb_data
);
151 m
->m_pkthdr
.csum_flags
= *pbuf
->pb_csum_flags
;
152 m
->m_pkthdr
.csum_data
= *pbuf
->pb_csum_data
;
153 m
->m_pkthdr
.pkt_proto
= *pbuf
->pb_proto
;
154 m
->m_pkthdr
.pkt_flowsrc
= *pbuf
->pb_flowsrc
;
155 m
->m_pkthdr
.pkt_flowid
= *pbuf
->pb_flowid
;
156 m
->m_pkthdr
.pkt_flags
= *pbuf
->pb_flags
;
158 if (pbuf
->pb_pftag
!= NULL
) {
159 struct pf_mtag
*pftag
= m_pftag(m
);
162 *pftag
= *pbuf
->pb_pftag
;
173 pbuf_clone_to_mbuf(pbuf_t
*pbuf
)
175 struct mbuf
*m
= NULL
;
179 if (pbuf
->pb_type
== PBUF_TYPE_MBUF
)
180 m
= m_copy(pbuf
->pb_mbuf
, 0, M_COPYALL
);
182 if (pbuf
->pb_type
== PBUF_TYPE_MEMORY
)
183 m
= pbuf_to_mbuf(pbuf
, FALSE
);
185 panic("%s: bad pb_type: %d", __func__
, pbuf
->pb_type
);
191 pbuf_ensure_writable(pbuf_t
*pbuf
, size_t len
)
194 if (pbuf
->pb_type
== PBUF_TYPE_MBUF
) {
195 struct mbuf
*m
= pbuf
->pb_mbuf
;
197 if (m_makewritable(&pbuf
->pb_mbuf
, 0, len
, M_DONTWAIT
))
200 if (pbuf
->pb_mbuf
== NULL
) {
205 if (m
!= pbuf
->pb_mbuf
)
209 if (pbuf
->pb_type
!= PBUF_TYPE_MEMORY
)
210 panic("%s: bad pb_type: %d", __func__
, pbuf
->pb_type
);
212 return (pbuf
->pb_data
);
216 pbuf_resize_segment(pbuf_t
*pbuf
, int off
, int olen
, int nlen
)
221 VERIFY((u_int
)off
<= pbuf
->pb_packet_len
);
223 if (pbuf
->pb_type
== PBUF_TYPE_MBUF
) {
226 VERIFY(pbuf
->pb_mbuf
!= NULL
);
231 /* Split the mbuf chain at the specified boundary */
232 if ((n
= m_split(m
, off
, M_DONTWAIT
)) == NULL
)
238 /* Trim old length */
241 /* Prepend new length */
242 if (M_PREPEND(n
, nlen
, M_DONTWAIT
, 0) == NULL
)
245 rv
= mtod(n
, void *);
248 /* Merge the two chains */
251 mlen
= n
->m_pkthdr
.len
;
253 m
->m_pkthdr
.len
+= mlen
;
255 /* The new mbuf becomes the packet header */
261 if (pbuf
->pb_type
== PBUF_TYPE_MEMORY
) {
262 struct pbuf_memory
*nm
= &pbuf
->pb_memory
;
263 u_int true_offset
, move_len
;
265 uint8_t *psrc
, *pdst
;
267 delta_len
= nlen
- olen
;
268 VERIFY(nm
->pm_offset
+ (nm
->pm_len
+ delta_len
) <=
271 true_offset
= (u_int
)off
+ nm
->pm_offset
;
272 rv
= &nm
->pm_buffer
[true_offset
];
273 psrc
= &nm
->pm_buffer
[true_offset
+ (u_int
)olen
];
274 pdst
= &nm
->pm_buffer
[true_offset
+ (u_int
)nlen
];
275 move_len
= pbuf
->pb_packet_len
- ((u_int
)off
+ olen
);
276 memmove(pdst
, psrc
, move_len
);
278 nm
->pm_len
+= delta_len
;
280 VERIFY((nm
->pm_len
+ nm
->pm_offset
) <= nm
->pm_buffer_len
);
284 panic("pbuf_csum_flags_get: bad pb_type: %d", pbuf
->pb_type
);
290 pbuf_contig_segment(pbuf_t
*pbuf
, int off
, int len
)
296 VERIFY((u_int
)(off
+ len
) < pbuf
->pb_packet_len
);
299 * Note: If this fails, then the pbuf is destroyed. This is a
300 * side-effect of m_pulldown().
302 * PF expects this behaviour so it's not a real problem.
305 if (pbuf
->pb_type
== PBUF_TYPE_MBUF
) {
309 n
= m_pulldown(pbuf
->pb_mbuf
, off
, len
, &moff
);
311 /* mbuf is freed by m_pulldown() in this case */
312 pbuf
->pb_mbuf
= NULL
;
319 rv
= (void *)(mtod(n
, uint8_t *) + moff
);
321 if (pbuf
->pb_type
== PBUF_TYPE_MEMORY
) {
323 * This always succeeds since memory pbufs are fully contig.
325 rv
= (void *)(uintptr_t)(((uint8_t *)pbuf
->pb_data
)[off
]);
327 panic("%s: bad pb_type: %d", __func__
, pbuf
->pb_type
);
333 pbuf_copy_back(pbuf_t
*pbuf
, int off
, int len
, void *src
)
338 VERIFY((u_int
)(off
+ len
) <= pbuf
->pb_packet_len
);
340 if (pbuf
->pb_type
== PBUF_TYPE_MBUF
)
341 m_copyback(pbuf
->pb_mbuf
, off
, len
, src
);
343 if (pbuf
->pb_type
== PBUF_TYPE_MBUF
) {
345 memcpy(&((uint8_t *)pbuf
->pb_data
)[off
], src
, len
);
347 panic("%s: bad pb_type: %d", __func__
, pbuf
->pb_type
);
351 pbuf_copy_data(pbuf_t
*pbuf
, int off
, int len
, void *dst
)
356 VERIFY((u_int
)(off
+ len
) <= pbuf
->pb_packet_len
);
358 if (pbuf
->pb_type
== PBUF_TYPE_MBUF
)
359 m_copydata(pbuf
->pb_mbuf
, off
, len
, dst
);
361 if (pbuf
->pb_type
== PBUF_TYPE_MBUF
) {
363 memcpy(dst
, &((uint8_t *)pbuf
->pb_data
)[off
], len
);
365 panic("%s: bad pb_type: %d", __func__
, pbuf
->pb_type
);
369 pbuf_inet_cksum(const pbuf_t
*pbuf
, uint32_t nxt
, uint32_t off
, uint32_t len
)
373 if (pbuf
->pb_type
== PBUF_TYPE_MBUF
)
374 sum
= inet_cksum(pbuf
->pb_mbuf
, nxt
, off
, len
);
376 if (pbuf
->pb_type
== PBUF_TYPE_MEMORY
)
377 sum
= inet_cksum_buffer(pbuf
->pb_data
, nxt
, off
, len
);
379 panic("%s: bad pb_type: %d", __func__
, pbuf
->pb_type
);
385 pbuf_inet6_cksum(const pbuf_t
*pbuf
, uint32_t nxt
, uint32_t off
, uint32_t len
)
389 if (pbuf
->pb_type
== PBUF_TYPE_MBUF
)
390 sum
= inet6_cksum(pbuf
->pb_mbuf
, nxt
, off
, len
);
392 if (pbuf
->pb_type
== PBUF_TYPE_MEMORY
)
393 sum
= inet6_cksum_buffer(pbuf
->pb_data
, nxt
, off
, len
);
395 panic("%s: bad pb_type: %d", __func__
, pbuf
->pb_type
);
401 pbuf_get_service_class(const pbuf_t
*pbuf
)
404 if (pbuf
->pb_type
== PBUF_TYPE_MBUF
)
405 return m_get_service_class(pbuf
->pb_mbuf
);
407 VERIFY(pbuf
->pb_type
== PBUF_TYPE_MEMORY
);