Commit 2efbe911d3ea518f5d4648954379f9d5aa02e806
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: | ... | ... |