]>
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
)))
99 /* verify that hdr is within the mbuf data */
100 for (m0
= m
; m0
!= NULL
; m0
= m0
->m_next
)
101 if (((caddr_t
)t
->pftag_hdr
>= m0
->m_data
) &&
102 ((caddr_t
)t
->pftag_hdr
< m0
->m_data
+ m0
->m_len
))
105 /* ick, tag info is stale */
106 printf("%s: can't locate header!\n", __func__
);
107 return ((u_int8_t
)0);
110 if (t
->pftag_flags
& PF_TAG_HDR_INET
) {
111 struct ip
*ip
= (struct ip
*)(void *)t
->pftag_hdr
;
113 if (((uintptr_t)ip
+ sizeof (*ip
)) >
114 ((uintptr_t)mbuf_datastart(m0
) + mbuf_maxlen(m0
)))
115 return (0); /* out of bounds */
118 return ((u_int8_t
)0); /* version mismatch! */
119 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! */
133 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
)))
148 /* verify that hdr is within the mbuf data */
149 for (m0
= m
; m0
!= NULL
; m0
= m0
->m_next
)
150 if (((caddr_t
)t
->pftag_hdr
>= m0
->m_data
) &&
151 ((caddr_t
)t
->pftag_hdr
< m0
->m_data
+ m0
->m_len
))
154 /* ick, tag info is stale */
155 printf("%s: can't locate header!\n", __func__
);
159 if (t
->pftag_flags
& PF_TAG_HDR_INET
) {
160 struct ip
*ip
= (struct ip
*)(void *)t
->pftag_hdr
;
164 if (((uintptr_t)ip
+ sizeof (*ip
)) >
165 ((uintptr_t)mbuf_datastart(m0
) + mbuf_maxlen(m0
)))
166 return; /* out of bounds */
169 return; /* version mismatch! */
171 dsfield
|= old
& 3; /* leave CU bits */
174 ip
->ip_tos
= dsfield
;
176 * update checksum (from RFC1624)
177 * HC' = ~(~HC + ~m + m')
179 sum
= ~ntohs(ip
->ip_sum
) & 0xffff;
180 sum
+= 0xff00 + (~old
& 0xff) + dsfield
;
181 sum
= (sum
>> 16) + (sum
& 0xffff);
182 sum
+= (sum
>> 16); /* add carry */
184 ip
->ip_sum
= htons(~sum
& 0xffff);
187 else if (t
->pftag_flags
& PF_TAG_HDR_INET6
) {
188 struct ip6_hdr
*ip6
= (struct ip6_hdr
*)t
->pftag_hdr
;
191 if (((uintptr_t)ip6
+ sizeof (*ip6
)) >
192 ((uintptr_t)mbuf_datastart(m0
) + mbuf_maxlen(m0
)))
193 return; /* out of bounds */
195 flowlabel
= ntohl(ip6
->ip6_flow
);
196 if ((flowlabel
>> 28) != 6)
197 return; /* version mismatch! */
198 flowlabel
= (flowlabel
& 0xf03fffff) | (dsfield
<< 20);
199 ip6
->ip6_flow
= htonl(flowlabel
);
205 * try to mark CE bit to the packet.
206 * returns 1 if successfully marked, 0 otherwise.
209 mark_ecn(struct mbuf
*m
, struct pf_mtag
*t
, int flags
)
215 if ((hdr
= t
->pftag_hdr
) == NULL
||
216 !(t
->pftag_flags
& (PF_TAG_HDR_INET
|PF_TAG_HDR_INET6
)))
219 /* verify that hdr is within the mbuf data */
220 for (m0
= m
; m0
!= NULL
; m0
= m0
->m_next
)
221 if (((caddr_t
)hdr
>= m0
->m_data
) &&
222 ((caddr_t
)hdr
< m0
->m_data
+ m0
->m_len
))
225 /* ick, tag info is stale */
226 printf("%s: can't locate header!\n", __func__
);
230 if (t
->pftag_flags
& PF_TAG_HDR_INET
)
232 else if (t
->pftag_flags
& PF_TAG_HDR_INET6
)
239 if (flags
& CLASSQF_ECN4
) { /* REDF_ECN4 == BLUEF_ECN4 */
244 if (((uintptr_t)ip
+ sizeof (*ip
)) >
245 ((uintptr_t)mbuf_datastart(m0
) + mbuf_maxlen(m0
)))
246 return (0); /* out of bounds */
249 return (0); /* version mismatch! */
250 if ((ip
->ip_tos
& IPTOS_ECN_MASK
) == IPTOS_ECN_NOTECT
)
251 return (0); /* not-ECT */
252 if ((ip
->ip_tos
& IPTOS_ECN_MASK
) == IPTOS_ECN_CE
)
253 return (1); /* already marked */
256 * ecn-capable but not marked,
257 * mark CE and update checksum
260 ip
->ip_tos
|= IPTOS_ECN_CE
;
262 * update checksum (from RFC1624) only if hw
263 * checksum is not supported.
264 * HC' = ~(~HC + ~m + m')
266 if (!(m
->m_pkthdr
.csum_flags
& CSUM_DELAY_IP
)) {
267 sum
= ~ntohs(ip
->ip_sum
) & 0xffff;
268 sum
+= (~otos
& 0xffff) + ip
->ip_tos
;
269 sum
= (sum
>> 16) + (sum
& 0xffff);
270 sum
+= (sum
>> 16); /* add carry */
271 ip
->ip_sum
= htons(~sum
& 0xffff);
278 if (flags
& CLASSQF_ECN6
) { /* REDF_ECN6 == BLUEF_ECN6 */
279 struct ip6_hdr
*ip6
= hdr
;
282 if (((uintptr_t)ip6
+ sizeof (*ip6
)) >
283 ((uintptr_t)mbuf_datastart(m0
) + mbuf_maxlen(m0
)))
284 return (0); /* out of bounds */
286 flowlabel
= ntohl(ip6
->ip6_flow
);
287 if ((flowlabel
>> 28) != 6)
288 return (0); /* version mismatch! */
289 if ((flowlabel
& (IPTOS_ECN_MASK
<< 20)) ==
290 (IPTOS_ECN_NOTECT
<< 20))
291 return (0); /* not-ECT */
292 if ((flowlabel
& (IPTOS_ECN_MASK
<< 20)) ==
293 (IPTOS_ECN_CE
<< 20))
294 return (1); /* already marked */
296 * ecn-capable but not marked, mark CE
298 flowlabel
|= (IPTOS_ECN_CE
<< 20);
299 ip6
->ip6_flow
= htonl(flowlabel
);