summaryrefslogtreecommitdiffstats
path: root/sys/netinet/ipsec_input.c
diff options
context:
space:
mode:
authorprovos <provos@openbsd.org>2001-06-24 18:22:47 +0000
committerprovos <provos@openbsd.org>2001-06-24 18:22:47 +0000
commit6d7c3229ae5671e2ea9170f95fc99ae4a8e80f7c (patch)
treef968a59d029b09752c8295e7b27298933a1ce917 /sys/netinet/ipsec_input.c
parentgrammar (diff)
downloadwireguard-openbsd-6d7c3229ae5671e2ea9170f95fc99ae4a8e80f7c.tar.xz
wireguard-openbsd-6d7c3229ae5671e2ea9170f95fc99ae4a8e80f7c.zip
path mtu discovery for ipsec. on receiving a need fragment icmp match
against active tdb and store the ipsec header size corrected mtu
Diffstat (limited to 'sys/netinet/ipsec_input.c')
-rw-r--r--sys/netinet/ipsec_input.c90
1 files changed, 89 insertions, 1 deletions
diff --git a/sys/netinet/ipsec_input.c b/sys/netinet/ipsec_input.c
index c570ddf0e33..451f1a7c5e3 100644
--- a/sys/netinet/ipsec_input.c
+++ b/sys/netinet/ipsec_input.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ipsec_input.c,v 1.45 2001/06/23 16:15:56 fgsch Exp $ */
+/* $OpenBSD: ipsec_input.c,v 1.46 2001/06/24 18:22:47 provos Exp $ */
/*
* The authors of this code are John Ioannidis (ji@tla.org),
@@ -37,6 +37,7 @@
#include <sys/param.h>
#include <sys/systm.h>
+#include <sys/protosw.h>
#include <sys/mbuf.h>
#include <sys/socket.h>
#include <sys/sysctl.h>
@@ -49,7 +50,9 @@
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>
+#include <netinet/ip_var.h>
#include <netinet/in_var.h>
+#include <netinet/ip_icmp.h>
#include <netinet/tcp.h>
#include <netinet/udp.h>
@@ -71,6 +74,7 @@
#include "bpfilter.h"
int ipsec_common_input(struct mbuf *, int, int, int, int);
+void *ipsec_common_ctlinput(int, struct sockaddr *, void *, int);
#ifdef ENCDEBUG
#define DPRINTF(x) if (encdebug) printf x
@@ -643,6 +647,17 @@ ah4_input_cb(struct mbuf *m, ...)
return 0;
}
+
+void *
+ah4_ctlinput(int cmd, struct sockaddr *sa, void *v)
+{
+ if (sa->sa_family != AF_INET ||
+ sa->sa_len != sizeof(struct sockaddr_in))
+ return (NULL);
+
+ return (ipsec_common_ctlinput(cmd, sa, v, IPPROTO_AH));
+}
+
/* IPv4 ESP wrapper */
void
esp4_input(struct mbuf *m, ...)
@@ -686,6 +701,79 @@ esp4_input_cb(struct mbuf *m, ...)
return 0;
}
+
+void *
+ipsec_common_ctlinput(int cmd, struct sockaddr *sa, void *v, int proto)
+{
+ extern u_int ip_mtudisc_timeout;
+ struct ip *ip = v;
+ int s;
+
+ if (cmd == PRC_MSGSIZE && ip && ip->ip_v == 4) {
+ struct tdb *tdbp;
+ struct sockaddr_in dst;
+ struct icmp *icp;
+ int hlen = ip->ip_hl << 2;
+ u_int32_t spi, mtu;
+ ssize_t adjust;
+
+ /* Find the right MTU */
+ 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(struct sockaddr_in));
+ dst.sin_family = AF_INET;
+ dst.sin_len = sizeof(struct sockaddr_in);
+ dst.sin_addr.s_addr = ip->ip_dst.s_addr;
+
+ bcopy((caddr_t)ip + hlen, &spi, sizeof(u_int32_t));
+
+ s = spltdb();
+ tdbp = gettdb(spi, (union sockaddr_union *)&dst, proto);
+ if (tdbp == NULL || tdbp->tdb_flags & TDBF_INVALID) {
+ splx(s);
+ return (NULL);
+ }
+
+ /* Walk the chain backswards to the first tdb */
+ for (; tdbp; tdbp = tdbp->tdb_inext) {
+ if (tdbp->tdb_flags & TDBF_INVALID ||
+ (adjust = ipsec_hdrsz(tdbp)) == -1) {
+ splx(s);
+ return (NULL);
+ }
+
+ mtu -= adjust;
+
+ /* Store adjusted MTU in tdb */
+ tdbp->tdb_mtu = mtu;
+ tdbp->tdb_mtutimeout = time.tv_sec +
+ ip_mtudisc_timeout;
+ }
+ splx(s);
+
+ return (NULL);
+ }
+
+ return (NULL);
+}
+
+void *
+esp4_ctlinput(int cmd, struct sockaddr *sa, void *v)
+{
+ if (sa->sa_family != AF_INET ||
+ sa->sa_len != sizeof(struct sockaddr_in))
+ return (NULL);
+
+ return (ipsec_common_ctlinput(cmd, sa, v, IPPROTO_ESP));
+}
#endif /* INET */
#ifdef INET6