00001
00002
00003
00004
00005
00006
00007
00008
00009 #include <sys/types.h>
00010 #include <sys/ioctl.h>
00011 #include <sys/wait.h>
00012 #include <stdio.h>
00013 #include <unistd.h>
00014 #include <string.h>
00015 #include <unistd.h>
00016 #include <stdlib.h>
00017 #include <fcntl.h>
00018 #include <signal.h>
00019 #include <errno.h>
00020 #include <net/netlib.h>
00021 #include <net/hton.h>
00022 #include <net/gen/netdb.h>
00023 #include <net/gen/in.h>
00024 #include <net/gen/inet.h>
00025 #include <net/gen/tcp.h>
00026 #include <net/gen/tcp_io.h>
00027
00028 #include "ftp.h"
00029 #include "file.h"
00030 #include "net.h"
00031
00032 _PROTOTYPE(void donothing, (int sig));
00033
00034 static int ftpcomm_fd;
00035 static ipaddr_t myip;
00036 static ipaddr_t hostip;
00037 static char host[256];
00038 static int lpid;
00039
00040 void NETinit()
00041 {
00042 int s;
00043 char *tcp_device;
00044 int tcp_fd;
00045 nwio_tcpconf_t nwio_tcpconf;
00046
00047
00048
00049 if((tcp_device = getenv("TCP_DEVICE")) == (char *)NULL)
00050 tcp_device = TCP_DEVICE;
00051
00052 tcp_fd = open(tcp_device, O_RDWR);
00053 if(tcp_fd < 0) {
00054 perror("ftp: Could not open tcp_device");
00055 exit(-1);
00056 }
00057 s = ioctl(tcp_fd, NWIOGTCPCONF, &nwio_tcpconf);
00058 if(s < 0) {
00059 perror("ftp: Could not get tcp configuration");
00060 exit(-1);
00061 }
00062
00063 myip = nwio_tcpconf.nwtc_locaddr;
00064
00065 close(tcp_fd);
00066 }
00067
00068 int DOopen()
00069 {
00070 nwio_tcpconf_t tcpconf;
00071 nwio_tcpcl_t tcpcopt;
00072 char *tcp_device;
00073 tcpport_t port;
00074 int s;
00075 struct hostent *hp;
00076 struct servent *servent;
00077
00078 if(linkopen) {
00079 printf("Use \"CLOSE\" to close the connection first.\n");
00080 return(0);
00081 }
00082
00083 if(cmdargc < 2)
00084 readline("Host: ", host, sizeof(host));
00085 else
00086 strncpy(host, cmdargv[1], sizeof(host));
00087
00088 if((servent = getservbyname("ftp", "tcp")) == (struct servent *)NULL) {
00089 fprintf(stderr, "ftp: Could not find ftp tcp service\n");
00090 return(-1);
00091 }
00092 port = (tcpport_t)servent->s_port;
00093
00094 hp = gethostbyname(host);
00095 if (hp == (struct hostent *)NULL) {
00096 hostip = (ipaddr_t)0;
00097 printf("Unresolved host %s\n", host);
00098 return(0);
00099 } else
00100 memcpy((char *) &hostip, (char *) hp->h_addr, hp->h_length);
00101
00102
00103
00104 if(hostip == inet_addr("127.0.0.1"))
00105 hostip = myip;
00106
00107 if((tcp_device = getenv("TCP_DEVICE")) == NULL)
00108 tcp_device = "/dev/tcp";
00109
00110 if((ftpcomm_fd = open(tcp_device, O_RDWR)) < 0) {
00111 perror("ftp: open error on tcp device");
00112 return(-1);
00113 }
00114
00115 tcpconf.nwtc_flags = NWTC_LP_SEL | NWTC_SET_RA | NWTC_SET_RP;
00116 tcpconf.nwtc_remaddr = hostip;
00117 tcpconf.nwtc_remport = port;
00118
00119 s = ioctl(ftpcomm_fd, NWIOSTCPCONF, &tcpconf);
00120 if(s < 0) {
00121 perror("ftp: ioctl error on NWIOSTCPCONF");
00122 close(ftpcomm_fd);
00123 return(s);
00124 }
00125
00126 tcpcopt.nwtcl_flags = 0;
00127
00128 s = ioctl(ftpcomm_fd, NWIOTCPCONN, &tcpcopt);
00129 if(s < 0) {
00130 perror("ftp: ioctl error on NWIOTCPCONN");
00131 close(ftpcomm_fd);
00132 return(s);
00133 }
00134
00135 s = ioctl(ftpcomm_fd, NWIOGTCPCONF, &tcpconf);
00136 if(s < 0) {
00137 perror("ftp: ioctl error on NWIOGTCPCONF");
00138 close(ftpcomm_fd);
00139 return(s);
00140 }
00141
00142 fpcommin = fdopen(ftpcomm_fd, "r");
00143 fpcommout = fdopen(ftpcomm_fd, "w");
00144
00145 s = DOgetreply();
00146
00147 if(s < 0) {
00148 fclose(fpcommin);
00149 fclose(fpcommout);
00150 close(ftpcomm_fd);
00151 return(s);
00152 }
00153
00154 if(s != 220) {
00155 fclose(fpcommin);
00156 fclose(fpcommout);
00157 close(ftpcomm_fd);
00158 return(0);
00159 }
00160
00161 linkopen = 1;
00162
00163 return(s);
00164 }
00165
00166 int DOclose()
00167 {
00168 if(!linkopen) {
00169 printf("You can't close a connection that isn't open.\n");
00170 return(0);
00171 }
00172
00173 fclose(fpcommin);
00174 fclose(fpcommout);
00175 close(ftpcomm_fd);
00176
00177 linkopen = 0;
00178 loggedin = 0;
00179
00180 return(0);
00181 }
00182
00183 int DOquit()
00184 {
00185 int s;
00186
00187 if(linkopen) {
00188 s = DOcommand("QUIT", "");
00189 s = DOclose();
00190 }
00191
00192 printf("FTP done.\n");
00193
00194 exit(0);
00195 }
00196
00197 void donothing(sig)
00198 int sig;
00199 {
00200 }
00201
00202 int DOdata(datacom, file, direction, fd)
00203 char *datacom;
00204 char *file;
00205 int direction;
00206 int fd;
00207 {
00208 nwio_tcpconf_t tcpconf;
00209 nwio_tcpcl_t tcplopt, tcpcopt;
00210 char *tcp_device;
00211 int ftpdata_fd;
00212 char *buff;
00213 ipaddr_t ripaddr;
00214 tcpport_t rport;
00215 static tcpport_t lport = HTONS(0xF000);
00216 int s;
00217 int i;
00218 int cs;
00219 int pfd[2];
00220 char dummy;
00221 char port[32];
00222
00223 ripaddr = hostip;
00224 rport = HTONS(20);
00225
00226
00227
00228
00229 if((tcp_device = getenv("TCP_DEVICE")) == NULL)
00230 tcp_device = "/dev/tcp";
00231
00232 if((ftpdata_fd = open(tcp_device, O_RDWR)) < 0) {
00233 perror("ftp: open error on tcp device");
00234 return(-1);
00235 }
00236
00237 if(passive) {
00238 s = DOcommand("PASV", "");
00239 if(s != 227) {
00240 close(ftpdata_fd);
00241 return(s);
00242 }
00243
00244 buff = reply;
00245 while(*buff && (*buff != '(')) buff++;
00246 buff++;
00247 ripaddr = (ipaddr_t)0;
00248 for(i = 0; i < 4; i++) {
00249 ripaddr = (ripaddr << 8) + (ipaddr_t)atoi(buff);
00250 if((buff = strchr(buff, ',')) == (char *)0) {
00251 printf("Could not parse PASV reply\n");
00252 return(-1);
00253 }
00254 buff++;
00255 }
00256 rport = (tcpport_t)atoi(buff);
00257 if((buff = strchr(buff, ',')) == (char *)0) {
00258 printf("Could not parse PASV reply\n");
00259 return(-1);
00260 }
00261 buff++;
00262 rport = (rport << 8) + (tcpport_t)atoi(buff);
00263 ripaddr = ntohl(ripaddr);
00264 rport = ntohs(rport);
00265 }
00266
00267 for (;;) {
00268 tcpconf.nwtc_flags = NWTC_SET_RA | NWTC_SET_RP;
00269 if (passive || ntohs(lport) >= 0xF000) {
00270 tcpconf.nwtc_flags |= NWTC_LP_SEL;
00271 } else {
00272
00273
00274
00275 lport = htons(ntohs(lport) + 1);
00276 tcpconf.nwtc_flags |= NWTC_LP_SET;
00277 tcpconf.nwtc_locport = lport;
00278 }
00279
00280 tcpconf.nwtc_remaddr = ripaddr;
00281 tcpconf.nwtc_remport = rport;
00282
00283 s = ioctl(ftpdata_fd, NWIOSTCPCONF, &tcpconf);
00284 if(s < 0) {
00285 if (errno == EADDRINUSE) continue;
00286 perror("ftp: ioctl error on NWIOSTCPCONF");
00287 close(ftpdata_fd);
00288 return(s);
00289 }
00290 break;
00291 }
00292
00293 s = ioctl(ftpdata_fd, NWIOGTCPCONF, &tcpconf);
00294 if(s < 0) {
00295 perror("ftp: ioctl error on NWIOGTCPCONF");
00296 close(ftpdata_fd);
00297 return(s);
00298 }
00299 lport = tcpconf.nwtc_locport;
00300
00301 if(passive) {
00302 tcplopt.nwtcl_flags = 0;
00303 s = ioctl(ftpdata_fd, NWIOTCPCONN, &tcpcopt);
00304 if(s < 0) {
00305 perror("ftp: error on ioctl NWIOTCPCONN");
00306 close(ftpdata_fd);
00307 return(0);
00308 }
00309 s = ioctl(ftpdata_fd, NWIOGTCPCONF, &tcpconf);
00310 if(s < 0) {
00311 perror("ftp: error on ioctl NWIOGTCPCONF");
00312 close(ftpdata_fd);
00313 return(0);
00314 }
00315 } else {
00316 tcplopt.nwtcl_flags = 0;
00317
00318 if (pipe(pfd) < 0) {
00319 perror("ftp: could not create a pipe");
00320 return(s);
00321 }
00322 lpid = fork();
00323 if(lpid < 0) {
00324 perror("ftp: could not fork listener");
00325 close(ftpdata_fd);
00326 close(pfd[0]);
00327 close(pfd[1]);
00328 return(s);
00329 } else if(lpid == 0) {
00330 close(pfd[0]);
00331 signal(SIGALRM, donothing);
00332 alarm(15);
00333 close(pfd[1]);
00334 s = ioctl(ftpdata_fd, NWIOTCPLISTEN, &tcplopt);
00335 alarm(0);
00336 if(s < 0)
00337 if(errno == EINTR)
00338 exit(1);
00339 else
00340 exit(-1);
00341 else
00342 exit(0);
00343 }
00344
00345 close(pfd[1]);
00346 (void) read(pfd[0], &dummy, 1);
00347 close(pfd[0]);
00348 while(1) {
00349 signal(SIGALRM, donothing);
00350 alarm(1);
00351 s = ioctl(ftpdata_fd, NWIOGTCPCONF, &tcpconf);
00352 alarm(0);
00353 if(s == -1) break;
00354 }
00355 }
00356
00357 #define hiword(x) ((u16_t)((x) >> 16))
00358 #define loword(x) ((u16_t)(x & 0xffff))
00359 #define hibyte(x) (((x) >> 8) & 0xff)
00360 #define lobyte(x) ((x) & 0xff)
00361
00362 if(!passive) {
00363 sprintf(port, "%u,%u,%u,%u,%u,%u",
00364 hibyte(hiword(ntohl(myip))), lobyte(hiword(ntohl(myip))),
00365 hibyte(loword(ntohl(myip))), lobyte(loword(ntohl(myip))),
00366 hibyte(ntohs(lport)), lobyte(ntohs(lport)));
00367 s = DOcommand("PORT", port);
00368 if(s != 200) {
00369 close(ftpdata_fd);
00370 kill(lpid, SIGKILL);
00371 return(s);
00372 }
00373 }
00374
00375 s = DOcommand(datacom, file);
00376 if(s == 125 || s == 150) {
00377 if(!passive) {
00378 while(1) {
00379 s = wait(&cs);
00380 if(s < 0 || s == lpid)
00381 break;
00382 }
00383 if(s < 0) {
00384 perror("wait error:");
00385 close(ftpdata_fd);
00386 kill(lpid, SIGKILL);
00387 return(s);
00388 }
00389 if((cs & 0x00ff)) {
00390 printf("Child listener failed %04x\n", cs);
00391 close(ftpdata_fd);
00392 return(-1);
00393 }
00394 cs = (cs >> 8) & 0x00ff;
00395 if(cs == 1) {
00396 printf("Child listener timed out\n");
00397 return(DOgetreply());
00398 } else if(cs) {
00399 printf("Child listener returned %02x\n", cs);
00400 close(ftpdata_fd);
00401 return(-1);
00402 }
00403 }
00404 switch(direction) {
00405 case RETR:
00406 s = recvfile(fd, ftpdata_fd);
00407 break;
00408 case STOR:
00409 s = sendfile(fd, ftpdata_fd);
00410 break;
00411 }
00412 close(ftpdata_fd);
00413 s = DOgetreply();
00414 } else {
00415 if(!passive)
00416 kill(lpid, SIGKILL);
00417 close(ftpdata_fd);
00418 }
00419
00420 return(s);
00421 }