summaryrefslogtreecommitdiff
path: root/sys/net
diff options
context:
space:
mode:
authorMarkus Friedl <markus@cvs.openbsd.org>2006-01-23 22:46:58 +0000
committerMarkus Friedl <markus@cvs.openbsd.org>2006-01-23 22:46:58 +0000
commit97c8ab8358e56736041ba987501756a20011f682 (patch)
tree6a5efbe11f90ad0419e82228c2b1a0c4cb7475d9 /sys/net
parentcb1bc43bd2af03ffcb07e17d12d8970609ee73c5 (diff)
support PMTU-Discovery for link2 ipsec bridges; ok claudio
Diffstat (limited to 'sys/net')
-rw-r--r--sys/net/if_bridge.c37
1 files changed, 27 insertions, 10 deletions
diff --git a/sys/net/if_bridge.c b/sys/net/if_bridge.c
index 7706ddce813..0af05d429a8 100644
--- a/sys/net/if_bridge.c
+++ b/sys/net/if_bridge.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_bridge.c,v 1.148 2006/01/05 03:28:34 deraadt Exp $ */
+/* $OpenBSD: if_bridge.c,v 1.149 2006/01/23 22:46:57 markus Exp $ */
/*
* Copyright (c) 1999, 2000 Jason L. Wright (jason@thought.net)
@@ -158,10 +158,13 @@ void bridge_fragment(struct bridge_softc *, struct ifnet *,
struct ether_header *, struct mbuf *);
#ifdef INET
void bridge_send_icmp_err(struct bridge_softc *, struct ifnet *,
- struct ether_header *, struct mbuf *, int, struct llc *, int, int);
+ struct ether_header *, struct mbuf *, int, struct llc *, int, int, int);
#endif
#ifdef IPSEC
-int bridge_ipsec(int, int, int, struct mbuf *);
+int bridge_ipsec(struct bridge_softc *, struct ifnet *,
+ struct ether_header *, int, struct llc *,
+ int, int, int, struct mbuf *);
+#define ICMP_DEFLEN MHLEN
#endif
int bridge_clone_create(struct if_clone *, int);
int bridge_clone_destroy(struct ifnet *ifp);
@@ -2122,7 +2125,9 @@ bridge_flushrule(struct bridge_iflist *bif)
#ifdef IPSEC
int
-bridge_ipsec(int dir, int af, int hlen, struct mbuf *m)
+bridge_ipsec(struct bridge_softc *sc, struct ifnet *ifp,
+ struct ether_header *eh, int hassnap, struct llc *llc,
+ int dir, int af, int hlen, struct mbuf *m)
{
union sockaddr_union dst;
struct timeval tv;
@@ -2292,7 +2297,17 @@ bridge_ipsec(int dir, int af, int hlen, struct mbuf *m)
if (m == NULL)
return (1);
#endif /* NPF */
- error = ipsp_process_packet(m, tdb, af, 0);
+
+ ip = mtod(m, struct ip *);
+ if ((af == AF_INET) &&
+ ip_mtudisc && (ip->ip_off & htons(IP_DF)) &&
+ tdb->tdb_mtu && ntohs(ip->ip_len) > tdb->tdb_mtu &&
+ tdb->tdb_mtutimeout > time_second)
+ bridge_send_icmp_err(sc, ifp, eh, m,
+ hassnap, llc, tdb->tdb_mtu,
+ ICMP_UNREACH, ICMP_UNREACH_NEEDFRAG);
+ else
+ error = ipsp_process_packet(m, tdb, af, 0);
return (1);
} else
return (0);
@@ -2401,7 +2416,8 @@ bridge_filter(struct bridge_softc *sc, int dir, struct ifnet *ifp,
#ifdef IPSEC
if ((sc->sc_if.if_flags & IFF_LINK2) == IFF_LINK2 &&
- bridge_ipsec(dir, AF_INET, hlen, m))
+ bridge_ipsec(sc, ifp, eh, hassnap, &llc,
+ dir, AF_INET, hlen, m))
return (NULL);
#endif /* IPSEC */
@@ -2449,7 +2465,8 @@ bridge_filter(struct bridge_softc *sc, int dir, struct ifnet *ifp,
hlen = sizeof(struct ip6_hdr);
if ((sc->sc_if.if_flags & IFF_LINK2) == IFF_LINK2 &&
- bridge_ipsec(dir, AF_INET6, hlen, m))
+ bridge_ipsec(sc, ifp, eh, hassnap, &llc,
+ dir, AF_INET6, hlen, m))
return (NULL);
#endif /* IPSEC */
@@ -2551,7 +2568,7 @@ bridge_fragment(struct bridge_softc *sc, struct ifnet *ifp,
/* Respect IP_DF, return a ICMP_UNREACH_NEEDFRAG. */
if (ip->ip_off & htons(IP_DF)) {
bridge_send_icmp_err(sc, ifp, eh, m, hassnap, &llc,
- ICMP_UNREACH, ICMP_UNREACH_NEEDFRAG);
+ ifp->if_mtu, ICMP_UNREACH, ICMP_UNREACH_NEEDFRAG);
return;
}
@@ -2630,7 +2647,7 @@ bridge_ifenqueue(struct bridge_softc *sc, struct ifnet *ifp, struct mbuf *m)
void
bridge_send_icmp_err(struct bridge_softc *sc, struct ifnet *ifp,
struct ether_header *eh, struct mbuf *n, int hassnap, struct llc *llc,
- int type, int code)
+ int mtu, int type, int code)
{
struct ip *ip;
struct icmp *icp;
@@ -2644,7 +2661,7 @@ bridge_send_icmp_err(struct bridge_softc *sc, struct ifnet *ifp,
m_freem(n);
return;
}
- m = icmp_do_error(n, type, code, 0, ifp->if_mtu);
+ m = icmp_do_error(n, type, code, 0, mtu);
if (m == NULL) {
m_freem(n2);
return;