pf: use inet_ntoa_r() instead of inet_ntoa(); maybe fix IPv6 OS fingerprinting

inet_ntoa() cannot be used safely in a multithreaded environment
because it uses a static local buffer. Instead, use inet_ntoa_r()
with a buffer on the caller's stack.

This code had an INET6 conditional before this commit, but opt_inet6.h
was not included, so INET6 was never defined.  Apparently, pf's OS
fingerprinting hasn't worked with IPv6 for quite some time.
This commit might fix it, but I didn't test that.

Reviewed by:	gnn, kp
MFC after:	2 weeks
Relnotes:	yes (if I/someone can test pf OS fingerprinting with IPv6)
Sponsored by:	Dell EMC
Differential Revision:	https://reviews.freebsd.org/D9625
This commit is contained in:
Eric van Gyzen 2017-02-16 20:44:44 +00:00
parent 10723054ce
commit 643faabe0d
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=313820

View File

@ -19,6 +19,8 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include "opt_inet6.h"
#include <sys/param.h>
#include <sys/kernel.h>
#include <sys/lock.h>
@ -34,7 +36,9 @@ __FBSDID("$FreeBSD$");
#include <net/vnet.h>
#include <net/pfvar.h>
#ifdef INET6
#include <netinet/ip6.h>
#endif
static MALLOC_DEFINE(M_PFOSFP, "pf_osfp", "pf(4) operating system fingerprints");
#define DPFPRINTF(format, x...) \
@ -94,7 +98,11 @@ pf_osfp_fingerprint_hdr(const struct ip *ip, const struct ip6_hdr *ip6, const st
struct pf_os_fingerprint fp, *fpresult;
int cnt, optlen = 0;
const u_int8_t *optp;
char srcname[128];
#ifdef INET6
char srcname[INET6_ADDRSTRLEN];
#else
char srcname[INET_ADDRSTRLEN];
#endif
if ((tcp->th_flags & (TH_SYN|TH_ACK)) != TH_SYN)
return (NULL);
@ -110,7 +118,7 @@ pf_osfp_fingerprint_hdr(const struct ip *ip, const struct ip6_hdr *ip6, const st
fp.fp_ttl = ip->ip_ttl;
if (ip->ip_off & htons(IP_DF))
fp.fp_flags |= PF_OSFP_DF;
strlcpy(srcname, inet_ntoa(ip->ip_src), sizeof(srcname));
inet_ntoa_r(ip->ip_src, srcname);
}
#ifdef INET6
else if (ip6) {
@ -119,8 +127,7 @@ pf_osfp_fingerprint_hdr(const struct ip *ip, const struct ip6_hdr *ip6, const st
fp.fp_ttl = ip6->ip6_hlim;
fp.fp_flags |= PF_OSFP_DF;
fp.fp_flags |= PF_OSFP_INET6;
strlcpy(srcname, ip6_sprintf((struct in6_addr *)&ip6->ip6_src),
sizeof(srcname));
ip6_sprintf(srcname, (const struct in6_addr *)&ip6->ip6_src);
}
#endif
else