Hi Peter On Fri, Aug 08, 2025 at 09:27:35AM +0200, Peter Enderborg wrote: > This fixes two old TODO's in ipv6 multicast handling. > If the system as SIOCGIFINDEX ioctl a helper function to iterate over > all interfaces added to join the multicast group on interface if approperite. > > The default value is IN6ADDR_ANY (::) and it then joins all interfaces > that are up and have multicast support. Local address can be > specified and then it join ALL interfaces that use that specific > local address. > > Limitations (TODO's) > Handling when network configuration is changed. if up/down etc. > > Signed-off-by: Peter Enderborg > --- > libavformat/udp.c | 98 ++++++++++++++++++++++++++++++++++++++++++++++- > 1 file changed, 96 insertions(+), 2 deletions(-) > > diff --git a/libavformat/udp.c b/libavformat/udp.c > index 84f9d3e62e..a0482c122f 100644 > --- a/libavformat/udp.c > +++ b/libavformat/udp.c > @@ -68,6 +68,13 @@ > #include "libavutil/thread.h" > #endif > > +#if HAVE_STRUCT_IPV6_MREQ && HAVE_IOCTL_GIFINDEX && defined(IPPROTO_IPV6) > +#include > +#include > +#include > +#include > +#endif > + > #ifndef IPV6_ADD_MEMBERSHIP > #define IPV6_ADD_MEMBERSHIP IPV6_JOIN_GROUP > #define IPV6_DROP_MEMBERSHIP IPV6_LEAVE_GROUP > @@ -205,6 +212,79 @@ static int udp_set_multicast_ttl(int sockfd, int mcastTTL, > > return 0; > } > +#if HAVE_STRUCT_IPV6_MREQ && HAVE_IOCTL_GIFINDEX && defined(IPPROTO_IPV6) > +static int udp_ipv6_multicast_iterate(int sockfd, struct sockaddr_in6 *addr, > + struct sockaddr_in6 *local_addr, int mop, void *logctx) > +{ > + struct in6_addr anyipv6 = IN6ADDR_ANY_INIT; > + struct ifaddrs *ifal=NULL,*ife=NULL; > + int iindex_fd = socket(AF_INET, SOCK_STREAM, IPPROTO_IP); > + int membership_changed = 0; > + > + if (iindex_fd >= 0 && !getifaddrs(&ifal)) { > + for(ife=ifal; ife!=NULL; ife=ife->ifa_next) { > + if (ife->ifa_addr && > + (ife->ifa_addr->sa_family == AF_INET6) && > + (ife->ifa_flags & IFF_MULTICAST) && > + (ife->ifa_flags & IFF_UP)) { > + if ((!memcmp(&local_addr->sin6_addr, &anyipv6, sizeof(struct in6_addr))) || > + (!memcmp(&local_addr->sin6_addr, &((struct sockaddr_in6 *)ife->ifa_addr)->sin6_addr, sizeof(struct in6_addr)))) { > + struct ifreq if_req; > + strncpy(if_req.ifr_name, ife->ifa_name, IFNAMSIZ); > + if (ioctl(iindex_fd, SIOCGIFINDEX, &if_req) != -1) { > + struct ipv6_mreq mreq6; > + memcpy(&mreq6.ipv6mr_multiaddr, &addr->sin6_addr, sizeof(struct in6_addr)); > + mreq6.ipv6mr_interface = if_req.ifr_ifindex; > + switch (mop) { > + case IPV6_JOIN_GROUP: > + if (setsockopt(sockfd, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, &mreq6, sizeof(mreq6)) == 0) { > + membership_changed = 1; > + } else { > + /* Subscribe for all ipv6 addresses belong to a > + interface.It can generate EADDRINUSE but > + is accaptable. */ > + if (errno != EADDRINUSE) { > + ff_log_net_error(logctx, AV_LOG_ERROR, "setsockopt(IPV6_ADD_MEMBERSHIP)"); > + goto error; the patch mixes tabs and spaces, we use only spaces in C files for indention. I will leave the review of teh actual changes to others as I am sure you know much more about ipv6 multicast than i do thx [...] -- Michael GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB Does the universe only have a finite lifespan? No, its going to go on forever, its just that you wont like living in it. -- Hiranya Peiri