diff options
author | luigi <luigi@FreeBSD.org> | 2010-01-07 10:39:15 +0000 |
---|---|---|
committer | luigi <luigi@FreeBSD.org> | 2010-01-07 10:39:15 +0000 |
commit | db333db4e680708d586264636ea6a5968be810ac (patch) | |
tree | 5011e2610be6e93e190c2d7fc7e30482ada9ac57 /sys/netinet | |
parent | f1fcae96add4034bc2e513e4a13d14851c00d0b4 (diff) | |
download | FreeBSD-src-db333db4e680708d586264636ea6a5968be810ac.zip FreeBSD-src-db333db4e680708d586264636ea6a5968be810ac.tar.gz |
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.
Diffstat (limited to 'sys/netinet')
-rw-r--r-- | sys/netinet/ip_divert.c | 44 | ||||
-rw-r--r-- | sys/netinet/ip_var.h | 47 | ||||
-rw-r--r-- | sys/netinet/ipfw/ip_fw_private.h | 48 | ||||
-rw-r--r-- | sys/netinet/raw_ip.c | 10 |
4 files changed, 72 insertions, 77 deletions
diff --git a/sys/netinet/ip_divert.c b/sys/netinet/ip_divert.c index 811ca06..225dd46 100644 --- a/sys/netinet/ip_divert.c +++ b/sys/netinet/ip_divert.c @@ -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. */ diff --git a/sys/netinet/ip_var.h b/sys/netinet/ip_var.h index a1d2166..d041dd3 100644 --- a/sys/netinet/ip_var.h +++ b/sys/netinet/ip_var.h @@ -249,7 +249,43 @@ VNET_DECLARE(struct pfil_head, inet_pfil_hook); /* packet filter hooks */ 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_ptr); #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) diff --git a/sys/netinet/ipfw/ip_fw_private.h b/sys/netinet/ipfw/ip_fw_private.h index cfc07aa..92508f1 100644 --- a/sys/netinet/ipfw/ip_fw_private.h +++ b/sys/netinet/ipfw/ip_fw_private.h @@ -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_chain *ch, uint16_t tbl, in_addr_t addr, 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 */ diff --git a/sys/netinet/raw_ip.c b/sys/netinet/raw_ip.c index 3573472..9341cf2 100644 --- a/sys/netinet/raw_ip.c +++ b/sys/netinet/raw_ip.c @@ -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 |