Our IPSec stack rejects UDP-encapsulated traffic using a non encapsulating SA, but not the other way around. This diff adds the missing check and the corresponding stat counter.
Ok ? Index: sys/netinet/ip_esp.h =================================================================== RCS file: /cvs/src/sys/netinet/ip_esp.h,v retrieving revision 1.42 diff -u -p -r1.42 ip_esp.h --- sys/netinet/ip_esp.h 10 Jan 2010 12:43:07 -0000 1.42 +++ sys/netinet/ip_esp.h 1 Sep 2016 08:24:15 -0000 @@ -62,6 +62,7 @@ struct espstat u_int32_t esps_udpencin; /* Input ESP-in-UDP packets */ u_int32_t esps_udpencout; /* Output ESP-in-UDP packets */ u_int32_t esps_udpinval; /* Invalid input ESP-in-UDP packets */ + u_int32_t esps_udpneeded; /* Trying to use a ESP-in-UDP TDB */ }; /* Index: sys/netinet/ipsec_input.c =================================================================== RCS file: /cvs/src/sys/netinet/ipsec_input.c,v retrieving revision 1.135 diff -u -p -r1.135 ipsec_input.c --- sys/netinet/ipsec_input.c 10 Sep 2015 17:52:05 -0000 1.135 +++ sys/netinet/ipsec_input.c 1 Sep 2016 08:24:16 -0000 @@ -262,6 +262,16 @@ ipsec_common_input(struct mbuf *m, int s return EINVAL; } + if (!udpencap && (tdbp->tdb_flags & TDBF_UDPENCAP)) { + splx(s); + DPRINTF(("ipsec_common_input(): attempted to use udpencap " + "SA %s/%08x/%u\n", ipsp_address(&dst_address, buf, + sizeof(buf)), ntohl(spi), tdbp->tdb_sproto)); + m_freem(m); + espstat.esps_udpneeded++; + return EINVAL; + } + if (tdbp->tdb_xform == NULL) { splx(s); DPRINTF(("ipsec_common_input(): attempted to use uninitialized " Index: usr.bin/netstat/inet.c =================================================================== RCS file: /cvs/src/usr.bin/netstat/inet.c,v retrieving revision 1.150 diff -u -p -r1.150 inet.c --- usr.bin/netstat/inet.c 27 Aug 2016 04:13:43 -0000 1.150 +++ usr.bin/netstat/inet.c 1 Sep 2016 08:24:16 -0000 @@ -1073,6 +1073,7 @@ esp_stats(char *name) p(esps_udpencin, "\t%u input UDP encapsulated ESP packet%s\n"); p(esps_udpencout, "\t%u output UDP encapsulated ESP packet%s\n"); p(esps_udpinval, "\t%u UDP packet%s for non-encapsulating TDB received\n"); + p(esps_udpneeded, "\t%u raw ESP packet%s for encapsulating TDB received\n"); p(esps_ibytes, "\t%llu input byte%s\n"); p(esps_obytes, "\t%llu output byte%s\n");