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: | ... | ... |