On bad parameter number print syntax; struct single pointers are now mostly called sfd

This commit is contained in:
Gerhard Rieger 2023-07-13 09:06:35 +02:00
parent 5eebca3a5b
commit 50b199dcd9
42 changed files with 1354 additions and 1163 deletions

View file

@ -188,6 +188,8 @@ Coding:
Moved multicast related code from xioopts.c to xio-ip.c and xio-ip6.c Moved multicast related code from xioopts.c to xio-ip.c and xio-ip6.c
Pointers of type struct single are now always called sfd.
Porting: Porting:
Removed Config/ because its contents have not been maintained for many Removed Config/ because its contents have not been maintained for many
years. years.
@ -207,6 +209,8 @@ Documentation:
Renamed xiogetpacketsrc() to xiogetancillary() Renamed xiogetpacketsrc() to xiogetancillary()
On bad parameter number now print syntax.
####################### V 1.7.4.5 (not released): ####################### V 1.7.4.5 (not released):
Corrections: Corrections:

View file

@ -17097,7 +17097,6 @@ CMD0="$TRACE $SOCAT $opts -T 2 PIPE EXEC:\"$CAT\",pty,setsid,sigint"
printf "test $F_n $TEST... " $N printf "test $F_n $TEST... " $N
$CMD0 >/dev/null 2>"${te}0" & $CMD0 >/dev/null 2>"${te}0" &
pid0=$! pid0=$!
#echo "pid0=$pid0" >&2 #!!!
sleep 1 sleep 1
kill -INT $pid0 kill -INT $pid0
wait wait

View file

@ -13,7 +13,7 @@
#include "xio-creat.h" #include "xio-creat.h"
static int xioopen_creat(int arg, const char *argv[], struct opt *opts, int rw, xiofile_t *fd, groups_t groups, int dummy1, int dummy2, int dummy3); static int xioopen_creat(int arg, const char *argv[], struct opt *opts, int rw, xiofile_t *fd, const struct addrdesc *addrdesc);
/*! within stream model, this is a write-only address - use 2 instead of 3 */ /*! within stream model, this is a write-only address - use 2 instead of 3 */
@ -37,7 +37,14 @@ static int _xioopen_creat(const char *path, int rw, struct opt *opts) {
} }
static int xioopen_creat(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *xxfd, groups_t groups, int dummy1, int dummy2, int dummy3) { static int xioopen_creat(
int argc,
const char *argv[],
struct opt *opts,
int xioflags,
xiofile_t *xxfd,
const struct addrdesc *addrdesc)
{
struct single *sfd = &xxfd->stream; struct single *sfd = &xxfd->stream;
const char *filename = argv[1]; const char *filename = argv[1];
int rw = (xioflags&XIO_ACCMODE); int rw = (xioflags&XIO_ACCMODE);
@ -46,7 +53,10 @@ static int xioopen_creat(int argc, const char *argv[], struct opt *opts, int xio
int result; int result;
/* remove old file, or set user/permissions on old file; parse options */ /* remove old file, or set user/permissions on old file; parse options */
if ((result = _xioopen_named_early(argc, argv, xxfd, groups, &exists, opts)) < 0) { if ((result =
_xioopen_named_early(argc, argv, xxfd, addrdesc->groups, &exists, opts,
addrdesc->syntax))
< 0) {
return result; return result;
} }

View file

@ -13,23 +13,20 @@
#if WITH_EXEC #if WITH_EXEC
static int xioopen_exec(int argc, const char *argv[], struct opt *opts, static int xioopen_exec(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *xfd, const struct addrdesc *addrdesc);
int xioflags, /* XIO_RDONLY etc. */
xiofile_t *fd,
groups_t groups,
int dummy1, int dummy2, int dummy3
);
const struct addrdesc xioaddr_exec = { "EXEC", 3, xioopen_exec, GROUP_FD|GROUP_FORK|GROUP_EXEC|GROUP_SOCKET|GROUP_SOCK_UNIX|GROUP_TERMIOS|GROUP_FIFO|GROUP_PTY|GROUP_PARENT, 0, 0, 0 HELP(":<command-line>") }; const struct addrdesc xioaddr_exec = { "EXEC", 3, xioopen_exec, GROUP_FD|GROUP_FORK|GROUP_EXEC|GROUP_SOCKET|GROUP_SOCK_UNIX|GROUP_TERMIOS|GROUP_FIFO|GROUP_PTY|GROUP_PARENT, 0, 0, 0 HELP(":<command-line>") };
const struct optdesc opt_dash = { "dash", "login", OPT_DASH, GROUP_EXEC, PH_PREEXEC, TYPE_BOOL, OFUNC_SPEC }; const struct optdesc opt_dash = { "dash", "login", OPT_DASH, GROUP_EXEC, PH_PREEXEC, TYPE_BOOL, OFUNC_SPEC };
static int xioopen_exec(int argc, const char *argv[], struct opt *opts, static int xioopen_exec(
int xioflags, /* XIO_RDONLY, XIO_MAYCHILD etc. */ int argc,
xiofile_t *xfd, const char *argv[],
groups_t groups, struct opt *opts,
int dummy1, int dummy2, int dummy3 int xioflags, /* XIO_RDONLY, XIO_MAYCHILD etc. */
) { xiofile_t *xfd,
const struct addrdesc *addrdesc)
{
struct single *sfd = &xfd->stream; struct single *sfd = &xfd->stream;
int status; int status;
bool dash = false; bool dash = false;
@ -37,12 +34,14 @@ static int xioopen_exec(int argc, const char *argv[], struct opt *opts,
int numleft; int numleft;
if (argc != 2) { if (argc != 2) {
Error2("\"%s\": wrong number of parameters (%d instead of 1)", argv[0], argc-1); xio_syntax(argv[0], 1, argc-1, addrdesc->syntax);
return STAT_NORETRY;
} }
retropt_bool(opts, OPT_DASH, &dash); retropt_bool(opts, OPT_DASH, &dash);
status = _xioopen_foxec(xioflags, sfd, groups, &opts, &duptostderr); status =
_xioopen_foxec(xioflags, sfd, addrdesc->groups, &opts, &duptostderr);
if (status < 0) if (status < 0)
return status; return status;
if (status == 0) { /* child */ if (status == 0) { /* child */

View file

@ -14,8 +14,8 @@
#if WITH_FDNUM #if WITH_FDNUM
static int xioopen_fdnum(int argc, const char *argv[], struct opt *opts, int rw, xiofile_t *xfd, groups_t groups, int dummy1, int dummy2, int dummy3); static int xioopen_fdnum(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *xfd, const struct addrdesc *addrdesc);
static int xioopen_accept_fd(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *xfd, groups_t groups, int dummy1, int dummy2, int dummy3); static int xioopen_accept_fd(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *xfd, const struct addrdesc *addrdesc);
const struct addrdesc xioaddr_fd = { "FD", 1+XIO_RDWR, xioopen_fdnum, GROUP_FD|GROUP_FIFO|GROUP_CHR|GROUP_BLK|GROUP_FILE|GROUP_SOCKET|GROUP_TERMIOS|GROUP_SOCK_UNIX|GROUP_SOCK_IP|GROUP_IPAPP, 0, 0, 0 HELP(":<fdnum>") }; const struct addrdesc xioaddr_fd = { "FD", 1+XIO_RDWR, xioopen_fdnum, GROUP_FD|GROUP_FIFO|GROUP_CHR|GROUP_BLK|GROUP_FILE|GROUP_SOCKET|GROUP_TERMIOS|GROUP_SOCK_UNIX|GROUP_SOCK_IP|GROUP_IPAPP, 0, 0, 0 HELP(":<fdnum>") };
@ -25,9 +25,14 @@ const struct addrdesc xioaddr_accept_fd = { "ACCEPT-FD", 1+XIO_RDWR, xioopen_acc
/* use some file descriptor and apply the options. Set the FD_CLOEXEC flag. */ /* use some file descriptor and apply the options. Set the FD_CLOEXEC flag. */
static int xioopen_fdnum(int argc, const char *argv[], struct opt *opts, static int xioopen_fdnum(
int xioflags, xiofile_t *xfd, groups_t groups, int argc,
int dummy1, int dummy2, int dummy3) { const char *argv[],
struct opt *opts,
int xioflags,
xiofile_t *xfd,
const struct addrdesc *addrdesc)
{
char *a1; char *a1;
int rw = (xioflags&XIO_ACCMODE); int rw = (xioflags&XIO_ACCMODE);
int numfd; int numfd;
@ -46,7 +51,7 @@ static int xioopen_fdnum(int argc, const char *argv[], struct opt *opts,
Warn2("fcntl(%d, F_SETFD, FD_CLOEXEC): %s", numfd, strerror(errno)); Warn2("fcntl(%d, F_SETFD, FD_CLOEXEC): %s", numfd, strerror(errno));
} }
Notice2("using file descriptor %d for %s", numfd, ddirection[rw]); Notice2("using file descriptor %d for %s", numfd, ddirection[rw]);
if ((result = xioopen_fd(opts, rw, &xfd->stream, numfd, dummy2, dummy3)) < 0) { if ((result = xioopen_fd(opts, rw, &xfd->stream, numfd)) < 0) {
return result; return result;
} }
return 0; return 0;
@ -61,10 +66,7 @@ static int xioopen_accept_fd(
struct opt *opts, struct opt *opts,
int xioflags, int xioflags,
xiofile_t *xfd, xiofile_t *xfd,
groups_t groups, const struct addrdesc *addrdesc)
int dummy1,
int dummy2,
int dummy3)
{ {
char *a1; char *a1;
int rw = (xioflags&XIO_ACCMODE); int rw = (xioflags&XIO_ACCMODE);
@ -74,7 +76,8 @@ static int xioopen_accept_fd(
int result; int result;
if (argc != 2) { if (argc != 2) {
Error2("%s: wrong number of parameters (%d instead of 1)", argv[0], argc-1); xio_syntax(argv[0], 1, argc-1, addrdesc->syntax);
return STAT_NORETRY;
} }
numfd = strtoul(argv[1], &a1, 0); numfd = strtoul(argv[1], &a1, 0);
@ -103,29 +106,29 @@ static int xioopen_accept_fd(
#if WITH_FD #if WITH_FD
/* retrieve and apply options to a standard file descriptor. /* Retrieves and apply options to a standard file descriptor.
Do not set FD_CLOEXEC flag. */ Does not set FD_CLOEXEC flag. */
int xioopen_fd(struct opt *opts, int rw, xiosingle_t *xfd, int numfd, int dummy2, int dummy3) { int xioopen_fd(struct opt *opts, int rw, struct single *sfd, int numfd) {
xfd->fd = numfd; sfd->fd = numfd;
xfd->howtoend = END_NONE; sfd->howtoend = END_NONE;
#if WITH_TERMIOS #if WITH_TERMIOS
if (Isatty(xfd->fd)) { if (Isatty(sfd->fd)) {
if (Tcgetattr(xfd->fd, &xfd->savetty) < 0) { if (Tcgetattr(sfd->fd, &sfd->savetty) < 0) {
Warn2("cannot query current terminal settings on fd %d: %s", Warn2("cannot query current terminal settings on fd %d: %s",
xfd->fd, strerror(errno)); sfd->fd, strerror(errno));
} else { } else {
xfd->ttyvalid = true; sfd->ttyvalid = true;
} }
} }
#endif /* WITH_TERMIOS */ #endif /* WITH_TERMIOS */
if (applyopts_single(xfd, opts, PH_INIT) < 0) if (applyopts_single(sfd, opts, PH_INIT) < 0)
return -1; return -1;
applyopts2(xfd, -1, opts, PH_INIT, PH_FD); applyopts2(sfd, -1, opts, PH_INIT, PH_FD);
return _xio_openlate(xfd, opts); return _xio_openlate(sfd, opts);
} }
#endif /* WITH_FD */ #endif /* WITH_FD */

View file

@ -8,6 +8,6 @@
extern const struct addrdesc xioaddr_fd; extern const struct addrdesc xioaddr_fd;
extern const struct addrdesc xioaddr_accept_fd; extern const struct addrdesc xioaddr_accept_fd;
extern int xioopen_fd(struct opt *opts, int rw, xiosingle_t *xfd, int numfd, int dummy2, int dummy3); extern int xioopen_fd(struct opt *opts, int rw, xiosingle_t *xfd, int numfd);
#endif /* !defined(__xio_fdnum_h_included) */ #endif /* !defined(__xio_fdnum_h_included) */

View file

@ -11,7 +11,7 @@
#include "xio-file.h" #include "xio-file.h"
static int xioopen_open(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *fd, groups_t groups, int dummy1, int dummy2, int dummy3); static int xioopen_open(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *fd, const struct addrdesc *addrdesc);
#if WITH_OPEN #if WITH_OPEN
@ -72,7 +72,14 @@ const struct addrdesc xioaddr_open = { "OPEN", 3, xioopen_open, GROUP_FD|GRO
if the filesystem entry already exists, the data is appended if the filesystem entry already exists, the data is appended
if it does not exist, a file is created and the data is appended if it does not exist, a file is created and the data is appended
*/ */
static int xioopen_open(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *xfd, groups_t groups, int dummy1, int dummy2, int dummy3) { static int xioopen_open(
int argc,
const char *argv[],
struct opt *opts,
int xioflags,
xiofile_t *xfd,
const struct addrdesc *addrdesc)
{
const char *filename = argv[1]; const char *filename = argv[1];
int rw = (xioflags & XIO_ACCMODE); int rw = (xioflags & XIO_ACCMODE);
struct single *sfd = &xfd->stream; struct single *sfd = &xfd->stream;
@ -81,7 +88,10 @@ static int xioopen_open(int argc, const char *argv[], struct opt *opts, int xiof
int result; int result;
/* remove old file, or set user/permissions on old file; parse options */ /* remove old file, or set user/permissions on old file; parse options */
if ((result = _xioopen_named_early(argc, argv, xfd, groups, &exists, opts)) < 0) { if ((result =
_xioopen_named_early(argc, argv, xfd, addrdesc->groups, &exists, opts,
addrdesc->syntax))
< 0) {
return result; return result;
} }

View file

@ -14,12 +14,19 @@
#if WITH_GOPEN #if WITH_GOPEN
static int xioopen_gopen(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *fd, groups_t groups, int dummy1, int dummy2, int dummy3); static int xioopen_gopen(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *fd, const struct addrdesc *addrdesc);
const struct addrdesc xioaddr_gopen = { "GOPEN", 3, xioopen_gopen, GROUP_FD|GROUP_FIFO|GROUP_CHR|GROUP_BLK|GROUP_REG|GROUP_NAMED|GROUP_OPEN|GROUP_FILE|GROUP_TERMIOS|GROUP_SOCKET|GROUP_SOCK_UNIX, 0, 0, 0 HELP(":<filename>") }; const struct addrdesc xioaddr_gopen = { "GOPEN", 3, xioopen_gopen, GROUP_FD|GROUP_FIFO|GROUP_CHR|GROUP_BLK|GROUP_REG|GROUP_NAMED|GROUP_OPEN|GROUP_FILE|GROUP_TERMIOS|GROUP_SOCKET|GROUP_SOCK_UNIX, 0, 0, 0 HELP(":<filename>") };
static int xioopen_gopen(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *xxfd, groups_t groups, int dummy1, int dummy2, int dummy3) { static int xioopen_gopen(
int argc,
const char *argv[],
struct opt *opts,
int xioflags,
xiofile_t *xxfd,
const struct addrdesc *addrdesc)
{
struct single *sfd = &xxfd->stream; struct single *sfd = &xxfd->stream;
const char *filename = argv[1]; const char *filename = argv[1];
flags_t openflags = (xioflags & XIO_ACCMODE); flags_t openflags = (xioflags & XIO_ACCMODE);
@ -29,7 +36,9 @@ static int xioopen_gopen(int argc, const char *argv[], struct opt *opts, int xio
int result; int result;
if ((result = if ((result =
_xioopen_named_early(argc, argv, xxfd, GROUP_NAMED|groups, &exists, opts)) < 0) { _xioopen_named_early(argc, argv, xxfd, GROUP_NAMED|addrdesc->groups, &exists,
opts, addrdesc->syntax))
< 0) {
return result; return result;
} }
st_mode = result; st_mode = result;
@ -53,7 +62,7 @@ static int xioopen_gopen(int argc, const char *argv[], struct opt *opts, int xio
Info1("\"%s\" is a socket, connecting to it", filename); Info1("\"%s\" is a socket, connecting to it", filename);
result = result =
_xioopen_unix_client(sfd, xioflags, groups, 0, opts, filename); _xioopen_unix_client(sfd, xioflags, addrdesc->groups, 0, opts, filename);
if (result < 0) { if (result < 0) {
return result; return result;
} }

View file

@ -15,10 +15,7 @@
#include "xio-interface.h" #include "xio-interface.h"
static static int xioopen_interface(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *xfd, const struct addrdesc *addrdesc);
int xioopen_interface(int argc, const char *argv[], struct opt *opts,
int xioflags, xiofile_t *xfd, groups_t groups, int pf,
int dummy2, int dummy3);
/*0 const struct optdesc opt_interface_addr = { "interface-addr", "address", OPT_INTERFACE_ADDR, GROUP_INTERFACE, PH_FD, TYPE_STRING, OFUNC_SPEC };*/ /*0 const struct optdesc opt_interface_addr = { "interface-addr", "address", OPT_INTERFACE_ADDR, GROUP_INTERFACE, PH_FD, TYPE_STRING, OFUNC_SPEC };*/
/*0 const struct optdesc opt_interface_netmask = { "interface-netmask", "netmask", OPT_INTERFACE_NETMASK, GROUP_INTERFACE, PH_FD, TYPE_STRING, OFUNC_SPEC };*/ /*0 const struct optdesc opt_interface_netmask = { "interface-netmask", "netmask", OPT_INTERFACE_NETMASK, GROUP_INTERFACE, PH_FD, TYPE_STRING, OFUNC_SPEC };*/
@ -62,7 +59,7 @@ static
int _xioopen_interface(const char *ifname, int _xioopen_interface(const char *ifname,
struct opt *opts, int xioflags, xiofile_t *xxfd, struct opt *opts, int xioflags, xiofile_t *xxfd,
groups_t groups, int pf) { groups_t groups, int pf) {
xiosingle_t *xfd = &xxfd->stream; xiosingle_t *sfd = &xxfd->stream;
union sockaddr_union us = {{0}}; union sockaddr_union us = {{0}};
socklen_t uslen; socklen_t uslen;
int socktype = SOCK_RAW; int socktype = SOCK_RAW;
@ -77,21 +74,21 @@ int _xioopen_interface(const char *ifname,
ifidx = 0; /* desparate attempt to continue */ ifidx = 0; /* desparate attempt to continue */
} }
xfd->howtoend = END_INTERFACE; sfd->howtoend = END_INTERFACE;
retropt_int(opts, OPT_SO_TYPE, &socktype); retropt_int(opts, OPT_SO_TYPE, &socktype);
retropt_socket_pf(opts, &pf); retropt_socket_pf(opts, &pf);
/* ...res_opts[] */ /* ...res_opts[] */
if (applyopts_single(xfd, opts, PH_INIT) < 0) return -1; if (applyopts_single(sfd, opts, PH_INIT) < 0) return -1;
applyopts(xfd, -1, opts, PH_INIT); applyopts(sfd, -1, opts, PH_INIT);
xfd->salen = sizeof(xfd->peersa); sfd->salen = sizeof(sfd->peersa);
if (pf == PF_UNSPEC) { if (pf == PF_UNSPEC) {
pf = xfd->peersa.soa.sa_family; pf = sfd->peersa.soa.sa_family;
} }
xfd->dtype = XIODATA_RECVFROM_SKIPIP; sfd->dtype = XIODATA_RECVFROM_SKIPIP;
if (retropt_string(opts, OPT_BIND, &bindstring)) { if (retropt_string(opts, OPT_BIND, &bindstring)) {
needbind = true; needbind = true;
@ -102,24 +99,24 @@ int _xioopen_interface(const char *ifname,
us.ll.sll_ifindex = ifidx; us.ll.sll_ifindex = ifidx;
uslen = sizeof(sall); uslen = sizeof(sall);
needbind = true; needbind = true;
xfd->peersa = (union sockaddr_union)us; sfd->peersa = (union sockaddr_union)us;
rc = rc =
_xioopen_dgram_sendto(needbind?&us:NULL, uslen, _xioopen_dgram_sendto(needbind?&us:NULL, uslen,
opts, xioflags, xfd, groups, pf, socktype, 0, 0); opts, xioflags, sfd, groups, pf, socktype, 0, 0);
if (rc < 0) if (rc < 0)
return rc; return rc;
strncpy(xfd->para.interface.name, ifname, IFNAMSIZ); strncpy(sfd->para.interface.name, ifname, IFNAMSIZ);
_xiointerface_get_iff(xfd->fd, ifname, &xfd->para.interface.save_iff); _xiointerface_get_iff(sfd->fd, ifname, &sfd->para.interface.save_iff);
_xiointerface_apply_iff(xfd->fd, ifname, xfd->para.interface.iff_opts); _xiointerface_apply_iff(sfd->fd, ifname, sfd->para.interface.iff_opts);
#ifdef PACKET_IGNORE_OUTGOING #ifdef PACKET_IGNORE_OUTGOING
/* Raw socket might also provide packets that are outbound - we are not /* Raw socket might also provide packets that are outbound - we are not
interested in these and disable this "feature" in kernel if possible */ interested in these and disable this "feature" in kernel if possible */
if (Setsockopt(xfd->fd, SOL_PACKET, PACKET_IGNORE_OUTGOING, &one, sizeof(one)) < 0) { if (Setsockopt(sfd->fd, SOL_PACKET, PACKET_IGNORE_OUTGOING, &one, sizeof(one)) < 0) {
Warn2("setsockopt(%d, SOL_PACKET, PACKET_IGNORE_OUTGOING, {1}): %s", Warn2("setsockopt(%d, SOL_PACKET, PACKET_IGNORE_OUTGOING, {1}): %s",
xfd->fd, strerror(errno)); sfd->fd, strerror(errno));
} }
#endif /*defined(PACKET_IGNORE_OUTGOING) */ #endif /*defined(PACKET_IGNORE_OUTGOING) */
@ -144,32 +141,37 @@ int _interface_setsockopt_auxdata(int fd, int auxdata) {
} }
static static
int xioopen_interface(int argc, const char *argv[], struct opt *opts, int xioopen_interface(
int xioflags, xiofile_t *xxfd, groups_t groups, int argc,
int pf, int dummy2, int dummy3) { const char *argv[],
xiosingle_t *xfd = &xxfd->stream; struct opt *opts,
int xioflags,
xiofile_t *xxfd,
const struct addrdesc *addrdesc)
{
xiosingle_t *sfd = &xxfd->stream;
int result; int result;
if (argc != 2) { if (argc != 2) {
Error2("%s: wrong number of parameters (%d instead of 1)", xio_syntax(argv[0], 1, argc-1, addrdesc->syntax);
argv[0], argc-1);
return STAT_NORETRY; return STAT_NORETRY;
} }
if ((result = if ((result =
_xioopen_interface(argv[1], opts, xioflags, xxfd, groups, pf)) _xioopen_interface(argv[1], opts, xioflags, xxfd, addrdesc->groups,
addrdesc->arg1))
!= STAT_OK) { != STAT_OK) {
return result; return result;
} }
xfd->dtype = XIOREAD_RECV|XIOWRITE_SENDTO; sfd->dtype = XIOREAD_RECV|XIOWRITE_SENDTO;
if (pf == PF_INET) { if (addrdesc->arg1 == PF_INET) {
xfd->dtype |= XIOREAD_RECV_SKIPIP; sfd->dtype |= XIOREAD_RECV_SKIPIP;
} }
xfd->para.socket.la.soa.sa_family = xfd->peersa.soa.sa_family; sfd->para.socket.la.soa.sa_family = sfd->peersa.soa.sa_family;
_xio_openlate(xfd, opts); _xio_openlate(sfd, opts);
return STAT_OK; return STAT_OK;
} }

View file

@ -731,7 +731,7 @@ int xiotype_ip_add_membership(
#if defined(HAVE_STRUCT_IP_MREQ) || defined (HAVE_STRUCT_IP_MREQN) #if defined(HAVE_STRUCT_IP_MREQ) || defined (HAVE_STRUCT_IP_MREQN)
int xioapply_ip_add_membership( int xioapply_ip_add_membership(
xiosingle_t *xfd, struct single *sfd,
struct opt *opt) struct opt *opt)
{ {
union { union {
@ -754,9 +754,9 @@ mc:addr
/* First parameter is always multicast address */ /* First parameter is always multicast address */
/*! result */ /*! result */
xioresolve(opt->value.u_string/*multiaddr*/, NULL, xioresolve(opt->value.u_string/*multiaddr*/, NULL,
xfd->para.socket.la.soa.sa_family, sfd->para.socket.la.soa.sa_family,
SOCK_DGRAM, IPPROTO_IP, &sockaddr1, &socklen1, SOCK_DGRAM, IPPROTO_IP, &sockaddr1, &socklen1,
xfd->para.socket.ip.ai_flags); sfd->para.socket.ip.ai_flags);
ip4_mreqn.mreq.imr_multiaddr = sockaddr1.ip4.sin_addr; ip4_mreqn.mreq.imr_multiaddr = sockaddr1.ip4.sin_addr;
if (0) { if (0) {
; /* for canonical reasons */ ; /* for canonical reasons */
@ -765,9 +765,9 @@ mc:addr
/* three parameters */ /* three parameters */
/* second parameter is interface address */ /* second parameter is interface address */
xioresolve(opt->value2.u_string/*param2*/, NULL, xioresolve(opt->value2.u_string/*param2*/, NULL,
xfd->para.socket.la.soa.sa_family, sfd->para.socket.la.soa.sa_family,
SOCK_DGRAM, IPPROTO_IP, &sockaddr2, &socklen2, SOCK_DGRAM, IPPROTO_IP, &sockaddr2, &socklen2,
xfd->para.socket.ip.ai_flags); sfd->para.socket.ip.ai_flags);
ip4_mreqn.mreq.imr_interface = sockaddr2.ip4.sin_addr; ip4_mreqn.mreq.imr_interface = sockaddr2.ip4.sin_addr;
/* third parameter is interface */ /* third parameter is interface */
if (ifindex(opt->value3.u_string/*ifindex*/, if (ifindex(opt->value3.u_string/*ifindex*/,
@ -793,10 +793,10 @@ mc:addr
} else { } else {
/*! result */ /*! result */
xioresolve(opt->value2.u_string/*param2*/, NULL, xioresolve(opt->value2.u_string/*param2*/, NULL,
xfd->para.socket.la.soa.sa_family, sfd->para.socket.la.soa.sa_family,
SOCK_DGRAM, IPPROTO_IP, SOCK_DGRAM, IPPROTO_IP,
&sockaddr2, &socklen2, &sockaddr2, &socklen2,
xfd->para.socket.ip.ai_flags); sfd->para.socket.ip.ai_flags);
ip4_mreqn.mreq.imr_interface = sockaddr2.ip4.sin_addr; ip4_mreqn.mreq.imr_interface = sockaddr2.ip4.sin_addr;
} }
} }
@ -804,18 +804,18 @@ mc:addr
#if LATER #if LATER
if (0) { if (0) {
; /* for canonical reasons */ ; /* for canonical reasons */
} else if (xfd->para.socket.la.soa.sa_family == PF_INET) { } else if (sfd->para.socket.la.soa.sa_family == PF_INET) {
} else if (xfd->para.socket.la.soa.sa_family == PF_INET6) { } else if (sfd->para.socket.la.soa.sa_family == PF_INET6) {
ip6_mreqn.mreq.imr_multiaddr = sockaddr1.ip6.sin6_addr; ip6_mreqn.mreq.imr_multiaddr = sockaddr1.ip6.sin6_addr;
ip6_mreqn.mreq.imr_interface = sockaddr2.ip6.sin6_addr; ip6_mreqn.mreq.imr_interface = sockaddr2.ip6.sin6_addr;
} }
#endif #endif
#if HAVE_STRUCT_IP_MREQN #if HAVE_STRUCT_IP_MREQN
if (Setsockopt(xfd->fd, opt->desc->major, opt->desc->minor, if (Setsockopt(sfd->fd, opt->desc->major, opt->desc->minor,
&ip4_mreqn.mreqn, sizeof(ip4_mreqn.mreqn)) < 0) { &ip4_mreqn.mreqn, sizeof(ip4_mreqn.mreqn)) < 0) {
Error8("setsockopt(%d, %d, %d, {0x%08x,0x%08x,%d}, "F_Zu"): %s", Error8("setsockopt(%d, %d, %d, {0x%08x,0x%08x,%d}, "F_Zu"): %s",
xfd->fd, opt->desc->major, opt->desc->minor, sfd->fd, opt->desc->major, opt->desc->minor,
ip4_mreqn.mreqn.imr_multiaddr.s_addr, ip4_mreqn.mreqn.imr_multiaddr.s_addr,
ip4_mreqn.mreqn.imr_address.s_addr, ip4_mreqn.mreqn.imr_address.s_addr,
ip4_mreqn.mreqn.imr_ifindex, ip4_mreqn.mreqn.imr_ifindex,
@ -825,10 +825,10 @@ mc:addr
return -1; return -1;
} }
#else #else
if (Setsockopt(xfd->fd, opt->desc->major, opt->desc->minor, if (Setsockopt(sfd->fd, opt->desc->major, opt->desc->minor,
&ip4_mreqn.mreq, sizeof(ip4_mreqn.mreq)) < 0) { &ip4_mreqn.mreq, sizeof(ip4_mreqn.mreq)) < 0) {
Error7("setsockopt(%d, %d, %d, {0x%08x,0x%08x}, "F_Zu"): %s", Error7("setsockopt(%d, %d, %d, {0x%08x,0x%08x}, "F_Zu"): %s",
xfd->fd, opt->desc->major, opt->desc->minor, sfd->fd, opt->desc->major, opt->desc->minor,
ip4_mreqn.mreq.imr_multiaddr, ip4_mreqn.mreq.imr_multiaddr,
ip4_mreqn.mreq.imr_interface, ip4_mreqn.mreq.imr_interface,
sizeof(ip4_mreqn.mreq), sizeof(ip4_mreqn.mreq),
@ -932,7 +932,7 @@ int xiotype_ip_add_source_membership(char *token, const struct optname *ent, str
return 0; return 0;
} }
int xioapply_ip_add_source_membership(struct single *xfd, struct opt *opt) { int xioapply_ip_add_source_membership(struct single *sfd, struct opt *opt) {
struct ip_mreq_source ip4_mreq_src = {{0}}; struct ip_mreq_source ip4_mreq_src = {{0}};
/* IPv6 not supported - seems to have different handling */ /* IPv6 not supported - seems to have different handling */
union sockaddr_union sockaddr1; union sockaddr_union sockaddr1;
@ -945,35 +945,35 @@ int xioapply_ip_add_source_membership(struct single *xfd, struct opt *opt) {
/* first parameter is always multicast address */ /* first parameter is always multicast address */
rc = xioresolve(opt->value.u_string/*mcaddr*/, NULL, rc = xioresolve(opt->value.u_string/*mcaddr*/, NULL,
xfd->para.socket.la.soa.sa_family, sfd->para.socket.la.soa.sa_family,
SOCK_DGRAM, IPPROTO_IP, SOCK_DGRAM, IPPROTO_IP,
&sockaddr1, &socklen1, xfd->para.socket.ip.ai_flags); &sockaddr1, &socklen1, sfd->para.socket.ip.ai_flags);
if (rc < 0) { if (rc < 0) {
return -1; return -1;
} }
ip4_mreq_src.imr_multiaddr = sockaddr1.ip4.sin_addr; ip4_mreq_src.imr_multiaddr = sockaddr1.ip4.sin_addr;
/* second parameter is interface address */ /* second parameter is interface address */
rc = xioresolve(opt->value.u_string/*ifaddr*/, NULL, rc = xioresolve(opt->value.u_string/*ifaddr*/, NULL,
xfd->para.socket.la.soa.sa_family, sfd->para.socket.la.soa.sa_family,
SOCK_DGRAM, IPPROTO_IP, SOCK_DGRAM, IPPROTO_IP,
&sockaddr2, &socklen2, xfd->para.socket.ip.ai_flags); &sockaddr2, &socklen2, sfd->para.socket.ip.ai_flags);
if (rc < 0) { if (rc < 0) {
return -1; return -1;
} }
ip4_mreq_src.imr_interface = sockaddr2.ip4.sin_addr; ip4_mreq_src.imr_interface = sockaddr2.ip4.sin_addr;
/* third parameter is source address */ /* third parameter is source address */
rc = xioresolve(opt->value.u_string/*srcaddr*/, NULL, rc = xioresolve(opt->value.u_string/*srcaddr*/, NULL,
xfd->para.socket.la.soa.sa_family, sfd->para.socket.la.soa.sa_family,
SOCK_DGRAM, IPPROTO_IP, SOCK_DGRAM, IPPROTO_IP,
&sockaddr3, &socklen3, xfd->para.socket.ip.ai_flags); &sockaddr3, &socklen3, sfd->para.socket.ip.ai_flags);
if (rc < 0) { if (rc < 0) {
return -1; return -1;
} }
ip4_mreq_src.imr_sourceaddr = sockaddr3.ip4.sin_addr; ip4_mreq_src.imr_sourceaddr = sockaddr3.ip4.sin_addr;
if (Setsockopt(xfd->fd, opt->desc->major, opt->desc->minor, if (Setsockopt(sfd->fd, opt->desc->major, opt->desc->minor,
&ip4_mreq_src, sizeof(ip4_mreq_src)) < 0) { &ip4_mreq_src, sizeof(ip4_mreq_src)) < 0) {
Error8("setsockopt(%d, %d, %d, {0x%08x,0x%08x,0x%08x}, "F_Zu"): %s", Error8("setsockopt(%d, %d, %d, {0x%08x,0x%08x,0x%08x}, "F_Zu"): %s",
xfd->fd, opt->desc->major, opt->desc->minor, sfd->fd, opt->desc->major, opt->desc->minor,
htonl((uint32_t)ip4_mreq_src.imr_multiaddr.s_addr), htonl((uint32_t)ip4_mreq_src.imr_multiaddr.s_addr),
ip4_mreq_src.imr_interface.s_addr, ip4_mreq_src.imr_interface.s_addr,
ip4_mreq_src.imr_sourceaddr.s_addr, ip4_mreq_src.imr_sourceaddr.s_addr,

View file

@ -259,7 +259,7 @@ int xiocheckrange_ip6(struct sockaddr_in6 *pa, struct xiorange *range) {
returns STAT_OK on success returns STAT_OK on success
*/ */
int xiolog_ancillary_ip6( int xiolog_ancillary_ip6(
struct single *xfd, struct single *sfd,
struct cmsghdr *cmsg, struct cmsghdr *cmsg,
int *num, int *num,
char *typbuff, int typlen, char *typbuff, int typlen,
@ -476,7 +476,7 @@ xiosetsockaddrenv_ip6(int idx, char *namebuff, size_t namelen,
#if defined(HAVE_STRUCT_IPV6_MREQ) #if defined(HAVE_STRUCT_IPV6_MREQ)
int xioapply_ipv6_join_group( int xioapply_ipv6_join_group(
xiosingle_t *xfd, struct single *sfd,
struct opt *opt) struct opt *opt)
{ {
struct ipv6_mreq ip6_mreq = {{{{0}}}}; struct ipv6_mreq ip6_mreq = {{{{0}}}};
@ -488,10 +488,10 @@ int xioapply_ipv6_join_group(
/* First parameter is multicast address */ /* First parameter is multicast address */
if ((res = if ((res =
xioresolve(opt->value.u_string/*multiaddr*/, NULL, xioresolve(opt->value.u_string/*multiaddr*/, NULL,
xfd->para.socket.la.soa.sa_family, sfd->para.socket.la.soa.sa_family,
SOCK_DGRAM, IPPROTO_IP, SOCK_DGRAM, IPPROTO_IP,
&sockaddr1, &socklen1, &sockaddr1, &socklen1,
xfd->para.socket.ip.ai_flags)) sfd->para.socket.ip.ai_flags))
!= STAT_OK) { != STAT_OK) {
return res; return res;
} }
@ -504,10 +504,10 @@ int xioapply_ipv6_join_group(
ip6_mreq.ipv6mr_interface = htonl(0); ip6_mreq.ipv6mr_interface = htonl(0);
} }
if (Setsockopt(xfd->fd, opt->desc->major, opt->desc->minor, if (Setsockopt(sfd->fd, opt->desc->major, opt->desc->minor,
&ip6_mreq, sizeof(ip6_mreq)) < 0) { &ip6_mreq, sizeof(ip6_mreq)) < 0) {
Error6("setsockopt(%d, %d, %d, {...,0x%08x}, "F_Zu"): %s", Error6("setsockopt(%d, %d, %d, {...,0x%08x}, "F_Zu"): %s",
xfd->fd, opt->desc->major, opt->desc->minor, sfd->fd, opt->desc->major, opt->desc->minor,
ip6_mreq.ipv6mr_interface, ip6_mreq.ipv6mr_interface,
sizeof(ip6_mreq), sizeof(ip6_mreq),
strerror(errno)); strerror(errno));
@ -618,7 +618,7 @@ int xiotype_ip6_join_source_group(
return 0; return 0;
} }
int xioapply_ip6_join_source_group(struct single *xfd, struct opt *opt) { int xioapply_ip6_join_source_group(struct single *sfd, struct opt *opt) {
struct group_source_req ip6_gsr = {0}; struct group_source_req ip6_gsr = {0};
union sockaddr_union sockaddr1; union sockaddr_union sockaddr1;
socklen_t socklen1 = sizeof(sockaddr1.ip6); socklen_t socklen1 = sizeof(sockaddr1.ip6);
@ -629,9 +629,9 @@ int xioapply_ip6_join_source_group(struct single *xfd, struct opt *opt) {
/* First parameter is always multicast address */ /* First parameter is always multicast address */
if ((res = if ((res =
xioresolve(opt->value.u_string/*mcaddr*/, NULL, xioresolve(opt->value.u_string/*mcaddr*/, NULL,
xfd->para.socket.la.soa.sa_family, sfd->para.socket.la.soa.sa_family,
SOCK_DGRAM, IPPROTO_IP, &sockaddr1, &socklen1, SOCK_DGRAM, IPPROTO_IP, &sockaddr1, &socklen1,
xfd->para.socket.ip.ai_flags)) sfd->para.socket.ip.ai_flags))
!= STAT_OK) { != STAT_OK) {
return res; return res;
} }
@ -647,17 +647,17 @@ int xioapply_ip6_join_source_group(struct single *xfd, struct opt *opt) {
/* Third parameter is source address */ /* Third parameter is source address */
if ((res = if ((res =
xioresolve(opt->value3.u_string/*srcaddr*/, NULL, xioresolve(opt->value3.u_string/*srcaddr*/, NULL,
xfd->para.socket.la.soa.sa_family, sfd->para.socket.la.soa.sa_family,
SOCK_DGRAM, IPPROTO_IP, &sockaddr2, &socklen2, SOCK_DGRAM, IPPROTO_IP, &sockaddr2, &socklen2,
xfd->para.socket.ip.ai_flags)) sfd->para.socket.ip.ai_flags))
!= STAT_OK) { != STAT_OK) {
return res; return res;
} }
memcpy(&ip6_gsr.gsr_source, &sockaddr2.ip6, socklen2); memcpy(&ip6_gsr.gsr_source, &sockaddr2.ip6, socklen2);
if (Setsockopt(xfd->fd, opt->desc->major, opt->desc->minor, if (Setsockopt(sfd->fd, opt->desc->major, opt->desc->minor,
&ip6_gsr, sizeof(ip6_gsr)) < 0) { &ip6_gsr, sizeof(ip6_gsr)) < 0) {
Error6("setsockopt(%d, %d, %d, {%d,...}, "F_Zu"): %s", Error6("setsockopt(%d, %d, %d, {%d,...}, "F_Zu"): %s",
xfd->fd, opt->desc->major, opt->desc->minor, sfd->fd, opt->desc->major, opt->desc->minor,
ip6_gsr.gsr_interface, ip6_gsr.gsr_interface,
sizeof(ip6_gsr), sizeof(ip6_gsr),
strerror(errno)); strerror(errno));

View file

@ -21,12 +21,19 @@ const struct optdesc opt_lowport = { "lowport", NULL, OPT_LOWPORT, GROUP_IPAPP,
#if WITH_IP4 #if WITH_IP4
/* we expect the form "host:port" */ /* we expect the form "host:port" */
int xioopen_ipapp_connect(int argc, const char *argv[], struct opt *opts, int xioopen_ipapp_connect(
int xioflags, xiofile_t *xxfd, int argc,
groups_t groups, int socktype, int ipproto, const char *argv[],
int pf) { struct opt *opts,
struct single *xfd = &xxfd->stream; int xioflags,
xiofile_t *xxfd,
const struct addrdesc *addrdesc)
{
struct single *sfd = &xxfd->stream;
struct opt *opts0 = NULL; struct opt *opts0 = NULL;
int socktype = addrdesc->arg1;
int ipproto = addrdesc->arg2;
int pf = addrdesc->arg3;
const char *hostname = argv[1], *portname = argv[2]; const char *hostname = argv[1], *portname = argv[2];
bool dofork = false; bool dofork = false;
union sockaddr_union us_sa, *us = &us_sa; union sockaddr_union us_sa, *us = &us_sa;
@ -41,19 +48,21 @@ int xioopen_ipapp_connect(int argc, const char *argv[], struct opt *opts,
int result; int result;
if (argc != 3) { if (argc != 3) {
Error2("%s: wrong number of parameters (%d instead of 2)", argv[0], argc-1); xio_syntax(argv[0], 2, argc-1, addrdesc->syntax);
return STAT_NORETRY;
} }
xfd->howtoend = END_SHUTDOWN; xioinit_ip(&pf, xioparms.default_ip);
sfd->howtoend = END_SHUTDOWN;
if (applyopts_single(xfd, opts, PH_INIT) < 0) if (applyopts_single(sfd, opts, PH_INIT) < 0)
return -1; return -1;
applyopts(xfd, -1, opts, PH_INIT); applyopts(sfd, -1, opts, PH_INIT);
retropt_bool(opts, OPT_FORK, &dofork); retropt_bool(opts, OPT_FORK, &dofork);
if (_xioopen_ipapp_prepare(opts, &opts0, hostname, portname, &pf, ipproto, if (_xioopen_ipapp_prepare(opts, &opts0, hostname, portname, &pf, ipproto,
xfd->para.socket.ip.ai_flags, sfd->para.socket.ip.ai_flags,
&themlist, us, &uslen, &needbind, &lowport, &themlist, us, &uslen, &needbind, &lowport,
socktype) != STAT_OK) { socktype) != STAT_OK) {
return STAT_NORETRY; return STAT_NORETRY;
@ -95,14 +104,14 @@ int xioopen_ipapp_connect(int argc, const char *argv[], struct opt *opts,
infobuff, sizeof(infobuff))); infobuff, sizeof(infobuff)));
#if WITH_RETRY #if WITH_RETRY
if (xfd->forever || xfd->retry || ai_sorted[i] != NULL) { if (sfd->forever || sfd->retry || ai_sorted[i] != NULL) {
level = E_INFO; level = E_INFO;
} else } else
#endif /* WITH_RETRY */ #endif /* WITH_RETRY */
level = E_ERROR; level = E_ERROR;
result = result =
_xioopen_connect(xfd, _xioopen_connect(sfd,
needbind?us:NULL, uslen, needbind?us:NULL, uslen,
themp->ai_addr, themp->ai_addrlen, themp->ai_addr, themp->ai_addrlen,
opts, pf?pf:themp->ai_family, socktype, ipproto, opts, pf?pf:themp->ai_family, socktype, ipproto,
@ -119,10 +128,10 @@ int xioopen_ipapp_connect(int argc, const char *argv[], struct opt *opts,
#if WITH_RETRY #if WITH_RETRY
case STAT_RETRYLATER: case STAT_RETRYLATER:
case STAT_RETRYNOW: case STAT_RETRYNOW:
if (xfd->forever || xfd->retry) { if (sfd->forever || sfd->retry) {
--xfd->retry; --sfd->retry;
if (result == STAT_RETRYLATER) { if (result == STAT_RETRYLATER) {
Nanosleep(&xfd->intervall, NULL); Nanosleep(&sfd->intervall, NULL);
} }
dropopts(opts, PH_ALL); free(opts); opts = copyopts(opts0, GROUP_ALL); dropopts(opts, PH_ALL); free(opts); opts = copyopts(opts0, GROUP_ALL);
continue; continue;
@ -138,13 +147,13 @@ int xioopen_ipapp_connect(int argc, const char *argv[], struct opt *opts,
if (dofork) { if (dofork) {
pid_t pid; pid_t pid;
int level = E_ERROR; int level = E_ERROR;
if (xfd->forever || xfd->retry) { if (sfd->forever || sfd->retry) {
level = E_WARN; /* most users won't expect a problem here, level = E_WARN; /* most users won't expect a problem here,
so Notice is too weak */ so Notice is too weak */
} }
while ((pid = xio_fork(false, level, xfd->shutup)) < 0) { while ((pid = xio_fork(false, level, sfd->shutup)) < 0) {
if (xfd->forever || --xfd->retry) { if (sfd->forever || --sfd->retry) {
Nanosleep(&xfd->intervall, NULL); continue; Nanosleep(&sfd->intervall, NULL); continue;
} }
free(ai_sorted); free(ai_sorted);
free(opts0); free(opts0);
@ -152,14 +161,14 @@ int xioopen_ipapp_connect(int argc, const char *argv[], struct opt *opts,
} }
if (pid == 0) { /* child process */ if (pid == 0) { /* child process */
xfd->forever = false; xfd->retry = 0; sfd->forever = false; sfd->retry = 0;
break; break;
} }
/* parent process */ /* parent process */
Close(xfd->fd); Close(sfd->fd);
/* with and without retry */ /* with and without retry */
Nanosleep(&xfd->intervall, NULL); Nanosleep(&sfd->intervall, NULL);
dropopts(opts, PH_ALL); free(opts); opts = copyopts(opts0, GROUP_ALL); dropopts(opts, PH_ALL); free(opts); opts = copyopts(opts0, GROUP_ALL);
continue; /* with next socket() bind() connect() */ continue; /* with next socket() bind() connect() */
} else } else
@ -172,7 +181,7 @@ int xioopen_ipapp_connect(int argc, const char *argv[], struct opt *opts,
free(ai_sorted); free(ai_sorted);
xiofreeaddrinfo(themlist); xiofreeaddrinfo(themlist);
if ((result = _xio_openlate(xfd, opts)) < 0) { if ((result = _xio_openlate(sfd, opts)) < 0) {
free(opts0);free(opts); free(opts0);free(opts);
return result; return result;
} }
@ -302,18 +311,26 @@ int _xioopen_ipapp_listen_prepare(
/* we expect the form: port */ /* we expect the form: port */
/* currently only used for TCP4 */ /* currently only used for TCP4 */
int xioopen_ipapp_listen(int argc, const char *argv[], struct opt *opts, int xioopen_ipapp_listen(
int xioflags, xiofile_t *xfd, int argc,
groups_t groups, int socktype, const char *argv[],
int ipproto, int pf) { struct opt *opts,
int xioflags,
xiofile_t *xfd,
const struct addrdesc *addrdesc)
{
struct single *sfd = &xfd->stream; struct single *sfd = &xfd->stream;
struct opt *opts0 = NULL; struct opt *opts0 = NULL;
int socktype = addrdesc->arg1;
int ipproto = addrdesc->arg2;
int pf = addrdesc->arg3;
union sockaddr_union us_sa, *us = &us_sa; union sockaddr_union us_sa, *us = &us_sa;
socklen_t uslen = sizeof(us_sa); socklen_t uslen = sizeof(us_sa);
int result; int result;
if (argc != 2) { if (argc != 2) {
Error2("%s: wrong number of parameters (%d instead of 1)", argv[0], argc-1); xio_syntax(argv[0], 2, argc-1, addrdesc->syntax);
return STAT_NORETRY;
} }
xioinit_ip(&pf, xioparms.default_ip); xioinit_ip(&pf, xioparms.default_ip);
@ -331,23 +348,23 @@ int xioopen_ipapp_listen(int argc, const char *argv[], struct opt *opts,
#endif #endif
} }
xfd->stream.howtoend = END_SHUTDOWN; sfd->howtoend = END_SHUTDOWN;
if (applyopts_single(&xfd->stream, opts, PH_INIT) < 0) return -1; if (applyopts_single(sfd, opts, PH_INIT) < 0) return -1;
applyopts(sfd, -1, opts, PH_INIT); applyopts(sfd, -1, opts, PH_INIT);
applyopts(sfd, -1, opts, PH_EARLY); applyopts(sfd, -1, opts, PH_EARLY);
if (_xioopen_ipapp_listen_prepare(opts, &opts0, argv[1], &pf, ipproto, if (_xioopen_ipapp_listen_prepare(opts, &opts0, argv[1], &pf, ipproto,
xfd->stream.para.socket.ip.ai_flags, sfd->para.socket.ip.ai_flags,
us, &uslen, socktype) us, &uslen, socktype)
!= STAT_OK) { != STAT_OK) {
return STAT_NORETRY; return STAT_NORETRY;
} }
if ((result = if ((result =
xioopen_listen(&xfd->stream, xioflags, xioopen_listen(sfd, xioflags,
(struct sockaddr *)us, uslen, (struct sockaddr *)us, uslen,
opts, opts0, pf, socktype, ipproto)) opts, opts0, pf, socktype, ipproto))
!= 0) != 0)
return result; return result;
return 0; return 0;

View file

@ -14,19 +14,13 @@ extern const struct optdesc opt_sourceport;
/*extern const struct optdesc opt_port;*/ /*extern const struct optdesc opt_port;*/
extern const struct optdesc opt_lowport; extern const struct optdesc opt_lowport;
extern int xioopen_ipapp_connect(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *fd, extern int xioopen_ipapp_connect(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *fd, const struct addrdesc *addrdesc);
groups_t groups, int socktype, extern int _xioopen_ipapp_prepare(struct opt *opts, struct opt **opts0, const char *hostname, const char *portname, int *pf, int protocol, const int ai_flags[2], struct addrinfo **res, union sockaddr_union *us, socklen_t *uslen, bool *needbind, bool *lowport, int socktype);
int ipproto, int protname);
extern int _xioopen_ipapp_prepare(struct opt *opts, struct opt **opts0, const char *hostname, const char *portname, int *pf, int protocol, const int ai_flags[2], struct addrinfo **res, union sockaddr_union *us, socklen_t *uslen, bool *needbind, bool *lowport,
int socktype);
extern int _xioopen_ip4app_connect(const char *hostname, const char *portname, extern int _xioopen_ip4app_connect(const char *hostname, const char *portname,
struct single *xfd, struct single *xfd,
int socktype, int ipproto, void *protname, int socktype, int ipproto, void *protname,
struct opt *opts); struct opt *opts);
extern int xioopen_ipapp_listen(int argc, const char *argv[], struct opt *opts, extern int xioopen_ipapp_listen(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *fd, const struct addrdesc *addrdesc);
int xioflags, xiofile_t *fd,
groups_t groups, int socktype,
int ipproto, int protname);
extern int _xioopen_ipapp_listen_prepare(struct opt *opts, struct opt **opts0, const char *portname, int *pf, int ipproto, const int ai_flags[2], union sockaddr_union *us, socklen_t *uslen, int socktype); extern int _xioopen_ipapp_listen_prepare(struct opt *opts, struct opt **opts0, const char *portname, int *pf, int ipproto, const int ai_flags[2], union sockaddr_union *us, socklen_t *uslen, int socktype);
extern int _xio_sort_ip_addresses(struct addrinfo *themlist, struct addrinfo **ai_sorted); extern int _xio_sort_ip_addresses(struct addrinfo *themlist, struct addrinfo **ai_sorted);

View file

@ -35,7 +35,7 @@ const struct optdesc opt_accept_timeout = { "accept-timeout", "listen-timeout",
OPT_SOURCEPORT, OPT_LOWPORT, cloexec OPT_SOURCEPORT, OPT_LOWPORT, cloexec
*/ */
int int
xioopen_listen(struct single *xfd, int xioflags, xioopen_listen(struct single *sfd, int xioflags,
struct sockaddr *us, socklen_t uslen, struct sockaddr *us, socklen_t uslen,
struct opt *opts, struct opt *opts0, struct opt *opts, struct opt *opts0,
int pf, int socktype, int proto) { int pf, int socktype, int proto) {
@ -43,7 +43,7 @@ int
int result; int result;
#if WITH_RETRY #if WITH_RETRY
if (xfd->forever || xfd->retry) { if (sfd->forever || sfd->retry) {
level = E_INFO; level = E_INFO;
} else } else
#endif /* WITH_RETRY */ #endif /* WITH_RETRY */
@ -53,7 +53,7 @@ int
/* tcp listen; this can fork() for us; it only returns on error or on /* tcp listen; this can fork() for us; it only returns on error or on
successful establishment of tcp connection */ successful establishment of tcp connection */
result = _xioopen_listen(xfd, xioflags, result = _xioopen_listen(sfd, xioflags,
(struct sockaddr *)us, uslen, (struct sockaddr *)us, uslen,
opts, pf, socktype, proto, level); opts, pf, socktype, proto, level);
/*! not sure if we should try again on retry/forever */ /*! not sure if we should try again on retry/forever */
@ -62,13 +62,13 @@ int
#if WITH_RETRY #if WITH_RETRY
case STAT_RETRYLATER: case STAT_RETRYLATER:
case STAT_RETRYNOW: case STAT_RETRYNOW:
if (xfd->forever || xfd->retry) { if (sfd->forever || sfd->retry) {
dropopts(opts, PH_ALL); opts = copyopts(opts0, GROUP_ALL); dropopts(opts, PH_ALL); opts = copyopts(opts0, GROUP_ALL);
if (result == STAT_RETRYLATER) { if (result == STAT_RETRYLATER) {
Nanosleep(&xfd->intervall, NULL); Nanosleep(&sfd->intervall, NULL);
} }
dropopts(opts, PH_ALL); opts = copyopts(opts0, GROUP_ALL); dropopts(opts, PH_ALL); opts = copyopts(opts0, GROUP_ALL);
--xfd->retry; --sfd->retry;
continue; continue;
} }
return STAT_NORETRY; return STAT_NORETRY;
@ -103,31 +103,31 @@ int
OPT_FORK, OPT_SO_TYPE, OPT_SO_PROTOTYPE, OPT_BACKLOG, OPT_RANGE, tcpwrap, OPT_FORK, OPT_SO_TYPE, OPT_SO_PROTOTYPE, OPT_BACKLOG, OPT_RANGE, tcpwrap,
OPT_SOURCEPORT, OPT_LOWPORT, cloexec OPT_SOURCEPORT, OPT_LOWPORT, cloexec
*/ */
int _xioopen_listen(struct single *xfd, int xioflags, struct sockaddr *us, socklen_t uslen, int _xioopen_listen(struct single *sfd, int xioflags, struct sockaddr *us, socklen_t uslen,
struct opt *opts, int pf, int socktype, int proto, int level) { struct opt *opts, int pf, int socktype, int proto, int level) {
int backlog = 5; /* why? 1 seems to cause problems under some load */ int backlog = 5; /* why? 1 seems to cause problems under some load */
char infobuff[256]; char infobuff[256];
if (applyopts_single(xfd, opts, PH_INIT) < 0) return -1; if (applyopts_single(sfd, opts, PH_INIT) < 0) return -1;
if ((xfd->fd = xiosocket(opts, pf?pf:us->sa_family, socktype, proto, level)) < 0) { if ((sfd->fd = xiosocket(opts, pf?pf:us->sa_family, socktype, proto, level)) < 0) {
return STAT_RETRYLATER; return STAT_RETRYLATER;
} }
applyopts(xfd, -1, opts, PH_PASTSOCKET); applyopts(sfd, -1, opts, PH_PASTSOCKET);
applyopts_offset(xfd, opts); applyopts_offset(sfd, opts);
applyopts_cloexec(xfd->fd, opts); applyopts_cloexec(sfd->fd, opts);
/* Phase prebind */ /* Phase prebind */
xiosock_reuseaddr(xfd->fd, proto, opts); xiosock_reuseaddr(sfd->fd, proto, opts);
applyopts(xfd, -1, opts, PH_PREBIND); applyopts(sfd, -1, opts, PH_PREBIND);
applyopts(xfd, -1, opts, PH_BIND); applyopts(sfd, -1, opts, PH_BIND);
if (Bind(xfd->fd, (struct sockaddr *)us, uslen) < 0) { if (Bind(sfd->fd, (struct sockaddr *)us, uslen) < 0) {
Msg4(level, "bind(%d, {%s}, "F_socklen"): %s", xfd->fd, Msg4(level, "bind(%d, {%s}, "F_socklen"): %s", sfd->fd,
sockaddr_info(us, uslen, infobuff, sizeof(infobuff)), uslen, sockaddr_info(us, uslen, infobuff, sizeof(infobuff)), uslen,
strerror(errno)); strerror(errno));
Close(xfd->fd); Close(sfd->fd);
return STAT_RETRYLATER; return STAT_RETRYLATER;
} }
@ -136,36 +136,36 @@ int _xioopen_listen(struct single *xfd, int xioflags, struct sockaddr *us, sockl
if (((union sockaddr_union *)us)->un.sun_path[0] != '\0') { if (((union sockaddr_union *)us)->un.sun_path[0] != '\0') {
applyopts_named(((struct sockaddr_un *)us)->sun_path, opts, PH_FD); applyopts_named(((struct sockaddr_un *)us)->sun_path, opts, PH_FD);
} else { } else {
applyopts(xfd, -1, opts, PH_FD); applyopts(sfd, -1, opts, PH_FD);
} }
} }
#endif #endif
applyopts(xfd, -1, opts, PH_PASTBIND); applyopts(sfd, -1, opts, PH_PASTBIND);
#if WITH_UNIX #if WITH_UNIX
if (us->sa_family == AF_UNIX) { if (us->sa_family == AF_UNIX) {
if (((union sockaddr_union *)us)->un.sun_path[0] != '\0') { if (((union sockaddr_union *)us)->un.sun_path[0] != '\0') {
applyopts_named(((struct sockaddr_un *)us)->sun_path, opts, PH_EARLY); applyopts_named(((struct sockaddr_un *)us)->sun_path, opts, PH_EARLY);
applyopts_named(((struct sockaddr_un *)us)->sun_path, opts, PH_PREOPEN); applyopts_named(((struct sockaddr_un *)us)->sun_path, opts, PH_PREOPEN);
} else { } else {
applyopts(xfd, -1, opts, PH_EARLY); applyopts(sfd, -1, opts, PH_EARLY);
applyopts(xfd, -1, opts, PH_PREOPEN); applyopts(sfd, -1, opts, PH_PREOPEN);
} }
} }
#endif /* WITH_UNIX */ #endif /* WITH_UNIX */
applyopts(xfd, -1, opts, PH_PRELISTEN); applyopts(sfd, -1, opts, PH_PRELISTEN);
retropt_int(opts, OPT_BACKLOG, &backlog); retropt_int(opts, OPT_BACKLOG, &backlog);
applyopts(xfd, -1, opts, PH_LISTEN); applyopts(sfd, -1, opts, PH_LISTEN);
if (Listen(xfd->fd, backlog) < 0) { if (Listen(sfd->fd, backlog) < 0) {
Error3("listen(%d, %d): %s", xfd->fd, backlog, strerror(errno)); Error3("listen(%d, %d): %s", sfd->fd, backlog, strerror(errno));
return STAT_RETRYLATER; return STAT_RETRYLATER;
} }
return _xioopen_accept_fd(xfd, xioflags, us, uslen, opts, pf, proto,level); return _xioopen_accept_fd(sfd, xioflags, us, uslen, opts, pf, proto,level);
} }
int _xioopen_accept_fd( int _xioopen_accept_fd(
struct single *xfd, struct single *sfd,
int xioflags, int xioflags,
struct sockaddr *us, struct sockaddr *us,
socklen_t uslen, socklen_t uslen,
@ -196,7 +196,7 @@ int _xioopen_accept_fd(
Error("option fork not allowed here"); Error("option fork not allowed here");
return STAT_NORETRY; return STAT_NORETRY;
} }
xfd->flags |= XIO_DOESFORK; sfd->flags |= XIO_DOESFORK;
} }
retropt_int(opts, OPT_MAX_CHILDREN, &maxchildren); retropt_int(opts, OPT_MAX_CHILDREN, &maxchildren);
@ -213,33 +213,33 @@ int _xioopen_accept_fd(
/* Under some circumstances (e.g., TCP listen on port 0) bind() fills empty /* Under some circumstances (e.g., TCP listen on port 0) bind() fills empty
fields that we want to know. */ fields that we want to know. */
salen = sizeof(sa); salen = sizeof(sa);
if (Getsockname(xfd->fd, us, &uslen) < 0) { if (Getsockname(sfd->fd, us, &uslen) < 0) {
Warn4("getsockname(%d, %p, {%d}): %s", Warn4("getsockname(%d, %p, {%d}): %s",
xfd->fd, &us, uslen, strerror(errno)); sfd->fd, &us, uslen, strerror(errno));
} }
#if WITH_IP4 /*|| WITH_IP6*/ #if WITH_IP4 /*|| WITH_IP6*/
if (retropt_string(opts, OPT_RANGE, &rangename) >= 0) { if (retropt_string(opts, OPT_RANGE, &rangename) >= 0) {
if (xioparserange(rangename, pf, &xfd->para.socket.range, if (xioparserange(rangename, pf, &sfd->para.socket.range,
xfd->para.socket.ip.ai_flags) sfd->para.socket.ip.ai_flags)
< 0) { < 0) {
free(rangename); free(rangename);
return STAT_NORETRY; return STAT_NORETRY;
} }
free(rangename); free(rangename);
xfd->para.socket.dorange = true; sfd->para.socket.dorange = true;
} }
#endif #endif
#if (WITH_TCP || WITH_UDP) && WITH_LIBWRAP #if (WITH_TCP || WITH_UDP) && WITH_LIBWRAP
xio_retropt_tcpwrap(xfd, opts); xio_retropt_tcpwrap(sfd, opts);
#endif /* && (WITH_TCP || WITH_UDP) && WITH_LIBWRAP */ #endif /* && (WITH_TCP || WITH_UDP) && WITH_LIBWRAP */
#if WITH_TCP || WITH_UDP #if WITH_TCP || WITH_UDP
if (retropt_ushort(opts, OPT_SOURCEPORT, &xfd->para.socket.ip.sourceport) >= 0) { if (retropt_ushort(opts, OPT_SOURCEPORT, &sfd->para.socket.ip.sourceport) >= 0) {
xfd->para.socket.ip.dosourceport = true; sfd->para.socket.ip.dosourceport = true;
} }
retropt_bool(opts, OPT_LOWPORT, &xfd->para.socket.ip.lowport); retropt_bool(opts, OPT_LOWPORT, &sfd->para.socket.ip.lowport);
#endif /* WITH_TCP || WITH_UDP */ #endif /* WITH_TCP || WITH_UDP */
if (xioparms.logopt == 'm') { if (xioparms.logopt == 'm') {
@ -259,30 +259,30 @@ int _xioopen_accept_fd(
do { do {
/*? int level = E_ERROR;*/ /*? int level = E_ERROR;*/
Notice1("listening on %s", sockaddr_info(us, uslen, lisname, sizeof(lisname))); Notice1("listening on %s", sockaddr_info(us, uslen, lisname, sizeof(lisname)));
if (xfd->para.socket.accept_timeout.tv_sec > 0 || if (sfd->para.socket.accept_timeout.tv_sec > 0 ||
xfd->para.socket.accept_timeout.tv_usec > 0) { sfd->para.socket.accept_timeout.tv_usec > 0) {
fd_set rfd; fd_set rfd;
struct timeval tmo; struct timeval tmo;
FD_ZERO(&rfd); FD_ZERO(&rfd);
FD_SET(xfd->fd, &rfd); FD_SET(sfd->fd, &rfd);
tmo.tv_sec = xfd->para.socket.accept_timeout.tv_sec; tmo.tv_sec = sfd->para.socket.accept_timeout.tv_sec;
tmo.tv_usec = xfd->para.socket.accept_timeout.tv_usec; tmo.tv_usec = sfd->para.socket.accept_timeout.tv_usec;
while (1) { while (1) {
if (Select(xfd->fd+1, &rfd, NULL, NULL, &tmo) < 0) { if (Select(sfd->fd+1, &rfd, NULL, NULL, &tmo) < 0) {
if (errno != EINTR) { if (errno != EINTR) {
Error5("Select(%d, &0x%lx, NULL, NULL, {%ld.%06ld}): %s", xfd->fd+1, 1L<<(xfd->fd+1), Error5("Select(%d, &0x%lx, NULL, NULL, {%ld.%06ld}): %s", sfd->fd+1, 1L<<(sfd->fd+1),
xfd->para.socket.accept_timeout.tv_sec, xfd->para.socket.accept_timeout.tv_usec, sfd->para.socket.accept_timeout.tv_sec, sfd->para.socket.accept_timeout.tv_usec,
strerror(errno)); strerror(errno));
} }
} else { } else {
break; break;
} }
} }
if (!FD_ISSET(xfd->fd, &rfd)) { if (!FD_ISSET(sfd->fd, &rfd)) {
struct sigaction act; struct sigaction act;
Warn1("accept: %s", strerror(ETIMEDOUT)); Warn1("accept: %s", strerror(ETIMEDOUT));
Close(xfd->fd); Close(sfd->fd);
Notice("Waiting for child processes to terminate"); Notice("Waiting for child processes to terminate");
memset(&act, 0, sizeof(struct sigaction)); memset(&act, 0, sizeof(struct sigaction));
act.sa_flags = SA_NOCLDSTOP/*|SA_RESTART*/ act.sa_flags = SA_NOCLDSTOP/*|SA_RESTART*/
@ -304,9 +304,9 @@ int _xioopen_accept_fd(
Exit(0); Exit(0);
} }
} }
ps = Accept(xfd->fd, (struct sockaddr *)&sa, &salen); ps = Accept(sfd->fd, (struct sockaddr *)&sa, &salen);
if (ps >= 0) { if (ps >= 0) {
/*0 Info4("accept(%d, %p, {"F_Zu"}) -> %d", xfd->fd, &sa, salen, ps);*/ /*0 Info4("accept(%d, %p, {"F_Zu"}) -> %d", sfd->fd, &sa, salen, ps);*/
break; /* success, break out of loop */ break; /* success, break out of loop */
} }
if (errno == EINTR) { if (errno == EINTR) {
@ -314,12 +314,12 @@ int _xioopen_accept_fd(
} }
if (errno == ECONNABORTED) { if (errno == ECONNABORTED) {
Notice4("accept(%d, %p, {"F_socklen"}): %s", Notice4("accept(%d, %p, {"F_socklen"}): %s",
xfd->fd, &sa, salen, strerror(errno)); sfd->fd, &sa, salen, strerror(errno));
continue; continue;
} }
Msg4(level, "accept(%d, %p, {"F_socklen"}): %s", Msg4(level, "accept(%d, %p, {"F_socklen"}): %s",
xfd->fd, &sa, salen, strerror(errno)); sfd->fd, &sa, salen, strerror(errno));
Close(xfd->fd); Close(sfd->fd);
return STAT_RETRYLATER; return STAT_RETRYLATER;
} while (true); } while (true);
applyopts_cloexec(ps, opts); applyopts_cloexec(ps, opts);
@ -339,7 +339,7 @@ int _xioopen_accept_fd(
la? la?
sockaddr_info(&la->soa, las, sockname, sizeof(sockname)):"NULL"); sockaddr_info(&la->soa, las, sockname, sizeof(sockname)):"NULL");
if (pa != NULL && la != NULL && xiocheckpeer(xfd, pa, la) < 0) { if (pa != NULL && la != NULL && xiocheckpeer(sfd, pa, la) < 0) {
if (Shutdown(ps, 2) < 0) { if (Shutdown(ps, 2) < 0) {
Info2("shutdown(%d, 2): %s", ps, strerror(errno)); Info2("shutdown(%d, 2): %s", ps, strerror(errno));
} }
@ -363,9 +363,9 @@ int _xioopen_accept_fd(
if ((pid = if ((pid =
xio_fork(false, level==E_ERROR?level:E_WARN, xio_fork(false, level==E_ERROR?level:E_WARN,
xfd->shutup)) sfd->shutup))
< 0) { < 0) {
Close(xfd->fd); Close(sfd->fd);
Sigprocmask(SIG_UNBLOCK, &mask_sigchld, NULL); Sigprocmask(SIG_UNBLOCK, &mask_sigchld, NULL);
return STAT_RETRYLATER; return STAT_RETRYLATER;
} }
@ -376,14 +376,14 @@ int _xioopen_accept_fd(
Info1("just born: child process "F_pid, cpid); Info1("just born: child process "F_pid, cpid);
xiosetenvulong("PID", cpid, 1); xiosetenvulong("PID", cpid, 1);
if (Close(xfd->fd) < 0) { if (Close(sfd->fd) < 0) {
Info2("close(%d): %s", xfd->fd, strerror(errno)); Info2("close(%d): %s", sfd->fd, strerror(errno));
} }
xfd->fd = ps; sfd->fd = ps;
#if WITH_RETRY #if WITH_RETRY
/* !? */ /* !? */
xfd->forever = false; xfd->retry = 0; sfd->forever = false; sfd->retry = 0;
level = E_ERROR; level = E_ERROR;
#endif /* WITH_RETRY */ #endif /* WITH_RETRY */
@ -410,18 +410,18 @@ int _xioopen_accept_fd(
} }
Info("still listening"); Info("still listening");
} else { } else {
if (Close(xfd->fd) < 0) { if (Close(sfd->fd) < 0) {
Info2("close(%d): %s", xfd->fd, strerror(errno)); Info2("close(%d): %s", sfd->fd, strerror(errno));
} }
xfd->fd = ps; sfd->fd = ps;
break; break;
} }
} }
applyopts(xfd, -1, opts, PH_FD); applyopts(sfd, -1, opts, PH_FD);
applyopts(xfd, -1, opts, PH_PASTSOCKET); applyopts(sfd, -1, opts, PH_PASTSOCKET);
applyopts(xfd, -1, opts, PH_CONNECTED); applyopts(sfd, -1, opts, PH_CONNECTED);
if ((result = _xio_openlate(xfd, opts)) < 0) if ((result = _xio_openlate(sfd, opts)) < 0)
return result; return result;
/* set the env vars describing the local and remote sockets */ /* set the env vars describing the local and remote sockets */

View file

@ -95,8 +95,14 @@ int applyopts_named(const char *filename, struct opt *opts, unsigned int phase)
If the path exists, its st_mode field is returned. If the path exists, its st_mode field is returned.
After this sub you may proceed with open() or whatever... After this sub you may proceed with open() or whatever...
*/ */
int _xioopen_named_early(int argc, const char *argv[], xiofile_t *xfd, int _xioopen_named_early(
groups_t groups, bool *exists, struct opt *opts) int argc,
const char *argv[],
xiofile_t *xfd,
groups_t groups,
bool *exists,
struct opt *opts,
const char *syntax)
{ {
const char *path = argv[1]; const char *path = argv[1];
struct single *sfd = &xfd->stream; struct single *sfd = &xfd->stream;
@ -108,7 +114,8 @@ int _xioopen_named_early(int argc, const char *argv[], xiofile_t *xfd,
bool opt_unlink_early = false; bool opt_unlink_early = false;
if (argc != 2) { if (argc != 2) {
Error2("%s: wrong number of parameters (%d instead of 1)", argv[0]?argv[0]:"<named>", argc); xio_syntax(argv[0], 1, argc-1, syntax);
return STAT_NORETRY;
} }
statbuf.st_mode = 0; statbuf.st_mode = 0;
/* find the appropriate groupbits */ /* find the appropriate groupbits */

View file

@ -18,9 +18,7 @@ extern const struct optdesc opt_umask;
extern int extern int
applyopts_named(const char *filename, struct opt *opts, unsigned int phase); applyopts_named(const char *filename, struct opt *opts, unsigned int phase);
extern int _xioopen_named_early(int argc, const char *argv[], xiofile_t *xfd, extern int _xioopen_named_early(int argc, const char *argv[], xiofile_t *xfd, groups_t groups, bool *exists, struct opt *opts, const char *syntax);
groups_t groups,
bool *exists, struct opt *opts);
extern int _xioopen_open(const char *path, int rw, struct opt *opts); extern int _xioopen_open(const char *path, int rw, struct opt *opts);
extern int xio_unlink(const char *pathname, int level); extern int xio_unlink(const char *pathname, int level);

View file

@ -43,21 +43,18 @@
*/ */
/* static declaration of ssl's open function */ /* static declaration of ssl's open function */
static int xioopen_openssl_connect(int argc, const char *argv[], struct opt *opts, static int xioopen_openssl_connect(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *fd, const struct addrdesc *addrdesc);
int xioflags, xiofile_t *fd, groups_t groups,
int dummy1, int dummy2, int dummy3);
/* static declaration of ssl's open function */ /* static declaration of ssl's open function */
static int xioopen_openssl_listen(int argc, const char *argv[], struct opt *opts, static int xioopen_openssl_listen(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *fd, const struct addrdesc *addrdesc);
int xioflags, xiofile_t *fd, groups_t groups,
int dummy1, int dummy2, int dummy3);
static int openssl_SSL_ERROR_SSL(int level, const char *funcname); static int openssl_SSL_ERROR_SSL(int level, const char *funcname);
static int openssl_handle_peer_certificate(struct single *xfd, static int openssl_handle_peer_certificate(struct single *sfd,
const char *peername, const char *peername,
bool opt_ver, bool opt_ver,
int level); int level);
static int xioSSL_set_fd(struct single *xfd, int level); static int xioSSL_set_fd(struct single *sfd, int level);
static int xioSSL_connect(struct single *xfd, const char *opt_commonname, bool opt_ver, int level); static int xioSSL_connect(struct single *sfd, const char *opt_commonname, bool opt_ver, int level);
static int openssl_delete_cert_info(void); static int openssl_delete_cert_info(void);
@ -223,26 +220,20 @@ static void openssl_conn_loginfo(SSL *ssl) {
} }
/* the open function for OpenSSL client */ /* the open function for OpenSSL client */
static int static int xioopen_openssl_connect(
xioopen_openssl_connect(int argc, int argc,
const char *argv[], /* the arguments in the address string */ const char *argv[], /* the arguments in the address string */
struct opt *opts, struct opt *opts,
int xioflags, /* is the open meant for reading (0), int xioflags, /* is the open meant for reading (0),
writing (1), or both (2) ? */ writing (1), or both (2) ? */
xiofile_t *xxfd, /* a xio file descriptor structure, xiofile_t *xxfd, /* a xio file descriptor structure,
already allocated */ already allocated */
groups_t groups, /* the matching address groups... */ const struct addrdesc *addrdesc) /* the above descriptor */
int protogrp, /* first transparent integer value from
addr_openssl */
int dummy2, /* second transparent integer value from
addr_openssl */
int dummy3) /* transparent pointer value from
addr_openssl */
{ {
struct single *xfd = &xxfd->stream; struct single *sfd = &xxfd->stream;
struct single *sfd = xfd;
struct opt *opts0 = NULL; struct opt *opts0 = NULL;
const char *hostname, *portname; const char *hostname, *portname;
int protogrp = addrdesc->arg1;
int pf = PF_UNSPEC; int pf = PF_UNSPEC;
bool use_dtls = (protogrp != 0); bool use_dtls = (protogrp != 0);
int socktype = SOCK_STREAM; int socktype = SOCK_STREAM;
@ -268,10 +259,10 @@ static int
Error("address with data processing not allowed here"); Error("address with data processing not allowed here");
return STAT_NORETRY; return STAT_NORETRY;
} }
xfd->flags |= XIO_DOESCONVERT; sfd->flags |= XIO_DOESCONVERT;
if (argc != 3) { if (argc != 3) {
Error1("%s: 2 parameters required", argv[0]); xio_syntax(argv[0], 2, argc-1, addrdesc->syntax);
return STAT_NORETRY; return STAT_NORETRY;
} }
hostname = argv[1]; hostname = argv[1];
@ -283,8 +274,10 @@ static int
return STAT_NORETRY; return STAT_NORETRY;
} }
xfd->howtoend = END_SHUTDOWN; xioinit_ip(&pf, xioparms.default_ip);
if (applyopts_single(xfd, opts, PH_INIT) < 0) return -1; sfd->howtoend = END_SHUTDOWN;
if (applyopts_single(sfd, opts, PH_INIT) < 0)
return -1;
applyopts(sfd, -1, opts, PH_INIT); applyopts(sfd, -1, opts, PH_INIT);
retropt_bool(opts, OPT_FORK, &dofork); retropt_bool(opts, OPT_FORK, &dofork);
@ -317,7 +310,7 @@ static int
#endif #endif
result = result =
_xioopen_openssl_prepare(opts, xfd, false, &opt_ver, opt_cert, &ctx, (bool *)&use_dtls); _xioopen_openssl_prepare(opts, sfd, false, &opt_ver, opt_cert, &ctx, (bool *)&use_dtls);
if (result != STAT_OK) return STAT_NORETRY; if (result != STAT_OK) return STAT_NORETRY;
if (use_dtls) { if (use_dtls) {
@ -329,7 +322,7 @@ static int
result = result =
_xioopen_ipapp_prepare(opts, &opts0, hostname, portname, &pf, ipproto, _xioopen_ipapp_prepare(opts, &opts0, hostname, portname, &pf, ipproto,
xfd->para.socket.ip.ai_flags, sfd->para.socket.ip.ai_flags,
&themlist, us, &uslen, &themlist, us, &uslen,
&needbind, &lowport, socktype); &needbind, &lowport, socktype);
if (result != STAT_OK) return STAT_NORETRY; if (result != STAT_OK) return STAT_NORETRY;
@ -362,7 +355,7 @@ static int
while (themp != NULL) { while (themp != NULL) {
#if WITH_RETRY #if WITH_RETRY
if (xfd->forever || xfd->retry || ai_sorted[i] != NULL) { if (sfd->forever || sfd->retry || ai_sorted[i] != NULL) {
level = E_INFO; level = E_INFO;
} else } else
#endif /* WITH_RETRY */ #endif /* WITH_RETRY */
@ -370,7 +363,7 @@ static int
/* This cannot fork because we retrieved fork option above */ /* This cannot fork because we retrieved fork option above */
result = result =
_xioopen_connect(xfd, _xioopen_connect(sfd,
needbind?us:NULL, uslen, needbind?us:NULL, uslen,
themp->ai_addr, themp->ai_addrlen, themp->ai_addr, themp->ai_addrlen,
opts, pf?pf:themp->ai_addr->sa_family, socktype, ipproto, lowport, level); opts, pf?pf:themp->ai_addr->sa_family, socktype, ipproto, lowport, level);
@ -386,12 +379,12 @@ static int
#if WITH_RETRY #if WITH_RETRY
case STAT_RETRYLATER: case STAT_RETRYLATER:
case STAT_RETRYNOW: case STAT_RETRYNOW:
if (xfd->forever || xfd->retry) { if (sfd->forever || sfd->retry) {
dropopts(opts, PH_ALL); opts = copyopts(opts0, GROUP_ALL); dropopts(opts, PH_ALL); opts = copyopts(opts0, GROUP_ALL);
if (result == STAT_RETRYLATER) { if (result == STAT_RETRYLATER) {
Nanosleep(&xfd->intervall, NULL); Nanosleep(&sfd->intervall, NULL);
} }
--xfd->retry; --sfd->retry;
continue; continue;
} }
free(ai_sorted); free(ai_sorted);
@ -402,25 +395,25 @@ static int
return result; return result;
} }
/*! isn't this too early? */ /*! isn't this too early? */
if ((result = _xio_openlate(xfd, opts)) < 0) { if ((result = _xio_openlate(sfd, opts)) < 0) {
free(ai_sorted); free(ai_sorted);
return result; return result;
} }
result = _xioopen_openssl_connect(xfd, opt_ver, opt_commonname, result = _xioopen_openssl_connect(sfd, opt_ver, opt_commonname,
opt_no_sni, opt_snihost, ctx, level); opt_no_sni, opt_snihost, ctx, level);
switch (result) { switch (result) {
case STAT_OK: break; case STAT_OK: break;
#if WITH_RETRY #if WITH_RETRY
case STAT_RETRYLATER: case STAT_RETRYLATER:
case STAT_RETRYNOW: case STAT_RETRYNOW:
if (xfd->forever || xfd->retry) { if (sfd->forever || sfd->retry) {
Close(xfd->fd); Close(sfd->fd);
dropopts(opts, PH_ALL); opts = copyopts(opts0, GROUP_ALL); dropopts(opts, PH_ALL); opts = copyopts(opts0, GROUP_ALL);
if (result == STAT_RETRYLATER) { if (result == STAT_RETRYLATER) {
Nanosleep(&xfd->intervall, NULL); Nanosleep(&sfd->intervall, NULL);
} }
--xfd->retry; --sfd->retry;
continue; continue;
} }
#endif /* WITH_RETRY */ #endif /* WITH_RETRY */
@ -437,28 +430,28 @@ static int
if (dofork) { if (dofork) {
pid_t pid; pid_t pid;
int level = E_ERROR; int level = E_ERROR;
if (xfd->forever || xfd->retry) { if (sfd->forever || sfd->retry) {
level = E_WARN; level = E_WARN;
} }
while ((pid = xio_fork(false, level, xfd->shutup)) < 0) { while ((pid = xio_fork(false, level, sfd->shutup)) < 0) {
if (xfd->forever || --xfd->retry) { if (sfd->forever || --sfd->retry) {
Nanosleep(&xfd->intervall, NULL); continue; Nanosleep(&sfd->intervall, NULL); continue;
} }
xiofreeaddrinfo(themlist); xiofreeaddrinfo(themlist);
return STAT_RETRYLATER; return STAT_RETRYLATER;
} }
if (pid == 0) { /* child process */ if (pid == 0) { /* child process */
xfd->forever = false; xfd->retry = 0; sfd->forever = false; sfd->retry = 0;
break; break;
} }
/* parent process */ /* parent process */
Close(xfd->fd); Close(sfd->fd);
sycSSL_free(xfd->para.openssl.ssl); sycSSL_free(sfd->para.openssl.ssl);
xfd->para.openssl.ssl = NULL; sfd->para.openssl.ssl = NULL;
/* with and without retry */ /* with and without retry */
Nanosleep(&xfd->intervall, NULL); Nanosleep(&sfd->intervall, NULL);
dropopts(opts, PH_ALL); opts = copyopts(opts0, GROUP_ALL); dropopts(opts, PH_ALL); opts = copyopts(opts0, GROUP_ALL);
continue; /* with next socket() bind() connect() */ continue; /* with next socket() bind() connect() */
} }
@ -468,7 +461,7 @@ static int
free(ai_sorted); free(ai_sorted);
xiofreeaddrinfo(themlist); xiofreeaddrinfo(themlist);
openssl_conn_loginfo(xfd->para.openssl.ssl); openssl_conn_loginfo(sfd->para.openssl.ssl);
free((void *)opt_commonname); free((void *)opt_commonname);
free((void *)opt_snihost); free((void *)opt_snihost);
@ -479,10 +472,10 @@ static int
/* this function is typically called within the OpenSSL client fork/retry loop. /* this function is typically called within the OpenSSL client fork/retry loop.
xfd must be of type DATA_OPENSSL, and its fd must be set with a valid file sfd must be of type DATA_OPENSSL, and its fd must be set with a valid file
descriptor. this function then performs all SSL related step to make a valid descriptor. this function then performs all SSL related step to make a valid
SSL connection from an FD and a CTX. */ SSL connection from an FD and a CTX. */
int _xioopen_openssl_connect(struct single *xfd, int _xioopen_openssl_connect(struct single *sfd,
bool opt_ver, bool opt_ver,
const char *opt_commonname, const char *opt_commonname,
bool no_sni, bool no_sni,
@ -502,12 +495,12 @@ int _xioopen_openssl_connect(struct single *xfd,
/*Error("SSL_new()");*/ /*Error("SSL_new()");*/
return STAT_RETRYLATER; return STAT_RETRYLATER;
} }
xfd->para.openssl.ssl = ssl; sfd->para.openssl.ssl = ssl;
result = xioSSL_set_fd(xfd, level); result = xioSSL_set_fd(sfd, level);
if (result != STAT_OK) { if (result != STAT_OK) {
sycSSL_free(xfd->para.openssl.ssl); sycSSL_free(sfd->para.openssl.ssl);
xfd->para.openssl.ssl = NULL; sfd->para.openssl.ssl = NULL;
return result; return result;
} }
@ -517,25 +510,25 @@ int _xioopen_openssl_connect(struct single *xfd,
Warn("refusing to set empty SNI host name"); Warn("refusing to set empty SNI host name");
} else if (!SSL_set_tlsext_host_name(ssl, snihost)) { } else if (!SSL_set_tlsext_host_name(ssl, snihost)) {
Error1("Failed to set SNI host \"%s\"", snihost); Error1("Failed to set SNI host \"%s\"", snihost);
sycSSL_free(xfd->para.openssl.ssl); sycSSL_free(sfd->para.openssl.ssl);
xfd->para.openssl.ssl = NULL; sfd->para.openssl.ssl = NULL;
return STAT_NORETRY; return STAT_NORETRY;
} }
} }
#endif #endif
result = xioSSL_connect(xfd, opt_commonname, opt_ver, level); result = xioSSL_connect(sfd, opt_commonname, opt_ver, level);
if (result != STAT_OK) { if (result != STAT_OK) {
sycSSL_free(xfd->para.openssl.ssl); sycSSL_free(sfd->para.openssl.ssl);
xfd->para.openssl.ssl = NULL; sfd->para.openssl.ssl = NULL;
return result; return result;
} }
result = openssl_handle_peer_certificate(xfd, opt_commonname, result = openssl_handle_peer_certificate(sfd, opt_commonname,
opt_ver, level); opt_ver, level);
if (result != STAT_OK) { if (result != STAT_OK) {
sycSSL_free(xfd->para.openssl.ssl); sycSSL_free(sfd->para.openssl.ssl);
xfd->para.openssl.ssl = NULL; sfd->para.openssl.ssl = NULL;
return result; return result;
} }
@ -545,25 +538,19 @@ int _xioopen_openssl_connect(struct single *xfd,
#if WITH_LISTEN #if WITH_LISTEN
static int static int xioopen_openssl_listen(
xioopen_openssl_listen(int argc, int argc,
const char *argv[], /* the arguments in the address string */ const char *argv[], /* the arguments in the address string */
struct opt *opts, struct opt *opts,
int xioflags, /* is the open meant for reading (0), int xioflags, /* is the open meant for reading (0),
writing (1), or both (2) ? */ writing (1), or both (2) ? */
xiofile_t *xxfd, /* a xio file descriptor structure, xiofile_t *xxfd, /* a xio file descriptor structure,
already allocated */ already allocated */
groups_t groups, /* the matching address groups... */ const struct addrdesc *addrdesc) /* the above descriptor */
int protogrp, /* first transparent integer value from
addr_openssl */
int dummy2, /* second transparent integer value from
addr_openssl */
int dummy3) /* transparent pointer value from
addr_openssl */
{ {
struct single *xfd = &xxfd->stream; struct single *sfd = &xxfd->stream;
struct single *sfd = xfd;
const char *portname; const char *portname;
int protogrp = addrdesc->arg1;
struct opt *opts0 = NULL; struct opt *opts0 = NULL;
union sockaddr_union us_sa, *us = &us_sa; union sockaddr_union us_sa, *us = &us_sa;
socklen_t uslen = sizeof(us_sa); socklen_t uslen = sizeof(us_sa);
@ -583,13 +570,14 @@ static int
Error("address with data processing not allowed here"); Error("address with data processing not allowed here");
return STAT_NORETRY; return STAT_NORETRY;
} }
xfd->flags |= XIO_DOESCONVERT; sfd->flags |= XIO_DOESCONVERT;
if (argc != 2) { if (argc != 2) {
Error1("%s: 1 parameter required", argv[0]); xio_syntax(argv[0], 1, argc-1, addrdesc->syntax);
return STAT_NORETRY; return STAT_NORETRY;
} }
xioinit_ip(&pf, xioparms.default_ip);
#if WITH_IP4 && WITH_IP6 #if WITH_IP4 && WITH_IP6
switch (xioparms.default_ip) { switch (xioparms.default_ip) {
case '4': pf = PF_INET; break; case '4': pf = PF_INET; break;
@ -604,8 +592,8 @@ static int
portname = argv[1]; portname = argv[1];
xfd->howtoend = END_SHUTDOWN; sfd->howtoend = END_SHUTDOWN;
if (applyopts_single(xfd, opts, PH_INIT) < 0) return -1; if (applyopts_single(sfd, opts, PH_INIT) < 0) return -1;
applyopts(sfd, -1, opts, PH_INIT); applyopts(sfd, -1, opts, PH_INIT);
retropt_string(opts, OPT_OPENSSL_CERTIFICATE, &opt_cert); retropt_string(opts, OPT_OPENSSL_CERTIFICATE, &opt_cert);
@ -618,7 +606,7 @@ static int
applyopts(sfd, -1, opts, PH_EARLY); applyopts(sfd, -1, opts, PH_EARLY);
result = result =
_xioopen_openssl_prepare(opts, xfd, true, &opt_ver, opt_cert, &ctx, &use_dtls); _xioopen_openssl_prepare(opts, sfd, true, &opt_ver, opt_cert, &ctx, &use_dtls);
if (result != STAT_OK) return STAT_NORETRY; if (result != STAT_OK) return STAT_NORETRY;
if (use_dtls) { if (use_dtls) {
@ -629,7 +617,7 @@ static int
retropt_int(opts, OPT_SO_PROTOTYPE, &ipproto); retropt_int(opts, OPT_SO_PROTOTYPE, &ipproto);
if (_xioopen_ipapp_listen_prepare(opts, &opts0, portname, &pf, ipproto, if (_xioopen_ipapp_listen_prepare(opts, &opts0, portname, &pf, ipproto,
xfd->para.socket.ip.ai_flags, sfd->para.socket.ip.ai_flags,
us, &uslen, socktype) us, &uslen, socktype)
!= STAT_OK) { != STAT_OK) {
return STAT_NORETRY; return STAT_NORETRY;
@ -637,12 +625,12 @@ static int
if (pf == 0) if (pf == 0)
pf = us->soa.sa_family; pf = us->soa.sa_family;
xfd->dtype = XIODATA_OPENSSL; sfd->dtype = XIODATA_OPENSSL;
while (true) { /* loop over failed attempts */ while (true) { /* loop over failed attempts */
#if WITH_RETRY #if WITH_RETRY
if (xfd->forever || xfd->retry) { if (sfd->forever || sfd->retry) {
level = E_INFO; level = E_INFO;
} else } else
#endif /* WITH_RETRY */ #endif /* WITH_RETRY */
@ -651,18 +639,18 @@ static int
/* this can fork() for us; it only returns on error or on /* this can fork() for us; it only returns on error or on
successful establishment of connection */ successful establishment of connection */
if (ipproto == IPPROTO_TCP) { if (ipproto == IPPROTO_TCP) {
result = _xioopen_listen(xfd, xioflags, result = _xioopen_listen(sfd, xioflags,
(struct sockaddr *)us, uslen, (struct sockaddr *)us, uslen,
opts, pf, socktype, ipproto, opts, pf, socktype, ipproto,
#if WITH_RETRY #if WITH_RETRY
(xfd->retry||xfd->forever)?E_INFO:E_ERROR (sfd->retry||sfd->forever)?E_INFO:E_ERROR
#else #else
E_ERROR E_ERROR
#endif /* WITH_RETRY */ #endif /* WITH_RETRY */
); );
#if WITH_UDP #if WITH_UDP
} else { } else {
result = _xioopen_ipdgram_listen(xfd, xioflags, result = _xioopen_ipdgram_listen(sfd, xioflags,
us, uslen, opts, pf, socktype, ipproto); us, uslen, opts, pf, socktype, ipproto);
#endif /* WITH_UDP */ #endif /* WITH_UDP */
} }
@ -672,13 +660,13 @@ static int
#if WITH_RETRY #if WITH_RETRY
case STAT_RETRYLATER: case STAT_RETRYLATER:
case STAT_RETRYNOW: case STAT_RETRYNOW:
if (xfd->forever || xfd->retry) { if (sfd->forever || sfd->retry) {
dropopts(opts, PH_ALL); opts = copyopts(opts0, GROUP_ALL); dropopts(opts, PH_ALL); opts = copyopts(opts0, GROUP_ALL);
if (result == STAT_RETRYLATER) { if (result == STAT_RETRYLATER) {
Nanosleep(&xfd->intervall, NULL); Nanosleep(&sfd->intervall, NULL);
} }
dropopts(opts, PH_ALL); opts = copyopts(opts0, GROUP_ALL); dropopts(opts, PH_ALL); opts = copyopts(opts0, GROUP_ALL);
--xfd->retry; --sfd->retry;
continue; continue;
} }
return STAT_NORETRY; return STAT_NORETRY;
@ -687,19 +675,19 @@ static int
return result; return result;
} }
result = _xioopen_openssl_listen(xfd, opt_ver, opt_commonname, ctx, level); result = _xioopen_openssl_listen(sfd, opt_ver, opt_commonname, ctx, level);
switch (result) { switch (result) {
case STAT_OK: break; case STAT_OK: break;
#if WITH_RETRY #if WITH_RETRY
case STAT_RETRYLATER: case STAT_RETRYLATER:
case STAT_RETRYNOW: case STAT_RETRYNOW:
if (xfd->forever || xfd->retry) { if (sfd->forever || sfd->retry) {
dropopts(opts, PH_ALL); opts = copyopts(opts0, GROUP_ALL); dropopts(opts, PH_ALL); opts = copyopts(opts0, GROUP_ALL);
if (result == STAT_RETRYLATER) { if (result == STAT_RETRYLATER) {
Nanosleep(&xfd->intervall, NULL); Nanosleep(&sfd->intervall, NULL);
} }
dropopts(opts, PH_ALL); opts = copyopts(opts0, GROUP_ALL); dropopts(opts, PH_ALL); opts = copyopts(opts0, GROUP_ALL);
--xfd->retry; --sfd->retry;
continue; continue;
} }
return STAT_NORETRY; return STAT_NORETRY;
@ -708,7 +696,7 @@ static int
return result; return result;
} }
openssl_conn_loginfo(xfd->para.openssl.ssl); openssl_conn_loginfo(sfd->para.openssl.ssl);
break; break;
} /* drop out on success */ } /* drop out on success */
@ -719,7 +707,7 @@ static int
} }
int _xioopen_openssl_listen(struct single *xfd, int _xioopen_openssl_listen(struct single *sfd,
bool opt_ver, bool opt_ver,
const char *opt_commonname, const char *opt_commonname,
SSL_CTX *ctx, SSL_CTX *ctx,
@ -729,7 +717,7 @@ int _xioopen_openssl_listen(struct single *xfd,
int errint, ret; int errint, ret;
/* create an SSL object */ /* create an SSL object */
if ((xfd->para.openssl.ssl = sycSSL_new(ctx)) == NULL) { if ((sfd->para.openssl.ssl = sycSSL_new(ctx)) == NULL) {
if (ERR_peek_error() == 0) Msg(level, "SSL_new() failed"); if (ERR_peek_error() == 0) Msg(level, "SSL_new() failed");
while (err = ERR_get_error()) { while (err = ERR_get_error()) {
Msg1(level, "SSL_new(): %s", ERR_error_string(err, NULL)); Msg1(level, "SSL_new(): %s", ERR_error_string(err, NULL));
@ -739,11 +727,11 @@ int _xioopen_openssl_listen(struct single *xfd,
} }
/* assign the network connection to the SSL object */ /* assign the network connection to the SSL object */
if (sycSSL_set_fd(xfd->para.openssl.ssl, xfd->fd) <= 0) { if (sycSSL_set_fd(sfd->para.openssl.ssl, sfd->fd) <= 0) {
if (ERR_peek_error() == 0) Msg(level, "SSL_set_fd() failed"); if (ERR_peek_error() == 0) Msg(level, "SSL_set_fd() failed");
while (err = ERR_get_error()) { while (err = ERR_get_error()) {
Msg2(level, "SSL_set_fd(, %d): %s", Msg2(level, "SSL_set_fd(, %d): %s",
xfd->fd, ERR_error_string(err, NULL)); sfd->fd, ERR_error_string(err, NULL));
} }
} }
@ -753,7 +741,7 @@ int _xioopen_openssl_listen(struct single *xfd,
const char *ciphers = NULL; const char *ciphers = NULL;
Debug("available ciphers:"); Debug("available ciphers:");
do { do {
ciphers = SSL_get_cipher_list(xfd->para.openssl.ssl, i); ciphers = SSL_get_cipher_list(sfd->para.openssl.ssl, i);
if (ciphers == NULL) break; if (ciphers == NULL) break;
Debug2("CIPHERS pri=%d: %s", i, ciphers); Debug2("CIPHERS pri=%d: %s", i, ciphers);
++i; ++i;
@ -762,9 +750,9 @@ int _xioopen_openssl_listen(struct single *xfd,
#endif /* WITH_DEBUG */ #endif /* WITH_DEBUG */
/* connect via SSL by performing handshake */ /* connect via SSL by performing handshake */
if ((ret = sycSSL_accept(xfd->para.openssl.ssl)) <= 0) { if ((ret = sycSSL_accept(sfd->para.openssl.ssl)) <= 0) {
/*if (ERR_peek_error() == 0) Msg(level, "SSL_accept() failed");*/ /*if (ERR_peek_error() == 0) Msg(level, "SSL_accept() failed");*/
errint = SSL_get_error(xfd->para.openssl.ssl, ret); errint = SSL_get_error(sfd->para.openssl.ssl, ret);
switch (errint) { switch (errint) {
case SSL_ERROR_NONE: case SSL_ERROR_NONE:
Msg(level, "ok"); break; Msg(level, "ok"); break;
@ -803,7 +791,7 @@ int _xioopen_openssl_listen(struct single *xfd,
return STAT_RETRYLATER; return STAT_RETRYLATER;
} }
if (openssl_handle_peer_certificate(xfd, opt_commonname, opt_ver, E_ERROR/*!*/) < 0) { if (openssl_handle_peer_certificate(sfd, opt_commonname, opt_ver, E_ERROR/*!*/) < 0) {
return STAT_NORETRY; return STAT_NORETRY;
} }
@ -978,7 +966,7 @@ static int _xio_openssl_parse_version(const char *verstring, int vergroups) {
int int
_xioopen_openssl_prepare(struct opt *opts, _xioopen_openssl_prepare(struct opt *opts,
struct single *xfd,/* a xio file descriptor struct single *sfd,/* a xio file descriptor
structure, already allocated structure, already allocated
*/ */
bool server, /* SSL client: false */ bool server, /* SSL client: false */
@ -1004,7 +992,7 @@ int
unsigned long err; unsigned long err;
int result; int result;
xfd->dtype = XIODATA_OPENSSL; sfd->dtype = XIODATA_OPENSSL;
retropt_bool(opts, OPT_OPENSSL_FIPS, &opt_fips); retropt_bool(opts, OPT_OPENSSL_FIPS, &opt_fips);
retropt_string(opts, OPT_OPENSSL_METHOD, &me_str); retropt_string(opts, OPT_OPENSSL_METHOD, &me_str);
@ -1237,35 +1225,35 @@ int
/*ERR_clear_error;*/ /*ERR_clear_error;*/
return STAT_RETRYLATER; return STAT_RETRYLATER;
} }
xfd->para.openssl.ctx = ctx; sfd->para.openssl.ctx = ctx;
*ctxp = ctx; *ctxp = ctx;
#if HAVE_SSL_CTX_set_min_proto_version || defined(SSL_CTX_set_min_proto_version) #if HAVE_SSL_CTX_set_min_proto_version || defined(SSL_CTX_set_min_proto_version)
if (xfd->para.openssl.min_proto_version != NULL) { if (sfd->para.openssl.min_proto_version != NULL) {
int sslver, rc; int sslver, rc;
sslver = _xio_openssl_parse_version(xfd->para.openssl.min_proto_version, sslver = _xio_openssl_parse_version(sfd->para.openssl.min_proto_version,
XIO_OPENSSL_VERSIONGROUP_TLS|XIO_OPENSSL_VERSIONGROUP_DTLS); XIO_OPENSSL_VERSIONGROUP_TLS|XIO_OPENSSL_VERSIONGROUP_DTLS);
if (sslver < 0) if (sslver < 0)
return STAT_NORETRY; return STAT_NORETRY;
if ((rc = SSL_CTX_set_min_proto_version(ctx, sslver)) <= 0) { if ((rc = SSL_CTX_set_min_proto_version(ctx, sslver)) <= 0) {
Debug1("version: %ld", SSL_CTX_get_min_proto_version(ctx)); Debug1("version: %ld", SSL_CTX_get_min_proto_version(ctx));
Error3("_xioopen_openssl_prepare(): SSL_CTX_set_min_proto_version(\"%s\"->%d): failed (%d)", Error3("_xioopen_openssl_prepare(): SSL_CTX_set_min_proto_version(\"%s\"->%d): failed (%d)",
xfd->para.openssl.min_proto_version, sslver, rc); sfd->para.openssl.min_proto_version, sslver, rc);
return STAT_NORETRY; return STAT_NORETRY;
} }
Debug1("version: %ld", SSL_CTX_get_min_proto_version(ctx)); Debug1("version: %ld", SSL_CTX_get_min_proto_version(ctx));
} }
#endif /* HAVE_SSL_set_min_proto_version || defined(SSL_set_min_proto_version) */ #endif /* HAVE_SSL_set_min_proto_version || defined(SSL_set_min_proto_version) */
#if HAVE_SSL_CTX_set_max_proto_version || defined(SSL_CTX_set_max_proto_version) #if HAVE_SSL_CTX_set_max_proto_version || defined(SSL_CTX_set_max_proto_version)
if (xfd->para.openssl.max_proto_version != NULL) { if (sfd->para.openssl.max_proto_version != NULL) {
int sslver; int sslver;
sslver = _xio_openssl_parse_version(xfd->para.openssl.max_proto_version, sslver = _xio_openssl_parse_version(sfd->para.openssl.max_proto_version,
XIO_OPENSSL_VERSIONGROUP_TLS|XIO_OPENSSL_VERSIONGROUP_DTLS); XIO_OPENSSL_VERSIONGROUP_TLS|XIO_OPENSSL_VERSIONGROUP_DTLS);
if (sslver < 0) if (sslver < 0)
return STAT_NORETRY; return STAT_NORETRY;
if (SSL_CTX_set_max_proto_version(ctx, sslver) <= 0) { if (SSL_CTX_set_max_proto_version(ctx, sslver) <= 0) {
Error2("_xioopen_openssl_prepare(): SSL_CTX_set_max_proto_version(\"%s\"->%d): failed", Error2("_xioopen_openssl_prepare(): SSL_CTX_set_max_proto_version(\"%s\"->%d): failed",
xfd->para.openssl.max_proto_version, sslver); sfd->para.openssl.max_proto_version, sslver);
return STAT_NORETRY; return STAT_NORETRY;
} }
} }
@ -1793,7 +1781,7 @@ static bool openssl_check_peername(X509_NAME *name, const char *peername) {
/* peername is, with OpenSSL client, the server name, or the value of option /* peername is, with OpenSSL client, the server name, or the value of option
commonname if provided; commonname if provided;
With OpenSSL server, it is the value of option commonname */ With OpenSSL server, it is the value of option commonname */
static int openssl_handle_peer_certificate(struct single *xfd, static int openssl_handle_peer_certificate(struct single *sfd,
const char *peername, const char *peername,
bool opt_ver, int level) { bool opt_ver, int level) {
X509 *peer_cert; X509 *peer_cert;
@ -1802,7 +1790,7 @@ static int openssl_handle_peer_certificate(struct single *xfd,
int extcount, i, ok = 0; int extcount, i, ok = 0;
int status; int status;
if ((peer_cert = SSL_get_peer_certificate(xfd->para.openssl.ssl)) == NULL) { if ((peer_cert = SSL_get_peer_certificate(sfd->para.openssl.ssl)) == NULL) {
if (opt_ver) { if (opt_ver) {
Msg(level, "no peer certificate"); Msg(level, "no peer certificate");
status = STAT_RETRYLATER; status = STAT_RETRYLATER;
@ -1816,7 +1804,7 @@ static int openssl_handle_peer_certificate(struct single *xfd,
/* verify peer certificate (trust, signature, validity dates) */ /* verify peer certificate (trust, signature, validity dates) */
if (opt_ver) { if (opt_ver) {
long verify_result; long verify_result;
if ((verify_result = sycSSL_get_verify_result(xfd->para.openssl.ssl)) != X509_V_OK) { if ((verify_result = sycSSL_get_verify_result(sfd->para.openssl.ssl)) != X509_V_OK) {
const char *message = NULL; const char *message = NULL;
if (verify_result >= 0 && if (verify_result >= 0 &&
(size_t)verify_result < (size_t)verify_result <
@ -1912,7 +1900,7 @@ static int openssl_handle_peer_certificate(struct single *xfd,
case 16: /* IPv6 */ case 16: /* IPv6 */
inet_ntop(AF_INET6, data, aBuffer, sizeof(aBuffer)); inet_ntop(AF_INET6, data, aBuffer, sizeof(aBuffer));
if (peername != NULL) { if (peername != NULL) {
xioip6_pton(peername, &ip6bin, xfd->para.socket.ip.ai_flags); xioip6_pton(peername, &ip6bin, sfd->para.socket.ip.ai_flags);
if (memcmp(data, &ip6bin, sizeof(ip6bin)) == 0) { if (memcmp(data, &ip6bin, sizeof(ip6bin)) == 0) {
Debug2("subjectAltName \"%s\" matches peername \"%s\"", Debug2("subjectAltName \"%s\" matches peername \"%s\"",
aBuffer, peername); aBuffer, peername);
@ -1964,15 +1952,15 @@ static int openssl_handle_peer_certificate(struct single *xfd,
return status; return status;
} }
static int xioSSL_set_fd(struct single *xfd, int level) { static int xioSSL_set_fd(struct single *sfd, int level) {
unsigned long err; unsigned long err;
/* assign a network connection to the SSL object */ /* assign a network connection to the SSL object */
if (sycSSL_set_fd(xfd->para.openssl.ssl, xfd->fd) <= 0) { if (sycSSL_set_fd(sfd->para.openssl.ssl, sfd->fd) <= 0) {
Msg(level, "SSL_set_fd() failed"); Msg(level, "SSL_set_fd() failed");
while (err = ERR_get_error()) { while (err = ERR_get_error()) {
Msg2(level, "SSL_set_fd(, %d): %s", Msg2(level, "SSL_set_fd(, %d): %s",
xfd->fd, ERR_error_string(err, NULL)); sfd->fd, ERR_error_string(err, NULL));
} }
return STAT_RETRYLATER; return STAT_RETRYLATER;
} }
@ -1984,16 +1972,16 @@ static int xioSSL_set_fd(struct single *xfd, int level) {
in case of an error condition, this function check forever and retry in case of an error condition, this function check forever and retry
options and ev. sleeps an interval. It returns NORETRY when the caller options and ev. sleeps an interval. It returns NORETRY when the caller
should not retry for any reason. */ should not retry for any reason. */
static int xioSSL_connect(struct single *xfd, const char *opt_commonname, static int xioSSL_connect(struct single *sfd, const char *opt_commonname,
bool opt_ver, int level) { bool opt_ver, int level) {
char error_string[120]; char error_string[120];
int errint, status, ret; int errint, status, ret;
unsigned long err; unsigned long err;
/* connect via SSL by performing handshake */ /* connect via SSL by performing handshake */
if ((ret = sycSSL_connect(xfd->para.openssl.ssl)) <= 0) { if ((ret = sycSSL_connect(sfd->para.openssl.ssl)) <= 0) {
/*if (ERR_peek_error() == 0) Msg(level, "SSL_connect() failed");*/ /*if (ERR_peek_error() == 0) Msg(level, "SSL_connect() failed");*/
errint = SSL_get_error(xfd->para.openssl.ssl, ret); errint = SSL_get_error(sfd->para.openssl.ssl, ret);
switch (errint) { switch (errint) {
case SSL_ERROR_NONE: case SSL_ERROR_NONE:
/* this is not an error, but I dare not continue for security reasons*/ /* this is not an error, but I dare not continue for security reasons*/
@ -2030,7 +2018,7 @@ static int xioSSL_connect(struct single *xfd, const char *opt_commonname,
break; break;
case SSL_ERROR_SSL: case SSL_ERROR_SSL:
status = openssl_SSL_ERROR_SSL(level, "SSL_connect"); status = openssl_SSL_ERROR_SSL(level, "SSL_connect");
if (openssl_handle_peer_certificate(xfd, opt_commonname, opt_ver, level/*!*/) < 0) { if (openssl_handle_peer_certificate(sfd, opt_commonname, opt_ver, level/*!*/) < 0) {
return STAT_RETRYLATER; return STAT_RETRYLATER;
} }
break; break;

View file

@ -14,7 +14,7 @@
#if WITH_PIPE #if WITH_PIPE
static int xioopen_fifo(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *fd, groups_t groups, int dummy1, int dummy2, int dummy3); static int xioopen_fifo(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *fd, const struct addrdesc *addrdesc);
static int xioopen_fifo_unnamed(xiofile_t *sock, struct opt *opts); static int xioopen_fifo_unnamed(xiofile_t *sock, struct opt *opts);
@ -77,7 +77,14 @@ static int xioopen_fifo_unnamed(xiofile_t *sock, struct opt *opts) {
/* open a named or unnamed pipe/fifo */ /* open a named or unnamed pipe/fifo */
static int xioopen_fifo(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *xfd, groups_t groups, int dummy1, int dummy2, int dummy3) { static int xioopen_fifo(
int argc,
const char *argv[],
struct opt *opts,
int xioflags,
xiofile_t *xfd,
const struct addrdesc *addrdesc)
{
struct single *sfd = &xfd->stream; struct single *sfd = &xfd->stream;
const char *pipename = argv[1]; const char *pipename = argv[1];
int rw = (xioflags & XIO_ACCMODE); int rw = (xioflags & XIO_ACCMODE);
@ -96,7 +103,8 @@ static int xioopen_fifo(int argc, const char *argv[], struct opt *opts, int xiof
} }
if (argc != 2) { if (argc != 2) {
Error2("%s: wrong number of parameters (%d instead of 1)", argv[0], argc-1); xio_syntax(argv[0], 1, argc-1,addrdesc->syntax);
return STAT_NORETRY;
} }
if (applyopts_single(sfd, opts, PH_INIT) < 0) if (applyopts_single(sfd, opts, PH_INIT) < 0)

View file

@ -19,7 +19,7 @@ static int _posixmq_unlink(
const char *name, const char *name,
int level); /* message level on error */ int level); /* message level on error */
static int xioopen_posixmq(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *xfd, groups_t groups, int dirs, int dummy, int dummy3); static int xioopen_posixmq(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *xfd, const struct addrdesc *addrdesc);
const struct addrdesc xioaddr_posixmq_bidir = { "POSIXMQ-BIDIRECTIONAL", 1+XIO_RDWR, xioopen_posixmq, GROUP_FD|GROUP_NAMED|GROUP_POSIXMQ|GROUP_RETRY, XIO_RDWR, 0, 0 HELP(":<mqname>") }; const struct addrdesc xioaddr_posixmq_bidir = { "POSIXMQ-BIDIRECTIONAL", 1+XIO_RDWR, xioopen_posixmq, GROUP_FD|GROUP_NAMED|GROUP_POSIXMQ|GROUP_RETRY, XIO_RDWR, 0, 0 HELP(":<mqname>") };
const struct addrdesc xioaddr_posixmq_read = { "POSIXMQ-READ", 1+XIO_RDONLY, xioopen_posixmq, GROUP_FD|GROUP_NAMED|GROUP_POSIXMQ|GROUP_RETRY, XIO_RDONLY, 0, 0 HELP(":<mqname>") }; const struct addrdesc xioaddr_posixmq_read = { "POSIXMQ-READ", 1+XIO_RDONLY, xioopen_posixmq, GROUP_FD|GROUP_NAMED|GROUP_POSIXMQ|GROUP_RETRY, XIO_RDONLY, 0, 0 HELP(":<mqname>") };
@ -37,14 +37,13 @@ static int xioopen_posixmq(
struct opt *opts, struct opt *opts,
int xioflags, int xioflags,
xiofile_t *xfd, xiofile_t *xfd,
groups_t groups, const struct addrdesc *addrdesc)
int dirs,
int oneshot,
int dummy3)
{ {
/* We expect the form: /mqname */ /* We expect the form: /mqname */
xiosingle_t *sfd = &xfd->stream; xiosingle_t *sfd = &xfd->stream;
const char *name; const char *name;
int dirs = addrdesc->arg1;
int oneshot = addrdesc->arg2;
bool opt_unlink_early = false; bool opt_unlink_early = false;
int oflag; int oflag;
bool opt_o_excl = false; bool opt_o_excl = false;
@ -61,8 +60,7 @@ static int xioopen_posixmq(
return STAT_NORETRY; return STAT_NORETRY;
} }
if (argc != 2) { if (argc != 2) {
Error2("%s: wrong number of parameters (%d instead of 1)", xio_syntax(argv[0], 1, argc-1, addrdesc->syntax);
argv[0], argc-1);
return STAT_NORETRY; return STAT_NORETRY;
} }

View file

@ -312,8 +312,8 @@ int _xioopen_foxec(int xioflags, /* XIO_RDONLY etc. */
if (rw != XIO_WRONLY) { if (rw != XIO_WRONLY) {
applyopts_cloexec(rdpip[0], popts); applyopts_cloexec(rdpip[0], popts);
applyopts(NULL, rdpip[0], popts, PH_FD); applyopts(sfd, rdpip[0], popts, PH_FD);
applyopts(NULL, rdpip[1], copts, PH_FD); applyopts(sfd, rdpip[1], copts, PH_FD);
} }
if (rw != XIO_RDONLY) { if (rw != XIO_RDONLY) {
@ -326,8 +326,8 @@ int _xioopen_foxec(int xioflags, /* XIO_RDONLY etc. */
/* wrpip[1]: write by socat; wrpip[0]: read by child */ /* wrpip[1]: write by socat; wrpip[0]: read by child */
if (rw != XIO_RDONLY) { if (rw != XIO_RDONLY) {
applyopts_cloexec(wrpip[1], popts); applyopts_cloexec(wrpip[1], popts);
applyopts(NULL, wrpip[1], popts, PH_FD); applyopts(sfd, wrpip[1], popts, PH_FD);
applyopts(NULL, wrpip[0], copts, PH_FD); applyopts(sfd, wrpip[0], copts, PH_FD);
} }
if (sfd->howtoend == END_UNSPEC) { if (sfd->howtoend == END_UNSPEC) {
sfd->howtoend = END_CLOSE_KILL; sfd->howtoend = END_CLOSE_KILL;
@ -362,19 +362,19 @@ int _xioopen_foxec(int xioflags, /* XIO_RDONLY etc. */
return -1; return -1;
} }
popts = opts; popts = opts;
applyopts(NULL, sv[0], copts, PH_PASTSOCKET); applyopts(sfd, sv[0], copts, PH_PASTSOCKET);
applyopts(NULL, sv[1], popts, PH_PASTSOCKET); applyopts(sfd, sv[1], popts, PH_PASTSOCKET);
applyopts_cloexec(sv[0], copts); applyopts_cloexec(sv[0], copts);
applyopts(NULL, sv[0], copts, PH_FD); applyopts(sfd, sv[0], copts, PH_FD);
applyopts(NULL, sv[1], popts, PH_FD); applyopts(sfd, sv[1], popts, PH_FD);
applyopts(NULL, sv[0], copts, PH_PREBIND); applyopts(sfd, sv[0], copts, PH_PREBIND);
applyopts(NULL, sv[0], copts, PH_BIND); applyopts(sfd, sv[0], copts, PH_BIND);
applyopts(NULL, sv[0], copts, PH_PASTBIND); applyopts(sfd, sv[0], copts, PH_PASTBIND);
applyopts(NULL, sv[1], popts, PH_PREBIND); applyopts(sfd, sv[1], popts, PH_PREBIND);
applyopts(NULL, sv[1], popts, PH_BIND); applyopts(sfd, sv[1], popts, PH_BIND);
applyopts(NULL, sv[1], popts, PH_PASTBIND); applyopts(sfd, sv[1], popts, PH_PASTBIND);
if (sfd->howtoend == END_UNSPEC) { if (sfd->howtoend == END_UNSPEC) {
sfd->howtoend = END_SHUTDOWN_KILL; sfd->howtoend = END_SHUTDOWN_KILL;
@ -437,7 +437,7 @@ int _xioopen_foxec(int xioflags, /* XIO_RDONLY etc. */
#endif #endif
/* this for child, was after fork */ /* this for child, was after fork */
applyopts(NULL, ttyfd, copts, PH_FD); applyopts(sfd, ttyfd, copts, PH_FD);
Info1("opened pseudo terminal %s", tn); Info1("opened pseudo terminal %s", tn);
Close(ptyfd); Close(ptyfd);
@ -464,8 +464,8 @@ int _xioopen_foxec(int xioflags, /* XIO_RDONLY etc. */
applyopts_cloexec(ttyfd, copts); applyopts_cloexec(ttyfd, copts);
} }
applyopts(NULL, ttyfd, copts, PH_LATE); applyopts(sfd, ttyfd, copts, PH_LATE);
applyopts(NULL, ttyfd, copts, PH_LATE2); applyopts(sfd, ttyfd, copts, PH_LATE2);
} else } else
#endif /* HAVE_PTY */ #endif /* HAVE_PTY */
if (usepipes) { if (usepipes) {
@ -515,10 +515,10 @@ int _xioopen_foxec(int xioflags, /* XIO_RDONLY etc. */
/* applyopts_cloexec(fdi, *copts);*/ /* option is already consumed! */ /* applyopts_cloexec(fdi, *copts);*/ /* option is already consumed! */
} }
applyopts(NULL, fdi, copts, PH_LATE); applyopts(sfd, fdi, copts, PH_LATE);
applyopts(NULL, fdo, copts, PH_LATE); applyopts(sfd, fdo, copts, PH_LATE);
applyopts(NULL, fdi, copts, PH_LATE2); applyopts(sfd, fdi, copts, PH_LATE2);
applyopts(NULL, fdo, copts, PH_LATE2); applyopts(sfd, fdo, copts, PH_LATE2);
} else { /* socketpair */ } else { /* socketpair */
Close(sv[0]); Close(sv[0]);
@ -545,8 +545,8 @@ int _xioopen_foxec(int xioflags, /* XIO_RDONLY etc. */
Close(sv[1]); Close(sv[1]);
} }
applyopts(NULL, fdi, copts, PH_LATE); applyopts(sfd, fdi, copts, PH_LATE);
applyopts(NULL, fdi, copts, PH_LATE2); applyopts(sfd, fdi, copts, PH_LATE2);
} }
if (withfork) { if (withfork) {
Info("notifying parent that child process is ready"); Info("notifying parent that child process is ready");
@ -554,8 +554,8 @@ int _xioopen_foxec(int xioflags, /* XIO_RDONLY etc. */
} }
} /* withfork */ } /* withfork */
else { else {
applyopts(NULL, -1, copts, PH_LATE); applyopts(sfd, -1, copts, PH_LATE);
applyopts(NULL, -1, copts, PH_LATE2); applyopts(sfd, -1, copts, PH_LATE2);
} }
_xioopen_setdelayeduser(); _xioopen_setdelayeduser();
if (withstderr) { if (withstderr) {

View file

@ -20,10 +20,7 @@
#define PROXYPORT "8080" #define PROXYPORT "8080"
static int xioopen_proxy_connect(int argc, const char *argv[], struct opt *opts, static int xioopen_proxy_connect(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *fd, const struct addrdesc *addrdesc);
int xioflags, xiofile_t *fd,
groups_t groups, int dummy1, int dummy2,
int dummy3);
const struct optdesc opt_proxyport = { "proxyport", NULL, OPT_PROXYPORT, GROUP_HTTP, PH_LATE, TYPE_STRING, OFUNC_SPEC }; const struct optdesc opt_proxyport = { "proxyport", NULL, OPT_PROXYPORT, GROUP_HTTP, PH_LATE, TYPE_STRING, OFUNC_SPEC };
const struct optdesc opt_ignorecr = { "ignorecr", NULL, OPT_IGNORECR, GROUP_HTTP, PH_LATE, TYPE_BOOL, OFUNC_SPEC }; const struct optdesc opt_ignorecr = { "ignorecr", NULL, OPT_IGNORECR, GROUP_HTTP, PH_LATE, TYPE_BOOL, OFUNC_SPEC };
@ -57,15 +54,15 @@ enum {
returns <0 when error occurs returns <0 when error occurs
*/ */
static ssize_t static ssize_t
xioproxy_recvbytes(struct single *xfd, char *buff, size_t buflen, int level) { xioproxy_recvbytes(struct single *sfd, char *buff, size_t buflen, int level) {
ssize_t result; ssize_t result;
do { do {
/* we need at least buflen bytes... */ /* we need at least buflen bytes... */
result = Read(xfd->fd, buff, buflen); result = Read(sfd->fd, buff, buflen);
} while (result < 0 && errno == EINTR); /*! EAGAIN? */ } while (result < 0 && errno == EINTR); /*! EAGAIN? */
if (result < 0) { if (result < 0) {
Msg4(level, "read(%d, %p, "F_Zu"): %s", Msg4(level, "read(%d, %p, "F_Zu"): %s",
xfd->fd, buff, buflen, strerror(errno)); sfd->fd, buff, buflen, strerror(errno));
return result; return result;
} }
if (result == 0) { if (result == 0) {
@ -78,12 +75,16 @@ static ssize_t
#define BUFLEN 2048 #define BUFLEN 2048
static int xioopen_proxy_connect(int argc, const char *argv[], struct opt *opts, static int xioopen_proxy_connect(
int xioflags, xiofile_t *xxfd, int argc,
groups_t groups, int dummy1, int dummy2, const char *argv[],
int dummy3) { struct opt *opts,
int xioflags,
xiofile_t *xxfd,
const struct addrdesc *addrdesc)
{
/* we expect the form: host:host:port */ /* we expect the form: host:host:port */
struct single *xfd = &xxfd->stream; struct single *sfd = &xxfd->stream;
struct opt *opts0 = NULL; struct opt *opts0 = NULL;
struct proxyvars struct_proxyvars = { 0 }, *proxyvars = &struct_proxyvars; struct proxyvars struct_proxyvars = { 0 }, *proxyvars = &struct_proxyvars;
/* variables to be filled with address option values */ /* variables to be filled with address option values */
@ -105,16 +106,17 @@ static int xioopen_proxy_connect(int argc, const char *argv[], struct opt *opts,
int result; int result;
if (argc != 4) { if (argc != 4) {
Error1("%s: 3 parameters required", argv[0]); xio_syntax(argv[0], 3, argc-1, addrdesc->syntax);
return STAT_NORETRY; return STAT_NORETRY;
} }
proxyname = argv[1]; proxyname = argv[1];
targetname = argv[2]; targetname = argv[2];
targetport = argv[3]; targetport = argv[3];
xfd->howtoend = END_SHUTDOWN; sfd->howtoend = END_SHUTDOWN;
if (applyopts_single(xfd, opts, PH_INIT) < 0) return -1; if (applyopts_single(sfd, opts, PH_INIT) < 0)
applyopts(xfd, 1, opts, PH_INIT); return -1;
applyopts(sfd, 1, opts, PH_INIT);
retropt_int(opts, OPT_SO_TYPE, &socktype); retropt_int(opts, OPT_SO_TYPE, &socktype);
@ -127,7 +129,7 @@ static int xioopen_proxy_connect(int argc, const char *argv[], struct opt *opts,
} }
result = _xioopen_proxy_prepare(proxyvars, opts, targetname, targetport, result = _xioopen_proxy_prepare(proxyvars, opts, targetname, targetport,
xfd->para.socket.ip.ai_flags); sfd->para.socket.ip.ai_flags);
if (result != STAT_OK) if (result != STAT_OK)
return result; return result;
@ -142,7 +144,7 @@ static int xioopen_proxy_connect(int argc, const char *argv[], struct opt *opts,
result = result =
_xioopen_ipapp_prepare(opts, &opts0, proxyname, proxyport, _xioopen_ipapp_prepare(opts, &opts0, proxyname, proxyport,
&pf, ipproto, &pf, ipproto,
xfd->para.socket.ip.ai_flags, sfd->para.socket.ip.ai_flags,
&themlist, us, &uslen, &themlist, us, &uslen,
&needbind, &lowport, socktype); &needbind, &lowport, socktype);
if (result != STAT_OK) if (result != STAT_OK)
@ -168,14 +170,14 @@ static int xioopen_proxy_connect(int argc, const char *argv[], struct opt *opts,
Notice4("opening connection to %s:%u via proxy %s:%s", Notice4("opening connection to %s:%u via proxy %s:%s",
proxyvars->targetaddr, proxyvars->targetport, proxyname, proxyport); proxyvars->targetaddr, proxyvars->targetport, proxyname, proxyport);
#if WITH_RETRY #if WITH_RETRY
if (xfd->forever || xfd->retry || ai_sorted[i] != NULL) { if (sfd->forever || sfd->retry || ai_sorted[i] != NULL) {
level = E_INFO; level = E_INFO;
} else } else
#endif /* WITH_RETRY */ #endif /* WITH_RETRY */
level = E_ERROR; level = E_ERROR;
result = result =
_xioopen_connect(xfd, _xioopen_connect(sfd,
needbind?us:NULL, sizeof(*us), needbind?us:NULL, sizeof(*us),
themp->ai_addr, themp->ai_addrlen, themp->ai_addr, themp->ai_addrlen,
opts, pf?pf:themp->ai_family, socktype, IPPROTO_TCP, lowport, level); opts, pf?pf:themp->ai_family, socktype, IPPROTO_TCP, lowport, level);
@ -190,10 +192,10 @@ static int xioopen_proxy_connect(int argc, const char *argv[], struct opt *opts,
#if WITH_RETRY #if WITH_RETRY
case STAT_RETRYLATER: case STAT_RETRYLATER:
case STAT_RETRYNOW: case STAT_RETRYNOW:
if (xfd->forever || xfd->retry) { if (sfd->forever || sfd->retry) {
--xfd->retry; --sfd->retry;
if (result == STAT_RETRYLATER) if (result == STAT_RETRYLATER)
Nanosleep(&xfd->intervall, NULL); Nanosleep(&sfd->intervall, NULL);
continue; continue;
} }
#endif /* WITH_RETRY */ #endif /* WITH_RETRY */
@ -204,19 +206,19 @@ static int xioopen_proxy_connect(int argc, const char *argv[], struct opt *opts,
} }
} }
xiofreeaddrinfo(themlist); xiofreeaddrinfo(themlist);
applyopts(xfd, -1, opts, PH_ALL); applyopts(sfd, -1, opts, PH_ALL);
if ((result = _xio_openlate(xfd, opts)) < 0) if ((result = _xio_openlate(sfd, opts)) < 0)
return result; return result;
result = _xioopen_proxy_connect(xfd, proxyvars, level); result = _xioopen_proxy_connect(sfd, proxyvars, level);
switch (result) { switch (result) {
case STAT_OK: break; case STAT_OK: break;
#if WITH_RETRY #if WITH_RETRY
case STAT_RETRYLATER: case STAT_RETRYLATER:
case STAT_RETRYNOW: case STAT_RETRYNOW:
if (xfd->forever || xfd->retry--) { if (sfd->forever || sfd->retry--) {
if (result == STAT_RETRYLATER) Nanosleep(&xfd->intervall, NULL); if (result == STAT_RETRYLATER) Nanosleep(&sfd->intervall, NULL);
continue; continue;
} }
#endif /* WITH_RETRY */ #endif /* WITH_RETRY */
@ -232,24 +234,24 @@ static int xioopen_proxy_connect(int argc, const char *argv[], struct opt *opts,
if (dofork) { if (dofork) {
pid_t pid; pid_t pid;
int level = E_ERROR; int level = E_ERROR;
if (xfd->forever || xfd->retry) { if (sfd->forever || sfd->retry) {
level = E_WARN; level = E_WARN;
} }
while ((pid = xio_fork(false, level, xfd->shutup)) < 0) { while ((pid = xio_fork(false, level, sfd->shutup)) < 0) {
if (xfd->forever || --xfd->retry) { if (sfd->forever || --sfd->retry) {
Nanosleep(&xfd->intervall, NULL); continue; Nanosleep(&sfd->intervall, NULL); continue;
} }
return STAT_RETRYLATER; return STAT_RETRYLATER;
} }
if (pid == 0) { /* child process */ if (pid == 0) { /* child process */
xfd->forever = false; xfd->retry = 0; sfd->forever = false; sfd->retry = 0;
break; break;
} }
/* parent process */ /* parent process */
Close(xfd->fd); Close(sfd->fd);
Nanosleep(&xfd->intervall, NULL); Nanosleep(&sfd->intervall, NULL);
dropopts(opts, PH_ALL); opts = copyopts(opts0, GROUP_ALL); dropopts(opts, PH_ALL); opts = copyopts(opts0, GROUP_ALL);
continue; continue;
} else } else
@ -357,7 +359,7 @@ int _xioopen_proxy_prepare(
return STAT_OK; return STAT_OK;
} }
int _xioopen_proxy_connect(struct single *xfd, int _xioopen_proxy_connect(struct single *sfd,
struct proxyvars *proxyvars, struct proxyvars *proxyvars,
int level) { int level) {
size_t offset; size_t offset;
@ -387,11 +389,11 @@ int _xioopen_proxy_connect(struct single *xfd,
* xiosanitize(request, strlen(request), textbuff) = '\0'; * xiosanitize(request, strlen(request), textbuff) = '\0';
Info1("sending \"%s\"", textbuff); Info1("sending \"%s\"", textbuff);
/* write errors are assumed to always be hard errors, no retry */ /* write errors are assumed to always be hard errors, no retry */
if (writefull(xfd->fd, request, strlen(request)) < 0) { if (writefull(sfd->fd, request, strlen(request)) < 0) {
Msg4(level, "write(%d, %p, "F_Zu"): %s", Msg4(level, "write(%d, %p, "F_Zu"): %s",
xfd->fd, request, strlen(request), strerror(errno)); sfd->fd, request, strlen(request), strerror(errno));
if (Close(xfd->fd) < 0) { if (Close(sfd->fd) < 0) {
Info2("close(%d): %s", xfd->fd, strerror(errno)); Info2("close(%d): %s", sfd->fd, strerror(errno));
} }
return STAT_RETRYLATER; return STAT_RETRYLATER;
} }
@ -417,11 +419,11 @@ int _xioopen_proxy_connect(struct single *xfd,
*next = '\0'; *next = '\0';
Info1("sending \"%s\\r\\n\"", header); Info1("sending \"%s\\r\\n\"", header);
*next++ = '\r'; *next++ = '\n'; *next++ = '\0'; *next++ = '\r'; *next++ = '\n'; *next++ = '\0';
if (writefull(xfd->fd, header, strlen(header)) < 0) { if (writefull(sfd->fd, header, strlen(header)) < 0) {
Msg4(level, "write(%d, %p, "F_Zu"): %s", Msg4(level, "write(%d, %p, "F_Zu"): %s",
xfd->fd, header, strlen(header), strerror(errno)); sfd->fd, header, strlen(header), strerror(errno));
if (Close(xfd->fd) < 0) { if (Close(sfd->fd) < 0) {
Info2("close(%d): %s", xfd->fd, strerror(errno)); Info2("close(%d): %s", sfd->fd, strerror(errno));
} }
return STAT_RETRYLATER; return STAT_RETRYLATER;
} }
@ -430,11 +432,11 @@ int _xioopen_proxy_connect(struct single *xfd,
} }
Info("sending \"\\r\\n\""); Info("sending \"\\r\\n\"");
if (writefull(xfd->fd, "\r\n", 2) < 0) { if (writefull(sfd->fd, "\r\n", 2) < 0) {
Msg2(level, "write(%d, \"\\r\\n\", 2): %s", Msg2(level, "write(%d, \"\\r\\n\", 2): %s",
xfd->fd, strerror(errno)); sfd->fd, strerror(errno));
if (Close(xfd->fd) < 0) { if (Close(sfd->fd) < 0) {
Info2("close(%d): %s", xfd->fd, strerror(errno)); Info2("close(%d): %s", sfd->fd, strerror(errno));
} }
return STAT_RETRYLATER; return STAT_RETRYLATER;
} }
@ -450,7 +452,7 @@ int _xioopen_proxy_connect(struct single *xfd,
offset = 0; /* up to where the buffer is filled (relative) */ offset = 0; /* up to where the buffer is filled (relative) */
/*eol;*/ /* points to the first lineterm of the current line */ /*eol;*/ /* points to the first lineterm of the current line */
do { do {
sresult = xioproxy_recvbytes(xfd, buff+offset, 1, level); sresult = xioproxy_recvbytes(sfd, buff+offset, 1, level);
if (sresult <= 0) { if (sresult <= 0) {
state = XIOSTATE_ERROR; state = XIOSTATE_ERROR;
break; /* leave read cycles */ break; /* leave read cycles */

View file

@ -18,7 +18,7 @@
#define MAXPTYNAMELEN 64 #define MAXPTYNAMELEN 64
static int xioopen_pty(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *fd, groups_t groups, int dummy1, int dummy2, int dummy3); static int xioopen_pty(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *fd, const struct addrdesc *addrdesc);
const struct addrdesc xioaddr_pty = { "PTY", 3, xioopen_pty, GROUP_NAMED|GROUP_FD|GROUP_TERMIOS|GROUP_PTY, 0, 0, 0 HELP("") }; const struct addrdesc xioaddr_pty = { "PTY", 3, xioopen_pty, GROUP_NAMED|GROUP_FD|GROUP_TERMIOS|GROUP_PTY, 0, 0, 0 HELP("") };
@ -28,7 +28,14 @@ const struct optdesc opt_pty_wait_slave = { "pty-wait-slave", "wait-slave", OPT_
const struct optdesc opt_pty_intervall = { "pty-interval", NULL, OPT_PTY_INTERVALL, GROUP_PTY, PH_EARLY, TYPE_TIMESPEC, OFUNC_SPEC, 0, 0 }; const struct optdesc opt_pty_intervall = { "pty-interval", NULL, OPT_PTY_INTERVALL, GROUP_PTY, PH_EARLY, TYPE_TIMESPEC, OFUNC_SPEC, 0, 0 };
#endif /* HAVE_POLL */ #endif /* HAVE_POLL */
static int xioopen_pty(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *xfd, groups_t groups, int dummy1, int dummy2, int dummy3) { static int xioopen_pty(
int argc,
const char *argv[],
struct opt *opts,
int xioflags,
xiofile_t *xfd,
const struct addrdesc *addrdesc)
{
/* we expect the form: filename */ /* we expect the form: filename */
struct single *sfd = &xfd->stream; struct single *sfd = &xfd->stream;
int ptyfd = -1, ttyfd = -1; int ptyfd = -1, ttyfd = -1;
@ -49,7 +56,8 @@ static int xioopen_pty(int argc, const char *argv[], struct opt *opts, int xiofl
struct timespec pollintv = { PTY_INTERVALL }; struct timespec pollintv = { PTY_INTERVALL };
if (argc != 1) { if (argc != 1) {
Error2("%s: wrong number of parameters (%d instead of 0)", argv[0], argc-1); xio_syntax(argv[0], 0, argc-1, addrdesc->syntax);
return STAT_NORETRY;
} }
sfd->howtoend = END_CLOSE; sfd->howtoend = END_CLOSE;

View file

@ -17,22 +17,10 @@
#include "xio-rawip.h" #include "xio-rawip.h"
static static int xioopen_rawip_sendto(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *fd, const struct addrdesc *addrdesc);
int xioopen_rawip_sendto(int argc, const char *argv[], struct opt *opts, static int xioopen_rawip_datagram(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *fd, const struct addrdesc *addrdesc);
int xioflags, xiofile_t *fd, groups_t groups, int pf, static int xioopen_rawip_recvfrom(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *xfd, const struct addrdesc *addrdesc);
int dummy2, int dummy3); static int xioopen_rawip_recv(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *xfd, const struct addrdesc *addrdesc);
static
int xioopen_rawip_datagram(int argc, const char *argv[], struct opt *opts,
int xioflags, xiofile_t *fd, groups_t groups, int pf,
int dummy2, int dummy3);
static
int xioopen_rawip_recvfrom(int argc, const char *argv[], struct opt *opts,
int xioflags, xiofile_t *xfd, groups_t groups,
int pf, int socktype, int dummy3);
static
int xioopen_rawip_recv(int argc, const char *argv[], struct opt *opts,
int xioflags, xiofile_t *xfd, groups_t groups,
int pf, int socktype, int ipproto);
static static
int _xioopen_rawip_sendto(const char *hostname, const char *protname, int _xioopen_rawip_sendto(const char *hostname, const char *protname,
@ -62,21 +50,25 @@ const struct addrdesc xioaddr_rawip6_recv = { "IP6-RECV", 1+XIO_RDONLY,
/* we expect the form: host:protocol */ /* we expect the form: host:protocol */
/* struct sockaddr_in sa;*/ /* struct sockaddr_in sa;*/
/* socklen_t salen;*/ /* socklen_t salen;*/
static static int xioopen_rawip_sendto(
int xioopen_rawip_sendto(int argc, const char *argv[], struct opt *opts, int argc,
int xioflags, xiofile_t *xxfd, groups_t groups, const char *argv[],
int pf, int dummy2, int dummy3) { struct opt *opts,
int xioflags,
xiofile_t *xxfd,
const struct addrdesc *addrdesc)
{
int pf = addrdesc->arg1;
int result; int result;
if (argc != 3) { if (argc != 3) {
Error2("%s: wrong number of parameters (%d instead of 2)", xio_syntax(argv[0], 2, argc-1, addrdesc->syntax);
argv[0], argc-1);
return STAT_NORETRY; return STAT_NORETRY;
} }
xioinit_ip(&pf, xioparms.preferred_ip); xioinit_ip(&pf, xioparms.preferred_ip);
if ((result = _xioopen_rawip_sendto(argv[1], argv[2], opts, xioflags, xxfd, if ((result = _xioopen_rawip_sendto(argv[1], argv[2], opts, xioflags, xxfd,
groups, &pf)) != STAT_OK) { addrdesc->groups, &pf)) != STAT_OK) {
return result; return result;
} }
_xio_openlate(&xxfd->stream, opts); _xio_openlate(&xxfd->stream, opts);
@ -95,7 +87,7 @@ int _xioopen_rawip_sendto(const char *hostname, const char *protname,
struct opt *opts, int xioflags, xiofile_t *xxfd, struct opt *opts, int xioflags, xiofile_t *xxfd,
groups_t groups, int *pf) { groups_t groups, int *pf) {
char *garbage; char *garbage;
xiosingle_t *xfd = &xxfd->stream; xiosingle_t *sfd = &xxfd->stream;
union sockaddr_union us; union sockaddr_union us;
socklen_t uslen; socklen_t uslen;
int feats = 1; /* option bind supports only address, not port */ int feats = 1; /* option bind supports only address, not port */
@ -114,95 +106,106 @@ int _xioopen_rawip_sendto(const char *hostname, const char *protname,
/*return STAT_NORETRY;*/ /*return STAT_NORETRY;*/
} }
xfd->howtoend = END_SHUTDOWN; sfd->howtoend = END_SHUTDOWN;
retropt_int(opts, OPT_PROTOCOL_FAMILY, pf); retropt_int(opts, OPT_PROTOCOL_FAMILY, pf);
if (applyopts_single(xfd, opts, PH_INIT) < 0) return -1; if (applyopts_single(sfd, opts, PH_INIT) < 0) return -1;
applyopts(xfd, -1, opts, PH_INIT); applyopts(sfd, -1, opts, PH_INIT);
xfd->salen = sizeof(xfd->peersa); sfd->salen = sizeof(sfd->peersa);
if ((result = if ((result =
xioresolve(hostname, NULL, *pf, socktype, ipproto, xioresolve(hostname, NULL, *pf, socktype, ipproto,
&xfd->peersa, &xfd->salen, &sfd->peersa, &sfd->salen,
xfd->para.socket.ip.ai_flags)) sfd->para.socket.ip.ai_flags))
!= STAT_OK) { != STAT_OK) {
return result; return result;
} }
if (*pf == PF_UNSPEC) { if (*pf == PF_UNSPEC) {
*pf = xfd->peersa.soa.sa_family; *pf = sfd->peersa.soa.sa_family;
} }
uslen = socket_init(*pf, &us); uslen = socket_init(*pf, &us);
xfd->dtype = XIODATA_RECVFROM_SKIPIP; sfd->dtype = XIODATA_RECVFROM_SKIPIP;
if (retropt_bind(opts, *pf, socktype, ipproto, &us.soa, &uslen, feats, if (retropt_bind(opts, *pf, socktype, ipproto, &us.soa, &uslen, feats,
xfd->para.socket.ip.ai_flags) sfd->para.socket.ip.ai_flags)
!= STAT_NOACTION) { != STAT_NOACTION) {
needbind = true; needbind = true;
} }
return return
_xioopen_dgram_sendto(needbind?&us:NULL, uslen, _xioopen_dgram_sendto(needbind?&us:NULL, uslen,
opts, xioflags, xfd, groups, *pf, socktype, ipproto, 0); opts, xioflags, sfd, groups, *pf, socktype, ipproto, 0);
} }
/* we expect the form: address:protocol */ /* we expect the form: address:protocol */
static static int xioopen_rawip_datagram(
int xioopen_rawip_datagram(int argc, const char *argv[], struct opt *opts, int argc,
int xioflags, xiofile_t *xxfd, groups_t groups, const char *argv[],
int pf, int dummy2, int dummy3) { struct opt *opts,
xiosingle_t *xfd = &xxfd->stream; int xioflags,
xiofile_t *xxfd,
const struct addrdesc *addrdesc)
{
xiosingle_t *sfd = &xxfd->stream;
int pf = addrdesc->arg1;
char *rangename; char *rangename;
int result; int result;
if (argc != 3) { if (argc != 3) {
Error2("%s: wrong number of parameters (%d instead of 2)", xio_syntax(argv[0], 2, argc-1, addrdesc->syntax);
argv[0], argc-1);
return STAT_NORETRY; return STAT_NORETRY;
} }
xioinit_ip(&pf, xioparms.preferred_ip); xioinit_ip(&pf, xioparms.preferred_ip);
if ((result = if ((result =
_xioopen_rawip_sendto(argv[1], argv[2], opts, xioflags, xxfd, _xioopen_rawip_sendto(argv[1], argv[2], opts, xioflags, xxfd,
groups, &pf)) != STAT_OK) { addrdesc->groups, &pf)) != STAT_OK) {
return result; return result;
} }
xfd->dtype = XIOREAD_RECV|XIOWRITE_SENDTO; sfd->dtype = XIOREAD_RECV|XIOWRITE_SENDTO;
if (pf == PF_INET) { if (pf == PF_INET) {
xfd->dtype |= XIOREAD_RECV_SKIPIP; sfd->dtype |= XIOREAD_RECV_SKIPIP;
} }
xfd->para.socket.la.soa.sa_family = xfd->peersa.soa.sa_family; sfd->para.socket.la.soa.sa_family = sfd->peersa.soa.sa_family;
/* which reply packets will be accepted - determine by range option */ /* which reply packets will be accepted - determine by range option */
if (retropt_string(opts, OPT_RANGE, &rangename) >= 0) { if (retropt_string(opts, OPT_RANGE, &rangename) >= 0) {
if (xioparserange(rangename, pf, &xfd->para.socket.range, if (xioparserange(rangename, pf, &sfd->para.socket.range,
xfd->para.socket.ip.ai_flags) sfd->para.socket.ip.ai_flags)
< 0) { < 0) {
free(rangename); free(rangename);
return STAT_NORETRY; return STAT_NORETRY;
} }
xfd->para.socket.dorange = true; sfd->para.socket.dorange = true;
xfd->dtype |= XIOREAD_RECV_CHECKRANGE; sfd->dtype |= XIOREAD_RECV_CHECKRANGE;
free(rangename); free(rangename);
} }
#if WITH_LIBWRAP #if WITH_LIBWRAP
xio_retropt_tcpwrap(xfd, opts); xio_retropt_tcpwrap(sfd, opts);
#endif /* WITH_LIBWRAP */ #endif /* WITH_LIBWRAP */
_xio_openlate(xfd, opts); _xio_openlate(sfd, opts);
return STAT_OK; return STAT_OK;
} }
static static int xioopen_rawip_recvfrom(
int xioopen_rawip_recvfrom(int argc, const char *argv[], struct opt *opts, int argc,
int xioflags, xiofile_t *xfd, groups_t groups, const char *argv[],
int pf, int socktype, int dummy3) { struct opt *opts,
int xioflags,
xiofile_t *xfd,
const struct addrdesc *addrdesc)
{
struct single *sfd = &xfd->stream;
const char *protname = argv[1]; const char *protname = argv[1];
int pf = addrdesc->arg1;
int socktype = addrdesc->arg2;
char *garbage; char *garbage;
union sockaddr_union us; union sockaddr_union us;
socklen_t uslen = sizeof(us); socklen_t uslen = sizeof(us);
@ -211,8 +214,7 @@ int xioopen_rawip_recvfrom(int argc, const char *argv[], struct opt *opts,
int result; int result;
if (argc != 2) { if (argc != 2) {
Error2("%s: wrong number of parameters (%d instead of 1)", xio_syntax(argv[0], 1, argc-1, addrdesc->syntax);
argv[0], argc-1);
return STAT_NORETRY; return STAT_NORETRY;
} }
@ -226,7 +228,7 @@ int xioopen_rawip_recvfrom(int argc, const char *argv[], struct opt *opts,
protname); protname);
/*return STAT_NORETRY;*/ /*return STAT_NORETRY;*/
} }
xfd->stream.howtoend = END_NONE; sfd->howtoend = END_NONE;
retropt_socket_pf(opts, &pf); retropt_socket_pf(opts, &pf);
if (pf == PF_UNSPEC) { if (pf == PF_UNSPEC) {
@ -244,28 +246,34 @@ int xioopen_rawip_recvfrom(int argc, const char *argv[], struct opt *opts,
} }
if (retropt_bind(opts, pf, socktype, ipproto, &us.soa, &uslen, 1, if (retropt_bind(opts, pf, socktype, ipproto, &us.soa, &uslen, 1,
xfd->stream.para.socket.ip.ai_flags) sfd->para.socket.ip.ai_flags)
!= STAT_NOACTION) { != STAT_NOACTION) {
needbind = true; needbind = true;
} }
xfd->stream.dtype = XIODATA_RECVFROM_SKIPIP_ONE; sfd->dtype = XIODATA_RECVFROM_SKIPIP_ONE;
if ((result = if ((result =
_xioopen_dgram_recvfrom(&xfd->stream, xioflags, needbind?&us.soa:NULL, _xioopen_dgram_recvfrom(sfd, xioflags, needbind?&us.soa:NULL,
uslen, opts, pf, socktype, ipproto, E_ERROR)) uslen, opts, pf, socktype, ipproto, E_ERROR))
!= STAT_OK) { != STAT_OK) {
return result; return result;
} }
_xio_openlate(&xfd->stream, opts); _xio_openlate(sfd, opts);
return STAT_OK; return STAT_OK;
} }
static static int xioopen_rawip_recv(
int xioopen_rawip_recv(int argc, const char *argv[], struct opt *opts, int argc,
int xioflags, xiofile_t *xfd, groups_t groups, const char *argv[],
int pf, int socktype, int dummy3) { struct opt *opts,
int xioflags,
xiofile_t *xfd,
const struct addrdesc *addrdesc)
{
const char *protname = argv[1]; const char *protname = argv[1];
int pf = addrdesc->arg1;
int socktype = addrdesc->arg2;
char *garbage; char *garbage;
bool needbind = false; bool needbind = false;
union sockaddr_union us; union sockaddr_union us;
@ -274,8 +282,7 @@ int xioopen_rawip_recv(int argc, const char *argv[], struct opt *opts,
int result; int result;
if (argc != 2) { if (argc != 2) {
Error2("%s: wrong number of parameters (%d instead of 1)", xio_syntax(argv[0], 1, argc-1, addrdesc->syntax);
argv[0], argc-1);
return STAT_NORETRY; return STAT_NORETRY;
} }

View file

@ -25,9 +25,7 @@ uses stdin!!
/* length of buffer for dynamic prompt */ /* length of buffer for dynamic prompt */
#define READLINE_MAXPROMPT 512 #define READLINE_MAXPROMPT 512
static int xioopen_readline(int argc, const char *argv[], struct opt *opts, static int xioopen_readline(int argc, const char *argv[], struct opt *opts, int rw, xiofile_t *xfd, const struct addrdesc *addrdesc);
int rw, xiofile_t *xfd, groups_t groups,
int dummy1, int dummy2, int dummy3);
const struct addrdesc xioaddr_readline = { "READLINE", 3, xioopen_readline, GROUP_FD|GROUP_TERMIOS|GROUP_READLINE, 0, 0, 0 HELP(NULL) }; const struct addrdesc xioaddr_readline = { "READLINE", 3, xioopen_readline, GROUP_FD|GROUP_TERMIOS|GROUP_READLINE, 0, 0, 0 HELP(NULL) };
@ -37,9 +35,14 @@ const struct optdesc opt_prompt = { "prompt", NULL, OPT_PROMPT,
const struct optdesc opt_noprompt = { "noprompt", NULL, OPT_NOPROMPT, GROUP_READLINE, PH_LATE, TYPE_BOOL, OFUNC_SPEC, 0 }; const struct optdesc opt_noprompt = { "noprompt", NULL, OPT_NOPROMPT, GROUP_READLINE, PH_LATE, TYPE_BOOL, OFUNC_SPEC, 0 };
const struct optdesc opt_noecho = { "noecho", NULL, OPT_NOECHO, GROUP_READLINE, PH_LATE, TYPE_STRING, OFUNC_SPEC, 0 }; const struct optdesc opt_noecho = { "noecho", NULL, OPT_NOECHO, GROUP_READLINE, PH_LATE, TYPE_STRING, OFUNC_SPEC, 0 };
static int xioopen_readline(int argc, const char *argv[], struct opt *opts, static int xioopen_readline(
int xioflags, xiofile_t *xfd, groups_t groups, int argc,
int dummy1, int dummy2, int dummy3) { const char *argv[],
struct opt *opts,
int xioflags,
xiofile_t *xfd,
const struct addrdesc *addrdesc)
{
struct single *sfd = &xfd->stream; struct single *sfd = &xfd->stream;
int rw = (xioflags & XIO_ACCMODE); int rw = (xioflags & XIO_ACCMODE);
char msgbuf[256], *cp = msgbuf; char msgbuf[256], *cp = msgbuf;
@ -47,7 +50,7 @@ static int xioopen_readline(int argc, const char *argv[], struct opt *opts,
char *noecho = NULL; char *noecho = NULL;
if (argc != 1) { if (argc != 1) {
Error1("%s: 0 parameters required", argv[0]); xio_syntax(argv[0], 0, argc-1, addrdesc->syntax);
return STAT_NORETRY; return STAT_NORETRY;
} }

View file

@ -30,30 +30,12 @@
#include "xio-tcpwrap.h" #include "xio-tcpwrap.h"
static static int xioopen_socket_connect(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *xfd, const struct addrdesc *addrdesc);
int xioopen_socket_connect(int argc, const char *argv[], struct opt *opts, static int xioopen_socket_listen(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *xfd, const struct addrdesc *addrdesc);
int xioflags, xiofile_t *xfd, groups_t groups, static int xioopen_socket_sendto(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *xfd, const struct addrdesc *addrdesc);
int dummy1, int dummy2, int dummy3); static int xioopen_socket_datagram(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *xfd, const struct addrdesc *addrdesc);
static static int xioopen_socket_recvfrom(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *xfd, const struct addrdesc *addrdesc);
int xioopen_socket_listen(int argc, const char *argv[], struct opt *opts, static int xioopen_socket_recv(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *xfd, const struct addrdesc *addrdesc);
int xioflags, xiofile_t *xfd, groups_t 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, groups_t 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, groups_t 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, groups_t 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, groups_t groups,
int dummy1, int dummy2, int dummy3);
static static
int _xioopen_socket_sendto(const char *pfname, const char *type, int _xioopen_socket_sendto(const char *pfname, const char *type,
@ -68,7 +50,7 @@ xiolog_ancillary_socket(struct single *sfd, struct cmsghdr *cmsg, int *num,
char *envbuff, int envlen, char *envbuff, int envlen,
char *valbuff, int vallen); char *valbuff, int vallen);
static int xiobind( static int xiobind(
struct single *xfd, struct single *sfd,
union sockaddr_union *us, union sockaddr_union *us,
size_t uslen, size_t uslen,
struct opt *opts, struct opt *opts,
@ -215,10 +197,14 @@ const struct optdesc opt_null_eof = { "null-eof", NULL, OPT_NULL_EOF, GROUP_SOCK
#if WITH_GENERICSOCKET #if WITH_GENERICSOCKET
static static int xioopen_socket_connect(
int xioopen_socket_connect(int argc, const char *argv[], struct opt *opts, int argc,
int xioflags, xiofile_t *xxfd, groups_t groups, const char *argv[],
int dummy1, int dummy2, int dummy3) { struct opt *opts,
int xioflags,
xiofile_t *xxfd,
const struct addrdesc *addrdesc)
{
struct single *sfd = &xxfd->stream; struct single *sfd = &xxfd->stream;
const char *pfname = argv[1]; const char *pfname = argv[1];
const char *protname = argv[2]; const char *protname = argv[2];
@ -233,8 +219,7 @@ int xioopen_socket_connect(int argc, const char *argv[], struct opt *opts,
int result; int result;
if (argc != 4) { if (argc != 4) {
Error2("%s: wrong number of parameters (%d instead of 3)", xio_syntax(argv[0], 3, argc-1, addrdesc->syntax);
argv[0], argc-1);
return STAT_NORETRY; return STAT_NORETRY;
} }
@ -297,10 +282,14 @@ int xioopen_socket_connect(int argc, const char *argv[], struct opt *opts,
} }
#if WITH_LISTEN #if WITH_LISTEN
static static int xioopen_socket_listen(
int xioopen_socket_listen(int argc, const char *argv[], struct opt *opts, int argc,
int xioflags, xiofile_t *xxfd, groups_t groups, const char *argv[],
int dummy1, int dummy2, int dummy3) { struct opt *opts,
int xioflags,
xiofile_t *xxfd,
const struct addrdesc *addrdesc)
{
struct single *sfd = &xxfd->stream; struct single *sfd = &xxfd->stream;
const char *pfname = argv[1]; const char *pfname = argv[1];
const char *protname = argv[2]; const char *protname = argv[2];
@ -314,8 +303,7 @@ int xioopen_socket_listen(int argc, const char *argv[], struct opt *opts,
int result; int result;
if (argc != 4) { if (argc != 4) {
Error2("%s: wrong number of parameters (%d instead of 3)", xio_syntax(argv[0], 3, argc-1, addrdesc->syntax);
argv[0], argc-1);
return STAT_NORETRY; return STAT_NORETRY;
} }
@ -368,20 +356,23 @@ int xioopen_socket_listen(int argc, const char *argv[], struct opt *opts,
#endif /* WITH_LISTEN */ #endif /* WITH_LISTEN */
/* we expect the form: ...:domain:type:protocol:remote-address */ /* we expect the form: ...:domain:type:protocol:remote-address */
static static int xioopen_socket_sendto(
int xioopen_socket_sendto(int argc, const char *argv[], struct opt *opts, int argc,
int xioflags, xiofile_t *xxfd, groups_t groups, const char *argv[],
int dummy1, int dummy2, int dummy3) { struct opt *opts,
int xioflags,
xiofile_t *xxfd,
const struct addrdesc *addrdesc)
{
int result; int result;
if (argc != 5) { if (argc != 5) {
Error2("%s: wrong number of parameters (%d instead of 4)", xio_syntax(argv[0], 4, argc-1, addrdesc->syntax);
argv[0], argc-1);
return STAT_NORETRY; return STAT_NORETRY;
} }
if ((result = if ((result =
_xioopen_socket_sendto(argv[1], argv[2], argv[3], argv[4], _xioopen_socket_sendto(argv[1], argv[2], argv[3], argv[4],
opts, xioflags, xxfd, groups)) opts, xioflags, xxfd, addrdesc->groups))
!= STAT_OK) { != STAT_OK) {
return result; return result;
} }
@ -482,24 +473,28 @@ int _xioopen_socket_sendto(const char *pfname, const char *type,
/* we expect the form: ...:domain:socktype:protocol:local-address */ /* we expect the form: ...:domain:socktype:protocol:local-address */
static static
int xioopen_socket_recvfrom(int argc, const char *argv[], struct opt *opts, int xioopen_socket_recvfrom(
int xioflags, xiofile_t *xxfd, groups_t groups, int argc,
int dummy, int summy2, int dummy3) { const char *argv[],
struct single *xfd = &xxfd->stream; struct opt *opts,
int xioflags,
xiofile_t *xxfd,
const struct addrdesc *addrdesc)
{
struct single *sfd = &xxfd->stream;
const char *pfname = argv[1]; const char *pfname = argv[1];
const char *typename = argv[2]; const char *typename = argv[2];
const char *protname = argv[3]; const char *protname = argv[3];
const char *address = argv[4]; const char *address = argv[4];
char *garbage; char *garbage;
union sockaddr_union *us = &xfd->para.socket.la; union sockaddr_union *us = &sfd->para.socket.la;
socklen_t uslen; size_t ussize; socklen_t uslen; size_t ussize;
int pf, socktype, proto; int pf, socktype, proto;
char *rangename; char *rangename;
int result; int result;
if (argc != 5) { if (argc != 5) {
Error2("%s: wrong number of parameters (%d instead of 4)", xio_syntax(argv[0], 4, argc-1, addrdesc->syntax);
argv[0], argc-1);
return STAT_NORETRY; return STAT_NORETRY;
} }
@ -521,7 +516,7 @@ int xioopen_socket_recvfrom(int argc, const char *argv[], struct opt *opts,
retropt_socket_pf(opts, &pf); retropt_socket_pf(opts, &pf);
retropt_int(opts, OPT_SO_TYPE, &socktype); retropt_int(opts, OPT_SO_TYPE, &socktype);
/*retropt_int(opts, OPT_IP_PROTOCOL, &proto);*/ /*retropt_int(opts, OPT_IP_PROTOCOL, &proto);*/
xfd->howtoend = END_NONE; sfd->howtoend = END_NONE;
ussize = 0; ussize = 0;
if ((result = if ((result =
@ -537,35 +532,40 @@ int xioopen_socket_recvfrom(int argc, const char *argv[], struct opt *opts,
+ sizeof(us->soa.sa_len); + sizeof(us->soa.sa_len);
#endif #endif
; ;
xfd->dtype = XIOREAD_RECV|XIOWRITE_SENDTO; sfd->dtype = XIOREAD_RECV|XIOWRITE_SENDTO;
if (retropt_string(opts, OPT_RANGE, &rangename) >= 0) { if (retropt_string(opts, OPT_RANGE, &rangename) >= 0) {
if (xioparserange(rangename, 0, &xfd->para.socket.range, if (xioparserange(rangename, 0, &sfd->para.socket.range,
xfd->para.socket.ip.ai_flags) sfd->para.socket.ip.ai_flags)
< 0) { < 0) {
free(rangename); free(rangename);
return STAT_NORETRY; return STAT_NORETRY;
} }
xfd->para.socket.dorange = true; sfd->para.socket.dorange = true;
free(rangename); free(rangename);
} }
if ((result = if ((result =
_xioopen_dgram_recvfrom(xfd, xioflags, &us->soa, uslen, _xioopen_dgram_recvfrom(sfd, xioflags, &us->soa, uslen,
opts, pf, socktype, proto, E_ERROR)) opts, pf, socktype, proto, E_ERROR))
!= STAT_OK) { != STAT_OK) {
return result; return result;
} }
_xio_openlate(xfd, opts); _xio_openlate(sfd, opts);
return STAT_OK; return STAT_OK;
} }
/* we expect the form: ...:domain:type:protocol:local-address */ /* we expect the form: ...:domain:type:protocol:local-address */
static static
int xioopen_socket_recv(int argc, const char *argv[], struct opt *opts, int xioopen_socket_recv(
int xioflags, xiofile_t *xxfd, groups_t groups, int argc,
int dummy1, int dummy2, int dummy3) { const char *argv[],
struct single *xfd = &xxfd->stream; struct opt *opts,
int xioflags,
xiofile_t *xxfd,
const struct addrdesc *addrdesc)
{
struct single *sfd = &xxfd->stream;
const char *pfname = argv[1]; const char *pfname = argv[1];
const char *typename = argv[2]; const char *typename = argv[2];
const char *protname = argv[3]; const char *protname = argv[3];
@ -578,8 +578,7 @@ int xioopen_socket_recv(int argc, const char *argv[], struct opt *opts,
int result; int result;
if (argc != 5) { if (argc != 5) {
Error2("%s: wrong number of parameters (%d instead of 4)", xio_syntax(argv[0], 4, argc-1, addrdesc->syntax);
argv[0], argc-1);
return STAT_NORETRY; return STAT_NORETRY;
} }
@ -601,7 +600,7 @@ int xioopen_socket_recv(int argc, const char *argv[], struct opt *opts,
retropt_socket_pf(opts, &pf); retropt_socket_pf(opts, &pf);
retropt_int(opts, OPT_SO_TYPE, &socktype); retropt_int(opts, OPT_SO_TYPE, &socktype);
/*retropt_int(opts, OPT_IP_PROTOCOL, &proto);*/ /*retropt_int(opts, OPT_IP_PROTOCOL, &proto);*/
xfd->howtoend = END_NONE; sfd->howtoend = END_NONE;
ussize = 0; ussize = 0;
if ((result = if ((result =
@ -617,37 +616,41 @@ int xioopen_socket_recv(int argc, const char *argv[], struct opt *opts,
+sizeof(us.soa.sa_len) +sizeof(us.soa.sa_len)
#endif #endif
; ;
xfd->dtype = XIOREAD_RECV; sfd->dtype = XIOREAD_RECV;
xfd->para.socket.la.soa.sa_family = pf; sfd->para.socket.la.soa.sa_family = pf;
if (retropt_string(opts, OPT_RANGE, &rangename) >= 0) { if (retropt_string(opts, OPT_RANGE, &rangename) >= 0) {
if (xioparserange(rangename, 0, &xfd->para.socket.range, if (xioparserange(rangename, 0, &sfd->para.socket.range,
xfd->para.socket.ip.ai_flags) sfd->para.socket.ip.ai_flags)
< 0) { < 0) {
free(rangename); free(rangename);
return STAT_NORETRY; return STAT_NORETRY;
} }
xfd->para.socket.dorange = true; sfd->para.socket.dorange = true;
free(rangename); free(rangename);
} }
if ((result = if ((result =
_xioopen_dgram_recv(xfd, xioflags, &us.soa, _xioopen_dgram_recv(sfd, xioflags, &us.soa,
uslen, opts, pf, socktype, proto, E_ERROR)) uslen, opts, pf, socktype, proto, E_ERROR))
!= STAT_OK) { != STAT_OK) {
return result; return result;
} }
_xio_openlate(xfd, opts); _xio_openlate(sfd, opts);
return STAT_OK; return STAT_OK;
} }
/* we expect the form: ...:domain:type:protocol:remote-address */ /* we expect the form: ...:domain:type:protocol:remote-address */
static static int xioopen_socket_datagram(
int xioopen_socket_datagram(int argc, const char *argv[], struct opt *opts, int argc,
int xioflags, xiofile_t *xxfd, groups_t groups, const char *argv[],
int dummy1, int dummy2, int dummy3) { struct opt *opts,
xiosingle_t *xfd = &xxfd->stream; int xioflags,
xiofile_t *xxfd,
const struct addrdesc *addrdesc)
{
xiosingle_t *sfd = &xxfd->stream;
const char *pfname = argv[1]; const char *pfname = argv[1];
const char *typename = argv[2]; const char *typename = argv[2];
const char *protname = argv[3]; const char *protname = argv[3];
@ -659,8 +662,7 @@ int xioopen_socket_datagram(int argc, const char *argv[], struct opt *opts,
int result; int result;
if (argc != 5) { if (argc != 5) {
Error2("%s: wrong number of parameters (%d instead of 4)", xio_syntax(argv[0], 4, argc-1, addrdesc->syntax);
argv[0], argc-1);
return STAT_NORETRY; return STAT_NORETRY;
} }
@ -671,50 +673,50 @@ int xioopen_socket_datagram(int argc, const char *argv[], struct opt *opts,
retropt_socket_pf(opts, &pf); retropt_socket_pf(opts, &pf);
/*retropt_int(opts, OPT_IP_PROTOCOL, &proto);*/ /*retropt_int(opts, OPT_IP_PROTOCOL, &proto);*/
xfd->howtoend = END_SHUTDOWN; sfd->howtoend = END_SHUTDOWN;
xfd->peersa.soa.sa_family = pf; sfd->peersa.soa.sa_family = pf;
themsize = 0; themsize = 0;
if ((result = if ((result =
dalan(address, (uint8_t *)&xfd->peersa.soa.sa_data, &themsize, dalan(address, (uint8_t *)&sfd->peersa.soa.sa_data, &themsize,
sizeof(xfd->peersa), 'i')) sizeof(sfd->peersa), 'i'))
< 0) { < 0) {
Error1("data too long: \"%s\"", address); Error1("data too long: \"%s\"", address);
} else if (result > 0) { } else if (result > 0) {
Error1("syntax error in \"%s\"", address); Error1("syntax error in \"%s\"", address);
} }
xfd->salen = themsize + sizeof(sa_family_t); sfd->salen = themsize + sizeof(sa_family_t);
#if HAVE_STRUCT_SOCKADDR_SALEN #if HAVE_STRUCT_SOCKADDR_SALEN
xfd->peersa.soa.sa_len = sfd->peersa.soa.sa_len =
sizeof(xfd->peersa.soa.sa_len) + sizeof(xfd->peersa.soa.sa_family) + sizeof(sfd->peersa.soa.sa_len) + sizeof(sfd->peersa.soa.sa_family) +
themsize; themsize;
#endif #endif
if ((result = if ((result =
_xioopen_socket_sendto(pfname, typename, protname, address, _xioopen_socket_sendto(pfname, typename, protname, address,
opts, xioflags, xxfd, groups)) opts, xioflags, xxfd, addrdesc->groups))
!= STAT_OK) { != STAT_OK) {
return result; return result;
} }
xfd->dtype = XIOREAD_RECV|XIOWRITE_SENDTO; sfd->dtype = XIOREAD_RECV|XIOWRITE_SENDTO;
xfd->para.socket.la.soa.sa_family = xfd->peersa.soa.sa_family; sfd->para.socket.la.soa.sa_family = sfd->peersa.soa.sa_family;
/* which reply sockets will accept - determine by range option */ /* which reply sockets will accept - determine by range option */
if (retropt_string(opts, OPT_RANGE, &rangename) >= 0) { if (retropt_string(opts, OPT_RANGE, &rangename) >= 0) {
if (xioparserange(rangename, 0, &xfd->para.socket.range, if (xioparserange(rangename, 0, &sfd->para.socket.range,
xfd->para.socket.ip.ai_flags) sfd->para.socket.ip.ai_flags)
< 0) { < 0) {
free(rangename); free(rangename);
return STAT_NORETRY; return STAT_NORETRY;
} }
xfd->para.socket.dorange = true; sfd->para.socket.dorange = true;
xfd->dtype |= XIOREAD_RECV_CHECKRANGE; sfd->dtype |= XIOREAD_RECV_CHECKRANGE;
free(rangename); free(rangename);
} }
_xio_openlate(xfd, opts); _xio_openlate(sfd, opts);
return STAT_OK; return STAT_OK;
} }
@ -943,7 +945,7 @@ int _xioopen_connect(struct single *sfd, union sockaddr_union *us, size_t uslen,
OPT_FORK, OPT_SO_TYPE, OPT_SO_PROTOTYPE, OPT_USER, OPT_GROUP, OPT_CLOEXEC OPT_FORK, OPT_SO_TYPE, OPT_SO_PROTOTYPE, OPT_USER, OPT_GROUP, OPT_CLOEXEC
returns 0 on success. returns 0 on success.
*/ */
int xioopen_connect(struct single *xfd, union sockaddr_union *us, size_t uslen, int xioopen_connect(struct single *sfd, union sockaddr_union *us, size_t uslen,
struct sockaddr *them, size_t themlen, struct sockaddr *them, size_t themlen,
struct opt *opts, int pf, int socktype, int protocol, struct opt *opts, int pf, int socktype, int protocol,
bool alt) { bool alt) {
@ -963,22 +965,22 @@ int xioopen_connect(struct single *xfd, union sockaddr_union *us, size_t uslen,
do { /* loop over retries and forks */ do { /* loop over retries and forks */
#if WITH_RETRY #if WITH_RETRY
if (xfd->forever || xfd->retry) { if (sfd->forever || sfd->retry) {
level = E_INFO; level = E_INFO;
} else } else
#endif /* WITH_RETRY */ #endif /* WITH_RETRY */
level = E_ERROR; level = E_ERROR;
result = result =
_xioopen_connect(xfd, us, uslen, them, themlen, opts, _xioopen_connect(sfd, us, uslen, them, themlen, opts,
pf, socktype, protocol, alt, level); pf, socktype, protocol, alt, level);
switch (result) { switch (result) {
case STAT_OK: break; case STAT_OK: break;
#if WITH_RETRY #if WITH_RETRY
case STAT_RETRYLATER: case STAT_RETRYLATER:
if (xfd->forever || xfd->retry) { if (sfd->forever || sfd->retry) {
--xfd->retry; --sfd->retry;
if (result == STAT_RETRYLATER) { if (result == STAT_RETRYLATER) {
Nanosleep(&xfd->intervall, NULL); Nanosleep(&sfd->intervall, NULL);
} }
dropopts(opts, PH_ALL); opts = copyopts(opts0, GROUP_ALL); dropopts(opts, PH_ALL); opts = copyopts(opts0, GROUP_ALL);
continue; continue;
@ -997,16 +999,16 @@ int xioopen_connect(struct single *xfd, union sockaddr_union *us, size_t uslen,
if (dofork) { if (dofork) {
pid_t pid; pid_t pid;
int level = E_ERROR; int level = E_ERROR;
if (xfd->forever || xfd->retry) { if (sfd->forever || sfd->retry) {
level = E_WARN; /* most users won't expect a problem here, level = E_WARN; /* most users won't expect a problem here,
so Notice is too weak */ so Notice is too weak */
} }
while ((pid = xio_fork(false, level, xfd->shutup)) < 0) { while ((pid = xio_fork(false, level, sfd->shutup)) < 0) {
--xfd->retry; --sfd->retry;
if (xfd->forever || xfd->retry) { if (sfd->forever || sfd->retry) {
dropopts(opts, PH_ALL); opts = copyopts(opts0, GROUP_ALL); dropopts(opts, PH_ALL); opts = copyopts(opts0, GROUP_ALL);
Nanosleep(&xfd->intervall, NULL); continue; Nanosleep(&sfd->intervall, NULL); continue;
} }
return STAT_RETRYLATER; return STAT_RETRYLATER;
} }
@ -1016,9 +1018,9 @@ int xioopen_connect(struct single *xfd, union sockaddr_union *us, size_t uslen,
} }
/* parent process */ /* parent process */
Close(xfd->fd); Close(sfd->fd);
/* with and without retry */ /* with and without retry */
Nanosleep(&xfd->intervall, NULL); Nanosleep(&sfd->intervall, NULL);
dropopts(opts, PH_ALL); opts = copyopts(opts0, GROUP_ALL); dropopts(opts, PH_ALL); opts = copyopts(opts0, GROUP_ALL);
continue; /* with next socket() bind() connect() */ continue; /* with next socket() bind() connect() */
} else } else
@ -1124,7 +1126,7 @@ int _xioopen_dgram_sendto(/* them is already in xfd->peersa */
OPT_FORK, OPT_SO_TYPE, OPT_SO_PROTOTYPE, cloexec, OPT_RANGE, tcpwrap OPT_FORK, OPT_SO_TYPE, OPT_SO_PROTOTYPE, cloexec, OPT_RANGE, tcpwrap
EINTR is not handled specially. EINTR is not handled specially.
*/ */
int _xioopen_dgram_recvfrom(struct single *xfd, int xioflags, int _xioopen_dgram_recvfrom(struct single *sfd, int xioflags,
struct sockaddr *us, socklen_t uslen, struct sockaddr *us, socklen_t uslen,
struct opt *opts, struct opt *opts,
int pf, int socktype, int proto, int level) { int pf, int socktype, int proto, int level) {
@ -1143,25 +1145,25 @@ int _xioopen_dgram_recvfrom(struct single *xfd, int xioflags,
Error("option fork not allowed here"); Error("option fork not allowed here");
return STAT_NORETRY; return STAT_NORETRY;
} }
xfd->flags |= XIO_DOESFORK; sfd->flags |= XIO_DOESFORK;
} }
if (applyopts_single(xfd, opts, PH_INIT) < 0) return STAT_NORETRY; if (applyopts_single(sfd, opts, PH_INIT) < 0) return STAT_NORETRY;
if ((xfd->fd = xiosocket(opts, pf, socktype, proto, level)) < 0) { if ((sfd->fd = xiosocket(opts, pf, socktype, proto, level)) < 0) {
return STAT_RETRYLATER; return STAT_RETRYLATER;
} }
applyopts(xfd, -1, opts, PH_PASTSOCKET); applyopts(sfd, -1, opts, PH_PASTSOCKET);
applyopts_cloexec(xfd->fd, opts); applyopts_cloexec(sfd->fd, opts);
if (xiobind(xfd, (union sockaddr_union *)us, uslen, if (xiobind(sfd, (union sockaddr_union *)us, uslen,
opts, pf, 0, level) < 0) { opts, pf, 0, level) < 0) {
return -1; return -1;
} }
applyopts(xfd, -1, opts, PH_PASTBIND); applyopts(sfd, -1, opts, PH_PASTBIND);
#if WITH_UNIX #if WITH_UNIX
if (pf == AF_UNIX && us != NULL) { if (pf == AF_UNIX && us != NULL) {
@ -1173,18 +1175,18 @@ int _xioopen_dgram_recvfrom(struct single *xfd, int xioflags,
/* for generic sockets, this has already been retrieved */ /* for generic sockets, this has already been retrieved */
if (retropt_string(opts, OPT_RANGE, &rangename) >= 0) { if (retropt_string(opts, OPT_RANGE, &rangename) >= 0) {
if (xioparserange(rangename, pf, &xfd->para.socket.range, if (xioparserange(rangename, pf, &sfd->para.socket.range,
xfd->para.socket.ip.ai_flags) sfd->para.socket.ip.ai_flags)
< 0) { < 0) {
free(rangename); free(rangename);
return STAT_NORETRY; return STAT_NORETRY;
} }
free(rangename); free(rangename);
xfd->para.socket.dorange = true; sfd->para.socket.dorange = true;
} }
#if (WITH_TCP || WITH_UDP) && WITH_LIBWRAP #if (WITH_TCP || WITH_UDP) && WITH_LIBWRAP
xio_retropt_tcpwrap(xfd, opts); xio_retropt_tcpwrap(sfd, opts);
#endif /* && (WITH_TCP || WITH_UDP) && WITH_LIBWRAP */ #endif /* && (WITH_TCP || WITH_UDP) && WITH_LIBWRAP */
if (xioparms.logopt == 'm') { if (xioparms.logopt == 'm') {
@ -1215,7 +1217,7 @@ int _xioopen_dgram_recvfrom(struct single *xfd, int xioflags,
if (drop) { if (drop) {
char *dummy[2]; char *dummy[2];
Recv(xfd->fd, dummy, sizeof(dummy), 0); Recv(sfd->fd, dummy, sizeof(dummy), 0);
drop = true; drop = true;
} }
@ -1229,7 +1231,7 @@ int _xioopen_dgram_recvfrom(struct single *xfd, int xioflags,
} else { } else {
Notice1("receiving IP protocol %u", proto); Notice1("receiving IP protocol %u", proto);
} }
readfd.fd = xfd->fd; readfd.fd = sfd->fd;
readfd.events = POLLIN; readfd.events = POLLIN;
if (xiopoll(&readfd, 1, NULL) > 0) { if (xiopoll(&readfd, 1, NULL) > 0) {
break; break;
@ -1239,8 +1241,8 @@ int _xioopen_dgram_recvfrom(struct single *xfd, int xioflags,
continue; continue;
} }
Msg2(level, "poll({%d,,},,-1): %s", xfd->fd, strerror(errno)); Msg2(level, "poll({%d,,},,-1): %s", sfd->fd, strerror(errno));
Close(xfd->fd); Close(sfd->fd);
return STAT_RETRYLATER; return STAT_RETRYLATER;
} while (true); } while (true);
@ -1252,7 +1254,7 @@ int _xioopen_dgram_recvfrom(struct single *xfd, int xioflags,
#if HAVE_STRUCT_MSGHDR_MSGCONTROLLEN #if HAVE_STRUCT_MSGHDR_MSGCONTROLLEN
msgh.msg_controllen = sizeof(ctrlbuff); msgh.msg_controllen = sizeof(ctrlbuff);
#endif #endif
while ((rc = xiogetancillary(xfd->fd, while ((rc = xiogetancillary(sfd->fd,
&msgh, &msgh,
MSG_PEEK MSG_PEEK
#ifdef MSG_TRUNC #ifdef MSG_TRUNC
@ -1267,12 +1269,12 @@ int _xioopen_dgram_recvfrom(struct single *xfd, int xioflags,
sockaddr_info(&pa->soa, palen, peername, sizeof(peername))/*, sockaddr_info(&pa->soa, palen, peername, sizeof(peername))/*,
sockaddr_info(&la->soa, sockname, sizeof(sockname))*/); sockaddr_info(&la->soa, sockname, sizeof(sockname))*/);
xiodopacketinfo(xfd, &msgh, true, true); xiodopacketinfo(sfd, &msgh, true, true);
if (xiocheckpeer(xfd, pa, la) < 0) { if (xiocheckpeer(sfd, pa, la) < 0) {
/* drop packet */ /* drop packet */
char buff[512]; char buff[512];
Recv(xfd->fd, buff, sizeof(buff), 0); Recv(sfd->fd, buff, sizeof(buff), 0);
continue; continue;
} }
Info1("permitting packet from %s", Info1("permitting packet from %s",
@ -1283,12 +1285,12 @@ int _xioopen_dgram_recvfrom(struct single *xfd, int xioflags,
/*xiosetsockaddrenv("SOCK", la, lalen, proto);*/ /*xiosetsockaddrenv("SOCK", la, lalen, proto);*/
xiosetsockaddrenv("PEER", pa, palen, proto); xiosetsockaddrenv("PEER", pa, palen, proto);
applyopts(xfd, -1, opts, PH_FD); applyopts(sfd, -1, opts, PH_FD);
applyopts(xfd, -1, opts, PH_CONNECTED); applyopts(sfd, -1, opts, PH_CONNECTED);
xfd->peersa = *(union sockaddr_union *)pa; sfd->peersa = *(union sockaddr_union *)pa;
xfd->salen = palen; sfd->salen = palen;
if (dofork) { if (dofork) {
Info("Generating socketpair that triggers parent when packet has been consumed"); Info("Generating socketpair that triggers parent when packet has been consumed");
@ -1296,29 +1298,29 @@ int _xioopen_dgram_recvfrom(struct single *xfd, int xioflags,
Error1("socketpair(PF_UNIX, SOCK_STREAM, 0, ...): %s", strerror(errno)); Error1("socketpair(PF_UNIX, SOCK_STREAM, 0, ...): %s", strerror(errno));
} }
if ((pid = xio_fork(false, level, xfd->shutup)) < 0) { if ((pid = xio_fork(false, level, sfd->shutup)) < 0) {
Close(trigger[0]); Close(trigger[0]);
Close(trigger[1]); Close(trigger[1]);
Close(xfd->fd); Close(sfd->fd);
return STAT_RETRYLATER; return STAT_RETRYLATER;
} }
if (pid == 0) { /* child */ if (pid == 0) { /* child */
Close(trigger[0]); Close(trigger[0]);
xfd->triggerfd = trigger[1]; sfd->triggerfd = trigger[1];
Fcntl_l(xfd->triggerfd, F_SETFD, FD_CLOEXEC); Fcntl_l(sfd->triggerfd, F_SETFD, FD_CLOEXEC);
#if WITH_RETRY #if WITH_RETRY
/* !? */ /* !? */
xfd->retry = 0; sfd->retry = 0;
xfd->forever = 0; sfd->forever = 0;
level = E_ERROR; level = E_ERROR;
#endif /* WITH_RETRY */ #endif /* WITH_RETRY */
#if WITH_UNIX #if WITH_UNIX
/* with UNIX sockets: only listening parent is allowed to remove /* with UNIX sockets: only listening parent is allowed to remove
the socket file */ the socket file */
xfd->opt_unlink_close = false; sfd->opt_unlink_close = false;
#endif /* WITH_UNIX */ #endif /* WITH_UNIX */
break; break;
@ -1337,7 +1339,7 @@ int _xioopen_dgram_recvfrom(struct single *xfd, int xioflags,
break; break;
} }
} }
if ((result = _xio_openlate(xfd, opts)) != 0) if ((result = _xio_openlate(sfd, opts)) != 0)
return STAT_NORETRY; return STAT_NORETRY;
return STAT_OK; return STAT_OK;
@ -1345,23 +1347,23 @@ int _xioopen_dgram_recvfrom(struct single *xfd, int xioflags,
/* returns STAT_* */ /* returns STAT_* */
int _xioopen_dgram_recv(struct single *xfd, int xioflags, int _xioopen_dgram_recv(struct single *sfd, int xioflags,
struct sockaddr *us, socklen_t uslen, struct sockaddr *us, socklen_t uslen,
struct opt *opts, int pf, int socktype, int proto, struct opt *opts, int pf, int socktype, int proto,
int level) { int level) {
char *rangename; char *rangename;
if (applyopts_single(xfd, opts, PH_INIT) < 0) return STAT_NORETRY; if (applyopts_single(sfd, opts, PH_INIT) < 0) return STAT_NORETRY;
if ((xfd->fd = xiosocket(opts, pf, socktype, proto, level)) < 0) { if ((sfd->fd = xiosocket(opts, pf, socktype, proto, level)) < 0) {
return STAT_RETRYLATER; return STAT_RETRYLATER;
} }
applyopts(xfd, -1, opts, PH_PASTSOCKET); applyopts(sfd, -1, opts, PH_PASTSOCKET);
applyopts_cloexec(xfd->fd, opts); applyopts_cloexec(sfd->fd, opts);
if (xiobind(xfd, (union sockaddr_union *)us, uslen, opts, pf, 0, level) < 0) { if (xiobind(sfd, (union sockaddr_union *)us, uslen, opts, pf, 0, level) < 0) {
return -1; return -1;
} }
@ -1375,19 +1377,19 @@ int _xioopen_dgram_recv(struct single *xfd, int xioflags,
#if WITH_IP4 /*|| WITH_IP6*/ #if WITH_IP4 /*|| WITH_IP6*/
if (retropt_string(opts, OPT_RANGE, &rangename) >= 0) { if (retropt_string(opts, OPT_RANGE, &rangename) >= 0) {
if (xioparserange(rangename, pf, &xfd->para.socket.range, if (xioparserange(rangename, pf, &sfd->para.socket.range,
xfd->para.socket.ip.ai_flags) sfd->para.socket.ip.ai_flags)
< 0) { < 0) {
free(rangename); free(rangename);
return STAT_NORETRY; return STAT_NORETRY;
} }
free(rangename); free(rangename);
xfd->para.socket.dorange = true; sfd->para.socket.dorange = true;
} }
#endif #endif
#if (WITH_TCP || WITH_UDP) && WITH_LIBWRAP #if (WITH_TCP || WITH_UDP) && WITH_LIBWRAP
xio_retropt_tcpwrap(xfd, opts); xio_retropt_tcpwrap(sfd, opts);
#endif /* && (WITH_TCP || WITH_UDP) && WITH_LIBWRAP */ #endif /* && (WITH_TCP || WITH_UDP) && WITH_LIBWRAP */
if (xioparms.logopt == 'm') { if (xioparms.logopt == 'm') {
@ -1599,15 +1601,15 @@ int xiocheckrange(union sockaddr_union *sa, struct xiorange *range) {
return -1; return -1;
} }
int xiocheckpeer(xiosingle_t *xfd, int xiocheckpeer(xiosingle_t *sfd,
union sockaddr_union *pa, union sockaddr_union *la) { union sockaddr_union *pa, union sockaddr_union *la) {
char infobuff[256]; char infobuff[256];
int result; int result;
#if WITH_IP4 #if WITH_IP4
if (xfd->para.socket.dorange) { if (sfd->para.socket.dorange) {
if (pa == NULL) { return -1; } if (pa == NULL) { return -1; }
if (xiocheckrange(pa, &xfd->para.socket.range) < 0) { if (xiocheckrange(pa, &sfd->para.socket.range) < 0) {
char infobuff[256]; char infobuff[256];
Warn1("refusing connection from %s due to range option", Warn1("refusing connection from %s due to range option",
sockaddr_info(&pa->soa, 0, sockaddr_info(&pa->soa, 0,
@ -1621,11 +1623,11 @@ int xiocheckpeer(xiosingle_t *xfd,
#endif /* WITH_IP4 */ #endif /* WITH_IP4 */
#if WITH_TCP || WITH_UDP #if WITH_TCP || WITH_UDP
if (xfd->para.socket.ip.dosourceport) { if (sfd->para.socket.ip.dosourceport) {
if (pa == NULL) { return -1; } if (pa == NULL) { return -1; }
#if WITH_IP4 #if WITH_IP4
if (pa->soa.sa_family == AF_INET && if (pa->soa.sa_family == AF_INET &&
ntohs(((struct sockaddr_in *)pa)->sin_port) != xfd->para.socket.ip.sourceport) { ntohs(((struct sockaddr_in *)pa)->sin_port) != sfd->para.socket.ip.sourceport) {
Warn1("refusing connection from %s due to wrong sourceport", Warn1("refusing connection from %s due to wrong sourceport",
sockaddr_info(&pa->soa, 0, sockaddr_info(&pa->soa, 0,
infobuff, sizeof(infobuff))); infobuff, sizeof(infobuff)));
@ -1634,7 +1636,7 @@ int xiocheckpeer(xiosingle_t *xfd,
#endif /* WITH_IP4 */ #endif /* WITH_IP4 */
#if WITH_IP6 #if WITH_IP6
if (pa->soa.sa_family == AF_INET6 && if (pa->soa.sa_family == AF_INET6 &&
ntohs(((struct sockaddr_in6 *)pa)->sin6_port) != xfd->para.socket.ip.sourceport) { ntohs(((struct sockaddr_in6 *)pa)->sin6_port) != sfd->para.socket.ip.sourceport) {
Warn1("refusing connection from %s due to wrong sourceport", Warn1("refusing connection from %s due to wrong sourceport",
sockaddr_info(&pa->soa, 0, sockaddr_info(&pa->soa, 0,
infobuff, sizeof(infobuff))); infobuff, sizeof(infobuff)));
@ -1644,7 +1646,7 @@ int xiocheckpeer(xiosingle_t *xfd,
Info1("permitting connection from %s due to sourceport option", Info1("permitting connection from %s due to sourceport option",
sockaddr_info(&pa->soa, 0, sockaddr_info(&pa->soa, 0,
infobuff, sizeof(infobuff))); infobuff, sizeof(infobuff)));
} else if (xfd->para.socket.ip.lowport) { } else if (sfd->para.socket.ip.lowport) {
if (pa == NULL) { return -1; } if (pa == NULL) { return -1; }
if (pa->soa.sa_family == AF_INET && if (pa->soa.sa_family == AF_INET &&
ntohs(((struct sockaddr_in *)pa)->sin_port) >= IPPORT_RESERVED) { ntohs(((struct sockaddr_in *)pa)->sin_port) >= IPPORT_RESERVED) {
@ -1670,7 +1672,7 @@ int xiocheckpeer(xiosingle_t *xfd,
#endif /* WITH_TCP || WITH_UDP */ #endif /* WITH_TCP || WITH_UDP */
#if (WITH_TCP || WITH_UDP) && WITH_LIBWRAP #if (WITH_TCP || WITH_UDP) && WITH_LIBWRAP
result = xio_tcpwrap_check(xfd, la, pa); result = xio_tcpwrap_check(sfd, la, pa);
if (result < 0) { if (result < 0) {
char infobuff[256]; char infobuff[256];
Warn1("refusing connection from %s due to tcpwrapper option", Warn1("refusing connection from %s due to tcpwrapper option",
@ -2052,7 +2054,7 @@ xiosocketpair(struct opt *opts, int pf, int socktype, int proto, int sv[2]) {
} }
int xiobind( int xiobind(
struct single *xfd, struct single *sfd,
union sockaddr_union *us, union sockaddr_union *us,
size_t uslen, size_t uslen,
struct opt *opts, struct opt *opts,
@ -2068,8 +2070,8 @@ int xiobind(
applyopts_named(us->un.sun_path, opts, PH_PREOPEN); applyopts_named(us->un.sun_path, opts, PH_PREOPEN);
} }
#endif #endif
applyopts(xfd, xfd->fd, opts, PH_PREBIND); applyopts(sfd, sfd->fd, opts, PH_PREBIND);
applyopts(xfd, xfd->fd, opts, PH_BIND); applyopts(sfd, sfd->fd, opts, PH_BIND);
#if WITH_TCP || WITH_UDP #if WITH_TCP || WITH_UDP
if (alt) { if (alt) {
union sockaddr_union sin, *sinp; union sockaddr_union sin, *sinp;
@ -2125,13 +2127,13 @@ int xiobind(
i = N = XIO_IPPORT_LOWER + dv.rem; i = N = XIO_IPPORT_LOWER + dv.rem;
do { /* loop over lowport bind() attempts */ do { /* loop over lowport bind() attempts */
*port = htons(i); *port = htons(i);
if (Bind(xfd->fd, &sinp->soa, sizeof(*sinp)) < 0) { if (Bind(sfd->fd, &sinp->soa, sizeof(*sinp)) < 0) {
Msg4(errno==EADDRINUSE?E_INFO:level, Msg4(errno==EADDRINUSE?E_INFO:level,
"bind(%d, {%s}, "F_Zd"): %s", xfd->fd, "bind(%d, {%s}, "F_Zd"): %s", sfd->fd,
sockaddr_info(&sinp->soa, sizeof(*sinp), infobuff, sizeof(infobuff)), sockaddr_info(&sinp->soa, sizeof(*sinp), infobuff, sizeof(infobuff)),
sizeof(*sinp), strerror(errno)); sizeof(*sinp), strerror(errno));
if (errno != EADDRINUSE) { if (errno != EADDRINUSE) {
Close(xfd->fd); Close(sfd->fd);
return STAT_RETRYLATER; return STAT_RETRYLATER;
} }
} else { } else {
@ -2141,7 +2143,7 @@ int xiobind(
if (i == N) { if (i == N) {
Msg(level, "no low port available"); Msg(level, "no low port available");
/*errno = EADDRINUSE; still assigned */ /*errno = EADDRINUSE; still assigned */
Close(xfd->fd); Close(sfd->fd);
return STAT_RETRYLATER; return STAT_RETRYLATER;
} }
} while (i != N); } while (i != N);
@ -2154,11 +2156,11 @@ int xiobind(
applyopts_named(us->un.sun_path, opts, PH_PREOPEN); applyopts_named(us->un.sun_path, opts, PH_PREOPEN);
} }
#endif #endif
if (Bind(xfd->fd, &us->soa, uslen) < 0) { if (Bind(sfd->fd, &us->soa, uslen) < 0) {
Msg4(level, "bind(%d, {%s}, "F_Zd"): %s", Msg4(level, "bind(%d, {%s}, "F_Zd"): %s",
xfd->fd, sockaddr_info(&us->soa, uslen, infobuff, sizeof(infobuff)), sfd->fd, sockaddr_info(&us->soa, uslen, infobuff, sizeof(infobuff)),
uslen, strerror(errno)); uslen, strerror(errno));
Close(xfd->fd); Close(sfd->fd);
return STAT_RETRYLATER; return STAT_RETRYLATER;
} }
} }
@ -2168,7 +2170,7 @@ int xiobind(
} }
#endif #endif
applyopts(xfd, -1, opts, PH_PASTBIND); applyopts(sfd, -1, opts, PH_PASTBIND);
return 0; return 0;
} }

View file

@ -14,8 +14,7 @@
#if WITH_SOCKETPAIR #if WITH_SOCKETPAIR
static int xioopen_socketpair(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *xfd, groups_t groups, int dummy1, int dummy2, int dummy3); static int xioopen_socketpair(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *xfd, const struct addrdesc *addrdesc);
const struct addrdesc xioaddr_socketpair = { "SOCKETPAIR", 3, xioopen_socketpair, GROUP_FD|GROUP_SOCKET, 0, 0, 0 HELP(":<filename>") }; const struct addrdesc xioaddr_socketpair = { "SOCKETPAIR", 3, xioopen_socketpair, GROUP_FD|GROUP_SOCKET, 0, 0, 0 HELP(":<filename>") };
@ -27,10 +26,7 @@ static int xioopen_socketpair(
struct opt *opts, struct opt *opts,
int xioflags, int xioflags,
xiofile_t *xfd, xiofile_t *xfd,
groups_t groups , const struct addrdesc *addrdesc)
int dummy1,
int dummy2,
int dummy3)
{ {
struct single *sfd = &xfd->stream; struct single *sfd = &xfd->stream;
struct opt *opts2; struct opt *opts2;
@ -41,7 +37,8 @@ static int xioopen_socketpair(
int result; int result;
if (argc != 1) { if (argc != 1) {
Error2("%s: wrong number of parameters (%d instead of 1)", argv[0], argc-1); xio_syntax(argv[0], 1, argc-1, addrdesc->syntax);
return STAT_NORETRY;
} }
sfd->para.bipipe.socktype = SOCK_DGRAM; sfd->para.bipipe.socktype = SOCK_DGRAM;

View file

@ -27,10 +27,7 @@ enum {
#define SOCKSPORT "1080" #define SOCKSPORT "1080"
#define BUFF_LEN (SIZEOF_STRUCT_SOCKS4+512) #define BUFF_LEN (SIZEOF_STRUCT_SOCKS4+512)
static int xioopen_socks4_connect(int argc, const char *argv[], struct opt *opts, static int xioopen_socks4_connect(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *fd, const struct addrdesc *addrdesc);
int xioflags, xiofile_t *fd,
groups_t groups, int dummy1, int dummy2,
int dummy3);
const struct optdesc opt_socksport = { "socksport", NULL, OPT_SOCKSPORT, GROUP_IP_SOCKS4, PH_LATE, TYPE_STRING, OFUNC_SPEC }; const struct optdesc opt_socksport = { "socksport", NULL, OPT_SOCKSPORT, GROUP_IP_SOCKS4, PH_LATE, TYPE_STRING, OFUNC_SPEC };
const struct optdesc opt_socksuser = { "socksuser", NULL, OPT_SOCKSUSER, GROUP_IP_SOCKS4, PH_LATE, TYPE_NAME, OFUNC_SPEC }; const struct optdesc opt_socksuser = { "socksuser", NULL, OPT_SOCKSUSER, GROUP_IP_SOCKS4, PH_LATE, TYPE_NAME, OFUNC_SPEC };
@ -39,12 +36,17 @@ const struct addrdesc xioaddr_socks4_connect = { "SOCKS4", 3, xioopen_socks4_con
const struct addrdesc xioaddr_socks4a_connect = { "SOCKS4A", 3, xioopen_socks4_connect, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP4|GROUP_SOCK_IP6|GROUP_IP_TCP|GROUP_IP_SOCKS4|GROUP_CHILD|GROUP_RETRY, 1, 0, 0 HELP(":<socks-server>:<host>:<port>") }; const struct addrdesc xioaddr_socks4a_connect = { "SOCKS4A", 3, xioopen_socks4_connect, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP4|GROUP_SOCK_IP6|GROUP_IP_TCP|GROUP_IP_SOCKS4|GROUP_CHILD|GROUP_RETRY, 1, 0, 0 HELP(":<socks-server>:<host>:<port>") };
static int xioopen_socks4_connect(int argc, const char *argv[], struct opt *opts, static int xioopen_socks4_connect(
int xioflags, xiofile_t *xxfd, int argc,
groups_t groups, int socks4a, int dummy2, const char *argv[],
int dummy3) { struct opt *opts,
int xioflags,
xiofile_t *xxfd,
const struct addrdesc *addrdesc)
{
/* we expect the form: host:host:port */ /* we expect the form: host:host:port */
struct single *xfd = &xxfd->stream; struct single *sfd = &xxfd->stream;
int socks4a = addrdesc->arg1;
struct opt *opts0 = NULL; struct opt *opts0 = NULL;
const char *sockdname; char *socksport; const char *sockdname; char *socksport;
const char *targetname, *targetport; const char *targetname, *targetport;
@ -67,16 +69,16 @@ static int xioopen_socks4_connect(int argc, const char *argv[], struct opt *opts
int result; int result;
if (argc != 4) { if (argc != 4) {
Error1("%s: 3 parameters required", argv[0]); xio_syntax(argv[0], 3, argc-1, addrdesc->syntax);
return STAT_NORETRY; return STAT_NORETRY;
} }
sockdname = argv[1]; sockdname = argv[1];
targetname = argv[2]; targetname = argv[2];
targetport = argv[3]; targetport = argv[3];
xfd->howtoend = END_SHUTDOWN; sfd->howtoend = END_SHUTDOWN;
if (applyopts_single(xfd, opts, PH_INIT) < 0) return -1; if (applyopts_single(sfd, opts, PH_INIT) < 0) return -1;
applyopts(xfd, 1, opts, PH_INIT); applyopts(sfd, 1, opts, PH_INIT);
retropt_int(opts, OPT_SO_TYPE, &socktype); retropt_int(opts, OPT_SO_TYPE, &socktype);
@ -99,7 +101,7 @@ static int xioopen_socks4_connect(int argc, const char *argv[], struct opt *opts
result = result =
_xioopen_ipapp_prepare(opts, &opts0, sockdname, socksport, _xioopen_ipapp_prepare(opts, &opts0, sockdname, socksport,
&pf, ipproto, &pf, ipproto,
xfd->para.socket.ip.ai_flags, sfd->para.socket.ip.ai_flags,
&themlist, us, &uslen, &themlist, us, &uslen,
&needbind, &lowport, socktype); &needbind, &lowport, socktype);
@ -119,15 +121,16 @@ static int xioopen_socks4_connect(int argc, const char *argv[], struct opt *opts
/* we try to resolve the target address _before_ connecting to the socks /* we try to resolve the target address _before_ connecting to the socks
server: this avoids unnecessary socks connects and timeouts */ server: this avoids unnecessary socks connects and timeouts */
result = result =
_xioopen_socks4_connect0(xfd, targetname, socks4a, sockhead, _xioopen_socks4_connect0(sfd, targetname, socks4a, sockhead,
(ssize_t *)&buflen, level); (ssize_t *)&buflen, level);
switch (result) { switch (result) {
case STAT_OK: break; case STAT_OK: break;
#if WITH_RETRY #if WITH_RETRY
case STAT_RETRYLATER: case STAT_RETRYLATER:
case STAT_RETRYNOW: case STAT_RETRYNOW:
if (xfd->forever || xfd->retry--) { if (sfd->forever || sfd->retry--) {
if (result == STAT_RETRYLATER) Nanosleep(&xfd->intervall, NULL); if (result == STAT_RETRYLATER)
Nanosleep(&sfd->intervall, NULL);
continue; continue;
} }
#endif /* WITH_RETRY */ #endif /* WITH_RETRY */
@ -143,7 +146,7 @@ static int xioopen_socks4_connect(int argc, const char *argv[], struct opt *opts
sockaddr_info(themp->ai_addr, themp->ai_addrlen, sockaddr_info(themp->ai_addr, themp->ai_addrlen,
infobuff, sizeof(infobuff))); infobuff, sizeof(infobuff)));
#if WITH_RETRY #if WITH_RETRY
if (xfd->forever || xfd->retry || ai_sorted[i] != NULL) { if (sfd->forever || sfd->retry || ai_sorted[i] != NULL) {
level = E_INFO; level = E_INFO;
} else } else
#endif /* WITH_RETRY */ #endif /* WITH_RETRY */
@ -151,27 +154,25 @@ static int xioopen_socks4_connect(int argc, const char *argv[], struct opt *opts
/* this cannot fork because we retrieved fork option above */ /* this cannot fork because we retrieved fork option above */
result = result =
_xioopen_connect(xfd, _xioopen_connect(sfd,
needbind?us:NULL, sizeof(*us), needbind?us:NULL, sizeof(*us),
themp->ai_addr, themp->ai_addrlen, themp->ai_addr, themp->ai_addrlen,
opts, pf?pf:themp->ai_family, socktype, IPPROTO_TCP, opts, pf?pf:themp->ai_family, socktype, IPPROTO_TCP, lowport, level);
lowport, level);
if (result == STAT_OK) if (result == STAT_OK)
break; break;
themp = ai_sorted[i++]; themp = ai_sorted[i++];
if (themp == NULL) { if (themp == NULL)
result = STAT_RETRYLATER; result = STAT_RETRYLATER;
}
} }
switch (result) { switch (result) {
case STAT_OK: break; case STAT_OK: break;
#if WITH_RETRY #if WITH_RETRY
case STAT_RETRYLATER: case STAT_RETRYLATER:
case STAT_RETRYNOW: case STAT_RETRYNOW:
if (xfd->forever || xfd->retry) { if (sfd->forever || sfd->retry) {
--xfd->retry; --sfd->retry;
if (result == STAT_RETRYLATER) if (result == STAT_RETRYLATER)
Nanosleep(&xfd->intervall, NULL); Nanosleep(&sfd->intervall, NULL);
continue; continue;
} }
#endif /* WITH_RETRY */ #endif /* WITH_RETRY */
@ -181,19 +182,19 @@ static int xioopen_socks4_connect(int argc, const char *argv[], struct opt *opts
return result; return result;
} }
xiofreeaddrinfo(themlist); xiofreeaddrinfo(themlist);
applyopts(xfd, -1, opts, PH_ALL); applyopts(sfd, -1, opts, PH_ALL);
if ((result = _xio_openlate(xfd, opts)) < 0) if ((result = _xio_openlate(sfd, opts)) < 0)
return result; return result;
result = _xioopen_socks4_connect(xfd, sockhead, buflen, level); result = _xioopen_socks4_connect(sfd, sockhead, buflen, level);
switch (result) { switch (result) {
case STAT_OK: break; case STAT_OK: break;
#if WITH_RETRY #if WITH_RETRY
case STAT_RETRYLATER: case STAT_RETRYLATER:
case STAT_RETRYNOW: case STAT_RETRYNOW:
if (xfd->forever || xfd->retry--) { if (sfd->forever || sfd->retry--) {
if (result == STAT_RETRYLATER) Nanosleep(&xfd->intervall, NULL); if (result == STAT_RETRYLATER) Nanosleep(&sfd->intervall, NULL);
continue; continue;
} }
#endif /* WITH_RETRY */ #endif /* WITH_RETRY */
@ -209,26 +210,27 @@ static int xioopen_socks4_connect(int argc, const char *argv[], struct opt *opts
if (dofork) { if (dofork) {
pid_t pid; pid_t pid;
int level = E_ERROR; int level = E_ERROR;
if (xfd->forever || xfd->retry) { if (sfd->forever || sfd->retry) {
level = E_WARN; /* most users won't expect a problem here, level = E_WARN; /* most users won't expect a problem here,
so Notice is too weak */ so Notice is too weak */
} }
while ((pid = xio_fork(false, level, xfd->shutup)) < 0) { while ((pid = xio_fork(false, level, sfd->shutup)) < 0) {
if (xfd->forever || --xfd->retry) { if (sfd->forever || --sfd->retry) {
Nanosleep(&xfd->intervall, NULL); Nanosleep(&sfd->intervall, NULL);
continue; continue;
} }
return STAT_RETRYLATER; return STAT_RETRYLATER;
} }
if (pid == 0) { /* child process */ if (pid == 0) { /* child process */
xfd->forever = false; xfd->retry = 0; sfd->forever = false;
sfd->retry = 0;
break; break;
} }
/* parent process */ /* parent process */
Close(xfd->fd); Close(sfd->fd);
Nanosleep(&xfd->intervall, NULL); Nanosleep(&sfd->intervall, NULL);
dropopts(opts, PH_ALL); opts = copyopts(opts0, GROUP_ALL); dropopts(opts, PH_ALL); opts = copyopts(opts0, GROUP_ALL);
continue; continue;
} else } else
@ -282,7 +284,7 @@ int _xioopen_socks4_prepare(const char *targetport, struct opt *opts, char **soc
/* called within retry/fork loop, before connect() */ /* called within retry/fork loop, before connect() */
int int
_xioopen_socks4_connect0(struct single *xfd, _xioopen_socks4_connect0(struct single *sfd,
const char *hostname, /* socks target host */ const char *hostname, /* socks target host */
int socks4a, int socks4a,
struct socks4 *sockhead, struct socks4 *sockhead,
@ -298,7 +300,7 @@ int
if ((result = xioresolve(hostname, NULL, if ((result = xioresolve(hostname, NULL,
PF_INET, SOCK_STREAM, IPPROTO_TCP, PF_INET, SOCK_STREAM, IPPROTO_TCP,
&sau, &saulen, &sau, &saulen,
xfd->para.socket.ip.ai_flags)) sfd->para.socket.ip.ai_flags))
!= STAT_OK) { != STAT_OK) {
return result; /*! STAT_RETRY? */ return result; /*! STAT_RETRY? */
} }
@ -330,7 +332,7 @@ int
/* perform socks4 client dialog on existing FD. /* perform socks4 client dialog on existing FD.
Called within fork/retry loop, after connect() */ Called within fork/retry loop, after connect() */
int _xioopen_socks4_connect(struct single *xfd, int _xioopen_socks4_connect(struct single *sfd,
struct socks4 *sockhead, struct socks4 *sockhead,
size_t headlen, size_t headlen,
int level) { int level) {
@ -365,11 +367,11 @@ int _xioopen_socks4_connect(struct single *xfd,
} }
} }
#endif /* WITH_MSGLEVEL <= E_DEBUG */ #endif /* WITH_MSGLEVEL <= E_DEBUG */
if (writefull(xfd->fd, sockhead, headlen) < 0) { if (writefull(sfd->fd, sockhead, headlen) < 0) {
Msg4(level, "write(%d, %p, "F_Zu"): %s", Msg4(level, "write(%d, %p, "F_Zu"): %s",
xfd->fd, sockhead, headlen, strerror(errno)); sfd->fd, sockhead, headlen, strerror(errno));
if (Close(xfd->fd) < 0) { if (Close(sfd->fd) < 0) {
Info2("close(%d): %s", xfd->fd, strerror(errno)); Info2("close(%d): %s", sfd->fd, strerror(errno));
} }
return STAT_RETRYLATER; /* retry complete open cycle */ return STAT_RETRYLATER; /* retry complete open cycle */
} }
@ -379,20 +381,20 @@ int _xioopen_socks4_connect(struct single *xfd,
while (bytes >= 0) { /* loop over answer chunks until complete or error */ while (bytes >= 0) { /* loop over answer chunks until complete or error */
/* receive socks answer */ /* receive socks answer */
do { do {
result = Read(xfd->fd, buff+bytes, SIZEOF_STRUCT_SOCKS4-bytes); result = Read(sfd->fd, buff+bytes, SIZEOF_STRUCT_SOCKS4-bytes);
} while (result < 0 && errno == EINTR); } while (result < 0 && errno == EINTR);
if (result < 0) { if (result < 0) {
Msg4(level, "read(%d, %p, "F_Zu"): %s", Msg4(level, "read(%d, %p, "F_Zu"): %s",
xfd->fd, buff+bytes, SIZEOF_STRUCT_SOCKS4-bytes, sfd->fd, buff+bytes, SIZEOF_STRUCT_SOCKS4-bytes,
strerror(errno)); strerror(errno));
if (Close(xfd->fd) < 0) { if (Close(sfd->fd) < 0) {
Info2("close(%d): %s", xfd->fd, strerror(errno)); Info2("close(%d): %s", sfd->fd, strerror(errno));
} }
} }
if (result == 0) { if (result == 0) {
Msg(level, "read(): EOF during read of socks reply, peer might not be a socks4 server"); Msg(level, "read(): EOF during read of socks reply, peer might not be a socks4 server");
if (Close(xfd->fd) < 0) { if (Close(sfd->fd) < 0) {
Info2("close(%d): %s", xfd->fd, strerror(errno)); Info2("close(%d): %s", sfd->fd, strerror(errno));
} }
return STAT_RETRYLATER; return STAT_RETRYLATER;
} }
@ -431,9 +433,9 @@ int _xioopen_socks4_connect(struct single *xfd,
case SOCKS_CD_GRANTED: case SOCKS_CD_GRANTED:
/* Notice("socks: connect request succeeded"); */ /* Notice("socks: connect request succeeded"); */
#if 0 #if 0
if (Getsockname(xfd->fd, (struct sockaddr *)&us, &uslen) < 0) { if (Getsockname(sfd->fd, (struct sockaddr *)&us, &uslen) < 0) {
Warn4("getsockname(%d, %p, {%d}): %s", Warn4("getsockname(%d, %p, {%d}): %s",
xfd->fd, &us, uslen, strerror(errno)); sfd->fd, &us, uslen, strerror(errno));
} }
Notice1("successfully connected from %s via socks4", Notice1("successfully connected from %s via socks4",
sockaddr_info((struct sockaddr *)&us, infobuff, sizeof(infobuff))); sockaddr_info((struct sockaddr *)&us, infobuff, sizeof(infobuff)));

View file

@ -48,10 +48,7 @@
#define SOCKS5_STATUS_COMMAND_NOT_SUPPORTED 7 #define SOCKS5_STATUS_COMMAND_NOT_SUPPORTED 7
#define SOCKS5_STATUS_ADDRESS_TYPE_NOT_SUPPORTED 8 #define SOCKS5_STATUS_ADDRESS_TYPE_NOT_SUPPORTED 8
static int xioopen_socks5(int argc, const char *argv[], struct opt *opts, static int xioopen_socks5(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *xxfd, const struct addrdesc *addrdesc);
int xioflags, xiofile_t *xxfd,
groups_t groups, int dummy1, int dummy2,
int dummy3);
const struct addrdesc xioaddr_socks5_connect = { "SOCKS5-CONNECT", 1+XIO_RDWR, xioopen_socks5, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP4|GROUP_SOCK_IP6|GROUP_IP_TCP|GROUP_CHILD|GROUP_RETRY, SOCKS5_COMMAND_CONNECT, 0, 0 HELP(":<socks-server>:<socks-port>:<target-host>:<target-port>") }; const struct addrdesc xioaddr_socks5_connect = { "SOCKS5-CONNECT", 1+XIO_RDWR, xioopen_socks5, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP4|GROUP_SOCK_IP6|GROUP_IP_TCP|GROUP_CHILD|GROUP_RETRY, SOCKS5_COMMAND_CONNECT, 0, 0 HELP(":<socks-server>:<socks-port>:<target-host>:<target-port>") };
@ -92,7 +89,7 @@ static const char * _xioopen_socks5_strerror(uint8_t r)
* send(0x050100) followed by "return read() == 0x0500", but will be easier to * send(0x050100) followed by "return read() == 0x0500", but will be easier to
* extend for other auth mode support. * extend for other auth mode support.
*/ */
static int _xioopen_socks5_handshake(struct single *xfd, int level) static int _xioopen_socks5_handshake(struct single *sfd, int level)
{ {
int result; int result;
ssize_t bytes; ssize_t bytes;
@ -106,8 +103,8 @@ static int _xioopen_socks5_handshake(struct single *xfd, int level)
if (client_hello == NULL) { if (client_hello == NULL) {
Msg2(level, "malloc(%d): %s", Msg2(level, "malloc(%d): %s",
client_hello_size, strerror(errno)); client_hello_size, strerror(errno));
if (Close(xfd->fd) < 0) { if (Close(sfd->fd) < 0) {
Info2("close(%d): %s", xfd->fd, strerror(errno)); Info2("close(%d): %s", sfd->fd, strerror(errno));
} }
/* malloc failed - could succeed later, so retry then */ /* malloc failed - could succeed later, so retry then */
@ -138,12 +135,12 @@ static int _xioopen_socks5_handshake(struct single *xfd, int level)
} }
#endif #endif
if (writefull(xfd->fd, client_hello, client_hello_size) < 0) { if (writefull(sfd->fd, client_hello, client_hello_size) < 0) {
Msg4(level, "write(%d, %p, %d): %s", Msg4(level, "write(%d, %p, %d): %s",
xfd->fd, client_hello, client_hello_size, sfd->fd, client_hello, client_hello_size,
strerror(errno)); strerror(errno));
if (Close(xfd->fd) < 0) { if (Close(sfd->fd) < 0) {
Info2("close(%d): %s", xfd->fd, strerror(errno)); Info2("close(%d): %s", sfd->fd, strerror(errno));
} }
free(client_hello); free(client_hello);
@ -156,22 +153,22 @@ static int _xioopen_socks5_handshake(struct single *xfd, int level)
Info("waiting for socks5 reply"); Info("waiting for socks5 reply");
while (bytes >= 0) { while (bytes >= 0) {
do { do {
result = Read(xfd->fd, server_hello_ptr + bytes, result = Read(sfd->fd, server_hello_ptr + bytes,
sizeof(struct socks5_server_hello)-bytes); sizeof(struct socks5_server_hello)-bytes);
} while (result < 0 && errno == EINTR); } while (result < 0 && errno == EINTR);
if (result < 0) { if (result < 0) {
Msg4(level, "read(%d, %p, "F_Zu"): %s", Msg4(level, "read(%d, %p, "F_Zu"): %s",
xfd->fd, server_hello_ptr + bytes, sfd->fd, server_hello_ptr + bytes,
sizeof(struct socks5_server_hello)-bytes, sizeof(struct socks5_server_hello)-bytes,
strerror(errno)); strerror(errno));
if (Close(xfd->fd) < 0) { if (Close(sfd->fd) < 0) {
Info2("close(%d): %s", xfd->fd, strerror(errno)); Info2("close(%d): %s", sfd->fd, strerror(errno));
} }
} }
if (result == 0) { if (result == 0) {
Msg(level, "read(): EOF during read of SOCKS5 server hello, peer might not be a SOCKS5 server"); Msg(level, "read(): EOF during read of SOCKS5 server hello, peer might not be a SOCKS5 server");
if (Close(xfd->fd) < 0) { if (Close(sfd->fd) < 0) {
Info2("close(%d): %s", xfd->fd, Info2("close(%d): %s", sfd->fd,
strerror(errno)); strerror(errno));
} }
@ -197,16 +194,16 @@ static int _xioopen_socks5_handshake(struct single *xfd, int level)
if (server_hello.version != SOCKS5_VERSION) { if (server_hello.version != SOCKS5_VERSION) {
Msg2(level, "SOCKS5 Server Hello version was %d, not the expected %d, peer might not be a SOCKS5 server", Msg2(level, "SOCKS5 Server Hello version was %d, not the expected %d, peer might not be a SOCKS5 server",
server_hello.version, SOCKS5_VERSION); server_hello.version, SOCKS5_VERSION);
if (Close(xfd->fd) < 0) { if (Close(sfd->fd) < 0) {
Info2("close(%d): %s", xfd->fd, strerror(errno)); Info2("close(%d): %s", sfd->fd, strerror(errno));
} }
return STAT_RETRYLATER; return STAT_RETRYLATER;
} }
if (server_hello.method == SOCKS5_AUTH_FAIL) { if (server_hello.method == SOCKS5_AUTH_FAIL) {
Msg(level, "SOCKS5 authentication negotiation failed - client & server have no common supported methods"); Msg(level, "SOCKS5 authentication negotiation failed - client & server have no common supported methods");
if (Close(xfd->fd) < 0) { if (Close(sfd->fd) < 0) {
Info2("close(%d): %s", xfd->fd, strerror(errno)); Info2("close(%d): %s", sfd->fd, strerror(errno));
} }
return STAT_RETRYLATER; return STAT_RETRYLATER;
} }
@ -214,8 +211,8 @@ static int _xioopen_socks5_handshake(struct single *xfd, int level)
if (server_hello.method != SOCKS5_AUTH_NONE) { if (server_hello.method != SOCKS5_AUTH_NONE) {
Msg1(level, "SOCKS5 server requested unsupported auth method (%d)", Msg1(level, "SOCKS5 server requested unsupported auth method (%d)",
server_hello.method); server_hello.method);
if (Close(xfd->fd) < 0) { if (Close(sfd->fd) < 0) {
Info2("close(%d): %s", xfd->fd, strerror(errno)); Info2("close(%d): %s", sfd->fd, strerror(errno));
} }
return STAT_RETRYLATER; return STAT_RETRYLATER;
} }
@ -303,7 +300,7 @@ static struct socks5_request *_xioopen_socks5_prepare_request(
* Reads a server reply after a request has been sent * Reads a server reply after a request has been sent
*/ */
static int _xioopen_socks5_read_reply( static int _xioopen_socks5_read_reply(
struct single *xfd, struct socks5_reply *reply, int level) struct single *sfd, struct socks5_reply *reply, int level)
{ {
int result = 0; int result = 0;
int bytes_read = 0; int bytes_read = 0;
@ -313,24 +310,24 @@ static int _xioopen_socks5_read_reply(
while (bytes_to_read >= 0) { while (bytes_to_read >= 0) {
Info("reading SOCKS5 reply"); Info("reading SOCKS5 reply");
do { do {
result = Read(xfd->fd, result = Read(sfd->fd,
((unsigned char *)reply) + bytes_read, ((unsigned char *)reply) + bytes_read,
bytes_to_read-bytes_read); bytes_to_read-bytes_read);
} while (result < 0 && errno == EINTR); } while (result < 0 && errno == EINTR);
if (result < 0) { if (result < 0) {
Msg4(level, "read(%d, %p, %d): %s", Msg4(level, "read(%d, %p, %d): %s",
xfd->fd, ((unsigned char *)reply) + bytes_read, sfd->fd, ((unsigned char *)reply) + bytes_read,
bytes_to_read-bytes_read, strerror(errno)); bytes_to_read-bytes_read, strerror(errno));
if (Close(xfd->fd) < 0) { if (Close(sfd->fd) < 0) {
Info2("close(%d): %s", xfd->fd, strerror(errno)); Info2("close(%d): %s", sfd->fd, strerror(errno));
} }
return STAT_RETRYLATER; return STAT_RETRYLATER;
} }
if (result == 0) { if (result == 0) {
Msg(level, "read(): EOF during read of SOCKS5 reply"); Msg(level, "read(): EOF during read of SOCKS5 reply");
if (Close(xfd->fd) < 0) { if (Close(sfd->fd) < 0) {
Info2("close(%d): %s", Info2("close(%d): %s",
xfd->fd, strerror(errno)); sfd->fd, strerror(errno));
} }
return STAT_RETRYLATER; return STAT_RETRYLATER;
} }
@ -356,9 +353,9 @@ static int _xioopen_socks5_read_reply(
default: default:
Msg1(level, "invalid SOCKS5 reply address type (%d)", Msg1(level, "invalid SOCKS5 reply address type (%d)",
reply->address_type); reply->address_type);
if (Close(xfd->fd) < 0) { if (Close(sfd->fd) < 0) {
Info2("close(%d): %s", Info2("close(%d): %s",
xfd->fd, strerror(errno)); sfd->fd, strerror(errno));
} }
return STAT_RETRYLATER; return STAT_RETRYLATER;
} }
@ -388,7 +385,7 @@ static int _xioopen_socks5_read_reply(
* If command is BIND we receive two replies. * If command is BIND we receive two replies.
*/ */
static int _xioopen_socks5_request( static int _xioopen_socks5_request(
struct single *xfd, const char *target_name, const char *target_port, struct single *sfd, const char *target_name, const char *target_port,
uint8_t socks_command, int level) uint8_t socks_command, int level)
{ {
struct socks5_request *req; struct socks5_request *req;
@ -397,8 +394,8 @@ static int _xioopen_socks5_request(
req = _xioopen_socks5_prepare_request(&bytes, target_name, target_port, req = _xioopen_socks5_prepare_request(&bytes, target_name, target_port,
socks_command, level); socks_command, level);
if (req == NULL) { if (req == NULL) {
if (Close(xfd->fd) < 0) { if (Close(sfd->fd) < 0) {
Info2("close(%d): %s", xfd->fd, strerror(errno)); Info2("close(%d): %s", sfd->fd, strerror(errno));
} }
/* Prepare_request could fail due to malloc, but most likely /* Prepare_request could fail due to malloc, but most likely
@ -420,11 +417,11 @@ static int _xioopen_socks5_request(
} }
#endif #endif
if (writefull(xfd->fd, req, bytes) < 0) { if (writefull(sfd->fd, req, bytes) < 0) {
Msg4(level, "write(%d, %p, %d): %s", Msg4(level, "write(%d, %p, %d): %s",
xfd->fd, req, bytes, strerror(errno)); sfd->fd, req, bytes, strerror(errno));
if (Close(xfd->fd) < 0) { if (Close(sfd->fd) < 0) {
Info2("close(%d): %s", xfd->fd, strerror(errno)); Info2("close(%d): %s", sfd->fd, strerror(errno));
} }
free(req); free(req);
return STAT_RETRYLATER; return STAT_RETRYLATER;
@ -434,14 +431,14 @@ static int _xioopen_socks5_request(
struct socks5_reply *reply = Malloc(SOCKS5_MAX_REPLY_SIZE); struct socks5_reply *reply = Malloc(SOCKS5_MAX_REPLY_SIZE);
if (reply == NULL) { if (reply == NULL) {
if (Close(xfd->fd) < 0) { if (Close(sfd->fd) < 0) {
Info2("close(%d): %s", xfd->fd, strerror(errno)); Info2("close(%d): %s", sfd->fd, strerror(errno));
} }
return STAT_RETRYLATER; return STAT_RETRYLATER;
} }
result = _xioopen_socks5_read_reply(xfd, reply, level); result = _xioopen_socks5_read_reply(sfd, reply, level);
if (result != STAT_OK) { if (result != STAT_OK) {
free(reply); free(reply);
return result; return result;
@ -454,8 +451,8 @@ static int _xioopen_socks5_request(
if (reply->version != SOCKS5_VERSION) { if (reply->version != SOCKS5_VERSION) {
Msg2(level, "SOCKS5 reply version was %d, not the expected %d, peer might not be a SOCKS5 server", Msg2(level, "SOCKS5 reply version was %d, not the expected %d, peer might not be a SOCKS5 server",
reply->version, SOCKS5_VERSION); reply->version, SOCKS5_VERSION);
if (Close(xfd->fd) < 0) { if (Close(sfd->fd) < 0) {
Info2("close(%d): %s", xfd->fd, strerror(errno)); Info2("close(%d): %s", sfd->fd, strerror(errno));
} }
free(reply); free(reply);
return STAT_RETRYLATER; return STAT_RETRYLATER;
@ -466,7 +463,7 @@ static int _xioopen_socks5_request(
Notice("listening on remote host, waiting for connection"); Notice("listening on remote host, waiting for connection");
/* TODO: nicer debug output */ /* TODO: nicer debug output */
/* For BIND, we read two replies */ /* For BIND, we read two replies */
result = _xioopen_socks5_read_reply(xfd, reply, level); result = _xioopen_socks5_read_reply(sfd, reply, level);
if (result != STAT_OK) { if (result != STAT_OK) {
free(reply); free(reply);
return result; return result;
@ -484,8 +481,8 @@ static int _xioopen_socks5_request(
Msg2(level, "SOCKS5 server error %d: %s", Msg2(level, "SOCKS5 server error %d: %s",
reply->reply, reply->reply,
_xioopen_socks5_strerror(reply->reply)); _xioopen_socks5_strerror(reply->reply));
if (Close(xfd->fd) < 0) { if (Close(sfd->fd) < 0) {
Info2("close(%d): %s", xfd->fd, strerror(errno)); Info2("close(%d): %s", sfd->fd, strerror(errno));
} }
free(reply); free(reply);
return STAT_RETRYLATER; return STAT_RETRYLATER;
@ -497,17 +494,21 @@ static int _xioopen_socks5_request(
/* Same function for all socks5-modes, determined by argv[0] */ /* Same function for all socks5-modes, determined by argv[0] */
static int xioopen_socks5( static int xioopen_socks5(
int argc, const char *argv[], struct opt *opts, int xioflags, int argc,
xiofile_t *xxfd, groups_t groups, int socks_command, int dummy2, const char *argv[],
int dummy3) struct opt *opts,
int xioflags,
xiofile_t *xxfd,
const struct addrdesc *addrdesc)
{ {
int socks_command = addrdesc->arg1;
bool dofork = false; bool dofork = false;
int socktype = SOCK_STREAM; int socktype = SOCK_STREAM;
int pf = PF_UNSPEC; int pf = PF_UNSPEC;
int ipproto = IPPROTO_TCP; int ipproto = IPPROTO_TCP;
int level, result; int level, result;
struct opt *opts0 = NULL; struct opt *opts0 = NULL;
struct single *xfd = &xxfd->stream; struct single *sfd = &xxfd->stream;
const char *socks_server, *target_name, *target_port, *socks_port; const char *socks_server, *target_name, *target_port, *socks_port;
union sockaddr_union us_sa, *us = &us_sa; union sockaddr_union us_sa, *us = &us_sa;
socklen_t uslen = sizeof(us_sa); socklen_t uslen = sizeof(us_sa);
@ -521,14 +522,7 @@ static int xioopen_socks5(
return STAT_NORETRY; return STAT_NORETRY;
} }
if (argc != 5) { if (argc != 5) {
#if WITH_HELP xio_syntax(argv[0], 4, argc-1, addrdesc->syntax);
Error2("%s: 4 parameters required like %s", argv[0],
socks_command==SOCKS5_COMMAND_CONNECT ?
xioaddr_socks5_connect.syntax :
xioaddr_socks5_listen.syntax);
#else
Error1("%s: 4 parameters required", argv[0]);
#endif
return STAT_NORETRY; return STAT_NORETRY;
} }
@ -537,16 +531,16 @@ static int xioopen_socks5(
target_name = argv[3]; target_name = argv[3];
target_port = argv[4]; target_port = argv[4];
xfd->howtoend = END_SHUTDOWN; sfd->howtoend = END_SHUTDOWN;
if (applyopts_single(xfd, opts, PH_INIT) < 0) return -1; if (applyopts_single(sfd, opts, PH_INIT) < 0) return -1;
applyopts(xfd, -1, opts, PH_INIT); applyopts(sfd, -1, opts, PH_INIT);
retropt_int(opts, OPT_SO_TYPE, &socktype); retropt_int(opts, OPT_SO_TYPE, &socktype);
retropt_bool(opts, OPT_FORK, &dofork); retropt_bool(opts, OPT_FORK, &dofork);
result = _xioopen_ipapp_prepare(opts, &opts0, socks_server, socks_port, result = _xioopen_ipapp_prepare(opts, &opts0, socks_server, socks_port,
&pf, ipproto, &pf, ipproto,
xfd->para.socket.ip.ai_flags, sfd->para.socket.ip.ai_flags,
&themlist, us, &uslen, &themlist, us, &uslen,
&needbind, &lowport, socktype); &needbind, &lowport, socktype);
@ -555,7 +549,7 @@ static int xioopen_socks5(
do { do {
#if WITH_RETRY #if WITH_RETRY
if (xfd->forever || xfd->retry) { if (sfd->forever || sfd->retry) {
level = E_INFO; level = E_INFO;
} else { } else {
level = E_ERROR; level = E_ERROR;
@ -568,7 +562,7 @@ static int xioopen_socks5(
Notice1("opening connection to %s", Notice1("opening connection to %s",
sockaddr_info(themp->ai_addr, themp->ai_addrlen, sockaddr_info(themp->ai_addr, themp->ai_addrlen,
infobuff, sizeof(infobuff))); infobuff, sizeof(infobuff)));
result = _xioopen_connect(xfd, needbind?us:NULL, sizeof(*us), result = _xioopen_connect(sfd, needbind?us:NULL, sizeof(*us),
themp->ai_addr, themp->ai_addrlen, themp->ai_addr, themp->ai_addrlen,
opts, pf?pf:themp->ai_family, socktype, opts, pf?pf:themp->ai_family, socktype,
IPPROTO_TCP, lowport, level); IPPROTO_TCP, lowport, level);
@ -583,8 +577,8 @@ static int xioopen_socks5(
#if WITH_RETRY #if WITH_RETRY
case STAT_RETRYLATER: case STAT_RETRYLATER:
case STAT_RETRYNOW: case STAT_RETRYNOW:
if (xfd->forever || xfd->retry-- ) { if (sfd->forever || sfd->retry-- ) {
if (result == STAT_RETRYLATER) Nanosleep(&xfd->intervall, NULL); if (result == STAT_RETRYLATER) Nanosleep(&sfd->intervall, NULL);
continue; continue;
} }
#endif #endif
@ -594,24 +588,24 @@ static int xioopen_socks5(
} }
} }
xiofreeaddrinfo(themlist); xiofreeaddrinfo(themlist);
applyopts(xfd, -1, opts, PH_ALL); applyopts(sfd, -1, opts, PH_ALL);
if ((result = _xio_openlate(xfd, opts)) < 0) if ((result = _xio_openlate(sfd, opts)) < 0)
return result; return result;
if ((result = _xioopen_socks5_handshake(xfd, level)) != STAT_OK) { if ((result = _xioopen_socks5_handshake(sfd, level)) != STAT_OK) {
return result; return result;
} }
result = _xioopen_socks5_request(xfd, target_name, target_port, socks_command, level); result = _xioopen_socks5_request(sfd, target_name, target_port, socks_command, level);
switch (result) { switch (result) {
case STAT_OK: case STAT_OK:
break; break;
#if WITH_RETRY #if WITH_RETRY
case STAT_RETRYLATER: case STAT_RETRYLATER:
case STAT_RETRYNOW: case STAT_RETRYNOW:
if ( xfd->forever || xfd->retry-- ) { if ( sfd->forever || sfd->retry-- ) {
if (result == STAT_RETRYLATER) Nanosleep(&xfd->intervall, NULL); if (result == STAT_RETRYLATER) Nanosleep(&sfd->intervall, NULL);
continue; continue;
} }
#endif #endif
@ -627,24 +621,24 @@ static int xioopen_socks5(
if (dofork) { if (dofork) {
pid_t pid; pid_t pid;
int level = E_ERROR; int level = E_ERROR;
if (xfd->forever || xfd->retry) { if (sfd->forever || sfd->retry) {
level = E_WARN; level = E_WARN;
} }
while ((pid = xio_fork(false, level, xfd->shutup)) < 0) { while ((pid = xio_fork(false, level, sfd->shutup)) < 0) {
if (xfd->forever || --xfd->retry) { if (sfd->forever || --sfd->retry) {
Nanosleep(&xfd->intervall, NULL); Nanosleep(&sfd->intervall, NULL);
continue; continue;
} }
return STAT_RETRYLATER; return STAT_RETRYLATER;
} }
if ( pid == 0 ) { if ( pid == 0 ) {
xfd->forever = false; sfd->forever = false;
xfd->retry = 0; sfd->retry = 0;
break; break;
} }
Close(xfd->fd); Close(sfd->fd);
Nanosleep(&xfd->intervall, NULL); Nanosleep(&sfd->intervall, NULL);
dropopts(opts, PH_ALL); dropopts(opts, PH_ALL);
opts = copyopts(opts0, GROUP_ALL); opts = copyopts(opts0, GROUP_ALL);
continue; continue;

View file

@ -13,8 +13,8 @@
#if WITH_STDIO #if WITH_STDIO
static int xioopen_stdio(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *fd, groups_t groups, int dummy1, int dummy2, int dummy3); static int xioopen_stdio(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *fd, const struct addrdesc *addrdesc);
static int xioopen_stdfd(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *xfd, groups_t groups, int fd, int dummy2, int dummy3); static int xioopen_stdfd(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *xfd, const struct addrdesc *addrdesc);
/* we specify all option groups that we can imagine for a FD, becasue the /* we specify all option groups that we can imagine for a FD, becasue the
@ -135,7 +135,14 @@ int xioopen_stdio_bi(xiofile_t *sock) {
/* wrap around unidirectional xioopensingle and xioopen_fd to automatically determine stdin or stdout fd depending on rw. /* wrap around unidirectional xioopensingle and xioopen_fd to automatically determine stdin or stdout fd depending on rw.
Do not set FD_CLOEXEC flag. */ Do not set FD_CLOEXEC flag. */
static int xioopen_stdio(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *fd, groups_t groups, int dummy1, int dummy2, int dummy3) { static int xioopen_stdio(
int argc,
const char *argv[],
struct opt *opts,
int xioflags,
xiofile_t *fd,
const struct addrdesc *addrdesc)
{
int rw = (xioflags&XIO_ACCMODE); int rw = (xioflags&XIO_ACCMODE);
if (argc != 1) { if (argc != 1) {
@ -149,13 +156,21 @@ static int xioopen_stdio(int argc, const char *argv[], struct opt *opts, int xio
Notice2("using %s for %s", Notice2("using %s for %s",
&("stdin\0\0\0stdout"[rw<<3]), &("stdin\0\0\0stdout"[rw<<3]),
ddirection[rw]); ddirection[rw]);
return xioopen_fd(opts, rw, &fd->stream, rw, dummy2, dummy3); return xioopen_fd(opts, rw, &fd->stream, rw);
} }
/* wrap around unidirectional xioopensingle and xioopen_fd to automatically determine stdin or stdout fd depending on rw. /* wrap around unidirectional xioopensingle and xioopen_fd to automatically determine stdin or stdout fd depending on rw.
Do not set FD_CLOEXEC flag. */ Do not set FD_CLOEXEC flag. */
static int xioopen_stdfd(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *xfd, groups_t groups, int fd, int dummy2, int dummy3) { static int xioopen_stdfd(
int argc,
const char *argv[],
struct opt *opts,
int xioflags,
xiofile_t *xfd,
const struct addrdesc *addrdesc)
{
int rw = (xioflags&XIO_ACCMODE); int rw = (xioflags&XIO_ACCMODE);
int fd = addrdesc->arg1;
if (argc != 1) { if (argc != 1) {
Error2("%s: wrong number of parameters (%d instead of 0)", argv[0], argc-1); Error2("%s: wrong number of parameters (%d instead of 0)", argv[0], argc-1);
@ -163,6 +178,6 @@ static int xioopen_stdfd(int argc, const char *argv[], struct opt *opts, int xio
Notice2("using %s for %s", Notice2("using %s for %s",
&("stdin\0\0\0stdout\0\0stderr"[fd<<3]), &("stdin\0\0\0stdout\0\0stderr"[fd<<3]),
ddirection[rw]); ddirection[rw]);
return xioopen_fd(opts, rw, &xfd->stream, fd, dummy2, dummy3); return xioopen_fd(opts, rw, &xfd->stream, fd);
} }
#endif /* WITH_STDIO */ #endif /* WITH_STDIO */

View file

@ -13,22 +13,19 @@
#if WITH_SYSTEM #if WITH_SYSTEM
static int xioopen_system(int arg, const char *argv[], struct opt *opts, static int xioopen_system(int arg, const char *argv[], struct opt *opts, int xioflags, xiofile_t *xfd, const struct addrdesc *addrdesc);
int xioflags, /* XIO_RDONLY etc. */
xiofile_t *fd,
groups_t groups,
int dummy1, int dummy2, int dummy3
);
const struct addrdesc xioaddr_system = { "SYSTEM", 3, xioopen_system, GROUP_FD|GROUP_FORK|GROUP_EXEC|GROUP_SOCKET|GROUP_SOCK_UNIX|GROUP_TERMIOS|GROUP_FIFO|GROUP_PTY|GROUP_PARENT, 1, 0, 0 HELP(":<shell-command>") }; const struct addrdesc xioaddr_system = { "SYSTEM", 3, xioopen_system, GROUP_FD|GROUP_FORK|GROUP_EXEC|GROUP_SOCKET|GROUP_SOCK_UNIX|GROUP_TERMIOS|GROUP_FIFO|GROUP_PTY|GROUP_PARENT, 1, 0, 0 HELP(":<shell-command>") };
static int xioopen_system(int argc, const char *argv[], struct opt *opts, static int xioopen_system(
int xioflags, /* XIO_RDONLY etc. */ int argc,
xiofile_t *xfd, const char *argv[],
groups_t groups, struct opt *opts,
int dummy1, int dummy2, int dummy3 int xioflags, /* XIO_RDONLY etc. */
) { xiofile_t *xfd,
const struct addrdesc *addrdesc)
{
struct single *sfd = &xfd->stream; struct single *sfd = &xfd->stream;
int status; int status;
char *path = NULL; char *path = NULL;
@ -36,7 +33,13 @@ static int xioopen_system(int argc, const char *argv[], struct opt *opts,
int result; int result;
const char *string = argv[1]; const char *string = argv[1];
status = _xioopen_foxec(xioflags, sfd, groups, &opts, &duptostderr); if (argc != 2) {
xio_syntax(argv[0], 1, argc-1, addrdesc->syntax);
return STAT_NORETRY;
}
status =
_xioopen_foxec(xioflags, sfd, addrdesc->groups, &opts, &duptostderr);
if (status < 0) if (status < 0)
return status; return status;
if (status == 0) { /* child */ if (status == 0) { /* child */

View file

@ -32,42 +32,44 @@ int allow_severity=10, deny_severity=10;
/* returns 0 if option was found and could be applied /* returns 0 if option was found and could be applied
returns 1 if option was not found returns 1 if option was not found
returns -1 if option was found but failed */ returns -1 if option was found but failed */
int xio_retropt_tcpwrap(xiosingle_t *xfd, struct opt *opts) { int xio_retropt_tcpwrap(
struct single *sfd,
struct opt *opts) {
bool dolibwrap = false; bool dolibwrap = false;
dolibwrap = dolibwrap =
retropt_string(opts, OPT_TCPWRAPPERS, retropt_string(opts, OPT_TCPWRAPPERS,
&xfd->para.socket.ip.libwrapname) >= 0 || dolibwrap; &sfd->para.socket.ip.libwrapname) >= 0 || dolibwrap;
dolibwrap = dolibwrap =
retropt_string(opts, OPT_TCPWRAP_ETC, retropt_string(opts, OPT_TCPWRAP_ETC,
&xfd->para.socket.ip.tcpwrap_etc) >= 0 || dolibwrap; &sfd->para.socket.ip.tcpwrap_etc) >= 0 || dolibwrap;
#if defined(HAVE_HOSTS_ALLOW_TABLE) #if defined(HAVE_HOSTS_ALLOW_TABLE)
dolibwrap = dolibwrap =
retropt_string(opts, OPT_TCPWRAP_HOSTS_ALLOW_TABLE, retropt_string(opts, OPT_TCPWRAP_HOSTS_ALLOW_TABLE,
&xfd->para.socket.ip.hosts_allow_table) >= 0 || dolibwrap; &sfd->para.socket.ip.hosts_allow_table) >= 0 || dolibwrap;
#endif #endif
#if defined(HAVE_HOSTS_DENY_TABLE) #if defined(HAVE_HOSTS_DENY_TABLE)
dolibwrap = dolibwrap =
retropt_string(opts, OPT_TCPWRAP_HOSTS_DENY_TABLE, retropt_string(opts, OPT_TCPWRAP_HOSTS_DENY_TABLE,
&xfd->para.socket.ip.hosts_deny_table) >= 0 || dolibwrap; &sfd->para.socket.ip.hosts_deny_table) >= 0 || dolibwrap;
#endif #endif
if (dolibwrap) { if (dolibwrap) {
xfd->para.socket.ip.dolibwrap = true; sfd->para.socket.ip.dolibwrap = true;
if (xfd->para.socket.ip.libwrapname == NULL) { if (sfd->para.socket.ip.libwrapname == NULL) {
xfd->para.socket.ip.libwrapname = (char *)diag_get_string('p'); sfd->para.socket.ip.libwrapname = (char *)diag_get_string('p');
} }
#if defined(HAVE_HOSTS_ALLOW_TABLE) || defined(HAVE_HOSTS_DENY_TABLE) #if defined(HAVE_HOSTS_ALLOW_TABLE) || defined(HAVE_HOSTS_DENY_TABLE)
if (xfd->para.socket.ip.tcpwrap_etc) { if (sfd->para.socket.ip.tcpwrap_etc) {
if (xfd->para.socket.ip.hosts_allow_table == NULL) { if (sfd->para.socket.ip.hosts_allow_table == NULL) {
xfd->para.socket.ip.hosts_allow_table = sfd->para.socket.ip.hosts_allow_table =
Malloc(strlen(xfd->para.socket.ip.tcpwrap_etc)+1+11+1); Malloc(strlen(sfd->para.socket.ip.tcpwrap_etc)+1+11+1);
sprintf(xfd->para.socket.ip.hosts_allow_table, "%s/hosts.allow", sprintf(sfd->para.socket.ip.hosts_allow_table, "%s/hosts.allow",
xfd->para.socket.ip.tcpwrap_etc); sfd->para.socket.ip.tcpwrap_etc);
} }
if (xfd->para.socket.ip.hosts_deny_table == NULL) { if (sfd->para.socket.ip.hosts_deny_table == NULL) {
xfd->para.socket.ip.hosts_deny_table = sfd->para.socket.ip.hosts_deny_table =
Malloc(strlen(xfd->para.socket.ip.tcpwrap_etc)+1+10+1); Malloc(strlen(sfd->para.socket.ip.tcpwrap_etc)+1+10+1);
sprintf(xfd->para.socket.ip.hosts_deny_table, "%s/hosts.deny", sprintf(sfd->para.socket.ip.hosts_deny_table, "%s/hosts.deny",
xfd->para.socket.ip.tcpwrap_etc); sfd->para.socket.ip.tcpwrap_etc);
} }
} }
#endif /* defined(HAVE_HOSTS_ALLOW_TABLE) || defined(HAVE_HOSTS_DENY_TABLE) */ #endif /* defined(HAVE_HOSTS_ALLOW_TABLE) || defined(HAVE_HOSTS_DENY_TABLE) */
@ -79,8 +81,10 @@ int xio_retropt_tcpwrap(xiosingle_t *xfd, struct opt *opts) {
/* returns -1 if forbidden, 0 if no tcpwrap check, or 1 if explicitely allowed /* returns -1 if forbidden, 0 if no tcpwrap check, or 1 if explicitely allowed
*/ */
int xio_tcpwrap_check(xiosingle_t *xfd, union sockaddr_union *us, int xio_tcpwrap_check(
union sockaddr_union *them) { struct single *sfd,
union sockaddr_union *us,
union sockaddr_union *them) {
char *save_hosts_allow_table, *save_hosts_deny_table; char *save_hosts_allow_table, *save_hosts_deny_table;
struct request_info ri; struct request_info ri;
#if WITH_IP6 #if WITH_IP6
@ -90,25 +94,25 @@ int xio_tcpwrap_check(xiosingle_t *xfd, union sockaddr_union *us,
#endif #endif
int allow; int allow;
if (!xfd->para.socket.ip.dolibwrap) { if (!sfd->para.socket.ip.dolibwrap) {
return 0; return 0;
} }
if (us == NULL || them == NULL) { return -1; } if (us == NULL || them == NULL) { return -1; }
#if defined(HAVE_HOSTS_ALLOW_TABLE) #if defined(HAVE_HOSTS_ALLOW_TABLE)
save_hosts_allow_table = hosts_allow_table; save_hosts_allow_table = hosts_allow_table;
if (xfd->para.socket.ip.hosts_allow_table) { if (sfd->para.socket.ip.hosts_allow_table) {
Debug1("hosts_allow_table = \"%s\"", Debug1("hosts_allow_table = \"%s\"",
xfd->para.socket.ip.hosts_allow_table); sfd->para.socket.ip.hosts_allow_table);
hosts_allow_table = xfd->para.socket.ip.hosts_allow_table; hosts_allow_table = sfd->para.socket.ip.hosts_allow_table;
} }
#endif /* defined(HAVE_HOSTS_ALLOW_TABLE) */ #endif /* defined(HAVE_HOSTS_ALLOW_TABLE) */
#if defined(HAVE_HOSTS_DENY_TABLE) #if defined(HAVE_HOSTS_DENY_TABLE)
save_hosts_deny_table = hosts_deny_table; save_hosts_deny_table = hosts_deny_table;
if (xfd->para.socket.ip.hosts_deny_table) { if (sfd->para.socket.ip.hosts_deny_table) {
Debug1("hosts_deny_table = \"%s\"", Debug1("hosts_deny_table = \"%s\"",
xfd->para.socket.ip.hosts_deny_table); sfd->para.socket.ip.hosts_deny_table);
hosts_deny_table = xfd->para.socket.ip.hosts_deny_table; hosts_deny_table = sfd->para.socket.ip.hosts_deny_table;
} }
#endif /* defined(HAVE_HOSTS_DENY_TABLE) */ #endif /* defined(HAVE_HOSTS_DENY_TABLE) */
@ -132,14 +136,14 @@ int xio_tcpwrap_check(xiosingle_t *xfd, union sockaddr_union *us,
Warn1("inet_ntop(): %s", strerror(errno)); Warn1("inet_ntop(): %s", strerror(errno));
} }
Debug7("request_init(%p, RQ_FILE, %d, RQ_CLIENT_SIN, {%s:%u}, RQ_SERVER_SIN, {%s:%u}, RQ_DAEMON, \"%s\", 0", Debug7("request_init(%p, RQ_FILE, %d, RQ_CLIENT_SIN, {%s:%u}, RQ_SERVER_SIN, {%s:%u}, RQ_DAEMON, \"%s\", 0",
&ri, xfd->fd, clientaddr, &ri, sfd->fd, clientaddr,
ntohs(((struct sockaddr_in *)them)->sin_port), ntohs(((struct sockaddr_in *)them)->sin_port),
serveraddr, ntohs(us->ip4.sin_port), serveraddr, ntohs(us->ip4.sin_port),
xfd->para.socket.ip.libwrapname?xfd->para.socket.ip.libwrapname:(char *)diag_get_string('p')); sfd->para.socket.ip.libwrapname?sfd->para.socket.ip.libwrapname:(char *)diag_get_string('p'));
request_init(&ri, RQ_FILE, xfd->fd, request_init(&ri, RQ_FILE, sfd->fd,
RQ_CLIENT_SIN, them, RQ_CLIENT_SIN, them,
RQ_SERVER_SIN, &us->soa, RQ_SERVER_SIN, &us->soa,
RQ_DAEMON, xfd->para.socket.ip.libwrapname?xfd->para.socket.ip.libwrapname:(char *)diag_get_string('p'), 0); RQ_DAEMON, sfd->para.socket.ip.libwrapname?sfd->para.socket.ip.libwrapname:(char *)diag_get_string('p'), 0);
Debug("request_init() ->"); Debug("request_init() ->");
Debug1("sock_methods(%p)", &ri); Debug1("sock_methods(%p)", &ri);

View file

@ -16,7 +16,7 @@
#include "xio-tun.h" #include "xio-tun.h"
static int xioopen_tun(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *fd, groups_t groups, int dummy1, int dummy2, int dummy3); static int xioopen_tun(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *xfd, const struct addrdesc *addrdesc);
/****** TUN options ******/ /****** TUN options ******/
const struct optdesc opt_tun_device = { "tun-device", NULL, OPT_TUN_DEVICE, GROUP_TUN, PH_OPEN, TYPE_FILENAME, OFUNC_SPEC }; const struct optdesc opt_tun_device = { "tun-device", NULL, OPT_TUN_DEVICE, GROUP_TUN, PH_OPEN, TYPE_FILENAME, OFUNC_SPEC };
@ -45,7 +45,14 @@ static const struct optname xio_route_options[] = {
} ; } ;
#endif #endif
static int xioopen_tun(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *xfd, groups_t groups, int dummy1, int dummy2, int dummy3) { static int xioopen_tun(
int argc,
const char *argv[],
struct opt *opts,
int xioflags,
xiofile_t *xfd,
const struct addrdesc *addrdesc)
{
struct single *sfd = &xfd->stream; struct single *sfd = &xfd->stream;
char *tundevice = NULL; char *tundevice = NULL;
char *tunname = NULL, *tuntype = NULL; char *tunname = NULL, *tuntype = NULL;
@ -61,8 +68,13 @@ static int xioopen_tun(int argc, const char *argv[], struct opt *opts, int xiofl
int result; int result;
if (argc > 2 || argc < 0) { if (argc > 2 || argc < 0) {
#if WITH_HELP
Error3("%s: wrong number of parameters (%d instead of 0 or 1); usage: %s",
argv[0], argc-1, addrdesc->syntax);
#else
Error2("%s: wrong number of parameters (%d instead of 0 or 1)", Error2("%s: wrong number of parameters (%d instead of 0 or 1)",
argv[0], argc-1); argv[0], argc-1);
#endif
} }
if (retropt_string(opts, OPT_TUN_DEVICE, &tundevice) != 0) { if (retropt_string(opts, OPT_TUN_DEVICE, &tundevice) != 0) {
@ -74,7 +86,8 @@ static int xioopen_tun(int argc, const char *argv[], struct opt *opts, int xiofl
namedargv[1] = tundevice; namedargv[1] = tundevice;
/* open the tun cloning device */ /* open the tun cloning device */
if ((result = _xioopen_named_early(2, namedargv, xfd, groups, &exists, opts)) < 0) { if ((result = _xioopen_named_early(2, namedargv, xfd, addrdesc->groups,
&exists, opts, addrdesc->syntax)) < 0) {
return result; return result;
} }

189
xio-udp.c
View file

@ -19,22 +19,10 @@
#include "xio-udp.h" #include "xio-udp.h"
static static int xioopen_udp_sendto(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *xfd, const struct addrdesc *addrdesc);
int xioopen_udp_sendto(int argc, const char *argv[], struct opt *opts, static int xioopen_udp_datagram(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *xfd, const struct addrdesc *addrdesc);
int xioflags, xiofile_t *xfd, groups_t groups, static int xioopen_udp_recvfrom(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *xfd, const struct addrdesc *addrdesc);
int pf, int socktype, int ipproto); static int xioopen_udp_recv(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *xfd, const struct addrdesc *addrdesc);
static
int xioopen_udp_datagram(int argc, const char *argv[], struct opt *opts,
int xioflags, xiofile_t *xfd, groups_t groups,
int pf, int socktype, int ipproto);
static
int xioopen_udp_recvfrom(int argc, const char *argv[], struct opt *opts,
int xioflags, xiofile_t *xfd, groups_t groups,
int pf, int socktype, int ipproto);
static
int xioopen_udp_recv(int argc, const char *argv[], struct opt *opts,
int xioflags, xiofile_t *xfd, groups_t groups,
int pf, int socktype, int ipproto);
static static
int _xioopen_udp_sendto(const char *hostname, const char *servname, int _xioopen_udp_sendto(const char *hostname, const char *servname,
@ -283,18 +271,25 @@ int _xioopen_ipdgram_listen(struct single *sfd,
} }
/* we expect the form: port */ /* we expect the form: port */
int xioopen_ipdgram_listen(int argc, const char *argv[], struct opt *opts, int xioopen_ipdgram_listen(
int xioflags, xiofile_t *xfd, int argc,
groups_t groups, int pf, int ipproto, const char *argv[],
int protname) { struct opt *opts,
int xioflags,
xiofile_t *xfd,
const struct addrdesc *addrdesc)
{
struct single *sfd = &xfd->stream; struct single *sfd = &xfd->stream;
const char *portname = argv[1]; const char *portname = argv[1];
int pf = addrdesc->arg1;
int ipproto = addrdesc->arg2;
union sockaddr_union us; union sockaddr_union us;
int socktype = SOCK_DGRAM; int socktype = SOCK_DGRAM;
socklen_t uslen; socklen_t uslen;
if (argc != 2) { if (argc != 2) {
Error2("%s: wrong number of parameters (%d instead of 1)", argv[0], argc-1); xio_syntax(argv[0], 1, argc-1, addrdesc->syntax);
return STAT_NORETRY;
} }
xioinit_ip(&pf, xioparms.default_ip); xioinit_ip(&pf, xioparms.default_ip);
@ -342,21 +337,27 @@ int xioopen_ipdgram_listen(int argc, const char *argv[], struct opt *opts,
opts, pf, socktype, ipproto); opts, pf, socktype, ipproto);
} }
static static int xioopen_udp_sendto(
int xioopen_udp_sendto(int argc, const char *argv[], struct opt *opts, int argc,
int xioflags, xiofile_t *xfd, groups_t groups, const char *argv[],
int pf, int socktype, int ipproto) { struct opt *opts,
int xioflags,
xiofile_t *xfd,
const struct addrdesc *addrdesc)
{
int pf = addrdesc->arg1;
int socktype = addrdesc->arg2;
int ipproto = addrdesc->arg3;
int result; int result;
if (argc != 3) { if (argc != 3) {
Error2("%s: wrong number of parameters (%d instead of 2)", xio_syntax(argv[0], 2, argc-1, addrdesc->syntax);
argv[0], argc-1);
return STAT_NORETRY; return STAT_NORETRY;
} }
retropt_socket_pf(opts, &pf); retropt_socket_pf(opts, &pf);
if ((result = _xioopen_udp_sendto(argv[1], argv[2], opts, xioflags, xfd, if ((result = _xioopen_udp_sendto(argv[1], argv[2], opts, xioflags, xfd,
groups, pf, socktype, ipproto)) addrdesc->groups, pf, socktype, ipproto))
!= STAT_OK) { != STAT_OK) {
return result; return result;
} }
@ -375,75 +376,83 @@ int _xioopen_udp_sendto(const char *hostname, const char *servname,
struct opt *opts, struct opt *opts,
int xioflags, xiofile_t *xxfd, groups_t groups, int xioflags, xiofile_t *xxfd, groups_t groups,
int pf, int socktype, int ipproto) { int pf, int socktype, int ipproto) {
xiosingle_t *xfd = &xxfd->stream; struct single *sfd = &xxfd->stream;
union sockaddr_union us; union sockaddr_union us;
socklen_t uslen; socklen_t uslen;
int feats = 3; /* option bind supports address and port */ int feats = 3; /* option bind supports address and port */
bool needbind = false; bool needbind = false;
int result; int result;
xfd->howtoend = END_SHUTDOWN; sfd->howtoend = END_SHUTDOWN;
if (applyopts_single(xfd, opts, PH_INIT) < 0) return -1; /* ...res_opts[] */
applyopts(xfd, -1, opts, PH_INIT); if (applyopts_single(sfd, opts, PH_INIT) < 0)
return -1;
applyopts(sfd, -1, opts, PH_INIT);
xfd->salen = sizeof(xfd->peersa); sfd->salen = sizeof(sfd->peersa);
if ((result = if ((result =
xioresolve(hostname, servname, pf, socktype, ipproto, xioresolve(hostname, servname, pf, socktype, ipproto,
&xfd->peersa, &xfd->salen, &sfd->peersa, &sfd->salen,
xfd->para.socket.ip.ai_flags)) sfd->para.socket.ip.ai_flags))
!= STAT_OK) { != STAT_OK) {
return result; return result;
} }
if (pf == PF_UNSPEC) { if (pf == PF_UNSPEC) {
pf = xfd->peersa.soa.sa_family; pf = sfd->peersa.soa.sa_family;
} }
uslen = socket_init(pf, &us); uslen = socket_init(pf, &us);
if (retropt_bind(opts, pf, socktype, ipproto, &us.soa, &uslen, feats, if (retropt_bind(opts, pf, socktype, ipproto, &us.soa, &uslen, feats,
xfd->para.socket.ip.ai_flags) sfd->para.socket.ip.ai_flags)
!= STAT_NOACTION) { != STAT_NOACTION) {
needbind = true; needbind = true;
} }
if (retropt_ushort(opts, OPT_SOURCEPORT, if (retropt_ushort(opts, OPT_SOURCEPORT,
&xfd->para.socket.ip.sourceport) >= 0) { &sfd->para.socket.ip.sourceport) >= 0) {
switch (pf) { switch (pf) {
#if WITH_IP4 #if WITH_IP4
case PF_INET: case PF_INET:
us.ip4.sin_port = htons(xfd->para.socket.ip.sourceport); us.ip4.sin_port = htons(sfd->para.socket.ip.sourceport);
break; break;
#endif #endif
#if WITH_IP6 #if WITH_IP6
case PF_INET6: case PF_INET6:
us.ip6.sin6_port = htons(xfd->para.socket.ip.sourceport); us.ip6.sin6_port = htons(sfd->para.socket.ip.sourceport);
break; break;
#endif #endif
} }
needbind = true; needbind = true;
} }
retropt_bool(opts, OPT_LOWPORT, &xfd->para.socket.ip.lowport); retropt_bool(opts, OPT_LOWPORT, &sfd->para.socket.ip.lowport);
xfd->dtype = XIODATA_RECVFROM; sfd->dtype = XIODATA_RECVFROM;
return _xioopen_dgram_sendto(needbind?&us:NULL, uslen, return _xioopen_dgram_sendto(needbind?&us:NULL, uslen,
opts, xioflags, xfd, groups, opts, xioflags, sfd, groups,
pf, socktype, ipproto, pf, socktype, ipproto,
xfd->para.socket.ip.lowport); sfd->para.socket.ip.lowport);
} }
static static int xioopen_udp_datagram(
int xioopen_udp_datagram(int argc, const char *argv[], struct opt *opts, int argc,
int xioflags, xiofile_t *xxfd, groups_t groups, const char *argv[],
int pf, int socktype, int ipproto) { struct opt *opts,
xiosingle_t *xfd = &xxfd->stream; int xioflags,
xiofile_t *xxfd,
const struct addrdesc *addrdesc)
{
struct single *sfd = &xxfd->stream;
int pf = addrdesc->arg1;
int socktype = addrdesc->arg2;
int ipproto = addrdesc->arg3;
char *rangename; char *rangename;
char *hostname; char *hostname;
int result; int result;
if (argc != 3) { if (argc != 3) {
Error2("%s: wrong number of parameters (%d instead of 2)", xio_syntax(argv[0], 2, argc-1, addrdesc->syntax);
argv[0], argc-1);
return STAT_NORETRY; return STAT_NORETRY;
} }
@ -453,65 +462,71 @@ int xioopen_udp_datagram(int argc, const char *argv[], struct opt *opts,
} }
/* only accept packets with correct remote ports */ /* only accept packets with correct remote ports */
if (retropt_ushort(opts, OPT_SOURCEPORT, &xfd->para.socket.ip.sourceport) if (retropt_ushort(opts, OPT_SOURCEPORT, &sfd->para.socket.ip.sourceport)
>= 0) { >= 0) {
xfd->para.socket.ip.dosourceport = true; sfd->para.socket.ip.dosourceport = true;
xfd->para.socket.ip.sourceport = ntohs(xfd->peersa.ip4.sin_port); sfd->para.socket.ip.sourceport = ntohs(sfd->peersa.ip4.sin_port);
} }
retropt_socket_pf(opts, &pf); retropt_socket_pf(opts, &pf);
result = result =
_xioopen_udp_sendto(hostname, argv[2], opts, xioflags, xxfd, groups, _xioopen_udp_sendto(hostname, argv[2], opts, xioflags, xxfd,
pf, socktype, ipproto); addrdesc->groups, pf, socktype, ipproto);
free(hostname); free(hostname);
if (result != STAT_OK) { if (result != STAT_OK) {
return result; return result;
} }
xfd->dtype = XIOREAD_RECV|XIOWRITE_SENDTO; sfd->dtype = XIOREAD_RECV|XIOWRITE_SENDTO;
xfd->para.socket.la.soa.sa_family = xfd->peersa.soa.sa_family; sfd->para.socket.la.soa.sa_family = sfd->peersa.soa.sa_family;
/* which reply packets will be accepted - determine by range option */ /* which reply packets will be accepted - determine by range option */
if (retropt_string(opts, OPT_RANGE, &rangename) if (retropt_string(opts, OPT_RANGE, &rangename) >= 0) {
>= 0) { if (xioparserange(rangename, pf, &sfd->para.socket.range,
if (xioparserange(rangename, pf, &xfd->para.socket.range, sfd->para.socket.ip.ai_flags)
xfd->para.socket.ip.ai_flags)
< 0) { < 0) {
free(rangename); free(rangename);
return STAT_NORETRY; return STAT_NORETRY;
} }
xfd->para.socket.dorange = true; sfd->para.socket.dorange = true;
xfd->dtype |= XIOREAD_RECV_CHECKRANGE; sfd->dtype |= XIOREAD_RECV_CHECKRANGE;
free(rangename); free(rangename);
} }
#if WITH_LIBWRAP #if WITH_LIBWRAP
xio_retropt_tcpwrap(xfd, opts); xio_retropt_tcpwrap(sfd, opts);
#endif /* WITH_LIBWRAP */ #endif /* WITH_LIBWRAP */
_xio_openlate(xfd, opts); _xio_openlate(sfd, opts);
return STAT_OK; return STAT_OK;
} }
static static int xioopen_udp_recvfrom(
int xioopen_udp_recvfrom(int argc, const char *argv[], struct opt *opts, int argc,
int xioflags, xiofile_t *xfd, groups_t groups, const char *argv[],
int pf, int socktype, int ipproto) { struct opt *opts,
int xioflags,
xiofile_t *xfd,
const struct addrdesc *addrdesc)
{
struct single *sfd = &xfd->stream;
int pf = addrdesc->arg1;
int socktype = addrdesc->arg2;
int ipproto = addrdesc->arg3;
union sockaddr_union us; union sockaddr_union us;
socklen_t uslen = sizeof(us); socklen_t uslen = sizeof(us);
int ai_flags2[2]; int ai_flags2[2];
int result; int result;
if (argc != 2) { if (argc != 2) {
Error2("%s: wrong number of parameters (%d instead of 1)", xio_syntax(argv[0], 1, argc-1, addrdesc->syntax);
argv[0], argc-1);
return STAT_NORETRY; return STAT_NORETRY;
} }
xioinit_ip(&pf, xioparms.default_ip); xioinit_ip(&pf, xioparms.default_ip);
xfd->stream.howtoend = END_NONE; sfd->howtoend = END_NONE;
retropt_socket_pf(opts, &pf); retropt_socket_pf(opts, &pf);
if (pf == PF_UNSPEC) { if (pf == PF_UNSPEC) {
#if WITH_IP4 && WITH_IP6 #if WITH_IP4 && WITH_IP6
@ -548,7 +563,7 @@ int xioopen_udp_recvfrom(int argc, const char *argv[], struct opt *opts,
socklen_t lalen = sizeof(la); socklen_t lalen = sizeof(la);
if (retropt_bind(opts, pf, socktype, ipproto, &la.soa, &lalen, 1, if (retropt_bind(opts, pf, socktype, ipproto, &la.soa, &lalen, 1,
xfd->stream.para.socket.ip.ai_flags) sfd->para.socket.ip.ai_flags)
!= STAT_NOACTION) { != STAT_NOACTION) {
switch (pf) { switch (pf) {
#if WITH_IP4 #if WITH_IP4
@ -561,14 +576,14 @@ int xioopen_udp_recvfrom(int argc, const char *argv[], struct opt *opts,
} }
} }
if (retropt_ushort(opts, OPT_SOURCEPORT, &xfd->stream.para.socket.ip.sourceport) >= 0) { if (retropt_ushort(opts, OPT_SOURCEPORT, &sfd->para.socket.ip.sourceport) >= 0) {
xfd->stream.para.socket.ip.dosourceport = true; sfd->para.socket.ip.dosourceport = true;
} }
retropt_bool(opts, OPT_LOWPORT, &xfd->stream.para.socket.ip.lowport); retropt_bool(opts, OPT_LOWPORT, &sfd->para.socket.ip.lowport);
xfd->stream.dtype = XIODATA_RECVFROM_ONE; xfd->stream.dtype = XIODATA_RECVFROM_ONE;
if ((result = if ((result =
_xioopen_dgram_recvfrom(&xfd->stream, xioflags, &us.soa, uslen, _xioopen_dgram_recvfrom(sfd, xioflags, &us.soa, uslen,
opts, pf, socktype, ipproto, E_ERROR)) opts, pf, socktype, ipproto, E_ERROR))
!= STAT_OK) { != STAT_OK) {
return result; return result;
@ -578,10 +593,17 @@ int xioopen_udp_recvfrom(int argc, const char *argv[], struct opt *opts,
} }
static static int xioopen_udp_recv(
int xioopen_udp_recv(int argc, const char *argv[], struct opt *opts, int argc,
int xioflags, xiofile_t *xfd, groups_t groups, const char *argv[],
int pf, int socktype, int ipproto) { struct opt *opts,
int xioflags,
xiofile_t *xfd,
const struct addrdesc *addrdesc)
{
int pf = addrdesc->arg1;
int socktype = addrdesc->arg2;
int ipproto = addrdesc->arg3;
union sockaddr_union us; union sockaddr_union us;
socklen_t uslen = sizeof(us); socklen_t uslen = sizeof(us);
char *rangename; char *rangename;
@ -589,8 +611,7 @@ int xioopen_udp_recv(int argc, const char *argv[], struct opt *opts,
int result; int result;
if (argc != 2) { if (argc != 2) {
Error2("%s: wrong number of parameters (%d instead of 1)", xio_syntax(argv[0], 1, argc-1, addrdesc->syntax);
argv[0], argc-1);
return STAT_NORETRY; return STAT_NORETRY;
} }

View file

@ -28,9 +28,6 @@ extern int _xioopen_ipdgram_listen(struct single *sfd,
int xioflags, union sockaddr_union *us, socklen_t uslen, int xioflags, union sockaddr_union *us, socklen_t uslen,
struct opt *opts, int pf, int socktype, int ipproto); struct opt *opts, int pf, int socktype, int ipproto);
extern int xioopen_ipdgram_listen(int argc, const char *argv[], struct opt *opts, extern int xioopen_ipdgram_listen(int argc, const char *argv[], struct opt *opts, int rw, xiofile_t *xfd, const struct addrdesc *addrdesc);
int rw, xiofile_t *fd,
groups_t groups, int af, int ipproto,
int protname);
#endif /* !defined(__xio_udp_h_included) */ #endif /* !defined(__xio_udp_h_included) */

View file

@ -24,16 +24,12 @@
# define ABSTRACT 0 # define ABSTRACT 0
#endif #endif
static int xioopen_unix_connect(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *xxfd, groups_t groups, int abstract, int dummy2, int dummy3); static int xioopen_unix_connect(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *xxfd, const struct addrdesc *addrdesc);
static int xioopen_unix_listen(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *xxfd, groups_t groups, int abstract, int dummy2, int dummy3); static int xioopen_unix_listen(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *xxfd, const struct addrdesc *addrdesc);
static int xioopen_unix_sendto(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *xxfd, groups_t groups, int abstract, int dummy2, int dummy3); static int xioopen_unix_sendto(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *xxfd, const struct addrdesc *addrdesc);
static int xioopen_unix_recvfrom(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *xxfd, groups_t groups, int abstract, int dummy2, int dummy3); static int xioopen_unix_recvfrom(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *xxfd, const struct addrdesc *addrdesc);
static static int xioopen_unix_recv(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *xxfd, const struct addrdesc *addrdesc);
int xioopen_unix_recv(int argc, const char *argv[], struct opt *opts, static int xioopen_unix_client(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *xxfd, const struct addrdesc *addrdesc);
int xioflags, xiofile_t *xxfd, groups_t groups,
int abstract, int dummy2, int dummy3);
static
int xioopen_unix_client(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *xxfd, groups_t groups, int abstract, int dummy2, int dummy3);
/* the first free parameter is 0 for "normal" unix domain sockets, or 1 for /* the first free parameter is 0 for "normal" unix domain sockets, or 1 for
abstract unix sockets (Linux); the second and third free parameter are abstract unix sockets (Linux); the second and third free parameter are
@ -115,10 +111,17 @@ xiosetunix(int pf,
} }
#if WITH_LISTEN #if WITH_LISTEN
static int xioopen_unix_listen(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *xxfd, groups_t groups, int abstract, int dummy2, int dummy3) { static int xioopen_unix_listen(
int argc,
const char *argv[],
struct opt *opts,
int xioflags,
xiofile_t *xxfd,
const struct addrdesc *addrdesc)
{
/* we expect the form: filename */ /* we expect the form: filename */
const char *name; const char *name;
xiosingle_t *xfd = &xxfd->stream; xiosingle_t *sfd = &xxfd->stream;
int pf = PF_UNIX; int pf = PF_UNIX;
int socktype = SOCK_STREAM; int socktype = SOCK_STREAM;
int protocol = 0; int protocol = 0;
@ -127,35 +130,35 @@ static int xioopen_unix_listen(int argc, const char *argv[], struct opt *opts, i
struct opt *opts0 = NULL; struct opt *opts0 = NULL;
pid_t pid = Getpid(); pid_t pid = Getpid();
bool opt_unlink_early = false; bool opt_unlink_early = false;
bool opt_unlink_close = (abstract != 1); bool opt_unlink_close = (addrdesc->arg1/*abstract*/ != 1);
int result; int result;
if (argc != 2) { if (argc != 2) {
Error2("%s: wrong number of parameters (%d instead of 1)", xio_syntax(argv[0], 1, argc-1, addrdesc->syntax);
argv[0], argc-1);
return STAT_NORETRY; return STAT_NORETRY;
} }
name = argv[1]; name = argv[1];
xfd->para.socket.un.tight = true; sfd->para.socket.un.tight = true;
retropt_socket_pf(opts, &pf); retropt_socket_pf(opts, &pf);
xfd->howtoend = END_SHUTDOWN; sfd->howtoend = END_SHUTDOWN;
if (!(ABSTRACT && abstract)) { if (!(ABSTRACT && addrdesc->arg1/*abstract*/)) {
/* only for non abstract because abstract do not work in file system */ /* only for non abstract because abstract do not work in file system */
retropt_bool(opts, OPT_UNLINK_EARLY, &opt_unlink_early); retropt_bool(opts, OPT_UNLINK_EARLY, &opt_unlink_early);
retropt_bool(opts, OPT_UNLINK_CLOSE, &opt_unlink_close); retropt_bool(opts, OPT_UNLINK_CLOSE, &opt_unlink_close);
} }
if (applyopts_single(xfd, opts, PH_INIT) < 0) return STAT_NORETRY; if (applyopts_single(sfd, opts, PH_INIT) < 0) return STAT_NORETRY;
applyopts(xfd, -1, opts, PH_INIT); applyopts(sfd, -1, opts, PH_INIT);
applyopts_named(name, opts, PH_EARLY); /* umask! */ applyopts_named(name, opts, PH_EARLY); /* umask! */
applyopts_offset(xfd, opts); applyopts_offset(sfd, opts);
applyopts(xfd, -1, opts, PH_EARLY); applyopts(sfd, -1, opts, PH_EARLY);
uslen = xiosetunix(pf, &us, name, abstract, xfd->para.socket.un.tight); uslen = xiosetunix(pf, &us, name, addrdesc->arg1/*abstract*/,
sfd->para.socket.un.tight);
if (!(ABSTRACT && abstract)) { if (!(ABSTRACT && addrdesc->arg1/*abstract*/)) {
if (opt_unlink_early) { if (opt_unlink_early) {
xio_unlink(name, E_ERROR); xio_unlink(name, E_ERROR);
} else { } else {
@ -166,10 +169,10 @@ static int xioopen_unix_listen(int argc, const char *argv[], struct opt *opts, i
} }
} }
if (opt_unlink_close) { if (opt_unlink_close) {
if ((xfd->unlink_close = strdup(name)) == NULL) { if ((sfd->unlink_close = strdup(name)) == NULL) {
Error1("strdup(\"%s\"): out of memory", name); Error1("strdup(\"%s\"): out of memory", name);
} }
xfd->opt_unlink_close = true; sfd->opt_unlink_close = true;
} }
/* trying to set user-early, perm-early etc. here is useless because /* trying to set user-early, perm-early etc. here is useless because
@ -180,17 +183,17 @@ static int xioopen_unix_listen(int argc, const char *argv[], struct opt *opts, i
/* this may fork() */ /* this may fork() */
if ((result = if ((result =
xioopen_listen(xfd, xioflags, xioopen_listen(sfd, xioflags,
(struct sockaddr *)&us, uslen, (struct sockaddr *)&us, uslen,
opts, opts0, pf, socktype, protocol)) opts, opts0, pf, socktype, protocol))
!= 0) != 0)
return result; return result;
if (!(ABSTRACT && abstract)) { if (!(ABSTRACT && addrdesc->arg1/*abstract*/)) {
if (opt_unlink_close) { if (opt_unlink_close) {
if (pid != Getpid()) { if (pid != Getpid()) {
/* in a child process - do not unlink-close here! */ /* in a child process - do not unlink-close here! */
xfd->opt_unlink_close = false; sfd->opt_unlink_close = false;
} }
} }
} }
@ -200,10 +203,17 @@ static int xioopen_unix_listen(int argc, const char *argv[], struct opt *opts, i
#endif /* WITH_LISTEN */ #endif /* WITH_LISTEN */
static int xioopen_unix_connect(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *xxfd, groups_t groups, int abstract, int dummy2, int dummy3) { static int xioopen_unix_connect(
int argc,
const char *argv[],
struct opt *opts,
int xioflags,
xiofile_t *xxfd,
const struct addrdesc *addrdesc)
{
/* we expect the form: filename */ /* we expect the form: filename */
const char *name; const char *name;
struct single *xfd = &xxfd->stream; struct single *sfd = &xxfd->stream;
const struct opt *namedopt; const struct opt *namedopt;
int pf = PF_UNIX; int pf = PF_UNIX;
int socktype = SOCK_STREAM; int socktype = SOCK_STREAM;
@ -211,7 +221,7 @@ static int xioopen_unix_connect(int argc, const char *argv[], struct opt *opts,
struct sockaddr_un them, us; struct sockaddr_un them, us;
socklen_t themlen, uslen = sizeof(us); socklen_t themlen, uslen = sizeof(us);
bool needbind = false; bool needbind = false;
bool opt_unlink_close = (abstract != 1); bool opt_unlink_close = (addrdesc->arg1/*abstract*/ != 1);
bool dofork = false; bool dofork = false;
struct opt *opts0; struct opt *opts0;
char infobuff[256]; char infobuff[256];
@ -219,29 +229,30 @@ static int xioopen_unix_connect(int argc, const char *argv[], struct opt *opts,
int result; int result;
if (argc != 2) { if (argc != 2) {
Error2("%s: wrong number of parameters (%d instead of 1)", xio_syntax(argv[0], 1, argc-1, addrdesc->syntax);
argv[0], argc-1);
return STAT_NORETRY; return STAT_NORETRY;
} }
name = argv[1]; name = argv[1];
xfd->para.socket.un.tight = true; sfd->para.socket.un.tight = true;
retropt_socket_pf(opts, &pf); retropt_socket_pf(opts, &pf);
xfd->howtoend = END_SHUTDOWN; sfd->howtoend = END_SHUTDOWN;
if (applyopts_single(xfd, opts, PH_INIT) < 0) return STAT_NORETRY; if (applyopts_single(sfd, opts, PH_INIT) < 0) return STAT_NORETRY;
applyopts(xfd, -1, opts, PH_INIT); applyopts(sfd, -1, opts, PH_INIT);
applyopts_offset(xfd, opts); applyopts_offset(sfd, opts);
applyopts(xfd, -1, opts, PH_EARLY); applyopts(sfd, -1, opts, PH_EARLY);
themlen = xiosetunix(pf, &them, name, abstract, xfd->para.socket.un.tight); themlen = xiosetunix(pf, &them, name, addrdesc->arg1/*abstract*/,
sfd->para.socket.un.tight);
if (!(ABSTRACT && abstract)) { if (!(ABSTRACT && addrdesc->arg1/*abstract*/)) {
/* only for non abstract because abstract do not work in file system */ /* Only for non abstract because abstract do not work in file system */
retropt_bool(opts, OPT_UNLINK_CLOSE, &opt_unlink_close); retropt_bool(opts, OPT_UNLINK_CLOSE, &opt_unlink_close);
} }
if (retropt_bind(opts, pf, socktype, protocol, (struct sockaddr *)&us, &uslen, if (retropt_bind(opts, pf, socktype, protocol, (struct sockaddr *)&us, &uslen,
(abstract<<1)|xfd->para.socket.un.tight, NULL) (addrdesc->arg1/*abstract*/<<1)|sfd->para.socket.un.tight,
== STAT_OK) { sfd->para.socket.ip.ai_flags)
== STAT_OK) {
needbind = true; needbind = true;
} }
@ -251,10 +262,10 @@ static int xioopen_unix_connect(int argc, const char *argv[], struct opt *opts,
} }
if (opt_unlink_close && needbind) { if (opt_unlink_close && needbind) {
if ((xfd->unlink_close = strdup(us.sun_path)) == NULL) { if ((sfd->unlink_close = strdup(us.sun_path)) == NULL) {
Error1("strdup(\"%s\"): out of memory", name); Error1("strdup(\"%s\"): out of memory", name);
} }
xfd->opt_unlink_close = true; sfd->opt_unlink_close = true;
} }
retropt_bool(opts, OPT_FORK, &dofork); retropt_bool(opts, OPT_FORK, &dofork);
@ -267,14 +278,14 @@ static int xioopen_unix_connect(int argc, const char *argv[], struct opt *opts,
do { /* loop over retries and forks */ do { /* loop over retries and forks */
#if WITH_RETRY #if WITH_RETRY
if (xfd->forever || xfd->retry) { if (sfd->forever || sfd->retry) {
level = E_INFO; level = E_INFO;
} else } else
#endif /* WITH_RETRY */ #endif /* WITH_RETRY */
level = E_ERROR; level = E_ERROR;
result = result =
_xioopen_connect(xfd, _xioopen_connect(sfd,
needbind?(union sockaddr_union *)&us:NULL, uslen, needbind?(union sockaddr_union *)&us:NULL, uslen,
(struct sockaddr *)&them, themlen, (struct sockaddr *)&them, themlen,
opts, pf, socktype, protocol, false, level); opts, pf, socktype, protocol, false, level);
@ -289,10 +300,10 @@ static int xioopen_unix_connect(int argc, const char *argv[], struct opt *opts,
case STAT_OK: break; case STAT_OK: break;
#if WITH_RETRY #if WITH_RETRY
case STAT_RETRYLATER: case STAT_RETRYLATER:
if (xfd->forever || xfd->retry) { if (sfd->forever || sfd->retry) {
--xfd->retry; --sfd->retry;
if (result == STAT_RETRYLATER) { if (result == STAT_RETRYLATER) {
Nanosleep(&xfd->intervall, NULL); Nanosleep(&sfd->intervall, NULL);
} }
dropopts(opts, PH_ALL); opts = copyopts(opts0, GROUP_ALL); dropopts(opts, PH_ALL); opts = copyopts(opts0, GROUP_ALL);
continue; continue;
@ -311,16 +322,16 @@ static int xioopen_unix_connect(int argc, const char *argv[], struct opt *opts,
if (dofork) { if (dofork) {
pid_t pid; pid_t pid;
int level = E_ERROR; int level = E_ERROR;
if (xfd->forever || xfd->retry) { if (sfd->forever || sfd->retry) {
level = E_WARN; /* most users won't expect a problem here, level = E_WARN; /* most users won't expect a problem here,
so Notice is too weak */ so Notice is too weak */
} }
while ((pid = xio_fork(false, level, xfd->shutup)) < 0) { while ((pid = xio_fork(false, level, sfd->shutup)) < 0) {
--xfd->retry; --sfd->retry;
if (xfd->forever || xfd->retry) { if (sfd->forever || sfd->retry) {
dropopts(opts, PH_ALL); opts = copyopts(opts0, GROUP_ALL); dropopts(opts, PH_ALL); opts = copyopts(opts0, GROUP_ALL);
Nanosleep(&xfd->intervall, NULL); continue; Nanosleep(&sfd->intervall, NULL); continue;
} }
return STAT_RETRYLATER; return STAT_RETRYLATER;
} }
@ -330,9 +341,9 @@ static int xioopen_unix_connect(int argc, const char *argv[], struct opt *opts,
} }
/* parent process */ /* parent process */
Close(xfd->fd); Close(sfd->fd);
/* with and without retry */ /* with and without retry */
Nanosleep(&xfd->intervall, NULL); Nanosleep(&sfd->intervall, NULL);
dropopts(opts, PH_ALL); opts = copyopts(opts0, GROUP_ALL); dropopts(opts, PH_ALL); opts = copyopts(opts0, GROUP_ALL);
continue; /* with next socket() bind() connect() */ continue; /* with next socket() bind() connect() */
} else } else
@ -342,17 +353,31 @@ static int xioopen_unix_connect(int argc, const char *argv[], struct opt *opts,
} }
} while (true); } while (true);
if ((result = _xio_openlate(xfd, opts)) < 0) { if (opt_unlink_close && needbind) {
if ((sfd->unlink_close = strndup(us.sun_path, sizeof(us.sun_path))) == NULL) {
Error2("strndup(\"%s\", "F_Zu"): out of memory", name, sizeof(us.sun_path));
}
sfd->opt_unlink_close = true;
}
if ((result = _xio_openlate(sfd, opts)) < 0) {
return result; return result;
} }
return STAT_OK; return STAT_OK;
} }
static int xioopen_unix_sendto(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *xxfd, groups_t groups, int abstract, int dummy, int dummy3) { static int xioopen_unix_sendto(
int argc,
const char *argv[],
struct opt *opts,
int xioflags,
xiofile_t *xxfd,
const struct addrdesc *addrdesc)
{
/* we expect the form: filename */ /* we expect the form: filename */
const char *name; const char *name;
xiosingle_t *xfd = &xxfd->stream; xiosingle_t *sfd = &xxfd->stream;
const struct opt *namedopt; const struct opt *namedopt;
int pf = PF_UNIX; int pf = PF_UNIX;
int socktype = SOCK_DGRAM; int socktype = SOCK_DGRAM;
@ -360,33 +385,33 @@ static int xioopen_unix_sendto(int argc, const char *argv[], struct opt *opts, i
union sockaddr_union us; union sockaddr_union us;
socklen_t uslen = sizeof(us); socklen_t uslen = sizeof(us);
bool needbind = false; bool needbind = false;
bool opt_unlink_close = (abstract != 1); bool opt_unlink_close = (addrdesc->arg1/*abstract*/ != 1);
int result; int result;
if (argc != 2) { if (argc != 2) {
Error2("%s: wrong number of parameters (%d instead of 1)", xio_syntax(argv[0], 1, argc-1, addrdesc->syntax);
argv[0], argc-1);
return STAT_NORETRY; return STAT_NORETRY;
} }
name = argv[1]; name = argv[1];
xfd->para.socket.un.tight = true; sfd->para.socket.un.tight = true;
retropt_socket_pf(opts, &pf); retropt_socket_pf(opts, &pf);
xfd->howtoend = END_SHUTDOWN; sfd->howtoend = END_SHUTDOWN;
applyopts_offset(xfd, opts); applyopts_offset(sfd, opts);
xfd->salen = xiosetunix(pf, &xfd->peersa.un, name, abstract, xfd->para.socket.un.tight); sfd->salen = xiosetunix(pf, &sfd->peersa.un, name, addrdesc->arg1/*abstract*/, sfd->para.socket.un.tight);
if (!(ABSTRACT && abstract)) { if (!(ABSTRACT && addrdesc->arg1/*abstract*/)) {
/* only for non abstract because abstract do not work in file system */ /* only for non abstract because abstract do not work in file system */
retropt_bool(opts, OPT_UNLINK_CLOSE, &opt_unlink_close); retropt_bool(opts, OPT_UNLINK_CLOSE, &opt_unlink_close);
} }
xfd->dtype = XIODATA_RECVFROM; sfd->dtype = XIODATA_RECVFROM;
if (retropt_bind(opts, pf, socktype, protocol, &us.soa, &uslen, if (retropt_bind(opts, pf, socktype, protocol, &us.soa, &uslen,
(abstract<<1)| xfd->para.socket.un.tight, NULL) (addrdesc->arg1/*abstract*/<<1)| sfd->para.socket.un.tight,
== STAT_OK) { sfd->para.socket.ip.ai_flags)
== STAT_OK) {
needbind = true; needbind = true;
} }
@ -395,34 +420,39 @@ static int xioopen_unix_sendto(int argc, const char *argv[], struct opt *opts, i
Error1("Option \"%s\" only with bind option", namedopt->desc->defname); Error1("Option \"%s\" only with bind option", namedopt->desc->defname);
} }
if (applyopts_single(xfd, opts, PH_INIT) < 0) return -1; if (applyopts_single(sfd, opts, PH_INIT) < 0) return -1;
applyopts(xfd, -1, opts, PH_INIT); applyopts(sfd, -1, opts, PH_INIT);
result = result =
_xioopen_dgram_sendto(needbind?(union sockaddr_union *)&us:NULL, uslen, _xioopen_dgram_sendto(needbind?(union sockaddr_union *)&us:NULL, uslen,
opts, xioflags, xfd, groups, opts, xioflags, sfd, addrdesc->groups,
pf, socktype, protocol, 0); pf, socktype, protocol, 0);
if (result != 0) { if (result != 0) {
return result; return result;
} }
if (opt_unlink_close && needbind) { if (opt_unlink_close && needbind) {
if ((xfd->unlink_close = strdup(us.un.sun_path)) == NULL) { if ((sfd->unlink_close = strndup(us.un.sun_path, sizeof(us.un.sun_path))) == NULL) {
Error1("strdup(\"%s\"): out of memory", name); Error2("strndup(\"%s\", "F_Zu"): out of memory", name, sizeof(us.un.sun_path));
} }
xfd->opt_unlink_close = true; sfd->opt_unlink_close = true;
} }
return STAT_OK; return STAT_OK;
} }
static static
int xioopen_unix_recvfrom(int argc, const char *argv[], struct opt *opts, int xioopen_unix_recvfrom(
int xioflags, xiofile_t *xxfd, groups_t groups, int argc,
int abstract, int dummy2, int dummy3) { const char *argv[],
struct opt *opts,
int xioflags,
xiofile_t *xxfd,
const struct addrdesc *addrdesc)
{
/* we expect the form: filename */ /* we expect the form: filename */
const char *name; const char *name;
xiosingle_t *xfd = &xxfd->stream; xiosingle_t *sfd = &xxfd->stream;
int pf = PF_UNIX; int pf = PF_UNIX;
int socktype = SOCK_DGRAM; int socktype = SOCK_DGRAM;
int protocol = 0; int protocol = 0;
@ -430,40 +460,41 @@ int xioopen_unix_recvfrom(int argc, const char *argv[], struct opt *opts,
socklen_t uslen; socklen_t uslen;
bool needbind = true; bool needbind = true;
bool opt_unlink_early = false; bool opt_unlink_early = false;
bool opt_unlink_close = (abstract != 1); bool opt_unlink_close = (addrdesc->arg1/*abstract*/ != 1);
if (argc != 2) { if (argc != 2) {
Error2("%s: wrong number of parameters (%d instead of 1)", xio_syntax(argv[0], 1, argc-1, addrdesc->syntax);
argv[0], argc-1);
return STAT_NORETRY; return STAT_NORETRY;
} }
name = argv[1]; name = argv[1];
xfd->para.socket.un.tight = true; sfd->para.socket.un.tight = true;
retropt_socket_pf(opts, &pf); retropt_socket_pf(opts, &pf);
xfd->howtoend = END_NONE; sfd->howtoend = END_NONE;
if (applyopts_single(xfd, opts, PH_INIT) < 0) return STAT_NORETRY; if (applyopts_single(sfd, opts, PH_INIT) < 0) return STAT_NORETRY;
applyopts(xfd, -1, opts, PH_INIT); applyopts(sfd, -1, opts, PH_INIT);
applyopts_named(name, opts, PH_EARLY); /* umask! */ applyopts_named(name, opts, PH_EARLY); /* umask! */
applyopts_offset(xfd, opts); applyopts_offset(sfd, opts);
if (!(ABSTRACT && abstract)) { if (!(ABSTRACT && addrdesc->arg1/*abstract*/)) {
/* only for non abstract because abstract do not work in file system */ /* only for non abstract because abstract do not work in file system */
retropt_bool(opts, OPT_UNLINK_EARLY, &opt_unlink_early); retropt_bool(opts, OPT_UNLINK_EARLY, &opt_unlink_early);
retropt_bool(opts, OPT_UNLINK_CLOSE, &opt_unlink_close); retropt_bool(opts, OPT_UNLINK_CLOSE, &opt_unlink_close);
} }
applyopts(xfd, -1, opts, PH_EARLY); applyopts(sfd, -1, opts, PH_EARLY);
uslen = xiosetunix(pf, &us, name, abstract, xfd->para.socket.un.tight); uslen = xiosetunix(pf, &us, name, addrdesc->arg1/*abstract*/,
sfd->para.socket.un.tight);
#if 0 #if 0
if (retropt_bind(opts, pf, socktype, protocol, (struct sockaddr *)&us, &uslen, if (retropt_bind(opts, pf, socktype, protocol, (struct sockaddr *)&us, &uslen,
(abstract<<1)|xfd->para.socket.un.tight, NULL) (addrdesc->arg1/*abstract*/<<1)|sfd->para.socket.un.tight,
== STAT_OK) { sfd->para.socket.ip.ai_flags)) {
== STAT_OK) {
} }
#endif #endif
if (!(ABSTRACT && abstract)) { if (!(ABSTRACT && addrdesc->arg1/*abstract*/)) {
if (opt_unlink_early) { if (opt_unlink_early) {
xio_unlink(name, E_ERROR); xio_unlink(name, E_ERROR);
} else { } else {
@ -474,10 +505,10 @@ int xioopen_unix_recvfrom(int argc, const char *argv[], struct opt *opts,
} }
} }
if (opt_unlink_close) { if (opt_unlink_close) {
if ((xfd->unlink_close = strdup(name)) == NULL) { if ((sfd->unlink_close = strdup(name)) == NULL) {
Error1("strdup(\"%s\"): out of memory", name); Error1("strdup(\"%s\"): out of memory", name);
} }
xfd->opt_unlink_close = true; sfd->opt_unlink_close = true;
} }
/* trying to set user-early, perm-early etc. here is useless because /* trying to set user-early, perm-early etc. here is useless because
@ -485,66 +516,71 @@ int xioopen_unix_recvfrom(int argc, const char *argv[], struct opt *opts,
} }
applyopts_named(name, opts, PH_EARLY); /* umask! */ applyopts_named(name, opts, PH_EARLY); /* umask! */
xfd->para.socket.la.soa.sa_family = pf; sfd->para.socket.la.soa.sa_family = pf;
xfd->dtype = XIODATA_RECVFROM_ONE; sfd->dtype = XIODATA_RECVFROM_ONE;
/* this may fork */ /* this may fork */
return return
_xioopen_dgram_recvfrom(xfd, xioflags, _xioopen_dgram_recvfrom(sfd, xioflags,
needbind?(struct sockaddr *)&us:NULL, uslen, needbind?(struct sockaddr *)&us:NULL, uslen,
opts, pf, socktype, protocol, E_ERROR); opts, pf, socktype, protocol, E_ERROR);
} }
static static int xioopen_unix_recv(
int xioopen_unix_recv(int argc, const char *argv[], struct opt *opts, int argc,
int xioflags, xiofile_t *xxfd, groups_t groups, const char *argv[],
int abstract, int dummy2, int dummy3) { struct opt *opts,
int xioflags,
xiofile_t *xxfd,
const struct addrdesc *addrdesc)
{
/* we expect the form: filename */ /* we expect the form: filename */
const char *name; const char *name;
xiosingle_t *xfd = &xxfd->stream; xiosingle_t *sfd = &xxfd->stream;
int pf = PF_UNIX; int pf = PF_UNIX;
int socktype = SOCK_DGRAM; int socktype = SOCK_DGRAM;
int protocol = 0; int protocol = 0;
union sockaddr_union us; union sockaddr_union us;
socklen_t uslen; socklen_t uslen;
bool opt_unlink_early = false; bool opt_unlink_early = false;
bool opt_unlink_close = (abstract != 1); bool opt_unlink_close = (addrdesc->arg1/*abstract*/ != 1);
int result; int result;
if (argc != 2) { if (argc != 2) {
Error2("%s: wrong number of parameters (%d instead of 1)", xio_syntax(argv[0], 1, argc-1, addrdesc->syntax);
argv[0], argc-1);
return STAT_NORETRY; return STAT_NORETRY;
} }
name = argv[1]; name = argv[1];
xfd->para.socket.un.tight = true; sfd->para.socket.un.tight = true;
retropt_socket_pf(opts, &pf); retropt_socket_pf(opts, &pf);
xfd->howtoend = END_SHUTDOWN; sfd->howtoend = END_SHUTDOWN;
if (applyopts_single(xfd, opts, PH_INIT) < 0) return STAT_NORETRY; if (applyopts_single(sfd, opts, PH_INIT) < 0) return STAT_NORETRY;
applyopts(xfd, -1, opts, PH_INIT); applyopts(sfd, -1, opts, PH_INIT);
applyopts_named(name, opts, PH_EARLY); /* umask! */ applyopts_named(name, opts, PH_EARLY); /* umask! */
applyopts_offset(xfd, opts); applyopts_offset(sfd, opts);
if (!(ABSTRACT && abstract)) { if (!(ABSTRACT && addrdesc->arg1/*abstract*/)) {
/* only for non abstract because abstract do not work in file system */ /* only for non abstract because abstract do not work in file system */
retropt_bool(opts, OPT_UNLINK_EARLY, &opt_unlink_early); retropt_bool(opts, OPT_UNLINK_EARLY, &opt_unlink_early);
retropt_bool(opts, OPT_UNLINK_CLOSE, &opt_unlink_close); retropt_bool(opts, OPT_UNLINK_CLOSE, &opt_unlink_close);
} }
applyopts(xfd, -1, opts, PH_EARLY); applyopts(sfd, -1, opts, PH_EARLY);
uslen = xiosetunix(pf, &us.un, name, abstract, xfd->para.socket.un.tight); uslen = xiosetunix(pf, &us.un, name, addrdesc->arg1/*abstract*/,
sfd->para.socket.un.tight);
#if 0 #if 0
if (retropt_bind(opts, pf, socktype, protocol, &us.soa, &uslen, if (retropt_bind(opts, pf, socktype, protocol, &us.soa, &uslen,
(abstract<<1)|xfd->para.socket.un.tight, NULL) (addrdesc->arg1/*abstract*/<<1)|sfd->para.socket.un.tight,
sfd->para.socket.ip.ai_flags)
== STAT_OK) { == STAT_OK) {
} }
#endif #endif
if (!(ABSTRACT && abstract)) { if (!(ABSTRACT && addrdesc->arg1/*abstract*/)) {
if (opt_unlink_early) { if (opt_unlink_early) {
xio_unlink(name, E_ERROR); xio_unlink(name, E_ERROR);
} else { } else {
@ -555,33 +591,41 @@ int xioopen_unix_recv(int argc, const char *argv[], struct opt *opts,
} }
} }
if (opt_unlink_close) { if (opt_unlink_close) {
if ((xfd->unlink_close = strdup(name)) == NULL) { if ((sfd->unlink_close = strdup(name)) == NULL) {
Error1("strdup(\"%s\"): out of memory", name); Error1("strdup(\"%s\"): out of memory", name);
} }
xfd->opt_unlink_close = true; sfd->opt_unlink_close = true;
} }
} }
applyopts_named(name, opts, PH_EARLY); /* umask! */ applyopts_named(name, opts, PH_EARLY); /* umask! */
xfd->para.socket.la.soa.sa_family = pf; sfd->para.socket.la.soa.sa_family = pf;
xfd->dtype = XIODATA_RECV; sfd->dtype = XIODATA_RECV;
result = _xioopen_dgram_recv(xfd, xioflags, &us.soa, uslen, result = _xioopen_dgram_recv(sfd, xioflags, &us.soa, uslen,
opts, pf, socktype, protocol, E_ERROR); opts, pf, socktype, protocol, E_ERROR);
return result; return result;
} }
/* generic UNIX socket client, tries connect, SEQPACKET, send(to) */ /* generic UNIX socket client, tries connect, SEQPACKET, send(to) */
static int xioopen_unix_client(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *xxfd, groups_t groups, int abstract, int dummy2, int dummy3) { static int xioopen_unix_client(
int argc,
const char *argv[],
struct opt *opts,
int xioflags,
xiofile_t *xxfd,
const struct addrdesc *addrdesc)
{
/* we expect the form: filename */ /* we expect the form: filename */
if (argc != 2) { if (argc != 2) {
Error2("%s: wrong number of parameters (%d instead of 1)", argv[0], argc-1); xio_syntax(argv[0], 1, argc-1, addrdesc->syntax);
return STAT_NORETRY;
} }
return return
_xioopen_unix_client(&xxfd->stream, xioflags, groups, abstract, opts, _xioopen_unix_client(&xxfd->stream, xioflags, addrdesc->groups,
argv[1]); addrdesc->arg1/*abstract*/, opts, argv[1]);
} }
/* establishes communication with an existing UNIX type socket. supports stream /* establishes communication with an existing UNIX type socket. supports stream
@ -595,7 +639,7 @@ static int xioopen_unix_client(int argc, const char *argv[], struct opt *opts, i
OPT_SO_TYPE, OPT_SO_PROTOTYPE, OPT_CLOEXEC, OPT_USER, OPT_GROUP, ?OPT_FORK, OPT_SO_TYPE, OPT_SO_PROTOTYPE, OPT_CLOEXEC, OPT_USER, OPT_GROUP, ?OPT_FORK,
*/ */
int int
_xioopen_unix_client(xiosingle_t *xfd, int xioflags, groups_t groups, _xioopen_unix_client(xiosingle_t *sfd, int xioflags, groups_t groups,
int abstract, struct opt *opts, const char *name) { int abstract, struct opt *opts, const char *name) {
const struct opt *namedopt; const struct opt *namedopt;
int pf = PF_UNIX; int pf = PF_UNIX;
@ -608,23 +652,24 @@ _xioopen_unix_client(xiosingle_t *xfd, int xioflags, groups_t groups,
struct opt *opts0; struct opt *opts0;
int result; int result;
xfd->para.socket.un.tight = true; sfd->para.socket.un.tight = true;
retropt_socket_pf(opts, &pf); retropt_socket_pf(opts, &pf);
xfd->howtoend = END_SHUTDOWN; sfd->howtoend = END_SHUTDOWN;
if (applyopts_single(xfd, opts, PH_INIT) < 0) return STAT_NORETRY; if (applyopts_single(sfd, opts, PH_INIT) < 0) return STAT_NORETRY;
applyopts(xfd, -1, opts, PH_INIT); applyopts(sfd, -1, opts, PH_INIT);
applyopts_offset(xfd, opts); applyopts_offset(sfd, opts);
retropt_int(opts, OPT_SO_TYPE, &socktype); retropt_int(opts, OPT_SO_TYPE, &socktype);
retropt_int(opts, OPT_SO_PROTOTYPE, &protocol); retropt_int(opts, OPT_SO_PROTOTYPE, &protocol);
applyopts(xfd, -1, opts, PH_EARLY); applyopts(sfd, -1, opts, PH_EARLY);
themlen = xiosetunix(pf, &them.un, name, abstract, xfd->para.socket.un.tight); themlen = xiosetunix(pf, &them.un, name, abstract, sfd->para.socket.un.tight);
if (!(ABSTRACT && abstract)) { if (!(ABSTRACT && abstract)) {
/* only for non abstract because abstract do not work in file system */ /* only for non abstract because abstract do not work in file system */
retropt_bool(opts, OPT_UNLINK_CLOSE, &opt_unlink_close); retropt_bool(opts, OPT_UNLINK_CLOSE, &opt_unlink_close);
} }
if (retropt_bind(opts, pf, socktype, protocol, &us.soa, &uslen, if (retropt_bind(opts, pf, socktype, protocol, &us.soa, &uslen,
(abstract<<1)|xfd->para.socket.un.tight, NULL) (abstract<<1)|sfd->para.socket.un.tight,
sfd->para.socket.ip.ai_flags)
!= STAT_NOACTION) { != STAT_NOACTION) {
needbind = true; needbind = true;
} }
@ -635,10 +680,10 @@ _xioopen_unix_client(xiosingle_t *xfd, int xioflags, groups_t groups,
} }
if (opt_unlink_close) { if (opt_unlink_close) {
if ((xfd->unlink_close = strdup(name)) == NULL) { if ((sfd->unlink_close = strdup(name)) == NULL) {
Error1("strdup(\"%s\"): out of memory", name); Error1("strdup(\"%s\"): out of memory", name);
} }
xfd->opt_unlink_close = true; sfd->opt_unlink_close = true;
} }
/* save options, because we might have to start again */ /* save options, because we might have to start again */
@ -646,10 +691,10 @@ _xioopen_unix_client(xiosingle_t *xfd, int xioflags, groups_t groups,
/* just a breakable block, helps to avoid goto */ /* just a breakable block, helps to avoid goto */
do { do {
/* xfd->dtype = DATA_STREAM; // is default */ /* sfd->dtype = DATA_STREAM; // is default */
/* this function handles AF_UNIX with EPROTOTYPE specially for us */ /* this function handles AF_UNIX with EPROTOTYPE specially for us */
if ((result = if ((result =
_xioopen_connect(xfd, _xioopen_connect(sfd,
needbind?&us:NULL, uslen, needbind?&us:NULL, uslen,
&them.soa, themlen, &them.soa, themlen,
opts, pf, socktype?socktype:SOCK_STREAM, protocol, opts, pf, socktype?socktype:SOCK_STREAM, protocol,
@ -663,7 +708,7 @@ _xioopen_unix_client(xiosingle_t *xfd, int xioflags, groups_t groups,
socktype = SOCK_SEQPACKET; socktype = SOCK_SEQPACKET;
if ((result = if ((result =
_xioopen_connect(xfd, _xioopen_connect(sfd,
needbind?&us:NULL, uslen, needbind?&us:NULL, uslen,
(struct sockaddr *)&them, themlen, (struct sockaddr *)&them, themlen,
opts, pf, SOCK_SEQPACKET, protocol, opts, pf, SOCK_SEQPACKET, protocol,
@ -675,14 +720,14 @@ _xioopen_unix_client(xiosingle_t *xfd, int xioflags, groups_t groups,
xio_unlink(us.un.sun_path, E_ERROR); xio_unlink(us.un.sun_path, E_ERROR);
dropopts2(opts, PH_INIT, PH_SPEC); opts = opts0; dropopts2(opts, PH_INIT, PH_SPEC); opts = opts0;
xfd->peersa = them; sfd->peersa = them;
xfd->salen = sizeof(struct sockaddr_un); sfd->salen = sizeof(struct sockaddr_un);
if ((result = if ((result =
_xioopen_dgram_sendto(needbind?&us:NULL, uslen, _xioopen_dgram_sendto(needbind?&us:NULL, uslen,
opts, xioflags, xfd, groups, opts, xioflags, sfd, groups,
pf, SOCK_DGRAM, protocol, 0)) pf, SOCK_DGRAM, protocol, 0))
== 0) { == 0) {
xfd->dtype = XIODATA_RECVFROM; sfd->dtype = XIODATA_RECVFROM;
break; break;
} }
} while (0); } while (0);
@ -694,7 +739,7 @@ _xioopen_unix_client(xiosingle_t *xfd, int xioflags, groups_t groups,
return result; return result;
} }
if ((result = _xio_openlate(xfd, opts)) < 0) { if ((result = _xio_openlate(sfd, opts)) < 0) {
return result; return result;
} }
return 0; return 0;

View file

@ -13,12 +13,8 @@
#include "xio-socket.h" #include "xio-socket.h"
#include "xio-vsock.h" #include "xio-vsock.h"
static int xioopen_vsock_connect(int argc, const char *argv[], struct opt *opts, static int xioopen_vsock_connect(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *xxfd, const struct addrdesc *addrdesc);
int xioflags, xiofile_t *xxfd, groups_t groups, int abstract, static int xioopen_vsock_listen(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *xxfd, const struct addrdesc *addrdesc);
int dummy2, int dummy3);
static int xioopen_vsock_listen(int argc, const char *argv[], struct opt *opts,
int xioflags, xiofile_t *xxfd, groups_t groups, int abstract,
int dummy2, int dummy3);
static void xiolog_vsock_cid(void); static void xiolog_vsock_cid(void);
@ -45,26 +41,31 @@ static int vsock_addr_init(struct sockaddr_vm *sa, const char *cid_str,
/* Performs a few steps during opening an address of type VSOCK */ /* Performs a few steps during opening an address of type VSOCK */
static int vsock_init(struct opt *opts, struct single *xfd) { static int vsock_init(struct opt *opts, struct single *sfd) {
xfd->howtoend = END_SHUTDOWN; sfd->howtoend = END_SHUTDOWN;
if (applyopts_single(xfd, opts, PH_INIT) < 0) if (applyopts_single(sfd, opts, PH_INIT) < 0)
return STAT_NORETRY; return STAT_NORETRY;
applyopts(xfd, -1, opts, PH_INIT); applyopts(sfd, -1, opts, PH_INIT);
applyopts(xfd, -1, opts, PH_EARLY); applyopts(sfd, -1, opts, PH_EARLY);
xfd->dtype = XIODATA_STREAM; sfd->dtype = XIODATA_STREAM;
return STAT_OK; return STAT_OK;
} }
static int xioopen_vsock_connect(int argc, const char *argv[], struct opt *opts, static int xioopen_vsock_connect(
int xioflags, xiofile_t *xxfd, groups_t groups, int argc,
int abstract, int dummy2, int dummy3) { const char *argv[],
struct opt *opts,
int xioflags,
xiofile_t *xxfd,
const struct addrdesc *addrdesc)
{
/* we expect the form :cid:port */ /* we expect the form :cid:port */
struct single *xfd = &xxfd->stream; struct single *sfd = &xxfd->stream;
struct sockaddr_vm sa, sa_local; struct sockaddr_vm sa, sa_local;
socklen_t sa_len = sizeof(sa); socklen_t sa_len = sizeof(sa);
bool needbind = false; bool needbind = false;
@ -74,8 +75,7 @@ static int xioopen_vsock_connect(int argc, const char *argv[], struct opt *opts,
int ret; int ret;
if (argc != 3) { if (argc != 3) {
Error2("%s: wrong number of parameters (%d instead of 2)", xio_syntax(argv[0], 2, argc-1, addrdesc->syntax);
argv[0], argc-1);
return STAT_NORETRY; return STAT_NORETRY;
} }
@ -88,7 +88,7 @@ static int xioopen_vsock_connect(int argc, const char *argv[], struct opt *opts,
return ret; return ret;
} }
ret = vsock_init(opts, xfd); ret = vsock_init(opts, sfd);
if (ret) { if (ret) {
return ret; return ret;
} }
@ -96,19 +96,20 @@ static int xioopen_vsock_connect(int argc, const char *argv[], struct opt *opts,
xiolog_vsock_cid(); xiolog_vsock_cid();
ret = retropt_bind(opts, pf, socktype, protocol, ret = retropt_bind(opts, pf, socktype, protocol,
(struct sockaddr *)&sa_local, &sa_len, 3, NULL); (struct sockaddr *)&sa_local, &sa_len, 3,
sfd->para.socket.ip.ai_flags);
if (ret == STAT_NORETRY) if (ret == STAT_NORETRY)
return ret; return ret;
if (ret == STAT_OK) if (ret == STAT_OK)
needbind = true; needbind = true;
ret = xioopen_connect(xfd, needbind ? (union sockaddr_union *)&sa_local : NULL, ret = xioopen_connect(sfd, needbind ? (union sockaddr_union *)&sa_local : NULL,
sa_len, (struct sockaddr *)&sa, sizeof(sa), sa_len, (struct sockaddr *)&sa, sizeof(sa),
opts, pf, socktype, protocol, false); opts, pf, socktype, protocol, false);
if (ret) if (ret)
return ret; return ret;
ret = _xio_openlate(xfd, opts); ret = _xio_openlate(sfd, opts);
if (ret < 0) if (ret < 0)
return ret; return ret;
@ -117,11 +118,16 @@ static int xioopen_vsock_connect(int argc, const char *argv[], struct opt *opts,
#if WITH_LISTEN #if WITH_LISTEN
static int xioopen_vsock_listen(int argc, const char *argv[], struct opt *opts, static int xioopen_vsock_listen(
int xioflags, xiofile_t *xxfd, groups_t groups, int abstract, int argc,
int dummy2, int dummy3) { const char *argv[],
struct opt *opts,
int xioflags,
xiofile_t *xxfd,
const struct addrdesc *addrdesc)
{
/* we expect the form :port */ /* we expect the form :port */
struct single *xfd = &xxfd->stream; struct single *sfd = &xxfd->stream;
struct sockaddr_vm sa, sa_bind; struct sockaddr_vm sa, sa_bind;
socklen_t sa_len = sizeof(sa_bind); socklen_t sa_len = sizeof(sa_bind);
struct opt *opts0; struct opt *opts0;
@ -131,8 +137,7 @@ static int xioopen_vsock_listen(int argc, const char *argv[], struct opt *opts,
int ret; int ret;
if (argc != 2) { if (argc != 2) {
Error2("%s: wrong number of parameters (%d instead of 1)", xio_syntax(argv[0], 1, argc-1, addrdesc->syntax);
argv[0], argc-1);
return STAT_NORETRY; return STAT_NORETRY;
} }
@ -145,7 +150,7 @@ static int xioopen_vsock_listen(int argc, const char *argv[], struct opt *opts,
return ret; return ret;
} }
ret = vsock_init(opts, xfd); ret = vsock_init(opts, sfd);
if (ret) { if (ret) {
return ret; return ret;
} }
@ -153,7 +158,8 @@ static int xioopen_vsock_listen(int argc, const char *argv[], struct opt *opts,
opts0 = copyopts(opts, GROUP_ALL); opts0 = copyopts(opts, GROUP_ALL);
ret = retropt_bind(opts, pf, socktype, protocol, (struct sockaddr *)&sa_bind, ret = retropt_bind(opts, pf, socktype, protocol, (struct sockaddr *)&sa_bind,
&sa_len, 1, NULL); &sa_len, 1,
sfd->para.socket.ip.ai_flags);
if (ret == STAT_NORETRY) if (ret == STAT_NORETRY)
return ret; return ret;
if (ret == STAT_OK) if (ret == STAT_OK)
@ -162,7 +168,7 @@ static int xioopen_vsock_listen(int argc, const char *argv[], struct opt *opts,
xiolog_vsock_cid(); xiolog_vsock_cid();
/* this may fork() */ /* this may fork() */
return xioopen_listen(xfd, xioflags, (struct sockaddr *)&sa, sizeof(sa), return xioopen_listen(sfd, xioflags, (struct sockaddr *)&sa, sizeof(sa),
opts, opts0, pf, socktype, protocol); opts, opts0, pf, socktype, protocol);
} }
#endif /* WITH_LISTEN */ #endif /* WITH_LISTEN */

3
xio.h
View file

@ -355,8 +355,7 @@ typedef union bipipe {
struct addrdesc { struct addrdesc {
const char *defname; /* main (canonical) name of address */ const char *defname; /* main (canonical) name of address */
int directions; /* 1..read, 2..write, 3..both */ int directions; /* 1..read, 2..write, 3..both */
int (*func)(int argc, const char *argv[], struct opt *opts, int rw, xiofile_t *fd, groups_t groups, int (*func)(int argc, const char *argv[], struct opt *opts, int rw, xiofile_t *fd, const struct addrdesc *addrdesc);
int arg1, int arg2, int arg3);
groups_t groups; groups_t groups;
int arg1; int arg1;
int arg2; int arg2;

View file

@ -218,4 +218,16 @@ int xioopenhelp(FILE *of,
return 0; return 0;
} }
/* This function may be used by address handling code to log syntax error */
int xiohelp_syntax(
const char *addr,
int expectnum,
int isnum,
const char *syntax)
{
Error4("%s: wrong number of parameters (%d instead of %d): usage: %s",
addr, isnum, expectnum, syntax);
return -1;
}
#endif /* WITH_HELP */ #endif /* WITH_HELP */

View file

@ -11,4 +11,6 @@ extern int xioopenhelp(FILE *of,
int level /* 0..only addresses, 1..and options */ int level /* 0..only addresses, 1..and options */
); );
extern int xiohelp_syntax(const char *addr, int expectnum, int isnum, const char *syntax);
#endif /* !defined(__xiohelp_h_included) */ #endif /* !defined(__xiohelp_h_included) */

View file

@ -8,11 +8,11 @@
#include "xioopen.h" #include "xioopen.h"
#include "xiomodes.h" #include "xiomodes.h"
#include "xiohelp.h"
#include "nestlex.h" #include "nestlex.h"
static xiofile_t *xioallocfd(void); static xiofile_t *xioallocfd(void);
xiosingle_t hugo;
static xiosingle_t *xioparse_single(const char **addr); static xiosingle_t *xioparse_single(const char **addr);
static xiofile_t *xioparse_dual(const char **addr); static xiofile_t *xioparse_dual(const char **addr);
static int xioopen_dual(xiofile_t *xfd, int xioflags); static int xioopen_dual(xiofile_t *xfd, int xioflags);
@ -668,8 +668,7 @@ int xioopen_single(xiofile_t *xfd, int xioflags) {
xfd->stream.flags |= (xioflags & XIO_ACCMODE); xfd->stream.flags |= (xioflags & XIO_ACCMODE);
result = (*addrdesc->func)(xfd->stream.argc, xfd->stream.argv, result = (*addrdesc->func)(xfd->stream.argc, xfd->stream.argv,
xfd->stream.opts, xioflags, xfd, xfd->stream.opts, xioflags, xfd,
addrdesc->groups, addrdesc->arg1, addrdesc);
addrdesc->arg2, addrdesc->arg3);
#if HAVE_RESOLV_H #if HAVE_RESOLV_H
if (do_res) if (do_res)
@ -690,3 +689,11 @@ int xioopen_single(xiofile_t *xfd, int xioflags) {
return result; return result;
} }
int xio_syntax(
const char *addr,
int expectnum,
int isnum,
const char *syntax)
{
return xiohelp_syntax(addr, expectnum, isnum, syntax);
}

View file

@ -45,6 +45,12 @@ extern const struct optname optionnames[];
extern int xioopen_makedual(xiofile_t *file); extern int xioopen_makedual(xiofile_t *file);
#if WITH_HELP
extern int xio_syntax(const char *addr, int expectnum, int isnum, const char *syntax);
#else
#define xio_syntax(a,e,i,s) Error3("%s: wrong number of parameters (%d instead of %d)", a, i, e);
#endif
#define retropt_2bytes(o,c,r) retropt_ushort(o,c,r) #define retropt_2bytes(o,c,r) retropt_ushort(o,c,r)
/* mode_t might be unsigned short or unsigned int or what else? */ /* mode_t might be unsigned short or unsigned int or what else? */

View file

@ -151,7 +151,7 @@ bool xioopts_ignoregroups;
#endif #endif
static int applyopt_offset(struct single *xfd, struct opt *opt); static int applyopt_offset(struct single *sfd, struct opt *opt);
static int applyopt(struct single *sfd, int fd, struct opt *opt); static int applyopt(struct single *sfd, int fd, struct opt *opt);
@ -4080,10 +4080,10 @@ int applyopts_fchown(int fd, struct opt *opts) {
} }
/* caller must make sure that option is not yet consumed */ /* caller must make sure that option is not yet consumed */
static int applyopt_offset(struct single *xfd, struct opt *opt) { static int applyopt_offset(struct single *sfd, struct opt *opt) {
unsigned char *ptr; unsigned char *ptr;
ptr = (unsigned char *)xfd + opt->desc->major; ptr = (unsigned char *)sfd + opt->desc->major;
switch (opt->desc->type) { switch (opt->desc->type) {
case TYPE_BOOL: case TYPE_BOOL:
*(bool *)ptr = opt->value.u_bool; break; *(bool *)ptr = opt->value.u_bool; break;
@ -4117,7 +4117,7 @@ static int applyopt_offset(struct single *xfd, struct opt *opt) {
return 0; return 0;
} }
int applyopts_offset(struct single *xfd, struct opt *opts) { int applyopts_offset(struct single *sfd, struct opt *opts) {
struct opt *opt; struct opt *opt;
opt = opts; while (opt->desc != ODESC_END) { opt = opts; while (opt->desc != ODESC_END) {
@ -4125,16 +4125,16 @@ int applyopts_offset(struct single *xfd, struct opt *opts) {
opt->desc->func != OFUNC_OFFSET) { opt->desc->func != OFUNC_OFFSET) {
++opt; continue; } ++opt; continue; }
applyopt_offset(xfd, opt); applyopt_offset(sfd, opt);
opt->desc = ODESC_DONE; opt->desc = ODESC_DONE;
++opt; ++opt;
} }
return 0; return 0;
} }
/* applies to xfd all OFUNC_EXT options belonging to phase /* applies to sfd all OFUNC_EXT options belonging to phase
returns -1 if an error occurred */ returns -1 if an error occurred */
int applyopts_single(struct single *xfd, struct opt *opts, enum e_phase phase) { int applyopts_single(struct single *sfd, struct opt *opts, enum e_phase phase) {
struct opt *opt; struct opt *opt;
int rc = 0; int rc = 0;
@ -4145,9 +4145,9 @@ int applyopts_single(struct single *xfd, struct opt *opts, enum e_phase phase) {
if ((opt->desc != ODESC_DONE && opt->desc != ODESC_ERROR) && if ((opt->desc != ODESC_DONE && opt->desc != ODESC_ERROR) &&
(opt->desc->phase == phase && phase != PH_ALL)) { (opt->desc->phase == phase && phase != PH_ALL)) {
if (opt->desc->func < OFUNC_XIO) { if (opt->desc->func < OFUNC_XIO) {
rc = applyopt(NULL, xfd->fd, opt); rc = applyopt(NULL, sfd->fd, opt);
} else { } else {
rc = applyopt(xfd, -1, opt); rc = applyopt(sfd, -1, opt);
} }
if (rc == 0) if (rc == 0)
opt->desc = ODESC_DONE; opt->desc = ODESC_DONE;