diff options
Diffstat (limited to 'net/ipv6/af_inet6.c')
| -rw-r--r-- | net/ipv6/af_inet6.c | 53 |
1 files changed, 28 insertions, 25 deletions
diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c index e127a32f9540..12e69d364dd5 100644 --- a/net/ipv6/af_inet6.c +++ b/net/ipv6/af_inet6.c | |||
| @@ -95,7 +95,8 @@ static __inline__ struct ipv6_pinfo *inet6_sk_generic(struct sock *sk) | |||
| 95 | return (struct ipv6_pinfo *)(((u8 *)sk) + offset); | 95 | return (struct ipv6_pinfo *)(((u8 *)sk) + offset); |
| 96 | } | 96 | } |
| 97 | 97 | ||
| 98 | static int inet6_create(struct net *net, struct socket *sock, int protocol) | 98 | static int inet6_create(struct net *net, struct socket *sock, int protocol, |
| 99 | int kern) | ||
| 99 | { | 100 | { |
| 100 | struct inet_sock *inet; | 101 | struct inet_sock *inet; |
| 101 | struct ipv6_pinfo *np; | 102 | struct ipv6_pinfo *np; |
| @@ -158,7 +159,7 @@ lookup_protocol: | |||
| 158 | } | 159 | } |
| 159 | 160 | ||
| 160 | err = -EPERM; | 161 | err = -EPERM; |
| 161 | if (answer->capability > 0 && !capable(answer->capability)) | 162 | if (sock->type == SOCK_RAW && !kern && !capable(CAP_NET_RAW)) |
| 162 | goto out_rcu_unlock; | 163 | goto out_rcu_unlock; |
| 163 | 164 | ||
| 164 | sock->ops = answer->ops; | 165 | sock->ops = answer->ops; |
| @@ -185,7 +186,7 @@ lookup_protocol: | |||
| 185 | inet->is_icsk = (INET_PROTOSW_ICSK & answer_flags) != 0; | 186 | inet->is_icsk = (INET_PROTOSW_ICSK & answer_flags) != 0; |
| 186 | 187 | ||
| 187 | if (SOCK_RAW == sock->type) { | 188 | if (SOCK_RAW == sock->type) { |
| 188 | inet->num = protocol; | 189 | inet->inet_num = protocol; |
| 189 | if (IPPROTO_RAW == protocol) | 190 | if (IPPROTO_RAW == protocol) |
| 190 | inet->hdrincl = 1; | 191 | inet->hdrincl = 1; |
| 191 | } | 192 | } |
| @@ -228,12 +229,12 @@ lookup_protocol: | |||
| 228 | */ | 229 | */ |
| 229 | sk_refcnt_debug_inc(sk); | 230 | sk_refcnt_debug_inc(sk); |
| 230 | 231 | ||
| 231 | if (inet->num) { | 232 | if (inet->inet_num) { |
| 232 | /* It assumes that any protocol which allows | 233 | /* It assumes that any protocol which allows |
| 233 | * the user to assign a number at socket | 234 | * the user to assign a number at socket |
| 234 | * creation time automatically shares. | 235 | * creation time automatically shares. |
| 235 | */ | 236 | */ |
| 236 | inet->sport = htons(inet->num); | 237 | inet->inet_sport = htons(inet->inet_num); |
| 237 | sk->sk_prot->hash(sk); | 238 | sk->sk_prot->hash(sk); |
| 238 | } | 239 | } |
| 239 | if (sk->sk_prot->init) { | 240 | if (sk->sk_prot->init) { |
| @@ -281,7 +282,7 @@ int inet6_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) | |||
| 281 | lock_sock(sk); | 282 | lock_sock(sk); |
| 282 | 283 | ||
| 283 | /* Check these errors (active socket, double bind). */ | 284 | /* Check these errors (active socket, double bind). */ |
| 284 | if (sk->sk_state != TCP_CLOSE || inet->num) { | 285 | if (sk->sk_state != TCP_CLOSE || inet->inet_num) { |
| 285 | err = -EINVAL; | 286 | err = -EINVAL; |
| 286 | goto out; | 287 | goto out; |
| 287 | } | 288 | } |
| @@ -314,6 +315,7 @@ int inet6_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) | |||
| 314 | if (addr_type != IPV6_ADDR_ANY) { | 315 | if (addr_type != IPV6_ADDR_ANY) { |
| 315 | struct net_device *dev = NULL; | 316 | struct net_device *dev = NULL; |
| 316 | 317 | ||
| 318 | rcu_read_lock(); | ||
| 317 | if (addr_type & IPV6_ADDR_LINKLOCAL) { | 319 | if (addr_type & IPV6_ADDR_LINKLOCAL) { |
| 318 | if (addr_len >= sizeof(struct sockaddr_in6) && | 320 | if (addr_len >= sizeof(struct sockaddr_in6) && |
| 319 | addr->sin6_scope_id) { | 321 | addr->sin6_scope_id) { |
| @@ -326,12 +328,12 @@ int inet6_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) | |||
| 326 | /* Binding to link-local address requires an interface */ | 328 | /* Binding to link-local address requires an interface */ |
| 327 | if (!sk->sk_bound_dev_if) { | 329 | if (!sk->sk_bound_dev_if) { |
| 328 | err = -EINVAL; | 330 | err = -EINVAL; |
| 329 | goto out; | 331 | goto out_unlock; |
| 330 | } | 332 | } |
| 331 | dev = dev_get_by_index(net, sk->sk_bound_dev_if); | 333 | dev = dev_get_by_index_rcu(net, sk->sk_bound_dev_if); |
| 332 | if (!dev) { | 334 | if (!dev) { |
| 333 | err = -ENODEV; | 335 | err = -ENODEV; |
| 334 | goto out; | 336 | goto out_unlock; |
| 335 | } | 337 | } |
| 336 | } | 338 | } |
| 337 | 339 | ||
| @@ -342,19 +344,16 @@ int inet6_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) | |||
| 342 | if (!(addr_type & IPV6_ADDR_MULTICAST)) { | 344 | if (!(addr_type & IPV6_ADDR_MULTICAST)) { |
| 343 | if (!ipv6_chk_addr(net, &addr->sin6_addr, | 345 | if (!ipv6_chk_addr(net, &addr->sin6_addr, |
| 344 | dev, 0)) { | 346 | dev, 0)) { |
| 345 | if (dev) | ||
| 346 | dev_put(dev); | ||
| 347 | err = -EADDRNOTAVAIL; | 347 | err = -EADDRNOTAVAIL; |
| 348 | goto out; | 348 | goto out_unlock; |
| 349 | } | 349 | } |
| 350 | } | 350 | } |
| 351 | if (dev) | 351 | rcu_read_unlock(); |
| 352 | dev_put(dev); | ||
| 353 | } | 352 | } |
| 354 | } | 353 | } |
| 355 | 354 | ||
| 356 | inet->rcv_saddr = v4addr; | 355 | inet->inet_rcv_saddr = v4addr; |
| 357 | inet->saddr = v4addr; | 356 | inet->inet_saddr = v4addr; |
| 358 | 357 | ||
| 359 | ipv6_addr_copy(&np->rcv_saddr, &addr->sin6_addr); | 358 | ipv6_addr_copy(&np->rcv_saddr, &addr->sin6_addr); |
| 360 | 359 | ||
| @@ -375,12 +374,15 @@ int inet6_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) | |||
| 375 | } | 374 | } |
| 376 | if (snum) | 375 | if (snum) |
| 377 | sk->sk_userlocks |= SOCK_BINDPORT_LOCK; | 376 | sk->sk_userlocks |= SOCK_BINDPORT_LOCK; |
| 378 | inet->sport = htons(inet->num); | 377 | inet->inet_sport = htons(inet->inet_num); |
| 379 | inet->dport = 0; | 378 | inet->inet_dport = 0; |
| 380 | inet->daddr = 0; | 379 | inet->inet_daddr = 0; |
| 381 | out: | 380 | out: |
| 382 | release_sock(sk); | 381 | release_sock(sk); |
| 383 | return err; | 382 | return err; |
| 383 | out_unlock: | ||
| 384 | rcu_read_unlock(); | ||
| 385 | goto out; | ||
| 384 | } | 386 | } |
| 385 | 387 | ||
| 386 | EXPORT_SYMBOL(inet6_bind); | 388 | EXPORT_SYMBOL(inet6_bind); |
| @@ -441,12 +443,12 @@ int inet6_getname(struct socket *sock, struct sockaddr *uaddr, | |||
| 441 | sin->sin6_flowinfo = 0; | 443 | sin->sin6_flowinfo = 0; |
| 442 | sin->sin6_scope_id = 0; | 444 | sin->sin6_scope_id = 0; |
| 443 | if (peer) { | 445 | if (peer) { |
| 444 | if (!inet->dport) | 446 | if (!inet->inet_dport) |
| 445 | return -ENOTCONN; | 447 | return -ENOTCONN; |
| 446 | if (((1 << sk->sk_state) & (TCPF_CLOSE | TCPF_SYN_SENT)) && | 448 | if (((1 << sk->sk_state) & (TCPF_CLOSE | TCPF_SYN_SENT)) && |
| 447 | peer == 1) | 449 | peer == 1) |
| 448 | return -ENOTCONN; | 450 | return -ENOTCONN; |
| 449 | sin->sin6_port = inet->dport; | 451 | sin->sin6_port = inet->inet_dport; |
| 450 | ipv6_addr_copy(&sin->sin6_addr, &np->daddr); | 452 | ipv6_addr_copy(&sin->sin6_addr, &np->daddr); |
| 451 | if (np->sndflow) | 453 | if (np->sndflow) |
| 452 | sin->sin6_flowinfo = np->flow_label; | 454 | sin->sin6_flowinfo = np->flow_label; |
| @@ -456,7 +458,7 @@ int inet6_getname(struct socket *sock, struct sockaddr *uaddr, | |||
| 456 | else | 458 | else |
| 457 | ipv6_addr_copy(&sin->sin6_addr, &np->rcv_saddr); | 459 | ipv6_addr_copy(&sin->sin6_addr, &np->rcv_saddr); |
| 458 | 460 | ||
| 459 | sin->sin6_port = inet->sport; | 461 | sin->sin6_port = inet->inet_sport; |
| 460 | } | 462 | } |
| 461 | if (ipv6_addr_type(&sin->sin6_addr) & IPV6_ADDR_LINKLOCAL) | 463 | if (ipv6_addr_type(&sin->sin6_addr) & IPV6_ADDR_LINKLOCAL) |
| 462 | sin->sin6_scope_id = sk->sk_bound_dev_if; | 464 | sin->sin6_scope_id = sk->sk_bound_dev_if; |
| @@ -552,7 +554,7 @@ const struct proto_ops inet6_dgram_ops = { | |||
| 552 | #endif | 554 | #endif |
| 553 | }; | 555 | }; |
| 554 | 556 | ||
| 555 | static struct net_proto_family inet6_family_ops = { | 557 | static const struct net_proto_family inet6_family_ops = { |
| 556 | .family = PF_INET6, | 558 | .family = PF_INET6, |
| 557 | .create = inet6_create, | 559 | .create = inet6_create, |
| 558 | .owner = THIS_MODULE, | 560 | .owner = THIS_MODULE, |
| @@ -654,8 +656,9 @@ int inet6_sk_rebuild_header(struct sock *sk) | |||
| 654 | ipv6_addr_copy(&fl.fl6_src, &np->saddr); | 656 | ipv6_addr_copy(&fl.fl6_src, &np->saddr); |
| 655 | fl.fl6_flowlabel = np->flow_label; | 657 | fl.fl6_flowlabel = np->flow_label; |
| 656 | fl.oif = sk->sk_bound_dev_if; | 658 | fl.oif = sk->sk_bound_dev_if; |
| 657 | fl.fl_ip_dport = inet->dport; | 659 | fl.mark = sk->sk_mark; |
| 658 | fl.fl_ip_sport = inet->sport; | 660 | fl.fl_ip_dport = inet->inet_dport; |
| 661 | fl.fl_ip_sport = inet->inet_sport; | ||
| 659 | security_sk_classify_flow(sk, &fl); | 662 | security_sk_classify_flow(sk, &fl); |
| 660 | 663 | ||
| 661 | if (np->opt && np->opt->srcrt) { | 664 | if (np->opt && np->opt->srcrt) { |
