1 /* net.c Copyright 1992-2000 by Michael Temari All Rights Reserved
3 * This file is part of ftp.
6 * 01/25/96 Initial Release Michael Temari, <Michael@TemWare.Com>
10 #include <sys/ioctl.h>
20 #include <net/netlib.h>
22 #include <net/gen/netdb.h>
23 #include <net/gen/in.h>
24 #include <net/gen/inet.h>
25 #include <net/gen/tcp.h>
26 #include <net/gen/tcp_io.h>
32 void donothing(int sig
);
36 static ipaddr_t hostip
;
37 static char host
[256];
45 nwio_tcpconf_t nwio_tcpconf
;
47 /* All this just to get our ip address */
49 if((tcp_device
= getenv("TCP_DEVICE")) == (char *)NULL
)
50 tcp_device
= TCP_DEVICE
;
52 tcp_fd
= open(tcp_device
, O_RDWR
);
54 perror("ftp: Could not open tcp_device");
57 s
= ioctl(tcp_fd
, NWIOGTCPCONF
, &nwio_tcpconf
);
59 perror("ftp: Could not get tcp configuration");
63 myip
= nwio_tcpconf
.nwtc_locaddr
;
72 nwio_tcpconf_t tcpconf
;
78 struct servent
*servent
;
81 printf("Use \"CLOSE\" to close the connection first.\n");
86 if(readline("Host: ", host
, sizeof(host
)) < 0)
89 strncpy(host
, cmdargv
[1], sizeof(host
));
91 if((servent
= getservbyname("ftp", "tcp")) == (struct servent
*)NULL
) {
92 fprintf(stderr
, "ftp: Could not find ftp tcp service\n");
95 port
= (tcpport_t
)servent
->s_port
;
97 hp
= gethostbyname(host
);
98 if(hp
== (struct hostent
*)NULL
) {
100 printf("Unresolved host %s\n", host
);
103 memcpy((char *) &hostip
, (char *) hp
->h_addr
, hp
->h_length
);
105 /* This HACK allows the server to establish data connections correctly */
106 /* when using the loopback device to talk to ourselves */
108 if((hostip
& ntohl(0xFF000000)) == inet_addr("127.0.0.0"))
110 if((hostip
& NTOHL(0xFF000000)) == inet_addr("127.0.0.0"))
114 if((tcp_device
= getenv("TCP_DEVICE")) == NULL
)
115 tcp_device
= "/dev/tcp";
117 if((ftpcomm_fd
= open(tcp_device
, O_RDWR
)) < 0) {
118 perror("ftp: open error on tcp device");
122 tcpconf
.nwtc_flags
= NWTC_LP_SEL
| NWTC_SET_RA
| NWTC_SET_RP
;
123 tcpconf
.nwtc_remaddr
= hostip
;
124 tcpconf
.nwtc_remport
= port
;
126 s
= ioctl(ftpcomm_fd
, NWIOSTCPCONF
, &tcpconf
);
128 perror("ftp: ioctl error on NWIOSTCPCONF");
133 tcpcopt
.nwtcl_flags
= 0;
135 s
= ioctl(ftpcomm_fd
, NWIOTCPCONN
, &tcpcopt
);
137 perror("ftp: ioctl error on NWIOTCPCONN");
142 s
= ioctl(ftpcomm_fd
, NWIOGTCPCONF
, &tcpconf
);
144 perror("ftp: ioctl error on NWIOGTCPCONF");
169 printf("You can't close a connection that isn't open.\n");
186 s
= DOcommand("QUIT", "");
190 printf("FTP done.\n");
200 int DOdata(datacom
, file
, direction
, fd
)
203 int direction
; /* RETR or STOR */
206 nwio_tcpconf_t tcpconf
;
207 nwio_tcpcl_t tcplopt
, tcpcopt
;
209 static int ftpdata_fd
= -1;
213 static tcpport_t lport
;
223 lport
= htons(0xF000);
226 printf("DOdata %s %s %d %d\n", datacom
, file
, direction
, fd
);
236 /* here we set up a connection to listen on if not passive mode */
237 /* otherwise we use this to connect for passive mode */
239 if((tcp_device
= getenv("TCP_DEVICE")) == NULL
)
240 tcp_device
= "/dev/tcp";
242 if(ftpdata_fd
>= 0 && mode
!= MODE_B
) {
247 wasopen
= (ftpdata_fd
>= 0);
250 printf("wasopen = %d\n", wasopen
);
257 printf("b4 open = %d\n", ftpdata_fd
);
261 if((ftpdata_fd
= open(tcp_device
, O_RDWR
)) < 0) {
262 perror("ftp: open error on tcp device");
267 printf("at open = %d\n", ftpdata_fd
);
272 printf("b4 PASV command\n");
274 s
= DOcommand("PASV", "");
276 printf("PASV command returned %d\n", s
);
283 /* decode host and port */
285 while(*buff
&& (*buff
!= '(')) buff
++;
287 ripaddr
= (ipaddr_t
)0;
288 for(i
= 0; i
< 4; i
++) {
289 ripaddr
= (ripaddr
<< 8) + (ipaddr_t
)atoi(buff
);
290 if((buff
= strchr(buff
, ',')) == (char *)0) {
291 printf("Could not parse PASV reply\n");
296 rport
= (tcpport_t
)atoi(buff
);
297 if((buff
= strchr(buff
, ',')) == (char *)0) {
298 printf("Could not parse PASV reply\n");
302 rport
= (rport
<< 8) + (tcpport_t
)atoi(buff
);
303 ripaddr
= ntohl(ripaddr
);
304 rport
= ntohs(rport
);
306 printf("PASV %08x %04x\n", ripaddr
, rport
);
311 tcpconf
.nwtc_flags
= NWTC_SET_RA
| NWTC_SET_RP
;
312 if(passive
|| ntohs(lport
) >= 0xF000) {
313 tcpconf
.nwtc_flags
|= NWTC_LP_SEL
;
315 /* For no good reason Sun hosts don't like it if they have to
316 * connect to the same port twice in a short time...
318 lport
= htons(ntohs(lport
) + 1);
319 tcpconf
.nwtc_flags
|= NWTC_LP_SET
;
320 tcpconf
.nwtc_locport
= lport
;
323 tcpconf
.nwtc_remaddr
= ripaddr
;
324 tcpconf
.nwtc_remport
= rport
;
327 printf("b4 STCPCONF locport = %d\n", lport
);
330 s
= ioctl(ftpdata_fd
, NWIOSTCPCONF
, &tcpconf
);
332 printf("at STCPCONF %d %d\n", s
, errno
);
335 if(errno
== EADDRINUSE
) continue;
336 perror("ftp: ioctl error on NWIOSTCPCONF");
345 printf("b4 GTCPCONF\n");
347 s
= ioctl(ftpdata_fd
, NWIOGTCPCONF
, &tcpconf
);
349 printf("at GTCPCONF %d %d\n", s
, errno
);
352 perror("ftp: ioctl error on NWIOGTCPCONF");
357 lport
= tcpconf
.nwtc_locport
;
360 printf("lport = %04x\n", lport
);
364 /* passive mode we connect to them */
365 tcpcopt
.nwtcl_flags
= 0;
367 printf("Doing TCPCONN\n");
369 s
= ioctl(ftpdata_fd
, NWIOTCPCONN
, &tcpcopt
);
371 printf("TCPCONN %d %d\n", s
, errno
);
374 perror("ftp: error on ioctl NWIOTCPCONN");
380 printf("GTCPCONF\n");
382 s
= ioctl(ftpdata_fd
, NWIOGTCPCONF
, &tcpconf
);
384 printf("GTCPCONF %d %d\n", s
, errno
);
387 perror("ftp: error on ioctl NWIOGTCPCONF");
393 /* we listen for them */
394 tcplopt
.nwtcl_flags
= 0;
400 perror("ftp: could not create a pipe");
407 perror("ftp: could not fork listener");
413 } else if(lpid
== 0) {
415 printf("Child here\n");
418 signal(SIGALRM
, donothing
);
422 printf("child TCPLISTEN\n");
424 s
= ioctl(ftpdata_fd
, NWIOTCPLISTEN
, &tcplopt
);
427 printf("listen %d %d\n", s
, errno
);
430 exit(errno
); /* error */
432 exit(0); /* connection made */
435 printf("Fork = %d\n", lpid
);
437 /* Wait for the pipe to close, then the listener is ready (almost). */
439 (void) read(pfd
[0], &dummy
, 1);
442 wpid
= waitpid(lpid
, &cs
, WNOHANG
);
444 printf("waitpid %d %d\n", wpid
, cs
);
445 printf("GTCPCONF loop\n");
448 signal(SIGALRM
, donothing
);
450 s
= ioctl(ftpdata_fd
, NWIOGTCPCONF
, &tcpconf
);
453 printf("GTCPCONF loop %d %d\n", s
, errno
);
459 printf("GTCPCONF = %d\n", s
);
463 #define hiword(x) ((u16_t)((x) >> 16))
464 #define loword(x) ((u16_t)(x & 0xffff))
465 #define hibyte(x) (((x) >> 8) & 0xff)
466 #define lobyte(x) ((x) & 0xff)
472 cs
= (cs
>> 8) & 0x00ff;
473 printf("Child listener error %s\n", strerror(cs
));
476 sprintf(port
, "%u,%u,%u,%u,%u,%u",
477 hibyte(hiword(ntohl(myip
))), lobyte(hiword(ntohl(myip
))),
478 hibyte(loword(ntohl(myip
))), lobyte(loword(ntohl(myip
))),
479 hibyte(ntohs(lport
)), lobyte(ntohs(lport
)));
481 printf("sending port command %s\n", port
);
483 s
= DOcommand("PORT", port
);
485 printf("port command = %d\n", s
);
499 printf("doing data command %s %s\n", datacom
, file
);
501 s
= DOcommand(datacom
, file
);
503 printf("do command reply %d\n", s
);
505 if(s
== 125 || s
== 150) {
506 if(!passive
&& !wasopen
) {
509 printf("Waiting for child %d\n", lpid
);
513 printf("Wait returned %d cs=%d errno=%d\n", s
, cs
, errno
);
515 if(s
< 0 || s
== lpid
)
519 perror("wait error:");
527 printf("Child listener failed %04x\n", cs
);
532 cs
= (cs
>> 8) & 0x00ff;
534 printf("Child listener error %s\n", strerror(cs
));
537 return(DOgetreply());
541 printf("Before recvfile/sendfile call\n");
545 s
= recvfile(fd
, ftpdata_fd
);
548 s
= sendfile(fd
, ftpdata_fd
);
552 printf("send/recieve %d\n", s
);
561 printf("send/recieve reply %d\n", s
);
563 if(mode
== MODE_B
&& s
== 226) {