IPv6 site-local multicast

This commit is contained in:
nickkelsey 2023-03-15 21:02:28 -07:00
commit ea350935d9
3 changed files with 67 additions and 27 deletions

View file

@ -65,7 +65,8 @@ struct hdhomerun_discover_t {
struct hdhomerun_debug_t *dbg;
};
static uint8_t hdhomerun_discover_ipv6_multicast_ip[16] = { 0xFF, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x76 };
static uint8_t hdhomerun_discover_ipv6_linklocal_multicast_ip[16] = { 0xFF, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x76 };
static uint8_t hdhomerun_discover_ipv6_sitelocal_multicast_ip[16] = { 0xFF, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x76 };
static void hdhomerun_discover_sock_free(struct hdhomerun_discover_sock_t *dss)
{
@ -132,6 +133,8 @@ static void hdhomerun_discover_sock_add_ipv6(void *arg, uint32_t ifindex, const
return;
}
hdhomerun_sock_set_ttl(dss->sock, 64);
/* Bind socket. */
local_ip_in6->sin6_port = htons(hdhomerun_discover_get_local_port(ds));
@ -191,6 +194,8 @@ static void hdhomerun_discover_sock_add_ipv4(void *arg, uint32_t ifindex, const
return;
}
hdhomerun_sock_set_ttl(dss->sock, 64);
/* Bind socket. */
local_ip_in->sin_port = htons(hdhomerun_discover_get_local_port(ds));
@ -604,15 +609,13 @@ static void hdhomerun_discover_send_ipv6_multicast(struct hdhomerun_discover_t *
hdhomerun_discover_sock_flush_list(ds, ds->ipv6_socks);
hdhomerun_discover_sock_recv_list_append_list(recv_list, ds->ipv6_socks);
if (flags & HDHOMERUN_DISCOVER_FLAGS_IPV6_LINKLOCAL) {
struct sockaddr_in6 sock_addr_in;
memset(&sock_addr_in, 0, sizeof(sock_addr_in));
sock_addr_in.sin6_family = AF_INET6;
memcpy(sock_addr_in.sin6_addr.s6_addr, hdhomerun_discover_ipv6_multicast_ip, 16);
memcpy(sock_addr_in.sin6_addr.s6_addr, hdhomerun_discover_ipv6_linklocal_multicast_ip, 16);
sock_addr_in.sin6_port = htons(HDHOMERUN_DISCOVER_UDP_PORT);
bool send_general = (flags & HDHOMERUN_DISCOVER_FLAGS_IPV6_GENERAL) != 0;
bool send_linklocal = (flags & HDHOMERUN_DISCOVER_FLAGS_IPV6_LINKLOCAL) != 0;
struct hdhomerun_discover_sock_t *dss = default_dss->next;
while (dss) {
if (!dss->active) {
@ -620,8 +623,7 @@ static void hdhomerun_discover_send_ipv6_multicast(struct hdhomerun_discover_t *
continue;
}
bool linklocal = hdhomerun_sock_sockaddr_is_ipv6_linklocal((const struct sockaddr *)&dss->local_ip);
if ((linklocal && !send_linklocal) || (!linklocal && !send_general)) {
if (!hdhomerun_sock_sockaddr_is_ipv6_linklocal((const struct sockaddr *)&dss->local_ip)) {
dss = dss->next;
continue;
}
@ -640,6 +642,40 @@ static void hdhomerun_discover_send_ipv6_multicast(struct hdhomerun_discover_t *
}
}
if (flags & HDHOMERUN_DISCOVER_FLAGS_IPV6_GENERAL) {
struct sockaddr_in6 sock_addr_in;
memset(&sock_addr_in, 0, sizeof(sock_addr_in));
sock_addr_in.sin6_family = AF_INET6;
memcpy(sock_addr_in.sin6_addr.s6_addr, hdhomerun_discover_ipv6_sitelocal_multicast_ip, 16);
sock_addr_in.sin6_port = htons(HDHOMERUN_DISCOVER_UDP_PORT);
struct hdhomerun_discover_sock_t *dss = default_dss->next;
while (dss) {
if (!dss->active) {
dss = dss->next;
continue;
}
if (hdhomerun_sock_sockaddr_is_ipv6_linklocal((const struct sockaddr *)&dss->local_ip)) {
dss = dss->next;
continue;
}
hdhomerun_sock_set_ipv6_multicast_ifindex(dss->sock, dss->ifindex);
struct sockaddr_in6 *local_ip_in = (struct sockaddr_in6 *)&dss->local_ip;
sock_addr_in.sin6_scope_id = local_ip_in->sin6_scope_id;
if (!hdhomerun_discover_send_request(ds, dss, (const struct sockaddr *)&sock_addr_in, device_types, device_types_count, device_id)) {
dss = dss->next;
continue;
}
dss = dss->next;
}
}
}
static void hdhomerun_discover_send_ipv4_broadcast(struct hdhomerun_discover_t *ds, uint32_t flags, const uint32_t device_types[], size_t device_types_count, uint32_t device_id, struct hdhomerun_discover_sock_t **recv_list)
{
struct hdhomerun_discover_sock_t *default_dss = ds->ipv4_socks;

View file

@ -126,9 +126,11 @@ void hdhomerun_sock_set_ttl(struct hdhomerun_sock_t *sock, uint8_t ttl)
int sock_opt = (int)(unsigned int)ttl;
if (sock->af == AF_INET) {
setsockopt(sock->sock, IPPROTO_IP, IP_TTL, (char *)&sock_opt, sizeof(sock_opt));
setsockopt(sock->sock, IPPROTO_IP, IP_MULTICAST_TTL, (char *)&sock_opt, sizeof(sock_opt));
}
if (sock->af == AF_INET6) {
setsockopt(sock->sock, IPPROTO_IPV6, IPV6_UNICAST_HOPS, (char *)&sock_opt, sizeof(sock_opt));
setsockopt(sock->sock, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, (char *)&sock_opt, sizeof(sock_opt));
}
sock->ttl_set = ttl;

View file

@ -211,9 +211,11 @@ void hdhomerun_sock_set_ttl(struct hdhomerun_sock_t *sock, uint8_t ttl)
int sock_opt = (int)(unsigned int)ttl;
if (sock->af == AF_INET) {
setsockopt(sock->sock, IPPROTO_IP, IP_TTL, (char *)&sock_opt, sizeof(sock_opt));
setsockopt(sock->sock, IPPROTO_IP, IP_MULTICAST_TTL, (char *)&sock_opt, sizeof(sock_opt));
}
if (sock->af == AF_INET6) {
setsockopt(sock->sock, IPPROTO_IPV6, IPV6_UNICAST_HOPS, (char *)&sock_opt, sizeof(sock_opt));
setsockopt(sock->sock, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, (char *)&sock_opt, sizeof(sock_opt));
}
sock->ttl_set = ttl;