-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathstone.c
10344 lines (10062 loc) · 269 KB
/
stone.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
/*
* stone.c simple repeater
* Copyright(c)1995-2008 by Hiroaki Sengoku <[email protected]>
* Version 1.0 Jan 28, 1995
* Version 1.1 Jun 7, 1995
* Version 1.2 Aug 20, 1995
* Version 1.3 Feb 16, 1996 relay UDP
* Version 1.5 Nov 15, 1996 for Win32
* Version 1.6 Jul 5, 1997 for SSL
* Version 1.7 Aug 20, 1997 return packet of UDP
* Version 1.8 Oct 18, 1997 pseudo parallel using SIGALRM
* Version 2.0 Nov 3, 1997 http proxy & over http
* Version 2.1 Nov 14, 1998 respawn & pop
* Version 2.2 May 25, 2003 Posix Thread, XferBufMax, no ALRM, SSL verify
* Version 2.3 Jan 1, 2006 LB, healthCheck, NonBlock, IPv6, sockaddr_un
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNU Emacs; see the file COPYING. If not, write to
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
*
* Usage: stone [-d] [-n] [-u <max>] [-f <n>] [-a <file>] [-L <file>] [-l]
* [-o <n>] [-g <n>] [-t <dir>] [-z <SSL>] [-D]
* [-C <file>] [-P <command>]
* <st> [-- <st>]...
* <st> := <host>:<port> <sport> [<xhost>...]
* | proxy <sport> [<xhost>...]
* | <host>:<port#>/http <sport> <request> [<xhost>...]
* | <host>:<port#>/proxy <sport> <header> [<xhost>...]
* <port> := <port#>[/udp | /ssl | /apop]
* <sport> := [<host>:]<port#>[/udp | /ssl | /http]
* <xhost> := <host>[/<mask>]
*
* Any packets received by <sport> are passed to <host>:<port>
* as long as these packets are sent from <xhost>...
* if <xhost> are not given, any hosts are welcome.
*
* Make:
* gcc -o stone stone.c
* or
* cl -DWINDOWS stone.c /MT wsock32.lib
* or
* gcc -DWINDOWS -o stone.exe stone.c -lwsock32
*
* POP -> APOP conversion
* gcc -DUSE_POP -o stone stone.c md5c.c
* or
* cl -DWINDOWS -DUSE_POP stone.c md5c.c /MT wsock32.lib
* or
* gcc -DWINDOWS -DUSE_POP -o stone.exe stone.c md5c.c -lwsock32
*
* md5c.c global.h md5.h are contained in RFC1321
*
* Using OpenSSL
* gcc -DUSE_SSL -I/usr/local/ssl/include -o stone stone.c \
* -L/usr/local/ssl/lib -lssl -lcrypto
* or
* cl -DWINDOWS -DUSE_SSL stone.c /MT wsock32.lib ssleay32.lib libeay32.lib
* or
* gcc -DWINDOWS -DUSE_SSL -o stone.exe stone.c -lwsock32 -lssl32 -leay32
*
* -DUSE_POP use POP -> APOP conversion
* -DUSE_SSL use OpenSSL
* -DCPP preprocessor for reading config. file
* -DIGN_SIGTERM ignore SIGTERM signal
* -DUNIX_DAEMON fork into background and become a UNIX Daemon
* -DNO_BCOPY without bcopy(3)
* -DNO_SNPRINTF without snprintf(3)
* -DNO_SYSLOG without syslog(2)
* -DNO_RINDEX without rindex(3)
* -DNO_STRDUP without strdup(3)
* -DNO_THREAD without thread
* -DNO_PID_T without pid_t
* -DNO_SOCKLEN_T without socklen_t
* -DNO_ADDRINFO without getaddrinfo
* -DNO_FAMILY_T without sa_family_t
* -DADDRCACHE cache address used in proxy
* -DUSE_EPOLL use epoll(4) (Linux)
* -DPTHREAD use Posix Thread
* -DPRCTL use prctl(2) - operations on a process
* -DOS2 OS/2 with EMX
* -DWINDOWS Windows95/98/NT
* -DNT_SERVICE WindowsNT/2000 native service
*/
#define VERSION "2.3e"
static char *CVS_ID =
"@(#) $Id: stone.c,v 2.3.2.7 2008/02/24 23:03:16 hiroaki_sengoku Exp $";
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h>
#include <ctype.h>
#include <stdarg.h>
#include <signal.h>
#ifdef USE_PCRE
#include <pcreposix.h>
#else
#include <regex.h>
#endif
typedef void (*FuncPtr)(void*);
#ifdef WINDOWS
#define FD_SETSIZE 4096
#include <process.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#if !defined(EINPROGRESS) && defined(WSAEWOULDBLOCK)
#define EINPROGRESS WSAEWOULDBLOCK
#endif
#if !defined(EMSGSIZE) && defined(WSAEMSGSIZE)
#define EMSGSIZE WSAEMSGSIZE
#endif
#if !defined(EADDRINUSE) && defined(WSAEADDRINUSE)
#define EADDRINUSE WSAEADDRINUSE
#endif
#if !defined(ECONNABORTED) && defined(WSAECONNABORTED)
#define ECONNABORTED WSAECONNABORTED
#endif
#if !defined(ECONNRESET) && defined(WSAECONNRESET)
#define ECONNRESET WSAECONNRESET
#endif
#if !defined(EISCONN) && defined(WSAEISCONN)
#define EISCONN WSAEISCONN
#endif
#include <time.h>
#ifdef NT_SERVICE
#include <windows.h>
#include "logmsg.h"
#endif
#define NO_SYSLOG
#define NO_FORK
#define NO_SETUID
#define NO_CHROOT
#define NO_GETTIMEOFDAY
#define NO_FAMILY_T
#define NO_UNIXDOMAIN
#define ValidSocket(sd) ((sd) != INVALID_SOCKET)
#define FD_SET_BUG
#undef EINTR
#define EINTR WSAEINTR
#define NO_BCOPY
#define bzero(b,n) memset(b,0,n)
#define usleep(usec) Sleep(usec)
#define ASYNC(func,arg) {\
if (Debug > 7) message(LOG_DEBUG, "ASYNC: %d", AsyncCount);\
waitMutex(AsyncMutex);\
AsyncCount++;\
freeMutex(AsyncMutex);\
if (_beginthread((FuncPtr)func, 0, arg) < 0) {\
message(LOG_ERR, "_beginthread error err=%d", errno);\
func(arg);\
}\
}
#else /* ! WINDOWS */
#include <sys/param.h>
#ifdef OS2
#define INCL_DOSSEMAPHORES
#define INCL_DOSERRORS
#include <process.h>
#include <os2.h>
#define NO_SYSLOG
#define NO_UNIXDOMAIN
#define ASYNC(func,arg) {\
if (Debug > 7) message(LOG_DEBUG,"ASYNC: %d",AsyncCount);\
waitMutex(AsyncMutex);\
AsyncCount++;\
freeMutex(AsyncMutex);\
if (_beginthread((FuncPtr)func,NULL,32768,arg) < 0) {\
message(LOG_ERR,"_beginthread error err=%d",errno);\
func(arg);\
}\
}
#else /* ! WINDOWS & ! OS2 */
#ifdef PTHREAD
#include <pthread.h>
pthread_attr_t thread_attr;
typedef void *(*aync_start_routine) (void *);
#define ASYNC(func,arg) {\
pthread_t thread;\
int err;\
if (Debug > 7) message(LOG_DEBUG,"ASYNC: %d",AsyncCount);\
waitMutex(AsyncMutex);\
AsyncCount++;\
freeMutex(AsyncMutex);\
err=pthread_create(&thread,&thread_attr,(aync_start_routine)func,arg);\
if (err) {\
message(LOG_ERR,"pthread_create error err=%d",err);\
func(arg);\
} else if (Debug > 7) {\
message(LOG_DEBUG,"pthread ID=%lu",thread);\
}\
}
#else /* ! PTHREAD */
#define ASYNC(func,arg) {\
waitMutex(AsyncMutex);\
AsyncCount++;\
freeMutex(AsyncMutex);\
func(arg);\
}
#define NO_THREAD
#endif /* ! PTHREAD */
#endif /* ! WINDOWS & ! OS2 */
#include <sys/wait.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <time.h>
#ifndef NO_SETUID
#include <grp.h>
#endif
#ifdef PRCTL
#include <sys/prctl.h>
#endif
#ifdef MEMLEAK_CHECK
#include <mcheck.h>
#endif
typedef int SOCKET;
#define INVALID_SOCKET -1
#define ValidSocket(sd) ((sd) >= 0)
#define closesocket(sd) close(sd)
#endif /* ! WINDOWS */
#define InvalidSocket(sd) (!ValidSocket(sd))
#ifdef USE_EPOLL
#include <sys/epoll.h>
#define EVSMAX 100
#else
#ifdef FD_SET_BUG
int FdSetBug = 0;
#define FdSet(fd,set) do{if (!FdSetBug || !FD_ISSET((fd),(set))) \
FD_SET((fd),(set));}while(0)
#else
#define FdSet(fd,set) FD_SET((fd),(set))
#endif
#endif
#ifdef NO_THREAD
#define ASYNC_BEGIN /* */
#define _ASYNC_END /* */
#else
#define ASYNC_BEGIN \
if (Debug > 7) message(LOG_DEBUG,"ASYNC_BEGIN: %d",AsyncCount)
#define _ASYNC_END \
if (Debug > 7) message(LOG_DEBUG,"ASYNC_END: %d",AsyncCount);\
waitMutex(AsyncMutex);\
AsyncCount--;\
freeMutex(AsyncMutex)
#endif
#ifdef USE_SSL
#define ASYNC_END \
_ASYNC_END;\
ERR_remove_state(0)
#else
#define ASYNC_END _ASYNC_END
#endif
#ifdef NO_SYSLOG
#define LOG_CRIT 2 /* critical conditions */
#define LOG_ERR 3 /* error conditions */
#define LOG_WARNING 4 /* warning conditions */
#define LOG_NOTICE 5 /* normal but signification condition */
#define LOG_INFO 6 /* informational */
#define LOG_DEBUG 7 /* debug-level messages */
#else /* SYSLOG */
#include <syslog.h>
#endif
#define BACKLOG_MAX 50
#define XPORT 6000
#define BUFMAX 2048
#define LONGSTRMAX 1024
#define STRMAX 127 /* > 38 */
#define CONN_TIMEOUT 60 /* 1 min */
#define LB_MAX 100
#define FREE_TIMEOUT 600 /* 10 min */
#ifndef MAXHOSTNAMELEN
#define MAXHOSTNAMELEN 255
#endif
#define TICK_SELECT 100000 /* 0.1 sec */
#define SPIN_MAX 10 /* 1 sec */
#define NERRS_MAX 10 /* # of select errors */
#define REF_UNIT 10 /* unit of pair->count */
#ifdef USE_SSL
#include <openssl/crypto.h>
#include <openssl/x509.h>
#include <openssl/x509v3.h>
#include <openssl/ssl.h>
#include <openssl/bio.h>
#include <openssl/err.h>
#include <openssl/pkcs12.h>
#include <openssl/rand.h>
#ifdef CRYPTOAPI
int SSL_CTX_use_CryptoAPI_certificate(SSL_CTX *ssl_ctx, const char *cert_prop);
int CryptoAPI_verify_certificate(X509 *x509);
#endif
#define NMATCH_MAX 9 /* \1 ... \9 */
#define DEPTH_MAX 10
#ifndef TLSEXT_NAMETYPE_host_name
#define OPENSSL_NO_TLSEXT
#endif
typedef struct {
int verbose;
int shutdown_mode;
int depth;
long serial;
SSL_CTX *ctx;
regex_t *re[DEPTH_MAX];
char *name;
unsigned char lbmod;
unsigned char lbparm;
unsigned char sslparm;
} StoneSSL;
const int sslparm_ignore = 0x01;
const int sslparm_storeca = 0x02;
const int sslparm_sni = 0x04;
typedef struct {
int verbose;
int shutdown_mode;
int mode;
int depth;
int vflags;
long off;
long serial;
/* const */ SSL_METHOD *meth;
int (*callback)(int, X509_STORE_CTX *);
unsigned char *sid_ctx;
int useSNI;
char *keyFile;
char *certFile;
char *keyFilePat;
char *certFilePat;
char *caFile;
char *caPath;
char *pfxFile;
char *pfxFilePat;
char *passFile;
char *passFilePat;
char *passwd;
char *servername;
int certIgnore;
#ifdef CRYPTOAPI
int certStoreCA;
char *certStore;
#endif
char *cipherList;
char *regexp[DEPTH_MAX];
unsigned char lbmod;
unsigned char lbparm;
char *dhparamFile;
#if OPENSSL_VERSION_NUMBER >= 0x1000000fL && !defined(OPENSSL_NO_ECDH)
char *ecdhCurve;
#endif
} SSLOpts;
DH *dhParam = NULL;
SSLOpts ServerOpts;
SSLOpts ClientOpts;
int PairIndex;
int MatchIndex;
int NewMatchCount = 0;
#ifdef WINDOWS
HANDLE *SSLMutex = NULL;
#else
#ifdef PTHREAD
pthread_mutex_t *SSLMutex = NULL;
#endif
#endif
int NSSLMutexs = 0;
#include <openssl/md5.h>
#define MD5Init MD5_Init
#define MD5Update MD5_Update
#define MD5Final MD5_Final
#else
#ifdef USE_POP
#include "global.h"
#include "md5.h"
#endif
#endif
#ifdef CPP
char *CppCommand = CPP;
char *CppOptions = NULL;
#endif
#ifdef NO_ADDRINFO
#undef AF_INET6
#endif
#ifdef NO_SOCKLEN_T
typedef int socklen_t;
#endif
typedef struct _Chat {
struct _Chat *next;
char *send;
int len;
regex_t expect;
} Chat;
typedef struct {
socklen_t len;
struct sockaddr addr;
} SockAddr;
#define SockAddrBaseSize ((int)&((SockAddr*)NULL)->addr)
typedef struct _XHosts {
struct _XHosts *next;
short mbits;
short mode;
SockAddr xhost; /* must be the last member */
} XHosts;
#define XHostsBaseSize (sizeof(XHosts) - sizeof(struct sockaddr))
#define XHostsMode_Dump 0xF
typedef struct _XPorts {
struct _XPorts *next;
short from; /* port range from */
short end; /* port range to, or equals to from */
} XPorts;
typedef struct _PortXHosts {
struct _PortXHosts *next;
XPorts *ports;
XHosts *xhosts;
} PortXHosts;
typedef struct _Backup {
struct _Backup *next;
SockAddr *check;
/* host:port for check (usually same as master) */
SockAddr *master;
SockAddr *backup;
int proto;
Chat *chat; /* chat script for health check */
short interval; /* interval of health check */
short bn; /* 0: health, 1: backup */
short used; /* 0: not used, 1: assigned, 2: used */
time_t last; /* last health check */
} Backup;
typedef struct _LBSet {
struct _LBSet *next;
int proto;
short ndsts;
SockAddr *dsts[0];
} LBSet;
#define type_mask 0x000f
#define type_pair 0x0001
#define type_origin 0x0002
#define type_stone 0x0003
#define type_pktbuf 0x0004
typedef struct _Stone {
int common;
SOCKET sd; /* socket descriptor to listen */
int port;
SockAddr *listen;
short ndsts; /* # of destinations */
SockAddr **dsts; /* destinations */
SockAddr *from;
int proto;
Backup **backups;
struct _Pair *pairs;
char *p;
int timeout;
struct _Stone *next;
struct _Stone *children;
struct _Stone *parent;
#ifdef USE_SSL
StoneSSL *ssl_server;
StoneSSL *ssl_client;
#endif
int nhosts; /* # of hosts */
XHosts *xhosts; /* hosts permitted to connect */
} Stone;
typedef struct _TimeLog {
time_t clock; /* time of beginning */
int pri; /* log priority */
char str[0]; /* Log message */
} TimeLog;
const int data_parm_mask = 0x00ff;
const int data_apop = 0x0100;
const int data_identuser = 0x0200;
const int data_ucred = 0x0300;
const int data_peeraddr = 0x0400;
#define DATA_HEAD_LEN sizeof(int)
typedef struct _ExBuf { /* extensible buffer */
struct _ExBuf *next;
int start; /* index of buf */
int len; /* last data is at buf[start+len-1] */
int bufmax; /* buffer size */
char buf[BUFMAX];
} ExBuf;
typedef struct _Pair {
int common;
struct _Pair *pair;
struct _Pair *prev;
struct _Pair *next;
Stone *stone; /* parent */
#ifdef USE_SSL
SSL *ssl; /* SSL handle */
int ssl_flag;
#endif
XHosts *xhost;
time_t clock;
int timeout;
SOCKET sd; /* socket descriptor */
int proto;
int count; /* reference counter */
ExBuf *d;
TimeLog *log;
int tx; /* sent bytes */
int rx; /* received bytes */
int loop; /* loop count */
int nbuf;
ExBuf *t; /* top */
ExBuf *b; /* bottom */
} Pair;
typedef struct _Conn {
SockAddr *dst; /* destination */
Pair *pair;
int lock;
struct _Conn *next;
} Conn;
typedef struct _Origin {
int common;
SOCKET sd; /* peer */
Stone *stone;
SockAddr *from; /* from where */
int lock;
XHosts *xhost;
time_t clock;
struct _Origin *next;
} Origin;
typedef struct _PktBuf { /* packet buffer */
int common;
struct _PktBuf *next;
int type;
Origin *origin;
int len;
int bufmax; /* buffer size */
char buf[BUFMAX];
} PktBuf;
typedef struct _Comm {
char *str;
int (*func)(Pair*, char*, int);
} Comm;
Stone *stones = NULL;
Stone *oldstones = NULL;
int ReuseAddr = 0;
PortXHosts *portXHosts = NULL;
XHosts *XHostsTrue = NULL;
Chat *healthChat = NULL;
Backup *backups = NULL;
LBSet *lbsets = NULL;
int MinInterval = 0;
time_t lastScanBackups = 0;
time_t lastEstablished = 0;
time_t lastReadWrite = 0;
Pair *PairTop = NULL;
Pair trash;
Pair *freePairs = NULL;
int nFreePairs = 0;
ExBuf *freeExBuf = NULL;
int nFreeExBuf = 0;
ExBuf *freeExBot = NULL;
int nFreeExBot = 0;
time_t freeExBotClock = 0;
Conn conns;
Origin *OriginTop = NULL;
int OriginMax = 100;
PktBuf *freePktBuf = NULL;
int nFreePktBuf = 0;
#ifdef USE_EPOLL
int ePollFd;
#else
fd_set rin, win, ein;
#endif
int PairTimeOut = 10 * 60; /* 10 min */
int AsyncCount = 0;
int MutexConflict = 0;
const int state_mask = 0x00ff;
const int proto_command = 0x0f00; /* command (dest. only) */
/* only for Stone */
const int proto_ident = 0x1000; /* need ident */
const int proto_nobackup = 0x2000; /* no backup */
const int proto_udp_s = 0x4000; /* UDP source */
const int proto_udp_d = 0x8000; /* destination */
const int proto_v6_s = 0x10000; /* IPv6 source */
const int proto_v6_d = 0x20000; /* destination */
const int proto_ip_only_s = 0x40000; /* IPv6 only source */
const int proto_ip_only_d = 0x80000; /* destination */
const int proto_unix_s = 0x100000; /* unix socket source */
const int proto_unix_d = 0x200000; /* destination */
const int proto_block_s = 0x400000; /* blocking I/O source */
const int proto_block_d = 0x800000; /* destination*/
const int proto_ssl_s = 0x1000000; /* SSL source */
const int proto_ssl_d = 0x2000000; /* destination */
/* only for Pair */
const int proto_dirty = 0x1000; /* ev must be updated */
const int proto_noconnect = 0x2000; /* no connection needed */
const int proto_connect = 0x4000; /* connection established */
const int proto_dgram = 0x8000; /* UDP */
const int proto_first_r = 0x10000; /* first read packet */
const int proto_first_w = 0x20000; /* first written packet */
const int proto_select_r = 0x40000; /* select to read */
const int proto_select_w = 0x80000; /* select to write */
const int proto_shutdown = 0x100000; /* sent shutdown */
const int proto_close = 0x200000; /* request to close */
const int proto_eof = 0x400000; /* EOF was received */
const int proto_error = 0x800000; /* error reported */
#ifndef USE_EPOLL
const int proto_thread = 0x1000000; /* on thread */
#endif
const int proto_conninprog = 0x2000000; /* connect in progress */
const int proto_ohttp_s = 0x4000000; /* over http source */
const int proto_ohttp_d = 0x8000000; /* destination */
const int proto_base_s = 0x10000000; /* base64 source */
const int proto_base_d = 0x20000000; /* destination */
#define command_ihead 0x0100 /* insert header */
#define command_iheads 0x0200 /* insert header repeatedly */
#define command_pop 0x0300 /* POP -> APOP conversion */
#define command_health 0x0400 /* is stone healthy ? */
#define command_identd 0x0500 /* identd of stone */
#define command_proxy 0x0600 /* http proxy */
#define command_source 0x0f00 /* source flag */
#define proto_ssl (proto_ssl_s|proto_ssl_d)
#define proto_v6 (proto_v6_s|proto_v6_d)
#define proto_udp (proto_udp_s|proto_udp_d)
#define proto_ip_only (proto_ip_only_s|proto_ip_only_d)
#define proto_unix (proto_unix_s|proto_unix_d)
#define proto_block (proto_block_s|proto_block_d)
#define proto_ohttp (proto_ohttp_s|proto_ohttp_d)
#define proto_base (proto_base_s|proto_base_d)
#define proto_stone_s (proto_udp_s|proto_command|\
proto_ohttp_s|proto_base_s|\
proto_v6_s|proto_ip_only_s|\
proto_ssl_s|proto_ident)
#define proto_stone_d (proto_udp_d|proto_command|\
proto_ohttp_d|proto_base_d|\
proto_v6_d|proto_ip_only_d|\
proto_ssl_d|proto_nobackup)
#define proto_pair_s (proto_ohttp_s|proto_base_s)
#define proto_pair_d (proto_ohttp_d|proto_base_d|proto_command)
#ifdef USE_SSL
const int sf_mask = 0x0000f;
const int sf_depth = 0x000f0; /* depth of cert chain */
const int sf_depth_bit = 4;
const int sf_sb_on_r = 0x00100; /* SSL_shutdown blocked on read */
const int sf_sb_on_w = 0x00200; /* SSL_shutdown blocked on write */
const int sf_wb_on_r = 0x00400; /* SSL_write blocked on read */
const int sf_rb_on_w = 0x00800; /* SSL_read blocked on write */
const int sf_cb_on_r = 0x01000; /* SSL_connect blocked on read */
const int sf_cb_on_w = 0x02000; /* SSL_connect blocked on write */
const int sf_ab_on_r = 0x04000; /* SSL_accept blocked on read */
const int sf_ab_on_w = 0x08000; /* SSL_accept blocked on write */
#endif
int BacklogMax = BACKLOG_MAX;
int XferBufMax = 1000; /* TCP packet buffer initial size (must < 1024 ?) */
#define PKT_LEN_INI 2048 /* initial size */
int pkt_len_max = PKT_LEN_INI; /* size of UDP packet buffer */
int AddrFlag = 0;
#ifndef NO_SYSLOG
int Syslog = 0;
char SyslogName[STRMAX+1];
#endif
FILE *LogFp = NULL;
char *LogFileName = NULL;
FILE *AccFp = NULL;
char *AccFileName = NULL;
char *ConfigFile = NULL;
char *PidFile = NULL;
SockAddr *ConnectFrom = NULL;
int DryRun = 0;
int ConfigArgc = 0;
int OldConfigArgc = 0;
char **ConfigArgv = NULL;
char **OldConfigArgv = NULL;
#ifdef UNIX_DAEMON
int DaemonMode = 0;
#endif
#ifndef NO_CHROOT
char *RootDir = NULL;
#endif
#ifndef NO_SETUID
uid_t SetUID = 0;
gid_t SetGID = 0;
#endif
char *CoreDumpDir = NULL;
#ifdef NO_PID_T
typedef int pid_t;
#endif
pid_t MyPid;
#ifndef NO_FORK
int NForks = 0;
pid_t *Pid;
#endif
int Debug = 0; /* debugging level */
#ifdef ADDRCACHE
#define CACHE_TIMEOUT 180 /* 3 min */
int AddrCacheSize = 0;
#endif
#ifdef PTHREAD
pthread_mutex_t FastMutex = PTHREAD_MUTEX_INITIALIZER;
char FastMutexs[11];
#define PairMutex 0
#define ConnMutex 1
#define OrigMutex 2
#define AsyncMutex 3
#ifndef USE_EPOLL
#define FdRinMutex 4
#define FdWinMutex 5
#define FdEinMutex 6
#endif
#define ExBufMutex 7
#define FPairMutex 8
#define PkBufMutex 9
#ifdef ADDRCACHE
#define HashMutex 10
#endif
#endif
#ifdef WINDOWS
HANDLE PairMutex, ConnMutex, OrigMutex, AsyncMutex;
HANDLE FdRinMutex, FdWinMutex, FdEinMutex;
HANDLE ExBufMutex, FPairMutex, PkBufMutex;
#ifdef ADDRCACHE
HANDLE HashMutex;
#endif
#endif
#ifdef OS2
HMTX PairMutex, ConnMutex, OrigMutex, AsyncMutex;
HMTX FdRinMutex, FdWinMutex, FdEinMutex;
HMTX ExBufMutex, FPairMutex, PkBufMutex;
#ifdef ADDRCACHE
HMTX HashMutex;
#endif
#endif
#ifdef NT_SERVICE
SERVICE_STATUS NTServiceStatus;
SERVICE_STATUS_HANDLE NTServiceStatusHandle;
#define NTServiceDisplayPrefix "Stone "
char *NTServiceDisplayName = NULL;
char *NTServiceName = NULL;
HANDLE NTServiceLog = NULL;
HANDLE NTServiceThreadHandle = NULL;
#endif
#ifdef NO_VSNPRINTF
int vsnprintf(char *str, size_t len, char *fmt, va_list ap) {
int ret;
ret = vsprintf(str, fmt, ap);
if (strlen(str) >= len) {
fprintf(stderr, "Buffer overrun\n");
exit(1);
}
return ret;
}
#endif
#ifdef NO_SNPRINTF
int snprintf(char *str, size_t len, char *fmt, ...) {
va_list ap;
int ret;
va_start(ap, fmt);
ret = vsnprintf(str, len, fmt, ap);
va_end(ap);
return ret;
}
#endif
#ifdef NO_BCOPY
void bcopy(const void *b1, void *b2, int len) {
if (b1 < b2 && (char*)b2 < (char*)b1 + len) { /* overlapping */
char *p, *q;
q = (char*)b2 + len - 1;
for (p=(char*)b1+len-1; (char*)b1 <= p; p--, q--) *q = *p;
} else {
memcpy(b2, b1, len);
}
}
#endif
#ifdef NO_RINDEX
char *rindex(char *p, int ch) {
char *save = NULL;
do {
if (*p == ch) save = p;
} while (*p++);
return save;
}
#endif
#ifdef NO_STRDUP
char *strdup(const char *s) {
int len = strlen(s);
char *ret = malloc(len+1);
if (ret) {
bcopy(s, ret, len+1);
}
return ret;
}
#endif
#ifdef WINDOWS
struct tm *localtime_r(const time_t *clock, struct tm *t) {
FILETIME utc, local;
SYSTEMTIME system;
LONGLONG ll;
ll = Int32x32To64(*clock, 10000000) + 116444736000000000ULL;
utc.dwLowDateTime = (DWORD)ll;
utc.dwHighDateTime = ll >> 32;
if (!FileTimeToLocalFileTime(&utc, &local)) return NULL;
if (!FileTimeToSystemTime(&local, &system)) return NULL;
t->tm_sec = system.wSecond;
t->tm_min = system.wMinute;
t->tm_hour = system.wHour;
t->tm_mday = system.wDay;
t->tm_mon = system.wMonth-1;
t->tm_year = system.wYear-1900;
t->tm_wday = system.wDayOfWeek;
return t;
}
#endif
static char Month[][4] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun",
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
char *strntime(char *str, int len, time_t *clock, long micro) {
#ifdef THREAD_UNSAFE
struct tm *t = localtime(clock);
#else
struct tm tm;
struct tm *t = localtime_r(clock, &tm);
#endif
if (micro >= 0) {
snprintf(str, len, "%s %2d %02d:%02d:%02d.%06ld ",
Month[t->tm_mon], t->tm_mday,
t->tm_hour, t->tm_min, t->tm_sec, micro);
} else {
snprintf(str, len, "%s %2d %02d:%02d:%02d ",
Month[t->tm_mon], t->tm_mday,
t->tm_hour, t->tm_min, t->tm_sec);
}
return str;
}
#ifdef NO_GETTIMEOFDAY
int gettimeofday(struct timeval *tv, void *tz) {
static u_long start = 0;
u_long tick = GetTickCount();
time_t now;
time(&now);
if (start == 0) start = now - tick / 1000;
if (tz) return -1;
if (tv) {
tv->tv_usec = (tick % 1000) * 1000;
tv->tv_sec = start + (tick / 1000);
if (now < tv->tv_sec - 1 || tv->tv_sec + 1 < now) {
start = 0;
tv->tv_usec = -1; /* diff is too large */
}
return 0;
}
return -1;
}
#endif
#if defined (__STDC__) && __STDC__
void message(int pri, char *fmt, ...)
__attribute__ ((__format__ (__printf__, 2, 3)));
#endif
void message(int pri, char *fmt, ...) {
char str[LONGSTRMAX+1];
int pos = 0;
unsigned long thid = 0;
va_list ap;
#ifndef NO_SYSLOG
if (!Syslog)
#endif
{
struct timeval tv;
if (gettimeofday(&tv, NULL) >= 0) {
strntime(str+pos, LONGSTRMAX-pos, &tv.tv_sec, tv.tv_usec);
}
str[LONGSTRMAX] = '\0';
pos = strlen(str);
}
#ifdef WINDOWS
thid = (unsigned long)GetCurrentThreadId();
#else
#ifdef PTHREAD
thid = (unsigned long)pthread_self();
#endif
#endif
if (thid) {
snprintf(str+pos, LONGSTRMAX-pos, "%lu ", thid);
pos += strlen(str+pos);
}
va_start(ap, fmt);
vsnprintf(str+pos, LONGSTRMAX-pos, fmt, ap);
va_end(ap);
str[LONGSTRMAX] = '\0';
if (LogFp) fprintf(LogFp, "%s\n", str);
#ifndef NO_SYSLOG
else if (Syslog) {
if (Syslog == 1
|| pri != LOG_DEBUG) syslog(pri, "%s", str);
if (Syslog > 1) fprintf(stdout, "%s\n", str); /* daemontools */
}
#elif defined(NT_SERVICE)
else if (NTServiceLog) {
LPCTSTR msgs[] = {str, NULL};
int type = EVENTLOG_INFORMATION_TYPE;
if (pri <= LOG_ERR) type = EVENTLOG_ERROR_TYPE;
else if (pri <= LOG_NOTICE) type = EVENTLOG_WARNING_TYPE;
ReportEvent(NTServiceLog, type, 0, EVLOG, NULL, 1, 0, msgs, NULL);
}
#endif
}
void message_time(Pair *pair, int pri, char *fmt, ...) {
va_list ap;
char str[LONGSTRMAX+1];
TimeLog *log;
log = pair->log;
if (log) {
pair->log = NULL;
free(log);
}
va_start(ap, fmt);
vsnprintf(str, LONGSTRMAX, fmt, ap);
va_end(ap);
str[LONGSTRMAX] = '\0';
log = (TimeLog*)malloc(sizeof(TimeLog)+strlen(str)+1);
if (log) {
time(&log->clock);
log->pri = pri;
strcpy(log->str, str);
pair->log = log;
}
}
int priority(Pair *pair) {
int pri = LOG_ERR;
if (pair) {
if (pair->proto & proto_error) pri = LOG_DEBUG;
else pair->proto |= proto_error;
}
return pri;
}
void packet_dump(char *head, char *buf, int len, XHosts *xhost) {
char line[LONGSTRMAX+1];
int mode = (xhost->mode & XHostsMode_Dump);