diff options
author | Andrea Bastoni <bastoni@cs.unc.edu> | 2010-05-30 19:16:45 -0400 |
---|---|---|
committer | Andrea Bastoni <bastoni@cs.unc.edu> | 2010-05-30 19:16:45 -0400 |
commit | ada47b5fe13d89735805b566185f4885f5a3f750 (patch) | |
tree | 644b88f8a71896307d71438e9b3af49126ffb22b /net/ipv6/af_inet6.c | |
parent | 43e98717ad40a4ae64545b5ba047c7b86aa44f4f (diff) | |
parent | 3280f21d43ee541f97f8cda5792150d2dbec20d5 (diff) |
Merge branch 'wip-2.6.34' into old-private-masterarchived-private-master
Diffstat (limited to 'net/ipv6/af_inet6.c')
-rw-r--r-- | net/ipv6/af_inet6.c | 88 |
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 | ||
98 | static int inet6_create(struct net *net, struct socket *sock, int protocol) | 99 | static 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; |
381 | out: | 381 | out: |
382 | release_sock(sk); | 382 | release_sock(sk); |
383 | return err; | 383 | return err; |
384 | out_unlock: | ||
385 | rcu_read_unlock(); | ||
386 | goto out; | ||
384 | } | 387 | } |
385 | 388 | ||
386 | EXPORT_SYMBOL(inet6_bind); | 389 | EXPORT_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 | ||
555 | static struct net_proto_family inet6_family_ops = { | 558 | static 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 | ||
969 | static int __net_init ipv6_init_mibs(struct net *net) | 973 | static 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 | ||
988 | err_icmpmsg_mib: | 992 | err_icmpmsg_mib: |
989 | snmp_mib_free((void **)net->mib.icmpv6_statistics); | 993 | snmp_mib_free((void __percpu **)net->mib.icmpv6_statistics); |
990 | err_icmp_mib: | 994 | err_icmp_mib: |
991 | snmp_mib_free((void **)net->mib.ipv6_statistics); | 995 | snmp_mib_free((void __percpu **)net->mib.ipv6_statistics); |
992 | err_ip_mib: | 996 | err_ip_mib: |
993 | snmp_mib_free((void **)net->mib.udplite_stats_in6); | 997 | snmp_mib_free((void __percpu **)net->mib.udplite_stats_in6); |
994 | err_udplite_mib: | 998 | err_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 | ||
999 | static void __net_exit ipv6_cleanup_mibs(struct net *net) | 1003 | static 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 | ||
1008 | static int __net_init inet6_net_init(struct net *net) | 1012 | static int __net_init inet6_net_init(struct net *net) |
@@ -1039,7 +1043,7 @@ out: | |||
1039 | #endif | 1043 | #endif |
1040 | } | 1044 | } |
1041 | 1045 | ||
1042 | static void inet6_net_exit(struct net *net) | 1046 | static 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); |