From ea350935d9dc55245a2ed75044f5ac4837858730 Mon Sep 17 00:00:00 2001 From: nickkelsey Date: Wed, 15 Mar 2023 21:02:28 -0700 Subject: [PATCH] IPv6 site-local multicast --- hdhomerun_discover.c | 90 ++++++++++++++++++++++++++++------------ hdhomerun_sock_posix.c | 2 + hdhomerun_sock_windows.c | 2 + 3 files changed, 67 insertions(+), 27 deletions(-) diff --git a/hdhomerun_discover.c b/hdhomerun_discover.c index 5904e28..6a375d6 100644 --- a/hdhomerun_discover.c +++ b/hdhomerun_discover.c @@ -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,39 +609,70 @@ 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); - 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); - sock_addr_in.sin6_port = htons(HDHOMERUN_DISCOVER_UDP_PORT); + 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_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) { + 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; + } - struct hdhomerun_discover_sock_t *dss = default_dss->next; - while (dss) { - if (!dss->active) { dss = dss->next; - continue; } + } + + 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; + } - bool linklocal = hdhomerun_sock_sockaddr_is_ipv6_linklocal((const struct sockaddr *)&dss->local_ip); - if ((linklocal && !send_linklocal) || (!linklocal && !send_general)) { 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; } } diff --git a/hdhomerun_sock_posix.c b/hdhomerun_sock_posix.c index 03fb557..f610e13 100644 --- a/hdhomerun_sock_posix.c +++ b/hdhomerun_sock_posix.c @@ -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; diff --git a/hdhomerun_sock_windows.c b/hdhomerun_sock_windows.c index 824c803..41c0719 100644 --- a/hdhomerun_sock_windows.c +++ b/hdhomerun_sock_windows.c @@ -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;