Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 7 Jan 2010 10:39:15 +0000 (UTC)
From:      Luigi Rizzo <luigi@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r201735 - in head/sys/netinet: . ipfw
Message-ID:  <201001071039.o07AdF6m025873@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: luigi
Date: Thu Jan  7 10:39:15 2010
New Revision: 201735
URL: http://svn.freebsd.org/changeset/base/201735

Log:
  Following up on a request from Ermal Luci to make
  ip_divert work as a client of pf(4),
  make ip_divert not depend on ipfw.
  
  This is achieved by moving to ip_var.h the struct ipfw_rule_ref
  (which is part of the mtag for all reinjected packets) and other
  declarations of global variables, and moving to raw_ip.c global
  variables for filter and divert hooks.
  
  Note that names and locations could be made more generic
  (ipfw_rule_ref is really a generic reference robust to reconfigurations;
  the packet filter is not necessarily ipfw; filters and their clients
  are not necessarily limited to ipv4), but _right now_ most
  of this stuff works on ipfw and ipv4, so i don't feel like
  doing a gratuitous renaming, at least for the time being.

Modified:
  head/sys/netinet/ip_divert.c
  head/sys/netinet/ip_var.h
  head/sys/netinet/ipfw/ip_fw_private.h
  head/sys/netinet/raw_ip.c

Modified: head/sys/netinet/ip_divert.c
==============================================================================
--- head/sys/netinet/ip_divert.c	Thu Jan  7 10:27:52 2010	(r201734)
+++ head/sys/netinet/ip_divert.c	Thu Jan  7 10:39:15 2010	(r201735)
@@ -32,14 +32,10 @@ __FBSDID("$FreeBSD$");
 
 #if !defined(KLD_MODULE)
 #include "opt_inet.h"
-#include "opt_ipfw.h"
 #include "opt_sctp.h"
 #ifndef INET
 #error "IPDIVERT requires INET."
 #endif
-#ifndef IPFIREWALL
-#error "IPDIVERT requires IPFIREWALL"
-#endif
 #endif
 
 #include <sys/param.h>
@@ -55,10 +51,10 @@ __FBSDID("$FreeBSD$");
 #include <sys/socket.h>
 #include <sys/socketvar.h>
 #include <sys/sysctl.h>
+#include <net/vnet.h>
 
 #include <net/if.h>
 #include <net/netisr.h> 
-#include <net/vnet.h>
 
 #include <netinet/in.h>
 #include <netinet/in_pcb.h>
@@ -66,8 +62,6 @@ __FBSDID("$FreeBSD$");
 #include <netinet/in_var.h>
 #include <netinet/ip.h>
 #include <netinet/ip_var.h>
-#include <netinet/ip_fw.h>
-#include <netinet/ipfw/ip_fw_private.h>
 #ifdef SCTP
 #include <netinet/sctp_crc32.h>
 #endif
@@ -85,27 +79,29 @@ __FBSDID("$FreeBSD$");
 #define	DIVRCVQ		(65536 + 100)
 
 /*
- * Divert sockets work in conjunction with ipfw, see the divert(4)
- * manpage for features.
- * Internally, packets selected by ipfw in ip_input() or ip_output(),
- * and never diverted before, are passed to the input queue of the
- * divert socket with a given 'divert_port' number (as specified in
- * the matching ipfw rule), and they are tagged with a 16 bit cookie
- * (representing the rule number of the matching ipfw rule), which
- * is passed to process reading from the socket.
+ * Divert sockets work in conjunction with ipfw or other packet filters,
+ * see the divert(4) manpage for features.
+ * Packets are selected by the packet filter and tagged with an
+ * MTAG_IPFW_RULE tag carrying the 'divert port' number (as set by
+ * the packet filter) and information on the matching filter rule for
+ * subsequent reinjection. The divert_port is used to put the packet
+ * on the corresponding divert socket, while the rule number is passed
+ * up (at least partially) as the sin_port in the struct sockaddr.
  *
- * Packets written to the divert socket are again tagged with a cookie
- * (usually the same as above) and a destination address.
- * If the destination address is INADDR_ANY then the packet is
- * treated as outgoing and sent to ip_output(), otherwise it is
- * treated as incoming and sent to ip_input().
- * In both cases, the packet is tagged with the cookie.
+ * Packets written to the divert socket carry in sin_addr a
+ * destination address, and in sin_port the number of the filter rule
+ * after which to continue processing.
+ * If the destination address is INADDR_ANY, the packet is treated as
+ * as outgoing and sent to ip_output(); otherwise it is treated as
+ * incoming and sent to ip_input().
+ * Further, sin_zero carries some information on the interface,
+ * which can be used in the reinject -- see comments in the code.
  *
  * On reinjection, processing in ip_input() and ip_output()
  * will be exactly the same as for the original packet, except that
- * ipfw processing will start at the rule number after the one
- * written in the cookie (so, tagging a packet with a cookie of 0
- * will cause it to be effectively considered as a standard packet).
+ * packet filter processing will start at the rule number after the one
+ * written in the sin_port (ipfw does not allow a rule #0, so sin_port=0
+ * will apply the entire ruleset to the packet).
  */
 
 /* Internal variables. */

Modified: head/sys/netinet/ip_var.h
==============================================================================
--- head/sys/netinet/ip_var.h	Thu Jan  7 10:27:52 2010	(r201734)
+++ head/sys/netinet/ip_var.h	Thu Jan  7 10:39:15 2010	(r201735)
@@ -249,7 +249,43 @@ VNET_DECLARE(struct pfil_head, inet_pfil
 
 void	in_delayed_cksum(struct mbuf *m);
 
-/* ipfw and dummynet hooks. Most are declared in raw_ip.c */
+/* Hooks for ipfw, dummynet, divert etc. Most are declared in raw_ip.c */
+/*
+ * Reference to an ipfw or packet filter rule that can be carried
+ * outside critical sections.
+ * A rule is identified by rulenum:rule_id which is ordered.
+ * In version chain_id the rule can be found in slot 'slot', so
+ * we don't need a lookup if chain_id == chain->id.
+ *
+ * On exit from the firewall this structure refers to the rule after
+ * the matching one (slot points to the new rule; rulenum:rule_id-1
+ * is the matching rule), and additional info (e.g. info often contains
+ * the insn argument or tablearg in the low 16 bits, in host format).
+ * On entry, the structure is valid if slot>0, and refers to the starting
+ * rules. 'info' contains the reason for reinject, e.g. divert port,
+ * divert direction, and so on.
+ */
+struct ipfw_rule_ref {
+	uint32_t	slot;		/* slot for matching rule	*/
+	uint32_t	rulenum;	/* matching rule number		*/
+	uint32_t	rule_id;	/* matching rule id		*/
+	uint32_t	chain_id;	/* ruleset id			*/
+	uint32_t	info;		/* see below			*/
+};
+
+enum {
+	IPFW_INFO_MASK	= 0x0000ffff,
+	IPFW_INFO_OUT	= 0x00000000,	/* outgoing, just for convenience */
+	IPFW_INFO_IN	= 0x80000000,	/* incoming, overloads dir */
+	IPFW_ONEPASS	= 0x40000000,	/* One-pass, do not reinject */
+	IPFW_IS_MASK	= 0x30000000,	/* which source ? */
+	IPFW_IS_DIVERT	= 0x20000000,
+	IPFW_IS_DUMMYNET =0x10000000,
+	IPFW_IS_PIPE	= 0x08000000,	/* pip1=1, queue = 0 */
+};
+#define MTAG_IPFW	1148380143	/* IPFW-tagged cookie */
+#define MTAG_IPFW_RULE	1262273568	/* rule reference */
+
 struct ip_fw_args;
 typedef int	(*ip_fw_chk_ptr_t)(struct ip_fw_args *args);
 typedef int	(*ip_fw_ctl_ptr_t)(struct sockopt *);
@@ -258,9 +294,14 @@ VNET_DECLARE(ip_fw_ctl_ptr_t, ip_fw_ctl_
 #define	V_ip_fw_chk_ptr		VNET(ip_fw_chk_ptr)
 #define	V_ip_fw_ctl_ptr		VNET(ip_fw_ctl_ptr)
 
+/* Divert hooks. */
+extern void	(*ip_divert_ptr)(struct mbuf *m, int incoming);
+/* ng_ipfw hooks -- XXX make it the same as divert and dummynet */
+extern int	(*ng_ipfw_input_p)(struct mbuf **, int,
+			struct ip_fw_args *, int);
+
 extern int	(*ip_dn_ctl_ptr)(struct sockopt *);
-extern int	(*ip_dn_io_ptr)(struct mbuf **m, int dir, struct ip_fw_args *fwa);
-extern void	(*ip_dn_ruledel_ptr)(void *);		/* in ip_fw2.c */
+extern int	(*ip_dn_io_ptr)(struct mbuf **, int, struct ip_fw_args *);
 
 VNET_DECLARE(int, ip_do_randomid);
 #define	V_ip_do_randomid	VNET(ip_do_randomid)

Modified: head/sys/netinet/ipfw/ip_fw_private.h
==============================================================================
--- head/sys/netinet/ipfw/ip_fw_private.h	Thu Jan  7 10:27:52 2010	(r201734)
+++ head/sys/netinet/ipfw/ip_fw_private.h	Thu Jan  7 10:39:15 2010	(r201735)
@@ -35,8 +35,6 @@
 
 #ifdef _KERNEL
 
-#define MTAG_IPFW	1148380143	/* IPFW-tagged cookie */
-#define MTAG_IPFW_RULE	1262273568	/* rule reference */
 
 /* Return values from ipfw_chk() */
 enum {
@@ -66,38 +64,6 @@ struct _ip6dn_args {
        struct route_in6 ro_pmtu_or;
 };
 
-/*
- * Reference to an ipfw rule that can be carried outside critical sections.
- * A rule is identified by rulenum:rule_id which is ordered.
- * In version chain_id the rule can be found in slot 'slot', so
- * we don't need a lookup if chain_id == chain->id.
- *
- * On exit from the firewall this structure refers to the rule after
- * the matching one (slot points to the new rule; rulenum:rule_id-1
- * is the matching rule), and additional info (e.g. info often contains
- * the insn argument or tablearg in the low 16 bits, in host format).
- * On entry, the structure is valid if slot>0, and refers to the starting
- * rules. 'info' contains the reason for reinject, e.g. divert port,
- * divert direction, and so on.
- */
-struct ipfw_rule_ref {
-	uint32_t	slot;		/* slot for matching rule	*/
-	uint32_t	rulenum;	/* matching rule number		*/
-	uint32_t	rule_id;	/* matching rule id		*/
-	uint32_t	chain_id;	/* ruleset id			*/
-	uint32_t	info;		/* see below			*/
-};
-
-enum {
-	IPFW_INFO_MASK	= 0x0000ffff,
-	IPFW_INFO_OUT	= 0x00000000,	/* outgoing, just for convenience */
-	IPFW_INFO_IN	= 0x80000000,	/* incoming, overloads dir */
-	IPFW_ONEPASS	= 0x40000000,	/* One-pass, do not reinject */
-	IPFW_IS_MASK	= 0x30000000,	/* which source ? */
-	IPFW_IS_DIVERT	= 0x20000000,
-	IPFW_IS_DUMMYNET =0x10000000,
-	IPFW_IS_PIPE	= 0x08000000,	/* pip1=1, queue = 0 */
-};
 
 /*
  * Arguments for calling ipfw_chk() and dummynet_io(). We put them
@@ -289,10 +255,7 @@ int ipfw_del_table_entry(struct ip_fw_ch
 int ipfw_count_table(struct ip_fw_chain *ch, uint32_t tbl, uint32_t *cnt);
 int ipfw_dump_table(struct ip_fw_chain *ch, ipfw_table *tbl);
 
-/* hooks for divert */
-extern void (*ip_divert_ptr)(struct mbuf *m, int incoming);
-
-/* In ip_fw_nat.c */
+/* In ip_fw_nat.c -- XXX to be moved to ip_var.h */
 
 extern struct cfg_nat *(*lookup_nat_ptr)(struct nat_list *, int);
 
@@ -307,14 +270,5 @@ extern ipfw_nat_cfg_t *ipfw_nat_del_ptr;
 extern ipfw_nat_cfg_t *ipfw_nat_get_cfg_ptr;
 extern ipfw_nat_cfg_t *ipfw_nat_get_log_ptr;
 
-/* netgraph prototypes */
-
-typedef int ng_ipfw_input_t(struct mbuf **, int, struct ip_fw_args *, int);
-extern  ng_ipfw_input_t *ng_ipfw_input_p;
-#define NG_IPFW_LOADED  (ng_ipfw_input_p != NULL)
-
-#define TAGSIZ  (sizeof(struct ng_ipfw_tag) - sizeof(struct m_tag))
-
-
 #endif /* _KERNEL */
 #endif /* _IPFW2_PRIVATE_H */

Modified: head/sys/netinet/raw_ip.c
==============================================================================
--- head/sys/netinet/raw_ip.c	Thu Jan  7 10:27:52 2010	(r201734)
+++ head/sys/netinet/raw_ip.c	Thu Jan  7 10:39:15 2010	(r201735)
@@ -80,14 +80,18 @@ VNET_DEFINE(struct inpcbinfo, ripcbinfo)
 #define	V_ripcbinfo		VNET(ripcbinfo)
 
 /*
- * Control and data hooks for ipfw and dummynet.
+ * Control and data hooks for ipfw, dummynet, divert and so on.
  * The data hooks are not used here but it is convenient
  * to keep them all in one place.
  */
 VNET_DEFINE(ip_fw_chk_ptr_t, ip_fw_chk_ptr) = NULL;
 VNET_DEFINE(ip_fw_ctl_ptr_t, ip_fw_ctl_ptr) = NULL;
-int (*ip_dn_ctl_ptr)(struct sockopt *) = NULL;
-int (*ip_dn_io_ptr)(struct mbuf **m, int dir, struct ip_fw_args *fwa) = NULL;
+
+int	(*ip_dn_ctl_ptr)(struct sockopt *);
+int	(*ip_dn_io_ptr)(struct mbuf **, int, struct ip_fw_args *);
+void	(*ip_divert_ptr)(struct mbuf *, int);
+int	(*ng_ipfw_input_p)(struct mbuf **, int,
+			struct ip_fw_args *, int);
 
 /*
  * Hooks for multicast routing. They all default to NULL, so leave them not



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201001071039.o07AdF6m025873>