]> git.sesse.net Git - vlc/commitdiff
Implement IPv6 multicast output interface selection (closes #491)
authorRémi Denis-Courmont <rem@videolan.org>
Sat, 11 Feb 2006 10:42:48 +0000 (10:42 +0000)
committerRémi Denis-Courmont <rem@videolan.org>
Sat, 11 Feb 2006 10:42:48 +0000 (10:42 +0000)
modules/misc/network/ipv4.c
modules/misc/network/ipv6.c
src/libvlc.h
src/network/udp.c

index 86cb68928f3afe808d9659b0031ac3f0bd610484..2912b2a3d1f5a1a2f45cea970386a5eb239591dc 100644 (file)
@@ -343,11 +343,11 @@ static int OpenUDP( vlc_object_t * p_this )
 #if defined (WIN32) || defined (UNDER_CE)
             else
             {
-                               typedef DWORD (CALLBACK * GETBESTINTERFACE) ( IPAddr, PDWORD );
-                               typedef DWORD (CALLBACK * GETIPADDRTABLE) ( PMIB_IPADDRTABLE, PULONG, BOOL );
+                typedef DWORD (CALLBACK * GETBESTINTERFACE) ( IPAddr, PDWORD );
+                typedef DWORD (CALLBACK * GETIPADDRTABLE) ( PMIB_IPADDRTABLE, PULONG, BOOL );
 
                 GETBESTINTERFACE OurGetBestInterface;
-                               GETIPADDRTABLE OurGetIpAddrTable;
+                GETIPADDRTABLE OurGetIpAddrTable;
                 HINSTANCE hiphlpapi = LoadLibrary(_T("Iphlpapi.dll"));
                 DWORD i_index;
 
index fa4f2a4dd8a6e9a0f85d44b755615353a852575b..2f88d239736ca1e74c60b1c052d97704af5c6d91 100644 (file)
 
 #include <errno.h>
 
-#ifdef HAVE_FCNTL_H
-#   include <fcntl.h>
-#endif
-#ifdef HAVE_SYS_TYPES_H
-#   include <sys/types.h>
-#endif
-#ifdef HAVE_UNISTD_H
-#   include <unistd.h>
-#endif
-
 #ifdef WIN32
 #   include <winsock2.h>
 #   include <ws2tcpip.h>
-#elif !defined( SYS_BEOS ) && !defined( SYS_NTO )
+#   define if_nametoindex( str ) atoi( str )
+#else
+#   include <sys/types.h>
+#   include <unistd.h>
 #   include <netdb.h>                                         /* hostent ... */
 #   include <sys/socket.h>
 #   include <netinet/in.h>
+#   include <net/if.h>
 #endif
 
 #include "network.h"
@@ -312,9 +306,7 @@ static int OpenUDP( vlc_object_t * p_this )
 
     if( *psz_server_addr )
     {
-        int ttl = p_socket->i_ttl;
-        if( ttl <= 0 )
-            ttl = config_GetInt( p_this, "ttl" );
+        int ttl;
 
         /* Build socket for remote connection */
         if ( BuildAddr( p_this, &sock, psz_server_addr, i_server_port ) == -1 )
@@ -334,9 +326,12 @@ static int OpenUDP( vlc_object_t * p_this )
         }
 
         /* Set the time-to-live */
+        ttl = p_socket->i_ttl;
+        if( ttl <= 0 )
+            ttl = config_GetInt( p_this, "ttl" );
+
         if( ttl > 0 )
         {
-#if defined( WIN32 ) || defined( HAVE_IF_NAMETOINDEX )
             if( IN6_IS_ADDR_MULTICAST(&sock.sin6_addr) )
             {
                 if( setsockopt( i_handle, IPPROTO_IPV6, IPV6_MULTICAST_HOPS,
@@ -347,7 +342,6 @@ static int OpenUDP( vlc_object_t * p_this )
                 }
             }
             else
-#endif
             {
                 if( setsockopt( i_handle, IPPROTO_IPV6, IPV6_UNICAST_HOPS,
                                 (void *)&ttl, sizeof( ttl ) ) < 0 )
@@ -357,6 +351,36 @@ static int OpenUDP( vlc_object_t * p_this )
                 }
             }
         }
+
+        /* Set multicast output interface */
+        if( IN6_IS_ADDR_MULTICAST(&sock.sin6_addr) )
+        {
+            char *psz_mif = config_GetPsz( p_this, "miface" );
+            if( psz_mif != NULL )
+            {
+                int intf = if_nametoindex( psz_mif );
+                free( psz_mif  );
+
+                if( intf != 0 )
+                {
+                    if( setsockopt( i_handle, IPPROTO_IPV6, IPV6_MULTICAST_IF,
+                        &intf, sizeof( intf ) ) < 0 )
+                    {
+                        msg_Err( p_this, "%s as multicast interface: %s",
+                                 psz_mif, strerror(errno) );
+                        close( i_handle );
+                        return 0;
+                    }
+                }
+                else
+                {
+                    msg_Err( p_this, "%s: bad IPv6 interface spefication",
+                             psz_mif );
+                    close( i_handle );
+                    return 0;
+                }
+            }
+        }
     }
 
     p_socket->i_handle = i_handle;
index 40993399053e77a7673a2591e3adf7edae663863..42e6048f5076b0ac630897b404cf5be1d5a141f5 100644 (file)
@@ -1,7 +1,7 @@
 /*****************************************************************************
  * libvlc.h: main libvlc header
  *****************************************************************************
- * Copyright (C) 1998-2005 VideoLAN (Centrale Réseaux) and its contributors
+ * Copyright (C) 1998-2006 the VideoLAN team
  * $Id$
  *
  * Authors: Vincent Seguin <seguin@via.ecp.fr>
@@ -366,7 +366,7 @@ static char *ppsz_clock_descriptions[] =
 
 #define SERVER_PORT_TEXT N_("UDP port")
 #define SERVER_PORT_LONGTEXT N_( \
-    "This is the port used for UDP streams. By default, we chose 1234.")
+    "This is the port used for UDP streams. 1234 by default.")
 
 #define MTU_TEXT N_("MTU of the network interface")
 #define MTU_LONGTEXT N_( \
@@ -378,11 +378,16 @@ static char *ppsz_clock_descriptions[] =
     "Specify the hop limit (TTL) of the multicast packets sent by " \
     "the stream output.")
 
-#define MIFACE_TEXT N_("Multicast output interface")
+#define MIFACE_TEXT N_("IPv6 multicast output interface")
 #define MIFACE_LONGTEXT N_( \
     "Indicate here the multicast output interface. " \
     "This overrides the routing table.")
 
+#define MIFACE_ADDR_TEXT N_("IPv4 multicast output interface address")
+#define MIFACE_ADDR_LONGTEXT N_( \
+    "Specify the IPv4 address of the networking interface. " \
+    "This overrides the routing table.")
+
 #define INPUT_PROGRAM_TEXT N_("Program to select")
 #define INPUT_PROGRAM_LONGTEXT N_( \
     "Choose the program to select by giving its Service ID.\n" \
@@ -1328,7 +1333,8 @@ vlc_module_begin();
     add_module( "access_output", "sout access", NULL, NULL,
                 ACCESS_OUTPUT_TEXT, ACCESS_OUTPUT_LONGTEXT, VLC_TRUE );
     add_integer( "ttl", 1, NULL, TTL_TEXT, TTL_LONGTEXT, VLC_TRUE );
-    add_string( "miface-addr", NULL, NULL, MIFACE_TEXT, MIFACE_LONGTEXT, VLC_TRUE );
+    add_string( "miface", NULL, NULL, MIFACE_TEXT, MIFACE_LONGTEXT, VLC_TRUE );
+    add_string( "miface-addr", NULL, NULL, MIFACE_ADDR_TEXT, MIFACE_ADDR_LONGTEXT, VLC_TRUE );
 
     set_subcategory( SUBCAT_SOUT_PACKETIZER );
     add_module( "packetizer","packetizer", NULL, NULL,
index 36597c58f4de65d6db9105cad58ae51222529c31..3fe792dc079eb4885a5c77f2631a7377530740d1 100644 (file)
@@ -1,7 +1,7 @@
 /*****************************************************************************
  * udp.c:
  *****************************************************************************
- * Copyright (C) 2004-2005 the VideoLAN team
+ * Copyright (C) 2004-2006 the VideoLAN team
  * $Id$
  *
  * Authors: Laurent Aimar <fenrir@videolan.org>
 
 #include <errno.h>
 
-#ifdef HAVE_FCNTL_H
-#   include <fcntl.h>
-#endif
 #ifdef HAVE_SYS_TIME_H
 #    include <sys/time.h>
 #endif
-#ifdef HAVE_UNISTD_H
-#   include <unistd.h>
-#endif
 
 #include "network.h"
 
 #       define IP_ADD_MEMBERSHIP 5
 #   endif
 #   define EAFNOSUPPORT WSAEAFNOSUPPORT
+#   define if_nametoindex( str ) atoi( str )
+#else
+#   include <unistd.h>
+#   include <net/if.h>
 #endif
 
 #ifndef SOL_IP
@@ -109,42 +107,60 @@ static int net_SetMcastHopLimit( vlc_object_t *p_this,
 }
 
 
-static int net_SetMcastSource( vlc_object_t *p_this,
-                                int fd, int family, const char *str )
+static int net_SetMcastIface( vlc_object_t *p_this,
+                              int fd, int family, const char *str )
 {
-#ifndef SYS_BEOS
     switch( family )
     {
+#ifndef SYS_BEOS
         case AF_INET:
         {
             struct in_addr addr;
 
             if( inet_pton( AF_INET, str, &addr) <= 0 )
             {
-                msg_Err( p_this, "Invalid multicast interface %s",
-                         str );
+                msg_Err( p_this, "Invalid multicast interface %s", str );
                 return VLC_EGENERIC;
             }
 
-            if( setsockopt( fd, IPPROTO_IP, IP_MULTICAST_IF, &addr,
+            if( setsockopt( fd, SOL_IP, IP_MULTICAST_IF, &addr,
                             sizeof( addr ) ) < 0 )
             {
-                msg_Dbg( p_this, "Cannot set multicast interface (%s)",
+                msg_Err( p_this, "Cannot use %s as multicast interface: %s",
                          strerror(errno) );
                 return VLC_EGENERIC;
             }
             break;
         }
+#endif /* SYS_BEOS */
 
 #ifdef IPV6_MULTICAST_IF
-/* FIXME: TODO */
+        case AF_INET6:
+        {
+            int scope = if_nametoindex( str );
+
+            if( scope == 0 )
+            {
+                msg_Err( p_this, "Invalid multicast interface %s", str );
+                return VLC_EGENERIC;
+            }
+
+            if( setsockopt( fd, SOL_IPV6, IPV6_MULTICAST_IF,
+                            &scope, sizeof( scope ) ) < 0 )
+            {
+                msg_Err( p_this, "Cannot use %s as multicast interface: %s",
+                         str, strerror( errno ) );
+                return VLC_EGENERIC;
+            }
+            break;
+        }
 #endif
+
         default:
             msg_Warn( p_this, "%s", strerror( EAFNOSUPPORT ) );
             return VLC_EGENERIC;
     }
 
-#endif
     return VLC_SUCCESS;
 }
 
@@ -183,7 +199,7 @@ int __net_ConnectUDP( vlc_object_t *p_this, const char *psz_host, int i_port,
     for( ptr = res; ptr != NULL; ptr = ptr->ai_next )
     {
         int fd;
-        char *psz_mif_addr;
+        char *psz_mif;
 
         fd = net_Socket( p_this, ptr->ai_family, ptr->ai_socktype,
                          ptr->ai_protocol );
@@ -212,11 +228,12 @@ int __net_ConnectUDP( vlc_object_t *p_this, const char *psz_host, int i_port,
 
         if( i_hlim > 0 )
             net_SetMcastHopLimit( p_this, fd, ptr->ai_family, i_hlim );
-        psz_mif_addr = config_GetPsz( p_this, "miface-addr" );
-        if( psz_mif_addr != NULL )
+        psz_mif = config_GetPsz( p_this, (ptr->ai_family != AF_INET)
+                                            ? "miface" : "miface-addr" );
+        if( psz_mif != NULL )
         {
-            net_SetMcastSource( p_this, fd, ptr->ai_family, psz_mif_addr );
-            free( psz_mif_addr );
+            net_SetMcastIface( p_this, fd, ptr->ai_family, psz_mif );
+            free( psz_mif );
         }
 
         if( connect( fd, ptr->ai_addr, ptr->ai_addrlen ) == 0 )