Re: [FFmpeg-devel] [PATCH v3] avformat: enable UDP IPv6 multicast interface selection using zone index

2024-04-19 Thread RS

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

2024-04-11 Thread RS
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(_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, , 
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 
*), 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, , 
sizeof(unsigned int)) < 0) {
+ff_log_net_error(logctx, AV_LOG_ERROR, 
"setsockopt(IPV6_MULTICAST_IF)");
+

Re: [FFmpeg-devel] [PATCH v2] avformat: enable UDP IPv6 multicast interface selection using zone index

2024-04-11 Thread RS

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

2024-04-11 Thread RS
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(_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, , 
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 
*), 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, , 
sizeof(unsigned int)) < 0) {
+ff_log_net_error(logctx, AV_LOG_ERROR, 
"setsockopt(IPV6_MULTICAST_IF)");
+return ff_neterrno();
+ 

[FFmpeg-devel] [PATCH v2] avformat: enable UDP IPv6 multicast interface selection using zone index

2024-03-27 Thread RS
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(_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, , 
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 
*), 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, , 
sizeof(unsigned int)) < 0) {
+ff_log_net_error(logctx, AV_LOG_ERROR, 
"setsockopt(IPV6_MULTICAST_IF)");
+return ff_neterrno();
+ 

Re: [FFmpeg-devel] [PATCH v3] avformat: enable UDP IPv6 multicast interface selection using localaddr

2024-03-27 Thread RS

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

2024-03-26 Thread RS
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, );
+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() == -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);
 #include 
 #include 

[FFmpeg-devel] [PATCH v3] avformat: enable UDP IPv6 multicast interface selection using localaddr

2024-03-26 Thread RS
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, );
+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() == -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 
 #include 

Re: [FFmpeg-devel] [PATCH v2] avformat: enable UDP IPv6 multicast interface selection

2024-03-22 Thread RS

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

2024-03-22 Thread RS
>> 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

2024-03-21 Thread RS
> 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

2024-03-20 Thread RS

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

2024-03-20 Thread RS

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

2024-03-20 Thread RS

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

2024-03-20 Thread RS
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, );
+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() == -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 

Re: [FFmpeg-devel] [PATCH] avformat: enable UDP IPv6 multicast interface selection

2024-03-19 Thread RS


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

2024-03-18 Thread RS

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

2024-03-14 Thread RS
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, );
+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() == -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,7 @@ static 

Re: [FFmpeg-devel] [PATCH] avformat: enable UDP IPv6 multicast interface selection

2024-03-14 Thread RS
>> +if (if_indextoname(iface, ifr.ifr_name)) {
>> +if (setsockopt(udp_fd, SOL_SOCKET, SO_BINDTODEVICE, (void 
>> *), 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

2024-03-14 Thread RS
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, );
+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() == -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
---