mirror of
https://github.com/moparisthebest/socat
synced 2024-11-10 19:15:03 -05:00
3800 lines
106 KiB
C
3800 lines
106 KiB
C
/* source: xioopts.c */
|
|
/* Copyright Gerhard Rieger 2001-2008 */
|
|
/* 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 "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_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
|
|
IF_IP ("aaonly", &opt_res_aaonly)
|
|
#endif /* HAVE_RESOLV_H */
|
|
#ifdef TCP_ABORT_THRESHOLD /* HP_UX */
|
|
IF_TCP ("abort-threshold", &opt_tcp_abort_threshold)
|
|
#endif
|
|
#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_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_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 WITH_EXT2 && defined(EXT2_COMPR_FL)
|
|
IF_ANY ("compr", &opt_ext2_compr)
|
|
#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_TERMIOS("crdly", &opt_crdly)
|
|
#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_TERMIOS("csize", &opt_csize)
|
|
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)
|
|
#ifdef O_DIRECT
|
|
IF_OPEN ("direct", &opt_o_direct)
|
|
#endif
|
|
#ifdef O_DIRECTORY
|
|
IF_OPEN ("directory", &opt_o_directory)
|
|
#endif
|
|
#if WITH_EXT2 && defined(EXT2_DIRSYNC_FL)
|
|
IF_ANY ("dirsync", &opt_ext2_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)
|
|
IF_IP6 ("dstopts", &opt_ipv6_dstopts)
|
|
#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_EXT2 && defined(EXT2_APPEND_FL)
|
|
IF_ANY ("ext2-append", &opt_ext2_append)
|
|
#endif
|
|
#if WITH_EXT2 && defined(EXT2_COMPR_FL)
|
|
IF_ANY ("ext2-compr", &opt_ext2_compr)
|
|
#endif
|
|
#if WITH_EXT2 && defined(EXT2_DIRSYNC_FL)
|
|
IF_ANY ("ext2-dirsync", &opt_ext2_dirsync)
|
|
#endif
|
|
#if WITH_EXT2 && defined(EXT2_IMMUTABLE_FL)
|
|
IF_ANY ("ext2-immutable", &opt_ext2_immutable)
|
|
#endif
|
|
#if WITH_EXT2 && defined(EXT2_JOURNAL_DATA_FL)
|
|
IF_ANY ("ext2-journal-data", &opt_ext2_journal_data)
|
|
#endif
|
|
#if WITH_EXT2 && defined(EXT2_NOATIME_FL)
|
|
IF_ANY ("ext2-noatime", &opt_ext2_noatime)
|
|
#endif
|
|
#if WITH_EXT2 && defined(EXT2_NODUMP_FL)
|
|
IF_ANY ("ext2-nodump", &opt_ext2_nodump)
|
|
#endif
|
|
#if WITH_EXT2 && defined(EXT2_NOTAIL_FL)
|
|
IF_ANY ("ext2-notail", &opt_ext2_notail)
|
|
#endif
|
|
#if WITH_EXT2 && defined(EXT2_SECRM_FL)
|
|
IF_ANY ("ext2-secrm", &opt_ext2_secrm)
|
|
#endif
|
|
#if WITH_EXT2 && defined(EXT2_SYNC_FL)
|
|
IF_ANY ("ext2-sync", &opt_ext2_sync)
|
|
#endif
|
|
#if WITH_EXT2 && defined(EXT2_TOPDIR_FL)
|
|
IF_ANY ("ext2-topdir", &opt_ext2_topdir)
|
|
#endif
|
|
#if WITH_EXT2 && defined(EXT2_UNRM_FL)
|
|
IF_ANY ("ext2-unrm", &opt_ext2_unrm)
|
|
#endif
|
|
#if WITH_EXT2 && defined(EXT2_APPEND_FL)
|
|
IF_ANY ("ext3-append", &opt_ext2_append)
|
|
#endif
|
|
#if WITH_EXT2 && defined(EXT2_COMPR_FL)
|
|
IF_ANY ("ext3-compr", &opt_ext2_compr)
|
|
#endif
|
|
#if WITH_EXT2 && defined(EXT2_DIRSYNC_FL)
|
|
IF_ANY ("ext3-dirsync", &opt_ext2_dirsync)
|
|
#endif
|
|
#if WITH_EXT2 && defined(EXT2_IMMUTABLE_FL)
|
|
IF_ANY ("ext3-immutable", &opt_ext2_immutable)
|
|
#endif
|
|
#if WITH_EXT2 && defined(EXT2_JOURNAL_DATA_FL)
|
|
IF_ANY ("ext3-journal-data", &opt_ext2_journal_data)
|
|
#endif
|
|
#if WITH_EXT2 && defined(EXT2_NOATIME_FL)
|
|
IF_ANY ("ext3-noatime", &opt_ext2_noatime)
|
|
#endif
|
|
#if WITH_EXT2 && defined(EXT2_NODUMP_FL)
|
|
IF_ANY ("ext3-nodump", &opt_ext2_nodump)
|
|
#endif
|
|
#if WITH_EXT2 && defined(EXT2_NOTAIL_FL)
|
|
IF_ANY ("ext3-notail", &opt_ext2_notail)
|
|
#endif
|
|
#if WITH_EXT2 && defined(EXT2_SECRM_FL)
|
|
IF_ANY ("ext3-secrm", &opt_ext2_secrm)
|
|
#endif
|
|
#if WITH_EXT2 && defined(EXT2_SYNC_FL)
|
|
IF_ANY ("ext3-sync", &opt_ext2_sync)
|
|
#endif
|
|
#if WITH_EXT2 && defined(EXT2_TOPDIR_FL)
|
|
IF_ANY ("ext3-topdir", &opt_ext2_topdir)
|
|
#endif
|
|
#if WITH_EXT2 && defined(EXT2_UNRM_FL)
|
|
IF_ANY ("ext3-unrm", &opt_ext2_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 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)
|
|
IF_IP6 ("hoplimit", &opt_ipv6_hoplimit)
|
|
IF_IP6 ("hopopts", &opt_ipv6_hopopts)
|
|
#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)
|
|
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_EXT2 && defined(EXT2_IMMUTABLE_FL)
|
|
IF_ANY ("immutable", &opt_ext2_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)
|
|
#ifdef IP_ADD_MEMBERSHIP
|
|
IF_IP ("ip-add-membership", &opt_ip_add_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)
|
|
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)
|
|
IF_IP6 ("ipv6-add-membership", &opt_ipv6_join_group)
|
|
#ifdef IPV6_AUTHHDR
|
|
IF_IP6 ("ipv6-authhdr", &opt_ipv6_authhdr)
|
|
#endif
|
|
IF_IP6 ("ipv6-dstopts", &opt_ipv6_dstopts)
|
|
#ifdef IPV4_FLOWINFO
|
|
IF_IP6 ("ipv6-flowinfo", &opt_ipv6_flowinfo)
|
|
#endif
|
|
IF_IP6 ("ipv6-hoplimit", &opt_ipv6_hoplimit)
|
|
IF_IP6 ("ipv6-hopopts", &opt_ipv6_hopopts)
|
|
IF_IP6 ("ipv6-join-group", &opt_ipv6_join_group)
|
|
IF_IP6 ("ipv6-pktinfo", &opt_ipv6_pktinfo)
|
|
IF_IP6 ("ipv6-recvdstopts", &opt_ipv6_recvdstopts)
|
|
#ifdef IPV6_RECVERR
|
|
IF_IP6 ("ipv6-recverr", &opt_ipv6_recverr)
|
|
#endif
|
|
IF_IP6 ("ipv6-recvhoplimit", &opt_ipv6_recvhoplimit)
|
|
IF_IP6 ("ipv6-recvhopopts", &opt_ipv6_recvhopopts)
|
|
#ifdef IPV6_PATHMTU
|
|
IF_IP6 ("ipv6-recvpathmtu", &opt_ipv6_recvpathmtu)
|
|
#endif
|
|
IF_IP6 ("ipv6-recvpktinfo", &opt_ipv6_recvpktinfo)
|
|
IF_IP6 ("ipv6-recvrthdr", &opt_ipv6_recvrthdr)
|
|
IF_IP6 ("ipv6-recvtclass", &opt_ipv6_recvtclass)
|
|
IF_IP6 ("ipv6-rthdr", &opt_ipv6_rthdr)
|
|
IF_IP6 ("ipv6-tclass", &opt_ipv6_tclass)
|
|
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)
|
|
#ifdef 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)
|
|
IF_IP6 ("join-group", &opt_ipv6_join_group)
|
|
#if WITH_EXT2 && defined(EXT2_JOURNAL_DATA_FL)
|
|
IF_ANY ("journal", &opt_ext2_journal_data)
|
|
IF_ANY ("journal-data", &opt_ext2_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_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)
|
|
#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_OPENSSL("method", &opt_openssl_method)
|
|
IF_TERMIOS("min", &opt_vmin)
|
|
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_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_EXT2 && defined(EXT2_NODUMP_FL)
|
|
IF_ANY ("nodump", &opt_ext2_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_TUN ("notrailers", &opt_iff_notrailers)
|
|
#ifdef O_NSHARE
|
|
IF_OPEN ("nshare", &opt_o_nshare)
|
|
#endif
|
|
#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-dhparam", &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_OPENSSL("openssl-method", &opt_openssl_method)
|
|
IF_OPENSSL("openssl-pseudo", &opt_openssl_pseudo)
|
|
IF_OPENSSL("openssl-verify", &opt_openssl_verify)
|
|
IF_TERMIOS("opost", &opt_opost)
|
|
#ifdef HAVE_TERMIOS_ISPEED
|
|
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)
|
|
/*IF_IPAPP("port", &opt_port)*/
|
|
IF_TUN ("portsel", &opt_iff_portsel)
|
|
#if HAVE_RESOLV_H
|
|
IF_IP ("primary", &opt_res_primary)
|
|
#endif /* HAVE_RESOLV_H */
|
|
#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)
|
|
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-resolve", &opt_proxy_resolve)
|
|
IF_PROXY ("proxyauth", &opt_proxy_authorization)
|
|
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 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_SOCKET ("rcvbuf", &opt_so_rcvbuf)
|
|
IF_SOCKET ("rcvbuf-late", &opt_so_rcvbuf_late)
|
|
#ifdef SO_RCVLOWAT
|
|
IF_SOCKET ("rcvlowat", &opt_so_rcvlowat)
|
|
#endif
|
|
#ifdef SO_RCVTIMEO
|
|
IF_SOCKET ("rcvtimeo", &opt_so_rcvtimeo)
|
|
#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
|
|
IF_IP6 ("recvdstopts", &opt_ipv6_recvdstopts)
|
|
#ifdef IP_RECVERR
|
|
IF_IP ("recverr", &opt_ip_recverr)
|
|
#endif
|
|
IF_IP6 ("recvhoplimit", &opt_ipv6_recvhoplimit)
|
|
IF_IP6 ("recvhopopts", &opt_ipv6_recvhopopts)
|
|
#ifdef IP_RECVIF
|
|
IF_IP ("recvif", &opt_ip_recvif)
|
|
#endif
|
|
#ifdef IP_RECVOPTS
|
|
IF_IP ("recvopts", &opt_ip_recvopts)
|
|
#endif
|
|
IF_IP6 ("recvpktinfo", &opt_ipv6_recvpktinfo)
|
|
IF_IP6 ("recvrthdr", &opt_ipv6_recvrthdr)
|
|
#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_IP ("res-aaonly", &opt_res_aaonly)
|
|
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_IP ("res-primary", &opt_res_primary)
|
|
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
|
|
IF_IP6 ("rthdr", &opt_ipv6_rthdr)
|
|
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)
|
|
#if WITH_EXT2 && defined(EXT2_SECRM_FL)
|
|
IF_ANY ("secrm", &opt_ext2_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_ANY ("setuid", &opt_setuid)
|
|
IF_ANY ("setuid-early", &opt_setuid_early)
|
|
#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
|
|
#ifdef SO_SNDTIMEO
|
|
IF_SOCKET ("sndtimeo", &opt_so_sndtimeo)
|
|
#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-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
|
|
#ifdef SO_RCVTIMEO
|
|
IF_SOCKET ("so-rcvtimeo", &opt_so_rcvtimeo)
|
|
#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_SNDTIMEO
|
|
IF_SOCKET ("so-sndtimeo", &opt_so_sndtimeo)
|
|
#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_SOCKS4 ("socksport", &opt_socksport)
|
|
IF_SOCKS4 ("socksuser", &opt_socksuser)
|
|
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)
|
|
IF_ANY ("su", &opt_substuser)
|
|
IF_ANY ("su-d", &opt_substuser_delayed)
|
|
IF_ANY ("substuser", &opt_substuser)
|
|
IF_ANY ("substuser-delayed", &opt_substuser_delayed)
|
|
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 EXT2_SYNC_FL
|
|
IF_ANY ("sync", &opt_ext2_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_TERMIOS("tabdly", &opt_tabdly)
|
|
#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
|
|
#ifdef O_TEXT
|
|
IF_ANY ("text", &opt_o_text)
|
|
#endif
|
|
IF_UNIX ("tightsocklen", &opt_unix_tightsocklen)
|
|
IF_TERMIOS("time", &opt_vtime)
|
|
#ifdef SO_TIMESTAMP
|
|
IF_SOCKET ("timestamp", &opt_so_timestamp)
|
|
#endif
|
|
IF_TERMIOS("tiocsctty", &opt_tiocsctty)
|
|
#if WITH_EXT2 && defined(EXT2_TOPDIR_FL)
|
|
IF_ANY ("topdir", &opt_ext2_topdir)
|
|
#endif
|
|
IF_IP ("tos", &opt_ip_tos)
|
|
IF_TERMIOS("tostop", &opt_tostop)
|
|
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", &opt_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_EXT2 && defined(EXT2_UNRM_FL)
|
|
IF_ANY ("unrm", &opt_ext2_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[512], *tokp; size_t len;
|
|
int parsres;
|
|
int result;
|
|
char 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) {
|
|
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(): unknown option \"%s\"", token);
|
|
continue;
|
|
}
|
|
|
|
if (!(ent->desc->group & groups) && !(ent->desc->group & GROUP_ANY) &&
|
|
!xioopts_ignoregroups) {
|
|
Error1("parseopts(): option \"%s\" not supported with this address type",
|
|
token /*a0*/);
|
|
Info2("parseopts() 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) {
|
|
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))) != 0) {
|
|
Error1("parseopts(): 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);
|
|
if (ul > UCHAR_MAX) {
|
|
Error3("parseopts(%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;
|
|
case TYPE_INT:
|
|
if (assign) {
|
|
char *rest;
|
|
(*opts)[i].value.u_int = strtoul(token, &rest/*!*/, 0);
|
|
} 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);
|
|
if (rest && *rest) {
|
|
Error1("error in option \"%s\": \"0\" or \"1\" required", 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);
|
|
if (ulongval > UINT_MAX) {
|
|
Error3("parseopts(%s): unsigned int value exceeds limit (%lu vs. %u), using max",
|
|
a0, ulongval, UINT_MAX);
|
|
}
|
|
(*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);
|
|
if (ulongval > USHRT_MAX) {
|
|
Error3("parseopts(%s): unsigned short value exceeds limit (%lu vs. %u), using max",
|
|
a0, ulongval, USHRT_MAX);
|
|
}
|
|
(*opts)[i].value.u_ushort = ulongval;
|
|
}
|
|
Info2("setting option \"%s\" to %u", ent->desc->defname,
|
|
(*opts)[i].value.u_ushort);
|
|
break;
|
|
|
|
case TYPE_OFF32:
|
|
#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 = strtol(token, &rest, 0);
|
|
(*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);
|
|
(*opts)[i].value.u_ulong = ulongval;
|
|
}
|
|
Info2("setting option \"%s\" to %lu", ent->desc->defname,
|
|
(*opts)[i].value.u_ulong);
|
|
break;
|
|
|
|
#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);
|
|
# else
|
|
/* in this case, input value range is limited */
|
|
slonglongval = strtol(token, &rest, 0);
|
|
# endif /* HAVE_STRTOLL */
|
|
(*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);
|
|
} 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);
|
|
} 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);
|
|
}
|
|
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;
|
|
val = strtod(token, NULL);
|
|
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) * 1000000;
|
|
}
|
|
break;
|
|
#if HAVE_STRUCT_TIMESPEC
|
|
case TYPE_TIMESPEC:
|
|
if (!assign) {
|
|
Error1("option \"%s\": value required", a0);
|
|
continue;
|
|
} else {
|
|
double val;
|
|
val = strtod(token, NULL);
|
|
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);
|
|
}
|
|
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 */
|
|
#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= */
|
|
nestlex((const char **)&tokp, &buffp, &bufspc,
|
|
ends, NULL, NULL, nests,
|
|
true, false, false);
|
|
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= */
|
|
nestlex((const char **)&tokp, &buffp, &bufspc,
|
|
ends, NULL, NULL, nests,
|
|
true, false, false);
|
|
*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);
|
|
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 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;
|
|
nestlex((const char **)&tokp, &buffp, &bufspc,
|
|
ends, NULL, NULL, nests,
|
|
true, false, false);
|
|
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.s_addr;
|
|
}
|
|
break;
|
|
#endif /* defined(WITH_IP4) */
|
|
|
|
default:
|
|
Error2("parseopts(): 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;
|
|
}
|
|
|
|
/* 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) {
|
|
*result = opt->value.u_int;
|
|
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 an 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) */
|
|
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 */
|
|
unsigned long res_opts0, unsigned long res_opts1) {
|
|
const char portsep[] = ":";
|
|
const char *ends[] = { portsep, NULL };
|
|
const char *nests[] = { "[", "]", NULL };
|
|
bool addrallowed, portallowed;
|
|
char *bindname, *bindp;
|
|
char hostname[512], *hostp = hostname, *portp = NULL;
|
|
size_t hostlen = sizeof(hostname)-1;
|
|
int result;
|
|
|
|
if (retropt_string(opts, OPT_BIND, &bindname) < 0) {
|
|
return STAT_NOACTION;
|
|
}
|
|
addrallowed = true;
|
|
portallowed = (feats>=2);
|
|
bindp = bindname;
|
|
nestlex((const char **)&bindp, &hostp, &hostlen, ends, NULL, NULL, nests,
|
|
true, false, false);
|
|
*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);
|
|
}
|
|
}
|
|
|
|
switch (af) {
|
|
#if WITH_IP4 || WITH_IP6
|
|
#if WITH_IP4
|
|
case AF_INET:
|
|
#endif
|
|
#if WITH_IP6
|
|
case AF_INET6:
|
|
#endif /*WITH_IP6 */
|
|
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 tight = false;
|
|
struct sockaddr_un *s_un = (struct sockaddr_un *)sa;
|
|
*salen = xiosetunix(s_un, bindname, false, 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, unsigned int 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_long, opt->desc->major) < 0) {
|
|
Error4("lseek(%d, %ld, %d): %s",
|
|
fd, opt->value.u_long, 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, %Ld, %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;
|
|
}
|
|
|
|
#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, %d): %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,
|
|
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_Zu"}): %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;
|
|
}
|
|
#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_long) < 0) {
|
|
Error3("ftruncate(%d, %ld): %s",
|
|
fd, opt->value.u_long, strerror(errno));
|
|
opt->desc = ODESC_ERROR; ++opt; continue;
|
|
}
|
|
break;
|
|
#if HAVE_FTRUNCATE64
|
|
case OPT_FTRUNCATE64:
|
|
if (Ftruncate64(fd, opt->value.u_long) < 0) {
|
|
Error3("ftruncate64(%d, %ld): %s",
|
|
fd, opt->value.u_long, 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:
|
|
{
|
|
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;
|
|
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;
|
|
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 0
|
|
union {
|
|
struct termios termarg;
|
|
tcflag_t flags[4];
|
|
} tdata;
|
|
if (Tcgetattr(fd, &tdata.termarg) < 0) {
|
|
Error3("tcgetattr(%d, %p): %s",
|
|
fd, &tdata.termarg, strerror(errno));
|
|
opt->desc = ODESC_ERROR; ++opt; continue;
|
|
}
|
|
if (opt->value.u_bool) {
|
|
tdata.flags[opt->desc->major] |= opt->desc->minor;
|
|
} else {
|
|
tdata.flags[opt->desc->major] &= ~opt->desc->minor;
|
|
}
|
|
if (Tcsetattr(fd, TCSADRAIN, &tdata.termarg) < 0) {
|
|
Error3("tcsetattr(%d, TCSADRAIN, %p): %s",
|
|
fd, &tdata.termarg, strerror(errno));
|
|
opt->desc = ODESC_ERROR; ++opt; continue;
|
|
}
|
|
#else
|
|
if (xiotermiosflag_applyopt(fd, opt) < 0) {
|
|
opt->desc = ODESC_ERROR; ++opt; continue;
|
|
}
|
|
#endif
|
|
|
|
} else if (opt->desc->func == OFUNC_TERMIOS_VALUE) {
|
|
union {
|
|
struct termios termarg;
|
|
tcflag_t flags[4];
|
|
} tdata;
|
|
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 (Tcgetattr(fd, &tdata.termarg) < 0) {
|
|
Error3("tcgetattr(%d, %p): %s",
|
|
fd, &tdata.termarg, strerror(errno));
|
|
opt->desc = ODESC_ERROR; ++opt; continue;
|
|
}
|
|
|
|
tdata.flags[opt->desc->major] &= ~opt->desc->minor;
|
|
tdata.flags[opt->desc->major] |=
|
|
((opt->value.u_uint << opt->desc->arg3) & opt->desc->minor);
|
|
if (Tcsetattr(fd, TCSADRAIN, &tdata.termarg) < 0) {
|
|
Error3("tcsetattr(%d, TCSADRAIN, %p): %s",
|
|
fd, &tdata.termarg, strerror(errno));
|
|
opt->desc = ODESC_ERROR; ++opt; continue;
|
|
}
|
|
|
|
} else if (opt->desc->func == OFUNC_TERMIOS_PATTERN) {
|
|
union {
|
|
struct termios termarg;
|
|
tcflag_t flags[4];
|
|
} tdata;
|
|
if (Tcgetattr(fd, &tdata.termarg) < 0) {
|
|
Error3("tcgetattr(%d, %p): %s",
|
|
fd, &tdata.termarg, strerror(errno));
|
|
opt->desc = ODESC_ERROR; ++opt; continue;
|
|
}
|
|
tdata.flags[opt->desc->major] &= ~opt->desc->arg3;
|
|
tdata.flags[opt->desc->major] |= opt->desc->minor;
|
|
if (Tcsetattr(fd, TCSADRAIN, &tdata.termarg) < 0) {
|
|
Error3("tcsetattr(%d, TCSADRAIN, %p): %s",
|
|
fd, &tdata.termarg, strerror(errno));
|
|
opt->desc = ODESC_ERROR;++opt; continue;
|
|
}
|
|
|
|
} else if (opt->desc->func == OFUNC_TERMIOS_CHAR) {
|
|
struct termios termarg;
|
|
if (Tcgetattr(fd, &termarg) < 0) {
|
|
Error3("tcgetattr(%d, %p): %s",
|
|
fd, &termarg, strerror(errno));
|
|
opt->desc = ODESC_ERROR; ++opt; continue;
|
|
}
|
|
termarg.c_cc[opt->desc->major] = opt->value.u_byte;
|
|
if (Tcsetattr(fd, TCSADRAIN, &termarg) < 0) {
|
|
Error3("tcsetattr(%d, TCSADRAIN, %p): %s",
|
|
fd, &termarg, strerror(errno));
|
|
opt->desc = ODESC_ERROR; ++opt; continue;
|
|
}
|
|
|
|
#ifdef HAVE_TERMIOS_ISPEED
|
|
} else if (opt->desc->func == OFUNC_TERMIOS_SPEED) {
|
|
union {
|
|
struct termios termarg;
|
|
speed_t speeds[sizeof(struct termios)/sizeof(speed_t)];
|
|
} tdata;
|
|
if (Tcgetattr(fd, &tdata.termarg) < 0) {
|
|
Error3("tcgetattr(%d, %p): %s",
|
|
fd, &tdata.termarg, strerror(errno));
|
|
opt->desc = ODESC_ERROR; ++opt; continue;
|
|
}
|
|
tdata.speeds[opt->desc->major] = opt->value.u_uint;
|
|
if (Tcsetattr(fd, TCSADRAIN, &tdata.termarg) < 0) {
|
|
Error3("tcsetattr(%d, TCSADRAIN, %p): %s",
|
|
fd, &tdata.termarg, strerror(errno));
|
|
opt->desc = ODESC_ERROR; ++opt; continue;
|
|
}
|
|
#endif /* HAVE_TERMIOS_ISPEED */
|
|
|
|
} else if (opt->desc->func == OFUNC_TERMIOS_SPEC) {
|
|
struct termios termarg;
|
|
if (Tcgetattr(fd, &termarg) < 0) {
|
|
Error3("tcgetattr(%d, %p): %s",
|
|
fd, &termarg, strerror(errno));
|
|
opt->desc = ODESC_ERROR; ++opt; continue;
|
|
}
|
|
switch (opt->desc->optcode) {
|
|
case OPT_RAW:
|
|
termarg.c_iflag &=
|
|
~(IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK|ISTRIP|INLCR|IGNCR|ICRNL|IXON|IXOFF
|
|
#ifdef IUCLC
|
|
|IUCLC
|
|
#endif
|
|
|IXANY|IMAXBEL);
|
|
termarg.c_iflag |= (0);
|
|
termarg.c_oflag &= ~(OPOST);
|
|
termarg.c_oflag |= (0);
|
|
termarg.c_cflag &= ~(0);
|
|
termarg.c_cflag |= (0);
|
|
termarg.c_lflag &= ~(ISIG|ICANON
|
|
#ifdef XCASE
|
|
|XCASE
|
|
#endif
|
|
);
|
|
termarg.c_lflag |= (0);
|
|
termarg.c_cc[VMIN] = 1;
|
|
termarg.c_cc[VTIME] = 0;
|
|
break;
|
|
case OPT_SANE:
|
|
/* cread -ignbrk brkint -inlcr -igncr icrnl
|
|
-ixoff -iuclc -ixany imaxbel opost -olcuc -ocrnl
|
|
onlcr -onocr -onlret -ofill -ofdel nl0 cr0 tab0 bs0
|
|
vt0 ff0 isig icanon iexten echo echoe echok -echonl
|
|
-noflsh -xcase -tostop -echoprt echoctl echoke, and
|
|
also sets all special characters to their default
|
|
values.
|
|
*/
|
|
termarg.c_iflag &= ~(IGNBRK|INLCR|IGNCR|IXOFF
|
|
#ifdef IUCLC
|
|
|IUCLC
|
|
#endif
|
|
|IXANY);
|
|
termarg.c_iflag |= (BRKINT|ICRNL|IMAXBEL);
|
|
termarg.c_oflag &= ~(0 /* for canonical reasons */
|
|
#ifdef OLCUC
|
|
|OLCUC
|
|
#endif
|
|
#ifdef OCRNL
|
|
|OCRNL
|
|
#endif
|
|
#ifdef ONOCR
|
|
|ONOCR
|
|
#endif
|
|
#ifdef ONLRET
|
|
|ONLRET
|
|
#endif
|
|
#ifdef OFILL
|
|
|OFILL
|
|
#endif
|
|
#ifdef OFDEL
|
|
|OFDEL
|
|
#endif
|
|
#ifdef NLDLY
|
|
|NLDLY
|
|
#endif
|
|
#ifdef CRDLY
|
|
|CRDLY
|
|
#endif
|
|
#ifdef TABDLY
|
|
|TABDLY
|
|
#endif
|
|
#ifdef BSDLY
|
|
|BSDLY
|
|
#endif
|
|
#ifdef VTDLY
|
|
|VTDLY
|
|
#endif
|
|
#ifdef FFDLY
|
|
|FFDLY
|
|
#endif
|
|
);
|
|
termarg.c_oflag |= (OPOST|ONLCR
|
|
#ifdef NL0
|
|
|NL0
|
|
#endif
|
|
#ifdef CR0
|
|
|CR0
|
|
#endif
|
|
#ifdef TAB0
|
|
|TAB0
|
|
#endif
|
|
#ifdef BS0
|
|
|BS0
|
|
#endif
|
|
#ifdef VT0
|
|
|VT0
|
|
#endif
|
|
#ifdef FF0
|
|
|FF0
|
|
#endif
|
|
);
|
|
termarg.c_cflag &= ~(0);
|
|
termarg.c_cflag |= (CREAD);
|
|
termarg.c_lflag &= ~(ECHONL|NOFLSH
|
|
#ifdef XCASE
|
|
|XCASE
|
|
#endif
|
|
|TOSTOP
|
|
#ifdef ECHOPRT
|
|
|ECHOPRT
|
|
#endif
|
|
);
|
|
termarg.c_lflag |= (ISIG|ICANON|IEXTEN|ECHO|ECHOE|ECHOK|ECHOCTL|ECHOKE);
|
|
/*! "sets characters to their default values... - which? */
|
|
break;
|
|
default:
|
|
Error("TERMIOS option not handled - internal error?");
|
|
}
|
|
if (Tcsetattr(fd, TCSADRAIN, &termarg) < 0) {
|
|
Error3("tcsetattr(%d, TCSADRAIN, %p): %s",
|
|
fd, &termarg, strerror(errno));
|
|
opt->desc = ODESC_ERROR; ++opt; continue;
|
|
}
|
|
|
|
#endif /* WITH_TERMIOS */
|
|
|
|
} 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;
|
|
}
|
|
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) {
|
|
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)
|
|
< 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)
|
|
>= 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_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) < 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) {
|
|
free(opts);
|
|
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;
|
|
}
|
|
|