static int dup_internal(const struct socket_info *si_oldd, int fd) { struct socket_info *si_newd; si_newd = (struct socket_info *)calloc(1, sizeof(struct socket_info)); si_newd->fd = fd; si_newd->family = si_oldd->family; si_newd->type = si_oldd->type; si_newd->protocol = si_oldd->protocol; si_newd->bound = si_oldd->bound; si_newd->bcast = si_oldd->bcast; if (si_oldd->path) si_newd->path = strdup(si_oldd->path); if (si_oldd->tmp_path) si_newd->tmp_path = strdup(si_oldd->tmp_path); si_newd->myname = sockaddr_dup(si_oldd->myname, si_oldd->myname_len); si_newd->myname_len = si_oldd->myname_len; si_newd->peername = sockaddr_dup(si_oldd->peername, si_oldd->peername_len); si_newd->peername_len = si_oldd->peername_len; si_newd->io = si_oldd->io; SWRAP_DLIST_ADD(sockets, si_newd); return fd; }
_PUBLIC_ int swrap_socket(int family, int type, int protocol) { struct socket_info *si; int fd; if (!socket_wrapper_dir()) { return real_socket(family, type, protocol); } switch (family) { case AF_INET: #ifdef HAVE_IPV6 case AF_INET6: #endif 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; } #if 0 switch (protocol) { case 0: break; default: errno = EPROTONOSUPPORT; return -1; } #endif 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, len; int ret; parent_si = find_socket_info(s); if (!parent_si) { return real_accept(s, addr, addrlen); } /* * assume out sockaddr have the same size as the in parent * socket family */ my_addrlen = socket_length(parent_si->family); if (my_addrlen <= 0) { errno = EINVAL; return -1; } my_addr = (struct sockaddr *)malloc(my_addrlen); if (my_addr == NULL) { return -1; } memset(&un_addr, 0, sizeof(un_addr)); memset(&un_my_addr, 0, sizeof(un_my_addr)); ret = real_accept(s, (struct sockaddr *)&un_addr, &un_addrlen); if (ret == -1) { free(my_addr); return ret; } fd = ret; len = my_addrlen; ret = sockaddr_convert_from_un(parent_si, &un_addr, un_addrlen, parent_si->family, my_addr, &len); if (ret == -1) { free(my_addr); 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; child_si->connected = 1; child_si->peername_len = len; child_si->peername = sockaddr_dup(my_addr, len); if (addr != NULL && addrlen != NULL) { *addrlen = len; if (*addrlen >= len) memcpy(addr, my_addr, len); *addrlen = 0; } ret = real_getsockname(fd, (struct sockaddr *)&un_my_addr, &un_my_addrlen); if (ret == -1) { free(child_si); close(fd); return ret; } len = my_addrlen; ret = sockaddr_convert_from_un(child_si, &un_my_addr, un_my_addrlen, child_si->family, my_addr, &len); if (ret == -1) { free(child_si); free(my_addr); close(fd); return ret; } child_si->myname_len = len; child_si->myname = sockaddr_dup(my_addr, len); free(my_addr); 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; }
_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; }