- Add more flags to ip_fw_args. At this changeset only IPFW_ARGS_IN and

IPFW_ARGS_OUT are utilized. They are intented to substitute the "dir"
  parameter that is often passes together with args.
- Rename ip_fw_args.oif to ifp and now it is set to either input or
  output interface, depending on IPFW_ARGS_IN/OUT bit set.
This commit is contained in:
Gleb Smirnoff 2019-03-14 22:28:50 +00:00
parent 1830dae3d3
commit b7795b6746
7 changed files with 66 additions and 73 deletions

View File

@ -841,7 +841,7 @@ tag_mbuf(struct mbuf *m, int dir, struct ip_fw_args *fwa)
dt->rule = fwa->rule;
dt->rule.info &= IPFW_ONEPASS; /* only keep this info */
dt->dn_dir = dir;
dt->ifp = fwa->oif;
dt->ifp = fwa->flags & IPFW_ARGS_OUT ? fwa->ifp : NULL;
/* dt->output tame is updated as we move through */
dt->output_time = dn_cfg.curr_time;
dt->iphdr_off = (dir & PROTO_LAYER2) ? ETHER_HDR_LEN : 0;

View File

@ -1080,13 +1080,11 @@ check_uidgid(ipfw_insn_u32 *insn, struct ip_fw_args *args, int *ugid_lookupp,
struct inpcbinfo *pi;
struct ipfw_flow_id *id;
struct inpcb *pcb, *inp;
struct ifnet *oif;
int lookupflags;
int match;
id = &args->f_id;
inp = args->inp;
oif = args->oif;
/*
* Check to see if the UDP or TCP stack supplied us with
@ -1124,16 +1122,16 @@ check_uidgid(ipfw_insn_u32 *insn, struct ip_fw_args *args, int *ugid_lookupp,
if (*ugid_lookupp == 0) {
if (id->addr_type == 6) {
#ifdef INET6
if (oif == NULL)
if (args->flags & IPFW_ARGS_IN)
pcb = in6_pcblookup_mbuf(pi,
&id->src_ip6, htons(id->src_port),
&id->dst_ip6, htons(id->dst_port),
lookupflags, oif, args->m);
lookupflags, NULL, args->m);
else
pcb = in6_pcblookup_mbuf(pi,
&id->dst_ip6, htons(id->dst_port),
&id->src_ip6, htons(id->src_port),
lookupflags, oif, args->m);
lookupflags, args->ifp, args->m);
#else
*ugid_lookupp = -1;
return (0);
@ -1141,16 +1139,16 @@ check_uidgid(ipfw_insn_u32 *insn, struct ip_fw_args *args, int *ugid_lookupp,
} else {
src_ip.s_addr = htonl(id->src_ip);
dst_ip.s_addr = htonl(id->dst_ip);
if (oif == NULL)
if (args->flags & IPFW_ARGS_IN)
pcb = in_pcblookup_mbuf(pi,
src_ip, htons(id->src_port),
dst_ip, htons(id->dst_port),
lookupflags, oif, args->m);
lookupflags, NULL, args->m);
else
pcb = in_pcblookup_mbuf(pi,
dst_ip, htons(id->dst_port),
src_ip, htons(id->src_port),
lookupflags, oif, args->m);
lookupflags, args->ifp, args->m);
}
if (pcb != NULL) {
INP_RLOCK_ASSERT(pcb);
@ -1263,8 +1261,7 @@ jump_linear(struct ip_fw_chain *chain, struct ip_fw *f, int num,
* args->eh (in) Mac header if present, NULL for layer3 packet.
* args->L3offset Number of bytes bypassed if we came from L2.
* e.g. often sizeof(eh) ** NOTYET **
* args->oif Outgoing interface, NULL if packet is incoming.
* The incoming interface is in the mbuf. (in)
* args->ifp Incoming or outgoing interface.
* args->divert_rule (in/out)
* Skip up to the first rule past this rule number;
* upon return, non-zero port number for divert or tee.
@ -1331,17 +1328,9 @@ ipfw_chk(struct ip_fw_args *args)
struct ucred *ucred_cache = NULL;
#endif
int ucred_lookup = 0;
/*
* oif | args->oif If NULL, ipfw_chk has been called on the
* inbound path (ether_input, ip_input).
* If non-NULL, ipfw_chk has been called on the outbound path
* (ether_output, ip_output).
*/
struct ifnet *oif = args->oif;
int f_pos = 0; /* index of current rule in the array */
int retval = 0;
struct ifnet *oif, *iif;
/*
* hlen The length of the IP header.
@ -1724,6 +1713,15 @@ do { \
f_pos = 0;
}
if (args->flags & IPFW_ARGS_IN) {
iif = args->ifp;
oif = NULL;
} else {
MPASS(args->flags & IPFW_ARGS_OUT);
iif = m->m_pkthdr.rcvif;
oif = args->ifp;
}
/*
* Now scan the rules, and parse microinstructions for each rule.
* We have two nested loops and an inner switch. Sometimes we
@ -1820,8 +1818,8 @@ do { \
break;
case O_RECV:
match = iface_match(m->m_pkthdr.rcvif,
(ipfw_insn_if *)cmd, chain, &tablearg);
match = iface_match(iif, (ipfw_insn_if *)cmd,
chain, &tablearg);
break;
case O_XMIT:
@ -1830,9 +1828,8 @@ do { \
break;
case O_VIA:
match = iface_match(oif ? oif :
m->m_pkthdr.rcvif, (ipfw_insn_if *)cmd,
chain, &tablearg);
match = iface_match(args->ifp,
(ipfw_insn_if *)cmd, chain, &tablearg);
break;
case O_MACADDR2:
@ -2334,7 +2331,7 @@ do { \
case O_LOG:
ipfw_log(chain, f, hlen, args, m,
oif, offset | ip6f_mf, tablearg, ip);
offset | ip6f_mf, tablearg, ip);
match = 1;
break;
@ -2344,16 +2341,14 @@ do { \
case O_VERREVPATH:
/* Outgoing packets automatically pass/match */
match = ((oif != NULL) ||
(m->m_pkthdr.rcvif == NULL) ||
match = (args->flags & IPFW_ARGS_OUT ||
(
#ifdef INET6
is_ipv6 ?
verify_path6(&(args->f_id.src_ip6),
m->m_pkthdr.rcvif, args->f_id.fib) :
iif, args->f_id.fib) :
#endif
verify_path(src_ip, m->m_pkthdr.rcvif,
args->f_id.fib)));
verify_path(src_ip, iif, args->f_id.fib)));
break;
case O_VERSRCREACH:
@ -2379,12 +2374,10 @@ do { \
match =
#ifdef INET6
is_ipv6 ? verify_path6(
&(args->f_id.src_ip6),
m->m_pkthdr.rcvif,
&(args->f_id.src_ip6), iif,
args->f_id.fib) :
#endif
verify_path(src_ip,
m->m_pkthdr.rcvif,
verify_path(src_ip, iif,
args->f_id.fib);
else
match = 1;

View File

@ -1173,12 +1173,9 @@ dyn_getscopeid(const struct ip_fw_args *args)
* determine the scope zone id to resolve address scope ambiguity.
*/
if (IN6_IS_ADDR_LINKLOCAL(&args->f_id.src_ip6) ||
IN6_IS_ADDR_LINKLOCAL(&args->f_id.dst_ip6)) {
MPASS(args->oif != NULL ||
args->m->m_pkthdr.rcvif != NULL);
return (in6_getscopezone(args->oif != NULL ? args->oif:
args->m->m_pkthdr.rcvif, IPV6_ADDR_SCOPE_LINKLOCAL));
}
IN6_IS_ADDR_LINKLOCAL(&args->f_id.dst_ip6))
return (in6_getscopezone(args->ifp, IPV6_ADDR_SCOPE_LINKLOCAL));
return (0);
}

View File

@ -99,7 +99,7 @@ __FBSDID("$FreeBSD$");
*/
void
ipfw_log(struct ip_fw_chain *chain, struct ip_fw *f, u_int hlen,
struct ip_fw_args *args, struct mbuf *m, struct ifnet *oif,
struct ip_fw_args *args, struct mbuf *m,
u_short offset, uint32_t tablearg, struct ip *ip)
{
char *action;
@ -405,19 +405,14 @@ ipfw_log(struct ip_fw_chain *chain, struct ip_fw *f, u_int hlen,
}
}
#ifdef __FreeBSD__
if (oif || m->m_pkthdr.rcvif)
log(LOG_SECURITY | LOG_INFO,
"ipfw: %d %s %s %s via %s%s\n",
f ? f->rulenum : -1,
action, proto, oif ? "out" : "in",
oif ? oif->if_xname : m->m_pkthdr.rcvif->if_xname,
fragment);
else
log(LOG_SECURITY | LOG_INFO, "ipfw: %d %s %s %s via %s%s\n",
f ? f->rulenum : -1, action, proto,
args->flags & IPFW_ARGS_OUT ? "out" : "in", args->ifp->if_xname,
fragment);
#else
log(LOG_SECURITY | LOG_INFO, "ipfw: %d %s %s [no if info]%s\n",
f ? f->rulenum : -1, action, proto, fragment);
#endif
log(LOG_SECURITY | LOG_INFO,
"ipfw: %d %s %s [no if info]%s\n",
f ? f->rulenum : -1,
action, proto, fragment);
if (limit_reached)
log(LOG_SECURITY | LOG_NOTICE,
"ipfw: limit %d reached on entry %d\n",

View File

@ -347,7 +347,7 @@ ipfw_nat(struct ip_fw_args *args, struct cfg_nat *t, struct mbuf *m)
/* Check if this is 'global' instance */
if (t == NULL) {
if (args->oif == NULL) {
if (args->flags & IPFW_ARGS_IN) {
/* Wrong direction, skip processing */
args->m = mcl;
return (IP_FW_NAT);
@ -374,7 +374,7 @@ ipfw_nat(struct ip_fw_args *args, struct cfg_nat *t, struct mbuf *m)
return (IP_FW_NAT);
}
} else {
if (args->oif == NULL)
if (args->flags & IPFW_ARGS_IN)
retval = LibAliasIn(t->lib, c,
mcl->m_len + M_TRAILINGSPACE(mcl));
else
@ -391,7 +391,8 @@ ipfw_nat(struct ip_fw_args *args, struct cfg_nat *t, struct mbuf *m)
* PKT_ALIAS_DENY_INCOMING flag is set.
*/
if (retval == PKT_ALIAS_ERROR ||
(args->oif == NULL && (retval == PKT_ALIAS_UNRESOLVED_FRAGMENT ||
((args->flags & IPFW_ARGS_IN) &&
(retval == PKT_ALIAS_UNRESOLVED_FRAGMENT ||
(retval == PKT_ALIAS_IGNORED &&
(t->mode & PKT_ALIAS_DENY_INCOMING) != 0)))) {
/* XXX - should i add some logging? */

View File

@ -118,17 +118,16 @@ SYSEND
* The packet may be consumed.
*/
static pfil_return_t
ipfw_check_packet(struct mbuf **m0, struct ifnet *ifp, int dir,
ipfw_check_packet(struct mbuf **m0, struct ifnet *ifp, int flags,
void *ruleset __unused, struct inpcb *inp)
{
struct ip_fw_args args;
struct m_tag *tag;
pfil_return_t ret;
int ipfw;
int ipfw, dir;
/* convert dir to IPFW values */
dir = (dir & PFIL_IN) ? DIR_IN : DIR_OUT;
args.flags = 0;
args.flags = (flags & PFIL_IN) ? IPFW_ARGS_IN : IPFW_ARGS_OUT;
dir = (flags & PFIL_IN) ? DIR_IN : DIR_OUT;
again:
/*
* extract and remove the tag if present. If we are left
@ -144,7 +143,7 @@ ipfw_check_packet(struct mbuf **m0, struct ifnet *ifp, int dir,
}
args.m = *m0;
args.oif = dir == DIR_OUT ? ifp : NULL;
args.ifp = ifp;
args.inp = inp;
ipfw = ipfw_chk(&args);
@ -198,7 +197,7 @@ ipfw_check_packet(struct mbuf **m0, struct ifnet *ifp, int dir,
* m_tag_find. Outgoing packets may be tagged, so we
* reuse the tag if present.
*/
tag = (dir == DIR_IN) ? NULL :
tag = (flags & PFIL_IN) ? NULL :
m_tag_find(*m0, PACKET_TAG_IPFORWARD, NULL);
if (tag != NULL) {
m_tag_unlink(*m0, tag);
@ -346,6 +345,7 @@ ipfw_check_frame(struct mbuf **m0, struct ifnet *ifp, int dir,
int i;
args.flags = IPFW_ARGS_ETHER;
args.flags |= (dir & PFIL_IN) ? IPFW_ARGS_IN : IPFW_ARGS_OUT;
again:
/* fetch start point from rule, if any. remove the tag if present. */
mtag = m_tag_locate(*m0, MTAG_IPFW_RULE, 0, NULL);
@ -372,7 +372,7 @@ ipfw_check_frame(struct mbuf **m0, struct ifnet *ifp, int dir,
m_adj(m, ETHER_HDR_LEN); /* strip ethernet header */
args.m = m; /* the packet we are looking at */
args.oif = dir & PFIL_OUT ? ifp: NULL; /* destination, if any */
args.ifp = ifp;
args.eh = &save_eh; /* MAC header for bridged/MAC packets */
args.inp = inp; /* used by ipfw uid/gid/jail rules */
i = ipfw_chk(&args);

View File

@ -85,12 +85,19 @@ struct _ip6dn_args {
*/
struct ip_fw_args {
uint32_t flags;
#define IPFW_ARGS_ETHER 0x0001 /* has valid ethernet header */
#define IPFW_ARGS_NH4 0x0002 /* has IPv4 next hop in hopstore */
#define IPFW_ARGS_NH6 0x0004 /* has IPv6 next hop in hopstore */
#define IPFW_ARGS_NH4PTR 0x0008 /* has IPv4 next hop in next_hop */
#define IPFW_ARGS_NH6PTR 0x0010 /* has IPv6 next hop in next_hop6 */
#define IPFW_ARGS_REF 0x0020 /* has valid ipfw_rule_ref */
#define IPFW_ARGS_ETHER 0x00010000 /* valid ethernet header */
#define IPFW_ARGS_NH4 0x00020000 /* IPv4 next hop in hopstore */
#define IPFW_ARGS_NH6 0x00040000 /* IPv6 next hop in hopstore */
#define IPFW_ARGS_NH4PTR 0x00080000 /* IPv4 next hop in next_hop */
#define IPFW_ARGS_NH6PTR 0x00100000 /* IPv6 next hop in next_hop6 */
#define IPFW_ARGS_REF 0x00200000 /* valid ipfw_rule_ref */
#define IPFW_ARGS_IN 0x00400000 /* called on input */
#define IPFW_ARGS_OUT 0x00800000 /* called on output */
#define IPFW_ARGS_IP4 0x01000000 /* belongs to v4 ISR */
#define IPFW_ARGS_IP6 0x02000000 /* belongs to v6 ISR */
#define IPFW_ARGS_DROP 0x04000000 /* drop it (dummynet) */
#define IPFW_ARGS_LENMASK 0x0000ffff /* length of data in *mem */
#define IPFW_ARGS_LENGTH(f) ((f) & IPFW_ARGS_LENMASK)
/*
* On return, it points to the matching rule.
* On entry, rule.slot > 0 means the info is valid and
@ -100,7 +107,7 @@ struct ip_fw_args {
*/
struct ipfw_rule_ref rule; /* match/restart info */
struct ifnet *oif; /* output interface */
struct ifnet *ifp; /* input/output interface */
struct inpcb *inp;
union {
/*
@ -181,7 +188,7 @@ void ipfw_bpf_init(int);
void ipfw_bpf_uninit(int);
void ipfw_bpf_mtap2(void *, u_int, struct mbuf *);
void ipfw_log(struct ip_fw_chain *chain, struct ip_fw *f, u_int hlen,
struct ip_fw_args *args, struct mbuf *m, struct ifnet *oif,
struct ip_fw_args *args, struct mbuf *m,
u_short offset, uint32_t tablearg, struct ip *ip);
VNET_DECLARE(u_int64_t, norule_counter);
#define V_norule_counter VNET(norule_counter)