Page MenuHomeFreeBSD

D53877.diff
No OneTemporary

D53877.diff

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

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)

Event Timeline