Commit 429d3006 authored by Rémi Denis-Courmont's avatar Rémi Denis-Courmont

- Fix (?) handling of EPSV non-compliant FTP servers

with EPSV compliant NAT
- Fix socket error value check
parent fe087a38
...@@ -99,61 +99,19 @@ static int ftp_ReadCommand( access_t *, int *, char ** ); ...@@ -99,61 +99,19 @@ static int ftp_ReadCommand( access_t *, int *, char ** );
static int ftp_StartStream( access_t *, int64_t ); static int ftp_StartStream( access_t *, int64_t );
static int ftp_StopStream ( access_t *); static int ftp_StopStream ( access_t *);
/**************************************************************************** static int Connect( access_t *p_access, access_sys_t *p_sys )
* Open: connect to ftp server and ask for file
****************************************************************************/
static int Open( vlc_object_t *p_this )
{ {
access_t *p_access = (access_t*)p_this; int fd, i_answer;
access_sys_t *p_sys;
char *psz; char *psz;
int i_answer;
char *psz_arg;
/* Init p_access */
p_access->pf_read = Read;
p_access->pf_block = NULL;
p_access->pf_seek = Seek;
p_access->pf_control = Control;
p_access->info.i_update = 0;
p_access->info.i_size = 0;
p_access->info.i_pos = 0;
p_access->info.b_eof = VLC_FALSE;
p_access->info.i_title = 0;
p_access->info.i_seekpoint = 0;
p_access->p_sys = p_sys = malloc( sizeof( access_sys_t ) );
memset( p_sys, 0, sizeof( access_sys_t ) );
p_sys->fd_cmd = -1;
p_sys->fd_data = -1;
p_sys->psz_epsv_ip = NULL;
/* *** Parse URL and get server addr/port and path *** */
psz = p_access->psz_path;
while( *psz == '/' )
{
psz++;
}
vlc_UrlParse( &p_sys->url, psz, 0 );
if( p_sys->url.psz_host == NULL || *p_sys->url.psz_host == '\0' )
{
msg_Err( p_access, "invalid server name" );
goto exit_error;
}
if( p_sys->url.i_port <= 0 )
{
p_sys->url.i_port = 21; /* default port */
}
/* *** Open a TCP connection with server *** */ /* *** Open a TCP connection with server *** */
msg_Dbg( p_access, "waiting for connection..." ); msg_Dbg( p_access, "waiting for connection..." );
p_sys->fd_cmd = net_OpenTCP( p_access, p_sys->url.psz_host, p_sys->fd_cmd = fd = net_OpenTCP( p_access, p_sys->url.psz_host,
p_sys->url.i_port ); p_sys->url.i_port );
if( p_sys->fd_cmd < 0 ) if( fd < 0 )
{ {
msg_Err( p_access, "failed to connect with server" ); msg_Err( p_access, "failed to connect with server" );
goto exit_error; return -1;
} }
for( ;; ) for( ;; )
...@@ -166,7 +124,7 @@ static int Open( vlc_object_t *p_this ) ...@@ -166,7 +124,7 @@ static int Open( vlc_object_t *p_this )
if( i_answer / 100 != 2 ) if( i_answer / 100 != 2 )
{ {
msg_Err( p_access, "connection rejected" ); msg_Err( p_access, "connection rejected" );
goto exit_error; return -1;
} }
msg_Dbg( p_access, "connection accepted (%d)", i_answer ); msg_Dbg( p_access, "connection accepted (%d)", i_answer );
...@@ -176,7 +134,7 @@ static int Open( vlc_object_t *p_this ) ...@@ -176,7 +134,7 @@ static int Open( vlc_object_t *p_this )
ftp_ReadCommand( p_access, &i_answer, NULL ) < 0 ) ftp_ReadCommand( p_access, &i_answer, NULL ) < 0 )
{ {
free( psz ); free( psz );
goto exit_error; return -1;
} }
free( psz ); free( psz );
...@@ -192,7 +150,7 @@ static int Open( vlc_object_t *p_this ) ...@@ -192,7 +150,7 @@ static int Open( vlc_object_t *p_this )
ftp_ReadCommand( p_access, &i_answer, NULL ) < 0 ) ftp_ReadCommand( p_access, &i_answer, NULL ) < 0 )
{ {
free( psz ); free( psz );
goto exit_error; return -1;
} }
free( psz ); free( psz );
...@@ -209,34 +167,87 @@ static int Open( vlc_object_t *p_this ) ...@@ -209,34 +167,87 @@ static int Open( vlc_object_t *p_this )
ftp_ReadCommand( p_access, &i_answer, NULL ) < 0 ) ftp_ReadCommand( p_access, &i_answer, NULL ) < 0 )
{ {
free( psz ); free( psz );
goto exit_error; return -1;
} }
free( psz ); free( psz );
if( i_answer / 100 != 2 ) if( i_answer / 100 != 2 )
{ {
msg_Err( p_access, "account rejected" ); msg_Err( p_access, "account rejected" );
goto exit_error; return -1;
} }
msg_Dbg( p_access, "account accepted" ); msg_Dbg( p_access, "account accepted" );
break; break;
default: default:
msg_Err( p_access, "password rejected" ); msg_Err( p_access, "password rejected" );
goto exit_error; return -1;
} }
break; break;
default: default:
msg_Err( p_access, "user rejected" ); msg_Err( p_access, "user rejected" );
goto exit_error; return -1;
} }
/* Extended passive mode */ /* Extended passive mode */
if( ftp_SendCommand( p_access, "EPSV ALL" ) < 0 ) if( ftp_SendCommand( p_access, "EPSV ALL" ) < 0 )
{ {
msg_Err( p_access, "cannot request extended passive mode" ); msg_Err( p_access, "cannot request extended passive mode" );
return -1;
}
return 0;
}
/****************************************************************************
* Open: connect to ftp server and ask for file
****************************************************************************/
static int Open( vlc_object_t *p_this )
{
access_t *p_access = (access_t*)p_this;
access_sys_t *p_sys;
char *psz;
int i_answer;
char *psz_arg;
/* Init p_access */
p_access->pf_read = Read;
p_access->pf_block = NULL;
p_access->pf_seek = Seek;
p_access->pf_control = Control;
p_access->info.i_update = 0;
p_access->info.i_size = 0;
p_access->info.i_pos = 0;
p_access->info.b_eof = VLC_FALSE;
p_access->info.i_title = 0;
p_access->info.i_seekpoint = 0;
p_access->p_sys = p_sys = malloc( sizeof( access_sys_t ) );
memset( p_sys, 0, sizeof( access_sys_t ) );
p_sys->fd_cmd = -1;
p_sys->fd_data = -1;
p_sys->psz_epsv_ip = NULL;
/* *** Parse URL and get server addr/port and path *** */
psz = p_access->psz_path;
while( *psz == '/' )
{
psz++;
}
vlc_UrlParse( &p_sys->url, psz, 0 );
if( p_sys->url.psz_host == NULL || *p_sys->url.psz_host == '\0' )
{
msg_Err( p_access, "invalid server name" );
goto exit_error; goto exit_error;
} }
if( p_sys->url.i_port <= 0 )
{
p_sys->url.i_port = 21; /* default port */
}
if( Connect( p_access, p_sys ) < 0 )
goto exit_error;
if( ftp_ReadCommand( p_access, &i_answer, NULL ) == 2 ) if( ftp_ReadCommand( p_access, &i_answer, NULL ) == 2 )
{ {
...@@ -259,9 +270,24 @@ static int Open( vlc_object_t *p_this ) ...@@ -259,9 +270,24 @@ static int Open( vlc_object_t *p_this )
goto exit_error; goto exit_error;
} }
p_sys->psz_epsv_ip = strdup( hostaddr ); p_sys->psz_epsv_ip = strdup( hostaddr );
}
if( p_sys->psz_epsv_ip == NULL ) if( p_sys->psz_epsv_ip == NULL )
goto exit_error;
}
else
{
/* If ESPV ALL fails, we fallback to PASV.
* We have to restart the connection in case there is a NAT that
* understands EPSV ALL in the way, and hence won't allow PASV on
* the initial connection.
*/
net_Close( p_sys->fd_cmd );
p_sys->fd_cmd = -1;
if( ( p_sys->fd_cmd = Connect( p_access, p_sys ) ) < 0 )
goto exit_error;
msg_Info( p_access, "FTP Extended passive mode disabled" ); msg_Info( p_access, "FTP Extended passive mode disabled" );
}
/* binary mode */ /* binary mode */
if( ftp_SendCommand( p_access, "TYPE I" ) < 0 || if( ftp_SendCommand( p_access, "TYPE I" ) < 0 ||
...@@ -295,10 +321,8 @@ static int Open( vlc_object_t *p_this ) ...@@ -295,10 +321,8 @@ static int Open( vlc_object_t *p_this )
return VLC_SUCCESS; return VLC_SUCCESS;
exit_error: exit_error:
if( p_sys->fd_cmd > 0 ) if( p_sys->fd_cmd >= 0 )
{
net_Close( p_sys->fd_cmd ); net_Close( p_sys->fd_cmd );
}
vlc_UrlClean( &p_sys->url ); vlc_UrlClean( &p_sys->url );
free( p_sys ); free( p_sys );
return VLC_EGENERIC; return VLC_EGENERIC;
......
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