diff --git a/sys/net/bridge.c b/sys/net/bridge.c index 101f752dc7a6..3a4b7aaac4cd 100644 --- a/sys/net/bridge.c +++ b/sys/net/bridge.c @@ -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; } /* diff --git a/sys/net/if_ethersubr.c b/sys/net/if_ethersubr.c index 2a0df50ccac0..590e551cb293 100644 --- a/sys/net/if_ethersubr.c +++ b/sys/net/if_ethersubr.c @@ -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; } diff --git a/sys/netinet/ip_fw.h b/sys/netinet/ip_fw.h index e73d7019cb20..de9295119675 100644 --- a/sys/netinet/ip_fw.h +++ b/sys/netinet/ip_fw.h @@ -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; }; diff --git a/sys/netinet/ip_fw2.c b/sys/netinet/ip_fw2.c index 1ac1eb497215..0973a46ee042 100644 --- a/sys/netinet/ip_fw2.c +++ b/sys/netinet/ip_fw2.c @@ -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 @@ after_ip_checks: */ if (fw_one_pass) { IPFW_RUNLOCK(chain); - return 0; + return (IP_FW_PASS); } f = args->rule->next_rule; @@ -1921,13 +1918,13 @@ after_ip_checks: 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 @@ check_body: 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 @@ check_body: 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 @@ check_body: /* 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 @@ check_body: } /* FALLTHROUGH */ case O_DENY: - retval = IP_FW_PORT_DENY_FLAG; + retval = IP_FW_DENY; goto done; case O_FORWARD_IP: @@ -2527,7 +2524,7 @@ check_body: 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 @@ done: 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); } /* diff --git a/sys/netinet/ip_fw_pfil.c b/sys/netinet/ip_fw_pfil.c index 44e86521a1a6..d186aab94c8e 100644 --- a/sys/netinet/ip_fw_pfil.c +++ b/sys/netinet/ip_fw_pfil.c @@ -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 @@ again: 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 @@ again: 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 @@ again: 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 @@ again: 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)