1 /*
2 +----------------------------------------------------------------------+
3 | PHP Version 7 |
4 +----------------------------------------------------------------------+
5 | Copyright (c) 1997-2018 The PHP Group |
6 +----------------------------------------------------------------------+
7 | This source file is subject to version 3.01 of the PHP license, |
8 | that is bundled with this package in the file LICENSE, and is |
9 | available at through the world-wide-web at the following url: |
10 | http://www.php.net/license/3_01.txt. |
11 | If you did not receive a copy of the PHP license and are unable to |
12 | obtain it through the world-wide-web, please send a note to |
13 | license@php.net so we can mail you a copy immediately. |
14 +----------------------------------------------------------------------+
15 | Author: George Wang <gwang@litespeedtech.com> |
16 +----------------------------------------------------------------------+
17 */
18
19 /*
20 Copyright (c) 2002-2018, Lite Speed Technologies Inc.
21 All rights reserved.
22
23 Redistribution and use in source and binary forms, with or without
24 modification, are permitted provided that the following conditions are
25 met:
26
27 * Redistributions of source code must retain the above copyright
28 notice, this list of conditions and the following disclaimer.
29 * Redistributions in binary form must reproduce the above
30 copyright notice, this list of conditions and the following
31 disclaimer in the documentation and/or other materials provided
32 with the distribution.
33 * Neither the name of the Lite Speed Technologies Inc nor the
34 names of its contributors may be used to endorse or promote
35 products derived from this software without specific prior
36 written permission.
37
38 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
39 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
40 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
41 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
42 OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
43 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
44 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
45 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
46 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
47 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
48 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
49 */
50
51
52 #include <ctype.h>
53 #include <dlfcn.h>
54 #include <errno.h>
55 #include <fcntl.h>
56 #include <limits.h>
57 #include <sys/stat.h>
58 #include <sched.h>
59 #include <signal.h>
60 #include <stdlib.h>
61 #include <stdio.h>
62 #include <stdarg.h>
63 #include <string.h>
64 #include <sys/mman.h>
65 #include <sys/resource.h>
66 #include <sys/socket.h>
67 #include <sys/time.h>
68 #include <sys/uio.h>
69 #include <sys/wait.h>
70 #include <grp.h>
71 #include <pwd.h>
72 #include <time.h>
73 #include <unistd.h>
74 #include <arpa/inet.h>
75 #include <netdb.h>
76 #include <netinet/in.h>
77 #include <netinet/tcp.h>
78 #include <sys/un.h>
79
80 #include "lsapilib.h"
81
82 #if defined(linux) || defined(__linux) || defined(__linux__) || defined(__gnu_linux__)
83 #include <sys/prctl.h>
84 #endif
85
86 #if defined(__FreeBSD__ ) || defined(__NetBSD__) || defined(__OpenBSD__) \
87 || defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__)
88 #include <sys/sysctl.h>
89 #endif
90
91 #include <inttypes.h>
92 #ifndef uint32
93 #define uint32 uint32_t
94 #endif
95
96 struct lsapi_MD5Context {
97 uint32 buf[4];
98 uint32 bits[2];
99 unsigned char in[64];
100 };
101
102 void lsapi_MD5Init(struct lsapi_MD5Context *context);
103 void lsapi_MD5Update(struct lsapi_MD5Context *context, unsigned char const *buf,
104 unsigned len);
105 void lsapi_MD5Final(unsigned char digest[16], struct lsapi_MD5Context *context);
106
107 /*
108 * This is needed to make RSAREF happy on some MS-DOS compilers.
109 */
110 typedef struct lsapi_MD5Context lsapi_MD5_CTX;
111
112
113 #define LSAPI_ST_REQ_HEADER 1
114 #define LSAPI_ST_REQ_BODY 2
115 #define LSAPI_ST_RESP_HEADER 4
116 #define LSAPI_ST_RESP_BODY 8
117 #define LSAPI_ST_BACKGROUND 16
118
119 #define LSAPI_RESP_BUF_SIZE 8192
120 #define LSAPI_INIT_RESP_HEADER_LEN 4096
121
122 enum
123 {
124 LSAPI_STATE_IDLE,
125 LSAPI_STATE_CONNECTED,
126 LSAPI_STATE_ACCEPTING,
127 };
128
129 typedef struct lsapi_child_status
130 {
131 int m_pid;
132 long m_tmStart;
133
134 volatile short m_iKillSent;
135 volatile char m_inProcess;
136 volatile char m_state;
137 volatile int m_iReqCounter;
138
139 volatile long m_tmWaitBegin;
140 volatile long m_tmReqBegin;
141 volatile long m_tmLastCheckPoint;
142 }
143 lsapi_child_status;
144
145 static lsapi_child_status * s_worker_status = NULL;
146
147 static int g_inited = 0;
148 static int g_running = 1;
149 static int s_ppid;
150 static int s_restored_ppid = 0;
151 static int s_pid = 0;
152 static int s_slow_req_msecs = 0;
153 static int s_keepListener = 0;
154 static int s_dump_debug_info = 0;
155 static int s_pid_dump_debug_info = 0;
156 static int s_req_processed = 0;
157 static int s_skip_write = 0;
158 static int (*pthread_atfork_func)(void (*prepare)(void), void (*parent)(void),
159 void (*child)(void)) = NULL;
160
161 static int *s_busy_workers = NULL;
162 static int *s_accepting_workers = NULL;
163 static int *s_global_counter = &s_req_processed;
164 static int s_max_busy_workers = -1;
165 static char *s_stderr_log_path = NULL;
166 static int s_stderr_is_pipe = 0;
167 static int s_ignore_pid = -1;
168 static size_t s_total_pages = 1;
169 static size_t s_min_avail_pages = 256 * 1024;
170 static size_t *s_avail_pages = &s_total_pages;
171
172 LSAPI_Request g_req =
173 { .m_fdListen = -1, .m_fd = -1 };
174
175 static char s_secret[24];
176
177 static LSAPI_On_Timer_pf s_proc_group_timer_cb = NULL;
178
179 void Flush_RespBuf_r( LSAPI_Request * pReq );
180 static int lsapi_reopen_stderr(const char *p);
181
182 static const char *CGI_HEADERS[H_TRANSFER_ENCODING+1] =
183 {
184 "HTTP_ACCEPT", "HTTP_ACCEPT_CHARSET",
185 "HTTP_ACCEPT_ENCODING",
186 "HTTP_ACCEPT_LANGUAGE", "HTTP_AUTHORIZATION",
187 "HTTP_CONNECTION", "CONTENT_TYPE",
188 "CONTENT_LENGTH", "HTTP_COOKIE", "HTTP_COOKIE2",
189 "HTTP_HOST", "HTTP_PRAGMA",
190 "HTTP_REFERER", "HTTP_USER_AGENT",
191 "HTTP_CACHE_CONTROL",
192 "HTTP_IF_MODIFIED_SINCE", "HTTP_IF_MATCH",
193 "HTTP_IF_NONE_MATCH",
194 "HTTP_IF_RANGE",
195 "HTTP_IF_UNMODIFIED_SINCE",
196 "HTTP_KEEP_ALIVE",
197 "HTTP_RANGE",
198 "HTTP_X_FORWARDED_FOR",
199 "HTTP_VIA",
200 "HTTP_TRANSFER_ENCODING"
201 };
202
203 static int CGI_HEADER_LEN[H_TRANSFER_ENCODING+1] =
204 { 11, 19, 20, 20, 18, 15, 12, 14, 11, 12, 9, 11, 12, 15, 18,
205 22, 13, 18, 13, 24, 15, 10, 20, 8, 22 };
206
207
208 static const char *HTTP_HEADERS[H_TRANSFER_ENCODING+1] =
209 {
210 "Accept", "Accept-Charset",
211 "Accept-Encoding",
212 "Accept-Language", "Authorization",
213 "Connection", "Content-Type",
214 "Content-Length", "Cookie", "Cookie2",
215 "Host", "Pragma",
216 "Referer", "User-Agent",
217 "Cache-Control",
218 "If-Modified-Since", "If-Match",
219 "If-None-Match",
220 "If-Range",
221 "If-Unmodified-Since",
222 "Keep-Alive",
223 "Range",
224 "X-Forwarded-For",
225 "Via",
226 "Transfer-Encoding"
227 };
228
229 static int HTTP_HEADER_LEN[H_TRANSFER_ENCODING+1] =
230 { 6, 14, 15, 15, 13, 10, 12, 14, 6, 7, 4, 6, 7, 10, //user-agent
231 13,17, 8, 13, 8, 19, 10, 5, 15, 3, 17
232 };
233
234
235 static const char *s_log_level_names[8] =
236 {
237 "", "DEBUG","INFO", "NOTICE", "WARN", "ERROR", "CRIT", "FATAL"
238 };
239
240
LSAPI_Log(int flag,const char * fmt,...)241 void LSAPI_Log(int flag, const char * fmt, ...)
242 {
243 char buf[1024];
244 char *p = buf;
245 if ((flag & LSAPI_LOG_TIMESTAMP_BITS) &&
246 !((flag & LSAPI_LOG_TIMESTAMP_STDERR) && s_stderr_is_pipe))
247 {
248 struct timeval tv;
249 struct tm tm;
250 gettimeofday(&tv, NULL);
251 localtime_r(&tv.tv_sec, &tm);
252 if (flag & LSAPI_LOG_TIMESTAMP_FULL)
253 {
254 p += snprintf(p, 1024, "%04d-%02d-%02d %02d:%02d:%02d.%06d ",
255 tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
256 tm.tm_hour, tm.tm_min, tm.tm_sec, (int)tv.tv_usec);
257 }
258 else if (flag & LSAPI_LOG_TIMESTAMP_HMS)
259 {
260 p += snprintf(p, 1024, "%02d:%02d:%02d ",
261 tm.tm_hour, tm.tm_min, tm.tm_sec);
262 }
263 }
264
265 int level = flag & LSAPI_LOG_LEVEL_BITS;
266 if (level && level <= LSAPI_LOG_FLAG_FATAL)
267 {
268 p += snprintf(p, 100, "[%s] ", s_log_level_names[level]);
269 }
270
271 if (flag & LSAPI_LOG_PID)
272 {
273 p += snprintf(p, 100, "[%d] ", s_pid);
274 }
275
276 if (p > buf)
277 fprintf(stderr, "%.*s", (int)(p - buf), buf);
278 va_list ap;
279 va_start(ap, fmt);
280 vfprintf(stderr, fmt, ap);
281 va_end(ap);
282 }
283
284 #ifdef LSAPI_DEBUG
285
286 #define DBGLOG_FLAG (LSAPI_LOG_TIMESTAMP_FULL|LSAPI_LOG_FLAG_DEBUG|LSAPI_LOG_PID)
287 #define lsapi_dbg(...) LSAPI_Log(DBGLOG_FLAG, __VA_ARGS__)
288
289 #else
290
291 #define lsapi_dbg(...)
292
293 #endif
294
295 #define lsapi_log(...) LSAPI_Log(LSAPI_LOG_TIMESTAMP_FULL|LSAPI_LOG_TIMESTAMP_STDERR|LSAPI_LOG_PID, __VA_ARGS__)
296
297
lsapi_parent_dead()298 static int lsapi_parent_dead()
299 {
300 // Return non-zero if the parent is dead. 0 if still alive.
301 if (!s_ppid) {
302 // not checking, so not dead
303 return(0);
304 }
305 if (s_restored_ppid) {
306 if (kill(s_restored_ppid,0) == -1) {
307 if (errno == EPERM) {
308 return(0); // no permission, but it's still there.
309 }
310 return(1); // Dead
311 }
312 return(0); // it worked, so it's not dead
313 }
314 return(s_ppid != getppid());
315 }
316
317
lsapi_sigpipe(int sig)318 static void lsapi_sigpipe( int sig )
319 {
320 }
321
322
lsapi_siguser1(int sig)323 static void lsapi_siguser1( int sig )
324 {
325 g_running = 0;
326 }
327
328 #ifndef sighandler_t
329 typedef void (*sighandler_t)(int);
330 #endif
331
lsapi_signal(int signo,sighandler_t handler)332 static void lsapi_signal(int signo, sighandler_t handler)
333 {
334 struct sigaction sa;
335
336 sigaction(signo, NULL, &sa);
337
338 if (sa.sa_handler == SIG_DFL)
339 {
340 sigemptyset(&sa.sa_mask);
341 sa.sa_flags = 0;
342 sa.sa_handler = handler;
343 sigaction(signo, &sa, NULL);
344 }
345 }
346
347
348 static int s_enable_core_dump = 0;
lsapi_enable_core_dump(void)349 static void lsapi_enable_core_dump(void)
350 {
351 #if defined(__FreeBSD__ ) || defined(__NetBSD__) || defined(__OpenBSD__) \
352 || defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__)
353 int mib[2];
354 size_t len;
355
356 len = 2;
357 if ( sysctlnametomib("kern.sugid_coredump", mib, &len) == 0 )
358 {
359 len = sizeof(s_enable_core_dump);
360 if (sysctl(mib, 2, NULL, 0, &s_enable_core_dump, len) == -1)
361 perror( "sysctl: Failed to set 'kern.sugid_coredump', "
362 "core dump may not be available!");
363 }
364
365
366 #endif
367
368 #if defined(linux) || defined(__linux) || defined(__linux__) || defined(__gnu_linux__)
369 if (prctl(PR_SET_DUMPABLE, s_enable_core_dump,0,0,0) == -1)
370 perror( "prctl: Failed to set dumpable, "
371 "core dump may not be available!");
372 #endif
373 }
374
375
lsapi_buildPacketHeader(struct lsapi_packet_header * pHeader,char type,int len)376 static inline void lsapi_buildPacketHeader( struct lsapi_packet_header * pHeader,
377 char type, int len )
378 {
379 pHeader->m_versionB0 = LSAPI_VERSION_B0; /* LSAPI protocol version */
380 pHeader->m_versionB1 = LSAPI_VERSION_B1;
381 pHeader->m_type = type;
382 pHeader->m_flag = LSAPI_ENDIAN;
383 pHeader->m_packetLen.m_iLen = len;
384 }
385
386
lsapi_set_nblock(int fd,int nonblock)387 static int lsapi_set_nblock( int fd, int nonblock )
388 {
389 int val = fcntl( fd, F_GETFL, 0 );
390 if ( nonblock )
391 {
392 if (!( val & O_NONBLOCK ))
393 {
394 return fcntl( fd, F_SETFL, val | O_NONBLOCK );
395 }
396 }
397 else
398 {
399 if ( val & O_NONBLOCK )
400 {
401 return fcntl( fd, F_SETFL, val &(~O_NONBLOCK) );
402 }
403 }
404 return 0;
405 }
406
407
lsapi_close(int fd)408 static int lsapi_close( int fd )
409 {
410 int ret;
411 while( 1 )
412 {
413 ret = close( fd );
414 if (( ret == -1 )&&( errno == EINTR )&&(g_running))
415 continue;
416 return ret;
417 }
418 }
419
420
lsapi_close_connection(LSAPI_Request * pReq)421 static void lsapi_close_connection(LSAPI_Request *pReq)
422 {
423 if (pReq->m_fd == -1)
424 return;
425 lsapi_close(pReq->m_fd);
426 pReq->m_fd = -1;
427 if (s_busy_workers)
428 __sync_fetch_and_sub(s_busy_workers, 1);
429 if (s_worker_status)
430 __sync_lock_test_and_set(&s_worker_status->m_state, LSAPI_STATE_IDLE);
431 }
432
433
lsapi_read(int fd,void * pBuf,size_t len)434 static inline ssize_t lsapi_read( int fd, void * pBuf, size_t len )
435 {
436 ssize_t ret;
437 while( 1 )
438 {
439 ret = read( fd, (char *)pBuf, len );
440 if (( ret == -1 )&&( errno == EINTR )&&(g_running))
441 continue;
442 return ret;
443 }
444 }
445
446
447 /*
448 static int lsapi_write( int fd, const void * pBuf, int len )
449 {
450 int ret;
451 const char * pCur;
452 const char * pEnd;
453 if ( len == 0 )
454 return 0;
455 pCur = (const char *)pBuf;
456 pEnd = pCur + len;
457 while( g_running && (pCur < pEnd) )
458 {
459 ret = write( fd, pCur, pEnd - pCur );
460 if ( ret >= 0)
461 pCur += ret;
462 else if (( ret == -1 )&&( errno != EINTR ))
463 return ret;
464 }
465 return pCur - (const char *)pBuf;
466 }
467 */
468
469
lsapi_writev(int fd,struct iovec ** pVec,int count,int totalLen)470 static int lsapi_writev( int fd, struct iovec ** pVec, int count, int totalLen )
471 {
472 int ret;
473 int left = totalLen;
474 int n = count;
475
476 if (s_skip_write)
477 return totalLen;
478
479 while(( left > 0 )&&g_running )
480 {
481 ret = writev( fd, *pVec, n );
482 if ( ret > 0 )
483 {
484 left -= ret;
485 if (( left <= 0)||( !g_running ))
486 return totalLen - left;
487 while( ret > 0 )
488 {
489 if ( (*pVec)->iov_len <= (unsigned int )ret )
490 {
491 ret -= (*pVec)->iov_len;
492 ++(*pVec);
493 }
494 else
495 {
496 (*pVec)->iov_base = (char *)(*pVec)->iov_base + ret;
497 (*pVec)->iov_len -= ret;
498 break;
499 }
500 }
501 }
502 else if ( ret == -1 )
503 {
504 if ( errno == EAGAIN )
505 {
506 if ( totalLen - left > 0 )
507 return totalLen - left;
508 else
509 return -1;
510 }
511 else if ( errno != EINTR )
512 return ret;
513 }
514 }
515 return totalLen - left;
516 }
517
518
519 /*
520 static int getTotalLen( struct iovec * pVec, int count )
521 {
522 struct iovec * pEnd = pVec + count;
523 int total = 0;
524 while( pVec < pEnd )
525 {
526 total += pVec->iov_len;
527 ++pVec;
528 }
529 return total;
530 }
531 */
532
533
allocateBuf(LSAPI_Request * pReq,int size)534 static inline int allocateBuf( LSAPI_Request * pReq, int size )
535 {
536 char * pBuf = (char *)realloc( pReq->m_pReqBuf, size );
537 if ( pBuf )
538 {
539 pReq->m_pReqBuf = pBuf;
540 pReq->m_reqBufSize = size;
541 pReq->m_pHeader = (struct lsapi_req_header *)pReq->m_pReqBuf;
542 return 0;
543 }
544 return -1;
545 }
546
547
allocateIovec(LSAPI_Request * pReq,int n)548 static int allocateIovec( LSAPI_Request * pReq, int n )
549 {
550 struct iovec * p = (struct iovec *)realloc(
551 pReq->m_pIovec, sizeof(struct iovec) * n );
552 if ( !p )
553 return -1;
554 pReq->m_pIovecToWrite = p + ( pReq->m_pIovecToWrite - pReq->m_pIovec );
555 pReq->m_pIovecCur = p + ( pReq->m_pIovecCur - pReq->m_pIovec );
556 pReq->m_pIovec = p;
557 pReq->m_pIovecEnd = p + n;
558 return 0;
559 }
560
561
allocateRespHeaderBuf(LSAPI_Request * pReq,int size)562 static int allocateRespHeaderBuf( LSAPI_Request * pReq, int size )
563 {
564 char * p = (char *)realloc( pReq->m_pRespHeaderBuf, size );
565 if ( !p )
566 return -1;
567 pReq->m_pRespHeaderBufPos = p + ( pReq->m_pRespHeaderBufPos - pReq->m_pRespHeaderBuf );
568 pReq->m_pRespHeaderBuf = p;
569 pReq->m_pRespHeaderBufEnd = p + size;
570 return 0;
571 }
572
573
verifyHeader(struct lsapi_packet_header * pHeader,char pktType)574 static inline int verifyHeader( struct lsapi_packet_header * pHeader, char pktType )
575 {
576 if (( LSAPI_VERSION_B0 != pHeader->m_versionB0 )||
577 ( LSAPI_VERSION_B1 != pHeader->m_versionB1 )||
578 ( pktType != pHeader->m_type ))
579 return -1;
580 if ( LSAPI_ENDIAN != (pHeader->m_flag & LSAPI_ENDIAN_BIT ))
581 {
582 register char b;
583 b = pHeader->m_packetLen.m_bytes[0];
584 pHeader->m_packetLen.m_bytes[0] = pHeader->m_packetLen.m_bytes[3];
585 pHeader->m_packetLen.m_bytes[3] = b;
586 b = pHeader->m_packetLen.m_bytes[1];
587 pHeader->m_packetLen.m_bytes[1] = pHeader->m_packetLen.m_bytes[2];
588 pHeader->m_packetLen.m_bytes[2] = b;
589 }
590 return pHeader->m_packetLen.m_iLen;
591 }
592
593
allocateEnvList(struct LSAPI_key_value_pair ** pEnvList,int * curSize,int newSize)594 static int allocateEnvList( struct LSAPI_key_value_pair ** pEnvList,
595 int *curSize, int newSize )
596 {
597 struct LSAPI_key_value_pair * pBuf;
598 if ( *curSize >= newSize )
599 return 0;
600 if ( newSize > 8192 )
601 return -1;
602 pBuf = (struct LSAPI_key_value_pair *)realloc( *pEnvList, newSize *
603 sizeof(struct LSAPI_key_value_pair) );
604 if ( pBuf )
605 {
606 *pEnvList = pBuf;
607 *curSize = newSize;
608 return 0;
609 }
610 else
611 return -1;
612
613 }
614
615
isPipe(int fd)616 static inline int isPipe( int fd )
617 {
618 char achPeer[128];
619 socklen_t len = 128;
620 if (( getpeername( fd, (struct sockaddr *)achPeer, &len ) != 0 )&&
621 ( errno == ENOTCONN ))
622 return 0;
623 else
624 return 1;
625 }
626
627
parseEnv(struct LSAPI_key_value_pair * pEnvList,int count,char ** pBegin,char * pEnd)628 static int parseEnv( struct LSAPI_key_value_pair * pEnvList, int count,
629 char **pBegin, char * pEnd )
630 {
631 struct LSAPI_key_value_pair * pEnvEnd;
632 int keyLen = 0, valLen = 0;
633 if ( count > 8192 )
634 return -1;
635 pEnvEnd = pEnvList + count;
636 while( pEnvList != pEnvEnd )
637 {
638 if ( pEnd - *pBegin < 4 )
639 return -1;
640 keyLen = *((unsigned char *)((*pBegin)++));
641 keyLen = (keyLen << 8) + *((unsigned char *)((*pBegin)++));
642 valLen = *((unsigned char *)((*pBegin)++));
643 valLen = (valLen << 8) + *((unsigned char *)((*pBegin)++));
644 if ( *pBegin + keyLen + valLen > pEnd )
645 return -1;
646 if (( !keyLen )||( !valLen ))
647 return -1;
648
649 pEnvList->pKey = *pBegin;
650 *pBegin += keyLen;
651 pEnvList->pValue = *pBegin;
652 *pBegin += valLen;
653
654 pEnvList->keyLen = keyLen - 1;
655 pEnvList->valLen = valLen - 1;
656 ++pEnvList;
657 }
658 if ( memcmp( *pBegin, "\0\0\0\0", 4 ) != 0 )
659 return -1;
660 *pBegin += 4;
661 return 0;
662 }
663
664
swapIntEndian(int * pInteger)665 static inline void swapIntEndian( int * pInteger )
666 {
667 char * p = (char *)pInteger;
668 register char b;
669 b = p[0];
670 p[0] = p[3];
671 p[3] = b;
672 b = p[1];
673 p[1] = p[2];
674 p[2] = b;
675
676 }
677
678
fixEndian(LSAPI_Request * pReq)679 static inline void fixEndian( LSAPI_Request * pReq )
680 {
681 struct lsapi_req_header *p= pReq->m_pHeader;
682 swapIntEndian( &p->m_httpHeaderLen );
683 swapIntEndian( &p->m_reqBodyLen );
684 swapIntEndian( &p->m_scriptFileOff );
685 swapIntEndian( &p->m_scriptNameOff );
686 swapIntEndian( &p->m_queryStringOff );
687 swapIntEndian( &p->m_requestMethodOff );
688 swapIntEndian( &p->m_cntUnknownHeaders );
689 swapIntEndian( &p->m_cntEnv );
690 swapIntEndian( &p->m_cntSpecialEnv );
691 }
692
693
fixHeaderIndexEndian(LSAPI_Request * pReq)694 static void fixHeaderIndexEndian( LSAPI_Request * pReq )
695 {
696 int i;
697 for( i = 0; i < H_TRANSFER_ENCODING; ++i )
698 {
699 if ( pReq->m_pHeaderIndex->m_headerOff[i] )
700 {
701 register char b;
702 char * p = (char *)(&pReq->m_pHeaderIndex->m_headerLen[i]);
703 b = p[0];
704 p[0] = p[1];
705 p[1] = b;
706 swapIntEndian( &pReq->m_pHeaderIndex->m_headerOff[i] );
707 }
708 }
709 if ( pReq->m_pHeader->m_cntUnknownHeaders > 0 )
710 {
711 struct lsapi_header_offset * pCur, *pEnd;
712 pCur = pReq->m_pUnknownHeader;
713 pEnd = pCur + pReq->m_pHeader->m_cntUnknownHeaders;
714 while( pCur < pEnd )
715 {
716 swapIntEndian( &pCur->nameOff );
717 swapIntEndian( &pCur->nameLen );
718 swapIntEndian( &pCur->valueOff );
719 swapIntEndian( &pCur->valueLen );
720 ++pCur;
721 }
722 }
723 }
724
725
validateHeaders(LSAPI_Request * pReq)726 static int validateHeaders( LSAPI_Request * pReq )
727 {
728 int totalLen = pReq->m_pHeader->m_httpHeaderLen;
729 int i;
730 for(i = 0; i < H_TRANSFER_ENCODING; ++i)
731 {
732 if ( pReq->m_pHeaderIndex->m_headerOff[i] )
733 {
734 if (pReq->m_pHeaderIndex->m_headerOff[i] > totalLen
735 || pReq->m_pHeaderIndex->m_headerLen[i]
736 + pReq->m_pHeaderIndex->m_headerOff[i] > totalLen)
737 return -1;
738 }
739 }
740 if (pReq->m_pHeader->m_cntUnknownHeaders > 0)
741 {
742 struct lsapi_header_offset * pCur, *pEnd;
743 pCur = pReq->m_pUnknownHeader;
744 pEnd = pCur + pReq->m_pHeader->m_cntUnknownHeaders;
745 while( pCur < pEnd )
746 {
747 if (pCur->nameOff > totalLen
748 || pCur->nameOff + pCur->nameLen > totalLen
749 || pCur->valueOff > totalLen
750 || pCur->valueOff + pCur->valueLen > totalLen)
751 return -1;
752 ++pCur;
753 }
754 }
755 return 0;
756 }
757
758
759 static uid_t s_uid = 0;
760 static uid_t s_defaultUid; //web server need set this
761 static gid_t s_defaultGid;
762
763 #if defined(linux) || defined(__linux) || defined(__linux__) || defined(__gnu_linux__)
764
765 #define LSAPI_LVE_DISABLED 0
766 #define LSAPI_LVE_ENABLED 1
767 #define LSAPI_CAGEFS_ENABLED 2
768 #define LSAPI_CAGEFS_NO_SUEXEC 3
769 struct liblve;
770 static int s_enable_lve = LSAPI_LVE_DISABLED;
771 static struct liblve * s_lve = NULL;
772
773 static void *s_liblve;
774 static int (*fp_lve_is_available)(void) = NULL;
775 static int (*fp_lve_instance_init)(struct liblve *) = NULL;
776 static int (*fp_lve_destroy)(struct liblve *) = NULL;
777 static int (*fp_lve_enter)(struct liblve *, uint32_t, int32_t, int32_t, uint32_t *) = NULL;
778 static int (*fp_lve_leave)(struct liblve *, uint32_t *) = NULL;
779 static int (*fp_lve_jail)( struct passwd *, char *) = NULL;
lsapi_load_lve_lib(void)780 static int lsapi_load_lve_lib(void)
781 {
782 s_liblve = dlopen("liblve.so.0", RTLD_LAZY);
783 if (s_liblve)
784 {
785 fp_lve_is_available = dlsym(s_liblve, "lve_is_available");
786 if (dlerror() == NULL)
787 {
788 if ( !(*fp_lve_is_available)() )
789 {
790 int uid = getuid();
791 if ( uid )
792 {
793 if (setreuid( s_uid, uid )) {};
794 if ( !(*fp_lve_is_available)() )
795 s_enable_lve = 0;
796 if (setreuid( uid, s_uid )) {};
797 }
798 }
799 }
800 }
801 else
802 {
803 s_enable_lve = LSAPI_LVE_DISABLED;
804 }
805 return (s_liblve)? 0 : -1;
806 }
807
808
init_lve_ex(void)809 static int init_lve_ex(void)
810 {
811 int rc;
812 if ( !s_liblve )
813 return -1;
814 fp_lve_instance_init = dlsym(s_liblve, "lve_instance_init");
815 fp_lve_destroy = dlsym(s_liblve, "lve_destroy");
816 fp_lve_enter = dlsym(s_liblve, "lve_enter");
817 fp_lve_leave = dlsym(s_liblve, "lve_leave");
818 if ( s_enable_lve >= LSAPI_CAGEFS_ENABLED )
819 fp_lve_jail = dlsym(s_liblve, "jail" );
820
821 if ( s_lve == NULL )
822 {
823 rc = (*fp_lve_instance_init)(NULL);
824 s_lve = malloc(rc);
825 }
826 rc = (*fp_lve_instance_init)(s_lve);
827 if (rc != 0)
828 {
829 perror( "LSAPI: Unable to initialize LVE" );
830 free( s_lve );
831 s_lve = NULL;
832 return -1;
833 }
834 return 0;
835
836 }
837
838 #endif
839
840
841
readSecret(const char * pSecretFile)842 static int readSecret( const char * pSecretFile )
843 {
844 struct stat st;
845 int fd = open( pSecretFile, O_RDONLY , 0600 );
846 if ( fd == -1 )
847 {
848 lsapi_log("LSAPI: failed to open secret file: %s!\n", pSecretFile );
849 return -1;
850 }
851 if ( fstat( fd, &st ) == -1 )
852 {
853 lsapi_log("LSAPI: failed to check state of file: %s!\n", pSecretFile );
854 close( fd );
855 return -1;
856 }
857 /*
858 if ( st.st_uid != s_uid )
859 {
860 lsapi_log("LSAPI: file owner check failure: %s!\n", pSecretFile );
861 close( fd );
862 return -1;
863 }
864 */
865 if ( st.st_mode & 0077 )
866 {
867 lsapi_log("LSAPI: file permission check failure: %s\n", pSecretFile );
868 close( fd );
869 return -1;
870 }
871 if ( read( fd, s_secret, 16 ) < 16 )
872 {
873 lsapi_log("LSAPI: failed to read secret from secret file: %s\n", pSecretFile );
874 close( fd );
875 return -1;
876 }
877 close( fd );
878 return 0;
879 }
880
881
LSAPI_is_suEXEC_Daemon(void)882 int LSAPI_is_suEXEC_Daemon(void)
883 {
884 if (( !s_uid )&&( s_secret[0] ))
885 return 1;
886 else
887 return 0;
888 }
889
890
LSAPI_perror_r(LSAPI_Request * pReq,const char * pErr1,const char * pErr2)891 static int LSAPI_perror_r( LSAPI_Request * pReq, const char * pErr1, const char *pErr2 )
892 {
893 char achError[4096];
894 int n = snprintf(achError, sizeof(achError), "[%d] %s:%s: %s\n", getpid(),
895 pErr1, (pErr2)?pErr2:"", strerror(errno));
896 if (n > (int)sizeof(achError))
897 n = sizeof(achError);
898 if ( pReq )
899 LSAPI_Write_Stderr_r( pReq, achError, n );
900 else
901 if (write( STDERR_FILENO, achError, n )) {};
902 return 0;
903 }
904
905
lsapi_lve_error(LSAPI_Request * pReq)906 static int lsapi_lve_error( LSAPI_Request * pReq )
907 {
908 static const char * headers[] =
909 {
910 "Cache-Control: private, no-cache, no-store, must-revalidate, max-age=0",
911 "Pragma: no-cache",
912 "Retry-After: 60",
913 "Content-Type: text/html",
914 NULL
915 };
916 static const char achBody[] =
917 "<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">\n"
918 "<HTML><HEAD>\n<TITLE>508 Resource Limit Is Reached</TITLE>\n"
919 "</HEAD><BODY>\n" "<H1>Resource Limit Is Reached</H1>\n"
920 "The website is temporarily unable to service your request as it exceeded resource limit.\n"
921 "Please try again later.\n"
922 "<HR>\n"
923 "</BODY></HTML>\n";
924
925 LSAPI_ErrResponse_r( pReq, 508, headers, achBody, sizeof( achBody ) - 1 );
926 return 0;
927 }
928
929
lsapi_enterLVE(LSAPI_Request * pReq,uid_t uid)930 static int lsapi_enterLVE( LSAPI_Request * pReq, uid_t uid )
931 {
932 #if defined(linux) || defined(__linux) || defined(__linux__) || defined(__gnu_linux__)
933 if ( s_lve && uid ) //root user should not do that
934 {
935 uint32_t cookie;
936 int ret = -1;
937 ret = (*fp_lve_enter)(s_lve, uid, -1, -1, &cookie);
938 if ( ret < 0 )
939 {
940 lsapi_log("enter LVE (%d) : ressult: %d !\n", uid, ret );
941 LSAPI_perror_r(pReq, "LSAPI: lve_enter() failure, reached resource limit.", NULL );
942 lsapi_lve_error( pReq );
943 return -1;
944 }
945 }
946 #endif
947
948 return 0;
949 }
950
951
lsapi_jailLVE(LSAPI_Request * pReq,uid_t uid,struct passwd * pw)952 static int lsapi_jailLVE( LSAPI_Request * pReq, uid_t uid, struct passwd * pw )
953 {
954 int ret = 0;
955 #if defined(linux) || defined(__linux) || defined(__linux__) || defined(__gnu_linux__)
956 char error_msg[1024] = "";
957 ret = (*fp_lve_jail)( pw, error_msg );
958 if ( ret < 0 )
959 {
960 lsapi_log("LSAPI: LVE jail(%d) ressult: %d, error: %s !\n",
961 uid, ret, error_msg );
962 LSAPI_perror_r( pReq, "LSAPI: jail() failure.", NULL );
963 return -1;
964 }
965 #endif
966 return ret;
967 }
968
969
970 #if defined(linux) || defined(__linux) || defined(__linux__) || defined(__gnu_linux__)
lsapi_initLVE(void)971 static int lsapi_initLVE(void)
972 {
973 const char * pEnv;
974 if ( (pEnv = getenv( "LSAPI_LVE_ENABLE" ))!= NULL )
975 {
976 s_enable_lve = atol( pEnv );
977 pEnv = NULL;
978 }
979 else if ( (pEnv = getenv( "LVE_ENABLE" ))!= NULL )
980 {
981 s_enable_lve = atol( pEnv );
982 pEnv = NULL;
983 }
984 if ( s_enable_lve && !s_uid )
985 {
986 lsapi_load_lve_lib();
987 if ( s_enable_lve )
988 {
989 return init_lve_ex();
990 }
991
992 }
993 return 0;
994 }
995 #endif
996
997
setUID_LVE(LSAPI_Request * pReq,uid_t uid,gid_t gid,const char * pChroot)998 static int setUID_LVE(LSAPI_Request * pReq, uid_t uid, gid_t gid, const char * pChroot)
999 {
1000 int rv;
1001 struct passwd * pw;
1002 pw = getpwuid( uid );
1003 #if defined(linux) || defined(__linux) || defined(__linux__) || defined(__gnu_linux__)
1004 if ( s_lve )
1005 {
1006 if( lsapi_enterLVE( pReq, uid ) == -1 )
1007 return -1;
1008 if ( pw && fp_lve_jail)
1009 {
1010 rv = lsapi_jailLVE( pReq, uid, pw );
1011 if ( rv == -1 )
1012 return -1;
1013 if (( rv == 1 )&&(s_enable_lve == LSAPI_CAGEFS_NO_SUEXEC )) //this mode only use cageFS, does not use suEXEC
1014 {
1015 uid = s_defaultUid;
1016 gid = s_defaultGid;
1017 pw = getpwuid( uid );
1018 }
1019 }
1020 }
1021 #endif
1022 //if ( !uid || !gid ) //do not allow root
1023 //{
1024 // return -1;
1025 //}
1026
1027 #if defined(__FreeBSD__ ) || defined(__NetBSD__) || defined(__OpenBSD__) \
1028 || defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__)
1029 if ( s_enable_core_dump )
1030 lsapi_enable_core_dump();
1031 #endif
1032
1033 rv = setgid(gid);
1034 if (rv == -1)
1035 {
1036 LSAPI_perror_r(pReq, "LSAPI: setgid()", NULL);
1037 return -1;
1038 }
1039 if ( pw && (pw->pw_gid == gid ))
1040 {
1041 rv = initgroups( pw->pw_name, gid );
1042 if (rv == -1)
1043 {
1044 LSAPI_perror_r(pReq, "LSAPI: initgroups()", NULL);
1045 return -1;
1046 }
1047 }
1048 else
1049 {
1050 rv = setgroups(1, &gid);
1051 if (rv == -1)
1052 {
1053 LSAPI_perror_r(pReq, "LSAPI: setgroups()", NULL);
1054 }
1055 }
1056 if ( pChroot )
1057 {
1058 rv = chroot( pChroot );
1059 if ( rv == -1 )
1060 {
1061 LSAPI_perror_r(pReq, "LSAPI: chroot()", NULL);
1062 return -1;
1063 }
1064 }
1065 rv = setuid(uid);
1066 if (rv == -1)
1067 {
1068 LSAPI_perror_r(pReq, "LSAPI: setuid()", NULL);
1069 return -1;
1070 }
1071 #if defined(linux) || defined(__linux) || defined(__linux__) || defined(__gnu_linux__)
1072 if ( s_enable_core_dump )
1073 lsapi_enable_core_dump();
1074 #endif
1075 return 0;
1076 }
1077
lsapi_suexec_auth(LSAPI_Request * pReq,char * pAuth,int len,char * pUgid,int ugidLen)1078 static int lsapi_suexec_auth( LSAPI_Request *pReq,
1079 char * pAuth, int len, char * pUgid, int ugidLen )
1080 {
1081 lsapi_MD5_CTX md5ctx;
1082 unsigned char achMD5[16];
1083 if ( len < 32 )
1084 return -1;
1085 memmove( achMD5, pAuth + 16, 16 );
1086 memmove( pAuth + 16, s_secret, 16 );
1087 lsapi_MD5Init( &md5ctx );
1088 lsapi_MD5Update( &md5ctx, (unsigned char *)pAuth, 32 );
1089 lsapi_MD5Update( &md5ctx, (unsigned char *)pUgid, 8 );
1090 lsapi_MD5Final( (unsigned char *)pAuth + 16, &md5ctx);
1091 if ( memcmp( achMD5, pAuth + 16, 16 ) == 0 )
1092 return 0;
1093 return 1;
1094 }
1095
1096
lsapi_changeUGid(LSAPI_Request * pReq)1097 static int lsapi_changeUGid( LSAPI_Request * pReq )
1098 {
1099 int uid = s_defaultUid;
1100 int gid = s_defaultGid;
1101 const char *pStderrLog;
1102 const char *pChroot = NULL;
1103 struct LSAPI_key_value_pair * pEnv;
1104 struct LSAPI_key_value_pair * pAuth;
1105 int i;
1106 if ( s_uid )
1107 return 0;
1108 //with special ID 0x00
1109 //authenticate the suEXEC request;
1110 //first one should be MD5( nonce + lscgid secret )
1111 //remember to clear the secret after verification
1112 //it should be set at the end of special env
1113 i = pReq->m_pHeader->m_cntSpecialEnv - 1;
1114 if ( i >= 0 )
1115 {
1116 pEnv = pReq->m_pSpecialEnvList + i;
1117 if (( *pEnv->pKey == '\000' )&&
1118 ( strcmp( pEnv->pKey+1, "SUEXEC_AUTH" ) == 0 ))
1119 {
1120 --pReq->m_pHeader->m_cntSpecialEnv;
1121 pAuth = pEnv--;
1122 if (( *pEnv->pKey == '\000' )&&
1123 ( strcmp( pEnv->pKey+1, "SUEXEC_UGID" ) == 0 ))
1124 {
1125 --pReq->m_pHeader->m_cntSpecialEnv;
1126 uid = *(uint32_t *)pEnv->pValue;
1127 gid = *(((uint32_t *)pEnv->pValue) + 1 );
1128 //lsapi_log("LSAPI: SUEXEC_UGID set UID: %d, GID: %d\n", uid, gid );
1129 }
1130 else
1131 {
1132 lsapi_log("LSAPI: missing SUEXEC_UGID env, use default user!\n" );
1133 pEnv = NULL;
1134 }
1135 if ( pEnv&& lsapi_suexec_auth( pReq, pAuth->pValue, pAuth->valLen, pEnv->pValue, pEnv->valLen ) == 0 )
1136 {
1137 //read UID, GID from specialEnv
1138
1139 }
1140 else
1141 {
1142 //authentication error
1143 lsapi_log("LSAPI: SUEXEC_AUTH authentication failed, use default user!\n" );
1144 uid = 0;
1145 }
1146 }
1147 else
1148 {
1149 //lsapi_log("LSAPI: no SUEXEC_AUTH env, use default user!\n" );
1150 }
1151 }
1152
1153
1154 if ( !uid )
1155 {
1156 uid = s_defaultUid;
1157 gid = s_defaultGid;
1158 }
1159
1160 //change uid
1161 if ( setUID_LVE( pReq, uid, gid, pChroot ) == -1 )
1162 {
1163 return -1;
1164 }
1165
1166 s_uid = uid;
1167
1168 if ( pReq->m_fdListen != -1 )
1169 {
1170 close( pReq->m_fdListen );
1171 pReq->m_fdListen = -1;
1172 }
1173
1174 pStderrLog = LSAPI_GetEnv_r( pReq, "LSAPI_STDERR_LOG");
1175 if (pStderrLog)
1176 lsapi_reopen_stderr(pStderrLog);
1177
1178 return 0;
1179
1180 }
1181
1182
parseContentLenFromHeader(LSAPI_Request * pReq)1183 static int parseContentLenFromHeader(LSAPI_Request * pReq)
1184 {
1185 const char * pContentLen = LSAPI_GetHeader_r( pReq, H_CONTENT_LENGTH );
1186 if ( pContentLen )
1187 pReq->m_reqBodyLen = strtoll( pContentLen, NULL, 10 );
1188 return 0;
1189 }
1190
1191
parseRequest(LSAPI_Request * pReq,int totalLen)1192 static int parseRequest( LSAPI_Request * pReq, int totalLen )
1193 {
1194 int shouldFixEndian;
1195 char * pBegin = pReq->m_pReqBuf + sizeof( struct lsapi_req_header );
1196 char * pEnd = pReq->m_pReqBuf + totalLen;
1197 shouldFixEndian = ( LSAPI_ENDIAN != (
1198 pReq->m_pHeader->m_pktHeader.m_flag & LSAPI_ENDIAN_BIT ) );
1199 if ( shouldFixEndian )
1200 {
1201 fixEndian( pReq );
1202 }
1203 if ( (pReq->m_specialEnvListSize < pReq->m_pHeader->m_cntSpecialEnv )&&
1204 allocateEnvList( &pReq->m_pSpecialEnvList,
1205 &pReq->m_specialEnvListSize,
1206 pReq->m_pHeader->m_cntSpecialEnv ) == -1 )
1207 return -1;
1208 if ( (pReq->m_envListSize < pReq->m_pHeader->m_cntEnv )&&
1209 allocateEnvList( &pReq->m_pEnvList, &pReq->m_envListSize,
1210 pReq->m_pHeader->m_cntEnv ) == -1 )
1211 return -1;
1212
1213 if ( parseEnv( pReq->m_pSpecialEnvList,
1214 pReq->m_pHeader->m_cntSpecialEnv,
1215 &pBegin, pEnd ) == -1 )
1216 return -1;
1217 if ( parseEnv( pReq->m_pEnvList, pReq->m_pHeader->m_cntEnv,
1218 &pBegin, pEnd ) == -1 )
1219 return -1;
1220 if (pReq->m_pHeader->m_scriptFileOff < 0
1221 || pReq->m_pHeader->m_scriptFileOff >= totalLen
1222 || pReq->m_pHeader->m_scriptNameOff < 0
1223 || pReq->m_pHeader->m_scriptNameOff >= totalLen
1224 || pReq->m_pHeader->m_queryStringOff < 0
1225 || pReq->m_pHeader->m_queryStringOff >= totalLen
1226 || pReq->m_pHeader->m_requestMethodOff < 0
1227 || pReq->m_pHeader->m_requestMethodOff >= totalLen)
1228 {
1229 lsapi_log("Bad request header - ERROR#1\n");
1230 return -1;
1231 }
1232 pReq->m_pScriptFile = pReq->m_pReqBuf + pReq->m_pHeader->m_scriptFileOff;
1233 pReq->m_pScriptName = pReq->m_pReqBuf + pReq->m_pHeader->m_scriptNameOff;
1234 pReq->m_pQueryString = pReq->m_pReqBuf + pReq->m_pHeader->m_queryStringOff;
1235 pReq->m_pRequestMethod = pReq->m_pReqBuf + pReq->m_pHeader->m_requestMethodOff;
1236
1237 pBegin = pReq->m_pReqBuf + (( pBegin - pReq->m_pReqBuf + 7 ) & (~0x7));
1238 pReq->m_pHeaderIndex = ( struct lsapi_http_header_index * )pBegin;
1239 pBegin += sizeof( struct lsapi_http_header_index );
1240
1241 pReq->m_pUnknownHeader = (struct lsapi_header_offset *)pBegin;
1242 pBegin += sizeof( struct lsapi_header_offset) *
1243 pReq->m_pHeader->m_cntUnknownHeaders;
1244
1245 pReq->m_pHttpHeader = pBegin;
1246 pBegin += pReq->m_pHeader->m_httpHeaderLen;
1247 if ( pBegin != pEnd )
1248 {
1249 lsapi_log("Request header does match total size, total: %d, "
1250 "real: %ld\n", totalLen, pBegin - pReq->m_pReqBuf );
1251 return -1;
1252 }
1253 if ( shouldFixEndian )
1254 {
1255 fixHeaderIndexEndian( pReq );
1256 }
1257
1258 if (validateHeaders(pReq) == -1)
1259 {
1260 lsapi_log("Bad request header - ERROR#2\n");
1261 return -1;
1262 }
1263
1264 pReq->m_reqBodyLen = pReq->m_pHeader->m_reqBodyLen;
1265 if ( pReq->m_reqBodyLen == -2 )
1266 {
1267 parseContentLenFromHeader(pReq);
1268 }
1269
1270 return 0;
1271 }
1272
1273
1274 //OPTIMIZATION
1275 static char s_accept_notify = 0;
1276 static char s_schedule_notify = 0;
1277 static char s_notify_scheduled = 0;
1278 static char s_notified_pid = 0;
1279
1280 static struct lsapi_packet_header s_ack = {'L', 'S',
1281 LSAPI_REQ_RECEIVED, LSAPI_ENDIAN, {LSAPI_PACKET_HEADER_LEN} };
1282 static struct lsapi_packet_header s_conn_close_pkt = {'L', 'S',
1283 LSAPI_CONN_CLOSE, LSAPI_ENDIAN, {LSAPI_PACKET_HEADER_LEN} };
1284
1285
send_notification_pkt(int fd,struct lsapi_packet_header * pkt)1286 static inline int send_notification_pkt( int fd, struct lsapi_packet_header *pkt )
1287 {
1288 if ( write( fd, pkt, LSAPI_PACKET_HEADER_LEN ) < LSAPI_PACKET_HEADER_LEN )
1289 return -1;
1290 return 0;
1291 }
1292
1293
send_req_received_notification(int fd)1294 static inline int send_req_received_notification( int fd )
1295 {
1296 return send_notification_pkt(fd, &s_ack);
1297 }
1298
1299
send_conn_close_notification(int fd)1300 static inline int send_conn_close_notification( int fd )
1301 {
1302 return send_notification_pkt(fd, &s_conn_close_pkt);
1303 }
1304
1305
1306 //static void lsapi_sigalarm( int sig )
1307 //{
1308 // if ( s_notify_scheduled )
1309 // {
1310 // s_notify_scheduled = 0;
1311 // if ( g_req.m_fd != -1 )
1312 // write_req_received_notification( g_req.m_fd );
1313 // }
1314 //}
1315
1316
lsapi_schedule_notify(void)1317 static inline int lsapi_schedule_notify(void)
1318 {
1319 if ( !s_notify_scheduled )
1320 {
1321 alarm( 2 );
1322 s_notify_scheduled = 1;
1323 }
1324 return 0;
1325 }
1326
1327
notify_req_received(int fd)1328 static inline int notify_req_received( int fd )
1329 {
1330 if ( s_schedule_notify )
1331 return lsapi_schedule_notify();
1332 return send_req_received_notification( fd );
1333
1334 }
1335
1336
lsapi_notify_pid(int fd)1337 static inline int lsapi_notify_pid( int fd )
1338 {
1339 char achBuf[16];
1340 lsapi_buildPacketHeader( (struct lsapi_packet_header *)achBuf, LSAPI_STDERR_STREAM,
1341 8 + LSAPI_PACKET_HEADER_LEN );
1342 memmove( &achBuf[8], "\0PID", 4 );
1343 *((int *)&achBuf[12]) = getpid();
1344
1345 if ( write( fd, achBuf, 16 ) < 16 )
1346 return -1;
1347 return 0;
1348 }
1349
1350
1351 static char s_conn_key_packet[16];
init_conn_key(int fd)1352 static inline int init_conn_key( int fd )
1353 {
1354 struct lsapi_packet_header * pHeader = (struct lsapi_packet_header *)s_conn_key_packet;
1355 struct timeval tv;
1356 int i;
1357 gettimeofday( &tv, NULL );
1358 srand( (tv.tv_sec % 0x1000 + tv.tv_usec) ^ rand() );
1359 for( i = 8; i < 16; ++i )
1360 {
1361 s_conn_key_packet[i]=(int) (256.0*rand()/(RAND_MAX+1.0));
1362 }
1363 lsapi_buildPacketHeader( pHeader, LSAPI_REQ_RECEIVED,
1364 8 + LSAPI_PACKET_HEADER_LEN );
1365 if ( write( fd, s_conn_key_packet, LSAPI_PACKET_HEADER_LEN+8 )
1366 < LSAPI_PACKET_HEADER_LEN+8 )
1367 return -1;
1368 return 0;
1369
1370
1371 }
1372
1373
readReq(LSAPI_Request * pReq)1374 static int readReq( LSAPI_Request * pReq )
1375 {
1376 int len;
1377 int packetLen;
1378 if ( !pReq )
1379 return -1;
1380 if ( pReq->m_reqBufSize < 8192 )
1381 {
1382 if ( allocateBuf( pReq, 8192 ) == -1 )
1383 return -1;
1384 }
1385
1386 while ( pReq->m_bufRead < LSAPI_PACKET_HEADER_LEN )
1387 {
1388 len = lsapi_read( pReq->m_fd, pReq->m_pReqBuf, pReq->m_reqBufSize );
1389 if ( len <= 0 )
1390 return -1;
1391 pReq->m_bufRead += len;
1392 }
1393 pReq->m_reqState = LSAPI_ST_REQ_HEADER;
1394
1395 packetLen = verifyHeader( &pReq->m_pHeader->m_pktHeader, LSAPI_BEGIN_REQUEST );
1396 if ( packetLen < 0 )
1397 {
1398 lsapi_log("packetLen < 0\n");
1399 return -1;
1400 }
1401 if ( packetLen > LSAPI_MAX_HEADER_LEN )
1402 {
1403 lsapi_log("packetLen > %d\n", LSAPI_MAX_HEADER_LEN );
1404 return -1;
1405 }
1406
1407 if ( packetLen + 1024 > pReq->m_reqBufSize )
1408 {
1409 if ( allocateBuf( pReq, packetLen + 1024 ) == -1 )
1410 return -1;
1411 }
1412 while( packetLen > pReq->m_bufRead )
1413 {
1414 len = lsapi_read( pReq->m_fd, pReq->m_pReqBuf + pReq->m_bufRead, packetLen - pReq->m_bufRead );
1415 if ( len <= 0 )
1416 return -1;
1417 pReq->m_bufRead += len;
1418 }
1419 if ( parseRequest( pReq, packetLen ) < 0 )
1420 {
1421 lsapi_log("ParseRequest error\n");
1422 return -1;
1423 }
1424
1425 pReq->m_reqState = LSAPI_ST_REQ_BODY | LSAPI_ST_RESP_HEADER;
1426
1427 if ( !s_uid )
1428 {
1429 if ( lsapi_changeUGid( pReq ) )
1430 return -1;
1431 memset(s_secret, 0, sizeof(s_secret));
1432 }
1433 pReq->m_bufProcessed = packetLen;
1434
1435 //OPTIMIZATION
1436 if ( !s_accept_notify && !s_notified_pid )
1437 return notify_req_received( pReq->m_fd );
1438 else
1439 {
1440 s_notified_pid = 0;
1441 return 0;
1442 }
1443 }
1444
1445
LSAPI_Init(void)1446 int LSAPI_Init(void)
1447 {
1448 if ( !g_inited )
1449 {
1450 s_uid = geteuid();
1451 s_secret[0] = 0;
1452 lsapi_signal(SIGPIPE, lsapi_sigpipe);
1453 lsapi_signal(SIGUSR1, lsapi_siguser1);
1454
1455 #if defined(SIGXFSZ) && defined(SIG_IGN)
1456 signal(SIGXFSZ, SIG_IGN);
1457 #endif
1458 /* let STDOUT function as STDERR,
1459 just in case writing to STDOUT directly */
1460 dup2( 2, 1 );
1461 if ( LSAPI_InitRequest( &g_req, LSAPI_SOCK_FILENO ) == -1 )
1462 return -1;
1463 g_inited = 1;
1464 s_ppid = getppid();
1465 void *pthread_lib = dlopen("libpthread.so", RTLD_LAZY);
1466 if (pthread_lib)
1467 pthread_atfork_func = dlsym(pthread_lib, "pthread_atfork");
1468
1469 }
1470 return 0;
1471 }
1472
1473
LSAPI_Stop(void)1474 void LSAPI_Stop(void)
1475 {
1476 g_running = 0;
1477 }
1478
1479
LSAPI_IsRunning(void)1480 int LSAPI_IsRunning(void)
1481 {
1482 return g_running;
1483 }
1484
1485
LSAPI_Register_Pgrp_Timer_Callback(LSAPI_On_Timer_pf cb)1486 void LSAPI_Register_Pgrp_Timer_Callback(LSAPI_On_Timer_pf cb)
1487 {
1488 s_proc_group_timer_cb = cb;
1489 }
1490
1491
LSAPI_InitRequest(LSAPI_Request * pReq,int fd)1492 int LSAPI_InitRequest( LSAPI_Request * pReq, int fd )
1493 {
1494 int newfd;
1495 if ( !pReq )
1496 return -1;
1497 memset( pReq, 0, sizeof( LSAPI_Request ) );
1498 if ( allocateIovec( pReq, 16 ) == -1 )
1499 return -1;
1500 pReq->m_pRespBuf = pReq->m_pRespBufPos = (char *)malloc( LSAPI_RESP_BUF_SIZE );
1501 if ( !pReq->m_pRespBuf )
1502 return -1;
1503 pReq->m_pRespBufEnd = pReq->m_pRespBuf + LSAPI_RESP_BUF_SIZE;
1504 pReq->m_pIovecCur = pReq->m_pIovecToWrite = pReq->m_pIovec + 1;
1505 pReq->m_respPktHeaderEnd = &pReq->m_respPktHeader[5];
1506 if ( allocateRespHeaderBuf( pReq, LSAPI_INIT_RESP_HEADER_LEN ) == -1 )
1507 return -1;
1508
1509 if ( fd == STDIN_FILENO )
1510 {
1511 fd = dup( fd );
1512 newfd = open( "/dev/null", O_RDWR );
1513 dup2( newfd, STDIN_FILENO );
1514 }
1515
1516 if ( isPipe( fd ) )
1517 {
1518 pReq->m_fdListen = -1;
1519 pReq->m_fd = fd;
1520 }
1521 else
1522 {
1523 pReq->m_fdListen = fd;
1524 pReq->m_fd = -1;
1525 lsapi_set_nblock( fd, 1 );
1526 }
1527 return 0;
1528 }
1529
1530
LSAPI_Is_Listen(void)1531 int LSAPI_Is_Listen( void )
1532 {
1533 return LSAPI_Is_Listen_r( &g_req );
1534 }
1535
1536
LSAPI_Is_Listen_r(LSAPI_Request * pReq)1537 int LSAPI_Is_Listen_r( LSAPI_Request * pReq)
1538 {
1539 return pReq->m_fdListen != -1;
1540 }
1541
1542
LSAPI_Accept_r(LSAPI_Request * pReq)1543 int LSAPI_Accept_r( LSAPI_Request * pReq )
1544 {
1545 char achPeer[128];
1546 socklen_t len;
1547 int nodelay = 1;
1548
1549 if ( !pReq )
1550 return -1;
1551 if ( LSAPI_Finish_r( pReq ) == -1 )
1552 return -1;
1553 lsapi_set_nblock( pReq->m_fdListen , 0 );
1554 while( g_running )
1555 {
1556 if ( pReq->m_fd == -1 )
1557 {
1558 if ( pReq->m_fdListen != -1)
1559 {
1560 len = sizeof( achPeer );
1561 pReq->m_fd = accept( pReq->m_fdListen,
1562 (struct sockaddr *)&achPeer, &len );
1563 if ( pReq->m_fd == -1 )
1564 {
1565 if (( errno == EINTR )||( errno == EAGAIN))
1566 continue;
1567 else
1568 return -1;
1569 }
1570 else
1571 {
1572 if (s_worker_status)
1573 __sync_lock_test_and_set(&s_worker_status->m_state,
1574 LSAPI_STATE_CONNECTED);
1575 if (s_busy_workers)
1576 __sync_fetch_and_add(s_busy_workers, 1);
1577 lsapi_set_nblock( pReq->m_fd , 0 );
1578 if (((struct sockaddr *)&achPeer)->sa_family == AF_INET )
1579 {
1580 setsockopt(pReq->m_fd, IPPROTO_TCP, TCP_NODELAY,
1581 (char *)&nodelay, sizeof(nodelay));
1582 }
1583 //init_conn_key( pReq->m_fd );
1584 //OPTIMIZATION
1585 if ( s_accept_notify )
1586 if ( notify_req_received( pReq->m_fd ) == -1 )
1587 return -1;
1588 }
1589 }
1590 else
1591 return -1;
1592 }
1593 if ( !readReq( pReq ) )
1594 break;
1595 //abort();
1596 lsapi_close_connection(pReq);
1597 LSAPI_Reset_r( pReq );
1598 }
1599 return 0;
1600 }
1601
1602
1603 static struct lsapi_packet_header finish_close[2] =
1604 {
1605 {'L', 'S', LSAPI_RESP_END, LSAPI_ENDIAN, {LSAPI_PACKET_HEADER_LEN} },
1606 {'L', 'S', LSAPI_CONN_CLOSE, LSAPI_ENDIAN, {LSAPI_PACKET_HEADER_LEN} }
1607 };
1608
1609
LSAPI_Finish_r(LSAPI_Request * pReq)1610 int LSAPI_Finish_r( LSAPI_Request * pReq )
1611 {
1612 /* finish req body */
1613 if ( !pReq )
1614 return -1;
1615 if (pReq->m_reqState)
1616 {
1617 if ( pReq->m_fd != -1 )
1618 {
1619 if ( pReq->m_reqState & LSAPI_ST_RESP_HEADER )
1620 {
1621 LSAPI_FinalizeRespHeaders_r( pReq );
1622 }
1623 if ( pReq->m_pRespBufPos != pReq->m_pRespBuf )
1624 {
1625 Flush_RespBuf_r( pReq );
1626 }
1627
1628 pReq->m_pIovecCur->iov_base = (void *)finish_close;
1629 pReq->m_pIovecCur->iov_len = LSAPI_PACKET_HEADER_LEN;
1630 pReq->m_totalLen += LSAPI_PACKET_HEADER_LEN;
1631 ++pReq->m_pIovecCur;
1632 LSAPI_Flush_r( pReq );
1633 }
1634 LSAPI_Reset_r( pReq );
1635 }
1636 return 0;
1637 }
1638
1639
LSAPI_End_Response_r(LSAPI_Request * pReq)1640 int LSAPI_End_Response_r(LSAPI_Request * pReq)
1641 {
1642 if (!pReq)
1643 return -1;
1644 if (pReq->m_reqState & LSAPI_ST_BACKGROUND)
1645 return 0;
1646 if (pReq->m_reqState)
1647 {
1648 if ( pReq->m_fd != -1 )
1649 {
1650 if ( pReq->m_reqState & LSAPI_ST_RESP_HEADER )
1651 {
1652 if ( pReq->m_pRespHeaderBufPos <= pReq->m_pRespHeaderBuf )
1653 return 0;
1654
1655 LSAPI_FinalizeRespHeaders_r( pReq );
1656 }
1657 if ( pReq->m_pRespBufPos != pReq->m_pRespBuf )
1658 {
1659 Flush_RespBuf_r( pReq );
1660 }
1661
1662 pReq->m_pIovecCur->iov_base = (void *)finish_close;
1663 pReq->m_pIovecCur->iov_len = LSAPI_PACKET_HEADER_LEN << 1;
1664 pReq->m_totalLen += LSAPI_PACKET_HEADER_LEN << 1;
1665 ++pReq->m_pIovecCur;
1666 LSAPI_Flush_r( pReq );
1667 lsapi_close_connection(pReq);
1668 }
1669 pReq->m_reqState |= LSAPI_ST_BACKGROUND;
1670 }
1671 return 0;
1672 }
1673
1674
LSAPI_Reset_r(LSAPI_Request * pReq)1675 void LSAPI_Reset_r( LSAPI_Request * pReq )
1676 {
1677 pReq->m_pRespBufPos = pReq->m_pRespBuf;
1678 pReq->m_pIovecCur = pReq->m_pIovecToWrite = pReq->m_pIovec + 1;
1679 pReq->m_pRespHeaderBufPos = pReq->m_pRespHeaderBuf;
1680
1681 memset( &pReq->m_pHeaderIndex, 0,
1682 (char *)(pReq->m_respHeaderLen) - (char *)&pReq->m_pHeaderIndex );
1683 }
1684
1685
LSAPI_Release_r(LSAPI_Request * pReq)1686 int LSAPI_Release_r( LSAPI_Request * pReq )
1687 {
1688 if ( pReq->m_pReqBuf )
1689 free( pReq->m_pReqBuf );
1690 if ( pReq->m_pSpecialEnvList )
1691 free( pReq->m_pSpecialEnvList );
1692 if ( pReq->m_pEnvList )
1693 free( pReq->m_pEnvList );
1694 if ( pReq->m_pRespHeaderBuf )
1695 free( pReq->m_pRespHeaderBuf );
1696 return 0;
1697 }
1698
1699
LSAPI_GetHeader_r(LSAPI_Request * pReq,int headerIndex)1700 char * LSAPI_GetHeader_r( LSAPI_Request * pReq, int headerIndex )
1701 {
1702 int off;
1703 if ( !pReq || ((unsigned int)headerIndex > H_TRANSFER_ENCODING) )
1704 return NULL;
1705 off = pReq->m_pHeaderIndex->m_headerOff[ headerIndex ];
1706 if ( !off )
1707 return NULL;
1708 if ( *(pReq->m_pHttpHeader + off
1709 + pReq->m_pHeaderIndex->m_headerLen[ headerIndex ]) )
1710 {
1711 *( pReq->m_pHttpHeader + off
1712 + pReq->m_pHeaderIndex->m_headerLen[ headerIndex ]) = 0;
1713 }
1714 return pReq->m_pHttpHeader + off;
1715 }
1716
1717
readBodyToReqBuf(LSAPI_Request * pReq)1718 static int readBodyToReqBuf( LSAPI_Request * pReq )
1719 {
1720 off_t bodyLeft;
1721 ssize_t len = pReq->m_bufRead - pReq->m_bufProcessed;
1722 if ( len > 0 )
1723 return len;
1724 pReq->m_bufRead = pReq->m_bufProcessed = pReq->m_pHeader->m_pktHeader.m_packetLen.m_iLen;
1725
1726 bodyLeft = pReq->m_reqBodyLen - pReq->m_reqBodyRead;
1727 len = pReq->m_reqBufSize - pReq->m_bufRead;
1728 if ( len < 0 )
1729 return -1;
1730 if ( len > bodyLeft )
1731 len = bodyLeft;
1732
1733 len = lsapi_read( pReq->m_fd, pReq->m_pReqBuf + pReq->m_bufRead, len );
1734 if ( len > 0 )
1735 pReq->m_bufRead += len;
1736 return len;
1737 }
1738
1739
LSAPI_ReqBodyGetChar_r(LSAPI_Request * pReq)1740 int LSAPI_ReqBodyGetChar_r( LSAPI_Request * pReq )
1741 {
1742 if (!pReq || (pReq->m_fd ==-1) )
1743 return EOF;
1744 if ( pReq->m_bufProcessed >= pReq->m_bufRead )
1745 {
1746 if ( readBodyToReqBuf( pReq ) <= 0 )
1747 return EOF;
1748 }
1749 ++pReq->m_reqBodyRead;
1750 return (unsigned char)*(pReq->m_pReqBuf + pReq->m_bufProcessed++);
1751 }
1752
1753
LSAPI_ReqBodyGetLine_r(LSAPI_Request * pReq,char * pBuf,size_t bufLen,int * getLF)1754 int LSAPI_ReqBodyGetLine_r( LSAPI_Request * pReq, char * pBuf, size_t bufLen, int *getLF )
1755 {
1756 ssize_t len;
1757 ssize_t left;
1758 char * pBufEnd = pBuf + bufLen - 1;
1759 char * pBufCur = pBuf;
1760 char * pCur;
1761 char * p;
1762 if (!pReq || pReq->m_fd == -1 || !pBuf || !getLF)
1763 return -1;
1764 *getLF = 0;
1765 while( (left = pBufEnd - pBufCur ) > 0 )
1766 {
1767
1768 len = pReq->m_bufRead - pReq->m_bufProcessed;
1769 if ( len <= 0 )
1770 {
1771 if ( (len = readBodyToReqBuf( pReq )) <= 0 )
1772 {
1773 *getLF = 1;
1774 break;
1775 }
1776 }
1777 if ( len > left )
1778 len = left;
1779 pCur = pReq->m_pReqBuf + pReq->m_bufProcessed;
1780 p = memchr( pCur, '\n', len );
1781 if ( p )
1782 len = p - pCur + 1;
1783 memmove( pBufCur, pCur, len );
1784 pBufCur += len;
1785 pReq->m_bufProcessed += len;
1786
1787 pReq->m_reqBodyRead += len;
1788
1789 if ( p )
1790 {
1791 *getLF = 1;
1792 break;
1793 }
1794 }
1795 *pBufCur = 0;
1796
1797 return pBufCur - pBuf;
1798 }
1799
1800
LSAPI_ReadReqBody_r(LSAPI_Request * pReq,char * pBuf,size_t bufLen)1801 ssize_t LSAPI_ReadReqBody_r( LSAPI_Request * pReq, char * pBuf, size_t bufLen )
1802 {
1803 ssize_t len;
1804 off_t total;
1805 /* char *pOldBuf = pBuf; */
1806 if (!pReq || pReq->m_fd == -1 || !pBuf || (ssize_t)bufLen < 0)
1807 return -1;
1808
1809 total = pReq->m_reqBodyLen - pReq->m_reqBodyRead;
1810
1811 if ( total <= 0 )
1812 return 0;
1813 if ( total < (ssize_t)bufLen )
1814 bufLen = total;
1815
1816 total = 0;
1817 len = pReq->m_bufRead - pReq->m_bufProcessed;
1818 if ( len > 0 )
1819 {
1820 if ( len > (ssize_t)bufLen )
1821 len = bufLen;
1822 memmove( pBuf, pReq->m_pReqBuf + pReq->m_bufProcessed, len );
1823 pReq->m_bufProcessed += len;
1824 total += len;
1825 pBuf += len;
1826 bufLen -= len;
1827 }
1828 while( bufLen > 0 )
1829 {
1830 len = lsapi_read( pReq->m_fd, pBuf, bufLen );
1831 if ( len > 0 )
1832 {
1833 total += len;
1834 pBuf += len;
1835 bufLen -= len;
1836 }
1837 else if ( len <= 0 )
1838 {
1839 if ( !total)
1840 return -1;
1841 break;
1842 }
1843 }
1844 pReq->m_reqBodyRead += total;
1845 return total;
1846
1847 }
1848
1849
LSAPI_Write_r(LSAPI_Request * pReq,const char * pBuf,size_t len)1850 ssize_t LSAPI_Write_r( LSAPI_Request * pReq, const char * pBuf, size_t len )
1851 {
1852 struct lsapi_packet_header * pHeader;
1853 const char * pEnd;
1854 const char * p;
1855 ssize_t bufLen;
1856 ssize_t toWrite;
1857 ssize_t packetLen;
1858 int skip = 0;
1859
1860 if (!pReq || !pBuf)
1861 return -1;
1862 if (pReq->m_reqState & LSAPI_ST_BACKGROUND)
1863 return len;
1864 if (pReq->m_fd == -1)
1865 return -1;
1866 if ( pReq->m_reqState & LSAPI_ST_RESP_HEADER )
1867 {
1868 LSAPI_FinalizeRespHeaders_r( pReq );
1869 /*
1870 if ( *pBuf == '\r' )
1871 {
1872 ++skip;
1873 }
1874 if ( *pBuf == '\n' )
1875 {
1876 ++skip;
1877 }
1878 */
1879 }
1880 pReq->m_reqState |= LSAPI_ST_RESP_BODY;
1881
1882 if ( ((ssize_t)len - skip) < pReq->m_pRespBufEnd - pReq->m_pRespBufPos )
1883 {
1884 memmove( pReq->m_pRespBufPos, pBuf + skip, len - skip );
1885 pReq->m_pRespBufPos += len - skip;
1886 return len;
1887 }
1888
1889
1890 pHeader = pReq->m_respPktHeader;
1891 p = pBuf + skip;
1892 pEnd = pBuf + len;
1893 bufLen = pReq->m_pRespBufPos - pReq->m_pRespBuf;
1894
1895 while( ( toWrite = pEnd - p ) > 0 )
1896 {
1897 packetLen = toWrite + bufLen;
1898 if ( LSAPI_MAX_DATA_PACKET_LEN < packetLen)
1899 {
1900 packetLen = LSAPI_MAX_DATA_PACKET_LEN;
1901 toWrite = packetLen - bufLen;
1902 }
1903
1904 lsapi_buildPacketHeader( pHeader, LSAPI_RESP_STREAM,
1905 packetLen + LSAPI_PACKET_HEADER_LEN );
1906 pReq->m_totalLen += packetLen + LSAPI_PACKET_HEADER_LEN;
1907
1908 pReq->m_pIovecCur->iov_base = (void *)pHeader;
1909 pReq->m_pIovecCur->iov_len = LSAPI_PACKET_HEADER_LEN;
1910 ++pReq->m_pIovecCur;
1911 ++pHeader;
1912 if ( bufLen > 0 )
1913 {
1914 pReq->m_pIovecCur->iov_base = (void *)pReq->m_pRespBuf;
1915 pReq->m_pIovecCur->iov_len = bufLen;
1916 pReq->m_pRespBufPos = pReq->m_pRespBuf;
1917 ++pReq->m_pIovecCur;
1918 bufLen = 0;
1919 }
1920
1921 pReq->m_pIovecCur->iov_base = (void *)p;
1922 pReq->m_pIovecCur->iov_len = toWrite;
1923 ++pReq->m_pIovecCur;
1924 p += toWrite;
1925
1926 if ( pHeader >= pReq->m_respPktHeaderEnd - 1)
1927 {
1928 if ( LSAPI_Flush_r( pReq ) == -1 )
1929 return -1;
1930 pHeader = pReq->m_respPktHeader;
1931 }
1932 }
1933 if ( pHeader != pReq->m_respPktHeader )
1934 if ( LSAPI_Flush_r( pReq ) == -1 )
1935 return -1;
1936 return p - pBuf;
1937 }
1938
1939
1940 #if defined(__FreeBSD__ ) || defined(__NetBSD__) || defined(__OpenBSD__)
gsendfile(int fdOut,int fdIn,off_t * off,size_t size)1941 ssize_t gsendfile( int fdOut, int fdIn, off_t* off, size_t size )
1942 {
1943 ssize_t ret;
1944 off_t written;
1945 ret = sendfile( fdIn, fdOut, *off, size, NULL, &written, 0 );
1946 if ( written > 0 )
1947 {
1948 ret = written;
1949 *off += ret;
1950 }
1951 return ret;
1952 }
1953 #endif
1954
1955
1956 #if defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__)
gsendfile(int fdOut,int fdIn,off_t * off,size_t size)1957 ssize_t gsendfile( int fdOut, int fdIn, off_t* off, size_t size )
1958 {
1959 ssize_t ret;
1960 off_t len = size;
1961 ret = sendfile( fdIn, fdOut, *off, &len, NULL, 0 );
1962 if (( ret == 0 )&&( len > 0 ))
1963 {
1964 ret = len;
1965 *off += len;
1966 }
1967 return ret;
1968 }
1969 #endif
1970
1971
1972 #if defined(sun) || defined(__sun)
1973 #include <sys/sendfile.h>
gsendfile(int fdOut,int fdIn,off_t * off,size_t size)1974 ssize_t gsendfile( int fdOut, int fdIn, off_t *off, size_t size )
1975 {
1976 int n = 0 ;
1977 sendfilevec_t vec[1];
1978
1979 vec[n].sfv_fd = fdIn;
1980 vec[n].sfv_flag = 0;
1981 vec[n].sfv_off = *off;
1982 vec[n].sfv_len = size;
1983 ++n;
1984
1985 size_t written;
1986 ssize_t ret = sendfilev( fdOut, vec, n, &written );
1987 if (( !ret )||( errno == EAGAIN ))
1988 ret = written;
1989 if ( ret > 0 )
1990 *off += ret;
1991 return ret;
1992 }
1993 #endif
1994
1995
1996 #if defined(linux) || defined(__linux) || defined(__linux__) || \
1997 defined(__gnu_linux__)
1998 #include <sys/sendfile.h>
1999 #define gsendfile sendfile
2000 #endif
2001
2002
2003 #if defined(HPUX)
gsendfile(int fdOut,int fdIn,off_t * off,size_t size)2004 ssize_t gsendfile( int fdOut, int fdIn, off_t * off, size_t size )
2005 {
2006 return sendfile( fdOut, fdIn, off, size, NULL, 0 );
2007 }
2008 #endif
2009
2010
LSAPI_sendfile_r(LSAPI_Request * pReq,int fdIn,off_t * off,size_t size)2011 ssize_t LSAPI_sendfile_r( LSAPI_Request * pReq, int fdIn, off_t* off, size_t size )
2012 {
2013 struct lsapi_packet_header * pHeader = pReq->m_respPktHeader;
2014 if ( !pReq || (pReq->m_fd == -1) || fdIn == -1 )
2015 return -1;
2016 if ( pReq->m_reqState & LSAPI_ST_RESP_HEADER )
2017 {
2018 LSAPI_FinalizeRespHeaders_r( pReq );
2019 }
2020 pReq->m_reqState |= LSAPI_ST_RESP_BODY;
2021
2022 LSAPI_Flush_r(pReq);
2023
2024 lsapi_buildPacketHeader( pHeader, LSAPI_RESP_STREAM,
2025 size + LSAPI_PACKET_HEADER_LEN );
2026
2027
2028 if (write(pReq->m_fd, (const char *) pHeader, LSAPI_PACKET_HEADER_LEN ) != LSAPI_PACKET_HEADER_LEN)
2029 return -1;
2030
2031 return gsendfile( pReq->m_fd, fdIn, off, size );
2032 }
2033
2034
Flush_RespBuf_r(LSAPI_Request * pReq)2035 void Flush_RespBuf_r( LSAPI_Request * pReq )
2036 {
2037 struct lsapi_packet_header * pHeader = pReq->m_respPktHeader;
2038 int bufLen = pReq->m_pRespBufPos - pReq->m_pRespBuf;
2039 pReq->m_reqState |= LSAPI_ST_RESP_BODY;
2040 lsapi_buildPacketHeader( pHeader, LSAPI_RESP_STREAM,
2041 bufLen + LSAPI_PACKET_HEADER_LEN );
2042 pReq->m_totalLen += bufLen + LSAPI_PACKET_HEADER_LEN;
2043
2044 pReq->m_pIovecCur->iov_base = (void *)pHeader;
2045 pReq->m_pIovecCur->iov_len = LSAPI_PACKET_HEADER_LEN;
2046 ++pReq->m_pIovecCur;
2047 ++pHeader;
2048 if ( bufLen > 0 )
2049 {
2050 pReq->m_pIovecCur->iov_base = (void *)pReq->m_pRespBuf;
2051 pReq->m_pIovecCur->iov_len = bufLen;
2052 pReq->m_pRespBufPos = pReq->m_pRespBuf;
2053 ++pReq->m_pIovecCur;
2054 bufLen = 0;
2055 }
2056 }
2057
2058
LSAPI_Flush_r(LSAPI_Request * pReq)2059 int LSAPI_Flush_r( LSAPI_Request * pReq )
2060 {
2061 int ret = 0;
2062 int n;
2063 if ( !pReq )
2064 return -1;
2065 n = pReq->m_pIovecCur - pReq->m_pIovecToWrite;
2066 if (( 0 == n )&&( pReq->m_pRespBufPos == pReq->m_pRespBuf ))
2067 return 0;
2068 if ( pReq->m_fd == -1 )
2069 {
2070 pReq->m_pRespBufPos = pReq->m_pRespBuf;
2071 pReq->m_totalLen = 0;
2072 pReq->m_pIovecCur = pReq->m_pIovecToWrite = pReq->m_pIovec;
2073 return -1;
2074 }
2075 if ( pReq->m_reqState & LSAPI_ST_RESP_HEADER )
2076 {
2077 LSAPI_FinalizeRespHeaders_r( pReq );
2078 }
2079 if ( pReq->m_pRespBufPos != pReq->m_pRespBuf )
2080 {
2081 Flush_RespBuf_r( pReq );
2082 }
2083
2084 n = pReq->m_pIovecCur - pReq->m_pIovecToWrite;
2085 if ( n > 0 )
2086 {
2087
2088 ret = lsapi_writev( pReq->m_fd, &pReq->m_pIovecToWrite,
2089 n, pReq->m_totalLen );
2090 if ( ret < pReq->m_totalLen )
2091 {
2092 lsapi_close_connection(pReq);
2093 ret = -1;
2094 }
2095 pReq->m_totalLen = 0;
2096 pReq->m_pIovecCur = pReq->m_pIovecToWrite = pReq->m_pIovec;
2097 }
2098 return ret;
2099 }
2100
2101
LSAPI_Write_Stderr_r(LSAPI_Request * pReq,const char * pBuf,size_t len)2102 ssize_t LSAPI_Write_Stderr_r( LSAPI_Request * pReq, const char * pBuf, size_t len )
2103 {
2104 struct lsapi_packet_header header;
2105 const char * pEnd;
2106 const char * p;
2107 ssize_t packetLen;
2108 ssize_t totalLen;
2109 int ret;
2110 struct iovec iov[2];
2111 struct iovec *pIov;
2112
2113 if ( !pReq )
2114 return -1;
2115 if (s_stderr_log_path || pReq->m_fd == -1 || pReq->m_fd == pReq->m_fdListen)
2116 return write( 2, pBuf, len );
2117 if ( pReq->m_pRespBufPos != pReq->m_pRespBuf )
2118 {
2119 LSAPI_Flush_r( pReq );
2120 }
2121
2122 p = pBuf;
2123 pEnd = pBuf + len;
2124
2125 while( ( packetLen = pEnd - p ) > 0 )
2126 {
2127 if ( LSAPI_MAX_DATA_PACKET_LEN < packetLen)
2128 {
2129 packetLen = LSAPI_MAX_DATA_PACKET_LEN;
2130 }
2131
2132 lsapi_buildPacketHeader( &header, LSAPI_STDERR_STREAM,
2133 packetLen + LSAPI_PACKET_HEADER_LEN );
2134 totalLen = packetLen + LSAPI_PACKET_HEADER_LEN;
2135
2136 iov[0].iov_base = (void *)&header;
2137 iov[0].iov_len = LSAPI_PACKET_HEADER_LEN;
2138
2139 iov[1].iov_base = (void *)p;
2140 iov[1].iov_len = packetLen;
2141 p += packetLen;
2142 pIov = iov;
2143 ret = lsapi_writev( pReq->m_fd, &pIov,
2144 2, totalLen );
2145 if ( ret < totalLen )
2146 {
2147 lsapi_close_connection(pReq);
2148 ret = -1;
2149 }
2150 }
2151 return p - pBuf;
2152 }
2153
2154
GetHeaderVar(LSAPI_Request * pReq,const char * name)2155 static char * GetHeaderVar( LSAPI_Request * pReq, const char * name )
2156 {
2157 int i;
2158 char * pValue;
2159 for( i = 0; i < H_TRANSFER_ENCODING; ++i )
2160 {
2161 if ( pReq->m_pHeaderIndex->m_headerOff[i] )
2162 {
2163 if ( strcmp( name, CGI_HEADERS[i] ) == 0 )
2164 {
2165 pValue = pReq->m_pHttpHeader
2166 + pReq->m_pHeaderIndex->m_headerOff[i];
2167 if ( *(pValue + pReq->m_pHeaderIndex->m_headerLen[i]) != '\0')
2168 {
2169 *(pValue + pReq->m_pHeaderIndex->m_headerLen[i]) = '\0';
2170 }
2171 return pValue;
2172 }
2173 }
2174 }
2175 if ( pReq->m_pHeader->m_cntUnknownHeaders > 0 )
2176 {
2177 const char *p;
2178 char *pKey;
2179 char *pKeyEnd;
2180 int keyLen;
2181 struct lsapi_header_offset * pCur, *pEnd;
2182 pCur = pReq->m_pUnknownHeader;
2183 pEnd = pCur + pReq->m_pHeader->m_cntUnknownHeaders;
2184 while( pCur < pEnd )
2185 {
2186 pKey = pReq->m_pHttpHeader + pCur->nameOff;
2187 keyLen = pCur->nameLen;
2188 pKeyEnd = pKey + keyLen;
2189 p = &name[5];
2190
2191 while(( pKey < pKeyEnd )&&( *p ))
2192 {
2193 char ch = toupper( *pKey );
2194 if ((ch != *p )||(( *p == '_' )&&( ch != '-')))
2195 break;
2196 ++p; ++pKey;
2197 }
2198 if (( pKey == pKeyEnd )&& (!*p ))
2199 {
2200 pValue = pReq->m_pHttpHeader + pCur->valueOff;
2201
2202 if ( *(pValue + pCur->valueLen) != '\0')
2203 {
2204 *(pValue + pCur->valueLen) = '\0';
2205 }
2206 return pValue;
2207 }
2208 ++pCur;
2209 }
2210 }
2211 return NULL;
2212 }
2213
2214
LSAPI_GetEnv_r(LSAPI_Request * pReq,const char * name)2215 char * LSAPI_GetEnv_r( LSAPI_Request * pReq, const char * name )
2216 {
2217 struct LSAPI_key_value_pair * pBegin = pReq->m_pEnvList;
2218 struct LSAPI_key_value_pair * pEnd = pBegin + pReq->m_pHeader->m_cntEnv;
2219 if ( !pReq || !name )
2220 return NULL;
2221 if ( strncmp( name, "HTTP_", 5 ) == 0 )
2222 {
2223 return GetHeaderVar( pReq, name );
2224 }
2225 while( pBegin < pEnd )
2226 {
2227 if ( strcmp( name, pBegin->pKey ) == 0 )
2228 return pBegin->pValue;
2229 ++pBegin;
2230 }
2231 return NULL;
2232 }
2233
2234
2235 struct _headerInfo
2236 {
2237 const char * _name;
2238 int _nameLen;
2239 const char * _value;
2240 int _valueLen;
2241 };
2242
2243
compareValueLocation(const void * v1,const void * v2)2244 int compareValueLocation(const void * v1, const void *v2 )
2245 {
2246 return ((const struct _headerInfo *)v1)->_value -
2247 ((const struct _headerInfo *)v2)->_value;
2248 }
2249
2250
LSAPI_ForeachOrgHeader_r(LSAPI_Request * pReq,LSAPI_CB_EnvHandler fn,void * arg)2251 int LSAPI_ForeachOrgHeader_r( LSAPI_Request * pReq,
2252 LSAPI_CB_EnvHandler fn, void * arg )
2253 {
2254 int i;
2255 int len = 0;
2256 char * pValue;
2257 int ret;
2258 int count = 0;
2259 struct _headerInfo headers[512];
2260
2261 if ( !pReq || !fn )
2262 return -1;
2263
2264 if ( !pReq->m_pHeaderIndex )
2265 return 0;
2266
2267 for( i = 0; i < H_TRANSFER_ENCODING; ++i )
2268 {
2269 if ( pReq->m_pHeaderIndex->m_headerOff[i] )
2270 {
2271 len = pReq->m_pHeaderIndex->m_headerLen[i];
2272 pValue = pReq->m_pHttpHeader + pReq->m_pHeaderIndex->m_headerOff[i];
2273 *(pValue + len ) = 0;
2274 headers[count]._name = HTTP_HEADERS[i];
2275 headers[count]._nameLen = HTTP_HEADER_LEN[i];
2276 headers[count]._value = pValue;
2277 headers[count]._valueLen = len;
2278 ++count;
2279
2280 //ret = (*fn)( HTTP_HEADERS[i], HTTP_HEADER_LEN[i],
2281 // pValue, len, arg );
2282 //if ( ret <= 0 )
2283 // return ret;
2284 }
2285 }
2286 if ( pReq->m_pHeader->m_cntUnknownHeaders > 0 )
2287 {
2288 char *pKey;
2289 int keyLen;
2290 struct lsapi_header_offset * pCur, *pEnd;
2291 pCur = pReq->m_pUnknownHeader;
2292 pEnd = pCur + pReq->m_pHeader->m_cntUnknownHeaders;
2293 while( pCur < pEnd )
2294 {
2295 pKey = pReq->m_pHttpHeader + pCur->nameOff;
2296 keyLen = pCur->nameLen;
2297 *(pKey + keyLen ) = 0;
2298
2299 pValue = pReq->m_pHttpHeader + pCur->valueOff;
2300 *(pValue + pCur->valueLen ) = 0;
2301 headers[count]._name = pKey;
2302 headers[count]._nameLen = keyLen;
2303 headers[count]._value = pValue;
2304 headers[count]._valueLen = pCur->valueLen;
2305 ++count;
2306 if ( count == 512 )
2307 break;
2308 //ret = (*fn)( pKey, keyLen,
2309 // pValue, pCur->valueLen, arg );
2310 //if ( ret <= 0 )
2311 // return ret;
2312 ++pCur;
2313 }
2314 }
2315 qsort( headers, count, sizeof( struct _headerInfo ), compareValueLocation );
2316 for( i = 0; i < count; ++i )
2317 {
2318 ret = (*fn)( headers[i]._name, headers[i]._nameLen,
2319 headers[i]._value, headers[i]._valueLen, arg );
2320 if ( ret <= 0 )
2321 return ret;
2322 }
2323 return count;
2324 }
2325
2326
LSAPI_ForeachHeader_r(LSAPI_Request * pReq,LSAPI_CB_EnvHandler fn,void * arg)2327 int LSAPI_ForeachHeader_r( LSAPI_Request * pReq,
2328 LSAPI_CB_EnvHandler fn, void * arg )
2329 {
2330 int i;
2331 int len = 0;
2332 char * pValue;
2333 int ret;
2334 int count = 0;
2335 if ( !pReq || !fn )
2336 return -1;
2337 for( i = 0; i < H_TRANSFER_ENCODING; ++i )
2338 {
2339 if ( pReq->m_pHeaderIndex->m_headerOff[i] )
2340 {
2341 len = pReq->m_pHeaderIndex->m_headerLen[i];
2342 pValue = pReq->m_pHttpHeader + pReq->m_pHeaderIndex->m_headerOff[i];
2343 *(pValue + len ) = 0;
2344 ret = (*fn)( CGI_HEADERS[i], CGI_HEADER_LEN[i],
2345 pValue, len, arg );
2346 ++count;
2347 if ( ret <= 0 )
2348 return ret;
2349 }
2350 }
2351 if ( pReq->m_pHeader->m_cntUnknownHeaders > 0 )
2352 {
2353 char achHeaderName[256];
2354 char *p;
2355 char *pKey;
2356 char *pKeyEnd ;
2357 int keyLen;
2358 struct lsapi_header_offset * pCur, *pEnd;
2359 pCur = pReq->m_pUnknownHeader;
2360 pEnd = pCur + pReq->m_pHeader->m_cntUnknownHeaders;
2361 while( pCur < pEnd )
2362 {
2363 pKey = pReq->m_pHttpHeader + pCur->nameOff;
2364 keyLen = pCur->nameLen;
2365 if ( keyLen > 250 )
2366 keyLen = 250;
2367 pKeyEnd = pKey + keyLen;
2368 memcpy( achHeaderName, "HTTP_", 5 );
2369 p = &achHeaderName[5];
2370
2371 while( pKey < pKeyEnd )
2372 {
2373 char ch = *pKey++;
2374 if ( ch == '-' )
2375 *p++ = '_';
2376 else
2377 *p++ = toupper( ch );
2378 }
2379 *p = 0;
2380 keyLen += 5;
2381
2382 pValue = pReq->m_pHttpHeader + pCur->valueOff;
2383 *(pValue + pCur->valueLen ) = 0;
2384 ret = (*fn)( achHeaderName, keyLen,
2385 pValue, pCur->valueLen, arg );
2386 if ( ret <= 0 )
2387 return ret;
2388 ++pCur;
2389 }
2390 }
2391 return count + pReq->m_pHeader->m_cntUnknownHeaders;
2392 }
2393
2394
EnvForeach(struct LSAPI_key_value_pair * pEnv,int n,LSAPI_CB_EnvHandler fn,void * arg)2395 static int EnvForeach( struct LSAPI_key_value_pair * pEnv,
2396 int n, LSAPI_CB_EnvHandler fn, void * arg )
2397 {
2398 struct LSAPI_key_value_pair * pEnd = pEnv + n;
2399 int ret;
2400 if ( !pEnv || !fn )
2401 return -1;
2402 while( pEnv < pEnd )
2403 {
2404 ret = (*fn)( pEnv->pKey, pEnv->keyLen,
2405 pEnv->pValue, pEnv->valLen, arg );
2406 if ( ret <= 0 )
2407 return ret;
2408 ++pEnv;
2409 }
2410 return n;
2411 }
2412
2413
LSAPI_ForeachEnv_r(LSAPI_Request * pReq,LSAPI_CB_EnvHandler fn,void * arg)2414 int LSAPI_ForeachEnv_r( LSAPI_Request * pReq,
2415 LSAPI_CB_EnvHandler fn, void * arg )
2416 {
2417 if ( !pReq || !fn )
2418 return -1;
2419 if ( pReq->m_pHeader->m_cntEnv > 0 )
2420 {
2421 return EnvForeach( pReq->m_pEnvList, pReq->m_pHeader->m_cntEnv,
2422 fn, arg );
2423 }
2424 return 0;
2425 }
2426
2427
LSAPI_ForeachSpecialEnv_r(LSAPI_Request * pReq,LSAPI_CB_EnvHandler fn,void * arg)2428 int LSAPI_ForeachSpecialEnv_r( LSAPI_Request * pReq,
2429 LSAPI_CB_EnvHandler fn, void * arg )
2430 {
2431 if ( !pReq || !fn )
2432 return -1;
2433 if ( pReq->m_pHeader->m_cntSpecialEnv > 0 )
2434 {
2435 return EnvForeach( pReq->m_pSpecialEnvList,
2436 pReq->m_pHeader->m_cntSpecialEnv,
2437 fn, arg );
2438 }
2439 return 0;
2440
2441 }
2442
2443
LSAPI_FinalizeRespHeaders_r(LSAPI_Request * pReq)2444 int LSAPI_FinalizeRespHeaders_r( LSAPI_Request * pReq )
2445 {
2446 if ( !pReq || !pReq->m_pIovec )
2447 return -1;
2448 if ( !( pReq->m_reqState & LSAPI_ST_RESP_HEADER ) )
2449 return 0;
2450 pReq->m_reqState &= ~LSAPI_ST_RESP_HEADER;
2451 if ( pReq->m_pRespHeaderBufPos > pReq->m_pRespHeaderBuf )
2452 {
2453 pReq->m_pIovecCur->iov_base = (void *)pReq->m_pRespHeaderBuf;
2454 pReq->m_pIovecCur->iov_len = pReq->m_pRespHeaderBufPos - pReq->m_pRespHeaderBuf;
2455 pReq->m_totalLen += pReq->m_pIovecCur->iov_len;
2456 ++pReq->m_pIovecCur;
2457 }
2458
2459 pReq->m_pIovec->iov_len = sizeof( struct lsapi_resp_header)
2460 + pReq->m_respHeader.m_respInfo.m_cntHeaders * sizeof( short );
2461 pReq->m_totalLen += pReq->m_pIovec->iov_len;
2462
2463 lsapi_buildPacketHeader( &pReq->m_respHeader.m_pktHeader,
2464 LSAPI_RESP_HEADER, pReq->m_totalLen );
2465 pReq->m_pIovec->iov_base = (void *)&pReq->m_respHeader;
2466 pReq->m_pIovecToWrite = pReq->m_pIovec;
2467 return 0;
2468 }
2469
2470
LSAPI_AppendRespHeader2_r(LSAPI_Request * pReq,const char * pHeaderName,const char * pHeaderValue)2471 int LSAPI_AppendRespHeader2_r( LSAPI_Request * pReq, const char * pHeaderName,
2472 const char * pHeaderValue )
2473 {
2474 int nameLen, valLen, len;
2475 if ( !pReq || !pHeaderName || !pHeaderValue )
2476 return -1;
2477 if ( pReq->m_reqState & LSAPI_ST_RESP_BODY )
2478 return -1;
2479 if ( pReq->m_respHeader.m_respInfo.m_cntHeaders >= LSAPI_MAX_RESP_HEADERS )
2480 return -1;
2481 nameLen = strlen( pHeaderName );
2482 valLen = strlen( pHeaderValue );
2483 if ( nameLen == 0 )
2484 return -1;
2485 while( nameLen > 0 )
2486 {
2487 char ch = *(pHeaderName + nameLen - 1 );
2488 if (( ch == '\n' )||( ch == '\r' ))
2489 --nameLen;
2490 else
2491 break;
2492 }
2493 if ( nameLen <= 0 )
2494 return 0;
2495 while( valLen > 0 )
2496 {
2497 char ch = *(pHeaderValue + valLen - 1 );
2498 if (( ch == '\n' )||( ch == '\r' ))
2499 --valLen;
2500 else
2501 break;
2502 }
2503 len = nameLen + valLen + 1;
2504 if ( len > LSAPI_RESP_HTTP_HEADER_MAX )
2505 return -1;
2506
2507 if ( pReq->m_pRespHeaderBufPos + len + 1 > pReq->m_pRespHeaderBufEnd )
2508 {
2509 int newlen = pReq->m_pRespHeaderBufPos + len + 4096 - pReq->m_pRespHeaderBuf;
2510 newlen -= newlen % 4096;
2511 if ( allocateRespHeaderBuf( pReq, newlen ) == -1 )
2512 return -1;
2513 }
2514 memmove( pReq->m_pRespHeaderBufPos, pHeaderName, nameLen );
2515 pReq->m_pRespHeaderBufPos += nameLen;
2516 *pReq->m_pRespHeaderBufPos++ = ':';
2517 memmove( pReq->m_pRespHeaderBufPos, pHeaderValue, valLen );
2518 pReq->m_pRespHeaderBufPos += valLen;
2519 *pReq->m_pRespHeaderBufPos++ = 0;
2520 ++len; /* add one byte padding for \0 */
2521 pReq->m_respHeaderLen[pReq->m_respHeader.m_respInfo.m_cntHeaders] = len;
2522 ++pReq->m_respHeader.m_respInfo.m_cntHeaders;
2523 return 0;
2524 }
2525
2526
LSAPI_AppendRespHeader_r(LSAPI_Request * pReq,const char * pBuf,int len)2527 int LSAPI_AppendRespHeader_r( LSAPI_Request * pReq, const char * pBuf, int len )
2528 {
2529 if ( !pReq || !pBuf || len <= 0 || len > LSAPI_RESP_HTTP_HEADER_MAX )
2530 return -1;
2531 if ( pReq->m_reqState & LSAPI_ST_RESP_BODY )
2532 return -1;
2533 if ( pReq->m_respHeader.m_respInfo.m_cntHeaders >= LSAPI_MAX_RESP_HEADERS )
2534 return -1;
2535 while( len > 0 )
2536 {
2537 char ch = *(pBuf + len - 1 );
2538 if (( ch == '\n' )||( ch == '\r' ))
2539 --len;
2540 else
2541 break;
2542 }
2543 if ( len <= 0 )
2544 return 0;
2545 if ( pReq->m_pRespHeaderBufPos + len + 1 > pReq->m_pRespHeaderBufEnd )
2546 {
2547 int newlen = pReq->m_pRespHeaderBufPos + len + 4096 - pReq->m_pRespHeaderBuf;
2548 newlen -= newlen % 4096;
2549 if ( allocateRespHeaderBuf( pReq, newlen ) == -1 )
2550 return -1;
2551 }
2552 memmove( pReq->m_pRespHeaderBufPos, pBuf, len );
2553 pReq->m_pRespHeaderBufPos += len;
2554 *pReq->m_pRespHeaderBufPos++ = 0;
2555 ++len; /* add one byte padding for \0 */
2556 pReq->m_respHeaderLen[pReq->m_respHeader.m_respInfo.m_cntHeaders] = len;
2557 ++pReq->m_respHeader.m_respInfo.m_cntHeaders;
2558 return 0;
2559 }
2560
2561
LSAPI_CreateListenSock2(const struct sockaddr * pServerAddr,int backlog)2562 int LSAPI_CreateListenSock2( const struct sockaddr * pServerAddr, int backlog )
2563 {
2564 int ret;
2565 int fd;
2566 int flag = 1;
2567 int addr_len;
2568
2569 switch( pServerAddr->sa_family )
2570 {
2571 case AF_INET:
2572 addr_len = 16;
2573 break;
2574 case AF_INET6:
2575 addr_len = sizeof( struct sockaddr_in6 );
2576 break;
2577 case AF_UNIX:
2578 addr_len = sizeof( struct sockaddr_un );
2579 unlink( ((struct sockaddr_un *)pServerAddr)->sun_path );
2580 break;
2581 default:
2582 return -1;
2583 }
2584
2585 fd = socket( pServerAddr->sa_family, SOCK_STREAM, 0 );
2586 if ( fd == -1 )
2587 return -1;
2588
2589 fcntl( fd, F_SETFD, FD_CLOEXEC );
2590
2591 if(setsockopt( fd, SOL_SOCKET, SO_REUSEADDR,
2592 (char *)( &flag ), sizeof(flag)) == 0)
2593 {
2594 ret = bind( fd, pServerAddr, addr_len );
2595 if ( !ret )
2596 {
2597 ret = listen( fd, backlog );
2598 if ( !ret )
2599 return fd;
2600 }
2601 }
2602
2603 ret = errno;
2604 close(fd);
2605 errno = ret;
2606 return -1;
2607 }
2608
2609
LSAPI_ParseSockAddr(const char * pBind,struct sockaddr * pAddr)2610 int LSAPI_ParseSockAddr( const char * pBind, struct sockaddr * pAddr )
2611 {
2612 char achAddr[256];
2613 char * p = achAddr;
2614 char * pEnd;
2615 struct addrinfo *res, hints;
2616 int doAddrInfo = 0;
2617 int port;
2618
2619 if ( !pBind )
2620 return -1;
2621
2622 while( isspace( *pBind ) )
2623 ++pBind;
2624
2625 strncpy(achAddr, pBind, 255);
2626 achAddr[255] = 0;
2627
2628 switch( *p )
2629 {
2630 case '/':
2631 pAddr->sa_family = AF_UNIX;
2632 strncpy( ((struct sockaddr_un *)pAddr)->sun_path, p,
2633 sizeof(((struct sockaddr_un *)pAddr)->sun_path) );
2634 return 0;
2635
2636 case '[':
2637 pAddr->sa_family = AF_INET6;
2638 ++p;
2639 pEnd = strchr( p, ']' );
2640 if ( !pEnd )
2641 return -1;
2642 *pEnd++ = 0;
2643
2644 if ( *p == '*' )
2645 {
2646 strcpy( achAddr, "::" );
2647 p = achAddr;
2648 }
2649 doAddrInfo = 1;
2650 break;
2651
2652 default:
2653 pAddr->sa_family = AF_INET;
2654 pEnd = strchr( p, ':' );
2655 if ( !pEnd )
2656 return -1;
2657 *pEnd++ = 0;
2658
2659 doAddrInfo = 0;
2660 if ( *p == '*' )
2661 {
2662 ((struct sockaddr_in *)pAddr)->sin_addr.s_addr = htonl(INADDR_ANY);
2663 }
2664 else if (!strcasecmp( p, "localhost" ) )
2665 ((struct sockaddr_in *)pAddr)->sin_addr.s_addr = htonl( INADDR_LOOPBACK );
2666 else
2667 {
2668 ((struct sockaddr_in *)pAddr)->sin_addr.s_addr = inet_addr( p );
2669 if ( ((struct sockaddr_in *)pAddr)->sin_addr.s_addr == INADDR_BROADCAST)
2670 {
2671 doAddrInfo = 1;
2672 }
2673 }
2674 break;
2675 }
2676 if ( *pEnd == ':' )
2677 ++pEnd;
2678
2679 port = atoi( pEnd );
2680 if (( port <= 0 )||( port > 65535 ))
2681 return -1;
2682 if ( doAddrInfo )
2683 {
2684
2685 memset(&hints, 0, sizeof(hints));
2686
2687 hints.ai_family = pAddr->sa_family;
2688 hints.ai_socktype = SOCK_STREAM;
2689 hints.ai_protocol = IPPROTO_TCP;
2690
2691 if ( getaddrinfo(p, NULL, &hints, &res) )
2692 {
2693 return -1;
2694 }
2695
2696 memcpy(pAddr, res->ai_addr, res->ai_addrlen);
2697 freeaddrinfo(res);
2698 }
2699
2700 if ( pAddr->sa_family == AF_INET )
2701 ((struct sockaddr_in *)pAddr)->sin_port = htons( port );
2702 else
2703 ((struct sockaddr_in6 *)pAddr)->sin6_port = htons( port );
2704 return 0;
2705
2706 }
2707
2708
LSAPI_CreateListenSock(const char * pBind,int backlog)2709 int LSAPI_CreateListenSock( const char * pBind, int backlog )
2710 {
2711 char serverAddr[128];
2712 int ret;
2713 int fd = -1;
2714 ret = LSAPI_ParseSockAddr( pBind, (struct sockaddr *)serverAddr );
2715 if ( !ret )
2716 {
2717 fd = LSAPI_CreateListenSock2( (struct sockaddr *)serverAddr, backlog );
2718 }
2719 return fd;
2720 }
2721
2722
2723 static fn_select_t g_fnSelect = select;
2724 typedef struct _lsapi_prefork_server
2725 {
2726 int m_fd;
2727 int m_iMaxChildren;
2728 int m_iExtraChildren;
2729 int m_iCurChildren;
2730 int m_iMaxIdleChildren;
2731 int m_iServerMaxIdle;
2732 int m_iChildrenMaxIdleTime;
2733 int m_iMaxReqProcessTime;
2734 int m_iAvoidFork;
2735
2736 lsapi_child_status * m_pChildrenStatus;
2737 lsapi_child_status * m_pChildrenStatusCur;
2738 lsapi_child_status * m_pChildrenStatusEnd;
2739
2740 }lsapi_prefork_server;
2741 static lsapi_prefork_server * g_prefork_server = NULL;
2742
2743
LSAPI_Init_Prefork_Server(int max_children,fn_select_t fp,int avoidFork)2744 int LSAPI_Init_Prefork_Server( int max_children, fn_select_t fp, int avoidFork )
2745 {
2746 if ( g_prefork_server )
2747 return 0;
2748 if ( max_children <= 1 )
2749 return -1;
2750 if ( max_children >= 10000)
2751 max_children = 10000;
2752
2753 if (s_max_busy_workers == 0)
2754 s_max_busy_workers = max_children / 2 + 1;
2755
2756 g_prefork_server = (lsapi_prefork_server *)malloc( sizeof( lsapi_prefork_server ) );
2757 if ( !g_prefork_server )
2758 return -1;
2759 memset( g_prefork_server, 0, sizeof( lsapi_prefork_server ) );
2760
2761 if ( fp != NULL )
2762 g_fnSelect = fp;
2763
2764 s_ppid = getppid();
2765 s_pid = getpid();
2766 setpgid( s_pid, s_pid );
2767 #if defined(linux) || defined(__linux) || defined(__linux__) || defined(__gnu_linux__)
2768 s_total_pages = sysconf(_SC_PHYS_PAGES);
2769 #endif
2770 g_prefork_server->m_iAvoidFork = avoidFork;
2771 g_prefork_server->m_iMaxChildren = max_children;
2772
2773 g_prefork_server->m_iExtraChildren = ( avoidFork ) ? 0 : (max_children / 3) ;
2774 g_prefork_server->m_iMaxIdleChildren = ( avoidFork ) ? (max_children + 1) : (max_children / 3);
2775 if ( g_prefork_server->m_iMaxIdleChildren == 0 )
2776 g_prefork_server->m_iMaxIdleChildren = 1;
2777 g_prefork_server->m_iChildrenMaxIdleTime = 300;
2778 g_prefork_server->m_iMaxReqProcessTime = 3600;
2779
2780 setsid();
2781
2782 return 0;
2783 }
2784
2785
LSAPI_Set_Server_fd(int fd)2786 void LSAPI_Set_Server_fd( int fd )
2787 {
2788 if( g_prefork_server )
2789 g_prefork_server->m_fd = fd;
2790 }
2791
2792
lsapi_accept(int fdListen)2793 static int lsapi_accept( int fdListen )
2794 {
2795 int fd;
2796 int nodelay = 1;
2797 socklen_t len;
2798 char achPeer[128];
2799
2800 len = sizeof( achPeer );
2801 fd = accept( fdListen, (struct sockaddr *)&achPeer, &len );
2802 if ( fd != -1 )
2803 {
2804 if (((struct sockaddr *)&achPeer)->sa_family == AF_INET )
2805 {
2806 setsockopt( fd, IPPROTO_TCP, TCP_NODELAY,
2807 (char *)&nodelay, sizeof(nodelay));
2808 }
2809
2810 //OPTIMIZATION
2811 //if ( s_accept_notify )
2812 // notify_req_received( fd );
2813 }
2814 return fd;
2815
2816 }
2817
2818
2819 static unsigned int s_max_reqs = UINT_MAX;
2820 static int s_max_idle_secs = 300;
2821 static int s_stop;
2822
lsapi_cleanup(int signal)2823 static void lsapi_cleanup(int signal)
2824 {
2825 s_stop = signal;
2826 }
2827
2828
find_child_status(int pid)2829 static lsapi_child_status * find_child_status( int pid )
2830 {
2831 lsapi_child_status * pStatus = g_prefork_server->m_pChildrenStatus;
2832 lsapi_child_status * pEnd = g_prefork_server->m_pChildrenStatusEnd;
2833 while( pStatus < pEnd )
2834 {
2835 if ( pStatus->m_pid == pid )
2836 {
2837 if (pid == 0)
2838 {
2839 memset(pStatus, 0, sizeof( *pStatus ) );
2840 pStatus->m_pid = -1;
2841 }
2842 if ( pStatus + 1 > g_prefork_server->m_pChildrenStatusCur )
2843 g_prefork_server->m_pChildrenStatusCur = pStatus + 1;
2844 return pStatus;
2845 }
2846 ++pStatus;
2847 }
2848 return NULL;
2849 }
2850
2851
LSAPI_reset_server_state(void)2852 void LSAPI_reset_server_state( void )
2853 {
2854 /*
2855 Reset child status
2856 */
2857 g_prefork_server->m_iCurChildren = 0;
2858 lsapi_child_status * pStatus = g_prefork_server->m_pChildrenStatus;
2859 lsapi_child_status * pEnd = g_prefork_server->m_pChildrenStatusEnd;
2860 while( pStatus < pEnd )
2861 {
2862 pStatus->m_pid = 0;
2863 ++pStatus;
2864 }
2865 if (s_busy_workers)
2866 __sync_lock_release(s_busy_workers);
2867 if (s_accepting_workers)
2868 __sync_lock_release(s_accepting_workers);
2869
2870 }
2871
2872
lsapi_sigchild(int signal)2873 static void lsapi_sigchild( int signal )
2874 {
2875 int status, pid;
2876 lsapi_child_status * child_status;
2877 if (g_prefork_server == NULL)
2878 return;
2879 while( 1 )
2880 {
2881 pid = waitpid( -1, &status, WNOHANG|WUNTRACED );
2882 if ( pid <= 0 )
2883 {
2884 break;
2885 }
2886 if ( WIFSIGNALED( status ))
2887 {
2888 int sig_num = WTERMSIG( status );
2889
2890 #ifdef WCOREDUMP
2891 const char * dump = WCOREDUMP( status ) ? "yes" : "no";
2892 #else
2893 const char * dump = "unknown";
2894 #endif
2895 lsapi_log("Child process with pid: %d was killed by signal: "
2896 "%d, core dumped: %s\n", pid, sig_num, dump );
2897 }
2898 if ( pid == s_pid_dump_debug_info )
2899 {
2900 pid = 0;
2901 continue;
2902 }
2903 if ( pid == s_ignore_pid )
2904 {
2905 pid = 0;
2906 s_ignore_pid = -1;
2907 continue;
2908 }
2909 child_status = find_child_status( pid );
2910 if ( child_status )
2911 {
2912 if (__sync_bool_compare_and_swap(&child_status->m_state,
2913 LSAPI_STATE_CONNECTED,
2914 LSAPI_STATE_IDLE))
2915 {
2916 if (s_busy_workers)
2917 __sync_fetch_and_sub(s_busy_workers, 1);
2918 }
2919 else if (__sync_bool_compare_and_swap(&child_status->m_state,
2920 LSAPI_STATE_ACCEPTING,
2921 LSAPI_STATE_IDLE))
2922 {
2923 if (s_accepting_workers)
2924 __sync_fetch_and_sub(s_accepting_workers, 1);
2925 }
2926 child_status->m_pid = 0;
2927 --g_prefork_server->m_iCurChildren;
2928 }
2929 }
2930 while(( g_prefork_server->m_pChildrenStatusCur > g_prefork_server->m_pChildrenStatus )
2931 &&( g_prefork_server->m_pChildrenStatusCur[-1].m_pid == 0 ))
2932 --g_prefork_server->m_pChildrenStatusCur;
2933
2934 }
2935
2936
lsapi_init_children_status(void)2937 static int lsapi_init_children_status(void)
2938 {
2939 int size = 4096;
2940 int max_children;
2941 if (g_prefork_server->m_pChildrenStatus)
2942 return 0;
2943 max_children = g_prefork_server->m_iMaxChildren
2944 + g_prefork_server->m_iExtraChildren;
2945
2946 char * pBuf;
2947 size = max_children * sizeof( lsapi_child_status ) * 2 + 3 * sizeof(int);
2948 size = (size + 4095) / 4096 * 4096;
2949 pBuf =( char*) mmap( NULL, size, PROT_READ | PROT_WRITE,
2950 MAP_ANON | MAP_SHARED, -1, 0 );
2951 if ( pBuf == MAP_FAILED )
2952 {
2953 perror( "Anonymous mmap() failed" );
2954 return -1;
2955 }
2956 memset( pBuf, 0, size );
2957 g_prefork_server->m_pChildrenStatus = (lsapi_child_status *)pBuf;
2958 g_prefork_server->m_pChildrenStatusCur = (lsapi_child_status *)pBuf;
2959 g_prefork_server->m_pChildrenStatusEnd = (lsapi_child_status *)pBuf + max_children;
2960 s_busy_workers = (int *)g_prefork_server->m_pChildrenStatusEnd;
2961 s_accepting_workers = s_busy_workers + 1;
2962 s_global_counter = s_accepting_workers + 1;
2963 s_avail_pages = (size_t *)(s_global_counter + 1);
2964
2965 setsid();
2966 return 0;
2967 }
2968
2969
dump_debug_info(lsapi_child_status * pStatus,long tmCur)2970 static void dump_debug_info( lsapi_child_status * pStatus, long tmCur )
2971 {
2972 char achCmd[1024];
2973 if ( s_pid_dump_debug_info )
2974 {
2975 if ( kill( s_pid_dump_debug_info, 0 ) == 0 )
2976 return;
2977 }
2978
2979 lsapi_log("Possible runaway process, PPID: %d, PID: %d, "
2980 "reqCount: %d, process time: %ld, checkpoint time: %ld, start "
2981 "time: %ld\n", getpid(), pStatus->m_pid,
2982 pStatus->m_iReqCounter, tmCur - pStatus->m_tmReqBegin,
2983 tmCur - pStatus->m_tmLastCheckPoint, tmCur - pStatus->m_tmStart );
2984
2985 s_pid_dump_debug_info = fork();
2986 if (s_pid_dump_debug_info == 0)
2987 {
2988 snprintf( achCmd, 1024, "gdb --batch -ex \"attach %d\" -ex \"set height 0\" "
2989 "-ex \"bt\" >&2;PATH=$PATH:/usr/sbin lsof -p %d >&2",
2990 pStatus->m_pid, pStatus->m_pid );
2991 if ( system( achCmd ) == -1 )
2992 perror( "system()" );
2993 exit( 0 );
2994 }
2995 }
2996
2997
lsapi_check_child_status(long tmCur)2998 static void lsapi_check_child_status( long tmCur )
2999 {
3000 int idle = 0;
3001 int tobekilled;
3002 int dying = 0;
3003 int count = 0;
3004 lsapi_child_status * pStatus = g_prefork_server->m_pChildrenStatus;
3005 lsapi_child_status * pEnd = g_prefork_server->m_pChildrenStatusCur;
3006 while( pStatus < pEnd )
3007 {
3008 tobekilled = 0;
3009 if ( pStatus->m_pid != 0 )
3010 {
3011 ++count;
3012 if ( !pStatus->m_inProcess )
3013 {
3014
3015 if (g_prefork_server->m_iCurChildren - dying
3016 > g_prefork_server->m_iMaxChildren
3017 || idle > g_prefork_server->m_iMaxIdleChildren)
3018 {
3019 ++pStatus->m_iKillSent;
3020 //tobekilled = SIGUSR1;
3021 }
3022 else
3023 {
3024 if (s_max_idle_secs> 0
3025 && tmCur - pStatus->m_tmWaitBegin > s_max_idle_secs + 5)
3026 {
3027 ++pStatus->m_iKillSent;
3028 //tobekilled = SIGUSR1;
3029 }
3030 }
3031 if ( !tobekilled )
3032 ++idle;
3033 }
3034 else
3035 {
3036 if (tmCur - pStatus->m_tmReqBegin >
3037 g_prefork_server->m_iMaxReqProcessTime)
3038 {
3039 if ((pStatus->m_iKillSent % 5) == 0 && s_dump_debug_info)
3040 dump_debug_info( pStatus, tmCur );
3041 if ( pStatus->m_iKillSent > 5 )
3042 {
3043 tobekilled = SIGKILL;
3044 lsapi_log("Force killing runaway process PID: %d"
3045 " with SIGKILL\n", pStatus->m_pid );
3046 }
3047 else
3048 {
3049 tobekilled = SIGTERM;
3050 lsapi_log("Killing runaway process PID: %d with "
3051 "SIGTERM\n", pStatus->m_pid );
3052 }
3053 }
3054 }
3055 if ( tobekilled )
3056 {
3057 if (( kill( pStatus->m_pid, tobekilled ) == -1 ) &&
3058 ( errno == ESRCH ))
3059 {
3060 pStatus->m_pid = 0;
3061 --count;
3062 }
3063 else
3064 {
3065 ++pStatus->m_iKillSent;
3066 ++dying;
3067 }
3068 }
3069 }
3070 ++pStatus;
3071 }
3072 if ( abs( g_prefork_server->m_iCurChildren - count ) > 1 )
3073 {
3074 lsapi_log("Children tracking is wrong: Cur Children: %d,"
3075 " count: %d, idle: %d, dying: %d\n",
3076 g_prefork_server->m_iCurChildren, count, idle, dying );
3077 }
3078 }
3079
3080
3081 //static int lsapi_all_children_must_die(void)
3082 //{
3083 // int maxWait;
3084 // int sec =0;
3085 // g_prefork_server->m_iMaxReqProcessTime = 10;
3086 // g_prefork_server->m_iMaxIdleChildren = -1;
3087 // maxWait = 15;
3088 //
3089 // while( g_prefork_server->m_iCurChildren && (sec < maxWait) )
3090 // {
3091 // lsapi_check_child_status(time(NULL));
3092 // sleep( 1 );
3093 // sec++;
3094 // }
3095 // if ( g_prefork_server->m_iCurChildren != 0 )
3096 // kill( -getpgrp(), SIGKILL );
3097 // return 0;
3098 //}
3099
3100
set_skip_write()3101 void set_skip_write()
3102 { s_skip_write = 1; }
3103
3104
is_enough_free_mem()3105 int is_enough_free_mem()
3106 {
3107 #if defined(linux) || defined(__linux) || defined(__linux__) || defined(__gnu_linux__)
3108 //minimum 1GB or 10% available free memory
3109 return (*s_avail_pages > s_min_avail_pages
3110 || (*s_avail_pages * 10) / s_total_pages > 0);
3111 #endif
3112 return 1;
3113 }
3114
3115
lsapi_prefork_server_accept(lsapi_prefork_server * pServer,LSAPI_Request * pReq)3116 static int lsapi_prefork_server_accept( lsapi_prefork_server * pServer,
3117 LSAPI_Request * pReq )
3118 {
3119 struct sigaction act, old_term, old_quit, old_int,
3120 old_usr1, old_child;
3121 lsapi_child_status * child_status;
3122 int wait_secs = 0;
3123 int ret = 0;
3124 int pid;
3125 time_t lastTime = 0;
3126 time_t curTime = 0;
3127 fd_set readfds;
3128 struct timeval timeout;
3129
3130 sigset_t mask;
3131 sigset_t orig_mask;
3132
3133 lsapi_init_children_status();
3134
3135 act.sa_flags = 0;
3136 act.sa_handler = lsapi_sigchild;
3137 sigemptyset(&(act.sa_mask));
3138 if( sigaction( SIGCHLD, &act, &old_child ) )
3139 {
3140 perror( "Can't set signal handler for SIGCHILD" );
3141 return -1;
3142 }
3143
3144 /* Set up handler to kill children upon exit */
3145 act.sa_flags = 0;
3146 act.sa_handler = lsapi_cleanup;
3147 sigemptyset(&(act.sa_mask));
3148 if( sigaction( SIGTERM, &act, &old_term ) ||
3149 sigaction( SIGINT, &act, &old_int ) ||
3150 sigaction( SIGUSR1, &act, &old_usr1 ) ||
3151 sigaction( SIGQUIT, &act, &old_quit ))
3152 {
3153 perror( "Can't set signals" );
3154 return -1;
3155 }
3156
3157 while( !s_stop )
3158 {
3159 if (s_proc_group_timer_cb != NULL) {
3160 s_proc_group_timer_cb(&s_ignore_pid);
3161 }
3162
3163 curTime = time( NULL );
3164 if (curTime != lastTime )
3165 {
3166 lastTime = curTime;
3167 if (lsapi_parent_dead())
3168 break;
3169 lsapi_check_child_status(curTime );
3170 if (pServer->m_iServerMaxIdle)
3171 {
3172 if ( pServer->m_iCurChildren <= 0 )
3173 {
3174 ++wait_secs;
3175 if ( wait_secs > pServer->m_iServerMaxIdle )
3176 return -1;
3177 }
3178 else
3179 wait_secs = 0;
3180 }
3181 }
3182
3183 #if defined(linux) || defined(__linux) || defined(__linux__) || defined(__gnu_linux__)
3184 *s_avail_pages = sysconf(_SC_AVPHYS_PAGES);
3185 #endif
3186 FD_ZERO( &readfds );
3187 FD_SET( pServer->m_fd, &readfds );
3188 timeout.tv_sec = 1;
3189 timeout.tv_usec = 0;
3190 ret = (*g_fnSelect)(pServer->m_fd+1, &readfds, NULL, NULL, &timeout);
3191 if (ret == 1 )
3192 {
3193 int accepting = 0;
3194 if (s_accepting_workers)
3195 accepting = __sync_add_and_fetch(s_accepting_workers, 0);
3196
3197 if (pServer->m_iCurChildren > 0 && accepting > 0)
3198 {
3199 usleep(400);
3200 while(accepting-- > 0)
3201 sched_yield();
3202 continue;
3203 }
3204 }
3205 else if ( ret == -1 )
3206 {
3207 if ( errno == EINTR )
3208 continue;
3209 /* perror( "select()" ); */
3210 break;
3211 }
3212 else
3213 {
3214 continue;
3215 }
3216
3217 if (pServer->m_iCurChildren >=
3218 pServer->m_iMaxChildren + pServer->m_iExtraChildren)
3219 {
3220 lsapi_log("Reached max children process limit: %d, extra: %d,"
3221 " current: %d, busy: %d, please increase LSAPI_CHILDREN.\n",
3222 pServer->m_iMaxChildren, pServer->m_iExtraChildren,
3223 pServer->m_iCurChildren,
3224 s_busy_workers ? *s_busy_workers : -1 );
3225 usleep( 100000 );
3226 continue;
3227 }
3228
3229 pReq->m_fd = lsapi_accept( pServer->m_fd );
3230 if ( pReq->m_fd != -1 )
3231 {
3232 wait_secs = 0;
3233 child_status = find_child_status( 0 );
3234
3235 sigemptyset( &mask );
3236 sigaddset( &mask, SIGCHLD );
3237
3238 if ( sigprocmask(SIG_BLOCK, &mask, &orig_mask) < 0 )
3239 {
3240 perror( "sigprocmask(SIG_BLOCK) to block SIGCHLD" );
3241 }
3242
3243 pid = fork();
3244
3245 if ( !pid )
3246 {
3247 setsid();
3248 if (sigprocmask(SIG_SETMASK, &orig_mask, NULL) < 0)
3249 perror( "sigprocmask( SIG_SETMASK ) to restore SIGMASK in child" );
3250 g_prefork_server = NULL;
3251 s_ppid = getppid();
3252 s_pid = getpid();
3253 s_req_processed = 0;
3254 s_proc_group_timer_cb = NULL;
3255 s_worker_status = child_status;
3256
3257 if (pthread_atfork_func)
3258 (*pthread_atfork_func)(NULL, NULL, set_skip_write);
3259
3260 __sync_lock_test_and_set(&s_worker_status->m_state,
3261 LSAPI_STATE_CONNECTED);
3262 if (s_busy_workers)
3263 __sync_add_and_fetch(s_busy_workers, 1);
3264 lsapi_set_nblock( pReq->m_fd, 0 );
3265 //keep it open if busy_count is used.
3266 if (s_busy_workers
3267 && *s_busy_workers > (pServer->m_iMaxChildren >> 1))
3268 s_keepListener = 1;
3269 if ((s_uid == 0 || !s_keepListener || !is_enough_free_mem())
3270 && pReq->m_fdListen != -1 )
3271 {
3272 close( pReq->m_fdListen );
3273 pReq->m_fdListen = -1;
3274 }
3275 /* don't catch our signals */
3276 sigaction( SIGCHLD, &old_child, 0 );
3277 sigaction( SIGTERM, &old_term, 0 );
3278 sigaction( SIGQUIT, &old_quit, 0 );
3279 sigaction( SIGINT, &old_int, 0 );
3280 sigaction( SIGUSR1, &old_usr1, 0 );
3281 //init_conn_key( pReq->m_fd );
3282 lsapi_notify_pid( pReq->m_fd );
3283 s_notified_pid = 1;
3284 //if ( s_accept_notify )
3285 // return notify_req_received( pReq->m_fd );
3286 return 0;
3287 }
3288 else if ( pid == -1 )
3289 {
3290 perror( "fork() failed, please increase process limit" );
3291 }
3292 else
3293 {
3294 ++pServer->m_iCurChildren;
3295 if ( child_status )
3296 {
3297 child_status->m_pid = pid;
3298 child_status->m_tmWaitBegin = curTime;
3299 child_status->m_tmStart = curTime;
3300 }
3301 }
3302 close( pReq->m_fd );
3303 pReq->m_fd = -1;
3304
3305 if (sigprocmask(SIG_SETMASK, &orig_mask, NULL) < 0)
3306 perror( "sigprocmask( SIG_SETMASK ) to restore SIGMASK" );
3307
3308 }
3309 else
3310 {
3311 if (( errno == EINTR )||( errno == EAGAIN))
3312 continue;
3313 perror( "accept() failed" );
3314 return -1;
3315 }
3316 }
3317 sigaction( SIGUSR1, &old_usr1, 0 );
3318 //kill( -getpgrp(), SIGUSR1 );
3319 //lsapi_all_children_must_die(); /* Sorry, children ;-) */
3320 return -1;
3321
3322 }
3323
3324
3325 static struct sigaction old_term, old_quit, old_int,
3326 old_usr1, old_child;
3327
3328
LSAPI_Postfork_Child(LSAPI_Request * pReq)3329 int LSAPI_Postfork_Child(LSAPI_Request * pReq)
3330 {
3331 int max_children = g_prefork_server->m_iMaxChildren;
3332 s_pid = getpid();
3333 __sync_lock_test_and_set(&pReq->child_status->m_pid, s_pid);
3334 s_worker_status = pReq->child_status;
3335
3336 setsid();
3337 g_prefork_server = NULL;
3338 s_ppid = getppid();
3339 s_req_processed = 0;
3340 s_proc_group_timer_cb = NULL;
3341
3342 if (pthread_atfork_func)
3343 (*pthread_atfork_func)(NULL, NULL, set_skip_write);
3344
3345 __sync_lock_test_and_set(&s_worker_status->m_state,
3346 LSAPI_STATE_CONNECTED);
3347 if (s_busy_workers)
3348 __sync_add_and_fetch(s_busy_workers, 1);
3349 lsapi_set_nblock( pReq->m_fd, 0 );
3350 //keep it open if busy_count is used.
3351 if (s_busy_workers
3352 && *s_busy_workers > (max_children >> 1))
3353 s_keepListener = 1;
3354 if ((s_uid == 0 || !s_keepListener || !is_enough_free_mem())
3355 && pReq->m_fdListen != -1 )
3356 {
3357 close(pReq->m_fdListen);
3358 pReq->m_fdListen = -1;
3359 }
3360
3361 //init_conn_key( pReq->m_fd );
3362 lsapi_notify_pid(pReq->m_fd);
3363 s_notified_pid = 1;
3364 //if ( s_accept_notify )
3365 // return notify_req_received( pReq->m_fd );
3366 return 0;
3367 }
3368
3369
LSAPI_Postfork_Parent(LSAPI_Request * pReq)3370 int LSAPI_Postfork_Parent(LSAPI_Request * pReq)
3371 {
3372 ++g_prefork_server->m_iCurChildren;
3373 if (pReq->child_status)
3374 {
3375 time_t curTime = time( NULL );
3376 pReq->child_status->m_tmWaitBegin = curTime;
3377 pReq->child_status->m_tmStart = curTime;
3378 }
3379 close(pReq->m_fd);
3380 pReq->m_fd = -1;
3381 return 0;
3382 }
3383
3384
LSAPI_Accept_Before_Fork(LSAPI_Request * pReq)3385 int LSAPI_Accept_Before_Fork(LSAPI_Request * pReq)
3386 {
3387 time_t lastTime = 0;
3388 time_t curTime = 0;
3389 fd_set readfds;
3390 struct timeval timeout;
3391 int wait_secs = 0;
3392 int ret = 0;
3393
3394 lsapi_prefork_server * pServer = g_prefork_server;
3395
3396 struct sigaction act;
3397
3398 lsapi_init_children_status();
3399
3400 act.sa_flags = 0;
3401 act.sa_handler = lsapi_sigchild;
3402 sigemptyset(&(act.sa_mask));
3403 if (sigaction(SIGCHLD, &act, &old_child))
3404 {
3405 perror( "Can't set signal handler for SIGCHILD" );
3406 return -1;
3407 }
3408
3409 /* Set up handler to kill children upon exit */
3410 act.sa_flags = 0;
3411 act.sa_handler = lsapi_cleanup;
3412 sigemptyset(&(act.sa_mask));
3413 if (sigaction(SIGTERM, &act, &old_term) ||
3414 sigaction(SIGINT, &act, &old_int ) ||
3415 sigaction(SIGUSR1, &act, &old_usr1) ||
3416 sigaction(SIGQUIT, &act, &old_quit))
3417 {
3418 perror( "Can't set signals" );
3419 return -1;
3420 }
3421 s_stop = 0;
3422 pReq->m_reqState = 0;
3423
3424 while(!s_stop)
3425 {
3426 if (s_proc_group_timer_cb != NULL) {
3427 s_proc_group_timer_cb(&s_ignore_pid);
3428 }
3429
3430 curTime = time(NULL);
3431 if (curTime != lastTime)
3432 {
3433 lastTime = curTime;
3434 if (lsapi_parent_dead())
3435 break;
3436 lsapi_check_child_status(curTime);
3437 if (pServer->m_iServerMaxIdle)
3438 {
3439 if (pServer->m_iCurChildren <= 0)
3440 {
3441 ++wait_secs;
3442 if ( wait_secs > pServer->m_iServerMaxIdle )
3443 return -1;
3444 }
3445 else
3446 wait_secs = 0;
3447 }
3448 }
3449
3450 #if defined(linux) || defined(__linux) || defined(__linux__) || defined(__gnu_linux__)
3451 *s_avail_pages = sysconf(_SC_AVPHYS_PAGES);
3452 // lsapi_log("Memory total: %zd, free: %zd, free %%%zd\n",
3453 // s_total_pages, *s_avail_pages, *s_avail_pages * 100 / s_total_pages);
3454
3455 #endif
3456 FD_ZERO(&readfds);
3457 FD_SET(pServer->m_fd, &readfds);
3458 timeout.tv_sec = 1;
3459 timeout.tv_usec = 0;
3460 ret = (*g_fnSelect)(pServer->m_fd+1, &readfds, NULL, NULL, &timeout);
3461 if (ret == 1 )
3462 {
3463 int accepting = 0;
3464 if (s_accepting_workers)
3465 accepting = __sync_add_and_fetch(s_accepting_workers, 0);
3466
3467 if (pServer->m_iCurChildren > 0
3468 && accepting > 0)
3469 {
3470 usleep( 400);
3471 while(accepting-- > 0)
3472 sched_yield();
3473 continue;
3474 }
3475 }
3476 else if (ret == -1)
3477 {
3478 if (errno == EINTR)
3479 continue;
3480 /* perror( "select()" ); */
3481 break;
3482 }
3483 else
3484 {
3485 continue;
3486 }
3487
3488 if (pServer->m_iCurChildren >=
3489 pServer->m_iMaxChildren + pServer->m_iExtraChildren)
3490 {
3491 lsapi_log("Reached max children process limit: %d, extra: %d,"
3492 " current: %d, busy: %d, please increase LSAPI_CHILDREN.\n",
3493 pServer->m_iMaxChildren, pServer->m_iExtraChildren,
3494 pServer->m_iCurChildren,
3495 s_busy_workers ? *s_busy_workers : -1);
3496 usleep(100000);
3497 continue;
3498 }
3499
3500 pReq->m_fd = lsapi_accept(pServer->m_fd);
3501 if (pReq->m_fd != -1)
3502 {
3503 wait_secs = 0;
3504 pReq->child_status = find_child_status(0);
3505
3506 ret = 0;
3507 break;
3508 }
3509 else
3510 {
3511 if ((errno == EINTR) || (errno == EAGAIN))
3512 continue;
3513 perror( "accept() failed" );
3514 ret = -1;
3515 break;
3516 }
3517 }
3518
3519 sigaction(SIGCHLD, &old_child, 0);
3520 sigaction(SIGTERM, &old_term, 0);
3521 sigaction(SIGQUIT, &old_quit, 0);
3522 sigaction(SIGINT, &old_int, 0);
3523 sigaction(SIGUSR1, &old_usr1, 0);
3524
3525 return ret;
3526 }
3527
3528
lsapi_perror(const char * pMessage,int err_no)3529 void lsapi_perror( const char * pMessage, int err_no )
3530 {
3531 lsapi_log("%s, errno: %d (%s)\n", pMessage, err_no,
3532 strerror( err_no ) );
3533 }
3534
3535
LSAPI_Prefork_Accept_r(LSAPI_Request * pReq)3536 int LSAPI_Prefork_Accept_r( LSAPI_Request * pReq )
3537 {
3538 int fd;
3539 int ret;
3540 int wait_secs;
3541 fd_set readfds;
3542 struct timeval timeout;
3543
3544 if (s_skip_write)
3545 return -1;
3546
3547 LSAPI_Finish_r( pReq );
3548
3549 if ( g_prefork_server )
3550 {
3551 if ( g_prefork_server->m_fd != -1 )
3552 if ( lsapi_prefork_server_accept( g_prefork_server, pReq ) == -1 )
3553 return -1;
3554 }
3555 else if (s_req_processed > 0 && s_max_busy_workers > 0 && s_busy_workers)
3556 {
3557 ret = __sync_fetch_and_add(s_busy_workers, 0);
3558 if (ret >= s_max_busy_workers)
3559 {
3560 send_conn_close_notification(pReq->m_fd);
3561 lsapi_close_connection(pReq);
3562 }
3563 }
3564
3565 if ( (unsigned int)s_req_processed > s_max_reqs )
3566 return -1;
3567
3568 if ( s_worker_status )
3569 {
3570 s_worker_status->m_tmWaitBegin = time( NULL );
3571 }
3572
3573
3574 while( g_running )
3575 {
3576 if ( pReq->m_fd != -1 )
3577 {
3578 fd = pReq->m_fd;
3579 }
3580 else if ( pReq->m_fdListen != -1 )
3581 fd = pReq->m_fdListen;
3582 else
3583 {
3584 break;
3585 }
3586 wait_secs = 0;
3587 while( 1 )
3588 {
3589 if ( !g_running )
3590 return -1;
3591 if (s_req_processed && s_worker_status
3592 && s_worker_status->m_iKillSent)
3593 return -1;
3594 FD_ZERO( &readfds );
3595 FD_SET( fd, &readfds );
3596 timeout.tv_sec = 1;
3597 timeout.tv_usec = 0;
3598 if (fd == pReq->m_fdListen)
3599 {
3600 if (s_worker_status)
3601 __sync_lock_test_and_set(&s_worker_status->m_state,
3602 LSAPI_STATE_ACCEPTING);
3603 if (s_accepting_workers)
3604 __sync_fetch_and_add(s_accepting_workers, 1);
3605 }
3606 ret = (*g_fnSelect)(fd+1, &readfds, NULL, NULL, &timeout);
3607 if (fd == pReq->m_fdListen)
3608 {
3609 if (s_accepting_workers)
3610 __sync_fetch_and_sub(s_accepting_workers, 1);
3611 if (s_worker_status)
3612 __sync_lock_test_and_set(&s_worker_status->m_state,
3613 LSAPI_STATE_IDLE);
3614 }
3615
3616 if ( ret == 0 )
3617 {
3618 if ( s_worker_status )
3619 {
3620 s_worker_status->m_inProcess = 0;
3621 if (fd == pReq->m_fdListen
3622 && (s_keepListener != 2 || !is_enough_free_mem()))
3623 return -1;
3624 }
3625 ++wait_secs;
3626 if (( s_max_idle_secs > 0 )&&(wait_secs >= s_max_idle_secs ))
3627 return -1;
3628 if ( lsapi_parent_dead() )
3629 return -1;
3630 }
3631 else if ( ret == -1 )
3632 {
3633 if ( errno == EINTR )
3634 continue;
3635 else
3636 return -1;
3637 }
3638 else if ( ret >= 1 )
3639 {
3640 if (s_req_processed && s_worker_status
3641 && s_worker_status->m_iKillSent)
3642 return -1;
3643 if ( fd == pReq->m_fdListen )
3644 {
3645 pReq->m_fd = lsapi_accept( pReq->m_fdListen );
3646 if ( pReq->m_fd != -1 )
3647 {
3648 if (s_worker_status)
3649 __sync_lock_test_and_set(&s_worker_status->m_state,
3650 LSAPI_STATE_CONNECTED);
3651 if (s_busy_workers)
3652 __sync_fetch_and_add(s_busy_workers, 1);
3653
3654 fd = pReq->m_fd;
3655
3656 lsapi_set_nblock( fd, 0 );
3657 //init_conn_key( pReq->m_fd );
3658 if (!s_keepListener)
3659 {
3660 close( pReq->m_fdListen );
3661 pReq->m_fdListen = -1;
3662 }
3663 if ( s_accept_notify )
3664 if ( notify_req_received( pReq->m_fd ) == -1 )
3665 return -1;
3666 }
3667 else
3668 {
3669 if (( errno == EINTR )||( errno == EAGAIN))
3670 continue;
3671 lsapi_perror( "lsapi_accept() error", errno );
3672 return -1;
3673 }
3674 }
3675 else
3676 break;
3677 }
3678 }
3679
3680 if ( !readReq( pReq ) )
3681 {
3682 if ( s_worker_status )
3683 {
3684 s_worker_status->m_iKillSent = 0;
3685 s_worker_status->m_inProcess = 1;
3686 ++s_worker_status->m_iReqCounter;
3687 s_worker_status->m_tmReqBegin =
3688 s_worker_status->m_tmLastCheckPoint = time(NULL);
3689 }
3690 ++s_req_processed;
3691 return 0;
3692 }
3693 lsapi_close_connection(pReq);
3694 LSAPI_Reset_r( pReq );
3695 }
3696 return -1;
3697
3698 }
3699
3700
LSAPI_Set_Max_Reqs(int reqs)3701 void LSAPI_Set_Max_Reqs( int reqs )
3702 { s_max_reqs = reqs - 1; }
3703
LSAPI_Set_Max_Idle(int secs)3704 void LSAPI_Set_Max_Idle( int secs )
3705 { s_max_idle_secs = secs; }
3706
3707
LSAPI_Set_Max_Children(int maxChildren)3708 void LSAPI_Set_Max_Children( int maxChildren )
3709 {
3710 if ( g_prefork_server )
3711 g_prefork_server->m_iMaxChildren = maxChildren;
3712 }
3713
3714
LSAPI_Set_Extra_Children(int extraChildren)3715 void LSAPI_Set_Extra_Children( int extraChildren )
3716 {
3717 if (( g_prefork_server )&&( extraChildren >= 0 ))
3718 g_prefork_server->m_iExtraChildren = extraChildren;
3719 }
3720
3721
LSAPI_Set_Max_Process_Time(int secs)3722 void LSAPI_Set_Max_Process_Time( int secs )
3723 {
3724 if (( g_prefork_server )&&( secs > 0 ))
3725 g_prefork_server->m_iMaxReqProcessTime = secs;
3726 }
3727
3728
LSAPI_Set_Max_Idle_Children(int maxIdleChld)3729 void LSAPI_Set_Max_Idle_Children( int maxIdleChld )
3730 {
3731 if (( g_prefork_server )&&( maxIdleChld > 0 ))
3732 g_prefork_server->m_iMaxIdleChildren = maxIdleChld;
3733 }
3734
3735
LSAPI_Set_Server_Max_Idle_Secs(int serverMaxIdle)3736 void LSAPI_Set_Server_Max_Idle_Secs( int serverMaxIdle )
3737 {
3738 if ( g_prefork_server )
3739 g_prefork_server->m_iServerMaxIdle = serverMaxIdle;
3740 }
3741
3742
LSAPI_Set_Slow_Req_Msecs(int msecs)3743 void LSAPI_Set_Slow_Req_Msecs( int msecs )
3744 {
3745 s_slow_req_msecs = msecs;
3746 }
3747
3748
LSAPI_Get_Slow_Req_Msecs(void)3749 int LSAPI_Get_Slow_Req_Msecs(void)
3750 {
3751 return s_slow_req_msecs;
3752 }
3753
3754
LSAPI_No_Check_ppid(void)3755 void LSAPI_No_Check_ppid(void)
3756 {
3757 s_ppid = 0;
3758 }
3759
3760
LSAPI_Get_ppid()3761 int LSAPI_Get_ppid()
3762 {
3763 return(s_ppid);
3764 }
3765
3766
3767 #if defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__)
3768 #include <crt_externs.h>
3769 #else
3770 extern char ** environ;
3771 #endif
unset_lsapi_envs(void)3772 static void unset_lsapi_envs(void)
3773 {
3774 char **env;
3775 #if defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__)
3776 env = *_NSGetEnviron();
3777 #else
3778 env = environ;
3779 #endif
3780 while( env != NULL && *env != NULL )
3781 {
3782 if (!strncmp(*env, "LSAPI_", 6) || !strncmp( *env, "PHP_LSAPI_", 10 )
3783 || (!strncmp( *env, "PHPRC=", 6 )&&(!s_uid)))
3784 {
3785 char ** del = env;
3786 do
3787 *del = del[1];
3788 while( *del++ );
3789 }
3790 else
3791 ++env;
3792 }
3793 }
3794
3795
lsapi_initSuEXEC(void)3796 static int lsapi_initSuEXEC(void)
3797 {
3798 int i;
3799 struct passwd * pw;
3800 s_defaultUid = 0;
3801 s_defaultGid = 0;
3802 if ( s_uid == 0 )
3803 {
3804 const char * p = getenv( "LSAPI_DEFAULT_UID" );
3805 if ( p )
3806 {
3807 i = atoi( p );
3808 if ( i > 0 )
3809 s_defaultUid = i;
3810 }
3811 p = getenv( "LSAPI_DEFAULT_GID" );
3812 if ( p )
3813 {
3814 i = atoi( p );
3815 if ( i > 0 )
3816 s_defaultGid = i;
3817 }
3818 p = getenv( "LSAPI_SECRET" );
3819 if (( !p )||( readSecret(p) == -1 ))
3820 return -1;
3821 if ( g_prefork_server )
3822 {
3823 if ( g_prefork_server->m_iMaxChildren < 100 )
3824 g_prefork_server->m_iMaxChildren = 100;
3825 if ( g_prefork_server->m_iExtraChildren < 1000 )
3826 g_prefork_server->m_iExtraChildren = 1000;
3827 }
3828 }
3829 if ( !s_defaultUid || !s_defaultGid )
3830 {
3831 pw = getpwnam( "nobody" );
3832 if ( pw )
3833 {
3834 if ( !s_defaultUid )
3835 s_defaultUid = pw->pw_uid;
3836 if ( !s_defaultGid )
3837 s_defaultGid = pw->pw_gid;
3838 }
3839 else
3840 {
3841 if ( !s_defaultUid )
3842 s_defaultUid = 10000;
3843 if ( !s_defaultGid )
3844 s_defaultGid = 10000;
3845 }
3846 }
3847 return 0;
3848 }
3849
3850
lsapi_check_path(const char * p,char * final,int max_len)3851 static int lsapi_check_path(const char *p, char *final, int max_len)
3852 {
3853 char resolved_path[PATH_MAX+1];
3854 int len = 0;
3855 char *end;
3856 if (*p != '/')
3857 {
3858 if (getcwd(final, max_len) == NULL)
3859 return -1;
3860 len = strlen(final);
3861 *(final + len) = '/';
3862 ++len;
3863 }
3864 end = memccpy(&final[len], p, '\0', PATH_MAX - len);
3865 if (!end)
3866 {
3867 errno = EINVAL;
3868 return -1;
3869 }
3870 p = final;
3871 if (realpath(p, resolved_path) == NULL
3872 && errno != ENOENT && errno != EACCES)
3873 return -1;
3874 if (strncmp(resolved_path, "/etc/", 5) == 0)
3875 {
3876 errno = EPERM;
3877 return -1;
3878 }
3879 return 0;
3880 }
3881
3882
lsapi_reopen_stderr2(const char * full_path)3883 static int lsapi_reopen_stderr2(const char *full_path)
3884 {
3885 int newfd = open(full_path, O_WRONLY | O_CREAT | O_APPEND, 0644);
3886 if (newfd == -1)
3887 {
3888 LSAPI_perror_r(NULL, "Failed to open custom stderr log", full_path);
3889 return -1;
3890 }
3891 if (newfd != 2)
3892 {
3893 dup2(newfd, 2);
3894 close(newfd);
3895 dup2(2, 1);
3896 }
3897 if (s_stderr_log_path && full_path != s_stderr_log_path)
3898 {
3899 free(s_stderr_log_path);
3900 s_stderr_log_path = NULL;
3901 }
3902 s_stderr_log_path = strdup(full_path);
3903 return 0;
3904 }
3905
3906
lsapi_reopen_stderr(const char * p)3907 static int lsapi_reopen_stderr(const char *p)
3908 {
3909 char full_path[PATH_MAX];
3910 if (s_uid == 0)
3911 return -1;
3912 if (lsapi_check_path(p, full_path, PATH_MAX) == -1)
3913 {
3914 LSAPI_perror_r(NULL, "Invalid custom stderr log path", p);
3915 return -1;
3916 }
3917 return lsapi_reopen_stderr2(full_path);
3918 }
3919
3920
LSAPI_Init_Env_Parameters(fn_select_t fp)3921 int LSAPI_Init_Env_Parameters( fn_select_t fp )
3922 {
3923 const char *p;
3924 char ch;
3925 int n;
3926 int avoidFork = 0;
3927
3928 p = getenv("LSAPI_STDERR_LOG");
3929 if (p)
3930 {
3931 lsapi_reopen_stderr(p);
3932 }
3933 if (!s_stderr_log_path)
3934 s_stderr_is_pipe = isPipe(STDERR_FILENO);
3935
3936 p = getenv( "PHP_LSAPI_MAX_REQUESTS" );
3937 if ( !p )
3938 p = getenv( "LSAPI_MAX_REQS" );
3939 if ( p )
3940 {
3941 n = atoi( p );
3942 if ( n > 0 )
3943 LSAPI_Set_Max_Reqs( n );
3944 }
3945
3946 p = getenv( "LSAPI_KEEP_LISTEN" );
3947 if ( p )
3948 {
3949 n = atoi( p );
3950 s_keepListener = n;
3951 }
3952
3953 p = getenv( "LSAPI_AVOID_FORK" );
3954 if ( p )
3955 {
3956 avoidFork = atoi( p );
3957 if (avoidFork)
3958 {
3959 s_keepListener = 2;
3960 ch = *(p + strlen(p) - 1);
3961 if ( ch == 'G' || ch == 'g' )
3962 avoidFork *= 1024 * 1024 * 1024;
3963 else if ( ch == 'M' || ch == 'm' )
3964 avoidFork *= 1024 * 1024;
3965 if (avoidFork >= 1024 * 10240)
3966 s_min_avail_pages = avoidFork / 4096;
3967 }
3968 }
3969
3970 p = getenv( "LSAPI_ACCEPT_NOTIFY" );
3971 if ( p )
3972 {
3973 s_accept_notify = atoi( p );
3974 }
3975
3976 p = getenv( "LSAPI_SLOW_REQ_MSECS" );
3977 if ( p )
3978 {
3979 n = atoi( p );
3980 LSAPI_Set_Slow_Req_Msecs( n );
3981 }
3982
3983 #if defined( RLIMIT_CORE )
3984 p = getenv( "LSAPI_ALLOW_CORE_DUMP" );
3985 if ( !p )
3986 {
3987 struct rlimit limit = { 0, 0 };
3988 setrlimit( RLIMIT_CORE, &limit );
3989 }
3990 else
3991 s_enable_core_dump = 1;
3992
3993 #endif
3994
3995 p = getenv( "LSAPI_MAX_IDLE" );
3996 if ( p )
3997 {
3998 n = atoi( p );
3999 LSAPI_Set_Max_Idle( n );
4000 }
4001
4002 if ( LSAPI_Is_Listen() )
4003 {
4004 n = 0;
4005 p = getenv( "PHP_LSAPI_CHILDREN" );
4006 if ( !p )
4007 p = getenv( "LSAPI_CHILDREN" );
4008 if ( p )
4009 n = atoi( p );
4010 if ( n > 1 )
4011 {
4012 LSAPI_Init_Prefork_Server( n, fp, avoidFork != 0 );
4013 LSAPI_Set_Server_fd( g_req.m_fdListen );
4014 }
4015
4016 p = getenv( "LSAPI_EXTRA_CHILDREN" );
4017 if ( p )
4018 LSAPI_Set_Extra_Children( atoi( p ) );
4019
4020 p = getenv( "LSAPI_MAX_IDLE_CHILDREN" );
4021 if ( p )
4022 LSAPI_Set_Max_Idle_Children( atoi( p ) );
4023
4024 p = getenv( "LSAPI_PGRP_MAX_IDLE" );
4025 if ( p )
4026 {
4027 LSAPI_Set_Server_Max_Idle_Secs( atoi( p ) );
4028 }
4029
4030 p = getenv( "LSAPI_MAX_PROCESS_TIME" );
4031 if ( p )
4032 LSAPI_Set_Max_Process_Time( atoi( p ) );
4033
4034 if ( getenv( "LSAPI_PPID_NO_CHECK" ) )
4035 {
4036 LSAPI_No_Check_ppid();
4037 }
4038
4039 p = getenv("LSAPI_MAX_BUSY_WORKER");
4040 if (p)
4041 {
4042 n = atoi(p);
4043 s_max_busy_workers = n;
4044 if (n >= 0)
4045 LSAPI_No_Check_ppid();
4046 }
4047
4048
4049 p = getenv( "LSAPI_DUMP_DEBUG_INFO" );
4050 if ( p )
4051 s_dump_debug_info = atoi( p );
4052
4053 if ( lsapi_initSuEXEC() == -1 )
4054 return -1;
4055 #if defined(linux) || defined(__linux) || defined(__linux__) || defined(__gnu_linux__)
4056 lsapi_initLVE();
4057 #endif
4058 }
4059 unset_lsapi_envs();
4060 return 0;
4061 }
4062
4063
LSAPI_ErrResponse_r(LSAPI_Request * pReq,int code,const char ** pRespHeaders,const char * pBody,int bodyLen)4064 int LSAPI_ErrResponse_r( LSAPI_Request * pReq, int code, const char ** pRespHeaders,
4065 const char * pBody, int bodyLen )
4066 {
4067 LSAPI_SetRespStatus_r( pReq, code );
4068 if ( pRespHeaders )
4069 {
4070 while( *pRespHeaders )
4071 {
4072 LSAPI_AppendRespHeader_r( pReq, *pRespHeaders, strlen( *pRespHeaders ) );
4073 ++pRespHeaders;
4074 }
4075 }
4076 if ( pBody &&( bodyLen > 0 ))
4077 {
4078 LSAPI_Write_r( pReq, pBody, bodyLen );
4079 }
4080 LSAPI_Finish_r( pReq );
4081 return 0;
4082 }
4083
4084
4085 static void lsapi_MD5Transform(uint32 buf[4], uint32 const in[16]);
4086
4087 /*
4088 * Note: this code is harmless on little-endian machines.
4089 */
byteReverse(unsigned char * buf,unsigned longs)4090 static void byteReverse(unsigned char *buf, unsigned longs)
4091 {
4092 uint32 t;
4093 do {
4094 t = (uint32) ((unsigned) buf[3] << 8 | buf[2]) << 16 |
4095 ((unsigned) buf[1] << 8 | buf[0]);
4096 *(uint32 *) buf = t;
4097 buf += 4;
4098 } while (--longs);
4099 }
4100
4101
4102 /*
4103 * Start MD5 accumulation. Set bit count to 0 and buffer to mysterious
4104 * initialization constants.
4105 */
lsapi_MD5Init(struct lsapi_MD5Context * ctx)4106 void lsapi_MD5Init(struct lsapi_MD5Context *ctx)
4107 {
4108 ctx->buf[0] = 0x67452301;
4109 ctx->buf[1] = 0xefcdab89;
4110 ctx->buf[2] = 0x98badcfe;
4111 ctx->buf[3] = 0x10325476;
4112
4113 ctx->bits[0] = 0;
4114 ctx->bits[1] = 0;
4115 }
4116
4117 /*
4118 * Update context to reflect the concatenation of another buffer full
4119 * of bytes.
4120 */
lsapi_MD5Update(struct lsapi_MD5Context * ctx,unsigned char const * buf,unsigned len)4121 void lsapi_MD5Update(struct lsapi_MD5Context *ctx, unsigned char const *buf, unsigned len)
4122 {
4123 register uint32 t;
4124
4125 /* Update bitcount */
4126
4127 t = ctx->bits[0];
4128 if ((ctx->bits[0] = t + ((uint32) len << 3)) < t)
4129 ctx->bits[1]++; /* Carry from low to high */
4130 ctx->bits[1] += len >> 29;
4131
4132 t = (t >> 3) & 0x3f; /* Bytes already in shsInfo->data */
4133
4134 /* Handle any leading odd-sized chunks */
4135
4136 if (t) {
4137 unsigned char *p = (unsigned char *) ctx->in + t;
4138
4139 t = 64 - t;
4140 if (len < t) {
4141 memmove(p, buf, len);
4142 return;
4143 }
4144 memmove(p, buf, t);
4145 byteReverse(ctx->in, 16);
4146 lsapi_MD5Transform(ctx->buf, (uint32 *) ctx->in);
4147 buf += t;
4148 len -= t;
4149 }
4150 /* Process data in 64-byte chunks */
4151
4152 while (len >= 64) {
4153 memmove(ctx->in, buf, 64);
4154 byteReverse(ctx->in, 16);
4155 lsapi_MD5Transform(ctx->buf, (uint32 *) ctx->in);
4156 buf += 64;
4157 len -= 64;
4158 }
4159
4160 /* Handle any remaining bytes of data. */
4161
4162 memmove(ctx->in, buf, len);
4163 }
4164
4165
4166 /*
4167 * Final wrapup - pad to 64-byte boundary with the bit pattern
4168 * 1 0* (64-bit count of bits processed, MSB-first)
4169 */
lsapi_MD5Final(unsigned char digest[16],struct lsapi_MD5Context * ctx)4170 void lsapi_MD5Final(unsigned char digest[16], struct lsapi_MD5Context *ctx)
4171 {
4172 unsigned int count;
4173 unsigned char *p;
4174
4175 /* Compute number of bytes mod 64 */
4176 count = (ctx->bits[0] >> 3) & 0x3F;
4177
4178 /* Set the first char of padding to 0x80. This is safe since there is
4179 always at least one byte free */
4180 p = ctx->in + count;
4181 *p++ = 0x80;
4182
4183 /* Bytes of padding needed to make 64 bytes */
4184 count = 64 - 1 - count;
4185
4186 /* Pad out to 56 mod 64 */
4187 if (count < 8) {
4188 /* Two lots of padding: Pad the first block to 64 bytes */
4189 memset(p, 0, count);
4190 byteReverse(ctx->in, 16);
4191 lsapi_MD5Transform(ctx->buf, (uint32 *) ctx->in);
4192
4193 /* Now fill the next block with 56 bytes */
4194 memset(ctx->in, 0, 56);
4195 } else {
4196 /* Pad block to 56 bytes */
4197 memset(p, 0, count - 8);
4198 }
4199 byteReverse(ctx->in, 14);
4200
4201 /* Append length in bits and transform */
4202 ((uint32 *) ctx->in)[14] = ctx->bits[0];
4203 ((uint32 *) ctx->in)[15] = ctx->bits[1];
4204
4205 lsapi_MD5Transform(ctx->buf, (uint32 *) ctx->in);
4206 byteReverse((unsigned char *) ctx->buf, 4);
4207 memmove(digest, ctx->buf, 16);
4208 memset(ctx, 0, sizeof(*ctx)); /* In case it's sensitive */
4209 }
4210
4211
4212 /* The four core functions - F1 is optimized somewhat */
4213
4214 /* #define F1(x, y, z) (x & y | ~x & z) */
4215 #define F1(x, y, z) (z ^ (x & (y ^ z)))
4216 #define F2(x, y, z) F1(z, x, y)
4217 #define F3(x, y, z) (x ^ y ^ z)
4218 #define F4(x, y, z) (y ^ (x | ~z))
4219
4220 /* This is the central step in the MD5 algorithm. */
4221 #define MD5STEP(f, w, x, y, z, data, s) \
4222 ( w += f(x, y, z) + data, w = w<<s | w>>(32-s), w += x )
4223
4224 /*
4225 * The core of the MD5 algorithm, this alters an existing MD5 hash to
4226 * reflect the addition of 16 longwords of new data. MD5Update blocks
4227 * the data and converts bytes into longwords for this routine.
4228 */
lsapi_MD5Transform(uint32 buf[4],uint32 const in[16])4229 static void lsapi_MD5Transform(uint32 buf[4], uint32 const in[16])
4230 {
4231 register uint32 a, b, c, d;
4232
4233 a = buf[0];
4234 b = buf[1];
4235 c = buf[2];
4236 d = buf[3];
4237
4238 MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7);
4239 MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12);
4240 MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17);
4241 MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22);
4242 MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7);
4243 MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12);
4244 MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17);
4245 MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22);
4246 MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7);
4247 MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12);
4248 MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17);
4249 MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22);
4250 MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7);
4251 MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12);
4252 MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17);
4253 MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22);
4254
4255 MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5);
4256 MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9);
4257 MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14);
4258 MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20);
4259 MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5);
4260 MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9);
4261 MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14);
4262 MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20);
4263 MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5);
4264 MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9);
4265 MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14);
4266 MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20);
4267 MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5);
4268 MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9);
4269 MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14);
4270 MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20);
4271
4272 MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4);
4273 MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11);
4274 MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16);
4275 MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23);
4276 MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4);
4277 MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11);
4278 MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16);
4279 MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23);
4280 MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4);
4281 MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11);
4282 MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16);
4283 MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23);
4284 MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4);
4285 MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11);
4286 MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16);
4287 MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23);
4288
4289 MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6);
4290 MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10);
4291 MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15);
4292 MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21);
4293 MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6);
4294 MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10);
4295 MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15);
4296 MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21);
4297 MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6);
4298 MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10);
4299 MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15);
4300 MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21);
4301 MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6);
4302 MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10);
4303 MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15);
4304 MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21);
4305
4306 buf[0] += a;
4307 buf[1] += b;
4308 buf[2] += c;
4309 buf[3] += d;
4310 }
4311
4312
LSAPI_Set_Restored_Parent_Pid(int pid)4313 int LSAPI_Set_Restored_Parent_Pid(int pid)
4314 {
4315 int old_ppid = s_ppid;
4316 s_restored_ppid = pid;
4317 return old_ppid;
4318 }
4319
4320
LSAPI_Inc_Req_Processed(int cnt)4321 int LSAPI_Inc_Req_Processed(int cnt)
4322 {
4323 return __sync_add_and_fetch(s_global_counter, cnt);
4324 }
4325