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