Skip to content

Commit

Permalink
Remove xform_ipip.c and code related to XF_IP4.
Browse files Browse the repository at this point in the history
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
  • Loading branch information
bu7cher committed Apr 18, 2015
1 parent 7ba0420 commit 76eadbe
Show file tree
Hide file tree
Showing 4 changed files with 129 additions and 405 deletions.
1 change: 0 additions & 1 deletion sys/conf/files
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
220 changes: 128 additions & 92 deletions sys/netipsec/ipsec_output.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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.
Expand All @@ -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"));
Expand Down Expand Up @@ -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);
Expand All @@ -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);
Expand Down Expand Up @@ -606,7 +665,6 @@ ipsec6_process_packet(
goto bad;
return EJUSTRETURN;
}

sav = isr->sav;
dst = &sav->sah->saidx.dst;

Expand All @@ -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;
goto bad;
}

if (error) {
if (mp) {
/* XXX: Should never happen! */
m_freem(mp);
}
m = NULL; /* ipip_output() already freed it */
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;
}

m = mp;
mp = NULL;
}

#ifdef DEV_ENC
Expand Down
6 changes: 1 addition & 5 deletions sys/netipsec/xform.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Expand All @@ -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);
Expand Down
Loading

0 comments on commit 76eadbe

Please sign in to comment.