diff options
Diffstat (limited to 'libc-top-half/musl/src/network/setsockopt.c')
-rw-r--r-- | libc-top-half/musl/src/network/setsockopt.c | 46 |
1 files changed, 46 insertions, 0 deletions
diff --git a/libc-top-half/musl/src/network/setsockopt.c b/libc-top-half/musl/src/network/setsockopt.c new file mode 100644 index 0000000..612a194 --- /dev/null +++ b/libc-top-half/musl/src/network/setsockopt.c @@ -0,0 +1,46 @@ +#include <sys/socket.h> +#include <sys/time.h> +#include <errno.h> +#include "syscall.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) +{ + 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); +} |