X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=src%2Fnetwork%2Fsetsockopt.c;h=612a1947a1f6182b4fd057fef4300c3df32eae5b;hb=ae388becb529428ac926da102f1d025b3c3968da;hp=b50303b86ac52032e13f38b901ba07a62a08bab0;hpb=0b44a0315b47dd8eced9f3b7f31580cf14bbfc01;p=musl diff --git a/src/network/setsockopt.c b/src/network/setsockopt.c index b50303b8..612a1947 100644 --- a/src/network/setsockopt.c +++ b/src/network/setsockopt.c @@ -1,9 +1,46 @@ #include +#include +#include #include "syscall.h" -#include "socketcall.h" + +#define IS32BIT(x) !((x)+0x80000000ULL>>32) +#define CLAMP(x) (int)(IS32BIT(x) ? (x) : 0x7fffffffU+((0ULL+(x))>>63)) int setsockopt(int fd, int level, int optname, const void *optval, socklen_t optlen) { - unsigned long args[] = { fd, level, optname, (unsigned long)optval, optlen }; - return syscall2(__NR_socketcall, SYS_SETSOCKOPT, (long)args); + const struct timeval *tv; + time_t s; + suseconds_t us; + + int r = __socketcall(setsockopt, fd, level, optname, optval, optlen, 0); + + if (r==-ENOPROTOOPT) switch (level) { + case SOL_SOCKET: + switch (optname) { + case SO_RCVTIMEO: + case SO_SNDTIMEO: + if (SO_RCVTIMEO == SO_RCVTIMEO_OLD) break; + if (optlen < sizeof *tv) return __syscall_ret(-EINVAL); + tv = optval; + s = tv->tv_sec; + us = tv->tv_usec; + if (!IS32BIT(s)) return __syscall_ret(-ENOTSUP); + + if (optname==SO_RCVTIMEO) optname=SO_RCVTIMEO_OLD; + if (optname==SO_SNDTIMEO) optname=SO_SNDTIMEO_OLD; + + r = __socketcall(setsockopt, fd, level, optname, + ((long[]){s, CLAMP(us)}), 2*sizeof(long), 0); + break; + case SO_TIMESTAMP: + case SO_TIMESTAMPNS: + if (SO_TIMESTAMP == SO_TIMESTAMP_OLD) break; + if (optname==SO_TIMESTAMP) optname=SO_TIMESTAMP_OLD; + if (optname==SO_TIMESTAMPNS) optname=SO_TIMESTAMPNS_OLD; + r = __socketcall(setsockopt, fd, level, + optname, optval, optlen, 0); + break; + } + } + return __syscall_ret(r); }