/* * Copyright (C) 2000-2006 Erik Andersen * * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. */ #include #include #include #include #ifdef __NR_socketcall /* Various socketcall numbers */ #define SYS_SOCKET 1 #define SYS_BIND 2 #define SYS_CONNECT 3 #define SYS_LISTEN 4 #define SYS_ACCEPT 5 #define SYS_GETSOCKNAME 6 #define SYS_GETPEERNAME 7 #define SYS_SOCKETPAIR 8 #define SYS_SEND 9 #define SYS_RECV 10 #define SYS_SENDTO 11 #define SYS_RECVFROM 12 #define SYS_SHUTDOWN 13 #define SYS_SETSOCKOPT 14 #define SYS_GETSOCKOPT 15 #define SYS_SENDMSG 16 #define SYS_RECVMSG 17 #define SYS_ACCEPT4 18 #endif /* exposed on x86 since Linux commit 9dea5dc921b5f4045a18c63eb92e84dc274d17eb */ #if defined(__sparc__) || defined(__i386__) #undef __NR_accept #undef __NR_accept4 #undef __NR_bind #undef __NR_connect #undef __NR_getpeername #undef __NR_getsockname #undef __NR_getsockopt #undef __NR_listen #undef __NR_recv #undef __NR_recvfrom #undef __NR_recvmsg #undef __NR_send #undef __NR_sendmsg #undef __NR_sendto #undef __NR_setsockopt #undef __NR_shutdown #undef __NR_socket #undef __NR_socketpair #endif #ifdef L_accept static int __NC(accept)(int sockfd, struct sockaddr *addr, socklen_t *addrlen) { # ifdef __NR_accept return INLINE_SYSCALL(accept, 3, sockfd, addr, addrlen); # else unsigned long args[3]; args[0] = sockfd; args[1] = (unsigned long) addr; args[2] = (unsigned long) addrlen; return __socketcall(SYS_ACCEPT, args); # endif } CANCELLABLE_SYSCALL(int, accept, (int sockfd, struct sockaddr *addr, socklen_t *addrlen), (sockfd, addr, addrlen)) lt_libc_hidden(accept) #endif #ifdef L_accept4 #ifdef __NR_accept4 # define __NR___sys_accept4 __NR_accept4 static _syscall4(int, __sys_accept4, int, fd, struct sockaddr *, addr, socklen_t *, addrlen, int, flags) int accept4(int fd, struct sockaddr *addr, socklen_t * addrlen, int flags) { if (SINGLE_THREAD_P) return __sys_accept4(fd, addr, addrlen, flags); #ifdef __UCLIBC_HAS_THREADS_NATIVE__ else { int oldtype = LIBC_CANCEL_ASYNC (); int result = __sys_accept4(fd, addr, addrlen, flags); LIBC_CANCEL_RESET (oldtype); return result; } #endif } #elif defined(__NR_socketcall) int accept4(int fd, struct sockaddr *addr, socklen_t *addrlen, int flags) { unsigned long args[4]; args[0] = fd; args[1] = (unsigned long) addr; args[2] = (unsigned long) addrlen; args[3] = flags; if (SINGLE_THREAD_P) return __socketcall(SYS_ACCEPT4, args); #ifdef __UCLIBC_HAS_THREADS_NATIVE__ else { int oldtype = LIBC_CANCEL_ASYNC (); int result = __socketcall(SYS_ACCEPT4, args); LIBC_CANCEL_RESET (oldtype); return result; } #endif } #endif #endif #ifdef L_bind int bind(int sockfd, const struct sockaddr *myaddr, socklen_t addrlen) { # ifdef __NR_bind return INLINE_SYSCALL(bind, 3, sockfd, myaddr, addrlen); # else unsigned long args[3]; args[0] = sockfd; args[1] = (unsigned long) myaddr; args[2] = addrlen; return __socketcall(SYS_BIND, args); # endif } libc_hidden_def(bind) #endif #ifdef L_connect static int __NC(connect)(int sockfd, const struct sockaddr *saddr, socklen_t addrlen) { # ifdef __NR_connect return INLINE_SYSCALL(connect, 3, sockfd, saddr, addrlen); # else unsigned long args[3]; args[0] = sockfd; args[1] = (unsigned long) saddr; args[2] = addrlen; return __socketcall(SYS_CONNECT, args); # endif } CANCELLABLE_SYSCALL(int, connect, (int sockfd, const struct sockaddr *saddr, socklen_t addrlen), (sockfd, saddr, addrlen)) lt_libc_hidden(connect) #endif #ifdef L_getpeername int getpeername(int sockfd, struct sockaddr *addr, socklen_t *paddrlen) { # ifdef __NR_getpeername return INLINE_SYSCALL(getpeername, 3, sockfd, addr, paddrlen); # else unsigned long args[3]; args[0] = sockfd; args[1] = (unsigned long) addr; args[2] = (unsigned long) paddrlen; return __socketcall(SYS_GETPEERNAME, args); # endif } #endif #ifdef L_getsockname int getsockname(int sockfd, struct sockaddr *addr, socklen_t * paddrlen) { # ifdef __NR_getsockname return INLINE_SYSCALL(getsockname, 3, sockfd, addr, paddrlen); # else unsigned long args[3]; args[0] = sockfd; args[1] = (unsigned long) addr; args[2] = (unsigned long) paddrlen; return __socketcall(SYS_GETSOCKNAME, args); # endif } libc_hidden_def(getsockname) #endif #ifdef L_getsockopt int getsockopt(int fd, int level, int optname, void *optval, socklen_t *optlen) { # ifdef __NR_getsockopt return INLINE_SYSCALL(getsockopt, 5, fd, level, optname, optval, optlen); # else unsigned long args[5]; args[0] = fd; args[1] = level; args[2] = optname; args[3] = (unsigned long) optval; args[4] = (unsigned long) optlen; return (__socketcall(SYS_GETSOCKOPT, args)); # endif } #endif #ifdef L_listen int listen(int sockfd, int backlog) { # ifdef __NR_listen return INLINE_SYSCALL(listen, 2, sockfd, backlog); # else unsigned long args[2]; args[0] = sockfd; args[1] = backlog; return __socketcall(SYS_LISTEN, args); # endif } libc_hidden_def(listen) #endif #ifdef L_recv static ssize_t __NC(recv)(int sockfd, void *buffer, size_t len, int flags) { # ifdef __NR_recv return (ssize_t)INLINE_SYSCALL(recv, 4, sockfd, buffer, len, flags); # elif defined __NR_recvfrom && defined _syscall6 return __NC(recvfrom)(sockfd, buffer, len, flags, NULL, NULL); # else unsigned long args[4]; args[0] = sockfd; args[1] = (unsigned long) buffer; args[2] = len; args[3] = flags; return (ssize_t)__socketcall(SYS_RECV, args); # endif } CANCELLABLE_SYSCALL(ssize_t, recv, (int sockfd, void *buffer, size_t len, int flags), (sockfd, buffer, len, flags)) lt_libc_hidden(recv) #endif #ifdef L_recvfrom ssize_t __NC(recvfrom)(int sockfd, void *buffer, size_t len, int flags, struct sockaddr *to, socklen_t *tolen) { # if defined __NR_recvfrom && defined _syscall6 return (ssize_t)INLINE_SYSCALL(recvfrom, 6, sockfd, buffer, len, flags, to, tolen); # else unsigned long args[6]; args[0] = sockfd; args[1] = (unsigned long) buffer; args[2] = len; args[3] = flags; args[4] = (unsigned long) to; args[5] = (unsigned long) tolen; return (ssize_t)__socketcall(SYS_RECVFROM, args); # endif } CANCELLABLE_SYSCALL(ssize_t, recvfrom, (int sockfd, void *buffer, size_t len, int flags, struct sockaddr *to, socklen_t *tolen), (sockfd, buffer, len, flags, to, tolen)) lt_libc_hidden(recvfrom) #endif #ifdef L_recvmsg static ssize_t __NC(recvmsg)(int sockfd, struct msghdr *msg, int flags) { # ifdef __NR_recvmsg return (ssize_t)INLINE_SYSCALL(recvmsg, 3, sockfd, msg, flags); # else unsigned long args[3]; args[0] = sockfd; args[1] = (unsigned long) msg; args[2] = flags; return (ssize_t)__socketcall(SYS_RECVMSG, args); # endif } CANCELLABLE_SYSCALL(ssize_t, recvmsg, (int sockfd, struct msghdr *msg, int flags), (sockfd, msg, flags)) lt_libc_hidden(recvmsg) #endif #ifdef L_send static ssize_t __NC(send)(int sockfd, const void *buffer, size_t len, int flags) { # ifdef __NR_send return (ssize_t)INLINE_SYSCALL(send, 4, sockfd, buffer, len, flags); # elif defined __NR_sendto && defined _syscall6 return __NC(sendto)(sockfd, buffer, len, flags, NULL, 0); # else unsigned long args[4]; args[0] = sockfd; args[1] = (unsigned long) buffer; args[2] = len; args[3] = flags; return (ssize_t)__socketcall(SYS_SEND, args); # endif } CANCELLABLE_SYSCALL(ssize_t, send, (int sockfd, const void *buffer, size_t len, int flags), (sockfd, buffer, len, flags)) lt_libc_hidden(send) #endif #ifdef L_sendmsg static ssize_t __NC(sendmsg)(int sockfd, const struct msghdr *msg, int flags) { # ifdef __NR_sendmsg return (ssize_t)INLINE_SYSCALL(sendmsg, 3, sockfd, msg, flags); # else unsigned long args[3]; args[0] = sockfd; args[1] = (unsigned long) msg; args[2] = flags; return (ssize_t)__socketcall(SYS_SENDMSG, args); # endif } CANCELLABLE_SYSCALL(ssize_t, sendmsg, (int sockfd, const struct msghdr *msg, int flags), (sockfd, msg, flags)) lt_libc_hidden(sendmsg) #endif #ifdef L_sendto ssize_t __NC(sendto)(int sockfd, const void *buffer, size_t len, int flags, const struct sockaddr *to, socklen_t tolen) { # if defined __NR_sendto && defined _syscall6 return (ssize_t)INLINE_SYSCALL(sendto, 6, sockfd, buffer, len, flags, to, tolen); # else unsigned long args[6]; args[0] = sockfd; args[1] = (unsigned long) buffer; args[2] = len; args[3] = flags; args[4] = (unsigned long) to; args[5] = tolen; return (ssize_t)__socketcall(SYS_SENDTO, args); # endif } CANCELLABLE_SYSCALL(ssize_t, sendto, (int sockfd, const void *buffer, size_t len, int flags, const struct sockaddr *to, socklen_t tolen), (sockfd, buffer, len, flags, to, tolen)) lt_libc_hidden(sendto) #endif #ifdef L_setsockopt int setsockopt(int fd, int level, int optname, const void *optval, socklen_t optlen) { # ifdef __NR_setsockopt return INLINE_SYSCALL(setsockopt, 5, fd, level, optname, optval, optlen); # else unsigned long args[5]; args[0] = fd; args[1] = level; args[2] = optname; args[3] = (unsigned long) optval; args[4] = optlen; return __socketcall(SYS_SETSOCKOPT, args); # endif } libc_hidden_def(setsockopt) #endif #ifdef L_shutdown int shutdown(int sockfd, int how) { # ifdef __NR_shutdown return INLINE_SYSCALL(shutdown, 2, sockfd, how); # else unsigned long args[2]; args[0] = sockfd; args[1] = how; return __socketcall(SYS_SHUTDOWN, args); # endif } #endif #ifdef L_socket int socket(int family, int type, int protocol) { # ifdef __NR_socket return INLINE_SYSCALL(socket, 3, family, type, protocol); # else unsigned long args[3]; args[0] = family; args[1] = type; args[2] = (unsigned long) protocol; return __socketcall(SYS_SOCKET, args); # endif } libc_hidden_def(socket) #endif #ifdef L_socketpair int socketpair(int family, int type, int protocol, int sockvec[2]) { # ifdef __NR_socketpair return INLINE_SYSCALL(socketpair, 4, family, type, protocol, sockvec); # else unsigned long args[4]; args[0] = family; args[1] = type; args[2] = protocol; args[3] = (unsigned long) sockvec; return __socketcall(SYS_SOCKETPAIR, args); # endif } #endif