X-Git-Url: https://git.saurik.com/apple/xnu.git/blobdiff_plain/9bccf70c0258c7cac2dcb80011b2a964d884c552..a991bd8d3e7fe02dbca0644054bab73c5b75324a:/bsd/netinet/ip_ecn.c diff --git a/bsd/netinet/ip_ecn.c b/bsd/netinet/ip_ecn.c index 2dfc497e8..5cbc50b50 100644 --- a/bsd/netinet/ip_ecn.c +++ b/bsd/netinet/ip_ecn.c @@ -1,23 +1,29 @@ /* - * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2000-2016 Apple Inc. All rights reserved. * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. The rights granted to you under the License + * may not be used to create, or enable the creation or redistribution of, + * unlawful or unlicensed copies of an Apple operating system, or to + * circumvent, violate, or enable the circumvention or violation of, any + * terms of an Apple operating system software license agreement. + * + * Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ */ /* * Copyright (C) 1999 WIDE Project. @@ -62,36 +68,29 @@ #include #include #include -#if INET6 #include -#endif #include -#if INET6 #include -#endif /* * modify outer ECN (TOS) field on ingress operation (tunnel encapsulation). */ void -ip_ecn_ingress(mode, outer, inner) - int mode; - u_int8_t *outer; - const u_int8_t *inner; +ip_ecn_ingress(int mode, u_int8_t *outer, const u_int8_t *inner) { - if (!outer || !inner) + if (!outer || !inner) { panic("NULL pointer passed to ip_ecn_ingress"); + } *outer = *inner; switch (mode) { - case ECN_ALLOWED: /* ECN allowed */ - *outer &= ~IPTOS_CE; + case ECN_NORMAL: /* ECN normal mode, copy flags */ break; - case ECN_FORBIDDEN: /* ECN forbidden */ - *outer &= ~(IPTOS_ECT | IPTOS_CE); + case ECN_COMPATIBILITY: /* ECN compatibility mode */ + *outer &= ~IPTOS_ECN_MASK; break; - case ECN_NOCARE: /* no consideration to ECN */ + case ECN_NOCARE: /* no consideration to ECN */ break; } } @@ -99,37 +98,39 @@ ip_ecn_ingress(mode, outer, inner) /* * modify inner ECN (TOS) field on egress operation (tunnel decapsulation). */ -void -ip_ecn_egress(mode, outer, inner) - int mode; - const u_int8_t *outer; - u_int8_t *inner; +int +ip_ecn_egress(int mode, const u_int8_t *outer, u_int8_t *inner) { - if (!outer || !inner) + if (!outer || !inner) { panic("NULL pointer passed to ip_ecn_egress"); + } switch (mode) { - case ECN_ALLOWED: - if (*outer & IPTOS_CE) - *inner |= IPTOS_CE; + /* Process ECN for both normal and compatibility modes */ + case ECN_NORMAL: + case ECN_COMPATIBILITY: + if (((*outer & IPTOS_ECN_MASK) == IPTOS_ECN_CE) && + ((*inner & IPTOS_ECN_MASK) != IPTOS_ECN_NOTECT)) { + *inner |= IPTOS_ECN_CE; + } else if ((*outer & IPTOS_ECN_MASK) == IPTOS_ECN_ECT1 && + (*inner & IPTOS_ECN_MASK) == IPTOS_ECN_ECT0) { + *inner = *outer; + } break; - case ECN_FORBIDDEN: /* ECN forbidden */ - case ECN_NOCARE: /* no consideration to ECN */ + case ECN_NOCARE: /* no consideration to ECN */ break; } + return 1; } -#if INET6 void -ip6_ecn_ingress(mode, outer, inner) - int mode; - u_int32_t *outer; - const u_int32_t *inner; +ip6_ecn_ingress(int mode, u_int32_t *outer, const u_int32_t *inner) { u_int8_t outer8, inner8; - if (!outer || !inner) + if (!outer || !inner) { panic("NULL pointer passed to ip6_ecn_ingress"); + } inner8 = (ntohl(*inner) >> 20) & 0xff; ip_ecn_ingress(mode, &outer8, &inner8); @@ -137,20 +138,96 @@ ip6_ecn_ingress(mode, outer, inner) *outer |= htonl((u_int32_t)outer8 << 20); } -void -ip6_ecn_egress(mode, outer, inner) - int mode; - const u_int32_t *outer; - u_int32_t *inner; +int +ip6_ecn_egress(int mode, const u_int32_t *outer, u_int32_t *inner) { u_int8_t outer8, inner8; - if (!outer || !inner) + if (!outer || !inner) { panic("NULL pointer passed to ip6_ecn_egress"); + } outer8 = (ntohl(*outer) >> 20) & 0xff; - ip_ecn_egress(mode, &outer8, &inner8); + inner8 = (ntohl(*inner) >> 20) & 0xff; + if (ip_ecn_egress(mode, &outer8, &inner8) == 0) { + return 0; + } + *inner &= ~htonl(0xff << 20); + *inner |= htonl((u_int32_t)inner8 << 20); + return 1; +} + +/* + * Modify outer IPv6 ECN (Traffic Class) field according to inner IPv4 TOS field + * on ingress operation (tunnel encapsulation). + */ +void +ip46_ecn_ingress(int mode, u_int32_t *outer, const u_int8_t *tos) +{ + u_int8_t outer8; + + if (!outer || !tos) { + panic("NULL pointer passed to ip46_ecn_ingress"); + } + + ip_ecn_ingress(mode, &outer8, tos); + *outer &= ~htonl(0xff << 20); + *outer |= htonl((u_int32_t)outer8 << 20); +} + +/* + * Modify inner IPv4 ECN (TOS) field according to output IPv6 ECN (Traffic Class) + * on egress operation (tunnel decapsulation). + */ +int +ip46_ecn_egress(int mode, const u_int32_t *outer, u_int8_t *tos) +{ + u_int8_t outer8; + + if (!outer || !tos) { + panic("NULL pointer passed to ip46_ecn_egress"); + } + + outer8 = (ntohl(*outer) >> 20) & 0xff; + return ip_ecn_egress(mode, &outer8, tos); +} + +/* + * Modify outer IPv4 TOS field according to inner IPv6 ECN (Traffic Class) + * on ingress operation (tunnel encapsulation). + */ +void +ip64_ecn_ingress(int mode, u_int8_t *outer, const u_int32_t *inner) +{ + u_int8_t inner8; + + if (!outer || !inner) { + panic("NULL pointer passed to ip64_ecn_ingress"); + } + + inner8 = (ntohl(*inner) >> 20) & 0xff; + ip_ecn_ingress(mode, outer, &inner8); +} + +/* + * Modify inner IPv6 ECN (Traffic Class) according to outer IPv4 TOS field + * on egress operation (tunnel decapsulation). + */ +int +ip64_ecn_egress(int mode, const u_int8_t *outer, u_int32_t *inner) +{ + u_int8_t inner8; + + if (!outer || !inner) { + panic("NULL pointer passed to ip64_ecn_egress"); + } + + inner8 = (ntohl(*inner) >> 20) & 0xff; + if (ip_ecn_egress(mode, outer, &inner8) == 0) { + return 0; + } + *inner &= ~htonl(0xff << 20); *inner |= htonl((u_int32_t)inner8 << 20); + return 1; } -#endif