- Move IPDIVERT related bits into netinet/ip_divert.c
authorSepherosa Ziehau <sephe@dragonflybsd.org>
Sat, 13 Sep 2008 08:48:42 +0000 (08:48 +0000)
committerSepherosa Ziehau <sephe@dragonflybsd.org>
Sat, 13 Sep 2008 08:48:42 +0000 (08:48 +0000)
- Expose ip_reass(), which is used by ip_divert_in()
- Add function ptr ip_divert_p, which will be set to ip_divert(), if IPDIVERT
  support is compiled into kernel.  ip_divert() dispatches real work to either
  ip_divert_in() or ip_divert_out() based on the third parameter
- Hide divert_packet() after above change

sys/netinet/ip_divert.c
sys/netinet/ip_divert.h
sys/netinet/ip_input.c
sys/netinet/ip_output.c
sys/netinet/ip_var.h

index 6f97103..1c48d3b 100644 (file)
  * SUCH DAMAGE.
  *
  * $FreeBSD: src/sys/netinet/ip_divert.c,v 1.42.2.6 2003/01/23 21:06:45 sam Exp $
- * $DragonFly: src/sys/netinet/ip_divert.c,v 1.38 2008/08/28 14:10:03 sephe Exp $
+ * $DragonFly: src/sys/netinet/ip_divert.c,v 1.39 2008/09/13 08:48:42 sephe Exp $
  */
 
+#define        _IP_VHL
+
 #include "opt_inet.h"
 #include "opt_ipfw.h"
 #include "opt_ipdivert.h"
@@ -54,6 +56,7 @@
 #include <sys/systm.h>
 #include <sys/proc.h>
 #include <sys/thread2.h>
+#include <sys/in_cksum.h>
 #ifdef SMP
 #include <sys/msgport.h>
 #endif
@@ -119,6 +122,8 @@ static struct inpcbinfo divcbinfo;
 static u_long  div_sendspace = DIVSNDQ;        /* XXX sysctl ? */
 static u_long  div_recvspace = DIVRCVQ;        /* XXX sysctl ? */
 
+static struct mbuf *ip_divert(struct mbuf *, int, int);
+
 /*
  * Initialize divert connection block queue.
  */
@@ -137,6 +142,7 @@ div_init(void)
                                              &divcbinfo.wildcardhashmask);
        divcbinfo.ipi_zone = zinit("divcb", sizeof(struct inpcb),
                                   maxsockets, ZONE_INTERRUPT, 0);
+       ip_divert_p = ip_divert;
 }
 
 /*
@@ -328,7 +334,7 @@ div_packet_handler(struct netmsg *nmsg)
 }
 #endif /* SMP */
 
-void
+static void
 divert_packet(struct mbuf *m, int incoming)
 {
        struct m_tag *mtag;
@@ -562,3 +568,153 @@ struct pr_usrreqs div_usrreqs = {
        .pru_soreceive = soreceive,
        .pru_sopoll = sopoll
 };
+
+static struct mbuf *
+ip_divert_out(struct mbuf *m, int tee)
+{
+       struct mbuf *clone = NULL;
+       struct ip *ip = mtod(m, struct ip *);
+
+       /* Clone packet if we're doing a 'tee' */
+       if (tee)
+               clone = m_dup(m, MB_DONTWAIT);
+
+       /*
+        * XXX
+        * delayed checksums are not currently compatible
+        * with divert sockets.
+        */
+       if (m->m_pkthdr.csum_flags & CSUM_DELAY_DATA) {
+               in_delayed_cksum(m);
+               m->m_pkthdr.csum_flags &= ~CSUM_DELAY_DATA;
+       }
+
+       /* Restore packet header fields to original values */
+       ip->ip_len = htons(ip->ip_len);
+       ip->ip_off = htons(ip->ip_off);
+
+       /* Deliver packet to divert input routine */
+       divert_packet(m, 0);
+
+       /* If 'tee', continue with original packet */
+       return clone;
+}
+
+static struct mbuf *
+ip_divert_in(struct mbuf *m, int tee)
+{
+       struct mbuf *clone = NULL;
+       struct ip *ip = mtod(m, struct ip *);
+       struct m_tag *mtag;
+
+       if (ip->ip_off & (IP_MF | IP_OFFMASK)) {
+               const struct divert_info *divinfo;
+               u_short frag_off;
+               int hlen;
+
+               /*
+                * Only trust divert info in the fragment
+                * at offset 0.
+                */
+               frag_off = ip->ip_off << 3;
+               if (frag_off != 0) {
+                       mtag = m_tag_find(m, PACKET_TAG_IPFW_DIVERT, NULL);
+                       m_tag_delete(m, mtag);
+               }
+
+               /*
+                * Attempt reassembly; if it succeeds, proceed.
+                * ip_reass() will return a different mbuf.
+                */
+               m = ip_reass(m);
+               if (m == NULL)
+                       return NULL;
+               ip = mtod(m, struct ip *);
+
+               /* Caller need to redispatch the packet, if it is for us */
+               m->m_pkthdr.fw_flags |= FW_MBUF_REDISPATCH;
+
+               /*
+                * Get the header length of the reassembled
+                * packet
+                */
+               hlen = IP_VHL_HL(ip->ip_vhl) << 2;
+
+               /*
+                * Restore original checksum before diverting
+                * packet
+                */
+               ip->ip_len += hlen;
+               ip->ip_len = htons(ip->ip_len);
+               ip->ip_off = htons(ip->ip_off);
+               ip->ip_sum = 0;
+               if (hlen == sizeof(struct ip))
+                       ip->ip_sum = in_cksum_hdr(ip);
+               else
+                       ip->ip_sum = in_cksum(m, hlen);
+               ip->ip_off = ntohs(ip->ip_off);
+               ip->ip_len = ntohs(ip->ip_len);
+
+               /*
+                * Only use the saved divert info
+                */
+               mtag = m_tag_find(m, PACKET_TAG_IPFW_DIVERT, NULL);
+               if (mtag == NULL) {
+                       /* Wrongly configured ipfw */
+                       kprintf("ip_input no divert info\n");
+                       m_freem(m);
+                       return NULL;
+               }
+               divinfo = m_tag_data(mtag);
+               tee = divinfo->tee;
+       }
+
+       /*
+        * Divert or tee packet to the divert protocol if
+        * required.
+        */
+
+       /* Clone packet if we're doing a 'tee' */
+       if (tee)
+               clone = m_dup(m, MB_DONTWAIT);
+
+       /*
+        * Restore packet header fields to original
+        * values
+        */
+       ip->ip_len = htons(ip->ip_len);
+       ip->ip_off = htons(ip->ip_off);
+
+       /* Deliver packet to divert input routine */
+       divert_packet(m, 1);
+
+       /* Catch invalid reference */
+       m = NULL;
+       ip = NULL;
+
+       ipstat.ips_delivered++;
+
+       /* If 'tee', continue with original packet */
+       if (clone != NULL) {
+               /*
+                * Complete processing of the packet.
+                * XXX Better safe than sorry, remove the DIVERT tag.
+                */
+               mtag = m_tag_find(clone, PACKET_TAG_IPFW_DIVERT, NULL);
+               KKASSERT(mtag != NULL);
+               m_tag_delete(clone, mtag);
+       }
+       return clone;
+}
+
+static struct mbuf *
+ip_divert(struct mbuf *m, int tee, int incoming)
+{
+       struct mbuf *ret;
+
+       if (incoming)
+               ret = ip_divert_in(m, tee);
+       else
+               ret = ip_divert_out(m, tee);
+       return ret;
+}
index 7725b47..8d7d231 100644 (file)
@@ -30,7 +30,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $DragonFly: src/sys/netinet/ip_divert.h,v 1.2 2008/08/28 14:24:59 sephe Exp $
+ * $DragonFly: src/sys/netinet/ip_divert.h,v 1.3 2008/09/13 08:48:42 sephe Exp $
  */
 
 #ifndef _NETINET_IP_DIVERT_H_
@@ -53,7 +53,8 @@ void  div_input(struct mbuf *, ...);
 struct lwkt_port *
        div_soport(struct socket *, struct sockaddr *,
                   struct mbuf **, int);
-void   divert_packet(struct mbuf *, int);
+
+extern struct mbuf *(*ip_divert_p)(struct mbuf *, int, int);
 
 extern struct pr_usrreqs div_usrreqs;
 
index 83ea5c2..519eb68 100644 (file)
@@ -65,7 +65,7 @@
  *
  *     @(#)ip_input.c  8.2 (Berkeley) 1/4/94
  * $FreeBSD: src/sys/netinet/ip_input.c,v 1.130.2.52 2003/03/07 07:01:28 silby Exp $
- * $DragonFly: src/sys/netinet/ip_input.c,v 1.102 2008/09/13 07:15:14 sephe Exp $
+ * $DragonFly: src/sys/netinet/ip_input.c,v 1.103 2008/09/13 08:48:42 sephe Exp $
  */
 
 #define        _IP_VHL
 #include <netinet/in_pcb.h>
 #include <netinet/ip_var.h>
 #include <netinet/ip_icmp.h>
-#ifdef IPDIVERT
 #include <netinet/ip_divert.h>
-#endif
 
 #include <sys/thread2.h>
 #include <sys/msgport2.h>
@@ -267,6 +265,8 @@ int ip_fw_loaded;
 int fw_enable = 1;
 int fw_one_pass = 1;
 
+struct mbuf *(*ip_divert_p)(struct mbuf *, int, int);
+
 struct pfil_head inet_pfil_hook;
 
 /*
@@ -302,7 +302,6 @@ static void         save_rte(struct mbuf *, u_char *, struct in_addr);
 static int             ip_dooptions(struct mbuf *m, int, struct sockaddr_in *);
 static void            ip_freef(struct ipq *);
 static void            ip_input_handler(struct netmsg *);
-static struct mbuf     *ip_reass(struct mbuf *);
 
 /*
  * IP initialization: fill in IP protocol switch table.
@@ -409,115 +408,6 @@ ip_input_handler(struct netmsg *msg0)
        /* msg0 was embedded in the mbuf, do not reply! */
 }
 
-#ifdef IPDIVERT
-static struct mbuf *
-ip_divert_in(struct mbuf *m, int tee)
-{
-       struct mbuf *clone = NULL;
-       struct ip *ip = mtod(m, struct ip *);
-       struct m_tag *mtag;
-
-       if (ip->ip_off & (IP_MF | IP_OFFMASK)) {
-               const struct divert_info *divinfo;
-               u_short frag_off;
-               int hlen;
-
-               /*
-                * Only trust divert info in the fragment
-                * at offset 0.
-                */
-               frag_off = ip->ip_off << 3;
-               if (frag_off != 0) {
-                       mtag = m_tag_find(m, PACKET_TAG_IPFW_DIVERT, NULL);
-                       m_tag_delete(m, mtag);
-               }
-
-               /*
-                * Attempt reassembly; if it succeeds, proceed.
-                * ip_reass() will return a different mbuf.
-                */
-               m = ip_reass(m);
-               if (m == NULL)
-                       return NULL;
-               ip = mtod(m, struct ip *);
-
-               /* Caller need to redispatch the packet, if it is for us */
-               m->m_pkthdr.fw_flags |= FW_MBUF_REDISPATCH;
-
-               /*
-                * Get the header length of the reassembled
-                * packet
-                */
-               hlen = IP_VHL_HL(ip->ip_vhl) << 2;
-
-               /*
-                * Restore original checksum before diverting
-                * packet
-                */
-               ip->ip_len += hlen;
-               ip->ip_len = htons(ip->ip_len);
-               ip->ip_off = htons(ip->ip_off);
-               ip->ip_sum = 0;
-               if (hlen == sizeof(struct ip))
-                       ip->ip_sum = in_cksum_hdr(ip);
-               else
-                       ip->ip_sum = in_cksum(m, hlen);
-               ip->ip_off = ntohs(ip->ip_off);
-               ip->ip_len = ntohs(ip->ip_len);
-
-               /*
-                * Only use the saved divert info
-                */
-               mtag = m_tag_find(m, PACKET_TAG_IPFW_DIVERT, NULL);
-               if (mtag == NULL) {
-                       /* Wrongly configured ipfw */
-                       kprintf("ip_input no divert info\n");
-                       m_freem(m);
-                       return NULL;
-               }
-               divinfo = m_tag_data(mtag);
-               tee = divinfo->tee;
-       }
-
-       /*
-        * Divert or tee packet to the divert protocol if
-        * required.
-        */
-
-       /* Clone packet if we're doing a 'tee' */
-       if (tee)
-               clone = m_dup(m, MB_DONTWAIT);
-
-       /*
-        * Restore packet header fields to original
-        * values
-        */
-       ip->ip_len = htons(ip->ip_len);
-       ip->ip_off = htons(ip->ip_off);
-
-       /* Deliver packet to divert input routine */
-       divert_packet(m, 1);
-
-       /* Catch invalid reference */
-       m = NULL;
-       ip = NULL;
-
-       ipstat.ips_delivered++;
-
-       /* If 'tee', continue with original packet */
-       if (clone != NULL) {
-               /*
-                * Complete processing of the packet.
-                * XXX Better safe than sorry, remove the DIVERT tag.
-                */
-               mtag = m_tag_find(clone, PACKET_TAG_IPFW_DIVERT, NULL);
-               KKASSERT(mtag != NULL);
-               m_tag_delete(clone, mtag);
-       }
-       return clone;
-}
-#endif /* IPDIVERT */
-
 /*
  * IP input routine.  Checksum and byte swap header.  If fragmented
  * try to reassemble.  Process options.  Pass to next level.
@@ -724,17 +614,17 @@ iphack:
                        /* FALL THROUGH */
 
                case IP_FW_DIVERT:
-#ifdef IPDIVERT
-                       m = ip_divert_in(m, tee);
-                       if (m == NULL)
+                       if (ip_divert_p != NULL) {
+                               m = ip_divert_p(m, tee, 1);
+                               if (m == NULL)
+                                       return;
+                               ip = mtod(m, struct ip *);
+                               hlen = IP_VHL_HL(ip->ip_vhl) << 2;
+                               goto pass;
+                       } else {
+                               m_freem(m);
                                return;
-                       ip = mtod(m, struct ip *);
-                       hlen = IP_VHL_HL(ip->ip_vhl) << 2;
-                       goto pass;
-#else
-                       m_freem(m);
-                       return;
-#endif
+                       }
 
                default:
                        panic("unknown ipfw return value: %d\n", i);
@@ -1091,7 +981,7 @@ bad:
  * whole datagram.  If a chain for reassembly of this datagram already
  * exists, then it is given as fp; otherwise have to make a chain.
  */
-static struct mbuf *
+struct mbuf *
 ip_reass(struct mbuf *m)
 {
        struct ip *ip = mtod(m, struct ip *);
index 7ca9ad7..d1889d9 100644 (file)
@@ -28,7 +28,7 @@
  *
  *     @(#)ip_output.c 8.3 (Berkeley) 1/21/94
  * $FreeBSD: src/sys/netinet/ip_output.c,v 1.99.2.37 2003/04/15 06:44:45 silby Exp $
- * $DragonFly: src/sys/netinet/ip_output.c,v 1.61 2008/09/13 05:49:08 sephe Exp $
+ * $DragonFly: src/sys/netinet/ip_output.c,v 1.62 2008/09/13 08:48:42 sephe Exp $
  */
 
 #define _IP_VHL
@@ -65,9 +65,7 @@
 #include <netinet/in_pcb.h>
 #include <netinet/in_var.h>
 #include <netinet/ip_var.h>
-#ifdef IPDIVERT
 #include <netinet/ip_divert.h>
-#endif
 
 #include <netproto/mpls/mpls_var.h>
 
@@ -123,39 +121,6 @@ extern     void db_print_backtrace(void);
 
 extern struct protosw inetsw[];
 
-#ifdef IPDIVERT
-static struct mbuf *
-ip_divert_out(struct mbuf *m, int tee)
-{
-       struct mbuf *clone = NULL;
-       struct ip *ip = mtod(m, struct ip *);
-
-       /* Clone packet if we're doing a 'tee' */
-       if (tee)
-               clone = m_dup(m, MB_DONTWAIT);
-
-       /*
-        * XXX
-        * delayed checksums are not currently compatible
-        * with divert sockets.
-        */
-       if (m->m_pkthdr.csum_flags & CSUM_DELAY_DATA) {
-               in_delayed_cksum(m);
-               m->m_pkthdr.csum_flags &= ~CSUM_DELAY_DATA;
-       }
-
-       /* Restore packet header fields to original values */
-       ip->ip_len = htons(ip->ip_len);
-       ip->ip_off = htons(ip->ip_off);
-
-       /* Deliver packet to divert input routine */
-       divert_packet(m, 0);
-
-       /* If 'tee', continue with original packet */
-       return clone;
-}
-#endif /* IPDIVERT */
-
 static int
 ip_localforward(struct mbuf *m, const struct sockaddr_in *dst)
 {
@@ -876,18 +841,18 @@ spd_done:
                        /* FALL THROUGH */
 
                case IP_FW_DIVERT:
-#ifdef IPDIVERT
-                       m = ip_divert_out(m, tee);
-                       if (m == NULL)
+                       if (ip_divert_p != NULL) {
+                               m = ip_divert_p(m, tee, 0);
+                               if (m == NULL)
+                                       goto done;
+                               ip = mtod(m, struct ip *);
+                               break;
+                       } else {
+                               m_freem(m);
+                               /* not sure this is the right error msg */
+                               error = EACCES;
                                goto done;
-                       ip = mtod(m, struct ip *);
-                       break;
-#else
-                       m_freem(m);
-                       /* not sure this is the right error msg */
-                       error = EACCES;
-                       goto done;
-#endif
+                       }
 
                default:
                        panic("unknown ipfw return value: %d\n", off);
index 50b1b1f..4f6669b 100644 (file)
@@ -32,7 +32,7 @@
  *
  *     @(#)ip_var.h    8.2 (Berkeley) 1/9/95
  * $FreeBSD: src/sys/netinet/ip_var.h,v 1.50.2.13 2003/08/24 08:24:38 hsu Exp $
- * $DragonFly: src/sys/netinet/ip_var.h,v 1.26 2008/09/12 11:37:41 sephe Exp $
+ * $DragonFly: src/sys/netinet/ip_var.h,v 1.27 2008/09/13 08:48:42 sephe Exp $
  */
 
 #ifndef _NETINET_IP_VAR_H_
@@ -195,6 +195,8 @@ int  ip_ctloutput(struct socket *, struct sockopt *sopt);
 void    ip_drain(void);
 int     ip_fragment(struct ip *ip, struct mbuf **m_frag, int mtu,
            u_long if_hwassist_flags, int sw_csum);
+struct mbuf *
+        ip_reass(struct mbuf *);
 void    ip_freemoptions(struct ip_moptions *);
 void    ip_init(void);
 extern int      (*ip_mforward)(struct ip *, struct ifnet *, struct mbuf *,