diff options
author | 2012-07-16 18:05:35 +0000 | |
---|---|---|
committer | 2012-07-16 18:05:35 +0000 | |
commit | b56612b66b8cadc7230e84b35909f55f5c054283 (patch) | |
tree | 822862e8089359ab08fc085f1cbe0976036b9252 | |
parent | Forgot these files during the recent clock churning. (diff) | |
download | wireguard-openbsd-b56612b66b8cadc7230e84b35909f55f5c054283.tar.xz wireguard-openbsd-b56612b66b8cadc7230e84b35909f55f5c054283.zip |
add IP_IPSECFLOWINFO option to sendmsg() and recvmsg(), so npppd(4)
can use this to select the IPsec tunnel for sending L2TP packets.
this fixes Windows (always binding to 1701) and Android clients
(negotiating wildcard flows); feedback mpf@ and yasuoka@;
ok henning@ and yasuoka@; ok jmc@ for the manpage
-rw-r--r-- | share/man/man4/ip.4 | 41 | ||||
-rw-r--r-- | sys/net/if_bridge.c | 4 | ||||
-rw-r--r-- | sys/netinet/in.h | 3 | ||||
-rw-r--r-- | sys/netinet/in_pcb.h | 3 | ||||
-rw-r--r-- | sys/netinet/ip_input.c | 6 | ||||
-rw-r--r-- | sys/netinet/ip_ipsp.h | 4 | ||||
-rw-r--r-- | sys/netinet/ip_output.c | 14 | ||||
-rw-r--r-- | sys/netinet/ip_spd.c | 26 | ||||
-rw-r--r-- | sys/netinet/ip_var.h | 3 | ||||
-rw-r--r-- | sys/netinet/tcp_input.c | 4 | ||||
-rw-r--r-- | sys/netinet/udp_usrreq.c | 60 | ||||
-rw-r--r-- | sys/netinet6/ip6_forward.c | 4 | ||||
-rw-r--r-- | sys/netinet6/ip6_output.c | 4 | ||||
-rw-r--r-- | usr.sbin/npppd/common/recvfromto.c | 76 | ||||
-rw-r--r-- | usr.sbin/npppd/common/recvfromto.h | 3 | ||||
-rw-r--r-- | usr.sbin/npppd/l2tp/l2tp_ctrl.c | 15 | ||||
-rw-r--r-- | usr.sbin/npppd/l2tp/l2tp_local.h | 12 | ||||
-rw-r--r-- | usr.sbin/npppd/l2tp/l2tpd.c | 23 | ||||
-rw-r--r-- | usr.sbin/npppd/npppd/Makefile | 3 | ||||
-rw-r--r-- | usr.sbin/npppd/npppd/npppd.c | 6 |
20 files changed, 266 insertions, 48 deletions
diff --git a/share/man/man4/ip.4 b/share/man/man4/ip.4 index 3b3f83cbf7a..1a70a3541f8 100644 --- a/share/man/man4/ip.4 +++ b/share/man/man4/ip.4 @@ -1,4 +1,4 @@ -.\" $OpenBSD: ip.4,v 1.33 2011/09/08 16:43:56 giovanni Exp $ +.\" $OpenBSD: ip.4,v 1.34 2012/07/16 18:05:35 markus Exp $ .\" $NetBSD: ip.4,v 1.3 1994/11/30 16:22:19 jtc Exp $ .\" .\" Copyright (c) 1983, 1991, 1993 @@ -30,7 +30,7 @@ .\" .\" @(#)ip.4 8.2 (Berkeley) 11/30/93 .\" -.Dd $Mdocdate: September 8 2011 $ +.Dd $Mdocdate: July 16 2012 $ .Dt IP 4 .Os .Sh NAME @@ -209,6 +209,43 @@ int minttl = 255; setsockopt(s, IPPROTO_IP, IP_MINTTL, &minttl, sizeof(minttl)); .Ed .Pp +If the +.Dv IP_IPSECFLOWINFO +option is enabled on a +.Dv SOCK_DGRAM +socket, +the +.Xr recvmsg 2 +call will return information identifying the incoming +IPsec SA for a +.Tn UDP +datagram. +The +.Va msg_control +field in the +.Vt msghdr +structure points to a buffer that contains a +.Vt cmsghdr +structure followed by flow information in 32-bit network byte order. +When this information is passed to a +.Xr sendmsg 2 +call the ID of the incoming SA will be used for looking up the +outgoing SA for the +.Tn UDP +datagram. +The +.Vt cmsghdr +fields for +.Xr recvmsg 2 +and +.Xr sendmsg 2 +have the following values: +.Bd -literal -offset indent +cmsg_len = CMSG_LEN(sizeof(u_int32_t)) +cmsg_level = IPPROTO_IP +cmsg_type = IP_IPSECFLOWINFO +.Ed +.Pp The .Dv IP_PORTRANGE option causes the default allocation policy for when the kernel is asked diff --git a/sys/net/if_bridge.c b/sys/net/if_bridge.c index 730c902ab80..1d81886b002 100644 --- a/sys/net/if_bridge.c +++ b/sys/net/if_bridge.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_bridge.c,v 1.193 2011/07/04 06:54:49 claudio Exp $ */ +/* $OpenBSD: if_bridge.c,v 1.194 2012/07/16 18:05:36 markus Exp $ */ /* * Copyright (c) 1999, 2000 Jason L. Wright (jason@thought.net) @@ -2442,7 +2442,7 @@ bridge_ipsec(struct bridge_softc *sc, struct ifnet *ifp, } } else { /* Outgoing from the bridge. */ tdb = ipsp_spd_lookup(m, af, hlen, &error, - IPSP_DIRECTION_OUT, NULL, NULL); + IPSP_DIRECTION_OUT, NULL, NULL, 0); if (tdb != NULL) { /* * We don't need to do loop detection, the diff --git a/sys/netinet/in.h b/sys/netinet/in.h index 18f275bb84d..56e3986185a 100644 --- a/sys/netinet/in.h +++ b/sys/netinet/in.h @@ -1,4 +1,4 @@ -/* $OpenBSD: in.h,v 1.92 2012/07/10 11:49:42 guenther Exp $ */ +/* $OpenBSD: in.h,v 1.93 2012/07/16 18:05:36 markus Exp $ */ /* $NetBSD: in.h,v 1.20 1996/02/13 23:41:47 christos Exp $ */ /* @@ -298,6 +298,7 @@ struct ip_opts { #define IP_RECVDSTPORT 33 /* bool; receive IP dst port w/dgram */ #define IP_PIPEX 34 /* bool; using PIPEX */ #define IP_RECVRTABLE 35 /* bool; receive rdomain w/dgram */ +#define IP_IPSECFLOWINFO 36 /* bool; IPsec flow info for dgram */ #define IP_RTABLE 0x1021 /* int; routing table, see SO_RTABLE */ diff --git a/sys/netinet/in_pcb.h b/sys/netinet/in_pcb.h index de634b82b7f..9d4f0d96c91 100644 --- a/sys/netinet/in_pcb.h +++ b/sys/netinet/in_pcb.h @@ -1,4 +1,4 @@ -/* $OpenBSD: in_pcb.h,v 1.71 2011/06/15 09:11:01 mikeb Exp $ */ +/* $OpenBSD: in_pcb.h,v 1.72 2012/07/16 18:05:36 markus Exp $ */ /* $NetBSD: in_pcb.h,v 1.14 1996/02/13 23:42:00 christos Exp $ */ /* @@ -175,6 +175,7 @@ struct inpcbtable { #define INP_RECVTTL 0x040 /* receive incoming IP TTL */ #define INP_RECVDSTPORT 0x200 /* receive IP dst addr before rdr */ #define INP_RECVRTABLE 0x400 /* receive routing table */ +#define INP_IPSECFLOWINFO 0x800 /* receive IPsec flow info */ #define INP_CONTROLOPTS (INP_RECVOPTS|INP_RECVRETOPTS|INP_RECVDSTADDR| \ INP_RXSRCRT|INP_HOPLIMIT|INP_RECVIF|INP_RECVTTL|INP_RECVDSTPORT| \ diff --git a/sys/netinet/ip_input.c b/sys/netinet/ip_input.c index 7fa3d66f7f0..b39dc35c4f0 100644 --- a/sys/netinet/ip_input.c +++ b/sys/netinet/ip_input.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ip_input.c,v 1.195 2011/07/06 02:42:28 henning Exp $ */ +/* $OpenBSD: ip_input.c,v 1.196 2012/07/16 18:05:36 markus Exp $ */ /* $NetBSD: ip_input.c,v 1.30 1996/03/16 23:53:58 christos Exp $ */ /* @@ -479,7 +479,7 @@ ipv4_input(struct mbuf *m) } else tdb = NULL; ipsp_spd_lookup(m, AF_INET, hlen, &error, - IPSP_DIRECTION_IN, tdb, NULL); + IPSP_DIRECTION_IN, tdb, NULL, 0); splx(s); /* Error or otherwise drop-packet indication */ @@ -639,7 +639,7 @@ found: } else tdb = NULL; ipsp_spd_lookup(m, AF_INET, hlen, &error, IPSP_DIRECTION_IN, - tdb, NULL); + tdb, NULL, 0); splx(s); /* Error or otherwise drop-packet indication. */ diff --git a/sys/netinet/ip_ipsp.h b/sys/netinet/ip_ipsp.h index 80df24988d1..83b112262e6 100644 --- a/sys/netinet/ip_ipsp.h +++ b/sys/netinet/ip_ipsp.h @@ -1,4 +1,4 @@ -/* $OpenBSD: ip_ipsp.h,v 1.147 2012/06/29 14:48:04 mikeb Exp $ */ +/* $OpenBSD: ip_ipsp.h,v 1.148 2012/07/16 18:05:36 markus Exp $ */ /* * The authors of this code are John Ioannidis (ji@tla.org), * Angelos D. Keromytis (kermit@csd.uch.gr), @@ -634,7 +634,7 @@ extern unsigned char ipseczeroes[]; extern int ipsp_process_packet(struct mbuf *, struct tdb *, int, int); extern int ipsp_process_done(struct mbuf *, struct tdb *); extern struct tdb *ipsp_spd_lookup(struct mbuf *, int, int, int *, int, - struct tdb *, struct inpcb *); + struct tdb *, struct inpcb *, u_int32_t); extern struct tdb *ipsp_spd_inp(struct mbuf *, int, int, int *, int, struct tdb *, struct inpcb *, struct ipsec_policy *); extern int ipsec_common_input(struct mbuf *, int, int, int, int, int); diff --git a/sys/netinet/ip_output.c b/sys/netinet/ip_output.c index 19acb1c7b64..83c61ea159e 100644 --- a/sys/netinet/ip_output.c +++ b/sys/netinet/ip_output.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ip_output.c,v 1.229 2012/04/13 09:38:32 deraadt Exp $ */ +/* $OpenBSD: ip_output.c,v 1.230 2012/07/16 18:05:36 markus Exp $ */ /* $NetBSD: ip_output.c,v 1.28 1996/02/13 23:43:07 christos Exp $ */ /* @@ -120,6 +120,7 @@ ip_output(struct mbuf *m0, ...) struct inpcb *inp; struct tdb *tdb; + u_int32_t ipsecflowinfo; int s; #if NPF > 0 struct ifnet *encif; @@ -135,6 +136,7 @@ ip_output(struct mbuf *m0, ...) inp = va_arg(ap, struct inpcb *); if (inp && (inp->inp_flags & INP_IPV6) != 0) panic("ip_output: IPv6 pcb is passed"); + ipsecflowinfo = (flags & IP_IPSECFLOW) ? va_arg(ap, u_int32_t) : 0; #endif /* IPSEC */ va_end(ap); @@ -289,7 +291,7 @@ reroute: } else tdb = ipsp_spd_lookup(m, AF_INET, hlen, &error, - IPSP_DIRECTION_OUT, NULL, inp); + IPSP_DIRECTION_OUT, NULL, inp, ipsecflowinfo); if (tdb == NULL) { splx(s); @@ -1061,6 +1063,7 @@ ip_ctloutput(op, so, level, optname, mp) case IP_RECVTTL: case IP_RECVDSTPORT: case IP_RECVRTABLE: + case IP_IPSECFLOWINFO: if (m == NULL || m->m_len != sizeof(int)) error = EINVAL; else { @@ -1113,6 +1116,9 @@ ip_ctloutput(op, so, level, optname, mp) case IP_RECVRTABLE: OPTSET(INP_RECVRTABLE); break; + case IP_IPSECFLOWINFO: + OPTSET(INP_IPSECFLOWINFO); + break; } } break; @@ -1446,6 +1452,7 @@ ip_ctloutput(op, so, level, optname, mp) case IP_RECVTTL: case IP_RECVDSTPORT: case IP_RECVRTABLE: + case IP_IPSECFLOWINFO: *mp = m = m_get(M_WAIT, MT_SOOPTS); m->m_len = sizeof(int); switch (optname) { @@ -1487,6 +1494,9 @@ ip_ctloutput(op, so, level, optname, mp) case IP_RECVRTABLE: optval = OPTBIT(INP_RECVRTABLE); break; + case IP_IPSECFLOWINFO: + optval = OPTBIT(INP_IPSECFLOWINFO); + break; } *mtod(m, int *) = optval; break; diff --git a/sys/netinet/ip_spd.c b/sys/netinet/ip_spd.c index 86e12a0d5bc..fecc8af3a75 100644 --- a/sys/netinet/ip_spd.c +++ b/sys/netinet/ip_spd.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ip_spd.c,v 1.63 2010/09/28 01:44:57 deraadt Exp $ */ +/* $OpenBSD: ip_spd.c,v 1.64 2012/07/16 18:05:36 markus Exp $ */ /* * The author of this code is Angelos D. Keromytis (angelos@cis.upenn.edu) * @@ -79,12 +79,14 @@ int ipsec_acquire_pool_initialized = 0; */ struct tdb * ipsp_spd_lookup(struct mbuf *m, int af, int hlen, int *error, int direction, - struct tdb *tdbp, struct inpcb *inp) + struct tdb *tdbp, struct inpcb *inp, u_int32_t ipsecflowinfo) { struct route_enc re0, *re = &re0; union sockaddr_union sdst, ssrc; struct sockaddr_encap *ddst; struct ipsec_policy *ipo; + struct ipsec_ref *dstid = NULL, *srcid = NULL; + struct tdb *tdbin = NULL; int signore = 0, dignore = 0; u_int rdomain = rtable_l2(m->m_pkthdr.rdomain); @@ -334,6 +336,17 @@ ipsp_spd_lookup(struct mbuf *m, int af, int hlen, int *error, int direction, /* Outgoing packet policy check. */ if (direction == IPSP_DIRECTION_OUT) { /* + * Fetch the incoming TDB based on the SPI passed + * in ipsecflow and use it's dstid when looking + * up the outgoing TDB. + */ + if (ipsecflowinfo && + (tdbin = gettdb(rdomain, ipsecflowinfo, &ssrc, + ipo->ipo_sproto)) != NULL) { + srcid = tdbin->tdb_dstid; + dstid = tdbin->tdb_srcid; + } + /* * If the packet is destined for the policy-specified * gateway/endhost, and the socket has the BYPASS * option set, skip IPsec processing. @@ -361,7 +374,8 @@ ipsp_spd_lookup(struct mbuf *m, int af, int hlen, int *error, int direction, goto nomatchout; if (!ipsp_aux_match(ipo->ipo_tdb, - ipo->ipo_srcid, ipo->ipo_dstid, + srcid ? srcid : ipo->ipo_srcid, + dstid ? dstid : ipo->ipo_dstid, ipo->ipo_local_cred, NULL, &ipo->ipo_addr, &ipo->ipo_mask)) goto nomatchout; @@ -397,8 +411,10 @@ ipsp_spd_lookup(struct mbuf *m, int af, int hlen, int *error, int direction, ipo->ipo_tdb = gettdbbyaddr(rdomain, dignore ? &sdst : &ipo->ipo_dst, - ipo->ipo_sproto, ipo->ipo_srcid, - ipo->ipo_dstid, ipo->ipo_local_cred, m, af, + ipo->ipo_sproto, + srcid ? srcid : ipo->ipo_srcid, + dstid ? dstid : ipo->ipo_dstid, + ipo->ipo_local_cred, m, af, &ipo->ipo_addr, &ipo->ipo_mask); if (ipo->ipo_tdb) { TAILQ_INSERT_TAIL(&ipo->ipo_tdb->tdb_policy_head, diff --git a/sys/netinet/ip_var.h b/sys/netinet/ip_var.h index 9fe0fdf817c..fe60ebd6af8 100644 --- a/sys/netinet/ip_var.h +++ b/sys/netinet/ip_var.h @@ -1,4 +1,4 @@ -/* $OpenBSD: ip_var.h,v 1.43 2012/03/17 10:16:41 dlg Exp $ */ +/* $OpenBSD: ip_var.h,v 1.44 2012/07/16 18:05:36 markus Exp $ */ /* $NetBSD: ip_var.h,v 1.16 1996/02/13 23:43:20 christos Exp $ */ /* @@ -143,6 +143,7 @@ struct ipstat { #define IP_ALLOWBROADCAST SO_BROADCAST /* can send broadcast packets */ #define IP_MTUDISC 0x0800 /* pmtu discovery, set DF */ #define IP_ROUTETOETHER 0x1000 /* ether addresses given */ +#define IP_IPSECFLOW 0x2000 /* IPsec flow info */ extern struct ipstat ipstat; extern LIST_HEAD(ipqhead, ipq) ipq; /* ip reass. queue */ diff --git a/sys/netinet/tcp_input.c b/sys/netinet/tcp_input.c index fd0ac5c9c86..39651b9231c 100644 --- a/sys/netinet/tcp_input.c +++ b/sys/netinet/tcp_input.c @@ -1,4 +1,4 @@ -/* $OpenBSD: tcp_input.c,v 1.252 2012/03/10 12:03:29 claudio Exp $ */ +/* $OpenBSD: tcp_input.c,v 1.253 2012/07/16 18:05:36 markus Exp $ */ /* $NetBSD: tcp_input.c,v 1.23 1996/02/13 23:43:44 christos Exp $ */ /* @@ -912,7 +912,7 @@ findpcb: } else tdb = NULL; ipsp_spd_lookup(m, af, iphlen, &error, IPSP_DIRECTION_IN, - tdb, inp); + tdb, inp, 0); if (error) { splx(s); goto drop; diff --git a/sys/netinet/udp_usrreq.c b/sys/netinet/udp_usrreq.c index 67f5897f775..8e7c92db484 100644 --- a/sys/netinet/udp_usrreq.c +++ b/sys/netinet/udp_usrreq.c @@ -1,4 +1,4 @@ -/* $OpenBSD: udp_usrreq.c,v 1.147 2012/04/04 04:31:38 yasuoka Exp $ */ +/* $OpenBSD: udp_usrreq.c,v 1.148 2012/07/16 18:05:36 markus Exp $ */ /* $NetBSD: udp_usrreq.c,v 1.28 1996/03/16 23:54:03 christos Exp $ */ /* @@ -197,6 +197,7 @@ udp_input(struct mbuf *m, ...) struct m_tag *mtag; struct tdb_ident *tdbi; struct tdb *tdb; + struct mbuf *iopts = NULL; int error, s; #endif /* IPSEC */ @@ -629,7 +630,7 @@ udp_input(struct mbuf *m, ...) } else tdb = NULL; ipsp_spd_lookup(m, srcsa.sa.sa_family, iphlen, &error, - IPSP_DIRECTION_IN, tdb, inp); + IPSP_DIRECTION_IN, tdb, inp, 0); if (error) { splx(s); goto bad; @@ -671,6 +672,10 @@ udp_input(struct mbuf *m, ...) inp->inp_tdb_in = NULL; } } + /* create ipsec options while we know that tdb cannot be modified */ + if (tdb && (inp->inp_flags & INP_IPSECFLOWINFO)) + iopts = sbcreatecontrol((caddr_t)&tdb->tdb_spi, + sizeof(tdb->tdb_spi), IP_IPSECFLOWINFO, IPPROTO_IP); splx(s); #endif /*IPSEC */ @@ -691,6 +696,12 @@ udp_input(struct mbuf *m, ...) *mp = sbcreatecontrol((caddr_t)&uh->uh_dport, sizeof(u_int16_t), IP_RECVDSTPORT, IPPROTO_IP); } +#ifdef IPSEC + if (iopts) { + iopts->m_next = opts; + opts = iopts; /* prepend */ + } +#endif #ifdef PIPEX if (pipex_enable && inp->inp_pipex) { struct pipex_session *session; @@ -943,6 +954,7 @@ udp_output(struct mbuf *m, ...) struct inpcb *inp; struct mbuf *addr, *control; struct udpiphdr *ui; + u_int32_t ipsecflowinfo = 0; int len = m->m_pkthdr.len; struct in_addr laddr; int s = 0, error = 0; @@ -989,6 +1001,46 @@ udp_output(struct mbuf *m, ...) goto release; } } + +#ifdef IPSEC + if (control && (inp->inp_flags & INP_IPSECFLOWINFO) != 0) { + u_int clen; + struct cmsghdr *cm; + caddr_t cmsgs; + + /* + * XXX: Currently, we assume all the optional information is stored + * in a single mbuf. + */ + if (control->m_next) { + error = EINVAL; + goto bail; + } + + clen = control->m_len; + cmsgs = mtod(control, caddr_t); + do { + if (clen < CMSG_LEN(0)) { + error = EINVAL; + goto bail; + } + cm = (struct cmsghdr *)cmsgs; + if (cm->cmsg_len < CMSG_LEN(0) || + CMSG_ALIGN(cm->cmsg_len) > clen) { + error = EINVAL; + goto bail; + } + if (cm->cmsg_len == CMSG_LEN(sizeof(ipsecflowinfo)) && + cm->cmsg_level == IPPROTO_IP && + cm->cmsg_type == IP_IPSECFLOWINFO) { + ipsecflowinfo = *(u_int32_t *)CMSG_DATA(cm); + break; + } + clen -= CMSG_ALIGN(cm->cmsg_len); + cmsgs += CMSG_ALIGN(cm->cmsg_len); + } while (clen); + } +#endif /* * Calculate data length and get a mbuf * for UDP and IP headers. @@ -1034,8 +1086,8 @@ udp_output(struct mbuf *m, ...) m->m_pkthdr.rdomain = inp->inp_rtableid; error = ip_output(m, inp->inp_options, &inp->inp_route, - inp->inp_socket->so_options & (SO_DONTROUTE | SO_BROADCAST), - inp->inp_moptions, inp); + (inp->inp_socket->so_options & (SO_DONTROUTE | SO_BROADCAST)) + |IP_IPSECFLOW, inp->inp_moptions, inp, ipsecflowinfo); if (error == EACCES) /* translate pf(4) error for userland */ error = EHOSTUNREACH; diff --git a/sys/netinet6/ip6_forward.c b/sys/netinet6/ip6_forward.c index 4045cc1d6a1..3c63ac1c6df 100644 --- a/sys/netinet6/ip6_forward.c +++ b/sys/netinet6/ip6_forward.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ip6_forward.c,v 1.53 2011/07/04 06:54:49 claudio Exp $ */ +/* $OpenBSD: ip6_forward.c,v 1.54 2012/07/16 18:05:36 markus Exp $ */ /* $KAME: ip6_forward.c,v 1.75 2001/06/29 12:42:13 jinmei Exp $ */ /* @@ -171,7 +171,7 @@ reroute: m_tag_delete(m, mtag); } else tdb = ipsp_spd_lookup(m, AF_INET6, sizeof(struct ip6_hdr), - &error, IPSP_DIRECTION_OUT, NULL, NULL); + &error, IPSP_DIRECTION_OUT, NULL, NULL, 0); if (tdb == NULL) { splx(s); diff --git a/sys/netinet6/ip6_output.c b/sys/netinet6/ip6_output.c index 328d561dbeb..07aedeed4d2 100644 --- a/sys/netinet6/ip6_output.c +++ b/sys/netinet6/ip6_output.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ip6_output.c,v 1.124 2012/04/13 09:38:32 deraadt Exp $ */ +/* $OpenBSD: ip6_output.c,v 1.125 2012/07/16 18:05:36 markus Exp $ */ /* $KAME: ip6_output.c,v 1.172 2001/03/25 09:55:56 itojun Exp $ */ /* @@ -248,7 +248,7 @@ ip6_output(struct mbuf *m0, struct ip6_pktopts *opt, struct route_in6 *ro, m_tag_delete(m, mtag); } else tdb = ipsp_spd_lookup(m, AF_INET6, sizeof(struct ip6_hdr), - &error, IPSP_DIRECTION_OUT, NULL, inp); + &error, IPSP_DIRECTION_OUT, NULL, inp, 0); if (tdb == NULL) { splx(s); diff --git a/usr.sbin/npppd/common/recvfromto.c b/usr.sbin/npppd/common/recvfromto.c index 0f1b89a22db..4054d9fa001 100644 --- a/usr.sbin/npppd/common/recvfromto.c +++ b/usr.sbin/npppd/common/recvfromto.c @@ -40,7 +40,8 @@ * setsockopt() have already performed on socket. */ int -recvfromto(s, buf, buflen, flags, from, fromlen, to, tolen) +recvfromto_nat_t(s, buf, buflen, flags, from, fromlen, to, tolen, + ipsec, ipseclen) int s; void *buf; size_t buflen; @@ -49,8 +50,11 @@ recvfromto(s, buf, buflen, flags, from, fromlen, to, tolen) u_int *fromlen; struct sockaddr *to; u_int *tolen; + void *ipsec; + u_int *ipseclen; { int otolen; + u_int oipseclen = 0; ssize_t len; struct sockaddr_storage ss; struct msghdr m; @@ -81,6 +85,10 @@ recvfromto(s, buf, buflen, flags, from, fromlen, to, tolen) } *fromlen = m.msg_namelen; + if (ipsec && ipseclen) { + oipseclen = *ipseclen; + *ipseclen = 0; + } otolen = *tolen; *tolen = 0; for (cm = (struct cmsghdr *)CMSG_FIRSTHDR(&m); @@ -110,6 +118,16 @@ recvfromto(s, buf, buflen, flags, from, fromlen, to, tolen) otolen = -1; /* "to" already set */ continue; } +#ifdef IP_IPSECFLOWINFO + if (ss.ss_family == AF_INET /* ?? */ + && cm->cmsg_level == IPPROTO_IP + && cm->cmsg_type == IP_IPSECFLOWINFO + && oipseclen >= sizeof(u_int32_t)) { + *ipseclen = sizeof(u_int32_t); + memcpy(ipsec, CMSG_DATA(cm), *ipseclen); + continue; + } +#endif #ifdef __linux__ if (ss.ss_family == AF_INET && cm->cmsg_level == IPPROTO_IP @@ -167,3 +185,59 @@ recvfromto(s, buf, buflen, flags, from, fromlen, to, tolen) return len; } + +int +recvfromto(s, buf, buflen, flags, from, fromlen, to, tolen) + int s; + void *buf; + size_t buflen; + int flags; + struct sockaddr *from; + u_int *fromlen; + struct sockaddr *to; + u_int *tolen; +{ + return recvfromto_nat_t(s, buf, buflen, flags, from, fromlen, + to, tolen, NULL, NULL); +} + +int +sendto_nat_t(s, buf, buflen, flags, to, tolen, ipsec) + int s; + void *buf; + size_t buflen; + int flags; + struct sockaddr *to; + u_int tolen; + void *ipsec; +{ +#ifdef IP_IPSECFLOWINFO + if (ipsec) { + struct iovec iov[1]; + struct msghdr msg; + struct cmsghdr *cmsg; + union { + struct cmsghdr hdr; + char buf[CMSG_SPACE(sizeof(u_int32_t))]; + } cmsgbuf; + + iov[0].iov_base = (char *)buf; + iov[0].iov_len = buflen; + memset(&msg, 0, sizeof(msg)); + memset(&cmsgbuf, 0, sizeof(cmsgbuf)); + msg.msg_name = to; + msg.msg_namelen = tolen; + msg.msg_iov = iov; + msg.msg_iovlen = 1; + msg.msg_control = (caddr_t)&cmsgbuf.buf; + msg.msg_controllen = sizeof(cmsgbuf.buf); + cmsg = CMSG_FIRSTHDR(&msg); + cmsg->cmsg_len = CMSG_LEN(sizeof(u_int32_t)); + cmsg->cmsg_level = IPPROTO_IP; + cmsg->cmsg_type = IP_IPSECFLOWINFO; + memcpy(CMSG_DATA(cmsg), ipsec, sizeof(u_int32_t)); + return sendmsg(s, &msg, flags); + } +#endif + return sendto(s, buf, buflen, flags, to, tolen); +} diff --git a/usr.sbin/npppd/common/recvfromto.h b/usr.sbin/npppd/common/recvfromto.h index b46b24f0b86..cf0ac2295a7 100644 --- a/usr.sbin/npppd/common/recvfromto.h +++ b/usr.sbin/npppd/common/recvfromto.h @@ -30,6 +30,9 @@ extern "C" { #endif int recvfromto (int, void *, size_t, int, struct sockaddr *, u_int *, struct sockaddr *, u_int *); +int recvfromto_nat_t (int, void *, size_t, int, struct sockaddr *, u_int *, + struct sockaddr *, u_int *, void *, u_int *); +int sendto_nat_t (int, void *, size_t, int, struct sockaddr *, u_int, void *); #ifdef __cplusplus } diff --git a/usr.sbin/npppd/l2tp/l2tp_ctrl.c b/usr.sbin/npppd/l2tp/l2tp_ctrl.c index 87a41de6a82..a1f333e5fd5 100644 --- a/usr.sbin/npppd/l2tp/l2tp_ctrl.c +++ b/usr.sbin/npppd/l2tp/l2tp_ctrl.c @@ -1,4 +1,4 @@ -/* $OpenBSD: l2tp_ctrl.c,v 1.11 2012/05/08 13:28:06 yasuoka Exp $ */ +/* $OpenBSD: l2tp_ctrl.c,v 1.12 2012/07/16 18:05:36 markus Exp $ */ /*- * Copyright (c) 2009 Internet Initiative Japan Inc. @@ -26,7 +26,7 @@ * SUCH DAMAGE. */ /**@file Control connection processing functions for L2TP LNS */ -/* $Id: l2tp_ctrl.c,v 1.11 2012/05/08 13:28:06 yasuoka Exp $ */ +/* $Id: l2tp_ctrl.c,v 1.12 2012/07/16 18:05:36 markus Exp $ */ #include <sys/types.h> #include <sys/param.h> #include <sys/time.h> @@ -181,7 +181,7 @@ l2tp_ctrl_init(l2tp_ctrl *_this, l2tpd *_l2tpd, struct sockaddr *peer, "bytebuffer_create() failed in %s(): %m", __func__); goto fail; } -#ifdef USE_LIBSOCKUTIL +#if defined(USE_LIBSOCKUTIL) || defined(USE_SA_COOKIE) if (nat_t_ctx != NULL) { if ((_this->sa_cookie = malloc( sizeof(struct in_ipsec_sa_cookie))) != NULL) { @@ -235,7 +235,7 @@ void l2tp_ctrl_destroy(l2tp_ctrl *_this) { L2TP_CTRL_ASSERT(_this != NULL); -#ifdef USE_LIBSOCKUTIL +#if defined(USE_LIBSOCKUTIL) || defined(USE_SA_COOKIE) if (_this->sa_cookie != NULL) free(_this->sa_cookie); #endif @@ -594,6 +594,13 @@ l2tp_ctrl_send(l2tp_ctrl *_this, const void *msg, int len) (struct sockaddr *)&_this->sock, (struct sockaddr *)&_this->peer); #else +#ifdef USE_SA_COOKIE + if (_this->sa_cookie != NULL) + rval = sendto_nat_t(LISTENER_SOCK(_this), msg, len, 0, + (struct sockaddr *)&_this->peer, _this->peer.ss_len, + _this->sa_cookie); + else +#endif rval = sendto(LISTENER_SOCK(_this), msg, len, 0, (struct sockaddr *)&_this->peer, _this->peer.ss_len); #endif diff --git a/usr.sbin/npppd/l2tp/l2tp_local.h b/usr.sbin/npppd/l2tp/l2tp_local.h index 1a5490dc3a9..cdcb92c9ea7 100644 --- a/usr.sbin/npppd/l2tp/l2tp_local.h +++ b/usr.sbin/npppd/l2tp/l2tp_local.h @@ -1,4 +1,4 @@ -/* $OpenBSD: l2tp_local.h,v 1.5 2012/05/08 13:15:11 yasuoka Exp $ */ +/* $OpenBSD: l2tp_local.h,v 1.6 2012/07/16 18:05:36 markus Exp $ */ /*- * Copyright (c) 2009 Internet Initiative Japan Inc. * All rights reserved. @@ -26,7 +26,7 @@ */ #ifndef L2TP_LOCAL_H #define L2TP_LOCAL_H 1 -/* $Id: l2tp_local.h,v 1.5 2012/05/08 13:15:11 yasuoka Exp $ */ +/* $Id: l2tp_local.h,v 1.6 2012/07/16 18:05:36 markus Exp $ */ #ifndef GETSHORT #define GETSHORT(s, cp) { \ @@ -71,7 +71,9 @@ struct l2tp_header { #define LISTENER_SOCK(ctrl) \ ((l2tpd_listener *)slist_get(&(ctrl)->l2tpd->listener, \ (ctrl)->listener_index))->sock +#ifndef SIN #define SIN(ss) ((struct sockaddr_in *)(ss)) +#endif #define SIN6(ss) ((struct sockaddr_in6 *)(ss)) #define L2TP_SESSION_ID_MASK 0x00007fff @@ -85,4 +87,10 @@ struct l2tp_header { #error L2TP_NCALL must be less than 65536 #endif +#ifndef USE_LIBSOCKUTIL +struct in_ipsec_sa_cookie { + u_int32_t ipsecflow; +}; +#endif + #endif diff --git a/usr.sbin/npppd/l2tp/l2tpd.c b/usr.sbin/npppd/l2tp/l2tpd.c index a35028e9813..e5f739f8bc8 100644 --- a/usr.sbin/npppd/l2tp/l2tpd.c +++ b/usr.sbin/npppd/l2tp/l2tpd.c @@ -1,4 +1,4 @@ -/* $OpenBSD: l2tpd.c,v 1.9 2012/05/08 13:18:37 yasuoka Exp $ */ +/* $OpenBSD: l2tpd.c,v 1.10 2012/07/16 18:05:36 markus Exp $ */ /*- * Copyright (c) 2009 Internet Initiative Japan Inc. @@ -26,7 +26,7 @@ * SUCH DAMAGE. */ /**@file L2TP(Layer Two Tunneling Protocol "L2TP") / RFC2661 */ -/* $Id: l2tpd.c,v 1.9 2012/05/08 13:18:37 yasuoka Exp $ */ +/* $Id: l2tpd.c,v 1.10 2012/07/16 18:05:36 markus Exp $ */ #include <sys/types.h> #include <sys/socket.h> #include <sys/time.h> @@ -82,11 +82,6 @@ static inline uint32_t short_hash (const void *, int); /* sequence # of l2tpd ID */ static u_int l2tpd_id_seq = 0; -#ifndef USE_LIBSOCKUTIL -struct in_ipsec_sa_cookie { }; -#endif - - /* L2TP daemon instance */ /** @@ -356,6 +351,16 @@ l2tpd_listener_start(l2tpd_listener *_this, char *ipsec_policy_in, __func__); goto fail; } +#ifdef USE_SA_COOKIE + ival = 1; + if (setsockopt(sock, IPPROTO_IP, IP_IPSECFLOWINFO, &ival, + sizeof(ival)) != 0) { + l2tpd_log(_l2tpd, LOG_ERR, + "setsockopt(,,IP_IPSECFLOWINFO) failed in %s(): %m", + __func__); + goto fail; + } +#endif } else { ival = 1; if (setsockopt(sock, IPPROTO_IPV6, IPV6_RECVPKTINFO, &ival, @@ -781,7 +786,7 @@ l2tpd_io_event(int fd, short evtype, void *ctx) peerlen = sizeof(peer); socklen = sizeof(sock); while (!l2tpd_is_stopped(_l2tpd)) { -#ifdef USE_LIBSOCKUTIL +#if defined(USE_LIBSOCKUTIL) || defined(USE_SA_COOKIE) int sa_cookie_len; struct in_ipsec_sa_cookie sa_cookie; @@ -808,7 +813,7 @@ l2tpd_io_event(int fd, short evtype, void *ctx) /* source address check (allows.in) */ switch (peer.ss_family) { case AF_INET: -#ifdef USE_LIBSOCKUTIL +#if defined(USE_LIBSOCKUTIL) || defined(USE_SA_COOKIE) if (sa_cookie_len > 0) nat_t = &sa_cookie; else diff --git a/usr.sbin/npppd/npppd/Makefile b/usr.sbin/npppd/npppd/Makefile index ce76cd011a2..80e89f29b71 100644 --- a/usr.sbin/npppd/npppd/Makefile +++ b/usr.sbin/npppd/npppd/Makefile @@ -1,4 +1,4 @@ -# $OpenBSD: Makefile,v 1.11 2012/07/08 13:21:02 giovanni Exp $ +# $OpenBSD: Makefile,v 1.12 2012/07/16 18:05:36 markus Exp $ NPPPD_COMMON_DIR= ${.CURDIR}/../common @@ -35,6 +35,7 @@ CPPFLAGS+= -DNPPPD_MAX_IFACE=8 CPPFLAGS+= -DUSE_NPPPD_MPPE CPPFLAGS+= -DUSE_NPPPD_PIPEX CPPFLAGS+= -DUSE_NPPPD_RADIUS +CPPFLAGS+= -DUSE_SA_COOKIE CPPFLAGS+= -DGENERIC_USE -DRADISH diff --git a/usr.sbin/npppd/npppd/npppd.c b/usr.sbin/npppd/npppd/npppd.c index a9fa87e578d..3e81ff8c008 100644 --- a/usr.sbin/npppd/npppd/npppd.c +++ b/usr.sbin/npppd/npppd/npppd.c @@ -1,4 +1,4 @@ -/* $OpenBSD: npppd.c,v 1.18 2012/05/08 13:30:16 yasuoka Exp $ */ +/* $OpenBSD: npppd.c,v 1.19 2012/07/16 18:05:36 markus Exp $ */ /*- * Copyright (c) 2009 Internet Initiative Japan Inc. @@ -29,7 +29,7 @@ * Next pppd(nppd). This file provides a npppd daemon process and operations * for npppd instance. * @author Yasuoka Masahiko - * $Id: npppd.c,v 1.18 2012/05/08 13:30:16 yasuoka Exp $ + * $Id: npppd.c,v 1.19 2012/07/16 18:05:36 markus Exp $ */ #include <sys/cdefs.h> #include "version.h" @@ -82,6 +82,8 @@ __COPYRIGHT( #include "net_utils.h" #include "time_utils.h" +#include "l2tp_local.h" /* XXX sa_cookie */ + #ifdef USE_NPPPD_ARP #include "npppd_arp.h" #endif |