_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); struct sockaddr_storage ss; socklen_t ss_len = sizeof(ss); if (!si) { return real_recvfrom(s, buf, len, flags, from, fromlen); } if (!from) { from = (struct sockaddr *)&ss; fromlen = &ss_len; } len = MIN(len, 1500); /* 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_ 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; }