summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authormpf <mpf@openbsd.org>2006-01-13 10:11:23 +0000
committermpf <mpf@openbsd.org>2006-01-13 10:11:23 +0000
commitf421c88b261c44f11c1002a19ad7af228c1a6115 (patch)
tree4f015096b5bd68482cd26b0a6d03a11b094fc9d7 /sys
parent+asms (diff)
downloadwireguard-openbsd-f421c88b261c44f11c1002a19ad7af228c1a6115.tar.xz
wireguard-openbsd-f421c88b261c44f11c1002a19ad7af228c1a6115.zip
Path MTU discovery for NAT-T.
OK markus@, "looks good" hshoexer@
Diffstat (limited to 'sys')
-rw-r--r--sys/netinet/ip_ipsp.c4
-rw-r--r--sys/netinet/ip_ipsp.h3
-rw-r--r--sys/netinet/ipsec_input.c56
-rw-r--r--sys/netinet/udp_usrreq.c13
4 files changed, 69 insertions, 7 deletions
diff --git a/sys/netinet/ip_ipsp.c b/sys/netinet/ip_ipsp.c
index ac04c52ce6f..39611a04eed 100644
--- a/sys/netinet/ip_ipsp.c
+++ b/sys/netinet/ip_ipsp.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ip_ipsp.c,v 1.164 2005/11/24 12:08:16 pedro Exp $ */
+/* $OpenBSD: ip_ipsp.c,v 1.165 2006/01/13 10:11:23 mpf Exp $ */
/*
* The authors of this code are John Ioannidis (ji@tla.org),
* Angelos D. Keromytis (kermit@csd.uch.gr),
@@ -293,7 +293,6 @@ gettdb(u_int32_t spi, union sockaddr_union *dst, u_int8_t proto)
return tdbp;
}
-#ifdef TCP_SIGNATURE
/*
* Same as gettdb() but compare SRC as well, so we
* use the tdbsrc[] hash table. Setting spi to 0
@@ -339,7 +338,6 @@ gettdbbysrcdst(u_int32_t spi, union sockaddr_union *src,
return (tdbp);
}
-#endif
/*
* Check that credentials and IDs match. Return true if so. The t*
diff --git a/sys/netinet/ip_ipsp.h b/sys/netinet/ip_ipsp.h
index 9772a5bd9de..2b0f8bb069a 100644
--- a/sys/netinet/ip_ipsp.h
+++ b/sys/netinet/ip_ipsp.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: ip_ipsp.h,v 1.131 2005/11/24 12:08:16 pedro Exp $ */
+/* $OpenBSD: ip_ipsp.h,v 1.132 2006/01/13 10:11:23 mpf Exp $ */
/*
* The authors of this code are John Ioannidis (ji@tla.org),
* Angelos D. Keromytis (kermit@csd.uch.gr),
@@ -579,6 +579,7 @@ extern int ah_massage_headers(struct mbuf **, int, int, int, int);
extern void ah4_input(struct mbuf *, ...);
extern int ah4_input_cb(struct mbuf *, ...);
extern void *ah4_ctlinput(int, struct sockaddr *, void *);
+extern void *udpencap_ctlinput(int, struct sockaddr *, void *);
#endif /* INET */
#ifdef INET6
diff --git a/sys/netinet/ipsec_input.c b/sys/netinet/ipsec_input.c
index 17e23e856e0..aaddbf4a778 100644
--- a/sys/netinet/ipsec_input.c
+++ b/sys/netinet/ipsec_input.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ipsec_input.c,v 1.76 2005/07/31 03:52:19 pascoe Exp $ */
+/* $OpenBSD: ipsec_input.c,v 1.77 2006/01/13 10:11:23 mpf Exp $ */
/*
* The authors of this code are John Ioannidis (ji@tla.org),
* Angelos D. Keromytis (kermit@csd.uch.gr) and
@@ -859,6 +859,60 @@ ipsec_common_ctlinput(int cmd, struct sockaddr *sa, void *v, int proto)
}
void *
+udpencap_ctlinput(int cmd, struct sockaddr *sa, void *v)
+{
+ struct ip *ip = v;
+ struct tdb *tdbp;
+ struct icmp *icp;
+ u_int32_t mtu;
+ ssize_t adjust;
+ struct sockaddr_in dst, src;
+ union sockaddr_union *su_dst, *su_src;
+ int s;
+
+ icp = (struct icmp *)((caddr_t) ip - offsetof(struct icmp, icmp_ip));
+ mtu = ntohs(icp->icmp_nextmtu);
+
+ /*
+ * Ignore the packet, if we do not receive a MTU
+ * or the MTU is too small to be acceptable.
+ */
+ if (mtu < 296)
+ return (NULL);
+
+ bzero(&dst, sizeof(dst));
+ dst.sin_family = AF_INET;
+ dst.sin_len = sizeof(struct sockaddr_in);
+ dst.sin_addr.s_addr = ip->ip_dst.s_addr;
+ su_dst = (union sockaddr_union *)&dst;
+ bzero(&src, sizeof(src));
+ src.sin_family = AF_INET;
+ src.sin_len = sizeof(struct sockaddr_in);
+ src.sin_addr.s_addr = ip->ip_src.s_addr;
+ su_src = (union sockaddr_union *)&src;
+
+ s = spltdb();
+ tdbp = gettdbbysrcdst(0, su_src, su_dst, IPPROTO_ESP);
+
+ for (; tdbp != NULL; tdbp = tdbp->tdb_snext) {
+ if (tdbp->tdb_sproto == IPPROTO_ESP &&
+ ((tdbp->tdb_flags & (TDBF_INVALID|TDBF_UDPENCAP))
+ == TDBF_UDPENCAP) &&
+ !bcmp(&tdbp->tdb_dst, &dst, SA_LEN(&su_dst->sa)) &&
+ !bcmp(&tdbp->tdb_src, &src, SA_LEN(&su_src->sa))) {
+ if ((adjust = ipsec_hdrsz(tdbp)) != -1) {
+ /* Store adjusted MTU in tdb */
+ tdbp->tdb_mtu = mtu - adjust;
+ tdbp->tdb_mtutimeout = time_second +
+ ip_mtudisc_timeout;
+ }
+ }
+ }
+ splx(s);
+ return (NULL);
+}
+
+void *
esp4_ctlinput(int cmd, struct sockaddr *sa, void *v)
{
if (sa->sa_family != AF_INET ||
diff --git a/sys/netinet/udp_usrreq.c b/sys/netinet/udp_usrreq.c
index 46ff8c86d36..f92bc2cd69e 100644
--- a/sys/netinet/udp_usrreq.c
+++ b/sys/netinet/udp_usrreq.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: udp_usrreq.c,v 1.105 2005/10/17 08:43:34 henning Exp $ */
+/* $OpenBSD: udp_usrreq.c,v 1.106 2006/01/13 10:11:23 mpf Exp $ */
/* $NetBSD: udp_usrreq.c,v 1.28 1996/03/16 23:54:03 christos Exp $ */
/*
@@ -899,13 +899,22 @@ udp_ctlinput(cmd, sa, v)
return NULL;
if (ip) {
uhp = (struct udphdr *)((caddr_t)ip + (ip->ip_hl << 2));
+
+#ifdef IPSEC
+ /* PMTU discovery for udpencap */
+ if (cmd == PRC_MSGSIZE && ip_mtudisc && udpencap_enable &&
+ udpencap_port && uhp->uh_sport == htons(udpencap_port)) {
+ udpencap_ctlinput(cmd, sa, v);
+ return (NULL);
+ }
+#endif
inp = in_pcbhashlookup(&udbtable,
ip->ip_dst, uhp->uh_dport, ip->ip_src, uhp->uh_sport);
if (inp && inp->inp_socket != NULL)
notify(inp, errno);
} else
in_pcbnotifyall(&udbtable, sa, errno, notify);
- return NULL;
+ return (NULL);
}
int