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 <sys/priv.h>
 #include <sys/proc.h>
 #include <sys/protosw.h>
-#include <sys/rwlock.h>
-#include <sys/signalvar.h>
 #include <sys/socket.h>
 #include <sys/socketvar.h>
-#include <sys/sx.h>
 #include <sys/sysctl.h>
-#include <sys/systm.h>
-
-#include <vm/uma.h>
 
 #include <net/if.h>
 #include <net/netisr.h> 
-#include <net/route.h>
 #include <net/vnet.h>
 
 #include <netinet/in.h>
@@ -72,7 +65,6 @@ __FBSDID("$FreeBSD$");
 #include <netinet/in_systm.h>
 #include <netinet/in_var.h>
 #include <netinet/ip.h>
-#include <netinet/ip_divert.h>
 #include <netinet/ip_var.h>
 #include <netinet/ip_fw.h>
 #include <netinet/ipfw/ip_fw_private.h>
@@ -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 <netinet/ip_icmp.h>
 #include <netinet/ip_fw.h>
 #include <netinet/ipfw/ip_fw_private.h>
-#include <netinet/ip_divert.h>
 #include <netinet/ip_carp.h>
 #include <netinet/pim.h>
 #include <netinet/tcp_var.h>
@@ -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%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 <netinet/ip_var.h>
 #include <netinet/ip_fw.h>

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to