X-Git-Url: http://pilppa.org/gitweb/gitweb.cgi?a=blobdiff_plain;f=net%2Fipv6%2Faf_inet6.c;h=34c20533ba5d972bf3d8adf7384a5a51075e0261;hb=bb5cf80e94ad9650c4bd39e92fb917af8e87fa43;hp=eed09373a45d8cb9685ae28eebcaa761b5ef557e;hpb=5e16e3f0e24dadb79b96b6134cd3303f0d42f0c5;p=linux-2.6-omap-h63xx.git diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c index eed09373a45..34c20533ba5 100644 --- a/net/ipv6/af_inet6.c +++ b/net/ipv6/af_inet6.c @@ -68,7 +68,7 @@ MODULE_LICENSE("GPL"); int sysctl_ipv6_bindv6only __read_mostly; -/* The inetsw table contains everything that inet_create needs to +/* The inetsw6 table contains everything that inet6_create needs to * build a new socket. */ static struct list_head inetsw6[SOCK_MAX]; @@ -81,7 +81,7 @@ static __inline__ struct ipv6_pinfo *inet6_sk_generic(struct sock *sk) return (struct ipv6_pinfo *)(((u8 *)sk) + offset); } -static int inet6_create(struct socket *sock, int protocol) +static int inet6_create(struct net *net, struct socket *sock, int protocol) { struct inet_sock *inet; struct ipv6_pinfo *np; @@ -94,6 +94,9 @@ static int inet6_create(struct socket *sock, int protocol) int try_loading_module = 0; int err; + if (net != &init_net) + return -EAFNOSUPPORT; + if (sock->type != SOCK_RAW && sock->type != SOCK_DGRAM && !inet_ehash_secret) @@ -159,7 +162,7 @@ lookup_protocol: BUG_TRAP(answer_prot->slab != NULL); err = -ENOBUFS; - sk = sk_alloc(PF_INET6, GFP_KERNEL, answer_prot, 1); + sk = sk_alloc(net, PF_INET6, GFP_KERNEL, answer_prot); if (sk == NULL) goto out; @@ -299,7 +302,7 @@ int inet6_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) err = -EINVAL; goto out; } - dev = dev_get_by_index(sk->sk_bound_dev_if); + dev = dev_get_by_index(&init_net, sk->sk_bound_dev_if); if (!dev) { err = -ENODEV; goto out; @@ -484,10 +487,11 @@ const struct proto_ops inet6_stream_ops = { .shutdown = inet_shutdown, /* ok */ .setsockopt = sock_common_setsockopt, /* ok */ .getsockopt = sock_common_getsockopt, /* ok */ - .sendmsg = inet_sendmsg, /* ok */ + .sendmsg = tcp_sendmsg, /* ok */ .recvmsg = sock_common_recvmsg, /* ok */ .mmap = sock_no_mmap, .sendpage = tcp_sendpage, + .splice_read = tcp_splice_read, #ifdef CONFIG_COMPAT .compat_setsockopt = compat_sock_common_setsockopt, .compat_getsockopt = compat_sock_common_getsockopt, @@ -525,57 +529,23 @@ static struct net_proto_family inet6_family_ops = { .owner = THIS_MODULE, }; -/* Same as inet6_dgram_ops, sans udp_poll. */ -static const struct proto_ops inet6_sockraw_ops = { - .family = PF_INET6, - .owner = THIS_MODULE, - .release = inet6_release, - .bind = inet6_bind, - .connect = inet_dgram_connect, /* ok */ - .socketpair = sock_no_socketpair, /* a do nothing */ - .accept = sock_no_accept, /* a do nothing */ - .getname = inet6_getname, - .poll = datagram_poll, /* ok */ - .ioctl = inet6_ioctl, /* must change */ - .listen = sock_no_listen, /* ok */ - .shutdown = inet_shutdown, /* ok */ - .setsockopt = sock_common_setsockopt, /* ok */ - .getsockopt = sock_common_getsockopt, /* ok */ - .sendmsg = inet_sendmsg, /* ok */ - .recvmsg = sock_common_recvmsg, /* ok */ - .mmap = sock_no_mmap, - .sendpage = sock_no_sendpage, -#ifdef CONFIG_COMPAT - .compat_setsockopt = compat_sock_common_setsockopt, - .compat_getsockopt = compat_sock_common_getsockopt, -#endif -}; - -static struct inet_protosw rawv6_protosw = { - .type = SOCK_RAW, - .protocol = IPPROTO_IP, /* wild card */ - .prot = &rawv6_prot, - .ops = &inet6_sockraw_ops, - .capability = CAP_NET_RAW, - .no_check = UDP_CSUM_DEFAULT, - .flags = INET_PROTOSW_REUSE, -}; - -void -inet6_register_protosw(struct inet_protosw *p) +int inet6_register_protosw(struct inet_protosw *p) { struct list_head *lh; struct inet_protosw *answer; - int protocol = p->protocol; struct list_head *last_perm; + int protocol = p->protocol; + int ret; spin_lock_bh(&inetsw6_lock); + ret = -EINVAL; if (p->type >= SOCK_MAX) goto out_illegal; /* If we are trying to override a permanent protocol, bail. */ answer = NULL; + ret = -EPERM; last_perm = &inetsw6[p->type]; list_for_each(lh, &inetsw6[p->type]) { answer = list_entry(lh, struct inet_protosw, list); @@ -599,9 +569,10 @@ inet6_register_protosw(struct inet_protosw *p) * system automatically returns to the old behavior. */ list_add_rcu(&p->list, last_perm); + ret = 0; out: spin_unlock_bh(&inetsw6_lock); - return; + return ret; out_permanent: printk(KERN_ERR "Attempt to override permanent protocol %d.\n", @@ -710,23 +681,27 @@ EXPORT_SYMBOL_GPL(ipv6_opt_accepted); static int __init init_ipv6_mibs(void) { - if (snmp_mib_init((void **)ipv6_statistics, sizeof (struct ipstats_mib), - __alignof__(struct ipstats_mib)) < 0) + if (snmp_mib_init((void **)ipv6_statistics, + sizeof(struct ipstats_mib)) < 0) goto err_ip_mib; - if (snmp_mib_init((void **)icmpv6_statistics, sizeof (struct icmpv6_mib), - __alignof__(struct icmpv6_mib)) < 0) + if (snmp_mib_init((void **)icmpv6_statistics, + sizeof(struct icmpv6_mib)) < 0) goto err_icmp_mib; - if (snmp_mib_init((void **)udp_stats_in6, sizeof (struct udp_mib), - __alignof__(struct udp_mib)) < 0) + if (snmp_mib_init((void **)icmpv6msg_statistics, + sizeof(struct icmpv6msg_mib)) < 0) + goto err_icmpmsg_mib; + if (snmp_mib_init((void **)udp_stats_in6, sizeof (struct udp_mib)) < 0) goto err_udp_mib; - if (snmp_mib_init((void **)udplite_stats_in6, sizeof (struct udp_mib), - __alignof__(struct udp_mib)) < 0) + if (snmp_mib_init((void **)udplite_stats_in6, + sizeof (struct udp_mib)) < 0) goto err_udplite_mib; return 0; err_udplite_mib: snmp_mib_free((void **)udp_stats_in6); err_udp_mib: + snmp_mib_free((void **)icmpv6msg_statistics); +err_icmpmsg_mib: snmp_mib_free((void **)icmpv6_statistics); err_icmp_mib: snmp_mib_free((void **)ipv6_statistics); @@ -739,6 +714,7 @@ static void cleanup_ipv6_mibs(void) { snmp_mib_free((void **)ipv6_statistics); snmp_mib_free((void **)icmpv6_statistics); + snmp_mib_free((void **)icmpv6msg_statistics); snmp_mib_free((void **)udp_stats_in6); snmp_mib_free((void **)udplite_stats_in6); } @@ -759,7 +735,6 @@ static int __init inet6_init(void) __this_module.can_unload = &ipv6_unload; #endif #endif - err = proto_register(&tcpv6_prot, 1); if (err) goto out; @@ -784,14 +759,16 @@ static int __init inet6_init(void) /* We MUST register RAW sockets before we create the ICMP6, * IGMP6, or NDISC control sockets. */ - inet6_register_protosw(&rawv6_protosw); + err = rawv6_init(); + if (err) + goto out_unregister_raw_proto; /* Register the family here so that the init calls below will * be able to create sockets. (?? is this dangerous ??) */ err = sock_register(&inet6_family_ops); if (err) - goto out_unregister_raw_proto; + goto out_sock_register_fail; /* Initialise ipv6 mibs */ err = init_ipv6_mibs(); @@ -839,31 +816,61 @@ static int __init inet6_init(void) if (if6_proc_init()) goto proc_if6_fail; #endif - ip6_route_init(); - ip6_flowlabel_init(); + err = ip6_route_init(); + if (err) + goto ip6_route_fail; + err = ip6_flowlabel_init(); + if (err) + goto ip6_flowlabel_fail; err = addrconf_init(); if (err) goto addrconf_fail; /* Init v6 extension headers. */ - ipv6_rthdr_init(); - ipv6_frag_init(); - ipv6_nodata_init(); - ipv6_destopt_init(); + err = ipv6_exthdrs_init(); + if (err) + goto ipv6_exthdrs_fail; + + err = ipv6_frag_init(); + if (err) + goto ipv6_frag_fail; /* Init v6 transport protocols. */ - udpv6_init(); - udplitev6_init(); - tcpv6_init(); + err = udpv6_init(); + if (err) + goto udpv6_fail; - ipv6_packet_init(); - err = 0; + err = udplitev6_init(); + if (err) + goto udplitev6_fail; + + err = tcpv6_init(); + if (err) + goto tcpv6_fail; + + err = ipv6_packet_init(); + if (err) + goto ipv6_packet_fail; out: return err; +ipv6_packet_fail: + tcpv6_exit(); +tcpv6_fail: + udplitev6_exit(); +udplitev6_fail: + udpv6_exit(); +udpv6_fail: + ipv6_frag_exit(); +ipv6_frag_fail: + ipv6_exthdrs_exit(); +ipv6_exthdrs_fail: + addrconf_cleanup(); addrconf_fail: ip6_flowlabel_cleanup(); +ip6_flowlabel_fail: ip6_route_cleanup(); +ip6_route_fail: #ifdef CONFIG_PROC_FS if6_proc_exit(); proc_if6_fail: @@ -894,6 +901,9 @@ icmp_fail: cleanup_ipv6_mibs(); out_unregister_sock: sock_unregister(PF_INET6); + rtnl_unregister_all(PF_INET6); +out_sock_register_fail: + rawv6_exit(); out_unregister_raw_proto: proto_unregister(&rawv6_prot); out_unregister_udplite_proto: @@ -913,9 +923,14 @@ static void __exit inet6_exit(void) /* Disallow any further netlink messages */ rtnl_unregister_all(PF_INET6); + udpv6_exit(); + udplitev6_exit(); + tcpv6_exit(); + /* Cleanup code parts. */ ipv6_packet_cleanup(); - + ipv6_frag_exit(); + ipv6_exthdrs_exit(); addrconf_cleanup(); ip6_flowlabel_cleanup(); ip6_route_cleanup(); @@ -934,6 +949,7 @@ static void __exit inet6_exit(void) igmp6_cleanup(); ndisc_cleanup(); icmpv6_cleanup(); + rawv6_exit(); #ifdef CONFIG_SYSCTL ipv6_sysctl_unregister(); #endif