Add dtrace SDT probe ipfw:::rule-matched.
It helps to reduce complexity with debugging of large ipfw rulesets. Also define several constants and translators, that can by used by dtrace scripts with this probe. Reviewed by: gnn Obtained from: Yandex LLC MFC after: 2 weeks Sponsored by: Yandex LLC Differential Revision: https://reviews.freebsd.org/D26879
This commit is contained in:
parent
f1f45fa8c2
commit
8483987d89
@ -21,7 +21,7 @@ SCRIPTS= blocking \
|
||||
|
||||
SCRIPTSDIR= ${SHAREDIR}/dtrace
|
||||
|
||||
DSRCS= mbuf.d
|
||||
DSRCS= mbuf.d ipfw.d
|
||||
|
||||
FILES= ${DSRCS}
|
||||
FILESDIR= /usr/lib/dtrace
|
||||
|
219
share/dtrace/ipfw.d
Normal file
219
share/dtrace/ipfw.d
Normal file
@ -0,0 +1,219 @@
|
||||
/*-
|
||||
* SPDX-License-Identifier: BSD-2-Clause-FreeBSD
|
||||
*
|
||||
* Copyright (c) 2020 Yandex LLC
|
||||
* Copyright (c) 2020 Andrey V. Elsukov <ae@FreeBSD.org>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#pragma D depends_on provider ipfw
|
||||
|
||||
/* ipfw_chk() return values */
|
||||
#pragma D binding "1.0" IP_FW_PASS
|
||||
inline int IP_FW_PASS = 0;
|
||||
#pragma D binding "1.0" IP_FW_DENY
|
||||
inline int IP_FW_DENY = 1;
|
||||
#pragma D binding "1.0" IP_FW_DIVERT
|
||||
inline int IP_FW_DIVERT = 2;
|
||||
#pragma D binding "1.0" IP_FW_TEE
|
||||
inline int IP_FW_TEE = 3;
|
||||
#pragma D binding "1.0" IP_FW_DUMMYNET
|
||||
inline int IP_FW_DUMMYNET = 4;
|
||||
#pragma D binding "1.0" IP_FW_NETGRAPH
|
||||
inline int IP_FW_NETGRAPH = 5;
|
||||
#pragma D binding "1.0" IP_FW_NGTEE
|
||||
inline int IP_FW_NGTEE = 6;
|
||||
#pragma D binding "1.0" IP_FW_NAT
|
||||
inline int IP_FW_NAT = 7;
|
||||
#pragma D binding "1.0" IP_FW_REASS
|
||||
inline int IP_FW_REASS = 8;
|
||||
#pragma D binding "1.0" IP_FW_NAT64
|
||||
inline int IP_FW_NAT64 = 9;
|
||||
|
||||
#pragma D binding "1.0" ipfw_retcodes
|
||||
inline string ipfw_retcodes[int ret] =
|
||||
ret == IP_FW_PASS ? "PASS" :
|
||||
ret == IP_FW_DENY ? "DENY" :
|
||||
ret == IP_FW_DIVERT ? "DIVERT" :
|
||||
ret == IP_FW_TEE ? "TEE" :
|
||||
ret == IP_FW_DUMMYNET ? "DUMMYNET" :
|
||||
ret == IP_FW_NETGRAPH ? "NETGRAPH" :
|
||||
ret == IP_FW_NGTEE ? "NGTEE" :
|
||||
ret == IP_FW_NAT ? "NAT" :
|
||||
ret == IP_FW_REASS ? "REASS" :
|
||||
ret == IP_FW_NAT64 ? "NAT64" :
|
||||
"<unknown>";
|
||||
|
||||
/* ip_fw_args flags */
|
||||
#pragma D binding "1.0" IPFW_ARGS_ETHER
|
||||
inline int IPFW_ARGS_ETHER = 0x00010000; /* valid ethernet header */
|
||||
#pragma D binding "1.0" IPFW_ARGS_NH4
|
||||
inline int IPFW_ARGS_NH4 = 0x00020000; /* IPv4 next hop in hopstore */
|
||||
#pragma D binding "1.0" IPFW_ARGS_NH6
|
||||
inline int IPFW_ARGS_NH6 = 0x00040000; /* IPv6 next hop in hopstore */
|
||||
#pragma D binding "1.0" IPFW_ARGS_NH4PTR
|
||||
inline int IPFW_ARGS_NH4PTR = 0x00080000; /* IPv4 next hop in next_hop */
|
||||
#pragma D binding "1.0" IPFW_ARGS_NH6PTR
|
||||
inline int IPFW_ARGS_NH6PTR = 0x00100000; /* IPv6 next hop in next_hop6 */
|
||||
#pragma D binding "1.0" IPFW_ARGS_REF
|
||||
inline int IPFW_ARGS_REF = 0x00200000; /* valid ipfw_rule_ref */
|
||||
#pragma D binding "1.0" IPFW_ARGS_IN
|
||||
inline int IPFW_ARGS_IN = 0x00400000; /* called on input */
|
||||
#pragma D binding "1.0" IPFW_ARGS_OUT
|
||||
inline int IPFW_ARGS_OUT = 0x00800000; /* called on output */
|
||||
#pragma D binding "1.0" IPFW_ARGS_IP4
|
||||
inline int IPFW_ARGS_IP4 = 0x01000000; /* belongs to v4 ISR */
|
||||
#pragma D binding "1.0" IPFW_ARGS_IP6
|
||||
inline int IPFW_ARGS_IP6 = 0x02000000; /* belongs to v6 ISR */
|
||||
#pragma D binding "1.0" IPFW_ARGS_DROP
|
||||
inline int IPFW_ARGS_DROP = 0x04000000; /* drop it (dummynet) */
|
||||
#pragma D binding "1.0" IPFW_ARGS_LENMASK
|
||||
inline int IPFW_ARGS_LENMASK = 0x0000ffff; /* length of data in *mem */
|
||||
|
||||
/* ipfw_rule_ref.info */
|
||||
#pragma D binding "1.0" IPFW_INFO_MASK
|
||||
inline int IPFW_INFO_MASK = 0x0000ffff;
|
||||
#pragma D binding "1.0" IPFW_INFO_OUT
|
||||
inline int IPFW_INFO_OUT = 0x00000000;
|
||||
#pragma D binding "1.0" IPFW_INFO_IN
|
||||
inline int IPFW_INFO_IN = 0x80000000;
|
||||
#pragma D binding "1.0" IPFW_ONEPASS
|
||||
inline int IPFW_ONEPASS = 0x40000000;
|
||||
#pragma D binding "1.0" IPFW_IS_MASK
|
||||
inline int IPFW_IS_MASK = 0x30000000;
|
||||
#pragma D binding "1.0" IPFW_IS_DIVERT
|
||||
inline int IPFW_IS_DIVERT = 0x20000000;
|
||||
#pragma D binding "1.0" IPFW_IS_DUMMYNET
|
||||
inline int IPFW_IS_DUMMYNET = 0x10000000;
|
||||
#pragma D binding "1.0" IPFW_IS_PIPE
|
||||
inline int IPFW_IS_PIPE = 0x08000000;
|
||||
|
||||
typedef struct ipfw_match_info {
|
||||
uint32_t flags;
|
||||
|
||||
struct mbuf *m;
|
||||
void *mem;
|
||||
struct inpcb *inp;
|
||||
struct ifnet *ifp;
|
||||
struct ip *ipp;
|
||||
struct ip6_hdr *ip6p;
|
||||
|
||||
/* flow id */
|
||||
uint8_t addr_type;
|
||||
uint8_t proto;
|
||||
uint8_t proto_flags;
|
||||
uint16_t fib; /* XXX */
|
||||
in_addr_t dst_ip; /* in network byte order */
|
||||
in_addr_t src_ip; /* in network byte order */
|
||||
struct in6_addr dst_ip6;
|
||||
struct in6_addr src_ip6;
|
||||
|
||||
uint16_t dst_port; /* in host byte order */
|
||||
uint16_t src_port; /* in host byte order */
|
||||
|
||||
uint32_t flowid; /* IPv6 flowid */
|
||||
uint32_t extra;
|
||||
|
||||
/* ipfw_rule_ref */
|
||||
uint32_t slot;
|
||||
uint32_t rulenum;
|
||||
uint32_t rule_id;
|
||||
uint32_t chain_id;
|
||||
uint32_t match_info;
|
||||
} ipfw_match_info_t;
|
||||
|
||||
#pragma D binding "1.0" translator
|
||||
translator ipfw_match_info_t < struct ip_fw_args *p > {
|
||||
flags = p->flags;
|
||||
m = (p->flags & IPFW_ARGS_LENMASK) ? NULL : p->m;
|
||||
mem = (p->flags & IPFW_ARGS_LENMASK) ? p->mem : NULL;
|
||||
inp = p->inp;
|
||||
ifp = p->ifp;
|
||||
/* Initialize IP pointer corresponding to addr_type */
|
||||
ipp = (p->flags & IPFW_ARGS_IP4) ?
|
||||
(p->flags & IPFW_ARGS_LENMASK) ? (struct ip *)p->mem :
|
||||
(p->m != NULL) ? (struct ip *)p->m->m_data : NULL : NULL;
|
||||
ip6p = (p->flags & IPFW_ARGS_IP6) ?
|
||||
(p->flags & IPFW_ARGS_LENMASK) ? (struct ip6_hdr *)p->mem :
|
||||
(p->m != NULL) ? (struct ip6_hdr *)p->m->m_data : NULL : NULL;
|
||||
|
||||
/* fill f_id fields */
|
||||
addr_type = p->f_id.addr_type;
|
||||
proto = p->f_id.proto;
|
||||
proto_flags = p->f_id._flags;
|
||||
|
||||
/* f_id.fib keeps truncated fibnum, use mbuf's fibnum if possible */
|
||||
fib = p->m != NULL ? p->m->m_pkthdr.fibnum : p->f_id.fib;
|
||||
|
||||
/*
|
||||
* ipfw_chk() keeps IPv4 addresses in host byte order. But for
|
||||
* dtrace script it is useful to have them in network byte order,
|
||||
* because inet_ntoa() uses address in network byte order.
|
||||
*/
|
||||
dst_ip = htonl(p->f_id.dst_ip);
|
||||
src_ip = htonl(p->f_id.src_ip);
|
||||
|
||||
dst_ip6 = p->f_id.dst_ip6;
|
||||
src_ip6 = p->f_id.src_ip6;
|
||||
|
||||
dst_port = p->f_id.dst_port;
|
||||
src_port = p->f_id.src_port;
|
||||
|
||||
flowid = p->f_id.flow_id6;
|
||||
extra = p->f_id.extra;
|
||||
|
||||
/* ipfw_rule_ref */
|
||||
slot = (p->flags & IPFW_ARGS_REF) ? p->rule.slot : 0;
|
||||
rulenum = (p->flags & IPFW_ARGS_REF) ? p->rule.rulenum : 0;
|
||||
rule_id = (p->flags & IPFW_ARGS_REF) ? p->rule.rule_id : 0;
|
||||
chain_id = (p->flags & IPFW_ARGS_REF) ? p->rule.chain_id : 0;
|
||||
match_info = (p->flags & IPFW_ARGS_REF) ? p->rule.info : 0;
|
||||
};
|
||||
|
||||
typedef struct ipfw_rule_info {
|
||||
uint16_t act_ofs;
|
||||
uint16_t cmd_len;
|
||||
uint32_t rulenum;
|
||||
uint8_t flags;
|
||||
uint8_t set;
|
||||
uint32_t rule_id;
|
||||
uint32_t cached_id;
|
||||
uint32_t cached_pos;
|
||||
uint32_t refcnt;
|
||||
} ipfw_rule_info_t;
|
||||
|
||||
#pragma D binding "1.0" translator
|
||||
translator ipfw_rule_info_t < struct ip_fw *r > {
|
||||
act_ofs = r->act_ofs;
|
||||
cmd_len = r->cmd_len;
|
||||
rulenum = r->rulenum;
|
||||
flags = r->flags;
|
||||
set = r->set;
|
||||
rule_id = r->id;
|
||||
cached_id = r->cached_id;
|
||||
cached_pos = r->cached_pos;
|
||||
refcnt = r->refcnt;
|
||||
};
|
||||
|
@ -55,6 +55,7 @@ __FBSDID("$FreeBSD$");
|
||||
#include <sys/proc.h>
|
||||
#include <sys/rwlock.h>
|
||||
#include <sys/rmlock.h>
|
||||
#include <sys/sdt.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/socketvar.h>
|
||||
#include <sys/sysctl.h>
|
||||
@ -106,6 +107,18 @@ __FBSDID("$FreeBSD$");
|
||||
#include <security/mac/mac_framework.h>
|
||||
#endif
|
||||
|
||||
#define IPFW_PROBE(probe, arg0, arg1, arg2, arg3, arg4, arg5) \
|
||||
SDT_PROBE6(ipfw, , , probe, arg0, arg1, arg2, arg3, arg4, arg5)
|
||||
|
||||
SDT_PROVIDER_DEFINE(ipfw);
|
||||
SDT_PROBE_DEFINE6(ipfw, , , rule__matched,
|
||||
"int", /* retval */
|
||||
"int", /* af */
|
||||
"void *", /* src addr */
|
||||
"void *", /* dst addr */
|
||||
"struct ip_fw_args *", /* args */
|
||||
"struct ip_fw *" /* rule */);
|
||||
|
||||
/*
|
||||
* static variables followed by global ones.
|
||||
* All ipfw global variables are here.
|
||||
@ -3237,6 +3250,13 @@ do { \
|
||||
struct ip_fw *rule = chain->map[f_pos];
|
||||
/* Update statistics */
|
||||
IPFW_INC_RULE_COUNTER(rule, pktlen);
|
||||
IPFW_PROBE(rule__matched, retval,
|
||||
is_ipv4 ? AF_INET : AF_INET6,
|
||||
is_ipv4 ? (uintptr_t)&src_ip :
|
||||
(uintptr_t)&args->f_id.src_ip6,
|
||||
is_ipv4 ? (uintptr_t)&dst_ip :
|
||||
(uintptr_t)&args->f_id.dst_ip6,
|
||||
args, rule);
|
||||
} else {
|
||||
retval = IP_FW_DENY;
|
||||
printf("ipfw: ouch!, skip past end of rules, denying packet\n");
|
||||
|
Loading…
Reference in New Issue
Block a user