From owner-svn-src-all@FreeBSD.ORG Mon Jan 4 19:01:22 2010 Return-Path: Delivered-To: svn-src-all@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 7A0661065697; Mon, 4 Jan 2010 19:01:22 +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 675458FC0C; Mon, 4 Jan 2010 19:01:22 +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 o04J1M0J051453; Mon, 4 Jan 2010 19:01:22 GMT (envelope-from luigi@svn.freebsd.org) Received: (from luigi@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id o04J1MdD051439; Mon, 4 Jan 2010 19:01:22 GMT (envelope-from luigi@svn.freebsd.org) Message-Id: <201001041901.o04J1MdD051439@svn.freebsd.org> From: Luigi Rizzo Date: Mon, 4 Jan 2010 19:01:22 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r201527 - in head/sys: net netgraph netinet netinet/ipfw X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 04 Jan 2010 19:01:22 -0000 Author: luigi Date: Mon Jan 4 19:01:22 2010 New Revision: 201527 URL: http://svn.freebsd.org/changeset/base/201527 Log: Various cleanup done in ipfw3-head branch including: - use a uniform mtag format for all packets that exit and re-enter the firewall in the middle of a rulechain. On reentry, all tags containing reinject info are renamed to MTAG_IPFW_RULE so the processing is simpler. - make ipfw and dummynet use ip_len and ip_off in network format everywhere. Conversion is done only once instead of tracking the format in every place. - use a macro FREE_PKT to dispose of mbufs. This eases portability. On passing i also removed a few typos, staticise or localise variables, remove useless declarations and other minor things. Overall the code shrinks a bit and is hopefully more readable. I have tested functionality for all but ng_ipfw and if_bridge/if_ethersubr. For ng_ipfw i am actually waiting for feedback from glebius@ because we might have some small changes to make. For if_bridge and if_ethersubr feedback would be welcome (there are still some redundant parts in these two modules that I would like to remove, but first i need to check functionality). Modified: head/sys/net/if_bridge.c head/sys/net/if_ethersubr.c head/sys/netgraph/ng_ipfw.c head/sys/netinet/ip_divert.c head/sys/netinet/ip_divert.h head/sys/netinet/ip_dummynet.h head/sys/netinet/ipfw/ip_dummynet.c head/sys/netinet/ipfw/ip_fw2.c head/sys/netinet/ipfw/ip_fw_dynamic.c head/sys/netinet/ipfw/ip_fw_log.c head/sys/netinet/ipfw/ip_fw_nat.c head/sys/netinet/ipfw/ip_fw_pfil.c head/sys/netinet/ipfw/ip_fw_private.h head/sys/netinet/ipfw/ip_fw_sockopt.c Modified: head/sys/net/if_bridge.c ============================================================================== --- head/sys/net/if_bridge.c Mon Jan 4 18:57:22 2010 (r201526) +++ head/sys/net/if_bridge.c Mon Jan 4 19:01:22 2010 (r201527) @@ -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: head/sys/net/if_ethersubr.c ============================================================================== --- head/sys/net/if_ethersubr.c Mon Jan 4 18:57:22 2010 (r201526) +++ head/sys/net/if_ethersubr.c Mon Jan 4 19:01:22 2010 (r201527) @@ -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: head/sys/netgraph/ng_ipfw.c ============================================================================== --- head/sys/netgraph/ng_ipfw.c Mon Jan 4 18:57:22 2010 (r201526) +++ head/sys/netgraph/ng_ipfw.c Mon Jan 4 19:01:22 2010 (r201527) @@ -221,21 +221,23 @@ 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_rule_ref *tag; 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) { + tag = (struct ipfw_rule_ref *) + m_tag_locate(m, MTAG_IPFW_RULE, 0, NULL); + if (tag == NULL) { NG_FREE_M(m); return (EINVAL); /* XXX: find smth better */ }; - switch (ngit->dir) { - case DIR_OUT: - { + if (tag->info & IPFW_INFO_IN) { + ip_input(m); + return (0); + } else { struct ip *ip; if (m->m_len < sizeof(struct ip) && @@ -244,27 +246,16 @@ ng_ipfw_rcvdata(hook_p hook, item_p item ip = mtod(m, struct ip *); - ip->ip_len = ntohs(ip->ip_len); - ip->ip_off = ntohs(ip->ip_off); + SET_HOST_IPLEN(ip); return ip_output(m, NULL, NULL, IP_FORWARDING, NULL, NULL); - } - case DIR_IN: - ip_input(m); - return (0); - default: - panic("ng_ipfw_rcvdata: bad dir %u", ngit->dir); } - - /* not reached */ - return (0); } 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 ip *ip; hook_p hook; int error = 0; @@ -273,7 +264,7 @@ ng_ipfw_input(struct mbuf **m0, int dir, * Node must be loaded and corresponding hook must be present. */ if (fw_node == NULL || - (hook = ng_ipfw_findhook1(fw_node, fwa->cookie)) == NULL) { + (hook = ng_ipfw_findhook1(fw_node, fwa->rule.info)) == NULL) { if (tee == 0) m_freem(*m0); return (ESRCH); /* no hook associated with this rule */ @@ -285,21 +276,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_rule_ref *r; 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(MTAG_IPFW_RULE, 0, sizeof(*r), + M_NOWAIT|M_ZERO); + if (tag == 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); + r = (struct ipfw_rule_ref *)(tag + 1); + *r = fwa->rule; + r->info = dir ? IPFW_INFO_IN : IPFW_INFO_OUT; + m_tag_prepend(m, tag); } else if ((m = m_dup(*m0, M_DONTWAIT)) == NULL) @@ -310,8 +301,6 @@ ng_ipfw_input(struct mbuf **m0, int dir, return (EINVAL); ip = mtod(m, struct ip *); - ip->ip_len = htons(ip->ip_len); - ip->ip_off = htons(ip->ip_off); NG_SEND_DATA_ONLY(error, hook, m); Modified: head/sys/netinet/ip_divert.c ============================================================================== --- head/sys/netinet/ip_divert.c Mon Jan 4 18:57:22 2010 (r201526) +++ head/sys/netinet/ip_divert.c Mon Jan 4 19:01:22 2010 (r201527) @@ -52,19 +52,12 @@ __FBSDID("$FreeBSD$"); #include #include #include -#include -#include #include #include -#include #include -#include - -#include #include #include -#include #include #include @@ -72,7 +65,6 @@ __FBSDID("$FreeBSD$"); #include #include #include -#include #include #include #include @@ -194,7 +186,7 @@ div_destroy(void) * IPPROTO_DIVERT is not in the real IP protocol number space; this * function should never be called. Just in case, drop any packets. */ -void +static void div_input(struct mbuf *m, int off) { @@ -218,9 +210,8 @@ divert_packet(struct mbuf *m, int incomi struct sockaddr_in divsrc; struct m_tag *mtag; - mtag = m_tag_find(m, PACKET_TAG_DIVERT, NULL); + mtag = m_tag_locate(m, MTAG_IPFW_RULE, 0, NULL); if (mtag == NULL) { - printf("%s: no divert tag\n", __func__); m_freem(m); return; } @@ -245,14 +236,15 @@ divert_packet(struct mbuf *m, int incomi ip->ip_len = htons(ip->ip_len); } #endif + bzero(&divsrc, sizeof(divsrc)); + divsrc.sin_len = sizeof(divsrc); + divsrc.sin_family = AF_INET; + /* record matching rule, in host format */ + divsrc.sin_port = ((struct ipfw_rule_ref *)(mtag+1))->rulenum; /* * Record receive interface address, if any. * But only for incoming packets. */ - bzero(&divsrc, sizeof(divsrc)); - divsrc.sin_len = sizeof(divsrc); - divsrc.sin_family = AF_INET; - divsrc.sin_port = divert_cookie(mtag); /* record matching rule */ if (incoming) { struct ifaddr *ifa; struct ifnet *ifp; @@ -300,7 +292,7 @@ divert_packet(struct mbuf *m, int incomi /* Put packet on socket queue, if any */ sa = NULL; - nport = htons((u_int16_t)divert_info(mtag)); + nport = htons((u_int16_t)(((struct ipfw_rule_ref *)(mtag+1))->info)); INP_INFO_RLOCK(&V_divcbinfo); LIST_FOREACH(inp, &V_divcb, inp_list) { /* XXX why does only one socket match? */ @@ -339,7 +331,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 +346,31 @@ 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 */ + 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); /* 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. @@ -388,7 +388,7 @@ div_output(struct socket *so, struct mbu struct ip *const ip = mtod(m, struct ip *); struct inpcb *inp; - dt->info |= IP_FW_DIVERT_OUTPUT_FLAG; + dt->info |= IPFW_IS_DIVERT | IPFW_INFO_OUT; INP_INFO_WLOCK(&V_divcbinfo); inp = sotoinpcb(so); INP_RLOCK(inp); @@ -454,7 +454,7 @@ div_output(struct socket *so, struct mbu m_freem(options); } } else { - dt->info |= IP_FW_DIVERT_LOOPBACK_FLAG; + dt->info |= IPFW_IS_DIVERT | IPFW_INFO_IN; if (m->m_pkthdr.rcvif == NULL) { /* * No luck with the name, check by IP address. @@ -588,7 +588,7 @@ div_send(struct socket *so, int flags, s return div_output(so, m, (struct sockaddr_in *)nam, control); } -void +static void div_ctlinput(int cmd, struct sockaddr *sa, void *vip) { struct in_addr faddr; @@ -801,5 +801,5 @@ static moduledata_t ipdivertmod = { }; DECLARE_MODULE(ipdivert, ipdivertmod, SI_SUB_PROTO_IFATTACHDOMAIN, SI_ORDER_ANY); -MODULE_DEPEND(dummynet, ipfw, 2, 2, 2); +MODULE_DEPEND(ipdivert, ipfw, 2, 2, 2); MODULE_VERSION(ipdivert, 1); Modified: head/sys/netinet/ip_divert.h ============================================================================== --- head/sys/netinet/ip_divert.h Mon Jan 4 18:57:22 2010 (r201526) +++ head/sys/netinet/ip_divert.h Mon Jan 4 19:01:22 2010 (r201527) @@ -36,53 +36,20 @@ #define _NETINET_IP_DIVERT_H_ /* - * Sysctl declaration. + * divert has no custom kernel-userland API. + * + * All communication occurs through a sockaddr_in socket where + * + * kernel-->userland + * sin_port = matching rule, host format; + * sin_addr = IN: first address of the incoming interface; + * OUT: INADDR_ANY + * sin_zero = if fits, the interface name (max 7 bytes + NUL) + * + * userland->kernel + * sin_port = restart-rule - 1, host order + * (we restart at sin_port + 1) + * sin_addr = IN: address of the incoming interface; + * OUT: INADDR_ANY */ -#ifdef SYSCTL_DECL -SYSCTL_DECL(_net_inet_divert); -#endif - -/* - * 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. - */ -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 the divert info associated with the mbuf; if any. - */ -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; -} - -typedef void ip_divert_packet_t(struct mbuf *m, int incoming); -extern ip_divert_packet_t *ip_divert_ptr; - -extern void div_input(struct mbuf *, int); -extern void div_ctlinput(int, struct sockaddr *, void *); #endif /* _NETINET_IP_DIVERT_H_ */ Modified: head/sys/netinet/ip_dummynet.h ============================================================================== --- head/sys/netinet/ip_dummynet.h Mon Jan 4 18:57:22 2010 (r201526) +++ head/sys/netinet/ip_dummynet.h Mon Jan 4 19:01:22 2010 (r201527) @@ -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: head/sys/netinet/ipfw/ip_dummynet.c ============================================================================== --- head/sys/netinet/ipfw/ip_dummynet.c Mon Jan 4 18:57:22 2010 (r201526) +++ head/sys/netinet/ipfw/ip_dummynet.c Mon Jan 4 19:01:22 2010 (r201527) @@ -462,15 +462,10 @@ heap_free(struct dn_heap *h) */ /* - * Dispose a packet in dummynet. Use an inline functions so if we + * Dispose a list of packet. Use an inline functions so if we * need to free extra state associated to a packet, this is a * central point to do it. */ -static __inline void *dn_free_pkt(struct mbuf *m) -{ - m_freem(m); - return NULL; -} static __inline void dn_free_pkts(struct mbuf *mnext) { @@ -478,7 +473,7 @@ static __inline void dn_free_pkts(struct while ((m = mnext) != NULL) { mnext = m->m_nextpkt; - dn_free_pkt(m); + FREE_PKT(m); } } @@ -968,24 +963,31 @@ dummynet_send(struct mbuf *m) for (; m != NULL; m = n) { struct ifnet *ifp; int dst; + struct m_tag *tag; n = m->m_nextpkt; m->m_nextpkt = NULL; - if (m_tag_first(m) == NULL) { + tag = m_tag_first(m); + if (tag == NULL) { 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; + /* rename the tag so it carries reinject info */ + tag->m_tag_cookie = MTAG_IPFW_RULE; + tag->m_tag_id = 0; } switch (dst) { case DIR_OUT: + SET_HOST_IPLEN(mtod(m, struct ip *)); ip_output(m, NULL, NULL, IP_FORWARDING, NULL, NULL); break ; case DIR_IN : /* put header in network format for ip_input() */ - SET_NET_IPLEN(mtod(m, struct ip *)); + //SET_NET_IPLEN(mtod(m, struct ip *)); netisr_dispatch(NETISR_IP, m); break; #ifdef INET6 @@ -994,6 +996,7 @@ dummynet_send(struct mbuf *m) break; case DIR_OUT | PROTO_IPV6: + SET_HOST_IPLEN(mtod(m, struct ip *)); ip6_output(m, NULL, NULL, IPV6_FORWARDING, NULL, NULL, NULL); break; #endif @@ -1024,12 +1027,12 @@ dummynet_send(struct mbuf *m) case DIR_DROP: /* drop the packet after some time */ - dn_free_pkt(m); + FREE_PKT(m); break; default: printf("dummynet: bad switch %d!\n", dst); - dn_free_pkt(m); + FREE_PKT(m); break; } } @@ -1362,7 +1365,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 & IPFW_IS_PIPE; KASSERT(m->m_nextpkt == NULL, ("dummynet_io: mbuf queue passed to dummynet")); @@ -1371,16 +1374,13 @@ dummynet_io(struct mbuf **m0, int dir, s io_pkt++; /* * This is a dummynet rule, so we expect an O_PIPE or O_QUEUE rule. - * - * XXXGL: probably the pipe->fs and fs->pipe logic here - * below can be simplified. */ if (is_pipe) { - pipe = locate_pipe(fwa->cookie & 0xffff); + pipe = locate_pipe(fwa->rule.info & IPFW_INFO_MASK); if (pipe != NULL) fs = &(pipe->fs); } else - fs = locate_flowset(fwa->cookie & 0xffff); + fs = locate_flowset(fwa->rule.info & IPFW_INFO_MASK); if (fs == NULL) goto dropit; /* This queue/pipe does not exist! */ @@ -1426,12 +1426,9 @@ 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->rule.info &= IPFW_ONEPASS; /* only keep this info */ pkt->dn_dir = dir; - pkt->ifp = fwa->oif; if (q->head == NULL) @@ -1562,7 +1559,8 @@ dropit: if (q) q->drops++; DUMMYNET_UNLOCK(); - *m0 = dn_free_pkt(m); + FREE_PKT(m); + *m0 = NULL; return ((fs && (fs->flags_fs & DN_NOERROR)) ? 0 : ENOBUFS); } Modified: head/sys/netinet/ipfw/ip_fw2.c ============================================================================== --- head/sys/netinet/ipfw/ip_fw2.c Mon Jan 4 18:57:22 2010 (r201526) +++ head/sys/netinet/ipfw/ip_fw2.c Mon Jan 4 19:01:22 2010 (r201527) @@ -74,7 +74,6 @@ __FBSDID("$FreeBSD$"); #include #include #include -#include #include #include #include @@ -560,7 +559,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 +575,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; } @@ -603,9 +602,7 @@ send_reject(struct ip_fw_args *args, int #endif if (code != ICMP_REJECT_RST) { /* Send an ICMP unreach */ /* We need the IP header in host order for icmp_error(). */ - if (args->eh != NULL) { - SET_HOST_IPLEN(ip); - } + SET_HOST_IPLEN(ip); icmp_error(args->m, ICMP_UNREACH, code, 0L, 0); } else if (args->f_id.proto == IPPROTO_TCP) { struct tcphdr *const tcp = @@ -618,9 +615,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; } @@ -709,16 +706,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; } /* @@ -743,7 +742,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: * @@ -753,6 +752,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 @@ -797,14 +798,6 @@ ipfw_chk(struct ip_fw_args *args) int ucred_lookup = 0; /* - * divinput_flags If non-zero, set to the IP_FW_DIVERT_*_FLAG - * associated with a packet input on a divert socket. This - * will allow to distinguish traffic and its direction when - * it originates from a divert socket. - */ - u_int divinput_flags = 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 @@ -862,7 +855,6 @@ ipfw_chk(struct ip_fw_args *args) int dyn_dir = MATCH_UNKNOWN; ipfw_dyn_rule *q = NULL; struct ip_fw_chain *chain = &V_layer3_chain; - struct m_tag *mtag; /* * We store in ulp a pointer to the upper layer protocol header. @@ -1090,16 +1082,8 @@ do { \ proto = ip->ip_p; src_ip = ip->ip_src; dst_ip = ip->ip_dst; -#ifndef HAVE_NET_IPLEN - if (args->eh == NULL) { /* on l3 these are in host format */ - offset = ip->ip_off & IP_OFFMASK; - iplen = ip->ip_len; - } else -#endif /* !HAVE_NET_IPLEN */ - { /* otherwise they are in net format */ - offset = ntohs(ip->ip_off) & IP_OFFMASK; - iplen = ntohs(ip->ip_len); - } + offset = ntohs(ip->ip_off) & IP_OFFMASK; + iplen = ntohs(ip->ip_len); pktlen = iplen < pktlen ? iplen : pktlen; if (offset == 0) { @@ -1143,44 +1127,20 @@ 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) { - divinput_flags = divert_info(mtag) & - (IP_FW_DIVERT_OUTPUT_FLAG | IP_FW_DIVERT_LOOPBACK_FLAG); - m_tag_delete(m, mtag); } /* @@ -1332,10 +1292,15 @@ do { \ break; case O_DIVERTED: - match = (cmd->arg1 & 1 && divinput_flags & - IP_FW_DIVERT_LOOPBACK_FLAG) || - (cmd->arg1 & 2 && divinput_flags & - IP_FW_DIVERT_OUTPUT_FLAG); + { + /* For diverted packets, args->rule.info + * contains the divert port (in host format) + * reason and direction. + */ + uint32_t i = args->rule.info; + match = (i&IPFW_IS_MASK) == IPFW_IS_DIVERT && + cmd->arg1 & ((i & IPFW_INFO_IN) ? 1 : 2); + } break; case O_PROTO: @@ -1755,6 +1720,7 @@ do { \ break; case O_TAG: { + struct m_tag *mtag; uint32_t tag = (cmd->arg1 == IP_FW_TABLEARG) ? tablearg : cmd->arg1; @@ -1771,12 +1737,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; } @@ -1786,6 +1753,7 @@ do { \ break; case O_TAGGED: { + struct m_tag *mtag; uint32_t tag = (cmd->arg1 == IP_FW_TABLEARG) ? tablearg : cmd->arg1; @@ -1926,10 +1894,12 @@ 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; + if (cmd->opcode == O_PIPE) + args->rule.info |= IPFW_IS_PIPE; + if (V_fw_one_pass) + args->rule.info |= IPFW_ONEPASS; retval = IP_FW_DUMMYNET; l = 0; /* exit inner loop */ done = 1; /* exit outer loop */ @@ -1942,23 +1912,11 @@ 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) ? + 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: @@ -2074,7 +2032,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; @@ -2126,12 +2084,6 @@ do { \ f->pcnt++; f->bcnt += pktlen; l = 0; /* in any case exit inner loop */ - -#ifndef HAVE_NET_IPLEN - if (args->eh == NULL) - ip_off = ip->ip_off; - else -#endif /* !HAVE_NET_IPLEN */ ip_off = ntohs(ip->ip_off); /* if not fragmented, go to next rule */ @@ -2139,19 +2091,14 @@ do { \ break; /* * ip_reass() expects len & off in host - * byte order: fix them in case we come - * from layer2. + * byte order. */ - if (args->eh != NULL) { - SET_HOST_IPLEN(ip); - } + SET_HOST_IPLEN(ip); args->m = m = ip_reass(m); /* - * IP header checksum fixup after - * reassembly and leave header - * in network byte order. + * do IP header checksum fixup. */ if (m == NULL) { /* fragment got swallowed */ retval = IP_FW_DENY; @@ -2160,10 +2107,7 @@ do { \ ip = mtod(m, struct ip *); hlen = ip->ip_hl << 2; - /* revert len. & off to net format if needed */ - if (args->eh != NULL) { - SET_NET_IPLEN(ip); - } + SET_NET_IPLEN(ip); ip->ip_sum = 0; if (hlen == sizeof(struct ip)) ip->ip_sum = in_cksum_hdr(ip); Modified: head/sys/netinet/ipfw/ip_fw_dynamic.c ============================================================================== --- head/sys/netinet/ipfw/ip_fw_dynamic.c Mon Jan 4 18:57:22 2010 (r201526) +++ head/sys/netinet/ipfw/ip_fw_dynamic.c Mon Jan 4 19:01:22 2010 (r201527) @@ -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); @@ -1002,11 +1002,7 @@ ipfw_send_pkt(struct mbuf *replyto, stru h->ip_hl = sizeof(*h) >> 2; h->ip_tos = IPTOS_LOWDELAY; h->ip_off = 0; -#ifdef HAVE_NET_IPLEN /* XXX do we handle layer2 ? */ h->ip_len = htons(len); -#else - h->ip_len = len; -#endif h->ip_ttl = V_ip_defttl; h->ip_sum = 0; break; Modified: head/sys/netinet/ipfw/ip_fw_log.c ============================================================================== --- head/sys/netinet/ipfw/ip_fw_log.c Mon Jan 4 18:57:22 2010 (r201526) +++ head/sys/netinet/ipfw/ip_fw_log.c Mon Jan 4 19:01:22 2010 (r201527) @@ -165,16 +165,8 @@ ipfw_log(struct ip_fw *f, u_int hlen, st * more info in the header */ mh.mh_data = "DDDDDDSSSSSS\x08\x00"; - if (args->f_id.addr_type == 4) { - /* restore wire format */ - SET_NET_IPLEN(ip); - } } BPF_MTAP(log_if, (struct mbuf *)&mh); - if (args->eh == NULL && args->f_id.addr_type == 4) { - /* restore host format */ - SET_HOST_IPLEN(ip); - } #endif /* !WITHOUT_BPF */ return; } @@ -409,23 +401,15 @@ ipfw_log(struct ip_fw *f, u_int hlen, st } else #endif { - int ip_off, ip_len; -#ifndef HAVE_NET_IPLEN - if (args->eh == NULL) { - ip_off = ip->ip_off; - ip_len = ip->ip_len; - } else -#endif /* !HAVE_NET_IPLEN */ - { - ip_off = ntohs(ip->ip_off); - ip_len = ntohs(ip->ip_len); - } - if (ip_off & (IP_MF | IP_OFFMASK)) + int ipoff, iplen; + ipoff = ntohs(ip->ip_off); + iplen = ntohs(ip->ip_len); + if (ipoff & (IP_MF | IP_OFFMASK)) snprintf(SNPARGS(fragment, 0), " (frag %d:%d@%d%s)", - ntohs(ip->ip_id), ip_len - (ip->ip_hl << 2), + ntohs(ip->ip_id), iplen - (ip->ip_hl << 2), offset << 3, - (ip_off & IP_MF) ? "+" : ""); + (ipoff & IP_MF) ? "+" : ""); } } if (oif || m->m_pkthdr.rcvif) Modified: head/sys/netinet/ipfw/ip_fw_nat.c ============================================================================== --- head/sys/netinet/ipfw/ip_fw_nat.c Mon Jan 4 18:57:22 2010 (r201526) +++ head/sys/netinet/ipfw/ip_fw_nat.c Mon Jan 4 19:01:22 2010 (r201527) @@ -219,9 +219,6 @@ ipfw_nat(struct ip_fw_args *args, struct return (IP_FW_DENY); } ip = mtod(mcl, struct ip *); - if (args->eh == NULL) { - SET_NET_IPLEN(ip); - } /* * XXX - Libalias checksum offload 'duct tape': @@ -330,9 +327,6 @@ ipfw_nat(struct ip_fw_args *args, struct mcl->m_pkthdr.csum_flags &= ~CSUM_DELAY_DATA; } } - if (args->eh == NULL) { - SET_HOST_IPLEN(ip); - } args->m = mcl; return (IP_FW_NAT); } Modified: head/sys/netinet/ipfw/ip_fw_pfil.c ============================================================================== --- head/sys/netinet/ipfw/ip_fw_pfil.c Mon Jan 4 18:57:22 2010 (r201526) +++ head/sys/netinet/ipfw/ip_fw_pfil.c Mon Jan 4 19:01:22 2010 (r201527) @@ -59,7 +59,6 @@ __FBSDID("$FreeBSD$"); #include #include *** DIFF OUTPUT TRUNCATED AT 1000 LINES ***