X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=plugins%2Fnetwork%2Fipv6.c;h=03d1429ae4967cd4ab8be811c5210603d24543d4;hb=976dfc3eb46069ea3b920dec899e0c13ccf17c96;hp=6a337240d538ec610722fdda250a99a092696e81;hpb=e81cf378bece2349ad5b3d92bf6aba9efbadad6d;p=vlc diff --git a/plugins/network/ipv6.c b/plugins/network/ipv6.c index 6a337240d5..03d1429ae4 100644 --- a/plugins/network/ipv6.c +++ b/plugins/network/ipv6.c @@ -2,10 +2,11 @@ * ipv6.c: IPv6 network abstraction layer ***************************************************************************** * Copyright (C) 2002 VideoLAN - * $Id: ipv6.c,v 1.4 2002/04/18 04:34:37 sam Exp $ + * $Id: ipv6.c,v 1.16 2002/07/31 20:56:52 sam Exp $ * * Authors: Alexis Guillard * Christophe Massiot + * Remco Poortinga * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -27,12 +28,12 @@ *****************************************************************************/ #include #include -#include #include #include #include #include -#include + +#include #ifdef HAVE_UNISTD_H # include @@ -47,6 +48,7 @@ # include /* hostent ... */ # include # include +# include # ifdef HAVE_ARPA_INET_H # include /* inet_ntoa(), inet_aton() */ # endif @@ -54,45 +56,30 @@ #include "network.h" -/* Default MTU used for UDP socket. FIXME: we should issue some ioctl() - * call to get that value from the interface driver. */ -#define DEFAULT_MTU 1500 +#if defined(WIN32) +static const struct in6_addr in6addr_any = {{IN6ADDR_ANY_INIT}}; +/* the following will have to be removed when w32api defines them */ +#ifndef IPPROTO_IPV6 +# define IPPROTO_IPV6 41 +#endif +#ifndef IPV6_JOIN_GROUP +# define IPV6_JOIN_GROUP 20 +#endif +#endif /***************************************************************************** * Local prototypes *****************************************************************************/ -static void getfunctions( function_list_t * ); -static int NetworkOpen( struct network_socket_s * ); +static int Open( vlc_object_t * ); /***************************************************************************** - * Build configuration tree. + * Module descriptor *****************************************************************************/ -MODULE_CONFIG_START -MODULE_CONFIG_STOP - -MODULE_INIT_START - SET_DESCRIPTION( "IPv6 network abstraction layer" ) - ADD_CAPABILITY( NETWORK, 40 ) - ADD_SHORTCUT( "ipv6" ) -MODULE_INIT_STOP - -MODULE_ACTIVATE_START - getfunctions( &p_module->p_functions->network ); -MODULE_ACTIVATE_STOP - -MODULE_DEACTIVATE_START -MODULE_DEACTIVATE_STOP - -/***************************************************************************** - * Functions exported as capabilities. They are declared as static so that - * we don't pollute the namespace too much. - *****************************************************************************/ -static void getfunctions( function_list_t * p_function_list ) -{ -#define f p_function_list->functions.network - f.pf_open = NetworkOpen; -#undef f -} +vlc_module_begin(); + set_description( _("IPv6 network abstraction layer") ); + set_capability( "network", 40 ); + set_callbacks( Open, NULL ); +vlc_module_end(); /***************************************************************************** * BuildAddr: utility function to build a struct sockaddr_in6 @@ -100,9 +87,39 @@ static void getfunctions( function_list_t * p_function_list ) static int BuildAddr( struct sockaddr_in6 * p_socket, char * psz_address, int i_port ) { + char * psz_multicast_interface = ""; + +#if defined(WIN32) + /* Try to get getaddrinfo() and freeaddrinfo() from wship6.dll */ + typedef int (CALLBACK * GETADDRINFO) ( const char *nodename, + const char *servname, + const struct addrinfo *hints, + struct addrinfo **res ); + typedef void (CALLBACK * FREEADDRINFO) ( struct addrinfo FAR *ai ); + + struct addrinfo hints, *res; + GETADDRINFO _getaddrinfo = NULL; + FREEADDRINFO _freeaddrinfo = NULL; + + HINSTANCE wship6_dll = LoadLibrary("wship6.dll"); + if( wship6_dll ) + { + _getaddrinfo = (GETADDRINFO) GetProcAddress( wship6_dll, + "getaddrinfo" ); + _freeaddrinfo = (FREEADDRINFO) GetProcAddress( wship6_dll, + "freeaddrinfo" ); + } + if( !_getaddrinfo || !_freeaddrinfo ) + { +//X msg_Err( p_this, "no IPv6 stack installed" ); + if( wship6_dll ) FreeLibrary( wship6_dll ); + return( -1 ); + } +#endif + /* Reset struct */ memset( p_socket, 0, sizeof( struct sockaddr_in6 ) ); - p_socket->sin6_family = AF_INET6; /* family */ + p_socket->sin6_family = AF_INET6; /* family */ p_socket->sin6_port = htons( i_port ); if( !*psz_address ) { @@ -112,8 +129,44 @@ static int BuildAddr( struct sockaddr_in6 * p_socket, && psz_address[strlen(psz_address) - 1] == ']' ) { psz_address++; + /* see if there is an interface name in there... */ + if( (psz_multicast_interface = strchr(psz_address, '%')) != NULL ) + { + *psz_multicast_interface = '\0'; + psz_multicast_interface++; +//X msg_Dbg( p_this, "Interface name specified: \"%s\"", +// psz_multicast_interface ); + /* now convert that interface name to an index */ +#if !defined( WIN32 ) + p_socket->sin6_scope_id = if_nametoindex(psz_multicast_interface); +#else + /* FIXME: for now we always use the default interface */ + p_socket->sin6_scope_id = 0; +//X msg_Warn( 3, "Using default interface. This has to be FIXED!"); +#endif +//X msg_Warn( p_this, " = #%i\n", p_socket->sin6_scope_id ); + } psz_address[strlen(psz_address) - 1] = '\0' ; + +#if !defined( WIN32 ) inet_pton(AF_INET6, psz_address, &p_socket->sin6_addr.s6_addr); + +#else + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_INET6; + hints.ai_flags = AI_NUMERICHOST; + + if( _getaddrinfo( psz_address, NULL, &hints, &res ) ) + { + FreeLibrary( wship6_dll ); + return( -1 ); + } + memcpy( &p_socket->sin6_addr, + &((struct sockaddr_in6 *)res->ai_addr)->sin6_addr, + sizeof(struct in6_addr) ); + _freeaddrinfo( res ); + +#endif } else { @@ -123,19 +176,35 @@ static int BuildAddr( struct sockaddr_in6 * p_socket, /* We have a fqdn, try to find its address */ if ( (p_hostent = gethostbyname2( psz_address, AF_INET6 )) == NULL ) { - intf_ErrMsg( "ipv6 error: unknown host %s", psz_address ); +//X intf_ErrMsg( "ipv6 error: unknown host %s", psz_address ); return( -1 ); } /* Copy the first address of the host in the socket address */ memcpy( &p_socket->sin6_addr, p_hostent->h_addr_list[0], p_hostent->h_length ); + +#elif defined(WIN32) + if( _getaddrinfo( psz_address, NULL, &hints, &res ) ) + { + FreeLibrary( wship6_dll ); + return( -1 ); + } + memcpy( &p_socket->sin6_addr, + &((struct sockaddr_in6 *)res->ai_addr)->sin6_addr, + sizeof(struct in6_addr) ); + _freeaddrinfo( res ); + #else - intf_ErrMsg( "ipv6 error: IPv6 address %s is invalid", psz_address ); +//X intf_ErrMsg( "ipv6 error: IPv6 address %s is invalid", psz_address ); return( -1 ); #endif } +#if defined(WIN32) + FreeLibrary( wship6_dll ); +#endif + return( 0 ); } @@ -152,7 +221,7 @@ static int BuildAddr( struct sockaddr_in6 * p_socket, * Its use leads to great confusion and is currently discouraged. * This function returns -1 in case of error. *****************************************************************************/ -static int OpenUDP( network_socket_t * p_socket ) +static int OpenUDP( vlc_object_t * p_this, network_socket_t * p_socket ) { char * psz_bind_addr = p_socket->psz_bind_addr; int i_bind_port = p_socket->i_bind_port; @@ -164,14 +233,14 @@ static int OpenUDP( network_socket_t * p_socket ) if( i_bind_port == 0 ) { - i_bind_port = config_GetIntVariable( "server_port" ); +//X i_bind_port = config_GetInt( "server-port" ); } /* Open a SOCK_DGRAM (UDP) socket, in the AF_INET6 domain, automatic (0) * protocol */ if( (i_handle = socket( AF_INET6, SOCK_DGRAM, 0 )) == -1 ) { - intf_ErrMsg( "ipv6 error: cannot create socket (%s)", strerror(errno) ); + msg_Err( p_this, "cannot create socket (%s)", strerror(errno) ); return( -1 ); } @@ -180,8 +249,8 @@ static int OpenUDP( network_socket_t * p_socket ) if( setsockopt( i_handle, SOL_SOCKET, SO_REUSEADDR, (void *) &i_opt, sizeof( i_opt ) ) == -1 ) { - intf_ErrMsg( "ipv6 error: cannot configure socket (SO_REUSEADDR: %s)", - strerror(errno)); + msg_Err( p_this, "cannot configure socket (SO_REUSEADDR: %s)", + strerror(errno) ); close( i_handle ); return( -1 ); } @@ -192,9 +261,8 @@ static int OpenUDP( network_socket_t * p_socket ) if( setsockopt( i_handle, SOL_SOCKET, SO_RCVBUF, (void *) &i_opt, sizeof( i_opt ) ) == -1 ) { - intf_WarnMsg( 1, - "ipv6 warning: cannot configure socket (SO_RCVBUF: %s)", - strerror(errno)); + msg_Warn( p_this, "cannot configure socket (SO_RCVBUF: %s)", + strerror(errno) ); } /* Check if we really got what we have asked for, because Linux, etc. @@ -205,13 +273,13 @@ static int OpenUDP( network_socket_t * p_socket ) if( getsockopt( i_handle, SOL_SOCKET, SO_RCVBUF, (void*) &i_opt, &i_opt_size ) == -1 ) { - intf_WarnMsg( 1, "ipv6 warning: cannot query socket (SO_RCVBUF: %s)", - strerror(errno)); + msg_Warn( p_this, "cannot query socket (SO_RCVBUF: %s)", + strerror(errno) ); } else if( i_opt < 0x80000 ) { - intf_WarnMsg( 1, "ipv6 warning: socket buffer size is 0x%x" - " instead of 0x%x", i_opt, 0x80000 ); + msg_Warn( p_this, "socket buffer size is 0x%x instead of 0x%x", + i_opt, 0x80000 ); } /* Build the local socket */ @@ -224,7 +292,7 @@ static int OpenUDP( network_socket_t * p_socket ) /* Bind it */ if( bind( i_handle, (struct sockaddr *)&sock, sizeof( sock ) ) < 0 ) { - intf_ErrMsg( "ipv6 error: cannot bind socket (%s)", strerror(errno) ); + msg_Err( p_this, "cannot bind socket (%s)", strerror(errno) ); close( i_handle ); return( -1 ); } @@ -236,21 +304,35 @@ static int OpenUDP( network_socket_t * p_socket ) if( setsockopt( i_handle, SOL_SOCKET, SO_BROADCAST, (void*) &i_opt, sizeof( i_opt ) ) == -1 ) { - intf_WarnMsg( 1, - "ipv6 warning: cannot configure socket (SO_BROADCAST: %s)", - strerror(errno)); + msg_Warn( p_this, "ipv6 warning: cannot configure socket " + "(SO_BROADCAST: %s)", strerror(errno) ); } } /* Join the multicast group if the socket is a multicast address */ - /* FIXME: To be written */ + if( IN6_IS_ADDR_MULTICAST(&sock.sin6_addr) ) + { + struct ipv6_mreq imr; + int res; + + imr.ipv6mr_interface = sock.sin6_scope_id; + imr.ipv6mr_multiaddr = sock.sin6_addr; + res = setsockopt(i_handle, IPPROTO_IPV6, IPV6_JOIN_GROUP, (void*) &imr, + sizeof(imr)); + + if( res == -1 ) + { +//X intf_ErrMsg( "ipv6 error: setsockopt JOIN_GROUP failed" ); + } + } + if( *psz_server_addr ) { /* Build socket for remote connection */ if ( BuildAddr( &sock, psz_server_addr, i_server_port ) == -1 ) { - intf_ErrMsg( "ipv6 error: cannot build remote address" ); + msg_Err( p_this, "cannot build remote address" ); close( i_handle ); return( -1 ); } @@ -259,15 +341,15 @@ static int OpenUDP( network_socket_t * p_socket ) if( connect( i_handle, (struct sockaddr *) &sock, sizeof( sock ) ) == (-1) ) { - intf_ErrMsg( "ipv6 error: cannot connect socket (%s)", - strerror(errno) ); + msg_Err( p_this, "cannot connect socket (%s)", strerror(errno) ); close( i_handle ); return( -1 ); } } p_socket->i_handle = i_handle; - p_socket->i_mtu = DEFAULT_MTU; + p_socket->i_mtu = config_GetInt( p_this, "mtu" ); + return( 0 ); } @@ -279,7 +361,7 @@ static int OpenUDP( network_socket_t * p_socket ) * Other parameters are ignored. * This function returns -1 in case of error. *****************************************************************************/ -static int OpenTCP( network_socket_t * p_socket ) +static int OpenTCP( vlc_object_t * p_this, network_socket_t * p_socket ) { char * psz_server_addr = p_socket->psz_server_addr; int i_server_port = p_socket->i_server_port; @@ -296,7 +378,7 @@ static int OpenTCP( network_socket_t * p_socket ) * protocol */ if( (i_handle = socket( AF_INET6, SOCK_STREAM, 0 )) == -1 ) { - intf_ErrMsg( "ipv6 error: cannot create socket (%s)", strerror(errno) ); + msg_Err( p_this, "cannot create socket (%s)", strerror(errno) ); return( -1 ); } @@ -311,8 +393,7 @@ static int OpenTCP( network_socket_t * p_socket ) if( connect( i_handle, (struct sockaddr *) &sock, sizeof( sock ) ) == (-1) ) { - intf_ErrMsg( "ipv6 error: cannot connect socket (%s)", - strerror(errno) ); + msg_Err( p_this, "cannot connect socket (%s)", strerror(errno) ); close( i_handle ); return( -1 ); } @@ -324,18 +405,18 @@ static int OpenTCP( network_socket_t * p_socket ) } /***************************************************************************** - * NetworkOpen: wrapper around OpenUDP and OpenTCP + * Open: wrapper around OpenUDP and OpenTCP *****************************************************************************/ -static int NetworkOpen( network_socket_t * p_socket ) +static int Open( vlc_object_t * p_this ) { + network_socket_t * p_socket = p_this->p_private; + if( p_socket->i_type == NETWORK_UDP ) { - return OpenUDP( p_socket ); + return OpenUDP( p_this, p_socket ); } else { - return OpenTCP( p_socket ); + return OpenTCP( p_this, p_socket ); } } - -