diff options
-rw-r--r-- | include/net/xfrm.h | 10 | ||||
-rw-r--r-- | net/ipv4/ip_vti.c | 67 | ||||
-rw-r--r-- | net/ipv4/xfrm4_mode_tunnel.c | 16 |
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 | ||
1355 | struct xfrm_tunnel_notifier { | ||
1356 | int (*handler)(struct sk_buff *skb); | ||
1357 | struct xfrm_tunnel_notifier __rcu *next; | ||
1358 | int priority; | ||
1359 | }; | ||
1360 | |||
1355 | struct xfrm6_tunnel { | 1361 | struct 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); | |||
1495 | extern int xfrm4_output_finish(struct sk_buff *skb); | 1501 | extern int xfrm4_output_finish(struct sk_buff *skb); |
1496 | extern int xfrm4_tunnel_register(struct xfrm_tunnel *handler, unsigned short family); | 1502 | extern int xfrm4_tunnel_register(struct xfrm_tunnel *handler, unsigned short family); |
1497 | extern int xfrm4_tunnel_deregister(struct xfrm_tunnel *handler, unsigned short family); | 1503 | extern int xfrm4_tunnel_deregister(struct xfrm_tunnel *handler, unsigned short family); |
1498 | extern int xfrm4_mode_tunnel_input_register(struct xfrm_tunnel *handler); | 1504 | extern int xfrm4_mode_tunnel_input_register(struct xfrm_tunnel_notifier *handler); |
1499 | extern int xfrm4_mode_tunnel_input_deregister(struct xfrm_tunnel *handler); | 1505 | extern int xfrm4_mode_tunnel_input_deregister(struct xfrm_tunnel_notifier *handler); |
1500 | extern int xfrm6_extract_header(struct sk_buff *skb); | 1506 | extern int xfrm6_extract_header(struct sk_buff *skb); |
1501 | extern int xfrm6_extract_input(struct xfrm_state *x, struct sk_buff *skb); | 1507 | extern int xfrm6_extract_input(struct xfrm_state *x, struct sk_buff *skb); |
1502 | extern int xfrm6_rcv_spi(struct sk_buff *skb, int nexthdr, __be32 spi); | 1508 | extern 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; | |||
49 | static int vti_net_id __read_mostly; | 49 | static int vti_net_id __read_mostly; |
50 | static int vti_tunnel_init(struct net_device *dev); | 50 | static int vti_tunnel_init(struct net_device *dev); |
51 | 51 | ||
52 | static 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; | ||
112 | out: | ||
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 */ |
117 | static int vti_rcv(struct sk_buff *skb) | 53 | static 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 | ||
299 | static struct xfrm_tunnel vti_handler __read_mostly = { | 235 | static 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. */ |
19 | static struct xfrm_tunnel __rcu *rcv_notify_handlers __read_mostly; | 19 | static struct xfrm_tunnel_notifier __rcu *rcv_notify_handlers __read_mostly; |
20 | static DEFINE_MUTEX(xfrm4_mode_tunnel_input_mutex); | 20 | static DEFINE_MUTEX(xfrm4_mode_tunnel_input_mutex); |
21 | 21 | ||
22 | int xfrm4_mode_tunnel_input_register(struct xfrm_tunnel *handler) | 22 | int 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 | } |
51 | EXPORT_SYMBOL_GPL(xfrm4_mode_tunnel_input_register); | 51 | EXPORT_SYMBOL_GPL(xfrm4_mode_tunnel_input_register); |
52 | 52 | ||
53 | int xfrm4_mode_tunnel_input_deregister(struct xfrm_tunnel *handler) | 53 | int 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 | ||
135 | static int xfrm4_mode_tunnel_input(struct xfrm_state *x, struct sk_buff *skb) | 135 | static 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) |