From 47af17dbf24f8156d6a1b17eec5e4744f7bdc2db Mon Sep 17 00:00:00 2001 From: Gerhard Rieger Date: Thu, 26 Oct 2023 19:08:26 +0200 Subject: [PATCH] Interface flags now defined with INTERFACE, inherited by TUN --- CHANGES | 3 ++ configure.ac | 1 + doc/socat.yo | 48 ++++++++++------- sysincludes.h | 5 ++ sysutils.c | 4 ++ sysutils.h | 4 ++ test.sh | 40 ++++++++------ xio-interface.c | 135 ++++++++++++++++++++++++++++++++++++++++++++++-- xio-interface.h | 25 +++++++++ xio-socket.c | 1 + xio-tun.c | 55 +++----------------- xio-tun.h | 18 ------- xio.h | 11 ++-- xioclose.c | 10 ++++ xioconfig.h | 12 +++-- xioopts.c | 82 ++++++++++++++++++----------- 16 files changed, 312 insertions(+), 142 deletions(-) diff --git a/CHANGES b/CHANGES index ff7b477..55dcaba 100644 --- a/CHANGES +++ b/CHANGES @@ -83,6 +83,9 @@ Corrections: Now Socat handles EPIPE and ECONNRESET as errors to indicate possible failure of data transfer. + INTERFACE addresses did not accept options of INTERFACE group (for + historical reasons they were only available with TUN addresses). + Coding: Introduced groups_t instead of uint32_t, for more flexibility. diff --git a/configure.ac b/configure.ac index a48b127..60e269e 100644 --- a/configure.ac +++ b/configure.ac @@ -312,6 +312,7 @@ AC_ARG_ENABLE(genericsocket, [ --disable-genericsocket disable generic socket s *) AC_DEFINE(WITH_GENERICSOCKET) AC_MSG_RESULT(yes);; esac], [AC_DEFINE(WITH_GENERICSOCKET) AC_MSG_RESULT(yes)]) + AC_MSG_CHECKING(whether to include generic network interface support) AC_ARG_ENABLE(interface, [ --disable-interface disable network interface support], [case "$enableval" in diff --git a/doc/socat.yo b/doc/socat.yo index 40555e9..93f201a 100644 --- a/doc/socat.yo +++ b/doc/socat.yo @@ -1084,7 +1084,7 @@ label(ADDRESS_TUN)dit(bf(tt(TUN[:/]))) Note: If you intend to transfer packets between two Socat "wire sides" you need a protocol that keeps packet boundaries, e.g.UDP; TCP might work with option link(nodelay)(OPTION_TCP_NODELAY).nl() - Option groups: link(FD)(GROUP_FD),link(NAMED)(GROUP_NAMED),link(OPEN)(GROUP_OPEN),link(TUN)(GROUP_TUN) nl() + Option groups: link(FD)(GROUP_FD),link(NAMED)(GROUP_NAMED),link(OPEN)(GROUP_OPEN),link(TUN)(GROUP_INTERFACE) nl() Useful options: link(iff-up)(OPTION_IFF_UP), link(tun-device)(OPTION_TUN_DEVICE), @@ -3002,27 +3002,11 @@ enddit() startdit()enddit()nl() -label(GROUP_TUN)em(bf(TUN option group)) +label(GROUP_INTERFACE)em(bf(INTERFACE option group)) -Options that control Linux TUN/TAP interface device addresses. +Options that control Linux INTERFACE addresses. startdit() -label(OPTION_TUN_DEVICE)dit(bf(tt(tun-device=))) - Instructs socat to take another path for the TUN clone device. Default is - tt(/dev/net/tun). -label(OPTION_TUN_NAME)dit(bf(tt(tun-name=))) - Gives the resulting network interface a specific name instead of the system - generated (tun0, tun1, etc.) -label(OPTION_TUN_TYPE)dit(bf(tt(tun-type=[tun|tap]))) - Sets the type of the TUN device; use this option to generate a TAP - device. See the Linux docu for the difference between these types. - When you try to establish a tunnel between two TUN devices, their types - should be the same. -label(OPTION_IFF_NO_PI)dit(bf(tt(iff-no-pi))) - Sets the IFF_NO_PI flag which controls if the device includes additional - packet information in the tunnel. - When you try to establish a tunnel between two TUN devices, these flags - should have the same values. label(OPTION_IFF_UP)dit(bf(tt(iff-up))) Sets the TUN network interface status UP. Strongly recommended. label(OPTION_IFF_BROADCAST)dit(bf(tt(iff-broadcast))) @@ -3060,6 +3044,32 @@ enddit() startdit()enddit()nl() +label(GROUP_TUN)em(bf(TUN option group)) + +Options that control Linux TUN/TAP interface device addresses. + +startdit() +label(OPTION_TUN_DEVICE)dit(bf(tt(tun-device=))) + Instructs socat to take another path for the TUN clone device. Default is + tt(/dev/net/tun). +label(OPTION_TUN_NAME)dit(bf(tt(tun-name=))) + Gives the resulting network interface a specific name instead of the system + generated (tun0, tun1, etc.) +label(OPTION_TUN_TYPE)dit(bf(tt(tun-type=[tun|tap]))) + Sets the type of the TUN device; use this option to generate a TAP + device. See the Linux docu for the difference between these types. + When you try to establish a tunnel between two TUN devices, their types + should be the same. +label(OPTION_IFF_NO_PI)dit(bf(tt(iff-no-pi))) + Sets the IFF_NO_PI flag which controls if the device includes additional + packet information in the tunnel. + When you try to establish a tunnel between two TUN devices, these flags + should have the same values. +enddit() + +startdit()enddit()nl() + + label(VALUES) manpagesection(DATA VALUES) diff --git a/sysincludes.h b/sysincludes.h index 4170f27..4d1078f 100644 --- a/sysincludes.h +++ b/sysincludes.h @@ -5,6 +5,11 @@ #ifndef __sysincludes_h_included #define __sysincludes_h_included 1 +/* Sorry for this... */ +#if defined(__sun) || defined(__sun__) || defined(__SunOS) +# define BSD_COMP 1 /* for SIOCGIFFLAGS */ +#endif + #include /* ptrdiff_t */ #if HAVE_STDBOOL_H #include /* bool, true, false */ diff --git a/sysutils.c b/sysutils.c index 6c9b1c6..24efd39 100644 --- a/sysutils.c +++ b/sysutils.c @@ -16,6 +16,10 @@ #include "utils.h" #include "sysutils.h" +#if _WITH_INTERFACE +const int one = 1; +#endif + /* Substitute for Write(): Try to write all bytes before returning; this handles EINTR, EAGAIN/EWOULDBLOCK, and partial write situations. The drawback is that this diff --git a/sysutils.h b/sysutils.h index 514d1d2..e84df00 100644 --- a/sysutils.h +++ b/sysutils.h @@ -43,6 +43,10 @@ struct xiorange { } ; #endif /* _WITH_SOCKET */ +#if _WITH_INTERFACE +extern const int one; +#endif + extern ssize_t writefull(int fd, const void *buff, size_t bytes); #if _WITH_SOCKET diff --git a/test.sh b/test.sh index 60f5054..9fe7522 100755 --- a/test.sh +++ b/test.sh @@ -8395,34 +8395,42 @@ tl="$td/test$N.lock" da="$(date) $RANDOM" TUNNET=10.255.255 TUNNAME=tun9 -CMD1="$TRACE $SOCAT $opts -L $tl TUN:$TUNNET.1/24,iff-up=1,tun-type=tun,tun-name=$TUNNAME echo" -CMD="$TRACE $SOCAT $opts - INTERFACE:$TUNNAME" +CMD0="$TRACE $SOCAT $opts -L $tl TUN:$TUNNET.1/24,iff-up=1,tun-type=tun,tun-name=$TUNNAME PIPE" +CMD1="$TRACE $SOCAT $opts - INTERFACE:$TUNNAME" printf "test $F_n $TEST... " $N -$CMD1 2>"${te}1" & -pid1="$!" +$CMD0 2>"${te}1" & +pid0="$!" #waitinterface "$TUNNAME" -sleep 1 -echo "$da" |$CMD >"$tf" 2>"${te}" -kill $pid1 2>/dev/null +usleep $MICROS +{ echo "$da"; usleep $MICROS ; } |$CMD1 >"$tf" 2>"${te}" +rc1=$? +usleep $MICROS +kill $pid0 2>/dev/null wait -if [ $? -ne 0 ]; then - $PRINTF "$FAILED: $TRACE $SOCAT:\n" - echo "$CMD &" +if [ "$rc1" -ne 0 ]; then + $PRINTF "$FAILED (rc1=$rc1):\n" + echo "$CMD0 &" + cat "${te}0" >&2 echo "$CMD1" - cat "${te}" "${te}1" + cat "${te}1" >&2 numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" elif ! echo "$da" |diff - "$tf" >"$tdiff"; then - $PRINTF "$FAILED\n" - echo "$CMD &" + $PRINTF "$FAILED (diff)\n" + echo "$CMD0 &" + cat "${te}0" >&2 echo "$CMD1" + cat "${te}1" >&2 + echo "// diff:" cat "$tdiff" - cat "${te}" "${te}1" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" else $PRINTF "$OK\n" - if [ -n "$debug" ]; then cat "${te}" "${te}1"; fi + if [ "$VERBOSE" ]; then echo "$CMD0 &"; fi + if [ "$DEBUG" ]; then cat "${te}0" >&2; fi + if [ "$VERBOSE" ]; then echo "$CMD1"; fi + if [ "$DEBUG" ]; then cat "${te}1" >&2; fi numOK=$((numOK+1)) fi fi ;; # NUMCOND, feats @@ -13720,7 +13728,7 @@ elif [ $rc1 -ne 0 ]; then cat "${te}1" >&2 numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" -elif echo "$da" |diff - ${tf}1 >${tfdiff}$N; then +elif echo "$da" |diff - ${tf}1 >${tdiff}$N; then $PRINTF "$OK\n" numOK=$((numOK+1)) else diff --git a/xio-interface.c b/xio-interface.c index 1c9106f..cfd467b 100644 --- a/xio-interface.c +++ b/xio-interface.c @@ -6,7 +6,7 @@ #include "xiosysincludes.h" -#if WITH_INTERFACE +#if _WITH_INTERFACE #include "xioopen.h" #include "xio-socket.h" @@ -19,7 +19,39 @@ int xioopen_interface(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *xfd, groups_t groups, int pf, int dummy2, int dummy3); -const struct addrdesc xioaddr_interface= { "INTERFACE", 3, xioopen_interface, GROUP_FD|GROUP_SOCKET, PF_PACKET, 0, 0 HELP(":") }; +/*0 const struct optdesc opt_interface_addr = { "interface-addr", "address", OPT_INTERFACE_ADDR, GROUP_INTERFACE, PH_FD, TYPE_STRING, OFUNC_SPEC };*/ +/*0 const struct optdesc opt_interface_netmask = { "interface-netmask", "netmask", OPT_INTERFACE_NETMASK, GROUP_INTERFACE, PH_FD, TYPE_STRING, OFUNC_SPEC };*/ +const struct optdesc opt_iff_up = { "iff-up", "up", OPT_IFF_UP, GROUP_INTERFACE, PH_INIT, TYPE_BOOL, OFUNC_OFFSET_MASKS, XIO_OFFSETOF(para.interface.iff_opts), XIO_SIZEOF(para.interface.iff_opts), IFF_UP }; +const struct optdesc opt_iff_broadcast = { "iff-broadcast", NULL, OPT_IFF_BROADCAST, GROUP_INTERFACE, PH_FD, TYPE_BOOL, OFUNC_OFFSET_MASKS, XIO_OFFSETOF(para.interface.iff_opts), XIO_SIZEOF(para.interface.iff_opts), IFF_BROADCAST }; +const struct optdesc opt_iff_debug = { "iff-debug" , NULL, OPT_IFF_DEBUG, GROUP_INTERFACE, PH_FD, TYPE_BOOL, OFUNC_OFFSET_MASKS, XIO_OFFSETOF(para.interface.iff_opts), XIO_SIZEOF(para.interface.iff_opts), IFF_DEBUG }; +const struct optdesc opt_iff_loopback = { "iff-loopback" , "loopback", OPT_IFF_LOOPBACK, GROUP_INTERFACE, PH_FD, TYPE_BOOL, OFUNC_OFFSET_MASKS, XIO_OFFSETOF(para.interface.iff_opts), XIO_SIZEOF(para.interface.iff_opts), IFF_LOOPBACK }; +const struct optdesc opt_iff_pointopoint = { "iff-pointopoint", "pointopoint",OPT_IFF_POINTOPOINT, GROUP_INTERFACE, PH_FD, TYPE_BOOL, OFUNC_OFFSET_MASKS, XIO_OFFSETOF(para.interface.iff_opts), XIO_SIZEOF(para.interface.iff_opts), IFF_POINTOPOINT }; +const struct optdesc opt_iff_notrailers = { "iff-notrailers", "notrailers", OPT_IFF_NOTRAILERS, GROUP_INTERFACE, PH_FD, TYPE_BOOL, OFUNC_OFFSET_MASKS, XIO_OFFSETOF(para.interface.iff_opts), XIO_SIZEOF(para.interface.iff_opts), IFF_NOTRAILERS }; +const struct optdesc opt_iff_running = { "iff-running", "running", OPT_IFF_RUNNING, GROUP_INTERFACE, PH_FD, TYPE_BOOL, OFUNC_OFFSET_MASKS, XIO_OFFSETOF(para.interface.iff_opts), XIO_SIZEOF(para.interface.iff_opts), IFF_RUNNING }; +const struct optdesc opt_iff_noarp = { "iff-noarp", "noarp", OPT_IFF_NOARP, GROUP_INTERFACE, PH_FD, TYPE_BOOL, OFUNC_OFFSET_MASKS, XIO_OFFSETOF(para.interface.iff_opts), XIO_SIZEOF(para.interface.iff_opts), IFF_NOARP }; +const struct optdesc opt_iff_promisc = { "iff-promisc", "promisc", OPT_IFF_PROMISC, GROUP_INTERFACE, PH_FD, TYPE_BOOL, OFUNC_OFFSET_MASKS, XIO_OFFSETOF(para.interface.iff_opts), XIO_SIZEOF(para.interface.iff_opts), IFF_PROMISC }; +const struct optdesc opt_iff_allmulti = { "iff-allmulti", "allmulti", OPT_IFF_ALLMULTI, GROUP_INTERFACE, PH_FD, TYPE_BOOL, OFUNC_OFFSET_MASKS, XIO_OFFSETOF(para.interface.iff_opts), XIO_SIZEOF(para.interface.iff_opts), IFF_ALLMULTI }; +#ifdef IFF_MASTER +const struct optdesc opt_iff_master = { "iff-master", "master", OPT_IFF_MASTER, GROUP_INTERFACE, PH_FD, TYPE_BOOL, OFUNC_OFFSET_MASKS, XIO_OFFSETOF(para.interface.iff_opts), XIO_SIZEOF(para.interface.iff_opts), IFF_MASTER }; +#endif +#ifdef IFF_SLAVE +const struct optdesc opt_iff_slave = { "iff-slave", "slave", OPT_IFF_SLAVE, GROUP_INTERFACE, PH_FD, TYPE_BOOL, OFUNC_OFFSET_MASKS, XIO_OFFSETOF(para.interface.iff_opts), XIO_SIZEOF(para.interface.iff_opts), IFF_SLAVE }; +#endif +const struct optdesc opt_iff_multicast = { "iff-multicast", NULL, OPT_IFF_MULTICAST, GROUP_INTERFACE, PH_FD, TYPE_BOOL, OFUNC_OFFSET_MASKS, XIO_OFFSETOF(para.interface.iff_opts), XIO_SIZEOF(para.interface.iff_opts), IFF_MULTICAST }; +#ifdef IFF_PORTSEL +const struct optdesc opt_iff_portsel = { "iff-portsel", "portsel", OPT_IFF_PORTSEL, GROUP_INTERFACE, PH_FD, TYPE_BOOL, OFUNC_OFFSET_MASKS, XIO_OFFSETOF(para.interface.iff_opts), XIO_SIZEOF(para.interface.iff_opts), IFF_PORTSEL }; +#endif +#ifdef IFF_AUTOMEDIA +const struct optdesc opt_iff_automedia = { "iff-automedia", "automedia", OPT_IFF_AUTOMEDIA, GROUP_INTERFACE, PH_FD, TYPE_BOOL, OFUNC_OFFSET_MASKS, XIO_OFFSETOF(para.interface.iff_opts), XIO_SIZEOF(para.interface.iff_opts), IFF_AUTOMEDIA }; +#endif +/*const struct optdesc opt_iff_dynamic = { "iff-dynamic", "dynamic", OPT_IFF_DYNAMIC, GROUP_INTERFACE, PH_FD, TYPE_BOOL, OFUNC_OFFSET_MASKS, XIO_OFFSETOF(para.interface.iff_opts), XIO_SIZEOF(short), IFF_DYNAMIC };*/ +#if LATER +const struct optdesc opt_route = { "route", NULL, OPT_ROUTE, GROUP_INTERFACE, PH_INIT, TYPE_STRING, OFUNC_SPEC }; +#endif + +#if WITH_INTERFACE +const struct addrdesc xioaddr_interface = { "INTERFACE", 3, xioopen_interface, GROUP_FD|GROUP_SOCKET|GROUP_INTERFACE, PF_PACKET, 0, 0 HELP(":") }; +#endif /* WITH_INTERFACE */ static @@ -34,13 +66,14 @@ int _xioopen_interface(const char *ifname, bool needbind = false; char *bindstring = NULL; struct sockaddr_ll sall = { 0 }; + int rc; if (ifindex(ifname, &ifidx, -1) < 0) { Error1("unknown interface \"%s\"", ifname); ifidx = 0; /* desparate attempt to continue */ } - xfd->howtoend = END_SHUTDOWN; + xfd->howtoend = END_INTERFACE; retropt_int(opts, OPT_SO_TYPE, &socktype); retropt_socket_pf(opts, &pf); @@ -67,9 +100,25 @@ int _xioopen_interface(const char *ifname, needbind = true; xfd->peersa = (union sockaddr_union)us; - return + rc = _xioopen_dgram_sendto(needbind?&us:NULL, uslen, opts, xioflags, xfd, groups, pf, socktype, 0, 0); + if (rc < 0) + return rc; + + strncpy(xfd->para.interface.name, ifname, IFNAMSIZ); + _xiointerface_get_iff(xfd->fd, ifname, &xfd->para.interface.save_iff); + _xiointerface_apply_iff(xfd->fd, ifname, xfd->para.interface.iff_opts); + +#ifdef PACKET_IGNORE_OUTGOING + /* Raw socket may even provide packets that are outbound - we are not + interested in these and disable this "feature" in kernel if possible */ + if (Setsockopt(xfd->fd, SOL_PACKET, PACKET_IGNORE_OUTGOING, &one, sizeof(one)) < 0) { + Warn2("setsockopt(%d, SOL_PACKET, PACKET_IGNORE_OUTGOING, {1}): %s", + xfd->fd, strerror(errno)); + } +#endif + return 0; } static @@ -102,4 +151,80 @@ int xioopen_interface(int argc, const char *argv[], struct opt *opts, return STAT_OK; } -#endif /* WITH_INTERFACE */ + +/* Retrieves the interface flags related to sockfd */ +int _xiointerface_get_iff( + int sockfd, + const char *name, + short *save_iff) +{ + struct ifreq ifr; + + memset(&ifr, 0, sizeof(ifr)); + strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); + if (Ioctl(sockfd, SIOCGIFFLAGS, &ifr) < 0) { + Error3("ioctl(%d, SIOCGIFFLAGS, {\"%s\"}: %s", + sockfd, ifr.ifr_name, strerror(errno)); + } + *save_iff = ifr.ifr_flags; + return 0; +} + +/* Applies the interface flags to the socket FD. + Used by INTERFACE and TUN +*/ +int _xiointerface_set_iff( + int sockfd, + const char *name, + short new_iff) +{ + struct ifreq ifr; + + memset(&ifr, 0, sizeof(ifr)); + strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); + if (Ioctl(sockfd, SIOCGIFFLAGS, &ifr) < 0) { + Error3("ioctl(%d, SIOCGIFFLAGS, {\"%s\"}: %s", + sockfd, ifr.ifr_name, strerror(errno)); + } + ifr.ifr_flags = new_iff; + if (Ioctl(sockfd, SIOCSIFFLAGS, &ifr) < 0) { + Error4("ioctl(%d, SIOCSIFFLAGS, {\"%s\", %hd}: %s", + sockfd, ifr.ifr_name, ifr.ifr_flags, strerror(errno)); + } + return 0; +} + +/* Applies the interface flags to the socket FD + Used by INTERFACE and TUN + */ +int _xiointerface_apply_iff( + int sockfd, + const char *name, + short iff_opts[2]) +{ + struct ifreq ifr; + + memset(&ifr, 0, sizeof(ifr)); + strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); + if (Ioctl(sockfd, SIOCGIFFLAGS, &ifr) < 0) { + Error3("ioctl(%d, SIOCGIFFLAGS, {\"%s\"}: %s", + sockfd, ifr.ifr_name, strerror(errno)); + } + Debug2("\"%s\": system set flags: 0x%hx", ifr.ifr_name, ifr.ifr_flags); + ifr.ifr_flags |= iff_opts[0]; + ifr.ifr_flags &= ~iff_opts[1]; + Debug2("\"%s\": xio merged flags: 0x%hx", ifr.ifr_name, ifr.ifr_flags); + if (Ioctl(sockfd, SIOCSIFFLAGS, &ifr) < 0) { + Error4("ioctl(%d, SIOCSIFFLAGS, {\"%s\", %hd}: %s", + sockfd, ifr.ifr_name, ifr.ifr_flags, strerror(errno)); + } + ifr.ifr_flags = 0; + if (Ioctl(sockfd, SIOCGIFFLAGS, &ifr) < 0) { + Error3("ioctl(%d, SIOCGIFFLAGS, {\"%s\"}: %s", + sockfd, ifr.ifr_name, strerror(errno)); + } + Debug2("\"%s\": resulting flags: 0x%hx", ifr.ifr_name, ifr.ifr_flags); + return 0; +} + +#endif /* _WITH_INTERFACE */ diff --git a/xio-interface.h b/xio-interface.h index 286341b..aafd5e5 100644 --- a/xio-interface.h +++ b/xio-interface.h @@ -7,4 +7,29 @@ extern const struct addrdesc xioaddr_interface; +extern const struct optdesc opt_interface_addr; +extern const struct optdesc opt_interface_netmask; +extern const struct optdesc opt_iff_up; +extern const struct optdesc opt_iff_broadcast; +extern const struct optdesc opt_iff_debug; +extern const struct optdesc opt_iff_loopback; +extern const struct optdesc opt_iff_pointopoint; +extern const struct optdesc opt_iff_notrailers; +extern const struct optdesc opt_iff_running; +extern const struct optdesc opt_iff_noarp; +extern const struct optdesc opt_iff_promisc; +extern const struct optdesc opt_iff_allmulti; +extern const struct optdesc opt_iff_master; +extern const struct optdesc opt_iff_slave; +extern const struct optdesc opt_iff_multicast; +extern const struct optdesc opt_iff_portsel; +extern const struct optdesc opt_iff_automedia; +/*extern const struct optdesc opt_iff_dynamic;*/ + +extern int xiolog_ancillary_packet(struct single *sfd, struct cmsghdr *cmsg, int *num, char *typbuff, int typlen, char *nambuff, int namlen, char *envbuff, int envlen, char *valbuff, int vallen); + +extern int _xiointerface_get_iff(int sockfd, const char *name, short *save_iff); +extern int _xiointerface_set_iff(int sockfd, const char *name, short new_iff); +extern int _xiointerface_apply_iff(int sockfd, const char *name, short iff_opts[2]); + #endif /* !defined(__xio_interface_h_included) */ diff --git a/xio-socket.c b/xio-socket.c index 2d0c9f8..4497c1e 100644 --- a/xio-socket.c +++ b/xio-socket.c @@ -1055,6 +1055,7 @@ int _xioopen_dgram_sendto(/* them is already in xfd->peersa */ applyopts_offset(xfd, opts); applyopts_single(xfd, opts, PH_PASTSOCKET); applyopts(xfd->fd, opts, PH_PASTSOCKET); + applyopts_single(xfd, opts, PH_FD); applyopts(xfd->fd, opts, PH_FD); applyopts_cloexec(xfd->fd, opts); diff --git a/xio-tun.c b/xio-tun.c index b3d41e2..707331e 100644 --- a/xio-tun.c +++ b/xio-tun.c @@ -11,40 +11,21 @@ #include "xio-named.h" #include "xio-socket.h" #include "xio-ip.h" +#include "xio-interface.h" #include "xio-tun.h" static int xioopen_tun(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *fd, groups_t groups, int dummy1, int dummy2, int dummy3); -/****** TUN addresses ******/ +/****** TUN options ******/ const struct optdesc opt_tun_device = { "tun-device", NULL, OPT_TUN_DEVICE, GROUP_TUN, PH_OPEN, TYPE_FILENAME, OFUNC_SPEC }; const struct optdesc opt_tun_name = { "tun-name", NULL, OPT_TUN_NAME, GROUP_INTERFACE, PH_FD, TYPE_STRING, OFUNC_SPEC }; const struct optdesc opt_tun_type = { "tun-type", NULL, OPT_TUN_TYPE, GROUP_INTERFACE, PH_FD, TYPE_STRING, OFUNC_SPEC }; -const struct optdesc opt_iff_no_pi = { "iff-no-pi", "no-pi", OPT_IFF_NO_PI, GROUP_TUN, PH_FD, TYPE_BOOL, OFUNC_SPEC }; -/*0 const struct optdesc opt_interface_addr = { "interface-addr", "address", OPT_INTERFACE_ADDR, GROUP_INTERFACE, PH_FD, TYPE_STRING, OFUNC_SPEC };*/ -/*0 const struct optdesc opt_interface_netmask = { "interface-netmask", "netmask", OPT_INTERFACE_NETMASK, GROUP_INTERFACE, PH_FD, TYPE_STRING, OFUNC_SPEC };*/ -const struct optdesc opt_iff_up = { "iff-up", "up", OPT_IFF_UP, GROUP_INTERFACE, PH_FD, TYPE_BOOL, OFUNC_OFFSET_MASKS, XIO_OFFSETOF(para.tun.iff_opts), XIO_SIZEOF(para.tun.iff_opts), IFF_UP }; -const struct optdesc opt_iff_broadcast = { "iff-broadcast", NULL, OPT_IFF_BROADCAST, GROUP_INTERFACE, PH_FD, TYPE_BOOL, OFUNC_OFFSET_MASKS, XIO_OFFSETOF(para.tun.iff_opts), XIO_SIZEOF(para.tun.iff_opts), IFF_BROADCAST }; -const struct optdesc opt_iff_debug = { "iff-debug" , NULL, OPT_IFF_DEBUG, GROUP_INTERFACE, PH_FD, TYPE_BOOL, OFUNC_OFFSET_MASKS, XIO_OFFSETOF(para.tun.iff_opts), XIO_SIZEOF(para.tun.iff_opts), IFF_DEBUG }; -const struct optdesc opt_iff_loopback = { "iff-loopback" , "loopback", OPT_IFF_LOOPBACK, GROUP_INTERFACE, PH_FD, TYPE_BOOL, OFUNC_OFFSET_MASKS, XIO_OFFSETOF(para.tun.iff_opts), XIO_SIZEOF(para.tun.iff_opts), IFF_LOOPBACK }; -const struct optdesc opt_iff_pointopoint = { "iff-pointopoint", "pointopoint",OPT_IFF_POINTOPOINT, GROUP_INTERFACE, PH_FD, TYPE_BOOL, OFUNC_OFFSET_MASKS, XIO_OFFSETOF(para.tun.iff_opts), XIO_SIZEOF(para.tun.iff_opts), IFF_POINTOPOINT }; -const struct optdesc opt_iff_notrailers = { "iff-notrailers", "notrailers", OPT_IFF_NOTRAILERS, GROUP_INTERFACE, PH_FD, TYPE_BOOL, OFUNC_OFFSET_MASKS, XIO_OFFSETOF(para.tun.iff_opts), XIO_SIZEOF(para.tun.iff_opts), IFF_NOTRAILERS }; -const struct optdesc opt_iff_running = { "iff-running", "running", OPT_IFF_RUNNING, GROUP_INTERFACE, PH_FD, TYPE_BOOL, OFUNC_OFFSET_MASKS, XIO_OFFSETOF(para.tun.iff_opts), XIO_SIZEOF(para.tun.iff_opts), IFF_RUNNING }; -const struct optdesc opt_iff_noarp = { "iff-noarp", "noarp", OPT_IFF_NOARP, GROUP_INTERFACE, PH_FD, TYPE_BOOL, OFUNC_OFFSET_MASKS, XIO_OFFSETOF(para.tun.iff_opts), XIO_SIZEOF(para.tun.iff_opts), IFF_NOARP }; -const struct optdesc opt_iff_promisc = { "iff-promisc", "promisc", OPT_IFF_PROMISC, GROUP_INTERFACE, PH_FD, TYPE_BOOL, OFUNC_OFFSET_MASKS, XIO_OFFSETOF(para.tun.iff_opts), XIO_SIZEOF(para.tun.iff_opts), IFF_PROMISC }; -const struct optdesc opt_iff_allmulti = { "iff-allmulti", "allmulti", OPT_IFF_ALLMULTI, GROUP_INTERFACE, PH_FD, TYPE_BOOL, OFUNC_OFFSET_MASKS, XIO_OFFSETOF(para.tun.iff_opts), XIO_SIZEOF(para.tun.iff_opts), IFF_ALLMULTI }; -const struct optdesc opt_iff_master = { "iff-master", "master", OPT_IFF_MASTER, GROUP_INTERFACE, PH_FD, TYPE_BOOL, OFUNC_OFFSET_MASKS, XIO_OFFSETOF(para.tun.iff_opts), XIO_SIZEOF(para.tun.iff_opts), IFF_MASTER }; -const struct optdesc opt_iff_slave = { "iff-slave", "slave", OPT_IFF_SLAVE, GROUP_INTERFACE, PH_FD, TYPE_BOOL, OFUNC_OFFSET_MASKS, XIO_OFFSETOF(para.tun.iff_opts), XIO_SIZEOF(para.tun.iff_opts), IFF_SLAVE }; -const struct optdesc opt_iff_multicast = { "iff-multicast", NULL, OPT_IFF_MULTICAST, GROUP_INTERFACE, PH_FD, TYPE_BOOL, OFUNC_OFFSET_MASKS, XIO_OFFSETOF(para.tun.iff_opts), XIO_SIZEOF(para.tun.iff_opts), IFF_MULTICAST }; -const struct optdesc opt_iff_portsel = { "iff-portsel", "portsel", OPT_IFF_PORTSEL, GROUP_INTERFACE, PH_FD, TYPE_BOOL, OFUNC_OFFSET_MASKS, XIO_OFFSETOF(para.tun.iff_opts), XIO_SIZEOF(para.tun.iff_opts), IFF_PORTSEL }; -const struct optdesc opt_iff_automedia = { "iff-automedia", "automedia", OPT_IFF_AUTOMEDIA, GROUP_INTERFACE, PH_FD, TYPE_BOOL, OFUNC_OFFSET_MASKS, XIO_OFFSETOF(para.tun.iff_opts), XIO_SIZEOF(para.tun.iff_opts), IFF_AUTOMEDIA }; -/*const struct optdesc opt_iff_dynamic = { "iff-dynamic", "dynamic", OPT_IFF_DYNAMIC, GROUP_INTERFACE, PH_FD, TYPE_BOOL, OFUNC_OFFSET_MASKS, XIO_OFFSETOF(para.tun.iff_opts), XIO_SIZEOF(short), IFF_DYNAMIC };*/ -#if LATER -const struct optdesc opt_route = { "route", NULL, OPT_ROUTE, GROUP_INTERFACE, PH_INIT, TYPE_STRING, OFUNC_SPEC }; -#endif +const struct optdesc opt_iff_no_pi = { "iff-no-pi", "no-pi", OPT_IFF_NO_PI, GROUP_TUN, PH_FD, TYPE_BOOL, OFUNC_SPEC }; -const struct addrdesc xioaddr_tun = { "TUN", 3, xioopen_tun, GROUP_FD|GROUP_CHR|GROUP_NAMED|GROUP_OPEN|GROUP_TUN, 0, 0, 0 HELP("[:/]") }; +/****** TUN addresses ******/ +const struct addrdesc xioaddr_tun = { "TUN", 3, xioopen_tun, GROUP_FD|GROUP_CHR|GROUP_OPEN|GROUP_TUN, 0, 0, 0 HELP("[:/]") }; /* "if-name"=tun3 // "route"=address/netmask // "ip6-route"=address/netmask @@ -103,7 +84,7 @@ static int xioopen_tun(int argc, const char *argv[], struct opt *opts, int xiofl xfd->stream.fd = result; /* prepare configuration of the new network interface */ - memset(&ifr, 0,sizeof(ifr)); + memset(&ifr, 0, sizeof(ifr)); if (retropt_string(opts, OPT_TUN_NAME, &tunname) == 0) { strncpy(ifr.ifr_name, tunname, IFNAMSIZ); /* ok */ @@ -136,6 +117,7 @@ static int xioopen_tun(int argc, const char *argv[], struct opt *opts, int xiofl xfd->stream.fd, ifr.ifr_name, strerror(errno)); Close(xfd->stream.fd); } + Notice1("TUN: new device \"%s\"", ifr.ifr_name); /*===================== setting interface properties =====================*/ @@ -174,29 +156,8 @@ static int xioopen_tun(int argc, const char *argv[], struct opt *opts, int xiofl /*--------------------- setting interface flags --------------------------*/ applyopts_single(&xfd->stream, opts, PH_FD); - if (Ioctl(sockfd, SIOCGIFFLAGS, &ifr) < 0) { - Error3("ioctl(%d, SIOCGIFFLAGS, {\"%s\"}: %s", - sockfd, ifr.ifr_name, strerror(errno)); - } - Debug2("\"%s\": system set flags: 0x%hx", ifr.ifr_name, ifr.ifr_flags); - ifr.ifr_flags |= xfd->stream.para.tun.iff_opts[0]; - ifr.ifr_flags &= ~xfd->stream.para.tun.iff_opts[1]; - Debug2("\"%s\": xio merged flags: 0x%hx", ifr.ifr_name, ifr.ifr_flags); - if (Ioctl(sockfd, SIOCSIFFLAGS, &ifr) < 0) { - Error4("ioctl(%d, SIOCSIFFLAGS, {\"%s\", %hd}: %s", - sockfd, ifr.ifr_name, ifr.ifr_flags, strerror(errno)); - } - ifr.ifr_flags = 0; - if (Ioctl(sockfd, SIOCGIFFLAGS, &ifr) < 0) { - Error3("ioctl(%d, SIOCGIFFLAGS, {\"%s\"}: %s", - sockfd, ifr.ifr_name, strerror(errno)); - } - Debug2("\"%s\": resulting flags: 0x%hx", ifr.ifr_name, ifr.ifr_flags); + _xiointerface_apply_iff(sockfd, ifr.ifr_name, xfd->stream.para.interface.iff_opts); - -#if LATER - applyopts_named(tundevice, opts, PH_FD); -#endif applyopts(xfd->stream.fd, opts, PH_FD); applyopts_cloexec(xfd->stream.fd, opts); diff --git a/xio-tun.h b/xio-tun.h index 5f73113..bbb440d 100644 --- a/xio-tun.h +++ b/xio-tun.h @@ -9,24 +9,6 @@ extern const struct optdesc opt_tun_device; extern const struct optdesc opt_tun_name; extern const struct optdesc opt_tun_type; extern const struct optdesc opt_iff_no_pi; -extern const struct optdesc opt_interface_addr; -extern const struct optdesc opt_interface_netmask; -extern const struct optdesc opt_iff_up; -extern const struct optdesc opt_iff_broadcast; -extern const struct optdesc opt_iff_debug; -extern const struct optdesc opt_iff_loopback; -extern const struct optdesc opt_iff_pointopoint; -extern const struct optdesc opt_iff_notrailers; -extern const struct optdesc opt_iff_running; -extern const struct optdesc opt_iff_noarp; -extern const struct optdesc opt_iff_promisc; -extern const struct optdesc opt_iff_allmulti; -extern const struct optdesc opt_iff_master; -extern const struct optdesc opt_iff_slave; -extern const struct optdesc opt_iff_multicast; -extern const struct optdesc opt_iff_portsel; -extern const struct optdesc opt_iff_automedia; -/*extern const struct optdesc opt_iff_dynamic;*/ extern const struct addrdesc xioaddr_tun; diff --git a/xio.h b/xio.h index 2660db6..71f82e3 100644 --- a/xio.h +++ b/xio.h @@ -192,7 +192,8 @@ typedef struct single { END_SHUTDOWN, /* shutdown() */ END_KILL, /* has subprocess */ END_CLOSE_KILL, /* first close fd, then kill subprocess */ - END_SHUTDOWN_KILL /* first shutdown fd, then kill subprocess */ + END_SHUTDOWN_KILL,/* first shutdown fd, then kill subprocess */ + END_INTERFACE /* restore interface flags, then close fd */ } howtoend; #if _WITH_SOCKET union sockaddr_union peersa; @@ -276,11 +277,13 @@ typedef struct single { #endif } openssl; #endif /* WITH_OPENSSL */ -#if WITH_TUN +#if _WITH_INTERFACE struct { + char name[IFNAMSIZ]; /* name of interface */ + short save_iff; /* for restoring old settings on exit */ short iff_opts[2]; /* ifr flags, using OFUNC_OFFSET_MASKS */ - } tun; -#endif /* WITH_TUN */ + } interface; +#endif /* _WITH_INTERFACE */ } para; #if WITH_STATS unsigned long long blocks_read; diff --git a/xioclose.c b/xioclose.c index 3f87119..3bbfca7 100644 --- a/xioclose.c +++ b/xioclose.c @@ -10,6 +10,7 @@ #include "xiolockfile.h" #include "xio-termios.h" +#include "xio-interface.h" /* close the xio fd; must be valid and "simple" (not dual) */ @@ -77,6 +78,15 @@ int xioclose1(struct single *pipe) { Info3("shutdown(%d, %d): %s", pipe->fd, 2, strerror(errno)); } break; #endif /* _WITH_SOCKET */ +#if WITH_INTERFACE + case END_INTERFACE: + { + _xiointerface_set_iff(pipe->fd, pipe->para.interface.name, pipe->para.interface.save_iff); + if (Close(pipe->fd) < 0) { + Info2("close(%d): %s", pipe->fd, strerror(errno)); } break; + } + break; +#endif /* WITH_INTERFACE */ case END_NONE: default: break; } } diff --git a/xioconfig.h b/xioconfig.h index e339d3a..1194a2f 100644 --- a/xioconfig.h +++ b/xioconfig.h @@ -67,7 +67,13 @@ # undef WITH_LIBWRAP #endif -#if WITH_GENERICSOCKET || WITH_TUN +#if WITH_INTERFACE || WITH_TUN +# define _WITH_INTERFACE 1 +#else +# define _WITH_INTERFACE 0 +#endif + +#if WITH_GENERICSOCKET || _WITH_INTERFACE # define _WITH_SOCKET 1 #endif @@ -79,11 +85,11 @@ # define _WITH_IP6 1 #endif -#if WITH_NAMED || WITH_TUN +#if WITH_NAMED # define _WITH_NAMED 1 #endif -#if WITH_FILE || WITH_TUN +#if WITH_FILE # define _WITH_FILE 1 #endif diff --git a/xioopts.c b/xioopts.c index 67017ba..e11aa6c 100644 --- a/xioopts.c +++ b/xioopts.c @@ -125,6 +125,12 @@ bool xioopts_ignoregroups; # define IF_OPENSSL(a,b) #endif +#if WITH_INTERFACE +# define IF_INTERFACE(a,b) {a,b}, +#else +# define IF_INTERFACE(a,b) +#endif + #if WITH_TUN # define IF_TUN(a,b) {a,b}, #else @@ -167,7 +173,7 @@ const struct optname optionnames[] = { #if defined(HAVE_STRUCT_IP_MREQ_SOURCE) && defined(IP_ADD_SOURCE_MEMBERSHIP) IF_IP ("add-source-membership", &opt_ip_add_source_membership) #endif - IF_TUN ("allmulti", &opt_iff_allmulti) + IF_INTERFACE("allmulti", &opt_iff_allmulti) #if WITH_LIBWRAP && defined(HAVE_HOSTS_ALLOW_TABLE) IF_IPAPP ("allow-table", &opt_tcpwrap_hosts_allow_table) #endif @@ -185,7 +191,9 @@ const struct optname optionnames[] = { #ifdef IPV6_AUTHHDR IF_IP6 ("authhdr", &opt_ipv6_authhdr) #endif - IF_TUN ("automedia", &opt_iff_automedia) +#ifdef IFF_AUTOMEDIA + IF_INTERFACE("automedia", &opt_iff_automedia) +#endif #ifdef CBAUD IF_TERMIOS("b0", &opt_b0) #ifdef B1000000 @@ -629,23 +637,31 @@ const struct optname optionnames[] = { #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_INTERFACE("iff-allmulti", &opt_iff_allmulti) +#ifdef IFF_AUTOMEDIA + IF_INTERFACE("iff-automedia", &opt_iff_automedia) +#endif + IF_INTERFACE("iff-broadcast", &opt_iff_broadcast) + IF_INTERFACE("iff-debug", &opt_iff_debug) + /*IF_INTERFACE("iff-dynamic", &opt_iff_dynamic)*/ + IF_INTERFACE("iff-loopback", &opt_iff_loopback) +#ifdef IFF_MASTER + IF_INTERFACE("iff-master", &opt_iff_master) +#endif + IF_INTERFACE("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_INTERFACE("iff-noarp", &opt_iff_noarp) + IF_INTERFACE("iff-notrailers", &opt_iff_notrailers) + IF_INTERFACE("iff-pointopoint", &opt_iff_pointopoint) +#ifdef IFF_PORTSEL + IF_INTERFACE("iff-portsel", &opt_iff_portsel) +#endif + IF_INTERFACE("iff-promisc", &opt_iff_promisc) + IF_INTERFACE("iff-running", &opt_iff_running) +#ifdef IFF_SLAVE + IF_INTERFACE("iff-slave", &opt_iff_slave) +#endif + IF_INTERFACE("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: */ @@ -914,7 +930,7 @@ const struct optname optionnames[] = { IF_ANY ("lockw", &opt_flock_ex_nb) /* BSD, fallback */ #endif IF_EXEC ("login", &opt_dash) - IF_TUN ("loopback", &opt_iff_loopback) + IF_INTERFACE("loopback", &opt_iff_loopback) IF_IPAPP ("lowport", &opt_lowport) #if HAVE_LSEEK64 IF_ANY ("lseek", &opt_lseek64_set) @@ -931,7 +947,9 @@ const struct optname optionnames[] = { IF_ANY ("lseek64-end", &opt_lseek64_end) IF_ANY ("lseek64-set", &opt_lseek64_set) #endif - IF_TUN ("master", &opt_iff_master) +#ifdef IFF_MASTER + IF_INTERFACE("master", &opt_iff_master) +#endif IF_LISTEN ("max-children", &opt_max_children) #if HAVE_SSL_set_max_proto_version || defined(SSL_set_max_proto_version) IF_OPENSSL("max-version", &opt_openssl_max_proto_version) @@ -971,7 +989,7 @@ const struct optname optionnames[] = { #ifdef IP_MTU_DISCOVER IF_IP ("mtudiscover", &opt_ip_mtu_discover) #endif - IF_TUN ("multicast", &opt_iff_multicast) + IF_INTERFACE("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) @@ -999,7 +1017,7 @@ const struct optname optionnames[] = { #if defined(HAVE_SSL_set_tlsext_host_name) || defined(SSL_set_tlsext_host_name) IF_OPENSSL("no-sni", &opt_openssl_no_sni) #endif - IF_TUN ("noarp", &opt_iff_noarp) + IF_INTERFACE("noarp", &opt_iff_noarp) #ifdef O_NOATIME IF_OPEN ("noatime", &opt_o_noatime) #endif @@ -1038,7 +1056,7 @@ const struct optname optionnames[] = { #if defined(HAVE_SSL_set_tlsext_host_name) || defined(SSL_set_tlsext_host_name) IF_OPENSSL("nosni", &opt_openssl_no_sni) #endif - IF_TUN ("notrailers", &opt_iff_notrailers) + IF_INTERFACE("notrailers", &opt_iff_notrailers) #ifdef O_NSHARE IF_OPEN ("nshare", &opt_o_nshare) #endif @@ -1251,12 +1269,14 @@ const struct optname optionnames[] = { IF_IP ("pktoptions", &opt_ip_pktoptions) IF_IP ("pktopts", &opt_ip_pktoptions) #endif - IF_TUN ("pointopoint", &opt_iff_pointopoint) + IF_INTERFACE("pointopoint", &opt_iff_pointopoint) #ifdef I_POP IF_ANY ("pop-all", &opt_streams_i_pop_all) #endif /*IF_IPAPP("port", &opt_port)*/ - IF_TUN ("portsel", &opt_iff_portsel) +#ifdef IFF_PORTSEL + IF_INTERFACE("portsel", &opt_iff_portsel) +#endif #if HAVE_RESOLV_H && WITH_RES_PRIMARY IF_IP ("primary", &opt_res_primary) #endif @@ -1266,7 +1286,7 @@ const struct optname optionnames[] = { #ifdef O_PRIV IF_OPEN ("priv", &opt_o_priv) #endif - IF_TUN ("promisc", &opt_iff_promisc) + IF_INTERFACE("promisc", &opt_iff_promisc) IF_READLINE("prompt", &opt_prompt) #ifdef SO_PROTOTYPE IF_SOCKET ("protocol", &opt_so_prototype) @@ -1401,7 +1421,7 @@ const struct optname optionnames[] = { #ifdef IPV6_RTHDR IF_IP6 ("rthdr", &opt_ipv6_rthdr) #endif - IF_TUN ("running", &opt_iff_running) + IF_INTERFACE("running", &opt_iff_running) #ifdef TCP_SACK_DISABLE IF_TCP ("sack-disable", &opt_tcp_sack_disable) #endif @@ -1484,7 +1504,9 @@ const struct optname optionnames[] = { IF_SOCKET ("siocspgrp", &opt_siocspgrp) #endif IF_PTY ("sitout-eio", &opt_sitout_eio) - IF_TUN ("slave", &opt_iff_slave) +#ifdef IFF_SLAVE + IF_INTERFACE("slave", &opt_iff_slave) +#endif IF_SOCKET ("sndbuf", &opt_so_sndbuf) IF_SOCKET ("sndbuf-late", &opt_so_sndbuf_late) #ifdef SO_SNDLOWAT @@ -1797,7 +1819,7 @@ const struct optname optionnames[] = { #if WITH_FS && defined(FS_UNRM_FL) IF_ANY ("unrm", &opt_fs_unrm) #endif - IF_TUN ("up", &opt_iff_up) + IF_INTERFACE("up", &opt_iff_up) #ifdef SO_USE_IFBUFS IF_SOCKET ("use-ifbufs", &opt_so_use_ifbufs) IF_SOCKET ("useifbufs", &opt_so_use_ifbufs) @@ -3745,7 +3767,7 @@ int applyopts(int fd, struct opt *opts, enum e_phase phase) { /*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", + Error1("applyopts(): internal error: option \"%s\" does not apply", opt->desc->defname); opt->desc = ODESC_ERROR; ++opt;