Check socket path length in OS_CreateLocalIpcFd() and OS_FcgiConnect()
[catagits/fcgi2.git] / libfcgi / os_unix.c
CommitLineData
aadcc3c8 1/*
0198fd3c 2 * os_unix.c --
3 *
0198fd3c 4 * Bill Snapper
5 * snapper@openmarket.com
89856cf4 6 *
7 * Copyright (c) 1996 Open Market, Inc.
8 *
9 * See the file "LICENSE" for information on usage and redistribution
10 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
0198fd3c 11 */
12
13#ifndef lint
2a7273a1 14static const char rcsid[] = "$Id: os_unix.c,v 1.38 2003/06/22 00:16:43 robs Exp $";
0198fd3c 15#endif /* not lint */
16
6ad90ad2 17#include "fcgi_config.h"
0198fd3c 18
27064097 19#include <sys/types.h>
20
8db9dd8f 21#ifdef HAVE_NETINET_IN_H
22#include <netinet/in.h>
23#endif
24
6ad90ad2 25#include <arpa/inet.h>
0198fd3c 26#include <assert.h>
0198fd3c 27#include <errno.h>
6ad90ad2 28#include <fcntl.h> /* for fcntl */
0198fd3c 29#include <math.h>
6ad90ad2 30#include <memory.h> /* for memchr() */
31#include <netinet/tcp.h>
32#include <stdarg.h>
33#include <stdio.h>
34#include <stdlib.h>
35#include <string.h>
36#include <sys/time.h>
0198fd3c 37#include <sys/un.h>
d0686b0d 38#include <signal.h>
6ad90ad2 39
0198fd3c 40#ifdef HAVE_NETDB_H
41#include <netdb.h>
42#endif
0198fd3c 43
6ad90ad2 44#ifdef HAVE_SYS_SOCKET_H
45#include <sys/socket.h> /* for getpeername */
46#endif
47
48#ifdef HAVE_UNISTD_H
49#include <unistd.h>
50#endif
51
52#include "fastcgi.h"
6ad90ad2 53#include "fcgimisc.h"
0198fd3c 54#include "fcgios.h"
55
03f366ba 56#ifndef INADDR_NONE
57#define INADDR_NONE ((unsigned long) -1)
58#endif
59
0198fd3c 60/*
61 * This structure holds an entry for each oustanding async I/O operation.
62 */
63typedef struct {
64 OS_AsyncProc procPtr; /* callout completion procedure */
65 ClientData clientData; /* caller private data */
66 int fd;
67 int len;
68 int offset;
69 void *buf;
70 int inUse;
71} AioInfo;
72
73/*
74 * Entries in the async I/O table are allocated 2 per file descriptor.
75 *
76 * Read Entry Index = fd * 2
77 * Write Entry Index = (fd * 2) + 1
78 */
79#define AIO_RD_IX(fd) (fd * 2)
80#define AIO_WR_IX(fd) ((fd * 2) + 1)
81
2b391aca 82static int asyncIoInUse = FALSE;
0198fd3c 83static int asyncIoTableSize = 16;
84static AioInfo *asyncIoTable = NULL;
0198fd3c 85
0198fd3c 86static int libInitialized = FALSE;
87
88static fd_set readFdSet;
89static fd_set writeFdSet;
90
91static fd_set readFdSetPost;
92static int numRdPosted = 0;
93static fd_set writeFdSetPost;
94static int numWrPosted = 0;
95static int volatile maxFd = -1;
96
d0686b0d 97static int shutdownPending = FALSE;
98static int shutdownNow = FALSE;
99
d0686b0d 100void OS_ShutdownPending()
101{
102 shutdownPending = TRUE;
103}
104
994e1bb8 105static void OS_Sigusr1Handler(int signo)
d0686b0d 106{
107 OS_ShutdownPending();
108}
109
994e1bb8 110static void OS_SigpipeHandler(int signo)
d0686b0d 111{
112 ;
113}
114
115static void installSignalHandler(int signo, const struct sigaction * act, int force)
116{
117 struct sigaction sa;
118
119 sigaction(signo, NULL, &sa);
120
121 if (force || sa.sa_handler == SIG_DFL)
122 {
123 sigaction(signo, act, NULL);
124 }
125}
126
994e1bb8 127static void OS_InstallSignalHandlers(int force)
d0686b0d 128{
129 struct sigaction sa;
130
131 sigemptyset(&sa.sa_mask);
132 sa.sa_flags = 0;
133
134 sa.sa_handler = OS_SigpipeHandler;
135 installSignalHandler(SIGPIPE, &sa, force);
136
137 sa.sa_handler = OS_Sigusr1Handler;
138 installSignalHandler(SIGUSR1, &sa, force);
d0686b0d 139}
140
0198fd3c 141/*
142 *--------------------------------------------------------------
143 *
144 * OS_LibInit --
145 *
146 * Set up the OS library for use.
147 *
148 * NOTE: This function is really only needed for application
149 * asynchronous I/O. It will most likely change in the
150 * future to setup the multi-threaded environment.
151 *
152 * Results:
153 * Returns 0 if success, -1 if not.
154 *
155 * Side effects:
156 * Async I/O table allocated and initialized.
157 *
158 *--------------------------------------------------------------
159 */
160int OS_LibInit(int stdioFds[3])
161{
162 if(libInitialized)
163 return 0;
aadcc3c8 164
165 asyncIoTable = (AioInfo *)malloc(asyncIoTableSize * sizeof(AioInfo));
0198fd3c 166 if(asyncIoTable == NULL) {
167 errno = ENOMEM;
168 return -1;
169 }
170 memset((char *) asyncIoTable, 0,
171 asyncIoTableSize * sizeof(AioInfo));
172
173 FD_ZERO(&readFdSet);
174 FD_ZERO(&writeFdSet);
175 FD_ZERO(&readFdSetPost);
176 FD_ZERO(&writeFdSetPost);
d0686b0d 177
9ab74998 178 OS_InstallSignalHandlers(TRUE);
d0686b0d 179
0198fd3c 180 libInitialized = TRUE;
d0686b0d 181
0198fd3c 182 return 0;
183}
184
0198fd3c 185/*
186 *--------------------------------------------------------------
187 *
188 * OS_LibShutdown --
189 *
190 * Shutdown the OS library.
191 *
192 * Results:
193 * None.
194 *
195 * Side effects:
196 * Memory freed, fds closed.
197 *
198 *--------------------------------------------------------------
199 */
200void OS_LibShutdown()
201{
202 if(!libInitialized)
203 return;
aadcc3c8 204
0198fd3c 205 free(asyncIoTable);
206 asyncIoTable = NULL;
207 libInitialized = FALSE;
208 return;
209}
210
0198fd3c 211/*
212 *----------------------------------------------------------------------
213 *
214 * OS_BuildSockAddrUn --
215 *
216 * Using the pathname bindPath, fill in the sockaddr_un structure
217 * *servAddrPtr and the length of this structure *servAddrLen.
218 *
219 * The format of the sockaddr_un structure changed incompatibly in
220 * 4.3BSD Reno. Digital UNIX supports both formats, other systems
221 * support one or the other.
222 *
223 * Results:
224 * 0 for normal return, -1 for failure (bindPath too long).
225 *
226 *----------------------------------------------------------------------
227 */
228
0b7c9662 229static int OS_BuildSockAddrUn(const char *bindPath,
0198fd3c 230 struct sockaddr_un *servAddrPtr,
231 int *servAddrLen)
232{
233 int bindPathLen = strlen(bindPath);
234
235#ifdef HAVE_SOCKADDR_UN_SUN_LEN /* 4.3BSD Reno and later: BSDI, DEC */
236 if(bindPathLen >= sizeof(servAddrPtr->sun_path)) {
237 return -1;
238 }
239#else /* 4.3 BSD Tahoe: Solaris, HPUX, DEC, ... */
240 if(bindPathLen > sizeof(servAddrPtr->sun_path)) {
241 return -1;
242 }
243#endif
244 memset((char *) servAddrPtr, 0, sizeof(*servAddrPtr));
245 servAddrPtr->sun_family = AF_UNIX;
246 memcpy(servAddrPtr->sun_path, bindPath, bindPathLen);
247#ifdef HAVE_SOCKADDR_UN_SUN_LEN /* 4.3BSD Reno and later: BSDI, DEC */
248 *servAddrLen = sizeof(servAddrPtr->sun_len)
249 + sizeof(servAddrPtr->sun_family)
250 + bindPathLen + 1;
251 servAddrPtr->sun_len = *servAddrLen;
252#else /* 4.3 BSD Tahoe: Solaris, HPUX, DEC, ... */
253 *servAddrLen = sizeof(servAddrPtr->sun_family) + bindPathLen;
254#endif
255 return 0;
256}
0198fd3c 257union SockAddrUnion {
258 struct sockaddr_un unixVariant;
259 struct sockaddr_in inetVariant;
260};
261
0198fd3c 262/*
263 * OS_CreateLocalIpcFd --
264 *
265 * This procedure is responsible for creating the listener socket
266 * on Unix for local process communication. It will create a
267 * domain socket or a TCP/IP socket bound to "localhost" and return
268 * a file descriptor to it to the caller.
269 *
270 * Results:
271 * Listener socket created. This call returns either a valid
272 * file descriptor or -1 on error.
273 *
274 * Side effects:
275 * None.
276 *
277 *----------------------------------------------------------------------
278 */
0b7c9662 279int OS_CreateLocalIpcFd(const char *bindPath, int backlog)
0198fd3c 280{
281 int listenSock, servLen;
630ce256 282 union SockAddrUnion sa;
0198fd3c 283 int tcp = FALSE;
9f2857f4 284 unsigned long tcp_ia = 0;
0198fd3c 285 char *tp;
9f2857f4 286 short port = 0;
0198fd3c 287 char host[MAXPATHLEN];
288
d4be70bd 289 if (strlen(bindPath) >= MAXPATHLEN) {
290 fprintf(stderr,
291 "Listening socket path is longer than %d bytes -- exiting!\n",
292 MAXPATHLEN);
293 exit(1);
294 }
0198fd3c 295 strcpy(host, bindPath);
296 if((tp = strchr(host, ':')) != 0) {
297 *tp++ = 0;
298 if((port = atoi(tp)) == 0) {
299 *--tp = ':';
300 } else {
301 tcp = TRUE;
302 }
303 }
03f366ba 304 if(tcp) {
305 if (!*host || !strcmp(host,"*")) {
306 tcp_ia = htonl(INADDR_ANY);
307 } else {
308 tcp_ia = inet_addr(host);
309 if (tcp_ia == INADDR_NONE) {
310 struct hostent * hep;
311 hep = gethostbyname(host);
312 if ((!hep) || (hep->h_addrtype != AF_INET || !hep->h_addr_list[0])) {
313 fprintf(stderr, "Cannot resolve host name %s -- exiting!\n", host);
314 exit(1);
315 }
316 if (hep->h_addr_list[1]) {
317 fprintf(stderr, "Host %s has multiple addresses ---\n", host);
318 fprintf(stderr, "you must choose one explicitly!!!\n");
319 exit(1);
320 }
321 tcp_ia = ((struct in_addr *) (hep->h_addr))->s_addr;
322 }
323 }
0198fd3c 324 }
325
326 if(tcp) {
327 listenSock = socket(AF_INET, SOCK_STREAM, 0);
328 if(listenSock >= 0) {
329 int flag = 1;
330 if(setsockopt(listenSock, SOL_SOCKET, SO_REUSEADDR,
331 (char *) &flag, sizeof(flag)) < 0) {
332 fprintf(stderr, "Can't set SO_REUSEADDR.\n");
333 exit(1001);
334 }
335 }
336 } else {
337 listenSock = socket(AF_UNIX, SOCK_STREAM, 0);
338 }
339 if(listenSock < 0) {
340 return -1;
341 }
342
343 /*
344 * Bind the listening socket.
345 */
346 if(tcp) {
347 memset((char *) &sa.inetVariant, 0, sizeof(sa.inetVariant));
348 sa.inetVariant.sin_family = AF_INET;
03f366ba 349 sa.inetVariant.sin_addr.s_addr = tcp_ia;
0198fd3c 350 sa.inetVariant.sin_port = htons(port);
351 servLen = sizeof(sa.inetVariant);
352 } else {
353 unlink(bindPath);
354 if(OS_BuildSockAddrUn(bindPath, &sa.unixVariant, &servLen)) {
355 fprintf(stderr, "Listening socket's path name is too long.\n");
356 exit(1000);
357 }
358 }
359 if(bind(listenSock, (struct sockaddr *) &sa.unixVariant, servLen) < 0
0b7c9662 360 || listen(listenSock, backlog) < 0) {
0198fd3c 361 perror("bind/listen");
362 exit(errno);
363 }
364
365 return listenSock;
366}
367
0198fd3c 368/*
369 *----------------------------------------------------------------------
370 *
371 * OS_FcgiConnect --
372 *
373 * Create the socket and connect to the remote application if
374 * possible.
375 *
376 * This was lifted from the cgi-fcgi application and was abstracted
377 * out because Windows NT does not have a domain socket and must
378 * use a named pipe which has a different API altogether.
379 *
380 * Results:
381 * -1 if fail or a valid file descriptor if connection succeeds.
382 *
383 * Side effects:
384 * Remote connection established.
385 *
386 *----------------------------------------------------------------------
387 */
388int OS_FcgiConnect(char *bindPath)
389{
390 union SockAddrUnion sa;
391 int servLen, resultSock;
392 int connectStatus;
393 char *tp;
394 char host[MAXPATHLEN];
df986e9d 395 short port = 0;
0198fd3c 396 int tcp = FALSE;
397
d4be70bd 398 if (strlen(bindPath) >= MAXPATHLEN) {
399 fprintf(stderr, "Listening socket path is too long\n");
400 exit(1000);
401 }
0198fd3c 402 strcpy(host, bindPath);
403 if((tp = strchr(host, ':')) != 0) {
404 *tp++ = 0;
405 if((port = atoi(tp)) == 0) {
406 *--tp = ':';
407 } else {
408 tcp = TRUE;
409 }
410 }
411 if(tcp == TRUE) {
412 struct hostent *hp;
413 if((hp = gethostbyname((*host ? host : "localhost"))) == NULL) {
414 fprintf(stderr, "Unknown host: %s\n", bindPath);
415 exit(1000);
416 }
417 sa.inetVariant.sin_family = AF_INET;
203fd55e 418 memcpy(&sa.inetVariant.sin_addr, hp->h_addr, hp->h_length);
0198fd3c 419 sa.inetVariant.sin_port = htons(port);
420 servLen = sizeof(sa.inetVariant);
421 resultSock = socket(AF_INET, SOCK_STREAM, 0);
422 } else {
423 if(OS_BuildSockAddrUn(bindPath, &sa.unixVariant, &servLen)) {
424 fprintf(stderr, "Listening socket's path name is too long.\n");
425 exit(1000);
426 }
427 resultSock = socket(AF_UNIX, SOCK_STREAM, 0);
428 }
429
6f902b14 430 ASSERT(resultSock >= 0);
0198fd3c 431 connectStatus = connect(resultSock, (struct sockaddr *) &sa.unixVariant,
432 servLen);
433 if(connectStatus >= 0) {
434 return resultSock;
435 } else {
436 /*
437 * Most likely (errno == ENOENT || errno == ECONNREFUSED)
438 * and no FCGI application server is running.
439 */
440 close(resultSock);
441 return -1;
442 }
443}
aadcc3c8 444
0198fd3c 445/*
446 *--------------------------------------------------------------
447 *
448 * OS_Read --
449 *
450 * Pass through to the unix read function.
451 *
452 * Results:
453 * Returns number of byes read, 0, or -1 failure: errno
454 * contains actual error.
455 *
456 * Side effects:
457 * None.
458 *
459 *--------------------------------------------------------------
460 */
461int OS_Read(int fd, char * buf, size_t len)
462{
d0686b0d 463 if (shutdownNow) return -1;
0198fd3c 464 return(read(fd, buf, len));
465}
62e100c7 466
0198fd3c 467/*
468 *--------------------------------------------------------------
469 *
470 * OS_Write --
471 *
472 * Pass through to unix write function.
473 *
474 * Results:
475 * Returns number of byes read, 0, or -1 failure: errno
476 * contains actual error.
477 *
478 * Side effects:
479 * none.
480 *
481 *--------------------------------------------------------------
482 */
483int OS_Write(int fd, char * buf, size_t len)
484{
d0686b0d 485 if (shutdownNow) return -1;
0198fd3c 486 return(write(fd, buf, len));
487}
488
0198fd3c 489/*
490 *----------------------------------------------------------------------
491 *
492 * OS_SpawnChild --
493 *
494 * Spawns a new FastCGI listener process.
495 *
496 * Results:
497 * 0 if success, -1 if error.
498 *
499 * Side effects:
500 * Child process spawned.
501 *
502 *----------------------------------------------------------------------
503 */
504int OS_SpawnChild(char *appPath, int listenFd)
505{
506 int forkResult;
507
508 forkResult = fork();
509 if(forkResult < 0) {
510 exit(errno);
511 }
512
513 if(forkResult == 0) {
514 /*
515 * Close STDIN unconditionally. It's used by the parent
516 * process for CGI communication. The FastCGI applciation
517 * will be replacing this with the FastCGI listenFd IF
518 * STDIN_FILENO is the same as FCGI_LISTENSOCK_FILENO
519 * (which it is on Unix). Regardless, STDIN, STDOUT, and
520 * STDERR will be closed as the FastCGI process uses a
521 * multiplexed socket in their place.
522 */
523 close(STDIN_FILENO);
524
525 /*
526 * If the listenFd is already the value of FCGI_LISTENSOCK_FILENO
527 * we're set. If not, change it so the child knows where to
528 * get the listen socket from.
529 */
530 if(listenFd != FCGI_LISTENSOCK_FILENO) {
531 dup2(listenFd, FCGI_LISTENSOCK_FILENO);
532 close(listenFd);
533 }
534
535 close(STDOUT_FILENO);
536 close(STDERR_FILENO);
537
538 /*
539 * We're a child. Exec the application.
540 *
541 * XXX: entire environment passes through
542 */
543 execl(appPath, appPath, NULL);
544 /*
545 * XXX: Can't do this as we've already closed STDERR!!!
546 *
547 * perror("exec");
548 */
549 exit(errno);
550 }
551 return 0;
552}
553
0198fd3c 554/*
555 *--------------------------------------------------------------
556 *
557 * OS_AsyncReadStdin --
558 *
559 * This initiates an asynchronous read on the standard
560 * input handle.
561 *
562 * The abstraction is necessary because Windows NT does not
563 * have a clean way of "select"ing a file descriptor for
564 * I/O.
565 *
566 * Results:
567 * -1 if error, 0 otherwise.
568 *
569 * Side effects:
570 * Asynchronous bit is set in the readfd variable and
571 * request is enqueued.
572 *
573 *--------------------------------------------------------------
574 */
aadcc3c8 575int OS_AsyncReadStdin(void *buf, int len, OS_AsyncProc procPtr,
0198fd3c 576 ClientData clientData)
577{
578 int index = AIO_RD_IX(STDIN_FILENO);
579
2b391aca 580 asyncIoInUse = TRUE;
0198fd3c 581 ASSERT(asyncIoTable[index].inUse == 0);
582 asyncIoTable[index].procPtr = procPtr;
583 asyncIoTable[index].clientData = clientData;
584 asyncIoTable[index].fd = STDIN_FILENO;
585 asyncIoTable[index].len = len;
586 asyncIoTable[index].offset = 0;
587 asyncIoTable[index].buf = buf;
588 asyncIoTable[index].inUse = 1;
589 FD_SET(STDIN_FILENO, &readFdSet);
590 if(STDIN_FILENO > maxFd)
591 maxFd = STDIN_FILENO;
592 return 0;
593}
594
595static void GrowAsyncTable(void)
596{
597 int oldTableSize = asyncIoTableSize;
aadcc3c8 598
0198fd3c 599 asyncIoTableSize = asyncIoTableSize * 2;
aadcc3c8 600 asyncIoTable = (AioInfo *)realloc(asyncIoTable, asyncIoTableSize * sizeof(AioInfo));
0198fd3c 601 if(asyncIoTable == NULL) {
602 errno = ENOMEM;
603 exit(errno);
604 }
605 memset((char *) &asyncIoTable[oldTableSize], 0,
606 oldTableSize * sizeof(AioInfo));
607
608}
609
0198fd3c 610/*
611 *--------------------------------------------------------------
612 *
613 * OS_AsyncRead --
614 *
615 * This initiates an asynchronous read on the file
616 * handle which may be a socket or named pipe.
617 *
618 * We also must save the ProcPtr and ClientData, so later
619 * when the io completes, we know who to call.
620 *
621 * We don't look at any results here (the ReadFile may
622 * return data if it is cached) but do all completion
623 * processing in OS_Select when we get the io completion
624 * port done notifications. Then we call the callback.
625 *
626 * Results:
627 * -1 if error, 0 otherwise.
628 *
629 * Side effects:
630 * Asynchronous I/O operation is queued for completion.
631 *
632 *--------------------------------------------------------------
633 */
634int OS_AsyncRead(int fd, int offset, void *buf, int len,
635 OS_AsyncProc procPtr, ClientData clientData)
636{
637 int index = AIO_RD_IX(fd);
aadcc3c8 638
0198fd3c 639 ASSERT(asyncIoTable != NULL);
2b391aca 640 asyncIoInUse = TRUE;
0198fd3c 641
642 if(fd > maxFd)
643 maxFd = fd;
644
a34d549f 645 while (index >= asyncIoTableSize) {
0198fd3c 646 GrowAsyncTable();
647 }
648
649 ASSERT(asyncIoTable[index].inUse == 0);
650 asyncIoTable[index].procPtr = procPtr;
651 asyncIoTable[index].clientData = clientData;
652 asyncIoTable[index].fd = fd;
653 asyncIoTable[index].len = len;
654 asyncIoTable[index].offset = offset;
655 asyncIoTable[index].buf = buf;
656 asyncIoTable[index].inUse = 1;
657 FD_SET(fd, &readFdSet);
658 return 0;
659}
62e100c7 660
0198fd3c 661/*
662 *--------------------------------------------------------------
663 *
664 * OS_AsyncWrite --
665 *
666 * This initiates an asynchronous write on the "fake" file
667 * descriptor (which may be a file, socket, or named pipe).
668 * We also must save the ProcPtr and ClientData, so later
669 * when the io completes, we know who to call.
670 *
671 * We don't look at any results here (the WriteFile generally
672 * completes immediately) but do all completion processing
673 * in OS_DoIo when we get the io completion port done
674 * notifications. Then we call the callback.
675 *
676 * Results:
677 * -1 if error, 0 otherwise.
678 *
679 * Side effects:
680 * Asynchronous I/O operation is queued for completion.
681 *
682 *--------------------------------------------------------------
683 */
aadcc3c8 684int OS_AsyncWrite(int fd, int offset, void *buf, int len,
0198fd3c 685 OS_AsyncProc procPtr, ClientData clientData)
686{
687 int index = AIO_WR_IX(fd);
688
2b391aca 689 asyncIoInUse = TRUE;
690
0198fd3c 691 if(fd > maxFd)
692 maxFd = fd;
693
a34d549f 694 while (index >= asyncIoTableSize) {
0198fd3c 695 GrowAsyncTable();
696 }
697
698 ASSERT(asyncIoTable[index].inUse == 0);
699 asyncIoTable[index].procPtr = procPtr;
700 asyncIoTable[index].clientData = clientData;
701 asyncIoTable[index].fd = fd;
702 asyncIoTable[index].len = len;
703 asyncIoTable[index].offset = offset;
704 asyncIoTable[index].buf = buf;
705 asyncIoTable[index].inUse = 1;
706 FD_SET(fd, &writeFdSet);
707 return 0;
708}
62e100c7 709
0198fd3c 710/*
711 *--------------------------------------------------------------
712 *
713 * OS_Close --
714 *
715 * Closes the descriptor. This is a pass through to the
716 * Unix close.
717 *
718 * Results:
719 * 0 for success, -1 on failure
720 *
721 * Side effects:
722 * None.
723 *
724 *--------------------------------------------------------------
725 */
2a7273a1 726int OS_Close(int fd, int shutdown_ok)
0198fd3c 727{
8462b1ec 728 if (fd == -1)
729 return 0;
730
c92b39ad 731 if (asyncIoInUse) {
2b391aca 732 int index = AIO_RD_IX(fd);
aadcc3c8 733
2b391aca 734 FD_CLR(fd, &readFdSet);
735 FD_CLR(fd, &readFdSetPost);
736 if (asyncIoTable[index].inUse != 0) {
737 asyncIoTable[index].inUse = 0;
738 }
739
740 FD_CLR(fd, &writeFdSet);
741 FD_CLR(fd, &writeFdSetPost);
742 index = AIO_WR_IX(fd);
743 if (asyncIoTable[index].inUse != 0) {
744 asyncIoTable[index].inUse = 0;
745 }
aadcc3c8 746
2b391aca 747 if (maxFd == fd) {
748 maxFd--;
749 }
0198fd3c 750 }
69d80725 751
752 /*
753 * shutdown() the send side and then read() from client until EOF
754 * or a timeout expires. This is done to minimize the potential
755 * that a TCP RST will be sent by our TCP stack in response to
756 * receipt of additional data from the client. The RST would
757 * cause the client to discard potentially useful response data.
758 */
759
2a7273a1 760 if (shutdown_ok)
69d80725 761 {
2a7273a1 762 if (shutdown(fd, 1) == 0)
69d80725 763 {
2a7273a1 764 struct timeval tv;
765 fd_set rfds;
766 int rv;
767 char trash[1024];
768
769 FD_ZERO(&rfds);
770
771 do
772 {
773 FD_SET(fd, &rfds);
774 tv.tv_sec = 2;
775 tv.tv_usec = 0;
776 rv = select(fd + 1, &rfds, NULL, NULL, &tv);
777 }
778 while (rv > 0 && read(fd, trash, sizeof(trash)) > 0);
69d80725 779 }
69d80725 780 }
781
0198fd3c 782 return close(fd);
783}
62e100c7 784
0198fd3c 785/*
786 *--------------------------------------------------------------
787 *
788 * OS_CloseRead --
789 *
790 * Cancel outstanding asynchronous reads and prevent subsequent
791 * reads from completing.
792 *
793 * Results:
794 * Socket or file is shutdown. Return values mimic Unix shutdown:
795 * 0 success, -1 failure
796 *
797 *--------------------------------------------------------------
798 */
799int OS_CloseRead(int fd)
800{
801 if(asyncIoTable[AIO_RD_IX(fd)].inUse != 0) {
802 asyncIoTable[AIO_RD_IX(fd)].inUse = 0;
803 FD_CLR(fd, &readFdSet);
804 }
aadcc3c8 805
0198fd3c 806 return shutdown(fd, 0);
807}
808
0198fd3c 809/*
810 *--------------------------------------------------------------
811 *
812 * OS_DoIo --
813 *
814 * This function was formerly OS_Select. It's purpose is
815 * to pull I/O completion events off the queue and dispatch
816 * them to the appropriate place.
817 *
818 * Results:
819 * Returns 0.
820 *
821 * Side effects:
822 * Handlers are called.
823 *
824 *--------------------------------------------------------------
825 */
826int OS_DoIo(struct timeval *tmo)
827{
828 int fd, len, selectStatus;
829 OS_AsyncProc procPtr;
830 ClientData clientData;
831 AioInfo *aioPtr;
832 fd_set readFdSetCpy;
833 fd_set writeFdSetCpy;
834
2b391aca 835 asyncIoInUse = TRUE;
0198fd3c 836 FD_ZERO(&readFdSetCpy);
837 FD_ZERO(&writeFdSetCpy);
838
839 for(fd = 0; fd <= maxFd; fd++) {
840 if(FD_ISSET(fd, &readFdSet)) {
841 FD_SET(fd, &readFdSetCpy);
842 }
843 if(FD_ISSET(fd, &writeFdSet)) {
844 FD_SET(fd, &writeFdSetCpy);
845 }
846 }
aadcc3c8 847
0198fd3c 848 /*
849 * If there were no completed events from a prior call, see if there's
850 * any work to do.
851 */
852 if(numRdPosted == 0 && numWrPosted == 0) {
853 selectStatus = select((maxFd+1), &readFdSetCpy, &writeFdSetCpy,
854 NULL, tmo);
855 if(selectStatus < 0) {
856 exit(errno);
857 }
858
859 for(fd = 0; fd <= maxFd; fd++) {
860 /*
861 * Build up a list of completed events. We'll work off of
862 * this list as opposed to looping through the read and write
863 * fd sets since they can be affected by a callbacl routine.
864 */
865 if(FD_ISSET(fd, &readFdSetCpy)) {
866 numRdPosted++;
867 FD_SET(fd, &readFdSetPost);
868 FD_CLR(fd, &readFdSet);
869 }
870
871 if(FD_ISSET(fd, &writeFdSetCpy)) {
872 numWrPosted++;
873 FD_SET(fd, &writeFdSetPost);
874 FD_CLR(fd, &writeFdSet);
875 }
876 }
877 }
878
879 if(numRdPosted == 0 && numWrPosted == 0)
880 return 0;
aadcc3c8 881
0198fd3c 882 for(fd = 0; fd <= maxFd; fd++) {
883 /*
884 * Do reads and dispatch callback.
885 */
aadcc3c8 886 if(FD_ISSET(fd, &readFdSetPost)
0198fd3c 887 && asyncIoTable[AIO_RD_IX(fd)].inUse) {
888
889 numRdPosted--;
890 FD_CLR(fd, &readFdSetPost);
891 aioPtr = &asyncIoTable[AIO_RD_IX(fd)];
aadcc3c8 892
0198fd3c 893 len = read(aioPtr->fd, aioPtr->buf, aioPtr->len);
894
895 procPtr = aioPtr->procPtr;
896 aioPtr->procPtr = NULL;
897 clientData = aioPtr->clientData;
898 aioPtr->inUse = 0;
899
900 (*procPtr)(clientData, len);
901 }
902
903 /*
904 * Do writes and dispatch callback.
905 */
906 if(FD_ISSET(fd, &writeFdSetPost) &&
907 asyncIoTable[AIO_WR_IX(fd)].inUse) {
908
909 numWrPosted--;
910 FD_CLR(fd, &writeFdSetPost);
911 aioPtr = &asyncIoTable[AIO_WR_IX(fd)];
aadcc3c8 912
0198fd3c 913 len = write(aioPtr->fd, aioPtr->buf, aioPtr->len);
914
915 procPtr = aioPtr->procPtr;
916 aioPtr->procPtr = NULL;
917 clientData = aioPtr->clientData;
918 aioPtr->inUse = 0;
919 (*procPtr)(clientData, len);
920 }
921 }
922 return 0;
923}
924
226e4c76 925/*
926 * Not all systems have strdup().
927 * @@@ autoconf should determine whether or not this is needed, but for now..
928 */
37605d3c 929static char * str_dup(const char * str)
226e4c76 930{
931 char * sdup = (char *) malloc(strlen(str) + 1);
932
933 if (sdup)
934 strcpy(sdup, str);
935
936 return sdup;
937}
938
0198fd3c 939/*
940 *----------------------------------------------------------------------
941 *
942 * ClientAddrOK --
943 *
944 * Checks if a client address is in a list of allowed addresses
945 *
946 * Results:
947 * TRUE if address list is empty or client address is present
948 * in the list, FALSE otherwise.
949 *
950 *----------------------------------------------------------------------
951 */
0b7c9662 952static int ClientAddrOK(struct sockaddr_in *saPtr, const char *clientList)
0198fd3c 953{
954 int result = FALSE;
955 char *clientListCopy, *cur, *next;
0198fd3c 956
226e4c76 957 if (clientList == NULL || *clientList == '\0') {
0198fd3c 958 return TRUE;
959 }
960
226e4c76 961 clientListCopy = str_dup(clientList);
aadcc3c8 962
226e4c76 963 for (cur = clientListCopy; cur != NULL; cur = next) {
0198fd3c 964 next = strchr(cur, ',');
226e4c76 965 if (next != NULL) {
0198fd3c 966 *next++ = '\0';
226e4c76 967 }
968 if (inet_addr(cur) == saPtr->sin_addr.s_addr) {
0198fd3c 969 result = TRUE;
970 break;
971 }
972 }
226e4c76 973
0198fd3c 974 free(clientListCopy);
975 return result;
976}
977
0198fd3c 978/*
979 *----------------------------------------------------------------------
980 *
981 * AcquireLock --
982 *
983 * On platforms that implement concurrent calls to accept
984 * on a shared listening ipcFd, returns 0. On other platforms,
985 * acquires an exclusive lock across all processes sharing a
986 * listening ipcFd, blocking until the lock has been acquired.
987 *
988 * Results:
989 * 0 for successful call, -1 in case of system error (fatal).
990 *
991 * Side effects:
992 * This process now has the exclusive lock.
993 *
994 *----------------------------------------------------------------------
995 */
0b7c9662 996static int AcquireLock(int sock, int fail_on_intr)
0198fd3c 997{
998#ifdef USE_LOCKING
0b7c9662 999 do {
1000 struct flock lock;
1001 lock.l_type = F_WRLCK;
1002 lock.l_start = 0;
1003 lock.l_whence = SEEK_SET;
1004 lock.l_len = 0;
1005
1006 if (fcntl(sock, F_SETLKW, &lock) != -1)
1007 return 0;
98aeb41b 1008 } while (errno == EINTR
1009 && ! fail_on_intr
1010 && ! shutdownPending);
0b7c9662 1011
1012 return -1;
1013
1014#else
0198fd3c 1015 return 0;
0b7c9662 1016#endif
0198fd3c 1017}
62e100c7 1018
0198fd3c 1019/*
1020 *----------------------------------------------------------------------
1021 *
1022 * ReleaseLock --
1023 *
1024 * On platforms that implement concurrent calls to accept
1025 * on a shared listening ipcFd, does nothing. On other platforms,
1026 * releases an exclusive lock acquired by AcquireLock.
1027 *
1028 * Results:
1029 * 0 for successful call, -1 in case of system error (fatal).
1030 *
1031 * Side effects:
1032 * This process no longer holds the lock.
1033 *
1034 *----------------------------------------------------------------------
1035 */
0b7c9662 1036static int ReleaseLock(int sock)
0198fd3c 1037{
1038#ifdef USE_LOCKING
0b7c9662 1039 do {
1040 struct flock lock;
1041 lock.l_type = F_UNLCK;
1042 lock.l_start = 0;
1043 lock.l_whence = SEEK_SET;
1044 lock.l_len = 0;
1045
1046 if (fcntl(sock, F_SETLK, &lock) != -1)
1047 return 0;
1048 } while (errno == EINTR);
0198fd3c 1049
0b7c9662 1050 return -1;
1051
1052#else
0198fd3c 1053 return 0;
0b7c9662 1054#endif
0198fd3c 1055}
1056
69f62c0e 1057/**********************************************************************
aadcc3c8 1058 * Determine if the errno resulting from a failed accept() warrants a
69f62c0e 1059 * retry or exit(). Based on Apache's http_main.c accept() handling
1060 * and Stevens' Unix Network Programming Vol 1, 2nd Ed, para. 15.6.
1061 */
1062static int is_reasonable_accept_errno (const int error)
1063{
1064 switch (error) {
1065#ifdef EPROTO
aadcc3c8 1066 /* EPROTO on certain older kernels really means ECONNABORTED, so
1067 * we need to ignore it for them. See discussion in new-httpd
1068 * archives nh.9701 search for EPROTO. Also see nh.9603, search
1069 * for EPROTO: There is potentially a bug in Solaris 2.x x<6, and
1070 * other boxes that implement tcp sockets in userland (i.e. on top of
1071 * STREAMS). On these systems, EPROTO can actually result in a fatal
1072 * loop. See PR#981 for example. It's hard to handle both uses of
69f62c0e 1073 * EPROTO. */
1074 case EPROTO:
1075#endif
1076#ifdef ECONNABORTED
1077 case ECONNABORTED:
1078#endif
1079 /* Linux generates the rest of these, other tcp stacks (i.e.
1080 * bsd) tend to hide them behind getsockopt() interfaces. They
1081 * occur when the net goes sour or the client disconnects after the
1082 * three-way handshake has been done in the kernel but before
1083 * userland has picked up the socket. */
1084#ifdef ECONNRESET
1085 case ECONNRESET:
1086#endif
1087#ifdef ETIMEDOUT
1088 case ETIMEDOUT:
1089#endif
1090#ifdef EHOSTUNREACH
1091 case EHOSTUNREACH:
1092#endif
1093#ifdef ENETUNREACH
1094 case ENETUNREACH:
1095#endif
1096 return 1;
1097
1098 default:
1099 return 0;
1100 }
1101}
1102
1103/**********************************************************************
aadcc3c8 1104 * This works around a problem on Linux 2.0.x and SCO Unixware (maybe
1105 * others?). When a connect() is made to a Unix Domain socket, but its
1106 * not accept()ed before the web server gets impatient and close()s, an
1107 * accept() results in a valid file descriptor, but no data to read.
1108 * This causes a block on the first read() - which never returns!
1109 *
1110 * Another approach to this is to write() to the socket to provoke a
1111 * SIGPIPE, but this is a pain because of the FastCGI protocol, the fact
1112 * that whatever is written has to be universally ignored by all FastCGI
1113 * web servers, and a SIGPIPE handler has to be installed which returns
1114 * (or SIGPIPE is ignored).
1115 *
1116 * READABLE_UNIX_FD_DROP_DEAD_TIMEVAL = 2,0 by default.
1117 *
1118 * Making it shorter is probably safe, but I'll leave that to you. Making
1119 * it 0,0 doesn't work reliably. The shorter you can reliably make it,
1120 * the faster your application will be able to recover (waiting 2 seconds
1121 * may _cause_ the problem when there is a very high demand). At any rate,
1122 * this is better than perma-blocking.
1123 */
69f62c0e 1124static int is_af_unix_keeper(const int fd)
1125{
1126 struct timeval tval = { READABLE_UNIX_FD_DROP_DEAD_TIMEVAL };
1127 fd_set read_fds;
1128
1129 FD_ZERO(&read_fds);
1130 FD_SET(fd, &read_fds);
aadcc3c8 1131
69f62c0e 1132 return select(fd + 1, &read_fds, NULL, NULL, &tval) >= 0 && FD_ISSET(fd, &read_fds);
1133}
1134
0198fd3c 1135/*
1136 *----------------------------------------------------------------------
1137 *
0b7c9662 1138 * OS_Accept --
0198fd3c 1139 *
1140 * Accepts a new FastCGI connection. This routine knows whether
1141 * we're dealing with TCP based sockets or NT Named Pipes for IPC.
1142 *
1143 * Results:
1144 * -1 if the operation fails, otherwise this is a valid IPC fd.
1145 *
1146 * Side effects:
1147 * New IPC connection is accepted.
1148 *
1149 *----------------------------------------------------------------------
1150 */
1dd5d7a8 1151int OS_Accept(int listen_sock, int fail_on_intr, const char *webServerAddrs)
0198fd3c 1152{
d0686b0d 1153 int socket = -1;
69f62c0e 1154 union {
0198fd3c 1155 struct sockaddr_un un;
a3c43615 1156 struct sockaddr_in in;
0198fd3c 1157 } sa;
ed728efb 1158
0b7c9662 1159 for (;;) {
1160 if (AcquireLock(listen_sock, fail_on_intr))
1161 return -1;
a3c43615 1162
0b7c9662 1163 for (;;) {
69f62c0e 1164 do {
0b7c9662 1165#ifdef HAVE_SOCKLEN
1166 socklen_t len = sizeof(sa);
1167#else
1168 int len = sizeof(sa);
1169#endif
d0686b0d 1170 if (shutdownPending) break;
1171 /* There's a window here */
1172
0b7c9662 1173 socket = accept(listen_sock, (struct sockaddr *)&sa, &len);
d0686b0d 1174 } while (socket < 0
1175 && errno == EINTR
98aeb41b 1176 && ! fail_on_intr
1177 && ! shutdownPending);
a3c43615 1178
69f62c0e 1179 if (socket < 0) {
994e1bb8 1180 if (shutdownPending || ! is_reasonable_accept_errno(errno)) {
a3c43615 1181 int errnoSave = errno;
d0686b0d 1182
0b7c9662 1183 ReleaseLock(listen_sock);
d0686b0d 1184
994e1bb8 1185 if (! shutdownPending) {
d0686b0d 1186 errno = errnoSave;
1187 }
1188
69f62c0e 1189 return (-1);
a3c43615 1190 }
69f62c0e 1191 errno = 0;
1192 }
0b7c9662 1193 else { /* socket >= 0 */
69f62c0e 1194 int set = 1;
aadcc3c8 1195
69f62c0e 1196 if (sa.in.sin_family != AF_INET)
1197 break;
aadcc3c8 1198
69f62c0e 1199#ifdef TCP_NODELAY
1200 /* No replies to outgoing data, so disable Nagle */
1201 setsockopt(socket, IPPROTO_TCP, TCP_NODELAY, (char *)&set, sizeof(set));
aadcc3c8 1202#endif
1203
69f62c0e 1204 /* Check that the client IP address is approved */
1dd5d7a8 1205 if (ClientAddrOK(&sa.in, webServerAddrs))
69f62c0e 1206 break;
aadcc3c8 1207
69f62c0e 1208 close(socket);
0b7c9662 1209 } /* socket >= 0 */
1210 } /* for(;;) */
aadcc3c8 1211
0b7c9662 1212 if (ReleaseLock(listen_sock))
69f62c0e 1213 return (-1);
aadcc3c8 1214
69f62c0e 1215 if (sa.in.sin_family != AF_UNIX || is_af_unix_keeper(socket))
1216 break;
aadcc3c8 1217
69f62c0e 1218 close(socket);
1219 } /* while(1) - lock */
a3c43615 1220
a3c43615 1221 return (socket);
0198fd3c 1222}
62e100c7 1223
0198fd3c 1224/*
1225 *----------------------------------------------------------------------
1226 *
1227 * OS_IpcClose
1228 *
1229 * OS IPC routine to close an IPC connection.
1230 *
1231 * Results:
1232 *
1233 *
1234 * Side effects:
1235 * IPC connection is closed.
1236 *
1237 *----------------------------------------------------------------------
1238 */
2a7273a1 1239int OS_IpcClose(int ipcFd, int shutdown)
0198fd3c 1240{
2a7273a1 1241 return OS_Close(ipcFd, shutdown);
0198fd3c 1242}
1243
0198fd3c 1244/*
1245 *----------------------------------------------------------------------
1246 *
1247 * OS_IsFcgi --
1248 *
1249 * Determines whether this process is a FastCGI process or not.
1250 *
1251 * Results:
1252 * Returns 1 if FastCGI, 0 if not.
1253 *
1254 * Side effects:
1255 * None.
1256 *
1257 *----------------------------------------------------------------------
1258 */
0b7c9662 1259int OS_IsFcgi(int sock)
0198fd3c 1260{
b22c3782 1261 union {
1262 struct sockaddr_in in;
1263 struct sockaddr_un un;
1264 } sa;
8eac3e1b 1265#ifdef HAVE_SOCKLEN
ed728efb 1266 socklen_t len = sizeof(sa);
1267#else
b22c3782 1268 int len = sizeof(sa);
ed728efb 1269#endif
0198fd3c 1270
f43b4006 1271 errno = 0;
36c03862 1272
0b7c9662 1273 if (getpeername(sock, (struct sockaddr *)&sa, &len) != 0 && errno == ENOTCONN) {
1274 return TRUE;
1275 }
1276 else {
1277 return FALSE;
1278 }
0198fd3c 1279}
62e100c7 1280
0198fd3c 1281/*
1282 *----------------------------------------------------------------------
1283 *
1284 * OS_SetFlags --
1285 *
1286 * Sets selected flag bits in an open file descriptor.
1287 *
1288 *----------------------------------------------------------------------
1289 */
1290void OS_SetFlags(int fd, int flags)
1291{
1292 int val;
1293 if((val = fcntl(fd, F_GETFL, 0)) < 0) {
1294 exit(errno);
1295 }
1296 val |= flags;
1297 if(fcntl(fd, F_SETFL, val) < 0) {
1298 exit(errno);
1299 }
1300}