aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6/af_inet6.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv6/af_inet6.c')
-rw-r--r--net/ipv6/af_inet6.c175
1 files changed, 149 insertions, 26 deletions
diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c
index f0aa97738746..730a861b8f41 100644
--- a/net/ipv6/af_inet6.c
+++ b/net/ipv6/af_inet6.c
@@ -92,9 +92,6 @@ static int inet6_create(struct net *net, struct socket *sock, int protocol)
92 int try_loading_module = 0; 92 int try_loading_module = 0;
93 int err; 93 int err;
94 94
95 if (net != &init_net)
96 return -EAFNOSUPPORT;
97
98 if (sock->type != SOCK_RAW && 95 if (sock->type != SOCK_RAW &&
99 sock->type != SOCK_DGRAM && 96 sock->type != SOCK_DGRAM &&
100 !inet_ehash_secret) 97 !inet_ehash_secret)
@@ -248,6 +245,7 @@ int inet6_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
248 struct sock *sk = sock->sk; 245 struct sock *sk = sock->sk;
249 struct inet_sock *inet = inet_sk(sk); 246 struct inet_sock *inet = inet_sk(sk);
250 struct ipv6_pinfo *np = inet6_sk(sk); 247 struct ipv6_pinfo *np = inet6_sk(sk);
248 struct net *net = sk->sk_net;
251 __be32 v4addr = 0; 249 __be32 v4addr = 0;
252 unsigned short snum; 250 unsigned short snum;
253 int addr_type = 0; 251 int addr_type = 0;
@@ -278,7 +276,7 @@ int inet6_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
278 /* Check if the address belongs to the host. */ 276 /* Check if the address belongs to the host. */
279 if (addr_type == IPV6_ADDR_MAPPED) { 277 if (addr_type == IPV6_ADDR_MAPPED) {
280 v4addr = addr->sin6_addr.s6_addr32[3]; 278 v4addr = addr->sin6_addr.s6_addr32[3];
281 if (inet_addr_type(&init_net, v4addr) != RTN_LOCAL) { 279 if (inet_addr_type(net, v4addr) != RTN_LOCAL) {
282 err = -EADDRNOTAVAIL; 280 err = -EADDRNOTAVAIL;
283 goto out; 281 goto out;
284 } 282 }
@@ -300,7 +298,7 @@ int inet6_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
300 err = -EINVAL; 298 err = -EINVAL;
301 goto out; 299 goto out;
302 } 300 }
303 dev = dev_get_by_index(&init_net, sk->sk_bound_dev_if); 301 dev = dev_get_by_index(net, sk->sk_bound_dev_if);
304 if (!dev) { 302 if (!dev) {
305 err = -ENODEV; 303 err = -ENODEV;
306 goto out; 304 goto out;
@@ -312,7 +310,7 @@ int inet6_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
312 */ 310 */
313 v4addr = LOOPBACK4_IPV6; 311 v4addr = LOOPBACK4_IPV6;
314 if (!(addr_type & IPV6_ADDR_MULTICAST)) { 312 if (!(addr_type & IPV6_ADDR_MULTICAST)) {
315 if (!ipv6_chk_addr(&init_net, &addr->sin6_addr, 313 if (!ipv6_chk_addr(net, &addr->sin6_addr,
316 dev, 0)) { 314 dev, 0)) {
317 if (dev) 315 if (dev)
318 dev_put(dev); 316 dev_put(dev);
@@ -440,6 +438,7 @@ EXPORT_SYMBOL(inet6_getname);
440int inet6_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) 438int inet6_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
441{ 439{
442 struct sock *sk = sock->sk; 440 struct sock *sk = sock->sk;
441 struct net *net = sk->sk_net;
443 442
444 switch(cmd) 443 switch(cmd)
445 { 444 {
@@ -452,14 +451,14 @@ int inet6_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
452 case SIOCADDRT: 451 case SIOCADDRT:
453 case SIOCDELRT: 452 case SIOCDELRT:
454 453
455 return(ipv6_route_ioctl(cmd,(void __user *)arg)); 454 return(ipv6_route_ioctl(net, cmd, (void __user *)arg));
456 455
457 case SIOCSIFADDR: 456 case SIOCSIFADDR:
458 return addrconf_add_ifaddr((void __user *) arg); 457 return addrconf_add_ifaddr(net, (void __user *) arg);
459 case SIOCDIFADDR: 458 case SIOCDIFADDR:
460 return addrconf_del_ifaddr((void __user *) arg); 459 return addrconf_del_ifaddr(net, (void __user *) arg);
461 case SIOCSIFDSTADDR: 460 case SIOCSIFDSTADDR:
462 return addrconf_set_dstaddr((void __user *) arg); 461 return addrconf_set_dstaddr(net, (void __user *) arg);
463 default: 462 default:
464 if (!sk->sk_prot->ioctl) 463 if (!sk->sk_prot->ioctl)
465 return -ENOIOCTLCMD; 464 return -ENOIOCTLCMD;
@@ -678,6 +677,129 @@ int ipv6_opt_accepted(struct sock *sk, struct sk_buff *skb)
678 677
679EXPORT_SYMBOL_GPL(ipv6_opt_accepted); 678EXPORT_SYMBOL_GPL(ipv6_opt_accepted);
680 679
680static struct inet6_protocol *ipv6_gso_pull_exthdrs(struct sk_buff *skb,
681 int proto)
682{
683 struct inet6_protocol *ops = NULL;
684
685 for (;;) {
686 struct ipv6_opt_hdr *opth;
687 int len;
688
689 if (proto != NEXTHDR_HOP) {
690 ops = rcu_dereference(inet6_protos[proto]);
691
692 if (unlikely(!ops))
693 break;
694
695 if (!(ops->flags & INET6_PROTO_GSO_EXTHDR))
696 break;
697 }
698
699 if (unlikely(!pskb_may_pull(skb, 8)))
700 break;
701
702 opth = (void *)skb->data;
703 len = ipv6_optlen(opth);
704
705 if (unlikely(!pskb_may_pull(skb, len)))
706 break;
707
708 proto = opth->nexthdr;
709 __skb_pull(skb, len);
710 }
711
712 return ops;
713}
714
715static int ipv6_gso_send_check(struct sk_buff *skb)
716{
717 struct ipv6hdr *ipv6h;
718 struct inet6_protocol *ops;
719 int err = -EINVAL;
720
721 if (unlikely(!pskb_may_pull(skb, sizeof(*ipv6h))))
722 goto out;
723
724 ipv6h = ipv6_hdr(skb);
725 __skb_pull(skb, sizeof(*ipv6h));
726 err = -EPROTONOSUPPORT;
727
728 rcu_read_lock();
729 ops = ipv6_gso_pull_exthdrs(skb, ipv6h->nexthdr);
730 if (likely(ops && ops->gso_send_check)) {
731 skb_reset_transport_header(skb);
732 err = ops->gso_send_check(skb);
733 }
734 rcu_read_unlock();
735
736out:
737 return err;
738}
739
740static struct sk_buff *ipv6_gso_segment(struct sk_buff *skb, int features)
741{
742 struct sk_buff *segs = ERR_PTR(-EINVAL);
743 struct ipv6hdr *ipv6h;
744 struct inet6_protocol *ops;
745
746 if (!(features & NETIF_F_V6_CSUM))
747 features &= ~NETIF_F_SG;
748
749 if (unlikely(skb_shinfo(skb)->gso_type &
750 ~(SKB_GSO_UDP |
751 SKB_GSO_DODGY |
752 SKB_GSO_TCP_ECN |
753 SKB_GSO_TCPV6 |
754 0)))
755 goto out;
756
757 if (unlikely(!pskb_may_pull(skb, sizeof(*ipv6h))))
758 goto out;
759
760 ipv6h = ipv6_hdr(skb);
761 __skb_pull(skb, sizeof(*ipv6h));
762 segs = ERR_PTR(-EPROTONOSUPPORT);
763
764 rcu_read_lock();
765 ops = ipv6_gso_pull_exthdrs(skb, ipv6h->nexthdr);
766 if (likely(ops && ops->gso_segment)) {
767 skb_reset_transport_header(skb);
768 segs = ops->gso_segment(skb, features);
769 }
770 rcu_read_unlock();
771
772 if (unlikely(IS_ERR(segs)))
773 goto out;
774
775 for (skb = segs; skb; skb = skb->next) {
776 ipv6h = ipv6_hdr(skb);
777 ipv6h->payload_len = htons(skb->len - skb->mac_len -
778 sizeof(*ipv6h));
779 }
780
781out:
782 return segs;
783}
784
785static struct packet_type ipv6_packet_type = {
786 .type = __constant_htons(ETH_P_IPV6),
787 .func = ipv6_rcv,
788 .gso_send_check = ipv6_gso_send_check,
789 .gso_segment = ipv6_gso_segment,
790};
791
792static int __init ipv6_packet_init(void)
793{
794 dev_add_pack(&ipv6_packet_type);
795 return 0;
796}
797
798static void ipv6_packet_cleanup(void)
799{
800 dev_remove_pack(&ipv6_packet_type);
801}
802
681static int __init init_ipv6_mibs(void) 803static int __init init_ipv6_mibs(void)
682{ 804{
683 if (snmp_mib_init((void **)ipv6_statistics, 805 if (snmp_mib_init((void **)ipv6_statistics,
@@ -802,19 +924,13 @@ static int __init inet6_init(void)
802 err = register_pernet_subsys(&inet6_net_ops); 924 err = register_pernet_subsys(&inet6_net_ops);
803 if (err) 925 if (err)
804 goto register_pernet_fail; 926 goto register_pernet_fail;
805 927 err = icmpv6_init();
806#ifdef CONFIG_SYSCTL
807 err = ipv6_sysctl_register();
808 if (err)
809 goto sysctl_fail;
810#endif
811 err = icmpv6_init(&inet6_family_ops);
812 if (err) 928 if (err)
813 goto icmp_fail; 929 goto icmp_fail;
814 err = ndisc_init(&inet6_family_ops); 930 err = ndisc_init();
815 if (err) 931 if (err)
816 goto ndisc_fail; 932 goto ndisc_fail;
817 err = igmp6_init(&inet6_family_ops); 933 err = igmp6_init();
818 if (err) 934 if (err)
819 goto igmp_fail; 935 goto igmp_fail;
820 err = ipv6_netfilter_init(); 936 err = ipv6_netfilter_init();
@@ -874,9 +990,19 @@ static int __init inet6_init(void)
874 err = ipv6_packet_init(); 990 err = ipv6_packet_init();
875 if (err) 991 if (err)
876 goto ipv6_packet_fail; 992 goto ipv6_packet_fail;
993
994#ifdef CONFIG_SYSCTL
995 err = ipv6_sysctl_register();
996 if (err)
997 goto sysctl_fail;
998#endif
877out: 999out:
878 return err; 1000 return err;
879 1001
1002#ifdef CONFIG_SYSCTL
1003sysctl_fail:
1004 ipv6_packet_cleanup();
1005#endif
880ipv6_packet_fail: 1006ipv6_packet_fail:
881 tcpv6_exit(); 1007 tcpv6_exit();
882tcpv6_fail: 1008tcpv6_fail:
@@ -918,10 +1044,6 @@ igmp_fail:
918ndisc_fail: 1044ndisc_fail:
919 icmpv6_cleanup(); 1045 icmpv6_cleanup();
920icmp_fail: 1046icmp_fail:
921#ifdef CONFIG_SYSCTL
922 ipv6_sysctl_unregister();
923sysctl_fail:
924#endif
925 unregister_pernet_subsys(&inet6_net_ops); 1047 unregister_pernet_subsys(&inet6_net_ops);
926register_pernet_fail: 1048register_pernet_fail:
927 cleanup_ipv6_mibs(); 1049 cleanup_ipv6_mibs();
@@ -949,6 +1071,9 @@ static void __exit inet6_exit(void)
949 /* Disallow any further netlink messages */ 1071 /* Disallow any further netlink messages */
950 rtnl_unregister_all(PF_INET6); 1072 rtnl_unregister_all(PF_INET6);
951 1073
1074#ifdef CONFIG_SYSCTL
1075 ipv6_sysctl_unregister();
1076#endif
952 udpv6_exit(); 1077 udpv6_exit();
953 udplitev6_exit(); 1078 udplitev6_exit();
954 tcpv6_exit(); 1079 tcpv6_exit();
@@ -976,9 +1101,7 @@ static void __exit inet6_exit(void)
976 ndisc_cleanup(); 1101 ndisc_cleanup();
977 icmpv6_cleanup(); 1102 icmpv6_cleanup();
978 rawv6_exit(); 1103 rawv6_exit();
979#ifdef CONFIG_SYSCTL 1104
980 ipv6_sysctl_unregister();
981#endif
982 unregister_pernet_subsys(&inet6_net_ops); 1105 unregister_pernet_subsys(&inet6_net_ops);
983 cleanup_ipv6_mibs(); 1106 cleanup_ipv6_mibs();
984 proto_unregister(&rawv6_prot); 1107 proto_unregister(&rawv6_prot);