summaryrefslogtreecommitdiffstats
path: root/sys/contrib/pf/net/pf_osfp.c
diff options
context:
space:
mode:
authorglebius <glebius@FreeBSD.org>2012-09-08 06:41:54 +0000
committerglebius <glebius@FreeBSD.org>2012-09-08 06:41:54 +0000
commit5190d38ee392f405f48ee4edd4912dbe48d19953 (patch)
tree7b5b7e7d4dce516742188586df4e95db4183a7da /sys/contrib/pf/net/pf_osfp.c
parentfb40c86f7f3666ca5e299037097af8acad817a85 (diff)
downloadFreeBSD-src-5190d38ee392f405f48ee4edd4912dbe48d19953.zip
FreeBSD-src-5190d38ee392f405f48ee4edd4912dbe48d19953.tar.gz
Merge the projects/pf/head branch, that was worked on for last six months,
into head. The most significant achievements in the new code: o Fine grained locking, thus much better performance. o Fixes to many problems in pf, that were specific to FreeBSD port. New code doesn't have that many ifdefs and much less OpenBSDisms, thus is more attractive to our developers. Those interested in details, can browse through SVN log of the projects/pf/head branch. And for reference, here is exact list of revisions merged: r232043, r232044, r232062, r232148, r232149, r232150, r232298, r232330, r232332, r232340, r232386, r232390, r232391, r232605, r232655, r232656, r232661, r232662, r232663, r232664, r232673, r232691, r233309, r233782, r233829, r233830, r233834, r233835, r233836, r233865, r233866, r233868, r233873, r234056, r234096, r234100, r234108, r234175, r234187, r234223, r234271, r234272, r234282, r234307, r234309, r234382, r234384, r234456, r234486, r234606, r234640, r234641, r234642, r234644, r234651, r235505, r235506, r235535, r235605, r235606, r235826, r235991, r235993, r236168, r236173, r236179, r236180, r236181, r236186, r236223, r236227, r236230, r236252, r236254, r236298, r236299, r236300, r236301, r236397, r236398, r236399, r236499, r236512, r236513, r236525, r236526, r236545, r236548, r236553, r236554, r236556, r236557, r236561, r236570, r236630, r236672, r236673, r236679, r236706, r236710, r236718, r237154, r237155, r237169, r237314, r237363, r237364, r237368, r237369, r237376, r237440, r237442, r237751, r237783, r237784, r237785, r237788, r237791, r238421, r238522, r238523, r238524, r238525, r239173, r239186, r239644, r239652, r239661, r239773, r240125, r240130, r240131, r240136, r240186, r240196, r240212. I'd like to thank people who participated in early testing: Tested by: Florian Smeets <flo freebsd.org> Tested by: Chekaluk Vitaly <artemrts ukr.net> Tested by: Ben Wilber <ben desync.com> Tested by: Ian FREISLICH <ianf cloudseed.co.za>
Diffstat (limited to 'sys/contrib/pf/net/pf_osfp.c')
-rw-r--r--sys/contrib/pf/net/pf_osfp.c234
1 files changed, 31 insertions, 203 deletions
diff --git a/sys/contrib/pf/net/pf_osfp.c b/sys/contrib/pf/net/pf_osfp.c
index dcd8af7..29d4a40 100644
--- a/sys/contrib/pf/net/pf_osfp.c
+++ b/sys/contrib/pf/net/pf_osfp.c
@@ -17,23 +17,14 @@
*
*/
-#ifdef __FreeBSD__
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
-#endif
#include <sys/param.h>
+#include <sys/kernel.h>
#include <sys/socket.h>
-#ifdef _KERNEL
-#include <sys/systm.h>
-#ifndef __FreeBSD__
-#include <sys/pool.h>
-#endif
-#endif /* _KERNEL */
-#include <sys/mbuf.h>
#include <netinet/in.h>
-#include <netinet/in_systm.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>
@@ -41,77 +32,31 @@ __FBSDID("$FreeBSD$");
#include <net/pfvar.h>
#include <netinet/ip6.h>
-#ifdef _KERNEL
#include <netinet6/in6_var.h>
-#endif
-
-#ifdef _KERNEL
-#ifdef __FreeBSD__
+static MALLOC_DEFINE(M_PFOSFP, "pf_osfp", "pf(4) operating system fingerprints");
#define DPFPRINTF(format, x...) \
if (V_pf_status.debug >= PF_DEBUG_NOISY) \
printf(format , ##x)
-#else
-#define DPFPRINTF(format, x...) \
- if (pf_status.debug >= PF_DEBUG_NOISY) \
- printf(format , ##x)
-#endif
-#ifdef __FreeBSD__
-typedef uma_zone_t pool_t;
-#else
-typedef struct pool pool_t;
-#endif
-#else
-/* Userland equivalents so we can lend code to tcpdump et al. */
-
-#include <arpa/inet.h>
-#include <errno.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <netdb.h>
-#define pool_t int
-#define pool_get(pool, flags) malloc(*(pool))
-#define pool_put(pool, item) free(item)
-#define pool_init(pool, size, a, ao, f, m, p) (*(pool)) = (size)
-
-#ifdef __FreeBSD__
-#define NTOHS(x) (x) = ntohs((u_int16_t)(x))
-#endif
-
-#ifdef PFDEBUG
-#include <sys/stdarg.h>
-#define DPFPRINTF(format, x...) fprintf(stderr, format , ##x)
-#else
-#define DPFPRINTF(format, x...) ((void)0)
-#endif /* PFDEBUG */
-#endif /* _KERNEL */
-
-
-#ifdef __FreeBSD__
SLIST_HEAD(pf_osfp_list, pf_os_fingerprint);
-VNET_DEFINE(struct pf_osfp_list, pf_osfp_list);
+static VNET_DEFINE(struct pf_osfp_list, pf_osfp_list) =
+ SLIST_HEAD_INITIALIZER();
#define V_pf_osfp_list VNET(pf_osfp_list)
-VNET_DEFINE(pool_t, pf_osfp_entry_pl);
-#define pf_osfp_entry_pl VNET(pf_osfp_entry_pl)
-VNET_DEFINE(pool_t, pf_osfp_pl);
-#define pf_osfp_pl VNET(pf_osfp_pl)
-#else
-SLIST_HEAD(pf_osfp_list, pf_os_fingerprint) pf_osfp_list;
-pool_t pf_osfp_entry_pl;
-pool_t pf_osfp_pl;
-#endif
-struct pf_os_fingerprint *pf_osfp_find(struct pf_osfp_list *,
+static struct pf_osfp_enlist *pf_osfp_fingerprint_hdr(const struct ip *,
+ const struct ip6_hdr *,
+ const struct tcphdr *);
+static struct pf_os_fingerprint *pf_osfp_find(struct pf_osfp_list *,
struct pf_os_fingerprint *, u_int8_t);
-struct pf_os_fingerprint *pf_osfp_find_exact(struct pf_osfp_list *,
+static struct pf_os_fingerprint *pf_osfp_find_exact(struct pf_osfp_list *,
struct pf_os_fingerprint *);
-void pf_osfp_insert(struct pf_osfp_list *,
+static void pf_osfp_insert(struct pf_osfp_list *,
struct pf_os_fingerprint *);
+#ifdef PFDEBUG
+static struct pf_os_fingerprint *pf_osfp_validate(void);
+#endif
-
-#ifdef _KERNEL
/*
* Passively fingerprint the OS of the host (IPv4 TCP SYN packets only)
* Returns the list of possible OSes.
@@ -140,19 +85,14 @@ pf_osfp_fingerprint(struct pf_pdesc *pd, struct mbuf *m, int off,
return (pf_osfp_fingerprint_hdr(ip, ip6, (struct tcphdr *)hdr));
}
-#endif /* _KERNEL */
-struct pf_osfp_enlist *
+static struct pf_osfp_enlist *
pf_osfp_fingerprint_hdr(const struct ip *ip, const struct ip6_hdr *ip6, const struct tcphdr *tcp)
{
struct pf_os_fingerprint fp, *fpresult;
int cnt, optlen = 0;
const u_int8_t *optp;
-#ifdef _KERNEL
char srcname[128];
-#else
- char srcname[NI_MAXHOST];
-#endif
if ((tcp->th_flags & (TH_SYN|TH_ACK)) != TH_SYN)
return (NULL);
@@ -164,49 +104,21 @@ pf_osfp_fingerprint_hdr(const struct ip *ip, const struct ip6_hdr *ip6, const st
memset(&fp, 0, sizeof(fp));
if (ip) {
-#ifndef _KERNEL
- struct sockaddr_in sin;
-#endif
-
fp.fp_psize = ntohs(ip->ip_len);
fp.fp_ttl = ip->ip_ttl;
if (ip->ip_off & htons(IP_DF))
fp.fp_flags |= PF_OSFP_DF;
-#ifdef _KERNEL
strlcpy(srcname, inet_ntoa(ip->ip_src), sizeof(srcname));
-#else
- memset(&sin, 0, sizeof(sin));
- sin.sin_family = AF_INET;
- sin.sin_len = sizeof(struct sockaddr_in);
- sin.sin_addr = ip->ip_src;
- (void)getnameinfo((struct sockaddr *)&sin,
- sizeof(struct sockaddr_in), srcname, sizeof(srcname),
- NULL, 0, NI_NUMERICHOST);
-#endif
}
#ifdef INET6
else if (ip6) {
-#ifndef _KERNEL
- struct sockaddr_in6 sin6;
-#endif
-
/* jumbo payload? */
fp.fp_psize = sizeof(struct ip6_hdr) + ntohs(ip6->ip6_plen);
fp.fp_ttl = ip6->ip6_hlim;
fp.fp_flags |= PF_OSFP_DF;
fp.fp_flags |= PF_OSFP_INET6;
-#ifdef _KERNEL
strlcpy(srcname, ip6_sprintf((struct in6_addr *)&ip6->ip6_src),
sizeof(srcname));
-#else
- memset(&sin6, 0, sizeof(sin6));
- sin6.sin6_family = AF_INET6;
- sin6.sin6_len = sizeof(struct sockaddr_in6);
- sin6.sin6_addr = ip6->ip6_src;
- (void)getnameinfo((struct sockaddr *)&sin6,
- sizeof(struct sockaddr_in6), srcname, sizeof(srcname),
- NULL, 0, NI_NUMERICHOST);
-#endif
}
#endif
else
@@ -284,11 +196,7 @@ pf_osfp_fingerprint_hdr(const struct ip *ip, const struct ip6_hdr *ip6, const st
(fp.fp_flags & PF_OSFP_WSCALE_DC) ? "*" : "",
fp.fp_wscale);
-#ifdef __FreeBSD__
if ((fpresult = pf_osfp_find(&V_pf_osfp_list, &fp,
-#else
- if ((fpresult = pf_osfp_find(&pf_osfp_list, &fp,
-#endif
PF_OSFP_MAXTTL_OFFSET)))
return (&fpresult->fp_oses);
return (NULL);
@@ -324,52 +232,6 @@ pf_osfp_match(struct pf_osfp_enlist *list, pf_osfp_t os)
return (0);
}
-/* Initialize the OS fingerprint system */
-#ifdef __FreeBSD__
-int
-#else
-void
-#endif
-pf_osfp_initialize(void)
-{
-#if defined(__FreeBSD__) && defined(_KERNEL)
- int error = ENOMEM;
-
- do {
- pf_osfp_entry_pl = pf_osfp_pl = NULL;
- UMA_CREATE(pf_osfp_entry_pl, struct pf_osfp_entry, "pfospfen");
- UMA_CREATE(pf_osfp_pl, struct pf_os_fingerprint, "pfosfp");
- error = 0;
- } while(0);
-
- SLIST_INIT(&V_pf_osfp_list);
-#else
- pool_init(&pf_osfp_entry_pl, sizeof(struct pf_osfp_entry), 0, 0, 0,
- "pfosfpen", &pool_allocator_nointr);
- pool_init(&pf_osfp_pl, sizeof(struct pf_os_fingerprint), 0, 0, 0,
- "pfosfp", &pool_allocator_nointr);
- SLIST_INIT(&pf_osfp_list);
-#endif
-
-#ifdef __FreeBSD__
-#ifdef _KERNEL
- return (error);
-#else
- return (0);
-#endif
-#endif
-}
-
-#if defined(__FreeBSD__) && (_KERNEL)
-void
-pf_osfp_cleanup(void)
-{
-
- UMA_DESTROY(pf_osfp_entry_pl);
- UMA_DESTROY(pf_osfp_pl);
-}
-#endif
-
/* Flush the fingerprint list */
void
pf_osfp_flush(void)
@@ -377,18 +239,13 @@ pf_osfp_flush(void)
struct pf_os_fingerprint *fp;
struct pf_osfp_entry *entry;
-#ifdef __FreeBSD__
while ((fp = SLIST_FIRST(&V_pf_osfp_list))) {
SLIST_REMOVE_HEAD(&V_pf_osfp_list, fp_next);
-#else
- while ((fp = SLIST_FIRST(&pf_osfp_list))) {
- SLIST_REMOVE_HEAD(&pf_osfp_list, fp_next);
-#endif
while ((entry = SLIST_FIRST(&fp->fp_oses))) {
SLIST_REMOVE_HEAD(&fp->fp_oses, fp_entry);
- pool_put(&pf_osfp_entry_pl, entry);
+ free(entry, M_PFOSFP);
}
- pool_put(&pf_osfp_pl, fp);
+ free(fp, M_PFOSFP);
}
}
@@ -400,6 +257,8 @@ pf_osfp_add(struct pf_osfp_ioctl *fpioc)
struct pf_os_fingerprint *fp, fpadd;
struct pf_osfp_entry *entry;
+ PF_RULES_WASSERT();
+
memset(&fpadd, 0, sizeof(fpadd));
fpadd.fp_tcpopts = fpioc->fp_tcpopts;
fpadd.fp_wsize = fpioc->fp_wsize;
@@ -436,31 +295,18 @@ pf_osfp_add(struct pf_osfp_ioctl *fpioc)
fpioc->fp_os.fp_os);
#endif
-#ifdef __FreeBSD__
if ((fp = pf_osfp_find_exact(&V_pf_osfp_list, &fpadd))) {
-#else
- if ((fp = pf_osfp_find_exact(&pf_osfp_list, &fpadd))) {
-#endif
SLIST_FOREACH(entry, &fp->fp_oses, fp_entry) {
if (PF_OSFP_ENTRY_EQ(entry, &fpioc->fp_os))
return (EEXIST);
}
- if ((entry = pool_get(&pf_osfp_entry_pl,
-#ifdef __FreeBSD__
- PR_NOWAIT)) == NULL)
-#else
- PR_WAITOK|PR_LIMITFAIL)) == NULL)
-#endif
+ if ((entry = malloc(sizeof(*entry), M_PFOSFP, M_NOWAIT))
+ == NULL)
return (ENOMEM);
} else {
- if ((fp = pool_get(&pf_osfp_pl,
-#ifdef __FreeBSD__
- PR_NOWAIT)) == NULL)
-#else
- PR_WAITOK|PR_LIMITFAIL)) == NULL)
-#endif
+ if ((fp = malloc(sizeof(*fp), M_PFOSFP, M_ZERO | M_NOWAIT))
+ == NULL)
return (ENOMEM);
- memset(fp, 0, sizeof(*fp));
fp->fp_tcpopts = fpioc->fp_tcpopts;
fp->fp_wsize = fpioc->fp_wsize;
fp->fp_psize = fpioc->fp_psize;
@@ -470,20 +316,12 @@ pf_osfp_add(struct pf_osfp_ioctl *fpioc)
fp->fp_wscale = fpioc->fp_wscale;
fp->fp_ttl = fpioc->fp_ttl;
SLIST_INIT(&fp->fp_oses);
- if ((entry = pool_get(&pf_osfp_entry_pl,
-#ifdef __FreeBSD__
- PR_NOWAIT)) == NULL) {
-#else
- PR_WAITOK|PR_LIMITFAIL)) == NULL) {
-#endif
- pool_put(&pf_osfp_pl, fp);
+ if ((entry = malloc(sizeof(*entry), M_PFOSFP, M_NOWAIT))
+ == NULL) {
+ free(fp, M_PFOSFP);
return (ENOMEM);
}
-#ifdef __FreeBSD__
pf_osfp_insert(&V_pf_osfp_list, fp);
-#else
- pf_osfp_insert(&pf_osfp_list, fp);
-#endif
}
memcpy(entry, &fpioc->fp_os, sizeof(*entry));
@@ -503,7 +341,7 @@ pf_osfp_add(struct pf_osfp_ioctl *fpioc)
/* Find a fingerprint in the list */
-struct pf_os_fingerprint *
+static struct pf_os_fingerprint *
pf_osfp_find(struct pf_osfp_list *list, struct pf_os_fingerprint *find,
u_int8_t ttldiff)
{
@@ -578,7 +416,7 @@ pf_osfp_find(struct pf_osfp_list *list, struct pf_os_fingerprint *find,
}
/* Find an exact fingerprint in the list */
-struct pf_os_fingerprint *
+static struct pf_os_fingerprint *
pf_osfp_find_exact(struct pf_osfp_list *list, struct pf_os_fingerprint *find)
{
struct pf_os_fingerprint *f;
@@ -599,7 +437,7 @@ pf_osfp_find_exact(struct pf_osfp_list *list, struct pf_os_fingerprint *find)
}
/* Insert a fingerprint into the list */
-void
+static void
pf_osfp_insert(struct pf_osfp_list *list, struct pf_os_fingerprint *ins)
{
struct pf_os_fingerprint *f, *prev = NULL;
@@ -625,11 +463,7 @@ pf_osfp_get(struct pf_osfp_ioctl *fpioc)
memset(fpioc, 0, sizeof(*fpioc));
-#ifdef __FreeBSD__
SLIST_FOREACH(fp, &V_pf_osfp_list, fp_next) {
-#else
- SLIST_FOREACH(fp, &pf_osfp_list, fp_next) {
-#endif
SLIST_FOREACH(entry, &fp->fp_oses, fp_entry) {
if (i++ == num) {
fpioc->fp_mss = fp->fp_mss;
@@ -650,17 +484,14 @@ pf_osfp_get(struct pf_osfp_ioctl *fpioc)
}
+#ifdef PFDEBUG
/* Validate that each signature is reachable */
-struct pf_os_fingerprint *
+static struct pf_os_fingerprint *
pf_osfp_validate(void)
{
struct pf_os_fingerprint *f, *f2, find;
-#ifdef __FreeBSD__
SLIST_FOREACH(f, &V_pf_osfp_list, fp_next) {
-#else
- SLIST_FOREACH(f, &pf_osfp_list, fp_next) {
-#endif
memcpy(&find, f, sizeof(find));
/* We do a few MSS/th_win percolations to make things unique */
@@ -672,11 +503,7 @@ pf_osfp_validate(void)
find.fp_wsize *= (find.fp_mss + 40);
else if (f->fp_flags & PF_OSFP_WSIZE_MOD)
find.fp_wsize *= 2;
-#ifdef __FreeBSD__
if (f != (f2 = pf_osfp_find(&V_pf_osfp_list, &find, 0))) {
-#else
- if (f != (f2 = pf_osfp_find(&pf_osfp_list, &find, 0))) {
-#endif
if (f2)
printf("Found \"%s %s %s\" instead of "
"\"%s %s %s\"\n",
@@ -696,3 +523,4 @@ pf_osfp_validate(void)
}
return (NULL);
}
+#endif /* PFDEBUG */
OpenPOWER on IntegriCloud