From owner-svn-src-user@FreeBSD.ORG Thu Dec 31 18:28:40 2009 Return-Path: Delivered-To: svn-src-user@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 7A4FC1065698; Thu, 31 Dec 2009 18:28:40 +0000 (UTC) (envelope-from luigi@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 6623A8FC18; Thu, 31 Dec 2009 18:28:40 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id nBVISeql073688; Thu, 31 Dec 2009 18:28:40 GMT (envelope-from luigi@svn.freebsd.org) Received: (from luigi@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id nBVISeOm073676; Thu, 31 Dec 2009 18:28:40 GMT (envelope-from luigi@svn.freebsd.org) Message-Id: <200912311828.nBVISeOm073676@svn.freebsd.org> From: Luigi Rizzo Date: Thu, 31 Dec 2009 18:28:40 +0000 (UTC) To: src-committers@freebsd.org, svn-src-user@freebsd.org X-SVN-Group: user MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r201346 - in user/luigi/ipfw3-head/sys: net netgraph netinet netinet/ipfw X-BeenThere: svn-src-user@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the experimental " user" src tree" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 31 Dec 2009 18:28:40 -0000 Author: luigi Date: Thu Dec 31 18:28:40 2009 New Revision: 201346 URL: http://svn.freebsd.org/changeset/base/201346 Log: snapshot (probably not compiling) Modified: user/luigi/ipfw3-head/sys/net/if_bridge.c user/luigi/ipfw3-head/sys/net/if_ethersubr.c user/luigi/ipfw3-head/sys/netgraph/ng_ipfw.c user/luigi/ipfw3-head/sys/netinet/ip_divert.c user/luigi/ipfw3-head/sys/netinet/ip_divert.h user/luigi/ipfw3-head/sys/netinet/ip_dummynet.h user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dummynet.c user/luigi/ipfw3-head/sys/netinet/ipfw/ip_fw2.c user/luigi/ipfw3-head/sys/netinet/ipfw/ip_fw_dynamic.c user/luigi/ipfw3-head/sys/netinet/ipfw/ip_fw_pfil.c user/luigi/ipfw3-head/sys/netinet/ipfw/ip_fw_private.h Modified: user/luigi/ipfw3-head/sys/net/if_bridge.c ============================================================================== --- user/luigi/ipfw3-head/sys/net/if_bridge.c Thu Dec 31 18:02:48 2009 (r201345) +++ user/luigi/ipfw3-head/sys/net/if_bridge.c Thu Dec 31 18:28:40 2009 (r201346) @@ -3040,25 +3040,26 @@ bridge_pfil(struct mbuf **mp, struct ifn } /* XXX this section is also in if_ethersubr.c */ - if (V_ip_fw_chk_ptr && pfil_ipfw != 0 && dir == PFIL_OUT && ifp != NULL) { + // XXX PFIL_OUT or DIR_OUT ? + if (V_ip_fw_chk_ptr && pfil_ipfw != 0 && + dir == PFIL_OUT && ifp != NULL) { struct m_tag *mtag; error = -1; - mtag = m_tag_find(*mp, PACKET_TAG_DUMMYNET, NULL); + /* fetch the start point from existing tags, if any */ + mtag = m_tag_locate(*mp, MTAG_IPFW_RULE, 0, NULL); if (mtag == NULL) { - args.slot = 0; + args.rule.slot = 0; } else { struct dn_pkt_tag *dn_tag; + /* XXX can we free the tag after use ? */ mtag->m_tag_id = PACKET_TAG_NONE; dn_tag = (struct dn_pkt_tag *)(mtag + 1); - if (dn_tag->slot != 0 && V_fw_one_pass) - /* packet already partially processed */ + /* packet already partially processed ? */ + if (dn_tag->rule.slot != 0 && V_fw_one_pass) goto ipfwpass; - args.slot = dn_tag->slot; /* next rule to use */ - args.chain_id = dn_tag->chain_id; - args.rulenum = dn_tag->rulenum; - args.rule_id = dn_tag->rule_id; + args.rule = dn_tag->rule; } args.m = *mp; Modified: user/luigi/ipfw3-head/sys/net/if_ethersubr.c ============================================================================== --- user/luigi/ipfw3-head/sys/net/if_ethersubr.c Thu Dec 31 18:02:48 2009 (r201345) +++ user/luigi/ipfw3-head/sys/net/if_ethersubr.c Thu Dec 31 18:28:40 2009 (r201346) @@ -469,21 +469,20 @@ ether_ipfw_chk(struct mbuf **m0, struct struct ip_fw_args args; struct m_tag *mtag; - mtag = m_tag_find(*m0, PACKET_TAG_DUMMYNET, NULL); + /* fetch start point from rule, if any */ + mtag = m_tag_locate(*m0, MTAG_IPFW_RULE, 0, NULL); if (mtag == NULL) { - args.slot = 0; + args.rule.slot = 0; } else { struct dn_pkt_tag *dn_tag; + /* XXX can we free it after use ? */ mtag->m_tag_id = PACKET_TAG_NONE; dn_tag = (struct dn_pkt_tag *)(mtag + 1); - if (dn_tag->slot != 0 && V_fw_one_pass) + if (dn_tag->rule.slot != 0 && V_fw_one_pass) /* dummynet packet, already partially processed */ return (1); - args.slot = dn_tag->slot; /* matching rule to restart */ - args.rulenum = dn_tag->rulenum; - args.rule_id = dn_tag->rule_id; - args.chain_id = dn_tag->chain_id; + args.rule = dn_tag->rule; } /* Modified: user/luigi/ipfw3-head/sys/netgraph/ng_ipfw.c ============================================================================== --- user/luigi/ipfw3-head/sys/netgraph/ng_ipfw.c Thu Dec 31 18:02:48 2009 (r201345) +++ user/luigi/ipfw3-head/sys/netgraph/ng_ipfw.c Thu Dec 31 18:28:40 2009 (r201346) @@ -221,19 +221,20 @@ ng_ipfw_findhook1(node_p node, u_int16_t static int ng_ipfw_rcvdata(hook_p hook, item_p item) { - struct ng_ipfw_tag *ngit; + struct ipfw_start_info *ngit; struct mbuf *m; NGI_GET_M(item, m); NG_FREE_ITEM(item); - if ((ngit = (struct ng_ipfw_tag *)m_tag_locate(m, NGM_IPFW_COOKIE, 0, - NULL)) == NULL) { + ngit = (struct ipfw_start_info *) + m_tag_locate(m, NGM_IPFW_COOKIE, 0, NULL); + if (ngit == NULL) { NG_FREE_M(m); return (EINVAL); /* XXX: find smth better */ }; - switch (ngit->dir) { + switch (ngit->info) { case DIR_OUT: { struct ip *ip; @@ -263,7 +264,7 @@ static int ng_ipfw_input(struct mbuf **m0, int dir, struct ip_fw_args *fwa, int tee) { struct mbuf *m; - struct ng_ipfw_tag *ngit; + struct ipfw_start_info *ngit; struct ip *ip; hook_p hook; int error = 0; @@ -284,21 +285,21 @@ ng_ipfw_input(struct mbuf **m0, int dir, * a copy of a packet and forward it into netgraph without a tag. */ if (tee == 0) { + struct m_tag *tag; + struct ipfw_start_info *ngit; m = *m0; *m0 = NULL; /* it belongs now to netgraph */ - if ((ngit = (struct ng_ipfw_tag *)m_tag_alloc(NGM_IPFW_COOKIE, - 0, TAGSIZ, M_NOWAIT|M_ZERO)) == NULL) { + tag = m_tag_alloc(NGM_IPFW_COOKIE, sizeof(*mt), + M_NOWAIT|M_ZERO); + if (tagn == NULL) { m_freem(m); return (ENOMEM); } - ngit->slot = fwa->slot; - ngit->rulenum = fwa->rulenum; - ngit->rule_id = fwa->rule_id; - ngit->chain_id = fwa->chain_id; - ngit->dir = dir; -// ngit->ifp = fwa->oif; /* XXX do we use it ? */ - m_tag_prepend(m, &ngit->mt); + ngit = (struct ipfw_start_info *)(tag + 1); + *ngit = fwa->start + ngit->info = dir; + m_tag_prepend(m, tag); } else if ((m = m_dup(*m0, M_DONTWAIT)) == NULL) Modified: user/luigi/ipfw3-head/sys/netinet/ip_divert.c ============================================================================== --- user/luigi/ipfw3-head/sys/netinet/ip_divert.c Thu Dec 31 18:02:48 2009 (r201345) +++ user/luigi/ipfw3-head/sys/netinet/ip_divert.c Thu Dec 31 18:28:40 2009 (r201346) @@ -72,10 +72,10 @@ __FBSDID("$FreeBSD$"); #include #include #include -#include #include #include #include +#include #ifdef SCTP #include #endif @@ -301,6 +301,9 @@ divert_packet(struct mbuf *m, int incomi /* Put packet on socket queue, if any */ sa = NULL; nport = htons((u_int16_t)divert_info(mtag)); + printf("divert rule %d %s to port %d\n", divsrc.sin_port, + incoming ? "in" : "out", + ntohs(nport)); INP_INFO_RLOCK(&V_divcbinfo); LIST_FOREACH(inp, &V_divcb, inp_list) { /* XXX why does only one socket match? */ @@ -339,7 +342,7 @@ div_output(struct socket *so, struct mbu struct mbuf *control) { struct m_tag *mtag; - struct divert_tag *dt; + struct ipfw_rule_ref *dt; int error = 0; struct mbuf *options; @@ -354,23 +357,35 @@ div_output(struct socket *so, struct mbu if (control) m_freem(control); /* XXX */ - if ((mtag = m_tag_find(m, PACKET_TAG_DIVERT, NULL)) == NULL) { - mtag = m_tag_get(PACKET_TAG_DIVERT, sizeof(struct divert_tag), - M_NOWAIT | M_ZERO); + mtag = m_tag_locate(m, MTAG_IPFW_RULE, 0, NULL); + if (mtag == NULL) { + /* this should be normal */ + printf("create divert tag\n"); + mtag = m_tag_alloc(MTAG_IPFW_RULE, 0, + sizeof(struct ipfw_rule_ref), M_NOWAIT | M_ZERO); if (mtag == NULL) { error = ENOBUFS; goto cantsend; } - dt = (struct divert_tag *)(mtag+1); m_tag_prepend(m, mtag); - } else - dt = (struct divert_tag *)(mtag+1); + } + dt = (struct ipfw_rule_ref *)(mtag+1); + printf("%s sin %p dst rule %d addr 0x%x\n", __FUNCTION__, + sin, sin? sin->sin_port : -1, + sin ? sin->sin_addr.s_addr : 0xdeaddead); /* Loopback avoidance and state recovery */ if (sin) { int i; - dt->cookie = sin->sin_port; + /* set the starting point. We provide a non-zero slot, + * but a non_matching chain_id to skip that info and use + * the rulenum/rule_id. + */ + dt->slot = 1; /* dummy, chain_id is invalid */ + dt->chain_id = 0; + dt->rulenum = sin->sin_port+1; /* host format ? */ + dt->rule_id = 0; /* * Find receive interface with the given name, stuffed * (if it exists) in the sin_zero[] field. @@ -455,6 +470,7 @@ div_output(struct socket *so, struct mbu } } else { dt->info |= IP_FW_DIVERT_LOOPBACK_FLAG; + printf("divert to loopback\n"); if (m->m_pkthdr.rcvif == NULL) { /* * No luck with the name, check by IP address. @@ -467,6 +483,7 @@ div_output(struct socket *so, struct mbu sin->sin_port = 0; ifa = ifa_ifwithaddr((struct sockaddr *) sin); if (ifa == NULL) { + printf("%s ifa not found ???\n", __FUNCTION__); error = EADDRNOTAVAIL; goto cantsend; } Modified: user/luigi/ipfw3-head/sys/netinet/ip_divert.h ============================================================================== --- user/luigi/ipfw3-head/sys/netinet/ip_divert.h Thu Dec 31 18:02:48 2009 (r201345) +++ user/luigi/ipfw3-head/sys/netinet/ip_divert.h Thu Dec 31 18:28:40 2009 (r201346) @@ -45,10 +45,6 @@ SYSCTL_DECL(_net_inet_divert); /* * Divert socket definitions. */ -struct divert_tag { - u_int32_t info; /* port & flags */ - u_int16_t cookie; /* ipfw rule number */ -}; /* * Return the divert cookie associated with the mbuf; if any. @@ -56,13 +52,7 @@ struct divert_tag { static __inline u_int16_t divert_cookie(struct m_tag *mtag) { - return ((struct divert_tag *)(mtag+1))->cookie; -} -static __inline u_int16_t -divert_find_cookie(struct mbuf *m) -{ - struct m_tag *mtag = m_tag_find(m, PACKET_TAG_DIVERT, NULL); - return mtag ? divert_cookie(mtag) : 0; + return ((struct ipfw_rule_ref *)(mtag+1))->rulenum; } /* @@ -71,13 +61,7 @@ divert_find_cookie(struct mbuf *m) static __inline u_int32_t divert_info(struct m_tag *mtag) { - return ((struct divert_tag *)(mtag+1))->info; -} -static __inline u_int32_t -divert_find_info(struct mbuf *m) -{ - struct m_tag *mtag = m_tag_find(m, PACKET_TAG_DIVERT, NULL); - return mtag ? divert_info(mtag) : 0; + return ((struct ipfw_rule_ref *)(mtag+1))->info; } typedef void ip_divert_packet_t(struct mbuf *m, int incoming); Modified: user/luigi/ipfw3-head/sys/netinet/ip_dummynet.h ============================================================================== --- user/luigi/ipfw3-head/sys/netinet/ip_dummynet.h Thu Dec 31 18:02:48 2009 (r201345) +++ user/luigi/ipfw3-head/sys/netinet/ip_dummynet.h Thu Dec 31 18:28:40 2009 (r201346) @@ -114,11 +114,7 @@ struct dn_heap { * other forms of packet reinjection. */ struct dn_pkt_tag { - /* first part, reinject info */ - uint32_t slot; /* slot of next rule to use */ - uint32_t rulenum; /* matching rule number */ - uint32_t rule_id; /* matching rule id */ - uint32_t chain_id; /* ruleset id */ + struct ipfw_rule_ref rule; /* matching rule */ /* second part, dummynet specific */ int dn_dir; /* action when packet comes out. */ Modified: user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dummynet.c ============================================================================== --- user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dummynet.c Thu Dec 31 18:02:48 2009 (r201345) +++ user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dummynet.c Thu Dec 31 18:28:40 2009 (r201346) @@ -468,7 +468,7 @@ heap_free(struct dn_heap *h) */ static __inline void *dn_free_pkt(struct mbuf *m) { - m_freem(m); + FREE_PKT(m); return NULL; } @@ -975,8 +975,10 @@ dummynet_send(struct mbuf *m) dst = DIR_DROP; } else { struct dn_pkt_tag *pkt = dn_tag_get(m); + /* extract the dummynet info, rename the tag */ dst = pkt->dn_dir; ifp = pkt->ifp; + // XXX rename the tag } switch (dst) { @@ -1364,7 +1366,7 @@ dummynet_io(struct mbuf **m0, int dir, s struct dn_pipe *pipe; uint64_t len = m->m_pkthdr.len; struct dn_flow_queue *q = NULL; - int is_pipe = fwa->cookie & 0x8000000 ? 0 : 1; + int is_pipe = fwa->rule.info & 0x8000000 ? 0 : 1; KASSERT(m->m_nextpkt == NULL, ("dummynet_io: mbuf queue passed to dummynet")); @@ -1378,11 +1380,11 @@ dummynet_io(struct mbuf **m0, int dir, s * below can be simplified. */ if (is_pipe) { - pipe = locate_pipe(fwa->cookie & 0xffff); + pipe = locate_pipe(fwa->rule.info & 0xffff); if (pipe != NULL) fs = &(pipe->fs); } else - fs = locate_flowset(fwa->cookie & 0xffff); + fs = locate_flowset(fwa->rule.info & 0xffff); if (fs == NULL) goto dropit; /* This queue/pipe does not exist! */ @@ -1428,12 +1430,8 @@ dummynet_io(struct mbuf **m0, int dir, s * Ok, i can handle the pkt now... * Build and enqueue packet + parameters. */ - pkt->slot = fwa->slot; - pkt->rulenum = fwa->rulenum; - pkt->rule_id = fwa->rule_id; - pkt->chain_id = fwa->chain_id; + pkt->rule = fwa->rule; pkt->dn_dir = dir; - pkt->ifp = fwa->oif; if (q->head == NULL) Modified: user/luigi/ipfw3-head/sys/netinet/ipfw/ip_fw2.c ============================================================================== --- user/luigi/ipfw3-head/sys/netinet/ipfw/ip_fw2.c Thu Dec 31 18:02:48 2009 (r201345) +++ user/luigi/ipfw3-head/sys/netinet/ipfw/ip_fw2.c Thu Dec 31 18:28:40 2009 (r201346) @@ -560,7 +560,7 @@ send_reject6(struct ip_fw_args *args, in ip6_output(m0, NULL, NULL, 0, NULL, NULL, NULL); } - m_freem(m); + FREE_PKT(m); } else if (code != ICMP6_UNREACH_RST) { /* Send an ICMPv6 unreach. */ #if 0 /* @@ -576,7 +576,7 @@ send_reject6(struct ip_fw_args *args, in #endif icmp6_error(m, ICMP6_DST_UNREACH, code, 0); } else - m_freem(m); + FREE_PKT(m); args->m = NULL; } @@ -616,9 +616,9 @@ send_reject(struct ip_fw_args *args, int if (m != NULL) ip_output(m, NULL, NULL, 0, NULL, NULL); } - m_freem(args->m); + FREE_PKT(args->m); } else - m_freem(args->m); + FREE_PKT(args->m); args->m = NULL; } @@ -707,16 +707,18 @@ check_uidgid(ipfw_insn_u32 *insn, int pr } /* - * Helper function to write the matching rule into args + * Helper function to set args with info on the rule after the matching + * one. slot is precise, whereas we guess rule_id as they are + * assigned sequentially. */ static inline void set_match(struct ip_fw_args *args, int slot, struct ip_fw_chain *chain) { - args->chain_id = chain->id; - args->slot = slot + 1; /* we use 0 as a marker */ - args->rule_id = chain->map[slot]->id; - args->rulenum = chain->map[slot]->rulenum; + args->rule.chain_id = chain->id; + args->rule.slot = slot + 1; /* we use 0 as a marker */ + args->rule.rule_id = 1 + chain->map[slot]->id; + args->rule.rulenum = chain->map[slot]->rulenum; } /* @@ -741,7 +743,7 @@ set_match(struct ip_fw_args *args, int s * 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 + * args->rule.info a cookie depending on rule action * * Return value: * @@ -751,6 +753,8 @@ set_match(struct ip_fw_args *args, int s * 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 + * args->rule contains the matching rule, + * args->rule.info has additional information. * */ int @@ -1133,45 +1137,25 @@ do { \ IPFW_RUNLOCK(chain); return (IP_FW_PASS); /* accept */ } - /* XXX divert should be handled same as other tags */ - mtag = m_tag_find(m, PACKET_TAG_DIVERT, NULL); - if (args->slot) { + if (args->rule.slot) { /* * Packet has already been tagged as a result of a previous * match on rule args->rule aka args->rule_id (PIPE, QUEUE, - * REASS, NETGRAPH and similar, never a skipto). + * REASS, NETGRAPH, DIVERT/TEE...) * Validate the slot and continue from the next one * if still present, otherwise do a lookup. */ - if (V_fw_one_pass) { - IPFW_RUNLOCK(chain); - return (IP_FW_PASS); - } - f_pos = (args->chain_id == chain->id) ? - args->slot /* already incremented */ : - ipfw_find_rule(chain, args->rulenum, args->rule_id+1); + f_pos = (args->rule.chain_id == chain->id) ? + args->rule.slot : + ipfw_find_rule(chain, args->rule.rulenum, + args->rule.rule_id); } else { - /* - * Find the starting rule. It can be either the first - * one, or the one after divert_rule if asked so. - */ - int skipto = mtag ? divert_cookie(mtag) : 0; - f_pos = 0; - if (args->eh == NULL && skipto != 0) { - if (skipto >= IPFW_DEFAULT_RULE) { - IPFW_RUNLOCK(chain); - return (IP_FW_DENY); /* invalid */ - } - f_pos = ipfw_find_rule(chain, skipto+1, 0); - } } - /* reset divert rule to avoid confusion later */ - if (mtag) { +#if 0 // XXX to be fixed divinput_flags = divert_info(mtag) & (IP_FW_DIVERT_OUTPUT_FLAG | IP_FW_DIVERT_LOOPBACK_FLAG); - m_tag_delete(m, mtag); - } +#endif /* * Now scan the rules, and parse microinstructions for each rule. @@ -1761,12 +1745,13 @@ do { \ if (cmd->len & F_NOT) { /* `untag' action */ if (mtag != NULL) m_tag_delete(m, mtag); + match = 0; } else if (mtag == NULL) { if ((mtag = m_tag_alloc(MTAG_IPFW, tag, 0, M_NOWAIT)) != NULL) m_tag_prepend(m, mtag); + match = 1; } - match = (cmd->len & F_NOT) ? 0: 1; break; } @@ -1916,10 +1901,10 @@ do { \ case O_PIPE: case O_QUEUE: set_match(args, f_pos, chain); - args->cookie = (cmd->arg1 == IP_FW_TABLEARG) ? + args->rule.info = (cmd->arg1 == IP_FW_TABLEARG) ? tablearg : cmd->arg1; if (cmd->opcode == O_QUEUE) - args->cookie |= 0x80000000; + args->rule.info |= 0x80000000; retval = IP_FW_DUMMYNET; l = 0; /* exit inner loop */ done = 1; /* exit outer loop */ @@ -1932,23 +1917,9 @@ do { \ /* otherwise this is terminal */ l = 0; /* exit inner loop */ done = 1; /* exit outer loop */ - mtag = m_tag_get(PACKET_TAG_DIVERT, - sizeof(struct divert_tag), - M_NOWAIT); - if (mtag == NULL) { - retval = IP_FW_DENY; - } else { - struct divert_tag *dt; - dt = (struct divert_tag *)(mtag+1); - dt->cookie = f->rulenum; - if (cmd->arg1 == IP_FW_TABLEARG) - dt->info = tablearg; - else - dt->info = cmd->arg1; - m_tag_prepend(m, mtag); - retval = (cmd->opcode == O_DIVERT) ? - IP_FW_DIVERT : IP_FW_TEE; - } + set_match(args, f_pos, chain); + args->rule.info = (cmd->arg1 == IP_FW_TABLEARG) ? + tablearg : cmd->arg1; break; case O_COUNT: @@ -2064,7 +2035,7 @@ do { \ case O_NETGRAPH: case O_NGTEE: set_match(args, f_pos, chain); - args->cookie = (cmd->arg1 == IP_FW_TABLEARG) ? + args->rule.info = (cmd->arg1 == IP_FW_TABLEARG) ? tablearg : cmd->arg1; retval = (cmd->opcode == O_NETGRAPH) ? IP_FW_NETGRAPH : IP_FW_NGTEE; Modified: user/luigi/ipfw3-head/sys/netinet/ipfw/ip_fw_dynamic.c ============================================================================== --- user/luigi/ipfw3-head/sys/netinet/ipfw/ip_fw_dynamic.c Thu Dec 31 18:02:48 2009 (r201345) +++ user/luigi/ipfw3-head/sys/netinet/ipfw/ip_fw_dynamic.c Thu Dec 31 18:28:40 2009 (r201346) @@ -917,7 +917,7 @@ ipfw_send_pkt(struct mbuf *replyto, stru #endif default: /* XXX: log me?!? */ - m_freem(m); + FREE_PKT(m); return (NULL); } dir = ((flags & (TH_SYN | TH_RST)) == TH_SYN); Modified: user/luigi/ipfw3-head/sys/netinet/ipfw/ip_fw_pfil.c ============================================================================== --- user/luigi/ipfw3-head/sys/netinet/ipfw/ip_fw_pfil.c Thu Dec 31 18:02:48 2009 (r201345) +++ user/luigi/ipfw3-head/sys/netinet/ipfw/ip_fw_pfil.c Thu Dec 31 18:28:40 2009 (r201346) @@ -106,8 +106,7 @@ ipfw_check_hook(void *arg, struct mbuf * struct inpcb *inp) { struct ip_fw_args args; - struct ng_ipfw_tag *ng_tag; - struct m_tag *dn_tag; + struct m_tag *tag; int ipfw; int ret; #ifdef IPFIREWALL_FORWARD @@ -118,29 +117,11 @@ ipfw_check_hook(void *arg, struct mbuf * dir = (dir == PFIL_IN) ? DIR_IN : DIR_OUT; bzero(&args, sizeof(args)); - ng_tag = (struct ng_ipfw_tag *)m_tag_locate(*m0, NGM_IPFW_COOKIE, 0, - NULL); - if (ng_tag != NULL) { - KASSERT(ng_tag->dir == dir, - ("ng_ipfw tag with wrong direction")); - args.slot = ng_tag->slot; - args.rulenum = ng_tag->rulenum; - args.rule_id = ng_tag->rule_id; - args.chain_id = ng_tag->chain_id; - m_tag_delete(*m0, (struct m_tag *)ng_tag); - } - again: - dn_tag = m_tag_find(*m0, PACKET_TAG_DUMMYNET, NULL); - if (dn_tag != NULL) { - struct dn_pkt_tag *dt; - - dt = (struct dn_pkt_tag *)(dn_tag+1); - args.slot = dt->slot; - args.rulenum = dt->rulenum; - args.rule_id = dt->rule_id; - args.chain_id = dt->chain_id; - m_tag_delete(*m0, dn_tag); + tag = m_tag_locate(*m0, MTAG_IPFW_RULE, 0, NULL); + if (tag != NULL) { + args.rule = *((struct ipfw_rule_ref *)(tag+1)); + m_tag_delete(*m0, tag); } args.m = *m0; @@ -150,7 +131,7 @@ again: /* all the processing now uses ip_len in net format */ SET_NET_IPLEN(mtod(*m0, struct ip *)); - if (V_fw_one_pass == 0 || args.slot == 0) { + if (V_fw_one_pass == 0 || args.rule.slot == 0) { ipfw = ipfw_chk(&args); *m0 = args.m; } else @@ -224,15 +205,19 @@ again: ret = EACCES; break; /* i.e. drop */ } - ipfw_divert(m0, dir, (ipfw == IP_FW_TEE) ? 1 : 0); - if (*m0) { - /* continue processing for this one. We set - * args.slot=0, but the divert tag is processed - * in ipfw_chk to jump to the right place. - */ - args.slot = 0; - goto again; /* continue with packet */ + tag = m_tag_alloc(MTAG_IPFW_RULE, 0, + sizeof(struct ipfw_rule_ref), M_NOWAIT); + if (tag == NULL) { + ret = EACCES; + break; /* i.e. drop */ } + *((struct ipfw_rule_ref *)(tag+1)) = args.rule; + m_tag_prepend(*m0, tag); + + ipfw_divert(m0, dir, (ipfw == IP_FW_TEE) ? 1 : 0); + /* continue processing for the original packet (tee) */ + if (*m0) + goto again; break; case IP_FW_NGTEE: @@ -257,7 +242,7 @@ again: if (ret != 0) { if (*m0) - m_freem(*m0); + FREE_PKT(*m0); *m0 = NULL; } if (*m0) Modified: user/luigi/ipfw3-head/sys/netinet/ipfw/ip_fw_private.h ============================================================================== --- user/luigi/ipfw3-head/sys/netinet/ipfw/ip_fw_private.h Thu Dec 31 18:02:48 2009 (r201345) +++ user/luigi/ipfw3-head/sys/netinet/ipfw/ip_fw_private.h Thu Dec 31 18:28:40 2009 (r201346) @@ -36,6 +36,7 @@ #ifdef _KERNEL #define MTAG_IPFW 1148380143 /* IPFW-tagged cookie */ +#define MTAG_IPFW_RULE 1262273568 /* rule reference */ /* Return values from ipfw_chk() */ enum { @@ -70,6 +71,20 @@ struct _ip6dn_args { }; /* + * Reference to an ipfw rule that can be carried outside critical sections. + * A rule is identified by rulenum:rule_id which is ordered. + * In version chain_id the rule can be found in slot 'slot', so + * we don't need a lookup if chain_id == chain->id. + */ +struct ipfw_rule_ref { + uint32_t slot; /* slot for matching rule */ + uint32_t rulenum; /* matching rule number */ + uint32_t rule_id; /* matching rule id */ + uint32_t chain_id; /* ruleset id */ + uint32_t info; /* reason for reinject */ +}; + +/* * Arguments for calling ipfw_chk() and dummynet_io(). We put them * all into a structure because this way it is easier and more * efficient to pass variables around and extend the interface. @@ -79,19 +94,19 @@ struct ip_fw_args { struct ifnet *oif; /* output interface */ struct sockaddr_in *next_hop; /* forward address */ - /* chain_id validates 'slot', the location of the pointer to - * a matching rule. - * If invalid, we can lookup the rule using rule_id and rulenum + /* + * On return, it points to the matching rule. + * On entry, rule.slot > 0 means the info is valid and + * contains the the starting rule for an ipfw search. + * If chain_id == chain->id && slot >0 then jump to that slot. + * Otherwise, we locate the first rule >= rulenum:rule_id */ - uint32_t slot; /* slot for matching rule */ - uint32_t rulenum; /* matching rule number */ - uint32_t rule_id; /* matching rule id */ - uint32_t chain_id; /* ruleset id */ + struct ipfw_rule_ref rule; /* match/restart info */ struct ether_header *eh; /* for bridged packets */ struct ipfw_flow_id f_id; /* grabbed from IP header */ - uint32_t cookie; /* a cookie depending on rule action */ + //uint32_t cookie; /* a cookie depending on rule action */ struct inpcb *inp; struct _ip6dn_args dummypar; /* dummynet->ip6_output */ @@ -122,6 +137,9 @@ enum { /* PROTO_OLDBDG = 0x14, unused, old bridge */ }; +/* wrapper for freeing a packet, in case we need to do more work */ +#define FREE_PKT(m) m_freem(m) + /* * Function definitions. */ @@ -277,18 +295,6 @@ typedef int ng_ipfw_input_t(struct mbuf extern ng_ipfw_input_t *ng_ipfw_input_p; #define NG_IPFW_LOADED (ng_ipfw_input_p != NULL) -struct ng_ipfw_tag { - struct m_tag mt; /* tag header */ - /* reinject info */ - uint32_t slot; /* slot for next rule */ - uint32_t rulenum; /* matching rule number */ - uint32_t rule_id; /* matching rule id */ - uint32_t chain_id; /* ruleset id */ - int dir; - -// struct ifnet *ifp; /* interface, for ip_output */ -}; - #define TAGSIZ (sizeof(struct ng_ipfw_tag) - sizeof(struct m_tag))