Skip to content

Commit

Permalink
[INET]: Introduce tunnel4/tunnel6
Browse files Browse the repository at this point in the history
Basically this patch moves the generic tunnel protocol stuff out of
xfrm4_tunnel/xfrm6_tunnel and moves it into the new files of tunnel4.c
and tunnel6 respectively.

The reason for this is that the problem that Hugo uncovered is only
the tip of the iceberg.  The real problem is that when we removed the
dependency of ipip on xfrm4_tunnel we didn't really consider the module
case at all.

For instance, as it is it's possible to build both ipip and xfrm4_tunnel
as modules and if the latter is loaded then ipip simply won't load.

After considering the alternatives I've decided that the best way out of
this is to restore the dependency of ipip on the non-xfrm-specific part
of xfrm4_tunnel.  This is acceptable IMHO because the intention of the
removal was really to be able to use ipip without the xfrm subsystem.
This is still preserved by this patch.

So now both ipip/xfrm4_tunnel depend on the new tunnel4.c which handles
the arbitration between the two.  The order of processing is determined
by a simple integer which ensures that ipip gets processed before
xfrm4_tunnel.

The situation for ICMP handling is a little bit more complicated since
we may not have enough information to determine who it's for.  It's not
a big deal at the moment since the xfrm ICMP handlers are basically
no-ops.  In future we can deal with this when we look at ICMP caching
in general.

The user-visible change to this is the removal of the TUNNEL Kconfig
prompts.  This makes sense because it can only be used through IPCOMP
as it stands.

The addition of the new modules shouldn't introduce any problems since
module dependency will cause them to be loaded.

Oh and I also turned some unnecessary pskb's in IPv6 related to this
patch to skb's.

Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Herbert Xu authored and David S. Miller committed Mar 29, 2006
1 parent f0088a5 commit d2acc34
Show file tree
Hide file tree
Showing 12 changed files with 344 additions and 247 deletions.
16 changes: 11 additions & 5 deletions include/net/xfrm.h
Original file line number Diff line number Diff line change
Expand Up @@ -864,13 +864,19 @@ struct xfrm_algo_desc {
/* XFRM tunnel handlers. */
struct xfrm_tunnel {
int (*handler)(struct sk_buff *skb);
void (*err_handler)(struct sk_buff *skb, __u32 info);
int (*err_handler)(struct sk_buff *skb, __u32 info);

struct xfrm_tunnel *next;
int priority;
};

struct xfrm6_tunnel {
int (*handler)(struct sk_buff **pskb);
void (*err_handler)(struct sk_buff *skb, struct inet6_skb_parm *opt,
int type, int code, int offset, __u32 info);
int (*handler)(struct sk_buff *skb);
int (*err_handler)(struct sk_buff *skb, struct inet6_skb_parm *opt,
int type, int code, int offset, __u32 info);

struct xfrm6_tunnel *next;
int priority;
};

extern void xfrm_init(void);
Expand Down Expand Up @@ -906,7 +912,7 @@ extern int xfrm4_rcv(struct sk_buff *skb);
extern int xfrm4_output(struct sk_buff *skb);
extern int xfrm4_tunnel_register(struct xfrm_tunnel *handler);
extern int xfrm4_tunnel_deregister(struct xfrm_tunnel *handler);
extern int xfrm6_rcv_spi(struct sk_buff **pskb, u32 spi);
extern int xfrm6_rcv_spi(struct sk_buff *skb, u32 spi);
extern int xfrm6_rcv(struct sk_buff **pskb);
extern int xfrm6_tunnel_register(struct xfrm6_tunnel *handler);
extern int xfrm6_tunnel_deregister(struct xfrm6_tunnel *handler);
Expand Down
17 changes: 9 additions & 8 deletions net/ipv4/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,7 @@ config IP_PNP_RARP
# bool ' IP: ARP support' CONFIG_IP_PNP_ARP
config NET_IPIP
tristate "IP: tunneling"
select INET_TUNNEL
---help---
Tunneling means encapsulating data of one protocol type within
another protocol and sending it over a channel that understands the
Expand Down Expand Up @@ -395,7 +396,7 @@ config INET_ESP
config INET_IPCOMP
tristate "IP: IPComp transformation"
select XFRM
select INET_TUNNEL
select INET_XFRM_TUNNEL
select CRYPTO
select CRYPTO_DEFLATE
---help---
Expand All @@ -404,14 +405,14 @@ config INET_IPCOMP

If unsure, say Y.

config INET_XFRM_TUNNEL
tristate
select INET_TUNNEL
default n

config INET_TUNNEL
tristate "IP: tunnel transformation"
select XFRM
---help---
Support for generic IP tunnel transformation, which is required by
the IP tunneling module as well as tunnel mode IPComp.

If unsure, say Y.
tristate
default n

config INET_DIAG
tristate "INET: socket monitoring interface"
Expand Down
3 changes: 2 additions & 1 deletion net/ipv4/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@ obj-$(CONFIG_SYN_COOKIES) += syncookies.o
obj-$(CONFIG_INET_AH) += ah4.o
obj-$(CONFIG_INET_ESP) += esp4.o
obj-$(CONFIG_INET_IPCOMP) += ipcomp.o
obj-$(CONFIG_INET_TUNNEL) += xfrm4_tunnel.o
obj-$(CONFIG_INET_XFRM_TUNNEL) += xfrm4_tunnel.o
obj-$(CONFIG_INET_TUNNEL) += tunnel4.o
obj-$(CONFIG_IP_PNP) += ipconfig.o
obj-$(CONFIG_IP_ROUTE_MULTIPATH_RR) += multipath_rr.o
obj-$(CONFIG_IP_ROUTE_MULTIPATH_RANDOM) += multipath_random.o
Expand Down
79 changes: 28 additions & 51 deletions net/ipv4/ipip.c
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,6 @@
#include <net/sock.h>
#include <net/ip.h>
#include <net/icmp.h>
#include <net/protocol.h>
#include <net/ipip.h>
#include <net/inet_ecn.h>
#include <net/xfrm.h>
Expand Down Expand Up @@ -274,7 +273,7 @@ static void ipip_tunnel_uninit(struct net_device *dev)
dev_put(dev);
}

static void ipip_err(struct sk_buff *skb, u32 info)
static int ipip_err(struct sk_buff *skb, u32 info)
{
#ifndef I_WISH_WORLD_WERE_PERFECT

Expand All @@ -286,21 +285,22 @@ static void ipip_err(struct sk_buff *skb, u32 info)
int type = skb->h.icmph->type;
int code = skb->h.icmph->code;
struct ip_tunnel *t;
int err;

switch (type) {
default:
case ICMP_PARAMETERPROB:
return;
return 0;

case ICMP_DEST_UNREACH:
switch (code) {
case ICMP_SR_FAILED:
case ICMP_PORT_UNREACH:
/* Impossible event. */
return;
return 0;
case ICMP_FRAG_NEEDED:
/* Soft state for pmtu is maintained by IP core. */
return;
return 0;
default:
/* All others are translated to HOST_UNREACH.
rfc2003 contains "deep thoughts" about NET_UNREACH,
Expand All @@ -311,14 +311,18 @@ static void ipip_err(struct sk_buff *skb, u32 info)
break;
case ICMP_TIME_EXCEEDED:
if (code != ICMP_EXC_TTL)
return;
return 0;
break;
}

err = -ENOENT;

read_lock(&ipip_lock);
t = ipip_tunnel_lookup(iph->daddr, iph->saddr);
if (t == NULL || t->parms.iph.daddr == 0)
goto out;

err = 0;
if (t->parms.iph.ttl == 0 && type == ICMP_TIME_EXCEEDED)
goto out;

Expand All @@ -329,7 +333,7 @@ static void ipip_err(struct sk_buff *skb, u32 info)
t->err_time = jiffies;
out:
read_unlock(&ipip_lock);
return;
return err;
#else
struct iphdr *iph = (struct iphdr*)dp;
int hlen = iph->ihl<<2;
Expand All @@ -344,15 +348,15 @@ static void ipip_err(struct sk_buff *skb, u32 info)
struct rtable *rt;

if (len < hlen + sizeof(struct iphdr))
return;
return 0;
eiph = (struct iphdr*)(dp + hlen);

switch (type) {
default:
return;
return 0;
case ICMP_PARAMETERPROB:
if (skb->h.icmph->un.gateway < hlen)
return;
return 0;

/* So... This guy found something strange INSIDE encapsulated
packet. Well, he is fool, but what can we do ?
Expand All @@ -366,16 +370,16 @@ static void ipip_err(struct sk_buff *skb, u32 info)
case ICMP_SR_FAILED:
case ICMP_PORT_UNREACH:
/* Impossible event. */
return;
return 0;
case ICMP_FRAG_NEEDED:
/* And it is the only really necessary thing :-) */
rel_info = ntohs(skb->h.icmph->un.frag.mtu);
if (rel_info < hlen+68)
return;
return 0;
rel_info -= hlen;
/* BSD 4.2 MORE DOES NOT EXIST IN NATURE. */
if (rel_info > ntohs(eiph->tot_len))
return;
return 0;
break;
default:
/* All others are translated to HOST_UNREACH.
Expand All @@ -389,14 +393,14 @@ static void ipip_err(struct sk_buff *skb, u32 info)
break;
case ICMP_TIME_EXCEEDED:
if (code != ICMP_EXC_TTL)
return;
return 0;
break;
}

/* Prepare fake skb to feed it to icmp_send */
skb2 = skb_clone(skb, GFP_ATOMIC);
if (skb2 == NULL)
return;
return 0;
dst_release(skb2->dst);
skb2->dst = NULL;
skb_pull(skb2, skb->data - (u8*)eiph);
Expand All @@ -409,7 +413,7 @@ static void ipip_err(struct sk_buff *skb, u32 info)
fl.proto = IPPROTO_IPIP;
if (ip_route_output_key(&rt, &key)) {
kfree_skb(skb2);
return;
return 0;
}
skb2->dev = rt->u.dst.dev;

Expand All @@ -424,22 +428,22 @@ static void ipip_err(struct sk_buff *skb, u32 info)
rt->u.dst.dev->type != ARPHRD_TUNNEL) {
ip_rt_put(rt);
kfree_skb(skb2);
return;
return 0;
}
} else {
ip_rt_put(rt);
if (ip_route_input(skb2, eiph->daddr, eiph->saddr, eiph->tos, skb2->dev) ||
skb2->dst->dev->type != ARPHRD_TUNNEL) {
kfree_skb(skb2);
return;
return 0;
}
}

/* change mtu on this route */
if (type == ICMP_DEST_UNREACH && code == ICMP_FRAG_NEEDED) {
if (rel_info > dst_mtu(skb2->dst)) {
kfree_skb(skb2);
return;
return 0;
}
skb2->dst->ops->update_pmtu(skb2->dst, rel_info);
rel_info = htonl(rel_info);
Expand All @@ -453,7 +457,7 @@ static void ipip_err(struct sk_buff *skb, u32 info)

icmp_send(skb2, rel_type, rel_code, rel_info);
kfree_skb(skb2);
return;
return 0;
#endif
}

Expand Down Expand Up @@ -855,39 +859,12 @@ static int __init ipip_fb_tunnel_init(struct net_device *dev)
return 0;
}

#ifdef CONFIG_INET_TUNNEL
static struct xfrm_tunnel ipip_handler = {
.handler = ipip_rcv,
.err_handler = ipip_err,
.priority = 1,
};

static inline int ipip_register(void)
{
return xfrm4_tunnel_register(&ipip_handler);
}

static inline int ipip_unregister(void)
{
return xfrm4_tunnel_deregister(&ipip_handler);
}
#else
static struct net_protocol ipip_protocol = {
.handler = ipip_rcv,
.err_handler = ipip_err,
.no_policy = 1,
};

static inline int ipip_register(void)
{
return inet_add_protocol(&ipip_protocol, IPPROTO_IPIP);
}

static inline int ipip_unregister(void)
{
return inet_del_protocol(&ipip_protocol, IPPROTO_IPIP);
}
#endif

static char banner[] __initdata =
KERN_INFO "IPv4 over IPv4 tunneling driver\n";

Expand All @@ -897,7 +874,7 @@ static int __init ipip_init(void)

printk(banner);

if (ipip_register() < 0) {
if (xfrm4_tunnel_register(&ipip_handler)) {
printk(KERN_INFO "ipip init: can't register tunnel\n");
return -EAGAIN;
}
Expand All @@ -919,7 +896,7 @@ static int __init ipip_init(void)
err2:
free_netdev(ipip_fb_tunnel_dev);
err1:
ipip_unregister();
xfrm4_tunnel_deregister(&ipip_handler);
goto out;
}

Expand All @@ -939,7 +916,7 @@ static void __exit ipip_destroy_tunnels(void)

static void __exit ipip_fini(void)
{
if (ipip_unregister() < 0)
if (xfrm4_tunnel_deregister(&ipip_handler))
printk(KERN_INFO "ipip close: can't deregister tunnel\n");

rtnl_lock();
Expand Down
Loading

0 comments on commit d2acc34

Please sign in to comment.