1
0
mirror of https://github.com/moparisthebest/socat synced 2024-12-21 22:48:48 -05:00

new address "interface" for transparent network interface handling

This commit is contained in:
Gerhard Rieger 2008-09-20 23:37:56 +02:00
parent d70b8963aa
commit de910892f2
18 changed files with 300 additions and 31 deletions

View File

@ -1,4 +1,8 @@
new features:
new address "interface" for transparent network interface handling
(suggested by Stuart Nicholson)
corrections: corrections:
some raw IP and UNIX datagram modes failed on BSD systems some raw IP and UNIX datagram modes failed on BSD systems

View File

@ -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 \ xiolayer.c xioshutdown.c xioclose.c xioexit.c \
xio-process.c xio-fd.c xio-fdnum.c xio-stdio.c xio-pipe.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-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-rawip.c \
xio-progcall.c xio-exec.c xio-system.c xio-termios.c xio-readline.c \ xio-progcall.c xio-exec.c xio-system.c xio-termios.c xio-readline.c \
xio-pty.c xio-openssl.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 \ 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 \ 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 \ 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-named.h xio-file.h xio-creat.h xio-gopen.h xio-pipe.h \
xio-listen.h xio-unix.h xio-rawip.h xio-ip.h xio-ip4.h xio-ip6.h \ xio-socket.h xio-interface.h xio-listen.h xio-unix.h \
xio-ipapp.h xio-tcp.h xio-udp.h xio-socks.h xio-proxy.h xio-progcall.h xio-exec.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-system.h xio-termios.h xio-readline.h \
xio-pty.h xio-openssl.h \ xio-pty.h xio-openssl.h \
xio-ascii.h xiolockfile.h xio-tcpwrap.h xio-ext2.h xio-tun.h xio-ascii.h xiolockfile.h xio-tcpwrap.h xio-ext2.h xio-tun.h

View File

@ -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"

View File

@ -1,5 +1,5 @@
/* source: config.h.in */ /* 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 */ /* Published under the GNU General Public License V.2, see file COPYING */
#ifndef __config_h_included #ifndef __config_h_included
@ -227,6 +227,12 @@
/* Define if you have the <linux/if_tun.h> header file. */ /* Define if you have the <linux/if_tun.h> header file. */
#undef HAVE_LINUX_IF_TUN_H #undef HAVE_LINUX_IF_TUN_H
/* Define if you have the <netpacket/packet.h> header file. */
#undef HAVE_NETPACKET_PACKET_H
/* Define if you have the <netinet/if_ether.h> header file. */
#undef HAVE_NETINET_IF_ETHER_H
/* Define if you have the <sys/utsname.h> header file. */ /* Define if you have the <sys/utsname.h> header file. */
#undef HAVE_SYS_UTSNAME_H #undef HAVE_SYS_UTSNAME_H
@ -456,6 +462,7 @@
#undef WITH_IP4 #undef WITH_IP4
#undef WITH_IP6 #undef WITH_IP6
#undef WITH_RAWIP #undef WITH_RAWIP
#undef WITH_INTERFACE
#undef WITH_TCP #undef WITH_TCP
#undef WITH_UDP #undef WITH_UDP
#undef WITH_LISTEN #undef WITH_LISTEN

View File

@ -196,6 +196,29 @@ AC_ARG_ENABLE(rawip, [ --disable-rawip disable raw IP support],
esac], esac],
[AC_DEFINE(WITH_RAWIP) AC_MSG_RESULT(yes)]) [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_MSG_CHECKING(whether to include TCP support)
AC_ARG_ENABLE(tcp, [ --disable-tcp disable TCP support], AC_ARG_ENABLE(tcp, [ --disable-tcp disable TCP support],
[case "$enableval" in [case "$enableval" in

View File

@ -540,6 +540,15 @@ label(ADDRESS_NAMED_PIPE)dit(bf(tt(PIPE:<filename>)))
link(mode)(OPTION_MODE), link(mode)(OPTION_MODE),
link(unlink-early)(OPTION_UNLINK_EARLY)nl() link(unlink-early)(OPTION_UNLINK_EARLY)nl()
See also: link(unnamed pipe)(ADDRESS_UNNAMED_PIPE) See also: link(unnamed pipe)(ADDRESS_UNNAMED_PIPE)
label(ADDRESS_INTERFACE)dit(bf(tt(INTERFACE:<interface>)))
Communicate with a network connected on an interface using raw packets
including link level data. link(<interface>)(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))) label(ADDRESS_UNNAMED_PIPE)dit(bf(tt(PIPE)))
Creates an unnamed pipe and uses it for reading and writing. It works as an Creates an unnamed pipe and uses it for reading and writing. It works as an
echo, because everything written echo, because everything written
@ -1585,7 +1594,7 @@ label(OPTION_SNDLOWAT)dit(bf(tt(sndlowat=<bytes>)))
layer will send the data to <bytes> [link(int)(TYPE_INT)]. layer will send the data to <bytes> [link(int)(TYPE_INT)].
label(OPTION_SNDTIMEO)dit(bf(tt(sndtimeo=<seconds>))) label(OPTION_SNDTIMEO)dit(bf(tt(sndtimeo=<seconds>)))
Sets the send timeout to seconds [link(timeval)(TYPE_TIMEVAL)]. Sets the send timeout to seconds [link(timeval)(TYPE_TIMEVAL)].
label(OPTION_TYPE)dit(bf(tt(type=<type>))) label(OPTION_SO_TYPE)dit(bf(tt(type=<type>)))
Sets the type of the socket, usually as argument to the code(socket()) or Sets the type of the socket, usually as argument to the code(socket()) or
code(socketpair()) call, to <type> [link(int)(TYPE_INT)]. code(socketpair()) call, to <type> [link(int)(TYPE_INT)].
Under Linux, 1 means stream oriented socket, 2 means datagram socket, and 3 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=<pid_t>)))
COMMENT(label(OPTION_USEIFBUFS)dit(bf(tt(useifbufs))) COMMENT(label(OPTION_USEIFBUFS)dit(bf(tt(useifbufs)))
Set the code(SO_USE_IFBUFS) socket option.) Set the code(SO_USE_IFBUFS) socket option.)
label(OPTION_PROTOCOL_FAMILY)dit(bf(tt(pf=<string>))) label(OPTION_PROTOCOL_FAMILY)dit(bf(tt(pf=<string>)))
Forces the use of the specified IP version. <string> can be Forces the use of the specified IP version or protocol family. <string> can
something like "ip4" or "ip6". be something like "ip4" or "ip6" or a number.
enddit() enddit()
startdit()enddit()nl() startdit()enddit()nl()
@ -2433,7 +2442,8 @@ label(TYPE_INT)dit(int)
"0", i.e. decimal number, octal number with leading "0", or hexadecimal "0", i.e. decimal number, octal number with leading "0", or hexadecimal
number with leading "0x". The value must fit into a C int. number with leading "0x". The value must fit into a C int.
label(TYPE_INTERFACE)dit(interface) 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) label(TYPE_IP_ADDRESS)dit(IP address)
An IPv4 address in numbers-and-dots notation, an IPv6 address in hex 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 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(client)(EXAMPLE_ADDRESS_OPENSSL_CONNECT) and
link(server)(EXAMPLE_ADDRESS_OPENSSL_LISTEN)). 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() enddit()

View File

@ -426,6 +426,11 @@ void socat_version(FILE *fd) {
#else #else
fputs(" #undef WITH_RAWIP\n", fd); fputs(" #undef WITH_RAWIP\n", fd);
#endif #endif
#ifdef WITH_INTERFACE
fprintf(fd, " #define WITH_INTERFACE %d\n", WITH_INTERFACE);
#else
fputs(" #undef WITH_INTERFACE\n", fd);
#endif
#ifdef WITH_TCP #ifdef WITH_TCP
fprintf(fd, " #define WITH_TCP %d\n", WITH_TCP); fprintf(fd, " #define WITH_TCP %d\n", WITH_TCP);
#else #else

View File

@ -1,5 +1,5 @@
/* source: sysincludes.h */ /* 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 */ /* Published under the GNU General Public License V.2, see file COPYING */
#ifndef __sysincludes_h_included #ifndef __sysincludes_h_included
@ -116,6 +116,12 @@
#if HAVE_NET_IF_H #if HAVE_NET_IF_H
#include <net/if.h> #include <net/if.h>
#endif /* HAVE_NET_IF_H */ #endif /* HAVE_NET_IF_H */
#if HAVE_NETPACKET_PACKET_H
#include <netpacket/packet.h>
#endif
#if HAVE_NETINET_IF_ETHER_H
#include <netinet/if_ether.h>
#endif
#if HAVE_LINUX_IF_TUN_H #if HAVE_LINUX_IF_TUN_H
#include <linux/if_tun.h> #include <linux/if_tun.h>
#endif #endif

View File

@ -115,7 +115,7 @@ socklen_t socket_init(int af, union sockaddr_union *sa) {
#if WITH_IP6 #if WITH_IP6
case AF_INET6: socket_in6_init(&sa->ip6); return sizeof(sa->ip6); case AF_INET6: socket_in6_init(&sa->ip6); return sizeof(sa->ip6);
#endif #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)); memset(sa, 0, sizeof(union sockaddr_union));
sa->soa.sa_family = af; sa->soa.sa_family = af;
return 0; return 0;
@ -436,8 +436,12 @@ int parseport(const char *portname, int ipproto) {
#if WITH_IP4 || WITH_IP6 #if WITH_IP4 || WITH_IP6
/* check the systems interfaces for ifname and return its index /* check the systems interfaces for ifname and return its index
or -1 if no interface with this name was found */ or -1 if no interface with this name was found
int ifindexbyname(const char *ifname) { 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 */ /* Linux: man 7 netdevice */
/* FreeBSD: man 4 networking */ /* FreeBSD: man 4 networking */
/* Solaris: man 7 if_tcp */ /* Solaris: man 7 if_tcp */
@ -445,29 +449,35 @@ int ifindexbyname(const char *ifname) {
#if defined(HAVE_STRUCT_IFREQ) && defined(SIOCGIFCONF) && defined(SIOCGIFINDEX) #if defined(HAVE_STRUCT_IFREQ) && defined(SIOCGIFCONF) && defined(SIOCGIFINDEX)
/* currently we support Linux, FreeBSD; not Solaris */ /* currently we support Linux, FreeBSD; not Solaris */
#define IFBUFSIZ 1024 #define IFBUFSIZ 32*sizeof(struct ifreq) /*1024*/
int s; int s;
struct ifreq ifr; struct ifreq ifr;
if (ifname[0] == '\0') { if (ifname[0] == '\0') {
return -1; 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)); Error1("socket(PF_INET, SOCK_DGRAM, IPPROTO_IP): %s", strerror(errno));
return -1; return -1;
} }
strncpy(ifr.ifr_name, ifname, IFNAMSIZ); strncpy(ifr.ifr_name, ifname, IFNAMSIZ);
if (Ioctl(s, SIOCGIFINDEX, &ifr) < 0) { 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)); s, ifr.ifr_name, strerror(errno));
Close(s);
return -1; return -1;
} }
Close(s); Close(s);
#if HAVE_STRUCT_IFREQ_IFR_INDEX #if HAVE_STRUCT_IFREQ_IFR_INDEX
Info3("ioctl(%d, SIOCGIFINDEX, {\"%s\"}) -> { %d }",
s, ifname, ifr.ifr_index);
return ifr.ifr_index; return ifr.ifr_index;
#elif HAVE_STRUCT_IFREQ_IFR_IFINDEX #elif HAVE_STRUCT_IFREQ_IFR_IFINDEX
Info3("ioctl(%d, SIOCGIFINDEX, {\"%s\"}) -> { %d }",
s, ifname, ifr.ifr_ifindex);
return ifr.ifr_ifindex; return ifr.ifr_ifindex;
#endif /* HAVE_STRUCT_IFREQ_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, writes the resulting index to *ifindex and returns 0,
or returns -1 on error */ 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; char *endptr;
long int val; long int val;
@ -493,7 +504,7 @@ int ifindex(const char *ifname, unsigned int *ifindex) {
return 0; return 0;
} }
if ((val = ifindexbyname(ifname)) < 0) { if ((val = ifindexbyname(ifname, anysock)) < 0) {
return -1; return -1;
} }
*ifindex = val; *ifindex = val;

View File

@ -1,5 +1,5 @@
/* source: sysutils.h */ /* 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 */ /* Published under the GNU General Public License V.2, see file COPYING */
#ifndef __sysutils_h_included #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 parseport(const char *portname, int proto);
extern int ifindexbyname(const char *ifname); extern int ifindexbyname(const char *ifname, int anysock);
extern int ifindex(const char *ifname, unsigned int *ifindex); extern int ifindex(const char *ifname, unsigned int *ifindex, int anysock);
#endif /* !defined(__sysutils_h_included) */ #endif /* !defined(__sysutils_h_included) */

55
test.sh
View File

@ -7737,6 +7737,61 @@ PORT=$((PORT+1))
N=$((N+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 NAME=ABSTRACTSTREAM
case "$TESTS" in case "$TESTS" in
*%functions%*|*%unix%*|*%abstract%*|*%connect%*|*%listen%*|*%$NAME%*) *%functions%*|*%unix%*|*%abstract%*|*%connect%*|*%listen%*|*%$NAME%*)

105
xio-interface.c Normal file
View File

@ -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(":<interface>") };
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 */

10
xio-interface.h Normal file
View File

@ -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) */

View File

@ -936,8 +936,8 @@ int retropt_socket_pf(struct opt *opts, int *pf) {
char *pfname; char *pfname;
if (retropt_string(opts, OPT_PROTOCOL_FAMILY, &pfname) >= 0) { if (retropt_string(opts, OPT_PROTOCOL_FAMILY, &pfname) >= 0) {
if (false) { if (isdigit(pfname[0])) {
; *pf = strtoul(pfname, NULL /*!*/, 0);
#if WITH_IP4 #if WITH_IP4
} else if (!strcasecmp("inet", pfname) || } else if (!strcasecmp("inet", pfname) ||
!strcasecmp("inet4", pfname) || !strcasecmp("inet4", pfname) ||

View File

@ -1,5 +1,5 @@
/* source: xiomodes.h */ /* 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 */ /* Published under the GNU General Public License V.2, see file COPYING */
#ifndef __xiomodes_h_included #ifndef __xiomodes_h_included
@ -20,6 +20,7 @@
#include "xio-listen.h" #include "xio-listen.h"
#include "xio-unix.h" #include "xio-unix.h"
#include "xio-rawip.h" #include "xio-rawip.h"
#include "xio-interface.h"
#include "xio-ip.h" #include "xio-ip.h"
#if WITH_IP4 #if WITH_IP4
#include "xio-ip4.h" #include "xio-ip4.h"

View File

@ -1,5 +1,5 @@
/* source: xioopen.c */ /* 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 */ /* Published under the GNU General Public License V.2, see file COPYING */
/* this is the source file of the extended open function */ /* this is the source file of the extended open function */
@ -55,6 +55,9 @@ const struct addrname addressnames[] = {
#if WITH_GOPEN #if WITH_GOPEN
{ "gopen", &addr_gopen }, { "gopen", &addr_gopen },
#endif #endif
#if WITH_INTERFACE
{ "if", &xioaddr_interface },
#endif
#if (WITH_IP4 || WITH_IP6) && WITH_TCP #if (WITH_IP4 || WITH_IP6) && WITH_TCP
{ "inet", &addr_tcp_connect }, { "inet", &addr_tcp_connect },
#endif #endif
@ -76,6 +79,9 @@ const struct addrname addressnames[] = {
{ "inet6-l", &addr_tcp6_listen }, { "inet6-l", &addr_tcp6_listen },
{ "inet6-listen", &addr_tcp6_listen }, { "inet6-listen", &addr_tcp6_listen },
#endif #endif
#if WITH_INTERFACE
{ "interface", &xioaddr_interface },
#endif
#if WITH_RAWIP #if WITH_RAWIP
#if (WITH_IP4 || WITH_IP6) #if (WITH_IP4 || WITH_IP6)
{ "ip", &addr_rawip_sendto }, { "ip", &addr_rawip_sendto },

View File

@ -3535,7 +3535,7 @@ mc:addr
ip4_mreqn.mreq.imr_interface = sockaddr2.ip4.sin_addr; ip4_mreqn.mreq.imr_interface = sockaddr2.ip4.sin_addr;
/* third parameter is interface */ /* third parameter is interface */
if (ifindex(opt->value.u_ip_mreq.ifindex, if (ifindex(opt->value.u_ip_mreq.ifindex,
(unsigned int *)&ip4_mreqn.mreqn.imr_ifindex) (unsigned int *)&ip4_mreqn.mreqn.imr_ifindex, -1)
< 0) { < 0) {
Error1("cannot resolve interface \"%s\"", Error1("cannot resolve interface \"%s\"",
opt->value.u_ip_mreq.ifindex); opt->value.u_ip_mreq.ifindex);
@ -3548,7 +3548,8 @@ mc:addr
#if HAVE_STRUCT_IP_MREQN #if HAVE_STRUCT_IP_MREQN
/* there is a form with two parameters that uses mreqn */ /* there is a form with two parameters that uses mreqn */
} else if (ifindex(opt->value.u_ip_mreq.param2, } 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) { >= 0) {
/* yes, second param converts to interface */ /* yes, second param converts to interface */
ip4_mreqn.mreq.imr_interface.s_addr = htonl(0); ip4_mreqn.mreq.imr_interface.s_addr = htonl(0);
@ -3620,7 +3621,8 @@ mc:addr
&sockaddr1, &socklen1, 0, 0); &sockaddr1, &socklen1, 0, 0);
ip6_mreq.ipv6mr_multiaddr = sockaddr1.ip6.sin6_addr; ip6_mreq.ipv6mr_multiaddr = sockaddr1.ip6.sin6_addr;
if (ifindex(opt->value.u_ip_mreq.param2, if (ifindex(opt->value.u_ip_mreq.param2,
&ip6_mreq.ipv6mr_interface) < 0) { &ip6_mreq.ipv6mr_interface, -1)
< 0) {
Error1("interface \"%s\" not found", Error1("interface \"%s\" not found",
opt->value.u_ip_mreq.param2); opt->value.u_ip_mreq.param2);
ip6_mreq.ipv6mr_interface = htonl(0); ip6_mreq.ipv6mr_interface = htonl(0);

View File

@ -131,6 +131,15 @@ ssize_t xioread(xiofile_t *file, void *buff, size_t bufsiz) {
errno = _errno; errno = _errno;
return -1; 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", Notice2("received packet with "F_Zu" bytes from %s",
bytes, bytes,
sockaddr_info(&from.soa, fromlen, infobuff, sizeof(infobuff))); sockaddr_info(&from.soa, fromlen, infobuff, sizeof(infobuff)));