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