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 )
int i_server_port = p_socket->i_server_port;
int i_handle, i_opt;
struct sockaddr_in sock;
struct sockaddr_in loc, rem;
vlc_value_t val;
vlc_bool_t do_connect = VLC_TRUE;
#if defined(WIN32) || defined(UNDER_CE)
char strerror_buf[WINSOCK_STRERROR_SIZE];
# define strerror( x ) winsock_strerror( strerror_buf )
......@@ -172,11 +173,9 @@ static int OpenUDP( vlc_object_t * p_this )
p_socket->i_handle = -1;
/* Build the local socket */
if( BuildAddr( p_this, &sock, psz_bind_addr, i_bind_port ) == -1 )
{
msg_Dbg( p_this, "cannot build local address" );
if( BuildAddr( p_this, &loc, psz_bind_addr, i_bind_port )
|| BuildAddr( p_this, &rem, psz_server_addr, i_server_port ) )
return 0;
}
/* Open a SOCK_DGRAM (UDP) socket, in the AF_INET domain, automatic (0)
* protocol */
......@@ -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
* know.
*/
if( IN_MULTICAST( ntohl( sock.sin_addr.s_addr ) ) )
if( IN_MULTICAST( ntohl( loc.sin_addr.s_addr ) ) )
{
struct sockaddr_in stupid = sock;
stupid.sin_addr.s_addr = INADDR_ANY;
......@@ -234,7 +233,7 @@ static int OpenUDP( vlc_object_t * p_this )
else
#endif
/* 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) );
close( i_handle );
......@@ -243,7 +242,7 @@ static int OpenUDP( vlc_object_t * p_this )
#if !defined( SYS_BEOS )
/* Allow broadcast reception if we bound on INADDR_ANY */
if( !*psz_bind_addr )
if( loc.sin_addr.s_addr == INADDR_ANY )
{
i_opt = 1;
if( setsockopt( i_handle, SOL_SOCKET, SO_BROADCAST, (void*) &i_opt,
......@@ -255,7 +254,7 @@ static int OpenUDP( vlc_object_t * p_this )
#if !defined( SYS_BEOS )
/* 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 */
char * psz_if_addr = config_GetPsz( p_this, "miface-addr" );
......@@ -263,7 +262,7 @@ static int OpenUDP( vlc_object_t * p_this )
/* If we have a source address, we use IP_ADD_SOURCE_MEMBERSHIP
so that IGMPv3 aware OSes running on IGMPv3 aware networks
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)*/)
{
#ifndef IP_ADD_SOURCE_MEMBERSHIP
......@@ -271,8 +270,8 @@ static int OpenUDP( vlc_object_t * p_this )
#else
struct ip_mreq_source imr;
imr.imr_multiaddr.s_addr = sock.sin_addr.s_addr;
imr.imr_sourceaddr.s_addr = inet_addr(psz_server_addr);
imr.imr_multiaddr.s_addr = loc.sin_addr.s_addr;
imr.imr_sourceaddr.s_addr = rem.sin_addr.s_addr;
if( psz_if_addr != NULL && *psz_if_addr
&& inet_addr(psz_if_addr) != INADDR_NONE )
......@@ -288,7 +287,9 @@ static int OpenUDP( vlc_object_t * p_this )
/* Join Multicast group with source filter */
if( setsockopt( i_handle, IPPROTO_IP, IP_ADD_SOURCE_MEMBERSHIP,
(char*)&imr,
sizeof(struct ip_mreq_source) ) == -1 )
sizeof(struct ip_mreq_source) ) == 0 )
do_connect = VLC_FALSE;
else
#endif
{
msg_Warn( p_this, "Source specific multicast failed (%s) -"
......@@ -304,7 +305,7 @@ igmpv2:
struct ip_mreq imr;
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
&& inet_addr(psz_if_addr) != INADDR_NONE )
{
......@@ -383,23 +384,11 @@ igmpv2:
}
#endif
#ifdef __FreeBSD__
else
#endif
if( *psz_server_addr )
if( rem.sin_addr.s_addr != INADDR_ANY )
{
/* 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 */
if( connect( i_handle, (struct sockaddr *) &sock,
sizeof( sock ) ) == (-1) )
if( do_connect
&& connect( i_handle, (struct sockaddr *) &rem, sizeof( rem ) ) )
{
msg_Warn( p_this, "cannot connect socket (%s)", strerror(errno) );
close( i_handle );
......@@ -407,7 +396,7 @@ igmpv2:
}
#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 */
int i_ttl = p_socket->i_ttl;
......
......@@ -144,8 +144,9 @@ static int OpenUDP( vlc_object_t * p_this )
const char *psz_server_addr = p_socket->psz_server_addr;
int i_server_port = p_socket->i_server_port;
int i_handle, i_opt;
struct sockaddr_in6 sock;
struct sockaddr_in6 loc, rem;
vlc_value_t val;
vlc_bool_t do_connect = VLC_TRUE;
#if defined(WIN32) || defined(UNDER_CE)
char strerror_buf[WINSOCK_STRERROR_SIZE];
# define strerror( x ) winsock_strerror( strerror_buf )
......@@ -154,7 +155,9 @@ static int OpenUDP( vlc_object_t * p_this )
p_socket->i_handle = -1;
/* 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;
/* 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 )
#if defined(WIN32)
/* 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;
sockany.sin6_addr = in6addr_any;
sockany.sin6_scope_id = 0;
/* 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) );
close( i_handle );
......@@ -229,7 +232,7 @@ static int OpenUDP( vlc_object_t * p_this )
else
#endif
/* 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) );
close( i_handle );
......@@ -237,9 +240,9 @@ static int OpenUDP( vlc_object_t * p_this )
}
/* 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)*/)
{
#ifndef MCAST_JOIN_SOURCE_GROUP
......@@ -248,27 +251,19 @@ static int OpenUDP( vlc_object_t * p_this )
struct group_source_req imr;
struct sockaddr_in6 *p_sin6;
imr.gsr_interface = 0;
memset (&imr, 0, sizeof (imr));
imr.gsr_group.ss_family = AF_INET6;
imr.gsr_source.ss_family = AF_INET6;
p_sin6 = (struct sockaddr_in6 *)&imr.gsr_group;
p_sin6->sin6_addr = sock.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->sin6_addr = loc.sin6_addr;
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" );
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
{
......@@ -282,19 +277,20 @@ static int OpenUDP( vlc_object_t * p_this )
mldv1:
{
struct ipv6_mreq imr;
int res;
imr.ipv6mr_interface = sock.sin6_scope_id;
imr.ipv6mr_multiaddr = sock.sin6_addr;
memset (&imr, 0, sizeof (imr));
imr.ipv6mr_interface = loc.sin6_scope_id;
imr.ipv6mr_multiaddr = loc.sin6_addr;
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)
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
sizeof(imr));
sizeof(imr)
#endif
if( res == -1 )
))
{
msg_Err( p_this, "cannot join multicast group" );
close( i_handle );
......@@ -303,25 +299,13 @@ mldv1:
}
}
#ifdef __FreeBSD__
else
#endif
if( *psz_server_addr )
if( memcmp (&rem.sin6_addr, &in6addr_any, 16) )
{
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 */
if( connect( i_handle, (struct sockaddr *) &sock,
sizeof( sock ) ) == (-1) )
if( do_connect
&& connect( i_handle, (struct sockaddr *) &rem, sizeof( rem ) ) )
{
msg_Warn( p_this, "cannot connect socket (%s)", strerror(errno) );
close( i_handle );
......@@ -335,7 +319,7 @@ mldv1:
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,
(void *)&ttl, sizeof( ttl ) ) < 0 )
......@@ -356,7 +340,7 @@ mldv1:
}
/* 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" );
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