// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 OR ISC #include #if !defined(OPENSSL_NO_SOCK) #include #include "../internal.h" #include "./internal.h" BIO_ADDR *BIO_ADDR_new(void) { BIO_ADDR *ret = OPENSSL_zalloc(sizeof(BIO_ADDR)); if (ret == NULL) { return NULL; } ret->sa.sa_family = AF_UNSPEC; return ret; } void BIO_ADDR_free(BIO_ADDR *ap) { OPENSSL_free(ap); } int BIO_ADDR_copy(BIO_ADDR *dst, const BIO_ADDR *src) { GUARD_PTR(dst); GUARD_PTR(src); if (src->sa.sa_family == AF_UNSPEC) { BIO_ADDR_clear(dst); return 1; } if (src->sa.sa_family == AF_INET) { OPENSSL_memcpy(&dst->s_in, &src->sa, sizeof(dst->s_in)); return 1; } #ifdef AF_INET6 if (src->sa.sa_family == AF_INET6) { OPENSSL_memcpy(&dst->s_in6, &src->sa, sizeof(dst->s_in6)); return 1; } #endif #ifdef AWS_LC_HAS_AF_UNIX if (src->sa.sa_family == AF_UNIX) { OPENSSL_memcpy(&dst->s_un, &src->sa, sizeof(dst->s_un)); return 1; } #endif return 0; } BIO_ADDR *BIO_ADDR_dup(const BIO_ADDR *ap) { GUARD_PTR(ap); BIO_ADDR *ret = BIO_ADDR_new(); if (ret == NULL) { return NULL; } if (1 != BIO_ADDR_copy(ret, ap)) { BIO_ADDR_free(ret); ret = NULL; } return ret; } void BIO_ADDR_clear(BIO_ADDR *ap) { if (ap == NULL) { return; } OPENSSL_cleanse(ap, sizeof(BIO_ADDR)); ap->sa.sa_family = AF_UNSPEC; } int BIO_ADDR_family(const BIO_ADDR *ap) { GUARD_PTR(ap); return ap->sa.sa_family; } int BIO_ADDR_rawmake(BIO_ADDR *ap, int family, const void *where, size_t wherelen, unsigned short port) { GUARD_PTR(ap); if (family == AF_INET) { if (wherelen != sizeof(struct in_addr)) { return 0; } OPENSSL_cleanse(&ap->s_in, sizeof(ap->s_in)); ap->s_in.sin_family = family; ap->s_in.sin_port = port; ap->s_in.sin_addr = *(struct in_addr *)where; return 1; } #ifdef AF_INET6 if (family == AF_INET6) { if (wherelen != sizeof(struct in6_addr)) { return 0; } OPENSSL_cleanse(&ap->s_in6, sizeof(ap->s_in6)); ap->s_in6.sin6_family = family; ap->s_in6.sin6_port = port; ap->s_in6.sin6_addr = *(struct in6_addr *)where; return 1; } #endif #ifdef AWS_LC_HAS_AF_UNIX if (family == AF_UNIX) { GUARD_PTR(where); // wherelen is expected to be the length of the path string // not including the terminating NUL. if (wherelen + 1 > sizeof(ap->s_un.sun_path)) { return 0; } OPENSSL_cleanse(&ap->s_un, sizeof(ap->s_un)); ap->s_un.sun_family = family; OPENSSL_strlcpy(ap->s_un.sun_path, where, wherelen); return 1; } #endif return 0; } int BIO_ADDR_rawaddress(const BIO_ADDR *ap, void *p, size_t *l) { size_t len = 0; const void *addrptr = NULL; GUARD_PTR(ap); if (ap->sa.sa_family == AF_INET) { len = sizeof(ap->s_in.sin_addr); addrptr = &ap->s_in.sin_addr; } #ifdef AF_INET6 else if (ap->sa.sa_family == AF_INET6) { len = sizeof(ap->s_in6.sin6_addr); addrptr = &ap->s_in6.sin6_addr; } #endif #ifdef AWS_LC_HAS_AF_UNIX else if (ap->sa.sa_family == AF_UNIX) { // len does not include the null len = OPENSSL_strnlen(ap->s_un.sun_path, sizeof(ap->s_un.sun_path)); addrptr = &ap->s_un.sun_path; } #endif if (addrptr == NULL) { return 0; } if (l != NULL) { *l = len; } if (p != NULL) { OPENSSL_memcpy(p, addrptr, len); if (ap->sa.sa_family == AF_UNIX) { // OpenSSL does not write the terminating NUL ((char *)p)[len] = '\0'; } } return 1; } unsigned short BIO_ADDR_rawport(const BIO_ADDR *ap) { GUARD_PTR(ap); if (ap->sa.sa_family == AF_INET) { return ap->s_in.sin_port; } #ifdef AF_INET6 if (ap->sa.sa_family == AF_INET6) { return ap->s_in6.sin6_port; } #endif return 0; } #endif // !defined(OPENSSL_NO_SOCK)