int BIO_sock_info(int sock, enum BIO_sock_info_type type, union BIO_sock_info_u *info) { switch (type) { case BIO_SOCK_INFO_ADDRESS: { socklen_t addr_len; int ret = 0; addr_len = sizeof(*info->addr); ret = getsockname(sock, BIO_ADDR_sockaddr_noconst(info->addr), &addr_len); if (ret == -1) { SYSerr(SYS_F_GETSOCKNAME, get_last_socket_error()); BIOerr(BIO_F_BIO_SOCK_INFO, BIO_R_GETSOCKNAME_ERROR); return 0; } if ((size_t)addr_len > sizeof(*info->addr)) { BIOerr(BIO_F_BIO_SOCK_INFO, BIO_R_GETSOCKNAME_TRUNCATED_ADDRESS); return 0; } } break; default: BIOerr(BIO_F_BIO_SOCK_INFO, BIO_R_UNKNOWN_INFO_TYPE); return 0; } return 1; }
/*- * BIO_accept_ex - Accept new incoming connections * @sock: the listening socket * @addr: the BIO_ADDR to store the peer address in * @options: BIO socket options, applied on the accepted socket. * */ int BIO_accept_ex(int accept_sock, BIO_ADDR *addr_, int options) { socklen_t len; int accepted_sock; BIO_ADDR locaddr; BIO_ADDR *addr = addr_ == NULL ? &locaddr : addr_; len = sizeof(*addr); accepted_sock = accept(accept_sock, BIO_ADDR_sockaddr_noconst(addr), &len); if (accepted_sock == -1) { if (!BIO_sock_should_retry(accepted_sock)) { SYSerr(SYS_F_ACCEPT, get_last_socket_error()); BIOerr(BIO_F_BIO_ACCEPT_EX, BIO_R_ACCEPT_ERROR); } return INVALID_SOCKET; } if (!BIO_socket_nbio(accepted_sock, (options & BIO_SOCK_NONBLOCK) != 0)) { closesocket(accepted_sock); return INVALID_SOCKET; } return accepted_sock; }
/* addrinfo_wrap is used to build our own addrinfo "chain". * (it has only one entry, so calling it a chain may be a stretch) * It should ONLY be called when getaddrinfo() and friends * aren't available, OR when dealing with a non IP protocol * family, such as AF_UNIX * * the return value is 1 on success, or 0 on failure, which * only happens if a memory allocation error occurred. */ static int addrinfo_wrap(int family, int socktype, const void *where, size_t wherelen, unsigned short port, BIO_ADDRINFO **bai) { OPENSSL_assert(bai != NULL); *bai = OPENSSL_zalloc(sizeof(**bai)); if (*bai == NULL) return 0; (*bai)->bai_family = family; (*bai)->bai_socktype = socktype; if (socktype == SOCK_STREAM) (*bai)->bai_protocol = IPPROTO_TCP; if (socktype == SOCK_DGRAM) (*bai)->bai_protocol = IPPROTO_UDP; #ifdef AF_UNIX if (family == AF_UNIX) (*bai)->bai_protocol = 0; #endif { /* Magic: We know that BIO_ADDR_sockaddr_noconst is really just an advanced cast of BIO_ADDR* to struct sockaddr * by the power of union, so while it may seem that we're creating a memory leak here, we are not. It will be all right. */ BIO_ADDR *addr = BIO_ADDR_new(); if (addr != NULL) { BIO_ADDR_rawmake(addr, family, where, wherelen, port); (*bai)->bai_addr = BIO_ADDR_sockaddr_noconst(addr); } } (*bai)->bai_next = NULL; if ((*bai)->bai_addr == NULL) { BIO_ADDRINFO_free(*bai); *bai = NULL; return 0; } return 1; }