summaryrefslogtreecommitdiffstats
path: root/sys/netinet6/ip6_output.c
diff options
context:
space:
mode:
authorume <ume@FreeBSD.org>2004-02-08 18:22:27 +0000
committerume <ume@FreeBSD.org>2004-02-08 18:22:27 +0000
commit4975c09f545ec8737801eff13736328e4cbd2704 (patch)
tree221c4217d9bbc70f805cc868209a53e9fc80b9c4 /sys/netinet6/ip6_output.c
parentebd7964f02a85da4d91f43c4d44f9a94fbdecf49 (diff)
downloadFreeBSD-src-4975c09f545ec8737801eff13736328e4cbd2704.zip
FreeBSD-src-4975c09f545ec8737801eff13736328e4cbd2704.tar.gz
- obey ip6po_minmtu.
- notify a proper path MTU to applications. Obtained from: KAME
Diffstat (limited to 'sys/netinet6/ip6_output.c')
-rw-r--r--sys/netinet6/ip6_output.c33
1 files changed, 30 insertions, 3 deletions
diff --git a/sys/netinet6/ip6_output.c b/sys/netinet6/ip6_output.c
index fc69de1..1b30fa7 100644
--- a/sys/netinet6/ip6_output.c
+++ b/sys/netinet6/ip6_output.c
@@ -827,10 +827,28 @@ skip_ipsec2:;
goto bad;
/*
- * advanced API (IPV6_USE_MIN_MTU) overrides mtu setting
+ * The caller of this function may specify to use the minimum MTU
+ * in some cases.
+ * An advanced API option (IPV6_USE_MIN_MTU) can also override MTU
+ * setting. The logic is a bit complicated; by default, unicast
+ * packets will follow path MTU while multicast packets will be sent at
+ * the minimum MTU. If IP6PO_MINMTU_ALL is specified, all packets
+ * including unicast ones will be sent at the minimum MTU. Multicast
+ * packets will always be sent at the minimum MTU unless
+ * IP6PO_MINMTU_DISABLE is explicitly specified.
+ * See RFC 3542 for more details.
*/
- if ((flags & IPV6_MINMTU) != 0 && mtu > IPV6_MMTU)
- mtu = IPV6_MMTU;
+ if (mtu > IPV6_MMTU) {
+ if ((flags & IPV6_MINMTU))
+ mtu = IPV6_MMTU;
+ else if (opt && opt->ip6po_minmtu == IP6PO_MINMTU_ALL)
+ mtu = IPV6_MMTU;
+ else if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst) &&
+ (opt == NULL ||
+ opt->ip6po_minmtu != IP6PO_MINMTU_DISABLE)) {
+ mtu = IPV6_MMTU;
+ }
+ }
/* Fake scoped addresses */
if ((ifp->if_flags & IFF_LOOPBACK) != 0) {
@@ -1032,6 +1050,8 @@ skip_ipsec2:;
u_int32_t id = htonl(ip6_id++);
#endif
u_char nextproto;
+ struct ip6ctlparam ip6cp;
+ u_int32_t mtu32;
/*
* Too large for the destination or interface;
@@ -1042,6 +1062,13 @@ skip_ipsec2:;
if (mtu > IPV6_MAXPACKET)
mtu = IPV6_MAXPACKET;
+ /* Notify a proper path MTU to applications. */
+ mtu32 = (u_int32_t)mtu;
+ bzero(&ip6cp, sizeof(ip6cp));
+ ip6cp.ip6c_cmdarg = (void *)&mtu32;
+ pfctlinput2(PRC_MSGSIZE, (struct sockaddr *)&ro_pmtu->ro_dst,
+ (void *)&ip6cp);
+
len = (mtu - hlen - sizeof(struct ip6_frag)) & ~7;
if (len < 8) {
error = EMSGSIZE;
OpenPOWER on IntegriCloud