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