* [PATCH] Runtime interception method switch
@ 2008-01-13 15:12 Raphael Vallazza
2008-01-13 17:59 ` Joseph Mack NA3T
2008-01-15 8:20 ` Simon Horman
0 siblings, 2 replies; 14+ messages in thread
From: Raphael Vallazza @ 2008-01-13 15:12 UTC (permalink / raw)
To: LVS Devel
Hi,
i've just finished the patch for changing the connection interception
method at runtime (in /proc/sys/net/ipv4/vs/input_hook), it works
pretty well :) I've tested it with all the seetings and it worked
without any problems.
It has been made for net-2.6.25 branch. I've also made some minor
corrections to the "connection interception choice patch". These
patches have to be appliet together...
Thanks,
Raphael
P.S. i hope my mailer doesn't mess up the patches this time :-/
--
:: e n d i a n
:: open source - open minds
#### 0001-IPVS-Add-choice-for-connection-interception-method.patch ####
[PATCH] [IPVS]: Add choice for connection interception method
This patch adds an option to set the position at which IPVS intercepts
incoming connections from Netfilter.
The options are:
1. INPUT (default)
Intercept incoming connections after they have traveled through
the INPUT table, only connections that have the director as
destination address will be processed.
2. FORWARD
Intercept incoming connections after they have traveled through
the INPUT or the FORWARD table. It has the same functionlity of
the "INPUT method", but also processes connections that are
routed through the director, supporting VIP-less setups.
3. PREROUTING
Intercept incoming connections before DNAT and input filtering
has been applied, this enables transparent proxying on realnodes
and localnode.
Signed-off-by: Raphael Vallazza <raphael@endian.com>
---
net/ipv4/ipvs/Kconfig | 44 +++++++++++++++++++++++++++++++++++
+++++++++
net/ipv4/ipvs/ip_vs_core.c | 30 +++++++++++++++++++++++++++++-
2 files changed, 73 insertions(+), 1 deletions(-)
diff --git a/net/ipv4/ipvs/Kconfig b/net/ipv4/ipvs/Kconfig
index 09d0c3f..319f3e8 100644
--- a/net/ipv4/ipvs/Kconfig
+++ b/net/ipv4/ipvs/Kconfig
@@ -24,6 +24,50 @@ menuconfig IP_VS
if IP_VS
+choice
+ prompt "IPVS connection interception method"
+ default IP_VS_INPUT_LOCAL_IN
+ help
+ This option sets the position at which IPVS intercepts incoming
+ connections from Netfilter. If in doubt select 'LOCAL_IN'.
+
+config IP_VS_INPUT_LOCAL_IN
+ bool "INPUT"
+ ---help---
+ Intercept incoming connections after they have traveled through
+ the INPUT table, only connections that have the director as
+ destination address will be processed.
+
+ This method allows to apply packet filtering in the INPUT table
+ before the connection is intercepted by IPVS.
+
+config IP_VS_INPUT_FORWARD
+ bool "FORWARD"
+ ---help---
+ Intercept incoming connections after they have traveled through
+ the INPUT or the FORWARD table. It has the same functionlity of
+ the "INPUT method", but also processes connections that are
+ routed through the director, supporting VIP-less setups.
+
+ This method allows to apply packet filtering in the INPUT or
+ FORWARD table, before the connection is intercepted by IPVS.
+
+config IP_VS_INPUT_PRE_ROUTING
+ bool "PREROUTING"
+ ---help---
+ Intercept incoming connections before DNAT and input filtering
+ has been applied, this allows transparent proxying on realnodes
+ and localnode. Incoming connections are intercepted right after
+ the mangle PREROUTING table and before the nat PREROUTING table,
+ supporting VIP-less setups.
+
+ WARNING: This method doesn't apply any packet filtering before
+ packets are intercepted by IPVS. To filter the connections that
+ should be intercepted, you have to mark the traffic in the
+ mangle PREROUTING table.
+
+endchoice
+
config IP_VS_DEBUG
bool "IP virtual server debugging"
---help---
diff --git a/net/ipv4/ipvs/ip_vs_core.c b/net/ipv4/ipvs/ip_vs_core.c
index 963981a..0da4ef6 100644
--- a/net/ipv4/ipvs/ip_vs_core.c
+++ b/net/ipv4/ipvs/ip_vs_core.c
@@ -1026,6 +1026,7 @@ ip_vs_forward_icmp(unsigned int hooknum, struct
sk_buff *skb,
static struct nf_hook_ops ip_vs_ops[] __read_mostly = {
+#if defined(CONFIG_IP_VS_INPUT_LOCAL_IN) ||
defined(CONFIG_IP_VS_INPUT_FORWARD)
/* After packet filtering, forward packet through VS/DR, VS/TUN,
* or VS/NAT(change destination), so that filtering rules can be
* applied to IPVS. */
@@ -1036,6 +1037,33 @@ static struct nf_hook_ops ip_vs_ops[]
__read_mostly = {
.hooknum = NF_INET_LOCAL_IN,
.priority = 100,
},
+#endif
+#ifdef CONFIG_IP_VS_INPUT_FORWARD
+ /* Intercept incoming connections after they have traveled through
+ * the INPUT or the FORWARD table. It has the same functionlity of
+ * the "INPUT method", but also processes connections that are
+ * routed through the director, supporting VIP-less setups. */
+ {
+ .hook = ip_vs_in,
+ .owner = THIS_MODULE,
+ .pf = PF_INET,
+ .hooknum = NF_INET_FORWARD,
+ .priority = 98,
+ },
+#endif
+#ifdef CONFIG_IP_VS_INPUT_PRE_ROUTING
+ /* Intercept incoming connections before DNAT and input filtering
+ * has been applied, this enables ransparent proxying on realnodes
+ * and localnode. Hook right after MANGLE and before NAT_DST.
+ */
+ {
+ .hook = ip_vs_in,
+ .owner = THIS_MODULE,
+ .pf = PF_INET,
+ .hooknum = NF_INET_PRE_ROUTING,
+ .priority = NF_IP_PRI_NAT_DST - 1,
+ },
+#endif
/* After packet filtering, change source only for VS/NAT */
{
.hook = ip_vs_out,
@@ -1059,7 +1087,7 @@ static struct nf_hook_ops ip_vs_ops[]
__read_mostly = {
.owner = THIS_MODULE,
.pf = PF_INET,
.hooknum = NF_INET_POST_ROUTING,
- .priority = NF_IP_PRI_NAT_SRC-1,
+ .priority = NF_IP_PRI_NAT_SRC - 1,
},
};
--
1.5.3.7
#### 0002-IPVS-Runtime-interception-method-switch.patch ####
[IPVS]: Runtime interception method switch
This patch allows to switch interception method at runtime by changing
the value of /proc/sys/net/ipv4/vs/input_hook with one of the following
values:
0 = INPUT
1 = FORWARD
2 = PREROUTING
Signed-off-by: Raphael Vallazza <raphael@endian.com>
---
include/net/ip_vs.h | 15 +++++
net/ipv4/ipvs/Kconfig | 10 +++-
net/ipv4/ipvs/ip_vs_core.c | 141 +++++++++++++++++++++++++++++++++++
++-------
net/ipv4/ipvs/ip_vs_ctl.c | 43 +++++++++++++
4 files changed, 186 insertions(+), 23 deletions(-)
diff --git a/include/net/ip_vs.h b/include/net/ip_vs.h
index 56f3c94..6b71e31 100644
--- a/include/net/ip_vs.h
+++ b/include/net/ip_vs.h
@@ -681,6 +681,21 @@ extern void ip_vs_init_hash_table(struct
list_head *table, int rows);
#define IP_VS_APP_TYPE_FTP 1
/*
+ * IPVS input hook functions
+ */
+enum {
+ IP_VS_INPUT_HOOK_FIRST = -1,
+ IP_VS_INPUT_HOOK_LOCAL_IN,
+ IP_VS_INPUT_HOOK_FORWARD,
+ IP_VS_INPUT_HOOK_PRE_ROUTING,
+ IP_VS_INPUT_HOOK_LAST,
+};
+
+extern int ip_vs_get_input_hook(void);
+extern int ip_vs_register_hooks(int input_hook);
+extern int ip_vs_unregister_hooks(int input_hook);
+
+/*
* ip_vs_conn handling functions
* (from ip_vs_conn.c)
*/
diff --git a/net/ipv4/ipvs/Kconfig b/net/ipv4/ipvs/Kconfig
index 319f3e8..19217d7 100644
--- a/net/ipv4/ipvs/Kconfig
+++ b/net/ipv4/ipvs/Kconfig
@@ -28,8 +28,14 @@ choice
prompt "IPVS connection interception method"
default IP_VS_INPUT_LOCAL_IN
help
- This option sets the position at which IPVS intercepts incoming
- connections from Netfilter. If in doubt select 'LOCAL_IN'.
+ This option selects the default position at which IPVS intercepts
+ incoming connections from Netfilter. If in doubt select 'INPUT'.
+
+ The interception method can be switched at runtime in
+ /proc/sys/net/ipv4/vs/input_hook with the following values:
+ 0 = INPUT
+ 1 = FORWARD
+ 2 = PREROUTING
config IP_VS_INPUT_LOCAL_IN
bool "INPUT"
diff --git a/net/ipv4/ipvs/ip_vs_core.c b/net/ipv4/ipvs/ip_vs_core.c
index 0da4ef6..6acfbbd 100644
--- a/net/ipv4/ipvs/ip_vs_core.c
+++ b/net/ipv4/ipvs/ip_vs_core.c
@@ -1024,12 +1024,111 @@ ip_vs_forward_icmp(unsigned int hooknum,
struct sk_buff *skb,
return ip_vs_in_icmp(skb, &r, hooknum);
}
+/*
+ * Register netfilter hook based on input_hook type
+ */
+
+int ip_vs_register_hooks(int input_hook)
+{
+ int ret;
+ char *hookstr;
+ struct nf_hook_ops *in_hooks;
+ int count;
+
+ IP_VS_DBG(5, "Registering input hooks: %i\n", input_hook);
+
+ switch (input_hook) {
+ case IP_VS_INPUT_HOOK_LOCAL_IN:
+ hookstr = "INPUT";
+ in_hooks = ip_vs_ops_local_in;
+ count = ARRAY_SIZE(ip_vs_ops_local_in);
+ break;
+ case IP_VS_INPUT_HOOK_FORWARD:
+ hookstr = "FORWARD";
+ in_hooks = ip_vs_ops_forward;
+ count = ARRAY_SIZE(ip_vs_ops_forward);
+ break;
+ case IP_VS_INPUT_HOOK_PRE_ROUTING:
+ hookstr = "PREROUTING";
+ in_hooks = ip_vs_ops_pre_routing;
+ count = ARRAY_SIZE(ip_vs_ops_pre_routing);
+ break;
+ default:
+ return -1;
+ }
+
+ ret = nf_register_hooks(in_hooks, count);
+ if (ret < 0) {
+ IP_VS_ERR("Can't register %s hooks.\n", hookstr);
+ return -1;
+ }
+
+ ret = nf_register_hooks(ip_vs_ops_generic,
+ ARRAY_SIZE(ip_vs_ops_generic));
+ if (ret < 0) {
+ nf_unregister_hooks(in_hooks, count);
+ IP_VS_ERR("Can't register generic hooks.\n");
+ return -1;
+ }
+
+ IP_VS_INFO("Registered interception method: %s\n", hookstr);
+ return 0;
+}
+
+/*
+ * Unregister netfilter hook based on input_hook type
+ */
-static struct nf_hook_ops ip_vs_ops[] __read_mostly = {
-#if defined(CONFIG_IP_VS_INPUT_LOCAL_IN) ||
defined(CONFIG_IP_VS_INPUT_FORWARD)
- /* After packet filtering, forward packet through VS/DR, VS/TUN,
- * or VS/NAT(change destination), so that filtering rules can be
- * applied to IPVS. */
+int ip_vs_unregister_hooks(int input_hook)
+{
+ struct nf_hook_ops *in_hooks;
+ int count;
+
+ IP_VS_DBG(5, "Unregistering input hooks: %i\n", input_hook);
+
+ switch (input_hook) {
+ case IP_VS_INPUT_HOOK_LOCAL_IN:
+ in_hooks = ip_vs_ops_local_in;
+ count = ARRAY_SIZE(ip_vs_ops_local_in);
+ break;
+ case IP_VS_INPUT_HOOK_FORWARD:
+ in_hooks = ip_vs_ops_forward;
+ count = ARRAY_SIZE(ip_vs_ops_forward);
+ break;
+ case IP_VS_INPUT_HOOK_PRE_ROUTING:
+ in_hooks = ip_vs_ops_pre_routing;
+ count = ARRAY_SIZE(ip_vs_ops_pre_routing);
+ break;
+ default:
+ return -1;
+ }
+
+ nf_unregister_hooks(in_hooks, count);
+ nf_unregister_hooks(ip_vs_ops_generic, ARRAY_SIZE(ip_vs_ops_generic));
+
+ IP_VS_DBG(5, "Unregistered input hooks.\n");
+ return 0;
+}
+
+
+/* After packet filtering, forward packet through VS/DR, VS/TUN,
+ * or VS/NAT(change destination), so that filtering rules can be
+ * applied to IPVS. */
+static struct nf_hook_ops ip_vs_ops_local_in[] __read_mostly = {
+ {
+ .hook = ip_vs_in,
+ .owner = THIS_MODULE,
+ .pf = PF_INET,
+ .hooknum = NF_INET_LOCAL_IN,
+ .priority = 100,
+ },
+};
+
+/* Intercept incoming connections after they have traveled through
+ * the INPUT or the FORWARD table. It has the same functionlity of
+ * the "INPUT method", but also processes connections that are
+ * routed through the director, supporting VIP-less setups. */
+static struct nf_hook_ops ip_vs_ops_forward[] __read_mostly = {
{
.hook = ip_vs_in,
.owner = THIS_MODULE,
@@ -1037,12 +1136,6 @@ static struct nf_hook_ops ip_vs_ops[]
__read_mostly = {
.hooknum = NF_INET_LOCAL_IN,
.priority = 100,
},
-#endif
-#ifdef CONFIG_IP_VS_INPUT_FORWARD
- /* Intercept incoming connections after they have traveled through
- * the INPUT or the FORWARD table. It has the same functionlity of
- * the "INPUT method", but also processes connections that are
- * routed through the director, supporting VIP-less setups. */
{
.hook = ip_vs_in,
.owner = THIS_MODULE,
@@ -1050,12 +1143,13 @@ static struct nf_hook_ops ip_vs_ops[]
__read_mostly = {
.hooknum = NF_INET_FORWARD,
.priority = 98,
},
-#endif
-#ifdef CONFIG_IP_VS_INPUT_PRE_ROUTING
- /* Intercept incoming connections before DNAT and input filtering
- * has been applied, this enables ransparent proxying on realnodes
- * and localnode. Hook right after MANGLE and before NAT_DST.
- */
+};
+
+/* Intercept incoming connections before DNAT and input filtering
+ * has been applied, this enables ransparent proxying on realnodes
+ * and localnode. Hook right after MANGLE and before NAT_DST.
+ */
+static struct nf_hook_ops ip_vs_ops_pre_routing[] __read_mostly = {
{
.hook = ip_vs_in,
.owner = THIS_MODULE,
@@ -1063,7 +1157,13 @@ static struct nf_hook_ops ip_vs_ops[]
__read_mostly = {
.hooknum = NF_INET_PRE_ROUTING,
.priority = NF_IP_PRI_NAT_DST - 1,
},
-#endif
+};
+
+/*
+ * Generic Netfilter hooks required for all the input methods
+ */
+
+static struct nf_hook_ops ip_vs_ops_generic[] __read_mostly = {
/* After packet filtering, change source only for VS/NAT */
{
.hook = ip_vs_out,
@@ -1119,9 +1219,8 @@ static int __init ip_vs_init(void)
goto cleanup_app;
}
- ret = nf_register_hooks(ip_vs_ops, ARRAY_SIZE(ip_vs_ops));
+ ret = ip_vs_register_hooks(ip_vs_get_input_hook());
if (ret < 0) {
- IP_VS_ERR("can't register hooks.\n");
goto cleanup_conn;
}
@@ -1141,7 +1240,7 @@ static int __init ip_vs_init(void)
static void __exit ip_vs_cleanup(void)
{
- nf_unregister_hooks(ip_vs_ops, ARRAY_SIZE(ip_vs_ops));
+ ip_vs_unregister_hooks(ip_vs_get_input_hook());
ip_vs_conn_cleanup();
ip_vs_app_cleanup();
ip_vs_protocol_cleanup();
diff --git a/net/ipv4/ipvs/ip_vs_ctl.c b/net/ipv4/ipvs/ip_vs_ctl.c
index 94c5767..1e05c54 100644
--- a/net/ipv4/ipvs/ip_vs_ctl.c
+++ b/net/ipv4/ipvs/ip_vs_ctl.c
@@ -82,6 +82,15 @@ int sysctl_ip_vs_expire_quiescent_template = 0;
int sysctl_ip_vs_sync_threshold[2] = { 3, 50 };
int sysctl_ip_vs_nat_icmp_send = 0;
+#ifdef CONFIG_IP_VS_INPUT_LOCAL_IN
+static int sysctl_ip_vs_input_hook = IP_VS_INPUT_HOOK_LOCAL_IN;
+#endif
+#ifdef CONFIG_IP_VS_INPUT_FORWARD
+static int sysctl_ip_vs_input_hook = IP_VS_INPUT_HOOK_FORWARD;
+#endif
+#ifdef CONFIG_IP_VS_INPUT_PRE_ROUTING
+static int sysctl_ip_vs_input_hook = IP_VS_INPUT_HOOK_PRE_ROUTING;
+#endif
#ifdef CONFIG_IP_VS_DEBUG
static int sysctl_ip_vs_debug_level = 0;
@@ -92,6 +101,11 @@ int ip_vs_get_debug_level(void)
}
#endif
+int ip_vs_get_input_hook(void)
+{
+ return sysctl_ip_vs_input_hook;
+}
+
/*
* update_defense_level is called from keventd and from sysctl,
* so it needs to protect itself from softirqs
@@ -1376,6 +1390,28 @@ static int ip_vs_zero_all(void)
return 0;
}
+static int
+proc_do_input_hook(struct ctl_table *table, int write, struct file
*filp,
+ void __user *buffer, size_t *lenp, loff_t *ppos)
+{
+ char *valp = table->data;
+ int oldval = *valp;
+ int rc;
+
+ rc = proc_dointvec(table, write, filp, buffer, lenp, ppos);
+ if (write && (*valp != oldval)) {
+ if ((*valp <= IP_VS_INPUT_HOOK_FIRST) ||
+ (*valp >= IP_VS_INPUT_HOOK_LAST)) {
+ IP_VS_ERR("Invalid input hook value: %i\n", *valp);
+ *valp = oldval;
+ } else {
+ /* unregister old and register new input hooks */
+ ip_vs_unregister_hooks(oldval);
+ ip_vs_register_hooks(*valp);
+ }
+ }
+ return rc;
+}
static int
proc_do_defense_mode(ctl_table *table, int write, struct file * filp,
@@ -1430,6 +1466,13 @@ static struct ctl_table vs_vars[] = {
.mode = 0644,
.proc_handler = &proc_dointvec,
},
+ {
+ .procname = "input_hook",
+ .data = &sysctl_ip_vs_input_hook,
+ .maxlen = sizeof(int),
+ .mode = 0644,
+ .proc_handler = &proc_do_input_hook,
+ },
#ifdef CONFIG_IP_VS_DEBUG
{
.procname = "debug_level",
--
1.5.3.7
^ permalink raw reply related [flat|nested] 14+ messages in thread
* Re: [PATCH] Runtime interception method switch
2008-01-13 15:12 [PATCH] Runtime interception method switch Raphael Vallazza
@ 2008-01-13 17:59 ` Joseph Mack NA3T
2008-01-14 8:39 ` Raphael Vallazza
2008-01-15 8:20 ` Simon Horman
1 sibling, 1 reply; 14+ messages in thread
From: Joseph Mack NA3T @ 2008-01-13 17:59 UTC (permalink / raw)
To: LVS Devel
On Sun, 13 Jan 2008, Raphael Vallazza wrote:
> 3. PREROUTING Intercept incoming connections before DNAT
> and input filtering has been applied, this enables
> transparent proxying on realnodes and localnode.
Raphael,
What's the best way of implementing F5-SNAT? All
packets must arrive at the realservers with src_addr=DIP.
Where should ipvs be hooked and where should the iptables
rules be to NAT the packets?
client: CIP->VIP:80
ipvs on LVS-NAT director: CIP->RIP:80
iptables rules on director (in POSTROUTING?) DIP->RIP:80
realserver: RIP:80->DIP
iptables rules on director RIP:80->CIP
ipvs on LVS-NAT director: VIP:80->CIP
client: gets packet VIP:80->CIP
Thanks
Joe
--
Joseph Mack NA3T EME(B,D), FM05lw North Carolina
jmack (at) wm7d (dot) net - azimuthal equidistant map
generator at http://www.wm7d.net/azproj.shtml
Homepage http://www.austintek.com/ It's GNU/Linux!
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH] Runtime interception method switch
2008-01-13 17:59 ` Joseph Mack NA3T
@ 2008-01-14 8:39 ` Raphael Vallazza
2008-01-14 9:42 ` Joseph Mack NA3T
0 siblings, 1 reply; 14+ messages in thread
From: Raphael Vallazza @ 2008-01-14 8:39 UTC (permalink / raw)
To: Joseph Mack NA3T; +Cc: LVS Devel
I think this has nothing to with the input method, it's more a problem
of the *xmit* function. Packets for realservers don't seem to flow
through the SNAT chain, this way it's not possible to change the
source IP.
This could probably be implemented either by letting the packets flow
through the iptables/SNAT (it seems that the patch on http://www.austintek.com/LVS/LVS-HOWTO/HOWTO/LVS-HOWTO.non-modified_realservers.html
does this), or to implement SNAT in the IPVS/NAT method.
Raphael
Am 13.01.2008 um 18:59 schrieb Joseph Mack NA3T:
> On Sun, 13 Jan 2008, Raphael Vallazza wrote:
>
>> 3. PREROUTING Intercept incoming connections before DNAT and input
>> filtering has been applied, this enables transparent proxying on
>> realnodes and localnode.
>
> Raphael,
>
> What's the best way of implementing F5-SNAT? All packets must
> arrive at the realservers with src_addr=DIP. Where should ipvs be
> hooked and where should the iptables rules be to NAT the packets?
>
> client: CIP->VIP:80
>
> ipvs on LVS-NAT director: CIP->RIP:80
>
> iptables rules on director (in POSTROUTING?) DIP->RIP:80
>
> realserver: RIP:80->DIP
>
> iptables rules on director RIP:80->CIP
>
> ipvs on LVS-NAT director: VIP:80->CIP
>
> client: gets packet VIP:80->CIP
>
> Thanks Joe
> --
> Joseph Mack NA3T EME(B,D), FM05lw North Carolina
> jmack (at) wm7d (dot) net - azimuthal equidistant map
> generator at http://www.wm7d.net/azproj.shtml
> Homepage http://www.austintek.com/ It's GNU/Linux!
> -
> To unsubscribe from this list: send the line "unsubscribe lvs-devel"
> in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
--
:: e n d i a n
:: open source - open minds
:: raphael vallazza
:: phone +39 0471 631763 :: fax +39 0471 631764
:: http://www.endian.com :: raphael (AT) endian.com
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH] Runtime interception method switch
2008-01-14 8:39 ` Raphael Vallazza
@ 2008-01-14 9:42 ` Joseph Mack NA3T
2008-01-15 8:25 ` Simon Horman
0 siblings, 1 reply; 14+ messages in thread
From: Joseph Mack NA3T @ 2008-01-14 9:42 UTC (permalink / raw)
To: LVS Devel
On Mon, 14 Jan 2008, Raphael Vallazza wrote:
> I think this has nothing to with the input method,
I'd assumed that it would be fixed by hooking the FORWARD
chain because then the packets wouldn't bypass netfilter.
> it's more a problem of the *xmit* function. Packets for
> realservers don't seem to flow through the SNAT chain,
> this way it's not possible to change the source IP.
OK
> This could probably be implemented either by letting the
> packets flow through the iptables/SNAT (it seems that the
> patch on
> http://www.austintek.com/LVS/LVS-HOWTO/HOWTO/LVS-HOWTO.non-modified_realservers.html
> does this),
can this be put into the standard ipvs?
> or to implement SNAT in the IPVS/NAT method.
can you do either of these?
Thanks Joe
--
Joseph Mack NA3T EME(B,D), FM05lw North Carolina
jmack (at) wm7d (dot) net - azimuthal equidistant map
generator at http://www.wm7d.net/azproj.shtml
Homepage http://www.austintek.com/ It's GNU/Linux!
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH] Runtime interception method switch
2008-01-13 15:12 [PATCH] Runtime interception method switch Raphael Vallazza
2008-01-13 17:59 ` Joseph Mack NA3T
@ 2008-01-15 8:20 ` Simon Horman
1 sibling, 0 replies; 14+ messages in thread
From: Simon Horman @ 2008-01-15 8:20 UTC (permalink / raw)
To: Raphael Vallazza; +Cc: LVS Devel
On Sun, Jan 13, 2008 at 04:12:38PM +0100, Raphael Vallazza wrote:
> Hi,
>
> i've just finished the patch for changing the connection interception
> method at runtime (in /proc/sys/net/ipv4/vs/input_hook), it works pretty
> well :) I've tested it with all the seetings and it worked without any
> problems.
>
> It has been made for net-2.6.25 branch. I've also made some minor
> corrections to the "connection interception choice patch". These patches
> have to be appliet together...
>
> Thanks,
> Raphael
>
> P.S. i hope my mailer doesn't mess up the patches this time :-/
Unfortunately it did :-(
That asside, the patches look basically good.
I rediffed them and they seem to work fine.
Let me know if you want my version of the patches,
though I have not fixed all the issues that I saw.
Comments in-line.
> --
> :: e n d i a n
> :: open source - open minds
>
>
> #### 0001-IPVS-Add-choice-for-connection-interception-method.patch ####
>
> [PATCH] [IPVS]: Add choice for connection interception method
>
> This patch adds an option to set the position at which IPVS intercepts
> incoming connections from Netfilter.
>
> The options are:
>
> 1. INPUT (default)
> Intercept incoming connections after they have traveled through
> the INPUT table, only connections that have the director as
> destination address will be processed.
>
> 2. FORWARD
> Intercept incoming connections after they have traveled through
> the INPUT or the FORWARD table. It has the same functionlity of
> the "INPUT method", but also processes connections that are
> routed through the director, supporting VIP-less setups.
>
> 3. PREROUTING
> Intercept incoming connections before DNAT and input filtering
> has been applied, this enables transparent proxying on realnodes
> and localnode.
>
> Signed-off-by: Raphael Vallazza <raphael@endian.com>
> ---
> net/ipv4/ipvs/Kconfig | 44 +++++++++++++++++++++++++++++++++++
> +++++++++
> net/ipv4/ipvs/ip_vs_core.c | 30 +++++++++++++++++++++++++++++-
> 2 files changed, 73 insertions(+), 1 deletions(-)
>
> diff --git a/net/ipv4/ipvs/Kconfig b/net/ipv4/ipvs/Kconfig
> index 09d0c3f..319f3e8 100644
> --- a/net/ipv4/ipvs/Kconfig
> +++ b/net/ipv4/ipvs/Kconfig
> @@ -24,6 +24,50 @@ menuconfig IP_VS
>
> if IP_VS
>
> +choice
> + prompt "IPVS connection interception method"
> + default IP_VS_INPUT_LOCAL_IN
> + help
> + This option sets the position at which IPVS intercepts incoming
> + connections from Netfilter. If in doubt select 'LOCAL_IN'.
> +
> +config IP_VS_INPUT_LOCAL_IN
> + bool "INPUT"
> + ---help---
> + Intercept incoming connections after they have traveled through
> + the INPUT table, only connections that have the director as
> + destination address will be processed.
> +
> + This method allows to apply packet filtering in the INPUT table
> + before the connection is intercepted by IPVS.
> +
> +config IP_VS_INPUT_FORWARD
> + bool "FORWARD"
> + ---help---
> + Intercept incoming connections after they have traveled through
> + the INPUT or the FORWARD table. It has the same functionlity of
> + the "INPUT method", but also processes connections that are
> + routed through the director, supporting VIP-less setups.
> +
> + This method allows to apply packet filtering in the INPUT or
> + FORWARD table, before the connection is intercepted by IPVS.
> +
> +config IP_VS_INPUT_PRE_ROUTING
> + bool "PREROUTING"
> + ---help---
> + Intercept incoming connections before DNAT and input filtering
> + has been applied, this allows transparent proxying on realnodes
> + and localnode. Incoming connections are intercepted right after
> + the mangle PREROUTING table and before the nat PREROUTING table,
> + supporting VIP-less setups.
> +
> + WARNING: This method doesn't apply any packet filtering before
> + packets are intercepted by IPVS. To filter the connections that
> + should be intercepted, you have to mark the traffic in the
> + mangle PREROUTING table.
> +
> +endchoice
> +
> config IP_VS_DEBUG
> bool "IP virtual server debugging"
> ---help---
> diff --git a/net/ipv4/ipvs/ip_vs_core.c b/net/ipv4/ipvs/ip_vs_core.c
> index 963981a..0da4ef6 100644
> --- a/net/ipv4/ipvs/ip_vs_core.c
> +++ b/net/ipv4/ipvs/ip_vs_core.c
> @@ -1026,6 +1026,7 @@ ip_vs_forward_icmp(unsigned int hooknum, struct
> sk_buff *skb,
>
>
> static struct nf_hook_ops ip_vs_ops[] __read_mostly = {
> +#if defined(CONFIG_IP_VS_INPUT_LOCAL_IN) || defined(CONFIG_IP_VS_INPUT_FORWARD)
Shouldn't this just be
#if defined(CONFIG_IP_VS_INPUT_LOCAL_IN)
> /* After packet filtering, forward packet through VS/DR, VS/TUN,
> * or VS/NAT(change destination), so that filtering rules can be
> * applied to IPVS. */
> @@ -1036,6 +1037,33 @@ static struct nf_hook_ops ip_vs_ops[]
> __read_mostly = {
> .hooknum = NF_INET_LOCAL_IN,
> .priority = 100,
> },
> +#endif
> +#ifdef CONFIG_IP_VS_INPUT_FORWARD
> + /* Intercept incoming connections after they have traveled through
> + * the INPUT or the FORWARD table. It has the same functionlity of
> + * the "INPUT method", but also processes connections that are
> + * routed through the director, supporting VIP-less setups. */
> + {
> + .hook = ip_vs_in,
> + .owner = THIS_MODULE,
> + .pf = PF_INET,
> + .hooknum = NF_INET_FORWARD,
> + .priority = 98,
> + },
> +#endif
> +#ifdef CONFIG_IP_VS_INPUT_PRE_ROUTING
> + /* Intercept incoming connections before DNAT and input filtering
> + * has been applied, this enables ransparent proxying on realnodes
> + * and localnode. Hook right after MANGLE and before NAT_DST.
> + */
> + {
> + .hook = ip_vs_in,
> + .owner = THIS_MODULE,
> + .pf = PF_INET,
> + .hooknum = NF_INET_PRE_ROUTING,
> + .priority = NF_IP_PRI_NAT_DST - 1,
> + },
> +#endif
> /* After packet filtering, change source only for VS/NAT */
> {
> .hook = ip_vs_out,
> @@ -1059,7 +1087,7 @@ static struct nf_hook_ops ip_vs_ops[]
> __read_mostly = {
> .owner = THIS_MODULE,
> .pf = PF_INET,
> .hooknum = NF_INET_POST_ROUTING,
> - .priority = NF_IP_PRI_NAT_SRC-1,
> + .priority = NF_IP_PRI_NAT_SRC - 1,
> },
> };
>
> --
> 1.5.3.7
>
>
> #### 0002-IPVS-Runtime-interception-method-switch.patch ####
>
> [IPVS]: Runtime interception method switch
>
> This patch allows to switch interception method at runtime by changing
> the value of /proc/sys/net/ipv4/vs/input_hook with one of the following
> values:
> 0 = INPUT
> 1 = FORWARD
> 2 = PREROUTING
Could you ass documentation of this to
Documentation/networking/ipvs-sysctl.txt ?
>
> Signed-off-by: Raphael Vallazza <raphael@endian.com>
> ---
> include/net/ip_vs.h | 15 +++++
> net/ipv4/ipvs/Kconfig | 10 +++-
> net/ipv4/ipvs/ip_vs_core.c | 141 +++++++++++++++++++++++++++++++++++
> ++-------
> net/ipv4/ipvs/ip_vs_ctl.c | 43 +++++++++++++
> 4 files changed, 186 insertions(+), 23 deletions(-)
>
> diff --git a/include/net/ip_vs.h b/include/net/ip_vs.h
> index 56f3c94..6b71e31 100644
> --- a/include/net/ip_vs.h
> +++ b/include/net/ip_vs.h
> @@ -681,6 +681,21 @@ extern void ip_vs_init_hash_table(struct list_head
> *table, int rows);
> #define IP_VS_APP_TYPE_FTP 1
>
> /*
> + * IPVS input hook functions
> + */
> +enum {
> + IP_VS_INPUT_HOOK_FIRST = -1,
> + IP_VS_INPUT_HOOK_LOCAL_IN,
> + IP_VS_INPUT_HOOK_FORWARD,
> + IP_VS_INPUT_HOOK_PRE_ROUTING,
> + IP_VS_INPUT_HOOK_LAST,
> +};
> +
> +extern int ip_vs_get_input_hook(void);
> +extern int ip_vs_register_hooks(int input_hook);
> +extern int ip_vs_unregister_hooks(int input_hook);
> +
> +/*
> * ip_vs_conn handling functions
> * (from ip_vs_conn.c)
> */
> diff --git a/net/ipv4/ipvs/Kconfig b/net/ipv4/ipvs/Kconfig
> index 319f3e8..19217d7 100644
> --- a/net/ipv4/ipvs/Kconfig
> +++ b/net/ipv4/ipvs/Kconfig
> @@ -28,8 +28,14 @@ choice
> prompt "IPVS connection interception method"
> default IP_VS_INPUT_LOCAL_IN
> help
> - This option sets the position at which IPVS intercepts incoming
> - connections from Netfilter. If in doubt select 'LOCAL_IN'.
> + This option selects the default position at which IPVS intercepts
> + incoming connections from Netfilter. If in doubt select 'INPUT'.
> +
> + The interception method can be switched at runtime in
> + /proc/sys/net/ipv4/vs/input_hook with the following values:
> + 0 = INPUT
> + 1 = FORWARD
> + 2 = PREROUTING
>
> config IP_VS_INPUT_LOCAL_IN
> bool "INPUT"
> diff --git a/net/ipv4/ipvs/ip_vs_core.c b/net/ipv4/ipvs/ip_vs_core.c
> index 0da4ef6..6acfbbd 100644
> --- a/net/ipv4/ipvs/ip_vs_core.c
> +++ b/net/ipv4/ipvs/ip_vs_core.c
> @@ -1024,12 +1024,111 @@ ip_vs_forward_icmp(unsigned int hooknum, struct
> sk_buff *skb,
> return ip_vs_in_icmp(skb, &r, hooknum);
> }
>
> +/*
> + * Register netfilter hook based on input_hook type
> + */
> +
> +int ip_vs_register_hooks(int input_hook)
> +{
> + int ret;
> + char *hookstr;
> + struct nf_hook_ops *in_hooks;
Just me, but in_hook seems like a better name than in_hooks.
> + int count;
> +
> + IP_VS_DBG(5, "Registering input hooks: %i\n", input_hook);
> +
> + switch (input_hook) {
> + case IP_VS_INPUT_HOOK_LOCAL_IN:
> + hookstr = "INPUT";
> + in_hooks = ip_vs_ops_local_in;
> + count = ARRAY_SIZE(ip_vs_ops_local_in);
> + break;
> + case IP_VS_INPUT_HOOK_FORWARD:
> + hookstr = "FORWARD";
> + in_hooks = ip_vs_ops_forward;
> + count = ARRAY_SIZE(ip_vs_ops_forward);
> + break;
> + case IP_VS_INPUT_HOOK_PRE_ROUTING:
> + hookstr = "PREROUTING";
> + in_hooks = ip_vs_ops_pre_routing;
> + count = ARRAY_SIZE(ip_vs_ops_pre_routing);
> + break;
> + default:
> + return -1;
> + }
Could the calculation of count be moved out of the switch to here
as the following?
count = ARRAY_SIZE(in_hooks);
> +
> + ret = nf_register_hooks(in_hooks, count);
> + if (ret < 0) {
> + IP_VS_ERR("Can't register %s hooks.\n", hookstr);
> + return -1;
> + }
> +
> + ret = nf_register_hooks(ip_vs_ops_generic,
> + ARRAY_SIZE(ip_vs_ops_generic));
> + if (ret < 0) {
> + nf_unregister_hooks(in_hooks, count);
> + IP_VS_ERR("Can't register generic hooks.\n");
> + return -1;
> + }
> +
> + IP_VS_INFO("Registered interception method: %s\n", hookstr);
> + return 0;
> +}
> +
> +/*
> + * Unregister netfilter hook based on input_hook type
> + */
>
> -static struct nf_hook_ops ip_vs_ops[] __read_mostly = {
> -#if defined(CONFIG_IP_VS_INPUT_LOCAL_IN) ||
> defined(CONFIG_IP_VS_INPUT_FORWARD)
> - /* After packet filtering, forward packet through VS/DR, VS/TUN,
> - * or VS/NAT(change destination), so that filtering rules can be
> - * applied to IPVS. */
> +int ip_vs_unregister_hooks(int input_hook)
> +{
> + struct nf_hook_ops *in_hooks;
> + int count;
> +
> + IP_VS_DBG(5, "Unregistering input hooks: %i\n", input_hook);
> +
> + switch (input_hook) {
> + case IP_VS_INPUT_HOOK_LOCAL_IN:
> + in_hooks = ip_vs_ops_local_in;
> + count = ARRAY_SIZE(ip_vs_ops_local_in);
> + break;
> + case IP_VS_INPUT_HOOK_FORWARD:
> + in_hooks = ip_vs_ops_forward;
> + count = ARRAY_SIZE(ip_vs_ops_forward);
> + break;
> + case IP_VS_INPUT_HOOK_PRE_ROUTING:
> + in_hooks = ip_vs_ops_pre_routing;
> + count = ARRAY_SIZE(ip_vs_ops_pre_routing);
> + break;
> + default:
> + return -1;
> + }
Again, could the calculation of count be moved out of the switch
statement? Perhaps it could just be put directly in the
call to nf_unregister_hooks() ?
nf_unregister_hooks(in_hooks, ARRAY_SIZE(in_hooks));
> +
> + nf_unregister_hooks(in_hooks, count);
> + nf_unregister_hooks(ip_vs_ops_generic, ARRAY_SIZE(ip_vs_ops_generic));
> +
> + IP_VS_DBG(5, "Unregistered input hooks.\n");
> + return 0;
> +}
I found that I needed to move the definition of ip_ve_register_hooks()
and ip_vs_unregister_hooks() to below the definition of all
the struct nf_hook_ops, as they are used in these functions.
The hunks below seem a bit messed up
and ip_vs_ips_pre_forward ends up with a duplicate
of the NF_INET_LOCAL_IN fragment from ip_vs_ops_local_in.
> +
> +
> +/* After packet filtering, forward packet through VS/DR, VS/TUN,
> + * or VS/NAT(change destination), so that filtering rules can be
> + * applied to IPVS. */
> +static struct nf_hook_ops ip_vs_ops_local_in[] __read_mostly = {
> + {
> + .hook = ip_vs_in,
> + .owner = THIS_MODULE,
> + .pf = PF_INET,
> + .hooknum = NF_INET_LOCAL_IN,
> + .priority = 100,
> + },
> +};
> +
> +/* Intercept incoming connections after they have traveled through
> + * the INPUT or the FORWARD table. It has the same functionlity of
> + * the "INPUT method", but also processes connections that are
> + * routed through the director, supporting VIP-less setups. */
> +static struct nf_hook_ops ip_vs_ops_forward[] __read_mostly = {
> {
> .hook = ip_vs_in,
> .owner = THIS_MODULE,
> @@ -1037,12 +1136,6 @@ static struct nf_hook_ops ip_vs_ops[]
> __read_mostly = {
> .hooknum = NF_INET_LOCAL_IN,
> .priority = 100,
> },
> -#endif
> -#ifdef CONFIG_IP_VS_INPUT_FORWARD
> - /* Intercept incoming connections after they have traveled through
> - * the INPUT or the FORWARD table. It has the same functionlity of
> - * the "INPUT method", but also processes connections that are
> - * routed through the director, supporting VIP-less setups. */
> {
> .hook = ip_vs_in,
> .owner = THIS_MODULE,
> @@ -1050,12 +1143,13 @@ static struct nf_hook_ops ip_vs_ops[]
> __read_mostly = {
> .hooknum = NF_INET_FORWARD,
> .priority = 98,
> },
> -#endif
> -#ifdef CONFIG_IP_VS_INPUT_PRE_ROUTING
> - /* Intercept incoming connections before DNAT and input filtering
> - * has been applied, this enables ransparent proxying on realnodes
> - * and localnode. Hook right after MANGLE and before NAT_DST.
> - */
> +};
> +
> +/* Intercept incoming connections before DNAT and input filtering
> + * has been applied, this enables ransparent proxying on realnodes
> + * and localnode. Hook right after MANGLE and before NAT_DST.
> + */
> +static struct nf_hook_ops ip_vs_ops_pre_routing[] __read_mostly = {
> {
> .hook = ip_vs_in,
> .owner = THIS_MODULE,
> @@ -1063,7 +1157,13 @@ static struct nf_hook_ops ip_vs_ops[]
> __read_mostly = {
> .hooknum = NF_INET_PRE_ROUTING,
> .priority = NF_IP_PRI_NAT_DST - 1,
> },
> -#endif
> +};
> +
> +/*
> + * Generic Netfilter hooks required for all the input methods
> + */
> +
> +static struct nf_hook_ops ip_vs_ops_generic[] __read_mostly = {
> /* After packet filtering, change source only for VS/NAT */
> {
> .hook = ip_vs_out,
> @@ -1119,9 +1219,8 @@ static int __init ip_vs_init(void)
> goto cleanup_app;
> }
>
> - ret = nf_register_hooks(ip_vs_ops, ARRAY_SIZE(ip_vs_ops));
> + ret = ip_vs_register_hooks(ip_vs_get_input_hook());
> if (ret < 0) {
> - IP_VS_ERR("can't register hooks.\n");
> goto cleanup_conn;
> }
>
> @@ -1141,7 +1240,7 @@ static int __init ip_vs_init(void)
>
> static void __exit ip_vs_cleanup(void)
> {
> - nf_unregister_hooks(ip_vs_ops, ARRAY_SIZE(ip_vs_ops));
> + ip_vs_unregister_hooks(ip_vs_get_input_hook());
> ip_vs_conn_cleanup();
> ip_vs_app_cleanup();
> ip_vs_protocol_cleanup();
> diff --git a/net/ipv4/ipvs/ip_vs_ctl.c b/net/ipv4/ipvs/ip_vs_ctl.c
> index 94c5767..1e05c54 100644
> --- a/net/ipv4/ipvs/ip_vs_ctl.c
> +++ b/net/ipv4/ipvs/ip_vs_ctl.c
> @@ -82,6 +82,15 @@ int sysctl_ip_vs_expire_quiescent_template = 0;
> int sysctl_ip_vs_sync_threshold[2] = { 3, 50 };
> int sysctl_ip_vs_nat_icmp_send = 0;
>
> +#ifdef CONFIG_IP_VS_INPUT_LOCAL_IN
> +static int sysctl_ip_vs_input_hook = IP_VS_INPUT_HOOK_LOCAL_IN;
> +#endif
> +#ifdef CONFIG_IP_VS_INPUT_FORWARD
> +static int sysctl_ip_vs_input_hook = IP_VS_INPUT_HOOK_FORWARD;
> +#endif
> +#ifdef CONFIG_IP_VS_INPUT_PRE_ROUTING
> +static int sysctl_ip_vs_input_hook = IP_VS_INPUT_HOOK_PRE_ROUTING;
> +#endif
>
> #ifdef CONFIG_IP_VS_DEBUG
> static int sysctl_ip_vs_debug_level = 0;
> @@ -92,6 +101,11 @@ int ip_vs_get_debug_level(void)
> }
> #endif
>
> +int ip_vs_get_input_hook(void)
> +{
> + return sysctl_ip_vs_input_hook;
> +}
> +
> /*
> * update_defense_level is called from keventd and from sysctl,
> * so it needs to protect itself from softirqs
> @@ -1376,6 +1390,28 @@ static int ip_vs_zero_all(void)
> return 0;
> }
>
> +static int
> +proc_do_input_hook(struct ctl_table *table, int write, struct file
> *filp,
> + void __user *buffer, size_t *lenp, loff_t *ppos)
> +{
> + char *valp = table->data;
> + int oldval = *valp;
> + int rc;
> +
> + rc = proc_dointvec(table, write, filp, buffer, lenp, ppos);
> + if (write && (*valp != oldval)) {
> + if ((*valp <= IP_VS_INPUT_HOOK_FIRST) ||
> + (*valp >= IP_VS_INPUT_HOOK_LAST)) {
> + IP_VS_ERR("Invalid input hook value: %i\n", *valp);
> + *valp = oldval;
> + } else {
> + /* unregister old and register new input hooks */
> + ip_vs_unregister_hooks(oldval);
> + ip_vs_register_hooks(*valp);
> + }
> + }
> + return rc;
> +}
>
> static int
> proc_do_defense_mode(ctl_table *table, int write, struct file * filp,
> @@ -1430,6 +1466,13 @@ static struct ctl_table vs_vars[] = {
> .mode = 0644,
> .proc_handler = &proc_dointvec,
> },
> + {
> + .procname = "input_hook",
> + .data = &sysctl_ip_vs_input_hook,
> + .maxlen = sizeof(int),
> + .mode = 0644,
> + .proc_handler = &proc_do_input_hook,
> + },
> #ifdef CONFIG_IP_VS_DEBUG
> {
> .procname = "debug_level",
> --
> 1.5.3.7
>
>
>
> -
> To unsubscribe from this list: send the line "unsubscribe lvs-devel" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
--
Horms
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH] Runtime interception method switch
2008-01-14 9:42 ` Joseph Mack NA3T
@ 2008-01-15 8:25 ` Simon Horman
2008-01-15 13:13 ` Joseph Mack NA3T
0 siblings, 1 reply; 14+ messages in thread
From: Simon Horman @ 2008-01-15 8:25 UTC (permalink / raw)
To: Joseph Mack NA3T; +Cc: LVS Devel
On Mon, Jan 14, 2008 at 01:42:00AM -0800, Joseph Mack NA3T wrote:
> On Mon, 14 Jan 2008, Raphael Vallazza wrote:
>
>> I think this has nothing to with the input method,
>
> I'd assumed that it would be fixed by hooking the FORWARD chain because
> then the packets wouldn't bypass netfilter.
>
>> it's more a problem of the *xmit* function. Packets for realservers
>> don't seem to flow through the SNAT chain, this way it's not possible
>> to change the source IP.
>
> OK
>
>> This could probably be implemented either by letting the packets flow
>> through the iptables/SNAT (it seems that the patch on
>> http://www.austintek.com/LVS/LVS-HOWTO/HOWTO/LVS-HOWTO.non-modified_realservers.html
>> does this),
>
> can this be put into the standard ipvs?
In principle yes, though I am a bit wary about what
side-effects it might have.
>> or to implement SNAT in the IPVS/NAT method.
>
> can you do either of these?
--
Horms
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH] Runtime interception method switch
2008-01-15 8:25 ` Simon Horman
@ 2008-01-15 13:13 ` Joseph Mack NA3T
2008-01-16 7:50 ` Simon Horman
0 siblings, 1 reply; 14+ messages in thread
From: Joseph Mack NA3T @ 2008-01-15 13:13 UTC (permalink / raw)
To: LVS Devel
On Tue, 15 Jan 2008, Simon Horman wrote:
>> can this be put into the standard ipvs?
("this" == F5-SNAT
http://www.austintek.com/LVS/LVS-HOWTO/HOWTO/LVS-HOWTO.non-modified_realservers.html#F5_snat
)
> In principle yes, though I am a bit wary about what
> side-effects it might have.
>
>>> or to implement SNAT in the IPVS/NAT method.
>>
>> can you do either of these?
I know I'm not the one doing the coding but since
o we're having a bit of a redesign
o people reasonably expect iptables rules to be able to NAT
packets coming out of the director going to the realservers
and it would be nice to restore that functionality for ipvs
o F5-SNAT is useful
this would be a good time to look at adding F5-SNAT.
What side effects might there be? Are they worse than not
being able to NAT packets emerging from a director?
Joe
--
Joseph Mack NA3T EME(B,D), FM05lw North Carolina
jmack (at) wm7d (dot) net - azimuthal equidistant map
generator at http://www.wm7d.net/azproj.shtml
Homepage http://www.austintek.com/ It's GNU/Linux!
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH] Runtime interception method switch
2008-01-15 13:13 ` Joseph Mack NA3T
@ 2008-01-16 7:50 ` Simon Horman
2008-01-16 11:16 ` Janusz Krzysztofik
2008-01-16 15:09 ` Joseph Mack NA3T
0 siblings, 2 replies; 14+ messages in thread
From: Simon Horman @ 2008-01-16 7:50 UTC (permalink / raw)
To: Joseph Mack NA3T; +Cc: LVS Devel, Janusz Krzysztofik
On Tue, Jan 15, 2008 at 05:13:14AM -0800, Joseph Mack NA3T wrote:
> On Tue, 15 Jan 2008, Simon Horman wrote:
>
>>> can this be put into the standard ipvs?
>
> ("this" == F5-SNAT
>
> http://www.austintek.com/LVS/LVS-HOWTO/HOWTO/LVS-HOWTO.non-modified_realservers.html#F5_snat
>
> )
>
>> In principle yes, though I am a bit wary about what
>> side-effects it might have.
>>
>>>> or to implement SNAT in the IPVS/NAT method.
>>>
>>> can you do either of these?
>
> I know I'm not the one doing the coding but since
>
> o we're having a bit of a redesign
>
> o people reasonably expect iptables rules to be able to NAT packets
> coming out of the director going to the realservers and it would be nice
> to restore that functionality for ipvs
>
> o F5-SNAT is useful
>
> this would be a good time to look at adding F5-SNAT.
>
> What side effects might there be? Are they worse than not being able to
> NAT packets emerging from a director?
I'm not sure, and thats what concerns me.
For starters could we clarify that the patch in question is the
following one by Janusz Krzysztofik?
Also can I clarify that the aim is to be able to SNAT LVS-DR
connections (and if possible LVS-NAT and LVS-TUN)?
Or is the aim to add a new method, LVS-FULL-NAT?
--- linux-source-2.6.17-2-e49_9.200610211740/net/ipv4/ipvs/ip_vs_core.c.orig 2006-06-18 03:49:35.000000000 +0200
+++ linux-source-2.6.17-2-e49_9.200610211740/net/ipv4/ipvs/ip_vs_core.c 2006-10-21 21:38:20.000000000 +0200
@@ -672,6 +672,9 @@ static int ip_vs_out_icmp(struct sk_buff
if (!cp)
return NF_ACCEPT;
+ if (IP_VS_FWD_METHOD(cp) == IP_VS_CONN_F_DROUTE)
+ return NF_ACCEPT;
+
verdict = NF_DROP;
if (IP_VS_FWD_METHOD(cp) != 0) {
@@ -801,6 +804,9 @@ ip_vs_out(unsigned int hooknum, struct s
return NF_ACCEPT;
}
+ if (IP_VS_FWD_METHOD(cp) == IP_VS_CONN_F_DROUTE)
+ return NF_ACCEPT;
+
IP_VS_DBG_PKT(11, pp, skb, 0, "Outgoing packet");
if (!ip_vs_make_skb_writable(pskb, ihl))
--- linux-source-2.6.17-2-e49_9.200610211740/net/ipv4/ipvs/ip_vs_xmit.c.orig 2006-06-18 03:49:35.000000000 +0200
+++ linux-source-2.6.17-2-e49_9.200610211740/net/ipv4/ipvs/ip_vs_xmit.c 2006-10-21 21:22:56.000000000 +0200
@@ -127,7 +127,6 @@ ip_vs_dst_reset(struct ip_vs_dest *dest)
#define IP_VS_XMIT(skb, rt) \
do { \
- (skb)->ipvs_property = 1; \
(skb)->ip_summed = CHECKSUM_NONE; \
NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, (skb), NULL, \
(rt)->u.dst.dev, dst_output); \
@@ -278,6 +277,7 @@ ip_vs_nat_xmit(struct sk_buff *skb, stru
/* Another hack: avoid icmp_send in ip_fragment */
skb->local_df = 1;
+ skb->ipvs_property = 1;
IP_VS_XMIT(skb, rt);
LeaveFunction(10);
@@ -411,6 +411,7 @@ ip_vs_tunnel_xmit(struct sk_buff *skb, s
/* Another hack: avoid icmp_send in ip_fragment */
skb->local_df = 1;
+ skb->ipvs_property = 1;
IP_VS_XMIT(skb, rt);
LeaveFunction(10);
@@ -542,6 +543,7 @@ ip_vs_icmp_xmit(struct sk_buff *skb, str
/* Another hack: avoid icmp_send in ip_fragment */
skb->local_df = 1;
+ skb->ipvs_property = 1;
IP_VS_XMIT(skb, rt);
rc = NF_STOLEN;
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH] Runtime interception method switch
2008-01-16 7:50 ` Simon Horman
@ 2008-01-16 11:16 ` Janusz Krzysztofik
2008-01-16 11:28 ` Raphael Vallazza
2008-01-16 15:09 ` Joseph Mack NA3T
1 sibling, 1 reply; 14+ messages in thread
From: Janusz Krzysztofik @ 2008-01-16 11:16 UTC (permalink / raw)
Cc: LVS Devel
Simon Horman wrote:
> On Tue, Jan 15, 2008 at 05:13:14AM -0800, Joseph Mack NA3T wrote:
>> What side effects might there be? Are they worse than not being able to
>> NAT packets emerging from a director?
>
> I'm not sure, and thats what concerns me.
>
> For starters could we clarify that the patch in question is the
> following one by Janusz Krzysztofik?
>
> Also can I clarify that the aim is to be able to SNAT LVS-DR
> connections ...
Hi,
I can confirm what I have already said before: this patch works for me
(now for over two years) without any unexpected side effects. The only
side effect I can see is that all LVS-DR incoming packets go through
conntrack, even if you do not intend to SNAT them. That could present
excessive load on ancient hardware, but one can just unload conntrack
modules, or turn connection tracking off for specific traffic with
PREROUTING raw hook rules.
However, I think this patch should be considered, if at all, as a
temporary solution.
Thanks,
Janusz
PS. I am still busy with a different project, but subscribed to lvs-devel.
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH] Runtime interception method switch
2008-01-16 11:16 ` Janusz Krzysztofik
@ 2008-01-16 11:28 ` Raphael Vallazza
2008-01-18 8:52 ` Simon Horman
0 siblings, 1 reply; 14+ messages in thread
From: Raphael Vallazza @ 2008-01-16 11:28 UTC (permalink / raw)
To: LVS Devel
[-- Attachment #1: Type: text/plain, Size: 172 bytes --]
I've added the documentation for the input_hook switch, and attached
both patches for net-2.6.25 (i hope the mailer doesn't mess up things
this time :).
Bye,
Raphael
[-- Attachment #2: 0001-IPVS-Add-choice-for-connection-interception-method.patch --]
[-- Type: application/octet-stream, Size: 5226 bytes --]
From 31be5b549c946579e322b20d2c388fae0c221bb9 Mon Sep 17 00:00:00 2001
From: Raphael Vallazza <raphael@endian.com>
Date: Sun, 13 Jan 2008 09:29:53 +0100
Subject: [PATCH] [IPVS] Add choice for connection interception method
This patch adds an option to set the position at which IPVS intercepts
incoming connections from Netfilter.
The options are:
1. INPUT (default)
Intercept incoming connections after they have traveled through
the INPUT table, only connections that have the director as
destination address will be processed.
2. FORWARD
Intercept incoming connections after they have traveled through
the INPUT or the FORWARD table. It has the same functionlity of
the "INPUT method", but also processes connections that are
routed through the director, supporting VIP-less setups.
3. PREROUTING
Intercept incoming connections before DNAT and input filtering
has been applied, this enables transparent proxying on realnodes
and localnode.
Signed-off-by: Raphael Vallazza <raphael@endian.com>
---
net/ipv4/ipvs/Kconfig | 44 ++++++++++++++++++++++++++++++++++++++++++++
net/ipv4/ipvs/ip_vs_core.c | 30 +++++++++++++++++++++++++++++-
2 files changed, 73 insertions(+), 1 deletions(-)
diff --git a/net/ipv4/ipvs/Kconfig b/net/ipv4/ipvs/Kconfig
index 09d0c3f..319f3e8 100644
--- a/net/ipv4/ipvs/Kconfig
+++ b/net/ipv4/ipvs/Kconfig
@@ -24,6 +24,50 @@ menuconfig IP_VS
if IP_VS
+choice
+ prompt "IPVS connection interception method"
+ default IP_VS_INPUT_LOCAL_IN
+ help
+ This option sets the position at which IPVS intercepts incoming
+ connections from Netfilter. If in doubt select 'LOCAL_IN'.
+
+config IP_VS_INPUT_LOCAL_IN
+ bool "INPUT"
+ ---help---
+ Intercept incoming connections after they have traveled through
+ the INPUT table, only connections that have the director as
+ destination address will be processed.
+
+ This method allows to apply packet filtering in the INPUT table
+ before the connection is intercepted by IPVS.
+
+config IP_VS_INPUT_FORWARD
+ bool "FORWARD"
+ ---help---
+ Intercept incoming connections after they have traveled through
+ the INPUT or the FORWARD table. It has the same functionlity of
+ the "INPUT method", but also processes connections that are
+ routed through the director, supporting VIP-less setups.
+
+ This method allows to apply packet filtering in the INPUT or
+ FORWARD table, before the connection is intercepted by IPVS.
+
+config IP_VS_INPUT_PRE_ROUTING
+ bool "PREROUTING"
+ ---help---
+ Intercept incoming connections before DNAT and input filtering
+ has been applied, this allows transparent proxying on realnodes
+ and localnode. Incoming connections are intercepted right after
+ the mangle PREROUTING table and before the nat PREROUTING table,
+ supporting VIP-less setups.
+
+ WARNING: This method doesn't apply any packet filtering before
+ packets are intercepted by IPVS. To filter the connections that
+ should be intercepted, you have to mark the traffic in the
+ mangle PREROUTING table.
+
+endchoice
+
config IP_VS_DEBUG
bool "IP virtual server debugging"
---help---
diff --git a/net/ipv4/ipvs/ip_vs_core.c b/net/ipv4/ipvs/ip_vs_core.c
index 963981a..0da4ef6 100644
--- a/net/ipv4/ipvs/ip_vs_core.c
+++ b/net/ipv4/ipvs/ip_vs_core.c
@@ -1026,6 +1026,7 @@ ip_vs_forward_icmp(unsigned int hooknum, struct sk_buff *skb,
static struct nf_hook_ops ip_vs_ops[] __read_mostly = {
+#if defined(CONFIG_IP_VS_INPUT_LOCAL_IN) || defined(CONFIG_IP_VS_INPUT_FORWARD)
/* After packet filtering, forward packet through VS/DR, VS/TUN,
* or VS/NAT(change destination), so that filtering rules can be
* applied to IPVS. */
@@ -1036,6 +1037,33 @@ static struct nf_hook_ops ip_vs_ops[] __read_mostly = {
.hooknum = NF_INET_LOCAL_IN,
.priority = 100,
},
+#endif
+#ifdef CONFIG_IP_VS_INPUT_FORWARD
+ /* Intercept incoming connections after they have traveled through
+ * the INPUT or the FORWARD table. It has the same functionlity of
+ * the "INPUT method", but also processes connections that are
+ * routed through the director, supporting VIP-less setups. */
+ {
+ .hook = ip_vs_in,
+ .owner = THIS_MODULE,
+ .pf = PF_INET,
+ .hooknum = NF_INET_FORWARD,
+ .priority = 98,
+ },
+#endif
+#ifdef CONFIG_IP_VS_INPUT_PRE_ROUTING
+ /* Intercept incoming connections before DNAT and input filtering
+ * has been applied, this enables ransparent proxying on realnodes
+ * and localnode. Hook right after MANGLE and before NAT_DST.
+ */
+ {
+ .hook = ip_vs_in,
+ .owner = THIS_MODULE,
+ .pf = PF_INET,
+ .hooknum = NF_INET_PRE_ROUTING,
+ .priority = NF_IP_PRI_NAT_DST - 1,
+ },
+#endif
/* After packet filtering, change source only for VS/NAT */
{
.hook = ip_vs_out,
@@ -1059,7 +1087,7 @@ static struct nf_hook_ops ip_vs_ops[] __read_mostly = {
.owner = THIS_MODULE,
.pf = PF_INET,
.hooknum = NF_INET_POST_ROUTING,
- .priority = NF_IP_PRI_NAT_SRC-1,
+ .priority = NF_IP_PRI_NAT_SRC - 1,
},
};
--
1.5.3.7
[-- Attachment #3: 0002-IPVS-Runtime-interception-method-switch.patch --]
[-- Type: application/octet-stream, Size: 11981 bytes --]
From 918801f6b9233ed26ffe8cd0a4ea1ebdb4fc588b Mon Sep 17 00:00:00 2001
From: Raphael Vallazza <raphael@endian.com>
Date: Wed, 16 Jan 2008 12:23:59 +0100
Subject: [PATCH] [IPVS]: Runtime interception method switch
This patch allows to switch interception method at runtime by changing
the value of /proc/sys/net/ipv4/vs/input_hook with one of the following
values:
0 - INPUT (default)
1 - FORWARD
2 - PREROUTING
Signed-off-by: Raphael Vallazza <raphael@endian.com>
---
Documentation/networking/ipvs-sysctl.txt | 27 ++++++
include/net/ip_vs.h | 15 +++
net/ipv4/ipvs/Kconfig | 10 ++-
net/ipv4/ipvs/ip_vs_core.c | 141 +++++++++++++++++++++++++-----
net/ipv4/ipvs/ip_vs_ctl.c | 43 +++++++++
5 files changed, 213 insertions(+), 23 deletions(-)
diff --git a/Documentation/networking/ipvs-sysctl.txt b/Documentation/networking/ipvs-sysctl.txt
index 4ccdbca..3f15b8f 100644
--- a/Documentation/networking/ipvs-sysctl.txt
+++ b/Documentation/networking/ipvs-sysctl.txt
@@ -112,6 +112,33 @@ expire_quiescent_template - BOOLEAN
persistence template if it is to be used to schedule a new
connection and the destination server is quiescent.
+input_hook - INTEGER
+ 0 - INPUT (default)
+ 1 - FORWARD
+ 2 - PREROUTING
+
+ This switch sets the interception method used by IPVS for
+ intercepting incoming connections.
+
+ INPUT - Intercept incoming connections after they have traveled
+ through the INPUT table, only connections that have the director as
+ destination address will be processed.
+
+ FORWARD - Intercept incoming connections after they have traveled
+ through the INPUT or the FORWARD table. It has the same functionlity
+ of the "INPUT method", but also processes connections that are
+ routed through the director, supporting VIP-less setups.
+
+ PREROUTING - Intercept incoming connections before DNAT and input
+ filtering has been applied, this allows transparent proxying on
+ realnodes and localnode. Incoming connections are intercepted right
+ after the mangle PREROUTING table and before the nat PREROUTING
+ table, supporting VIP-less setups.
+ WARNING: This method doesn't apply any packet filtering before
+ packets are intercepted by IPVS. To filter the connections that
+ should be intercepted, you have to mark the traffic in the
+ mangle PREROUTING table.
+
nat_icmp_send - BOOLEAN
0 - disabled (default)
not 0 - enabled
diff --git a/include/net/ip_vs.h b/include/net/ip_vs.h
index 56f3c94..6b71e31 100644
--- a/include/net/ip_vs.h
+++ b/include/net/ip_vs.h
@@ -681,6 +681,21 @@ extern void ip_vs_init_hash_table(struct list_head *table, int rows);
#define IP_VS_APP_TYPE_FTP 1
/*
+ * IPVS input hook functions
+ */
+enum {
+ IP_VS_INPUT_HOOK_FIRST = -1,
+ IP_VS_INPUT_HOOK_LOCAL_IN,
+ IP_VS_INPUT_HOOK_FORWARD,
+ IP_VS_INPUT_HOOK_PRE_ROUTING,
+ IP_VS_INPUT_HOOK_LAST,
+};
+
+extern int ip_vs_get_input_hook(void);
+extern int ip_vs_register_hooks(int input_hook);
+extern int ip_vs_unregister_hooks(int input_hook);
+
+/*
* ip_vs_conn handling functions
* (from ip_vs_conn.c)
*/
diff --git a/net/ipv4/ipvs/Kconfig b/net/ipv4/ipvs/Kconfig
index 319f3e8..19217d7 100644
--- a/net/ipv4/ipvs/Kconfig
+++ b/net/ipv4/ipvs/Kconfig
@@ -28,8 +28,14 @@ choice
prompt "IPVS connection interception method"
default IP_VS_INPUT_LOCAL_IN
help
- This option sets the position at which IPVS intercepts incoming
- connections from Netfilter. If in doubt select 'LOCAL_IN'.
+ This option selects the default position at which IPVS intercepts
+ incoming connections from Netfilter. If in doubt select 'INPUT'.
+
+ The interception method can be switched at runtime in
+ /proc/sys/net/ipv4/vs/input_hook with the following values:
+ 0 = INPUT
+ 1 = FORWARD
+ 2 = PREROUTING
config IP_VS_INPUT_LOCAL_IN
bool "INPUT"
diff --git a/net/ipv4/ipvs/ip_vs_core.c b/net/ipv4/ipvs/ip_vs_core.c
index 0da4ef6..6acfbbd 100644
--- a/net/ipv4/ipvs/ip_vs_core.c
+++ b/net/ipv4/ipvs/ip_vs_core.c
@@ -1024,12 +1024,111 @@ ip_vs_forward_icmp(unsigned int hooknum, struct sk_buff *skb,
return ip_vs_in_icmp(skb, &r, hooknum);
}
+/*
+ * Register netfilter hook based on input_hook type
+ */
+
+int ip_vs_register_hooks(int input_hook)
+{
+ int ret;
+ char *hookstr;
+ struct nf_hook_ops *in_hooks;
+ int count;
+
+ IP_VS_DBG(5, "Registering input hooks: %i\n", input_hook);
+
+ switch (input_hook) {
+ case IP_VS_INPUT_HOOK_LOCAL_IN:
+ hookstr = "INPUT";
+ in_hooks = ip_vs_ops_local_in;
+ count = ARRAY_SIZE(ip_vs_ops_local_in);
+ break;
+ case IP_VS_INPUT_HOOK_FORWARD:
+ hookstr = "FORWARD";
+ in_hooks = ip_vs_ops_forward;
+ count = ARRAY_SIZE(ip_vs_ops_forward);
+ break;
+ case IP_VS_INPUT_HOOK_PRE_ROUTING:
+ hookstr = "PREROUTING";
+ in_hooks = ip_vs_ops_pre_routing;
+ count = ARRAY_SIZE(ip_vs_ops_pre_routing);
+ break;
+ default:
+ return -1;
+ }
+
+ ret = nf_register_hooks(in_hooks, count);
+ if (ret < 0) {
+ IP_VS_ERR("Can't register %s hooks.\n", hookstr);
+ return -1;
+ }
+
+ ret = nf_register_hooks(ip_vs_ops_generic,
+ ARRAY_SIZE(ip_vs_ops_generic));
+ if (ret < 0) {
+ nf_unregister_hooks(in_hooks, count);
+ IP_VS_ERR("Can't register generic hooks.\n");
+ return -1;
+ }
+
+ IP_VS_INFO("Registered interception method: %s\n", hookstr);
+ return 0;
+}
+
+/*
+ * Unregister netfilter hook based on input_hook type
+ */
-static struct nf_hook_ops ip_vs_ops[] __read_mostly = {
-#if defined(CONFIG_IP_VS_INPUT_LOCAL_IN) || defined(CONFIG_IP_VS_INPUT_FORWARD)
- /* After packet filtering, forward packet through VS/DR, VS/TUN,
- * or VS/NAT(change destination), so that filtering rules can be
- * applied to IPVS. */
+int ip_vs_unregister_hooks(int input_hook)
+{
+ struct nf_hook_ops *in_hooks;
+ int count;
+
+ IP_VS_DBG(5, "Unregistering input hooks: %i\n", input_hook);
+
+ switch (input_hook) {
+ case IP_VS_INPUT_HOOK_LOCAL_IN:
+ in_hooks = ip_vs_ops_local_in;
+ count = ARRAY_SIZE(ip_vs_ops_local_in);
+ break;
+ case IP_VS_INPUT_HOOK_FORWARD:
+ in_hooks = ip_vs_ops_forward;
+ count = ARRAY_SIZE(ip_vs_ops_forward);
+ break;
+ case IP_VS_INPUT_HOOK_PRE_ROUTING:
+ in_hooks = ip_vs_ops_pre_routing;
+ count = ARRAY_SIZE(ip_vs_ops_pre_routing);
+ break;
+ default:
+ return -1;
+ }
+
+ nf_unregister_hooks(in_hooks, count);
+ nf_unregister_hooks(ip_vs_ops_generic, ARRAY_SIZE(ip_vs_ops_generic));
+
+ IP_VS_DBG(5, "Unregistered input hooks.\n");
+ return 0;
+}
+
+
+/* After packet filtering, forward packet through VS/DR, VS/TUN,
+ * or VS/NAT(change destination), so that filtering rules can be
+ * applied to IPVS. */
+static struct nf_hook_ops ip_vs_ops_local_in[] __read_mostly = {
+ {
+ .hook = ip_vs_in,
+ .owner = THIS_MODULE,
+ .pf = PF_INET,
+ .hooknum = NF_INET_LOCAL_IN,
+ .priority = 100,
+ },
+};
+
+/* Intercept incoming connections after they have traveled through
+ * the INPUT or the FORWARD table. It has the same functionlity of
+ * the "INPUT method", but also processes connections that are
+ * routed through the director, supporting VIP-less setups. */
+static struct nf_hook_ops ip_vs_ops_forward[] __read_mostly = {
{
.hook = ip_vs_in,
.owner = THIS_MODULE,
@@ -1037,12 +1136,6 @@ static struct nf_hook_ops ip_vs_ops[] __read_mostly = {
.hooknum = NF_INET_LOCAL_IN,
.priority = 100,
},
-#endif
-#ifdef CONFIG_IP_VS_INPUT_FORWARD
- /* Intercept incoming connections after they have traveled through
- * the INPUT or the FORWARD table. It has the same functionlity of
- * the "INPUT method", but also processes connections that are
- * routed through the director, supporting VIP-less setups. */
{
.hook = ip_vs_in,
.owner = THIS_MODULE,
@@ -1050,12 +1143,13 @@ static struct nf_hook_ops ip_vs_ops[] __read_mostly = {
.hooknum = NF_INET_FORWARD,
.priority = 98,
},
-#endif
-#ifdef CONFIG_IP_VS_INPUT_PRE_ROUTING
- /* Intercept incoming connections before DNAT and input filtering
- * has been applied, this enables ransparent proxying on realnodes
- * and localnode. Hook right after MANGLE and before NAT_DST.
- */
+};
+
+/* Intercept incoming connections before DNAT and input filtering
+ * has been applied, this enables ransparent proxying on realnodes
+ * and localnode. Hook right after MANGLE and before NAT_DST.
+ */
+static struct nf_hook_ops ip_vs_ops_pre_routing[] __read_mostly = {
{
.hook = ip_vs_in,
.owner = THIS_MODULE,
@@ -1063,7 +1157,13 @@ static struct nf_hook_ops ip_vs_ops[] __read_mostly = {
.hooknum = NF_INET_PRE_ROUTING,
.priority = NF_IP_PRI_NAT_DST - 1,
},
-#endif
+};
+
+/*
+ * Generic Netfilter hooks required for all the input methods
+ */
+
+static struct nf_hook_ops ip_vs_ops_generic[] __read_mostly = {
/* After packet filtering, change source only for VS/NAT */
{
.hook = ip_vs_out,
@@ -1119,9 +1219,8 @@ static int __init ip_vs_init(void)
goto cleanup_app;
}
- ret = nf_register_hooks(ip_vs_ops, ARRAY_SIZE(ip_vs_ops));
+ ret = ip_vs_register_hooks(ip_vs_get_input_hook());
if (ret < 0) {
- IP_VS_ERR("can't register hooks.\n");
goto cleanup_conn;
}
@@ -1141,7 +1240,7 @@ static int __init ip_vs_init(void)
static void __exit ip_vs_cleanup(void)
{
- nf_unregister_hooks(ip_vs_ops, ARRAY_SIZE(ip_vs_ops));
+ ip_vs_unregister_hooks(ip_vs_get_input_hook());
ip_vs_conn_cleanup();
ip_vs_app_cleanup();
ip_vs_protocol_cleanup();
diff --git a/net/ipv4/ipvs/ip_vs_ctl.c b/net/ipv4/ipvs/ip_vs_ctl.c
index 94c5767..1e05c54 100644
--- a/net/ipv4/ipvs/ip_vs_ctl.c
+++ b/net/ipv4/ipvs/ip_vs_ctl.c
@@ -82,6 +82,15 @@ int sysctl_ip_vs_expire_quiescent_template = 0;
int sysctl_ip_vs_sync_threshold[2] = { 3, 50 };
int sysctl_ip_vs_nat_icmp_send = 0;
+#ifdef CONFIG_IP_VS_INPUT_LOCAL_IN
+static int sysctl_ip_vs_input_hook = IP_VS_INPUT_HOOK_LOCAL_IN;
+#endif
+#ifdef CONFIG_IP_VS_INPUT_FORWARD
+static int sysctl_ip_vs_input_hook = IP_VS_INPUT_HOOK_FORWARD;
+#endif
+#ifdef CONFIG_IP_VS_INPUT_PRE_ROUTING
+static int sysctl_ip_vs_input_hook = IP_VS_INPUT_HOOK_PRE_ROUTING;
+#endif
#ifdef CONFIG_IP_VS_DEBUG
static int sysctl_ip_vs_debug_level = 0;
@@ -92,6 +101,11 @@ int ip_vs_get_debug_level(void)
}
#endif
+int ip_vs_get_input_hook(void)
+{
+ return sysctl_ip_vs_input_hook;
+}
+
/*
* update_defense_level is called from keventd and from sysctl,
* so it needs to protect itself from softirqs
@@ -1376,6 +1390,28 @@ static int ip_vs_zero_all(void)
return 0;
}
+static int
+proc_do_input_hook(struct ctl_table *table, int write, struct file *filp,
+ void __user *buffer, size_t *lenp, loff_t *ppos)
+{
+ char *valp = table->data;
+ int oldval = *valp;
+ int rc;
+
+ rc = proc_dointvec(table, write, filp, buffer, lenp, ppos);
+ if (write && (*valp != oldval)) {
+ if ((*valp <= IP_VS_INPUT_HOOK_FIRST) ||
+ (*valp >= IP_VS_INPUT_HOOK_LAST)) {
+ IP_VS_ERR("Invalid input hook value: %i\n", *valp);
+ *valp = oldval;
+ } else {
+ /* unregister old and register new input hooks */
+ ip_vs_unregister_hooks(oldval);
+ ip_vs_register_hooks(*valp);
+ }
+ }
+ return rc;
+}
static int
proc_do_defense_mode(ctl_table *table, int write, struct file * filp,
@@ -1430,6 +1466,13 @@ static struct ctl_table vs_vars[] = {
.mode = 0644,
.proc_handler = &proc_dointvec,
},
+ {
+ .procname = "input_hook",
+ .data = &sysctl_ip_vs_input_hook,
+ .maxlen = sizeof(int),
+ .mode = 0644,
+ .proc_handler = &proc_do_input_hook,
+ },
#ifdef CONFIG_IP_VS_DEBUG
{
.procname = "debug_level",
--
1.5.3.7
[-- Attachment #4: Type: text/plain, Size: 1553 bytes --]
Am 16.01.2008 um 12:16 schrieb Janusz Krzysztofik:
> Simon Horman wrote:
>> On Tue, Jan 15, 2008 at 05:13:14AM -0800, Joseph Mack NA3T wrote:
>>> What side effects might there be? Are they worse than not being
>>> able to NAT packets emerging from a director?
>> I'm not sure, and thats what concerns me.
>> For starters could we clarify that the patch in question is the
>> following one by Janusz Krzysztofik?
>> Also can I clarify that the aim is to be able to SNAT LVS-DR
>> connections ...
>
> Hi,
>
> I can confirm what I have already said before: this patch works for
> me (now for over two years) without any unexpected side effects. The
> only side effect I can see is that all LVS-DR incoming packets go
> through conntrack, even if you do not intend to SNAT them. That
> could present excessive load on ancient hardware, but one can just
> unload conntrack modules, or turn connection tracking off for
> specific traffic with PREROUTING raw hook rules.
> However, I think this patch should be considered, if at all, as a
> temporary solution.
>
> Thanks,
> Janusz
>
> PS. I am still busy with a different project, but subscribed to lvs-
> devel.
> -
> To unsubscribe from this list: send the line "unsubscribe lvs-devel"
> in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
--
:: e n d i a n
:: open source - open minds
:: raphael vallazza
:: phone +39 0471 631763 :: fax +39 0471 631764
:: http://www.endian.com :: raphael (AT) endian.com
^ permalink raw reply related [flat|nested] 14+ messages in thread
* Re: [PATCH] Runtime interception method switch
2008-01-16 7:50 ` Simon Horman
2008-01-16 11:16 ` Janusz Krzysztofik
@ 2008-01-16 15:09 ` Joseph Mack NA3T
2008-01-18 8:58 ` Simon Horman
1 sibling, 1 reply; 14+ messages in thread
From: Joseph Mack NA3T @ 2008-01-16 15:09 UTC (permalink / raw)
To: Simon Horman; +Cc: LVS Devel, Janusz Krzysztofik
On Wed, 16 Jan 2008, Simon Horman wrote:
> For starters could we clarify that the patch in question
> is the following one by Janusz Krzysztofik?
I see Janusz has replied to this.
I had assumed that if Raphael could output the packets to
the right spot (before POSTROUTING on the inbound
direction?) that iptables could handle the NAT'ing and no
extra ipvs code would be neccessary.
What I didn't know was the original reason the packets were
output to a place where iptables couldn't manipulate them.
Was this for speed? to get ipvs to work at all? If for
speed, the director has always been limited by wirespeed,
not by anything in ipvs, so any increase in latency through
ipvs may not be seen.
> Also can I clarify that the aim is to be able to SNAT LVS-DR
> connections
I didn't realise Janusz was SNAT'ing LVS-DR.
> (and if possible LVS-NAT and LVS-TUN)?
> Or is the aim to add a new method, LVS-FULL-NAT?
What the users want is to be able to put unmodified servers
behind a director - they can't even change the default gw.
The only thing they can change is the RIP. So the servers
would have to be realservers behind an LVS-NAT director
which is outputting packets with src_addr=DIP, ie the
realservers see connect requests only from the DIP. I'd
assumed the director would be running a new version of
standard LVS-NAT, with iptables doing the SNAT in
POSTROUTING.
Joe
--
Joseph Mack NA3T EME(B,D), FM05lw North Carolina
jmack (at) wm7d (dot) net - azimuthal equidistant map
generator at http://www.wm7d.net/azproj.shtml
Homepage http://www.austintek.com/ It's GNU/Linux!
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH] Runtime interception method switch
2008-01-16 11:28 ` Raphael Vallazza
@ 2008-01-18 8:52 ` Simon Horman
0 siblings, 0 replies; 14+ messages in thread
From: Simon Horman @ 2008-01-18 8:52 UTC (permalink / raw)
To: Raphael Vallazza; +Cc: LVS Devel
On Wed, Jan 16, 2008 at 12:28:21PM +0100, Raphael Vallazza wrote:
> I've added the documentation for the input_hook switch, and attached
> both patches for net-2.6.25 (i hope the mailer doesn't mess up things
> this time :).
Indeed, this seems a lot better :-)
These patches are looking quite good. I only have two minor issues
at this stage.
1) The last fragment of the first patch seems spurious as its
just a whitespace change. But I'm happy to send it on to DaveM
and netdev as is.
@@ -1059,7 +1087,7 @@ static struct nf_hook_ops ip_vs_ops[] __read_mostly = {
.owner = THIS_MODULE,
.pf = PF_INET,
.hooknum = NF_INET_POST_ROUTING,
- .priority = NF_IP_PRI_NAT_SRC-1,
+ .priority = NF_IP_PRI_NAT_SRC - 1,
},
};
2) I am still getting errors with the second patch which
I can resolve by moving the hook definitions to below
ip_vs_register_hooks() and ip_vs_unregister_hooks()
The gcc version and errors are bellow.
As is a patch to do the re-ordering - that is all it does.
If you are happy with this change I can fold it into your
patch and send it on to DaveM and netdev, or you can send me
a fresh patch if you would prefer. I do belive this error is real,
perhaps your gcc is a different (older?) version and is ignoring
this?
# gcc --version
i686-unknown-linux-gnu-gcc (GCC) 3.4.5
Copyright (C) 2004 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is
NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE.
# make
CHK include/linux/version.h
CHK include/linux/utsrelease.h
CALL scripts/checksyscalls.sh
CHK include/linux/compile.h
CC net/ipv4/ipvs/ip_vs_core.o
net/ipv4/ipvs/ip_vs_core.c: In function `ip_vs_register_hooks':
net/ipv4/ipvs/ip_vs_core.c:1043: error: `ip_vs_ops_local_in' undeclared (first use in this function)
net/ipv4/ipvs/ip_vs_core.c:1043: error: (Each undeclared identifier is reported only once
net/ipv4/ipvs/ip_vs_core.c:1043: error: for each function it appears in.)
net/ipv4/ipvs/ip_vs_core.c:1044: warning: type defaults to `int' in declaration of `type name'
net/ipv4/ipvs/ip_vs_core.c:1044: warning: type defaults to `int' in declaration of `type name'
net/ipv4/ipvs/ip_vs_core.c:1044: error: size of array `type name' is negative
net/ipv4/ipvs/ip_vs_core.c:1048: error: `ip_vs_ops_forward' undeclared (first use in this function)
net/ipv4/ipvs/ip_vs_core.c:1049: warning: type defaults to `int' in declaration of `type name'
net/ipv4/ipvs/ip_vs_core.c:1049: warning: type defaults to `int' in declaration of `type name'
net/ipv4/ipvs/ip_vs_core.c:1049: error: size of array `type name' is negative
net/ipv4/ipvs/ip_vs_core.c:1053: error: `ip_vs_ops_pre_routing' undeclared (first use in this function)
net/ipv4/ipvs/ip_vs_core.c:1054: warning: type defaults to `int' in declaration of `type name'
net/ipv4/ipvs/ip_vs_core.c:1054: warning: type defaults to `int' in declaration of `type name'
net/ipv4/ipvs/ip_vs_core.c:1054: error: size of array `type name' is negative
net/ipv4/ipvs/ip_vs_core.c:1066: error: `ip_vs_ops_generic' undeclared (first use in this function)
net/ipv4/ipvs/ip_vs_core.c:1067: warning: type defaults to `int' in declaration of `type name'
net/ipv4/ipvs/ip_vs_core.c:1067: warning: type defaults to `int' in declaration of `type name'
net/ipv4/ipvs/ip_vs_core.c:1067: error: size of array `type name' is negative
net/ipv4/ipvs/ip_vs_core.c: In function `ip_vs_unregister_hooks':
net/ipv4/ipvs/ip_vs_core.c:1091: error: `ip_vs_ops_local_in' undeclared (first use in this function)
net/ipv4/ipvs/ip_vs_core.c:1092: warning: type defaults to `int' in declaration of `type name'
net/ipv4/ipvs/ip_vs_core.c:1092: warning: type defaults to `int' in declaration of `type name'
net/ipv4/ipvs/ip_vs_core.c:1092: error: size of array `type name' is negative
net/ipv4/ipvs/ip_vs_core.c:1095: error: `ip_vs_ops_forward' undeclared (first use in this function)
net/ipv4/ipvs/ip_vs_core.c:1096: warning: type defaults to `int' in declaration of `type name'
net/ipv4/ipvs/ip_vs_core.c:1096: warning: type defaults to `int' in declaration of `type name'
net/ipv4/ipvs/ip_vs_core.c:1096: error: size of array `type name' is negative
net/ipv4/ipvs/ip_vs_core.c:1099: error: `ip_vs_ops_pre_routing' undeclared (first use in this function)
net/ipv4/ipvs/ip_vs_core.c:1100: warning: type defaults to `int' in declaration of `type name'
net/ipv4/ipvs/ip_vs_core.c:1100: warning: type defaults to `int' in declaration of `type name'
net/ipv4/ipvs/ip_vs_core.c:1100: error: size of array `type name' is negative
net/ipv4/ipvs/ip_vs_core.c:1107: error: `ip_vs_ops_generic' undeclared (first use in this function)
net/ipv4/ipvs/ip_vs_core.c:1107: warning: type defaults to `int' in declaration of `type name'
net/ipv4/ipvs/ip_vs_core.c:1107: warning: type defaults to `int' in declaration of `type name'
net/ipv4/ipvs/ip_vs_core.c:1107: error: size of array `type name' is negative
net/ipv4/ipvs/ip_vs_core.c: At top level:
net/ipv4/ipvs/ip_vs_core.c:1117: warning: 'ip_vs_ops_local_in' defined but not used
net/ipv4/ipvs/ip_vs_core.c:1131: warning: 'ip_vs_ops_forward' defined but not used
net/ipv4/ipvs/ip_vs_core.c:1152: warning: 'ip_vs_ops_pre_routing' defined but not used
net/ipv4/ipvs/ip_vs_core.c:1166: warning: 'ip_vs_ops_generic' defined but not used
make[3]: *** [net/ipv4/ipvs/ip_vs_core.o] エラー 1
make[2]: *** [net/ipv4/ipvs] エラー 2
make[1]: *** [net/ipv4] エラー 2
make: *** [net] エラー 2
Index: net-2.6.25/net/ipv4/ipvs/ip_vs_core.c
===================================================================
--- net-2.6.25.orig/net/ipv4/ipvs/ip_vs_core.c 2008-01-18 17:34:23.000000000 +0900
+++ net-2.6.25/net/ipv4/ipvs/ip_vs_core.c 2008-01-18 17:35:07.000000000 +0900
@@ -1024,6 +1024,87 @@ ip_vs_forward_icmp(unsigned int hooknum,
return ip_vs_in_icmp(skb, &r, hooknum);
}
+
+/* After packet filtering, forward packet through VS/DR, VS/TUN,
+ * or VS/NAT(change destination), so that filtering rules can be
+ * applied to IPVS. */
+static struct nf_hook_ops ip_vs_ops_local_in[] __read_mostly = {
+ {
+ .hook = ip_vs_in,
+ .owner = THIS_MODULE,
+ .pf = PF_INET,
+ .hooknum = NF_INET_LOCAL_IN,
+ .priority = 100,
+ },
+};
+
+/* Intercept incoming connections after they have traveled through
+ * the INPUT or the FORWARD table. It has the same functionlity of
+ * the "INPUT method", but also processes connections that are
+ * routed through the director, supporting VIP-less setups. */
+static struct nf_hook_ops ip_vs_ops_forward[] __read_mostly = {
+ {
+ .hook = ip_vs_in,
+ .owner = THIS_MODULE,
+ .pf = PF_INET,
+ .hooknum = NF_INET_LOCAL_IN,
+ .priority = 100,
+ },
+ {
+ .hook = ip_vs_in,
+ .owner = THIS_MODULE,
+ .pf = PF_INET,
+ .hooknum = NF_INET_FORWARD,
+ .priority = 98,
+ },
+};
+
+/* Intercept incoming connections before DNAT and input filtering
+ * has been applied, this enables ransparent proxying on realnodes
+ * and localnode. Hook right after MANGLE and before NAT_DST.
+ */
+static struct nf_hook_ops ip_vs_ops_pre_routing[] __read_mostly = {
+ {
+ .hook = ip_vs_in,
+ .owner = THIS_MODULE,
+ .pf = PF_INET,
+ .hooknum = NF_INET_PRE_ROUTING,
+ .priority = NF_IP_PRI_NAT_DST - 1,
+ },
+};
+
+/*
+ * Generic Netfilter hooks required for all the input methods
+ */
+
+static struct nf_hook_ops ip_vs_ops_generic[] __read_mostly = {
+ /* After packet filtering, change source only for VS/NAT */
+ {
+ .hook = ip_vs_out,
+ .owner = THIS_MODULE,
+ .pf = PF_INET,
+ .hooknum = NF_INET_FORWARD,
+ .priority = 100,
+ },
+ /* After packet filtering (but before ip_vs_out_icmp), catch icmp
+ * destined for 0.0.0.0/0, which is for incoming IPVS connections */
+ {
+ .hook = ip_vs_forward_icmp,
+ .owner = THIS_MODULE,
+ .pf = PF_INET,
+ .hooknum = NF_INET_FORWARD,
+ .priority = 99,
+ },
+ /* Before the netfilter connection tracking, exit from POST_ROUTING */
+ {
+ .hook = ip_vs_post_routing,
+ .owner = THIS_MODULE,
+ .pf = PF_INET,
+ .hooknum = NF_INET_POST_ROUTING,
+ .priority = NF_IP_PRI_NAT_SRC - 1,
+ },
+};
+
/*
* Register netfilter hook based on input_hook type
*/
@@ -1111,87 +1192,6 @@ int ip_vs_unregister_hooks(int input_hoo
}
-/* After packet filtering, forward packet through VS/DR, VS/TUN,
- * or VS/NAT(change destination), so that filtering rules can be
- * applied to IPVS. */
-static struct nf_hook_ops ip_vs_ops_local_in[] __read_mostly = {
- {
- .hook = ip_vs_in,
- .owner = THIS_MODULE,
- .pf = PF_INET,
- .hooknum = NF_INET_LOCAL_IN,
- .priority = 100,
- },
-};
-
-/* Intercept incoming connections after they have traveled through
- * the INPUT or the FORWARD table. It has the same functionlity of
- * the "INPUT method", but also processes connections that are
- * routed through the director, supporting VIP-less setups. */
-static struct nf_hook_ops ip_vs_ops_forward[] __read_mostly = {
- {
- .hook = ip_vs_in,
- .owner = THIS_MODULE,
- .pf = PF_INET,
- .hooknum = NF_INET_LOCAL_IN,
- .priority = 100,
- },
- {
- .hook = ip_vs_in,
- .owner = THIS_MODULE,
- .pf = PF_INET,
- .hooknum = NF_INET_FORWARD,
- .priority = 98,
- },
-};
-
-/* Intercept incoming connections before DNAT and input filtering
- * has been applied, this enables ransparent proxying on realnodes
- * and localnode. Hook right after MANGLE and before NAT_DST.
- */
-static struct nf_hook_ops ip_vs_ops_pre_routing[] __read_mostly = {
- {
- .hook = ip_vs_in,
- .owner = THIS_MODULE,
- .pf = PF_INET,
- .hooknum = NF_INET_PRE_ROUTING,
- .priority = NF_IP_PRI_NAT_DST - 1,
- },
-};
-
-/*
- * Generic Netfilter hooks required for all the input methods
- */
-
-static struct nf_hook_ops ip_vs_ops_generic[] __read_mostly = {
- /* After packet filtering, change source only for VS/NAT */
- {
- .hook = ip_vs_out,
- .owner = THIS_MODULE,
- .pf = PF_INET,
- .hooknum = NF_INET_FORWARD,
- .priority = 100,
- },
- /* After packet filtering (but before ip_vs_out_icmp), catch icmp
- * destined for 0.0.0.0/0, which is for incoming IPVS connections */
- {
- .hook = ip_vs_forward_icmp,
- .owner = THIS_MODULE,
- .pf = PF_INET,
- .hooknum = NF_INET_FORWARD,
- .priority = 99,
- },
- /* Before the netfilter connection tracking, exit from POST_ROUTING */
- {
- .hook = ip_vs_post_routing,
- .owner = THIS_MODULE,
- .pf = PF_INET,
- .hooknum = NF_INET_POST_ROUTING,
- .priority = NF_IP_PRI_NAT_SRC - 1,
- },
-};
-
-
/*
* Initialize IP Virtual Server
*/
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH] Runtime interception method switch
2008-01-16 15:09 ` Joseph Mack NA3T
@ 2008-01-18 8:58 ` Simon Horman
2008-01-18 13:12 ` Joseph Mack NA3T
0 siblings, 1 reply; 14+ messages in thread
From: Simon Horman @ 2008-01-18 8:58 UTC (permalink / raw)
To: Joseph Mack NA3T; +Cc: LVS Devel, Janusz Krzysztofik
On Wed, Jan 16, 2008 at 07:09:26AM -0800, Joseph Mack NA3T wrote:
> On Wed, 16 Jan 2008, Simon Horman wrote:
>
>> For starters could we clarify that the patch in question is the
>> following one by Janusz Krzysztofik?
>
> I see Janusz has replied to this.
Yes I see. I'll take a look over the code a bit more.
But if he says its working then that is certainly a plus.
For the record, I am in favour of this change.
> I had assumed that if Raphael could output the packets to the right spot
> (before POSTROUTING on the inbound direction?) that iptables could handle
> the NAT'ing and no extra ipvs code would be neccessary.
>
> What I didn't know was the original reason the packets were output to a
> place where iptables couldn't manipulate them. Was this for speed? to get
> ipvs to work at all? If for speed, the director has always been limited
> by wirespeed, not by anything in ipvs, so any increase in latency through
> ipvs may not be seen.
I don't know the answer to that. But I guess speed. And you are right,
speed has never been much of a problem. Flexibilty on the other hand
and in particular interaction with contrack has always been problematic.
>> Also can I clarify that the aim is to be able to SNAT LVS-DR
>> connections
>
> I didn't realise Janusz was SNAT'ing LVS-DR.
>
>> (and if possible LVS-NAT and LVS-TUN)?
>> Or is the aim to add a new method, LVS-FULL-NAT?
>
> What the users want is to be able to put unmodified servers behind a
> director - they can't even change the default gw. The only thing they can
> change is the RIP. So the servers would have to be realservers behind an
> LVS-NAT director which is outputting packets with src_addr=DIP, ie the
> realservers see connect requests only from the DIP. I'd assumed the
> director would be running a new version of standard LVS-NAT, with
> iptables doing the SNAT in POSTROUTING.
Sorry to be picky. It seems to me that Janusz does achive the goal in
mind, in a fairly simple way. I will review ASAP.
--
Horms
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH] Runtime interception method switch
2008-01-18 8:58 ` Simon Horman
@ 2008-01-18 13:12 ` Joseph Mack NA3T
0 siblings, 0 replies; 14+ messages in thread
From: Joseph Mack NA3T @ 2008-01-18 13:12 UTC (permalink / raw)
To: Simon Horman; +Cc: LVS Devel, Janusz Krzysztofik
On Fri, 18 Jan 2008, Simon Horman wrote:
>> What the users want is to be able to put unmodified servers behind a
>> director - they can't even change the default gw. The only thing they can
>> change is the RIP. So the servers would have to be realservers behind an
>> LVS-NAT director which is outputting packets with src_addr=DIP, ie the
>> realservers see connect requests only from the DIP. I'd assumed the
>> director would be running a new version of standard LVS-NAT, with
>> iptables doing the SNAT in POSTROUTING.
>
> Sorry to be picky. It seems to me that Janusz does achive the goal in
> mind, in a fairly simple way. I will review ASAP.
not picky at all. I'm happy for anything that achieves the
functionality.
Joe
--
Joseph Mack NA3T EME(B,D), FM05lw North Carolina
jmack (at) wm7d (dot) net - azimuthal equidistant map
generator at http://www.wm7d.net/azproj.shtml
Homepage http://www.austintek.com/ It's GNU/Linux!
^ permalink raw reply [flat|nested] 14+ messages in thread
end of thread, other threads:[~2008-01-18 13:12 UTC | newest]
Thread overview: 14+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-01-13 15:12 [PATCH] Runtime interception method switch Raphael Vallazza
2008-01-13 17:59 ` Joseph Mack NA3T
2008-01-14 8:39 ` Raphael Vallazza
2008-01-14 9:42 ` Joseph Mack NA3T
2008-01-15 8:25 ` Simon Horman
2008-01-15 13:13 ` Joseph Mack NA3T
2008-01-16 7:50 ` Simon Horman
2008-01-16 11:16 ` Janusz Krzysztofik
2008-01-16 11:28 ` Raphael Vallazza
2008-01-18 8:52 ` Simon Horman
2008-01-16 15:09 ` Joseph Mack NA3T
2008-01-18 8:58 ` Simon Horman
2008-01-18 13:12 ` Joseph Mack NA3T
2008-01-15 8:20 ` Simon Horman
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.