Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use getaddrinfo instead of gethostbyname (fixes #3156) #3159

Merged
merged 1 commit into from
Mar 6, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 @@ -6561,23 +6561,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 @@ -8713,11 +8715,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 @@ -8728,11 +8734,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 @@ -8759,7 +8765,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 @@ -8836,7 +8842,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