Support IPv6 link-local addresses

Use `getaddrinfo` in `parse_address` instead of `inet_pton`.
Display Ipv6 addresses with scope identifiers correctly in `get_ip`
functions using `if_indextoname`.
This commit is contained in:
dsee 2024-02-25 09:19:11 +01:00 committed by Wim Taymans
parent c3d3e6f48b
commit 4888b35284
9 changed files with 107 additions and 275 deletions

View file

@ -30,6 +30,7 @@
#include <pipewire/impl.h>
#include <module-rtp/stream.h>
#include "network-utils.h"
#ifdef __FreeBSD__
#define ifr_ifindex ifr_index
@ -195,39 +196,6 @@ short_packet:
return;
}
static int get_ip(const struct sockaddr_storage *sa, char *ip, size_t len)
{
if (sa->ss_family == AF_INET) {
struct sockaddr_in *in = (struct sockaddr_in*)sa;
inet_ntop(sa->ss_family, &in->sin_addr, ip, len);
} else if (sa->ss_family == AF_INET6) {
struct sockaddr_in6 *in = (struct sockaddr_in6*)sa;
inet_ntop(sa->ss_family, &in->sin6_addr, ip, len);
} else
return -EIO;
return 0;
}
static int parse_address(const char *address, uint16_t port,
struct sockaddr_storage *addr, socklen_t *len)
{
struct sockaddr_in *sa4 = (struct sockaddr_in*)addr;
struct sockaddr_in6 *sa6 = (struct sockaddr_in6*)addr;
if (inet_pton(AF_INET, address, &sa4->sin_addr) > 0) {
sa4->sin_family = AF_INET;
sa4->sin_port = htons(port);
*len = sizeof(*sa4);
} else if (inet_pton(AF_INET6, address, &sa6->sin6_addr) > 0) {
sa6->sin6_family = AF_INET6;
sa6->sin6_port = htons(port);
*len = sizeof(*sa6);
} else
return -EINVAL;
return 0;
}
static int make_socket(const struct sockaddr* sa, socklen_t salen, char *ifname)
{
int af, fd, val, res;
@ -272,7 +240,7 @@ static int make_socket(const struct sockaddr* sa, socklen_t salen, char *ifname)
memset(&mr4, 0, sizeof(mr4));
mr4.imr_multiaddr = sa4->sin_addr;
mr4.imr_ifindex = req.ifr_ifindex;
get_ip((struct sockaddr_storage*)sa, addr, sizeof(addr));
get_ip((struct sockaddr_storage*)sa, addr, sizeof(addr), NULL, NULL);
pw_log_info("join IPv4 group: %s", addr);
res = setsockopt(fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mr4, sizeof(mr4));
} else {
@ -289,7 +257,7 @@ static int make_socket(const struct sockaddr* sa, socklen_t salen, char *ifname)
memset(&mr6, 0, sizeof(mr6));
mr6.ipv6mr_multiaddr = sa6->sin6_addr;
mr6.ipv6mr_interface = req.ifr_ifindex;
get_ip((struct sockaddr_storage*)sa, addr, sizeof(addr));
get_ip((struct sockaddr_storage*)sa, addr, sizeof(addr), NULL, NULL);
pw_log_info("join IPv6 group: %s", addr);
res = setsockopt(fd, IPPROTO_IPV6, IPV6_JOIN_GROUP, &mr6, sizeof(mr6));
} else {
@ -617,7 +585,7 @@ int pipewire__module_init(struct pw_impl_module *module, const char *args)
pw_log_error("invalid source.ip %s: %s", str, spa_strerror(res));
goto out;
}
get_ip(&impl->src_addr, addr, sizeof(addr));
get_ip(&impl->src_addr, addr, sizeof(addr), NULL, NULL);
pw_properties_set(stream_props, "rtp.source.ip", addr);
pw_properties_setf(stream_props, "rtp.source.port", "%u", impl->src_port);