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