1 /* net.c Copyright 1992-2000 by Michael Temari All Rights Reserved
3 * This file is part of ftpd.
10 * 01/25/1995 Initial Release Michael Temari, <Michael@TemWare.Com>
11 * 02/09/2005 Initial Release Michael Temari, <Michael@TemWare.Com>
14 #include <sys/types.h>
15 #include <sys/ioctl.h>
25 #include <net/netlib.h>
27 #include <net/gen/in.h>
28 #include <net/gen/inet.h>
29 #include <net/gen/tcp.h>
30 #include <net/gen/tcp_io.h>
31 #include <net/gen/socket.h>
32 #include <net/gen/netdb.h>
38 _PROTOTYPE(static void timeout
, (int sig
));
40 static char *msg425
= "425-Could not open data connection.\r\n";
41 static char *msg501
= "501 Syntax error in parameters.\r\n";
43 static int gottimeout
= 0;
45 static int didpassive
= 0;
47 /* they must be behind a firewall or using a web browser */
51 nwio_tcpconf_t tcpconf
;
65 /* here we set up a connection to listen on */
66 if((tcp_device
= getenv("TCP_DEVICE")) == NULL
)
67 tcp_device
= TCP_DEVICE
;
74 if((ftpdata_fd
= open(tcp_device
, O_RDWR
)) < 0) {
76 printf("425 Could not open tcp_device. Error %s\r\n", strerror(errno
));
80 tcpconf
.nwtc_flags
= NWTC_LP_SEL
| NWTC_SET_RA
| NWTC_UNSET_RP
;
82 tcpconf
.nwtc_remaddr
= rmtipaddr
;
83 tcpconf
.nwtc_remport
= htons(0);
84 tcpconf
.nwtc_locport
= htons(0);
86 s
= ioctl(ftpdata_fd
, NWIOSTCPCONF
, &tcpconf
);
89 printf("425 Could not ioctl NWIOSTCPCONF. Error %s\r\n", strerror(errno
));
95 s
= ioctl(ftpdata_fd
, NWIOGTCPCONF
, &tcpconf
);
98 printf("425 Could not NWIOGTCPCONF. Error %s\r\n", strerror(errno
));
103 ipaddr
= tcpconf
.nwtc_locaddr
;
104 lport
= tcpconf
.nwtc_locport
;
106 /* Now lets fork a child to do the listening :-( */
108 tcplopt
.nwtcl_flags
= 0;
113 printf("425 Could not fork listener. Error %s\r\n", strerror(errno
));
117 } else if(lpid
== 0) {
121 fprintf(logfile
, "ftpd: child %d parent %d listen try %d\n", getpid(), getppid(), retry
);
124 s
= ioctl(ftpdata_fd
, NWIOTCPLISTEN
, &tcplopt
);
125 if(!(s
== -1 && errno
== EAGAIN
)) break;
126 if(retry
++ > 10) break;
130 fprintf(logfile
, "ftpd: child %d s %d errno %d\n", getpid(), s
, errno
);
134 exit(errno
); /* tells parent listen failed */
136 exit(0); /* tells parent listen okay */
140 fprintf(logfile
, "ftpd: parent %d wait for %d\n", getpid(), lpid
);
144 /* wait for child to be listening, no more than serveral seconds */
145 (void) time(&starttime
);
147 if(time((time_t *)NULL
) > (starttime
+ 15)) break;
148 signal(SIGALRM
, timeout
);
150 s
= ioctl(ftpdata_fd
, NWIOGTCPCONF
, &tcpconf
);
152 fprintf(logfile
, "ftpd: parent %d child %d s %d errno %d start %ld now %ld\n",
153 getpid(), lpid
, s
, errno
, starttime
, time((time_t *)NULL
));
161 #define hiword(x) ((u16_t)((x) >> 16))
162 #define loword(x) ((u16_t)(x & 0xffff))
163 #define hibyte(x) (((x) >> 8) & 0xff)
164 #define lobyte(x) ((x) & 0xff)
166 printf("227 Entering Passive Mode (%u,%u,%u,%u,%u,%u).\r\n",
167 hibyte(hiword(htonl(ipaddr
))), lobyte(hiword(htonl(ipaddr
))),
168 hibyte(loword(htonl(ipaddr
))), lobyte(loword(htonl(ipaddr
))),
169 hibyte(htons(lport
)), lobyte(htons(lport
)));
172 fprintf(logfile
, "ftpd: parent %d child %d send 227\n", getpid(), lpid
);
181 /* they want us to connect here */
189 if(ftpdata_fd
>= 0) {
195 for(i
= 0; i
< 4; i
++) {
196 ipaddr
= (ipaddr
<< 8) + (u32_t
)atoi(buff
);
197 if((buff
= strchr(buff
, ',')) == (char *)0) {
203 port
= (u16_t
)atoi(buff
);
204 if((buff
= strchr(buff
, ',')) == (char *)0) {
209 port
= (port
<< 8) + (u16_t
)atoi(buff
);
211 dataaddr
= htonl(ipaddr
);
212 dataport
= htons(port
);
213 if(dataaddr
!= rmtipaddr
) {
218 printf("200 Port command okay.\r\n");
226 nwio_tcpconf_t tcpconf
;
227 nwio_tcpcl_t tcpcopt
;
228 nwio_tcpcl_t tcplopt
;
233 if(didpassive
&& ftpdata_fd
>= 0) {
236 signal(SIGALRM
, timeout
);
239 s
= waitpid(lpid
, &cs
, 0);
240 if((s
== lpid
) || (s
< 0 && errno
== ECHILD
)) break;
242 fprintf(logfile
, "ftpd: parent %d child %d waitpid s %d cs %04x errno %d\n", getpid(), lpid
, s
, cs
, errno
);
248 fprintf(logfile
, "ftpd: parent %d child %d waitpid s %d cs %04x errno %d\n", getpid(), lpid
, s
, cs
, errno
);
253 fprintf(logfile
, "ftpd: parent %d child %d got timeout\n", getpid(), lpid
);
257 s
= waitpid(lpid
, &cs
, 0);
260 fprintf(logfile
, "ftpd: parent %d child %d continuing\n", getpid(), lpid
);
266 printf("425 Child listener timeout.\r\n");
273 printf("425 Child listener vanished.\r\n");
280 printf("425 Child listener failed %04x\r\n", cs
);
285 cs
= (cs
>> 8) & 0x00ff;
288 printf("425 Child listener error %s\r\n", strerror(cs
));
294 fprintf(logfile
, "ftpd: parent %d child %d pasv done\n", getpid(), lpid
);
303 if((tcp_device
= getenv("TCP_DEVICE")) == NULL
)
304 tcp_device
= TCP_DEVICE
;
306 if((ftpdata_fd
= open(tcp_device
, O_RDWR
)) < 0) {
308 printf("425 Could not open tcp_device. Error %s\r\n", strerror(errno
));
312 tcpconf
.nwtc_flags
= NWTC_LP_SET
| NWTC_SET_RA
| NWTC_SET_RP
;
313 tcpconf
.nwtc_remaddr
= dataaddr
;
314 tcpconf
.nwtc_remport
= dataport
;
315 tcpconf
.nwtc_locport
= htons(20);
317 s
= ioctl(ftpdata_fd
, NWIOSTCPCONF
, &tcpconf
);
320 printf("425 Could not ioctl NWIOSTCPCONF. Error %s\r\n", strerror(errno
));
326 s
= ioctl(ftpdata_fd
, NWIOGTCPCONF
, &tcpconf
);
329 printf("425 Could not ioctl NWIOGTCPCONF. Error %s\r\n", strerror(errno
));
335 tcpcopt
.nwtcl_flags
= 0;
340 fprintf(logfile
, "try connect\n"); fflush(logfile
);
344 s
= ioctl(ftpdata_fd
, NWIOTCPCONN
, &tcpcopt
);
346 fprintf(logfile
, "after connect %d %d\n", s
, errno
);
349 if(!(s
== -1 && errno
== EAGAIN
)) break;
350 if(retry
++ > 10) break;
355 printf("425 Could not ioctl NWIOTCPCONN. Error %s\r\n", strerror(errno
));
361 s
= ioctl(ftpdata_fd
, NWIOGTCPCONF
, &tcpconf
);
364 printf("425 Could not ioctl NWIOGTCPCONF. Error %s\r\n", strerror(errno
));
373 /* Clean up stuff we did to get a Pasv connection going */
381 s
= waitpid(lpid
, &cs
, 0);
382 if(s
== lpid
|| (s
== -1 && errno
== ECHILD
))
396 nwio_tcpconf_t tcpconf
;
398 struct hostent
*hostent
;
400 /* Ask the system what our hostname is. */
401 if(gethostname(myhostname
, sizeof(myhostname
)) < 0)
402 strcpy(myhostname
, "unknown");
404 /* lets get our ip address and the clients ip address */
405 s
= ioctl(0, NWIOGTCPCONF
, &tcpconf
);
407 printf("421 FTP service unable to get remote ip address. Closing.\r\n");
412 myipaddr
= tcpconf
.nwtc_locaddr
;
413 myport
= tcpconf
.nwtc_locport
;
414 rmtipaddr
= tcpconf
.nwtc_remaddr
;
415 rmtport
= tcpconf
.nwtc_remport
;
417 /* Look up the host name of the remote host. */
418 hostent
= gethostbyaddr((char *) &rmtipaddr
, sizeof(rmtipaddr
), AF_INET
);
420 strcpy(rmthostname
, inet_ntoa(rmtipaddr
));
422 strncpy(rmthostname
, hostent
->h_name
, sizeof(rmthostname
)-1);
423 rmthostname
[sizeof(rmthostname
)-1] = '\0';
427 static void timeout(sig
)