From de910892f2798c5184c1234fe21afd83a9d56f88 Mon Sep 17 00:00:00 2001 From: Gerhard Rieger Date: Sat, 20 Sep 2008 23:37:56 +0200 Subject: [PATCH] new address "interface" for transparent network interface handling --- CHANGES | 4 ++ Makefile.in | 12 ++++-- VERSION | 2 +- config.h.in | 9 ++++- configure.in | 23 +++++++++++ doc/socat.yo | 29 +++++++++++-- socat.c | 5 +++ sysincludes.h | 8 +++- sysutils.c | 31 +++++++++----- sysutils.h | 6 +-- test.sh | 55 +++++++++++++++++++++++++ xio-interface.c | 105 ++++++++++++++++++++++++++++++++++++++++++++++++ xio-interface.h | 10 +++++ xio-socket.c | 4 +- xiomodes.h | 3 +- xioopen.c | 8 +++- xioopts.c | 8 ++-- xioread.c | 9 +++++ 18 files changed, 300 insertions(+), 31 deletions(-) create mode 100644 xio-interface.c create mode 100644 xio-interface.h diff --git a/CHANGES b/CHANGES index e78e07a..c783fb0 100644 --- a/CHANGES +++ b/CHANGES @@ -1,4 +1,8 @@ +new features: + new address "interface" for transparent network interface handling + (suggested by Stuart Nicholson) + corrections: some raw IP and UNIX datagram modes failed on BSD systems diff --git a/Makefile.in b/Makefile.in index 583985b..aabc06e 100644 --- a/Makefile.in +++ b/Makefile.in @@ -44,7 +44,9 @@ XIOSRCS = xioinitialize.c xiohelp.c xioparam.c xiodiag.c xioopen.c xioopts.c \ xiolayer.c xioshutdown.c xioclose.c xioexit.c \ xio-process.c xio-fd.c xio-fdnum.c xio-stdio.c xio-pipe.c \ xio-gopen.c xio-creat.c xio-file.c xio-named.c \ - xio-socket.c xio-listen.c xio-unix.c xio-ip.c xio-ip4.c xio-ip6.c xio-ipapp.c xio-tcp.c xio-socks.c xio-proxy.c xio-udp.c \ + xio-socket.c xio-interface.c xio-listen.c xio-unix.c \ + xio-ip.c xio-ip4.c xio-ip6.c xio-ipapp.c xio-tcp.c \ + xio-socks.c xio-proxy.c xio-udp.c \ xio-rawip.c \ xio-progcall.c xio-exec.c xio-system.c xio-termios.c xio-readline.c \ xio-pty.c xio-openssl.c \ @@ -59,9 +61,11 @@ PROGS = socat procan filan HFILES = sycls.h sslcls.h error.h dalan.h procan.h filan.h hostan.h sysincludes.h xio.h xioopen.h sysutils.h utils.h nestlex.h compat.h \ xioconfig.h mytypes.h xioopts.h xiodiag.h xiohelp.h xiosysincludes.h \ xiomodes.h xiolayer.h xio-process.h xio-fd.h xio-fdnum.h xio-stdio.h \ - xio-named.h xio-file.h xio-creat.h xio-gopen.h xio-pipe.h xio-socket.h \ - xio-listen.h xio-unix.h xio-rawip.h xio-ip.h xio-ip4.h xio-ip6.h \ - xio-ipapp.h xio-tcp.h xio-udp.h xio-socks.h xio-proxy.h xio-progcall.h xio-exec.h \ + xio-named.h xio-file.h xio-creat.h xio-gopen.h xio-pipe.h \ + xio-socket.h xio-interface.h xio-listen.h xio-unix.h \ + xio-ip.h xio-ip4.h xio-ip6.h xio-rawip.h \ + xio-ipapp.h xio-tcp.h xio-udp.h \ + xio-socks.h xio-proxy.h xio-progcall.h xio-exec.h \ xio-system.h xio-termios.h xio-readline.h \ xio-pty.h xio-openssl.h \ xio-ascii.h xiolockfile.h xio-tcpwrap.h xio-ext2.h xio-tun.h diff --git a/VERSION b/VERSION index 9a06c88..8119a18 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -"1.6.0.1+ip4bind+recvfromfork+x64+execstderr+execspaces+cosmetics+poll+udplistencont+ignoreeofunblock" +"1.6.0.1+ip4bind+recvfromfork+x64+execstderr+execspaces+cosmetics+poll+udplistencont+ignoreeofunblock+interface" diff --git a/config.h.in b/config.h.in index 2e330da..b99d769 100644 --- a/config.h.in +++ b/config.h.in @@ -1,5 +1,5 @@ /* source: config.h.in */ -/* Copyright Gerhard Rieger 2001-2007 */ +/* Copyright Gerhard Rieger 2001-2008 */ /* Published under the GNU General Public License V.2, see file COPYING */ #ifndef __config_h_included @@ -227,6 +227,12 @@ /* Define if you have the header file. */ #undef HAVE_LINUX_IF_TUN_H +/* Define if you have the header file. */ +#undef HAVE_NETPACKET_PACKET_H + +/* Define if you have the header file. */ +#undef HAVE_NETINET_IF_ETHER_H + /* Define if you have the header file. */ #undef HAVE_SYS_UTSNAME_H @@ -456,6 +462,7 @@ #undef WITH_IP4 #undef WITH_IP6 #undef WITH_RAWIP +#undef WITH_INTERFACE #undef WITH_TCP #undef WITH_UDP #undef WITH_LISTEN diff --git a/configure.in b/configure.in index f3161ce..69a5150 100644 --- a/configure.in +++ b/configure.in @@ -196,6 +196,29 @@ AC_ARG_ENABLE(rawip, [ --disable-rawip disable raw IP support], esac], [AC_DEFINE(WITH_RAWIP) AC_MSG_RESULT(yes)]) +AC_MSG_CHECKING(whether to include raw network INTERFACE support) +AC_ARG_ENABLE(interface, [ --disable-interface disable network interface support], + [case "$enableval" in + no) AC_MSG_RESULT(no); WITH_INTERFACE= ;; + *) AC_MSG_RESULT(yes); WITH_INTERFACE=1 ;; + esac], + [AC_MSG_RESULT(yes); WITH_INTERFACE=1 ]) +if test "$WITH_INTERFACE"; then + AC_CHECK_HEADER(netpacket/packet.h, + AC_DEFINE(HAVE_NETPACKET_PACKET_H), + [WITH_INTERFACE=; + AC_MSG_WARN([include file netpacket/packet.h not found, disabling INTERFACE])]) +fi +if test "$WITH_INTERFACE"; then + AC_CHECK_HEADER(netinet/if_ether.h, + AC_DEFINE(HAVE_NETINET_IF_ETHER_H), + [WITH_INTERFACE=; + AC_MSG_WARN([include file netinet/if_ether.h not found, disabling INTERFACE])]) +fi +if test "$WITH_INTERFACE"; then + AC_DEFINE(WITH_INTERFACE) +fi + AC_MSG_CHECKING(whether to include TCP support) AC_ARG_ENABLE(tcp, [ --disable-tcp disable TCP support], [case "$enableval" in diff --git a/doc/socat.yo b/doc/socat.yo index 4befd5b..c141e11 100644 --- a/doc/socat.yo +++ b/doc/socat.yo @@ -540,6 +540,15 @@ label(ADDRESS_NAMED_PIPE)dit(bf(tt(PIPE:))) link(mode)(OPTION_MODE), link(unlink-early)(OPTION_UNLINK_EARLY)nl() See also: link(unnamed pipe)(ADDRESS_UNNAMED_PIPE) +label(ADDRESS_INTERFACE)dit(bf(tt(INTERFACE:))) + Communicate with a network connected on an interface using raw packets + including link level data. link()(TYPE_INTERFACE) is the name of + the network interface. Currently only available on Linux. + Option groups: link(FD)(GROUP_FD),link(SOCKET)(GROUP_SOCKET) nl() + Useful options: + link(pf)(OPTION_PROTOCOL_FAMILY) + link(so-type)(OPTION_SO_TYPE)nl() + See also: link(ip-recv)(ADDRESS_IP_RECV) label(ADDRESS_UNNAMED_PIPE)dit(bf(tt(PIPE))) Creates an unnamed pipe and uses it for reading and writing. It works as an echo, because everything written @@ -1585,7 +1594,7 @@ label(OPTION_SNDLOWAT)dit(bf(tt(sndlowat=))) layer will send the data to [link(int)(TYPE_INT)]. label(OPTION_SNDTIMEO)dit(bf(tt(sndtimeo=))) Sets the send timeout to seconds [link(timeval)(TYPE_TIMEVAL)]. -label(OPTION_TYPE)dit(bf(tt(type=))) +label(OPTION_SO_TYPE)dit(bf(tt(type=))) Sets the type of the socket, usually as argument to the code(socket()) or code(socketpair()) call, to [link(int)(TYPE_INT)]. Under Linux, 1 means stream oriented socket, 2 means datagram socket, and 3 @@ -1633,8 +1642,8 @@ COMMENT(label(OPTION_SIOCSPGRP)dit(bf(tt(siocspgrp=))) COMMENT(label(OPTION_USEIFBUFS)dit(bf(tt(useifbufs))) Set the code(SO_USE_IFBUFS) socket option.) label(OPTION_PROTOCOL_FAMILY)dit(bf(tt(pf=))) - Forces the use of the specified IP version. can be - something like "ip4" or "ip6". + Forces the use of the specified IP version or protocol family. can + be something like "ip4" or "ip6" or a number. enddit() startdit()enddit()nl() @@ -2433,7 +2442,8 @@ label(TYPE_INT)dit(int) "0", i.e. decimal number, octal number with leading "0", or hexadecimal number with leading "0x". The value must fit into a C int. label(TYPE_INTERFACE)dit(interface) - A string specifying the device name of a network interface, e.g. "eth0". + A string specifying the device name of a network interface + as shown by ifconfig or procan, e.g. "eth0". label(TYPE_IP_ADDRESS)dit(IP address) An IPv4 address in numbers-and-dots notation, an IPv6 address in hex notation enclosed in brackets, or a hostname that resolves to an IPv4 or an @@ -2883,6 +2893,17 @@ client and server authentication (see OpenSSL link(client)(EXAMPLE_ADDRESS_OPENSSL_CONNECT) and link(server)(EXAMPLE_ADDRESS_OPENSSL_LISTEN)). + +label(EXAMPLE_INTERFACE) +dit(bf(tt(socat PTY,link=/var/run/ppp,raw,echo=0 INTERFACE:hdlc0))) + +circumvents the problem that pppd requires a serial device and thus might not +be able to work on a synchronous line that is represented by a network device. +socat creates a PTY to make pppd happy, binds to the network interface hdlc0, +and can transfer data between both devices. Use pppd on device /var/run/ppp +then. + + enddit() diff --git a/socat.c b/socat.c index 3128ec9..40c2831 100644 --- a/socat.c +++ b/socat.c @@ -426,6 +426,11 @@ void socat_version(FILE *fd) { #else fputs(" #undef WITH_RAWIP\n", fd); #endif +#ifdef WITH_INTERFACE + fprintf(fd, " #define WITH_INTERFACE %d\n", WITH_INTERFACE); +#else + fputs(" #undef WITH_INTERFACE\n", fd); +#endif #ifdef WITH_TCP fprintf(fd, " #define WITH_TCP %d\n", WITH_TCP); #else diff --git a/sysincludes.h b/sysincludes.h index f233358..7f62497 100644 --- a/sysincludes.h +++ b/sysincludes.h @@ -1,5 +1,5 @@ /* source: sysincludes.h */ -/* Copyright Gerhard Rieger 2001-2007 */ +/* Copyright Gerhard Rieger 2001-2008 */ /* Published under the GNU General Public License V.2, see file COPYING */ #ifndef __sysincludes_h_included @@ -116,6 +116,12 @@ #if HAVE_NET_IF_H #include #endif /* HAVE_NET_IF_H */ +#if HAVE_NETPACKET_PACKET_H +#include +#endif +#if HAVE_NETINET_IF_ETHER_H +#include +#endif #if HAVE_LINUX_IF_TUN_H #include #endif diff --git a/sysutils.c b/sysutils.c index 28ccae9..d55b636 100644 --- a/sysutils.c +++ b/sysutils.c @@ -115,7 +115,7 @@ socklen_t socket_init(int af, union sockaddr_union *sa) { #if WITH_IP6 case AF_INET6: socket_in6_init(&sa->ip6); return sizeof(sa->ip6); #endif - default: Error1("socket_init(): unknown address family %d", af); + default: Info1("socket_init(): unknown address family %d", af); memset(sa, 0, sizeof(union sockaddr_union)); sa->soa.sa_family = af; return 0; @@ -436,8 +436,12 @@ int parseport(const char *portname, int ipproto) { #if WITH_IP4 || WITH_IP6 /* check the systems interfaces for ifname and return its index - or -1 if no interface with this name was found */ -int ifindexbyname(const char *ifname) { + or -1 if no interface with this name was found + The system calls require an arbitrary socket; the calling program may + provide one in anysock to avoid creation of a dummy socket. anysock must be + <0 if it does not specify a socket fd. + */ +int ifindexbyname(const char *ifname, int anysock) { /* Linux: man 7 netdevice */ /* FreeBSD: man 4 networking */ /* Solaris: man 7 if_tcp */ @@ -445,29 +449,35 @@ int ifindexbyname(const char *ifname) { #if defined(HAVE_STRUCT_IFREQ) && defined(SIOCGIFCONF) && defined(SIOCGIFINDEX) /* currently we support Linux, FreeBSD; not Solaris */ -#define IFBUFSIZ 1024 +#define IFBUFSIZ 32*sizeof(struct ifreq) /*1024*/ int s; struct ifreq ifr; if (ifname[0] == '\0') { return -1; } - if ((s = Socket(PF_INET, SOCK_DGRAM, IPPROTO_IP)) < 0) { + if (anysock >= 0) { + s = anysock; + } else if ((s = Socket(PF_INET, SOCK_DGRAM, IPPROTO_IP)) < 0) { Error1("socket(PF_INET, SOCK_DGRAM, IPPROTO_IP): %s", strerror(errno)); return -1; } strncpy(ifr.ifr_name, ifname, IFNAMSIZ); if (Ioctl(s, SIOCGIFINDEX, &ifr) < 0) { - Close(s); - Info3("ioctl(%d, SIOCGIFINDEX, {%s}): %s", + Info3("ioctl(%d, SIOCGIFINDEX, {\"%s\"}): %s", s, ifr.ifr_name, strerror(errno)); + Close(s); return -1; } Close(s); #if HAVE_STRUCT_IFREQ_IFR_INDEX + Info3("ioctl(%d, SIOCGIFINDEX, {\"%s\"}) -> { %d }", + s, ifname, ifr.ifr_index); return ifr.ifr_index; #elif HAVE_STRUCT_IFREQ_IFR_IFINDEX + Info3("ioctl(%d, SIOCGIFINDEX, {\"%s\"}) -> { %d }", + s, ifname, ifr.ifr_ifindex); return ifr.ifr_ifindex; #endif /* HAVE_STRUCT_IFREQ_IFR_IFINDEX */ @@ -477,10 +487,11 @@ int ifindexbyname(const char *ifname) { } -/* like ifindexbyname(), but allows an index number as input. +/* like ifindexbyname(), but also allows the index number as input - in this + case it does not lookup the index. writes the resulting index to *ifindex and returns 0, or returns -1 on error */ -int ifindex(const char *ifname, unsigned int *ifindex) { +int ifindex(const char *ifname, unsigned int *ifindex, int anysock) { char *endptr; long int val; @@ -493,7 +504,7 @@ int ifindex(const char *ifname, unsigned int *ifindex) { return 0; } - if ((val = ifindexbyname(ifname)) < 0) { + if ((val = ifindexbyname(ifname, anysock)) < 0) { return -1; } *ifindex = val; diff --git a/sysutils.h b/sysutils.h index b9074b3..84cf84d 100644 --- a/sysutils.h +++ b/sysutils.h @@ -1,5 +1,5 @@ /* source: sysutils.h */ -/* Copyright Gerhard Rieger 2001-2007 */ +/* Copyright Gerhard Rieger 2001-2008 */ /* Published under the GNU General Public License V.2, see file COPYING */ #ifndef __sysutils_h_included @@ -94,7 +94,7 @@ extern int xiopoll(struct pollfd fds[], nfds_t nfds, int timeout); extern int parseport(const char *portname, int proto); -extern int ifindexbyname(const char *ifname); -extern int ifindex(const char *ifname, unsigned int *ifindex); +extern int ifindexbyname(const char *ifname, int anysock); +extern int ifindex(const char *ifname, unsigned int *ifindex, int anysock); #endif /* !defined(__sysutils_h_included) */ diff --git a/test.sh b/test.sh index 5cbb3ec..aa6543d 100755 --- a/test.sh +++ b/test.sh @@ -7737,6 +7737,61 @@ PORT=$((PORT+1)) N=$((N+1)) +# use the INTERFACE address on a tun/tap device and transfer data fully +# transparent +NAME=TUNINTERFACE +case "$TESTS" in +*%functions%*|*%tun%*|*%interface%*|*%root%*|*%$NAME%*) +TEST="$NAME: pass data through tun interface using INTERFACE" +#idea: create a TUN interface and send a raw packet on the interface side. +# It should arrive unmodified on the tunnel side. +if ! feat=$(testaddrs ip4 tun interface) || ! runsip4 >/dev/null; then + $PRINTF "test $F_n $TEST... ${YELLOW}$feat not available${NORMAL}\n" $N + numCANT=$((numCANT+1)) +elif [ $(id -u) -ne 0 -a "$withroot" -eq 0 ]; then + $PRINTF "test $F_n $TEST... ${YELLOW}must be root${NORMAL}\n" $N + numCANT=$((numCANT+1)) +else +tf="$td/test$N.stdout" +te="$td/test$N.stderr" +tdiff="$td/test$N.diff" +tl="$td/test$N.lock" +da="$(date) $RANDOM" +dalen=$((${#da}+1)) +TUNNET=10.255.255 +TUNNAME=tun9 +CMD1="$SOCAT $opts -L $tl TUN:$TUNNET.1/24,iff-up=1,tun-type=tun,tun-name=$TUNNAME echo" +CMD="$SOCAT $opts - INTERFACE:$TUNNAME" +printf "test $F_n $TEST... " $N +$CMD1 2>"${te}1" & +pid1="$!" +#waitinterface "$TUNNAME" +sleep 1 +echo "$da" |$CMD 2>"${te}1" >"$tf" 2>"${te}" +kill $pid1 2>/dev/null +wait +if [ $? -ne 0 ]; then + $PRINTF "$FAILED: $SOCAT:\n" + echo "$CMD &" + echo "$CMD1" + cat "${te}" "${te}1" + numFAIL=$((numFAIL+1)) +elif ! echo "$da" |diff - "$tf" >"$tdiff"; then + $PRINTF "$FAILED\n" + cat "$tdiff" + cat "${te}" "${te}1" + numFAIL=$((numFAIL+1)) +else + $PRINTF "$OK\n" + if [ -n "$debug" ]; then cat "${te}" "${te}1"; fi + numOK=$((numOK+1)) +fi +fi ;; # not feats, not root +esac +PORT=$((PORT+1)) +N=$((N+1)) + + NAME=ABSTRACTSTREAM case "$TESTS" in *%functions%*|*%unix%*|*%abstract%*|*%connect%*|*%listen%*|*%$NAME%*) diff --git a/xio-interface.c b/xio-interface.c new file mode 100644 index 0000000..f7ebb1b --- /dev/null +++ b/xio-interface.c @@ -0,0 +1,105 @@ +/* source: xio-interface.c */ +/* Copyright Gerhard Rieger 2008 */ +/* Published under the GNU General Public License V.2, see file COPYING */ + +/* this file contains the source for opening addresses of raw socket type */ + +#include "xiosysincludes.h" + +#if WITH_INTERFACE + +#include "xioopen.h" +#include "xio-socket.h" + +#include "xio-interface.h" + + +static +int xioopen_interface(int argc, const char *argv[], struct opt *opts, + int xioflags, xiofile_t *xfd, unsigned 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(":") }; + + +static +int _xioopen_interface(const char *ifname, + struct opt *opts, int xioflags, xiofile_t *xxfd, + unsigned groups, int pf) { + xiosingle_t *xfd = &xxfd->stream; + union sockaddr_union us = {{0}}; + socklen_t uslen; + int socktype = SOCK_RAW; + unsigned int ifidx; + bool needbind = false; + char *bindstring = NULL; + struct sockaddr_ll sall = { 0 }; + + if (ifindex(ifname, &ifidx, -1) < 0) { + Error1("unknown interface \"%s\"", ifname); + ifidx = 0; /* desparate attempt to continue */ + } + + xfd->howtoend = END_SHUTDOWN; + retropt_int(opts, OPT_SO_TYPE, &socktype); + + retropt_socket_pf(opts, &pf); + + /* ...res_opts[] */ + if (applyopts_single(xfd, opts, PH_INIT) < 0) return -1; + applyopts(-1, opts, PH_INIT); + + xfd->salen = sizeof(xfd->peersa); + if (pf == PF_UNSPEC) { + pf = xfd->peersa.soa.sa_family; + } + + xfd->dtype = XIODATA_RECVFROM_SKIPIP; + + if (retropt_string(opts, OPT_BIND, &bindstring)) { + needbind = true; + } + /*!!! parse by ':' */ + ((struct sockaddr_ll *)&us)->sll_family = pf; + ((struct sockaddr_ll *)&us)->sll_protocol = htons(ETH_P_ALL); + ((struct sockaddr_ll *)&us)->sll_ifindex = ifidx; + uslen = sizeof(sall); + needbind = true; + xfd->peersa = (union sockaddr_union)us; + + return + _xioopen_dgram_sendto(needbind?&us:NULL, uslen, + opts, xioflags, xfd, groups, pf, socktype, 0); +} + +static +int xioopen_interface(int argc, const char *argv[], struct opt *opts, + int xioflags, xiofile_t *xxfd, unsigned groups, + int pf, int dummy2, int dummy3) { + xiosingle_t *xfd = &xxfd->stream; + int result; + + if (argc != 2) { + Error2("%s: wrong number of parameters (%d instead of 1)", + argv[0], argc-1); + return STAT_NORETRY; + } + + if ((result = + _xioopen_interface(argv[1], opts, xioflags, xxfd, groups, pf)) + != STAT_OK) { + return result; + } + + xfd->dtype = XIOREAD_RECV|XIOWRITE_SENDTO; + if (pf == PF_INET) { + xfd->dtype |= XIOREAD_RECV_SKIPIP; + } + + xfd->para.socket.la.soa.sa_family = xfd->peersa.soa.sa_family; + + _xio_openlate(xfd, opts); + return STAT_OK; +} + +#endif /* WITH_INTERFACE */ diff --git a/xio-interface.h b/xio-interface.h new file mode 100644 index 0000000..c7ed866 --- /dev/null +++ b/xio-interface.h @@ -0,0 +1,10 @@ +/* source: xio-interface.h */ +/* Copyright Gerhard Rieger 2008 */ +/* Published under the GNU General Public License V.2, see file COPYING */ + +#ifndef __xio_interface_h_included +#define __xio_interface_h_included 1 + +extern const struct addrdesc xioaddr_interface; + +#endif /* !defined(__xio_interface_h_included) */ diff --git a/xio-socket.c b/xio-socket.c index d93bb98..b0dcfcc 100644 --- a/xio-socket.c +++ b/xio-socket.c @@ -936,8 +936,8 @@ int retropt_socket_pf(struct opt *opts, int *pf) { char *pfname; if (retropt_string(opts, OPT_PROTOCOL_FAMILY, &pfname) >= 0) { - if (false) { - ; + if (isdigit(pfname[0])) { + *pf = strtoul(pfname, NULL /*!*/, 0); #if WITH_IP4 } else if (!strcasecmp("inet", pfname) || !strcasecmp("inet4", pfname) || diff --git a/xiomodes.h b/xiomodes.h index b48c9b7..8576a2b 100644 --- a/xiomodes.h +++ b/xiomodes.h @@ -1,5 +1,5 @@ /* source: xiomodes.h */ -/* Copyright Gerhard Rieger 2001-2007 */ +/* Copyright Gerhard Rieger 2001-2008 */ /* Published under the GNU General Public License V.2, see file COPYING */ #ifndef __xiomodes_h_included @@ -20,6 +20,7 @@ #include "xio-listen.h" #include "xio-unix.h" #include "xio-rawip.h" +#include "xio-interface.h" #include "xio-ip.h" #if WITH_IP4 #include "xio-ip4.h" diff --git a/xioopen.c b/xioopen.c index f944740..3d19fe5 100644 --- a/xioopen.c +++ b/xioopen.c @@ -1,5 +1,5 @@ /* source: xioopen.c */ -/* Copyright Gerhard Rieger 2001-2007 */ +/* Copyright Gerhard Rieger 2001-2008 */ /* Published under the GNU General Public License V.2, see file COPYING */ /* this is the source file of the extended open function */ @@ -55,6 +55,9 @@ const struct addrname addressnames[] = { #if WITH_GOPEN { "gopen", &addr_gopen }, #endif +#if WITH_INTERFACE + { "if", &xioaddr_interface }, +#endif #if (WITH_IP4 || WITH_IP6) && WITH_TCP { "inet", &addr_tcp_connect }, #endif @@ -76,6 +79,9 @@ const struct addrname addressnames[] = { { "inet6-l", &addr_tcp6_listen }, { "inet6-listen", &addr_tcp6_listen }, #endif +#if WITH_INTERFACE + { "interface", &xioaddr_interface }, +#endif #if WITH_RAWIP #if (WITH_IP4 || WITH_IP6) { "ip", &addr_rawip_sendto }, diff --git a/xioopts.c b/xioopts.c index ad76434..c55d1b0 100644 --- a/xioopts.c +++ b/xioopts.c @@ -3535,7 +3535,7 @@ mc:addr 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) + (unsigned int *)&ip4_mreqn.mreqn.imr_ifindex, -1) < 0) { Error1("cannot resolve interface \"%s\"", opt->value.u_ip_mreq.ifindex); @@ -3548,7 +3548,8 @@ mc:addr #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) + (unsigned int *)&ip4_mreqn.mreqn.imr_ifindex, + -1) >= 0) { /* yes, second param converts to interface */ ip4_mreqn.mreq.imr_interface.s_addr = htonl(0); @@ -3620,7 +3621,8 @@ mc:addr &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) { + &ip6_mreq.ipv6mr_interface, -1) + < 0) { Error1("interface \"%s\" not found", opt->value.u_ip_mreq.param2); ip6_mreq.ipv6mr_interface = htonl(0); diff --git a/xioread.c b/xioread.c index 5db886c..57049d8 100644 --- a/xioread.c +++ b/xioread.c @@ -131,6 +131,15 @@ ssize_t xioread(xiofile_t *file, void *buff, size_t bufsiz) { errno = _errno; return -1; } + /* on packet type we also receive outgoing packets, this is not desired + */ + if (from.soa.sa_family == PF_PACKET) { + if ((((struct sockaddr_ll *)&from.soa)->sll_pkttype & PACKET_OUTGOING) + == 0) { + errno = EAGAIN; return -1; + } + } + Notice2("received packet with "F_Zu" bytes from %s", bytes, sockaddr_info(&from.soa, fromlen, infobuff, sizeof(infobuff)));