diff options
Diffstat (limited to 'net/core/sock.c')
-rw-r--r-- | net/core/sock.c | 775 |
1 files changed, 409 insertions, 366 deletions
diff --git a/net/core/sock.c b/net/core/sock.c index 27c4f62382bd..22183c2ef284 100644 --- a/net/core/sock.c +++ b/net/core/sock.c | |||
@@ -154,7 +154,8 @@ static const char *af_family_key_strings[AF_MAX+1] = { | |||
154 | "sk_lock-21" , "sk_lock-AF_SNA" , "sk_lock-AF_IRDA" , | 154 | "sk_lock-21" , "sk_lock-AF_SNA" , "sk_lock-AF_IRDA" , |
155 | "sk_lock-AF_PPPOX" , "sk_lock-AF_WANPIPE" , "sk_lock-AF_LLC" , | 155 | "sk_lock-AF_PPPOX" , "sk_lock-AF_WANPIPE" , "sk_lock-AF_LLC" , |
156 | "sk_lock-27" , "sk_lock-28" , "sk_lock-29" , | 156 | "sk_lock-27" , "sk_lock-28" , "sk_lock-29" , |
157 | "sk_lock-AF_TIPC" , "sk_lock-AF_BLUETOOTH", "sk_lock-AF_MAX" | 157 | "sk_lock-AF_TIPC" , "sk_lock-AF_BLUETOOTH", "sk_lock-IUCV" , |
158 | "sk_lock-AF_RXRPC" , "sk_lock-AF_MAX" | ||
158 | }; | 159 | }; |
159 | static const char *af_family_slock_key_strings[AF_MAX+1] = { | 160 | static const char *af_family_slock_key_strings[AF_MAX+1] = { |
160 | "slock-AF_UNSPEC", "slock-AF_UNIX" , "slock-AF_INET" , | 161 | "slock-AF_UNSPEC", "slock-AF_UNIX" , "slock-AF_INET" , |
@@ -167,7 +168,8 @@ static const char *af_family_slock_key_strings[AF_MAX+1] = { | |||
167 | "slock-21" , "slock-AF_SNA" , "slock-AF_IRDA" , | 168 | "slock-21" , "slock-AF_SNA" , "slock-AF_IRDA" , |
168 | "slock-AF_PPPOX" , "slock-AF_WANPIPE" , "slock-AF_LLC" , | 169 | "slock-AF_PPPOX" , "slock-AF_WANPIPE" , "slock-AF_LLC" , |
169 | "slock-27" , "slock-28" , "slock-29" , | 170 | "slock-27" , "slock-28" , "slock-29" , |
170 | "slock-AF_TIPC" , "slock-AF_BLUETOOTH", "slock-AF_MAX" | 171 | "slock-AF_TIPC" , "slock-AF_BLUETOOTH", "slock-AF_IUCV" , |
172 | "slock-AF_RXRPC" , "slock-AF_MAX" | ||
171 | }; | 173 | }; |
172 | #endif | 174 | #endif |
173 | 175 | ||
@@ -361,8 +363,8 @@ int sock_setsockopt(struct socket *sock, int level, int optname, | |||
361 | } | 363 | } |
362 | #endif | 364 | #endif |
363 | 365 | ||
364 | if(optlen<sizeof(int)) | 366 | if (optlen < sizeof(int)) |
365 | return(-EINVAL); | 367 | return -EINVAL; |
366 | 368 | ||
367 | if (get_user(val, (int __user *)optval)) | 369 | if (get_user(val, (int __user *)optval)) |
368 | return -EFAULT; | 370 | return -EFAULT; |
@@ -371,265 +373,270 @@ int sock_setsockopt(struct socket *sock, int level, int optname, | |||
371 | 373 | ||
372 | lock_sock(sk); | 374 | lock_sock(sk); |
373 | 375 | ||
374 | switch(optname) | 376 | switch(optname) { |
375 | { | 377 | case SO_DEBUG: |
376 | case SO_DEBUG: | 378 | if (val && !capable(CAP_NET_ADMIN)) { |
377 | if(val && !capable(CAP_NET_ADMIN)) | 379 | ret = -EACCES; |
378 | { | 380 | } |
379 | ret = -EACCES; | 381 | else if (valbool) |
380 | } | 382 | sock_set_flag(sk, SOCK_DBG); |
381 | else if (valbool) | 383 | else |
382 | sock_set_flag(sk, SOCK_DBG); | 384 | sock_reset_flag(sk, SOCK_DBG); |
383 | else | 385 | break; |
384 | sock_reset_flag(sk, SOCK_DBG); | 386 | case SO_REUSEADDR: |
385 | break; | 387 | sk->sk_reuse = valbool; |
386 | case SO_REUSEADDR: | 388 | break; |
387 | sk->sk_reuse = valbool; | 389 | case SO_TYPE: |
388 | break; | 390 | case SO_ERROR: |
389 | case SO_TYPE: | 391 | ret = -ENOPROTOOPT; |
390 | case SO_ERROR: | 392 | break; |
391 | ret = -ENOPROTOOPT; | 393 | case SO_DONTROUTE: |
392 | break; | 394 | if (valbool) |
393 | case SO_DONTROUTE: | 395 | sock_set_flag(sk, SOCK_LOCALROUTE); |
394 | if (valbool) | 396 | else |
395 | sock_set_flag(sk, SOCK_LOCALROUTE); | 397 | sock_reset_flag(sk, SOCK_LOCALROUTE); |
396 | else | 398 | break; |
397 | sock_reset_flag(sk, SOCK_LOCALROUTE); | 399 | case SO_BROADCAST: |
398 | break; | 400 | sock_valbool_flag(sk, SOCK_BROADCAST, valbool); |
399 | case SO_BROADCAST: | 401 | break; |
400 | sock_valbool_flag(sk, SOCK_BROADCAST, valbool); | 402 | case SO_SNDBUF: |
401 | break; | 403 | /* Don't error on this BSD doesn't and if you think |
402 | case SO_SNDBUF: | 404 | about it this is right. Otherwise apps have to |
403 | /* Don't error on this BSD doesn't and if you think | 405 | play 'guess the biggest size' games. RCVBUF/SNDBUF |
404 | about it this is right. Otherwise apps have to | 406 | are treated in BSD as hints */ |
405 | play 'guess the biggest size' games. RCVBUF/SNDBUF | 407 | |
406 | are treated in BSD as hints */ | 408 | if (val > sysctl_wmem_max) |
407 | 409 | val = sysctl_wmem_max; | |
408 | if (val > sysctl_wmem_max) | ||
409 | val = sysctl_wmem_max; | ||
410 | set_sndbuf: | 410 | set_sndbuf: |
411 | sk->sk_userlocks |= SOCK_SNDBUF_LOCK; | 411 | sk->sk_userlocks |= SOCK_SNDBUF_LOCK; |
412 | if ((val * 2) < SOCK_MIN_SNDBUF) | 412 | if ((val * 2) < SOCK_MIN_SNDBUF) |
413 | sk->sk_sndbuf = SOCK_MIN_SNDBUF; | 413 | sk->sk_sndbuf = SOCK_MIN_SNDBUF; |
414 | else | 414 | else |
415 | sk->sk_sndbuf = val * 2; | 415 | sk->sk_sndbuf = val * 2; |
416 | 416 | ||
417 | /* | 417 | /* |
418 | * Wake up sending tasks if we | 418 | * Wake up sending tasks if we |
419 | * upped the value. | 419 | * upped the value. |
420 | */ | 420 | */ |
421 | sk->sk_write_space(sk); | 421 | sk->sk_write_space(sk); |
422 | break; | 422 | break; |
423 | 423 | ||
424 | case SO_SNDBUFFORCE: | 424 | case SO_SNDBUFFORCE: |
425 | if (!capable(CAP_NET_ADMIN)) { | 425 | if (!capable(CAP_NET_ADMIN)) { |
426 | ret = -EPERM; | 426 | ret = -EPERM; |
427 | break; | 427 | break; |
428 | } | 428 | } |
429 | goto set_sndbuf; | 429 | goto set_sndbuf; |
430 | 430 | ||
431 | case SO_RCVBUF: | 431 | case SO_RCVBUF: |
432 | /* Don't error on this BSD doesn't and if you think | 432 | /* Don't error on this BSD doesn't and if you think |
433 | about it this is right. Otherwise apps have to | 433 | about it this is right. Otherwise apps have to |
434 | play 'guess the biggest size' games. RCVBUF/SNDBUF | 434 | play 'guess the biggest size' games. RCVBUF/SNDBUF |
435 | are treated in BSD as hints */ | 435 | are treated in BSD as hints */ |
436 | 436 | ||
437 | if (val > sysctl_rmem_max) | 437 | if (val > sysctl_rmem_max) |
438 | val = sysctl_rmem_max; | 438 | val = sysctl_rmem_max; |
439 | set_rcvbuf: | 439 | set_rcvbuf: |
440 | sk->sk_userlocks |= SOCK_RCVBUF_LOCK; | 440 | sk->sk_userlocks |= SOCK_RCVBUF_LOCK; |
441 | /* | 441 | /* |
442 | * We double it on the way in to account for | 442 | * We double it on the way in to account for |
443 | * "struct sk_buff" etc. overhead. Applications | 443 | * "struct sk_buff" etc. overhead. Applications |
444 | * assume that the SO_RCVBUF setting they make will | 444 | * assume that the SO_RCVBUF setting they make will |
445 | * allow that much actual data to be received on that | 445 | * allow that much actual data to be received on that |
446 | * socket. | 446 | * socket. |
447 | * | 447 | * |
448 | * Applications are unaware that "struct sk_buff" and | 448 | * Applications are unaware that "struct sk_buff" and |
449 | * other overheads allocate from the receive buffer | 449 | * other overheads allocate from the receive buffer |
450 | * during socket buffer allocation. | 450 | * during socket buffer allocation. |
451 | * | 451 | * |
452 | * And after considering the possible alternatives, | 452 | * And after considering the possible alternatives, |
453 | * returning the value we actually used in getsockopt | 453 | * returning the value we actually used in getsockopt |
454 | * is the most desirable behavior. | 454 | * is the most desirable behavior. |
455 | */ | 455 | */ |
456 | if ((val * 2) < SOCK_MIN_RCVBUF) | 456 | if ((val * 2) < SOCK_MIN_RCVBUF) |
457 | sk->sk_rcvbuf = SOCK_MIN_RCVBUF; | 457 | sk->sk_rcvbuf = SOCK_MIN_RCVBUF; |
458 | else | 458 | else |
459 | sk->sk_rcvbuf = val * 2; | 459 | sk->sk_rcvbuf = val * 2; |
460 | break; | ||
461 | |||
462 | case SO_RCVBUFFORCE: | ||
463 | if (!capable(CAP_NET_ADMIN)) { | ||
464 | ret = -EPERM; | ||
460 | break; | 465 | break; |
466 | } | ||
467 | goto set_rcvbuf; | ||
461 | 468 | ||
462 | case SO_RCVBUFFORCE: | 469 | case SO_KEEPALIVE: |
463 | if (!capable(CAP_NET_ADMIN)) { | ||
464 | ret = -EPERM; | ||
465 | break; | ||
466 | } | ||
467 | goto set_rcvbuf; | ||
468 | |||
469 | case SO_KEEPALIVE: | ||
470 | #ifdef CONFIG_INET | 470 | #ifdef CONFIG_INET |
471 | if (sk->sk_protocol == IPPROTO_TCP) | 471 | if (sk->sk_protocol == IPPROTO_TCP) |
472 | tcp_set_keepalive(sk, valbool); | 472 | tcp_set_keepalive(sk, valbool); |
473 | #endif | 473 | #endif |
474 | sock_valbool_flag(sk, SOCK_KEEPOPEN, valbool); | 474 | sock_valbool_flag(sk, SOCK_KEEPOPEN, valbool); |
475 | break; | 475 | break; |
476 | 476 | ||
477 | case SO_OOBINLINE: | 477 | case SO_OOBINLINE: |
478 | sock_valbool_flag(sk, SOCK_URGINLINE, valbool); | 478 | sock_valbool_flag(sk, SOCK_URGINLINE, valbool); |
479 | break; | ||
480 | |||
481 | case SO_NO_CHECK: | ||
482 | sk->sk_no_check = valbool; | ||
483 | break; | ||
484 | |||
485 | case SO_PRIORITY: | ||
486 | if ((val >= 0 && val <= 6) || capable(CAP_NET_ADMIN)) | ||
487 | sk->sk_priority = val; | ||
488 | else | ||
489 | ret = -EPERM; | ||
490 | break; | ||
491 | |||
492 | case SO_LINGER: | ||
493 | if (optlen < sizeof(ling)) { | ||
494 | ret = -EINVAL; /* 1003.1g */ | ||
479 | break; | 495 | break; |
480 | 496 | } | |
481 | case SO_NO_CHECK: | 497 | if (copy_from_user(&ling,optval,sizeof(ling))) { |
482 | sk->sk_no_check = valbool; | 498 | ret = -EFAULT; |
483 | break; | ||
484 | |||
485 | case SO_PRIORITY: | ||
486 | if ((val >= 0 && val <= 6) || capable(CAP_NET_ADMIN)) | ||
487 | sk->sk_priority = val; | ||
488 | else | ||
489 | ret = -EPERM; | ||
490 | break; | 499 | break; |
491 | 500 | } | |
492 | case SO_LINGER: | 501 | if (!ling.l_onoff) |
493 | if(optlen<sizeof(ling)) { | 502 | sock_reset_flag(sk, SOCK_LINGER); |
494 | ret = -EINVAL; /* 1003.1g */ | 503 | else { |
495 | break; | ||
496 | } | ||
497 | if (copy_from_user(&ling,optval,sizeof(ling))) { | ||
498 | ret = -EFAULT; | ||
499 | break; | ||
500 | } | ||
501 | if (!ling.l_onoff) | ||
502 | sock_reset_flag(sk, SOCK_LINGER); | ||
503 | else { | ||
504 | #if (BITS_PER_LONG == 32) | 504 | #if (BITS_PER_LONG == 32) |
505 | if ((unsigned int)ling.l_linger >= MAX_SCHEDULE_TIMEOUT/HZ) | 505 | if ((unsigned int)ling.l_linger >= MAX_SCHEDULE_TIMEOUT/HZ) |
506 | sk->sk_lingertime = MAX_SCHEDULE_TIMEOUT; | 506 | sk->sk_lingertime = MAX_SCHEDULE_TIMEOUT; |
507 | else | 507 | else |
508 | #endif | 508 | #endif |
509 | sk->sk_lingertime = (unsigned int)ling.l_linger * HZ; | 509 | sk->sk_lingertime = (unsigned int)ling.l_linger * HZ; |
510 | sock_set_flag(sk, SOCK_LINGER); | 510 | sock_set_flag(sk, SOCK_LINGER); |
511 | } | 511 | } |
512 | break; | 512 | break; |
513 | 513 | ||
514 | case SO_BSDCOMPAT: | 514 | case SO_BSDCOMPAT: |
515 | sock_warn_obsolete_bsdism("setsockopt"); | 515 | sock_warn_obsolete_bsdism("setsockopt"); |
516 | break; | 516 | break; |
517 | 517 | ||
518 | case SO_PASSCRED: | 518 | case SO_PASSCRED: |
519 | if (valbool) | 519 | if (valbool) |
520 | set_bit(SOCK_PASSCRED, &sock->flags); | 520 | set_bit(SOCK_PASSCRED, &sock->flags); |
521 | else | ||
522 | clear_bit(SOCK_PASSCRED, &sock->flags); | ||
523 | break; | ||
524 | |||
525 | case SO_TIMESTAMP: | ||
526 | case SO_TIMESTAMPNS: | ||
527 | if (valbool) { | ||
528 | if (optname == SO_TIMESTAMP) | ||
529 | sock_reset_flag(sk, SOCK_RCVTSTAMPNS); | ||
521 | else | 530 | else |
522 | clear_bit(SOCK_PASSCRED, &sock->flags); | 531 | sock_set_flag(sk, SOCK_RCVTSTAMPNS); |
523 | break; | 532 | sock_set_flag(sk, SOCK_RCVTSTAMP); |
533 | sock_enable_timestamp(sk); | ||
534 | } else { | ||
535 | sock_reset_flag(sk, SOCK_RCVTSTAMP); | ||
536 | sock_reset_flag(sk, SOCK_RCVTSTAMPNS); | ||
537 | } | ||
538 | break; | ||
524 | 539 | ||
525 | case SO_TIMESTAMP: | 540 | case SO_RCVLOWAT: |
526 | if (valbool) { | 541 | if (val < 0) |
527 | sock_set_flag(sk, SOCK_RCVTSTAMP); | 542 | val = INT_MAX; |
528 | sock_enable_timestamp(sk); | 543 | sk->sk_rcvlowat = val ? : 1; |
529 | } else | 544 | break; |
530 | sock_reset_flag(sk, SOCK_RCVTSTAMP); | ||
531 | break; | ||
532 | 545 | ||
533 | case SO_RCVLOWAT: | 546 | case SO_RCVTIMEO: |
534 | if (val < 0) | 547 | ret = sock_set_timeout(&sk->sk_rcvtimeo, optval, optlen); |
535 | val = INT_MAX; | 548 | break; |
536 | sk->sk_rcvlowat = val ? : 1; | ||
537 | break; | ||
538 | 549 | ||
539 | case SO_RCVTIMEO: | 550 | case SO_SNDTIMEO: |
540 | ret = sock_set_timeout(&sk->sk_rcvtimeo, optval, optlen); | 551 | ret = sock_set_timeout(&sk->sk_sndtimeo, optval, optlen); |
541 | break; | 552 | break; |
542 | 553 | ||
543 | case SO_SNDTIMEO: | 554 | #ifdef CONFIG_NETDEVICES |
544 | ret = sock_set_timeout(&sk->sk_sndtimeo, optval, optlen); | 555 | case SO_BINDTODEVICE: |
556 | { | ||
557 | char devname[IFNAMSIZ]; | ||
558 | |||
559 | /* Sorry... */ | ||
560 | if (!capable(CAP_NET_RAW)) { | ||
561 | ret = -EPERM; | ||
545 | break; | 562 | break; |
563 | } | ||
546 | 564 | ||
547 | #ifdef CONFIG_NETDEVICES | 565 | /* Bind this socket to a particular device like "eth0", |
548 | case SO_BINDTODEVICE: | 566 | * as specified in the passed interface name. If the |
549 | { | 567 | * name is "" or the option length is zero the socket |
550 | char devname[IFNAMSIZ]; | 568 | * is not bound. |
569 | */ | ||
551 | 570 | ||
552 | /* Sorry... */ | 571 | if (!valbool) { |
553 | if (!capable(CAP_NET_RAW)) { | 572 | sk->sk_bound_dev_if = 0; |
554 | ret = -EPERM; | 573 | } else { |
574 | if (optlen > IFNAMSIZ - 1) | ||
575 | optlen = IFNAMSIZ - 1; | ||
576 | memset(devname, 0, sizeof(devname)); | ||
577 | if (copy_from_user(devname, optval, optlen)) { | ||
578 | ret = -EFAULT; | ||
555 | break; | 579 | break; |
556 | } | 580 | } |
557 | 581 | ||
558 | /* Bind this socket to a particular device like "eth0", | 582 | /* Remove any cached route for this socket. */ |
559 | * as specified in the passed interface name. If the | 583 | sk_dst_reset(sk); |
560 | * name is "" or the option length is zero the socket | ||
561 | * is not bound. | ||
562 | */ | ||
563 | 584 | ||
564 | if (!valbool) { | 585 | if (devname[0] == '\0') { |
565 | sk->sk_bound_dev_if = 0; | 586 | sk->sk_bound_dev_if = 0; |
566 | } else { | 587 | } else { |
567 | if (optlen > IFNAMSIZ - 1) | 588 | struct net_device *dev = dev_get_by_name(devname); |
568 | optlen = IFNAMSIZ - 1; | 589 | if (!dev) { |
569 | memset(devname, 0, sizeof(devname)); | 590 | ret = -ENODEV; |
570 | if (copy_from_user(devname, optval, optlen)) { | ||
571 | ret = -EFAULT; | ||
572 | break; | 591 | break; |
573 | } | 592 | } |
574 | 593 | sk->sk_bound_dev_if = dev->ifindex; | |
575 | /* Remove any cached route for this socket. */ | 594 | dev_put(dev); |
576 | sk_dst_reset(sk); | ||
577 | |||
578 | if (devname[0] == '\0') { | ||
579 | sk->sk_bound_dev_if = 0; | ||
580 | } else { | ||
581 | struct net_device *dev = dev_get_by_name(devname); | ||
582 | if (!dev) { | ||
583 | ret = -ENODEV; | ||
584 | break; | ||
585 | } | ||
586 | sk->sk_bound_dev_if = dev->ifindex; | ||
587 | dev_put(dev); | ||
588 | } | ||
589 | } | 595 | } |
590 | break; | ||
591 | } | 596 | } |
597 | break; | ||
598 | } | ||
592 | #endif | 599 | #endif |
593 | 600 | ||
594 | 601 | ||
595 | case SO_ATTACH_FILTER: | 602 | case SO_ATTACH_FILTER: |
596 | ret = -EINVAL; | 603 | ret = -EINVAL; |
597 | if (optlen == sizeof(struct sock_fprog)) { | 604 | if (optlen == sizeof(struct sock_fprog)) { |
598 | struct sock_fprog fprog; | 605 | struct sock_fprog fprog; |
599 | 606 | ||
600 | ret = -EFAULT; | 607 | ret = -EFAULT; |
601 | if (copy_from_user(&fprog, optval, sizeof(fprog))) | 608 | if (copy_from_user(&fprog, optval, sizeof(fprog))) |
602 | break; | ||
603 | |||
604 | ret = sk_attach_filter(&fprog, sk); | ||
605 | } | ||
606 | break; | ||
607 | |||
608 | case SO_DETACH_FILTER: | ||
609 | rcu_read_lock_bh(); | ||
610 | filter = rcu_dereference(sk->sk_filter); | ||
611 | if (filter) { | ||
612 | rcu_assign_pointer(sk->sk_filter, NULL); | ||
613 | sk_filter_release(sk, filter); | ||
614 | rcu_read_unlock_bh(); | ||
615 | break; | 609 | break; |
616 | } | 610 | |
611 | ret = sk_attach_filter(&fprog, sk); | ||
612 | } | ||
613 | break; | ||
614 | |||
615 | case SO_DETACH_FILTER: | ||
616 | rcu_read_lock_bh(); | ||
617 | filter = rcu_dereference(sk->sk_filter); | ||
618 | if (filter) { | ||
619 | rcu_assign_pointer(sk->sk_filter, NULL); | ||
620 | sk_filter_release(sk, filter); | ||
617 | rcu_read_unlock_bh(); | 621 | rcu_read_unlock_bh(); |
618 | ret = -ENONET; | ||
619 | break; | 622 | break; |
623 | } | ||
624 | rcu_read_unlock_bh(); | ||
625 | ret = -ENONET; | ||
626 | break; | ||
620 | 627 | ||
621 | case SO_PASSSEC: | 628 | case SO_PASSSEC: |
622 | if (valbool) | 629 | if (valbool) |
623 | set_bit(SOCK_PASSSEC, &sock->flags); | 630 | set_bit(SOCK_PASSSEC, &sock->flags); |
624 | else | 631 | else |
625 | clear_bit(SOCK_PASSSEC, &sock->flags); | 632 | clear_bit(SOCK_PASSSEC, &sock->flags); |
626 | break; | 633 | break; |
627 | 634 | ||
628 | /* We implement the SO_SNDLOWAT etc to | 635 | /* We implement the SO_SNDLOWAT etc to |
629 | not be settable (1003.1g 5.3) */ | 636 | not be settable (1003.1g 5.3) */ |
630 | default: | 637 | default: |
631 | ret = -ENOPROTOOPT; | 638 | ret = -ENOPROTOOPT; |
632 | break; | 639 | break; |
633 | } | 640 | } |
634 | release_sock(sk); | 641 | release_sock(sk); |
635 | return ret; | 642 | return ret; |
@@ -641,8 +648,7 @@ int sock_getsockopt(struct socket *sock, int level, int optname, | |||
641 | { | 648 | { |
642 | struct sock *sk = sock->sk; | 649 | struct sock *sk = sock->sk; |
643 | 650 | ||
644 | union | 651 | union { |
645 | { | ||
646 | int val; | 652 | int val; |
647 | struct linger ling; | 653 | struct linger ling; |
648 | struct timeval tm; | 654 | struct timeval tm; |
@@ -651,148 +657,153 @@ int sock_getsockopt(struct socket *sock, int level, int optname, | |||
651 | unsigned int lv = sizeof(int); | 657 | unsigned int lv = sizeof(int); |
652 | int len; | 658 | int len; |
653 | 659 | ||
654 | if(get_user(len,optlen)) | 660 | if (get_user(len, optlen)) |
655 | return -EFAULT; | 661 | return -EFAULT; |
656 | if(len < 0) | 662 | if (len < 0) |
657 | return -EINVAL; | 663 | return -EINVAL; |
658 | 664 | ||
659 | switch(optname) | 665 | switch(optname) { |
660 | { | 666 | case SO_DEBUG: |
661 | case SO_DEBUG: | 667 | v.val = sock_flag(sk, SOCK_DBG); |
662 | v.val = sock_flag(sk, SOCK_DBG); | 668 | break; |
663 | break; | 669 | |
664 | 670 | case SO_DONTROUTE: | |
665 | case SO_DONTROUTE: | 671 | v.val = sock_flag(sk, SOCK_LOCALROUTE); |
666 | v.val = sock_flag(sk, SOCK_LOCALROUTE); | 672 | break; |
667 | break; | 673 | |
668 | 674 | case SO_BROADCAST: | |
669 | case SO_BROADCAST: | 675 | v.val = !!sock_flag(sk, SOCK_BROADCAST); |
670 | v.val = !!sock_flag(sk, SOCK_BROADCAST); | 676 | break; |
671 | break; | 677 | |
672 | 678 | case SO_SNDBUF: | |
673 | case SO_SNDBUF: | 679 | v.val = sk->sk_sndbuf; |
674 | v.val = sk->sk_sndbuf; | 680 | break; |
675 | break; | 681 | |
676 | 682 | case SO_RCVBUF: | |
677 | case SO_RCVBUF: | 683 | v.val = sk->sk_rcvbuf; |
678 | v.val = sk->sk_rcvbuf; | 684 | break; |
679 | break; | 685 | |
680 | 686 | case SO_REUSEADDR: | |
681 | case SO_REUSEADDR: | 687 | v.val = sk->sk_reuse; |
682 | v.val = sk->sk_reuse; | 688 | break; |
683 | break; | 689 | |
684 | 690 | case SO_KEEPALIVE: | |
685 | case SO_KEEPALIVE: | 691 | v.val = !!sock_flag(sk, SOCK_KEEPOPEN); |
686 | v.val = !!sock_flag(sk, SOCK_KEEPOPEN); | 692 | break; |
687 | break; | 693 | |
688 | 694 | case SO_TYPE: | |
689 | case SO_TYPE: | 695 | v.val = sk->sk_type; |
690 | v.val = sk->sk_type; | 696 | break; |
691 | break; | 697 | |
692 | 698 | case SO_ERROR: | |
693 | case SO_ERROR: | 699 | v.val = -sock_error(sk); |
694 | v.val = -sock_error(sk); | 700 | if (v.val==0) |
695 | if(v.val==0) | 701 | v.val = xchg(&sk->sk_err_soft, 0); |
696 | v.val = xchg(&sk->sk_err_soft, 0); | 702 | break; |
697 | break; | 703 | |
698 | 704 | case SO_OOBINLINE: | |
699 | case SO_OOBINLINE: | 705 | v.val = !!sock_flag(sk, SOCK_URGINLINE); |
700 | v.val = !!sock_flag(sk, SOCK_URGINLINE); | 706 | break; |
701 | break; | 707 | |
702 | 708 | case SO_NO_CHECK: | |
703 | case SO_NO_CHECK: | 709 | v.val = sk->sk_no_check; |
704 | v.val = sk->sk_no_check; | 710 | break; |
705 | break; | 711 | |
706 | 712 | case SO_PRIORITY: | |
707 | case SO_PRIORITY: | 713 | v.val = sk->sk_priority; |
708 | v.val = sk->sk_priority; | 714 | break; |
709 | break; | 715 | |
710 | 716 | case SO_LINGER: | |
711 | case SO_LINGER: | 717 | lv = sizeof(v.ling); |
712 | lv = sizeof(v.ling); | 718 | v.ling.l_onoff = !!sock_flag(sk, SOCK_LINGER); |
713 | v.ling.l_onoff = !!sock_flag(sk, SOCK_LINGER); | 719 | v.ling.l_linger = sk->sk_lingertime / HZ; |
714 | v.ling.l_linger = sk->sk_lingertime / HZ; | 720 | break; |
715 | break; | 721 | |
716 | 722 | case SO_BSDCOMPAT: | |
717 | case SO_BSDCOMPAT: | 723 | sock_warn_obsolete_bsdism("getsockopt"); |
718 | sock_warn_obsolete_bsdism("getsockopt"); | 724 | break; |
719 | break; | 725 | |
720 | 726 | case SO_TIMESTAMP: | |
721 | case SO_TIMESTAMP: | 727 | v.val = sock_flag(sk, SOCK_RCVTSTAMP) && |
722 | v.val = sock_flag(sk, SOCK_RCVTSTAMP); | 728 | !sock_flag(sk, SOCK_RCVTSTAMPNS); |
723 | break; | 729 | break; |
730 | |||
731 | case SO_TIMESTAMPNS: | ||
732 | v.val = sock_flag(sk, SOCK_RCVTSTAMPNS); | ||
733 | break; | ||
734 | |||
735 | case SO_RCVTIMEO: | ||
736 | lv=sizeof(struct timeval); | ||
737 | if (sk->sk_rcvtimeo == MAX_SCHEDULE_TIMEOUT) { | ||
738 | v.tm.tv_sec = 0; | ||
739 | v.tm.tv_usec = 0; | ||
740 | } else { | ||
741 | v.tm.tv_sec = sk->sk_rcvtimeo / HZ; | ||
742 | v.tm.tv_usec = ((sk->sk_rcvtimeo % HZ) * 1000000) / HZ; | ||
743 | } | ||
744 | break; | ||
745 | |||
746 | case SO_SNDTIMEO: | ||
747 | lv=sizeof(struct timeval); | ||
748 | if (sk->sk_sndtimeo == MAX_SCHEDULE_TIMEOUT) { | ||
749 | v.tm.tv_sec = 0; | ||
750 | v.tm.tv_usec = 0; | ||
751 | } else { | ||
752 | v.tm.tv_sec = sk->sk_sndtimeo / HZ; | ||
753 | v.tm.tv_usec = ((sk->sk_sndtimeo % HZ) * 1000000) / HZ; | ||
754 | } | ||
755 | break; | ||
724 | 756 | ||
725 | case SO_RCVTIMEO: | 757 | case SO_RCVLOWAT: |
726 | lv=sizeof(struct timeval); | 758 | v.val = sk->sk_rcvlowat; |
727 | if (sk->sk_rcvtimeo == MAX_SCHEDULE_TIMEOUT) { | 759 | break; |
728 | v.tm.tv_sec = 0; | ||
729 | v.tm.tv_usec = 0; | ||
730 | } else { | ||
731 | v.tm.tv_sec = sk->sk_rcvtimeo / HZ; | ||
732 | v.tm.tv_usec = ((sk->sk_rcvtimeo % HZ) * 1000000) / HZ; | ||
733 | } | ||
734 | break; | ||
735 | 760 | ||
736 | case SO_SNDTIMEO: | 761 | case SO_SNDLOWAT: |
737 | lv=sizeof(struct timeval); | 762 | v.val=1; |
738 | if (sk->sk_sndtimeo == MAX_SCHEDULE_TIMEOUT) { | 763 | break; |
739 | v.tm.tv_sec = 0; | ||
740 | v.tm.tv_usec = 0; | ||
741 | } else { | ||
742 | v.tm.tv_sec = sk->sk_sndtimeo / HZ; | ||
743 | v.tm.tv_usec = ((sk->sk_sndtimeo % HZ) * 1000000) / HZ; | ||
744 | } | ||
745 | break; | ||
746 | 764 | ||
747 | case SO_RCVLOWAT: | 765 | case SO_PASSCRED: |
748 | v.val = sk->sk_rcvlowat; | 766 | v.val = test_bit(SOCK_PASSCRED, &sock->flags) ? 1 : 0; |
749 | break; | 767 | break; |
750 | 768 | ||
751 | case SO_SNDLOWAT: | 769 | case SO_PEERCRED: |
752 | v.val=1; | 770 | if (len > sizeof(sk->sk_peercred)) |
753 | break; | 771 | len = sizeof(sk->sk_peercred); |
772 | if (copy_to_user(optval, &sk->sk_peercred, len)) | ||
773 | return -EFAULT; | ||
774 | goto lenout; | ||
754 | 775 | ||
755 | case SO_PASSCRED: | 776 | case SO_PEERNAME: |
756 | v.val = test_bit(SOCK_PASSCRED, &sock->flags) ? 1 : 0; | 777 | { |
757 | break; | 778 | char address[128]; |
758 | 779 | ||
759 | case SO_PEERCRED: | 780 | if (sock->ops->getname(sock, (struct sockaddr *)address, &lv, 2)) |
760 | if (len > sizeof(sk->sk_peercred)) | 781 | return -ENOTCONN; |
761 | len = sizeof(sk->sk_peercred); | 782 | if (lv < len) |
762 | if (copy_to_user(optval, &sk->sk_peercred, len)) | 783 | return -EINVAL; |
763 | return -EFAULT; | 784 | if (copy_to_user(optval, address, len)) |
764 | goto lenout; | 785 | return -EFAULT; |
765 | 786 | goto lenout; | |
766 | case SO_PEERNAME: | 787 | } |
767 | { | ||
768 | char address[128]; | ||
769 | |||
770 | if (sock->ops->getname(sock, (struct sockaddr *)address, &lv, 2)) | ||
771 | return -ENOTCONN; | ||
772 | if (lv < len) | ||
773 | return -EINVAL; | ||
774 | if (copy_to_user(optval, address, len)) | ||
775 | return -EFAULT; | ||
776 | goto lenout; | ||
777 | } | ||
778 | 788 | ||
779 | /* Dubious BSD thing... Probably nobody even uses it, but | 789 | /* Dubious BSD thing... Probably nobody even uses it, but |
780 | * the UNIX standard wants it for whatever reason... -DaveM | 790 | * the UNIX standard wants it for whatever reason... -DaveM |
781 | */ | 791 | */ |
782 | case SO_ACCEPTCONN: | 792 | case SO_ACCEPTCONN: |
783 | v.val = sk->sk_state == TCP_LISTEN; | 793 | v.val = sk->sk_state == TCP_LISTEN; |
784 | break; | 794 | break; |
785 | 795 | ||
786 | case SO_PASSSEC: | 796 | case SO_PASSSEC: |
787 | v.val = test_bit(SOCK_PASSSEC, &sock->flags) ? 1 : 0; | 797 | v.val = test_bit(SOCK_PASSSEC, &sock->flags) ? 1 : 0; |
788 | break; | 798 | break; |
789 | 799 | ||
790 | case SO_PEERSEC: | 800 | case SO_PEERSEC: |
791 | return security_socket_getpeersec_stream(sock, optval, optlen, len); | 801 | return security_socket_getpeersec_stream(sock, optval, optlen, len); |
792 | 802 | ||
793 | default: | 803 | default: |
794 | return(-ENOPROTOOPT); | 804 | return -ENOPROTOOPT; |
795 | } | 805 | } |
806 | |||
796 | if (len > lv) | 807 | if (len > lv) |
797 | len = lv; | 808 | len = lv; |
798 | if (copy_to_user(optval, &v, len)) | 809 | if (copy_to_user(optval, &v, len)) |
@@ -904,6 +915,7 @@ struct sock *sk_clone(const struct sock *sk, const gfp_t priority) | |||
904 | sk_node_init(&newsk->sk_node); | 915 | sk_node_init(&newsk->sk_node); |
905 | sock_lock_init(newsk); | 916 | sock_lock_init(newsk); |
906 | bh_lock_sock(newsk); | 917 | bh_lock_sock(newsk); |
918 | newsk->sk_backlog.head = newsk->sk_backlog.tail = NULL; | ||
907 | 919 | ||
908 | atomic_set(&newsk->sk_rmem_alloc, 0); | 920 | atomic_set(&newsk->sk_rmem_alloc, 0); |
909 | atomic_set(&newsk->sk_wmem_alloc, 0); | 921 | atomic_set(&newsk->sk_wmem_alloc, 0); |
@@ -923,7 +935,6 @@ struct sock *sk_clone(const struct sock *sk, const gfp_t priority) | |||
923 | newsk->sk_wmem_queued = 0; | 935 | newsk->sk_wmem_queued = 0; |
924 | newsk->sk_forward_alloc = 0; | 936 | newsk->sk_forward_alloc = 0; |
925 | newsk->sk_send_head = NULL; | 937 | newsk->sk_send_head = NULL; |
926 | newsk->sk_backlog.head = newsk->sk_backlog.tail = NULL; | ||
927 | newsk->sk_userlocks = sk->sk_userlocks & ~SOCK_BINDPORT_LOCK; | 938 | newsk->sk_userlocks = sk->sk_userlocks & ~SOCK_BINDPORT_LOCK; |
928 | 939 | ||
929 | sock_reset_flag(newsk, SOCK_DONE); | 940 | sock_reset_flag(newsk, SOCK_DONE); |
@@ -970,6 +981,21 @@ out: | |||
970 | 981 | ||
971 | EXPORT_SYMBOL_GPL(sk_clone); | 982 | EXPORT_SYMBOL_GPL(sk_clone); |
972 | 983 | ||
984 | void sk_setup_caps(struct sock *sk, struct dst_entry *dst) | ||
985 | { | ||
986 | __sk_dst_set(sk, dst); | ||
987 | sk->sk_route_caps = dst->dev->features; | ||
988 | if (sk->sk_route_caps & NETIF_F_GSO) | ||
989 | sk->sk_route_caps |= NETIF_F_GSO_MASK; | ||
990 | if (sk_can_gso(sk)) { | ||
991 | if (dst->header_len) | ||
992 | sk->sk_route_caps &= ~NETIF_F_GSO_MASK; | ||
993 | else | ||
994 | sk->sk_route_caps |= NETIF_F_SG | NETIF_F_HW_CSUM; | ||
995 | } | ||
996 | } | ||
997 | EXPORT_SYMBOL_GPL(sk_setup_caps); | ||
998 | |||
973 | void __init sk_init(void) | 999 | void __init sk_init(void) |
974 | { | 1000 | { |
975 | if (num_physpages <= 4096) { | 1001 | if (num_physpages <= 4096) { |
@@ -1220,13 +1246,13 @@ static void __lock_sock(struct sock *sk) | |||
1220 | { | 1246 | { |
1221 | DEFINE_WAIT(wait); | 1247 | DEFINE_WAIT(wait); |
1222 | 1248 | ||
1223 | for(;;) { | 1249 | for (;;) { |
1224 | prepare_to_wait_exclusive(&sk->sk_lock.wq, &wait, | 1250 | prepare_to_wait_exclusive(&sk->sk_lock.wq, &wait, |
1225 | TASK_UNINTERRUPTIBLE); | 1251 | TASK_UNINTERRUPTIBLE); |
1226 | spin_unlock_bh(&sk->sk_lock.slock); | 1252 | spin_unlock_bh(&sk->sk_lock.slock); |
1227 | schedule(); | 1253 | schedule(); |
1228 | spin_lock_bh(&sk->sk_lock.slock); | 1254 | spin_lock_bh(&sk->sk_lock.slock); |
1229 | if(!sock_owned_by_user(sk)) | 1255 | if (!sock_owned_by_user(sk)) |
1230 | break; | 1256 | break; |
1231 | } | 1257 | } |
1232 | finish_wait(&sk->sk_lock.wq, &wait); | 1258 | finish_wait(&sk->sk_lock.wq, &wait); |
@@ -1258,7 +1284,7 @@ static void __release_sock(struct sock *sk) | |||
1258 | } while (skb != NULL); | 1284 | } while (skb != NULL); |
1259 | 1285 | ||
1260 | bh_lock_sock(sk); | 1286 | bh_lock_sock(sk); |
1261 | } while((skb = sk->sk_backlog.head) != NULL); | 1287 | } while ((skb = sk->sk_backlog.head) != NULL); |
1262 | } | 1288 | } |
1263 | 1289 | ||
1264 | /** | 1290 | /** |
@@ -1420,7 +1446,7 @@ static void sock_def_write_space(struct sock *sk) | |||
1420 | /* Do not wake up a writer until he can make "significant" | 1446 | /* Do not wake up a writer until he can make "significant" |
1421 | * progress. --DaveM | 1447 | * progress. --DaveM |
1422 | */ | 1448 | */ |
1423 | if((atomic_read(&sk->sk_wmem_alloc) << 1) <= sk->sk_sndbuf) { | 1449 | if ((atomic_read(&sk->sk_wmem_alloc) << 1) <= sk->sk_sndbuf) { |
1424 | if (sk->sk_sleep && waitqueue_active(sk->sk_sleep)) | 1450 | if (sk->sk_sleep && waitqueue_active(sk->sk_sleep)) |
1425 | wake_up_interruptible(sk->sk_sleep); | 1451 | wake_up_interruptible(sk->sk_sleep); |
1426 | 1452 | ||
@@ -1482,8 +1508,7 @@ void sock_init_data(struct socket *sock, struct sock *sk) | |||
1482 | 1508 | ||
1483 | sock_set_flag(sk, SOCK_ZAPPED); | 1509 | sock_set_flag(sk, SOCK_ZAPPED); |
1484 | 1510 | ||
1485 | if(sock) | 1511 | if (sock) { |
1486 | { | ||
1487 | sk->sk_type = sock->type; | 1512 | sk->sk_type = sock->type; |
1488 | sk->sk_sleep = &sock->wait; | 1513 | sk->sk_sleep = &sock->wait; |
1489 | sock->sk = sk; | 1514 | sock->sk = sk; |
@@ -1512,8 +1537,7 @@ void sock_init_data(struct socket *sock, struct sock *sk) | |||
1512 | sk->sk_rcvtimeo = MAX_SCHEDULE_TIMEOUT; | 1537 | sk->sk_rcvtimeo = MAX_SCHEDULE_TIMEOUT; |
1513 | sk->sk_sndtimeo = MAX_SCHEDULE_TIMEOUT; | 1538 | sk->sk_sndtimeo = MAX_SCHEDULE_TIMEOUT; |
1514 | 1539 | ||
1515 | sk->sk_stamp.tv_sec = -1L; | 1540 | sk->sk_stamp = ktime_set(-1L, -1L); |
1516 | sk->sk_stamp.tv_usec = -1L; | ||
1517 | 1541 | ||
1518 | atomic_set(&sk->sk_refcnt, 1); | 1542 | atomic_set(&sk->sk_refcnt, 1); |
1519 | } | 1543 | } |
@@ -1554,17 +1578,36 @@ EXPORT_SYMBOL(release_sock); | |||
1554 | 1578 | ||
1555 | int sock_get_timestamp(struct sock *sk, struct timeval __user *userstamp) | 1579 | int sock_get_timestamp(struct sock *sk, struct timeval __user *userstamp) |
1556 | { | 1580 | { |
1581 | struct timeval tv; | ||
1557 | if (!sock_flag(sk, SOCK_TIMESTAMP)) | 1582 | if (!sock_flag(sk, SOCK_TIMESTAMP)) |
1558 | sock_enable_timestamp(sk); | 1583 | sock_enable_timestamp(sk); |
1559 | if (sk->sk_stamp.tv_sec == -1) | 1584 | tv = ktime_to_timeval(sk->sk_stamp); |
1585 | if (tv.tv_sec == -1) | ||
1560 | return -ENOENT; | 1586 | return -ENOENT; |
1561 | if (sk->sk_stamp.tv_sec == 0) | 1587 | if (tv.tv_sec == 0) { |
1562 | do_gettimeofday(&sk->sk_stamp); | 1588 | sk->sk_stamp = ktime_get_real(); |
1563 | return copy_to_user(userstamp, &sk->sk_stamp, sizeof(struct timeval)) ? | 1589 | tv = ktime_to_timeval(sk->sk_stamp); |
1564 | -EFAULT : 0; | 1590 | } |
1591 | return copy_to_user(userstamp, &tv, sizeof(tv)) ? -EFAULT : 0; | ||
1565 | } | 1592 | } |
1566 | EXPORT_SYMBOL(sock_get_timestamp); | 1593 | EXPORT_SYMBOL(sock_get_timestamp); |
1567 | 1594 | ||
1595 | int sock_get_timestampns(struct sock *sk, struct timespec __user *userstamp) | ||
1596 | { | ||
1597 | struct timespec ts; | ||
1598 | if (!sock_flag(sk, SOCK_TIMESTAMP)) | ||
1599 | sock_enable_timestamp(sk); | ||
1600 | ts = ktime_to_timespec(sk->sk_stamp); | ||
1601 | if (ts.tv_sec == -1) | ||
1602 | return -ENOENT; | ||
1603 | if (ts.tv_sec == 0) { | ||
1604 | sk->sk_stamp = ktime_get_real(); | ||
1605 | ts = ktime_to_timespec(sk->sk_stamp); | ||
1606 | } | ||
1607 | return copy_to_user(userstamp, &ts, sizeof(ts)) ? -EFAULT : 0; | ||
1608 | } | ||
1609 | EXPORT_SYMBOL(sock_get_timestampns); | ||
1610 | |||
1568 | void sock_enable_timestamp(struct sock *sk) | 1611 | void sock_enable_timestamp(struct sock *sk) |
1569 | { | 1612 | { |
1570 | if (!sock_flag(sk, SOCK_TIMESTAMP)) { | 1613 | if (!sock_flag(sk, SOCK_TIMESTAMP)) { |
@@ -1899,7 +1942,7 @@ static int proto_seq_show(struct seq_file *seq, void *v) | |||
1899 | return 0; | 1942 | return 0; |
1900 | } | 1943 | } |
1901 | 1944 | ||
1902 | static struct seq_operations proto_seq_ops = { | 1945 | static const struct seq_operations proto_seq_ops = { |
1903 | .start = proto_seq_start, | 1946 | .start = proto_seq_start, |
1904 | .next = proto_seq_next, | 1947 | .next = proto_seq_next, |
1905 | .stop = proto_seq_stop, | 1948 | .stop = proto_seq_stop, |