⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 syscall.c

📁 qemu虚拟机代码
💻 C
📖 第 1 页 / 共 5 页
字号:
    if (wfd_p) {        target_wfds = lock_user(wfd_p, sizeof(target_long) * n, 1);        wfds_ptr = target_to_host_fds(&wfds, target_wfds, n);    } else {        target_wfds = NULL;        wfds_ptr = NULL;    }    if (efd_p) {        target_efds = lock_user(efd_p, sizeof(target_long) * n, 1);        efds_ptr = target_to_host_fds(&efds, target_efds, n);    } else {        target_efds = NULL;        efds_ptr = NULL;    }                if (target_tv) {        target_to_host_timeval(&tv, target_tv);        tv_ptr = &tv;    } else {        tv_ptr = NULL;    }    ret = get_errno(select(n, rfds_ptr, wfds_ptr, efds_ptr, tv_ptr));    ok = !is_error(ret);    if (ok) {        host_to_target_fds(target_rfds, rfds_ptr, n);        host_to_target_fds(target_wfds, wfds_ptr, n);        host_to_target_fds(target_efds, efds_ptr, n);        if (target_tv) {            host_to_target_timeval(target_tv, &tv);        }    }    if (target_rfds)        unlock_user(target_rfds, rfd_p, ok ? sizeof(target_long) * n : 0);    if (target_wfds)        unlock_user(target_wfds, wfd_p, ok ? sizeof(target_long) * n : 0);    if (target_efds)        unlock_user(target_efds, efd_p, ok ? sizeof(target_long) * n : 0);    return ret;}static inline void target_to_host_sockaddr(struct sockaddr *addr,                                           target_ulong target_addr,                                           socklen_t len){    struct target_sockaddr *target_saddr;    target_saddr = lock_user(target_addr, len, 1);    memcpy(addr, target_saddr, len);    addr->sa_family = tswap16(target_saddr->sa_family);    unlock_user(target_saddr, target_addr, 0);}static inline void host_to_target_sockaddr(target_ulong target_addr,                                           struct sockaddr *addr,                                           socklen_t len){    struct target_sockaddr *target_saddr;    target_saddr = lock_user(target_addr, len, 0);    memcpy(target_saddr, addr, len);    target_saddr->sa_family = tswap16(addr->sa_family);    unlock_user(target_saddr, target_addr, len);}/* ??? Should this also swap msgh->name?  */static inline void target_to_host_cmsg(struct msghdr *msgh,                                       struct target_msghdr *target_msgh){    struct cmsghdr *cmsg = CMSG_FIRSTHDR(msgh);    struct target_cmsghdr *target_cmsg = TARGET_CMSG_FIRSTHDR(target_msgh);    socklen_t space = 0;    while (cmsg && target_cmsg) {        void *data = CMSG_DATA(cmsg);        void *target_data = TARGET_CMSG_DATA(target_cmsg);        int len = tswapl(target_cmsg->cmsg_len)                   - TARGET_CMSG_ALIGN(sizeof (struct target_cmsghdr));        space += CMSG_SPACE(len);        if (space > msgh->msg_controllen) {            space -= CMSG_SPACE(len);            gemu_log("Host cmsg overflow\n");            break;        }        cmsg->cmsg_level = tswap32(target_cmsg->cmsg_level);        cmsg->cmsg_type = tswap32(target_cmsg->cmsg_type);        cmsg->cmsg_len = CMSG_LEN(len);        if (cmsg->cmsg_level != SOL_SOCKET || cmsg->cmsg_type != SCM_RIGHTS) {            gemu_log("Unsupported ancillary data: %d/%d\n", cmsg->cmsg_level, cmsg->cmsg_type);            memcpy(data, target_data, len);        } else {            int *fd = (int *)data;            int *target_fd = (int *)target_data;            int i, numfds = len / sizeof(int);            for (i = 0; i < numfds; i++)                fd[i] = tswap32(target_fd[i]);        }        cmsg = CMSG_NXTHDR(msgh, cmsg);        target_cmsg = TARGET_CMSG_NXTHDR(target_msgh, target_cmsg);    }    msgh->msg_controllen = space;}/* ??? Should this also swap msgh->name?  */static inline void host_to_target_cmsg(struct target_msghdr *target_msgh,                                       struct msghdr *msgh){    struct cmsghdr *cmsg = CMSG_FIRSTHDR(msgh);    struct target_cmsghdr *target_cmsg = TARGET_CMSG_FIRSTHDR(target_msgh);    socklen_t space = 0;    while (cmsg && target_cmsg) {        void *data = CMSG_DATA(cmsg);        void *target_data = TARGET_CMSG_DATA(target_cmsg);        int len = cmsg->cmsg_len - CMSG_ALIGN(sizeof (struct cmsghdr));        space += TARGET_CMSG_SPACE(len);        if (space > tswapl(target_msgh->msg_controllen)) {            space -= TARGET_CMSG_SPACE(len);            gemu_log("Target cmsg overflow\n");            break;        }        target_cmsg->cmsg_level = tswap32(cmsg->cmsg_level);        target_cmsg->cmsg_type = tswap32(cmsg->cmsg_type);        target_cmsg->cmsg_len = tswapl(TARGET_CMSG_LEN(len));        if (cmsg->cmsg_level != SOL_SOCKET || cmsg->cmsg_type != SCM_RIGHTS) {            gemu_log("Unsupported ancillary data: %d/%d\n", cmsg->cmsg_level, cmsg->cmsg_type);            memcpy(target_data, data, len);        } else {            int *fd = (int *)data;            int *target_fd = (int *)target_data;            int i, numfds = len / sizeof(int);            for (i = 0; i < numfds; i++)                target_fd[i] = tswap32(fd[i]);        }        cmsg = CMSG_NXTHDR(msgh, cmsg);        target_cmsg = TARGET_CMSG_NXTHDR(target_msgh, target_cmsg);    }    msgh->msg_controllen = tswapl(space);}static long do_setsockopt(int sockfd, int level, int optname,                           target_ulong optval, socklen_t optlen){    int val, ret;                switch(level) {    case SOL_TCP:        /* TCP options all take an 'int' value.  */        if (optlen < sizeof(uint32_t))            return -EINVAL;                val = tget32(optval);        ret = get_errno(setsockopt(sockfd, level, optname, &val, sizeof(val)));        break;    case SOL_IP:        switch(optname) {        case IP_TOS:        case IP_TTL:        case IP_HDRINCL:        case IP_ROUTER_ALERT:        case IP_RECVOPTS:        case IP_RETOPTS:        case IP_PKTINFO:        case IP_MTU_DISCOVER:        case IP_RECVERR:        case IP_RECVTOS:#ifdef IP_FREEBIND        case IP_FREEBIND:#endif        case IP_MULTICAST_TTL:        case IP_MULTICAST_LOOP:            val = 0;            if (optlen >= sizeof(uint32_t)) {                val = tget32(optval);            } else if (optlen >= 1) {                val = tget8(optval);            }            ret = get_errno(setsockopt(sockfd, level, optname, &val, sizeof(val)));            break;        default:            goto unimplemented;        }        break;    case SOL_SOCKET:        switch (optname) {            /* Options with 'int' argument.  */        case SO_DEBUG:        case SO_REUSEADDR:        case SO_TYPE:        case SO_ERROR:        case SO_DONTROUTE:        case SO_BROADCAST:        case SO_SNDBUF:        case SO_RCVBUF:        case SO_KEEPALIVE:        case SO_OOBINLINE:        case SO_NO_CHECK:        case SO_PRIORITY:#ifdef SO_BSDCOMPAT        case SO_BSDCOMPAT:#endif        case SO_PASSCRED:        case SO_TIMESTAMP:        case SO_RCVLOWAT:        case SO_RCVTIMEO:        case SO_SNDTIMEO:            if (optlen < sizeof(uint32_t))                return -EINVAL;            val = tget32(optval);            ret = get_errno(setsockopt(sockfd, level, optname, &val, sizeof(val)));            break;        default:            goto unimplemented;        }        break;    default:    unimplemented:        gemu_log("Unsupported setsockopt level=%d optname=%d \n", level, optname);        ret = -ENOSYS;    }    return ret;}static long do_getsockopt(int sockfd, int level, int optname,                           target_ulong optval, target_ulong optlen){    int len, lv, val, ret;    switch(level) {    case SOL_SOCKET:	switch (optname) {	case SO_LINGER:	case SO_RCVTIMEO:	case SO_SNDTIMEO:	case SO_PEERCRED:	case SO_PEERNAME:	    /* These don't just return a single integer */	    goto unimplemented;        default:            goto int_case;        }        break;    case SOL_TCP:        /* TCP options all take an 'int' value.  */    int_case:        len = tget32(optlen);        if (len < 0)            return -EINVAL;        lv = sizeof(int);        ret = get_errno(getsockopt(sockfd, level, optname, &val, &lv));        if (ret < 0)            return ret;        val = tswap32(val);        if (len > lv)            len = lv;        if (len == 4)            tput32(optval, val);        else            tput8(optval, val);        tput32(optlen, len);        break;    case SOL_IP:        switch(optname) {        case IP_TOS:        case IP_TTL:        case IP_HDRINCL:        case IP_ROUTER_ALERT:        case IP_RECVOPTS:        case IP_RETOPTS:        case IP_PKTINFO:        case IP_MTU_DISCOVER:        case IP_RECVERR:        case IP_RECVTOS:#ifdef IP_FREEBIND        case IP_FREEBIND:#endif        case IP_MULTICAST_TTL:        case IP_MULTICAST_LOOP:            len = tget32(optlen);            if (len < 0)                return -EINVAL;            lv = sizeof(int);            ret = get_errno(getsockopt(sockfd, level, optname, &val, &lv));            if (ret < 0)                return ret;            if (len < sizeof(int) && len > 0 && val >= 0 && val < 255) {                len = 1;                tput32(optlen, len);                tput8(optval, val);            } else {                if (len > sizeof(int))                    len = sizeof(int);                tput32(optlen, len);                tput32(optval, val);            }            break;        default:            goto unimplemented;        }        break;    default:    unimplemented:        gemu_log("getsockopt level=%d optname=%d not yet supported\n",                 level, optname);        ret = -ENOSYS;        break;    }    return ret;}static void lock_iovec(struct iovec *vec, target_ulong target_addr,                       int count, int copy){    struct target_iovec *target_vec;    target_ulong base;    int i;    target_vec = lock_user(target_addr, count * sizeof(struct target_iovec), 1);    for(i = 0;i < count; i++) {        base = tswapl(target_vec[i].iov_base);        vec[i].iov_len = tswapl(target_vec[i].iov_len);        vec[i].iov_base = lock_user(base, vec[i].iov_len, copy);    }    unlock_user (target_vec, target_addr, 0);}static void unlock_iovec(struct iovec *vec, target_ulong target_addr,                         int count, int copy){    struct target_iovec *target_vec;    target_ulong base;    int i;    target_vec = lock_user(target_addr, count * sizeof(struct target_iovec), 1);    for(i = 0;i < count; i++) {        base = tswapl(target_vec[i].iov_base);        unlock_user(vec[i].iov_base, base, copy ? vec[i].iov_len : 0);    }    unlock_user (target_vec, target_addr, 0);}static long do_socketcall(int num, target_ulong vptr){    long ret;    const int n = sizeof(target_ulong);    switch(num) {    case SOCKOP_socket:	{            int domain = tgetl(vptr);            int type = tgetl(vptr + n);            int protocol = tgetl(vptr + 2 * n);            ret = get_errno(socket(domain, type, protocol));	}        break;    case SOCKOP_bind:	{            int sockfd = tgetl(vptr);            target_ulong target_addr = tgetl(vptr + n);            socklen_t addrlen = tgetl(vptr + 2 * n);            void *addr = alloca(addrlen);            target_to_host_sockaddr(addr, target_addr, addrlen);            ret = get_errno(bind(sockfd, addr, addrlen));        }        break;    case SOCKOP_connect:        {            int sockfd = tgetl(vptr);            target_ulong target_addr = tgetl(vptr + n);            socklen_t addrlen = tgetl(vptr + 2 * n);            void *addr = alloca(addrlen);            target_to_host_sockaddr(addr, target_addr, addrlen);            ret = get_errno(connect(sockfd, addr, addrlen));        }        break;    case SOCKOP_listen:        {            int sockfd = tgetl(vptr);            int backlog = tgetl(vptr + n);            ret = get_errno(listen(sockfd, backlog));        }        break;    case SOCKOP_accept:        {            int sockfd = tgetl(vptr);            target_ulong target_addr = tgetl(vptr + n);            target_ulong target_addrlen = tgetl(vptr + 2 * n);            socklen_t addrlen = tget32(target_addrlen);            void *addr = alloca(addrlen);            ret = get_errno(accept(sockfd, addr, &addrlen));            if (!is_error(ret)) {                host_to_target_sockaddr(target_addr, addr, addrlen);                tput32(target_addrlen, addrlen);            }        }        break;    case SOCKOP_getsockname:        {            int sockfd = tgetl(vptr);            target_ulong target_addr = tgetl(vptr + n);            target_ulong target_addrlen = tgetl(vptr + 2 * n);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -