diff --git a/CHANGES b/CHANGES index 7d73860..80ab592 100644 --- a/CHANGES +++ b/CHANGES @@ -54,6 +54,9 @@ new features: new address options ipv6-tclass and ipv6-unicast-hops set the related socket options. + STREAMS (UNIX System V STREAMS) can be configured with the new address + options i-pop-all and i-push + corrections: some raw IP and UNIX datagram modes failed on BSD systems diff --git a/Makefile.in b/Makefile.in index d1c1483..fb6329e 100644 --- a/Makefile.in +++ b/Makefile.in @@ -51,7 +51,7 @@ XIOSRCS = xioinitialize.c xiohelp.c xioparam.c xiodiag.c xioopen.c xioopts.c \ xio-socks.c xio-proxy.c xio-udp.c \ xio-rawip.c \ xio-progcall.c xio-exec.c xio-system.c xio-termios.c xio-readline.c \ - xio-pty.c xio-openssl.c \ + xio-pty.c xio-openssl.c xio-streams.c\ xio-ascii.c xiolockfile.c xio-tcpwrap.c xio-ext2.c xio-tun.c XIOOBJS = $(XIOSRCS:.c=.o) UTLSRCS = error.c dalan.c procan.c procan-cdefs.c hostan.c fdname.c sysutils.c utils.c nestlex.c @FILAN@ @SYCLS@ @SSLCLS@ @@ -69,7 +69,7 @@ HFILES = sycls.h sslcls.h error.h dalan.h procan.h filan.h hostan.h sysincludes. xio-ipapp.h xio-tcp.h xio-udp.h xio-sctp.h \ xio-socks.h xio-proxy.h xio-progcall.h xio-exec.h \ xio-system.h xio-termios.h xio-readline.h \ - xio-pty.h xio-openssl.h \ + xio-pty.h xio-openssl.h xio-streams.h \ xio-ascii.h xiolockfile.h xio-tcpwrap.h xio-ext2.h xio-tun.h diff --git a/config.h.in b/config.h.in index 2965536..ea26d95 100644 --- a/config.h.in +++ b/config.h.in @@ -490,6 +490,7 @@ #undef WITH_PTY #undef WITH_EXT2 #undef WITH_OPENSSL +#define WITH_STREAMS 1 #undef WITH_FIPS #undef OPENSSL_FIPS #undef WITH_LIBWRAP diff --git a/doc/socat.yo b/doc/socat.yo index 2153dc1..ef39d84 100644 --- a/doc/socat.yo +++ b/doc/socat.yo @@ -2512,6 +2512,13 @@ label(OPTION_VTDLY)dit(bf(tt(vtdly=))) label(OPTION_WERASE)dit(bf(tt(werase=))) label(OPTION_XCASE)dit(bf(tt(xcase=))) label(OPTION_XTABS)dit(bf(tt(xtabs))) +label(OPTION_I_POP_ALL)dit(bf(tt(i-pop-all))) + With UNIX System V STREAMS, removes all drivers from the stack. +label(OPTION_I_PUSH)dit(bf(tt(i-push=))) + With UNIX System V STREAMS, pushes the driver (module) with the given name + (link(string)(TYPE_STRING)) onto the stack. For example, to make sure that a + character device on Solaris supports termios etc, use the following options: + tt(i-pop-all,i-push=ptem,i-push=ldterm,i-push=ttcompat) enddit() startdit()enddit()nl() diff --git a/filan.c b/filan.c index 0296074..246c9d3 100644 --- a/filan.c +++ b/filan.c @@ -26,7 +26,9 @@ struct sockopt { char *name; }; -/* dirty workaround so we dont get an error on AIX when getting linked with +static int filan_streams_analyze(int fd, FILE *outfile); + +/* dirty workaround so we dont get an error on AIX when being linked with libwrap */ int allow_severity, deny_severity; @@ -353,6 +355,9 @@ int filan_stat( , outfile); } + /* ever heard of POSIX streams? here we handle these */ + filan_streams_analyze(statfd, outfile); + /* now see for type specific infos */ if (statfd >= 0) { /*!indent */ switch (buf->st_mode&S_IFMT) { @@ -408,6 +413,48 @@ int devinfo(int fd) { #endif +/* returns 0 on success (not a stream descriptor, or no module) + returns <0 on failure */ +static int filan_streams_analyze(int fd, FILE *outfile) { +#ifdef I_LIST +# define SL_NMODS 8 /* max number of module names we can store */ + struct str_list modnames; + int i; + + if (!isastream(fd)) { + fprintf(outfile, "\t(no STREAMS modules)"); + return 0; + } +#if 0 /* uncomment for debugging */ + fprintf(outfile, "\tfind=%d", ioctl(fd, I_FIND, "ldterm")); +#endif + modnames.sl_nmods = ioctl(fd, I_LIST, 0); + if (modnames.sl_nmods < 0) { + fprintf(stderr, "ioctl(%d, I_LIST, 0): %s\n", fd, strerror(errno)); + return -1; + } + modnames.sl_modlist = Malloc(modnames.sl_nmods*(sizeof(struct str_mlist))); + if (modnames.sl_modlist == NULL) { + fprintf(stderr, "out of memory\n"); + return -1; + } + if (ioctl(fd, I_LIST, &modnames) < 0) { + fprintf(stderr, "ioctl(%d, I_LIST, %p): %s\n", + fd, &modnames, strerror(errno)); + free(modnames.sl_modlist); + return -1; + } + fprintf(outfile, "\tSTREAMS: "); + for (i = 0; i < modnames.sl_nmods; ++i) { + fprintf(outfile, "\"%s\"", modnames.sl_modlist[i].l_name); + if (i+1 < modnames.sl_nmods) fputc(',', outfile); + } + free(modnames.sl_modlist); +#endif /* defined(I_LIST) */ + return 0; +} + + /* character device analysis */ int cdevan(int fd, FILE *outfile) { int ret; diff --git a/xio-fd.c b/xio-fd.c index 9fc1d57..53d6415 100644 --- a/xio-fd.c +++ b/xio-fd.c @@ -82,3 +82,8 @@ const struct optdesc opt_ioctl_int = { "ioctl-int", NULL, OPT_IOCTL_I const struct optdesc opt_ioctl_intp = { "ioctl-intp", NULL, OPT_IOCTL_INTP, GROUP_FD, PH_FD, TYPE_INT_INTP, OFUNC_IOCTL_GENERIC, 0, 0, 0 }; const struct optdesc opt_ioctl_bin = { "ioctl-bin", NULL, OPT_IOCTL_BIN, GROUP_FD, PH_FD, TYPE_INT_BIN, OFUNC_IOCTL_GENERIC, 0, 0, 0 }; const struct optdesc opt_ioctl_string = { "ioctl-string",NULL, OPT_IOCTL_STRING,GROUP_FD, PH_FD, TYPE_INT_STRING,OFUNC_IOCTL_GENERIC, 0, 0, 0 }; + +/* POSIX STREAMS */ +#define ENABLE_OPTIONS +#include "xio-streams.c" +#undef ENABLE_OPTIONS diff --git a/xio-fd.h b/xio-fd.h index a301b4e..d664212 100644 --- a/xio-fd.h +++ b/xio-fd.h @@ -42,5 +42,6 @@ extern const struct optdesc opt_f_setlk_wr; extern const struct optdesc opt_f_setlkw_wr; extern const struct optdesc opt_cool_write; extern const struct optdesc opt_end_close; +extern const struct optdesc opt_streams_i_push; #endif /* !defined(__xio_fd_h_included) */ diff --git a/xio-streams.c b/xio-streams.c new file mode 100644 index 0000000..910b53e --- /dev/null +++ b/xio-streams.c @@ -0,0 +1,79 @@ +/* source: xio-streams.c */ +/* Copyright Gerhard Rieger 2008 */ +/* Published under the GNU General Public License V.2, see file COPYING */ + +/* this file contains definitions and functions for handling POSIX STREAMS */ + +/* with this source file a new experimental approach is being introduced: + normally when adding a new option at least four existing files have to be + adapted; this is similar for new address types. + + in the future i would like to have a more automatic assembling of socat from + topic oriented source files. this should make integration and control of + contributions more easy. + + all code of a new topic - address and option definitions, open code, option + handing code, ev.parser code, etc. should go into one source file. the + selection of the desired code parts during the compilation is done by + setting cpp defines. + + in the same was all public declarations should go in one header (.h) file. +*/ + +/* do not compile this file directly but include it from other .c files. with + CPP defines you select one part you want to really get included: + + ENABLE_OPTIONS: activate the definition of the address option records + ENABLE_APPLYOPTS: C code that applies the address option passed in opt +*/ + +#ifdef ENABLE_OPTIONS + +#ifdef I_POP +const struct optdesc opt_streams_i_pop_all = { "streams-i-pop-all", "pop-all", OPT_STREAMS_I_POP_ALL, GROUP_FD, PH_FD, TYPE_BOOL, OFUNC_STREAMS_I_POP_ALL, 0, 0 }; +#endif +#ifdef I_PUSH +const struct optdesc opt_streams_i_push = { "streams-i-push", "push", OPT_STREAMS_I_PUSH, GROUP_FD, PH_FD, TYPE_STRING, OFUNC_STREAMS_I_PUSH, 0, 0 }; +#endif + +#elif defined(ENABLE_APPLYOPT) + +#if 0 +void dummy(void) { + if (0) { { ; +#endif +#ifdef I_POP + } else if (opt->desc->func == OFUNC_STREAMS_I_POP_ALL) { + while (Ioctl(fd, I_POP, 0) >= 0) { + Warn2("ioctl(%d, I_POP, 0): %s", fd, strerror(errno)); + } +#endif +#ifdef I_PUSH + } else if (opt->desc->func == OFUNC_STREAMS_I_PUSH) { + if (Ioctl(fd, I_PUSH, opt->value.u_string) < 0) { + Warn3("ioctl(%d, I_PUSH, \"%s\"): %s", + fd, opt->value.u_string, strerror(errno)); + opt->desc = ODESC_ERROR; ++opt; continue; + } +#endif +#if 0 +} } } +#endif + +#else /* !defined(ENABLE_APPLYOPT) */ + +#include "xiosysincludes.h" +#if WITH_STREAMS /* make this address configure dependend */ +#include "xioopen.h" + +#include "xio-fd.h" +#include "xio-socket.h" /* _xioopen_connect() */ +#include "xio-listen.h" +#include "xio-ipapp.h" +#include "xio-openssl.h" + + + +#endif /* WITH_STREAMS */ + +#endif /* !defined(ENABLE_OPTIONS) */ diff --git a/xio-streams.h b/xio-streams.h new file mode 100644 index 0000000..bc1bdbe --- /dev/null +++ b/xio-streams.h @@ -0,0 +1,40 @@ +/* source: xio-streams.h */ +/* Copyright Gerhard Rieger 2008 */ +/* Published under the GNU General Public License V.2, see file COPYING */ + +/* when including this file select one part that you need by defining the + appropriate CPP define: + + (none): standard define, variable, and function declarations + ENABLE_OPTCODE: option codes for use in enum e_optcode + ENABLE_OFUNC: option functions for use in enum e_func +*/ + +#ifdef ENABLE_OPTCODE + +#if 0 +enum { /* make syntax feature of editors cooperative */ +#endif + OPT_STREAMS_I_POP_ALL, /* with POSIX STREAMS */ + OPT_STREAMS_I_PUSH, /* with POSIX STREAMS */ +#if 0 +} ; +#endif + +#elif defined(ENABLE_OFUNC) + +#if 0 +enum { /* make syntax feature of editors cooperative */ +#endif + OFUNC_STREAMS_I_POP_ALL, + OFUNC_STREAMS_I_PUSH, +#if 0 +} ; +#endif + +#else /* normal declarations */ + +extern const struct optdesc opt_streams_i_pop_all; +extern const struct optdesc opt_streams_i_push; + +#endif diff --git a/xiomodes.h b/xiomodes.h index 999c4d4..602eab0 100644 --- a/xiomodes.h +++ b/xiomodes.h @@ -43,5 +43,6 @@ #include "xio-tcpwrap.h" #include "xio-ext2.h" #include "xio-tun.h" +#include "xio-streams.h" #endif /* !defined(__xiomodes_h_included) */ diff --git a/xioopts.c b/xioopts.c index 9d9e88d..ab6de76 100644 --- a/xioopts.c +++ b/xioopts.c @@ -551,6 +551,12 @@ const struct optname optionnames[] = { #endif IF_TERMIOS("hup", &opt_hupcl) IF_TERMIOS("hupcl", &opt_hupcl) +#ifdef I_POP + IF_ANY ("i-pop-all", &opt_streams_i_pop_all) +#endif +#ifdef I_PUSH + IF_ANY ("i-push", &opt_streams_i_push) +#endif IF_TERMIOS("icanon", &opt_icanon) IF_TERMIOS("icrnl", &opt_icrnl) IF_TERMIOS("iexten", &opt_iexten) @@ -1085,6 +1091,9 @@ const struct optname optionnames[] = { IF_IP ("pktopts", &opt_ip_pktoptions) #endif IF_TUN ("pointopoint", &opt_iff_pointopoint) +#ifdef I_POP + IF_ANY ("pop-all", &opt_streams_i_pop_all) +#endif /*IF_IPAPP("port", &opt_port)*/ IF_TUN ("portsel", &opt_iff_portsel) #if HAVE_RESOLV_H @@ -1122,6 +1131,9 @@ const struct optname optionnames[] = { IF_PTY ("pty-intervall", &opt_pty_intervall) IF_PTY ("pty-wait-slave", &opt_pty_wait_slave) #endif /* HAVE_PTY && HAVE_POLL */ +#ifdef I_PUSH + IF_ANY ("push", &opt_streams_i_push) +#endif #ifdef TCP_QUICKACK IF_TCP ("quickack", &opt_tcp_quickack) #endif @@ -1401,6 +1413,12 @@ const struct optname optionnames[] = { IF_TCP ("stdurg", &opt_tcp_stdurg) #endif IF_TERMIOS("stop", &opt_vstop) +#ifdef I_POP + IF_ANY ("streams-i-pop-all", &opt_streams_i_pop_all) +#endif +#ifdef I_PUSH + IF_ANY ("streams-i-push", &opt_streams_i_push) +#endif IF_ANY ("su", &opt_substuser) IF_ANY ("su-d", &opt_substuser_delayed) IF_ANY ("substuser", &opt_substuser) @@ -2797,7 +2815,7 @@ int retropt_bind(struct opt *opts, /* note: not all options can be applied this way (e.g. OFUNC_SPEC with PH_OPEN) implemented are: OFUNC_FCNTL, OFUNC_SOCKOPT (probably not all types), OFUNC_TERMIOS_FLAG, OFUNC_TERMIOS_PATTERN, and some OFUNC_SPEC */ -int applyopts(int fd, struct opt *opts, unsigned int phase) { +int applyopts(int fd, struct opt *opts, enum e_phase phase) { struct opt *opt; opt = opts; while (opt && opt->desc != ODESC_END) { @@ -3574,6 +3592,12 @@ int applyopts(int fd, struct opt *opts, unsigned int phase) { #endif /* WITH_TERMIOS */ +#if WITH_STREAMS +#define ENABLE_APPLYOPT +#include "xio-streams.c" +#undef ENABLE_APPLYOPT +#endif /* WITH_STREAMS */ + } else { /*Error1("applyopts(): function %d not implemented", opt->desc->func);*/ diff --git a/xioopts.h b/xioopts.h index 2a02362..fda6718 100644 --- a/xioopts.h +++ b/xioopts.h @@ -105,7 +105,10 @@ enum e_func { OFUNC_TERMIOS_SPEC, /* termios combined modes */ OFUNC_SIGNAL, /* a signal that should be passed to child process */ OFUNC_RESOLVER, /* a bit position used on _res.options */ - OFUNC_IFFLAG /* interface flag: locical-or a 1bit mask */ + OFUNC_IFFLAG, /* interface flag: locical-or a 1bit mask */ +# define ENABLE_OFUNC +# include "xio-streams.h" /* push a POSIX STREAMS module */ +# undef ENABLE_OFUNC } ; /* for simpler handling of option-to-connection-type relations we define @@ -689,6 +692,9 @@ enum e_optcode { #endif OPT_SOURCEPORT, OPT_STDERR, /* with exec, system */ +# define ENABLE_OPTCODE +# include "xio-streams.h" +# undef ENABLE_OPTCODE OPT_SUBSTUSER, OPT_SUBSTUSER_DELAYED, OPT_SYMBOLIC_LINK, /* with pty */ @@ -899,7 +905,7 @@ extern int retropt_bind(struct opt *opts, int feats, /* TCP etc: 1..address allowed, 3..address and port allowed */ unsigned long res_opts0, unsigned long res_opts1); -extern int applyopts(int fd, struct opt *opts, unsigned int phase); +extern int applyopts(int fd, struct opt *opts, enum e_phase phase); extern int applyopts2(int fd, struct opt *opts, unsigned int from, unsigned int to); extern int applyopts_flags(struct opt *opts, int group, flags_t *result);