1 /*****************************************************************************
3 *****************************************************************************
4 * Copyright (C) 2004-2005 VideoLAN
7 * Authors: Laurent Aimar <fenrir@videolan.org>
8 * RĂ©mi Denis-Courmont <rem # videolan.org>
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
23 *****************************************************************************/
25 /*****************************************************************************
27 *****************************************************************************/
37 #ifdef HAVE_SYS_TIME_H
38 # include <sys/time.h>
41 #if defined( WIN32 ) || defined( UNDER_CE )
42 # if defined(UNDER_CE) && defined(sockaddr_storage)
43 # undef sockaddr_storage
45 # include <winsock2.h>
46 # include <ws2tcpip.h>
48 # include <sys/socket.h>
49 # include <netinet/in.h>
50 # ifdef HAVE_ARPA_INET_H
51 # include <arpa/inet.h>
63 # define INADDR_ANY 0x00000000
66 # define INADDR_NONE 0xFFFFFFFF
69 # define PF_INET AF_INET
72 static int SocksNegociate( vlc_object_t *, int fd, int i_socks_version,
73 char *psz_socks_user, char *psz_socks_passwd );
74 static int SocksHandshakeTCP( vlc_object_t *,
75 int fd, int i_socks_version,
76 char *psz_socks_user, char *psz_socks_passwd,
77 const char *psz_host, int i_port );
79 /*****************************************************************************
81 *****************************************************************************
82 * Open a TCP connection and return a handle
83 *****************************************************************************/
84 int __net_OpenTCP( vlc_object_t *p_this, const char *psz_host, int i_port )
86 struct addrinfo hints, *res, *ptr;
87 const char *psz_realhost;
88 char *psz_realport, *psz_socks;
89 int i_val, i_handle = -1;
91 if( ( i_port < 0 ) || ( i_port > 65535 ) )
92 return -1; /* I don't expect the next TCP version shortly */
94 i_port = 80; /* historical VLC thing */
96 memset( &hints, 0, sizeof( hints ) );
97 hints.ai_socktype = SOCK_STREAM;
99 psz_socks = var_CreateGetString( p_this, "socks" );
100 if( *psz_socks && *psz_socks != ':' )
102 char *psz = strchr( psz_socks, ':' );
107 psz_realhost = psz_socks;
108 psz_realport = strdup( ( psz != NULL ) ? psz : "1080" );
110 msg_Dbg( p_this, "net: connecting to '%s:%s' for '%s:%d'",
111 psz_realhost, psz_realport, psz_host, i_port );
115 psz_realhost = psz_host;
116 psz_realport = malloc( 6 );
117 if( psz_realport == NULL )
123 sprintf( psz_realport, "%d", i_port );
124 msg_Dbg( p_this, "net: connecting to '%s:%s'", psz_realhost,
128 i_val = vlc_getaddrinfo( p_this, psz_realhost, psz_realport, &hints,
130 free( psz_realport );
133 msg_Err( p_this, "cannot resolve '%s' : %s", psz_realhost,
134 vlc_gai_strerror( i_val ) );
139 for( ptr = res; (ptr != NULL) && (i_handle == -1); ptr = ptr->ai_next )
143 fd = socket( ptr->ai_family, ptr->ai_socktype, ptr->ai_protocol );
146 #if defined(WIN32) || defined(UNDER_CE)
147 msg_Warn( p_this, "cannot create socket (%i)",
150 msg_Warn( p_this, "cannot create socket (%s)",
157 /* Set to non-blocking */
158 #if defined( WIN32 ) || defined( UNDER_CE )
160 unsigned long i_dummy = 1;
161 if( ioctlsocket( fd, FIONBIO, &i_dummy ) != 0 )
162 msg_Err( p_this, "cannot set socket to non-blocking mode" );
165 # ifdef IPV6_PROTECTION_LEVEL
166 if( ptr->ai_family == PF_INET6 )
168 i_val = PROTECTION_LEVEL_UNRESTRICTED;
169 setsockopt( fd, IPPROTO_IPV6, IPV6_PROTECTION_LEVEL, &i_val,
173 # warning You are using outdated headers for Winsock !
176 if( ( ( i_val = fcntl( fd, F_GETFL, 0 ) ) < 0 ) ||
177 ( fcntl( fd, F_SETFL, i_val | O_NONBLOCK ) < 0 ) )
178 msg_Err( p_this, "cannot set socket to non-blocking mode (%s)",
183 setsockopt( fd, SOL_SOCKET, SO_REUSEADDR, (void *)&i_val,
186 if( connect( fd, ptr->ai_addr, ptr->ai_addrlen ) )
188 int i_val_size = sizeof( i_val ), i_max_count;
193 #if defined( WIN32 ) || defined( UNDER_CE )
194 if( WSAGetLastError() != WSAEWOULDBLOCK )
196 msg_Warn( p_this, "connection to %s:%d failed (%d)", psz_host,
197 i_port, WSAGetLastError( ) );
202 if( errno != EINPROGRESS )
204 msg_Warn( p_this, "connection to %s:%d : %s", psz_host,
205 i_port, strerror( errno ) );
211 var_Create( p_this, "ipv4-timeout",
212 VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
213 var_Get( p_this, "ipv4-timeout", &timeout );
214 i_max_count = timeout.i_int / 100;
216 msg_Dbg( p_this, "connection in progress" );
221 msg_Dbg( p_this, "connection aborted" );
223 vlc_freeaddrinfo( res );
227 if( i_max_count <= 0 )
229 msg_Dbg( p_this, "connection timed out" );
236 /* Initialize file descriptor set */
240 /* We'll wait 0.1 second if nothing happens */
244 i_val = select( fd + 1, NULL, &fds, NULL, &tv );
246 while( ( i_val == 0 ) || ( ( i_val < 0 ) &&
247 #if defined( WIN32 ) || defined( UNDER_CE )
248 ( WSAGetLastError() == WSAEWOULDBLOCK )
256 msg_Warn( p_this, "connection aborted (select failed)" );
261 #if !defined( SYS_BEOS ) && !defined( UNDER_CE )
262 if( getsockopt( fd, SOL_SOCKET, SO_ERROR, (void*)&i_val,
263 &i_val_size ) == -1 || i_val != 0 )
266 msg_Warn( p_this, "connection to %s:%d failed (%d)", psz_host,
267 i_port, WSAGetLastError( ) );
269 msg_Warn( p_this, "connection to %s:%d : %s", psz_host,
270 i_port, strerror( i_val ) );
277 i_handle = fd; /* success! */
280 vlc_freeaddrinfo( res );
282 if( *psz_socks && *psz_socks != ':' )
284 char *psz_user = var_CreateGetString( p_this, "socks-user" );
285 char *psz_pwd = var_CreateGetString( p_this, "socks-pwd" );
287 if( SocksHandshakeTCP( p_this, i_handle, 5, psz_user, psz_pwd,
290 msg_Err( p_this, "failed to use the SOCKS server" );
291 net_Close( i_handle );
304 /*****************************************************************************
306 *****************************************************************************
307 * Open TCP passive "listening" socket(s)
308 * This function returns NULL in case of error.
309 *****************************************************************************/
310 int *__net_ListenTCP( vlc_object_t *p_this, const char *psz_host, int i_port )
312 struct addrinfo hints, *res, *ptr;
313 int i_val, *pi_handles, i_size;
316 if( ( i_port < 0 ) || ( i_port > 65535 ) )
317 return NULL; /* I don't expect the next TCP version shortly */
319 i_port = 80; /* historical VLC thing */
321 memset( &hints, 0, sizeof( hints ) );
322 hints.ai_socktype = SOCK_STREAM;
323 hints.ai_flags = AI_PASSIVE;
325 psz_port = malloc( 6 );
326 if( psz_port == NULL )
329 sprintf( psz_port, "%d", i_port );
330 msg_Dbg( p_this, "net: listening to '%s:%s'", psz_host, psz_port );
332 i_val = vlc_getaddrinfo( p_this, psz_host, psz_port, &hints, &res );
336 msg_Err( p_this, "cannot resolve '%s' : %s", psz_host,
337 vlc_gai_strerror( i_val ) );
344 for( ptr = res; ptr != NULL; ptr = ptr->ai_next )
348 fd = socket( ptr->ai_family, ptr->ai_socktype, ptr->ai_protocol );
351 #if defined(WIN32) || defined(UNDER_CE)
352 msg_Warn( p_this, "cannot create socket (%i)",
355 msg_Warn( p_this, "cannot create socket (%s)",
361 /* Set to non-blocking */
362 #if defined( WIN32 ) || defined( UNDER_CE )
364 unsigned long i_dummy = 1;
365 if( ioctlsocket( fd, FIONBIO, &i_dummy ) != 0 )
366 msg_Err( p_this, "cannot set socket to non-blocking mode" );
369 if( ( ( i_val = fcntl( fd, F_GETFL, 0 ) ) < 0 ) ||
370 ( fcntl( fd, F_SETFL, i_val | O_NONBLOCK ) < 0 ) )
371 msg_Err( p_this, "cannot set socket to non-blocking mode (%s)",
376 setsockopt( fd, SOL_SOCKET, SO_REUSEADDR, (void *)&i_val,
379 /* Bind the socket */
380 if( bind( fd, ptr->ai_addr, ptr->ai_addrlen ) )
382 #if defined(WIN32) || defined(UNDER_CE)
383 msg_Warn( p_this, "cannot bind socket (%i)", WSAGetLastError( ) );
385 msg_Warn( p_this, "cannot bind socket (%s)", strerror( errno ) );
392 if( listen( fd, 100 ) == -1 )
394 #if defined(WIN32) || defined(UNDER_CE)
395 msg_Err( p_this, "cannot bring socket in listening mode (%i)",
398 msg_Err( p_this, "cannot bring the socket in listening mode (%s)",
405 newpi = (int *)realloc( pi_handles, (++i_size) * sizeof( int ) );
413 newpi[i_size - 2] = fd;
418 vlc_freeaddrinfo( res );
420 if( pi_handles != NULL )
421 pi_handles[i_size - 1] = -1;
425 /*****************************************************************************
427 *****************************************************************************
428 * Accept a connection on a set of listening sockets and return it
429 *****************************************************************************/
430 int __net_Accept( vlc_object_t *p_this, int *pi_fd, mtime_t i_wait )
432 vlc_bool_t b_die = p_this->b_die, b_block = (i_wait < 0);
434 while( p_this->b_die == b_die )
436 int i_val = -1, *pi, *pi_end;
437 struct timeval timeout;
442 /* Initialize file descriptor set */
446 for( pi = pi_fd; *pi != -1; pi++ )
453 FD_SET( i_fd, &fds_r );
454 FD_SET( i_fd, &fds_e );
459 timeout.tv_usec = b_block ? 500000 : i_wait;
461 i_val = select( i_val + 1, &fds_r, NULL, &fds_e, &timeout );
462 if( ( ( i_val < 0 ) && ( errno == EINTR ) ) || i_val == 0 )
471 #if defined(WIN32) || defined(UNDER_CE)
472 msg_Err( p_this, "network select error (%i)", WSAGetLastError() );
474 msg_Err( p_this, "network select error (%s)", strerror( errno ) );
479 for( pi = pi_fd; *pi != -1; pi++ )
483 if( !FD_ISSET( i_fd, &fds_r ) && !FD_ISSET( i_fd, &fds_e ) )
486 i_val = accept( i_fd, NULL, 0 );
489 #if defined(WIN32) || defined(UNDER_CE)
490 msg_Err( p_this, "accept failed (%i)", WSAGetLastError() );
492 msg_Err( p_this, "accept failed (%s)", strerror( errno ) );
498 * This round-robin trick ensures that the first sockets in
499 * pi_fd won't prevent the last ones from getting accept'ed.
502 memmove( pi, pi + 1, pi_end - pi );
512 /*****************************************************************************
514 *****************************************************************************
515 * Open a UDP connection and return a handle
516 *****************************************************************************/
517 int __net_OpenUDP( vlc_object_t *p_this, char *psz_bind, int i_bind,
518 char *psz_server, int i_server )
523 char *psz_network = "";
524 network_socket_t sock;
528 /* Check if we have force ipv4 or ipv6 */
529 var_Create( p_this, "ipv4", VLC_VAR_BOOL | VLC_VAR_DOINHERIT );
530 var_Get( p_this, "ipv4", &val );
533 psz_network = "ipv4";
536 var_Create( p_this, "ipv6", VLC_VAR_BOOL | VLC_VAR_DOINHERIT );
537 var_Get( p_this, "ipv6", &val );
540 psz_network = "ipv6";
542 if( psz_server == NULL ) psz_server = "";
543 if( psz_bind == NULL ) psz_bind = "";
545 /* Prepare the network_socket_t structure */
546 sock.psz_bind_addr = psz_bind;
547 sock.i_bind_port = i_bind;
548 sock.psz_server_addr = psz_server;
549 sock.i_server_port = i_server;
552 msg_Dbg( p_this, "net: connecting to '%s:%d@%s:%d'",
553 psz_server, i_server, psz_bind, i_bind );
554 private = p_this->p_private;
555 p_this->p_private = (void*)&sock;
556 if( !( p_network = module_Need( p_this, "network", psz_network, 0 ) ) )
558 msg_Dbg( p_this, "net: connection to '%s:%d@%s:%d' failed",
559 psz_server, i_server, psz_bind, i_bind );
562 module_Unneed( p_this, p_network );
563 p_this->p_private = private;
565 return sock.i_handle;
568 /*****************************************************************************
570 *****************************************************************************
571 * Close a network handle
572 *****************************************************************************/
573 void net_Close( int fd )
576 CloseHandle( (HANDLE)fd );
577 #elif defined( WIN32 )
584 void net_ListenClose( int *pi_fd )
590 for( pi = pi_fd; *pi != -1; pi++ )
596 /*****************************************************************************
598 *****************************************************************************
599 * Read from a network socket
600 * If b_rety is true, then we repeat until we have read the right amount of
602 *****************************************************************************/
603 int __net_Read( vlc_object_t *p_this, int fd, v_socket_t *p_vs,
604 uint8_t *p_data, int i_data, vlc_bool_t b_retry )
606 struct timeval timeout;
611 vlc_bool_t b_die = p_this->b_die;
617 if( p_this->b_die != b_die )
622 /* Initialize file descriptor set */
624 FD_SET( fd, &fds_r );
626 FD_SET( fd, &fds_e );
628 /* We'll wait 0.5 second if nothing happens */
630 timeout.tv_usec = 500000;
632 } while( (i_ret = select(fd + 1, &fds_r, NULL, &fds_e, &timeout)) == 0
633 || ( i_ret < 0 && errno == EINTR ) );
637 #if defined(WIN32) || defined(UNDER_CE)
638 msg_Err( p_this, "network select error" );
640 msg_Err( p_this, "network select error (%s)", strerror(errno) );
642 return i_total > 0 ? i_total : -1;
645 if( ( i_recv = (p_vs != NULL)
646 ? p_vs->pf_recv( p_vs->p_sys, p_data, i_data )
647 : recv( fd, p_data, i_data, 0 ) ) < 0 )
649 #if defined(WIN32) || defined(UNDER_CE)
650 if( WSAGetLastError() == WSAEWOULDBLOCK )
652 /* only happens with p_vs (SSL) - not really an error */
656 /* On win32 recv() will fail if the datagram doesn't fit inside
657 * the passed buffer, even though the buffer will be filled with
658 * the first part of the datagram. */
659 if( WSAGetLastError() == WSAEMSGSIZE )
661 msg_Err( p_this, "recv() failed. "
662 "Increase the mtu size (--mtu option)" );
665 else if( WSAGetLastError() == WSAEINTR ) continue;
666 else msg_Err( p_this, "recv failed (%i)", WSAGetLastError() );
668 /* EAGAIN only happens with p_vs (SSL) and it's not an error */
669 if( errno != EAGAIN )
670 msg_Err( p_this, "recv failed (%s)", strerror(errno) );
672 return i_total > 0 ? i_total : -1;
674 else if( i_recv == 0 )
676 /* Connection closed */
691 /*****************************************************************************
692 * __net_ReadNonBlock:
693 *****************************************************************************
694 * Read from a network socket, non blocking mode (with timeout)
695 *****************************************************************************/
696 int __net_ReadNonBlock( vlc_object_t *p_this, int fd, v_socket_t *p_vs,
697 uint8_t *p_data, int i_data, mtime_t i_wait)
699 struct timeval timeout;
704 /* Initialize file descriptor set */
706 FD_SET( fd, &fds_r );
708 FD_SET( fd, &fds_e );
711 timeout.tv_usec = i_wait;
713 i_ret = select(fd + 1, &fds_r, NULL, &fds_e, &timeout);
715 if( i_ret < 0 && errno == EINTR )
721 #if defined(WIN32) || defined(UNDER_CE)
722 msg_Err( p_this, "network select error" );
724 msg_Err( p_this, "network select error (%s)", strerror(errno) );
734 #if !defined(UNDER_CE)
735 if( fd == 0/*STDIN_FILENO*/ ) i_recv = read( fd, p_data, i_data ); else
737 if( ( i_recv = (p_vs != NULL)
738 ? p_vs->pf_recv( p_vs->p_sys, p_data, i_data )
739 : recv( fd, p_data, i_data, 0 ) ) <= 0 )
741 #if defined(WIN32) || defined(UNDER_CE)
743 /* On win32 recv() will fail if the datagram doesn't fit inside
744 * the passed buffer, even though the buffer will be filled with
745 * the first part of the datagram. */
746 if( WSAGetLastError() == WSAEMSGSIZE )
748 msg_Err( p_this, "recv() failed. "
749 "Increase the mtu size (--mtu option)" );
751 else msg_Err( p_this, "recv failed (%i)", WSAGetLastError() );
753 msg_Err( p_this, "recv failed (%s)", strerror(errno) );
758 return i_recv ? i_recv : -1; /* !i_recv -> connection closed if tcp */
761 /* We will never be here */
765 /*****************************************************************************
767 *****************************************************************************
768 * Read from several sockets (with timeout). Takes data from the first socket
770 *****************************************************************************/
771 int __net_Select( vlc_object_t *p_this, int *pi_fd, v_socket_t **pp_vs,
772 int i_fd, uint8_t *p_data, int i_data, mtime_t i_wait )
774 struct timeval timeout;
781 /* Initialize file descriptor set */
785 for( i = 0 ; i < i_fd ; i++)
787 if( pi_fd[i] > i_max_fd ) i_max_fd = pi_fd[i];
788 FD_SET( pi_fd[i], &fds_r );
789 FD_SET( pi_fd[i], &fds_e );
793 timeout.tv_usec = i_wait;
795 i_ret = select( i_max_fd + 1, &fds_r, NULL, &fds_e, &timeout );
797 if( i_ret < 0 && errno == EINTR )
803 msg_Err( p_this, "network select error (%s)", strerror(errno) );
806 else if( i_ret == 0 )
812 for( i = 0 ; i < i_fd ; i++)
814 if( FD_ISSET( pi_fd[i], &fds_r ) )
816 i_recv = ((pp_vs != NULL) && (pp_vs[i] != NULL))
817 ? pp_vs[i]->pf_recv( pp_vs[i]->p_sys, p_data, i_data )
818 : recv( pi_fd[i], p_data, i_data, 0 );
823 /* On win32 recv() will fail if the datagram doesn't
824 * fit inside the passed buffer, even though the buffer
825 * will be filled with the first part of the datagram. */
826 if( WSAGetLastError() == WSAEMSGSIZE )
828 msg_Err( p_this, "recv() failed. "
829 "Increase the mtu size (--mtu option)" );
831 else msg_Err( p_this, "recv failed (%i)",
834 msg_Err( p_this, "recv failed (%s)", strerror(errno) );
844 /* We will never be here */
849 /* Write exact amount requested */
850 int __net_Write( vlc_object_t *p_this, int fd, v_socket_t *p_vs,
851 uint8_t *p_data, int i_data )
853 struct timeval timeout;
859 vlc_bool_t b_die = p_this->b_die;
865 if( p_this->b_die != b_die )
870 /* Initialize file descriptor set */
872 FD_SET( fd, &fds_w );
874 FD_SET( fd, &fds_e );
876 /* We'll wait 0.5 second if nothing happens */
878 timeout.tv_usec = 500000;
880 } while( (i_ret = select(fd + 1, NULL, &fds_w, &fds_e, &timeout)) == 0
881 || ( i_ret < 0 && errno == EINTR ) );
885 #if defined(WIN32) || defined(UNDER_CE)
886 msg_Err( p_this, "network select error" );
888 msg_Err( p_this, "network select error (%s)", strerror(errno) );
890 return i_total > 0 ? i_total : -1;
893 if( ( i_send = (p_vs != NULL)
894 ? p_vs->pf_send( p_vs->p_sys, p_data, i_data )
895 : send( fd, p_data, i_data, 0 ) ) < 0 )
897 /* XXX With udp for example, it will issue a message if the host
899 /* msg_Err( p_this, "send failed (%s)", strerror(errno) ); */
900 return i_total > 0 ? i_total : -1;
910 char *__net_Gets( vlc_object_t *p_this, int fd, v_socket_t *p_vs )
912 char *psz_line = malloc( 1024 );
919 if( net_Read( p_this, fd, p_vs, &psz_line[i_line], 1, VLC_TRUE ) != 1 )
921 psz_line[i_line] = '\0';
926 if( psz_line[i_line-1] == '\n' )
928 psz_line[i_line] = '\0';
932 if( i_line >= i_max - 1 )
935 psz_line = realloc( psz_line, i_max );
945 while( i_line >= 1 &&
946 ( psz_line[i_line-1] == '\n' || psz_line[i_line-1] == '\r' ) )
949 psz_line[i_line] = '\0';
954 int net_Printf( vlc_object_t *p_this, int fd, v_socket_t *p_vs,
955 const char *psz_fmt, ... )
959 va_start( args, psz_fmt );
960 i_ret = net_vaPrintf( p_this, fd, p_vs, psz_fmt, args );
966 int __net_vaPrintf( vlc_object_t *p_this, int fd, v_socket_t *p_vs,
967 const char *psz_fmt, va_list args )
972 vasprintf( &psz, psz_fmt, args );
973 i_size = strlen( psz );
974 i_ret = __net_Write( p_this, fd, p_vs, psz, i_size ) < i_size ? -1 : i_size;
982 /*****************************************************************************
984 *****************************************************************************
985 * Negociate authentication with a SOCKS server.
986 *****************************************************************************/
987 static int SocksNegociate( vlc_object_t *p_obj,
988 int fd, int i_socks_version,
989 char *psz_socks_user,
990 char *psz_socks_passwd )
992 uint8_t buffer[128+2*256];
994 vlc_bool_t b_auth = VLC_FALSE;
996 if( i_socks_version != 5 )
999 /* We negociate authentication */
1001 if( psz_socks_user && psz_socks_passwd &&
1002 *psz_socks_user && *psz_socks_passwd )
1005 buffer[0] = i_socks_version; /* SOCKS version */
1008 buffer[1] = 2; /* Number of methods */
1009 buffer[2] = 0x00; /* - No auth required */
1010 buffer[3] = 0x02; /* - USer/Password */
1015 buffer[1] = 1; /* Number of methods */
1016 buffer[2] = 0x00; /* - No auth required */
1020 if( net_Write( p_obj, fd, NULL, buffer, i_len ) != i_len )
1021 return VLC_EGENERIC;
1022 if( net_Read( p_obj, fd, NULL, buffer, 2, VLC_TRUE ) != 2 )
1023 return VLC_EGENERIC;
1025 msg_Dbg( p_obj, "socks: v=%d method=%x", buffer[0], buffer[1] );
1027 if( buffer[1] == 0x00 )
1029 msg_Dbg( p_obj, "socks: no authentication required" );
1031 else if( buffer[1] == 0x02 )
1033 int i_len1 = __MIN( strlen(psz_socks_user), 255 );
1034 int i_len2 = __MIN( strlen(psz_socks_passwd), 255 );
1035 msg_Dbg( p_obj, "socks: username/password authentication" );
1037 /* XXX: we don't support user/pwd > 255 (truncated)*/
1038 buffer[0] = i_socks_version; /* Version */
1039 buffer[1] = i_len1; /* User length */
1040 memcpy( &buffer[2], psz_socks_user, i_len1 );
1041 buffer[2+i_len1] = i_len2; /* Password length */
1042 memcpy( &buffer[2+i_len1+1], psz_socks_passwd, i_len2 );
1044 i_len = 3 + i_len1 + i_len2;
1046 if( net_Write( p_obj, fd, NULL, buffer, i_len ) != i_len )
1047 return VLC_EGENERIC;
1049 if( net_Read( p_obj, fd, NULL, buffer, 2, VLC_TRUE ) != 2 )
1050 return VLC_EGENERIC;
1052 msg_Dbg( p_obj, "socks: v=%d status=%x", buffer[0], buffer[1] );
1053 if( buffer[1] != 0x00 )
1055 msg_Err( p_obj, "socks: authentication rejected" );
1056 return VLC_EGENERIC;
1062 msg_Err( p_obj, "socks: unsupported authentication method %x",
1065 msg_Err( p_obj, "socks: authentification needed" );
1066 return VLC_EGENERIC;
1072 /*****************************************************************************
1073 * SocksHandshakeTCP:
1074 *****************************************************************************
1075 * Open a TCP connection using a SOCKS server and return a handle (RFC 1928)
1076 *****************************************************************************/
1077 static int SocksHandshakeTCP( vlc_object_t *p_obj,
1079 int i_socks_version,
1080 char *psz_socks_user, char *psz_socks_passwd,
1081 const char *psz_host, int i_port )
1083 uint8_t buffer[128+2*256];
1085 if( i_socks_version != 4 && i_socks_version != 5 )
1087 msg_Warn( p_obj, "invalid socks protocol version %d", i_socks_version );
1088 i_socks_version = 5;
1091 if( i_socks_version == 5 &&
1092 SocksNegociate( p_obj, fd, i_socks_version,
1093 psz_socks_user, psz_socks_passwd ) )
1094 return VLC_EGENERIC;
1096 if( i_socks_version == 4 )
1098 struct addrinfo hints = { 0 }, *p_res;
1100 /* v4 only support ipv4 */
1101 hints.ai_family = PF_INET;
1102 if( vlc_getaddrinfo( p_obj, psz_host, NULL, &hints, &p_res ) )
1103 return VLC_EGENERIC;
1105 buffer[0] = i_socks_version;
1106 buffer[1] = 0x01; /* CONNECT */
1107 SetWBE( &buffer[2], i_port ); /* Port */
1108 memcpy( &buffer[4], /* Address */
1109 &((struct sockaddr_in *)(p_res->ai_addr))->sin_addr, 4 );
1110 vlc_freeaddrinfo( p_res );
1112 buffer[8] = 0; /* Empty user id */
1114 if( net_Write( p_obj, fd, NULL, buffer, 9 ) != 9 )
1115 return VLC_EGENERIC;
1116 if( net_Read( p_obj, fd, NULL, buffer, 8, VLC_TRUE ) != 8 )
1117 return VLC_EGENERIC;
1119 msg_Dbg( p_obj, "socks: v=%d cd=%d",
1120 buffer[0], buffer[1] );
1122 if( buffer[1] != 90 )
1123 return VLC_EGENERIC;
1125 else if( i_socks_version == 5 )
1127 int i_hlen = __MIN(strlen( psz_host ), 255);
1130 buffer[0] = i_socks_version; /* Version */
1131 buffer[1] = 0x01; /* Cmd: connect */
1132 buffer[2] = 0x00; /* Reserved */
1133 buffer[3] = 3; /* ATYP: for now domainname */
1136 memcpy( &buffer[5], psz_host, i_hlen );
1137 SetWBE( &buffer[5+i_hlen], i_port );
1139 i_len = 5 + i_hlen + 2;
1142 if( net_Write( p_obj, fd, NULL, buffer, i_len ) != i_len )
1143 return VLC_EGENERIC;
1145 /* Read the header */
1146 if( net_Read( p_obj, fd, NULL, buffer, 5, VLC_TRUE ) != 5 )
1147 return VLC_EGENERIC;
1149 msg_Dbg( p_obj, "socks: v=%d rep=%d atyp=%d",
1150 buffer[0], buffer[1], buffer[3] );
1152 if( buffer[1] != 0x00 )
1154 msg_Err( p_obj, "socks: CONNECT request failed\n" );
1155 return VLC_EGENERIC;
1158 /* Read the remaining bytes */
1159 if( buffer[3] == 0x01 )
1161 else if( buffer[3] == 0x03 )
1162 i_len = buffer[4] + 2;
1163 else if( buffer[3] == 0x04 )
1166 return VLC_EGENERIC;
1168 if( net_Read( p_obj, fd, NULL, buffer, i_len, VLC_TRUE ) != i_len )
1169 return VLC_EGENERIC;
1175 /*****************************************************************************
1177 *****************************************************************************
1178 * Check that a given IP is within a set of IP/netmask.
1179 *****************************************************************************/
1180 int __net_CheckIP( vlc_object_t *p_this, char *psz_ip, char **ppsz_hosts,
1186 if( !inet_aton( psz_ip, &ip ) )
1188 return VLC_EGENERIC;
1191 for( i = 0; i < i_hosts; i++ )
1193 struct in_addr base, mask;
1194 char *psz_host = strdup( ppsz_hosts[i] );
1195 char *p = strchr( psz_host, '/' );
1202 if( i_mask < 0 || i_mask > 32 )
1204 msg_Err( p_this, "invalid netmask %s", p );
1205 mask.s_addr = INADDR_NONE;
1207 else if( i_mask == 0 )
1208 mask.s_addr = INADDR_ANY;
1210 mask.s_addr = htons( ntohs(INADDR_NONE) << (32 - i_mask) );
1213 mask.s_addr = INADDR_NONE;
1215 if( !inet_aton( psz_host, &base ) )
1217 msg_Err( p_this, "invalid base address %s", psz_host );
1223 if( !((ip.s_addr ^ base.s_addr) & mask.s_addr) )