Commit c6e34683 authored by Rémi Denis-Courmont's avatar Rémi Denis-Courmont

Implement IPv6 multicast output interface selection (closes #491)

parent 069e052f
......@@ -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;
......
......@@ -34,23 +34,17 @@
#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;
......
/*****************************************************************************
* 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,
......
/*****************************************************************************
* udp.c:
*****************************************************************************
* Copyright (C) 2004-2005 the VideoLAN team
* Copyright (C) 2004-2006 the VideoLAN team
* $Id$
*
* Authors: Laurent Aimar <fenrir@videolan.org>
......@@ -30,15 +30,9 @@
#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"
......@@ -50,6 +44,10 @@
# 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 )
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment