aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/net/xfrm.h10
-rw-r--r--net/ipv4/ip_vti.c67
-rw-r--r--net/ipv4/xfrm4_mode_tunnel.c16
3 files changed, 17 insertions, 76 deletions
diff --git a/include/net/xfrm.h b/include/net/xfrm.h
index 89d3d8ae204e..c7afa6e476c8 100644
--- a/include/net/xfrm.h
+++ b/include/net/xfrm.h
@@ -1352,6 +1352,12 @@ struct xfrm_tunnel {
1352 int priority; 1352 int priority;
1353}; 1353};
1354 1354
1355struct xfrm_tunnel_notifier {
1356 int (*handler)(struct sk_buff *skb);
1357 struct xfrm_tunnel_notifier __rcu *next;
1358 int priority;
1359};
1360
1355struct xfrm6_tunnel { 1361struct xfrm6_tunnel {
1356 int (*handler)(struct sk_buff *skb); 1362 int (*handler)(struct sk_buff *skb);
1357 int (*err_handler)(struct sk_buff *skb, struct inet6_skb_parm *opt, 1363 int (*err_handler)(struct sk_buff *skb, struct inet6_skb_parm *opt,
@@ -1495,8 +1501,8 @@ extern int xfrm4_output(struct sk_buff *skb);
1495extern int xfrm4_output_finish(struct sk_buff *skb); 1501extern int xfrm4_output_finish(struct sk_buff *skb);
1496extern int xfrm4_tunnel_register(struct xfrm_tunnel *handler, unsigned short family); 1502extern int xfrm4_tunnel_register(struct xfrm_tunnel *handler, unsigned short family);
1497extern int xfrm4_tunnel_deregister(struct xfrm_tunnel *handler, unsigned short family); 1503extern int xfrm4_tunnel_deregister(struct xfrm_tunnel *handler, unsigned short family);
1498extern int xfrm4_mode_tunnel_input_register(struct xfrm_tunnel *handler); 1504extern int xfrm4_mode_tunnel_input_register(struct xfrm_tunnel_notifier *handler);
1499extern int xfrm4_mode_tunnel_input_deregister(struct xfrm_tunnel *handler); 1505extern int xfrm4_mode_tunnel_input_deregister(struct xfrm_tunnel_notifier *handler);
1500extern int xfrm6_extract_header(struct sk_buff *skb); 1506extern int xfrm6_extract_header(struct sk_buff *skb);
1501extern int xfrm6_extract_input(struct xfrm_state *x, struct sk_buff *skb); 1507extern int xfrm6_extract_input(struct xfrm_state *x, struct sk_buff *skb);
1502extern int xfrm6_rcv_spi(struct sk_buff *skb, int nexthdr, __be32 spi); 1508extern int xfrm6_rcv_spi(struct sk_buff *skb, int nexthdr, __be32 spi);
diff --git a/net/ipv4/ip_vti.c b/net/ipv4/ip_vti.c
index e805e7b3030e..91f69bc883fe 100644
--- a/net/ipv4/ip_vti.c
+++ b/net/ipv4/ip_vti.c
@@ -49,70 +49,6 @@ static struct rtnl_link_ops vti_link_ops __read_mostly;
49static int vti_net_id __read_mostly; 49static int vti_net_id __read_mostly;
50static int vti_tunnel_init(struct net_device *dev); 50static int vti_tunnel_init(struct net_device *dev);
51 51
52static int vti_err(struct sk_buff *skb, u32 info)
53{
54
55 /* All the routers (except for Linux) return only
56 * 8 bytes of packet payload. It means, that precise relaying of
57 * ICMP in the real Internet is absolutely infeasible.
58 */
59 struct net *net = dev_net(skb->dev);
60 struct ip_tunnel_net *itn = net_generic(net, vti_net_id);
61 struct iphdr *iph = (struct iphdr *)skb->data;
62 const int type = icmp_hdr(skb)->type;
63 const int code = icmp_hdr(skb)->code;
64 struct ip_tunnel *t;
65 int err;
66
67 switch (type) {
68 default:
69 case ICMP_PARAMETERPROB:
70 return 0;
71
72 case ICMP_DEST_UNREACH:
73 switch (code) {
74 case ICMP_SR_FAILED:
75 case ICMP_PORT_UNREACH:
76 /* Impossible event. */
77 return 0;
78 default:
79 /* All others are translated to HOST_UNREACH. */
80 break;
81 }
82 break;
83 case ICMP_TIME_EXCEEDED:
84 if (code != ICMP_EXC_TTL)
85 return 0;
86 break;
87 }
88
89 err = -ENOENT;
90
91 t = ip_tunnel_lookup(itn, skb->dev->ifindex, TUNNEL_NO_KEY,
92 iph->daddr, iph->saddr, 0);
93 if (t == NULL)
94 goto out;
95
96 if (type == ICMP_DEST_UNREACH && code == ICMP_FRAG_NEEDED) {
97 ipv4_update_pmtu(skb, dev_net(skb->dev), info,
98 t->parms.link, 0, IPPROTO_IPIP, 0);
99 err = 0;
100 goto out;
101 }
102
103 err = 0;
104 if (t->parms.iph.ttl == 0 && type == ICMP_TIME_EXCEEDED)
105 goto out;
106
107 if (time_before(jiffies, t->err_time + IPTUNNEL_ERR_TIMEO))
108 t->err_count++;
109 else
110 t->err_count = 1;
111 t->err_time = jiffies;
112out:
113 return err;
114}
115
116/* We dont digest the packet therefore let the packet pass */ 52/* We dont digest the packet therefore let the packet pass */
117static int vti_rcv(struct sk_buff *skb) 53static int vti_rcv(struct sk_buff *skb)
118{ 54{
@@ -296,9 +232,8 @@ static void __net_init vti_fb_tunnel_init(struct net_device *dev)
296 iph->ihl = 5; 232 iph->ihl = 5;
297} 233}
298 234
299static struct xfrm_tunnel vti_handler __read_mostly = { 235static struct xfrm_tunnel_notifier vti_handler __read_mostly = {
300 .handler = vti_rcv, 236 .handler = vti_rcv,
301 .err_handler = vti_err,
302 .priority = 1, 237 .priority = 1,
303}; 238};
304 239
diff --git a/net/ipv4/xfrm4_mode_tunnel.c b/net/ipv4/xfrm4_mode_tunnel.c
index eb1dd4d643f2..b82cde1ea1b6 100644
--- a/net/ipv4/xfrm4_mode_tunnel.c
+++ b/net/ipv4/xfrm4_mode_tunnel.c
@@ -16,13 +16,13 @@
16#include <net/xfrm.h> 16#include <net/xfrm.h>
17 17
18/* Informational hook. The decap is still done here. */ 18/* Informational hook. The decap is still done here. */
19static struct xfrm_tunnel __rcu *rcv_notify_handlers __read_mostly; 19static struct xfrm_tunnel_notifier __rcu *rcv_notify_handlers __read_mostly;
20static DEFINE_MUTEX(xfrm4_mode_tunnel_input_mutex); 20static DEFINE_MUTEX(xfrm4_mode_tunnel_input_mutex);
21 21
22int xfrm4_mode_tunnel_input_register(struct xfrm_tunnel *handler) 22int xfrm4_mode_tunnel_input_register(struct xfrm_tunnel_notifier *handler)
23{ 23{
24 struct xfrm_tunnel __rcu **pprev; 24 struct xfrm_tunnel_notifier __rcu **pprev;
25 struct xfrm_tunnel *t; 25 struct xfrm_tunnel_notifier *t;
26 int ret = -EEXIST; 26 int ret = -EEXIST;
27 int priority = handler->priority; 27 int priority = handler->priority;
28 28
@@ -50,10 +50,10 @@ err:
50} 50}
51EXPORT_SYMBOL_GPL(xfrm4_mode_tunnel_input_register); 51EXPORT_SYMBOL_GPL(xfrm4_mode_tunnel_input_register);
52 52
53int xfrm4_mode_tunnel_input_deregister(struct xfrm_tunnel *handler) 53int xfrm4_mode_tunnel_input_deregister(struct xfrm_tunnel_notifier *handler)
54{ 54{
55 struct xfrm_tunnel __rcu **pprev; 55 struct xfrm_tunnel_notifier __rcu **pprev;
56 struct xfrm_tunnel *t; 56 struct xfrm_tunnel_notifier *t;
57 int ret = -ENOENT; 57 int ret = -ENOENT;
58 58
59 mutex_lock(&xfrm4_mode_tunnel_input_mutex); 59 mutex_lock(&xfrm4_mode_tunnel_input_mutex);
@@ -134,7 +134,7 @@ static int xfrm4_mode_tunnel_output(struct xfrm_state *x, struct sk_buff *skb)
134 134
135static int xfrm4_mode_tunnel_input(struct xfrm_state *x, struct sk_buff *skb) 135static int xfrm4_mode_tunnel_input(struct xfrm_state *x, struct sk_buff *skb)
136{ 136{
137 struct xfrm_tunnel *handler; 137 struct xfrm_tunnel_notifier *handler;
138 int err = -EINVAL; 138 int err = -EINVAL;
139 139
140 if (XFRM_MODE_SKB_CB(skb)->protocol != IPPROTO_IPIP) 140 if (XFRM_MODE_SKB_CB(skb)->protocol != IPPROTO_IPIP)