1 /*
2  * stone.c	simple repeater
3  * Copyright(c)1995-2008 by Hiroaki Sengoku <sengoku@gcd.org>
4  * Version 1.0	Jan 28, 1995
5  * Version 1.1	Jun  7, 1995
6  * Version 1.2	Aug 20, 1995
7  * Version 1.3	Feb 16, 1996	relay UDP
8  * Version 1.5	Nov 15, 1996	for Win32
9  * Version 1.6	Jul  5, 1997	for SSL
10  * Version 1.7	Aug 20, 1997	return packet of UDP
11  * Version 1.8	Oct 18, 1997	pseudo parallel using SIGALRM
12  * Version 2.0	Nov  3, 1997	http proxy & over http
13  * Version 2.1	Nov 14, 1998	respawn & pop
14  * Version 2.2	May 25, 2003	Posix Thread, XferBufMax, no ALRM, SSL verify
15  * Version 2.3	Jan  1, 2006	LB, healthCheck, NonBlock, IPv6, sockaddr_un
16  *
17  * This program is free software; you can redistribute it and/or modify
18  * it under the terms of the GNU General Public License as published by
19  * the Free Software Foundation; either version 2, or (at your option)
20  * any later version.
21  *
22  * This program is distributed in the hope that it will be useful,
23  * but WITHOUT ANY WARRANTY; without even the implied warranty of
24  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
25  * GNU General Public License for more details.
26  *
27  * You should have received a copy of the GNU General Public License
28  * along with GNU Emacs; see the file COPYING.  If not, write to
29  * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
30  *
31  * Usage: stone [-d] [-n] [-u <max>] [-f <n>] [-a <file>] [-L <file>] [-l]
32  *              [-o <n>] [-g <n>] [-t <dir>] [-z <SSL>] [-D]
33  *              [-C <file>] [-P <command>]
34  *              <st> [-- <st>]...
35  * <st> :=  <host>:<port> <sport> [<xhost>...]
36  *        | proxy <sport> [<xhost>...]
37  *        | <host>:<port#>/http <sport> <request> [<xhost>...]
38  *        | <host>:<port#>/proxy <sport> <header> [<xhost>...]
39  * <port>  := <port#>[/udp | /ssl | /apop]
40  * <sport> := [<host>:]<port#>[/udp | /ssl | /http]
41  * <xhost> := <host>[/<mask>]
42  *
43  *     Any packets received by <sport> are passed to <host>:<port>
44  *     as long as these packets are sent from <xhost>...
45  *     if <xhost> are not given, any hosts are welcome.
46  *
47  * Make:
48  * gcc -o stone stone.c
49  * or
50  * cl -DWINDOWS stone.c /MT wsock32.lib
51  * or
52  * gcc -DWINDOWS -o stone.exe stone.c -lwsock32
53  *
54  * POP -> APOP conversion
55  * gcc -DUSE_POP -o stone stone.c md5c.c
56  * or
57  * cl -DWINDOWS -DUSE_POP stone.c md5c.c /MT wsock32.lib
58  * or
59  * gcc -DWINDOWS -DUSE_POP -o stone.exe stone.c md5c.c -lwsock32
60  *
61  * md5c.c global.h md5.h are contained in RFC1321
62  *
63  * Using OpenSSL
64  * gcc -DUSE_SSL -I/usr/local/ssl/include -o stone stone.c \
65  *               -L/usr/local/ssl/lib -lssl -lcrypto
66  * or
67  * cl -DWINDOWS -DUSE_SSL stone.c /MT wsock32.lib ssleay32.lib libeay32.lib
68  * or
69  * gcc -DWINDOWS -DUSE_SSL -o stone.exe stone.c -lwsock32 -lssl32 -leay32
70  *
71  * -DUSE_POP	  use POP -> APOP conversion
72  * -DUSE_SSL	  use OpenSSL
73  * -DCPP	  preprocessor for reading config. file
74  * -DIGN_SIGTERM  ignore SIGTERM signal
75  * -DUNIX_DAEMON  fork into background and become a UNIX Daemon
76  * -DNO_BCOPY	  without bcopy(3)
77  * -DNO_SNPRINTF  without snprintf(3)
78  * -DNO_SYSLOG	  without syslog(2)
79  * -DNO_RINDEX	  without rindex(3)
80  * -DNO_STRDUP	  without strdup(3)
81  * -DNO_THREAD	  without thread
82  * -DNO_PID_T	  without pid_t
83  * -DNO_SOCKLEN_T without socklen_t
84  * -DNO_ADDRINFO  without getaddrinfo
85  * -DNO_FAMILY_T  without sa_family_t
86  * -DADDRCACHE	  cache address used in proxy
87  * -DUSE_EPOLL	  use epoll(4) (Linux)
88  * -DPTHREAD	  use Posix Thread
89  * -DPRCTL	  use prctl(2) - operations on a process
90  * -DOS2	  OS/2 with EMX
91  * -DWINDOWS	  Windows95/98/NT
92  * -DNT_SERVICE	  WindowsNT/2000 native service
93  * -DUSE_TPROXY	  use TProxy
94  */
95 #define VERSION	"2.4"
96 static char *CVS_ID =
97 "@(#) $Id: stone.c,v 2.4.1.2 2019/02/15 07:01:05 hiroaki_sengoku Exp $";
98 
99 #include <stdio.h>
100 #include <stdlib.h>
101 #include <string.h>
102 #include <errno.h>
103 #include <sys/types.h>
104 #include <ctype.h>
105 #include <stdarg.h>
106 #include <signal.h>
107 
108 #ifdef USE_PCRE
109 #include <pcreposix.h>
110 #else
111 #include <regex.h>
112 #endif
113 
114 typedef void (*FuncPtr)(void*);
115 
116 #ifdef WINDOWS
117 #define FD_SETSIZE	4096
118 #include <process.h>
119 #include <winsock2.h>
120 #include <ws2tcpip.h>
121 #ifdef WSAEWOULDBLOCK
122 #undef EINPROGRESS
123 #define EINPROGRESS     WSAEWOULDBLOCK
124 #endif
125 #ifdef WSAEMSGSIZE
126 #undef EMSGSIZE
127 #define	EMSGSIZE	WSAEMSGSIZE
128 #endif
129 #ifdef WSAEADDRINUSE
130 #undef EADDRINUSE
131 #define	EADDRINUSE	WSAEADDRINUSE
132 #endif
133 #ifdef WSAECONNABORTED
134 #undef ECONNABORTED
135 #define	ECONNABORTED	WSAECONNABORTED
136 #endif
137 #ifdef WSAECONNRESET
138 #undef ECONNRESET
139 #define	ECONNRESET	WSAECONNRESET
140 #endif
141 #ifdef WSAEISCONN
142 #undef EISCONN
143 #define	EISCONN		WSAEISCONN
144 #endif
145 #ifdef MSG_TRUNC
146 #undef MSG_TRUNC
147 #endif
148 #include <time.h>
149 #ifdef NT_SERVICE
150 #include <windows.h>
151 #include "logmsg.h"
152 #endif
153 #define NO_SYSLOG
154 #define NO_FORK
155 #define NO_SETUID
156 #define NO_CHROOT
157 #define	NO_GETTIMEOFDAY
158 #define NO_FAMILY_T
159 #define	NO_UNIXDOMAIN
160 #define ValidSocket(sd)		((sd) != INVALID_SOCKET)
161 #define FD_SET_BUG
162 #undef EINTR
163 #define EINTR	WSAEINTR
164 #define NO_BZERO
165 #define NO_BCOPY
166 #define	usleep(usec)	Sleep(usec)
167 #define ASYNC(func,arg)	{\
168     if (Debug > 7) message(LOG_DEBUG, "ASYNC: %d", AsyncCount);\
169     waitMutex(AsyncMutex);\
170     AsyncCount++;\
171     freeMutex(AsyncMutex);\
172     if (_beginthread((FuncPtr)func, 0, arg) < 0) {\
173 	message(LOG_ERR, "_beginthread error err=%d", errno);\
174 	func(arg);\
175     }\
176 }
177 #else	/* ! WINDOWS */
178 #include <strings.h>
179 #include <pwd.h>
180 #include <sys/param.h>
181 #ifdef OS2
182 #define INCL_DOSSEMAPHORES
183 #define INCL_DOSERRORS
184 #include <process.h>
185 #include <os2.h>
186 #define NO_SYSLOG
187 #define	NO_UNIXDOMAIN
188 #define ASYNC(func,arg)	{\
189     if (Debug > 7) message(LOG_DEBUG,"ASYNC: %d",AsyncCount);\
190     waitMutex(AsyncMutex);\
191     AsyncCount++;\
192     freeMutex(AsyncMutex);\
193     if (_beginthread((FuncPtr)func,NULL,32768,arg) < 0) {\
194 	message(LOG_ERR,"_beginthread error err=%d",errno);\
195 	func(arg);\
196     }\
197 }
198 #else	/* ! WINDOWS & ! OS2 */
199 #ifdef PTHREAD
200 #include <pthread.h>
201 pthread_attr_t thread_attr;
202 typedef void *(*aync_start_routine) (void *);
203 #define ASYNC(func,arg)	{\
204     pthread_t thread;\
205     int err;\
206     if (Debug > 7) message(LOG_DEBUG,"ASYNC: %d",AsyncCount);\
207     waitMutex(AsyncMutex);\
208     AsyncCount++;\
209     freeMutex(AsyncMutex);\
210     err=pthread_create(&thread,&thread_attr,(aync_start_routine)func,arg);\
211     if (err) {\
212 	message(LOG_ERR,"pthread_create error err=%d",err);\
213 	func(arg);\
214     } else if (Debug > 7) {\
215 	message(LOG_DEBUG,"pthread ID=%lu",thread);\
216     }\
217 }
218 #else	/* ! PTHREAD */
219 #define ASYNC(func,arg)	{\
220     waitMutex(AsyncMutex);\
221     AsyncCount++;\
222     freeMutex(AsyncMutex);\
223     func(arg);\
224 }
225 #define NO_THREAD
226 #endif	/* ! PTHREAD */
227 #endif	/* ! WINDOWS & ! OS2 */
228 #include <sys/wait.h>
229 #include <sys/time.h>
230 #include <sys/socket.h>
231 #include <sys/un.h>
232 #ifdef USE_TPROXY
233 #define IP_TRANSPARENT	19
234 #define IP_ORIGDSTADDR	20
235 #endif
236 #include <netinet/in.h>
237 #include <arpa/inet.h>
238 #include <netdb.h>
239 #include <unistd.h>
240 #include <fcntl.h>
241 #include <sys/stat.h>
242 #include <time.h>
243 #ifndef NO_SETUID
244 #include <grp.h>
245 #endif
246 #ifdef PRCTL
247 #include <sys/prctl.h>
248 #endif
249 #ifdef MEMLEAK_CHECK
250 #include <mcheck.h>
251 #endif
252 typedef int SOCKET;
253 #define INVALID_SOCKET		-1
254 #define ValidSocket(sd)		((sd) >= 0)
255 #define closesocket(sd)		close(sd)
256 #endif	/* ! WINDOWS */
257 #define InvalidSocket(sd)	(!ValidSocket(sd))
258 #ifdef USE_EPOLL
259 #include <sys/epoll.h>
260 #define EVSMAX	100
261 #else
262 #ifdef FD_SET_BUG
263 int FdSetBug = 0;
264 #define FdSet(fd,set)		do{if (!FdSetBug || !FD_ISSET((fd),(set))) \
265 					FD_SET((fd),(set));}while(0)
266 #else
267 #define FdSet(fd,set)		FD_SET((fd),(set))
268 #endif
269 #endif
270 
271 #ifdef NO_THREAD
272 #define ASYNC_BEGIN		/* */
273 #define _ASYNC_END		/* */
274 #else
275 #define ASYNC_BEGIN	\
276     if (Debug > 7) message(LOG_DEBUG,"ASYNC_BEGIN: %d",AsyncCount)
277 #define _ASYNC_END	\
278     if (Debug > 7) message(LOG_DEBUG,"ASYNC_END: %d",AsyncCount);\
279     waitMutex(AsyncMutex);\
280     AsyncCount--;\
281     freeMutex(AsyncMutex)
282 #endif
283 
284 #ifdef USE_SSL
285 #include <openssl/opensslv.h>
286 #if OPENSSL_VERSION_NUMBER < 0x10100000L
287 #define ASYNC_END	\
288     _ASYNC_END;\
289     ERR_remove_state(0)
290 #else
291 #if OPENSSL_VERSION_NUMBER < 0x10101000L
292 #define ASYNC_END	\
293     _ASYNC_END;\
294     ERR_remove_thread_state(NULL)
295 #else
296 #define ASYNC_END	_ASYNC_END
297 #endif
298 #endif
299 #else
300 #define ASYNC_END	_ASYNC_END
301 #endif
302 
303 #ifdef NO_SYSLOG
304 #ifdef ANDROID
305 #include <android/log.h>
306 #define LOG_CRIT	ANDROID_LOG_FATAL
307 #define LOG_ERR		ANDROID_LOG_ERROR
308 #define LOG_WARNING	ANDROID_LOG_WARN
309 #define LOG_NOTICE	ANDROID_LOG_INFO
310 #define LOG_INFO	ANDROID_LOG_DEBUG
311 #define LOG_DEBUG	ANDROID_LOG_VERBOSE
312 #else
313 #define LOG_CRIT	2	/* critical conditions */
314 #define LOG_ERR		3	/* error conditions */
315 #define LOG_WARNING	4	/* warning conditions */
316 #define LOG_NOTICE	5	/* normal but signification condition */
317 #define LOG_INFO	6	/* informational */
318 #define LOG_DEBUG	7	/* debug-level messages */
319 #endif
320 #else	/* SYSLOG */
321 #include <syslog.h>
322 #endif
323 
324 #define BACKLOG_MAX	50
325 #define XPORT		6000
326 #define BUFMAX		2048
327 #define LONGSTRMAX	1024
328 #define STRMAX		127	/* > 38 */
329 #define CONN_TIMEOUT	60	/* 1 min */
330 #define	LB_MAX		100
331 #define	FREE_TIMEOUT	600	/* 10 min */
332 
333 #ifndef MAXHOSTNAMELEN
334 #define MAXHOSTNAMELEN	255
335 #endif
336 
337 #define TICK_SELECT	100000	/* 0.1 sec */
338 #define SPIN_MAX	10	/* 1 sec */
339 #define	NERRS_MAX	10	/* # of select errors */
340 #define	REF_UNIT	10	/* unit of pair->count */
341 
342 #ifdef USE_SSL
343 #include <openssl/crypto.h>
344 #include <openssl/x509.h>
345 #include <openssl/x509v3.h>
346 #include <openssl/ssl.h>
347 #include <openssl/bio.h>
348 #include <openssl/err.h>
349 #include <openssl/pkcs12.h>
350 #include <openssl/rand.h>
351 
352 #ifndef OPENSSL_NO_SSL2
353 #define OPENSSL_NO_SSL2
354 #endif
355 
356 #ifdef CRYPTOAPI
357 int SSL_CTX_use_CryptoAPI_certificate(SSL_CTX *ssl_ctx, const char *cert_prop);
358 int CryptoAPI_verify_certificate(X509 *x509);
359 #endif
360 
361 #define NMATCH_MAX	9	/* \1 ... \9 */
362 #define DEPTH_MAX	10
363 
364 #ifndef TLSEXT_NAMETYPE_host_name
365 #define OPENSSL_NO_TLSEXT
366 #endif
367 
368 #ifdef ANDROID
369 #include <openssl/pem.h>
370 #include "keystore_get.h"
371 #ifndef SSL_in_accept_init
372 #define SSL_in_accept_init(a) (SSL_state(a) & SSL_ST_ACCEPT)
373 #endif
374 #endif
375 
376 typedef struct {
377     int verbose;
378     int shutdown_mode;
379     int depth;
380     long serial;
381     SSL_CTX *ctx;
382     regex_t *re[DEPTH_MAX];
383     char *name;
384 #ifdef ANDROID
385     char *keystore;
386 #endif
387     unsigned char lbmod;
388     unsigned char lbparm;
389     unsigned char sslparm;
390 } StoneSSL;
391 
392 const int sslparm_ignore  = 0x01;
393 const int sslparm_storeca = 0x02;
394 const int sslparm_sni     = 0x04;
395 
396 typedef struct {
397     int verbose;
398     int shutdown_mode;
399     int mode;
400     int depth;
401     int vflags;
402     long off;
403     long serial;
404 #ifdef CONST_SSL_METHOD
405     const
406 #endif
407     SSL_METHOD *meth;
408     int (*callback)(int, X509_STORE_CTX *);
409     unsigned char *sid_ctx;
410     int useSNI;
411     char *keyFile;
412     char *certFile;
413     char *keyFilePat;
414     char *certFilePat;
415     char *caFile;
416     char *caPath;
417     char *pfxFile;
418     char *pfxFilePat;
419     char *passFile;
420     char *passFilePat;
421     char *passwd;
422     char *servername;
423     int certIgnore;
424 #ifdef CRYPTOAPI
425     int certStoreCA;
426     char *certStore;
427 #endif
428 #ifdef ANDROID
429     char *certStore;
430 #endif
431     char *cipherList;
432     char *regexp[DEPTH_MAX];
433     unsigned char lbmod;
434     unsigned char lbparm;
435 } SSLOpts;
436 
437 SSLOpts ServerOpts;
438 SSLOpts ClientOpts;
439 int PairIndex;
440 int MatchIndex;
441 int NewMatchCount = 0;
442 #ifdef WINDOWS
443 #define OPENSSL_NO_TLS1_1
444 #define OPENSSL_NO_TLS1_2
445 #include <openssl/applink.c>
446 #pragma comment(lib, "libeay32.lib")
447 #pragma comment(lib, "ssleay32.lib")
448 HANDLE *SSLMutex = NULL;
449 #else
450 #ifdef PTHREAD
451 pthread_mutex_t *SSLMutex = NULL;
452 #endif
453 #endif
454 int NSSLMutexs = 0;
455 
456 #include <openssl/md5.h>
457 #define MD5Init		MD5_Init
458 #define MD5Update	MD5_Update
459 #define MD5Final	MD5_Final
460 #else
461 #ifdef USE_POP
462 #include "global.h"
463 #include "md5.h"
464 #endif
465 #endif
466 #ifdef CPP
467 char *CppCommand = CPP;
468 char *CppOptions = NULL;
469 #endif
470 
471 #ifdef NO_ADDRINFO
472 #undef AF_INET6
473 #endif
474 #ifdef NO_SOCKLEN_T
475 typedef int socklen_t;
476 #endif
477 
478 typedef struct _Chat {
479     struct _Chat *next;
480     char *send;
481     int len;
482     regex_t expect;
483 } Chat;
484 
485 typedef struct {
486     socklen_t len;
487     struct sockaddr addr;
488 } SockAddr;
489 #define SockAddrBaseSize	((int)(long long)&((SockAddr*)NULL)->addr)
490 
491 typedef struct _XHosts {
492     struct _XHosts *next;
493     short mbits;
494     short mode;
495     SockAddr xhost;	/* must be the last member */
496 } XHosts;
497 #define XHostsBaseSize		(sizeof(XHosts) - sizeof(struct sockaddr))
498 #define XHostsMode_Dump		0xF
499 
500 typedef struct _XPorts {
501     struct _XPorts *next;
502     short from;		/* port range from */
503     short end;		/* port range to, or equals to from */
504 } XPorts;
505 
506 typedef struct _PortXHosts {
507     struct _PortXHosts *next;
508     XPorts *ports;
509     XHosts *xhosts;
510 } PortXHosts;
511 
512 typedef struct _Backup {
513     struct _Backup *next;
514     SockAddr *check;
515     /* host:port for check (usually same as master) */
516     SockAddr *master;
517     SockAddr *backup;
518     int proto;
519     Chat *chat;		/* chat script for health check */
520     short interval;	/* interval of health check */
521     short bn;		/* 0: health, 1: backup */
522     short used;		/* 0: not used, 1: assigned, 2: used */
523     time_t last;	/* last health check */
524 } Backup;
525 
526 typedef struct _LBSet {
527     struct _LBSet *next;
528     int proto;
529     short ndsts;
530     SockAddr *dsts[0];
531 } LBSet;
532 
533 #define type_mask	0x000f
534 #define type_pair	0x0001
535 #define type_origin	0x0002
536 #define type_stone	0x0003
537 #define	type_pktbuf	0x0004
538 
539 typedef struct _Stone {
540     int common;
541     SOCKET sd;			/* socket descriptor to listen */
542     int port;
543     SockAddr *listen;
544     short ndsts;		/* # of destinations */
545     SockAddr **dsts;		/* destinations */
546     SockAddr *from;
547     int proto;
548     Backup **backups;
549     struct _Pair *pairs;
550     char *p;
551     int timeout;
552     struct _Stone *next;
553     struct _Stone *children;
554     struct _Stone *parent;
555 #ifdef USE_SSL
556     StoneSSL *ssl_server;
557     StoneSSL *ssl_client;
558 #endif
559     int nhosts;			/* # of hosts */
560     XHosts *xhosts;		/* hosts permitted to connect */
561 } Stone;
562 
563 typedef struct _TimeLog {
564     time_t clock;		/* time of beginning */
565     int pri;			/* log priority */
566     char str[0];		/* Log message */
567 } TimeLog;
568 
569 const int data_parm_mask =	0x00ff;
570 const int data_apop =		0x0100;
571 const int data_identuser =	0x0200;
572 const int data_ucred =		0x0300;
573 const int data_peeraddr = 	0x0400;
574 
575 #define DATA_HEAD_LEN	sizeof(int)
576 
577 typedef struct _ExBuf {	/* extensible buffer */
578     struct _ExBuf *next;
579     int start;		/* index of buf */
580     int len;		/* last data is at buf[start+len-1] */
581     int bufmax;		/* buffer size */
582     char buf[BUFMAX];
583 } ExBuf;
584 
585 typedef struct _Pair {
586     int common;
587     struct _Pair *pair;
588     struct _Pair *prev;
589     struct _Pair *next;
590     Stone *stone;	/* parent */
591 #ifdef USE_SSL
592     SSL *ssl;		/* SSL handle */
593     int ssl_flag;
594 #endif
595     XHosts *xhost;
596     time_t clock;
597     int timeout;
598     SOCKET sd;		/* socket descriptor */
599     int proto;
600     int count;		/* reference counter */
601     ExBuf *d;
602     TimeLog *log;
603     int tx;		/* sent bytes */
604     int rx;		/* received bytes */
605     int loop;		/* loop count */
606     int nbuf;
607     ExBuf *t;	/* top */
608     ExBuf *b;	/* bottom */
609 } Pair;
610 
611 typedef struct _Conn {
612     SockAddr *dst;	/* destination */
613     Pair *pair;
614     int lock;
615     struct _Conn *next;
616 } Conn;
617 
618 typedef struct _Origin {
619     int common;
620     SOCKET sd;		/* peer */
621     Stone *stone;
622     SockAddr *from;	/* from where */
623     int lock;
624     XHosts *xhost;
625     time_t clock;
626     struct _Origin *next;
627 } Origin;
628 
629 typedef struct _PktBuf {	/* packet buffer */
630     int common;
631     struct _PktBuf *next;
632     int type;
633     Origin *origin;
634     int len;
635     int bufmax;		/* buffer size */
636     char buf[BUFMAX];
637 } PktBuf;
638 
639 typedef struct _Comm {
640     char *str;
641     int (*func)(Pair*, char*, int);
642 } Comm;
643 
644 Stone *stones = NULL;
645 Stone *oldstones = NULL;
646 int ReuseAddr = 0;
647 PortXHosts *portXHosts = NULL;
648 XHosts *XHostsTrue = NULL;
649 Chat *healthChat = NULL;
650 Backup *backups = NULL;
651 LBSet *lbsets = NULL;
652 int MinInterval = 0;
653 time_t lastScanBackups = 0;
654 time_t lastEstablished = 0;
655 time_t lastReadWrite = 0;
656 Pair *PairTop = NULL;
657 Pair trash;
658 Pair *freePairs = NULL;
659 int nFreePairs = 0;
660 ExBuf *freeExBuf = NULL;
661 int nFreeExBuf = 0;
662 ExBuf *freeExBot = NULL;
663 int nFreeExBot = 0;
664 time_t freeExBotClock = 0;
665 Conn conns;
666 Origin *OriginTop = NULL;
667 int OriginMax = 100;
668 PktBuf *freePktBuf = NULL;
669 int nFreePktBuf = 0;
670 #ifdef USE_EPOLL
671 int ePollFd;
672 #else
673 fd_set rin, win, ein;
674 #endif
675 int PairTimeOut = 10 * 60;	/* 10 min */
676 int AsyncCount = 0;
677 int MutexConflict = 0;
678 
679 const int state_mask =		    0x00ff;
680 const int proto_command =	    0x0f00;	/* command (dest. only) */
681 						/* only for Stone */
682 const int proto_ident =		    0x1000;	  /* need ident */
683 const int proto_nobackup =	    0x2000;	  /* no backup */
684 const int proto_udp_s =		    0x4000;	  /* UDP source */
685 const int proto_udp_d =		    0x8000;	  /*     destination */
686 const int proto_v6_s =		   0x10000;	  /* IPv6 source */
687 const int proto_v6_d =		   0x20000;	  /*      destination */
688 const int proto_ip_only_s =	   0x40000;	  /* IPv6 only source */
689 const int proto_ip_only_d =	   0x80000;	  /*           destination */
690 const int proto_unix_s =	  0x100000;       /* unix socket source */
691 const int proto_unix_d =	  0x200000;	  /*             destination */
692 const int proto_block_s =	  0x400000;	  /* blocking I/O source */
693 const int proto_block_d =	  0x800000;	  /*              destination*/
694 const int proto_ssl_s =		 0x1000000;	  /* SSL source */
695 const int proto_ssl_d =		 0x2000000;	  /*     destination */
696 						/* only for Pair */
697 const int proto_dirty =		    0x1000;	  /* ev must be updated */
698 const int proto_noconnect =	    0x2000;	  /* no connection needed */
699 const int proto_connect =	    0x4000;	  /* connection established */
700 const int proto_dgram =		    0x8000;	  /* UDP */
701 const int proto_first_r =	   0x10000;	  /* first read packet */
702 const int proto_first_w =	   0x20000;	  /* first written packet */
703 const int proto_select_r =	   0x40000;	  /* select to read */
704 const int proto_select_w =	   0x80000;	  /* select to write */
705 const int proto_shutdown =	  0x100000;	  /* sent shutdown */
706 const int proto_close =	  	  0x200000;	  /* request to close */
707 const int proto_eof =		  0x400000;	  /* EOF was received */
708 const int proto_error =		  0x800000;	  /* error reported */
709 #ifndef USE_EPOLL
710 const int proto_thread =	 0x1000000;	  /* on thread */
711 #endif
712 const int proto_conninprog =	 0x2000000;	  /* connect in progress */
713 const int proto_ohttp_s =	 0x4000000;	/* over http source */
714 const int proto_ohttp_d =	 0x8000000;	/*           destination */
715 const int proto_base_s =	0x10000000;	/* base64 source */
716 const int proto_base_d =	0x20000000;	/*        destination */
717 #define command_ihead		    0x0100	/* insert header */
718 #define command_iheads		    0x0200	/* insert header repeatedly */
719 #define command_pop		    0x0300	/* POP -> APOP conversion */
720 #define command_health		    0x0400	/* is stone healthy ? */
721 #define command_identd		    0x0500	/* identd of stone */
722 #define command_proxy		    0x0600	/* http proxy */
723 #define command_source		    0x0f00	/* source flag */
724 
725 #define proto_ssl	(proto_ssl_s|proto_ssl_d)
726 #define proto_v6	(proto_v6_s|proto_v6_d)
727 #define proto_udp	(proto_udp_s|proto_udp_d)
728 #define proto_ip_only	(proto_ip_only_s|proto_ip_only_d)
729 #define proto_unix	(proto_unix_s|proto_unix_d)
730 #define proto_block	(proto_block_s|proto_block_d)
731 #define proto_ohttp	(proto_ohttp_s|proto_ohttp_d)
732 #define proto_base	(proto_base_s|proto_base_d)
733 #define proto_stone_s	(proto_udp_s|proto_command|\
734 			 proto_ohttp_s|proto_base_s|\
735 			 proto_v6_s|proto_ip_only_s|\
736 			 proto_ssl_s|proto_ident)
737 #define proto_stone_d	(proto_udp_d|proto_command|\
738 			 proto_ohttp_d|proto_base_d|\
739 			 proto_v6_d|proto_ip_only_d|\
740 			 proto_ssl_d|proto_nobackup)
741 #define proto_pair_s	(proto_ohttp_s|proto_base_s)
742 #define proto_pair_d	(proto_ohttp_d|proto_base_d|proto_command)
743 
744 #ifdef USE_SSL
745 const int sf_mask    =  0x0000f;
746 const int sf_depth   =	0x000f0;	/* depth of cert chain */
747 const int sf_depth_bit = 4;
748 const int sf_sb_on_r =  0x00100;	/* SSL_shutdown blocked on read */
749 const int sf_sb_on_w =  0x00200;	/* SSL_shutdown blocked on write */
750 const int sf_wb_on_r =	0x00400;	/* SSL_write blocked on read */
751 const int sf_rb_on_w =	0x00800;	/* SSL_read  blocked on write */
752 const int sf_cb_on_r =  0x01000;	/* SSL_connect blocked on read */
753 const int sf_cb_on_w =  0x02000;	/* SSL_connect blocked on write */
754 const int sf_ab_on_r =  0x04000;	/* SSL_accept blocked on read */
755 const int sf_ab_on_w =  0x08000;	/* SSL_accept blocked on write */
756 #endif
757 
758 int BacklogMax = BACKLOG_MAX;
759 int XferBufMax = 1000;	/* TCP packet buffer initial size (must < 1024 ?) */
760 #define PKT_LEN_INI		2048	/* initial size */
761 int pkt_len_max = PKT_LEN_INI;	/* size of UDP packet buffer */
762 int AddrFlag = 0;
763 #ifndef NO_SYSLOG
764 int Syslog = 0;
765 char SyslogName[STRMAX+1];
766 #elif defined(ANDROID)
767 int Syslog = 0;
768 #endif
769 FILE *LogFp = NULL;
770 char *LogFileName = NULL;
771 FILE *AccFp = NULL;
772 char *AccFileName = NULL;
773 char *ConfigFile = NULL;
774 char *PidFile = NULL;
775 SockAddr *ConnectFrom = NULL;
776 
777 int DryRun = 0;
778 int ConfigArgc = 0;
779 int OldConfigArgc = 0;
780 char **ConfigArgv = NULL;
781 char **OldConfigArgv = NULL;
782 #ifdef UNIX_DAEMON
783 int DaemonMode = 0;
784 #endif
785 #ifndef NO_CHROOT
786 char *RootDir = NULL;
787 #endif
788 #ifndef NO_SETUID
789 uid_t SetUID = 0;
790 gid_t SetGID = 0;
791 #endif
792 char *CoreDumpDir = NULL;
793 #ifdef NO_PID_T
794 typedef int pid_t;
795 #endif
796 pid_t MyPid;
797 #ifndef NO_FORK
798 int NForks = 0;
799 pid_t *Pid;
800 #endif
801 int Debug = 0;		/* debugging level */
802 
803 #ifdef ADDRCACHE
804 #define	CACHE_TIMEOUT	180	/* 3 min */
805 int AddrCacheSize = 0;
806 #endif
807 #ifdef PTHREAD
808 pthread_mutex_t FastMutex = PTHREAD_MUTEX_INITIALIZER;
809 char FastMutexs[11];
810 #define PairMutex	0
811 #define ConnMutex	1
812 #define OrigMutex	2
813 #define AsyncMutex	3
814 #ifndef USE_EPOLL
815 #define FdRinMutex	4
816 #define FdWinMutex	5
817 #define FdEinMutex	6
818 #endif
819 #define ExBufMutex	7
820 #define FPairMutex	8
821 #define	PkBufMutex	9
822 #ifdef ADDRCACHE
823 #define	HashMutex	10
824 #endif
825 #endif
826 #ifdef WINDOWS
827 HANDLE PairMutex, ConnMutex, OrigMutex, AsyncMutex;
828 HANDLE FdRinMutex, FdWinMutex, FdEinMutex;
829 HANDLE ExBufMutex, FPairMutex, PkBufMutex;
830 #ifdef ADDRCACHE
831 HANDLE HashMutex;
832 #endif
833 #endif
834 #ifdef OS2
835 HMTX PairMutex, ConnMutex, OrigMutex, AsyncMutex;
836 HMTX FdRinMutex, FdWinMutex, FdEinMutex;
837 HMTX ExBufMutex, FPairMutex, PkBufMutex;
838 #ifdef ADDRCACHE
839 HMTX HashMutex;
840 #endif
841 #endif
842 
843 #ifdef NT_SERVICE
844 SERVICE_STATUS NTServiceStatus;
845 SERVICE_STATUS_HANDLE NTServiceStatusHandle;
846 #define NTServiceDisplayPrefix	"Stone "
847 char *NTServiceDisplayName = NULL;
848 char *NTServiceName = NULL;
849 HANDLE NTServiceLog = NULL;
850 HANDLE NTServiceThreadHandle = NULL;
851 #endif
852 
853 #ifdef NO_VSNPRINTF
vsnprintf(char * str,size_t len,const char * fmt,va_list ap)854 int vsnprintf(char *str, size_t len, const char *fmt, va_list ap) {
855     int ret;
856     ret = vsprintf(str, fmt, ap);
857     if (strlen(str) >= len) {
858 	fprintf(stderr, "Buffer overrun\n");
859 	exit(1);
860     }
861     return ret;
862 }
863 #endif
864 
865 #ifdef NO_SNPRINTF
snprintf(char * str,size_t len,char * fmt,...)866 int snprintf(char *str, size_t len, char *fmt, ...) {
867     va_list ap;
868     int ret;
869     va_start(ap, fmt);
870     ret = vsnprintf(str, len, fmt, ap);
871     va_end(ap);
872     return ret;
873 }
874 #endif
875 
876 #ifdef NO_BZERO
877 #define bzero(b,n)	memset(b,0,n)
878 #endif
879 
880 #ifdef NO_BCOPY
bcopy(const void * b1,void * b2,int len)881 void bcopy(const void *b1, void *b2, int len) {
882     if (b1 < b2 && (char*)b2 < (char*)b1 + len) {	/* overlapping */
883 	char *p, *q;
884 	q = (char*)b2 + len - 1;
885 	for (p=(char*)b1+len-1; (char*)b1 <= p; p--, q--) *q = *p;
886     } else {
887 	memcpy(b2, b1, len);
888     }
889 }
890 #endif
891 
892 #ifdef NO_RINDEX
rindex(const char * p,int ch)893 char *rindex(const char *p, int ch) {
894     const char *save = NULL;
895     do {
896 	if (*p == ch) save = p;
897     } while (*p++);
898     return (char*)save;
899 }
900 #endif
901 
902 #ifdef NO_STRDUP
strdup(const char * s)903 char *strdup(const char *s) {
904     int len = strlen(s);
905     char *ret = malloc(len+1);
906     if (ret) {
907 	bcopy(s, ret, len+1);
908     }
909     return ret;
910 }
911 #endif
912 
913 #ifdef WINDOWS
localtime_r(const time_t * clock,struct tm * t)914 struct tm *localtime_r(const time_t *clock, struct tm *t) {
915     FILETIME utc, local;
916     SYSTEMTIME system;
917     LONGLONG ll;
918     ll = Int32x32To64(*clock, 10000000) + 116444736000000000ULL;
919     utc.dwLowDateTime = (DWORD)ll;
920     utc.dwHighDateTime = ll >> 32;
921     if (!FileTimeToLocalFileTime(&utc, &local)) return NULL;
922     if (!FileTimeToSystemTime(&local, &system)) return NULL;
923     t->tm_sec = system.wSecond;
924     t->tm_min = system.wMinute;
925     t->tm_hour = system.wHour;
926     t->tm_mday = system.wDay;
927     t->tm_mon = system.wMonth-1;
928     t->tm_year = system.wYear-1900;
929     t->tm_wday = system.wDayOfWeek;
930     return t;
931 }
932 #endif
933 
934 static char Month[][4] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun",
935 			  "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
936 
strntime(char * str,int len,time_t * clock,long micro)937 char *strntime(char *str, int len, time_t *clock, long micro) {
938 #ifdef THREAD_UNSAFE
939     struct tm *t = localtime(clock);
940 #else
941     struct tm tm;
942     struct tm *t = localtime_r(clock, &tm);
943 #endif
944     if (micro >= 0) {
945 	snprintf(str, len, "%s %2d %02d:%02d:%02d.%06ld ",
946 		 Month[t->tm_mon], t->tm_mday,
947 		 t->tm_hour, t->tm_min, t->tm_sec, micro);
948     } else {
949 	snprintf(str, len, "%s %2d %02d:%02d:%02d ",
950 		 Month[t->tm_mon], t->tm_mday,
951 		 t->tm_hour, t->tm_min, t->tm_sec);
952     }
953     return str;
954 }
955 
956 #ifdef NO_GETTIMEOFDAY
gettimeofday(struct timeval * tv,void * tz)957 int gettimeofday(struct timeval *tv, void *tz) {
958     static u_long start = 0;
959     u_long tick = GetTickCount();
960     time_t now;
961     time(&now);
962     if (start == 0) start = now - tick / 1000;
963     if (tz) return -1;
964     if (tv) {
965 	tv->tv_usec = (tick % 1000) * 1000;
966 	tv->tv_sec = start + (tick / 1000);
967 	if (now < tv->tv_sec - 1 || tv->tv_sec + 1 < now) {
968 	    start = 0;
969 	    tv->tv_usec = -1;	/* diff is too large */
970 	}
971 	return 0;
972     }
973     return -1;
974 }
975 #endif
976 
977 #if defined (__STDC__) && __STDC__
978 void message(int pri, char *fmt, ...)
979     __attribute__ ((__format__ (__printf__, 2, 3)));
980 #endif
981 
message(int pri,char * fmt,...)982 void message(int pri, char *fmt, ...) {
983     char str[LONGSTRMAX+1];
984     int pos = 0;
985     unsigned long thid = 0;
986     va_list ap;
987 #if !defined(NO_SYSLOG) || defined(ANDROID)
988     if (!Syslog)
989 #endif
990     {
991 	struct timeval tv;
992 	if (gettimeofday(&tv, NULL) >= 0) {
993 	    strntime(str+pos, LONGSTRMAX-pos, (time_t*)&tv.tv_sec, tv.tv_usec);
994 	}
995 	str[LONGSTRMAX] = '\0';
996 	pos = strlen(str);
997     }
998 #ifdef WINDOWS
999     thid = (unsigned long)GetCurrentThreadId();
1000 #else
1001 #ifdef PTHREAD
1002     thid = (unsigned long)pthread_self();
1003 #endif
1004 #endif
1005     if (thid) {
1006 	snprintf(str+pos, LONGSTRMAX-pos, "%lu ", thid);
1007 	pos += strlen(str+pos);
1008     }
1009     va_start(ap, fmt);
1010     vsnprintf(str+pos, LONGSTRMAX-pos, fmt, ap);
1011     va_end(ap);
1012     str[LONGSTRMAX] = '\0';
1013 #ifndef NO_SYSLOG
1014     if (Syslog) {
1015 	if (Syslog == 1
1016 	    || pri != LOG_DEBUG) syslog(pri, "%s", str);
1017 	if (Syslog > 1) fprintf(stdout, "%s\n", str);	/* daemontools */
1018     } else
1019 #elif defined(ANDROID)
1020     if (Syslog) {
1021 	if (Syslog == 1
1022 	    || pri != LOG_DEBUG) __android_log_write(pri, "stone", str);
1023 	if (Syslog > 1) fprintf(stdout, "%s\n", str);	/* daemontools */
1024     } else
1025 #elif defined(NT_SERVICE)
1026     if (NTServiceLog) {
1027 	LPCTSTR msgs[] = {str, NULL};
1028 	int type = EVENTLOG_INFORMATION_TYPE;
1029 	if (pri <= LOG_ERR) type = EVENTLOG_ERROR_TYPE;
1030 	else if (pri <= LOG_NOTICE) type = EVENTLOG_WARNING_TYPE;
1031 	ReportEvent(NTServiceLog, type, 0, EVLOG, NULL, 1, 0, msgs, NULL);
1032     } else
1033 #endif
1034     if (LogFp) fprintf(LogFp, "%s\n", str);
1035 }
1036 
message_time(Pair * pair,int pri,char * fmt,...)1037 void message_time(Pair *pair, int pri, char *fmt, ...) {
1038     va_list ap;
1039     char str[LONGSTRMAX+1];
1040     TimeLog *log;
1041     log = pair->log;
1042     if (log) {
1043 	pair->log = NULL;
1044 	free(log);
1045     }
1046     va_start(ap, fmt);
1047     vsnprintf(str, LONGSTRMAX, fmt, ap);
1048     va_end(ap);
1049     str[LONGSTRMAX] = '\0';
1050     log = (TimeLog*)malloc(sizeof(TimeLog)+strlen(str)+1);
1051     if (log) {
1052 	time(&log->clock);
1053 	log->pri = pri;
1054 	strcpy(log->str, str);
1055 	pair->log = log;
1056     }
1057 }
1058 
priority(Pair * pair)1059 int priority(Pair *pair) {
1060     int pri = LOG_ERR;
1061     if (pair) {
1062 	if (pair->proto & proto_error) pri = LOG_DEBUG;
1063 	else pair->proto |= proto_error;
1064     }
1065     return pri;
1066 }
1067 
packet_dump(char * head,char * buf,int len,XHosts * xhost)1068 void packet_dump(char *head, char *buf, int len, XHosts *xhost) {
1069     char line[LONGSTRMAX+1];
1070     int mode = (xhost->mode & XHostsMode_Dump);
1071     int i, j, k, l;
1072     int nb = 8;
1073     j = k = l = 0;
1074     for (i=0; i < len; i += j) {
1075 	if (mode <= 2) {
1076 	    nb = 16;
1077 	    l = 0;
1078 	    line[l++] = ' ';
1079 	    for (j=0; k <= j/10 && i+j < len && l < LONGSTRMAX-10; j++) {
1080 		if (' ' <= buf[i+j] && buf[i+j] <= '~')
1081 		    line[l++] = buf[i+j];
1082 		else {
1083 		    sprintf(&line[l], "<%02x>", buf[i+j]);
1084 		    l += strlen(&line[l]);
1085 		    if (buf[i+j] == '\n') {
1086 			k = 0;
1087 			j++;
1088 			break;
1089 		    }
1090 		    if (buf[i+j] != '\t' && buf[i+j] != '\r'
1091 			&& buf[i+j] != '\033')
1092 			k++;
1093 		}
1094 	    }
1095 	}
1096 	if (k > j/10 || nb < 16) {
1097 	    j = l = 0;
1098 	    for (j=0; j < nb && i+j < len; j++) {
1099 		if (mode == 1 && (' ' <= buf[i+j] && buf[i+j] <= '~')) {
1100 		    sprintf(&line[l], " '%c", buf[i+j]);
1101 		} else {
1102 		    sprintf(&line[l], " %02x", (unsigned char)buf[i+j]);
1103 		    if (buf[i+j] == '\n') k = 0; else k++;
1104 		}
1105 		l += strlen(&line[l]);
1106 	    }
1107 	    if (nb < 16) {
1108 		while (l < (nb * 3) + 2) line[l++] = ' ';
1109 		for (j=0; j < nb && i+j < len; j++) {
1110 		    if (' ' <= buf[i+j] && buf[i+j] <= '~')
1111 			line[l++] = buf[i+j];
1112 		    else
1113 			line[l++] = '.';
1114 		}
1115 	    }
1116 	}
1117 	line[l] = '\0';
1118 	message(LOG_DEBUG, "%s%s", head, line);
1119     }
1120 }
1121 
message_buf(Pair * pair,int len,char * str)1122 void message_buf(Pair *pair, int len, char *str) {	/* dump for debug */
1123     char head[STRMAX+1];
1124     Pair *p = pair->pair;
1125     if (p == NULL) return;
1126     head[STRMAX] = '\0';
1127     if ((pair->proto & proto_command) == command_source) {
1128 	snprintf(head, STRMAX, "%d %s%d<%d",
1129 		 (int)pair->stone->sd, str, (int)pair->sd, (int)p->sd);
1130     } else {
1131 	snprintf(head, STRMAX, "%d %s%d>%d",
1132 		 (int)pair->stone->sd, str, (int)p->sd, (int)pair->sd);
1133     }
1134     packet_dump(head, pair->t->buf + pair->t->start, len, pair->xhost);
1135 }
1136 
addr2ip(struct in_addr * addr,char * str,int len)1137 char *addr2ip(struct in_addr *addr, char *str, int len) {
1138     union {
1139 	u_long	l;
1140 	unsigned char	c[4];
1141     } u;
1142     if (len >= 1) {
1143 	u.l = addr->s_addr;
1144 	snprintf(str, len-1, "%d.%d.%d.%d", u.c[0], u.c[1], u.c[2], u.c[3]);
1145 	str[len-1] = '\0';
1146     }
1147     return str;
1148 }
1149 
1150 #ifdef AF_INET6
addr2ip6(struct in6_addr * addr,char * str,int len)1151 char *addr2ip6(struct in6_addr *addr, char *str, int len) {
1152     u_short *s;
1153     if (len >= 1) {
1154 	s = (u_short*)addr;
1155 	snprintf(str, len-1, "%x:%x:%x:%x:%x:%x:%x:%x",
1156 		 ntohs(s[0]), ntohs(s[1]), ntohs(s[2]), ntohs(s[3]),
1157 		 ntohs(s[4]), ntohs(s[5]), ntohs(s[6]), ntohs(s[7]));
1158 	str[len-1] = '\0';
1159     }
1160     return str;
1161 }
1162 #endif
1163 
addr2numeric(struct sockaddr * sa,char * str,int len)1164 char *addr2numeric(struct sockaddr *sa, char *str, int len) {
1165     if (sa->sa_family == AF_INET) {
1166 	addr2ip(&((struct sockaddr_in*)sa)->sin_addr, str, len);
1167 #ifdef AF_INET6
1168     } else if (sa->sa_family == AF_INET6) {
1169 	addr2ip6(&((struct sockaddr_in6*)sa)->sin6_addr, str, len);
1170 #endif
1171     } else {
1172 	snprintf(str, len, "%s", "???");
1173     }
1174     return str;
1175 }
1176 
ext2str(int ext,char * str,int len)1177 char *ext2str(int ext, char *str, int len) {
1178     char sep = '/';
1179     int i = 0;
1180     if (!str || len <= 1) return "";
1181     if (ext & proto_udp) {
1182 	if (i < len) str[i++] = sep;
1183 	sep = ',';
1184 	strncpy(str+i, "udp", len-i);
1185 	i += 3;
1186     }
1187     if (ext & proto_ohttp) {
1188 	if (i < len) str[i++] = sep;
1189 	sep = ',';
1190 	strncpy(str+i, "http", len-i);
1191 	i += 4;
1192     }
1193     if (ext & proto_ssl) {
1194 	if (i < len) str[i++] = sep;
1195 	sep = ',';
1196 	strncpy(str+i, "ssl", len-i);
1197 	i += 3;
1198     }
1199     if (ext & proto_v6) {
1200 	if (i < len) str[i++] = sep;
1201 	sep = ',';
1202 	if (ext & proto_ip_only) {
1203 	    strncpy(str+i, "v6only", len-i);
1204 	    i += 6;
1205 	} else {
1206 	    strncpy(str+i, "v6", len-i);
1207 	    i += 2;
1208 	}
1209     } else if (ext & proto_ip_only) {
1210 	sep = ',';
1211 	strncpy(str+i, "v4only", len-i);
1212 	i += 6;
1213     }
1214     if (ext & proto_base) {
1215 	if (i < len) str[i++] = sep;
1216 	sep = ',';
1217 	strncpy(str+i, "base", len-i);
1218 	i += 4;
1219     }
1220     if (ext & proto_block) {
1221 	if (i < len) str[i++] = sep;
1222 	sep = ',';
1223 	strncpy(str+i, "block", len-i);
1224 	i += 5;
1225     }
1226     if (ext & proto_ident) {
1227 	if (i < len) str[i++] = sep;
1228 	sep = ',';
1229 	strncpy(str+i, "ident", len-i);
1230 	i += 5;
1231     }
1232     if (ext & proto_nobackup) {
1233 	if (i < len) str[i++] = sep;
1234 	sep = ',';
1235 	strncpy(str+i, "nobackup", len-i);
1236 	i += 8;
1237     }
1238     switch(ext & proto_command) {
1239     case command_ihead:
1240 	if (i < len) str[i++] = sep;
1241 	sep = ',';
1242 	strncpy(str+i, "proxy", len-i);
1243 	i += 5;
1244 	break;
1245     case command_iheads:
1246 	if (i < len) str[i++] = sep;
1247 	sep = ',';
1248 	strncpy(str+i, "mproxy", len-i);
1249 	i += 6;
1250 	break;
1251     case command_pop:
1252 	if (i < len) str[i++] = sep;
1253 	sep = ',';
1254 	strncpy(str+i, "apop", len-i);
1255 	i += 4;
1256 	break;
1257     }
1258     return str;
1259 }
1260 
islocalhost(struct sockaddr * sa)1261 int islocalhost(struct sockaddr *sa) {
1262     if (sa->sa_family == AF_INET) {
1263 	if (ntohl(((struct sockaddr_in*)sa)->sin_addr.s_addr) == 0x7F000001L)
1264 	    return 1;	/* localhost */
1265 	if (ntohl(((struct sockaddr_in*)sa)->sin_addr.s_addr) == 0L)
1266 	    return -1;	/* null */
1267     }
1268 #ifdef AF_INET6
1269     if (sa->sa_family == AF_INET6) {
1270 	int i;
1271 	struct in6_addr *addrp = &((struct sockaddr_in6*)sa)->sin6_addr;
1272 	for (i=0; i < 12; i+=4)
1273 	    if (*(u_long*)&addrp->s6_addr[i] != 0) return 0;
1274 	if (*(u_long*)&addrp->s6_addr[i] == ntohl(1)) return 1;	/* localhost */
1275 	if (*(u_long*)&addrp->s6_addr[i] == 0) return -1;	/* null */
1276     }
1277 #endif
1278     return 0;
1279 }
1280 
1281 #ifdef NO_ADDRINFO
1282 #define NTRY_MAX	10
1283 #ifndef NI_NUMERICHOST
1284 #define NI_NUMERICHOST	1
1285 #endif
1286 
addr2str(struct sockaddr * sa,socklen_t salen,char * str,int len,int flags)1287 char *addr2str(struct sockaddr *sa, socklen_t salen,
1288 	       char *str, int len, int flags) {
1289     struct hostent *ent;
1290     struct in_addr *addr;
1291     int ntry = NTRY_MAX;
1292     if (!str || len <= 1) return "";
1293     str[len-1] = '\0';
1294     if (sa->sa_family != AF_INET) {
1295 	message(LOG_ERR, "Unknown family=%d", sa->sa_family);
1296 	strncpy(str, "?.?.?.?", len-1);
1297 	return str;
1298     }
1299     addr = &((struct sockaddr_in*)sa)->sin_addr;
1300     addr2ip(addr, str, len);
1301     if (!AddrFlag || flags) {
1302 	do {
1303 	    ent = gethostbyaddr((char*)&addr->s_addr,
1304 				sizeof(addr->s_addr), AF_INET);
1305 	    if (ent) {
1306 		strncpy(str, ent->h_name, len-1);
1307 		return str;
1308 	    }
1309 	} while (h_errno == TRY_AGAIN && ntry-- > 0);
1310 	message(LOG_ERR, "Unknown address: %s err=%d", str, h_errno);
1311     }
1312     return str;
1313 }
1314 
addrport2str(struct sockaddr * sa,socklen_t salen,int proto,char * str,int len,int flags)1315 char *addrport2str(struct sockaddr *sa, socklen_t salen,
1316 		   int proto, char *str, int len, int flags) {
1317     struct servent *ent;
1318     int port;
1319     int i = 0;
1320     if (!str || len <= 1) return "";
1321     str[len-1] = '\0';
1322     if (sa->sa_family == AF_INET) {
1323 	addr2str(sa, salen, str, len, 0);
1324 	i = strlen(str);
1325 	if (i < len-2) {
1326 	    str[i++] = ':';
1327 	    str[i] = '\0';
1328 	}
1329     } else {
1330 	message(LOG_ERR, "Unknown address family=%d len=%d",
1331 		sa->sa_family, salen);
1332     }
1333     port = ((struct sockaddr_in*)sa)->sin_port;
1334     if (!AddrFlag) {
1335 	ent = getservbyport(port, ((proto & proto_udp) ? "udp" : "tcp"));
1336 	if (ent) strncpy(str+i, ent->s_name, len-i-5);
1337     }
1338     if (str[i] == '\0')
1339 	snprintf(str+i, len-i-5, "%d", ntohs((unsigned short)port));
1340     i = strlen(str);
1341     ext2str(proto, str+i, len-i);
1342     return str;
1343 }
1344 #else
addr2str(struct sockaddr * sa,socklen_t salen,char * str,int len,int flags)1345 char *addr2str(struct sockaddr *sa, socklen_t salen,
1346 	       char *str, int len, int flags) {
1347     int err;
1348     if (AddrFlag) flags |= NI_NUMERICHOST;
1349     err = getnameinfo(sa, salen, str, len, NULL, 0, flags);
1350     if (err) {
1351 #ifdef WINDOWS
1352 	errno = WSAGetLastError();
1353 #endif
1354 	addr2numeric(sa, str, len);
1355 	if (len >= 1) str[len-1] = '\0';
1356 	message(LOG_ERR, "Unknown address: %s err=%d errno=%d",
1357 		str, err, errno);
1358     }
1359     return str;
1360 }
1361 
addrport2str(struct sockaddr * sa,socklen_t salen,int proto,char * str,int len,int flags)1362 char *addrport2str(struct sockaddr *sa, socklen_t salen,
1363 		   int proto, char *str, int len, int flags) {
1364     char serv[STRMAX+1];
1365     int err;
1366     int i;
1367     if (!str || len <= 1) return "";
1368     str[len-1] = '\0';
1369     serv[0] = '\0';
1370     if (AddrFlag) flags |= (NI_NUMERICHOST | NI_NUMERICSERV);
1371     else if (proto & proto_udp) flags |= NI_DGRAM;
1372     if (!(flags & NI_NUMERICHOST) && islocalhost(sa)) flags |= NI_NUMERICHOST;
1373     if (Debug > 10) {
1374 	addr2numeric(sa, serv, STRMAX);
1375 	serv[STRMAX] = '\0';
1376 	message(LOG_DEBUG, "getnameinfo: %s family=%d len=%d flags=%d",
1377 		serv, sa->sa_family, salen, flags);
1378     }
1379 #ifndef NO_UNIXDOMAIN
1380     if (sa->sa_family == AF_UNIX) {
1381 	int j;
1382 	j = salen - (((struct sockaddr_un*)sa)->sun_path - (char*)sa);
1383 	strncpy(serv, ((struct sockaddr_un*)sa)->sun_path, j);
1384 	serv[j] = '\0';
1385 	snprintf(str, len, "%s", "unix");
1386 	err = 0;
1387     } else
1388 #endif
1389 	err = getnameinfo(sa, salen, str, len, serv, STRMAX, flags);
1390 #ifdef WSANO_DATA
1391     if (err == WSANO_DATA && !(flags & NI_NUMERICSERV)) {
1392 	/*
1393 	  WinSock32 returns WSANO_DATA if serv can't be lookup although
1394 	  the hostname itself is resolvable.  So we must call again
1395 	  without looking up serv
1396 	*/
1397 	if (Debug > 10)
1398 	    message(LOG_DEBUG, "getnameinfo: WSANO_DATA flags=%d", flags);
1399 	flags |= NI_NUMERICSERV;
1400 	err = getnameinfo(sa, salen, str, len, serv, STRMAX, flags);
1401     }
1402 #endif
1403     if (err) {
1404 	if (sa->sa_family == AF_INET) {
1405 	    addr2ip(&((struct sockaddr_in*)sa)->sin_addr, str, len);
1406 	    i = strlen(str);
1407 	    snprintf(str+i, len-i-5, ":%d",
1408 		     ntohs(((struct sockaddr_in*)sa)->sin_port));
1409 #ifdef AF_INET6
1410 	} else if (sa->sa_family == AF_INET6) {
1411 	    addr2ip6(&((struct sockaddr_in6*)sa)->sin6_addr, str, len);
1412 	    i = strlen(str);
1413 	    snprintf(str+i, len-i-5, ":%d",
1414 		     ntohs(((struct sockaddr_in6*)sa)->sin6_port));
1415 #endif
1416 	} else {
1417 	    snprintf(str, len, "%s:?", "???");
1418 	}
1419 #ifdef WINDOWS
1420 	errno = WSAGetLastError();
1421 #endif
1422 	message(LOG_ERR, "Unknown node:serv %s len=%d err=%d errno=%d",
1423 		str, salen, err, errno);
1424     } else {
1425 	i = strlen(str);
1426 	snprintf(str+i, len-i, ":%s", serv);
1427     }
1428     i = strlen(str);
1429     ext2str(proto, str+i, len-i);
1430     return str;
1431 }
1432 #endif
1433 
addrport2strOnce(struct sockaddr * sa,socklen_t salen,int proto,char * str,int len,int flags)1434 char *addrport2strOnce(struct sockaddr *sa, socklen_t salen,
1435 		       int proto, char *str, int len, int flags) {
1436     if (! *str) {
1437 	addrport2str(sa, salen, proto, str, len, flags);
1438 	str[len] = '\0';
1439     }
1440     return str;
1441 }
1442 
isdigitstr(char * str)1443 int isdigitstr(char *str) {
1444     while (*str && !isspace(*str)) {
1445 	if (!isdigit(*str)) return 0;
1446 	str++;
1447     }
1448     return 1;
1449 }
1450 
isdigitaddr(char * name)1451 int isdigitaddr(char *name) {
1452     int ndigits = 0;
1453     int isdot = 1;
1454     while(*name) {
1455 	if (*name == '.') {
1456 	    if (isdot) return 0;	/* `.' appears twice */
1457 	    isdot = 1;
1458 	} else if (isdigit(*name)) {
1459 	    if (isdot) ndigits++;
1460 	    isdot = 0;
1461 	} else {
1462 	    return 0;	/* not digit nor dot */
1463 	}
1464 	name++;
1465     }
1466     return ndigits;
1467 }
1468 
1469 /* set port into struct sockaddr */
saPort(struct sockaddr * sa,u_short port)1470 void saPort(struct sockaddr *sa, u_short port) {
1471     if (sa->sa_family == AF_INET) {
1472 	((struct sockaddr_in*)sa)->sin_port = htons(port);
1473 	return;
1474     }
1475 #ifdef AF_INET6
1476     if (sa->sa_family == AF_INET6) {
1477 	((struct sockaddr_in6*)sa)->sin6_port = htons(port);
1478 	return;
1479     }
1480 #endif
1481     message(LOG_ERR, "saPort: unknown family=%d", sa->sa_family);
1482 }
1483 
1484 /* get port from struct sockaddr */
getport(struct sockaddr * sa)1485 int getport(struct sockaddr *sa) {
1486     if (sa->sa_family == AF_INET) {
1487 	return ntohs(((struct sockaddr_in*)sa)->sin_port);
1488 #ifdef AF_INET6
1489     } else if (sa->sa_family == AF_INET6) {
1490 	return ntohs(((struct sockaddr_in6*)sa)->sin6_port);
1491 #endif
1492     }
1493     return -1;
1494 }
1495 
hostPortExt(char * str,char * host,char * port)1496 int hostPortExt(char *str, char *host, char *port) {
1497     int port_pos = -1;
1498     int ext_pos = 0;
1499     int ipv6 = 0;	/* assume str is IPv6 address w/o port */
1500     int i;
1501     for (i=0; i < STRMAX && str[i]; i++) {
1502 	host[i] = str[i];
1503 	if (port_pos >= 0) port[i-port_pos] = str[i];
1504 	if (str[i] == ':') {
1505 	    port_pos = i+1;
1506 	    if ((ipv6 & 0xff) == 0) {	/* double ':' */
1507 		if (ipv6 & 0xf000) return -1;	/* illegal format */
1508 		ipv6 = 0x1000;
1509 		port_pos = -1;
1510 	    } else if (0 < ipv6 && (ipv6 & 0xff) <= 4) {
1511 		ipv6 = (ipv6 & 0xff00) + 0x100;	/* str may be IPv6 address */
1512 	    }
1513 	} else if (ipv6 >= 0) {
1514 	    char c = str[i];
1515 	    if (('0' <= c && c <= '9') ||
1516 		('A' <= c && c <= 'F') || ('a' <= c && c <= 'f')) {
1517 		ipv6++;
1518 	    } else {
1519 		ipv6 = -1;	/* str can't be IPv6 w/o port */
1520 	    }
1521 	}
1522 	if (str[i] == '/') {
1523 	    ext_pos = i+1;
1524 	    ipv6 = -1;	/* str can't be IPv6 w/o port */
1525 	}
1526     }
1527     host[i] = '\0';
1528     if (ipv6 >= 0
1529 	&& (ipv6 & 0xff00) != 0x0100	/* not [0-1a-f]+:<port> */
1530 	&& (ipv6 & 0xff00) != 0x0800) {	/* not <canonical IPv6>:<port> */
1531 	port[0] = '\0';	/* IPv6 w/o port */
1532     } else {
1533 	if (port_pos < 1) return -1;	/* illegal format */
1534 	host[port_pos-1] = '\0';
1535 	port[i-port_pos] = '\0';
1536 	if (ext_pos) port[ext_pos - port_pos - 1] = '\0';
1537     }
1538     return ext_pos;
1539 }
1540 
1541 #ifdef NO_ADDRINFO
str2port(char * str,char * proto)1542 int str2port(char *str, char *proto) {	/* host byte order */
1543     struct servent *ent;
1544     ent = getservbyname(str, proto);
1545     if (ent) {
1546 	return ntohs(ent->s_port);
1547     } else if (isdigitstr(str)) {
1548 	return atoi(str);
1549     } else {
1550 	return -1;
1551     }
1552 }
1553 
host2sa(char * name,char * serv,struct sockaddr * sa,socklen_t * salenp,int * socktypep,int * protocolp,int flags)1554 int host2sa(char *name, char *serv, struct sockaddr *sa, socklen_t *salenp,
1555 	    int *socktypep, int *protocolp, int flags) {
1556     struct hostent *hp;
1557     int ntry = NTRY_MAX;
1558     int port = -1;
1559     struct sockaddr_in *sinp = (struct sockaddr_in*)sa;
1560     struct in_addr *addrp = &sinp->sin_addr;
1561     if (*salenp < sizeof(struct sockaddr_in)) {
1562 	message(LOG_ERR, "host2sa: too small salen=%d", *salenp);
1563 	return EAI_MEMORY;	/* too small */
1564     }
1565     *salenp = sizeof(struct sockaddr_in);
1566     if (!name) {
1567 	bzero(sa, *salenp);
1568 	sa->sa_family = AF_INET;
1569 	goto hostok;
1570     }
1571     if (isdigitaddr(name)) {
1572 	if ((addrp->s_addr=inet_addr(name)) != -1) {
1573 	    sa->sa_family = AF_INET;
1574 	    goto hostok;
1575 	}
1576     } else {
1577 	do {
1578 	    hp = gethostbyname(name);
1579 	    if (hp) {
1580 		bcopy(hp->h_addr, (char *)addrp, hp->h_length);
1581 		sa->sa_family = hp->h_addrtype;
1582 	    hostok:
1583 		if (serv) {
1584 		    if (protocolp && *protocolp == IPPROTO_UDP) {
1585 			port = str2port(serv, "udp");
1586 		    } else {
1587 			port = str2port(serv, "tcp");
1588 		    }
1589 		    if (port < 0) {
1590 			message(LOG_ERR, "Unknown service: %s", serv);
1591 			return EAI_SERVICE;
1592 		    }
1593 		    saPort(sa, port);
1594 		}
1595 		return 0;	/* OK */
1596 	    } else if (h_errno != TRY_AGAIN) {
1597 		int err;
1598 		message(LOG_ERR, "Unknown host: %s err=%d", name, h_errno);
1599 		switch (h_errno) {
1600 		case HOST_NOT_FOUND:	err = EAI_NONAME;	break;
1601 		case NO_ADDRESS:	err = EAI_ADDRFAMILY;	break;
1602 		case NO_DATA:		err = EAI_NODATA;	break;
1603 		default:		err = EAI_SYSTEM;
1604 		}
1605 		return err;
1606 	    }
1607 	} while (ntry-- > 0);
1608     }
1609     message(LOG_ERR, "Unknown host: %s err=%d", name, h_errno);
1610     return EAI_AGAIN;
1611 }
1612 #else
host2sa(char * name,char * serv,struct sockaddr * sa,socklen_t * salenp,int * socktypep,int * protocolp,int flags)1613 int host2sa(char *name, char *serv, struct sockaddr *sa, socklen_t *salenp,
1614 	    int *socktypep, int *protocolp, int flags) {
1615     struct addrinfo *ai = NULL;
1616     struct addrinfo hint;
1617     int err;
1618     hint.ai_flags = flags;
1619     hint.ai_family = sa->sa_family;
1620     if (socktypep) hint.ai_socktype = *socktypep;
1621     else hint.ai_socktype = SOCK_STREAM;
1622     if (protocolp) hint.ai_protocol = *protocolp;
1623     else hint.ai_protocol = 0;
1624     hint.ai_addrlen = 0;
1625     hint.ai_addr = NULL;
1626     hint.ai_canonname = NULL;
1627     hint.ai_next = NULL;
1628     if (Debug > 10) {
1629 	message(LOG_DEBUG, "getaddrinfo: %s serv=%s family=%d socktype=%d flags=%d",
1630 		(name ? name : ""), (serv ? serv : ""),
1631 		sa->sa_family, hint.ai_socktype, flags);
1632     }
1633     err = getaddrinfo(name, serv, &hint, &ai);
1634     if (err != 0) {
1635 #ifdef WINDOWS
1636 	errno = WSAGetLastError();
1637 #endif
1638 	message(LOG_ERR, "getaddrinfo for %s serv=%s failed err=%d errno=%d",
1639 		(name ? name : ""), (serv ? serv : ""), err, errno);
1640     fail:
1641 	if (ai) freeaddrinfo(ai);
1642 	return err;
1643     }
1644     if (ai->ai_addrlen > *salenp) {
1645 	message(LOG_ERR,
1646 		"getaddrinfo for %s serv=%s returns unexpected addr size=%d",
1647 		(name ? name : ""), (serv ? serv : ""), ai->ai_addrlen);
1648 	goto fail;
1649     }
1650     *salenp = ai->ai_addrlen;
1651     if (socktypep) *socktypep = ai->ai_socktype;
1652     if (protocolp) *protocolp = ai->ai_protocol;
1653     bcopy(ai->ai_addr, sa, *salenp);
1654     freeaddrinfo(ai);
1655     return 0;
1656 }
1657 #endif
1658 
hostPort2sa(char * str,struct sockaddr * sa,socklen_t * salenp,int flags)1659 int hostPort2sa(char *str, struct sockaddr *sa, socklen_t *salenp, int flags) {
1660     char host[STRMAX+1];
1661     char port[STRMAX+1];
1662     int pos = hostPortExt(str, host, port);
1663     if (pos < 0) return 0;
1664 #ifdef AF_INET6
1665     if (pos && !strcmp(str+pos, "v6")) sa->sa_family = AF_INET6;
1666 #endif
1667     return host2sa(host, port, sa, salenp, NULL, NULL, flags);
1668 }
1669 
saDup(struct sockaddr * sa,socklen_t salen)1670 SockAddr *saDup(struct sockaddr *sa, socklen_t salen) {
1671     SockAddr *ret = malloc(SockAddrBaseSize + salen);
1672     if (ret) {
1673 	bcopy(sa, &ret->addr, salen);
1674 	ret->len = salen;
1675     }
1676     return ret;
1677 }
1678 
saComp(struct sockaddr * a,struct sockaddr * b)1679 int saComp(struct sockaddr *a, struct sockaddr *b) {
1680     if (a->sa_family != b->sa_family) {
1681 	if (Debug > 10) {
1682 	    message(LOG_DEBUG, "saComp: sa_family differ: %d, %d",
1683 		    a->sa_family, b->sa_family);
1684 	}
1685 	return 0;
1686     }
1687     if (a->sa_family == AF_INET) {
1688 	struct in_addr *an, *bn;
1689 	short ap, bp;
1690 	an = &((struct sockaddr_in*)a)->sin_addr;
1691 	bn = &((struct sockaddr_in*)b)->sin_addr;
1692 	ap = ((struct sockaddr_in*)a)->sin_port;
1693 	bp = ((struct sockaddr_in*)b)->sin_port;
1694 	if (Debug > 10) {
1695 	    message(LOG_DEBUG, "saComp: %lx:%d, %lx:%d",
1696 		    (long unsigned)ntohl(an->s_addr), ntohs(ap),
1697 		    (long unsigned)ntohl(bn->s_addr), ntohs(bp));
1698 	}
1699 	return (an->s_addr == bn->s_addr) && (ap == bp);
1700     }
1701 #ifdef AF_INET6
1702     if (a->sa_family == AF_INET6) {
1703 	struct in6_addr *an, *bn;
1704 	short ap, bp;
1705 	int i;
1706 	an = &((struct sockaddr_in6*)a)->sin6_addr;
1707 	bn = &((struct sockaddr_in6*)b)->sin6_addr;
1708 	ap = ((struct sockaddr_in6*)a)->sin6_port;
1709 	bp = ((struct sockaddr_in6*)b)->sin6_port;
1710 	if (ap != bp) return 0;
1711 	for (i=0; i < 16; i+=4)
1712 	    if (*(u_long*)&an->s6_addr[i]
1713 		!= *(u_long*)&bn->s6_addr[i]) return 0;
1714 	return 1;
1715     }
1716 #endif
1717     message(LOG_ERR, "saComp: unknown family=%d", a->sa_family);
1718     return 0;
1719 }
1720 
1721 /* *addrp is permitted to connect to *stone ? */
checkXhost(XHosts * xhosts,struct sockaddr * sa,socklen_t salen)1722 XHosts *checkXhost(XHosts *xhosts, struct sockaddr *sa, socklen_t salen) {
1723     int match = 1;
1724     if (!xhosts) return XHostsTrue; /* any hosts can access */
1725     for (; xhosts != NULL; xhosts = xhosts->next) {
1726 	if (xhosts->mbits < 0) {
1727 	    match = !match;
1728 	    continue;
1729 	}
1730 	(void)salen;
1731 	if (sa->sa_family == AF_INET
1732 	    && xhosts->xhost.addr.sa_family == AF_INET) {
1733 	    if (xhosts->mbits > 0) {
1734 		u_long addr = ntohl(((struct sockaddr_in*)sa)
1735 				    ->sin_addr.s_addr);
1736 		u_long xadr = ntohl(((struct sockaddr_in*)&xhosts->xhost.addr)
1737 				    ->sin_addr.s_addr);
1738 		u_long bits = ((u_long)~0 << (32 - xhosts->mbits));
1739 		if ((addr & bits) != (xadr & bits)) continue;
1740 	    }
1741 	    if (match) return xhosts;
1742 	    return NULL;
1743 #ifdef AF_INET6
1744 	} else if (sa->sa_family == AF_INET6
1745 		   && xhosts->xhost.addr.sa_family == AF_INET6) {
1746 	    struct in6_addr *adrp = &((struct sockaddr_in6*)sa)->sin6_addr;
1747 	    struct in6_addr *xadp = &((struct sockaddr_in6*)
1748 				      &xhosts->xhost.addr)->sin6_addr;
1749 	    int j, k;
1750 	    for (j=0, k=xhosts->mbits; k > 0; j+=4, k -= 32) {
1751 		u_long addr, xadr, mask;
1752 		addr = ntohl(*(u_long*)&adrp->s6_addr[j]);
1753 		xadr = ntohl(*(u_long*)&xadp->s6_addr[j]);
1754 		if (k >= 32) mask = (u_long)~0;
1755 		else mask = ((u_long)~0 << (32-k));	/* premise: k > 0 */
1756 		if (Debug > 12)
1757 		    message(LOG_DEBUG, "compare addr=%lx x=%lx m=%lx",
1758 			    addr, xadr, mask);
1759 		if ((addr & mask) != (xadr & mask)) break;
1760 	    }
1761 	    if (k <= 0) {
1762 		if (match) return xhosts;
1763 		return NULL;
1764 	    }
1765 	} else if (sa->sa_family == AF_INET6
1766 		   && xhosts->xhost.addr.sa_family == AF_INET) {
1767 	    struct in6_addr *adrp = &((struct sockaddr_in6*)sa)->sin6_addr;
1768 	    if (*(u_long*)&adrp->s6_addr[0] != 0
1769 		|| *(u_long*)&adrp->s6_addr[4] != 0
1770 		|| ntohl(*(u_long*)&adrp->s6_addr[8]) != 0xFFFF) continue;
1771 	    if (xhosts->mbits > 0) {
1772 		u_long addr = ntohl(*(u_long*)&adrp->s6_addr[12]);
1773 		u_long xadr = ntohl(((struct sockaddr_in*)&xhosts->xhost.addr)
1774 				    ->sin_addr.s_addr);
1775 		u_long bits = ((u_long)~0 << (32 - xhosts->mbits));
1776 		if ((addr & bits) != (xadr & bits)) continue;
1777 	    }
1778 	    if (match) return xhosts;
1779 	    return NULL;
1780 #endif
1781 	}
1782     }
1783     if (!match) return XHostsTrue;
1784     return NULL;
1785 }
1786 
1787 #ifdef WINDOWS
waitMutex(HANDLE h)1788 void waitMutex(HANDLE h) {
1789     DWORD ret;
1790     if (h) {
1791 	ret = WaitForSingleObject(h, 5000);	/* 5 sec */
1792 	if (ret == WAIT_FAILED) {
1793 	    message(LOG_ERR, "Fail to wait mutex err=%d, existing",
1794 		    (int)GetLastError());
1795 	    exit(1);
1796 	} else if (ret == WAIT_TIMEOUT) {
1797 	    message(LOG_ERR, "timeout to wait mutex, existing");
1798 	    exit(1);
1799 	}
1800     }
1801 }
1802 
freeMutex(HANDLE h)1803 void freeMutex(HANDLE h) {
1804     if (h) {
1805 	if (!ReleaseMutex(h)) {
1806 	    message(LOG_ERR, "Fail to release mutex err=%d",
1807 		    (int)GetLastError());
1808 	}
1809     }
1810 }
1811 #else	/* ! WINDOWS */
1812 #ifdef OS2
waitMutex(HMTX h)1813 void waitMutex(HMTX h) {
1814     APIRET ret;
1815     if (h) {
1816 	ret = DosRequestMutexSem(h, 500);	/* 0.5 sec */
1817 	if (ret == ERROR_TIMEOUT) {
1818 	    message(LOG_WARNING, "timeout to wait mutex");
1819 	} else if (ret) {
1820 	    message(LOG_ERR, "Fail to request mutex err=%d", ret);
1821 	}
1822     }
1823 }
1824 
freeMutex(HMTX h)1825 void freeMutex(HMTX h) {
1826     APIRET ret;
1827     if (h) {
1828 	ret = DosReleaseMutexSem(h);
1829 	if (ret) {
1830 	    message(LOG_ERR, "Fail to release mutex err=%d", ret);
1831 	}
1832     }
1833 }
1834 #else	/* ! OS2 & ! WINDOWS */
1835 #ifdef PTHREAD
waitMutex(int h)1836 void waitMutex(int h) {
1837     int err;
1838     for (;;) {
1839 	err = pthread_mutex_lock(&FastMutex);
1840 	if (err) {
1841 	    message(LOG_ERR, "Mutex %d err=%d", h, err);
1842 	}
1843 	if (FastMutexs[h] == 0) {
1844 	    int i = ++FastMutexs[h];
1845 	    pthread_mutex_unlock(&FastMutex);
1846 	    if (Debug > 20) message(LOG_DEBUG, "Lock Mutex %d = %d", h, i);
1847 	    break;
1848 	}
1849 	pthread_mutex_unlock(&FastMutex);
1850 	if (Debug > 10) message(LOG_DEBUG, "Mutex conflict %d = %d",
1851 				h, FastMutexs[h]);
1852 	MutexConflict++;
1853 	usleep(100);
1854     }
1855 }
1856 
freeMutex(int h)1857 void freeMutex(int h) {
1858     int err = pthread_mutex_lock(&FastMutex);
1859     if (err) {
1860 	message(LOG_ERR, "Mutex %d err=%d", h, err);
1861     }
1862     if (FastMutexs[h] > 0) {
1863 	if (FastMutexs[h] > 1)
1864 	    message(LOG_ERR, "Mutex %d Locked Recursively (%d)",
1865 		    h, FastMutexs[h]);
1866 	FastMutexs[h]--;
1867 	if (Debug > 20) message(LOG_DEBUG, "Unlock Mutex %d = %d",
1868 				h, FastMutexs[h]);
1869     }
1870     pthread_mutex_unlock(&FastMutex);
1871 }
1872 #else	/* ! OS2 & ! WINDOWS & PTHREAD */
1873 #define waitMutex(sem)	/* */
1874 #define freeMutex(sem)	/* */
1875 #endif
1876 #endif
1877 #endif
1878 
1879 /* backup */
1880 
healthCheck(struct sockaddr * sa,socklen_t salen,int proto,int timeout,Chat * chat)1881 int healthCheck(struct sockaddr *sa, socklen_t salen,
1882 		int proto, int timeout, Chat *chat) {
1883     SOCKET sd;
1884     int ret;
1885     char addrport[STRMAX+1];
1886 #ifdef WINDOWS
1887     u_long param;
1888 #endif
1889 #ifdef USE_EPOLL
1890     int epfd;
1891     struct epoll_event ev;
1892     struct epoll_event evs[1];
1893 #endif
1894     time_t start, now;
1895     time(&start);
1896     sd = socket(sa->sa_family, SOCK_STREAM, IPPROTO_TCP);
1897     if (InvalidSocket(sd)) {
1898 #ifdef WINDOWS
1899 	errno = WSAGetLastError();
1900 #endif
1901 	message(LOG_ERR, "health check: can't create socket err=%d",
1902 		errno);
1903 	return 1;	/* I can't tell the master is healthy or not */
1904     }
1905 #ifdef USE_EPOLL
1906     epfd = epoll_create(BACKLOG_MAX);
1907     if (epfd < 0) {
1908 	message(LOG_ERR, "health check: can't create epoll err=%d", errno);
1909 	return 1;	/* I can't tell the master is healthy or not */
1910     }
1911     ev.events = (EPOLLOUT | EPOLLONESHOT);
1912     if (epoll_ctl(epfd, EPOLL_CTL_ADD, sd, &ev) < 0) {
1913 	message(LOG_ERR, "health check: epoll_ctl ADD err=%d", errno);
1914 	close(epfd);
1915 	return 1;	/* I can't tell the master is healthy or not */
1916     }
1917 #endif
1918     addrport[0] = '\0';
1919     if (!(proto & proto_block_d)) {
1920 #ifdef WINDOWS
1921 	param = 1;
1922 	ioctlsocket(sd, FIONBIO, &param);
1923 #else
1924 	fcntl(sd, F_SETFL, O_NONBLOCK);
1925 #endif
1926     }
1927     ret = connect(sd, sa, salen);
1928     if (ret < 0) {
1929 #ifdef WINDOWS
1930         errno = WSAGetLastError();
1931 #endif
1932 	if (errno == EINPROGRESS) {
1933 #ifndef USE_EPOLL
1934 	    fd_set wout;
1935 	    struct timeval tv;
1936 #endif
1937 	    int optval;
1938 	    socklen_t optlen = sizeof(optval);
1939 	    do {
1940 		time(&now);
1941 		if (now - start >= timeout) goto timeout;
1942 #ifndef USE_EPOLL
1943 		tv.tv_sec = 1;
1944 		tv.tv_usec = 0;
1945 		FD_ZERO(&wout);
1946 		FdSet(sd, &wout);
1947 #endif
1948 	    } while (
1949 #ifdef USE_EPOLL
1950 		epoll_wait(epfd, evs, 1, 1000) == 0
1951 #else
1952 		select(FD_SETSIZE, NULL, &wout, NULL, &tv) == 0
1953 #endif
1954 		);
1955 	    getsockopt(sd, SOL_SOCKET, SO_ERROR, (char*)&optval, &optlen);
1956 	    if (optval) {
1957 		addrport2strOnce(sa, salen, (proto & proto_pair_d),
1958 				 addrport, STRMAX, 0);
1959 		message(LOG_ERR, "health check: connect %s getsockopt err=%d",
1960 			addrport, optval);
1961 		goto fail;
1962 	    }
1963 	} else {
1964 	    addrport2strOnce(sa, salen, (proto & proto_pair_d),
1965 			     addrport, STRMAX, 0);
1966 	    message(LOG_ERR, "health check: connect %s err=%d",
1967 		    addrport, errno);
1968 	    goto fail;
1969 	}
1970     }
1971     time(&now);
1972     if (now - start >= timeout) goto timeout;
1973     while (chat) {
1974 	char buf[BUFMAX];
1975 	int len;
1976 	int err;
1977 	ret = send(sd, chat->send, chat->len, 0);
1978 	if (ret < 0 || ret != chat->len) {
1979 #ifdef WINDOWS
1980 	    errno = WSAGetLastError();
1981 #endif
1982 	    addrport2strOnce(sa, salen, (proto & proto_pair_d),
1983 			     addrport, STRMAX, 0);
1984 	    message(LOG_ERR, "health check: send %s err=%d",
1985 		    addrport, errno);
1986 	    goto fail;
1987 	}
1988 	len = 0;
1989 	do {
1990 #ifdef USE_EPOLL
1991 	    ev.events = (EPOLLIN | EPOLLONESHOT);
1992 	    epoll_ctl(epfd, EPOLL_CTL_MOD, sd, &ev);
1993 #else
1994 	    fd_set rout;
1995 	    struct timeval tv;
1996 #endif
1997 	    do {
1998 		time(&now);
1999 		if (now - start >= timeout) goto timeout;
2000 #ifndef USE_EPOLL
2001 		tv.tv_sec = 1;
2002 		tv.tv_usec = 0;
2003 		FD_ZERO(&rout);
2004 		FdSet(sd, &rout);
2005 #endif
2006 	    } while (
2007 #ifdef USE_EPOLL
2008 		epoll_wait(epfd, evs, 1, 1000) == 0
2009 #else
2010 		select(FD_SETSIZE, &rout, NULL, NULL, &tv) == 0
2011 #endif
2012 		);
2013 	    ret = recv(sd, buf+len, BUFMAX-1-len, 0);
2014 	    if (ret < 0) {
2015 #ifdef WINDOWS
2016 		errno = WSAGetLastError();
2017 #endif
2018 		addrport2strOnce(sa, salen, (proto & proto_pair_d),
2019 				 addrport, STRMAX, 0);
2020 		message(LOG_ERR, "health check: recv from %s err=%d",
2021 			addrport, errno);
2022 		goto fail;
2023 	    }
2024 	    len += ret;
2025 	    buf[len] = '\0';
2026 	    err = regexec(&chat->expect, buf, 0, NULL, 0);
2027 	    if (Debug > 8) {
2028 		addrport2strOnce(sa, salen, (proto & proto_pair_d),
2029 				 addrport, STRMAX, 0);
2030 		message(LOG_DEBUG, "health check: %s regexec=%d",
2031 			addrport, err);
2032 	    }
2033 	    if (len > BUFMAX/2) {
2034 		bcopy(buf+(len-BUFMAX/2), buf, BUFMAX/2);
2035 		len = BUFMAX/2;
2036 	    }
2037 	} while (ret > 0 && err == REG_NOMATCH);
2038 #ifndef REG_NOERROR
2039 #ifdef REG_OK
2040 #define	REG_NOERROR	REG_OK
2041 #else
2042 #define	REG_NOERROR	0
2043 #endif
2044 #endif
2045 	if (err != REG_NOERROR) goto fail;
2046 	chat = chat->next;
2047     }
2048     shutdown(sd, 2);
2049 #ifdef USE_EPOLL
2050     close(epfd);
2051 #endif
2052     closesocket(sd);
2053     return 1;	/* healthy ! */
2054  timeout:
2055     if (Debug > 8) {
2056 	addrport2strOnce(sa, salen, (proto & proto_pair_d),
2057 			 addrport, STRMAX, 0);
2058 	message(LOG_DEBUG, "health check: %s timeout", addrport);
2059     }
2060  fail:
2061     shutdown(sd, 2);
2062 #ifdef USE_EPOLL
2063     close(epfd);
2064 #endif
2065     closesocket(sd);
2066     return 0;	/* fail */
2067 }
2068 
asyncHealthCheck(Backup * b)2069 void asyncHealthCheck(Backup *b) {
2070     time_t now;
2071     char addrport[STRMAX+1];
2072     ASYNC_BEGIN;
2073     time(&now);
2074     b->last = now + 60 * 60;	/* suppress further check */
2075     addrport[0] = '\0';
2076     if (Debug > 8) {
2077 	addrport2strOnce(&b->check->addr, b->check->len,
2078 			 (b->proto & proto_pair_d), addrport, STRMAX, 0);
2079 	message(LOG_DEBUG, "asyncHealthCheck %s", addrport);
2080     }
2081     if (healthCheck(&b->check->addr, b->check->len,
2082 		    b->proto, b->interval, b->chat)) {	/* healthy ? */
2083 	if (Debug > 3 || (b->bn && Debug > 1)) {
2084 	    addrport2strOnce(&b->check->addr, b->check->len,
2085 			     (b->proto & proto_pair_d), addrport, STRMAX, 0);
2086 	    message(LOG_DEBUG, "health check %s success", addrport);
2087 	}
2088 	if (b->bn) b->bn = 0;
2089     } else {	/* unhealthy */
2090 	if (Debug > 3 || (b->bn == 0 && Debug > 0)) {
2091 	    addrport2strOnce(&b->check->addr, b->check->len,
2092 			     (b->proto & proto_pair_d), addrport, STRMAX, 0);
2093 	    message(LOG_DEBUG, "health check %s fail", addrport);
2094 	}
2095 	if (b->bn == 0) b->bn++;
2096     }
2097     b->last = now;
2098     ASYNC_END;
2099 }
2100 
scanBackups(void)2101 void scanBackups(void) {
2102     Backup *b;
2103     time_t now;
2104     time(&now);
2105     for (b=backups; b != NULL; b=b->next) {
2106 	if (b->used < 2) continue;		/* not used */
2107 	if (b->interval <= 0 || now - b->last < b->interval) continue;
2108 	ASYNC(asyncHealthCheck, b);
2109     }
2110 }
2111 
findBackup(struct sockaddr * sa)2112 Backup *findBackup(struct sockaddr *sa) {
2113     Backup *b;
2114     for (b=backups; b != NULL; b=b->next) {
2115 	if (saComp(sa, &b->master->addr)) {	/* found */
2116 	    if (Debug > 1) {
2117 		char mhostport[STRMAX+1];
2118 		char bhostport[STRMAX+1];
2119 		addrport2str(&b->master->addr, b->master->len,
2120 			     (b->proto & proto_pair_d), mhostport, STRMAX, 0);
2121 		mhostport[STRMAX] = '\0';
2122 		addrport2str(&b->backup->addr, b->backup->len,
2123 			     (b->proto & proto_pair_d), bhostport, STRMAX, 0);
2124 		bhostport[STRMAX] = '\0';
2125 		message(LOG_DEBUG, "master %s backup %s interval %d",
2126 			mhostport, bhostport, b->interval);
2127 	    }
2128 	    return b;
2129 	}
2130     }
2131     return NULL;
2132 }
2133 
gcd(int a,int b)2134 int gcd(int a, int b) {
2135     int m;
2136     if (a > b) {
2137 	m = a % b;
2138 	if (m == 0) return b;
2139 	return gcd(m, b);
2140     } else {
2141 	m = b % a;
2142 	if (m == 0) return a;
2143 	return gcd(m, a);
2144     }
2145 }
2146 
mkBackup(int argc,int argi,char * argv[])2147 int mkBackup(int argc, int argi, char *argv[]) {
2148     char master_host[STRMAX+1];
2149     char master_port[STRMAX+1];
2150     char *master_ext = NULL;
2151     char backup_host[STRMAX+1];
2152     char backup_port[STRMAX+1];
2153     int pos;
2154     char *check_host = NULL;
2155     char *check_port = NULL;
2156     char *check_ext = NULL;
2157     struct sockaddr_storage ss;
2158     struct sockaddr *sa = (struct sockaddr*)&ss;
2159     socklen_t salen;
2160     Backup *b = malloc(sizeof(Backup));
2161     argi++;
2162     for ( ; argi < argc; argi++) {
2163 	if (!strncmp(argv[argi], "host=", 5)) {
2164 	    check_host = argv[argi]+5;
2165 	} else if (!strncmp(argv[argi], "port=", 5)) {
2166 	    check_port = argv[argi]+5;
2167 	} else if (!strncmp(argv[argi], "ext=", 4)) {
2168 	    check_ext = argv[argi]+4;
2169 	} else {
2170 	    break;
2171 	}
2172     }
2173     if (argi+2 >= argc) {
2174 	message(LOG_ERR, "Irregular backup option");
2175 	exit(1);
2176     }
2177     if (b) {
2178 	b->last = 0;
2179 	b->bn = 0;	/* healthy */
2180 	b->used = 0;
2181 	b->interval = atoi(argv[argi]);
2182     } else {
2183     memerr:
2184 	message(LOG_CRIT, "Out of memory, no backup for %s", argv[argi+1]);
2185 	return argi+2;
2186     }
2187     if (b->interval > 0) {
2188 	if (MinInterval > 0) {
2189 	    MinInterval = gcd(MinInterval, b->interval);
2190 	} else {
2191 	    MinInterval = b->interval;
2192 	}
2193     } else {
2194 	b->bn = 1;	/* force unhealthy */
2195     }
2196     b->proto = 0;
2197     pos = hostPortExt(argv[argi+1], master_host, master_port);
2198     if (pos < 0) {
2199 	message(LOG_ERR, "Illegal master: %s", argv[argi+1]);
2200 	free(b);
2201 	return argi+2;
2202     } else if (pos > 0) {
2203 	master_ext = argv[argi+1] + pos;
2204     }
2205     salen = sizeof(ss);
2206     sa->sa_family = AF_UNSPEC;
2207 #ifdef AF_INET6
2208     if (master_ext && !strcmp(master_ext, "v6")) sa->sa_family = AF_INET6;
2209 #endif
2210     if (host2sa(master_host, master_port, sa, &salen, NULL, NULL, 0)) {
2211 	free(b);
2212 	return argi+2;
2213     } else {
2214 	b->master = saDup(sa, salen);
2215 	if (!b->master) {
2216 	    free(b);
2217 	    goto memerr;
2218 	}
2219 	b->check = b->master;
2220     }
2221     pos = hostPortExt(argv[argi+2], backup_host, backup_port);
2222     if (pos < 0) {
2223 	message(LOG_ERR, "Illegal backup: %s", argv[argi+2]);
2224 	free(b);
2225 	return argi+2;
2226     }
2227     salen = sizeof(ss);
2228     sa->sa_family = AF_UNSPEC;
2229 #ifdef AF_INET6
2230     if (pos && !strcmp(argv[argi+2]+pos, "v6")) sa->sa_family = AF_INET6;
2231 #endif
2232     if (host2sa(backup_host, backup_port, sa, &salen, NULL, NULL, 0)) {
2233 	free(b->master);
2234 	free(b);
2235 	return argi+2;
2236     } else {
2237 	b->backup = saDup(sa, salen);
2238 	if (!b->backup) {
2239 	    free(b->master);
2240 	    free(b);
2241 	    goto memerr;
2242 	}
2243     }
2244     if (check_host || check_port || check_ext) {
2245 	if (!check_host) check_host = master_host;
2246 	if (!check_port) check_port = master_port;
2247 	if (!check_ext)  check_ext  = master_ext;
2248 	salen = sizeof(ss);
2249 	sa->sa_family = AF_UNSPEC;
2250 #ifdef AF_INET6
2251 	if (check_ext && !strcmp(check_ext, "v6")) sa->sa_family = AF_INET6;
2252 #endif
2253 	if (host2sa(check_host, check_port, sa, &salen, NULL, NULL, 0)) {
2254 	    /* ignore */
2255 	} else {
2256 	    b->check = saDup(sa, salen);
2257 	    if (!b->check) {
2258 		free(b->backup);
2259 		free(b->master);
2260 		free(b);
2261 		goto memerr;
2262 	    }
2263 	}
2264     }
2265     b->chat = healthChat;
2266     b->next = backups;
2267     backups = b;
2268     return argi+2;
2269 }
2270 
str2num(char ** pp,int rad)2271 int str2num(char **pp, int rad) {
2272     char *p;
2273     int num;
2274     int i;
2275     p = *pp;
2276     num = 0;
2277     for (i=0; i < 3; i++) {	/* 3 digit at most */
2278 	char c = p[i];
2279 	if ('0' <= c && c <= '9') {
2280 	    num = num * rad + c;
2281 	} else {
2282 	    c = toupper(c);
2283 	    if (rad > 10 && ('A' <= c && c <= ('A' + rad - 11))) {
2284 		num = num * rad + (c - 'A' + 10);
2285 	    } else {
2286 		break;
2287 	    }
2288 	}
2289     }
2290     *pp = p;
2291     return num;
2292 }
2293 
str2bin(char * p,int * lenp)2294 char *str2bin(char *p, int *lenp) {
2295     char buf[BUFMAX];
2296     char c;
2297     int i = 0;
2298     while ((c=*p++) && i < BUFMAX-5) {
2299 	if (c == '\\') {
2300 	    c = *p++;
2301 	    switch(c) {
2302 	    case 'n':  c = '\n';  break;
2303 	    case 'r':  c = '\r';  break;
2304 	    case 't':  c = '\t';  break;
2305 	    case '0':  c = str2num(&p,  8);  break;
2306 	    case 'x':  c = str2num(&p, 16);  break;
2307 	    case '\0':
2308 		c = '\\';
2309 		p--;
2310 	    }
2311 	}
2312 	buf[i++] = c;
2313     }
2314     p = malloc(i);
2315     if (!p) {
2316 	message(LOG_CRIT, "Out of memory, can't make str");
2317 	exit(1);
2318     }
2319     bcopy(buf, p, i);
2320     *lenp = i;
2321     return p;
2322 }
2323 
mkChat(int argc,int i,char * argv[])2324 int mkChat(int argc, int i, char *argv[]) {
2325     Chat *top, *bot;
2326     top = bot = NULL;
2327     i++;
2328     for ( ; i+1 < argc; i+=2) {
2329 	Chat *cur;
2330 	int err;
2331 	if (argv[i][0] == '-' && argv[i][1] == '-') {
2332 	    healthChat = top;
2333 	    return i;
2334 	}
2335 	cur = malloc(sizeof(Chat));
2336 	if (!cur) {
2337 	memerr:
2338 	    message(LOG_CRIT, "Out of memory, can't make Chat");
2339 	    exit(1);
2340 	}
2341 	cur->send = str2bin(argv[i], &cur->len);
2342 	if (!cur->send) {
2343 	    free(cur);
2344 	    goto memerr;
2345 	}
2346 	err = regcomp(&cur->expect, argv[i+1], REG_EXTENDED);
2347 	if (err) {
2348 	    message(LOG_ERR, "RegEx compiling error: \"%s\" err=%d",
2349 		    argv[i+1], err);
2350 	    exit(1);
2351 	}
2352 	cur->next = NULL;
2353 	if (!top) top = cur;
2354 	if (bot) bot->next = cur;
2355 	bot = cur;
2356     }
2357     message(LOG_ERR, "chat script ends unexpectedly");
2358     exit(1);
2359     return i;
2360 }
2361 
findLBSet(struct sockaddr * sa)2362 LBSet *findLBSet(struct sockaddr *sa) {
2363     LBSet *s;
2364     for (s=lbsets; s != NULL; s=s->next) {
2365 	if (saComp(&s->dsts[0]->addr, sa)) {	/* found */
2366 	    if (Debug > 1) {
2367 		char buf[LONGSTRMAX+1];
2368 		int len;
2369 		int i;
2370 		buf[LONGSTRMAX] = '\0';
2371 		strcpy(buf, "LB set:");
2372 		len = strlen(buf);
2373 		for (i=0; i < s->ndsts && len < LONGSTRMAX-2; i++) {
2374 		    buf[len++] = ' ';
2375 		    addrport2str(&s->dsts[i]->addr, s->dsts[i]->len,
2376 				 (s->proto & proto_pair_d),
2377 				 buf+len, LONGSTRMAX-1-len, 0);
2378 		    len += strlen(buf+len);
2379 		}
2380 		message(LOG_DEBUG, "%s", buf);
2381 	    }
2382 	    return s;
2383 	}
2384     }
2385     return NULL;
2386 }
2387 
lbsopts(int argc,int i,char * argv[])2388 int lbsopts(int argc, int i, char *argv[]) {
2389     SockAddr *dsts[LB_MAX];
2390     int ndsts = 0;
2391     LBSet *lbs;
2392     struct sockaddr_storage ss;
2393     struct sockaddr *sa = (struct sockaddr*)&ss;
2394     socklen_t salen;
2395     int proto = 0;
2396     i++;
2397     for ( ; i < argc; i++) {
2398 	if (argv[i][0] == '-' && argv[i][1] == '-') break;
2399 	if (ndsts >= LB_MAX) {
2400 	    message(LOG_ERR, "Too many load balancing hosts");
2401 	    exit(1);
2402 	}
2403 	salen = sizeof(ss);
2404 	sa->sa_family = AF_UNSPEC;
2405 	if (hostPort2sa(argv[i], sa, &salen, 0)) {
2406 	    message(LOG_ERR, "Illegal load balancing host: %s", argv[i]);
2407 	    exit(1);
2408 	}
2409 	dsts[ndsts] = saDup(sa, salen);
2410 	if (!dsts[ndsts]) goto memerr;
2411 	ndsts++;
2412     }
2413     lbs = malloc(sizeof(LBSet) + sizeof(SockAddr*) * ndsts);
2414     if (lbs) {
2415 	int j;
2416 	lbs->next = lbsets;
2417 	lbs->proto = proto;
2418 	lbs->ndsts = ndsts;
2419 	for (j=0; j < ndsts; j++) lbs->dsts[j] = dsts[j];
2420 	lbsets = lbs;
2421     } else {
2422     memerr:
2423 	message(LOG_CRIT, "Out of memory, can't make LB set");
2424 	exit(1);
2425     }
2426     return i;
2427 }
2428 
stone_dsts(Stone * stone,char * dhost,char * dserv)2429 int stone_dsts(Stone *stone, char *dhost, char *dserv) {
2430     struct sockaddr_storage dss;
2431     struct sockaddr *dsa = (struct sockaddr*)&dss;
2432     socklen_t dsalen = sizeof(dss);
2433     int dsatype;
2434     int dsaproto;
2435     int proto = stone->proto;
2436     if (stone->ndsts > 0) return stone->ndsts;
2437     if (stone->dsts) {
2438 	if (!dhost) dhost = (char*)stone->dsts[0];
2439 	if (!dserv) dserv = (char*)stone->dsts[1];
2440     }
2441 #ifdef AF_INET6
2442     if (proto & proto_v6_d) dsa->sa_family = AF_INET6;
2443     else
2444 #endif
2445 	dsa->sa_family = AF_INET;
2446     if (proto & proto_udp_d) {
2447 	dsatype = SOCK_DGRAM;
2448 	dsaproto = IPPROTO_UDP;
2449     } else {
2450 	dsatype = SOCK_STREAM;
2451 	dsaproto = IPPROTO_TCP;
2452     }
2453     if (host2sa(dhost, dserv, dsa, &dsalen, &dsatype, &dsaproto, 0)) {
2454 	if (!stone->dsts) {
2455 	    stone->dsts = malloc(sizeof(char*));
2456 	    if (!stone->dsts) {
2457 	    memerr:
2458 		message(LOG_CRIT, "Out of memory");
2459 		exit(1);
2460 	    }
2461 	    stone->dsts[0] = (void*)strdup(dhost);
2462 	    stone->dsts[1] = (void*)strdup(dserv);
2463 	}
2464     } else {
2465 	LBSet *lbset;
2466 	if (stone->dsts) {
2467 	    if (stone->dsts[0]) free(stone->dsts[0]);
2468 	    if (stone->dsts[1]) free(stone->dsts[1]);
2469 	    free(stone->dsts);
2470 	}
2471 	lbset = findLBSet(dsa);
2472 	if (lbset) {
2473 	    stone->ndsts = lbset->ndsts;
2474 	    stone->dsts = lbset->dsts;
2475 	} else {
2476 	    stone->ndsts = 1;
2477 	    stone->dsts = malloc(sizeof(SockAddr*));
2478 	    if (!stone->dsts) goto memerr;
2479 	    stone->dsts[0] = saDup(dsa, dsalen);
2480 	    if (!stone->dsts[0]) goto memerr;
2481 	}
2482     }
2483     return stone->ndsts;
2484 }
2485 
stone2str(Stone * stone,char * str,int strlen)2486 char *stone2str(Stone *stone, char *str, int strlen) {
2487     int proto;
2488     char src[STRMAX+1];
2489     addrport2str(&stone->listen->addr, stone->listen->len,
2490 		 (stone->proto & proto_stone_s), src, STRMAX, 0);
2491     src[STRMAX] = '\0';
2492     proto = stone->proto;
2493     if ((proto & proto_command) == command_proxy) {
2494 	snprintf(str, strlen, "stone %d: proxy <- %s", (int)stone->sd, src);
2495     } else if ((proto & proto_command) == command_health) {
2496 	snprintf(str, strlen, "stone %d: health <- %s", (int)stone->sd, src);
2497     } else if ((proto & proto_command) == command_identd) {
2498 	snprintf(str, strlen, "stone %d: identd <- %s", (int)stone->sd, src);
2499     } else {
2500 	char dst[STRMAX+1];
2501 	if (stone->ndsts > 0) {
2502 	    addrport2str(&stone->dsts[0]->addr, stone->dsts[0]->len,
2503 			 (stone->proto & proto_stone_d), dst, STRMAX, 0);
2504 	    dst[STRMAX] = '\0';
2505 	} else {
2506 	    snprintf(dst, STRMAX, "(%s:%s)",
2507 		     (char*)stone->dsts[0], (char*)stone->dsts[1]);
2508 	}
2509 	snprintf(str, strlen, "stone %d: %s <- %s", (int)stone->sd, dst, src);
2510     }
2511     str[strlen] = '\0';
2512     return str;
2513 }
2514 
ungetExBuf(ExBuf * ex)2515 void ungetExBuf(ExBuf *ex) {
2516     ExBuf *freeptr = NULL;
2517     time_t now;
2518     time(&now);
2519     waitMutex(ExBufMutex);
2520     if (ex->start < 0) {
2521 	freeMutex(ExBufMutex);
2522 	message(LOG_ERR, "ungetExBuf duplication. can't happen, ignore");
2523 	return;
2524     }
2525     if (now - freeExBotClock > FREE_TIMEOUT) {
2526 	if (nFreeExBot > 2) {
2527 	    freeptr = freeExBot->next;
2528 	    freeExBot->next = NULL;
2529 	    nFreeExBuf -= (nFreeExBot - 1);
2530 	} else {
2531 	    freeExBot = freeExBuf;
2532 	    nFreeExBot = nFreeExBuf;
2533 	}
2534 	freeExBotClock = now;
2535     }
2536     ex->start = -1;
2537     ex->len = 0;
2538     ex->next = freeExBuf;
2539     freeExBuf = ex;
2540     nFreeExBuf++;
2541     freeMutex(ExBufMutex);
2542     if (freeptr) {
2543 	if (Debug > 3) message(LOG_DEBUG, "freeExBot %d nfex=%d",
2544 			       nFreeExBot, nFreeExBuf);
2545 	freeExBot = NULL;
2546 	nFreeExBot = 0;
2547 	while (freeptr) {
2548 	    ExBuf *p = freeptr;
2549 	    freeptr = freeptr->next;
2550 	    free(p);
2551 	}
2552     }
2553 }
2554 
getExBuf(void)2555 ExBuf *getExBuf(void) {
2556     ExBuf *ret = NULL;
2557     time_t now;
2558     time(&now);
2559     waitMutex(ExBufMutex);
2560     if (freeExBuf) {
2561 	ret = freeExBuf;
2562 	freeExBuf = ret->next;
2563 	nFreeExBuf--;
2564 	if (nFreeExBuf < nFreeExBot) {
2565 	    nFreeExBot = nFreeExBuf;
2566 	    freeExBot = freeExBuf;
2567 	    freeExBotClock = now;
2568 	}
2569     }
2570     freeMutex(ExBufMutex);
2571     if (!ret) {
2572 	int size = XferBufMax;
2573 	do {
2574 	    ret = malloc(sizeof(ExBuf) + size - BUFMAX);
2575 	} while (!ret && XferBufMax > BUFMAX && (XferBufMax /= 2));
2576 	if (!ret) {
2577 	    message(LOG_CRIT, "Out of memory, no ExBuf");
2578 	    return ret;
2579 	}
2580 	ret->bufmax = size;
2581     }
2582     ret->next = NULL;
2583     ret->start = 0;
2584     ret->len = 0;
2585     return ret;
2586 }
2587 
getExData(Pair * pair,int type,int rmflag)2588 ExBuf *getExData(Pair *pair, int type, int rmflag) {
2589     ExBuf *ex = pair->d;
2590     ExBuf *prev = NULL;
2591     while (ex) {
2592 	int t = *(int*)ex->buf;
2593 	if (t == type) {
2594 	    if (rmflag) {
2595 		if (prev) prev->next = ex->next;
2596 		else pair->d = ex->next;
2597 	    }
2598 	    return ex;
2599 	}
2600 	prev = ex;
2601 	ex = ex->next;
2602     }
2603     return NULL;
2604 }
2605 
newExData(Pair * pair,int type)2606 ExBuf *newExData(Pair *pair, int type) {
2607     ExBuf *ex = getExBuf();
2608     if (!ex) return NULL;
2609     *(int*)ex->buf = type;
2610     ex->next = pair->d;
2611     pair->d = ex;
2612     return ex;
2613 }
2614 
2615 /* modify dest if needed */
modPairDest(Pair * p1,struct sockaddr * dst,socklen_t dstlenmax)2616 int modPairDest(Pair *p1, struct sockaddr *dst, socklen_t dstlenmax) {
2617     Pair *p2;
2618     socklen_t dstlen = 0;
2619     int offset = -1;	/* offset in load balancing group */
2620 #ifdef USE_SSL
2621     SSL *ssl;
2622 #endif
2623     p2 = p1->pair;
2624     if (p2 == NULL) return -1;
2625 #ifdef USE_SSL
2626     ssl = p2->ssl;
2627     if (ssl) {
2628 	unsigned char **match = SSL_get_ex_data(ssl, MatchIndex);
2629 	if (match && p2->stone->ssl_server) {
2630 	    int lbparm = p2->stone->ssl_server->lbparm;
2631 	    int lbmod = p2->stone->ssl_server->lbmod;
2632 	    unsigned char *s;
2633 	    if (0 <= lbparm && lbparm <= 9) s = match[lbparm];
2634 	    else s = match[1];
2635 	    if (!s) s = match[0];
2636 	    if (s && lbmod) {
2637 		int offset2 = 0;
2638 		offset = 0;
2639 		while (*s) {
2640 		    if (offset2 >= 0) {
2641 			if ('0' <= *s && *s <= '9') {
2642 			    offset2 = offset2 * 10 + (*s - '0');
2643 			} else {
2644 			    offset2 = -1;
2645 			}
2646 		    }
2647 		    offset <<= 6;
2648 		    offset += (*s & 0x3f);
2649 		    s++;
2650 		}
2651 		if (offset2 > 0) offset = offset2;
2652 		offset %= lbmod;
2653 		if (Debug > 2)
2654 		    message(LOG_DEBUG, "%d TCP %d: pair %d lb%d=%d",
2655 			    p1->stone->sd, p1->sd, p2->sd, lbparm, offset);
2656 	    }
2657 	}
2658     }
2659 #endif
2660     if (offset < 0 && p1->stone->ndsts > 1) {	/* load balancing */
2661 	int n = p1->stone->ndsts;
2662 	offset = (p1->stone->proto & state_mask) % n;
2663 	if (p1->stone->backups) {
2664 	    int i;
2665 	    for (i=0; i < n; i++) {
2666 		Backup *b = p1->stone->backups[(offset+i) % n];
2667 		if (!b || b->bn == 0) {	/* no backup or healthy, use it */
2668 		    offset = (offset+i) % n;
2669 		    break;
2670 		}
2671 		if (Debug > 8)
2672 		    message(LOG_DEBUG,
2673 			    "%d TCP %d: ofs=%d is unhealthy, skipped",
2674 			    p1->stone->sd, p1->sd, (offset+i) % n);
2675 	    }
2676 	}
2677 	/* round robin */
2678 	p1->stone->proto = ((p1->stone->proto & ~state_mask)
2679 			    | ((offset+1) & state_mask));
2680     }
2681     if (offset >= 0) {
2682 	dstlen = p1->stone->dsts[offset]->len;
2683 	if (dstlen < dstlenmax)
2684 	    bcopy(&p1->stone->dsts[offset]->addr, dst, dstlen);
2685     }
2686     if (p1->stone->backups) {
2687 	Backup *backup;
2688 	if (offset >= 0) backup = p1->stone->backups[offset];
2689 	else backup = p1->stone->backups[0];
2690 	if (backup) {
2691 	    backup->used = 2;
2692 	    if (backup->bn) {	/* unhealthy */
2693 		dstlen = backup->backup->len;
2694 		if (dstlen < dstlenmax)
2695 		    bcopy(&backup->backup->addr, dst, dstlen);
2696 	    }
2697 	}
2698     }
2699     return dstlen;
2700 }
2701 
2702 /* relay UDP */
2703 
message_origin(int pri,Origin * origin)2704 void message_origin(int pri, Origin *origin) {
2705     struct sockaddr_storage ss;
2706     struct sockaddr *name = (struct sockaddr*)&ss;
2707     socklen_t namelen = sizeof(ss);
2708     SOCKET sd;
2709     Stone *stone;
2710     int i;
2711     char str[LONGSTRMAX+1];
2712     str[LONGSTRMAX] = '\0';
2713     strntime(str, LONGSTRMAX, &origin->clock, -1);
2714     i = strlen(str);
2715     if (ValidSocket(origin->sd)) {
2716 	if (getsockname(origin->sd, name, &namelen) < 0) {
2717 #ifdef WINDOWS
2718 	    errno = WSAGetLastError();
2719 #endif
2720 	    if (Debug > 3)
2721 		message(LOG_DEBUG, "%d UDP %d: Can't get socket's name err=%d",
2722 			origin->stone->sd, origin->sd, errno);
2723 	} else {
2724 	    addrport2str(name, namelen, proto_udp, str+i, LONGSTRMAX-i, 0),
2725 	    i = strlen(str);
2726 	    if (i < LONGSTRMAX-2) str[i++] = ' ';
2727 	}
2728     }
2729     if (i > LONGSTRMAX) i = LONGSTRMAX;
2730     str[i] = '\0';
2731     stone = origin->stone;
2732     if (stone) sd = stone->sd;
2733     else sd = INVALID_SOCKET;
2734     addrport2str(&origin->from->addr, origin->from->len, proto_udp,
2735 		 str+i, STRMAX-i, 0);
2736     str[STRMAX] = '\0';
2737     message(pri, "%d UDP%3d:%3d %s", origin->stone->sd, origin->sd, sd, str);
2738 }
2739 
ungetPktBuf(PktBuf * pb)2740 void ungetPktBuf(PktBuf *pb) {
2741     if (pb->bufmax < pkt_len_max) {
2742 	free(pb);	/* never reuse short buffer */
2743 	return;
2744     }
2745     waitMutex(PkBufMutex);
2746     pb->next = freePktBuf;
2747     freePktBuf = pb;
2748     nFreePktBuf++;
2749     freeMutex(PkBufMutex);
2750 }
2751 
getPktBuf(void)2752 PktBuf *getPktBuf(void) {
2753     PktBuf *ret = NULL;
2754     waitMutex(PkBufMutex);
2755     if (freePktBuf) {
2756 	ret = freePktBuf;
2757 	freePktBuf = ret->next;
2758 	nFreePktBuf--;
2759     }
2760     freeMutex(PkBufMutex);
2761     if (ret && ret->bufmax < pkt_len_max) {
2762 	free(ret);	/* discard short buffer */
2763 	ret = NULL;
2764     }
2765     if (!ret) {
2766 	int size = pkt_len_max;
2767 	do {
2768 	    ret = malloc(sizeof(PktBuf) + size - BUFMAX);
2769 	} while (!ret && pkt_len_max > BUFMAX && (pkt_len_max /= 2));
2770 	if (!ret) {
2771 	    message(LOG_CRIT, "Out of memory, no ExBuf");
2772 	    return ret;
2773 	}
2774 	ret->common = type_pktbuf;
2775 	ret->bufmax = size;
2776     }
2777     ret->next = NULL;
2778     ret->origin = NULL;
2779     ret->len = 0;
2780     return ret;
2781 }
2782 
freeOrigin(Origin * origin)2783 void freeOrigin(Origin *origin) {
2784     if (origin->from) free(origin->from);
2785     free(origin);
2786 }
2787 
getOrigins(struct sockaddr * from,socklen_t fromlen,Stone * stone)2788 Origin *getOrigins(struct sockaddr *from, socklen_t fromlen, Stone *stone) {
2789     Origin *origin;
2790     Origin *origins = (Origin*)stone->p;
2791     SOCKET sd;
2792 #ifdef USE_EPOLL
2793     struct epoll_event ev;
2794 #endif
2795     for (origin=origins->next; origin != NULL && origin->from;
2796 	 origin=origin->next) {
2797 	if (InvalidSocket(origin->sd)) continue;
2798 	if (saComp(&origin->from->addr, from)) {
2799 	    origin->lock = 1;	/* lock origin */
2800 	    return origin;
2801 	}
2802     }
2803     /* can't find origin, so create */
2804     sd = socket(from->sa_family, SOCK_DGRAM, IPPROTO_UDP);
2805     if (InvalidSocket(sd)) {
2806 #ifdef WINDOWS
2807 	errno = WSAGetLastError();
2808 #endif
2809 	message(LOG_ERR, "%d UDP: can't create datagram socket err=%d",
2810 		stone->sd, errno);
2811 	return NULL;
2812     }
2813     if (Debug > 3) {
2814 	char addrport[STRMAX+1];
2815 	message(LOG_DEBUG, "%d UDP %d: New origin %s",
2816 		stone->sd, sd,
2817 		addrport2str(from, fromlen, proto_udp, addrport, STRMAX, 0));
2818     }
2819     if (!(stone->proto & proto_block_d)) {
2820 #ifdef WINDOWS
2821 	u_long param;
2822 	param = 1;
2823 	ioctlsocket(sd, FIONBIO, &param);
2824 #else
2825 	fcntl(sd, F_SETFL, O_NONBLOCK);
2826 #endif
2827     }
2828     origin = malloc(sizeof(Origin));
2829     if (!origin) {
2830     memerr:
2831 	message(LOG_CRIT, "%d UDP %d: Out of memory, closing socket",
2832 		stone->sd, sd);
2833 	return NULL;
2834     }
2835     origin->common = type_origin;
2836     origin->sd = sd;
2837     origin->stone = stone;
2838     origin->from = saDup(from, fromlen);
2839     if (!origin->from) {
2840 	free(origin);
2841 	goto memerr;
2842     }
2843     origin->lock = 0;
2844     origin->xhost = NULL;
2845 #ifdef USE_EPOLL
2846     ev.events = EPOLLIN;
2847     ev.data.ptr = origin;
2848     if (epoll_ctl(ePollFd, EPOLL_CTL_ADD, sd, &ev) < 0) {
2849 	message(LOG_ERR, "%d UDP %d: epoll_ctl ADD err=%d",
2850 		stone->sd, sd, errno);
2851 	freeOrigin(origin);
2852 	return NULL;
2853     }
2854 #else
2855     waitMutex(FdRinMutex);
2856     FdSet(origin->sd, &rin);
2857     freeMutex(FdRinMutex);
2858 #endif
2859     waitMutex(OrigMutex);
2860     origin->next = origins->next;	/* insert origin */
2861     origins->next = origin;
2862     freeMutex(OrigMutex);
2863     return origin;
2864 }
2865 
recvUDP(Stone * stone)2866 PktBuf *recvUDP(Stone *stone) {
2867     struct sockaddr_storage ss;
2868     struct sockaddr *from = (struct sockaddr*)&ss;
2869     socklen_t fromlen = sizeof(ss);
2870     Origin *origin;
2871     SOCKET sd;
2872     int flags = 0;
2873     char *dirstr;
2874     PktBuf *pb = getPktBuf();
2875     pb->type = (stone->common & type_mask);
2876     if (pb->type == type_origin) {
2877 	origin = (Origin*)stone;
2878 	sd = origin->sd;
2879 	stone = origin->stone;
2880 	dirstr = "<";
2881 #ifdef MSG_DONTWAIT
2882 	if (!(stone->proto & proto_block_d)) flags = MSG_DONTWAIT;
2883 #endif
2884     } else {
2885 	origin = NULL;
2886 	sd = stone->sd;
2887 	dirstr = ">";
2888 #ifdef MSG_DONTWAIT
2889 	if (!(stone->proto & proto_block_s)) flags = MSG_DONTWAIT;
2890 #endif
2891     }
2892 #ifdef MSG_TRUNC
2893     flags |= MSG_TRUNC;
2894 #endif
2895     pb->len = recvfrom(sd, pb->buf, pb->bufmax, flags, from, &fromlen);
2896     if (pb->len < 0) {
2897 #ifdef WINDOWS
2898 	errno = WSAGetLastError();
2899 #endif
2900 	if (errno == EMSGSIZE) {
2901 	    if (Debug > 4)
2902 		message(LOG_DEBUG, "%d UDP%s%d: recvfrom received larger msg",
2903 			stone->sd, dirstr, sd);
2904 	    pb->len = pb->bufmax + 1;
2905 	} else {
2906 	    message(LOG_ERR, "%d UDP%s%d: recvfrom failed err=%d",
2907 		    stone->sd, dirstr, sd, errno);
2908 	end:
2909 	    ungetPktBuf(pb);
2910 	    return NULL;
2911 	}
2912     }
2913     if (pb->type == type_stone) {	/* outward */
2914 	XHosts *xhost = checkXhost(stone->xhosts, from, fromlen);
2915 	if (!xhost) {
2916 	    if (Debug > 4) {
2917 		char addrport[STRMAX+1];
2918 		addrport2str(from, fromlen, proto_udp, addrport, STRMAX, 0);
2919 		addrport[STRMAX] = '\0';
2920 		message(LOG_DEBUG, "%d UDP%s%d: recvfrom denied %s",
2921 			stone->sd, dirstr, sd, addrport);
2922 	    }
2923 	    goto end;
2924 	}
2925 	origin = getOrigins(from, fromlen, stone);
2926 	if (!origin) goto end;
2927 	origin->xhost = xhost;
2928 	time(&origin->clock);
2929     }
2930     pb->origin = origin;
2931     if (pb->len > pb->bufmax || Debug > 4) {
2932 	char addrport[STRMAX+1];
2933 	addrport2str(from, fromlen, proto_udp, addrport, STRMAX, 0);
2934 	addrport[STRMAX] = '\0';
2935 	if (Debug > 4)
2936 	    message(LOG_DEBUG, "%d UDP%s%d: %d bytes received from %s",
2937 		    stone->sd, dirstr, origin->sd, pb->len, addrport);
2938 	if (pb->len > pb->bufmax) {
2939 	    message(LOG_NOTICE, "%d UDP%s%d: recvfrom failed: larger packet "
2940 		    "(%d bytes) arrived from %s",
2941 		    stone->sd, dirstr, origin->sd, pb->len, addrport);
2942 	    while (pkt_len_max < pb->len) pkt_len_max <<= 1;
2943 	    ungetPktBuf(pb);
2944 	    return NULL;	/* drop */
2945 	}
2946     }
2947     return pb;
2948 }
2949 
sendUDP(PktBuf * pb)2950 int sendUDP(PktBuf *pb) {
2951     Origin *origin = pb->origin;
2952     Stone *stone = origin->stone;
2953     SOCKET sd;
2954     int flags = 0;
2955     struct sockaddr *sa;
2956     socklen_t salen;
2957     char *dirstr;
2958     if (pb->type == type_stone) {
2959 	if (!stone->ndsts && !stone_dsts(stone, NULL, NULL)) return -1;
2960 	sd = origin->sd;
2961 	sa = &stone->dsts[0]->addr;
2962 	salen = stone->dsts[0]->len;
2963 	dirstr = ">";
2964 #ifdef MSG_DONTWAIT
2965 	if (!(stone->proto & proto_block_d)) flags = MSG_DONTWAIT;
2966 #endif
2967     } else {
2968 	sd = stone->sd;
2969 	sa = &origin->from->addr;
2970 	salen = origin->from->len;
2971 	dirstr = "<";
2972 #ifdef MSG_DONTWAIT
2973 	if (!(stone->proto & proto_block_s)) flags = MSG_DONTWAIT;
2974 #endif
2975     }
2976     if (sendto(sd, pb->buf, pb->len, flags, sa, salen) != pb->len) {
2977 	char addrport[STRMAX+1];
2978 	addrport2str(sa, salen, proto_udp, addrport, STRMAX, 0);
2979 	addrport[STRMAX] = '\0';
2980 #ifdef WINDOWS
2981 	errno = WSAGetLastError();
2982 #endif
2983 	message(LOG_ERR, "%d UDP%s%d: sendto failed err=%d: to %s",
2984 		stone->sd, dirstr, origin->sd, errno, addrport);
2985 	return -1;
2986     }
2987     if (Debug > 4) {
2988 	char addrport[STRMAX+1];
2989 	addrport2str(sa, salen, proto_udp, addrport, STRMAX, 0);
2990 	addrport[STRMAX] = '\0';
2991 	message(LOG_DEBUG, "%d UDP%s%d: %d bytes sent to %s",
2992 		stone->sd, dirstr, origin->sd, pb->len, addrport);
2993     }
2994     if ((origin->xhost->mode & XHostsMode_Dump) > 0) {
2995 	char head[STRMAX+1];
2996 	snprintf(head, STRMAX, "%d UDP%s%d:",
2997 		 (int)stone->sd, dirstr, (int)origin->sd);
2998 	head[STRMAX] = '\0';
2999 	packet_dump(head, pb->buf, pb->len, origin->xhost);
3000     }
3001     return pb->len;
3002 }
3003 
docloseUDP(Origin * origin)3004 void docloseUDP(Origin *origin) {
3005 #ifdef USE_EPOLL
3006     SOCKET sd = origin->sd;
3007 #endif
3008     if (Debug > 2) message(LOG_DEBUG, "%d UDP %d: close",
3009 			   origin->stone->sd, origin->sd);
3010     origin->lock = -1;	/* request to close */
3011 #ifdef USE_EPOLL
3012     origin->sd = INVALID_SOCKET;
3013     closesocket(sd);
3014 #else
3015     waitMutex(FdRinMutex);
3016     FD_CLR(origin->sd, &rin);
3017     freeMutex(FdRinMutex);
3018 #endif
3019 }
3020 
scanUDP(fd_set * rop,fd_set * eop,Origin * origins)3021 int scanUDP(
3022 #ifndef USE_EPOLL
3023     fd_set *rop, fd_set *eop,
3024 #endif
3025     Origin *origins
3026     ) {
3027     Origin *origin, *prev;
3028     int n = 0;
3029     int all;
3030     time_t now;
3031     time(&now);
3032 #ifndef USE_EPOLL
3033     (void)eop;
3034 #endif
3035     if (origins) {
3036 	all = 0;
3037     } else {
3038 	origins = OriginTop;
3039 	all = 1;
3040     }
3041     prev = origins;
3042     for (origin=origins->next; origin != NULL && (all || origin->from != NULL);
3043 	 prev=origin, origin=origin->next) {
3044 	if (all && origin->from == NULL) {
3045 	    origins = origin;
3046 	    continue;
3047 	}
3048 	if (InvalidSocket(origin->sd) || origin->lock > 0) {
3049 	    Origin *old = origin;
3050 	    waitMutex(OrigMutex);
3051 	    if (prev->next == origin) {
3052 		origin = prev;
3053 		origin->next = old->next;	/* remove `old' from list */
3054 		if (InvalidSocket(old->sd)) {
3055 		    freeOrigin(old);
3056 		} else {
3057 		    old->lock = 0;
3058 		    old->next = origins->next;	/* insert old on top */
3059 		    origins->next = old;
3060 		}
3061 	    }
3062 	    freeMutex(OrigMutex);
3063 	    goto next;
3064 	}
3065 #ifndef USE_EPOLL
3066 	if (origin->lock < 0) {
3067 	    int isset;
3068 	    waitMutex(FdRinMutex);
3069 	    isset = FD_ISSET(origin->sd, &rin);
3070 	    if (isset) FD_CLR(origin->sd, &rin);
3071 	    freeMutex(FdRinMutex);
3072 	    if (!isset) {
3073 		closesocket(origin->sd);
3074 		origin->sd = INVALID_SOCKET;
3075 	    }
3076 	    goto next;
3077 	}
3078 	if (FD_ISSET(origin->sd, rop) && FD_ISSET(origin->sd, &rin)) {
3079 	    PktBuf *pb = recvUDP((Stone*)origin);
3080 	    if (pb) {
3081 		sendUDP(pb);
3082 		ungetPktBuf(pb);
3083 	    }
3084 	    goto next;
3085 	}
3086 #endif
3087 	if (++n >= OriginMax || now - origin->clock > CONN_TIMEOUT)
3088 	    docloseUDP(origin);
3089       next:
3090 	;
3091     }
3092     return 1;
3093 }
3094 
3095 #define UDP_HEAD_LEN	2	/* sizeof(short): UDP packet length */
3096 
recvPairUDP(Pair * pair)3097 int recvPairUDP(Pair *pair) {
3098     Stone *stone = pair->stone;
3099     SOCKET sd = pair->sd;
3100     Pair *p;
3101     ExBuf *ex;
3102     ExBuf *t;
3103     int len;
3104     int flags = 0;
3105     struct sockaddr_storage ss;
3106     struct sockaddr *from = (struct sockaddr*)&ss;
3107     socklen_t fromlen = sizeof(ss);
3108     p = pair->pair;
3109     if (p == NULL) {	/* no pair, no more read */
3110 	message(priority(pair), "%d UDP %d: no pair, closing",
3111 		stone->sd, sd);
3112 	return -1;
3113     }
3114     ex = p->b;	/* bottom */
3115     if (ex->len > 0) {	/* not emply */
3116 	ex = getExBuf();
3117 	if (!ex) return -1;	/* out of memory */
3118 	if (Debug > 4) message(LOG_DEBUG, "%d UDP %d: get ExBuf nbuf=%d",
3119 			       stone->sd, p->sd, p->nbuf);
3120     }
3121     ex->start = 0;
3122 #ifdef MSG_DONTWAIT
3123     if (!(stone->proto & proto_block_d)) flags = MSG_DONTWAIT;
3124 #endif
3125 #ifdef MSG_TRUNC
3126     flags |= MSG_TRUNC;
3127 #endif
3128     len = recvfrom(sd, ex->buf + UDP_HEAD_LEN,
3129 		   ex->bufmax - UDP_HEAD_LEN,
3130 		   flags, from, &fromlen);
3131     if (len < 0) {
3132 #ifdef WINDOWS
3133 	errno = WSAGetLastError();
3134 #endif
3135 	message(LOG_ERR, "%d UDP %d: recvfrom err=%d",
3136 		stone->sd, sd, errno);
3137 	if (ex != p->b) ungetExBuf(ex);
3138 	return -1;
3139     }
3140     time(&pair->clock);
3141     p->clock = pair->clock;
3142     pair->rx += len;
3143     if (Debug > 8)
3144 	message(LOG_DEBUG, "%d UDP %d: recvfrom len=%d",
3145 		stone->sd, sd, len);
3146     t = getExData(pair, data_peeraddr, 0);
3147     if (t) {
3148 	SockAddr *peer = (SockAddr*)(t->buf + DATA_HEAD_LEN);
3149 	if (!saComp(&peer->addr, from))	goto unknown;
3150     } else {	/* from unknown */
3151 	char addrport[STRMAX+1];
3152     unknown:
3153 	addrport2str(from, fromlen, proto_udp, addrport, STRMAX, 0);
3154 	addrport[STRMAX] = '\0';
3155 	message(LOG_ERR, "%d UDP %d: received from unknown %s",
3156 		stone->sd, sd, addrport);
3157 	if (ex != p->b) ungetExBuf(ex);
3158 	return -1;
3159     }
3160     if (ex != p->b) {
3161 	p->b->next = ex;
3162 	p->b = ex;
3163 	p->nbuf++;
3164     }
3165     ex->buf[0] = ((unsigned)len >> 8);
3166     ex->buf[1] = ((unsigned)len % 256);
3167     ex->len += UDP_HEAD_LEN + len;
3168     return ex->len;
3169 }
3170 
sendPairUDPbuf(Stone * stone,Pair * pair,char * buf,int len)3171 static int sendPairUDPbuf(Stone *stone, Pair *pair, char *buf, int len) {
3172     int flags = 0;
3173     ExBuf *t;
3174     SockAddr *peer;
3175     int issrc = ((pair->proto & proto_command) == command_source);
3176     SOCKET sd;
3177     Pair *p = pair->pair;
3178 #ifdef MSG_DONTWAIT
3179     if (!(stone->proto & proto_block_d)) flags = MSG_DONTWAIT;
3180 #endif
3181     t = getExData(pair, data_peeraddr, 0);
3182     if (t) {
3183 	peer = (SockAddr*)(t->buf + DATA_HEAD_LEN);
3184     } else if (!issrc) {
3185 	int lenmax;
3186 	int dstlen;
3187 	if (!stone->ndsts && !stone_dsts(stone, NULL, NULL)) return -1;
3188 	t = newExData(pair, data_peeraddr);
3189 	peer = (SockAddr*)(t->buf + DATA_HEAD_LEN);
3190 	lenmax = t->bufmax - DATA_HEAD_LEN - SockAddrBaseSize;
3191 	peer->len = stone->dsts[0]->len;
3192 	bcopy(&stone->dsts[0]->addr, &peer->addr, peer->len);
3193 	dstlen = modPairDest(pair, &peer->addr, lenmax);
3194 	if (dstlen > 0) peer->len = dstlen;	/* dest is modified */
3195     } else {
3196 	message(LOG_ERR, "%d UDP<TCP%d: can't happen: no peer",
3197 		stone->sd, (p ? p->sd : -1));
3198 	return -1;
3199     }
3200     if (issrc) sd = stone->sd;
3201     else sd = pair->sd;
3202     if (sendto(sd, buf, len, flags, &peer->addr, peer->len) != len) {
3203 	char addrport[STRMAX+1];
3204 	addrport2str(&peer->addr, peer->len, proto_udp, addrport, STRMAX, 0);
3205 	addrport[STRMAX] = '\0';
3206 #ifdef WINDOWS
3207 	errno = WSAGetLastError();
3208 #endif
3209 	if (issrc) {
3210 	    message(LOG_ERR, "%d UDP<TCP%d: sendto failed err=%d: to %s",
3211 		    stone->sd, (p ? p->sd : -1), errno, addrport);
3212 	} else {
3213 	    message(LOG_ERR, "%d TCP%d>UDP%d: sendto failed err=%d: to %s",
3214 		    stone->sd, (p ? p->sd : -1), pair->sd, errno, addrport);
3215 	}
3216 	return -1;	/* error */
3217     }
3218     time(&pair->clock);
3219     if (p) p->clock = pair->clock;
3220     pair->tx += len;
3221     return 0;	/* success */
3222 }
3223 
sendPairUDP(Pair * pair)3224 int sendPairUDP(Pair *pair) {
3225     Stone *stone = pair->stone;
3226     ExBuf *next = pair->t;
3227     ExBuf *cur = NULL;
3228     ExBuf *ex = NULL;	/* dummy init to suppress warnings */
3229     unsigned char *buf = NULL;
3230     int pos = 0;
3231     int len = 0;
3232     int err = 0;
3233     char prefix[STRMAX+1];
3234     if ((pair->proto & proto_command) == command_source) {
3235 	Pair *p = pair->pair;
3236 	snprintf(prefix, STRMAX, "%d UDP<TCP%d:",
3237 		 (int)stone->sd, (p ? (int)p->sd : -1));
3238     } else {
3239 	Pair *p = pair->pair;
3240 	snprintf(prefix, STRMAX, "%d TCP%d>UDP%d:",
3241 		 (int)stone->sd, (p ? (int)p->sd : -1), (int)pair->sd);
3242     }
3243     while (next) {
3244 	ex = next;
3245 	next = ex->next;
3246 	int add;
3247 	if (ex->len <= 0) {	/* dispose empty buf */
3248 	    if (ex != pair->b) ungetExBuf(ex);
3249 	    continue;
3250 	}
3251 	if (!cur) {
3252 	    cur = ex;
3253 	    buf = (unsigned char*)&cur->buf[cur->start];
3254 	    pos = cur->len;
3255 	    len = (buf[0] << 8);
3256 	    if (pos == 1) {
3257 		ExBuf *t;
3258 		for (t=cur->next; t; t=t->next) {
3259 		    if (t->len > 0) {
3260 			len += (unsigned)t->buf[t->start];
3261 			break;
3262 		    }
3263 		}
3264 		if (!t) break;	/* must read header */
3265 	    } else {	/* assume UDP_HEAD_LEN == 2 */
3266 		len += buf[1];
3267 	    }
3268 	    if (Debug > 8)
3269 		message(LOG_DEBUG, "%s sendPairUDP len=%d (curbuf=%d)",
3270 			prefix, len, cur->len);
3271 	    len += UDP_HEAD_LEN;
3272 	    if (len > cur->bufmax) {
3273 		message(LOG_ERR, "%s sendPairUDP packet too large len=%d",
3274 			prefix, len);
3275 		err = -1;
3276 	    } else if (len > cur->bufmax - cur->start) {
3277 		if (Debug > 6)
3278 		    message(LOG_DEBUG, "%s sendPairUDP len=%d "
3279 			    "is larger than (bufmax-start=%d)=%d, move",
3280 			    prefix, len,
3281 			    cur->start, cur->bufmax - cur->start);
3282 		bcopy(cur->buf+cur->start, cur->buf, cur->len);
3283 		buf = (unsigned char*)cur->buf;
3284 		cur->start = 0;
3285 	    }
3286 	    if (len < cur->len) {	/* cur contains next packet */
3287 		cur->start += len;
3288 		cur->len -= len;
3289 		goto complete;
3290 	    } else if (len == cur->len) {
3291 		cur->len = cur->bufmax;	/* mark not to be used */
3292 		cur->start = 0;
3293 		goto complete;
3294 	    } else {
3295 		cur->len = cur->bufmax;	/* mark not to be used */
3296 		cur->start = 0;
3297 	    }
3298 	    continue;
3299 	}
3300 	add = len - pos;
3301 	if (ex->len > add) {	/* ex contains next packet */
3302 	    ex->start += add;
3303 	    ex->len -= add;
3304 	} else {	/* use entire buf */
3305 	    add = ex->len;
3306 	    ex->len = ex->bufmax;	/* mark not to be used */
3307 	    ex->start = 0;
3308 	}
3309 	if (!err) bcopy(ex->buf+ex->start, buf+pos, add);
3310 	pos += add;
3311 	if (ex != pair->b) ungetExBuf(ex);
3312 	if (pos >= len) {	/* complete the packet */
3313 	complete:
3314 	    if (!err) {
3315 		err = sendPairUDPbuf(stone, pair, (char*)(buf+UDP_HEAD_LEN),
3316 				     len-UDP_HEAD_LEN);
3317 		if (!err) {
3318 		    if ((pair->xhost->mode & XHostsMode_Dump) > 0
3319 			|| ((pair->proto & proto_first_w) && Debug > 3))
3320 			message_buf(pair, len, "tu");
3321 		}
3322 	    }
3323 	    if (cur != pair->b) ungetExBuf(cur);
3324 	    cur = NULL;
3325 	}
3326     }
3327     if (ex == pair->b) {
3328 	if (ex->len == ex->bufmax) ex->len = 0;
3329 	pair->t = ex;
3330     } else {
3331 	if (0 < ex->len && ex->len < ex->bufmax) {
3332 	    pair->t = ex;
3333 	} else {
3334 	    pair->t = ex->next;
3335 	    ungetExBuf(ex);
3336 	}
3337     }
3338     return err;
3339 }
3340 
3341 /* relay TCP */
3342 
message_pair(int pri,Pair * pair)3343 void message_pair(int pri, Pair *pair) {
3344     struct sockaddr_storage ss;
3345     struct sockaddr *name = (struct sockaddr*)&ss;
3346     socklen_t namelen = sizeof(ss);
3347     SOCKET sd, psd;
3348     Pair *p;
3349     int i;
3350     char str[LONGSTRMAX+1];
3351     str[LONGSTRMAX] = '\0';
3352     strntime(str, LONGSTRMAX, &pair->clock, -1);
3353     i = strlen(str);
3354     sd = pair->sd;
3355     if (ValidSocket(sd)) {
3356 	if (getsockname(sd, name, &namelen) < 0) {
3357 #ifdef WINDOWS
3358 	    errno = WSAGetLastError();
3359 #endif
3360 	    if (Debug > 3)
3361 		message(LOG_DEBUG, "%d TCP %d: Can't get socket's name err=%d",
3362 			pair->stone->sd, sd, errno);
3363 	} else {
3364 	    addrport2str(name, namelen, 0, str+i, LONGSTRMAX-i, 0);
3365 	    i = strlen(str);
3366 	    if (i < LONGSTRMAX-2) str[i++] = ' ';
3367 	}
3368 	namelen = sizeof(ss);
3369 	if (getpeername(sd, name, &namelen) < 0) {
3370 #ifdef WINDOWS
3371 	    errno = WSAGetLastError();
3372 #endif
3373 	    if (Debug > 3)
3374 		message(LOG_DEBUG, "%d TCP %d: Can't get peer's name err=%d",
3375 			pair->stone->sd, sd, errno);
3376 	} else {
3377 	    addrport2str(name, namelen, 0, str+i, LONGSTRMAX-i, 0);
3378 	    i += strlen(str+i);
3379 	}
3380     }
3381     if (i > LONGSTRMAX) i = LONGSTRMAX;
3382     str[i] = '\0';
3383     p = pair->pair;
3384     if (p) psd = p->sd;
3385     else psd = INVALID_SOCKET;
3386     message(pri, "%d TCP%3d:%3d %08x %d %s tx:%d rx:%d lp:%d",
3387 	    pair->stone->sd, sd, psd, pair->proto, pair->count, str,
3388 	    pair->tx, pair->rx, pair->loop);
3389 }
3390 
3391 #ifdef USE_SSL
printSSLinfo(int pri,SSL * ssl)3392 static void printSSLinfo(int pri, SSL *ssl) {
3393     X509 *peer;
3394     char *p = (char *)SSL_get_cipher(ssl);
3395     if (p == NULL) p = "<NULL>";
3396     message(pri, "[SSL cipher=%s]", p);
3397     peer = SSL_get_peer_certificate(ssl);
3398     if (peer) {
3399 	char buf[LONGSTRMAX+1];
3400 	ASN1_INTEGER *n = X509_get_serialNumber(peer);
3401 	if (n) message(pri, "[SSL serial=%lx]", ASN1_INTEGER_get(n));
3402 	buf[LONGSTRMAX] = '\0';
3403 	if (X509_NAME_oneline(X509_get_subject_name(peer), buf, LONGSTRMAX))
3404 	    message(pri, "[SSL subject=%s]", buf);
3405 	if (X509_NAME_oneline(X509_get_issuer_name(peer), buf, LONGSTRMAX))
3406 	    message(pri, "[SSL issuer=%s]", buf);
3407 	X509_free(peer);
3408     }
3409 }
3410 
doSSL_accept(Pair * pair)3411 int doSSL_accept(Pair *pair) {
3412     int err, ret;
3413     SOCKET sd;
3414     SSL *ssl;
3415     if (!pair) return -1;
3416     sd = pair->sd;
3417     if (InvalidSocket(sd)) return -1;
3418     ssl = pair->ssl;
3419     if (!ssl) {
3420 	ssl = SSL_new(pair->stone->ssl_server->ctx);
3421 	if (!ssl) {
3422 	    message(LOG_ERR, "%d TCP %d: SSL_new failed", pair->stone->sd, sd);
3423 	    return -1;
3424 	}
3425 	SSL_set_ex_data(ssl, PairIndex, pair);
3426 	SSL_set_fd(ssl, sd);
3427 	pair->ssl = ssl;
3428     }
3429     pair->ssl_flag &= ~(sf_ab_on_r | sf_ab_on_w);
3430     pair->proto |= proto_dirty;
3431     ret = SSL_accept(ssl);
3432     if (Debug > 7)
3433 	message(LOG_DEBUG, "%d TCP %d: SSL_accept ret=%d, state=%x, "
3434 		"finished=%x, in_init=%x/%x", pair->stone->sd,
3435 		sd, ret, SSL_get_state(ssl), SSL_is_init_finished(ssl),
3436 		SSL_in_init(ssl), SSL_in_accept_init(ssl));
3437     if (ret > 0) {	/* success */
3438 	if (SSL_in_accept_init(ssl)) {
3439 	    if (pair->stone->ssl_server->verbose) {
3440 		message(LOG_NOTICE, "%d TCP %d: SSL_accept unexpected EOF",
3441 			pair->stone->sd, sd);
3442 		message_pair(LOG_NOTICE, pair);
3443 	    }
3444 	    return -1;	/* unexpected EOF */
3445 	}
3446 	/* src & pair is connected */
3447 	pair->proto |= (proto_connect | proto_dirty);
3448 	if (Debug > 3) {
3449 	    SSL_CTX *ctx = pair->stone->ssl_server->ctx;
3450 	    message(LOG_DEBUG, "%d TCP %d: SSL_accept succeeded "
3451 		    "sess=%ld accept=%ld hits=%ld", pair->stone->sd, sd,
3452 		    (long)SSL_CTX_sess_number(ctx),
3453 		    (long)SSL_CTX_sess_accept(ctx),
3454 		    (long)SSL_CTX_sess_hits(ctx));
3455 	}
3456 	if (pair->stone->ssl_server->verbose) printSSLinfo(LOG_DEBUG, ssl);
3457 	return ret;
3458     }
3459     err = SSL_get_error(ssl, ret);
3460     if (err == SSL_ERROR_WANT_READ) {
3461 	pair->ssl_flag |= sf_ab_on_r;
3462 	ret = 0;
3463     } else if (err == SSL_ERROR_WANT_WRITE) {
3464 	pair->ssl_flag |= sf_ab_on_w;
3465 	ret = 0;
3466     } else if (err == SSL_ERROR_SYSCALL) {
3467 	unsigned long e = ERR_get_error();
3468 	if (e == 0) {
3469 #ifdef WINDOWS
3470 	    errno = WSAGetLastError();
3471 #endif
3472 	    if (errno == EINTR || errno == EAGAIN) {
3473 		pair->ssl_flag |= (sf_ab_on_r | sf_ab_on_r);
3474 		if (Debug > 8)
3475 		    message(LOG_DEBUG, "%d TCP %d: SSL_accept "
3476 			    "interrupted sf=%x",
3477 			    pair->stone->sd, sd, pair->ssl_flag);
3478 		return 0;
3479 	    }
3480 	    if (errno == 0) {
3481 		if (Debug > 0)
3482 		    message(LOG_DEBUG, "%d TCP %d: SSL_accept "
3483 			    "shutdowned by peer sf=%x errno=%d",
3484 			    pair->stone->sd, sd,
3485 			    pair->ssl_flag, errno);
3486 		return -1;	/* shutdowned */
3487 	    }
3488 	    message(priority(pair), "%d TCP %d: SSL_accept "
3489 		    "I/O error sf=%x errno=%d", pair->stone->sd, sd,
3490 		    pair->ssl_flag, errno);
3491 	} else {
3492 	    message(priority(pair), "%d TCP %d: SSL_accept sf=%x %s",
3493 		    pair->stone->sd, sd, pair->ssl_flag, ERR_error_string(e, NULL));
3494 	}
3495 	return ret;
3496     } else if (err == SSL_ERROR_SSL) {
3497 	unsigned long e = ERR_get_error();
3498 	message(priority(pair), "%d TCP %d: SSL_accept lib %s",
3499 		pair->stone->sd, sd, ERR_error_string(e, NULL));
3500 	return -1;	/* error */
3501     }
3502     if (Debug > 4)
3503 	message(LOG_DEBUG, "%d TCP %d: SSL_accept interrupted sf=%x err=%d",
3504 		pair->stone->sd, sd, pair->ssl_flag, err);
3505     return ret;
3506 }
3507 
3508 #ifdef ANDROID
keystore_BIO(const char * key)3509 static BIO *keystore_BIO(const char *key) {
3510     BIO *bio = NULL;
3511     uint8_t *value = NULL;
3512     int len = keystore_get(key, strlen(key), &value);
3513     if (len > 0 && (bio=BIO_new(BIO_s_mem()))) {
3514 	BIO_write(bio, value, len);
3515     } else {
3516 	message(LOG_NOTICE, "Can't get keystore: %s", key);
3517     }
3518     return bio;
3519 }
3520 
use_keystore(SSL_CTX * ctx,char * name)3521 static int use_keystore(SSL_CTX *ctx, char *name) {
3522     BIO *bio;
3523     STACK_OF(X509_INFO) *stack = NULL;
3524     X509 *cert = NULL;
3525     EVP_PKEY *key = NULL;
3526     char *kname = (char*)malloc(strlen(name)+10);
3527     int nkeys = 0;
3528     if (!kname) {
3529     memerr:
3530 	message(LOG_CRIT, "Out of memory");
3531 	exit(1);
3532     }
3533     strcpy(kname, "CACERT_");
3534     strcat(kname, name);
3535     if ((bio=keystore_BIO(kname))
3536 	&& (stack=PEM_X509_INFO_read_bio(bio, NULL, NULL, NULL))) {
3537 	int i;
3538 	for (i=0; i < (int)sk_X509_INFO_num(stack); i++) {
3539 	    X509_INFO *info = sk_X509_INFO_value(stack, i);
3540 	    if (!info) continue;
3541 	    if (info->x509) X509_STORE_add_cert(ctx->cert_store, info->x509);
3542 	    if (info->crl) X509_STORE_add_crl(ctx->cert_store, info->crl);
3543 	}
3544 	sk_X509_INFO_pop_free(stack, X509_INFO_free);
3545     }
3546     if (bio) BIO_free(bio);
3547     strcpy(kname, "USRCERT_");
3548     strcat(kname, name);
3549     if ((bio=keystore_BIO(kname))
3550 	&& (cert=PEM_read_bio_X509(bio, NULL, NULL, NULL))) {
3551 	if (!SSL_CTX_use_certificate(ctx, cert)) {
3552 	    message(LOG_ERR, "SSL_CTX_use_certificate(%s) %s",
3553 		    kname, ERR_error_string(ERR_get_error(), NULL));
3554 	    exit(1);
3555 	}
3556 	X509_free(cert);
3557     }
3558     if (bio) BIO_free(bio);
3559     strcpy(kname, "USRPKEY_");
3560     strcat(kname, name);
3561     if ((bio=keystore_BIO(kname))
3562 	&& (key=PEM_read_bio_PrivateKey(bio, NULL, NULL, NULL))) {
3563 	nkeys++;
3564 	if (!SSL_CTX_use_PrivateKey(ctx, key) ) {
3565 	    message(LOG_ERR, "SSL_CTX_use_PrivateKey(%s) %s",
3566 		    kname, ERR_error_string(ERR_get_error(), NULL));
3567 	    exit(1);
3568 	}
3569 	EVP_PKEY_free(key);
3570     }
3571     if (bio) BIO_free(bio);
3572     return nkeys;
3573 }
3574 #endif
3575 
doSSL_connect(Pair * pair)3576 int doSSL_connect(Pair *pair) {
3577     int ret;
3578     int err;
3579     SOCKET sd;
3580     SSL *ssl;
3581     if (!pair) return -1;
3582     sd = pair->sd;
3583     if (InvalidSocket(sd)) return -1;
3584     ssl = pair->ssl;
3585     if (!ssl) {
3586 #ifdef ANDROID
3587 	if (pair->stone->ssl_client->keystore) {
3588 	    int nkeys = use_keystore(pair->stone->ssl_client->ctx,
3589 				     pair->stone->ssl_client->keystore);
3590 	    if (nkeys > 0) pair->stone->ssl_client->keystore = NULL;
3591 	}
3592 #endif
3593 	ssl = SSL_new(pair->stone->ssl_client->ctx);
3594 	if (!ssl) {
3595 	    message(LOG_ERR, "%d TCP %d: SSL_new failed", pair->stone->sd, sd);
3596 	    return -1;
3597 	}
3598 	SSL_set_ex_data(ssl, PairIndex, pair);
3599 	SSL_set_fd(ssl, sd);
3600 	pair->ssl = ssl;
3601     }
3602 #ifndef OPENSSL_NO_TLSEXT
3603     if (pair->stone->ssl_client->sslparm & sslparm_sni) {
3604 	if (!SSL_set_tlsext_host_name(ssl, pair->stone->ssl_client->name)) {
3605 	    message(LOG_ERR, "%d TCP %d: Can't set TLS servername: %s",
3606 		    pair->stone->sd, sd, pair->stone->ssl_client->name);
3607 	}
3608     }
3609 #endif
3610     pair->ssl_flag &= ~(sf_cb_on_r | sf_cb_on_w);
3611     pair->proto |= proto_dirty;
3612     if (Debug > 8) message(LOG_DEBUG, "%d TCP %d: proto=%x SSL_connect",
3613 			   pair->stone->sd, pair->sd, pair->proto);
3614     ret = SSL_connect(ssl);
3615     if (ret > 0) {	/* success */
3616 	Pair *p = pair->pair;
3617 	/* pair & dst is connected */
3618 	pair->proto |= (proto_connect | proto_dirty);
3619 	if (p) p->proto |= proto_dirty;	/* src */
3620 	if (Debug > 3) {
3621 	    SSL_CTX *ctx = pair->stone->ssl_client->ctx;
3622 	    message(LOG_DEBUG, "%d TCP %d: SSL_connect succeeded "
3623 		    "sess=%ld connect=%ld hits=%ld", pair->stone->sd, sd,
3624 		    (long)SSL_CTX_sess_number(ctx),
3625 		    (long)SSL_CTX_sess_connect(ctx),
3626 		    (long)SSL_CTX_sess_hits(ctx));
3627 	    message_pair(LOG_DEBUG, pair);
3628 	}
3629 	if (pair->stone->ssl_client->verbose) printSSLinfo(LOG_DEBUG, ssl);
3630 	return ret;
3631     }
3632     err = SSL_get_error(ssl, ret);
3633     if (err == SSL_ERROR_WANT_READ) {
3634 	pair->ssl_flag |= sf_cb_on_r;
3635 	ret = 0;
3636     } else if (err == SSL_ERROR_WANT_WRITE) {
3637 	pair->ssl_flag |= sf_cb_on_w;
3638 	ret = 0;
3639     } else if (err == SSL_ERROR_SYSCALL) {
3640 	unsigned long e = ERR_get_error();
3641 	if (e == 0) {
3642 #ifdef WINDOWS
3643 	    errno = WSAGetLastError();
3644 #endif
3645 	    if (errno == 0) {
3646 		if (Debug > 8)
3647 		    message(LOG_DEBUG, "%d TCP %d: SSL_connect "
3648 			    "success ? sf=%x",
3649 			    pair->stone->sd, sd, pair->ssl_flag);
3650 		return 1;	/* success ? */
3651 	    } else if (errno == EINTR || errno == EAGAIN) {
3652 		pair->ssl_flag |= (sf_cb_on_r | sf_cb_on_r);
3653 		if (Debug > 8)
3654 		    message(LOG_DEBUG, "%d TCP %d: SSL_connect "
3655 			    "interrupted sf=%x",
3656 			    pair->stone->sd, sd, pair->ssl_flag);
3657 		return 0;
3658 	    }
3659 	    message(priority(pair), "%d TCP %d: SSL_connect "
3660 		    "I/O error sf=%x errno=%d", pair->stone->sd, sd,
3661 		    pair->ssl_flag, errno);
3662 	} else {
3663 	    message(priority(pair), "%d TCP %d: SSL_connect sf=%x %s",
3664 		    pair->stone->sd, sd, pair->ssl_flag, ERR_error_string(e, NULL));
3665 	}
3666 	return ret;
3667     }
3668     if (Debug > 4)
3669 	message(LOG_DEBUG, "%d TCP %d: SSL_connect interrupted sf=%x err=%d",
3670 		pair->stone->sd, sd, pair->ssl_flag, err);
3671     return ret;
3672 }
3673 
doSSL_shutdown(Pair * pair,int how)3674 int doSSL_shutdown(Pair *pair, int how) {
3675     int ret;
3676     int err;
3677     int i;
3678     SOCKET sd;
3679     SSL *ssl;
3680     StoneSSL *ss;
3681     if (!pair) return -1;
3682     sd = pair->sd;
3683     if (InvalidSocket(sd)) return -1;
3684     ssl = pair->ssl;
3685     if (!ssl) return -1;
3686     if (how >= 0) pair->ssl_flag = (how & sf_mask);
3687     else pair->ssl_flag = sf_mask;
3688     if ((pair->proto & proto_command) == command_source) {
3689 	ss = pair->stone->ssl_server;
3690     } else {
3691 	ss = pair->stone->ssl_client;
3692     }
3693     if (ss->shutdown_mode) {
3694 	int state = SSL_get_shutdown(ssl);
3695 	SSL_set_shutdown(ssl, (state | ss->shutdown_mode));
3696     }
3697     for (i=0; i < 4; i++) {
3698 	ret = SSL_shutdown(ssl);
3699 	if (ret != 0) break;
3700     }
3701     if (ret == 0 && ss->shutdown_mode == 0) {
3702 	if (Debug > 4)
3703 	    message(LOG_DEBUG, "%d TCP %d: SSL_shutdown ret=%d sf=%x, "
3704 		    "so don't wait peer's notify",
3705 		    pair->stone->sd, sd, ret, pair->ssl_flag);
3706 	SSL_set_shutdown(ssl, SSL_RECEIVED_SHUTDOWN);
3707 	ret = SSL_shutdown(ssl);
3708     }
3709     if (ret < 0) {
3710 	err = SSL_get_error(ssl, ret);
3711 	if (Debug > 4)
3712 	    message(LOG_DEBUG, "%d TCP %d: SSL_shutdown ret=%d err=%d sf=%x",
3713 		    pair->stone->sd, sd, ret, err, pair->ssl_flag);
3714 	if (err == SSL_ERROR_WANT_READ) {
3715 	    pair->ssl_flag |= sf_sb_on_r;
3716 	} else if (err == SSL_ERROR_WANT_WRITE) {
3717 	    pair->ssl_flag |= sf_sb_on_w;
3718 	} else if (err == SSL_ERROR_SYSCALL) {
3719 	    unsigned long e = ERR_get_error();
3720 	    if (e == 0) {
3721 #ifdef WINDOWS
3722 		errno = WSAGetLastError();
3723 #endif
3724 		if (errno == 0) {
3725 		    ret = 1;	/* success ? */
3726 		} else if (errno == EINTR || errno == EAGAIN) {
3727 		    pair->ssl_flag |= (sf_sb_on_r | sf_sb_on_w);
3728 		    if (Debug > 8)
3729 			message(LOG_DEBUG, "%d TCP %d: SSL_shutdown "
3730 				"interrupted sf=%x", pair->stone->sd, sd,
3731 				pair->ssl_flag);
3732 		} else {
3733 		    message(priority(pair), "%d TCP %d: SSL_shutdown "
3734 			    "I/O error sf=%x errno=%d", pair->stone->sd, sd,
3735 			    pair->ssl_flag, errno);
3736 		}
3737 	    } else {
3738 		message(priority(pair), "%d TCP %d: SSL_shutdown sf=%x %s",
3739 			pair->stone->sd, sd,
3740 			pair->ssl_flag, ERR_error_string(e, NULL));
3741 	    }
3742 	} else {
3743 	    if (Debug > 4)
3744 		message(LOG_DEBUG,
3745 			"%d TCP %d: SSL_shutdown interrupted sf=%x err=%d",
3746 			pair->stone->sd, sd, pair->ssl_flag, err);
3747 	}
3748     } else if (ret == 0) {
3749 	if (Debug > 4)
3750 	    message(priority(pair), "%d TCP %d: SSL_shutdown error "
3751 		    "ret=%d sf=%x, reset connection",
3752 		    pair->stone->sd, sd, ret, pair->ssl_flag);
3753 	shutdown(sd, 2);
3754 	ret = 0;
3755     }
3756     if (ret > 0) {	/* success */
3757 	if (Debug > 4)
3758 	    message(LOG_DEBUG, "%d TCP %d: SSL_shutdown sf=%x",
3759 		    pair->stone->sd, sd, pair->ssl_flag);
3760 	if ((pair->ssl_flag & sf_mask) != sf_mask)
3761 	    shutdown(sd, (pair->ssl_flag & sf_mask));
3762     }
3763     return ret;
3764 }
3765 #endif	/* USE_SSL */
3766 
doshutdown(Pair * pair,int how)3767 int doshutdown(Pair *pair, int how) {
3768 #ifdef USE_SSL
3769     SSL *ssl;
3770 #endif
3771     if (!pair) return -1;
3772 #ifdef USE_SSL
3773     ssl = pair->ssl;
3774     if (ssl) return doSSL_shutdown(pair, how);
3775     else {
3776 #endif
3777 	if (Debug > 4)
3778 	    message(LOG_DEBUG, "%d TCP %d: shutdown how=%d",
3779 		    pair->stone->sd, pair->sd, how);
3780 	return shutdown(pair->sd, how);
3781 #ifdef USE_SSL
3782     }
3783 #endif
3784 }
3785 
newPair(void)3786 Pair *newPair(void) {
3787     Pair *pair = NULL;
3788     waitMutex(FPairMutex);
3789     if (freePairs) {
3790 	pair = freePairs;
3791 	freePairs = pair->next;
3792 	nFreePairs--;
3793     }
3794     freeMutex(FPairMutex);
3795     if (!pair) pair = malloc(sizeof(Pair));
3796     if (pair) {
3797 	pair->common = type_pair;
3798 	pair->t = getExBuf();
3799 	if (!pair->t) {
3800 	    free(pair);
3801 	    return NULL;
3802 	}
3803 	pair->nbuf = 1;
3804 	pair->sd = INVALID_SOCKET;
3805 	pair->stone = NULL;
3806 	pair->proto = 0;
3807 	pair->xhost = NULL;
3808 	pair->timeout = PairTimeOut;
3809 	pair->count = 0;
3810 	pair->b = pair->t;
3811 	pair->d = NULL;
3812 	pair->log = NULL;
3813 	pair->tx = 0;
3814 	pair->rx = 0;
3815 	pair->loop = 0;
3816 	time(&pair->clock);
3817 	pair->pair = NULL;
3818 	pair->next = NULL;
3819 	pair->prev = NULL;
3820 #ifdef USE_SSL
3821 	pair->ssl = NULL;
3822 	pair->ssl_flag = 0;
3823 #endif
3824     }
3825     return pair;
3826 }
3827 
freePair(Pair * pair)3828 void freePair(Pair *pair) {
3829     SOCKET sd;
3830     TimeLog *log;
3831 #ifdef USE_SSL
3832     SSL *ssl;
3833 #endif
3834     ExBuf *ex;
3835     if (!pair) return;
3836     sd = pair->sd;
3837     pair->sd = INVALID_SOCKET;
3838     if (Debug > 8) message(LOG_DEBUG, "%d TCP %d: freePair",
3839 			   pair->stone->sd, sd);
3840     ex = pair->d;
3841     pair->d = NULL;
3842     while (ex) {
3843 	ExBuf *f = ex;
3844 	ex = f->next;
3845 	f->next = NULL;
3846 	ungetExBuf(f);
3847     }
3848     log = pair->log;
3849     if (log) {
3850 	pair->log = NULL;
3851 	free(log);
3852     }
3853 #ifdef USE_SSL
3854     ssl = pair->ssl;
3855     if (ssl) {
3856 	SSL_CTX *ctx = NULL;
3857 	int state;
3858 	pair->ssl = NULL;
3859 	state = SSL_get_shutdown(ssl);
3860 	if (!(state & SSL_RECEIVED_SHUTDOWN) && Debug > 2) {
3861 	    message(LOG_DEBUG, "%d TCP %d: SSL close notify was not received",
3862 		    pair->stone->sd, sd);
3863 	}
3864 	if (!(state & SSL_SENT_SHUTDOWN) && Debug > 2) {
3865 	    message(LOG_DEBUG, "%d TCP %d: SSL close notify was not sent",
3866 		    pair->stone->sd, sd);
3867 	    SSL_set_shutdown(ssl, (state | SSL_SENT_SHUTDOWN));
3868 	}
3869 	char **match = SSL_get_ex_data(ssl, MatchIndex);
3870 	if (match) {
3871 	    int i;
3872 	    for (i=0; i <= NMATCH_MAX; i++) {
3873 		if (match[i]) free(match[i]);
3874 	    }
3875 	    if (Debug > 4) message(LOG_DEBUG, "freeMatch %d: %llx",
3876 				   --NewMatchCount, (long long)match);
3877 	    free(match);
3878 	}
3879 	SSL_free(ssl);
3880 	if (pair->stone->proto & proto_ssl_s) {
3881 	    ctx = pair->stone->ssl_server->ctx;
3882 	}
3883 	if (ctx) SSL_CTX_flush_sessions(ctx, pair->clock);
3884     }
3885 #endif
3886     pair->b = NULL;
3887     ex = pair->t;
3888     pair->t = NULL;
3889     while (ex) {
3890 	ExBuf *f = ex;
3891 	ex = f->next;
3892 	f->next = NULL;
3893 	pair->nbuf--;
3894 	if (Debug > 4) message(LOG_DEBUG, "%d TCP %d: freePair "
3895 			       "unget ExBuf nbuf=%d nfex=%d",
3896 			       pair->stone->sd, sd, pair->nbuf, nFreeExBuf);
3897 	ungetExBuf(f);
3898     }
3899     if (ValidSocket(sd)) {
3900 #ifdef USE_EPOLL
3901 	if (Debug > 6)
3902 	    message(LOG_DEBUG, "%d TCP %d: freePair "
3903 		    "epoll_ctl %d DEL %lx",
3904 		    pair->stone->sd, sd, ePollFd, (long)pair);
3905 	epoll_ctl(ePollFd, EPOLL_CTL_DEL, sd, NULL);
3906 #endif
3907 	closesocket(sd);
3908     }
3909     waitMutex(FPairMutex);
3910     if (pair->clock == 0) {
3911 	freeMutex(FPairMutex);
3912 	message(LOG_ERR, "freePair duplication. can't happen, ignore");
3913 	return;
3914     }
3915     pair->clock = 0;
3916     pair->next = freePairs;
3917     freePairs = pair;
3918     nFreePairs++;
3919     freeMutex(FPairMutex);
3920 }
3921 
insertPairs(Pair * p1)3922 void insertPairs(Pair *p1) {
3923     Pair *p2 = p1->pair;
3924     Stone *stone = p1->stone;
3925     p1->next = p2;	/* link pair each other */
3926     p2->prev = p1;
3927     waitMutex(PairMutex);
3928     p2->next = stone->pairs->next;	/* insert pair */
3929     if (stone->pairs->next != NULL) stone->pairs->next->prev = p2;
3930     p1->prev = stone->pairs;
3931     stone->pairs->next = p1;
3932     freeMutex(PairMutex);
3933     if (Debug > 4) {
3934 	message(LOG_DEBUG, "%d TCP %d: pair %d inserted",
3935 		stone->sd, p1->sd, p2->sd);
3936 	message_pair(LOG_DEBUG, p1);
3937     }
3938 }
3939 
message_time_log(Pair * pair)3940 void message_time_log(Pair *pair) {
3941     TimeLog *log = pair->log;
3942     if (log && log->clock) {
3943 #ifdef THREAD_UNSAFE
3944 	struct tm *t = localtime(&log->clock);
3945 #else
3946 	struct tm tm;
3947 	struct tm *t = localtime_r(&log->clock, &tm);
3948 #endif
3949 	time_t now;
3950 	time(&now);
3951 	message(log->pri, "%02d:%02d:%02d %d %s",
3952 		t->tm_hour, t->tm_min, t->tm_sec,
3953 		(int)(now - log->clock), log->str);
3954 	log->clock = 0;
3955     }
3956 }
3957 
3958 /* after connect(2) successfully completed */
connected(Pair * pair)3959 void connected(Pair *pair) {
3960     Pair *p = pair->pair;
3961     if (Debug > 2)
3962 	message(LOG_DEBUG, "%d TCP %d: established to %d %08x %08x",
3963 		pair->stone->sd, p->sd, pair->sd, p->proto, pair->proto);
3964     time(&lastEstablished);
3965     /* now successfully connected */
3966 #ifdef USE_SSL
3967     if ((pair->stone->proto & proto_ssl_d) || (pair->ssl_flag & sf_cb_on_r)) {
3968 	if (doSSL_connect(pair) < 0) {
3969 	    /* SSL_connect fails, shutdown pairs */
3970 	    if (!(p->proto & proto_shutdown))
3971 		if (doshutdown(p, 2) >= 0)
3972 		    p->proto |= (proto_shutdown | proto_dirty);
3973 	    p->proto |= (proto_close | proto_dirty);
3974 	    pair->proto |= (proto_close | proto_dirty);
3975 	    return;
3976 	}
3977     } else
3978 #endif	/* pair & dst is connected */
3979     {
3980 	pair->proto |= (proto_connect | proto_dirty);
3981 	p->proto |= proto_dirty;	/* src */
3982     }
3983     /*
3984       SSL connection may not be established yet,
3985       but we can prepare for read/write
3986     */
3987     if (pair->t->len > 0) {
3988 	if (Debug > 8)
3989 	    message(LOG_DEBUG, "%d TCP %d: waiting %d bytes to write",
3990 		    pair->stone->sd, pair->sd, pair->t->len);
3991 	if (!(pair->proto & proto_shutdown))
3992 	    pair->proto |= (proto_select_w | proto_dirty);
3993     } else if (!(pair->proto & proto_ohttp_d)) {
3994 	if (Debug > 8)
3995 	    message(LOG_DEBUG, "%d TCP %d: request to read 1st",
3996 		    pair->stone->sd, p->sd);
3997 	if (!(p->proto & proto_eof))
3998 	    p->proto |= (proto_select_r | proto_dirty);
3999     }
4000     if (!(p->proto & proto_ohttp_s)) {
4001 	if (p->t->len > 0) {
4002 	    if (Debug > 8)
4003 		message(LOG_DEBUG, "%d TCP %d: waiting %d bytes to write",
4004 			pair->stone->sd, p->sd, p->t->len);
4005 	    if (!(p->proto & proto_shutdown))
4006 		p->proto |= (proto_select_w | proto_dirty);
4007 	} else {
4008 	    if (Debug > 8)
4009 		message(LOG_DEBUG, "%d TCP %d: request to read",
4010 			pair->stone->sd, pair->sd);
4011 	    if (!(pair->proto & proto_eof))
4012 		pair->proto |= (proto_select_r | proto_dirty);
4013 	}
4014     }
4015 }
4016 
message_conn(int pri,Conn * conn)4017 void message_conn(int pri, Conn *conn) {
4018     SOCKET sd = INVALID_SOCKET;
4019     Pair *p1, *p2;
4020     int proto = 0;
4021     int i = 0;
4022     char str[LONGSTRMAX+1];
4023     str[LONGSTRMAX] = '\0';
4024     p1 = conn->pair;
4025     if (p1) {
4026 	p2 = p1->pair;
4027 	strntime(str, LONGSTRMAX, &p1->clock, -1);
4028 	i = strlen(str);
4029 	proto = p1->proto;
4030 	if (p2) sd = p2->sd;
4031     }
4032     addrport2str(&conn->dst->addr, conn->dst->len, (proto & proto_pair_d),
4033 		 str+i, LONGSTRMAX-i, 0);
4034     i = strlen(str);
4035     if (i > LONGSTRMAX) i = LONGSTRMAX;
4036     str[i] = '\0';
4037     message(pri, "Conn %d: %08x %s", sd, proto, str);
4038 }
4039 
doconnect(Pair * p1,struct sockaddr * sa,socklen_t salen)4040 int doconnect(Pair *p1, struct sockaddr *sa, socklen_t salen) {
4041     struct sockaddr_storage ss;
4042     struct sockaddr *dst = (struct sockaddr*)&ss;	/* destination */
4043     socklen_t dstlen;
4044     int ret;
4045     Pair *p2;
4046     time_t clock;
4047     char addrport[STRMAX+1];
4048 #ifdef USE_EPOLL
4049     struct epoll_event ev;
4050 #endif
4051 #ifdef WINDOWS
4052     u_long param;
4053 #endif
4054     if (p1 == NULL) return -1;
4055     p2 = p1->pair;
4056     if (p2 == NULL) return -1;
4057     if (!(p2->proto & proto_connect)) return 0;
4058     bcopy(sa, dst, salen);
4059     dstlen = salen;
4060     time(&clock);
4061     if (Debug > 8) message(LOG_DEBUG, "%d TCP %d: doconnect",
4062 			   p1->stone->sd, p1->sd);
4063     if (!p1->stone->ndsts && !stone_dsts(p1->stone, NULL, NULL)) return -1;
4064     ret = modPairDest(p1, dst, sizeof(ss));
4065     if (ret > 0) dstlen = ret;	/* dest is modified */
4066     else if (ret == -2) return ret;	/* dest is not detemined yet */
4067     /*
4068       now destination is determined, engage
4069     */
4070     if (!(p1->stone->proto & proto_block_d)) {
4071 #ifdef WINDOWS
4072 	param = 1;
4073 	ioctlsocket(p1->sd, FIONBIO, &param);
4074 #else
4075 	fcntl(p1->sd, F_SETFL, O_NONBLOCK);
4076 #endif
4077     }
4078     addrport[0] = '\0';
4079     if (Debug > 2) {
4080 	addrport2strOnce(dst, dstlen, (p1->proto & proto_pair_d),
4081 			 addrport, STRMAX, 0);
4082 	message(LOG_DEBUG, "%d TCP %d: connecting to TCP %d %s",
4083 		p1->stone->sd, p2->sd, p1->sd, addrport);
4084     }
4085     if (p1->proto & proto_dgram) {
4086 	ret = 0;	/* do nothing */
4087     } else {
4088 	ret = connect(p1->sd, dst, dstlen);
4089     }
4090     if (ret < 0) {
4091 #ifdef WINDOWS
4092 	errno = WSAGetLastError();
4093 #endif
4094 	if (errno == EINPROGRESS) {
4095 	    p1->proto |= (proto_conninprog | proto_dirty);
4096 	    if (Debug > 3)
4097 		message(LOG_DEBUG, "%d TCP %d: connection in progress",
4098 			p1->stone->sd, p1->sd);
4099 	    goto done;
4100 	} else if (errno == EINTR) {
4101 	    if (Debug > 4)
4102 		message(LOG_DEBUG, "%d TCP %d: connect interrupted",
4103 			p1->stone->sd, p1->sd);
4104 	    if (clock - p1->clock < CONN_TIMEOUT) return 0;
4105 	    addrport2strOnce(dst, dstlen, (p1->proto & proto_pair_d),
4106 			     addrport, STRMAX, 0);
4107 	    message(priority(p2), "%d TCP %d: connect timeout to %s",
4108 		    p2->stone->sd, p2->sd, addrport);
4109 	} else if (errno == EISCONN || errno == EADDRINUSE
4110 #ifdef EALREADY
4111 		   || errno == EALREADY
4112 #endif
4113 	    ) {
4114 	    if (Debug > 4) {	/* SunOS's bug ? */
4115 		message(LOG_DEBUG, "%d TCP %d: connect bug err=%d",
4116 			p1->stone->sd, p1->sd, errno);
4117 		message_pair(LOG_DEBUG, p1);
4118 	    }
4119 	} else {
4120 	    addrport2strOnce(dst, dstlen, (p1->proto & proto_pair_d),
4121 			     addrport, STRMAX, 0);
4122 	    message(priority(p1),
4123 		    "%d TCP %d: can't connect err=%d: to %s",
4124 		    p1->stone->sd, p1->sd, errno, addrport);
4125 	}
4126     }
4127     if (ret < 0		/* fail to connect */
4128 	|| (p1->proto & proto_close)
4129 	|| (p2->proto & proto_close)) {
4130 	if (!(p2->proto & proto_shutdown))
4131 	    if (doshutdown(p2, 2) >= 0)
4132 		p2->proto |= (proto_shutdown | proto_dirty);
4133 	p2->proto |= (proto_close | proto_dirty);
4134 	p1->proto |= (proto_close | proto_dirty);
4135 	return -1;
4136     }
4137     connected(p1);
4138 done:
4139 #ifdef USE_EPOLL
4140     ev.events = EPOLLONESHOT;
4141     ev.data.ptr = p1;
4142     if (Debug > 6)
4143 	message(LOG_DEBUG, "%d TCP %d: doconnect epoll_ctl %d ADD %lx",
4144 		p1->stone->sd, p1->sd, ePollFd, (long)ev.data.ptr);
4145     if (epoll_ctl(ePollFd, EPOLL_CTL_ADD, p1->sd, &ev) < 0) {
4146 	message(LOG_ERR, "%d TCP %d: doconnect epoll_ctl %d ADD err=%d",
4147 		p1->stone->sd, p1->sd, ePollFd, errno);
4148     }
4149 #endif
4150     return 1;
4151 }
4152 
freeConn(Conn * conn)4153 void freeConn(Conn *conn) {
4154     if (conn->dst) free(conn->dst);
4155     free(conn);
4156 }
4157 
reqconn(Pair * pair,struct sockaddr * dst,socklen_t dstlen)4158 int reqconn(Pair *pair,		/* request pair to connect to destination */
4159 	    struct sockaddr *dst, socklen_t dstlen) {	/* connect to */
4160     int ret;
4161     Conn *conn;
4162     Pair *p = pair->pair;
4163     if ((pair->proto & proto_command) == command_proxy
4164 	|| (pair->proto & proto_command) == command_health
4165 	|| (pair->proto & proto_command) == command_identd) {
4166 	pair->proto |= proto_noconnect;
4167 	if (p && !(p->proto & (proto_eof | proto_close))) {
4168 	    /* must read request header */
4169 	    p->proto |= (proto_select_r | proto_dirty);
4170 	}
4171 	return 0;
4172     }
4173     ret = doconnect(pair, dst, dstlen);
4174     if (ret < 0) {
4175 	if (ret == -2) {
4176 	    /* must read more to determine dest */
4177 	    p->proto |= (proto_select_r | proto_dirty);
4178 	    return 0;
4179 	}
4180 	return -1;	/* error */
4181     }
4182     if (ret > 0) return ret;	/* connected or connection in progress */
4183     conn = malloc(sizeof(Conn));
4184     if (!conn) {
4185     memerr:
4186 	message(LOG_CRIT, "%d TCP %d: out of memory",
4187 		(p ? p->stone->sd : -1), (p ? p->sd : -1));
4188 	return -1;
4189     }
4190     time(&pair->clock);
4191     p->clock = pair->clock;
4192     pair->count += REF_UNIT;	/* request to connect */
4193     conn->pair = pair;
4194     conn->dst = saDup(dst, dstlen);
4195     if (!conn->dst) {
4196 	free(conn);
4197 	goto memerr;
4198     }
4199     conn->lock = 0;
4200     waitMutex(ConnMutex);
4201     conn->next = conns.next;
4202     conns.next = conn;
4203     freeMutex(ConnMutex);
4204     return 0;
4205 }
4206 
asyncConn(Conn * conn)4207 void asyncConn(Conn *conn) {
4208     Pair *p1, *p2;
4209     ASYNC_BEGIN;
4210     if (Debug > 8) message(LOG_DEBUG, "asyncConn");
4211     p1 = conn->pair;
4212     if (p1 == NULL) {
4213 	conn->pair = NULL;
4214 	conn->lock = -1;
4215     } else {
4216 	int ret = doconnect(p1, &conn->dst->addr, conn->dst->len);
4217 	if (ret == 0 || ret == -2) {
4218 	    conn->lock = 0;
4219 	} else {	/* no more request to connect */
4220 	    if (p1) p1->count -= REF_UNIT;
4221 	    conn->pair = NULL;
4222 	    conn->lock = -1;
4223 	}
4224     }
4225     if (p1) {
4226 #ifndef USE_EPOLL
4227 	p1->proto &= ~proto_thread;
4228 #endif
4229 	p1->proto |= proto_dirty;
4230 	p2 = p1->pair;
4231     } else {
4232 	p2 = NULL;
4233     }
4234     if (p2) {
4235 #ifndef USE_EPOLL
4236 	p2->proto &= ~proto_thread;
4237 #endif
4238 	p2->proto |= proto_dirty;
4239     }
4240     ASYNC_END;
4241 }
4242 
4243 /* scan conn request */
scanConns(void)4244 int scanConns(void) {
4245     Conn *conn, *pconn;
4246     Pair *p1, *p2;
4247     if (Debug > 8) message(LOG_DEBUG, "scanConns");
4248     pconn = &conns;
4249     for (conn=conns.next; conn != NULL; conn=conn->next) {
4250 	p1 = conn->pair;
4251 	if (p1) p2 = p1->pair;
4252 	if (p1 && !(p1->proto & proto_close) &&
4253 	    p2 && !(p2->proto & proto_close)) {
4254 	    if ((p2->proto & proto_connect) && conn->lock == 0
4255 #ifndef USE_EPOLL
4256 		&& !(p1->proto & proto_thread)
4257 		&& !(p2->proto & proto_thread)
4258 #endif
4259 		) {
4260 		conn->lock = 1;		/* lock conn */
4261 		if (Debug > 4) message_conn(LOG_DEBUG, conn);
4262 #ifndef USE_EPOLL
4263 		p1->proto |= (proto_thread | proto_dirty);
4264 		p2->proto |= (proto_thread | proto_dirty);
4265 #endif
4266 		ASYNC(asyncConn, conn);
4267 	    }
4268 	} else {
4269 	    waitMutex(ConnMutex);
4270 	    if (pconn->next == conn && conn->lock <= 0) {
4271 		pconn->next = conn->next;	/* remove conn */
4272 		freeConn(conn);
4273 		conn = pconn;
4274 	    }
4275 	    freeMutex(ConnMutex);
4276 	}
4277 	pconn = conn;
4278     }
4279     return 1;
4280 }
4281 
acceptPair(Stone * stone)4282 Pair *acceptPair(Stone *stone) {
4283     struct sockaddr_storage ss;
4284     struct sockaddr *from = (struct sockaddr*)&ss;
4285     socklen_t fromlen = sizeof(ss);
4286     Pair *pair;
4287 #ifdef USE_EPOLL
4288     struct epoll_event ev;
4289 #endif
4290     SOCKET nsd = accept(stone->sd, from, &fromlen);
4291     if (InvalidSocket(nsd)) {
4292 #ifdef WINDOWS
4293 	errno = WSAGetLastError();
4294 #endif
4295 	if (errno == EINTR) {
4296 	    if (Debug > 4)
4297 		message(LOG_DEBUG, "stone %d: accept interrupted", stone->sd);
4298 	    return NULL;
4299 	} else if (errno == EAGAIN) {
4300 	    if (Debug > 4)
4301 		message(LOG_DEBUG, "stone %d: accept no connection",
4302 			stone->sd);
4303 	    return NULL;
4304 	}
4305 #ifndef NO_FORK
4306 	else if (errno == EBADF && Debug < 5) {
4307 	    return NULL;
4308 	}
4309 #endif
4310 	message(LOG_ERR, "stone %d: accept error err=%d", stone->sd, errno);
4311 	return NULL;
4312     }
4313     pair = newPair();
4314     if (!pair) {
4315 	message(LOG_CRIT, "stone %d: out of memory, closing TCP %d",
4316 		stone->sd, nsd);
4317 	closesocket(nsd);
4318 	freePair(pair);
4319 	return NULL;
4320     }
4321     bcopy(&fromlen, pair->t->buf, sizeof(fromlen));	/* save to ExBuf */
4322     bcopy(from, pair->t->buf + sizeof(fromlen), fromlen);
4323     pair->sd = nsd;
4324     pair->stone = stone;
4325     pair->proto = ((stone->proto & proto_pair_s & ~proto_command) |
4326 		   proto_first_r | proto_first_w | command_source);
4327     pair->timeout = stone->timeout;
4328 #ifdef USE_EPOLL
4329     ev.events = EPOLLONESHOT;
4330     ev.data.ptr = pair;
4331     if (Debug > 6)
4332 	message(LOG_DEBUG, "%d TCP %d: acceptPair epoll_ctl %d ADD %lx",
4333 		stone->sd, pair->sd, ePollFd, (long)ev.data.ptr);
4334     if (epoll_ctl(ePollFd, EPOLL_CTL_ADD, pair->sd, &ev) < 0) {
4335 	message(LOG_ERR, "%d TCP %d: acceptPair epoll_ctl %d ADD err=%d",
4336 		stone->sd, pair->sd, ePollFd, errno);
4337     }
4338 #endif
4339     return pair;
4340 }
4341 
getident(char * str,struct sockaddr * sa,socklen_t salen,int cport,struct sockaddr * csa,socklen_t csalen)4342 int getident(char *str, struct sockaddr *sa, socklen_t salen,
4343 	     int cport, struct sockaddr *csa, socklen_t csalen) {
4344     /* (size of str) >= STRMAX+1 */
4345     SOCKET sd;
4346     struct sockaddr_storage ss;
4347     struct sockaddr *peer = (struct sockaddr*)&ss;
4348     socklen_t peerlen = sizeof(ss);
4349     int sport = getport(sa);
4350     char buf[LONGSTRMAX+1];
4351     char c;
4352     int len;
4353     int ret;
4354     char addr[STRMAX+1];
4355 #ifdef WINDOWS
4356     u_long param;
4357 #endif
4358     time_t start, now;
4359 #ifdef USE_EPOLL
4360     int epfd = INVALID_SOCKET;
4361     struct epoll_event ev;
4362     struct epoll_event evs[1];
4363 #endif
4364     time(&start);
4365     bcopy(sa, peer, salen);
4366     peerlen = salen;
4367     if (str) {
4368 	str[0] = '\0';
4369     }
4370     sd = socket(peer->sa_family, SOCK_STREAM, IPPROTO_TCP);
4371     if (InvalidSocket(sd)) {
4372 #ifdef WINDOWS
4373 	errno = WSAGetLastError();
4374 #endif
4375 	if (Debug > 0)
4376 	    message(LOG_DEBUG, "ident: can't create socket err=%d", errno);
4377 	return 0;
4378     }
4379     saPort(csa, 0);
4380     if (bind(sd, csa, csalen) < 0) {
4381 #ifdef WINDOWS
4382 	errno = WSAGetLastError();
4383 #endif
4384 	if (Debug > 0)
4385 	    message(LOG_DEBUG, "ident: can't bind socket err=%d", errno);
4386 	/* hope default source address is adequate */
4387     }
4388     saPort(peer, 113);	/* ident protocol */
4389     addr2str(peer, peerlen, addr, STRMAX, 0);
4390     addr[STRMAX] = '\0';
4391 #ifdef WINDOWS
4392     param = 1;
4393     ioctlsocket(sd, FIONBIO, &param);
4394 #else
4395     fcntl(sd, F_SETFL, O_NONBLOCK);
4396 #endif
4397 #ifdef USE_EPOLL
4398     epfd = epoll_create(BACKLOG_MAX);
4399     if (epfd < 0) {
4400 	message(LOG_ERR, "ident: can't create epoll err=%d", errno);
4401 	epfd = INVALID_SOCKET;
4402 	goto noconnect;	/* I can't tell the master is healthy or not */
4403     }
4404     ev.events = (EPOLLOUT | EPOLLONESHOT);
4405     if (epoll_ctl(epfd, EPOLL_CTL_ADD, sd, &ev) < 0) {
4406 	message(LOG_ERR, "ident: epoll_ctl ADD err=%d", errno);
4407 	goto noconnect;
4408     }
4409 #endif
4410     ret = connect(sd, peer, peerlen);
4411     if (ret < 0) {
4412 #ifdef WINDOWS
4413 	errno = WSAGetLastError();
4414 #endif
4415 	if (errno == EINPROGRESS) {
4416 #ifndef USE_EPOLL
4417 	    fd_set wout;
4418 	    struct timeval tv;
4419 #endif
4420 	    do {
4421 		time(&now);
4422 		if (now - start >= CONN_TIMEOUT) {
4423 		    if (Debug > 0)
4424 			message(LOG_DEBUG, "ident: connect to %s, timeout",
4425 				addr);
4426 		    goto noconnect;
4427 		}
4428 #ifndef USE_EPOLL
4429 		tv.tv_sec = 1;
4430 		tv.tv_usec = 0;
4431 		FD_ZERO(&wout);
4432 		FdSet(sd, &wout);
4433 #endif
4434 	    } while (
4435 #ifdef USE_EPOLL
4436 		epoll_wait(epfd, evs, 1, 1000) == 0
4437 #else
4438 		select(FD_SETSIZE, NULL, &wout, NULL, &tv) == 0
4439 #endif
4440 		);
4441 	} else {
4442 	    if (Debug > 0)
4443 		message(LOG_DEBUG, "ident: can't connect to %s, err=%d",
4444 			addr, errno);
4445 	noconnect:
4446 #ifdef USE_EPOLL
4447 	    if (ValidSocket(epfd)) close(epfd);
4448 #endif
4449 	    closesocket(sd);
4450 	    return 0;
4451 	}
4452     }
4453 #ifdef USE_EPOLL
4454     ev.events = (EPOLLIN | EPOLLONESHOT);
4455     if (epoll_ctl(epfd, EPOLL_CTL_MOD, sd, &ev) < 0) {
4456 	message(LOG_ERR, "ident: epoll_ctl MOD err=%d", errno);
4457 	goto noconnect;
4458     }
4459 #endif
4460     snprintf(buf, LONGSTRMAX, "%d, %d%c%c", sport, cport, '\r', '\n');
4461     len = strlen(buf);
4462     ret = send(sd, buf, len, 0);
4463     if (ret != len) {
4464 #ifdef WINDOWS
4465 	errno = WSAGetLastError();
4466 #endif
4467 	if (Debug > 0)
4468 	    message(LOG_DEBUG,
4469 		    "ident: can't send  to %s ret=%d err=%d buf=%s",
4470 		    addr, ret, errno, buf);
4471     error:
4472 	shutdown(sd, 2);
4473 #ifdef USE_EPOLL
4474 	if (ValidSocket(epfd)) close(epfd);
4475 #endif
4476 	closesocket(sd);
4477 	return 0;
4478     } else {
4479 #ifndef USE_EPOLL
4480 	fd_set rout;
4481 	struct timeval tv;
4482 #endif
4483 	do {
4484 	    time(&now);
4485 	    if (now - start >= CONN_TIMEOUT) {
4486 		if (Debug > 0)
4487 		    message(LOG_DEBUG, "ident: read from %s, timeout", addr);
4488 		goto error;
4489 	    }
4490 #ifndef USE_EPOLL
4491 	    tv.tv_sec = 1;
4492 	    tv.tv_usec = 0;
4493 	    FD_ZERO(&rout);
4494 	    FdSet(sd, &rout);
4495 #endif
4496 	} while (
4497 #ifdef USE_EPOLL
4498 	    epoll_wait(epfd, evs, 1, 1000) == 0
4499 #else
4500 	    select(FD_SETSIZE, &rout, NULL, NULL, &tv) == 0
4501 #endif
4502 	    );
4503 	ret = recv(sd, buf, LONGSTRMAX, 0);
4504 	if (ret <= 0) {
4505 	    if (Debug > 0)
4506 		message(LOG_DEBUG, "ident: can't read from %s, ret=%d",
4507 			addr, ret);
4508 	    goto error;
4509 	}
4510 	shutdown(sd, 2);
4511 #ifdef USE_EPOLL
4512 	if (ValidSocket(epfd)) close(epfd);
4513 #endif
4514 	closesocket(sd);
4515     }
4516     do {
4517 	ret--;
4518 	c = buf[ret];
4519     } while (ret > 0 && (c == '\r' || c == '\n'));
4520     ret++;
4521     buf[ret] = '\0';
4522     if (Debug > 2)
4523 	message(LOG_DEBUG, "ident: sent %s:%d, %d got %s",
4524 		addr, sport, cport, buf);
4525     if (str) {
4526 	char *p;
4527 	p = rindex(buf, ':');
4528 	if (p) {
4529 	    int i;
4530 	    do {
4531 		p++;
4532 	    } while (*p == ' ');
4533 	    for (i=0; i < STRMAX && *p; i++) str[i] = *p++;
4534 	    str[i] = '\0';
4535 	}
4536     }
4537     return 1;
4538 }
4539 
acceptCheck(Pair * pair1)4540 int acceptCheck(Pair *pair1) {
4541     struct sockaddr_storage ss;
4542     struct sockaddr *from = (struct sockaddr*)&ss;
4543     socklen_t fromlen = sizeof(ss);
4544     Stone *stone = pair1->stone;
4545     Pair *pair2 = NULL;
4546     int satype;
4547     int saproto = 0;
4548 #ifdef ENLARGE
4549     int prevXferBufMax = XferBufMax;
4550 #endif
4551     XHosts *xhost;
4552     char ident[STRMAX+1];
4553     char fromstr[STRMAX*2+1];
4554     int fslen;
4555     fslen = 0;
4556     ident[0] = '\0';
4557     bcopy(pair1->t->buf, &fromlen, sizeof(fromlen));	/* restore */
4558     if (0 < fromlen && fromlen <= (socklen_t)sizeof(ss)) {
4559 	bcopy(pair1->t->buf + sizeof(fromlen), from, fromlen);
4560     } else {
4561 	message(LOG_ERR, "%d TCP %d: acceptCheck Can't happen fromlen=%d",
4562 		stone->sd, pair1->sd, fromlen);
4563 	if (getpeername(pair1->sd, from, &fromlen) < 0) {
4564 #ifdef WINDOWS
4565 	    errno = WSAGetLastError();
4566 #endif
4567 	    message(LOG_ERR,
4568 		    "%d TCP %d: acceptCheck Can't get peer's name err=%d",
4569 		    stone->sd, pair1->sd, errno);
4570 	    return 0;
4571 	}
4572     }
4573     if (stone->proto & proto_ident) {
4574 	if (getident(ident, from, fromlen, stone->port,
4575 		     &stone->listen->addr, stone->listen->len)) {
4576 	    ExBuf *t = newExData(pair1, data_identuser);
4577 	    strncpy(fromstr, ident, STRMAX);	/* (size of ident) <= STRMAX */
4578 	    fromstr[STRMAX] = '\0';
4579 	    fslen = strlen(fromstr);
4580 	    if (t) {
4581 		strcpy(t->buf + DATA_HEAD_LEN, fromstr);
4582 		t->len = DATA_HEAD_LEN + fslen;
4583 	    }
4584 	    /* omit size check, because fslen <= STRMAX */
4585 	    fromstr[fslen++] = '@';
4586 	}
4587     }
4588     fromstr[fslen] = '\0';
4589     xhost = checkXhost(stone->xhosts, from, fromlen);
4590     if (!xhost) {
4591 	addrport2strOnce(from, fromlen, (stone->proto & proto_stone_s),
4592 			 fromstr+fslen, STRMAX*2-fslen, 0);
4593 	message(LOG_WARNING, "stone %d: access denied: from %s",
4594 		stone->sd, fromstr);
4595 	shutdown(pair1->sd, 2);
4596 	return 0;
4597     }
4598     if (AccFp) {
4599 	char str[STRMAX+1];
4600 	char tstr[STRMAX+1];
4601 	time_t clock;
4602 	time(&clock);
4603 	addr2str(from, fromlen, str, STRMAX, NI_NUMERICHOST);
4604 	str[STRMAX] = '\0';
4605 	strntime(tstr, STRMAX, &clock, -1);
4606 	tstr[STRMAX] = '\0';
4607 	addrport2strOnce(from, fromlen, (stone->proto & proto_stone_s),
4608 			 fromstr+fslen, STRMAX*2-fslen, 0);
4609 	fprintf(AccFp, "%s%d[%d] %s[%s]\n",
4610 		tstr, stone->port, (int)stone->sd, fromstr, str);
4611 
4612     }
4613     if ((xhost->mode & XHostsMode_Dump) > 0 || Debug > 1) {
4614 	addrport2strOnce(from, fromlen, (stone->proto & proto_stone_s),
4615 			 fromstr+fslen, STRMAX*2-fslen, 0);
4616 	message(LOG_DEBUG, "stone %d: accepted TCP %d from %s mode=%d",
4617 		stone->sd, pair1->sd, fromstr, xhost->mode);
4618     }
4619     pair2 = newPair();
4620     if (!pair2) {
4621 	message(LOG_CRIT, "stone %d: out of memory, closing TCP %d",
4622 		stone->sd, pair1->sd);
4623 	if (pair2) freePair(pair2);
4624 	return 0;
4625     }
4626     pair2->stone = stone;
4627     pair1->xhost = pair2->xhost = xhost;
4628     pair2->proto = ((stone->proto & proto_pair_d) |
4629 		    proto_first_r | proto_first_w);
4630     pair2->timeout = stone->timeout;
4631     /* now successfully accepted */
4632     if (!(stone->proto & proto_block_d)) {
4633 #ifdef WINDOWS
4634 	u_long param;
4635 	param = 1;
4636 	ioctlsocket(pair1->sd, FIONBIO, &param);
4637 #else
4638 	fcntl(pair1->sd, F_SETFL, O_NONBLOCK);
4639 #endif
4640     }
4641 #ifdef USE_SSL
4642     if (stone->proto & proto_ssl_s) {
4643 	if (doSSL_accept(pair1) < 0) goto error;
4644     } else
4645 #endif	/* src & pair1 is connected */
4646 	pair1->proto |= (proto_connect | proto_dirty);
4647     /*
4648       SSL connection may not be established yet,
4649       but we can prepare the pair for connecting to the destination
4650     */
4651     if (stone->proto & proto_udp_d) {
4652 	pair2->proto |= proto_dgram;
4653 	satype = SOCK_DGRAM;
4654 	saproto = IPPROTO_UDP;
4655     } else {
4656 	satype = SOCK_STREAM;
4657 	saproto = IPPROTO_TCP;
4658     }
4659 #ifdef AF_LOCAL
4660     if (stone->proto & proto_unix_d) {
4661 	saproto = 0;
4662 	pair2->sd = socket(AF_LOCAL, satype, saproto);
4663     } else
4664 #endif
4665 #ifdef AF_INET6
4666     if (stone->proto & proto_v6_d)
4667 	pair2->sd = socket(AF_INET6, satype, saproto);
4668     else
4669 #endif
4670 	pair2->sd = socket(AF_INET, satype, saproto);
4671     if (InvalidSocket(pair2->sd)) {
4672 #ifdef WINDOWS
4673 	errno = WSAGetLastError();
4674 #endif
4675 	message(priority(pair1), "%d TCP %d: can't create socket err=%d",
4676 		stone->sd, pair1->sd, errno);
4677 #ifdef USE_SSL
4678     error:
4679 #endif
4680 	freePair(pair2);
4681 	return 0;
4682     }
4683     if (stone->from) {
4684 	if (bind(pair2->sd, &stone->from->addr, stone->from->len) < 0) {
4685 	    char str[STRMAX+1];
4686 #ifdef WINDOWS
4687 	    errno = WSAGetLastError();
4688 #endif
4689 	    addrport2str(&stone->from->addr, stone->from->len, 0,
4690 			 str, STRMAX, 0);
4691 	    str[STRMAX] = '\0';
4692 	    message(LOG_ERR, "stone %d: can't bind %s err=%d",
4693 		    stone->sd, str, errno);
4694 	}
4695     }
4696     pair2->pair = pair1;
4697     pair1->pair = pair2;
4698     return 1;
4699 }
4700 
strnAddr(char * buf,int limit,SOCKET sd,int which,int isport)4701 int strnAddr(char *buf, int limit, SOCKET sd, int which, int isport) {
4702     struct sockaddr_storage ss;
4703     struct sockaddr *name = (struct sockaddr*)&ss;
4704     socklen_t namelen = sizeof(ss);
4705     int len;
4706     char str[STRMAX+1];
4707     int ret;
4708     switch (which) {
4709 #ifdef SO_ORIGINAL_DST
4710     case 1:	/* original destination */
4711 	ret = getsockopt(sd, SOL_IP, SO_ORIGINAL_DST, name, &namelen);
4712 	break;
4713 #endif
4714     default:	/* peer */
4715 	ret = getpeername(sd, name, &namelen);
4716     }
4717     if (ret < 0) {
4718 	if (isport) {
4719 	    strcpy(str, "0.0.0.0:0");
4720 	} else {
4721 	    strcpy(str, "0.0.0.0");
4722 	}
4723     } else {
4724 	if (isport) {
4725 	    addrport2str(name, namelen, 0, str, STRMAX, 0);
4726 	} else {
4727 	    addr2str(name, namelen, str, STRMAX, 0);
4728 	}
4729 	str[STRMAX] = '\0';
4730     }
4731     len = strlen(str);
4732     if (len > limit) len = limit;
4733     strncpy(buf, str, len);
4734     return len;
4735 }
4736 
strnUser(char * buf,int limit,Pair * pair,int which)4737 int strnUser(char *buf, int limit, Pair *pair, int which) {
4738 #if defined(AF_LOCAL) && defined(SO_PEERCRED)
4739     Stone *stone = pair->stone;
4740 #endif
4741     ExBuf *ex;
4742     int len;
4743     char str[STRMAX+1];
4744     str[0] = '\0';
4745     if (which == 2 && (ex = getExData(pair, data_identuser, 0))) {
4746 	len = ex->len - DATA_HEAD_LEN;
4747 	strncpy(str, ex->buf + DATA_HEAD_LEN, len);
4748 	str[len] = '\0';
4749     } else
4750 #if defined(AF_LOCAL) && defined(SO_PEERCRED)
4751     if (stone->listen->addr.sa_family == AF_LOCAL) {
4752 	struct ucred *cred = NULL;
4753 	ex = getExData(pair, data_ucred, 0);
4754 	if (ex) {
4755 	    cred = (struct ucred*)(ex->buf + DATA_HEAD_LEN);
4756 	} else {
4757 	    socklen_t optlen = sizeof(*cred);
4758 	    ex = newExData(pair, data_ucred);
4759 	    if (ex) {
4760 		cred = (struct ucred*)(ex->buf + DATA_HEAD_LEN);
4761 		if (getsockopt(pair->sd, SOL_SOCKET, SO_PEERCRED,
4762 			       cred, &optlen) < 0) {
4763 		    message(LOG_ERR, "%d TCP %d: Can't get PEERCRED err=%d",
4764 			    stone->sd, pair->sd, errno);
4765 		    ungetExBuf(ex);
4766 		    cred = NULL;
4767 		}
4768 	    }
4769 	}
4770 	switch (which) {
4771 	case 1:	/* gid */
4772 	    snprintf(str, STRMAX, "%d", (cred ? (int)cred->gid : -1));
4773 	    break;
4774 	case 2:	/* user name */
4775 	    *str = '\0';
4776 	    if (cred) {
4777 #ifdef THREAD_UNSAFE
4778 		struct passwd *passwd = getpwuid(cred->uid);
4779 		if (passwd) snprintf(str, STRMAX, "%s", passwd->pw_name);
4780 #else
4781 		struct passwd pwbuf;
4782 		char sbuf[STRMAX+1];
4783 		struct passwd *passwd;
4784 		int ret = getpwuid_r(cred->uid, &pwbuf, sbuf, STRMAX, &passwd);
4785 		if (ret == 0) snprintf(str, STRMAX, "%s", passwd->pw_name);
4786 #endif
4787 	    }
4788 	    break;
4789 	case 3:	/* group name */
4790 	    *str = '\0';
4791 	    if (cred) {
4792 #ifdef THREAD_UNSAFE
4793 		struct group *group = getgrgid(cred->gid);
4794 		if (group) snprintf(str, STRMAX, "%s", group->gr_name);
4795 #else
4796 		struct group gbuf;
4797 		char sbuf[STRMAX+1];
4798 		struct group *group;
4799 		int ret = getgrgid_r(cred->gid, &gbuf, sbuf, STRMAX, &group);
4800 		if (ret == 0) snprintf(str, STRMAX, "%s", group->gr_name);
4801 #endif
4802 	    }
4803 	    break;
4804 	default:	/* uid */
4805 	    snprintf(str, STRMAX, "%d", (cred ? (int)cred->uid : -1));
4806 	    break;
4807 	}
4808     }
4809 #endif
4810     len = strlen(str);
4811     if (len > limit) len = limit;
4812     strncpy(buf, str, len);
4813     return len;
4814 }
4815 
strnparse(char * buf,int limit,char ** pp,Pair * pair,char term)4816 int strnparse(char *buf, int limit, char **pp, Pair *pair, char term) {
4817     int i = 0;
4818     char *p;
4819     char c;
4820 #ifdef USE_SSL
4821     char **match = NULL;
4822     SSL *ssl = pair->ssl;
4823     int cond;
4824 #endif
4825     p = *pp;
4826     while (i < limit && (c = *p++)) {
4827 	if (c == '\\') {
4828 	    c = *p++;
4829 	    if (c == term) break;
4830 #ifdef USE_SSL
4831 	    cond = -1;
4832 	    if (c == '?') {
4833 		cond = 0;
4834 		c = *p++;
4835 	    }
4836 	    if ('0' <= c && c <= '9') {
4837 		if (ssl && !match) {
4838 		    match = SSL_get_ex_data(ssl, MatchIndex);
4839 		    if (!match) ssl = NULL;
4840 		    /* now (match || ssl == NULL) holds */
4841 		}
4842 		if (match) {
4843 		    int num = c - '0';
4844 		    if (match[num]) {
4845 			if (cond >= 0) {
4846 			    if (*match[num]) cond = 1;
4847 			} else {
4848 			    int len = strlen(match[num]);
4849 			    if (len >= limit - i) len = limit - i;
4850 			    if (buf) {
4851 				strncpy(buf+i, match[num], len);
4852 				i += len;
4853 			    }
4854 			}
4855 		    }
4856 		}
4857 		if (cond > 0) {
4858 		    if (buf) {
4859 			i += strnparse(buf+i, limit-i, &p, pair, ':');
4860 			strnparse(NULL, limit-i, &p, pair, '/');
4861 		    }
4862 		} else if (cond == 0) {
4863 		    if (buf) {
4864 			strnparse(NULL, limit-i, &p, pair, ':');
4865 			i += strnparse(buf+i, limit-i, &p, pair, '/');
4866 		    }
4867 		}
4868 		continue;
4869 	    }
4870 #endif
4871 	    switch(c) {
4872 	    case 'n':  c = '\n';  break;
4873 	    case 'r':  c = '\r';  break;
4874 	    case 't':  c = '\t';  break;
4875 	    case 'a':	/* peer address */
4876 		if (buf) i += strnAddr(buf+i, limit-i, pair->sd, 0, 0);
4877 		continue;
4878 	    case 'A':	/* peer address:port */
4879 		if (buf) i += strnAddr(buf+i, limit-i, pair->sd, 0, 1);
4880 		continue;
4881 #ifdef SO_ORIGINAL_DST
4882 	    case 'd':	/* dst address */
4883 		if (buf) i += strnAddr(buf+i, limit-i, pair->sd, 1, 0);
4884 		continue;
4885 	    case 'D':	/* dst address:port (transparent proxy) */
4886 		if (buf) i += strnAddr(buf+i, limit-i, pair->sd, 1, 1);
4887 		continue;
4888 #endif
4889 	    case 'u':
4890 		if (buf) i += strnUser(buf+i, limit-i, pair, 0);
4891 		continue;
4892 	    case 'g':
4893 		if (buf) i += strnUser(buf+i, limit-i, pair, 1);
4894 		continue;
4895 	    case 'U':
4896 		if (buf) i += strnUser(buf+i, limit-i, pair, 2);
4897 		continue;
4898 	    case 'G':
4899 		if (buf) i += strnUser(buf+i, limit-i, pair, 3);
4900 		continue;
4901 	    case '\0':
4902 		c = '\\';
4903 		p--;
4904 	    }
4905 	}
4906 	if (buf) buf[i++] = c;
4907     }
4908     if (buf) buf[i] = '\0';
4909     *pp = p;
4910     return i;
4911 }
4912 
scanClose(Pair * pairs)4913 int scanClose(Pair *pairs) {	/* scan close request */
4914     Pair *p1, *p2, *p;
4915     int n = 0;
4916     int m = 0;
4917     int all;
4918     if (pairs) {
4919 	all = 0;
4920     } else {
4921 	pairs = PairTop;
4922 	all = 1;
4923     }
4924     p1 = trash.next;
4925     while (p1 != NULL) {
4926 	p2 = p1;
4927 	p1 = p1->next;
4928 #ifndef USE_EPOLL
4929 	if (p2->proto & proto_thread) continue;
4930 #endif
4931 	if (p2->count > 0) {
4932 	    p2->count--;
4933 	    n++;
4934 	    continue;
4935 	}
4936 	if (p2->proto & (proto_select_r | proto_select_w)) {
4937 	    p2->proto &= ~(proto_select_r | proto_select_w);
4938 	    p2->proto |= proto_dirty;
4939 	    p2->count = REF_UNIT;
4940 	}
4941 #ifdef USE_SSL
4942 	if (p2->ssl_flag) {
4943 	    p2->ssl_flag = 0;
4944 	    p2->count = REF_UNIT;
4945 	}
4946 #endif
4947 	p = p2->prev;
4948 	if (p) p->next = p1;	/* remove `p2' from trash */
4949 	if (p1) p1->prev = p;
4950 	freePair(p2);
4951 	m++;
4952     }
4953     if (Debug > 8 && (n > 0 || m > 0))
4954 	message(LOG_DEBUG, "trash: queued=%d, removed=%d", n, m);
4955     p1 = pairs->next;
4956     while (p1 != NULL) {
4957 	if (p1->clock == -1) {	/* top */
4958 	    if (all) {
4959 		pairs = p1;
4960 		p1 = pairs->next;
4961 		continue;
4962 	    } else {
4963 		break;
4964 	    }
4965 	}
4966 	p2 = p1;
4967 	p1 = p1->next;
4968 	if (!(p2->proto & proto_close)) continue;	/* skip */
4969 	if (p2->count > 0) {
4970 	    p2->count--;
4971 	    continue;
4972 	}
4973 	waitMutex(PairMutex);
4974 	p = p2->prev;
4975 	if (p) p->next = p1;	/* remove `p2' from list */
4976 	if (p1) p1->prev = p;
4977 	p = p2->pair;
4978 	if (p) p->pair = NULL;
4979 	freeMutex(PairMutex);
4980 	if (trash.next) trash.next->prev = p2;	/* push `p2' to trash */
4981 	p2->prev = &trash;
4982 	p2->pair = NULL;
4983 	p2->count = REF_UNIT;
4984 	p2->next = trash.next;
4985 	trash.next = p2;
4986     }
4987     return 1;
4988 }
4989 
message_pairs(int pri)4990 void message_pairs(int pri) {	/* dump for debug */
4991     Pair *pair;
4992     for (pair=PairTop; pair != NULL; pair=pair->next) {
4993 	if (pair->clock != -1) {	/* not top */
4994 	    message_pair(pri, pair);
4995 	} else if (Debug > 2) {
4996 	    message(LOG_DEBUG, "%d TCP %d: top", pair->stone->sd, pair->sd);
4997 	}
4998     }
4999 }
5000 
message_origins(int pri)5001 void message_origins(int pri) {	/* dump for debug */
5002     Origin *origin;
5003     for (origin=OriginTop; origin != NULL; origin=origin->next) {
5004 	if (origin->from) {
5005 	    message_origin(pri, origin);
5006 	} else if (Debug > 2) {
5007 	    message(LOG_DEBUG, "%d UDP %d: top",
5008 		    origin->stone->sd, origin->sd);
5009 	}
5010     }
5011 }
5012 
message_conns(int pri)5013 void message_conns(int pri) {	/* dump for debug */
5014     Conn *conn;
5015     for (conn=conns.next; conn != NULL; conn=conn->next)
5016 	message_conn(pri, conn);
5017 }
5018 
5019 /* read write thread */
5020 /* no Mutex are needed because in the single thread */
5021 
setclose(Pair * pair,int flag)5022 void setclose(Pair *pair, int flag) {	/* set close flag */
5023     SOCKET sd = pair->sd;
5024     message_time_log(pair);
5025     if (!(pair->proto & proto_close)) {		/* request to close */
5026 	pair->proto |= (flag | proto_close);
5027 	if (Debug > 2 && ValidSocket(sd))
5028 	    message(LOG_DEBUG, "%d TCP %d: close tx:%d rx:%d lp:%d",
5029 		    pair->stone->sd, sd, pair->tx, pair->rx, pair->loop);
5030     }
5031 #ifdef USE_EPOLL
5032     if (ValidSocket(sd)) {
5033 	pair->sd = INVALID_SOCKET;
5034 	closesocket(sd);
5035     }
5036 #endif
5037 }
5038 
dowrite(Pair * pair)5039 int dowrite(Pair *pair) {	/* write from buf from pair->t->start */
5040     SOCKET sd = pair->sd;
5041     Pair *p;
5042     int len;
5043     ExBuf *ex;
5044     ex = pair->t;	/* top */
5045     if (!ex) return 0;
5046     while (ex->len <= 0 && ex->next) {
5047 	pair->t = ex->next;
5048 	ex->next = NULL;
5049 	pair->nbuf--;
5050 	if (Debug > 4) message(LOG_DEBUG, "%d TCP %d: before dowrite "
5051 			       "unget ExBuf nbuf=%d nfex=%d",
5052 			       pair->stone->sd, pair->sd,
5053 			       pair->nbuf, nFreeExBuf);
5054 	ungetExBuf(ex);
5055     }
5056     if (ex->len <= 0) return 0;	/* nothing to write */
5057     if (Debug > 5) message(LOG_DEBUG, "%d TCP %d: write %d bytes",
5058 			   pair->stone->sd, sd, ex->len);
5059     if (InvalidSocket(sd)) return -1;
5060 #ifdef USE_SSL
5061     if (pair->ssl) {
5062 	len = SSL_write(pair->ssl, &ex->buf[ex->start], ex->len);
5063 	if (pair->proto & proto_close) return -1;
5064 	if (len <= 0) {
5065 	    int err;
5066 	    err = SSL_get_error(pair->ssl, len);
5067 	    if (err == SSL_ERROR_NONE
5068 		|| err == SSL_ERROR_WANT_WRITE) {
5069 		if (Debug > 4)
5070 		    message(LOG_DEBUG,
5071 			    "%d TCP %d: SSL_write interrupted err=%d",
5072 			    pair->stone->sd, sd, err);
5073 		return 0;	/* EINTR */
5074 	    } else if (err == SSL_ERROR_WANT_READ) {
5075 		if (Debug > 4)
5076 		    message(LOG_DEBUG,
5077 			    "%d TCP %d: SSL_write blocked on read err=%d",
5078 			    pair->stone->sd, sd, err);
5079 		pair->ssl_flag |= sf_wb_on_r;
5080 		return 0;	/* EINTR */
5081 	    }
5082 	    if (err == SSL_ERROR_SYSCALL) {
5083 		unsigned long e = ERR_get_error();
5084 		if (e == 0) {
5085 #ifdef WINDOWS
5086 		    errno = WSAGetLastError();
5087 #endif
5088 		    if (errno == EINTR) {
5089 			if (Debug > 4)
5090 			    message(LOG_DEBUG,
5091 				    "%d TCP %d: SSL_write I/O interrupted",
5092 				    pair->stone->sd, sd);
5093 			return 0;
5094 		    }
5095 		    message(priority(pair),
5096 			    "%d TCP %d: SSL_write I/O error err=%d, closing",
5097 			    pair->stone->sd, sd, errno);
5098 		    message_pair(LOG_ERR, pair);
5099 		} else {
5100 		    message(priority(pair),
5101 			    "%d TCP %d: SSL_write I/O %s, closing",
5102 			    pair->stone->sd, sd, ERR_error_string(e, NULL));
5103 		    message_pair(LOG_ERR, pair);
5104 		}
5105 		return -1;	/* error */
5106 	    } else if (err != SSL_ERROR_ZERO_RETURN) {
5107 		message(priority(pair),
5108 			"%d TCP %d: SSL_write err=%d %s, closing",
5109 			pair->stone->sd, sd,
5110 			err, ERR_error_string(ERR_get_error(), NULL));
5111 		message_pair(LOG_ERR, pair);
5112 		return len;	/* error */
5113 	    }
5114 	}
5115     } else {
5116 #endif
5117 	len = send(sd, &ex->buf[ex->start], ex->len, 0);
5118 	if (pair->proto & proto_close) return -1;
5119 	if (len < 0) {
5120 #ifdef WINDOWS
5121 	    errno = WSAGetLastError();
5122 #endif
5123 	    if (errno == EINTR) {
5124 		if (Debug > 4)
5125 		    message(LOG_DEBUG, "%d TCP %d: write interrupted",
5126 			    pair->stone->sd, sd);
5127 		return 0;
5128 	    }
5129 	    if (errno == ECONNABORTED) {
5130 		if (Debug > 3)
5131 		    message(LOG_DEBUG, "%d TCP %d: write aborted",
5132 			    pair->stone->sd, sd);
5133 		return -1;
5134 	    }
5135 	    message(priority(pair), "%d TCP %d: write error err=%d, closing",
5136 		    pair->stone->sd, sd, errno);
5137 	    message_pair(LOG_ERR, pair);
5138 	    return len;	/* error */
5139 	}
5140 #ifdef USE_SSL
5141     }
5142 #endif
5143     if (Debug > 4) message(LOG_DEBUG, "%d TCP %d: %d bytes written",
5144 			   pair->stone->sd, sd, len);
5145     if ((pair->xhost->mode & XHostsMode_Dump) > 0
5146 	|| ((pair->proto & proto_first_w) && Debug > 3))
5147 	message_buf(pair, len, "");
5148     time(&pair->clock);
5149     p = pair->pair;
5150     if (p) p->clock = pair->clock;
5151     if (ex->len <= len) {
5152 	ex->start = 0;
5153     } else {
5154 	ex->start += len;
5155 	message(LOG_NOTICE,
5156 		"%d TCP %d: write %d bytes, but only %d bytes written",
5157 		pair->stone->sd, sd, ex->len, len);
5158 	message_pair(LOG_NOTICE, pair);
5159     }
5160     ex->len -= len;
5161     if (ex->len <= 0 && ex->next) {
5162 	pair->t = ex->next;
5163 	ex->next = NULL;
5164 	pair->nbuf--;
5165 	if (Debug > 4) message(LOG_DEBUG, "%d TCP %d: after dowrite "
5166 			       "unget ExBuf nbuf=%d nfex=%d",
5167 			       pair->stone->sd, pair->sd,
5168 			       pair->nbuf, nFreeExBuf);
5169 	ungetExBuf(ex);
5170     }
5171     pair->tx += len;
5172     if ((p->proto & proto_command) != command_health)
5173 	lastReadWrite = pair->clock;
5174     return len;
5175 }
5176 
5177 static unsigned char basis_64[] =
5178     "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
5179 
baseEncode(unsigned char * buf,int len,int max)5180 int baseEncode(unsigned char *buf, int len, int max) {
5181     unsigned char *org = buf + max - len;
5182     unsigned char c1;
5183     unsigned char c2 = 0;	/* dummy init to suppress warnings */
5184     unsigned char c3 = 0;
5185     int blen = 0;
5186     int i;
5187     bcopy(buf, org, len);
5188     for (i=0; i < len; i += 3) {
5189 	switch (len - i) {
5190 	case 1:
5191 	    c2 = '\0';
5192 	    buf[blen+2] = '=';
5193 	case 2:
5194 	    c3 = '\0';
5195 	    buf[blen+3] = '=';
5196 	}
5197 	switch (len - i) {
5198 	default:
5199 	    c3 = org[i+2];
5200 	    buf[blen+3] = basis_64[c3 & 0x3F];
5201 	case 2:
5202 	    c2 = org[i+1];
5203 	    buf[blen+2] = basis_64[((c2 & 0xF) << 2) | ((c3 & 0xC0) >>6)];
5204 	case 1:
5205 	    c1 = org[i];
5206 	    buf[blen+1] = basis_64[((c1 & 0x3)<< 4) | ((c2 & 0xF0) >> 4)];
5207 	    buf[blen] = basis_64[c1>>2];
5208 	}
5209 	blen += 4;
5210     }
5211     if (buf[blen-1] != '=') buf[blen++] = '=';
5212     return blen;
5213 }
5214 
5215 #define XX      255	/* illegal base64 char */
5216 #define EQ      254	/* padding */
5217 
5218 static unsigned char index_64[256] = {
5219     XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX,
5220     XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX,
5221     XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,62, XX,XX,XX,63,
5222     52,53,54,55, 56,57,58,59, 60,61,XX,XX, XX,EQ,XX,XX,
5223     XX, 0, 1, 2,  3, 4, 5, 6,  7, 8, 9,10, 11,12,13,14,
5224     15,16,17,18, 19,20,21,22, 23,24,25,XX, XX,XX,XX,XX,
5225     XX,26,27,28, 29,30,31,32, 33,34,35,36, 37,38,39,40,
5226     41,42,43,44, 45,46,47,48, 49,50,51,XX, XX,XX,XX,XX,
5227 
5228     XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX,
5229     XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX,
5230     XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX,
5231     XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX,
5232     XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX,
5233     XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX,
5234     XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX,
5235     XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX,
5236 };
5237 
baseDecode(unsigned char * buf,int len,char * rest)5238 int baseDecode(unsigned char *buf, int len, char *rest) {
5239     int blen = 0;
5240     unsigned char c[4], o[4];
5241     int i, j;
5242     j = 0;
5243     for (i=0; i < len; i++) {
5244 	c[j] = index_64[buf[i]];
5245 	if (c[j] == XX) continue;
5246 	if (j == 0 && c[j] == EQ) continue;
5247 	o[j++] = buf[i];
5248 	if (j == 4) {
5249 	    j = 0;
5250 	    buf[blen++] = (c[0] << 2) | ((c[1] & 0x30) >> 4);
5251 	    if (c[2] == EQ) continue;
5252 	    buf[blen++] = ((c[1] & 0x0F) << 4) | ((c[2] & 0x3C) >> 2);
5253 	    if (c[3] == EQ) continue;
5254 	    buf[blen++] = ((c[2] & 0x03) << 6) | c[3];
5255 	}
5256     }
5257     *rest = j;
5258     for (i=0; i < j; i++) *(rest-1-i) = o[i];
5259     return blen;
5260 }
5261 
doread(Pair * pair)5262 int doread(Pair *pair) {	/* read into buf from pair->pair->b->start */
5263     SOCKET sd = pair->sd;
5264     Pair *p;
5265     int len, i;
5266     ExBuf *ex;
5267     int bufmax, start;
5268     if (InvalidSocket(sd)) return -1;
5269     if (Debug > 5) message(LOG_DEBUG, "%d TCP %d: read", pair->stone->sd, sd);
5270     p = pair->pair;
5271     if (p == NULL) {	/* no pair, no more read */
5272 	char _buf[BUFMAX];
5273 #ifdef USE_SSL
5274 	if (pair->ssl) {
5275 	    len = SSL_read(pair->ssl, _buf, BUFMAX);
5276 	} else
5277 #endif
5278 	    len = recv(sd, _buf, BUFMAX, 0);
5279 	if (pair->proto & proto_close) return -1;
5280 	if (Debug > 4) message(LOG_DEBUG, "%d TCP %d: read %d bytes",
5281 			       pair->stone->sd, sd, len);
5282 	if (len == 0) return -1;	/* EOF w/o pair */
5283 	if (len > 0) {
5284 	    message(priority(pair), "%d TCP %d: no pair, closing",
5285 		    pair->stone->sd, sd);
5286 	    message_pair(LOG_ERR, pair);
5287 	    len = -1;
5288 	}
5289 	return len;
5290     }
5291     ex = p->b;	/* bottom */
5292     if (ex->len > 0) {	/* not emply */
5293 	ex = getExBuf();
5294 	if (!ex) return -1;	/* out of memory */
5295 	p->b->next = ex;
5296 	p->b = ex;
5297 	p->nbuf++;
5298 	if (Debug > 4) message(LOG_DEBUG, "%d TCP %d: get ExBuf nbuf=%d",
5299 			       pair->stone->sd, p->sd, p->nbuf);
5300     }
5301     bufmax = ex->bufmax - ex->start - ex->len;
5302     start = ex->start + ex->len;
5303     if (p->proto & proto_base) bufmax = (bufmax - 1) / 4 * 3;
5304     else if (pair->proto & proto_base) {
5305 	if (!(pair->proto & proto_first_r)) {
5306 	    len = *(ex->buf+ex->bufmax-1);
5307 	    for (i=0; i < len; i++) {
5308 		ex->buf[start++] = ex->buf[ex->bufmax-2-i];
5309 	    }
5310 	    bufmax -= len;
5311 	}
5312 	*(ex->buf+ex->bufmax-1) = 0;
5313 	bufmax -= 5;
5314     }
5315     if (((p->proto & proto_command) == command_ihead) ||
5316 	((p->proto & proto_command) == command_iheads)) bufmax = bufmax / 2;
5317 #ifdef USE_SSL
5318     if (pair->ssl) {
5319 	len = SSL_read(pair->ssl, &ex->buf[start], bufmax);
5320 	if (pair->proto & proto_close) return -1;
5321 	if (len < 0) {
5322 	    int err;
5323 	    err = SSL_get_error(pair->ssl, len);
5324 	    if (err == SSL_ERROR_NONE
5325 		|| err == SSL_ERROR_WANT_READ) {
5326 		if (Debug > 4)
5327 		    message(LOG_DEBUG,
5328 			    "%d TCP %d: SSL_read interrupted err=%d",
5329 			    pair->stone->sd, sd, err);
5330 		return 0;	/* EINTR */
5331 	    } else if (err == SSL_ERROR_WANT_WRITE) {
5332 		if (Debug > 4)
5333 		    message(LOG_DEBUG,
5334 			    "%d TCP %d: SSL_read blocked on write err=%d",
5335 			    pair->stone->sd, sd, err);
5336 		pair->ssl_flag |= sf_rb_on_w;
5337 		return 0;	/* EINTR */
5338 	    }
5339 	    if (err == SSL_ERROR_SYSCALL) {
5340 		unsigned long e = ERR_get_error();
5341 		if (e == 0) {
5342 #ifdef WINDOWS
5343 		    errno = WSAGetLastError();
5344 #endif
5345 		    if (errno == EINTR) {
5346 			if (Debug > 4)
5347 			    message(LOG_DEBUG,
5348 				    "%d TCP %d: SSL_read I/O interrupted",
5349 				    pair->stone->sd, sd);
5350 			return 0;
5351 		    }
5352 		    message(priority(pair),
5353 			    "%d TCP %d: SSL_read I/O error err=%d, closing",
5354 			    pair->stone->sd, sd, errno);
5355 		    message_pair(LOG_ERR, pair);
5356 		} else {
5357 		    message(priority(pair),
5358 			    "%d TCP %d: SSL_read I/O %s, closing",
5359 			    pair->stone->sd, sd, ERR_error_string(e, NULL));
5360 		    message_pair(LOG_ERR, pair);
5361 		}
5362 		return -1;	/* error */
5363 	    } else if (err != SSL_ERROR_ZERO_RETURN) {
5364 		message(priority(pair),
5365 			"%d TCP %d: SSL_read err=%d %s, closing",
5366 			pair->stone->sd, sd,
5367 			err, ERR_error_string(ERR_get_error(), NULL));
5368 		message_pair(LOG_ERR, pair);
5369 		return -1;	/* error */
5370 	    }
5371 	}
5372     } else {
5373 #endif
5374 	len = recv(sd, &ex->buf[start], bufmax, 0);
5375 	if (pair->proto & proto_close) return -1;
5376 	if (len < 0) {
5377 #ifdef WINDOWS
5378 	    errno = WSAGetLastError();
5379 #endif
5380 	    if (errno == EINTR) {
5381 		if (Debug > 4)
5382 		    message(LOG_DEBUG, "%d TCP %d: read interrupted",
5383 			    pair->stone->sd, sd);
5384 		return 0;	/* EINTR */
5385 	    }
5386 	    if (errno == ECONNRESET) {
5387 		if (Debug > 3)
5388 		    message(LOG_DEBUG, "%d TCP %d: read but reset by peer",
5389 			    pair->stone->sd, sd);
5390 		return -1;
5391 	    }
5392 	    message(priority(pair), "%d TCP %d: read error err=%d, closing",
5393 		    pair->stone->sd, sd, errno);
5394 	    message_pair(LOG_ERR, pair);
5395 	    return len;	/* error */
5396 	}
5397 #ifdef USE_SSL
5398     }
5399 #endif
5400     if (len > 0) {
5401 	pair->rx += len;
5402 #ifdef ENLARGE
5403 	if (len > ex->bufmax - 10
5404 	    && XferBufMax < ex->bufmax * 2) {
5405 	    XferBufMax = ex->bufmax * 2;
5406 	    message(LOG_NOTICE, "%d TCP %d: XferBufMax becomes %d byte",
5407 		    pair->stone->sd, sd, XferBufMax);
5408 	}
5409 #endif
5410 	ex->len = start + len - ex->start;
5411 	if (Debug > 4) {
5412 	    SOCKET psd = p->sd;
5413 	    if (start > ex->start) {
5414 		message(LOG_DEBUG, "%d TCP %d: read %d+%d bytes to %d",
5415 			pair->stone->sd, sd, len, start - ex->start, psd);
5416 	    } else {
5417 		message(LOG_DEBUG, "%d TCP %d: read %d bytes to %d",
5418 			pair->stone->sd, sd, ex->len, psd);
5419 	    }
5420 	}
5421 	time(&pair->clock);
5422 	p->clock = pair->clock;
5423 	if (p->proto & proto_base) {
5424 	    ex->len = baseEncode((unsigned char*)&ex->buf[ex->start], ex->len,
5425 				 ex->bufmax - ex->start);
5426 	} else if (pair->proto & proto_base) {
5427 	    ex->len = baseDecode((unsigned char*)&ex->buf[ex->start], ex->len,
5428 				 ex->buf+ex->bufmax-1);
5429 	    len = *(ex->buf+ex->bufmax-1);
5430 	    if (Debug > 4 && len > 0) {	/* len < 4 */
5431 		char str[STRMAX+1];
5432 		for (i=0; i < len; i++)
5433 		    sprintf(&str[i*3], " %02x", ex->buf[ex->bufmax-2-i]);
5434 		str[0] = '(';
5435 		message(LOG_DEBUG, "%d TCP %d: save %d bytes \"%s\")",
5436 			pair->stone->sd, sd, len, str);
5437 	    }
5438 	}
5439 	if ((p->proto & proto_command) != command_health)
5440 	    lastReadWrite = pair->clock;
5441     }
5442     if (p->t->len <= 0) {	/* top */
5443 	message_time_log(pair);
5444 	if (Debug > 2)
5445 	    message(LOG_DEBUG, "%d TCP %d: EOF", pair->stone->sd, sd);
5446 	return -2;	/* EOF w/ pair */
5447     }
5448     return p->t->len;
5449 }
5450 
5451 /* http */
5452 
5453 #define METHOD_LEN_MAX	10
5454 
commOutput(Pair * pair,char * fmt,...)5455 int commOutput(Pair *pair, char *fmt, ...) {
5456     Pair *p = pair->pair;
5457     ExBuf *ex;
5458     SOCKET psd;
5459     char *str;
5460     va_list ap;
5461     if (p == NULL) return -1;
5462     psd = p->sd;
5463     if ((p->proto & (proto_shutdown | proto_close)) || InvalidSocket(psd))
5464 	return -1;
5465     ex = p->b;	/* bottom */
5466     if (ex->bufmax - (ex->start + ex->len) < STRMAX+1) {
5467 	ExBuf *new = getExBuf();
5468 	if (new) {
5469 	    ex = new;
5470 	    p->b->next = ex;
5471 	    p->b = ex;
5472 	    p->nbuf++;
5473 	    if (Debug > 4) message(LOG_DEBUG, "%d TCP %d: get ExBuf nbuf=%d",
5474 				   pair->stone->sd, p->sd, p->nbuf);
5475 	}
5476     }
5477     str = &ex->buf[ex->start + ex->len];
5478     ex->buf[ex->bufmax-1] = '\0';
5479     va_start(ap, fmt);
5480     vsnprintf(str, ex->bufmax-1 - (ex->start + ex->len), fmt, ap);
5481     va_end(ap);
5482     if (p->proto & proto_base)
5483 	ex->len += baseEncode((unsigned char*)str, strlen(str),
5484 			      ex->bufmax-1 - (ex->start + ex->len));
5485     else ex->len += strlen(str);
5486     p->proto |= (proto_select_w | proto_dirty);	/* need to write */
5487     return ex->len;
5488 }
5489 
comm_match(char * buf,char * str)5490 static char *comm_match(char *buf, char *str) {
5491     while (*str) {
5492 	if (toupper(*buf++) != *str++) return NULL;	/* unmatch */
5493     }
5494     if (*buf) {
5495 	if (!isspace(*buf)) return NULL;
5496 /*	while (isspace(*buf)) buf++;	*/
5497 	if (*buf == ' ') buf++;
5498     }
5499     return buf;
5500 }
5501 
5502 #ifdef ADDRCACHE
str2hash(char * str)5503 unsigned int str2hash(char *str) {
5504     unsigned int hash = 0;
5505     while (*str) {
5506 	hash  = hash * 7 + *str;
5507 	str++;
5508     }
5509     return hash;
5510 }
5511 
5512 struct hashtable {
5513     char *host;
5514     char *serv;
5515     time_t clock;
5516     int len;
5517     struct sockaddr_storage ss;
5518 } *hashtable;
5519 
addrcache(char * name,char * serv,struct sockaddr * sa,socklen_t * salenp)5520 int addrcache(char *name, char *serv, struct sockaddr *sa, socklen_t *salenp) {
5521     struct hashtable *t;
5522     time_t now;
5523     time(&now);
5524     if (!hashtable) {
5525 	hashtable = malloc(AddrCacheSize * sizeof(struct hashtable));
5526 	if (!hashtable) {
5527 	    message(LOG_ERR, "addrcache: out of memory");
5528 	    return host2sa(name, serv, sa, salenp, NULL, NULL, 0) == 0;
5529 	}
5530 	bzero(hashtable, AddrCacheSize * sizeof(struct hashtable));
5531     }
5532     t = &hashtable[(str2hash(name) ^ str2hash(serv)) % AddrCacheSize];
5533     waitMutex(HashMutex);
5534     if (t->host && strcmp(t->host, name) == 0
5535 	&& t->serv && strcmp(t->serv, serv) == 0
5536 	&& t->len <= *salenp
5537 	&& now - t->clock < CACHE_TIMEOUT) {
5538 	bcopy(&t->ss, sa, t->len);
5539 	*salenp = t->len;
5540 	freeMutex(HashMutex);
5541 	if (Debug > 5) message(LOG_DEBUG, "addrcache hit: %s:%s %d",
5542 			       name, serv, (int)(now - t->clock));
5543 	return 1;
5544     }
5545     freeMutex(HashMutex);
5546     if (Debug > 9) message(LOG_DEBUG, "addrcache %s %s", name, serv);
5547     if (host2sa(name, serv, sa, salenp, NULL, NULL, 0)) return 0;
5548     waitMutex(HashMutex);
5549     if ((t->host && strcmp(t->host, name) != 0) ||
5550 	(t->serv && strcmp(t->serv, serv) != 0) ||
5551 	(t->len > *salenp)) {
5552 	free(t->host);
5553 	free(t->serv);
5554 	t->host = NULL;
5555 	t->serv = NULL;
5556 	t->len = sizeof(t->ss);
5557     }
5558     if (!t->host) t->host = strdup(name);
5559     if (!t->serv) t->serv = strdup(serv);
5560     bcopy(sa, &t->ss, *salenp);
5561     t->len = *salenp;
5562     t->clock = now;
5563     freeMutex(HashMutex);
5564     return 1;
5565 }
5566 #endif
5567 
doproxy(Pair * pair,char * host,char * serv)5568 int doproxy(Pair *pair, char *host, char *serv) {
5569     SOCKET sd = pair->sd;
5570     int reconnect = 0;
5571     PortXHosts *pxh;
5572     struct sockaddr_storage name_s;
5573     struct sockaddr *name = (struct sockaddr*)&name_s;
5574     struct sockaddr_storage ss;
5575     struct sockaddr *sa = (struct sockaddr*)&ss;
5576     socklen_t namelen = sizeof(name_s);
5577     socklen_t salen = sizeof(ss);
5578     if ((pair->stone->proto & proto_ip_only_d)) {
5579 #ifdef AF_INET6
5580 	if ((pair->stone->proto & proto_v6_d))
5581 	    sa->sa_family = AF_INET6;
5582 	else
5583 #endif
5584 	    sa->sa_family = AF_INET;
5585     } else {
5586 	sa->sa_family = AF_UNSPEC;
5587     }
5588 #ifdef ADDRCACHE
5589     if (AddrCacheSize > 0) {
5590 	if (!addrcache(host, serv, sa, &salen)) return -1;
5591     } else
5592 #endif
5593 	if (host2sa(host, serv, sa, &salen, NULL, NULL, 0)) return -1;
5594     if (islocalhost(sa)) {
5595 	TimeLog *log = pair->log;
5596 	pair->log = NULL;
5597 	if (log) free(log);
5598     }
5599     if ((pair->stone->proto & proto_nobackup) == 0) {
5600 	Backup *backup = findBackup(sa);
5601 	if (backup && backup->bn) {	/* unhealthy */
5602 	    sa = &backup->backup->addr;
5603 	    salen = backup->backup->len;
5604 	}
5605     }
5606     pxh = (PortXHosts*)pair->stone->dsts[1];
5607     if (pxh) {
5608 	for (; pxh; pxh=pxh->next) {
5609 	    XPorts *ports;
5610 	    XHosts *xhost;
5611 	    int isok = 0;
5612 	    int port = getport(sa);
5613 	    for (ports=pxh->ports; ports; ports=ports->next) {
5614 		if (ports->from <= port && port <= ports->end) {
5615 		    isok = 1;
5616 		}
5617 	    }
5618 	    if (!isok) continue;
5619 	    xhost = checkXhost(pxh->xhosts, sa, salen);
5620 	    if (xhost) {
5621 		if (xhost->mode) {
5622 		    Pair *p = pair->pair;
5623 		    pair->xhost = xhost;
5624 		    if (p) p->xhost = xhost;
5625 		}
5626 		if (Debug > 7) {
5627 		    message(LOG_DEBUG,
5628 			    "stone %d: proxy can connect to %s:%s mode=%d",
5629 			    pair->stone->sd, host, serv, xhost->mode);
5630 		}
5631 		break;
5632 	    } else {
5633 		message(LOG_WARNING, "stone %d: proxy may not connect to %s",
5634 			pair->stone->sd, host);
5635 		return -1;
5636 	    }
5637 	}
5638 	if (!pxh) {
5639 	    message(LOG_WARNING, "stone %d: proxy may not connect to port %s",
5640 		    pair->stone->sd, serv);
5641 	    return -1;
5642 	}
5643     }
5644     if ((pair->proto & proto_connect) && !(pair->proto & proto_close)
5645 	  && getpeername(sd, name, &namelen) >= 0) {	/* reconnect proxy */
5646 	Pair *p = pair->pair;
5647 	if (Debug > 7) {
5648 	    char str[STRMAX+1];
5649 	    message(LOG_DEBUG, "%d TCP %d: old proxy connection: %s",
5650 		    pair->stone->sd, sd,
5651 		    addrport2str(name, namelen, 0, str, STRMAX, 0));
5652 	}
5653 	if (p) p->proto |= (proto_first_w | proto_dirty);
5654 	if (saComp(sa, name)) return 0;	/* same sa, so need not to connect */
5655 	reconnect = 1;
5656     }
5657     if (reconnect
5658 	|| ((pair->stone->proto & proto_v6_d) && sa->sa_family == AF_INET)
5659 #ifdef AF_INET6
5660 	|| (!(pair->stone->proto & proto_v6_d) && sa->sa_family == AF_INET6)
5661 #endif
5662 	) {
5663 	SOCKET nsd = socket(sa->sa_family, SOCK_STREAM, IPPROTO_TCP);
5664 	if (ValidSocket(nsd)) {
5665 	    Pair *p = pair->pair;
5666 	    pair->sd = nsd;
5667 	    message(LOG_INFO, "%d TCP %d: close %d %08x, "
5668 		    "reopen %d as family=%d",
5669 		    pair->stone->sd, (p ? p->sd : INVALID_SOCKET),
5670 		    sd, pair->proto, nsd, sa->sa_family);
5671 	    closesocket(sd);
5672 	}
5673     }
5674     pair->proto &= ~(proto_connect | proto_command);
5675     if (reqconn(pair, sa, salen) < 0) return -1;
5676     if ((pair->proto & state_mask) == 1) {
5677 	if (Debug > 7) message(LOG_DEBUG, "%d TCP %d: command_proxy again",
5678 			       pair->stone->sd, pair->sd);
5679 	pair->proto |= command_proxy;
5680     }
5681     return 0;
5682 }
5683 
proxyCONNECT(Pair * pair,char * parm,int start)5684 int proxyCONNECT(Pair *pair, char *parm, int start) {
5685     char *port = "443";	/* default: https */
5686     char *r = parm;
5687     char *q = NULL;
5688     Pair *p;
5689     message_time(pair, LOG_INFO, "CONNECT %s", parm);
5690     while (*r) {
5691 	if (isspace(*r)) {
5692 	    *r = '\0';
5693 	    break;
5694 	}
5695 	if (*r == ':') q = r;
5696 	r++;
5697     }
5698     if (q) {
5699 	port = q + 1;
5700 	*q = '\0';
5701     }
5702     (void)start;
5703     pair->b->len += pair->b->start;
5704     pair->b->start = 0;
5705     p = pair->pair;
5706     if (p) p->proto |= proto_ohttp_s;	/* remove request header */
5707     return doproxy(pair, parm, port);
5708 }
5709 
proxyCommon(Pair * pair,char * parm,int start)5710 int proxyCommon(Pair *pair, char *parm, int start) {
5711     char *port = NULL;
5712     char *host;
5713     ExBuf *ex;
5714     char *top;
5715     char *p, *q;
5716     int i;
5717     int https = 0;
5718     ex = pair->b;	/* bottom */
5719     top = &ex->buf[start];
5720     for (i=0; i < METHOD_LEN_MAX; i++) {
5721 	if (parm[i] == ':') break;
5722     }
5723     if (strncmp(parm, "http", i) == 0) {
5724 	port = "80";	/* default port of http:// */
5725 #ifdef USE_SSL
5726     } else if (strncmp(parm, "https", i) == 0) {
5727 	https = 1;
5728 	port = "443";	/* default port of https:// */
5729 	pair->ssl_flag |= sf_cb_on_r;
5730 #endif
5731     }
5732     if (!port || parm[i+1] != '/' || parm[i+2] != '/') {
5733 	message(LOG_ERR, "Unknown URL format: %s", parm);
5734 	return -1;
5735     }
5736     host = &parm[i+3];
5737     p = host;
5738     while (*p) {
5739 	if (*p == ':') {
5740 	    port = p + 1;
5741 	    *p++ = '\0';
5742 	    continue;
5743 	}
5744 	if (isspace(*p) || *p == '/') {
5745 	    *p = '\0';
5746 	    break;
5747 	}
5748 	p++;
5749     }
5750     i = p - parm;		/* length of 'http://host' */
5751     p = top;
5752     while (!isspace(*p)) p++;	/* skip 'GET http://host' */
5753     while (isspace(*p)) p++;	/* now p points url */
5754     q = p + i;			/* now q points path */
5755     if (*q != '/') *--q = '/';
5756     bcopy(q, p, ex->start + ex->len - (q - top));
5757     ex->len = ex->start + ex->len - (q - p);
5758     ex->start = 0;
5759     if (Debug > 1) {
5760 	Pair *r = pair->pair;
5761 	message(LOG_DEBUG, "proxy %d -> http%s://%s:%s",
5762 		(r ? r->sd : INVALID_SOCKET),
5763 		(https ? "s" : ""), host, port);
5764     }
5765     pair->proto &= ~(proto_noconnect | state_mask);
5766     pair->proto |= (proto_dirty | 1);
5767     return doproxy(pair, host, port);
5768 }
5769 
proxyGET(Pair * pair,char * parm,int start)5770 int proxyGET(Pair *pair, char *parm, int start) {
5771     message_time(pair, LOG_INFO, "GET %s", parm);
5772     return proxyCommon(pair, parm, start);
5773 }
5774 
proxyHEAD(Pair * pair,char * parm,int start)5775 int proxyHEAD(Pair *pair, char *parm, int start) {
5776     message_time(pair, LOG_INFO, "HEAD %s", parm);
5777     return proxyCommon(pair, parm, start);
5778 }
5779 
proxyPOST(Pair * pair,char * parm,int start)5780 int proxyPOST(Pair *pair, char *parm, int start) {
5781     message_time(pair, LOG_INFO, "POST %s", parm);
5782     return proxyCommon(pair, parm, start);
5783 }
5784 
proxyErr(Pair * pair,char * parm,int start)5785 int proxyErr(Pair *pair, char *parm, int start) {
5786     (void)pair;
5787     (void)start;
5788     message(LOG_ERR, "Unknown method: %s", parm);
5789     return -1;
5790 }
5791 
5792 Comm proxyComm[] = {
5793     { "CONNECT", proxyCONNECT },
5794     { "POST", proxyPOST },
5795     { "GET", proxyGET },
5796     { "HEAD", proxyHEAD },
5797     { NULL, proxyErr },
5798 };
5799 
5800 #ifdef USE_POP
popUSER(Pair * pair,char * parm,int start)5801 int popUSER(Pair *pair, char *parm, int start) {
5802     int ulen, tlen;
5803     char *data;
5804     ExBuf *ex = getExData(pair, data_apop, 0);
5805     if (!ex) {
5806 	message(LOG_ERR, "%d TCP %d: popUSER Can't happen no ExData",
5807 		pair->stone->sd, pair->sd);
5808 	return -1;
5809     }
5810     (void)start;
5811     data = ex->buf + DATA_HEAD_LEN;
5812     if (Debug) message(LOG_DEBUG, ": USER %s", parm);
5813     ulen = strlen(parm);
5814     tlen = strlen(data);
5815     if (ulen + 1 + tlen + 1 >= BUFMAX-1) {
5816 	commOutput(pair, "+Err Too long user name\r\n");
5817 	return -1;
5818     }
5819     bcopy(data, data + ulen + 1, tlen + 1);
5820     strcpy(data, parm);
5821     commOutput(pair, "+OK Password required for %s\r\n", parm);
5822     pair->proto &= ~state_mask;
5823     pair->proto |= 1;
5824     return -2;	/* read more */
5825 }
5826 
5827 #define DIGEST_LEN 16
5828 
popPASS(Pair * pair,char * parm,int start)5829 int popPASS(Pair *pair, char *parm, int start) {
5830     MD5_CTX context;
5831     unsigned char digest[DIGEST_LEN];
5832     char *str;
5833     int ulen, tlen, plen, i;
5834     int state = (pair->proto & state_mask);
5835     ExBuf *ex;
5836     ExBuf *t;
5837     char *data;
5838     int max;
5839     if (Debug > 5) message(LOG_DEBUG, ": PASS %s", parm);
5840     if (state < 1) {
5841 	commOutput(pair, "-ERR USER first\r\n");
5842 	return -2;	/* read more */
5843     }
5844     t = getExData(pair, data_apop, 1);
5845     data = t->buf + DATA_HEAD_LEN;
5846     max = t->bufmax - DATA_HEAD_LEN;
5847     ulen = strlen(data);
5848     str = data + ulen + 1;
5849     tlen = strlen(str);
5850     plen = strlen(parm);
5851     if (ulen + 1 + tlen + plen + 1 >= max-1) {
5852 	commOutput(pair, "+Err Too long password\r\n");
5853 	return -1;
5854     }
5855     strcat(str, parm);
5856     (void)start;
5857     ex = pair->b;	/* bottom */
5858     sprintf(ex->buf, "APOP %s ", data);
5859     ulen = strlen(ex->buf);
5860     MD5Init(&context);
5861     MD5Update(&context, str, tlen + plen);
5862     MD5Final(digest, &context);
5863     ungetExBuf(t);
5864     for (i=0; i < DIGEST_LEN; i++) {
5865 	sprintf(ex->buf + ulen + i*2, "%02x", digest[i]);
5866     }
5867     message_time(pair, LOG_INFO, "POP -> %s", ex->buf);
5868     strcat(ex->buf, "\r\n");
5869     ex->start = 0;
5870     ex->len = strlen(ex->buf);
5871     return 0;
5872 }
5873 
popAUTH(Pair * pair,char * parm,int start)5874 int popAUTH(Pair *pair, char *parm, int start) {
5875     (void)start;
5876     if (Debug) message(LOG_DEBUG, ": AUTH %s", parm);
5877     commOutput(pair, "-ERR authorization first\r\n");
5878     return -2;	/* read more */
5879 }
5880 
popCAPA(Pair * pair,char * parm,int start)5881 int popCAPA(Pair *pair, char *parm, int start) {
5882     (void)start;
5883     if (Debug) message(LOG_DEBUG, ": CAPA %s", parm);
5884     commOutput(pair, "-ERR authorization first\r\n");
5885     return -2;	/* read more */
5886 }
5887 
popAPOP(Pair * pair,char * parm,int start)5888 int popAPOP(Pair *pair, char *parm, int start) {
5889     ExBuf *ex = pair->b;	/* bottom */
5890     message_time(pair, LOG_INFO, "APOP %s", parm);
5891     ex->len += ex->start - start;
5892     ex->start = start;
5893     return 0;
5894 }
5895 
popErr(Pair * pair,char * parm,int start)5896 int popErr(Pair *pair, char *parm, int start) {
5897     (void)pair;
5898     (void)start;
5899     message(LOG_ERR, "Unknown POP command: %s", parm);
5900     return -1;
5901 }
5902 
5903 Comm popComm[] = {
5904     { "USER", popUSER },
5905     { "PASS", popPASS },
5906     { "APOP", popAPOP },
5907     { "AUTH", popAUTH },
5908     { "CAPA", popCAPA },
5909     { NULL, popErr },
5910 };
5911 #endif
5912 
identd(int cport,struct sockaddr * ssa,socklen_t ssalen)5913 Pair *identd(int cport, struct sockaddr *ssa, socklen_t ssalen) {
5914     struct sockaddr_storage ss;
5915     struct sockaddr *sa = (struct sockaddr*)&ss;
5916     socklen_t salen;
5917     Pair *pair;
5918     for (pair=PairTop; pair != NULL; pair=pair->next) {
5919 	SOCKET sd;
5920 	if ((pair->proto & proto_command) == command_source) continue;
5921 	sd = pair->sd;
5922 	salen = sizeof(ss);
5923 	if (InvalidSocket(sd) || getsockname(sd, sa, &salen) < 0) {
5924 	    continue;
5925 	}
5926 	if (getport(sa) != cport) continue;
5927 	salen = sizeof(ss);
5928 	if (getpeername(sd, sa, &salen) < 0) {
5929 	    continue;
5930 	}
5931 	(void)ssalen;
5932 	if (!saComp(sa, ssa)) continue;
5933 	return pair;
5934     }
5935     return NULL;
5936 }
5937 
identdQUERY(Pair * pair,char * parm,int start)5938 int identdQUERY(Pair *pair, char *parm, int start) {
5939     int cport = 0;
5940     int sport = 0;
5941     char mesg[STRMAX+1];
5942     struct sockaddr_storage ss;
5943     struct sockaddr *sa = (struct sockaddr*)&ss;
5944     socklen_t salen = sizeof(ss);
5945     Pair *p = pair->pair;
5946     (void)start;
5947     strcpy(mesg, "ERROR : NO-USER");
5948     if (p) {
5949 	SOCKET sd = p->sd;
5950 	if (sscanf(parm, "%d,%d", &cport, &sport) == 2
5951 	    && ValidSocket(sd) && getpeername(sd, sa, &salen) >= 0) {
5952 	    if (Debug > 8) {
5953 		char addrport[STRMAX+1];
5954 		addrport2str(sa, salen, 0, addrport, STRMAX, 0);
5955 		message(LOG_DEBUG, "%d TCP %d: identd query %d,%d from %s",
5956 			pair->stone->sd, sd, cport, sport, addrport);
5957 	    }
5958 	    saPort(sa, sport);
5959 	    p = identd(cport, sa, salen);
5960 	    if (p) {
5961 		int port = -1;
5962 		Stone *stone = p->stone;
5963 		if (stone) port = stone->port;
5964 		snprintf(mesg, STRMAX, "USERID : STONE : %d", port);
5965 	    }
5966 	    if (Debug > 2) {
5967 		char addrport[STRMAX+1];
5968 		addrport2str(sa, salen, 0, addrport, STRMAX, 0);
5969 		message(LOG_DEBUG, "identd %d %s %s", cport, addrport, mesg);
5970 	    }
5971 	} else {
5972 	    return -1;
5973 	}
5974     }
5975     commOutput(pair, "%d , %d : %s\r\n", cport, sport, mesg);
5976     return -2;	/* read more */
5977 }
5978 
identdQUIT(Pair * pair,char * parm,int start)5979 int identdQUIT(Pair *pair, char *parm, int start) {
5980     (void)pair;
5981     (void)start;
5982     if (Debug) message(LOG_DEBUG, "identd QUIT %s", parm);
5983     return -1;
5984 }
5985 
5986 Comm identdComm[] = {
5987     { "QUIT", identdQUIT },
5988     { "", identdQUERY },
5989     { NULL, identdQUERY },
5990 };
5991 
nStones(void)5992 int nStones(void) {
5993     int n = 0;
5994     Stone *stone;
5995     for (stone=stones; stone != NULL; stone=stone->next) n++;
5996     return n;
5997 }
5998 
nPairs(Pair * top)5999 int nPairs(Pair *top) {
6000     int n = 0;
6001     Pair *pair;
6002     for (pair=top; pair != NULL; pair=pair->next)
6003 	if (pair->clock != -1) n++;	/* not top */
6004     return n;
6005 }
6006 
nConns(void)6007 int nConns(void) {
6008     int n = 0;
6009     Conn *conn;
6010     for (conn=conns.next; conn != NULL; conn=conn->next) n++;
6011     return n;
6012 }
6013 
nOrigins(void)6014 int nOrigins(void) {
6015     int n = 0;
6016     Origin *origin;
6017     for (origin=OriginTop; origin != NULL; origin=origin->next)
6018 	if (origin->from) n++;
6019     return n;
6020 }
6021 
limitCommon(Pair * pair,int var,int limit,char * str)6022 int limitCommon(Pair *pair, int var, int limit, char *str) {
6023     if (Debug) message(LOG_DEBUG, ": LIMIT %s %d: %d", str, limit, var);
6024     if (var < limit) {
6025 	commOutput(pair, "200 %s=%d is less than %d\r\n",
6026 		   str, var, limit);
6027     } else {
6028 	commOutput(pair, "500 %s=%d is not less than %d\r\n", str, var, limit);
6029     }
6030     return -2;	/* read more */
6031 }
6032 
limitPair(Pair * pair,char * parm,int start)6033 int limitPair(Pair *pair, char *parm, int start) {
6034     (void)start;
6035     return limitCommon(pair, nPairs(PairTop), atoi(parm), "pair");
6036 }
6037 
limitConn(Pair * pair,char * parm,int start)6038 int limitConn(Pair *pair, char *parm, int start) {
6039     (void)start;
6040     return limitCommon(pair, nConns(), atoi(parm), "conn");
6041 }
6042 
limitEstablished(Pair * pair,char * parm,int start)6043 int limitEstablished(Pair *pair, char *parm, int start) {
6044     time_t now;
6045     time(&now);
6046     (void)start;
6047     return limitCommon(pair, (int)(now - lastEstablished),
6048 		       atoi(parm), "established");
6049 }
6050 
limitReadWrite(Pair * pair,char * parm,int start)6051 int limitReadWrite(Pair *pair, char *parm, int start) {
6052     time_t now;
6053     time(&now);
6054     (void)start;
6055     return limitCommon(pair, (int)(now - lastReadWrite),
6056 		       atoi(parm), "readwrite");
6057 }
6058 
limitAsync(Pair * pair,char * parm,int start)6059 int limitAsync(Pair *pair, char *parm, int start) {
6060     (void)start;
6061     return limitCommon(pair, AsyncCount, atoi(parm), "async");
6062 }
6063 
limitErr(Pair * pair,char * parm,int start)6064 int limitErr(Pair *pair, char *parm, int start) {
6065     (void)start;
6066     if (Debug) message(LOG_ERR, ": Illegal LIMIT %s", parm);
6067     commOutput(pair, "500 Illegal LIMIT\r\n");
6068     return -2;	/* read more */
6069 }
6070 
6071 Comm limitComm[] = {
6072     { "PAIR", limitPair },
6073     { "CONN", limitConn },
6074     { "ESTABLISHED", limitEstablished },
6075     { "READWRITE", limitReadWrite },
6076     { "ASYNC", limitAsync },
6077     { NULL, limitErr },
6078 };
6079 
healthHELO(Pair * pair,char * parm,int start)6080 int healthHELO(Pair *pair, char *parm, int start) {
6081     char str[LONGSTRMAX+1];
6082     snprintf(str, LONGSTRMAX,
6083 	     "stone=%d pair=%d trash=%d conn=%d origin=%d",
6084 	     nStones(), nPairs(PairTop), nPairs(trash.next),
6085 	     nConns(), nOrigins());
6086     str[LONGSTRMAX] = '\0';
6087     if (Debug) message(LOG_DEBUG, ": HELO %s: %s", parm, str);
6088     (void)start;
6089     commOutput(pair, "250 stone:%s debug=%d %s\r\n",
6090 	       VERSION, Debug, str);
6091     return -2;	/* read more */
6092 }
6093 
healthSTAT(Pair * pair,char * parm,int start)6094 int healthSTAT(Pair *pair, char *parm, int start) {
6095     char str[LONGSTRMAX+1];
6096     int mc = MutexConflict;
6097     MutexConflict = 0;
6098     snprintf(str, LONGSTRMAX,
6099 	     "async=%d mutex=%d",
6100 	     AsyncCount, mc);
6101     str[LONGSTRMAX] = '\0';
6102     if (Debug) message(LOG_DEBUG, ": STAT %s: %s", parm, str);
6103     (void)start;
6104     commOutput(pair, "250 stone:%s debug=%d %s\r\n",
6105 	       VERSION, Debug, str);
6106     return -2;	/* read more */
6107 }
6108 
healthFREE(Pair * pair,char * parm,int start)6109 int healthFREE(Pair *pair, char *parm, int start) {
6110     char str[LONGSTRMAX+1];
6111     snprintf(str, LONGSTRMAX,
6112 	     "fpair=%d nfexbuf=%d nfexbot=%d nfpktbuf=%d",
6113 	     nFreePairs, nFreeExBuf, nFreeExBot, nFreePktBuf);
6114     str[LONGSTRMAX] = '\0';
6115     if (Debug) message(LOG_DEBUG, ": FREE %s: %s", parm, str);
6116     (void)start;
6117     commOutput(pair, "250 stone:%s debug=%d %s\r\n",
6118 	       VERSION, Debug, str);
6119     return -2;	/* read more */
6120 }
6121 
healthCLOCK(Pair * pair,char * parm,int start)6122 int healthCLOCK(Pair *pair, char *parm, int start) {
6123     char str[LONGSTRMAX+1];
6124     time_t now;
6125     time(&now);
6126     snprintf(str, LONGSTRMAX,
6127 	     "now=%ld established=%d readwrite=%d", (long)now,
6128 	     (int)(now - lastEstablished), (int)(now - lastReadWrite));
6129     str[LONGSTRMAX] = '\0';
6130     if (Debug) message(LOG_DEBUG, ": CLOCK %s: %s", parm, str);
6131     (void)start;
6132     commOutput(pair, "250 stone:%s debug=%d %s\r\n",
6133 	       VERSION, Debug, str);
6134     return -2;	/* read more */
6135 }
6136 
healthCVS_ID(Pair * pair,char * parm,int start)6137 int healthCVS_ID(Pair *pair, char *parm, int start) {
6138     (void)parm;
6139     (void)start;
6140     commOutput(pair, "200 stone %s %s\r\n", VERSION, CVS_ID);
6141     return -2;	/* read more */
6142 }
6143 
healthCONFIG(Pair * pair,char * parm,int start)6144 int healthCONFIG(Pair *pair, char *parm, int start) {
6145     int i;
6146     (void)parm;
6147     (void)start;
6148     for (i=1; i < ConfigArgc; i++)
6149 	commOutput(pair, "200%c%s\n", (i < ConfigArgc-1 ? '-' : ' '),
6150 		   ConfigArgv[i]);
6151     return -2;	/* read more */
6152 }
6153 
healthSTONE(Pair * pair,char * parm,int start)6154 int healthSTONE(Pair *pair, char *parm, int start) {
6155     Stone *stone;
6156     char str[STRMAX+1];
6157     (void)parm;
6158     (void)start;
6159     for (stone=stones; stone != NULL; stone=stone->next) {
6160 	Stone *child;
6161 	for (child=stone->children; child != NULL; child=child->children)
6162 	    commOutput(pair, "200-%s\n", stone2str(child, str, STRMAX));
6163 	commOutput(pair, "200%c%s\n", (stone->next ? '-' : ' '),
6164 		   stone2str(stone, str, STRMAX));
6165     }
6166     return -2;	/* read more */
6167 }
6168 
healthLIMIT(Pair * pair,char * parm,int start)6169 int healthLIMIT(Pair *pair, char *parm, int start) {
6170     Comm *comm = limitComm;
6171     char *q = NULL;
6172     while (comm->str) {
6173 	if ((q=comm_match(parm, comm->str)) != NULL) break;
6174 	comm++;
6175     }
6176     if (!q) return limitErr(pair, parm, start);
6177     return (*comm->func)(pair, q, start);
6178 }
6179 
healthQUIT(Pair * pair,char * parm,int start)6180 int healthQUIT(Pair *pair, char *parm, int start) {
6181     (void)pair;
6182     (void)start;
6183     if (Debug) message(LOG_DEBUG, ": QUIT %s", parm);
6184     return -1;
6185 }
6186 
healthCommon(char * comm,Pair * pair,char * parm,int start)6187 int healthCommon(char *comm, Pair *pair, char *parm, int start) {
6188     ExBuf *ex = pair->b;
6189     char buf[LONGSTRMAX];
6190     int i;
6191     int j = 0;
6192     int s = 0;
6193     buf[0] = '\0';
6194     (void)start;
6195     for (i=0; i < ex->len; i++) {
6196 	char c = ex->buf[ex->start + i];
6197 	if (s < 5) {
6198 	    if (toupper(c) == "HOST:"[s]) {
6199 		s++;
6200 	    } else {
6201 		s = 10;	/* skip to next line */
6202 	    }
6203 	} else if (s == 5) {
6204 	    if (c != ' ') s++;
6205 	} else if (s == 10) {
6206 	    if (c == '\r' || c == '\n') s++;
6207 	} else if (s == 11) {
6208 	    if (c != '\r' && c != '\n') {
6209 		s = 0;
6210 		i--;	/* unget */
6211 	    }
6212 	}
6213 	if (s == 6) {
6214 	    if (j >= LONGSTRMAX-2 || c == '\r' || c == '\n') {
6215 		buf[j++] = ' ';
6216 		buf[j] = '\0';
6217 		break;
6218 	    }
6219 	    buf[j++] = c;
6220 	}
6221     }
6222     if (*parm) message(LOG_INFO, "%s%s %s", buf, comm, parm);
6223     commOutput(pair, "HTTP/1.0 200 OK\r\nContent-Length: 0\r\n\r\n");
6224     return -2;
6225 }
6226 
healthGET(Pair * pair,char * parm,int start)6227 int healthGET(Pair *pair, char *parm, int start) {
6228     return healthCommon("GET", pair, parm, start);
6229 }
6230 
healthPOST(Pair * pair,char * parm,int start)6231 int healthPOST(Pair *pair, char *parm, int start) {
6232     return healthCommon("POST", pair, parm, start);
6233 }
6234 
healthHEAD(Pair * pair,char * parm,int start)6235 int healthHEAD(Pair *pair, char *parm, int start) {
6236     return healthCommon("HEAD", pair, parm, start);
6237 }
6238 
healthErr(Pair * pair,char * parm,int start)6239 int healthErr(Pair *pair, char *parm, int start) {
6240     (void)pair;
6241     (void)start;
6242     if (*parm) message(LOG_ERR, "Unknown health command: %s", parm);
6243     return -1;
6244 }
6245 
6246 Comm healthComm[] = {
6247     { "HELO", healthHELO },
6248     { "STAT", healthSTAT },
6249     { "FREE", healthFREE },
6250     { "CLOCK", healthCLOCK },
6251     { "CVS_ID", healthCVS_ID },
6252     { "CONFIG", healthCONFIG },
6253     { "STONE", healthSTONE },
6254     { "LIMIT", healthLIMIT },
6255     { "QUIT", healthQUIT },
6256     { "GET", healthGET },
6257     { "POST", healthPOST },
6258     { "HEAD", healthHEAD },
6259     { NULL, healthErr },
6260 };
6261 
memCheck(void)6262 int memCheck(void) {
6263     char *buf = malloc(BUFMAX * 10);
6264     if (buf) {
6265 	free(buf);
6266 	return 1;
6267     }
6268     message(LOG_CRIT, "memCheck: out of memory");
6269     return 0;
6270 }
6271 
docomm(Pair * pair,Comm * comm)6272 int docomm(Pair *pair, Comm *comm) {
6273     ExBuf *ex = pair->b;	/* bottom */
6274     char buf[BUFMAX];
6275     char *p;
6276     char *q = &ex->buf[ex->start + ex->len];
6277     int start, i;
6278     for (p=&ex->buf[ex->start]; p < q; p++) {
6279 	if (*p == '\r' || *p == '\n') break;
6280     }
6281     if (p >= q && p < &ex->buf[ex->bufmax]) {
6282 	ex->start += ex->len;
6283 	ex->len = 0;
6284 	return -2;	/* read more */
6285     }
6286     for (start=p-ex->buf-1; start >= 0; start--) {
6287 	if (ex->buf[start] == '\r' || ex->buf[start] == '\n') break;
6288     }
6289     start++;
6290     while ((*p == '\r' || *p == '\n') && p < q) p++;
6291     ex->start = p - ex->buf;
6292     if (p < q) {
6293 	ex->len = q - p;
6294     } else {
6295 	ex->len = 0;
6296     }
6297     while (comm->str) {
6298 	if ((q=comm_match(&ex->buf[start], comm->str)) != NULL) break;
6299 	comm++;
6300     }
6301     if (q == NULL) q = &ex->buf[start];
6302     for (i=0; q < p && i < BUFMAX-1; i++) {
6303 	if (*q == '\r' || *q == '\n') break;
6304 	buf[i] = *q++;
6305     }
6306     buf[i] = '\0';
6307     return (*comm->func)(pair, buf, start);
6308 }
6309 
insheader(Pair * pair)6310 int insheader(Pair *pair) {	/* insert header */
6311     ExBuf *ex = pair->b;	/* bottom */
6312     char *p;
6313     int bufmax = ex->bufmax;
6314     int len, i;
6315     len = ex->start + ex->len;
6316     for (i=ex->start; i < len; i++) {
6317 	if (ex->buf[i] == '\n') break;
6318     }
6319     if (i >= len) {
6320 	if (Debug > 3)
6321 	    message(LOG_DEBUG, "%d TCP %d: insheader needs more",
6322 		    pair->stone->sd, pair->sd);
6323 	return -1;
6324     }
6325     i++;
6326     len -= i;
6327     if (len > 0) {
6328 	bufmax -= len;		/* reserve */
6329 	/* save rest header */
6330 	bcopy(&ex->buf[i], &ex->buf[bufmax], len);
6331     }
6332     p = pair->stone->p;
6333     i += strnparse(&ex->buf[i], bufmax - i, &p, pair->pair, 0xFF);
6334     ex->buf[i++] = '\r';
6335     ex->buf[i++] = '\n';
6336     if (Debug > 5) {
6337 	message(LOG_DEBUG,
6338 		"%d TCP %d: insheader start=%d, ins=%d, rest=%d, max=%d",
6339 		pair->stone->sd, pair->sd, ex->start, i-ex->start, len, ex->bufmax);
6340     }
6341     if (len > 0)	/* restore */
6342 	bcopy(&ex->buf[bufmax], &ex->buf[i], len);
6343     ex->len = i - ex->start + len;
6344     return ex->len;
6345 }
6346 
rmheader(Pair * pair)6347 int rmheader(Pair *pair) {	/* remove header */
6348     ExBuf *ex = pair->b;	/* bottom */
6349     char *p;
6350     char *q = &ex->buf[ex->start+ex->len];
6351     int state = (pair->proto & state_mask);
6352     if (Debug > 3) message_buf(pair, ex->len, "rm");
6353     for (p=&ex->buf[ex->start]; p < q; p++) {
6354 	if (*p == '\r') continue;
6355 	if (*p == '\n') {
6356 	    state++;
6357 	    if (state >= 3) {
6358 		p++;
6359 		break;	/* end of header */
6360 	    }
6361 	} else {
6362 	    state = 1;
6363 	}
6364     }
6365     if (state < 3) {
6366 	ex->len = ex->start = 0;
6367 	pair->proto = ((pair->proto & ~state_mask) | state);
6368 	return -2;	/* header will continue... */
6369     }
6370     ex->len = q - p;	/* remove header */
6371     ex->start = p - ex->buf;
6372     pair->proto &= ~state_mask;
6373     return ex->len;
6374 }
6375 
first_read(Pair * pair)6376 int first_read(Pair *pair) {
6377     SOCKET sd = pair->sd;
6378     SOCKET psd;
6379     Pair *p = pair->pair;
6380     ExBuf *ex;
6381     Stone *stone = pair->stone;
6382     int len;
6383     if (p == NULL || (p->proto & (proto_shutdown | proto_close))
6384 	|| InvalidSocket(sd)) return -1;
6385     ex = p->b;	/* bottom */
6386     psd = p->sd;
6387     len = ex->len;
6388     pair->proto &= ~proto_first_r;
6389     if (p->proto & proto_command) {	/* proxy */
6390 	switch(p->proto & proto_command) {
6391 	case command_proxy:
6392 	    len = docomm(p, proxyComm);
6393 	    break;
6394 #ifdef USE_POP
6395 	case command_pop:
6396 	    if (getExData(p, data_apop, 0)) len = docomm(p, popComm);
6397 	    break;
6398 #endif
6399 	case command_health:
6400 	    if (!memCheck()) len = -1;
6401 	    else len = docomm(p, healthComm);
6402 	    break;
6403 	case command_identd:
6404 	    len = docomm(p, identdComm);
6405 	    break;
6406 	default:
6407 	    ;
6408 	}
6409 	if (len == -2) {	/* read more */
6410 	    if (Debug > 3) {
6411 		message(LOG_DEBUG, "%d TCP %d: read more from %d",
6412 			stone->sd, psd, sd);
6413 	    }
6414 	} else if (len < 0) {
6415 	    int flag = 0;
6416 	    if (!(pair->proto & proto_shutdown))
6417 		if (doshutdown(pair, 2) >= 0) flag = proto_shutdown;
6418 	    setclose(pair, flag);
6419 	    if (ValidSocket(psd)) {
6420 		flag = 0;
6421 		if (!(p->proto & proto_shutdown))
6422 		    if (doshutdown(p, 2) >= 0) flag = proto_shutdown;
6423 		setclose(p, flag);
6424 	    }
6425 	    return -1;
6426 	} else {
6427 	    len = ex->len;
6428 	}
6429     }
6430     if (pair->proto & proto_ohttp) {	/* over http */
6431 	len = rmheader(p);
6432 	if (len >= 0) {
6433 	    if (pair->proto & proto_ohttp_s) {
6434 		commOutput(p, "HTTP/1.0 200 OK\r\n\r\n");
6435 		pair->proto &= ~proto_ohttp_s;
6436 	    } else if (pair->proto & proto_ohttp_d) {
6437 		if (Debug > 3)
6438 		    message(LOG_DEBUG, "%d TCP %d: request to read, "
6439 			    "because response header from %d finished",
6440 			    stone->sd, psd, sd);
6441 		p->proto |= (proto_select_r | proto_dirty);
6442 	    }
6443 	}
6444     }
6445 #ifdef USE_POP
6446     if ((pair->proto & proto_command) == command_pop	/* apop */
6447 	&& !getExData(pair, data_apop, 0)) {
6448 	int i;
6449 	char *q;
6450 	for (i=ex->start; i < ex->start + ex->len; i++) {
6451 	    if (ex->buf[i] == '<') {	/* time stamp of APOP banner */
6452 		ExBuf *t = newExData(pair, data_apop);
6453 		if (!t) break;
6454 		q = t->buf + DATA_HEAD_LEN;
6455 		for (; i < ex->start + ex->len; i++) {
6456 		    *q++ = ex->buf[i];
6457 		    if (ex->buf[i] == '>') break;
6458 		}
6459 		*q = '\0';
6460 		if (Debug > 6)
6461 		    message(LOG_DEBUG, "%d TCP %d: APOP challenge: %s",
6462 			    stone->sd, sd, t->buf + DATA_HEAD_LEN);
6463 		break;
6464 	    }
6465 	}
6466     }
6467 #endif
6468     if (len <= 0 && !(pair->proto & (proto_eof | proto_close))) {
6469 	if (Debug > 8) {
6470 	    message(LOG_DEBUG, "%d TCP %d: read more", stone->sd, sd);
6471 	}
6472 	pair->proto |= (proto_select_r | proto_dirty);	/* read more */
6473 	if (len < 0) pair->proto |= (proto_first_r | proto_dirty);
6474     }
6475     return len;
6476 }
6477 
6478 #ifndef USE_EPOLL
message_select(int pri,char * msg,fd_set * rout,fd_set * wout,fd_set * eout)6479 static void message_select(int pri, char *msg,
6480 			   fd_set *rout, fd_set *wout, fd_set *eout) {
6481     int i, r, w, e;
6482     for (i=0; i < FD_SETSIZE; i++) {
6483 	r = FD_ISSET(i, rout);
6484 	w = FD_ISSET(i, wout);
6485 	e = FD_ISSET(i, eout);
6486 	if (r || w || e)
6487 	    message(pri, "%s %d: %c%c%c", msg,
6488 		    i, (r ? 'r' : ' '), (w ? 'w' : ' '), (e ? 'e' : ' '));
6489     }
6490 }
6491 #endif
6492 
6493 /* main event loop */
6494 
proto2fdset(int isthread,fd_set * routp,fd_set * woutp,fd_set * eoutp,Pair * pair)6495 void proto2fdset(
6496 #ifndef USE_EPOLL
6497     int isthread, fd_set *routp, fd_set *woutp, fd_set *eoutp,
6498 #endif
6499     Pair *pair) {
6500     SOCKET sd;
6501 #ifdef USE_EPOLL
6502     struct epoll_event ev;
6503     ev.events = EPOLLONESHOT;
6504     ev.data.ptr = pair;
6505 #endif
6506     if (!pair) return;
6507     sd = pair->sd;
6508     if (InvalidSocket(sd)) return;
6509 #ifndef USE_EPOLL
6510     if (!isthread && (pair->proto & proto_thread)) return;
6511 #endif
6512 #ifdef USE_SSL
6513     if (pair->ssl_flag & (sf_sb_on_r | sf_sb_on_w)) {
6514 #ifdef USE_EPOLL
6515 	if (pair->ssl_flag & sf_sb_on_r) ev.events |= EPOLLIN;
6516 	if (pair->ssl_flag & sf_sb_on_w) ev.events |= EPOLLOUT;
6517 	epoll_ctl(ePollFd, EPOLL_CTL_MOD, sd, &ev);
6518 #else
6519 	FD_CLR(sd, routp);
6520 	FD_CLR(sd, woutp);
6521 	if (pair->ssl_flag & sf_sb_on_r) FdSet(sd, routp);
6522 	if (pair->ssl_flag & sf_sb_on_w) FdSet(sd, woutp);
6523 #endif
6524     } else
6525 #endif
6526     if (pair->proto & proto_close) {
6527 	if (ValidSocket(sd)) {
6528 	    pair->sd = INVALID_SOCKET;
6529 	    closesocket(sd);
6530 	}
6531 	return;
6532     } else if (pair->proto & proto_conninprog) {
6533 #ifdef USE_EPOLL
6534 	ev.events |= (EPOLLOUT | EPOLLPRI);
6535 	epoll_ctl(ePollFd, EPOLL_CTL_MOD, sd, &ev);
6536 #else
6537 	FdSet(sd, woutp);
6538 	FdSet(sd, eoutp);
6539 #endif
6540 #ifdef USE_SSL
6541     } else if (pair->ssl_flag & sf_wb_on_r) {
6542 #ifdef USE_EPOLL
6543 	ev.events |= EPOLLIN;
6544 	epoll_ctl(ePollFd, EPOLL_CTL_MOD, sd, &ev);
6545 #else
6546 	FD_CLR(sd, woutp);
6547 	FdSet(sd, routp);
6548 #endif
6549     } else if (pair->ssl_flag & sf_rb_on_w) {
6550 #ifdef USE_EPOLL
6551 	ev.events |= EPOLLOUT;
6552 	epoll_ctl(ePollFd, EPOLL_CTL_MOD, sd, &ev);
6553 #else
6554 	FD_CLR(sd, routp);
6555 	FdSet(sd, woutp);
6556 #endif
6557     } else if (pair->ssl_flag & (sf_cb_on_r | sf_cb_on_w)) {
6558 	Pair *p = pair->pair;
6559 	if (p) {
6560 	    /*
6561 	      suppress hasty read/write until established connection.
6562 	      assumes p is located before pair in pairs list
6563 	    */
6564 	    SOCKET psd = p->sd;
6565 	    if (ValidSocket(psd)) {
6566 #ifdef USE_EPOLL
6567 		struct epoll_event pev;
6568 		pev.events = EPOLLONESHOT;
6569 		pev.data.ptr = p;
6570 		epoll_ctl(ePollFd, EPOLL_CTL_MOD, psd, &pev);
6571 		if (Debug > 7)
6572 		    message(LOG_DEBUG, "%d TCP %d: proto2fdset2 "
6573 			    "epoll_ctl %d MOD %lx events=%x",
6574 			    p->stone->sd, psd, ePollFd,
6575 			    (long)pev.data.ptr, pev.events);
6576 #else
6577 		FD_CLR(psd, routp);
6578 		FD_CLR(psd, woutp);
6579 #endif
6580 	    }
6581 	}
6582 #ifdef USE_EPOLL
6583 	if (pair->ssl_flag & (sf_cb_on_r)) ev.events |= EPOLLIN;
6584 	if (pair->ssl_flag & (sf_cb_on_w)) ev.events |= EPOLLOUT;
6585 	epoll_ctl(ePollFd, EPOLL_CTL_MOD, sd, &ev);
6586 #else
6587 	FD_CLR(sd, routp);
6588 	FD_CLR(sd, woutp);
6589 	if (pair->ssl_flag & (sf_cb_on_r)) FdSet(sd, routp);
6590 	if (pair->ssl_flag & (sf_cb_on_w)) FdSet(sd, woutp);
6591 #endif
6592     } else if (pair->ssl_flag & (sf_ab_on_r | sf_ab_on_w)) {
6593 #ifdef USE_EPOLL
6594 	if (pair->ssl_flag & (sf_ab_on_r)) ev.events |= EPOLLIN;
6595 	if (pair->ssl_flag & (sf_ab_on_w)) ev.events |= EPOLLOUT;
6596 	epoll_ctl(ePollFd, EPOLL_CTL_MOD, sd, &ev);
6597 #else
6598 	FD_CLR(sd, routp);
6599 	FD_CLR(sd, woutp);
6600 	if (pair->ssl_flag & (sf_ab_on_r)) FdSet(sd, routp);
6601 	if (pair->ssl_flag & (sf_ab_on_w)) FdSet(sd, woutp);
6602 #endif
6603 #endif
6604     } else if (pair->proto & proto_connect) {
6605 	int isset = 0;
6606 	if (!(pair->proto & proto_eof)
6607 	    && (pair->proto & proto_select_r)) {
6608 #ifdef USE_EPOLL
6609 	    ev.events |= EPOLLIN;
6610 #else
6611 	    FdSet(sd, routp);
6612 #endif
6613 	    isset = 1;
6614 	}
6615 	if (!(pair->proto & proto_shutdown)
6616 	    && (pair->proto & proto_select_w)) {
6617 #ifdef USE_EPOLL
6618 	    ev.events |= EPOLLOUT;
6619 #else
6620 	    FdSet(sd, woutp);
6621 #endif
6622 	    isset = 1;
6623 	}
6624 	if (isset)
6625 #ifdef USE_EPOLL
6626 	    ev.events |= EPOLLPRI;
6627 	epoll_ctl(ePollFd, EPOLL_CTL_MOD, sd, &ev);
6628 #else
6629 	    FdSet(sd, eoutp);
6630 #endif
6631     }
6632 #ifdef USE_EPOLL
6633     if (Debug > 7)
6634 	message(LOG_DEBUG, "%d TCP %d: proto2fdset "
6635 		"epoll_ctl %d MOD %lx events=%x",
6636 		pair->stone->sd, sd, ePollFd, (long)ev.data.ptr, ev.events);
6637 #endif
6638     pair->proto &= ~proto_dirty;
6639 }
6640 
6641 enum {
6642     RW_LEAVE = 0,
6643     RW_CONTINUE,
6644     RW_EINTR,
6645     RW_ONCE,
6646 };
6647 
doReadWritePair(Pair * pair,Pair * opposite,int ready_r,int ready_w,int ready_e,int hangup,int error)6648 int doReadWritePair(Pair *pair, Pair *opposite,
6649 		    int ready_r, int ready_w, int ready_e,
6650 		    int hangup, int error) {
6651     Pair *rPair, *wPair;
6652     Stone *stone;
6653     SOCKET stsd, sd, rsd, wsd;
6654     int len;
6655     int ret = RW_CONTINUE;	/* assume to continue */
6656     sd = pair->sd;
6657     if (InvalidSocket(sd)) return ret;
6658     stone = pair->stone;
6659     stsd = stone->sd;
6660     pair->loop++;
6661     if (hangup && (pair->proto & proto_connect)) ready_r = 1;
6662     if ((pair->proto & proto_conninprog)
6663 	&& (ready_w || ready_e || hangup)) {
6664 	int optval;
6665 	socklen_t optlen = sizeof(optval);
6666 	pair->proto &= ~proto_conninprog;
6667 	pair->proto |= proto_dirty;
6668 	if (getsockopt(sd, SOL_SOCKET, SO_ERROR,
6669 		       (char*)&optval, &optlen) < 0) {
6670 #ifdef WINDOWS
6671 	    errno = WSAGetLastError();
6672 #endif
6673 	    message(LOG_ERR, "%d TCP %d: getsockopt err=%d", stsd, sd, errno);
6674 	    pair->proto |= (proto_close | proto_dirty);
6675 	    if (opposite) opposite->proto |= (proto_close | proto_dirty);
6676 	    return RW_LEAVE;	/* leave */
6677 	}
6678 	if (optval) {
6679 	    message(LOG_ERR, "%d TCP %d: connect getsockopt err=%d",
6680 		    stsd, sd, optval);
6681 	    pair->proto |= (proto_close | proto_dirty);
6682 	    if (opposite) opposite->proto |= (proto_close | proto_dirty);
6683 	    return RW_LEAVE;	/* leave */
6684 	} else {	/* succeed in connecting */
6685 	    if (Debug > 4)
6686 		message(LOG_DEBUG, "%d TCP %d: connecting completed",
6687 			stsd, sd);
6688 	    connected(pair);
6689 	}
6690     } else if (ready_e) {	/* Out-of-Band Data */
6691 	char buf[1];
6692 	len = recv(sd, buf, 1, MSG_OOB);
6693 	if (len == 1) {
6694 	    if (opposite) wsd = opposite->sd; else wsd = INVALID_SOCKET;
6695 	    if (Debug > 3)
6696 		message(LOG_DEBUG, "%d TCP %d: MSG_OOB 0x%02x to %d",
6697 			stsd, sd, buf[0], wsd);
6698 	    if (ValidSocket(wsd)) {
6699 		len = send(wsd, buf, 1, MSG_OOB);
6700 		if (len != 1) {
6701 #ifdef WINDOWS
6702 		    errno = WSAGetLastError();
6703 #endif
6704 		    message(LOG_ERR,
6705 			    "%d TCP %d: send MSG_OOB ret=%d, err=%d",
6706 			    stsd, sd, len, errno);
6707 		}
6708 	    }
6709 	} else {
6710 #ifdef WINDOWS
6711 	    errno = WSAGetLastError();
6712 #endif
6713 	    message(LOG_ERR, "%d TCP %d: recv MSG_OOB ret=%d, err=%d",
6714 		    stsd, sd, len, errno);
6715 	}
6716 #ifdef USE_SSL
6717     } else if (((pair->ssl_flag & sf_sb_on_r) && ready_r)
6718 	       || ((pair->ssl_flag & sf_sb_on_w) && ready_w)
6719 	) {
6720 	pair->ssl_flag &= ~(sf_sb_on_r | sf_sb_on_w);
6721 	pair->proto |= proto_dirty;
6722 	doSSL_shutdown(pair, -1);
6723     } else if (((pair->ssl_flag & sf_cb_on_r) && ready_r)
6724 	       || ((pair->ssl_flag & sf_cb_on_w) && ready_w)) {
6725 	pair->ssl_flag &= ~(sf_cb_on_r | sf_cb_on_w);
6726 	pair->proto |= proto_dirty;
6727 	if (doSSL_connect(pair) < 0) {
6728 	    /* SSL_connect fails, shutdown pairs */
6729 	    if (opposite) {
6730 		if (!(opposite->proto & proto_shutdown))
6731 		    if (doshutdown(opposite, 2) >= 0)
6732 			opposite->proto |= (proto_shutdown | proto_dirty);
6733 		opposite->proto |= (proto_close | proto_dirty);
6734 	    }
6735 	    pair->proto |= (proto_close | proto_dirty);
6736 	}
6737     } else if (((pair->ssl_flag & sf_ab_on_r) && ready_r)
6738 	       || ((pair->ssl_flag & sf_ab_on_w) && ready_w)) {
6739 	pair->ssl_flag &= ~(sf_ab_on_r | sf_ab_on_w);
6740 	pair->proto |= proto_dirty;
6741 	if (doSSL_accept(pair) < 0) {
6742 	    /* SSL_accept fails */
6743 	    pair->proto |= (proto_close | proto_dirty);
6744 	    if (opposite) opposite->proto |= (proto_close | proto_dirty);
6745 	    return RW_LEAVE;	/* leave */
6746 	}
6747 	if (pair->proto & proto_connect) {
6748 	    if (!stone->ndsts && !stone_dsts(stone, NULL, NULL))
6749 		return RW_LEAVE;	/* leave */
6750 	    if (opposite) reqconn(opposite, &stone->dsts[0]->addr,
6751 				  stone->dsts[0]->len);
6752 	}
6753 #endif
6754     } else if (((pair->proto & proto_select_r) && ready_r	/* read */
6755 #ifdef USE_SSL
6756 		&& !(pair->ssl_flag & sf_wb_on_r))
6757 	       || ((pair->ssl_flag & sf_rb_on_w)
6758 		   && ready_w	/* WANT_WRITE */
6759 #endif
6760 		   )) {
6761 #ifdef USE_SSL
6762 	pair->ssl_flag &= ~sf_rb_on_w;
6763 	pair->proto |= proto_dirty;
6764 #endif
6765 	rPair = pair;
6766 	wPair = opposite;
6767 	rsd = sd;
6768 	if (wPair) wsd = wPair->sd; else wsd = INVALID_SOCKET;
6769 #ifdef USE_SSL
6770     read_pending:
6771 #endif
6772 	rPair->proto &= ~proto_select_r;
6773 	rPair->proto |= proto_dirty;
6774 	if (rPair->proto & proto_dgram) {	/* TCP <= UDP */
6775 	    len = recvPairUDP(rPair);
6776 	} else {
6777 	    rPair->count += REF_UNIT;
6778 	    len = doread(rPair);
6779 	    rPair->count -= REF_UNIT;
6780 	}
6781 	if (len < 0 || (rPair->proto & proto_close) || wPair == NULL) {
6782 	    if (len == -2	/* if EOF w/ pair, */
6783 		&& !(rPair->proto & proto_shutdown)
6784 		/* and not yet shutdowned, */
6785 		&& wPair
6786 		&& !(wPair->proto & (proto_eof | proto_shutdown
6787 				     | proto_close))
6788 		/* and not bi-directional EOF
6789 		   and peer is not yet shutdowned, */
6790 		&& (wPair->proto & proto_connect)
6791 		&& ValidSocket(wsd)) {	/* and pair is valid, */
6792 		/*
6793 		  recevied EOF from rPair,
6794 		  so reply SSL notify to rPair
6795 		  and send SSL notify and FIN to wPair...
6796 		*/
6797 		/* no more to read */
6798 		rPair->proto |= (proto_eof | proto_dirty);
6799 		/*
6800 		  Don't send notify, or further SSL_write will fail
6801 		  if (rPair->ssl) doSSL_shutdown(rPair, 0);
6802 		*/
6803 		if (!(wPair->proto & proto_shutdown))
6804 		    if (doshutdown(wPair, 1) >= 0)	/* send FIN */
6805 			wPair->proto |= (proto_shutdown | proto_dirty);
6806 		wPair->proto &= ~proto_select_w;
6807 		wPair->proto |= proto_dirty;
6808 	    } else {
6809 		/*
6810 		  error, already shutdowned, or bi-directional EOF,
6811 		  so reply SSL notify to rPair,
6812 		  send SSL notify to wPair and shutdown wPair,
6813 		  set close flag
6814 		*/
6815 		int flag = 0;
6816 		if (!(rPair->proto & proto_shutdown))
6817 		    if (doshutdown(rPair, 2) >= 0)
6818 			flag = proto_shutdown;
6819 		rPair->proto &= ~proto_select_w;
6820 		rPair->proto |= proto_dirty;
6821 		setclose(rPair, (proto_eof | flag));
6822 		flag = 0;
6823 		if (wPair) {
6824 		    if (!(wPair->proto & proto_shutdown))
6825 			if (doshutdown(wPair, 2) >= 0)
6826 			    flag = proto_shutdown;
6827 		    wPair->proto &= ~proto_select_w;
6828 		    wPair->proto |= proto_dirty;
6829 		    setclose(wPair, flag);
6830 		}
6831 	    }
6832 	} else {
6833 	    if (len > 0) {
6834 		int first_flag;
6835 		first_flag = (rPair->proto & proto_first_r);
6836 		if (first_flag) len = first_read(rPair);
6837 		if (wPair->proto & proto_dgram) {
6838 		    rPair->proto |= (proto_select_r | proto_dirty);
6839 		    if (sendPairUDP(wPair) < 0) {
6840 			int flag = 0;
6841 			if (!(rPair->proto & proto_shutdown))
6842 			    if (doshutdown(rPair, 2) >= 0)
6843 				flag = proto_shutdown;
6844 			rPair->proto &= ~proto_select_w;
6845 			rPair->proto |= proto_dirty;
6846 			setclose(rPair, (proto_eof | flag));
6847 		    }
6848 		} else if (len > 0 && ValidSocket(wsd)
6849 		    && (wPair->proto & proto_connect)
6850 		    && !(wPair->proto & (proto_shutdown | proto_close))
6851 		    && !(rPair->proto & proto_close)) {
6852 		    /* (wPair->proto & proto_eof) may be true */
6853 		    wPair->proto |= (proto_select_w | proto_dirty);
6854 #ifdef ALWAYS_BUFFERING
6855 		    rPair->proto |= (proto_select_r | proto_dirty);
6856 #endif
6857 		} else {
6858 		    return RW_LEAVE;	/* leave */
6859 		}
6860 	    } else {	/* EINTR */
6861 		rPair->proto |= (proto_select_r | proto_dirty);
6862 		ret = RW_EINTR;
6863 	    }
6864 	}
6865     } else if (((pair->proto & proto_select_w) && ready_w) /* write */
6866 #ifdef USE_SSL
6867 	       || ((pair->ssl_flag & sf_wb_on_r)
6868 		   && ready_r)	/* WANT_READ */
6869 #endif
6870 	) {
6871 #ifdef USE_SSL
6872 	pair->ssl_flag &= ~sf_wb_on_r;
6873 	pair->proto |= proto_dirty;
6874 #endif
6875 	wPair = pair;
6876 	rPair = opposite;
6877 	wsd = sd;
6878 	if (rPair) rsd = rPair->sd; else rsd = INVALID_SOCKET;
6879 	wPair->proto &= ~proto_select_w;
6880 	wPair->proto |= proto_dirty;
6881 	if (((wPair->proto & proto_command) == command_ihead) ||
6882 	    ((wPair->proto & proto_command) == command_iheads)) {
6883 	    int state = (wPair->proto & state_mask);
6884 	    if (state == 0) {
6885 		if (insheader(wPair) >= 0)	/* insert header */
6886 		    wPair->proto |= ++state;
6887 	    }
6888 	}
6889 	wPair->count += REF_UNIT;
6890 	len = dowrite(wPair);
6891 	wPair->count -= REF_UNIT;
6892 	if (len < 0 || (wPair->proto & proto_close) || rPair == NULL) {
6893 	    int flag = 0;
6894 	    if (rPair) {
6895 		if (ValidSocket(rsd)
6896 		    && !(rPair->proto & proto_shutdown))
6897 		    if (doshutdown(rPair, 2) >= 0) flag = proto_shutdown;
6898 		rPair->proto &= ~proto_select_w;
6899 		rPair->proto |= proto_dirty;
6900 		setclose(rPair, flag);
6901 	    }
6902 	    flag = 0;
6903 	    if (!(wPair->proto & proto_shutdown))
6904 		if (doshutdown(wPair, 2) >= 0) flag = proto_shutdown;
6905 	    setclose(wPair, flag);
6906 	} else {
6907 	    ExBuf *ex;
6908 	    ex = wPair->t;	/* top */
6909 	    /* (wPair->proto & proto_eof) may be true */
6910 	    if (ex->len <= 0) {	/* all written */
6911 		if (wPair->proto & proto_first_w) {
6912 		    wPair->proto &= ~proto_first_w;
6913 		    wPair->proto |= proto_dirty;
6914 		    if (rPair && ValidSocket(rsd)
6915 			&& ((rPair->proto & proto_command)
6916 			    == command_proxy)
6917 			&& ((rPair->proto & state_mask) == 1)) {
6918 			message_time_log(rPair);
6919 			if (Debug > 7)
6920 			    message(LOG_DEBUG,
6921 				    "%d TCP %d: reconnect proxy",
6922 				    stsd, wPair->sd);
6923 			wPair->proto |= (proto_first_r | proto_dirty);
6924 		    }
6925 		}
6926 		if (rPair && ValidSocket(rsd)
6927 		    && ((rPair->proto & proto_command)
6928 			== command_iheads)) {
6929 		    if (Debug > 7)
6930 			message(LOG_DEBUG,
6931 				"%d TCP %d: insheader again",
6932 				stsd, wPair->sd);
6933 		    rPair->proto &= ~state_mask;
6934 		}
6935 		if (rPair && ValidSocket(rsd)
6936 		    && (rPair->proto & proto_connect)
6937 		    && !(rPair->proto & (proto_eof | proto_close))
6938 		    && !(wPair->proto & (proto_shutdown | proto_close))
6939 		    ) {
6940 #ifdef USE_SSL
6941 		    if (rPair->ssl && SSL_pending(rPair->ssl)) {
6942 			if (Debug > 4)
6943 			    message(LOG_DEBUG,
6944 				    "%d TCP %d: SSL_pending, read again",
6945 				    stsd, rPair->sd);
6946 			ret = RW_ONCE;	/* read once */
6947 			goto read_pending;
6948 		    }
6949 #endif
6950 		    rPair->proto |= (proto_select_r | proto_dirty);
6951 		} else {
6952 		    return RW_LEAVE;	/* leave */
6953 		}
6954 	    } else {	/* EINTR */
6955 		wPair->proto |= (proto_select_w | proto_dirty);
6956 		ret = RW_EINTR;
6957 	    }
6958 	}
6959     } else if (error) {
6960 	if (Debug > 3) message(LOG_DEBUG, "%d TCP %d: error", stsd, sd);
6961 	pair->proto |= (proto_close | proto_dirty);
6962 	if (opposite) opposite->proto |= (proto_close | proto_dirty);
6963 	return RW_LEAVE;	/* leave */
6964     }
6965     return ret;
6966 }
6967 
6968 #ifndef USE_EPOLL
doReadWrite(Pair * pair)6969 void doReadWrite(Pair *pair) {	/* pair must be source side */
6970     int npairs = 1;
6971     Pair *p[2];
6972     SOCKET stsd;
6973     int loop;
6974     int rx[2];
6975     int tx[2];
6976     int i;
6977     fd_set ri, wi, ei;
6978     fd_set ro, wo, eo;
6979     struct timeval tv;
6980     p[0] = pair;
6981     p[1] = pair->pair;
6982     stsd = pair->stone->sd;
6983     if (Debug > 8) message(LOG_DEBUG, "%d TCP %d, %d: doReadWrite", stsd,
6984 			   (p[0] ? p[0]->sd : INVALID_SOCKET),
6985 			   (p[1] ? p[1]->sd : INVALID_SOCKET));
6986     if (p[1]) npairs++;
6987     FD_ZERO(&ri);
6988     FD_ZERO(&wi);
6989     FD_ZERO(&ei);
6990     rx[0] = p[0]->rx;
6991     tx[0] = p[0]->tx;
6992     if (p[1]) {
6993 	rx[1] = p[1]->rx;
6994 	tx[1] = p[1]->tx;
6995     } else {
6996 	rx[1] = -1;
6997 	tx[1] = -1;
6998     }
6999     loop = 0;
7000     for (;;) {	/* loop until timeout or EOF/error */
7001 	tv.tv_sec = 0;
7002 	tv.tv_usec = TICK_SELECT;
7003 	ro = ri;
7004 	wo = wi;
7005 	eo = ei;
7006 	for (i=0; i < npairs; i++) proto2fdset(1, &ro, &wo, &eo, p[i]);
7007 	if (Debug > 10)
7008 	    message_select(LOG_DEBUG, "selectReadWrite1", &ro, &wo, &eo);
7009 	if (select(FD_SETSIZE, &ro, &wo, &eo, &tv) <= 0) goto exit_loop;
7010 	if (Debug > 10)
7011 	    message_select(LOG_DEBUG, "selectReadWrite2", &ro, &wo, &eo);
7012 	for (i=0; i < npairs; i++) {
7013 	    SOCKET sd;
7014 	    int ret;
7015 	    if (!p[i]) continue;
7016 	    sd = p[i]->sd;
7017 	    if (InvalidSocket(sd)) continue;
7018 	    ret = doReadWritePair(p[i], p[1-i], FD_ISSET(sd, &ro),
7019 				  FD_ISSET(sd, &wo), FD_ISSET(sd, &eo), 0, 0);
7020 	    if (ret == RW_LEAVE) goto exit_loop;
7021 	    if (ret == RW_ONCE) break;		/* read once */
7022 	    if (ret == RW_EINTR) loop = 0;	/* EINTR */
7023 	}
7024 	if (++loop > 10) {	/* check if spin occured */
7025 	    if (rx[0] == p[0]->rx && tx[0] == p[0]->tx	/* no update => spin */
7026 		&& (!p[1] || (rx[1] == p[1]->rx && tx[1] == p[1]->tx))) {
7027 		message(LOG_ERR, "%d TCP %d, %d: doReadWrite Can't happen "
7028 			"spin occured tx/rx: %d/%d, %d/%d", stsd,
7029 			(p[0] ? p[0]->sd : INVALID_SOCKET),
7030 			(p[1] ? p[1]->sd : INVALID_SOCKET),
7031 			tx[0], rx[0], tx[1], rx[1]);
7032 		goto exit_loop;
7033 	    }
7034 	    rx[0] = p[0]->rx;
7035 	    tx[0] = p[0]->tx;
7036 	    if (p[1]) {
7037 		rx[1] = p[1]->rx;
7038 		tx[1] = p[1]->tx;
7039 	    }
7040 	    loop = 0;
7041 	}
7042     }
7043  exit_loop:
7044     for (i=0; i < npairs; i++) {
7045 	p[i]->proto &= ~proto_thread;
7046 	p[i]->proto |= proto_dirty;
7047 	p[i]->count -= REF_UNIT;
7048     }
7049     if (Debug > 8) message(LOG_DEBUG, "%d TCP %d, %d: doReadWrite end", stsd,
7050 			   (p[0] ? p[0]->sd : INVALID_SOCKET),
7051 			   (p[1] ? p[1]->sd : INVALID_SOCKET));
7052 }
7053 
asyncReadWrite(Pair * pair)7054 void asyncReadWrite(Pair *pair) {	/* pair must be source side */
7055     ASYNC_BEGIN;
7056     doReadWrite(pair);
7057     ASYNC_END;
7058 }
7059 
doPair(Pair * pair)7060 int doPair(Pair *pair) {
7061     SOCKET psd;
7062     Pair *p = pair->pair;
7063     if (!p || (pair->proto & proto_thread)) return 0;
7064     psd = p->sd;
7065     if (InvalidSocket(psd)) return 0;
7066     pair->count += REF_UNIT;
7067     p->count += REF_UNIT;
7068     pair->proto |= (proto_thread | proto_dirty);
7069     p->proto |= (proto_thread | proto_dirty);
7070     if ((pair->proto & proto_command) == command_source) {
7071 	ASYNC(asyncReadWrite, pair);
7072     } else {
7073 	ASYNC(asyncReadWrite, p);
7074     }
7075     return 1;
7076 }
7077 #endif
7078 
doAcceptConnect(Pair * p1)7079 int doAcceptConnect(Pair *p1) {
7080     Stone *stone = p1->stone;
7081     Pair *p2;
7082     int ret;
7083     if (Debug > 8) message(LOG_DEBUG, "%d TCP %d: doAcceptConnect",
7084 			   stone->sd, p1->sd);
7085     if (!acceptCheck(p1)) {
7086 	freePair(p1);
7087 	return 0;	/* pair is disposed */
7088     }
7089     p2 = p1->pair;
7090     if (p2->proto & proto_ohttp_d) {
7091 	int i;
7092 	char *p = stone->p;
7093 	ExBuf *ex = p2->b;	/* bottom */
7094 	i = strnparse(ex->buf, ex->bufmax - 5, &p, p1, 0xFF);
7095 	ex->buf[i++] = '\r';
7096 	ex->buf[i++] = '\n';
7097 	ex->buf[i++] = '\r';
7098 	ex->buf[i++] = '\n';
7099 	ex->len = i;
7100     }
7101     ret = -1;
7102     if ((p1->proto & proto_connect) || (p1->proto & proto_dgram)) {
7103 	if (!stone->ndsts && !stone_dsts(stone, NULL, NULL)) goto freepair;
7104 	ret = reqconn(p2, &stone->dsts[0]->addr,	/* 0 is default */
7105 		      stone->dsts[0]->len);
7106 	if (ret < 0) {
7107 	freepair:
7108 	    freePair(p2);
7109 	    freePair(p1);
7110 	    return 0;	/* pair is disposed */
7111 	}
7112     }
7113 #ifndef USE_EPOLL
7114     if (ret >= 0) {
7115 	p1->proto |= (proto_thread | proto_dirty);
7116 	p2->proto |= (proto_thread | proto_dirty);
7117 	doReadWrite(p1);
7118     }
7119 #endif
7120     if (!(p1->proto & proto_close)) {
7121 	p1->proto |= proto_dirty;
7122 	p2->proto |= proto_dirty;
7123 	insertPairs(p1);
7124 	return 1;	/* pair is inserted */
7125     } else {
7126 	freePair(p2);
7127 	freePair(p1);
7128 	return 0;	/* pair is disposed */
7129     }
7130 }
7131 
asyncAcceptConnect(Pair * pair)7132 void asyncAcceptConnect(Pair *pair) {
7133     ASYNC_BEGIN;
7134     doAcceptConnect(pair);
7135     ASYNC_END;
7136 }
7137 
getPairUDP(struct sockaddr * from,socklen_t fromlen,Stone * stone)7138 Pair *getPairUDP(struct sockaddr *from, socklen_t fromlen, Stone *stone) {
7139     Pair *pair;
7140     ExBuf *t;
7141     SockAddr *peer;
7142     for (pair=stone->pairs->next; pair && pair->clock != -1; pair=pair->next) {
7143 	Pair *p = pair->pair;
7144 	if ((pair->proto & proto_dgram) && p && (p->proto & proto_connect)) {
7145 	    ExBuf *t = getExData(pair, data_peeraddr, 0);
7146 	    SockAddr *dst;
7147 	    dst = (SockAddr*)(t->buf + DATA_HEAD_LEN);
7148 	    if (saComp(&dst->addr, from)) {
7149 		time(&pair->clock);
7150 		return pair;
7151 	    }
7152 	}
7153     }
7154     /* can't find pair, so create */
7155     pair = newPair();
7156     if (!pair) return NULL;
7157     /* save `from' to ExBuf to check in doAcceptConnect */
7158     bcopy(&fromlen, pair->t->buf, DATA_HEAD_LEN);
7159     bcopy(from, pair->t->buf + DATA_HEAD_LEN, fromlen);
7160     pair->stone = stone;
7161     pair->proto = (proto_dgram | command_source);
7162     pair->timeout = stone->timeout;
7163     t = newExData(pair, data_peeraddr);
7164     peer = (SockAddr*)(t->buf + DATA_HEAD_LEN);
7165     peer->len = fromlen;
7166     bcopy(from, &peer->addr, fromlen);
7167     if (doAcceptConnect(pair)) return pair;
7168     return NULL;	/* pair is disposed */
7169 }
7170 
recvStoneUDP(Stone * stone)7171 void recvStoneUDP(Stone *stone) {
7172     if (stone->proto & proto_udp_d) {	/* UDP => UDP */
7173 	PktBuf *pb = recvUDP(stone);
7174 	if (pb) {
7175 	    sendUDP(pb);
7176 	    ungetPktBuf(pb);
7177 	}
7178     } else {	/* UDP => TCP */
7179 	struct sockaddr_storage ss;
7180 	struct sockaddr *from = (struct sockaddr*)&ss;
7181 	socklen_t fromlen = sizeof(ss);
7182 	int flags = 0;
7183 	int len;
7184 	Pair *rPair;
7185 	Pair *wPair;
7186 	ExBuf *ex;
7187 	char addrport[STRMAX+1];
7188 	ex = getExBuf();
7189 	if (!ex) {
7190 	    message(LOG_CRIT, "%d UDP: out of memory", stone->sd);
7191 	    return;
7192 	}
7193 	ex->start = 0;
7194 #ifdef MSG_DONTWAIT
7195 	if (!(stone->proto & proto_block_s)) flags = MSG_DONTWAIT;
7196 #endif
7197 #ifdef MSG_TRUNC
7198 	flags |= MSG_TRUNC;
7199 #endif
7200 	len = recvfrom(stone->sd, ex->buf + UDP_HEAD_LEN,
7201 		       ex->bufmax - UDP_HEAD_LEN,
7202 		       flags, from, &fromlen);
7203 	addrport[0] = '\0';
7204 	if (len < 0) {
7205 #ifdef WINDOWS
7206 	    errno = WSAGetLastError();
7207 #endif
7208 	    addrport2strOnce(from, fromlen, proto_udp, addrport, STRMAX, 0);
7209 	    message(LOG_ERR, "%d UDP: recvfrom err=%d %s",
7210 		    stone->sd, errno, addrport);
7211 	    ungetExBuf(ex);
7212 	    return;
7213 	}
7214 	ex->buf[0] = ((unsigned)len >> 8);
7215 	ex->buf[1] = ((unsigned)len % 256);
7216 	ex->len += UDP_HEAD_LEN + len;
7217 	if (Debug > 8) {
7218 	    addrport2strOnce(from, fromlen, proto_udp, addrport, STRMAX, 0);
7219 	    message(LOG_DEBUG, "%d UDP: recvfrom len=%d %s",
7220 		    stone->sd, len, addrport);
7221 	}
7222 	rPair = getPairUDP(from, fromlen, stone);
7223 	if (!rPair) {
7224 	    message(LOG_ERR, "%d UDP: fail to get pair", stone->sd);
7225 	    ungetExBuf(ex);
7226 	    return;
7227 	}
7228 	rPair->rx += len;
7229 	wPair = rPair->pair;
7230 	if (wPair) {
7231 	    wPair->clock = rPair->clock;
7232 	    wPair->b->next = ex;
7233 	    wPair->b = ex;
7234 	    if (wPair->t->len <= 0) {
7235 		ExBuf *t = wPair->t;
7236 		wPair->t = wPair->t->next;	/* drop top */
7237 		ungetExBuf(t);
7238 	    }
7239 	    wPair->proto |= (proto_select_w | proto_dirty);
7240 	}
7241     }
7242 }
7243 
7244 #ifdef USE_EPOLL
dispatch(int epfd,struct epoll_event * evs,int nevs)7245 void dispatch(int epfd, struct epoll_event *evs, int nevs) {
7246     int i;
7247     for (i=0; i < nevs; i++) {
7248 	int common;
7249 	int other;
7250 	struct epoll_event ev = evs[i];
7251 	union {
7252 	    Stone stone;
7253 	    Pair pair;
7254 	    Origin origin;
7255 	} *p;
7256 	if (Debug > 8) message(LOG_DEBUG, "epoll %d: evs[%d].data=%lx",
7257 			       epfd, i, (long)ev.data.ptr);
7258 	common = *(int*)ev.data.ptr;
7259 	other = (ev.events & ~(EPOLLIN | EPOLLPRI | EPOLLOUT));
7260 	p = ev.data.ptr;
7261 	switch(common & type_mask) {
7262 	case type_stone:
7263 	    if (Debug > 10 || (other && Debug > 2))
7264 		message(LOG_DEBUG, "stone %d: epoll %d events=%x type=%d",
7265 			p->stone.sd, epfd, ev.events, common);
7266 	    if (p->stone.proto & proto_udp_s) {
7267 		recvStoneUDP(&p->stone);
7268 	    } else {
7269 		Pair *pair = acceptPair(&p->stone);
7270 		if (pair) {
7271 		    if (p->stone.proto & proto_ident) {
7272 			ASYNC(asyncAcceptConnect, pair);
7273 		    } else {
7274 			doAcceptConnect(pair);
7275 		    }
7276 		}
7277 	    }
7278 	    break;
7279 	case type_pair:
7280 	    if (Debug > 10 || (other && Debug > 2))
7281 		message(LOG_DEBUG, "TCP %d: epoll %d events=%x type=%d",
7282 			p->pair.sd, epfd, ev.events, common);
7283 	    doReadWritePair(&p->pair, p->pair.pair,
7284 			    (ev.events & EPOLLIN)  != 0,
7285 			    (ev.events & EPOLLOUT) != 0,
7286 			    (ev.events & EPOLLPRI) != 0,
7287 			    (ev.events & EPOLLHUP) != 0,
7288 			    (ev.events & EPOLLERR) != 0);
7289 	    break;
7290 	case type_origin:
7291 	    {
7292 		Origin *origin = &p->origin;
7293 		PktBuf *pb;
7294 		if (Debug > 10 || (other && Debug > 2))
7295 		    message(LOG_DEBUG, "%d UDP %d: epoll %d events=%x type=%d",
7296 			    origin->stone->sd, origin->sd,
7297 			    epfd, ev.events, common);
7298 		pb = recvUDP((Stone*)origin);
7299 		if (pb) {
7300 		    sendUDP(pb);
7301 		    ungetPktBuf(pb);
7302 		}
7303 	    }
7304 	    break;
7305 	default:
7306 	    message(LOG_ERR, "Irregular event events=%x type=%d",
7307 		    ev.events, common);
7308 	}
7309     }
7310 }
7311 #endif
7312 
scanPairs(fd_set * rop,fd_set * wop,fd_set * eop,Pair * pairs)7313 int scanPairs(
7314 #ifndef USE_EPOLL
7315     fd_set *rop, fd_set *wop, fd_set *eop,
7316 #endif
7317     Pair *pairs
7318     ) {
7319     Pair *pair;
7320     int ret = 1;
7321     int all;
7322     if (Debug > 8) message(LOG_DEBUG, "scanPairs");
7323     if (pairs) {
7324 	all = 0;
7325     } else {
7326 	pairs = PairTop;
7327 	all = 1;
7328     }
7329     for (pair=pairs->next;
7330 	 pair != NULL && (all || pair->clock != -1);	/* until top */
7331 	 pair=pair->next) {
7332 	SOCKET sd = pair->sd;
7333 	if (all && pair->clock == -1) {	/* skip top */
7334 	    pairs = pair;
7335 	    continue;
7336 	}
7337 	if (ValidSocket(sd)) {
7338 	    time_t clock;
7339 	    int idle = 1;	/* assume no events happen on sd */
7340 #ifndef USE_EPOLL
7341 	    if (pair->proto & proto_thread) continue;
7342 	    if (FD_ISSET(sd, rop) || FD_ISSET(sd, wop) || FD_ISSET(sd, eop)) {
7343 		Pair *p = pair->pair;
7344 		if (p && (p->proto & proto_dgram)) {
7345 		    doReadWritePair(pair, p,
7346 				    FD_ISSET(sd, rop),
7347 				    FD_ISSET(sd, wop),
7348 				    FD_ISSET(sd, eop), 0, 0);
7349 		    idle = 0;
7350 		} else if (doPair(pair)) idle = 0;
7351 	    }
7352 #endif
7353 	    if (idle && pair->timeout > 0
7354 		&& (time(&clock), clock - pair->clock > pair->timeout)) {
7355 		Pair *p = pair->pair;
7356 		if (Debug > 2) {
7357 		    message(LOG_DEBUG, "%d TCP %d: idle time exceeds",
7358 			    pair->stone->sd, sd);
7359 		    message_pair(LOG_DEBUG, pair);
7360 		}
7361 		setclose(pair, proto_shutdown);
7362 		if (p) setclose(p, proto_shutdown);
7363 	    }
7364 	}
7365     }
7366     if (Debug > 8) message(LOG_DEBUG, "scanPairs done");
7367     return ret;
7368 }
7369 
7370 #ifndef USE_EPOLL
scanStones(fd_set * rop,fd_set * wop,fd_set * eop)7371 int scanStones(fd_set *rop, fd_set *wop, fd_set *eop) {
7372     Stone *stone;
7373     for (stone=stones; stone != NULL; stone=stone->next) {
7374 	int isset;
7375 	waitMutex(FdEinMutex);
7376 	isset = (FD_ISSET(stone->sd, eop) && FD_ISSET(stone->sd, &ein));
7377 	if (isset) FD_CLR(stone->sd, &ein);
7378 	freeMutex(FdEinMutex);
7379 	if (isset) {
7380 	    message(LOG_ERR, "stone %d: exception", stone->sd);
7381 	} else {
7382 	    if (FD_ISSET(stone->sd, rop) && FD_ISSET(stone->sd, &rin)) {
7383 		if (stone->proto & proto_udp_s) {
7384 		    recvStoneUDP(stone);
7385 		} else {
7386 		    Pair *pair = acceptPair(stone);
7387 		    if (pair) ASYNC(asyncAcceptConnect, pair);
7388 		}
7389 	    }
7390 	}
7391 	if ((stone->proto & proto_udp_s) && (stone->proto & proto_udp_d)) {
7392 	    scanUDP(rop, eop, (Origin *)stone->p);
7393 	} else {
7394 	    scanPairs(rop, wop, eop, stone->pairs);
7395 	}
7396     }
7397     return 1;
7398 }
7399 #endif
7400 
7401 /* stone */
7402 
7403 #ifdef USE_SSL
hostcmp(char * pat,char * host)7404 static int hostcmp(char *pat, char *host) {
7405     char a, b;
7406     while (*pat) {
7407 	if (*pat == '*') {
7408 	    pat++;
7409 	    while (*host) {
7410 		if (*host == *pat) break;
7411 		host++;
7412 	    }
7413 	}
7414 	a = toupper(*pat);
7415 	b = toupper(*host);
7416 	if (a != b) return a - b;
7417 	pat++;
7418 	host++;
7419     }
7420     return *host;
7421 }
7422 
hostcheck(Pair * pair,X509 * cert,char * host)7423 static int hostcheck(Pair *pair, X509 *cert, char *host) {
7424     X509_EXTENSION *ext;
7425     GENERAL_NAMES *ialt;
7426     char name[LONGSTRMAX+1];
7427     int i = X509_get_ext_by_NID(cert, NID_subject_alt_name, -1);
7428     if (i >= 0
7429 	&& (ext=X509_get_ext(cert, i))
7430 	&& (ialt=X509V3_EXT_d2i(ext))) {
7431 	int done = 0;
7432 	for (i=0; !done && i < (int)sk_GENERAL_NAME_num(ialt); i++) {
7433 	    GENERAL_NAME *gen = sk_GENERAL_NAME_value(ialt, i);
7434 	    if (gen->type == GEN_DNS && gen->d.ia5) {
7435 		int len = gen->d.ia5->length;
7436 		if (len > LONGSTRMAX) len = LONGSTRMAX;
7437 		strncpy(name, (char*)gen->d.ia5->data, len);
7438 		name[len] = '\0';
7439 		if (hostcmp(name, host) == 0) {
7440 		    if (Debug > 4)
7441 			message(LOG_DEBUG, "match %s dNSName=%s",
7442 				host, name);
7443 		    done = 1;	/* match */
7444 		} else if (Debug > 5) message(LOG_DEBUG, "dNSName: %s", name);
7445 	    }
7446 	    GENERAL_NAME_free(gen);
7447 	}
7448 	sk_GENERAL_NAME_free(ialt);
7449 	if (done) return 1;
7450     }
7451     if (X509_NAME_get_text_by_NID(X509_get_subject_name(cert), NID_commonName,
7452 				  name, sizeof(name)) >= 0) {
7453 	if (hostcmp(name, host) == 0) {
7454 	    if (Debug > 4) message(LOG_DEBUG, "match %s CN=%s", host, name);
7455 	    return 1;	/* match */
7456 	}
7457 	message(LOG_ERR, "%d TCP %d: connect to %s, but CN=%s",
7458 		pair->stone->sd, pair->sd, host, name);
7459 	return 0;
7460     }
7461     message(LOG_ERR, "%d TCP %d: no dNSName nor CN",
7462 	    pair->stone->sd, pair->sd);
7463     return 0;
7464 }
7465 
verify_callback(int preverify_ok,X509_STORE_CTX * ctx)7466 static int verify_callback(int preverify_ok, X509_STORE_CTX *ctx) {
7467     X509 *err_cert;
7468     int err, depth, depthmax;
7469     regex_t *re;
7470     long serial = -1;
7471     SSL *ssl;
7472     Pair *pair;
7473     StoneSSL *ss;
7474     char buf[BUFMAX];
7475     char *p;
7476     err_cert = X509_STORE_CTX_get_current_cert(ctx);
7477     err = X509_STORE_CTX_get_error(ctx);
7478     depth = X509_STORE_CTX_get_error_depth(ctx);
7479     ssl = X509_STORE_CTX_get_ex_data
7480 		(ctx, SSL_get_ex_data_X509_STORE_CTX_idx());
7481     if (!ssl) {
7482 	message(LOG_ERR, "SSL callback can't get SSL object");
7483 	return 0;	/* always fail */
7484     }
7485     pair = SSL_get_ex_data(ssl, PairIndex);
7486     if (!pair) {
7487 	message(LOG_ERR, "SSL callback don't have ex_data, verify fails");
7488 	return 0;	/* always fail */
7489     }
7490     if ((pair->proto & proto_command) == command_source) {
7491 	ss = pair->stone->ssl_server;
7492     } else {
7493 	ss = pair->stone->ssl_client;
7494     }
7495     depthmax = ((pair->ssl_flag & sf_depth) >> sf_depth_bit);
7496     if (depth >= depthmax) {
7497 	depthmax = depth + 1;
7498 	pair->ssl_flag = ((pair->ssl_flag & ~sf_depth)
7499 			  | (depthmax << sf_depth_bit));
7500     }
7501     if (depth == 0) {
7502 	ASN1_INTEGER *n = X509_get_serialNumber(err_cert);
7503 	if (n) serial = ASN1_INTEGER_get(n);
7504 	if (ss->serial == -1 && serial >= 0) {
7505 	    ss->serial = serial;
7506 	} else if (ss->serial >= 0 && serial != ss->serial) {
7507 	    message(LOG_ERR, "%d TCP %d: SSL callback serial number mismatch "
7508 		    "%lx != %lx", pair->stone->sd, pair->sd,
7509 		    serial, ss->serial);
7510 	    return 0;	/* fail */
7511 	}
7512 	if (ss->name
7513 	    && !ss->re[depth]
7514 	    && !hostcheck(pair, err_cert, ss->name)) return 0;
7515     }
7516     if (Debug > 3)
7517 	message(LOG_DEBUG,
7518 		"%d TCP %d: callback: err=%d, depth=%d/%d, preverify=%d",
7519 		pair->stone->sd, pair->sd, err, depth, depth - depthmax,
7520 		preverify_ok);
7521     p = X509_NAME_oneline(X509_get_subject_name(err_cert), buf, BUFMAX-1);
7522     if (!p) return 0;
7523     if (ss->verbose) message(LOG_DEBUG, "%d TCP %d: [depth%d=%s]",
7524 			     pair->stone->sd, pair->sd, depth, p);
7525     if (depth > ss->depth) {
7526 	preverify_ok = 0;
7527 	X509_STORE_CTX_set_error(ctx, X509_V_ERR_CERT_CHAIN_TOO_LONG);
7528     }
7529     if (!preverify_ok) {
7530 #ifdef CRYPTOAPI
7531 	if (ss->sslparm & sslparm_storeca) {
7532 	    int ret = CryptoAPI_verify_certificate(err_cert);
7533 	    if (ret < 0) {
7534 		if (ss->verbose)
7535 		    message(LOG_DEBUG, "%d TCP %d: verify error err=%d %s, "
7536 			    "CryptoAPI verify %ld",
7537 			    pair->stone->sd, pair->sd,
7538 			    err, X509_verify_cert_error_string(err),
7539 			    ERR_get_error());
7540 		return 0;
7541 	    } else if (ret == 0) {
7542 		if (ss->verbose)
7543 		    message(LOG_DEBUG, "%d TCP %d: verify error err=%d %s, "
7544 			    "CryptoAPI certificate is not trusted",
7545 			    pair->stone->sd, pair->sd,
7546 			    err, X509_verify_cert_error_string(err));
7547 		return 0;
7548 	    }
7549 	} else {
7550 #endif
7551 	    if (ss->verbose)
7552 		message(LOG_DEBUG, "%d TCP %d: verify error err=%d %s",
7553 			pair->stone->sd, pair->sd,
7554 			err, X509_verify_cert_error_string(err));
7555 	    if (!(ss->sslparm & sslparm_ignore)) return 0;
7556 #ifdef CRYPTOAPI
7557 	}
7558 #endif
7559     }
7560     re = ss->re[DEPTH_MAX - depthmax + depth];
7561     if (!re) re = ss->re[depth];
7562     if (depth < DEPTH_MAX && re) {
7563 	regmatch_t pmatch[NMATCH_MAX];
7564 	err = regexec(re, p, (size_t)NMATCH_MAX, pmatch, 0);
7565 	if (Debug > 3) message(LOG_DEBUG, "%d TCP %d: regexec%d=%d",
7566 			       pair->stone->sd, pair->sd, depth, err);
7567 	if (err) return 0;	/* not match */
7568 	char **match = SSL_get_ex_data(ssl, MatchIndex);
7569 	if (!match) {
7570 	    match = malloc(sizeof(char*) * (NMATCH_MAX+1));
7571 	    if (!match) {
7572 		message(LOG_ERR,
7573 			"%d TCP %d: SSL callback can't get ex_data",
7574 			pair->stone->sd, pair->sd);
7575 		return 0;
7576 	    }
7577 	    int i;
7578 	    for (i=0; i <= NMATCH_MAX; i++)
7579 		match[i] = NULL;
7580 	    if (Debug > 4) message(LOG_DEBUG, "newMatch %d: %llx",
7581 				   NewMatchCount++, (long long)match);
7582 	    SSL_set_ex_data(ssl, MatchIndex, match);
7583 	}
7584 	int i;
7585 	int j = 1;
7586 	if (serial >= 0) {
7587 	    char str[STRMAX+1];
7588 	    int len;
7589 	    snprintf(str, STRMAX, "%lx", serial);
7590 	    len = strlen(str);
7591 	    if (match[0]) free(match[0]);
7592 	    match[0] = malloc(len+1);
7593 	    if (match[0]) {
7594 		strncpy(match[0], str, len);
7595 		match[0][len] = '\0';
7596 	    }
7597 	}
7598 	for (i=1; i <= NMATCH_MAX; i++) {
7599 	    if (match[i]) continue;
7600 	    if (pmatch[j].rm_so >= 0) {
7601 		int len = pmatch[j].rm_eo - pmatch[j].rm_so;
7602 		match[i] = malloc(len+1);
7603 		if (match[i]) {
7604 		    strncpy(match[i], p + pmatch[j].rm_so, len);
7605 		    match[i][len] = '\0';
7606 		    if (Debug > 4) message(LOG_DEBUG, "%d TCP %d: \\%d=%s",
7607 					   pair->stone->sd, pair->sd,
7608 					   i, match[i]);
7609 		}
7610 		j++;
7611 	    }
7612 	}
7613     } else {
7614 	if (Debug > 3) message(LOG_DEBUG, "%d TCP %d: re%d=NULL",
7615 			       pair->stone->sd, pair->sd, depth);
7616     }
7617     return 1;	/* if re is null, always succeed */
7618 }
7619 
passwd_callback(char * buf,int size,int rwflag,void * passwd)7620 static int passwd_callback(char *buf, int size, int rwflag, void *passwd) {
7621     (void)rwflag;
7622     strncpy(buf, (char *)(passwd), size);
7623     buf[size-1] = '\0';
7624     return(strlen(buf));
7625 }
7626 
7627 #ifndef OPENSSL_NO_TLSEXT
ssl_servername_callback(SSL * ssl,int * ad,void * arg)7628 static int ssl_servername_callback(SSL *ssl, int *ad, void *arg) {
7629     Pair *pair = SSL_get_ex_data(ssl, PairIndex);
7630     StoneSSL *ss = pair->stone->ssl_server;
7631     Stone *stone;
7632     const char *name = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
7633     if (!ss || !ss->name) return SSL_TLSEXT_ERR_NOACK;
7634     if (!name) {
7635 	if (ss && ss->verbose)
7636 	    message(LOG_DEBUG, "%d TCP %d: No servername, expects: %s",
7637 		    pair->stone->sd, pair->sd, ss->name);
7638 	return SSL_TLSEXT_ERR_OK;
7639     }
7640     if (strcmp(name, ss->name) == 0) return SSL_TLSEXT_ERR_OK;
7641     for (stone=pair->stone->children; stone; stone=stone->children) {
7642 	StoneSSL *sn = stone->ssl_server;
7643 	if (!sn || !sn->name) return SSL_TLSEXT_ERR_NOACK;
7644 	if (strcmp(name, sn->name) == 0) {
7645 	    if (sn->verbose)
7646 		message(LOG_DEBUG, "%d TCP %d: Switching server context: %s",
7647 			stone->sd, pair->sd, sn->name);
7648 	    SSL_set_SSL_CTX(ssl, sn->ctx);
7649 	    pair->stone = stone;
7650 	    return SSL_TLSEXT_ERR_OK;
7651 	}
7652     }
7653     (void)ad;
7654     (void)arg;
7655     return SSL_TLSEXT_ERR_ALERT_FATAL;
7656 }
7657 #endif
7658 
mkStoneSSL(SSLOpts * opts,int isserver)7659 StoneSSL *mkStoneSSL(SSLOpts *opts, int isserver) {
7660     StoneSSL *ss;
7661     int err;
7662     int i;
7663     ss = malloc(sizeof(StoneSSL));
7664     if (!ss) {
7665     memerr:
7666 	message(LOG_CRIT, "Out of memory");
7667 	exit(1);
7668     }
7669     ss->verbose = opts->verbose;
7670     ss->shutdown_mode = opts->shutdown_mode;
7671     ss->name = opts->servername;
7672     ss->ctx = SSL_CTX_new(opts->meth);
7673     if (!ss->ctx) {
7674 	message(LOG_ERR, "SSL_CTX_new error");
7675 	goto error;
7676     }
7677     SSL_CTX_set_options(ss->ctx, opts->off);
7678     SSL_CTX_set_mode(ss->ctx, SSL_MODE_ENABLE_PARTIAL_WRITE);
7679     SSL_CTX_set_verify(ss->ctx, opts->mode, opts->callback);
7680     SSL_CTX_set_verify_depth(ss->ctx, opts->depth + 1);
7681     ss->depth = opts->depth;
7682     ss->serial = opts->serial;
7683     ss->lbmod = opts->lbmod;
7684     ss->lbparm = opts->lbparm;
7685     if (opts->caFile || opts->caPath) {
7686 	if (!SSL_CTX_load_verify_locations(ss->ctx,
7687 					   opts->caFile, opts->caPath)) {
7688 	    message(LOG_ERR, "SSL_CTX_load_verify_locations(%s,%s) error",
7689 		    opts->caFile, opts->caPath);
7690 	    goto error;
7691 	}
7692 	if (opts->vflags)
7693 	    X509_STORE_set_flags(SSL_CTX_get_cert_store(ss->ctx),
7694 				 opts->vflags);
7695     }
7696     if (opts->pfxFile) {
7697 	FILE *fp = fopen(opts->pfxFile, "r");
7698 	PKCS12 *p12;
7699 	EVP_PKEY *key;
7700 	X509 *cert;
7701 	if (!fp) {
7702 	    message(LOG_ERR, "Can't open pfx file: %s", opts->pfxFile);
7703 	    goto error;
7704 	}
7705 	p12 = d2i_PKCS12_fp(fp, NULL);
7706 	if (!p12) {
7707 	    message(LOG_ERR, "Can't read pfx file: %s", opts->pfxFile);
7708 	    fclose(fp);
7709 	    goto error;
7710 	}
7711 	fclose(fp);
7712 	key = NULL;
7713 	cert = NULL;
7714 	if (!PKCS12_parse(p12, opts->passwd, &key, &cert, NULL)) {
7715 	    message(LOG_ERR, "Can't parse PKCS12(%s) %s",
7716 		    opts->pfxFile, ERR_error_string(ERR_get_error(), NULL));
7717 	    goto error;
7718 	}
7719 	if (cert) {
7720 	    if (!SSL_CTX_use_certificate(ss->ctx, cert)) {
7721 		message(LOG_ERR, "SSL_CTX_use_certificate(%s) %s",
7722 			opts->pfxFile,
7723 			ERR_error_string(ERR_get_error(), NULL));
7724 		X509_free(cert);
7725 		goto error;
7726 	    }
7727 	    X509_free(cert);
7728 	}
7729 	if (key) {
7730 	    if (!SSL_CTX_use_PrivateKey(ss->ctx, key)) {
7731 		message(LOG_ERR, "SSL_CTX_use_PrivateKey(%s) %s",
7732 			opts->pfxFile,
7733 			ERR_error_string(ERR_get_error(), NULL));
7734 		EVP_PKEY_free(key);
7735 		goto error;
7736 	    }
7737 	    EVP_PKEY_free(key);
7738 	}
7739 	PKCS12_free(p12);
7740     } else {
7741 	if (opts->passwd) {
7742 	    SSL_CTX_set_default_passwd_cb(ss->ctx, passwd_callback);
7743 	    SSL_CTX_set_default_passwd_cb_userdata(ss->ctx, opts->passwd);
7744 	}
7745 	if (opts->keyFile
7746 	    && !SSL_CTX_use_PrivateKey_file
7747 	    (ss->ctx, opts->keyFile, X509_FILETYPE_PEM)) {
7748 	    message(LOG_ERR, "SSL_CTX_use_PrivateKey_file(%s) %s",
7749 		    opts->keyFile, ERR_error_string(ERR_get_error(), NULL));
7750 	    goto error;
7751 	}
7752 	if (opts->certFile
7753 	    && !SSL_CTX_use_certificate_file(ss->ctx, opts->certFile,
7754 					     X509_FILETYPE_PEM)) {
7755 	    message(LOG_ERR, "SSL_CTX_use_certificate_file(%s) error",
7756 		    opts->certFile);
7757 	    goto error;
7758 	}
7759     }
7760     ss->sslparm = 0;
7761     if (opts->useSNI) ss->sslparm |= sslparm_sni;
7762     if (opts->certIgnore) ss->sslparm |= sslparm_ignore;
7763 #ifdef CRYPTOAPI
7764     if (opts->certStoreCA) ss->sslparm |= sslparm_storeca;
7765     if (opts->certStore) {
7766 	if (!SSL_CTX_use_CryptoAPI_certificate(ss->ctx, opts->certStore)) {
7767 	    message(LOG_ERR, "Can't load certificate \"%s\" "
7768 		    "from Microsoft Certificate Store, %s",
7769 		    opts->certStore, ERR_error_string(ERR_get_error(), NULL));
7770 	    goto error;
7771         }
7772     }
7773 #endif
7774 #ifdef ANDROID
7775     ss->keystore = NULL;
7776     if (opts->certStore) {
7777 	int nkeys = use_keystore(ss->ctx, opts->certStore);
7778 	if (nkeys <= 0) ss->keystore = opts->certStore;
7779     }
7780 #endif
7781     if (opts->cipherList
7782 	&& !SSL_CTX_set_cipher_list(ss->ctx, opts->cipherList)) {
7783 	message(LOG_ERR, "SSL_CTX_set_cipher_list(%s) error",
7784 		opts->cipherList);
7785 	goto error;
7786     }
7787     for (i=0; i < DEPTH_MAX; i++) {
7788 	if (opts->regexp[i]) {
7789 	    ss->re[i] = malloc(sizeof(regex_t));
7790 	    if (!ss->re[i]) goto memerr;
7791 	    err = regcomp(ss->re[i], opts->regexp[i], REG_EXTENDED|REG_ICASE);
7792 	    if (err) {
7793 		message(LOG_ERR, "RegEx compiling error %d", err);
7794 		goto error;
7795 	    }
7796 	    if (Debug > 5) {
7797 		message(LOG_DEBUG, "regexp[%d]=%s", i, opts->regexp[i]);
7798 	    }
7799 	} else {
7800 	    ss->re[i] = NULL;
7801 	}
7802     }
7803     if (isserver) {
7804 #ifndef OPENSSL_NO_TLSEXT
7805 	if (ss->sslparm & sslparm_sni) {
7806 	    SSL_CTX_set_tlsext_servername_callback
7807 		(ss->ctx, ssl_servername_callback);
7808 	}
7809 #endif
7810 	if (opts->sid_ctx) {
7811 	    int ret;
7812 	    int len = strlen((char*)opts->sid_ctx);
7813 	    ret = SSL_CTX_set_session_id_context(ss->ctx, opts->sid_ctx, len);
7814 	    if (!ret) {
7815 		len = SSL_MAX_SSL_SESSION_ID_LENGTH;
7816 		opts->sid_ctx[len] = '\0';
7817 		message(LOG_ERR, "Too long sid_ctx, truncated to '%s'",
7818 			opts->sid_ctx);
7819 		ret = SSL_CTX_set_session_id_context(ss->ctx,
7820 						     opts->sid_ctx, len);
7821 		if (!ret) {
7822 		    message(LOG_ERR, "SSL_CTX_set_session_id_context error");
7823 		}
7824 	    }
7825 	}
7826 	SSL_CTX_set_session_cache_mode
7827 	    (ss->ctx, (SSL_SESS_CACHE_SERVER | SSL_SESS_CACHE_NO_AUTO_CLEAR));
7828     }
7829     return ss;
7830  error:
7831     if (opts->verbose)
7832 	message(LOG_INFO, "%s", ERR_error_string(ERR_get_error(), NULL));
7833     exit(1);
7834 }
7835 
rmStoneSSL(StoneSSL * ss)7836 void rmStoneSSL(StoneSSL *ss) {
7837     int i;
7838     SSL_CTX_free(ss->ctx);
7839     for (i=0; i < DEPTH_MAX; i++) {
7840 	if (ss->re[i]) {
7841 	    regfree(ss->re[i]);
7842 	    free(ss->re[i]);
7843 	}
7844     }
7845     free(ss);
7846 }
7847 
exPatFile(char * pat,char * name,char * src,char * dst)7848 char *exPatFile(char *pat, char *name, char *src, char *dst) {
7849     char str[STRMAX+1];
7850     char *p;
7851     int pos, len, nlen, slen, dlen;
7852     int l;
7853     if (!name) name = "";
7854     if (!src) src = "";
7855     if (!dst) dst = "";
7856     nlen = strlen(name);
7857     slen = strlen(src);
7858     dlen = strlen(dst);
7859     len = 0;
7860     for (pos=0; pos < STRMAX; pos++) {
7861 	if (pat[pos] == '\0') {
7862 	    str[len] = '\0';
7863 	    break;
7864 	} else if (pat[pos] == '%') {
7865 	    switch (pat[++pos]) {
7866 	    case 'n':	l = nlen; p = name; break;
7867 	    case 's':	l = slen; p = src;  break;
7868 	    case 't':	l = dlen; p = dst;  break;
7869 	    default:
7870 		l = 1;
7871 		p = &pat[pos];
7872 	    }
7873 	    if (len + l >= STRMAX) l = STRMAX - len;
7874 	    strncpy(str+len, p, l);
7875 	    len += l;
7876 	} else {
7877 	    str[len++] = pat[pos];
7878 	}
7879     }
7880     str[STRMAX] = '\0';
7881     return strdup(str);
7882 }
7883 
exPatOpts(SSLOpts * opts,char * src,char * dst)7884 void exPatOpts(SSLOpts *opts, char *src, char *dst) {
7885     if (opts->pfxFilePat) {
7886 	opts->pfxFile = exPatFile(opts->pfxFilePat,
7887 				  opts->servername, src, dst);
7888 	if (Debug > 3) message(LOG_DEBUG, "exPatPfx: %s => %s",
7889 			       opts->pfxFilePat, opts->pfxFile);
7890     } else {
7891 	if (opts->certFilePat) {
7892 	    opts->certFile = exPatFile(opts->certFilePat,
7893 				       opts->servername, src, dst);
7894 	    if (Debug > 3) message(LOG_DEBUG, "exPatCert: %s => %s",
7895 				   opts->certFilePat, opts->certFile);
7896 	}
7897 	if (opts->keyFilePat) {
7898 	    opts->keyFile = exPatFile(opts->keyFilePat,
7899 				      opts->servername, src, dst);
7900 	    if (Debug > 3) message(LOG_DEBUG, "exPatKey: %s => %s",
7901 				   opts->keyFilePat, opts->keyFile);
7902 	}
7903     }
7904     if (opts->passFilePat) {
7905 	opts->passFile = exPatFile(opts->passFilePat,
7906 				   opts->servername, src, dst);
7907 	if (Debug > 3) message(LOG_DEBUG, "exPatPass: %s => %s",
7908 			       opts->passFilePat, opts->passFile);
7909     }
7910     if (opts->passFile) {
7911     	FILE *fp = fopen(opts->passFile, "r");
7912 	char str[STRMAX+1];
7913 	int i;
7914 	if (!fp) {
7915 	    message(LOG_ERR, "Can't open passwd file: %s", opts->passFile);
7916 	    exit(1);
7917 	}
7918 	for (i=0; i < STRMAX; i++) {
7919 	    int c = getc(fp);
7920 	    if (c == '\r' || c == '\n' || c == EOF) break;
7921 	    str[i] = c;
7922 	}
7923 	str[i] = '\0';
7924 	fclose(fp);
7925 	opts->passwd = strdup(str);
7926     }
7927 }
7928 #endif
7929 
rmoldstone(void)7930 void rmoldstone(void) {
7931     Stone *stone, *next;
7932     stone = oldstones;
7933     oldstones = NULL;
7934     for ( ; stone != NULL; stone=next) {
7935 	next = stone->next;
7936 	if (stone->port) {
7937 #ifdef USE_EPOLL
7938 	    epoll_ctl(ePollFd, EPOLL_CTL_DEL, stone->sd, NULL);
7939 #else
7940 	    waitMutex(FdRinMutex);
7941 	    waitMutex(FdEinMutex);
7942 	    FD_CLR(stone->sd, &rin);
7943 	    FD_CLR(stone->sd, &ein);
7944 	    freeMutex(FdEinMutex);
7945 	    freeMutex(FdRinMutex);
7946 #endif
7947 	    closesocket(stone->sd);
7948 	}
7949 #ifdef USE_SSL
7950 	if (stone->ssl_server) rmStoneSSL(stone->ssl_server);
7951 	if (stone->ssl_client) rmStoneSSL(stone->ssl_client);
7952 #endif
7953 	free(stone);
7954     }
7955 }
7956 
rmoldconfig(void)7957 void rmoldconfig(void) {
7958     int i;
7959     for (i=0; i < OldConfigArgc; i++) {
7960 	free(OldConfigArgv[i]);
7961     }
7962     OldConfigArgc = 0;
7963     free(OldConfigArgv);
7964     OldConfigArgv = NULL;
7965 }
7966 
repeater(void)7967 void repeater(void) {
7968     int ret;
7969     static int spin = 0;
7970     static int nerrs = 0;
7971     static time_t scantime = 0;
7972     time_t now;
7973     Pair *pair;
7974 #ifdef USE_EPOLL
7975     int timeout;
7976     struct epoll_event evs[EVSMAX];
7977     for (pair=PairTop; pair != NULL; pair=pair->next)
7978 	if (pair->clock != -1 &&	/* not top */
7979 	    (pair->proto & proto_dirty))
7980 	    proto2fdset(pair);
7981     if (conns.next || trash.next || spin > 0 || AsyncCount > 0) {
7982 	if (AsyncCount == 0 && spin > 0) spin--;
7983 	timeout = TICK_SELECT / 1000;
7984     } else if (MinInterval > 0) {
7985 	timeout = MinInterval * 1000;
7986     } else {
7987 	timeout = -1;
7988     }
7989     ret = epoll_wait(ePollFd, evs, EVSMAX, timeout);
7990     if (Debug > 10) {
7991 	message(LOG_DEBUG, "epoll %d: %d", ePollFd, ret);
7992     }
7993 #else
7994     struct timeval tv, *timeout;
7995     fd_set rout, wout, eout;
7996     rout = rin;
7997     wout = win;
7998     eout = ein;
7999     for (pair=PairTop; pair != NULL; pair=pair->next)
8000 	if (pair->clock != -1 &&	/* not top */
8001 	    !(pair->proto & proto_thread))
8002 	    proto2fdset(0, &rout, &wout, &eout, pair);
8003     if (conns.next || trash.next || spin > 0 || AsyncCount > 0) {
8004 	if (AsyncCount == 0 && spin > 0) spin--;
8005 	timeout = &tv;
8006 	timeout->tv_sec = 0;
8007 	timeout->tv_usec = TICK_SELECT;
8008     } else if (MinInterval > 0) {
8009 	timeout = &tv;
8010 	timeout->tv_sec = MinInterval;
8011 	timeout->tv_usec = 0;
8012     } else {
8013 	timeout = NULL;		/* block indefinitely */
8014     }
8015     if (Debug > 10) {
8016 	message(LOG_DEBUG, "select main(%ld)",
8017 		(timeout ? timeout->tv_usec : 0));
8018 	message_select(LOG_DEBUG, "select main IN ", &rout, &wout, &eout);
8019     }
8020     ret = select(FD_SETSIZE, &rout, &wout, &eout, timeout);
8021     if (Debug > 10) {
8022 	message(LOG_DEBUG, "select main: %d", ret);
8023 	message_select(LOG_DEBUG, "select main OUT", &rout, &wout, &eout);
8024     }
8025 #endif
8026     if (ret > 0) {
8027 	nerrs = 0;
8028 	spin = SPIN_MAX;
8029 #ifdef USE_EPOLL
8030 	dispatch(ePollFd, evs, ret);
8031 #else
8032 	(void)(scanStones(&rout, &wout, &eout) > 0);
8033 #endif
8034     } else if (ret < 0) {
8035 #ifdef WINDOWS
8036 	errno = WSAGetLastError();
8037 #endif
8038 	if (errno != EINTR) {
8039 #ifdef USE_EPOLL
8040 	    message(LOG_ERR, "epoll %d error err=%d", ePollFd, errno);
8041 #else
8042 	    message(LOG_ERR, "select error err=%d", errno);
8043 #endif
8044 	    if (++nerrs >= NERRS_MAX) {
8045 #ifdef USE_EPOLL
8046 		message(LOG_ERR, "epoll %d error %d times, exiting",
8047 			ePollFd, nerrs);
8048 #else
8049 		message(LOG_ERR, "select error %d times, exiting", nerrs);
8050 		message_select(LOG_INFO, "IN", &rin, &win, &ein);
8051 #endif
8052 		message_pairs(LOG_INFO);
8053 		message_origins(LOG_INFO);
8054 		message_conns(LOG_INFO);
8055 		exit(1);
8056 	    }
8057 	}
8058 	usleep(TICK_SELECT);
8059     }
8060     if (conns.next) scanConns();
8061     time(&now);
8062     if (now == scantime) return;
8063     scantime = now;
8064     if (backups && scantime - lastScanBackups >= MinInterval) {
8065 	lastScanBackups = scantime;
8066 	scanBackups();
8067     }
8068 #ifdef USE_EPOLL
8069     if (PairTop) scanPairs(NULL);
8070     if (OriginTop) scanUDP(NULL);
8071 #endif
8072     if (PairTop) scanClose(NULL);
8073     if (oldstones) rmoldstone();
8074     if (OldConfigArgc) rmoldconfig();
8075 #ifdef USE_SSL
8076 #if OPENSSL_VERSION_NUMBER < 0x10100000L
8077     ERR_remove_state(0);
8078 #else
8079 #if OPENSSL_VERSION_NUMBER < 0x10101000L
8080     ERR_remove_thread_state(NULL);
8081 #endif
8082 #endif
8083 #endif
8084 }
8085 
reusestone(Stone * stone)8086 int reusestone(Stone *stone) {
8087     Stone *s;
8088     if (!oldstones) return 0;
8089     for (s=oldstones; s != NULL; s=s->next) {
8090 	if (s->port == stone->port && s->proto == stone->proto) {
8091 	    if (Debug > 5)
8092 		message(LOG_DEBUG, "stone %d: reused port %d", s->sd, s->port);
8093 	    stone->sd = s->sd;
8094 	    s->port = 0;
8095 	    return 1;
8096 	}
8097     }
8098     return 0;
8099 }
8100 
8101 #ifdef NO_FAMILY_T
8102 typedef int sa_family_t;
8103 #endif
8104 
mkXhostsExt(char * host,char * str,XHosts * ext)8105 void mkXhostsExt(char *host, char *str, XHosts *ext) {
8106     int kind = 0;
8107     char *top = NULL;	/* dummy init to suppress warnings */
8108     u_long num = 0;
8109     int i = 0;
8110     do {
8111 	switch(kind) {
8112 	case -3:	/* pass if digit or '.' until ',' */
8113 	    if (str[i] == '.') break;
8114 	case -2:	/* pass if digit until ',' */
8115 	    if (isdigit(str[i])) break;
8116 	case -1:	/* pass ',' */
8117 	    if (str[i] == ',' || str[i] == '\0') {
8118 		kind = 0;	/* found next ext */
8119 		break;
8120 	    }
8121 	error:
8122 	    message(LOG_ERR, "Unknown extension: \"%s\" in %s/%s",
8123 		    &str[i], host, str);
8124 	    exit(1);
8125 	case 0:
8126 	    top = &str[i];
8127 	    if (isdigit(*top)) {
8128 		num = *top - '0';
8129 		kind = 1;
8130 		break;
8131 	    }
8132 	    if (*top == 'v') {
8133 		i++;
8134 		if (top[1] == '4') {
8135 		    ext->xhost.addr.sa_family = AF_INET;
8136 #ifdef AF_INET6
8137 		} else if (top[1] == '6') {
8138 		    ext->xhost.addr.sa_family = AF_INET6;
8139 #endif
8140 		} else {
8141 		    goto error;
8142 		}
8143 		kind = -1;	/* expect ',' or end of string */
8144 		break;
8145 	    }
8146 	    if (*top == 'p') {
8147 		if (isdigit(top[1])) {
8148 		    ext->mode = atoi(top+1);
8149 		} else {
8150 		    ext->mode = 1;
8151 		}
8152 		kind = -2;	/* skip to the next ext */
8153 		break;
8154 	    }
8155 	    goto error;
8156 	case 1:	/* net mask */
8157 	    if (str[i] == ',' || str[i] == '\0') {
8158 		ext->mbits = num;
8159 		if (ext->mbits > 32) {
8160 #ifdef AF_INET6
8161 		    /* force to set IPv6 */
8162 		    ext->xhost.addr.sa_family = AF_INET6;
8163 		}
8164 		if (ext->mbits > 128) {
8165 #endif
8166 		    goto error;
8167 		}
8168 		kind = 0;	/* found next ext */
8169 		break;
8170 	    }
8171 	case 2:	/* nnn.<nnn>.nnn.nnn */
8172 	case 3:	/* nnn.nnn.<nnn>.nnn */
8173 	    if (str[i] == '.') {
8174 		i++;
8175 		num <<= 8;
8176 		kind++;
8177 	    }
8178 	case 4:	/* nnn.nnn.nnn.<nnn> */
8179 	    if (isdigit(str[i])) {
8180 		num = ((num & 0xFFFFFF00)
8181 		       | ((num & 0xFF) * 10 + (str[i] - '0')));
8182 		break;
8183 	    }
8184 	    ext->xhost.addr.sa_family = AF_INET;	/* force to set IPv4 */
8185 	    for (ext->mbits=0; ext->mbits < 32 && num; ext->mbits++) {
8186 		if (!(num & 0x80000000)) {
8187 		    message(LOG_ERR, "netmask by bits pattern "
8188 			    "is deprecated: %s/%s", host, top);
8189 		    exit(1);
8190 		}
8191 		num <<= 1;
8192 	    }
8193 	    i--;	/* unget */
8194 	    kind = -1;	/* expect ',' or end of string */
8195 	    break;
8196 	default:
8197 	    message(LOG_ERR, "Can't happen: kind=%d in mkXhostsExt", kind);
8198 	    exit(1);
8199 	}
8200     } while (str[i++]);
8201     if (Debug > 9) message(LOG_DEBUG, "mkXhostsExt: host=%s ext=%s "
8202 			   "family=%d mbits=%d mode=%d",
8203 			   host, str, ext->xhost.addr.sa_family,
8204 			   ext->mbits, ext->mode);
8205 }
8206 
mkXhosts(int nhosts,char * hosts[],sa_family_t family,char * mesg)8207 XHosts *mkXhosts(int nhosts, char *hosts[], sa_family_t family, char *mesg) {
8208     XHosts *top = NULL;
8209     XHosts *bot = NULL;
8210     char xhost[STRMAX+1];
8211     int allow = 1;
8212     int i;
8213     char *p;
8214     for (i=0; i < nhosts; i++) {
8215 	XHosts *new;
8216 	if (Debug > 10) message(LOG_DEBUG, "xhost[%d]=\"%s\"", i, hosts[i]);
8217 	if (!strcmp(hosts[i], "!")) {
8218 	    new = malloc(XHostsBaseSize);
8219 	    if (!new) goto memerr;
8220 	    new->mbits = -1;
8221 	    allow = !allow;
8222 	} else {
8223 	    short mbits = -1;
8224 	    short mode = 0;
8225 	    struct sockaddr_storage ss;
8226 	    struct sockaddr *sa = (struct sockaddr*)&ss;
8227 	    socklen_t salen = sizeof(ss);
8228 	    strcpy(xhost, hosts[i]);
8229 	    p = strchr(xhost, '/');
8230 	    if (p) {
8231 		XHosts ext;
8232 		*p++ = '\0';
8233 		ext.mbits = mbits;
8234 		ext.mode = mode;
8235 		ext.xhost.addr.sa_family = family;
8236 		mkXhostsExt(xhost, p, &ext);
8237 		mbits = ext.mbits;
8238 		mode = ext.mode;
8239 		family = ext.xhost.addr.sa_family;
8240 	    }
8241 	    sa->sa_family = family;
8242 	    if (host2sa(xhost, NULL, sa, &salen, NULL, NULL, 0)) exit(1);
8243 	    new = malloc(XHostsBaseSize+salen);
8244 	    if (!new) goto memerr;
8245 	    new->xhost.len = salen;
8246 	    bcopy(sa, &new->xhost.addr, salen);
8247 	    if (mbits < 0) {
8248 		if (sa->sa_family == AF_INET) {
8249 		    mbits = 32;
8250 #ifdef AF_INET6
8251 		} else if (sa->sa_family == AF_INET6) {
8252 		    mbits = 128;
8253 #endif
8254 		} else {
8255 		    message(LOG_ERR, "mkXhosts: unknown family=%d",
8256 			    sa->sa_family);
8257 		    exit(1);
8258 		}
8259 	    }
8260 	    new->mbits = mbits;
8261 	    new->mode = mode;
8262 	    if (mesg) {
8263 		char str[STRMAX+1];
8264 		int pos = 0;
8265 		addr2str(&new->xhost.addr, new->xhost.len,
8266 			 str, STRMAX, NI_NUMERICHOST);
8267 		pos = strlen(str);
8268 		snprintf(str+pos, STRMAX-pos, "/%d", new->mbits);
8269 		pos += strlen(str+pos);
8270 		message(LOG_DEBUG, "%s%s is %s", mesg, str,
8271 			(allow ? "permitted" : "denied"));
8272 	    }
8273 	}
8274 	new->next = NULL;
8275 	if (!top) top = new;
8276 	if (bot) bot->next = new;
8277 	bot = new;
8278     }
8279     return top;
8280  memerr:
8281     message(LOG_CRIT, "Out of memory");
8282     exit(1);
8283 }
8284 
mkPortXhosts(int argc,int i,char * argv[])8285 int mkPortXhosts(int argc, int i, char *argv[]) {
8286     PortXHosts *pxh;
8287     XPorts *top = NULL;
8288     XPorts *bot = NULL;
8289     char **hosts;
8290     char *p, *q;
8291     char str[STRMAX+1];
8292     int isnum;
8293     int from;
8294     int j;
8295     i++;
8296     if (!strcmp(argv[i], "--")) {
8297 	portXHosts = NULL;
8298 	return i;
8299     }
8300     p = argv[i];
8301     q = str;
8302     isnum = 1;
8303     from = -1;
8304     for (;;) {
8305 	if (*p == ',' || *p == '-' || *p == '\0') {
8306 	    int port;
8307 	    *q = '\0';
8308 	    if (str[0]) {
8309 		if (isnum) port = atoi(str);
8310 		else {
8311 		    struct sockaddr_storage ss;
8312 		    struct sockaddr *sa = (struct sockaddr*)&ss;
8313 		    socklen_t salen = sizeof(ss);
8314 		    if (host2sa(NULL, str, sa, &salen, NULL, NULL, 0))
8315 			goto opterr;
8316 		    port = getport(sa);
8317 		}
8318 	    } else {
8319 	    opterr:
8320 		message(LOG_ERR, "Illegal option: -x requires port list: %s",
8321 			argv[i]);
8322 		exit(1);
8323 	    }
8324 	    if (*p == '-') {
8325 		from = port;
8326 	    } else {
8327 		XPorts *new = malloc(sizeof(XPorts));
8328 		if (!new) goto memerr;
8329 		new->next = NULL;
8330 		if (from >= 0) new->from = from;
8331 		else new->from = port;
8332 		new->end = port;
8333 		from = -1;
8334 		if (bot) bot->next = new;
8335 		bot = new;
8336 		if (!top) top = new;
8337 		if (*p == '\0') break;
8338 	    }
8339 	    p++;
8340 	    q = str;
8341 	    isnum = 1;
8342 	    continue;
8343 	} else if (!isdigit(*p)) {
8344 	    isnum = 0;
8345 	}
8346 	*q++ = *p++;
8347     }
8348     if (Debug > 5) {
8349 	char buf[BUFMAX];
8350 	XPorts *cur;
8351 	j = 0;
8352 	for (cur=top; j < BUFMAX && cur; cur=cur->next) {
8353 	    if (j > 0) buf[j++] = ',';
8354 	    snprintf(buf+j, BUFMAX-1-j, "%d-%d", cur->from, cur->end);
8355 	    j += strlen(buf+j);
8356 	}
8357 	buf[j] = '\0';
8358 	message(LOG_DEBUG, "XPorts: %s", buf);
8359     }
8360     i++;
8361     hosts = &argv[i];
8362     j = 0;
8363     for (; i < argc; i++, j++) if (!strcmp(argv[i], "--")) break;
8364     pxh = malloc(sizeof(PortXHosts));
8365     if (!pxh) goto memerr;
8366     pxh->ports = top;
8367     if (Debug > 5) p = "XHosts: "; else p = NULL;
8368     pxh->xhosts = mkXhosts(j, hosts, AF_UNSPEC, p);
8369     pxh->next = portXHosts;
8370     portXHosts = pxh;
8371     return i;
8372  memerr:
8373     message(LOG_CRIT, "Out of memory");
8374     exit(1);
8375 }
8376 
getStone(struct sockaddr * sa,socklen_t salen,int proto)8377 Stone *getStone(struct sockaddr *sa, socklen_t salen, int proto) {
8378     Stone *stone;
8379     proto &= proto_udp_s;
8380     (void)salen;
8381     for (stone=stones; stone != NULL; stone=stone->next) {
8382 	if ((stone->proto & proto_udp_s) == proto
8383 	    && saComp(&stone->listen->addr, sa)) {
8384 	    return stone;
8385 	}
8386     }
8387     return NULL;
8388 }
8389 
8390 /* make stone */
mkstone(char * dhost,char * dserv,char * host,char * intf,char * serv,int nhosts,char * hosts[],int proto)8391 Stone *mkstone(
8392     char *dhost,	/* destination hostname */
8393     char *dserv,	/* destination port */
8394     char *host,		/* listening host */
8395     char *intf,		/* listening interface */
8396     char *serv,		/* listening port */
8397     int nhosts,		/* # of hosts to permit */
8398     char *hosts[],	/* hosts to permit */
8399     int proto) {	/* UDP/TCP/SSL */
8400     Stone *stone;
8401     Stone *st;
8402     struct sockaddr_storage ss;
8403     struct sockaddr *sa = (struct sockaddr*)&ss;
8404     socklen_t salen = sizeof(ss);
8405     int satype;
8406     int saproto = 0;
8407     sa_family_t family;
8408     char *mesg;
8409     char str[STRMAX+1];
8410     stone = calloc(1, sizeof(Stone));
8411     if (!stone) {
8412 	message(LOG_CRIT, "Out of memory");
8413 	exit(1);
8414     }
8415     stone->next = NULL;
8416     stone->children = NULL;
8417     stone->parent = NULL;
8418     stone->common = type_stone;
8419     stone->p = NULL;
8420     stone->timeout = PairTimeOut;
8421     stone->proto = proto;
8422     if (proto & proto_udp_s) {
8423 	satype = SOCK_DGRAM;
8424 	saproto = IPPROTO_UDP;
8425     } else {
8426 	satype = SOCK_STREAM;
8427 	saproto = IPPROTO_TCP;
8428     }
8429 #ifdef AF_LOCAL
8430     if (proto & proto_unix_s) {
8431 	struct sockaddr_un *sun = (struct sockaddr_un*)sa;
8432 	salen = sizeof(struct sockaddr_un);
8433 	bzero(sa, salen);
8434 	sun->sun_family = AF_LOCAL;
8435 	snprintf(sun->sun_path, sizeof(sun->sun_path)-1, "%s", host);
8436 	saproto = 0;
8437     } else
8438 #endif
8439 #ifdef AF_INET6
8440     if (proto & proto_v6_s) {
8441 	struct sockaddr_in6 *sin6p = (struct sockaddr_in6*)sa;
8442 	sa->sa_family = AF_INET6;
8443 	if (host2sa(host, serv, sa, &salen, &satype, &saproto, AI_PASSIVE))
8444 	    exit(1);
8445 	stone->port = ntohs(sin6p->sin6_port);
8446     } else
8447 #endif
8448     {
8449 	struct sockaddr_in *sinp = (struct sockaddr_in*)sa;
8450 	sa->sa_family = AF_INET;
8451 	if (host2sa(host, serv, sa, &salen, &satype, &saproto, AI_PASSIVE))
8452 	    exit(1);
8453 	stone->port = ntohs(sinp->sin_port);
8454     }
8455     if ((proto & proto_command) == command_proxy
8456 	|| (proto & proto_command) == command_health
8457 	|| (proto & proto_command) == command_identd) {
8458 	stone->ndsts = 1;
8459 	if ((proto & proto_command) == command_proxy) {
8460 	    stone->dsts = malloc(sizeof(SockAddr*) + sizeof(PortXHosts*));
8461 	    if (stone->dsts) ((PortXHosts**)stone->dsts)[1] = portXHosts;
8462 	    /* only proxy stone needs portXHosts,
8463 	       so we divert dsts into holding current portXHosts */
8464 	} else {
8465 	    stone->dsts = malloc(sizeof(SockAddr*));	/* dummy */
8466 	}
8467 	if (!stone->dsts) {
8468 	    message(LOG_CRIT, "Out of memory");
8469 	    exit(1);
8470 	}
8471 	stone->dsts[0] = saDup(sa, salen);	/* dummy */
8472 #ifdef AF_LOCAL
8473     } else if (proto & proto_unix_d) {
8474 	struct sockaddr_storage dss;
8475 	struct sockaddr_un *sun = (struct sockaddr_un*)&dss;
8476 	stone->ndsts = 1;
8477 	stone->dsts = malloc(sizeof(SockAddr*));
8478 	if (!stone->dsts) {
8479 	memerr:
8480 	    message(LOG_CRIT, "Out of memory");
8481 	    exit(1);
8482 	}
8483 	bzero(sun, sizeof(dss));
8484 	sun->sun_family = AF_LOCAL;
8485 	snprintf(sun->sun_path, sizeof(sun->sun_path)-1, "%s", dhost);
8486 	stone->dsts[0] = saDup((struct sockaddr*)sun,
8487 				sizeof(struct sockaddr_un));
8488 	if (!stone->dsts[0]) goto memerr;
8489 #endif
8490     } else {
8491 	stone->ndsts = 0;
8492 	stone->dsts = NULL;
8493 	stone_dsts(stone, dhost, dserv);
8494     }
8495     stone->from = ConnectFrom;
8496     if (!reusestone(stone)) {	/* recycle stone */
8497 	stone->sd = socket(sa->sa_family, satype, saproto);
8498 	if (InvalidSocket(stone->sd)) {
8499 #ifdef WINDOWS
8500 	    errno = WSAGetLastError();
8501 #endif
8502 	    message(LOG_ERR, "stone %d: Can't get socket "
8503 		    "family=%d type=%d proto=%d err=%d",
8504 		    stone->sd, sa->sa_family, satype, saproto, errno);
8505 	    exit(1);
8506 	}
8507 #ifdef IPV6_V6ONLY
8508 	if ((proto & proto_v6_s) && (proto & proto_ip_only_s)) {
8509 	    int i = 1;
8510 	    setsockopt(stone->sd, IPPROTO_IPV6, IPV6_V6ONLY,
8511 		       (char*)&i, sizeof(i));
8512 	}
8513 #endif
8514 	if (!(proto & proto_udp_s) && ReuseAddr) {
8515 	    int i = 1;
8516 	    setsockopt(stone->sd, SOL_SOCKET, SO_REUSEADDR,
8517 		       (char*)&i, sizeof(i));
8518 	}
8519 #ifdef SO_BINDTODEVICE
8520 	if (intf) {
8521 	    if (setsockopt(stone->sd, SOL_SOCKET, SO_BINDTODEVICE,
8522 			   intf, strlen(intf)) < 0) {
8523 #ifdef WINDOWS
8524 		errno = WSAGetLastError();
8525 #endif
8526 		message(LOG_ERR, "stone %d: Can't set sockopt "
8527 			"BINDTODEVICE %s err=%d", stone->sd,
8528 			intf, errno);
8529 		exit(1);
8530 	    }
8531 	}
8532 #endif
8533 #ifdef USE_TPROXY
8534 	{
8535 	    int i = 1;
8536 	    if (setsockopt(stone->sd, SOL_IP, IP_TRANSPARENT,
8537 			   (char*)&i, sizeof(i)) < 0) {
8538 #ifdef WINDOWS
8539 		errno = WSAGetLastError();
8540 #endif
8541 		message(LOG_ERR, "stone %d: Can't set sockopt "
8542 			"IP_TRANSPARENT %d err=%d", stone->sd,
8543 			i, errno);
8544 		exit(1);
8545 	    }
8546 	}
8547 #endif
8548 	if ((st=getStone(sa, salen, proto))) {
8549 	    closesocket(stone->sd);
8550 	    stone->parent = st;
8551 	    stone->children = st->children;
8552 	    st->children = stone;
8553 	    stone->sd = st->sd;
8554 	} else if (!DryRun) {
8555 	    if (bind(stone->sd, sa, salen) < 0) {
8556 		char str[STRMAX+1];
8557 #ifdef WINDOWS
8558 		errno = WSAGetLastError();
8559 #endif
8560 		addrport2str(sa, salen, 0, str, STRMAX, 0);
8561 		str[STRMAX] = '\0';
8562 		message(LOG_ERR, "stone %d: Can't bind %s err=%d",
8563 			stone->sd, str, errno);
8564 		exit(1);
8565 	    }
8566 	    if (!(stone->proto & proto_block_s)) {
8567 #ifdef WINDOWS
8568 		u_long param;
8569 		param = 1;
8570 		ioctlsocket(stone->sd, FIONBIO, &param);
8571 #else
8572 		fcntl(stone->sd, F_SETFL, O_NONBLOCK);
8573 #endif
8574 	    }
8575 	    if (stone->port == 0) {
8576 		salen = sizeof(ss);
8577 		if (getsockname(stone->sd, sa, &salen) >= 0) {
8578 		    stone->port = getport(sa);
8579 		}
8580 	    }
8581 	    if (!(proto & proto_udp_s)) {	/* TCP */
8582 		if (listen(stone->sd, BacklogMax) < 0) {
8583 #ifdef WINDOWS
8584 		    errno = WSAGetLastError();
8585 #endif
8586 		    message(LOG_ERR, "stone %d: Can't listen err=%d",
8587 			    stone->sd, errno);
8588 		    exit(1);
8589 		}
8590 	    }
8591 	}	/* !DryRun */
8592     }
8593     stone->listen = saDup(sa, salen);
8594 #ifdef USE_SSL
8595     if (proto & proto_ssl_s) {	/* server side SSL */
8596 	exPatOpts(&ServerOpts, host, dhost);
8597 	stone->ssl_server = mkStoneSSL(&ServerOpts, 1);
8598 	if (stone->ssl_server->lbmod) {
8599 	    if (stone->ssl_server->lbmod > stone->ndsts) {
8600 		message(LOG_WARNING, "LB set (%d) < lbmod (%d)",
8601 			stone->ndsts, stone->ssl_server->lbmod);
8602 		stone->ssl_server->lbmod = stone->ndsts;
8603 	    }
8604 	}
8605     } else {
8606 	stone->ssl_server = NULL;
8607     }
8608     if ((proto & proto_ssl_d)	/* client side SSL */
8609 	|| (proto & proto_command) == command_proxy) {
8610 	exPatOpts(&ClientOpts, host, dhost);
8611 	stone->ssl_client = mkStoneSSL(&ClientOpts, 0);
8612 	if (!(stone->ssl_client->name && *stone->ssl_client->name))
8613 	    stone->ssl_client->name = dhost;
8614     } else {
8615 	stone->ssl_client = NULL;
8616     }
8617 #endif
8618     mesg = NULL;
8619     if (Debug > 1) {
8620 	mesg = str;
8621 	if ((proto & proto_command) == command_proxy) {
8622 	    snprintf(mesg, STRMAX, "stone %d: using proxy by ",
8623 		     (int)stone->sd);
8624 	} else if ((proto & proto_command) == command_health) {
8625 	    snprintf(mesg, STRMAX, "stone %d: health check by ",
8626 		     (int)stone->sd);
8627 	} else if ((proto & proto_command) == command_identd) {
8628 	    snprintf(mesg, STRMAX, "stone %d: ident query by ",
8629 		     (int)stone->sd);
8630 	} else {
8631 	    char addrport[STRMAX+1];
8632 	    if (stone->ndsts > 0) {
8633 		addrport2str(&stone->dsts[0]->addr, stone->dsts[0]->len,
8634 			     (stone->proto & proto_stone_d),
8635 			     addrport, STRMAX, 0);
8636 		addrport[STRMAX] = '\0';
8637 	    } else {
8638 		snprintf(addrport, STRMAX, "(%s:%s)",
8639 			 (char*)stone->dsts[0], (char*)stone->dsts[1]);
8640 	    }
8641 	    snprintf(mesg, STRMAX, "stone %d: connecting to %s by ",
8642 		     (int)stone->sd, addrport);
8643 	}
8644     }
8645     family = AF_INET;
8646 #ifdef AF_INET6
8647     if (stone->proto & proto_v6_s) {
8648 	if (host == NULL && !(stone->proto & proto_ip_only_s)) {
8649 	    family = AF_UNSPEC;
8650 	} else {
8651 	    family = AF_INET6;
8652 	}
8653     }
8654 #endif
8655     stone->xhosts = mkXhosts(nhosts, hosts, family, mesg);
8656     message(LOG_INFO, "%s", stone2str(stone, str, STRMAX));
8657     stone->backups = NULL;
8658     if ((proto & proto_command) != command_proxy
8659 	&& (proto & proto_command) != command_health
8660 	&& (proto & proto_command) != command_identd
8661 	&& (proto & proto_nobackup) == 0) {
8662 	Backup *bs[LB_MAX];
8663 	int found = 0;
8664 	int i;
8665 	for (i=0; i < stone->ndsts; i++) {
8666 	    bs[i] = findBackup(&stone->dsts[i]->addr);
8667 	    if (bs[i]) {
8668 		found = 1;
8669 		bs[i]->used = 1;
8670 	    }
8671 	}
8672 	if (found) {
8673 	    stone->backups = malloc(sizeof(Backup*) * stone->ndsts);
8674 	    if (stone->backups) {
8675 		for (i=0; i < stone->ndsts; i++) stone->backups[i] = bs[i];
8676 	    }
8677 	}
8678     }
8679     return stone;
8680 }
8681 
8682 /* main */
8683 
help(char * com,char * sub)8684 void help(char *com, char *sub) {
8685     message(LOG_INFO, "stone %s  http://www.gcd.org/sengoku/stone/", VERSION);
8686     message(LOG_INFO, "%s",
8687 	    "Copyright(C)2007 by Hiroaki Sengoku <sengoku@gcd.org>");
8688 #ifdef USE_SSL
8689     message(LOG_INFO, "using %s http://www.openssl.org/", SSLeay_version(SSLEAY_VERSION));
8690 #ifdef CRYPTOAPI
8691     message(LOG_INFO, "%s",
8692 	    "using cryptoapi.c by Peter 'Luna' Runestig <peter@runestig.com>");
8693 #endif
8694 #endif
8695     if (!sub) {
8696     help:
8697 	fprintf(stderr,
8698 		"Usage: %s <opt>... <stone> [-- <stone>]...\n"
8699 		"opt:  -h opt            ; help for <opt> more\n"
8700 		"      -h stone          ; help for <stone>\n"
8701 #ifdef USE_SSL
8702 		"      -h ssl            ; help for <SSL>, see -q/-z opt\n"
8703 #endif
8704 		, com);
8705 	return;
8706     }
8707     if (!strcmp(sub, "opt")) {
8708 	fprintf(stderr, "Usage: %s <opt>... <stone> [-- <stone>]...\n"
8709 "opt:  -C <file>         ; configuration file\n"
8710 #ifdef CPP
8711 "      -P <command>      ; preprocessor for config. file\n"
8712 "      -Q <options>      ; options for preprocessor\n"
8713 #endif
8714 "      -N                ; configuration check only\n"
8715 "      -d                ; increase debug level\n"
8716 "      -p                ; packet dump\n"
8717 "      -n                ; numerical address\n"
8718 "      -u <max>          ; # of UDP sessions\n"
8719 #ifndef NO_FORK
8720 "      -f <n>            ; # of child processes\n"
8721 #endif
8722 #if !defined(NO_SYSLOG) || defined(ANDROID)
8723 "      -l                ; use syslog\n"
8724 "      -ll               ; run under daemontools\n"
8725 #endif
8726 "      -L <file>         ; write log to <file>\n"
8727 "      -a <file>         ; write accounting to <file>\n"
8728 "      -i <file>         ; write process ID to <file>\n"
8729 "      -X <n>            ; size [byte] of Xfer buffer\n"
8730 "      -T <n>            ; timeout [sec] of TCP sessions\n"
8731 "      -A <n>            ; length of backlog\n"
8732 "      -r                ; reuse socket\n"
8733 "      -x <port>[,<port>][-<port>]... <xhost> --\n"
8734 "                        ; permit connecting to <xhost>:<port>\n"
8735 "      -s <send> <expect>... --\n"
8736 "                        ; health check script\n"
8737 "      -b <n> <master>:<port> <backup>:<port>\n"
8738 "                        ; check <master>:<port> every <n> sec\n"
8739 "                        ; use <backup>:<port>, if check failed\n"
8740 "      -B <host>:<port>... --\n"
8741 "                        ; load balancing hosts\n"
8742 #ifdef ADDRCACHE
8743 "      -H <size>         ; cache addresses used in proxy\n"
8744 #endif
8745 "      -I <host>[:<port>]; local end of its connections to\n"
8746 #ifndef NO_SETUID
8747 "      -o <uid>          ; set uid to <uid>\n"
8748 "      -g <gid>          ; set gid to <gid>\n"
8749 #endif
8750 #ifndef NO_CHROOT
8751 "      -t <dir>          ; chroot to <dir>\n"
8752 #endif
8753 #ifdef UNIX_DAEMON
8754 "      -D                ; become UNIX Daemon\n"
8755 #endif
8756 "      -c <dir>          ; core dump to <dir>\n"
8757 #ifdef USE_SSL
8758 "      -q <SSL>          ; SSL client option\n"
8759 "      -z <SSL>          ; SSL server option\n"
8760 "                        ; `-h ssl' for <SSL>\n"
8761 #endif
8762 #ifdef NT_SERVICE
8763 "      -M install <name> ; install service as <name>\n"
8764 "      -M remove <name>  ; remove service <name>\n"
8765 #endif
8766 		, com);
8767     } else if (!strcmp(sub, "stone")) {
8768 	fprintf(stderr, "Usage: %s <opt>... <stone> [-- <stone>]...\n"
8769 		"stone: <host>:<port> <sport> [<xhost>...]\n"
8770 		"       proxy"
8771 #ifdef AF_INET6
8772 		"[/[v4only | v6only]]"
8773 #endif
8774 		" <sport> [<xhost>...]\n"
8775 		"       health <sport> [<xhost>...]\n"
8776 		"       identd <sport> [<xhost>...]\n"
8777 		"       <host>:<port#>/http <sport> "
8778 		"<Request-Line> [<xhost>...]\n"
8779 		"       <host>:<port#>/proxy <sport> <header> [<xhost>...]\n"
8780 		"       <host>:<port#>/mproxy <sport> <header> [<xhost>...]\n"
8781 		"port:  <port#>[/<ext>[,<ext>]...]\n"
8782 		"ext:   tcp | udp"
8783 #ifdef USE_SSL
8784 		" | ssl"
8785 #endif
8786 #ifdef AF_INET6
8787 		" | v6"
8788 #endif
8789 #ifdef USE_POP
8790 		" | apop"
8791 #endif
8792 		" | base | block | nobackup\n"
8793 		"sport: [[<host>][%%<intf>]:]<port#>[/<exts>[,<exts>]...]\n"
8794 		"exts:  tcp | udp"
8795 #ifdef USE_SSL
8796 		" | ssl"
8797 #endif
8798 #ifdef AF_INET6
8799 		" | v6 | v6only"
8800 #endif
8801 		" | http | base | block | ident\n"
8802 		"xhost: <host>[/<ex>[,<ex>]...]\n"
8803 		"ex:    <#bits> | p<mode#>"
8804 #ifdef AF_INET6
8805 		" | v6"
8806 #endif
8807 		"\n"
8808 		, com);
8809 #ifdef USE_SSL
8810     } else if (!strcmp(sub, "ssl")) {
8811 	fprintf(stderr,
8812 "opt:  -q <SSL>            ; SSL client option\n"
8813 "      -z <SSL>            ; SSL server option\n"
8814 "SSL:   default            ; reset to default\n"
8815 "       verbose            ; verbose mode\n"
8816 "       verify             ; require peer's certificate\n"
8817 "       verify,once        ; verify client's certificate only once\n"
8818 "       verify,ifany       ; verify client's certificate if any\n"
8819 "       verify,none        ; don't require peer's certificate\n"
8820 "       crl_check          ; lookup CRLs\n"
8821 "       crl_check_all      ; lookup CRLs for whole chain\n"
8822 "       uniq               ; check serial # of peer's certificate\n"
8823 "       re<n>=<regex>      ; verify depth <n> with <regex>\n"
8824 "       depth=<n>          ; set verification depth to <n>\n"
8825 #ifndef OPENSSL_NO_TLS1
8826 "       tls1               ; just use TLSv1\n"
8827 #endif
8828 #ifndef OPENSSL_NO_TLS1_2
8829 "       tls1.2             ; just use TLSv1.2\n"
8830 #endif
8831 #ifndef OPENSSL_NO_TLS1_1
8832 "       tls1.1             ; just use TLSv1.1\n"
8833 #endif
8834 #ifndef OPENSSL_NO_SSL3
8835 "       ssl3               ; just use SSLv3\n"
8836 #endif
8837 #ifndef OPENSSL_NO_SSL2
8838 "       ssl2               ; just use SSLv2\n"
8839 #endif
8840 #ifndef OPENSSL_NO_TLS1
8841 "       no_tls1            ; turn off TLSv1\n"
8842 #endif
8843 #ifndef OPENSSL_NO_TLS1_2
8844 "       no_tls1.2          ; turn off TLSv1.2\n"
8845 #endif
8846 #ifndef OPENSSL_NO_TLS1_1
8847 "       no_tls1.1          ; turn off TLSv1.1\n"
8848 #endif
8849 #ifndef OPENSSL_NO_SSL3
8850 "       no_ssl3            ; turn off SSLv3\n"
8851 #endif
8852 #ifndef OPENSSL_NO_SSL2
8853 "       no_ssl2            ; turn off SSLv2\n"
8854 #endif
8855 #ifndef OPENSSL_NO_TLSEXT
8856 "       sni                ; Server Name Indication\n"
8857 "       servername=<str>   ; Server Name\n"
8858 #endif
8859 "       bugs               ; SSL implementation bug workarounds\n"
8860 #ifdef SSL_OP_CIPHER_SERVER_PREFERENCE
8861 "       serverpref         ; use server's cipher preferences\n"
8862 #endif
8863 "       shutdown=<mode>    ; accurate, nowait, unclean\n"
8864 "       sid_ctx=<str>      ; set session ID context\n"
8865 "       passfile=<file>    ; password file\n"
8866 "       passfilepat=<file> ; password file pattern\n"
8867 "       key=<file>         ; key file\n"
8868 "       keypat=<file>      ; key file pattern\n"
8869 "       cert=<file>        ; certificate file\n"
8870 "       certpat=<file>     ; certificate file pattern\n"
8871 "       certkey=<file>     ; certificate & key file\n"
8872 "       certkeypat=<file>  ; certificate & key file pattern\n"
8873 "       CAfile=<file>      ; certificate file of CA\n"
8874 "       CApath=<dir>       ; dir of CAs\n"
8875 "       pfx=<file>         ; PKCS#12 file\n"
8876 "       pfxpat=<file>      ; PKCS#12 file pattern\n"
8877 #ifdef CRYPTOAPI
8878 "       store=<prop>       ; \"SUBJ:<substr>\" or \"THUMB:<hex>\"\n"
8879 "       storeCA            ; use CA cert in Windows cert store\n"
8880 #endif
8881 #ifdef ANDROID
8882 "       store=<key>        ; keystore\n"
8883 #endif
8884 "       cipher=<ciphers>   ; list of ciphers\n"
8885 "       lb<n>=<m>          ; load balancing based on CN\n"
8886 	    );
8887 #endif
8888     } else {
8889 	goto help;
8890     }
8891 }
8892 
skipcomment(FILE * fp)8893 static void skipcomment(FILE *fp) {
8894     int c;
8895     while ((c=getc(fp)) != EOF && c != '\r' && c != '\n')	;
8896     while ((c=getc(fp)) != EOF && (c == '\r' || c == '\n'))	;
8897     if (c != EOF) ungetc(c, fp);
8898 }
8899 
getvar(FILE * fp,char * buf,int bufmax)8900 static int getvar(FILE *fp, char *buf, int bufmax) {
8901     char var[STRMAX+1];
8902     char *val;
8903     int i = 0;
8904     int paren = 0;
8905     int c = getc(fp);
8906     if (c == EOF) {
8907 	return 0;
8908     } else if (c == '{') {
8909 	paren = 1;
8910     } else {
8911 	ungetc(c, fp);
8912     }
8913     while ((c=getc(fp)) != EOF && i < STRMAX) {
8914 	if (paren && c == '}') {
8915 	    break;
8916 	} else if (isalnum(c) || c == '_') {
8917 	    var[i++] = c;
8918 	} else {
8919 	    ungetc(c, fp);
8920 	    break;
8921 	}
8922     }
8923     var[i] = '\0';
8924     if (*var == '\0') return 0;
8925     val = getenv(var);
8926     if (val == NULL) return 0;
8927     i = strlen(val);
8928     if (i > bufmax) i = bufmax;
8929     strncpy(buf, val, i);
8930     return i;
8931 }
8932 
gettoken(FILE * fp,char * buf)8933 static int gettoken(FILE *fp, char *buf) {
8934     int i = 0;
8935     int quote = 0;
8936     int c;
8937     for (;;) {
8938 	c = getc(fp);
8939 	if (c == EOF) return -1;
8940 	if (c == '#') {
8941 	    skipcomment(fp);
8942 	    continue;
8943 	}
8944 	if (!isspace(c)) {
8945 	    ungetc(c, fp);
8946 	    break;
8947 	}
8948     }
8949     while (i < BUFMAX-1) {
8950 	c = getc(fp);
8951 	if (c == EOF) {
8952 	    if (i > 0) break;
8953 	    return -1;
8954 	}
8955 	if (quote != '\'') {
8956 	    if (c == '$') {
8957 		i += getvar(fp, &buf[i], BUFMAX-1-i);
8958 		continue;
8959 	    }
8960 	    if (c == '\\') {	/* escape a char */
8961 		c = getc(fp);
8962 		if (c == EOF) break;
8963 		switch(c) {
8964 		case 'n':  c = '\n';  break;
8965 		case 'r':  c = '\r';  break;
8966 		case 't':  c = '\t';  break;
8967 		}
8968 	    }
8969 	}
8970 	if (quote) {
8971 	    if (c == quote) {
8972 		quote = 0;
8973 		continue;
8974 	    }
8975 	} else if (c == '\'' || c == '\"') {
8976 	    quote = c;
8977 	    continue;
8978 	} else if (isspace(c)) {
8979 	    c = getc(fp);
8980 	    if (c != ':' && c != '=') {
8981 		ungetc(c, fp);
8982 		break;
8983 	    }
8984 	} else if (c == '#') {
8985 	    skipcomment(fp);
8986 	    continue;
8987 	}
8988 	buf[i++] = c;
8989     }
8990     buf[i] = '\0';
8991     return i;
8992 }
8993 
openconfig(void)8994 FILE *openconfig(void) {
8995 #ifdef CPP
8996     int pfd[2];
8997     char host[MAXHOSTNAMELEN];
8998     if (CppCommand != NULL && *CppCommand != '\0') {
8999 	if (gethostname(host, MAXHOSTNAMELEN-1) < 0) {
9000 	    message(LOG_ERR, "gethostname err=%d", errno);
9001 	    exit(1);
9002 	}
9003 	if (pipe(pfd) < 0) {
9004 	    message(LOG_ERR, "Can't get pipe err=%d", errno);
9005 	    exit(1);
9006 	}
9007 	if (!fork()) {
9008 	    char *argv[BUFMAX/2];
9009 	    int i = 0;
9010 	    char buf[BUFMAX];
9011 	    int len = 0;
9012 	    char *p;
9013 	    if (CppOptions) {
9014 		snprintf(buf, BUFMAX-1, "%s %s", CppCommand, CppOptions);
9015 	    } else {
9016 		strncpy(buf, CppCommand, BUFMAX-1);
9017 	    }
9018 	    argv[i] = "cpp";
9019 	    while (buf[len]) {
9020 		if (isspace(buf[len])) {
9021 		    buf[len++] = '\0';
9022 		    while (buf[len] && isspace(buf[len])) len++;
9023 		    if (buf[len]) argv[++i] = &buf[len];
9024 		    else break;
9025 		}
9026 		len++;
9027 	    }
9028 	    len++;
9029 	    argv[++i] = buf + len;
9030 	    snprintf(argv[i], BUFMAX-len, "-DHOST=%s", host);
9031 	    len += strlen(argv[i]) + 1;
9032 	    argv[++i] = buf + len;
9033 	    for (p=host; *p; p++) if (*p == '.') *p = '_';
9034 	    snprintf(argv[i], BUFMAX-len, "-DHOST_%s", host);
9035 	    len += strlen(argv[i]) + 1;
9036 	    if (getenv("HOME")) {
9037 		argv[++i] = buf + len;
9038 		snprintf(argv[i], BUFMAX-len, "-DHOME=%s", getenv("HOME"));
9039 		len += strlen(argv[i]) + 1;
9040 	    }
9041 	    argv[++i] = ConfigFile;
9042 	    argv[++i] = NULL;
9043 	    close(pfd[0]);
9044 	    close(1);
9045 	    dup(pfd[1]);
9046 	    close(pfd[1]);
9047 	    if (Debug > 9) {
9048 		char str[BUFMAX];
9049 		snprintf(str, BUFMAX, "%s: ", buf);
9050 		for (i=0; argv[i]; i++) {
9051 		    len = strlen(str);
9052 		    snprintf(&str[len], BUFMAX-len, " %s", argv[i]);
9053 		}
9054 		message(LOG_DEBUG, "%s", str);
9055 	    }
9056 	    execv(buf, argv);
9057 	}
9058 	close(pfd[1]);
9059 	return fdopen(pfd[0], "r");
9060     } else
9061 #endif
9062 	return fopen(ConfigFile, "r");
9063 }
9064 
getconfig(void)9065 void getconfig(void) {
9066     FILE *fp;
9067     int nptr = 0;
9068     char **new;
9069     char buf[BUFMAX];
9070     int len;
9071     if (ConfigFile == NULL) return;
9072     ConfigArgc = 0;
9073     ConfigArgv = NULL;
9074     fp = openconfig();
9075     if (fp == NULL) {
9076 	message(LOG_ERR, "Can't open config file: %s err=%d",
9077 		ConfigFile, errno);
9078 	exit(1);
9079     }
9080     strcpy(buf, ConfigFile);
9081     len = strlen(buf);
9082     do {
9083 	if (Debug > 9) message(LOG_DEBUG, "token: \"%s\"", buf);
9084 	if (ConfigArgc >= nptr) {	/* allocate new ptrs */
9085 	    new = malloc((nptr+BUFMAX)*sizeof(*ConfigArgv));
9086 	    if (new == NULL) {
9087 		message(LOG_CRIT, "Out of memory");
9088 		exit(1);
9089 	    }
9090 	    if (ConfigArgv) {
9091 		bcopy(ConfigArgv, new, nptr*sizeof(*ConfigArgv));
9092 		free(ConfigArgv);
9093 	    }
9094 	    ConfigArgv = new;
9095 	    nptr += BUFMAX;
9096 	}
9097 	ConfigArgv[ConfigArgc] = malloc(len+1);
9098 	bcopy(buf, ConfigArgv[ConfigArgc], len+1);
9099 	ConfigArgc++;
9100     } while ((len=gettoken(fp, buf)) >= 0);
9101     fclose(fp);
9102 #ifdef CPP
9103     if (CppCommand != NULL && *CppCommand != '\0') {
9104 	wait(NULL);
9105     }
9106 #endif
9107 }
9108 
getdist(char * p,int * protop)9109 int getdist(	/* return pos where serv begins */
9110     char *p,
9111     int *protop) {
9112     char *port_str, *proto_str, *top;
9113     top = p;
9114     port_str = proto_str = NULL;
9115     *protop = 0;	/* default */
9116 #ifdef AF_LOCAL
9117     if (p[0] == '.' || p[0] == '/') {
9118 	struct stat st;
9119 	p++;
9120 	while (*p) {
9121 	    if (*p == '/') proto_str = ++p;
9122 	    else p++;
9123 	}
9124 	if (proto_str) {
9125 	    *(proto_str-1) = '\0';
9126 	    if (stat(top, &st) >=0 && S_ISDIR(st.st_mode)) {
9127 		*(proto_str-1) = '/';	/* restore */
9128 		proto_str = NULL;
9129 	    }
9130 	}
9131 	*protop |= proto_unix;
9132     } else
9133 #endif
9134     while (*p) {
9135 	if (*p == ':') port_str = ++p;
9136 	else if (*p == '/') proto_str = ++p;
9137 	else p++;
9138     }
9139     if (proto_str) {
9140 	*(proto_str-1) = '\0';
9141 	p = proto_str;
9142 	do {
9143 	    if (!strncmp(p, "tcp", 3)) {
9144 		p += 3;
9145 		*protop &= ~proto_udp;
9146 	    } else if (!strncmp(p, "udp", 3)) {
9147 		p += 3;
9148 		*protop |= proto_udp;
9149 	    } else if (!strncmp(p, "http", 4)) {
9150 		p += 4;
9151 		*protop |= proto_ohttp;
9152 	    } else if (!strncmp(p, "base", 4)) {
9153 		p += 4;
9154 		*protop |= proto_base;
9155 	    } else if (!strncmp(p, "ident", 5)) {
9156 		p += 5;
9157 		*protop |= proto_ident;
9158 	    } else if (!strncmp(p, "proxy", 5)) {
9159 		p += 5;
9160 		*protop &= ~proto_command;
9161 		*protop |= command_ihead;
9162 	    } else if (!strncmp(p, "mproxy", 6)) {
9163 		p += 6;
9164 		*protop &= ~proto_command;
9165 		*protop |= command_iheads;
9166 	    } else if (!strncmp(p, "nobackup", 8)) {
9167 		p += 8;
9168 		*protop |= proto_nobackup;
9169 #ifdef USE_SSL
9170 	    } else if (!strncmp(p, "ssl", 3)) {
9171 		p += 3;
9172 		*protop |= proto_ssl;
9173 #endif
9174 #ifdef AF_INET6
9175 	    } else if (!strncmp(p, "v6", 2)) {
9176 		p += 2;
9177 		*protop |= proto_v6;
9178 		if (!strncmp(p, "only", 4)) {
9179 		    p += 4;
9180 		    *protop |= proto_ip_only;
9181 		}
9182 #endif
9183 	    } else if (!strncmp(p, "v4only", 6)) {
9184 		p += 6;
9185 		*protop |= proto_ip_only;
9186 	    } else if (!strncmp(p, "block", 5)) {
9187 		p += 5;
9188 		*protop |= proto_block;
9189 #ifdef USE_POP
9190 	    } else if (!strncmp(p, "apop", 4)) {
9191 		p += 4;
9192 		*protop &= ~proto_command;
9193 		*protop |= command_pop;
9194 #endif
9195 	    } else return -1;	/* error */
9196 	} while ((*p == ',' || *p == '/') && p++);
9197     }
9198     if (port_str) {
9199 	*(port_str-1) = '\0';
9200 	return port_str - top;	/* host & serv */
9201     } else {
9202 #ifdef AF_LOCAL
9203 	if (*protop & proto_unix) {
9204 	    return 1;
9205 	}
9206 #endif
9207 	if (!strcmp(top, "proxy")) {
9208 	    *protop &= ~proto_command;
9209 	    *protop |= command_proxy;
9210 	    return 1;	/* host only */
9211 	}
9212 	if (!strcmp(top, "health")) {
9213 	    *protop &= ~proto_command;
9214 	    *protop |= command_health;
9215 	    return 1;	/* host only */
9216 	}
9217 	if (!strcmp(top, "identd")) {
9218 	    *protop &= ~proto_command;
9219 	    *protop |= command_identd;
9220 	    return 1;	/* host only */
9221 	}
9222 	return 0;	/* serv only */
9223     }
9224 }
9225 
9226 #ifdef USE_SSL
sslopts_default(SSLOpts * opts,int isserver)9227 void sslopts_default(SSLOpts *opts, int isserver) {
9228     int i;
9229     opts->verbose = 0;
9230     opts->shutdown_mode = 0;
9231     opts->mode = SSL_VERIFY_NONE;
9232     opts->depth = DEPTH_MAX - 1;
9233     opts->vflags = 0;
9234     opts->off = 0;
9235     opts->serial = -2;
9236     opts->callback = verify_callback;
9237     opts->sid_ctx = NULL;
9238     opts->useSNI = 0;
9239     if (isserver) {
9240 	char path[BUFMAX];
9241 	snprintf(path, BUFMAX-1, "%s/stone.pem", X509_get_default_cert_dir());
9242 	opts->keyFile = opts->certFile = strdup(path);
9243 	opts->keyFilePat = opts->certFilePat = NULL;
9244 	opts->meth = SSLv23_server_method();
9245 	opts->off = (0
9246 #ifdef OPENSSL_NO_SSL2
9247 		     | SSL_OP_NO_SSLv2
9248 #endif
9249 #ifdef OPENSSL_NO_SSL3
9250 		     | SSL_OP_NO_SSLv3
9251 #endif
9252 #ifdef OPENSSL_NO_TLS1
9253 		     | SSL_OP_NO_TLSv1
9254 #endif
9255 #ifdef OPENSSL_NO_TLS1_2
9256 		     | SSL_OP_NO_TLSv1_2
9257 #endif
9258 #ifdef OPENSSL_NO_TLS1_1
9259 		     | SSL_OP_NO_TLSv1_1
9260 #endif
9261 	    );
9262     } else {
9263 	opts->keyFile = opts->certFile = NULL;
9264 	opts->keyFilePat = opts->certFilePat = NULL;
9265 	opts->meth = SSLv23_client_method();
9266 	opts->off = (0
9267 #ifdef OPENSSL_NO_SSL2
9268 		     | SSL_OP_NO_SSLv2
9269 #endif
9270 #ifdef OPENSSL_NO_SSL3
9271 		     | SSL_OP_NO_SSLv3
9272 #endif
9273 #ifdef OPENSSL_NO_TLS1
9274 		     | SSL_OP_NO_TLSv1
9275 #endif
9276 #ifdef OPENSSL_NO_TLS1_2
9277 		     | SSL_OP_NO_TLSv1_2
9278 #endif
9279 #ifdef OPENSSL_NO_TLS1_1
9280 		     | SSL_OP_NO_TLSv1_1
9281 #endif
9282 	    );
9283     }
9284     opts->caFile = opts->caPath = NULL;
9285     opts->pfxFile = NULL;
9286     opts->pfxFilePat = NULL;
9287     opts->passFile = NULL;
9288     opts->passFilePat = NULL;
9289     opts->passwd = NULL;
9290     opts->servername = NULL;
9291     opts->certIgnore = 0;
9292 #ifdef CRYPTOAPI
9293     opts->certStoreCA = 0;
9294     opts->certStore = NULL;
9295 #endif
9296 #ifdef ANDROID
9297     opts->certStore = NULL;
9298 #endif
9299     opts->cipherList = getenv("SSL_CIPHER");
9300     for (i=0; i < DEPTH_MAX; i++) opts->regexp[i] = NULL;
9301     opts->lbmod = 0;
9302     opts->lbparm = 0xFF;
9303     opts->shutdown_mode = 0;
9304 }
9305 
sslopts(int argc,int argi,char * argv[],SSLOpts * opts,int isserver)9306 int sslopts(int argc, int argi, char *argv[], SSLOpts *opts, int isserver) {
9307     (void)argc;
9308     if (!strcmp(argv[argi], "default")) {
9309 	sslopts_default(opts, isserver);
9310     } else if (!strcmp(argv[argi], "verbose")) {
9311 	opts->verbose++;
9312     } else if (!strncmp(argv[argi], "shutdown=", 9)) {
9313 	if (!strcmp(argv[argi]+9, "nowait")) {
9314 	    opts->shutdown_mode = SSL_RECEIVED_SHUTDOWN;
9315 	} else if (!strcmp(argv[argi]+9, "accurate")) {
9316 	    opts->shutdown_mode = 0;
9317 	} else if (!strcmp(argv[argi]+9, "unclean")) {
9318 	    opts->shutdown_mode = (SSL_SENT_SHUTDOWN | SSL_RECEIVED_SHUTDOWN);
9319 	}
9320     } else if (!strncmp(argv[argi], "verify", 6)
9321 	       && (argv[argi][6] == '\0' || argv[argi][6] == ',')) {
9322 	if (!strcmp(argv[argi]+6, ",none")) {
9323 	    opts->mode = SSL_VERIFY_NONE;
9324 	} else if (isserver) {
9325 	    opts->mode = (SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT);
9326 	    if (argv[argi][6] == ',') {
9327 		if (!strcmp(argv[argi]+7, "ifany")) {
9328 		    opts->mode = (SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE);
9329 		} else if (!strcmp(argv[argi]+7, "once")) {
9330 		    opts->mode |= SSL_VERIFY_CLIENT_ONCE;
9331 		}
9332 	    }
9333 	} else if (argv[argi][6] == '\0') {
9334 	    opts->mode = SSL_VERIFY_PEER;
9335 	} else {
9336 	    goto error;
9337 	}
9338     } else if (!strncmp(argv[argi], "crl_check", 9)) {
9339 	opts->vflags |= X509_V_FLAG_CRL_CHECK;
9340     } else if (!strncmp(argv[argi], "crl_check_all", 13)) {
9341 	opts->vflags |= (X509_V_FLAG_CRL_CHECK
9342 			 | X509_V_FLAG_CRL_CHECK_ALL);
9343     } else if (!strncmp(argv[argi], "re", 2) && isdigit(argv[argi][2])
9344 	       && argv[argi][3] == '=') {
9345 	int depth = atoi(argv[argi]+2);
9346 	if (0 <= depth && depth < DEPTH_MAX) {
9347 	    opts->regexp[depth] = strdup(argv[argi]+4);
9348 	} else {
9349 	    goto error;
9350 	}
9351     } else if (!strncmp(argv[argi], "re-", 3) && isdigit(argv[argi][3])
9352 	       && argv[argi][4] == '=') {
9353 	int depth = atoi(argv[argi]+3);
9354 	if (0 < depth && depth <= DEPTH_MAX) {
9355 	    opts->regexp[DEPTH_MAX-depth] = strdup(argv[argi]+5);
9356 	} else {
9357 	    goto error;
9358 	}
9359     } else if (!strncmp(argv[argi], "depth=", 6)) {
9360 	opts->depth = atoi(argv[argi]+6);
9361 	if (opts->depth >= DEPTH_MAX) opts->depth = DEPTH_MAX - 1;
9362 	else if (opts->depth < 0) opts->depth = 0;
9363     } else if (!strcmp(argv[argi], "bugs")) {
9364 	opts->off |= SSL_OP_ALL;
9365 #ifndef OPENSSL_NO_TLS1
9366     } else if (!strcmp(argv[argi], "tls1")) {
9367 	if (isserver) opts->meth = TLSv1_server_method();
9368 	else opts->meth = TLSv1_client_method();
9369 #endif
9370 #ifndef OPENSSL_NO_TLS1_2
9371     } else if (!strcmp(argv[argi], "tls1.2")) {
9372 	if (isserver) opts->meth = TLSv1_2_server_method();
9373 	else opts->meth = TLSv1_2_client_method();
9374 #endif
9375 #ifndef OPENSSL_NO_TLS1_1
9376     } else if (!strcmp(argv[argi], "tls1.1")) {
9377 	if (isserver) opts->meth = TLSv1_1_server_method();
9378 	else opts->meth = TLSv1_1_client_method();
9379 #endif
9380 #ifndef OPENSSL_NO_SSL3
9381     } else if (!strcmp(argv[argi], "ssl3")) {
9382 	if (isserver) opts->meth = SSLv3_server_method();
9383 	else opts->meth = SSLv3_client_method();
9384 #endif
9385 #if !defined(OPENSSL_NO_SSL2) && OPENSSL_VERSION_NUMBER < 0x10100000L
9386     } else if (!strcmp(argv[argi], "ssl2")) {
9387 	if (isserver) opts->meth = SSLv2_server_method();
9388 	else opts->meth = SSLv2_client_method();
9389 #endif
9390 #ifndef OPENSSL_NO_TLS1
9391     } else if (!strcmp(argv[argi], "no_tls1")) {
9392 	opts->off |= SSL_OP_NO_TLSv1;
9393 #endif
9394 #ifndef OPENSSL_NO_TLS1_2
9395     } else if (!strcmp(argv[argi], "no_tls1.2")) {
9396 	opts->off |= SSL_OP_NO_TLSv1_2;
9397 #endif
9398 #ifndef OPENSSL_NO_TLS1_1
9399     } else if (!strcmp(argv[argi], "no_tls1.1")) {
9400 	opts->off |= SSL_OP_NO_TLSv1_1;
9401 #endif
9402 #ifndef OPENSSL_NO_SSL3
9403     } else if (!strcmp(argv[argi], "no_ssl3")) {
9404 	opts->off |= SSL_OP_NO_SSLv3;
9405 #endif
9406 #ifndef OPENSSL_NO_SSL2
9407     } else if (!strcmp(argv[argi], "no_ssl2")) {
9408 	opts->off |= SSL_OP_NO_SSLv2;
9409 #endif
9410 #ifdef SSL_OP_CIPHER_SERVER_PREFERENCE
9411     } else if (!strcmp(argv[argi], "serverpref")) {
9412 	opts->off |= SSL_OP_CIPHER_SERVER_PREFERENCE;
9413 #endif
9414     } else if (!strcmp(argv[argi], "uniq")) {
9415 	opts->serial = -1;
9416     } else if (!strncmp(argv[argi], "sid_ctx=", 8)) {
9417 	opts->sid_ctx = (unsigned char*)strdup(argv[argi]+8);
9418     } else if (!strcmp(argv[argi], "sni")) {
9419 	opts->useSNI = 1;
9420     } else if (!strncmp(argv[argi], "servername=", 11)) {
9421 	opts->servername = strdup(argv[argi]+11);
9422     } else if (!strncmp(argv[argi], "key=", 4)) {
9423 	opts->keyFile = strdup(argv[argi]+4);
9424 	opts->keyFilePat = NULL;
9425 	opts->pfxFile = NULL;
9426     } else if (!strncmp(argv[argi], "keypat=", 7)) {
9427 	opts->keyFilePat = strdup(argv[argi]+7);
9428 	opts->pfxFile = NULL;
9429     } else if (!strncmp(argv[argi], "cert=", 5)) {
9430 	opts->certFile = strdup(argv[argi]+5);
9431 	opts->certFilePat = NULL;
9432 	opts->pfxFile = NULL;
9433     } else if (!strncmp(argv[argi], "certpat=", 8)) {
9434 	opts->certFilePat = strdup(argv[argi]+8);
9435 	opts->pfxFile = NULL;
9436     } else if (!strncmp(argv[argi], "certkey=", 8)) {
9437 	opts->keyFile = opts->certFile = strdup(argv[argi]+8);
9438 	opts->keyFilePat = opts->certFilePat = NULL;
9439 	opts->pfxFile = NULL;
9440     } else if (!strncmp(argv[argi], "certkeypat=", 11)) {
9441 	opts->keyFilePat = opts->certFilePat = strdup(argv[argi]+11);
9442 	opts->pfxFile = NULL;
9443     } else if (!strncmp(argv[argi], "CAfile=", 7)) {
9444 	opts->caFile = strdup(argv[argi]+7);
9445     } else if (!strncmp(argv[argi], "CApath=", 7)) {
9446 	opts->caPath = strdup(argv[argi]+7);
9447     } else if (!strncmp(argv[argi], "pfx=", 4)) {
9448 	opts->pfxFile = strdup(argv[argi]+4);
9449 	opts->pfxFilePat = NULL;
9450 	opts->keyFile = opts->certFile = NULL;
9451 	opts->keyFilePat = opts->certFilePat = NULL;
9452     } else if (!strncmp(argv[argi], "pfxpat=", 7)) {
9453 	opts->pfxFilePat = strdup(argv[argi]+7);
9454 	opts->keyFile = opts->certFile = NULL;
9455 	opts->keyFilePat = opts->certFilePat = NULL;
9456     } else if (!strncmp(argv[argi], "passfile=", 9)) {
9457 	opts->passFile = strdup(argv[argi]+9);
9458 	opts->passFilePat = NULL;
9459     } else if (!strncmp(argv[argi], "passfilepat=", 12)) {
9460 	opts->passFilePat = strdup(argv[argi]+12);
9461 	opts->passFile = NULL;
9462     } else if (!strncmp(argv[argi], "ignore", 6)) {
9463 	opts->certIgnore = 1;
9464 #ifdef CRYPTOAPI
9465     } else if (!strncmp(argv[argi], "storeCA", 7)) {
9466 	opts->certStoreCA = 1;
9467     } else if (!strncmp(argv[argi], "store=", 6)) {
9468 	opts->certStore = strdup(argv[argi]+6);
9469 #endif
9470 #ifdef ANDROID
9471     } else if (!strncmp(argv[argi], "store=", 6)) {
9472 	opts->certStore = strdup(argv[argi]+6);
9473 #endif
9474     } else if (!strncmp(argv[argi], "cipher=", 7)) {
9475 	opts->cipherList = strdup(argv[argi]+7);
9476     } else if (!strncmp(argv[argi], "lb", 2) && isdigit(argv[argi][2])
9477 	       && argv[argi][3] == '=') {
9478 	opts->lbparm = argv[argi][2] - '0';
9479 	opts->lbmod = atoi(argv[argi]+4);
9480     } else {
9481     error:
9482 	message(LOG_ERR, "Invalid SSL Option: %s", argv[argi]);
9483 	help(argv[0], "ssl");
9484 	exit(1);
9485     }
9486     return argi;
9487 }
9488 
9489 #ifndef NO_THREAD
9490 /* SSL callback */
sslthread_id_callback(void)9491 unsigned long sslthread_id_callback(void) {
9492     unsigned long ret;
9493 #ifdef WINDOWS
9494     ret = (unsigned long)GetCurrentThreadId();
9495 #else
9496 #ifdef PTHREAD
9497     ret = (unsigned long)pthread_self();
9498 #endif
9499 #endif
9500     if (Debug > 19) message(LOG_DEBUG, "SSL_thread id=%ld", ret);
9501     return ret;
9502 }
9503 
sslthread_lock_callback(int mode,int n,const char * file,int line)9504 void sslthread_lock_callback(int mode, int n, const char *file, int line) {
9505     if (mode & CRYPTO_LOCK) {
9506 	if (Debug > 19)
9507 	    message(LOG_DEBUG, "SSL_lock mode=%x n=%d file=%s line=%d",
9508 		    mode, n, file, line);
9509 #ifdef WINDOWS
9510 	WaitForSingleObject(SSLMutex[n], 500);
9511 #else
9512 #ifdef PTHREAD
9513 	pthread_mutex_lock(&SSLMutex[n]);
9514 #endif
9515 #endif
9516     } else {
9517 	if (Debug > 19)
9518 	    message(LOG_DEBUG, "SSL_unlock mode=%x n=%d file=%s line=%d",
9519 		    mode, n, file, line);
9520 #ifdef WINDOWS
9521 	ReleaseMutex(SSLMutex[n]);
9522 #else
9523 #ifdef PTHREAD
9524 	pthread_mutex_unlock(&SSLMutex[n]);
9525 #endif
9526 #endif
9527     }
9528 }
9529 
sslthread_initialize(void)9530 int sslthread_initialize(void) {
9531     int i;
9532     NSSLMutexs = CRYPTO_num_locks();
9533     SSLMutex = malloc(NSSLMutexs * sizeof(*SSLMutex));
9534     if (!SSLMutex) return -1;
9535     if (Debug > 1) message(LOG_DEBUG, "SSL thread nlocks=%d", NSSLMutexs);
9536     for (i=0; i < NSSLMutexs; i++) {
9537 #ifdef WINDOWS
9538 	SSLMutex[i] = CreateMutex(NULL, FALSE, NULL);
9539 	if (!SSLMutex[i]) return -1;
9540 #else
9541 #ifdef PTHREAD
9542 	pthread_mutex_init(&SSLMutex[i], NULL);
9543 #endif
9544 #endif
9545     }
9546 #if defined(WINDOWS) || defined(PTHREAD)
9547     CRYPTO_set_id_callback(sslthread_id_callback);
9548     CRYPTO_set_locking_callback(sslthread_lock_callback);
9549     return 1;
9550 #else
9551     return 0;
9552 #endif
9553 }
9554 #endif
9555 #endif
9556 
dohyphen(char opt,int argc,char * argv[],int argi)9557 int dohyphen(char opt, int argc, char *argv[], int argi) {
9558     switch(opt) {
9559     case 'd':
9560 	Debug++;
9561 	break;
9562     case 'p':
9563 	XHostsTrue->mode = ((XHostsTrue->mode & ~XHostsMode_Dump)
9564 			    | (((XHostsTrue->mode & XHostsMode_Dump) + 1)
9565 			       & XHostsMode_Dump));
9566 	break;
9567 #if !defined(NO_SYSLOG) || defined(ANDROID)
9568     case 'l':
9569 	Syslog++;
9570 	break;
9571 #endif
9572     case 'L':
9573 	if (++argi >= argc) {
9574 	    message(LOG_ERR, "option -%c requires log <file>", opt);
9575 	    exit(1);
9576 	}
9577 	if (DryRun) break;
9578 	if (!strcmp(argv[argi], "-")) {
9579 	    LogFp = stdout;
9580 	} else {
9581 	    if (LogFp && LogFp != stderr) fclose(LogFp);
9582 	    LogFp = fopen(argv[argi], "a");
9583 	    if (LogFp == NULL) {
9584 		LogFp = stderr;
9585 		message(LOG_ERR, "Can't create log file: %s err=%d",
9586 			argv[argi], errno);
9587 		exit(1);
9588 	    }
9589 	    LogFileName = strdup(argv[argi]);
9590 	}
9591 	setbuf(LogFp, NULL);
9592 	break;
9593     case 'a':
9594 	if (++argi >= argc) {
9595 	    message(LOG_ERR, "option -%c requires accounting <file>", opt);
9596 	    exit(1);
9597 	}
9598 	if (DryRun) break;
9599 	if (!strcmp(argv[argi], "-")) {
9600 	    AccFp = stdout;
9601 	} else {
9602 	    if (AccFp && AccFp != stdout) fclose(AccFp);
9603 	    AccFp = fopen(argv[argi], "a");
9604 	    if (AccFp == NULL) {
9605 		message(LOG_ERR,
9606 			"Can't create account log file: %s err=%d",
9607 			argv[argi], errno);
9608 		exit(1);
9609 	    }
9610 	    AccFileName = strdup(argv[argi]);
9611 	}
9612 	setbuf(AccFp, NULL);
9613 	break;
9614     case 'i':
9615 	if (++argi >= argc) {
9616 	    message(LOG_ERR, "option -%c requires pid <file>", opt);
9617 	    exit(1);
9618 	}
9619 	PidFile = strdup(argv[argi]);
9620 	break;
9621 #ifndef NO_CHROOT
9622     case 't':
9623 	if (++argi >= argc) {
9624 	    message(LOG_ERR, "option -%c requires <dir>", opt);
9625 	    exit(1);
9626 	}
9627 	RootDir = strdup(argv[argi]);
9628 	break;
9629 #endif
9630     case 'n':
9631 	AddrFlag = 1;
9632 	break;
9633     case 'u':
9634 	if (++argi >= argc) {
9635 	    message(LOG_ERR, "option -%c requires # of <max> UDP sessions",
9636 		    opt);
9637 	    exit(1);
9638 	}
9639 	OriginMax = atoi(argv[argi]);
9640 	break;
9641     case 'X':
9642 	if (++argi >= argc) {
9643 	    message(LOG_ERR, "option -%c requires size of Xfer buffer <n>",
9644 		    opt);
9645 	    exit(1);
9646 	}
9647 	XferBufMax = atoi(argv[argi]);
9648 	break;
9649     case 'T':
9650 	if (++argi >= argc) {
9651 	    message(LOG_ERR, "option -%c requires timeout <n>", opt);
9652 	    exit(1);
9653 	}
9654 	PairTimeOut = atoi(argv[argi]);
9655 	break;
9656     case 'A':
9657 	if (++argi >= argc) {
9658 	    message(LOG_ERR, "option -%c requires length of backlog <n>", opt);
9659 	    exit(1);
9660 	}
9661 	BacklogMax = atoi(argv[argi]);
9662 	break;
9663 #ifndef NO_SETUID
9664     case 'o':
9665 	if (++argi >= argc) {
9666 	    message(LOG_ERR, "option -%c requires <uid>", opt);
9667 	    exit(1);
9668 	}
9669 	if (isdigitstr(argv[argi])) {
9670 	    SetUID = atoi(argv[argi]);
9671 	} else {
9672 #ifdef THREAD_UNSAFE
9673 	    struct passwd *passwd = getpwnam(argv[argi]);
9674 	    if (passwd) {
9675 		SetUID = passwd->pw_uid;
9676 	    }
9677 #else
9678 	    struct passwd pwbuf;
9679 	    char sbuf[STRMAX+1];
9680 	    struct passwd *passwd;
9681 	    int ret = getpwnam_r(argv[argi], &pwbuf, sbuf, STRMAX, &passwd);
9682 	    if (ret == 0) {
9683 		SetUID = passwd->pw_uid;
9684 	    }
9685 #endif
9686 	    else {
9687 		message(LOG_ERR, "option -%c requires valid <uid>: %s",
9688 			opt, argv[argi]);
9689 		exit(1);
9690 	    }
9691 	}
9692 	break;
9693     case 'g':
9694 	if (++argi >= argc) {
9695 	    message(LOG_ERR, "option -%c requires <gid>", opt);
9696 	    exit(1);
9697 	}
9698 	if (isdigitstr(argv[argi])) {
9699 	    SetGID = atoi(argv[argi]);
9700 	} else {
9701 #ifdef THREAD_UNSAFE
9702 	    struct group *group = getgrnam(argv[argi]);
9703 	    if (group) {
9704 		SetGID = group->gr_gid;
9705 	    }
9706 #else
9707 	    struct group grbuf;
9708 	    char gbuf[STRMAX+1];
9709 	    struct group *group;
9710 	    int ret = getgrnam_r(argv[argi], &grbuf, gbuf, STRMAX, &group);
9711 	    if (ret == 0) {
9712 		SetGID = group->gr_gid;
9713 	    }
9714 #endif
9715 	    else {
9716 		message(LOG_ERR, "option -%c requires valid <gid>: %s",
9717 			opt, argv[argi]);
9718 		exit(1);
9719 	    }
9720 	}
9721 	break;
9722 #endif
9723     case 'c':
9724 	if (++argi >= argc) {
9725 	    message(LOG_ERR, "option -%c requires <dir> for core dump", opt);
9726 	    exit(1);
9727 	}
9728 	CoreDumpDir = strdup(argv[argi]);
9729 	break;
9730 #ifndef NO_FORK
9731     case 'f':
9732 	if (++argi >= argc) {
9733 	    message(LOG_ERR, "option -%c requires # of child processes <n>",
9734 		    opt);
9735 	    exit(1);
9736 	}
9737 	NForks = atoi(argv[argi]);
9738 	break;
9739 #endif
9740 #ifdef UNIX_DAEMON
9741     case 'D':
9742 	DaemonMode = 1;
9743 	break;
9744 #endif
9745     case 'r':
9746 	ReuseAddr = 1;
9747 	break;
9748     case 'x':
9749 	argi = mkPortXhosts(argc, argi, argv);
9750 	break;
9751     case 's':
9752 	argi = mkChat(argc, argi, argv);
9753 	break;
9754     case 'b':
9755 	argi = mkBackup(argc, argi, argv);
9756 	break;
9757     case 'B':
9758 	argi = lbsopts(argc, argi, argv);
9759 	break;
9760 #ifdef ADDRCACHE
9761     case 'H':
9762 	if (++argi >= argc) {
9763 	    message(LOG_ERR, "option -%c requires addr cache size <n>", opt);
9764 	    exit(1);
9765 	}
9766 	AddrCacheSize = atoi(argv[argi]);
9767 	break;
9768 #endif
9769     case 'I':
9770 	if (++argi >= argc) {
9771 	    message(LOG_ERR, "option -%c requires local interface <host>",
9772 		    opt);
9773 	    exit(1);
9774 	}
9775 	if (!argv[argi] || argv[argi][0] == '\0') {
9776 	    ConnectFrom = NULL;
9777 	} else {
9778 	    char host[STRMAX+1];
9779 	    char port[STRMAX+1];
9780 	    struct sockaddr_storage ss;
9781 	    struct sockaddr *sa = (struct sockaddr*)&ss;
9782 	    socklen_t salen = sizeof(ss);
9783 	    int pos = hostPortExt(argv[argi], host, port);
9784 	    if (pos < 0) {
9785 		sa->sa_family = AF_UNSPEC;
9786 		if (host2sa(argv[argi], NULL, sa, &salen, NULL, NULL, 0))
9787 		    return -1;
9788 	    } else {
9789 		sa->sa_family = AF_UNSPEC;
9790 #ifdef AF_INET6
9791 		if (pos && !strcmp(argv[argi]+pos, "v6"))
9792 		    sa->sa_family = AF_INET6;
9793 #endif
9794 		if (host2sa(host, port, sa, &salen, NULL, NULL, 0))
9795 		    return -1;
9796 	    }
9797 	    ConnectFrom = saDup(sa, salen);
9798 	    if (!ConnectFrom) {
9799 		message(LOG_CRIT, "Out of memory");
9800 		exit(1);
9801 	    }
9802 	}
9803 	break;
9804 #ifdef USE_SSL
9805     case 'q':
9806 	if (++argi >= argc) {
9807 	    message(LOG_ERR, "Illegal Option: -q without <SSL>");
9808 	    exit(1);
9809 	}
9810 	argi = sslopts(argc, argi, argv, &ClientOpts, 0);
9811 	break;
9812     case 'z':
9813 	if (++argi >= argc) {
9814 	    message(LOG_ERR, "Illegal Option: -z without <SSL>");
9815 	    exit(1);
9816 	}
9817 	argi = sslopts(argc, argi, argv, &ServerOpts, 1);
9818 	break;
9819 #endif
9820 #ifdef CPP
9821     case 'P':
9822 	if (++argi >= argc) {
9823 	    message(LOG_ERR, "option -%c requires preprocessor <command>",
9824 		    opt);
9825 	    exit(1);
9826 	}
9827 	CppCommand = strdup(argv[argi]);
9828 	break;
9829     case 'Q':
9830 	if (++argi >= argc) {
9831 	    message(LOG_ERR, "option -%c requires <options> for preprocessor",
9832 		    opt);
9833 	    exit(1);
9834 	}
9835 	CppOptions = strdup(argv[argi]);
9836 	break;
9837 #endif
9838     default:
9839 	return -1;
9840     }
9841     return argi;
9842 }
9843 
9844 #ifdef NT_SERVICE
quoteToken(char * dst,char * src)9845 int quoteToken(char *dst, char *src) {
9846     char buf[STRMAX+1];
9847     int len;
9848     if (strchr(src, ' ')) {
9849 	snprintf(buf, STRMAX, "\"%s\"", src);
9850 	len = strlen(buf);
9851 	if (dst) strncpy(dst, buf, len);
9852     } else {
9853 	len = strlen(src);
9854 	if (dst) strncpy(dst, src, len);
9855     }
9856     return len;
9857 }
9858 
installService(int argc,char * argv[])9859 void installService(int argc, char *argv[]) {
9860     SC_HANDLE scManager;
9861     SC_HANDLE scService;
9862     char exeName[STRMAX+1];
9863     char *command;
9864     int commax, len;
9865     int i;
9866     int state;
9867     char *p;
9868     if (!GetModuleFileName(0, exeName, sizeof(exeName))) {
9869 	message(LOG_ERR, "Can't determine exe name err=%d",
9870 		(int)GetLastError());
9871 	exit(1);
9872     }
9873     scManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
9874     if (!scManager) {
9875 	message(LOG_ERR, "Can't open service control manager err=%d",
9876 		(int)GetLastError());
9877 	exit(1);
9878     }
9879     len = strlen(exeName);
9880     for (i=1; i < argc; i++) {
9881 	len += 1 + quoteToken(NULL, argv[i]);
9882     }
9883     commax = len;
9884     len++;	/* for '\0' */
9885     command = malloc(len);
9886     if (!command) {
9887 	message(LOG_CRIT, "Out of memory");
9888 	exit(1);
9889     }
9890     strcpy(command, exeName);
9891     len = strlen(command);
9892     state = 0;
9893     for (i=1; i < argc; i++) {
9894 	p = argv[i];
9895 	switch(state) {
9896 	case 0:
9897 	    if (!strcmp(p, "-M")) state++;
9898 	    break;
9899 	case 1:
9900 	    if (!strcmp(p, "install"))
9901 		p = "run_svc";	/* assume same length */
9902 	    break;
9903 	}
9904 	command[len++] = ' ';
9905 	len += quoteToken(command+len, p);
9906     }
9907     command[len] = '\0';
9908     if (Debug > 1) message(LOG_DEBUG, "install: %s", command);
9909     scService
9910 	= CreateService(scManager, NTServiceName,
9911 			NTServiceDisplayName,
9912 			SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS,
9913 			SERVICE_DEMAND_START, SERVICE_ERROR_NORMAL,
9914 			command, NULL, NULL, "TcpIp\0\0",
9915 			NULL, NULL);
9916     if (!scService) {
9917 	message(LOG_ERR, "Can't install service: %s err=%d",
9918 		NTServiceName, (int)GetLastError());
9919 	CloseServiceHandle(scManager);
9920 	exit(1);
9921     }
9922     message(LOG_INFO, "service installed: %s", NTServiceName);
9923     CloseServiceHandle(scService);
9924     CloseServiceHandle(scManager);
9925 }
9926 
removeService(void)9927 void removeService(void) {
9928     SC_HANDLE scManager;
9929     SC_HANDLE scService;
9930     scManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
9931     if (!scManager) {
9932 	message(LOG_ERR, "Can't open service control manager err=%d",
9933 		(int)GetLastError());
9934 	exit(1);
9935     }
9936     scService = OpenService(scManager, NTServiceName,
9937 			    SERVICE_ALL_ACCESS);
9938     if (!scService) {
9939 	message(LOG_ERR, "Can't open service: %s err=%d",
9940 		NTServiceName, (int)GetLastError());
9941 	CloseServiceHandle(scManager);
9942 	exit(1);
9943     }
9944     if (ControlService(scService, SERVICE_CONTROL_STOP, &NTServiceStatus)) {
9945 	do {
9946 	    usleep(1000);
9947 	} while (QueryServiceStatus(scService, &NTServiceStatus),
9948 		 NTServiceStatus.dwCurrentState == SERVICE_STOP_PENDING);
9949 	if (NTServiceStatus.dwCurrentState == SERVICE_STOPPED) {
9950 	    message(LOG_INFO, "%s stopped", NTServiceName);
9951 	} else {
9952 	    message(LOG_ERR, "failed to stop %s", NTServiceName);
9953 	}
9954     }
9955     if (!DeleteService(scService)) {
9956 	message(LOG_ERR, "failed to remove service: %s err=%d",
9957 		NTServiceName, (int)GetLastError());
9958 	CloseServiceHandle(scService);
9959 	CloseServiceHandle(scManager);
9960 	exit(1);
9961     }
9962     CloseServiceHandle(scService);
9963     CloseServiceHandle(scManager);
9964     message(LOG_INFO, "service removed: %s", NTServiceName);
9965 }
9966 
addEventSource(char * name)9967 void addEventSource(char *name) {
9968     HKEY hk;
9969     char key[LONGSTRMAX+1];
9970     char exeName[STRMAX+1];
9971     DWORD data;
9972     snprintf(key, LONGSTRMAX, "SYSTEM\\CurrentControlSet\\Services\\EventLog\\Application\\%s", name);
9973     if (RegCreateKey(HKEY_LOCAL_MACHINE, key, &hk)) return;
9974     if (!GetModuleFileName(0, exeName, sizeof(exeName))) return;
9975     if (RegSetValueEx(hk, "EventMessageFile", 0, REG_EXPAND_SZ,
9976 		      (BYTE*)exeName, strlen(exeName)+1)) return;
9977     data = (EVENTLOG_ERROR_TYPE | EVENTLOG_WARNING_TYPE |
9978 	    EVENTLOG_INFORMATION_TYPE);
9979     if (RegSetValueEx(hk, "TypesSupported", 0, REG_DWORD,
9980 		      (LPBYTE)&data, sizeof(DWORD))) return;
9981     RegCloseKey(hk);
9982 }
9983 #endif
9984 
doopts(int argc,char * argv[])9985 int doopts(int argc, char *argv[]) {
9986     int i;
9987     char *p;
9988     for (i=1; i < argc; i++) {
9989 	p = argv[i];
9990 	if (*p == '-') {
9991 	    p++;
9992 	    while(*p) {
9993 		int ret = dohyphen(*p, argc, argv, i);
9994 		if (ret >= 0) {
9995 		    i = ret;
9996 		} else switch(*p) {
9997 		case '-':	/* end of global options */
9998 		    return i+1;
9999 		case 'h':
10000 		    help(argv[0], argv[i+1]);
10001 		    exit(1);
10002 		    break;
10003 		case 'N':
10004 		    DryRun = 1;
10005 		    break;
10006 #ifdef NT_SERVICE
10007 		case 'M':
10008 		    i++;
10009 		    if (i+1 >= argc) {
10010 			message(LOG_ERR, "Illegal Option: -M without args");
10011 			exit(1);
10012 		    }
10013 		    NTServiceName = strdup(argv[i+1]);
10014 		    NTServiceDisplayName
10015 			= malloc(strlen(NTServiceName)
10016 				 + strlen(NTServiceDisplayPrefix) + 1);
10017 		    if (!NTServiceDisplayName) {
10018 			message(LOG_CRIT, "Out of memory");
10019 			exit(1);
10020 		    }
10021 		    strcpy(NTServiceDisplayName, NTServiceDisplayPrefix);
10022 		    strcat(NTServiceDisplayName, NTServiceName);
10023 		    if (!strcmp(argv[i], "install")) {
10024 			installService(argc, argv);
10025 			exit(0);
10026 		    } else if (!strcmp(argv[i], "remove")) {
10027 			removeService();
10028 			exit(0);
10029 		    } else if (!strcmp(argv[i], "run_svc")) {
10030 			addEventSource(NTServiceName);
10031 			NTServiceLog
10032 			    = RegisterEventSource(NULL, NTServiceName);
10033 		    } else {
10034 			message(LOG_ERR, "Illegal Option: -M %s %s",
10035 				argv[i], argv[i+1]);
10036 			exit(1);
10037 		    }
10038 		    i++;
10039 		    break;
10040 #endif
10041 		case 'C':
10042 		    if (!ConfigFile) {
10043 			i++;
10044 			ConfigFile = malloc(strlen(argv[i]) + 1);
10045 			if (ConfigFile == NULL) {
10046 			    message(LOG_CRIT, "Out of memory");
10047 			    exit(1);
10048 			}
10049 			strcpy(ConfigFile, argv[i]);
10050 			break;
10051 		    }	/* drop through */
10052 		default:
10053 		    message(LOG_ERR, "Invalid Option: %s", argv[i]);
10054 		    help(argv[0], "opt");
10055 		    exit(1);
10056 		}
10057 		p++;
10058 	    }
10059 	} else break;
10060     }
10061     return i;
10062 }
10063 
doargs(int argc,int i,char * argv[])10064 void doargs(int argc, int i, char *argv[]) {
10065     Stone *stone;
10066     char *host, *shost;
10067     char *sintf = NULL;
10068     char *serv, *sserv;
10069     int proto, sproto, dproto;
10070     char *p;
10071     int j, k;
10072     proto = sproto = dproto = 0;	/* default: TCP */
10073     if (argc - i < 1) {
10074 	help(argv[0], NULL);
10075 	exit(1);
10076     }
10077     for (; i < argc; i++) {
10078 	p = argv[i];
10079 	if (*p == '-') {
10080 	    p++;
10081 	    while(*p) {
10082 		int ret = dohyphen(*p, argc, argv, i);
10083 		if (ret >= 0) {
10084 		    i = ret;
10085 		} else {
10086 		    message(LOG_ERR, "Invalid Option: %s", argv[i]);
10087 		    help(argv[0], "opt");
10088 		    exit(1);
10089 		}
10090 		p++;
10091 	    }
10092 	    continue;
10093 	}
10094 	host = strdup(argv[i]);
10095 	j = getdist(host, &dproto);
10096 	if (j > 0) {	/* with hostname */
10097 	    i++;
10098 	    if (j > 1) serv = host + j; else serv = NULL;
10099 	    if (argc <= i) {
10100 		help(argv[0], NULL);
10101 		exit(1);
10102 	    }
10103 	    shost = strdup(argv[i]);
10104 	    j = getdist(shost, &sproto);
10105 	    if (j > 0) {
10106 		if (j > 1) sserv = shost + j; else sserv = NULL;
10107 		for (p=shost; *p; p++) {
10108 		    if (*p == '%') {	/* with interface */
10109 			*p = '\0';
10110 			sintf = p+1;
10111 			break;
10112 		    }
10113 		}
10114 		if (!*shost) shost = NULL;
10115 	    } else if (j == 0) {
10116 		sserv = shost;
10117 		shost = NULL;
10118 	    } else {
10119 		message(LOG_ERR, "Invalid <sport>: %s", argv[i]);
10120 		exit(1);
10121 	    }
10122 	} else {
10123 	    message(LOG_ERR, "Invalid <host>:<port>: %s", argv[i]);
10124 	    exit(1);
10125 	}
10126 	i++;
10127 	j = 0;
10128 	k = i;
10129 	for (; i < argc; i++, j++) if (!strcmp(argv[i], "--")) break;
10130 	if ((sproto & proto_udp)) {
10131 	    proto |= proto_udp_s;
10132 	    if (sproto & proto_v6) proto |= proto_v6_s;
10133 	    if (sproto & proto_ip_only) proto |= proto_ip_only_s;
10134 	} else {
10135 	    if (sproto & proto_ohttp) proto |= proto_ohttp_s;
10136 	    if (sproto & proto_ssl) proto |= proto_ssl_s;
10137 	    if (sproto & proto_v6) proto |= proto_v6_s;
10138 	    if (sproto & proto_ip_only) proto |= proto_ip_only_s;
10139 	    if (sproto & proto_unix) proto |= proto_unix_s;
10140 	    if (sproto & proto_block) proto |= proto_block_s;
10141 	    if (sproto & proto_base) proto |= proto_base_s;
10142 	    if (sproto & proto_ident) proto |= proto_ident;
10143 	}
10144 	if ((dproto & proto_udp)) {
10145 	    proto |= proto_udp_d;
10146 	    if (dproto & proto_v6) proto |= proto_v6_d;
10147 	    if (dproto & proto_ip_only) proto |= proto_ip_only_d;
10148 	} else {
10149 	    if ((dproto & proto_command) == command_proxy) {
10150 		proto &= ~proto_command;
10151 		proto |= command_proxy;
10152 #ifdef USE_POP
10153 	    } else if ((dproto & proto_command) == command_pop) {
10154 		proto &= ~proto_command;
10155 		proto |= command_pop;
10156 #endif
10157 	    } else if (dproto & proto_ohttp) {
10158 		proto |= proto_ohttp_d;
10159 		goto extra_arg;
10160 	    } else if ((dproto & proto_command) == command_ihead) {
10161 		proto &= ~proto_command;
10162 		proto |= command_ihead;
10163 	      extra_arg:
10164 		p = argv[k++];
10165 		j--;
10166 		if (k > argc || j < 0) {
10167 		    help(argv[0], NULL);
10168 		    exit(1);
10169 		}
10170 	    } else if ((dproto & proto_command) == command_iheads) {
10171 		proto &= ~proto_command;
10172 		proto |= command_iheads;
10173 		goto extra_arg;
10174 	    } else if ((dproto & proto_command) == command_health) {
10175 		proto &= ~proto_command;
10176 		proto |= command_health;
10177 	    } else if ((dproto & proto_command) == command_identd) {
10178 		proto &= ~proto_command;
10179 		proto |= command_identd;
10180 	    }
10181 	    if (dproto & proto_ssl) proto |= proto_ssl_d;
10182 	    if (dproto & proto_v6) proto |= proto_v6_d;
10183 	    if (dproto & proto_ip_only) proto |= proto_ip_only_d;
10184 	    if (dproto & proto_unix) proto |= proto_unix_d;
10185 	    if (dproto & proto_block) proto |= proto_block_d;
10186 	    if (dproto & proto_base) proto |= proto_base_d;
10187 	    if (dproto & proto_nobackup) proto |= proto_nobackup;
10188 	}
10189 	stone = mkstone(host, serv, shost, sintf, sserv, j, &argv[k], proto);
10190 	if ((proto & proto_udp_s) && (proto & proto_udp_d)) { /* UDP => UDP */
10191 	    Origin *origin = (Origin*)malloc(sizeof(Origin));
10192 	    if (origin == NULL) {
10193 	    memerr:
10194 		message(LOG_CRIT, "Out of memory");
10195 		exit(1);
10196 	    }
10197 	    bzero(origin, sizeof(Origin));
10198 	    origin->stone = stone;
10199 	    origin->common = type_origin;
10200 	    origin->sd = INVALID_SOCKET;
10201 	    origin->from = NULL;
10202 	    origin->next = OriginTop;
10203 	    OriginTop = origin;
10204 	    stone->p = (char*)origin;
10205 	} else if (proto & proto_ohttp_d) {
10206 	    stone->p = strdup(p);
10207 	} else if (((proto & proto_command) == command_ihead) ||
10208 		   ((proto & proto_command) == command_iheads)) {
10209 	    stone->p = strdup(p);
10210 	}
10211 	if (!(proto & proto_udp_s) || !(proto & proto_udp_d)) {
10212 	    stone->pairs = newPair();
10213 	    if (!stone->pairs) goto memerr;
10214 	    stone->pairs->clock = -1;	/* top */
10215 	    stone->pairs->stone = stone;
10216 	    stone->pairs->next = PairTop;
10217 	    if (PairTop) PairTop->prev = stone->pairs;
10218 	    PairTop = stone->pairs;
10219 	}
10220 	if (!stone->parent) {	/* stone is parent */
10221 	    stone->next = stones;
10222 	    stones = stone;
10223 	}
10224 	proto = sproto = dproto = 0;	/* default: TCP */
10225     }
10226 #ifndef USE_EPOLL
10227     for (stone=stones; stone != NULL; stone=stone->next) {
10228 	FdSet(stone->sd, &rin);
10229 	FdSet(stone->sd, &ein);
10230     }
10231 #endif
10232 }
10233 
10234 #ifdef FD_SET_BUG
checkFdSetBug(void)10235 void checkFdSetBug(void) {
10236     fd_set set;
10237     FD_ZERO(&set);
10238     FD_SET(0, &set);
10239     FD_SET(0, &set);
10240     FD_CLR(0, &set);
10241     if (FD_ISSET(0, &set)) {
10242 	if (Debug > 0)
10243 	    message(LOG_DEBUG, "FD_SET bug detected");
10244 	FdSetBug = 1;
10245     }
10246 }
10247 #endif
10248 
10249 #ifndef WINDOWS
handler(int sig)10250 static void handler(int sig) {
10251     int i;
10252     switch(sig) {
10253     case SIGHUP:
10254 	if (Debug > 4) message(LOG_DEBUG, "SIGHUP");
10255 #ifndef NO_FORK
10256 	if (NForks) {	/* mother process */
10257 	    if (ConfigFile && !oldstones) {
10258 	        oldstones = stones;
10259 		stones = NULL;
10260 		OldConfigArgc = ConfigArgc;
10261 		OldConfigArgv = ConfigArgv;
10262 		Debug = 0;
10263 		getconfig();	/* reconfigure */
10264 		i = doopts(ConfigArgc, ConfigArgv);
10265 		doargs(ConfigArgc, i, ConfigArgv);
10266 		for (i=0; i < NForks; i++) {
10267 		    kill(Pid[i], SIGHUP);
10268 		    kill(Pid[i], SIGINT);
10269 		}
10270 	    }
10271 	} else {	/* child process */
10272 #endif
10273 	    message_pairs(LOG_INFO);
10274 	    message_origins(LOG_INFO);
10275 	    message_conns(LOG_INFO);
10276 #ifndef NO_FORK
10277 	}
10278 #endif
10279 	if (LogFileName) {
10280 	    fclose(LogFp);
10281 	    LogFp = fopen(LogFileName, "a");
10282 	    if (LogFp == NULL) {
10283 		LogFp = stderr;
10284 		message(LOG_ERR, "Can't re-create log file: %s err=%d",
10285 			LogFileName, errno);
10286 		exit(1);
10287 	    }
10288 	    setbuf(LogFp, NULL);
10289 	}
10290 	if (AccFileName) {
10291 	    fclose(AccFp);
10292 	    AccFp = fopen(AccFileName, "a");
10293 	    if (AccFp == NULL) {
10294 		message(LOG_ERR, "Can't re-create account log file: %s err=%d",
10295 			AccFileName, errno);
10296 		exit(1);
10297 	    }
10298 	    setbuf(AccFp, NULL);
10299 	}
10300 	signal(SIGHUP, handler);
10301 	break;
10302     case SIGTERM:
10303 #ifdef IGN_SIGTERM
10304 	Debug = 0;
10305 	message(LOG_INFO, "SIGTERM. clear Debug level");
10306 	signal(SIGTERM, handler);
10307 	break;
10308 #endif
10309     case SIGINT:
10310 #ifndef NO_FORK
10311 	if (NForks) {	/* mother process */
10312 	    message(LOG_INFO, "SIGTERM/INT. killing children and exiting");
10313 	    for (i=0; i < NForks; i++) kill(Pid[i], sig);
10314 	} else
10315 #endif
10316 	    message(LOG_INFO, "SIGTERM/INT. exiting");  /* child process */
10317 	exit(1);
10318     case SIGUSR1:
10319 	Debug++;
10320 	message(LOG_INFO, "SIGUSR1. increase Debug level to %d", Debug);
10321 #ifndef NO_FORK
10322 	if (NForks) {	/* mother process */
10323 	    for (i=0; i < NForks; i++) kill(Pid[i], sig);
10324 	} else {
10325 #endif
10326 	    message_pairs(LOG_INFO);
10327 	    message_origins(LOG_INFO);
10328 	    message_conns(LOG_INFO);
10329 #ifndef NO_FORK
10330 	}
10331 #endif
10332 	signal(SIGUSR1, handler);
10333 	break;
10334     case SIGUSR2:
10335 	if (Debug > 0) Debug--;
10336 	message(LOG_INFO, "SIGUSR2. decrease Debug level to %d", Debug);
10337 #ifndef NO_FORK
10338 	if (NForks) {	/* mother process */
10339 	    for (i=0; i < NForks; i++) kill(Pid[i], sig);
10340 	}
10341 #endif
10342 	signal(SIGUSR2, handler);
10343 	break;
10344     case SIGPIPE:
10345 	if (Debug > 0) message(LOG_DEBUG, "SIGPIPE");
10346 	signal(SIGPIPE, handler);
10347 	break;
10348     case SIGSEGV:
10349     case SIGBUS:
10350     case SIGILL:
10351     case SIGFPE:
10352 	if (CoreDumpDir) {
10353 	    message(LOG_ERR, "Signal %d, core dumping to %s",
10354 		    sig, CoreDumpDir);
10355 	    if (chdir(CoreDumpDir) < 0) {
10356 		message(LOG_ERR, "Can't chdir to %s err=%d",
10357 			CoreDumpDir, errno);
10358 	    } else {
10359 		abort();
10360 	    }
10361 	} else {
10362 	    message(LOG_ERR, "Signal %d, exiting", sig);
10363 	}
10364 	exit(1);
10365 	break;
10366     default:
10367 	message(LOG_INFO, "signal %d. Debug level: %d", sig, Debug);
10368     }
10369 }
10370 #endif
10371 
10372 #ifdef UNIX_DAEMON
daemonize(void)10373 void daemonize(void) {
10374     pid_t pid;
10375     pid = fork();
10376     if (pid < 0) {
10377 	message(LOG_ERR, "Can't create daemon err=%d", errno);
10378 	exit(1);
10379     }
10380     if (pid > 0) _exit(0);
10381     MyPid = getpid();
10382     if (setsid() < 0)
10383 	message(LOG_WARNING, "Can't create new session err=%d", errno);
10384     if (chdir("/") < 0)
10385 	message(LOG_WARNING, "Can't change directory to / err=%d", errno);
10386     umask(0022);
10387     if (close(0) != 0)
10388 	message(LOG_WARNING, "Can't close stdin err=%d", errno);
10389     if (close(1) != 0)
10390 	message(LOG_WARNING, "Can't close stdout err=%d", errno);
10391 #if !defined(NO_SYSLOG) || defined(ANDROID)
10392     if (Syslog > 1) Syslog = 1;
10393 #endif
10394     if (!LogFileName) LogFp = NULL;
10395     if (close(2) != 0)
10396 	message(LOG_WARNING, "Can't close stderr err=%d", errno);
10397 }
10398 #endif
10399 
initialize(int argc,char * argv[])10400 void initialize(int argc, char *argv[]) {
10401     int i;
10402     int j = 0;	/* dummy init to suppress warnings */
10403 #ifdef WINDOWS
10404     WSADATA WSAData;
10405     if (WSAStartup(MAKEWORD(1, 1), &WSAData)) {
10406 	message(LOG_ERR, "Can't find winsock");
10407 	exit(1);
10408     }
10409     atexit((void(*)(void))WSACleanup);
10410 #endif
10411     MyPid = getpid();
10412     LogFp = stderr;
10413     setbuf(stderr, NULL);
10414 #ifdef USE_SSL
10415     SSL_library_init();
10416     SSL_load_error_strings();
10417     OpenSSL_add_all_algorithms();
10418     PairIndex = SSL_get_ex_new_index(0, "Pair index", NULL, NULL, NULL);
10419     MatchIndex = SSL_get_ex_new_index(0, "Match index", NULL, NULL, NULL);
10420     RAND_poll();
10421     if (!RAND_status()) {
10422 	message(LOG_WARNING, "Can't collect enough random seeds");
10423 	srand(time(NULL));
10424 	do {
10425 	    u_short rnd = (u_short)rand();
10426 	    RAND_seed(&rnd, sizeof(rnd));
10427 	} while (!RAND_status());
10428     }
10429     sslopts_default(&ServerOpts, 1);
10430     sslopts_default(&ClientOpts, 0);
10431 #endif
10432     XHostsTrue = malloc(XHostsBaseSize + sizeof(struct sockaddr_storage));
10433     if (!XHostsTrue) {
10434 	message(LOG_CRIT, "Out of memory");
10435 	exit(1);
10436     }
10437     XHostsTrue->next = NULL;
10438     XHostsTrue->mbits = 0;
10439     XHostsTrue->mode = 0;
10440     XHostsTrue->xhost.len = sizeof(struct sockaddr_storage);
10441     bzero(&XHostsTrue->xhost.addr, XHostsTrue->xhost.len);
10442     XHostsTrue->xhost.addr.sa_family = AF_UNSPEC;
10443     i = doopts(argc, argv);
10444     if (ConfigFile) {
10445 	getconfig();
10446 	j = doopts(ConfigArgc, ConfigArgv);
10447     }
10448 #ifdef UNIX_DAEMON
10449     if (DaemonMode) daemonize();
10450 #endif
10451     if (!DryRun && PidFile) {
10452 	FILE *fp = fopen(PidFile, "w");
10453 	if (fp) {
10454 	    fprintf(fp, "%d\n", MyPid);
10455 	    fclose(fp);
10456 	}
10457     }
10458 #ifndef NO_SYSLOG
10459     if (Syslog) {
10460 	snprintf(SyslogName, STRMAX, "stone[%d]", MyPid);
10461 	SyslogName[STRMAX] = '\0';
10462 	openlog(SyslogName, 0, LOG_DAEMON);
10463 	if (Syslog > 1) setbuf(stdout, NULL);
10464     }
10465 #endif
10466     message(LOG_INFO, "start (%s) [%d]", VERSION, MyPid);
10467     if (Debug > 0) {
10468 	message(LOG_DEBUG, "Debug level: %d", Debug);
10469     }
10470     trash.next = NULL;
10471     conns.next = NULL;
10472 #ifndef USE_EPOLL
10473 #ifdef FD_SET_BUG
10474     checkFdSetBug();
10475 #endif
10476     FD_ZERO(&rin);
10477     FD_ZERO(&win);
10478     FD_ZERO(&ein);
10479 #endif
10480     if (ConfigFile && ConfigArgc > j) {
10481 	if (argc > i) doargs(argc, i, argv);
10482 	doargs(ConfigArgc, j, ConfigArgv);
10483     } else {
10484 	doargs(argc, i, argv);
10485     }
10486 #ifndef WINDOWS
10487     signal(SIGHUP, handler);
10488     signal(SIGTERM, handler);
10489     signal(SIGINT, handler);
10490     signal(SIGPIPE, handler);
10491     signal(SIGUSR1, handler);
10492     signal(SIGUSR2, handler);
10493     signal(SIGSEGV, handler);
10494     signal(SIGBUS, handler);
10495     signal(SIGILL, handler);
10496     signal(SIGFPE, handler);
10497 #endif
10498 #ifndef NO_FORK
10499     if (!DryRun && NForks) {
10500 	Pid = malloc(sizeof(pid_t) * NForks);
10501 	if (!Pid) {
10502 	    message(LOG_CRIT, "Out of memory");
10503 	    exit(1);
10504 	}
10505 	for (i=0; i < NForks; i++) {
10506 	    Pid[i] = fork();
10507 	    if (!Pid[i]) break;
10508 	}
10509 	if (i >= NForks) {	/* the mother process */
10510 	    pid_t id;
10511 	    for (;;) {
10512 		int status;
10513 		id = wait(&status);
10514 		if (id < 0) continue;
10515 		message(LOG_WARNING, "Process died pid=%d, status=%x",
10516 			id, status);
10517 		for (i=0; i < NForks; i++) {
10518 		    if (Pid[i] == id) break;
10519 		}
10520 		if (i < NForks) {
10521 		    id = fork();
10522 		    if (!id) break;	/* respawned child */
10523 		    else Pid[i] = id;
10524 		} else {
10525 		    message(LOG_ERR, "This can't happen pid=%d", id);
10526 		}
10527 	    }
10528 	}
10529 	free(Pid);	/* child process */
10530 	Pid = NULL;
10531 	NForks = 0;
10532 	MyPid = getpid();
10533 #ifndef NO_SYSLOG
10534 	if (Syslog) {
10535 	    closelog();
10536 	    snprintf(SyslogName, STRMAX, "stone[%d]", MyPid);
10537 	    SyslogName[STRMAX] = '\0';
10538 	    openlog(SyslogName, 0, LOG_DAEMON);
10539 	}
10540 #endif
10541 	message(LOG_INFO, "child start (%s) [%d]", VERSION, MyPid);
10542     }
10543 #endif
10544 #ifdef PTHREAD
10545     pthread_attr_init(&thread_attr);
10546     pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_DETACHED);
10547 #endif
10548 #ifdef WINDOWS
10549     PairMutex = ConnMutex = OrigMutex = AsyncMutex = NULL;
10550     if (!(PairMutex=CreateMutex(NULL, FALSE, NULL)) ||
10551 	!(ConnMutex=CreateMutex(NULL, FALSE, NULL)) ||
10552 	!(OrigMutex=CreateMutex(NULL, FALSE, NULL)) ||
10553 	!(AsyncMutex=CreateMutex(NULL, FALSE, NULL)) ||
10554 #ifndef USE_EPOLL
10555 	!(FdRinMutex=CreateMutex(NULL, FALSE, NULL)) ||
10556 	!(FdWinMutex=CreateMutex(NULL, FALSE, NULL)) ||
10557 	!(FdEinMutex=CreateMutex(NULL, FALSE, NULL)) ||
10558 #endif
10559 	!(ExBufMutex=CreateMutex(NULL, FALSE, NULL)) ||
10560 	!(FPairMutex=CreateMutex(NULL, FALSE, NULL)) ||
10561 #ifdef ADDRCACHE
10562 	!(HashMutex=CreateMutex(NULL, FALSE, NULL)) ||
10563 #endif
10564 	!(PkBufMutex=CreateMutex(NULL, FALSE, NULL)) ) {
10565 	message(LOG_ERR, "Can't create Mutex err=%d", (int)GetLastError());
10566     }
10567 #endif
10568 #ifdef OS2
10569     PairMutex = ConnMutex = OrigMutex = AsyncMutex = NULLHANDLE;
10570     if ((j=DosCreateMutexSem(NULL, &PairMutex, 0, FALSE)) ||
10571 	(j=DosCreateMutexSem(NULL, &ConnMutex, 0, FALSE)) ||
10572 	(j=DosCreateMutexSem(NULL, &OrigMutex, 0, FALSE)) ||
10573 	(j=DosCreateMutexSem(NULL, &AsyncMutex, 0, FALSE)) ||
10574 #ifndef USE_EPOLL
10575 	(j=DosCreateMutexSem(NULL, &FdRinMutex, 0, FALSE)) ||
10576 	(j=DosCreateMutexSem(NULL, &FdWinMutex, 0, FALSE)) ||
10577 	(j=DosCreateMutexSem(NULL, &FdEinMutex, 0, FALSE)) ||
10578 #endif
10579 	(j=DosCreateMutexSem(NULL, &ExBufMutex, 0, FALSE)) ||
10580 	(j=DosCreateMutexSem(NULL, &FPairMutex, 0, FALSE)) ||
10581 #ifdef ADDRCACHE
10582 	(j=DosCreateMutexSem(NULL, &HashMutex, 0, FALSE)) ||
10583 #endif
10584 	(j=DosCreateMutexSem(NULL, &PkBufMutex, 0, FALSE)) ) {
10585 	message(LOG_ERR, "Can't create Mutex err=%d", j);
10586     }
10587 #endif
10588 #ifndef NO_THREAD
10589 #ifdef USE_SSL
10590     if (sslthread_initialize() < 0) {
10591 	message(LOG_ERR, "Fail to initialize SSL callback");
10592     }
10593 #endif
10594 #endif
10595 #ifndef NO_CHROOT
10596     if (RootDir) {
10597 	char cwd[BUFMAX];
10598 	int len = strlen(RootDir);
10599 	getcwd(cwd, BUFMAX-1);
10600 	if (strncmp(cwd, RootDir, len) != 0) len = -1;
10601 	if (chroot(RootDir) < 0) {
10602 	    message(LOG_WARNING, "Can't change root directory to %s", RootDir);
10603 	} else if (len <= 0) {
10604 	    if (Debug > 0)
10605 		message(LOG_DEBUG, "cwd=%s is outside chroot=%s, so chdir /",
10606 			cwd, RootDir);
10607 	    if (chdir("/") < 0) {
10608 		message(LOG_WARNING,
10609 			"Can't change directory to chroot / err=%d", errno);
10610 	    }
10611 	}
10612     }
10613 #endif
10614 #ifndef NO_SETUID
10615     if (SetUID || SetGID) {
10616 	if (AccFileName) fchown(fileno(AccFp), SetUID, SetGID);
10617 	if (LogFileName) fchown(fileno(LogFp), SetUID, SetGID);
10618     }
10619     if (SetGID) if (setgid(SetGID) < 0 || setgroups(1, &SetGID) < 0) {
10620 	message(LOG_WARNING, "Can't set gid err=%d", errno);
10621     }
10622     if (SetUID) if (setuid(SetUID) < 0) {
10623 	message(LOG_WARNING, "Can't set uid err=%d", errno);
10624     }
10625 #endif
10626 #ifdef PR_SET_DUMPABLE
10627     if (CoreDumpDir && (SetUID || SetGID)) {
10628 	if (prctl(PR_SET_DUMPABLE, 1) < 0) {
10629 	    message(LOG_ERR, "prctl err=%d", errno);
10630 	}
10631     }
10632 #endif
10633     if (MinInterval > 0) {
10634 	if (Debug > 1) message(LOG_DEBUG, "MinInterval: %d", MinInterval);
10635     }
10636     time(&lastEstablished);
10637     lastReadWrite = lastEstablished;
10638 #ifdef USE_EPOLL
10639     /* ePollFd must be created in each process */
10640     ePollFd = epoll_create(BACKLOG_MAX);
10641     if (ePollFd < 0) {
10642 	message(LOG_CRIT, "Can't create epoll err=%d", errno);
10643 	exit(1);
10644     } else {
10645 	Stone *stone;
10646 	for (stone=stones; stone != NULL; stone=stone->next) {
10647 	    struct epoll_event ev;
10648 	    ev.events = (EPOLLIN | EPOLLPRI);
10649 	    ev.data.ptr = stone;
10650 	    if (Debug > 6)
10651 		message(LOG_DEBUG, "stone %d: epoll_ctl %d ADD %lx",
10652 			stone->sd, ePollFd, (long)ev.data.ptr);
10653 	    if (epoll_ctl(ePollFd, EPOLL_CTL_ADD, stone->sd, &ev) < 0) {
10654 		message(LOG_CRIT, "stone %d: epoll_ctl %d ADD err=%d",
10655 			stone->sd, ePollFd, errno);
10656 		exit(1);
10657 	    }
10658 	}
10659     }
10660 #endif
10661 }
10662 
10663 #ifdef NT_SERVICE
scReportStatus(DWORD curState,DWORD exitCode,DWORD hint)10664 void scReportStatus(DWORD curState, DWORD exitCode, DWORD hint) {
10665     static DWORD checkPoint = 1;
10666     if (curState == SERVICE_START_PENDING)
10667 	NTServiceStatus.dwControlsAccepted = 0;
10668     else
10669 	NTServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP;
10670     NTServiceStatus.dwCurrentState = curState;
10671     NTServiceStatus.dwWin32ExitCode = exitCode;
10672     NTServiceStatus.dwWaitHint = hint;
10673     if ((curState == SERVICE_RUNNING) || (curState == SERVICE_STOPPED))
10674 	NTServiceStatus.dwCheckPoint = 0;
10675     else
10676 	NTServiceStatus.dwCheckPoint = checkPoint++;
10677     SetServiceStatus(NTServiceStatusHandle, &NTServiceStatus);
10678 }
10679 
serviceCtrl(DWORD code)10680 void WINAPI serviceCtrl(DWORD code) {
10681     switch(code) {
10682     case SERVICE_CONTROL_STOP:
10683 	scReportStatus(SERVICE_STOP_PENDING, NO_ERROR, 0);
10684 	message(LOG_INFO, "Service stopping..");
10685 	if (WaitForSingleObject(NTServiceThreadHandle, 1000) == WAIT_TIMEOUT)
10686 	    TerminateThread(NTServiceThreadHandle, 0);
10687 	break;
10688     default:
10689 	break;
10690     }
10691 }
10692 
serviceThread(LPVOID lpParms)10693 DWORD WINAPI serviceThread(LPVOID lpParms) {
10694     do {
10695 	repeater();
10696     } while (NTServiceStatus.dwCurrentState == SERVICE_RUNNING);
10697     ExitThread(0);
10698     return 0;
10699 }
10700 
serviceMain(DWORD argc,LPTSTR * argv)10701 void WINAPI serviceMain(DWORD argc, LPTSTR *argv) {
10702     DWORD thid;
10703     NTServiceStatusHandle
10704 	= RegisterServiceCtrlHandler(NTServiceName, serviceCtrl);
10705     if (!NTServiceStatusHandle) {
10706 	message(LOG_ERR, "Can't register ServiceCtrlHandler");
10707 	return;
10708     }
10709     NTServiceStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
10710     NTServiceStatus.dwServiceSpecificExitCode = 0;
10711     scReportStatus(SERVICE_START_PENDING, NO_ERROR, 3000);
10712     message(LOG_INFO, "Service started");
10713     scReportStatus(SERVICE_RUNNING, NO_ERROR, 0);
10714     NTServiceThreadHandle = CreateThread(0, 0, serviceThread, NULL, 0, &thid);
10715     if (NTServiceThreadHandle) {
10716 	WaitForSingleObject(NTServiceThreadHandle, INFINITE);
10717 	CloseHandle(NTServiceThreadHandle);
10718     }
10719     message(LOG_INFO, "Service stopped");
10720     scReportStatus(SERVICE_STOPPED, NO_ERROR, 0);
10721 }
10722 #endif
10723 
10724 #ifdef CLEAR_ARGS
clear_args(int argc,char * argv[])10725 static void clear_args(int argc, char *argv[]) {
10726     char *argend = argv[argc-1] + strlen(argv[argc-1]);
10727     char *p;
10728     for (p=argv[1]; p < argend; p++) *p = '\0';	/* clear args */
10729 }
10730 #endif
10731 
main(int argc,char * argv[])10732 int main(int argc, char *argv[]) {
10733     initialize(argc, argv);
10734     if (DryRun) return 0;
10735 #ifdef NT_SERVICE
10736     if (NTServiceName) {
10737 	SERVICE_TABLE_ENTRY dispatchTable[] =
10738 	    {
10739 		{ NTServiceName, (LPSERVICE_MAIN_FUNCTION)serviceMain },
10740 		{ NULL, NULL }
10741 	    };
10742 	if (!StartServiceCtrlDispatcher(dispatchTable))
10743 	    message(LOG_ERR, "StartServiceCtrlDispatcher failed");
10744 	return 0;
10745     }
10746 #endif
10747 #ifdef CLEAR_ARGS
10748     clear_args(argc, argv);
10749 #endif
10750 #ifdef MEMLEAK_CHECK
10751     mtrace();
10752 #endif
10753     for (;;) repeater();
10754     return 0;
10755 }
10756 
10757 /*
10758   For Gnu Emacs.
10759   Local Variables:
10760   tab-width: 8
10761   c-basic-offset: 4
10762   End:
10763 */
10764