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