diff options
Diffstat (limited to 'net/ipv6/sit.c')
-rw-r--r-- | net/ipv6/sit.c | 101 |
1 files changed, 48 insertions, 53 deletions
diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c index 8ce38f10a547..1cca5761aea9 100644 --- a/net/ipv6/sit.c +++ b/net/ipv6/sit.c | |||
@@ -250,11 +250,6 @@ static struct ip_tunnel *ipip6_tunnel_locate(struct net *net, | |||
250 | 250 | ||
251 | dev_net_set(dev, net); | 251 | dev_net_set(dev, net); |
252 | 252 | ||
253 | if (strchr(name, '%')) { | ||
254 | if (dev_alloc_name(dev, name) < 0) | ||
255 | goto failed_free; | ||
256 | } | ||
257 | |||
258 | nt = netdev_priv(dev); | 253 | nt = netdev_priv(dev); |
259 | 254 | ||
260 | nt->parms = *parms; | 255 | nt->parms = *parms; |
@@ -401,18 +396,13 @@ out: | |||
401 | return err; | 396 | return err; |
402 | } | 397 | } |
403 | 398 | ||
404 | static void prl_entry_destroy_rcu(struct rcu_head *head) | ||
405 | { | ||
406 | kfree(container_of(head, struct ip_tunnel_prl_entry, rcu_head)); | ||
407 | } | ||
408 | |||
409 | static void prl_list_destroy_rcu(struct rcu_head *head) | 399 | static void prl_list_destroy_rcu(struct rcu_head *head) |
410 | { | 400 | { |
411 | struct ip_tunnel_prl_entry *p, *n; | 401 | struct ip_tunnel_prl_entry *p, *n; |
412 | 402 | ||
413 | p = container_of(head, struct ip_tunnel_prl_entry, rcu_head); | 403 | p = container_of(head, struct ip_tunnel_prl_entry, rcu_head); |
414 | do { | 404 | do { |
415 | n = p->next; | 405 | n = rcu_dereference_protected(p->next, 1); |
416 | kfree(p); | 406 | kfree(p); |
417 | p = n; | 407 | p = n; |
418 | } while (p); | 408 | } while (p); |
@@ -421,26 +411,28 @@ static void prl_list_destroy_rcu(struct rcu_head *head) | |||
421 | static int | 411 | static int |
422 | ipip6_tunnel_del_prl(struct ip_tunnel *t, struct ip_tunnel_prl *a) | 412 | ipip6_tunnel_del_prl(struct ip_tunnel *t, struct ip_tunnel_prl *a) |
423 | { | 413 | { |
424 | struct ip_tunnel_prl_entry *x, **p; | 414 | struct ip_tunnel_prl_entry *x; |
415 | struct ip_tunnel_prl_entry __rcu **p; | ||
425 | int err = 0; | 416 | int err = 0; |
426 | 417 | ||
427 | ASSERT_RTNL(); | 418 | ASSERT_RTNL(); |
428 | 419 | ||
429 | if (a && a->addr != htonl(INADDR_ANY)) { | 420 | if (a && a->addr != htonl(INADDR_ANY)) { |
430 | for (p = &t->prl; *p; p = &(*p)->next) { | 421 | for (p = &t->prl; |
431 | if ((*p)->addr == a->addr) { | 422 | (x = rtnl_dereference(*p)) != NULL; |
432 | x = *p; | 423 | p = &x->next) { |
424 | if (x->addr == a->addr) { | ||
433 | *p = x->next; | 425 | *p = x->next; |
434 | call_rcu(&x->rcu_head, prl_entry_destroy_rcu); | 426 | kfree_rcu(x, rcu_head); |
435 | t->prl_count--; | 427 | t->prl_count--; |
436 | goto out; | 428 | goto out; |
437 | } | 429 | } |
438 | } | 430 | } |
439 | err = -ENXIO; | 431 | err = -ENXIO; |
440 | } else { | 432 | } else { |
441 | if (t->prl) { | 433 | x = rtnl_dereference(t->prl); |
434 | if (x) { | ||
442 | t->prl_count = 0; | 435 | t->prl_count = 0; |
443 | x = t->prl; | ||
444 | call_rcu(&x->rcu_head, prl_list_destroy_rcu); | 436 | call_rcu(&x->rcu_head, prl_list_destroy_rcu); |
445 | t->prl = NULL; | 437 | t->prl = NULL; |
446 | } | 438 | } |
@@ -450,7 +442,7 @@ out: | |||
450 | } | 442 | } |
451 | 443 | ||
452 | static int | 444 | static int |
453 | isatap_chksrc(struct sk_buff *skb, struct iphdr *iph, struct ip_tunnel *t) | 445 | isatap_chksrc(struct sk_buff *skb, const struct iphdr *iph, struct ip_tunnel *t) |
454 | { | 446 | { |
455 | struct ip_tunnel_prl_entry *p; | 447 | struct ip_tunnel_prl_entry *p; |
456 | int ok = 1; | 448 | int ok = 1; |
@@ -463,7 +455,8 @@ isatap_chksrc(struct sk_buff *skb, struct iphdr *iph, struct ip_tunnel *t) | |||
463 | else | 455 | else |
464 | skb->ndisc_nodetype = NDISC_NODETYPE_NODEFAULT; | 456 | skb->ndisc_nodetype = NDISC_NODETYPE_NODEFAULT; |
465 | } else { | 457 | } else { |
466 | struct in6_addr *addr6 = &ipv6_hdr(skb)->saddr; | 458 | const struct in6_addr *addr6 = &ipv6_hdr(skb)->saddr; |
459 | |||
467 | if (ipv6_addr_is_isatap(addr6) && | 460 | if (ipv6_addr_is_isatap(addr6) && |
468 | (addr6->s6_addr32[3] == iph->saddr) && | 461 | (addr6->s6_addr32[3] == iph->saddr) && |
469 | ipv6_chk_prefix(addr6, t->dev)) | 462 | ipv6_chk_prefix(addr6, t->dev)) |
@@ -497,7 +490,7 @@ static int ipip6_err(struct sk_buff *skb, u32 info) | |||
497 | 8 bytes of packet payload. It means, that precise relaying of | 490 | 8 bytes of packet payload. It means, that precise relaying of |
498 | ICMP in the real Internet is absolutely infeasible. | 491 | ICMP in the real Internet is absolutely infeasible. |
499 | */ | 492 | */ |
500 | struct iphdr *iph = (struct iphdr*)skb->data; | 493 | const struct iphdr *iph = (const struct iphdr *)skb->data; |
501 | const int type = icmp_hdr(skb)->type; | 494 | const int type = icmp_hdr(skb)->type; |
502 | const int code = icmp_hdr(skb)->code; | 495 | const int code = icmp_hdr(skb)->code; |
503 | struct ip_tunnel *t; | 496 | struct ip_tunnel *t; |
@@ -555,7 +548,7 @@ out: | |||
555 | return err; | 548 | return err; |
556 | } | 549 | } |
557 | 550 | ||
558 | static inline void ipip6_ecn_decapsulate(struct iphdr *iph, struct sk_buff *skb) | 551 | static inline void ipip6_ecn_decapsulate(const struct iphdr *iph, struct sk_buff *skb) |
559 | { | 552 | { |
560 | if (INET_ECN_is_ce(iph->tos)) | 553 | if (INET_ECN_is_ce(iph->tos)) |
561 | IP6_ECN_set_ce(ipv6_hdr(skb)); | 554 | IP6_ECN_set_ce(ipv6_hdr(skb)); |
@@ -563,7 +556,7 @@ static inline void ipip6_ecn_decapsulate(struct iphdr *iph, struct sk_buff *skb) | |||
563 | 556 | ||
564 | static int ipip6_rcv(struct sk_buff *skb) | 557 | static int ipip6_rcv(struct sk_buff *skb) |
565 | { | 558 | { |
566 | struct iphdr *iph; | 559 | const struct iphdr *iph; |
567 | struct ip_tunnel *tunnel; | 560 | struct ip_tunnel *tunnel; |
568 | 561 | ||
569 | if (!pskb_may_pull(skb, sizeof(struct ipv6hdr))) | 562 | if (!pskb_may_pull(skb, sizeof(struct ipv6hdr))) |
@@ -619,7 +612,7 @@ out: | |||
619 | * comes from 6rd / 6to4 (RFC 3056) addr space. | 612 | * comes from 6rd / 6to4 (RFC 3056) addr space. |
620 | */ | 613 | */ |
621 | static inline | 614 | static inline |
622 | __be32 try_6rd(struct in6_addr *v6dst, struct ip_tunnel *tunnel) | 615 | __be32 try_6rd(const struct in6_addr *v6dst, struct ip_tunnel *tunnel) |
623 | { | 616 | { |
624 | __be32 dst = 0; | 617 | __be32 dst = 0; |
625 | 618 | ||
@@ -662,8 +655,8 @@ static netdev_tx_t ipip6_tunnel_xmit(struct sk_buff *skb, | |||
662 | { | 655 | { |
663 | struct ip_tunnel *tunnel = netdev_priv(dev); | 656 | struct ip_tunnel *tunnel = netdev_priv(dev); |
664 | struct pcpu_tstats *tstats; | 657 | struct pcpu_tstats *tstats; |
665 | struct iphdr *tiph = &tunnel->parms.iph; | 658 | const struct iphdr *tiph = &tunnel->parms.iph; |
666 | struct ipv6hdr *iph6 = ipv6_hdr(skb); | 659 | const struct ipv6hdr *iph6 = ipv6_hdr(skb); |
667 | u8 tos = tunnel->parms.iph.tos; | 660 | u8 tos = tunnel->parms.iph.tos; |
668 | __be16 df = tiph->frag_off; | 661 | __be16 df = tiph->frag_off; |
669 | struct rtable *rt; /* Route to the other host */ | 662 | struct rtable *rt; /* Route to the other host */ |
@@ -671,8 +664,9 @@ static netdev_tx_t ipip6_tunnel_xmit(struct sk_buff *skb, | |||
671 | struct iphdr *iph; /* Our new IP header */ | 664 | struct iphdr *iph; /* Our new IP header */ |
672 | unsigned int max_headroom; /* The extra header space needed */ | 665 | unsigned int max_headroom; /* The extra header space needed */ |
673 | __be32 dst = tiph->daddr; | 666 | __be32 dst = tiph->daddr; |
667 | struct flowi4 fl4; | ||
674 | int mtu; | 668 | int mtu; |
675 | struct in6_addr *addr6; | 669 | const struct in6_addr *addr6; |
676 | int addr_type; | 670 | int addr_type; |
677 | 671 | ||
678 | if (skb->protocol != htons(ETH_P_IPV6)) | 672 | if (skb->protocol != htons(ETH_P_IPV6)) |
@@ -691,7 +685,7 @@ static netdev_tx_t ipip6_tunnel_xmit(struct sk_buff *skb, | |||
691 | goto tx_error; | 685 | goto tx_error; |
692 | } | 686 | } |
693 | 687 | ||
694 | addr6 = (struct in6_addr*)&neigh->primary_key; | 688 | addr6 = (const struct in6_addr*)&neigh->primary_key; |
695 | addr_type = ipv6_addr_type(addr6); | 689 | addr_type = ipv6_addr_type(addr6); |
696 | 690 | ||
697 | if ((addr_type & IPV6_ADDR_UNICAST) && | 691 | if ((addr_type & IPV6_ADDR_UNICAST) && |
@@ -716,7 +710,7 @@ static netdev_tx_t ipip6_tunnel_xmit(struct sk_buff *skb, | |||
716 | goto tx_error; | 710 | goto tx_error; |
717 | } | 711 | } |
718 | 712 | ||
719 | addr6 = (struct in6_addr*)&neigh->primary_key; | 713 | addr6 = (const struct in6_addr*)&neigh->primary_key; |
720 | addr_type = ipv6_addr_type(addr6); | 714 | addr_type = ipv6_addr_type(addr6); |
721 | 715 | ||
722 | if (addr_type == IPV6_ADDR_ANY) { | 716 | if (addr_type == IPV6_ADDR_ANY) { |
@@ -730,16 +724,14 @@ static netdev_tx_t ipip6_tunnel_xmit(struct sk_buff *skb, | |||
730 | dst = addr6->s6_addr32[3]; | 724 | dst = addr6->s6_addr32[3]; |
731 | } | 725 | } |
732 | 726 | ||
733 | { | 727 | rt = ip_route_output_ports(dev_net(dev), &fl4, NULL, |
734 | struct flowi fl = { .fl4_dst = dst, | 728 | dst, tiph->saddr, |
735 | .fl4_src = tiph->saddr, | 729 | 0, 0, |
736 | .fl4_tos = RT_TOS(tos), | 730 | IPPROTO_IPV6, RT_TOS(tos), |
737 | .oif = tunnel->parms.link, | 731 | tunnel->parms.link); |
738 | .proto = IPPROTO_IPV6 }; | 732 | if (IS_ERR(rt)) { |
739 | if (ip_route_output_key(dev_net(dev), &rt, &fl)) { | 733 | dev->stats.tx_carrier_errors++; |
740 | dev->stats.tx_carrier_errors++; | 734 | goto tx_error_icmp; |
741 | goto tx_error_icmp; | ||
742 | } | ||
743 | } | 735 | } |
744 | if (rt->rt_type != RTN_UNICAST) { | 736 | if (rt->rt_type != RTN_UNICAST) { |
745 | ip_rt_put(rt); | 737 | ip_rt_put(rt); |
@@ -826,8 +818,8 @@ static netdev_tx_t ipip6_tunnel_xmit(struct sk_buff *skb, | |||
826 | iph->frag_off = df; | 818 | iph->frag_off = df; |
827 | iph->protocol = IPPROTO_IPV6; | 819 | iph->protocol = IPPROTO_IPV6; |
828 | iph->tos = INET_ECN_encapsulate(tos, ipv6_get_dsfield(iph6)); | 820 | iph->tos = INET_ECN_encapsulate(tos, ipv6_get_dsfield(iph6)); |
829 | iph->daddr = rt->rt_dst; | 821 | iph->daddr = fl4.daddr; |
830 | iph->saddr = rt->rt_src; | 822 | iph->saddr = fl4.saddr; |
831 | 823 | ||
832 | if ((iph->ttl = tiph->ttl) == 0) | 824 | if ((iph->ttl = tiph->ttl) == 0) |
833 | iph->ttl = iph6->hop_limit; | 825 | iph->ttl = iph6->hop_limit; |
@@ -849,19 +841,21 @@ static void ipip6_tunnel_bind_dev(struct net_device *dev) | |||
849 | { | 841 | { |
850 | struct net_device *tdev = NULL; | 842 | struct net_device *tdev = NULL; |
851 | struct ip_tunnel *tunnel; | 843 | struct ip_tunnel *tunnel; |
852 | struct iphdr *iph; | 844 | const struct iphdr *iph; |
845 | struct flowi4 fl4; | ||
853 | 846 | ||
854 | tunnel = netdev_priv(dev); | 847 | tunnel = netdev_priv(dev); |
855 | iph = &tunnel->parms.iph; | 848 | iph = &tunnel->parms.iph; |
856 | 849 | ||
857 | if (iph->daddr) { | 850 | if (iph->daddr) { |
858 | struct flowi fl = { .fl4_dst = iph->daddr, | 851 | struct rtable *rt = ip_route_output_ports(dev_net(dev), &fl4, NULL, |
859 | .fl4_src = iph->saddr, | 852 | iph->daddr, iph->saddr, |
860 | .fl4_tos = RT_TOS(iph->tos), | 853 | 0, 0, |
861 | .oif = tunnel->parms.link, | 854 | IPPROTO_IPV6, |
862 | .proto = IPPROTO_IPV6 }; | 855 | RT_TOS(iph->tos), |
863 | struct rtable *rt; | 856 | tunnel->parms.link); |
864 | if (!ip_route_output_key(dev_net(dev), &rt, &fl)) { | 857 | |
858 | if (!IS_ERR(rt)) { | ||
865 | tdev = rt->dst.dev; | 859 | tdev = rt->dst.dev; |
866 | ip_rt_put(rt); | 860 | ip_rt_put(rt); |
867 | } | 861 | } |
@@ -1179,7 +1173,7 @@ static int __net_init ipip6_fb_tunnel_init(struct net_device *dev) | |||
1179 | if (!dev->tstats) | 1173 | if (!dev->tstats) |
1180 | return -ENOMEM; | 1174 | return -ENOMEM; |
1181 | dev_hold(dev); | 1175 | dev_hold(dev); |
1182 | sitn->tunnels_wc[0] = tunnel; | 1176 | rcu_assign_pointer(sitn->tunnels_wc[0], tunnel); |
1183 | return 0; | 1177 | return 0; |
1184 | } | 1178 | } |
1185 | 1179 | ||
@@ -1196,11 +1190,12 @@ static void __net_exit sit_destroy_tunnels(struct sit_net *sitn, struct list_hea | |||
1196 | for (prio = 1; prio < 4; prio++) { | 1190 | for (prio = 1; prio < 4; prio++) { |
1197 | int h; | 1191 | int h; |
1198 | for (h = 0; h < HASH_SIZE; h++) { | 1192 | for (h = 0; h < HASH_SIZE; h++) { |
1199 | struct ip_tunnel *t = sitn->tunnels[prio][h]; | 1193 | struct ip_tunnel *t; |
1200 | 1194 | ||
1195 | t = rtnl_dereference(sitn->tunnels[prio][h]); | ||
1201 | while (t != NULL) { | 1196 | while (t != NULL) { |
1202 | unregister_netdevice_queue(t->dev, head); | 1197 | unregister_netdevice_queue(t->dev, head); |
1203 | t = t->next; | 1198 | t = rtnl_dereference(t->next); |
1204 | } | 1199 | } |
1205 | } | 1200 | } |
1206 | } | 1201 | } |
@@ -1290,4 +1285,4 @@ static int __init sit_init(void) | |||
1290 | module_init(sit_init); | 1285 | module_init(sit_init); |
1291 | module_exit(sit_cleanup); | 1286 | module_exit(sit_cleanup); |
1292 | MODULE_LICENSE("GPL"); | 1287 | MODULE_LICENSE("GPL"); |
1293 | MODULE_ALIAS("sit0"); | 1288 | MODULE_ALIAS_NETDEV("sit0"); |