Example #1
0
DEFINE_SYSCALL(socketcall, int, call, uintptr_t *, args)
{
	if (call < 1 || call > SYS_SENDMMSG)
		return -L_EINVAL;
	if (!mm_check_read(args, nargs[call]))
		return -L_EFAULT;
	switch (call)
	{
	case SYS_SOCKET:
		return sys_socket(args[0], args[1], args[2]);

	case SYS_BIND:
		return sys_bind(args[0], (const struct sockaddr *)args[1], args[2]);

	case SYS_CONNECT:
		return sys_connect(args[0], (const struct sockaddr *)args[1], args[2]);

	case SYS_LISTEN:
		return sys_listen(args[0], args[1]);

	case SYS_ACCEPT:
		return sys_accept(args[0], (struct sockaddr *)args[1], (int *)args[2]);

	case SYS_GETSOCKNAME:
		return sys_getsockname(args[0], (struct sockaddr *)args[1], (int *)args[2]);

	case SYS_GETPEERNAME:
		return sys_getpeername(args[0], (struct sockaddr *)args[1], (int *)args[2]);

	case SYS_SEND:
		return sys_send(args[0], (const void *)args[1], args[2], args[3]);

	case SYS_RECV:
		return sys_recv(args[0], (void *)args[1], args[2], args[3]);

	case SYS_SENDTO:
		return sys_sendto(args[0], (const void *)args[1], args[2], args[3], (const struct sockaddr *)args[4], args[5]);
		
	case SYS_RECVFROM:
		return sys_recvfrom(args[0], (void *)args[1], args[2], args[3], (struct sockaddr *)args[4], (int *)args[5]);

	case SYS_SHUTDOWN:
		return sys_shutdown(args[0], args[1]);

	case SYS_SETSOCKOPT:
		return sys_setsockopt(args[0], args[1], args[2], (const void *)args[3], args[4]);

	case SYS_GETSOCKOPT:
		return sys_getsockopt(args[0], args[1], args[2], (void *)args[3], (int *)args[4]);

	case SYS_SENDMSG:
		return sys_sendmsg(args[0], (const struct msghdr *)args[1], args[2]);

	case SYS_RECVMSG:
		return sys_recvmsg(args[0], (struct msghdr *)args[1], args[2]);

	case SYS_ACCEPT4:
		return sys_accept4(args[0], (struct sockaddr *)args[1], (int *)args[2], args[3]);

	case SYS_SENDMMSG:
		return sys_sendmmsg(args[0], (struct mmsghdr *)args[1], args[2], args[3]);

	default:
	{
		log_error("Unimplemented socketcall: %d", call);
		return -L_EINVAL;
	}
	}
}
int main()
{
#if defined(SYS_sendmmsg)
    int s, fd_null;
    struct sockaddr_in sin1, from;
    pid_t pid = 0;
    char buf[2][1024];
    fd_set rdfds;
    struct mmsghdr msgs[2];
    struct iovec iov[2];
    socklen_t fromlen;

    /* initialize sockaddr's */
    sin1.sin_family = AF_INET;
    sin1.sin_port = htons((getpid() % 32768) + 11000);
    sin1.sin_addr.s_addr = INADDR_ANY;

    pid = start_server(&sin1);

    fromlen = sizeof(from);

    memset(msgs, 0, sizeof(msgs));
    iov[0].iov_base = buf[0];
    iov[0].iov_len = sizeof(buf[0]);
    msgs[0].msg_hdr.msg_iov = &iov[0];
    msgs[0].msg_hdr.msg_iovlen = 1;
    iov[1].iov_base = buf[1];
    iov[1].iov_len = sizeof(buf[1]);
    msgs[1].msg_hdr.msg_iov = &iov[1];
    msgs[1].msg_hdr.msg_iovlen = 1;

    fd_null = open("/dev/null", O_WRONLY);

    sys_sendmmsg(-1, msgs, 2, 0);
    //staptest// sendmmsg (-1, XXXX, 2, 0x0) = -NNNN (EBADF)

    sys_sendmmsg(fd_null, msgs, 2, MSG_DONTWAIT);
    //staptest// sendmmsg (NNNN, XXXX, 2, MSG_DONTWAIT) = -NNNN (ENOTSOCK)

    s = socket(PF_INET, SOCK_DGRAM, 0);
    //staptest// socket (PF_INET, SOCK_DGRAM, IPPROTO_IP) = NNNN

    sys_sendmmsg(s, msgs, 2, 0);
    //staptest// sendmmsg (NNNN, XXXX, 2, 0x0) = -NNNN (EDESTADDRREQ)

    sys_sendmmsg(s, (struct mmsghdr *)-1, 2, 0);
    //staptest// sendmmsg (NNNN, 0x[f]+, 2, 0x0) = -NNNN (EFAULT)

    close(s);
    //staptest// close (NNNN) = 0

    s = socket(PF_INET, SOCK_STREAM, 0);
    //staptest// socket (PF_INET, SOCK_STREAM, IPPROTO_IP) = NNNN

    connect(s, (struct sockaddr *)&sin1, sizeof(sin1));
    //staptest// connect (NNNN, {AF_INET, 0.0.0.0, NNNN}, 16) = 0

    // Note that the exact failure return value can differ here, so
    // we'll just ignore it. Also note that on a 32-bit kernel (i686
    // for instance), MAXSTRINGLEN is only 256. Passing a -1 as the
    // flags value can produce a string that will cause argstr to get
    // too big. So, we'll make the end of the argument optional.
    sys_sendmmsg(s, msgs, 2, -1);
    //staptest// sendmmsg (NNNN, XXXX, 2, MSG_[^ ]+[[[[|XXXX]]]]?) = NNNN

    close(s);
    //staptest// close (NNNN) = 0

    s = socket(PF_INET, SOCK_STREAM, 0);
    //staptest// socket (PF_INET, SOCK_STREAM, IPPROTO_IP) = NNNN

    connect(s, (struct sockaddr *)&sin1, sizeof(sin1));
    //staptest// connect (NNNN, {AF_INET, 0.0.0.0, NNNN}, 16) = 0

    // We don't want to wait for -1 vectors, since we'd be waiting for
    // a long time...
    sys_sendmmsg(s, msgs, -1, MSG_DONTWAIT);
    //staptest// sendmmsg (NNNN, XXXX, 4294967295, MSG_DONTWAIT)

    close(s);
    //staptest// close (NNNN) = 0

    s = socket(PF_INET, SOCK_STREAM, 0);
    //staptest// socket (PF_INET, SOCK_STREAM, IPPROTO_IP) = NNNN

    connect(s, (struct sockaddr *)&sin1, sizeof(sin1));
    //staptest// connect (NNNN, {AF_INET, 0.0.0.0, NNNN}, 16) = 0

    sys_sendmmsg(s, msgs, 2, MSG_DONTWAIT);
    //staptest// sendmmsg (NNNN, XXXX, 2, MSG_DONTWAIT) = NNNN

    close(s);
    //staptest// close (NNNN) = 0

    close(fd_null);
    //staptest// close (NNNN) = 0

    if (pid > 0)
	(void)kill(pid, SIGKILL);	/* kill server */
    //staptest// kill (NNNN, SIGKILL) = 0
#endif

    return 0;
}