Remove xform_ipip.c and code related to XF_IP4.
The only thing is used from this code is ipip_output() function, that does IPIP encapsulation. Other parts of XF_IP4 code were removed in r275133. Also it isn't possible to configure the use of XF_IP4, nor from userland via setkey(8), nor from the kernel. Simplify the ipip_output() function and rename it to ipsec_encap(). * move IP_DF handling from ipsec4_process_packet() into ipsec_encap(); * since ipsec_encap() called from ipsec[64]_process_packet(), it is safe to assume that mbuf is contiguous at least to IP header for used IP version. Remove all unneeded m_pullup(), m_copydata and related checks. * use V_ip_defttl and V_ip6_defhlim for outer headers; * use V_ip4_ipsec_ecn and V_ip6_ipsec_ecn for outer headers; * move all diagnostic messages to the ipsec_encap() callers; * simplify handling of ipsec_encap() results: if it returns non zero value, print diagnostic message and free mbuf. * some style(9) fixes. Differential Revision: https://reviews.freebsd.org/D2303 Reviewed by: glebius Sponsored by: Yandex LLC
This commit is contained in:
parent
4e25c86f4c
commit
61f376155d
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=281692
@ -3565,7 +3565,6 @@ netipsec/keysock.c optional ipsec inet | ipsec inet6
|
||||
netipsec/xform_ah.c optional ipsec inet | ipsec inet6
|
||||
netipsec/xform_esp.c optional ipsec inet | ipsec inet6
|
||||
netipsec/xform_ipcomp.c optional ipsec inet | ipsec inet6
|
||||
netipsec/xform_ipip.c optional ipsec inet | ipsec inet6
|
||||
netipsec/xform_tcp.c optional ipsec inet tcp_signature | \
|
||||
ipsec inet6 tcp_signature
|
||||
netnatm/natm.c optional natm
|
||||
|
@ -61,6 +61,7 @@
|
||||
#include <netinet/ip6.h>
|
||||
#ifdef INET6
|
||||
#include <netinet6/ip6_var.h>
|
||||
#include <netinet6/scope6_var.h>
|
||||
#endif
|
||||
#include <netinet/in_pcb.h>
|
||||
#ifdef INET6
|
||||
@ -419,6 +420,101 @@ ipsec_nextisr(
|
||||
#undef IPSEC_OSTAT
|
||||
}
|
||||
|
||||
static int
|
||||
ipsec_encap(struct mbuf **mp, struct secasindex *saidx)
|
||||
{
|
||||
#ifdef INET6
|
||||
struct ip6_hdr *ip6;
|
||||
#endif
|
||||
struct ip *ip;
|
||||
int setdf;
|
||||
uint8_t itos, proto;
|
||||
|
||||
ip = mtod(*mp, struct ip *);
|
||||
switch (ip->ip_v) {
|
||||
#ifdef INET
|
||||
case IPVERSION:
|
||||
proto = IPPROTO_IPIP;
|
||||
/*
|
||||
* Collect IP_DF state from the inner header
|
||||
* and honor system-wide control of how to handle it.
|
||||
*/
|
||||
switch (V_ip4_ipsec_dfbit) {
|
||||
case 0: /* clear in outer header */
|
||||
case 1: /* set in outer header */
|
||||
setdf = V_ip4_ipsec_dfbit;
|
||||
break;
|
||||
default:/* propagate to outer header */
|
||||
setdf = (ip->ip_off & ntohs(IP_DF)) != 0;
|
||||
}
|
||||
itos = ip->ip_tos;
|
||||
break;
|
||||
#endif
|
||||
#ifdef INET6
|
||||
case (IPV6_VERSION >> 4):
|
||||
proto = IPPROTO_IPV6;
|
||||
ip6 = mtod(*mp, struct ip6_hdr *);
|
||||
itos = (ntohl(ip6->ip6_flow) >> 20) & 0xff;
|
||||
setdf = V_ip4_ipsec_dfbit ? 1: 0;
|
||||
/* scoped address handling */
|
||||
in6_clearscope(&ip6->ip6_src);
|
||||
in6_clearscope(&ip6->ip6_dst);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
return (EAFNOSUPPORT);
|
||||
}
|
||||
switch (saidx->dst.sa.sa_family) {
|
||||
#ifdef INET
|
||||
case AF_INET:
|
||||
if (saidx->src.sa.sa_family != AF_INET ||
|
||||
saidx->src.sin.sin_addr.s_addr == INADDR_ANY ||
|
||||
saidx->dst.sin.sin_addr.s_addr == INADDR_ANY)
|
||||
return (EINVAL);
|
||||
M_PREPEND(*mp, sizeof(struct ip), M_NOWAIT);
|
||||
if (*mp == NULL)
|
||||
return (ENOBUFS);
|
||||
ip = mtod(*mp, struct ip *);
|
||||
ip->ip_v = IPVERSION;
|
||||
ip->ip_hl = sizeof(struct ip) >> 2;
|
||||
ip->ip_p = proto;
|
||||
ip->ip_len = htons((*mp)->m_pkthdr.len);
|
||||
ip->ip_ttl = V_ip_defttl;
|
||||
ip->ip_sum = 0;
|
||||
ip->ip_off = setdf ? htons(IP_DF): 0;
|
||||
ip->ip_src = saidx->src.sin.sin_addr;
|
||||
ip->ip_dst = saidx->dst.sin.sin_addr;
|
||||
ip_ecn_ingress(V_ip4_ipsec_ecn, &ip->ip_tos, &itos);
|
||||
ip_fillid(ip);
|
||||
break;
|
||||
#endif /* INET */
|
||||
#ifdef INET6
|
||||
case AF_INET6:
|
||||
if (saidx->src.sa.sa_family != AF_INET6 ||
|
||||
IN6_IS_ADDR_UNSPECIFIED(&saidx->src.sin6.sin6_addr) ||
|
||||
IN6_IS_ADDR_UNSPECIFIED(&saidx->dst.sin6.sin6_addr))
|
||||
return (EINVAL);
|
||||
M_PREPEND(*mp, sizeof(struct ip6_hdr), M_NOWAIT);
|
||||
if (*mp == NULL)
|
||||
return (ENOBUFS);
|
||||
ip6 = mtod(*mp, struct ip6_hdr *);
|
||||
ip6->ip6_flow = 0;
|
||||
ip6->ip6_vfc = IPV6_VERSION;
|
||||
ip6->ip6_hlim = V_ip6_defhlim;
|
||||
ip6->ip6_nxt = proto;
|
||||
ip6->ip6_dst = saidx->dst.sin6.sin6_addr;
|
||||
ip6->ip6_src = saidx->src.sin6.sin6_addr;
|
||||
ip6->ip6_plen = htons((*mp)->m_pkthdr.len - sizeof(*ip6));
|
||||
ip_ecn_ingress(V_ip6_ipsec_ecn, &proto, &itos);
|
||||
ip6->ip6_flow |= htonl((uint32_t)proto << 20);
|
||||
break;
|
||||
#endif /* INET6 */
|
||||
default:
|
||||
return (EAFNOSUPPORT);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
#ifdef INET
|
||||
/*
|
||||
* IPsec output logic for IPv4.
|
||||
@ -430,7 +526,7 @@ ipsec4_process_packet(struct mbuf *m, struct ipsecrequest *isr)
|
||||
struct secasindex saidx;
|
||||
struct secasvar *sav;
|
||||
struct ip *ip;
|
||||
int error, i, off, setdf;
|
||||
int error, i, off;
|
||||
|
||||
IPSEC_ASSERT(m != NULL, ("null mbuf"));
|
||||
IPSEC_ASSERT(isr != NULL, ("null isr"));
|
||||
@ -465,53 +561,23 @@ ipsec4_process_packet(struct mbuf *m, struct ipsecrequest *isr)
|
||||
/* Do the appropriate encapsulation, if necessary */
|
||||
if (isr->saidx.mode == IPSEC_MODE_TUNNEL || /* Tunnel requ'd */
|
||||
dst->sa.sa_family != AF_INET || /* PF mismatch */
|
||||
#if 0
|
||||
(sav->flags & SADB_X_SAFLAGS_TUNNEL) || /* Tunnel requ'd */
|
||||
sav->tdb_xform->xf_type == XF_IP4 || /* ditto */
|
||||
#endif
|
||||
(dst->sa.sa_family == AF_INET && /* Proxy */
|
||||
dst->sin.sin_addr.s_addr != INADDR_ANY &&
|
||||
dst->sin.sin_addr.s_addr != ip->ip_dst.s_addr)) {
|
||||
struct mbuf *mp;
|
||||
|
||||
/* Fix IPv4 header checksum and length */
|
||||
ip->ip_len = htons(m->m_pkthdr.len);
|
||||
ip->ip_sum = 0;
|
||||
ip->ip_sum = in_cksum(m, ip->ip_hl << 2);
|
||||
/*
|
||||
* Collect IP_DF state from the outer header
|
||||
* and honor system-wide control of how to handle it.
|
||||
*/
|
||||
switch (V_ip4_ipsec_dfbit) {
|
||||
case 0: /* clear in outer header */
|
||||
case 1: /* set in outer header */
|
||||
setdf = V_ip4_ipsec_dfbit;
|
||||
break;
|
||||
default: /* propagate to outer header */
|
||||
setdf = ntohs(ip->ip_off & IP_DF);
|
||||
}
|
||||
/* Encapsulate the packet */
|
||||
error = ipip_output(m, isr, &mp, 0, 0);
|
||||
error = ipsec_encap(&m, &sav->sah->saidx);
|
||||
if (error != 0) {
|
||||
m = NULL; /* ipip_output() already freed it */
|
||||
DPRINTF(("%s: encapsulation for SA %s->%s "
|
||||
"SPI 0x%08x failed with error %d\n", __func__,
|
||||
ipsec_address(&sav->sah->saidx.src),
|
||||
ipsec_address(&sav->sah->saidx.dst),
|
||||
ntohl(sav->spi), error));
|
||||
goto bad;
|
||||
}
|
||||
m = mp;
|
||||
/*
|
||||
* ipip_output clears IP_DF in the new header. If
|
||||
* we need to propagate IP_DF from the outer header,
|
||||
* then we have to do it here.
|
||||
*
|
||||
* XXX shouldn't assume what ipip_output does.
|
||||
*/
|
||||
if (dst->sa.sa_family == AF_INET && setdf) {
|
||||
ip = mtod(m, struct ip *);
|
||||
ip->ip_off = ntohs(ip->ip_off);
|
||||
ip->ip_off |= IP_DF;
|
||||
ip->ip_off = htons(ip->ip_off);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DEV_ENC
|
||||
/* pass the mbuf to enc0 for bpf processing */
|
||||
ipsec_bpf(m, sav, sav->sah->saidx.dst.sa.sa_family, ENC_OUT|ENC_AFTER);
|
||||
@ -523,40 +589,33 @@ ipsec4_process_packet(struct mbuf *m, struct ipsecrequest *isr)
|
||||
/*
|
||||
* Dispatch to the appropriate IPsec transform logic. The
|
||||
* packet will be returned for transmission after crypto
|
||||
* processing, etc. are completed. For encapsulation we
|
||||
* bypass this call because of the explicit call done above
|
||||
* (necessary to deal with IP_DF handling for IPv4).
|
||||
* processing, etc. are completed.
|
||||
*
|
||||
* NB: m & sav are ``passed to caller'' who's reponsible for
|
||||
* for reclaiming their resources.
|
||||
*/
|
||||
if (sav->tdb_xform->xf_type != XF_IP4) {
|
||||
union sockaddr_union *dst = &sav->sah->saidx.dst;
|
||||
switch(dst->sa.sa_family) {
|
||||
case AF_INET:
|
||||
ip = mtod(m, struct ip *);
|
||||
i = ip->ip_hl << 2;
|
||||
off = offsetof(struct ip, ip_p);
|
||||
break;
|
||||
switch(dst->sa.sa_family) {
|
||||
case AF_INET:
|
||||
ip = mtod(m, struct ip *);
|
||||
i = ip->ip_hl << 2;
|
||||
off = offsetof(struct ip, ip_p);
|
||||
break;
|
||||
#ifdef INET6
|
||||
case AF_INET6:
|
||||
i = sizeof(struct ip6_hdr);
|
||||
off = offsetof(struct ip6_hdr, ip6_nxt);
|
||||
break;
|
||||
case AF_INET6:
|
||||
i = sizeof(struct ip6_hdr);
|
||||
off = offsetof(struct ip6_hdr, ip6_nxt);
|
||||
break;
|
||||
#endif /* INET6 */
|
||||
default:
|
||||
default:
|
||||
DPRINTF(("%s: unsupported protocol family %u\n",
|
||||
__func__, dst->sa.sa_family));
|
||||
error = EPFNOSUPPORT;
|
||||
IPSECSTAT_INC(ips_out_inval);
|
||||
goto bad;
|
||||
}
|
||||
error = (*sav->tdb_xform->xf_output)(m, isr, NULL, i, off);
|
||||
} else {
|
||||
error = ipsec_process_done(m, isr);
|
||||
__func__, dst->sa.sa_family));
|
||||
error = EPFNOSUPPORT;
|
||||
IPSECSTAT_INC(ips_out_inval);
|
||||
goto bad;
|
||||
}
|
||||
error = (*sav->tdb_xform->xf_output)(m, isr, NULL, i, off);
|
||||
IPSECREQUEST_UNLOCK(isr);
|
||||
return error;
|
||||
return (error);
|
||||
bad:
|
||||
if (isr)
|
||||
IPSECREQUEST_UNLOCK(isr);
|
||||
@ -606,7 +665,6 @@ ipsec6_process_packet(
|
||||
goto bad;
|
||||
return EJUSTRETURN;
|
||||
}
|
||||
|
||||
sav = isr->sav;
|
||||
dst = &sav->sah->saidx.dst;
|
||||
|
||||
@ -630,42 +688,20 @@ ipsec6_process_packet(
|
||||
(!IN6_IS_ADDR_UNSPECIFIED(&dst->sin6.sin6_addr)) &&
|
||||
(!in6_sa_equal_addrwithscope(&dst->sin6,
|
||||
&ip6->ip6_dst)))) {
|
||||
struct mbuf *mp;
|
||||
|
||||
/* Fix IPv6 header payload length. */
|
||||
if (m->m_len < sizeof(struct ip6_hdr))
|
||||
if ((m = m_pullup(m,sizeof(struct ip6_hdr))) == NULL) {
|
||||
error = ENOBUFS;
|
||||
goto bad;
|
||||
}
|
||||
|
||||
if (m->m_pkthdr.len - sizeof(*ip6) > IPV6_MAXPACKET) {
|
||||
/* No jumbogram support. */
|
||||
error = ENXIO; /*XXX*/
|
||||
goto bad;
|
||||
}
|
||||
|
||||
/* Encapsulate the packet */
|
||||
error = ipip_output(m, isr, &mp, 0, 0);
|
||||
if (mp == NULL && !error) {
|
||||
/* Should never happen. */
|
||||
DPRINTF(("ipsec6_process_packet: ipip_output "
|
||||
"returns no mbuf and no error!"));
|
||||
error = EFAULT;
|
||||
error = ipsec_encap(&m, &sav->sah->saidx);
|
||||
if (error != 0) {
|
||||
DPRINTF(("%s: encapsulation for SA %s->%s "
|
||||
"SPI 0x%08x failed with error %d\n", __func__,
|
||||
ipsec_address(&sav->sah->saidx.src),
|
||||
ipsec_address(&sav->sah->saidx.dst),
|
||||
ntohl(sav->spi), error));
|
||||
goto bad;
|
||||
}
|
||||
|
||||
if (error) {
|
||||
if (mp) {
|
||||
/* XXX: Should never happen! */
|
||||
m_freem(mp);
|
||||
}
|
||||
m = NULL; /* ipip_output() already freed it */
|
||||
goto bad;
|
||||
}
|
||||
|
||||
m = mp;
|
||||
mp = NULL;
|
||||
}
|
||||
|
||||
#ifdef DEV_ENC
|
||||
|
@ -83,7 +83,7 @@ struct ipescrequest;
|
||||
|
||||
struct xformsw {
|
||||
u_short xf_type; /* xform ID */
|
||||
#define XF_IP4 1 /* IP inside IP */
|
||||
#define XF_IP4 1 /* unused */
|
||||
#define XF_AH 2 /* AH */
|
||||
#define XF_ESP 3 /* ESP */
|
||||
#define XF_TCPSIGNATURE 5 /* TCP MD5 Signature option, RFC 2358 */
|
||||
@ -108,10 +108,6 @@ extern int xform_init(struct secasvar *sav, int xftype);
|
||||
|
||||
struct cryptoini;
|
||||
|
||||
/* XF_IP4 */
|
||||
extern int ipip_output(struct mbuf *, struct ipsecrequest *,
|
||||
struct mbuf **, int, int);
|
||||
|
||||
/* XF_AH */
|
||||
extern int ah_init0(struct secasvar *, struct xformsw *, struct cryptoini *);
|
||||
extern int ah_zeroize(struct secasvar *sav);
|
||||
|
@ -1,307 +0,0 @@
|
||||
/* $FreeBSD$ */
|
||||
/* $OpenBSD: ip_ipip.c,v 1.25 2002/06/10 18:04:55 itojun Exp $ */
|
||||
/*-
|
||||
* The authors of this code are John Ioannidis (ji@tla.org),
|
||||
* Angelos D. Keromytis (kermit@csd.uch.gr) and
|
||||
* Niels Provos (provos@physnet.uni-hamburg.de).
|
||||
*
|
||||
* The original version of this code was written by John Ioannidis
|
||||
* for BSD/OS in Athens, Greece, in November 1995.
|
||||
*
|
||||
* Ported to OpenBSD and NetBSD, with additional transforms, in December 1996,
|
||||
* by Angelos D. Keromytis.
|
||||
*
|
||||
* Additional transforms and features in 1997 and 1998 by Angelos D. Keromytis
|
||||
* and Niels Provos.
|
||||
*
|
||||
* Additional features in 1999 by Angelos D. Keromytis.
|
||||
*
|
||||
* Copyright (C) 1995, 1996, 1997, 1998, 1999 by John Ioannidis,
|
||||
* Angelos D. Keromytis and Niels Provos.
|
||||
* Copyright (c) 2001, Angelos D. Keromytis.
|
||||
*
|
||||
* Permission to use, copy, and modify this software with or without fee
|
||||
* is hereby granted, provided that this entire notice is included in
|
||||
* all copies of any software which is or includes a copy or
|
||||
* modification of this software.
|
||||
* You may use this code under the GNU public license if you so wish. Please
|
||||
* contribute changes back to the authors under this freer than GPL license
|
||||
* so that we may further the use of strong encryption without limitations to
|
||||
* all.
|
||||
*
|
||||
* THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR
|
||||
* IMPLIED WARRANTY. IN PARTICULAR, NONE OF THE AUTHORS MAKES ANY
|
||||
* REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE
|
||||
* MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR
|
||||
* PURPOSE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* IP-inside-IP processing
|
||||
*/
|
||||
#include "opt_inet.h"
|
||||
#include "opt_inet6.h"
|
||||
#include "opt_enc.h"
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/mbuf.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/protosw.h>
|
||||
#include <sys/sysctl.h>
|
||||
|
||||
#include <net/if.h>
|
||||
#include <net/if_var.h>
|
||||
#include <net/pfil.h>
|
||||
#include <net/netisr.h>
|
||||
#include <net/vnet.h>
|
||||
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/in_systm.h>
|
||||
#include <netinet/in_var.h>
|
||||
#include <netinet/ip.h>
|
||||
#include <netinet/ip_ecn.h>
|
||||
#include <netinet/ip_var.h>
|
||||
|
||||
#include <netipsec/ipsec.h>
|
||||
#include <netipsec/xform.h>
|
||||
|
||||
#ifdef INET6
|
||||
#include <netinet/ip6.h>
|
||||
#include <netipsec/ipsec6.h>
|
||||
#include <netinet6/ip6_ecn.h>
|
||||
#include <netinet6/in6_var.h>
|
||||
#include <netinet6/scope6_var.h>
|
||||
#endif
|
||||
|
||||
#include <netipsec/key.h>
|
||||
#include <netipsec/key_debug.h>
|
||||
|
||||
int
|
||||
ipip_output(struct mbuf *m, struct ipsecrequest *isr, struct mbuf **mp,
|
||||
int skip, int protoff)
|
||||
{
|
||||
struct secasvar *sav;
|
||||
u_int8_t tp, otos;
|
||||
struct secasindex *saidx;
|
||||
int error;
|
||||
#if defined(INET) || defined(INET6)
|
||||
u_int8_t itos;
|
||||
#endif
|
||||
#ifdef INET
|
||||
struct ip *ipo;
|
||||
#endif /* INET */
|
||||
#ifdef INET6
|
||||
struct ip6_hdr *ip6, *ip6o;
|
||||
#endif /* INET6 */
|
||||
|
||||
sav = isr->sav;
|
||||
IPSEC_ASSERT(sav != NULL, ("null SA"));
|
||||
IPSEC_ASSERT(sav->sah != NULL, ("null SAH"));
|
||||
|
||||
/* XXX Deal with empty TDB source/destination addresses. */
|
||||
|
||||
m_copydata(m, 0, 1, &tp);
|
||||
tp = (tp >> 4) & 0xff; /* Get the IP version number. */
|
||||
|
||||
saidx = &sav->sah->saidx;
|
||||
switch (saidx->dst.sa.sa_family) {
|
||||
#ifdef INET
|
||||
case AF_INET:
|
||||
if (saidx->src.sa.sa_family != AF_INET ||
|
||||
saidx->src.sin.sin_addr.s_addr == INADDR_ANY ||
|
||||
saidx->dst.sin.sin_addr.s_addr == INADDR_ANY) {
|
||||
DPRINTF(("%s: unspecified tunnel endpoint "
|
||||
"address in SA %s/%08lx\n", __func__,
|
||||
ipsec_address(&saidx->dst),
|
||||
(u_long) ntohl(sav->spi)));
|
||||
error = EINVAL;
|
||||
goto bad;
|
||||
}
|
||||
|
||||
M_PREPEND(m, sizeof(struct ip), M_NOWAIT);
|
||||
if (m == 0) {
|
||||
DPRINTF(("%s: M_PREPEND failed\n", __func__));
|
||||
error = ENOBUFS;
|
||||
goto bad;
|
||||
}
|
||||
|
||||
ipo = mtod(m, struct ip *);
|
||||
|
||||
ipo->ip_v = IPVERSION;
|
||||
ipo->ip_hl = 5;
|
||||
ipo->ip_len = htons(m->m_pkthdr.len);
|
||||
ipo->ip_ttl = V_ip_defttl;
|
||||
ipo->ip_sum = 0;
|
||||
ipo->ip_src = saidx->src.sin.sin_addr;
|
||||
ipo->ip_dst = saidx->dst.sin.sin_addr;
|
||||
/* If the inner protocol is IP... */
|
||||
switch (tp) {
|
||||
case IPVERSION:
|
||||
/* Save ECN notification */
|
||||
m_copydata(m, sizeof(struct ip) +
|
||||
offsetof(struct ip, ip_tos),
|
||||
sizeof(u_int8_t), (caddr_t) &itos);
|
||||
|
||||
ipo->ip_p = IPPROTO_IPIP;
|
||||
|
||||
/*
|
||||
* We should be keeping tunnel soft-state and
|
||||
* send back ICMPs if needed.
|
||||
*/
|
||||
m_copydata(m, sizeof(struct ip) +
|
||||
offsetof(struct ip, ip_off),
|
||||
sizeof(u_int16_t), (caddr_t) &ipo->ip_off);
|
||||
ipo->ip_off = ntohs(ipo->ip_off);
|
||||
ipo->ip_off &= ~(IP_DF | IP_MF | IP_OFFMASK);
|
||||
ipo->ip_off = htons(ipo->ip_off);
|
||||
break;
|
||||
#ifdef INET6
|
||||
case (IPV6_VERSION >> 4):
|
||||
{
|
||||
u_int32_t itos32;
|
||||
|
||||
/* Save ECN notification. */
|
||||
m_copydata(m, sizeof(struct ip) +
|
||||
offsetof(struct ip6_hdr, ip6_flow),
|
||||
sizeof(u_int32_t), (caddr_t) &itos32);
|
||||
itos = ntohl(itos32) >> 20;
|
||||
ipo->ip_p = IPPROTO_IPV6;
|
||||
ipo->ip_off = 0;
|
||||
break;
|
||||
}
|
||||
#endif /* INET6 */
|
||||
default:
|
||||
goto nofamily;
|
||||
}
|
||||
ip_fillid(ipo);
|
||||
|
||||
otos = 0;
|
||||
ip_ecn_ingress(ECN_ALLOWED, &otos, &itos);
|
||||
ipo->ip_tos = otos;
|
||||
break;
|
||||
#endif /* INET */
|
||||
|
||||
#ifdef INET6
|
||||
case AF_INET6:
|
||||
if (IN6_IS_ADDR_UNSPECIFIED(&saidx->dst.sin6.sin6_addr) ||
|
||||
saidx->src.sa.sa_family != AF_INET6 ||
|
||||
IN6_IS_ADDR_UNSPECIFIED(&saidx->src.sin6.sin6_addr)) {
|
||||
DPRINTF(("%s: unspecified tunnel endpoint "
|
||||
"address in SA %s/%08lx\n", __func__,
|
||||
ipsec_address(&saidx->dst),
|
||||
(u_long) ntohl(sav->spi)));
|
||||
error = ENOBUFS;
|
||||
goto bad;
|
||||
}
|
||||
|
||||
/* scoped address handling */
|
||||
ip6 = mtod(m, struct ip6_hdr *);
|
||||
in6_clearscope(&ip6->ip6_src);
|
||||
in6_clearscope(&ip6->ip6_dst);
|
||||
M_PREPEND(m, sizeof(struct ip6_hdr), M_NOWAIT);
|
||||
if (m == 0) {
|
||||
DPRINTF(("%s: M_PREPEND failed\n", __func__));
|
||||
error = ENOBUFS;
|
||||
goto bad;
|
||||
}
|
||||
|
||||
/* Initialize IPv6 header */
|
||||
ip6o = mtod(m, struct ip6_hdr *);
|
||||
ip6o->ip6_flow = 0;
|
||||
ip6o->ip6_vfc &= ~IPV6_VERSION_MASK;
|
||||
ip6o->ip6_vfc |= IPV6_VERSION;
|
||||
ip6o->ip6_hlim = IPV6_DEFHLIM;
|
||||
ip6o->ip6_dst = saidx->dst.sin6.sin6_addr;
|
||||
ip6o->ip6_src = saidx->src.sin6.sin6_addr;
|
||||
ip6o->ip6_plen = htons(m->m_pkthdr.len - sizeof(*ip6));
|
||||
|
||||
switch (tp) {
|
||||
#ifdef INET
|
||||
case IPVERSION:
|
||||
/* Save ECN notification */
|
||||
m_copydata(m, sizeof(struct ip6_hdr) +
|
||||
offsetof(struct ip, ip_tos), sizeof(u_int8_t),
|
||||
(caddr_t) &itos);
|
||||
|
||||
/* This is really IPVERSION. */
|
||||
ip6o->ip6_nxt = IPPROTO_IPIP;
|
||||
break;
|
||||
#endif /* INET */
|
||||
case (IPV6_VERSION >> 4):
|
||||
{
|
||||
u_int32_t itos32;
|
||||
|
||||
/* Save ECN notification. */
|
||||
m_copydata(m, sizeof(struct ip6_hdr) +
|
||||
offsetof(struct ip6_hdr, ip6_flow),
|
||||
sizeof(u_int32_t), (caddr_t) &itos32);
|
||||
itos = ntohl(itos32) >> 20;
|
||||
|
||||
ip6o->ip6_nxt = IPPROTO_IPV6;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
goto nofamily;
|
||||
}
|
||||
|
||||
otos = 0;
|
||||
ip_ecn_ingress(V_ip6_ipsec_ecn, &otos, &itos);
|
||||
ip6o->ip6_flow |= htonl((u_int32_t) otos << 20);
|
||||
break;
|
||||
#endif /* INET6 */
|
||||
|
||||
default:
|
||||
nofamily:
|
||||
DPRINTF(("%s: unsupported protocol family %u\n", __func__,
|
||||
saidx->dst.sa.sa_family));
|
||||
error = EAFNOSUPPORT; /* XXX diffs from openbsd */
|
||||
goto bad;
|
||||
}
|
||||
|
||||
*mp = m;
|
||||
return (0);
|
||||
bad:
|
||||
if (m)
|
||||
m_freem(m);
|
||||
*mp = NULL;
|
||||
return (error);
|
||||
}
|
||||
|
||||
static int
|
||||
ipe4_init(struct secasvar *sav, struct xformsw *xsp)
|
||||
{
|
||||
sav->tdb_xform = xsp;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
ipe4_zeroize(struct secasvar *sav)
|
||||
{
|
||||
sav->tdb_xform = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
ipe4_input(struct mbuf *m, struct secasvar *sav, int skip, int protoff)
|
||||
{
|
||||
/* This is a rather serious mistake, so no conditional printing. */
|
||||
printf("%s: should never be called\n", __func__);
|
||||
if (m)
|
||||
m_freem(m);
|
||||
return EOPNOTSUPP;
|
||||
}
|
||||
|
||||
static struct xformsw ipe4_xformsw = {
|
||||
XF_IP4, 0, "IPv4 Simple Encapsulation",
|
||||
ipe4_init, ipe4_zeroize, ipe4_input, ipip_output,
|
||||
};
|
||||
|
||||
static void
|
||||
ipe4_attach(void)
|
||||
{
|
||||
|
||||
xform_register(&ipe4_xformsw);
|
||||
}
|
||||
SYSINIT(ipe4_xform_init, SI_SUB_PROTO_DOMAIN, SI_ORDER_MIDDLE, ipe4_attach, NULL);
|
Loading…
Reference in New Issue
Block a user