📄 socket_wrapper.c
字号:
break; case AF_UNIX: return real_socket(family, type, protocol); default: errno = EAFNOSUPPORT; return -1; } switch (type) { case SOCK_STREAM: break; case SOCK_DGRAM: break; default: errno = EPROTONOSUPPORT; return -1; } switch (protocol) { case 0: break; default: errno = EPROTONOSUPPORT; return -1; } fd = real_socket(AF_UNIX, type, 0); if (fd == -1) return -1; si = (struct socket_info *)calloc(1, sizeof(struct socket_info)); si->family = family; si->type = type; si->protocol = protocol; si->fd = fd; SWRAP_DLIST_ADD(sockets, si); return si->fd;}_PUBLIC_ int swrap_accept(int s, struct sockaddr *addr, socklen_t *addrlen){ struct socket_info *parent_si, *child_si; int fd; struct sockaddr_un un_addr; socklen_t un_addrlen = sizeof(un_addr); struct sockaddr_un un_my_addr; socklen_t un_my_addrlen = sizeof(un_my_addr); struct sockaddr my_addr; socklen_t my_addrlen = sizeof(my_addr); int ret; parent_si = find_socket_info(s); if (!parent_si) { return real_accept(s, addr, addrlen); } memset(&un_addr, 0, sizeof(un_addr)); memset(&un_my_addr, 0, sizeof(un_my_addr)); memset(&my_addr, 0, sizeof(my_addr)); ret = real_accept(s, (struct sockaddr *)&un_addr, &un_addrlen); if (ret == -1) return ret; fd = ret; ret = sockaddr_convert_from_un(parent_si, &un_addr, un_addrlen, parent_si->family, addr, addrlen); if (ret == -1) { close(fd); return ret; } child_si = (struct socket_info *)malloc(sizeof(struct socket_info)); memset(child_si, 0, sizeof(*child_si)); child_si->fd = fd; child_si->family = parent_si->family; child_si->type = parent_si->type; child_si->protocol = parent_si->protocol; child_si->bound = 1; child_si->is_server = 1; ret = real_getsockname(fd, (struct sockaddr *)&un_my_addr, &un_my_addrlen); if (ret == -1) { free(child_si); close(fd); return ret; } ret = sockaddr_convert_from_un(child_si, &un_my_addr, un_my_addrlen, child_si->family, &my_addr, &my_addrlen); if (ret == -1) { free(child_si); close(fd); return ret; } child_si->myname_len = my_addrlen; child_si->myname = sockaddr_dup(&my_addr, my_addrlen); child_si->peername_len = *addrlen; child_si->peername = sockaddr_dup(addr, *addrlen); SWRAP_DLIST_ADD(sockets, child_si); swrap_dump_packet(child_si, addr, SWRAP_ACCEPT_SEND, NULL, 0); swrap_dump_packet(child_si, addr, SWRAP_ACCEPT_RECV, NULL, 0); swrap_dump_packet(child_si, addr, SWRAP_ACCEPT_ACK, NULL, 0); return fd;}static int autobind_start_init;static int autobind_start;/* using sendto() or connect() on an unbound socket would give the recipient no way to reply, as unlike UDP and TCP, a unix domain socket can't auto-assign emphemeral port numbers, so we need to assign it here */static int swrap_auto_bind(struct socket_info *si){ struct sockaddr_un un_addr; struct sockaddr_in in; int i; char type; int ret; int port; struct stat st; if (autobind_start_init != 1) { autobind_start_init = 1; autobind_start = getpid(); autobind_start %= 50000; autobind_start += 10000; } un_addr.sun_family = AF_UNIX; switch (si->type) { case SOCK_STREAM: type = SOCKET_TYPE_CHAR_TCP; break; case SOCK_DGRAM: type = SOCKET_TYPE_CHAR_UDP; break; default: errno = ESOCKTNOSUPPORT; return -1; } if (autobind_start > 60000) { autobind_start = 10000; } for (i=0;i<1000;i++) { port = autobind_start + i; snprintf(un_addr.sun_path, sizeof(un_addr.sun_path), "%s/"SOCKET_FORMAT, socket_wrapper_dir(), type, socket_wrapper_default_iface(), port); if (stat(un_addr.sun_path, &st) == 0) continue; ret = real_bind(si->fd, (struct sockaddr *)&un_addr, sizeof(un_addr)); if (ret == -1) return ret; si->tmp_path = strdup(un_addr.sun_path); si->bound = 1; autobind_start = port + 1; break; } if (i == 1000) { errno = ENFILE; return -1; } memset(&in, 0, sizeof(in)); in.sin_family = AF_INET; in.sin_port = htons(port); in.sin_addr.s_addr = htonl(127<<24 | socket_wrapper_default_iface()); si->myname_len = sizeof(in); si->myname = sockaddr_dup(&in, si->myname_len); return 0;}_PUBLIC_ int swrap_connect(int s, const struct sockaddr *serv_addr, socklen_t addrlen){ int ret; struct sockaddr_un un_addr; struct socket_info *si = find_socket_info(s); if (!si) { return real_connect(s, serv_addr, addrlen); } if (si->bound == 0) { ret = swrap_auto_bind(si); if (ret == -1) return -1; } ret = sockaddr_convert_to_un(si, (const struct sockaddr *)serv_addr, addrlen, &un_addr, 0, NULL); if (ret == -1) return -1; swrap_dump_packet(si, serv_addr, SWRAP_CONNECT_SEND, NULL, 0); ret = real_connect(s, (struct sockaddr *)&un_addr, sizeof(struct sockaddr_un)); /* to give better errors */ if (ret == -1 && errno == ENOENT) { errno = EHOSTUNREACH; } if (ret == 0) { si->peername_len = addrlen; si->peername = sockaddr_dup(serv_addr, addrlen); swrap_dump_packet(si, serv_addr, SWRAP_CONNECT_RECV, NULL, 0); swrap_dump_packet(si, serv_addr, SWRAP_CONNECT_ACK, NULL, 0); } else { swrap_dump_packet(si, serv_addr, SWRAP_CONNECT_UNREACH, NULL, 0); } return ret;}_PUBLIC_ int swrap_bind(int s, const struct sockaddr *myaddr, socklen_t addrlen){ int ret; struct sockaddr_un un_addr; struct socket_info *si = find_socket_info(s); if (!si) { return real_bind(s, myaddr, addrlen); } si->myname_len = addrlen; si->myname = sockaddr_dup(myaddr, addrlen); ret = sockaddr_convert_to_un(si, (const struct sockaddr *)myaddr, addrlen, &un_addr, 1, &si->bcast); if (ret == -1) return -1; unlink(un_addr.sun_path); ret = real_bind(s, (struct sockaddr *)&un_addr, sizeof(struct sockaddr_un)); if (ret == 0) { si->bound = 1; } return ret;}_PUBLIC_ int swrap_listen(int s, int backlog){ int ret; struct socket_info *si = find_socket_info(s); if (!si) { return real_listen(s, backlog); } ret = real_listen(s, backlog); return ret;}_PUBLIC_ int swrap_getpeername(int s, struct sockaddr *name, socklen_t *addrlen){ struct socket_info *si = find_socket_info(s); if (!si) { return real_getpeername(s, name, addrlen); } if (!si->peername) { errno = ENOTCONN; return -1; } memcpy(name, si->peername, si->peername_len); *addrlen = si->peername_len; return 0;}_PUBLIC_ int swrap_getsockname(int s, struct sockaddr *name, socklen_t *addrlen){ struct socket_info *si = find_socket_info(s); if (!si) { return real_getsockname(s, name, addrlen); } memcpy(name, si->myname, si->myname_len); *addrlen = si->myname_len; return 0;}_PUBLIC_ int swrap_getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen){ struct socket_info *si = find_socket_info(s); if (!si) { return real_getsockopt(s, level, optname, optval, optlen); } if (level == SOL_SOCKET) { return real_getsockopt(s, level, optname, optval, optlen); } errno = ENOPROTOOPT; return -1;}_PUBLIC_ int swrap_setsockopt(int s, int level, int optname, const void *optval, socklen_t optlen){ struct socket_info *si = find_socket_info(s); if (!si) { return real_setsockopt(s, level, optname, optval, optlen); } if (level == SOL_SOCKET) { return real_setsockopt(s, level, optname, optval, optlen); } switch (si->family) { case AF_INET: return 0; default: errno = ENOPROTOOPT; return -1; }}_PUBLIC_ ssize_t swrap_recvfrom(int s, void *buf, size_t len, int flags, struct sockaddr *from, socklen_t *fromlen){ struct sockaddr_un un_addr; socklen_t un_addrlen = sizeof(un_addr); int ret; struct socket_info *si = find_socket_info(s); if (!si) { return real_recvfrom(s, buf, len, flags, from, fromlen); } /* irix 6.4 forgets to null terminate the sun_path string :-( */ memset(&un_addr, 0, sizeof(un_addr)); ret = real_recvfrom(s, buf, len, flags, (struct sockaddr *)&un_addr, &un_addrlen); if (ret == -1) return ret; if (sockaddr_convert_from_un(si, &un_addr, un_addrlen, si->family, from, fromlen) == -1) { return -1; } swrap_dump_packet(si, from, SWRAP_RECVFROM, buf, ret); return ret;}_PUBLIC_ ssize_t swrap_sendto(int s, const void *buf, size_t len, int flags, const struct sockaddr *to, socklen_t tolen){ struct sockaddr_un un_addr; int ret; struct socket_info *si = find_socket_info(s); int bcast = 0; if (!si) { return real_sendto(s, buf, len, flags, to, tolen); } if (si->bound == 0) { ret = swrap_auto_bind(si); if (ret == -1) return -1; } ret = sockaddr_convert_to_un(si, to, tolen, &un_addr, 0, &bcast); if (ret == -1) return -1; if (bcast) { struct stat st; unsigned int iface; unsigned int prt = ntohs(((const struct sockaddr_in *)to)->sin_port); char type; type = SOCKET_TYPE_CHAR_UDP; for(iface=0; iface <= MAX_WRAPPED_INTERFACES; iface++) { snprintf(un_addr.sun_path, sizeof(un_addr.sun_path), "%s/"SOCKET_FORMAT, socket_wrapper_dir(), type, iface, prt); if (stat(un_addr.sun_path, &st) != 0) continue; /* ignore the any errors in broadcast sends */ real_sendto(s, buf, len, flags, (struct sockaddr *)&un_addr, sizeof(un_addr)); } swrap_dump_packet(si, to, SWRAP_SENDTO, buf, len); return len; } ret = real_sendto(s, buf, len, flags, (struct sockaddr *)&un_addr, sizeof(un_addr)); /* to give better errors */ if (ret == -1 && errno == ENOENT) { errno = EHOSTUNREACH; } if (ret == -1) { swrap_dump_packet(si, to, SWRAP_SENDTO, buf, len); swrap_dump_packet(si, to, SWRAP_SENDTO_UNREACH, buf, len); } else { swrap_dump_packet(si, to, SWRAP_SENDTO, buf, ret); } return ret;}_PUBLIC_ int swrap_ioctl(int s, int r, void *p){ int ret; struct socket_info *si = find_socket_info(s); int value; if (!si) { return real_ioctl(s, r, p); } ret = real_ioctl(s, r, p); switch (r) { case FIONREAD: value = *((int *)p); if (ret == -1 && errno != EAGAIN && errno != ENOBUFS) { swrap_dump_packet(si, NULL, SWRAP_PENDING_RST, NULL, 0); } else if (value == 0) { /* END OF FILE */ swrap_dump_packet(si, NULL, SWRAP_PENDING_RST, NULL, 0); } break; } return ret;}_PUBLIC_ ssize_t swrap_recv(int s, void *buf, size_t len, int flags){ int ret; struct socket_info *si = find_socket_info(s); if (!si) { return real_recv(s, buf, len, flags); } ret = real_recv(s, buf, len, flags); if (ret == -1 && errno != EAGAIN && errno != ENOBUFS) { swrap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0); } else if (ret == 0) { /* END OF FILE */ swrap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0); } else { swrap_dump_packet(si, NULL, SWRAP_RECV, buf, ret); } return ret;}_PUBLIC_ ssize_t swrap_send(int s, const void *buf, size_t len, int flags){ int ret; struct socket_info *si = find_socket_info(s); if (!si) { return real_send(s, buf, len, flags); } ret = real_send(s, buf, len, flags); if (ret == -1) { swrap_dump_packet(si, NULL, SWRAP_SEND, buf, len); swrap_dump_packet(si, NULL, SWRAP_SEND_RST, NULL, 0); } else { swrap_dump_packet(si, NULL, SWRAP_SEND, buf, ret); } return ret;}_PUBLIC_ int swrap_close(int fd){ struct socket_info *si = find_socket_info(fd); int ret; if (!si) { return real_close(fd); } SWRAP_DLIST_REMOVE(sockets, si); if (si->myname && si->peername) { swrap_dump_packet(si, NULL, SWRAP_CLOSE_SEND, NULL, 0); } ret = real_close(fd); if (si->myname && si->peername) { swrap_dump_packet(si, NULL, SWRAP_CLOSE_RECV, NULL, 0); swrap_dump_packet(si, NULL, SWRAP_CLOSE_ACK, NULL, 0); } if (si->path) free(si->path); if (si->myname) free(si->myname); if (si->peername) free(si->peername); if (si->tmp_path) { unlink(si->tmp_path); free(si->tmp_path); } free(si); return ret;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -