/* 3APA3A simplest proxy server (c) 2002-2026 by Vladimir Dubrovin please read License Agreement */ #ifndef _STRUCTURES_H_ #define _STRUCTURES_H_ #include #include #include #include #include #include #ifndef PRId64 #include #endif #ifdef __cplusplus extern "C" { #endif #ifndef _WIN32 #include #include #include #include #include #include #include #ifdef IP_BOUND_IF #include #endif #define SASIZETYPE socklen_t #define SOCKET int #define INVALID_SOCKET (-1) #define _3proxy_mutex_t pthread_mutex_t #define _3proxy_mutex_init(x) pthread_mutex_init(x,NULL) #define _3proxy_mutex_destroy pthread_mutex_destroy #define _3proxy_mutex_lock pthread_mutex_lock #define _3proxy_mutex_unlock pthread_mutex_unlock typedef struct _3proxy_sem_s { pthread_mutex_t mutex; pthread_cond_t cond; unsigned count; unsigned maxcount; int monotonic; /* timed waits measured on CLOCK_MONOTONIC */ } _3proxy_sem_t; #else #include #include #define _3proxy_mutex_t CRITICAL_SECTION #define _3proxy_mutex_init(x) InitializeCriticalSection(x) #define _3proxy_mutex_lock(x) EnterCriticalSection(x) #define _3proxy_mutex_unlock(x) LeaveCriticalSection(x) #define _3proxy_mutex_destroy(x) DeleteCriticalSection(x) #define _3proxy_sem_t HANDLE #ifdef MSVC #pragma warning (disable : 4996) #endif #endif #define MAXBANDLIMS 10 #define MAXFAILEDPARENTS 16 /* Parent weights are kept as a share of WEIGHTSCALE, which is what the weights of a group add up to. WEIGHTFUZZ is how far short of it a group may fall and still be taken for a whole one, a thousandth of the share: three weights of 333, or of .333333333, otherwise leave a remainder. */ #define WEIGHTSCALE 1000000000u #define WEIGHTFUZZ 1000000u #ifdef WITH_POLL #include #else #ifdef WITH_WSAPOLL #define poll(A,B,C) WSAPoll(A,B,C) #else struct mypollfd { SOCKET fd; /* file descriptor */ short events; /* events to look for */ short revents; /* events returned */ }; #define pollfd mypollfd int #ifdef _WIN32 WINAPI #endif mypoll(struct mypollfd *fds, unsigned int nfds, int timeout); #ifndef POLLIN #define POLLIN 1 #endif #ifndef POLLOUT #define POLLOUT 2 #endif #ifndef POLLPRI #define POLLPRI 4 #endif #ifndef POLLERR #define POLLERR 8 #endif #ifndef POLLHUP #define POLLHUP 16 #endif #ifndef POLLNVAL #define POLLNVAL 32 #endif #endif #endif #ifdef WITH_UN #include #endif #define ALLOW 0 #define DENY 1 #define REDIRECT 2 #define BANDLIM 3 #define NOBANDLIM 4 #define COUNTIN 5 #define NOCOUNTIN 6 #define COUNTOUT 7 #define NOCOUNTOUT 8 #define CONNLIM 9 #define NOCONNLIM 10 #define COUNTALL 11 #define NOCOUNTALL 12 #define CONNECT 0x00000001 #define BIND 0x00000002 #define UDPASSOC 0x00000004 #define ICMPASSOC 0x00000008 /* reserved */ #define HTTP_GET 0x00000100 #define HTTP_PUT 0x00000200 #define HTTP_POST 0x00000400 #define HTTP_HEAD 0x00000800 #define HTTP_CONNECT 0x00001000 #define HTTP_OTHER 0x00008000 #define HTTP 0x0000EF00 /* all except HTTP_CONNECT */ #define HTTPS HTTP_CONNECT #define FTP_GET 0x00010000 #define FTP_PUT 0x00020000 #define FTP_LIST 0x00040000 #define FTP_DATA 0x00080000 #define FTP 0x000F0000 #define DNSRESOLVE 0x00100000 #define ADMIN 0x01000000 #ifdef NO_UN #undef WITH_UN #endif #define SAFAMILY(sa) (&(((struct sockaddr_in *)sa)->sin_family)) #ifdef WITH_UN #define UN_SAPORT(sa) (((struct sockaddr_un *)sa)->sun_family == AF_UNIX)? (uint16_t *)(((uint8_t *)(sa)) + sizeof(struct sockaddr_storage) - 2) : #define UN_SAADDR(sa) (((struct sockaddr_un *)sa)->sun_family == AF_UNIX)? (unsigned char *)((struct sockaddr_un *)sa)->sun_path : #define UN_SAADDRLEN(sa) (((struct sockaddr_un *)sa)->sun_family == AF_UNIX)? (int)sizeof(((struct sockaddr_un *)sa)->sun_path) : #define UN_SASOCK(sa) (((struct sockaddr_un *)sa)->sun_family == AF_UNIX)? PF_UNIX : #define UN_SASIZE(sa) (((struct sockaddr_un *)sa)->sun_family == AF_UNIX)? sizeof(struct sockaddr_un) : #define UN_SAISNULL(sa) (((struct sockaddr_un *)sa)->sun_family == AF_UNIX)? (((struct sockaddr_un *)sa)->sun_path[0] == 0 && ((struct sockaddr_un *)sa)->sun_path[1] == 0) : #else #define UN_SAPORT(sa) #define UN_SAADDR(sa) #define UN_SAADDRLEN(sa) #define UN_SASOCK(sa) #define UN_SASIZE(sa) #define UN_SAISNULL(sa) #endif #ifndef NOIPV6 #define SAPORT(sa) ( UN_SAPORT(sa) ((struct sockaddr_in *)sa)->sin_family == AF_INET6? &((struct sockaddr_in6 *)sa)->sin6_port : &((struct sockaddr_in *)sa)->sin_port) #define SAADDR(sa) ( UN_SAADDR(sa) ((struct sockaddr_in *)sa)->sin_family == AF_INET6? (unsigned char *)&((struct sockaddr_in6 *)sa)->sin6_addr : (unsigned char *)&((struct sockaddr_in *)sa)->sin_addr.s_addr) #define SAADDRLEN(sa) ( UN_SAADDRLEN(sa) ((struct sockaddr_in *)sa)->sin_family == AF_INET6? 16:4) #define SASOCK(sa) ( UN_SASOCK(sa) ((struct sockaddr_in *)sa)->sin_family == AF_INET6? PF_INET6:PF_INET) #define SASIZE(sa) ( UN_SASIZE(sa) ((struct sockaddr_in *)sa)->sin_family == AF_INET6? sizeof(struct sockaddr_in6):sizeof(struct sockaddr_in)) #define SAISNULL(sa) ( UN_SAISNULL(sa) !memcmp(((struct sockaddr_in *)sa)->sin_family == AF_INET6? (unsigned char *)&((struct sockaddr_in6 *)sa)->sin6_addr : (unsigned char *)&((struct sockaddr_in *)sa)->sin_addr.s_addr, NULLADDR, (((struct sockaddr_in *)sa)->sin_family == AF_INET6? 16:4))) #else #define SAPORT(sa) ( UN_SAPORT(sa) &((struct sockaddr_in *)sa)->sin_port) #define SAADDR(sa) ( UN_SAADDR(sa) (unsigned char *)&((struct sockaddr_in *)sa)->sin_addr.s_addr) #define SAADDRLEN(sa) ( UN_SAADDRLEN(sa) 4) #define SASOCK(sa) ( UN_SASOCK(sa) PF_INET) #define SASIZE(sa) ( UN_SASIZE(sa) sizeof(struct sockaddr_in)) #define SAISNULL(sa) ( UN_SAISNULL(sa) ((struct sockaddr_in *)sa)->sin_addr.s_addr == 0) #endif #ifdef WITH_UN #define PROXYSOCKADDRTYPE struct sockaddr_storage #else #ifndef NOIPV6 #define PROXYSOCKADDRTYPE struct sockaddr_in6 #else #define PROXYSOCKADDRTYPE struct sockaddr_in #endif #endif #define MAX_HASH_SIZE (64) #define UDPBUFSIZE 16384 #define CLIENTBUFSIZE (16384 + 64) #define CLIENTTMPBUFSIZE 8192 #define HOSTNAMELEN 256 #define USERNAMELEN 128 extern char* NULLADDR; typedef enum { CLIENT, SERVER } DIRECTION; typedef enum { S_NOSERVICE = 0, S_PROXY, S_TCPPM, S_POP3P = 3, S_SOCKS4 = 4, /* =4 */ S_SOCKS5 = 5, /* =5 */ S_UDPPM, S_SOCKS, S_SOCKS45, S_ADMIN, S_DNSPR, S_FTPPR, S_SMTPP, S_AUTO, S_TLSPR, S_IMAPP, S_HTTPSRV, S_ZOMBIE }PROXYSERVICE; #define MAX_SERVICE S_ZOMBIE struct clientparam; struct node; struct symbol; struct pluginlink; struct srvparam; typedef void (*LOGFUNC)(struct clientparam * param, const unsigned char *); typedef int (*AUTHFUNC)(struct clientparam * param); typedef void * (*REDIRECTFUNC)(struct clientparam * param); typedef uint32_t (*RESOLVFUNC)(int af, unsigned char *name, unsigned char *value); typedef unsigned (*BANDLIMFUNC)(struct clientparam * param, unsigned nbytesin, unsigned nbytesout); typedef void (*TRAFCOUNTFUNC)(struct clientparam * param); typedef void * (*EXTENDFUNC) (struct node *node); typedef void (*CBFUNC)(void *cb, char * buf, int inbuf); typedef void (*PRINTFUNC) (struct node *node, CBFUNC cbf, void*cb); #ifdef WIN32 #define PLUGINAPI __declspec(dllexport) typedef int (__cdecl *PLUGINFUNC) (struct pluginlink *pluginlink, int argc, char** argv); #define PLUGINCALL __cdecl #else #define PLUGINCALL #define PLUGINAPI typedef int (*PLUGINFUNC)(struct pluginlink *pluginlink, int argc, char** argv); #endif struct auth { struct auth *next; AUTHFUNC authenticate; AUTHFUNC authorize; char * desc; }; struct iplist { struct iplist *next; int family; PROXYSOCKADDRTYPE ip_from; PROXYSOCKADDRTYPE ip_to; }; struct portlist { struct portlist * next; uint16_t startport; uint16_t endport; }; struct userlist { struct userlist * next; unsigned char * user; }; typedef enum { SYS, CL, CR, NT, LM, UN }PWTYPE; struct passwords { struct passwords *next; unsigned char * user; unsigned char * password; int pwtype; }; typedef enum { R_TCP = 1, R_CONNECT, R_SOCKS4, R_SOCKS5, R_HTTP, R_POP3, R_SMTP, R_FTP, R_CONNECTP, R_SOCKS4P, R_SOCKS5P, R_SOCKS4B, R_SOCKS5B, R_ADMIN, R_EXTIP, R_TLS, R_HA, R_DNS, R_IMAP, R_EXTPORT, R_INTPORT } REDIRTYPE; struct redirdesc { REDIRTYPE redir; char * name; void * (*func)(struct clientparam *); }; extern struct redirdesc redirs[]; struct chain { struct chain * next; int type; int secure; PROXYSOCKADDRTYPE addr; unsigned char * exthost; unsigned char * extuser; unsigned char * extpass; unsigned weight; unsigned short cidr; /* local port range for extport/intport, first in the low half */ uint32_t range; }; struct period { struct period *next; int fromtime; int totime; }; #define MATCHBEGIN 1 #define MATCHEND 2 /* A pattern is either the star form above, matched by matchtype, or a regular expression compiled once when the configuration is read. */ #define MATCHGLOB 4 /* stars anywhere: * within a path element, ** across */ #define MATCHREGEX 5 /* What a star or a capturing group stood for. Element 0 is the whole subject, so a template writes it as $0 and the groups as $1 upwards. */ #define MAXCAPTURES 10 struct capture { int start; int len; }; struct hostname { struct hostname *next; unsigned char * name; int matchtype; void * re; /* compiled regular expression, MATCHREGEX only */ }; /* A request handed to an http operation. */ struct httpreq { struct capture caps[MAXCAPTURES]; int ncaps; struct capture hostcaps[MAXCAPTURES]; int nhostcaps; const char *ctype; const char *hdrs; int maxage; int code; time_t ims; /* what If-Modified-Since asked about, or 0 */ int version; /* 0 for HTTP/1.0, 1 for HTTP/1.1 */ int keepalive; /* whether the connection carries another request */ int first; /* the first request on this connection */ int chunkedreq; /* a body this server does not know how to read */ int proxy; /* the client asked the way it asks a proxy */ int connect; /* and asked for a tunnel */ int mayproxy; /* an access rule sent this to the local proxy */ int drained; /* the body has been read and thrown away */ char *lasthost; /* where the last request on this connection went */ void *handoff; /* a child which takes the connection over */ struct clientparam *param; char method[16]; char path[256]; char query[512]; char host[256]; uint64_t contentlen; int globstart, globlen; }; /* One "http" line: which host and url it answers for, which operation serves it and the parameters that operation takes. Patterns use the same syntax and the same matcher as host lists in access rules. */ struct httprule { struct httprule *next; struct hostname host; struct hostname url; int op; unsigned char *params; unsigned char *ctype; /* type named by the rule, or NULL to work it out */ unsigned char *hdrs; /* headers the rule adds, already CRLF separated */ int maxage; /* seconds to allow caching for, or -1 to say nothing */ int code; /* status the rule answers with, or 0 for the usual */ }; struct ace { struct ace *next; int action; int operation; int wdays; int weight; int nolog; struct period *periods; struct userlist *users; struct iplist *src, *dst; struct hostname *dstnames; struct portlist *ports; struct chain *chains; }; struct bandlim { struct bandlim *next; struct ace *ace; time_t basetime; unsigned nexttime; unsigned rate; }; struct connlim { struct connlim *next; struct ace *ace; time_t basetime; uint64_t rating; unsigned period; unsigned rate; }; typedef enum {NONE, MINUTELY, HOURLY, DAILY, WEEKLY, MONTHLY, ANNUALLY, NEVER} ROTATION; struct schedule { struct schedule *next; ROTATION type; void *data; int (*function)(void *); time_t start_time; }; struct trafcount { struct trafcount *next; struct ace *ace; unsigned number; ROTATION type; uint64_t traf64; uint64_t traflim64; char * comment; int disabled; time_t cleared; time_t updated; }; struct nserver { PROXYSOCKADDRTYPE addr; int usetcp; }; extern int numservers; typedef void * (* PROXYFUNC)(struct clientparam *); typedef enum { PASS = 0, CONTINUE, HANDLED, REJECT, REMOVE } FILTER_ACTION; typedef void* FILTER_OPEN(void * idata, struct srvparam * param); typedef FILTER_ACTION FILTER_CLIENT(void *fo, struct clientparam * param, void** fc); typedef FILTER_ACTION FILTER_PREDATA(void *fc, struct clientparam * param); typedef FILTER_ACTION FILTER_BUFFER(void *fc, struct clientparam * param, unsigned char ** buf_p, int * bufsize_p, int offset, int * length_p); typedef void FILTER_CLOSE(void *fo); struct filter { struct filter * next; char * instance; void * data; FILTER_OPEN *filter_open; FILTER_CLIENT *filter_client; FILTER_BUFFER *filter_request; FILTER_PREDATA *filter_connect; FILTER_PREDATA *filter_afterauth; FILTER_BUFFER *filter_header_cli; FILTER_BUFFER *filter_header_srv; FILTER_PREDATA *filter_predata; FILTER_BUFFER *filter_data_cli; FILTER_BUFFER *filter_data_srv; FILTER_CLOSE *filter_clear; FILTER_CLOSE *filter_close; }; struct filterp { struct filter *filter; void *data; }; #define MAX_FILTERS 256 /* Socket options for one kind of socket, -oc and the like: which of sockopts[] are given, by their index there, and the value of each. */ #define MAXSOCKOPTS 32 struct sockoptset { unsigned set; int value[MAXSOCKOPTS]; }; struct sockfuncs { void * state; void (*freefunc)(void* state); #ifdef _WIN32 SOCKET (WINAPI *_socket)(void* state, int domain, int type, int protocol); SOCKET (WINAPI *_accept)(void* state, SOCKET s, struct sockaddr * addr, int * addrlen); int (WINAPI *_bind)(void* state, SOCKET s, const struct sockaddr *addr, int addrlen); int (WINAPI *_listen)(void* state, SOCKET s, int backlog); int (WINAPI *_connect)(void* state, SOCKET s, const struct sockaddr *name, int namelen); int (WINAPI *_getpeername)(void* state, SOCKET s, struct sockaddr * name, int * namelen); int (WINAPI *_getsockname)(void* state, SOCKET s, struct sockaddr * name, int * namelen); int (WINAPI *_getsockopt)(void* state, SOCKET s, int level, int optname, char * optval, int * optlen); int (WINAPI *_setsockopt)(void* state, SOCKET s, int level, int optname, const char *optval, int optlen); int (WINAPI *_poll)(void* state, struct pollfd *fds, unsigned int nfds, int timeout); int (WINAPI *_send)(void* state, SOCKET s, const char *msg, int len, int flags); int (WINAPI *_sendto)(void* state, SOCKET s, const char *msg, int len, int flags, const struct sockaddr *to, int tolen); int (WINAPI *_recv)(void* state, SOCKET s, char *buf, int len, int flags); int (WINAPI *_recvfrom)(void* state, SOCKET s, char * buf, int len, int flags, struct sockaddr * from, int * fromlen); int (WINAPI *_shutdown)(void* state, SOCKET s, int how); int (WINAPI *_closesocket)(void* state, SOCKET s); #else SOCKET (*_socket)(void* state, int domain, int type, int protocol); SOCKET (*_accept)(void* state, SOCKET s, struct sockaddr * addr, socklen_t * addrlen); int (*_bind)(void* state, SOCKET s, const struct sockaddr *addr, socklen_t addrlen); int (*_listen)(void* state, SOCKET s, int backlog); int (*_connect)(void* state, SOCKET s, const struct sockaddr *name, socklen_t namelen); int (*_getpeername)(void* state, SOCKET s, struct sockaddr * name, socklen_t * namelen); int (*_getsockname)(void* state, SOCKET s, struct sockaddr * name, socklen_t * namelen); int (*_getsockopt)(void* state, SOCKET s, int level, int optname, void * optval, socklen_t * optlen); int (*_setsockopt)(void* state, int s, int level, int optname, const void *optval, socklen_t optlen); int (*_poll)(void* state, struct pollfd *fds, nfds_t nfds, int timeout); ssize_t (*_send)(void* state, SOCKET s, const void *msg, size_t len, int flags); ssize_t (*_sendto)(void* state, SOCKET s, const void *msg, size_t len, int flags, const struct sockaddr *to, SASIZETYPE tolen); ssize_t (*_recv)(void* state, SOCKET s, void *buf, size_t len, int flags); ssize_t (*_recvfrom)(void* state, SOCKET s, void * buf, size_t len, int flags, struct sockaddr * from, SASIZETYPE * fromlen); int (*_shutdown)(void* state, SOCKET s, int how); int (*_closesocket)(void* state, SOCKET s); #endif }; extern struct sockfuncs so; struct hashtable { void (*index2hash_add)(const struct hashtable *ht, void *index, uint8_t *hash); void (*index2hash_search)(const struct hashtable *ht, void *index, uint8_t *hash); unsigned recsize; unsigned hash_size; unsigned poolsize; unsigned tablesize; unsigned growlimit; uint32_t * ihashtable; uint8_t * hashvalues; uint8_t * hashhashvalues; _3proxy_mutex_t hash_mutex; time_t compacted; uint32_t ihashhashempty; uint32_t ihashempty; uint32_t entropy; }; struct srvparam { struct sockfuncs so; struct srvparam *next; struct srvparam *prev; struct clientparam *child; PROXYSERVICE service; LOGFUNC logfunc; AUTHFUNC authfunc; PROXYFUNC pf; SOCKET srvsock, cbsock; int childcount; int maxchild; int backlog; int paused, version; int s_option; int needuser; int silent; int transparent; int nfilters, nreqfilters, nconnectfilters, nafterauthfilters, nhdrfilterscli, nhdrfilterssrv, npredatfilters, ndatfilterscli, ndatfilterssrv; int family; int stacksize; int timeouts[12]; /* conf.timeouts as they were when the service started */ int noforce; int anonymous; struct sockoptset clisockopts, srvsockopts, lissockopts, cbcsockopts, cbssockopts; int gracetraf, gracenum, gracedelay; int requirecert; int haproxy; int nostarttls; PROXYSERVICE srvstarttls; int allowftp; /* the http proxy fetches ftp:// for this service */ uint32_t fakeip; unsigned char fakeip6[16]; #ifdef WITHSPLICE int usesplice; #endif int halfclose; int udpauth; unsigned bufsize; unsigned authcachetype, authcachetime; unsigned logdumpsrv, logdumpcli; PROXYSOCKADDRTYPE intsa, intNat, extNat; #ifndef NOIPV6 PROXYSOCKADDRTYPE extsa6; #endif PROXYSOCKADDRTYPE extsa; _3proxy_mutex_t counter_mutex; _3proxy_sem_t childslots; /* maxchild of them, one held by each child */ struct pollfd fds; FILE *stdlog; unsigned char * target; #if defined SO_BINDTODEVICE || defined IP_BOUND_IF char * ibindtodevice; char * obindtodevice; #endif #ifdef __linux__ char * inetns; char * onetns; /* -ni and -ne namespaces, opened with the service, -1 for the main one */ int i_nsfd; int o_nsfd; #endif struct auth *authenticate; struct pollfd * srvfds; struct ace *acl; #ifdef WITH_HTTPSRV struct httprule *httprules; #endif struct auth *authfuncs; struct filter *filter; unsigned char * logformat; unsigned char * logtarget; unsigned char * nonprintable; uint16_t targetport; unsigned char replace; time_t time_start; unsigned char *udpbuf; unsigned char *udpbuf2; int udplen; }; struct clientparam { struct clientparam *next, *prev; void * sostate; struct srvparam *srv; REDIRECTFUNC redirectfunc; BANDLIMFUNC bandlimfunc; TRAFCOUNTFUNC trafcountfunc; PROXYSERVICE service; PROXYSERVICE clientstarttls; SOCKET clisock, remsock, ctrlsock, ctrlsocksrv; REDIRTYPE redirtype; uint64_t waitclient64, waitserver64, cycles, threadid; uint8_t hash[MAX_HASH_SIZE]; int redirected, operation, nfilters, nreqfilters, nconnectfilters, nafterauthfilters, nhdrfilterscli, nhdrfilterssrv, npredatfilters, ndatfilterscli, ndatfilterssrv, unsafefilter, bandlimver; int res, status; int pwtype, weight, nolog, nolongdatfilter, nooverwritefilter, transparent, chunked, paused, version, connlim, predatdone, preauth, dstindep; unsigned char *clibuf, *srvbuf; /* splice() pipes for the client's and the server's data, -1 until made; kept for the life of the connection */ int pipecli[2], pipesrv[2]; unsigned cliinbuf, srvinbuf, clioffset, srvoffset, clibufsize, srvbufsize, msec_start; uint64_t maxtrafin64, maxtrafout64; PROXYSOCKADDRTYPE sincl, sincr; PROXYSOCKADDRTYPE sinsl, sinsr, req; uint32_t extport, intport; uint64_t statscli64, statssrv64; unsigned long nreads, nwrites, nconnects; struct bandlim *bandlims[MAXBANDLIMS], *bandlimsout[MAXBANDLIMS]; PROXYSOCKADDRTYPE udp_relay[3]; int udp_nhops; struct ace *lastace; time_t time_start; /* Set by a service which read a request itself and handed it to another child to answer: that child answers this one request and returns, leaving the connection to the service which called it. Added last so that a plugin built against an older header still finds the fields it knows where they were. */ int onerequest; /* A STARTTLS protocol to speak before the session is wrapped, set for one connection rather than for the service, which is how a redirect and a service name standing in for a mail proxy reach tlspr. */ PROXYSERVICE starttls; /* Parents which failed for this connection. A retry picks another member of the group instead of the same one again, and a zero weight member is only reached once every weighted one is in here. */ struct chain *failedparents[MAXFAILEDPARENTS]; int nfailedparents; /* Where in clibuf a request being read began, -1 when nothing is to be kept, -2 once a request was too big for the buffer. While it is set, refilling the buffer keeps everything from there on instead of starting over, so the request can be read again from the buffer. */ int climark; /* Names and credentials, empty when there are none. A value too long for its field is refused, never cut short: set them with PARAMSTR. */ unsigned char hostname[HOSTNAMELEN], username[USERNAMELEN], password[USERNAMELEN], extusername[USERNAMELEN], extpassword[USERNAMELEN]; /* The filters this connection runs, which a new connection makes for itself: the service's are not copied to it. Ordered for each stage. */ struct filterp filters[MAX_FILTERS], *reqfilters[MAX_FILTERS], *connectfilters[MAX_FILTERS], *afterauthfilters[MAX_FILTERS], *hdrfilterscli[MAX_FILTERS], *hdrfilterssrv[MAX_FILTERS], *predatfilters[MAX_FILTERS], *datfilterscli[MAX_FILTERS], *datfilterssrv[MAX_FILTERS]; /* The thread this structure belongs to, which keeps it from one connection to the next while it waits in the pool. */ struct clientparam *poolnext; /* next idle worker */ _3proxy_sem_t wake; /* posted when given a connection */ size_t stacksize; /* of its thread */ uint64_t workerid; /* the thread's id */ int pooled, /* waiting in the pool */ poolexit; /* woken to end instead */ /* The connection's scratch buffer, for a log line and the like: for something done at once, never for what has to outlive a call into anything that could log. */ unsigned char tmpbuf[CLIENTTMPBUFSIZE]; /* Each side's data buffer, which clibuf and srvbuf point to unless a filter needed a bigger one. */ unsigned char clibufdata[CLIENTBUFSIZE], srvbufdata[CLIENTBUFSIZE]; }; /* Threads whose connections have ended wait here for the next one, with the clientparam they keep, for any service whose stack fits theirs. */ struct threadpool { _3proxy_mutex_t mutex; struct clientparam *idle; /* most recently parked first */ unsigned nidle; unsigned limit; /* the cap last applied */ unsigned services; /* running services and their maxchild, */ unsigned maxchild; /* for the automatic cap */ uint64_t created, reused; }; extern struct threadpool tpool; struct filemon { char * path; struct stat sb; struct filemon *next; }; struct extparam { int *timeouts; struct ace * acl; #ifdef WITH_HTTPSRV struct httprule *httprules; #endif char * conffile; struct bandlim * bandlimiter, *bandlimiterout; struct connlim * connlimiter; struct trafcount * trafcounter; struct srvparam *services; int stacksize, counterd, haveerror, rotate, paused, archiverc, demon, maxchild, backlog, needreload, timetoexit, version, noforce, bandlimver, parentretries; unsigned authcachetype, authcachetime; int filtermaxsize; int poolmax, pooltimeout; /* threadpool: idle workers kept, -1 automatic */ int gracetraf, gracenum, gracedelay; int maxseg; unsigned char *logname, **archiver; ROTATION logtype, countertype; char * counterfile; PROXYSOCKADDRTYPE intsa; #ifndef NOIPV6 PROXYSOCKADDRTYPE extsa6; #endif PROXYSOCKADDRTYPE extsa; struct passwords *pwl; struct auth * authenticate; AUTHFUNC authfunc; LOGFUNC logfunc; BANDLIMFUNC bandlimfunc; TRAFCOUNTFUNC trafcountfunc; unsigned char *logtarget, *logformat; struct filemon * fmon; struct filter * filters; struct auth *authfuncs; FILE *stdlog; char* demanddialprog; unsigned char **stringtable; time_t logtime, time; unsigned logdumpsrv, logdumpcli; char delimchar; }; struct property { char * name; EXTENDFUNC e_f; int type; char * description; }; struct datatype { char * type; EXTENDFUNC i_f; PRINTFUNC p_f; struct property * properties; unsigned properties_count; }; struct node { void * value; void * iteration; struct node * parent; int type; }; struct dictionary { char * name; struct node * node; EXTENDFUNC array_f; int arraysize; }; struct commands { struct commands *next; char * command; int (* handler)(int argc, unsigned char ** argv); int minargs; int maxargs; }; struct symbol { struct symbol *next; char * name; void * value; }; struct proxydef { PROXYFUNC pf; uint16_t port; int isudp; int service; char * helpmessage; }; extern struct proxydef childdef; struct child { int argc; unsigned char **argv; }; extern struct hashtable dns_table; extern struct hashtable dns6_table; extern struct hashtable auth_table; extern struct hashtable pwl_table; extern struct hashtable udp_table; struct authcache { unsigned char username[64]; #ifndef NOIPV6 uint8_t sincr_addr[16]; uint8_t sinsl_addr[16]; #else uint8_t sincr_addr[4]; uint8_t sinsl_addr[4]; #endif uint16_t sincr_family; uint16_t sinsl_family; }; struct pluginlink { struct symbol symbols; struct extparam *conf; struct nserver *nservers; int * linenum; struct auth *authfuncs; struct commands * commandhandlers; void * (*findbyname)(const char *name); int (*socksend)(struct clientparam *param, SOCKET sock, unsigned char * buf, int bufsize, int to); int (*socksendto)(struct clientparam *param, SOCKET sock, struct sockaddr * sin, unsigned char * buf, int bufsize, int to); int (*sockrecvfrom)(struct clientparam *param, SOCKET sock, struct sockaddr * sin, unsigned char * buf, int bufsize, int to); int (*sockgetcharcli)(struct clientparam * param, int timeosec, int timeousec); int (*sockgetcharsrv)(struct clientparam * param, int timeosec, int timeousec); int (*sockgetlinebuf)(struct clientparam * param, DIRECTION which, unsigned char * buf, int bufsize, int delim, int to); int (*myinet_ntop)(int af, void *src, char *dst, socklen_t size); int (*dobuf)(struct clientparam * param, unsigned char * buf, const unsigned char *s, const unsigned char * doublec); int (*dobuf2)(struct clientparam * param, unsigned char * buf, const unsigned char *s, const unsigned char * doublec, struct tm* tm, char * format); int (*scanaddr)(const unsigned char *s, uint32_t * ip, uint32_t * mask); uint32_t (*getip46)(int family, unsigned char *name, struct sockaddr *sa); int (*sockmap)(struct clientparam * param, int timeo, int usesplice); int (*ACLMatches)(struct ace* acentry, struct clientparam * param); int (*alwaysauth)(struct clientparam * param); int (*checkACL)(struct clientparam * param); unsigned char* (*en64)(const unsigned char *in, unsigned char *out, int inlen, int outsize); int (*de64)(const unsigned char *in, unsigned char *out, int maxlen); void (*tohex)(unsigned char *in, unsigned char *out, int len); void (*fromhex)(unsigned char *in, unsigned char *out, int len); void (*decodeurl)(unsigned char *s, int allowcr); int (*parsestr) (unsigned char *str, unsigned char **argm, int nitems, unsigned char ** buff, int *inbuf, int *bufsize); struct ace * (*make_ace) (int argc, unsigned char ** argv); void * (*mallocfunc)(size_t size); void (*freefunc)(void *ptr); void *(*reallocfunc)(void *ptr, size_t size); char * (*strdupfunc)(const char *str); TRAFCOUNTFUNC trafcountfunc; char ** proxy_table; struct schedule ** schedule; void (*freeacl)(struct ace*); char ** admin_table; struct proxydef * childdef; int (*start_proxy_thread)(struct child * chp); void (*freeparam)(struct clientparam * param); int (*parsehostname)(char *hostname, struct clientparam *param, uint16_t port); int (*parseusername)(char *username, struct clientparam *param, int extpasswd); int (*parseconnusername)(char *username, struct clientparam *param, int extpasswd, uint16_t port); struct sockfuncs *so; unsigned char * (*dologname) (unsigned char *buf, unsigned char *name, const unsigned char *ext, ROTATION lt, time_t t); }; struct counter_header { unsigned char sig[4]; time_t updated; }; struct counter_record { uint64_t traf64; time_t cleared; time_t updated; }; extern struct pluginlink pluginlink; extern char *rotations[]; typedef enum { SINGLEBYTE_S, SINGLEBYTE_L, STRING_S, STRING_L, CONNECTION_S, CONNECTION_L, DNS_TO, CHAIN_TO, CONNECT_TO, CONNBACK_TO, LINGER_TO }TIMEOUT; typedef enum { TYPE_INTEGER, TYPE_SHORT, TYPE_CHAR, TYPE_UNSIGNED, TYPE_UNSIGNED64, TYPE_TRAFFIC, TYPE_PORT, TYPE_IP, TYPE_SA, TYPE_CIDR, TYPE_STRING, TYPE_DATETIME, TYPE_OPERATIONS, TYPE_ROTATION, TYPE_PORTLIST, TYPE_IPLIST, TYPE_USERLIST, TYPE_PWLIST, TYPE_CHAIN, TYPE_ACE, TYPE_BANDLIMIT, TYPE_TRAFCOUNTER, TYPE_CLIENT, TYPE_WEEKDAYS, TYPE_TIME, TYPE_PERIOD, TYPE_SERVER, TYPE_PASSWORD, TYPE_HOSTNAME, TYPE_THREADPOOL }DATA_TYPE; #ifdef __cplusplus } #endif #endif