diff options
| -rw-r--r-- | net/ipv4/ipip.c | 59 |
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 | ||
| 129 | static int ipip_err(struct sk_buff *skb, u32 info) | 129 | static 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 | ||
