ip_ecn.c revision 62587
162587Sitojun/*	$FreeBSD: head/sys/netinet/ip_ecn.c 62587 2000-07-04 16:35:15Z itojun $	*/
262587Sitojun/*	$KAME: ip_ecn.c,v 1.7 2000/05/05 11:00:56 sumikawa Exp $	*/
362587Sitojun
455009Sshin/*
555009Sshin * Copyright (C) 1999 WIDE Project.
655009Sshin * All rights reserved.
755009Sshin *
855009Sshin * Redistribution and use in source and binary forms, with or without
955009Sshin * modification, are permitted provided that the following conditions
1055009Sshin * are met:
1155009Sshin * 1. Redistributions of source code must retain the above copyright
1255009Sshin *    notice, this list of conditions and the following disclaimer.
1355009Sshin * 2. Redistributions in binary form must reproduce the above copyright
1455009Sshin *    notice, this list of conditions and the following disclaimer in the
1555009Sshin *    documentation and/or other materials provided with the distribution.
1655009Sshin * 3. Neither the name of the project nor the names of its contributors
1755009Sshin *    may be used to endorse or promote products derived from this software
1855009Sshin *    without specific prior written permission.
1955009Sshin *
2055009Sshin * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
2155009Sshin * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2255009Sshin * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2355009Sshin * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
2455009Sshin * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2555009Sshin * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2655009Sshin * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2755009Sshin * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2855009Sshin * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2955009Sshin * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3055009Sshin * SUCH DAMAGE.
3155009Sshin *
3255009Sshin */
3355009Sshin/*
3455009Sshin * ECN consideration on tunnel ingress/egress operation.
3555009Sshin * http://www.aciri.org/floyd/papers/draft-ipsec-ecn-00.txt
3655009Sshin */
3755009Sshin
3855009Sshin#include "opt_inet.h"
3955009Sshin#include "opt_inet6.h"
4055009Sshin
4155009Sshin#include <sys/param.h>
4255009Sshin#include <sys/systm.h>
4355009Sshin#include <sys/mbuf.h>
4455009Sshin#include <sys/errno.h>
4555009Sshin
4655009Sshin#ifdef INET
4755009Sshin#include <netinet/in.h>
4855009Sshin#include <netinet/in_systm.h>
4955009Sshin#include <netinet/ip.h>
5055009Sshin#endif
5155009Sshin
5255009Sshin#ifdef INET6
5355009Sshin#ifndef INET
5455009Sshin#include <netinet/in.h>
5555009Sshin#endif
5655009Sshin#include <netinet/ip6.h>
5755009Sshin#endif
5855009Sshin
5955009Sshin#include <netinet/ip_ecn.h>
6055009Sshin#ifdef INET6
6155009Sshin#include <netinet6/ip6_ecn.h>
6255009Sshin#endif
6355009Sshin
6455009Sshin/*
6555009Sshin * modify outer ECN (TOS) field on ingress operation (tunnel encapsulation).
6655009Sshin * call it after you've done the default initialization/copy for the outer.
6755009Sshin */
6855009Sshinvoid
6955009Sshinip_ecn_ingress(mode, outer, inner)
7055009Sshin	int mode;
7155009Sshin	u_int8_t *outer;
7255009Sshin	u_int8_t *inner;
7355009Sshin{
7455009Sshin	if (!outer || !inner)
7555009Sshin		panic("NULL pointer passed to ip_ecn_ingress");
7655009Sshin
7755009Sshin	switch (mode) {
7855009Sshin	case ECN_ALLOWED:		/* ECN allowed */
7955009Sshin		*outer &= ~IPTOS_CE;
8055009Sshin		break;
8155009Sshin	case ECN_FORBIDDEN:		/* ECN forbidden */
8255009Sshin		*outer &= ~(IPTOS_ECT | IPTOS_CE);
8355009Sshin		break;
8455009Sshin	case ECN_NOCARE:	/* no consideration to ECN */
8555009Sshin		break;
8655009Sshin	}
8755009Sshin}
8855009Sshin
8955009Sshin/*
9055009Sshin * modify inner ECN (TOS) field on egress operation (tunnel decapsulation).
9155009Sshin * call it after you've done the default initialization/copy for the inner.
9255009Sshin */
9355009Sshinvoid
9455009Sshinip_ecn_egress(mode, outer, inner)
9555009Sshin	int mode;
9655009Sshin	u_int8_t *outer;
9755009Sshin	u_int8_t *inner;
9855009Sshin{
9955009Sshin	if (!outer || !inner)
10055009Sshin		panic("NULL pointer passed to ip_ecn_egress");
10155009Sshin
10255009Sshin	switch (mode) {
10355009Sshin	case ECN_ALLOWED:
10455009Sshin		if (*outer & IPTOS_CE)
10555009Sshin			*inner |= IPTOS_CE;
10655009Sshin		break;
10755009Sshin	case ECN_FORBIDDEN:		/* ECN forbidden */
10855009Sshin	case ECN_NOCARE:	/* no consideration to ECN */
10955009Sshin		break;
11055009Sshin	}
11155009Sshin}
11255009Sshin
11355009Sshin#ifdef INET6
11455009Sshinvoid
11555009Sshinip6_ecn_ingress(mode, outer, inner)
11655009Sshin	int mode;
11755009Sshin	u_int32_t *outer;
11855009Sshin	u_int32_t *inner;
11955009Sshin{
12055009Sshin	u_int8_t outer8, inner8;
12155009Sshin
12255009Sshin	if (!outer || !inner)
12355009Sshin		panic("NULL pointer passed to ip6_ecn_ingress");
12455009Sshin
12555009Sshin	outer8 = (ntohl(*outer) >> 20) & 0xff;
12655009Sshin	inner8 = (ntohl(*inner) >> 20) & 0xff;
12755009Sshin	ip_ecn_ingress(mode, &outer8, &inner8);
12855009Sshin	*outer &= ~htonl(0xff << 20);
12955009Sshin	*outer |= htonl((u_int32_t)outer8 << 20);
13055009Sshin}
13155009Sshin
13255009Sshinvoid
13355009Sshinip6_ecn_egress(mode, outer, inner)
13455009Sshin	int mode;
13555009Sshin	u_int32_t *outer;
13655009Sshin	u_int32_t *inner;
13755009Sshin{
13855009Sshin	u_int8_t outer8, inner8;
13955009Sshin
14055009Sshin	if (!outer || !inner)
14155009Sshin		panic("NULL pointer passed to ip6_ecn_egress");
14255009Sshin
14355009Sshin	outer8 = (ntohl(*outer) >> 20) & 0xff;
14455009Sshin	inner8 = (ntohl(*inner) >> 20) & 0xff;
14555009Sshin	ip_ecn_egress(mode, &outer8, &inner8);
14655009Sshin	*inner &= ~htonl(0xff << 20);
14755009Sshin	*inner |= htonl((u_int32_t)inner8 << 20);
14855009Sshin}
14955009Sshin#endif
150