📄 syscall.c
字号:
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 != TARGET_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 != TARGET_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 TARGET_SOL_SOCKET: switch (optname) { /* Options with 'int' argument. */ case TARGET_SO_DEBUG: optname = SO_DEBUG; break; case TARGET_SO_REUSEADDR: optname = SO_REUSEADDR; break; case TARGET_SO_TYPE: optname = SO_TYPE; break; case TARGET_SO_ERROR: optname = SO_ERROR; break; case TARGET_SO_DONTROUTE: optname = SO_DONTROUTE; break; case TARGET_SO_BROADCAST: optname = SO_BROADCAST; break; case TARGET_SO_SNDBUF: optname = SO_SNDBUF; break; case TARGET_SO_RCVBUF: optname = SO_RCVBUF; break; case TARGET_SO_KEEPALIVE: optname = SO_KEEPALIVE; break; case TARGET_SO_OOBINLINE: optname = SO_OOBINLINE; break; case TARGET_SO_NO_CHECK: optname = SO_NO_CHECK; break; case TARGET_SO_PRIORITY: optname = SO_PRIORITY; break;#ifdef SO_BSDCOMPAT case TARGET_SO_BSDCOMPAT: optname = SO_BSDCOMPAT; break;#endif case TARGET_SO_PASSCRED: optname = SO_PASSCRED; break; case TARGET_SO_TIMESTAMP: optname = SO_TIMESTAMP; break; case TARGET_SO_RCVLOWAT: optname = SO_RCVLOWAT; break; case TARGET_SO_RCVTIMEO: optname = SO_RCVTIMEO; break; case TARGET_SO_SNDTIMEO: optname = SO_SNDTIMEO; break; break; default: goto unimplemented; } if (optlen < sizeof(uint32_t)) return -EINVAL; val = tget32(optval); ret = get_errno(setsockopt(sockfd, SOL_SOCKET, optname, &val, sizeof(val))); 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 TARGET_SOL_SOCKET: level = SOL_SOCKET; switch (optname) { case TARGET_SO_LINGER: case TARGET_SO_RCVTIMEO: case TARGET_SO_SNDTIMEO: case TARGET_SO_PEERCRED: case TARGET_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_socket(int domain, int type, int protocol){#if defined(TARGET_MIPS) switch(type) { case TARGET_SOCK_DGRAM: type = SOCK_DGRAM; break; case TARGET_SOCK_STREAM: type = SOCK_STREAM; break; case TARGET_SOCK_RAW: type = SOCK_RAW; break; case TARGET_SOCK_RDM: type = SOCK_RDM; break; case TARGET_SOCK_SEQPACKET: type = SOCK_SEQPACKET; break; case TARGET_SOCK_PACKET: type = SOCK_PACKET; break; }#endif return get_errno(socket(domain, type, protocol));}static long do_bind(int sockfd, target_ulong target_addr, socklen_t addrlen){ void *addr = alloca(addrlen); target_to_host_sockaddr(addr, target_addr, addrlen); return get_errno(bind(sockfd, addr, addrlen));}static long do_connect(int sockfd, target_ulong target_addr, socklen_t addrlen){ void *addr = alloca(addrlen); target_to_host_sockaddr(addr, target_addr, addrlen); return get_errno(connect(sockfd, addr, addrlen));}static long do_sendrecvmsg(int fd, target_ulong target_msg, int flags, int send){ long ret; struct target_msghdr *msgp; struct msghdr msg; int count; struct iovec *vec; target_ulong target_vec; lock_user_struct(msgp, target_msg, 1); if (msgp->msg_name) { msg.msg_namelen = tswap32(msgp->msg_namelen); msg.msg_name = alloca(msg.msg_namelen); target_to_host_sockaddr(msg.msg_name, tswapl(msgp->msg_name), msg.msg_namelen); } else { msg.msg_name = NULL; msg.msg_namelen = 0; } msg.msg_controllen = 2 * tswapl(msgp->msg_controllen); msg.msg_control = alloca(msg.msg_controllen); msg.msg_flags = tswap32(msgp->msg_flags); count = tswapl(msgp->msg_iovlen); vec = alloca(count * sizeof(struct iovec)); target_vec = tswapl(msgp->msg_iov); lock_iovec(vec, target_vec, count, send); msg.msg_iovlen = count; msg.msg_iov = vec; if (send) { target_to_host_cmsg(&msg, msgp); ret = get_errno(sendmsg(fd, &msg, flags)); } else { ret = get_errno(recvmsg(fd, &msg, flags)); if (!is_error(ret)) host_to_target_cmsg(msgp, &msg); } unlock_iovec(vec, target_vec, count, !send); return ret;}static long do_accept(int fd, target_ulong target_addr, target_ulong target_addrlen){ socklen_t addrlen = tget32(target_addrlen); void *addr = alloca(addrlen); long ret; ret = get_errno(accept(fd, addr, &addrlen)); if (!is_error(ret)) { host_to_target_sockaddr(target_addr, addr, addrlen); tput32(target_addrlen, addrlen); } return ret;}static long do_getpeername(int fd, target_ulong target_addr, target_ulong target_addrlen){ socklen_t addrlen = tget32(target_addrlen); void *addr = alloca(target_addrlen); long ret; ret = get_errno(getpeername(fd, addr, &addrlen)); if (!is_error(ret)) { host_to_target_sockaddr(target_addr, addr, addrlen); tput32(target_addrlen, addrlen); } return ret;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -