mirror of
https://repo.or.cz/socat.git
synced 2024-12-22 23:42:34 +00:00
Use PACKET_IGNORE_OUTGOING when available; a few corrections and renamings for raw sockets and ancillary messages
This commit is contained in:
parent
47af17dbf2
commit
11d1e9e11f
12 changed files with 185 additions and 42 deletions
6
CHANGES
6
CHANGES
|
@ -108,6 +108,10 @@ Porting:
|
||||||
Removed Config/ because its contents have not been maintained for many
|
Removed Config/ because its contents have not been maintained for many
|
||||||
years.
|
years.
|
||||||
|
|
||||||
|
Try to not receive outgoing packets on raw (PF_PACKET) sockets - use
|
||||||
|
PACKET_IGNORE_OUTGOING socket options when available.
|
||||||
|
Test: INTERFACE_IGNOREOUTGOING
|
||||||
|
|
||||||
Testing:
|
Testing:
|
||||||
Removed obselete parts from test.sh
|
Removed obselete parts from test.sh
|
||||||
|
|
||||||
|
@ -117,6 +121,8 @@ Documentation:
|
||||||
Added doc for option ipv6-join-group (ipv6-add-membership)
|
Added doc for option ipv6-join-group (ipv6-add-membership)
|
||||||
Thanks to Martin Buck for sending the patch.
|
Thanks to Martin Buck for sending the patch.
|
||||||
|
|
||||||
|
Renamed xiogetpacketsrc() to xiogetancillary()
|
||||||
|
|
||||||
####################### V 1.7.4.5 (not released):
|
####################### V 1.7.4.5 (not released):
|
||||||
|
|
||||||
Corrections:
|
Corrections:
|
||||||
|
|
2
VERSION
2
VERSION
|
@ -1 +1 @@
|
||||||
"1.7.4.5+"
|
"1.7.4.5+vlans"
|
||||||
|
|
|
@ -285,8 +285,8 @@
|
||||||
/* Define if you have the <linux/vm_sockets.h> header file. */
|
/* Define if you have the <linux/vm_sockets.h> header file. */
|
||||||
#undef HAVE_LINUX_VM_SOCKETS_H
|
#undef HAVE_LINUX_VM_SOCKETS_H
|
||||||
|
|
||||||
/* Define if you have the <netpacket/packet.h> header file. */
|
/* Define if you have the <linux/if_packet.h> header file. */
|
||||||
#undef HAVE_NETPACKET_PACKET_H
|
#undef HAVE_LINUX_IF_PACKET_H
|
||||||
|
|
||||||
/* Define if you have the <netinet/if_ether.h> header file. */
|
/* Define if you have the <netinet/if_ether.h> header file. */
|
||||||
#undef HAVE_NETINET_IF_ETHER_H
|
#undef HAVE_NETINET_IF_ETHER_H
|
||||||
|
|
|
@ -321,10 +321,10 @@ AC_ARG_ENABLE(interface, [ --disable-interface disable network interface suppo
|
||||||
esac],
|
esac],
|
||||||
[AC_MSG_RESULT(yes); WITH_INTERFACE=1 ])
|
[AC_MSG_RESULT(yes); WITH_INTERFACE=1 ])
|
||||||
if test "$WITH_INTERFACE"; then
|
if test "$WITH_INTERFACE"; then
|
||||||
AC_CHECK_HEADER(netpacket/packet.h,
|
AC_CHECK_HEADER(linux/if_packet.h,
|
||||||
AC_DEFINE(HAVE_NETPACKET_PACKET_H),
|
AC_DEFINE(HAVE_LINUX_IF_PACKET_H),
|
||||||
[WITH_INTERFACE=;
|
[WITH_INTERFACE=;
|
||||||
AC_MSG_WARN([include file netpacket/packet.h not found, disabling interface])])
|
AC_MSG_WARN([include file linux/if_packet.h not found, disabling interface])])
|
||||||
fi
|
fi
|
||||||
if test "$WITH_INTERFACE"; then
|
if test "$WITH_INTERFACE"; then
|
||||||
AC_CHECK_HEADER(netinet/if_ether.h,
|
AC_CHECK_HEADER(netinet/if_ether.h,
|
||||||
|
|
|
@ -389,7 +389,7 @@ label(ADDRESS_IP_SENDTO)dit(bf(tt(IP-SENDTO:<host>:<protocol>)))
|
||||||
label(ADDRESS_INTERFACE)dit(bf(tt(INTERFACE:<interface>)))
|
label(ADDRESS_INTERFACE)dit(bf(tt(INTERFACE:<interface>)))
|
||||||
Communicates with a network connected on an interface using raw packets
|
Communicates with a network connected on an interface using raw packets
|
||||||
including link level data. link(<interface>)(TYPE_INTERFACE) is the name of
|
including link level data. link(<interface>)(TYPE_INTERFACE) is the name of
|
||||||
the network interface. Currently only available on Linux.
|
the network interface. Currently only available on Linux.nl()
|
||||||
Option groups: link(FD)(GROUP_FD),link(SOCKET)(GROUP_SOCKET) nl()
|
Option groups: link(FD)(GROUP_FD),link(SOCKET)(GROUP_SOCKET) nl()
|
||||||
Useful options:
|
Useful options:
|
||||||
link(pf)(OPTION_PROTOCOL_FAMILY),
|
link(pf)(OPTION_PROTOCOL_FAMILY),
|
||||||
|
|
|
@ -141,8 +141,8 @@
|
||||||
#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
|
#if HAVE_LINUX_IF_PACKET_H
|
||||||
#include <netpacket/packet.h>
|
#include <linux/if_packet.h>
|
||||||
#endif
|
#endif
|
||||||
#if HAVE_NETINET_IF_ETHER_H
|
#if HAVE_NETINET_IF_ETHER_H
|
||||||
#include <netinet/if_ether.h>
|
#include <netinet/if_ether.h>
|
||||||
|
|
117
test.sh
117
test.sh
|
@ -760,7 +760,8 @@ testaddrs () {
|
||||||
local a A;
|
local a A;
|
||||||
for a in $@; do
|
for a in $@; do
|
||||||
A=$(echo "$a" |tr 'a-z' 'A-Z')
|
A=$(echo "$a" |tr 'a-z' 'A-Z')
|
||||||
if ! $SOCAT $A /dev/null 2>&1 </dev/null |grep -q "E unknown device/address"; then
|
# the ::::: forces syntax errer and prevents the address from doing anything
|
||||||
|
if ! $SOCAT $A::::: /dev/null 2>&1 </dev/null |grep -q "E unknown device/address"; then
|
||||||
shift
|
shift
|
||||||
continue
|
continue
|
||||||
fi
|
fi
|
||||||
|
@ -9468,9 +9469,10 @@ elif ! grep "ancillary message: $SCM_TYPE: $SCM_NAME=$SCM_VALUE\$" ${te}0 >/dev/
|
||||||
listFAIL="$listFAIL $N"
|
listFAIL="$listFAIL $N"
|
||||||
else
|
else
|
||||||
$PRINTF "$OK\n"
|
$PRINTF "$OK\n"
|
||||||
if [ -n "$debug" ]; then
|
if [ "$VERBOSE" ]; then echo "$CMD0 &"; fi
|
||||||
grep " $LEVELS " "${te}0"; echo; grep " $LEVELS " "${te}1";
|
if [ "$DEBUG" ]; then grep " $LEVELS " "${te}0" >&2; fi
|
||||||
fi
|
if [ "$VERBOSE" ]; then echo "echo XYZ |$CMD1"; fi
|
||||||
|
if [ "$DEBUG" ]; then grep " $LEVELS " "${te}1" >&2; fi
|
||||||
numOK=$((numOK+1))
|
numOK=$((numOK+1))
|
||||||
fi
|
fi
|
||||||
else # option is not supported
|
else # option is not supported
|
||||||
|
@ -9716,9 +9718,10 @@ elif ! expr "$(cat "$tf")" : "$SCM_VALUE\$" >/dev/null; then
|
||||||
listFAIL="$listFAIL $N"
|
listFAIL="$listFAIL $N"
|
||||||
else
|
else
|
||||||
$PRINTF "$OK\n"
|
$PRINTF "$OK\n"
|
||||||
if [ -n "$debug" ]; then
|
if [ "$VERBOSE" ]; then echo "$CMD0 &"; fi
|
||||||
cat "${te}0"; echo; cat "${te}1";
|
if [ "$DEBUG" ]; then cat "${te}0" >&2; fi
|
||||||
fi
|
if [ "$VERBOSE" ]; then echo "{ echo XYZ; sleep 0.1; } |$CMD1"; fi
|
||||||
|
if [ "$DEBUG" ]; then cat "${te}1" >&2; fi
|
||||||
numOK=$((numOK+1))
|
numOK=$((numOK+1))
|
||||||
fi
|
fi
|
||||||
else # option is not supported
|
else # option is not supported
|
||||||
|
@ -13148,7 +13151,6 @@ fi
|
||||||
fi ;; # NUMCOND, feats
|
fi ;; # NUMCOND, feats
|
||||||
esac
|
esac
|
||||||
N=$((N+1))
|
N=$((N+1))
|
||||||
set +vx
|
|
||||||
|
|
||||||
# test the DTLS server feature
|
# test the DTLS server feature
|
||||||
NAME=OPENSSL_DTLS_SERVER
|
NAME=OPENSSL_DTLS_SERVER
|
||||||
|
@ -15590,6 +15592,99 @@ esac
|
||||||
N=$((N+1))
|
N=$((N+1))
|
||||||
|
|
||||||
|
|
||||||
|
# Socats INTERFACE address has to ignore outgoing packets if possible.
|
||||||
|
# On Linux is uses socket option PACKET_IGNORE_OUTGOING or it queries per
|
||||||
|
# packet the PACKET_OUTGOING flag of struct sockaddr_ll.sll_pkttype
|
||||||
|
NAME=INTERFACE_IGNOREOUTGOING
|
||||||
|
case "$TESTS" in
|
||||||
|
*%$N%*|*%functions%*|*%interface%*|*%tun%*|*%root%*|*%$NAME%*)
|
||||||
|
TEST="$NAME: INTERFACE ignores outgoing packets"
|
||||||
|
#idea: create a TUN interface and hook with INTERFACE.
|
||||||
|
# Send a packet out the interface, should not be seen by INTERFACE
|
||||||
|
if ! eval $NUMCOND; then :;
|
||||||
|
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))
|
||||||
|
listCANT="$listCANT $N"
|
||||||
|
elif ! $(type ping >/dev/null 2>&1); then
|
||||||
|
$PRINTF "test $F_n $TEST... ${YELLOW}ping not available${NORMAL}\n" $N
|
||||||
|
numCANT=$((numCANT+1))
|
||||||
|
listCANT="$listCANT $N"
|
||||||
|
elif ! feat=$(testfeats TUN STDIO INTERFACE); then
|
||||||
|
$PRINTF "test $F_n $TEST... ${YELLOW}$feat not available${NORMAL}\n" $N
|
||||||
|
numCANT=$((numCANT+1))
|
||||||
|
listCANT="$listCANT $N"
|
||||||
|
elif ! A=$(testaddrs - TUN STDIO INTERFACE); then
|
||||||
|
$PRINTF "test $F_n $TEST... ${YELLOW}Address $A not available in $SOCAT${NORMAL}\n" $N
|
||||||
|
numCANT=$((numCANT+1))
|
||||||
|
listCANT="$listCANT $N"
|
||||||
|
elif ! o=$(testoptions iff-up tun-type tun-name ) >/dev/null; then
|
||||||
|
$PRINTF "test $F_n $TEST... ${YELLOW}Option $o not available in $SOCAT${NORMAL}\n" $N
|
||||||
|
numCANT=$((numCANT+1))
|
||||||
|
listCANT="$listCANT $N"
|
||||||
|
elif ! runsip4 >/dev/null; then
|
||||||
|
$PRINTF "test $F_n $TEST... ${YELLOW}IPv4 not available${NORMAL}\n" $N
|
||||||
|
numCANT=$((numCANT+1))
|
||||||
|
listCANT="$listCANT $N"
|
||||||
|
else
|
||||||
|
tf="$td/test$N.stdout"
|
||||||
|
te="$td/test$N.stderr"
|
||||||
|
tdiff="$td/test$N.diff"
|
||||||
|
tl="$td/test$N.lock"
|
||||||
|
da="$(date) $RANDOM"
|
||||||
|
TUNNET=10.255.255
|
||||||
|
TUNNAME=tun9
|
||||||
|
CMD0="$TRACE $SOCAT $opts -L $tl TUN:$TUNNET.1/24,iff-up=1,tun-type=tun,tun-name=$TUNNAME -"
|
||||||
|
CMD1="$TRACE $SOCAT $opts -u INTERFACE:$TUNNAME -"
|
||||||
|
CMD2="ping -c 1 -w 1 -b $TUNNET.255"
|
||||||
|
printf "test $F_n $TEST... " $N
|
||||||
|
sleep 1 |$CMD0 2>"${te}0" >/dev/null &
|
||||||
|
pid0="$!"
|
||||||
|
#waitinterface "$TUNNAME"
|
||||||
|
usleep $MICROS
|
||||||
|
$CMD1 >"${tf}1" 2>"${te}1" &
|
||||||
|
pid1="$!"
|
||||||
|
usleep $MICROS
|
||||||
|
$CMD2 2>"${te}2" 1>&2
|
||||||
|
kill $pid1 2>/dev/null
|
||||||
|
usleep $MICROS
|
||||||
|
kill $pid0 2>/dev/null
|
||||||
|
wait
|
||||||
|
if [ $? -ne 0 ]; then
|
||||||
|
$PRINTF "$FAILED: $TRACE $SOCAT:\n"
|
||||||
|
echo "$CMD0 &"
|
||||||
|
cat "${te}0" >&2
|
||||||
|
echo "$CMD1"
|
||||||
|
cat "${te}1" >&2
|
||||||
|
echo "$CMD2"
|
||||||
|
cat "${te}2" >&2
|
||||||
|
numCANT=$((numCANT+1))
|
||||||
|
listCANT="$listCANT $N"
|
||||||
|
elif test -s "${tf}1"; then
|
||||||
|
$PRINTF "$FAILED\n"
|
||||||
|
echo "$CMD0 &"
|
||||||
|
cat "${te}0" >&2
|
||||||
|
echo "$CMD1"
|
||||||
|
cat "${te}1" >&2
|
||||||
|
echo "$CMD2"
|
||||||
|
cat "${te}2" >&2
|
||||||
|
numFAIL=$((numFAIL+1))
|
||||||
|
listFAIL="$listFAIL $N"
|
||||||
|
else
|
||||||
|
$PRINTF "$OK\n"
|
||||||
|
if [ "$VERBOSE" ]; then echo "$CMD0 &"; fi
|
||||||
|
if [ "$DEBUG" ]; then cat "${te}0" >&2; fi
|
||||||
|
if [ "$VERBOSE" ]; then echo "$CMD1"; fi
|
||||||
|
if [ "$DEBUG" ]; then cat "${te}1" >&2; fi
|
||||||
|
if [ "$VERBOSE" ]; then echo "$CMD2"; fi
|
||||||
|
if [ "$DEBUG" ]; then cat "${te}2" >&2; fi
|
||||||
|
numOK=$((numOK+1))
|
||||||
|
fi
|
||||||
|
fi ;; # NUMCOND, feats
|
||||||
|
esac
|
||||||
|
PORT=$((PORT+1))
|
||||||
|
N=$((N+1))
|
||||||
|
|
||||||
# end of common tests
|
# end of common tests
|
||||||
|
|
||||||
##################################################################################
|
##################################################################################
|
||||||
|
@ -15694,9 +15789,11 @@ if [ "$OPT_EXPECT_FAIL" ]; then
|
||||||
grep "^< " "$td/failed.diff" |awk '{print($2);}' >"$td/ok.unexp"
|
grep "^< " "$td/failed.diff" |awk '{print($2);}' >"$td/ok.unexp"
|
||||||
ln -s "$td/ok.unexp" .
|
ln -s "$td/ok.unexp" .
|
||||||
echo "OK unexpected: $(cat "$td/ok.unexp" |xargs echo)"
|
echo "OK unexpected: $(cat "$td/ok.unexp" |xargs echo)"
|
||||||
|
else
|
||||||
|
touch "$td/failed.diff"
|
||||||
fi
|
fi
|
||||||
listFAIL=$(cat "$td/failed.lst" |xargs echo)
|
#listFAIL=$(cat "$td/failed.lst" |xargs echo)
|
||||||
numFAIL="$(wc -l "$td/failed.lst" |awk '{print($1);}')"
|
#numFAIL="$(wc -l "$td/failed.lst" |awk '{print($1);}')"
|
||||||
|
|
||||||
! test -s "$td/failed.unexp"
|
! test -s "$td/failed.unexp"
|
||||||
exit
|
exit
|
||||||
|
|
|
@ -111,13 +111,14 @@ int _xioopen_interface(const char *ifname,
|
||||||
_xiointerface_apply_iff(xfd->fd, ifname, xfd->para.interface.iff_opts);
|
_xiointerface_apply_iff(xfd->fd, ifname, xfd->para.interface.iff_opts);
|
||||||
|
|
||||||
#ifdef PACKET_IGNORE_OUTGOING
|
#ifdef PACKET_IGNORE_OUTGOING
|
||||||
/* Raw socket may even provide packets that are outbound - we are not
|
/* Raw socket might also provide packets that are outbound - we are not
|
||||||
interested in these and disable this "feature" in kernel if possible */
|
interested in these and disable this "feature" in kernel if possible */
|
||||||
if (Setsockopt(xfd->fd, SOL_PACKET, PACKET_IGNORE_OUTGOING, &one, sizeof(one)) < 0) {
|
if (Setsockopt(xfd->fd, SOL_PACKET, PACKET_IGNORE_OUTGOING, &one, sizeof(one)) < 0) {
|
||||||
Warn2("setsockopt(%d, SOL_PACKET, PACKET_IGNORE_OUTGOING, {1}): %s",
|
Warn2("setsockopt(%d, SOL_PACKET, PACKET_IGNORE_OUTGOING, {1}): %s",
|
||||||
xfd->fd, strerror(errno));
|
xfd->fd, strerror(errno));
|
||||||
}
|
}
|
||||||
#endif
|
#endif /*defined(PACKET_IGNORE_OUTGOING) */
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
12
xio-socket.c
12
xio-socket.c
|
@ -25,6 +25,7 @@
|
||||||
#endif /* WITH_IP6 */
|
#endif /* WITH_IP6 */
|
||||||
#include "xio-ip.h"
|
#include "xio-ip.h"
|
||||||
#include "xio-listen.h"
|
#include "xio-listen.h"
|
||||||
|
#include "xio-interface.h"
|
||||||
#include "xio-ipapp.h" /*! not clean */
|
#include "xio-ipapp.h" /*! not clean */
|
||||||
#include "xio-tcpwrap.h"
|
#include "xio-tcpwrap.h"
|
||||||
|
|
||||||
|
@ -733,7 +734,7 @@ int xiogetpacketinfo(int fd)
|
||||||
#if HAVE_STRUCT_MSGHDR_MSGCONTROLLEN
|
#if HAVE_STRUCT_MSGHDR_MSGCONTROLLEN
|
||||||
msgh.msg_controllen = sizeof(ctrlbuff);
|
msgh.msg_controllen = sizeof(ctrlbuff);
|
||||||
#endif
|
#endif
|
||||||
if (xiogetpacketsrc(fd,
|
if (xiogetancillary(fd,
|
||||||
&msgh,
|
&msgh,
|
||||||
MSG_ERRQUEUE
|
MSG_ERRQUEUE
|
||||||
#ifdef MSG_TRUNC
|
#ifdef MSG_TRUNC
|
||||||
|
@ -1078,7 +1079,7 @@ int _xioopen_dgram_sendto(/* them is already in xfd->peersa */
|
||||||
applyopts_named(us->un.sun_path, opts, PH_LATE);
|
applyopts_named(us->un.sun_path, opts, PH_LATE);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
applyopts(xfd->fd, opts, PH_LATE);
|
/*applyopts(xfd->fd, opts, PH_LATE);*/
|
||||||
|
|
||||||
/* xfd->dtype = DATA_RECVFROM; *//* no, the caller must set this (ev _SKIPIP) */
|
/* xfd->dtype = DATA_RECVFROM; *//* no, the caller must set this (ev _SKIPIP) */
|
||||||
Notice1("successfully prepared local socket %s",
|
Notice1("successfully prepared local socket %s",
|
||||||
|
@ -1244,7 +1245,7 @@ int _xioopen_dgram_recvfrom(struct single *xfd, int xioflags,
|
||||||
#if HAVE_STRUCT_MSGHDR_MSGCONTROLLEN
|
#if HAVE_STRUCT_MSGHDR_MSGCONTROLLEN
|
||||||
msgh.msg_controllen = sizeof(ctrlbuff);
|
msgh.msg_controllen = sizeof(ctrlbuff);
|
||||||
#endif
|
#endif
|
||||||
while ((rc = xiogetpacketsrc(xfd->fd,
|
while ((rc = xiogetancillary(xfd->fd,
|
||||||
&msgh,
|
&msgh,
|
||||||
MSG_PEEK
|
MSG_PEEK
|
||||||
#ifdef MSG_TRUNC
|
#ifdef MSG_TRUNC
|
||||||
|
@ -1431,8 +1432,9 @@ int retropt_socket_pf(struct opt *opts, int *pf) {
|
||||||
In msgh the msg_name pointer must refer to an (empty) sockaddr storage.
|
In msgh the msg_name pointer must refer to an (empty) sockaddr storage.
|
||||||
Returns STAT_OK on success, or STAT_RETRYLATER when an error occurred,
|
Returns STAT_OK on success, or STAT_RETRYLATER when an error occurred,
|
||||||
including EINTR.
|
including EINTR.
|
||||||
|
(recvmsg() retrieves just meta info, not the data)
|
||||||
*/
|
*/
|
||||||
int xiogetpacketsrc(int fd, struct msghdr *msgh, int flags) {
|
int xiogetancillary(int fd, struct msghdr *msgh, int flags) {
|
||||||
char peekbuff[1];
|
char peekbuff[1];
|
||||||
#if HAVE_STRUCT_IOVEC
|
#if HAVE_STRUCT_IOVEC
|
||||||
struct iovec iovec;
|
struct iovec iovec;
|
||||||
|
@ -1473,6 +1475,8 @@ int xiodopacketinfo(struct msghdr *msgh, bool withlog, bool withenv) {
|
||||||
char valbuff[256], *valp;
|
char valbuff[256], *valp;
|
||||||
char envbuff[256], *envp;
|
char envbuff[256], *envp;
|
||||||
|
|
||||||
|
Info3("ancillary message in xiodopacketinfo(): len="F_Zu", level=%d, type=%d",
|
||||||
|
cmsg->cmsg_len, cmsg->cmsg_level, cmsg->cmsg_type);
|
||||||
if (withlog) {
|
if (withlog) {
|
||||||
xiodump(CMSG_DATA(cmsg),
|
xiodump(CMSG_DATA(cmsg),
|
||||||
cmsg->cmsg_len-((char *)CMSG_DATA(cmsg)-(char *)cmsg),
|
cmsg->cmsg_len-((char *)CMSG_DATA(cmsg)-(char *)cmsg),
|
||||||
|
|
|
@ -84,6 +84,7 @@ extern
|
||||||
char *xiogetifname(int ind, char *val, int ins);
|
char *xiogetifname(int ind, char *val, int ins);
|
||||||
|
|
||||||
extern int retropt_socket_pf(struct opt *opts, int *pf);
|
extern int retropt_socket_pf(struct opt *opts, int *pf);
|
||||||
|
extern int xiogetancillary(int fd, struct msghdr *msgh, int flags);
|
||||||
|
|
||||||
extern int xioopen_connect(struct single *fd,
|
extern int xioopen_connect(struct single *fd,
|
||||||
union sockaddr_union *us, size_t uslen,
|
union sockaddr_union *us, size_t uslen,
|
||||||
|
|
|
@ -81,7 +81,10 @@ int xioclose1(struct single *pipe) {
|
||||||
#if WITH_INTERFACE
|
#if WITH_INTERFACE
|
||||||
case END_INTERFACE:
|
case END_INTERFACE:
|
||||||
{
|
{
|
||||||
_xiointerface_set_iff(pipe->fd, pipe->para.interface.name, pipe->para.interface.save_iff);
|
if (pipe->para.interface.name[0] != '\0') {
|
||||||
|
_xiointerface_set_iff(pipe->fd, pipe->para.interface.name,
|
||||||
|
pipe->para.interface.save_iff);
|
||||||
|
}
|
||||||
if (Close(pipe->fd) < 0) {
|
if (Close(pipe->fd) < 0) {
|
||||||
Info2("close(%d): %s", pipe->fd, strerror(errno)); } break;
|
Info2("close(%d): %s", pipe->fd, strerror(errno)); } break;
|
||||||
}
|
}
|
||||||
|
|
63
xioread.c
63
xioread.c
|
@ -42,7 +42,7 @@ ssize_t xioread(xiofile_t *file, void *buff, size_t bufsiz) {
|
||||||
|
|
||||||
if (pipe->readbytes) {
|
if (pipe->readbytes) {
|
||||||
if (pipe->actbytes == 0) {
|
if (pipe->actbytes == 0) {
|
||||||
Info("xioread(): readbytes consumed, inserting EOF");
|
Info1("xioread(%d, ...): readbytes consumed, inserting EOF", pipe->fd);
|
||||||
return 0; /* EOF by count */
|
return 0; /* EOF by count */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -135,6 +135,10 @@ ssize_t xioread(xiofile_t *file, void *buff, size_t bufsiz) {
|
||||||
#if _WITH_SOCKET
|
#if _WITH_SOCKET
|
||||||
case XIOREAD_RECV:
|
case XIOREAD_RECV:
|
||||||
if (pipe->dtype & XIOREAD_RECV_FROM) {
|
if (pipe->dtype & XIOREAD_RECV_FROM) {
|
||||||
|
/* Receiving packets in addresses of RECVFROM types, the sender address
|
||||||
|
has already been determined in OPEN phase. */
|
||||||
|
Debug1("%s(): XIOREAD_RECV and XIOREAD_RECV_FROM (peer checks already done)",
|
||||||
|
__func__);
|
||||||
#if WITH_RAWIP || WITH_UDP || WITH_UNIX
|
#if WITH_RAWIP || WITH_UDP || WITH_UNIX
|
||||||
struct msghdr msgh = {0};
|
struct msghdr msgh = {0};
|
||||||
union sockaddr_union from = {{0}};
|
union sockaddr_union from = {{0}};
|
||||||
|
@ -151,8 +155,7 @@ ssize_t xioread(xiofile_t *file, void *buff, size_t bufsiz) {
|
||||||
#if HAVE_STRUCT_MSGHDR_MSGCONTROLLEN
|
#if HAVE_STRUCT_MSGHDR_MSGCONTROLLEN
|
||||||
msgh.msg_controllen = sizeof(ctrlbuff);
|
msgh.msg_controllen = sizeof(ctrlbuff);
|
||||||
#endif
|
#endif
|
||||||
|
while ((rc = xiogetancillary(pipe->fd, &msgh,
|
||||||
while ((rc = xiogetpacketsrc(pipe->fd, &msgh,
|
|
||||||
MSG_PEEK
|
MSG_PEEK
|
||||||
#ifdef MSG_TRUNC
|
#ifdef MSG_TRUNC
|
||||||
|MSG_TRUNC
|
|MSG_TRUNC
|
||||||
|
@ -161,6 +164,9 @@ ssize_t xioread(xiofile_t *file, void *buff, size_t bufsiz) {
|
||||||
errno == EINTR) ;
|
errno == EINTR) ;
|
||||||
if (rc < 0) return -1;
|
if (rc < 0) return -1;
|
||||||
|
|
||||||
|
/* Note: we do not call xiodopacketinfo() and xiocheckpeer() here because
|
||||||
|
that already happened in xioopen() / _xioopen_dgram_recvfrom() ... */
|
||||||
|
|
||||||
do {
|
do {
|
||||||
bytes =
|
bytes =
|
||||||
Recvfrom(pipe->fd, buff, bufsiz, 0, &from.soa, &fromlen);
|
Recvfrom(pipe->fd, buff, bufsiz, 0, &from.soa, &fromlen);
|
||||||
|
@ -175,16 +181,22 @@ 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 defined(PF_PACKET) && !defined(PACKET_IGNORE_OUTGOING) && defined(PACKET_OUTGOING)
|
||||||
#if defined(PF_PACKET) && defined(PACKET_OUTGOING)
|
/* In future versions there may be an option that controls receiving of
|
||||||
|
outgoing packets, but currently it is hardcoded that we try to avoid
|
||||||
|
them - either by once setting socket option PACKET_IGNORE_OUTGOING
|
||||||
|
when available, otherwise by checking flag PACKET_OUTGOING per packet.
|
||||||
|
*/
|
||||||
if (from.soa.sa_family == PF_PACKET) {
|
if (from.soa.sa_family == PF_PACKET) {
|
||||||
if ((from.ll.sll_pkttype & PACKET_OUTGOING)
|
if ((from.ll.sll_pkttype & PACKET_OUTGOING) != 0) {
|
||||||
== 0) {
|
Info2("%s(fd=%d): ignoring outgoing packet", __func__, pipe->fd);
|
||||||
errno = EAGAIN; return -1;
|
errno = EAGAIN;
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
|
Debug2("%s(fd=%d): packet is not outgoing - process it", __func__, pipe->fd);
|
||||||
}
|
}
|
||||||
#endif /* defined(PF_PACKET) && defined(PACKET_OUTGOING) */
|
#endif /* defined(PF_PACKET) && !defined(PACKET_IGNORE_OUTGOING) && defined(PACKET_OUTGOING) */
|
||||||
|
|
||||||
Notice2("received packet with "F_Zu" bytes from %s",
|
Notice2("received packet with "F_Zu" bytes from %s",
|
||||||
bytes,
|
bytes,
|
||||||
|
@ -336,19 +348,24 @@ ssize_t xioread(xiofile_t *file, void *buff, size_t bufsiz) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#else /* !WITH_RAWIP */
|
#else /* !(WITH_RAWIP || WITH_UDP || WITH_UNIX) */
|
||||||
Fatal("address requires raw sockets, but they are not compiled in");
|
Fatal("address requires raw sockets, but they are not compiled in");
|
||||||
return -1;
|
return -1;
|
||||||
#endif /* !WITH_RAWIP || WITH_UDP || WITH_UNIX */
|
#endif /* !(WITH_RAWIP || WITH_UDP || WITH_UNIX) */
|
||||||
|
|
||||||
} else /* ~XIOREAD_RECV_FROM */ {
|
} else /* ~XIOREAD_RECV_FROM */ {
|
||||||
union sockaddr_union from; socklen_t fromlen = sizeof(from);
|
/* Receiving packets without planning to answer to the sender, but we
|
||||||
char infobuff[256];
|
might need sender info for some checks, thus we use recvfrom() */
|
||||||
struct msghdr msgh = {0};
|
struct msghdr msgh = {0};
|
||||||
|
union sockaddr_union from = {{ 0 }};
|
||||||
|
socklen_t fromlen = sizeof(from);
|
||||||
|
char infobuff[256];
|
||||||
char ctrlbuff[1024]; /* ancillary messages */
|
char ctrlbuff[1024]; /* ancillary messages */
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
socket_init(pipe->para.socket.la.soa.sa_family, &from);
|
Debug1("%s(): XIOREAD_RECV and not XIOREAD_RECV_FROM (peer checks to be done)",
|
||||||
|
__func__);
|
||||||
|
|
||||||
/* get source address */
|
/* get source address */
|
||||||
msgh.msg_name = &from;
|
msgh.msg_name = &from;
|
||||||
msgh.msg_namelen = fromlen;
|
msgh.msg_namelen = fromlen;
|
||||||
|
@ -358,7 +375,7 @@ ssize_t xioread(xiofile_t *file, void *buff, size_t bufsiz) {
|
||||||
#if HAVE_STRUCT_MSGHDR_MSGCONTROLLEN
|
#if HAVE_STRUCT_MSGHDR_MSGCONTROLLEN
|
||||||
msgh.msg_controllen = sizeof(ctrlbuff);
|
msgh.msg_controllen = sizeof(ctrlbuff);
|
||||||
#endif
|
#endif
|
||||||
while ((rc = xiogetpacketsrc(pipe->fd, &msgh,
|
while ((rc = xiogetancillary(pipe->fd, &msgh,
|
||||||
MSG_PEEK
|
MSG_PEEK
|
||||||
#ifdef MSG_TRUNC
|
#ifdef MSG_TRUNC
|
||||||
|MSG_TRUNC
|
|MSG_TRUNC
|
||||||
|
@ -390,9 +407,23 @@ ssize_t xioread(xiofile_t *file, void *buff, size_t bufsiz) {
|
||||||
errno = _errno;
|
errno = _errno;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if defined(PF_PACKET) && !defined(PACKET_IGNORE_OUTGOING) && defined(PACKET_OUTGOING)
|
||||||
|
/* For remarks see similar section above */
|
||||||
|
if (from.soa.sa_family == PF_PACKET) {
|
||||||
|
if ((from.ll.sll_pkttype & PACKET_OUTGOING) != 0) {
|
||||||
|
Info2("%s(fd=%d): ignoring outgoing packet", __func__, pipe->fd);
|
||||||
|
errno = EAGAIN;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
Debug2("%s(fd=%d): packet is not outgoing - process it", __func__, pipe->fd);
|
||||||
|
}
|
||||||
|
#endif /* defined(PF_PACKET) && !defined(PACKET_IGNORE_OUTGOING) && defined(PACKET_OUTGOING) */
|
||||||
|
|
||||||
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)));
|
||||||
|
|
||||||
if (bytes == 0) {
|
if (bytes == 0) {
|
||||||
if (!pipe->para.socket.null_eof) {
|
if (!pipe->para.socket.null_eof) {
|
||||||
errno = EAGAIN; return -1;
|
errno = EAGAIN; return -1;
|
||||||
|
|
Loading…
Reference in a new issue