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