Commit 2efbe911d3ea518f5d4648954379f9d5aa02e806

Authored by bellard
1 parent 667f38b1

more set/getsockopt values


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1516 c046a42c-6fe2-441c-8c8c-71466251a162
Showing 1 changed file with 71 additions and 7 deletions
linux-user/syscall.c
... ... @@ -547,7 +547,21 @@ static long do_setsockopt(int sockfd, int level, int optname,
547 547 break;
548 548 case SOL_IP:
549 549 switch(optname) {
  550 + case IP_TOS:
  551 + case IP_TTL:
550 552 case IP_HDRINCL:
  553 + case IP_ROUTER_ALERT:
  554 + case IP_RECVOPTS:
  555 + case IP_RETOPTS:
  556 + case IP_PKTINFO:
  557 + case IP_MTU_DISCOVER:
  558 + case IP_RECVERR:
  559 + case IP_RECVTOS:
  560 +#ifdef IP_FREEBIND
  561 + case IP_FREEBIND:
  562 +#endif
  563 + case IP_MULTICAST_TTL:
  564 + case IP_MULTICAST_LOOP:
551 565 val = 0;
552 566 if (optlen >= sizeof(uint32_t)) {
553 567 if (get_user(val, (uint32_t *)optval))
... ... @@ -619,6 +633,45 @@ static long do_getsockopt(int sockfd, int level, int optname,
619 633 /* These don't just return a single integer */
620 634 goto unimplemented;
621 635 default:
  636 + goto int_case;
  637 + }
  638 + break;
  639 + case SOL_TCP:
  640 + /* TCP options all take an 'int' value. */
  641 + int_case:
  642 + if (get_user(len, optlen))
  643 + return -EFAULT;
  644 + if (len < 0)
  645 + return -EINVAL;
  646 + lv = sizeof(int);
  647 + ret = get_errno(getsockopt(sockfd, level, optname, &val, &lv));
  648 + if (ret < 0)
  649 + return ret;
  650 + val = tswap32(val);
  651 + if (len > lv)
  652 + len = lv;
  653 + if (copy_to_user(optval, &val, len))
  654 + return -EFAULT;
  655 + if (put_user(len, optlen))
  656 + return -EFAULT;
  657 + break;
  658 + case SOL_IP:
  659 + switch(optname) {
  660 + case IP_TOS:
  661 + case IP_TTL:
  662 + case IP_HDRINCL:
  663 + case IP_ROUTER_ALERT:
  664 + case IP_RECVOPTS:
  665 + case IP_RETOPTS:
  666 + case IP_PKTINFO:
  667 + case IP_MTU_DISCOVER:
  668 + case IP_RECVERR:
  669 + case IP_RECVTOS:
  670 +#ifdef IP_FREEBIND
  671 + case IP_FREEBIND:
  672 +#endif
  673 + case IP_MULTICAST_TTL:
  674 + case IP_MULTICAST_LOOP:
622 675 if (get_user(len, optlen))
623 676 return -EFAULT;
624 677 if (len < 0)
... ... @@ -627,14 +680,25 @@ static long do_getsockopt(int sockfd, int level, int optname,
627 680 ret = get_errno(getsockopt(sockfd, level, optname, &val, &lv));
628 681 if (ret < 0)
629 682 return ret;
630   - val = tswap32(val);
631   - if (len > lv)
632   - len = lv;
633   - if (copy_to_user(optval, &val, len))
634   - return -EFAULT;
635   - if (put_user(len, optlen))
636   - return -EFAULT;
  683 + if (len < sizeof(int) && len > 0 && val >= 0 && val < 255) {
  684 + unsigned char ucval = val;
  685 + len = 1;
  686 + if (put_user(len, optlen))
  687 + return -EFAULT;
  688 + if (copy_to_user(optval,&ucval,1))
  689 + return -EFAULT;
  690 + } else {
  691 + val = tswap32(val);
  692 + if (len > sizeof(int))
  693 + len = sizeof(int);
  694 + if (put_user(len, optlen))
  695 + return -EFAULT;
  696 + if (copy_to_user(optval, &val, len))
  697 + return -EFAULT;
  698 + }
637 699 break;
  700 + default:
  701 + goto unimplemented;
638 702 }
639 703 break;
640 704 default:
... ...