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 9 * 10 * $Id: ipv6_sockglue.c,v 1.41 2002/02/01 22:01:04 davem Exp $ 11 * 12 * This program is free software; you can redistribute it and/or 13 * modify it under the terms of the GNU General Public License 14 * as published by the Free Software Foundation; either version 15 * 2 of the License, or (at your option) any later version. 16 * 17 * FIXME: Make the setsockopt code POSIX compliant: That is 18 * 19 * o Return -EINVAL for setsockopt of short lengths 20 * o Truncate getsockopt returns 21 * o Return an optlen of the truncated length if need be 22 * 23 * Changes: 24 * David L Stevens <dlstevens@us.ibm.com>: 25 * - added multicast source filtering API for MLDv2 26 */ 27 28 #include <linux/module.h> 29 #include <linux/config.h> 30 #include <linux/errno.h> 31 #include <linux/types.h> 32 #include <linux/socket.h> 33 #include <linux/sockios.h> 34 #include <linux/sched.h> 35 #include <linux/net.h> 36 #include <linux/in6.h> 37 #include <linux/netdevice.h> 38 #include <linux/if_arp.h> 39 #include <linux/init.h> 40 #include <linux/sysctl.h> 41 #include <linux/netfilter.h> 42 43 #include <net/sock.h> 44 #include <net/snmp.h> 45 #include <net/ipv6.h> 46 #include <net/ndisc.h> 47 #include <net/protocol.h> 48 #include <net/transp_v6.h> 49 #include <net/ip6_route.h> 50 #include <net/addrconf.h> 51 #include <net/inet_common.h> 52 #include <net/tcp.h> 53 #include <net/udp.h> 54 #include <net/xfrm.h> 55 56 #include <asm/uaccess.h> 57 58 DEFINE_SNMP_STAT(struct ipstats_mib, ipv6_statistics); 59 60 static struct packet_type ipv6_packet_type = { 61 .type = __constant_htons(ETH_P_IPV6), 62 .func = ipv6_rcv, 63 }; 64 65 struct ip6_ra_chain *ip6_ra_chain; 66 DEFINE_RWLOCK(ip6_ra_lock); 67 68 int ip6_ra_control(struct sock *sk, int sel, void (*destructor)(struct sock *)) 69 { 70 struct ip6_ra_chain *ra, *new_ra, **rap; 71 72 /* RA packet may be delivered ONLY to IPPROTO_RAW socket */ 73 if (sk->sk_type != SOCK_RAW || inet_sk(sk)->num != IPPROTO_RAW) 74 return -EINVAL; 75 76 new_ra = (sel>=0) ? kmalloc(sizeof(*new_ra), GFP_KERNEL) : NULL; 77 78 write_lock_bh(&ip6_ra_lock); 79 for (rap = &ip6_ra_chain; (ra=*rap) != NULL; rap = &ra->next) { 80 if (ra->sk == sk) { 81 if (sel>=0) { 82 write_unlock_bh(&ip6_ra_lock); 83 if (new_ra) 84 kfree(new_ra); 85 return -EADDRINUSE; 86 } 87 88 *rap = ra->next; 89 write_unlock_bh(&ip6_ra_lock); 90 91 if (ra->destructor) 92 ra->destructor(sk); 93 sock_put(sk); 94 kfree(ra); 95 return 0; 96 } 97 } 98 if (new_ra == NULL) { 99 write_unlock_bh(&ip6_ra_lock); 100 return -ENOBUFS; 101 } 102 new_ra->sk = sk; 103 new_ra->sel = sel; 104 new_ra->destructor = destructor; 105 new_ra->next = ra; 106 *rap = new_ra; 107 sock_hold(sk); 108 write_unlock_bh(&ip6_ra_lock); 109 return 0; 110 } 111 112 extern int ip6_mc_source(int add, int omode, struct sock *sk, 113 struct group_source_req *pgsr); 114 extern int ip6_mc_msfilter(struct sock *sk, struct group_filter *gsf); 115 extern int ip6_mc_msfget(struct sock *sk, struct group_filter *gsf, 116 struct group_filter __user *optval, int __user *optlen); 117 118 119 int ipv6_setsockopt(struct sock *sk, int level, int optname, 120 char __user *optval, int optlen) 121 { 122 struct ipv6_pinfo *np = inet6_sk(sk); 123 int val, valbool; 124 int retv = -ENOPROTOOPT; 125 126 if (level == SOL_IP && sk->sk_type != SOCK_RAW) 127 return udp_prot.setsockopt(sk, level, optname, optval, optlen); 128 129 if(level!=SOL_IPV6) 130 goto out; 131 132 if (optval == NULL) 133 val=0; 134 else if (get_user(val, (int __user *) optval)) 135 return -EFAULT; 136 137 valbool = (val!=0); 138 139 lock_sock(sk); 140 141 switch (optname) { 142 143 case IPV6_ADDRFORM: 144 if (val == PF_INET) { 145 struct ipv6_txoptions *opt; 146 struct sk_buff *pktopt; 147 148 if (sk->sk_protocol != IPPROTO_UDP && 149 sk->sk_protocol != IPPROTO_TCP) 150 break; 151 152 if (sk->sk_state != TCP_ESTABLISHED) { 153 retv = -ENOTCONN; 154 break; 155 } 156 157 if (ipv6_only_sock(sk) || 158 !(ipv6_addr_type(&np->daddr) & IPV6_ADDR_MAPPED)) { 159 retv = -EADDRNOTAVAIL; 160 break; 161 } 162 163 fl6_free_socklist(sk); 164 ipv6_sock_mc_close(sk); 165 166 /* 167 * Sock is moving from IPv6 to IPv4 (sk_prot), so 168 * remove it from the refcnt debug socks count in the 169 * original family... 170 */ 171 sk_refcnt_debug_dec(sk); 172 173 if (sk->sk_protocol == IPPROTO_TCP) { 174 struct tcp_sock *tp = tcp_sk(sk); 175 176 local_bh_disable(); 177 sock_prot_dec_use(sk->sk_prot); 178 sock_prot_inc_use(&tcp_prot); 179 local_bh_enable(); 180 sk->sk_prot = &tcp_prot; 181 tp->af_specific = &ipv4_specific; 182 sk->sk_socket->ops = &inet_stream_ops; 183 sk->sk_family = PF_INET; 184 tcp_sync_mss(sk, tp->pmtu_cookie); 185 } else { 186 local_bh_disable(); 187 sock_prot_dec_use(sk->sk_prot); 188 sock_prot_inc_use(&udp_prot); 189 local_bh_enable(); 190 sk->sk_prot = &udp_prot; 191 sk->sk_socket->ops = &inet_dgram_ops; 192 sk->sk_family = PF_INET; 193 } 194 opt = xchg(&np->opt, NULL); 195 if (opt) 196 sock_kfree_s(sk, opt, opt->tot_len); 197 pktopt = xchg(&np->pktoptions, NULL); 198 if (pktopt) 199 kfree_skb(pktopt); 200 201 sk->sk_destruct = inet_sock_destruct; 202 /* 203 * ... and add it to the refcnt debug socks count 204 * in the new family. -acme 205 */ 206 sk_refcnt_debug_inc(sk); 207 module_put(THIS_MODULE); 208 retv = 0; 209 break; 210 } 211 goto e_inval; 212 213 case IPV6_V6ONLY: 214 if (inet_sk(sk)->num) 215 goto e_inval; 216 np->ipv6only = valbool; 217 retv = 0; 218 break; 219 220 case IPV6_PKTINFO: 221 np->rxopt.bits.rxinfo = valbool; 222 retv = 0; 223 break; 224 225 case IPV6_HOPLIMIT: 226 np->rxopt.bits.rxhlim = valbool; 227 retv = 0; 228 break; 229 230 case IPV6_RTHDR: 231 if (val < 0 || val > 2) 232 goto e_inval; 233 np->rxopt.bits.srcrt = val; 234 retv = 0; 235 break; 236 237 case IPV6_HOPOPTS: 238 np->rxopt.bits.hopopts = valbool; 239 retv = 0; 240 break; 241 242 case IPV6_DSTOPTS: 243 np->rxopt.bits.dstopts = valbool; 244 retv = 0; 245 break; 246 247 case IPV6_FLOWINFO: 248 np->rxopt.bits.rxflow = valbool; 249 retv = 0; 250 break; 251 252 case IPV6_PKTOPTIONS: 253 { 254 struct ipv6_txoptions *opt = NULL; 255 struct msghdr msg; 256 struct flowi fl; 257 int junk; 258 259 fl.fl6_flowlabel = 0; 260 fl.oif = sk->sk_bound_dev_if; 261 262 if (optlen == 0) 263 goto update; 264 265 /* 1K is probably excessive 266 * 1K is surely not enough, 2K per standard header is 16K. 267 */ 268 retv = -EINVAL; 269 if (optlen > 64*1024) 270 break; 271 272 opt = sock_kmalloc(sk, sizeof(*opt) + optlen, GFP_KERNEL); 273 retv = -ENOBUFS; 274 if (opt == NULL) 275 break; 276 277 memset(opt, 0, sizeof(*opt)); 278 opt->tot_len = sizeof(*opt) + optlen; 279 retv = -EFAULT; 280 if (copy_from_user(opt+1, optval, optlen)) 281 goto done; 282 283 msg.msg_controllen = optlen; 284 msg.msg_control = (void*)(opt+1); 285 286 retv = datagram_send_ctl(&msg, &fl, opt, &junk); 287 if (retv) 288 goto done; 289 update: 290 retv = 0; 291 if (sk->sk_type == SOCK_STREAM) { 292 if (opt) { 293 struct tcp_sock *tp = tcp_sk(sk); 294 if (!((1 << sk->sk_state) & 295 (TCPF_LISTEN | TCPF_CLOSE)) 296 && inet_sk(sk)->daddr != LOOPBACK4_IPV6) { 297 tp->ext_header_len = opt->opt_flen + opt->opt_nflen; 298 tcp_sync_mss(sk, tp->pmtu_cookie); 299 } 300 } 301 opt = xchg(&np->opt, opt); 302 sk_dst_reset(sk); 303 } else { 304 write_lock(&sk->sk_dst_lock); 305 opt = xchg(&np->opt, opt); 306 write_unlock(&sk->sk_dst_lock); 307 sk_dst_reset(sk); 308 } 309 310 done: 311 if (opt) 312 sock_kfree_s(sk, opt, opt->tot_len); 313 break; 314 } 315 case IPV6_UNICAST_HOPS: 316 if (val > 255 || val < -1) 317 goto e_inval; 318 np->hop_limit = val; 319 retv = 0; 320 break; 321 322 case IPV6_MULTICAST_HOPS: 323 if (sk->sk_type == SOCK_STREAM) 324 goto e_inval; 325 if (val > 255 || val < -1) 326 goto e_inval; 327 np->mcast_hops = val; 328 retv = 0; 329 break; 330 331 case IPV6_MULTICAST_LOOP: 332 np->mc_loop = valbool; 333 retv = 0; 334 break; 335 336 case IPV6_MULTICAST_IF: 337 if (sk->sk_type == SOCK_STREAM) 338 goto e_inval; 339 if (sk->sk_bound_dev_if && sk->sk_bound_dev_if != val) 340 goto e_inval; 341 342 if (__dev_get_by_index(val) == NULL) { 343 retv = -ENODEV; 344 break; 345 } 346 np->mcast_oif = val; 347 retv = 0; 348 break; 349 case IPV6_ADD_MEMBERSHIP: 350 case IPV6_DROP_MEMBERSHIP: 351 { 352 struct ipv6_mreq mreq; 353 354 retv = -EFAULT; 355 if (copy_from_user(&mreq, optval, sizeof(struct ipv6_mreq))) 356 break; 357 358 if (optname == IPV6_ADD_MEMBERSHIP) 359 retv = ipv6_sock_mc_join(sk, mreq.ipv6mr_ifindex, &mreq.ipv6mr_multiaddr); 360 else 361 retv = ipv6_sock_mc_drop(sk, mreq.ipv6mr_ifindex, &mreq.ipv6mr_multiaddr); 362 break; 363 } 364 case IPV6_JOIN_ANYCAST: 365 case IPV6_LEAVE_ANYCAST: 366 { 367 struct ipv6_mreq mreq; 368 369 if (optlen != sizeof(struct ipv6_mreq)) 370 goto e_inval; 371 372 retv = -EFAULT; 373 if (copy_from_user(&mreq, optval, sizeof(struct ipv6_mreq))) 374 break; 375 376 if (optname == IPV6_JOIN_ANYCAST) 377 retv = ipv6_sock_ac_join(sk, mreq.ipv6mr_ifindex, &mreq.ipv6mr_acaddr); 378 else 379 retv = ipv6_sock_ac_drop(sk, mreq.ipv6mr_ifindex, &mreq.ipv6mr_acaddr); 380 break; 381 } 382 case MCAST_JOIN_GROUP: 383 case MCAST_LEAVE_GROUP: 384 { 385 struct group_req greq; 386 struct sockaddr_in6 *psin6; 387 388 retv = -EFAULT; 389 if (copy_from_user(&greq, optval, sizeof(struct group_req))) 390 break; 391 if (greq.gr_group.ss_family != AF_INET6) { 392 retv = -EADDRNOTAVAIL; 393 break; 394 } 395 psin6 = (struct sockaddr_in6 *)&greq.gr_group; 396 if (optname == MCAST_JOIN_GROUP) 397 retv = ipv6_sock_mc_join(sk, greq.gr_interface, 398 &psin6->sin6_addr); 399 else 400 retv = ipv6_sock_mc_drop(sk, greq.gr_interface, 401 &psin6->sin6_addr); 402 break; 403 } 404 case MCAST_JOIN_SOURCE_GROUP: 405 case MCAST_LEAVE_SOURCE_GROUP: 406 case MCAST_BLOCK_SOURCE: 407 case MCAST_UNBLOCK_SOURCE: 408 { 409 struct group_source_req greqs; 410 int omode, add; 411 412 if (optlen != sizeof(struct group_source_req)) 413 goto e_inval; 414 if (copy_from_user(&greqs, optval, sizeof(greqs))) { 415 retv = -EFAULT; 416 break; 417 } 418 if (greqs.gsr_group.ss_family != AF_INET6 || 419 greqs.gsr_source.ss_family != AF_INET6) { 420 retv = -EADDRNOTAVAIL; 421 break; 422 } 423 if (optname == MCAST_BLOCK_SOURCE) { 424 omode = MCAST_EXCLUDE; 425 add = 1; 426 } else if (optname == MCAST_UNBLOCK_SOURCE) { 427 omode = MCAST_EXCLUDE; 428 add = 0; 429 } else if (optname == MCAST_JOIN_SOURCE_GROUP) { 430 struct sockaddr_in6 *psin6; 431 432 psin6 = (struct sockaddr_in6 *)&greqs.gsr_group; 433 retv = ipv6_sock_mc_join(sk, greqs.gsr_interface, 434 &psin6->sin6_addr); 435 /* prior join w/ different source is ok */ 436 if (retv && retv != -EADDRINUSE) 437 break; 438 omode = MCAST_INCLUDE; 439 add = 1; 440 } else /* MCAST_LEAVE_SOURCE_GROUP */ { 441 omode = MCAST_INCLUDE; 442 add = 0; 443 } 444 retv = ip6_mc_source(add, omode, sk, &greqs); 445 break; 446 } 447 case MCAST_MSFILTER: 448 { 449 extern int sysctl_optmem_max; 450 extern int sysctl_mld_max_msf; 451 struct group_filter *gsf; 452 453 if (optlen < GROUP_FILTER_SIZE(0)) 454 goto e_inval; 455 if (optlen > sysctl_optmem_max) { 456 retv = -ENOBUFS; 457 break; 458 } 459 gsf = (struct group_filter *)kmalloc(optlen,GFP_KERNEL); 460 if (gsf == 0) { 461 retv = -ENOBUFS; 462 break; 463 } 464 retv = -EFAULT; 465 if (copy_from_user(gsf, optval, optlen)) { 466 kfree(gsf); 467 break; 468 } 469 /* numsrc >= (4G-140)/128 overflow in 32 bits */ 470 if (gsf->gf_numsrc >= 0x1ffffffU || 471 gsf->gf_numsrc > sysctl_mld_max_msf) { 472 kfree(gsf); 473 retv = -ENOBUFS; 474 break; 475 } 476 if (GROUP_FILTER_SIZE(gsf->gf_numsrc) > optlen) { 477 kfree(gsf); 478 retv = -EINVAL; 479 break; 480 } 481 retv = ip6_mc_msfilter(sk, gsf); 482 kfree(gsf); 483 484 break; 485 } 486 case IPV6_ROUTER_ALERT: 487 retv = ip6_ra_control(sk, val, NULL); 488 break; 489 case IPV6_MTU_DISCOVER: 490 if (val<0 || val>2) 491 goto e_inval; 492 np->pmtudisc = val; 493 retv = 0; 494 break; 495 case IPV6_MTU: 496 if (val && val < IPV6_MIN_MTU) 497 goto e_inval; 498 np->frag_size = val; 499 retv = 0; 500 break; 501 case IPV6_RECVERR: 502 np->recverr = valbool; 503 if (!val) 504 skb_queue_purge(&sk->sk_error_queue); 505 retv = 0; 506 break; 507 case IPV6_FLOWINFO_SEND: 508 np->sndflow = valbool; 509 retv = 0; 510 break; 511 case IPV6_FLOWLABEL_MGR: 512 retv = ipv6_flowlabel_opt(sk, optval, optlen); 513 break; 514 case IPV6_IPSEC_POLICY: 515 case IPV6_XFRM_POLICY: 516 retv = -EPERM; 517 if (!capable(CAP_NET_ADMIN)) 518 break; 519 retv = xfrm_user_policy(sk, optname, optval, optlen); 520 break; 521 522 #ifdef CONFIG_NETFILTER 523 default: 524 retv = nf_setsockopt(sk, PF_INET6, optname, optval, 525 optlen); 526 break; 527 #endif 528 529 } 530 release_sock(sk); 531 532 out: 533 return retv; 534 535 e_inval: 536 release_sock(sk); 537 return -EINVAL; 538 } 539 540 int ipv6_getsockopt(struct sock *sk, int level, int optname, 541 char __user *optval, int __user *optlen) 542 { 543 struct ipv6_pinfo *np = inet6_sk(sk); 544 int len; 545 int val; 546 547 if (level == SOL_IP && sk->sk_type != SOCK_RAW) 548 return udp_prot.getsockopt(sk, level, optname, optval, optlen); 549 if(level!=SOL_IPV6) 550 return -ENOPROTOOPT; 551 if (get_user(len, optlen)) 552 return -EFAULT; 553 switch (optname) { 554 case IPV6_ADDRFORM: 555 if (sk->sk_protocol != IPPROTO_UDP && 556 sk->sk_protocol != IPPROTO_TCP) 557 return -EINVAL; 558 if (sk->sk_state != TCP_ESTABLISHED) 559 return -ENOTCONN; 560 val = sk->sk_family; 561 break; 562 case MCAST_MSFILTER: 563 { 564 struct group_filter gsf; 565 int err; 566 567 if (len < GROUP_FILTER_SIZE(0)) 568 return -EINVAL; 569 if (copy_from_user(&gsf, optval, GROUP_FILTER_SIZE(0))) 570 return -EFAULT; 571 lock_sock(sk); 572 err = ip6_mc_msfget(sk, &gsf, 573 (struct group_filter __user *)optval, optlen); 574 release_sock(sk); 575 return err; 576 } 577 578 case IPV6_PKTOPTIONS: 579 { 580 struct msghdr msg; 581 struct sk_buff *skb; 582 583 if (sk->sk_type != SOCK_STREAM) 584 return -ENOPROTOOPT; 585 586 msg.msg_control = optval; 587 msg.msg_controllen = len; 588 msg.msg_flags = 0; 589 590 lock_sock(sk); 591 skb = np->pktoptions; 592 if (skb) 593 atomic_inc(&skb->users); 594 release_sock(sk); 595 596 if (skb) { 597 int err = datagram_recv_ctl(sk, &msg, skb); 598 kfree_skb(skb); 599 if (err) 600 return err; 601 } else { 602 if (np->rxopt.bits.rxinfo) { 603 struct in6_pktinfo src_info; 604 src_info.ipi6_ifindex = np->mcast_oif; 605 ipv6_addr_copy(&src_info.ipi6_addr, &np->daddr); 606 put_cmsg(&msg, SOL_IPV6, IPV6_PKTINFO, sizeof(src_info), &src_info); 607 } 608 if (np->rxopt.bits.rxhlim) { 609 int hlim = np->mcast_hops; 610 put_cmsg(&msg, SOL_IPV6, IPV6_HOPLIMIT, sizeof(hlim), &hlim); 611 } 612 } 613 len -= msg.msg_controllen; 614 return put_user(len, optlen); 615 } 616 case IPV6_MTU: 617 { 618 struct dst_entry *dst; 619 val = 0; 620 lock_sock(sk); 621 dst = sk_dst_get(sk); 622 if (dst) { 623 val = dst_mtu(dst); 624 dst_release(dst); 625 } 626 release_sock(sk); 627 if (!val) 628 return -ENOTCONN; 629 break; 630 } 631 632 case IPV6_V6ONLY: 633 val = np->ipv6only; 634 break; 635 636 case IPV6_PKTINFO: 637 val = np->rxopt.bits.rxinfo; 638 break; 639 640 case IPV6_HOPLIMIT: 641 val = np->rxopt.bits.rxhlim; 642 break; 643 644 case IPV6_RTHDR: 645 val = np->rxopt.bits.srcrt; 646 break; 647 648 case IPV6_HOPOPTS: 649 val = np->rxopt.bits.hopopts; 650 break; 651 652 case IPV6_DSTOPTS: 653 val = np->rxopt.bits.dstopts; 654 break; 655 656 case IPV6_FLOWINFO: 657 val = np->rxopt.bits.rxflow; 658 break; 659 660 case IPV6_UNICAST_HOPS: 661 val = np->hop_limit; 662 break; 663 664 case IPV6_MULTICAST_HOPS: 665 val = np->mcast_hops; 666 break; 667 668 case IPV6_MULTICAST_LOOP: 669 val = np->mc_loop; 670 break; 671 672 case IPV6_MULTICAST_IF: 673 val = np->mcast_oif; 674 break; 675 676 case IPV6_MTU_DISCOVER: 677 val = np->pmtudisc; 678 break; 679 680 case IPV6_RECVERR: 681 val = np->recverr; 682 break; 683 684 case IPV6_FLOWINFO_SEND: 685 val = np->sndflow; 686 break; 687 688 default: 689 #ifdef CONFIG_NETFILTER 690 lock_sock(sk); 691 val = nf_getsockopt(sk, PF_INET6, optname, optval, 692 &len); 693 release_sock(sk); 694 if (val >= 0) 695 val = put_user(len, optlen); 696 return val; 697 #else 698 return -EINVAL; 699 #endif 700 } 701 len = min_t(unsigned int, sizeof(int), len); 702 if(put_user(len, optlen)) 703 return -EFAULT; 704 if(copy_to_user(optval,&val,len)) 705 return -EFAULT; 706 return 0; 707 } 708 709 void __init ipv6_packet_init(void) 710 { 711 dev_add_pack(&ipv6_packet_type); 712 } 713 714 void ipv6_packet_cleanup(void) 715 { 716 dev_remove_pack(&ipv6_packet_type); 717 } 718