| /* source: xioopts.c */ |
| /* Copyright Gerhard Rieger and contributors (see file CHANGES) */ |
| /* Published under the GNU General Public License V.2, see file COPYING */ |
| |
| /* this file contains the source for address options handling */ |
| |
| #include "xiosysincludes.h" |
| #include "xioopen.h" |
| #include "xio-unix.h" |
| #include "xio-ip.h" |
| |
| #include "xiomodes.h" |
| #include "xiolockfile.h" |
| #include "nestlex.h" |
| |
| bool xioopts_ignoregroups; |
| |
| #define IF_ANY(a,b) {a,b}, |
| |
| #if WITH_NAMED |
| # define IF_NAMED(a,b) {a,b}, |
| #else |
| # define IF_NAMED(a,b) |
| #endif |
| |
| #if WITH_PIPE || WITH_GOPEN |
| # define IF_OPEN(a,b) {a,b}, |
| #else |
| # define IF_OPEN(a,b) |
| #endif |
| |
| #if WITH_TERMIOS |
| # define IF_TERMIOS(a,b) {a,b}, |
| #else |
| # define IF_TERMIOS(a,b) |
| #endif |
| |
| #if WITH_EXEC |
| # define IF_EXEC(a,b) {a,b}, |
| #else |
| # define IF_EXEC(a,b) |
| #endif |
| |
| #if _WITH_SOCKET |
| # define IF_SOCKET(a,b) {a,b}, |
| #else |
| # define IF_SOCKET(a,b) |
| #endif |
| |
| #if WITH_LISTEN |
| # define IF_LISTEN(a,b) {a,b}, |
| #else |
| # define IF_LISTEN(a,b) |
| #endif |
| |
| #if (WITH_UDP || WITH_TCP) && WITH_LISTEN |
| # define IF_RANGE(a,b) {a,b}, |
| #else |
| # define IF_RANGE(a,b) |
| #endif |
| |
| #if WITH_IP4 || WITH_IP6 |
| # define IF_IP(a,b) {a,b}, |
| #else |
| # define IF_IP(a,b) |
| #endif |
| |
| #if WITH_IP6 |
| # define IF_IP6(a,b) {a,b}, |
| #else |
| # define IF_IP6(a,b) |
| #endif |
| |
| #if WITH_TCP|WITH_UDP |
| # define IF_IPAPP(a,b) {a,b}, |
| #else |
| # define IF_IPAPP(a,b) |
| #endif |
| |
| #if WITH_TCP |
| # define IF_TCP(a,b) {a,b}, |
| #else |
| # define IF_TCP(a,b) |
| #endif |
| |
| #if WITH_UDP |
| # define IF_UDP(a,b) {a,b}, |
| #else |
| # define IF_UDP(a,b) |
| #endif |
| |
| #if WITH_SCTP |
| # define IF_SCTP(a,b) {a,b}, |
| #else |
| # define IF_SCTP(a,b) |
| #endif |
| |
| #if WITH_SOCKS4 |
| # define IF_SOCKS4(a,b) {a,b}, |
| #else |
| # define IF_SOCKS4(a,b) |
| #endif |
| |
| #if WITH_PROXY |
| # define IF_PROXY(a,b) {a,b}, |
| #else |
| # define IF_PROXY(a,b) |
| #endif |
| |
| #if WITH_READLINE |
| # define IF_READLINE(a,b) {a,b}, |
| #else |
| # define IF_READLINE(a,b) |
| #endif |
| |
| #if WITH_PTY |
| # define IF_PTY(a,b) {a,b}, |
| #else |
| # define IF_PTY(a,b) |
| #endif |
| |
| #if WITH_OPENSSL |
| # define IF_OPENSSL(a,b) {a,b}, |
| #else |
| # define IF_OPENSSL(a,b) |
| #endif |
| |
| #if WITH_TUN |
| # define IF_TUN(a,b) {a,b}, |
| #else |
| # define IF_TUN(a,b) |
| #endif |
| |
| #if WITH_UNIX |
| # define IF_UNIX(a,b) {a,b}, |
| #else |
| # define IF_UNIX(a,b) |
| #endif |
| |
| #if WITH_RETRY |
| # define IF_RETRY(a,b) {a,b}, |
| #else |
| # define IF_RETRY(a,b) |
| #endif |
| |
| |
| static int applyopt_offset(struct single *xfd, struct opt *opt); |
| |
| |
| /* address options - keep this array strictly alphabetically sorted for |
| binary search! */ |
| /* NULL terminated */ |
| const struct optname optionnames[] = { |
| #if HAVE_RESOLV_H && WITH_RES_AAONLY |
| IF_IP ("aaonly", &opt_res_aaonly) |
| #endif |
| #ifdef TCP_ABORT_THRESHOLD /* HP_UX */ |
| IF_TCP ("abort-threshold", &opt_tcp_abort_threshold) |
| #endif |
| IF_LISTEN ("accept-timeout", &opt_accept_timeout) |
| #ifdef SO_ACCEPTCONN /* AIX433 */ |
| IF_SOCKET ("acceptconn", &opt_so_acceptconn) |
| #endif /* SO_ACCEPTCONN */ |
| #ifdef IP_ADD_MEMBERSHIP |
| IF_IP ("add-membership", &opt_ip_add_membership) |
| #endif |
| #if defined(HAVE_STRUCT_IP_MREQ_SOURCE) && defined(IP_ADD_SOURCE_MEMBERSHIP) |
| IF_IP ("add-source-membership", &opt_ip_add_source_membership) |
| #endif |
| IF_TUN ("allmulti", &opt_iff_allmulti) |
| #if WITH_LIBWRAP && defined(HAVE_HOSTS_ALLOW_TABLE) |
| IF_IPAPP ("allow-table", &opt_tcpwrap_hosts_allow_table) |
| #endif |
| IF_ANY ("append", &opt_append) |
| #ifdef O_ASYNC |
| IF_ANY ("async", &opt_async) |
| #endif |
| #ifdef SO_ATTACH_FILTER |
| IF_SOCKET ("attach-filter", &opt_so_attach_filter) |
| IF_SOCKET ("attachfilter", &opt_so_attach_filter) |
| #endif |
| #ifdef SO_AUDIT /* AIX 4.3.3 */ |
| IF_SOCKET ("audit", &opt_so_audit) |
| #endif /* SO_AUDIT */ |
| #ifdef IPV6_AUTHHDR |
| IF_IP6 ("authhdr", &opt_ipv6_authhdr) |
| #endif |
| IF_TUN ("automedia", &opt_iff_automedia) |
| #ifdef CBAUD |
| IF_TERMIOS("b0", &opt_b0) |
| #ifdef B1000000 |
| IF_TERMIOS("b1000000", &opt_b1000000) |
| #endif |
| IF_TERMIOS("b110", &opt_b110) |
| #ifdef B115200 |
| IF_TERMIOS("b115200", &opt_b115200) |
| #endif |
| #ifdef B1152000 |
| IF_TERMIOS("b1152000", &opt_b1152000) |
| #endif |
| IF_TERMIOS("b1200", &opt_b1200) |
| IF_TERMIOS("b134", &opt_b134) |
| IF_TERMIOS("b150", &opt_b150) |
| #ifdef B1500000 |
| IF_TERMIOS("b1500000", &opt_b1500000) |
| #endif |
| IF_TERMIOS("b1800", &opt_b1800) |
| IF_TERMIOS("b19200", &opt_b19200) |
| IF_TERMIOS("b200", &opt_b200) |
| #ifdef B2000000 |
| IF_TERMIOS("b2000000", &opt_b2000000) |
| #endif |
| #ifdef B230400 |
| IF_TERMIOS("b230400", &opt_b230400) |
| #endif |
| IF_TERMIOS("b2400", &opt_b2400) |
| #ifdef B2500000 |
| IF_TERMIOS("b2500000", &opt_b2500000) |
| #endif |
| IF_TERMIOS("b300", &opt_b300) |
| #ifdef B3000000 |
| IF_TERMIOS("b3000000", &opt_b3000000) |
| #endif |
| #ifdef B3500000 |
| IF_TERMIOS("b3500000", &opt_b3500000) |
| #endif |
| #ifdef B3600 /* HP-UX */ |
| IF_TERMIOS("b3600", &opt_b3600) |
| #endif |
| IF_TERMIOS("b38400", &opt_b38400) |
| #ifdef B4000000 |
| IF_TERMIOS("b4000000", &opt_b4000000) |
| #endif |
| #ifdef B460800 |
| IF_TERMIOS("b460800", &opt_b460800) |
| #endif |
| IF_TERMIOS("b4800", &opt_b4800) |
| IF_TERMIOS("b50", &opt_b50) |
| #ifdef B500000 |
| IF_TERMIOS("b500000", &opt_b500000) |
| #endif |
| #ifdef B57600 |
| IF_TERMIOS("b57600", &opt_b57600) |
| #endif |
| #ifdef B576000 |
| IF_TERMIOS("b576000", &opt_b576000) |
| #endif |
| IF_TERMIOS("b600", &opt_b600) |
| #ifdef B7200 /* HP-UX */ |
| IF_TERMIOS("b7200", &opt_b7200) |
| #endif |
| IF_TERMIOS("b75", &opt_b75) |
| #ifdef B900 /* HP-UX */ |
| IF_TERMIOS("b900", &opt_b900) |
| #endif |
| #ifdef B921600 |
| IF_TERMIOS("b921600", &opt_b921600) |
| #endif |
| IF_TERMIOS("b9600", &opt_b9600) |
| #endif /* defined(CBAUD) */ |
| IF_LISTEN ("backlog", &opt_backlog) |
| #ifdef O_BINARY |
| IF_OPEN ("bin", &opt_o_binary) |
| IF_OPEN ("binary", &opt_o_binary) |
| #endif |
| IF_SOCKET ("bind", &opt_bind) |
| #ifdef SO_BINDTODEVICE |
| IF_SOCKET ("bindtodevice", &opt_so_bindtodevice) |
| #endif |
| IF_TERMIOS("brkint", &opt_brkint) |
| IF_SOCKET ("broadcast", &opt_so_broadcast) |
| #ifdef BSDLY |
| # ifdef BS0 |
| IF_TERMIOS("bs0", &opt_bs0) |
| # endif |
| # ifdef BS1 |
| IF_TERMIOS("bs1", &opt_bs1) |
| # endif |
| #endif |
| #ifdef SO_BSDCOMPAT |
| IF_SOCKET ("bsdcompat", &opt_so_bsdcompat) |
| #endif |
| #ifdef BSDLY |
| IF_TERMIOS("bsdly", &opt_bsdly) |
| #endif |
| IF_ANY ("bytes", &opt_readbytes) |
| IF_OPENSSL("cafile", &opt_openssl_cafile) |
| IF_OPENSSL("capath", &opt_openssl_capath) |
| IF_OPENSSL("cert", &opt_openssl_certificate) |
| IF_OPENSSL("certificate", &opt_openssl_certificate) |
| IF_TERMIOS("cfmakeraw", &opt_termios_cfmakeraw) |
| IF_ANY ("chroot", &opt_chroot) |
| IF_ANY ("chroot-early", &opt_chroot_early) |
| /*IF_TERMIOS("cibaud", &opt_cibaud)*/ |
| IF_OPENSSL("cipher", &opt_openssl_cipherlist) |
| IF_OPENSSL("cipherlist", &opt_openssl_cipherlist) |
| IF_OPENSSL("ciphers", &opt_openssl_cipherlist) |
| #ifdef SO_CKSUMRECV |
| IF_SOCKET ("cksumrecv", &opt_so_cksumrecv) |
| #endif /* SO_CKSUMRECV */ |
| /*IF_NAMED ("cleanup", &opt_cleanup)*/ |
| IF_TERMIOS("clocal", &opt_clocal) |
| IF_ANY ("cloexec", &opt_cloexec) |
| IF_ANY ("close", &opt_end_close) |
| IF_OPENSSL("cn", &opt_openssl_commonname) |
| IF_OPENSSL("commonname", &opt_openssl_commonname) |
| #if WITH_FS && defined(FS_COMPR_FL) |
| IF_ANY ("compr", &opt_fs_compr) |
| #endif |
| #if OPENSSL_VERSION_NUMBER >= 0x00908000L && !defined(OPENSSL_NO_COMP) |
| IF_OPENSSL("compress", &opt_openssl_compress) |
| #endif |
| #ifdef TCP_CONN_ABORT_THRESHOLD /* HP_UX */ |
| IF_TCP ("conn-abort-threshold", &opt_tcp_conn_abort_threshold) |
| #endif |
| IF_SOCKET ("connect-timeout", &opt_connect_timeout) |
| IF_LISTEN ("cool-write", &opt_cool_write) |
| IF_LISTEN ("coolwrite", &opt_cool_write) |
| #ifdef TCP_CORK |
| IF_TCP ("cork", &opt_tcp_cork) |
| #endif |
| IF_ANY ("cr", &opt_cr) |
| #ifdef CRDLY |
| # ifdef CR0 |
| IF_TERMIOS("cr0", &opt_cr0) |
| # endif |
| # ifdef CR1 |
| IF_TERMIOS("cr1", &opt_cr1) |
| # endif |
| # ifdef CR2 |
| IF_TERMIOS("cr2", &opt_cr2) |
| # endif |
| # ifdef CR3 |
| IF_TERMIOS("cr3", &opt_cr3) |
| # endif |
| # if CRDLY_SHIFT >= 0 |
| IF_TERMIOS("crdly", &opt_crdly) |
| # endif |
| #endif /* defined(CRDLY) */ |
| IF_TERMIOS("cread", &opt_cread) |
| IF_OPEN ("creat", &opt_o_create) |
| IF_OPEN ("create", &opt_o_create) |
| IF_ANY ("crlf", &opt_crnl) |
| IF_ANY ("crnl", &opt_crnl) |
| IF_TERMIOS("crterase", &opt_echoe) |
| IF_TERMIOS("crtkill", &opt_echoke) |
| #ifdef CRTSCTS |
| IF_TERMIOS("crtscts", &opt_crtscts) |
| #endif |
| IF_TERMIOS("cs5", &opt_cs5) |
| IF_TERMIOS("cs6", &opt_cs6) |
| IF_TERMIOS("cs7", &opt_cs7) |
| IF_TERMIOS("cs8", &opt_cs8) |
| #if CSIZE_SHIFT >= 0 |
| IF_TERMIOS("csize", &opt_csize) |
| #endif |
| IF_TERMIOS("cstopb", &opt_cstopb) |
| IF_TERMIOS("ctlecho", &opt_echoctl) |
| IF_TERMIOS("ctty", &opt_tiocsctty) |
| IF_EXEC ("dash", &opt_dash) |
| IF_SOCKET ("debug", &opt_so_debug) |
| /*IF_IP ("debug", &opt_res_debug)*/ |
| #ifdef O_DEFER |
| IF_OPEN ("defer", &opt_o_defer) |
| #endif |
| #ifdef TCP_DEFER_ACCEPT /* Linux 2.4.0 */ |
| IF_TCP ("defer-accept", &opt_tcp_defer_accept) |
| #endif |
| #if HAVE_RESOLV_H |
| IF_IP ("defnames", &opt_res_defnames) |
| #endif /* HAVE_RESOLV_H */ |
| #ifdef O_DELAY |
| IF_OPEN ("delay", &opt_o_delay) |
| #endif |
| IF_NAMED ("delete", &opt_unlink) |
| #if WITH_LIBWRAP && defined(HAVE_HOSTS_DENY_TABLE) |
| IF_IPAPP ("deny-table", &opt_tcpwrap_hosts_deny_table) |
| #endif |
| #ifdef SO_DETACH_FILTER |
| IF_SOCKET ("detach-filter", &opt_so_detach_filter) |
| IF_SOCKET ("detachfilter", &opt_so_detach_filter) |
| #endif |
| #ifdef SO_DGRAM_ERRIND |
| IF_SOCKET ("dgram-errind", &opt_so_dgram_errind) |
| IF_SOCKET ("dgramerrind", &opt_so_dgram_errind) |
| #endif |
| IF_OPENSSL("dh", &opt_openssl_dhparam) |
| IF_OPENSSL("dhparam", &opt_openssl_dhparam) |
| IF_OPENSSL("dhparams", &opt_openssl_dhparam) |
| #ifdef O_DIRECT |
| IF_OPEN ("direct", &opt_o_direct) |
| #endif |
| #ifdef O_DIRECTORY |
| IF_OPEN ("directory", &opt_o_directory) |
| #endif |
| #if WITH_FS && defined(FS_DIRSYNC_FL) |
| IF_ANY ("dirsync", &opt_fs_dirsync) |
| #endif |
| #ifdef VDISCARD |
| IF_TERMIOS("discard", &opt_vdiscard) |
| #endif |
| #if HAVE_RESOLV_H |
| IF_IP ("dnsrch", &opt_res_dnsrch) |
| #endif /* HAVE_RESOLV_H */ |
| #ifdef SO_DONTLINGER |
| IF_SOCKET ("dontlinger", &opt_so_dontlinger) |
| #endif |
| IF_SOCKET ("dontroute", &opt_so_dontroute) |
| #ifdef IPV6_DSTOPTS |
| IF_IP6 ("dstopts", &opt_ipv6_dstopts) |
| #endif |
| #ifdef VDSUSP /* HP-UX */ |
| IF_TERMIOS("dsusp", &opt_vdsusp) |
| #endif |
| #ifdef O_DSYNC |
| IF_OPEN ("dsync", &opt_o_dsync) |
| #endif |
| IF_TERMIOS("echo", &opt_echo) |
| IF_TERMIOS("echoctl", &opt_echoctl) |
| IF_TERMIOS("echoe", &opt_echoe) |
| IF_TERMIOS("echok", &opt_echok) |
| IF_TERMIOS("echoke", &opt_echoke) |
| IF_TERMIOS("echonl", &opt_echonl) |
| #ifdef ECHOPRT |
| IF_TERMIOS("echoprt", &opt_echoprt) |
| #endif |
| IF_OPENSSL("egd", &opt_openssl_egd) |
| IF_ANY ("end-close", &opt_end_close) |
| IF_TERMIOS("eof", &opt_veof) |
| IF_TERMIOS("eol", &opt_veol) |
| IF_TERMIOS("eol2", &opt_veol2) |
| IF_TERMIOS("erase", &opt_verase) |
| IF_SOCKET ("error", &opt_so_error) |
| IF_ANY ("escape", &opt_escape) |
| IF_OPEN ("excl", &opt_o_excl) |
| #if WITH_FS && defined(FS_APPEND_FL) |
| IF_ANY ("ext2-append", &opt_fs_append) |
| #endif |
| #if WITH_FS && defined(FS_COMPR_FL) |
| IF_ANY ("ext2-compr", &opt_fs_compr) |
| #endif |
| #if WITH_FS && defined(FS_DIRSYNC_FL) |
| IF_ANY ("ext2-dirsync", &opt_fs_dirsync) |
| #endif |
| #if WITH_FS && defined(FS_IMMUTABLE_FL) |
| IF_ANY ("ext2-immutable", &opt_fs_immutable) |
| #endif |
| #if WITH_FS && defined(FS_JOURNAL_DATA_FL) |
| IF_ANY ("ext2-journal-data", &opt_fs_journal_data) |
| #endif |
| #if WITH_FS && defined(FS_NOATIME_FL) |
| IF_ANY ("ext2-noatime", &opt_fs_noatime) |
| #endif |
| #if WITH_FS && defined(FS_NODUMP_FL) |
| IF_ANY ("ext2-nodump", &opt_fs_nodump) |
| #endif |
| #if WITH_FS && defined(FS_NOTAIL_FL) |
| IF_ANY ("ext2-notail", &opt_fs_notail) |
| #endif |
| #if WITH_FS && defined(FS_SECRM_FL) |
| IF_ANY ("ext2-secrm", &opt_fs_secrm) |
| #endif |
| #if WITH_FS && defined(FS_SYNC_FL) |
| IF_ANY ("ext2-sync", &opt_fs_sync) |
| #endif |
| #if WITH_FS && defined(FS_TOPDIR_FL) |
| IF_ANY ("ext2-topdir", &opt_fs_topdir) |
| #endif |
| #if WITH_FS && defined(FS_UNRM_FL) |
| IF_ANY ("ext2-unrm", &opt_fs_unrm) |
| #endif |
| #if WITH_FS && defined(FS_APPEND_FL) |
| IF_ANY ("ext3-append", &opt_fs_append) |
| #endif |
| #if WITH_FS && defined(FS_COMPR_FL) |
| IF_ANY ("ext3-compr", &opt_fs_compr) |
| #endif |
| #if WITH_FS && defined(FS_DIRSYNC_FL) |
| IF_ANY ("ext3-dirsync", &opt_fs_dirsync) |
| #endif |
| #if WITH_FS && defined(FS_IMMUTABLE_FL) |
| IF_ANY ("ext3-immutable", &opt_fs_immutable) |
| #endif |
| #if WITH_FS && defined(FS_JOURNAL_DATA_FL) |
| IF_ANY ("ext3-journal-data", &opt_fs_journal_data) |
| #endif |
| #if WITH_FS && defined(FS_NOATIME_FL) |
| IF_ANY ("ext3-noatime", &opt_fs_noatime) |
| #endif |
| #if WITH_FS && defined(FS_NODUMP_FL) |
| IF_ANY ("ext3-nodump", &opt_fs_nodump) |
| #endif |
| #if WITH_FS && defined(FS_NOTAIL_FL) |
| IF_ANY ("ext3-notail", &opt_fs_notail) |
| #endif |
| #if WITH_FS && defined(FS_SECRM_FL) |
| IF_ANY ("ext3-secrm", &opt_fs_secrm) |
| #endif |
| #if WITH_FS && defined(FS_SYNC_FL) |
| IF_ANY ("ext3-sync", &opt_fs_sync) |
| #endif |
| #if WITH_FS && defined(FS_TOPDIR_FL) |
| IF_ANY ("ext3-topdir", &opt_fs_topdir) |
| #endif |
| #if WITH_FS && defined(FS_UNRM_FL) |
| IF_ANY ("ext3-unrm", &opt_fs_unrm) |
| #endif |
| IF_ANY ("f-setlk", &opt_f_setlk_wr) |
| IF_ANY ("f-setlk-rd", &opt_f_setlk_rd) |
| IF_ANY ("f-setlk-wr", &opt_f_setlk_wr) |
| IF_ANY ("f-setlkw", &opt_f_setlkw_wr) |
| IF_ANY ("f-setlkw-rd", &opt_f_setlkw_rd) |
| IF_ANY ("f-setlkw-wr", &opt_f_setlkw_wr) |
| IF_EXEC ("fdin", &opt_fdin) |
| IF_EXEC ("fdout", &opt_fdout) |
| #ifdef FFDLY |
| # ifdef FF0 |
| IF_TERMIOS("ff0", &opt_ff0) |
| # endif |
| # ifdef FF1 |
| IF_TERMIOS("ff1", &opt_ff1) |
| # endif |
| IF_TERMIOS("ffdly", &opt_ffdly) |
| #endif |
| #ifdef FIOSETOWN |
| IF_SOCKET ("fiosetown", &opt_fiosetown) |
| #endif |
| #if WITH_FIPS |
| IF_OPENSSL("fips", &opt_openssl_fips) |
| #endif |
| #if HAVE_FLOCK |
| IF_ANY ("flock", &opt_flock_ex) |
| IF_ANY ("flock-ex", &opt_flock_ex) |
| IF_ANY ("flock-ex-nb", &opt_flock_ex_nb) |
| IF_ANY ("flock-nb", &opt_flock_ex_nb) |
| IF_ANY ("flock-sh", &opt_flock_sh) |
| IF_ANY ("flock-sh-nb", &opt_flock_sh_nb) |
| #endif |
| #ifdef IPV4_FLOWINFO |
| IF_IP6 ("flowinfo", &opt_ipv6_flowinfo) |
| #endif |
| IF_TERMIOS("flusho", &opt_flusho) |
| IF_RETRY ("forever", &opt_forever) |
| IF_LISTEN ("fork", &opt_fork) |
| #ifdef IP_FREEBIND |
| IF_IP ("freebind", &opt_ip_freebind) |
| #endif |
| #if WITH_FS && defined(FS_APPEND_FL) |
| IF_ANY ("fs-append", &opt_fs_append) |
| #endif |
| #if WITH_FS && defined(FS_COMPR_FL) |
| IF_ANY ("fs-compr", &opt_fs_compr) |
| #endif |
| #if WITH_FS && defined(FS_DIRSYNC_FL) |
| IF_ANY ("fs-dirsync", &opt_fs_dirsync) |
| #endif |
| #if WITH_FS && defined(FS_IMMUTABLE_FL) |
| IF_ANY ("fs-immutable", &opt_fs_immutable) |
| #endif |
| #if WITH_FS && defined(FS_JOURNAL_DATA_FL) |
| IF_ANY ("fs-journal-data", &opt_fs_journal_data) |
| #endif |
| #if WITH_FS && defined(FS_NOATIME_FL) |
| IF_ANY ("fs-noatime", &opt_fs_noatime) |
| #endif |
| #if WITH_FS && defined(FS_NODUMP_FL) |
| IF_ANY ("fs-nodump", &opt_fs_nodump) |
| #endif |
| #if WITH_FS && defined(FS_NOTAIL_FL) |
| IF_ANY ("fs-notail", &opt_fs_notail) |
| #endif |
| #if WITH_FS && defined(FS_SECRM_FL) |
| IF_ANY ("fs-secrm", &opt_fs_secrm) |
| #endif |
| #if WITH_FS && defined(FS_SYNC_FL) |
| IF_ANY ("fs-sync", &opt_fs_sync) |
| #endif |
| #if WITH_FS && defined(FS_TOPDIR_FL) |
| IF_ANY ("fs-topdir", &opt_fs_topdir) |
| #endif |
| #if WITH_FS && defined(FS_UNRM_FL) |
| IF_ANY ("fs-unrm", &opt_fs_unrm) |
| #endif |
| #if HAVE_FTRUNCATE64 |
| IF_ANY ("ftruncate", &opt_ftruncate64) |
| #else |
| IF_ANY ("ftruncate", &opt_ftruncate32) |
| #endif |
| IF_ANY ("ftruncate32", &opt_ftruncate32) |
| #if HAVE_FTRUNCATE64 |
| IF_ANY ("ftruncate64", &opt_ftruncate64) |
| #endif |
| IF_ANY ("gid", &opt_group) |
| IF_NAMED ("gid-e", &opt_group_early) |
| IF_ANY ("gid-l", &opt_group_late) |
| IF_ANY ("group", &opt_group) |
| IF_NAMED ("group-early", &opt_group_early) |
| IF_ANY ("group-late", &opt_group_late) |
| #ifdef IP_HDRINCL |
| IF_IP ("hdrincl", &opt_ip_hdrincl) |
| #endif |
| IF_READLINE("history", &opt_history_file) |
| IF_READLINE("history-file", &opt_history_file) |
| #ifdef IPV6_HOPLIMIT |
| IF_IP6 ("hoplimit", &opt_ipv6_hoplimit) |
| #endif |
| #ifdef IPV6_HOPOPTS |
| IF_IP6 ("hopopts", &opt_ipv6_hopopts) |
| #endif |
| #if WITH_LIBWRAP && defined(HAVE_HOSTS_ALLOW_TABLE) |
| IF_IPAPP ("hosts-allow", &opt_tcpwrap_hosts_allow_table) |
| #endif |
| #if WITH_LIBWRAP && defined(HAVE_HOSTS_DENY_TABLE) |
| IF_IPAPP ("hosts-deny", &opt_tcpwrap_hosts_deny_table) |
| #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) |
| #ifdef SO_BINDTODEVICE |
| IF_SOCKET ("if", &opt_so_bindtodevice) |
| #endif |
| IF_TUN ("iff-allmulti", &opt_iff_allmulti) |
| IF_TUN ("iff-automedia", &opt_iff_automedia) |
| IF_TUN ("iff-broadcast", &opt_iff_broadcast) |
| IF_TUN ("iff-debug", &opt_iff_debug) |
| /*IF_TUN ("iff-dynamic", &opt_iff_dynamic)*/ |
| IF_TUN ("iff-loopback", &opt_iff_loopback) |
| IF_TUN ("iff-master", &opt_iff_master) |
| IF_TUN ("iff-multicast", &opt_iff_multicast) |
| IF_TUN ("iff-no-pi", &opt_iff_no_pi) |
| IF_TUN ("iff-noarp", &opt_iff_noarp) |
| IF_TUN ("iff-notrailers", &opt_iff_notrailers) |
| IF_TUN ("iff-pointopoint", &opt_iff_pointopoint) |
| IF_TUN ("iff-portsel", &opt_iff_portsel) |
| IF_TUN ("iff-promisc", &opt_iff_promisc) |
| IF_TUN ("iff-running", &opt_iff_running) |
| IF_TUN ("iff-slave", &opt_iff_slave) |
| IF_TUN ("iff-up", &opt_iff_up) |
| IF_TERMIOS("ignbrk", &opt_ignbrk) |
| IF_TERMIOS("igncr", &opt_igncr) |
| /* you might need to terminate socat manually if you use this option: */ |
| IF_PROXY ("ignorecr", &opt_ignorecr) |
| IF_ANY ("ignoreeof", &opt_ignoreeof) |
| IF_ANY ("ignoreof", &opt_ignoreeof) |
| IF_TERMIOS("ignpar", &opt_ignpar) |
| #if HAVE_RESOLV_H |
| IF_IP ("igntc", &opt_res_igntc) |
| #endif /* HAVE_RESOLV_H */ |
| IF_TERMIOS("imaxbel", &opt_imaxbel) |
| #if WITH_FS && defined(FS_IMMUTABLE_FL) |
| IF_ANY ("immutable", &opt_fs_immutable) |
| #endif |
| #ifdef TCP_INFO /* Linux 2.4.0 */ |
| IF_TCP ("info", &opt_tcp_info) |
| #endif |
| IF_TERMIOS("inlcr", &opt_inlcr) |
| IF_TERMIOS("inpck", &opt_inpck) |
| #ifdef SO_BINDTODEVICE |
| IF_SOCKET ("interface", &opt_so_bindtodevice) |
| #endif |
| IF_RETRY ("interval", &opt_intervall) |
| IF_RETRY ("intervall", &opt_intervall) |
| IF_TERMIOS("intr", &opt_vintr) |
| IF_ANY ("ioctl", &opt_ioctl_void) |
| IF_ANY ("ioctl-bin", &opt_ioctl_bin) |
| IF_ANY ("ioctl-int", &opt_ioctl_int) |
| IF_ANY ("ioctl-intp", &opt_ioctl_intp) |
| IF_ANY ("ioctl-string", &opt_ioctl_string) |
| IF_ANY ("ioctl-void", &opt_ioctl_void) |
| #ifdef IP_ADD_MEMBERSHIP |
| IF_IP ("ip-add-membership", &opt_ip_add_membership) |
| #endif |
| #if defined(HAVE_STRUCT_IP_MREQ_SOURCE) && defined(IP_ADD_SOURCE_MEMBERSHIP) |
| IF_IP ("ip-add-source-membership", &opt_ip_add_source_membership) |
| #endif |
| #ifdef IP_FREEBIND |
| IF_IP ("ip-freebind", &opt_ip_freebind) |
| #endif |
| #ifdef IP_HDRINCL |
| IF_IP ("ip-hdrincl", &opt_ip_hdrincl) |
| #endif |
| #ifdef IP_ADD_MEMBERSHIP |
| IF_IP ("ip-membership", &opt_ip_add_membership) |
| #endif |
| #ifdef IP_MTU |
| IF_IP ("ip-mtu", &opt_ip_mtu) |
| #endif |
| #ifdef IP_MTU_DISCOVER |
| IF_IP ("ip-mtu-discover", &opt_ip_mtu_discover) |
| #endif |
| IF_IP ("ip-multicast-if", &opt_ip_multicast_if) |
| IF_IP ("ip-multicast-loop", &opt_ip_multicast_loop) |
| IF_IP ("ip-multicast-ttl", &opt_ip_multicast_ttl) |
| #ifdef IP_OPTIONS |
| IF_IP ("ip-options", &opt_ip_options) |
| #endif |
| #ifdef IP_PKTINFO |
| IF_IP ("ip-pktinfo", &opt_ip_pktinfo) |
| #endif |
| #ifdef IP_PKTOPTIONS |
| IF_IP ("ip-pktoptions", &opt_ip_pktoptions) |
| #endif |
| #ifdef IP_RECVDSTADDR |
| IF_IP ("ip-recvdstaddr", &opt_ip_recvdstaddr) |
| #endif |
| #ifdef IP_RECVERR |
| IF_IP ("ip-recverr", &opt_ip_recverr) |
| #endif |
| #ifdef IP_RECVIF |
| IF_IP ("ip-recvif", &opt_ip_recvif) |
| #endif |
| #ifdef IP_RECVOPTS |
| IF_IP ("ip-recvopts", &opt_ip_recvopts) |
| #endif |
| #ifdef IP_RECVTOS |
| IF_IP ("ip-recvtos", &opt_ip_recvtos) |
| #endif |
| #ifdef IP_RECVTTL |
| IF_IP ("ip-recvttl", &opt_ip_recvttl) |
| #endif |
| #ifdef IP_RETOPTS |
| IF_IP ("ip-retopts", &opt_ip_retopts) |
| #endif |
| #ifdef IP_ROUTER_ALERT |
| IF_IP ("ip-router-alert", &opt_ip_router_alert) |
| #endif |
| IF_IP ("ip-tos", &opt_ip_tos) |
| #ifdef IP_TRANSPARENT |
| IF_IP ("ip-transparent", &opt_ip_transparent) |
| #endif |
| IF_IP ("ip-ttl", &opt_ip_ttl) |
| #ifdef IP_FREEBIND |
| IF_IP ("ipfreebind", &opt_ip_freebind) |
| #endif |
| #ifdef IP_HDRINCL |
| IF_IP ("iphdrincl", &opt_ip_hdrincl) |
| #endif |
| #ifdef IP_MTU |
| IF_IP ("ipmtu", &opt_ip_mtu) |
| #endif |
| #ifdef IP_MTU_DISCOVER |
| IF_IP ("ipmtudiscover", &opt_ip_mtu_discover) |
| #endif |
| IF_IP ("ipmulticastloop", &opt_ip_multicast_loop) |
| IF_IP ("ipmulticastttl", &opt_ip_multicast_ttl) |
| #ifdef IP_OPTIONS |
| IF_IP ("ipoptions", &opt_ip_options) |
| #endif |
| #ifdef IP_PKTINFO |
| IF_IP ("ippktinfo", &opt_ip_pktinfo) |
| #endif |
| #ifdef IP_PKTOPTIONS |
| IF_IP ("ippktoptions", &opt_ip_pktoptions) |
| #endif |
| #ifdef IP_RECVDSTADDR |
| IF_IP ("iprecvdstaddr", &opt_ip_recvdstaddr) |
| #endif |
| #ifdef IP_RECVERR |
| IF_IP ("iprecverr", &opt_ip_recverr) |
| #endif |
| #ifdef IP_RECVOPTS |
| IF_IP ("iprecvopts", &opt_ip_recvopts) |
| #endif |
| #ifdef IP_RECVTOS |
| IF_IP ("iprecvtos", &opt_ip_recvtos) |
| #endif |
| #ifdef IP_RECVTTL |
| IF_IP ("iprecvttl", &opt_ip_recvttl) |
| #endif |
| #ifdef IP_RETOPTS |
| IF_IP ("ipretopts", &opt_ip_retopts) |
| #endif |
| #ifdef IP_ROUTER_ALERT |
| IF_IP ("iprouteralert", &opt_ip_router_alert) |
| #endif |
| IF_IP ("iptos", &opt_ip_tos) |
| IF_IP ("ipttl", &opt_ip_ttl) |
| #ifdef IPV6_JOIN_GROUP |
| IF_IP6 ("ipv6-add-membership", &opt_ipv6_join_group) |
| #endif |
| #ifdef IPV6_AUTHHDR |
| IF_IP6 ("ipv6-authhdr", &opt_ipv6_authhdr) |
| #endif |
| #ifdef IPV6_DSTOPTS |
| IF_IP6 ("ipv6-dstopts", &opt_ipv6_dstopts) |
| #endif |
| #ifdef IPV4_FLOWINFO |
| IF_IP6 ("ipv6-flowinfo", &opt_ipv6_flowinfo) |
| #endif |
| #ifdef IPV6_HOPLIMIT |
| IF_IP6 ("ipv6-hoplimit", &opt_ipv6_hoplimit) |
| #endif |
| #ifdef IPV6_HOPOPTS |
| IF_IP6 ("ipv6-hopopts", &opt_ipv6_hopopts) |
| #endif |
| #ifdef IPV6_JOIN_GROUP |
| IF_IP6 ("ipv6-join-group", &opt_ipv6_join_group) |
| #endif |
| #ifdef IPV6_PKTINFO |
| IF_IP6 ("ipv6-pktinfo", &opt_ipv6_pktinfo) |
| #endif |
| #ifdef IPV6_RECVDSTOPTS |
| IF_IP6 ("ipv6-recvdstopts", &opt_ipv6_recvdstopts) |
| #endif |
| #ifdef IPV6_RECVERR |
| IF_IP6 ("ipv6-recverr", &opt_ipv6_recverr) |
| #endif |
| #ifdef IPV6_RECVHOPLIMIT |
| IF_IP6 ("ipv6-recvhoplimit", &opt_ipv6_recvhoplimit) |
| #endif |
| #ifdef IPV6_RECVHOPOPTS |
| IF_IP6 ("ipv6-recvhopopts", &opt_ipv6_recvhopopts) |
| #endif |
| #ifdef IPV6_PATHMTU |
| IF_IP6 ("ipv6-recvpathmtu", &opt_ipv6_recvpathmtu) |
| #endif |
| #ifdef IPV6_RECVPKTINFO |
| IF_IP6 ("ipv6-recvpktinfo", &opt_ipv6_recvpktinfo) |
| #endif |
| #ifdef IPV6_RECVRTHDR |
| IF_IP6 ("ipv6-recvrthdr", &opt_ipv6_recvrthdr) |
| #endif |
| #ifdef IPV6_RECVTCLASS |
| IF_IP6 ("ipv6-recvtclass", &opt_ipv6_recvtclass) |
| #endif |
| #ifdef IPV6_RTHDR |
| IF_IP6 ("ipv6-rthdr", &opt_ipv6_rthdr) |
| #endif |
| #ifdef IPV6_TCLASS |
| IF_IP6 ("ipv6-tclass", &opt_ipv6_tclass) |
| #endif |
| IF_IP6 ("ipv6-unicast-hops", &opt_ipv6_unicast_hops) |
| #ifdef IPV6_V6ONLY |
| IF_IP6 ("ipv6-v6only", &opt_ipv6_v6only) |
| IF_IP6 ("ipv6only", &opt_ipv6_v6only) |
| #endif |
| IF_TERMIOS("isig", &opt_isig) |
| #if HAVE_TERMIOS_ISPEED |
| IF_TERMIOS("ispeed", &opt_ispeed) |
| #endif |
| IF_TERMIOS("istrip", &opt_istrip) |
| #ifdef IUCLC |
| IF_TERMIOS("iuclc", &opt_iuclc) |
| #endif |
| IF_TERMIOS("ixany", &opt_ixany) |
| IF_TERMIOS("ixoff", &opt_ixoff) |
| IF_TERMIOS("ixon", &opt_ixon) |
| #ifdef IPV6_JOIN_GROUP |
| IF_IP6 ("join-group", &opt_ipv6_join_group) |
| #endif |
| #if WITH_FS && defined(FS_JOURNAL_DATA_FL) |
| IF_ANY ("journal", &opt_fs_journal_data) |
| IF_ANY ("journal-data", &opt_fs_journal_data) |
| #endif |
| IF_SOCKET ("keepalive", &opt_so_keepalive) |
| #ifdef TCP_KEEPCNT /* Linux 2.4.0 */ |
| IF_TCP ("keepcnt", &opt_tcp_keepcnt) |
| #endif |
| #ifdef TCP_KEEPIDLE /* Linux 2.4.0 */ |
| IF_TCP ("keepidle", &opt_tcp_keepidle) |
| #endif |
| #ifdef TCP_KEEPINIT /* OSF1 */ |
| IF_TCP ("keepinit", &opt_tcp_keepinit) |
| #endif |
| #ifdef TCP_KEEPINTVL /* Linux 2.4.0 */ |
| IF_TCP ("keepintvl", &opt_tcp_keepintvl) |
| #endif |
| #ifdef SO_KERNACCEPT /* AIX 4.3.3 */ |
| IF_SOCKET ("kernaccept", &opt_so_kernaccept) |
| #endif /* SO_KERNACCEPT */ |
| IF_OPENSSL("key", &opt_openssl_key) |
| IF_TERMIOS("kill", &opt_vkill) |
| #ifdef O_LARGEFILE |
| IF_OPEN ("largefile", &opt_o_largefile) |
| #endif |
| #if WITH_LIBWRAP |
| IF_IPAPP ("libwrap", &opt_tcpwrappers) |
| #endif |
| IF_SOCKET ("linger", &opt_so_linger) |
| #ifdef TCP_LINGER2 /* Linux 2.4.0 */ |
| IF_TCP ("linger2", &opt_tcp_linger2) |
| #endif |
| IF_PTY ("link", &opt_symbolic_link) |
| IF_LISTEN ("listen-timeout", &opt_accept_timeout) |
| IF_TERMIOS("lnext", &opt_vlnext) |
| #if defined(F_SETLKW) |
| IF_ANY ("lock", &opt_f_setlkw_wr) /* POSIX, first choice */ |
| #elif defined(HAVE_FLOCK) |
| IF_ANY ("lock", &opt_flock_ex) /* BSD, fallback */ |
| #endif |
| IF_ANY ("lockfile", &opt_lockfile) |
| #if defined(F_SETLKW) |
| IF_ANY ("lockw", &opt_f_setlkw_wr) /* POSIX, first choice */ |
| #elif defined(HAVE_FLOCK) |
| IF_ANY ("lockw", &opt_flock_ex_nb) /* BSD, fallback */ |
| #endif |
| IF_EXEC ("login", &opt_dash) |
| IF_TUN ("loopback", &opt_iff_loopback) |
| IF_IPAPP ("lowport", &opt_lowport) |
| #if HAVE_LSEEK64 |
| IF_ANY ("lseek", &opt_lseek64_set) |
| #else |
| IF_ANY ("lseek", &opt_lseek32_set) |
| #endif |
| IF_ANY ("lseek32", &opt_lseek32_set) |
| IF_ANY ("lseek32-cur", &opt_lseek32_cur) |
| IF_ANY ("lseek32-end", &opt_lseek32_end) |
| IF_ANY ("lseek32-set", &opt_lseek32_set) |
| #if HAVE_LSEEK64 |
| IF_ANY ("lseek64", &opt_lseek64_set) |
| IF_ANY ("lseek64-cur", &opt_lseek64_cur) |
| IF_ANY ("lseek64-end", &opt_lseek64_end) |
| IF_ANY ("lseek64-set", &opt_lseek64_set) |
| #endif |
| IF_TUN ("master", &opt_iff_master) |
| IF_LISTEN ("max-children", &opt_max_children) |
| #if HAVE_SSL_set_max_proto_version || defined(SSL_set_max_proto_version) |
| IF_OPENSSL("max-version", &opt_openssl_max_proto_version) |
| #endif |
| IF_LISTEN ("maxchildren", &opt_max_children) |
| #ifdef TCP_MAXSEG |
| IF_TCP ("maxseg", &opt_tcp_maxseg) |
| IF_TCP ("maxseg-late", &opt_tcp_maxseg_late) |
| #endif |
| #ifdef TCP_MD5SUM |
| IF_TCP ("md5sig", &opt_tcp_md5sig) |
| #endif |
| #ifdef IP_ADD_MEMBERSHIP |
| IF_IP ("membership", &opt_ip_add_membership) |
| #endif |
| #if WITH_OPENSSL_METHOD |
| IF_OPENSSL("method", &opt_openssl_method) |
| #endif |
| IF_TERMIOS("min", &opt_vmin) |
| #if HAVE_SSL_set_min_proto_version || defined(SSL_set_min_proto_version) |
| IF_OPENSSL("min-version", &opt_openssl_min_proto_version) |
| #endif |
| IF_ANY ("mode", &opt_perm) |
| #ifdef TCP_MAXSEG |
| IF_TCP ("mss", &opt_tcp_maxseg) |
| IF_TCP ("mss-late", &opt_tcp_maxseg_late) |
| #endif |
| #ifdef IP_MTU |
| IF_IP ("mtu", &opt_ip_mtu) |
| #endif |
| #ifdef IP_MTU_DISCOVER |
| IF_IP ("mtudiscover", &opt_ip_mtu_discover) |
| #endif |
| IF_TUN ("multicast", &opt_iff_multicast) |
| IF_IP ("multicast-if", &opt_ip_multicast_if) |
| IF_IP ("multicast-loop", &opt_ip_multicast_loop) |
| IF_IP ("multicast-ttl", &opt_ip_multicast_ttl) |
| IF_IP ("multicastloop", &opt_ip_multicast_loop) |
| IF_IP ("multicastttl", &opt_ip_multicast_ttl) |
| #if defined(O_NDELAY) && (!defined(O_NONBLOCK) || O_NDELAY != O_NONBLOCK) |
| IF_ANY ("ndelay", &opt_o_ndelay) |
| #else |
| IF_ANY ("ndelay", &opt_nonblock) |
| #endif |
| IF_NAMED ("new", &opt_unlink_early) |
| #ifdef NLDLY |
| # ifdef NL0 |
| IF_TERMIOS("nl0", &opt_nl0) |
| # endif |
| # ifdef NL1 |
| IF_TERMIOS("nl1", &opt_nl1) |
| # endif |
| IF_TERMIOS("nldly", &opt_nldly) |
| #endif /* defined(NLDLY) */ |
| #ifdef SO_NO_CHECK |
| IF_SOCKET ("no-check", &opt_so_no_check) |
| #endif |
| IF_TUN ("no-pi", &opt_iff_no_pi) |
| #if defined(HAVE_SSL_set_tlsext_host_name) || defined(SSL_set_tlsext_host_name) |
| IF_OPENSSL("no-sni", &opt_openssl_no_sni) |
| #endif |
| IF_TUN ("noarp", &opt_iff_noarp) |
| #ifdef O_NOATIME |
| IF_OPEN ("noatime", &opt_o_noatime) |
| #endif |
| #ifdef SO_NO_CHECK |
| IF_SOCKET ("nocheck", &opt_so_no_check) |
| #endif |
| IF_OPEN ("noctty", &opt_o_noctty) |
| #ifdef TCP_NODELAY |
| IF_TCP ("nodelay", &opt_tcp_nodelay) |
| #endif |
| #if WITH_FS && defined(FS_NODUMP_FL) |
| IF_ANY ("nodump", &opt_fs_nodump) |
| #endif |
| #if HAVE_REGEX_H |
| IF_READLINE("noecho", &opt_noecho) |
| #endif /* HAVE_REGEX_H */ |
| IF_TERMIOS("noflsh", &opt_noflsh) |
| #ifdef O_NOFOLLOW |
| IF_OPEN ("nofollow", &opt_o_nofollow) |
| #endif |
| IF_EXEC ("nofork", &opt_nofork) |
| #ifdef O_NOINHERIT |
| IF_ANY ("noinherit", &opt_o_noinherit) |
| #endif |
| IF_ANY ("nonblock", &opt_nonblock) |
| #ifdef TCP_NOOPT |
| IF_TCP ("noopt", &opt_tcp_noopt) |
| #endif |
| IF_READLINE("noprompt", &opt_noprompt) |
| #ifdef TCP_NOPUSH |
| IF_TCP ("nopush", &opt_tcp_nopush) |
| #endif |
| #ifdef SO_NOREUSEADDR /* AIX 4.3.3 */ |
| IF_SOCKET ("noreuseaddr", &opt_so_noreuseaddr) |
| #endif /* SO_NOREUSEADDR */ |
| #if defined(HAVE_SSL_set_tlsext_host_name) || defined(SSL_set_tlsext_host_name) |
| IF_OPENSSL("nosni", &opt_openssl_no_sni) |
| #endif |
| IF_TUN ("notrailers", &opt_iff_notrailers) |
| #ifdef O_NSHARE |
| IF_OPEN ("nshare", &opt_o_nshare) |
| #endif |
| IF_SOCKET ("null-eof", &opt_null_eof) |
| IF_ANY ("o-append", &opt_append) |
| #ifdef O_ASYNC |
| IF_ANY ("o-async", &opt_async) |
| #endif |
| #ifdef O_BINARY |
| IF_OPEN ("o-binary", &opt_o_binary) |
| #endif |
| IF_OPEN ("o-creat", &opt_o_create) |
| IF_OPEN ("o-create", &opt_o_create) |
| #ifdef O_DEFER |
| IF_OPEN ("o-defer", &opt_o_defer) |
| #endif |
| #ifdef O_DELAY |
| IF_OPEN ("o-delay", &opt_o_delay) |
| #endif |
| #ifdef O_DIRECT |
| IF_OPEN ("o-direct", &opt_o_direct) |
| #endif |
| #ifdef O_DIRECTORY |
| IF_OPEN ("o-directory", &opt_o_directory) |
| #endif |
| #ifdef O_DSYNC |
| IF_OPEN ("o-dsync", &opt_o_dsync) |
| #endif |
| IF_OPEN ("o-excl", &opt_o_excl) |
| #ifdef O_LARGEFILE |
| IF_OPEN ("o-largefile", &opt_o_largefile) |
| #endif |
| #if defined(O_NDELAY) && (!defined(O_NONBLOCK) || O_NDELAY != O_NONBLOCK) |
| IF_ANY ("o-ndelay", &opt_o_ndelay) |
| #else |
| IF_ANY ("o-ndelay", &opt_nonblock) |
| #endif |
| #ifdef O_NOATIME |
| IF_OPEN ("o-noatime", &opt_o_noatime) |
| #endif |
| IF_OPEN ("o-noctty", &opt_o_noctty) |
| #ifdef O_NOFOLLOW |
| IF_OPEN ("o-nofollow", &opt_o_nofollow) |
| #endif |
| #ifdef O_NOINHERIT |
| IF_ANY ("o-noinherit", &opt_o_noinherit) |
| #endif |
| IF_ANY ("o-nonblock", &opt_nonblock) |
| #ifdef O_NSHARE |
| IF_OPEN ("o-nshare", &opt_o_nshare) |
| #endif |
| #ifdef O_PRIV |
| IF_OPEN ("o-priv", &opt_o_priv) |
| #endif |
| IF_OPEN ("o-rdonly", &opt_o_rdonly) |
| IF_OPEN ("o-rdwr", &opt_o_rdwr) |
| #ifdef O_RSHARE |
| IF_OPEN ("o-rshare", &opt_o_rshare) |
| #endif |
| #ifdef O_RSYNC |
| IF_OPEN ("o-rsync", &opt_o_rsync) |
| #endif |
| #ifdef O_SYNC |
| IF_OPEN ("o-sync", &opt_o_sync) |
| #endif |
| #ifdef O_TEXT |
| IF_ANY ("o-text", &opt_o_text) |
| #endif |
| IF_OPEN ("o-trunc", &opt_o_trunc) |
| IF_OPEN ("o-wronly", &opt_o_wronly) |
| IF_OPEN ("o_create", &opt_o_create) |
| #ifdef O_DEFER |
| IF_OPEN ("o_defer", &opt_o_defer) |
| #endif |
| #ifdef O_DELAY |
| IF_OPEN ("o_delay", &opt_o_delay) |
| #endif |
| #ifdef O_DIRECT |
| IF_OPEN ("o_direct", &opt_o_direct) |
| #endif |
| #ifdef O_DIRECTORY |
| IF_OPEN ("o_directory", &opt_o_directory) |
| #endif |
| #ifdef O_DSYNC |
| IF_OPEN ("o_dsync", &opt_o_dsync) |
| #endif |
| IF_OPEN ("o_excl", &opt_o_excl) |
| #ifdef O_LARGEFILE |
| IF_OPEN ("o_largefile", &opt_o_largefile) |
| #endif |
| #if defined(O_NDELAY) && (!defined(O_NONBLOCK) || O_NDELAY != O_NONBLOCK) |
| IF_ANY ("o_ndelay", &opt_o_ndelay) |
| #else |
| IF_ANY ("o_ndelay", &opt_nonblock) |
| #endif |
| IF_OPEN ("o_noctty", &opt_o_noctty) |
| #ifdef O_NOFOLLOW |
| IF_OPEN ("o_nofollow", &opt_o_nofollow) |
| #endif |
| #ifdef O_NSHARE |
| IF_OPEN ("o_nshare", &opt_o_nshare) |
| #endif |
| #ifdef O_PRIV |
| IF_OPEN ("o_priv", &opt_o_priv) |
| #endif |
| IF_OPEN ("o_rdonly", &opt_o_rdonly) |
| IF_OPEN ("o_rdwr", &opt_o_rdwr) |
| #ifdef O_RSHARE |
| IF_OPEN ("o_rshare", &opt_o_rshare) |
| #endif |
| #ifdef O_RSYNC |
| IF_OPEN ("o_rsync", &opt_o_rsync) |
| #endif |
| #ifdef O_SYNC |
| IF_OPEN ("o_sync", &opt_o_sync) |
| #endif |
| IF_OPEN ("o_wronly", &opt_o_wronly) |
| #ifdef OCRNL |
| IF_TERMIOS("ocrnl", &opt_ocrnl) |
| #endif |
| #ifdef OFDEL |
| IF_TERMIOS("ofdel", &opt_ofdel) |
| #endif |
| #ifdef OFILL |
| IF_TERMIOS("ofill", &opt_ofill) |
| #endif |
| #ifdef OLCUC |
| IF_TERMIOS("olcuc", &opt_olcuc) |
| #endif |
| IF_TERMIOS("onlcr", &opt_onlcr) |
| #ifdef ONLRET |
| IF_TERMIOS("onlret", &opt_onlret) |
| #endif |
| #ifdef ONOCR |
| IF_TERMIOS("onocr", &opt_onocr) |
| #endif |
| IF_SOCKET ("oobinline", &opt_so_oobinline) |
| #if HAVE_OPENPTY |
| IF_EXEC ("openpty", &opt_openpty) |
| #endif /* HAVE_OPENPTY */ |
| IF_OPENSSL("openssl-cafile", &opt_openssl_cafile) |
| IF_OPENSSL("openssl-capath", &opt_openssl_capath) |
| IF_OPENSSL("openssl-certificate", &opt_openssl_certificate) |
| IF_OPENSSL("openssl-cipherlist", &opt_openssl_cipherlist) |
| IF_OPENSSL("openssl-commonname", &opt_openssl_commonname) |
| #if OPENSSL_VERSION_NUMBER >= 0x00908000L && !defined(OPENSSL_NO_COMP) |
| IF_OPENSSL("openssl-compress", &opt_openssl_compress) |
| #endif |
| IF_OPENSSL("openssl-dhparam", &opt_openssl_dhparam) |
| IF_OPENSSL("openssl-dhparams", &opt_openssl_dhparam) |
| IF_OPENSSL("openssl-egd", &opt_openssl_egd) |
| #if WITH_FIPS |
| IF_OPENSSL("openssl-fips", &opt_openssl_fips) |
| #endif |
| IF_OPENSSL("openssl-key", &opt_openssl_key) |
| #if HAVE_SSL_set_max_proto_version || defined(SSL_set_max_proto_version) |
| IF_OPENSSL("openssl-max-proto-version", &opt_openssl_max_proto_version) |
| #endif |
| #if WITH_OPENSSL_METHOD |
| IF_OPENSSL("openssl-method", &opt_openssl_method) |
| #endif |
| #if HAVE_SSL_set_min_proto_version || defined(SSL_set_min_proto_version) |
| IF_OPENSSL("openssl-min-proto-version", &opt_openssl_min_proto_version) |
| #endif |
| #if defined(HAVE_SSL_set_tlsext_host_name) || defined(SSL_set_tlsext_host_name) |
| IF_OPENSSL("openssl-no-sni", &opt_openssl_no_sni) |
| #endif |
| IF_OPENSSL("openssl-pseudo", &opt_openssl_pseudo) |
| #if defined(HAVE_SSL_set_tlsext_host_name) || defined(SSL_set_tlsext_host_name) |
| IF_OPENSSL("openssl-snihost", &opt_openssl_snihost) |
| #endif |
| IF_OPENSSL("openssl-verify", &opt_openssl_verify) |
| IF_TERMIOS("opost", &opt_opost) |
| #if HAVE_TERMIOS_OSPEED |
| IF_TERMIOS("ospeed", &opt_ospeed) |
| #endif |
| IF_ANY ("owner", &opt_user) |
| IF_TERMIOS("parenb", &opt_parenb) |
| IF_TERMIOS("parmrk", &opt_parmrk) |
| IF_TERMIOS("parodd", &opt_parodd) |
| #ifdef SO_PASSCRED |
| IF_SOCKET ("passcred", &opt_so_passcred) |
| #endif |
| IF_EXEC ("path", &opt_path) |
| #ifdef TCP_PAWS /* OSF1 */ |
| IF_TCP ("paws", &opt_tcp_paws) |
| #endif |
| #ifdef SO_PEERCRED |
| IF_SOCKET ("peercred", &opt_so_peercred) |
| #endif |
| #ifdef PENDIN |
| IF_TERMIOS("pendin", &opt_pendin) |
| #endif |
| IF_ANY ("perm", &opt_perm) |
| IF_NAMED ("perm-early", &opt_perm_early) |
| IF_ANY ("perm-late", &opt_perm_late) |
| IF_SOCKET ("pf", &opt_protocol_family) |
| IF_EXEC ("pgid", &opt_setpgid) |
| IF_EXEC ("pipes", &opt_pipes) |
| #ifdef IP_PKTINFO |
| IF_IP ("pktinfo", &opt_ip_pktinfo) |
| #endif |
| #ifdef IP_PKTOPTIONS |
| IF_IP ("pktoptions", &opt_ip_pktoptions) |
| 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 && WITH_RES_PRIMARY |
| IF_IP ("primary", &opt_res_primary) |
| #endif |
| #ifdef SO_PRIORITY |
| IF_SOCKET ("priority", &opt_so_priority) |
| #endif |
| #ifdef O_PRIV |
| IF_OPEN ("priv", &opt_o_priv) |
| #endif |
| IF_TUN ("promisc", &opt_iff_promisc) |
| IF_READLINE("prompt", &opt_prompt) |
| #ifdef SO_PROTOTYPE |
| IF_SOCKET ("protocol", &opt_so_prototype) |
| #endif |
| IF_SOCKET ("protocol-family", &opt_protocol_family) |
| #ifdef SO_PROTOTYPE |
| IF_SOCKET ("prototype", &opt_so_prototype) |
| #endif |
| IF_PROXY ("proxy-auth", &opt_proxy_authorization) |
| IF_PROXY ("proxy-authorization", &opt_proxy_authorization) |
| IF_PROXY ("proxy-authorization-file", &opt_proxy_authorization_file) |
| IF_PROXY ("proxy-resolve", &opt_proxy_resolve) |
| IF_PROXY ("proxyauth", &opt_proxy_authorization) |
| IF_PROXY ("proxyauthfile", &opt_proxy_authorization_file) |
| IF_PROXY ("proxyport", &opt_proxyport) |
| #ifdef ECHOPRT |
| IF_TERMIOS("prterase", &opt_echoprt) |
| #endif |
| IF_OPENSSL("pseudo", &opt_openssl_pseudo) |
| #if HAVE_DEV_PTMX || HAVE_DEV_PTC |
| IF_EXEC ("ptmx", &opt_ptmx) |
| #endif |
| #if HAVE_PTY |
| IF_EXEC ("pty", &opt_pty) |
| #endif |
| #if HAVE_PTY && HAVE_POLL |
| IF_PTY ("pty-interval", &opt_pty_intervall) |
| 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 |
| IF_TERMIOS("quit", &opt_vquit) |
| IF_RANGE ("range", &opt_range) |
| IF_TERMIOS("raw", &opt_raw) |
| IF_TERMIOS("rawer", &opt_termios_rawer) |
| IF_SOCKET ("rcvbuf", &opt_so_rcvbuf) |
| IF_SOCKET ("rcvbuf-late", &opt_so_rcvbuf_late) |
| #ifdef SO_RCVLOWAT |
| IF_SOCKET ("rcvlowat", &opt_so_rcvlowat) |
| #endif |
| IF_OPEN ("rdonly", &opt_o_rdonly) |
| IF_OPEN ("rdwr", &opt_o_rdwr) |
| IF_ANY ("readbytes", &opt_readbytes) |
| #if HAVE_RESOLV_H |
| IF_IP ("recurse", &opt_res_recurse) |
| #endif /* HAVE_RESOLV_H */ |
| #ifdef IP_RECVDSTADDR |
| IF_IP ("recvdstaddr", &opt_ip_recvdstaddr) |
| #endif |
| #ifdef IPV6_RECVDSTOPTS |
| IF_IP6 ("recvdstopts", &opt_ipv6_recvdstopts) |
| #endif |
| #ifdef IP_RECVERR |
| IF_IP ("recverr", &opt_ip_recverr) |
| #endif |
| #ifdef IPV6_RECVHOPLIMIT |
| IF_IP6 ("recvhoplimit", &opt_ipv6_recvhoplimit) |
| #endif |
| #ifdef IPV6_RECVHOPOPTS |
| IF_IP6 ("recvhopopts", &opt_ipv6_recvhopopts) |
| #endif |
| #ifdef IP_RECVIF |
| IF_IP ("recvif", &opt_ip_recvif) |
| #endif |
| #ifdef IP_RECVOPTS |
| IF_IP ("recvopts", &opt_ip_recvopts) |
| #endif |
| #ifdef IPV6_RECVPKTINFO |
| IF_IP6 ("recvpktinfo", &opt_ipv6_recvpktinfo) |
| #endif |
| #ifdef IPV6_RECVRTHDR |
| IF_IP6 ("recvrthdr", &opt_ipv6_recvrthdr) |
| #endif |
| #ifdef IP_RECVTOS |
| IF_IP ("recvtos", &opt_ip_recvtos) |
| #endif |
| #ifdef IP_RECVTTL |
| IF_IP ("recvttl", &opt_ip_recvttl) |
| #endif |
| IF_NAMED ("remove", &opt_unlink) |
| #ifdef VREPRINT |
| IF_TERMIOS("reprint", &opt_vreprint) |
| #endif |
| #if HAVE_RESOLV_H |
| # if WITH_AA_ONLY |
| IF_IP ("res-aaonly", &opt_res_aaonly) |
| # endif |
| IF_IP ("res-debug", &opt_res_debug) |
| IF_IP ("res-defnames", &opt_res_defnames) |
| IF_IP ("res-dnsrch", &opt_res_dnsrch) |
| IF_IP ("res-igntc", &opt_res_igntc) |
| # if WITH_RES_PRIMARY |
| IF_IP ("res-primary", &opt_res_primary) |
| # endif |
| IF_IP ("res-recurse", &opt_res_recurse) |
| IF_IP ("res-stayopen", &opt_res_stayopen) |
| IF_IP ("res-usevc", &opt_res_usevc) |
| #endif /* HAVE_RESOLV_H */ |
| IF_PROXY ("resolv", &opt_proxy_resolve) |
| IF_PROXY ("resolve", &opt_proxy_resolve) |
| #ifdef IP_RETOPTS |
| IF_IP ("retopts", &opt_ip_retopts) |
| #endif |
| IF_RETRY ("retry", &opt_retry) |
| IF_SOCKET ("reuseaddr", &opt_so_reuseaddr) |
| #ifdef SO_REUSEPORT /* AIX 4.3.3 */ |
| IF_SOCKET ("reuseport", &opt_so_reuseport) |
| #endif /* defined(SO_REUSEPORT) */ |
| #ifdef TCP_RFC1323 |
| IF_TCP ("rfc1323", &opt_tcp_rfc1323) |
| #endif |
| #ifdef IP_ROUTER_ALERT |
| IF_IP ("routeralert", &opt_ip_router_alert) |
| #endif |
| #ifdef VREPRINT |
| IF_TERMIOS("rprnt", &opt_vreprint) |
| #endif |
| #ifdef O_RSHARE |
| IF_OPEN ("rshare", &opt_o_rshare) |
| #endif |
| #ifdef O_RSYNC |
| IF_OPEN ("rsync", &opt_o_rsync) |
| #endif |
| #ifdef IPV6_RTHDR |
| IF_IP6 ("rthdr", &opt_ipv6_rthdr) |
| #endif |
| IF_TUN ("running", &opt_iff_running) |
| #ifdef TCP_SACK_DISABLE |
| IF_TCP ("sack-disable", &opt_tcp_sack_disable) |
| #endif |
| #ifdef TCP_SACKENA /* OSF1 */ |
| IF_TCP ("sackena", &opt_tcp_sackena) |
| #endif |
| IF_TERMIOS("sane", &opt_sane) |
| #ifdef SCTP_MAXSEG |
| IF_SCTP ("sctp-maxseg", &opt_sctp_maxseg) |
| IF_SCTP ("sctp-maxseg-late", &opt_sctp_maxseg_late) |
| #endif |
| #ifdef SCTP_NODELAY |
| IF_SCTP ("sctp-nodelay", &opt_sctp_nodelay) |
| #endif |
| #if WITH_FS && defined(FS_SECRM_FL) |
| IF_ANY ("secrm", &opt_fs_secrm) |
| #endif |
| #ifdef SO_SECURITY_AUTHENTICATION |
| IF_SOCKET ("security-authentication", &opt_so_security_authentication) |
| #endif |
| #ifdef SO_SECURITY_ENCRYPTION_NETWORK |
| IF_SOCKET ("security-encryption-network", &opt_so_security_encryption_network) |
| #endif |
| #ifdef SO_SECURITY_ENCRYPTION_TRANSPORT |
| IF_SOCKET ("security-encryption-transport", &opt_so_security_encryption_transport) |
| #endif |
| #ifdef SO_SECURITY_AUTHENTICATION |
| IF_SOCKET ("securityauthentication", &opt_so_security_authentication) |
| #endif |
| #ifdef SO_SECURITY_ENCRYPTION_NETWORK |
| IF_SOCKET ("securityencryptionnetwork", &opt_so_security_encryption_network) |
| #endif |
| #ifdef SO_SECURITY_ENCRYPTION_TRANSPORT |
| IF_SOCKET ("securityencryptiontransport", &opt_so_security_encryption_transport) |
| #endif |
| #if HAVE_LSEEK64 |
| IF_ANY ("seek", &opt_lseek64_set) |
| IF_ANY ("seek-cur", &opt_lseek64_cur) |
| IF_ANY ("seek-end", &opt_lseek64_end) |
| IF_ANY ("seek-set", &opt_lseek64_set) |
| #else |
| IF_ANY ("seek", &opt_lseek32_set) |
| IF_ANY ("seek-cur", &opt_lseek32_cur) |
| IF_ANY ("seek-end", &opt_lseek32_end) |
| IF_ANY ("seek-set", &opt_lseek32_set) |
| #endif |
| IF_ANY ("setgid", &opt_setgid) |
| IF_ANY ("setgid-early", &opt_setgid_early) |
| IF_ANY ("setlk", &opt_f_setlk_wr) |
| IF_ANY ("setlk-rd", &opt_f_setlk_rd) |
| IF_ANY ("setlk-wr", &opt_f_setlk_wr) |
| IF_ANY ("setlkw", &opt_f_setlkw_wr) |
| IF_ANY ("setlkw-rd", &opt_f_setlkw_rd) |
| IF_ANY ("setlkw-wr", &opt_f_setlkw_wr) |
| IF_EXEC ("setpgid", &opt_setpgid) |
| #if WITH_EXEC || WITH_SYSTEM |
| IF_EXEC ("setsid", &opt_setsid) |
| #endif |
| IF_SOCKET ("setsockopt", &opt_setsockopt) |
| IF_SOCKET ("setsockopt-bin", &opt_setsockopt_bin) |
| IF_SOCKET ("setsockopt-int", &opt_setsockopt_int) |
| IF_SOCKET ("setsockopt-listen", &opt_setsockopt_listen) |
| IF_SOCKET ("setsockopt-string", &opt_setsockopt_string) |
| IF_ANY ("setuid", &opt_setuid) |
| IF_ANY ("setuid-early", &opt_setuid_early) |
| IF_ANY ("shut-close", &opt_shut_close) |
| IF_ANY ("shut-down", &opt_shut_down) |
| IF_ANY ("shut-none", &opt_shut_none) |
| IF_ANY ("shut-null", &opt_shut_null) |
| #if WITH_EXEC || WITH_SYSTEM |
| IF_ANY ("sid", &opt_setsid) |
| #endif |
| IF_EXEC ("sighup", &opt_sighup) |
| IF_EXEC ("sigint", &opt_sigint) |
| #ifdef TCP_SIGNATURE_ENABLE |
| IF_TCP ("signature-enable", &opt_tcp_signature_enable) |
| #endif |
| IF_EXEC ("sigquit", &opt_sigquit) |
| #ifdef SIOCSPGRP |
| IF_SOCKET ("siocspgrp", &opt_siocspgrp) |
| #endif |
| IF_TUN ("slave", &opt_iff_slave) |
| IF_SOCKET ("sndbuf", &opt_so_sndbuf) |
| IF_SOCKET ("sndbuf-late", &opt_so_sndbuf_late) |
| #ifdef SO_SNDLOWAT |
| IF_SOCKET ("sndlowat", &opt_so_sndlowat) |
| #endif |
| #if defined(HAVE_SSL_set_tlsext_host_name) || defined(SSL_set_tlsext_host_name) |
| IF_OPENSSL("snihost", &opt_openssl_snihost) |
| #endif |
| #ifdef SO_ACCEPTCONN /* AIX433 */ |
| IF_SOCKET ("so-acceptconn", &opt_so_acceptconn) |
| #endif /* SO_ACCEPTCONN */ |
| #ifdef SO_ATTACH_FILTER |
| IF_SOCKET ("so-attach-filter", &opt_so_attach_filter) |
| #endif |
| #ifdef SO_AUDIT /* AIX 4.3.3 */ |
| IF_SOCKET ("so-audit", &opt_so_audit) |
| #endif /* SO_AUDIT */ |
| #ifdef SO_BINDTODEVICE |
| IF_SOCKET ("so-bindtodevice", &opt_so_bindtodevice) |
| #endif |
| IF_SOCKET ("so-broadcast", &opt_so_broadcast) |
| #ifdef SO_BSDCOMPAT |
| IF_SOCKET ("so-bsdcompat", &opt_so_bsdcompat) |
| #endif |
| #ifdef SO_CKSUMRECV |
| IF_SOCKET ("so-cksumrecv", &opt_so_cksumrecv) |
| #endif /* SO_CKSUMRECV */ |
| IF_SOCKET ("so-debug", &opt_so_debug) |
| #ifdef SO_DETACH_FILTER |
| IF_SOCKET ("so-detach-filter", &opt_so_detach_filter) |
| #endif |
| #ifdef SO_DGRAM_ERRIND |
| IF_SOCKET ("so-dgram-errind", &opt_so_dgram_errind) |
| #endif |
| #ifdef SO_DONTLINGER |
| IF_SOCKET ("so-dontlinger", &opt_so_dontlinger) |
| #endif |
| IF_SOCKET ("so-dontroute", &opt_so_dontroute) |
| IF_SOCKET ("so-error", &opt_so_error) |
| IF_SOCKET ("so-keepalive", &opt_so_keepalive) |
| #ifdef SO_KERNACCEPT /* AIX 4.3.3 */ |
| IF_SOCKET ("so-kernaccept", &opt_so_kernaccept) |
| #endif /* SO_KERNACCEPT */ |
| IF_SOCKET ("so-linger", &opt_so_linger) |
| #ifdef SO_NO_CHECK |
| IF_SOCKET ("so-no-check", &opt_so_no_check) |
| #endif |
| #ifdef SO_NOREUSEADDR /* AIX 4.3.3 */ |
| IF_SOCKET ("so-noreuseaddr", &opt_so_noreuseaddr) |
| #endif /* SO_NOREUSEADDR */ |
| IF_SOCKET ("so-oobinline", &opt_so_oobinline) |
| #ifdef SO_PASSCRED |
| IF_SOCKET ("so-passcred", &opt_so_passcred) |
| #endif |
| #ifdef SO_PEERCRED |
| IF_SOCKET ("so-peercred", &opt_so_peercred) |
| #endif |
| #ifdef SO_PRIORITY |
| IF_SOCKET ("so-priority", &opt_so_priority) |
| #endif |
| #ifdef SO_PROTOTYPE |
| IF_SOCKET ("so-protocol", &opt_so_prototype) |
| IF_SOCKET ("so-prototype", &opt_so_prototype) |
| #endif |
| IF_SOCKET ("so-rcvbuf", &opt_so_rcvbuf) |
| IF_SOCKET ("so-rcvbuf-late", &opt_so_rcvbuf_late) |
| #ifdef SO_RCVLOWAT |
| IF_SOCKET ("so-rcvlowat", &opt_so_rcvlowat) |
| #endif |
| IF_SOCKET ("so-reuseaddr", &opt_so_reuseaddr) |
| #ifdef SO_REUSEPORT /* AIX 4.3.3 */ |
| IF_SOCKET ("so-reuseport", &opt_so_reuseport) |
| #endif /* defined(SO_REUSEPORT) */ |
| #ifdef SO_SECURITY_AUTHENTICATION |
| IF_SOCKET ("so-security-authentication", &opt_so_security_authentication) |
| #endif |
| #ifdef SO_SECURITY_ENCRYPTION_NETWORK |
| IF_SOCKET ("so-security-encryption-network", &opt_so_security_encryption_network) |
| #endif |
| #ifdef SO_SECURITY_ENCRYPTION_TRANSPORT |
| IF_SOCKET ("so-security-encryption-transport", &opt_so_security_encryption_transport) |
| #endif |
| IF_SOCKET ("so-sndbuf", &opt_so_sndbuf) |
| IF_SOCKET ("so-sndbuf-late", &opt_so_sndbuf_late) |
| #ifdef SO_SNDLOWAT |
| IF_SOCKET ("so-sndlowat", &opt_so_sndlowat) |
| #endif |
| #ifdef SO_TIMESTAMP |
| IF_SOCKET ("so-timestamp", &opt_so_timestamp) |
| #endif |
| IF_SOCKET ("so-type", &opt_so_type) |
| #ifdef SO_USE_IFBUFS |
| IF_SOCKET ("so-use-ifbufs", &opt_so_use_ifbufs) |
| #endif /* SO_USE_IFBUFS */ |
| #ifdef SO_USELOOPBACK /* AIX433, Solaris */ |
| IF_SOCKET ("so-useloopback", &opt_so_useloopback) |
| #endif /* SO_USELOOPBACK */ |
| IF_SOCKET ("sockopt", &opt_setsockopt) |
| IF_SOCKET ("sockopt-bin", &opt_setsockopt_bin) |
| IF_SOCKET ("sockopt-int", &opt_setsockopt_int) |
| IF_SOCKET ("sockopt-listen", &opt_setsockopt_listen) |
| IF_SOCKET ("sockopt-string", &opt_setsockopt_string) |
| IF_SOCKS4 ("socksport", &opt_socksport) |
| IF_SOCKS4 ("socksuser", &opt_socksuser) |
| IF_SOCKET ("socktype", &opt_so_type) |
| #if defined(HAVE_STRUCT_IP_MREQ_SOURCE) && defined(IP_ADD_SOURCE_MEMBERSHIP) |
| IF_IP ("source-membership", &opt_ip_add_source_membership) |
| #endif |
| IF_IPAPP ("sourceport", &opt_sourceport) |
| IF_IPAPP ("sp", &opt_sourceport) |
| IF_TERMIOS("start", &opt_vstart) |
| #if HAVE_RESOLV_H |
| IF_IP ("stayopen", &opt_res_stayopen) |
| #endif /* HAVE_RESOLV_H */ |
| IF_EXEC ("stderr", &opt_stderr) |
| #ifdef TCP_STDURG |
| 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 defined(HAVE_SETGRENT) && defined(HAVE_GETGRENT) && defined(HAVE_ENDGRENT) |
| IF_ANY ("su-d", &opt_substuser_delayed) |
| #endif |
| IF_ANY ("su-e", &opt_substuser_early) |
| IF_ANY ("substuser", &opt_substuser) |
| #if defined(HAVE_SETGRENT) && defined(HAVE_GETGRENT) && defined(HAVE_ENDGRENT) |
| IF_ANY ("substuser-delayed", &opt_substuser_delayed) |
| #endif |
| IF_ANY ("substuser-early", &opt_substuser_early) |
| IF_TERMIOS("susp", &opt_vsusp) |
| #ifdef VSWTC |
| IF_TERMIOS("swtc", &opt_vswtc) |
| IF_TERMIOS("swtch", &opt_vswtc) |
| #endif |
| IF_PTY ("symbolic-link", &opt_symbolic_link) |
| #ifdef O_SYNC |
| IF_OPEN ("sync", &opt_o_sync) |
| #elif FS_SYNC_FL |
| IF_ANY ("sync", &opt_fs_sync) |
| #endif |
| #ifdef TCP_SYNCNT |
| IF_TCP ("syncnt", &opt_tcp_syncnt) |
| #endif |
| #ifdef TABDLY |
| # ifdef TAB0 |
| IF_TERMIOS("tab0", &opt_tab0) |
| # endif |
| # ifdef TAB1 |
| IF_TERMIOS("tab1", &opt_tab1) |
| # endif |
| # ifdef TAB2 |
| IF_TERMIOS("tab2", &opt_tab2) |
| # endif |
| # ifdef TAB3 |
| IF_TERMIOS("tab3", &opt_tab3) |
| # endif |
| # if TABDLY_SHIFT >= 0 |
| IF_TERMIOS("tabdly", &opt_tabdly) |
| # endif |
| #endif |
| IF_TERMIOS("tandem", &opt_ixoff) |
| #ifdef TCP_ABORT_THRESHOLD /* HP_UX */ |
| IF_TCP ("tcp-abort-threshold", &opt_tcp_abort_threshold) |
| #endif |
| #ifdef TCP_CONN_ABORT_THRESHOLD /* HP_UX */ |
| IF_TCP ("tcp-conn-abort-threshold", &opt_tcp_conn_abort_threshold) |
| #endif |
| #ifdef TCP_CORK |
| IF_TCP ("tcp-cork", &opt_tcp_cork) |
| #endif |
| #ifdef TCP_DEFER_ACCEPT /* Linux 2.4.0 */ |
| IF_TCP ("tcp-defer-accept", &opt_tcp_defer_accept) |
| #endif |
| #ifdef TCP_INFO /* Linux 2.4.0 */ |
| IF_TCP ("tcp-info", &opt_tcp_info) |
| #endif |
| #ifdef TCP_KEEPCNT /* Linux 2.4.0 */ |
| IF_TCP ("tcp-keepcnt", &opt_tcp_keepcnt) |
| #endif |
| #ifdef TCP_KEEPIDLE /* Linux 2.4.0 */ |
| IF_TCP ("tcp-keepidle", &opt_tcp_keepidle) |
| #endif |
| #ifdef TCP_KEEPINIT /* OSF1 */ |
| IF_TCP ("tcp-keepinit", &opt_tcp_keepinit) |
| #endif |
| #ifdef TCP_KEEPINTVL /* Linux 2.4.0 */ |
| IF_TCP ("tcp-keepintvl", &opt_tcp_keepintvl) |
| #endif |
| #ifdef TCP_LINGER2 /* Linux 2.4.0 */ |
| IF_TCP ("tcp-linger2", &opt_tcp_linger2) |
| #endif |
| #ifdef TCP_MAXSEG |
| IF_TCP ("tcp-maxseg", &opt_tcp_maxseg) |
| IF_TCP ("tcp-maxseg-late", &opt_tcp_maxseg_late) |
| #endif |
| #ifdef TCP_MD5SIG |
| IF_TCP ("tcp-md5sig", &opt_tcp_md5sig) |
| #endif |
| #ifdef TCP_NODELAY |
| IF_TCP ("tcp-nodelay", &opt_tcp_nodelay) |
| #endif |
| #ifdef TCP_NOOPT |
| IF_TCP ("tcp-noopt", &opt_tcp_noopt) |
| #endif |
| #ifdef TCP_NOPUSH |
| IF_TCP ("tcp-nopush", &opt_tcp_nopush) |
| #endif |
| #ifdef TCP_PAWS /* OSF1 */ |
| IF_TCP ("tcp-paws", &opt_tcp_paws) |
| #endif |
| #ifdef TCP_QUICKACK |
| IF_TCP ("tcp-quickack", &opt_tcp_quickack) |
| #endif |
| #ifdef TCP_RFC1323 |
| IF_TCP ("tcp-rfc1323", &opt_tcp_rfc1323) |
| #endif |
| #ifdef TCP_SACK_DISABLE |
| IF_TCP ("tcp-sack-disable", &opt_tcp_sack_disable) |
| #endif |
| #ifdef TCP_SACKENA /* OSF1 */ |
| IF_TCP ("tcp-sackena", &opt_tcp_sackena) |
| #endif |
| #ifdef TCP_SIGNATURE_ENABLE |
| IF_TCP ("tcp-signature-enable", &opt_tcp_signature_enable) |
| #endif |
| #ifdef TCP_STDURG |
| IF_TCP ("tcp-stdurg", &opt_tcp_stdurg) |
| #endif |
| #ifdef TCP_SYNCNT /* Linux 2.4.0 */ |
| IF_TCP ("tcp-syncnt", &opt_tcp_syncnt) |
| #endif |
| #ifdef TCP_TSOPTENA /* OSF1 */ |
| IF_TCP ("tcp-tsoptena", &opt_tcp_tsoptena) |
| #endif |
| #ifdef TCP_WINDOW_CLAMP /* Linux 2.4.0 */ |
| IF_TCP ("tcp-window-clamp", &opt_tcp_window_clamp) |
| #endif |
| #if WITH_LIBWRAP |
| IF_IPAPP ("tcpwrap", &opt_tcpwrappers) |
| IF_IPAPP ("tcpwrap-dir", &opt_tcpwrap_etc) |
| IF_IPAPP ("tcpwrap-etc", &opt_tcpwrap_etc) |
| #if WITH_LIBWRAP && defined(HAVE_HOSTS_ALLOW_TABLE) |
| IF_IPAPP ("tcpwrap-hosts-allow-table", &opt_tcpwrap_hosts_allow_table) |
| #endif |
| #if WITH_LIBWRAP && defined(HAVE_HOSTS_DENY_TABLE) |
| IF_IPAPP ("tcpwrap-hosts-deny-table", &opt_tcpwrap_hosts_deny_table) |
| #endif |
| IF_IPAPP ("tcpwrapper", &opt_tcpwrappers) |
| IF_IPAPP ("tcpwrappers", &opt_tcpwrappers) |
| #endif |
| IF_TERMIOS("termios-cfmakeraw", &opt_termios_cfmakeraw) |
| IF_TERMIOS("termios-rawer", &opt_termios_rawer) |
| #ifdef O_TEXT |
| IF_ANY ("text", &opt_o_text) |
| #endif |
| IF_UNIX ("tightsocklen", &xioopt_unix_tightsocklen) |
| IF_TERMIOS("time", &opt_vtime) |
| #ifdef SO_TIMESTAMP |
| IF_SOCKET ("timestamp", &opt_so_timestamp) |
| #endif |
| IF_TERMIOS("tiocsctty", &opt_tiocsctty) |
| #if WITH_FS && defined(FS_TOPDIR_FL) |
| IF_ANY ("topdir", &opt_fs_topdir) |
| #endif |
| IF_IP ("tos", &opt_ip_tos) |
| IF_TERMIOS("tostop", &opt_tostop) |
| #ifdef IP_TRANSPARENT |
| IF_IP ("transparent", &opt_ip_transparent) |
| #endif |
| IF_OPEN ("trunc", &opt_o_trunc) |
| #if HAVE_FTRUNCATE64 |
| IF_ANY ("truncate", &opt_ftruncate64) |
| #else |
| IF_ANY ("truncate", &opt_ftruncate32) |
| #endif |
| #ifdef TCP_TSOPTENA /* OSF1 */ |
| IF_TCP ("tsoptena", &opt_tcp_tsoptena) |
| #endif |
| IF_IP ("ttl", &opt_ip_ttl) |
| IF_TUN ("tun-device", &opt_tun_device) |
| IF_TUN ("tun-name", &opt_tun_name) |
| IF_TUN ("tun-no-pi", &opt_iff_no_pi) |
| IF_TUN ("tun-type", &opt_tun_type) |
| IF_SOCKET ("type", &opt_so_type) |
| IF_ANY ("uid", &opt_user) |
| IF_NAMED ("uid-e", &opt_user_early) |
| IF_ANY ("uid-l", &opt_user_late) |
| IF_NAMED ("umask", &opt_umask) |
| IF_IP6 ("unicast-hops", &opt_ipv6_unicast_hops) |
| IF_UNIX ("unix-tightsocklen", &xioopt_unix_tightsocklen) |
| IF_NAMED ("unlink", &opt_unlink) |
| IF_NAMED ("unlink-close", &opt_unlink_close) |
| IF_NAMED ("unlink-early", &opt_unlink_early) |
| IF_NAMED ("unlink-late", &opt_unlink_late) |
| #if WITH_FS && defined(FS_UNRM_FL) |
| IF_ANY ("unrm", &opt_fs_unrm) |
| #endif |
| IF_TUN ("up", &opt_iff_up) |
| #ifdef SO_USE_IFBUFS |
| IF_SOCKET ("use-ifbufs", &opt_so_use_ifbufs) |
| IF_SOCKET ("useifbufs", &opt_so_use_ifbufs) |
| #endif /* SO_USE_IFBUFS */ |
| #ifdef SO_USELOOPBACK /* AIX433, Solaris */ |
| IF_SOCKET ("useloopback", &opt_so_useloopback) |
| #endif /* SO_USELOOPBACK */ |
| IF_ANY ("user", &opt_user) |
| IF_NAMED ("user-early", &opt_user_early) |
| IF_ANY ("user-late", &opt_user_late) |
| #if HAVE_RESOLV_H |
| IF_IP ("usevc", &opt_res_usevc) |
| #endif /* HAVE_RESOLV_H */ |
| #ifdef IPV6_V6ONLY |
| IF_IP6 ("v6only", &opt_ipv6_v6only) |
| #endif |
| #ifdef VDISCARD |
| IF_TERMIOS("vdiscard", &opt_vdiscard) |
| #endif |
| #ifdef VDSUSP /* HP-UX */ |
| IF_TERMIOS("vdsusp", &opt_vdsusp) |
| #endif |
| IF_TERMIOS("veof", &opt_veof) |
| IF_TERMIOS("veol", &opt_veol) |
| IF_TERMIOS("veol2", &opt_veol2) |
| IF_TERMIOS("verase", &opt_verase) |
| IF_OPENSSL("verify", &opt_openssl_verify) |
| IF_TERMIOS("vintr", &opt_vintr) |
| IF_TERMIOS("vkill", &opt_vkill) |
| IF_TERMIOS("vlnext", &opt_vlnext) |
| IF_TERMIOS("vmin", &opt_vmin) |
| IF_TERMIOS("vquit", &opt_vquit) |
| #ifdef VREPRINT |
| IF_TERMIOS("vreprint", &opt_vreprint) |
| #endif |
| IF_TERMIOS("vstart", &opt_vstart) |
| IF_TERMIOS("vstop", &opt_vstop) |
| IF_TERMIOS("vsusp", &opt_vsusp) |
| #ifdef VSWTC |
| IF_TERMIOS("vswtc", &opt_vswtc) |
| #endif |
| #ifdef VTDLY |
| # ifdef VT0 |
| IF_TERMIOS("vt0", &opt_vt0) |
| # endif |
| # ifdef VT1 |
| IF_TERMIOS("vt1", &opt_vt1) |
| # endif |
| IF_TERMIOS("vtdly", &opt_vtdly) |
| #endif |
| IF_TERMIOS("vtime", &opt_vtime) |
| #ifdef VWERASE |
| IF_TERMIOS("vwerase", &opt_vwerase) |
| #endif |
| #if HAVE_PTY && HAVE_POLL |
| IF_PTY ("wait-slave", &opt_pty_wait_slave) |
| #endif /* HAVE_PTY && HAVE_POLL */ |
| IF_ANY ("waitlock", &opt_waitlock) |
| #if HAVE_PTY && HAVE_POLL |
| IF_PTY ("waitslave", &opt_pty_wait_slave) |
| #endif /* HAVE_PTY && HAVE_POLL */ |
| #ifdef VWERASE |
| IF_TERMIOS("werase", &opt_vwerase) |
| #endif |
| #ifdef TCP_WINDOW_CLAMP /* Linux 2.4.0 */ |
| IF_TCP ("window-clamp", &opt_tcp_window_clamp) |
| #endif |
| #if WITH_LIBWRAP |
| IF_IPAPP ("wrap", &opt_tcpwrappers) |
| #endif |
| IF_OPEN ("wronly", &opt_o_wronly) |
| #ifdef XCASE |
| IF_TERMIOS("xcase", &opt_xcase) |
| #endif |
| #if defined(TABDLY) && defined(XTABS) |
| IF_TERMIOS("xtabs", &opt_xtabs) |
| #endif |
| { NULL } |
| } ; |
| |
| |
| /* walks the text argument a and writes its options that conform to groups |
| to the array opts. Uses the option table 'optionnames'. |
| returns 0 on success, -1 on error, 1 on unknown/wrong option |
| */ |
| int parseopts(const char **a, unsigned int groups, struct opt **opts) { |
| |
| return parseopts_table(a, groups, opts, optionnames, |
| sizeof(optionnames)/sizeof(struct optname)-1); |
| } |
| |
| |
| /* walks the text argument a and writes its options that conform to groups |
| to the array opts. Uses the specified option table. |
| returns 0 on success, -1 on error, 1 on unknown/wrong option |
| */ |
| int parseopts_table(const char **a, unsigned int groups, struct opt **opts, |
| const struct optname optionnames[], size_t optionnum) { |
| int i=0; |
| struct opt *opt; |
| bool assign; |
| const char *a0 = *a; |
| unsigned long ulongval; |
| long slongval; |
| long long slonglongval; |
| char token[2048], *tokp; size_t len; |
| int parsres; |
| int result; |
| uint8_t optbuf[256]; size_t optlen; |
| const char *endkey[6+1]; |
| const char *endval[5+1]; |
| const char *assign_str = "="; |
| const char *hquotes[] = { |
| "'", |
| NULL |
| } ; |
| const char *squotes[] = { |
| "\"", |
| NULL |
| } ; |
| const char *nests[] = { |
| "(", ")", |
| "[", "]", |
| "{", "}", |
| NULL |
| } ; |
| |
| i = 0; |
| /*endkey[i++] = xioopts.chainsep;*/ /* default: "|" */ |
| endkey[i++] = xioopts.pipesep; /* default: "!!" */ |
| endkey[i++] = ","/*xioopts.comma*/; /* default: "," */ |
| endkey[i++] = "="; |
| endkey[i++] = NULL; |
| |
| i = 0; |
| /*endval[i++] = xioopts.chainsep;*/ /* default: "|" */ |
| endval[i++] = xioopts.pipesep; /* default: "!!" */ |
| endval[i++] = ","/*xioopts.comma*/; /* default: "," */ |
| endval[i++] = NULL; |
| |
| i = 0; |
| *opts = Malloc((i+8)*sizeof(struct opt)); |
| if (*opts == NULL) { |
| return -1; |
| } |
| if (*a == NULL) { |
| (*opts)[i].desc = ODESC_END; |
| return 0; |
| } |
| |
| while (true) { |
| const struct optname *ent; |
| |
| if (a == NULL || *a == NULL || **a == '\0') |
| break; |
| |
| while (!strncmp(*a, ",", strlen(","))) { (*a) += strlen(","); } |
| a0 = *a; |
| |
| len = sizeof(token); tokp = token; |
| parsres = |
| nestlex(a, &tokp, &len, endkey, hquotes, squotes, nests, |
| true, true, false); |
| if (parsres < 0) { |
| Error1("option too long: \"%s\"", *a); |
| return -1; |
| } else if (parsres > 0) { |
| Error1("syntax error in \"%s\"", *a); |
| return -1; |
| } |
| if (tokp == token) { |
| /* no option found */ |
| break; |
| } |
| *tokp = '\0'; |
| |
| ent = (struct optname *) |
| keyw((struct wordent *)optionnames, token, optionnum); |
| if (ent == NULL) { |
| Error1("parseopts_table(): unknown option \"%s\"", token); |
| continue; |
| } |
| |
| if (!(ent->desc->group & groups) && !(ent->desc->group & GROUP_ANY) && |
| !xioopts_ignoregroups) { |
| Error1("parseopts_table(): option \"%s\" not supported with this address type", |
| token /*a0*/); |
| Info2("parseopts_table() groups=%08x, ent->group=%08x", |
| groups, ent->desc->group); |
| #if 0 |
| continue; |
| #endif |
| } |
| (*opts)[i].desc = ent->desc; |
| |
| if (!strncmp(*a, assign_str, strlen(assign_str))) { |
| /* there is an assignment (mostly "=") */ |
| (*a) += strlen(assign_str); |
| len = sizeof(token); tokp = token; |
| parsres = |
| nestlex(a, &tokp, &len, endval, hquotes, squotes, nests, |
| true, true, false); |
| if (parsres < 0) { |
| Error1("option too long: \"%s\"", *a); |
| return -1; |
| } else if (parsres > 0) { |
| Error1("syntax error in \"%s\"", *a); |
| return -1; |
| } |
| *tokp = '\0'; |
| assign = true; |
| |
| } else { |
| assign = false; |
| } |
| opt = &(*opts)[i]; |
| |
| switch (ent->desc->type) { |
| case TYPE_CONST: |
| if (assign) { |
| Error1("no value permitted for option \"%s\"", |
| ent->desc->defname); |
| continue; |
| } |
| Info1("setting option \"%s\"", ent->desc->defname); |
| break; |
| case TYPE_BIN: |
| if (!assign) { Error1("option \"%s\": value required", a0); |
| continue; } |
| optlen = 0; |
| if ((result = dalan(token, optbuf, &optlen, sizeof(optbuf), 'i')) != 0) { |
| Error1("parseopts_table(): problem with \"%s\" data", token); |
| continue; |
| } |
| if (((*opts)[i].value.u_bin.b_data = memdup(optbuf, optlen)) == NULL) { |
| Error1("memdup(, "F_Zu"): out of memory", optlen); |
| return -1; |
| } |
| (*opts)[i].value.u_bin.b_len = optlen; |
| break; |
| case TYPE_BYTE: |
| if (assign) { |
| unsigned long ul; |
| char *rest; |
| ul = Strtoul(token, &rest, 0, a0); |
| if (ul > UCHAR_MAX) { |
| Error3("parseopts(): option \"%s\": byte value exceeds limit (%lu vs. %u), using max", |
| a0, ul, UCHAR_MAX); |
| (*opts)[i].value.u_byte = UCHAR_MAX; |
| } else { |
| (*opts)[i].value.u_byte = ul; |
| } |
| } else { |
| (*opts)[i].value.u_byte = 1; |
| } |
| Info2("setting option \"%s\" to %d", ent->desc->defname, |
| (*opts)[i].value.u_byte); |
| break; |
| #if HAVE_BASIC_OFF_T==3 |
| case TYPE_OFF32: |
| #endif |
| case TYPE_INT: |
| if (assign) { |
| char *rest; |
| (*opts)[i].value.u_int = Strtoul(token, &rest, 0, a0); |
| } else { |
| (*opts)[i].value.u_int = 1; |
| } |
| Info2("setting option \"%s\" to %d", ent->desc->defname, |
| (*opts)[i].value.u_int); |
| break; |
| case TYPE_BOOL: |
| if (!assign) { |
| (*opts)[i].value.u_bool = 1; |
| } else { |
| char *rest; |
| (*opts)[i].value.u_bool = Strtoul(token, &rest, 0, a0); |
| } |
| Info2("setting option \"%s\" to %d", ent->desc->defname, |
| (*opts)[i].value.u_bool); |
| break; |
| |
| #if HAVE_BASIC_SIZE_T==4 |
| case TYPE_SIZE_T: |
| #endif |
| case TYPE_UINT: |
| if (!assign) { |
| (*opts)[i].value.u_uint = 1; |
| } else { |
| char *rest; |
| ulongval = Strtoul(token, &rest, 0, a0); |
| (*opts)[i].value.u_uint = ulongval; |
| } |
| Info2("setting option \"%s\" to %u", ent->desc->defname, |
| (*opts)[i].value.u_uint); |
| break; |
| |
| #if HAVE_BASIC_SIZE_T==2 |
| case TYPE_SIZE_T: |
| #endif |
| case TYPE_USHORT: |
| if (!assign) { |
| (*opts)[i].value.u_ushort = 1; |
| } else { |
| char *rest; |
| ulongval = Strtoul(token, &rest, 0, a0); |
| (*opts)[i].value.u_ushort = ulongval; |
| } |
| Info2("setting option \"%s\" to %u", ent->desc->defname, |
| (*opts)[i].value.u_ushort); |
| break; |
| |
| #if HAVE_BASIC_OFF_T==5 |
| case TYPE_OFF32: |
| #endif |
| #if HAVE_STAT64 && defined(HAVE_BASIC_OFF64_T) && HAVE_BASIC_OFF64_T==5 |
| case TYPE_OFF64: |
| #endif |
| case TYPE_LONG: |
| if (!assign) { |
| (*opts)[i].value.u_long = 1; |
| } else { |
| char *rest; |
| slongval = Strtoul(token, &rest, 0, a0); |
| (*opts)[i].value.u_long = slongval; |
| } |
| Info2("setting option \"%s\" to %lu", ent->desc->defname, |
| (*opts)[i].value.u_long); |
| break; |
| |
| #if HAVE_BASIC_SIZE_T==6 |
| case TYPE_SIZE_T: |
| #endif |
| case TYPE_ULONG: |
| if (!assign) { |
| (*opts)[i].value.u_ulong = 1; |
| } else { |
| char *rest; |
| ulongval = Strtoul(token, &rest, 0, a0); |
| (*opts)[i].value.u_ulong = ulongval; |
| } |
| Info2("setting option \"%s\" to %lu", ent->desc->defname, |
| (*opts)[i].value.u_ulong); |
| break; |
| |
| #if HAVE_BASIC_OFF_T==7 |
| case TYPE_OFF32: |
| #endif |
| #if HAVE_TYPE_LONGLONG |
| case TYPE_LONGLONG: |
| # if HAVE_STAT64 && defined(HAVE_BASIC_OFF64_T) && HAVE_BASIC_OFF64_T==7 |
| case TYPE_OFF64: |
| # endif |
| if (!assign) { |
| (*opts)[i].value.u_longlong = 1; |
| } else { |
| char *rest; |
| # if HAVE_STRTOLL |
| slonglongval = Strtoll(token, &rest, 0, a0); |
| # else |
| /* in this case, input value range is limited */ |
| slonglongval = Strtol(token, &rest, 0, a0); |
| # endif /* HAVE_STRTOLL */ |
| if (*rest != '\0') { |
| Error1("parseopts(): trailing garbage in numerical arg of option \"%s\"", a0); |
| } |
| (*opts)[i].value.u_longlong = slonglongval; |
| } |
| Info2("setting option \"%s\" to %Lu", ent->desc->defname, |
| (*opts)[i].value.u_longlong); |
| break; |
| #endif /* HAVE_TYPE_LONGLONG */ |
| |
| case TYPE_UIDT: |
| if (!assign) { |
| Error1("option \"%s\": value required", a0); |
| continue; |
| } |
| if (isdigit((*token)&0xff)) { |
| char *rest; |
| (*opts)[i].value.u_uidt = Strtoul(token, &rest, 0, a0); |
| } else { |
| struct passwd *pwd; |
| if ((pwd = getpwnam(token)) == NULL) { |
| Error1("getpwnam(\"%s\"): no such user", token); |
| continue; |
| } |
| (*opts)[i].value.u_uidt = getpwnam(token)->pw_uid; |
| } |
| Info2("setting option \"%s\" to %u", ent->desc->defname, |
| (*opts)[i].value.u_uidt); |
| break; |
| |
| case TYPE_GIDT: |
| if (!assign) { Error1("option \"%s\": value required", a0); |
| continue; } |
| if (isdigit((token[0])&0xff)) { |
| char *rest; |
| (*opts)[i].value.u_gidt = Strtoul(token, &rest, 0, a0); |
| } else { |
| struct group *grp; |
| grp = getgrnam(token); |
| if (grp == NULL) { |
| Error1("getgrnam(\"%s\"): no such group", token); |
| continue; |
| } |
| (*opts)[i].value.u_gidt = grp->gr_gid; |
| } |
| Info2("setting option \"%s\" to %u", ent->desc->defname, |
| (*opts)[i].value.u_gidt); |
| break; |
| |
| case TYPE_MODET: |
| if (!assign) { Error1("option \"%s\": value required", a0); |
| continue; |
| } |
| { |
| char *rest; |
| (*opts)[i].value.u_modet = Strtoul(token, &rest, 8, a0); |
| } |
| Info2("setting option \"%s\" to %u", ent->desc->defname, |
| (*opts)[i].value.u_modet); |
| break; |
| |
| case TYPE_STRING: |
| if (!assign) { |
| Error1("option \"%s\": value required", a0); |
| continue; |
| } |
| if (((*opts)[i].value.u_string = strdup(token)) == NULL) { |
| Error("out of memory"); return -1; |
| } |
| Info2("setting option \"%s\" to \"%s\"", ent->desc->defname, |
| (*opts)[i].value.u_string); |
| break; |
| |
| case TYPE_STRING_NULL: |
| if (!assign) { |
| (*opts)[i].value.u_string = NULL; |
| Info1("setting option \"%s\" to NULL", ent->desc->defname); |
| } else { |
| (*opts)[i].value.u_string = strdup(token); |
| Info2("setting option \"%s\" to \"%s\"", ent->desc->defname, |
| (*opts)[i].value.u_string); |
| } |
| break; |
| |
| #if LATER |
| case TYPE_INT3: |
| |
| break; |
| #endif |
| |
| case TYPE_TIMEVAL: |
| if (!assign) { |
| Error1("option \"%s\": value required", a0); |
| continue; |
| } else { |
| double val; |
| char *rest; |
| val = Strtod(token, &rest, a0); |
| if (val == HUGE_VAL || val == -HUGE_VAL || |
| val == 0.0 && errno == ERANGE) { |
| Error2("strtod(\"%s\", NULL): %s", token, strerror(errno)); |
| val = 0.0; |
| } |
| (*opts)[i].value.u_timeval.tv_sec = val; |
| (*opts)[i].value.u_timeval.tv_usec = |
| (val-(*opts)[i].value.u_timeval.tv_sec+0.0000005) * 1000000; |
| } |
| break; |
| |
| #if HAVE_STRUCT_TIMESPEC |
| case TYPE_TIMESPEC: |
| if (!assign) { |
| Error1("option \"%s\": value required", a0); |
| continue; |
| } else { |
| double val; |
| char *rest; |
| val = Strtod(token, &rest, a0); |
| if (val == HUGE_VAL || val == -HUGE_VAL || |
| val == 0.0 && errno == ERANGE) { |
| Error2("strtod(\"%s\", NULL): %s", token, strerror(errno)); |
| val = 0.0; |
| } |
| (*opts)[i].value.u_timespec.tv_sec = val; |
| (*opts)[i].value.u_timespec.tv_nsec = |
| (val-(*opts)[i].value.u_timespec.tv_sec) * 1000000000.; |
| } |
| break; |
| #endif /* HAVE_STRUCT_TIMESPEC */ |
| |
| #if HAVE_STRUCT_LINGER |
| case TYPE_LINGER: |
| if (!assign) { |
| Error1("option \"%s\": value required", a0); |
| continue; |
| } |
| (*opts)[i].value.u_linger.l_onoff = 1; |
| { |
| char *rest; |
| (*opts)[i].value.u_linger.l_linger = Strtoul(token, &rest, 0, a0); |
| } |
| Info3("setting option \"%s\" to {%d,%d}", ent->desc->defname, |
| (*opts)[i].value.u_linger.l_onoff, |
| (*opts)[i].value.u_linger.l_linger); |
| break; |
| #endif /* HAVE_STRUCT_LINGER */ |
| |
| case TYPE_INT_INT: |
| case TYPE_INT_INTP: |
| if (!assign) { |
| Error1("option \"%s\": values required", a0); |
| continue; |
| } |
| { |
| char *rest; |
| (*opts)[i].value.u_int = strtoul(token, &rest, 0); |
| if (token == rest) { |
| Error1("parseopts(): missing numerical value of option \"%s\"", a0); |
| } |
| if (*rest == '\0') { |
| Error1("parseopts(): option \"%s\": 2 arguments required", |
| ent->desc->defname); |
| } |
| ++rest; |
| (*opts)[i].value2.u_int = Strtoul(rest, &rest, 0, a0); |
| } |
| Info3("setting option \"%s\" to %d:%d", ent->desc->defname, |
| (*opts)[i].value.u_int, (*opts)[i].value2.u_int); |
| break; |
| |
| case TYPE_INT_BIN: |
| if (!assign) { |
| Error1("option \"%s\": values required", a0); |
| continue; |
| } |
| { |
| char *rest; |
| (*opts)[i].value.u_int = strtoul(token, &rest, 0); |
| if (token == rest) { |
| Error1("parseopts(): missing numerical value of option \"%s\"", a0); |
| } |
| if (*rest != ':') { |
| Error1("parseopts(): trailing garbage in numerical arg of option \"%s\"", a0); |
| } |
| if (*rest == '\0') { |
| Error1("parseopts(): option \"%s\": 2 arguments required", |
| ent->desc->defname); |
| } |
| ++rest; |
| optlen = 0; |
| if ((result = dalan(rest, optbuf, &optlen, sizeof(optbuf), 'i')) != 0) { |
| Error1("parseopts_table(): problem with \"%s\" data", rest); |
| continue; |
| } |
| if (((*opts)[i].value2.u_bin.b_data = memdup(optbuf, optlen)) == NULL) { |
| Error1("memdup(, "F_Zu"): out of memory", optlen); |
| return -1; |
| } |
| (*opts)[i].value2.u_bin.b_len = optlen; |
| } |
| Info2("setting option \"%s\" to %d:..."/*!!!*/, ent->desc->defname, |
| (*opts)[i].value.u_int); |
| break; |
| |
| case TYPE_INT_STRING: |
| if (!assign) { |
| Error1("option \"%s\": values required", a0); |
| continue; |
| } |
| { |
| char *rest; |
| (*opts)[i].value.u_int = strtoul(token, &rest, 0); |
| if (token == rest) { |
| Error1("parseopts(): missing numerical value of option \"%s\"", a0); |
| } |
| if (*rest != ':') { |
| Error1("parseopts(): trailing garbage in numerical arg of option \"%s\"", a0); |
| } |
| if (*rest == '\0') { |
| Error1("parseopts(): option \"%s\": 2 arguments required", |
| ent->desc->defname); |
| } |
| ++rest; |
| if (((*opts)[i].value2.u_string = strdup(rest)) == NULL) { |
| Error("out of memory"); return -1; |
| } |
| } |
| Info3("setting option \"%s\" to %d:\"%s\"", ent->desc->defname, |
| (*opts)[i].value.u_int, (*opts)[i].value2.u_string); |
| break; |
| |
| case TYPE_INT_INT_INT: |
| if (!assign) { |
| Error1("option \"%s\": values required", a0); |
| continue; |
| } |
| { |
| char *rest; |
| (*opts)[i].value.u_int = strtoul(token, &rest, 0); |
| if (token == rest) { |
| Error1("parseopts(): missing numerical value of option \"%s\"", a0); |
| } |
| if (*rest == '\0') { |
| Error1("parseopts(): option \"%s\": 3 arguments required", ent->desc->defname); |
| } |
| if (*rest != ':') { |
| Error1("parseopts(): trailing garbage in 1st numerical arg of option \"%s\"", a0); |
| } |
| ++rest; |
| (*opts)[i].value2.u_int = strtoul(rest, &rest, 0); |
| if (token == rest) { |
| Error1("parseopts(): missing numerical value of option \"%s\"", a0); |
| } |
| if (*rest == '\0') { |
| Error1("parseopts(): option \"%s\": 3 arguments required", ent->desc->defname); |
| } |
| if (*rest != ':') { |
| Error1("parseopts(): trailing garbage in 2nd numerical arg of option \"%s\"", a0); |
| } |
| ++rest; |
| (*opts)[i].value3.u_int = Strtoul(rest, &rest, 0, a0); |
| } |
| Info4("setting option \"%s\" to %d:%d:%d", ent->desc->defname, |
| (*opts)[i].value.u_int, (*opts)[i].value2.u_int, (*opts)[i].value3.u_int); |
| break; |
| |
| case TYPE_INT_INT_BIN: |
| case TYPE_INT_INT_GENERIC: |
| if (!assign) { |
| Error1("option \"%s\": values required", a0); |
| continue; |
| } |
| { |
| char *rest; |
| (*opts)[i].value.u_int = strtoul(token, &rest, 0); |
| if (token == rest) { |
| Error1("parseopts(): missing numerical value of option \"%s\"", a0); |
| } |
| if (*rest == '\0') { |
| Error1("option \"%s\": 3 arguments required", |
| ent->desc->defname); |
| } |
| if (*rest != ':') { |
| Error1("parseopts(): trailing garbage in 1st numerical arg of option \"%s\"", a0); |
| } |
| ++rest; |
| (*opts)[i].value2.u_int = strtoul(rest, &rest, 0); |
| if (token == rest) { |
| Error1("parseopts(): missing numerical value of option \"%s\"", a0); |
| } |
| if (*rest == '\0') { |
| Error1("option \"%s\": 3 arguments required", |
| ent->desc->defname); |
| } |
| if (*rest != ':') { |
| Error1("parseopts(): trailing garbage in 2nd numerical arg of option \"%s\"", a0); |
| } |
| ++rest; |
| optlen = 0; |
| if ((result = dalan(rest, optbuf, &optlen, sizeof(optbuf), 'i')) != 0) { |
| Error1("parseopts_table(): problem with \"%s\" data", rest); |
| continue; |
| } |
| if (((*opts)[i].value3.u_bin.b_data = memdup(optbuf, optlen)) == NULL) { |
| Error1("memdup(, "F_Zu"): out of memory", optlen); |
| return -1; |
| } |
| (*opts)[i].value3.u_bin.b_len = optlen; |
| } |
| Info3("setting option \"%s\" to %d:%d:..."/*!!!*/, ent->desc->defname, |
| (*opts)[i].value.u_int, (*opts)[i].value2.u_int); |
| break; |
| |
| case TYPE_INT_INT_STRING: |
| if (!assign) { |
| Error1("option \"%s\": values required", a0); |
| continue; |
| } |
| { |
| char *rest; |
| (*opts)[i].value.u_int = strtoul(token, &rest, 0); |
| if (token == rest) { |
| Error1("parseopts(): missing numerical value of option \"%s\"", a0); |
| } |
| if (*rest == '\0') { |
| Error1("parseopts(): option \"%s\": 3 arguments required", |
| ent->desc->defname); |
| } |
| if (*rest != ':') { |
| Error1("parseopts(): trailing garbage in 1st numerical arg of option \"%s\"", a0); |
| } |
| ++rest; |
| (*opts)[i].value2.u_int = strtoul(rest, &rest, 0); |
| if (token == rest) { |
| Error1("parseopts(): missing numerical value of option \"%s\"", a0); |
| } |
| if (*rest == '\0') { |
| Error1("parseopts(): option \"%s\": 3 arguments required", |
| ent->desc->defname); |
| } |
| if (*rest != ':') { |
| Error1("parseopts(): trailing garbage in 2nd numerical arg of option \"%s\"", a0); |
| } |
| ++rest; |
| if (((*opts)[i].value3.u_string = strdup(rest)) == NULL) { |
| Error("out of memory"); return -1; |
| } |
| } |
| Info4("setting option \"%s\" to %d:%d:\"%s\"", ent->desc->defname, |
| (*opts)[i].value.u_int, (*opts)[i].value2.u_int, |
| (*opts)[i].value3.u_string); |
| break; |
| #if defined(HAVE_STRUCT_IP_MREQ) || defined (HAVE_STRUCT_IP_MREQN) |
| |
| case TYPE_IP_MREQN: |
| { |
| /* we do not resolve the addresses here because we do not yet know |
| if we are coping with a IPv4 or IPv6 socat address */ |
| const char *ends[] = { ":", NULL }; |
| const char *nests[] = { "[","]", NULL }; |
| char buff[512], *buffp=buff; size_t bufspc = sizeof(buff)-1; |
| |
| /* parse first IP address, expect ':' */ |
| tokp = token; |
| /*! result= */ |
| parsres = |
| nestlex((const char **)&tokp, &buffp, &bufspc, |
| ends, NULL, NULL, nests, |
| true, false, false); |
| if (parsres < 0) { |
| Error1("option too long: \"%s\"", *a); |
| return -1; |
| } else if (parsres > 0) { |
| Error1("syntax error in \"%s\"", *a); |
| return -1; |
| } |
| if (*tokp != ':') { |
| Error1("syntax in option %s: missing ':'", token); |
| } |
| *buffp++ = '\0'; |
| (*opts)[i].value.u_ip_mreq.multiaddr = strdup(buff); /*!!! NULL */ |
| |
| ++tokp; |
| /* parse second IP address, expect ':' or '\0'' */ |
| buffp = buff; |
| /*! result= */ |
| parsres = |
| nestlex((const char **)&tokp, &buffp, &bufspc, |
| ends, NULL, NULL, nests, |
| true, false, false); |
| if (parsres < 0) { |
| Error1("option too long: \"%s\"", *a); |
| return -1; |
| } else if (parsres > 0) { |
| Error1("syntax error in \"%s\"", *a); |
| return -1; |
| } |
| *buffp++ = '\0'; |
| (*opts)[i].value.u_ip_mreq.param2 = strdup(buff); /*!!! NULL */ |
| |
| #if HAVE_STRUCT_IP_MREQN |
| if (*tokp++ == ':') { |
| strncpy((*opts)[i].value.u_ip_mreq.ifindex, tokp, IF_NAMESIZE); /* ok */ |
| Info4("setting option \"%s\" to {\"%s\",\"%s\",\"%s\"}", |
| ent->desc->defname, |
| (*opts)[i].value.u_ip_mreq.multiaddr, |
| (*opts)[i].value.u_ip_mreq.param2, |
| (*opts)[i].value.u_ip_mreq.ifindex); |
| } else { |
| (*opts)[i].value.u_ip_mreq.ifindex[0] = '\0'; |
| Info3("setting option \"%s\" to {\"%s\",\"%s\"}", |
| ent->desc->defname, |
| (*opts)[i].value.u_ip_mreq.multiaddr, |
| (*opts)[i].value.u_ip_mreq.param2); |
| } |
| #else /* !HAVE_STRUCT_IP_MREQN */ |
| Info3("setting option \"%s\" to {0x%08x,0x%08x}", |
| ent->desc->defname, |
| (*opts)[i].value.u_ip_mreq.multiaddr, |
| (*opts)[i].value.u_ip_mreq.param2); |
| #endif /* !HAVE_STRUCT_IP_MREQN */ |
| } |
| break; |
| #endif /* defined(HAVE_STRUCT_IP_MREQ) || defined (HAVE_STRUCT_IP_MREQN) */ |
| |
| #if defined(HAVE_STRUCT_IP_MREQ_SOURCE) && defined(IP_ADD_SOURCE_MEMBERSHIP) |
| case TYPE_IP_MREQ_SOURCE: |
| xiotype_ip_add_source_membership(token, ent, opt); |
| break; |
| #endif |
| |
| #if WITH_IP4 |
| case TYPE_IP4NAME: |
| { |
| struct sockaddr_in sa; socklen_t salen = sizeof(sa); |
| const char *ends[] = { NULL }; |
| const char *nests[] = { "[","]", NULL }; |
| char buff[512], *buffp=buff; size_t bufspc = sizeof(buff)-1; |
| |
| tokp = token; |
| parsres = |
| nestlex((const char **)&tokp, &buffp, &bufspc, |
| ends, NULL, NULL, nests, |
| true, false, false); |
| if (parsres < 0) { |
| Error1("option too long: \"%s\"", *a); |
| return -1; |
| } else if (parsres > 0) { |
| Error1("syntax error in \"%s\"", *a); |
| return -1; |
| } |
| if (*tokp != '\0') { |
| Error1("trailing data in option \"%s\"", token); |
| } |
| *buffp = '\0'; |
| if (xiogetaddrinfo(buff, NULL, AF_INET, SOCK_DGRAM, IPPROTO_IP, |
| (union sockaddr_union *)&sa, &salen, |
| 0, 0/*!!!*/) != STAT_OK) { |
| opt->desc = ODESC_ERROR; continue; |
| } |
| opt->value.u_ip4addr = sa.sin_addr; |
| } |
| break; |
| #endif /* defined(WITH_IP4) */ |
| |
| case TYPE_GENERIC: |
| if (!assign) { |
| (*opts)[i].value.u_int = 1; |
| } else { |
| int rc; |
| size_t binlen = 64; /*!!!*/ |
| if (((*opts[i]).value.u_bin.b_data = Malloc(binlen)) == NULL) Error("!!!"); |
| (*opts)[i].value.u_bin.b_len = 0; |
| rc = dalan(token, (*opts)[i].value.u_bin.b_data, |
| &(*opts)[i].value.u_bin.b_len, binlen, 'i'); |
| if (rc != 0) { |
| Error("!!!"); |
| } |
| //(*opts)[i].value.u_bin.b_len |
| } |
| break; |
| |
| default: |
| Error2("parseopts_table(): internal error on option \"%s\": unimplemented type %d", |
| ent->desc->defname, ent->desc->type); |
| continue; |
| } |
| |
| ++i; |
| if ((i % 8) == 0) { |
| *opts = Realloc(*opts, (i+8) * sizeof(struct opt)); |
| if (*opts == NULL) { |
| return -1; |
| } |
| } |
| } |
| |
| /*(*opts)[i+1].desc = ODESC_END;*/ |
| (*opts)[i].desc = ODESC_END; |
| return 0; |
| } |
| |
| |
| /* look for an option with the given properties |
| return a pointer to the first matching valid option in the list |
| Returns NULL when no matching option found */ |
| const struct opt *searchopt(const struct opt *opts, unsigned int groups, enum e_phase from, enum e_phase to, |
| enum e_func func) { |
| int i; |
| |
| if (!opts) return NULL; |
| |
| /* remember: struct opt are in an array */ |
| i = 0; |
| while (opts[i].desc != ODESC_END) { |
| if (opts[i].desc != ODESC_DONE && |
| (groups == 0 || (groups && (opts[i].desc->group&groups))) && |
| (from == 0 || (from <= opts[i].desc->phase)) && |
| (to == 0 || (opts[i].desc->phase <= to)) && |
| (func == 0 || (opts[i].desc->func == func))) { |
| return &opts[i]; |
| } |
| ++i; |
| } |
| return NULL; |
| } |
| |
| /* copy the already parsed options for repeated application, but only those |
| matching groups ANY and <groups> */ |
| struct opt *copyopts(const struct opt *opts, unsigned int groups) { |
| struct opt *new; |
| int i, j, n; |
| |
| if (!opts) return NULL; |
| |
| /* just count the options in the array */ |
| i = 0; while (opts[i].desc != ODESC_END) { |
| ++i; |
| } |
| n = i+1; |
| |
| new = Malloc(n * sizeof(struct opt)); |
| if (new == NULL) { |
| return NULL; |
| } |
| |
| i = 0, j = 0; |
| while (i < n-1) { |
| if (opts[i].desc == ODESC_DONE) { |
| new[j].desc = ODESC_DONE; |
| } else if ((opts[i].desc->group & (GROUP_ANY&~GROUP_PROCESS)) || |
| (opts[i].desc->group & groups)) { |
| new[j++] = opts[i]; |
| } |
| ++i; |
| } |
| new[j].desc = ODESC_END; |
| return new; |
| } |
| |
| /* move options to a new options list |
| move only those matching <groups> */ |
| struct opt *moveopts(struct opt *opts, unsigned int groups) { |
| struct opt *new; |
| int i, j, n; |
| |
| if (!opts) return NULL; |
| |
| /* just count the options in the array */ |
| i = 0; j = 0; while (opts[i].desc != ODESC_END) { |
| if (opts[i].desc != ODESC_DONE && |
| opts[i].desc != ODESC_ERROR) |
| ++j; |
| ++i; |
| } |
| n = i; |
| |
| new = Malloc((j+1) * sizeof(struct opt)); |
| if (new == NULL) { |
| return NULL; |
| } |
| |
| i = 0, j = 0; |
| while (i < n) { |
| if (opts[i].desc == ODESC_DONE || |
| opts[i].desc == ODESC_ERROR) { |
| ++i; continue; |
| } else if (opts[i].desc->group & groups) { |
| new[j++] = opts[i]; |
| opts[i].desc = ODESC_DONE; |
| } |
| ++i; |
| } |
| new[j].desc = ODESC_END; |
| return new; |
| } |
| |
| /* return the number of yet unconsumed options; -1 on error */ |
| int leftopts(const struct opt *opts) { |
| const struct opt *opt = opts; |
| int num = 0; |
| |
| if (!opts) return 0; |
| |
| while (opt->desc != ODESC_END) { |
| if (opt->desc != ODESC_DONE) { |
| ++num; |
| } |
| ++opt; |
| } |
| return num; |
| } |
| |
| /* show as warning which options are still unused */ |
| int showleft(const struct opt *opts) { |
| const struct opt *opt = opts; |
| |
| while (opt->desc != ODESC_END) { |
| if (opt->desc != ODESC_DONE) { |
| Warn1("showleft(): option \"%s\" not inquired", opt->desc->defname); |
| } |
| ++opt; |
| } |
| return 0; |
| } |
| |
| |
| /* determines the address group from mode_t */ |
| /* does not set GROUP_FD; cannot determine GROUP_TERMIOS ! */ |
| int _groupbits(mode_t mode) { |
| unsigned int result = 0; |
| |
| switch ((mode&S_IFMT)>>12) { |
| case (S_IFIFO>>12): /* 1, FIFO */ |
| result = GROUP_FIFO; break; |
| case (S_IFCHR>>12): /* 2, character device */ |
| result = GROUP_CHR|GROUP_TERMIOS; break; |
| case (S_IFDIR>>12): /* 4, directory !!! not supported */ |
| result = GROUP_NONE; break; |
| case (S_IFBLK>>12): /* 6, block device */ |
| result = GROUP_BLK; break; |
| case (S_IFREG>>12): /* 8, regular file */ |
| result = GROUP_REG; break; |
| case (S_IFLNK>>12): /* 10, symbolic link !!! not supported */ |
| result = GROUP_NONE; break; |
| #ifdef S_IFSOCK |
| case (S_IFSOCK>>12): /* 12, socket */ |
| result = GROUP_SOCKET|GROUP_SOCK_UNIX; break; |
| #else |
| default: /* some systems (pure POSIX.1) do not know S_IFSOCK */ |
| result = GROUP_SOCKET|GROUP_SOCK_UNIX; break; |
| #endif |
| } |
| Debug2("_groupbits(%d) -> %d", mode, result); |
| return result; |
| } |
| |
| /* does not set GROUP_FD */ |
| int groupbits(int fd) { |
| #if HAVE_STAT64 |
| struct stat64 buf; |
| #else |
| struct stat buf; |
| #endif /* !HAVE_STAT64 */ |
| int result; |
| |
| if ( |
| #if HAVE_STAT64 |
| Fstat64(fd, &buf) < 0 |
| #else |
| Fstat(fd, &buf) < 0 |
| #endif /* !HAVE_STAT64 */ |
| ) { |
| Error4("groupbits(%d): fstat(%d, %p): %s", |
| fd, fd, &buf, strerror(errno)); |
| return -1; |
| } |
| result = _groupbits(buf.st_mode&S_IFMT); |
| if (result == GROUP_CHR) { |
| if (Isatty(fd) > 0) { |
| result |= GROUP_TERMIOS; |
| } |
| } |
| return result; |
| } |
| |
| #if 0 /* currently not used */ |
| int retropt(struct opt *opts, int optcode, union integral *result) { |
| struct opt *opt = opts; |
| |
| while (opt->desc != ODESC_END) { |
| if (opt->desc != ODESC_DONE && opt->desc->optcode == optcode) { |
| *result = opt->value; |
| opt->desc = ODESC_DONE; |
| return 0; |
| } |
| ++opt; |
| } |
| return -1; |
| } |
| #endif |
| |
| static struct opt *xio_findopt(struct opt *opts, int optcode) { |
| struct opt *opt = opts; |
| |
| while (opt->desc != ODESC_END) { |
| if (opt->desc != ODESC_DONE && opt->desc->optcode == optcode) { |
| return opt; |
| } |
| ++opt; |
| } |
| return NULL; |
| } |
| |
| int retropt_timespec(struct opt *opts, int optcode, struct timespec *result) { |
| struct opt *opt; |
| |
| if (!(opt = xio_findopt(opts, optcode))) { |
| return -1; |
| } |
| *result = opt->value.u_timespec; |
| opt->desc = ODESC_DONE; |
| return 0; |
| } |
| |
| |
| /* Looks for the first option of type <optcode>. If the option is found, |
| this function stores its bool value in *result, "consumes" the |
| option, and returns 0. |
| If the option is not found, *result is not modified, and -1 is returned. */ |
| int retropt_bool(struct opt *opts, int optcode, bool *result) { |
| struct opt *opt = opts; |
| |
| while (opt->desc != ODESC_END) { |
| if (opt->desc != ODESC_DONE && opt->desc->optcode == optcode) { |
| *result = opt->value.u_bool; |
| opt->desc = ODESC_DONE; |
| return 0; |
| } |
| ++opt; |
| } |
| return -1; |
| } |
| |
| #if 0 /* currently not used */ |
| /* Looks for the first option of type <optcode>. If the option is found, |
| this function stores its short value in *result, "consumes" the |
| option, and returns 0. |
| If the option is not found, *result is not modified, and -1 is returned. */ |
| int retropt_short(struct opt *opts, int optcode, short *result) { |
| struct opt *opt = opts; |
| |
| while (opt->desc != ODESC_END) { |
| if (opt->desc != ODESC_DONE && opt->desc->optcode == optcode) { |
| *result = opt->value.u_short; |
| opt->desc = ODESC_DONE; |
| return 0; |
| } |
| ++opt; |
| } |
| return -1; |
| } |
| #endif |
| |
| /* Looks for the first option of type <optcode>. If the option is found, |
| this function stores its unsigned short value in *result, "consumes" the |
| option, and returns 0. |
| If the option is not found, *result is not modified, and -1 is returned. */ |
| int retropt_ushort(struct opt *opts, int optcode, unsigned short *result) { |
| struct opt *opt = opts; |
| |
| while (opt->desc != ODESC_END) { |
| if (opt->desc != ODESC_DONE && opt->desc->optcode == optcode) { |
| *result = opt->value.u_ushort; |
| opt->desc = ODESC_DONE; |
| return 0; |
| } |
| ++opt; |
| } |
| return -1; |
| } |
| |
| /* Looks for the first option of type <optcode>. If the option is found, |
| this function stores its int value in *result, "consumes" the |
| option, and returns 0. |
| If the option is not found, *result is not modified, and -1 is returned. */ |
| int retropt_int(struct opt *opts, int optcode, int *result) { |
| struct opt *opt = opts; |
| |
| while (opt->desc != ODESC_END) { |
| if (opt->desc != ODESC_DONE && opt->desc->optcode == optcode) { |
| char *rest; |
| switch (opt->desc->type) { |
| case TYPE_INT: *result = opt->value.u_int; break; |
| case TYPE_STRING: *result = strtol(opt->value.u_string, &rest, 0); |
| if (*rest != '\0') { |
| Error1("retropts: trailing garbage in numerical arg of option \"%s\"", |
| opt->desc->defname); |
| } |
| break; |
| default: Error2("cannot convert type %d of option %s to int", |
| opt->desc->type, opt->desc->defname); |
| opt->desc = ODESC_ERROR; |
| return -1; |
| } |
| opt->desc = ODESC_DONE; |
| return 0; |
| } |
| ++opt; |
| } |
| return -1; |
| } |
| |
| /* Looks for the first option of type <optcode>. If the option is found, |
| this function stores its unsigned int value in *result, "consumes" the |
| option, and returns 0. |
| If the option is not found, *result is not modified, and -1 is returned. */ |
| int retropt_uint(struct opt *opts, int optcode, unsigned int *result) { |
| struct opt *opt = opts; |
| |
| while (opt->desc != ODESC_END) { |
| if (opt->desc != ODESC_DONE && opt->desc->optcode == optcode) { |
| *result = opt->value.u_uint; |
| opt->desc = ODESC_DONE; |
| return 0; |
| } |
| ++opt; |
| } |
| return -1; |
| } |
| |
| /* Looks for the first option of type <optcode>. If the option is found, |
| this function stores its long value in *result, "consumes" the option, |
| and returns 0. |
| If the option is not found, *result is not modified, and -1 is returned. */ |
| int retropt_long(struct opt *opts, int optcode, long *result) { |
| struct opt *opt = opts; |
| |
| while (opt->desc != ODESC_END) { |
| if (opt->desc != ODESC_DONE && opt->desc->optcode == optcode) { |
| *result = opt->value.u_long; |
| opt->desc = ODESC_DONE; |
| return 0; |
| } |
| ++opt; |
| } |
| return -1; |
| } |
| |
| /* Looks for the first option of type <optcode>. If the option is found, |
| this function stores its unsigned long value in *result, "consumes" the |
| option, and returns 0. |
| If the option is not found, *result is not modified, and -1 is returned. */ |
| int retropt_ulong(struct opt *opts, int optcode, unsigned long *result) { |
| struct opt *opt = opts; |
| |
| while (opt->desc != ODESC_END) { |
| if (opt->desc != ODESC_DONE && opt->desc->optcode == optcode) { |
| *result = opt->value.u_ulong; |
| opt->desc = ODESC_DONE; |
| return 0; |
| } |
| ++opt; |
| } |
| return -1; |
| } |
| |
| #if 0 /* currently not used */ |
| /* get the value of a FLAG typed option, and apply it to the appropriate |
| bit position. Mark the option as consumed (done). return 0 if options was found and successfully applied, |
| or -1 if option was not in opts */ |
| int retropt_flag(struct opt *opts, int optcode, flags_t *result) { |
| struct opt *opt = opts; |
| |
| while (opt->desc != ODESC_END) { |
| if (opt->desc != ODESC_DONE && opt->desc->optcode == optcode) { |
| if (opt->value.u_bool) { |
| *result |= opt->desc->major; |
| } else { |
| *result &= ~opt->desc->major; |
| } |
| opt->desc = ODESC_DONE; |
| return 0; |
| } |
| ++opt; |
| } |
| return -1; |
| } |
| #endif |
| |
| /* Looks for the first option of type <optcode>. If the option is found, |
| this function stores its character pointer value in *result, "consumes" the |
| option, and returns 0. Note that, for options of type STRING_NULL, the |
| character pointer might degenerate to NULL. |
| The resulting string is malloc'ed and should be freed after use. |
| If the option is not found, *result is not modified, and -1 is returned. |
| */ |
| int retropt_string(struct opt *opts, int optcode, char **result) { |
| struct opt *opt = opts; |
| |
| while (opt->desc != ODESC_END) { |
| if (opt->desc != ODESC_DONE && opt->desc->optcode == optcode) { |
| if (opt->value.u_string == NULL) { |
| *result = NULL; |
| } else if ((*result = strdup(opt->value.u_string)) == NULL) { |
| Error1("strdup("F_Zu"): out of memory", |
| strlen(opt->value.u_string)); |
| return -1; |
| } |
| opt->desc = ODESC_DONE; |
| return 0; |
| } |
| ++opt; |
| } |
| return -1; |
| } |
| |
| |
| #if _WITH_SOCKET |
| /* looks for a bind option and, if found, overwrites the complete contents of |
| sa with the appropriate value(s). |
| returns STAT_OK if option exists and could be resolved, |
| STAT_NORETRY if option exists but had error, |
| or STAT_NOACTION if it does not exist */ |
| /* currently only for IP (v4, v6) and raw (PF_UNSPEC) */ |
| int retropt_bind(struct opt *opts, |
| int af, |
| int socktype, |
| int ipproto, |
| struct sockaddr *sa, |
| socklen_t *salen, |
| int feats, /* TCP etc: 1..address allowed, |
| 3..address and port allowed |
| UNIX (or'd): 1..tight |
| 2..abstract |
| */ |
| unsigned long res_opts0, unsigned long res_opts1) { |
| const char portsep[] = ":"; |
| const char *ends[] = { portsep, NULL }; |
| const char *nests[] = { "[", "]", NULL }; |
| bool portallowed; |
| char *bindname, *bindp; |
| char hostname[512], *hostp = hostname, *portp = NULL; |
| size_t hostlen = sizeof(hostname)-1; |
| int parsres; |
| int result; |
| |
| if (retropt_string(opts, OPT_BIND, &bindname) < 0) { |
| return STAT_NOACTION; |
| } |
| bindp = bindname; |
| |
| switch (af) { |
| |
| case AF_UNSPEC: |
| { |
| size_t p = 0; |
| dalan(bindname, (uint8_t *)sa->sa_data, &p, *salen-sizeof(sa->sa_family), 'i'); |
| *salen = p + sizeof(sa->sa_family); |
| *salen = p + |
| #if HAVE_STRUCT_SOCKADDR_SALEN |
| sizeof(sa->sa_len) + |
| #endif |
| sizeof(sa->sa_family); |
| #if HAVE_STRUCT_SOCKADDR_SALEN |
| sa->sa_len = *salen; |
| #endif |
| } |
| break; |
| |
| #if WITH_IP4 || WITH_IP6 || WITH_VSOCK |
| #if WITH_VSOCK |
| case AF_VSOCK: |
| #endif |
| #if WITH_IP4 |
| case AF_INET: |
| #endif |
| #if WITH_IP6 |
| case AF_INET6: |
| #endif /*WITH_IP6 */ |
| portallowed = (feats>=2); |
| parsres = |
| nestlex((const char **)&bindp, &hostp, &hostlen, ends, NULL, NULL, nests, |
| true, false, false); |
| if (parsres < 0) { |
| Error1("option too long: \"%s\"", bindp); |
| return STAT_NORETRY; |
| } else if (parsres > 0) { |
| Error1("syntax error in \"%s\"", bindp); |
| return STAT_NORETRY; |
| } |
| *hostp++ = '\0'; |
| if (!strncmp(bindp, portsep, strlen(portsep))) { |
| if (!portallowed) { |
| Error("port specification not allowed in this bind option"); |
| return STAT_NORETRY; |
| } else { |
| portp = bindp + strlen(portsep); |
| } |
| } |
| if ((result = |
| xiogetaddrinfo(hostname[0]!='\0'?hostname:NULL, portp, |
| af, socktype, ipproto, |
| (union sockaddr_union *)sa, salen, |
| res_opts0, res_opts1)) |
| != STAT_OK) { |
| Error("error resolving bind option"); |
| return STAT_NORETRY; |
| } |
| break; |
| #endif /* WITH_IP4 || WITH_IP6 */ |
| |
| #if WITH_UNIX |
| case AF_UNIX: |
| { |
| bool abstract = (feats&2); |
| bool tight = (feats&1); |
| struct sockaddr_un *s_un = (struct sockaddr_un *)sa; |
| *salen = xiosetunix(af, s_un, bindname, abstract, tight); |
| } |
| break; |
| #endif /* WITH_UNIX */ |
| |
| default: |
| Error1("bind: unknown address family %d", af); |
| return STAT_NORETRY; |
| } |
| return STAT_OK; |
| } |
| #endif /* _WITH_SOCKET */ |
| |
| |
| /* applies to fd all options belonging to phase */ |
| /* 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, enum e_phase phase) { |
| struct opt *opt; |
| |
| opt = opts; while (opt && opt->desc != ODESC_END) { |
| if (opt->desc == ODESC_DONE || |
| (phase != PH_ALL && opt->desc->phase != phase)) { |
| ++opt; continue; } |
| |
| if (opt->desc->func == OFUNC_SEEK32) { |
| if (Lseek(fd, opt->value.u_off, opt->desc->major) < 0) { |
| Error4("lseek(%d, "F_off", %d): %s", |
| fd, opt->value.u_off, opt->desc->major, strerror(errno)); |
| } |
| #if HAVE_LSEEK64 |
| } else if (opt->desc->func == OFUNC_SEEK64) { |
| |
| /*! this depends on off64_t atomic type */ |
| if (Lseek64(fd, opt->value.u_off64, opt->desc->major) < 0) { |
| Error4("lseek64(%d, "F_off64", %d): %s", |
| fd, opt->value.u_off64, opt->desc->major, strerror(errno)); |
| } |
| #endif /* HAVE_LSEEK64 */ |
| |
| } else if (opt->desc->func == OFUNC_FCNTL) { |
| int flag; |
| |
| /* retrieve existing flag setttings */ |
| if ((flag = Fcntl(fd, opt->desc->major-1)) < 0) { |
| Error3("fcntl(%d, %d): %s", |
| fd, opt->desc->major, strerror(errno)); |
| opt->desc = ODESC_ERROR; ++opt; continue; |
| } else { |
| if (opt->value.u_bool) { |
| flag |= opt->desc->minor; |
| } else { |
| flag &= ~opt->desc->minor; |
| } |
| if (Fcntl_l(fd, opt->desc->major, flag) < 0) { |
| Error4("fcntl(%d, %d, %d): %s", |
| fd, opt->desc->major, flag, strerror(errno)); |
| opt->desc = ODESC_ERROR; ++opt; continue; |
| } |
| } |
| |
| } else if (opt->desc->func == OFUNC_IOCTL) { |
| if (Ioctl(fd, opt->desc->major, (void *)&opt->value) < 0) { |
| Error4("ioctl(%d, 0x%x, %p): %s", |
| fd, opt->desc->major, (void *)&opt->value, strerror(errno)); |
| opt->desc = ODESC_ERROR; ++opt; continue; |
| } |
| |
| } else if (opt->desc->func == OFUNC_IOCTL_MASK_LONG) { |
| long val; |
| int getreq = opt->desc->major; |
| int setreq = opt->desc->minor; |
| long mask = opt->desc->arg3; |
| |
| if (Ioctl(fd, getreq, (void *)&val) < 0) { |
| Error4("ioctl(%d, 0x%x, %p): %s", |
| fd, opt->desc->major, (void *)&val, strerror(errno)); |
| opt->desc = ODESC_ERROR; ++opt; continue; |
| } |
| val &= ~mask; |
| if (opt->value.u_bool) val |= mask; |
| if (Ioctl(fd, setreq, (void *)&val) < 0) { |
| Error4("ioctl(%d, 0x%x, %p): %s", |
| fd, opt->desc->major, (void *)&val, strerror(errno)); |
| opt->desc = ODESC_ERROR; ++opt; continue; |
| } |
| |
| } else if (opt->desc->func == OFUNC_IOCTL_GENERIC) { |
| switch (opt->desc->type) { |
| case TYPE_INT: |
| if (Ioctl(fd, opt->value.u_int, NULL) < 0) { |
| Error3("ioctl(%d, 0x%x, NULL): %s", |
| fd, opt->value.u_int, strerror(errno)); |
| opt->desc = ODESC_ERROR; ++opt; continue; |
| } |
| break; |
| case TYPE_INT_INT: |
| if (Ioctl_int(fd, opt->value.u_int, opt->value2.u_int) < 0) { |
| Error4("ioctl(%d, 0x%x, 0x%x): %s", |
| fd, opt->value.u_int, opt->value2.u_int, strerror(errno)); |
| opt->desc = ODESC_ERROR; ++opt; continue; |
| } |
| break; |
| case TYPE_INT_INTP: |
| if (Ioctl(fd, opt->value.u_int, (void *)&opt->value2.u_int) < 0) { |
| Error4("ioctl(%d, 0x%x, %p): %s", |
| fd, opt->value.u_int, (void *)&opt->value2.u_int, strerror(errno)); |
| opt->desc = ODESC_ERROR; ++opt; continue; |
| } |
| break; |
| case TYPE_INT_BIN: |
| if (Ioctl(fd, opt->value.u_int, (void *)opt->value2.u_bin.b_data) < 0) { |
| Error4("ioctl(%d, 0x%x, %p): %s", |
| fd, opt->value.u_int, (void *)opt->value2.u_bin.b_data, strerror(errno)); |
| opt->desc = ODESC_ERROR; ++opt; continue; |
| } |
| break; |
| case TYPE_INT_STRING: |
| if (Ioctl(fd, opt->value.u_int, (void *)opt->value2.u_string) < 0) { |
| Error4("ioctl(%d, 0x%x, %p): %s", |
| fd, opt->value.u_int, (void *)opt->value2.u_string, strerror(errno)); |
| opt->desc = ODESC_ERROR; ++opt; continue; |
| } |
| break; |
| default: |
| Error1("ioctl() data type %d not implemented", |
| opt->desc->type); |
| } |
| |
| #if _WITH_SOCKET |
| } else if (opt->desc->func == OFUNC_SOCKOPT) { |
| if (0) { |
| ; |
| #if 0 && HAVE_STRUCT_LINGER |
| } else if (opt->desc->optcode == OPT_SO_LINGER) { |
| struct linger lingstru; |
| lingstru.l_onoff = (opt->value.u_int>=0 ? 1 : 0); |
| lingstru.l_linger = opt->value.u_int; |
| if (Setsockopt(fd, opt->desc->major, opt->desc->minor, &lingstru, |
| sizeof(lingstru)) < 0) { |
| Error6("setsockopt(%d, %d, %d, {%d,%d}, "F_Zu, |
| fd, opt->desc->major, opt->desc->minor, lingstru.l_onoff, |
| lingstru.l_linger, sizeof(lingstru)); |
| opt->desc = ODESC_ERROR; ++opt; continue; |
| } |
| #endif /* HAVE_STRUCT_LINGER */ |
| } else { |
| switch (opt->desc->type) { |
| case TYPE_BIN: |
| if (Setsockopt(fd, opt->desc->major, opt->desc->minor, |
| opt->value.u_bin.b_data, opt->value.u_bin.b_len) |
| < 0) { |
| Error6("setsockopt(%d, %d, %d, %p, "F_Zu"): %s", |
| fd, opt->desc->major, opt->desc->minor, |
| opt->value.u_bin.b_data, opt->value.u_bin.b_len, |
| strerror(errno)); |
| opt->desc = ODESC_ERROR; ++opt; continue; |
| } |
| break; |
| case TYPE_BOOL: |
| if (Setsockopt(fd, opt->desc->major, opt->desc->minor, |
| &opt->value.u_bool, sizeof(opt->value.u_bool)) |
| < 0) { |
| Error6("setsockopt(%d, %d, %d, {%d}, "F_Zu"): %s", fd, |
| opt->desc->major, opt->desc->minor, |
| opt->value.u_bool, sizeof(opt->value.u_bool), |
| strerror(errno)); |
| opt->desc = ODESC_ERROR; ++opt; continue; |
| } |
| break; |
| case TYPE_BYTE: |
| if (Setsockopt(fd, opt->desc->major, opt->desc->minor, |
| &opt->value.u_byte, sizeof(uint8_t)) < 0) { |
| Error6("setsockopt(%d, %d, %d, {%u}, "F_Zu"): %s", |
| fd, opt->desc->major, opt->desc->minor, |
| opt->value.u_byte, sizeof(uint8_t), strerror(errno)); |
| opt->desc = ODESC_ERROR; ++opt; continue; |
| } |
| break; |
| case TYPE_INT: |
| if (Setsockopt(fd, opt->desc->major, opt->desc->minor, |
| &opt->value.u_int, sizeof(int)) < 0) { |
| Error6("setsockopt(%d, %d, %d, {%d}, "F_Zu"): %s", |
| fd, opt->desc->major, opt->desc->minor, |
| opt->value.u_int, sizeof(int), strerror(errno)); |
| opt->desc = ODESC_ERROR; ++opt; continue; |
| } |
| break; |
| case TYPE_LONG: |
| if (Setsockopt(fd, opt->desc->major, opt->desc->minor, |
| &opt->value.u_long, sizeof(long)) < 0) { |
| Error6("setsockopt(%d, %d, %d, {%ld}, "F_Zu"): %s", |
| fd, opt->desc->major, opt->desc->minor, |
| opt->value.u_long, sizeof(long), strerror(errno)); |
| opt->desc = ODESC_ERROR; ++opt; continue; |
| } |
| break; |
| case TYPE_STRING: |
| if (Setsockopt(fd, opt->desc->major, opt->desc->minor, |
| opt->value.u_string, |
| strlen(opt->value.u_string)+1) < 0) { |
| Error6("setsockopt(%d, %d, %d, \"%s\", "F_Zu"): %s", |
| fd, opt->desc->major, opt->desc->minor, |
| opt->value.u_string, strlen(opt->value.u_string)+1, |
| strerror(errno)); |
| opt->desc = ODESC_ERROR; ++opt; continue; |
| } |
| break; |
| case TYPE_UINT: |
| if (Setsockopt(fd, opt->desc->major, opt->desc->minor, |
| &opt->value.u_uint, sizeof(unsigned int)) < 0) { |
| Error6("setsockopt(%d, %d, %d, {%u}, "F_Zu"): %s", |
| fd, opt->desc->major, opt->desc->minor, |
| opt->value.u_uint, sizeof(unsigned int), |
| strerror(errno)); |
| opt->desc = ODESC_ERROR; ++opt; continue; |
| } |
| break; |
| case TYPE_TIMEVAL: |
| if (Setsockopt(fd, opt->desc->major, opt->desc->minor, |
| &opt->value.u_timeval, sizeof(struct timeval)) < 0) { |
| Error7("setsockopt(%d, %d, %d, {%ld,%ld}, "F_Zu"): %s", |
| fd, opt->desc->major, opt->desc->minor, |
| opt->value.u_timeval.tv_sec, opt->value.u_timeval.tv_usec, |
| sizeof(struct timeval), strerror(errno)); |
| opt->desc = ODESC_ERROR; ++opt; continue; |
| } |
| break; |
| #if HAVE_STRUCT_LINGER |
| case TYPE_LINGER: |
| { |
| struct linger lingstru; |
| lingstru.l_onoff = (opt->value.u_linger.l_onoff>=0 ? 1 : 0); |
| lingstru.l_linger = opt->value.u_linger.l_linger; |
| if (Setsockopt(fd, opt->desc->major, opt->desc->minor, |
| &lingstru, sizeof(lingstru)) < 0) { |
| Error6("setsockopt(%d, %d, %d, {%d,%d}): %s", |
| fd, opt->desc->major, opt->desc->minor, |
| lingstru.l_onoff, lingstru.l_linger, |
| strerror(errno)); |
| opt->desc = ODESC_ERROR; ++opt; continue; |
| } |
| } |
| break; |
| #endif /* HAVE_STRUCT_LINGER */ |
| #if defined(HAVE_STRUCT_IP_MREQ) || defined (HAVE_STRUCT_IP_MREQN) |
| case TYPE_IP_MREQN: |
| /* handled in applyopts_single */ |
| ++opt; continue; |
| #endif /* defined(HAVE_STRUCT_IP_MREQ) || defined (HAVE_STRUCT_IP_MREQN) */ |
| |
| /*! still many types missing; implement on demand */ |
| #if WITH_IP4 |
| case TYPE_IP4NAME: |
| if (Setsockopt(fd, opt->desc->major, opt->desc->minor, |
| &opt->value.u_ip4addr, sizeof(opt->value.u_ip4addr)) < 0) { |
| Error6("setsockopt(%d, %d, %d, {0x%x}, "F_Zu"): %s", |
| fd, opt->desc->major, opt->desc->minor, |
| *(uint32_t *)&opt->value.u_ip4addr, sizeof(opt->value.u_ip4addr), |
| strerror(errno)); |
| } |
| break; |
| #endif /* defined(WITH_IP4) */ |
| default: |
| #if !NDEBUG |
| Error1("applyopts(): type %d not implemented", |
| opt->desc->type); |
| #else |
| Warn1("applyopts(): type %d not implemented", |
| opt->desc->type); |
| #endif |
| opt->desc = ODESC_ERROR; ++opt; continue; |
| } |
| } |
| |
| } else if (opt->desc->func == OFUNC_SOCKOPT_APPEND) { |
| switch (opt->desc->type) { |
| uint8_t data[256]; |
| socklen_t oldlen, newlen; |
| case TYPE_BIN: |
| oldlen = sizeof(data); |
| if (Getsockopt(fd, opt->desc->major, opt->desc->minor, |
| data, &oldlen) |
| < 0) { |
| Error6("getsockopt(%d, %d, %d, %p, {"F_socklen"}): %s", |
| fd, opt->desc->major, opt->desc->minor, data, oldlen, |
| strerror(errno)); |
| opt->desc = ODESC_ERROR; ++opt; continue; |
| } |
| memcpy(&data[oldlen], opt->value.u_bin.b_data, |
| MIN(opt->value.u_bin.b_len, sizeof(data)-oldlen)); |
| newlen = oldlen + MIN(opt->value.u_bin.b_len, sizeof(data)-oldlen); |
| if (Setsockopt(fd, opt->desc->major, opt->desc->minor, |
| data, newlen) |
| < 0) { |
| Error6("setsockopt(%d, %d, %d, %p, %d): %s", |
| fd, opt->desc->major, opt->desc->minor, data, newlen, |
| strerror(errno)); |
| opt->desc = ODESC_ERROR; ++opt; continue; |
| } |
| break; |
| default: |
| Error2("internal: option \"%s\": unimplemented type %d", |
| opt->desc->defname, opt->desc->type); |
| break; |
| } |
| } else if (opt->desc->func == OFUNC_SOCKOPT_GENERIC) { |
| switch (opt->desc->type) { |
| case TYPE_INT_INT_INT: |
| if (Setsockopt(fd, opt->value.u_int, opt->value2.u_int, |
| &opt->value3.u_int, sizeof(int)) < 0) { |
| Error6("setsockopt(%d, %d, %d, {%d}, "F_Zu"): %s", |
| fd, opt->value.u_int, opt->value2.u_int, |
| opt->value3.u_int, sizeof(int), strerror(errno)); |
| } |
| break; |
| case TYPE_INT_INT_BIN: |
| if (Setsockopt(fd, opt->value.u_int, opt->value2.u_int, |
| opt->value3.u_bin.b_data, opt->value3.u_bin.b_len) < 0) { |
| Error5("setsockopt(%d, %d, %d, {...}, "F_Zu"): %s", |
| fd, opt->value.u_int, opt->value2.u_int, |
| opt->value3.u_bin.b_len, strerror(errno)); |
| } |
| break; |
| case TYPE_INT_INT_STRING: |
| if (Setsockopt(fd, opt->value.u_int, opt->value2.u_int, |
| opt->value3.u_string, |
| strlen(opt->value3.u_string)+1) < 0) { |
| Error6("setsockopt(%d, %d, %d, \"%s\", "F_Zu"): %s", |
| fd, opt->value.u_int, opt->value2.u_int, |
| opt->value3.u_string, strlen(opt->value3.u_string)+1, |
| strerror(errno)); |
| } |
| break; |
| default: |
| Error1("setsockopt() data type %d not implemented", |
| opt->desc->type); |
| } |
| #endif /* _WITH_SOCKET */ |
| |
| #if HAVE_FLOCK |
| } else if (opt->desc->func == OFUNC_FLOCK) { |
| if (Flock(fd, opt->desc->major) < 0) { |
| Error3("flock(%d, %d): %s", |
| fd, opt->desc->major, strerror(errno)); |
| opt->desc = ODESC_ERROR; ++opt; continue; |
| } |
| #endif /* defined(HAVE_FLOCK) */ |
| |
| } else if (opt->desc->func == OFUNC_SPEC || |
| opt->desc->func == OFUNC_FLAG) { |
| switch (opt->desc->optcode) { |
| case OPT_USER: |
| case OPT_USER_LATE: |
| if (Fchown(fd, opt->value.u_uidt, -1) < 0) { |
| Error3("fchown(%d, "F_uid", -1): %s", |
| fd, opt->value.u_uidt, strerror(errno)); |
| opt->desc = ODESC_ERROR; ++opt; continue; |
| } |
| break; |
| case OPT_GROUP: |
| case OPT_GROUP_LATE: |
| if (Fchown(fd, -1, opt->value.u_gidt) < 0) { |
| Error3("fchown(%d, -1, "F_gid"): %s", |
| fd, opt->value.u_gidt, strerror(errno)); |
| opt->desc = ODESC_ERROR; ++opt; continue; |
| } |
| break; |
| case OPT_PERM: |
| case OPT_PERM_LATE: |
| if (Fchmod(fd, opt->value.u_modet) < 0) { |
| Error3("fchmod(%d, %u): %s", |
| fd, opt->value.u_modet, strerror(errno)); |
| opt->desc = ODESC_ERROR; ++opt; continue; |
| } |
| break; |
| case OPT_FTRUNCATE32: |
| if (Ftruncate(fd, opt->value.u_off) < 0) { |
| Error3("ftruncate(%d, "F_off"): %s", |
| fd, opt->value.u_off, strerror(errno)); |
| opt->desc = ODESC_ERROR; ++opt; continue; |
| } |
| break; |
| #if HAVE_FTRUNCATE64 |
| case OPT_FTRUNCATE64: |
| if (Ftruncate64(fd, opt->value.u_off64) < 0) { |
| Error3("ftruncate64(%d, "F_off64"): %s", |
| fd, opt->value.u_off64, strerror(errno)); |
| opt->desc = ODESC_ERROR; ++opt; continue; |
| } |
| #endif /* HAVE_FTRUNCATE64 */ |
| break; |
| case OPT_F_SETLK_RD: |
| case OPT_F_SETLK_WR: |
| case OPT_F_SETLKW_RD: |
| case OPT_F_SETLKW_WR: |
| { |
| struct flock l; /* Linux: <asm/fcntl.h> */ |
| l.l_type = opt->desc->minor; |
| l.l_whence = SEEK_SET; |
| l.l_start = 0; |
| l.l_len = LONG_MAX; |
| l.l_pid = 0; /* hope this uses our current process */ |
| if (Fcntl_lock(fd, opt->desc->major, &l) < 0) { |
| Error3("fcntl(%d, %d, {type=F_WRLCK,whence=SEEK_SET,start=0,len=LONG_MAX,pid=0}): %s", fd, opt->desc->major, strerror(errno)); |
| opt->desc = ODESC_ERROR; ++opt; continue; |
| } |
| } |
| break; |
| case OPT_SETUID_EARLY: |
| case OPT_SETUID: |
| if (Setuid(opt->value.u_uidt) < 0) { |
| Error2("setuid("F_uid"): %s", opt->value.u_uidt, |
| strerror(errno)); |
| opt->desc = ODESC_ERROR; ++opt; continue; |
| } |
| break; |
| case OPT_SETGID_EARLY: |
| case OPT_SETGID: |
| if (Setgid(opt->value.u_gidt) < 0) { |
| Error2("setgid("F_gid"): %s", opt->value.u_gidt, |
| strerror(errno)); |
| opt->desc = ODESC_ERROR; ++opt; continue; |
| } |
| break; |
| case OPT_SUBSTUSER_EARLY: |
| case OPT_SUBSTUSER: |
| { |
| struct passwd *pwd; |
| if ((pwd = getpwuid(opt->value.u_uidt)) == NULL) { |
| Error1("getpwuid("F_uid"): no such user", |
| opt->value.u_uidt); |
| opt->desc = ODESC_ERROR; ++opt; continue; |
| } |
| if (Initgroups(pwd->pw_name, pwd->pw_gid) < 0) { |
| Error3("initgroups(%s, "F_gid"): %s", |
| pwd->pw_name, pwd->pw_gid, strerror(errno)); |
| opt->desc = ODESC_ERROR; ++opt; continue; |
| } |
| if (Setgid(pwd->pw_gid) < 0) { |
| Error2("setgid("F_gid"): %s", pwd->pw_gid, |
| strerror(errno)); |
| opt->desc = ODESC_ERROR; ++opt; continue; |
| } |
| if (Setuid(opt->value.u_uidt) < 0) { |
| Error2("setuid("F_uid"): %s", opt->value.u_uidt, |
| strerror(errno)); |
| opt->desc = ODESC_ERROR; ++opt; continue; |
| } |
| #if 1 |
| if (setenv("USER", pwd->pw_name, 1) < 0) |
| Error1("setenv(\"USER\", \"%s\", 1): insufficient space", |
| pwd->pw_name); |
| if (setenv("LOGNAME", pwd->pw_name, 1) < 0) |
| Error1("setenv(\"LOGNAME\", \"%s\", 1): insufficient space", |
| pwd->pw_name); |
| if (setenv("HOME", pwd->pw_dir, 1) < 0) |
| Error1("setenv(\"HOME\", \"%s\", 1): insufficient space", |
| pwd->pw_dir); |
| if (setenv("SHELL", pwd->pw_shell, 1) < 0) |
| Error1("setenv(\"SHELL\", \"%s\", 1): insufficient space", |
| pwd->pw_shell); |
| #endif |
| } |
| break; |
| #if defined(HAVE_SETGRENT) && defined(HAVE_GETGRENT) && defined(HAVE_ENDGRENT) |
| case OPT_SUBSTUSER_DELAYED: |
| { |
| struct passwd *pwd; |
| |
| if ((pwd = getpwuid(opt->value.u_uidt)) == NULL) { |
| Error1("getpwuid("F_uid"): no such user", |
| opt->value.u_uidt); |
| opt->desc = ODESC_ERROR; ++opt; continue; |
| } |
| delayeduser_uid = opt->value.u_uidt; |
| delayeduser_gid = pwd->pw_gid; |
| if ((delayeduser_name = strdup(pwd->pw_name)) == NULL) { |
| Error1("strdup("F_Zu"): out of memory", |
| strlen(pwd->pw_name)+1); |
| opt->desc = ODESC_ERROR; ++opt; continue; |
| } |
| if ((delayeduser_dir = strdup(pwd->pw_dir)) == NULL) { |
| Error1("strdup("F_Zu"): out of memory", |
| strlen(pwd->pw_dir)+1); |
| opt->desc = ODESC_ERROR; ++opt; continue; |
| } |
| if ((delayeduser_shell = strdup(pwd->pw_shell)) == NULL) { |
| Error1("strdup("F_Zu"): out of memory", |
| strlen(pwd->pw_shell)+1); |
| opt->desc = ODESC_ERROR; ++opt; continue; |
| } |
| /* function to get all supplementary groups of user */ |
| delayeduser_ngids = sizeof(delayeduser_gids)/sizeof(gid_t); |
| getusergroups(delayeduser_name, delayeduser_gids, |
| &delayeduser_ngids); |
| delayeduser = true; |
| } |
| break; |
| #endif |
| case OPT_CHROOT_EARLY: |
| case OPT_CHROOT: |
| if (Chroot(opt->value.u_string) < 0) { |
| Error2("chroot(\"%s\"): %s", opt->value.u_string, |
| strerror(errno)); |
| opt->desc = ODESC_ERROR; ++opt; continue; |
| } |
| if (Chdir("/") < 0) { |
| Error1("chdir(\"/\"): %s", strerror(errno)); |
| } |
| break; |
| case OPT_SETSID: |
| if (Setsid() < 0) { |
| Warn1("setsid(): %s", strerror(errno)); |
| if (Setpgid(getpid(), getppid()) < 0) { |
| Warn3("setpgid(%d, %d): %s", |
| getpid(), getppid(), strerror(errno)); |
| } else { |
| if (Setsid() < 0) { |
| Error1("setsid(): %s", strerror(errno)); |
| } |
| } |
| } |
| break; |
| case OPT_SETPGID: |
| if (Setpgid(0, opt->value.u_int) < 0) { |
| Warn2("setpgid(0, "F_pid"): %s", |
| opt->value.u_int, strerror(errno)); |
| } |
| break; |
| case OPT_TIOCSCTTY: |
| { |
| int mytty; |
| /* this code idea taken from ssh/pty.c: make pty controlling term. */ |
| if ((mytty = Open("/dev/tty", O_NOCTTY, 0640)) < 0) { |
| Warn1("open(\"/dev/tty\", O_NOCTTY, 0640): %s", strerror(errno)); |
| } else { |
| /*0 Info1("open(\"/dev/tty\", O_NOCTTY, 0640) -> %d", mytty);*/ |
| #ifdef TIOCNOTTY |
| if (Ioctl(mytty, TIOCNOTTY, NULL) < 0) { |
| Warn2("ioctl(%d, TIOCNOTTY, NULL): %s", |
| mytty, strerror(errno)); |
| } |
| #endif |
| if (Close(mytty) < 0) { |
| Info2("close(%d): %s", |
| mytty, strerror(errno)); |
| } |
| } |
| #ifdef TIOCSCTTY |
| if (Ioctl(fd, TIOCSCTTY, NULL) < 0) { |
| Warn2("ioctl(%d, TIOCSCTTY, NULL): %s", fd, strerror(errno)); |
| } |
| #endif |
| if (Tcsetpgrp(0, getpid()) < 0) { |
| Warn2("tcsetpgrp("F_pid"): %s", getpid(), strerror(errno)); |
| } |
| } |
| break; |
| |
| default: Error1("applyopts(): option \"%s\" not implemented", |
| opt->desc->defname); |
| opt->desc = ODESC_ERROR; ++opt; continue; |
| } |
| |
| #if WITH_TERMIOS |
| } else if (opt->desc->func == OFUNC_TERMIOS_FLAG) { |
| if (xiotermiosflag_applyopt(fd, opt) < 0) { |
| opt->desc = ODESC_ERROR; ++opt; continue; |
| } |
| |
| } else if (opt->desc->func == OFUNC_TERMIOS_VALUE) { |
| if (((opt->value.u_uint << opt->desc->arg3) & opt->desc->minor) != |
| (opt->value.u_uint << opt->desc->arg3)) { |
| Error2("option %s: invalid value %u", |
| opt->desc->defname, opt->value.u_uint); |
| opt->desc = ODESC_ERROR; ++opt; continue; |
| } |
| if (xiotermios_value(fd, opt->desc->major, opt->desc->minor, |
| (opt->value.u_uint << opt->desc->arg3) & opt->desc->minor) < 0) { |
| opt->desc = ODESC_ERROR; ++opt; continue; |
| } |
| |
| } else if (opt->desc->func == OFUNC_TERMIOS_PATTERN) { |
| if (xiotermios_value(fd, opt->desc->major, opt->desc->arg3, opt->desc->minor) < 0) { |
| opt->desc = ODESC_ERROR; ++opt; continue; |
| } |
| |
| } else if (opt->desc->func == OFUNC_TERMIOS_CHAR) { |
| if (xiotermios_char(fd, opt->desc->major, opt->value.u_byte) < 0) { |
| opt->desc = ODESC_ERROR; ++opt; continue; |
| } |
| |
| #ifdef HAVE_TERMIOS_ISPEED |
| } else if (opt->desc->func == OFUNC_TERMIOS_SPEED) { |
| if (xiotermios_speed(fd, opt->desc->major, opt->value.u_uint) < 0) { |
| opt->desc = ODESC_ERROR; ++opt; continue; |
| } |
| #endif /* HAVE_TERMIOS_ISPEED */ |
| |
| } else if (opt->desc->func == OFUNC_TERMIOS_SPEC) { |
| if (xiotermios_spec(fd, opt->desc->optcode) < 0) { |
| opt->desc = ODESC_ERROR; ++opt; continue; |
| } |
| |
| #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);*/ |
| if (opt->desc->func != OFUNC_EXT && opt->desc->func != OFUNC_SIGNAL) { |
| Error1("applyopts(): option \"%s\" does not apply", |
| opt->desc->defname); |
| opt->desc = ODESC_ERROR; |
| ++opt; |
| continue; |
| } |
| ++opt; |
| continue; |
| } |
| opt->desc = ODESC_DONE; |
| ++opt; |
| } |
| |
| #if WITH_TERMIOS |
| if (phase == PH_FD || phase == PH_ALL) { |
| xiotermios_flush(fd); |
| } |
| #endif /* WITH_TERMIOS */ |
| return 0; |
| } |
| |
| /* applies to fd all options belonging to phases */ |
| /* 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 applyopts2(int fd, struct opt *opts, unsigned int from, unsigned int to) { |
| unsigned int i; |
| int stat; |
| |
| for (i = from; i <= to; ++i) { |
| if ((stat = applyopts(fd, opts, i)) < 0) |
| return stat; |
| } |
| return 0; |
| } |
| |
| /* apply and consume all options of type FLAG and group. |
| Return 0 if everything went right, or -1 if an error occurred. */ |
| int applyopts_flags(struct opt *opts, int group, flags_t *result) { |
| struct opt *opt = opts; |
| |
| if (!opts) return 0; |
| |
| while (opt->desc != ODESC_END) { |
| if (opt->desc != ODESC_DONE && |
| (opt->desc->group & group)) { |
| if (opt->desc->func == OFUNC_FLAG) { |
| if (opt->value.u_bool) { |
| *result |= opt->desc->major; |
| } else { |
| *result &= ~opt->desc->major; |
| } |
| opt->desc = ODESC_DONE; |
| } else if (opt->desc->func == OFUNC_FLAG_PATTERN) { |
| *result &= ~opt->desc->minor; |
| *result |= opt->desc->major; |
| opt->desc = ODESC_DONE; |
| } |
| } |
| ++opt; |
| } |
| return 0; |
| } |
| |
| |
| |
| /* set the FD_CLOEXEC fcntl if the options do not set it to 0 */ |
| int applyopts_cloexec(int fd, struct opt *opts) { |
| bool docloexec = 1; |
| |
| if (!opts) return 0; |
| |
| retropt_bool(opts, OPT_CLOEXEC, &docloexec); |
| if (docloexec) { |
| if (Fcntl_l(fd, F_SETFD, FD_CLOEXEC) < 0) { |
| Warn2("fcntl(%d, F_SETFD, FD_CLOEXEC): %s", fd, strerror(errno)); |
| } |
| } |
| return 0; |
| } |
| |
| int applyopts_fchown(int fd, struct opt *opts) { |
| uid_t user = -1; |
| gid_t group = -1; |
| |
| retropt_uidt(opts, OPT_USER, &user); |
| retropt_gidt(opts, OPT_GROUP, &group); |
| |
| if (user != (uid_t)-1 || group != (gid_t)-1) { |
| if (Fchown(fd, user, group) < 0) { |
| Error4("fchown(%d, "F_uid", "F_gid"): %s", fd, user, group, |
| strerror(errno)); |
| return STAT_RETRYLATER; |
| } |
| } |
| return 0; |
| } |
| |
| /* caller must make sure that option is not yet consumed */ |
| static int applyopt_offset(struct single *xfd, struct opt *opt) { |
| unsigned char *ptr; |
| |
| ptr = (unsigned char *)xfd + opt->desc->major; |
| switch (opt->desc->type) { |
| case TYPE_BOOL: |
| *(bool *)ptr = opt->value.u_bool; break; |
| case TYPE_INT: |
| *(int *)ptr = opt->value.u_int; break; |
| case TYPE_DOUBLE: |
| *(double *)ptr = opt->value.u_double; break; |
| case TYPE_TIMEVAL: |
| *(struct timeval *)ptr = opt->value.u_timeval; break; |
| case TYPE_STRING_NULL: |
| if (opt->value.u_string == NULL) { |
| *(char **)ptr = NULL; |
| break; |
| } |
| /* PASSTHROUGH */ |
| case TYPE_STRING: |
| if ((*(char **)ptr = strdup(opt->value.u_string)) == NULL) { |
| Error1("strdup("F_Zu"): out of memory", |
| strlen(opt->value.u_string)+1); |
| } |
| break; |
| case TYPE_CONST: |
| *(int *)ptr = opt->desc->minor; |
| break; |
| default: |
| Error1("applyopt_offset(): type %d not implemented", |
| opt->desc->type); |
| return -1; |
| } |
| opt->desc = ODESC_DONE; |
| return 0; |
| } |
| |
| int applyopts_offset(struct single *xfd, struct opt *opts) { |
| struct opt *opt; |
| |
| opt = opts; while (opt->desc != ODESC_END) { |
| if ((opt->desc == ODESC_DONE) || |
| opt->desc->func != OFUNC_OFFSET) { |
| ++opt; continue; } |
| |
| applyopt_offset(xfd, opt); |
| opt->desc = ODESC_DONE; |
| ++opt; |
| } |
| return 0; |
| } |
| |
| /* applies to xfd all OFUNC_EXT options belonging to phase |
| returns -1 if an error occurred */ |
| int applyopts_single(struct single *xfd, struct opt *opts, enum e_phase phase) { |
| struct opt *opt; |
| int lockrc; |
| |
| if (!opts) return 0; |
| |
| opt = opts; while (opt->desc != ODESC_END) { |
| if ((opt->desc == ODESC_DONE) || |
| (opt->desc->phase != phase && phase != PH_ALL)) { |
| /* option not handled in this function */ |
| ++opt; continue; |
| } else { |
| switch (opt->desc->func) { |
| |
| case OFUNC_OFFSET: |
| applyopt_offset(xfd, opt); |
| break; |
| |
| case OFUNC_EXT: |
| switch (opt->desc->optcode) { |
| #if 0 |
| case OPT_IGNOREEOF: |
| xfd->ignoreeof = true; |
| break; |
| case OPT_CR: |
| xfd->lineterm = LINETERM_CR; |
| break; |
| case OPT_CRNL: |
| xfd->lineterm = LINETERM_CRNL; |
| break; |
| #endif /* 0 */ |
| case OPT_READBYTES: |
| xfd->readbytes = opt->value.u_sizet; |
| xfd->actbytes = xfd->readbytes; |
| break; |
| case OPT_LOCKFILE: |
| if (xfd->lock.lockfile) { |
| Error("only one use of options lockfile and waitlock allowed"); |
| } |
| xfd->lock.lockfile = strdup(opt->value.u_string); |
| xfd->lock.intervall.tv_sec = 1; |
| xfd->lock.intervall.tv_nsec = 0; |
| |
| if ((lockrc = xiolock(&xfd->lock)) < 0) { |
| /* error message already printed */ |
| return -1; |
| } |
| if (lockrc) { |
| Error1("could not obtain lock \"%s\"", xfd->lock.lockfile); |
| } else { |
| xfd->havelock = true; |
| } |
| break; |
| case OPT_WAITLOCK: |
| if (xfd->lock.lockfile) { |
| Error("only one use of options lockfile and waitlock allowed"); |
| } |
| xfd->lock.lockfile = strdup(opt->value.u_string); |
| xfd->lock.waitlock = true; |
| xfd->lock.intervall.tv_sec = 1; |
| xfd->lock.intervall.tv_nsec = 0; |
| |
| /*! this should be integrated into central select()/poll() loop */ |
| if (xiolock(&xfd->lock) < 0) { |
| return -1; |
| } |
| xfd->havelock = true; |
| break; |
| |
| default: |
| /* just store the value in the correct component of struct single */ |
| if (opt->desc->type == TYPE_CONST) { |
| /* only for integral types compatible to int */ |
| *(int *)(&((char *)xfd)[opt->desc->major]) = opt->desc->arg3; |
| } else { |
| memcpy(&((char *)xfd)[opt->desc->major], &opt->value, opt->desc->minor); |
| } |
| } |
| break; |
| |
| case OFUNC_OFFSET_MASKS: |
| { |
| void *masks = (char *)xfd + opt->desc->major; |
| size_t masksize = opt->desc->minor; |
| unsigned long bit = opt->desc->arg3; |
| switch (masksize>>1) { |
| case sizeof(uint16_t): |
| if (opt->value.u_bool) { |
| ((uint16_t *)masks)[0] |= bit; |
| } else { |
| ((uint16_t *)masks)[1] |= bit; |
| } |
| break; |
| case sizeof(uint32_t): |
| if (opt->value.u_bool) { |
| ((uint32_t *)masks)[0] |= bit; |
| } else { |
| ((uint32_t *)masks)[1] |= bit; |
| } |
| break; |
| default: |
| Info1("sizeof(uint32_t)="F_Zu, sizeof(uint32_t)); |
| Error1("applyopts_single: masksize "F_Zu" not implemented", |
| masksize); |
| } |
| } |
| break; |
| |
| #if _WITH_SOCKET |
| case OFUNC_SOCKOPT: |
| switch (opt->desc->optcode) { |
| #if WITH_IP4 && (defined(HAVE_STRUCT_IP_MREQ) || defined (HAVE_STRUCT_IP_MREQN)) |
| case OPT_IP_ADD_MEMBERSHIP: |
| { |
| union { |
| #if HAVE_STRUCT_IP_MREQN |
| struct ip_mreqn mreqn; |
| #endif |
| struct ip_mreq mreq; |
| } ip4_mreqn = {{{0}}}; |
| /* IPv6 not supported - seems to have different handling */ |
| /* |
| mc:addr:ifname|ifind |
| mc:ifname|ifind |
| mc:addr |
| */ |
| union sockaddr_union sockaddr1; |
| socklen_t socklen1 = sizeof(sockaddr1.ip4); |
| union sockaddr_union sockaddr2; |
| socklen_t socklen2 = sizeof(sockaddr2.ip4); |
| |
| /* first parameter is alway multicast address */ |
| /*! result */ |
| xiogetaddrinfo(opt->value.u_ip_mreq.multiaddr, NULL, |
| xfd->para.socket.la.soa.sa_family, |
| SOCK_DGRAM, IPPROTO_IP, |
| &sockaddr1, &socklen1, 0, 0); |
| ip4_mreqn.mreq.imr_multiaddr = sockaddr1.ip4.sin_addr; |
| if (0) { |
| ; /* for canonical reasons */ |
| #if HAVE_STRUCT_IP_MREQN |
| } else if (opt->value.u_ip_mreq.ifindex[0] != '\0') { |
| /* three parameters */ |
| /* second parameter is interface address */ |
| xiogetaddrinfo(opt->value.u_ip_mreq.param2, NULL, |
| xfd->para.socket.la.soa.sa_family, |
| SOCK_DGRAM, IPPROTO_IP, |
| &sockaddr2, &socklen2, 0, 0); |
| ip4_mreqn.mreq.imr_interface = sockaddr2.ip4.sin_addr; |
| /* third parameter is interface */ |
| if (ifindex(opt->value.u_ip_mreq.ifindex, |
| (unsigned int *)&ip4_mreqn.mreqn.imr_ifindex, -1) |
| < 0) { |
| Error1("cannot resolve interface \"%s\"", |
| opt->value.u_ip_mreq.ifindex); |
| } |
| #endif /* HAVE_STRUCT_IP_MREQN */ |
| } else { |
| /* two parameters */ |
| if (0) { |
| ; /* for canonical reasons */ |
| #if HAVE_STRUCT_IP_MREQN |
| /* there is a form with two parameters that uses mreqn */ |
| } else if (ifindex(opt->value.u_ip_mreq.param2, |
| (unsigned int *)&ip4_mreqn.mreqn.imr_ifindex, |
| -1) |
| >= 0) { |
| /* yes, second param converts to interface */ |
| ip4_mreqn.mreq.imr_interface.s_addr = htonl(0); |
| #endif /* HAVE_STRUCT_IP_MREQN */ |
| } else { |
| /*! result */ |
| xiogetaddrinfo(opt->value.u_ip_mreq.param2, NULL, |
| xfd->para.socket.la.soa.sa_family, |
| SOCK_DGRAM, IPPROTO_IP, |
| &sockaddr2, &socklen2, 0, 0); |
| ip4_mreqn.mreq.imr_interface = sockaddr2.ip4.sin_addr; |
| } |
| } |
| |
| #if LATER |
| if (0) { |
| ; /* for canonical reasons */ |
| } else if (xfd->para.socket.la.soa.sa_family == PF_INET) { |
| } else if (xfd->para.socket.la.soa.sa_family == PF_INET6) { |
| ip6_mreqn.mreq.imr_multiaddr = sockaddr1.ip6.sin6_addr; |
| ip6_mreqn.mreq.imr_interface = sockaddr2.ip6.sin6_addr; |
| } |
| #endif |
| |
| #if HAVE_STRUCT_IP_MREQN |
| if (Setsockopt(xfd->fd, opt->desc->major, opt->desc->minor, |
| &ip4_mreqn.mreqn, sizeof(ip4_mreqn.mreqn)) < 0) { |
| Error8("setsockopt(%d, %d, %d, {0x%08x,0x%08x,%d}, "F_Zu"): %s", |
| xfd->fd, opt->desc->major, opt->desc->minor, |
| ip4_mreqn.mreqn.imr_multiaddr.s_addr, |
| ip4_mreqn.mreqn.imr_address.s_addr, |
| ip4_mreqn.mreqn.imr_ifindex, |
| sizeof(ip4_mreqn.mreqn), |
| strerror(errno)); |
| opt->desc = ODESC_ERROR; continue; |
| } |
| #else |
| if (Setsockopt(xfd->fd, opt->desc->major, opt->desc->minor, |
| &ip4_mreqn.mreq, sizeof(ip4_mreqn.mreq)) < 0) { |
| Error7("setsockopt(%d, %d, %d, {0x%08x,0x%08x}, "F_Zu"): %s", |
| xfd->fd, opt->desc->major, opt->desc->minor, |
| ip4_mreqn.mreq.imr_multiaddr, |
| ip4_mreqn.mreq.imr_interface, |
| sizeof(ip4_mreqn.mreq), |
| strerror(errno)); |
| opt->desc = ODESC_ERROR; continue; |
| } |
| #endif |
| break; |
| } |
| break; |
| #endif /* WITH_IP4 && (defined(HAVE_STRUCT_IP_MREQ) || defined (HAVE_STRUCT_IP_MREQN)) */ |
| |
| #if WITH_IP4 && defined(HAVE_STRUCT_IP_MREQ_SOURCE) && defined(IP_ADD_SOURCE_MEMBERSHIP) |
| case OPT_IP_ADD_SOURCE_MEMBERSHIP: |
| if (xioapply_ip_add_source_membership(xfd, opt) < 0) { |
| continue; |
| } |
| break; |
| #endif /* WITH_IP4 && defined(HAVE_STRUCT_IP_MREQ_SOURCE) && defined(IP_ADD_SOURCE_MEMBERSHIP) */ |
| |
| #if WITH_IP6 && defined(HAVE_STRUCT_IPV6_MREQ) |
| case OPT_IPV6_JOIN_GROUP: |
| { |
| struct ipv6_mreq ip6_mreq = {{{{0}}}}; |
| union sockaddr_union sockaddr1; |
| socklen_t socklen1 = sizeof(sockaddr1.ip6); |
| |
| /* always two parameters */ |
| /* first parameter is multicast address */ |
| /*! result */ |
| xiogetaddrinfo(opt->value.u_ip_mreq.multiaddr, NULL, |
| xfd->para.socket.la.soa.sa_family, |
| SOCK_DGRAM, IPPROTO_IP, |
| &sockaddr1, &socklen1, 0, 0); |
| ip6_mreq.ipv6mr_multiaddr = sockaddr1.ip6.sin6_addr; |
| if (ifindex(opt->value.u_ip_mreq.param2, |
| &ip6_mreq.ipv6mr_interface, -1) |
| < 0) { |
| Error1("interface \"%s\" not found", |
| opt->value.u_ip_mreq.param2); |
| ip6_mreq.ipv6mr_interface = htonl(0); |
| } |
| |
| if (Setsockopt(xfd->fd, opt->desc->major, opt->desc->minor, |
| &ip6_mreq, sizeof(ip6_mreq)) < 0) { |
| Error6("setsockopt(%d, %d, %d, {...,0x%08x}, "F_Zu"): %s", |
| xfd->fd, opt->desc->major, opt->desc->minor, |
| ip6_mreq.ipv6mr_interface, |
| sizeof(ip6_mreq), |
| strerror(errno)); |
| opt->desc = ODESC_ERROR; continue; |
| } |
| } |
| break; |
| #endif /* WITH_IP6 && defined(HAVE_STRUCT_IPV6_MREQ) */ |
| default: |
| /* ignore here */ |
| ++opt; continue; |
| } |
| break; |
| #endif /* _WITH_SOCKET */ |
| |
| default: |
| ++opt; |
| continue; |
| } |
| opt->desc = ODESC_DONE; |
| ++opt; |
| } |
| } |
| return 0; |
| } |
| |
| |
| /* xfd->para.exec.pid must be set */ |
| int applyopts_signal(struct single *xfd, struct opt *opts) { |
| struct opt *opt; |
| |
| if (!opts) return 0; |
| |
| opt = opts; while (opt->desc != ODESC_END) { |
| if (opt->desc == ODESC_DONE || opt->desc->func != OFUNC_SIGNAL) { |
| ++opt; continue; |
| } |
| |
| if (xio_opt_signal(xfd->para.exec.pid, opt->desc->major) < 0) { |
| opt->desc = ODESC_ERROR; continue; |
| } |
| opt->desc = ODESC_DONE; |
| ++opt; |
| } |
| return 0; |
| } |
| |
| /* apply remaining options to file descriptor, and tell us if something is |
| still unused */ |
| int _xio_openlate(struct single *fd, struct opt *opts) { |
| int numleft; |
| int result; |
| |
| _xioopen_setdelayeduser(); |
| |
| if ((result = applyopts(fd->fd, opts, PH_LATE)) < 0) { |
| return result; |
| } |
| if ((result = applyopts_single(fd, opts, PH_LATE)) < 0) { |
| return result; |
| } |
| if ((result = applyopts(fd->fd, opts, PH_LATE2)) < 0) { |
| return result; |
| } |
| |
| if ((numleft = leftopts(opts)) > 0) { |
| showleft(opts); |
| Error1("%d option(s) could not be used", numleft); |
| return -1; |
| } |
| return 0; |
| } |
| |
| int dropopts(struct opt *opts, unsigned int phase) { |
| struct opt *opt; |
| |
| if (phase == PH_ALL) { |
| opts[0].desc = ODESC_END; |
| return 0; |
| } |
| opt = opts; while (opt && opt->desc != ODESC_END) { |
| if (opt->desc != ODESC_DONE && opt->desc->phase == phase) { |
| Debug1("ignoring option \"%s\"", opt->desc->defname); |
| opt->desc = ODESC_DONE; |
| } |
| ++opt; |
| } |
| return 0; |
| } |
| |
| int dropopts2(struct opt *opts, unsigned int from, unsigned int to) { |
| unsigned int i; |
| |
| for (i = from; i <= to; ++i) { |
| dropopts(opts, i); |
| } |
| return 0; |
| } |
| |