mirror of
https://repo.or.cz/socat.git
synced 2024-12-23 07:52:32 +00:00
665 lines
24 KiB
C
665 lines
24 KiB
C
/* source: xio.h */
|
|
/* Copyright Gerhard Rieger 2001-2012 */
|
|
/* Published under the GNU General Public License V.2, see file COPYING */
|
|
|
|
#ifndef __xio_h_included
|
|
#define __xio_h_included 1
|
|
|
|
#if 1 /*!*/
|
|
#include "mytypes.h"
|
|
#include "sysutils.h"
|
|
#endif
|
|
|
|
#define XIO_MAXSOCK 2
|
|
|
|
/* Linux 2.2.10 */
|
|
#define HAVE_STRUCT_LINGER 1
|
|
|
|
#define LINETERM_RAW 0
|
|
#define LINETERM_CR 1
|
|
#define LINETERM_CRNL 2
|
|
|
|
union xioaddr_desc;
|
|
struct opt;
|
|
|
|
/* the flags argument of xioopen */
|
|
#define XIO_RDONLY O_RDONLY /* asserted to be 0 */
|
|
#define XIO_WRONLY O_WRONLY /* asserted to be 1 */
|
|
#define XIO_RDWR O_RDWR /* asserted to be 2 */
|
|
#define XIO_ACCMODE O_ACCMODE /* must be 3 */
|
|
/* 3 is undefined */
|
|
#define XIO_MAYFORK 4 /* address is allowed to fork the program (fork),
|
|
especially with listen and connect addresses */
|
|
#define XIO_MAYCHILD 8 /* address is allowed to fork off a child that
|
|
exec's another program or calls system() */
|
|
#define XIO_MAYEXEC 16 /* address is allowed to exec a prog (exec+nofork) */
|
|
#define XIO_MAYCONVERT 32 /* address is allowed to perform modifications on the
|
|
stream data, e.g. SSL, READLINE; CRLF */
|
|
#define XIO_MAYCHAIN 64 /* address is allowed to consist of a chain of
|
|
subaddresses that are handled by socat
|
|
subprocesses */
|
|
#define XIO_EMBEDDED 256 /* address is nonterminal */
|
|
#define XIO_MAYALL INT_MAX /* all features enabled */
|
|
|
|
/* the status flags of xiofile_t */
|
|
#define XIO_DOESFORK XIO_MAYFORK
|
|
#define XIO_DOESCHILD XIO_MAYCHILD
|
|
#define XIO_DOESEXEC XIO_MAYEXEC
|
|
#define XIO_DOESCONVERT XIO_MAYCONVERT
|
|
#define XIO_DOESCHAIN XIO_MAYCHAIN
|
|
|
|
/* sometimes we use a set of allowed direction(s), a bit pattern */
|
|
#define XIOBIT_RDONLY (1<<XIO_RDONLY)
|
|
#define XIOBIT_WRONLY (1<<XIO_WRONLY)
|
|
#define XIOBIT_RDWR (1<<XIO_RDWR)
|
|
#define XIOBIT_ALL (XIOBIT_RDONLY|XIOBIT_WRONLY|XIOBIT_RDWR)
|
|
#define XIOBIT_ALLRD (XIOBIT_RDONLY|XIOBIT_RDWR)
|
|
#define XIOBIT_ALLWR (XIOBIT_WRONLY|XIOBIT_RDWR)
|
|
#define XIOBIT_ONE (XIOBIT_RDONLY|XIOBIT_WRONLY)
|
|
/* reverse the direction pattern */
|
|
#define XIOBIT_REVERSE(x) (((x)&XIOBIT_RDWR)|(((x)&XIOBIT_RDONLY)?XIOBIT_WRONLY:0)|(((x)&XIOBIT_WRONLY)?XIOBIT_RDONLY:0))
|
|
|
|
#define XIOWITHRD(rw) ((rw+1)&(XIO_RDONLY+1))
|
|
#define XIOWITHWR(rw) ((rw+1)&(XIO_WRONLY+1))
|
|
|
|
/* methods for reading and writing, and for related checks */
|
|
#define XIODATA_READMASK 0xf000 /* mask for basic r/w method */
|
|
#define XIOREAD_STREAM 0x1000 /* read() (default) */
|
|
#define XIOREAD_RECV 0x2000 /* recvfrom() */
|
|
#define XIOREAD_PTY 0x4000 /* handle EIO */
|
|
#define XIOREAD_READLINE 0x5000 /* ... */
|
|
#define XIOREAD_OPENSSL 0x6000 /* SSL_read() */
|
|
#define XIOREAD_TEST 0x7000 /* xioread_test() */
|
|
#define XIODATA_WRITEMASK 0x0f00 /* mask for basic r/w method */
|
|
#define XIOWRITE_STREAM 0x0100 /* write() (default) */
|
|
#define XIOWRITE_SENDTO 0x0200 /* sendto() */
|
|
#define XIOWRITE_PIPE 0x0300 /* write() to alternate (pipe) Fd */
|
|
#define XIOWRITE_2PIPE 0x0400 /* write() to alternate (2pipe) Fd */
|
|
#define XIOWRITE_READLINE 0x0500 /* check for prompt */
|
|
#define XIOWRITE_OPENSSL 0x0600 /* SSL_write() */
|
|
#define XIOWRITE_TEST 0x0700 /* xiowrite_test() */
|
|
#define XIOWRITE_TESTREV 0x0800 /* xiowrite_testrev() */
|
|
/* modifiers to XIODATA_READ_RECV */
|
|
#define XIOREAD_RECV_CHECKPORT 0x0001 /* recv, check peer port */
|
|
#define XIOREAD_RECV_CHECKADDR 0x0002 /* recv, check peer address */
|
|
#define XIOREAD_RECV_CHECKRANGE 0x0004 /* recv, check if peer addr in range */
|
|
#define XIOREAD_RECV_ONESHOT 0x0008 /* give EOF after first packet */
|
|
#define XIOREAD_RECV_SKIPIP 0x0010 /* recv, skip IPv4 header */
|
|
#define XIOREAD_RECV_FROM 0x0020 /* remember peer for replying */
|
|
|
|
/* combinations */
|
|
#define XIODATA_MASK (XIODATA_READMASK|XIODATA_WRITEMASK)
|
|
#define XIODATA_STREAM (XIOREAD_STREAM|XIOWRITE_STREAM)
|
|
#define XIODATA_RECVFROM (XIOREAD_RECV|XIOWRITE_SENDTO|XIOREAD_RECV_CHECKPORT|XIOREAD_RECV_CHECKADDR|XIOREAD_RECV_FROM)
|
|
#define XIODATA_RECVFROM_SKIPIP (XIODATA_RECVFROM|XIOREAD_RECV_SKIPIP)
|
|
#define XIODATA_RECVFROM_ONE (XIODATA_RECVFROM|XIOREAD_RECV_ONESHOT)
|
|
#define XIODATA_RECVFROM_SKIPIP_ONE (XIODATA_RECVFROM_SKIPIP|XIOREAD_RECV_ONESHOT)
|
|
#define XIODATA_RECV (XIOREAD_RECV|XIOWRITE_SENDTO|XIOREAD_RECV_CHECKRANGE)
|
|
#define XIODATA_RECV_SKIPIP (XIODATA_RECV|XIOREAD_RECV_SKIPIP)
|
|
#define XIODATA_PIPE (XIOREAD_STREAM|XIOWRITE_PIPE)
|
|
#define XIODATA_2PIPE (XIOREAD_STREAM|XIOWRITE_2PIPE)
|
|
#define XIODATA_PTY (XIOREAD_PTY|XIOWRITE_STREAM)
|
|
#define XIODATA_READLINE (XIOREAD_READLINE|XIOWRITE_STREAM)
|
|
#define XIODATA_OPENSSL (XIOREAD_OPENSSL|XIOWRITE_OPENSSL)
|
|
#define XIODATA_TEST (XIOREAD_TEST|XIOWRITE_TEST)
|
|
#define XIODATA_TESTUNI XIOWRITE_TEST
|
|
#define XIODATA_TESTREV XIOWRITE_TESTREV
|
|
|
|
/* XIOSHUT_* define the actions on shutdown of the address */
|
|
/* */
|
|
#define XIOSHUTRD_MASK 0x00f0
|
|
#define XIOSHUTWR_MASK 0x000f
|
|
#define XIOSHUTSPEC_MASK 0xff00 /* specific action */
|
|
#define XIOSHUTRD_UNSPEC 0x0000
|
|
#define XIOSHUTWR_UNSPEC 0x0000
|
|
#define XIOSHUTRD_NONE 0x0010 /* no action - e.g. stdin */
|
|
#define XIOSHUTWR_NONE 0x0001 /* no action - e.g. stdout */
|
|
#define XIOSHUTRD_CLOSE 0x0020 /* close() */
|
|
#define XIOSHUTWR_CLOSE 0x0002 /* close() */
|
|
#define XIOSHUTRD_DOWN 0x0030 /* shutdown(, SHUT_RD) */
|
|
#define XIOSHUTWR_DOWN 0x0003 /* shutdown(, SHUT_WR) */
|
|
#define XIOSHUTRD_SIGHUP 0x0040 /* kill sub process */
|
|
#define XIOSHUTWR_SIGHUP 0x0004 /* flush sub process with SIGHPUP */
|
|
#define XIOSHUTRD_SIGTERM 0x0050 /* kill sub process with SIGTERM */
|
|
#define XIOSHUTWR_SIGTERM 0x0005 /* kill sub process with SIGTERM */
|
|
#define XIOSHUTWR_SIGKILL 0x0006 /* kill sub process with SIGKILL */
|
|
#define XIOSHUTWR_NULL 0x0007 /* send empty packet (dgram socket) */
|
|
#define XIOSHUT_UNSPEC (XIOSHUTRD_UNSPEC|XIOSHUTWR_UNSPEC)
|
|
#define XIOSHUT_NONE (XIOSHUTRD_NONE|XIOSHUTWR_NONE)
|
|
#define XIOSHUT_CLOSE (XIOSHUTRD_CLOSE|XIOSHUTWR_CLOSE)
|
|
#define XIOSHUT_DOWN (XIOSHUTRD_DOWN|XIOSHUTWR_DOWN)
|
|
#define XIOSHUT_KILL (XIOSHUTRD_KILL|XIOSHUTWR_KILL)
|
|
#define XIOSHUT_NULL (XIOSHUTRD_DOWN|XIOSHUTWR_NULL)
|
|
#define XIOSHUT_PTYEOF 0x0100 /* change pty to icanon and write VEOF */
|
|
#define XIOSHUT_OPENSSL 0x0101 /* specific action on openssl */
|
|
/*!!!*/
|
|
|
|
#define XIOCLOSE_UNSPEC 0x0000 /* after init, when no end-close... option */
|
|
#define XIOCLOSE_NONE 0x0001 /* no action */
|
|
#define XIOCLOSE_CLOSE 0x0002 /* close() */
|
|
#define XIOCLOSE_SIGTERM 0x0003 /* send SIGTERM to sub process */
|
|
#define XIOCLOSE_SIGKILL 0x0004 /* send SIGKILL to sub process */
|
|
#define XIOCLOSE_CLOSE_SIGTERM 0x0005 /* close fd, then send SIGTERM */
|
|
#define XIOCLOSE_CLOSE_SIGKILL 0x0006 /* close fd, then send SIGKILL */
|
|
#define XIOCLOSE_SLEEP_SIGTERM 0x0007 /* short sleep, then SIGTERM */
|
|
#define XIOCLOSE_OPENSSL 0x0101
|
|
#define XIOCLOSE_READLINE 0x0102
|
|
|
|
/* these are the values allowed for the "enum xiotag tag" flag of the "struct
|
|
single" and "union bipipe" (xiofile_t) structures. */
|
|
enum xiotag {
|
|
XIO_TAG_INVALID, /* the record is not in use */
|
|
XIO_TAG_RDONLY, /* this is a single read-only stream */
|
|
XIO_TAG_WRONLY, /* this is a single write-only stream */
|
|
XIO_TAG_RDWR, /* this is a single read-write stream */
|
|
XIO_TAG_DUAL /* this is a dual stream, consisting of two single
|
|
streams */
|
|
} ;
|
|
|
|
/* inter address communication types */
|
|
enum xiocomm {
|
|
XIOCOMM_SOCKETPAIRS, /* two unix (local) socket pairs */
|
|
XIOCOMM_PIPES, /* two unnamed pipes (fifos) */
|
|
XIOCOMM_SOCKETPAIR, /* one unix (local) socket pairs */
|
|
XIOCOMM_PTYS, /* two pseudo terminals, each from master to slave */
|
|
XIOCOMM_PTY, /* one pseudo terminal, master on left side */
|
|
XIOCOMM_TCP, /* one TCP socket pair */
|
|
XIOCOMM_TCP4, /* one TCP/IPv4 socket pair */
|
|
XIOCOMM_TCP4_LISTEN, /* right side listens for TCP/IPv4, left connects */
|
|
} ;
|
|
|
|
union bipipe;
|
|
|
|
|
|
#define XIOADDR_ENDPOINT 0 /* endpoint address */
|
|
#define XIOADDR_INTER 1 /* inter address */
|
|
#define XIOADDR_SYS XIOADDR_ENDPOINT
|
|
#define XIOADDR_PROT XIOADDR_INTER
|
|
|
|
/* one side of an "extended socketpair" */
|
|
typedef struct fddesc {
|
|
int rfd; /* used for reading */
|
|
int wfd; /* used for writing */
|
|
bool single; /* rfd and wfd refer to the same "file" */
|
|
int dtype; /* specifies methods for reading and writing */
|
|
int howtoshut; /* specifies method for shutting down wfd */
|
|
int howtoclose; /* specifies method for closing rfd and wfd */
|
|
} xiofd_t;
|
|
|
|
struct xioaddr_inter_desc {
|
|
int tag; /* 0: endpoint addr; 1: inter addr */
|
|
const char *defname; /* main (canonical) name of address */
|
|
int numparams; /* number of required parameters */
|
|
int leftdirs; /* set of data directions supported on left side:
|
|
e.g. XIOBIT_RDONLY|XIOBIT_WRONLY|XIOBIT_RDWR */
|
|
unsigned groups;
|
|
int howtoshut;
|
|
int howtoclose;
|
|
int (*func)(int argc, const char *argv[], struct opt *opts, int rw, union bipipe *fd, unsigned groups,
|
|
int arg1, int arg2, int arg3);
|
|
int arg1;
|
|
int arg2;
|
|
int arg3;
|
|
int rightdirs;
|
|
#if WITH_HELP
|
|
const char *syntax;
|
|
#endif
|
|
} ;
|
|
|
|
struct xioaddr_endpoint_desc {
|
|
int tag; /* XIOADDR_ENDPOINT, XIOADDR_INTER */
|
|
const char *defname; /* main (canonical) name of address */
|
|
int numparams; /* number of required parameters */
|
|
int leftdirs; /* XIOBIT_* */
|
|
unsigned groups;
|
|
int howtoshut;
|
|
int howtoclose;
|
|
int (*func)(int argc, const char *argv[], struct opt *opts, int rw, union bipipe *fd, unsigned groups,
|
|
int arg1, int arg2, int arg3);
|
|
int arg1;
|
|
int arg2;
|
|
int arg3;
|
|
#if WITH_HELP
|
|
const char *syntax;
|
|
#endif
|
|
} ;
|
|
|
|
|
|
struct xioaddr_common_desc {
|
|
int tag; /* 0: endpoint addr; 1: inter addr */
|
|
const char *defname; /* main (canonical) name of address */
|
|
int numparams; /* number of required parameters */
|
|
int leftdirs;
|
|
unsigned groups;
|
|
int howtoshut;
|
|
int howtoclose;
|
|
} ;
|
|
|
|
|
|
union xioaddr_desc {
|
|
int tag; /* 0: endpoint addr; 1: inter addr */
|
|
struct xioaddr_common_desc common_desc;
|
|
struct xioaddr_inter_desc inter_desc;
|
|
struct xioaddr_endpoint_desc endpoint_desc;
|
|
} ;
|
|
|
|
union xioaddr_descp {
|
|
struct xioaddr_common_desc *
|
|
common_desc;
|
|
int *tag; /* 0: endpoint addr; 1: inter addr */
|
|
struct xioaddr_inter_desc *inter_desc;
|
|
struct xioaddr_endpoint_desc *endpoint_desc;
|
|
} ;
|
|
|
|
|
|
/*!!! this to xio-sockd4.h */
|
|
struct socks4head {
|
|
uint8_t version;
|
|
uint8_t action;
|
|
uint16_t port;
|
|
uint32_t dest;
|
|
} ;
|
|
|
|
/* global XIO options/parameters */
|
|
typedef struct {
|
|
bool strictopts;
|
|
const char *pipesep;
|
|
const char *paramsep;
|
|
const char *optionsep;
|
|
char ip4portsep;
|
|
char ip6portsep; /* do not change, might be hardcoded somewhere! */
|
|
const char *syslogfac; /* syslog facility (only with mixed mode) */
|
|
char default_ip; /* default prot.fam for IP based listen ('4' or '6') */
|
|
char preferred_ip; /* preferred prot.fam. for name resolution ('0' for
|
|
unspecified, '4', or '6') */
|
|
char *reversechar;
|
|
char *chainsep;
|
|
size_t bufsiz;
|
|
bool verbose;
|
|
bool verbhex;
|
|
bool debug;
|
|
char logopt; /* y..syslog; s..stderr; f..file; m..mixed */
|
|
struct timeval total_timeout;/* when nothing happens, die after seconds */
|
|
struct timeval pollintv; /* with ignoreeof, reread after seconds */
|
|
struct timeval closwait; /* after close of x, die after seconds */
|
|
bool lefttoright; /* first addr ro, second addr wo */
|
|
bool righttoleft; /* first addr wo, second addr ro */
|
|
int pipetype; /* communication (pipe) type; 0: 2 unidirectional
|
|
socketpairs; 1: 2 pipes; 2: 1 socketpair */
|
|
} xioopts_t;
|
|
|
|
/* pack the description of a lock file */
|
|
typedef struct {
|
|
const char *lockfile; /* name of lockfile; NULL if no locking */
|
|
bool waitlock; /* dont't exit when already locked */
|
|
struct timespec intervall; /* polling intervall */
|
|
} xiolock_t;
|
|
|
|
#define MAXARGV 8
|
|
|
|
/* a non-dual file descriptor */
|
|
typedef struct single {
|
|
enum xiotag tag; /* see enum xiotag */
|
|
const union xioaddr_desc *addrdesc;
|
|
int flags;
|
|
/* until here, keep consistent with bipipe.common !!! */
|
|
#if WITH_RETRY
|
|
unsigned int retry; /* retry opening this many times */
|
|
bool forever; /* retry opening forever */
|
|
struct timespec intervall; /* wait so long between retries */
|
|
#endif /* WITH_RETRY */
|
|
bool ignoreeof; /* option ignoreeof; do not pass eof condition to app*/
|
|
int eof; /* 1..exec'd child has died, but no explicit eof
|
|
occurred
|
|
2..fd0 has reached EOF (definitely; never with
|
|
ignoreeof! */
|
|
size_t wsize; /* write always this size; 0..all available */
|
|
size_t readbytes; /* read only so many bytes; 0...unlimited */
|
|
size_t actbytes; /* so many bytes still to be read (when readbytes!=0)*/
|
|
xiolock_t lock; /* parameters of lockfile */
|
|
bool havelock; /* we are happy owner of the above lock */
|
|
/* until here, keep consistent with bipipe.dual ! */
|
|
int reverse; /* valid during parse and overload, before open:
|
|
will this (inter) address be integrated forward or
|
|
reverse? */
|
|
const union xioaddr_desc **addrdescs;
|
|
/* valid after parse, before overload:
|
|
the list of possible address descriptors derived
|
|
from addr keyword, one of which will be selected by
|
|
context and num of parameters */
|
|
int closing; /* 0..write channel is up, 1..just shutdown write ch.,
|
|
2..counting down closing timeout, 3..no more write
|
|
possible */
|
|
bool cool_write; /* downlevel EPIPE, ECONNRESET to notice */
|
|
int argc; /* number of fields in argv */
|
|
const char *argv[MAXARGV]; /* address keyword, required args */
|
|
struct opt *opts; /* the options of this address */
|
|
int lineterm; /* 0..dont touch; 1..CR; 2..CRNL on extern data */
|
|
int rfd; /* was fd1 */
|
|
int wfd; /* was fd2 */
|
|
pid_t subaddrpid; /* pid of subaddress (process handling next addr in
|
|
chain) */
|
|
int subaddrstat; /* state of subaddress process
|
|
0...no sub address process
|
|
1...running
|
|
-1...ended (aborted?) */
|
|
int subaddrexit; /* if subaddstat==-1: exit code of sub process */
|
|
bool opt_unlink_close; /* option unlink_close */
|
|
char *unlink_close; /* name of a symlink or unix socket to be removed */
|
|
int dtype;
|
|
int howtoshut; /* method for shutting down xfds */
|
|
int howtoclose; /* method for closing xfds */
|
|
#if _WITH_SOCKET
|
|
union sockaddr_union peersa;
|
|
socklen_t salen;
|
|
#endif /* _WITH_SOCKET */
|
|
#if WITH_TERMIOS
|
|
bool ttyvalid; /* the following struct is valid */
|
|
struct termios savetty; /* save orig tty settings for later restore */
|
|
#endif /* WITH_TERMIOS */
|
|
/*0 const char *name;*/ /* only with END_UNLINK */
|
|
struct { /* this was for exec only, now for embedded */
|
|
pid_t pid; /* child PID, with EXEC: */
|
|
int (*sigchild)(struct single *); /* callback after sigchild */
|
|
} child;
|
|
pid_t ppid; /* parent pid, only if we send it signals */
|
|
int escape; /* escape character; -1 for no escape */
|
|
bool actescape; /* escape character found in input data */
|
|
pthread_t subthread; /* thread handling next inter-addr in chain */
|
|
union {
|
|
#if 0
|
|
struct {
|
|
int fdout; /* use fd for output */
|
|
} bipipe;
|
|
#endif
|
|
#if _WITH_SOCKET
|
|
struct {
|
|
struct timeval connect_timeout; /* how long to hang in connect() */
|
|
union sockaddr_union la; /* local socket address */
|
|
bool null_eof; /* with dgram: empty packet means EOF */
|
|
bool dorange;
|
|
struct xiorange range; /* restrictions for peer address */
|
|
#if _WITH_IP4 || _WITH_IP6
|
|
struct {
|
|
unsigned int res_opts[2]; /* bits to be set in _res.options are
|
|
at [0], bits to be cleared are at [1] */
|
|
bool dosourceport;
|
|
uint16_t sourceport; /* host byte order */
|
|
bool lowport;
|
|
#if (WITH_TCP || WITH_UDP) && WITH_LIBWRAP
|
|
bool dolibwrap;
|
|
char *libwrapname;
|
|
char *tcpwrap_etc;
|
|
char *hosts_allow_table;
|
|
char *hosts_deny_table;
|
|
#endif
|
|
} ip;
|
|
#endif /* _WITH_IP4 || _WITH_IP6 */
|
|
} socket;
|
|
#endif /* _WITH_SOCKET */
|
|
struct {
|
|
pid_t pid; /* child PID, with EXEC: */
|
|
int fdout; /* use fd for output if two pipes */
|
|
} exec;
|
|
#if WITH_READLINE
|
|
struct {
|
|
char *history_file;
|
|
char *prompt; /* static prompt, passed to readline() */
|
|
size_t dynbytes; /* length of buffer for dynamic prompt */
|
|
char *dynprompt; /* the dynamic prompt */
|
|
char *dynend; /* current end of dynamic prompt */
|
|
#if HAVE_REGEX_H
|
|
bool hasnoecho; /* following regex is set */
|
|
regex_t noecho; /* if it matches the prompt, input is silent */
|
|
#endif
|
|
} readline;
|
|
#endif /* WITH_READLINE */
|
|
#if WITH_SOCKS4_SERVER
|
|
struct {
|
|
int state; /* state of socks4 protocol negotiation */
|
|
/* we cannot rely on all request data arriving at once */
|
|
struct socks4head head;
|
|
char *userid;
|
|
char *hostname; /* socks4a only */
|
|
/* the following structs are an experiment for future synchronization
|
|
mechanisms */
|
|
struct {
|
|
size_t canrecv;
|
|
size_t wantwrite;
|
|
void *inbuff;
|
|
size_t inbuflen; /* length of buffer */
|
|
size_t bytes; /* current bytes in buffer */
|
|
} proto;
|
|
struct {
|
|
size_t canrecv;
|
|
size_t wantwrite;
|
|
} peer_proto;
|
|
struct {
|
|
size_t canrecv;
|
|
size_t wantwrite;
|
|
int _errno;
|
|
} data;
|
|
struct {
|
|
size_t canrecv;
|
|
size_t wantwrite;
|
|
} peer_data;
|
|
} socks4d;
|
|
#endif /* WITH_SOCKS4_SERVER */
|
|
#if WITH_OPENSSL
|
|
struct {
|
|
struct timeval connect_timeout; /* how long to hang in connect() */
|
|
SSL *ssl;
|
|
SSL_CTX* ctx;
|
|
} openssl;
|
|
#endif /* WITH_OPENSSL */
|
|
#if WITH_TUN
|
|
struct {
|
|
short iff_opts[2]; /* ifr flags, using OFUNC_OFFSET_MASKS */
|
|
} tun;
|
|
#endif /* WITH_TUN */
|
|
#if _WITH_GZIP
|
|
struct {
|
|
gzFile in; /* for reading (uncompressing from stream to API) */
|
|
gzFile out; /* for writing (compressing from API to stream) */
|
|
int level;
|
|
} gzip;
|
|
#endif /* _WITH_GZIP */
|
|
} para;
|
|
} xiosingle_t;
|
|
|
|
/* rw: 0..read, 1..write, 2..r/w */
|
|
/* when implementing a new address type take care of following topics:
|
|
. be aware that xioopen_single is used for O_RDONLY, O_WRONLY, and O_RDWR data
|
|
. which options are allowed (option groups)
|
|
. implement application of all these options
|
|
. set FD_CLOEXEC on new file descriptors BEFORE the cloexec option might be
|
|
applied
|
|
.
|
|
*/
|
|
|
|
typedef union bipipe {
|
|
enum xiotag tag;
|
|
struct {
|
|
enum xiotag tag;
|
|
const union xioaddr_desc *addrdesc;
|
|
int flags;
|
|
} common;
|
|
struct single stream;
|
|
struct {
|
|
enum xiotag tag;
|
|
const union xioaddr_desc *addrdesc;
|
|
int flags; /* compatible to fcntl(.., F_GETFL, ..) */
|
|
#if WITH_RETRY
|
|
unsigned retry; /* retry opening this many times */
|
|
bool forever; /* retry opening forever */
|
|
struct timespec intervall; /* wait so long between retries */
|
|
#endif /* WITH_RETRY */
|
|
bool ignoreeof;
|
|
int eof; /* fd0 has reached EOF */
|
|
size_t wsize; /* write always this size; 0..all available */
|
|
size_t readbytes; /* read only so many bytes; 0...unlimited */
|
|
size_t actbytes; /* so many bytes still to be read */
|
|
xiolock_t lock; /* parameters of lockfile */
|
|
bool havelock; /* we are happy owner of the above lock */
|
|
/* until here, keep consistent with struct single ! */
|
|
xiosingle_t *stream[2]; /* input stream, output stream */
|
|
} dual;
|
|
} xiofile_t;
|
|
|
|
|
|
#define XIO_WRITABLE(s) (((s)->common.flags+1)&2)
|
|
#define XIO_READABLE(s) (((s)->common.flags+1)&1)
|
|
#define XIO_RDSTREAM(s) (((s)->tag==XIO_TAG_DUAL)?(s)->dual.stream[0]:&(s)->stream)
|
|
#define XIO_WRSTREAM(s) (((s)->tag==XIO_TAG_DUAL)?(s)->dual.stream[1]:&(s)->stream)
|
|
#define XIO_GETRDFD(s) (((s)->tag==XIO_TAG_DUAL)?(s)->dual.stream[0]->rfd:(s)->stream.rfd)
|
|
#define _XIO_GETWRFD(s) ((s)->wfd)
|
|
#define XIO_GETWRFD(s) (((s)->tag==XIO_TAG_DUAL)?_XIO_GETWRFD((s)->dual.stream[1]):_XIO_GETWRFD(&(s)->stream))
|
|
#define XIO_EOF(s) (XIO_RDSTREAM(s)->eof && !XIO_RDSTREAM(s)->ignoreeof)
|
|
|
|
typedef unsigned long flags_t;
|
|
|
|
union integral {
|
|
int u_bool;
|
|
uint8_t u_byte;
|
|
gid_t u_gidt;
|
|
int u_int;
|
|
long u_long;
|
|
#if HAVE_TYPE_LONGLONG
|
|
long long u_longlong;
|
|
#endif
|
|
double u_double;
|
|
mode_t u_modet;
|
|
short u_short;
|
|
size_t u_sizet;
|
|
char *u_string;
|
|
uid_t u_uidt;
|
|
unsigned int u_uint;
|
|
unsigned long u_ulong;
|
|
unsigned short u_ushort;
|
|
uint16_t u_2bytes;
|
|
void *u_ptr;
|
|
flags_t u_flag;
|
|
struct {
|
|
uint8_t *b_data;
|
|
size_t b_len;
|
|
} u_bin;
|
|
struct timeval u_timeval;
|
|
#if HAVE_STRUCT_LINGER
|
|
struct linger u_linger;
|
|
#endif /* HAVE_STRUCT_LINGER */
|
|
#if HAVE_STRUCT_TIMESPEC
|
|
struct timespec u_timespec;
|
|
#endif /* HAVE_STRUCT_TIMESPEC */
|
|
#if HAVE_STRUCT_IP_MREQ || HAVE_STRUCT_IP_MREQN
|
|
struct {
|
|
char *multiaddr;
|
|
char *param2; /* address, interface */
|
|
#if HAVE_STRUCT_IP_MREQN
|
|
char ifindex[IF_NAMESIZE+1];
|
|
#endif
|
|
} u_ip_mreq;
|
|
#endif
|
|
#if WITH_IP4
|
|
struct in_addr u_ip4addr;
|
|
#endif
|
|
} ;
|
|
|
|
/* some aliases */
|
|
#define u_off u_long /* please report when this causes problems */
|
|
|
|
#if HAVE_BASIC_OFF_T==3
|
|
# define u_off u_int
|
|
#elif HAVE_BASIC_OFF_T==5
|
|
# define u_off u_long
|
|
#else
|
|
# error "unexpected size of off_t, please report this as bug"
|
|
#endif
|
|
|
|
#if defined(HAVE_BASIC_OFF64_T) && HAVE_BASIC_OFF64_T
|
|
# if HAVE_BASIC_OFF64_T==5
|
|
# define u_off64 u_long
|
|
# elif HAVE_BASIC_OFF64_T==7
|
|
# define u_off64 u_longlong
|
|
# else
|
|
# error "unexpected size of off64_t, please report this as bug"
|
|
# endif
|
|
#endif /* defined(HAVE_BASIC_OFF64_T) && HAVE_BASIC_OFF64_T */
|
|
|
|
|
|
/* this handles option instances, for communication between subroutines */
|
|
struct opt {
|
|
const struct optdesc *desc;
|
|
union integral value;
|
|
union integral value2;
|
|
union integral value3;
|
|
} ;
|
|
|
|
/* with threading, the arguments indirectly passed to xioengine() */
|
|
struct threadarg_struct {
|
|
int rw; /* one of XIO_RDONLY, ... */
|
|
xiofile_t *xfd1;
|
|
xiofile_t *xfd2;
|
|
} ;
|
|
|
|
extern const char *PIPESEP;
|
|
extern xiofile_t *sock[XIO_MAXSOCK]; /*!!!*/
|
|
|
|
extern int num_child;
|
|
|
|
/* return values of xioopensingle */
|
|
#define STAT_OK 0
|
|
#define STAT_WARNING 1
|
|
#define STAT_EXIT 2
|
|
#define STAT_NOACTION 3 /* by retropt_* when option not applied */
|
|
#define STAT_RETRYNOW -1 /* only after timeouts useful ? */
|
|
#define STAT_RETRYLATER -2 /* address cannot be opened, but user might
|
|
change something in the filesystem etc. to
|
|
make this process succeed later. */
|
|
#define STAT_NORETRY -3 /* address syntax error, not implemented etc;
|
|
not even by external changes correctable */
|
|
|
|
extern int xioinitialize(int xioflags);
|
|
extern int xioinitialize2(void);
|
|
extern pid_t xio_fork(bool subchild, int level);
|
|
extern int xio_forked_inchild(void);
|
|
extern int xiosetopt(char what, const char *arg);
|
|
extern int xioinqopt(char what, char *arg, size_t n);
|
|
extern xiofile_t *xioopen(const char *args, int xioflags);
|
|
extern xiofile_t *xioopenx(const char *addr, int xioflags, int infd, int outfd);
|
|
extern int xiosocketpair2(int pf, int socktype, int protocol, int sv[2]);
|
|
extern int xiosocketpair3(xiofile_t **xfd1p, xiofile_t **xfd2p, int how, ...);
|
|
extern int xiopty(int useptmx, int *ttyfdp, int *ptyfdp);
|
|
extern int xiocommpair(int commtype, bool lefttoright, bool righttoleft,
|
|
int dual, xiofd_t *left, xiofd_t *right, ...);
|
|
|
|
extern int xioopensingle(char *addr, xiosingle_t *fd, int xioflags);
|
|
extern int xioopenhelp(FILE *of, int level);
|
|
|
|
/* must be outside function for use by childdied handler */
|
|
extern xiofile_t *xioallocfd(void);
|
|
extern void xiofreefd(xiofile_t *xfd);
|
|
|
|
extern int xiosetsigchild(xiofile_t *xfd, int (*callback)(struct single *));
|
|
extern int xiosetchilddied(void);
|
|
extern int xio_opt_signal(pid_t pid, int signum);
|
|
|
|
extern void *xioengine(void *thread_arg);
|
|
extern int _socat(xiofile_t *xfd1, xiofile_t *xfd2);
|
|
extern ssize_t xioread(xiofile_t *sock1, void *buff, size_t bufsiz);
|
|
extern ssize_t xiopending(xiofile_t *sock1);
|
|
extern ssize_t xiowrite(xiofile_t *sock1, const void *buff, size_t bufsiz);
|
|
extern int xiotransfer(xiofile_t *inpipe, xiofile_t *outpipe,
|
|
unsigned char **buff, size_t bufsiz, bool righttoleft);
|
|
extern int xioshutdown(xiofile_t *sock, int how);
|
|
|
|
extern int xioclose(xiofile_t *sock);
|
|
extern void xioexit(void);
|
|
|
|
extern int (*xiohook_newchild)(void); /* xio calls this function from a new child process */
|
|
extern int socat_sigchild(struct single *file);
|
|
|
|
|
|
extern xioopts_t xioopts, *xioparams;
|
|
|
|
|
|
#endif /* !defined(__xio_h_included) */
|