o Clean up interface between ip_fw_chk() and its callers:

- ip_fw_chk() returns action as function return value. Field retval is
  removed from args structure. Action is not flag any more. It is one
  of integer constants.
- Any action-specific cookies are returned either in new "cookie" field
  in args structure (dummynet, future netgraph glue), or in mbuf tag
  attached to packet (divert, tee, some future action).

o Convert parsing of return value from ip_fw_chk() in ipfw_check_{in,out}()
  to a switch structure, so that the functions are more readable, and a future
  actions can be added with less modifications.

Approved by:	andre
MFC after:	2 months
This commit is contained in:
Gleb Smirnoff 2005-01-14 09:00:46 +00:00
parent e50508df66
commit 6c69a7c30b
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=140224
5 changed files with 120 additions and 89 deletions

View file

@ -1073,12 +1073,14 @@ bdg_forward(struct mbuf *m0, struct ifnet *dst)
if (m0 != NULL)
EH_RESTORE(m0); /* restore Ethernet header */
if ( (i & IP_FW_PORT_DENY_FLAG) || m0 == NULL) /* drop */
if (i == IP_FW_DENY) /* drop */
return m0;
KASSERT(m0 != NULL, ("bdg_forward: m0 is NULL"));
if (i == 0) /* a PASS rule. */
goto forward;
if (DUMMYNET_LOADED && (i & IP_FW_PORT_DYNT_FLAG)) {
if (DUMMYNET_LOADED && (i == IP_FW_DUMMYNET)) {
/*
* Pass the pkt to dummynet, which consumes it.
* If shared, make a copy and keep the original.
@ -1095,7 +1097,7 @@ bdg_forward(struct mbuf *m0, struct ifnet *dst)
}
args.oif = real_dst;
ip_dn_io_ptr(m, (i & 0xffff),DN_TO_BDG_FWD, &args);
ip_dn_io_ptr(m, args.cookie, DN_TO_BDG_FWD, &args);
return m0;
}
/*

View file

@ -440,13 +440,15 @@ ether_ipfw_chk(struct mbuf **m0, struct ifnet *dst,
*m0 = m;
*rule = args.rule;
if ( (i & IP_FW_PORT_DENY_FLAG) || m == NULL) /* drop */
if (i == IP_FW_DENY) /* drop */
return 0;
if (i == 0) /* a PASS rule. */
KASSERT(m != NULL, ("ether_ipfw_chk: m is NULL"));
if (i == IP_FW_PASS) /* a PASS rule. */
return 1;
if (DUMMYNET_LOADED && (i & IP_FW_PORT_DYNT_FLAG)) {
if (DUMMYNET_LOADED && (i == IP_FW_DUMMYNET)) {
/*
* Pass the pkt to dummynet, which consumes it.
* If shared, make a copy and keep the original.
@ -462,7 +464,7 @@ ether_ipfw_chk(struct mbuf **m0, struct ifnet *dst,
*/
*m0 = NULL ;
}
ip_dn_io_ptr(m, (i & 0xffff),
ip_dn_io_ptr(m, args.cookie,
dst ? DN_TO_ETH_OUT: DN_TO_ETH_DEMUX, &args);
return 0;
}

View file

@ -417,9 +417,17 @@ typedef struct _ipfw_table {
*/
#ifdef _KERNEL
#define IP_FW_PORT_DYNT_FLAG 0x00010000
#define IP_FW_PORT_TEE_FLAG 0x00020000
#define IP_FW_PORT_DENY_FLAG 0x00040000
/* Return values from ipfw_chk() */
enum {
IP_FW_PASS = 0,
IP_FW_DENY,
IP_FW_DIVERT,
IP_FW_TEE,
IP_FW_DUMMYNET,
IP_FW_NETGRAPH,
};
/* flags for divert mtag */
#define IP_FW_DIVERT_LOOPBACK_FLAG 0x00080000
#define IP_FW_DIVERT_OUTPUT_FLAG 0x00100000
@ -438,7 +446,7 @@ struct ip_fw_args {
int flags; /* for dummynet */
struct ipfw_flow_id f_id; /* grabbed from IP header */
u_int32_t retval;
u_int32_t cookie; /* a cookie depending on rule action */
struct inpcb *inp;
};

View file

@ -1695,20 +1695,17 @@ check_uidgid(ipfw_insn_u32 *insn,
* args->rule Pointer to the last matching rule (in/out)
* args->next_hop Socket we are forwarding to (out).
* args->f_id Addresses grabbed from the packet (out)
* args->cookie a cookie depending on rule action
*
* Return value:
*
* IP_FW_PORT_DENY_FLAG the packet must be dropped.
* 0 The packet is to be accepted and routed normally OR
* the packet was denied/rejected and has been dropped;
* in the latter case, *m is equal to NULL upon return.
* port Divert the packet to port, with these caveats:
* IP_FW_PASS the packet must be accepted
* IP_FW_DENY the packet must be dropped
* IP_FW_DIVERT divert packet, port in m_tag
* IP_FW_TEE tee packet, port in m_tag
* IP_FW_DUMMYNET to dummynet, pipe in args->cookie
* IP_FW_NETGRAPH into netgraph, cookie args->cookie
*
* - If IP_FW_PORT_TEE_FLAG is set, tee the packet instead
* of diverting it (ie, 'ipfw tee').
*
* - If IP_FW_PORT_DYNT_FLAG is set, interpret the lower
* 16 bits as a dummynet pipe number instead of diverting
*/
int
@ -1806,7 +1803,7 @@ ipfw_chk(struct ip_fw_args *args)
struct m_tag *mtag;
if (m->m_flags & M_SKIP_FIREWALL)
return 0; /* accept */
return (IP_FW_PASS); /* accept */
/*
* dyn_dir = MATCH_UNKNOWN when rules unchecked,
* MATCH_NONE when checked and not matched (q = NULL),
@ -1904,7 +1901,7 @@ ipfw_chk(struct ip_fw_args *args)
*/
if (fw_one_pass) {
IPFW_RUNLOCK(chain);
return 0;
return (IP_FW_PASS);
}
f = args->rule->next_rule;
@ -1921,13 +1918,13 @@ ipfw_chk(struct ip_fw_args *args)
if (args->eh == NULL && skipto != 0) {
if (skipto >= IPFW_DEFAULT_RULE) {
IPFW_RUNLOCK(chain);
return(IP_FW_PORT_DENY_FLAG); /* invalid */
return (IP_FW_DENY); /* invalid */
}
while (f && f->rulenum <= skipto)
f = f->next;
if (f == NULL) { /* drop packet */
IPFW_RUNLOCK(chain);
return(IP_FW_PORT_DENY_FLAG);
return (IP_FW_DENY);
}
}
}
@ -2408,7 +2405,7 @@ ipfw_chk(struct ip_fw_args *args)
case O_KEEP_STATE:
if (install_state(f,
(ipfw_insn_limit *)cmd, args)) {
retval = IP_FW_PORT_DENY_FLAG;
retval = IP_FW_DENY;
goto done; /* error/limit violation */
}
match = 1;
@ -2460,7 +2457,8 @@ ipfw_chk(struct ip_fw_args *args)
case O_PIPE:
case O_QUEUE:
args->rule = f; /* report matching rule */
retval = cmd->arg1 | IP_FW_PORT_DYNT_FLAG;
args->cookie = cmd->arg1;
retval = IP_FW_DUMMYNET;
goto done;
case O_DIVERT:
@ -2476,15 +2474,14 @@ ipfw_chk(struct ip_fw_args *args)
/* XXX statistic */
/* drop packet */
IPFW_RUNLOCK(chain);
return IP_FW_PORT_DENY_FLAG;
return (IP_FW_DENY);
}
dt = (struct divert_tag *)(mtag+1);
dt->cookie = f->rulenum;
dt->info = (cmd->opcode == O_DIVERT) ?
cmd->arg1 :
cmd->arg1 | IP_FW_PORT_TEE_FLAG;
dt->info = cmd->arg1;
m_tag_prepend(m, mtag);
retval = dt->info;
retval = (cmd->opcode == O_DIVERT) ?
IP_FW_DIVERT : IP_FW_TEE;
goto done;
}
@ -2518,7 +2515,7 @@ ipfw_chk(struct ip_fw_args *args)
}
/* FALLTHROUGH */
case O_DENY:
retval = IP_FW_PORT_DENY_FLAG;
retval = IP_FW_DENY;
goto done;
case O_FORWARD_IP:
@ -2527,7 +2524,7 @@ ipfw_chk(struct ip_fw_args *args)
if (!q || dyn_dir == MATCH_FORWARD)
args->next_hop =
&((ipfw_insn_sa *)cmd)->sa;
retval = 0;
retval = IP_FW_PASS;
goto done;
default:
@ -2552,7 +2549,7 @@ next_rule:; /* try next rule */
} /* end of outer for, scan rules */
printf("ipfw: ouch!, skip past end of rules, denying packet\n");
IPFW_RUNLOCK(chain);
return(IP_FW_PORT_DENY_FLAG);
return (IP_FW_DENY);
done:
/* Update statistics */
@ -2560,12 +2557,12 @@ next_rule:; /* try next rule */
f->bcnt += pktlen;
f->timestamp = time_second;
IPFW_RUNLOCK(chain);
return retval;
return (retval);
pullup_failed:
if (fw_verbose)
printf("ipfw: pullup failed\n");
return(IP_FW_PORT_DENY_FLAG);
return (IP_FW_DENY);
}
/*

View file

@ -82,6 +82,7 @@ ipfw_check_in(void *arg, struct mbuf **m0, struct ifnet *ifp, int dir,
struct m_tag *dn_tag;
int ipfw = 0;
int divert;
int tee;
#ifdef IPFIREWALL_FORWARD
struct m_tag *fwd_tag;
#endif
@ -108,35 +109,17 @@ ipfw_check_in(void *arg, struct mbuf **m0, struct ifnet *ifp, int dir,
args.inp = inp;
ipfw = ipfw_chk(&args);
*m0 = args.m;
tee = 0;
if ((ipfw & IP_FW_PORT_DENY_FLAG) || *m0 == NULL)
goto drop;
KASSERT(*m0 != NULL || ipfw == IP_FW_DENY, ("%s: m0 is NULL",
__func__));
if (ipfw == 0 && args.next_hop == NULL)
goto pass;
if (DUMMYNET_LOADED && (ipfw & IP_FW_PORT_DYNT_FLAG) != 0) {
ip_dn_io_ptr(*m0, ipfw & 0xffff, DN_TO_IP_IN, &args);
*m0 = NULL;
return 0; /* packet consumed */
}
if (ipfw != 0 && (ipfw & IP_FW_PORT_DYNT_FLAG) == 0) {
if ((ipfw & IP_FW_PORT_TEE_FLAG) != 0)
divert = ipfw_divert(m0, DIV_DIR_IN, 1);
else
divert = ipfw_divert(m0, DIV_DIR_IN, 0);
/* tee should continue again with the firewall. */
if (divert) {
*m0 = NULL;
return 0; /* packet consumed */
} else
goto again; /* continue with packet */
}
switch (ipfw) {
case IP_FW_PASS:
if (args.next_hop == NULL)
goto pass;
#ifdef IPFIREWALL_FORWARD
if (ipfw == 0 && args.next_hop != NULL) {
fwd_tag = m_tag_get(PACKET_TAG_IPFORWARD,
sizeof(struct sockaddr_in), M_NOWAIT);
if (fwd_tag == NULL)
@ -147,8 +130,35 @@ ipfw_check_in(void *arg, struct mbuf **m0, struct ifnet *ifp, int dir,
if (in_localip(args.next_hop->sin_addr))
(*m0)->m_flags |= M_FASTFWD_OURS;
goto pass;
}
#endif
break; /* not reached */
case IP_FW_DENY:
goto drop;
break; /* not reached */
case IP_FW_DUMMYNET:
if (!DUMMYNET_LOADED)
goto drop;
ip_dn_io_ptr(*m0, args.cookie, DN_TO_IP_IN, &args);
*m0 = NULL;
return 0; /* packet consumed */
case IP_FW_TEE:
tee = 1;
/* fall through */
case IP_FW_DIVERT:
divert = ipfw_divert(m0, DIV_DIR_IN, tee);
if (divert) {
*m0 = NULL;
return 0; /* packet consumed */
} else
goto again; /* continue with packet */
default:
KASSERT(0, ("%s: unknown retval", __func__));
}
drop:
if (*m0)
@ -167,6 +177,7 @@ ipfw_check_out(void *arg, struct mbuf **m0, struct ifnet *ifp, int dir,
struct m_tag *dn_tag;
int ipfw = 0;
int divert;
int tee;
#ifdef IPFIREWALL_FORWARD
struct m_tag *fwd_tag;
#endif
@ -194,34 +205,16 @@ ipfw_check_out(void *arg, struct mbuf **m0, struct ifnet *ifp, int dir,
args.inp = inp;
ipfw = ipfw_chk(&args);
*m0 = args.m;
tee = 0;
if ((ipfw & IP_FW_PORT_DENY_FLAG) || *m0 == NULL)
goto drop;
if (ipfw == 0 && args.next_hop == NULL)
goto pass;
if (DUMMYNET_LOADED && (ipfw & IP_FW_PORT_DYNT_FLAG) != 0) {
ip_dn_io_ptr(*m0, ipfw & 0xffff, DN_TO_IP_OUT, &args);
*m0 = NULL;
return 0; /* packet consumed */
}
if (ipfw != 0 && (ipfw & IP_FW_PORT_DYNT_FLAG) == 0) {
if ((ipfw & IP_FW_PORT_TEE_FLAG) != 0)
divert = ipfw_divert(m0, DIV_DIR_OUT, 1);
else
divert = ipfw_divert(m0, DIV_DIR_OUT, 0);
if (divert) {
*m0 = NULL;
return 0; /* packet consumed */
} else
goto again; /* continue with packet */
}
KASSERT(*m0 != NULL || ipfw == IP_FW_DENY, ("%s: m0 is NULL",
__func__));
switch (ipfw) {
case IP_FW_PASS:
if (args.next_hop == NULL)
goto pass;
#ifdef IPFIREWALL_FORWARD
if (ipfw == 0 && args.next_hop != NULL) {
/* Overwrite existing tag. */
fwd_tag = m_tag_find(*m0, PACKET_TAG_IPFORWARD, NULL);
if (fwd_tag == NULL) {
@ -237,8 +230,37 @@ ipfw_check_out(void *arg, struct mbuf **m0, struct ifnet *ifp, int dir,
if (in_localip(args.next_hop->sin_addr))
(*m0)->m_flags |= M_FASTFWD_OURS;
goto pass;
}
#endif
break; /* not reached */
case IP_FW_DENY:
goto drop;
break; /* not reached */
case IP_FW_DUMMYNET:
if (!DUMMYNET_LOADED)
break;
ip_dn_io_ptr(*m0, args.cookie, DN_TO_IP_OUT, &args);
*m0 = NULL;
return 0; /* packet consumed */
break;
case IP_FW_TEE:
tee = 1;
/* fall through */
case IP_FW_DIVERT:
divert = ipfw_divert(m0, DIV_DIR_OUT, tee);
if (divert) {
*m0 = NULL;
return 0; /* packet consumed */
} else
goto again; /* continue with packet */
default:
KASSERT(0, ("%s: unknown retval", __func__));
}
drop:
if (*m0)