diff --git a/openvpn/client/cliproto.hpp b/openvpn/client/cliproto.hpp index 428f43e4..2fa39c91 100644 --- a/openvpn/client/cliproto.hpp +++ b/openvpn/client/cliproto.hpp @@ -443,12 +443,21 @@ class Session : ProtoContextCallbackInterface, if (buf.size()) { const ProtoContext::ProtoConfig &c = proto_context.conf(); + + bool df = true; + + if (IPCommon::version(buf[0]) == IPCommon::IPv4 && buf.size() >= sizeof(struct IPv4Header)) + { + df = IPv4Header::is_df_set(buf.c_data()); + } + // when calculating mss, we take IPv4 and TCP headers into account // here we need to add it back since we check the whole IP packet size, not just TCP payload constexpr size_t MinTcpHeader = 20; constexpr size_t MinIpHeader = 20; size_t mss_no_tcp_ip_encap = c.mss_fix + (MinTcpHeader + MinIpHeader); - if (c.mss_fix > 0 && buf.size() > mss_no_tcp_ip_encap) + + if (df && c.mss_fix > 0 && buf.size() > mss_no_tcp_ip_encap) { Ptb::generate_icmp_ptb(buf, clamp_to_typerange(mss_no_tcp_ip_encap)); tun->tun_send(buf); diff --git a/openvpn/ip/ip4.hpp b/openvpn/ip/ip4.hpp index d77ef000..e8f64cf2 100644 --- a/openvpn/ip/ip4.hpp +++ b/openvpn/ip/ip4.hpp @@ -43,6 +43,12 @@ struct IPv4Header return static_cast(((len >> 2) & 0x0F) | (version & 0x0F) << 4); } + static bool is_df_set(const unsigned char *data) + { + auto *hdr = reinterpret_cast(data); + return ntohs(hdr->frag_off) & IPv4Header::DF; + } + std::uint8_t version_len; std::uint8_t tos; @@ -52,6 +58,7 @@ struct IPv4Header enum { OFFMASK = 0x1fff, + DF = 0x4000, }; std::uint16_t frag_off;