- abi_long ret;
- const int n = sizeof(abi_ulong);
-
- switch(num) {
- case SOCKOP_socket:
- {
- abi_ulong domain, type, protocol;
-
- if (get_user_ual(domain, vptr)
- || get_user_ual(type, vptr + n)
- || get_user_ual(protocol, vptr + 2 * n))
- return -TARGET_EFAULT;
-
- ret = do_socket(domain, type, protocol);
- }
- break;
- case SOCKOP_bind:
- {
- abi_ulong sockfd;
- abi_ulong target_addr;
- socklen_t addrlen;
-
- if (get_user_ual(sockfd, vptr)
- || get_user_ual(target_addr, vptr + n)
- || get_user_ual(addrlen, vptr + 2 * n))
- return -TARGET_EFAULT;
-
- ret = do_bind(sockfd, target_addr, addrlen);
- }
- break;
- case SOCKOP_connect:
- {
- abi_ulong sockfd;
- abi_ulong target_addr;
- socklen_t addrlen;
-
- if (get_user_ual(sockfd, vptr)
- || get_user_ual(target_addr, vptr + n)
- || get_user_ual(addrlen, vptr + 2 * n))
- return -TARGET_EFAULT;
-
- ret = do_connect(sockfd, target_addr, addrlen);
- }
- break;
- case SOCKOP_listen:
- {
- abi_ulong sockfd, backlog;
-
- if (get_user_ual(sockfd, vptr)
- || get_user_ual(backlog, vptr + n))
- return -TARGET_EFAULT;
-
- ret = get_errno(listen(sockfd, backlog));
- }
- break;
- case SOCKOP_accept:
- {
- abi_ulong sockfd;
- abi_ulong target_addr, target_addrlen;
-
- if (get_user_ual(sockfd, vptr)
- || get_user_ual(target_addr, vptr + n)
- || get_user_ual(target_addrlen, vptr + 2 * n))
- return -TARGET_EFAULT;
-
- ret = do_accept4(sockfd, target_addr, target_addrlen, 0);
- }
- break;
- case SOCKOP_getsockname:
- {
- abi_ulong sockfd;
- abi_ulong target_addr, target_addrlen;
-
- if (get_user_ual(sockfd, vptr)
- || get_user_ual(target_addr, vptr + n)
- || get_user_ual(target_addrlen, vptr + 2 * n))
- return -TARGET_EFAULT;
-
- ret = do_getsockname(sockfd, target_addr, target_addrlen);
- }
- break;
- case SOCKOP_getpeername:
- {
- abi_ulong sockfd;
- abi_ulong target_addr, target_addrlen;
-
- if (get_user_ual(sockfd, vptr)
- || get_user_ual(target_addr, vptr + n)
- || get_user_ual(target_addrlen, vptr + 2 * n))
- return -TARGET_EFAULT;
-
- ret = do_getpeername(sockfd, target_addr, target_addrlen);
- }
- break;
- case SOCKOP_socketpair:
- {
- abi_ulong domain, type, protocol;
- abi_ulong tab;
-
- if (get_user_ual(domain, vptr)
- || get_user_ual(type, vptr + n)
- || get_user_ual(protocol, vptr + 2 * n)
- || get_user_ual(tab, vptr + 3 * n))
- return -TARGET_EFAULT;
-
- ret = do_socketpair(domain, type, protocol, tab);
- }
- break;
- case SOCKOP_send:
- {
- abi_ulong sockfd;
- abi_ulong msg;
- size_t len;
- abi_ulong flags;
-
- if (get_user_ual(sockfd, vptr)
- || get_user_ual(msg, vptr + n)
- || get_user_ual(len, vptr + 2 * n)
- || get_user_ual(flags, vptr + 3 * n))
- return -TARGET_EFAULT;
-
- ret = do_sendto(sockfd, msg, len, flags, 0, 0);
- }
- break;
- case SOCKOP_recv:
- {
- abi_ulong sockfd;
- abi_ulong msg;
- size_t len;
- abi_ulong flags;
-
- if (get_user_ual(sockfd, vptr)
- || get_user_ual(msg, vptr + n)
- || get_user_ual(len, vptr + 2 * n)
- || get_user_ual(flags, vptr + 3 * n))
- return -TARGET_EFAULT;
-
- ret = do_recvfrom(sockfd, msg, len, flags, 0, 0);
- }
- break;
- case SOCKOP_sendto:
- {
- abi_ulong sockfd;
- abi_ulong msg;
- size_t len;
- abi_ulong flags;
- abi_ulong addr;
- socklen_t addrlen;
-
- if (get_user_ual(sockfd, vptr)
- || get_user_ual(msg, vptr + n)
- || get_user_ual(len, vptr + 2 * n)
- || get_user_ual(flags, vptr + 3 * n)
- || get_user_ual(addr, vptr + 4 * n)
- || get_user_ual(addrlen, vptr + 5 * n))
- return -TARGET_EFAULT;
-
- ret = do_sendto(sockfd, msg, len, flags, addr, addrlen);
- }
- break;
- case SOCKOP_recvfrom:
- {
- abi_ulong sockfd;
- abi_ulong msg;
- size_t len;
- abi_ulong flags;
- abi_ulong addr;
- socklen_t addrlen;
-
- if (get_user_ual(sockfd, vptr)
- || get_user_ual(msg, vptr + n)
- || get_user_ual(len, vptr + 2 * n)
- || get_user_ual(flags, vptr + 3 * n)
- || get_user_ual(addr, vptr + 4 * n)
- || get_user_ual(addrlen, vptr + 5 * n))
- return -TARGET_EFAULT;
-
- ret = do_recvfrom(sockfd, msg, len, flags, addr, addrlen);
- }
- break;
- case SOCKOP_shutdown:
- {
- abi_ulong sockfd, how;
-
- if (get_user_ual(sockfd, vptr)
- || get_user_ual(how, vptr + n))
- return -TARGET_EFAULT;
-
- ret = get_errno(shutdown(sockfd, how));
- }
- break;
- case SOCKOP_sendmsg:
- case SOCKOP_recvmsg:
- {
- abi_ulong fd;
- abi_ulong target_msg;
- abi_ulong flags;
-
- if (get_user_ual(fd, vptr)
- || get_user_ual(target_msg, vptr + n)
- || get_user_ual(flags, vptr + 2 * n))
- return -TARGET_EFAULT;
-
- ret = do_sendrecvmsg(fd, target_msg, flags,
- (num == SOCKOP_sendmsg));
- }
- break;
- case SOCKOP_setsockopt:
- {
- abi_ulong sockfd;
- abi_ulong level;
- abi_ulong optname;
- abi_ulong optval;
- socklen_t optlen;
-
- if (get_user_ual(sockfd, vptr)
- || get_user_ual(level, vptr + n)
- || get_user_ual(optname, vptr + 2 * n)
- || get_user_ual(optval, vptr + 3 * n)
- || get_user_ual(optlen, vptr + 4 * n))
+ static const unsigned ac[] = { /* number of arguments per call */
+ [SOCKOP_socket] = 3, /* domain, type, protocol */
+ [SOCKOP_bind] = 3, /* sockfd, addr, addrlen */
+ [SOCKOP_connect] = 3, /* sockfd, addr, addrlen */
+ [SOCKOP_listen] = 2, /* sockfd, backlog */
+ [SOCKOP_accept] = 3, /* sockfd, addr, addrlen */
+ [SOCKOP_accept4] = 4, /* sockfd, addr, addrlen, flags */
+ [SOCKOP_getsockname] = 3, /* sockfd, addr, addrlen */
+ [SOCKOP_getpeername] = 3, /* sockfd, addr, addrlen */
+ [SOCKOP_socketpair] = 4, /* domain, type, protocol, tab */
+ [SOCKOP_send] = 4, /* sockfd, msg, len, flags */
+ [SOCKOP_recv] = 4, /* sockfd, msg, len, flags */
+ [SOCKOP_sendto] = 6, /* sockfd, msg, len, flags, addr, addrlen */
+ [SOCKOP_recvfrom] = 6, /* sockfd, msg, len, flags, addr, addrlen */
+ [SOCKOP_shutdown] = 2, /* sockfd, how */
+ [SOCKOP_sendmsg] = 3, /* sockfd, msg, flags */
+ [SOCKOP_recvmsg] = 3, /* sockfd, msg, flags */
+ [SOCKOP_setsockopt] = 5, /* sockfd, level, optname, optval, optlen */
+ [SOCKOP_getsockopt] = 5, /* sockfd, level, optname, optval, optlen */
+ };
+ abi_long a[6]; /* max 6 args */
+
+ /* first, collect the arguments in a[] according to ac[] */
+ if (num >= 0 && num < ARRAY_SIZE(ac)) {
+ unsigned i;
+ assert(ARRAY_SIZE(a) >= ac[num]); /* ensure we have space for args */
+ for (i = 0; i < ac[num]; ++i) {
+ if (get_user_ual(a[i], vptr + i * sizeof(abi_long)) != 0) {