]>
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>
86 * read and write diffserv field in IPv4 or IPv6 header
89 read_dsfield(struct mbuf
*m
, struct pf_mtag
*t
)
92 u_int8_t ds_field
= 0;
94 if (t
->pftag_hdr
== NULL
||
95 !(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
))
104 /* ick, tag info is stale */
105 printf("%s: can't locate header!\n", __func__
);
106 return ((u_int8_t
)0);
109 if (t
->pftag_flags
& PF_TAG_HDR_INET
) {
110 struct ip
*ip
= (struct ip
*)(void *)t
->pftag_hdr
;
112 if (((uintptr_t)ip
+ sizeof (*ip
)) >
113 ((uintptr_t)mbuf_datastart(m0
) + mbuf_maxlen(m0
)))
114 return (0); /* out of bounds */
117 return ((u_int8_t
)0); /* version mismatch! */
118 ds_field
= ip
->ip_tos
;
121 else if (t
->pftag_flags
& PF_TAG_HDR_INET6
) {
122 struct ip6_hdr
*ip6
= (struct ip6_hdr
*)(void *)t
->pftag_hdr
;
125 if (((uintptr_t)ip6
+ sizeof (*ip6
)) >
126 ((uintptr_t)mbuf_datastart(m0
) + mbuf_maxlen(m0
)))
127 return (0); /* out of bounds */
129 flowlabel
= ntohl(ip6
->ip6_flow
);
130 if ((flowlabel
>> 28) != 6)
131 return ((u_int8_t
)0); /* version mismatch! */
132 ds_field
= (flowlabel
>> 20) & 0xff;
139 write_dsfield(struct mbuf
*m
, struct pf_mtag
*t
, u_int8_t dsfield
)
143 if (t
->pftag_hdr
== NULL
||
144 !(t
->pftag_flags
& (PF_TAG_HDR_INET
|PF_TAG_HDR_INET6
)))
147 /* verify that hdr is within the mbuf data */
148 for (m0
= m
; m0
!= NULL
; m0
= m0
->m_next
)
149 if (((caddr_t
)t
->pftag_hdr
>= m0
->m_data
) &&
150 ((caddr_t
)t
->pftag_hdr
< m0
->m_data
+ m0
->m_len
))
153 /* ick, tag info is stale */
154 printf("%s: can't locate header!\n", __func__
);
158 if (t
->pftag_flags
& PF_TAG_HDR_INET
) {
159 struct ip
*ip
= (struct ip
*)(void *)t
->pftag_hdr
;
163 if (((uintptr_t)ip
+ sizeof (*ip
)) >
164 ((uintptr_t)mbuf_datastart(m0
) + mbuf_maxlen(m0
)))
165 return; /* out of bounds */
168 return; /* version mismatch! */
170 dsfield
|= old
& 3; /* leave CU bits */
173 ip
->ip_tos
= dsfield
;
175 * update checksum (from RFC1624)
176 * HC' = ~(~HC + ~m + m')
178 sum
= ~ntohs(ip
->ip_sum
) & 0xffff;
179 sum
+= 0xff00 + (~old
& 0xff) + dsfield
;
180 sum
= (sum
>> 16) + (sum
& 0xffff);
181 sum
+= (sum
>> 16); /* add carry */
183 ip
->ip_sum
= htons(~sum
& 0xffff);
186 else if (t
->pftag_flags
& PF_TAG_HDR_INET6
) {
187 struct ip6_hdr
*ip6
= (struct ip6_hdr
*)t
->pftag_hdr
;
190 if (((uintptr_t)ip6
+ sizeof (*ip6
)) >
191 ((uintptr_t)mbuf_datastart(m0
) + mbuf_maxlen(m0
)))
192 return; /* out of bounds */
194 flowlabel
= ntohl(ip6
->ip6_flow
);
195 if ((flowlabel
>> 28) != 6)
196 return; /* version mismatch! */
197 flowlabel
= (flowlabel
& 0xf03fffff) | (dsfield
<< 20);
198 ip6
->ip6_flow
= htonl(flowlabel
);
204 * try to mark CE bit to the packet.
205 * returns 1 if successfully marked, 0 otherwise.
208 mark_ecn(struct mbuf
*m
, struct pf_mtag
*t
, int flags
)
214 if ((hdr
= t
->pftag_hdr
) == NULL
||
215 !(t
->pftag_flags
& (PF_TAG_HDR_INET
|PF_TAG_HDR_INET6
)))
218 /* verify that hdr is within the mbuf data */
219 for (m0
= m
; m0
!= NULL
; m0
= m0
->m_next
)
220 if (((caddr_t
)hdr
>= m0
->m_data
) &&
221 ((caddr_t
)hdr
< m0
->m_data
+ m0
->m_len
))
224 /* ick, tag info is stale */
225 printf("%s: can't locate header!\n", __func__
);
229 if (t
->pftag_flags
& PF_TAG_HDR_INET
)
231 else if (t
->pftag_flags
& PF_TAG_HDR_INET6
)
238 if (flags
& CLASSQF_ECN4
) { /* REDF_ECN4 == BLUEF_ECN4 */
243 if (((uintptr_t)ip
+ sizeof (*ip
)) >
244 ((uintptr_t)mbuf_datastart(m0
) + mbuf_maxlen(m0
)))
245 return (0); /* out of bounds */
248 return (0); /* version mismatch! */
249 if ((ip
->ip_tos
& IPTOS_ECN_MASK
) == IPTOS_ECN_NOTECT
)
250 return (0); /* not-ECT */
251 if ((ip
->ip_tos
& IPTOS_ECN_MASK
) == IPTOS_ECN_CE
)
252 return (1); /* already marked */
255 * ecn-capable but not marked,
256 * mark CE and update checksum
259 ip
->ip_tos
|= IPTOS_ECN_CE
;
261 * update checksum (from RFC1624)
262 * HC' = ~(~HC + ~m + m')
264 sum
= ~ntohs(ip
->ip_sum
) & 0xffff;
265 sum
+= (~otos
& 0xffff) + ip
->ip_tos
;
266 sum
= (sum
>> 16) + (sum
& 0xffff);
267 sum
+= (sum
>> 16); /* add carry */
268 ip
->ip_sum
= htons(~sum
& 0xffff);
274 if (flags
& CLASSQF_ECN6
) { /* REDF_ECN6 == BLUEF_ECN6 */
275 struct ip6_hdr
*ip6
= hdr
;
278 if (((uintptr_t)ip6
+ sizeof (*ip6
)) >
279 ((uintptr_t)mbuf_datastart(m0
) + mbuf_maxlen(m0
)))
280 return (0); /* out of bounds */
282 flowlabel
= ntohl(ip6
->ip6_flow
);
283 if ((flowlabel
>> 28) != 6)
284 return (0); /* version mismatch! */
285 if ((flowlabel
& (IPTOS_ECN_MASK
<< 20)) ==
286 (IPTOS_ECN_NOTECT
<< 20))
287 return (0); /* not-ECT */
288 if ((flowlabel
& (IPTOS_ECN_MASK
<< 20)) ==
289 (IPTOS_ECN_CE
<< 20))
290 return (1); /* already marked */
292 * ecn-capable but not marked, mark CE
294 flowlabel
|= (IPTOS_ECN_CE
<< 20);
295 ip6
->ip6_flow
= htonl(flowlabel
);