|
|
1.1 ! root 1: /* execnet.cpp */ ! 2: ! 3: /* Synchronet command shell/module TCP/IP Network functions */ ! 4: ! 5: /* $Id: execnet.cpp,v 1.22 2003/10/24 21:46:55 rswindell Exp $ */ ! 6: ! 7: /**************************************************************************** ! 8: * @format.tab-size 4 (Plain Text/Source Code File Header) * ! 9: * @format.use-tabs true (see http://www.synchro.net/ptsc_hdr.html) * ! 10: * * ! 11: * Copyright 2003 Rob Swindell - http://www.synchro.net/copyright.html * ! 12: * * ! 13: * This program is free software; you can redistribute it and/or * ! 14: * modify it under the terms of the GNU General Public License * ! 15: * as published by the Free Software Foundation; either version 2 * ! 16: * of the License, or (at your option) any later version. * ! 17: * See the GNU General Public License for more details: gpl.txt or * ! 18: * http://www.fsf.org/copyleft/gpl.html * ! 19: * * ! 20: * Anonymous FTP access to the most recent released source is available at * ! 21: * ftp://vert.synchro.net, ftp://cvs.synchro.net and ftp://ftp.synchro.net * ! 22: * * ! 23: * Anonymous CVS access to the development source and modification history * ! 24: * is available at cvs.synchro.net:/cvsroot/sbbs, example: * ! 25: * cvs -d :pserver:[email protected]:/cvsroot/sbbs login * ! 26: * (just hit return, no password is necessary) * ! 27: * cvs -d :pserver:[email protected]:/cvsroot/sbbs checkout src * ! 28: * * ! 29: * For Synchronet coding style and modification guidelines, see * ! 30: * http://www.synchro.net/source.html * ! 31: * * ! 32: * You are encouraged to submit any modifications (preferably in Unix diff * ! 33: * format) via e-mail to [email protected] * ! 34: * * ! 35: * Note: If this box doesn't appear square, then you need to fix your tabs. * ! 36: ****************************************************************************/ ! 37: ! 38: #include "sbbs.h" ! 39: #include "cmdshell.h" ! 40: ! 41: #define TIMEOUT_SOCK_READLINE 30 /* seconds */ ! 42: #define TIMEOUT_SOCK_LISTEN 30 /* seconds */ ! 43: #define TIMEOUT_FTP_RESPONSE 300 /* seconds */ ! 44: ! 45: int sbbs_t::exec_net(csi_t* csi) ! 46: { ! 47: char str[512],rsp[512],buf[1025],ch,*p,**pp,**pp1,**pp2; ! 48: ushort w; ! 49: uint i; ! 50: BOOL rd; ! 51: long *lp,*lp1,*lp2; ! 52: time_t start; ! 53: ! 54: switch(*(csi->ip++)) { /* sub-op-code stored as next byte */ ! 55: case CS_SOCKET_OPEN: ! 56: lp=getintvar(csi,*(long *)csi->ip); ! 57: csi->ip+=4; ! 58: csi->logic=LOGIC_FALSE; ! 59: csi->socket_error=0; ! 60: if(csi->sockets>=MAX_SOCKETS) ! 61: return(0); ! 62: if(lp!=NULL) { ! 63: ! 64: SOCKET sock=open_socket(SOCK_STREAM); ! 65: if(sock!=INVALID_SOCKET) { ! 66: ! 67: SOCKADDR_IN addr; ! 68: ! 69: memset(&addr,0,sizeof(addr)); ! 70: addr.sin_addr.s_addr = htonl(startup->telnet_interface); ! 71: addr.sin_family = AF_INET; ! 72: ! 73: if((i=bind(sock, (struct sockaddr *) &addr, sizeof (addr)))!=0) { ! 74: csi->socket_error=ERROR_VALUE; ! 75: close_socket(sock); ! 76: return(0); ! 77: } ! 78: ! 79: *lp=sock; ! 80: ! 81: for(i=0;i<csi->sockets;i++) ! 82: if(!csi->socket[i]) ! 83: break; ! 84: csi->socket[i]=*lp; ! 85: if(i==csi->sockets) ! 86: csi->sockets++; ! 87: csi->logic=LOGIC_TRUE; ! 88: } ! 89: } ! 90: return(0); ! 91: case CS_SOCKET_CLOSE: ! 92: lp=getintvar(csi,*(long *)csi->ip); ! 93: csi->ip+=4; ! 94: csi->logic=LOGIC_FALSE; ! 95: csi->socket_error=0; ! 96: if(lp && *lp) { ! 97: csi->logic=close_socket((SOCKET)*lp); ! 98: csi->socket_error=ERROR_VALUE; ! 99: for(i=0;i<csi->sockets;i++) ! 100: if(csi->socket[i]==*lp) ! 101: csi->socket[i]=0; ! 102: *lp=0; ! 103: } ! 104: return(0); ! 105: case CS_SOCKET_CHECK: ! 106: lp=getintvar(csi,*(long *)csi->ip); ! 107: csi->ip+=4; ! 108: csi->logic=LOGIC_FALSE; ! 109: csi->socket_error=0; ! 110: ! 111: if(lp==NULL || *lp==INVALID_SOCKET) ! 112: return(0); ! 113: ! 114: if(socket_check(*lp,NULL,NULL,0)==TRUE) ! 115: csi->logic=LOGIC_TRUE; ! 116: else ! 117: csi->socket_error=ERROR_VALUE; ! 118: ! 119: return(0); ! 120: case CS_SOCKET_CONNECT: ! 121: lp=getintvar(csi,*(long *)csi->ip); /* socket */ ! 122: csi->ip+=4; ! 123: ! 124: pp=getstrvar(csi,*(long *)csi->ip); /* address */ ! 125: csi->ip+=4; ! 126: ! 127: w=*(ushort *)csi->ip; /* port */ ! 128: csi->ip+=2; ! 129: ! 130: csi->logic=LOGIC_FALSE; ! 131: csi->socket_error=0; ! 132: ! 133: if(!lp || !*lp || !pp || !*pp || !w) ! 134: return(0); ! 135: ! 136: ulong ip_addr; ! 137: ! 138: if((ip_addr=resolve_ip(*pp))==INADDR_NONE) ! 139: return(0); ! 140: ! 141: SOCKADDR_IN addr; ! 142: ! 143: memset(&addr,0,sizeof(addr)); ! 144: addr.sin_addr.s_addr = ip_addr; ! 145: addr.sin_family = AF_INET; ! 146: addr.sin_port = htons(w); ! 147: ! 148: if((i=connect(*lp, (struct sockaddr *)&addr, sizeof(addr)))!=0) { ! 149: csi->socket_error=ERROR_VALUE; ! 150: return(0); ! 151: } ! 152: csi->logic=LOGIC_TRUE; ! 153: return(0); ! 154: case CS_SOCKET_ACCEPT: ! 155: lp1=getintvar(csi,*(long *)csi->ip); /* socket */ ! 156: csi->ip+=4; ! 157: csi->socket_error=0; ! 158: /* TODO */ ! 159: return(0); ! 160: case CS_SOCKET_NREAD: ! 161: lp1=getintvar(csi,*(long *)csi->ip); /* socket */ ! 162: csi->ip+=4; ! 163: lp2=getintvar(csi,*(long *)csi->ip); /* var */ ! 164: csi->ip+=4; ! 165: ! 166: csi->logic=LOGIC_FALSE; ! 167: csi->socket_error=0; ! 168: ! 169: if(!lp1 || !lp2) ! 170: return(0); ! 171: ! 172: if(ioctlsocket(*lp1, FIONREAD, (ulong*)lp2)==0) ! 173: csi->logic=LOGIC_TRUE; ! 174: else ! 175: csi->socket_error=ERROR_VALUE; ! 176: return(0); ! 177: case CS_SOCKET_PEEK: ! 178: case CS_SOCKET_READ: ! 179: lp=getintvar(csi,*(long *)csi->ip); /* socket */ ! 180: csi->ip+=4; ! 181: pp=getstrvar(csi,*(long *)csi->ip); /* buffer */ ! 182: csi->ip+=4; ! 183: w=*(ushort *)csi->ip; /* length */ ! 184: csi->ip+=2; ! 185: ! 186: csi->logic=LOGIC_FALSE; ! 187: csi->socket_error=0; ! 188: ! 189: if(!lp || !pp) ! 190: return(0); ! 191: ! 192: if(w<1 || w>sizeof(buf)-1) ! 193: w=sizeof(buf)-1; ! 194: ! 195: if((i=recv(*lp,buf,w ! 196: ,*(csi->ip-13)==CS_SOCKET_PEEK ? MSG_PEEK : 0))>0) { ! 197: csi->logic=LOGIC_TRUE; ! 198: buf[i]=0; ! 199: if(csi->etx) { ! 200: p=strchr(buf,csi->etx); ! 201: if(p) *p=0; ! 202: } ! 203: *pp=copystrvar(csi,*pp,buf); ! 204: } else ! 205: csi->socket_error=ERROR_VALUE; ! 206: return(0); ! 207: case CS_SOCKET_READLINE: ! 208: lp=getintvar(csi,*(long *)csi->ip); /* socket */ ! 209: csi->ip+=4; ! 210: pp=getstrvar(csi,*(long *)csi->ip); /* buffer */ ! 211: csi->ip+=4; ! 212: w=*(ushort *)csi->ip; /* length */ ! 213: csi->ip+=2; ! 214: ! 215: csi->logic=LOGIC_FALSE; ! 216: csi->socket_error=0; ! 217: ! 218: if(!lp || !pp) ! 219: return(0); ! 220: ! 221: if(w<1 || w>sizeof(buf)-1) ! 222: w=sizeof(buf)-1; ! 223: ! 224: start=time(NULL); ! 225: for(i=0;i<w;) { ! 226: ! 227: if(!online) ! 228: return(1); ! 229: ! 230: if(!socket_check(*lp,&rd,NULL,1000)) ! 231: return(0); ! 232: ! 233: if(!rd) { ! 234: if(time(NULL)-start>TIMEOUT_SOCK_READLINE) { ! 235: lprintf(LOG_WARNING,"!socket_readline: timeout (%d) exceeded" ! 236: ,TIMEOUT_SOCK_READLINE); ! 237: return(0); ! 238: } ! 239: continue; ! 240: } ! 241: ! 242: if(recv(*lp, &ch, 1, 0)!=1) { ! 243: csi->socket_error=ERROR_VALUE; ! 244: return(0); ! 245: } ! 246: ! 247: if(ch=='\n' && i>=1) ! 248: break; ! 249: ! 250: buf[i++]=ch; ! 251: } ! 252: if(i>0 && buf[i-1]=='\r') ! 253: buf[i-1]=0; ! 254: else ! 255: buf[i]=0; ! 256: ! 257: if(csi->etx) { ! 258: p=strchr(buf,csi->etx); ! 259: if(p) *p=0; ! 260: } ! 261: *pp=copystrvar(csi,*pp,buf); ! 262: csi->logic=LOGIC_TRUE; ! 263: return(0); ! 264: case CS_SOCKET_WRITE: ! 265: lp=getintvar(csi,*(long *)csi->ip); /* socket */ ! 266: csi->ip+=4; ! 267: pp=getstrvar(csi,*(long *)csi->ip); /* buffer */ ! 268: csi->ip+=4; ! 269: ! 270: csi->logic=LOGIC_FALSE; ! 271: csi->socket_error=0; ! 272: ! 273: if(!lp || !pp || !(*pp)) ! 274: return(0); ! 275: ! 276: if(sendsocket(*lp,*pp,strlen(*pp))>0) ! 277: csi->logic=LOGIC_TRUE; ! 278: else ! 279: csi->socket_error=ERROR_VALUE; ! 280: return(0); ! 281: ! 282: /* FTP Functions */ ! 283: case CS_FTP_LOGIN: ! 284: lp=getintvar(csi,*(long *)csi->ip); /* socket */ ! 285: csi->ip+=4; ! 286: pp1=getstrvar(csi,*(long *)csi->ip); /* username */ ! 287: csi->ip+=4; ! 288: pp2=getstrvar(csi,*(long *)csi->ip); /* password */ ! 289: csi->ip+=4; ! 290: ! 291: csi->logic=LOGIC_FALSE; ! 292: csi->socket_error=0; ! 293: ! 294: if(!lp || !pp1 || !pp2) ! 295: return(0); ! 296: ! 297: if(!ftp_cmd(csi,*lp,NULL,rsp)) ! 298: return(0); ! 299: ! 300: if(atoi(rsp)!=220) ! 301: return(0); ! 302: ! 303: sprintf(str,"USER %s",*pp1); ! 304: ! 305: if(!ftp_cmd(csi,*lp,str,rsp)) ! 306: return(0); ! 307: ! 308: if(atoi(rsp)==331) { /* Password needed */ ! 309: sprintf(str,"PASS %s",*pp2); ! 310: if(!ftp_cmd(csi,*lp,str,rsp)) ! 311: return(0); ! 312: } ! 313: ! 314: if(atoi(rsp)==230) /* Login successful */ ! 315: csi->logic=LOGIC_TRUE; ! 316: return(0); ! 317: ! 318: case CS_FTP_LOGOUT: ! 319: lp=getintvar(csi,*(long *)csi->ip); /* socket */ ! 320: csi->ip+=4; ! 321: csi->logic=LOGIC_FALSE; ! 322: csi->socket_error=0; ! 323: ! 324: if(!lp) ! 325: return(0); ! 326: ! 327: if(!ftp_cmd(csi,*lp,"QUIT",rsp)) ! 328: return(0); ! 329: ! 330: if(atoi(rsp)==221) /* Logout successful */ ! 331: csi->logic=LOGIC_TRUE; ! 332: return(0); ! 333: ! 334: case CS_FTP_PWD: ! 335: lp=getintvar(csi,*(long *)csi->ip); /* socket */ ! 336: csi->ip+=4; ! 337: csi->logic=LOGIC_FALSE; ! 338: csi->socket_error=0; ! 339: if(!lp) ! 340: return(0); ! 341: ! 342: if(!ftp_cmd(csi,*lp,"PWD",rsp)) ! 343: return(0); ! 344: ! 345: if(atoi(rsp)==257) /* pathname */ ! 346: csi->logic=LOGIC_TRUE; ! 347: return(0); ! 348: ! 349: case CS_FTP_CWD: ! 350: lp=getintvar(csi,*(long *)csi->ip); /* socket */ ! 351: csi->ip+=4; ! 352: pp=getstrvar(csi,*(long *)csi->ip); /* path */ ! 353: csi->ip+=4; ! 354: ! 355: csi->logic=LOGIC_FALSE; ! 356: csi->socket_error=0; ! 357: if(!lp || !pp) ! 358: return(0); ! 359: ! 360: sprintf(str,"CWD %s",*pp); ! 361: if(!ftp_cmd(csi,*lp,str,rsp)) ! 362: return(0); ! 363: ! 364: if(atoi(rsp)==250) ! 365: csi->logic=LOGIC_TRUE; ! 366: ! 367: return(0); ! 368: ! 369: case CS_FTP_DIR: ! 370: lp=getintvar(csi,*(long *)csi->ip); /* socket */ ! 371: csi->ip+=4; ! 372: pp=getstrvar(csi,*(long *)csi->ip); /* path */ ! 373: csi->ip+=4; ! 374: ! 375: csi->logic=LOGIC_FALSE; ! 376: csi->socket_error=0; ! 377: ! 378: if(!lp || !pp) ! 379: return(0); ! 380: ! 381: if(ftp_get(csi,*lp,*pp,NULL /* unused */, true /* DIR */)==true) ! 382: csi->logic=LOGIC_TRUE; ! 383: ! 384: return(0); ! 385: ! 386: case CS_FTP_DELETE: ! 387: lp=getintvar(csi,*(long *)csi->ip); /* socket */ ! 388: csi->ip+=4; ! 389: pp=getstrvar(csi,*(long *)csi->ip); /* path */ ! 390: csi->ip+=4; ! 391: ! 392: csi->logic=LOGIC_FALSE; ! 393: csi->socket_error=0; ! 394: if(!lp || !pp) ! 395: return(0); ! 396: ! 397: sprintf(str,"DELE %s",*pp); ! 398: if(!ftp_cmd(csi,*lp,str,rsp)) ! 399: return(0); ! 400: ! 401: if(atoi(rsp)==250) ! 402: csi->logic=LOGIC_TRUE; ! 403: ! 404: return(0); ! 405: ! 406: ! 407: case CS_FTP_GET: ! 408: lp=getintvar(csi,*(long *)csi->ip); /* socket */ ! 409: csi->ip+=4; ! 410: pp1=getstrvar(csi,*(long *)csi->ip); /* src path */ ! 411: csi->ip+=4; ! 412: pp2=getstrvar(csi,*(long *)csi->ip); /* dest path */ ! 413: csi->ip+=4; ! 414: ! 415: csi->logic=LOGIC_FALSE; ! 416: csi->socket_error=0; ! 417: ! 418: if(!lp || !pp1 || !pp2) ! 419: return(0); ! 420: ! 421: if(ftp_get(csi,*lp,*pp1,*pp2)==true) ! 422: csi->logic=LOGIC_TRUE; ! 423: ! 424: return(0); ! 425: ! 426: case CS_FTP_PUT: ! 427: lp=getintvar(csi,*(long *)csi->ip); /* socket */ ! 428: csi->ip+=4; ! 429: pp1=getstrvar(csi,*(long *)csi->ip); /* src path */ ! 430: csi->ip+=4; ! 431: pp2=getstrvar(csi,*(long *)csi->ip); /* dest path */ ! 432: csi->ip+=4; ! 433: ! 434: csi->logic=LOGIC_FALSE; ! 435: csi->socket_error=0; ! 436: ! 437: if(!lp || !pp1 || !pp2) ! 438: return(0); ! 439: ! 440: if(ftp_put(csi,*lp,*pp1,*pp2)==true) ! 441: csi->logic=LOGIC_TRUE; ! 442: ! 443: return(0); ! 444: ! 445: ! 446: default: ! 447: errormsg(WHERE,ERR_CHK,"net sub-instruction",*(csi->ip-1)); ! 448: return(0); ! 449: } ! 450: } ! 451: ! 452: /* FTP Command/Response function */ ! 453: bool sbbs_t::ftp_cmd(csi_t* csi, SOCKET sock, char* cmdsrc, char* rsp) ! 454: { ! 455: char cmd[512]; ! 456: int len; ! 457: BOOL data_avail; ! 458: time_t start; ! 459: ! 460: if(cmdsrc!=NULL) { ! 461: sprintf(cmd,"%s\r\n",cmdsrc); ! 462: ! 463: if(csi->ftp_mode&CS_FTP_ECHO_CMD) ! 464: bputs(cmd); ! 465: ! 466: len=strlen(cmd); ! 467: if(sendsocket(sock,cmd,len)!=len) { ! 468: csi->socket_error=ERROR_VALUE; ! 469: return(FALSE); ! 470: } ! 471: } ! 472: ! 473: if(rsp!=NULL) { ! 474: ! 475: int rd; ! 476: char ch; ! 477: ! 478: while(1) { ! 479: rd=0; ! 480: ! 481: start=time(NULL); ! 482: while(rd<500) { ! 483: ! 484: if(!online) ! 485: return(FALSE); ! 486: ! 487: if(!socket_check(sock,&data_avail,NULL,1000)) ! 488: return(FALSE); ! 489: ! 490: if(!data_avail) { ! 491: if(time(NULL)-start>TIMEOUT_FTP_RESPONSE) { ! 492: lprintf(LOG_WARNING,"!ftp_cmd: TIMEOUT_FTP_RESPONSE (%d) exceeded" ! 493: ,TIMEOUT_FTP_RESPONSE); ! 494: return(FALSE); ! 495: } ! 496: continue; ! 497: } ! 498: ! 499: if(recv(sock, &ch, 1, 0)!=1) { ! 500: csi->socket_error=ERROR_VALUE; ! 501: return(FALSE); ! 502: } ! 503: ! 504: if(ch=='\n' && rd>=1) ! 505: break; ! 506: ! 507: rsp[rd++]=ch; ! 508: } ! 509: rsp[rd-1]=0; ! 510: if(csi->ftp_mode&CS_FTP_ECHO_RSP) ! 511: bprintf("%s\r\n",rsp); ! 512: if(rsp[0]!=' ' && rsp[3]!='-') ! 513: break; ! 514: } ! 515: } ! 516: ! 517: return(TRUE); ! 518: } ! 519: ! 520: SOCKET sbbs_t::ftp_data_sock(csi_t* csi, SOCKET ctrl_sock, SOCKADDR_IN* addr) ! 521: { ! 522: char cmd[512]; ! 523: char rsp[512]; ! 524: char* p; ! 525: socklen_t addr_len; ! 526: SOCKET data_sock; ! 527: int ip_b[4]; ! 528: int port_b[2]; ! 529: union { ! 530: DWORD dw; ! 531: BYTE b[sizeof(DWORD)]; ! 532: } ip_addr; ! 533: union { ! 534: WORD w; ! 535: BYTE b[sizeof(WORD)]; ! 536: } port; ! 537: ! 538: if(csi->ftp_mode&CS_FTP_ASCII) ! 539: strcpy(cmd,"TYPE A"); ! 540: else /* BINARY */ ! 541: strcpy(cmd,"TYPE I"); ! 542: if(!ftp_cmd(csi,ctrl_sock,cmd,rsp) ! 543: || atoi(rsp)!=200) { ! 544: return(INVALID_SOCKET); ! 545: } ! 546: ! 547: if((data_sock=open_socket(SOCK_STREAM))==INVALID_SOCKET) { ! 548: csi->socket_error=ERROR_VALUE; ! 549: return(INVALID_SOCKET); ! 550: } ! 551: ! 552: memset(addr,0,sizeof(SOCKADDR_IN)); ! 553: addr->sin_addr.s_addr = htonl(startup->telnet_interface); ! 554: addr->sin_family = AF_INET; ! 555: ! 556: if(bind(data_sock, (struct sockaddr *)addr,sizeof(SOCKADDR_IN))!= 0) { ! 557: csi->socket_error=ERROR_VALUE; ! 558: close_socket(data_sock); ! 559: return(INVALID_SOCKET); ! 560: } ! 561: ! 562: if(csi->ftp_mode&CS_FTP_PASV) { ! 563: ! 564: if(!ftp_cmd(csi,ctrl_sock,"PASV",rsp) ! 565: || atoi(rsp)!=227 /* PASV response */) { ! 566: bprintf("ftp: failure, line %d",__LINE__); ! 567: close_socket(data_sock); ! 568: return(INVALID_SOCKET); ! 569: } ! 570: ! 571: p=strchr(rsp,'('); ! 572: if(p==NULL) { ! 573: bprintf("ftp: failure, line %d",__LINE__); ! 574: close_socket(data_sock); ! 575: return(INVALID_SOCKET); ! 576: } ! 577: p++; ! 578: if(sscanf(p,"%u,%u,%u,%u,%u,%u" ! 579: ,&ip_b[0],&ip_b[1],&ip_b[2],&ip_b[3] ! 580: ,&port_b[0],&port_b[1])!=6) { ! 581: bprintf("ftp: failure, line %d",__LINE__); ! 582: close_socket(data_sock); ! 583: return(INVALID_SOCKET); ! 584: } ! 585: ! 586: ip_addr.b[0]=ip_b[0]; ip_addr.b[1]=ip_b[1]; ! 587: ip_addr.b[2]=ip_b[2]; ip_addr.b[3]=ip_b[3]; ! 588: port.b[0]=port_b[0]; port.b[1]=port_b[1]; ! 589: ! 590: addr->sin_addr.s_addr=ip_addr.dw; ! 591: addr->sin_port=port.w; ! 592: ! 593: } else { /* Normal (Active) FTP */ ! 594: ! 595: addr_len=sizeof(SOCKADDR_IN); ! 596: if(getsockname(data_sock, (struct sockaddr *)addr,&addr_len)!=0) { ! 597: csi->socket_error=ERROR_VALUE; ! 598: close_socket(data_sock); ! 599: return(INVALID_SOCKET); ! 600: } ! 601: ! 602: SOCKADDR_IN ctrl_addr; ! 603: addr_len=sizeof(ctrl_addr); ! 604: if(getsockname(ctrl_sock, (struct sockaddr *)&ctrl_addr,&addr_len)!=0) { ! 605: csi->socket_error=ERROR_VALUE; ! 606: close_socket(data_sock); ! 607: return(INVALID_SOCKET); ! 608: } ! 609: ! 610: if(listen(data_sock, 1)!= 0) { ! 611: csi->socket_error=ERROR_VALUE; ! 612: close_socket(data_sock); ! 613: return(INVALID_SOCKET); ! 614: } ! 615: ! 616: ip_addr.dw=ntohl(ctrl_addr.sin_addr.s_addr); ! 617: port.w=ntohs(addr->sin_port); ! 618: sprintf(cmd,"PORT %u,%u,%u,%u,%u,%u" ! 619: ,ip_addr.b[3] ! 620: ,ip_addr.b[2] ! 621: ,ip_addr.b[1] ! 622: ,ip_addr.b[0] ! 623: ,port.b[1] ! 624: ,port.b[0] ! 625: ); ! 626: ! 627: if(!ftp_cmd(csi,ctrl_sock,cmd,rsp) ! 628: || atoi(rsp)!=200 /* PORT response */) { ! 629: close_socket(data_sock); ! 630: return(INVALID_SOCKET); ! 631: } ! 632: ! 633: } ! 634: ! 635: return(data_sock); ! 636: } ! 637: ! 638: bool sbbs_t::ftp_get(csi_t* csi, SOCKET ctrl_sock, char* src, char* dest, bool dir) ! 639: { ! 640: char cmd[512]; ! 641: char rsp[512]; ! 642: char buf[4097]; ! 643: int rd; ! 644: int result; ! 645: BOOL data_avail; ! 646: ulong total=0; ! 647: SOCKET data_sock; ! 648: SOCKADDR_IN addr; ! 649: socklen_t addr_len; ! 650: FILE* fp=NULL; ! 651: struct timeval tv; ! 652: fd_set socket_set; ! 653: ! 654: if((data_sock=ftp_data_sock(csi, ctrl_sock, &addr))==INVALID_SOCKET) ! 655: return(false); ! 656: ! 657: if(csi->ftp_mode&CS_FTP_PASV) { ! 658: ! 659: #if 0 // Debug ! 660: bprintf("Connecting to %s:%hd\r\n" ! 661: ,inet_ntoa(addr.sin_addr) ! 662: ,ntohs(addr.sin_port)); ! 663: #endif ! 664: ! 665: if(connect(data_sock,(struct sockaddr *)&addr,sizeof(addr))!=0) { ! 666: csi->socket_error=ERROR_VALUE; ! 667: close_socket(data_sock); ! 668: return(false); ! 669: } ! 670: } ! 671: ! 672: if(dir) ! 673: sprintf(cmd,"LIST %s",src); ! 674: else ! 675: sprintf(cmd,"RETR %s",src); ! 676: ! 677: if(!ftp_cmd(csi,ctrl_sock,cmd,rsp) ! 678: || atoi(rsp)!=150 /* Open data connection */) { ! 679: close_socket(data_sock); ! 680: return(false); ! 681: } ! 682: ! 683: if(!(csi->ftp_mode&CS_FTP_PASV)) { /* Normal (Active) FTP */ ! 684: ! 685: /* Setup for select() */ ! 686: tv.tv_sec=TIMEOUT_SOCK_LISTEN; ! 687: tv.tv_usec=0; ! 688: ! 689: FD_ZERO(&socket_set); ! 690: FD_SET(data_sock,&socket_set); ! 691: ! 692: result=select(data_sock+1,&socket_set,NULL,NULL,&tv); ! 693: if(result<1) { ! 694: csi->socket_error=ERROR_VALUE; ! 695: closesocket(data_sock); ! 696: return(false); ! 697: } ! 698: ! 699: SOCKET accept_sock; ! 700: ! 701: addr_len=sizeof(addr); ! 702: if((accept_sock=accept_socket(data_sock,(struct sockaddr*)&addr,&addr_len)) ! 703: ==INVALID_SOCKET) { ! 704: csi->socket_error=ERROR_VALUE; ! 705: closesocket(data_sock); ! 706: return(false); ! 707: } ! 708: ! 709: close_socket(data_sock); ! 710: data_sock=accept_sock; ! 711: } ! 712: ! 713: if(!dir) ! 714: if((fp=fopen(dest,"wb"))==NULL) { ! 715: close_socket(data_sock); ! 716: return(false); ! 717: } ! 718: ! 719: while(online) { ! 720: ! 721: if(!socket_check(ctrl_sock,NULL,NULL,0)) ! 722: break; /* Control connection lost */ ! 723: ! 724: if(!socket_check(data_sock,&data_avail,NULL,100)) ! 725: break; /* Data connection lost */ ! 726: ! 727: if(!data_avail) ! 728: continue; ! 729: ! 730: if((rd=recv(data_sock, buf, sizeof(buf)-1, 0))<1) ! 731: break; ! 732: ! 733: if(dir) { ! 734: buf[rd]=0; ! 735: bputs(buf); ! 736: } else ! 737: fwrite(buf,1,rd,fp); ! 738: ! 739: total+=rd; ! 740: ! 741: if(!dir && csi->ftp_mode&CS_FTP_HASH) ! 742: outchar('#'); ! 743: } ! 744: ! 745: if(!dir && csi->ftp_mode&CS_FTP_HASH) { ! 746: CRLF; ! 747: } ! 748: ! 749: if(fp!=NULL) ! 750: fclose(fp); ! 751: ! 752: close_socket(data_sock); ! 753: ! 754: if(!ftp_cmd(csi,ctrl_sock,NULL,rsp) ! 755: || atoi(rsp)!=226 /* Download complete */) ! 756: return(false); ! 757: ! 758: bprintf("ftp: %lu bytes received.\r\n", total); ! 759: ! 760: return(true); ! 761: } ! 762: ! 763: bool sbbs_t::ftp_put(csi_t* csi, SOCKET ctrl_sock, char* src, char* dest) ! 764: { ! 765: char cmd[512]; ! 766: char rsp[512]; ! 767: char path[MAX_PATH+1]; ! 768: char buf[4097]; ! 769: int rd; ! 770: int result; ! 771: ulong total=0; ! 772: SOCKET data_sock; ! 773: SOCKADDR_IN addr; ! 774: socklen_t addr_len; ! 775: FILE* fp=NULL; ! 776: bool error=false; ! 777: struct timeval tv; ! 778: fd_set socket_set; ! 779: ! 780: SAFECOPY(path,src); ! 781: ! 782: if(!fexistcase(path)) ! 783: return(false); ! 784: ! 785: if((data_sock=ftp_data_sock(csi, ctrl_sock, &addr))==INVALID_SOCKET) { ! 786: bprintf("ftp: failure, line %d",__LINE__); ! 787: return(false); ! 788: } ! 789: ! 790: if(csi->ftp_mode&CS_FTP_PASV) { ! 791: ! 792: #if 0 // Debug ! 793: bprintf("Connecting to %s:%hd\r\n" ! 794: ,inet_ntoa(addr.sin_addr) ! 795: ,ntohs(addr.sin_port)); ! 796: #endif ! 797: ! 798: if(connect(data_sock,(struct sockaddr *)&addr,sizeof(addr))!=0) { ! 799: bprintf("ftp: failure, line %d",__LINE__); ! 800: csi->socket_error=ERROR_VALUE; ! 801: close_socket(data_sock); ! 802: return(false); ! 803: } ! 804: } ! 805: ! 806: if((fp=fopen(path,"rb"))==NULL) { ! 807: bprintf("ftp: failure, line %d",__LINE__); ! 808: close_socket(data_sock); ! 809: return(false); ! 810: } ! 811: ! 812: sprintf(cmd,"STOR %s",dest); ! 813: ! 814: if(!ftp_cmd(csi,ctrl_sock,cmd,rsp) ! 815: || atoi(rsp)!=150 /* Open data connection */) { ! 816: bprintf("ftp: failure, line %d",__LINE__); ! 817: close_socket(data_sock); ! 818: return(false); ! 819: } ! 820: ! 821: if(!(csi->ftp_mode&CS_FTP_PASV)) { /* Normal (Active) FTP */ ! 822: ! 823: /* Setup for select() */ ! 824: tv.tv_sec=TIMEOUT_SOCK_LISTEN; ! 825: tv.tv_usec=0; ! 826: ! 827: FD_ZERO(&socket_set); ! 828: FD_SET(data_sock,&socket_set); ! 829: ! 830: result=select(data_sock+1,&socket_set,NULL,NULL,&tv); ! 831: if(result<1) { ! 832: csi->socket_error=ERROR_VALUE; ! 833: closesocket(data_sock); ! 834: return(false); ! 835: } ! 836: ! 837: SOCKET accept_sock; ! 838: ! 839: addr_len=sizeof(addr); ! 840: if((accept_sock=accept_socket(data_sock,(struct sockaddr*)&addr,&addr_len)) ! 841: ==INVALID_SOCKET) { ! 842: csi->socket_error=ERROR_VALUE; ! 843: closesocket(data_sock); ! 844: return(false); ! 845: } ! 846: ! 847: close_socket(data_sock); ! 848: data_sock=accept_sock; ! 849: } ! 850: ! 851: while(online && !feof(fp)) { ! 852: ! 853: rd=fread(buf,sizeof(char),sizeof(buf),fp); ! 854: if(rd<1) /* EOF or READ error */ ! 855: break; ! 856: ! 857: if(!socket_check(ctrl_sock,NULL,NULL,0)) ! 858: break; /* Control connection lost */ ! 859: ! 860: if(sendsocket(data_sock,buf,rd)<1) { ! 861: error=true; ! 862: break; ! 863: } ! 864: ! 865: total+=rd; ! 866: ! 867: if(csi->ftp_mode&CS_FTP_HASH) ! 868: outchar('#'); ! 869: } ! 870: ! 871: if(csi->ftp_mode&CS_FTP_HASH) { ! 872: CRLF; ! 873: } ! 874: ! 875: fclose(fp); ! 876: ! 877: close_socket(data_sock); ! 878: ! 879: if(!ftp_cmd(csi,ctrl_sock,NULL,rsp) ! 880: || atoi(rsp)!=226 /* Upload complete */) ! 881: return(false); ! 882: ! 883: if(!error) ! 884: bprintf("ftp: %lu bytes sent.\r\n", total); ! 885: ! 886: return(!error); ! 887: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.