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