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