]>
git.saurik.com Git - apple/xnu.git/blob - bsd/net/classq/classq_util.c
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>
78 #include <netinet/ip6.h>
80 #include <netinet/tcp.h>
81 #include <netinet/udp.h>
83 #include <libkern/libkern.h>
87 * read and write diffserv field in IPv4 or IPv6 header
90 read_dsfield(struct mbuf
*m
, struct pf_mtag
*t
)
93 u_int8_t ds_field
= 0;
95 if (t
->pftag_hdr
== NULL
||
96 !(t
->pftag_flags
& (PF_TAG_HDR_INET
| PF_TAG_HDR_INET6
))) {
100 /* verify that hdr is within the mbuf data */
101 for (m0
= m
; m0
!= NULL
; m0
= m0
->m_next
) {
102 if (((caddr_t
)t
->pftag_hdr
>= m0
->m_data
) &&
103 ((caddr_t
)t
->pftag_hdr
< m0
->m_data
+ m0
->m_len
)) {
108 /* ick, tag info is stale */
109 printf("%s: can't locate header!\n", __func__
);
113 if (t
->pftag_flags
& PF_TAG_HDR_INET
) {
114 struct ip
*ip
= (struct ip
*)(void *)t
->pftag_hdr
;
116 if (((uintptr_t)ip
+ sizeof(*ip
)) >
117 ((uintptr_t)mbuf_datastart(m0
) + mbuf_maxlen(m0
))) {
118 return 0; /* out of bounds */
121 return (u_int8_t
)0; /* version mismatch! */
123 ds_field
= ip
->ip_tos
;
126 else if (t
->pftag_flags
& PF_TAG_HDR_INET6
) {
127 struct ip6_hdr
*ip6
= (struct ip6_hdr
*)(void *)t
->pftag_hdr
;
130 if (((uintptr_t)ip6
+ sizeof(*ip6
)) >
131 ((uintptr_t)mbuf_datastart(m0
) + mbuf_maxlen(m0
))) {
132 return 0; /* out of bounds */
134 flowlabel
= ntohl(ip6
->ip6_flow
);
135 if ((flowlabel
>> 28) != 6) {
136 return (u_int8_t
)0; /* version mismatch! */
138 ds_field
= (flowlabel
>> 20) & 0xff;
145 write_dsfield(struct mbuf
*m
, struct pf_mtag
*t
, u_int8_t dsfield
)
149 if (t
->pftag_hdr
== NULL
||
150 !(t
->pftag_flags
& (PF_TAG_HDR_INET
| PF_TAG_HDR_INET6
))) {
154 /* verify that hdr is within the mbuf data */
155 for (m0
= m
; m0
!= NULL
; m0
= m0
->m_next
) {
156 if (((caddr_t
)t
->pftag_hdr
>= m0
->m_data
) &&
157 ((caddr_t
)t
->pftag_hdr
< m0
->m_data
+ m0
->m_len
)) {
162 /* ick, tag info is stale */
163 printf("%s: can't locate header!\n", __func__
);
167 if (t
->pftag_flags
& PF_TAG_HDR_INET
) {
168 struct ip
*ip
= (struct ip
*)(void *)t
->pftag_hdr
;
172 if (((uintptr_t)ip
+ sizeof(*ip
)) >
173 ((uintptr_t)mbuf_datastart(m0
) + mbuf_maxlen(m0
))) {
174 return; /* out of bounds */
177 return; /* version mismatch! */
180 dsfield
|= old
& 3; /* leave CU bits */
181 if (old
== dsfield
) {
184 ip
->ip_tos
= dsfield
;
186 * update checksum (from RFC1624)
187 * HC' = ~(~HC + ~m + m')
189 sum
= ~ntohs(ip
->ip_sum
) & 0xffff;
190 sum
+= 0xff00 + (~old
& 0xff) + dsfield
;
191 sum
= (sum
>> 16) + (sum
& 0xffff);
192 sum
+= (sum
>> 16); /* add carry */
194 ip
->ip_sum
= htons(~sum
& 0xffff);
197 else if (t
->pftag_flags
& PF_TAG_HDR_INET6
) {
198 struct ip6_hdr
*ip6
= (struct ip6_hdr
*)t
->pftag_hdr
;
201 if (((uintptr_t)ip6
+ sizeof(*ip6
)) >
202 ((uintptr_t)mbuf_datastart(m0
) + mbuf_maxlen(m0
))) {
203 return; /* out of bounds */
205 flowlabel
= ntohl(ip6
->ip6_flow
);
206 if ((flowlabel
>> 28) != 6) {
207 return; /* version mismatch! */
209 flowlabel
= (flowlabel
& 0xf03fffff) | (dsfield
<< 20);
210 ip6
->ip6_flow
= htonl(flowlabel
);
216 * try to mark CE bit to the packet.
217 * returns 1 if successfully marked, 0 otherwise.
220 mark_ecn(struct mbuf
*m
, struct pf_mtag
*t
, int flags
)
226 if ((hdr
= t
->pftag_hdr
) == NULL
||
227 !(t
->pftag_flags
& (PF_TAG_HDR_INET
| PF_TAG_HDR_INET6
))) {
231 /* verify that hdr is within the mbuf data */
232 for (m0
= m
; m0
!= NULL
; m0
= m0
->m_next
) {
233 if (((caddr_t
)hdr
>= m0
->m_data
) &&
234 ((caddr_t
)hdr
< m0
->m_data
+ m0
->m_len
)) {
239 /* ick, tag info is stale */
240 printf("%s: can't locate header!\n", __func__
);
244 if (t
->pftag_flags
& PF_TAG_HDR_INET
) {
246 } else if (t
->pftag_flags
& PF_TAG_HDR_INET6
) {
254 if (flags
& CLASSQF_ECN4
) { /* REDF_ECN4 == BLUEF_ECN4 */
259 if (((uintptr_t)ip
+ sizeof(*ip
)) >
260 ((uintptr_t)mbuf_datastart(m0
) + mbuf_maxlen(m0
))) {
261 return 0; /* out of bounds */
264 return 0; /* version mismatch! */
266 if ((ip
->ip_tos
& IPTOS_ECN_MASK
) == IPTOS_ECN_NOTECT
) {
267 return 0; /* not-ECT */
269 if ((ip
->ip_tos
& IPTOS_ECN_MASK
) == IPTOS_ECN_CE
) {
270 return 1; /* already marked */
273 * ecn-capable but not marked,
274 * mark CE and update checksum
277 ip
->ip_tos
|= IPTOS_ECN_CE
;
279 * update checksum (from RFC1624) only if hw
280 * checksum is not supported.
281 * HC' = ~(~HC + ~m + m')
283 if (!(m
->m_pkthdr
.csum_flags
& CSUM_DELAY_IP
)) {
284 sum
= ~ntohs(ip
->ip_sum
) & 0xffff;
285 sum
+= (~otos
& 0xffff) + ip
->ip_tos
;
286 sum
= (sum
>> 16) + (sum
& 0xffff);
287 sum
+= (sum
>> 16); /* add carry */
288 ip
->ip_sum
= htons(~sum
& 0xffff);
295 if (flags
& CLASSQF_ECN6
) { /* REDF_ECN6 == BLUEF_ECN6 */
296 struct ip6_hdr
*ip6
= hdr
;
299 if (((uintptr_t)ip6
+ sizeof(*ip6
)) >
300 ((uintptr_t)mbuf_datastart(m0
) + mbuf_maxlen(m0
))) {
301 return 0; /* out of bounds */
303 flowlabel
= ntohl(ip6
->ip6_flow
);
304 if ((flowlabel
>> 28) != 6) {
305 return 0; /* version mismatch! */
307 if ((flowlabel
& (IPTOS_ECN_MASK
<< 20)) ==
308 (IPTOS_ECN_NOTECT
<< 20)) {
309 return 0; /* not-ECT */
311 if ((flowlabel
& (IPTOS_ECN_MASK
<< 20)) ==
312 (IPTOS_ECN_CE
<< 20)) {
313 return 1; /* already marked */
316 * ecn-capable but not marked, mark CE
318 flowlabel
|= (IPTOS_ECN_CE
<< 20);
319 ip6
->ip6_flow
= htonl(flowlabel
);