mirror of
https://github.com/moparisthebest/socat
synced 2024-12-21 06:28:48 -05:00
new address "interface" for transparent network interface handling
This commit is contained in:
parent
d70b8963aa
commit
de910892f2
4
CHANGES
4
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
|
||||
|
||||
|
12
Makefile.in
12
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
|
||||
|
2
VERSION
2
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"
|
||||
|
@ -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 <linux/if_tun.h> header file. */
|
||||
#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. */
|
||||
#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
|
||||
|
23
configure.in
23
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
|
||||
|
29
doc/socat.yo
29
doc/socat.yo
@ -540,6 +540,15 @@ label(ADDRESS_NAMED_PIPE)dit(bf(tt(PIPE:<filename>)))
|
||||
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:<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)))
|
||||
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=<bytes>)))
|
||||
layer will send the data to <bytes> [link(int)(TYPE_INT)].
|
||||
label(OPTION_SNDTIMEO)dit(bf(tt(sndtimeo=<seconds>)))
|
||||
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
|
||||
code(socketpair()) call, to <type> [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=<pid_t>)))
|
||||
COMMENT(label(OPTION_USEIFBUFS)dit(bf(tt(useifbufs)))
|
||||
Set the code(SO_USE_IFBUFS) socket option.)
|
||||
label(OPTION_PROTOCOL_FAMILY)dit(bf(tt(pf=<string>)))
|
||||
Forces the use of the specified IP version. <string> can be
|
||||
something like "ip4" or "ip6".
|
||||
Forces the use of the specified IP version or protocol family. <string> 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()
|
||||
|
||||
|
||||
|
5
socat.c
5
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
|
||||
|
@ -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 <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
|
||||
#include <linux/if_tun.h>
|
||||
#endif
|
||||
|
31
sysutils.c
31
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;
|
||||
|
@ -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) */
|
||||
|
55
test.sh
55
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%*)
|
||||
|
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) */
|
@ -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) ||
|
||||
|
@ -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"
|
||||
|
@ -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 },
|
||||
|
@ -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);
|
||||
|
@ -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)));
|
||||
|
Loading…
Reference in New Issue
Block a user