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

Bunch of fixes for network plugins:

 - Check the actual numerical address,
   instead of assuming that undefined is written down "".
 - Resolve remote peer before messing with sockets, and do it only once.
 - Do not try to connect to remote peer when SSM join succeeded
   (I do not feel like guessing which OSes besides FreeBSD didn't like this).
 - Do not assume that address are in numerical notation for SSM.
parent a719a0db
...@@ -162,8 +162,9 @@ static int OpenUDP( vlc_object_t * p_this ) ...@@ -162,8 +162,9 @@ static int OpenUDP( vlc_object_t * p_this )
int i_server_port = p_socket->i_server_port; int i_server_port = p_socket->i_server_port;
int i_handle, i_opt; int i_handle, i_opt;
struct sockaddr_in sock; struct sockaddr_in loc, rem;
vlc_value_t val; vlc_value_t val;
vlc_bool_t do_connect = VLC_TRUE;
#if defined(WIN32) || defined(UNDER_CE) #if defined(WIN32) || defined(UNDER_CE)
char strerror_buf[WINSOCK_STRERROR_SIZE]; char strerror_buf[WINSOCK_STRERROR_SIZE];
# define strerror( x ) winsock_strerror( strerror_buf ) # define strerror( x ) winsock_strerror( strerror_buf )
...@@ -172,11 +173,9 @@ static int OpenUDP( vlc_object_t * p_this ) ...@@ -172,11 +173,9 @@ static int OpenUDP( vlc_object_t * p_this )
p_socket->i_handle = -1; p_socket->i_handle = -1;
/* Build the local socket */ /* Build the local socket */
if( BuildAddr( p_this, &sock, psz_bind_addr, i_bind_port ) == -1 ) if( BuildAddr( p_this, &loc, psz_bind_addr, i_bind_port )
{ || BuildAddr( p_this, &rem, psz_server_addr, i_server_port ) )
msg_Dbg( p_this, "cannot build local address" );
return 0; return 0;
}
/* Open a SOCK_DGRAM (UDP) socket, in the AF_INET domain, automatic (0) /* Open a SOCK_DGRAM (UDP) socket, in the AF_INET domain, automatic (0)
* protocol */ * protocol */
...@@ -219,7 +218,7 @@ static int OpenUDP( vlc_object_t * p_this ) ...@@ -219,7 +218,7 @@ static int OpenUDP( vlc_object_t * p_this )
* to via other sockets. How this actually works in Winsock, I don't * to via other sockets. How this actually works in Winsock, I don't
* know. * know.
*/ */
if( IN_MULTICAST( ntohl( sock.sin_addr.s_addr ) ) ) if( IN_MULTICAST( ntohl( loc.sin_addr.s_addr ) ) )
{ {
struct sockaddr_in stupid = sock; struct sockaddr_in stupid = sock;
stupid.sin_addr.s_addr = INADDR_ANY; stupid.sin_addr.s_addr = INADDR_ANY;
...@@ -234,7 +233,7 @@ static int OpenUDP( vlc_object_t * p_this ) ...@@ -234,7 +233,7 @@ static int OpenUDP( vlc_object_t * p_this )
else else
#endif #endif
/* Bind it */ /* Bind it */
if( bind( i_handle, (struct sockaddr *)&sock, sizeof( sock ) ) < 0 ) if( bind( i_handle, (struct sockaddr *)&loc, sizeof( loc ) ) < 0 )
{ {
msg_Warn( p_this, "cannot bind socket (%s)", strerror(errno) ); msg_Warn( p_this, "cannot bind socket (%s)", strerror(errno) );
close( i_handle ); close( i_handle );
...@@ -243,7 +242,7 @@ static int OpenUDP( vlc_object_t * p_this ) ...@@ -243,7 +242,7 @@ static int OpenUDP( vlc_object_t * p_this )
#if !defined( SYS_BEOS ) #if !defined( SYS_BEOS )
/* Allow broadcast reception if we bound on INADDR_ANY */ /* Allow broadcast reception if we bound on INADDR_ANY */
if( !*psz_bind_addr ) if( loc.sin_addr.s_addr == INADDR_ANY )
{ {
i_opt = 1; i_opt = 1;
if( setsockopt( i_handle, SOL_SOCKET, SO_BROADCAST, (void*) &i_opt, if( setsockopt( i_handle, SOL_SOCKET, SO_BROADCAST, (void*) &i_opt,
...@@ -255,7 +254,7 @@ static int OpenUDP( vlc_object_t * p_this ) ...@@ -255,7 +254,7 @@ static int OpenUDP( vlc_object_t * p_this )
#if !defined( SYS_BEOS ) #if !defined( SYS_BEOS )
/* Join the multicast group if the socket is a multicast address */ /* Join the multicast group if the socket is a multicast address */
if( IN_MULTICAST( ntohl(sock.sin_addr.s_addr) ) ) if( IN_MULTICAST( ntohl(loc.sin_addr.s_addr) ) )
{ {
/* Determine interface to be used for multicast */ /* Determine interface to be used for multicast */
char * psz_if_addr = config_GetPsz( p_this, "miface-addr" ); char * psz_if_addr = config_GetPsz( p_this, "miface-addr" );
...@@ -263,7 +262,7 @@ static int OpenUDP( vlc_object_t * p_this ) ...@@ -263,7 +262,7 @@ static int OpenUDP( vlc_object_t * p_this )
/* If we have a source address, we use IP_ADD_SOURCE_MEMBERSHIP /* If we have a source address, we use IP_ADD_SOURCE_MEMBERSHIP
so that IGMPv3 aware OSes running on IGMPv3 aware networks so that IGMPv3 aware OSes running on IGMPv3 aware networks
will do an IGMPv3 query on the network */ will do an IGMPv3 query on the network */
if (( *psz_server_addr ) if (( rem.sin_addr.s_addr != INADDR_ANY )
/*&& ((ntohl (sock.sin_addr.s_addr) >> 24) == 232)*/) /*&& ((ntohl (sock.sin_addr.s_addr) >> 24) == 232)*/)
{ {
#ifndef IP_ADD_SOURCE_MEMBERSHIP #ifndef IP_ADD_SOURCE_MEMBERSHIP
...@@ -271,8 +270,8 @@ static int OpenUDP( vlc_object_t * p_this ) ...@@ -271,8 +270,8 @@ static int OpenUDP( vlc_object_t * p_this )
#else #else
struct ip_mreq_source imr; struct ip_mreq_source imr;
imr.imr_multiaddr.s_addr = sock.sin_addr.s_addr; imr.imr_multiaddr.s_addr = loc.sin_addr.s_addr;
imr.imr_sourceaddr.s_addr = inet_addr(psz_server_addr); imr.imr_sourceaddr.s_addr = rem.sin_addr.s_addr;
if( psz_if_addr != NULL && *psz_if_addr if( psz_if_addr != NULL && *psz_if_addr
&& inet_addr(psz_if_addr) != INADDR_NONE ) && inet_addr(psz_if_addr) != INADDR_NONE )
...@@ -288,7 +287,9 @@ static int OpenUDP( vlc_object_t * p_this ) ...@@ -288,7 +287,9 @@ static int OpenUDP( vlc_object_t * p_this )
/* Join Multicast group with source filter */ /* Join Multicast group with source filter */
if( setsockopt( i_handle, IPPROTO_IP, IP_ADD_SOURCE_MEMBERSHIP, if( setsockopt( i_handle, IPPROTO_IP, IP_ADD_SOURCE_MEMBERSHIP,
(char*)&imr, (char*)&imr,
sizeof(struct ip_mreq_source) ) == -1 ) sizeof(struct ip_mreq_source) ) == 0 )
do_connect = VLC_FALSE;
else
#endif #endif
{ {
msg_Warn( p_this, "Source specific multicast failed (%s) -" msg_Warn( p_this, "Source specific multicast failed (%s) -"
...@@ -304,7 +305,7 @@ igmpv2: ...@@ -304,7 +305,7 @@ igmpv2:
struct ip_mreq imr; struct ip_mreq imr;
imr.imr_interface.s_addr = INADDR_ANY; imr.imr_interface.s_addr = INADDR_ANY;
imr.imr_multiaddr.s_addr = sock.sin_addr.s_addr; imr.imr_multiaddr.s_addr = loc.sin_addr.s_addr;
if( psz_if_addr != NULL && *psz_if_addr if( psz_if_addr != NULL && *psz_if_addr
&& inet_addr(psz_if_addr) != INADDR_NONE ) && inet_addr(psz_if_addr) != INADDR_NONE )
{ {
...@@ -383,23 +384,11 @@ igmpv2: ...@@ -383,23 +384,11 @@ igmpv2:
} }
#endif #endif
#ifdef __FreeBSD__ if( rem.sin_addr.s_addr != INADDR_ANY )
else
#endif
if( *psz_server_addr )
{ {
/* Build socket for remote connection */
if ( BuildAddr( p_this, &sock, psz_server_addr, i_server_port ) == -1 )
{
msg_Warn( p_this, "cannot build remote address" );
close( i_handle );
return 0;
}
/* Connect the socket */ /* Connect the socket */
if( connect( i_handle, (struct sockaddr *) &sock, if( do_connect
sizeof( sock ) ) == (-1) ) && connect( i_handle, (struct sockaddr *) &rem, sizeof( rem ) ) )
{ {
msg_Warn( p_this, "cannot connect socket (%s)", strerror(errno) ); msg_Warn( p_this, "cannot connect socket (%s)", strerror(errno) );
close( i_handle ); close( i_handle );
...@@ -407,7 +396,7 @@ igmpv2: ...@@ -407,7 +396,7 @@ igmpv2:
} }
#if !defined( SYS_BEOS ) #if !defined( SYS_BEOS )
if( IN_MULTICAST( ntohl(inet_addr(psz_server_addr) ) ) ) if( IN_MULTICAST( ntohl(rem.sin_addr.s_addr) ) )
{ {
/* set the time-to-live */ /* set the time-to-live */
int i_ttl = p_socket->i_ttl; int i_ttl = p_socket->i_ttl;
......
...@@ -144,8 +144,9 @@ static int OpenUDP( vlc_object_t * p_this ) ...@@ -144,8 +144,9 @@ static int OpenUDP( vlc_object_t * p_this )
const char *psz_server_addr = p_socket->psz_server_addr; const char *psz_server_addr = p_socket->psz_server_addr;
int i_server_port = p_socket->i_server_port; int i_server_port = p_socket->i_server_port;
int i_handle, i_opt; int i_handle, i_opt;
struct sockaddr_in6 sock; struct sockaddr_in6 loc, rem;
vlc_value_t val; vlc_value_t val;
vlc_bool_t do_connect = VLC_TRUE;
#if defined(WIN32) || defined(UNDER_CE) #if defined(WIN32) || defined(UNDER_CE)
char strerror_buf[WINSOCK_STRERROR_SIZE]; char strerror_buf[WINSOCK_STRERROR_SIZE];
# define strerror( x ) winsock_strerror( strerror_buf ) # define strerror( x ) winsock_strerror( strerror_buf )
...@@ -154,7 +155,9 @@ static int OpenUDP( vlc_object_t * p_this ) ...@@ -154,7 +155,9 @@ static int OpenUDP( vlc_object_t * p_this )
p_socket->i_handle = -1; p_socket->i_handle = -1;
/* Build the local socket */ /* Build the local socket */
if ( BuildAddr( p_this, &sock, psz_bind_addr, i_bind_port ) == -1 ) if ( BuildAddr( p_this, &loc, psz_bind_addr, i_bind_port )
/* Build socket for remote connection */
|| BuildAddr( p_this, &rem, psz_server_addr, i_server_port ) )
return 0; return 0;
/* Open a SOCK_DGRAM (UDP) socket, in the AF_INET6 domain, automatic (0) /* Open a SOCK_DGRAM (UDP) socket, in the AF_INET6 domain, automatic (0)
...@@ -212,14 +215,14 @@ static int OpenUDP( vlc_object_t * p_this ) ...@@ -212,14 +215,14 @@ static int OpenUDP( vlc_object_t * p_this )
#if defined(WIN32) #if defined(WIN32)
/* Under Win32 and for multicasting, we bind to IN6ADDR_ANY */ /* Under Win32 and for multicasting, we bind to IN6ADDR_ANY */
if( IN6_IS_ADDR_MULTICAST(&sock.sin6_addr) ) if( IN6_IS_ADDR_MULTICAST(&loc.sin6_addr) )
{ {
struct sockaddr_in6 sockany = sock; struct sockaddr_in6 sockany = sock;
sockany.sin6_addr = in6addr_any; sockany.sin6_addr = in6addr_any;
sockany.sin6_scope_id = 0; sockany.sin6_scope_id = 0;
/* Bind it */ /* Bind it */
if( bind( i_handle, (struct sockaddr *)&sockany, sizeof( sock ) ) < 0 ) if( bind( i_handle, (struct sockaddr *)&sockany, sizeof( sockany ) ) < 0 )
{ {
msg_Warn( p_this, "cannot bind socket (%s)", strerror(errno) ); msg_Warn( p_this, "cannot bind socket (%s)", strerror(errno) );
close( i_handle ); close( i_handle );
...@@ -229,7 +232,7 @@ static int OpenUDP( vlc_object_t * p_this ) ...@@ -229,7 +232,7 @@ static int OpenUDP( vlc_object_t * p_this )
else else
#endif #endif
/* Bind it */ /* Bind it */
if( bind( i_handle, (struct sockaddr *)&sock, sizeof( sock ) ) < 0 ) if( bind( i_handle, (struct sockaddr *)&loc, sizeof( loc ) ) < 0 )
{ {
msg_Warn( p_this, "cannot bind socket (%s)", strerror(errno) ); msg_Warn( p_this, "cannot bind socket (%s)", strerror(errno) );
close( i_handle ); close( i_handle );
...@@ -237,9 +240,9 @@ static int OpenUDP( vlc_object_t * p_this ) ...@@ -237,9 +240,9 @@ static int OpenUDP( vlc_object_t * p_this )
} }
/* Join the multicast group if the socket is a multicast address */ /* Join the multicast group if the socket is a multicast address */
if( IN6_IS_ADDR_MULTICAST(&sock.sin6_addr) ) if( IN6_IS_ADDR_MULTICAST(&loc.sin6_addr) )
{ {
if ((*psz_server_addr) if (memcmp (&rem.sin6_addr, &in6addr_any, 16)
/*&& ((U32_AT (&sock.sin6_addr) & 0xff30ffff) == 0xff300000)*/) /*&& ((U32_AT (&sock.sin6_addr) & 0xff30ffff) == 0xff300000)*/)
{ {
#ifndef MCAST_JOIN_SOURCE_GROUP #ifndef MCAST_JOIN_SOURCE_GROUP
...@@ -248,27 +251,19 @@ static int OpenUDP( vlc_object_t * p_this ) ...@@ -248,27 +251,19 @@ static int OpenUDP( vlc_object_t * p_this )
struct group_source_req imr; struct group_source_req imr;
struct sockaddr_in6 *p_sin6; struct sockaddr_in6 *p_sin6;
imr.gsr_interface = 0; memset (&imr, 0, sizeof (imr));
imr.gsr_group.ss_family = AF_INET6; imr.gsr_group.ss_family = AF_INET6;
imr.gsr_source.ss_family = AF_INET6; imr.gsr_source.ss_family = AF_INET6;
p_sin6 = (struct sockaddr_in6 *)&imr.gsr_group; p_sin6 = (struct sockaddr_in6 *)&imr.gsr_group;
p_sin6->sin6_addr = sock.sin6_addr; p_sin6->sin6_addr = loc.sin6_addr;
/* Build socket for remote connection */
msg_Dbg( p_this, "psz_server_addr : %s", psz_server_addr);
if ( BuildAddr( p_this, &sock, psz_server_addr, i_server_port ) )
{
msg_Warn( p_this, "cannot build remote address" );
close( i_handle );
return 0;
}
p_sin6 = (struct sockaddr_in6 *)&imr.gsr_source; p_sin6 = (struct sockaddr_in6 *)&imr.gsr_source;
p_sin6->sin6_addr = sock.sin6_addr; p_sin6->sin6_addr = rem.sin6_addr;
msg_Dbg( p_this, "MCAST_JOIN_SOURCE_GROUP multicast request" ); msg_Dbg( p_this, "MCAST_JOIN_SOURCE_GROUP multicast request" );
if( setsockopt( i_handle, IPPROTO_IPV6, MCAST_JOIN_SOURCE_GROUP, if( setsockopt( i_handle, IPPROTO_IPV6, MCAST_JOIN_SOURCE_GROUP,
(char *)&imr, sizeof(struct group_source_req) ) == -1 ) (void *)&imr, sizeof(struct group_source_req) ) == 0 )
do_connect = VLC_FALSE;
else
#endif #endif
{ {
...@@ -282,19 +277,20 @@ static int OpenUDP( vlc_object_t * p_this ) ...@@ -282,19 +277,20 @@ static int OpenUDP( vlc_object_t * p_this )
mldv1: mldv1:
{ {
struct ipv6_mreq imr; struct ipv6_mreq imr;
int res;
imr.ipv6mr_interface = sock.sin6_scope_id; memset (&imr, 0, sizeof (imr));
imr.ipv6mr_multiaddr = sock.sin6_addr; imr.ipv6mr_interface = loc.sin6_scope_id;
imr.ipv6mr_multiaddr = loc.sin6_addr;
msg_Dbg( p_this, "IPV6_JOIN_GROUP multicast request" ); msg_Dbg( p_this, "IPV6_JOIN_GROUP multicast request" );
res = setsockopt(i_handle, IPPROTO_IPV6, IPV6_JOIN_GROUP, (void*) &imr, if (setsockopt(i_handle, IPPROTO_IPV6, IPV6_JOIN_GROUP, (void*) &imr,
#if defined(WIN32) #if defined(WIN32)
sizeof(imr) + 4); /* Doesn't work without this */ sizeof(imr) + 4
/* Doesn't work without this
* - Really? because it's really a buffer overflow... */
#else #else
sizeof(imr)); sizeof(imr)
#endif #endif
))
if( res == -1 )
{ {
msg_Err( p_this, "cannot join multicast group" ); msg_Err( p_this, "cannot join multicast group" );
close( i_handle ); close( i_handle );
...@@ -303,25 +299,13 @@ mldv1: ...@@ -303,25 +299,13 @@ mldv1:
} }
} }
#ifdef __FreeBSD__ if( memcmp (&rem.sin6_addr, &in6addr_any, 16) )
else
#endif
if( *psz_server_addr )
{ {
int ttl; int ttl;
/* Build socket for remote connection */
if ( BuildAddr( p_this, &sock, psz_server_addr, i_server_port ) == -1 )
{
msg_Warn( p_this, "cannot build remote address" );
close( i_handle );
return 0;
}
/* Connect the socket */ /* Connect the socket */
if( connect( i_handle, (struct sockaddr *) &sock, if( do_connect
sizeof( sock ) ) == (-1) ) && connect( i_handle, (struct sockaddr *) &rem, sizeof( rem ) ) )
{ {
msg_Warn( p_this, "cannot connect socket (%s)", strerror(errno) ); msg_Warn( p_this, "cannot connect socket (%s)", strerror(errno) );
close( i_handle ); close( i_handle );
...@@ -335,7 +319,7 @@ mldv1: ...@@ -335,7 +319,7 @@ mldv1:
if( ttl > 0 ) if( ttl > 0 )
{ {
if( IN6_IS_ADDR_MULTICAST(&sock.sin6_addr) ) if( IN6_IS_ADDR_MULTICAST(&rem.sin6_addr) )
{ {
if( setsockopt( i_handle, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, if( setsockopt( i_handle, IPPROTO_IPV6, IPV6_MULTICAST_HOPS,
(void *)&ttl, sizeof( ttl ) ) < 0 ) (void *)&ttl, sizeof( ttl ) ) < 0 )
...@@ -356,7 +340,7 @@ mldv1: ...@@ -356,7 +340,7 @@ mldv1:
} }
/* Set multicast output interface */ /* Set multicast output interface */
if( IN6_IS_ADDR_MULTICAST(&sock.sin6_addr) ) if( IN6_IS_ADDR_MULTICAST(&rem.sin6_addr) )
{ {
char *psz_mif = config_GetPsz( p_this, "miface" ); char *psz_mif = config_GetPsz( p_this, "miface" );
if( psz_mif != NULL ) if( psz_mif != NULL )
......
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