mirror of
https://repo.or.cz/socat.git
synced 2024-12-22 23:42:34 +00:00
merged feature raw network interface
This commit is contained in:
commit
784e378ede
18 changed files with 293 additions and 25 deletions
6
CHANGES
6
CHANGES
|
@ -2,7 +2,11 @@
|
||||||
new features:
|
new features:
|
||||||
new address types SCTP-CONNECT and SCTP-LISTEN implement SCTP stream
|
new address types SCTP-CONNECT and SCTP-LISTEN implement SCTP stream
|
||||||
mode for IPv4 and IPv6; new address options sctp-maxseg and
|
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,
|
added generic socket addresses: SOCKET-CONNECT, SOCKET-LISTEN,
|
||||||
SOCKET-SENDTO, SOCKET-RECVFROM, SOCKET-RECV, SOCKET-DATAGRAM allow
|
SOCKET-SENDTO, SOCKET-RECVFROM, SOCKET-RECV, SOCKET-DATAGRAM allow
|
||||||
|
|
14
Makefile.in
14
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 \
|
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-sctp.c xio-rawip.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-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 \
|
||||||
xio-ascii.c xiolockfile.c xio-tcpwrap.c xio-ext2.c xio-tun.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 \
|
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-sctp.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-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
|
||||||
|
|
2
VERSION
2
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"
|
||||||
|
|
|
@ -236,6 +236,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
|
||||||
|
|
||||||
|
@ -469,6 +475,7 @@
|
||||||
#undef WITH_IP6
|
#undef WITH_IP6
|
||||||
#undef WITH_RAWIP
|
#undef WITH_RAWIP
|
||||||
#undef WITH_GENERICSOCKET
|
#undef WITH_GENERICSOCKET
|
||||||
|
#undef WITH_INTERFACE
|
||||||
#undef WITH_TCP
|
#undef WITH_TCP
|
||||||
#undef WITH_UDP
|
#undef WITH_UDP
|
||||||
#undef WITH_SCTP
|
#undef WITH_SCTP
|
||||||
|
|
22
configure.in
22
configure.in
|
@ -220,6 +220,28 @@ AC_ARG_ENABLE(rawsocket, [ --disable-genericsocket disable generic socket suppo
|
||||||
*) AC_DEFINE(WITH_GENERICSOCKET) AC_MSG_RESULT(yes);;
|
*) AC_DEFINE(WITH_GENERICSOCKET) AC_MSG_RESULT(yes);;
|
||||||
esac],
|
esac],
|
||||||
[AC_DEFINE(WITH_GENERICSOCKET) AC_MSG_RESULT(yes)])
|
[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_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],
|
||||||
|
|
23
doc/socat.yo
23
doc/socat.yo
|
@ -541,6 +541,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
|
||||||
|
@ -2741,7 +2750,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
|
||||||
|
@ -3193,6 +3203,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()
|
||||||
|
|
||||||
|
|
||||||
|
|
5
socat.c
5
socat.c
|
@ -428,6 +428,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
|
||||||
|
|
|
@ -125,6 +125,12 @@
|
||||||
#if HAVE_LINUX_ERRQUEUE_H
|
#if HAVE_LINUX_ERRQUEUE_H
|
||||||
#include <linux/errqueue.h> /* struct sock_extended_err */
|
#include <linux/errqueue.h> /* struct sock_extended_err */
|
||||||
#endif
|
#endif
|
||||||
|
#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
|
||||||
|
|
31
sysutils.c
31
sysutils.c
|
@ -116,7 +116,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;
|
||||||
|
@ -452,8 +452,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 */
|
||||||
|
@ -461,29 +465,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 */
|
||||||
|
|
||||||
|
@ -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,
|
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;
|
||||||
|
|
||||||
|
@ -509,7 +520,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;
|
||||||
|
|
|
@ -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 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);
|
||||||
|
|
||||||
extern int xiosetenv(const char *varname, const char *value, int overwrite);
|
extern int xiosetenv(const char *varname, const char *value, int overwrite);
|
||||||
extern int
|
extern int
|
||||||
|
|
55
test.sh
55
test.sh
|
@ -7851,6 +7851,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
105
xio-interface.c
Normal 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
10
xio-interface.h
Normal 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) */
|
|
@ -1500,8 +1500,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) ||
|
||||||
|
|
|
@ -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"
|
||||||
|
|
|
@ -59,6 +59,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
|
||||||
|
@ -80,6 +83,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 },
|
||||||
|
|
|
@ -3876,7 +3876,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);
|
||||||
|
@ -3889,7 +3889,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);
|
||||||
|
@ -3961,7 +3962,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);
|
||||||
|
|
|
@ -144,6 +144,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)));
|
||||||
|
|
Loading…
Reference in a new issue