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.c88
1 files changed, 46 insertions, 42 deletions
diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c
index e127a32f9540..3f9e86b15e0d 100644
--- a/net/ipv6/af_inet6.c
+++ b/net/ipv6/af_inet6.c
@@ -36,6 +36,7 @@
36#include <linux/proc_fs.h> 36#include <linux/proc_fs.h>
37#include <linux/stat.h> 37#include <linux/stat.h>
38#include <linux/init.h> 38#include <linux/init.h>
39#include <linux/slab.h>
39 40
40#include <linux/inet.h> 41#include <linux/inet.h>
41#include <linux/netdevice.h> 42#include <linux/netdevice.h>
@@ -95,7 +96,8 @@ static __inline__ struct ipv6_pinfo *inet6_sk_generic(struct sock *sk)
95 return (struct ipv6_pinfo *)(((u8 *)sk) + offset); 96 return (struct ipv6_pinfo *)(((u8 *)sk) + offset);
96} 97}
97 98
98static int inet6_create(struct net *net, struct socket *sock, int protocol) 99static int inet6_create(struct net *net, struct socket *sock, int protocol,
100 int kern)
99{ 101{
100 struct inet_sock *inet; 102 struct inet_sock *inet;
101 struct ipv6_pinfo *np; 103 struct ipv6_pinfo *np;
@@ -158,7 +160,7 @@ lookup_protocol:
158 } 160 }
159 161
160 err = -EPERM; 162 err = -EPERM;
161 if (answer->capability > 0 && !capable(answer->capability)) 163 if (sock->type == SOCK_RAW && !kern && !capable(CAP_NET_RAW))
162 goto out_rcu_unlock; 164 goto out_rcu_unlock;
163 165
164 sock->ops = answer->ops; 166 sock->ops = answer->ops;
@@ -185,7 +187,7 @@ lookup_protocol:
185 inet->is_icsk = (INET_PROTOSW_ICSK & answer_flags) != 0; 187 inet->is_icsk = (INET_PROTOSW_ICSK & answer_flags) != 0;
186 188
187 if (SOCK_RAW == sock->type) { 189 if (SOCK_RAW == sock->type) {
188 inet->num = protocol; 190 inet->inet_num = protocol;
189 if (IPPROTO_RAW == protocol) 191 if (IPPROTO_RAW == protocol)
190 inet->hdrincl = 1; 192 inet->hdrincl = 1;
191 } 193 }
@@ -198,7 +200,7 @@ lookup_protocol:
198 200
199 inet_sk(sk)->pinet6 = np = inet6_sk_generic(sk); 201 inet_sk(sk)->pinet6 = np = inet6_sk_generic(sk);
200 np->hop_limit = -1; 202 np->hop_limit = -1;
201 np->mcast_hops = -1; 203 np->mcast_hops = IPV6_DEFAULT_MCASTHOPS;
202 np->mc_loop = 1; 204 np->mc_loop = 1;
203 np->pmtudisc = IPV6_PMTUDISC_WANT; 205 np->pmtudisc = IPV6_PMTUDISC_WANT;
204 np->ipv6only = net->ipv6.sysctl.bindv6only; 206 np->ipv6only = net->ipv6.sysctl.bindv6only;
@@ -228,12 +230,12 @@ lookup_protocol:
228 */ 230 */
229 sk_refcnt_debug_inc(sk); 231 sk_refcnt_debug_inc(sk);
230 232
231 if (inet->num) { 233 if (inet->inet_num) {
232 /* It assumes that any protocol which allows 234 /* It assumes that any protocol which allows
233 * the user to assign a number at socket 235 * the user to assign a number at socket
234 * creation time automatically shares. 236 * creation time automatically shares.
235 */ 237 */
236 inet->sport = htons(inet->num); 238 inet->inet_sport = htons(inet->inet_num);
237 sk->sk_prot->hash(sk); 239 sk->sk_prot->hash(sk);
238 } 240 }
239 if (sk->sk_prot->init) { 241 if (sk->sk_prot->init) {
@@ -281,7 +283,7 @@ int inet6_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
281 lock_sock(sk); 283 lock_sock(sk);
282 284
283 /* Check these errors (active socket, double bind). */ 285 /* Check these errors (active socket, double bind). */
284 if (sk->sk_state != TCP_CLOSE || inet->num) { 286 if (sk->sk_state != TCP_CLOSE || inet->inet_num) {
285 err = -EINVAL; 287 err = -EINVAL;
286 goto out; 288 goto out;
287 } 289 }
@@ -314,6 +316,7 @@ int inet6_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
314 if (addr_type != IPV6_ADDR_ANY) { 316 if (addr_type != IPV6_ADDR_ANY) {
315 struct net_device *dev = NULL; 317 struct net_device *dev = NULL;
316 318
319 rcu_read_lock();
317 if (addr_type & IPV6_ADDR_LINKLOCAL) { 320 if (addr_type & IPV6_ADDR_LINKLOCAL) {
318 if (addr_len >= sizeof(struct sockaddr_in6) && 321 if (addr_len >= sizeof(struct sockaddr_in6) &&
319 addr->sin6_scope_id) { 322 addr->sin6_scope_id) {
@@ -326,12 +329,12 @@ int inet6_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
326 /* Binding to link-local address requires an interface */ 329 /* Binding to link-local address requires an interface */
327 if (!sk->sk_bound_dev_if) { 330 if (!sk->sk_bound_dev_if) {
328 err = -EINVAL; 331 err = -EINVAL;
329 goto out; 332 goto out_unlock;
330 } 333 }
331 dev = dev_get_by_index(net, sk->sk_bound_dev_if); 334 dev = dev_get_by_index_rcu(net, sk->sk_bound_dev_if);
332 if (!dev) { 335 if (!dev) {
333 err = -ENODEV; 336 err = -ENODEV;
334 goto out; 337 goto out_unlock;
335 } 338 }
336 } 339 }
337 340
@@ -342,19 +345,16 @@ int inet6_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
342 if (!(addr_type & IPV6_ADDR_MULTICAST)) { 345 if (!(addr_type & IPV6_ADDR_MULTICAST)) {
343 if (!ipv6_chk_addr(net, &addr->sin6_addr, 346 if (!ipv6_chk_addr(net, &addr->sin6_addr,
344 dev, 0)) { 347 dev, 0)) {
345 if (dev)
346 dev_put(dev);
347 err = -EADDRNOTAVAIL; 348 err = -EADDRNOTAVAIL;
348 goto out; 349 goto out_unlock;
349 } 350 }
350 } 351 }
351 if (dev) 352 rcu_read_unlock();
352 dev_put(dev);
353 } 353 }
354 } 354 }
355 355
356 inet->rcv_saddr = v4addr; 356 inet->inet_rcv_saddr = v4addr;
357 inet->saddr = v4addr; 357 inet->inet_saddr = v4addr;
358 358
359 ipv6_addr_copy(&np->rcv_saddr, &addr->sin6_addr); 359 ipv6_addr_copy(&np->rcv_saddr, &addr->sin6_addr);
360 360
@@ -375,12 +375,15 @@ int inet6_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
375 } 375 }
376 if (snum) 376 if (snum)
377 sk->sk_userlocks |= SOCK_BINDPORT_LOCK; 377 sk->sk_userlocks |= SOCK_BINDPORT_LOCK;
378 inet->sport = htons(inet->num); 378 inet->inet_sport = htons(inet->inet_num);
379 inet->dport = 0; 379 inet->inet_dport = 0;
380 inet->daddr = 0; 380 inet->inet_daddr = 0;
381out: 381out:
382 release_sock(sk); 382 release_sock(sk);
383 return err; 383 return err;
384out_unlock:
385 rcu_read_unlock();
386 goto out;
384} 387}
385 388
386EXPORT_SYMBOL(inet6_bind); 389EXPORT_SYMBOL(inet6_bind);
@@ -441,12 +444,12 @@ int inet6_getname(struct socket *sock, struct sockaddr *uaddr,
441 sin->sin6_flowinfo = 0; 444 sin->sin6_flowinfo = 0;
442 sin->sin6_scope_id = 0; 445 sin->sin6_scope_id = 0;
443 if (peer) { 446 if (peer) {
444 if (!inet->dport) 447 if (!inet->inet_dport)
445 return -ENOTCONN; 448 return -ENOTCONN;
446 if (((1 << sk->sk_state) & (TCPF_CLOSE | TCPF_SYN_SENT)) && 449 if (((1 << sk->sk_state) & (TCPF_CLOSE | TCPF_SYN_SENT)) &&
447 peer == 1) 450 peer == 1)
448 return -ENOTCONN; 451 return -ENOTCONN;
449 sin->sin6_port = inet->dport; 452 sin->sin6_port = inet->inet_dport;
450 ipv6_addr_copy(&sin->sin6_addr, &np->daddr); 453 ipv6_addr_copy(&sin->sin6_addr, &np->daddr);
451 if (np->sndflow) 454 if (np->sndflow)
452 sin->sin6_flowinfo = np->flow_label; 455 sin->sin6_flowinfo = np->flow_label;
@@ -456,7 +459,7 @@ int inet6_getname(struct socket *sock, struct sockaddr *uaddr,
456 else 459 else
457 ipv6_addr_copy(&sin->sin6_addr, &np->rcv_saddr); 460 ipv6_addr_copy(&sin->sin6_addr, &np->rcv_saddr);
458 461
459 sin->sin6_port = inet->sport; 462 sin->sin6_port = inet->inet_sport;
460 } 463 }
461 if (ipv6_addr_type(&sin->sin6_addr) & IPV6_ADDR_LINKLOCAL) 464 if (ipv6_addr_type(&sin->sin6_addr) & IPV6_ADDR_LINKLOCAL)
462 sin->sin6_scope_id = sk->sk_bound_dev_if; 465 sin->sin6_scope_id = sk->sk_bound_dev_if;
@@ -552,7 +555,7 @@ const struct proto_ops inet6_dgram_ops = {
552#endif 555#endif
553}; 556};
554 557
555static struct net_proto_family inet6_family_ops = { 558static const struct net_proto_family inet6_family_ops = {
556 .family = PF_INET6, 559 .family = PF_INET6,
557 .create = inet6_create, 560 .create = inet6_create,
558 .owner = THIS_MODULE, 561 .owner = THIS_MODULE,
@@ -654,8 +657,9 @@ int inet6_sk_rebuild_header(struct sock *sk)
654 ipv6_addr_copy(&fl.fl6_src, &np->saddr); 657 ipv6_addr_copy(&fl.fl6_src, &np->saddr);
655 fl.fl6_flowlabel = np->flow_label; 658 fl.fl6_flowlabel = np->flow_label;
656 fl.oif = sk->sk_bound_dev_if; 659 fl.oif = sk->sk_bound_dev_if;
657 fl.fl_ip_dport = inet->dport; 660 fl.mark = sk->sk_mark;
658 fl.fl_ip_sport = inet->sport; 661 fl.fl_ip_dport = inet->inet_dport;
662 fl.fl_ip_sport = inet->inet_sport;
659 security_sk_classify_flow(sk, &fl); 663 security_sk_classify_flow(sk, &fl);
660 664
661 if (np->opt && np->opt->srcrt) { 665 if (np->opt && np->opt->srcrt) {
@@ -968,41 +972,41 @@ static void ipv6_packet_cleanup(void)
968 972
969static int __net_init ipv6_init_mibs(struct net *net) 973static int __net_init ipv6_init_mibs(struct net *net)
970{ 974{
971 if (snmp_mib_init((void **)net->mib.udp_stats_in6, 975 if (snmp_mib_init((void __percpu **)net->mib.udp_stats_in6,
972 sizeof (struct udp_mib)) < 0) 976 sizeof (struct udp_mib)) < 0)
973 return -ENOMEM; 977 return -ENOMEM;
974 if (snmp_mib_init((void **)net->mib.udplite_stats_in6, 978 if (snmp_mib_init((void __percpu **)net->mib.udplite_stats_in6,
975 sizeof (struct udp_mib)) < 0) 979 sizeof (struct udp_mib)) < 0)
976 goto err_udplite_mib; 980 goto err_udplite_mib;
977 if (snmp_mib_init((void **)net->mib.ipv6_statistics, 981 if (snmp_mib_init((void __percpu **)net->mib.ipv6_statistics,
978 sizeof(struct ipstats_mib)) < 0) 982 sizeof(struct ipstats_mib)) < 0)
979 goto err_ip_mib; 983 goto err_ip_mib;
980 if (snmp_mib_init((void **)net->mib.icmpv6_statistics, 984 if (snmp_mib_init((void __percpu **)net->mib.icmpv6_statistics,
981 sizeof(struct icmpv6_mib)) < 0) 985 sizeof(struct icmpv6_mib)) < 0)
982 goto err_icmp_mib; 986 goto err_icmp_mib;
983 if (snmp_mib_init((void **)net->mib.icmpv6msg_statistics, 987 if (snmp_mib_init((void __percpu **)net->mib.icmpv6msg_statistics,
984 sizeof(struct icmpv6msg_mib)) < 0) 988 sizeof(struct icmpv6msg_mib)) < 0)
985 goto err_icmpmsg_mib; 989 goto err_icmpmsg_mib;
986 return 0; 990 return 0;
987 991
988err_icmpmsg_mib: 992err_icmpmsg_mib:
989 snmp_mib_free((void **)net->mib.icmpv6_statistics); 993 snmp_mib_free((void __percpu **)net->mib.icmpv6_statistics);
990err_icmp_mib: 994err_icmp_mib:
991 snmp_mib_free((void **)net->mib.ipv6_statistics); 995 snmp_mib_free((void __percpu **)net->mib.ipv6_statistics);
992err_ip_mib: 996err_ip_mib:
993 snmp_mib_free((void **)net->mib.udplite_stats_in6); 997 snmp_mib_free((void __percpu **)net->mib.udplite_stats_in6);
994err_udplite_mib: 998err_udplite_mib:
995 snmp_mib_free((void **)net->mib.udp_stats_in6); 999 snmp_mib_free((void __percpu **)net->mib.udp_stats_in6);
996 return -ENOMEM; 1000 return -ENOMEM;
997} 1001}
998 1002
999static void __net_exit ipv6_cleanup_mibs(struct net *net) 1003static void ipv6_cleanup_mibs(struct net *net)
1000{ 1004{
1001 snmp_mib_free((void **)net->mib.udp_stats_in6); 1005 snmp_mib_free((void __percpu **)net->mib.udp_stats_in6);
1002 snmp_mib_free((void **)net->mib.udplite_stats_in6); 1006 snmp_mib_free((void __percpu **)net->mib.udplite_stats_in6);
1003 snmp_mib_free((void **)net->mib.ipv6_statistics); 1007 snmp_mib_free((void __percpu **)net->mib.ipv6_statistics);
1004 snmp_mib_free((void **)net->mib.icmpv6_statistics); 1008 snmp_mib_free((void __percpu **)net->mib.icmpv6_statistics);
1005 snmp_mib_free((void **)net->mib.icmpv6msg_statistics); 1009 snmp_mib_free((void __percpu **)net->mib.icmpv6msg_statistics);
1006} 1010}
1007 1011
1008static int __net_init inet6_net_init(struct net *net) 1012static int __net_init inet6_net_init(struct net *net)
@@ -1039,7 +1043,7 @@ out:
1039#endif 1043#endif
1040} 1044}
1041 1045
1042static void inet6_net_exit(struct net *net) 1046static void __net_exit inet6_net_exit(struct net *net)
1043{ 1047{
1044#ifdef CONFIG_PROC_FS 1048#ifdef CONFIG_PROC_FS
1045 udp6_proc_exit(net); 1049 udp6_proc_exit(net);