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,7 +547,21 @@ static long do_setsockopt(int sockfd, int level, int optname,
547 break; 547 break;
548 case SOL_IP: 548 case SOL_IP:
549 switch(optname) { 549 switch(optname) {
  550 + case IP_TOS:
  551 + case IP_TTL:
550 case IP_HDRINCL: 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 val = 0; 565 val = 0;
552 if (optlen >= sizeof(uint32_t)) { 566 if (optlen >= sizeof(uint32_t)) {
553 if (get_user(val, (uint32_t *)optval)) 567 if (get_user(val, (uint32_t *)optval))
@@ -619,6 +633,45 @@ static long do_getsockopt(int sockfd, int level, int optname, @@ -619,6 +633,45 @@ static long do_getsockopt(int sockfd, int level, int optname,
619 /* These don't just return a single integer */ 633 /* These don't just return a single integer */
620 goto unimplemented; 634 goto unimplemented;
621 default: 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 if (get_user(len, optlen)) 675 if (get_user(len, optlen))
623 return -EFAULT; 676 return -EFAULT;
624 if (len < 0) 677 if (len < 0)
@@ -627,14 +680,25 @@ static long do_getsockopt(int sockfd, int level, int optname, @@ -627,14 +680,25 @@ static long do_getsockopt(int sockfd, int level, int optname,
627 ret = get_errno(getsockopt(sockfd, level, optname, &val, &lv)); 680 ret = get_errno(getsockopt(sockfd, level, optname, &val, &lv));
628 if (ret < 0) 681 if (ret < 0)
629 return ret; 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 break; 699 break;
  700 + default:
  701 + goto unimplemented;
638 } 702 }
639 break; 703 break;
640 default: 704 default: