]>
git.saurik.com Git - apple/xnu.git/blob - bsd/net/classq/classq_util.c
100943f63be4653a8ec9365d802e446d6b132ad3
2 * Copyright (c) 2007-2011 Apple Inc. All rights reserved.
4 * @APPLE_OSREFERENCE_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. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
30 * Copyright (c) 1991-1997 Regents of the University of California.
31 * All rights reserved.
33 * Redistribution and use in source and binary forms, with or without
34 * modification, are permitted provided that the following conditions
36 * 1. Redistributions of source code must retain the above copyright
37 * notice, this list of conditions and the following disclaimer.
38 * 2. Redistributions in binary form must reproduce the above copyright
39 * notice, this list of conditions and the following disclaimer in the
40 * documentation and/or other materials provided with the distribution.
41 * 3. All advertising materials mentioning features or use of this software
42 * must display the following acknowledgement:
43 * This product includes software developed by the Network Research
44 * Group at Lawrence Berkeley Laboratory.
45 * 4. Neither the name of the University nor of the Laboratory may be used
46 * to endorse or promote products derived from this software without
47 * specific prior written permission.
49 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
50 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
51 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
52 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
53 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
54 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
55 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
56 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
57 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
58 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
62 #include <sys/cdefs.h>
63 #include <sys/param.h>
65 #include <sys/errno.h>
66 #include <sys/random.h>
67 #include <sys/kernel_types.h>
68 #include <sys/sysctl.h>
71 #include <net/net_osdep.h>
72 #include <net/classq/classq.h>
74 #include <netinet/in.h>
75 #include <netinet/in_systm.h>
76 #include <netinet/ip.h>
77 #include <netinet/ip6.h>
78 #include <netinet/tcp.h>
79 #include <netinet/udp.h>
81 #include <libkern/libkern.h>
85 * read and write diffserv field in IPv4 or IPv6 header
88 read_dsfield(struct mbuf
*m
, struct pf_mtag
*t
)
91 u_int8_t ds_field
= 0;
93 if (t
->pftag_hdr
== NULL
||
94 !(t
->pftag_flags
& (PF_TAG_HDR_INET
| PF_TAG_HDR_INET6
))) {
98 /* verify that hdr is within the mbuf data */
99 for (m0
= m
; m0
!= NULL
; m0
= m0
->m_next
) {
100 if (((caddr_t
)t
->pftag_hdr
>= m0
->m_data
) &&
101 ((caddr_t
)t
->pftag_hdr
< m0
->m_data
+ m0
->m_len
)) {
106 /* ick, tag info is stale */
107 printf("%s: can't locate header!\n", __func__
);
111 if (t
->pftag_flags
& PF_TAG_HDR_INET
) {
112 struct ip
*ip
= (struct ip
*)(void *)t
->pftag_hdr
;
114 if (((uintptr_t)ip
+ sizeof(*ip
)) >
115 ((uintptr_t)mbuf_datastart(m0
) + mbuf_maxlen(m0
))) {
116 return 0; /* out of bounds */
119 return (u_int8_t
)0; /* version mismatch! */
121 ds_field
= ip
->ip_tos
;
122 } else if (t
->pftag_flags
& PF_TAG_HDR_INET6
) {
123 struct ip6_hdr
*ip6
= (struct ip6_hdr
*)(void *)t
->pftag_hdr
;
126 if (((uintptr_t)ip6
+ sizeof(*ip6
)) >
127 ((uintptr_t)mbuf_datastart(m0
) + mbuf_maxlen(m0
))) {
128 return 0; /* out of bounds */
130 flowlabel
= ntohl(ip6
->ip6_flow
);
131 if ((flowlabel
>> 28) != 6) {
132 return (u_int8_t
)0; /* version mismatch! */
134 ds_field
= (flowlabel
>> 20) & 0xff;
140 write_dsfield(struct mbuf
*m
, struct pf_mtag
*t
, u_int8_t dsfield
)
144 if (t
->pftag_hdr
== NULL
||
145 !(t
->pftag_flags
& (PF_TAG_HDR_INET
| PF_TAG_HDR_INET6
))) {
149 /* verify that hdr is within the mbuf data */
150 for (m0
= m
; m0
!= NULL
; m0
= m0
->m_next
) {
151 if (((caddr_t
)t
->pftag_hdr
>= m0
->m_data
) &&
152 ((caddr_t
)t
->pftag_hdr
< m0
->m_data
+ m0
->m_len
)) {
157 /* ick, tag info is stale */
158 printf("%s: can't locate header!\n", __func__
);
162 if (t
->pftag_flags
& PF_TAG_HDR_INET
) {
163 struct ip
*ip
= (struct ip
*)(void *)t
->pftag_hdr
;
167 if (((uintptr_t)ip
+ sizeof(*ip
)) >
168 ((uintptr_t)mbuf_datastart(m0
) + mbuf_maxlen(m0
))) {
169 return; /* out of bounds */
172 return; /* version mismatch! */
175 dsfield
|= old
& 3; /* leave CU bits */
176 if (old
== dsfield
) {
179 ip
->ip_tos
= dsfield
;
181 * update checksum (from RFC1624)
182 * HC' = ~(~HC + ~m + m')
184 sum
= ~ntohs(ip
->ip_sum
) & 0xffff;
185 sum
+= 0xff00 + (~old
& 0xff) + dsfield
;
186 sum
= (sum
>> 16) + (sum
& 0xffff);
187 sum
+= (sum
>> 16); /* add carry */
189 ip
->ip_sum
= htons(~sum
& 0xffff);
190 } else if (t
->pftag_flags
& PF_TAG_HDR_INET6
) {
191 struct ip6_hdr
*ip6
= (struct ip6_hdr
*)t
->pftag_hdr
;
194 if (((uintptr_t)ip6
+ sizeof(*ip6
)) >
195 ((uintptr_t)mbuf_datastart(m0
) + mbuf_maxlen(m0
))) {
196 return; /* out of bounds */
198 flowlabel
= ntohl(ip6
->ip6_flow
);
199 if ((flowlabel
>> 28) != 6) {
200 return; /* version mismatch! */
202 flowlabel
= (flowlabel
& 0xf03fffff) | (dsfield
<< 20);
203 ip6
->ip6_flow
= htonl(flowlabel
);
208 * try to mark CE bit to the packet.
209 * returns 1 if successfully marked, 0 otherwise.
212 mark_ecn(struct mbuf
*m
, struct pf_mtag
*t
, int flags
)
218 if ((hdr
= t
->pftag_hdr
) == NULL
||
219 !(t
->pftag_flags
& (PF_TAG_HDR_INET
| PF_TAG_HDR_INET6
))) {
223 /* verify that hdr is within the mbuf data */
224 for (m0
= m
; m0
!= NULL
; m0
= m0
->m_next
) {
225 if (((caddr_t
)hdr
>= m0
->m_data
) &&
226 ((caddr_t
)hdr
< m0
->m_data
+ m0
->m_len
)) {
231 /* ick, tag info is stale */
232 printf("%s: can't locate header!\n", __func__
);
236 if (t
->pftag_flags
& PF_TAG_HDR_INET
) {
238 } else if (t
->pftag_flags
& PF_TAG_HDR_INET6
) {
246 if (flags
& CLASSQF_ECN4
) { /* REDF_ECN4 == BLUEF_ECN4 */
251 if (((uintptr_t)ip
+ sizeof(*ip
)) >
252 ((uintptr_t)mbuf_datastart(m0
) + mbuf_maxlen(m0
))) {
253 return 0; /* out of bounds */
256 return 0; /* version mismatch! */
258 if ((ip
->ip_tos
& IPTOS_ECN_MASK
) == IPTOS_ECN_NOTECT
) {
259 return 0; /* not-ECT */
261 if ((ip
->ip_tos
& IPTOS_ECN_MASK
) == IPTOS_ECN_CE
) {
262 return 1; /* already marked */
265 * ecn-capable but not marked,
266 * mark CE and update checksum
269 ip
->ip_tos
|= IPTOS_ECN_CE
;
271 * update checksum (from RFC1624) only if hw
272 * checksum is not supported.
273 * HC' = ~(~HC + ~m + m')
275 if (!(m
->m_pkthdr
.csum_flags
& CSUM_DELAY_IP
)) {
276 sum
= ~ntohs(ip
->ip_sum
) & 0xffff;
277 sum
+= (~otos
& 0xffff) + ip
->ip_tos
;
278 sum
= (sum
>> 16) + (sum
& 0xffff);
279 sum
+= (sum
>> 16); /* add carry */
280 ip
->ip_sum
= htons(~sum
& 0xffff);
286 if (flags
& CLASSQF_ECN6
) { /* REDF_ECN6 == BLUEF_ECN6 */
287 struct ip6_hdr
*ip6
= hdr
;
290 if (((uintptr_t)ip6
+ sizeof(*ip6
)) >
291 ((uintptr_t)mbuf_datastart(m0
) + mbuf_maxlen(m0
))) {
292 return 0; /* out of bounds */
294 flowlabel
= ntohl(ip6
->ip6_flow
);
295 if ((flowlabel
>> 28) != 6) {
296 return 0; /* version mismatch! */
298 if ((flowlabel
& (IPTOS_ECN_MASK
<< 20)) ==
299 (IPTOS_ECN_NOTECT
<< 20)) {
300 return 0; /* not-ECT */
302 if ((flowlabel
& (IPTOS_ECN_MASK
<< 20)) ==
303 (IPTOS_ECN_CE
<< 20)) {
304 return 1; /* already marked */
307 * ecn-capable but not marked, mark CE
309 flowlabel
|= (IPTOS_ECN_CE
<< 20);
310 ip6
->ip6_flow
= htonl(flowlabel
);