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.c53
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
98static int inet6_create(struct net *net, struct socket *sock, int protocol) 98static 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;
381out: 380out:
382 release_sock(sk); 381 release_sock(sk);
383 return err; 382 return err;
383out_unlock:
384 rcu_read_unlock();
385 goto out;
384} 386}
385 387
386EXPORT_SYMBOL(inet6_bind); 388EXPORT_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
555static struct net_proto_family inet6_family_ops = { 557static 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) {