📄 syscall.c
字号:
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 + -