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 _PROTOTYPE(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 */
107 if((hostip
& NTOHL(0xFF000000)) == inet_addr("127.0.0.0"))
110 if((tcp_device
= getenv("TCP_DEVICE")) == NULL
)
111 tcp_device
= "/dev/tcp";
113 if((ftpcomm_fd
= open(tcp_device
, O_RDWR
)) < 0) {
114 perror("ftp: open error on tcp device");
118 tcpconf
.nwtc_flags
= NWTC_LP_SEL
| NWTC_SET_RA
| NWTC_SET_RP
;
119 tcpconf
.nwtc_remaddr
= hostip
;
120 tcpconf
.nwtc_remport
= port
;
122 s
= ioctl(ftpcomm_fd
, NWIOSTCPCONF
, &tcpconf
);
124 perror("ftp: ioctl error on NWIOSTCPCONF");
129 tcpcopt
.nwtcl_flags
= 0;
131 s
= ioctl(ftpcomm_fd
, NWIOTCPCONN
, &tcpcopt
);
133 perror("ftp: ioctl error on NWIOTCPCONN");
138 s
= ioctl(ftpcomm_fd
, NWIOGTCPCONF
, &tcpconf
);
140 perror("ftp: ioctl error on NWIOGTCPCONF");
165 printf("You can't close a connection that isn't open.\n");
182 s
= DOcommand("QUIT", "");
186 printf("FTP done.\n");
196 int DOdata(datacom
, file
, direction
, fd
)
199 int direction
; /* RETR or STOR */
202 nwio_tcpconf_t tcpconf
;
203 nwio_tcpcl_t tcplopt
, tcpcopt
;
205 static int ftpdata_fd
= -1;
209 static tcpport_t lport
= HTONS(0xF000);
220 printf("DOdata %s %s %d %d\n", datacom
, file
, direction
, fd
);
226 /* here we set up a connection to listen on if not passive mode */
227 /* otherwise we use this to connect for passive mode */
229 if((tcp_device
= getenv("TCP_DEVICE")) == NULL
)
230 tcp_device
= "/dev/tcp";
232 if(ftpdata_fd
>= 0 && mode
!= MODE_B
) {
237 wasopen
= (ftpdata_fd
>= 0);
240 printf("wasopen = %d\n", wasopen
);
247 printf("b4 open = %d\n", ftpdata_fd
);
251 if((ftpdata_fd
= open(tcp_device
, O_RDWR
)) < 0) {
252 perror("ftp: open error on tcp device");
257 printf("at open = %d\n", ftpdata_fd
);
262 printf("b4 PASV command\n");
264 s
= DOcommand("PASV", "");
266 printf("PASV command returned %d\n", s
);
273 /* decode host and port */
275 while(*buff
&& (*buff
!= '(')) buff
++;
277 ripaddr
= (ipaddr_t
)0;
278 for(i
= 0; i
< 4; i
++) {
279 ripaddr
= (ripaddr
<< 8) + (ipaddr_t
)atoi(buff
);
280 if((buff
= strchr(buff
, ',')) == (char *)0) {
281 printf("Could not parse PASV reply\n");
286 rport
= (tcpport_t
)atoi(buff
);
287 if((buff
= strchr(buff
, ',')) == (char *)0) {
288 printf("Could not parse PASV reply\n");
292 rport
= (rport
<< 8) + (tcpport_t
)atoi(buff
);
293 ripaddr
= ntohl(ripaddr
);
294 rport
= ntohs(rport
);
296 printf("PASV %08x %04x\n", ripaddr
, rport
);
301 tcpconf
.nwtc_flags
= NWTC_SET_RA
| NWTC_SET_RP
;
302 if(passive
|| ntohs(lport
) >= 0xF000) {
303 tcpconf
.nwtc_flags
|= NWTC_LP_SEL
;
305 /* For no good reason Sun hosts don't like it if they have to
306 * connect to the same port twice in a short time...
308 lport
= htons(ntohs(lport
) + 1);
309 tcpconf
.nwtc_flags
|= NWTC_LP_SET
;
310 tcpconf
.nwtc_locport
= lport
;
313 tcpconf
.nwtc_remaddr
= ripaddr
;
314 tcpconf
.nwtc_remport
= rport
;
317 printf("b4 STCPCONF locport = %d\n", lport
);
320 s
= ioctl(ftpdata_fd
, NWIOSTCPCONF
, &tcpconf
);
322 printf("at STCPCONF %d %d\n", s
, errno
);
325 if(errno
== EADDRINUSE
) continue;
326 perror("ftp: ioctl error on NWIOSTCPCONF");
335 printf("b4 GTCPCONF\n");
337 s
= ioctl(ftpdata_fd
, NWIOGTCPCONF
, &tcpconf
);
339 printf("at GTCPCONF %d %d\n", s
, errno
);
342 perror("ftp: ioctl error on NWIOGTCPCONF");
347 lport
= tcpconf
.nwtc_locport
;
350 printf("lport = %04x\n", lport
);
354 /* passive mode we connect to them */
355 tcplopt
.nwtcl_flags
= 0;
357 printf("Doing TCPCONN\n");
359 s
= ioctl(ftpdata_fd
, NWIOTCPCONN
, &tcpcopt
);
361 printf("TCPCONN %d %d\n", s
, errno
);
364 perror("ftp: error on ioctl NWIOTCPCONN");
370 printf("GTCPCONF\n");
372 s
= ioctl(ftpdata_fd
, NWIOGTCPCONF
, &tcpconf
);
374 printf("GTCPCONF %d %d\n", s
, errno
);
377 perror("ftp: error on ioctl NWIOGTCPCONF");
383 /* we listen for them */
384 tcplopt
.nwtcl_flags
= 0;
390 perror("ftp: could not create a pipe");
397 perror("ftp: could not fork listener");
403 } else if(lpid
== 0) {
405 printf("Child here\n");
408 signal(SIGALRM
, donothing
);
412 printf("child TCPLISTEN\n");
414 s
= ioctl(ftpdata_fd
, NWIOTCPLISTEN
, &tcplopt
);
417 printf("listen %d %d\n", s
, errno
);
420 exit(errno
); /* error */
422 exit(0); /* connection made */
425 printf("Fork = %d\n", lpid
);
427 /* Wait for the pipe to close, then the listener is ready (almost). */
429 (void) read(pfd
[0], &dummy
, 1);
432 wpid
= waitpid(lpid
, &cs
, WNOHANG
);
434 printf("waitpid %d %d\n", wpid
, cs
);
435 printf("GTCPCONF loop\n");
438 signal(SIGALRM
, donothing
);
440 s
= ioctl(ftpdata_fd
, NWIOGTCPCONF
, &tcpconf
);
443 printf("GTCPCONF loop %d %d\n", s
, errno
);
449 printf("GTCPCONF = %d\n", s
);
453 #define hiword(x) ((u16_t)((x) >> 16))
454 #define loword(x) ((u16_t)(x & 0xffff))
455 #define hibyte(x) (((x) >> 8) & 0xff)
456 #define lobyte(x) ((x) & 0xff)
462 cs
= (cs
>> 8) & 0x00ff;
463 printf("Child listener error %s\n", strerror(cs
));
466 sprintf(port
, "%u,%u,%u,%u,%u,%u",
467 hibyte(hiword(ntohl(myip
))), lobyte(hiword(ntohl(myip
))),
468 hibyte(loword(ntohl(myip
))), lobyte(loword(ntohl(myip
))),
469 hibyte(ntohs(lport
)), lobyte(ntohs(lport
)));
471 printf("sending port command %s\n", port
);
473 s
= DOcommand("PORT", port
);
475 printf("port command = %d\n", s
);
489 printf("doing data command %s %s\n", datacom
, file
);
491 s
= DOcommand(datacom
, file
);
493 printf("do command reply %d\n", s
);
495 if(s
== 125 || s
== 150) {
496 if(!passive
&& !wasopen
) {
499 printf("Waiting for child %d\n", lpid
);
503 printf("Wait returned %d cs=%d errno=%d\n", s
, cs
, errno
);
505 if(s
< 0 || s
== lpid
)
509 perror("wait error:");
517 printf("Child listener failed %04x\n", cs
);
522 cs
= (cs
>> 8) & 0x00ff;
524 printf("Child listener error %s\n", strerror(cs
));
527 return(DOgetreply());
531 printf("Before recvfile/sendfile call\n");
535 s
= recvfile(fd
, ftpdata_fd
);
538 s
= sendfile(fd
, ftpdata_fd
);
542 printf("send/recieve %d\n", s
);
551 printf("send/recieve reply %d\n", s
);
553 if(mode
== MODE_B
&& s
== 226) {