| 167 |
copy_strerror(); |
copy_strerror(); |
| 168 |
return LIBOFTP_ERROR_OS; |
return LIBOFTP_ERROR_OS; |
| 169 |
} |
} |
| 170 |
DEBUGPRINT1( "RESP1: %s", str1 ); |
DEBUGPRINT1( "RESP1: %s\n", str1 ); |
| 171 |
if( n < 3 ) { |
if( n < 3 ) { |
| 172 |
return LIBOFTP_ERROR_PROTOCOL; |
return LIBOFTP_ERROR_PROTOCOL; |
| 173 |
} |
} |
| 185 |
copy_strerror(); |
copy_strerror(); |
| 186 |
return LIBOFTP_ERROR_OS; |
return LIBOFTP_ERROR_OS; |
| 187 |
} |
} |
| 188 |
DEBUGPRINT1( "RESP2: %s", str1 ); |
DEBUGPRINT1( "RESP2: %s\n", str1 ); |
| 189 |
if( n < 3 ) { |
if( n < 3 ) { |
| 190 |
return LIBOFTP_ERROR_PROTOCOL; |
return LIBOFTP_ERROR_PROTOCOL; |
| 191 |
} |
} |
| 223 |
*/ |
*/ |
| 224 |
int ftp_getready_active( LIBOFTP *ftp, const char *cmd, const char *fname ) |
int ftp_getready_active( LIBOFTP *ftp, const char *cmd, const char *fname ) |
| 225 |
{ |
{ |
| 226 |
int sock = 0; |
int sock_listen, sock_accept = -1; |
| 227 |
struct sockaddr_in saddr; |
struct sockaddr_in saddr; |
| 228 |
int saddr_len; |
int saddr_len; |
| 229 |
unsigned char *ip, *pt; |
unsigned char *ip, *pt; |
| 231 |
int res; |
int res; |
| 232 |
struct timeval timeout; |
struct timeval timeout; |
| 233 |
fd_set rfds, wfds; |
fd_set rfds, wfds; |
| 234 |
|
int flag_status_ok = 0; |
| 235 |
|
|
| 236 |
/* |
/* |
| 237 |
* open data port. |
* open data port. |
| 238 |
* (note) |
* (note) |
| 239 |
* same command port ip and automatic random port. |
* same command port ip and automatic random port. |
| 240 |
*/ |
*/ |
| 241 |
sock = socket( PF_INET, SOCK_STREAM, IPPROTO_TCP ); |
sock_listen = socket( PF_INET, SOCK_STREAM, IPPROTO_TCP ); |
| 242 |
if( sock < 0 ) { |
if( sock_listen < 0 ) { |
| 243 |
DEBUGPRINT1( "getready_active: can't open socket. %s\n", strerror(errno) ); |
DEBUGPRINT1( "getready_active: can't open socket. %s\n", strerror(errno) ); |
| 244 |
goto ERROR_OS; |
goto ERROR_OS; |
| 245 |
} |
} |
| 252 |
} |
} |
| 253 |
saddr.sin_port = htons( 0 ); |
saddr.sin_port = htons( 0 ); |
| 254 |
|
|
| 255 |
if( bind( sock, (struct sockaddr *)&saddr, sizeof( saddr ) ) < 0 ) { |
if( bind( sock_listen, (struct sockaddr *)&saddr, sizeof( saddr ) ) < 0 ) { |
| 256 |
DEBUGPRINT1( "getready_active: can't bind socket. %s\n", strerror(errno) ); |
DEBUGPRINT1( "getready_active: can't bind socket. %s\n", strerror(errno) ); |
| 257 |
goto ERROR_OS; |
goto ERROR_OS; |
| 258 |
} |
} |
| 259 |
|
|
| 260 |
if( listen( sock, 1 ) < 0 ) { |
if( listen( sock_listen, 1 ) < 0 ) { |
| 261 |
DEBUGPRINT1( "getready_active: can't listen socket. %s\n", strerror(errno) ); |
DEBUGPRINT1( "getready_active: can't listen socket. %s\n", strerror(errno) ); |
| 262 |
goto ERROR_OS; |
goto ERROR_OS; |
| 263 |
} |
} |
| 264 |
|
|
|
|
|
| 265 |
/* |
/* |
| 266 |
* make PORT command. |
* make PORT command. |
| 267 |
*/ |
*/ |
| 268 |
memset( &saddr, 0, sizeof( saddr ) ); |
memset( &saddr, 0, sizeof( saddr ) ); |
| 269 |
saddr_len = sizeof( saddr ); |
saddr_len = sizeof( saddr ); |
| 270 |
if( getsockname( sock, (struct sockaddr *)&saddr, &saddr_len ) < 0 ) { |
if( getsockname( sock_listen, (struct sockaddr *)&saddr, &saddr_len ) < 0 ) { |
| 271 |
DEBUGPRINT1( "getready_active: can't get data socket name. %s\n", strerror(errno) ); |
DEBUGPRINT1( "getready_active: can't get data socket name. %s\n", strerror(errno) ); |
| 272 |
goto ERROR_OS; |
goto ERROR_OS; |
| 273 |
} |
} |
| 280 |
*/ |
*/ |
| 281 |
if( ftp_send_command( ftp, str1 ) < 0 ) { |
if( ftp_send_command( ftp, str1 ) < 0 ) { |
| 282 |
DEBUGPRINT1( "getready_active: %s command sending error.\n", "PORT" ); |
DEBUGPRINT1( "getready_active: %s command sending error.\n", "PORT" ); |
| 283 |
close( sock ); |
close( sock_listen ); |
| 284 |
return LIBOFTP_ERROR_OS; |
return LIBOFTP_ERROR_OS; |
| 285 |
} |
} |
| 286 |
res = ftp_receive_response( ftp, ftp->error_message, sizeof(ftp->error_message) - 1 ); |
res = ftp_receive_response( ftp, ftp->error_message, sizeof(ftp->error_message) - 1 ); |
| 287 |
if( res != 200 ) { /* 200: Command okay. */ |
if( res != 200 ) { /* 200: Command okay. */ |
| 288 |
DEBUGPRINT1( "getready_active: get PORT response code %d\n", res ); |
DEBUGPRINT1( "getready_active: get PORT response code %d\n", res ); |
| 289 |
close( sock ); |
close( sock_listen ); |
| 290 |
return LIBOFTP_ERROR_PROTOCOL; |
return LIBOFTP_ERROR_PROTOCOL; |
| 291 |
} |
} |
| 292 |
|
|
| 300 |
} |
} |
| 301 |
if( ftp_send_command( ftp, str1 ) < 0 ) { |
if( ftp_send_command( ftp, str1 ) < 0 ) { |
| 302 |
DEBUGPRINT1( "getready_active: command sending error. %s", str1 ); |
DEBUGPRINT1( "getready_active: command sending error. %s", str1 ); |
| 303 |
close( sock ); |
close( sock_listen ); |
| 304 |
return LIBOFTP_ERROR_OS; |
return LIBOFTP_ERROR_OS; |
| 305 |
} |
} |
| 306 |
|
|
| 307 |
/* |
/* |
| 308 |
* accept data connection with timeout. |
* accept data connection with timeout, or get status by control connection. |
| 309 |
*/ |
*/ |
| 310 |
timeout.tv_sec = ftp->timeout_sec; |
timeout.tv_sec = ftp->timeout_sec; |
| 311 |
timeout.tv_usec = 0; |
timeout.tv_usec = 0; |
|
|
|
| 312 |
do { |
do { |
| 313 |
|
int nfds = (sock_listen > ftp->socket)? sock_listen: ftp->socket; |
| 314 |
FD_ZERO( &rfds ); |
FD_ZERO( &rfds ); |
| 315 |
FD_ZERO( &wfds ); |
FD_ZERO( &wfds ); |
| 316 |
FD_SET( sock, &rfds ); |
if( sock_listen >= 0) { |
| 317 |
FD_SET( sock, &wfds ); |
FD_SET( sock_listen, &rfds ); |
| 318 |
|
FD_SET( sock_listen, &wfds ); |
| 319 |
|
} |
| 320 |
|
FD_SET( ftp->socket, &rfds ); |
| 321 |
|
|
| 322 |
res = select( sock+1, &rfds, &wfds, 0, &timeout ); |
res = select( nfds+1, &rfds, &wfds, 0, &timeout ); |
| 323 |
if( res == 0 ) { /* timeout */ |
/* ckeck timeout */ |
| 324 |
|
if( res == 0 ) { |
| 325 |
DEBUGPRINT1( "getready_active: waiting connection timeout.%s\n", "" ); |
DEBUGPRINT1( "getready_active: waiting connection timeout.%s\n", "" ); |
| 326 |
close( sock ); |
close( sock_listen ); |
| 327 |
strncpy( ftp->error_message, "connection timeout.", sizeof( ftp->error_message )-1 ); |
strncpy( ftp->error_message, "connection timeout.", sizeof( ftp->error_message )-1 ); |
| 328 |
return LIBOFTP_ERROR_TIMEOUT; |
return LIBOFTP_ERROR_TIMEOUT; |
| 329 |
} |
} |
| 330 |
|
|
| 331 |
|
/* check some OS errors. */ |
| 332 |
if( res < 0 ) { |
if( res < 0 ) { |
| 333 |
if( errno == EINTR ) continue; |
if( errno == EINTR ) continue; |
| 334 |
DEBUGPRINT1( "getready_active: select error. %s\n", strerror(errno) ); |
DEBUGPRINT1( "getready_active: select error. %s\n", strerror(errno) ); |
| 335 |
goto ERROR_OS; |
goto ERROR_OS; |
| 336 |
} |
} |
| 337 |
|
|
| 338 |
if( FD_ISSET( sock, &rfds ) || FD_ISSET( sock, &wfds ) ) break; |
/* accept data connection. */ |
| 339 |
} while( 1 ); |
if( FD_ISSET( sock_listen, &rfds ) || FD_ISSET( sock_listen, &wfds ) ) { |
| 340 |
|
sock_accept = accept( sock_listen, (struct sockaddr *)&saddr, &saddr_len ); |
| 341 |
res = accept( sock, (struct sockaddr *)&saddr, &saddr_len ); |
close( sock_listen ); |
| 342 |
close( sock ); |
sock_listen = -1; |
| 343 |
if( res < 0 ) { |
if( sock_accept < 0 ) { |
| 344 |
DEBUGPRINT1( "getready_active: socket accept error. %s\n", strerror(errno) ); |
DEBUGPRINT1( "getready_active: socket accept error. %s\n", strerror(errno) ); |
| 345 |
goto ERROR_OS; |
goto ERROR_OS; |
| 346 |
} |
} |
| 347 |
sock = res; |
DEBUGPRINT1( "getready_active: socket accept. fd=%d\n", sock_accept ); |
| 348 |
|
} |
| 349 |
|
|
| 350 |
/* |
/* get status. */ |
| 351 |
* get status. |
if( FD_ISSET( ftp->socket, &rfds ) ) { |
| 352 |
*/ |
res = ftp_receive_response( ftp, ftp->error_message, sizeof(ftp->error_message) - 1 ); |
| 353 |
res = ftp_receive_response( ftp, ftp->error_message, sizeof(ftp->error_message) - 1 ); |
DEBUGPRINT1( "getready_active: get STOR/RETR response code %d\n", res ); |
| 354 |
if( res != 150 ) { /* 150: File status okay; about to open data connection. */ |
if( res != 150 ) { /* 150: File status okay; about to open data connection. */ |
| 355 |
DEBUGPRINT1( "getready_active: get STOR/RETR response code %d\n", res ); |
if( sock_listen >= 0 ) close( sock_listen ); |
| 356 |
close( sock ); |
if( sock_accept >= 0 ) close( sock_accept ); |
| 357 |
return LIBOFTP_ERROR_PROTOCOL; |
return LIBOFTP_ERROR_PROTOCOL; |
| 358 |
} |
} |
| 359 |
|
flag_status_ok = 1; |
| 360 |
|
} |
| 361 |
|
|
| 362 |
|
} while( !( sock_accept >= 0 && flag_status_ok ) ); |
| 363 |
|
|
| 364 |
return sock; |
return sock_accept; |
| 365 |
|
|
| 366 |
|
|
| 367 |
ERROR_OS: |
ERROR_OS: |
| 368 |
copy_strerror(); |
copy_strerror(); |
| 369 |
if( sock > 0 ) { |
if( sock_listen >= 0 ) { |
| 370 |
close( sock ); |
close( sock_listen ); |
| 371 |
} |
} |
| 372 |
return LIBOFTP_ERROR_OS; |
return LIBOFTP_ERROR_OS; |
| 373 |
} |
} |