mirror of
https://repo.or.cz/socat.git
synced 2024-12-22 15:32:35 +00:00
merged features ioctl, setsockopt, generic-socket
This commit is contained in:
commit
d78b080ef0
44 changed files with 2035 additions and 263 deletions
19
CHANGES
19
CHANGES
|
@ -1,5 +1,20 @@
|
|||
|
||||
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.
|
||||
|
||||
added address options setsockopt-int, setsockopt-bin, and
|
||||
setsockopt-string
|
||||
|
||||
so-type now only affect the socket() and socketpair() calls, not the
|
||||
name resolution. so-type and so-prototype can be applied to all socket
|
||||
based addresses.
|
||||
|
||||
new address option "escape" allows to break a socat instance even when
|
||||
raw terminal mode prevents ^C etc.
|
||||
|
||||
|
@ -31,10 +46,6 @@ new features:
|
|||
new address options ipv6-tclass and ipv6-unicast-hops set the related
|
||||
socket options.
|
||||
|
||||
so-type now only affect the socket() and socketpair() calls, not the
|
||||
name resolution. so-type and so-prototype can be applied to all socket
|
||||
based addresses.
|
||||
|
||||
corrections:
|
||||
some raw IP and UNIX datagram modes failed on BSD systems
|
||||
|
||||
|
|
22
EXAMPLES
22
EXAMPLES
|
@ -285,6 +285,28 @@ $ socat -d -d -d -d - udp-datagram:224.0.0.2:6666,bind=:6666,ip-add-membership=2
|
|||
// packets leave via wrong interface (set route: ...)
|
||||
// socket bound to specific address
|
||||
|
||||
//=============================================================================
|
||||
// GENERIC FUNCTION CALLS
|
||||
|
||||
// ioctl(): open CD drive (given value valid on Linux)
|
||||
// on my Linux system I find in /usr/include/linux/cdrom.h the define:
|
||||
// #define CDROMEJECT 0x5309 /* Ejects the cdrom media */
|
||||
// the following command makes something like ioctl(fd, CDROMEJECT, NULL)
|
||||
$ socat /dev/cdrom,o-nonblock,ioctl-void=0x5309 -
|
||||
|
||||
// setsockopt(): SO_REUSEADDR
|
||||
// the following command performs - beyond lots of overhead - something like:
|
||||
// myint=1; setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &myint, sizeof(myint))
|
||||
$ socat -u udp-recv:7777,setsockopt-int=1:2:1 -
|
||||
// setsockopt(): SO_BINDTODEVICE
|
||||
|
||||
// ways to apply SO_BINDTODEVICE without using the special socat address option
|
||||
// so-bindtodevice:
|
||||
// with string argument:
|
||||
$ sudo ./socat tcp-l:7777,setsockopt-string=1:25:eth0 pipe
|
||||
// with binary argument:
|
||||
$ sudo ./socat tcp-l:7777,setsockopt-bin=1:25:x6574683000 pipe
|
||||
|
||||
===============================================================================
|
||||
|
||||
// not tested, just ideas, or have problems
|
||||
|
|
2
VERSION
2
VERSION
|
@ -1 +1 @@
|
|||
"1.6.0.1+ip4bind+recvfromfork+x64+execstderr+execspaces+cosmetics+poll+udplistencont+ignoreeofunblock+escape+timestamp+ancillary+envvar+protocol"
|
||||
"1.6.0.1+ip4bind+recvfromfork+x64+execstderr+execspaces+cosmetics+poll+udplistencont+ignoreeofunblock+escape+timestamp+ancillary+envvar+protocol+ioctl+setsockopt+genericsocket"
|
||||
|
|
|
@ -468,6 +468,7 @@
|
|||
#undef WITH_IP4
|
||||
#undef WITH_IP6
|
||||
#undef WITH_RAWIP
|
||||
#undef WITH_GENERICSOCKET
|
||||
#undef WITH_TCP
|
||||
#undef WITH_UDP
|
||||
#undef WITH_LISTEN
|
||||
|
|
|
@ -213,6 +213,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
|
||||
|
|
1
dalan.c
1
dalan.c
|
@ -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
|
||||
|
|
182
doc/socat.yo
182
doc/socat.yo
|
@ -10,7 +10,7 @@ def(Filan)(0)(bf(Filan))
|
|||
def(procan)(0)(bf(procan))
|
||||
def(Procan)(0)(bf(Procan))
|
||||
|
||||
manpage(socat)(1)(Jul 2008)(socat)()
|
||||
manpage(socat)(1)(Sep 2008)(socat)()
|
||||
|
||||
whenhtml(
|
||||
label(CONTENTS)
|
||||
|
@ -600,6 +600,145 @@ 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 by link(int)(TYPE_INT)
|
||||
numbers. Consult your OS documentation and include files to find the
|
||||
appropriate values. The remote-address must be the link(data)(TYPE_DATA)
|
||||
representation of a sockaddr structure without sa_family and (BSD) sa_len
|
||||
components.nl()
|
||||
Please note that you can - beyond the options of the specified groups - also
|
||||
use options of higher level protocols when you apply socat option
|
||||
link(-g)(option_g).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 by link(int)(TYPE_INT)
|
||||
numbers. Consult your OS documentation and include files to find the
|
||||
appropriate values. The remote-address must be the link(data)(TYPE_DATA)
|
||||
representation of a sockaddr structure without sa_family and (BSD) sa_len
|
||||
components.nl()
|
||||
Please note that you can - beyond the options of the specified groups - also
|
||||
use options of higher level protocols when you apply socat option
|
||||
link(-g)(option_g).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 by
|
||||
link(int)(TYPE_INT) numbers. Consult your OS documentation and include files
|
||||
to find the appropriate values. The local-address must be the
|
||||
link(data)(TYPE_DATA) representation of a sockaddr structure without
|
||||
sa_family and (BSD) sa_len components.nl()
|
||||
Please note that you can - beyond the options of the specified groups - also
|
||||
use options of higher level protocols when you apply socat option
|
||||
link(-g)(option_g).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 by link(int)(TYPE_INT) numbers. Consult your
|
||||
OS documentation and include files to find the appropriate values. The
|
||||
local-address must be the link(data)(TYPE_DATA) representation of a sockaddr
|
||||
structure without sa_family and (BSD) sa_len components.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
|
||||
link(int)(TYPE_INT) numbers. Consult your OS documentation and include files
|
||||
to find the appropriate values. The local-address must be the
|
||||
link(data)(TYPE_DATA) representation of a sockaddr structure without
|
||||
sa_family and (BSD) sa_len components.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 link(int)(TYPE_INT)
|
||||
numbers. Consult your OS documentation and include files to find the
|
||||
appropriate values. The remote-address must be the link(data)(TYPE_DATA)
|
||||
representation of a sockaddr structure without sa_family and (BSD) sa_len
|
||||
components.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)]
|
||||
|
@ -1265,6 +1404,24 @@ label(OPTION_END_CLOSE)dit(bf(tt(end-close)))
|
|||
Similarly, when an address of type EXEC or SYSTEM is ended, socat usually
|
||||
will explicitely kill the sub process. With this option, it will just close
|
||||
the file descriptors.
|
||||
label(OPTION_IOCTL_VOID)dit(bf(tt(ioctl-void=<request>)))
|
||||
Calls tt(ioctl()) with the request value as second argument and NULL as
|
||||
third argument. This option allows to utilize ioctls that are not
|
||||
explicitely implemented in socat.
|
||||
label(OPTION_IOCTL_INT)dit(bf(tt(ioctl-int=<reqeust>:<value>)))
|
||||
Calls tt(ioctl()) with the request value as second argument and the integer
|
||||
value as third argument.
|
||||
label(OPTION_IOCTL_INTP)dit(bf(tt(ioctl-intp=<reqeust>:<value>)))
|
||||
Calls tt(ioctl()) with the request value as second argument and a pointer to
|
||||
the integer value as third argument.
|
||||
label(OPTION_IOCTL_BIN)dit(bf(tt(ioctl-bin=<reqeust>:<value>)))
|
||||
Calls tt(ioctl()) with the request value as second argument and a pointer to
|
||||
the given data value as third argument. This data must be specified in
|
||||
link(<dalan>)(TYPE_DATA) form.
|
||||
label(OPTION_IOCTL_STRING)dit(bf(tt(ioctl-string=<reqeust>:<value>)))
|
||||
Calls tt(ioctl()) with the request value as second argument and a pointer to
|
||||
the given string as third argument.
|
||||
link(<dalan>)(TYPE_DATA) form.
|
||||
enddit()
|
||||
|
||||
startdit()enddit()nl()
|
||||
|
@ -1650,6 +1807,24 @@ COMMENT(label(OPTION_USEIFBUFS)dit(bf(tt(useifbufs)))
|
|||
label(OPTION_SO_TIMESTAMP)dit(bf(tt(so-timestamp)))
|
||||
Sets the SO_TIMESTAMP socket option. This enables receiving and logging of
|
||||
timestamp ancillary messages.
|
||||
label(OPTION_SETSOCKOPT_INT)dit(bf(tt(setsockopt-int=<level>:<optname>:<optval>)))
|
||||
Invokes tt(setsockopt()) for the socket with the given parameters. tt(level)
|
||||
[link(int)(TYPE_INT)] is used as second argument to tt(setsockopt()) and
|
||||
specifies the layer, e.g. SOL_TCP for TCP (6 on Linux), or SOL_SOCKET for
|
||||
the socket layer (1 on Linux). tt(optname) [link(int)(TYPE_INT)] is the
|
||||
third argument to tt(setsockopt()) and tells which socket option is to be
|
||||
set. For the actual numbers you might have to look up the appropriate include
|
||||
files of your system. The 4th tt(setsockopt()) parameter, tt(value)
|
||||
[link(int)(TYPE_INT)], is passed to the function per pointer, and for the
|
||||
length parameter sizeof(int) is taken implicitely.
|
||||
label(OPTION_SETSOCKOPT_BIN)dit(bf(tt(setsockopt-bin=<level>:<optname>:<optval>)))
|
||||
Like tt(setsockopt-int), but <optval> must be provided in
|
||||
link(dalan)(TYPE_DATA) format and specifies an arbitrary sequence of bytes;
|
||||
the length parameter is automatically derived from the data.
|
||||
label(OPTION_SETSOCKOPT_STRING)dit(bf(tt(setsockopt-string=<level>:<optname>:<optval>)))
|
||||
Like tt(setsockopt-int), but <optval> must be a link(string)(TYPE_STRING).
|
||||
This string is passed to the function with trailing null character, and the
|
||||
length parameter is automatically derived from the data.
|
||||
enddit()
|
||||
|
||||
startdit()enddit()nl()
|
||||
|
@ -2464,8 +2639,9 @@ label(TYPE_COMMAND_LINE)dit(command-line)
|
|||
A string specifying a program name and its arguments, separated by single
|
||||
spaces.
|
||||
label(TYPE_DATA)dit(data)
|
||||
A raw data specification following em(dalan) syntax. The only documented
|
||||
form is a string starting with 'x' followed by an even number of hex digits.
|
||||
A raw data specification following em(dalan) syntax. Currently the only
|
||||
valid form is a string starting with 'x' followed by an even number of hex
|
||||
digits, specifying a sequence of bytes.
|
||||
label(TYPE_DIRECTORY)dit(directory)
|
||||
A string with usual unix() directory name semantics.
|
||||
label(TYPE_FACILITY)dit(facility)
|
||||
|
|
8
fdname.c
8
fdname.c
|
@ -142,7 +142,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) {
|
||||
|
@ -153,7 +153,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() */
|
||||
|
@ -188,7 +188,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
|
||||
|
@ -323,7 +323,7 @@ int sockname(int fd, FILE *outfile) {
|
|||
#undef FDNAME_OPTLEN
|
||||
#undef FDNAME_NAMELEN
|
||||
}
|
||||
#endif /* WITH_SOCKET */
|
||||
#endif /* _WITH_SOCKET */
|
||||
|
||||
|
||||
|
||||
|
|
22
filan.c
22
filan.c
|
@ -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
|
||||
|
@ -637,7 +637,7 @@ int sockan(int fd, FILE *outfile) {
|
|||
#undef FILAN_OPTLEN
|
||||
#undef FILAN_NAMELEN
|
||||
}
|
||||
#endif /* WITH_SOCKET */
|
||||
#endif /* _WITH_SOCKET */
|
||||
|
||||
|
||||
#if WITH_IP4 || WITH_IP6
|
||||
|
@ -826,7 +826,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];
|
||||
|
@ -862,10 +862,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
|
||||
|
@ -886,7 +886,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) {
|
||||
|
|
4
filan.h
4
filan.h
|
@ -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, const char *numform);
|
||||
|
|
6
hostan.c
6
hostan.c
|
@ -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, NetBSD: man 4 networking */
|
||||
|
@ -81,4 +81,4 @@ static int iffan(FILE *outfile) {
|
|||
#endif /* defined(SIOCGIFCONF) */
|
||||
return 0;
|
||||
}
|
||||
#endif /* WITH_SOCKET */
|
||||
#endif /* _WITH_SOCKET */
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
10
sycls.c
10
sycls.c
|
@ -593,6 +593,16 @@ int Ioctl(int d, int request, void *argp) {
|
|||
return retval;
|
||||
}
|
||||
|
||||
int Ioctl_int(int d, int request, int arg) {
|
||||
int retval, _errno;
|
||||
Debug3("ioctl(%d, 0x%x, %d)", d, request, arg);
|
||||
retval = ioctl(d, request, arg);
|
||||
_errno = errno;
|
||||
Debug1("ioctl() -> %d", retval);
|
||||
errno = _errno;
|
||||
return retval;
|
||||
}
|
||||
|
||||
int Close(int fd) {
|
||||
int retval, _errno;
|
||||
Info1("close(%d)", fd);
|
||||
|
|
2
sycls.h
2
sycls.h
|
@ -64,6 +64,7 @@ int Ftruncate64(int fd, off64_t length);
|
|||
#endif /* HAVE_FTRUNCATE64 */
|
||||
int Flock(int fd, int operation);
|
||||
int Ioctl(int d, int request, void *argp);
|
||||
int Ioctl_int(int d, int request, int arg);
|
||||
int Close(int fd);
|
||||
int Fchown(int fd, uid_t owner, gid_t group);
|
||||
int Fchmod(int fd, mode_t mode);
|
||||
|
@ -197,6 +198,7 @@ void Add_history(const char *string);
|
|||
#define Ftruncate64(f,l) ftruncate64(f,l)
|
||||
#define Flock(f,o) flock(f,o)
|
||||
#define Ioctl(d,r,a) ioctl(d,r,a)
|
||||
#define Ioctl_int(d,r,a) ioctl(d,r,a)
|
||||
#define Close(f) close(f)
|
||||
#define Fchown(f,o,g) fchown(f,o,g)
|
||||
#define Fchmod(f,m) fchmod(f,m)
|
||||
|
|
|
@ -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 ", sas->soa.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 ", sau->soa.sa_family)) < 0) {
|
||||
Warn1("sockaddr_info(): buffer too short ("F_Zu")", blen);
|
||||
*buff = '\0';
|
||||
|
|
26
sysutils.h
26
sysutils.h
|
@ -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 */
|
||||
|
||||
|
|
641
test.sh
641
test.sh
|
@ -144,14 +144,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
|
||||
|
@ -187,20 +194,20 @@ vt100|vt320|linux|xterm|cons25|dtterm|aixterm|sun-color|xterm-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}"
|
||||
|
@ -1512,9 +1519,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
|
||||
|
@ -1522,7 +1531,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))
|
||||
|
@ -1577,7 +1587,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) ")" ;;
|
||||
|
@ -1599,8 +1610,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
|
||||
|
@ -4399,7 +4411,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
|
||||
|
@ -4471,7 +4483,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
|
||||
|
@ -4869,7 +4882,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))
|
||||
|
@ -4878,6 +4897,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
|
||||
|
@ -5556,7 +5591,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"
|
||||
|
@ -5578,12 +5613,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"
|
||||
|
@ -5941,10 +5976,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"
|
||||
|
@ -5966,16 +6004,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
|
||||
|
@ -8836,6 +8874,559 @@ UNIX UNIX $td/test\$N.server - , so-timestamp TIMESTAMP
|
|||
"
|
||||
|
||||
|
||||
# test the SOCKET-CONNECT address (against TCP4-LISTEN)
|
||||
NAME=SOCKET_CONNECT_TCP4
|
||||
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="test$N $(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-CONNECT address (against TCP6-LISTEN)
|
||||
NAME=SOCKET_CONNECT_TCP6
|
||||
case "$TESTS" in
|
||||
*%functions%*|*%generic%*|*%tcp6%*|*%socket%*|*%$NAME%*)
|
||||
TEST="$NAME: socket connect with TCP/IPv6"
|
||||
# start a TCP6-LISTEN process that echoes data, and send test data using
|
||||
# SOCKET-CONNECT, selecting TCP/IPv6. 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="[::1]"
|
||||
ts1p=$(printf "%04x" $ts0p);
|
||||
ts1a="00000000000000000000000000000001" # "127.0.0.1"
|
||||
ts1="x${ts1p}x000000000000x${ts1a}"
|
||||
ts1b=$(printf "%04x" $PORT); PORT=$((PORT+1))
|
||||
da="test$N $(date) $RANDOM"
|
||||
CMD0="$SOCAT $opts TCP6-LISTEN:$ts0p,reuseaddr,bind=$ts0a PIPE"
|
||||
CMD1="$SOCAT $opts - SOCKET-CONNECT:10:6:$ts1,bind=x${ts1b}x000000000000x00000000000000000000000000000000"
|
||||
printf "test $F_n $TEST... " $N
|
||||
$CMD0 2>"${te}0" &
|
||||
pid0="$!"
|
||||
waittcp6port $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-CONNECT address (against UNIX-LISTEN)
|
||||
NAME=SOCKET_CONNECT_UNIX
|
||||
case "$TESTS" in
|
||||
*%functions%*|*%generic%*|*%unix%*|*%socket%*|*%$NAME%*)
|
||||
TEST="$NAME: socket connect with UNIX domain"
|
||||
# start a UNIX-LISTEN process that echoes data, and send test data using
|
||||
# SOCKET-CONNECT, selecting UNIX socket. The sent data should be returned.
|
||||
tf="$td/test$N.stdout"
|
||||
te="$td/test$N.stderr"
|
||||
tdiff="$td/test$N.diff"
|
||||
ts0="$td/test$N.server"
|
||||
ts1="$td/test$N.client"
|
||||
da="test$N $(date) $RANDOM"
|
||||
CMD0="$SOCAT $opts UNIX-LISTEN:$ts0,reuseaddr PIPE"
|
||||
CMD1="$SOCAT $opts - SOCKET-CONNECT:1:0:\\\"$ts0\\\0\\\",bind=\\\"$ts1\\\0\\\""
|
||||
printf "test $F_n $TEST... " $N
|
||||
$CMD0 2>"${te}0" &
|
||||
pid0="$!"
|
||||
waitfile $ts0 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
|
||||
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="test$N $(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="test$N $(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="test$N $(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="test$N $(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="test$N $(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
|
||||
*%functions%*|*%pty%*|*%generic%*|*%$NAME%*)
|
||||
TEST="$NAME: test the ioctl-void option"
|
||||
# there are not many ioctls that apply to non global resources and do not
|
||||
# require root. TIOCEXCL seems to fit:
|
||||
# process 0 provides a pty;
|
||||
# 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 [ -z "$TIOCEXCL" ]; then
|
||||
# we use the numeric value of TIOCEXL which is system dependent
|
||||
$PRINTF "test $F_n $TEST... ${YELLOW}no value of TIOCEXCL${NORMAL}\n" $N
|
||||
numCANT=$((numCANT+1))
|
||||
else
|
||||
tp="$td/test$N.pty"
|
||||
tf="$td/test$N.stdout"
|
||||
te="$td/test$N.stderr"
|
||||
tdiff="$td/test$N.diff"
|
||||
da="test$N $(date) $RANDOM"
|
||||
CMD0="$SOCAT $opts PTY,LINK=$tp pipe"
|
||||
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" &
|
||||
pid0=$!
|
||||
waitfile $tp 1
|
||||
(echo "$da"; sleep 2) |$CMD1 >"$tf" 2>"${te}1" & # this should always work
|
||||
pid1=$!
|
||||
usleep 1000000
|
||||
$CMD2 >/dev/null 2>"${te}2" </dev/null
|
||||
rc2=$?
|
||||
kill $pid0 $pid1 2>/dev/null; wait
|
||||
if ! echo "$da" |diff - "$tf"; then
|
||||
$PRINTF "${YELLOW}phase 1 failed${NORMAL}\n"
|
||||
echo "$CMD0 &"
|
||||
echo "$CMD1"
|
||||
numCANT=$((numCANT+1))
|
||||
elif [ $rc2 -eq 0 ]; then
|
||||
$PRINTF "$FAILED: $SOCAT:\n"
|
||||
echo "$CMD0 &"
|
||||
echo "$CMD1"
|
||||
echo "$CMD2"
|
||||
cat "${te}0" "${te}1" "${te}2"
|
||||
numFAIL=$((numFAIL+1))
|
||||
else
|
||||
$PRINTF "$OK\n"
|
||||
if [ -n "$debug" ]; then cat "${te}0" "${te}1" "${te}2"; fi
|
||||
numOK=$((numOK+1))
|
||||
fi
|
||||
fi # !Linux
|
||||
;;
|
||||
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
|
||||
*%functions%*|*%ip4%*|*%tcp%*|*%generic%*|*%$NAME%*)
|
||||
TEST="$NAME: test the setsockopt-int option"
|
||||
# there are not many socket options that apply to non global resources, do not
|
||||
# require root, do not require a network connection, and can easily be
|
||||
# tested. SO_REUSEADDR seems to fit:
|
||||
# process 0 provides a tcp listening socket with reuseaddr;
|
||||
# process 1 connects to this port; thus the port is connected but no longer
|
||||
# listening
|
||||
# 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 [ -z "SO_REUSEADDR" ]; then
|
||||
# we use the numeric value of SO_REUSEADDR which might be system dependent
|
||||
$PRINTF "test $F_n $TEST... ${YELLOW}value of SO_REUSEADDR not known${NORMAL}\n" $N
|
||||
numCANT=$((numCANT+1))
|
||||
else
|
||||
tp="$PORT"
|
||||
tf="$td/test$N.stdout"
|
||||
te="$td/test$N.stderr"
|
||||
tdiff="$td/test$N.diff"
|
||||
da="test$N $(date) $RANDOM"
|
||||
CMD0="$SOCAT $opts TCP4-L:$tp,setsockopt-int=$SOL_SOCKET:$SO_REUSEADDR:1 PIPE"
|
||||
CMD1="$SOCAT $opts - TCP:localhost:$tp"
|
||||
CMD2="$CMD0"
|
||||
CMD3="$CMD1"
|
||||
printf "test $F_n $TEST... " $N
|
||||
$CMD0 >/dev/null 2>"${te}0" &
|
||||
pid0=$!
|
||||
waittcp4port $tp 1
|
||||
(echo "$da"; sleep 3) |$CMD1 >"$tf" 2>"${te}1" & # this should always work
|
||||
pid1=$!
|
||||
usleep 1000000
|
||||
$CMD2 >/dev/null 2>"${te}2" &
|
||||
pid2=$!
|
||||
waittcp4port $tp 1
|
||||
(echo "$da") |$CMD3 >"${tf}3" 2>"${te}3"
|
||||
rc3=$?
|
||||
kill $pid0 $pid1 $pid2 2>/dev/null; wait
|
||||
if ! echo "$da" |diff - "$tf"; then
|
||||
$PRINTF "${YELLOW}phase 1 failed${NORMAL}\n"
|
||||
echo "$CMD0 &"
|
||||
echo "$CMD1"
|
||||
numCANT=$((numCANT+1))
|
||||
elif [ $rc3 -ne 0 ]; then
|
||||
$PRINTF "$FAILED: $SOCAT:\n"
|
||||
echo "$CMD2 &"
|
||||
echo "$CMD3"
|
||||
cat "${te}2" "${te}3"
|
||||
numFAIL=$((numFAIL+1))
|
||||
elif ! echo "$da" |diff - "${tf}3"; then
|
||||
$PRINTF "$FAILED: $SOCAT:\n"
|
||||
echo "$CMD2 &"
|
||||
echo "$CMD3"
|
||||
echo "$da" |diff - "${tf}3"
|
||||
numCANT=$((numCANT+1))
|
||||
else
|
||||
$PRINTF "$OK\n"
|
||||
if [ -n "$debug" ]; then cat "${te}0" "${te}1" "${te}2" "${te}3"; fi
|
||||
numOK=$((numOK+1))
|
||||
fi
|
||||
fi # !Linux
|
||||
;;
|
||||
esac
|
||||
PORT=$((PORT+1))
|
||||
N=$((N+1))
|
||||
|
||||
|
||||
echo "summary: $((N-1)) tests; $numOK ok, $numFAIL failed, $numCANT could not be performed"
|
||||
|
||||
if [ "$numFAIL" -gt 0 ]; then
|
||||
|
|
9
xio-fd.c
9
xio-fd.c
|
@ -1,5 +1,5 @@
|
|||
/* source: xio-fd.c */
|
||||
/* Copyright Gerhard Rieger 2001-2006 */
|
||||
/* Copyright Gerhard Rieger 2001-2008 */
|
||||
/* Published under the GNU General Public License V.2, see file COPYING */
|
||||
|
||||
/* this file contains common file descriptor related option definitions */
|
||||
|
@ -75,3 +75,10 @@ const struct optdesc opt_cool_write = { "cool-write", "coolwrite", OPT_COOL_WRIT
|
|||
|
||||
/* control closing of connections */
|
||||
const struct optdesc opt_end_close = { "end-close", "close", OPT_END_CLOSE, GROUP_FD, PH_INIT, TYPE_CONST, OFUNC_OFFSET, (bool)&((xiofile_t *)0)->stream.howtoend, END_CLOSE };
|
||||
|
||||
/****** generic ioctl() options ******/
|
||||
const struct optdesc opt_ioctl_void = { "ioctl-void", "ioctl", OPT_IOCTL_VOID, GROUP_FD, PH_FD, TYPE_INT, OFUNC_IOCTL_GENERIC, 0, 0, 0 };
|
||||
const struct optdesc opt_ioctl_int = { "ioctl-int", NULL, OPT_IOCTL_INT, GROUP_FD, PH_FD, TYPE_INT_INT, OFUNC_IOCTL_GENERIC, 0, 0, 0 };
|
||||
const struct optdesc opt_ioctl_intp = { "ioctl-intp", NULL, OPT_IOCTL_INTP, GROUP_FD, PH_FD, TYPE_INT_INTP, OFUNC_IOCTL_GENERIC, 0, 0, 0 };
|
||||
const struct optdesc opt_ioctl_bin = { "ioctl-bin", NULL, OPT_IOCTL_BIN, GROUP_FD, PH_FD, TYPE_INT_BIN, OFUNC_IOCTL_GENERIC, 0, 0, 0 };
|
||||
const struct optdesc opt_ioctl_string = { "ioctl-string",NULL, OPT_IOCTL_STRING,GROUP_FD, PH_FD, TYPE_INT_STRING,OFUNC_IOCTL_GENERIC, 0, 0, 0 };
|
||||
|
|
7
xio-fd.h
7
xio-fd.h
|
@ -1,10 +1,15 @@
|
|||
/* source: xio-fd.h */
|
||||
/* Copyright Gerhard Rieger 2001-2006 */
|
||||
/* Copyright Gerhard Rieger 2001-2008 */
|
||||
/* Published under the GNU General Public License V.2, see file COPYING */
|
||||
|
||||
#ifndef __xio_fd_h_included
|
||||
#define __xio_fd_h_included 1
|
||||
|
||||
extern const struct optdesc opt_ioctl_void;
|
||||
extern const struct optdesc opt_ioctl_int;
|
||||
extern const struct optdesc opt_ioctl_intp;
|
||||
extern const struct optdesc opt_ioctl_bin;
|
||||
extern const struct optdesc opt_ioctl_string;
|
||||
extern const struct optdesc opt_append;
|
||||
extern const struct optdesc opt_nonblock;
|
||||
extern const struct optdesc opt_o_ndelay;
|
||||
|
|
86
xio-ip.c
86
xio-ip.c
|
@ -444,92 +444,6 @@ int xiogetaddrinfo(const char *node, const char *service,
|
|||
}
|
||||
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
#if defined(HAVE_STRUCT_CMSGHDR) && defined(CMSG_DATA)
|
||||
/* these are valid for IPv4 and IPv6 */
|
||||
int xiolog_ancillary_ip(struct cmsghdr *cmsg, int *num,
|
||||
|
|
5
xio-ip.h
5
xio-ip.h
|
@ -42,11 +42,6 @@ extern int xiogetaddrinfo(const char *node, const char *service,
|
|||
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);
|
||||
extern
|
||||
int xiolog_ancillary_ip(struct cmsghdr *cmsg, int *num,
|
||||
char *typbuff, int typlen,
|
||||
char *nambuff, int namlen,
|
||||
|
|
52
xio-ip4.c
52
xio-ip4.c
|
@ -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];
|
||||
|
||||
|
|
|
@ -7,8 +7,9 @@
|
|||
|
||||
extern const struct optdesc opt_ip4_add_membership;
|
||||
|
||||
int xioparsenetwork_ip4(const char *rangename, struct xiorange *range);
|
||||
extern
|
||||
int xiocheckrange_ip4(struct sockaddr_in *pa, struct xiorange_ip4 *range);
|
||||
int xiocheckrange_ip4(struct sockaddr_in *pa, struct xiorange *range);
|
||||
extern int
|
||||
xiosetsockaddrenv_ip4(int idx, char *namebuff, size_t namelen,
|
||||
char *valuebuff, size_t valuelen,
|
||||
|
|
17
xio-ip6.c
17
xio-ip6.c
|
@ -51,15 +51,15 @@ const struct optdesc opt_ipv6_recvtclass = { "ipv6-recvtclass", "recvtclass", OP
|
|||
const struct optdesc opt_ipv6_recvpathmtu = { "ipv6-recvpathmtu", "recvpathmtu", OPT_IPV6_RECVPATHMTU, GROUP_SOCK_IP6, PH_PASTSOCKET, TYPE_BOOL, OFUNC_SOCKOPT, SOL_IPV6, IPV6_RECVPATHMTU };
|
||||
#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] != ']') {
|
||||
|
@ -117,7 +117,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];
|
||||
|
@ -126,7 +126,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;
|
||||
|
@ -134,12 +135,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]),
|
||||
|
|
|
@ -28,11 +28,11 @@ extern const struct optdesc opt_ipv6_recvtclass;
|
|||
extern const struct optdesc opt_ipv6_recvpathmtu;
|
||||
|
||||
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);
|
||||
extern
|
||||
int xiolog_ancillary_ip6(struct cmsghdr *cmsg, int *num,
|
||||
char *typbuff, int typlen,
|
||||
|
|
22
xio-listen.c
22
xio-listen.c
|
@ -91,13 +91,16 @@ int
|
|||
/* creates the listening socket, bind, applies options; 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 (expecting 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
|
||||
process or in a subprocess.
|
||||
This function does not retry. If you need retries, handle this in a
|
||||
loop in the calling function (and always provide the options...)
|
||||
after fork, we set the forever/retry of the child process to 0
|
||||
After fork, we set the forever/retry of the child process to 0
|
||||
applies and consumes the following option:
|
||||
PH_INIT, PH_PASTSOCKET, PH_PREBIND, PH_BIND, PH_PASTBIND, PH_EARLY,
|
||||
PH_PREOPEN, PH_FD, PH_CONNECTED, PH_LATE, PH_LATE2
|
||||
|
@ -137,7 +140,7 @@ int _xioopen_listen(struct single *xfd, int xioflags, struct sockaddr *us, sockl
|
|||
xiosetchilddied(); /* set SIGCHLD handler */
|
||||
}
|
||||
|
||||
if ((xfd->fd = xiosocket(opts, pf, socktype, proto, level)) < 0) {
|
||||
if ((xfd->fd = xiosocket(opts, us->sa_family, socktype, proto, level)) < 0) {
|
||||
return STAT_RETRYLATER;
|
||||
}
|
||||
|
||||
|
@ -177,15 +180,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;
|
||||
}
|
||||
|
@ -205,6 +203,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';
|
||||
|
|
|
@ -176,7 +176,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;
|
||||
}
|
||||
|
@ -291,7 +291,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) {
|
||||
|
@ -304,7 +305,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;
|
||||
|
|
663
xio-socket.c
663
xio-socket.c
|
@ -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"
|
||||
|
||||
|
@ -20,10 +21,42 @@
|
|||
#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);
|
||||
|
||||
static int
|
||||
xiolog_ancillary_socket(struct cmsghdr *cmsg, int *num,
|
||||
char *typbuff, int typlen,
|
||||
|
@ -32,6 +65,17 @@ xiolog_ancillary_socket(struct cmsghdr *cmsg, int *num,
|
|||
char *valbuff, int vallen);
|
||||
|
||||
|
||||
/* 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};
|
||||
|
@ -143,6 +187,504 @@ const struct optdesc opt_connect_timeout = { "connect-timeout", NULL, OPT_CONNEC
|
|||
const struct optdesc opt_protocol_family = { "protocol-family", "pf", OPT_PROTOCOL_FAMILY, GROUP_SOCKET, PH_PRESOCKET, TYPE_STRING, OFUNC_SPEC };
|
||||
const struct optdesc opt_protocol = { "protocol", NULL, OPT_PROTOCOL, GROUP_SOCKET, PH_PRESOCKET, TYPE_STRING, OFUNC_SPEC };
|
||||
|
||||
/* generic setsockopt() options */
|
||||
const struct optdesc opt_setsockopt_int = { "setsockopt-int", "sockopt-int", OPT_SETSOCKOPT_INT, GROUP_SOCKET,PH_PASTSOCKET,TYPE_INT_INT_INT, OFUNC_SOCKOPT_GENERIC, 0, 0 };
|
||||
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.
|
||||
might fork.
|
||||
|
@ -675,9 +1217,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;
|
||||
|
@ -685,7 +1227,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);
|
||||
|
@ -930,7 +1471,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;
|
||||
|
@ -1104,17 +1645,17 @@ int xiodopacketinfo(struct msghdr *msgh, bool withlog, bool withenv) {
|
|||
}
|
||||
|
||||
|
||||
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;
|
||||
|
@ -1208,6 +1749,7 @@ int xiocheckpeer(xiosingle_t *xfd,
|
|||
return 0; /* permitted */
|
||||
}
|
||||
|
||||
|
||||
/* converts the ancillary message in *cmsg into a form useable for further
|
||||
processing. knows the specifics of common message types.
|
||||
returns the number of resulting syntax elements is *num
|
||||
|
@ -1327,6 +1869,111 @@ char *xiogetifname(int ind, char *val, int ins) {
|
|||
}
|
||||
|
||||
|
||||
/* 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);
|
||||
addrname[maskname-rangename-1] = '\0';
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
/* set environment variables describing (part of) a socket address, e.g.
|
||||
SOCAT_SOCKADDR. lr (local/remote) specifies a string like "SOCK" or "PEER".
|
||||
proto should correspond to the third parameter of socket(2) and is used to
|
||||
|
|
21
xio-socket.h
21
xio-socket.h
|
@ -11,6 +11,13 @@
|
|||
#define SO_PROTOTYPE 0x9999
|
||||
#endif
|
||||
|
||||
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;
|
||||
|
@ -57,6 +64,9 @@ extern const struct optdesc opt_fiosetown;
|
|||
extern const struct optdesc opt_siocspgrp;
|
||||
extern const struct optdesc opt_bind;
|
||||
extern const struct optdesc opt_protocol_family;
|
||||
extern const struct optdesc opt_setsockopt_int;
|
||||
extern const struct optdesc opt_setsockopt_bin;
|
||||
extern const struct optdesc opt_setsockopt_string;
|
||||
|
||||
|
||||
extern
|
||||
|
@ -101,11 +111,18 @@ int xiogetpacketsrc(int fd, struct msghdr *msgh);
|
|||
extern
|
||||
int xiocheckpeer(xiosingle_t *xfd,
|
||||
union sockaddr_union *pa, union sockaddr_union *la);
|
||||
extern
|
||||
int xiosetsockaddrenv(const char *lr, union sockaddr_union *sau, socklen_t salen, int proto);
|
||||
|
||||
extern
|
||||
int xioparsenetwork(const char *rangename, int pf,
|
||||
struct xiorange *range);
|
||||
extern
|
||||
int xioparserange(const char *rangename, int pf, struct xiorange *range);
|
||||
|
||||
extern int
|
||||
xiosocket(struct opt *opts, int pf, int socktype, int proto, int level);
|
||||
extern int
|
||||
xiosocketpair(struct opt *opts, int pf, int socktype, int proto, int sv[2]);
|
||||
extern
|
||||
int xiosetsockaddrenv(const char *lr, union sockaddr_union *sau, socklen_t salen, int proto);
|
||||
|
||||
#endif /* !defined(__xio_socket_h_included) */
|
||||
|
|
|
@ -68,7 +68,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);
|
||||
|
@ -155,12 +155,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,
|
||||
|
|
|
@ -144,7 +144,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;
|
||||
}
|
||||
|
@ -433,7 +433,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;
|
||||
}
|
||||
|
@ -591,7 +591,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;
|
||||
|
|
|
@ -105,6 +105,9 @@ xiosetunix(int pf,
|
|||
if (tight) {
|
||||
len = sizeof(struct sockaddr_un)-sizeof(saun->sun_path)+
|
||||
MIN(pathlen, sizeof(saun->sun_path));
|
||||
#if HAVE_STRUCT_SOCKADDR_SALEN
|
||||
saun->sun_len = len;
|
||||
#endif
|
||||
} else {
|
||||
len = sizeof(struct sockaddr_un);
|
||||
}
|
||||
|
@ -238,7 +241,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;
|
||||
}
|
||||
|
||||
|
||||
|
|
4
xio.h
4
xio.h
|
@ -179,7 +179,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
|
||||
|
@ -357,6 +357,8 @@ union integral {
|
|||
struct opt {
|
||||
const struct optdesc *desc;
|
||||
union integral value;
|
||||
union integral value2;
|
||||
union integral value3;
|
||||
} ;
|
||||
|
||||
extern const char *PIPESEP;
|
||||
|
|
|
@ -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;
|
||||
|
|
10
xioconfig.h
10
xioconfig.h
|
@ -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
|
||||
|
||||
|
|
|
@ -29,6 +29,8 @@ static const char *optiontypenames[] = {
|
|||
"STRUCT-IP_MREQ",
|
||||
#endif
|
||||
"IP4NAME",
|
||||
"INT:INT", "INT:INTP", "INT:BIN", "INT:STRING",
|
||||
"INT:INT:INT", "INT:INT:BIN", "INT:INT:STRING",
|
||||
} ;
|
||||
|
||||
|
||||
|
|
|
@ -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"
|
||||
|
|
19
xioopen.c
19
xioopen.c
|
@ -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.escape = -1;
|
||||
|
|
295
xioopts.c
295
xioopts.c
|
@ -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)
|
||||
|
@ -593,6 +593,12 @@ const struct optname optionnames[] = {
|
|||
IF_RETRY ("interval", &opt_intervall)
|
||||
IF_RETRY ("intervall", &opt_intervall)
|
||||
IF_TERMIOS("intr", &opt_vintr)
|
||||
IF_ANY ("ioctl", &opt_ioctl_void)
|
||||
IF_ANY ("ioctl-bin", &opt_ioctl_bin)
|
||||
IF_ANY ("ioctl-int", &opt_ioctl_int)
|
||||
IF_ANY ("ioctl-intp", &opt_ioctl_intp)
|
||||
IF_ANY ("ioctl-string", &opt_ioctl_string)
|
||||
IF_ANY ("ioctl-void", &opt_ioctl_void)
|
||||
#ifdef IP_ADD_MEMBERSHIP
|
||||
IF_IP ("ip-add-membership", &opt_ip_add_membership)
|
||||
#endif
|
||||
|
@ -1246,6 +1252,9 @@ const struct optname optionnames[] = {
|
|||
#if WITH_EXEC || WITH_SYSTEM
|
||||
IF_EXEC ("setsid", &opt_setsid)
|
||||
#endif
|
||||
IF_SOCKET ("setsockopt-bin", &opt_setsockopt_bin)
|
||||
IF_SOCKET ("setsockopt-int", &opt_setsockopt_int)
|
||||
IF_SOCKET ("setsockopt-string", &opt_setsockopt_string)
|
||||
IF_ANY ("setuid", &opt_setuid)
|
||||
IF_ANY ("setuid-early", &opt_setuid_early)
|
||||
#if WITH_EXEC || WITH_SYSTEM
|
||||
|
@ -1363,6 +1372,9 @@ const struct optname optionnames[] = {
|
|||
#ifdef SO_USELOOPBACK /* AIX433, Solaris */
|
||||
IF_SOCKET ("so-useloopback", &opt_so_useloopback)
|
||||
#endif /* SO_USELOOPBACK */
|
||||
IF_SOCKET ("sockopt-bin", &opt_setsockopt_bin)
|
||||
IF_SOCKET ("sockopt-int", &opt_setsockopt_int)
|
||||
IF_SOCKET ("sockopt-string", &opt_setsockopt_string)
|
||||
IF_SOCKS4 ("socksport", &opt_socksport)
|
||||
IF_SOCKS4 ("socksuser", &opt_socksuser)
|
||||
IF_IPAPP ("sourceport", &opt_sourceport)
|
||||
|
@ -2032,6 +2044,155 @@ int parseopts_table(const char **a, unsigned int groups, struct opt **opts,
|
|||
(*opts)[i].value.u_linger.l_linger);
|
||||
break;
|
||||
#endif /* HAVE_STRUCT_LINGER */
|
||||
case TYPE_INT_INT:
|
||||
if (!assign) {
|
||||
Error1("option \"%s\": values required", a0);
|
||||
continue;
|
||||
}
|
||||
{
|
||||
char *rest;
|
||||
(*opts)[i].value.u_int = strtoul(token, &rest, 0);
|
||||
if (*rest != ':') {
|
||||
Error1("option \"%s\": 2 arguments required",
|
||||
ent->desc->defname);
|
||||
}
|
||||
++rest;
|
||||
(*opts)[i].value2.u_int = strtoul(rest, &rest, 0);
|
||||
}
|
||||
Info3("setting option \"%s\" to %d:%d", ent->desc->defname,
|
||||
(*opts)[i].value.u_int, (*opts)[i].value2.u_int);
|
||||
break;
|
||||
case TYPE_INT_BIN:
|
||||
if (!assign) {
|
||||
Error1("option \"%s\": values required", a0);
|
||||
continue;
|
||||
}
|
||||
{
|
||||
char *rest;
|
||||
(*opts)[i].value.u_int = strtoul(token, &rest, 0);
|
||||
if (*rest != ':') {
|
||||
Error1("option \"%s\": 2 arguments required",
|
||||
ent->desc->defname);
|
||||
}
|
||||
++rest;
|
||||
optlen = 0;
|
||||
if ((result = dalan(rest, optbuf, &optlen, sizeof(optbuf))) != 0) {
|
||||
Error1("parseopts(): problem with \"%s\" data", rest);
|
||||
continue;
|
||||
}
|
||||
if (((*opts)[i].value2.u_bin.b_data = memdup(optbuf, optlen)) == NULL) {
|
||||
Error1("memdup(, "F_Zu"): out of memory", optlen);
|
||||
return -1;
|
||||
}
|
||||
(*opts)[i].value2.u_bin.b_len = optlen;
|
||||
}
|
||||
Info2("setting option \"%s\" to %d:..."/*!!!*/, ent->desc->defname,
|
||||
(*opts)[i].value.u_int);
|
||||
break;
|
||||
case TYPE_INT_STRING:
|
||||
if (!assign) {
|
||||
Error1("option \"%s\": values required", a0);
|
||||
continue;
|
||||
}
|
||||
{
|
||||
char *rest;
|
||||
(*opts)[i].value.u_int = strtoul(token, &rest, 0);
|
||||
if (*rest != ':') {
|
||||
Error1("option \"%s\": 2 arguments required",
|
||||
ent->desc->defname);
|
||||
}
|
||||
++rest;
|
||||
if (((*opts)[i].value2.u_string = strdup(rest)) == NULL) {
|
||||
Error("out of memory"); return -1;
|
||||
}
|
||||
}
|
||||
Info3("setting option \"%s\" to %d:\"%s\"", ent->desc->defname,
|
||||
(*opts)[i].value.u_int, (*opts)[i].value2.u_string);
|
||||
break;
|
||||
case TYPE_INT_INT_INT:
|
||||
if (!assign) {
|
||||
Error1("option \"%s\": values required", a0);
|
||||
continue;
|
||||
}
|
||||
{
|
||||
char *rest;
|
||||
(*opts)[i].value.u_int = strtoul(token, &rest, 0);
|
||||
if (*rest != ':') {
|
||||
Error1("option \"%s\": 3 arguments required",
|
||||
ent->desc->defname);
|
||||
}
|
||||
++rest;
|
||||
(*opts)[i].value2.u_int = strtoul(rest, &rest, 0);
|
||||
if (*rest != ':') {
|
||||
Error1("option \"%s\": 3 arguments required",
|
||||
ent->desc->defname);
|
||||
}
|
||||
++rest;
|
||||
(*opts)[i].value3.u_int = strtoul(rest, &rest, 0);
|
||||
}
|
||||
Info4("setting option \"%s\" to %d:%d:%d", ent->desc->defname,
|
||||
(*opts)[i].value.u_int, (*opts)[i].value2.u_int, (*opts)[i].value3.u_int);
|
||||
break;
|
||||
case TYPE_INT_INT_BIN:
|
||||
if (!assign) {
|
||||
Error1("option \"%s\": values required", a0);
|
||||
continue;
|
||||
}
|
||||
{
|
||||
char *rest;
|
||||
(*opts)[i].value.u_int = strtoul(token, &rest, 0);
|
||||
if (*rest != ':') {
|
||||
Error1("option \"%s\": 3 arguments required",
|
||||
ent->desc->defname);
|
||||
}
|
||||
++rest;
|
||||
(*opts)[i].value2.u_int = strtoul(rest, &rest, 0);
|
||||
if (*rest != ':') {
|
||||
Error1("option \"%s\": 3 arguments required",
|
||||
ent->desc->defname);
|
||||
}
|
||||
++rest;
|
||||
optlen = 0;
|
||||
if ((result = dalan(rest, optbuf, &optlen, sizeof(optbuf))) != 0) {
|
||||
Error1("parseopts(): problem with \"%s\" data", rest);
|
||||
continue;
|
||||
}
|
||||
if (((*opts)[i].value3.u_bin.b_data = memdup(optbuf, optlen)) == NULL) {
|
||||
Error1("memdup(, "F_Zu"): out of memory", optlen);
|
||||
return -1;
|
||||
}
|
||||
(*opts)[i].value3.u_bin.b_len = optlen;
|
||||
}
|
||||
Info3("setting option \"%s\" to %d:%d:..."/*!!!*/, ent->desc->defname,
|
||||
(*opts)[i].value.u_int, (*opts)[i].value2.u_int);
|
||||
break;
|
||||
case TYPE_INT_INT_STRING:
|
||||
if (!assign) {
|
||||
Error1("option \"%s\": values required", a0);
|
||||
continue;
|
||||
}
|
||||
{
|
||||
char *rest;
|
||||
(*opts)[i].value.u_int = strtoul(token, &rest, 0);
|
||||
if (*rest != ':') {
|
||||
Error1("option \"%s\": 3 arguments required",
|
||||
ent->desc->defname);
|
||||
}
|
||||
++rest;
|
||||
(*opts)[i].value2.u_int = strtoul(rest, &rest, 0);
|
||||
if (*rest != ':') {
|
||||
Error1("option \"%s\": 3 arguments required",
|
||||
ent->desc->defname);
|
||||
}
|
||||
++rest;
|
||||
if (((*opts)[i].value3.u_string = strdup(rest)) == NULL) {
|
||||
Error("out of memory"); return -1;
|
||||
}
|
||||
}
|
||||
Info4("setting option \"%s\" to %d:%d:\"%s\"", ent->desc->defname,
|
||||
(*opts)[i].value.u_int, (*opts)[i].value2.u_int,
|
||||
(*opts)[i].value3.u_int);
|
||||
break;
|
||||
#if defined(HAVE_STRUCT_IP_MREQ) || defined (HAVE_STRUCT_IP_MREQN)
|
||||
case TYPE_IP_MREQN:
|
||||
{
|
||||
|
@ -2520,13 +2681,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,
|
||||
|
@ -2548,22 +2709,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:
|
||||
|
@ -2571,6 +2736,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,
|
||||
|
@ -2599,7 +2777,7 @@ int retropt_bind(struct opt *opts,
|
|||
}
|
||||
return STAT_OK;
|
||||
}
|
||||
#endif /* WITH_SOCKET */
|
||||
#endif /* _WITH_SOCKET */
|
||||
|
||||
|
||||
/* applies to fd all options belonging to phase */
|
||||
|
@ -2676,7 +2854,49 @@ int applyopts(int fd, struct opt *opts, unsigned int phase) {
|
|||
opt->desc = ODESC_ERROR; ++opt; continue;
|
||||
}
|
||||
|
||||
#if WITH_SOCKET
|
||||
} else if (opt->desc->func == OFUNC_IOCTL_GENERIC) {
|
||||
switch (opt->desc->type) {
|
||||
case TYPE_INT:
|
||||
if (Ioctl(fd, opt->value.u_int, NULL) < 0) {
|
||||
Error3("ioctl(%d, 0x%x, NULL): %s",
|
||||
fd, opt->value.u_int, strerror(errno));
|
||||
opt->desc = ODESC_ERROR; ++opt; continue;
|
||||
}
|
||||
break;
|
||||
case TYPE_INT_INT:
|
||||
if (Ioctl_int(fd, opt->value.u_int, opt->value2.u_int) < 0) {
|
||||
Error4("ioctl(%d, %d, %p): %s",
|
||||
fd, opt->value.u_int, opt->value2.u_int, strerror(errno));
|
||||
opt->desc = ODESC_ERROR; ++opt; continue;
|
||||
}
|
||||
break;
|
||||
case TYPE_INT_INTP:
|
||||
if (Ioctl(fd, opt->value.u_int, (void *)&opt->value2.u_int) < 0) {
|
||||
Error4("ioctl(%d, 0x%x, %p): %s",
|
||||
fd, opt->value.u_int, (void *)&opt->value2.u_int, strerror(errno));
|
||||
opt->desc = ODESC_ERROR; ++opt; continue;
|
||||
}
|
||||
break;
|
||||
case TYPE_INT_BIN:
|
||||
if (Ioctl(fd, opt->value.u_int, (void *)opt->value2.u_bin.b_data) < 0) {
|
||||
Error4("ioctl(%d, 0x%x, %p): %s",
|
||||
fd, opt->value.u_int, (void *)opt->value2.u_bin.b_data, strerror(errno));
|
||||
opt->desc = ODESC_ERROR; ++opt; continue;
|
||||
}
|
||||
break;
|
||||
case TYPE_INT_STRING:
|
||||
if (Ioctl(fd, opt->value.u_int, (void *)opt->value2.u_string) < 0) {
|
||||
Error4("ioctl(%d, 0x%x, %p): %s",
|
||||
fd, opt->value.u_int, (void *)opt->value2.u_string, strerror(errno));
|
||||
opt->desc = ODESC_ERROR; ++opt; continue;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
Error1("ioctl() data type %d not implemented",
|
||||
opt->desc->type);
|
||||
}
|
||||
|
||||
#if _WITH_SOCKET
|
||||
} else if (opt->desc->func == OFUNC_SOCKOPT) {
|
||||
if (0) {
|
||||
;
|
||||
|
@ -2853,7 +3073,39 @@ int applyopts(int fd, struct opt *opts, unsigned int phase) {
|
|||
opt->desc->defname, opt->desc->type);
|
||||
break;
|
||||
}
|
||||
#endif /* WITH_SOCKET */
|
||||
} else if (opt->desc->func == OFUNC_SOCKOPT_GENERIC) {
|
||||
switch (opt->desc->type) {
|
||||
case TYPE_INT_INT_INT:
|
||||
if (Setsockopt(fd, opt->value.u_int, opt->value2.u_int,
|
||||
&opt->value3.u_int, sizeof(int)) < 0) {
|
||||
Error6("setsockopt(%d, %d, %d, {%d}, "F_Zu"): %s",
|
||||
fd, opt->value.u_int, opt->value2.u_int,
|
||||
opt->value3.u_int, sizeof(int), strerror(errno));
|
||||
}
|
||||
break;
|
||||
case TYPE_INT_INT_BIN:
|
||||
if (Setsockopt(fd, opt->value.u_int, opt->value2.u_int,
|
||||
opt->value3.u_bin.b_data, opt->value3.u_bin.b_len) < 0) {
|
||||
Error5("setsockopt(%d, %d, %d, {...}, "F_Zu"): %s",
|
||||
fd, opt->value.u_int, opt->value2.u_int,
|
||||
opt->value3.u_bin.b_len, strerror(errno));
|
||||
}
|
||||
break;
|
||||
case TYPE_INT_INT_STRING:
|
||||
if (Setsockopt(fd, opt->value.u_int, opt->value2.u_int,
|
||||
opt->value3.u_string,
|
||||
strlen(opt->value3.u_string)+1) < 0) {
|
||||
Error6("setsockopt(%d, %d, %d, \"%s\", "F_Zu"): %s",
|
||||
fd, opt->value.u_int, opt->value2.u_int,
|
||||
opt->value3.u_string, strlen(opt->value3.u_string)+1,
|
||||
strerror(errno));
|
||||
}
|
||||
break;
|
||||
default:
|
||||
Error1("setsockopt() data type %d not implemented",
|
||||
opt->desc->type);
|
||||
}
|
||||
#endif /* _WITH_SOCKET */
|
||||
|
||||
#if HAVE_FLOCK
|
||||
} else if (opt->desc->func == OFUNC_FLOCK) {
|
||||
|
@ -3071,6 +3323,7 @@ int applyopts(int fd, struct opt *opts, unsigned int phase) {
|
|||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default: Error1("applyopts(): option \"%s\" not implemented",
|
||||
opt->desc->defname);
|
||||
opt->desc = ODESC_ERROR; ++opt; continue;
|
||||
|
@ -3567,7 +3820,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))
|
||||
|
@ -3718,7 +3971,7 @@ mc:addr
|
|||
++opt; continue;
|
||||
}
|
||||
break;
|
||||
#endif /* WITH_SOCKET */
|
||||
#endif /* _WITH_SOCKET */
|
||||
|
||||
default:
|
||||
++opt;
|
||||
|
|
39
xioopts.h
39
xioopts.h
|
@ -24,39 +24,53 @@ enum e_types {
|
|||
TYPE_BIN, /* raw binary data, length determined by data */
|
||||
TYPE_BOOL, /* value is 0 or 1 (no-value is interpreted as 1) */
|
||||
TYPE_BYTE, /* unsigned char */
|
||||
|
||||
TYPE_INT, /* int */
|
||||
TYPE_LONG, /* long */
|
||||
TYPE_STRING, /* char * */
|
||||
TYPE_NAME = TYPE_STRING,
|
||||
TYPE_FILENAME = TYPE_STRING,
|
||||
TYPE_PTRDIFF, /* ptrdiff_t */
|
||||
|
||||
TYPE_SHORT, /* short */
|
||||
TYPE_SIZE_T, /* size_t */
|
||||
TYPE_SOCKADDR, /* struct sockaddr * */
|
||||
TYPE_UINT, /* unsigned int */
|
||||
|
||||
TYPE_ULONG, /* unsigned long */
|
||||
TYPE_USHORT, /* unsigned short */
|
||||
TYPE_2BYTE = TYPE_USHORT,
|
||||
TYPE_MODET, /* representation of mode_t */
|
||||
TYPE_GIDT, /* representation of gid_t */
|
||||
|
||||
TYPE_UIDT, /* representation of uid_t */
|
||||
/*TYPE_FLAG,*/
|
||||
TYPE_INT3, /* int[3] */
|
||||
TYPE_TIMEVAL, /* struct timeval: {long;long;}, seconds and microsec. */
|
||||
TYPE_TIMESPEC, /* struct timespec: {time_t;long;}, seconds and nanosec. */
|
||||
#if HAVE_STRUCT_LINGER
|
||||
TYPE_LINGER, /* struct linger */
|
||||
#endif /* HAVE_STRUCT_LINGER */
|
||||
|
||||
TYPE_DOUBLE, /* double */
|
||||
TYPE_STRING_NULL, /* char *; string or NULL */
|
||||
TYPE_LONGLONG, /* long long */
|
||||
TYPE_OFF32, /* off_t */
|
||||
|
||||
TYPE_OFF64, /* off64_t */
|
||||
TYPE_INT_INT, /* 2 parameters: first is int, second is int */
|
||||
TYPE_INT_INTP, /* 2 parameters: first is int, second is int* */
|
||||
TYPE_INT_BIN, /* 2 parameters: first is int, second is binary */
|
||||
|
||||
TYPE_INT_STRING, /* 2 parameters: first is int, second is req string */
|
||||
TYPE_INT_INT_INT, /* 3 params: first and second are int, 3rd is int */
|
||||
TYPE_INT_INT_BIN, /* 3 params: first and second are int, 3rd is binary */
|
||||
TYPE_INT_INT_STRING, /* 3 params: first and second are int, 3rd is string */
|
||||
|
||||
TYPE_IP4NAME, /* IPv4 hostname or address */
|
||||
#if HAVE_STRUCT_LINGER
|
||||
TYPE_LINGER, /* struct linger */
|
||||
#endif /* HAVE_STRUCT_LINGER */
|
||||
#if HAVE_STRUCT_IP_MREQ || HAVE_STRUCT_IP_MREQN
|
||||
TYPE_IP_MREQN, /* for struct ip_mreq or struct ip_mreqn */
|
||||
#endif
|
||||
TYPE_IP4NAME, /* IPv4 hostname or address */
|
||||
|
||||
TYPE_2BYTE = TYPE_USHORT
|
||||
} ;
|
||||
|
||||
enum e_func {
|
||||
|
@ -66,11 +80,14 @@ enum e_func {
|
|||
OFUNC_SEEK32, /* lseek(): arg1 is whence (SEEK_SET etc.) */
|
||||
OFUNC_SEEK64, /* lseek64(): arg1 is whence (SEEK_SET etc.) */
|
||||
OFUNC_FCNTL, /* fcntl(, ): arg1 is cmd */
|
||||
OFUNC_IOCTL, /* ioctl(): arg1 is request */
|
||||
OFUNC_IOCTL, /* ioctl(): arg1 of option description is request, arg2
|
||||
is int setrequest */
|
||||
OFUNC_IOCTL_MASK_LONG, /* arg1 is getrequest, arg2 is setrequest:
|
||||
ioctl(arg1, ); |= arg3; ioctl(arg2, ); */
|
||||
OFUNC_IOCTL_GENERIC, /* generic ioctl() (request on cmdline) */
|
||||
OFUNC_SOCKOPT, /* setsockopt() */
|
||||
OFUNC_SOCKOPT_APPEND,/* getsockopt(), append data, setsockopt() */
|
||||
OFUNC_SOCKOPT_GENERIC,/* generic setsockopt() (level, optname on cmdline) */
|
||||
OFUNC_FLOCK, /* flock() */
|
||||
OFUNC_TERMIO, /* termio() ? */
|
||||
OFUNC_SPEC, /* special, i.e. no generalizable function call */
|
||||
|
@ -349,6 +366,11 @@ enum e_optcode {
|
|||
#if 0 /* see Linux: man 7 netlink; probably not what we need yet */
|
||||
OPT_IO_SIOCGIFNAME,
|
||||
#endif
|
||||
OPT_IOCTL_BIN, /* generic ioctl with binary value (pointed to) */
|
||||
OPT_IOCTL_INT, /* generic ioctl with integer value */
|
||||
OPT_IOCTL_INTP, /* generic ioctl with integer value (pointed to) */
|
||||
OPT_IOCTL_STRING, /* generic ioctl with integer value (pointed to) */
|
||||
OPT_IOCTL_VOID, /* generic ioctl without value */
|
||||
OPT_IP_ADD_MEMBERSHIP,
|
||||
#ifdef IP_HDRINCL
|
||||
OPT_IP_HDRINCL,
|
||||
|
@ -556,6 +578,9 @@ enum e_optcode {
|
|||
OPT_SETGID_EARLY,
|
||||
OPT_SETPGID,
|
||||
OPT_SETSID,
|
||||
OPT_SETSOCKOPT_BIN,
|
||||
OPT_SETSOCKOPT_INT,
|
||||
OPT_SETSOCKOPT_STRING,
|
||||
OPT_SETUID,
|
||||
OPT_SETUID_EARLY,
|
||||
OPT_SIGHUP,
|
||||
|
|
|
@ -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
|
||||
|
@ -378,7 +378,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");
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 {
|
||||
|
|
Loading…
Reference in a new issue