Index: sys/netinet/in_pcb.h =================================================================== --- sys/netinet/in_pcb.h +++ sys/netinet/in_pcb.h @@ -122,8 +122,9 @@ * Flags for inc_flags. */ #define INC_ISIPV6 0x01 +#define INC_IPV6MINMTU 0x02 -#define inc_isipv6 inc_flags /* temp compatibility */ +#define inc_isipv6 (inc_flags & INC_ISIPV6) /* temp compatibility */ #define inc_fport inc_ie.ie_fport #define inc_lport inc_ie.ie_lport #define inc_faddr inc_ie.ie_faddr Index: sys/netinet/tcp_input.c =================================================================== --- sys/netinet/tcp_input.c +++ sys/netinet/tcp_input.c @@ -1051,6 +1051,8 @@ #ifdef INET6 if (isipv6) { inc.inc_flags |= INC_ISIPV6; + if (inp->inp_inc.inc_flags & INC_IPV6MINMTU) + inc.inc_flags |= INC_IPV6MINMTU; inc.inc6_faddr = ip6->ip6_src; inc.inc6_laddr = ip6->ip6_dst; } else Index: sys/netinet/tcp_subr.c =================================================================== --- sys/netinet/tcp_subr.c +++ sys/netinet/tcp_subr.c @@ -2850,6 +2850,9 @@ KASSERT(inc != NULL, ("tcp_maxmtu6 with NULL in_conninfo pointer")); + if (inc->inc_flags & INC_IPV6MINMTU) + return (IPV6_MMTU); + if (!IN6_IS_ADDR_UNSPECIFIED(&inc->inc6_faddr)) { in6_splitscope(&inc->inc6_faddr, &dst6, &scopeid); if (fib6_lookup_nh_ext(inc->inc_fibnum, &dst6, scopeid, 0, Index: sys/netinet/tcp_usrreq.c =================================================================== --- sys/netinet/tcp_usrreq.c +++ sys/netinet/tcp_usrreq.c @@ -1580,6 +1580,33 @@ if (inp->inp_vflag & INP_IPV6PROTO) { INP_WUNLOCK(inp); error = ip6_ctloutput(so, sopt); + if ((error == 0) && + (sopt->sopt_dir == SOPT_SET) && + (sopt->sopt_level == IPPROTO_IPV6) && + (sopt->sopt_name == IPV6_USE_MIN_MTU)) { + INP_WLOCK(inp); + if ((inp->inp_flags & + (INP_TIMEWAIT | INP_DROPPED))) { + INP_WUNLOCK(inp); + return (ECONNRESET); + } + inp->inp_inc.inc_flags |= INC_IPV6MINMTU; + tp = intotcpcb(inp); + if ((tp->t_state >= TCPS_SYN_SENT) && + (inp->inp_inc.inc_flags & INC_ISIPV6)) { + struct ip6_pktopts *opt; + + opt = inp->in6p_outputopts; + if ((opt != NULL) && + (opt->ip6po_minmtu == + IP6PO_MINMTU_ALL)) { + if (tp->t_maxseg > TCP6_MSS) { + tp->t_maxseg = TCP6_MSS; + } + } + } + INP_WUNLOCK(inp); + } } #endif /* INET6 */ #if defined(INET6) && defined(INET)