Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F157760454
D31771.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
4 KB
Referenced Files
None
Subscribers
None
D31771.diff
View Options
diff --git a/sys/netipsec/ipsec6.h b/sys/netipsec/ipsec6.h
--- a/sys/netipsec/ipsec6.h
+++ b/sys/netipsec/ipsec6.h
@@ -74,6 +74,7 @@
int ipsec6_capability(struct mbuf *, u_int);
int ipsec6_common_input_cb(struct mbuf *, struct secasvar *, int, int);
int ipsec6_ctlinput(int, struct sockaddr *, void *);
+int ipsec6_check_pmtu(struct mbuf *, struct secpolicy *, int);
int ipsec6_process_packet(struct mbuf *, struct secpolicy *, struct inpcb *);
int ip6_ipsec_filtertunnel(struct mbuf *);
diff --git a/sys/netipsec/ipsec_output.c b/sys/netipsec/ipsec_output.c
--- a/sys/netipsec/ipsec_output.c
+++ b/sys/netipsec/ipsec_output.c
@@ -106,6 +106,7 @@
} while (0)
static int ipsec_encap(struct mbuf **mp, struct secasindex *saidx);
+static size_t ipsec_get_pmtu(struct secasvar *sav);
#ifdef INET
static struct secasvar *
@@ -297,8 +298,6 @@
int
ipsec4_check_pmtu(struct mbuf *m, struct secpolicy *sp, int forwarding)
{
- union sockaddr_union *dst;
- struct in_conninfo inc;
struct secasvar *sav;
struct ip *ip;
size_t hlen, pmtu;
@@ -333,44 +332,15 @@
return (error);
}
- dst = &sav->sah->saidx.dst;
- memset(&inc, 0, sizeof(inc));
- switch (dst->sa.sa_family) {
- case AF_INET:
- inc.inc_faddr = satosin(&dst->sa)->sin_addr;
- break;
-#ifdef INET6
- case AF_INET6:
- inc.inc6_faddr = satosin6(&dst->sa)->sin6_addr;
- inc.inc_flags |= INC_ISIPV6;
- break;
-#endif
- default:
+ pmtu = ipsec_get_pmtu(sav);
+ if (pmtu == 0) {
key_freesav(&sav);
return (0);
}
+ hlen = ipsec_hdrsiz_internal(sp);
key_freesav(&sav);
- pmtu = tcp_hc_getmtu(&inc);
- /* No entry in hostcache. Use link MTU instead. */
- if (pmtu == 0) {
- switch (dst->sa.sa_family) {
- case AF_INET:
- pmtu = tcp_maxmtu(&inc, NULL);
- break;
-#ifdef INET6
- case AF_INET6:
- pmtu = tcp_maxmtu6(&inc, NULL);
- break;
-#endif
- }
- if (pmtu == 0)
- return (0);
-
- tcp_hc_updatemtu(&inc, pmtu);
- }
- hlen = ipsec_hdrsiz_internal(sp);
if (m_length(m, NULL) + hlen > pmtu) {
/*
* If we're forwarding generate ICMP message here,
@@ -720,6 +690,72 @@
return (ipsec6_perform_request(m, sp, inp, 0));
}
+/*
+ * IPv6 implementation is based on IPv4 implementation.
+ */
+int
+ipsec6_check_pmtu(struct mbuf *m, struct secpolicy *sp, int forwarding)
+{
+ struct secasvar *sav;
+ size_t hlen, pmtu;
+ uint32_t idx;
+ int error;
+
+ /*
+ * According to RFC8200 L3 fragmentation is supposed to be done only on
+ * locally generated packets. During L3 forwarding packets that are too
+ * big are always supposed to be dropped, with an ICMPv6 packet being
+ * sent back.
+ */
+ if (!forwarding)
+ return (0);
+
+ idx = sp->tcount - 1;
+ sav = ipsec6_allocsa(m, sp, &idx, &error);
+ if (sav == NULL) {
+ key_freesp(&sp);
+ /*
+ * No matching SA was found and SADB_ACQUIRE message was generated.
+ * Since we have matched a SP to this packet drop it silently.
+ */
+ if (error == 0)
+ error = EINPROGRESS;
+ if (error != EJUSTRETURN)
+ m_freem(m);
+
+ return (error);
+ }
+
+ pmtu = ipsec_get_pmtu(sav);
+ if (pmtu == 0) {
+ key_freesav(&sav);
+ return (0);
+ }
+
+ hlen = ipsec_hdrsiz_internal(sp);
+ key_freesav(&sav);
+
+ if (m_length(m, NULL) + hlen > pmtu) {
+ /*
+ * If we're forwarding generate ICMPv6 message here,
+ * so that it contains pmtu substracted by header size.
+ * Set error to EINPROGRESS, in order for the frame
+ * to be dropped silently.
+ */
+ if (forwarding) {
+ if (pmtu > hlen)
+ icmp6_error(m, ICMP6_PACKET_TOO_BIG, 0, pmtu - hlen);
+ else
+ m_freem(m);
+
+ key_freesp(&sp);
+ return (EINPROGRESS); /* Pretend that we consumed it. */
+ }
+ }
+
+ return (0);
+}
+
static int
ipsec6_common_output(struct mbuf *m, struct inpcb *inp, int forwarding)
{
@@ -766,6 +802,15 @@
}
#endif
}
+
+ error = ipsec6_check_pmtu(m, sp, forwarding);
+ if (error != 0) {
+ if (error == EJUSTRETURN)
+ return (0);
+
+ return (error);
+ }
+
/* NB: callee frees mbuf and releases reference to SP */
error = ipsec6_process_packet(m, sp, inp);
if (error == EJUSTRETURN) {
@@ -1001,6 +1046,59 @@
return (n);
}
+static size_t
+ipsec_get_pmtu(struct secasvar *sav)
+{
+ union sockaddr_union *dst;
+ struct in_conninfo inc;
+ size_t pmtu;
+
+ dst = &sav->sah->saidx.dst;
+ memset(&inc, 0, sizeof(inc));
+
+ switch (dst->sa.sa_family) {
+#ifdef INET
+ case AF_INET:
+ inc.inc_faddr = satosin(&dst->sa)->sin_addr;
+ break;
+#endif
+#ifdef INET6
+ case AF_INET6:
+ inc.inc6_faddr = satosin6(&dst->sa)->sin6_addr;
+ inc.inc_flags |= INC_ISIPV6;
+ break;
+#endif
+ default:
+ return (0);
+ }
+
+ pmtu = tcp_hc_getmtu(&inc);
+ if (pmtu != 0)
+ return (pmtu);
+
+ /* No entry in hostcache. Assume that PMTU is equal to link's MTU */
+ switch (dst->sa.sa_family) {
+#ifdef INET
+ case AF_INET:
+ pmtu = tcp_maxmtu(&inc, NULL);
+ break;
+#endif
+#ifdef INET6
+ case AF_INET6:
+ pmtu = tcp_maxmtu6(&inc, NULL);
+ break;
+#endif
+ default:
+ return (0);
+ }
+ if (pmtu == 0)
+ return (0);
+
+ tcp_hc_updatemtu(&inc, pmtu);
+
+ return (pmtu);
+}
+
static int
ipsec_encap(struct mbuf **mp, struct secasindex *saidx)
{
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Mon, May 25, 10:19 PM (14 h, 38 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
33517377
Default Alt Text
D31771.diff (4 KB)
Attached To
Mode
D31771: ipsec: Add support for PMTUD for IPv6 tunnels
Attached
Detach File
Event Timeline
Log In to Comment