Skip to content

Commit

Permalink
Use getaddrinfo instead of gethostbyname (fixes #3156) (#3159)
Browse files Browse the repository at this point in the history
  • Loading branch information
lminiero committed Mar 6, 2023
1 parent 96a22b0 commit acb1378
Show file tree
Hide file tree
Showing 6 changed files with 271 additions and 135 deletions.
46 changes: 46 additions & 0 deletions src/ip-utils.c
Original file line number Diff line number Diff line change
Expand Up @@ -321,3 +321,49 @@ char *janus_network_detect_local_ip_as_string(janus_network_query_options addr_t
return NULL;
return g_strdup(janus_network_address_string_from_buffer(&buf));
}

int janus_network_resolve_address(const char *host, struct sockaddr_storage *address) {
if(!host || !address)
return -EINVAL;
/* Check whether we need to resolve the address*/
gboolean resolved = FALSE;
if(strstr(host, ":")) {
struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)address;
addr6->sin6_family = AF_INET6;
if(inet_pton(AF_INET6, host, &addr6->sin6_addr) == 1) {
/* Numeric IPv6 address */
resolved = TRUE;
}
} else {
struct sockaddr_in *addr = (struct sockaddr_in *)address;
addr->sin_family = AF_INET;
if(inet_pton(AF_INET, host, &addr->sin_addr) == 1) {
/* Numeric IPv4 address */
resolved = TRUE;
}
}
if(!resolved) {
/* Perform a getaddrinfo on the address */
struct addrinfo *result = NULL;
int res = getaddrinfo(host, NULL, NULL, &result);
if(res == 0) {
/* Address resolved */
struct addrinfo *temp = result;
while(temp && !resolved) {
if(result->ai_family == AF_INET6) {
resolved = TRUE;
struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)address;
memcpy(&addr6->sin6_addr, result->ai_addr, sizeof(*addr6));
} else if(result->ai_family == AF_INET) {
resolved = TRUE;
struct sockaddr_in *addr = (struct sockaddr_in *)address;
memcpy(&addr->sin_addr, result->ai_addr, sizeof(*addr));
}
temp = temp->ai_next;
}
freeaddrinfo(result);
}
}
/* Done */
return resolved ? 0 : -1;
}
22 changes: 18 additions & 4 deletions src/ip-utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,7 @@ int janus_network_string_is_valid_address(janus_network_query_options addr_type,
* janus_network_query_options_ipv6 or janus_network_query_options_any_ip)
* \param user_value The IP address string to check
* \param result Pointer to a valid janus_network_address instance that will contain the result
* \return 0 in case of success, -EINVAL otherwise otherwise
* \return 0 in case of success, -EINVAL otherwise
*/
int janus_network_string_to_address(janus_network_query_options addr_type, const char *user_value, janus_network_address *result);

Expand All @@ -224,7 +224,7 @@ int janus_network_string_to_address(janus_network_query_options addr_type, const
* \param ifas The list of interfaces to look into (e.g., as returned from getifaddrs)
* \param iface The interface name or IP address to look for
* \param result Pointer to a valid janus_network_address instance that will contain the result
* \return 0 in case of success, -EINVAL otherwise otherwise
* \return 0 in case of success, -EINVAL otherwise
*/
int janus_network_lookup_interface(const struct ifaddrs *ifas, const char *iface, janus_network_address *result);

Expand All @@ -233,7 +233,7 @@ int janus_network_lookup_interface(const struct ifaddrs *ifas, const char *iface
* \param addr_type The type of address you're interested in (janus_network_query_options_ipv4,
* janus_network_query_options_ipv6 or janus_network_query_options_any_ip)
* \param result Pointer to a valid janus_network_address instance that will contain the result
* \return 0 in case of success, -EINVAL otherwise otherwise
* \return 0 in case of success, -EINVAL otherwise
*/
int janus_network_detect_local_ip(janus_network_query_options addr_type, janus_network_address *result);

Expand All @@ -242,9 +242,23 @@ int janus_network_detect_local_ip(janus_network_query_options addr_type, janus_n
* \note The string is allocated with g_strdup and so needs to be freed by the caller
* \param addr_type The type of address you're interested in (janus_network_query_options_ipv4,
* janus_network_query_options_ipv6 or janus_network_query_options_any_ip)
* \return 0 in case of success, -EINVAL otherwise otherwise
* \return 0 in case of success, -EINVAL otherwise
*/
char *janus_network_detect_local_ip_as_string(janus_network_query_options addr_type);
///@}

/** @name Janus helper methods to resolve external addresses
*/
/*!
* \brief Wrapper inet_pton or getaddrinfo to fill a struct sockaddr_storage structure from an address
* \note The method will only do inet_pton if it detects a numeric address, and will perform
* a getaddrinfo otherwise. Notice that, since the request is synchronous, it may have to wait
* for a DNS response to that request.
* \param host The address to resolve
* \param address A pointer to the struct sockaddr_storage to write the result to
* \return 0 in case of success, a negative integer otherwise
*/
int janus_network_resolve_address(const char *host, struct sockaddr_storage *address);
///@}

#endif
54 changes: 30 additions & 24 deletions src/plugins/janus_audiobridge.c
Original file line number Diff line number Diff line change
Expand Up @@ -6560,23 +6560,25 @@ static void *janus_audiobridge_handler(void *data) {
g_free(participant->plainrtp_media.remote_audio_ip);
participant->plainrtp_media.remote_audio_ip = g_strdup(ip);
participant->plainrtp_media.remote_audio_rtp_port = port;
struct sockaddr_in audio_server_addr = { 0 };
memset(&audio_server_addr, 0, sizeof(struct sockaddr_in));
audio_server_addr.sin_family = AF_INET;
gboolean have_audio_server_ip = TRUE;
if(participant->plainrtp_media.remote_audio_ip && inet_aton(participant->plainrtp_media.remote_audio_ip, &audio_server_addr.sin_addr) == 0) { /* Not a numeric IP... */
/* Note that gethostbyname() may block waiting for response if it triggers on the wire request.*/
struct hostent *host = gethostbyname(participant->plainrtp_media.remote_audio_ip); /* ...resolve name */
if(!host) {
JANUS_LOG(LOG_ERR, "[AudioBridge-%p] Couldn't get host (%s)\n", session, participant->plainrtp_media.remote_audio_ip);
have_audio_server_ip = FALSE;
} else {
audio_server_addr.sin_addr = *(struct in_addr *)host->h_addr_list;
/* Resolve the address */
gboolean have_audio_server_ip = FALSE;
struct sockaddr_storage audio_server_addr = { 0 };
if(janus_network_resolve_address(participant->plainrtp_media.remote_audio_ip, &audio_server_addr) < 0) {
JANUS_LOG(LOG_ERR, "[AudioBridge-%p] Couldn't get host '%s'\n", session,
participant->plainrtp_media.remote_audio_ip);
} else {
/* Address resolved */
have_audio_server_ip = TRUE;
if(audio_server_addr.ss_family == AF_INET6) {
struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&audio_server_addr;
addr6->sin6_port = htons(port);
} else if(audio_server_addr.ss_family == AF_INET) {
struct sockaddr_in *addr = (struct sockaddr_in *)&audio_server_addr;
addr->sin_port = htons(port);
}
}
audio_server_addr.sin_port = htons(participant->plainrtp_media.remote_audio_rtp_port);
if(have_audio_server_ip) {
if(connect(participant->plainrtp_media.audio_rtp_fd, (struct sockaddr *)&audio_server_addr, sizeof(struct sockaddr)) == -1) {
if(connect(participant->plainrtp_media.audio_rtp_fd, (struct sockaddr *)&audio_server_addr, sizeof(audio_server_addr)) == -1) {
JANUS_LOG(LOG_ERR, "[AudioBridge-%p] Couldn't connect audio RTP? (%s:%d)\n", session,
participant->plainrtp_media.remote_audio_ip, participant->plainrtp_media.remote_audio_rtp_port);
JANUS_LOG(LOG_ERR, "[AudioBridge-%p] -- %d (%s)\n", session, errno, g_strerror(errno));
Expand Down Expand Up @@ -8712,11 +8714,15 @@ static int janus_audiobridge_plainrtp_allocate_port(janus_audiobridge_plainrtp_m
JANUS_LOG(LOG_ERR, "No ports available in range: %u -- %u\n", rtp_range_min, rtp_range_max);
break;
}
if(rtp_fd == -1)
rtp_fd = socket(AF_INET6, SOCK_DGRAM, 0);
if(rtp_fd == -1) {
rtp_fd = socket(AF_INET, SOCK_DGRAM, 0);
JANUS_LOG(LOG_ERR, "Error creating socket... %d (%s)\n", errno, g_strerror(errno));
break;
}
if(rtp_fd == -1) {
JANUS_LOG(LOG_ERR, "Error creating socket...\n");
int v6only = 0;
if(setsockopt(rtp_fd, IPPROTO_IPV6, IPV6_V6ONLY, &v6only, sizeof(v6only)) != 0) {
JANUS_LOG(LOG_ERR, "setsockopt on socket failed... %d (%s)\n", errno, g_strerror(errno));
break;
}
int rtp_port = rtp_port_next;
Expand All @@ -8727,11 +8733,11 @@ static int janus_audiobridge_plainrtp_allocate_port(janus_audiobridge_plainrtp_m
rtp_port_next = rtp_range_min;
rtp_port_wrap = TRUE;
}
struct sockaddr_in rtp_address = { 0 };
rtp_address.sin_family = AF_INET;
rtp_address.sin_port = htons(rtp_port);
inet_pton(AF_INET, local_ip, &rtp_address.sin_addr.s_addr);
if(bind(rtp_fd, (struct sockaddr *)(&rtp_address), sizeof(struct sockaddr)) < 0) {
struct sockaddr_in6 rtp_address = { 0 };
rtp_address.sin6_family = AF_INET6;
rtp_address.sin6_port = htons(rtp_port);
rtp_address.sin6_addr = in6addr_any;
if(bind(rtp_fd, (struct sockaddr *)(&rtp_address), sizeof(rtp_address)) < 0) {
/* rtp_fd still unbound, reuse it in the next iteration */
} else {
media->audio_rtp_fd = rtp_fd;
Expand All @@ -8758,7 +8764,7 @@ static void *janus_audiobridge_plainrtp_relay_thread(void *data) {

/* File descriptors */
socklen_t addrlen;
struct sockaddr_in remote = { 0 };
struct sockaddr_storage remote = { 0 };
int resfd = 0, bytes = 0, pollerrs = 0;
struct pollfd fds[2];
int pipe_fd = participant->plainrtp_media.pipefd[0];
Expand Down Expand Up @@ -8835,7 +8841,7 @@ static void *janus_audiobridge_plainrtp_relay_thread(void *data) {
}
/* Got an RTP packet */
addrlen = sizeof(remote);
bytes = recvfrom(fds[i].fd, buffer, 1500, 0, (struct sockaddr*)&remote, &addrlen);
bytes = recvfrom(fds[i].fd, buffer, 1500, 0, (struct sockaddr *)&remote, &addrlen);
if(bytes < 0) {
/* Failed to read? */
continue;
Expand Down
Loading

0 comments on commit acb1378

Please sign in to comment.