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 #ifdef HAVE_INET_PTON
2692 if (!inet_pton(AF_INET, p, &((struct sockaddr_in *)pAddr)->sin_addr))
2693 #else
2694 ((struct sockaddr_in *)pAddr)->sin_addr.s_addr = inet_addr( p );
2695 if ( ((struct sockaddr_in *)pAddr)->sin_addr.s_addr == INADDR_BROADCAST)
2696 #endif
2697 {
2698 doAddrInfo = 1;
2699 }
2700 }
2701 break;
2702 }
2703 if ( *pEnd == ':' )
2704 ++pEnd;
2705
2706 port = atoi( pEnd );
2707 if (( port <= 0 )||( port > 65535 ))
2708 return -1;
2709 if ( doAddrInfo )
2710 {
2711
2712 memset(&hints, 0, sizeof(hints));
2713
2714 hints.ai_family = pAddr->sa_family;
2715 hints.ai_socktype = SOCK_STREAM;
2716 hints.ai_protocol = IPPROTO_TCP;
2717
2718 if ( getaddrinfo(p, NULL, &hints, &res) )
2719 {
2720 return -1;
2721 }
2722
2723 memcpy(pAddr, res->ai_addr, res->ai_addrlen);
2724 freeaddrinfo(res);
2725 }
2726
2727 if ( pAddr->sa_family == AF_INET )
2728 ((struct sockaddr_in *)pAddr)->sin_port = htons( port );
2729 else
2730 ((struct sockaddr_in6 *)pAddr)->sin6_port = htons( port );
2731 return 0;
2732
2733 }
2734
2735
LSAPI_CreateListenSock(const char * pBind,int backlog)2736 int LSAPI_CreateListenSock( const char * pBind, int backlog )
2737 {
2738 char serverAddr[128];
2739 int ret;
2740 int fd = -1;
2741 ret = LSAPI_ParseSockAddr( pBind, (struct sockaddr *)serverAddr );
2742 if ( !ret )
2743 {
2744 fd = LSAPI_CreateListenSock2( (struct sockaddr *)serverAddr, backlog );
2745 }
2746 return fd;
2747 }
2748
2749
2750 static fn_select_t g_fnSelect = select;
2751 typedef struct _lsapi_prefork_server
2752 {
2753 int m_fd;
2754 int m_iMaxChildren;
2755 int m_iExtraChildren;
2756 int m_iCurChildren;
2757 int m_iMaxIdleChildren;
2758 int m_iServerMaxIdle;
2759 int m_iChildrenMaxIdleTime;
2760 int m_iMaxReqProcessTime;
2761 int m_iAvoidFork;
2762
2763 lsapi_child_status * m_pChildrenStatus;
2764 lsapi_child_status * m_pChildrenStatusCur;
2765 lsapi_child_status * m_pChildrenStatusEnd;
2766
2767 }lsapi_prefork_server;
2768 static lsapi_prefork_server * g_prefork_server = NULL;
2769
2770
LSAPI_Init_Prefork_Server(int max_children,fn_select_t fp,int avoidFork)2771 int LSAPI_Init_Prefork_Server( int max_children, fn_select_t fp, int avoidFork )
2772 {
2773 if ( g_prefork_server )
2774 return 0;
2775 if ( max_children <= 1 )
2776 return -1;
2777 if ( max_children >= 10000)
2778 max_children = 10000;
2779
2780 if (s_max_busy_workers == 0)
2781 s_max_busy_workers = max_children / 2 + 1;
2782
2783 g_prefork_server = (lsapi_prefork_server *)malloc( sizeof( lsapi_prefork_server ) );
2784 if ( !g_prefork_server )
2785 return -1;
2786 memset( g_prefork_server, 0, sizeof( lsapi_prefork_server ) );
2787
2788 if ( fp != NULL )
2789 g_fnSelect = fp;
2790
2791 s_ppid = getppid();
2792 s_pid = getpid();
2793 setpgid( s_pid, s_pid );
2794 #if defined(linux) || defined(__linux) || defined(__linux__) || defined(__gnu_linux__)
2795 s_total_pages = sysconf(_SC_PHYS_PAGES);
2796 #endif
2797 g_prefork_server->m_iAvoidFork = avoidFork;
2798 g_prefork_server->m_iMaxChildren = max_children;
2799
2800 g_prefork_server->m_iExtraChildren = ( avoidFork ) ? 0 : (max_children / 3) ;
2801 g_prefork_server->m_iMaxIdleChildren = ( avoidFork ) ? (max_children + 1) : (max_children / 3);
2802 if ( g_prefork_server->m_iMaxIdleChildren == 0 )
2803 g_prefork_server->m_iMaxIdleChildren = 1;
2804 g_prefork_server->m_iChildrenMaxIdleTime = 300;
2805 g_prefork_server->m_iMaxReqProcessTime = 3600;
2806
2807 setsid();
2808
2809 return 0;
2810 }
2811
2812
LSAPI_Set_Server_fd(int fd)2813 void LSAPI_Set_Server_fd( int fd )
2814 {
2815 if( g_prefork_server )
2816 g_prefork_server->m_fd = fd;
2817 }
2818
2819
lsapi_accept(int fdListen)2820 static int lsapi_accept( int fdListen )
2821 {
2822 int fd;
2823 int nodelay = 1;
2824 socklen_t len;
2825 char achPeer[128];
2826
2827 len = sizeof( achPeer );
2828 fd = accept( fdListen, (struct sockaddr *)&achPeer, &len );
2829 if ( fd != -1 )
2830 {
2831 if (((struct sockaddr *)&achPeer)->sa_family == AF_INET )
2832 {
2833 setsockopt( fd, IPPROTO_TCP, TCP_NODELAY,
2834 (char *)&nodelay, sizeof(nodelay));
2835 }
2836
2837 //OPTIMIZATION
2838 //if ( s_accept_notify )
2839 // notify_req_received( fd );
2840 }
2841 return fd;
2842
2843 }
2844
2845
2846 static unsigned int s_max_reqs = UINT_MAX;
2847 static int s_max_idle_secs = 300;
2848 static int s_stop;
2849
lsapi_cleanup(int signal)2850 static void lsapi_cleanup(int signal)
2851 {
2852 s_stop = signal;
2853 }
2854
2855
find_child_status(int pid)2856 static lsapi_child_status * find_child_status( int pid )
2857 {
2858 lsapi_child_status * pStatus = g_prefork_server->m_pChildrenStatus;
2859 lsapi_child_status * pEnd = g_prefork_server->m_pChildrenStatusEnd;
2860 while( pStatus < pEnd )
2861 {
2862 if ( pStatus->m_pid == pid )
2863 {
2864 if (pid == 0)
2865 {
2866 memset(pStatus, 0, sizeof( *pStatus ) );
2867 pStatus->m_pid = -1;
2868 }
2869 if ( pStatus + 1 > g_prefork_server->m_pChildrenStatusCur )
2870 g_prefork_server->m_pChildrenStatusCur = pStatus + 1;
2871 return pStatus;
2872 }
2873 ++pStatus;
2874 }
2875 return NULL;
2876 }
2877
2878
LSAPI_reset_server_state(void)2879 void LSAPI_reset_server_state( void )
2880 {
2881 /*
2882 Reset child status
2883 */
2884 g_prefork_server->m_iCurChildren = 0;
2885 lsapi_child_status * pStatus = g_prefork_server->m_pChildrenStatus;
2886 lsapi_child_status * pEnd = g_prefork_server->m_pChildrenStatusEnd;
2887 while( pStatus < pEnd )
2888 {
2889 pStatus->m_pid = 0;
2890 ++pStatus;
2891 }
2892 if (s_busy_workers)
2893 __atomic_store_n(s_busy_workers, 0, __ATOMIC_SEQ_CST);
2894 if (s_accepting_workers)
2895 __atomic_store_n(s_accepting_workers, 0, __ATOMIC_SEQ_CST);
2896
2897 }
2898
2899
lsapi_sigchild(int signal)2900 static void lsapi_sigchild( int signal )
2901 {
2902 int status, pid;
2903 char expect_connected = LSAPI_STATE_CONNECTED;
2904 char expect_accepting = LSAPI_STATE_ACCEPTING;
2905 lsapi_child_status * child_status;
2906 if (g_prefork_server == NULL)
2907 return;
2908 while( 1 )
2909 {
2910 pid = waitpid( -1, &status, WNOHANG|WUNTRACED );
2911 if ( pid <= 0 )
2912 {
2913 break;
2914 }
2915 if ( WIFSIGNALED( status ))
2916 {
2917 int sig_num = WTERMSIG( status );
2918
2919 #ifdef WCOREDUMP
2920 const char * dump = WCOREDUMP( status ) ? "yes" : "no";
2921 #else
2922 const char * dump = "unknown";
2923 #endif
2924 lsapi_log("Child process with pid: %d was killed by signal: "
2925 "%d, core dumped: %s\n", pid, sig_num, dump );
2926 }
2927 if ( pid == s_pid_dump_debug_info )
2928 {
2929 pid = 0;
2930 continue;
2931 }
2932 if ( pid == s_ignore_pid )
2933 {
2934 pid = 0;
2935 s_ignore_pid = -1;
2936 continue;
2937 }
2938 child_status = find_child_status( pid );
2939 if ( child_status )
2940 {
2941 if (__atomic_compare_exchange_n(&child_status->m_state,
2942 &expect_connected,
2943 LSAPI_STATE_IDLE, 1,
2944 __ATOMIC_SEQ_CST,
2945 __ATOMIC_SEQ_CST))
2946 {
2947 if (s_busy_workers)
2948 __atomic_fetch_sub(s_busy_workers, 1, __ATOMIC_SEQ_CST);
2949 }
2950 else if (__atomic_compare_exchange_n(&child_status->m_state,
2951 &expect_accepting,
2952 LSAPI_STATE_IDLE, 1,
2953 __ATOMIC_SEQ_CST,
2954 __ATOMIC_SEQ_CST))
2955 {
2956 if (s_accepting_workers)
2957 __atomic_fetch_sub(s_accepting_workers, 1, __ATOMIC_SEQ_CST);
2958 }
2959 child_status->m_pid = 0;
2960 --g_prefork_server->m_iCurChildren;
2961 }
2962 }
2963 while(( g_prefork_server->m_pChildrenStatusCur > g_prefork_server->m_pChildrenStatus )
2964 &&( g_prefork_server->m_pChildrenStatusCur[-1].m_pid == 0 ))
2965 --g_prefork_server->m_pChildrenStatusCur;
2966
2967 }
2968
2969
lsapi_init_children_status(void)2970 static int lsapi_init_children_status(void)
2971 {
2972 char * pBuf;
2973 int size = 4096;
2974 int max_children;
2975 if (g_prefork_server->m_pChildrenStatus)
2976 return 0;
2977 max_children = g_prefork_server->m_iMaxChildren
2978 + g_prefork_server->m_iExtraChildren;
2979
2980 size = max_children * sizeof( lsapi_child_status ) * 2 + 3 * sizeof(int);
2981 size = (size + 4095) / 4096 * 4096;
2982 pBuf =( char*) mmap( NULL, size, PROT_READ | PROT_WRITE,
2983 MAP_ANON | MAP_SHARED, -1, 0 );
2984 if ( pBuf == MAP_FAILED )
2985 {
2986 perror( "Anonymous mmap() failed" );
2987 return -1;
2988 }
2989 memset( pBuf, 0, size );
2990 g_prefork_server->m_pChildrenStatus = (lsapi_child_status *)pBuf;
2991 g_prefork_server->m_pChildrenStatusCur = (lsapi_child_status *)pBuf;
2992 g_prefork_server->m_pChildrenStatusEnd = (lsapi_child_status *)pBuf + max_children;
2993 s_busy_workers = (int *)g_prefork_server->m_pChildrenStatusEnd;
2994 s_accepting_workers = s_busy_workers + 1;
2995 s_global_counter = s_accepting_workers + 1;
2996 s_avail_pages = (size_t *)(s_global_counter + 1);
2997
2998 setsid();
2999 return 0;
3000 }
3001
3002
dump_debug_info(lsapi_child_status * pStatus,long tmCur)3003 static void dump_debug_info( lsapi_child_status * pStatus, long tmCur )
3004 {
3005 char achCmd[1024];
3006 if ( s_pid_dump_debug_info )
3007 {
3008 if ( kill( s_pid_dump_debug_info, 0 ) == 0 )
3009 return;
3010 }
3011
3012 lsapi_log("Possible runaway process, UID: %d, PPID: %d, PID: %d, "
3013 "reqCount: %d, process time: %ld, checkpoint time: %ld, start "
3014 "time: %ld\n", getuid(), getppid(), pStatus->m_pid,
3015 pStatus->m_iReqCounter, tmCur - pStatus->m_tmReqBegin,
3016 tmCur - pStatus->m_tmLastCheckPoint, tmCur - pStatus->m_tmStart );
3017
3018 s_pid_dump_debug_info = fork();
3019 if (s_pid_dump_debug_info == 0)
3020 {
3021 snprintf( achCmd, 1024, "gdb --batch -ex \"attach %d\" -ex \"set height 0\" "
3022 "-ex \"bt\" >&2;PATH=$PATH:/usr/sbin lsof -p %d >&2",
3023 pStatus->m_pid, pStatus->m_pid );
3024 if ( system( achCmd ) == -1 )
3025 perror( "system()" );
3026 exit( 0 );
3027 }
3028 }
3029
3030
lsapi_check_child_status(long tmCur)3031 static void lsapi_check_child_status( long tmCur )
3032 {
3033 int idle = 0;
3034 int tobekilled;
3035 int dying = 0;
3036 int count = 0;
3037 lsapi_child_status * pStatus = g_prefork_server->m_pChildrenStatus;
3038 lsapi_child_status * pEnd = g_prefork_server->m_pChildrenStatusCur;
3039 while( pStatus < pEnd )
3040 {
3041 tobekilled = 0;
3042 if ( pStatus->m_pid != 0 && pStatus->m_pid != -1)
3043 {
3044 ++count;
3045 if ( !pStatus->m_inProcess )
3046 {
3047 if (g_prefork_server->m_iCurChildren - dying
3048 > g_prefork_server->m_iMaxChildren
3049 || idle > g_prefork_server->m_iMaxIdleChildren)
3050 {
3051 ++pStatus->m_iKillSent;
3052 //tobekilled = SIGUSR1;
3053 }
3054 else
3055 {
3056 if (s_max_idle_secs> 0
3057 && tmCur - pStatus->m_tmWaitBegin > s_max_idle_secs + 5)
3058 {
3059 ++pStatus->m_iKillSent;
3060 //tobekilled = SIGUSR1;
3061 }
3062 }
3063 if (!pStatus->m_iKillSent)
3064 ++idle;
3065 }
3066 else
3067 {
3068 if (tmCur - pStatus->m_tmReqBegin >
3069 g_prefork_server->m_iMaxReqProcessTime)
3070 {
3071 if ((pStatus->m_iKillSent % 5) == 0 && s_dump_debug_info)
3072 dump_debug_info( pStatus, tmCur );
3073 if ( pStatus->m_iKillSent > 5 )
3074 {
3075 tobekilled = SIGKILL;
3076 lsapi_log("Force killing runaway process PID: %d"
3077 " with SIGKILL\n", pStatus->m_pid );
3078 }
3079 else
3080 {
3081 tobekilled = SIGTERM;
3082 lsapi_log("Killing runaway process PID: %d with "
3083 "SIGTERM\n", pStatus->m_pid );
3084 }
3085 }
3086 }
3087 if ( tobekilled )
3088 {
3089 if (( kill( pStatus->m_pid, tobekilled ) == -1 ) &&
3090 ( errno == ESRCH ))
3091 {
3092 pStatus->m_pid = 0;
3093 --count;
3094 }
3095 else
3096 {
3097 ++pStatus->m_iKillSent;
3098 ++dying;
3099 }
3100 }
3101 }
3102 ++pStatus;
3103 }
3104 if ( abs( g_prefork_server->m_iCurChildren - count ) > 1 )
3105 {
3106 lsapi_log("Children tracking is wrong: Cur Children: %d,"
3107 " count: %d, idle: %d, dying: %d\n",
3108 g_prefork_server->m_iCurChildren, count, idle, dying );
3109 }
3110 }
3111
3112
3113 //static int lsapi_all_children_must_die(void)
3114 //{
3115 // int maxWait;
3116 // int sec =0;
3117 // g_prefork_server->m_iMaxReqProcessTime = 10;
3118 // g_prefork_server->m_iMaxIdleChildren = -1;
3119 // maxWait = 15;
3120 //
3121 // while( g_prefork_server->m_iCurChildren && (sec < maxWait) )
3122 // {
3123 // lsapi_check_child_status(time(NULL));
3124 // sleep( 1 );
3125 // sec++;
3126 // }
3127 // if ( g_prefork_server->m_iCurChildren != 0 )
3128 // kill( -getpgrp(), SIGKILL );
3129 // return 0;
3130 //}
3131
3132
set_skip_write(void)3133 void set_skip_write(void)
3134 { s_skip_write = 1; }
3135
3136
is_enough_free_mem(void)3137 int is_enough_free_mem(void)
3138 {
3139 #if defined(linux) || defined(__linux) || defined(__linux__) || defined(__gnu_linux__)
3140 //minimum 1GB or 10% available free memory
3141 return (*s_avail_pages > s_min_avail_pages
3142 || (*s_avail_pages * 10) / s_total_pages > 0);
3143 #endif
3144 return 1;
3145 }
3146
3147
lsapi_prefork_server_accept(lsapi_prefork_server * pServer,LSAPI_Request * pReq)3148 static int lsapi_prefork_server_accept( lsapi_prefork_server * pServer,
3149 LSAPI_Request * pReq )
3150 {
3151 struct sigaction act, old_term, old_quit, old_int,
3152 old_usr1, old_child;
3153 lsapi_child_status * child_status;
3154 int wait_secs = 0;
3155 int ret = 0;
3156 int pid;
3157 time_t lastTime = 0;
3158 time_t curTime = 0;
3159 fd_set readfds;
3160 struct timeval timeout;
3161
3162 sigset_t mask;
3163 sigset_t orig_mask;
3164
3165 lsapi_init_children_status();
3166
3167 act.sa_flags = 0;
3168 act.sa_handler = lsapi_sigchild;
3169 sigemptyset(&(act.sa_mask));
3170 if( sigaction( SIGCHLD, &act, &old_child ) )
3171 {
3172 perror( "Can't set signal handler for SIGCHILD" );
3173 return -1;
3174 }
3175
3176 /* Set up handler to kill children upon exit */
3177 act.sa_flags = 0;
3178 act.sa_handler = lsapi_cleanup;
3179 sigemptyset(&(act.sa_mask));
3180 if( sigaction( SIGTERM, &act, &old_term ) ||
3181 sigaction( SIGINT, &act, &old_int ) ||
3182 sigaction( SIGUSR1, &act, &old_usr1 ) ||
3183 sigaction( SIGQUIT, &act, &old_quit ))
3184 {
3185 perror( "Can't set signals" );
3186 return -1;
3187 }
3188
3189 while( !s_stop )
3190 {
3191 if (s_proc_group_timer_cb != NULL) {
3192 s_proc_group_timer_cb(&s_ignore_pid);
3193 }
3194
3195 curTime = time( NULL );
3196 if (curTime != lastTime )
3197 {
3198 lastTime = curTime;
3199 if (lsapi_parent_dead())
3200 break;
3201 lsapi_check_child_status(curTime );
3202 if (pServer->m_iServerMaxIdle)
3203 {
3204 if ( pServer->m_iCurChildren <= 0 )
3205 {
3206 ++wait_secs;
3207 if ( wait_secs > pServer->m_iServerMaxIdle )
3208 return -1;
3209 }
3210 else
3211 wait_secs = 0;
3212 }
3213 }
3214
3215 #if defined(linux) || defined(__linux) || defined(__linux__) || defined(__gnu_linux__)
3216 *s_avail_pages = sysconf(_SC_AVPHYS_PAGES);
3217 // lsapi_log("Memory total: %zd, free: %zd, free %%%zd\n",
3218 // s_total_pages, *s_avail_pages, *s_avail_pages * 100 / s_total_pages);
3219
3220 #endif
3221 FD_ZERO( &readfds );
3222 FD_SET( pServer->m_fd, &readfds );
3223 timeout.tv_sec = 1;
3224 timeout.tv_usec = 0;
3225 ret = (*g_fnSelect)(pServer->m_fd+1, &readfds, NULL, NULL, &timeout);
3226 if (ret == 1 )
3227 {
3228 int accepting = 0;
3229 if (s_accepting_workers)
3230 accepting = __atomic_load_n(s_accepting_workers, __ATOMIC_SEQ_CST);
3231
3232 if (pServer->m_iCurChildren > 0
3233 && accepting > 0)
3234 {
3235 usleep(400);
3236 while(accepting-- > 0)
3237 sched_yield();
3238 continue;
3239 }
3240 }
3241 else if ( ret == -1 )
3242 {
3243 if ( errno == EINTR )
3244 continue;
3245 /* perror( "select()" ); */
3246 break;
3247 }
3248 else
3249 {
3250 continue;
3251 }
3252
3253 if (pServer->m_iCurChildren >=
3254 pServer->m_iMaxChildren + pServer->m_iExtraChildren)
3255 {
3256 lsapi_log("Reached max children process limit: %d, extra: %d,"
3257 " current: %d, busy: %d, please increase LSAPI_CHILDREN.\n",
3258 pServer->m_iMaxChildren, pServer->m_iExtraChildren,
3259 pServer->m_iCurChildren,
3260 s_busy_workers ? *s_busy_workers : -1 );
3261 usleep( 100000 );
3262 continue;
3263 }
3264
3265 pReq->m_fd = lsapi_accept( pServer->m_fd );
3266 if ( pReq->m_fd != -1 )
3267 {
3268 wait_secs = 0;
3269 child_status = find_child_status( 0 );
3270
3271 sigemptyset( &mask );
3272 sigaddset( &mask, SIGCHLD );
3273
3274 if ( sigprocmask(SIG_BLOCK, &mask, &orig_mask) < 0 )
3275 {
3276 perror( "sigprocmask(SIG_BLOCK) to block SIGCHLD" );
3277 }
3278
3279 pid = fork();
3280
3281 if ( !pid )
3282 {
3283 setsid();
3284 if (sigprocmask(SIG_SETMASK, &orig_mask, NULL) < 0)
3285 perror( "sigprocmask( SIG_SETMASK ) to restore SIGMASK in child" );
3286 g_prefork_server = NULL;
3287 s_ppid = getppid();
3288 s_pid = getpid();
3289 s_req_processed = 0;
3290 s_proc_group_timer_cb = NULL;
3291 s_worker_status = child_status;
3292
3293 if (pthread_atfork_func)
3294 (*pthread_atfork_func)(NULL, NULL, set_skip_write);
3295
3296 __atomic_store_n(&s_worker_status->m_state,
3297 LSAPI_STATE_CONNECTED, __ATOMIC_SEQ_CST);
3298 if (s_busy_workers)
3299 __atomic_add_fetch(s_busy_workers, 1, __ATOMIC_SEQ_CST);
3300 lsapi_set_nblock( pReq->m_fd, 0 );
3301 //keep it open if busy_count is used.
3302 if (!s_keep_listener && s_busy_workers
3303 && *s_busy_workers > (pServer->m_iMaxChildren >> 1))
3304 s_keep_listener = 1;
3305 if ((s_uid == 0 || !s_keep_listener || !is_enough_free_mem())
3306 && pReq->m_fdListen != -1 )
3307 {
3308 close( pReq->m_fdListen );
3309 pReq->m_fdListen = -1;
3310 }
3311 /* don't catch our signals */
3312 sigaction( SIGCHLD, &old_child, 0 );
3313 sigaction( SIGTERM, &old_term, 0 );
3314 sigaction( SIGQUIT, &old_quit, 0 );
3315 sigaction( SIGINT, &old_int, 0 );
3316 sigaction( SIGUSR1, &old_usr1, 0 );
3317 //init_conn_key( pReq->m_fd );
3318 lsapi_notify_pid( pReq->m_fd );
3319 s_notified_pid = 1;
3320 //if ( s_accept_notify )
3321 // return notify_req_received( pReq->m_fd );
3322 return 0;
3323 }
3324 else if ( pid == -1 )
3325 {
3326 lsapi_perror("fork() failed, please increase process limit", errno);
3327 if (child_status)
3328 child_status->m_pid = 0;
3329 }
3330 else
3331 {
3332 ++pServer->m_iCurChildren;
3333 if ( child_status )
3334 {
3335 child_status->m_pid = pid;
3336 child_status->m_tmWaitBegin = curTime;
3337 child_status->m_tmStart = curTime;
3338 }
3339 }
3340 close( pReq->m_fd );
3341 pReq->m_fd = -1;
3342
3343 if (sigprocmask(SIG_SETMASK, &orig_mask, NULL) < 0)
3344 perror( "sigprocmask( SIG_SETMASK ) to restore SIGMASK" );
3345
3346 }
3347 else
3348 {
3349 if (( errno == EINTR )||( errno == EAGAIN))
3350 continue;
3351 lsapi_perror("accept() failed", errno);
3352 return -1;
3353 }
3354 }
3355 sigaction( SIGUSR1, &old_usr1, 0 );
3356 //kill( -getpgrp(), SIGUSR1 );
3357 //lsapi_all_children_must_die(); /* Sorry, children ;-) */
3358 return -1;
3359
3360 }
3361
3362
3363 static struct sigaction old_term, old_quit, old_int,
3364 old_usr1, old_child;
3365
3366
LSAPI_Postfork_Child(LSAPI_Request * pReq)3367 int LSAPI_Postfork_Child(LSAPI_Request * pReq)
3368 {
3369 int max_children = g_prefork_server->m_iMaxChildren;
3370 s_pid = getpid();
3371 __atomic_store_n(&pReq->child_status->m_pid, s_pid, __ATOMIC_SEQ_CST);
3372 s_worker_status = pReq->child_status;
3373
3374 setsid();
3375 g_prefork_server = NULL;
3376 s_ppid = getppid();
3377 s_req_processed = 0;
3378 s_proc_group_timer_cb = NULL;
3379
3380 if (pthread_atfork_func)
3381 (*pthread_atfork_func)(NULL, NULL, set_skip_write);
3382
3383 __atomic_store_n(&s_worker_status->m_state,
3384 LSAPI_STATE_CONNECTED, __ATOMIC_SEQ_CST);
3385 if (s_busy_workers)
3386 __atomic_add_fetch(s_busy_workers, 1, __ATOMIC_SEQ_CST);
3387 lsapi_set_nblock( pReq->m_fd, 0 );
3388 //keep it open if busy_count is used.
3389 if (!s_keep_listener && s_busy_workers
3390 && *s_busy_workers > (max_children >> 1))
3391 s_keep_listener = 1;
3392 if ((s_uid == 0 || !s_keep_listener || !is_enough_free_mem())
3393 && pReq->m_fdListen != -1 )
3394 {
3395 close(pReq->m_fdListen);
3396 pReq->m_fdListen = -1;
3397 }
3398
3399 //init_conn_key( pReq->m_fd );
3400 lsapi_notify_pid(pReq->m_fd);
3401 s_notified_pid = 1;
3402 //if ( s_accept_notify )
3403 // return notify_req_received( pReq->m_fd );
3404 return 0;
3405 }
3406
3407
LSAPI_Postfork_Parent(LSAPI_Request * pReq)3408 int LSAPI_Postfork_Parent(LSAPI_Request * pReq)
3409 {
3410 ++g_prefork_server->m_iCurChildren;
3411 if (pReq->child_status)
3412 {
3413 time_t curTime = time( NULL );
3414 pReq->child_status->m_tmWaitBegin = curTime;
3415 pReq->child_status->m_tmStart = curTime;
3416 }
3417 close(pReq->m_fd);
3418 pReq->m_fd = -1;
3419 return 0;
3420 }
3421
3422
LSAPI_Accept_Before_Fork(LSAPI_Request * pReq)3423 int LSAPI_Accept_Before_Fork(LSAPI_Request * pReq)
3424 {
3425 time_t lastTime = 0;
3426 time_t curTime = 0;
3427 fd_set readfds;
3428 struct timeval timeout;
3429 int wait_secs = 0;
3430 int ret = 0;
3431
3432 lsapi_prefork_server * pServer = g_prefork_server;
3433
3434 struct sigaction act;
3435
3436 lsapi_init_children_status();
3437
3438 act.sa_flags = 0;
3439 act.sa_handler = lsapi_sigchild;
3440 sigemptyset(&(act.sa_mask));
3441 if (sigaction(SIGCHLD, &act, &old_child))
3442 {
3443 perror( "Can't set signal handler for SIGCHILD" );
3444 return -1;
3445 }
3446
3447 /* Set up handler to kill children upon exit */
3448 act.sa_flags = 0;
3449 act.sa_handler = lsapi_cleanup;
3450 sigemptyset(&(act.sa_mask));
3451 if (sigaction(SIGTERM, &act, &old_term) ||
3452 sigaction(SIGINT, &act, &old_int ) ||
3453 sigaction(SIGUSR1, &act, &old_usr1) ||
3454 sigaction(SIGQUIT, &act, &old_quit))
3455 {
3456 perror( "Can't set signals" );
3457 return -1;
3458 }
3459 s_stop = 0;
3460 pReq->m_reqState = 0;
3461
3462 while(!s_stop)
3463 {
3464 if (s_proc_group_timer_cb != NULL) {
3465 s_proc_group_timer_cb(&s_ignore_pid);
3466 }
3467
3468 curTime = time(NULL);
3469 if (curTime != lastTime)
3470 {
3471 lastTime = curTime;
3472 if (lsapi_parent_dead())
3473 break;
3474 lsapi_check_child_status(curTime);
3475 if (pServer->m_iServerMaxIdle)
3476 {
3477 if (pServer->m_iCurChildren <= 0)
3478 {
3479 ++wait_secs;
3480 if ( wait_secs > pServer->m_iServerMaxIdle )
3481 return -1;
3482 }
3483 else
3484 wait_secs = 0;
3485 }
3486 }
3487
3488 #if defined(linux) || defined(__linux) || defined(__linux__) || defined(__gnu_linux__)
3489 *s_avail_pages = sysconf(_SC_AVPHYS_PAGES);
3490 // lsapi_log("Memory total: %zd, free: %zd, free %%%zd\n",
3491 // s_total_pages, *s_avail_pages, *s_avail_pages * 100 / s_total_pages);
3492
3493 #endif
3494 FD_ZERO(&readfds);
3495 FD_SET(pServer->m_fd, &readfds);
3496 timeout.tv_sec = 1;
3497 timeout.tv_usec = 0;
3498 ret = (*g_fnSelect)(pServer->m_fd+1, &readfds, NULL, NULL, &timeout);
3499 if (ret == 1 )
3500 {
3501 int accepting = 0;
3502 if (s_accepting_workers)
3503 accepting = __atomic_load_n(s_accepting_workers, __ATOMIC_SEQ_CST);
3504
3505 if (pServer->m_iCurChildren > 0
3506 && accepting > 0)
3507 {
3508 usleep( 400);
3509 while(accepting-- > 0)
3510 sched_yield();
3511 continue;
3512 }
3513 }
3514 else if (ret == -1)
3515 {
3516 if (errno == EINTR)
3517 continue;
3518 /* perror( "select()" ); */
3519 break;
3520 }
3521 else
3522 {
3523 continue;
3524 }
3525
3526 if (pServer->m_iCurChildren >=
3527 pServer->m_iMaxChildren + pServer->m_iExtraChildren)
3528 {
3529 lsapi_log("Reached max children process limit: %d, extra: %d,"
3530 " current: %d, busy: %d, please increase LSAPI_CHILDREN.\n",
3531 pServer->m_iMaxChildren, pServer->m_iExtraChildren,
3532 pServer->m_iCurChildren,
3533 s_busy_workers ? *s_busy_workers : -1);
3534 usleep(100000);
3535 continue;
3536 }
3537
3538 pReq->m_fd = lsapi_accept(pServer->m_fd);
3539 if (pReq->m_fd != -1)
3540 {
3541 wait_secs = 0;
3542 pReq->child_status = find_child_status(0);
3543
3544 ret = 0;
3545 break;
3546 }
3547 else
3548 {
3549 if ((errno == EINTR) || (errno == EAGAIN))
3550 continue;
3551 lsapi_perror("accept() failed", errno);
3552 ret = -1;
3553 break;
3554 }
3555 }
3556
3557 sigaction(SIGCHLD, &old_child, 0);
3558 sigaction(SIGTERM, &old_term, 0);
3559 sigaction(SIGQUIT, &old_quit, 0);
3560 sigaction(SIGINT, &old_int, 0);
3561 sigaction(SIGUSR1, &old_usr1, 0);
3562
3563 return ret;
3564 }
3565
3566
LSAPI_Prefork_Accept_r(LSAPI_Request * pReq)3567 int LSAPI_Prefork_Accept_r( LSAPI_Request * pReq )
3568 {
3569 int fd;
3570 int ret;
3571 int wait_secs;
3572 fd_set readfds;
3573 struct timeval timeout;
3574
3575 if (s_skip_write)
3576 return -1;
3577
3578 LSAPI_Finish_r( pReq );
3579
3580 if ( g_prefork_server )
3581 {
3582 if ( g_prefork_server->m_fd != -1 )
3583 if ( lsapi_prefork_server_accept( g_prefork_server, pReq ) == -1 )
3584 return -1;
3585 }
3586 else if (s_req_processed > 0 && s_max_busy_workers > 0 && s_busy_workers)
3587 {
3588 ret = __atomic_load_n(s_busy_workers, __ATOMIC_SEQ_CST);
3589 if (ret >= s_max_busy_workers)
3590 {
3591 send_conn_close_notification(pReq->m_fd);
3592 lsapi_close_connection(pReq);
3593 }
3594 }
3595
3596 if ( (unsigned int)s_req_processed > s_max_reqs )
3597 return -1;
3598
3599 if ( s_worker_status )
3600 {
3601 s_worker_status->m_tmWaitBegin = time( NULL );
3602 }
3603
3604
3605 while( g_running )
3606 {
3607 if ( pReq->m_fd != -1 )
3608 {
3609 fd = pReq->m_fd;
3610 }
3611 else if ( pReq->m_fdListen != -1 )
3612 fd = pReq->m_fdListen;
3613 else
3614 {
3615 break;
3616 }
3617 wait_secs = 0;
3618 while( 1 )
3619 {
3620 if ( !g_running )
3621 return -1;
3622 if (s_req_processed && s_worker_status
3623 && s_worker_status->m_iKillSent)
3624 return -1;
3625 FD_ZERO( &readfds );
3626 FD_SET( fd, &readfds );
3627 timeout.tv_sec = 1;
3628 timeout.tv_usec = 0;
3629 if (fd == pReq->m_fdListen)
3630 {
3631 if (s_worker_status)
3632 __atomic_store_n(&s_worker_status->m_state,
3633 LSAPI_STATE_ACCEPTING, __ATOMIC_SEQ_CST);
3634 if (s_accepting_workers)
3635 __atomic_fetch_add(s_accepting_workers, 1, __ATOMIC_SEQ_CST);
3636 }
3637 ret = (*g_fnSelect)(fd+1, &readfds, NULL, NULL, &timeout);
3638 if (fd == pReq->m_fdListen)
3639 {
3640 if (s_accepting_workers)
3641 __atomic_fetch_sub(s_accepting_workers, 1, __ATOMIC_SEQ_CST);
3642 if (s_worker_status)
3643 __atomic_store_n(&s_worker_status->m_state,
3644 LSAPI_STATE_IDLE, __ATOMIC_SEQ_CST);
3645 }
3646
3647 if ( ret == 0 )
3648 {
3649 if ( s_worker_status )
3650 {
3651 s_worker_status->m_inProcess = 0;
3652 if (fd == pReq->m_fdListen)
3653 {
3654 if (s_keep_listener == 0 || !is_enough_free_mem())
3655 return -1;
3656 if (s_keep_listener == 1)
3657 {
3658 int wait_time = 10;
3659 if (s_busy_workers)
3660 wait_time += *s_busy_workers * 10;
3661 if (s_accepting_workers)
3662 wait_time >>= (*s_accepting_workers);
3663 if (wait_secs >= wait_time)
3664 return -1;
3665 }
3666 }
3667 }
3668 ++wait_secs;
3669 if (( s_max_idle_secs > 0 )&&(wait_secs >= s_max_idle_secs ))
3670 return -1;
3671 if ( lsapi_parent_dead() )
3672 return -1;
3673 }
3674 else if ( ret == -1 )
3675 {
3676 if ( errno == EINTR )
3677 continue;
3678 else
3679 return -1;
3680 }
3681 else if ( ret >= 1 )
3682 {
3683 if (s_req_processed && s_worker_status
3684 && s_worker_status->m_iKillSent)
3685 return -1;
3686 if ( fd == pReq->m_fdListen )
3687 {
3688 pReq->m_fd = lsapi_accept( pReq->m_fdListen );
3689 if ( pReq->m_fd != -1 )
3690 {
3691 if (s_worker_status)
3692 __atomic_store_n(&s_worker_status->m_state,
3693 LSAPI_STATE_CONNECTED,
3694 __ATOMIC_SEQ_CST);
3695 if (s_busy_workers)
3696 __atomic_fetch_add(s_busy_workers, 1, __ATOMIC_SEQ_CST);
3697
3698 fd = pReq->m_fd;
3699
3700 lsapi_set_nblock( fd, 0 );
3701 //init_conn_key( pReq->m_fd );
3702 if (!s_keep_listener)
3703 {
3704 close( pReq->m_fdListen );
3705 pReq->m_fdListen = -1;
3706 }
3707 if ( s_accept_notify )
3708 if ( notify_req_received( pReq->m_fd ) == -1 )
3709 return -1;
3710 }
3711 else
3712 {
3713 if (( errno == EINTR )||( errno == EAGAIN))
3714 continue;
3715 lsapi_perror( "lsapi_accept() error", errno );
3716 return -1;
3717 }
3718 }
3719 else
3720 break;
3721 }
3722 }
3723
3724 if ( !readReq( pReq ) )
3725 {
3726 if ( s_worker_status )
3727 {
3728 s_worker_status->m_iKillSent = 0;
3729 s_worker_status->m_inProcess = 1;
3730 ++s_worker_status->m_iReqCounter;
3731 s_worker_status->m_tmReqBegin =
3732 s_worker_status->m_tmLastCheckPoint = time(NULL);
3733 }
3734 ++s_req_processed;
3735 return 0;
3736 }
3737 lsapi_close_connection(pReq);
3738 LSAPI_Reset_r( pReq );
3739 }
3740 return -1;
3741
3742 }
3743
3744
LSAPI_Set_Max_Reqs(int reqs)3745 void LSAPI_Set_Max_Reqs( int reqs )
3746 { s_max_reqs = reqs - 1; }
3747
LSAPI_Set_Max_Idle(int secs)3748 void LSAPI_Set_Max_Idle( int secs )
3749 { s_max_idle_secs = secs; }
3750
3751
LSAPI_Set_Max_Children(int maxChildren)3752 void LSAPI_Set_Max_Children( int maxChildren )
3753 {
3754 if ( g_prefork_server )
3755 g_prefork_server->m_iMaxChildren = maxChildren;
3756 }
3757
3758
LSAPI_Set_Extra_Children(int extraChildren)3759 void LSAPI_Set_Extra_Children( int extraChildren )
3760 {
3761 if (( g_prefork_server )&&( extraChildren >= 0 ))
3762 g_prefork_server->m_iExtraChildren = extraChildren;
3763 }
3764
3765
LSAPI_Set_Max_Process_Time(int secs)3766 void LSAPI_Set_Max_Process_Time( int secs )
3767 {
3768 if (( g_prefork_server )&&( secs > 0 ))
3769 g_prefork_server->m_iMaxReqProcessTime = secs;
3770 }
3771
3772
LSAPI_Set_Max_Idle_Children(int maxIdleChld)3773 void LSAPI_Set_Max_Idle_Children( int maxIdleChld )
3774 {
3775 if (( g_prefork_server )&&( maxIdleChld > 0 ))
3776 g_prefork_server->m_iMaxIdleChildren = maxIdleChld;
3777 }
3778
3779
LSAPI_Set_Server_Max_Idle_Secs(int serverMaxIdle)3780 void LSAPI_Set_Server_Max_Idle_Secs( int serverMaxIdle )
3781 {
3782 if ( g_prefork_server )
3783 g_prefork_server->m_iServerMaxIdle = serverMaxIdle;
3784 }
3785
3786
LSAPI_Set_Slow_Req_Msecs(int msecs)3787 void LSAPI_Set_Slow_Req_Msecs( int msecs )
3788 {
3789 s_slow_req_msecs = msecs;
3790 }
3791
3792
LSAPI_Get_Slow_Req_Msecs(void)3793 int LSAPI_Get_Slow_Req_Msecs(void)
3794 {
3795 return s_slow_req_msecs;
3796 }
3797
3798
LSAPI_No_Check_ppid(void)3799 void LSAPI_No_Check_ppid(void)
3800 {
3801 s_ppid = 0;
3802 }
3803
3804
LSAPI_Get_ppid(void)3805 int LSAPI_Get_ppid(void)
3806 {
3807 return(s_ppid);
3808 }
3809
3810
3811 #if defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__)
3812 #include <crt_externs.h>
3813 #else
3814 extern char ** environ;
3815 #endif
unset_lsapi_envs(void)3816 static void unset_lsapi_envs(void)
3817 {
3818 char **env;
3819 #if defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__)
3820 env = *_NSGetEnviron();
3821 #else
3822 env = environ;
3823 #endif
3824 while( env != NULL && *env != NULL )
3825 {
3826 if (!strncmp(*env, "LSAPI_", 6) || !strncmp( *env, "PHP_LSAPI_", 10 )
3827 || (!strncmp( *env, "PHPRC=", 6 )&&(!s_uid)))
3828 {
3829 char ** del = env;
3830 do
3831 *del = del[1];
3832 while( *del++ );
3833 }
3834 else
3835 ++env;
3836 }
3837 }
3838
3839
lsapi_initSuEXEC(void)3840 static int lsapi_initSuEXEC(void)
3841 {
3842 int i;
3843 struct passwd * pw;
3844 s_defaultUid = 0;
3845 s_defaultGid = 0;
3846 if ( s_uid == 0 )
3847 {
3848 const char * p = getenv( "LSAPI_DEFAULT_UID" );
3849 if ( p )
3850 {
3851 i = atoi( p );
3852 if ( i > 0 )
3853 s_defaultUid = i;
3854 }
3855 p = getenv( "LSAPI_DEFAULT_GID" );
3856 if ( p )
3857 {
3858 i = atoi( p );
3859 if ( i > 0 )
3860 s_defaultGid = i;
3861 }
3862 p = getenv( "LSAPI_SECRET" );
3863 if (( !p )||( readSecret(p) == -1 ))
3864 return -1;
3865 if ( g_prefork_server )
3866 {
3867 if ( g_prefork_server->m_iMaxChildren < 100 )
3868 g_prefork_server->m_iMaxChildren = 100;
3869 if ( g_prefork_server->m_iExtraChildren < 1000 )
3870 g_prefork_server->m_iExtraChildren = 1000;
3871 }
3872 }
3873 if ( !s_defaultUid || !s_defaultGid )
3874 {
3875 pw = getpwnam( "nobody" );
3876 if ( pw )
3877 {
3878 if ( !s_defaultUid )
3879 s_defaultUid = pw->pw_uid;
3880 if ( !s_defaultGid )
3881 s_defaultGid = pw->pw_gid;
3882 }
3883 else
3884 {
3885 if ( !s_defaultUid )
3886 s_defaultUid = 10000;
3887 if ( !s_defaultGid )
3888 s_defaultGid = 10000;
3889 }
3890 }
3891 return 0;
3892 }
3893
3894
lsapi_check_path(const char * p,char * final,int max_len)3895 static int lsapi_check_path(const char *p, char *final, int max_len)
3896 {
3897 char resolved_path[PATH_MAX+1];
3898 int len = 0;
3899 char *end;
3900 if (*p != '/')
3901 {
3902 if (getcwd(final, max_len) == NULL)
3903 return -1;
3904 len = strlen(final);
3905 *(final + len) = '/';
3906 ++len;
3907 }
3908 end = memccpy(&final[len], p, '\0', PATH_MAX - len);
3909 if (!end)
3910 {
3911 errno = EINVAL;
3912 return -1;
3913 }
3914 p = final;
3915 if (realpath(p, resolved_path) == NULL
3916 && errno != ENOENT && errno != EACCES)
3917 return -1;
3918 if (strncmp(resolved_path, "/etc/", 5) == 0)
3919 {
3920 errno = EPERM;
3921 return -1;
3922 }
3923 return 0;
3924 }
3925
3926
lsapi_reopen_stderr2(const char * full_path)3927 static int lsapi_reopen_stderr2(const char *full_path)
3928 {
3929 int newfd = open(full_path, O_WRONLY | O_CREAT | O_APPEND, 0644);
3930 if (newfd == -1)
3931 {
3932 LSAPI_perror_r(NULL, "Failed to open custom stderr log", full_path);
3933 return -1;
3934 }
3935 if (newfd != 2)
3936 {
3937 dup2(newfd, 2);
3938 close(newfd);
3939 dup2(2, 1);
3940 }
3941 if (s_stderr_log_path && full_path != s_stderr_log_path)
3942 {
3943 free(s_stderr_log_path);
3944 s_stderr_log_path = NULL;
3945 }
3946 s_stderr_log_path = strdup(full_path);
3947 return 0;
3948 }
3949
3950
lsapi_reopen_stderr(const char * p)3951 static int lsapi_reopen_stderr(const char *p)
3952 {
3953 char full_path[PATH_MAX];
3954 if (s_uid == 0)
3955 return -1;
3956 if (lsapi_check_path(p, full_path, PATH_MAX) == -1)
3957 {
3958 LSAPI_perror_r(NULL, "Invalid custom stderr log path", p);
3959 return -1;
3960 }
3961 return lsapi_reopen_stderr2(full_path);
3962 }
3963
3964
LSAPI_Init_Env_Parameters(fn_select_t fp)3965 int LSAPI_Init_Env_Parameters( fn_select_t fp )
3966 {
3967 const char *p;
3968 char ch;
3969 int n;
3970 int avoidFork = 0;
3971
3972 p = getenv("LSAPI_STDERR_LOG");
3973 if (p)
3974 {
3975 lsapi_reopen_stderr(p);
3976 }
3977 if (!s_stderr_log_path)
3978 s_stderr_is_pipe = isPipe(STDERR_FILENO);
3979
3980 p = getenv( "PHP_LSAPI_MAX_REQUESTS" );
3981 if ( !p )
3982 p = getenv( "LSAPI_MAX_REQS" );
3983 if ( p )
3984 {
3985 n = atoi( p );
3986 if ( n > 0 )
3987 LSAPI_Set_Max_Reqs( n );
3988 }
3989
3990 p = getenv( "LSAPI_KEEP_LISTEN" );
3991 if ( p )
3992 {
3993 n = atoi( p );
3994 s_keep_listener = n;
3995 }
3996
3997 p = getenv( "LSAPI_AVOID_FORK" );
3998 if ( p )
3999 {
4000 avoidFork = atoi( p );
4001 if (avoidFork)
4002 {
4003 s_keep_listener = 2;
4004 ch = *(p + strlen(p) - 1);
4005 if ( ch == 'G' || ch == 'g' )
4006 avoidFork *= 1024 * 1024 * 1024;
4007 else if ( ch == 'M' || ch == 'm' )
4008 avoidFork *= 1024 * 1024;
4009 if (avoidFork >= 1024 * 10240)
4010 s_min_avail_pages = avoidFork / 4096;
4011 }
4012 }
4013
4014 p = getenv( "LSAPI_ACCEPT_NOTIFY" );
4015 if ( p )
4016 {
4017 s_accept_notify = atoi( p );
4018 }
4019
4020 p = getenv( "LSAPI_SLOW_REQ_MSECS" );
4021 if ( p )
4022 {
4023 n = atoi( p );
4024 LSAPI_Set_Slow_Req_Msecs( n );
4025 }
4026
4027 #if defined( RLIMIT_CORE )
4028 p = getenv( "LSAPI_ALLOW_CORE_DUMP" );
4029 if ( !p )
4030 {
4031 struct rlimit limit = { 0, 0 };
4032 setrlimit( RLIMIT_CORE, &limit );
4033 }
4034 else
4035 s_enable_core_dump = 1;
4036
4037 #endif
4038
4039 p = getenv( "LSAPI_MAX_IDLE" );
4040 if ( p )
4041 {
4042 n = atoi( p );
4043 LSAPI_Set_Max_Idle( n );
4044 }
4045
4046 if ( LSAPI_Is_Listen() )
4047 {
4048 n = 0;
4049 p = getenv( "PHP_LSAPI_CHILDREN" );
4050 if ( !p )
4051 p = getenv( "LSAPI_CHILDREN" );
4052 if ( p )
4053 n = atoi( p );
4054 if ( n > 1 )
4055 {
4056 LSAPI_Init_Prefork_Server( n, fp, avoidFork != 0 );
4057 LSAPI_Set_Server_fd( g_req.m_fdListen );
4058 }
4059
4060 p = getenv( "LSAPI_EXTRA_CHILDREN" );
4061 if ( p )
4062 LSAPI_Set_Extra_Children( atoi( p ) );
4063
4064 p = getenv( "LSAPI_MAX_IDLE_CHILDREN" );
4065 if ( p )
4066 LSAPI_Set_Max_Idle_Children( atoi( p ) );
4067
4068 p = getenv( "LSAPI_PGRP_MAX_IDLE" );
4069 if ( p )
4070 {
4071 LSAPI_Set_Server_Max_Idle_Secs( atoi( p ) );
4072 }
4073
4074 p = getenv( "LSAPI_MAX_PROCESS_TIME" );
4075 if ( p )
4076 LSAPI_Set_Max_Process_Time( atoi( p ) );
4077
4078 if ( getenv( "LSAPI_PPID_NO_CHECK" ) )
4079 {
4080 LSAPI_No_Check_ppid();
4081 }
4082
4083 p = getenv("LSAPI_MAX_BUSY_WORKER");
4084 if (p)
4085 {
4086 n = atoi(p);
4087 s_max_busy_workers = n;
4088 if (n >= 0)
4089 LSAPI_No_Check_ppid();
4090 }
4091
4092
4093 p = getenv( "LSAPI_DUMP_DEBUG_INFO" );
4094 if ( p )
4095 s_dump_debug_info = atoi( p );
4096
4097 if ( lsapi_initSuEXEC() == -1 )
4098 return -1;
4099 #if defined(linux) || defined(__linux) || defined(__linux__) || defined(__gnu_linux__)
4100 lsapi_initLVE();
4101 #endif
4102 }
4103 unset_lsapi_envs();
4104 return 0;
4105 }
4106
4107
LSAPI_ErrResponse_r(LSAPI_Request * pReq,int code,const char ** pRespHeaders,const char * pBody,int bodyLen)4108 int LSAPI_ErrResponse_r( LSAPI_Request * pReq, int code, const char ** pRespHeaders,
4109 const char * pBody, int bodyLen )
4110 {
4111 LSAPI_SetRespStatus_r( pReq, code );
4112 if ( pRespHeaders )
4113 {
4114 while( *pRespHeaders )
4115 {
4116 LSAPI_AppendRespHeader_r( pReq, *pRespHeaders, strlen( *pRespHeaders ) );
4117 ++pRespHeaders;
4118 }
4119 }
4120 if ( pBody &&( bodyLen > 0 ))
4121 {
4122 LSAPI_Write_r( pReq, pBody, bodyLen );
4123 }
4124 LSAPI_Finish_r( pReq );
4125 return 0;
4126 }
4127
4128
4129 static void lsapi_MD5Transform(uint32 buf[4], uint32 const in[16]);
4130
4131 /*
4132 * Note: this code is harmless on little-endian machines.
4133 */
byteReverse(unsigned char * buf,unsigned longs)4134 static void byteReverse(unsigned char *buf, unsigned longs)
4135 {
4136 uint32 t;
4137 do {
4138 t = (uint32) ((unsigned) buf[3] << 8 | buf[2]) << 16 |
4139 ((unsigned) buf[1] << 8 | buf[0]);
4140 *(uint32 *) buf = t;
4141 buf += 4;
4142 } while (--longs);
4143 }
4144
4145
4146 /*
4147 * Start MD5 accumulation. Set bit count to 0 and buffer to mysterious
4148 * initialization constants.
4149 */
lsapi_MD5Init(struct lsapi_MD5Context * ctx)4150 void lsapi_MD5Init(struct lsapi_MD5Context *ctx)
4151 {
4152 ctx->buf[0] = 0x67452301;
4153 ctx->buf[1] = 0xefcdab89;
4154 ctx->buf[2] = 0x98badcfe;
4155 ctx->buf[3] = 0x10325476;
4156
4157 ctx->bits[0] = 0;
4158 ctx->bits[1] = 0;
4159 }
4160
4161 /*
4162 * Update context to reflect the concatenation of another buffer full
4163 * of bytes.
4164 */
lsapi_MD5Update(struct lsapi_MD5Context * ctx,unsigned char const * buf,unsigned len)4165 void lsapi_MD5Update(struct lsapi_MD5Context *ctx, unsigned char const *buf, unsigned len)
4166 {
4167 register uint32 t;
4168
4169 /* Update bitcount */
4170
4171 t = ctx->bits[0];
4172 if ((ctx->bits[0] = t + ((uint32) len << 3)) < t)
4173 ctx->bits[1]++; /* Carry from low to high */
4174 ctx->bits[1] += len >> 29;
4175
4176 t = (t >> 3) & 0x3f; /* Bytes already in shsInfo->data */
4177
4178 /* Handle any leading odd-sized chunks */
4179
4180 if (t) {
4181 unsigned char *p = (unsigned char *) ctx->in + t;
4182
4183 t = 64 - t;
4184 if (len < t) {
4185 memmove(p, buf, len);
4186 return;
4187 }
4188 memmove(p, buf, t);
4189 byteReverse(ctx->in, 16);
4190 lsapi_MD5Transform(ctx->buf, (uint32 *) ctx->in);
4191 buf += t;
4192 len -= t;
4193 }
4194 /* Process data in 64-byte chunks */
4195
4196 while (len >= 64) {
4197 memmove(ctx->in, buf, 64);
4198 byteReverse(ctx->in, 16);
4199 lsapi_MD5Transform(ctx->buf, (uint32 *) ctx->in);
4200 buf += 64;
4201 len -= 64;
4202 }
4203
4204 /* Handle any remaining bytes of data. */
4205
4206 memmove(ctx->in, buf, len);
4207 }
4208
4209
4210 /*
4211 * Final wrap-up - pad to 64-byte boundary with the bit pattern
4212 * 1 0* (64-bit count of bits processed, MSB-first)
4213 */
lsapi_MD5Final(unsigned char digest[16],struct lsapi_MD5Context * ctx)4214 void lsapi_MD5Final(unsigned char digest[16], struct lsapi_MD5Context *ctx)
4215 {
4216 unsigned int count;
4217 unsigned char *p;
4218
4219 /* Compute number of bytes mod 64 */
4220 count = (ctx->bits[0] >> 3) & 0x3F;
4221
4222 /* Set the first char of padding to 0x80. This is safe since there is
4223 always at least one byte free */
4224 p = ctx->in + count;
4225 *p++ = 0x80;
4226
4227 /* Bytes of padding needed to make 64 bytes */
4228 count = 64 - 1 - count;
4229
4230 /* Pad out to 56 mod 64 */
4231 if (count < 8) {
4232 /* Two lots of padding: Pad the first block to 64 bytes */
4233 memset(p, 0, count);
4234 byteReverse(ctx->in, 16);
4235 lsapi_MD5Transform(ctx->buf, (uint32 *) ctx->in);
4236
4237 /* Now fill the next block with 56 bytes */
4238 memset(ctx->in, 0, 56);
4239 } else {
4240 /* Pad block to 56 bytes */
4241 memset(p, 0, count - 8);
4242 }
4243 byteReverse(ctx->in, 14);
4244
4245 /* Append length in bits and transform */
4246 ((uint32 *) ctx->in)[14] = ctx->bits[0];
4247 ((uint32 *) ctx->in)[15] = ctx->bits[1];
4248
4249 lsapi_MD5Transform(ctx->buf, (uint32 *) ctx->in);
4250 byteReverse((unsigned char *) ctx->buf, 4);
4251 memmove(digest, ctx->buf, 16);
4252 memset(ctx, 0, sizeof(*ctx)); /* In case it's sensitive */
4253 }
4254
4255
4256 /* The four core functions - F1 is optimized somewhat */
4257
4258 /* #define F1(x, y, z) (x & y | ~x & z) */
4259 #define F1(x, y, z) (z ^ (x & (y ^ z)))
4260 #define F2(x, y, z) F1(z, x, y)
4261 #define F3(x, y, z) (x ^ y ^ z)
4262 #define F4(x, y, z) (y ^ (x | ~z))
4263
4264 /* This is the central step in the MD5 algorithm. */
4265 #define MD5STEP(f, w, x, y, z, data, s) \
4266 ( w += f(x, y, z) + data, w = w<<s | w>>(32-s), w += x )
4267
4268 /*
4269 * The core of the MD5 algorithm, this alters an existing MD5 hash to
4270 * reflect the addition of 16 longwords of new data. MD5Update blocks
4271 * the data and converts bytes into longwords for this routine.
4272 */
lsapi_MD5Transform(uint32 buf[4],uint32 const in[16])4273 static void lsapi_MD5Transform(uint32 buf[4], uint32 const in[16])
4274 {
4275 register uint32 a, b, c, d;
4276
4277 a = buf[0];
4278 b = buf[1];
4279 c = buf[2];
4280 d = buf[3];
4281
4282 MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7);
4283 MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12);
4284 MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17);
4285 MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22);
4286 MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7);
4287 MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12);
4288 MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17);
4289 MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22);
4290 MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7);
4291 MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12);
4292 MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17);
4293 MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22);
4294 MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7);
4295 MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12);
4296 MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17);
4297 MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22);
4298
4299 MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5);
4300 MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9);
4301 MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14);
4302 MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20);
4303 MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5);
4304 MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9);
4305 MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14);
4306 MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20);
4307 MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5);
4308 MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9);
4309 MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14);
4310 MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20);
4311 MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5);
4312 MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9);
4313 MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14);
4314 MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20);
4315
4316 MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4);
4317 MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11);
4318 MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16);
4319 MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23);
4320 MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4);
4321 MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11);
4322 MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16);
4323 MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23);
4324 MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4);
4325 MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11);
4326 MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16);
4327 MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23);
4328 MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4);
4329 MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11);
4330 MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16);
4331 MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23);
4332
4333 MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6);
4334 MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10);
4335 MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15);
4336 MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21);
4337 MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6);
4338 MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10);
4339 MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15);
4340 MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21);
4341 MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6);
4342 MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10);
4343 MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15);
4344 MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21);
4345 MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6);
4346 MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10);
4347 MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15);
4348 MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21);
4349
4350 buf[0] += a;
4351 buf[1] += b;
4352 buf[2] += c;
4353 buf[3] += d;
4354 }
4355
4356
LSAPI_Set_Restored_Parent_Pid(int pid)4357 int LSAPI_Set_Restored_Parent_Pid(int pid)
4358 {
4359 int old_ppid = s_ppid;
4360 s_restored_ppid = pid;
4361 return old_ppid;
4362 }
4363
4364
LSAPI_Inc_Req_Processed(int cnt)4365 int LSAPI_Inc_Req_Processed(int cnt)
4366 {
4367 return __atomic_add_fetch(s_global_counter, cnt, __ATOMIC_SEQ_CST);
4368 }
4369