+ 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);
+
+ if( psz_if_addr != NULL && *psz_if_addr
+ && inet_addr(psz_if_addr) != INADDR_NONE )
+ {
+ imr.imr_interface.s_addr = inet_addr(psz_if_addr);
+ }
+ else
+ {
+ imr.imr_interface.s_addr = INADDR_ANY;
+ }
+ if( psz_if_addr != NULL ) free( psz_if_addr );
+
+ msg_Dbg( p_this, "IP_ADD_SOURCE_MEMBERSHIP multicast request" );
+ /* Join Multicast group with source filter */
+ if( setsockopt( i_handle, IPPROTO_IP, IP_ADD_SOURCE_MEMBERSHIP,
+ (char*)&imr,
+ sizeof(struct ip_mreq_source) ) == -1 )
+ {
+ msg_Err( p_this, "failed to join IP multicast group (%s)",
+ strerror(errno) );
+ msg_Err( p_this, "are you sure your OS supports IGMPv3?" );
+ close( i_handle );
+ return 0;
+ }
+ }
+ /* If there is no source address, we use IP_ADD_MEMBERSHIP */
+ else
+ {
+ struct ip_mreq imr;
+
+ imr.imr_interface.s_addr = INADDR_ANY;
+ imr.imr_multiaddr.s_addr = sock.sin_addr.s_addr;
+ if( psz_if_addr != NULL && *psz_if_addr
+ && inet_addr(psz_if_addr) != INADDR_NONE )
+ {
+ imr.imr_interface.s_addr = inet_addr(psz_if_addr);
+ }
+#if defined (WIN32) || defined (UNDER_CE)
+ else
+ {
+ typedef DWORD (CALLBACK * GETBESTINTERFACE) ( IPAddr, PDWORD );
+ typedef DWORD (CALLBACK * GETIPADDRTABLE) ( PMIB_IPADDRTABLE, PULONG, BOOL );
+
+ GETBESTINTERFACE OurGetBestInterface;
+ GETIPADDRTABLE OurGetIpAddrTable;
+ HINSTANCE hiphlpapi = LoadLibrary(_T("Iphlpapi.dll"));
+ DWORD i_index;
+
+ if( hiphlpapi )
+ {
+ OurGetBestInterface =
+ (void *)GetProcAddress( hiphlpapi,
+ _T("GetBestInterface") );
+ OurGetIpAddrTable =
+ (void *)GetProcAddress( hiphlpapi,
+ _T("GetIpAddrTable") );
+ }
+
+ if( hiphlpapi && OurGetBestInterface && OurGetIpAddrTable &&
+ OurGetBestInterface( sock.sin_addr.s_addr,
+ &i_index ) == NO_ERROR )
+ {
+ PMIB_IPADDRTABLE p_table;
+ DWORD i = 0;
+
+ msg_Dbg( p_this, "Winsock best interface is %lu",
+ (unsigned long)i_index );
+ OurGetIpAddrTable( NULL, &i, 0 );
+
+ p_table = (PMIB_IPADDRTABLE)malloc( i );
+ if( p_table != NULL )
+ {
+ if( OurGetIpAddrTable( p_table, &i, 0 ) == NO_ERROR )
+ {
+ for( i = 0; i < p_table->dwNumEntries; i-- )
+ {
+ if( p_table->table[i].dwIndex == i_index )
+ {
+ imr.imr_interface.s_addr =
+ p_table->table[i].dwAddr;
+ msg_Dbg( p_this, "using interface 0x%08x",
+ p_table->table[i].dwAddr );
+ }
+ }
+ }
+ else msg_Warn( p_this, "GetIpAddrTable failed" );
+ free( p_table );
+ }
+ }
+ else msg_Dbg( p_this, "GetBestInterface failed" );
+
+ if( hiphlpapi ) FreeLibrary( hiphlpapi );
+ }