ported generic socket to *BSD; minor improvements

This commit is contained in:
Gerhard Rieger 2008-08-17 23:28:11 +02:00
parent 8947cc92dc
commit 13b73776e7
37 changed files with 1441 additions and 258 deletions

View file

@ -1,5 +1,10 @@
new features:
added generic socket addresses: SOCKET-CONNECT, SOCKET-LISTEN,
SOCKET-SENDTO, SOCKET-RECVFROM, SOCKET-RECV, SOCKET-DATAGRAM allow
protocol independent socket handling; all parameters are explicitely
specified as numbers or hex data
added address options ioctl-void, ioctl-int, ioctl-intp, ioctl-string,
ioctl-bin for generic ioctl() calls.

View file

@ -1 +1 @@
"1.6.0.1+ip4bind+recvfromfork+x64+execstderr+execspaces+cosmetics+poll+udplistencont+ignoreeofunblock+ioctl+ioctl+setsockopt"
"1.6.0.1+ip4bind+recvfromfork+x64+execstderr+execspaces+cosmetics+poll+udplistencont+ignoreeofunblock+ioctl+setsockopt+genericsocket"

View file

@ -456,6 +456,7 @@
#undef WITH_IP4
#undef WITH_IP6
#undef WITH_RAWIP
#undef WITH_GENERICSOCKET
#undef WITH_TCP
#undef WITH_UDP
#undef WITH_LISTEN

View file

@ -196,6 +196,14 @@ 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 generic socket support)
AC_ARG_ENABLE(rawsocket, [ --disable-genericsocket disable generic socket support],
[case "$enableval" in
no) AC_MSG_RESULT(no);;
*) AC_DEFINE(WITH_GENERICSOCKET) AC_MSG_RESULT(yes);;
esac],
[AC_DEFINE(WITH_GENERICSOCKET) AC_MSG_RESULT(yes)])
AC_MSG_CHECKING(whether to include TCP support)
AC_ARG_ENABLE(tcp, [ --disable-tcp disable TCP support],
[case "$enableval" in

View file

@ -68,6 +68,7 @@ void dalan_init(void) {
/* read data description from line, write result to data; do not write
so much data that *p exceeds n !
p must be initialized to 0.
return 0 on success,
-1 if the data was cut due to n limit,
1 if a syntax error occurred

View file

@ -599,6 +599,144 @@ label(ADDRESS_READLINE)dit(bf(tt(READLINE)))
link(noecho)(OPTION_NOECHO)nl()
See also:
link(STDIO)(ADDRESS_STDIO)
label(ADDRESS_SOCKET_CONNECT)dit(bf(tt(SOCKET-CONNECT:<domain>:<protocol>:<remote-address>)))
Creates a stream socket using the first and second given socket parameters
and tt(SOCK_STREAM) (see man
socket(2)) and connects to the remote-address. The
two socket parameters have to be specified as numbers of type
link(int)(TYPE_INT). Consult your OS documentation and include files to find
the desired values. The remote-address must be the link(data)(TYPE_DATA)
representation of a sockaddr structure without the sa_family component.nl()
Please note that you can - beyond the options of the specified groups - also
apply options of higher level protocols when you use socat option
link(-s)(option_s).nl()
Option groups: link(FD)(GROUP_FD),link(SOCKET)(GROUP_SOCKET),link(CHILD)(GROUP_CHILD),link(RETRY)(GROUP_RETRY)nl()
Useful options:
link(bind)(OPTION_BIND),
link(setsockopt-int)(OPTION_SETSOCKOPT_INT),
link(setsockopt-bin)(OPTION_SETSOCKOPT_BIN),
link(setsockopt-string)(OPTION_SETSOCKOPT_STRING)
nl()
See also:
link(TCP)(ADDRESS_TCP_CONNECT),
link(UDP-CONNECT)(ADDRESS_UDP_CONNECT),
link(UNIX-CONNECT)(ADDRESS_UNIX_CONNECT),
link(SOCKET-LISTEN)(ADDRESS_SOCKET_LISTEN),
link(SOCKET-SENDTO)(ADDRESS_SOCKET_SENDTO)
label(ADDRESS_SOCKET_DATAGRAM)dit(bf(tt(SOCKET-DATAGRAM:<domain>:<type>:<protocol>:<remote-address>)))
Creates a datagram socket using the first three given socket parameters (see man
socket(2)) and sends outgoing data to the remote-address. The
three socket parameters have to be specified as numbers of type
link(int)(TYPE_INT). Consult your OS documentation and include files to find
the desired values. The remote-address must be the link(data)(TYPE_DATA)
representation of a sockaddr structure without the sa_family component.nl()
Please note that you can - beyond the options of the specified groups - also
apply options of higher level protocols when you use socat option
link(-s)(option_s).nl()
Option groups: link(FD)(GROUP_FD),link(SOCKET)(GROUP_SOCKET),link(RANGE)(GROUP_RANGE)
Useful options:
link(bind)(OPTION_BIND),
link(range)(OPTION_RANGE),
link(setsockopt-int)(OPTION_SETSOCKOPT_INT),
link(setsockopt-bin)(OPTION_SETSOCKOPT_BIN),
link(setsockopt-string)(OPTION_SETSOCKOPT_STRING)
nl()
See also:
link(UDP-DATAGRAM)(ADDRESS_UDP_DATAGRAM),
link(IP-DATAGRAM)(ADDRESS_IP_DATAGRAM),
link(SOCKET-SENDTO)(ADDRESS_SOCKET_SENDTO),
link(SOCKET-RECV)(ADDRESS_SOCKET_RECV),
link(SOCKET-RECVFROM)(ADDRESS_SOCKET_RECVFROM)
label(ADDRESS_SOCKET_LISTEN)dit(bf(tt(SOCKET-LISTEN:<domain>:<protocol>:<local-address>)))
Creates a stream socket using the first and second given socket parameters
and tt(SOCK_STREAM) (see man
socket(2)) and waits for incoming connections on local-address. The
two socket parameters have to be specified as numbers of type
link(int)(TYPE_INT). Consult your OS documentation and include files to find
the desired values. The local-address must be the link(data)(TYPE_DATA)
representation of a sockaddr structure without the sa_family component.nl()
Please note that you can - beyond the options of the specified groups - also
apply options of higher level protocols when you use socat option
link(-s)(option_s).nl()
Option groups: link(FD)(GROUP_FD),link(SOCKET)(GROUP_SOCKET),link(LISTEN)(GROUP_LISTEN),link(RANGE)(GROUP_RANGE),link(CHILD)(GROUP_CHILD),link(RETRY)(GROUP_RETRY)nl()
Useful options:
link(setsockopt-int)(OPTION_SETSOCKOPT_INT),
link(setsockopt-bin)(OPTION_SETSOCKOPT_BIN),
link(setsockopt-string)(OPTION_SETSOCKOPT_STRING)
nl()
See also:
link(TCP)(ADDRESS_TCP_LISTEN),
link(UDP-CONNECT)(ADDRESS_UDP_LISTEN),
link(UNIX-CONNECT)(ADDRESS_UNIX_LISTEN),
link(SOCKET-LISTEN)(ADDRESS_SOCKET_CONNECT),
link(SOCKET-SENDTO)(ADDRESS_SOCKET_RECVFROM),
link(SOCKET-SENDTO)(ADDRESS_SOCKET_RECV)
label(ADDRESS_SOCKET_RECV)dit(bf(tt(SOCKET_RECV:<domain>:<type>:<protocol>:<local-address>)))
Creates a socket using the three given socket parameters (see man
socket(2)) and binds it to <local-address>. Receives arriving data. The
three parameters have to be specified as numbers of type
link(int)(TYPE_INT). Consult your OS documentation and include files to find
the desired values. The local-address must be the link(data)(TYPE_DATA)
representation of a sockaddr structure without the sa_family component.nl()
Option groups: link(FD)(GROUP_FD),link(SOCKET)(GROUP_SOCKET),link(RANGE)(GROUP_RANGE)
Useful options:
link(range)(OPTION_RANGE),
link(setsockopt-int)(OPTION_SETSOCKOPT_INT),
link(setsockopt-bin)(OPTION_SETSOCKOPT_BIN),
link(setsockopt-string)(OPTION_SETSOCKOPT_STRING)
nl()
See also:
link(UDP-RECV)(ADDRESS_UDP_RECV),
link(IP-RECV)(ADDRESS_IP_RECV),
link(UNIX-RECV)(ADDRESS_UNIX_RECV),
link(SOCKET-DATAGRAM)(ADDRESS_SOCKET_DATAGRAM),
link(SOCKET-SENDTO)(ADDRESS_SOCKET_SENDTO),
link(SOCKET-RECVFROM)(ADDRESS_SOCKET_RECVFROM)
label(ADDRESS_SOCKET_RECVFROM)dit(bf(tt(SOCKET_RECVFROM:<domain>:<type>:<protocol>:<local-address>)))
Creates a socket using the three given socket parameters (see man
socket(2)) and binds it to <local-address>. Receives arriving data and sends
replies back to the sender. The first three parameters have to be specified as
numbers of type link(int)(TYPE_INT). Consult your OS documentation and
include files to find the desired values. The local-address must be the
link(data)(TYPE_DATA)
representation of a sockaddr structure without the sa_family component.nl()
Option groups: link(FD)(GROUP_FD),link(SOCKET)(GROUP_SOCKET),link(CHILD)(GROUP_CHILD),link(RANGE)(GROUP_RANGE)
Useful options:
link(fork)(OPTION_FORK),
link(range)(OPTION_RANGE),
link(setsockopt-int)(OPTION_SETSOCKOPT_INT),
link(setsockopt-bin)(OPTION_SETSOCKOPT_BIN),
link(setsockopt-string)(OPTION_SETSOCKOPT_STRING)
nl()
See also:
link(UDP-RECVFROM)(ADDRESS_UDP_RECVFROM),
link(IP-RECVFROM)(ADDRESS_IP_RECVFROM),
link(UNIX-RECVFROM)(ADDRESS_UNIX_RECVFROM),
link(SOCKET-DATAGRAM)(ADDRESS_SOCKET_DATAGRAM),
link(SOCKET-SENDTO)(ADDRESS_SOCKET_SENDTO),
link(SOCKET-RECV)(ADDRESS_SOCKET_RECV)
label(ADDRESS_SOCKET_SENDTO)dit(bf(tt(SOCKET_SENDTO:<domain>:<type>:<protocol>:<remote-address>)))
Creates a socket using the three given socket parameters (see man
socket(2)). Sends outgoing data to the given address and receives replies.
The three parameters have to be specified as
numbers of type link(int)(TYPE_INT). Consult your OS documentation and
include files to find the desired values. The remote-address must be the
link(data)(TYPE_DATA) representation of a sockaddr structure without the
sa_family component.nl()
Option groups: link(FD)(GROUP_FD),link(SOCKET)(GROUP_SOCKET)
Useful options:
link(bind)(OPTION_BIND),
link(setsockopt-int)(OPTION_SETSOCKOPT_INT),
link(setsockopt-bin)(OPTION_SETSOCKOPT_BIN),
link(setsockopt-string)(OPTION_SETSOCKOPT_STRING)
nl()
See also:
link(UDP-SENDTO)(ADDRESS_UDP_SENDTO),
link(IP-SENDTO)(ADDRESS_IP_SENDTO),
link(UNIX-SENDTO)(ADDRESS_UNIX_SENDTO),
link(SOCKET-DATAGRAM)(ADDRESS_SOCKET_DATAGRAM),
link(SOCKET-RECV)(ADDRESS_SOCKET_RECV)
link(SOCKET-RECVFROM)(ADDRESS_SOCKET_RECVFROM)
label(ADDRESS_SOCKS4)dit(bf(tt(SOCKS4:<socks-server>:<host>:<port>)))
Connects via <socks-server> [link(IP address)(TYPE_IP_ADDRESS)]
to <host> [link(IPv4 address)(TYPE_IPV4_ADDRESS)]

View file

@ -139,7 +139,7 @@ int statname(const char *file, int fd, int filetype, FILE *outfile) {
if (file) fprintf(outfile, " %s", file);
break;
case (S_IFSOCK>>12): /* 12, socket */
#if WITH_SOCKET
#if _WITH_SOCKET
if (fd >= 0) {
result = sockname(fd, outfile);
} else if (file) {
@ -150,7 +150,7 @@ int statname(const char *file, int fd, int filetype, FILE *outfile) {
#else
Error("SOCKET support not compiled in");
return -1;
#endif /* !WITH_SOCKET */
#endif /* !_WITH_SOCKET */
break;
}
/* ioctl() */
@ -185,7 +185,7 @@ int cdevname(int fd, FILE *outfile) {
}
#if WITH_SOCKET
#if _WITH_SOCKET
int sockname(int fd, FILE *outfile) {
#define FDNAME_OPTLEN 256
#define FDNAME_NAMELEN 256
@ -320,7 +320,7 @@ int sockname(int fd, FILE *outfile) {
#undef FDNAME_OPTLEN
#undef FDNAME_NAMELEN
}
#endif /* WITH_SOCKET */
#endif /* _WITH_SOCKET */

22
filan.c
View file

@ -1,5 +1,5 @@
/* source: filan.c */
/* Copyright Gerhard Rieger 2001-2007 */
/* Copyright Gerhard Rieger 2001-2008 */
/* Published under the GNU General Public License V.2, see file COPYING */
/* the subroutine filan makes a "FILe descriptor ANalysis". It checks the
@ -150,7 +150,7 @@ int filan_fd(int fd, FILE *outfile) {
}
}
#endif /* defined(FIONREAD) */
#if WITH_SOCKET && defined(MSG_DONTWAIT)
#if _WITH_SOCKET && defined(MSG_DONTWAIT)
if ((ufds.revents & POLLIN) && isasocket(fd)) {
char _peername[SOCKADDR_MAX];
struct sockaddr *pa = (struct sockaddr *)_peername;
@ -186,7 +186,7 @@ int filan_fd(int fd, FILE *outfile) {
fprintf(outfile, "recvmsg="F_Zd", ", bytes);
}
}
#endif /* WITH_SOCKET && defined(MSG_DONTWAIT) */
#endif /* _WITH_SOCKET && defined(MSG_DONTWAIT) */
}
}
}
@ -371,12 +371,12 @@ int filan_stat(
break;
#ifdef S_IFSOCK
case (S_IFSOCK): /* 12, socket */
#if WITH_SOCKET
#if _WITH_SOCKET
result = sockan(statfd, outfile);
#else
Warn("SOCKET support not compiled in");
return -1;
#endif /* !WITH_SOCKET */
#endif /* !_WITH_SOCKET */
break;
#endif /* S_IFSOCK */
}
@ -462,7 +462,7 @@ int cdevan(int fd, FILE *outfile) {
}
#if WITH_SOCKET
#if _WITH_SOCKET
int sockan(int fd, FILE *outfile) {
#define FILAN_OPTLEN 256
#define FILAN_NAMELEN 256
@ -634,7 +634,7 @@ int sockan(int fd, FILE *outfile) {
#undef FILAN_OPTLEN
#undef FILAN_NAMELEN
}
#endif /* WITH_SOCKET */
#endif /* _WITH_SOCKET */
#if WITH_IP4 || WITH_IP6
@ -823,7 +823,7 @@ int tcpan(int fd, FILE *outfile) {
#endif /* WITH_TCP */
#if WITH_SOCKET
#if _WITH_SOCKET
int sockoptan(int fd, const struct sockopt *optname, int socklay, FILE *outfile) {
#define FILAN_OPTLEN 256
char optval[FILAN_OPTLEN];
@ -859,10 +859,10 @@ int sockoptan(int fd, const struct sockopt *optname, int socklay, FILE *outfile)
return 0;
#undef FILAN_OPTLEN
}
#endif /* WITH_SOCKET */
#endif /* _WITH_SOCKET */
#if WITH_SOCKET
#if _WITH_SOCKET
int isasocket(int fd) {
int retval;
#if HAVE_STAT64
@ -883,7 +883,7 @@ int isasocket(int fd) {
/* note: when S_ISSOCK was undefined, it always gives 0 */
return S_ISSOCK(props.st_mode);
}
#endif /* WITH_SOCKET */
#endif /* _WITH_SOCKET */
const char *getfiletypestring(int st_mode) {

View file

@ -1,5 +1,5 @@
/* source: filan.h */
/* Copyright Gerhard Rieger 2001-2007 */
/* Copyright Gerhard Rieger 2001-2008 */
/* Published under the GNU General Public License V.2, see file COPYING */
@ -26,12 +26,12 @@ extern int filan_stat(
extern int cdevan(int fd, FILE *outfile);
#if WITH_SOCKET
#if _WITH_SOCKET
extern int isasocket(int fd);
extern int sockan(int fd, FILE *outfile);
extern int ipan(int fd, FILE *outfile);
extern int ip6an(int fd, FILE *outfile);
#endif /* WITH_SOCKET */
#endif /* _WITH_SOCKET */
extern int fdname(const char *file, int fd, FILE *outfile);

View file

@ -20,14 +20,14 @@
static int iffan(FILE *outfile);
int hostan(FILE *outfile) {
#if WITH_SOCKET
#if _WITH_SOCKET
fprintf(outfile, "\nIP INTERFACES\n");
iffan(outfile);
#endif
return 0;
}
#if WITH_SOCKET
#if _WITH_SOCKET
static int iffan(FILE *outfile) {
/* Linux: man 7 netdevice */
/* FreeBSD: man 4 networking */
@ -80,4 +80,4 @@ static int iffan(FILE *outfile) {
#endif /* defined(SIOCGIFINDEX) */
return 0;
}
#endif /* WITH_SOCKET */
#endif /* _WITH_SOCKET */

View file

@ -75,10 +75,25 @@ int procan_cdefs(FILE *outfile) {
#ifdef CSIZE
fprintf(outfile, "#define CSIZE 0%011o\n", CSIZE);
#endif
#ifdef TIOCEXCL
fprintf(outfile, "#define TIOCEXCL 0x%lx\n", (unsigned long)TIOCEXCL);
#endif
/* stdio constants */
#ifdef FOPEN_MAX
fprintf(outfile, "#define FOPEN_MAX %u\n", FOPEN_MAX);
#endif
/* socket constants */
#ifdef SOCK_DGRAM
fprintf(outfile, "#define SOCK_DGRAM %d\n", SOCK_DGRAM);
#endif
#ifdef SOL_SOCKET
fprintf(outfile, "#define SOL_SOCKET 0x%x\n", SOL_SOCKET);
#endif
#ifdef SO_REUSEADDR
fprintf(outfile, "#define SO_REUSEADDR %d\n", SO_REUSEADDR);
#endif
return 0;
}

View file

@ -1,6 +1,6 @@
#! /bin/bash
# source: readline-test.sh
# Copyright Gerhard Rieger 2003
# Copyright Gerhard Rieger 2003-2008
# Published under the GNU General Public License V.2, see file COPYING
# script that simulates a simple program with authentication.
@ -29,8 +29,9 @@ trap "$ECHO $0 got SIGQUIT" QUIT
# print banner
$ECHO "$BANNER"
read -r -p "$($ECHO "$USERPROMPT")" USERNAME
read -rs -p "$PWDPROMPT" PASSWORD
# on (some) ksh read -p does not mean prompt
$ECHO "$USERPROMPT\c"; read -r USERNAME
$ECHO "$PWDPROMPT\c"; read -rs PASSWORD
$ECHO
if [ "$USERNAME" != "$CREDUSER" -o "$PASSWORD" != "$CREDPASS" ]; then
@ -38,7 +39,7 @@ if [ "$USERNAME" != "$CREDUSER" -o "$PASSWORD" != "$CREDPASS" ]; then
exit -1
fi
while read -r -p "$PROMPT" COMMAND; do
while $ECHO "$PROMPT\c"; read -r COMMAND; do
if [ "$COMMAND" = "exit" ]; then
break;
fi

View file

@ -106,6 +106,7 @@ void socket_in6_init(struct sockaddr_in6 *sa) {
length of the specific socket address, or 0 on error. */
socklen_t socket_init(int af, union sockaddr_union *sa) {
switch (af) {
case AF_UNSPEC: memset(sa, 0, sizeof(*sa)); return sizeof(*sa);
#if WITH_UNIX
case AF_UNIX: socket_un_init(&sa->un); return sizeof(sa->un);
#endif
@ -134,6 +135,14 @@ char *sockaddr_info(const struct sockaddr *sa, socklen_t salen, char *buff, size
char *cp = lbuff;
int n;
#if HAVE_STRUCT_SOCKADDR_SALEN
if ((n = snprintf(cp, blen, "LEN=%d ", sa->sa_len)) < 0) {
Warn1("sockaddr_info(): buffer too short ("F_Zu")", blen);
*buff = '\0';
return buff;
}
cp += n, blen -= n;
#endif
if ((n = snprintf(cp, blen, "AF=%d ", sa->sa_family)) < 0) {
Warn1("sockaddr_info(): buffer too short ("F_Zu")", blen);
*buff = '\0';

View file

@ -15,6 +15,7 @@ union xioin6_u {
} ;
#endif /* WITH_IP6 */
#if _WITH_SOCKET
union sockaddr_union {
struct sockaddr soa;
#if WITH_UNIX
@ -27,29 +28,12 @@ union sockaddr_union {
struct sockaddr_in6 ip6;
#endif /* WITH_IP6 */
} ;
#if _WITH_IP4
struct xiorange_ip4 {
struct in_addr netaddr; /* network byte order */
struct in_addr netmask; /* network byte order */
} ;
#endif /* _WITH_IP4 */
#if _WITH_IP6
struct xiorange_ip6 {
struct in6_addr addr;
struct in6_addr mask;
} ;
#endif /* _WITH_IP4 */
#endif /* _WITH_SOCKET */
#if _WITH_SOCKET
union xiorange_union {
#if _WITH_IP4
struct xiorange_ip4 ip4;
#endif /* _WITH_IP4 */
#if _WITH_IP6
struct xiorange_ip6 ip6;
#endif /* _WITH_IP6 */
struct xiorange {
union sockaddr_union netaddr;
union sockaddr_union netmask;
} ;
#endif /* _WITH_SOCKET */

432
test.sh
View file

@ -141,14 +141,21 @@ SunOS)
BROADCASTIF="$MAINIF"
#BROADCASTIF=hme0
#BROADCASTIF=eri0
SECONDADDR=$($IFCONFIG $BROADCASTIF |grep 'inet ' |awk '{print($2);}')
BCIFADDR="$SECONDADDR"
BCADDR=$($IFCONFIG $BROADCASTIF |grep 'broadcast ' |sed 's/.*broadcast/broadcast/' |awk '{print($2);}') ;;
#SECONDADDR=$($IFCONFIG $BROADCASTIF |grep 'inet ' |awk '{print($2);}')
SECONDADDR=$(expr "$($IFCONFIG -a |grep 'inet ' |fgrep -v ' 127.0.0.1 '| head -n 1)" : '.*inet \([0-9.]*\) .*')
#BCIFADDR="$SECONDADDR"
#BCADDR=$($IFCONFIG $BROADCASTIF |grep 'broadcast ' |sed 's/.*broadcast/broadcast/' |awk '{print($2);}')
;;
#AIX|FreeBSD|Solaris)
*)
SECONDADDR=$(expr "$($IFCONFIG -a |grep 'inet ' |fgrep -v ' 127.0.0.1 '| head -n 1)" : '.*inet \([0-9.]*\) .*')
SECONDADDR=$(expr "$($IFCONFIG -a |grep 'inet ' |fgrep -v ' 127.0.0.1 ' |head -n 1)" : '.*inet \([0-9.]*\) .*')
;;
esac
# for generic sockets we need this address in hex form
if [ "$SECONDADDR" ]; then
SECONDADDRHEX="$(printf "%02x%02x%02x%02x\n" $(echo "$SECONDADDR" |tr '.' '
'))"
fi
# for some tests we need a second local IPv6 address
case "$UNAME" in
@ -184,20 +191,20 @@ vt100|vt320|linux|xterm|cons25|dtterm|aixterm|sun-color)
RED="\0033[31m"
GREEN="\0033[32m"
YELLOW="\0033[33m"
if false && [ "$UNAME" = SunOS ]; then
NORMAL="\0033[30m"
else
# if [ "$UNAME" = SunOS ]; then
# NORMAL="\0033[30m"
# else
NORMAL="\0033[39m"
fi
# fi
else
RED="\033[31m"
GREEN="\033[32m"
YELLOW="\033[33m"
if false && [ "$UNAME" = SunOS ]; then
NORMAL="\033[30m"
else
# if [ "$UNAME" = SunOS ]; then
# NORMAL="\033[30m"
# else
NORMAL="\033[39m"
fi
# fi
fi
OK="${GREEN}OK${NORMAL}"
FAILED="${RED}FAILED${NORMAL}"
@ -1509,9 +1516,11 @@ testod () {
local T="$6"; [ -z "$T" ] && T=0
local tf="$td/test$N.stdout"
local te="$td/test$N.stderr"
local tr="$td/test$N.ref"
local tdiff="$td/test$N.diff"
local dain="$(date) $RANDOM"
local daout="$(echo "$dain" |$OD_C)"
echo "$dain" |$OD_C >"$tr"
# local daout="$(echo "$dain" |$OD_C)"
$PRINTF "test $F_n %s... " $num "$title"
(psleep $T; echo "$dain"; psleep $T) |$SOCAT $opts "$arg1" "$arg2" >"$tf" 2>"$te"
if [ "$?" != 0 ]; then
@ -1519,7 +1528,8 @@ testod () {
echo "$SOCAT $opts $arg1 $arg2"
cat "$te"
numFAIL=$((numFAIL+1))
elif echo "$daout" |diff - "$tf" >"$tdiff" 2>&1; then
# elif echo "$daout" |diff - "$tf" >"$tdiff" 2>&1; then
elif diff "$tr" "$tf" >"$tdiff" 2>&1; then
$PRINTF "$OK\n"
if [ -n "$debug" ]; then cat $te; fi
numOK=$((numOK+1))
@ -1574,7 +1584,8 @@ ifprocess () {
FreeBSD) l="$(ps -faje |grep "^........ $(printf %5u $1)")" ;;
HP-UX) l="$(ps -fade |grep "^........ $(printf %5u $1)")" ;;
Linux) l="$(ps -fade |grep "^........ $(printf %5u $1)")" ;;
NetBSD) l="$(ps -aj |grep "^........ $(printf %4u $1)")" ;;
# NetBSD) l="$(ps -aj |grep "^........ $(printf %4u $1)")" ;;
NetBSD) l="$(ps -aj |grep "^[^ ][^ ]*[ ][ ]*$(printf %5u $1) ")" ;;
OpenBSD) l="$(ps -kaj |grep "^........ $(printf %5u $1)")" ;;
SunOS) l="$(ps -fade |grep "^........ $(printf %5u $1)")" ;;
*) l="$(ps -fade |grep "^[^ ][^ ]*[ ][ ]*$(printf %5u $1) ")" ;;
@ -1596,8 +1607,9 @@ childprocess () {
FreeBSD) l="$(ps -faje |grep "^........ ..... $(printf %5u $1)")" ;;
HP-UX) l="$(ps -fade |grep "^........ ..... $(printf %5u $1)")" ;;
Linux) l="$(ps -fade |grep "^........ ..... $(printf %5u $1)")" ;;
NetBSD) l="$(ps -aj |grep "^........ ..... $(printf %4u $1)")" ;;
OpenBSD) l="$(ps -kaj |grep "^........ ..... $(printf %5u $1)")" ;;
# NetBSD) l="$(ps -aj |grep "^........ ..... $(printf %4u $1)")" ;;
NetBSD) l="$(ps -aj |grep "^[^ ][^ ]*[ ][ ]*..... $(printf %5u $1)")" ;;
OpenBSD) l="$(ps -aj |grep "^........ ..... $(printf %5u $1)")" ;;
SunOS) l="$(ps -fade |grep "^........ ..... $(printf %5u $1)")" ;;
*) l="$(ps -fade |grep "^[^ ][^ ]*[ ][ ]*[0-9][0-9]**[ ][ ]*$(printf %5u $1) ")" ;; esac
if [ -z "$l" ]; then
@ -4387,7 +4399,7 @@ tr="$td/test$N.ref"
tdiff="$td/test$N.diff"
da="test$N $(date) $RANDOM"; da="$da$($ECHO '\r')"
# the feature that we really want to test is in the readline.sh script:
CMD="$SOCAT $opts open:$tpi,nonblock!!open:$tpo exec:\"./readline.sh -nh ./readline-test.sh\",pty,ctty,setsid,raw,echo=0,isig"
CMD="$SOCAT $opts -t1 open:$tpi,nonblock!!open:$tpo exec:\"./readline.sh -nh ./readline-test.sh\",pty,ctty,setsid,raw,echo=0,isig"
#echo "$CMD" >"$ts"
#chmod a+x "$ts"
printf "test $F_n $TEST... " $N
@ -4459,7 +4471,8 @@ else
if [ -n "$debug" ]; then cat $te; fi
numOK=$((numOK+1))
fi
#kill $pid 2>/dev/null
kill $pid 2>/dev/null # necc on OpenBSD
wait
MICROS=$SAVEMICS
TERM="$SAVETERM"
fi
@ -4857,7 +4870,13 @@ NAME=TCP4RANGEBITS
case "$TESTS" in
*%functions%*|*%security%*|*%tcp%*|*%tcp4%*|*%ip4%*|*%range%*|*%$NAME%*)
TEST="$NAME: security of TCP4-L with RANGE option"
if [ -z "$SECONDADDR" ]; then
# we need access to a second addresses
$PRINTF "test $F_n $TEST... ${YELLOW}need a second IPv4 address${NORMAL}\n" $N
numCANT=$((numCANT+1))
else
testserversec "$N" "$TEST" "$opts -s" "tcp4-l:$PORT,reuseaddr,fork,retry=1" "" "range=$SECONDADDR/32" "tcp4:127.0.0.1:$PORT" 4 tcp $PORT 0
fi ;; # $SECONDADDR
esac
PORT=$((PORT+1))
N=$((N+1))
@ -4866,6 +4885,22 @@ NAME=TCP4RANGEMASK
case "$TESTS" in
*%functions%*|*%security%*|*%tcp%*|*%tcp4%*|*%ip4%*|*%range%*|*%$NAME%*)
TEST="$NAME: security of TCP4-L with RANGE option"
if [ -z "$SECONDADDR" ]; then
# we need access to a second addresses
$PRINTF "test $F_n $TEST... ${YELLOW}need a second IPv4 address${NORMAL}\n" $N
numCANT=$((numCANT+1))
else
testserversec "$N" "$TEST" "$opts -s" "tcp4-l:$PORT,reuseaddr,fork,retry=1" "" "range=$SECONDADDR:255.255.255.255" "tcp4:127.0.0.1:$PORT" 4 tcp $PORT 0
fi ;; # $SECONDADDR
esac
PORT=$((PORT+1))
N=$((N+1))
# like TCP4RANGEMASK, but the "bad" address is within the same class A network
NAME=TCP4RANGEMASKHAIRY
case "$TESTS" in
*%functions%*|*%security%*|*%tcp%*|*%tcp4%*|*%ip4%*|*%range%*|*%$NAME%*)
TEST="$NAME: security of TCP4-L with RANGE option"
if [ "$UNAME" != Linux ]; then
# we need access to more loopback addresses
$PRINTF "test $F_n $TEST... ${YELLOW}only on Linux${NORMAL}\n" $N
@ -5544,7 +5579,7 @@ N=$((N+1))
signum () {
if [ ! "$BASH_VERSION" ]; then
# we expect:
for i in $(kill -l); do echo $i; done |grep -n -i $1 |cut -d: -f1
for i in $(POSIXLY_CORRECT=1 kill -l); do echo $i; done |grep -n -i "^$1$" |cut -d: -f1
else
# expect:
# " 1) SIGHUP 2) SIGINT 3) SIGQUIT 4) SIGILL"
@ -5566,12 +5601,12 @@ if ! feat=$(testaddrs pty); then
$PRINTF "test $F_n $TEST... ${YELLOW}$(echo $feat |tr a-z A-Z) not available${NORMAL}\n" $N
numCANT=$((numCANT+1))
else
SIG=$(signum $signam)
SIG="$(signum $signam)"
te="$td/test$N.stderr"
tpp="$td/test$N.ppid"
tp="$td/test$N.pid"
$PRINTF "test $F_n $TEST... " $N
(sleep 1; kill -$SIG $(cat "$tpp")) &
(sleep 1; kill -"$SIG" "$(cat "$tpp")") &
# a simple "system:echo $PPID..." does not work on NetBSD, OpenBSD
#$SOCAT $opts echo system:'exec /bin/bash -c "echo \$PPID '">$tpp"'; echo \$$ '">$tp; read x\"",nofork 2>"$te"; stat=$?
tsh="$td/test$N.sh"
@ -5929,10 +5964,13 @@ PORT=$((PORT+1))
N=$((N+1))
# test the UDP4-SENDTO and UDP4-RECVFROM addresses together
NAME=UDP4DGRAM
case "$TESTS" in
*%functions%*|*%udp%*|*%udp4%*|*%ip4%*|*%dgram%*|*%$NAME%*)
TEST="$NAME: UDP/IPv4 datagram"
TEST="$NAME: UDP/IPv4 sendto and recvfrom"
# start a UDP4-RECVFROM process that echoes data, and send test data using
# UDP4-SENDTO. The sent data should be returned.
tf="$td/test$N.stdout"
te="$td/test$N.stderr"
tdiff="$td/test$N.diff"
@ -5954,16 +5992,16 @@ kill "$pid1" 2>/dev/null; wait;
if [ "$rc2" -ne 0 ]; then
$PRINTF "$FAILED: $SOCAT:\n"
echo "$CMD1 &"
echo "$CMD2"
cat "${te}1"
echo "$CMD2"
cat "${te}2"
numFAIL=$((numFAIL+1))
elif ! echo "$da" |diff - "$tf" >"$tdiff"; then
$PRINTF "$FAILED\n"
cat "$tdiff"
echo "$CMD1 &"
echo "$CMD2"
cat "${te}1"
echo "$CMD2"
cat "${te}2"
numFAIL=$((numFAIL+1))
else
@ -8447,6 +8485,334 @@ esac
N=$((N+1))
# test the SOCKET-CONNECT address (against TCP4-LISTEN)
NAME=SOCKET_CONNECT
case "$TESTS" in
*%functions%*|*%generic%*|*%socket%*|*%$NAME%*)
TEST="$NAME: socket connect with TCP/IPv4"
# start a TCP4-LISTEN process that echoes data, and send test data using
# SOCKET-CONNECT, selecting TCP/IPv4. The sent data should be returned.
tf="$td/test$N.stdout"
te="$td/test$N.stderr"
tdiff="$td/test$N.diff"
ts0p=$PORT; PORT=$((PORT+1))
ts0a="127.0.0.1"
ts1p=$(printf "%04x" $ts0p);
ts1a="7f000001" # "127.0.0.1"
ts1="x${ts1p}${ts1a}x0000000000000000"
ts1b=$(printf "%04x" $PORT); PORT=$((PORT+1))
da="$(date) $RANDOM"
CMD0="$SOCAT $opts TCP4-LISTEN:$ts0p,reuseaddr,bind=$ts0a PIPE"
CMD1="$SOCAT $opts - SOCKET-CONNECT:2:6:$ts1,bind=x${ts1b}00000000x0000000000000000"
printf "test $F_n $TEST... " $N
$CMD0 2>"${te}0" &
pid0="$!"
waittcp4port $ts0p 1
echo "$da" |$CMD1 >>"$tf" 2>>"${te}1"
rc1="$?"
kill "$pid0" 2>/dev/null; wait;
if [ "$rc1" -ne 0 ]; then
$PRINTF "$FAILED: $SOCAT:\n"
echo "$CMD0 &"
cat "${te}0"
echo "$CMD1"
cat "${te}1"
numFAIL=$((numFAIL+1))
elif ! echo "$da" |diff - "$tf" >"$tdiff"; then
$PRINTF "$FAILED\n"
cat "$tdiff"
echo "$CMD0 &"
cat "${te}0"
echo "$CMD1"
cat "${te}1"
numFAIL=$((numFAIL+1))
else
$PRINTF "$OK\n"
if [ -n "$debug" ]; then cat $te; fi
numOK=$((numOK+1))
fi ;;
esac
PORT=$((PORT+1))
N=$((N+1))
# test the SOCKET-LISTEN address (with TCP4-CONNECT)
NAME=SOCKET_LISTEN
case "$TESTS" in
*%functions%*|*%generic%*|*%socket%*|*%$NAME%*)
TEST="$NAME: socket recvfrom with TCP/IPv4"
# start a SOCKET-LISTEN process that uses TCP/IPv4 and echoes data, and
# send test data using TCP4-CONNECT. The sent data should be returned.
tf="$td/test$N.stdout"
te="$td/test$N.stderr"
tdiff="$td/test$N.diff"
ts1p=$PORT; PORT=$((PORT+1))
ts1a="127.0.0.1"
ts0p=$(printf "%04x" $ts1p);
ts0a="7f000001" # "127.0.0.1"
ts0="x${ts0p}${ts0a}x0000000000000000"
ts1b=$PORT; PORT=$((PORT+1))
ts1="$ts1a:$ts1p"
da="$(date) $RANDOM"
CMD0="$SOCAT $opts SOCKET-LISTEN:2:6:$ts0,reuseaddr PIPE"
CMD1="$SOCAT $opts - TCP4-CONNECT:$ts1,bind=:$ts1b"
printf "test $F_n $TEST... " $N
$CMD0 2>"${te}0" &
pid0="$!"
#sleep 1
waittcp4port $ts1p 1
echo "$da" |$CMD1 >>"$tf" 2>>"${te}1"
rc1="$?"
kill "$pid0" 2>/dev/null; wait;
if [ "$rc1" -ne 0 ]; then
$PRINTF "$FAILED: $SOCAT:\n"
echo "$CMD0 &"
cat "${te}0"
echo "$CMD1"
cat "${te}1"
numFAIL=$((numFAIL+1))
elif ! echo "$da" |diff - "$tf" >"$tdiff"; then
$PRINTF "$FAILED\n"
cat "$tdiff"
echo "$CMD0 &"
cat "${te}0"
echo "$CMD1"
cat "${te}1"
numFAIL=$((numFAIL+1))
else
$PRINTF "$OK\n"
if [ -n "$debug" ]; then cat $te; fi
numOK=$((numOK+1))
fi ;;
esac
PORT=$((PORT+1))
N=$((N+1))
SOCK_DGRAM="$($PROCAN -c |grep "^#define[[:space:]]*SOCK_DGRAM[[:space:]]" |cut -d' ' -f3)"
# test the SOCKET-SENDTO address (against UDP4-RECVFROM)
NAME=SOCKET_SENDTO
case "$TESTS" in
*%functions%*|*%generic%*|*%socket%*|*%ip4%*|*%udp%*|*%dgram%*|*%$NAME%*)
TEST="$NAME: socket sendto with UDP/IPv4"
# start a UDP4-RECVFROM process that echoes data, and send test data using
# SOCKET-SENDTO, selecting UDP/IPv4. The sent data should be returned.
tf="$td/test$N.stdout"
te="$td/test$N.stderr"
tdiff="$td/test$N.diff"
ts0p=$PORT; PORT=$((PORT+1))
ts0a="127.0.0.1"
ts1p=$(printf "%04x" $ts0p);
ts1a="7f000001" # "127.0.0.1"
ts1="x${ts1p}${ts1a}x0000000000000000"
ts1b=$(printf "%04x" $PORT); PORT=$((PORT+1))
da="$(date) $RANDOM"
CMD0="$SOCAT $opts UDP4-RECVFROM:$ts0p,reuseaddr,bind=$ts0a PIPE"
CMD1="$SOCAT $opts - SOCKET-SENDTO:2:$SOCK_DGRAM:17:$ts1,bind=x${ts1b}x00000000x0000000000000000"
printf "test $F_n $TEST... " $N
$CMD0 2>"${te}0" &
pid0="$!"
waitudp4port $ts0p 1
echo "$da" |$CMD1 >>"$tf" 2>>"${te}1"
rc1="$?"
kill "$pid0" 2>/dev/null; wait;
if [ "$rc1" -ne 0 ]; then
$PRINTF "$FAILED: $SOCAT:\n"
echo "$CMD0 &"
cat "${te}0"
echo "$CMD1"
cat "${te}1"
numFAIL=$((numFAIL+1))
elif ! echo "$da" |diff - "$tf" >"$tdiff"; then
$PRINTF "$FAILED\n"
cat "$tdiff"
echo "$CMD0 &"
cat "${te}0"
echo "$CMD1"
cat "${te}1"
numFAIL=$((numFAIL+1))
else
$PRINTF "$OK\n"
if [ -n "$debug" ]; then cat $te; fi
numOK=$((numOK+1))
fi ;;
esac
PORT=$((PORT+1))
N=$((N+1))
# test the SOCKET-RECVFROM address (with UDP4-SENDTO)
NAME=SOCKET_RECVFROM
case "$TESTS" in
*%functions%*|*%generic%*|*%socket%*|*%ip4%*|*%udp%*|*%dgram%*|*%$NAME%*)
TEST="$NAME: socket recvfrom with UDP/IPv4"
# start a SOCKET-RECVFROM process that uses UDP/IPv4 and echoes data, and
# send test data using UDP4-SENDTO. The sent data should be returned.
tf="$td/test$N.stdout"
te="$td/test$N.stderr"
tdiff="$td/test$N.diff"
ts1p=$PORT; PORT=$((PORT+1))
ts1a="127.0.0.1"
ts0p=$(printf "%04x" $ts1p);
ts0a="7f000001" # "127.0.0.1"
ts0="x${ts0p}${ts0a}x0000000000000000"
ts1b=$PORT; PORT=$((PORT+1))
ts1="$ts1a:$ts1p"
da="$(date) $RANDOM"
CMD0="$SOCAT $opts SOCKET-RECVFROM:2:$SOCK_DGRAM:17:$ts0,reuseaddr PIPE"
CMD1="$SOCAT $opts - UDP4-SENDTO:$ts1,bind=:$ts1b"
printf "test $F_n $TEST... " $N
$CMD0 2>"${te}0" &
pid0="$!"
sleep 1 # waitudp4port $ts1p 1
echo "$da" |$CMD1 >>"$tf" 2>>"${te}1"
rc1="$?"
kill "$pid0" 2>/dev/null; wait;
if [ "$rc1" -ne 0 ]; then
$PRINTF "$FAILED: $SOCAT:\n"
echo "$CMD0 &"
cat "${te}0"
echo "$CMD1"
cat "${te}1"
numFAIL=$((numFAIL+1))
elif ! echo "$da" |diff - "$tf" >"$tdiff"; then
$PRINTF "$FAILED\n"
cat "$tdiff"
echo "$CMD0 &"
cat "${te}0"
echo "$CMD1"
cat "${te}1"
numFAIL=$((numFAIL+1))
else
$PRINTF "$OK\n"
if [ -n "$debug" ]; then cat $te; fi
numOK=$((numOK+1))
fi ;;
esac
PORT=$((PORT+1))
N=$((N+1))
# test the SOCKET-RECV address (with UDP4-SENDTO)
NAME=SOCKET_RECV
case "$TESTS" in
*%functions%*|*%generic%*|*%socket%*|*%ip4%*|*%udp%*|*%dgram%*|*%$NAME%*)
TEST="$NAME: socket recv with UDP/IPv4"
# start a SOCKET-RECV process that uses UPD/IPv4 and writes received data to file, and
# send test data using UDP4-SENDTO.
tf="$td/test$N.stdout"
te="$td/test$N.stderr"
tdiff="$td/test$N.diff"
ts1p=$PORT; PORT=$((PORT+1))
ts1a="127.0.0.1"
ts0p=$(printf "%04x" $ts1p);
ts0a="7f000001" # "127.0.0.1"
ts0="x${ts0p}${ts0a}x0000000000000000"
ts1b=$PORT; PORT=$((PORT+1))
ts1="$ts1a:$ts1p"
da="$(date) $RANDOM"
CMD0="$SOCAT $opts -u SOCKET-RECV:2:$SOCK_DGRAM:17:$ts0,reuseaddr -"
CMD1="$SOCAT $opts -u - UDP4-SENDTO:$ts1,bind=:$ts1b"
printf "test $F_n $TEST... " $N
$CMD0 2>"${te}0" >"$tf" &
pid0="$!"
sleep 1 # waitudp4port $ts1p 1
echo "$da" |$CMD1 2>>"${te}1"
rc1="$?"
sleep 1
kill "$pid0" 2>/dev/null; wait;
if [ "$rc1" -ne 0 ]; then
$PRINTF "$FAILED: $SOCAT:\n"
echo "$CMD0 &"
cat "${te}0"
echo "$CMD1"
cat "${te}1"
numFAIL=$((numFAIL+1))
elif ! echo "$da" |diff - "$tf" >"$tdiff"; then
$PRINTF "$FAILED\n"
cat "$tdiff"
echo "$CMD0 &"
cat "${te}0"
echo "$CMD1"
cat "${te}1"
numFAIL=$((numFAIL+1))
else
$PRINTF "$OK\n"
if [ -n "$debug" ]; then cat $te; fi
numOK=$((numOK+1))
fi ;;
esac
PORT=$((PORT+1))
N=$((N+1))
# test SOCKET-DATAGRAM (with UDP4-DATAGRAM)
NAME=SOCKET_DATAGRAM
case "$TESTS" in
*%functions%*|*%generic%*|*%socket%*|*%ip4%*|*%udp%*|*%dgram%*|*%$NAME%*)
TEST="$NAME: socket datagram via UDP/IPv4"
# start a UDP4-DATAGRAM process that echoes data, and send test data using
# SOCKET-DATAGRAM, selecting UDP/IPv4. The sent data should be returned.
tf="$td/test$N.stdout"
te="$td/test$N.stderr"
tdiff="$td/test$N.diff"
ts0p=$PORT; PORT=$((PORT+1))
ts1p=$PORT; PORT=$((PORT+1))
ts0a="127.0.0.1"
ts1b=$(printf "%04x" $ts0p);
ts1a="7f000001" # "127.0.0.1"
ts0b=$(printf "%04x" $ts0p)
ts1b=$(printf "%04x" $ts1p)
ts1="x${ts0b}${ts1a}x0000000000000000"
da="$(date) $RANDOM"
CMD0="$SOCAT $opts UDP4-DATAGRAM:$ts0a:$ts1p,bind=:$ts0p,reuseaddr PIPE"
CMD1="$SOCAT $opts - SOCKET-DATAGRAM:2:$SOCK_DGRAM:17:$ts1,bind=x${ts1b}x00000000x0000000000000000"
printf "test $F_n $TEST... " $N
$CMD0 2>"${te}0" &
pid0="$!"
waitudp4port $ts0p 1
echo "$da" |$CMD1 2>>"${te}1" >"$tf"
rc1="$?"
kill "$pid0" 2>/dev/null; wait;
if [ "$rc1" -ne 0 ]; then
$PRINTF "$FAILED: $SOCAT:\n"
echo "$CMD0 &"
cat "${te}0"
echo "$CMD1"
cat "${te}1"
numFAIL=$((numFAIL+1))
elif ! echo "$da" |diff - "$tf" >"$tdiff"; then
$PRINTF "$FAILED\n"
cat "$tdiff"
echo "$CMD0 &"
cat "${te}0"
echo "$CMD1"
cat "${te}1"
numFAIL=$((numFAIL+1))
else
$PRINTF "$OK\n"
if [ -n "$debug" ]; then cat $te; fi
numOK=$((numOK+1))
fi ;;
esac
PORT=$((PORT+1))
N=$((N+1))
NAME=SOCKETRANGEMASK
case "$TESTS" in
*%functions%*|*%security%*|*%generic%*|*%tcp%*|*%tcp4%*|*%ip4%*|*%socket%*|*%range%*|*%$NAME%*)
TEST="$NAME: security of generic socket-listen with RANGE option"
if [ -z "$SECONDADDR" ]; then
# we need access to more loopback addresses
$PRINTF "test $F_n $TEST... ${YELLOW}need a second IPv4 address${NORMAL}\n" $N
numCANT=$((numCANT+1))
else
ts1p=$(printf "%04x" $PORT);
testserversec "$N" "$TEST" "$opts -s" "SOCKET-LISTEN:2:6:x${ts1p}x00000000x0000000000000000,reuseaddr,fork,retry=1" "" "range=x0000x7f000000:x0000xffffffff" "SOCKET-CONNECT:2:6:x${ts1p}x${SECONDADDRHEX}x0000000000000000" 4 tcp $PORT 0
fi ;; # $SECONDADDR
esac
PORT=$((PORT+1))
N=$((N+1))
TIOCEXCL="$($PROCAN -c |grep "^#define[[:space:]]*TIOCEXCL[[:space:]]" |cut -d' ' -f3)"
# test the generic ioctl-void option
NAME=IOCTL_VOID
case "$TESTS" in
@ -8458,9 +8824,9 @@ TEST="$NAME: test the ioctl-void option"
# process 1 opens it with the TIOCEXCL ioctl;
# process 2 opens it too and fails with "device or resource busy" only when the
# previous ioctl was successful
if [ "$UNAME" != Linux ]; then
if [ -z "$TIOCEXCL" ]; then
# we use the numeric value of TIOCEXL which is system dependent
$PRINTF "test $F_n $TEST... ${YELLOW}only on Linux${NORMAL}\n" $N
$PRINTF "test $F_n $TEST... ${YELLOW}no value of TIOCEXCL${NORMAL}\n" $N
numCANT=$((numCANT+1))
else
tp="$td/test$N.pty"
@ -8469,7 +8835,7 @@ te="$td/test$N.stderr"
tdiff="$td/test$N.diff"
da="$(date)"
CMD0="$SOCAT $opts PTY,LINK=$tp pipe"
CMD1="$SOCAT $opts - file:$tp,ioctl-void=0x540c,raw,echo=0"
CMD1="$SOCAT $opts - file:$tp,ioctl-void=$TIOCEXCL,raw,echo=0"
CMD2="$SOCAT $opts - file:$tp,raw,echo=0"
printf "test $F_n $TEST... " $N
$CMD0 >/dev/null 2>"${te}0" &
@ -8504,6 +8870,9 @@ esac
N=$((N+1))
SOL_SOCKET="$($PROCAN -c |grep "^#define[[:space:]]*SOL_SOCKET[[:space:]]" |cut -d' ' -f3)"
SO_REUSEADDR="$($PROCAN -c |grep "^#define[[:space:]]*SO_REUSEADDR[[:space:]]" |cut -d' ' -f3)"
# test the generic setsockopt-int option
NAME=SETSOCKOPT_INT
case "$TESTS" in
@ -8518,9 +8887,9 @@ TEST="$NAME: test the setsockopt-int option"
# process 2 tries to listen on this port with SO_REUSEADDR, will fail if the
# (generically specified) SO_REUSEADDR socket options did not work
# process 3 connects to this port; only if it is successful the test is ok
if [ "$UNAME" != Linux ]; then
if [ -z "SO_REUSEADDR" ]; then
# we use the numeric value of SO_REUSEADDR which might be system dependent
$PRINTF "test $F_n $TEST... ${YELLOW}only on Linux${NORMAL}\n" $N
$PRINTF "test $F_n $TEST... ${YELLOW}value of SO_REUSEADDR not known${NORMAL}\n" $N
numCANT=$((numCANT+1))
else
tp="$PORT"
@ -8528,8 +8897,7 @@ tf="$td/test$N.stdout"
te="$td/test$N.stderr"
tdiff="$td/test$N.diff"
da="$(date)"
# level=SOL_SOCKET=1, optname=SO_REUSEADDR=2, value=1
CMD0="$SOCAT $opts TCP4-L:$tp,setsockopt-int=1:2:1 PIPE"
CMD0="$SOCAT $opts TCP4-L:$tp,setsockopt-int=$SOL_SOCKET:$SO_REUSEADDR:1 PIPE"
CMD1="$SOCAT $opts - TCP:localhost:$tp"
CMD2="$CMD0"
CMD3="$CMD1"

View file

@ -423,90 +423,4 @@ int xiogetaddrinfo(const char *node, const char *service,
return STAT_OK;
}
int xioparsenetwork(const char *rangename, int pf, union xiorange_union *range) {
#if WITH_IP4
struct in_addr *netaddr_in = &range->ip4.netaddr;
struct in_addr *netmask_in = &range->ip4.netmask;
#endif /* WITH_IP4 */
struct hostent *maskaddr;
char *delimpos; /* absolute address of delimiter */
int bits;
switch (pf) {
#if WITH_IP4
char *rangename1; /* a copy of rangename with writing allowed */
case PF_INET:
if ((rangename1 = strdup(rangename)) == NULL) {
Error1("strdup(\"%s\"): out of memory", rangename);
return STAT_RETRYLATER;
}
if (delimpos = strchr(rangename1, '/')) {
bits = strtoul(delimpos+1, NULL, 10);
netmask_in->s_addr = htonl((0xffffffff << (32-bits)));
} else if (delimpos = strchr(rangename1, ':')) {
if ((maskaddr = Gethostbyname(delimpos+1)) == NULL) {
Error2("gethostbyname(\"%s\"): %s", delimpos+1,
h_errno == NETDB_INTERNAL ? strerror(errno) :
hstrerror(h_errno));
return STAT_NORETRY;
}
netmask_in->s_addr = *(uint32_t *)maskaddr->h_addr_list[0];
} else {
Error1("xioparsenetwork(\"%s\",,): missing netmask delimiter", rangename);
free(rangename1);
return STAT_NORETRY;
}
{
struct hostent *nameaddr;
*delimpos = 0;
if ((nameaddr = Gethostbyname(rangename1)) == NULL) {
Error2("gethostbyname(\"%s\"): %s", rangename1,
h_errno == NETDB_INTERNAL ? strerror(errno) :
hstrerror(h_errno));
free(rangename1);
return STAT_NORETRY;
}
netaddr_in->s_addr = *(unsigned long *)nameaddr->h_addr_list[0];
}
free(rangename1);
break;
#endif /* WITH_IP4 */
#if WITH_IP6
case PF_INET6:
return xioparsenetwork_ip6(rangename, &range->ip6);
break;
#endif /* WITH_IP6 */
default:
Error1("range option not supported with address family %d", pf);
return STAT_NORETRY;
}
return STAT_OK;
}
/* parses a string of form address/bits or address:mask, and fills the fields
of the range union. The addr component is masked with mask. */
int parserange(const char *rangename, int pf, union xiorange_union *range) {
if (xioparsenetwork(rangename, pf, range) < 0) {
return -1;
}
switch (pf) {
#if WITH_IP4
case PF_INET:
range->ip4.netaddr.s_addr &= range->ip4.netmask.s_addr;
break;
#endif /* WITH_IP4 */
#if WITH_IP6
case PF_INET6:
return xiorange_ip6andmask(&range->ip6);
break;
#endif /* WITH_IP6 */
default:
Error1("range option not supported with address family %d", pf);
return STAT_NORETRY;
}
return 0;
}
#endif /* _WITH_IP4 || _WITH_IP6 */

View file

@ -1,5 +1,5 @@
/* source: xio-ip.h */
/* Copyright Gerhard Rieger 2001-2007 */
/* Copyright Gerhard Rieger 2001-2008 */
/* Published under the GNU General Public License V.2, see file COPYING */
#ifndef __xio_ip_h_included
@ -39,10 +39,5 @@ extern int xiogetaddrinfo(const char *node, const char *service,
int family, int socktype, int protocol,
union sockaddr_union *sa, socklen_t *socklen,
unsigned long res_opts0, unsigned long res_opts1);
extern
int xioparsenetwork(const char *rangename, int pf,
union xiorange_union *range);
extern
int parserange(const char *rangename, int pf, union xiorange_union *range);
#endif /* !defined(__xio_ip_h_included) */

View file

@ -1,5 +1,5 @@
/* source: xio-ip4.c */
/* Copyright Gerhard Rieger 2001-2007 */
/* Copyright Gerhard Rieger 2001-2008 */
/* Published under the GNU General Public License V.2, see file COPYING */
/* this file contains the source for IP4 related functions */
@ -13,11 +13,57 @@
#include "xio-ip.h"
#include "xio-ip4.h"
int xioparsenetwork_ip4(const char *rangename, struct xiorange *range) {
struct hostent *maskaddr;
struct in_addr *netaddr_in = &range->netaddr.ip4.sin_addr;
struct in_addr *netmask_in = &range->netmask.ip4.sin_addr;
char *rangename1; /* a copy of rangename with writing allowed */
char *delimpos; /* absolute address of delimiter */
int bits;
if ((rangename1 = strdup(rangename)) == NULL) {
Error1("strdup(\"%s\"): out of memory", rangename);
return STAT_RETRYLATER;
}
if (delimpos = strchr(rangename1, '/')) {
bits = strtoul(delimpos+1, NULL, 10);
netmask_in->s_addr = htonl((0xffffffff << (32-bits)));
} else if (delimpos = strchr(rangename1, ':')) {
if ((maskaddr = Gethostbyname(delimpos+1)) == NULL) {
Error2("gethostbyname(\"%s\"): %s", delimpos+1,
h_errno == NETDB_INTERNAL ? strerror(errno) :
hstrerror(h_errno));
return STAT_NORETRY;
}
netmask_in->s_addr = *(uint32_t *)maskaddr->h_addr_list[0];
} else {
Error1("xioparsenetwork_ip4(\"%s\",,): missing netmask delimiter", rangename);
free(rangename1);
return STAT_NORETRY;
}
{
struct hostent *nameaddr;
*delimpos = 0;
if ((nameaddr = Gethostbyname(rangename1)) == NULL) {
Error2("gethostbyname(\"%s\"): %s", rangename1,
h_errno == NETDB_INTERNAL ? strerror(errno) :
hstrerror(h_errno));
free(rangename1);
return STAT_NORETRY;
}
netaddr_in->s_addr = *(unsigned long *)nameaddr->h_addr_list[0];
}
free(rangename1);
return STAT_OK;
}
/* check if peer address is within permitted range.
return >= 0 if so. */
int xiocheckrange_ip4(struct sockaddr_in *pa, struct xiorange_ip4 *range) {
struct in_addr *netaddr_in = &range->netaddr;
struct in_addr *netmask_in = &range->netmask;
int xiocheckrange_ip4(struct sockaddr_in *pa, struct xiorange *range) {
struct in_addr *netaddr_in = &range->netaddr.ip4.sin_addr;
struct in_addr *netmask_in = &range->netmask.ip4.sin_addr;
char addrbuf[256], maskbuf[256];
char peername[256];

View file

@ -1,5 +1,5 @@
/* source: xio-ip4.h */
/* Copyright Gerhard Rieger 2001-2007 */
/* Copyright Gerhard Rieger 2001-2008 */
/* Published under the GNU General Public License V.2, see file COPYING */
#ifndef __xio_ip4_h_included
@ -8,6 +8,8 @@
extern const struct optdesc opt_ip4_add_membership;
extern
int xiocheckrange_ip4(struct sockaddr_in *pa, struct xiorange_ip4 *range);
int xioparsenetwork_ip4(const char *rangename, struct xiorange *range);
extern
int xiocheckrange_ip4(struct sockaddr_in *pa, struct xiorange *range);
#endif /* !defined(__xio_ip4_h_included) */

View file

@ -1,5 +1,5 @@
/* source: xio-ip6.c */
/* Copyright Gerhard Rieger 2001-2007 */
/* Copyright Gerhard Rieger 2001-2008 */
/* Published under the GNU General Public License V.2, see file COPYING */
/* this file contains the source for IP6 related functions */
@ -21,15 +21,15 @@ const struct optdesc opt_ipv6_v6only = { "ipv6-v6only", "ipv6only", OPT_IPV6_V6O
const struct optdesc opt_ipv6_join_group = { "ipv6-join-group", "join-group", OPT_IPV6_JOIN_GROUP, GROUP_SOCK_IP6, PH_PASTBIND, TYPE_IP_MREQN, OFUNC_SOCKOPT, SOL_IPV6, IPV6_JOIN_GROUP };
#endif
int xioparsenetwork_ip6(const char *rangename, struct xiorange_ip6 *range) {
int xioparsenetwork_ip6(const char *rangename, struct xiorange *range) {
char *delimpos; /* absolute address of delimiter */
size_t delimind; /* index of delimiter in string */
int bits;
char *baseaddr;
union sockaddr_union sockaddr;
socklen_t sockaddrlen = sizeof(sockaddr);
union xioin6_u *rangeaddr = (union xioin6_u *)&range->addr;
union xioin6_u *rangemask = (union xioin6_u *)&range->mask;
union xioin6_u *rangeaddr = (union xioin6_u *)&range->netaddr.ip6.sin6_addr;
union xioin6_u *rangemask = (union xioin6_u *)&range->netmask.ip6.sin6_addr;
union xioin6_u *nameaddr = (union xioin6_u *)&sockaddr.ip6.sin6_addr;
if (rangename[0] != '[' || rangename[strlen(rangename)-1] != ']') {
@ -87,7 +87,7 @@ int xioparsenetwork_ip6(const char *rangename, struct xiorange_ip6 *range) {
return 0;
}
int xiorange_ip6andmask(struct xiorange_ip6 *range) {
int xiorange_ip6andmask(struct xiorange *range) {
int i;
#if 0
range->addr.s6_addr32[0] &= range->mask.s6_addr32[0];
@ -96,7 +96,8 @@ int xiorange_ip6andmask(struct xiorange_ip6 *range) {
range->addr.s6_addr32[3] &= range->mask.s6_addr32[3];
#else
for (i = 0; i < 16; ++i) {
range->addr.s6_addr[i] &= range->mask.s6_addr[i];
range->netaddr.ip6.sin6_addr.s6_addr[i] &=
range->netmask.ip6.sin6_addr.s6_addr[i];
}
#endif
return 0;
@ -104,12 +105,12 @@ int xiorange_ip6andmask(struct xiorange_ip6 *range) {
/* check if peer address is within permitted range.
return >= 0 if so. */
int xiocheckrange_ip6(struct sockaddr_in6 *pa, struct xiorange_ip6 *range) {
int xiocheckrange_ip6(struct sockaddr_in6 *pa, struct xiorange *range) {
union xioin6_u masked;
int i;
char peername[256];
union xioin6_u *rangeaddr = (union xioin6_u *)&range->addr;
union xioin6_u *rangemask = (union xioin6_u *)&range->mask;
union xioin6_u *rangeaddr = (union xioin6_u *)&range->netaddr.ip6.sin6_addr;
union xioin6_u *rangemask = (union xioin6_u *)&range->netmask.ip6;
Debug16("permitted client subnet: [%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x]:[%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x]",
htons(rangeaddr->u6_addr16[0]), htons(rangeaddr->u6_addr16[1]),

View file

@ -1,5 +1,5 @@
/* source: xio-ip6.h */
/* Copyright Gerhard Rieger 2001-2007 */
/* Copyright Gerhard Rieger 2001-2008 */
/* Published under the GNU General Public License V.2, see file COPYING */
#ifndef __xio_ip6_h_included
@ -11,11 +11,11 @@ extern const struct optdesc opt_ipv6_v6only;
extern const struct optdesc opt_ipv6_join_group;
extern
int xioparsenetwork_ip6(const char *rangename, struct xiorange_ip6 *range);
extern int xiorange_ip6andmask(struct xiorange_ip6 *range);
int xioparsenetwork_ip6(const char *rangename, struct xiorange *range);
extern int xiorange_ip6andmask(struct xiorange *range);
extern
int xiocheckrange_ip6(struct sockaddr_in6 *pa, struct xiorange_ip6 *range);
int xiocheckrange_ip6(struct sockaddr_in6 *pa, struct xiorange *range);
#endif /* WITH_IP6 */

View file

@ -83,6 +83,9 @@ int
/* waits for incoming connection, checks its source address and port. Depending
on fork option, it may fork a subprocess.
pf specifies the syntax expected for range option. In the case of generic
socket it is 0 (expcting raw binary data), and the real pf can be obtained
from us->af_family; for other socket types pf == us->af_family
Returns 0 if a connection was accepted; with fork option, this is always in
a subprocess!
Other return values indicate a problem; this can happen in the master
@ -119,9 +122,9 @@ int _xioopen_listen(struct single *xfd, int xioflags, struct sockaddr *us, sockl
xiosetchilddied(); /* set SIGCHLD handler */
}
if ((xfd->fd = Socket(pf, socktype, proto)) < 0) {
if ((xfd->fd = Socket(us->sa_family, socktype, proto)) < 0) {
Msg4(level,
"socket(%d, %d, %d): %s", pf, socktype, proto, strerror(errno));
"socket(%d, %d, %d): %s", us->sa_family, socktype, proto, strerror(errno));
return STAT_RETRYLATER;
}
@ -161,15 +164,10 @@ int _xioopen_listen(struct single *xfd, int xioflags, struct sockaddr *us, sockl
}
#endif /* WITH_UNIX */
retropt_int(opts, OPT_BACKLOG, &backlog);
if (Listen(xfd->fd, backlog) < 0) {
Error3("listen(%d, %d): %s", xfd->fd, backlog, strerror(errno));
return STAT_RETRYLATER;
}
#if WITH_IP4 /*|| WITH_IP6*/
if (retropt_string(opts, OPT_RANGE, &rangename) >= 0) {
if (parserange(rangename, us->sa_family, &xfd->para.socket.range) < 0) {
if (xioparserange(rangename, pf, &xfd->para.socket.range)
< 0) {
free(rangename);
return STAT_NORETRY;
}
@ -189,6 +187,12 @@ int _xioopen_listen(struct single *xfd, int xioflags, struct sockaddr *us, sockl
retropt_bool(opts, OPT_LOWPORT, &xfd->para.socket.ip.lowport);
#endif /* WITH_TCP || WITH_UDP */
retropt_int(opts, OPT_BACKLOG, &backlog);
if (Listen(xfd->fd, backlog) < 0) {
Error3("listen(%d, %d): %s", xfd->fd, backlog, strerror(errno));
return STAT_RETRYLATER;
}
if (xioopts.logopt == 'm') {
Info("starting accept loop, switching to syslog");
diag_set('y', xioopts.syslogfac); xioopts.logopt = 'y';

View file

@ -170,7 +170,7 @@ int xioopen_rawip_datagram(int argc, const char *argv[], struct opt *opts,
/* which reply packets will be accepted - determine by range option */
if (retropt_string(opts, OPT_RANGE, &rangename) >= 0) {
if (parserange(rangename, pf, &xfd->para.socket.range) < 0) {
if (xioparserange(rangename, pf, &xfd->para.socket.range) < 0) {
free(rangename);
return STAT_NORETRY;
}
@ -287,7 +287,8 @@ int xioopen_rawip_recv(int argc, const char *argv[], struct opt *opts,
#endif
}
if (retropt_bind(opts, pf, socktype, ipproto, &/*us.soa*/xfd->stream.para.socket.la.soa, &uslen, 1,
if (retropt_bind(opts, pf, socktype, ipproto,
&/*us.soa*/xfd->stream.para.socket.la.soa, &uslen, 1,
xfd->stream.para.socket.ip.res_opts[0],
xfd->stream.para.socket.ip.res_opts[1]) ==
STAT_OK) {
@ -300,7 +301,8 @@ int xioopen_rawip_recv(int argc, const char *argv[], struct opt *opts,
xfd->stream.dtype = XIODATA_RECV_SKIPIP;
result =
_xioopen_dgram_recv(&xfd->stream, xioflags,
needbind?&xfd->stream.para.socket.la.soa:NULL, uslen,
needbind?&/*us.soa*/xfd->stream.para.socket.la.soa:NULL,
uslen,
opts, pf, socktype, ipproto, E_ERROR);
_xio_openlate(&xfd->stream, opts);
return result;

View file

@ -2,7 +2,8 @@
/* Copyright Gerhard Rieger 2001-2008 */
/* Published under the GNU General Public License V.2, see file COPYING */
/* this file contains the source for socket related functions */
/* this file contains the source for socket related functions, and the
implementation of generic socket addresses */
#include "xiosysincludes.h"
@ -18,9 +19,54 @@
#include "xio-ip6.h"
#endif /* WITH_IP6 */
#include "xio-ip.h"
#include "xio-listen.h"
#include "xio-ipapp.h" /*! not clean */
#include "xio-tcpwrap.h"
static
int xioopen_socket_connect(int argc, const char *argv[], struct opt *opts,
int xioflags, xiofile_t *xfd, unsigned groups,
int dummy1, int dummy2, int dummy3);
static
int xioopen_socket_listen(int argc, const char *argv[], struct opt *opts,
int xioflags, xiofile_t *xfd, unsigned groups,
int dummy1, int dummy2, int dummy3);
static
int xioopen_socket_sendto(int argc, const char *argv[], struct opt *opts,
int xioflags, xiofile_t *xfd, unsigned groups,
int dummy1, int dummy2, int dummy3);
static
int xioopen_socket_datagram(int argc, const char *argv[], struct opt *opts,
int xioflags, xiofile_t *xfd, unsigned groups,
int dummy1, int dummy2, int dummy3);
static
int xioopen_socket_recvfrom(int argc, const char *argv[], struct opt *opts,
int xioflags, xiofile_t *xfd, unsigned groups,
int dummy1, int socktype, int dummy3);
static
int xioopen_socket_recv(int argc, const char *argv[], struct opt *opts,
int xioflags, xiofile_t *xfd, unsigned groups,
int dumy1, int dummy2, int dummy3);
static
int _xioopen_socket_sendto(const char *pfname, const char *type,
const char *proto, const char *address,
struct opt *opts, int xioflags, xiofile_t *xxfd,
unsigned groups);
/* generic socket addresses */
const struct addrdesc xioaddr_socket_connect = { "socket-connect", 1, xioopen_socket_connect, GROUP_FD|GROUP_SOCKET|GROUP_CHILD|GROUP_RETRY, 0, 0, 0 HELP(":<domain>:<protocol>:<remote-address>") };
const struct addrdesc xioaddr_socket_listen = { "socket-listen", 1, xioopen_socket_listen, GROUP_FD|GROUP_SOCKET|GROUP_LISTEN|GROUP_RANGE|GROUP_CHILD|GROUP_RETRY, 0, 0, 0 HELP(":<domain>:<protocol>:<local-address>") };
const struct addrdesc xioaddr_socket_sendto = { "socket-sendto", 3, xioopen_socket_sendto, GROUP_FD|GROUP_SOCKET, 0, 0, 0 HELP(":<domain>:<type>:<protocol>:<remote-address>") };
const struct addrdesc xioaddr_socket_datagram= { "socket-datagram", 3, xioopen_socket_datagram, GROUP_FD|GROUP_SOCKET|GROUP_RANGE, 0, 0, 0 HELP(":<domain>:<type>:<protocol>:<remote-address>") };
const struct addrdesc xioaddr_socket_recvfrom= { "socket-recvfrom", 3, xioopen_socket_recvfrom, GROUP_FD|GROUP_SOCKET|GROUP_RANGE|GROUP_CHILD, 0, 0, 0 HELP(":<domain>:<type>:<protocol>:<local-address>") };
const struct addrdesc xioaddr_socket_recv = { "socket-recv", 1, xioopen_socket_recv, GROUP_FD|GROUP_SOCKET|GROUP_RANGE, 0, 0, 0 HELP(":<domain>:<type>:<protocol>:<local-address>") };
/* the following options apply not only to generic socket addresses but to all
addresses that have anything to do with sockets */
const struct optdesc opt_so_debug = { "so-debug", "debug", OPT_SO_DEBUG, GROUP_SOCKET, PH_PASTSOCKET, TYPE_INT, OFUNC_SOCKOPT, SOL_SOCKET, SO_DEBUG };
#ifdef SO_ACCEPTCONN /* AIX433 */
const struct optdesc opt_so_acceptconn={ "so-acceptconn","acceptconn",OPT_SO_ACCEPTCONN,GROUP_SOCKET,PH_PASTSOCKET,TYPE_INT, OFUNC_SOCKOPT, SOL_SOCKET, SO_ACCEPTCONN};
@ -133,6 +179,498 @@ const struct optdesc opt_setsockopt_int = { "setsockopt-int", "sockopt-int
const struct optdesc opt_setsockopt_bin = { "setsockopt-bin", "sockopt-bin", OPT_SETSOCKOPT_BIN, GROUP_SOCKET,PH_PASTSOCKET,TYPE_INT_INT_BIN, OFUNC_SOCKOPT_GENERIC, 0, 0 };
const struct optdesc opt_setsockopt_string = { "setsockopt-string", "sockopt-string", OPT_SETSOCKOPT_STRING, GROUP_SOCKET,PH_PASTSOCKET,TYPE_INT_INT_STRING, OFUNC_SOCKOPT_GENERIC, 0, 0 };
static
int xioopen_socket_connect(int argc, const char *argv[], struct opt *opts,
int xioflags, xiofile_t *xxfd, unsigned groups,
int dummy1, int dummy2, int dummy3) {
struct single *xfd = &xxfd->stream;
const char *pfname = argv[1];
const char *protname = argv[2];
const char *address = argv[3];
char *garbage;
int pf;
int proto;
int socktype = SOCK_STREAM;
int needbind = 0;
union sockaddr_union them; socklen_t themlen;
union sockaddr_union us; socklen_t uslen = sizeof(us);
int result;
if (argc != 4) {
Error2("%s: wrong number of parameters (%d instead of 3)",
argv[0], argc-1);
return STAT_NORETRY;
}
pf = strtoul(pfname, &garbage, 0);
if (*garbage != '\0') {
Warn1("garbage in parameter: \"%s\"", garbage);
}
proto = strtoul(protname, &garbage, 0);
if (*garbage != '\0') {
Warn1("garbage in parameter: \"%s\"", garbage);
}
retropt_socket_pf(opts, &pf);
retropt_int(opts, OPT_SO_TYPE, &socktype);
/*retropt_int(opts, OPT_IP_PROTOCOL, &proto);*/
xfd->howtoend = END_SHUTDOWN;
applyopts(-1, opts, PH_INIT);
if (applyopts_single(xfd, opts, PH_INIT) < 0) return -1;
applyopts(-1, opts, PH_EARLY);
themlen = 0;
if ((result =
dalan(address, (char *)&them.soa.sa_data, &themlen, sizeof(them)))
< 0) {
Error1("data too long: \"%s\"", address);
} else if (result > 0) {
Error1("syntax error in \"%s\"", address);
}
them.soa.sa_family = pf;
themlen +=
#if HAVE_STRUCT_SOCKADDR_SALEN
sizeof(them.soa.sa_len) +
#endif
sizeof(them.soa.sa_family);
xfd->dtype = XIOREAD_STREAM|XIOWRITE_STREAM;
socket_init(0, &us);
if (retropt_bind(opts, 0 /*pf*/, socktype, proto, (struct sockaddr *)&us, &uslen, 3,
0, 0)
!= STAT_NOACTION) {
needbind = true;
us.soa.sa_family = pf;
}
if ((result =
xioopen_connect(xfd,
needbind?(struct sockaddr *)&us:NULL, uslen,
(struct sockaddr *)&them, themlen,
opts, pf, socktype, proto, false)) != 0) {
return result;
}
if ((result = _xio_openlate(xfd, opts)) < 0) {
return result;
}
return STAT_OK;
}
static
int xioopen_socket_listen(int argc, const char *argv[], struct opt *opts,
int xioflags, xiofile_t *xxfd, unsigned groups,
int dummy1, int dummy2, int dummy3) {
struct single *xfd = &xxfd->stream;
const char *pfname = argv[1];
const char *protname = argv[2];
const char *usname = argv[3];
char *garbage;
int pf;
int proto;
int socktype = SOCK_STREAM;
union sockaddr_union us; socklen_t uslen;
struct opt *opts0;
int result;
if (argc != 4) {
Error2("%s: wrong number of parameters (%d instead of 3)",
argv[0], argc-1);
return STAT_NORETRY;
}
pf = strtoul(pfname, &garbage, 0);
if (*garbage != '\0') {
Warn1("garbage in parameter: \"%s\"", garbage);
}
proto = strtoul(protname, &garbage, 0);
if (*garbage != '\0') {
Warn1("garbage in parameter: \"%s\"", garbage);
}
retropt_socket_pf(opts, &pf);
retropt_int(opts, OPT_SO_TYPE, &socktype);
/*retropt_int(opts, OPT_IP_PROTOCOL, &proto);*/
xfd->howtoend = END_SHUTDOWN;
socket_init(0, &us);
uslen = 0;
if ((result =
dalan(usname, (char *)&us.soa.sa_data, &uslen, sizeof(us)))
< 0) {
Error1("data too long: \"%s\"", usname);
} else if (result > 0) {
Error1("syntax error in \"%s\"", usname);
}
uslen += sizeof(us.soa.sa_family)
#if HAVE_STRUCT_SOCKADDR_SALEN
+ sizeof(us.soa.sa_len)
#endif
;
us.soa.sa_family = pf;
if (applyopts_single(xfd, opts, PH_INIT) < 0) return -1;
applyopts(-1, opts, PH_INIT);
applyopts(-1, opts, PH_EARLY);
opts0 = copyopts(opts, GROUP_ALL);
if ((result =
xioopen_listen(xfd, xioflags,
(struct sockaddr *)&us, uslen,
opts, opts0, 0/*instead of pf*/, socktype, proto))
!= STAT_OK)
return result;
return STAT_OK;
}
/* we expect the form: ...:domain:type:protocol:remote-address */
static
int xioopen_socket_sendto(int argc, const char *argv[], struct opt *opts,
int xioflags, xiofile_t *xxfd, unsigned groups,
int dummy1, int dummy2, int dummy3) {
int result;
if (argc != 5) {
Error2("%s: wrong number of parameters (%d instead of 4)",
argv[0], argc-1);
return STAT_NORETRY;
}
if ((result =
_xioopen_socket_sendto(argv[1], argv[2], argv[3], argv[4],
opts, xioflags, xxfd, groups))
!= STAT_OK) {
return result;
}
_xio_openlate(&xxfd->stream, opts);
return STAT_OK;
}
static
int _xioopen_socket_sendto(const char *pfname, const char *type,
const char *protname, const char *address,
struct opt *opts, int xioflags, xiofile_t *xxfd,
unsigned groups) {
xiosingle_t *xfd = &xxfd->stream;
char *garbage;
union sockaddr_union us = {{0}};
socklen_t uslen = 0;
socklen_t themlen = 0;
int pf;
int socktype = SOCK_RAW;
int proto;
bool needbind = false;
char *bindstring = NULL;
int result;
pf = strtoul(pfname, &garbage, 0);
if (*garbage != '\0') {
Warn1("garbage in parameter: \"%s\"", garbage);
}
socktype = strtoul(type, &garbage, 0);
if (*garbage != '\0') {
Warn1("garbage in parameter: \"%s\"", garbage);
}
proto = strtoul(protname, &garbage, 0);
if (*garbage != '\0') {
Warn1("garbage in parameter: \"%s\"", garbage);
}
retropt_socket_pf(opts, &pf);
retropt_int(opts, OPT_SO_TYPE, &socktype);
/*retropt_int(opts, OPT_IP_PROTOCOL, &proto);*/
xfd->howtoend = END_SHUTDOWN;
xfd->peersa.soa.sa_family = pf;
themlen = 0;
if ((result =
dalan(address, (char *)&xfd->peersa.soa.sa_data, &themlen,
sizeof(xfd->peersa)))
< 0) {
Error1("data too long: \"%s\"", address);
} else if (result > 0) {
Error1("syntax error in \"%s\"", address);
}
xfd->salen = themlen + sizeof(sa_family_t)
#if HAVE_STRUCT_SOCKADDR_SALEN
+ sizeof(xfd->peersa.soa.sa_len)
#endif
;
#if HAVE_STRUCT_SOCKADDR_SALEN
xfd->peersa.soa.sa_len =
sizeof(xfd->peersa.soa.sa_len) + sizeof(xfd->peersa.soa.sa_family) +
themlen;
#endif
/* ...res_opts[] */
if (applyopts_single(xfd, opts, PH_INIT) < 0) return -1;
applyopts(-1, opts, PH_INIT);
if (pf == PF_UNSPEC) {
pf = xfd->peersa.soa.sa_family;
}
xfd->dtype = XIODATA_RECVFROM;
if (retropt_string(opts, OPT_BIND, &bindstring) == 0) {
uslen = 0;
if ((result =
dalan(bindstring, (char *)&us.soa.sa_data, &uslen, sizeof(us)))
< 0) {
Error1("data too long: \"%s\"", bindstring);
} else if (result > 0) {
Error1("syntax error in \"%s\"", bindstring);
}
us.soa.sa_family = pf;
uslen += sizeof(sa_family_t)
#if HAVE_STRUCT_SOCKADDR_SALEN
+ sizeof(us.soa.sa_len)
#endif
;
needbind = true;
}
return
_xioopen_dgram_sendto(needbind?&us:NULL, uslen,
opts, xioflags, xfd, groups, pf, socktype, proto);
}
/* we expect the form: ...:domain:socktype:protocol:local-address */
static
int xioopen_socket_recvfrom(int argc, const char *argv[], struct opt *opts,
int xioflags, xiofile_t *xxfd, unsigned groups,
int dummy, int summy2, int dummy3) {
struct single *xfd = &xxfd->stream;
const char *pfname = argv[1];
const char *typename = argv[2];
const char *protname = argv[3];
const char *address = argv[4];
char *garbage;
union sockaddr_union *us = &xfd->para.socket.la;
socklen_t uslen = sizeof(*us);
int pf, socktype, proto;
char *rangename;
int result;
if (argc != 5) {
Error2("%s: wrong number of parameters (%d instead of 4)",
argv[0], argc-1);
return STAT_NORETRY;
}
pf = strtoul(pfname, &garbage, 0);
if (*garbage != '\0') {
Warn1("garbage in parameter: \"%s\"", garbage);
}
socktype = strtoul(typename, &garbage, 0);
if (*garbage != '\0') {
Warn1("garbage in parameter: \"%s\"", garbage);
}
proto = strtoul(protname, &garbage, 0);
if (*garbage != '\0') {
Warn1("garbage in parameter: \"%s\"", garbage);
}
retropt_socket_pf(opts, &pf);
retropt_int(opts, OPT_SO_TYPE, &socktype);
/*retropt_int(opts, OPT_IP_PROTOCOL, &proto);*/
xfd->howtoend = END_NONE;
uslen = 0;
if ((result =
dalan(address, (char *)&us->soa.sa_data, &uslen, sizeof(*us)))
< 0) {
Error1("data too long: \"%s\"", address);
} else if (result > 0) {
Error1("syntax error in \"%s\"", address);
}
us->soa.sa_family = pf;
uslen += sizeof(us->soa.sa_family)
#if HAVE_STRUCT_SOCKADDR_SALEN
+ sizeof(us->soa.sa_len);
#endif
;
xfd->dtype = XIOREAD_RECV|XIOWRITE_SENDTO;
if (retropt_string(opts, OPT_RANGE, &rangename) >= 0) {
if (xioparserange(rangename, 0, &xfd->para.socket.range) < 0) {
return STAT_NORETRY;
}
xfd->para.socket.dorange = true;
free(rangename);
}
if ((result =
_xioopen_dgram_recvfrom(xfd, xioflags, &us->soa, uslen,
opts, pf, socktype, proto, E_ERROR))
!= STAT_OK) {
return result;
}
_xio_openlate(xfd, opts);
return STAT_OK;
}
/* we expect the form: ...:domain:type:protocol:local-address */
static
int xioopen_socket_recv(int argc, const char *argv[], struct opt *opts,
int xioflags, xiofile_t *xxfd, unsigned groups,
int dummy1, int dummy2, int dummy3) {
struct single *xfd = &xxfd->stream;
const char *pfname = argv[1];
const char *typename = argv[2];
const char *protname = argv[3];
const char *address = argv[4];
char *garbage;
union sockaddr_union us;
socklen_t uslen = sizeof(us);
int pf, socktype, proto;
char *rangename;
int result;
if (argc != 5) {
Error2("%s: wrong number of parameters (%d instead of 4)",
argv[0], argc-1);
return STAT_NORETRY;
}
pf = strtoul(pfname, &garbage, 0);
if (*garbage != '\0') {
Warn1("garbage in parameter: \"%s\"", garbage);
}
socktype = strtoul(typename, &garbage, 0);
if (*garbage != '\0') {
Warn1("garbage in parameter: \"%s\"", garbage);
}
proto = strtoul(protname, &garbage, 0);
if (*garbage != '\0') {
Warn1("garbage in parameter: \"%s\"", garbage);
}
retropt_socket_pf(opts, &pf);
retropt_int(opts, OPT_SO_TYPE, &socktype);
/*retropt_int(opts, OPT_IP_PROTOCOL, &proto);*/
xfd->howtoend = END_NONE;
uslen = 0;
if ((result =
dalan(address, (char *)&us.soa.sa_data, &uslen, sizeof(us)))
< 0) {
Error1("data too long: \"%s\"", address);
} else if (result > 0) {
Error1("syntax error in \"%s\"", address);
}
us.soa.sa_family = pf;
uslen += sizeof(sa_family_t)
#if HAVE_STRUCT_SOCKADDR_SALEN
+sizeof(us.soa.sa_len)
#endif
;
xfd->dtype = XIOREAD_RECV;
xfd->para.socket.la.soa.sa_family = pf;
if (retropt_string(opts, OPT_RANGE, &rangename) >= 0) {
if (xioparserange(rangename, 0, &xfd->para.socket.range) < 0) {
return STAT_NORETRY;
}
xfd->para.socket.dorange = true;
free(rangename);
}
if ((result =
_xioopen_dgram_recv(xfd, xioflags, &us.soa,
uslen, opts, pf, socktype, proto, E_ERROR))
!= STAT_OK) {
return result;
}
_xio_openlate(xfd, opts);
return STAT_OK;
}
/* we expect the form: ...:domain:type:protocol:remote-address */
static
int xioopen_socket_datagram(int argc, const char *argv[], struct opt *opts,
int xioflags, xiofile_t *xxfd, unsigned groups,
int dummy1, int dummy2, int dummy3) {
xiosingle_t *xfd = &xxfd->stream;
const char *pfname = argv[1];
const char *typename = argv[2];
const char *protname = argv[3];
const char *address = argv[4];
char *garbage;
char *rangename;
socklen_t themlen;
int pf;
int result;
if (argc != 5) {
Error2("%s: wrong number of parameters (%d instead of 4)",
argv[0], argc-1);
return STAT_NORETRY;
}
pf = strtoul(pfname, &garbage, 0);
if (*garbage != '\0') {
Warn1("garbage in parameter: \"%s\"", garbage);
}
retropt_socket_pf(opts, &pf);
/*retropt_int(opts, OPT_IP_PROTOCOL, &proto);*/
xfd->howtoend = END_SHUTDOWN;
xfd->peersa.soa.sa_family = pf;
themlen = 0;
if ((result =
dalan(address, (char *)&xfd->peersa.soa.sa_data, &themlen,
sizeof(xfd->peersa)))
< 0) {
Error1("data too long: \"%s\"", address);
} else if (result > 0) {
Error1("syntax error in \"%s\"", address);
}
xfd->salen = themlen + sizeof(sa_family_t);
#if HAVE_STRUCT_SOCKADDR_SALEN
xfd->peersa.soa.sa_len =
sizeof(xfd->peersa.soa.sa_len) + sizeof(xfd->peersa.soa.sa_family) +
themlen;
#endif
if ((result =
_xioopen_socket_sendto(pfname, typename, protname, address,
opts, xioflags, xxfd, groups))
!= STAT_OK) {
return result;
}
xfd->dtype = XIOREAD_RECV|XIOWRITE_SENDTO;
xfd->para.socket.la.soa.sa_family = xfd->peersa.soa.sa_family;
/* which reply sockets will accept - determine by range option */
if (retropt_string(opts, OPT_RANGE, &rangename) >= 0) {
if (xioparserange(rangename, 0, &xfd->para.socket.range) < 0) {
free(rangename);
return STAT_NORETRY;
}
xfd->para.socket.dorange = true;
xfd->dtype |= XIOREAD_RECV_CHECKRANGE;
free(rangename);
}
_xio_openlate(xfd, opts);
return STAT_OK;
}
/* a subroutine that is common to all socket addresses that want to connect
to a peer address.
@ -658,9 +1196,9 @@ int _xioopen_dgram_recvfrom(struct single *xfd, int xioflags,
}
#endif /* WITH_UNIX */
#if WITH_IP4 /*|| WITH_IP6*/
/* for generic sockets, this has already been retrieved */
if (retropt_string(opts, OPT_RANGE, &rangename) >= 0) {
if (parserange(rangename, pf, &xfd->para.socket.range)
if (xioparserange(rangename, pf, &xfd->para.socket.range)
< 0) {
free(rangename);
return STAT_NORETRY;
@ -668,7 +1206,6 @@ int _xioopen_dgram_recvfrom(struct single *xfd, int xioflags,
free(rangename);
xfd->para.socket.dorange = true;
}
#endif
#if (WITH_TCP || WITH_UDP) && WITH_LIBWRAP
xio_retropt_tcpwrap(xfd, opts);
@ -913,7 +1450,7 @@ int _xioopen_dgram_recv(struct single *xfd, int xioflags,
#if WITH_IP4 /*|| WITH_IP6*/
if (retropt_string(opts, OPT_RANGE, &rangename) >= 0) {
if (parserange(rangename, pf, &xfd->para.socket.range)
if (xioparserange(rangename, pf, &xfd->para.socket.range)
< 0) {
free(rangename);
return STAT_NORETRY;
@ -1032,17 +1569,17 @@ int xiogetpacketsrc(int fd, union sockaddr_union *pa, socklen_t *palen) {
}
int xiocheckrange(union sockaddr_union *sa, union xiorange_union *range) {
int xiocheckrange(union sockaddr_union *sa, struct xiorange *range) {
switch (sa->soa.sa_family) {
#if WITH_IP4
case PF_INET:
return
xiocheckrange_ip4(&sa->ip4, &range->ip4);
xiocheckrange_ip4(&sa->ip4, range);
#endif /* WITH_IP4 */
#if WITH_IP6
case PF_INET6:
return
xiocheckrange_ip6(&sa->ip6, &range->ip6);
xiocheckrange_ip6(&sa->ip6, range);
#endif /* WITH_IP6 */
}
return -1;
@ -1133,4 +1670,107 @@ int xiocheckpeer(xiosingle_t *xfd,
return 0; /* permitted */
}
/* parses a network specification consisting of an address and a mask. */
int xioparsenetwork(const char *rangename, int pf, struct xiorange *range) {
size_t addrlen = 0, masklen = 0;
int result;
switch (pf) {
#if WITH_IP4
case PF_INET:
return xioparsenetwork_ip4(rangename, range);
break;
#endif /* WITH_IP4 */
#if WITH_IP6
case PF_INET6:
return xioparsenetwork_ip6(rangename, range);
break;
#endif /* WITH_IP6 */
case PF_UNSPEC:
{
char *addrname;
const char *maskname;
if ((maskname = strchr(rangename, ':')) == NULL) {
Error1("syntax error in range \"%s\": use <addr>:<mask>", rangename);
return STAT_NORETRY;
}
++maskname; /* skip ':' */
if ((addrname = Malloc(maskname-rangename)) == NULL) {
return STAT_NORETRY;
}
strncpy(addrname, rangename, maskname-rangename-1);
result =
dalan(addrname, (char *)&range->netaddr.soa.sa_data, &addrlen,
sizeof(range->netaddr)-(size_t)(&((struct sockaddr *)0)->sa_data)
/* data length */);
if (result < 0) {
Error1("data too long: \"%s\"", addrname);
free(addrname); return STAT_NORETRY;
} else if (result > 0) {
Error1("syntax error in \"%s\"", addrname);
free(addrname); return STAT_NORETRY;
}
free(addrname);
result =
dalan(maskname, (char *)&range->netmask.soa.sa_data, &masklen,
sizeof(range->netaddr)-(size_t)(&((struct sockaddr *)0)->sa_data)
/* data length */);
if (result < 0) {
Error1("data too long: \"%s\"", maskname);
return STAT_NORETRY;
} else if (result > 0) {
Error1("syntax error in \"%s\"", maskname);
return STAT_NORETRY;
}
if (addrlen != masklen) {
Error2("network address is "F_Zu" bytes long, mask is "F_Zu" bytes long",
addrlen, masklen);
/* recover by padding the shorter component with 0 */
memset((char *)&range->netaddr.soa.sa_data+addrlen, 0,
MAX(0, addrlen-masklen));
memset((char *)&range->netmask.soa.sa_data+masklen, 0,
MAX(0, masklen-addrlen));
}
}
break;
default:
Error1("range option not supported with address family %d", pf);
return STAT_NORETRY;
}
return STAT_OK;
}
/* parses a string of form address/bits or address:mask, and fills the fields
of the range union. The addr component is masked with mask. */
int xioparserange(const char *rangename, int pf, struct xiorange *range) {
int i;
if (xioparsenetwork(rangename, pf, range) < 0) {
return -1;
}
/* we have parsed the address and mask; now we make sure that the stored
address has 0 where mask is 0, to simplify comparisions */
switch (pf) {
#if WITH_IP4
case PF_INET:
range->netaddr.ip4.sin_addr.s_addr &= range->netmask.ip4.sin_addr.s_addr;
break;
#endif /* WITH_IP4 */
#if WITH_IP6
case PF_INET6:
return xiorange_ip6andmask(range);
break;
#endif /* WITH_IP6 */
case PF_UNSPEC:
for (i = 0; i < sizeof(range->netaddr); ++i) {
((char *)&range->netaddr)[i] &= ((char *)&range->netmask)[i];
}
break;
default:
Error1("range option not supported with address family %d", pf);
return STAT_NORETRY;
}
return 0;
}
#endif /* _WITH_SOCKET */

View file

@ -5,6 +5,13 @@
#ifndef __xio_socket_h_included
#define __xio_socket_h_included 1
extern const struct addrdesc xioaddr_socket_connect;
extern const struct addrdesc xioaddr_socket_listen;
extern const struct addrdesc xioaddr_socket_sendto;
extern const struct addrdesc xioaddr_socket_datagram;
extern const struct addrdesc xioaddr_socket_recvfrom;
extern const struct addrdesc xioaddr_socket_recv;
extern const struct optdesc opt_connect_timeout;
extern const struct optdesc opt_so_debug;
extern const struct optdesc opt_so_acceptconn;
@ -89,5 +96,10 @@ int xiogetpacketsrc(int fd, union sockaddr_union *pa, socklen_t *palen);
extern
int xiocheckpeer(xiosingle_t *xfd,
union sockaddr_union *pa, union sockaddr_union *la);
extern
int xioparsenetwork(const char *rangename, int pf,
struct xiorange *range);
extern
int xioparserange(const char *rangename, int pf, struct xiorange *range);
#endif /* !defined(__xio_socket_h_included) */

View file

@ -70,7 +70,7 @@ static int xioopen_tun(int argc, const char *argv[], struct opt *opts, int xiofl
char *tundevice = NULL;
char *tunname = NULL, *tuntype = NULL;
int pf = /*! PF_UNSPEC*/ PF_INET;
union xiorange_union network;
struct xiorange network;
bool no_pi = false;
const char *namedargv[] = { "tun", NULL, NULL };
int rw = (xioflags & XIO_ACCMODE);
@ -157,12 +157,14 @@ static int xioopen_tun(int argc, const char *argv[], struct opt *opts, int xiofl
return result;
}
socket_init(pf, (union sockaddr_union *)&ifr.ifr_addr);
((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr = network.ip4.netaddr;
((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr =
network.netaddr.ip4.sin_addr;
if (Ioctl(sockfd, SIOCSIFADDR, &ifr) < 0) {
Error4("ioctl(%d, SIOCSIFADDR, {\"%s\", \"%s\"}: %s",
sockfd, ifr.ifr_name, ifaddr, strerror(errno));
}
((struct sockaddr_in *)&ifr.ifr_netmask)->sin_addr = network.ip4.netmask;
((struct sockaddr_in *)&ifr.ifr_netmask)->sin_addr =
network.netmask.ip4.sin_addr;
if (Ioctl(sockfd, SIOCSIFNETMASK, &ifr) < 0) {
Error4("ioctl(%d, SIOCSIFNETMASK, {\"0x%08u\", \"%s\"}, %s",
sockfd, ((struct sockaddr_in *)&ifr.ifr_netmask)->sin_addr.s_addr,

View file

@ -145,7 +145,7 @@ int xioopen_ipdgram_listen(int argc, const char *argv[], struct opt *opts,
#if WITH_IP4 /*|| WITH_IP6*/
if (retropt_string(opts, OPT_RANGE, &rangename) >= 0) {
if (parserange(rangename, pf, &fd->stream.para.socket.range) < 0) {
if (xioparserange(rangename, pf, &fd->stream.para.socket.range) < 0) {
free(rangename);
return STAT_NORETRY;
}
@ -424,7 +424,7 @@ int xioopen_udp_datagram(int argc, const char *argv[], struct opt *opts,
/* which reply packets will be accepted - determine by range option */
if (retropt_string(opts, OPT_RANGE, &rangename)
>= 0) {
if (parserange(rangename, pf, &xfd->para.socket.range) < 0) {
if (xioparserange(rangename, pf, &xfd->para.socket.range) < 0) {
free(rangename);
return STAT_NORETRY;
}
@ -582,7 +582,7 @@ int xioopen_udp_recv(int argc, const char *argv[], struct opt *opts,
#if WITH_IP4 /*|| WITH_IP6*/
if (retropt_string(opts, OPT_RANGE, &rangename) >= 0) {
if (parserange(rangename, pf, &xfd->stream.para.socket.range) < 0) {
if (xioparserange(rangename, pf, &xfd->stream.para.socket.range) < 0) {
return STAT_NORETRY;
}
xfd->stream.para.socket.dorange = true;

View file

@ -84,6 +84,9 @@ xiosetunix(struct sockaddr_un *saun,
} else {
len = sizeof(struct sockaddr_un);
}
#if HAVE_STRUCT_SOCKADDR_SALEN
saun->sun_len = len;
#endif
} else {
if ((pathlen = strlen(path)) >= sizeof(saun->sun_path)) {
Warn2("socket address "F_Zu" characters long, truncating to "F_Zu"",
@ -225,7 +228,7 @@ static int xioopen_unix_connect(int argc, const char *argv[], struct opt *opts,
if ((result = _xio_openlate(xfd, opts)) < 0) {
return result;
}
return 0;
return STAT_OK;
}

2
xio.h
View file

@ -177,7 +177,7 @@ typedef struct single {
union sockaddr_union la; /* local socket address */
bool emptyiseof; /* with dgram: empty packet means EOF */
bool dorange;
union xiorange_union range; /* restrictions for peer address */
struct xiorange range; /* restrictions for peer address */
#if _WITH_IP4 || _WITH_IP6
struct {
unsigned int res_opts[2]; /* bits to be set in _res.options are

View file

@ -66,12 +66,12 @@ int xioclose1(struct single *pipe) {
case END_CLOSE: case END_CLOSE_KILL:
if (Close(pipe->fd) < 0) {
Info2("close(%d): %s", pipe->fd, strerror(errno)); } break;
#if WITH_SOCKET
#if _WITH_SOCKET
case END_SHUTDOWN: case END_SHUTDOWN_KILL:
if (Shutdown(pipe->fd, 2) < 0) {
Info3("shutdown(%d, %d): %s", pipe->fd, 2, strerror(errno)); }
break;
#endif /* WITH_SOCKET */
#endif /* _WITH_SOCKET */
case END_UNLINK: if (Unlink((const char *)pipe->name) < 0) {
Warn2("unlink(\"%s\"): %s", pipe->name, strerror(errno)); }
break;

View file

@ -47,13 +47,13 @@
# endif
#endif
#if WITH_UNIX || WITH_IP4 || WITH_IP6 || WITH_SOCKS4 || WITH_RAWIP
# define WITH_SOCKET 1
#if WITH_UNIX || WITH_IP4 || WITH_IP6 || WITH_SOCKS4 || WITH_RAWIP || WITH_GENERICSOCKET
# define _WITH_SOCKET 1
#else
# undef WITH_SOCKET
# undef _WITH_SOCKET
#endif
#if !WITH_SOCKET
#if !_WITH_SOCKET
# undef WITH_LISTEN
#endif
@ -61,7 +61,7 @@
# undef WITH_LIBWRAP
#endif
#if WITH_SOCKET || WITH_TUN
#if WITH_GENERICSOCKET || WITH_TUN
# define _WITH_SOCKET 1
#endif

View file

@ -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
@ -15,7 +15,7 @@
#include "xio-creat.h"
#include "xio-gopen.h"
#include "xio-pipe.h"
#if WITH_SOCKET
#if _WITH_SOCKET
#include "xio-socket.h"
#include "xio-listen.h"
#include "xio-unix.h"
@ -30,7 +30,7 @@
#include "xio-udp.h"
#include "xio-socks.h"
#include "xio-proxy.h"
#endif /* WITH_SOCKET */
#endif /* _WITH_SOCKET */
#include "xio-progcall.h"
#include "xio-exec.h"
#include "xio-system.h"

View file

@ -37,6 +37,10 @@ const struct addrname addressnames[] = {
{ "creat", &addr_creat },
{ "create", &addr_creat },
#endif
#if WITH_GENERICSOCKET
{ "datagram", &xioaddr_socket_datagram },
{ "dgram", &xioaddr_socket_datagram },
#endif
#if WITH_PIPE
{ "echo", &addr_pipe },
#endif
@ -131,6 +135,17 @@ const struct addrname addressnames[] = {
#if WITH_READLINE
{ "readline", &addr_readline },
#endif
#if WITH_GENERICSOCKET
{ "sendto", &xioaddr_socket_sendto },
#endif
#if WITH_GENERICSOCKET
{ "socket-connect", &xioaddr_socket_connect },
{ "socket-datagram", &xioaddr_socket_datagram },
{ "socket-listen", &xioaddr_socket_listen },
{ "socket-recv", &xioaddr_socket_recv },
{ "socket-recvfrom", &xioaddr_socket_recvfrom },
{ "socket-sendto", &xioaddr_socket_sendto },
#endif
#if WITH_SOCKS4
{ "socks", &addr_socks4_connect },
{ "socks4", &addr_socks4_connect },
@ -296,9 +311,9 @@ static xiofile_t *xioallocfd(void) {
fd->stream.fd = -1;
fd->stream.dtype = XIODATA_STREAM;
#if WITH_SOCKET
#if _WITH_SOCKET
/* fd->stream.salen = 0; */
#endif /* WITH_SOCKET */
#endif /* _WITH_SOCKET */
fd->stream.howtoend = END_UNSPEC;
/* fd->stream.name = NULL; */
/* fd->stream.para.exec.pid = 0; */

View file

@ -40,7 +40,7 @@ bool xioopts_ignoregroups;
# define IF_EXEC(a,b)
#endif
#if WITH_SOCKET
#if _WITH_SOCKET
# define IF_SOCKET(a,b) {a,b},
#else
# define IF_SOCKET(a,b)
@ -2608,13 +2608,13 @@ int retropt_string(struct opt *opts, int optcode, char **result) {
}
#if WITH_SOCKET
#if _WITH_SOCKET
/* looks for an bind option and, if found, overwrites the complete contents of
sa with the appropriate value(s).
returns STAT_OK if option exists and could be resolved,
STAT_NORETRY if option exists but had error,
or STAT_NOACTION if it does not exist */
/* currently only for IP (v4, v6) */
/* currently only for IP (v4, v6) and raw (PF_UNSPEC) */
int retropt_bind(struct opt *opts,
int af,
int socktype,
@ -2636,22 +2636,26 @@ int retropt_bind(struct opt *opts,
if (retropt_string(opts, OPT_BIND, &bindname) < 0) {
return STAT_NOACTION;
}
addrallowed = true;
portallowed = (feats>=2);
bindp = bindname;
nestlex((const char **)&bindp, &hostp, &hostlen, ends, NULL, NULL, nests,
true, false, false);
*hostp++ = '\0';
if (!strncmp(bindp, portsep, strlen(portsep))) {
if (!portallowed) {
Error("port specification not allowed in this bind option");
return STAT_NORETRY;
} else {
portp = bindp + strlen(portsep);
}
}
switch (af) {
case AF_UNSPEC:
{
size_t p = 0;
dalan(bindname, (char *)sa->sa_data, &p, *salen-sizeof(sa->sa_family));
*salen = p + sizeof(sa->sa_family);
*salen = p +
#if HAVE_STRUCT_SOCKADDR_SALEN
sizeof(sa->sa_len) +
#endif
sizeof(sa->sa_family);
#if HAVE_STRUCT_SOCKADDR_SALEN
sa->sa_len = *salen;
#endif
}
break;
#if WITH_IP4 || WITH_IP6
#if WITH_IP4
case AF_INET:
@ -2659,6 +2663,19 @@ int retropt_bind(struct opt *opts,
#if WITH_IP6
case AF_INET6:
#endif /*WITH_IP6 */
addrallowed = true;
portallowed = (feats>=2);
nestlex((const char **)&bindp, &hostp, &hostlen, ends, NULL, NULL, nests,
true, false, false);
*hostp++ = '\0';
if (!strncmp(bindp, portsep, strlen(portsep))) {
if (!portallowed) {
Error("port specification not allowed in this bind option");
return STAT_NORETRY;
} else {
portp = bindp + strlen(portsep);
}
}
if ((result =
xiogetaddrinfo(hostname[0]!='\0'?hostname:NULL, portp,
af, socktype, ipproto,
@ -2687,7 +2704,7 @@ int retropt_bind(struct opt *opts,
}
return STAT_OK;
}
#endif /* WITH_SOCKET */
#endif /* _WITH_SOCKET */
/* applies to fd all options belonging to phase */
@ -2806,7 +2823,7 @@ int applyopts(int fd, struct opt *opts, unsigned int phase) {
opt->desc->type);
}
#if WITH_SOCKET
#if _WITH_SOCKET
} else if (opt->desc->func == OFUNC_SOCKOPT) {
if (0) {
;
@ -3015,7 +3032,7 @@ int applyopts(int fd, struct opt *opts, unsigned int phase) {
Error1("setsockopt() data type %d not implemented",
opt->desc->type);
}
#endif /* WITH_SOCKET */
#endif /* _WITH_SOCKET */
#if HAVE_FLOCK
} else if (opt->desc->func == OFUNC_FLOCK) {
@ -3728,7 +3745,7 @@ int applyopts_single(struct single *xfd, struct opt *opts, enum e_phase phase) {
}
break;
#if WITH_SOCKET
#if _WITH_SOCKET
case OFUNC_SOCKOPT:
switch (opt->desc->optcode) {
#if WITH_IP4 && (defined(HAVE_STRUCT_IP_MREQ) || defined (HAVE_STRUCT_IP_MREQN))
@ -3879,7 +3896,7 @@ mc:addr
++opt; continue;
}
break;
#endif /* WITH_SOCKET */
#endif /* _WITH_SOCKET */
default:
++opt;

View file

@ -109,7 +109,7 @@ ssize_t xioread(xiofile_t *file, void *buff, size_t bufsiz) {
break;
#endif /* WITH_OPENSSL */
#if WITH_SOCKET
#if _WITH_SOCKET
case XIOREAD_RECV:
if (pipe->dtype & XIOREAD_RECV_FROM) {
#if WITH_RAWIP || WITH_UDP || WITH_UNIX
@ -354,7 +354,7 @@ ssize_t xioread(xiofile_t *file, void *buff, size_t bufsiz) {
}
break;
#endif /* WITH_SOCKET */
#endif /* _WITH_SOCKET */
default:
Error("internal: undefined read operation");

View file

@ -1,5 +1,5 @@
/* source: xioshutdown.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 of the extended shutdown function */
@ -65,7 +65,7 @@ int xioshutdown(xiofile_t *sock, int how) {
sock->stream.para.exec.fdout, strerror(errno));
}
}
#if WITH_SOCKET
#if _WITH_SOCKET
} else if (sock->stream.howtoend == END_SHUTDOWN) {
if ((result = Shutdown(sock->stream.fd, how)) < 0) {
Info3("shutdown(%d, %d): %s",
@ -107,7 +107,7 @@ int xioshutdown(xiofile_t *sock, int how) {
sock->stream.eof = 2;
sock->stream.fd = -1;
}
#endif /* WITH_SOCKET */
#endif /* _WITH_SOCKET */
#if 0
} else {
Error1("xioshutdown(): bad data type specification %d", sock->stream.dtype);

View file

@ -76,7 +76,7 @@ ssize_t xiowrite(xiofile_t *file, const void *buff, size_t bytes) {
}
break;
#if WITH_SOCKET
#if _WITH_SOCKET
case XIOWRITE_SENDTO:
/*union {
char space[sizeof(struct sockaddr_un)];
@ -117,7 +117,7 @@ ssize_t xiowrite(xiofile_t *file, const void *buff, size_t bytes) {
sockaddr_info(&us.soa, uslen, infobuff, sizeof(infobuff)));
}
break;
#endif /* WITH_SOCKET */
#endif /* _WITH_SOCKET */
case XIOWRITE_PIPE:
do {