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, ¶m);
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, ¶m);
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, ¶m);
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, ¶m);
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, ¶m);
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, ¶m);
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