aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4/ipip.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv4/ipip.c')
-rw-r--r--net/ipv4/ipip.c59
1 files changed, 42 insertions, 17 deletions
diff --git a/net/ipv4/ipip.c b/net/ipv4/ipip.c
index fb1ad22b5e29..cdd627355ed1 100644
--- a/net/ipv4/ipip.c
+++ b/net/ipv4/ipip.c
@@ -128,43 +128,68 @@ static struct rtnl_link_ops ipip_link_ops __read_mostly;
128 128
129static int ipip_err(struct sk_buff *skb, u32 info) 129static int ipip_err(struct sk_buff *skb, u32 info)
130{ 130{
131 131 /* All the routers (except for Linux) return only
132/* All the routers (except for Linux) return only 132 * 8 bytes of packet payload. It means, that precise relaying of
133 8 bytes of packet payload. It means, that precise relaying of 133 * ICMP in the real Internet is absolutely infeasible.
134 ICMP in the real Internet is absolutely infeasible. 134 */
135 */
136 struct net *net = dev_net(skb->dev); 135 struct net *net = dev_net(skb->dev);
137 struct ip_tunnel_net *itn = net_generic(net, ipip_net_id); 136 struct ip_tunnel_net *itn = net_generic(net, ipip_net_id);
138 const struct iphdr *iph = (const struct iphdr *)skb->data; 137 const struct iphdr *iph = (const struct iphdr *)skb->data;
139 struct ip_tunnel *t;
140 int err;
141 const int type = icmp_hdr(skb)->type; 138 const int type = icmp_hdr(skb)->type;
142 const int code = icmp_hdr(skb)->code; 139 const int code = icmp_hdr(skb)->code;
140 struct ip_tunnel *t;
141 int err = 0;
142
143 switch (type) {
144 case ICMP_DEST_UNREACH:
145 switch (code) {
146 case ICMP_SR_FAILED:
147 /* Impossible event. */
148 goto out;
149 default:
150 /* All others are translated to HOST_UNREACH.
151 * rfc2003 contains "deep thoughts" about NET_UNREACH,
152 * I believe they are just ether pollution. --ANK
153 */
154 break;
155 }
156 break;
157
158 case ICMP_TIME_EXCEEDED:
159 if (code != ICMP_EXC_TTL)
160 goto out;
161 break;
162
163 case ICMP_REDIRECT:
164 break;
165
166 default:
167 goto out;
168 }
143 169
144 err = -ENOENT;
145 t = ip_tunnel_lookup(itn, skb->dev->ifindex, TUNNEL_NO_KEY, 170 t = ip_tunnel_lookup(itn, skb->dev->ifindex, TUNNEL_NO_KEY,
146 iph->daddr, iph->saddr, 0); 171 iph->daddr, iph->saddr, 0);
147 if (!t) 172 if (!t) {
173 err = -ENOENT;
148 goto out; 174 goto out;
175 }
149 176
150 if (type == ICMP_DEST_UNREACH && code == ICMP_FRAG_NEEDED) { 177 if (type == ICMP_DEST_UNREACH && code == ICMP_FRAG_NEEDED) {
151 ipv4_update_pmtu(skb, dev_net(skb->dev), info, 178 ipv4_update_pmtu(skb, net, info, t->parms.link, 0,
152 t->parms.link, 0, iph->protocol, 0); 179 iph->protocol, 0);
153 err = 0;
154 goto out; 180 goto out;
155 } 181 }
156 182
157 if (type == ICMP_REDIRECT) { 183 if (type == ICMP_REDIRECT) {
158 ipv4_redirect(skb, dev_net(skb->dev), t->parms.link, 0, 184 ipv4_redirect(skb, net, t->parms.link, 0, iph->protocol, 0);
159 iph->protocol, 0);
160 err = 0;
161 goto out; 185 goto out;
162 } 186 }
163 187
164 if (t->parms.iph.daddr == 0) 188 if (t->parms.iph.daddr == 0) {
189 err = -ENOENT;
165 goto out; 190 goto out;
191 }
166 192
167 err = 0;
168 if (t->parms.iph.ttl == 0 && type == ICMP_TIME_EXCEEDED) 193 if (t->parms.iph.ttl == 0 && type == ICMP_TIME_EXCEEDED)
169 goto out; 194 goto out;
170 195