source: trunk/minix/commands/ftpd200/net.c@ 15

Last change on this file since 15 was 9, checked in by Mattia Monga, 14 years ago

Minix 3.1.2a

File size: 9.5 KB
Line 
1/* net.c Copyright 1992-2000 by Michael Temari All Rights Reserved
2 *
3 * This file is part of ftpd.
4 *
5 * This file handles:
6 *
7 * PASV PORT
8 *
9 *
10 * 01/25/1995 Initial Release Michael Temari, <Michael@TemWare.Com>
11 * 02/09/2005 Initial Release Michael Temari, <Michael@TemWare.Com>
12 */
13
14#include <sys/types.h>
15#include <sys/ioctl.h>
16#include <sys/wait.h>
17#include <stdio.h>
18#include <stdlib.h>
19#include <string.h>
20#include <errno.h>
21#include <fcntl.h>
22#include <signal.h>
23#include <unistd.h>
24#include <time.h>
25#include <net/netlib.h>
26#include <net/hton.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>
33
34#include "ftpd.h"
35#include "access.h"
36#include "net.h"
37
38_PROTOTYPE(static void timeout, (int sig));
39
40static char *msg425 = "425-Could not open data connection.\r\n";
41static char *msg501 = "501 Syntax error in parameters.\r\n";
42
43static int gottimeout = 0;
44static int lpid = -1;
45static int didpassive = 0;
46
47/* they must be behind a firewall or using a web browser */
48int doPASV(buff)
49char *buff;
50{
51nwio_tcpconf_t tcpconf;
52nwio_tcpcl_t tcplopt;
53char *tcp_device;
54ipaddr_t ipaddr;
55tcpport_t lport;
56int s;
57time_t starttime;
58int retry;
59
60 if(ChkLoggedIn())
61 return(GOOD);
62
63 CleanUpPasv();
64
65 /* here we set up a connection to listen on */
66 if((tcp_device = getenv("TCP_DEVICE")) == NULL)
67 tcp_device = TCP_DEVICE;
68
69 if(ftpdata_fd >= 0) {
70 close(ftpdata_fd);
71 ftpdata_fd = -1;
72 }
73
74 if((ftpdata_fd = open(tcp_device, O_RDWR)) < 0) {
75 printf(msg425);
76 printf("425 Could not open tcp_device. Error %s\r\n", strerror(errno));
77 return(GOOD);
78 }
79
80 tcpconf.nwtc_flags = NWTC_LP_SEL | NWTC_SET_RA | NWTC_UNSET_RP;
81
82 tcpconf.nwtc_remaddr = rmtipaddr;
83 tcpconf.nwtc_remport = htons(0);
84 tcpconf.nwtc_locport = htons(0);
85
86 s = ioctl(ftpdata_fd, NWIOSTCPCONF, &tcpconf);
87 if(s < 0) {
88 printf(msg425);
89 printf("425 Could not ioctl NWIOSTCPCONF. Error %s\r\n", strerror(errno));
90 close(ftpdata_fd);
91 ftpdata_fd = -1;
92 return(GOOD);
93 }
94
95 s = ioctl(ftpdata_fd, NWIOGTCPCONF, &tcpconf);
96 if(s < 0) {
97 printf(msg425);
98 printf("425 Could not NWIOGTCPCONF. Error %s\r\n", strerror(errno));
99 close(ftpdata_fd);
100 ftpdata_fd = -1;
101 return(GOOD);
102 }
103 ipaddr = tcpconf.nwtc_locaddr;
104 lport = tcpconf.nwtc_locport;
105
106 /* Now lets fork a child to do the listening :-( */
107
108 tcplopt.nwtcl_flags = 0;
109
110 lpid = fork();
111 if(lpid < 0) {
112 printf(msg425);
113 printf("425 Could not fork listener. Error %s\r\n", strerror(errno));
114 close(ftpdata_fd);
115 ftpdata_fd = -1;
116 return(GOOD);
117 } else if(lpid == 0) {
118 retry = 0;
119 while(1) {
120#ifdef DEBUG
121 fprintf(logfile, "ftpd: child %d parent %d listen try %d\n", getpid(), getppid(), retry);
122 fflush(logfile);
123#endif
124 s = ioctl(ftpdata_fd, NWIOTCPLISTEN, &tcplopt);
125 if(!(s == -1 && errno == EAGAIN)) break;
126 if(retry++ > 10) break;
127 sleep(1);
128 }
129#ifdef DEBUG
130 fprintf(logfile, "ftpd: child %d s %d errno %d\n", getpid(), s, errno);
131 fflush(logfile);
132#endif
133 if(s < 0)
134 exit(errno); /* tells parent listen failed */
135 else
136 exit(0); /* tells parent listen okay */
137 }
138
139#ifdef DEBUG
140 fprintf(logfile, "ftpd: parent %d wait for %d\n", getpid(), lpid);
141 fflush(logfile);
142#endif
143
144 /* wait for child to be listening, no more than serveral seconds */
145 (void) time(&starttime);
146 while(1) {
147 if(time((time_t *)NULL) > (starttime + 15)) break;
148 signal(SIGALRM, timeout);
149 alarm(1);
150 s = ioctl(ftpdata_fd, NWIOGTCPCONF, &tcpconf);
151#ifdef DEBUG
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));
154 fflush(logfile);
155#endif
156 alarm(0);
157 if(s == -1) break;
158 sleep(1);
159 }
160
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)
165
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)));
170
171#ifdef DEBUG
172 fprintf(logfile, "ftpd: parent %d child %d send 227\n", getpid(), lpid);
173 fflush(logfile);
174#endif
175
176 didpassive = -1;
177
178 return(GOOD);
179}
180
181/* they want us to connect here */
182int doPORT(buff)
183char *buff;
184{
185u32_t ipaddr;
186u16_t port;
187int i;
188
189 if(ftpdata_fd >= 0) {
190 close(ftpdata_fd);
191 ftpdata_fd = -1;
192 }
193
194 ipaddr = (u32_t)0;
195 for(i = 0; i < 4; i++) {
196 ipaddr = (ipaddr << 8) + (u32_t)atoi(buff);
197 if((buff = strchr(buff, ',')) == (char *)0) {
198 printf(msg501);
199 return(GOOD);
200 }
201 buff++;
202 }
203 port = (u16_t)atoi(buff);
204 if((buff = strchr(buff, ',')) == (char *)0) {
205 printf(msg501);
206 return(0);
207 }
208 buff++;
209 port = (port << 8) + (u16_t)atoi(buff);
210
211 dataaddr = htonl(ipaddr);
212 dataport = htons(port);
213 if(dataaddr != rmtipaddr) {
214 printf(msg501);
215 return(GOOD);
216 }
217
218 printf("200 Port command okay.\r\n");
219
220 return(GOOD);
221}
222
223/* connect, huh? */
224int DataConnect()
225{
226nwio_tcpconf_t tcpconf;
227nwio_tcpcl_t tcpcopt;
228nwio_tcpcl_t tcplopt;
229char *tcp_device;
230int s, cs;
231int retry;
232
233 if(didpassive && ftpdata_fd >= 0) {
234 didpassive = 0;
235 gottimeout = 0;
236 signal(SIGALRM, timeout);
237 alarm(10);
238 while(!gottimeout) {
239 s = waitpid(lpid, &cs, 0);
240 if((s == lpid) || (s < 0 && errno == ECHILD)) break;
241#ifdef DEBUG
242 fprintf(logfile, "ftpd: parent %d child %d waitpid s %d cs %04x errno %d\n", getpid(), lpid, s, cs, errno);
243 fflush(logfile);
244#endif
245 }
246 alarm(0);
247#ifdef DEBUG
248 fprintf(logfile, "ftpd: parent %d child %d waitpid s %d cs %04x errno %d\n", getpid(), lpid, s, cs, errno);
249 fflush(logfile);
250#endif
251 if(gottimeout) {
252#ifdef DEBUG
253 fprintf(logfile, "ftpd: parent %d child %d got timeout\n", getpid(), lpid);
254 fflush(logfile);
255#endif
256 kill(lpid, SIGKILL);
257 s = waitpid(lpid, &cs, 0);
258 }
259#ifdef DEBUG
260 fprintf(logfile, "ftpd: parent %d child %d continuing\n", getpid(), lpid);
261 fflush(logfile);
262#endif
263 lpid = -1;
264 if(gottimeout) {
265 printf(msg425);
266 printf("425 Child listener timeout.\r\n");
267 close(ftpdata_fd);
268 ftpdata_fd = -1;
269 return(BAD);
270 }
271 if(s < 0) {
272 printf(msg425);
273 printf("425 Child listener vanished.\r\n");
274 close(ftpdata_fd);
275 ftpdata_fd = -1;
276 return(BAD);
277 }
278 if((cs & 0x00ff)) {
279 printf(msg425);
280 printf("425 Child listener failed %04x\r\n", cs);
281 close(ftpdata_fd);
282 ftpdata_fd = -1;
283 return(BAD);
284 }
285 cs = (cs >> 8) & 0x00ff;
286 if(cs) {
287 printf(msg425);
288 printf("425 Child listener error %s\r\n", strerror(cs));
289 close(ftpdata_fd);
290 ftpdata_fd = -1;
291 return(BAD);
292 }
293#ifdef DEBUG
294 fprintf(logfile, "ftpd: parent %d child %d pasv done\n", getpid(), lpid);
295 fflush(logfile);
296#endif
297 return(GOOD);
298 }
299
300 if(ftpdata_fd >= 0)
301 return(GOOD);
302
303 if((tcp_device = getenv("TCP_DEVICE")) == NULL)
304 tcp_device = TCP_DEVICE;
305
306 if((ftpdata_fd = open(tcp_device, O_RDWR)) < 0) {
307 printf(msg425);
308 printf("425 Could not open tcp_device. Error %s\r\n", strerror(errno));
309 return(BAD);
310 }
311
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);
316
317 s = ioctl(ftpdata_fd, NWIOSTCPCONF, &tcpconf);
318 if(s < 0) {
319 printf(msg425);
320 printf("425 Could not ioctl NWIOSTCPCONF. Error %s\r\n", strerror(errno));
321 close(ftpdata_fd);
322 ftpdata_fd = -1;
323 return(BAD);
324 }
325
326 s = ioctl(ftpdata_fd, NWIOGTCPCONF, &tcpconf);
327 if(s < 0) {
328 printf(msg425);
329 printf("425 Could not ioctl NWIOGTCPCONF. Error %s\r\n", strerror(errno));
330 close(ftpdata_fd);
331 ftpdata_fd = -1;
332 return(BAD);
333 }
334
335 tcpcopt.nwtcl_flags = 0;
336
337 retry = 0;
338 do {
339#ifdef DEBUG
340 fprintf(logfile, "try connect\n"); fflush(logfile);
341 fflush(logfile);
342#endif
343 sleep(2);
344 s = ioctl(ftpdata_fd, NWIOTCPCONN, &tcpcopt);
345#ifdef DEBUG
346 fprintf(logfile, "after connect %d %d\n", s, errno);
347 fflush(logfile);
348#endif
349 if(!(s == -1 && errno == EAGAIN)) break;
350 if(retry++ > 10) break;
351 sleep(1);
352 } while(1);
353 if(s < 0) {
354 printf(msg425);
355 printf("425 Could not ioctl NWIOTCPCONN. Error %s\r\n", strerror(errno));
356 close(ftpdata_fd);
357 ftpdata_fd = -1;
358 return(BAD);
359 }
360
361 s = ioctl(ftpdata_fd, NWIOGTCPCONF, &tcpconf);
362 if(s < 0) {
363 printf(msg425);
364 printf("425 Could not ioctl NWIOGTCPCONF. Error %s\r\n", strerror(errno));
365 close(ftpdata_fd);
366 ftpdata_fd = -1;
367 return(BAD);
368 }
369
370 return(GOOD);
371}
372
373/* Clean up stuff we did to get a Pasv connection going */
374int CleanUpPasv()
375{
376int s, cs;
377
378 if(lpid >= 0) {
379 kill(lpid, SIGKILL);
380 while(1) {
381 s = waitpid(lpid, &cs, 0);
382 if(s == lpid || (s == -1 && errno == ECHILD))
383 break;
384 }
385 }
386
387 lpid = -1;
388
389 didpassive = 0;
390
391 return(GOOD);
392}
393
394void GetNetInfo()
395{
396nwio_tcpconf_t tcpconf;
397int s;
398struct hostent *hostent;
399
400 /* Ask the system what our hostname is. */
401 if(gethostname(myhostname, sizeof(myhostname)) < 0)
402 strcpy(myhostname, "unknown");
403
404 /* lets get our ip address and the clients ip address */
405 s = ioctl(0, NWIOGTCPCONF, &tcpconf);
406 if(s < 0) {
407 printf("421 FTP service unable to get remote ip address. Closing.\r\n");
408 fflush(stdout);
409 exit(1);
410 }
411
412 myipaddr = tcpconf.nwtc_locaddr;
413 myport = tcpconf.nwtc_locport;
414 rmtipaddr = tcpconf.nwtc_remaddr;
415 rmtport = tcpconf.nwtc_remport;
416
417 /* Look up the host name of the remote host. */
418 hostent = gethostbyaddr((char *) &rmtipaddr, sizeof(rmtipaddr), AF_INET);
419 if(!hostent)
420 strcpy(rmthostname, inet_ntoa(rmtipaddr));
421 else {
422 strncpy(rmthostname, hostent->h_name, sizeof(rmthostname)-1);
423 rmthostname[sizeof(rmthostname)-1] = '\0';
424 }
425}
426
427static void timeout(sig)
428int sig;
429{
430 gottimeout = 1;
431}
Note: See TracBrowser for help on using the repository browser.