Revision 2efbe911
b/linux-user/syscall.c | ||
---|---|---|
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 | 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 | 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: |
Also available in: Unified diff