Re: [FFmpeg-devel] [PATCH v3] avformat: enable UDP IPv6 multicast interface selection using zone index
This message has been marked as Public on 04/19/2024 10:23Z. On Thursday, April 11, 2024 3:01 PM Ignjatović, Lazar (RS) wrote: > avformat: enable UDP IPv6 multicast interface selection using zone index > > Enabled IPv6 interface selection using zone index. Properly resolved > interface index in places where default 0 interface index is used > (marked with TODO: within udp.c). Adjusted binding for multicast > sockets that are used for reading from the network. > > For mcast addresses, bind to mcast address is attempted as before. > In case that this fails, which will happen on Windows, socket is bound > to INADDR_ANY/IN6ADDR_ANY_INIT depending on address family. Actual > interface selection is performed using udp_set_multicast_interface to > point to the desired interface for sending. Anyone got a chance to take a look at the final version of this patch? Any comments? Lazar Ignjatović Associate Software Engineer Cubic Defense // Digital Intelligence cubic.com ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
[FFmpeg-devel] [PATCH v3] avformat: enable UDP IPv6 multicast interface selection using zone index
avformat: enable UDP IPv6 multicast interface selection using zone index Enabled IPv6 interface selection using zone index. Properly resolved interface index in places where default 0 interface index is used (marked with TODO: within udp.c). Adjusted binding for multicast sockets that are used for reading from the network. For mcast addresses, bind to mcast address is attempted as before. In case that this fails, which will happen on Windows, socket is bound to INADDR_ANY/IN6ADDR_ANY_INIT depending on address family. Actual interface selection is performed using udp_set_multicast_interface to point to the desired interface for sending. Closes: #368 Signed-off-by: Lazar Ignjatovic --- NOTE: Due to comments, this patch is proposed as one of two alternatives The other alternative uses `localaddr` for defining interfaces. V1 -> V2 reverted iface resolution for IPv4 MCAST_JOIN_SOURCE_GROUP V2 -> V3 resolved conflicts configure | 3 ++ doc/protocols.texi| 2 +- libavformat/network.h | 6 +++ libavformat/udp.c | 85 +++ 4 files changed, 88 insertions(+), 8 deletions(-) diff --git a/configure b/configure index 55f1fc354d..96183e58b3 100755 --- a/configure +++ b/configure @@ -2311,6 +2311,7 @@ HEADERS_LIST=" valgrind_valgrind_h windows_h winsock2_h +iphlpapi_h " INTRINSICS_LIST=" @@ -6483,6 +6484,8 @@ if ! disabled network; then check_struct winsock2.h "struct sockaddr" sa_len check_type ws2tcpip.h "struct sockaddr_in6" check_type ws2tcpip.h "struct sockaddr_storage" +check_headers iphlpapi.h -liphlpapi && network_extralibs="$network_extralibs -liphlpapi" || disable iphlpapi_h +check_func_headers iphlpapi.h GetBestInterfaceEx $network_extralibs else disable network fi diff --git a/doc/protocols.texi b/doc/protocols.texi index f54600b846..a8892845d3 100644 --- a/doc/protocols.texi +++ b/doc/protocols.texi @@ -2027,7 +2027,7 @@ packet bursts. Override the local UDP port to bind with. @item localaddr=@var{addr} -Local IP address of a network interface used for sending packets or joining +Local IPv4 address of a network interface used for sending packets or joining multicast groups. @item pkt_size=@var{size} diff --git a/libavformat/network.h b/libavformat/network.h index ca214087fc..2461b651d4 100644 --- a/libavformat/network.h +++ b/libavformat/network.h @@ -38,6 +38,10 @@ #include #include +#if HAVE_IPHLPAPI_H +#include +#endif + #ifndef EPROTONOSUPPORT #define EPROTONOSUPPORT WSAEPROTONOSUPPORT #endif @@ -64,6 +68,8 @@ int ff_neterrno(void); #include #include #include +#include +#include #define ff_neterrno() AVERROR(errno) #endif /* HAVE_WINSOCK2_H */ diff --git a/libavformat/udp.c b/libavformat/udp.c index c1ebdd1222..fa2f62b0b7 100644 --- a/libavformat/udp.c +++ b/libavformat/udp.c @@ -36,6 +36,7 @@ #include "libavutil/opt.h" #include "libavutil/log.h" #include "libavutil/time.h" +#include "libavutil/avstring.h" #include "network.h" #include "os_support.h" #include "url.h" @@ -220,8 +221,7 @@ static int udp_join_multicast_group(int sockfd, struct sockaddr *addr, struct ipv6_mreq mreq6; memcpy(&mreq6.ipv6mr_multiaddr, &(((struct sockaddr_in6 *)addr)->sin6_addr), sizeof(struct in6_addr)); -//TODO: Interface index should be looked up from local_addr -mreq6.ipv6mr_interface = 0; +mreq6.ipv6mr_interface = ((struct sockaddr_in6 *)addr)->sin6_scope_id; if (setsockopt(sockfd, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, &mreq6, sizeof(mreq6)) < 0) { ff_log_net_error(logctx, AV_LOG_ERROR, "setsockopt(IPV6_ADD_MEMBERSHIP)"); return ff_neterrno(); @@ -231,6 +231,39 @@ static int udp_join_multicast_group(int sockfd, struct sockaddr *addr, return 0; } +static int udp_set_multicast_interface(int sockfd, struct sockaddr *addr, +struct sockaddr *local_addr, void *logctx) +{ +#ifdef IP_MULTICAST_IF +if (addr->sa_family == AF_INET) { +struct ip_mreq mreq; + +mreq.imr_multiaddr.s_addr = ((struct sockaddr_in *)addr)->sin_addr.s_addr; +if (local_addr) +mreq.imr_interface = ((struct sockaddr_in *)local_addr)->sin_addr; +else +mreq.imr_interface.s_addr = INADDR_ANY; + +if (setsockopt(sockfd, IPPROTO_IP, IP_MULTICAST_IF, (const void *)&mreq, sizeof(mreq)) < 0) { +ff_log_net_error(logctx, AV_LOG_ERROR, "setsockopt(IP_MULTICAST_IF)"); +return ff_neterrno(); +} +} +#endif +#if defined(IPV6_MULTICAST_IF) && defined(IPPROTO_IPV6) +if (addr->sa_family == AF_INET6) { +unsigned int iface; +iface = ((struct sockaddr_in6 *)addr)->sin6_scope_id; + +if (setsockopt(sockfd, IPPROTO_IPV6, IPV6_MULTICAST_IF, &iface, sizeof(unsigned int)) < 0) { +ff_log_net_error(logctx, AV_LOG_ERROR, "setsockopt(IPV6_MULTI
Re: [FFmpeg-devel] [PATCH v2] avformat: enable UDP IPv6 multicast interface selection using zone index
This message has been marked as Public on 04/11/2024 07:58Z. On Thursday, April 11, 2024 9:50 AM Lynne wrote: > Is there a reason why we can't switch to IPv4 addresses mapped in IPv6 and > just use the IPv6 API everywhere? I'm not the person to give you that answer. My guess is that due to API discrepancies between v4 and v6 it would require a _lot_ of work to make that jump. Also, different levels of IPv6 support across kernels doesn't make it any easier. Lazar Ignjatović Associate Software Engineer Cubic Defense cubic.com ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
[FFmpeg-devel] [PATCH v2] avformat: enable UDP IPv6 multicast interface selection using zone index
avformat: enable UDP IPv6 multicast interface selection using zone index Enabled IPv6 interface selection using zone index. Properly resolved interface index in places where default 0 interface index is used (marked with TODO: within udp.c). Adjusted binding for multicast sockets that are used for reading from the network. For mcast addresses, bind to mcast address is attempted as before. In case that this fails, which will happen on Windows, socket is bound to INADDR_ANY/IN6ADDR_ANY_INIT depending on address family. Actual interface selection is performed using udp_set_multicast_interface to point to the desired interface for sending. Closes: #368 Signed-off-by: Lazar Ignjatovic --- V1 -> V2 reverted iface resolution for IPv4 MCAST_JOIN_SOURCE_GROUP NOTE: Due to comments, this patch is proposed as one of two alternatives The other alternative uses `localaddr` for defining interfaces. configure | 3 ++ doc/protocols.texi| 2 +- libavformat/network.h | 6 +++ libavformat/udp.c | 85 +++ 4 files changed, 88 insertions(+), 8 deletions(-) diff --git a/configure b/configure index 2a1d22310b..35d6a0b78c 100755 --- a/configure +++ b/configure @@ -2307,6 +2307,7 @@ HEADERS_LIST=" valgrind_valgrind_h windows_h winsock2_h +iphlpapi_h " INTRINSICS_LIST=" @@ -6475,6 +6476,8 @@ if ! disabled network; then check_struct winsock2.h "struct sockaddr" sa_len check_type ws2tcpip.h "struct sockaddr_in6" check_type ws2tcpip.h "struct sockaddr_storage" +check_headers iphlpapi.h -liphlpapi && network_extralibs="$network_extralibs -liphlpapi" || disable iphlpapi_h +check_func_headers iphlpapi.h GetBestInterfaceEx $network_extralibs else disable network fi diff --git a/doc/protocols.texi b/doc/protocols.texi index f54600b846..a8892845d3 100644 --- a/doc/protocols.texi +++ b/doc/protocols.texi @@ -2027,7 +2027,7 @@ packet bursts. Override the local UDP port to bind with. @item localaddr=@var{addr} -Local IP address of a network interface used for sending packets or joining +Local IPv4 address of a network interface used for sending packets or joining multicast groups. @item pkt_size=@var{size} diff --git a/libavformat/network.h b/libavformat/network.h index ca214087fc..2461b651d4 100644 --- a/libavformat/network.h +++ b/libavformat/network.h @@ -38,6 +38,10 @@ #include #include +#if HAVE_IPHLPAPI_H +#include +#endif + #ifndef EPROTONOSUPPORT #define EPROTONOSUPPORT WSAEPROTONOSUPPORT #endif @@ -64,6 +68,8 @@ int ff_neterrno(void); #include #include #include +#include +#include #define ff_neterrno() AVERROR(errno) #endif /* HAVE_WINSOCK2_H */ diff --git a/libavformat/udp.c b/libavformat/udp.c index d9514f5026..00c73f9ec9 100644 --- a/libavformat/udp.c +++ b/libavformat/udp.c @@ -35,6 +35,7 @@ #include "libavutil/opt.h" #include "libavutil/log.h" #include "libavutil/time.h" +#include "libavutil/avstring.h" #include "internal.h" #include "network.h" #include "os_support.h" @@ -220,8 +221,7 @@ static int udp_join_multicast_group(int sockfd, struct sockaddr *addr, struct ipv6_mreq mreq6; memcpy(&mreq6.ipv6mr_multiaddr, &(((struct sockaddr_in6 *)addr)->sin6_addr), sizeof(struct in6_addr)); -//TODO: Interface index should be looked up from local_addr -mreq6.ipv6mr_interface = 0; +mreq6.ipv6mr_interface = ((struct sockaddr_in6 *)addr)->sin6_scope_id; if (setsockopt(sockfd, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, &mreq6, sizeof(mreq6)) < 0) { ff_log_net_error(logctx, AV_LOG_ERROR, "setsockopt(IPV6_ADD_MEMBERSHIP)"); return ff_neterrno(); @@ -231,6 +231,39 @@ static int udp_join_multicast_group(int sockfd, struct sockaddr *addr, return 0; } +static int udp_set_multicast_interface(int sockfd, struct sockaddr *addr, +struct sockaddr *local_addr, void *logctx) +{ +#ifdef IP_MULTICAST_IF +if (addr->sa_family == AF_INET) { +struct ip_mreq mreq; + +mreq.imr_multiaddr.s_addr = ((struct sockaddr_in *)addr)->sin_addr.s_addr; +if (local_addr) +mreq.imr_interface = ((struct sockaddr_in *)local_addr)->sin_addr; +else +mreq.imr_interface.s_addr = INADDR_ANY; + +if (setsockopt(sockfd, IPPROTO_IP, IP_MULTICAST_IF, (const void *)&mreq, sizeof(mreq)) < 0) { +ff_log_net_error(logctx, AV_LOG_ERROR, "setsockopt(IP_MULTICAST_IF)"); +return ff_neterrno(); +} +} +#endif +#if defined(IPV6_MULTICAST_IF) && defined(IPPROTO_IPV6) +if (addr->sa_family == AF_INET6) { +unsigned int iface; +iface = ((struct sockaddr_in6 *)addr)->sin6_scope_id; + +if (setsockopt(sockfd, IPPROTO_IPV6, IPV6_MULTICAST_IF, &iface, sizeof(unsigned int)) < 0) { +ff_log_net_error(logctx, AV_LOG_ERROR, "setsockopt(IPV6_MULTICAST_IF)"); +
[FFmpeg-devel] [PATCH v2] avformat: enable UDP IPv6 multicast interface selection using zone index
avformat: enable UDP IPv6 multicast interface selection using zone index Enabled IPv6 interface selection using zone index. Properly resolved interface index in places where default 0 interface index is used (marked with TODO: within udp.c). Adjusted binding for multicast sockets that are used for reading from the network. For mcast addresses, bind to mcast address is attempted as before. In case that this fails, which will happen on Windows, socket is bound to INADDR_ANY/IN6ADDR_ANY_INIT depending on address family. Actual interface selection is performed using udp_set_multicast_interface to point to the desired interface for sending. Closes: #368 Signed-off-by: Lazar Ignjatovic --- V1 -> V2 reverted iface resolution for IPv4 MCAST_JOIN_SOURCE_GROUP NOTE: Due to comments, this patch is proposed as one of two alternatives The other alternative uses `localaddr` for defining interfaces. configure | 3 ++ doc/protocols.texi| 2 +- libavformat/network.h | 6 +++ libavformat/udp.c | 85 +++ 4 files changed, 88 insertions(+), 8 deletions(-) diff --git a/configure b/configure index 2a1d22310b..35d6a0b78c 100755 --- a/configure +++ b/configure @@ -2307,6 +2307,7 @@ HEADERS_LIST=" valgrind_valgrind_h windows_h winsock2_h +iphlpapi_h " INTRINSICS_LIST=" @@ -6475,6 +6476,8 @@ if ! disabled network; then check_struct winsock2.h "struct sockaddr" sa_len check_type ws2tcpip.h "struct sockaddr_in6" check_type ws2tcpip.h "struct sockaddr_storage" +check_headers iphlpapi.h -liphlpapi && network_extralibs="$network_extralibs -liphlpapi" || disable iphlpapi_h +check_func_headers iphlpapi.h GetBestInterfaceEx $network_extralibs else disable network fi diff --git a/doc/protocols.texi b/doc/protocols.texi index f54600b846..a8892845d3 100644 --- a/doc/protocols.texi +++ b/doc/protocols.texi @@ -2027,7 +2027,7 @@ packet bursts. Override the local UDP port to bind with. @item localaddr=@var{addr} -Local IP address of a network interface used for sending packets or joining +Local IPv4 address of a network interface used for sending packets or joining multicast groups. @item pkt_size=@var{size} diff --git a/libavformat/network.h b/libavformat/network.h index ca214087fc..2461b651d4 100644 --- a/libavformat/network.h +++ b/libavformat/network.h @@ -38,6 +38,10 @@ #include #include +#if HAVE_IPHLPAPI_H +#include +#endif + #ifndef EPROTONOSUPPORT #define EPROTONOSUPPORT WSAEPROTONOSUPPORT #endif @@ -64,6 +68,8 @@ int ff_neterrno(void); #include #include #include +#include +#include #define ff_neterrno() AVERROR(errno) #endif /* HAVE_WINSOCK2_H */ diff --git a/libavformat/udp.c b/libavformat/udp.c index d9514f5026..00c73f9ec9 100644 --- a/libavformat/udp.c +++ b/libavformat/udp.c @@ -35,6 +35,7 @@ #include "libavutil/opt.h" #include "libavutil/log.h" #include "libavutil/time.h" +#include "libavutil/avstring.h" #include "internal.h" #include "network.h" #include "os_support.h" @@ -220,8 +221,7 @@ static int udp_join_multicast_group(int sockfd, struct sockaddr *addr, struct ipv6_mreq mreq6; memcpy(&mreq6.ipv6mr_multiaddr, &(((struct sockaddr_in6 *)addr)->sin6_addr), sizeof(struct in6_addr)); -//TODO: Interface index should be looked up from local_addr -mreq6.ipv6mr_interface = 0; +mreq6.ipv6mr_interface = ((struct sockaddr_in6 *)addr)->sin6_scope_id; if (setsockopt(sockfd, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, &mreq6, sizeof(mreq6)) < 0) { ff_log_net_error(logctx, AV_LOG_ERROR, "setsockopt(IPV6_ADD_MEMBERSHIP)"); return ff_neterrno(); @@ -231,6 +231,39 @@ static int udp_join_multicast_group(int sockfd, struct sockaddr *addr, return 0; } +static int udp_set_multicast_interface(int sockfd, struct sockaddr *addr, +struct sockaddr *local_addr, void *logctx) +{ +#ifdef IP_MULTICAST_IF +if (addr->sa_family == AF_INET) { +struct ip_mreq mreq; + +mreq.imr_multiaddr.s_addr = ((struct sockaddr_in *)addr)->sin_addr.s_addr; +if (local_addr) +mreq.imr_interface = ((struct sockaddr_in *)local_addr)->sin_addr; +else +mreq.imr_interface.s_addr = INADDR_ANY; + +if (setsockopt(sockfd, IPPROTO_IP, IP_MULTICAST_IF, (const void *)&mreq, sizeof(mreq)) < 0) { +ff_log_net_error(logctx, AV_LOG_ERROR, "setsockopt(IP_MULTICAST_IF)"); +return ff_neterrno(); +} +} +#endif +#if defined(IPV6_MULTICAST_IF) && defined(IPPROTO_IPV6) +if (addr->sa_family == AF_INET6) { +unsigned int iface; +iface = ((struct sockaddr_in6 *)addr)->sin6_scope_id; + +if (setsockopt(sockfd, IPPROTO_IPV6, IPV6_MULTICAST_IF, &iface, sizeof(unsigned int)) < 0) { +ff_log_net_error(logctx, AV_LOG_ERROR, "setsockopt(IPV6_MULTICAST_IF)"); +
Re: [FFmpeg-devel] [PATCH v3] avformat: enable UDP IPv6 multicast interface selection using localaddr
This message has been marked as Public on 03/27/2024 08:53Z. On Tuesday, March 26, 2024 7:26 PM Rémi Denis-Courmont wrote: > Both patches -1 for same reasons as before and that's unnecessary, > functionally incorrect and potentially racy, enumeration of local interfaces. Enumeration of interfaces is done only for IPv4 MCAST_JOIN_SOURCE_GROUP/MCAST_BLOCK_SOURCE within zone index patch. Adding a separate parameter just for this seems pointless to me. Would removal of this, and reverting back to how it was ( = 0; // default interface in every case), address your concerns? Lazar Ignjatović Associate Software Engineer Cubic Defense cubic.com ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
[FFmpeg-devel] [PATCH] avformat: enable UDP IPv6 multicast interface selection using zone index
avformat: enable UDP IPv6 multicast interface selection using zone index Enabled IPv6 interface selection using zone index. Properly resolved interface index in places where default 0 interface index is used (marked with TODO: within udp.c). Adjusted binding for multicast sockets that are used for reading from the network. For mcast addresses, bind to mcast address is attempted as before. In case that this fails, which will happen on Windows, socket is bound to INADDR_ANY/IN6ADDR_ANY_INIT depending on address family. Actual interface selection is performed using udp_set_multicast_interface to point to the desired interface for sending. IPv6 interfaces are resolved based on sin6_scope_id field, while IPv4 interface resolution is performed based on address. Closes: #368 Signed-off-by: Lazar Ignjatovic --- NOTE: Due to comments, this patch is proposed as one of two alternatives The other alternative uses `localaddr` for defining interfaces. configure | 3 ++ doc/protocols.texi| 2 +- libavformat/ip.c | 48 libavformat/ip.h | 6 +++ libavformat/network.h | 6 +++ libavformat/udp.c | 87 ++- 6 files changed, 142 insertions(+), 10 deletions(-) diff --git a/configure b/configure index 2a1d22310b..35d6a0b78c 100755 --- a/configure +++ b/configure @@ -2307,6 +2307,7 @@ HEADERS_LIST=" valgrind_valgrind_h windows_h winsock2_h +iphlpapi_h " INTRINSICS_LIST=" @@ -6475,6 +6476,8 @@ if ! disabled network; then check_struct winsock2.h "struct sockaddr" sa_len check_type ws2tcpip.h "struct sockaddr_in6" check_type ws2tcpip.h "struct sockaddr_storage" +check_headers iphlpapi.h -liphlpapi && network_extralibs="$network_extralibs -liphlpapi" || disable iphlpapi_h +check_func_headers iphlpapi.h GetBestInterfaceEx $network_extralibs else disable network fi diff --git a/doc/protocols.texi b/doc/protocols.texi index f54600b846..a8892845d3 100644 --- a/doc/protocols.texi +++ b/doc/protocols.texi @@ -2027,7 +2027,7 @@ packet bursts. Override the local UDP port to bind with. @item localaddr=@var{addr} -Local IP address of a network interface used for sending packets or joining +Local IPv4 address of a network interface used for sending packets or joining multicast groups. @item pkt_size=@var{size} diff --git a/libavformat/ip.c b/libavformat/ip.c index b2c7ef07e5..dc488b12c2 100644 --- a/libavformat/ip.c +++ b/libavformat/ip.c @@ -18,6 +18,9 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#define _DEFAULT_SOURCE +#define _SVID_SOURCE + #include #include "ip.h" #include "libavutil/avstring.h" @@ -159,3 +162,48 @@ void ff_ip_reset_filters(IPSourceFilters *filters) filters->nb_include_addrs = 0; filters->nb_exclude_addrs = 0; } + +unsigned int ff_ip_resolve_interface_index(struct sockaddr_storage *local_addr) +{ +#if HAVE_WINSOCK2_H +#if HAVE_IPHLPAPI_H +DWORD retval; +unsigned long iface; + +if (local_addr == NULL) +return 0; + +retval = GetBestInterfaceEx((struct sockaddr*)local_addr, &iface); +if (retval == NO_ERROR) +return iface; +#endif /* HAVE_IPHLPAPI_H */ +return 0; +#else /* HAVE_WINSOCK2_H */ +struct ifaddrs *ifaddr, *ifa; +unsigned int iface; + +if (local_addr == NULL) +return 0; + +#if HAVE_STRUCT_SOCKADDR_IN6 +if (local_addr->ss_family == AF_INET6) { +iface = ((struct sockaddr_in6*)local_addr)->sin6_scope_id; +if (iface) +return iface; +} +#endif /* HAVE_STRUCT_SOCKADDR_IN6 */ +if (getifaddrs(&ifaddr) == -1) +return 0; + +iface = 0; +for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) { +if (ifa->ifa_addr != NULL && compare_addr((struct sockaddr_storage*)ifa->ifa_addr, local_addr) == 0) { +iface = if_nametoindex(ifa->ifa_name); +break; +} +} + +freeifaddrs(ifaddr); +return iface; +#endif /* HAVE_WINSOCK2_H */ +} \ No newline at end of file diff --git a/libavformat/ip.h b/libavformat/ip.h index b76cdab91c..4085e96f08 100644 --- a/libavformat/ip.h +++ b/libavformat/ip.h @@ -69,4 +69,10 @@ int ff_ip_parse_blocks(void *log_ctx, const char *buf, IPSourceFilters *filters) */ void ff_ip_reset_filters(IPSourceFilters *filters); +/** + * Resolves IP address to an associated interface index + * @return interface index, 0 as default interface value on error + */ +unsigned int ff_ip_resolve_interface_index(struct sockaddr_storage *local_addr); + #endif /* AVFORMAT_IP_H */ diff --git a/libavformat/network.h b/libavformat/network.h index ca214087fc..2461b651d4 100644 --- a/libavformat/network.h +++ b/libavformat/network.h @@ -38,6 +38,10 @@ #include #include +#if HAVE_IPHLPAPI_H +#include +#endif + #ifndef EPROTONOSUPPORT #define EPROTONOSUPPORT WSAEPROTONOSUPPORT #endif @@ -64,6 +68,8 @@ int ff_neterrno(void); #includ
[FFmpeg-devel] [PATCH v3] avformat: enable UDP IPv6 multicast interface selection using localaddr
avformat: enable UDP IPv6 multicast interface selection using localaddr localaddr option now properly works with IPv6 addresses. Properly resolved interface index in places where default 0 interface index is used (marked with TODO: within udp.c). Adjusted binding for multicast sockets that are used for reading from the network. Need for this arises from the fact that link-local multicast addresses need to have a defined interface for binding to avoid ambiguity between multiple link-local networks on the same host. Failing to set this option causes errors on Linux systems for interface and link-local scopes. For mcast addresses, bind to mcast address is attempted as before. In case that this fails, which will happen on Windows, socket is bound to INADDR_ANY/IN6ADDR_ANY_INIT depending on address family. Actual interface selection is performed using udp_set_multicast_interface to point to the desired interface for sending. Utilization of sin6_scope_id field enables usage and adequate resolving of IPv6 addresses that utilize zone index (e.g. fe80::1%eth2) Closes: #368 Signed-off-by: Lazar Ignjatovic --- V1 -> V2: SO_BINDTODEVICE -> sin6_scope_id, addressed comments V2 -> V3: mcast check sin6_scope_id for iface specification NOTE: Due to comments, this patch is proposed as one of two alternatives The other alternative uses exclusively %scope format for defining interfaces. This patch can handle scoped IPv6 link-local addresses configure | 3 ++ libavformat/ip.c | 48 libavformat/ip.h | 6 +++ libavformat/network.h | 6 +++ libavformat/udp.c | 85 +++ 5 files changed, 140 insertions(+), 8 deletions(-) diff --git a/configure b/configure index e019d1b996..08f35bbd25 100755 --- a/configure +++ b/configure @@ -2258,6 +2258,7 @@ HEADERS_LIST=" valgrind_valgrind_h windows_h winsock2_h +iphlpapi_h " INTRINSICS_LIST=" @@ -6406,6 +6407,8 @@ if ! disabled network; then check_struct winsock2.h "struct sockaddr" sa_len check_type ws2tcpip.h "struct sockaddr_in6" check_type ws2tcpip.h "struct sockaddr_storage" +check_headers iphlpapi.h -liphlpapi && network_extralibs="$network_extralibs -liphlpapi" || disable iphlpapi_h +check_func_headers iphlpapi.h GetBestInterfaceEx $network_extralibs else disable network fi diff --git a/libavformat/ip.c b/libavformat/ip.c index b2c7ef07e5..821595edc5 100644 --- a/libavformat/ip.c +++ b/libavformat/ip.c @@ -18,6 +18,9 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#define _DEFAULT_SOURCE +#define _SVID_SOURCE + #include #include "ip.h" #include "libavutil/avstring.h" @@ -159,3 +162,48 @@ void ff_ip_reset_filters(IPSourceFilters *filters) filters->nb_include_addrs = 0; filters->nb_exclude_addrs = 0; } + +unsigned int ff_ip_resolve_interface_index(struct sockaddr_storage *local_addr) +{ +#if HAVE_WINSOCK2_H +#if HAVE_IPHLPAPI_H +DWORD retval; +unsigned long iface; + +if (local_addr == NULL) +return 0; + +retval = GetBestInterfaceEx((struct sockaddr*)local_addr, &iface); +if (retval == NO_ERROR) +return iface; +#endif /* HAVE_IPHLPAPI_H */ +return 0; +#else /* HAVE_WINSOCK2_H */ +struct ifaddrs *ifaddr, *ifa; +unsigned int iface; + +if (local_addr == NULL) +return 0; + +#if HAVE_STRUCT_SOCKADDR_IN6 +if (local_addr->ss_family == AF_INET6) { +iface = ((struct sockaddr_in6*)local_addr)->sin6_scope_id; +if (iface) +return iface; +} +#endif /* HAVE_STRUCT_SOCKADDR_IN6 */ +if (getifaddrs(&ifaddr) == -1) +return 0; + +iface = 0; +for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) { +if (ifa->ifa_addr != NULL && compare_addr((struct sockaddr_storage*)ifa->ifa_addr, local_addr) == 0) { +iface = if_nametoindex(ifa->ifa_name); +break; +} +} + +freeifaddrs(ifaddr); +return iface; +#endif /* HAVE_WINSOCK2_H */ +} diff --git a/libavformat/ip.h b/libavformat/ip.h index b76cdab91c..4085e96f08 100644 --- a/libavformat/ip.h +++ b/libavformat/ip.h @@ -69,4 +69,10 @@ int ff_ip_parse_blocks(void *log_ctx, const char *buf, IPSourceFilters *filters) */ void ff_ip_reset_filters(IPSourceFilters *filters); +/** + * Resolves IP address to an associated interface index + * @return interface index, 0 as default interface value on error + */ +unsigned int ff_ip_resolve_interface_index(struct sockaddr_storage *local_addr); + #endif /* AVFORMAT_IP_H */ diff --git a/libavformat/network.h b/libavformat/network.h index ca214087fc..2461b651d4 100644 --- a/libavformat/network.h +++ b/libavformat/network.h @@ -38,6 +38,10 @@ #include #include +#if HAVE_IPHLPAPI_H +#include +#endif + #ifndef EPROTONOSUPPORT #define EPROTONOSUPPORT WSAEPROTONOSUPPORT #endif @@ -64,6 +68,8 @@ int ff_neterrno(void); #include #include #
Re: [FFmpeg-devel] [PATCH v2] avformat: enable UDP IPv6 multicast interface selection
This message has been marked as Public on 03/22/2024 10:16Z. On Friday, March 22, 2024 10:55 AM Rémi Denis-Courmont wrote: > So why are you arguing now? Because I still belive that using localaddr is the better approach. However, I will create and submit v3 of this patch and also create another patch following your suggestions of either using a new param or using scope_id. Both will be available, so the maintainers can choose. I think that’s fair. Lazar Ignjatović Associate Software Engineer Cubic Defense cubic.com ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
Re: [FFmpeg-devel] [PATCH v2] avformat: enable UDP IPv6 multicast interface selection
>> I've compared ffmpeg 5.1.2 against my MR on IPv6 multicast. Here are >> the >> results: > > I don't care. That does not make your MR any less counter-sensical. If I may cite Marton Balint ``` d3bda871f033be4825ecb69d444b3396bf2a2eb7 avformat/udp: specify the local address for some source filtered multicast joins We already use localaddr for the multicast joins without source filters, so we should use them for source filters as well. This patch only fixes the IP_ADD_SOURCE_MEMBERSHIP and the IP_BLOCK_SOURCE case. Unless we do this, the kernel automatically selects an interface based on the source address, and that interface might be different from the one set in localaddr. For blocked sources this even casues EINVAL because we joined the multicast group on a different interface. Signed-off-by: Marton Balint --- ... //TODO: Interface index should be looked up from local_addr ... ``` And another commit ``` ab0812c1a8925a95315354b88b41256faad5faa8 avformat/udp: always use IP_ADD_SOURCE_MEMBERSHIP for subscribing to an UDP multicast source group in IPv4 That alone supports specifying the interface based on its address. Getting the interface index from the local address seems quite a bit of work in a platform independent way... Obviously for IPv6 we still always use MCAST_JOIN_SOURCE_GROUP. As a side effect this also fixes ticket #7459. Signed-off-by: Marton Balint ``` From this I understand that the intention is to still use localaddr parameter with the same semantics as with IPv4 > If you could infer the scope ID from the IPv6 address, there wouldn't be a > scope ID field in the socket address in the first place. Is it that hard to > understand? Well, it's not that simple. Here I have to cite ipv6(7) — Linux manual page ``` sin6_scope_id is an ID depending on the scope of the address. It is new in Linux 2.4. Linux supports it only for link-local addresses, in that case sin6_scope_id contains the interface index (see netdevice(7)) ``` > That "problem" was solved before FFmpeg existed by adding a separate parameter > (ping6) or prepending the interface name after a percent sign (glibc). And this is the closest you've got to providing an alternate solution to the proposed. Which is adding another parameter, or relying on % for every type of multicast. > If you tests show anything, it's that LL addressing is not intended for > application protocols. And just to clarify FF11::1%eth0 is an interface-local multicast, thus supported FF12::1%eth0 is a link-local multicast, thus supported All other multicast scopes are not supported by Linux in respect to %scope. If we choose to support ff15::1%eth0 for example, we are introducing something that is not normally supported on Linux, potentially creating confusion among users. Interface parameter seems like a better option than the %scope for everything. Can someone else agree with this? If this is, in fact, the preferred way, then okay. I will propose the v3 of the patch done this way. Still, I prefer keeping the IPv4 semantics for v6. Lazar Ignjatović Associate Software Engineer Cubic Defense cubic.com This message has been marked as Public on 03/22/2024 09:31Z. ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
Re: [FFmpeg-devel] [PATCH v2] avformat: enable UDP IPv6 multicast interface selection
> Your MR makes even less sense for multicast. For multicast there is no local > address to match to an interface. So you just have to have the interface > specified explicitly in addition to the LL group address. This is true for > both egress and ingress. I've compared ffmpeg 5.1.2 against my MR on IPv6 multicast. Here are the results: Recv (on interface other than default) | Address| localaddr | 5.1.2 | MR | | -- | - | - | --- | | FF11::1| null | NO| NO | | FF11::1| iface addr| NO| YES | | FF11::1%eth0 | null | NO| YES | | FF12::1| null | NO| NO | | FF12::1| iface addr| NO| YES | | FF12::1%eth0 | null | NO| YES | | FF14::1| null | NO| NO | | FF14::1| iface addr| NO| YES | | FF14::1%eth0 | null | NO| NO | | FF15::1| null | NO| NO | | FF15::1| iface addr| NO| YES | | FF15::1%eth0 | null | NO| NO | | FF18::1| null | NO| NO | | FF18::1| iface addr| NO| YES | | FF18::1%eth0 | null | NO| NO | Send (on interface other than default) | Address| localaddr | 5.1.2 | MR | | -- | - | - | --- | | FF11::1| null | NO| NO | | FF11::1| iface addr| NO| YES | | FF11::1%eth0 | null | YES | YES | | FF12::1| null | NO| NO | | FF12::1| iface addr| NO| YES | | FF12::1%eth0 | null | YES | YES | | FF14::1| null | NO| NO | | FF14::1| iface addr| NO| YES | | FF14::1%eth0 | null | NO| NO | | FF15::1| null | NO| NO | | FF15::1| iface addr| NO| YES | | FF15::1%eth0 | null | NO| NO | | FF18::1| null | NO| NO | | FF18::1| iface addr| NO| YES | | FF18::1%eth0 | null | NO| NO | Here are the reasons why the combinations marked NO under my MR don’t work: FF11::1 -> ambiguous interface on which to listen/send FF12::1 -> ambiguous interface on which to listen/send FF14::1 -> ambiguous interface on which to listen/send, uses only default iface FF14::1%eth0 -> getaddrinfo errors as it supports %scope only for link-local FF15::1 -> ambiguous interface on which to listen/send, uses only default iface FF15::1%eth0 -> getaddrinfo errors as it supports %scope only for link-local FF18::1 -> ambiguous interface on which to listen/send, uses only default iface FF18::1%eth0 -> getaddrinfo errors as it supports %scope only for link-local So the problem to overcome here is controlling on which interface we listen/send multicat IPv6. For link local yes, %scope is the way to go. I proposed this MR as the solution to the problem, keepeng the `localaddr` parameter semantics the same as with IPv4. Other solution could be introduction of a new parameter, as I said before. In this case then, the documentation should be changed to reflect that `localaddr` is only used for IPv4 addresses, and that same functionality can be obtained with this new parameter under IPv6. There will certainly be V3 of the patch, as I've identified minor changes needed for this approach. If you have any other ideas, I'm open to hearing them. Lazar Ignjatović Associate Software Engineer Cubic Defense cubic.com This message has been marked as Public on 03/21/2024 13:01Z. ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
Re: [FFmpeg-devel] [PATCH v2] avformat: enable UDP IPv6 multicast interface selection
This message has been marked as Public on 03/20/2024 12:35Z. On Wednesday, March 20, 2024 1:18 PM Rémi Denis-Courmont wrote: >> In all other cases, determining the interface ID by address should be >> ok, > > No! The only other case is non-LL addressing, which does not require link ID > at all. For IPv4 that is certainly true, but it differs for v6. Specifying egress interface is done by setting the setsockopt(IPV6_MULTICAST_IF) to the value of the interface, not address. On the other hand v4 for the similar option setsockopt(IP_MULTICAST_IF) sets it by definig an address (not interface). Without setting IPV6_MULTICAST_IF to the appropriate interface, default interface is chosen. We want to have control over this, and I cant se how this can be achieved without knowing the interface id. For ingress IPv6 traffic, the way to filter on which interface is being listened on is by binding to a mcast addres, which has sin6_scope_id properly set. Lazar Ignjatović Associate Software Engineer Cubic Defense cubic.com ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
Re: [FFmpeg-devel] [PATCH v2] avformat: enable UDP IPv6 multicast interface selection
This message has been marked as Public on 03/20/2024 11:45Z. On Wednesday, March 20, 2024 12:30 PM Rémi Denis-Courmont wrote: > You're not supposed to guess the link ID from the local address. This is > counter-sensical. And it's entirely possible to have the same LL address > assigned to two interfaces (e.g. using a software bridge) anyway. You are right about the same LL on multiple interfaces, that’s why the `sin6_scope_id` is used. For specifying LL address, a scoped address format should be used to avoid ambiguity. In all other cases, determining the interface ID by address should be ok, while keeping the same functionality that `localaddr` param has with IPv6. Currently, I don't see any other way of specifying IPv6 multicast interface without the introduction of another query param like `iface` or something. Let me know what you think. Sincirely, Lazar Ignjatović Associate Software Engineer Cubic Defense cubic.com ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
Re: [FFmpeg-devel] [PATCH v2] avformat: enable UDP IPv6 multicast interface selection
This message has been marked as Public on 03/20/2024 11:09Z. On Wednesday, March 20, 2024 11:51 AM Rémi Denis-Courmont wrote: > Same fundamental problem as previous version, AFAICT. > > -1 Would you mind being more specific? There are 2 problems you pointed out, one about SO_BINDTODEVICE, and another in respect to casting `sockaddr* ` to `sockaddr_in6*` and `sockaddr_storage*` to `sockaddr_in6*`. Assuming you are reffering to the cast comment, I've addressed this in the other thread. That should not be an issue to my knowledge, and is done on multiple places throughout the codebase. Also I've assked you for additional comments, which I'm doing again. Lazar Ignjatović Associate Software Engineer Cubic Defense cubic.com ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
[FFmpeg-devel] [PATCH v2] avformat: enable UDP IPv6 multicast interface selection
avformat: enable UDP IPv6 multicast interface selection localaddr option now properly works with IPv6 addresses. Properly resolved interface index in places where default 0 interface index is used (marked with TODO: within udp.c). Adjusted binding for multicast sockets that are used for reading from the network. Need for this arises from the fact that [ffx1::*] and [ffx2::*] mcast addresses need to have a defined interface for binding to avoid ambiguity between multiple link-local networks on the same host. Failing to set this option causes errors on Linux systems for interface and link-local scopes. For mcast addresses, bind to mcast address is attempted as before. In case that this fails, which will happen on Windows, socket is bound to INADDR_ANY/IN6ADDR_ANY_INIT depending on address family. Actual interface selection is performed using udp_set_multicast_interface to point to the desired interface for sending. Utilization of sin6_scope_id field enables usage and adequate resolving of localaddr IPv6 addresses that utilize zone index (e.g. fe80::1ff:fe23:4567:890a%eth2) This is not fully supported on Windows, thus relying on this field is not done on Windows systems. Closes: #368 Signed-off-by: Lazar Ignjatovic --- V1 -> V2: SO_BINDTODEVICE -> sin6_scope_id, addressed comments configure | 3 ++ libavformat/ip.c | 49 ++ libavformat/ip.h | 6 libavformat/network.h | 6 libavformat/udp.c | 81 ++- 5 files changed, 137 insertions(+), 8 deletions(-) diff --git a/configure b/configure index e019d1b996..08f35bbd25 100755 --- a/configure +++ b/configure @@ -2258,6 +2258,7 @@ HEADERS_LIST=" valgrind_valgrind_h windows_h winsock2_h +iphlpapi_h " INTRINSICS_LIST=" @@ -6406,6 +6407,8 @@ if ! disabled network; then check_struct winsock2.h "struct sockaddr" sa_len check_type ws2tcpip.h "struct sockaddr_in6" check_type ws2tcpip.h "struct sockaddr_storage" +check_headers iphlpapi.h -liphlpapi && network_extralibs="$network_extralibs -liphlpapi" || disable iphlpapi_h +check_func_headers iphlpapi.h GetBestInterfaceEx $network_extralibs else disable network fi diff --git a/libavformat/ip.c b/libavformat/ip.c index b2c7ef07e5..4b83e79298 100644 --- a/libavformat/ip.c +++ b/libavformat/ip.c @@ -18,6 +18,9 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#define _DEFAULT_SOURCE +#define _SVID_SOURCE + #include #include "ip.h" #include "libavutil/avstring.h" @@ -159,3 +162,49 @@ void ff_ip_reset_filters(IPSourceFilters *filters) filters->nb_include_addrs = 0; filters->nb_exclude_addrs = 0; } + +unsigned int ff_ip_resolve_interface_index(struct sockaddr_storage *local_addr) +{ +#if HAVE_WINSOCK2_H +#if HAVE_IPHLPAPI_H +DWORD retval; +unsigned long iface; + +if (local_addr == NULL) +return 0; + +retval = GetBestInterfaceEx((struct sockaddr*)local_addr, &iface); +if (retval == NO_ERROR) +return iface; +#endif /* HAVE_IPHLPAPI_H */ +return 0; +#else /* HAVE_WINSOCK2_H */ +struct ifaddrs *ifaddr, *ifa; +unsigned int iface; + +if (local_addr == NULL) +return 0; + +#if HAVE_STRUCT_SOCKADDR_IN6 && defined(IN6_IS_ADDR_LINKLOCAL) +/* Special case for link-local addresses, relevant interface is stored in sin6_scope_id */ +if (local_addr->ss_family == AF_INET6) { +iface = ((struct sockaddr_in6*)local_addr)->sin6_scope_id; +if (iface != 0) +return iface; +} +#endif /* HAVE_STRUCT_SOCKADDR_IN6 && defined(IN6_IS_ADDR_LINKLOCAL) */ +if (getifaddrs(&ifaddr) == -1) +return 0; + +iface = 0; +for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) { +if (ifa->ifa_addr != NULL && compare_addr((struct sockaddr_storage*)ifa->ifa_addr, local_addr) == 0) { +iface = if_nametoindex(ifa->ifa_name); +break; +} +} + +freeifaddrs(ifaddr); +return iface; +#endif /* HAVE_WINSOCK2_H */ +} diff --git a/libavformat/ip.h b/libavformat/ip.h index b76cdab91c..4085e96f08 100644 --- a/libavformat/ip.h +++ b/libavformat/ip.h @@ -69,4 +69,10 @@ int ff_ip_parse_blocks(void *log_ctx, const char *buf, IPSourceFilters *filters) */ void ff_ip_reset_filters(IPSourceFilters *filters); +/** + * Resolves IP address to an associated interface index + * @return interface index, 0 as default interface value on error + */ +unsigned int ff_ip_resolve_interface_index(struct sockaddr_storage *local_addr); + #endif /* AVFORMAT_IP_H */ diff --git a/libavformat/network.h b/libavformat/network.h index ca214087fc..2461b651d4 100644 --- a/libavformat/network.h +++ b/libavformat/network.h @@ -38,6 +38,10 @@ #include #include +#if HAVE_IPHLPAPI_H +#include +#endif + #ifndef EPROTONOSUPPORT #define EPROTONOSUPPORT WSAEPROTONOSUPPORT #endif @@ -64,6 +68,8 @@ int ff_neterrno(void)
Re: [FFmpeg-devel] [PATCH] avformat: enable UDP IPv6 multicast interface selection
This message has been marked as Public on 03/19/2024 09:40Z. On Friday, March 15, 2024 5:27 PM Rémi Denis-Courmont wrote: >> >> localaddr option now properly works with IPv6 addresses. Properly >> resolved interface index in places where default 0 interface index is >> used (marked with TODO: within udp.c). Added SO_BINDTODEVICE for mcast >> sockets that are used for reading from the network. > > AFAIK, that is privileged, and is not intended for the purpose of scoping > multicast.Where the need arises to specify an interface for multicast, there > is typically a dedicated ioctl or field of an ioctl. I agree, although it gets the job done, in this case it is more acceptable to modify `sin6_scope_id` field to point to the desired interface. Will change within V2 of the patch. >> +/* Special case for link-local addresses, relevant interface is >> + stored >> in sin6_scope_id */ +#if HAVE_STRUCT_SOCKADDR_IN6 && >> defined(IN6_IS_ADDR_LINKLOCAL) >> +if (local_addr->ss_family == AF_INET6 && >> IN6_IS_ADDR_LINKLOCAL(&((struct sockaddr_in6*)local_addr)->sin6_addr)) >> { > > Invalid cast, breaks aliasing, AFAICT. AFAIK the primary purpose of `sockaddr_storage` is to store sockaddr regardles of address family. In this case it is used to store local addr, wether it is V4 or V6. With checking that the `ss_family` is in fact `AF_INET6`, `sockaddr_storage` can be safely cast into `sockaddr_in6`. Maybe I'm missing something here. Would you mind further elaborating your comment? Thank you for your time! Sincirely, Lazar Ignjatović Associate Software Engineer Cubic Defense cubic.com ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
Re: [FFmpeg-devel] [PATCH] avformat: enable UDP IPv6 multicast interface selection
This message has been marked as Public on 03/18/2024 13:45Z. On Thursday, March 14, 2024 10:14 PM, Michael Niedermayer wrote: > breaks mingw64 build > > CC libavformat/ip.o > src/libavformat/ip.c: In function ‘ff_ip_resolve_interface_index’: > src/libavformat/ip.c:206:1: error: control reaches end of non-void function > [-Werror=return-type] } ^ > cc1: some warnings being treated as errors > src/ffbuild/common.mak:81: recipe for target 'libavformat/ip.o' failed > make: *** [libavformat/ip.o] Error 1 I see the problem, when building for windows without iphlpapi.h, mentioned function has no code within. Will account for such case. > also configure produces > ../configure: 6415: ../configure: network_extralibs+= -liphlpapi: not found Problem here is that "+=" operator is a bashism, probably causing the previous error by not including iphlpapi properly. Some questions I have: Should I send another patch within this thread to address these comments, or should I create a V2 of the patch? Also, if creating a V2, should the patch be sent within this thread, or should a new thread be opened? Thank you for your time! Sincirely, Lazar Ignjatović Associate Software Engineer Cubic Defense cubic.com ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
[FFmpeg-devel] [PATCH] avformat: enable UDP IPv6 multicast interface selection
localaddr option now properly works with IPv6 addresses. Properly resolved interface index in places where default 0 interface index is used (marked with TODO: within udp.c). Added SO_BINDTODEVICE for mcast sockets that are used for reading from the network. Need for this arises from the fact that [ffx1::*] and [ffx2::*] mcast addresses need to have a defined interface for binding to avoid ambiguity between multiple link-local networks on the same host. Failing to set this option causes errors on Linux systems for interface and link-local scopes. For mcast addresses, bind to mcast address is attempted as before. In case that this fails, which will happen on Windows, socket is bound to INADDR_ANY/IN6ADDR_ANY_INIT depending on address family. Actual interface selection is performed using udp_set_multicast_interface to point to the desired interface for sending/listening. Utilization of sin6_scope_id field enables usage and adequate resolving of IPv6 addresses that utilize zone index (e.g. fe80::1ff:fe23:4567:890a%eth2) This is not fully supported on Windows, thus relying on this field is not done on Windows systems. Closes: #368 Signed-off-by: Lazar Ignjatovic --- configure | 3 ++ libavformat/ip.c | 45 libavformat/ip.h | 6 libavformat/network.h | 6 libavformat/udp.c | 80 ++- 5 files changed, 132 insertions(+), 8 deletions(-) diff --git a/configure b/configure index c34bdd13f5..77f03948ce 100755 --- a/configure +++ b/configure @@ -2256,6 +2256,7 @@ HEADERS_LIST=" valgrind_valgrind_h windows_h winsock2_h +iphlpapi_h " INTRINSICS_LIST=" @@ -6408,6 +6409,8 @@ if ! disabled network; then check_struct winsock2.h "struct sockaddr" sa_len check_type ws2tcpip.h "struct sockaddr_in6" check_type ws2tcpip.h "struct sockaddr_storage" +check_headers iphlpapi.h && network_extralibs+=" -liphlpapi" || disable iphlpapi_h +check_func_headers iphlpapi.h GetBestInterfaceEx else disable network fi diff --git a/libavformat/ip.c b/libavformat/ip.c index b2c7ef07e5..4f2d998c34 100644 --- a/libavformat/ip.c +++ b/libavformat/ip.c @@ -18,6 +18,9 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#define _DEFAULT_SOURCE +#define _SVID_SOURCE + #include #include "ip.h" #include "libavutil/avstring.h" @@ -159,3 +162,45 @@ void ff_ip_reset_filters(IPSourceFilters *filters) filters->nb_include_addrs = 0; filters->nb_exclude_addrs = 0; } + +unsigned int ff_ip_resolve_interface_index(struct sockaddr_storage *local_addr) +{ +#if HAVE_WINSOCK2_H && HAVE_IPHLPAPI_H +DWORD retval; +unsigned long iface; + +if (local_addr == NULL) +return 0; + +retval = GetBestInterfaceEx((struct sockaddr*)local_addr, &iface); +if (retval == NO_ERROR) +return iface; + +return 0; +#elif !HAVE_WINSOCK2_H +struct ifaddrs *ifaddr, *ifa; + +if (local_addr == NULL) +return 0; + +/* Special case for link-local addresses, relevant interface is stored in sin6_scope_id */ +#if HAVE_STRUCT_SOCKADDR_IN6 && defined(IN6_IS_ADDR_LINKLOCAL) +if (local_addr->ss_family == AF_INET6 && IN6_IS_ADDR_LINKLOCAL(&((struct sockaddr_in6*)local_addr)->sin6_addr)) { +unsigned int interface; +interface = ((struct sockaddr_in6*)local_addr)->sin6_scope_id; + +if (interface != 0) +return interface; +} +#endif +if (getifaddrs(&ifaddr) == -1) +return 0; + +for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) { +if (ifa->ifa_addr != NULL && compare_addr((struct sockaddr_storage*)ifa->ifa_addr, local_addr) == 0) +return if_nametoindex(ifa->ifa_name); +} + +return 0; +#endif +} diff --git a/libavformat/ip.h b/libavformat/ip.h index b76cdab91c..4085e96f08 100644 --- a/libavformat/ip.h +++ b/libavformat/ip.h @@ -69,4 +69,10 @@ int ff_ip_parse_blocks(void *log_ctx, const char *buf, IPSourceFilters *filters) */ void ff_ip_reset_filters(IPSourceFilters *filters); +/** + * Resolves IP address to an associated interface index + * @return interface index, 0 as default interface value on error + */ +unsigned int ff_ip_resolve_interface_index(struct sockaddr_storage *local_addr); + #endif /* AVFORMAT_IP_H */ diff --git a/libavformat/network.h b/libavformat/network.h index ca214087fc..2461b651d4 100644 --- a/libavformat/network.h +++ b/libavformat/network.h @@ -38,6 +38,10 @@ #include #include +#if HAVE_IPHLPAPI_H +#include +#endif + #ifndef EPROTONOSUPPORT #define EPROTONOSUPPORT WSAEPROTONOSUPPORT #endif @@ -64,6 +68,8 @@ int ff_neterrno(void); #include #include #include +#include +#include #define ff_neterrno() AVERROR(errno) #endif /* HAVE_WINSOCK2_H */ diff --git a/libavformat/udp.c b/libavformat/udp.c index d9514f5026..a603a9961e 100644 --- a/libavformat/udp.c +++ b/libavformat/udp.c @@ -220,8 +220
Re: [FFmpeg-devel] [PATCH] avformat: enable UDP IPv6 multicast interface selection
>> +if (if_indextoname(iface, ifr.ifr_name)) { >> +if (setsockopt(udp_fd, SOL_SOCKET, SO_BINDTODEVICE, (void >> *)&ifr, sizeof(ifr)) < 0) { >> +perror("setsockopt SO_BINDTODEVICE"); > > This should use the proper av_log logging instead. Will fix and resubmit corrected version. Thanks, Lazar Ignjatović Associate Software Engineer Cubic Defense cubic.com This message has been marked as Public on 03/14/2024 11:02Z. ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
[FFmpeg-devel] [PATCH] avformat: enable UDP IPv6 multicast interface selection
avformat: enable UDP IPv6 multicast interface selection localaddr option now properly works with IPv6 addresses. Properly resolved interface index in places where default 0 interface index is used (marked with TODO: within udp.c). Added SO_BINDTODEVICE for mcast sockets that are used for reading from the network. Need for this arises from the fact that [ffx1::*] and [ffx2::*] mcast addresses need to have a defined interface for binding to avoid ambiguity between multiple link-local networks on the same host. Failing to set this option causes errors on Linux systems for interface and link-local scopes. For mcast addresses, bind to mcast address is attempted as before. In case that this fails, which will happen on Windows, socket is bound to INADDR_ANY/IN6ADDR_ANY_INIT depending on address family. Actual interface selection is performed using udp_set_multicast_interface to point to the desired interface for sending/listening. Utilization of sin6_scope_id field enables usage and adequate resolving of IPv6 addresses that utilize zone index (e.g. fe80::1ff:fe23:4567:890a%eth2 ) This is not fully supported on Windows, thus relying on this field is not done on Windows systems. Closes: #368 Signed-off-by: Lazar Ignjatovic --- configure | 3 ++ libavformat/ip.c | 45 libavformat/ip.h | 6 libavformat/network.h | 6 libavformat/udp.c | 80 ++- 5 files changed, 132 insertions(+), 8 deletions(-) diff --git a/configure b/configure index c34bdd13f5..77f03948ce 100755 --- a/configure +++ b/configure @@ -2256,6 +2256,7 @@ HEADERS_LIST=" valgrind_valgrind_h windows_h winsock2_h +iphlpapi_h " INTRINSICS_LIST=" @@ -6408,6 +6409,8 @@ if ! disabled network; then check_struct winsock2.h "struct sockaddr" sa_len check_type ws2tcpip.h "struct sockaddr_in6" check_type ws2tcpip.h "struct sockaddr_storage" +check_headers iphlpapi.h && network_extralibs+=" -liphlpapi" || disable iphlpapi_h +check_func_headers iphlpapi.h GetBestInterfaceEx else disable network fi diff --git a/libavformat/ip.c b/libavformat/ip.c index b2c7ef07e5..4f2d998c34 100644 --- a/libavformat/ip.c +++ b/libavformat/ip.c @@ -18,6 +18,9 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#define _DEFAULT_SOURCE +#define _SVID_SOURCE + #include #include "ip.h" #include "libavutil/avstring.h" @@ -159,3 +162,45 @@ void ff_ip_reset_filters(IPSourceFilters *filters) filters->nb_include_addrs = 0; filters->nb_exclude_addrs = 0; } + +unsigned int ff_ip_resolve_interface_index(struct sockaddr_storage *local_addr) +{ +#if HAVE_WINSOCK2_H && HAVE_IPHLPAPI_H +DWORD retval; +unsigned long iface; + +if (local_addr == NULL) +return 0; + +retval = GetBestInterfaceEx((struct sockaddr*)local_addr, &iface); +if (retval == NO_ERROR) +return iface; + +return 0; +#elif !HAVE_WINSOCK2_H +struct ifaddrs *ifaddr, *ifa; + +if (local_addr == NULL) +return 0; + +/* Special case for link-local addresses, relevant interface is stored in sin6_scope_id */ +#if HAVE_STRUCT_SOCKADDR_IN6 && defined(IN6_IS_ADDR_LINKLOCAL) +if (local_addr->ss_family == AF_INET6 && IN6_IS_ADDR_LINKLOCAL(&((struct sockaddr_in6*)local_addr)->sin6_addr)) { +unsigned int interface; +interface = ((struct sockaddr_in6*)local_addr)->sin6_scope_id; + +if (interface != 0) +return interface; +} +#endif +if (getifaddrs(&ifaddr) == -1) +return 0; + +for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) { +if (ifa->ifa_addr != NULL && compare_addr((struct sockaddr_storage*)ifa->ifa_addr, local_addr) == 0) +return if_nametoindex(ifa->ifa_name); +} + +return 0; +#endif +} diff --git a/libavformat/ip.h b/libavformat/ip.h index b76cdab91c..4085e96f08 100644 --- a/libavformat/ip.h +++ b/libavformat/ip.h @@ -69,4 +69,10 @@ int ff_ip_parse_blocks(void *log_ctx, const char *buf, IPSourceFilters *filters) */ void ff_ip_reset_filters(IPSourceFilters *filters); +/** + * Resolves IP address to an associated interface index + * @return interface index, 0 as default interface value on error + */ +unsigned int ff_ip_resolve_interface_index(struct sockaddr_storage *local_addr); + #endif /* AVFORMAT_IP_H */ diff --git a/libavformat/network.h b/libavformat/network.h index ca214087fc..2461b651d4 100644 --- a/libavformat/network.h +++ b/libavformat/network.h @@ -38,6 +38,10 @@ #include #include +#if HAVE_IPHLPAPI_H +#include +#endif + #ifndef EPROTONOSUPPORT #define EPROTONOSUPPORT WSAEPROTONOSUPPORT #endif @@ -64,6 +68,8 @@ int ff_neterrno(void); #include #include #include +#include +#include #define ff_neterrno() AVERROR(errno) #endif /* HAVE_WINSOCK2_H */ diff --git a/libavformat/udp.c b/libavformat/udp.c index d9514f5026..9b8ca74282 100644 ---