diff options
author | ume <ume@FreeBSD.org> | 2004-02-08 18:22:27 +0000 |
---|---|---|
committer | ume <ume@FreeBSD.org> | 2004-02-08 18:22:27 +0000 |
commit | 4975c09f545ec8737801eff13736328e4cbd2704 (patch) | |
tree | 221c4217d9bbc70f805cc868209a53e9fc80b9c4 /sys/netinet6 | |
parent | ebd7964f02a85da4d91f43c4d44f9a94fbdecf49 (diff) | |
download | FreeBSD-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')
-rw-r--r-- | sys/netinet6/ip6_output.c | 33 |
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; |