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