* [PATCH RFC v2 0/13] vti4: prepare namespace and interfamily support.
@ 2013-12-16 9:18 Steffen Klassert
2013-12-16 9:19 ` [PATCH RFC v2 01/13] xfrm4: Add IPsec protocol multiplexer Steffen Klassert
` (13 more replies)
0 siblings, 14 replies; 19+ messages in thread
From: Steffen Klassert @ 2013-12-16 9:18 UTC (permalink / raw)
To: netdev; +Cc: Christophe Gouault, Saurabh Mohan
This patchset prepares vti4 for proper namespace and interfamily support.
Currently the receive hook is in the middle of the decapsulation
process, some of the header pointers point still into the IPsec packet
others point already into the decapsulated packet. This makes it
very unflexible and proper namespace and interfamily support can't
be done as it is.
The patchset that implements an IPsec protocol multiplexer, so that vti
can register it's own receive path hooks. Further it makes the i_key
usable for vti and changes the vti4 code to do the following:
vti uses the IPsec protocol multiplexer to register it's
own receive side hooks for ESP, AH and IPCOMP.
Vti does the following on receive side:
1. Do an input policy check for the IPsec packet we received.
This is required because this packet could be already
processed by IPsec (tunnel in tunnel or a block policy
is present), so an inbound policy check is needed.
2. Clean the skb to not leak informations on namespace
transitions.
3. Mark the packet with the i_key. The policy and the state
must match this key now. Policy and state belong to the vti
namespace and policy enforcement is done at the further layers.
4. Call the generic xfrm layer to do decryption and decapsulation.
5. Wait for a callback from the xfrm layer to properly update
the device statistics.
On transmit side:
1. Mark the packet with the o_key. The policy and the state
must match this key now.
2. Do a xfrm_lookup on the original packet with the mark applied.
3. Check if we got an IPsec route.
4. Clean the skb to not leak informations on namespace
transitions.
5. Attach the dst_enty we got from the xfrm_lookup to the skb.
6. Call dst_output to do the IPsec processing.
7. Do the device statistics.
Changes from v1:
- Rebased to current net-next.
- Fix a rcu lockdep complaint in xfrm protocol registration/deregistration.
- Fix usage of a ipv4 specific callback handler in generic code.
- Use skb_scrub_packet() to clear the skb in vti_rcv(), suggested by
Nicolas Dichtel.
- Add support for IPCOMP.
- Support inter address family tunneling.
I'd take this into the ipsec-next tree after some testing if noone
has further suggestions or objections.
I have the ipv6 side ready too, this will be a separate patchset.
The ipv6 patchset has dependencies against the ipv4 patchset, so I
hold it back until we have got the ipv4 side merged.
^ permalink raw reply [flat|nested] 19+ messages in thread
* [PATCH RFC v2 01/13] xfrm4: Add IPsec protocol multiplexer
2013-12-16 9:18 [PATCH RFC v2 0/13] vti4: prepare namespace and interfamily support Steffen Klassert
@ 2013-12-16 9:19 ` Steffen Klassert
2013-12-16 9:19 ` [PATCH RFC v2 02/13] esp4: Use the IPsec protocol multiplexer API Steffen Klassert
` (12 subsequent siblings)
13 siblings, 0 replies; 19+ messages in thread
From: Steffen Klassert @ 2013-12-16 9:19 UTC (permalink / raw)
To: netdev; +Cc: Christophe Gouault, Saurabh Mohan
This patch add an IPsec protocol multiplexer. With this
it is possible to add alternative protocol handlers as
needed for IPsec virtual tunnel interfaces.
Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
---
include/net/xfrm.h | 23 +++++
net/ipv4/Makefile | 2 +-
net/ipv4/xfrm4_protocol.c | 242 +++++++++++++++++++++++++++++++++++++++++++++
net/xfrm/xfrm_input.c | 18 ++--
4 files changed, 278 insertions(+), 7 deletions(-)
create mode 100644 net/ipv4/xfrm4_protocol.c
diff --git a/include/net/xfrm.h b/include/net/xfrm.h
index 6b82fdf..2c39cd4 100644
--- a/include/net/xfrm.h
+++ b/include/net/xfrm.h
@@ -1348,6 +1348,17 @@ struct xfrm_algo_desc {
struct sadb_alg desc;
};
+
+/* XFRM protocol handlers. */
+struct xfrm4_protocol {
+ int (*handler)(struct sk_buff *skb);
+ int (*cb_handler)(struct sk_buff *skb, int err);
+ int (*err_handler)(struct sk_buff *skb, u32 info);
+
+ struct xfrm4_protocol __rcu *next;
+ int priority;
+};
+
/* XFRM tunnel handlers. */
struct xfrm_tunnel {
int (*handler)(struct sk_buff *skb);
@@ -1503,6 +1514,9 @@ int xfrm4_extract_output(struct xfrm_state *x, struct sk_buff *skb);
int xfrm4_prepare_output(struct xfrm_state *x, struct sk_buff *skb);
int xfrm4_output(struct sk_buff *skb);
int xfrm4_output_finish(struct sk_buff *skb);
+void xfrm4_rcv_cb(struct sk_buff *skb, u8 protocol, int err);
+int xfrm4_protocol_register(struct xfrm4_protocol *handler, unsigned char protocol);
+int xfrm4_protocol_deregister(struct xfrm4_protocol *handler, unsigned char protocol);
int xfrm4_tunnel_register(struct xfrm_tunnel *handler, unsigned short family);
int xfrm4_tunnel_deregister(struct xfrm_tunnel *handler, unsigned short family);
void xfrm4_local_error(struct sk_buff *skb, u32 mtu);
@@ -1735,4 +1749,13 @@ static inline int xfrm_mark_put(struct sk_buff *skb, const struct xfrm_mark *m)
return ret;
}
+static inline void xfrm_rcv_cb(struct sk_buff *skb, unsigned int family,
+ u8 protocol, int err)
+{
+ switch(family) {
+ case AF_INET:
+ xfrm4_rcv_cb(skb, protocol, err);
+ }
+}
+
#endif /* _NET_XFRM_H */
diff --git a/net/ipv4/Makefile b/net/ipv4/Makefile
index 4b81e91..4a73d5c 100644
--- a/net/ipv4/Makefile
+++ b/net/ipv4/Makefile
@@ -55,4 +55,4 @@ obj-$(CONFIG_MEMCG_KMEM) += tcp_memcontrol.o
obj-$(CONFIG_NETLABEL) += cipso_ipv4.o
obj-$(CONFIG_XFRM) += xfrm4_policy.o xfrm4_state.o xfrm4_input.o \
- xfrm4_output.o
+ xfrm4_output.o xfrm4_protocol.o
diff --git a/net/ipv4/xfrm4_protocol.c b/net/ipv4/xfrm4_protocol.c
new file mode 100644
index 0000000..02ec971
--- /dev/null
+++ b/net/ipv4/xfrm4_protocol.c
@@ -0,0 +1,242 @@
+/* xfrm4_protocol.c - Generic xfrm protocol multiplexer.
+ *
+ * Copyright (C) 2013 secunet Security Networks AG
+ *
+ * Author:
+ * Steffen Klassert <steffen.klassert@secunet.com>
+ *
+ * Based on:
+ * net/ipv4/tunnel4.c
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#include <linux/init.h>
+#include <linux/mutex.h>
+#include <linux/skbuff.h>
+#include <net/icmp.h>
+#include <net/ip.h>
+#include <net/protocol.h>
+#include <net/xfrm.h>
+
+static struct xfrm4_protocol __rcu *esp4_handlers __read_mostly;
+static struct xfrm4_protocol __rcu *ah4_handlers __read_mostly;
+static struct xfrm4_protocol __rcu *ipcomp4_handlers __read_mostly;
+static DEFINE_MUTEX(xfrm4_protocol_mutex);
+
+static inline struct xfrm4_protocol __rcu **proto_handlers(u8 protocol)
+{
+ switch (protocol) {
+ case IPPROTO_ESP:
+ return &esp4_handlers;
+ case IPPROTO_AH:
+ return &ah4_handlers;
+ case IPPROTO_COMP:
+ return &ipcomp4_handlers;
+ }
+
+ return NULL;
+}
+
+#define for_each_protocol_rcu(head, handler) \
+ for (handler = rcu_dereference(head); \
+ handler != NULL; \
+ handler = rcu_dereference(handler->next)) \
+
+void xfrm4_rcv_cb(struct sk_buff *skb, u8 protocol, int err)
+{
+ struct xfrm4_protocol *handler;
+
+ for_each_protocol_rcu(*proto_handlers(protocol), handler)
+ if (!handler->cb_handler(skb, err))
+ return;
+}
+EXPORT_SYMBOL(xfrm4_rcv_cb);
+
+static int xfrm4_esp_rcv(struct sk_buff *skb)
+{
+ struct xfrm4_protocol *handler;
+
+ for_each_protocol_rcu(esp4_handlers, handler)
+ if (!handler->handler(skb))
+ return 0;
+
+ icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0);
+
+ kfree_skb(skb);
+ return 0;
+}
+
+static void xfrm4_esp_err(struct sk_buff *skb, u32 info)
+{
+ struct xfrm4_protocol *handler;
+
+ for_each_protocol_rcu(esp4_handlers, handler)
+ if (!handler->err_handler(skb, info))
+ break;
+}
+
+static int xfrm4_ah_rcv(struct sk_buff *skb)
+{
+ struct xfrm4_protocol *handler;
+
+ for_each_protocol_rcu(esp4_handlers, handler)
+ if (!handler->handler(skb))
+ return 0;
+
+ icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0);
+
+ kfree_skb(skb);
+ return 0;
+}
+
+static void xfrm4_ah_err(struct sk_buff *skb, u32 info)
+{
+ struct xfrm4_protocol *handler;
+
+ for_each_protocol_rcu(ah4_handlers, handler)
+ if (!handler->err_handler(skb, info))
+ break;
+}
+
+static int xfrm4_ipcomp_rcv(struct sk_buff *skb)
+{
+ struct xfrm4_protocol *handler;
+
+ for_each_protocol_rcu(ipcomp4_handlers, handler)
+ if (!handler->handler(skb))
+ return 0;
+
+ icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0);
+
+ kfree_skb(skb);
+ return 0;
+}
+
+static void xfrm4_ipcomp_err(struct sk_buff *skb, u32 info)
+{
+ struct xfrm4_protocol *handler;
+
+ for_each_protocol_rcu(ipcomp4_handlers, handler)
+ if (!handler->err_handler(skb, info))
+ break;
+}
+
+static const struct net_protocol esp4_protocol = {
+ .handler = xfrm4_esp_rcv,
+ .err_handler = xfrm4_esp_err,
+ .no_policy = 1,
+ .netns_ok = 1,
+};
+
+static const struct net_protocol ah4_protocol = {
+ .handler = xfrm4_ah_rcv,
+ .err_handler = xfrm4_ah_err,
+ .no_policy = 1,
+ .netns_ok = 1,
+};
+
+static const struct net_protocol ipcomp4_protocol = {
+ .handler = xfrm4_ipcomp_rcv,
+ .err_handler = xfrm4_ipcomp_err,
+ .no_policy = 1,
+ .netns_ok = 1,
+};
+
+static inline const struct net_protocol *netproto(unsigned char protocol)
+{
+ switch (protocol) {
+ case IPPROTO_ESP:
+ return &esp4_protocol;
+ case IPPROTO_AH:
+ return &ah4_protocol;
+ case IPPROTO_COMP:
+ return &ipcomp4_protocol;
+ }
+
+ return NULL;
+}
+
+int xfrm4_protocol_register(struct xfrm4_protocol *handler,
+ unsigned char protocol)
+{
+ struct xfrm4_protocol __rcu **pprev;
+ struct xfrm4_protocol *t;
+ bool add_netproto = false;
+
+ int ret = -EEXIST;
+ int priority = handler->priority;
+
+ mutex_lock(&xfrm4_protocol_mutex);
+
+ if (!rcu_dereference_protected(*proto_handlers(protocol),
+ lockdep_is_held(&xfrm4_protocol_mutex)))
+ add_netproto = true;
+
+ for (pprev = proto_handlers(protocol);
+ (t = rcu_dereference_protected(*pprev,
+ lockdep_is_held(&xfrm4_protocol_mutex))) != NULL;
+ pprev = &t->next) {
+ if (t->priority < priority)
+ break;
+ if (t->priority == priority)
+ goto err;
+ }
+
+ handler->next = *pprev;
+ rcu_assign_pointer(*pprev, handler);
+
+ ret = 0;
+
+err:
+ mutex_unlock(&xfrm4_protocol_mutex);
+
+ if (add_netproto) {
+ if (inet_add_protocol(netproto(protocol), protocol)) {
+ pr_err("%s: can't add protocol\n", __func__);
+ ret = -EAGAIN;
+ }
+ }
+
+ return ret;
+}
+EXPORT_SYMBOL(xfrm4_protocol_register);
+
+int xfrm4_protocol_deregister(struct xfrm4_protocol *handler,
+ unsigned char protocol)
+{
+ struct xfrm4_protocol __rcu **pprev;
+ struct xfrm4_protocol *t;
+ int ret = -ENOENT;
+
+ mutex_lock(&xfrm4_protocol_mutex);
+
+ for (pprev = proto_handlers(protocol);
+ (t = rcu_dereference_protected(*pprev,
+ lockdep_is_held(&xfrm4_protocol_mutex))) != NULL;
+ pprev = &t->next) {
+ if (t == handler) {
+ *pprev = handler->next;
+ ret = 0;
+ break;
+ }
+ }
+
+ if (!rcu_dereference_protected(*proto_handlers(protocol),
+ lockdep_is_held(&xfrm4_protocol_mutex))) {
+ if (inet_del_protocol(netproto(protocol), protocol) < 0) {
+ pr_err("%s: can't remove protocol\n", __func__);
+ ret = -EAGAIN;
+ }
+ }
+
+ mutex_unlock(&xfrm4_protocol_mutex);
+
+ synchronize_net();
+
+ return ret;
+}
+EXPORT_SYMBOL(xfrm4_protocol_deregister);
diff --git a/net/xfrm/xfrm_input.c b/net/xfrm/xfrm_input.c
index 8884399..d680a3c 100644
--- a/net/xfrm/xfrm_input.c
+++ b/net/xfrm/xfrm_input.c
@@ -108,7 +108,7 @@ int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type)
int err;
__be32 seq;
__be32 seq_hi;
- struct xfrm_state *x;
+ struct xfrm_state *x = NULL;
xfrm_address_t *daddr;
struct xfrm_mode *inner_mode;
unsigned int family;
@@ -120,9 +120,14 @@ int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type)
async = 1;
x = xfrm_input_state(skb);
seq = XFRM_SKB_CB(skb)->seq.input.low;
+ family = x->outer_mode->afinfo->family;
goto resume;
}
+ daddr = (xfrm_address_t *)(skb_network_header(skb) +
+ XFRM_SPI_SKB_CB(skb)->daddroff);
+ family = XFRM_SPI_SKB_CB(skb)->family;
+
/* Allocate new secpath or COW existing one. */
if (!skb->sp || atomic_read(&skb->sp->refcnt) != 1) {
struct sec_path *sp;
@@ -137,10 +142,6 @@ int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type)
skb->sp = sp;
}
- daddr = (xfrm_address_t *)(skb_network_header(skb) +
- XFRM_SPI_SKB_CB(skb)->daddroff);
- family = XFRM_SPI_SKB_CB(skb)->family;
-
seq = 0;
if (!spi && (err = xfrm_parse_spi(skb, nexthdr, &spi, &seq)) != 0) {
XFRM_INC_STATS(net, LINUX_MIB_XFRMINHDRERROR);
@@ -199,8 +200,10 @@ int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type)
nexthdr = x->type->input(x, skb);
- if (nexthdr == -EINPROGRESS)
+ if (nexthdr == -EINPROGRESS) {
+ xfrm_rcv_cb(skb, family, x->type->proto, nexthdr);
return 0;
+ }
resume:
spin_lock(&x->lock);
@@ -263,6 +266,8 @@ resume:
}
} while (!err);
+ xfrm_rcv_cb(skb, family, x->type->proto, 0);
+
nf_reset(skb);
if (decaps) {
@@ -276,6 +281,7 @@ resume:
drop_unlock:
spin_unlock(&x->lock);
drop:
+ xfrm_rcv_cb(skb, family, x ? x->type->proto : nexthdr, -1);
kfree_skb(skb);
return 0;
}
--
1.7.9.5
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH RFC v2 02/13] esp4: Use the IPsec protocol multiplexer API
2013-12-16 9:18 [PATCH RFC v2 0/13] vti4: prepare namespace and interfamily support Steffen Klassert
2013-12-16 9:19 ` [PATCH RFC v2 01/13] xfrm4: Add IPsec protocol multiplexer Steffen Klassert
@ 2013-12-16 9:19 ` Steffen Klassert
2013-12-16 9:20 ` [PATCH RFC v2 03/13] esp4: Export esp4_err Steffen Klassert
` (11 subsequent siblings)
13 siblings, 0 replies; 19+ messages in thread
From: Steffen Klassert @ 2013-12-16 9:19 UTC (permalink / raw)
To: netdev; +Cc: Christophe Gouault, Saurabh Mohan
Switch esp4 to use the new IPsec protocol multiplexer.
Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
---
net/ipv4/esp4.c | 25 ++++++++++++++++---------
1 file changed, 16 insertions(+), 9 deletions(-)
diff --git a/net/ipv4/esp4.c b/net/ipv4/esp4.c
index 7785b28..d1a4ccd 100644
--- a/net/ipv4/esp4.c
+++ b/net/ipv4/esp4.c
@@ -473,7 +473,7 @@ static u32 esp4_get_mtu(struct xfrm_state *x, int mtu)
net_adj) & ~(blksize - 1)) + net_adj - 2;
}
-static void esp4_err(struct sk_buff *skb, u32 info)
+static int esp4_err(struct sk_buff *skb, u32 info)
{
struct net *net = dev_net(skb->dev);
const struct iphdr *iph = (const struct iphdr *)skb->data;
@@ -483,23 +483,25 @@ static void esp4_err(struct sk_buff *skb, u32 info)
switch (icmp_hdr(skb)->type) {
case ICMP_DEST_UNREACH:
if (icmp_hdr(skb)->code != ICMP_FRAG_NEEDED)
- return;
+ return 0;
case ICMP_REDIRECT:
break;
default:
- return;
+ return 0;
}
x = xfrm_state_lookup(net, skb->mark, (const xfrm_address_t *)&iph->daddr,
esph->spi, IPPROTO_ESP, AF_INET);
if (!x)
- return;
+ return 0;
if (icmp_hdr(skb)->type == ICMP_DEST_UNREACH)
ipv4_update_pmtu(skb, net, info, 0, 0, IPPROTO_ESP, 0);
else
ipv4_redirect(skb, net, 0, 0, IPPROTO_ESP, 0);
xfrm_state_put(x);
+
+ return 0;
}
static void esp_destroy(struct xfrm_state *x)
@@ -672,6 +674,11 @@ error:
return err;
}
+static int esp4_rcv_cb(struct sk_buff *skb, int err)
+{
+ return 0;
+}
+
static const struct xfrm_type esp_type =
{
.description = "ESP4",
@@ -685,11 +692,11 @@ static const struct xfrm_type esp_type =
.output = esp_output
};
-static const struct net_protocol esp4_protocol = {
+static struct xfrm4_protocol esp4_protocol = {
.handler = xfrm4_rcv,
+ .cb_handler = esp4_rcv_cb,
.err_handler = esp4_err,
- .no_policy = 1,
- .netns_ok = 1,
+ .priority = 0,
};
static int __init esp4_init(void)
@@ -698,7 +705,7 @@ static int __init esp4_init(void)
pr_info("%s: can't add xfrm type\n", __func__);
return -EAGAIN;
}
- if (inet_add_protocol(&esp4_protocol, IPPROTO_ESP) < 0) {
+ if (xfrm4_protocol_register(&esp4_protocol, IPPROTO_ESP) < 0) {
pr_info("%s: can't add protocol\n", __func__);
xfrm_unregister_type(&esp_type, AF_INET);
return -EAGAIN;
@@ -708,7 +715,7 @@ static int __init esp4_init(void)
static void __exit esp4_fini(void)
{
- if (inet_del_protocol(&esp4_protocol, IPPROTO_ESP) < 0)
+ if (xfrm4_protocol_deregister(&esp4_protocol, IPPROTO_ESP) < 0)
pr_info("%s: can't remove protocol\n", __func__);
if (xfrm_unregister_type(&esp_type, AF_INET) < 0)
pr_info("%s: can't remove xfrm type\n", __func__);
--
1.7.9.5
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH RFC v2 03/13] esp4: Export esp4_err
2013-12-16 9:18 [PATCH RFC v2 0/13] vti4: prepare namespace and interfamily support Steffen Klassert
2013-12-16 9:19 ` [PATCH RFC v2 01/13] xfrm4: Add IPsec protocol multiplexer Steffen Klassert
2013-12-16 9:19 ` [PATCH RFC v2 02/13] esp4: Use the IPsec protocol multiplexer API Steffen Klassert
@ 2013-12-16 9:20 ` Steffen Klassert
2013-12-16 9:21 ` [PATCH RFC v2 04/13] ah4: Use the IPsec protocol multiplexer API Steffen Klassert
` (10 subsequent siblings)
13 siblings, 0 replies; 19+ messages in thread
From: Steffen Klassert @ 2013-12-16 9:20 UTC (permalink / raw)
To: netdev; +Cc: Christophe Gouault, Saurabh Mohan
esp4_err can be shared with the upcomming vti esp handler.
Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
---
include/net/esp.h | 2 ++
net/ipv4/esp4.c | 3 ++-
2 files changed, 4 insertions(+), 1 deletion(-)
diff --git a/include/net/esp.h b/include/net/esp.h
index a43be85..e239597 100644
--- a/include/net/esp.h
+++ b/include/net/esp.h
@@ -5,6 +5,8 @@
struct ip_esp_hdr;
+int esp4_err(struct sk_buff *skb, u32 info);
+
static inline struct ip_esp_hdr *ip_esp_hdr(const struct sk_buff *skb)
{
return (struct ip_esp_hdr *)skb_transport_header(skb);
diff --git a/net/ipv4/esp4.c b/net/ipv4/esp4.c
index d1a4ccd..1e72fe0 100644
--- a/net/ipv4/esp4.c
+++ b/net/ipv4/esp4.c
@@ -473,7 +473,7 @@ static u32 esp4_get_mtu(struct xfrm_state *x, int mtu)
net_adj) & ~(blksize - 1)) + net_adj - 2;
}
-static int esp4_err(struct sk_buff *skb, u32 info)
+int esp4_err(struct sk_buff *skb, u32 info)
{
struct net *net = dev_net(skb->dev);
const struct iphdr *iph = (const struct iphdr *)skb->data;
@@ -503,6 +503,7 @@ static int esp4_err(struct sk_buff *skb, u32 info)
return 0;
}
+EXPORT_SYMBOL(esp4_err);
static void esp_destroy(struct xfrm_state *x)
{
--
1.7.9.5
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH RFC v2 04/13] ah4: Use the IPsec protocol multiplexer API
2013-12-16 9:18 [PATCH RFC v2 0/13] vti4: prepare namespace and interfamily support Steffen Klassert
` (2 preceding siblings ...)
2013-12-16 9:20 ` [PATCH RFC v2 03/13] esp4: Export esp4_err Steffen Klassert
@ 2013-12-16 9:21 ` Steffen Klassert
2013-12-16 9:21 ` [PATCH RFC v2 05/13] ah4: Export ah4_err Steffen Klassert
` (9 subsequent siblings)
13 siblings, 0 replies; 19+ messages in thread
From: Steffen Klassert @ 2013-12-16 9:21 UTC (permalink / raw)
To: netdev; +Cc: Christophe Gouault, Saurabh Mohan
Switch ah4 to use the new IPsec protocol multiplexer.
Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
---
net/ipv4/ah4.c | 24 +++++++++++++++---------
1 file changed, 15 insertions(+), 9 deletions(-)
diff --git a/net/ipv4/ah4.c b/net/ipv4/ah4.c
index 7179026..ea30e4e 100644
--- a/net/ipv4/ah4.c
+++ b/net/ipv4/ah4.c
@@ -397,7 +397,7 @@ out:
return err;
}
-static void ah4_err(struct sk_buff *skb, u32 info)
+static int ah4_err(struct sk_buff *skb, u32 info)
{
struct net *net = dev_net(skb->dev);
const struct iphdr *iph = (const struct iphdr *)skb->data;
@@ -407,23 +407,25 @@ static void ah4_err(struct sk_buff *skb, u32 info)
switch (icmp_hdr(skb)->type) {
case ICMP_DEST_UNREACH:
if (icmp_hdr(skb)->code != ICMP_FRAG_NEEDED)
- return;
+ return 0;
case ICMP_REDIRECT:
break;
default:
- return;
+ return 0;
}
x = xfrm_state_lookup(net, skb->mark, (const xfrm_address_t *)&iph->daddr,
ah->spi, IPPROTO_AH, AF_INET);
if (!x)
- return;
+ return 0;
if (icmp_hdr(skb)->type == ICMP_DEST_UNREACH)
ipv4_update_pmtu(skb, net, info, 0, 0, IPPROTO_AH, 0);
else
ipv4_redirect(skb, net, 0, 0, IPPROTO_AH, 0);
xfrm_state_put(x);
+
+ return 0;
}
static int ah_init_state(struct xfrm_state *x)
@@ -505,6 +507,10 @@ static void ah_destroy(struct xfrm_state *x)
kfree(ahp);
}
+static int ah4_rcv_cb(struct sk_buff *skb, int err)
+{
+ return 0;
+}
static const struct xfrm_type ah_type =
{
@@ -518,11 +524,11 @@ static const struct xfrm_type ah_type =
.output = ah_output
};
-static const struct net_protocol ah4_protocol = {
+static struct xfrm4_protocol ah4_protocol = {
.handler = xfrm4_rcv,
+ .cb_handler = ah4_rcv_cb,
.err_handler = ah4_err,
- .no_policy = 1,
- .netns_ok = 1,
+ .priority = 0,
};
static int __init ah4_init(void)
@@ -531,7 +537,7 @@ static int __init ah4_init(void)
pr_info("%s: can't add xfrm type\n", __func__);
return -EAGAIN;
}
- if (inet_add_protocol(&ah4_protocol, IPPROTO_AH) < 0) {
+ if (xfrm4_protocol_register(&ah4_protocol, IPPROTO_AH) < 0) {
pr_info("%s: can't add protocol\n", __func__);
xfrm_unregister_type(&ah_type, AF_INET);
return -EAGAIN;
@@ -541,7 +547,7 @@ static int __init ah4_init(void)
static void __exit ah4_fini(void)
{
- if (inet_del_protocol(&ah4_protocol, IPPROTO_AH) < 0)
+ if (xfrm4_protocol_deregister(&ah4_protocol, IPPROTO_AH) < 0)
pr_info("%s: can't remove protocol\n", __func__);
if (xfrm_unregister_type(&ah_type, AF_INET) < 0)
pr_info("%s: can't remove xfrm type\n", __func__);
--
1.7.9.5
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH RFC v2 05/13] ah4: Export ah4_err
2013-12-16 9:18 [PATCH RFC v2 0/13] vti4: prepare namespace and interfamily support Steffen Klassert
` (3 preceding siblings ...)
2013-12-16 9:21 ` [PATCH RFC v2 04/13] ah4: Use the IPsec protocol multiplexer API Steffen Klassert
@ 2013-12-16 9:21 ` Steffen Klassert
2013-12-16 9:22 ` [PATCH RFC v2 06/13] ipcomp4: Use the IPsec protocol multiplexer API Steffen Klassert
` (8 subsequent siblings)
13 siblings, 0 replies; 19+ messages in thread
From: Steffen Klassert @ 2013-12-16 9:21 UTC (permalink / raw)
To: netdev; +Cc: Christophe Gouault, Saurabh Mohan
ah4_err can be shared with the upcomming vti ah handler.
Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
---
include/net/ah.h | 2 ++
net/ipv4/ah4.c | 3 ++-
2 files changed, 4 insertions(+), 1 deletion(-)
diff --git a/include/net/ah.h b/include/net/ah.h
index ca95b98..6aa0f43 100644
--- a/include/net/ah.h
+++ b/include/net/ah.h
@@ -6,6 +6,8 @@
/* This is the maximum truncated ICV length that we know of. */
#define MAX_AH_AUTH_LEN 64
+int ah4_err(struct sk_buff *skb, u32 info);
+
struct crypto_ahash;
struct ah_data {
diff --git a/net/ipv4/ah4.c b/net/ipv4/ah4.c
index ea30e4e..4374671 100644
--- a/net/ipv4/ah4.c
+++ b/net/ipv4/ah4.c
@@ -397,7 +397,7 @@ out:
return err;
}
-static int ah4_err(struct sk_buff *skb, u32 info)
+int ah4_err(struct sk_buff *skb, u32 info)
{
struct net *net = dev_net(skb->dev);
const struct iphdr *iph = (const struct iphdr *)skb->data;
@@ -427,6 +427,7 @@ static int ah4_err(struct sk_buff *skb, u32 info)
return 0;
}
+EXPORT_SYMBOL(ah4_err);
static int ah_init_state(struct xfrm_state *x)
{
--
1.7.9.5
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH RFC v2 06/13] ipcomp4: Use the IPsec protocol multiplexer API
2013-12-16 9:18 [PATCH RFC v2 0/13] vti4: prepare namespace and interfamily support Steffen Klassert
` (4 preceding siblings ...)
2013-12-16 9:21 ` [PATCH RFC v2 05/13] ah4: Export ah4_err Steffen Klassert
@ 2013-12-16 9:22 ` Steffen Klassert
2013-12-16 9:23 ` [PATCH RFC v2 07/13] ipcomp4: Export ipcomp4_err Steffen Klassert
` (7 subsequent siblings)
13 siblings, 0 replies; 19+ messages in thread
From: Steffen Klassert @ 2013-12-16 9:22 UTC (permalink / raw)
To: netdev; +Cc: Christophe Gouault, Saurabh Mohan
Switch ipcomp4 to use the new IPsec protocol multiplexer.
Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
---
net/ipv4/ipcomp.c | 25 ++++++++++++++++---------
1 file changed, 16 insertions(+), 9 deletions(-)
diff --git a/net/ipv4/ipcomp.c b/net/ipv4/ipcomp.c
index 826be4c..c94d1c2 100644
--- a/net/ipv4/ipcomp.c
+++ b/net/ipv4/ipcomp.c
@@ -23,7 +23,7 @@
#include <net/protocol.h>
#include <net/sock.h>
-static void ipcomp4_err(struct sk_buff *skb, u32 info)
+static int ipcomp4_err(struct sk_buff *skb, u32 info)
{
struct net *net = dev_net(skb->dev);
__be32 spi;
@@ -34,24 +34,26 @@ static void ipcomp4_err(struct sk_buff *skb, u32 info)
switch (icmp_hdr(skb)->type) {
case ICMP_DEST_UNREACH:
if (icmp_hdr(skb)->code != ICMP_FRAG_NEEDED)
- return;
+ return 0;
case ICMP_REDIRECT:
break;
default:
- return;
+ return 0;
}
spi = htonl(ntohs(ipch->cpi));
x = xfrm_state_lookup(net, skb->mark, (const xfrm_address_t *)&iph->daddr,
spi, IPPROTO_COMP, AF_INET);
if (!x)
- return;
+ return 0;
if (icmp_hdr(skb)->type == ICMP_DEST_UNREACH)
ipv4_update_pmtu(skb, net, info, 0, 0, IPPROTO_COMP, 0);
else
ipv4_redirect(skb, net, 0, 0, IPPROTO_COMP, 0);
xfrm_state_put(x);
+
+ return 0;
}
/* We always hold one tunnel user reference to indicate a tunnel */
@@ -147,6 +149,11 @@ out:
return err;
}
+static int ipcomp4_rcv_cb(struct sk_buff *skb, int err)
+{
+ return 0;
+}
+
static const struct xfrm_type ipcomp_type = {
.description = "IPCOMP4",
.owner = THIS_MODULE,
@@ -157,11 +164,11 @@ static const struct xfrm_type ipcomp_type = {
.output = ipcomp_output
};
-static const struct net_protocol ipcomp4_protocol = {
+static struct xfrm4_protocol ipcomp4_protocol = {
.handler = xfrm4_rcv,
+ .cb_handler = ipcomp4_rcv_cb,
.err_handler = ipcomp4_err,
- .no_policy = 1,
- .netns_ok = 1,
+ .priority = 1,
};
static int __init ipcomp4_init(void)
@@ -170,7 +177,7 @@ static int __init ipcomp4_init(void)
pr_info("%s: can't add xfrm type\n", __func__);
return -EAGAIN;
}
- if (inet_add_protocol(&ipcomp4_protocol, IPPROTO_COMP) < 0) {
+ if (xfrm4_protocol_register(&ipcomp4_protocol, IPPROTO_COMP) < 0) {
pr_info("%s: can't add protocol\n", __func__);
xfrm_unregister_type(&ipcomp_type, AF_INET);
return -EAGAIN;
@@ -180,7 +187,7 @@ static int __init ipcomp4_init(void)
static void __exit ipcomp4_fini(void)
{
- if (inet_del_protocol(&ipcomp4_protocol, IPPROTO_COMP) < 0)
+ if (xfrm4_protocol_register(&ipcomp4_protocol, IPPROTO_COMP) < 0)
pr_info("%s: can't remove protocol\n", __func__);
if (xfrm_unregister_type(&ipcomp_type, AF_INET) < 0)
pr_info("%s: can't remove xfrm type\n", __func__);
--
1.7.9.5
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH RFC v2 07/13] ipcomp4: Export ipcomp4_err
2013-12-16 9:18 [PATCH RFC v2 0/13] vti4: prepare namespace and interfamily support Steffen Klassert
` (5 preceding siblings ...)
2013-12-16 9:22 ` [PATCH RFC v2 06/13] ipcomp4: Use the IPsec protocol multiplexer API Steffen Klassert
@ 2013-12-16 9:23 ` Steffen Klassert
2013-12-16 9:23 ` [PATCH RFC v2 08/13] xfrm: Add xfrm_tunnel_skb_cb to the skb common buffer Steffen Klassert
` (6 subsequent siblings)
13 siblings, 0 replies; 19+ messages in thread
From: Steffen Klassert @ 2013-12-16 9:23 UTC (permalink / raw)
To: netdev; +Cc: Christophe Gouault, Saurabh Mohan
ipcomp4_err can be shared with the upcomming vti ipcomp handler.
Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
---
include/net/ipcomp.h | 1 +
net/ipv4/ipcomp.c | 3 ++-
2 files changed, 3 insertions(+), 1 deletion(-)
diff --git a/include/net/ipcomp.h b/include/net/ipcomp.h
index cc4f30c..c9021de 100644
--- a/include/net/ipcomp.h
+++ b/include/net/ipcomp.h
@@ -20,6 +20,7 @@ int ipcomp_input(struct xfrm_state *x, struct sk_buff *skb);
int ipcomp_output(struct xfrm_state *x, struct sk_buff *skb);
void ipcomp_destroy(struct xfrm_state *x);
int ipcomp_init_state(struct xfrm_state *x);
+int ipcomp4_err(struct sk_buff *skb, u32 info);
static inline struct ip_comp_hdr *ip_comp_hdr(const struct sk_buff *skb)
{
diff --git a/net/ipv4/ipcomp.c b/net/ipv4/ipcomp.c
index c94d1c2..3a3404c 100644
--- a/net/ipv4/ipcomp.c
+++ b/net/ipv4/ipcomp.c
@@ -23,7 +23,7 @@
#include <net/protocol.h>
#include <net/sock.h>
-static int ipcomp4_err(struct sk_buff *skb, u32 info)
+int ipcomp4_err(struct sk_buff *skb, u32 info)
{
struct net *net = dev_net(skb->dev);
__be32 spi;
@@ -55,6 +55,7 @@ static int ipcomp4_err(struct sk_buff *skb, u32 info)
return 0;
}
+EXPORT_SYMBOL(ipcomp4_err);
/* We always hold one tunnel user reference to indicate a tunnel */
static struct xfrm_state *ipcomp_tunnel_create(struct xfrm_state *x)
--
1.7.9.5
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH RFC v2 08/13] xfrm: Add xfrm_tunnel_skb_cb to the skb common buffer
2013-12-16 9:18 [PATCH RFC v2 0/13] vti4: prepare namespace and interfamily support Steffen Klassert
` (6 preceding siblings ...)
2013-12-16 9:23 ` [PATCH RFC v2 07/13] ipcomp4: Export ipcomp4_err Steffen Klassert
@ 2013-12-16 9:23 ` Steffen Klassert
2013-12-16 12:54 ` Nicolas Dichtel
2013-12-16 9:24 ` [PATCH RFC v2 09/13] ip_tunnel: Make vti work with i_key set Steffen Klassert
` (5 subsequent siblings)
13 siblings, 1 reply; 19+ messages in thread
From: Steffen Klassert @ 2013-12-16 9:23 UTC (permalink / raw)
To: netdev; +Cc: Christophe Gouault, Saurabh Mohan
IPsec vti_rcv needs to remind the tunnel pointer to
check it later at the vti_rcv_cb callback. So add
this pointer to the IPsec common buffer.
Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
---
include/net/xfrm.h | 29 +++++++++++++++++------------
1 file changed, 17 insertions(+), 12 deletions(-)
diff --git a/include/net/xfrm.h b/include/net/xfrm.h
index 2c39cd4..584d0ee4 100644
--- a/include/net/xfrm.h
+++ b/include/net/xfrm.h
@@ -600,16 +600,27 @@ struct xfrm_mgr {
int xfrm_register_km(struct xfrm_mgr *km);
int xfrm_unregister_km(struct xfrm_mgr *km);
+struct xfrm_tunnel_skb_cb {
+ union {
+ struct inet_skb_parm h4;
+ struct inet6_skb_parm h6;
+ } header;
+
+ union {
+ struct ip_tunnel *ip4;
+ struct ip6_tnl *ip6;
+ } tunnel;
+};
+
+#define XFRM_TUNNEL_SKB_CB(__skb) ((struct xfrm_tunnel_skb_cb *)&((__skb)->cb[0]))
+
/*
* This structure is used for the duration where packets are being
* transformed by IPsec. As soon as the packet leaves IPsec the
* area beyond the generic IP part may be overwritten.
*/
struct xfrm_skb_cb {
- union {
- struct inet_skb_parm h4;
- struct inet6_skb_parm h6;
- } header;
+ struct xfrm_tunnel_skb_cb header;
/* Sequence number for replay protection. */
union {
@@ -631,10 +642,7 @@ struct xfrm_skb_cb {
* to transmit header information to the mode input/output functions.
*/
struct xfrm_mode_skb_cb {
- union {
- struct inet_skb_parm h4;
- struct inet6_skb_parm h6;
- } header;
+ struct xfrm_tunnel_skb_cb header;
/* Copied from header for IPv4, always set to zero and DF for IPv6. */
__be16 id;
@@ -666,10 +674,7 @@ struct xfrm_mode_skb_cb {
* related information.
*/
struct xfrm_spi_skb_cb {
- union {
- struct inet_skb_parm h4;
- struct inet6_skb_parm h6;
- } header;
+ struct xfrm_tunnel_skb_cb header;
unsigned int daddroff;
unsigned int family;
--
1.7.9.5
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH RFC v2 09/13] ip_tunnel: Make vti work with i_key set
2013-12-16 9:18 [PATCH RFC v2 0/13] vti4: prepare namespace and interfamily support Steffen Klassert
` (7 preceding siblings ...)
2013-12-16 9:23 ` [PATCH RFC v2 08/13] xfrm: Add xfrm_tunnel_skb_cb to the skb common buffer Steffen Klassert
@ 2013-12-16 9:24 ` Steffen Klassert
2013-12-16 9:25 ` [PATCH RFC v2 10/13] vti: Update the ipv4 side to use it's own receive hook Steffen Klassert
` (4 subsequent siblings)
13 siblings, 0 replies; 19+ messages in thread
From: Steffen Klassert @ 2013-12-16 9:24 UTC (permalink / raw)
To: netdev; +Cc: Christophe Gouault, Saurabh Mohan
Vti uses the o_key to mark packets that were transmitted or received
by a vti interface. Unfortunately we can't apply different marks
to in and outbound packets with only one key availabe. Vti interfaces
typically use wildcard selectors for vti IPsec policies. On forwarding,
the same output policy will match for both directions. This generates
a loop between the IPsec gateways until the ttl of the packet is
exceeded.
The gre i_key/o_key are usually there to find the right gre tunnel
during a lookup. When vti uses the i_key to mark packets, the tunnel
lookup does not work any more because vti does not use the gre keys
as a hash key for the lookup.
This patch workarounds this my not including the i_key when comupting
the hash for the tunnel lookup in case of vti tunnels.
With this we have separate keys available for the transmitting and
receiving side of the vti interface.
Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
---
net/ipv4/ip_tunnel.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/net/ipv4/ip_tunnel.c b/net/ipv4/ip_tunnel.c
index 90ff957..4bc7a6e 100644
--- a/net/ipv4/ip_tunnel.c
+++ b/net/ipv4/ip_tunnel.c
@@ -228,13 +228,17 @@ static struct hlist_head *ip_bucket(struct ip_tunnel_net *itn,
{
unsigned int h;
__be32 remote;
+ __be32 i_key = parms->i_key;
if (parms->iph.daddr && !ipv4_is_multicast(parms->iph.daddr))
remote = parms->iph.daddr;
else
remote = 0;
- h = ip_tunnel_hash(itn, parms->i_key, remote);
+ if (!(parms->i_flags & TUNNEL_KEY) && (parms->i_flags & VTI_ISVTI))
+ i_key = 0;
+
+ h = ip_tunnel_hash(itn, i_key, remote);
return &itn->tunnels[h];
}
--
1.7.9.5
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH RFC v2 10/13] vti: Update the ipv4 side to use it's own receive hook
2013-12-16 9:18 [PATCH RFC v2 0/13] vti4: prepare namespace and interfamily support Steffen Klassert
` (8 preceding siblings ...)
2013-12-16 9:24 ` [PATCH RFC v2 09/13] ip_tunnel: Make vti work with i_key set Steffen Klassert
@ 2013-12-16 9:25 ` Steffen Klassert
2013-12-16 9:26 ` [PATCH RFC v2 11/13] xfrm4: Remove xfrm_tunnel_notifier Steffen Klassert
` (3 subsequent siblings)
13 siblings, 0 replies; 19+ messages in thread
From: Steffen Klassert @ 2013-12-16 9:25 UTC (permalink / raw)
To: netdev; +Cc: Christophe Gouault, Saurabh Mohan
With this patch, vti uses the IPsec protocol multiplexer to
register it's own receive side hooks for ESP, AH and IPCOMP.
Vti now does the following on receive side:
1. Do an input policy check for the IPsec packet we received.
This is required because this packet could be already
prosecces by IPsec, so an inbuond policy check is needed.
2. Clean the skb to not leak informations on namespace
transitions.
3. Mark the packet with the i_key. The policy and the state
must match this key now. Policy and state belong to the vti
namespace and policy enforcement is done at the further layers.
4. Call the generic xfrm layer to do decryption and decapsulation.
5. Wait for a callback from the xfrm layer to properly update
the device statistics.
On transmit side:
1. Mark the packet with the o_key. The policy and the state
must match this key now.
2. Do a xfrm_lookup on the original packet with the mark applied.
3. Check if we got an IPsec route.
4. Clean the skb to not leak informations on namespace
transitions.
5. Attach the dst_enty we got from the xfrm_lookup to the skb.
6. Call dst_output to do the IPsec processing.
7. Do the device statistics.
Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
---
net/ipv4/ip_vti.c | 139 ++++++++++++++++++++++++++++++++++++++---------------
1 file changed, 100 insertions(+), 39 deletions(-)
diff --git a/net/ipv4/ip_vti.c b/net/ipv4/ip_vti.c
index 52b802a..17ec174 100644
--- a/net/ipv4/ip_vti.c
+++ b/net/ipv4/ip_vti.c
@@ -41,6 +41,9 @@
#include <net/ip_tunnels.h>
#include <net/inet_ecn.h>
#include <net/xfrm.h>
+#include <net/esp.h>
+#include <net/ah.h>
+#include <net/ipcomp.h>
#include <net/net_namespace.h>
#include <net/netns/generic.h>
@@ -49,7 +52,6 @@ static struct rtnl_link_ops vti_link_ops __read_mostly;
static int vti_net_id __read_mostly;
static int vti_tunnel_init(struct net_device *dev);
-/* We dont digest the packet therefore let the packet pass */
static int vti_rcv(struct sk_buff *skb)
{
struct ip_tunnel *tunnel;
@@ -60,66 +62,79 @@ static int vti_rcv(struct sk_buff *skb)
tunnel = ip_tunnel_lookup(itn, skb->dev->ifindex, TUNNEL_NO_KEY,
iph->saddr, iph->daddr, 0);
if (tunnel != NULL) {
- struct pcpu_tstats *tstats;
- u32 oldmark = skb->mark;
- int ret;
+ if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb))
+ goto drop;
+ skb_scrub_packet(skb, !net_eq(tunnel->net, dev_net(tunnel->dev)));
- /* temporarily mark the skb with the tunnel o_key, to
- * only match policies with this mark.
- */
- skb->mark = be32_to_cpu(tunnel->parms.o_key);
- ret = xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb);
- skb->mark = oldmark;
- if (!ret)
- return -1;
+ XFRM_TUNNEL_SKB_CB(skb)->tunnel.ip4 = tunnel;
- tstats = this_cpu_ptr(tunnel->dev->tstats);
+ skb->mark = be32_to_cpu(tunnel->parms.i_key);
+ skb->dev = tunnel->dev;
+
+ return xfrm4_rcv(skb);
+ }
+
+ return -1;
+drop:
+ kfree_skb(skb);
+ return 0;
+}
+
+static int vti_rcv_cb(struct sk_buff *skb, int err)
+{
+ struct net_device *dev = skb->dev;
+ struct pcpu_tstats *tstats;
+ struct ip_tunnel *tunnel = XFRM_TUNNEL_SKB_CB(skb)->tunnel.ip4;
+
+ if (!tunnel || tunnel != netdev_priv(dev))
+ return -1;
+
+ tstats = this_cpu_ptr(dev->tstats);
+
+ if (!err) {
u64_stats_update_begin(&tstats->syncp);
tstats->rx_packets++;
tstats->rx_bytes += skb->len;
u64_stats_update_end(&tstats->syncp);
- secpath_reset(skb);
- skb->dev = tunnel->dev;
- return 1;
+ return 0;
}
- return -1;
+ if (err == -EINPROGRESS)
+ return 0;
+
+ dev->stats.rx_errors++;
+ dev->stats.rx_dropped++;
+
+ return 0;
}
/* This function assumes it is being called from dev_queue_xmit()
* and that skb is filled properly by that function.
*/
-
static netdev_tx_t vti_tunnel_xmit(struct sk_buff *skb, struct net_device *dev)
{
struct ip_tunnel *tunnel = netdev_priv(dev);
- struct iphdr *tiph = &tunnel->parms.iph;
- u8 tos;
struct rtable *rt; /* Route to the other host */
struct net_device *tdev; /* Device to other host */
- struct iphdr *old_iph = ip_hdr(skb);
- __be32 dst = tiph->daddr;
- struct flowi4 fl4;
+ struct flowi fl;
int err;
if (skb->protocol != htons(ETH_P_IP))
goto tx_error;
- tos = old_iph->tos;
+ memset(&fl, 0, sizeof(fl));
+ skb->mark = be32_to_cpu(tunnel->parms.o_key);
+ xfrm_decode_session(skb, &fl, AF_INET);
- memset(&fl4, 0, sizeof(fl4));
- flowi4_init_output(&fl4, tunnel->parms.link,
- be32_to_cpu(tunnel->parms.o_key), RT_TOS(tos),
- RT_SCOPE_UNIVERSE,
- IPPROTO_IPIP, 0,
- dst, tiph->saddr, 0, 0);
- rt = ip_route_output_key(dev_net(dev), &fl4);
+ dst_hold(skb_dst(skb));
+ rt = (struct rtable *)xfrm_lookup(tunnel->net, skb_dst(skb), &fl, NULL, 0);
if (IS_ERR(rt)) {
dev->stats.tx_carrier_errors++;
goto tx_error_icmp;
}
+
/* if there is no transform then this tunnel is not functional.
* Or if the xfrm is not mode tunnel.
*/
@@ -147,9 +162,8 @@ static netdev_tx_t vti_tunnel_xmit(struct sk_buff *skb, struct net_device *dev)
}
memset(IPCB(skb), 0, sizeof(*IPCB(skb)));
- skb_dst_drop(skb);
+ skb_scrub_packet(skb, !net_eq(tunnel->net, dev_net(dev)));
skb_dst_set(skb, &rt->dst);
- nf_reset(skb);
skb->dev = skb_dst(skb)->dev;
err = dst_output(skb);
@@ -181,12 +195,13 @@ vti_tunnel_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
return -EINVAL;
}
+ p.i_flags |= VTI_ISVTI;
err = ip_tunnel_ioctl(dev, &p, cmd);
if (err)
return err;
if (cmd != SIOCDELTUNNEL) {
- p.i_flags |= GRE_KEY | VTI_ISVTI;
+ p.i_flags |= GRE_KEY;
p.o_flags |= GRE_KEY;
}
@@ -241,9 +256,25 @@ static void __net_init vti_fb_tunnel_init(struct net_device *dev)
iph->ihl = 5;
}
-static struct xfrm_tunnel_notifier vti_handler __read_mostly = {
+static struct xfrm4_protocol vti_esp4_protocol __read_mostly = {
.handler = vti_rcv,
- .priority = 1,
+ .cb_handler = vti_rcv_cb,
+ .err_handler = esp4_err,
+ .priority = 100,
+};
+
+static struct xfrm4_protocol vti_ah4_protocol __read_mostly = {
+ .handler = vti_rcv,
+ .cb_handler = vti_rcv_cb,
+ .err_handler = ah4_err,
+ .priority = 100,
+};
+
+static struct xfrm4_protocol vti_ipcomp4_protocol __read_mostly = {
+ .handler = vti_rcv,
+ .cb_handler = vti_rcv_cb,
+ .err_handler = ipcomp4_err,
+ .priority = 100,
};
static int __net_init vti_init_net(struct net *net)
@@ -287,6 +318,8 @@ static void vti_netlink_parms(struct nlattr *data[],
if (!data)
return;
+ parms->i_flags = VTI_ISVTI;
+
if (data[IFLA_VTI_LINK])
parms->link = nla_get_u32(data[IFLA_VTI_LINK]);
@@ -382,10 +415,31 @@ static int __init vti_init(void)
err = register_pernet_device(&vti_net_ops);
if (err < 0)
return err;
- err = xfrm4_mode_tunnel_input_register(&vti_handler);
+ err = xfrm4_protocol_register(&vti_esp4_protocol, IPPROTO_ESP);
+ if (err < 0) {
+ unregister_pernet_device(&vti_net_ops);
+ pr_info("vti init: can't register tunnel\n");
+
+ return err;
+ }
+
+ err = xfrm4_protocol_register(&vti_ah4_protocol, IPPROTO_AH);
+ if (err < 0) {
+ xfrm4_protocol_deregister(&vti_esp4_protocol, IPPROTO_ESP);
+ unregister_pernet_device(&vti_net_ops);
+ pr_info("vti init: can't register tunnel\n");
+
+ return err;
+ }
+
+ err = xfrm4_protocol_register(&vti_ipcomp4_protocol, IPPROTO_COMP);
if (err < 0) {
+ xfrm4_protocol_deregister(&vti_ah4_protocol, IPPROTO_AH);
+ xfrm4_protocol_deregister(&vti_esp4_protocol, IPPROTO_ESP);
unregister_pernet_device(&vti_net_ops);
pr_info("vti init: can't register tunnel\n");
+
+ return err;
}
err = rtnl_link_register(&vti_link_ops);
@@ -395,7 +449,9 @@ static int __init vti_init(void)
return err;
rtnl_link_failed:
- xfrm4_mode_tunnel_input_deregister(&vti_handler);
+ xfrm4_protocol_deregister(&vti_ipcomp4_protocol, IPPROTO_COMP);
+ xfrm4_protocol_deregister(&vti_ah4_protocol, IPPROTO_AH);
+ xfrm4_protocol_deregister(&vti_esp4_protocol, IPPROTO_ESP);
unregister_pernet_device(&vti_net_ops);
return err;
}
@@ -403,8 +459,13 @@ rtnl_link_failed:
static void __exit vti_fini(void)
{
rtnl_link_unregister(&vti_link_ops);
- if (xfrm4_mode_tunnel_input_deregister(&vti_handler))
+ if (xfrm4_protocol_deregister(&vti_ipcomp4_protocol, IPPROTO_COMP))
+ pr_info("vti close: can't deregister tunnel\n");
+ if (xfrm4_protocol_deregister(&vti_ah4_protocol, IPPROTO_AH))
pr_info("vti close: can't deregister tunnel\n");
+ if (xfrm4_protocol_deregister(&vti_esp4_protocol, IPPROTO_ESP))
+ pr_info("vti close: can't deregister tunnel\n");
+
unregister_pernet_device(&vti_net_ops);
}
--
1.7.9.5
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH RFC v2 11/13] xfrm4: Remove xfrm_tunnel_notifier
2013-12-16 9:18 [PATCH RFC v2 0/13] vti4: prepare namespace and interfamily support Steffen Klassert
` (9 preceding siblings ...)
2013-12-16 9:25 ` [PATCH RFC v2 10/13] vti: Update the ipv4 side to use it's own receive hook Steffen Klassert
@ 2013-12-16 9:26 ` Steffen Klassert
2013-12-16 9:27 ` [PATCH RFC v2 12/13] vti4: Use the on xfrm_lookup returned dst_entry directly Steffen Klassert
` (2 subsequent siblings)
13 siblings, 0 replies; 19+ messages in thread
From: Steffen Klassert @ 2013-12-16 9:26 UTC (permalink / raw)
To: netdev; +Cc: Christophe Gouault, Saurabh Mohan
This was used from vti and is replaced by the IPsec protocol
multiplexer hooks. It is now unused, so remove it.
Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
---
include/net/xfrm.h | 2 --
net/ipv4/xfrm4_mode_tunnel.c | 68 ------------------------------------------
2 files changed, 70 deletions(-)
diff --git a/include/net/xfrm.h b/include/net/xfrm.h
index 584d0ee4..ef66eaf 100644
--- a/include/net/xfrm.h
+++ b/include/net/xfrm.h
@@ -1525,8 +1525,6 @@ int xfrm4_protocol_deregister(struct xfrm4_protocol *handler, unsigned char prot
int xfrm4_tunnel_register(struct xfrm_tunnel *handler, unsigned short family);
int xfrm4_tunnel_deregister(struct xfrm_tunnel *handler, unsigned short family);
void xfrm4_local_error(struct sk_buff *skb, u32 mtu);
-int xfrm4_mode_tunnel_input_register(struct xfrm_tunnel_notifier *handler);
-int xfrm4_mode_tunnel_input_deregister(struct xfrm_tunnel_notifier *handler);
int xfrm6_mode_tunnel_input_register(struct xfrm_tunnel_notifier *handler);
int xfrm6_mode_tunnel_input_deregister(struct xfrm_tunnel_notifier *handler);
int xfrm6_extract_header(struct sk_buff *skb);
diff --git a/net/ipv4/xfrm4_mode_tunnel.c b/net/ipv4/xfrm4_mode_tunnel.c
index 31b1815..05f2b48 100644
--- a/net/ipv4/xfrm4_mode_tunnel.c
+++ b/net/ipv4/xfrm4_mode_tunnel.c
@@ -15,65 +15,6 @@
#include <net/ip.h>
#include <net/xfrm.h>
-/* Informational hook. The decap is still done here. */
-static struct xfrm_tunnel_notifier __rcu *rcv_notify_handlers __read_mostly;
-static DEFINE_MUTEX(xfrm4_mode_tunnel_input_mutex);
-
-int xfrm4_mode_tunnel_input_register(struct xfrm_tunnel_notifier *handler)
-{
- struct xfrm_tunnel_notifier __rcu **pprev;
- struct xfrm_tunnel_notifier *t;
- int ret = -EEXIST;
- int priority = handler->priority;
-
- mutex_lock(&xfrm4_mode_tunnel_input_mutex);
-
- for (pprev = &rcv_notify_handlers;
- (t = rcu_dereference_protected(*pprev,
- lockdep_is_held(&xfrm4_mode_tunnel_input_mutex))) != NULL;
- pprev = &t->next) {
- if (t->priority > priority)
- break;
- if (t->priority == priority)
- goto err;
-
- }
-
- handler->next = *pprev;
- rcu_assign_pointer(*pprev, handler);
-
- ret = 0;
-
-err:
- mutex_unlock(&xfrm4_mode_tunnel_input_mutex);
- return ret;
-}
-EXPORT_SYMBOL_GPL(xfrm4_mode_tunnel_input_register);
-
-int xfrm4_mode_tunnel_input_deregister(struct xfrm_tunnel_notifier *handler)
-{
- struct xfrm_tunnel_notifier __rcu **pprev;
- struct xfrm_tunnel_notifier *t;
- int ret = -ENOENT;
-
- mutex_lock(&xfrm4_mode_tunnel_input_mutex);
- for (pprev = &rcv_notify_handlers;
- (t = rcu_dereference_protected(*pprev,
- lockdep_is_held(&xfrm4_mode_tunnel_input_mutex))) != NULL;
- pprev = &t->next) {
- if (t == handler) {
- *pprev = handler->next;
- ret = 0;
- break;
- }
- }
- mutex_unlock(&xfrm4_mode_tunnel_input_mutex);
- synchronize_net();
-
- return ret;
-}
-EXPORT_SYMBOL_GPL(xfrm4_mode_tunnel_input_deregister);
-
static inline void ipip_ecn_decapsulate(struct sk_buff *skb)
{
struct iphdr *inner_iph = ipip_hdr(skb);
@@ -127,14 +68,8 @@ static int xfrm4_mode_tunnel_output(struct xfrm_state *x, struct sk_buff *skb)
return 0;
}
-#define for_each_input_rcu(head, handler) \
- for (handler = rcu_dereference(head); \
- handler != NULL; \
- handler = rcu_dereference(handler->next))
-
static int xfrm4_mode_tunnel_input(struct xfrm_state *x, struct sk_buff *skb)
{
- struct xfrm_tunnel_notifier *handler;
int err = -EINVAL;
if (XFRM_MODE_SKB_CB(skb)->protocol != IPPROTO_IPIP)
@@ -143,9 +78,6 @@ static int xfrm4_mode_tunnel_input(struct xfrm_state *x, struct sk_buff *skb)
if (!pskb_may_pull(skb, sizeof(struct iphdr)))
goto out;
- for_each_input_rcu(rcv_notify_handlers, handler)
- handler->handler(skb);
-
err = skb_unclone(skb, GFP_ATOMIC);
if (err)
goto out;
--
1.7.9.5
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH RFC v2 12/13] vti4: Use the on xfrm_lookup returned dst_entry directly
2013-12-16 9:18 [PATCH RFC v2 0/13] vti4: prepare namespace and interfamily support Steffen Klassert
` (10 preceding siblings ...)
2013-12-16 9:26 ` [PATCH RFC v2 11/13] xfrm4: Remove xfrm_tunnel_notifier Steffen Klassert
@ 2013-12-16 9:27 ` Steffen Klassert
2013-12-16 9:28 ` [PATCH RFC v2 13/13] vti4: Support inter address family tunneling Steffen Klassert
2014-01-07 16:11 ` [PATCH RFC v2 0/13] vti4: prepare namespace and interfamily support Christophe Gouault
13 siblings, 0 replies; 19+ messages in thread
From: Steffen Klassert @ 2013-12-16 9:27 UTC (permalink / raw)
To: netdev; +Cc: Christophe Gouault, Saurabh Mohan
We need to be protocol family indepenent to support
inter addresss family tunneling with vti. So use a
dst_entry instead of the ipv4 rtable in vti_tunnel_xmit.
Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
---
net/ipv4/ip_vti.c | 18 +++++++++---------
1 file changed, 9 insertions(+), 9 deletions(-)
diff --git a/net/ipv4/ip_vti.c b/net/ipv4/ip_vti.c
index 17ec174..f269310 100644
--- a/net/ipv4/ip_vti.c
+++ b/net/ipv4/ip_vti.c
@@ -116,7 +116,7 @@ static int vti_rcv_cb(struct sk_buff *skb, int err)
static netdev_tx_t vti_tunnel_xmit(struct sk_buff *skb, struct net_device *dev)
{
struct ip_tunnel *tunnel = netdev_priv(dev);
- struct rtable *rt; /* Route to the other host */
+ struct dst_entry *dst;
struct net_device *tdev; /* Device to other host */
struct flowi fl;
int err;
@@ -129,8 +129,8 @@ static netdev_tx_t vti_tunnel_xmit(struct sk_buff *skb, struct net_device *dev)
xfrm_decode_session(skb, &fl, AF_INET);
dst_hold(skb_dst(skb));
- rt = (struct rtable *)xfrm_lookup(tunnel->net, skb_dst(skb), &fl, NULL, 0);
- if (IS_ERR(rt)) {
+ dst = xfrm_lookup(tunnel->net, skb_dst(skb), &fl, NULL, 0);
+ if (IS_ERR(dst)) {
dev->stats.tx_carrier_errors++;
goto tx_error_icmp;
}
@@ -138,16 +138,16 @@ static netdev_tx_t vti_tunnel_xmit(struct sk_buff *skb, struct net_device *dev)
/* if there is no transform then this tunnel is not functional.
* Or if the xfrm is not mode tunnel.
*/
- if (!rt->dst.xfrm ||
- rt->dst.xfrm->props.mode != XFRM_MODE_TUNNEL) {
+ if (!dst->xfrm ||
+ dst->xfrm->props.mode != XFRM_MODE_TUNNEL) {
dev->stats.tx_carrier_errors++;
- ip_rt_put(rt);
+ dst_release(dst);
goto tx_error_icmp;
}
- tdev = rt->dst.dev;
+ tdev = dst->dev;
if (tdev == dev) {
- ip_rt_put(rt);
+ dst_release(dst);
dev->stats.collisions++;
goto tx_error;
}
@@ -163,7 +163,7 @@ static netdev_tx_t vti_tunnel_xmit(struct sk_buff *skb, struct net_device *dev)
memset(IPCB(skb), 0, sizeof(*IPCB(skb)));
skb_scrub_packet(skb, !net_eq(tunnel->net, dev_net(dev)));
- skb_dst_set(skb, &rt->dst);
+ skb_dst_set(skb, dst);
skb->dev = skb_dst(skb)->dev;
err = dst_output(skb);
--
1.7.9.5
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH RFC v2 13/13] vti4: Support inter address family tunneling.
2013-12-16 9:18 [PATCH RFC v2 0/13] vti4: prepare namespace and interfamily support Steffen Klassert
` (11 preceding siblings ...)
2013-12-16 9:27 ` [PATCH RFC v2 12/13] vti4: Use the on xfrm_lookup returned dst_entry directly Steffen Klassert
@ 2013-12-16 9:28 ` Steffen Klassert
2014-01-07 16:11 ` [PATCH RFC v2 0/13] vti4: prepare namespace and interfamily support Christophe Gouault
13 siblings, 0 replies; 19+ messages in thread
From: Steffen Klassert @ 2013-12-16 9:28 UTC (permalink / raw)
To: netdev; +Cc: Christophe Gouault, Saurabh Mohan
With this patch we can tunnel ipv6 traffic via a vti4
interface. A vti4 interface can now have an ipv6 address
and ipv6 traffic can be routed via a vti4 interface.
The resulting traffic is xfrm transformed and tunneled
throuhg ipv4 if matching IPsec policies and states are
present.
Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
---
net/ipv4/ip_vti.c | 48 ++++++++++++++++++++++++++++++++++--------------
1 file changed, 34 insertions(+), 14 deletions(-)
diff --git a/net/ipv4/ip_vti.c b/net/ipv4/ip_vti.c
index f269310..8a2934c 100644
--- a/net/ipv4/ip_vti.c
+++ b/net/ipv4/ip_vti.c
@@ -34,6 +34,7 @@
#include <linux/init.h>
#include <linux/netfilter_ipv4.h>
#include <linux/if_ether.h>
+#include <linux/icmpv6.h>
#include <net/sock.h>
#include <net/ip.h>
@@ -110,26 +111,16 @@ static int vti_rcv_cb(struct sk_buff *skb, int err)
return 0;
}
-/* This function assumes it is being called from dev_queue_xmit()
- * and that skb is filled properly by that function.
- */
-static netdev_tx_t vti_tunnel_xmit(struct sk_buff *skb, struct net_device *dev)
+static netdev_tx_t vti_xmit(struct sk_buff *skb, struct net_device *dev,
+ struct flowi *fl)
{
struct ip_tunnel *tunnel = netdev_priv(dev);
struct dst_entry *dst;
struct net_device *tdev; /* Device to other host */
- struct flowi fl;
int err;
- if (skb->protocol != htons(ETH_P_IP))
- goto tx_error;
-
- memset(&fl, 0, sizeof(fl));
- skb->mark = be32_to_cpu(tunnel->parms.o_key);
- xfrm_decode_session(skb, &fl, AF_INET);
-
dst_hold(skb_dst(skb));
- dst = xfrm_lookup(tunnel->net, skb_dst(skb), &fl, NULL, 0);
+ dst = xfrm_lookup(tunnel->net, skb_dst(skb), fl, NULL, 0);
if (IS_ERR(dst)) {
dev->stats.tx_carrier_errors++;
goto tx_error_icmp;
@@ -161,7 +152,6 @@ static netdev_tx_t vti_tunnel_xmit(struct sk_buff *skb, struct net_device *dev)
tunnel->err_count = 0;
}
- memset(IPCB(skb), 0, sizeof(*IPCB(skb)));
skb_scrub_packet(skb, !net_eq(tunnel->net, dev_net(dev)));
skb_dst_set(skb, dst);
skb->dev = skb_dst(skb)->dev;
@@ -180,6 +170,36 @@ tx_error:
return NETDEV_TX_OK;
}
+/* This function assumes it is being called from dev_queue_xmit()
+ * and that skb is filled properly by that function.
+ */
+static netdev_tx_t vti_tunnel_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+ struct ip_tunnel *tunnel = netdev_priv(dev);
+ struct flowi fl;
+
+ memset(&fl, 0, sizeof(fl));
+
+ skb->mark = be32_to_cpu(tunnel->parms.o_key);
+
+ switch (skb->protocol) {
+ case htons(ETH_P_IP):
+ xfrm_decode_session(skb, &fl, AF_INET);
+ memset(IPCB(skb), 0, sizeof(*IPCB(skb)));
+ break;
+ case htons(ETH_P_IPV6):
+ xfrm_decode_session(skb, &fl, AF_INET6);
+ memset(IP6CB(skb), 0, sizeof(*IP6CB(skb)));
+ break;
+ default:
+ dev->stats.tx_errors++;
+ dev_kfree_skb(skb);
+ return NETDEV_TX_OK;
+ }
+
+ return vti_xmit(skb, dev, &fl);
+}
+
static int
vti_tunnel_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
{
--
1.7.9.5
^ permalink raw reply related [flat|nested] 19+ messages in thread
* Re: [PATCH RFC v2 08/13] xfrm: Add xfrm_tunnel_skb_cb to the skb common buffer
2013-12-16 9:23 ` [PATCH RFC v2 08/13] xfrm: Add xfrm_tunnel_skb_cb to the skb common buffer Steffen Klassert
@ 2013-12-16 12:54 ` Nicolas Dichtel
2013-12-16 13:02 ` Steffen Klassert
0 siblings, 1 reply; 19+ messages in thread
From: Nicolas Dichtel @ 2013-12-16 12:54 UTC (permalink / raw)
To: Steffen Klassert, netdev; +Cc: Christophe Gouault, Saurabh Mohan
Le 16/12/2013 10:23, Steffen Klassert a écrit :
> IPsec vti_rcv needs to remind the tunnel pointer to
> check it later at the vti_rcv_cb callback. So add
> this pointer to the IPsec common buffer.
>
> Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
> ---
> include/net/xfrm.h | 29 +++++++++++++++++------------
> 1 file changed, 17 insertions(+), 12 deletions(-)
>
> diff --git a/include/net/xfrm.h b/include/net/xfrm.h
> index 2c39cd4..584d0ee4 100644
> --- a/include/net/xfrm.h
> +++ b/include/net/xfrm.h
> @@ -600,16 +600,27 @@ struct xfrm_mgr {
> int xfrm_register_km(struct xfrm_mgr *km);
> int xfrm_unregister_km(struct xfrm_mgr *km);
>
> +struct xfrm_tunnel_skb_cb {
> + union {
> + struct inet_skb_parm h4;
> + struct inet6_skb_parm h6;
> + } header;
Nitpicking: this line is aligned with spaces instead tabs (yes, it's
a copy and paste ;-)).
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH RFC v2 08/13] xfrm: Add xfrm_tunnel_skb_cb to the skb common buffer
2013-12-16 12:54 ` Nicolas Dichtel
@ 2013-12-16 13:02 ` Steffen Klassert
0 siblings, 0 replies; 19+ messages in thread
From: Steffen Klassert @ 2013-12-16 13:02 UTC (permalink / raw)
To: Nicolas Dichtel; +Cc: netdev, Christophe Gouault, Saurabh Mohan
On Mon, Dec 16, 2013 at 01:54:10PM +0100, Nicolas Dichtel wrote:
> Le 16/12/2013 10:23, Steffen Klassert a écrit :
> >IPsec vti_rcv needs to remind the tunnel pointer to
> >check it later at the vti_rcv_cb callback. So add
> >this pointer to the IPsec common buffer.
> >
> >Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
> >---
> > include/net/xfrm.h | 29 +++++++++++++++++------------
> > 1 file changed, 17 insertions(+), 12 deletions(-)
> >
> >diff --git a/include/net/xfrm.h b/include/net/xfrm.h
> >index 2c39cd4..584d0ee4 100644
> >--- a/include/net/xfrm.h
> >+++ b/include/net/xfrm.h
> >@@ -600,16 +600,27 @@ struct xfrm_mgr {
> > int xfrm_register_km(struct xfrm_mgr *km);
> > int xfrm_unregister_km(struct xfrm_mgr *km);
> >
> >+struct xfrm_tunnel_skb_cb {
> >+ union {
> >+ struct inet_skb_parm h4;
> >+ struct inet6_skb_parm h6;
> >+ } header;
> Nitpicking: this line is aligned with spaces instead tabs (yes, it's
> a copy and paste ;-)).
No problem, will fix it.
Thanks for looking at the vti patches :)
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH RFC v2 0/13] vti4: prepare namespace and interfamily support.
2013-12-16 9:18 [PATCH RFC v2 0/13] vti4: prepare namespace and interfamily support Steffen Klassert
` (12 preceding siblings ...)
2013-12-16 9:28 ` [PATCH RFC v2 13/13] vti4: Support inter address family tunneling Steffen Klassert
@ 2014-01-07 16:11 ` Christophe Gouault
2014-01-07 19:45 ` Christophe Gouault
2014-01-14 7:51 ` Steffen Klassert
13 siblings, 2 replies; 19+ messages in thread
From: Christophe Gouault @ 2014-01-07 16:11 UTC (permalink / raw)
To: Steffen Klassert, netdev; +Cc: Saurabh Mohan
On 12/16/2013 10:18 AM, Steffen Klassert wrote:
> This patchset prepares vti4 for proper namespace and interfamily support.
>
> Currently the receive hook is in the middle of the decapsulation
> process, some of the header pointers point still into the IPsec packet
> others point already into the decapsulated packet. This makes it
> very unflexible and proper namespace and interfamily support can't
> be done as it is.
>
> The patchset that implements an IPsec protocol multiplexer, so that vti
> can register it's own receive path hooks. Further it makes the i_key
> usable for vti and changes the vti4 code to do the following:
>
> vti uses the IPsec protocol multiplexer to register it's
> own receive side hooks for ESP, AH and IPCOMP.
>
> Vti does the following on receive side:
>
> 1. Do an input policy check for the IPsec packet we received.
> This is required because this packet could be already
> processed by IPsec (tunnel in tunnel or a block policy
> is present), so an inbound policy check is needed.
>
> 2. Clean the skb to not leak informations on namespace
> transitions.
>
> 3. Mark the packet with the i_key. The policy and the state
> must match this key now. Policy and state belong to the vti
> namespace and policy enforcement is done at the further layers.
>
> 4. Call the generic xfrm layer to do decryption and decapsulation.
>
> 5. Wait for a callback from the xfrm layer to properly update
> the device statistics.
Sorry for my late comments, I had to delay my tests due to Christmas and
New Year's celebrations.
I have a few comments about your proposed patches:
In input, the vti tunnel processing does not follow the usual tunnel
processing. Conventionally, the packets are first decapsulated, then
only the skbuff interface is changed to the tunnel interface. In the vti
code, the interface is changed before IPsec decryption, hence before
decapsulation.
It results in a configuration asymmetry when we later support cross
netns: the outer SAs and SPs must be defined in the outer netns, while
the inner SAs and SPs must be defined in the inner netns. This is a
little disturbing.
> On transmit side:
>
> 1. Mark the packet with the o_key. The policy and the state
> must match this key now.
>
> 2. Do a xfrm_lookup on the original packet with the mark applied.
>
> 3. Check if we got an IPsec route.
>
> 4. Clean the skb to not leak informations on namespace
> transitions.
>
> 5. Attach the dst_enty we got from the xfrm_lookup to the skb.
>
> 6. Call dst_output to do the IPsec processing.
>
> 7. Do the device statistics.
In output, when the route points to a vti interface, the global SPD
lookup is not bypassed: an SPD lookup is still performed for a global
SPD (i.e. without applying the vti mark). Then only the packet can enter
the vti interface, in which a second SPD lookup is done, in the vti
interface SPD (i.e. after applying the vti mark). Of course if the
global SPD lookup returned a tunnel mode policy, then the packet may
finally not enter the vti interface, because a new route is looked up
after the IPsec encapsulation.
My understanding of the vti interface interest is enabling to use
routing (possibly dynamic routes) *instead* of complex security
policies. And in this use case I expect that entering a vti interface
will *override* the global policies (in the same manner as socket
policies override the global policies).
Otherwise, if we want to mix global and vti policies on the same
machine, then we must carefully define global policies that do not match
traffic destined to vti interfaces.
Note that setting the NOXFRM flag on the vti interface does not work
around this issue, it disables both the global and vti SPD lookup and
the traffic is finally dropped.
> Changes from v1:
>
> - Rebased to current net-next.
> - Fix a rcu lockdep complaint in xfrm protocol registration/deregistration.
> - Fix usage of a ipv4 specific callback handler in generic code.
> - Use skb_scrub_packet() to clear the skb in vti_rcv(), suggested by
> Nicolas Dichtel.
> - Add support for IPCOMP.
> - Support inter address family tunneling.
>
> I'd take this into the ipsec-next tree after some testing if noone
> has further suggestions or objections.
>
> I have the ipv6 side ready too, this will be a separate patchset.
> The ipv6 patchset has dependencies against the ipv4 patchset, so I
> hold it back until we have got the ipv4 side merged.
>
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH RFC v2 0/13] vti4: prepare namespace and interfamily support.
2014-01-07 16:11 ` [PATCH RFC v2 0/13] vti4: prepare namespace and interfamily support Christophe Gouault
@ 2014-01-07 19:45 ` Christophe Gouault
2014-01-14 7:51 ` Steffen Klassert
1 sibling, 0 replies; 19+ messages in thread
From: Christophe Gouault @ 2014-01-07 19:45 UTC (permalink / raw)
To: Steffen Klassert, netdev; +Cc: Saurabh Mohan
Le 07/01/2014 17:11, Christophe Gouault a écrit :
> On 12/16/2013 10:18 AM, Steffen Klassert wrote:
>> This patchset prepares vti4 for proper namespace and interfamily support.
>>
>> Currently the receive hook is in the middle of the decapsulation
>> process, some of the header pointers point still into the IPsec packet
>> others point already into the decapsulated packet. This makes it
>> very unflexible and proper namespace and interfamily support can't
>> be done as it is.
>>
>> The patchset that implements an IPsec protocol multiplexer, so that vti
>> can register it's own receive path hooks. Further it makes the i_key
>> usable for vti and changes the vti4 code to do the following:
>>
>> vti uses the IPsec protocol multiplexer to register it's
>> own receive side hooks for ESP, AH and IPCOMP.
>>
>> Vti does the following on receive side:
>>
>> 1. Do an input policy check for the IPsec packet we received.
>> This is required because this packet could be already
>> processed by IPsec (tunnel in tunnel or a block policy
>> is present), so an inbound policy check is needed.
>>
>> 2. Clean the skb to not leak informations on namespace
>> transitions.
>>
>> 3. Mark the packet with the i_key. The policy and the state
>> must match this key now. Policy and state belong to the vti
>> namespace and policy enforcement is done at the further layers.
>>
>> 4. Call the generic xfrm layer to do decryption and decapsulation.
>>
>> 5. Wait for a callback from the xfrm layer to properly update
>> the device statistics.
>
> Sorry for my late comments, I had to delay my tests due to Christmas and
> New Year's celebrations.
>
> I have a few comments about your proposed patches:
>
> In input, the vti tunnel processing does not follow the usual tunnel
> processing. Conventionally, the packets are first decapsulated, then
> only the skbuff interface is changed to the tunnel interface. In the vti
> code, the interface is changed before IPsec decryption, hence before
> decapsulation.
>
> It results in a configuration asymmetry when we later support cross
> netns: the outer SAs and SPs must be defined in the outer netns, while
> the inner SAs and SPs must be defined in the inner netns. This is a
> little disturbing.
>
>> On transmit side:
>>
>> 1. Mark the packet with the o_key. The policy and the state
>> must match this key now.
>>
>> 2. Do a xfrm_lookup on the original packet with the mark applied.
>>
>> 3. Check if we got an IPsec route.
>>
>> 4. Clean the skb to not leak informations on namespace
>> transitions.
>>
>> 5. Attach the dst_enty we got from the xfrm_lookup to the skb.
>>
>> 6. Call dst_output to do the IPsec processing.
>>
>> 7. Do the device statistics.
>
> In output, when the route points to a vti interface, the global SPD
> lookup is not bypassed: an SPD lookup is still performed for a global
> SPD (i.e. without applying the vti mark). Then only the packet can enter
> the vti interface, in which a second SPD lookup is done, in the vti
> interface SPD (i.e. after applying the vti mark). Of course if the
> global SPD lookup returned a tunnel mode policy, then the packet may
> finally not enter the vti interface, because a new route is looked up
> after the IPsec encapsulation.
>
> My understanding of the vti interface interest is enabling to use
> routing (possibly dynamic routes) *instead* of complex security
> policies. And in this use case I expect that entering a vti interface
> will *override* the global policies (in the same manner as socket
> policies override the global policies).
>
> Otherwise, if we want to mix global and vti policies on the same
> machine, then we must carefully define global policies that do not match
> traffic destined to vti interfaces.
>
> Note that setting the NOXFRM flag on the vti interface does not work
> around this issue, it disables both the global and vti SPD lookup and
> the traffic is finally dropped.
I finally found a way of bypassing the global SPD lookup, by explicitly
adding a global policy of higher priority than other global policies:
# bypass outbound SPD lookup if packet is destined to vti1
ip xfrm policy add dir out dev vti1 mark 0 priority 0 allow
>> Changes from v1:
>>
>> - Rebased to current net-next.
>> - Fix a rcu lockdep complaint in xfrm protocol
>> registration/deregistration.
>> - Fix usage of a ipv4 specific callback handler in generic code.
>> - Use skb_scrub_packet() to clear the skb in vti_rcv(), suggested by
>> Nicolas Dichtel.
>> - Add support for IPCOMP.
>> - Support inter address family tunneling.
>>
>> I'd take this into the ipsec-next tree after some testing if noone
>> has further suggestions or objections.
>>
>> I have the ipv6 side ready too, this will be a separate patchset.
>> The ipv6 patchset has dependencies against the ipv4 patchset, so I
>> hold it back until we have got the ipv4 side merged.
>>
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH RFC v2 0/13] vti4: prepare namespace and interfamily support.
2014-01-07 16:11 ` [PATCH RFC v2 0/13] vti4: prepare namespace and interfamily support Christophe Gouault
2014-01-07 19:45 ` Christophe Gouault
@ 2014-01-14 7:51 ` Steffen Klassert
1 sibling, 0 replies; 19+ messages in thread
From: Steffen Klassert @ 2014-01-14 7:51 UTC (permalink / raw)
To: Christophe Gouault; +Cc: netdev, Saurabh Mohan
On Tue, Jan 07, 2014 at 05:11:00PM +0100, Christophe Gouault wrote:
>
> Sorry for my late comments, I had to delay my tests due to Christmas and
> New Year's celebrations.
Sorry for the delay on my side, I had to setup a testcase
for vti with namespaces first.
>
> I have a few comments about your proposed patches:
>
> In input, the vti tunnel processing does not follow the usual tunnel
> processing. Conventionally, the packets are first decapsulated, then
> only the skbuff interface is changed to the tunnel interface. In the vti
> code, the interface is changed before IPsec decryption, hence before
> decapsulation.
>
> It results in a configuration asymmetry when we later support cross
> netns: the outer SAs and SPs must be defined in the outer netns, while
> the inner SAs and SPs must be defined in the inner netns.
You are absolutely right here. I'll change this to do the namespace
transition after the decapsulation in the vti_rcv_cb() callback.
Then in and outbound states/policies must be defined in the outer
namespace. I'll send another RFC version of that patchset during the
next days.
Thanks for pointing this out!
^ permalink raw reply [flat|nested] 19+ messages in thread
end of thread, other threads:[~2014-01-14 7:51 UTC | newest]
Thread overview: 19+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2013-12-16 9:18 [PATCH RFC v2 0/13] vti4: prepare namespace and interfamily support Steffen Klassert
2013-12-16 9:19 ` [PATCH RFC v2 01/13] xfrm4: Add IPsec protocol multiplexer Steffen Klassert
2013-12-16 9:19 ` [PATCH RFC v2 02/13] esp4: Use the IPsec protocol multiplexer API Steffen Klassert
2013-12-16 9:20 ` [PATCH RFC v2 03/13] esp4: Export esp4_err Steffen Klassert
2013-12-16 9:21 ` [PATCH RFC v2 04/13] ah4: Use the IPsec protocol multiplexer API Steffen Klassert
2013-12-16 9:21 ` [PATCH RFC v2 05/13] ah4: Export ah4_err Steffen Klassert
2013-12-16 9:22 ` [PATCH RFC v2 06/13] ipcomp4: Use the IPsec protocol multiplexer API Steffen Klassert
2013-12-16 9:23 ` [PATCH RFC v2 07/13] ipcomp4: Export ipcomp4_err Steffen Klassert
2013-12-16 9:23 ` [PATCH RFC v2 08/13] xfrm: Add xfrm_tunnel_skb_cb to the skb common buffer Steffen Klassert
2013-12-16 12:54 ` Nicolas Dichtel
2013-12-16 13:02 ` Steffen Klassert
2013-12-16 9:24 ` [PATCH RFC v2 09/13] ip_tunnel: Make vti work with i_key set Steffen Klassert
2013-12-16 9:25 ` [PATCH RFC v2 10/13] vti: Update the ipv4 side to use it's own receive hook Steffen Klassert
2013-12-16 9:26 ` [PATCH RFC v2 11/13] xfrm4: Remove xfrm_tunnel_notifier Steffen Klassert
2013-12-16 9:27 ` [PATCH RFC v2 12/13] vti4: Use the on xfrm_lookup returned dst_entry directly Steffen Klassert
2013-12-16 9:28 ` [PATCH RFC v2 13/13] vti4: Support inter address family tunneling Steffen Klassert
2014-01-07 16:11 ` [PATCH RFC v2 0/13] vti4: prepare namespace and interfamily support Christophe Gouault
2014-01-07 19:45 ` Christophe Gouault
2014-01-14 7:51 ` Steffen Klassert
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).