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