Home | History | Annotate | Line # | Download | only in netipsec
xform_ipip.c revision 1.8
      1  1.8       scw /*	$NetBSD: xform_ipip.c,v 1.8 2004/01/16 11:06:27 scw Exp $	*/
      2  1.1  jonathan /*	$FreeBSD: src/sys/netipsec/xform_ipip.c,v 1.3.2.1 2003/01/24 05:11:36 sam Exp $	*/
      3  1.1  jonathan /*	$OpenBSD: ip_ipip.c,v 1.25 2002/06/10 18:04:55 itojun Exp $ */
      4  1.1  jonathan 
      5  1.1  jonathan /*
      6  1.1  jonathan  * The authors of this code are John Ioannidis (ji (at) tla.org),
      7  1.1  jonathan  * Angelos D. Keromytis (kermit (at) csd.uch.gr) and
      8  1.1  jonathan  * Niels Provos (provos (at) physnet.uni-hamburg.de).
      9  1.1  jonathan  *
     10  1.1  jonathan  * The original version of this code was written by John Ioannidis
     11  1.1  jonathan  * for BSD/OS in Athens, Greece, in November 1995.
     12  1.1  jonathan  *
     13  1.1  jonathan  * Ported to OpenBSD and NetBSD, with additional transforms, in December 1996,
     14  1.1  jonathan  * by Angelos D. Keromytis.
     15  1.1  jonathan  *
     16  1.1  jonathan  * Additional transforms and features in 1997 and 1998 by Angelos D. Keromytis
     17  1.1  jonathan  * and Niels Provos.
     18  1.1  jonathan  *
     19  1.1  jonathan  * Additional features in 1999 by Angelos D. Keromytis.
     20  1.1  jonathan  *
     21  1.1  jonathan  * Copyright (C) 1995, 1996, 1997, 1998, 1999 by John Ioannidis,
     22  1.1  jonathan  * Angelos D. Keromytis and Niels Provos.
     23  1.1  jonathan  * Copyright (c) 2001, Angelos D. Keromytis.
     24  1.1  jonathan  *
     25  1.1  jonathan  * Permission to use, copy, and modify this software with or without fee
     26  1.1  jonathan  * is hereby granted, provided that this entire notice is included in
     27  1.1  jonathan  * all copies of any software which is or includes a copy or
     28  1.1  jonathan  * modification of this software.
     29  1.1  jonathan  * You may use this code under the GNU public license if you so wish. Please
     30  1.1  jonathan  * contribute changes back to the authors under this freer than GPL license
     31  1.1  jonathan  * so that we may further the use of strong encryption without limitations to
     32  1.1  jonathan  * all.
     33  1.1  jonathan  *
     34  1.1  jonathan  * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR
     35  1.1  jonathan  * IMPLIED WARRANTY. IN PARTICULAR, NONE OF THE AUTHORS MAKES ANY
     36  1.1  jonathan  * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE
     37  1.1  jonathan  * MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR
     38  1.1  jonathan  * PURPOSE.
     39  1.1  jonathan  */
     40  1.1  jonathan 
     41  1.1  jonathan #include <sys/cdefs.h>
     42  1.8       scw __KERNEL_RCSID(0, "$NetBSD: xform_ipip.c,v 1.8 2004/01/16 11:06:27 scw Exp $");
     43  1.1  jonathan 
     44  1.1  jonathan /*
     45  1.1  jonathan  * IP-inside-IP processing
     46  1.1  jonathan  */
     47  1.1  jonathan #include "opt_inet.h"
     48  1.2  jonathan #ifdef __FreeBSD__
     49  1.1  jonathan #include "opt_inet6.h"
     50  1.1  jonathan #include "opt_random_ip_id.h"
     51  1.1  jonathan #endif /* __FreeBSD__ */
     52  1.1  jonathan 
     53  1.1  jonathan 
     54  1.1  jonathan #include <sys/param.h>
     55  1.1  jonathan #include <sys/systm.h>
     56  1.1  jonathan #include <sys/mbuf.h>
     57  1.1  jonathan #include <sys/socket.h>
     58  1.1  jonathan #include <sys/kernel.h>
     59  1.1  jonathan #include <sys/protosw.h>
     60  1.1  jonathan #include <sys/sysctl.h>
     61  1.1  jonathan 
     62  1.1  jonathan #include <net/if.h>
     63  1.1  jonathan #include <net/route.h>
     64  1.1  jonathan #include <net/netisr.h>
     65  1.1  jonathan 
     66  1.1  jonathan #include <netinet/in.h>
     67  1.1  jonathan #include <netinet/in_systm.h>
     68  1.1  jonathan #include <netinet/in_var.h>
     69  1.1  jonathan #include <netinet/ip.h>
     70  1.1  jonathan #include <netinet/ip_ecn.h>
     71  1.1  jonathan #include <netinet/ip_var.h>
     72  1.1  jonathan #include <netinet/ip_encap.h>
     73  1.1  jonathan #ifdef __FreeBSD__
     74  1.1  jonathan #include <netinet/ipprotosw.h>
     75  1.1  jonathan #endif
     76  1.1  jonathan 
     77  1.1  jonathan #include <netipsec/ipsec.h>
     78  1.1  jonathan #include <netipsec/xform.h>
     79  1.1  jonathan 
     80  1.1  jonathan #include <netipsec/ipip_var.h>
     81  1.1  jonathan 
     82  1.1  jonathan #ifdef MROUTING
     83  1.1  jonathan #include <netinet/ip_mroute.h>
     84  1.1  jonathan #endif
     85  1.1  jonathan 
     86  1.1  jonathan #ifdef INET6
     87  1.1  jonathan #include <netinet/ip6.h>
     88  1.1  jonathan #include <netipsec/ipsec6.h>
     89  1.1  jonathan #include <netinet6/ip6_ecn.h>
     90  1.1  jonathan #include <netinet6/in6_var.h>
     91  1.1  jonathan #include <netinet6/ip6protosw.h>
     92  1.1  jonathan #endif
     93  1.1  jonathan 
     94  1.5       tls #include <netipsec/key.h>
     95  1.5       tls #include <netipsec/key_debug.h>
     96  1.1  jonathan #include <netipsec/ipsec_osdep.h>
     97  1.1  jonathan 
     98  1.1  jonathan #include <machine/stdarg.h>
     99  1.1  jonathan 
    100  1.1  jonathan #ifdef __FreeBSD__
    101  1.1  jonathan typedef void	pr_in_input_t (struct mbuf *, int, int); /* XXX FIX THIS */
    102  1.1  jonathan #else
    103  1.1  jonathan typedef void	pr_in_input_t (struct mbuf *m, ...);
    104  1.1  jonathan #endif
    105  1.1  jonathan 
    106  1.1  jonathan /*
    107  1.1  jonathan  * We can control the acceptance of IP4 packets by altering the sysctl
    108  1.1  jonathan  * net.inet.ipip.allow value.  Zero means drop them, all else is acceptance.
    109  1.1  jonathan  */
    110  1.1  jonathan int	ipip_allow = 0;
    111  1.1  jonathan struct	ipipstat ipipstat;
    112  1.1  jonathan 
    113  1.1  jonathan #ifdef SYSCTL_DECL
    114  1.1  jonathan SYSCTL_DECL(_net_inet_ipip);
    115  1.1  jonathan 
    116  1.1  jonathan SYSCTL_INT(_net_inet_ipip, OID_AUTO,
    117  1.1  jonathan 	ipip_allow,	CTLFLAG_RW,	&ipip_allow,	0, "");
    118  1.1  jonathan SYSCTL_STRUCT(_net_inet_ipip, IPSECCTL_STATS,
    119  1.1  jonathan 	stats,		CTLFLAG_RD,	&ipipstat,	ipipstat, "");
    120  1.1  jonathan 
    121  1.1  jonathan #endif
    122  1.1  jonathan 
    123  1.1  jonathan #ifdef __FreeBSD__
    124  1.1  jonathan static
    125  1.1  jonathan #endif
    126  1.1  jonathan void ipe4_attach(void);
    127  1.1  jonathan 
    128  1.1  jonathan 
    129  1.1  jonathan /* XXX IPCOMP */
    130  1.1  jonathan #define	M_IPSEC	(M_AUTHIPHDR|M_AUTHIPDGM|M_DECRYPTED)
    131  1.1  jonathan 
    132  1.1  jonathan static void _ipip_input(struct mbuf *m, int iphlen, struct ifnet *gifp);
    133  1.1  jonathan 
    134  1.1  jonathan #ifdef INET6
    135  1.1  jonathan /*
    136  1.1  jonathan  * Really only a wrapper for ipip_input(), for use with IPv6.
    137  1.1  jonathan  */
    138  1.1  jonathan int
    139  1.1  jonathan ip4_input6(struct mbuf **m, int *offp, int proto)
    140  1.1  jonathan {
    141  1.1  jonathan #if 0
    142  1.1  jonathan 	/* If we do not accept IP-in-IP explicitly, drop.  */
    143  1.1  jonathan 	if (!ipip_allow && ((*m)->m_flags & M_IPSEC) == 0) {
    144  1.1  jonathan 		DPRINTF(("ip4_input6: dropped due to policy\n"));
    145  1.1  jonathan 		ipipstat.ipips_pdrops++;
    146  1.1  jonathan 		m_freem(*m);
    147  1.1  jonathan 		return IPPROTO_DONE;
    148  1.1  jonathan 	}
    149  1.1  jonathan #endif
    150  1.1  jonathan 	_ipip_input(*m, *offp, NULL);
    151  1.1  jonathan 	return IPPROTO_DONE;
    152  1.1  jonathan }
    153  1.1  jonathan #endif /* INET6 */
    154  1.1  jonathan 
    155  1.1  jonathan #ifdef INET
    156  1.1  jonathan /*
    157  1.1  jonathan  * Really only a wrapper for ipip_input(), for use with IPv4.
    158  1.1  jonathan  */
    159  1.1  jonathan void
    160  1.1  jonathan ip4_input(struct mbuf *m, ...)
    161  1.1  jonathan {
    162  1.1  jonathan 	va_list ap;
    163  1.1  jonathan 	int iphlen;
    164  1.1  jonathan 
    165  1.1  jonathan #if 0
    166  1.1  jonathan 	/* If we do not accept IP-in-IP explicitly, drop.  */
    167  1.1  jonathan 	if (!ipip_allow && (m->m_flags & M_IPSEC) == 0) {
    168  1.1  jonathan 		DPRINTF(("ip4_input: dropped due to policy\n"));
    169  1.1  jonathan 		ipipstat.ipips_pdrops++;
    170  1.1  jonathan 		m_freem(m);
    171  1.1  jonathan 		return;
    172  1.1  jonathan 	}
    173  1.1  jonathan #endif
    174  1.1  jonathan 	va_start(ap, m);
    175  1.1  jonathan 	iphlen = va_arg(ap, int);
    176  1.1  jonathan 	va_end(ap);
    177  1.1  jonathan 
    178  1.1  jonathan 	_ipip_input(m, iphlen, NULL);
    179  1.1  jonathan }
    180  1.1  jonathan #endif /* INET */
    181  1.1  jonathan 
    182  1.1  jonathan /*
    183  1.1  jonathan  * ipip_input gets called when we receive an IP{46} encapsulated packet,
    184  1.1  jonathan  * either because we got it at a real interface, or because AH or ESP
    185  1.1  jonathan  * were being used in tunnel mode (in which case the rcvif element will
    186  1.1  jonathan  * contain the address of the encX interface associated with the tunnel.
    187  1.1  jonathan  */
    188  1.1  jonathan 
    189  1.1  jonathan static void
    190  1.1  jonathan _ipip_input(struct mbuf *m, int iphlen, struct ifnet *gifp)
    191  1.1  jonathan {
    192  1.1  jonathan 	register struct sockaddr_in *sin;
    193  1.1  jonathan 	register struct ifnet *ifp;
    194  1.1  jonathan 	register struct ifaddr *ifa;
    195  1.1  jonathan 	struct ifqueue *ifq = NULL;
    196  1.1  jonathan 	struct ip *ipo;
    197  1.1  jonathan #ifdef INET6
    198  1.1  jonathan 	register struct sockaddr_in6 *sin6;
    199  1.1  jonathan 	struct ip6_hdr *ip6 = NULL;
    200  1.1  jonathan 	u_int8_t itos;
    201  1.1  jonathan #endif
    202  1.1  jonathan 	u_int8_t nxt;
    203  1.1  jonathan 	int isr;
    204  1.1  jonathan 	u_int8_t otos;
    205  1.1  jonathan 	u_int8_t v;
    206  1.1  jonathan 	int hlen;
    207  1.1  jonathan 
    208  1.1  jonathan 	ipipstat.ipips_ipackets++;
    209  1.1  jonathan 
    210  1.1  jonathan 	m_copydata(m, 0, 1, &v);
    211  1.1  jonathan 
    212  1.1  jonathan 	switch (v >> 4) {
    213  1.1  jonathan #ifdef INET
    214  1.1  jonathan         case 4:
    215  1.1  jonathan 		hlen = sizeof(struct ip);
    216  1.1  jonathan 		break;
    217  1.1  jonathan #endif /* INET */
    218  1.1  jonathan #ifdef INET6
    219  1.1  jonathan         case 6:
    220  1.1  jonathan 		hlen = sizeof(struct ip6_hdr);
    221  1.1  jonathan 		break;
    222  1.1  jonathan #endif
    223  1.1  jonathan         default:
    224  1.1  jonathan 		DPRINTF(("_ipip_input: bad protocol version 0x%x (%u) "
    225  1.1  jonathan 			"for outer header\n", v, v>>4));
    226  1.1  jonathan 		ipipstat.ipips_family++;
    227  1.1  jonathan 		m_freem(m);
    228  1.1  jonathan 		return /* EAFNOSUPPORT */;
    229  1.1  jonathan 	}
    230  1.1  jonathan 
    231  1.1  jonathan 	/* Bring the IP header in the first mbuf, if not there already */
    232  1.1  jonathan 	if (m->m_len < hlen) {
    233  1.1  jonathan 		if ((m = m_pullup(m, hlen)) == NULL) {
    234  1.1  jonathan 			DPRINTF(("ipip_input: m_pullup (1) failed\n"));
    235  1.1  jonathan 			ipipstat.ipips_hdrops++;
    236  1.1  jonathan 			return;
    237  1.1  jonathan 		}
    238  1.1  jonathan 	}
    239  1.1  jonathan 
    240  1.1  jonathan 	ipo = mtod(m, struct ip *);
    241  1.1  jonathan 
    242  1.1  jonathan #ifdef MROUTING
    243  1.1  jonathan 	if (ipo->ip_v == IPVERSION && ipo->ip_p == IPPROTO_IPV4) {
    244  1.1  jonathan 		if (IN_MULTICAST(((struct ip *)((char *) ipo + iphlen))->ip_dst.s_addr)) {
    245  1.1  jonathan 			ipip_mroute_input (m, iphlen);
    246  1.1  jonathan 			return;
    247  1.1  jonathan 		}
    248  1.1  jonathan 	}
    249  1.1  jonathan #endif /* MROUTING */
    250  1.1  jonathan 
    251  1.1  jonathan 	/* Keep outer ecn field. */
    252  1.1  jonathan 	switch (v >> 4) {
    253  1.1  jonathan #ifdef INET
    254  1.1  jonathan 	case 4:
    255  1.1  jonathan 		otos = ipo->ip_tos;
    256  1.1  jonathan 		break;
    257  1.1  jonathan #endif /* INET */
    258  1.1  jonathan #ifdef INET6
    259  1.1  jonathan 	case 6:
    260  1.1  jonathan 		otos = (ntohl(mtod(m, struct ip6_hdr *)->ip6_flow) >> 20) & 0xff;
    261  1.1  jonathan 		break;
    262  1.1  jonathan #endif
    263  1.1  jonathan 	default:
    264  1.1  jonathan 		panic("ipip_input: unknown ip version %u (outer)", v>>4);
    265  1.1  jonathan 	}
    266  1.1  jonathan 
    267  1.1  jonathan 	/* Remove outer IP header */
    268  1.1  jonathan 	m_adj(m, iphlen);
    269  1.1  jonathan 
    270  1.1  jonathan 	/* Sanity check */
    271  1.1  jonathan 	if (m->m_pkthdr.len < sizeof(struct ip))  {
    272  1.1  jonathan 		ipipstat.ipips_hdrops++;
    273  1.1  jonathan 		m_freem(m);
    274  1.1  jonathan 		return;
    275  1.1  jonathan 	}
    276  1.1  jonathan 
    277  1.1  jonathan 	m_copydata(m, 0, 1, &v);
    278  1.1  jonathan 
    279  1.1  jonathan 	switch (v >> 4) {
    280  1.1  jonathan #ifdef INET
    281  1.1  jonathan         case 4:
    282  1.1  jonathan 		hlen = sizeof(struct ip);
    283  1.1  jonathan 		break;
    284  1.1  jonathan #endif /* INET */
    285  1.1  jonathan 
    286  1.1  jonathan #ifdef INET6
    287  1.1  jonathan         case 6:
    288  1.1  jonathan 		hlen = sizeof(struct ip6_hdr);
    289  1.1  jonathan 		break;
    290  1.1  jonathan #endif
    291  1.1  jonathan 	default:
    292  1.1  jonathan 		DPRINTF(("_ipip_input: bad protocol version 0x%x (%u) "
    293  1.1  jonathan 			"for inner header\n", v, v>>4));
    294  1.1  jonathan 		ipipstat.ipips_family++;
    295  1.1  jonathan 		m_freem(m);
    296  1.1  jonathan 		return; /* EAFNOSUPPORT */
    297  1.1  jonathan 	}
    298  1.1  jonathan 
    299  1.1  jonathan 	/*
    300  1.1  jonathan 	 * Bring the inner IP header in the first mbuf, if not there already.
    301  1.1  jonathan 	 */
    302  1.1  jonathan 	if (m->m_len < hlen) {
    303  1.1  jonathan 		if ((m = m_pullup(m, hlen)) == NULL) {
    304  1.1  jonathan 			DPRINTF(("ipip_input: m_pullup (2) failed\n"));
    305  1.1  jonathan 			ipipstat.ipips_hdrops++;
    306  1.1  jonathan 			return;
    307  1.1  jonathan 		}
    308  1.1  jonathan 	}
    309  1.1  jonathan 
    310  1.1  jonathan 	/*
    311  1.1  jonathan 	 * RFC 1853 specifies that the inner TTL should not be touched on
    312  1.1  jonathan 	 * decapsulation. There's no reason this comment should be here, but
    313  1.1  jonathan 	 * this is as good as any a position.
    314  1.1  jonathan 	 */
    315  1.1  jonathan 
    316  1.1  jonathan 	/* Some sanity checks in the inner IP header */
    317  1.1  jonathan 	switch (v >> 4) {
    318  1.1  jonathan #ifdef INET
    319  1.1  jonathan     	case 4:
    320  1.1  jonathan                 ipo = mtod(m, struct ip *);
    321  1.1  jonathan                 nxt = ipo->ip_p;
    322  1.1  jonathan 		ip_ecn_egress(ip4_ipsec_ecn, &otos, &ipo->ip_tos);
    323  1.1  jonathan                 break;
    324  1.1  jonathan #endif /* INET */
    325  1.1  jonathan #ifdef INET6
    326  1.1  jonathan     	case 6:
    327  1.1  jonathan                 ip6 = (struct ip6_hdr *) ipo;
    328  1.1  jonathan                 nxt = ip6->ip6_nxt;
    329  1.1  jonathan 		itos = (ntohl(ip6->ip6_flow) >> 20) & 0xff;
    330  1.1  jonathan 		ip_ecn_egress(ip6_ipsec_ecn, &otos, &itos);
    331  1.1  jonathan 		ip6->ip6_flow &= ~htonl(0xff << 20);
    332  1.1  jonathan 		ip6->ip6_flow |= htonl((u_int32_t) itos << 20);
    333  1.1  jonathan                 break;
    334  1.1  jonathan #endif
    335  1.1  jonathan 	default:
    336  1.1  jonathan 		panic("ipip_input: unknown ip version %u (inner)", v>>4);
    337  1.1  jonathan 	}
    338  1.1  jonathan 
    339  1.1  jonathan 	/* Check for local address spoofing. */
    340  1.1  jonathan 	if ((m->m_pkthdr.rcvif == NULL ||
    341  1.1  jonathan 	    !(m->m_pkthdr.rcvif->if_flags & IFF_LOOPBACK)) &&
    342  1.1  jonathan 	    ipip_allow != 2) {
    343  1.1  jonathan 		for (ifp = ifnet.tqh_first; ifp != 0;
    344  1.1  jonathan 		     ifp = ifp->if_list.tqe_next) {
    345  1.1  jonathan 			for (ifa = ifp->if_addrlist.tqh_first; ifa != 0;
    346  1.1  jonathan 			     ifa = ifa->ifa_list.tqe_next) {
    347  1.1  jonathan #ifdef INET
    348  1.1  jonathan 				if (ipo) {
    349  1.1  jonathan 					if (ifa->ifa_addr->sa_family !=
    350  1.1  jonathan 					    AF_INET)
    351  1.1  jonathan 						continue;
    352  1.1  jonathan 
    353  1.1  jonathan 					sin = (struct sockaddr_in *) ifa->ifa_addr;
    354  1.1  jonathan 
    355  1.1  jonathan 					if (sin->sin_addr.s_addr ==
    356  1.1  jonathan 					    ipo->ip_src.s_addr)	{
    357  1.1  jonathan 						ipipstat.ipips_spoof++;
    358  1.1  jonathan 						m_freem(m);
    359  1.1  jonathan 						return;
    360  1.1  jonathan 					}
    361  1.1  jonathan 				}
    362  1.1  jonathan #endif /* INET */
    363  1.1  jonathan 
    364  1.1  jonathan #ifdef INET6
    365  1.1  jonathan 				if (ip6) {
    366  1.1  jonathan 					if (ifa->ifa_addr->sa_family !=
    367  1.1  jonathan 					    AF_INET6)
    368  1.1  jonathan 						continue;
    369  1.1  jonathan 
    370  1.1  jonathan 					sin6 = (struct sockaddr_in6 *) ifa->ifa_addr;
    371  1.1  jonathan 
    372  1.1  jonathan 					if (IN6_ARE_ADDR_EQUAL(&sin6->sin6_addr, &ip6->ip6_src)) {
    373  1.1  jonathan 						ipipstat.ipips_spoof++;
    374  1.1  jonathan 						m_freem(m);
    375  1.1  jonathan 						return;
    376  1.1  jonathan 					}
    377  1.1  jonathan 
    378  1.1  jonathan 				}
    379  1.1  jonathan #endif /* INET6 */
    380  1.1  jonathan 			}
    381  1.1  jonathan 		}
    382  1.1  jonathan 	}
    383  1.1  jonathan 
    384  1.1  jonathan 	/* Statistics */
    385  1.1  jonathan 	ipipstat.ipips_ibytes += m->m_pkthdr.len - iphlen;
    386  1.1  jonathan 
    387  1.1  jonathan 	/*
    388  1.1  jonathan 	 * Interface pointer stays the same; if no IPsec processing has
    389  1.1  jonathan 	 * been done (or will be done), this will point to a normal
    390  1.1  jonathan 	 * interface. Otherwise, it'll point to an enc interface, which
    391  1.1  jonathan 	 * will allow a packet filter to distinguish between secure and
    392  1.1  jonathan 	 * untrusted packets.
    393  1.1  jonathan 	 */
    394  1.1  jonathan 
    395  1.1  jonathan 	switch (v >> 4) {
    396  1.1  jonathan #ifdef INET
    397  1.1  jonathan 	case 4:
    398  1.1  jonathan 		ifq = &ipintrq;
    399  1.1  jonathan 		isr = NETISR_IP;
    400  1.1  jonathan 		break;
    401  1.1  jonathan #endif
    402  1.1  jonathan #ifdef INET6
    403  1.1  jonathan 	case 6:
    404  1.1  jonathan 		ifq = &ip6intrq;
    405  1.1  jonathan 		isr = NETISR_IPV6;
    406  1.1  jonathan 		break;
    407  1.1  jonathan #endif
    408  1.1  jonathan 	default:
    409  1.1  jonathan 		panic("ipip_input: should never reach here");
    410  1.1  jonathan 	}
    411  1.1  jonathan 
    412  1.1  jonathan 	if (!IF_HANDOFF(ifq, m, NULL)) {
    413  1.1  jonathan 		ipipstat.ipips_qfull++;
    414  1.1  jonathan 
    415  1.1  jonathan 		DPRINTF(("ipip_input: packet dropped because of full queue\n"));
    416  1.1  jonathan 	} else {
    417  1.1  jonathan 		schednetisr(isr);
    418  1.1  jonathan 	}
    419  1.1  jonathan }
    420  1.1  jonathan 
    421  1.1  jonathan int
    422  1.1  jonathan ipip_output(
    423  1.1  jonathan 	struct mbuf *m,
    424  1.1  jonathan 	struct ipsecrequest *isr,
    425  1.1  jonathan 	struct mbuf **mp,
    426  1.1  jonathan 	int skip,
    427  1.1  jonathan 	int protoff
    428  1.1  jonathan )
    429  1.1  jonathan {
    430  1.1  jonathan 	struct secasvar *sav;
    431  1.1  jonathan 	u_int8_t tp, otos;
    432  1.1  jonathan 	struct secasindex *saidx;
    433  1.1  jonathan 	int error;
    434  1.1  jonathan #ifdef INET
    435  1.1  jonathan 	u_int8_t itos;
    436  1.1  jonathan 	struct ip *ipo;
    437  1.1  jonathan #endif /* INET */
    438  1.1  jonathan #ifdef INET6
    439  1.1  jonathan 	struct ip6_hdr *ip6, *ip6o;
    440  1.1  jonathan #endif /* INET6 */
    441  1.1  jonathan 
    442  1.1  jonathan 	IPSEC_SPLASSERT_SOFTNET("ipip_output");
    443  1.1  jonathan 
    444  1.1  jonathan 	sav = isr->sav;
    445  1.1  jonathan 	IPSEC_ASSERT(sav != NULL, ("ipip_output: null SA"));
    446  1.1  jonathan 	IPSEC_ASSERT(sav->sah != NULL, ("ipip_output: null SAH"));
    447  1.1  jonathan 
    448  1.1  jonathan 	/* XXX Deal with empty TDB source/destination addresses. */
    449  1.1  jonathan 
    450  1.1  jonathan 	m_copydata(m, 0, 1, &tp);
    451  1.1  jonathan 	tp = (tp >> 4) & 0xff;  /* Get the IP version number. */
    452  1.1  jonathan 
    453  1.1  jonathan 	saidx = &sav->sah->saidx;
    454  1.1  jonathan 	switch (saidx->dst.sa.sa_family) {
    455  1.1  jonathan #ifdef INET
    456  1.1  jonathan 	case AF_INET:
    457  1.1  jonathan 		if (saidx->src.sa.sa_family != AF_INET ||
    458  1.1  jonathan 		    saidx->src.sin.sin_addr.s_addr == INADDR_ANY ||
    459  1.1  jonathan 		    saidx->dst.sin.sin_addr.s_addr == INADDR_ANY) {
    460  1.1  jonathan 			DPRINTF(("ipip_output: unspecified tunnel endpoint "
    461  1.1  jonathan 			    "address in SA %s/%08lx\n",
    462  1.1  jonathan 			    ipsec_address(&saidx->dst),
    463  1.1  jonathan 			    (u_long) ntohl(sav->spi)));
    464  1.1  jonathan 			ipipstat.ipips_unspec++;
    465  1.1  jonathan 			error = EINVAL;
    466  1.1  jonathan 			goto bad;
    467  1.1  jonathan 		}
    468  1.1  jonathan 
    469  1.1  jonathan 		M_PREPEND(m, sizeof(struct ip), M_DONTWAIT);
    470  1.1  jonathan 		if (m == 0) {
    471  1.1  jonathan 			DPRINTF(("ipip_output: M_PREPEND failed\n"));
    472  1.1  jonathan 			ipipstat.ipips_hdrops++;
    473  1.1  jonathan 			error = ENOBUFS;
    474  1.1  jonathan 			goto bad;
    475  1.1  jonathan 		}
    476  1.1  jonathan 
    477  1.1  jonathan 		ipo = mtod(m, struct ip *);
    478  1.1  jonathan 
    479  1.1  jonathan 		ipo->ip_v = IPVERSION;
    480  1.1  jonathan 		ipo->ip_hl = 5;
    481  1.1  jonathan 		ipo->ip_len = htons(m->m_pkthdr.len);
    482  1.1  jonathan 		ipo->ip_ttl = ip_defttl;
    483  1.1  jonathan 		ipo->ip_sum = 0;
    484  1.1  jonathan 		ipo->ip_src = saidx->src.sin.sin_addr;
    485  1.1  jonathan 		ipo->ip_dst = saidx->dst.sin.sin_addr;
    486  1.1  jonathan 
    487  1.7  jonathan #if defined(__NetBSD__)
    488  1.7  jonathan 		ipo->ip_id = ip_newid();
    489  1.7  jonathan #elif defined(RANDOM_IP_ID)
    490  1.5       tls 		ipo->ip_id = ip_randomid();
    491  1.5       tls #else
    492  1.5       tls 		ipo->ip_id = htons(ip_id++);
    493  1.5       tls #endif
    494  1.1  jonathan 
    495  1.1  jonathan 		/* If the inner protocol is IP... */
    496  1.1  jonathan 		if (tp == IPVERSION) {
    497  1.1  jonathan 			/* Save ECN notification */
    498  1.1  jonathan 			m_copydata(m, sizeof(struct ip) +
    499  1.1  jonathan 			    offsetof(struct ip, ip_tos),
    500  1.1  jonathan 			    sizeof(u_int8_t), (caddr_t) &itos);
    501  1.1  jonathan 
    502  1.1  jonathan 			ipo->ip_p = IPPROTO_IPIP;
    503  1.1  jonathan 
    504  1.1  jonathan 			/*
    505  1.1  jonathan 			 * We should be keeping tunnel soft-state and
    506  1.1  jonathan 			 * send back ICMPs if needed.
    507  1.1  jonathan 			 */
    508  1.1  jonathan 			m_copydata(m, sizeof(struct ip) +
    509  1.1  jonathan 			    offsetof(struct ip, ip_off),
    510  1.1  jonathan 			    sizeof(u_int16_t), (caddr_t) &ipo->ip_off);
    511  1.1  jonathan 			ipo->ip_off = ntohs(ipo->ip_off);
    512  1.1  jonathan 			ipo->ip_off &= ~(IP_DF | IP_MF | IP_OFFMASK);
    513  1.1  jonathan 			ipo->ip_off = htons(ipo->ip_off);
    514  1.1  jonathan 		}
    515  1.1  jonathan #ifdef INET6
    516  1.1  jonathan 		else if (tp == (IPV6_VERSION >> 4)) {
    517  1.1  jonathan 			u_int32_t itos32;
    518  1.1  jonathan 
    519  1.1  jonathan 			/* Save ECN notification. */
    520  1.1  jonathan 			m_copydata(m, sizeof(struct ip) +
    521  1.1  jonathan 			    offsetof(struct ip6_hdr, ip6_flow),
    522  1.1  jonathan 			    sizeof(u_int32_t), (caddr_t) &itos32);
    523  1.1  jonathan 			itos = ntohl(itos32) >> 20;
    524  1.1  jonathan 			ipo->ip_p = IPPROTO_IPV6;
    525  1.1  jonathan 			ipo->ip_off = 0;
    526  1.1  jonathan 		}
    527  1.1  jonathan #endif /* INET6 */
    528  1.1  jonathan 		else {
    529  1.1  jonathan 			goto nofamily;
    530  1.1  jonathan 		}
    531  1.1  jonathan 
    532  1.1  jonathan 		otos = 0;
    533  1.1  jonathan 		ip_ecn_ingress(ECN_ALLOWED, &otos, &itos);
    534  1.1  jonathan 		ipo->ip_tos = otos;
    535  1.1  jonathan 		break;
    536  1.1  jonathan #endif /* INET */
    537  1.1  jonathan 
    538  1.1  jonathan #ifdef INET6
    539  1.1  jonathan 	case AF_INET6:
    540  1.1  jonathan 		if (IN6_IS_ADDR_UNSPECIFIED(&saidx->dst.sin6.sin6_addr) ||
    541  1.1  jonathan 		    saidx->src.sa.sa_family != AF_INET6 ||
    542  1.1  jonathan 		    IN6_IS_ADDR_UNSPECIFIED(&saidx->src.sin6.sin6_addr)) {
    543  1.1  jonathan 			DPRINTF(("ipip_output: unspecified tunnel endpoint "
    544  1.1  jonathan 			    "address in SA %s/%08lx\n",
    545  1.1  jonathan 			    ipsec_address(&saidx->dst),
    546  1.1  jonathan 			    (u_long) ntohl(sav->spi)));
    547  1.1  jonathan 			ipipstat.ipips_unspec++;
    548  1.1  jonathan 			error = ENOBUFS;
    549  1.1  jonathan 			goto bad;
    550  1.1  jonathan 		}
    551  1.1  jonathan 
    552  1.1  jonathan 		/* scoped address handling */
    553  1.1  jonathan 		ip6 = mtod(m, struct ip6_hdr *);
    554  1.1  jonathan 		if (IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_src))
    555  1.1  jonathan 			ip6->ip6_src.s6_addr16[1] = 0;
    556  1.1  jonathan 		if (IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_dst))
    557  1.1  jonathan 			ip6->ip6_dst.s6_addr16[1] = 0;
    558  1.1  jonathan 
    559  1.1  jonathan 		M_PREPEND(m, sizeof(struct ip6_hdr), M_DONTWAIT);
    560  1.1  jonathan 		if (m == 0) {
    561  1.1  jonathan 			DPRINTF(("ipip_output: M_PREPEND failed\n"));
    562  1.1  jonathan 			ipipstat.ipips_hdrops++;
    563  1.1  jonathan 			error = ENOBUFS;
    564  1.1  jonathan 			goto bad;
    565  1.1  jonathan 		}
    566  1.1  jonathan 
    567  1.1  jonathan 		/* Initialize IPv6 header */
    568  1.1  jonathan 		ip6o = mtod(m, struct ip6_hdr *);
    569  1.1  jonathan 		ip6o->ip6_flow = 0;
    570  1.1  jonathan 		ip6o->ip6_vfc &= ~IPV6_VERSION_MASK;
    571  1.1  jonathan 		ip6o->ip6_vfc |= IPV6_VERSION;
    572  1.1  jonathan 		ip6o->ip6_plen = htons(m->m_pkthdr.len);
    573  1.1  jonathan 		ip6o->ip6_hlim = ip_defttl;
    574  1.1  jonathan 		ip6o->ip6_dst = saidx->dst.sin6.sin6_addr;
    575  1.1  jonathan 		ip6o->ip6_src = saidx->src.sin6.sin6_addr;
    576  1.1  jonathan 
    577  1.1  jonathan #ifdef INET
    578  1.1  jonathan 		if (tp == IPVERSION) {
    579  1.1  jonathan 			/* Save ECN notification */
    580  1.1  jonathan 			m_copydata(m, sizeof(struct ip6_hdr) +
    581  1.1  jonathan 			    offsetof(struct ip, ip_tos), sizeof(u_int8_t),
    582  1.1  jonathan 			    (caddr_t) &itos);
    583  1.1  jonathan 
    584  1.1  jonathan 			/* This is really IPVERSION. */
    585  1.1  jonathan 			ip6o->ip6_nxt = IPPROTO_IPIP;
    586  1.1  jonathan 		} else
    587  1.1  jonathan #endif /* INET */
    588  1.1  jonathan 			if (tp == (IPV6_VERSION >> 4)) {
    589  1.1  jonathan 				u_int32_t itos32;
    590  1.1  jonathan 
    591  1.1  jonathan 				/* Save ECN notification. */
    592  1.1  jonathan 				m_copydata(m, sizeof(struct ip6_hdr) +
    593  1.1  jonathan 				    offsetof(struct ip6_hdr, ip6_flow),
    594  1.1  jonathan 				    sizeof(u_int32_t), (caddr_t) &itos32);
    595  1.1  jonathan 				itos = ntohl(itos32) >> 20;
    596  1.1  jonathan 
    597  1.1  jonathan 				ip6o->ip6_nxt = IPPROTO_IPV6;
    598  1.1  jonathan 			} else {
    599  1.1  jonathan 				goto nofamily;
    600  1.1  jonathan 			}
    601  1.1  jonathan 
    602  1.1  jonathan 		otos = 0;
    603  1.1  jonathan 		ip_ecn_ingress(ECN_ALLOWED, &otos, &itos);
    604  1.1  jonathan 		ip6o->ip6_flow |= htonl((u_int32_t) otos << 20);
    605  1.1  jonathan 		break;
    606  1.1  jonathan #endif /* INET6 */
    607  1.1  jonathan 
    608  1.1  jonathan 	default:
    609  1.1  jonathan nofamily:
    610  1.1  jonathan 		DPRINTF(("ipip_output: unsupported protocol family %u\n",
    611  1.1  jonathan 		    saidx->dst.sa.sa_family));
    612  1.1  jonathan 		ipipstat.ipips_family++;
    613  1.1  jonathan 		error = EAFNOSUPPORT;		/* XXX diffs from openbsd */
    614  1.1  jonathan 		goto bad;
    615  1.1  jonathan 	}
    616  1.1  jonathan 
    617  1.1  jonathan 	ipipstat.ipips_opackets++;
    618  1.1  jonathan 	*mp = m;
    619  1.1  jonathan 
    620  1.1  jonathan #ifdef INET
    621  1.1  jonathan 	if (saidx->dst.sa.sa_family == AF_INET) {
    622  1.1  jonathan #if 0
    623  1.1  jonathan 		if (sav->tdb_xform->xf_type == XF_IP4)
    624  1.1  jonathan 			tdb->tdb_cur_bytes +=
    625  1.1  jonathan 			    m->m_pkthdr.len - sizeof(struct ip);
    626  1.1  jonathan #endif
    627  1.1  jonathan 		ipipstat.ipips_obytes += m->m_pkthdr.len - sizeof(struct ip);
    628  1.1  jonathan 	}
    629  1.1  jonathan #endif /* INET */
    630  1.1  jonathan 
    631  1.1  jonathan #ifdef INET6
    632  1.1  jonathan 	if (saidx->dst.sa.sa_family == AF_INET6) {
    633  1.1  jonathan #if 0
    634  1.1  jonathan 		if (sav->tdb_xform->xf_type == XF_IP4)
    635  1.1  jonathan 			tdb->tdb_cur_bytes +=
    636  1.1  jonathan 			    m->m_pkthdr.len - sizeof(struct ip6_hdr);
    637  1.1  jonathan #endif
    638  1.1  jonathan 		ipipstat.ipips_obytes +=
    639  1.1  jonathan 		    m->m_pkthdr.len - sizeof(struct ip6_hdr);
    640  1.1  jonathan 	}
    641  1.1  jonathan #endif /* INET6 */
    642  1.1  jonathan 
    643  1.1  jonathan 	return 0;
    644  1.1  jonathan bad:
    645  1.1  jonathan 	if (m)
    646  1.8       scw 		m_freem(m);
    647  1.8       scw 	*mp = NULL;
    648  1.1  jonathan 	return (error);
    649  1.1  jonathan }
    650  1.1  jonathan 
    651  1.1  jonathan #ifdef FAST_IPSEC
    652  1.1  jonathan static int
    653  1.1  jonathan ipe4_init(struct secasvar *sav, struct xformsw *xsp)
    654  1.1  jonathan {
    655  1.1  jonathan 	sav->tdb_xform = xsp;
    656  1.1  jonathan 	return 0;
    657  1.1  jonathan }
    658  1.1  jonathan 
    659  1.1  jonathan static int
    660  1.1  jonathan ipe4_zeroize(struct secasvar *sav)
    661  1.1  jonathan {
    662  1.1  jonathan 	sav->tdb_xform = NULL;
    663  1.1  jonathan 	return 0;
    664  1.1  jonathan }
    665  1.1  jonathan 
    666  1.1  jonathan static int
    667  1.1  jonathan ipe4_input(struct mbuf *m, struct secasvar *sav, int skip, int protoff)
    668  1.1  jonathan {
    669  1.1  jonathan 	/* This is a rather serious mistake, so no conditional printing. */
    670  1.1  jonathan 	printf("ipe4_input: should never be called\n");
    671  1.1  jonathan 	if (m)
    672  1.1  jonathan 		m_freem(m);
    673  1.1  jonathan 	return EOPNOTSUPP;
    674  1.1  jonathan }
    675  1.1  jonathan 
    676  1.1  jonathan static struct xformsw ipe4_xformsw = {
    677  1.1  jonathan 	XF_IP4,		0,		"IPv4 Simple Encapsulation",
    678  1.1  jonathan 	ipe4_init,	ipe4_zeroize,	ipe4_input,	ipip_output,
    679  1.1  jonathan };
    680  1.1  jonathan 
    681  1.1  jonathan extern struct domain inetdomain;
    682  1.1  jonathan static struct ipprotosw ipe4_protosw[] = {
    683  1.1  jonathan { SOCK_RAW,	&inetdomain,	IPPROTO_IPV4,	PR_ATOMIC|PR_ADDR|PR_LASTHDR,
    684  1.1  jonathan   ip4_input,	0, 		0,		rip_ctloutput,
    685  1.1  jonathan   rip_usrreq,
    686  1.1  jonathan   0,		0,		0,		0,
    687  1.1  jonathan },
    688  1.1  jonathan #ifdef INET6
    689  1.1  jonathan { SOCK_RAW,	&inetdomain,	IPPROTO_IPV6,	PR_ATOMIC|PR_ADDR|PR_LASTHDR,
    690  1.1  jonathan   ip4_input,	0,	 	0,		rip_ctloutput,
    691  1.1  jonathan   rip_usrreq,
    692  1.1  jonathan   0,		0,		0,		0,
    693  1.1  jonathan },
    694  1.1  jonathan #endif
    695  1.1  jonathan };
    696  1.1  jonathan 
    697  1.1  jonathan /*
    698  1.1  jonathan  * Check the encapsulated packet to see if we want it
    699  1.1  jonathan  */
    700  1.1  jonathan static int
    701  1.1  jonathan ipe4_encapcheck(const struct mbuf *m, int off, int proto, void *arg)
    702  1.1  jonathan {
    703  1.1  jonathan 	/*
    704  1.1  jonathan 	 * Only take packets coming from IPSEC tunnels; the rest
    705  1.1  jonathan 	 * must be handled by the gif tunnel code.  Note that we
    706  1.1  jonathan 	 * also return a minimum priority when we want the packet
    707  1.1  jonathan 	 * so any explicit gif tunnels take precedence.
    708  1.1  jonathan 	 */
    709  1.1  jonathan 	return ((m->m_flags & M_IPSEC) != 0 ? 1 : 0);
    710  1.1  jonathan }
    711  1.1  jonathan 
    712  1.1  jonathan INITFN void
    713  1.1  jonathan ipe4_attach(void)
    714  1.1  jonathan {
    715  1.1  jonathan 	xform_register(&ipe4_xformsw);
    716  1.1  jonathan 	/* attach to encapsulation framework */
    717  1.1  jonathan 	/* XXX save return cookie for detach on module remove */
    718  1.1  jonathan 	(void) encap_attach_func(AF_INET, -1,
    719  1.1  jonathan 		ipe4_encapcheck, (struct protosw*) &ipe4_protosw[0], NULL);
    720  1.1  jonathan #ifdef INET6
    721  1.1  jonathan 	(void) encap_attach_func(AF_INET6, -1,
    722  1.1  jonathan 		ipe4_encapcheck, (struct protosw*) &ipe4_protosw[1], NULL);
    723  1.1  jonathan #endif
    724  1.1  jonathan }
    725  1.1  jonathan 
    726  1.1  jonathan #ifdef SYSINIT
    727  1.1  jonathan SYSINIT(ipe4_xform_init, SI_SUB_PROTO_DOMAIN, SI_ORDER_MIDDLE, ipe4_attach, NULL);
    728  1.1  jonathan #endif
    729  1.1  jonathan 
    730  1.1  jonathan #endif	/* FAST_IPSEC */
    731