diff options
author | 2006-01-13 10:11:23 +0000 | |
---|---|---|
committer | 2006-01-13 10:11:23 +0000 | |
commit | f421c88b261c44f11c1002a19ad7af228c1a6115 (patch) | |
tree | 4f015096b5bd68482cd26b0a6d03a11b094fc9d7 | |
parent | +asms (diff) | |
download | wireguard-openbsd-f421c88b261c44f11c1002a19ad7af228c1a6115.tar.xz wireguard-openbsd-f421c88b261c44f11c1002a19ad7af228c1a6115.zip |
Path MTU discovery for NAT-T.
OK markus@, "looks good" hshoexer@
-rw-r--r-- | sys/netinet/ip_ipsp.c | 4 | ||||
-rw-r--r-- | sys/netinet/ip_ipsp.h | 3 | ||||
-rw-r--r-- | sys/netinet/ipsec_input.c | 56 | ||||
-rw-r--r-- | sys/netinet/udp_usrreq.c | 13 |
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 |