Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F137285923
D53877.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
8 KB
Referenced Files
None
Subscribers
None
D53877.diff
View Options
diff --git a/sys/netpfil/ipfw/ip_fw_bpf.c b/sys/netpfil/ipfw/ip_fw_bpf.c
--- a/sys/netpfil/ipfw/ip_fw_bpf.c
+++ b/sys/netpfil/ipfw/ip_fw_bpf.c
@@ -31,13 +31,14 @@
#include <sys/kernel.h>
#include <sys/lock.h>
#include <sys/socket.h>
+#include <sys/tree.h>
#include <net/ethernet.h>
#include <net/if.h>
#include <net/if_pflog.h>
#include <net/vnet.h>
#include <net/bpf.h>
-#include <netinet/in.h>
+#include <netinet/ip.h>
#include <netinet/ip_fw.h>
#include <netinet/ip_var.h>
#include <netpfil/ipfw/ip_fw_private.h>
@@ -53,48 +54,104 @@
.bif_chkdir = bpf_ipfw_chkdir,
};
-static const char ipfwname[] = "ipfw0";
-static const char ipfwlogname[] = "ipfwlog0";
+struct ipfw_tap {
+ RB_ENTRY(ipfw_tap) entry;
+ uint32_t rule;
+ struct bpf_if *bpf;
+ char name[sizeof("ipfw65535")];
+};
-VNET_DEFINE_STATIC(struct bpf_if *, bpf_en10mb);
-VNET_DEFINE_STATIC(struct bpf_if *, bpf_pflog);
-#define V_bpf_en10mb VNET(bpf_en10mb)
-#define V_bpf_pflog VNET(bpf_pflog)
+static int32_t
+tap_compare(const struct ipfw_tap *a, const struct ipfw_tap *b)
+{
+ return ((int32_t)(a->rule/2 - b->rule/2));
+}
+RB_HEAD(tap_tree, ipfw_tap);
+VNET_DEFINE_STATIC(struct tap_tree, tap_tree);
+#define V_tap_tree VNET(tap_tree)
+RB_GENERATE_STATIC(tap_tree, ipfw_tap, entry, tap_compare);
+VNET_DEFINE_STATIC(struct ipfw_tap *, default_tap);
+#define V_default_tap VNET(default_tap)
void
-ipfw_bpf_tap(u_char *pkt, u_int pktlen)
+ipfw_tap_alloc(uint32_t rule)
{
- bpf_tap(V_bpf_en10mb, pkt, pktlen);
+ struct ipfw_tap *tap, *dup __diagused;
+ int n __diagused;
+
+ tap = malloc(sizeof(*tap), M_IPFW, M_WAITOK);
+ tap->rule = rule;
+ /* Note: the default rule logs to "ipfw0". */
+ if (__predict_false(rule == IPFW_DEFAULT_RULE)) {
+ V_default_tap = tap;
+ rule = 0;
+ }
+ n = snprintf(tap->name, sizeof(tap->name), "ipfw%u", rule);
+ MPASS(n > 4 && n < sizeof("ipfw65535"));
+ tap->bpf = bpf_attach(tap->name, DLT_EN10MB, PFLOG_HDRLEN,
+ &bpf_ipfw_methods, NULL);
+ dup = RB_INSERT(tap_tree, &V_tap_tree, tap);
+ MPASS(dup == NULL);
}
void
-ipfw_bpf_mtap(struct mbuf *m)
+ipfw_tap_free(uint32_t rule)
{
- bpf_mtap(V_bpf_en10mb, m);
+
+ struct ipfw_tap *tap, key = { .rule = rule };
+
+ tap = RB_FIND(tap_tree, &V_tap_tree, &key);
+ MPASS(tap != NULL);
+ bpf_detach(tap->bpf);
+ RB_REMOVE(tap_tree, &V_tap_tree, tap);
+ free(tap, M_IPFW);
}
void
-ipfw_bpf_mtap2(void *data, u_int dlen, struct mbuf *m)
+ipfw_bpf_tap(struct ip_fw_args *args, struct ip *ip, uint32_t rulenum)
{
- switch (dlen) {
- case (ETHER_HDR_LEN):
- bpf_mtap2(V_bpf_en10mb, data, dlen, m);
- break;
- case (PFLOG_HDRLEN):
- bpf_mtap2(V_bpf_pflog, data, dlen, m);
- break;
- default:
- MPASS(0);
+ struct ipfw_tap *tap, key = { .rule = rulenum };
+
+ tap = RB_FIND(tap_tree, &V_tap_tree, &key);
+ MPASS(tap != NULL);
+ if (!bpf_peers_present(tap->bpf))
+ tap = V_default_tap;
+ if (args->flags & IPFW_ARGS_LENMASK) {
+ bpf_tap(tap->bpf, args->mem, IPFW_ARGS_LENGTH(args->flags));
+ } else if (args->flags & IPFW_ARGS_ETHER) {
+ /* layer2, use orig hdr */
+ bpf_mtap(tap->bpf, args->m);
+ } else {
+ char *fakehdr;
+
+ /* Add fake header. Later we will store
+ * more info in the header.
+ */
+ if (ip->ip_v == 4)
+ fakehdr = "DDDDDDSSSSSS\x08\x00";
+ else if (ip->ip_v == 6)
+ fakehdr = "DDDDDDSSSSSS\x86\xdd";
+ else
+ /* Obviously bogus EtherType. */
+ fakehdr = "DDDDDDSSSSSS\xff\xff";
+
+ bpf_mtap2(tap->bpf, fakehdr, ETHER_HDR_LEN, args->m);
}
}
+VNET_DEFINE_STATIC(struct bpf_if *, bpf_pflog);
+#define V_bpf_pflog VNET(bpf_pflog)
void
-ipfw_bpf_init(int first __unused)
+ipfw_pflog_tap(void *data, struct mbuf *m)
{
+ bpf_mtap2(V_bpf_pflog, data, PFLOG_HDRLEN, m);
+}
- V_bpf_en10mb = bpf_attach(ipfwname, DLT_EN10MB, ETHER_HDR_LEN,
- &bpf_ipfw_methods, NULL);
- V_bpf_pflog = bpf_attach(ipfwlogname, DLT_PFLOG, PFLOG_HDRLEN,
+void
+ipfw_bpf_init(int first __unused)
+{
+ ipfw_tap_alloc(IPFW_DEFAULT_RULE);
+ V_bpf_pflog = bpf_attach("ipfwlog0", DLT_PFLOG, PFLOG_HDRLEN,
&bpf_ipfw_methods, NULL);
}
@@ -102,6 +159,6 @@
ipfw_bpf_uninit(int last __unused)
{
- bpf_detach(V_bpf_en10mb);
+ ipfw_tap_free(IPFW_DEFAULT_RULE);
bpf_detach(V_bpf_pflog);
}
diff --git a/sys/netpfil/ipfw/ip_fw_log.c b/sys/netpfil/ipfw/ip_fw_log.c
--- a/sys/netpfil/ipfw/ip_fw_log.c
+++ b/sys/netpfil/ipfw/ip_fw_log.c
@@ -96,31 +96,6 @@
#define TARG(k, f) IP_FW_ARG_TABLEARG(chain, k, f)
-static void
-ipfw_log_ipfw0(struct ip_fw_args *args, struct ip *ip)
-{
- if (args->flags & IPFW_ARGS_LENMASK)
- ipfw_bpf_tap(args->mem, IPFW_ARGS_LENGTH(args->flags));
- else if (args->flags & IPFW_ARGS_ETHER)
- /* layer2, use orig hdr */
- ipfw_bpf_mtap(args->m);
- else {
- /* Add fake header. Later we will store
- * more info in the header.
- */
- if (ip->ip_v == 4)
- ipfw_bpf_mtap2("DDDDDDSSSSSS\x08\x00",
- ETHER_HDR_LEN, args->m);
- else if (ip->ip_v == 6)
- ipfw_bpf_mtap2("DDDDDDSSSSSS\x86\xdd",
- ETHER_HDR_LEN, args->m);
- else
- /* Obviously bogus EtherType. */
- ipfw_bpf_mtap2("DDDDDDSSSSSS\xff\xff",
- ETHER_HDR_LEN, args->m);
- }
-}
-
/*
* XXX this function alone takes about 2Kbytes of code!
*/
@@ -747,7 +722,8 @@
/* O_LOG is the first action */
((cmd = ACTION_PTR(f)) && cmd->arg1 == IPFW_LOG_DEFAULT)) {
if (V_fw_verbose == 0) {
- ipfw_log_ipfw0(args, ip);
+ ipfw_bpf_tap(args, ip,
+ f != NULL ? f->rulenum : IPFW_DEFAULT_RULE);
return;
}
ipfw_log_syslog(chain, f, hlen, args, offset, tablearg, ip);
@@ -761,6 +737,6 @@
ipfw_log_rtsock(chain, f, hlen, args, offset, tablearg, eh);
if (cmd->arg1 & IPFW_LOG_IPFW0)
- ipfw_log_ipfw0(args, ip);
+ ipfw_bpf_tap(args, ip, f->rulenum);
}
/* end of file */
diff --git a/sys/netpfil/ipfw/ip_fw_private.h b/sys/netpfil/ipfw/ip_fw_private.h
--- a/sys/netpfil/ipfw/ip_fw_private.h
+++ b/sys/netpfil/ipfw/ip_fw_private.h
@@ -161,9 +161,10 @@
void ipfw_bpf_init(int);
void ipfw_bpf_uninit(int);
-void ipfw_bpf_tap(u_char *, u_int);
-void ipfw_bpf_mtap(struct mbuf *);
-void ipfw_bpf_mtap2(void *, u_int, struct mbuf *);
+void ipfw_tap_alloc(uint32_t);
+void ipfw_tap_free(uint32_t);
+void ipfw_bpf_tap(struct ip_fw_args *, struct ip *, uint32_t);
+void ipfw_pflog_tap(void *, struct mbuf *);
void ipfw_log(struct ip_fw_chain *chain, struct ip_fw *f, u_int hlen,
struct ip_fw_args *args, u_short offset, uint32_t tablearg, struct ip *ip,
void *eh);
diff --git a/sys/netpfil/ipfw/ip_fw_sockopt.c b/sys/netpfil/ipfw/ip_fw_sockopt.c
--- a/sys/netpfil/ipfw/ip_fw_sockopt.c
+++ b/sys/netpfil/ipfw/ip_fw_sockopt.c
@@ -210,6 +210,8 @@
*/
if (rule->refcnt > 1)
return;
+ if (ACTION_PTR(rule)->opcode == O_LOG)
+ ipfw_tap_free(rule->rulenum);
uma_zfree_pcpu(V_ipfw_cntr_zone, rule->cntr);
free(rule, M_IPFW);
}
@@ -2511,6 +2513,9 @@
/* Copy opcodes */
memcpy(krule->cmd, urule->cmd, krule->cmd_len * sizeof(uint32_t));
+
+ if (ACTION_PTR(krule)->opcode == O_LOG)
+ ipfw_tap_alloc(krule->rulenum);
}
/*
diff --git a/sys/netpfil/ipfw/nat64/nat64_translate.c b/sys/netpfil/ipfw/nat64/nat64_translate.c
--- a/sys/netpfil/ipfw/nat64/nat64_translate.c
+++ b/sys/netpfil/ipfw/nat64/nat64_translate.c
@@ -151,7 +151,7 @@
logdata->dir = PF_OUT;
logdata->af = family;
- ipfw_bpf_mtap2(logdata, PFLOG_HDRLEN, m);
+ ipfw_pflog_tap(logdata, m);
}
static int
diff --git a/sys/netpfil/ipfw/nat64/nat64clat.c b/sys/netpfil/ipfw/nat64/nat64clat.c
--- a/sys/netpfil/ipfw/nat64/nat64clat.c
+++ b/sys/netpfil/ipfw/nat64/nat64clat.c
@@ -77,7 +77,7 @@
plog->subrulenr = htonl(pktid);
plog->ruleset[0] = '\0';
strlcpy(plog->ifname, "NAT64CLAT", sizeof(plog->ifname));
- ipfw_bpf_mtap2(plog, PFLOG_HDRLEN, m);
+ ipfw_pflog_tap(plog, m);
}
static int
diff --git a/sys/netpfil/ipfw/nat64/nat64lsn.c b/sys/netpfil/ipfw/nat64/nat64lsn.c
--- a/sys/netpfil/ipfw/nat64/nat64lsn.c
+++ b/sys/netpfil/ipfw/nat64/nat64lsn.c
@@ -187,7 +187,7 @@
(state->proto << 8) | (state->ip_dst & 0xff));
plog->ruleset[0] = '\0';
strlcpy(plog->ifname, "NAT64LSN", sizeof(plog->ifname));
- ipfw_bpf_mtap2(plog, PFLOG_HDRLEN, m);
+ ipfw_pflog_tap(plog, m);
}
#define HVAL(p, n, s) jenkins_hash32((const uint32_t *)(p), (n), (s))
diff --git a/sys/netpfil/ipfw/nat64/nat64stl.c b/sys/netpfil/ipfw/nat64/nat64stl.c
--- a/sys/netpfil/ipfw/nat64/nat64stl.c
+++ b/sys/netpfil/ipfw/nat64/nat64stl.c
@@ -76,7 +76,7 @@
plog->subrulenr = htonl(pktid);
plog->ruleset[0] = '\0';
strlcpy(plog->ifname, "NAT64STL", sizeof(plog->ifname));
- ipfw_bpf_mtap2(plog, PFLOG_HDRLEN, m);
+ ipfw_pflog_tap(plog, m);
}
static int
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sun, Nov 23, 1:48 AM (14 h, 13 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
25998479
Default Alt Text
D53877.diff (8 KB)
Attached To
Mode
D53877: ipfw: create a bpf tap point for every log rule
Attached
Detach File
Event Timeline
Log In to Comment