mirror of
https://github.com/moparisthebest/socat
synced 2024-12-21 14:38:48 -05:00
ported generic socket to *BSD; minor improvements
This commit is contained in:
parent
8947cc92dc
commit
13b73776e7
5
CHANGES
5
CHANGES
@ -1,5 +1,10 @@
|
||||
|
||||
new features:
|
||||
added generic socket addresses: SOCKET-CONNECT, SOCKET-LISTEN,
|
||||
SOCKET-SENDTO, SOCKET-RECVFROM, SOCKET-RECV, SOCKET-DATAGRAM allow
|
||||
protocol independent socket handling; all parameters are explicitely
|
||||
specified as numbers or hex data
|
||||
|
||||
added address options ioctl-void, ioctl-int, ioctl-intp, ioctl-string,
|
||||
ioctl-bin for generic ioctl() calls.
|
||||
|
||||
|
2
VERSION
2
VERSION
@ -1 +1 @@
|
||||
"1.6.0.1+ip4bind+recvfromfork+x64+execstderr+execspaces+cosmetics+poll+udplistencont+ignoreeofunblock+ioctl+ioctl+setsockopt"
|
||||
"1.6.0.1+ip4bind+recvfromfork+x64+execstderr+execspaces+cosmetics+poll+udplistencont+ignoreeofunblock+ioctl+setsockopt+genericsocket"
|
||||
|
@ -456,6 +456,7 @@
|
||||
#undef WITH_IP4
|
||||
#undef WITH_IP6
|
||||
#undef WITH_RAWIP
|
||||
#undef WITH_GENERICSOCKET
|
||||
#undef WITH_TCP
|
||||
#undef WITH_UDP
|
||||
#undef WITH_LISTEN
|
||||
|
@ -196,6 +196,14 @@ AC_ARG_ENABLE(rawip, [ --disable-rawip disable raw IP support],
|
||||
esac],
|
||||
[AC_DEFINE(WITH_RAWIP) AC_MSG_RESULT(yes)])
|
||||
|
||||
AC_MSG_CHECKING(whether to include generic socket support)
|
||||
AC_ARG_ENABLE(rawsocket, [ --disable-genericsocket disable generic socket support],
|
||||
[case "$enableval" in
|
||||
no) AC_MSG_RESULT(no);;
|
||||
*) AC_DEFINE(WITH_GENERICSOCKET) AC_MSG_RESULT(yes);;
|
||||
esac],
|
||||
[AC_DEFINE(WITH_GENERICSOCKET) AC_MSG_RESULT(yes)])
|
||||
|
||||
AC_MSG_CHECKING(whether to include TCP support)
|
||||
AC_ARG_ENABLE(tcp, [ --disable-tcp disable TCP support],
|
||||
[case "$enableval" in
|
||||
|
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
|
||||
|
138
doc/socat.yo
138
doc/socat.yo
@ -599,6 +599,144 @@ label(ADDRESS_READLINE)dit(bf(tt(READLINE)))
|
||||
link(noecho)(OPTION_NOECHO)nl()
|
||||
See also:
|
||||
link(STDIO)(ADDRESS_STDIO)
|
||||
label(ADDRESS_SOCKET_CONNECT)dit(bf(tt(SOCKET-CONNECT:<domain>:<protocol>:<remote-address>)))
|
||||
Creates a stream socket using the first and second given socket parameters
|
||||
and tt(SOCK_STREAM) (see man
|
||||
socket(2)) and connects to the remote-address. The
|
||||
two socket parameters have to be specified as numbers of type
|
||||
link(int)(TYPE_INT). Consult your OS documentation and include files to find
|
||||
the desired values. The remote-address must be the link(data)(TYPE_DATA)
|
||||
representation of a sockaddr structure without the sa_family component.nl()
|
||||
Please note that you can - beyond the options of the specified groups - also
|
||||
apply options of higher level protocols when you use socat option
|
||||
link(-s)(option_s).nl()
|
||||
Option groups: link(FD)(GROUP_FD),link(SOCKET)(GROUP_SOCKET),link(CHILD)(GROUP_CHILD),link(RETRY)(GROUP_RETRY)nl()
|
||||
Useful options:
|
||||
link(bind)(OPTION_BIND),
|
||||
link(setsockopt-int)(OPTION_SETSOCKOPT_INT),
|
||||
link(setsockopt-bin)(OPTION_SETSOCKOPT_BIN),
|
||||
link(setsockopt-string)(OPTION_SETSOCKOPT_STRING)
|
||||
nl()
|
||||
See also:
|
||||
link(TCP)(ADDRESS_TCP_CONNECT),
|
||||
link(UDP-CONNECT)(ADDRESS_UDP_CONNECT),
|
||||
link(UNIX-CONNECT)(ADDRESS_UNIX_CONNECT),
|
||||
link(SOCKET-LISTEN)(ADDRESS_SOCKET_LISTEN),
|
||||
link(SOCKET-SENDTO)(ADDRESS_SOCKET_SENDTO)
|
||||
label(ADDRESS_SOCKET_DATAGRAM)dit(bf(tt(SOCKET-DATAGRAM:<domain>:<type>:<protocol>:<remote-address>)))
|
||||
Creates a datagram socket using the first three given socket parameters (see man
|
||||
socket(2)) and sends outgoing data to the remote-address. The
|
||||
three socket parameters have to be specified as numbers of type
|
||||
link(int)(TYPE_INT). Consult your OS documentation and include files to find
|
||||
the desired values. The remote-address must be the link(data)(TYPE_DATA)
|
||||
representation of a sockaddr structure without the sa_family component.nl()
|
||||
Please note that you can - beyond the options of the specified groups - also
|
||||
apply options of higher level protocols when you use socat option
|
||||
link(-s)(option_s).nl()
|
||||
Option groups: link(FD)(GROUP_FD),link(SOCKET)(GROUP_SOCKET),link(RANGE)(GROUP_RANGE)
|
||||
Useful options:
|
||||
link(bind)(OPTION_BIND),
|
||||
link(range)(OPTION_RANGE),
|
||||
link(setsockopt-int)(OPTION_SETSOCKOPT_INT),
|
||||
link(setsockopt-bin)(OPTION_SETSOCKOPT_BIN),
|
||||
link(setsockopt-string)(OPTION_SETSOCKOPT_STRING)
|
||||
nl()
|
||||
See also:
|
||||
link(UDP-DATAGRAM)(ADDRESS_UDP_DATAGRAM),
|
||||
link(IP-DATAGRAM)(ADDRESS_IP_DATAGRAM),
|
||||
link(SOCKET-SENDTO)(ADDRESS_SOCKET_SENDTO),
|
||||
link(SOCKET-RECV)(ADDRESS_SOCKET_RECV),
|
||||
link(SOCKET-RECVFROM)(ADDRESS_SOCKET_RECVFROM)
|
||||
label(ADDRESS_SOCKET_LISTEN)dit(bf(tt(SOCKET-LISTEN:<domain>:<protocol>:<local-address>)))
|
||||
Creates a stream socket using the first and second given socket parameters
|
||||
and tt(SOCK_STREAM) (see man
|
||||
socket(2)) and waits for incoming connections on local-address. The
|
||||
two socket parameters have to be specified as numbers of type
|
||||
link(int)(TYPE_INT). Consult your OS documentation and include files to find
|
||||
the desired values. The local-address must be the link(data)(TYPE_DATA)
|
||||
representation of a sockaddr structure without the sa_family component.nl()
|
||||
Please note that you can - beyond the options of the specified groups - also
|
||||
apply options of higher level protocols when you use socat option
|
||||
link(-s)(option_s).nl()
|
||||
Option groups: link(FD)(GROUP_FD),link(SOCKET)(GROUP_SOCKET),link(LISTEN)(GROUP_LISTEN),link(RANGE)(GROUP_RANGE),link(CHILD)(GROUP_CHILD),link(RETRY)(GROUP_RETRY)nl()
|
||||
Useful options:
|
||||
link(setsockopt-int)(OPTION_SETSOCKOPT_INT),
|
||||
link(setsockopt-bin)(OPTION_SETSOCKOPT_BIN),
|
||||
link(setsockopt-string)(OPTION_SETSOCKOPT_STRING)
|
||||
nl()
|
||||
See also:
|
||||
link(TCP)(ADDRESS_TCP_LISTEN),
|
||||
link(UDP-CONNECT)(ADDRESS_UDP_LISTEN),
|
||||
link(UNIX-CONNECT)(ADDRESS_UNIX_LISTEN),
|
||||
link(SOCKET-LISTEN)(ADDRESS_SOCKET_CONNECT),
|
||||
link(SOCKET-SENDTO)(ADDRESS_SOCKET_RECVFROM),
|
||||
link(SOCKET-SENDTO)(ADDRESS_SOCKET_RECV)
|
||||
label(ADDRESS_SOCKET_RECV)dit(bf(tt(SOCKET_RECV:<domain>:<type>:<protocol>:<local-address>)))
|
||||
Creates a socket using the three given socket parameters (see man
|
||||
socket(2)) and binds it to <local-address>. Receives arriving data. The
|
||||
three parameters have to be specified as numbers of type
|
||||
link(int)(TYPE_INT). Consult your OS documentation and include files to find
|
||||
the desired values. The local-address must be the link(data)(TYPE_DATA)
|
||||
representation of a sockaddr structure without the sa_family component.nl()
|
||||
Option groups: link(FD)(GROUP_FD),link(SOCKET)(GROUP_SOCKET),link(RANGE)(GROUP_RANGE)
|
||||
Useful options:
|
||||
link(range)(OPTION_RANGE),
|
||||
link(setsockopt-int)(OPTION_SETSOCKOPT_INT),
|
||||
link(setsockopt-bin)(OPTION_SETSOCKOPT_BIN),
|
||||
link(setsockopt-string)(OPTION_SETSOCKOPT_STRING)
|
||||
nl()
|
||||
See also:
|
||||
link(UDP-RECV)(ADDRESS_UDP_RECV),
|
||||
link(IP-RECV)(ADDRESS_IP_RECV),
|
||||
link(UNIX-RECV)(ADDRESS_UNIX_RECV),
|
||||
link(SOCKET-DATAGRAM)(ADDRESS_SOCKET_DATAGRAM),
|
||||
link(SOCKET-SENDTO)(ADDRESS_SOCKET_SENDTO),
|
||||
link(SOCKET-RECVFROM)(ADDRESS_SOCKET_RECVFROM)
|
||||
label(ADDRESS_SOCKET_RECVFROM)dit(bf(tt(SOCKET_RECVFROM:<domain>:<type>:<protocol>:<local-address>)))
|
||||
Creates a socket using the three given socket parameters (see man
|
||||
socket(2)) and binds it to <local-address>. Receives arriving data and sends
|
||||
replies back to the sender. The first three parameters have to be specified as
|
||||
numbers of type link(int)(TYPE_INT). Consult your OS documentation and
|
||||
include files to find the desired values. The local-address must be the
|
||||
link(data)(TYPE_DATA)
|
||||
representation of a sockaddr structure without the sa_family component.nl()
|
||||
Option groups: link(FD)(GROUP_FD),link(SOCKET)(GROUP_SOCKET),link(CHILD)(GROUP_CHILD),link(RANGE)(GROUP_RANGE)
|
||||
Useful options:
|
||||
link(fork)(OPTION_FORK),
|
||||
link(range)(OPTION_RANGE),
|
||||
link(setsockopt-int)(OPTION_SETSOCKOPT_INT),
|
||||
link(setsockopt-bin)(OPTION_SETSOCKOPT_BIN),
|
||||
link(setsockopt-string)(OPTION_SETSOCKOPT_STRING)
|
||||
nl()
|
||||
See also:
|
||||
link(UDP-RECVFROM)(ADDRESS_UDP_RECVFROM),
|
||||
link(IP-RECVFROM)(ADDRESS_IP_RECVFROM),
|
||||
link(UNIX-RECVFROM)(ADDRESS_UNIX_RECVFROM),
|
||||
link(SOCKET-DATAGRAM)(ADDRESS_SOCKET_DATAGRAM),
|
||||
link(SOCKET-SENDTO)(ADDRESS_SOCKET_SENDTO),
|
||||
link(SOCKET-RECV)(ADDRESS_SOCKET_RECV)
|
||||
label(ADDRESS_SOCKET_SENDTO)dit(bf(tt(SOCKET_SENDTO:<domain>:<type>:<protocol>:<remote-address>)))
|
||||
Creates a socket using the three given socket parameters (see man
|
||||
socket(2)). Sends outgoing data to the given address and receives replies.
|
||||
The three parameters have to be specified as
|
||||
numbers of type link(int)(TYPE_INT). Consult your OS documentation and
|
||||
include files to find the desired values. The remote-address must be the
|
||||
link(data)(TYPE_DATA) representation of a sockaddr structure without the
|
||||
sa_family component.nl()
|
||||
Option groups: link(FD)(GROUP_FD),link(SOCKET)(GROUP_SOCKET)
|
||||
Useful options:
|
||||
link(bind)(OPTION_BIND),
|
||||
link(setsockopt-int)(OPTION_SETSOCKOPT_INT),
|
||||
link(setsockopt-bin)(OPTION_SETSOCKOPT_BIN),
|
||||
link(setsockopt-string)(OPTION_SETSOCKOPT_STRING)
|
||||
nl()
|
||||
See also:
|
||||
link(UDP-SENDTO)(ADDRESS_UDP_SENDTO),
|
||||
link(IP-SENDTO)(ADDRESS_IP_SENDTO),
|
||||
link(UNIX-SENDTO)(ADDRESS_UNIX_SENDTO),
|
||||
link(SOCKET-DATAGRAM)(ADDRESS_SOCKET_DATAGRAM),
|
||||
link(SOCKET-RECV)(ADDRESS_SOCKET_RECV)
|
||||
link(SOCKET-RECVFROM)(ADDRESS_SOCKET_RECVFROM)
|
||||
label(ADDRESS_SOCKS4)dit(bf(tt(SOCKS4:<socks-server>:<host>:<port>)))
|
||||
Connects via <socks-server> [link(IP address)(TYPE_IP_ADDRESS)]
|
||||
to <host> [link(IPv4 address)(TYPE_IPV4_ADDRESS)]
|
||||
|
8
fdname.c
8
fdname.c
@ -139,7 +139,7 @@ int statname(const char *file, int fd, int filetype, FILE *outfile) {
|
||||
if (file) fprintf(outfile, " %s", file);
|
||||
break;
|
||||
case (S_IFSOCK>>12): /* 12, socket */
|
||||
#if WITH_SOCKET
|
||||
#if _WITH_SOCKET
|
||||
if (fd >= 0) {
|
||||
result = sockname(fd, outfile);
|
||||
} else if (file) {
|
||||
@ -150,7 +150,7 @@ int statname(const char *file, int fd, int filetype, FILE *outfile) {
|
||||
#else
|
||||
Error("SOCKET support not compiled in");
|
||||
return -1;
|
||||
#endif /* !WITH_SOCKET */
|
||||
#endif /* !_WITH_SOCKET */
|
||||
break;
|
||||
}
|
||||
/* ioctl() */
|
||||
@ -185,7 +185,7 @@ int cdevname(int fd, FILE *outfile) {
|
||||
}
|
||||
|
||||
|
||||
#if WITH_SOCKET
|
||||
#if _WITH_SOCKET
|
||||
int sockname(int fd, FILE *outfile) {
|
||||
#define FDNAME_OPTLEN 256
|
||||
#define FDNAME_NAMELEN 256
|
||||
@ -320,7 +320,7 @@ int sockname(int fd, FILE *outfile) {
|
||||
#undef FDNAME_OPTLEN
|
||||
#undef FDNAME_NAMELEN
|
||||
}
|
||||
#endif /* WITH_SOCKET */
|
||||
#endif /* _WITH_SOCKET */
|
||||
|
||||
|
||||
|
||||
|
22
filan.c
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
|
||||
@ -634,7 +634,7 @@ int sockan(int fd, FILE *outfile) {
|
||||
#undef FILAN_OPTLEN
|
||||
#undef FILAN_NAMELEN
|
||||
}
|
||||
#endif /* WITH_SOCKET */
|
||||
#endif /* _WITH_SOCKET */
|
||||
|
||||
|
||||
#if WITH_IP4 || WITH_IP6
|
||||
@ -823,7 +823,7 @@ int tcpan(int fd, FILE *outfile) {
|
||||
#endif /* WITH_TCP */
|
||||
|
||||
|
||||
#if WITH_SOCKET
|
||||
#if _WITH_SOCKET
|
||||
int sockoptan(int fd, const struct sockopt *optname, int socklay, FILE *outfile) {
|
||||
#define FILAN_OPTLEN 256
|
||||
char optval[FILAN_OPTLEN];
|
||||
@ -859,10 +859,10 @@ int sockoptan(int fd, const struct sockopt *optname, int socklay, FILE *outfile)
|
||||
return 0;
|
||||
#undef FILAN_OPTLEN
|
||||
}
|
||||
#endif /* WITH_SOCKET */
|
||||
#endif /* _WITH_SOCKET */
|
||||
|
||||
|
||||
#if WITH_SOCKET
|
||||
#if _WITH_SOCKET
|
||||
int isasocket(int fd) {
|
||||
int retval;
|
||||
#if HAVE_STAT64
|
||||
@ -883,7 +883,7 @@ int isasocket(int fd) {
|
||||
/* note: when S_ISSOCK was undefined, it always gives 0 */
|
||||
return S_ISSOCK(props.st_mode);
|
||||
}
|
||||
#endif /* WITH_SOCKET */
|
||||
#endif /* _WITH_SOCKET */
|
||||
|
||||
|
||||
const char *getfiletypestring(int st_mode) {
|
||||
|
6
filan.h
6
filan.h
@ -1,5 +1,5 @@
|
||||
/* source: filan.h */
|
||||
/* Copyright Gerhard Rieger 2001-2007 */
|
||||
/* Copyright Gerhard Rieger 2001-2008 */
|
||||
|
||||
/* Published under the GNU General Public License V.2, see file COPYING */
|
||||
|
||||
@ -26,12 +26,12 @@ extern int filan_stat(
|
||||
|
||||
extern int cdevan(int fd, FILE *outfile);
|
||||
|
||||
#if WITH_SOCKET
|
||||
#if _WITH_SOCKET
|
||||
extern int isasocket(int fd);
|
||||
extern int sockan(int fd, FILE *outfile);
|
||||
extern int ipan(int fd, FILE *outfile);
|
||||
extern int ip6an(int fd, FILE *outfile);
|
||||
#endif /* WITH_SOCKET */
|
||||
#endif /* _WITH_SOCKET */
|
||||
|
||||
extern int fdname(const char *file, int fd, FILE *outfile);
|
||||
|
||||
|
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: man 4 networking */
|
||||
@ -80,4 +80,4 @@ static int iffan(FILE *outfile) {
|
||||
#endif /* defined(SIOCGIFINDEX) */
|
||||
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
|
||||
|
@ -106,6 +106,7 @@ void socket_in6_init(struct sockaddr_in6 *sa) {
|
||||
length of the specific socket address, or 0 on error. */
|
||||
socklen_t socket_init(int af, union sockaddr_union *sa) {
|
||||
switch (af) {
|
||||
case AF_UNSPEC: memset(sa, 0, sizeof(*sa)); return sizeof(*sa);
|
||||
#if WITH_UNIX
|
||||
case AF_UNIX: socket_un_init(&sa->un); return sizeof(sa->un);
|
||||
#endif
|
||||
@ -134,6 +135,14 @@ char *sockaddr_info(const struct sockaddr *sa, socklen_t salen, char *buff, size
|
||||
char *cp = lbuff;
|
||||
int n;
|
||||
|
||||
#if HAVE_STRUCT_SOCKADDR_SALEN
|
||||
if ((n = snprintf(cp, blen, "LEN=%d ", sa->sa_len)) < 0) {
|
||||
Warn1("sockaddr_info(): buffer too short ("F_Zu")", blen);
|
||||
*buff = '\0';
|
||||
return buff;
|
||||
}
|
||||
cp += n, blen -= n;
|
||||
#endif
|
||||
if ((n = snprintf(cp, blen, "AF=%d ", sa->sa_family)) < 0) {
|
||||
Warn1("sockaddr_info(): buffer too short ("F_Zu")", blen);
|
||||
*buff = '\0';
|
||||
|
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 */
|
||||
|
||||
|
432
test.sh
432
test.sh
@ -141,14 +141,21 @@ SunOS)
|
||||
BROADCASTIF="$MAINIF"
|
||||
#BROADCASTIF=hme0
|
||||
#BROADCASTIF=eri0
|
||||
SECONDADDR=$($IFCONFIG $BROADCASTIF |grep 'inet ' |awk '{print($2);}')
|
||||
BCIFADDR="$SECONDADDR"
|
||||
BCADDR=$($IFCONFIG $BROADCASTIF |grep 'broadcast ' |sed 's/.*broadcast/broadcast/' |awk '{print($2);}') ;;
|
||||
#SECONDADDR=$($IFCONFIG $BROADCASTIF |grep 'inet ' |awk '{print($2);}')
|
||||
SECONDADDR=$(expr "$($IFCONFIG -a |grep 'inet ' |fgrep -v ' 127.0.0.1 '| head -n 1)" : '.*inet \([0-9.]*\) .*')
|
||||
#BCIFADDR="$SECONDADDR"
|
||||
#BCADDR=$($IFCONFIG $BROADCASTIF |grep 'broadcast ' |sed 's/.*broadcast/broadcast/' |awk '{print($2);}')
|
||||
;;
|
||||
#AIX|FreeBSD|Solaris)
|
||||
*)
|
||||
SECONDADDR=$(expr "$($IFCONFIG -a |grep 'inet ' |fgrep -v ' 127.0.0.1 '| head -n 1)" : '.*inet \([0-9.]*\) .*')
|
||||
SECONDADDR=$(expr "$($IFCONFIG -a |grep 'inet ' |fgrep -v ' 127.0.0.1 ' |head -n 1)" : '.*inet \([0-9.]*\) .*')
|
||||
;;
|
||||
esac
|
||||
# for generic sockets we need this address in hex form
|
||||
if [ "$SECONDADDR" ]; then
|
||||
SECONDADDRHEX="$(printf "%02x%02x%02x%02x\n" $(echo "$SECONDADDR" |tr '.' '
|
||||
'))"
|
||||
fi
|
||||
|
||||
# for some tests we need a second local IPv6 address
|
||||
case "$UNAME" in
|
||||
@ -184,20 +191,20 @@ vt100|vt320|linux|xterm|cons25|dtterm|aixterm|sun-color)
|
||||
RED="\0033[31m"
|
||||
GREEN="\0033[32m"
|
||||
YELLOW="\0033[33m"
|
||||
if false && [ "$UNAME" = SunOS ]; then
|
||||
NORMAL="\0033[30m"
|
||||
else
|
||||
# if [ "$UNAME" = SunOS ]; then
|
||||
# NORMAL="\0033[30m"
|
||||
# else
|
||||
NORMAL="\0033[39m"
|
||||
fi
|
||||
# fi
|
||||
else
|
||||
RED="\033[31m"
|
||||
GREEN="\033[32m"
|
||||
YELLOW="\033[33m"
|
||||
if false && [ "$UNAME" = SunOS ]; then
|
||||
NORMAL="\033[30m"
|
||||
else
|
||||
# if [ "$UNAME" = SunOS ]; then
|
||||
# NORMAL="\033[30m"
|
||||
# else
|
||||
NORMAL="\033[39m"
|
||||
fi
|
||||
# fi
|
||||
fi
|
||||
OK="${GREEN}OK${NORMAL}"
|
||||
FAILED="${RED}FAILED${NORMAL}"
|
||||
@ -1509,9 +1516,11 @@ testod () {
|
||||
local T="$6"; [ -z "$T" ] && T=0
|
||||
local tf="$td/test$N.stdout"
|
||||
local te="$td/test$N.stderr"
|
||||
local tr="$td/test$N.ref"
|
||||
local tdiff="$td/test$N.diff"
|
||||
local dain="$(date) $RANDOM"
|
||||
local daout="$(echo "$dain" |$OD_C)"
|
||||
echo "$dain" |$OD_C >"$tr"
|
||||
# local daout="$(echo "$dain" |$OD_C)"
|
||||
$PRINTF "test $F_n %s... " $num "$title"
|
||||
(psleep $T; echo "$dain"; psleep $T) |$SOCAT $opts "$arg1" "$arg2" >"$tf" 2>"$te"
|
||||
if [ "$?" != 0 ]; then
|
||||
@ -1519,7 +1528,8 @@ testod () {
|
||||
echo "$SOCAT $opts $arg1 $arg2"
|
||||
cat "$te"
|
||||
numFAIL=$((numFAIL+1))
|
||||
elif echo "$daout" |diff - "$tf" >"$tdiff" 2>&1; then
|
||||
# elif echo "$daout" |diff - "$tf" >"$tdiff" 2>&1; then
|
||||
elif diff "$tr" "$tf" >"$tdiff" 2>&1; then
|
||||
$PRINTF "$OK\n"
|
||||
if [ -n "$debug" ]; then cat $te; fi
|
||||
numOK=$((numOK+1))
|
||||
@ -1574,7 +1584,8 @@ ifprocess () {
|
||||
FreeBSD) l="$(ps -faje |grep "^........ $(printf %5u $1)")" ;;
|
||||
HP-UX) l="$(ps -fade |grep "^........ $(printf %5u $1)")" ;;
|
||||
Linux) l="$(ps -fade |grep "^........ $(printf %5u $1)")" ;;
|
||||
NetBSD) l="$(ps -aj |grep "^........ $(printf %4u $1)")" ;;
|
||||
# NetBSD) l="$(ps -aj |grep "^........ $(printf %4u $1)")" ;;
|
||||
NetBSD) l="$(ps -aj |grep "^[^ ][^ ]*[ ][ ]*$(printf %5u $1) ")" ;;
|
||||
OpenBSD) l="$(ps -kaj |grep "^........ $(printf %5u $1)")" ;;
|
||||
SunOS) l="$(ps -fade |grep "^........ $(printf %5u $1)")" ;;
|
||||
*) l="$(ps -fade |grep "^[^ ][^ ]*[ ][ ]*$(printf %5u $1) ")" ;;
|
||||
@ -1596,8 +1607,9 @@ childprocess () {
|
||||
FreeBSD) l="$(ps -faje |grep "^........ ..... $(printf %5u $1)")" ;;
|
||||
HP-UX) l="$(ps -fade |grep "^........ ..... $(printf %5u $1)")" ;;
|
||||
Linux) l="$(ps -fade |grep "^........ ..... $(printf %5u $1)")" ;;
|
||||
NetBSD) l="$(ps -aj |grep "^........ ..... $(printf %4u $1)")" ;;
|
||||
OpenBSD) l="$(ps -kaj |grep "^........ ..... $(printf %5u $1)")" ;;
|
||||
# NetBSD) l="$(ps -aj |grep "^........ ..... $(printf %4u $1)")" ;;
|
||||
NetBSD) l="$(ps -aj |grep "^[^ ][^ ]*[ ][ ]*..... $(printf %5u $1)")" ;;
|
||||
OpenBSD) l="$(ps -aj |grep "^........ ..... $(printf %5u $1)")" ;;
|
||||
SunOS) l="$(ps -fade |grep "^........ ..... $(printf %5u $1)")" ;;
|
||||
*) l="$(ps -fade |grep "^[^ ][^ ]*[ ][ ]*[0-9][0-9]**[ ][ ]*$(printf %5u $1) ")" ;; esac
|
||||
if [ -z "$l" ]; then
|
||||
@ -4387,7 +4399,7 @@ tr="$td/test$N.ref"
|
||||
tdiff="$td/test$N.diff"
|
||||
da="test$N $(date) $RANDOM"; da="$da$($ECHO '\r')"
|
||||
# the feature that we really want to test is in the readline.sh script:
|
||||
CMD="$SOCAT $opts open:$tpi,nonblock!!open:$tpo exec:\"./readline.sh -nh ./readline-test.sh\",pty,ctty,setsid,raw,echo=0,isig"
|
||||
CMD="$SOCAT $opts -t1 open:$tpi,nonblock!!open:$tpo exec:\"./readline.sh -nh ./readline-test.sh\",pty,ctty,setsid,raw,echo=0,isig"
|
||||
#echo "$CMD" >"$ts"
|
||||
#chmod a+x "$ts"
|
||||
printf "test $F_n $TEST... " $N
|
||||
@ -4459,7 +4471,8 @@ else
|
||||
if [ -n "$debug" ]; then cat $te; fi
|
||||
numOK=$((numOK+1))
|
||||
fi
|
||||
#kill $pid 2>/dev/null
|
||||
kill $pid 2>/dev/null # necc on OpenBSD
|
||||
wait
|
||||
MICROS=$SAVEMICS
|
||||
TERM="$SAVETERM"
|
||||
fi
|
||||
@ -4857,7 +4870,13 @@ NAME=TCP4RANGEBITS
|
||||
case "$TESTS" in
|
||||
*%functions%*|*%security%*|*%tcp%*|*%tcp4%*|*%ip4%*|*%range%*|*%$NAME%*)
|
||||
TEST="$NAME: security of TCP4-L with RANGE option"
|
||||
if [ -z "$SECONDADDR" ]; then
|
||||
# we need access to a second addresses
|
||||
$PRINTF "test $F_n $TEST... ${YELLOW}need a second IPv4 address${NORMAL}\n" $N
|
||||
numCANT=$((numCANT+1))
|
||||
else
|
||||
testserversec "$N" "$TEST" "$opts -s" "tcp4-l:$PORT,reuseaddr,fork,retry=1" "" "range=$SECONDADDR/32" "tcp4:127.0.0.1:$PORT" 4 tcp $PORT 0
|
||||
fi ;; # $SECONDADDR
|
||||
esac
|
||||
PORT=$((PORT+1))
|
||||
N=$((N+1))
|
||||
@ -4866,6 +4885,22 @@ NAME=TCP4RANGEMASK
|
||||
case "$TESTS" in
|
||||
*%functions%*|*%security%*|*%tcp%*|*%tcp4%*|*%ip4%*|*%range%*|*%$NAME%*)
|
||||
TEST="$NAME: security of TCP4-L with RANGE option"
|
||||
if [ -z "$SECONDADDR" ]; then
|
||||
# we need access to a second addresses
|
||||
$PRINTF "test $F_n $TEST... ${YELLOW}need a second IPv4 address${NORMAL}\n" $N
|
||||
numCANT=$((numCANT+1))
|
||||
else
|
||||
testserversec "$N" "$TEST" "$opts -s" "tcp4-l:$PORT,reuseaddr,fork,retry=1" "" "range=$SECONDADDR:255.255.255.255" "tcp4:127.0.0.1:$PORT" 4 tcp $PORT 0
|
||||
fi ;; # $SECONDADDR
|
||||
esac
|
||||
PORT=$((PORT+1))
|
||||
N=$((N+1))
|
||||
|
||||
# like TCP4RANGEMASK, but the "bad" address is within the same class A network
|
||||
NAME=TCP4RANGEMASKHAIRY
|
||||
case "$TESTS" in
|
||||
*%functions%*|*%security%*|*%tcp%*|*%tcp4%*|*%ip4%*|*%range%*|*%$NAME%*)
|
||||
TEST="$NAME: security of TCP4-L with RANGE option"
|
||||
if [ "$UNAME" != Linux ]; then
|
||||
# we need access to more loopback addresses
|
||||
$PRINTF "test $F_n $TEST... ${YELLOW}only on Linux${NORMAL}\n" $N
|
||||
@ -5544,7 +5579,7 @@ N=$((N+1))
|
||||
signum () {
|
||||
if [ ! "$BASH_VERSION" ]; then
|
||||
# we expect:
|
||||
for i in $(kill -l); do echo $i; done |grep -n -i $1 |cut -d: -f1
|
||||
for i in $(POSIXLY_CORRECT=1 kill -l); do echo $i; done |grep -n -i "^$1$" |cut -d: -f1
|
||||
else
|
||||
# expect:
|
||||
# " 1) SIGHUP 2) SIGINT 3) SIGQUIT 4) SIGILL"
|
||||
@ -5566,12 +5601,12 @@ if ! feat=$(testaddrs pty); then
|
||||
$PRINTF "test $F_n $TEST... ${YELLOW}$(echo $feat |tr a-z A-Z) not available${NORMAL}\n" $N
|
||||
numCANT=$((numCANT+1))
|
||||
else
|
||||
SIG=$(signum $signam)
|
||||
SIG="$(signum $signam)"
|
||||
te="$td/test$N.stderr"
|
||||
tpp="$td/test$N.ppid"
|
||||
tp="$td/test$N.pid"
|
||||
$PRINTF "test $F_n $TEST... " $N
|
||||
(sleep 1; kill -$SIG $(cat "$tpp")) &
|
||||
(sleep 1; kill -"$SIG" "$(cat "$tpp")") &
|
||||
# a simple "system:echo $PPID..." does not work on NetBSD, OpenBSD
|
||||
#$SOCAT $opts echo system:'exec /bin/bash -c "echo \$PPID '">$tpp"'; echo \$$ '">$tp; read x\"",nofork 2>"$te"; stat=$?
|
||||
tsh="$td/test$N.sh"
|
||||
@ -5929,10 +5964,13 @@ PORT=$((PORT+1))
|
||||
N=$((N+1))
|
||||
|
||||
|
||||
# test the UDP4-SENDTO and UDP4-RECVFROM addresses together
|
||||
NAME=UDP4DGRAM
|
||||
case "$TESTS" in
|
||||
*%functions%*|*%udp%*|*%udp4%*|*%ip4%*|*%dgram%*|*%$NAME%*)
|
||||
TEST="$NAME: UDP/IPv4 datagram"
|
||||
TEST="$NAME: UDP/IPv4 sendto and recvfrom"
|
||||
# start a UDP4-RECVFROM process that echoes data, and send test data using
|
||||
# UDP4-SENDTO. The sent data should be returned.
|
||||
tf="$td/test$N.stdout"
|
||||
te="$td/test$N.stderr"
|
||||
tdiff="$td/test$N.diff"
|
||||
@ -5954,16 +5992,16 @@ kill "$pid1" 2>/dev/null; wait;
|
||||
if [ "$rc2" -ne 0 ]; then
|
||||
$PRINTF "$FAILED: $SOCAT:\n"
|
||||
echo "$CMD1 &"
|
||||
echo "$CMD2"
|
||||
cat "${te}1"
|
||||
echo "$CMD2"
|
||||
cat "${te}2"
|
||||
numFAIL=$((numFAIL+1))
|
||||
elif ! echo "$da" |diff - "$tf" >"$tdiff"; then
|
||||
$PRINTF "$FAILED\n"
|
||||
cat "$tdiff"
|
||||
echo "$CMD1 &"
|
||||
echo "$CMD2"
|
||||
cat "${te}1"
|
||||
echo "$CMD2"
|
||||
cat "${te}2"
|
||||
numFAIL=$((numFAIL+1))
|
||||
else
|
||||
@ -8447,6 +8485,334 @@ esac
|
||||
N=$((N+1))
|
||||
|
||||
|
||||
# test the SOCKET-CONNECT address (against TCP4-LISTEN)
|
||||
NAME=SOCKET_CONNECT
|
||||
case "$TESTS" in
|
||||
*%functions%*|*%generic%*|*%socket%*|*%$NAME%*)
|
||||
TEST="$NAME: socket connect with TCP/IPv4"
|
||||
# start a TCP4-LISTEN process that echoes data, and send test data using
|
||||
# SOCKET-CONNECT, selecting TCP/IPv4. The sent data should be returned.
|
||||
tf="$td/test$N.stdout"
|
||||
te="$td/test$N.stderr"
|
||||
tdiff="$td/test$N.diff"
|
||||
ts0p=$PORT; PORT=$((PORT+1))
|
||||
ts0a="127.0.0.1"
|
||||
ts1p=$(printf "%04x" $ts0p);
|
||||
ts1a="7f000001" # "127.0.0.1"
|
||||
ts1="x${ts1p}${ts1a}x0000000000000000"
|
||||
ts1b=$(printf "%04x" $PORT); PORT=$((PORT+1))
|
||||
da="$(date) $RANDOM"
|
||||
CMD0="$SOCAT $opts TCP4-LISTEN:$ts0p,reuseaddr,bind=$ts0a PIPE"
|
||||
CMD1="$SOCAT $opts - SOCKET-CONNECT:2:6:$ts1,bind=x${ts1b}00000000x0000000000000000"
|
||||
printf "test $F_n $TEST... " $N
|
||||
$CMD0 2>"${te}0" &
|
||||
pid0="$!"
|
||||
waittcp4port $ts0p 1
|
||||
echo "$da" |$CMD1 >>"$tf" 2>>"${te}1"
|
||||
rc1="$?"
|
||||
kill "$pid0" 2>/dev/null; wait;
|
||||
if [ "$rc1" -ne 0 ]; then
|
||||
$PRINTF "$FAILED: $SOCAT:\n"
|
||||
echo "$CMD0 &"
|
||||
cat "${te}0"
|
||||
echo "$CMD1"
|
||||
cat "${te}1"
|
||||
numFAIL=$((numFAIL+1))
|
||||
elif ! echo "$da" |diff - "$tf" >"$tdiff"; then
|
||||
$PRINTF "$FAILED\n"
|
||||
cat "$tdiff"
|
||||
echo "$CMD0 &"
|
||||
cat "${te}0"
|
||||
echo "$CMD1"
|
||||
cat "${te}1"
|
||||
numFAIL=$((numFAIL+1))
|
||||
else
|
||||
$PRINTF "$OK\n"
|
||||
if [ -n "$debug" ]; then cat $te; fi
|
||||
numOK=$((numOK+1))
|
||||
fi ;;
|
||||
esac
|
||||
PORT=$((PORT+1))
|
||||
N=$((N+1))
|
||||
|
||||
# test the SOCKET-LISTEN address (with TCP4-CONNECT)
|
||||
NAME=SOCKET_LISTEN
|
||||
case "$TESTS" in
|
||||
*%functions%*|*%generic%*|*%socket%*|*%$NAME%*)
|
||||
TEST="$NAME: socket recvfrom with TCP/IPv4"
|
||||
# start a SOCKET-LISTEN process that uses TCP/IPv4 and echoes data, and
|
||||
# send test data using TCP4-CONNECT. The sent data should be returned.
|
||||
tf="$td/test$N.stdout"
|
||||
te="$td/test$N.stderr"
|
||||
tdiff="$td/test$N.diff"
|
||||
ts1p=$PORT; PORT=$((PORT+1))
|
||||
ts1a="127.0.0.1"
|
||||
ts0p=$(printf "%04x" $ts1p);
|
||||
ts0a="7f000001" # "127.0.0.1"
|
||||
ts0="x${ts0p}${ts0a}x0000000000000000"
|
||||
ts1b=$PORT; PORT=$((PORT+1))
|
||||
ts1="$ts1a:$ts1p"
|
||||
da="$(date) $RANDOM"
|
||||
CMD0="$SOCAT $opts SOCKET-LISTEN:2:6:$ts0,reuseaddr PIPE"
|
||||
CMD1="$SOCAT $opts - TCP4-CONNECT:$ts1,bind=:$ts1b"
|
||||
printf "test $F_n $TEST... " $N
|
||||
$CMD0 2>"${te}0" &
|
||||
pid0="$!"
|
||||
#sleep 1
|
||||
waittcp4port $ts1p 1
|
||||
echo "$da" |$CMD1 >>"$tf" 2>>"${te}1"
|
||||
rc1="$?"
|
||||
kill "$pid0" 2>/dev/null; wait;
|
||||
if [ "$rc1" -ne 0 ]; then
|
||||
$PRINTF "$FAILED: $SOCAT:\n"
|
||||
echo "$CMD0 &"
|
||||
cat "${te}0"
|
||||
echo "$CMD1"
|
||||
cat "${te}1"
|
||||
numFAIL=$((numFAIL+1))
|
||||
elif ! echo "$da" |diff - "$tf" >"$tdiff"; then
|
||||
$PRINTF "$FAILED\n"
|
||||
cat "$tdiff"
|
||||
echo "$CMD0 &"
|
||||
cat "${te}0"
|
||||
echo "$CMD1"
|
||||
cat "${te}1"
|
||||
numFAIL=$((numFAIL+1))
|
||||
else
|
||||
$PRINTF "$OK\n"
|
||||
if [ -n "$debug" ]; then cat $te; fi
|
||||
numOK=$((numOK+1))
|
||||
fi ;;
|
||||
esac
|
||||
PORT=$((PORT+1))
|
||||
N=$((N+1))
|
||||
|
||||
SOCK_DGRAM="$($PROCAN -c |grep "^#define[[:space:]]*SOCK_DGRAM[[:space:]]" |cut -d' ' -f3)"
|
||||
|
||||
# test the SOCKET-SENDTO address (against UDP4-RECVFROM)
|
||||
NAME=SOCKET_SENDTO
|
||||
case "$TESTS" in
|
||||
*%functions%*|*%generic%*|*%socket%*|*%ip4%*|*%udp%*|*%dgram%*|*%$NAME%*)
|
||||
TEST="$NAME: socket sendto with UDP/IPv4"
|
||||
# start a UDP4-RECVFROM process that echoes data, and send test data using
|
||||
# SOCKET-SENDTO, selecting UDP/IPv4. The sent data should be returned.
|
||||
tf="$td/test$N.stdout"
|
||||
te="$td/test$N.stderr"
|
||||
tdiff="$td/test$N.diff"
|
||||
ts0p=$PORT; PORT=$((PORT+1))
|
||||
ts0a="127.0.0.1"
|
||||
ts1p=$(printf "%04x" $ts0p);
|
||||
ts1a="7f000001" # "127.0.0.1"
|
||||
ts1="x${ts1p}${ts1a}x0000000000000000"
|
||||
ts1b=$(printf "%04x" $PORT); PORT=$((PORT+1))
|
||||
da="$(date) $RANDOM"
|
||||
CMD0="$SOCAT $opts UDP4-RECVFROM:$ts0p,reuseaddr,bind=$ts0a PIPE"
|
||||
CMD1="$SOCAT $opts - SOCKET-SENDTO:2:$SOCK_DGRAM:17:$ts1,bind=x${ts1b}x00000000x0000000000000000"
|
||||
printf "test $F_n $TEST... " $N
|
||||
$CMD0 2>"${te}0" &
|
||||
pid0="$!"
|
||||
waitudp4port $ts0p 1
|
||||
echo "$da" |$CMD1 >>"$tf" 2>>"${te}1"
|
||||
rc1="$?"
|
||||
kill "$pid0" 2>/dev/null; wait;
|
||||
if [ "$rc1" -ne 0 ]; then
|
||||
$PRINTF "$FAILED: $SOCAT:\n"
|
||||
echo "$CMD0 &"
|
||||
cat "${te}0"
|
||||
echo "$CMD1"
|
||||
cat "${te}1"
|
||||
numFAIL=$((numFAIL+1))
|
||||
elif ! echo "$da" |diff - "$tf" >"$tdiff"; then
|
||||
$PRINTF "$FAILED\n"
|
||||
cat "$tdiff"
|
||||
echo "$CMD0 &"
|
||||
cat "${te}0"
|
||||
echo "$CMD1"
|
||||
cat "${te}1"
|
||||
numFAIL=$((numFAIL+1))
|
||||
else
|
||||
$PRINTF "$OK\n"
|
||||
if [ -n "$debug" ]; then cat $te; fi
|
||||
numOK=$((numOK+1))
|
||||
fi ;;
|
||||
esac
|
||||
PORT=$((PORT+1))
|
||||
N=$((N+1))
|
||||
|
||||
# test the SOCKET-RECVFROM address (with UDP4-SENDTO)
|
||||
NAME=SOCKET_RECVFROM
|
||||
case "$TESTS" in
|
||||
*%functions%*|*%generic%*|*%socket%*|*%ip4%*|*%udp%*|*%dgram%*|*%$NAME%*)
|
||||
TEST="$NAME: socket recvfrom with UDP/IPv4"
|
||||
# start a SOCKET-RECVFROM process that uses UDP/IPv4 and echoes data, and
|
||||
# send test data using UDP4-SENDTO. The sent data should be returned.
|
||||
tf="$td/test$N.stdout"
|
||||
te="$td/test$N.stderr"
|
||||
tdiff="$td/test$N.diff"
|
||||
ts1p=$PORT; PORT=$((PORT+1))
|
||||
ts1a="127.0.0.1"
|
||||
ts0p=$(printf "%04x" $ts1p);
|
||||
ts0a="7f000001" # "127.0.0.1"
|
||||
ts0="x${ts0p}${ts0a}x0000000000000000"
|
||||
ts1b=$PORT; PORT=$((PORT+1))
|
||||
ts1="$ts1a:$ts1p"
|
||||
da="$(date) $RANDOM"
|
||||
CMD0="$SOCAT $opts SOCKET-RECVFROM:2:$SOCK_DGRAM:17:$ts0,reuseaddr PIPE"
|
||||
CMD1="$SOCAT $opts - UDP4-SENDTO:$ts1,bind=:$ts1b"
|
||||
printf "test $F_n $TEST... " $N
|
||||
$CMD0 2>"${te}0" &
|
||||
pid0="$!"
|
||||
sleep 1 # waitudp4port $ts1p 1
|
||||
echo "$da" |$CMD1 >>"$tf" 2>>"${te}1"
|
||||
rc1="$?"
|
||||
kill "$pid0" 2>/dev/null; wait;
|
||||
if [ "$rc1" -ne 0 ]; then
|
||||
$PRINTF "$FAILED: $SOCAT:\n"
|
||||
echo "$CMD0 &"
|
||||
cat "${te}0"
|
||||
echo "$CMD1"
|
||||
cat "${te}1"
|
||||
numFAIL=$((numFAIL+1))
|
||||
elif ! echo "$da" |diff - "$tf" >"$tdiff"; then
|
||||
$PRINTF "$FAILED\n"
|
||||
cat "$tdiff"
|
||||
echo "$CMD0 &"
|
||||
cat "${te}0"
|
||||
echo "$CMD1"
|
||||
cat "${te}1"
|
||||
numFAIL=$((numFAIL+1))
|
||||
else
|
||||
$PRINTF "$OK\n"
|
||||
if [ -n "$debug" ]; then cat $te; fi
|
||||
numOK=$((numOK+1))
|
||||
fi ;;
|
||||
esac
|
||||
PORT=$((PORT+1))
|
||||
N=$((N+1))
|
||||
|
||||
# test the SOCKET-RECV address (with UDP4-SENDTO)
|
||||
NAME=SOCKET_RECV
|
||||
case "$TESTS" in
|
||||
*%functions%*|*%generic%*|*%socket%*|*%ip4%*|*%udp%*|*%dgram%*|*%$NAME%*)
|
||||
TEST="$NAME: socket recv with UDP/IPv4"
|
||||
# start a SOCKET-RECV process that uses UPD/IPv4 and writes received data to file, and
|
||||
# send test data using UDP4-SENDTO.
|
||||
tf="$td/test$N.stdout"
|
||||
te="$td/test$N.stderr"
|
||||
tdiff="$td/test$N.diff"
|
||||
ts1p=$PORT; PORT=$((PORT+1))
|
||||
ts1a="127.0.0.1"
|
||||
ts0p=$(printf "%04x" $ts1p);
|
||||
ts0a="7f000001" # "127.0.0.1"
|
||||
ts0="x${ts0p}${ts0a}x0000000000000000"
|
||||
ts1b=$PORT; PORT=$((PORT+1))
|
||||
ts1="$ts1a:$ts1p"
|
||||
da="$(date) $RANDOM"
|
||||
CMD0="$SOCAT $opts -u SOCKET-RECV:2:$SOCK_DGRAM:17:$ts0,reuseaddr -"
|
||||
CMD1="$SOCAT $opts -u - UDP4-SENDTO:$ts1,bind=:$ts1b"
|
||||
printf "test $F_n $TEST... " $N
|
||||
$CMD0 2>"${te}0" >"$tf" &
|
||||
pid0="$!"
|
||||
sleep 1 # waitudp4port $ts1p 1
|
||||
echo "$da" |$CMD1 2>>"${te}1"
|
||||
rc1="$?"
|
||||
sleep 1
|
||||
kill "$pid0" 2>/dev/null; wait;
|
||||
if [ "$rc1" -ne 0 ]; then
|
||||
$PRINTF "$FAILED: $SOCAT:\n"
|
||||
echo "$CMD0 &"
|
||||
cat "${te}0"
|
||||
echo "$CMD1"
|
||||
cat "${te}1"
|
||||
numFAIL=$((numFAIL+1))
|
||||
elif ! echo "$da" |diff - "$tf" >"$tdiff"; then
|
||||
$PRINTF "$FAILED\n"
|
||||
cat "$tdiff"
|
||||
echo "$CMD0 &"
|
||||
cat "${te}0"
|
||||
echo "$CMD1"
|
||||
cat "${te}1"
|
||||
numFAIL=$((numFAIL+1))
|
||||
else
|
||||
$PRINTF "$OK\n"
|
||||
if [ -n "$debug" ]; then cat $te; fi
|
||||
numOK=$((numOK+1))
|
||||
fi ;;
|
||||
esac
|
||||
PORT=$((PORT+1))
|
||||
N=$((N+1))
|
||||
|
||||
# test SOCKET-DATAGRAM (with UDP4-DATAGRAM)
|
||||
NAME=SOCKET_DATAGRAM
|
||||
case "$TESTS" in
|
||||
*%functions%*|*%generic%*|*%socket%*|*%ip4%*|*%udp%*|*%dgram%*|*%$NAME%*)
|
||||
TEST="$NAME: socket datagram via UDP/IPv4"
|
||||
# start a UDP4-DATAGRAM process that echoes data, and send test data using
|
||||
# SOCKET-DATAGRAM, selecting UDP/IPv4. The sent data should be returned.
|
||||
tf="$td/test$N.stdout"
|
||||
te="$td/test$N.stderr"
|
||||
tdiff="$td/test$N.diff"
|
||||
ts0p=$PORT; PORT=$((PORT+1))
|
||||
ts1p=$PORT; PORT=$((PORT+1))
|
||||
ts0a="127.0.0.1"
|
||||
ts1b=$(printf "%04x" $ts0p);
|
||||
ts1a="7f000001" # "127.0.0.1"
|
||||
ts0b=$(printf "%04x" $ts0p)
|
||||
ts1b=$(printf "%04x" $ts1p)
|
||||
ts1="x${ts0b}${ts1a}x0000000000000000"
|
||||
da="$(date) $RANDOM"
|
||||
CMD0="$SOCAT $opts UDP4-DATAGRAM:$ts0a:$ts1p,bind=:$ts0p,reuseaddr PIPE"
|
||||
CMD1="$SOCAT $opts - SOCKET-DATAGRAM:2:$SOCK_DGRAM:17:$ts1,bind=x${ts1b}x00000000x0000000000000000"
|
||||
printf "test $F_n $TEST... " $N
|
||||
$CMD0 2>"${te}0" &
|
||||
pid0="$!"
|
||||
waitudp4port $ts0p 1
|
||||
echo "$da" |$CMD1 2>>"${te}1" >"$tf"
|
||||
rc1="$?"
|
||||
kill "$pid0" 2>/dev/null; wait;
|
||||
if [ "$rc1" -ne 0 ]; then
|
||||
$PRINTF "$FAILED: $SOCAT:\n"
|
||||
echo "$CMD0 &"
|
||||
cat "${te}0"
|
||||
echo "$CMD1"
|
||||
cat "${te}1"
|
||||
numFAIL=$((numFAIL+1))
|
||||
elif ! echo "$da" |diff - "$tf" >"$tdiff"; then
|
||||
$PRINTF "$FAILED\n"
|
||||
cat "$tdiff"
|
||||
echo "$CMD0 &"
|
||||
cat "${te}0"
|
||||
echo "$CMD1"
|
||||
cat "${te}1"
|
||||
numFAIL=$((numFAIL+1))
|
||||
else
|
||||
$PRINTF "$OK\n"
|
||||
if [ -n "$debug" ]; then cat $te; fi
|
||||
numOK=$((numOK+1))
|
||||
fi ;;
|
||||
esac
|
||||
PORT=$((PORT+1))
|
||||
N=$((N+1))
|
||||
|
||||
NAME=SOCKETRANGEMASK
|
||||
case "$TESTS" in
|
||||
*%functions%*|*%security%*|*%generic%*|*%tcp%*|*%tcp4%*|*%ip4%*|*%socket%*|*%range%*|*%$NAME%*)
|
||||
TEST="$NAME: security of generic socket-listen with RANGE option"
|
||||
if [ -z "$SECONDADDR" ]; then
|
||||
# we need access to more loopback addresses
|
||||
$PRINTF "test $F_n $TEST... ${YELLOW}need a second IPv4 address${NORMAL}\n" $N
|
||||
numCANT=$((numCANT+1))
|
||||
else
|
||||
ts1p=$(printf "%04x" $PORT);
|
||||
testserversec "$N" "$TEST" "$opts -s" "SOCKET-LISTEN:2:6:x${ts1p}x00000000x0000000000000000,reuseaddr,fork,retry=1" "" "range=x0000x7f000000:x0000xffffffff" "SOCKET-CONNECT:2:6:x${ts1p}x${SECONDADDRHEX}x0000000000000000" 4 tcp $PORT 0
|
||||
fi ;; # $SECONDADDR
|
||||
esac
|
||||
PORT=$((PORT+1))
|
||||
N=$((N+1))
|
||||
|
||||
|
||||
TIOCEXCL="$($PROCAN -c |grep "^#define[[:space:]]*TIOCEXCL[[:space:]]" |cut -d' ' -f3)"
|
||||
|
||||
# test the generic ioctl-void option
|
||||
NAME=IOCTL_VOID
|
||||
case "$TESTS" in
|
||||
@ -8458,9 +8824,9 @@ TEST="$NAME: test the ioctl-void option"
|
||||
# process 1 opens it with the TIOCEXCL ioctl;
|
||||
# process 2 opens it too and fails with "device or resource busy" only when the
|
||||
# previous ioctl was successful
|
||||
if [ "$UNAME" != Linux ]; then
|
||||
if [ -z "$TIOCEXCL" ]; then
|
||||
# we use the numeric value of TIOCEXL which is system dependent
|
||||
$PRINTF "test $F_n $TEST... ${YELLOW}only on Linux${NORMAL}\n" $N
|
||||
$PRINTF "test $F_n $TEST... ${YELLOW}no value of TIOCEXCL${NORMAL}\n" $N
|
||||
numCANT=$((numCANT+1))
|
||||
else
|
||||
tp="$td/test$N.pty"
|
||||
@ -8469,7 +8835,7 @@ te="$td/test$N.stderr"
|
||||
tdiff="$td/test$N.diff"
|
||||
da="$(date)"
|
||||
CMD0="$SOCAT $opts PTY,LINK=$tp pipe"
|
||||
CMD1="$SOCAT $opts - file:$tp,ioctl-void=0x540c,raw,echo=0"
|
||||
CMD1="$SOCAT $opts - file:$tp,ioctl-void=$TIOCEXCL,raw,echo=0"
|
||||
CMD2="$SOCAT $opts - file:$tp,raw,echo=0"
|
||||
printf "test $F_n $TEST... " $N
|
||||
$CMD0 >/dev/null 2>"${te}0" &
|
||||
@ -8504,6 +8870,9 @@ esac
|
||||
N=$((N+1))
|
||||
|
||||
|
||||
SOL_SOCKET="$($PROCAN -c |grep "^#define[[:space:]]*SOL_SOCKET[[:space:]]" |cut -d' ' -f3)"
|
||||
SO_REUSEADDR="$($PROCAN -c |grep "^#define[[:space:]]*SO_REUSEADDR[[:space:]]" |cut -d' ' -f3)"
|
||||
|
||||
# test the generic setsockopt-int option
|
||||
NAME=SETSOCKOPT_INT
|
||||
case "$TESTS" in
|
||||
@ -8518,9 +8887,9 @@ TEST="$NAME: test the setsockopt-int option"
|
||||
# process 2 tries to listen on this port with SO_REUSEADDR, will fail if the
|
||||
# (generically specified) SO_REUSEADDR socket options did not work
|
||||
# process 3 connects to this port; only if it is successful the test is ok
|
||||
if [ "$UNAME" != Linux ]; then
|
||||
if [ -z "SO_REUSEADDR" ]; then
|
||||
# we use the numeric value of SO_REUSEADDR which might be system dependent
|
||||
$PRINTF "test $F_n $TEST... ${YELLOW}only on Linux${NORMAL}\n" $N
|
||||
$PRINTF "test $F_n $TEST... ${YELLOW}value of SO_REUSEADDR not known${NORMAL}\n" $N
|
||||
numCANT=$((numCANT+1))
|
||||
else
|
||||
tp="$PORT"
|
||||
@ -8528,8 +8897,7 @@ tf="$td/test$N.stdout"
|
||||
te="$td/test$N.stderr"
|
||||
tdiff="$td/test$N.diff"
|
||||
da="$(date)"
|
||||
# level=SOL_SOCKET=1, optname=SO_REUSEADDR=2, value=1
|
||||
CMD0="$SOCAT $opts TCP4-L:$tp,setsockopt-int=1:2:1 PIPE"
|
||||
CMD0="$SOCAT $opts TCP4-L:$tp,setsockopt-int=$SOL_SOCKET:$SO_REUSEADDR:1 PIPE"
|
||||
CMD1="$SOCAT $opts - TCP:localhost:$tp"
|
||||
CMD2="$CMD0"
|
||||
CMD3="$CMD1"
|
||||
|
86
xio-ip.c
86
xio-ip.c
@ -423,90 +423,4 @@ int xiogetaddrinfo(const char *node, const char *service,
|
||||
return STAT_OK;
|
||||
}
|
||||
|
||||
|
||||
int xioparsenetwork(const char *rangename, int pf, union xiorange_union *range) {
|
||||
#if WITH_IP4
|
||||
struct in_addr *netaddr_in = &range->ip4.netaddr;
|
||||
struct in_addr *netmask_in = &range->ip4.netmask;
|
||||
#endif /* WITH_IP4 */
|
||||
struct hostent *maskaddr;
|
||||
char *delimpos; /* absolute address of delimiter */
|
||||
int bits;
|
||||
|
||||
switch (pf) {
|
||||
#if WITH_IP4
|
||||
char *rangename1; /* a copy of rangename with writing allowed */
|
||||
case PF_INET:
|
||||
if ((rangename1 = strdup(rangename)) == NULL) {
|
||||
Error1("strdup(\"%s\"): out of memory", rangename);
|
||||
return STAT_RETRYLATER;
|
||||
}
|
||||
|
||||
if (delimpos = strchr(rangename1, '/')) {
|
||||
bits = strtoul(delimpos+1, NULL, 10);
|
||||
netmask_in->s_addr = htonl((0xffffffff << (32-bits)));
|
||||
} else if (delimpos = strchr(rangename1, ':')) {
|
||||
if ((maskaddr = Gethostbyname(delimpos+1)) == NULL) {
|
||||
Error2("gethostbyname(\"%s\"): %s", delimpos+1,
|
||||
h_errno == NETDB_INTERNAL ? strerror(errno) :
|
||||
hstrerror(h_errno));
|
||||
return STAT_NORETRY;
|
||||
}
|
||||
netmask_in->s_addr = *(uint32_t *)maskaddr->h_addr_list[0];
|
||||
} else {
|
||||
Error1("xioparsenetwork(\"%s\",,): missing netmask delimiter", rangename);
|
||||
free(rangename1);
|
||||
return STAT_NORETRY;
|
||||
}
|
||||
{
|
||||
struct hostent *nameaddr;
|
||||
*delimpos = 0;
|
||||
if ((nameaddr = Gethostbyname(rangename1)) == NULL) {
|
||||
Error2("gethostbyname(\"%s\"): %s", rangename1,
|
||||
h_errno == NETDB_INTERNAL ? strerror(errno) :
|
||||
hstrerror(h_errno));
|
||||
free(rangename1);
|
||||
return STAT_NORETRY;
|
||||
}
|
||||
netaddr_in->s_addr = *(unsigned long *)nameaddr->h_addr_list[0];
|
||||
}
|
||||
free(rangename1);
|
||||
break;
|
||||
#endif /* WITH_IP4 */
|
||||
#if WITH_IP6
|
||||
case PF_INET6:
|
||||
return xioparsenetwork_ip6(rangename, &range->ip6);
|
||||
break;
|
||||
#endif /* WITH_IP6 */
|
||||
default:
|
||||
Error1("range option not supported with address family %d", pf);
|
||||
return STAT_NORETRY;
|
||||
}
|
||||
return STAT_OK;
|
||||
}
|
||||
|
||||
/* parses a string of form address/bits or address:mask, and fills the fields
|
||||
of the range union. The addr component is masked with mask. */
|
||||
int parserange(const char *rangename, int pf, union xiorange_union *range) {
|
||||
if (xioparsenetwork(rangename, pf, range) < 0) {
|
||||
return -1;
|
||||
}
|
||||
switch (pf) {
|
||||
#if WITH_IP4
|
||||
case PF_INET:
|
||||
range->ip4.netaddr.s_addr &= range->ip4.netmask.s_addr;
|
||||
break;
|
||||
#endif /* WITH_IP4 */
|
||||
#if WITH_IP6
|
||||
case PF_INET6:
|
||||
return xiorange_ip6andmask(&range->ip6);
|
||||
break;
|
||||
#endif /* WITH_IP6 */
|
||||
default:
|
||||
Error1("range option not supported with address family %d", pf);
|
||||
return STAT_NORETRY;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* _WITH_IP4 || _WITH_IP6 */
|
||||
|
7
xio-ip.h
7
xio-ip.h
@ -1,5 +1,5 @@
|
||||
/* source: xio-ip.h */
|
||||
/* Copyright Gerhard Rieger 2001-2007 */
|
||||
/* Copyright Gerhard Rieger 2001-2008 */
|
||||
/* Published under the GNU General Public License V.2, see file COPYING */
|
||||
|
||||
#ifndef __xio_ip_h_included
|
||||
@ -39,10 +39,5 @@ extern int xiogetaddrinfo(const char *node, const char *service,
|
||||
int family, int socktype, int protocol,
|
||||
union sockaddr_union *sa, socklen_t *socklen,
|
||||
unsigned long res_opts0, unsigned long res_opts1);
|
||||
extern
|
||||
int xioparsenetwork(const char *rangename, int pf,
|
||||
union xiorange_union *range);
|
||||
extern
|
||||
int parserange(const char *rangename, int pf, union xiorange_union *range);
|
||||
|
||||
#endif /* !defined(__xio_ip_h_included) */
|
||||
|
54
xio-ip4.c
54
xio-ip4.c
@ -1,5 +1,5 @@
|
||||
/* source: xio-ip4.c */
|
||||
/* Copyright Gerhard Rieger 2001-2007 */
|
||||
/* Copyright Gerhard Rieger 2001-2008 */
|
||||
/* Published under the GNU General Public License V.2, see file COPYING */
|
||||
|
||||
/* this file contains the source for IP4 related functions */
|
||||
@ -13,11 +13,57 @@
|
||||
#include "xio-ip.h"
|
||||
#include "xio-ip4.h"
|
||||
|
||||
|
||||
int xioparsenetwork_ip4(const char *rangename, struct xiorange *range) {
|
||||
struct hostent *maskaddr;
|
||||
struct in_addr *netaddr_in = &range->netaddr.ip4.sin_addr;
|
||||
struct in_addr *netmask_in = &range->netmask.ip4.sin_addr;
|
||||
char *rangename1; /* a copy of rangename with writing allowed */
|
||||
char *delimpos; /* absolute address of delimiter */
|
||||
int bits;
|
||||
|
||||
if ((rangename1 = strdup(rangename)) == NULL) {
|
||||
Error1("strdup(\"%s\"): out of memory", rangename);
|
||||
return STAT_RETRYLATER;
|
||||
}
|
||||
|
||||
if (delimpos = strchr(rangename1, '/')) {
|
||||
bits = strtoul(delimpos+1, NULL, 10);
|
||||
netmask_in->s_addr = htonl((0xffffffff << (32-bits)));
|
||||
} else if (delimpos = strchr(rangename1, ':')) {
|
||||
if ((maskaddr = Gethostbyname(delimpos+1)) == NULL) {
|
||||
Error2("gethostbyname(\"%s\"): %s", delimpos+1,
|
||||
h_errno == NETDB_INTERNAL ? strerror(errno) :
|
||||
hstrerror(h_errno));
|
||||
return STAT_NORETRY;
|
||||
}
|
||||
netmask_in->s_addr = *(uint32_t *)maskaddr->h_addr_list[0];
|
||||
} else {
|
||||
Error1("xioparsenetwork_ip4(\"%s\",,): missing netmask delimiter", rangename);
|
||||
free(rangename1);
|
||||
return STAT_NORETRY;
|
||||
}
|
||||
{
|
||||
struct hostent *nameaddr;
|
||||
*delimpos = 0;
|
||||
if ((nameaddr = Gethostbyname(rangename1)) == NULL) {
|
||||
Error2("gethostbyname(\"%s\"): %s", rangename1,
|
||||
h_errno == NETDB_INTERNAL ? strerror(errno) :
|
||||
hstrerror(h_errno));
|
||||
free(rangename1);
|
||||
return STAT_NORETRY;
|
||||
}
|
||||
netaddr_in->s_addr = *(unsigned long *)nameaddr->h_addr_list[0];
|
||||
}
|
||||
free(rangename1);
|
||||
return STAT_OK;
|
||||
}
|
||||
|
||||
/* check if peer address is within permitted range.
|
||||
return >= 0 if so. */
|
||||
int xiocheckrange_ip4(struct sockaddr_in *pa, struct xiorange_ip4 *range) {
|
||||
struct in_addr *netaddr_in = &range->netaddr;
|
||||
struct in_addr *netmask_in = &range->netmask;
|
||||
int xiocheckrange_ip4(struct sockaddr_in *pa, struct xiorange *range) {
|
||||
struct in_addr *netaddr_in = &range->netaddr.ip4.sin_addr;
|
||||
struct in_addr *netmask_in = &range->netmask.ip4.sin_addr;
|
||||
char addrbuf[256], maskbuf[256];
|
||||
char peername[256];
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* source: xio-ip4.h */
|
||||
/* Copyright Gerhard Rieger 2001-2007 */
|
||||
/* Copyright Gerhard Rieger 2001-2008 */
|
||||
/* Published under the GNU General Public License V.2, see file COPYING */
|
||||
|
||||
#ifndef __xio_ip4_h_included
|
||||
@ -8,6 +8,8 @@
|
||||
extern const struct optdesc opt_ip4_add_membership;
|
||||
|
||||
extern
|
||||
int xiocheckrange_ip4(struct sockaddr_in *pa, struct xiorange_ip4 *range);
|
||||
int xioparsenetwork_ip4(const char *rangename, struct xiorange *range);
|
||||
extern
|
||||
int xiocheckrange_ip4(struct sockaddr_in *pa, struct xiorange *range);
|
||||
|
||||
#endif /* !defined(__xio_ip4_h_included) */
|
||||
|
19
xio-ip6.c
19
xio-ip6.c
@ -1,5 +1,5 @@
|
||||
/* source: xio-ip6.c */
|
||||
/* Copyright Gerhard Rieger 2001-2007 */
|
||||
/* Copyright Gerhard Rieger 2001-2008 */
|
||||
/* Published under the GNU General Public License V.2, see file COPYING */
|
||||
|
||||
/* this file contains the source for IP6 related functions */
|
||||
@ -21,15 +21,15 @@ const struct optdesc opt_ipv6_v6only = { "ipv6-v6only", "ipv6only", OPT_IPV6_V6O
|
||||
const struct optdesc opt_ipv6_join_group = { "ipv6-join-group", "join-group", OPT_IPV6_JOIN_GROUP, GROUP_SOCK_IP6, PH_PASTBIND, TYPE_IP_MREQN, OFUNC_SOCKOPT, SOL_IPV6, IPV6_JOIN_GROUP };
|
||||
#endif
|
||||
|
||||
int xioparsenetwork_ip6(const char *rangename, struct xiorange_ip6 *range) {
|
||||
int xioparsenetwork_ip6(const char *rangename, struct xiorange *range) {
|
||||
char *delimpos; /* absolute address of delimiter */
|
||||
size_t delimind; /* index of delimiter in string */
|
||||
int bits;
|
||||
char *baseaddr;
|
||||
union sockaddr_union sockaddr;
|
||||
socklen_t sockaddrlen = sizeof(sockaddr);
|
||||
union xioin6_u *rangeaddr = (union xioin6_u *)&range->addr;
|
||||
union xioin6_u *rangemask = (union xioin6_u *)&range->mask;
|
||||
union xioin6_u *rangeaddr = (union xioin6_u *)&range->netaddr.ip6.sin6_addr;
|
||||
union xioin6_u *rangemask = (union xioin6_u *)&range->netmask.ip6.sin6_addr;
|
||||
union xioin6_u *nameaddr = (union xioin6_u *)&sockaddr.ip6.sin6_addr;
|
||||
|
||||
if (rangename[0] != '[' || rangename[strlen(rangename)-1] != ']') {
|
||||
@ -87,7 +87,7 @@ int xioparsenetwork_ip6(const char *rangename, struct xiorange_ip6 *range) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int xiorange_ip6andmask(struct xiorange_ip6 *range) {
|
||||
int xiorange_ip6andmask(struct xiorange *range) {
|
||||
int i;
|
||||
#if 0
|
||||
range->addr.s6_addr32[0] &= range->mask.s6_addr32[0];
|
||||
@ -96,7 +96,8 @@ int xiorange_ip6andmask(struct xiorange_ip6 *range) {
|
||||
range->addr.s6_addr32[3] &= range->mask.s6_addr32[3];
|
||||
#else
|
||||
for (i = 0; i < 16; ++i) {
|
||||
range->addr.s6_addr[i] &= range->mask.s6_addr[i];
|
||||
range->netaddr.ip6.sin6_addr.s6_addr[i] &=
|
||||
range->netmask.ip6.sin6_addr.s6_addr[i];
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
@ -104,12 +105,12 @@ int xiorange_ip6andmask(struct xiorange_ip6 *range) {
|
||||
|
||||
/* check if peer address is within permitted range.
|
||||
return >= 0 if so. */
|
||||
int xiocheckrange_ip6(struct sockaddr_in6 *pa, struct xiorange_ip6 *range) {
|
||||
int xiocheckrange_ip6(struct sockaddr_in6 *pa, struct xiorange *range) {
|
||||
union xioin6_u masked;
|
||||
int i;
|
||||
char peername[256];
|
||||
union xioin6_u *rangeaddr = (union xioin6_u *)&range->addr;
|
||||
union xioin6_u *rangemask = (union xioin6_u *)&range->mask;
|
||||
union xioin6_u *rangeaddr = (union xioin6_u *)&range->netaddr.ip6.sin6_addr;
|
||||
union xioin6_u *rangemask = (union xioin6_u *)&range->netmask.ip6;
|
||||
|
||||
Debug16("permitted client subnet: [%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x]:[%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x]",
|
||||
htons(rangeaddr->u6_addr16[0]), htons(rangeaddr->u6_addr16[1]),
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* source: xio-ip6.h */
|
||||
/* Copyright Gerhard Rieger 2001-2007 */
|
||||
/* Copyright Gerhard Rieger 2001-2008 */
|
||||
/* Published under the GNU General Public License V.2, see file COPYING */
|
||||
|
||||
#ifndef __xio_ip6_h_included
|
||||
@ -11,11 +11,11 @@ extern const struct optdesc opt_ipv6_v6only;
|
||||
extern const struct optdesc opt_ipv6_join_group;
|
||||
|
||||
extern
|
||||
int xioparsenetwork_ip6(const char *rangename, struct xiorange_ip6 *range);
|
||||
extern int xiorange_ip6andmask(struct xiorange_ip6 *range);
|
||||
int xioparsenetwork_ip6(const char *rangename, struct xiorange *range);
|
||||
extern int xiorange_ip6andmask(struct xiorange *range);
|
||||
|
||||
extern
|
||||
int xiocheckrange_ip6(struct sockaddr_in6 *pa, struct xiorange_ip6 *range);
|
||||
int xiocheckrange_ip6(struct sockaddr_in6 *pa, struct xiorange *range);
|
||||
|
||||
#endif /* WITH_IP6 */
|
||||
|
||||
|
22
xio-listen.c
22
xio-listen.c
@ -83,6 +83,9 @@ int
|
||||
|
||||
/* waits for incoming connection, checks its source address and port. Depending
|
||||
on fork option, it may fork a subprocess.
|
||||
pf specifies the syntax expected for range option. In the case of generic
|
||||
socket it is 0 (expcting raw binary data), and the real pf can be obtained
|
||||
from us->af_family; for other socket types pf == us->af_family
|
||||
Returns 0 if a connection was accepted; with fork option, this is always in
|
||||
a subprocess!
|
||||
Other return values indicate a problem; this can happen in the master
|
||||
@ -119,9 +122,9 @@ int _xioopen_listen(struct single *xfd, int xioflags, struct sockaddr *us, sockl
|
||||
xiosetchilddied(); /* set SIGCHLD handler */
|
||||
}
|
||||
|
||||
if ((xfd->fd = Socket(pf, socktype, proto)) < 0) {
|
||||
if ((xfd->fd = Socket(us->sa_family, socktype, proto)) < 0) {
|
||||
Msg4(level,
|
||||
"socket(%d, %d, %d): %s", pf, socktype, proto, strerror(errno));
|
||||
"socket(%d, %d, %d): %s", us->sa_family, socktype, proto, strerror(errno));
|
||||
return STAT_RETRYLATER;
|
||||
}
|
||||
|
||||
@ -161,15 +164,10 @@ int _xioopen_listen(struct single *xfd, int xioflags, struct sockaddr *us, sockl
|
||||
}
|
||||
#endif /* WITH_UNIX */
|
||||
|
||||
retropt_int(opts, OPT_BACKLOG, &backlog);
|
||||
if (Listen(xfd->fd, backlog) < 0) {
|
||||
Error3("listen(%d, %d): %s", xfd->fd, backlog, strerror(errno));
|
||||
return STAT_RETRYLATER;
|
||||
}
|
||||
|
||||
#if WITH_IP4 /*|| WITH_IP6*/
|
||||
if (retropt_string(opts, OPT_RANGE, &rangename) >= 0) {
|
||||
if (parserange(rangename, us->sa_family, &xfd->para.socket.range) < 0) {
|
||||
if (xioparserange(rangename, pf, &xfd->para.socket.range)
|
||||
< 0) {
|
||||
free(rangename);
|
||||
return STAT_NORETRY;
|
||||
}
|
||||
@ -189,6 +187,12 @@ int _xioopen_listen(struct single *xfd, int xioflags, struct sockaddr *us, sockl
|
||||
retropt_bool(opts, OPT_LOWPORT, &xfd->para.socket.ip.lowport);
|
||||
#endif /* WITH_TCP || WITH_UDP */
|
||||
|
||||
retropt_int(opts, OPT_BACKLOG, &backlog);
|
||||
if (Listen(xfd->fd, backlog) < 0) {
|
||||
Error3("listen(%d, %d): %s", xfd->fd, backlog, strerror(errno));
|
||||
return STAT_RETRYLATER;
|
||||
}
|
||||
|
||||
if (xioopts.logopt == 'm') {
|
||||
Info("starting accept loop, switching to syslog");
|
||||
diag_set('y', xioopts.syslogfac); xioopts.logopt = 'y';
|
||||
|
@ -170,7 +170,7 @@ int xioopen_rawip_datagram(int argc, const char *argv[], struct opt *opts,
|
||||
|
||||
/* which reply packets will be accepted - determine by range option */
|
||||
if (retropt_string(opts, OPT_RANGE, &rangename) >= 0) {
|
||||
if (parserange(rangename, pf, &xfd->para.socket.range) < 0) {
|
||||
if (xioparserange(rangename, pf, &xfd->para.socket.range) < 0) {
|
||||
free(rangename);
|
||||
return STAT_NORETRY;
|
||||
}
|
||||
@ -287,7 +287,8 @@ int xioopen_rawip_recv(int argc, const char *argv[], struct opt *opts,
|
||||
#endif
|
||||
}
|
||||
|
||||
if (retropt_bind(opts, pf, socktype, ipproto, &/*us.soa*/xfd->stream.para.socket.la.soa, &uslen, 1,
|
||||
if (retropt_bind(opts, pf, socktype, ipproto,
|
||||
&/*us.soa*/xfd->stream.para.socket.la.soa, &uslen, 1,
|
||||
xfd->stream.para.socket.ip.res_opts[0],
|
||||
xfd->stream.para.socket.ip.res_opts[1]) ==
|
||||
STAT_OK) {
|
||||
@ -300,7 +301,8 @@ int xioopen_rawip_recv(int argc, const char *argv[], struct opt *opts,
|
||||
xfd->stream.dtype = XIODATA_RECV_SKIPIP;
|
||||
result =
|
||||
_xioopen_dgram_recv(&xfd->stream, xioflags,
|
||||
needbind?&xfd->stream.para.socket.la.soa:NULL, uslen,
|
||||
needbind?&/*us.soa*/xfd->stream.para.socket.la.soa:NULL,
|
||||
uslen,
|
||||
opts, pf, socktype, ipproto, E_ERROR);
|
||||
_xio_openlate(&xfd->stream, opts);
|
||||
return result;
|
||||
|
656
xio-socket.c
656
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"
|
||||
|
||||
@ -18,9 +19,54 @@
|
||||
#include "xio-ip6.h"
|
||||
#endif /* WITH_IP6 */
|
||||
#include "xio-ip.h"
|
||||
#include "xio-listen.h"
|
||||
#include "xio-ipapp.h" /*! not clean */
|
||||
#include "xio-tcpwrap.h"
|
||||
|
||||
|
||||
static
|
||||
int xioopen_socket_connect(int argc, const char *argv[], struct opt *opts,
|
||||
int xioflags, xiofile_t *xfd, unsigned groups,
|
||||
int dummy1, int dummy2, int dummy3);
|
||||
static
|
||||
int xioopen_socket_listen(int argc, const char *argv[], struct opt *opts,
|
||||
int xioflags, xiofile_t *xfd, unsigned groups,
|
||||
int dummy1, int dummy2, int dummy3);
|
||||
static
|
||||
int xioopen_socket_sendto(int argc, const char *argv[], struct opt *opts,
|
||||
int xioflags, xiofile_t *xfd, unsigned groups,
|
||||
int dummy1, int dummy2, int dummy3);
|
||||
static
|
||||
int xioopen_socket_datagram(int argc, const char *argv[], struct opt *opts,
|
||||
int xioflags, xiofile_t *xfd, unsigned groups,
|
||||
int dummy1, int dummy2, int dummy3);
|
||||
static
|
||||
int xioopen_socket_recvfrom(int argc, const char *argv[], struct opt *opts,
|
||||
int xioflags, xiofile_t *xfd, unsigned groups,
|
||||
int dummy1, int socktype, int dummy3);
|
||||
static
|
||||
int xioopen_socket_recv(int argc, const char *argv[], struct opt *opts,
|
||||
int xioflags, xiofile_t *xfd, unsigned groups,
|
||||
int dumy1, int dummy2, int dummy3);
|
||||
|
||||
static
|
||||
int _xioopen_socket_sendto(const char *pfname, const char *type,
|
||||
const char *proto, const char *address,
|
||||
struct opt *opts, int xioflags, xiofile_t *xxfd,
|
||||
unsigned groups);
|
||||
|
||||
|
||||
/* generic socket addresses */
|
||||
const struct addrdesc xioaddr_socket_connect = { "socket-connect", 1, xioopen_socket_connect, GROUP_FD|GROUP_SOCKET|GROUP_CHILD|GROUP_RETRY, 0, 0, 0 HELP(":<domain>:<protocol>:<remote-address>") };
|
||||
const struct addrdesc xioaddr_socket_listen = { "socket-listen", 1, xioopen_socket_listen, GROUP_FD|GROUP_SOCKET|GROUP_LISTEN|GROUP_RANGE|GROUP_CHILD|GROUP_RETRY, 0, 0, 0 HELP(":<domain>:<protocol>:<local-address>") };
|
||||
const struct addrdesc xioaddr_socket_sendto = { "socket-sendto", 3, xioopen_socket_sendto, GROUP_FD|GROUP_SOCKET, 0, 0, 0 HELP(":<domain>:<type>:<protocol>:<remote-address>") };
|
||||
const struct addrdesc xioaddr_socket_datagram= { "socket-datagram", 3, xioopen_socket_datagram, GROUP_FD|GROUP_SOCKET|GROUP_RANGE, 0, 0, 0 HELP(":<domain>:<type>:<protocol>:<remote-address>") };
|
||||
const struct addrdesc xioaddr_socket_recvfrom= { "socket-recvfrom", 3, xioopen_socket_recvfrom, GROUP_FD|GROUP_SOCKET|GROUP_RANGE|GROUP_CHILD, 0, 0, 0 HELP(":<domain>:<type>:<protocol>:<local-address>") };
|
||||
const struct addrdesc xioaddr_socket_recv = { "socket-recv", 1, xioopen_socket_recv, GROUP_FD|GROUP_SOCKET|GROUP_RANGE, 0, 0, 0 HELP(":<domain>:<type>:<protocol>:<local-address>") };
|
||||
|
||||
|
||||
/* the following options apply not only to generic socket addresses but to all
|
||||
addresses that have anything to do with sockets */
|
||||
const struct optdesc opt_so_debug = { "so-debug", "debug", OPT_SO_DEBUG, GROUP_SOCKET, PH_PASTSOCKET, TYPE_INT, OFUNC_SOCKOPT, SOL_SOCKET, SO_DEBUG };
|
||||
#ifdef SO_ACCEPTCONN /* AIX433 */
|
||||
const struct optdesc opt_so_acceptconn={ "so-acceptconn","acceptconn",OPT_SO_ACCEPTCONN,GROUP_SOCKET,PH_PASTSOCKET,TYPE_INT, OFUNC_SOCKOPT, SOL_SOCKET, SO_ACCEPTCONN};
|
||||
@ -133,6 +179,498 @@ const struct optdesc opt_setsockopt_int = { "setsockopt-int", "sockopt-int
|
||||
const struct optdesc opt_setsockopt_bin = { "setsockopt-bin", "sockopt-bin", OPT_SETSOCKOPT_BIN, GROUP_SOCKET,PH_PASTSOCKET,TYPE_INT_INT_BIN, OFUNC_SOCKOPT_GENERIC, 0, 0 };
|
||||
const struct optdesc opt_setsockopt_string = { "setsockopt-string", "sockopt-string", OPT_SETSOCKOPT_STRING, GROUP_SOCKET,PH_PASTSOCKET,TYPE_INT_INT_STRING, OFUNC_SOCKOPT_GENERIC, 0, 0 };
|
||||
|
||||
static
|
||||
int xioopen_socket_connect(int argc, const char *argv[], struct opt *opts,
|
||||
int xioflags, xiofile_t *xxfd, unsigned groups,
|
||||
int dummy1, int dummy2, int dummy3) {
|
||||
struct single *xfd = &xxfd->stream;
|
||||
const char *pfname = argv[1];
|
||||
const char *protname = argv[2];
|
||||
const char *address = argv[3];
|
||||
char *garbage;
|
||||
int pf;
|
||||
int proto;
|
||||
int socktype = SOCK_STREAM;
|
||||
int needbind = 0;
|
||||
union sockaddr_union them; socklen_t themlen;
|
||||
union sockaddr_union us; socklen_t uslen = sizeof(us);
|
||||
int result;
|
||||
|
||||
if (argc != 4) {
|
||||
Error2("%s: wrong number of parameters (%d instead of 3)",
|
||||
argv[0], argc-1);
|
||||
return STAT_NORETRY;
|
||||
}
|
||||
|
||||
pf = strtoul(pfname, &garbage, 0);
|
||||
if (*garbage != '\0') {
|
||||
Warn1("garbage in parameter: \"%s\"", garbage);
|
||||
}
|
||||
|
||||
proto = strtoul(protname, &garbage, 0);
|
||||
if (*garbage != '\0') {
|
||||
Warn1("garbage in parameter: \"%s\"", garbage);
|
||||
}
|
||||
|
||||
retropt_socket_pf(opts, &pf);
|
||||
retropt_int(opts, OPT_SO_TYPE, &socktype);
|
||||
/*retropt_int(opts, OPT_IP_PROTOCOL, &proto);*/
|
||||
xfd->howtoend = END_SHUTDOWN;
|
||||
|
||||
applyopts(-1, opts, PH_INIT);
|
||||
if (applyopts_single(xfd, opts, PH_INIT) < 0) return -1;
|
||||
applyopts(-1, opts, PH_EARLY);
|
||||
|
||||
themlen = 0;
|
||||
if ((result =
|
||||
dalan(address, (char *)&them.soa.sa_data, &themlen, sizeof(them)))
|
||||
< 0) {
|
||||
Error1("data too long: \"%s\"", address);
|
||||
} else if (result > 0) {
|
||||
Error1("syntax error in \"%s\"", address);
|
||||
}
|
||||
them.soa.sa_family = pf;
|
||||
themlen +=
|
||||
#if HAVE_STRUCT_SOCKADDR_SALEN
|
||||
sizeof(them.soa.sa_len) +
|
||||
#endif
|
||||
sizeof(them.soa.sa_family);
|
||||
|
||||
xfd->dtype = XIOREAD_STREAM|XIOWRITE_STREAM;
|
||||
|
||||
socket_init(0, &us);
|
||||
if (retropt_bind(opts, 0 /*pf*/, socktype, proto, (struct sockaddr *)&us, &uslen, 3,
|
||||
0, 0)
|
||||
!= STAT_NOACTION) {
|
||||
needbind = true;
|
||||
us.soa.sa_family = pf;
|
||||
}
|
||||
|
||||
if ((result =
|
||||
xioopen_connect(xfd,
|
||||
needbind?(struct sockaddr *)&us:NULL, uslen,
|
||||
(struct sockaddr *)&them, themlen,
|
||||
opts, pf, socktype, proto, false)) != 0) {
|
||||
return result;
|
||||
}
|
||||
if ((result = _xio_openlate(xfd, opts)) < 0) {
|
||||
return result;
|
||||
}
|
||||
return STAT_OK;
|
||||
}
|
||||
|
||||
static
|
||||
int xioopen_socket_listen(int argc, const char *argv[], struct opt *opts,
|
||||
int xioflags, xiofile_t *xxfd, unsigned groups,
|
||||
int dummy1, int dummy2, int dummy3) {
|
||||
struct single *xfd = &xxfd->stream;
|
||||
const char *pfname = argv[1];
|
||||
const char *protname = argv[2];
|
||||
const char *usname = argv[3];
|
||||
char *garbage;
|
||||
int pf;
|
||||
int proto;
|
||||
int socktype = SOCK_STREAM;
|
||||
union sockaddr_union us; socklen_t uslen;
|
||||
struct opt *opts0;
|
||||
int result;
|
||||
|
||||
if (argc != 4) {
|
||||
Error2("%s: wrong number of parameters (%d instead of 3)",
|
||||
argv[0], argc-1);
|
||||
return STAT_NORETRY;
|
||||
}
|
||||
|
||||
pf = strtoul(pfname, &garbage, 0);
|
||||
if (*garbage != '\0') {
|
||||
Warn1("garbage in parameter: \"%s\"", garbage);
|
||||
}
|
||||
|
||||
proto = strtoul(protname, &garbage, 0);
|
||||
if (*garbage != '\0') {
|
||||
Warn1("garbage in parameter: \"%s\"", garbage);
|
||||
}
|
||||
|
||||
retropt_socket_pf(opts, &pf);
|
||||
retropt_int(opts, OPT_SO_TYPE, &socktype);
|
||||
/*retropt_int(opts, OPT_IP_PROTOCOL, &proto);*/
|
||||
xfd->howtoend = END_SHUTDOWN;
|
||||
|
||||
socket_init(0, &us);
|
||||
uslen = 0;
|
||||
if ((result =
|
||||
dalan(usname, (char *)&us.soa.sa_data, &uslen, sizeof(us)))
|
||||
< 0) {
|
||||
Error1("data too long: \"%s\"", usname);
|
||||
} else if (result > 0) {
|
||||
Error1("syntax error in \"%s\"", usname);
|
||||
}
|
||||
uslen += sizeof(us.soa.sa_family)
|
||||
#if HAVE_STRUCT_SOCKADDR_SALEN
|
||||
+ sizeof(us.soa.sa_len)
|
||||
#endif
|
||||
;
|
||||
us.soa.sa_family = pf;
|
||||
|
||||
if (applyopts_single(xfd, opts, PH_INIT) < 0) return -1;
|
||||
applyopts(-1, opts, PH_INIT);
|
||||
applyopts(-1, opts, PH_EARLY);
|
||||
|
||||
opts0 = copyopts(opts, GROUP_ALL);
|
||||
|
||||
if ((result =
|
||||
xioopen_listen(xfd, xioflags,
|
||||
(struct sockaddr *)&us, uslen,
|
||||
opts, opts0, 0/*instead of pf*/, socktype, proto))
|
||||
!= STAT_OK)
|
||||
return result;
|
||||
return STAT_OK;
|
||||
}
|
||||
|
||||
/* we expect the form: ...:domain:type:protocol:remote-address */
|
||||
static
|
||||
int xioopen_socket_sendto(int argc, const char *argv[], struct opt *opts,
|
||||
int xioflags, xiofile_t *xxfd, unsigned groups,
|
||||
int dummy1, int dummy2, int dummy3) {
|
||||
int result;
|
||||
|
||||
if (argc != 5) {
|
||||
Error2("%s: wrong number of parameters (%d instead of 4)",
|
||||
argv[0], argc-1);
|
||||
return STAT_NORETRY;
|
||||
}
|
||||
if ((result =
|
||||
_xioopen_socket_sendto(argv[1], argv[2], argv[3], argv[4],
|
||||
opts, xioflags, xxfd, groups))
|
||||
!= STAT_OK) {
|
||||
return result;
|
||||
}
|
||||
_xio_openlate(&xxfd->stream, opts);
|
||||
return STAT_OK;
|
||||
}
|
||||
|
||||
static
|
||||
int _xioopen_socket_sendto(const char *pfname, const char *type,
|
||||
const char *protname, const char *address,
|
||||
struct opt *opts, int xioflags, xiofile_t *xxfd,
|
||||
unsigned groups) {
|
||||
xiosingle_t *xfd = &xxfd->stream;
|
||||
char *garbage;
|
||||
union sockaddr_union us = {{0}};
|
||||
socklen_t uslen = 0;
|
||||
socklen_t themlen = 0;
|
||||
int pf;
|
||||
int socktype = SOCK_RAW;
|
||||
int proto;
|
||||
bool needbind = false;
|
||||
char *bindstring = NULL;
|
||||
int result;
|
||||
|
||||
pf = strtoul(pfname, &garbage, 0);
|
||||
if (*garbage != '\0') {
|
||||
Warn1("garbage in parameter: \"%s\"", garbage);
|
||||
}
|
||||
|
||||
socktype = strtoul(type, &garbage, 0);
|
||||
if (*garbage != '\0') {
|
||||
Warn1("garbage in parameter: \"%s\"", garbage);
|
||||
}
|
||||
|
||||
proto = strtoul(protname, &garbage, 0);
|
||||
if (*garbage != '\0') {
|
||||
Warn1("garbage in parameter: \"%s\"", garbage);
|
||||
}
|
||||
|
||||
retropt_socket_pf(opts, &pf);
|
||||
retropt_int(opts, OPT_SO_TYPE, &socktype);
|
||||
/*retropt_int(opts, OPT_IP_PROTOCOL, &proto);*/
|
||||
xfd->howtoend = END_SHUTDOWN;
|
||||
|
||||
xfd->peersa.soa.sa_family = pf;
|
||||
themlen = 0;
|
||||
if ((result =
|
||||
dalan(address, (char *)&xfd->peersa.soa.sa_data, &themlen,
|
||||
sizeof(xfd->peersa)))
|
||||
< 0) {
|
||||
Error1("data too long: \"%s\"", address);
|
||||
} else if (result > 0) {
|
||||
Error1("syntax error in \"%s\"", address);
|
||||
}
|
||||
xfd->salen = themlen + sizeof(sa_family_t)
|
||||
#if HAVE_STRUCT_SOCKADDR_SALEN
|
||||
+ sizeof(xfd->peersa.soa.sa_len)
|
||||
#endif
|
||||
;
|
||||
#if HAVE_STRUCT_SOCKADDR_SALEN
|
||||
xfd->peersa.soa.sa_len =
|
||||
sizeof(xfd->peersa.soa.sa_len) + sizeof(xfd->peersa.soa.sa_family) +
|
||||
themlen;
|
||||
#endif
|
||||
|
||||
/* ...res_opts[] */
|
||||
if (applyopts_single(xfd, opts, PH_INIT) < 0) return -1;
|
||||
applyopts(-1, opts, PH_INIT);
|
||||
|
||||
if (pf == PF_UNSPEC) {
|
||||
pf = xfd->peersa.soa.sa_family;
|
||||
}
|
||||
|
||||
xfd->dtype = XIODATA_RECVFROM;
|
||||
|
||||
if (retropt_string(opts, OPT_BIND, &bindstring) == 0) {
|
||||
uslen = 0;
|
||||
if ((result =
|
||||
dalan(bindstring, (char *)&us.soa.sa_data, &uslen, sizeof(us)))
|
||||
< 0) {
|
||||
Error1("data too long: \"%s\"", bindstring);
|
||||
} else if (result > 0) {
|
||||
Error1("syntax error in \"%s\"", bindstring);
|
||||
}
|
||||
us.soa.sa_family = pf;
|
||||
uslen += sizeof(sa_family_t)
|
||||
#if HAVE_STRUCT_SOCKADDR_SALEN
|
||||
+ sizeof(us.soa.sa_len)
|
||||
#endif
|
||||
;
|
||||
needbind = true;
|
||||
}
|
||||
|
||||
return
|
||||
_xioopen_dgram_sendto(needbind?&us:NULL, uslen,
|
||||
opts, xioflags, xfd, groups, pf, socktype, proto);
|
||||
}
|
||||
|
||||
|
||||
/* we expect the form: ...:domain:socktype:protocol:local-address */
|
||||
static
|
||||
int xioopen_socket_recvfrom(int argc, const char *argv[], struct opt *opts,
|
||||
int xioflags, xiofile_t *xxfd, unsigned groups,
|
||||
int dummy, int summy2, int dummy3) {
|
||||
struct single *xfd = &xxfd->stream;
|
||||
const char *pfname = argv[1];
|
||||
const char *typename = argv[2];
|
||||
const char *protname = argv[3];
|
||||
const char *address = argv[4];
|
||||
char *garbage;
|
||||
union sockaddr_union *us = &xfd->para.socket.la;
|
||||
socklen_t uslen = sizeof(*us);
|
||||
int pf, socktype, proto;
|
||||
char *rangename;
|
||||
int result;
|
||||
|
||||
if (argc != 5) {
|
||||
Error2("%s: wrong number of parameters (%d instead of 4)",
|
||||
argv[0], argc-1);
|
||||
return STAT_NORETRY;
|
||||
}
|
||||
|
||||
pf = strtoul(pfname, &garbage, 0);
|
||||
if (*garbage != '\0') {
|
||||
Warn1("garbage in parameter: \"%s\"", garbage);
|
||||
}
|
||||
|
||||
socktype = strtoul(typename, &garbage, 0);
|
||||
if (*garbage != '\0') {
|
||||
Warn1("garbage in parameter: \"%s\"", garbage);
|
||||
}
|
||||
|
||||
proto = strtoul(protname, &garbage, 0);
|
||||
if (*garbage != '\0') {
|
||||
Warn1("garbage in parameter: \"%s\"", garbage);
|
||||
}
|
||||
|
||||
retropt_socket_pf(opts, &pf);
|
||||
retropt_int(opts, OPT_SO_TYPE, &socktype);
|
||||
/*retropt_int(opts, OPT_IP_PROTOCOL, &proto);*/
|
||||
xfd->howtoend = END_NONE;
|
||||
|
||||
uslen = 0;
|
||||
if ((result =
|
||||
dalan(address, (char *)&us->soa.sa_data, &uslen, sizeof(*us)))
|
||||
< 0) {
|
||||
Error1("data too long: \"%s\"", address);
|
||||
} else if (result > 0) {
|
||||
Error1("syntax error in \"%s\"", address);
|
||||
}
|
||||
us->soa.sa_family = pf;
|
||||
uslen += sizeof(us->soa.sa_family)
|
||||
#if HAVE_STRUCT_SOCKADDR_SALEN
|
||||
+ sizeof(us->soa.sa_len);
|
||||
#endif
|
||||
;
|
||||
xfd->dtype = XIOREAD_RECV|XIOWRITE_SENDTO;
|
||||
|
||||
if (retropt_string(opts, OPT_RANGE, &rangename) >= 0) {
|
||||
if (xioparserange(rangename, 0, &xfd->para.socket.range) < 0) {
|
||||
return STAT_NORETRY;
|
||||
}
|
||||
xfd->para.socket.dorange = true;
|
||||
free(rangename);
|
||||
}
|
||||
|
||||
if ((result =
|
||||
_xioopen_dgram_recvfrom(xfd, xioflags, &us->soa, uslen,
|
||||
opts, pf, socktype, proto, E_ERROR))
|
||||
!= STAT_OK) {
|
||||
return result;
|
||||
}
|
||||
_xio_openlate(xfd, opts);
|
||||
return STAT_OK;
|
||||
}
|
||||
|
||||
/* we expect the form: ...:domain:type:protocol:local-address */
|
||||
static
|
||||
int xioopen_socket_recv(int argc, const char *argv[], struct opt *opts,
|
||||
int xioflags, xiofile_t *xxfd, unsigned groups,
|
||||
int dummy1, int dummy2, int dummy3) {
|
||||
struct single *xfd = &xxfd->stream;
|
||||
const char *pfname = argv[1];
|
||||
const char *typename = argv[2];
|
||||
const char *protname = argv[3];
|
||||
const char *address = argv[4];
|
||||
char *garbage;
|
||||
union sockaddr_union us;
|
||||
socklen_t uslen = sizeof(us);
|
||||
int pf, socktype, proto;
|
||||
char *rangename;
|
||||
int result;
|
||||
|
||||
if (argc != 5) {
|
||||
Error2("%s: wrong number of parameters (%d instead of 4)",
|
||||
argv[0], argc-1);
|
||||
return STAT_NORETRY;
|
||||
}
|
||||
|
||||
pf = strtoul(pfname, &garbage, 0);
|
||||
if (*garbage != '\0') {
|
||||
Warn1("garbage in parameter: \"%s\"", garbage);
|
||||
}
|
||||
|
||||
socktype = strtoul(typename, &garbage, 0);
|
||||
if (*garbage != '\0') {
|
||||
Warn1("garbage in parameter: \"%s\"", garbage);
|
||||
}
|
||||
|
||||
proto = strtoul(protname, &garbage, 0);
|
||||
if (*garbage != '\0') {
|
||||
Warn1("garbage in parameter: \"%s\"", garbage);
|
||||
}
|
||||
|
||||
retropt_socket_pf(opts, &pf);
|
||||
retropt_int(opts, OPT_SO_TYPE, &socktype);
|
||||
/*retropt_int(opts, OPT_IP_PROTOCOL, &proto);*/
|
||||
xfd->howtoend = END_NONE;
|
||||
|
||||
uslen = 0;
|
||||
if ((result =
|
||||
dalan(address, (char *)&us.soa.sa_data, &uslen, sizeof(us)))
|
||||
< 0) {
|
||||
Error1("data too long: \"%s\"", address);
|
||||
} else if (result > 0) {
|
||||
Error1("syntax error in \"%s\"", address);
|
||||
}
|
||||
us.soa.sa_family = pf;
|
||||
uslen += sizeof(sa_family_t)
|
||||
#if HAVE_STRUCT_SOCKADDR_SALEN
|
||||
+sizeof(us.soa.sa_len)
|
||||
#endif
|
||||
;
|
||||
xfd->dtype = XIOREAD_RECV;
|
||||
xfd->para.socket.la.soa.sa_family = pf;
|
||||
|
||||
if (retropt_string(opts, OPT_RANGE, &rangename) >= 0) {
|
||||
if (xioparserange(rangename, 0, &xfd->para.socket.range) < 0) {
|
||||
return STAT_NORETRY;
|
||||
}
|
||||
xfd->para.socket.dorange = true;
|
||||
free(rangename);
|
||||
}
|
||||
|
||||
if ((result =
|
||||
_xioopen_dgram_recv(xfd, xioflags, &us.soa,
|
||||
uslen, opts, pf, socktype, proto, E_ERROR))
|
||||
!= STAT_OK) {
|
||||
return result;
|
||||
}
|
||||
_xio_openlate(xfd, opts);
|
||||
return STAT_OK;
|
||||
}
|
||||
|
||||
|
||||
/* we expect the form: ...:domain:type:protocol:remote-address */
|
||||
static
|
||||
int xioopen_socket_datagram(int argc, const char *argv[], struct opt *opts,
|
||||
int xioflags, xiofile_t *xxfd, unsigned groups,
|
||||
int dummy1, int dummy2, int dummy3) {
|
||||
xiosingle_t *xfd = &xxfd->stream;
|
||||
const char *pfname = argv[1];
|
||||
const char *typename = argv[2];
|
||||
const char *protname = argv[3];
|
||||
const char *address = argv[4];
|
||||
char *garbage;
|
||||
char *rangename;
|
||||
socklen_t themlen;
|
||||
int pf;
|
||||
int result;
|
||||
|
||||
if (argc != 5) {
|
||||
Error2("%s: wrong number of parameters (%d instead of 4)",
|
||||
argv[0], argc-1);
|
||||
return STAT_NORETRY;
|
||||
}
|
||||
|
||||
pf = strtoul(pfname, &garbage, 0);
|
||||
if (*garbage != '\0') {
|
||||
Warn1("garbage in parameter: \"%s\"", garbage);
|
||||
}
|
||||
|
||||
retropt_socket_pf(opts, &pf);
|
||||
/*retropt_int(opts, OPT_IP_PROTOCOL, &proto);*/
|
||||
xfd->howtoend = END_SHUTDOWN;
|
||||
|
||||
xfd->peersa.soa.sa_family = pf;
|
||||
themlen = 0;
|
||||
if ((result =
|
||||
dalan(address, (char *)&xfd->peersa.soa.sa_data, &themlen,
|
||||
sizeof(xfd->peersa)))
|
||||
< 0) {
|
||||
Error1("data too long: \"%s\"", address);
|
||||
} else if (result > 0) {
|
||||
Error1("syntax error in \"%s\"", address);
|
||||
}
|
||||
xfd->salen = themlen + sizeof(sa_family_t);
|
||||
#if HAVE_STRUCT_SOCKADDR_SALEN
|
||||
xfd->peersa.soa.sa_len =
|
||||
sizeof(xfd->peersa.soa.sa_len) + sizeof(xfd->peersa.soa.sa_family) +
|
||||
themlen;
|
||||
#endif
|
||||
|
||||
if ((result =
|
||||
_xioopen_socket_sendto(pfname, typename, protname, address,
|
||||
opts, xioflags, xxfd, groups))
|
||||
!= STAT_OK) {
|
||||
return result;
|
||||
}
|
||||
|
||||
xfd->dtype = XIOREAD_RECV|XIOWRITE_SENDTO;
|
||||
|
||||
xfd->para.socket.la.soa.sa_family = xfd->peersa.soa.sa_family;
|
||||
|
||||
/* which reply sockets will accept - determine by range option */
|
||||
if (retropt_string(opts, OPT_RANGE, &rangename) >= 0) {
|
||||
if (xioparserange(rangename, 0, &xfd->para.socket.range) < 0) {
|
||||
free(rangename);
|
||||
return STAT_NORETRY;
|
||||
}
|
||||
xfd->para.socket.dorange = true;
|
||||
xfd->dtype |= XIOREAD_RECV_CHECKRANGE;
|
||||
free(rangename);
|
||||
}
|
||||
|
||||
_xio_openlate(xfd, opts);
|
||||
return STAT_OK;
|
||||
}
|
||||
|
||||
|
||||
/* a subroutine that is common to all socket addresses that want to connect
|
||||
to a peer address.
|
||||
@ -658,9 +1196,9 @@ int _xioopen_dgram_recvfrom(struct single *xfd, int xioflags,
|
||||
}
|
||||
#endif /* WITH_UNIX */
|
||||
|
||||
#if WITH_IP4 /*|| WITH_IP6*/
|
||||
/* for generic sockets, this has already been retrieved */
|
||||
if (retropt_string(opts, OPT_RANGE, &rangename) >= 0) {
|
||||
if (parserange(rangename, pf, &xfd->para.socket.range)
|
||||
if (xioparserange(rangename, pf, &xfd->para.socket.range)
|
||||
< 0) {
|
||||
free(rangename);
|
||||
return STAT_NORETRY;
|
||||
@ -668,7 +1206,6 @@ int _xioopen_dgram_recvfrom(struct single *xfd, int xioflags,
|
||||
free(rangename);
|
||||
xfd->para.socket.dorange = true;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if (WITH_TCP || WITH_UDP) && WITH_LIBWRAP
|
||||
xio_retropt_tcpwrap(xfd, opts);
|
||||
@ -913,7 +1450,7 @@ int _xioopen_dgram_recv(struct single *xfd, int xioflags,
|
||||
|
||||
#if WITH_IP4 /*|| WITH_IP6*/
|
||||
if (retropt_string(opts, OPT_RANGE, &rangename) >= 0) {
|
||||
if (parserange(rangename, pf, &xfd->para.socket.range)
|
||||
if (xioparserange(rangename, pf, &xfd->para.socket.range)
|
||||
< 0) {
|
||||
free(rangename);
|
||||
return STAT_NORETRY;
|
||||
@ -1032,17 +1569,17 @@ int xiogetpacketsrc(int fd, union sockaddr_union *pa, socklen_t *palen) {
|
||||
}
|
||||
|
||||
|
||||
int xiocheckrange(union sockaddr_union *sa, union xiorange_union *range) {
|
||||
int xiocheckrange(union sockaddr_union *sa, struct xiorange *range) {
|
||||
switch (sa->soa.sa_family) {
|
||||
#if WITH_IP4
|
||||
case PF_INET:
|
||||
return
|
||||
xiocheckrange_ip4(&sa->ip4, &range->ip4);
|
||||
xiocheckrange_ip4(&sa->ip4, range);
|
||||
#endif /* WITH_IP4 */
|
||||
#if WITH_IP6
|
||||
case PF_INET6:
|
||||
return
|
||||
xiocheckrange_ip6(&sa->ip6, &range->ip6);
|
||||
xiocheckrange_ip6(&sa->ip6, range);
|
||||
#endif /* WITH_IP6 */
|
||||
}
|
||||
return -1;
|
||||
@ -1133,4 +1670,107 @@ int xiocheckpeer(xiosingle_t *xfd,
|
||||
return 0; /* permitted */
|
||||
}
|
||||
|
||||
|
||||
/* parses a network specification consisting of an address and a mask. */
|
||||
int xioparsenetwork(const char *rangename, int pf, struct xiorange *range) {
|
||||
size_t addrlen = 0, masklen = 0;
|
||||
int result;
|
||||
|
||||
switch (pf) {
|
||||
#if WITH_IP4
|
||||
case PF_INET:
|
||||
return xioparsenetwork_ip4(rangename, range);
|
||||
break;
|
||||
#endif /* WITH_IP4 */
|
||||
#if WITH_IP6
|
||||
case PF_INET6:
|
||||
return xioparsenetwork_ip6(rangename, range);
|
||||
break;
|
||||
#endif /* WITH_IP6 */
|
||||
case PF_UNSPEC:
|
||||
{
|
||||
char *addrname;
|
||||
const char *maskname;
|
||||
if ((maskname = strchr(rangename, ':')) == NULL) {
|
||||
Error1("syntax error in range \"%s\": use <addr>:<mask>", rangename);
|
||||
return STAT_NORETRY;
|
||||
}
|
||||
++maskname; /* skip ':' */
|
||||
if ((addrname = Malloc(maskname-rangename)) == NULL) {
|
||||
return STAT_NORETRY;
|
||||
}
|
||||
strncpy(addrname, rangename, maskname-rangename-1);
|
||||
result =
|
||||
dalan(addrname, (char *)&range->netaddr.soa.sa_data, &addrlen,
|
||||
sizeof(range->netaddr)-(size_t)(&((struct sockaddr *)0)->sa_data)
|
||||
/* data length */);
|
||||
if (result < 0) {
|
||||
Error1("data too long: \"%s\"", addrname);
|
||||
free(addrname); return STAT_NORETRY;
|
||||
} else if (result > 0) {
|
||||
Error1("syntax error in \"%s\"", addrname);
|
||||
free(addrname); return STAT_NORETRY;
|
||||
}
|
||||
free(addrname);
|
||||
result =
|
||||
dalan(maskname, (char *)&range->netmask.soa.sa_data, &masklen,
|
||||
sizeof(range->netaddr)-(size_t)(&((struct sockaddr *)0)->sa_data)
|
||||
/* data length */);
|
||||
if (result < 0) {
|
||||
Error1("data too long: \"%s\"", maskname);
|
||||
return STAT_NORETRY;
|
||||
} else if (result > 0) {
|
||||
Error1("syntax error in \"%s\"", maskname);
|
||||
return STAT_NORETRY;
|
||||
}
|
||||
if (addrlen != masklen) {
|
||||
Error2("network address is "F_Zu" bytes long, mask is "F_Zu" bytes long",
|
||||
addrlen, masklen);
|
||||
/* recover by padding the shorter component with 0 */
|
||||
memset((char *)&range->netaddr.soa.sa_data+addrlen, 0,
|
||||
MAX(0, addrlen-masklen));
|
||||
memset((char *)&range->netmask.soa.sa_data+masklen, 0,
|
||||
MAX(0, masklen-addrlen));
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
Error1("range option not supported with address family %d", pf);
|
||||
return STAT_NORETRY;
|
||||
}
|
||||
return STAT_OK;
|
||||
}
|
||||
|
||||
/* parses a string of form address/bits or address:mask, and fills the fields
|
||||
of the range union. The addr component is masked with mask. */
|
||||
int xioparserange(const char *rangename, int pf, struct xiorange *range) {
|
||||
int i;
|
||||
if (xioparsenetwork(rangename, pf, range) < 0) {
|
||||
return -1;
|
||||
}
|
||||
/* we have parsed the address and mask; now we make sure that the stored
|
||||
address has 0 where mask is 0, to simplify comparisions */
|
||||
switch (pf) {
|
||||
#if WITH_IP4
|
||||
case PF_INET:
|
||||
range->netaddr.ip4.sin_addr.s_addr &= range->netmask.ip4.sin_addr.s_addr;
|
||||
break;
|
||||
#endif /* WITH_IP4 */
|
||||
#if WITH_IP6
|
||||
case PF_INET6:
|
||||
return xiorange_ip6andmask(range);
|
||||
break;
|
||||
#endif /* WITH_IP6 */
|
||||
case PF_UNSPEC:
|
||||
for (i = 0; i < sizeof(range->netaddr); ++i) {
|
||||
((char *)&range->netaddr)[i] &= ((char *)&range->netmask)[i];
|
||||
}
|
||||
break;
|
||||
default:
|
||||
Error1("range option not supported with address family %d", pf);
|
||||
return STAT_NORETRY;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* _WITH_SOCKET */
|
||||
|
12
xio-socket.h
12
xio-socket.h
@ -5,6 +5,13 @@
|
||||
#ifndef __xio_socket_h_included
|
||||
#define __xio_socket_h_included 1
|
||||
|
||||
extern const struct addrdesc xioaddr_socket_connect;
|
||||
extern const struct addrdesc xioaddr_socket_listen;
|
||||
extern const struct addrdesc xioaddr_socket_sendto;
|
||||
extern const struct addrdesc xioaddr_socket_datagram;
|
||||
extern const struct addrdesc xioaddr_socket_recvfrom;
|
||||
extern const struct addrdesc xioaddr_socket_recv;
|
||||
|
||||
extern const struct optdesc opt_connect_timeout;
|
||||
extern const struct optdesc opt_so_debug;
|
||||
extern const struct optdesc opt_so_acceptconn;
|
||||
@ -89,5 +96,10 @@ int xiogetpacketsrc(int fd, union sockaddr_union *pa, socklen_t *palen);
|
||||
extern
|
||||
int xiocheckpeer(xiosingle_t *xfd,
|
||||
union sockaddr_union *pa, union sockaddr_union *la);
|
||||
extern
|
||||
int xioparsenetwork(const char *rangename, int pf,
|
||||
struct xiorange *range);
|
||||
extern
|
||||
int xioparserange(const char *rangename, int pf, struct xiorange *range);
|
||||
|
||||
#endif /* !defined(__xio_socket_h_included) */
|
||||
|
@ -70,7 +70,7 @@ static int xioopen_tun(int argc, const char *argv[], struct opt *opts, int xiofl
|
||||
char *tundevice = NULL;
|
||||
char *tunname = NULL, *tuntype = NULL;
|
||||
int pf = /*! PF_UNSPEC*/ PF_INET;
|
||||
union xiorange_union network;
|
||||
struct xiorange network;
|
||||
bool no_pi = false;
|
||||
const char *namedargv[] = { "tun", NULL, NULL };
|
||||
int rw = (xioflags & XIO_ACCMODE);
|
||||
@ -157,12 +157,14 @@ static int xioopen_tun(int argc, const char *argv[], struct opt *opts, int xiofl
|
||||
return result;
|
||||
}
|
||||
socket_init(pf, (union sockaddr_union *)&ifr.ifr_addr);
|
||||
((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr = network.ip4.netaddr;
|
||||
((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr =
|
||||
network.netaddr.ip4.sin_addr;
|
||||
if (Ioctl(sockfd, SIOCSIFADDR, &ifr) < 0) {
|
||||
Error4("ioctl(%d, SIOCSIFADDR, {\"%s\", \"%s\"}: %s",
|
||||
sockfd, ifr.ifr_name, ifaddr, strerror(errno));
|
||||
}
|
||||
((struct sockaddr_in *)&ifr.ifr_netmask)->sin_addr = network.ip4.netmask;
|
||||
((struct sockaddr_in *)&ifr.ifr_netmask)->sin_addr =
|
||||
network.netmask.ip4.sin_addr;
|
||||
if (Ioctl(sockfd, SIOCSIFNETMASK, &ifr) < 0) {
|
||||
Error4("ioctl(%d, SIOCSIFNETMASK, {\"0x%08u\", \"%s\"}, %s",
|
||||
sockfd, ((struct sockaddr_in *)&ifr.ifr_netmask)->sin_addr.s_addr,
|
||||
|
@ -145,7 +145,7 @@ int xioopen_ipdgram_listen(int argc, const char *argv[], struct opt *opts,
|
||||
|
||||
#if WITH_IP4 /*|| WITH_IP6*/
|
||||
if (retropt_string(opts, OPT_RANGE, &rangename) >= 0) {
|
||||
if (parserange(rangename, pf, &fd->stream.para.socket.range) < 0) {
|
||||
if (xioparserange(rangename, pf, &fd->stream.para.socket.range) < 0) {
|
||||
free(rangename);
|
||||
return STAT_NORETRY;
|
||||
}
|
||||
@ -424,7 +424,7 @@ int xioopen_udp_datagram(int argc, const char *argv[], struct opt *opts,
|
||||
/* which reply packets will be accepted - determine by range option */
|
||||
if (retropt_string(opts, OPT_RANGE, &rangename)
|
||||
>= 0) {
|
||||
if (parserange(rangename, pf, &xfd->para.socket.range) < 0) {
|
||||
if (xioparserange(rangename, pf, &xfd->para.socket.range) < 0) {
|
||||
free(rangename);
|
||||
return STAT_NORETRY;
|
||||
}
|
||||
@ -582,7 +582,7 @@ int xioopen_udp_recv(int argc, const char *argv[], struct opt *opts,
|
||||
|
||||
#if WITH_IP4 /*|| WITH_IP6*/
|
||||
if (retropt_string(opts, OPT_RANGE, &rangename) >= 0) {
|
||||
if (parserange(rangename, pf, &xfd->stream.para.socket.range) < 0) {
|
||||
if (xioparserange(rangename, pf, &xfd->stream.para.socket.range) < 0) {
|
||||
return STAT_NORETRY;
|
||||
}
|
||||
xfd->stream.para.socket.dorange = true;
|
||||
|
@ -84,6 +84,9 @@ xiosetunix(struct sockaddr_un *saun,
|
||||
} else {
|
||||
len = sizeof(struct sockaddr_un);
|
||||
}
|
||||
#if HAVE_STRUCT_SOCKADDR_SALEN
|
||||
saun->sun_len = len;
|
||||
#endif
|
||||
} else {
|
||||
if ((pathlen = strlen(path)) >= sizeof(saun->sun_path)) {
|
||||
Warn2("socket address "F_Zu" characters long, truncating to "F_Zu"",
|
||||
@ -225,7 +228,7 @@ static int xioopen_unix_connect(int argc, const char *argv[], struct opt *opts,
|
||||
if ((result = _xio_openlate(xfd, opts)) < 0) {
|
||||
return result;
|
||||
}
|
||||
return 0;
|
||||
return STAT_OK;
|
||||
}
|
||||
|
||||
|
||||
|
2
xio.h
2
xio.h
@ -177,7 +177,7 @@ typedef struct single {
|
||||
union sockaddr_union la; /* local socket address */
|
||||
bool emptyiseof; /* with dgram: empty packet means EOF */
|
||||
bool dorange;
|
||||
union xiorange_union range; /* restrictions for peer address */
|
||||
struct xiorange range; /* restrictions for peer address */
|
||||
#if _WITH_IP4 || _WITH_IP6
|
||||
struct {
|
||||
unsigned int res_opts[2]; /* bits to be set in _res.options are
|
||||
|
@ -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
|
||||
|
||||
|
@ -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.para.exec.pid = 0; */
|
||||
|
59
xioopts.c
59
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)
|
||||
@ -2608,13 +2608,13 @@ int retropt_string(struct opt *opts, int optcode, char **result) {
|
||||
}
|
||||
|
||||
|
||||
#if WITH_SOCKET
|
||||
#if _WITH_SOCKET
|
||||
/* looks for an bind option and, if found, overwrites the complete contents of
|
||||
sa with the appropriate value(s).
|
||||
returns STAT_OK if option exists and could be resolved,
|
||||
STAT_NORETRY if option exists but had error,
|
||||
or STAT_NOACTION if it does not exist */
|
||||
/* currently only for IP (v4, v6) */
|
||||
/* currently only for IP (v4, v6) and raw (PF_UNSPEC) */
|
||||
int retropt_bind(struct opt *opts,
|
||||
int af,
|
||||
int socktype,
|
||||
@ -2636,22 +2636,26 @@ int retropt_bind(struct opt *opts,
|
||||
if (retropt_string(opts, OPT_BIND, &bindname) < 0) {
|
||||
return STAT_NOACTION;
|
||||
}
|
||||
addrallowed = true;
|
||||
portallowed = (feats>=2);
|
||||
bindp = bindname;
|
||||
nestlex((const char **)&bindp, &hostp, &hostlen, ends, NULL, NULL, nests,
|
||||
true, false, false);
|
||||
*hostp++ = '\0';
|
||||
if (!strncmp(bindp, portsep, strlen(portsep))) {
|
||||
if (!portallowed) {
|
||||
Error("port specification not allowed in this bind option");
|
||||
return STAT_NORETRY;
|
||||
} else {
|
||||
portp = bindp + strlen(portsep);
|
||||
}
|
||||
}
|
||||
|
||||
switch (af) {
|
||||
|
||||
case AF_UNSPEC:
|
||||
{
|
||||
size_t p = 0;
|
||||
dalan(bindname, (char *)sa->sa_data, &p, *salen-sizeof(sa->sa_family));
|
||||
*salen = p + sizeof(sa->sa_family);
|
||||
*salen = p +
|
||||
#if HAVE_STRUCT_SOCKADDR_SALEN
|
||||
sizeof(sa->sa_len) +
|
||||
#endif
|
||||
sizeof(sa->sa_family);
|
||||
#if HAVE_STRUCT_SOCKADDR_SALEN
|
||||
sa->sa_len = *salen;
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
|
||||
#if WITH_IP4 || WITH_IP6
|
||||
#if WITH_IP4
|
||||
case AF_INET:
|
||||
@ -2659,6 +2663,19 @@ int retropt_bind(struct opt *opts,
|
||||
#if WITH_IP6
|
||||
case AF_INET6:
|
||||
#endif /*WITH_IP6 */
|
||||
addrallowed = true;
|
||||
portallowed = (feats>=2);
|
||||
nestlex((const char **)&bindp, &hostp, &hostlen, ends, NULL, NULL, nests,
|
||||
true, false, false);
|
||||
*hostp++ = '\0';
|
||||
if (!strncmp(bindp, portsep, strlen(portsep))) {
|
||||
if (!portallowed) {
|
||||
Error("port specification not allowed in this bind option");
|
||||
return STAT_NORETRY;
|
||||
} else {
|
||||
portp = bindp + strlen(portsep);
|
||||
}
|
||||
}
|
||||
if ((result =
|
||||
xiogetaddrinfo(hostname[0]!='\0'?hostname:NULL, portp,
|
||||
af, socktype, ipproto,
|
||||
@ -2687,7 +2704,7 @@ int retropt_bind(struct opt *opts,
|
||||
}
|
||||
return STAT_OK;
|
||||
}
|
||||
#endif /* WITH_SOCKET */
|
||||
#endif /* _WITH_SOCKET */
|
||||
|
||||
|
||||
/* applies to fd all options belonging to phase */
|
||||
@ -2806,7 +2823,7 @@ int applyopts(int fd, struct opt *opts, unsigned int phase) {
|
||||
opt->desc->type);
|
||||
}
|
||||
|
||||
#if WITH_SOCKET
|
||||
#if _WITH_SOCKET
|
||||
} else if (opt->desc->func == OFUNC_SOCKOPT) {
|
||||
if (0) {
|
||||
;
|
||||
@ -3015,7 +3032,7 @@ int applyopts(int fd, struct opt *opts, unsigned int phase) {
|
||||
Error1("setsockopt() data type %d not implemented",
|
||||
opt->desc->type);
|
||||
}
|
||||
#endif /* WITH_SOCKET */
|
||||
#endif /* _WITH_SOCKET */
|
||||
|
||||
#if HAVE_FLOCK
|
||||
} else if (opt->desc->func == OFUNC_FLOCK) {
|
||||
@ -3728,7 +3745,7 @@ int applyopts_single(struct single *xfd, struct opt *opts, enum e_phase phase) {
|
||||
}
|
||||
break;
|
||||
|
||||
#if WITH_SOCKET
|
||||
#if _WITH_SOCKET
|
||||
case OFUNC_SOCKOPT:
|
||||
switch (opt->desc->optcode) {
|
||||
#if WITH_IP4 && (defined(HAVE_STRUCT_IP_MREQ) || defined (HAVE_STRUCT_IP_MREQN))
|
||||
@ -3879,7 +3896,7 @@ mc:addr
|
||||
++opt; continue;
|
||||
}
|
||||
break;
|
||||
#endif /* WITH_SOCKET */
|
||||
#endif /* _WITH_SOCKET */
|
||||
|
||||
default:
|
||||
++opt;
|
||||
|
@ -109,7 +109,7 @@ ssize_t xioread(xiofile_t *file, void *buff, size_t bufsiz) {
|
||||
break;
|
||||
#endif /* WITH_OPENSSL */
|
||||
|
||||
#if WITH_SOCKET
|
||||
#if _WITH_SOCKET
|
||||
case XIOREAD_RECV:
|
||||
if (pipe->dtype & XIOREAD_RECV_FROM) {
|
||||
#if WITH_RAWIP || WITH_UDP || WITH_UNIX
|
||||
@ -354,7 +354,7 @@ ssize_t xioread(xiofile_t *file, void *buff, size_t bufsiz) {
|
||||
|
||||
}
|
||||
break;
|
||||
#endif /* WITH_SOCKET */
|
||||
#endif /* _WITH_SOCKET */
|
||||
|
||||
default:
|
||||
Error("internal: undefined read operation");
|
||||
|
@ -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 New Issue
Block a user