]>
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
);