1 #define _GNU_SOURCE
2 #include "gatling.h"
3 
4 #include "socket.h"
5 #include "io.h"
6 #include "buffer.h"
7 #include "ip4.h"
8 #include "ip6.h"
9 #include "array.h"
10 #include "case.h"
11 #include "fmt.h"
12 #include "iob.h"
13 #include "str.h"
14 #include "scan.h"
15 #include "textcode.h"
16 #include "uint32.h"
17 #include "uint16.h"
18 #include "mmap.h"
19 #include "rangecheck.h"
20 #include <sys/types.h>
21 #include <sys/stat.h>
22 #include <sys/time.h>
23 #include <unistd.h>
24 #include <errno.h>
25 #ifndef __MINGW32__
26 #include <sys/resource.h>
27 #include <sys/socket.h>
28 #include <pwd.h>
29 #include <grp.h>
30 #include <netinet/in.h>
31 #include <netinet/tcp.h>
32 #include <sys/mman.h>
33 #include <fnmatch.h>
34 #include <sys/wait.h>
35 #endif
36 #include <stdlib.h>
37 #include <dirent.h>
38 #include <time.h>
39 #include <signal.h>
40 #include "version.h"
41 #include <assert.h>
42 #ifdef SUPPORT_SMB
43 #include <iconv.h>
44 #endif
45 #ifdef SUPPORT_PROXY
46 #include <regex.h>
47 #endif
48 #include <limits.h>
49 #include <fcntl.h>
50 #include <string.h>
51 #include <ctype.h>
52 // #include <crypt.h>
53 #include "havealloca.h"
54 #include "havesetresuid.h"
55 #include "dirfd.h"
56 
57 #include <stdio.h>
58 
59 #if !defined(__OPTIMIZE__) && defined(__linux__)
60 #include <sys/prctl.h>
61 #endif
62 
63 char serverroot[1024];
64 
65 #ifdef SUPPORT_MULTIPROC
66 unsigned long instances=1;
67 #endif
68 unsigned long timeout_secs=23;
69 tai6464 now,next;
70 
71 #ifdef TIMEOUT_DEBUG
new_io_timeout(int64 d,tai6464 t)72 void new_io_timeout(int64 d,tai6464 t) {
73   struct taia now;
74   struct taia diff;
75   taia_now(&now);
76   taia_sub(&diff,&t,&now);
77   buffer_puts(buffer_2,"DEBUG: scheduling timeout for fd #");
78   buffer_putlonglong(buffer_2,d);
79   buffer_puts(buffer_2," in ");
80   buffer_putlonglong(buffer_2,diff.sec.x);
81   buffer_putsflush(buffer_2," seconds.\n");
82   io_timeout(d,t);
83 }
84 
new_io_timeouted()85 int64 new_io_timeouted() {
86   int64 x=io_timeouted();
87   buffer_puts(buffer_2,"DEBUG: io_timeouted called, returned ");
88   buffer_putlonglong(buffer_2,x);
89   buffer_putnlflush(buffer_2);
90   return x;
91 }
92 
93 #define io_timeout new_io_timeout
94 #define io_timeouted new_io_timeouted
95 #endif
96 
97 const char months[] = "JanFebMarAprMayJunJulAugSepOctNovDec";
98 
99 #ifdef SUPPORT_CGI
100 int forksock[2];
101 #endif
102 
103 #if defined(__OpenBSD__) || defined(__NetBSD__)
104 #define __broken_itojun_v6__
105 #endif
106 
107 int virtual_hosts;
108 int transproxy;
109 int directory_index;
110 int logging;
111 int nouploads;
112 int chmoduploads;
113 #ifdef __MINGW32__
114 char origdir[PATH_MAX];
115 #else
116 int64 origdir;
117 #endif
118 
119 #ifdef SUPPORT_SMB
120 char workgroup[20]="FNORD";
121 int wglen;
122 char workgroup_utf16[100];
123 int wglen16;
124 #endif
125 
carp(const char * routine)126 static void carp(const char* routine) {
127   buffer_putmflush(buffer_2,routine,": ",strerror(errno),"\n");
128 }
129 
panic(const char * routine)130 static void panic(const char* routine) {
131   carp(routine);
132   exit(111);
133 }
134 
135 unsigned long connections;
136 unsigned long http_connections, https_connections, ftp_connections, smb_connections;
137 unsigned long cps,cps1;	/* connections per second */
138 unsigned long rps,rps1;	/* requests per second */
139 unsigned long eps,eps1;	/* events per second */
140 unsigned long long tin,tin1;	/* traffic inbound */
141 unsigned long long tout,tout1;	/* traffic outbound */
142 
143 
144 #ifdef SUPPORT_THREADED_OPEN
145 unsigned int threads;
146 int threadpipe_query[2];
147 int threadpipe_response[2];
148 
worker_thread(void * unused)149 void* worker_thread(void* unused) {
150   int src=threadpipe_query[0];
151   int dest=threadpipe_response[1];
152   (void)unused;
153   for (;;) {
154     int fd;
155     struct http_data* x;
156     if (read(src,&fd,sizeof(fd))!=fd) return 0;
157     x=io_getcookie(fd);
158     if (!x) continue;
159     if (fchdir(x->cwd)==-1) continue;
160     x->filefd=open(x->name_of_file_to_open,O_RDONLY);
161     write(dest,&fd,sizeof(fd));
162   }
163 }
164 
init_threads(int n)165 void init_threads(int n) {
166   threads=0;
167   if (n<=0) return;
168   if (threads>0) {
169     int i;
170     if (pipe(threadpipe_query)==-1 || pipe(threadpipe_response)==-1) return;
171     for (i=0; i<n; ++i) {
172       pthread_t tmp;
173       pthread_create(&tmp,0,worker_thread,0);
174       pthread_detach(tmp);
175     }
176     threads=n;
177   }
178 }
179 #endif
180 
181 
182 #if defined(SUPPORT_PROXY) || defined(SUPPORT_CGI)
183 /* You configure a list of regular expressions, and if a request matches
184  * one of them, the request is forwarded to some other IP:port.  You can
185  * run another httpd there that can handle CGI, PHP, JSP and whatnot. */
186 struct cgi_proxy* cgis,* last;
187 
188 char** _envp;
189 
190 /* if port==0 then execute the CGI locally */
191 #endif
192 
193 #ifdef SUPPORT_CGI
add_cgi(const char * c)194 static int add_cgi(const char* c) {
195   struct cgi_proxy* x=malloc(sizeof(struct cgi_proxy));
196   if (!x) return -1;
197   byte_zero(x,sizeof(struct cgi_proxy));
198   if (!strcmp(c,"+x"))
199     x->file_executable=1;
200   else if (regcomp(&x->r,c,REG_EXTENDED)) {
201     free(x);
202     return -1;
203   }
204   if (!last)
205     cgis=x;
206   else
207     last->next=x;
208   last=x;
209   return 0;
210 }
211 #endif
212 
cleanup(int64 fd)213 void cleanup(int64 fd) {
214   struct http_data* h=io_getcookie(fd);
215   int buddyfd=-1;
216   if (h) {
217     buddyfd=h->buddy;
218 
219     if (h->t==HTTPREQUEST
220 #ifdef SUPPORT_FTP
221 	|| h->t==FTPCONTROL6 || h->t==FTPCONTROL4
222 #endif
223 #ifdef SUPPORT_SMB
224 	|| h->t==SMBREQUEST
225 #endif
226 #ifdef SUPPORT_HTTPS
227 	|| h->t==HTTPSREQUEST || h->t==HTTPSACCEPT || h->t==HTTPSPOST
228 #endif
229 	  ) --connections;
230     if (h->t==HTTPREQUEST
231 #ifdef SUPPORT_PROXY
232 	|| h->t==HTTPPOST
233 #endif
234 	) --http_connections;
235 #ifdef SUPPORT_FTP
236     if (h->t==FTPCONTROL4 || h->t==FTPCONTROL6) --ftp_connections;
237 #endif
238 #ifdef SUPPORT_SMB
239     if (h->t==SMBREQUEST) --smb_connections;
240 #endif
241 #ifdef SUPPORT_HTTPS
242     if (h->t==HTTPSREQUEST || h->t==HTTPSPOST || h->t==HTTPSACCEPT ||
243 	h->t==HTTPSACCEPT_CHECK || h->t==HTTPSRESPONSE) {
244       --https_connections;
245 #ifdef USE_OPENSSL
246       SSL_shutdown(h->ssl);
247 #endif
248     }
249 #endif
250 
251 #if defined(SUPPORT_FTP)
252     if (h->t==FTPSLAVE || h->t==FTPACTIVE || h->t==FTPPASSIVE) {
253       if (buddyfd!=-1) {
254 	struct http_data* b=io_getcookie(buddyfd);
255 	if (b)
256 	  b->buddy=-1;
257       }
258       buddyfd=-1;
259     }
260 #endif
261     if (h->filefd!=-1) io_close(h->filefd);
262     array_reset(&h->r);
263     iob_reset(&h->iob);
264 #if defined(SUPPORT_FTP) || defined(SUPPORT_SMB)
265     free(h->ftppath);
266 #endif
267 #ifdef SUPPORT_HTTPS
268 #ifdef USE_OPENSSL
269     if (h->ssl) SSL_free(h->ssl);
270 #endif
271 #ifdef USE_POLARSSL
272     if (h->ssldata) {
273       free_tls_ctx(h->ssldata);
274       free(h->ssldata);
275     }
276 #endif
277 #endif
278 #ifdef SUPPORT_SMB
279     close_all_handles(&h->h);
280 #endif
281     free(h);
282   }
283   io_close(fd);
284   if (buddyfd>=0) {
285     h=io_getcookie(buddyfd);
286     if (h) h->buddy=-1;
287     cleanup(buddyfd);
288   }
289 }
290 
header_complete(struct http_data * r,int64 sock)291 size_t header_complete(struct http_data* r,int64 sock) {
292   long i;
293   long l=array_bytes(&r->r);
294   const char* c=array_start(&r->r);
295   if (r->t==HTTPREQUEST
296 #ifdef SUPPORT_PROXY
297       || r->t==HTTPPOST
298 #endif
299 #ifdef SUPPORT_HTTPS
300       || r->t==HTTPSREQUEST || r->t==HTTPSPOST
301 #endif
302      )
303   {
304     /* first of all, in case someone is bombarding me with crap, detect
305      * that early so we can drop the connection */
306     if (l>10) {
307       tai6464 tarpit;
308       for (i=0; i<l; ++i) {
309 	if (c[i]==' ') goto ok;
310 	if (c[i]<'A' || c[i]>'Z') break;
311       }
312       /* detected invalid HTTP request */
313       if (logging) {
314 	char buf[100];
315 	buffer_puts(buffer_1,"close/not_http_traffic ");
316 	buffer_putulong(buffer_1,sock);
317 	buffer_putspace(buffer_1);
318 	buffer_put(buffer_1,buf,fmt_ip6c(buf,r->peerip));
319 	buffer_putnlflush(buffer_1);
320       }
321       io_dontwantread(sock);
322       io_dontwantwrite(sock);
323       --http_connections;
324       changestate(r,PUNISHMENT);
325       tarpit=now;
326       tarpit.sec.x+=10;
327       io_timeout(sock,tarpit);
328       return 0;
329     }
330 ok:
331 
332     /* Erdgeist nudged me into optimizing this :-)
333      * I'd be surprised if this optimization has any measurable
334      * advantage, but it sure is impressive */
335     for (i=0; i+1<l; i+=2) {
336       if (c[i+1]=='\n') {
337 	if (c[i]=='\n') return i+2;
338 	else if (c[i]=='\r' && i+3<l && c[i+2]=='\r' && c[i+3]=='\n')
339 	  return i+4;
340 	--i;
341       } else if (c[i+1]=='\r') {
342 	if (i+4<l && c[i+2]=='\n' && c[i+3]=='\r' && c[i+4]=='\n')
343 	  return i+5;
344 	--i;
345       }
346     }
347 
348 #ifdef SUPPORT_SMB
349   } else if (r->t==SMBREQUEST) {
350     /* SMB */
351     /* first four bytes are the NetBIOS session;
352      * byte 0: 0 ("session message"),
353      * bytes 1-3: message length (big endian) */
354     uint32 len;
355     if (c[0]!=0) {
356 //      printf("can't happen error: netbios byte 0 was not 0!?\n");
357       return 1;
358     }
359     len=uint32_read_big(c) & 0x00ffffff;
360     if (l>=len+4) return len+4;
361 #endif
362   } else {
363     /* FTP */
364     for (i=0; i<l; ++i)
365       if (c[i]=='\n')
366 	return i+1;
367   }
368   return 0;
369 }
370 
371 static char oom[]="HTTP/1.0 500 internal error\r\nContent-Type: text/plain\r\nConnection: close\r\n\r\nout of memory\n";
372 
httperror_realm(struct http_data * r,const char * title,const char * message,const char * realm,int nobody)373 void httperror_realm(struct http_data* r,const char* title,const char* message,const char* realm,int nobody) {
374   char* c;
375   if (r->t==HTTPSERVER4 || r->t==HTTPSERVER6 || r->t==HTTPREQUEST
376 #ifdef SUPPORT_HTTPS
377       || r->t==HTTPSSERVER4 || r->t==HTTPSSERVER6
378       || r->t==HTTPSREQUEST || r->t==HTTPSRESPONSE
379 #endif
380 								) {
381     c=r->hdrbuf=(char*)malloc(str_len(message)+str_len(title)+str_len(realm?realm:"")+300);
382     if (!c) {
383       r->hdrbuf=oom;
384       r->hlen=str_len(r->hdrbuf);
385       buffer_putsflush(buffer_1,"error_oom\n");
386       iob_addbuf(&r->iob,r->hdrbuf,r->hlen);
387     } else {
388       c+=fmt_str(c,"HTTP/1.0 ");
389       c+=fmt_str(c,title);
390       c+=fmt_str(c,"\r\nContent-Type: text/html\r\nConnection: ");
391       c+=fmt_str(c,r->keepalive?"keep-alive":"close");
392       c+=fmt_str(c,"\r\nServer: " RELEASE "\r\nContent-Length: ");
393       c+=fmt_ulong(c,str_len(message)+str_len(title)-4+17);
394       if (realm) {
395 	c+=fmt_str(c,"\r\nWWW-Authenticate: Basic realm=\"");
396 	c+=fmt_str(c,realm);
397 	c+=fmt_str(c,"\"");
398       }
399       c+=fmt_str(c,"\r\n\r\n");
400       if (!nobody) {
401 	c+=fmt_str(c,"<title>");
402 	c+=fmt_str(c,title+4);
403 	c+=fmt_str(c,"</title>\n");
404 	c+=fmt_str(c,message);
405 	c+=fmt_str(c,"\n");
406       }
407       r->hlen=c - r->hdrbuf;
408       iob_addbuf_free(&r->iob,r->hdrbuf,r->hlen);
409     }
410   } else {
411     /* FTP */
412     c=r->hdrbuf=(char*)malloc(str_len(title)+3);
413     c+=fmt_str(c,title);
414     c+=fmt_str(c,"\r\n");
415     r->hlen=c-r->hdrbuf;
416     iob_addbuf_free(&r->iob,r->hdrbuf,r->hlen);
417   }
418 }
419 
httperror(struct http_data * r,const char * title,const char * message,int nobody)420 void httperror(struct http_data* r,const char* title,const char* message,int nobody) {
421   httperror_realm(r,title,message,0,nobody);
422 }
423 
fmt_2digits(char * dest,int i)424 unsigned int fmt_2digits(char* dest,int i) {
425   dest[0]=(i/10)+'0';
426   dest[1]=(i%10)+'0';
427   return 2;
428 }
429 
430 
431 
432 #if 0
433  _     _   _
434 | |__ | |_| |_ _ __
435 | '_ \| __| __| '_ \
436 | | | | |_| |_| |_) |
437 |_| |_|\__|\__| .__/
438               |_|
439 #endif
440 
441 const char* mimetypesfilename;
442 
443 char* base;
444 
sort_name_a(de * x,de * y)445 int sort_name_a(de* x,de* y) { return (str_diff(base+x->name,base+y->name)); }
sort_name_d(de * x,de * y)446 int sort_name_d(de* x,de* y) { return (str_diff(base+y->name,base+x->name)); }
sort_mtime_a(de * x,de * y)447 int sort_mtime_a(de* x,de* y) { return x->ss.st_mtime-y->ss.st_mtime; }
sort_mtime_d(de * x,de * y)448 int sort_mtime_d(de* x,de* y) { return y->ss.st_mtime-x->ss.st_mtime; }
sort_size_a(de * x,de * y)449 int sort_size_a(de* x,de* y) { return x->ss.st_size-y->ss.st_size; }
sort_size_d(de * x,de * y)450 int sort_size_d(de* x,de* y) { return y->ss.st_size-x->ss.st_size; }
451 
452 
453 
454 #ifndef __MINGW32__
455 static uid_t __uid;
456 static gid_t __gid;
457 static int do_switch_uid;
458 
prepare_switch_uid(const char * new_uid)459 static int prepare_switch_uid(const char* new_uid) {
460   uid_t u=0;
461   gid_t g=0;
462   if (new_uid) {
463     if (new_uid[0]>='0' && new_uid[0]<='9') {
464       unsigned long l;
465       const char *c=new_uid+scan_ulong(new_uid,&l);
466       if (*c && *c!=':' && *c!='.') return -1;
467       if ((u=l)!=l) return -1; /* catch overflow */
468       if (*c) {
469 	++c;
470 	c=c+scan_ulong(c,&l);
471 	if ((g=l)!=l) return -1; /* catch overflow */
472 	if (*c) return -1;
473       }
474     } else {
475       struct passwd *p=getpwnam(new_uid);
476       if (!p) return -1;
477       u=p->pw_uid;
478       g=p->pw_gid;
479     }
480     __uid=u;
481     __gid=g;
482     do_switch_uid=1;
483   }
484   return 0;
485 }
486 
switch_uid()487 int switch_uid() {
488   if (!do_switch_uid) return 0;
489 #ifdef LIBC_HAS_SETRESUID
490   if (setresgid(__gid,__gid,__gid) ||
491       setgroups(1,&__gid) ||
492       setresuid(__uid,__uid,__uid))
493 #else
494   if (setgid(__gid) ||
495       setgroups(1,&__gid) ||
496       setuid(__uid))
497 #endif
498   {
499     /* if dropping privileges failed with EPERM, we are already running
500      * with reduced privileges.  Don't make a fuss about it then. */
501     if (errno==EPERM) return 0;
502     return -1;
503   }
504   return 0;
505 }
506 #endif
507 
508 static volatile int fini;
509 
sighandler(int sig)510 void sighandler(int sig) {
511   fini=(sig==SIGINT?1:2);	/* 2 for SIGHUP */
512 }
513 
514 
515 
is_server_connection(enum conntype t)516 static int is_server_connection(enum conntype t) {
517   return (t==HTTPSERVER6 || t==HTTPSERVER4
518 #ifdef SUPPORT_FTP
519 	|| t==FTPSERVER6 || t==FTPSERVER4
520 #endif
521 #ifdef SUPPORT_SMB
522 	|| t==SMBSERVER6 || t==SMBSERVER4
523 #endif
524 #ifdef SUPPORT_HTTPS
525 	|| t==HTTPSSERVER6 || t==HTTPSSERVER4
526 #endif
527 	);
528 }
529 
530 #ifdef __broken_itojun_v6__
531 #warning "working around idiotic openbse ipv6 stupidity - please kick itojun for this!"
532   int s4;		/* ipv4 http socket */
533 #ifdef SUPPORT_FTP
534   int f4;		/* ipv4 ftp socket */
535 #endif
536 #ifdef SUPPORT_HTTPS
537   int httpss4;		/* ipv4 https socket */
538 #endif
539 #endif
540 
541 #ifdef SUPPORT_HTTPS
542 char* sshd;
543 unsigned long ssh_timeout;
544 #endif
545 
546 int limit_to_lan;
547 
accept_server_connection(int64 i,struct http_data * H,unsigned long ftptimeout_secs,tai6464 nextftp)548 static void accept_server_connection(int64 i,struct http_data* H,unsigned long ftptimeout_secs,tai6464 nextftp) {
549   /* This is an FTP or HTTP(S) or SMB server connection.
550     * This read event means that someone connected to us.
551     * accept() the connection, establish connection type from
552     * server connection type, and put the new connection into the
553     * state table */
554   char ip[16];
555   uint16 port;
556   uint32 scope_id;
557   int n;
558 
559   while (1) {
560     int punk;
561 #ifdef __broken_itojun_v6__
562     if (H->t==HTTPSERVER4 || H->t==FTPSERVER4
563 #ifdef SUPPORT_SMB
564 					      || H->t==SMBSERVER4
565 #endif
566 #ifdef SUPPORT_HTTPS
567 					      || H->t==HTTPSSERVER4
568 #endif
569 								  ) {
570       byte_copy(ip,12,V4mappedprefix);
571       scope_id=0;
572       n=socket_accept4(i,ip+12,&port);
573     } else
574 #endif
575       n=socket_accept6(i,ip,&port,&scope_id);
576     if (n==-1) break;
577     punk=new_request_from_ip(ip,now.sec.x-4611686018427387914ULL)==1;
578     ++cps1;
579     ++connections;
580     if (logging) {
581       char buf[IP6_FMT];
582 
583       buffer_puts(buffer_1,punk?(timeout_secs?"dos_tarpit ":"dos_drop "):"accept ");
584       buffer_putulong(buffer_1,n);
585       buffer_puts(buffer_1," ");
586       buffer_put(buffer_1,buf,fmt_ip6c(buf,ip));
587       buffer_puts(buffer_1," ");
588       buffer_putulong(buffer_1,port);
589       buffer_puts(buffer_1," ");
590       buffer_putulong(buffer_1,connections-1);
591       buffer_puts(buffer_1," ");
592       {
593 	const char* service;
594 	switch (H->t) {
595 	case HTTPSERVER4:
596 	case HTTPSERVER6: service="http"; break;
597 #ifdef SUPPORT_HTTPS
598 	case HTTPSSERVER4:
599 	case HTTPSSERVER6: service="https"; break;
600 #endif
601 #ifdef SUPPORT_FTP
602 	case FTPSERVER4:
603 	case FTPSERVER6: service="ftp"; break;
604 #endif
605 #ifdef SUPPORT_SMB
606 	case SMBSERVER4:
607 	case SMBSERVER6: service="smb"; break;
608 #endif
609 	default: service="unk";
610 	}
611 	buffer_puts(buffer_1,service);
612       }
613       buffer_putnlflush(buffer_1);
614     }
615     if (limit_to_lan) {
616       int passed;
617       /* if the -L option is given, only accept connections from local
618        * or reserved IP ranges */
619       if (byte_equal(ip,12,V4mappedprefix)) {
620 	unsigned char* ip4=(unsigned char*)ip+12;
621 	passed = ip4[0]==127 ||	/* 127.0.0.1/8 */
622 	    ip4[0]==10 ||	/* RFC1918: 10.0.0.0/8 */
623 	    (ip4[0]==192 && ip4[1]==168) ||	/* RFC1918: 192.168.0.0/16 */
624 	    (ip4[0]==172 && ip4[1]>=16 && ip4[1]<=31) ||	/* RFC1918: 172.16.0.0/12 */
625 	    (ip4[0]==169 && ip4[1]==254 && ip4[2]!=0 && ip4[2]!=255);	/* RFC 5735: 169.254.0.0/16 */
626       } else {	/* IPv6 */
627 	unsigned char* ip6=(unsigned char*)ip;
628 	passed = byte_equal(ip6,16,V6loopback) ||	/* ::1 */
629 	  (ip6[0]==0xfc && (ip6[1]&0xfe)==0) ||	/* RF4193 ULA fc00::/7 */
630 	  (ip6[0]==0xfe && (ip6[1]&0xfc)==0xc0) ||	/* deprecated site-local */
631 	  (ip6[0]==0xfe && (ip6[1]&0xfc)==0x80);	/* RFC5735 link-local */
632       }
633       if (!passed) {
634 	timeout_secs=0;
635 	punk=1;
636 	if (logging) {
637 	  buffer_puts(buffer_1,"close/outside_lan_drop ");
638 	  buffer_putulong(buffer_1,n);
639 	  buffer_putnlflush(buffer_1);
640 	}
641       }
642     }
643     if (punk && !timeout_secs) {
644       io_close(n);
645       continue;
646     }
647 #ifdef SUPPORT_SERVERSTATUS
648     if (H->t==HTTPSERVER4 || H->t==HTTPSERVER6) ++http_connections;
649 #ifdef SUPPORT_HTTPS
650     if (H->t==HTTPSSERVER4 || H->t==HTTPSSERVER6) ++https_connections;
651 #endif
652 #ifdef SUPPORT_FTP
653     if (H->t==FTPSERVER4 || H->t==FTPSERVER6) ++ftp_connections;
654 #endif
655 #ifdef SUPPORT_SMB
656     if (H->t==SMBSERVER4 || H->t==SMBSERVER6) ++smb_connections;
657 #endif
658 #endif
659 
660 #ifdef TCP_NODELAY
661     {
662       int i=1;
663       setsockopt(n,IPPROTO_TCP,TCP_NODELAY,&i,sizeof(i));
664     }
665 #else
666 #warning TCP_NODELAY not defined
667 #endif
668 
669 #ifdef HAVE_IO_FD_FLAGS
670     if (io_fd_flags(n,IO_FD_CANWRITE|IO_FD_NONBLOCK))
671 #else
672     if (io_fd_canwrite(n))
673 #endif
674     {
675       struct http_data* h;
676       h=(struct http_data*)malloc(sizeof(struct http_data));
677       if (h) {
678 	io_nonblock(n);
679 	if (!punk) {
680 	  if (H->t==HTTPSERVER6 || H->t==HTTPSERVER4
681 #ifdef SUPPORT_SMB
682 	    || H->t==SMBSERVER6 || H->t==SMBSERVER4
683 #endif
684 #ifdef SUPPORT_HTTPS
685 	    || H->t==HTTPSSERVER6 || H->t==HTTPSSERVER4
686 #endif
687 	    )
688 	    io_wantread(n);
689 	  else
690 	    io_wantwrite(n);
691 	}
692 	byte_zero(h,sizeof(struct http_data));
693 #ifdef STATE_DEBUG
694 	h->myfd=n;
695 #endif
696 #ifdef __broken_itojun_v6__
697 	if (i==s4 || i==f4) {
698 	  byte_copy(h->myip,12,V4mappedprefix);
699 	  socket_local4(n,h->myip+12,&h->myport);
700 	} else
701 	  socket_local6(n,h->myip,&h->myport,0);
702 #else
703 	socket_local6(n,h->myip,&h->myport,0);
704 #endif
705 	byte_copy(h->peerip,16,ip);
706 	h->peerport=port;
707 	h->myscope_id=scope_id;
708 	if (punk) {
709 	  changestate(h,PUNISHMENT);
710 	  io_timeout(n,next);
711 	} else if (H->t==HTTPSERVER4 || H->t==HTTPSERVER6) {
712 	  changestate(h,HTTPREQUEST);
713 	  if (timeout_secs)
714 	    io_timeout(n,next);
715 #ifdef SUPPORT_HTTPS
716 	} else if (H->t==HTTPSSERVER4 || H->t==HTTPSSERVER6) {
717 #ifdef __MINGW32__
718 //	  printf("chdir(\"%s\") -> %d\n",origdir,chdir(origdir));
719 //	  chdir(origdir);
720 #else
721 	  fchdir(origdir);
722 #endif
723 #ifdef USE_OPENSSL
724 	  if (init_serverside_tls(&h->ssl,n))
725 #elif defined(USE_POLARSSL)
726 	  h->ssldata=malloc(sizeof(*h->ssldata));
727 	  if (!h->ssldata || init_serverside_tls(h->ssldata,n))
728 #endif
729 	  {
730 	    if (logging) {
731 	      char a[FMT_ULONG];
732 	      a[fmt_ulong(a,n)]=0;
733 	      buffer_putmflush(buffer_1,"ssl_setup_failed ",a," ",strerror(errno),"\nclose/readerr ",a,"\n");
734 	    }
735 	    cleanup(n);
736 	    continue;
737 	  }
738 
739 	  changestate(h,HTTPSACCEPT_CHECK);
740 	  if (timeout_secs)
741 	    io_timeout(n,nextftp);
742 #endif
743 #ifdef SUPPORT_SMB
744 	} else if (H->t==SMBSERVER4 || H->t==SMBSERVER6) {
745 	  changestate(h,SMBREQUEST);
746 	  if (timeout_secs)
747 	    io_timeout(n,next);
748 #endif
749 #ifdef SUPPORT_FTP
750 	} else {
751 	  if (H->t==FTPSERVER6)
752 	    changestate(h,FTPCONTROL6);
753 	  else
754 	    changestate(h,FTPCONTROL4);
755 	  iob_addbuf(&h->iob,"220 Hi there!\r\n",15);
756 	  h->keepalive=1;
757 	  if (ftptimeout_secs)
758 	    io_timeout(n,nextftp);
759 #endif
760 	}
761 	h->buddy=-1;
762 	h->filefd=-1;
763 	io_setcookie(n,h);
764       } else {
765 	buffer_puts(buffer_1,"close/malloc_failed ");
766 	buffer_putulong(buffer_1,n);
767 	buffer_putnlflush(buffer_1);
768 	io_close(n);
769       }
770     } else {
771       buffer_puts(buffer_1,"close/io_fd_canwrite_failed ");
772       buffer_putulong(buffer_1,n);
773       buffer_putnlflush(buffer_1);
774       io_close(n);
775     }
776 #ifdef SUPPORT_MULTIPROC
777     if (instances>1) break;
778 #endif
779   }
780   if (errno==EAGAIN)
781     io_eagain_read(i);
782   else
783 #ifdef __broken_itojun_v6__
784     carp(H->t==HTTPSERVER4||H->t==FTPSERVER4?"socket_accept4":"socket_accept6");
785 #else
786     if (errno==EINVAL) {
787       static int64 lasteinval;
788       if (lasteinval!=i) {
789 	lasteinval=i;
790 	carp("socket_accept6");
791       }
792     }
793 #endif
794 }
795 
796 #ifdef SUPPORT_HTTPS
797 
handle_ssl_error_code(int sock,int code,int reading)798 int handle_ssl_error_code(int sock,int code,int reading) {
799 #ifdef USE_POLARSSL
800   char errorbuf[256];
801 #endif
802 
803 //  printf("handle_ssl_error_code(sock %d,code %d,reading %d)\n",sock,code,reading);
804   switch (code) {
805 #ifdef USE_OPENSSL
806   case SSL_ERROR_WANT_READ:
807     io_eagain_read(sock);
808     io_wantread(sock);
809     io_dontwantwrite(sock);
810     return 0;
811   case SSL_ERROR_WANT_WRITE:
812     io_eagain_write(sock);
813     io_wantwrite(sock);
814     io_dontwantread(sock);
815     return 0;
816 #elif defined(USE_POLARSSL)
817   case MBEDTLS_ERR_SSL_WANT_READ:
818     io_eagain_read(sock);
819     io_wantread(sock);
820     io_dontwantwrite(sock);
821     return 0;
822   case MBEDTLS_ERR_SSL_WANT_WRITE:
823     io_eagain_write(sock);
824     io_wantwrite(sock);
825     io_dontwantread(sock);
826     return 0;
827 #endif
828 #ifdef USE_OPENSSL
829   case SSL_ERROR_SYSCALL:
830 #elif defined(USE_POLARSSL)
831   case MBEDTLS_ERR_NET_RECV_FAILED:
832   case MBEDTLS_ERR_NET_SEND_FAILED:
833   case MBEDTLS_ERR_NET_CONN_RESET:
834     errno=ECONNRESET;
835 #endif
836     // we already signal the error up and upsteam will then write an
837     // error message
838     return -1;
839   default:
840     if (logging) {
841       buffer_puts(buffer_1,"ssl_protocol_error ");
842       buffer_putulong(buffer_1,sock);
843 #ifdef USE_POLARSSL
844       mbedtls_strerror(code,errorbuf,sizeof(errorbuf));
845       buffer_putm(buffer_1," ",errorbuf);
846 #endif
847       buffer_puts(buffer_1,"\nclose/readerr ");
848       buffer_putulong(buffer_1,sock);
849       buffer_putnlflush(buffer_1);
850     }
851     errno=EPROTO;
852     return -1;
853   }
854 }
855 
do_sslaccept(int sock,struct http_data * h,int reading)856 void do_sslaccept(int sock,struct http_data* h,int reading) {
857   int r;
858   if (h->t == HTTPSACCEPT_CHECK) {
859     unsigned char buf[10];
860     changestate(h,HTTPSACCEPT);
861     /* now, try to peek into the buffer, and see if it looks like an SSL
862      * handshake */
863     r=recv(sock,buf,sizeof(buf),MSG_PEEK);
864     if (r>5) {
865       if (sshd && buf[0]=='S' && buf[1]=='S' && buf[2]=='H') {
866 	if (logging) {
867 	  char numbuf[FMT_ULONG];
868 	  numbuf[fmt_ulong(numbuf,sock)]=0;
869 	  buffer_putmflush(buffer_1,"close/ssh_handshake ",numbuf,"\n");
870 	}
871 	{
872 	  uint32 a=0;
873 	  write(forksock[0],&a,4);
874 	  io_passfd(forksock[0],sock);
875 	}
876 	--https_connections;
877 	changestate(h,PUNISHMENT);
878 	cleanup(sock);
879 	return;
880       }
881       /* Apparently the packets look radically different depending on
882        * whether it's TLS or SSLv2.  GREAT! */
883       /* first packet must be handshake */
884       if (buf[0]!=0x16 ||	/* content type: handshake */
885 	  buf[1]>3 ||	/* version major */
886 	  buf[2]>3 ||	/* version minor */
887 	  buf[3]>2) {	/* length > 0x200 */
888 	if (buf[0]!=0x80 ||
889 	    buf[2]!=1 ||	/* Client Hello */
890 	    buf[3]>3 ||	/* version major */
891 	    buf[4]>3) {	/* version minor */
892 	  tai6464 tarpit;
893 	  /* this does not look like an SSL packet. */
894 	  if (logging) {
895 	    char tmp[100];
896 	    buffer_puts(buffer_1,"close/not_ssl_traffic ");
897 	    buffer_putulong(buffer_1,sock);
898 	    buffer_putspace(buffer_1);
899 	    buffer_put(buffer_1,tmp,fmt_ip6c(tmp,h->peerip));
900 	    buffer_putnlflush(buffer_1);
901 	  }
902 	  io_dontwantread(sock);
903 	  io_dontwantwrite(sock);
904 	  --https_connections;
905 	  changestate(h,PUNISHMENT);
906 	  tarpit=now;
907 	  tarpit.sec.x+=10;
908 	  io_timeout(sock,tarpit);
909 	  return;
910 	}
911       }
912     }
913   }
914 
915 #ifdef USE_OPENSSL
916 //  printf("got SSL traffic on fd %d, calling SSL_accept\n",sock); fflush(stdout);
917   r=SSL_get_error(h->ssl,SSL_accept(h->ssl));
918 //  printf("SSL_accept returned %d\n",r); fflush(stdout);
919 //  printf("do_sslaccept -> %d\n",r);
920   if (r==SSL_ERROR_NONE)
921 #elif defined(USE_POLARSSL)
922   r=mbedtls_ssl_handshake(&h->ssldata->ssl);
923   if (r==0)
924 #endif
925   {
926 #if 0
927     h->writefail=1;
928 #endif
929     changestate(h,HTTPSREQUEST);
930     if (logging) {
931       buffer_puts(buffer_1,"ssl_handshake_ok ");
932       buffer_putulong(buffer_1,sock);
933       buffer_putnlflush(buffer_1);
934     }
935     return;
936   } else
937     if (handle_ssl_error_code(sock,r,reading)==-1)
938       cleanup(sock);
939 }
940 #endif
941 
handle_incoming_data(int64 i,struct http_data * h)942 static void handle_incoming_data(int64 i,struct http_data* h) {
943   int l;
944   if ((l=header_complete(h,i))) {
945     /* at this point we saw a \r\n\r\n */
946     long alen;
947 pipeline:
948     /* The h->mimetype reference is here so that we don't count both the HTTP
949       * connection and the first request on it as a dos attack. */
950     if (h->mimetype && new_request_from_ip(h->peerip,now.sec.x-4611686018427387914ULL)==1) {
951       changestate(h,PUNISHMENT);
952       if (logging) {
953 	char buf[IP6_FMT];
954 	char n[FMT_LONG];
955 	n[fmt_ulong(n,i)]=0;
956 	buf[fmt_ip6c(buf,h->peerip)]=0;
957 
958 	buffer_putmflush(buffer_1,"dos_tarpit2 ",n," ",buf,"\n");
959       }
960       if (timeout_secs) {
961 	io_dontwantread(i);
962 	io_dontwantwrite(i);
963       } else
964 	/* if we don't have timeouts enabled, just drop the connection */
965 	cleanup(i);
966       return;
967     }
968 #ifdef SUPPORT_HTTPS
969     if (h->t==HTTPREQUEST || h->t==HTTPSREQUEST) {
970       httpresponse(h,i,l);
971       if (h->t == HTTPSREQUEST) changestate(h,HTTPSRESPONSE);
972     }
973 #else
974     if (h->t==HTTPREQUEST)
975       httpresponse(h,i,l);
976 #endif
977 #ifdef SUPPORT_SMB
978     else if (h->t==SMBREQUEST) {
979       if (smbresponse(h,i)==-1) {
980 	cleanup(i);
981 	return;
982       }
983     }
984 #endif
985 #ifdef SUPPORT_FTP
986     else
987       ftpresponse(h,i);
988 #endif
989 #ifdef SUPPORT_PROXY
990     if (h->t != HTTPPOST
991 #ifdef SUPPORT_HTTPS
992       && h->t != HTTPSPOST
993 #endif
994 			  ) {
995 #endif
996       if (l < (alen=array_bytes(&h->r))) {
997 	char* c=array_start(&h->r);
998 
999 #if 0
1000 	printf("continuation: consumed %lu bytes from buffer (%lu still there)\n",
1001 		(unsigned long)l,
1002 		(unsigned long)(alen-l));
1003 #endif
1004 	byte_copy(c,alen-l,c+l);
1005 	array_truncate(&h->r,1,alen-l);
1006 	l=header_complete(h,i);
1007 
1008 #if 0
1009 	write(1,"\n\n",2);
1010 	write(1,array_start(&h->r),array_bytes(&h->r));
1011 	write(1,"\n\n",2);
1012 #endif
1013 
1014 	if (l) {
1015 	  /* this breaks SMB: */
1016 //	      if (h->r.initialized) --h->r.initialized;
1017 	  goto pipeline;
1018 	}
1019       } else
1020 	array_reset(&h->r);
1021 #ifdef SUPPORT_PROXY
1022     }
1023 #endif
1024   } else
1025     io_wantread(i);
1026 }
1027 
handle_read_misc(int64 i,struct http_data * h,unsigned long ftptimeout_secs,tai6464 nextftp)1028 static void handle_read_misc(int64 i,struct http_data* h,unsigned long ftptimeout_secs,tai6464 nextftp) {
1029   /* This is a TCP client connection waiting for input, i.e.
1030     *   - an HTTP connection waiting for a HTTP request, or
1031     *   - an FTP connection waiting for a command, or
1032     *   - an FTP upload waiting for more data, or
1033     *   - an SMB connection waiting for the next command */
1034   char buf[8192];
1035   int l;
1036 #ifdef SUPPORT_HTTPS
1037   assert(h->t != HTTPSRESPONSE);
1038   if (h->t == HTTPSREQUEST) {
1039 //    printf("calling SSL_read on fd %d\n",(int)i); fflush(stdout);
1040 #ifdef USE_OPENSSL
1041     l=SSL_read(h->ssl,buf,sizeof(buf));
1042 #elif defined(USE_POLARSSL)
1043     l=mbedtls_ssl_read(&h->ssldata->ssl,(unsigned char*)buf,sizeof(buf));
1044 #else
1045 #error fixme
1046 #endif
1047 //    printf("SSL_read(sock %d,buf %p,n %d) -> %d\n",(int)i,buf,(int)sizeof(buf),(int)l); fflush(stdout);
1048 #ifdef USE_OPENSSL
1049     if (l==-1) {
1050       l=SSL_get_error(h->ssl,l);
1051 //      printf("SSL_get_error -> %d (SSL_ERROR_WANT_READ=%d, SSL_ERROR_WANT_WRITE=%d)\n",l,SSL_ERROR_WANT_READ,SSL_ERROR_WANT_WRITE); fflush(stdout);
1052       if (l==SSL_ERROR_WANT_READ || l==SSL_ERROR_WANT_WRITE) {
1053 #elif defined(USE_POLARSSL)
1054     if (l<0) {
1055       if (l==MBEDTLS_ERR_SSL_WANT_READ || l==MBEDTLS_ERR_SSL_WANT_WRITE) {
1056 #else
1057 #error fixme
1058 #endif
1059 //      printf("  error %d %s\n",l,ERR_error_string(l,0));
1060 #ifdef USE_OPENSSL
1061 	if (l==SSL_ERROR_WANT_READ) io_eagain_read(i);
1062 	else if (l==SSL_ERROR_WANT_WRITE) io_eagain_write(i);
1063 #elif defined(USE_POLARSSL)
1064 	if (l==MBEDTLS_ERR_SSL_WANT_READ) io_eagain_read(i);
1065 	else if (l==MBEDTLS_ERR_SSL_WANT_WRITE) io_eagain_write(i);
1066 #else
1067 #error fixme
1068 #endif
1069 	if (handle_ssl_error_code(i,l,1)==-1) {
1070 	  cleanup(i);
1071 	  return;
1072 	}
1073 	l=-1;
1074 #ifdef USE_POLARSSL
1075       } else if (l==MBEDTLS_ERR_NET_RECV_FAILED) {
1076 	l=0;
1077 #endif
1078       } else {
1079 	printf("got polarssl error %x\n",l);
1080 	errno=ECONNRESET;
1081 	l=-3;
1082       }
1083     }
1084   } else
1085 #endif
1086   l=io_tryread(i,buf,sizeof buf);
1087   if (l==-3) {
1088 #ifdef SUPPORT_FTP
1089 ioerror:
1090 #endif
1091     if (logging) {
1092       char a[FMT_ULONG];
1093       a[fmt_ulong(a,i)]=0;
1094       buffer_putmflush(buffer_1,"io_error ",a," ",strerror(errno),"\nclose/readerr ",a,"\n");
1095     }
1096     cleanup(i);
1097   } else if (l==0) {
1098     if (logging) {
1099       buffer_puts(buffer_1,"close/read0 ");
1100       buffer_putulong(buffer_1,i);
1101       buffer_putnlflush(buffer_1);
1102     }
1103 #ifdef SUPPORT_FTP
1104     if (h->t==FTPSLAVE) {
1105       /* This is an FTP upload, it just finished. */
1106       struct http_data* b=io_getcookie(h->buddy);
1107       assert(b);
1108       b->buddy=-1;
1109       iob_reset(&b->iob);
1110       iob_adds(&b->iob,"226 Got it.\r\n");
1111       io_dontwantread(h->buddy);
1112       io_wantwrite(h->buddy);
1113       if (chmoduploads)
1114 	fchmod(h->filefd,0644);
1115       if (logging) {
1116 	struct stat ss;
1117 	if (fstat(h->filefd,&ss)==0) {
1118 	  char a[FMT_ULONG];
1119 	  char b[FMT_ULONG];
1120 	  a[fmt_ulong(a,i)]=0;
1121 	  b[fmt_ulong(b,ss.st_size)]=0;
1122 	  buffer_putmflush(buffer_1,"received ",a," ",b,"\n");
1123 	}
1124       }
1125     }
1126 #endif
1127 #ifdef SUPPORT_HTTPS
1128     if (h->t==HTTPSPOST || h->t==HTTPSRESPONSE || h->t==HTTPSREQUEST) {
1129 #ifdef USE_OPENSSL
1130       SSL_shutdown(h->ssl);
1131 #endif
1132     }
1133 #endif
1134     cleanup(i);
1135   } else if (l>0) {
1136     /* successfully read some data (l bytes) */
1137     h->received+=l;
1138     tin1+=l;
1139 #ifdef SUPPORT_FTP
1140     if (h->t==FTPCONTROL4 || h->t==FTPCONTROL6) {
1141       if (ftptimeout_secs)
1142 	io_timeout(i,nextftp);
1143     } else {
1144       if (timeout_secs)
1145 	io_timeout(i,next);
1146     }
1147 
1148     if (h->t==FTPSLAVE) {
1149       /* receive an upload */
1150       if (ftptimeout_secs)
1151 	io_timeout(h->buddy,nextftp);
1152       if (write(h->filefd,buf,l)!=l)
1153 	goto ioerror;
1154     } else
1155 #endif
1156     {
1157       /* received a request */
1158 //      printf("previous size: %lu, adding %lu bytes.\n",(unsigned long)array_bytes(&h->r),(unsigned long)l);
1159       array_catb(&h->r,buf,l);
1160       if (array_failed(&h->r)) {
1161 	httperror(h,"500 Server Error","request too long.",0);
1162 emerge:
1163 	io_dontwantread(i);
1164 	io_wantwrite(i);
1165       } else if (array_bytes(&h->r)>MAX_HEADER_SIZE) {
1166 	httperror(h,"500 request too long","You sent too much header data",0);
1167 	array_reset(&h->r);
1168 	goto emerge;
1169       } else
1170 	handle_incoming_data(i,h);
1171     }
1172   }
1173 }
1174 
1175 #ifdef SUPPORT_HTTPS
1176 int64 https_write_callback(int64 sock,const void* buf,uint64 n) {
1177   int l;
1178   struct http_data* H=io_getcookie(sock);
1179   if (!H) return -3;
1180 
1181 #if 0
1182   H->writefail=!H->writefail;
1183   if (H->writefail) { errno=EAGAIN; return -1; }
1184 #endif
1185   if (n>65536) n=65536;
1186 #ifdef USE_OPENSSL
1187   l=SSL_write(H->ssl,buf,n);
1188 //  fprintf(stderr,"SSL_write(\"%.*s\",%u) -> %d\n",n>16?16:(int)n,buf,(unsigned int)n,l);
1189   if (l<0) {
1190     l=SSL_get_error(H->ssl,l);
1191 #elif defined(USE_POLARSSL)
1192   l=mbedtls_ssl_write(&H->ssldata->ssl,buf,n);
1193   if (l<0) {
1194 #endif
1195     if (handle_ssl_error_code(sock,l,0)==-1) {
1196 //      cleanup(sock);
1197       return -3;
1198     }
1199 #ifdef USE_OPENSSL
1200     if (l==SSL_ERROR_WANT_READ || l==SSL_ERROR_WANT_WRITE) {
1201 #elif defined(USE_POLARSSL)
1202     if (l==MBEDTLS_ERR_SSL_WANT_READ || l==MBEDTLS_ERR_SSL_WANT_WRITE) {
1203 #endif
1204       l=-1; errno=EAGAIN;
1205     } else
1206       l=-3;
1207   }
1208   return l;
1209 }
1210 #endif
1211 
1212 /* call iob_send and handle errors;
1213  * if keep-alive is on, detect HTTP pipelining and return 1 if there is
1214  * more data left in h->r, otherwise return 0 */
1215 static int handle_write_misc(int64 i,struct http_data* h,uint64 prefetchquantum) {
1216   int64 r;
1217 #ifdef SUPPORT_HTTPS
1218   assert(h->t != HTTPSREQUEST);
1219   if (h->t == HTTPSRESPONSE)
1220     r=iob_write(i,&h->iob,https_write_callback);
1221   else
1222 #endif
1223   r=iob_send(i,&h->iob);
1224   if (r==-1)
1225     io_eagain_write(i);
1226   else if (r<=0) {
1227     if (r==-3) {
1228       if (logging) {
1229 	char a[FMT_ULONG];
1230 	char r[FMT_ULONG];
1231 	char s[FMT_ULONG];
1232 	a[fmt_ulong(a,i)]=0;
1233 	r[fmt_ulonglong(r,h->received)]=0;
1234 	s[fmt_ulonglong(s,h->sent)]=0;
1235 	buffer_putmflush(buffer_1,"socket_error ",a," ",strerror(errno),"\nclose/writefail ",a," ",r," ",s,"\n");
1236       }
1237 #ifdef SUPPORT_FTP
1238       if (h->t==FTPSLAVE || h->t==FTPACTIVE) {
1239 	struct http_data* b=io_getcookie(h->buddy);
1240 	if (b) {
1241 	  b->buddy=-1;
1242 	  iob_reset(&b->iob);
1243 	  iob_adds(&b->iob,"554 socket error.\r\n");
1244 	  io_wantwrite(h->buddy);
1245 	} else {
1246 	  /* Apparently the main control connection already died.
1247 	   * Nothing more to do here except clean up. */
1248 	}
1249       }
1250 #endif
1251       cleanup(i);
1252     } else {	/* returned 0, i.e. we wrote it all */
1253 wroteitall:
1254 #ifdef SUPPORT_HTTPS
1255       if (h->t == HTTPSRESPONSE) h->t = HTTPSREQUEST;
1256 #endif
1257 #ifdef SUPPORT_PROXY
1258 #ifdef SUPPORT_HTTPS
1259       if ((h->t == HTTPREQUEST || h->t == HTTPSREQUEST) && h->buddy!=-1)
1260 #else
1261       if (h->t == HTTPREQUEST && h->buddy!=-1)
1262 #endif
1263       {
1264 	io_dontwantwrite(i);
1265 	io_wantread(h->buddy);
1266 	return 0;
1267       }
1268 #endif
1269       if (logging && (h->t == HTTPREQUEST
1270 #ifdef SUPPORT_HTTPS
1271 	  || h->t == HTTPSREQUEST
1272 #endif
1273 	  )) {
1274 	buffer_puts(buffer_1,"request_done ");
1275 	buffer_putulong(buffer_1,i);
1276 	buffer_puts(buffer_1," ");
1277 	buffer_putulonglong(buffer_1,h->received);
1278 	buffer_puts(buffer_1," ");
1279 	buffer_putulonglong(buffer_1,h->sent);
1280 	buffer_putnlflush(buffer_1);
1281 	h->received=h->sent=0;
1282       }
1283 //      if (array_bytes(&h->r)>0 && h->r.p[h->r.initialized-1]==0) --h->r.initialized;
1284       iob_reset(&h->iob);
1285       h->hdrbuf=0;
1286       if (h->keepalive) {
1287 	if (array_bytes(&h->r)>0)
1288 	  return 1;
1289 //	iob_reset(&h->iob);
1290 	io_dontwantwrite(i);
1291 	io_wantread(i);
1292       } else {
1293 	if (logging) {
1294 	  buffer_puts(buffer_1,"close/reqdone ");
1295 	  buffer_putulong(buffer_1,i);
1296 	  buffer_putnlflush(buffer_1);
1297 	}
1298 #ifdef SUPPORT_FTP
1299 	if (h->t==FTPSLAVE) {
1300 	  struct http_data* b=io_getcookie(h->buddy);
1301 	  if (b) {
1302 	    b->buddy=-1;
1303 //	    iob_reset(&b->iob);
1304 	    iob_adds(&b->iob,"226 Done.\r\n");
1305 	    io_dontwantread(h->buddy);
1306 	    io_wantwrite(h->buddy);
1307 	  } else
1308 	    buffer_putsflush(buffer_2,"ARGH: no cookie or no buddy for FTP slave!\n");
1309 	}
1310 #endif
1311 	cleanup(i);
1312       }
1313     }
1314   } else {
1315     h->sent+=r;
1316     tout1+=r;
1317     /* write OK, now would be a good time to do some prefetching */
1318     h->sent_until+=r;
1319     if (prefetchquantum) {
1320       if (h->prefetched_until<h->sent_until || h->prefetched_until+prefetchquantum<h->sent_until) {
1321 	if (prefetchquantum) iob_prefetch(&h->iob,2*prefetchquantum);
1322 	h->prefetched_until+=2*prefetchquantum;
1323       }
1324     }
1325     if (iob_bytesleft(&h->iob)==0)	/* optimization, not strictly necessary */
1326       goto wroteitall;
1327   }
1328   return 0;
1329 }
1330 
1331 static void prepare_listen(int s,void* whatever) {
1332   if (s!=-1) {
1333 #ifdef HAVE_IO_FD_FLAGS
1334     if (!io_fd_flags(s,IO_FD_NONBLOCK))
1335 #else
1336     if (!io_fd(s))
1337 #endif
1338       panic("io_fd");
1339     io_setcookie(s,whatever);
1340     io_wantread(s);
1341   }
1342 }
1343 
1344 #ifdef SUPPORT_BITTORRENT
1345 int handle_torrent_request(int64 sock,struct http_data* h) {
1346   /* http://wiki.theory.org/BitTorrentSpecification#Tracker_HTTP.2FHTTPS_Protocol */
1347   /* http://www.bittorrent.org/protocol.html */
1348   char* req=array_start(&h->r); /* "GET /announce?info_hash=%c3%f4%31%0e%aa%ec%ae%3d%84%c1%63%70%a2%36%67%6b%24%99%b6%e1&peer_id=-TR0006-u0u5j57kcmm4&port=6887&uploaded=0&downloaded=0&left=243269632&compact=1&numwant=50&key=njyytouhv5fymdafkhzi&event=started\r\n" */
1349   char* t=strchr(req,'\n');
1350   char* s=strchr(req,'?');
1351   if (s && t && s<t) {
1352     if (t[-1]=='\r') --t;
1353   } else
1354     httperror(h,"500 invalid bittorrent request","Invalid BitTorrent request",*req=='H');
1355   return 0;
1356 }
1357 #endif
1358 
1359 /* Attempt to enable TCP fast open (linux only for now).
1360  * This means that the client sends the first bytes of the HTTP request
1361  * with the third packet of the TCP handshake, instead of sending a
1362  * useless ACK there.  I'm not sure why we are expected to switch this
1363  * on server-side, but hey, we'll do what we have to.
1364  * This is only useful for protocols where the client sends data first,
1365  * i.e. not for FTP and not for SSL */
1366 #ifndef HAVE_SOCKET_FASTOPEN
1367 static void socket_fastopen(int sock) {
1368 #ifdef TCP_FASTOPEN
1369   setsockopt(sock,SOL_TCP,TCP_FASTOPEN,(int[]){ 5 }, sizeof(int));
1370 #endif
1371 }
1372 #endif
1373 
1374 /* Attempt to turn off quick ack mode (linux only for now).
1375  * This means that the server won't ACK incoming data immediately
1376  * because it knows we will be replying to it soon anyway and can
1377  * drive-by ACK their stuff then.
1378  * This is useful for all non-interactive protocols. */
1379 static void quickackoff(int sock) {
1380 #ifdef HAVE_SOCKET_FASTOPEN
1381   socket_quickack(sock,0);
1382 #else
1383 #ifdef TCP_QUICKACK
1384   setsockopt(sock,SOL_TCP,TCP_QUICKACK,(int[]){ 0 }, sizeof(int));
1385 #endif
1386 #endif
1387 }
1388 
1389 int main(int argc,char* argv[],char* envp[]) {
1390   int s;		/* http socket */
1391   int f=-1;		/* ftp socket */
1392 #ifdef SUPPORT_SMB
1393   int smbs=-1;		/* smb socket */
1394   enum conntype sct=SMBSERVER6;
1395 #endif
1396   int doftp=0;		/* -1 = don't, 0 = try, but don't fail if not working, 1 = do */
1397   int dohttp=0;		/* -1 = don't, 0 = try, but don't fail if not working, 1 = do */
1398   int dosmb=0;
1399   enum { HTTP, FTP, SMB, HTTPS } lastopt=HTTP;
1400   enum conntype ct=HTTPSERVER6;	/* used as cookie to recognize server connections */
1401 #ifdef SUPPORT_FTP
1402   enum conntype fct=FTPSERVER6;	/* dito */
1403 #endif
1404 #ifdef SUPPORT_HTTPS
1405   int httpss=-1;	/* https socket */
1406   enum conntype httpsct=HTTPSSERVER6;
1407   int dohttps=0;
1408 #endif
1409 #ifdef __broken_itojun_v6__
1410   enum conntype ct4=HTTPSERVER4;
1411 #ifdef SUPPORT_FTP
1412   enum conntype fct4=FTPSERVER4;
1413 #endif
1414 #ifdef SUPPORT_HTTPS
1415   enum conntype httpsct4=HTTPSSERVER4;
1416 #endif
1417 #endif
1418   uint32 scope_id;
1419   char ip[16];
1420   uint16 port,fport,sport;
1421 #ifdef SUPPORT_HTTPS
1422   uint16 httpsport=0;
1423   static tai6464 nexthttps;
1424 #endif
1425   static tai6464 last,tick,nextftp;
1426   unsigned long ftptimeout_secs=600;
1427   char* new_uid=0;
1428   char* chroot_to=0;
1429   unsigned long long prefetchquantum=0;
1430 #ifdef SUPPORT_MULTIPROC
1431   pid_t* Instances;
1432 #endif
1433 
1434   initdircache();
1435 
1436 #if defined(DEBUG_EVENTS) || defined(SMDEBUG) || defined(STATE_DEBUG)
1437 #ifdef __dietlibc__
1438   fflush(stdout);
1439 #endif
1440 #endif
1441 
1442 #ifdef SUPPORT_HTTPS
1443 #ifdef USE_OPENSSL
1444   SSL_load_error_strings();
1445 #endif
1446 #endif
1447 
1448 #if defined(SUPPORT_CGI) || defined(SUPPORT_PROXY)
1449   _envp=envp;
1450 #endif
1451 #ifdef SUPPORT_CGI
1452   {
1453     int found;
1454     int _argc=argc;
1455     char* new_uid=0;
1456     char** _argv=argv;
1457 
1458     found=0;
1459     for (;;) {
1460       int c=getopt(_argc,_argv,"HP:hnfFi:p:vVdDtT:c:u:Uaw:sSO:C:lLeEr:o:N:m:A:X:I:");
1461       if (c==-1) break;
1462       switch (c) {
1463       case 'c':
1464 	chroot_to=optarg;
1465 	break;
1466 #ifdef SUPPORT_HTTPS
1467       case 'X':
1468 	sshd=optarg;
1469 	if (isdigit(*sshd)) {
1470 	  while (isdigit(*sshd)) ++sshd;
1471 	  ++sshd;
1472 	}
1473 	/* fall through */
1474 #endif
1475       case 'C':
1476 	found=1;
1477 	break;
1478       case 'u':
1479 	new_uid=optarg;
1480 	break;
1481       case '?':
1482 	break;
1483       }
1484     }
1485 
1486     optind=0;
1487 
1488     forksock[0]=forksock[1]=-1;
1489     if (found) {
1490       if (socketpair(AF_UNIX,SOCK_STREAM,0,forksock)==-1)
1491 	panic("socketpair");
1492       switch (fork()) {
1493       case -1:
1494 	panic("fork");
1495       case 0:
1496 	close(forksock[0]);
1497 	{
1498 	  int64 savedir;
1499 	  buffer fsb;
1500 	  /* we want to drop privileges here unless we are configured to
1501 	   * support sshd mode, in which case sshd won't work if we
1502 	   * change our uid before executing it */
1503 #ifdef SUPPORT_HTTPS
1504 	  if (!sshd) {
1505 #endif
1506 #ifndef __MINGW32__
1507 	  if (chroot_to) { chdir(chroot_to); chroot(chroot_to); }
1508 	  if (prepare_switch_uid(new_uid)==-1 || switch_uid()==-1) panic("switch_uid failed");
1509 #endif
1510 #ifdef SUPPORT_HTTPS
1511 #ifndef __MINGW32__
1512 	  } else {
1513 	    if (prepare_switch_uid(new_uid)==-1) panic("switch_uid failed");
1514 #endif
1515 	  }
1516 #endif
1517 	  if (!io_readfile(&savedir,".")) panic("open()");
1518 	  buffer_init(&fsb,(void*)read,forksock[1],fsbuf,sizeof fsbuf);
1519 	  while (1) {
1520 	    pid_t r;
1521 	    do {
1522 	      r=waitpid(-1,0,WNOHANG);
1523 	    } while (r!=0 && r!=-1);
1524 	    forkslave(forksock[1],&fsb,savedir,chroot_to);
1525 	    fchdir(savedir);
1526 	  }
1527 	}
1528 	break;
1529       default:
1530 	close(forksock[1]);
1531 	break;
1532       }
1533     }
1534   }
1535 
1536 #if 0
1537   {	/* debug test for the forkslave code */
1538     int64 fd;
1539     uint32 a; uint16 b;
1540     char* req="GET /?/ HTTP/1.0\r\nHost: localhost:80\r\n\r\n";
1541     char* dir="default";
1542     char* ra="127.0.0.1";
1543     a=strlen(req); write(forksock[0],&a,4);
1544     a=strlen(dir); write(forksock[0],&a,4);
1545     a=strlen(ra); write(forksock[0],&a,4);
1546     write(forksock[0],req,strlen(req));
1547     write(forksock[0],dir,strlen(dir));
1548     write(forksock[0],ra,strlen(ra));
1549     b=12345; write(forksock[0],&b,2);
1550     b=80; write(forksock[0],&b,2);
1551 
1552     read(forksock[0],&a,4);
1553     buffer_puts(buffer_1,"code ");
1554     buffer_putulong(buffer_1,a);
1555     buffer_putnlflush(buffer_1);
1556 
1557     read(forksock[0],&a,4);
1558     if (a) {
1559       char* c=alloca(a+1);
1560       read(forksock[0],c,a);
1561       buffer_put(buffer_1,c,a);
1562       buffer_putnlflush(buffer_1);
1563     } else {
1564       read(forksock[0],&a,4); /* PID */
1565       fd=io_receivefd(forksock[0]);
1566       if (fd==-1)
1567 	buffer_putsflush(buffer_2,"received no file descriptor for CGI\n");
1568       else {
1569 	char buf[1024];
1570 	int l;
1571 	while ((l=read(fd,buf,sizeof buf))) {
1572 	  write(1,buf,l);
1573 	}
1574       }
1575     }
1576   }
1577   exit(0);
1578 #endif
1579 #endif
1580 
1581   s=socket_tcp6();
1582 #ifdef __broken_itojun_v6__
1583 #ifdef SUPPORT_FTP
1584   f4=socket_tcp4();
1585 #endif
1586   s4=socket_tcp4();
1587 #endif
1588 
1589 #ifndef __MINGW32__
1590   signal(SIGPIPE,SIG_IGN);
1591 
1592   {
1593     struct sigaction sa;
1594     byte_zero(&sa,sizeof(sa));
1595     sigemptyset(&sa.sa_mask);
1596     sa.sa_handler=sighandler;
1597     sigaction(SIGINT,&sa,0);
1598     sigaction(SIGHUP,&sa,0);
1599   }
1600 
1601   if (!geteuid()) {
1602     struct rlimit orig,rl;
1603     long l;
1604     getrlimit(RLIMIT_NOFILE,&orig);
1605 #ifdef RLIMIT_NPROC
1606     rl.rlim_cur=RLIM_INFINITY; rl.rlim_max=RLIM_INFINITY;
1607     setrlimit(RLIMIT_NPROC,&rl);
1608 #endif
1609     for (l=orig.rlim_max; l<20000; l+=500) {
1610       rl.rlim_cur=l; rl.rlim_max=l;
1611       if (setrlimit(RLIMIT_NOFILE,&rl)==-1) {
1612 	if (errno==EPERM) {
1613 	  /* We run as root but we still get EPERM?  That only happens
1614 	   * on linux-vserver.  There is no good way to handle this, so
1615 	   * we'll set the soft limit to the hard limit */
1616 	  orig.rlim_cur=orig.rlim_max;
1617 	  setrlimit(RLIMIT_NOFILE,&orig);
1618 	}
1619 	break;
1620       }
1621     }
1622   }
1623 #endif
1624 
1625   byte_zero(ip,16);
1626   port=0; fport=0; sport=0; scope_id=0;
1627 
1628   logging=1;
1629 
1630 #if !defined(__linux__)
1631   optind=1;
1632 #if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__DragonFly__)
1633   optreset=1;
1634 #endif
1635 #endif
1636 
1637   for (;;) {
1638     int i;
1639     int c=getopt(argc,argv,"HP:hnfFi:p:vVdDtT:c:u:Uaw:sSO:C:lLeEr:o:N:m:A:X:I:");
1640     if (c==-1) break;
1641     switch (c) {
1642     case 'L':
1643       limit_to_lan=1;
1644       break;
1645     case 'U':
1646       nouploads=1;
1647       break;
1648     case 'a':
1649       chmoduploads=1;
1650       break;
1651     case 'n':
1652       logging=0;
1653       break;
1654     case 'u':
1655       new_uid=optarg;
1656       break;
1657     case 'c':
1658       chroot_to=optarg;
1659       break;
1660     case 'm':
1661       mimetypesfilename=optarg;
1662       break;
1663     case 'P':
1664       i=scan_ulonglong(optarg,&prefetchquantum);
1665       if (i==0) {
1666 	buffer_puts(buffer_2,"gatling: warning: could not parse prefetch quantum");
1667 	buffer_puts(buffer_2,optarg+i+1);
1668 	buffer_putsflush(buffer_2,".\n");
1669       }
1670       if (optarg[i]=='M') prefetchquantum*=1024*1024;
1671       if (optarg[i]=='G') prefetchquantum*=1024*1024*1024;
1672       break;
1673     case 'i':
1674       i=scan_ip6if(optarg,ip,&scope_id);
1675       if (optarg[i]!=0) {
1676 	buffer_puts(buffer_2,"gatling: warning: could not parse IP address ");
1677 	buffer_puts(buffer_2,optarg+i+1);
1678 	buffer_putsflush(buffer_2,".\n");
1679       }
1680       break;
1681     case 'I':
1682       defaultindex=optarg;
1683       break;
1684     case 'p':
1685       if (lastopt==FTP)
1686 	i=scan_ushort(optarg,&fport);
1687       else if (lastopt==SMB)
1688 	i=scan_ushort(optarg,&sport);
1689 #ifdef SUPPORT_HTTPS
1690       else if (lastopt==HTTPS)
1691 	i=scan_ushort(optarg,&httpsport);
1692 #endif
1693       else
1694 	i=scan_ushort(optarg,&port);
1695       if (i==0) {
1696 	buffer_puts(buffer_2,"gatling: warning: could not parse port ");
1697 	buffer_puts(buffer_2,optarg+i+1);
1698 	buffer_putsflush(buffer_2,".\n");
1699       }
1700       break;
1701     case 'v': virtual_hosts=1; break;
1702     case 'V': virtual_hosts=-1; break;
1703     case 't': transproxy=1; break;
1704     case 'd': directory_index=1; break;
1705     case 'D': directory_index=-1; break;
1706 #ifdef SUPPORT_FTP
1707     case 'f': doftp=1; lastopt=FTP; break;
1708     case 'F': doftp=-1; break;
1709     case 'l':
1710       askforpassword=1;
1711       break;
1712 #endif
1713 #ifdef SUPPORT_HTTPS
1714     case 'e': dohttps=1; lastopt=HTTPS; break;
1715     case 'E': dohttps=-1; break;
1716     case 'X': sshd=optarg;
1717 	      if (isdigit(sshd[0])) {
1718 		i=scan_ulong(optarg,&ssh_timeout);
1719 		if (sshd[i]!=',' && sshd[i]!=' ') goto usage;
1720 		sshd+=i+1;
1721 	      } else ssh_timeout=2;
1722 	      break;
1723 #endif
1724     case 'H': dohttp=-1; break;
1725     case 's': dosmb=1; lastopt=SMB; break;
1726     case 'S': dosmb=-1; break;
1727     case 'T':
1728       i=scan_ulong(optarg,doftp?&ftptimeout_secs:&timeout_secs);
1729       if (i==0) {
1730 	buffer_puts(buffer_2,"gatling: warning: could not parse timeout in seconds ");
1731 	buffer_puts(buffer_2,optarg+i+1);
1732 	buffer_putsflush(buffer_2,".\n");
1733       }
1734       break;
1735 #ifdef SUPPORT_SMB
1736     case 'w':
1737       if (str_len(optarg)>12)
1738 	buffer_putsflush(buffer_2,"gatling: workgroup name too long (12 max)\n");
1739       else
1740 	str_copy(workgroup,optarg);
1741       break;
1742 #endif
1743 #ifdef SUPPORT_CGI
1744     case 'C':
1745       errno=0;
1746       if (add_cgi(optarg)) {
1747 	if (errno==ENOMEM)
1748 	  buffer_putmflush(buffer_2,"gatling: out of memory\n");
1749 	else
1750 	  buffer_putmflush(buffer_2,"gatling: could not parse `",optarg,"': expected something like `\\.cgi$'\n");
1751       }
1752       break;
1753 #endif
1754 #ifdef SUPPORT_PROXY
1755     case 'O':
1756       errno=0;
1757       if (add_proxy(optarg)) {
1758 	if (errno==ENOMEM)
1759 	  buffer_putmflush(buffer_2,"gatling: out of memory\n");
1760 	else
1761 	  buffer_putmflush(buffer_2,"gatling: could not parse `",optarg,"': expected something like `127.0.0.1/8001/\\.jsp'\n");
1762       }
1763       break;
1764 #endif
1765 #ifdef SUPPORT_FALLBACK_REDIR
1766     case 'r':
1767       if (strstr(optarg,"://"))
1768 	redir=optarg;
1769       else
1770 	buffer_putmflush(buffer_2,"gatling: -r needs something like http://fallback.example.com as argument!\n");
1771       break;
1772 #endif
1773 #ifdef SUPPORT_MULTIPROC
1774     case 'N':
1775       i=scan_ulong(optarg,&instances);
1776       if (i==0) {
1777 	buffer_puts(buffer_2,"gatling: warning: could not parse instances at ");
1778 	buffer_puts(buffer_2,optarg+i+1);
1779 	buffer_putsflush(buffer_2,".\n");
1780       }
1781       break;
1782 #endif
1783     case 'A':
1784       i=scan_uint(optarg,&max_requests_per_minute);
1785       if (i==0) {
1786 	buffer_puts(buffer_2,"gatling: warning: could not parse max_requests_per_minute at ");
1787 	buffer_puts(buffer_2,optarg+i+1);
1788 	buffer_putsflush(buffer_2,".\n");
1789       }
1790       break;
1791 
1792 #ifdef SUPPORT_THREADED_OPEN
1793     case 'o':
1794 #endif
1795     default:
1796     case '?':
1797     case 'h':
1798 usage:
1799       buffer_putsflush(buffer_2,
1800 		  "usage: gatling [-HhnvVtdDfFUa] [-i bind-to-ip] [-p bind-to-port] [-T seconds]\n"
1801 		  "               [-u uid] [-c dir] [-w workgroup] [-P bytes] [-O ip/port/regex]\n"
1802 		  "               [-r redirurl] [-N processes] [-I filename]\n"
1803 		  "\n"
1804 		  "\t-h\tprint this help\n"
1805 		  "\t-H\tdo not provide HTTP\n"
1806 		  "\t-v\tenable virtual hosting mode\n"
1807 		  "\t-V\tdisable virtual hosting mode\n"
1808 		  "\t\t(default is to try both)\n"
1809 		  "\t-t\ttransproxy mode: do not replace :port in Host headers\n"
1810 		  "\t-d\tgenerate directory index\n"
1811 		  "\t-D\tdo not generate directory index\n"
1812 		  "\t\t(default is -d unless in virtual hosting mode)\n"
1813 		  "\t-T n\tset timeout in seconds (0 to disable, default 23)\n"
1814 		  "\t-u uid\tswitch to this UID after binding\n"
1815 		  "\t-c dir\tchroot to dir after binding\n"
1816 		  "\t-n\tdo not produce logging output\n"
1817 		  "\t-f\tprovide FTP (default); next -p is meant for the FTP port (default: 21)\n"
1818 		  "\t-F\tdo not provide FTP\n"
1819 		  "\t-U\tdisallow FTP uploads, even to world writable directories\n"
1820 		  "\t-a\tchmod go+r uploaded files, so they can be downloaded immediately\n"
1821 		  "\t-P n\tenable experimental prefetching code (may actually be slower)\n"
1822 		  "\t-l\task for password (FTP server; work around buggy proxies)\n"
1823 		  "\t-m fn\tparse fn as mime.types style mime type database\n"
1824 		  "\t-A rpm\ttarpit clients if they have more than rpm request per minute\n"
1825 #ifdef SUPPORT_MULTIPROC
1826 		  "\t-N n\tfork n instances of gatling\n"
1827 #endif
1828 #ifdef SUPPORT_CGI
1829 		  "\t-C regex\tregex for local CGI execution (\"\\.cgi\")\n"
1830 		  "\t\tuse -C+x to assume executables are CGIs\n"
1831 #endif
1832 		  "\t-I name\talso try name, used for \"index.php\" etc\n"
1833 #ifdef SUPPORT_PROXY
1834 		  "\t-O [flag/]ip/port/regex\tregex for proxy mode (\"F/127.0.0.1/8001/\\.jsp$\")\n"
1835 		  "\t-O [flag/]|filename|regex\tregex for proxy mode (\"F/|/tmp/php.sock|\\.jsp$\")\n"
1836 		  "\t\tflags: F - FastCGI, S - SCGI, J - JSP\n"
1837 #endif
1838 #ifdef SUPPORT_SMB
1839 		  "\t-s\tprovide SMB service (default)\n"
1840 		  "\t-S\tdo not provide SMB service\n"
1841 		  "\t-w name\tset SMB workgroup\n"
1842 #endif
1843 #ifdef SUPPORT_HTTPS
1844 		  "\t-e\tprovide encryption (https://...)\n"
1845 		  "\t-E\tdo not provide encryption\n"
1846 		  "\t-X timeout,sshd (\"2,/opt/diet/sbin/sshd -u0\")\n"
1847 		  "\t\tforward TLS socket to sshd if no activity after connect\n"
1848 #endif
1849 #ifdef SUPPORT_FALLBACK_REDIR
1850 		  "\t-r url\tinstead of a 404, generate a redirect to url+localpart\n"
1851 #endif
1852 		  "\t-L\tonly accept connections from localhost or link/site local reserved IP addresses\n"
1853 		  );
1854       return 0;
1855     }
1856   }
1857 #ifdef SUPPORT_SMB
1858   {
1859     iconv_t i=iconv_open("UTF-16LE","ISO-8859-1");
1860     size_t X,Y;
1861     char* x,* y;
1862     X=str_len(workgroup)+1;
1863     Y=sizeof(workgroup_utf16);
1864     x=workgroup;
1865     y=workgroup_utf16;
1866 #if defined(__sun__) || defined(__FreeBSD__)
1867     if (iconv(i,(const char**)&x,&X,&y,&Y)) panic("UTF-16 conversion of workgroup failed.\n");
1868 #else
1869     if (iconv(i,&x,&X,&y,&Y)) panic("UTF-16 conversion of workgroup failed.\n");
1870 #endif
1871     wglen=str_len(workgroup);
1872     wglen16=sizeof(workgroup_utf16)-Y;
1873     iconv_close(i);
1874 
1875   }
1876   {
1877     extern iconv_t wc2utf8;
1878     extern iconv_t utf82wc2;
1879     wc2utf8=iconv_open("UTF-8","UTF-16LE");
1880     utf82wc2=iconv_open("UTF-16LE","UTF-8");
1881   }
1882 #endif
1883   if (!directory_index)
1884     directory_index=virtual_hosts<1;
1885   else if (directory_index==-1)
1886     directory_index=0;
1887 
1888   if (timeout_secs) {
1889     taia_now(&last);
1890     byte_copy(&next,sizeof(next),&last);
1891     next.sec.x += timeout_secs;
1892     byte_copy(&nextftp,sizeof(next),&last);
1893     nextftp.sec.x += ftptimeout_secs;
1894 #ifdef SUPPORT_HTTPS
1895     if (ssh_timeout) {
1896       byte_copy(&nexthttps,sizeof(now),&now);
1897       nexthttps.sec.x += ssh_timeout;
1898     } else
1899       byte_copy(&nexthttps,sizeof(next),&next);
1900 #endif
1901     byte_copy(&tick,sizeof(next),&last);
1902     ++tick.sec.x;
1903   }
1904 
1905   {
1906 #ifdef __MINGW32__
1907     int euid=0;
1908 #else
1909     uid_t euid=geteuid();
1910 #endif
1911     if (port==0)
1912       port=euid?8000:80;
1913     if (fport==0)
1914       fport=euid?2121:21;
1915 #ifdef SUPPORT_SMB
1916     if (sport==0)
1917       sport=445;
1918 #endif
1919 #ifdef SUPPORT_HTTPS
1920     if (httpsport==0)
1921       httpsport=euid?4433:443;
1922 #endif
1923   }
1924 #ifdef __broken_itojun_v6__
1925   if (byte_equal(ip,12,V4mappedprefix) || byte_equal(ip,16,V6any)) {
1926     if (byte_equal(ip,16,V6any)) {
1927       if (dohttp==-1) {
1928 	close(s); s=-1;
1929       } else {
1930 	if (socket_bind6_reuse(s,ip,port,scope_id)==-1 || socket_listen(s,16)==-1)
1931 	  panic("socket_bind6_reuse for http");
1932       }
1933 #ifdef SUPPORT_FTP
1934       f=socket_tcp6();
1935       if (doftp>=0) {
1936 	if (socket_bind6_reuse(f,ip,fport,scope_id)==-1 || socket_listen(f,16)==-1) {
1937 	  if (doftp==1)
1938 	    panic("socket_bind6_reuse for ftp");
1939 	  buffer_putsflush(buffer_2,"warning: could not bind to FTP port; FTP will be unavailable.\n");
1940 	  io_close(f); f=-1;
1941 	}
1942       }
1943 #endif
1944     } else {
1945       io_close(s); s=-1;
1946     }
1947     if (socket_bind4_reuse(s4,ip+12,port)==-1 || socket_listen(s4,16)==-1)
1948       panic("socket_bind4_reuse");
1949 #ifdef SUPPORT_FTP
1950     if (doftp>=0)
1951       if (socket_bind4_reuse(f4,ip+12,fport)==-1 || socket_listen(f4,16)==-1) {
1952 	if (doftp==1)
1953 	  panic("socket_bind4_reuse");
1954 	buffer_putsflush(buffer_2,"warning: could not bind to FTP port; FTP will be unavailable.\n");
1955 	io_close(f4); f4=-1;
1956       }
1957 #endif
1958   } else {
1959     if (dohttp==-1) {
1960       close(s);
1961       s=-1;
1962     } else {
1963       if (socket_bind6_reuse(s,ip,port,scope_id)==-1 || socket_listen(s,16)==-1)
1964 	panic("socket_bind6_reuse");
1965     }
1966     s4=-1;
1967 #ifdef SUPPORT_FTP
1968     if (doftp>=0)
1969       if (socket_bind6_reuse(f,ip,fport,scope_id)==-1 || socket_listen(f,16)==-1) {
1970 	if (doftp==1)
1971 	  panic("socket_bind6_reuse");
1972 	buffer_putsflush(buffer_2,"warning: could not bind to FTP port; FTP will be unavailable.\n");
1973 	io_close(f); f=-1;
1974       }
1975     f4=-1;
1976 #endif
1977   }
1978   buffer_putsflush(buffer_2,"WARNING: We are taking heavy losses working around itojun KAME madness here.\n"
1979 		            "         Please consider using an operating system with real IPv6 support instead!\n");
1980 #else
1981   if (dohttp==-1) {
1982     close(s);
1983     s=-1;
1984   } else {
1985 #ifndef __linux__
1986     /* Enabling this on Linux leads to a denial of service attack when
1987      * somebody just opens 16 or so connections without sending HTTP
1988      * requests, stalling the whole HTTP server in the process */
1989     socket_deferaccept(s,HTTPIN);
1990 #endif
1991     if (socket_bind6_reuse(s,ip,port,0)==-1 || socket_listen(s,16)==-1)
1992       panic("socket_bind6_reuse");
1993     socket_fastopen(s);
1994     quickackoff(s);
1995   }
1996 #ifdef SUPPORT_FTP
1997   if (doftp>=0) {
1998     f=socket_tcp6();
1999     if (socket_bind6_reuse(f,ip,fport,scope_id)==-1 || socket_listen(f,16)==-1) {
2000       if (doftp==1)
2001 	panic("socket_bind6_reuse");
2002       buffer_putsflush(buffer_2,"warning: could not bind to FTP port; FTP will be unavailable.\n");
2003       io_close(f); f=-1;
2004     }
2005     quickackoff(f);
2006   }
2007 #endif
2008 #ifdef SUPPORT_SMB
2009   if (dosmb>=0) {
2010     smbs=socket_tcp6();
2011 #ifndef __linux__
2012     socket_deferaccept(smbs,DATAIN);
2013 #endif
2014     if (socket_bind6_reuse(smbs,ip,sport,scope_id)==-1 || socket_listen(smbs,16)) {
2015       if (dosmb==1)
2016 	panic("socket_bind6_reuse");
2017       buffer_putsflush(buffer_2,"warning: could not bind to SMB port; SMB will be unavailable.\n");
2018       io_close(smbs); smbs=-1;
2019     }
2020     socket_fastopen(smbs);
2021     quickackoff(smbs);
2022   }
2023 #endif
2024 #ifdef SUPPORT_HTTPS
2025   if (dohttps>=0) {
2026     httpss=socket_tcp6();
2027 #ifndef __linux__
2028     if (ssh_timeout==0)
2029       socket_deferaccept(httpss,DATAIN);
2030 #endif
2031     if (socket_bind6_reuse(httpss,ip,httpsport,scope_id)==-1 || socket_listen(httpss,16)) {
2032       if (dohttps==1)
2033 	panic("socket_bind6_reuse");
2034       buffer_putsflush(buffer_2,"warning: could not bind to HTTPS port; HTTPS will be unavailable.\n");
2035       io_close(httpss); httpss=-1;
2036     }
2037     quickackoff(httpss);
2038   }
2039 #endif
2040 #endif
2041 
2042 #ifndef __MINGW32__
2043   if (prepare_switch_uid(new_uid)==-1)
2044     goto usage;
2045   if (chroot_to) {
2046     if (chroot(chroot_to)==-1)
2047       panic("chroot");
2048     if (chdir("/")==-1)
2049       panic("chdir");
2050   }
2051   if (new_uid && switch_uid()==-1)
2052     panic("switch_uid");
2053 
2054 #endif
2055 
2056 #ifdef __MINGW32__
2057   _getcwd(origdir,sizeof(origdir));
2058   strncpy(serverroot,origdir,sizeof(serverroot));
2059 //  printf("origdir is \"%s\"\n",origdir);
2060 #else
2061   /* get fd for . so we can always fchdir back */
2062   if (!io_readfile(&origdir,".")) panic("open()");
2063   /* note the server root path for CGI $SCRIPT_FILENAME */
2064   if (!getcwd(serverroot,sizeof(serverroot))) {
2065     serverroot[0]='.';
2066     serverroot[1]=0;
2067   }
2068 #endif
2069 
2070 #ifdef SUPPORT_MULTIPROC
2071 
2072   if (instances>1) {
2073     unsigned long i;
2074     --instances;
2075 
2076     if (instances>100) instances=100;
2077     Instances=alloca(instances*sizeof(pid_t));
2078     for (i=0; i<instances; ++i) {
2079       if ((Instances[i]=fork()) == -1)
2080 	panic("fork failed");
2081       else if (Instances[i] == 0) {
2082 	instances=0;
2083 	break;
2084       }
2085     }
2086 
2087 #ifdef __broken_itojun_v6__
2088     prepare_listen(s,&ct);
2089     prepare_listen(s4,&ct4);
2090     prepare_listen(f,&fct);
2091     prepare_listen(f4,&fct4);
2092 #else
2093     prepare_listen(s,&ct);
2094 #ifdef SUPPORT_FTP
2095     prepare_listen(f,&fct);
2096 #endif
2097 #ifdef SUPPORT_SMB
2098     prepare_listen(smbs,&sct);
2099 #endif
2100 #ifdef SUPPORT_HTTPS
2101     prepare_listen(httpss,&httpsct);
2102 #endif
2103 #endif
2104 
2105   } else {
2106 #endif
2107 #ifdef SUPPORT_MULTIPROC
2108     Instances=0;
2109     instances=0;
2110 #endif
2111 
2112 #ifdef __broken_itojun_v6__
2113     prepare_listen(s,&ct);
2114     prepare_listen(s4,&ct4);
2115     prepare_listen(f,&fct);
2116     prepare_listen(f4,&fct4);
2117 #else
2118     prepare_listen(s,&ct);
2119 #ifdef SUPPORT_FTP
2120     prepare_listen(f,&fct);
2121 #endif
2122 #ifdef SUPPORT_SMB
2123     prepare_listen(smbs,&sct);
2124 #endif
2125 #ifdef SUPPORT_HTTPS
2126     prepare_listen(httpss,&httpsct);
2127 #endif
2128 #endif
2129 
2130 #ifdef SUPPORT_MULTIPROC
2131   }
2132 #endif
2133 
2134 #ifdef __linux__
2135   if (io_fd(ifd))
2136     io_wantread(ifd);
2137 #endif
2138 
2139   {
2140     char buf[IP6_FMT];
2141     if (s!=-1) {
2142       buffer_puts(buffer_1,"starting_up 0 ");
2143       buffer_put(buffer_1,buf,fmt_ip6c(buf,ip));
2144       buffer_puts(buffer_1," ");
2145       buffer_putulong(buffer_1,port);
2146       buffer_putnlflush(buffer_1);
2147     }
2148     if (f!=-1) {
2149       buffer_puts(buffer_1,"start_ftp 0 ");
2150       buffer_put(buffer_1,buf,fmt_ip6c(buf,ip));
2151       buffer_puts(buffer_1," ");
2152       buffer_putulong(buffer_1,fport);
2153       buffer_putnlflush(buffer_1);
2154     }
2155 #ifdef SUPPORT_SMB
2156     if (smbs!=-1) {
2157       buffer_puts(buffer_1,"start_smb 0 ");
2158       buffer_put(buffer_1,buf,fmt_ip6c(buf,ip));
2159       buffer_puts(buffer_1," ");
2160       buffer_putulong(buffer_1,sport);
2161       buffer_putnlflush(buffer_1);
2162     }
2163 #endif
2164 #ifdef SUPPORT_HTTPS
2165     if (httpss!=-1) {
2166       buffer_puts(buffer_1,"start_https 0 ");
2167       buffer_put(buffer_1,buf,fmt_ip6c(buf,ip));
2168       buffer_puts(buffer_1," ");
2169       buffer_putulong(buffer_1,httpsport);
2170       buffer_putnlflush(buffer_1);
2171     }
2172 #endif
2173   }
2174 
2175   connections=1;
2176 
2177 #if !defined(__OPTIMIZE__) && defined(__linux__)
2178   /* This happens only if the code was compiled without optimization */
2179   /* make sure we can dump core even if we switched uid */
2180   prctl(PR_SET_DUMPABLE,1,0,0);
2181   /* and make sure we don't have a core dump size limit in place */
2182   {
2183     struct rlimit orig;
2184     orig.rlim_cur=orig.rlim_max=RLIM_INFINITY;
2185     setrlimit(RLIMIT_CORE,&orig);
2186   }
2187 #endif
2188 
2189   for (;;) {
2190     int events;		/* accept new connections asap */
2191     int64 i;
2192     events=0;
2193 
2194     if (fini==2) {
2195       --connections;
2196       io_close(s);
2197 #ifdef __broken_itojun_v6__
2198       io_close(s4);
2199 #endif
2200 #ifdef SUPPORT_FTP
2201       io_close(f);
2202 #ifdef __broken_itojun_v6__
2203       io_close(f4);
2204 #endif
2205 #endif
2206 #ifdef SUPPORT_SMB
2207       io_close(smbs);
2208 #endif
2209       buffer_puts(buffer_1,"closing_server_sockets ");
2210       buffer_putulong(buffer_1,connections);
2211       buffer_putnlflush(buffer_1);
2212       fini=0;
2213     }
2214     if (!connections) fini=1;
2215     if (fini) {
2216       buffer_putsflush(buffer_1,"stopping\n");
2217       break;
2218     }
2219 
2220     if (timeout_secs)
2221       io_waituntil(tick);
2222     else
2223       io_wait();
2224 
2225     taia_now(&now);
2226     if (timeout_secs) {
2227       if (now.sec.x != last.sec.x) {
2228 	cps=cps1; cps1=0;
2229 	rps=rps1; rps1=0;
2230 	eps=eps1; eps1=0;
2231 	tin=tin1; tin1=0;
2232 	tout=tout1; tout1=0;
2233 	byte_copy(&last,sizeof(now),&now);
2234 	byte_copy(&next,sizeof(now),&now);
2235 	next.sec.x += timeout_secs;
2236 	byte_copy(&nextftp,sizeof(now),&now);
2237 	nextftp.sec.x += ftptimeout_secs;
2238 #if defined(SUPPORT_HTTPS) && !defined(SUPPORT_MULTIPROC)
2239 	if (ssh_timeout) {
2240 	  byte_copy(&nexthttps,sizeof(now),&now);
2241 	  nexthttps.sec.x += ssh_timeout;
2242 	} else
2243 	  byte_copy(&nexthttps,sizeof(next),&next);
2244 #endif
2245 	byte_copy(&tick,sizeof(next),&now);
2246 	++tick.sec.x;
2247 	while ((i=io_timeouted())!=-1) {
2248 	  struct http_data* x;
2249 #if defined(SUPPORT_HTTPS) && !defined(SUPPORT_MULTIPROC)
2250 	  if (ssh_timeout && (x=io_getcookie(i)) && x->t == HTTPSACCEPT_CHECK) {
2251 	    if (logging) {
2252 	      char numbuf[FMT_ULONG];
2253 	      numbuf[fmt_ulong(numbuf,i)]=0;
2254 	      buffer_putmflush(buffer_1,"timeout/sshd ",numbuf,"\n");
2255 	    }
2256 	    {
2257 	      uint32 a=0;
2258 	      write(forksock[0],&a,4);
2259 	      io_passfd(forksock[0],i);
2260 	    }
2261 	    --https_connections;
2262 	  }
2263 #endif
2264 	  if (logging) {
2265 	    /* shut up in the tarpit case, don't give them the
2266 	     * satisfaction of spamming our logs too much */
2267 	    if ((x=io_getcookie(i)) && x->t != PUNISHMENT) {
2268 	      char numbuf[FMT_ULONG];
2269 	      numbuf[fmt_ulong(numbuf,i)]=0;
2270 	      buffer_putmflush(buffer_1,"timeout ",numbuf,"\nclose/timeout ",numbuf,"\n");
2271 	    }
2272 	  }
2273 	  cleanup(i);
2274 	}
2275       }
2276     }
2277 
2278     /* HANDLE READ EVENTS */
2279     while ((i=io_canread())!=-1) {
2280 #ifdef __linux__
2281       if (i==ifd) {
2282 	handle_inotify_events();
2283 	continue;
2284       }
2285 #endif
2286       struct http_data* H=io_getcookie(i);
2287 
2288       ++eps1;
2289       if (!H) {
2290 	char a[FMT_ULONG];
2291 	a[fmt_ulong(a,i)]=0;
2292 	buffer_putmflush(buffer_2,"canthappen ",a,": got read event on socket with no cookie!\n");
2293 	io_dontwantread(i);
2294 	io_close(i);
2295 	continue;
2296       }
2297 
2298 #ifdef SMDEBUG
2299       {
2300 	char a[FMT_ULONG];
2301 	a[fmt_ulong(a,i)]=0;
2302 	buffer_putmflush(buffer_2,"DEBUG: fd ",a," got READ event, state is ",state2string(H->t),"!\n");
2303       }
2304 #endif
2305 
2306       /* This is a speed hack.  If we have a LOT of connections, we
2307        * might get swamped handling events and it might take a while for
2308        * us to get around to accepting new connections.  Unfortunately,
2309        * the kernel has a limited number of connections that can be
2310        * incoming but not accepted; if more attempts come in, the kernel
2311        * just drops them, and they then run into a timeout and try
2312        * again.  To avoid this, we try accepting connections even
2313        * without any events. */
2314       if (++events==10) {
2315 	events=0;
2316 	if (s!=-1) accept_server_connection(s,(struct http_data*)&ct,ftptimeout_secs,nextftp);
2317 #ifdef SUPPORT_FTP
2318 	if (f!=-1) accept_server_connection(f,(struct http_data*)&fct,ftptimeout_secs,nextftp);
2319 #endif
2320 #ifdef SUPPORT_HTTPS
2321 	if (httpss!=-1) {
2322 	  if (ssh_timeout)
2323 	    accept_server_connection(httpss,(struct http_data*)&httpsct,ssh_timeout,nexthttps);
2324 	  else
2325 	    accept_server_connection(httpss,(struct http_data*)&httpsct,ftptimeout_secs,nextftp);
2326 	}
2327 #endif
2328 #ifdef __broken_itojun_v6__
2329 	if (s4!=-1) accept_server_connection(s4,(struct http_data*)&ct4,ftptimeout_secs,nextftp);
2330 #ifdef SUPPORT_FTP
2331 	if (f4!=-1) accept_server_connection(f4,(struct http_data*)&fct4,ftptimeout_secs,nextftp);
2332 #endif
2333 #ifdef SUPPORT_HTTPS
2334 	if (httpss4!=-1) {
2335 	  if (ssh_timeout)
2336 	    accept_server_connection(httpss4,(struct http_data*)&httpsct4,ssh_timeout,nexthttps);
2337 	  else
2338 	    accept_server_connection(httpss4,(struct http_data*)&httpsct4,ftptimeout_secs,nextftp);
2339 	}
2340 #endif
2341 #endif
2342       }
2343 
2344       if (H->t == HTTPREQUEST
2345 #ifdef SUPPORT_FTP
2346 	  || H->t == FTPSLAVE
2347 #endif
2348 #ifdef SUPPORT_SMB
2349 	  || H->t == SMBREQUEST
2350 #endif
2351 #ifdef SUPPORT_HTTPS
2352 	  || H->t == HTTPSRESPONSE
2353 #endif
2354 	 )
2355 	H->sent_until=H->prefetched_until=0;
2356 
2357 #ifdef SUPPORT_PROXY
2358 	/* read on PROXYPOST means the CGI sent some data */
2359       if (H->t==PROXYPOST) {
2360 	int64 mainsock=H->buddy;
2361 	if (handle_read_proxypost(i,H)==-4) {
2362 	  /* the CGI was done, we closed the CGI socket, now check if
2363 	   * there is keep-alive / pipelining to take care of */
2364 	  struct http_data* h=io_getcookie(mainsock);
2365 	  if (h->keepalive) {
2366 #ifdef SUPPORT_HTTPS
2367 	    if (h->t==HTTPSPOST) h->t=HTTPSREQUEST;
2368 #endif
2369 	    if (h->t==HTTPPOST) h->t=HTTPREQUEST;
2370 	    handle_incoming_data(mainsock,h);
2371 	  } else {
2372 #ifdef SUPPORT_HTTPS
2373 	    if (h->t==HTTPSPOST) {
2374 #ifdef USE_OPENSSL
2375 	      SSL_shutdown(h->ssl);
2376 #endif
2377 	    }
2378 #endif
2379 	    cleanup(i);
2380 	  }
2381 	}
2382       } else if (H->t==HTTPPOST
2383 #ifdef SUPPORT_HTTPS
2384 	    || H->t==HTTPSPOST
2385 #endif
2386 			      )
2387 	/* read on HTTPPOST means the browser sent some more POST data */
2388 	handle_read_httppost(i,H);
2389       else
2390 #endif
2391 #ifdef SUPPORT_FTP
2392       if (H->t==FTPPASSIVE)
2393 	handle_read_ftppassive(i,H);
2394       else
2395 #endif
2396 #ifdef SUPPORT_HTTPS
2397       if (H->t==HTTPSACCEPT || H->t==HTTPSACCEPT_CHECK)
2398 	do_sslaccept(i,H,1);
2399       else
2400 #endif
2401       if (is_server_connection(H->t)) {
2402 #ifdef SUPPORT_HTTPS
2403 	if (ssh_timeout && (H->t == HTTPSSERVER6 || H->t == HTTPSSERVER4))
2404 	  accept_server_connection(i,H,ssh_timeout,nexthttps);
2405 	else
2406 #endif
2407 	accept_server_connection(i,H,ftptimeout_secs,nextftp);
2408       }
2409       else {
2410 #ifdef SUPPORT_HTTPS
2411 	/* This looks wrong but isn't.  SSL has renegotiation.
2412 	   If that happens, we can be waiting for read when we are actually trying to write something */
2413 	if (H->t == HTTPSRESPONSE)
2414 	  handle_write_misc(i,H,prefetchquantum);
2415 	else
2416 #endif
2417 	handle_read_misc(i,H,ftptimeout_secs,nextftp);
2418       }
2419     }
2420 
2421     /* HANDLE WRITABLE EVENTS */
2422     while ((i=io_canwrite())!=-1) {
2423       struct http_data* h=io_getcookie(i);
2424       ++eps1;
2425       if (!h) {
2426 	char a[FMT_ULONG];
2427 	a[fmt_ulong(a,i)]=0;
2428 	buffer_putmflush(buffer_2,"canthappen ",a,": got write event on socket with no cookie!\n");
2429 	io_dontwantwrite(i);
2430 	io_close(i);
2431 	continue;
2432       }
2433 
2434 #ifdef SMDEBUG
2435       {
2436 	char a[FMT_ULONG];
2437 	a[fmt_ulong(a,i)]=0;
2438 	buffer_putmflush(buffer_2,"DEBUG: fd ",a," got WRITE event, state is ",state2string(h->t),"!\n");
2439       }
2440 #endif
2441 
2442       if (++events==10) {
2443 	events=0;
2444 	accept_server_connection(s,(struct http_data*)&ct,ftptimeout_secs,nextftp);
2445 #ifdef SUPPORT_FTP
2446 	if (f!=-1) accept_server_connection(f,(struct http_data*)&fct,ftptimeout_secs,nextftp);
2447 #endif
2448 #ifdef SUPPORT_HTTPS
2449 	if (httpss!=-1) {
2450 	  if (ssh_timeout)
2451 	    accept_server_connection(httpss,(struct http_data*)&httpsct,ssh_timeout,nexthttps);
2452 	  else
2453 	    accept_server_connection(httpss,(struct http_data*)&httpsct,ftptimeout_secs,nextftp);
2454 	}
2455 #endif
2456 #ifdef __broken_itojun_v6__
2457 	if (s4!=-1) accept_server_connection(s4,(struct http_data*)&ct4,ftptimeout_secs,nextftp);
2458 #ifdef SUPPORT_FTP
2459 	if (f4!=-1) accept_server_connection(f4,(struct http_data*)&fct4,ftptimeout_secs,nextftp);
2460 #endif
2461 #ifdef SUPPORT_HTTPS
2462 	if (httpss4!=-1) {
2463 	  if (ssh_timeout)
2464 	    accept_server_connection(httpss4,(struct http_data*)&httpsct4,ssh_timeout,nexthttps);
2465 	  else
2466 	    accept_server_connection(httpss4,(struct http_data*)&httpsct4,ftptimeout_secs,nextftp);
2467 	}
2468 #endif
2469 #endif
2470       }
2471 
2472 #ifdef SUPPORT_FTP
2473       if (h->t==FTPCONTROL4 || h->t==FTPCONTROL6) {
2474 	if (ftptimeout_secs)
2475 	  io_timeout(i,nextftp);
2476       } else
2477 #endif
2478       if (timeout_secs) {
2479 	io_timeout(i,next);
2480 	if (h->buddy>0) {
2481 #ifdef SUPPORT_FTP
2482 	  if (h->t==FTPSLAVE) {
2483 	    io_timeout(h->buddy,nextftp);
2484 	  } else
2485 #endif
2486 	    io_timeout(h->buddy,next);
2487 	}
2488       }
2489 
2490 #ifdef SUPPORT_PROXY
2491       if (h->t==PROXYSLAVE)
2492 	handle_write_proxyslave(i,h);
2493       else if (h->t==PROXYPOST)
2494 	handle_write_proxypost(i,h);
2495       else if (h->t==HTTPPOST
2496 #ifdef SUPPORT_HTTPS
2497 	    || h->t==HTTPSPOST
2498 #endif
2499 			      )
2500 	handle_write_httppost(i,h);
2501       else
2502 #endif
2503 #ifdef SUPPORT_HTTPS
2504       if (h->t==HTTPSACCEPT)
2505 	do_sslaccept(i,h,0);
2506       else if (h->t == HTTPSREQUEST)
2507 	handle_read_misc(i,h,ftptimeout_secs,nextftp);
2508       else
2509 #endif
2510 #ifdef SUPPORT_FTP
2511       if (h->t==FTPACTIVE)
2512 	handle_write_ftpactive(i,h);
2513       else
2514 #endif
2515       {
2516 	if (handle_write_misc(i,h,prefetchquantum)==1)
2517 	  /* keep-alive && pipelining, generate read event on i */
2518 	  handle_incoming_data(i,h);
2519       }
2520     }
2521   }
2522 #ifdef SUPPORT_MULTIPROC
2523   if (instances) {
2524     unsigned long i;
2525     for (i=0; i<instances; ++i)
2526       kill(Instances[i],15);
2527   }
2528 #endif
2529   io_finishandshutdown();
2530 #ifdef SUPPORT_HTTPS
2531   free_tls_memory();
2532 #endif
2533 #ifdef SUPPORT_SMB
2534   {
2535     extern iconv_t wc2utf8;
2536     extern iconv_t utf82wc2;
2537     iconv_close(wc2utf8);
2538     iconv_close(utf82wc2);
2539   }
2540 #endif
2541   _exit(0);
2542   return 0;
2543 }
2544 
2545 #if 0
2546 int epoll_create(int i) { return -1; }
2547 #endif
2548