diff --git a/CHANGES b/CHANGES index 6cb1d7c..2c21388 100644 --- a/CHANGES +++ b/CHANGES @@ -2,7 +2,11 @@ new features: new address types SCTP-CONNECT and SCTP-LISTEN implement SCTP stream mode for IPv4 and IPv6; new address options sctp-maxseg and - sctp-nodelay + sctp-nodelay (suggested by David A. Madore; thanks to Jonathan Brennan + for providing an initial patch) + + new address "interface" for transparent network interface handling + (suggested by Stuart Nicholson) added generic socket addresses: SOCKET-CONNECT, SOCKET-LISTEN, SOCKET-SENDTO, SOCKET-RECVFROM, SOCKET-RECV, SOCKET-DATAGRAM allow diff --git a/Makefile.in b/Makefile.in index 7e505a4..d1c1483 100644 --- a/Makefile.in +++ b/Makefile.in @@ -45,8 +45,11 @@ 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-sctp.c xio-rawip.c \ + xio-socks.c xio-proxy.c xio-udp.c \ + xio-rawip.c \ xio-progcall.c xio-exec.c xio-system.c xio-termios.c xio-readline.c \ xio-pty.c xio-openssl.c \ xio-ascii.c xiolockfile.c xio-tcpwrap.c xio-ext2.c xio-tun.c @@ -60,10 +63,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-sctp.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-sctp.h \ + xio-socks.h xio-proxy.h xio-progcall.h xio-exec.h \ xio-system.h xio-termios.h xio-readline.h \ xio-pty.h xio-openssl.h \ xio-ascii.h xiolockfile.h xio-tcpwrap.h xio-ext2.h xio-tun.h diff --git a/VERSION b/VERSION index 64a05c6..3c08469 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -"1.6.0.1+ip4bind+recvfromfork+x64+execstderr+execspaces+cosmetics+poll+udplistencont+ignoreeofunblock+escape+timestamp+ancillary+envvar+protocol+ioctl+setsockopt+genericsocket+sctp" +"1.6.0.1+ip4bind+recvfromfork+x64+execstderr+execspaces+cosmetics+poll+udplistencont+ignoreeofunblock+escape+timestamp+ancillary+envvar+protocol+ioctl+setsockopt+genericsocket+sctp+interface" diff --git a/config.h.in b/config.h.in index 7f7dcbc..2965536 100644 --- a/config.h.in +++ b/config.h.in @@ -236,6 +236,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 @@ -469,6 +475,7 @@ #undef WITH_IP6 #undef WITH_RAWIP #undef WITH_GENERICSOCKET +#undef WITH_INTERFACE #undef WITH_TCP #undef WITH_UDP #undef WITH_SCTP diff --git a/configure.in b/configure.in index 26074c6..f52f996 100644 --- a/configure.in +++ b/configure.in @@ -220,6 +220,28 @@ AC_ARG_ENABLE(rawsocket, [ --disable-genericsocket disable generic socket suppo *) AC_DEFINE(WITH_GENERICSOCKET) AC_MSG_RESULT(yes);; esac], [AC_DEFINE(WITH_GENERICSOCKET) 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], diff --git a/doc/socat.yo b/doc/socat.yo index 5723b1e..2153dc1 100644 --- a/doc/socat.yo +++ b/doc/socat.yo @@ -541,6 +541,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 @@ -2741,7 +2750,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 @@ -3193,6 +3203,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 cf56a83..cee4191 100644 --- a/socat.c +++ b/socat.c @@ -428,6 +428,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 6d053b9..295104a 100644 --- a/sysincludes.h +++ b/sysincludes.h @@ -125,6 +125,12 @@ #if HAVE_LINUX_ERRQUEUE_H #include /* struct sock_extended_err */ #endif +#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 615fb55..1e1aa57 100644 --- a/sysutils.c +++ b/sysutils.c @@ -116,7 +116,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; @@ -452,8 +452,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 */ @@ -461,29 +465,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 */ @@ -493,10 +503,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; @@ -509,7 +520,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 e8c8f32..62664ae 100644 --- a/sysutils.h +++ b/sysutils.h @@ -78,8 +78,8 @@ 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); extern int xiosetenv(const char *varname, const char *value, int overwrite); extern int diff --git a/test.sh b/test.sh index 6820123..8f9e5e9 100755 --- a/test.sh +++ b/test.sh @@ -7851,6 +7851,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 9fbdbbe..1cbfa80 100644 --- a/xio-socket.c +++ b/xio-socket.c @@ -1500,8 +1500,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 48f8dac..999c4d4 100644 --- a/xiomodes.h +++ b/xiomodes.h @@ -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 051bbc7..25ab136 100644 --- a/xioopen.c +++ b/xioopen.c @@ -59,6 +59,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 @@ -80,6 +83,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 550a292..cb969b0 100644 --- a/xioopts.c +++ b/xioopts.c @@ -3876,7 +3876,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); @@ -3889,7 +3889,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); @@ -3961,7 +3962,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 34590ea..559d9be 100644 --- a/xioread.c +++ b/xioread.c @@ -144,6 +144,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)));