ipv6_sockglue.c (9d066a252786e1a18484a6283f82614d42a9f4ac) | ipv6_sockglue.c (ceba1832b1b2da0149c51de62a847c00bca1677a) |
---|---|
1/* 2 * IPv6 BSD socket options interface 3 * Linux INET6 implementation 4 * 5 * Authors: 6 * Pedro Roque <roque@di.fc.ul.pt> 7 * 8 * Based on linux/net/ipv4/ip_sockglue.c --- 84 unchanged lines hidden (view full) --- 93 new_ra->sel = sel; 94 new_ra->next = ra; 95 *rap = new_ra; 96 sock_hold(sk); 97 write_unlock_bh(&ip6_ra_lock); 98 return 0; 99} 100 | 1/* 2 * IPv6 BSD socket options interface 3 * Linux INET6 implementation 4 * 5 * Authors: 6 * Pedro Roque <roque@di.fc.ul.pt> 7 * 8 * Based on linux/net/ipv4/ip_sockglue.c --- 84 unchanged lines hidden (view full) --- 93 new_ra->sel = sel; 94 new_ra->next = ra; 95 *rap = new_ra; 96 sock_hold(sk); 97 write_unlock_bh(&ip6_ra_lock); 98 return 0; 99} 100 |
101static | |
102struct ipv6_txoptions *ipv6_update_options(struct sock *sk, 103 struct ipv6_txoptions *opt) 104{ 105 if (inet_sk(sk)->is_icsk) { 106 if (opt && 107 !((1 << sk->sk_state) & (TCPF_LISTEN | TCPF_CLOSE)) && 108 inet_sk(sk)->inet_daddr != LOOPBACK4_IPV6) { 109 struct inet_connection_sock *icsk = inet_csk(sk); --- 292 unchanged lines hidden (view full) --- 402 optlen & 0x7 || optlen > 8 * 255) 403 goto e_inval; 404 405 /* hop-by-hop / destination options are privileged option */ 406 retv = -EPERM; 407 if (optname != IPV6_RTHDR && !ns_capable(net->user_ns, CAP_NET_RAW)) 408 break; 409 | 101struct ipv6_txoptions *ipv6_update_options(struct sock *sk, 102 struct ipv6_txoptions *opt) 103{ 104 if (inet_sk(sk)->is_icsk) { 105 if (opt && 106 !((1 << sk->sk_state) & (TCPF_LISTEN | TCPF_CLOSE)) && 107 inet_sk(sk)->inet_daddr != LOOPBACK4_IPV6) { 108 struct inet_connection_sock *icsk = inet_csk(sk); --- 292 unchanged lines hidden (view full) --- 401 optlen & 0x7 || optlen > 8 * 255) 402 goto e_inval; 403 404 /* hop-by-hop / destination options are privileged option */ 405 retv = -EPERM; 406 if (optname != IPV6_RTHDR && !ns_capable(net->user_ns, CAP_NET_RAW)) 407 break; 408 |
410 opt = rcu_dereference_protected(np->opt, 411 lockdep_sock_is_held(sk)); | 409 opt = rcu_dereference_protected(np->opt, sock_owned_by_user(sk)); |
412 opt = ipv6_renew_options(sk, opt, optname, 413 (struct ipv6_opt_hdr __user *)optval, 414 optlen); 415 if (IS_ERR(opt)) { 416 retv = PTR_ERR(opt); 417 break; 418 } 419 --- 47 unchanged lines hidden (view full) --- 467 break; 468 } 469 470 case IPV6_2292PKTOPTIONS: 471 { 472 struct ipv6_txoptions *opt = NULL; 473 struct msghdr msg; 474 struct flowi6 fl6; | 410 opt = ipv6_renew_options(sk, opt, optname, 411 (struct ipv6_opt_hdr __user *)optval, 412 optlen); 413 if (IS_ERR(opt)) { 414 retv = PTR_ERR(opt); 415 break; 416 } 417 --- 47 unchanged lines hidden (view full) --- 465 break; 466 } 467 468 case IPV6_2292PKTOPTIONS: 469 { 470 struct ipv6_txoptions *opt = NULL; 471 struct msghdr msg; 472 struct flowi6 fl6; |
475 struct sockcm_cookie sockc_junk; 476 struct ipcm6_cookie ipc6; | 473 int junk; |
477 478 memset(&fl6, 0, sizeof(fl6)); 479 fl6.flowi6_oif = sk->sk_bound_dev_if; 480 fl6.flowi6_mark = sk->sk_mark; 481 482 if (optlen == 0) 483 goto update; 484 --- 13 unchanged lines hidden (view full) --- 498 atomic_set(&opt->refcnt, 1); 499 opt->tot_len = sizeof(*opt) + optlen; 500 retv = -EFAULT; 501 if (copy_from_user(opt+1, optval, optlen)) 502 goto done; 503 504 msg.msg_controllen = optlen; 505 msg.msg_control = (void *)(opt+1); | 474 475 memset(&fl6, 0, sizeof(fl6)); 476 fl6.flowi6_oif = sk->sk_bound_dev_if; 477 fl6.flowi6_mark = sk->sk_mark; 478 479 if (optlen == 0) 480 goto update; 481 --- 13 unchanged lines hidden (view full) --- 495 atomic_set(&opt->refcnt, 1); 496 opt->tot_len = sizeof(*opt) + optlen; 497 retv = -EFAULT; 498 if (copy_from_user(opt+1, optval, optlen)) 499 goto done; 500 501 msg.msg_controllen = optlen; 502 msg.msg_control = (void *)(opt+1); |
506 ipc6.opt = opt; | |
507 | 503 |
508 retv = ip6_datagram_send_ctl(net, sk, &msg, &fl6, &ipc6, &sockc_junk); | 504 retv = ip6_datagram_send_ctl(net, sk, &msg, &fl6, opt, &junk, 505 &junk, &junk); |
509 if (retv) 510 goto done; 511update: 512 retv = 0; 513 opt = ipv6_update_options(sk, opt); 514done: 515 if (opt) { 516 atomic_sub(opt->tot_len, &sk->sk_omem_alloc); --- 603 unchanged lines hidden (view full) --- 1120 case IPV6_HOPOPTS: 1121 case IPV6_RTHDRDSTOPTS: 1122 case IPV6_RTHDR: 1123 case IPV6_DSTOPTS: 1124 { 1125 struct ipv6_txoptions *opt; 1126 1127 lock_sock(sk); | 506 if (retv) 507 goto done; 508update: 509 retv = 0; 510 opt = ipv6_update_options(sk, opt); 511done: 512 if (opt) { 513 atomic_sub(opt->tot_len, &sk->sk_omem_alloc); --- 603 unchanged lines hidden (view full) --- 1117 case IPV6_HOPOPTS: 1118 case IPV6_RTHDRDSTOPTS: 1119 case IPV6_RTHDR: 1120 case IPV6_DSTOPTS: 1121 { 1122 struct ipv6_txoptions *opt; 1123 1124 lock_sock(sk); |
1128 opt = rcu_dereference_protected(np->opt, 1129 lockdep_sock_is_held(sk)); | 1125 opt = rcu_dereference_protected(np->opt, sock_owned_by_user(sk)); |
1130 len = ipv6_getsockopt_sticky(sk, opt, optname, optval, len); 1131 release_sock(sk); 1132 /* check if ipv6_getsockopt_sticky() returns err code */ 1133 if (len < 0) 1134 return len; 1135 return put_user(len, optlen); 1136 } 1137 --- 261 unchanged lines hidden --- | 1126 len = ipv6_getsockopt_sticky(sk, opt, optname, optval, len); 1127 release_sock(sk); 1128 /* check if ipv6_getsockopt_sticky() returns err code */ 1129 if (len < 0) 1130 return len; 1131 return put_user(len, optlen); 1132 } 1133 --- 261 unchanged lines hidden --- |