aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6/sit.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv6/sit.c')
-rw-r--r--net/ipv6/sit.c133
1 files changed, 25 insertions, 108 deletions
diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c
index 5a6fab95569f..32e871a6c25a 100644
--- a/net/ipv6/sit.c
+++ b/net/ipv6/sit.c
@@ -222,15 +222,18 @@ __ipip6_tunnel_locate_prl(struct ip_tunnel *t, __be32 addr)
222 222
223} 223}
224 224
225static int ipip6_tunnel_get_prl(struct ip_tunnel *t, struct ip_tunnel_prl *a) 225static int ipip6_tunnel_get_prl(struct ip_tunnel *t,
226 struct ip_tunnel_prl __user *a)
226{ 227{
227 struct ip_tunnel_prl *kp; 228 struct ip_tunnel_prl kprl, *kp;
228 struct ip_tunnel_prl_entry *prl; 229 struct ip_tunnel_prl_entry *prl;
229 unsigned int cmax, c = 0, ca, len; 230 unsigned int cmax, c = 0, ca, len;
230 int ret = 0; 231 int ret = 0;
231 232
232 cmax = a->datalen / sizeof(*a); 233 if (copy_from_user(&kprl, a, sizeof(kprl)))
233 if (cmax > 1 && a->addr != htonl(INADDR_ANY)) 234 return -EFAULT;
235 cmax = kprl.datalen / sizeof(kprl);
236 if (cmax > 1 && kprl.addr != htonl(INADDR_ANY))
234 cmax = 1; 237 cmax = 1;
235 238
236 /* For simple GET or for root users, 239 /* For simple GET or for root users,
@@ -261,26 +264,25 @@ static int ipip6_tunnel_get_prl(struct ip_tunnel *t, struct ip_tunnel_prl *a)
261 for (prl = t->prl; prl; prl = prl->next) { 264 for (prl = t->prl; prl; prl = prl->next) {
262 if (c > cmax) 265 if (c > cmax)
263 break; 266 break;
264 if (a->addr != htonl(INADDR_ANY) && prl->addr != a->addr) 267 if (kprl.addr != htonl(INADDR_ANY) && prl->addr != kprl.addr)
265 continue; 268 continue;
266 kp[c].addr = prl->addr; 269 kp[c].addr = prl->addr;
267 kp[c].flags = prl->flags; 270 kp[c].flags = prl->flags;
268 c++; 271 c++;
269 if (a->addr != htonl(INADDR_ANY)) 272 if (kprl.addr != htonl(INADDR_ANY))
270 break; 273 break;
271 } 274 }
272out: 275out:
273 read_unlock(&ipip6_lock); 276 read_unlock(&ipip6_lock);
274 277
275 len = sizeof(*kp) * c; 278 len = sizeof(*kp) * c;
276 ret = len ? copy_to_user(a->data, kp, len) : 0; 279 ret = 0;
280 if ((len && copy_to_user(a + 1, kp, len)) || put_user(len, &a->datalen))
281 ret = -EFAULT;
277 282
278 kfree(kp); 283 kfree(kp);
279 if (ret)
280 return -EFAULT;
281 284
282 a->datalen = len; 285 return ret;
283 return 0;
284} 286}
285 287
286static int 288static int
@@ -403,9 +405,8 @@ static void ipip6_tunnel_uninit(struct net_device *dev)
403 405
404static int ipip6_err(struct sk_buff *skb, u32 info) 406static int ipip6_err(struct sk_buff *skb, u32 info)
405{ 407{
406#ifndef I_WISH_WORLD_WERE_PERFECT
407 408
408/* It is not :-( All the routers (except for Linux) return only 409/* All the routers (except for Linux) return only
409 8 bytes of packet payload. It means, that precise relaying of 410 8 bytes of packet payload. It means, that precise relaying of
410 ICMP in the real Internet is absolutely infeasible. 411 ICMP in the real Internet is absolutely infeasible.
411 */ 412 */
@@ -462,92 +463,6 @@ static int ipip6_err(struct sk_buff *skb, u32 info)
462out: 463out:
463 read_unlock(&ipip6_lock); 464 read_unlock(&ipip6_lock);
464 return err; 465 return err;
465#else
466 struct iphdr *iph = (struct iphdr*)dp;
467 int hlen = iph->ihl<<2;
468 struct ipv6hdr *iph6;
469 const int type = icmp_hdr(skb)->type;
470 const int code = icmp_hdr(skb)->code;
471 int rel_type = 0;
472 int rel_code = 0;
473 int rel_info = 0;
474 struct sk_buff *skb2;
475 struct rt6_info *rt6i;
476
477 if (len < hlen + sizeof(struct ipv6hdr))
478 return;
479 iph6 = (struct ipv6hdr*)(dp + hlen);
480
481 switch (type) {
482 default:
483 return;
484 case ICMP_PARAMETERPROB:
485 if (icmp_hdr(skb)->un.gateway < hlen)
486 return;
487
488 /* So... This guy found something strange INSIDE encapsulated
489 packet. Well, he is fool, but what can we do ?
490 */
491 rel_type = ICMPV6_PARAMPROB;
492 rel_info = icmp_hdr(skb)->un.gateway - hlen;
493 break;
494
495 case ICMP_DEST_UNREACH:
496 switch (code) {
497 case ICMP_SR_FAILED:
498 case ICMP_PORT_UNREACH:
499 /* Impossible event. */
500 return;
501 case ICMP_FRAG_NEEDED:
502 /* Too complicated case ... */
503 return;
504 default:
505 /* All others are translated to HOST_UNREACH.
506 rfc2003 contains "deep thoughts" about NET_UNREACH,
507 I believe, it is just ether pollution. --ANK
508 */
509 rel_type = ICMPV6_DEST_UNREACH;
510 rel_code = ICMPV6_ADDR_UNREACH;
511 break;
512 }
513 break;
514 case ICMP_TIME_EXCEEDED:
515 if (code != ICMP_EXC_TTL)
516 return;
517 rel_type = ICMPV6_TIME_EXCEED;
518 rel_code = ICMPV6_EXC_HOPLIMIT;
519 break;
520 }
521
522 /* Prepare fake skb to feed it to icmpv6_send */
523 skb2 = skb_clone(skb, GFP_ATOMIC);
524 if (skb2 == NULL)
525 return 0;
526 dst_release(skb2->dst);
527 skb2->dst = NULL;
528 skb_pull(skb2, skb->data - (u8*)iph6);
529 skb_reset_network_header(skb2);
530
531 /* Try to guess incoming interface */
532 rt6i = rt6_lookup(dev_net(skb->dev), &iph6->saddr, NULL, NULL, 0);
533 if (rt6i && rt6i->rt6i_dev) {
534 skb2->dev = rt6i->rt6i_dev;
535
536 rt6i = rt6_lookup(dev_net(skb->dev),
537 &iph6->daddr, &iph6->saddr, NULL, 0);
538
539 if (rt6i && rt6i->rt6i_dev && rt6i->rt6i_dev->type == ARPHRD_SIT) {
540 struct ip_tunnel *t = netdev_priv(rt6i->rt6i_dev);
541 if (rel_type == ICMPV6_TIME_EXCEED && t->parms.iph.ttl) {
542 rel_type = ICMPV6_DEST_UNREACH;
543 rel_code = ICMPV6_ADDR_UNREACH;
544 }
545 icmpv6_send(skb2, rel_type, rel_code, rel_info, skb2->dev);
546 }
547 }
548 kfree_skb(skb2);
549 return 0;
550#endif
551} 466}
552 467
553static inline void ipip6_ecn_decapsulate(struct iphdr *iph, struct sk_buff *skb) 468static inline void ipip6_ecn_decapsulate(struct iphdr *iph, struct sk_buff *skb)
@@ -960,11 +875,20 @@ ipip6_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd)
960 break; 875 break;
961 876
962 case SIOCGETPRL: 877 case SIOCGETPRL:
878 err = -EINVAL;
879 if (dev == sitn->fb_tunnel_dev)
880 goto done;
881 err = -ENOENT;
882 if (!(t = netdev_priv(dev)))
883 goto done;
884 err = ipip6_tunnel_get_prl(t, ifr->ifr_ifru.ifru_data);
885 break;
886
963 case SIOCADDPRL: 887 case SIOCADDPRL:
964 case SIOCDELPRL: 888 case SIOCDELPRL:
965 case SIOCCHGPRL: 889 case SIOCCHGPRL:
966 err = -EPERM; 890 err = -EPERM;
967 if (cmd != SIOCGETPRL && !capable(CAP_NET_ADMIN)) 891 if (!capable(CAP_NET_ADMIN))
968 goto done; 892 goto done;
969 err = -EINVAL; 893 err = -EINVAL;
970 if (dev == sitn->fb_tunnel_dev) 894 if (dev == sitn->fb_tunnel_dev)
@@ -977,12 +901,6 @@ ipip6_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd)
977 goto done; 901 goto done;
978 902
979 switch (cmd) { 903 switch (cmd) {
980 case SIOCGETPRL:
981 err = ipip6_tunnel_get_prl(t, &prl);
982 if (!err && copy_to_user(ifr->ifr_ifru.ifru_data,
983 &prl, sizeof(prl)))
984 err = -EFAULT;
985 break;
986 case SIOCDELPRL: 904 case SIOCDELPRL:
987 err = ipip6_tunnel_del_prl(t, &prl); 905 err = ipip6_tunnel_del_prl(t, &prl);
988 break; 906 break;
@@ -991,8 +909,7 @@ ipip6_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd)
991 err = ipip6_tunnel_add_prl(t, &prl, cmd == SIOCCHGPRL); 909 err = ipip6_tunnel_add_prl(t, &prl, cmd == SIOCCHGPRL);
992 break; 910 break;
993 } 911 }
994 if (cmd != SIOCGETPRL) 912 netdev_state_change(dev);
995 netdev_state_change(dev);
996 break; 913 break;
997 914
998 default: 915 default: