Internal: Reworked xioopts

This commit is contained in:
Gerhard Rieger 2023-07-13 09:06:08 +02:00
parent 1c1a91027a
commit 5eebca3a5b
37 changed files with 1380 additions and 1199 deletions

View file

@ -17093,11 +17093,12 @@ tf="$td/test$N.stdout"
te="$td/test$N.stderr" te="$td/test$N.stderr"
tdiff="$td/test$N.diff" tdiff="$td/test$N.diff"
da="test$N $(date) $RANDOM" da="test$N $(date) $RANDOM"
CMD0="$TRACE $SOCAT $opts -T 1 PIPE EXEC:cat,setsid,sigint" 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=$!
relsleep 2 #echo "pid0=$pid0" >&2 #!!!
sleep 1
kill -INT $pid0 kill -INT $pid0
wait wait
if grep -q " W waitpid..: child .* exited with status 130" "${te}0" || if grep -q " W waitpid..: child .* exited with status 130" "${te}0" ||

View file

@ -37,7 +37,8 @@ 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 *fd, 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, groups_t groups, int dummy1, int dummy2, int dummy3) {
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);
bool exists; bool exists;
@ -45,32 +46,32 @@ 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, fd, groups, &exists, opts)) < 0) { if ((result = _xioopen_named_early(argc, argv, xxfd, groups, &exists, opts)) < 0) {
return result; return result;
} }
retropt_bool(opts, OPT_UNLINK_CLOSE, &opt_unlink_close); retropt_bool(opts, OPT_UNLINK_CLOSE, &opt_unlink_close);
if (opt_unlink_close) { if (opt_unlink_close) {
if ((fd->stream.unlink_close = strdup(filename)) == NULL) { if ((sfd->unlink_close = strdup(filename)) == NULL) {
Error1("strdup(\"%s\"): out of memory", filename); Error1("strdup(\"%s\"): out of memory", filename);
} }
fd->stream.opt_unlink_close = true; sfd->opt_unlink_close = true;
} }
Notice2("creating regular file \"%s\" for %s", filename, ddirection[rw]); Notice2("creating regular file \"%s\" for %s", filename, ddirection[rw]);
if ((result = _xioopen_creat(filename, rw, opts)) < 0) if ((result = _xioopen_creat(filename, rw, opts)) < 0)
return result; return result;
fd->stream.fd = result; sfd->fd = result;
applyopts_named(filename, opts, PH_PASTOPEN); applyopts_named(filename, opts, PH_PASTOPEN);
if ((result = applyopts2(fd->stream.fd, opts, PH_PASTOPEN, PH_LATE2)) < 0) if ((result = applyopts2(sfd, -1, opts, PH_PASTOPEN, PH_LATE2)) < 0)
return result; return result;
applyopts_cloexec(fd->stream.fd, opts); applyopts_cloexec(sfd->fd, opts);
applyopts_fchown(fd->stream.fd, opts); applyopts_fchown(sfd->fd, opts);
if ((result = _xio_openlate(&fd->stream, opts)) < 0) if ((result = _xio_openlate(sfd, opts)) < 0)
return result; return result;
return 0; return 0;

View file

@ -26,13 +26,15 @@ const struct optdesc opt_dash = { "dash", "login", OPT_DASH, GROUP_EXEC, PH_PREE
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, /* XIO_RDONLY, XIO_MAYCHILD etc. */ int xioflags, /* XIO_RDONLY, XIO_MAYCHILD etc. */
xiofile_t *fd, xiofile_t *xfd,
groups_t groups, groups_t groups,
int dummy1, int dummy2, int dummy3 int dummy1, int dummy2, int dummy3
) { ) {
struct single *sfd = &xfd->stream;
int status; int status;
bool dash = false; bool dash = false;
int duptostderr; int duptostderr;
int numleft;
if (argc != 2) { if (argc != 2) {
Error2("\"%s\": wrong number of parameters (%d instead of 1)", argv[0], argc-1); Error2("\"%s\": wrong number of parameters (%d instead of 1)", argv[0], argc-1);
@ -40,8 +42,9 @@ static int xioopen_exec(int argc, const char *argv[], struct opt *opts,
retropt_bool(opts, OPT_DASH, &dash); retropt_bool(opts, OPT_DASH, &dash);
status = _xioopen_foxec(xioflags, &fd->stream, groups, &opts, &duptostderr); status = _xioopen_foxec(xioflags, sfd, groups, &opts, &duptostderr);
if (status < 0) return status; if (status < 0)
return status;
if (status == 0) { /* child */ if (status == 0) { /* child */
const char *ends[] = { " ", NULL }; const char *ends[] = { " ", NULL };
const char *hquotes[] = { "'", NULL }; const char *hquotes[] = { "'", NULL };
@ -61,7 +64,6 @@ static int xioopen_exec(int argc, const char *argv[], struct opt *opts,
char *tokp; char *tokp;
char *path = NULL; char *path = NULL;
char *tmp; char *tmp;
int numleft;
/*! Close(something) */ /*! Close(something) */
/* parse command line */ /* parse command line */
@ -143,6 +145,7 @@ static int xioopen_exec(int argc, const char *argv[], struct opt *opts,
} }
/* parent */ /* parent */
_xio_openlate(sfd, opts);
return 0; return 0;
} }
#endif /* WITH_EXEC */ #endif /* WITH_EXEC */

View file

@ -120,10 +120,10 @@ int xioopen_fd(struct opt *opts, int rw, xiosingle_t *xfd, int numfd, int dummy2
} }
} }
#endif /* WITH_TERMIOS */ #endif /* WITH_TERMIOS */
if (applyopts_single(xfd, opts, PH_INIT) < 0) return -1; if (applyopts_single(xfd, opts, PH_INIT) < 0)
applyopts(-1, opts, PH_INIT); return -1;
applyopts2(xfd->fd, opts, PH_INIT, PH_FD); applyopts2(xfd, -1, opts, PH_INIT, PH_FD);
return _xio_openlate(xfd, opts); return _xio_openlate(xfd, opts);
} }

View file

@ -72,50 +72,51 @@ 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 *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 *xfd, groups_t groups, int dummy1, int dummy2, int dummy3) {
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;
bool exists; bool exists;
bool opt_unlink_close = false; bool opt_unlink_close = false;
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, fd, groups, &exists, opts)) < 0) { if ((result = _xioopen_named_early(argc, argv, xfd, groups, &exists, opts)) < 0) {
return result; return result;
} }
retropt_bool(opts, OPT_UNLINK_CLOSE, &opt_unlink_close); retropt_bool(opts, OPT_UNLINK_CLOSE, &opt_unlink_close);
if (opt_unlink_close) { if (opt_unlink_close) {
if ((fd->stream.unlink_close = strdup(filename)) == NULL) { if ((sfd->unlink_close = strdup(filename)) == NULL) {
Error1("strdup(\"%s\"): out of memory", filename); Error1("strdup(\"%s\"): out of memory", filename);
} }
fd->stream.opt_unlink_close = true; sfd->opt_unlink_close = true;
} }
Notice3("opening %s \"%s\" for %s", Notice3("opening %s \"%s\" for %s",
filetypenames[(result&S_IFMT)>>12], filename, ddirection[rw]); filetypenames[(result&S_IFMT)>>12], filename, ddirection[rw]);
if ((result = _xioopen_open(filename, rw, opts)) < 0) if ((result = _xioopen_open(filename, rw, opts)) < 0)
return result; return result;
fd->stream.fd = result; sfd->fd = result;
#if WITH_TERMIOS #if WITH_TERMIOS
if (Isatty(fd->stream.fd)) { if (Isatty(sfd->fd)) {
if (Tcgetattr(fd->stream.fd, &fd->stream.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",
fd->stream.fd, strerror(errno)); sfd->fd, strerror(errno));
} else { } else {
fd->stream.ttyvalid = true; sfd->ttyvalid = true;
} }
} }
#endif /* WITH_TERMIOS */ #endif /* WITH_TERMIOS */
applyopts_named(filename, opts, PH_FD); applyopts_named(filename, opts, PH_FD);
applyopts(fd->stream.fd, opts, PH_FD); applyopts(sfd, -1, opts, PH_FD);
applyopts_cloexec(fd->stream.fd, opts); applyopts_cloexec(sfd->fd, opts);
applyopts_fchown(fd->stream.fd, opts); applyopts_fchown(sfd->fd, opts);
if ((result = _xio_openlate(&fd->stream, opts)) < 0) if ((result = _xio_openlate(sfd, opts)) < 0)
return result; return result;
return 0; return 0;

View file

@ -19,7 +19,8 @@ static int xioopen_gopen(int argc, const char *argv[], struct opt *opts, int xio
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 *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 *xxfd, groups_t groups, int dummy1, int dummy2, int dummy3) {
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);
mode_t st_mode; mode_t st_mode;
@ -28,7 +29,7 @@ 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, fd, GROUP_NAMED|groups, &exists, opts)) < 0) { _xioopen_named_early(argc, argv, xxfd, GROUP_NAMED|groups, &exists, opts)) < 0) {
return result; return result;
} }
st_mode = result; st_mode = result;
@ -52,15 +53,15 @@ 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(&fd->stream, xioflags, groups, 0, opts, filename); _xioopen_unix_client(sfd, xioflags, groups, 0, opts, filename);
if (result < 0) { if (result < 0) {
return result; return result;
} }
applyopts_named(filename, opts, PH_PASTOPEN); /* unlink-late */ applyopts_named(filename, opts, PH_PASTOPEN); /* unlink-late */
if (Getsockname(fd->stream.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",
fd->stream.fd, &us, uslen, strerror(errno)); sfd->fd, &us, uslen, strerror(errno));
} else { } else {
Notice1("successfully connected via %s", Notice1("successfully connected via %s",
sockaddr_unix_info(&us.un, uslen, sockaddr_unix_info(&us.un, uslen,
@ -78,10 +79,10 @@ static int xioopen_gopen(int argc, const char *argv[], struct opt *opts, int xio
retropt_bool(opts, OPT_UNLINK_CLOSE, &opt_unlink_close); retropt_bool(opts, OPT_UNLINK_CLOSE, &opt_unlink_close);
if (opt_unlink_close) { if (opt_unlink_close) {
if ((fd->stream.unlink_close = strdup(filename)) == NULL) { if ((sfd->unlink_close = strdup(filename)) == NULL) {
Error1("strdup(\"%s\"): out of memory", filename); Error1("strdup(\"%s\"): out of memory", filename);
} }
fd->stream.opt_unlink_close = true; sfd->opt_unlink_close = true;
} }
Notice3("opening %s \"%s\" for %s", Notice3("opening %s \"%s\" for %s",
@ -95,27 +96,27 @@ static int xioopen_gopen(int argc, const char *argv[], struct opt *opts, int xio
Ioctl(result, I_PUSH, "ttcompat"); /* ... AdressSanitizer */ Ioctl(result, I_PUSH, "ttcompat"); /* ... AdressSanitizer */
} }
#endif #endif
fd->stream.fd = result; sfd->fd = result;
#if WITH_TERMIOS #if WITH_TERMIOS
if (Isatty(fd->stream.fd)) { if (Isatty(sfd->fd)) {
if (Tcgetattr(fd->stream.fd, &fd->stream.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",
fd->stream.fd, strerror(errno)); sfd->fd, strerror(errno));
} else { } else {
fd->stream.ttyvalid = true; sfd->ttyvalid = true;
} }
} }
#endif /* WITH_TERMIOS */ #endif /* WITH_TERMIOS */
applyopts_named(filename, opts, PH_FD); applyopts_named(filename, opts, PH_FD);
applyopts(fd->stream.fd, opts, PH_FD); applyopts(sfd, -1, opts, PH_FD);
applyopts_cloexec(fd->stream.fd, opts); applyopts_cloexec(sfd->fd, opts);
} }
if ((result = applyopts2(fd->stream.fd, opts, PH_PASTSOCKET, PH_CONNECTED)) < 0) if ((result = applyopts2(sfd, -1, opts, PH_PASTSOCKET, PH_CONNECTED)) < 0)
return result; return result;
if ((result = _xio_openlate(&fd->stream, opts)) < 0) if ((result = _xio_openlate(sfd, opts)) < 0)
return result; return result;
return 0; return 0;
} }

View file

@ -84,7 +84,7 @@ int _xioopen_interface(const char *ifname,
/* ...res_opts[] */ /* ...res_opts[] */
if (applyopts_single(xfd, opts, PH_INIT) < 0) return -1; if (applyopts_single(xfd, opts, PH_INIT) < 0) return -1;
applyopts(-1, opts, PH_INIT); applyopts(xfd, -1, opts, PH_INIT);
xfd->salen = sizeof(xfd->peersa); xfd->salen = sizeof(xfd->peersa);
if (pf == PF_UNSPEC) { if (pf == PF_UNSPEC) {

View file

@ -69,7 +69,7 @@ const struct optdesc opt_ip_multicast_if ={"ip-multicast-if", "multicast-if",
const struct optdesc opt_ip_pktoptions = { "ip-pktoptions", "pktopts", OPT_IP_PKTOPTIONS, GROUP_SOCK_IP, PH_PASTSOCKET, TYPE_INT, OFUNC_SOCKOPT, SOL_IP, IP_PKTOPTIONS }; const struct optdesc opt_ip_pktoptions = { "ip-pktoptions", "pktopts", OPT_IP_PKTOPTIONS, GROUP_SOCK_IP, PH_PASTSOCKET, TYPE_INT, OFUNC_SOCKOPT, SOL_IP, IP_PKTOPTIONS };
#endif #endif
#ifdef IP_ADD_MEMBERSHIP #ifdef IP_ADD_MEMBERSHIP
const struct optdesc opt_ip_add_membership = { "ip-add-membership", "membership",OPT_IP_ADD_MEMBERSHIP, GROUP_SOCK_IP, PH_PASTSOCKET, TYPE_IP_MREQN, OFUNC_SOCKOPT, SOL_IP, IP_ADD_MEMBERSHIP }; const struct optdesc opt_ip_add_membership = { "ip-add-membership", "membership",OPT_IP_ADD_MEMBERSHIP, GROUP_SOCK_IP, PH_PASTSOCKET, TYPE_IP_MREQN, OFUNC_SPEC, SOL_IP, IP_ADD_MEMBERSHIP };
#endif #endif
#if defined(HAVE_STRUCT_IP_MREQ_SOURCE) && defined(IP_ADD_SOURCE_MEMBERSHIP) #if defined(HAVE_STRUCT_IP_MREQ_SOURCE) && defined(IP_ADD_SOURCE_MEMBERSHIP)
const struct optdesc opt_ip_add_source_membership = { "ip-add-source-membership", "source-membership",OPT_IP_ADD_SOURCE_MEMBERSHIP, GROUP_SOCK_IP, PH_PASTSOCKET, TYPE_IP_MREQ_SOURCE, OFUNC_SOCKOPT, SOL_IP, IP_ADD_SOURCE_MEMBERSHIP }; const struct optdesc opt_ip_add_source_membership = { "ip-add-source-membership", "source-membership",OPT_IP_ADD_SOURCE_MEMBERSHIP, GROUP_SOCK_IP, PH_PASTSOCKET, TYPE_IP_MREQ_SOURCE, OFUNC_SOCKOPT, SOL_IP, IP_ADD_SOURCE_MEMBERSHIP };

View file

@ -48,7 +48,7 @@ int xioopen_ipapp_connect(int argc, const char *argv[], struct opt *opts,
if (applyopts_single(xfd, opts, PH_INIT) < 0) if (applyopts_single(xfd, opts, PH_INIT) < 0)
return -1; return -1;
applyopts(-1, opts, PH_INIT); applyopts(xfd, -1, opts, PH_INIT);
retropt_bool(opts, OPT_FORK, &dofork); retropt_bool(opts, OPT_FORK, &dofork);
@ -216,7 +216,7 @@ int
} }
} }
applyopts(-1, opts, PH_EARLY); applyopts(NULL, -1, opts, PH_EARLY);
/* 3 means: IP address AND port accepted */ /* 3 means: IP address AND port accepted */
if (retropt_bind(opts, (*pf!=PF_UNSPEC)?*pf:(*themlist)->ai_family, if (retropt_bind(opts, (*pf!=PF_UNSPEC)?*pf:(*themlist)->ai_family,
@ -306,6 +306,7 @@ int xioopen_ipapp_listen(int argc, const char *argv[], struct opt *opts,
int xioflags, xiofile_t *xfd, int xioflags, xiofile_t *xfd,
groups_t groups, int socktype, groups_t groups, int socktype,
int ipproto, int pf) { int ipproto, int pf) {
struct single *sfd = &xfd->stream;
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);
@ -333,8 +334,8 @@ int xioopen_ipapp_listen(int argc, const char *argv[], struct opt *opts,
xfd->stream.howtoend = END_SHUTDOWN; xfd->stream.howtoend = END_SHUTDOWN;
if (applyopts_single(&xfd->stream, opts, PH_INIT) < 0) return -1; if (applyopts_single(&xfd->stream, opts, PH_INIT) < 0) return -1;
applyopts(-1, opts, PH_INIT); applyopts(sfd, -1, opts, PH_INIT);
applyopts(-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, xfd->stream.para.socket.ip.ai_flags,

View file

@ -113,16 +113,16 @@ int _xioopen_listen(struct single *xfd, int xioflags, struct sockaddr *us, sockl
if ((xfd->fd = xiosocket(opts, pf?pf:us->sa_family, socktype, proto, level)) < 0) { if ((xfd->fd = xiosocket(opts, pf?pf:us->sa_family, socktype, proto, level)) < 0) {
return STAT_RETRYLATER; return STAT_RETRYLATER;
} }
applyopts(xfd->fd, opts, PH_PASTSOCKET); applyopts(xfd, -1, opts, PH_PASTSOCKET);
applyopts_offset(xfd, opts); applyopts_offset(xfd, opts);
applyopts_cloexec(xfd->fd, opts); applyopts_cloexec(xfd->fd, opts);
/* Phase prebind */ /* Phase prebind */
xiosock_reuseaddr(xfd->fd, proto, opts); xiosock_reuseaddr(xfd->fd, proto, opts);
applyopts(xfd->fd, opts, PH_PREBIND); applyopts(xfd, -1, opts, PH_PREBIND);
applyopts(xfd->fd, opts, PH_BIND); applyopts(xfd, -1, opts, PH_BIND);
if (Bind(xfd->fd, (struct sockaddr *)us, uslen) < 0) { if (Bind(xfd->fd, (struct sockaddr *)us, uslen) < 0) {
Msg4(level, "bind(%d, {%s}, "F_socklen"): %s", xfd->fd, Msg4(level, "bind(%d, {%s}, "F_socklen"): %s", xfd->fd,
sockaddr_info(us, uslen, infobuff, sizeof(infobuff)), uslen, sockaddr_info(us, uslen, infobuff, sizeof(infobuff)), uslen,
@ -136,28 +136,27 @@ 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->fd, opts, PH_FD); applyopts(xfd, -1, opts, PH_FD);
} }
} }
#endif #endif
applyopts(xfd->fd, opts, PH_PASTBIND); applyopts(xfd, -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_early(((struct sockaddr_un *)us)->sun_path, opts);*/
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->fd, opts, PH_EARLY); applyopts(xfd, -1, opts, PH_EARLY);
applyopts(xfd->fd, opts, PH_PREOPEN); applyopts(xfd, -1, opts, PH_PREOPEN);
} }
} }
#endif /* WITH_UNIX */ #endif /* WITH_UNIX */
applyopts(xfd->fd, opts, PH_PRELISTEN); applyopts(xfd, -1, opts, PH_PRELISTEN);
retropt_int(opts, OPT_BACKLOG, &backlog); retropt_int(opts, OPT_BACKLOG, &backlog);
applyopts(xfd->fd, opts, PH_LISTEN); applyopts(xfd, -1, opts, PH_LISTEN);
if (Listen(xfd->fd, backlog) < 0) { if (Listen(xfd->fd, backlog) < 0) {
Error3("listen(%d, %d): %s", xfd->fd, backlog, strerror(errno)); Error3("listen(%d, %d): %s", xfd->fd, backlog, strerror(errno));
return STAT_RETRYLATER; return STAT_RETRYLATER;
@ -419,9 +418,9 @@ int _xioopen_accept_fd(
} }
} }
applyopts(xfd->fd, opts, PH_FD); applyopts(xfd, -1, opts, PH_FD);
applyopts(xfd->fd, opts, PH_PASTSOCKET); applyopts(xfd, -1, opts, PH_PASTSOCKET);
applyopts(xfd->fd, opts, PH_CONNECTED); applyopts(xfd, -1, opts, PH_CONNECTED);
if ((result = _xio_openlate(xfd, opts)) < 0) if ((result = _xio_openlate(xfd, opts)) < 0)
return result; return result;

View file

@ -99,6 +99,7 @@ int _xioopen_named_early(int argc, const char *argv[], xiofile_t *xfd,
groups_t groups, bool *exists, struct opt *opts) groups_t groups, bool *exists, struct opt *opts)
{ {
const char *path = argv[1]; const char *path = argv[1];
struct single *sfd = &xfd->stream;
#if HAVE_STAT64 #if HAVE_STAT64
struct stat64 statbuf; struct stat64 statbuf;
#else #else
@ -127,8 +128,9 @@ int _xioopen_named_early(int argc, const char *argv[], xiofile_t *xfd,
*exists = true; *exists = true;
} }
if (applyopts_single(&xfd->stream, opts, PH_INIT) < 0) return -1; if (applyopts_single(sfd, opts, PH_INIT) < 0)
applyopts(-1, opts, PH_INIT); return -1;
applyopts(sfd, -1, opts, PH_INIT);
retropt_bool(opts, OPT_UNLINK_EARLY, &opt_unlink_early); retropt_bool(opts, OPT_UNLINK_EARLY, &opt_unlink_early);
if (*exists && opt_unlink_early) { if (*exists && opt_unlink_early) {
@ -141,7 +143,7 @@ int _xioopen_named_early(int argc, const char *argv[], xiofile_t *xfd,
} }
applyopts_named(path, opts, PH_EARLY); applyopts_named(path, opts, PH_EARLY);
applyopts(-1, opts, PH_EARLY); applyopts(sfd, -1, opts, PH_EARLY);
if (*exists) { if (*exists) {
applyopts_named(path, opts, PH_PREOPEN); applyopts_named(path, opts, PH_PREOPEN);
} else { } else {

View file

@ -240,6 +240,7 @@ static int
addr_openssl */ addr_openssl */
{ {
struct single *xfd = &xxfd->stream; struct single *xfd = &xxfd->stream;
struct single *sfd = xfd;
struct opt *opts0 = NULL; struct opt *opts0 = NULL;
const char *hostname, *portname; const char *hostname, *portname;
int pf = PF_UNSPEC; int pf = PF_UNSPEC;
@ -284,7 +285,7 @@ static int
xfd->howtoend = END_SHUTDOWN; xfd->howtoend = END_SHUTDOWN;
if (applyopts_single(xfd, opts, PH_INIT) < 0) return -1; if (applyopts_single(xfd, opts, PH_INIT) < 0) return -1;
applyopts(-1, opts, PH_INIT); applyopts(sfd, -1, opts, PH_INIT);
retropt_bool(opts, OPT_FORK, &dofork); retropt_bool(opts, OPT_FORK, &dofork);
@ -561,6 +562,7 @@ static int
addr_openssl */ addr_openssl */
{ {
struct single *xfd = &xxfd->stream; struct single *xfd = &xxfd->stream;
struct single *sfd = xfd;
const char *portname; const char *portname;
struct opt *opts0 = NULL; struct opt *opts0 = NULL;
union sockaddr_union us_sa, *us = &us_sa; union sockaddr_union us_sa, *us = &us_sa;
@ -604,7 +606,7 @@ static int
xfd->howtoend = END_SHUTDOWN; xfd->howtoend = END_SHUTDOWN;
if (applyopts_single(xfd, opts, PH_INIT) < 0) return -1; if (applyopts_single(xfd, opts, PH_INIT) < 0) return -1;
applyopts(-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);
if (opt_cert == NULL) { if (opt_cert == NULL) {
@ -613,7 +615,7 @@ static int
retropt_string(opts, OPT_OPENSSL_COMMONNAME, (char **)&opt_commonname); retropt_string(opts, OPT_OPENSSL_COMMONNAME, (char **)&opt_commonname);
applyopts(-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, xfd, true, &opt_ver, opt_cert, &ctx, &use_dtls);

View file

@ -24,13 +24,14 @@ const struct addrdesc xioaddr_pipe = { "PIPE", 3, xioopen_fifo, GROUP_FD|GR
/* process an unnamed bidirectional "pipe" or "fifo" or "echo" argument with /* process an unnamed bidirectional "pipe" or "fifo" or "echo" argument with
options */ options */
static int xioopen_fifo_unnamed(xiofile_t *sock, struct opt *opts) { static int xioopen_fifo_unnamed(xiofile_t *sock, struct opt *opts) {
struct single *sfd = &sock->stream;
struct opt *opts2; struct opt *opts2;
int filedes[2]; int filedes[2];
int numleft; int numleft;
int result; int result;
if (applyopts_single(&sock->stream, opts, PH_INIT) < 0) return -1; if (applyopts_single(sfd, opts, PH_INIT) < 0) return -1;
applyopts(-1, opts, PH_INIT); applyopts(sfd, -1, opts, PH_INIT);
if (Pipe(filedes) != 0) { if (Pipe(filedes) != 0) {
Error2("pipe(%p): %s", filedes, strerror(errno)); Error2("pipe(%p): %s", filedes, strerror(errno));
@ -39,15 +40,15 @@ static int xioopen_fifo_unnamed(xiofile_t *sock, struct opt *opts) {
/*0 Info2("pipe({%d,%d})", filedes[0], filedes[1]);*/ /*0 Info2("pipe({%d,%d})", filedes[0], filedes[1]);*/
sock->common.tag = XIO_TAG_RDWR; sock->common.tag = XIO_TAG_RDWR;
sock->stream.dtype = XIODATA_PIPE; sfd->dtype = XIODATA_PIPE;
sock->stream.fd = filedes[0]; sfd->fd = filedes[0];
sock->stream.para.bipipe.fdout = filedes[1]; sfd->para.bipipe.fdout = filedes[1];
sock->stream.para.bipipe.socktype = SOCK_STREAM; /* due to socketpair reuse */ sfd->para.bipipe.socktype = SOCK_STREAM; /* due to socketpair reuse */
applyopts_cloexec(sock->stream.fd, opts); applyopts_cloexec(sfd->fd, opts);
applyopts_cloexec(sock->stream.para.bipipe.fdout, opts); applyopts_cloexec(sfd->para.bipipe.fdout, opts);
/* one-time and input-direction options, no second application */ /* one-time and input-direction options, no second application */
retropt_bool(opts, OPT_IGNOREEOF, &sock->stream.ignoreeof); retropt_bool(opts, OPT_IGNOREEOF, &sfd->ignoreeof);
/* here we copy opts! */ /* here we copy opts! */
if ((opts2 = copyopts(opts, GROUP_FIFO)) == NULL) { if ((opts2 = copyopts(opts, GROUP_FIFO)) == NULL) {
@ -55,18 +56,16 @@ static int xioopen_fifo_unnamed(xiofile_t *sock, struct opt *opts) {
} }
/* apply options to first FD */ /* apply options to first FD */
if ((result = applyopts(sock->stream.fd, opts, PH_ALL)) < 0) { if ((result = applyopts(sfd, -1, opts, PH_ALL)) < 0) {
return result; return result;
} }
if ((result = applyopts_single(&sock->stream, opts, PH_ALL)) < 0) { if ((result = applyopts_single(sfd, opts, PH_ALL)) < 0) {
return result; return result;
} }
/* apply options to second FD */ /* apply options to second FD */
if ((result = applyopts(sock->stream.para.bipipe.fdout, opts2, PH_ALL)) < 0) if (applyopts(&sock->stream, sfd->para.bipipe.fdout, opts2, PH_ALL) < 0)
{ return -1;
return result;
}
if ((numleft = leftopts(opts)) > 0) { if ((numleft = leftopts(opts)) > 0) {
showleft(opts); showleft(opts);
@ -78,7 +77,8 @@ 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 *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 *xfd, groups_t groups, int dummy1, int dummy2, int dummy3) {
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);
#if HAVE_STAT64 #if HAVE_STAT64
@ -92,19 +92,20 @@ static int xioopen_fifo(int argc, const char *argv[], struct opt *opts, int xiof
int result; int result;
if (argc == 1) { if (argc == 1) {
return xioopen_fifo_unnamed(fd, fd->stream.opts); return xioopen_fifo_unnamed(xfd, sfd->opts);
} }
if (argc != 2) { if (argc != 2) {
Error2("%s: wrong number of parameters (%d instead of 1)", argv[0], argc-1); Error2("%s: wrong number of parameters (%d instead of 1)", argv[0], argc-1);
} }
if (applyopts_single(&fd->stream, opts, PH_INIT) < 0) return -1; if (applyopts_single(sfd, opts, PH_INIT) < 0)
applyopts(-1, opts, PH_INIT); return -1;
applyopts(sfd, -1, opts, PH_INIT);
retropt_bool(opts, OPT_UNLINK_EARLY, &opt_unlink_early); retropt_bool(opts, OPT_UNLINK_EARLY, &opt_unlink_early);
applyopts_named(pipename, opts, PH_EARLY); /* umask! */ applyopts_named(pipename, opts, PH_EARLY); /* umask! */
applyopts(-1, opts, PH_EARLY); applyopts(sfd, -1, opts, PH_EARLY);
if (opt_unlink_early) { if (opt_unlink_early) {
if (Unlink(pipename) < 0) { if (Unlink(pipename) < 0) {
@ -149,10 +150,10 @@ static int xioopen_fifo(int argc, const char *argv[], struct opt *opts, int xiof
} }
if (opt_unlink_close) { if (opt_unlink_close) {
if ((fd->stream.unlink_close = strdup(pipename)) == NULL) { if ((sfd->unlink_close = strdup(pipename)) == NULL) {
Error1("strdup(\"%s\"): out of memory", pipename); Error1("strdup(\"%s\"): out of memory", pipename);
} }
fd->stream.opt_unlink_close = true; sfd->opt_unlink_close = true;
} }
} else { } else {
/* exists */ /* exists */
@ -160,19 +161,18 @@ static int xioopen_fifo(int argc, const char *argv[], struct opt *opts, int xiof
Notice3("opening %s \"%s\" for %s", Notice3("opening %s \"%s\" for %s",
filetypenames[(pipstat.st_mode&S_IFMT)>>12], filetypenames[(pipstat.st_mode&S_IFMT)>>12],
pipename, ddirection[rw]); pipename, ddirection[rw]);
/*applyopts_early(pipename, opts);*/
applyopts_named(pipename, opts, PH_EARLY); applyopts_named(pipename, opts, PH_EARLY);
} }
if ((result = _xioopen_open(pipename, rw, opts)) < 0) { if ((result = _xioopen_open(pipename, rw, opts)) < 0) {
return result; return result;
} }
fd->stream.fd = result; sfd->fd = result;
applyopts_named(pipename, opts, PH_FD); applyopts_named(pipename, opts, PH_FD);
applyopts(fd->stream.fd, opts, PH_FD); applyopts(sfd, -1, opts, PH_FD);
applyopts_cloexec(fd->stream.fd, opts); applyopts_cloexec(sfd->fd, opts);
return _xio_openlate(&fd->stream, opts); return _xio_openlate(sfd, opts);
} }
#endif /* WITH_PIPE */ #endif /* WITH_PIPE */

View file

@ -90,7 +90,7 @@ static int xioopen_posixmq(
} }
applyopts_offset(sfd, opts); applyopts_offset(sfd, opts);
if (applyopts_single(sfd, opts, PH_INIT) < 0) return STAT_NORETRY; if (applyopts_single(sfd, opts, PH_INIT) < 0) return STAT_NORETRY;
applyopts(-1, opts, PH_INIT); applyopts(sfd, -1, opts, PH_INIT);
if ((sfd->para.posixmq.name = strdup(name)) == NULL) { if ((sfd->para.posixmq.name = strdup(name)) == NULL) {
Error1("strdup(\"%s\"): out of memory", name); Error1("strdup(\"%s\"): out of memory", name);

View file

@ -47,12 +47,14 @@ const struct optdesc opt_sigquit = { "sigquit", NULL, OPT_SIGQUIT, GROUP_P
return<0: error occurred, assume parent process and no child exists !!! return<0: error occurred, assume parent process and no child exists !!!
*/ */
int _xioopen_foxec(int xioflags, /* XIO_RDONLY etc. */ int _xioopen_foxec(int xioflags, /* XIO_RDONLY etc. */
struct single *fd, struct single *sfd,
groups_t groups, groups_t groups,
struct opt **copts, /* in: opts; out: opts for child */ struct opt **optsp, /* in: opts; out: opts for parent/child */
int *duptostderr /* out: redirect stderr to output fd */ int *duptostderr /* out: redirect stderr to output fd */
) { ) {
struct opt *popts; /* parent process options */ struct opt *opts; /* common options */
struct opt *popts; /* parent options */
struct opt *copts; /* child options */
int numleft; int numleft;
int d, sv[2], rdpip[2], wrpip[2]; int d, sv[2], rdpip[2], wrpip[2];
int rw = (xioflags & XIO_ACCMODE); int rw = (xioflags & XIO_ACCMODE);
@ -78,21 +80,21 @@ int _xioopen_foxec(int xioflags, /* XIO_RDONLY etc. */
char *tn = NULL; char *tn = NULL;
int trigger[2]; /* [0] watched by parent, [1] closed by child when ready */ int trigger[2]; /* [0] watched by parent, [1] closed by child when ready */
popts = moveopts(*copts, GROUP_ALL); opts = *optsp;
if (applyopts_single(fd, popts, PH_INIT) < 0) return -1; if (applyopts_single(sfd, opts, PH_INIT) < 0) return -1;
applyopts2(-1, popts, PH_INIT, PH_EARLY); applyopts2(sfd, -1, opts, PH_INIT, PH_EARLY);
retropt_bool(popts, OPT_NOFORK, &nofork); retropt_bool(opts, OPT_NOFORK, &nofork);
withfork = !nofork; withfork = !nofork;
retropt_bool(popts, OPT_PIPES, &usepipes); retropt_bool(opts, OPT_PIPES, &usepipes);
#if HAVE_PTY #if HAVE_PTY
retropt_bool(popts, OPT_PTY, &usebestpty); retropt_bool(opts, OPT_PTY, &usebestpty);
#if HAVE_OPENPTY #if HAVE_OPENPTY
retropt_bool(popts, OPT_OPENPTY, &useopenpty); retropt_bool(opts, OPT_OPENPTY, &useopenpty);
#endif #endif
#if defined(HAVE_DEV_PTMX) || defined(HAVE_DEV_PTC) #if defined(HAVE_DEV_PTMX) || defined(HAVE_DEV_PTC)
retropt_bool(popts, OPT_PTMX, &useptmx); retropt_bool(opts, OPT_PTMX, &useptmx);
#endif #endif
usepty = (usebestpty usepty = (usebestpty
#if HAVE_OPENPTY #if HAVE_OPENPTY
@ -108,12 +110,12 @@ int _xioopen_foxec(int xioflags, /* XIO_RDONLY etc. */
} }
#endif /* HAVE_PTY */ #endif /* HAVE_PTY */
if (retropt_ushort(popts, OPT_FDIN, (unsigned short *)&fdi) >= 0) { if (retropt_ushort(opts, OPT_FDIN, (unsigned short *)&fdi) >= 0) {
if ((xioflags&XIO_ACCMODE) == XIO_RDONLY) { if ((xioflags&XIO_ACCMODE) == XIO_RDONLY) {
Error("_xioopen_foxec(): option fdin is useless in read-only mode"); Error("_xioopen_foxec(): option fdin is useless in read-only mode");
} }
} }
if (retropt_ushort(popts, OPT_FDOUT, (unsigned short *)&fdo) >= 0) { if (retropt_ushort(opts, OPT_FDOUT, (unsigned short *)&fdo) >= 0) {
if ((xioflags&XIO_ACCMODE) == XIO_WRONLY) { if ((xioflags&XIO_ACCMODE) == XIO_WRONLY) {
Error("_xioopen_foxec(): option fdout is useless in write-only mode"); Error("_xioopen_foxec(): option fdout is useless in write-only mode");
} }
@ -125,7 +127,7 @@ int _xioopen_foxec(int xioflags, /* XIO_RDONLY etc. */
/*!! free something */ /*!! free something */
return -1; return -1;
} }
fd->flags |= XIO_DOESCHILD; sfd->flags |= XIO_DOESCHILD;
#if HAVE_PTY #if HAVE_PTY
Notice2("forking off child, using %s for %s", Notice2("forking off child, using %s for %s",
@ -137,7 +139,7 @@ int _xioopen_foxec(int xioflags, /* XIO_RDONLY etc. */
ddirection[rw]); ddirection[rw]);
#endif /* HAVE_PTY */ #endif /* HAVE_PTY */
} }
applyopts(-1, popts, PH_PREBIGEN); applyopts(sfd, -1, opts, PH_PREBIGEN);
if (!withfork) { if (!withfork) {
/*0 struct single *stream1, *stream2;*/ /*0 struct single *stream1, *stream2;*/
@ -147,10 +149,13 @@ int _xioopen_foxec(int xioflags, /* XIO_RDONLY etc. */
/*!! free something */ /*!! free something */
return -1; return -1;
} }
fd->flags |= XIO_DOESEXEC; sfd->flags |= XIO_DOESEXEC;
free(*copts); /* Only one process, no parent,child */
*copts = moveopts(popts, GROUP_ALL); if ((copts = moveopts(opts, GROUP_ALL)) == NULL) {
/*!! free something */
return -1;
}
#if 0 /*!! */ #if 0 /*!! */
if (sock1->tag == XIO_TAG_DUAL) { if (sock1->tag == XIO_TAG_DUAL) {
@ -207,7 +212,8 @@ int _xioopen_foxec(int xioflags, /* XIO_RDONLY etc. */
/*0 Info2("dup2(%d, %d)", XIO_GETWRFD(sock[0]), fdo);*/ /*0 Info2("dup2(%d, %d)", XIO_GETWRFD(sock[0]), fdo);*/
} }
} }
} else /* !withfork */
} else /* withfork */
#if HAVE_PTY #if HAVE_PTY
if (usepty) { if (usepty) {
@ -216,7 +222,7 @@ int _xioopen_foxec(int xioflags, /* XIO_RDONLY etc. */
#elif HAVE_DEV_PTC #elif HAVE_DEV_PTC
# define PTMX "/dev/ptc" /* AIX 4.3.3 */ # define PTMX "/dev/ptc" /* AIX 4.3.3 */
#endif #endif
fd->dtype = XIODATA_PTY; sfd->dtype = XIODATA_PTY;
#if HAVE_DEV_PTMX || HAVE_DEV_PTC #if HAVE_DEV_PTMX || HAVE_DEV_PTC
if (usebestpty || useptmx) { if (usebestpty || useptmx) {
if ((ptyfd = Open(PTMX, O_RDWR|O_NOCTTY, 0620)) < 0) { if ((ptyfd = Open(PTMX, O_RDWR|O_NOCTTY, 0620)) < 0) {
@ -264,30 +270,30 @@ int _xioopen_foxec(int xioflags, /* XIO_RDONLY etc. */
} }
} }
#endif /* HAVE_OPENPTY */ #endif /* HAVE_OPENPTY */
free(*copts); /* withfork use_pty */
if ((*copts = moveopts(popts, GROUP_TERMIOS|GROUP_FORK|GROUP_EXEC|GROUP_PROCESS|GROUP_NAMED)) == NULL) { if ((copts = moveopts(opts, GROUP_TERMIOS|GROUP_FORK|GROUP_EXEC|GROUP_PROCESS|GROUP_NAMED)) == NULL) {
return -1; return -1;
} }
popts = opts;
applyopts_cloexec(ptyfd, popts);/*!*/ applyopts_cloexec(ptyfd, popts);/*!*/
/* exec:...,pty did not kill child process under some circumstances */ /* exec:...,pty did not kill child process under some circumstances */
if (fd->howtoend == END_UNSPEC) { if (sfd->howtoend == END_UNSPEC) {
fd->howtoend = END_CLOSE_KILL; sfd->howtoend = END_CLOSE_KILL;
} }
/* this for parent, was after fork */ /* this for parent, was after fork */
applyopts(ptyfd, popts, PH_FD); applyopts(sfd, ptyfd, popts, PH_FD);
applyopts(ptyfd, popts, PH_LATE); sfd->fd = ptyfd;
if (applyopts_single(fd, popts, PH_LATE) < 0) return -1;
fd->fd = ptyfd; /* end withfork, use_pty */
} else /* end withfork, use_pty */
} else
#endif /* HAVE_PTY */ #endif /* HAVE_PTY */
if (usepipes) { if (usepipes) {
struct opt *popts2, *copts2; /* withfork usepipes */
if (rw == XIO_RDWR) if (rw == XIO_RDWR)
fd->dtype = XIODATA_2PIPE; sfd->dtype = XIODATA_2PIPE;
if (rw != XIO_WRONLY) { if (rw != XIO_WRONLY) {
if (Pipe(rdpip) < 0) { if (Pipe(rdpip) < 0) {
Error2("pipe(%p): %s", rdpip, strerror(errno)); Error2("pipe(%p): %s", rdpip, strerror(errno));
@ -296,19 +302,18 @@ int _xioopen_foxec(int xioflags, /* XIO_RDONLY etc. */
} }
/*0 Info2("pipe({%d,%d})", rdpip[0], rdpip[1]);*/ /*0 Info2("pipe({%d,%d})", rdpip[0], rdpip[1]);*/
/* rdpip[0]: read by socat; rdpip[1]: write by child */ /* rdpip[0]: read by socat; rdpip[1]: write by child */
free(*copts);
if ((*copts = moveopts(popts, GROUP_FORK|GROUP_EXEC|GROUP_PROCESS)) /* withfork usepipes */
if ((copts = moveopts(opts, GROUP_FORK|GROUP_EXEC|GROUP_PROCESS))
== NULL) { == NULL) {
return -1; return -1;
} }
popts = opts;
popts2 = copyopts(popts, GROUP_ALL);
copts2 = copyopts(*copts, GROUP_ALL);
if (rw != XIO_WRONLY) { if (rw != XIO_WRONLY) {
applyopts_cloexec(rdpip[0], popts); applyopts_cloexec(rdpip[0], popts);
applyopts(rdpip[0], popts, PH_FD); applyopts(NULL, rdpip[0], popts, PH_FD);
applyopts(rdpip[1], *copts, PH_FD); applyopts(NULL, rdpip[1], copts, PH_FD);
} }
if (rw != XIO_RDONLY) { if (rw != XIO_RDONLY) {
@ -317,65 +322,70 @@ int _xioopen_foxec(int xioflags, /* XIO_RDONLY etc. */
return -1; return -1;
} }
} }
/*0 Info2("pipe({%d,%d})", wrpip[0], wrpip[1]);*/
/* 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], popts2); applyopts_cloexec(wrpip[1], popts);
applyopts(wrpip[1], popts2, PH_FD); applyopts(NULL, wrpip[1], popts, PH_FD);
applyopts(wrpip[0], copts2, PH_FD); applyopts(NULL, wrpip[0], copts, PH_FD);
} }
if (fd->howtoend == END_UNSPEC) { if (sfd->howtoend == END_UNSPEC) {
fd->howtoend = END_CLOSE_KILL; sfd->howtoend = END_CLOSE_KILL;
} }
/* this for parent, was after fork */ /* this for parent, was after fork */
switch (rw) { switch (rw) {
case XIO_RDONLY: fd->fd = rdpip[0]; break; case XIO_RDONLY: sfd->fd = rdpip[0]; break;
case XIO_WRONLY: fd->fd = wrpip[1]; break; case XIO_WRONLY: sfd->fd = wrpip[1]; break;
case XIO_RDWR: fd->fd = rdpip[0]; case XIO_RDWR: sfd->fd = rdpip[0];
fd->para.exec.fdout = wrpip[1]; sfd->para.exec.fdout = wrpip[1];
break; break;
} }
applyopts(fd->fd, popts, PH_FD); applyopts(sfd, -1, popts, PH_FD);
applyopts(fd->fd, popts, PH_LATE); applyopts(sfd, -1, popts, PH_LATE);
if (applyopts_single(fd, popts, PH_LATE) < 0) return -1; if (applyopts_single(sfd, popts, PH_LATE) < 0)
return -1;
/* end withfork, use_pipes */
} else { } else {
/* withfork, socketpair */
d = AF_UNIX; d = AF_UNIX;
retropt_int(popts, OPT_PROTOCOL_FAMILY, &d); retropt_int(opts, OPT_PROTOCOL_FAMILY, &d);
result = xiosocketpair(popts, d, SOCK_STREAM, 0, sv); result = xiosocketpair(opts, d, SOCK_STREAM, 0, sv);
if (result < 0) { if (result < 0) {
return -1; return -1;
} }
/*0 Info5("socketpair(%d, %d, %d, {%d,%d})",
d, type, protocol, sv[0], sv[1]);*/ /* withfork socketpair */
free(*copts); if ((copts = moveopts(opts, GROUP_FORK|GROUP_EXEC|GROUP_PROCESS)) == NULL) {
if ((*copts = moveopts(popts, GROUP_FORK|GROUP_EXEC|GROUP_PROCESS)) == NULL) {
return -1; return -1;
} }
applyopts(sv[0], *copts, PH_PASTSOCKET); popts = opts;
applyopts(sv[1], popts, PH_PASTSOCKET); applyopts(NULL, sv[0], copts, PH_PASTSOCKET);
applyopts(NULL, sv[1], popts, PH_PASTSOCKET);
applyopts_cloexec(sv[0], *copts); applyopts_cloexec(sv[0], copts);
applyopts(sv[0], *copts, PH_FD); applyopts(NULL, sv[0], copts, PH_FD);
applyopts(sv[1], popts, PH_FD); applyopts(NULL, sv[1], popts, PH_FD);
applyopts(sv[0], *copts, PH_PREBIND); applyopts(NULL, sv[0], copts, PH_PREBIND);
applyopts(sv[0], *copts, PH_BIND); applyopts(NULL, sv[0], copts, PH_BIND);
applyopts(sv[0], *copts, PH_PASTBIND); applyopts(NULL, sv[0], copts, PH_PASTBIND);
applyopts(sv[1], popts, PH_PREBIND); applyopts(NULL, sv[1], popts, PH_PREBIND);
applyopts(sv[1], popts, PH_BIND); applyopts(NULL, sv[1], popts, PH_BIND);
applyopts(sv[1], popts, PH_PASTBIND); applyopts(NULL, sv[1], popts, PH_PASTBIND);
if (fd->howtoend == END_UNSPEC) { if (sfd->howtoend == END_UNSPEC) {
fd->howtoend = END_SHUTDOWN_KILL; sfd->howtoend = END_SHUTDOWN_KILL;
} }
/* this for parent, was after fork */ /* this for parent, was after fork */
fd->fd = sv[0]; sfd->fd = sv[0];
applyopts(fd->fd, popts, PH_FD); applyopts(sfd, -1, popts, PH_FD);
/* end withfork, socketpair */
} }
retropt_bool(*copts, OPT_STDERR, &withstderr); retropt_bool(copts, OPT_STDERR, &withstderr);
xiosetchilddied(); /* set SIGCHLD handler */ xiosetchilddied(); /* set SIGCHLD handler */
@ -387,7 +397,7 @@ int _xioopen_foxec(int xioflags, /* XIO_RDONLY etc. */
} }
} }
if (!withfork || pid == 0) { /* in single process, or in child */ if (!withfork || pid == 0) { /* in single process, or in child */
applyopts_optgroup(-1, *copts, PH_PRESOCKET, PH_PRESOCKET, GROUP_PROCESS); applyopts_optgroup(sfd, -1, copts, GROUP_PROCESS);
if (withfork) { if (withfork) {
Close(trigger[0]); /* in child: not needed here */ Close(trigger[0]); /* in child: not needed here */
/* The child should have default handling for SIGCHLD. */ /* The child should have default handling for SIGCHLD. */
@ -398,9 +408,9 @@ int _xioopen_foxec(int xioflags, /* XIO_RDONLY etc. */
#if HAVE_PTY #if HAVE_PTY
if (usepty) { if (usepty) {
applyopts_named(tn, *copts, PH_PREOPEN); applyopts_named(tn, copts, PH_PREOPEN);
applyopts_named(tn, *copts, PH_EARLY); applyopts_named(tn, copts, PH_EARLY);
applyopts_named(tn, *copts, PH_FD); applyopts_named(tn, copts, PH_FD);
if (ttyfd < 0) { if (ttyfd < 0) {
if ((ttyfd = Open(tn, O_RDWR|O_NOCTTY, 0620)) < 0) { if ((ttyfd = Open(tn, O_RDWR|O_NOCTTY, 0620)) < 0) {
@ -427,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(ttyfd, *copts, PH_FD); applyopts(NULL, ttyfd, copts, PH_FD);
Info1("opened pseudo terminal %s", tn); Info1("opened pseudo terminal %s", tn);
Close(ptyfd); Close(ptyfd);
@ -451,11 +461,11 @@ int _xioopen_foxec(int xioflags, /* XIO_RDONLY etc. */
} }
if ((rw == XIO_RDONLY || fdi != ttyfd) && if ((rw == XIO_RDONLY || fdi != ttyfd) &&
(rw == XIO_WRONLY || fdo != ttyfd)) { (rw == XIO_WRONLY || fdo != ttyfd)) {
applyopts_cloexec(ttyfd, *copts); applyopts_cloexec(ttyfd, copts);
} }
applyopts(ttyfd, *copts, PH_LATE); applyopts(NULL, ttyfd, copts, PH_LATE);
applyopts(ttyfd, *copts, PH_LATE2); applyopts(NULL, ttyfd, copts, PH_LATE2);
} else } else
#endif /* HAVE_PTY */ #endif /* HAVE_PTY */
if (usepipes) { if (usepipes) {
@ -492,8 +502,6 @@ int _xioopen_foxec(int xioflags, /* XIO_RDONLY etc. */
return -1; return -1;
} }
Close(rdpip[1]); Close(rdpip[1]);
/*0 Info2("dup2(%d, %d)", rdpip[1], fdo);*/
/*0 applyopts_cloexec(fdo, *copts);*/
} }
if (rw != XIO_RDONLY && wrpip[0] != fdi) { if (rw != XIO_RDONLY && wrpip[0] != fdi) {
/* make sure that the internal diagnostic socket pair fds do not conflict /* make sure that the internal diagnostic socket pair fds do not conflict
@ -504,15 +512,13 @@ int _xioopen_foxec(int xioflags, /* XIO_RDONLY etc. */
return -1; return -1;
} }
Close(wrpip[0]); Close(wrpip[0]);
/*0 Info2("dup2(%d, %d)", wrpip[0], fdi);*/
/*0 applyopts_cloexec(wrpip[0], *copts);*/ /* option is already consumed! */
/* applyopts_cloexec(fdi, *copts);*/ /* option is already consumed! */ /* applyopts_cloexec(fdi, *copts);*/ /* option is already consumed! */
} }
applyopts(fdi, *copts, PH_LATE); applyopts(NULL, fdi, copts, PH_LATE);
applyopts(fdo, *copts, PH_LATE); applyopts(NULL, fdo, copts, PH_LATE);
applyopts(fdi, *copts, PH_LATE2); applyopts(NULL, fdi, copts, PH_LATE2);
applyopts(fdo, *copts, PH_LATE2); applyopts(NULL, fdo, copts, PH_LATE2);
} else { /* socketpair */ } else { /* socketpair */
Close(sv[0]); Close(sv[0]);
@ -535,12 +541,12 @@ int _xioopen_foxec(int xioflags, /* XIO_RDONLY etc. */
/*0 Info2("dup2(%d, %d)", sv[1], fdo);*/ /*0 Info2("dup2(%d, %d)", sv[1], fdo);*/
} }
if (fdi != sv[1] && fdo != sv[1]) { if (fdi != sv[1] && fdo != sv[1]) {
applyopts_cloexec(sv[1], *copts); applyopts_cloexec(sv[1], copts);
Close(sv[1]); Close(sv[1]);
} }
applyopts(fdi, *copts, PH_LATE); applyopts(NULL, fdi, copts, PH_LATE);
applyopts(fdi, *copts, PH_LATE2); applyopts(NULL, fdi, copts, PH_LATE2);
} }
if (withfork) { if (withfork) {
Info("notifying parent that child process is ready"); Info("notifying parent that child process is ready");
@ -548,8 +554,8 @@ int _xioopen_foxec(int xioflags, /* XIO_RDONLY etc. */
} }
} /* withfork */ } /* withfork */
else { else {
applyopts(-1, *copts, PH_LATE); applyopts(NULL, -1, copts, PH_LATE);
applyopts(-1, *copts, PH_LATE2); applyopts(NULL, -1, copts, PH_LATE2);
} }
_xioopen_setdelayeduser(); _xioopen_setdelayeduser();
if (withstderr) { if (withstderr) {
@ -558,6 +564,7 @@ int _xioopen_foxec(int xioflags, /* XIO_RDONLY etc. */
*duptostderr = -1; *duptostderr = -1;
} }
*optsp = copts;
return 0; /* indicate child process */ return 0; /* indicate child process */
} }
@ -565,12 +572,6 @@ int _xioopen_foxec(int xioflags, /* XIO_RDONLY etc. */
Notice1("forked off child process "F_pid, pid); Notice1("forked off child process "F_pid, pid);
Close(trigger[1]); /* in parent */ Close(trigger[1]); /* in parent */
#if 0
if ((popts = copyopts(*copts,
GROUP_FD|GROUP_TERMIOS|GROUP_FORK|GROUP_SOCKET|GROUP_SOCK_UNIX|GROUP_FIFO)) == NULL)
return STAT_RETRYLATER;
#endif
#if HAVE_PTY #if HAVE_PTY
if (usepty) { if (usepty) {
# if 0 # if 0
@ -586,13 +587,12 @@ int _xioopen_foxec(int xioflags, /* XIO_RDONLY etc. */
} else { } else {
Close(sv[1]); Close(sv[1]);
} }
fd->para.exec.pid = pid; sfd->para.exec.pid = pid;
if (applyopts_single(fd, popts, PH_LATE) < 0) return -1; if (applyopts_single(sfd, popts, PH_LATE) < 0) return -1;
applyopts_signal(fd, popts); applyopts(sfd, -1, popts, PH_LATE);
applyopts(-1, popts, PH_LATE); applyopts(sfd, -1, popts, PH_LATE2);
applyopts(-1, popts, PH_LATE2); applyopts(sfd, -1, popts, PH_PASTEXEC);
applyopts(-1, popts, PH_PASTEXEC);
if ((numleft = leftopts(popts)) > 0) { if ((numleft = leftopts(popts)) > 0) {
showleft(popts); showleft(popts);
Error1("INTERNAL: %d option(s) remained unused", numleft); Error1("INTERNAL: %d option(s) remained unused", numleft);
@ -607,6 +607,11 @@ int _xioopen_foxec(int xioflags, /* XIO_RDONLY etc. */
Info("child process notified parent that it is ready"); Info("child process notified parent that it is ready");
} }
applyopts(sfd, ptyfd, popts, PH_LATE);
if (applyopts_single(sfd, popts, PH_LATE) < 0)
return -1;
*optsp = popts;
return pid; /* indicate parent (main) process */ return pid; /* indicate parent (main) process */
} }
#endif /* WITH_EXEC || WITH_SYSTEM */ #endif /* WITH_EXEC || WITH_SYSTEM */

View file

@ -114,7 +114,7 @@ static int xioopen_proxy_connect(int argc, const char *argv[], struct opt *opts,
xfd->howtoend = END_SHUTDOWN; xfd->howtoend = END_SHUTDOWN;
if (applyopts_single(xfd, opts, PH_INIT) < 0) return -1; if (applyopts_single(xfd, opts, PH_INIT) < 0) return -1;
applyopts(-1, opts, PH_INIT); applyopts(xfd, 1, opts, PH_INIT);
retropt_int(opts, OPT_SO_TYPE, &socktype); retropt_int(opts, OPT_SO_TYPE, &socktype);
@ -203,6 +203,8 @@ static int xioopen_proxy_connect(int argc, const char *argv[], struct opt *opts,
return result; return result;
} }
} }
xiofreeaddrinfo(themlist);
applyopts(xfd, -1, opts, PH_ALL);
if ((result = _xio_openlate(xfd, opts)) < 0) if ((result = _xio_openlate(xfd, opts)) < 0)
return result; return result;

View file

@ -30,6 +30,7 @@ const struct optdesc opt_pty_intervall = { "pty-interval", NULL, OPT_P
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, groups_t groups, int dummy1, int dummy2, int dummy3) {
/* we expect the form: filename */ /* we expect the form: filename */
struct single *sfd = &xfd->stream;
int ptyfd = -1, ttyfd = -1; int ptyfd = -1, ttyfd = -1;
#if defined(HAVE_DEV_PTMX) || defined(HAVE_DEV_PTC) #if defined(HAVE_DEV_PTMX) || defined(HAVE_DEV_PTC)
bool useptmx = false; /* use /dev/ptmx or equivalent */ bool useptmx = false; /* use /dev/ptmx or equivalent */
@ -51,10 +52,10 @@ static int xioopen_pty(int argc, const char *argv[], struct opt *opts, int xiofl
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);
} }
xfd->stream.howtoend = END_CLOSE; sfd->howtoend = END_CLOSE;
if (applyopts_single(&xfd->stream, opts, PH_INIT) < 0) return -1; if (applyopts_single(sfd, opts, PH_INIT) < 0) return -1;
applyopts(-1, opts, PH_INIT); applyopts(sfd, -1, opts, PH_INIT);
retropt_bool(opts, OPT_UNLINK_CLOSE, &opt_unlink_close); retropt_bool(opts, OPT_UNLINK_CLOSE, &opt_unlink_close);
@ -88,10 +89,10 @@ static int xioopen_pty(int argc, const char *argv[], struct opt *opts, int xiofl
retropt_timespec(opts, OPT_PTY_INTERVALL, &pollintv); retropt_timespec(opts, OPT_PTY_INTERVALL, &pollintv);
#endif /* HAVE_POLL */ #endif /* HAVE_POLL */
if (applyopts_single(&xfd->stream, opts, PH_INIT) < 0) return -1; if (applyopts_single(sfd, opts, PH_INIT) < 0) return -1;
applyopts2(-1, opts, PH_INIT, PH_EARLY); applyopts2(sfd, -1, opts, PH_INIT, PH_EARLY);
applyopts(-1, opts, PH_PREBIGEN); applyopts(sfd, -1, opts, PH_PREBIGEN);
#if defined(HAVE_DEV_PTMX) #if defined(HAVE_DEV_PTMX)
# define PTMX "/dev/ptmx" /* Linux */ # define PTMX "/dev/ptmx" /* Linux */
@ -155,10 +156,10 @@ static int xioopen_pty(int argc, const char *argv[], struct opt *opts, int xiofl
ptyname, linkname, strerror(errno)); ptyname, linkname, strerror(errno));
} }
if (opt_unlink_close) { if (opt_unlink_close) {
if ((xfd->stream.unlink_close = strdup(linkname)) == NULL) { if ((sfd->unlink_close = strdup(linkname)) == NULL) {
Error1("strdup(\"%s\"): out of memory", linkname); Error1("strdup(\"%s\"): out of memory", linkname);
} }
xfd->stream.opt_unlink_close = true; sfd->opt_unlink_close = true;
} }
} }
@ -166,9 +167,9 @@ static int xioopen_pty(int argc, const char *argv[], struct opt *opts, int xiofl
applyopts_named(ptyname, opts, PH_FD); applyopts_named(ptyname, opts, PH_FD);
applyopts_cloexec(ptyfd, opts);/*!*/ applyopts_cloexec(ptyfd, opts);/*!*/
xfd->stream.dtype = XIODATA_PTY; sfd->dtype = XIODATA_PTY;
applyopts(ptyfd, opts, PH_FD); applyopts(sfd, ptyfd, opts, PH_FD);
{ {
/* special handling of user-late etc.; with standard behaviour (up to /* special handling of user-late etc.; with standard behaviour (up to
@ -196,9 +197,10 @@ static int xioopen_pty(int argc, const char *argv[], struct opt *opts, int xiofl
} }
xfd->stream.fd = ptyfd; sfd->fd = ptyfd;
applyopts(ptyfd, opts, PH_LATE); applyopts(sfd, -1, opts, PH_LATE);
if (applyopts_single(&xfd->stream, opts, PH_LATE) < 0) return -1; if (applyopts_single(sfd, opts, PH_LATE) < 0)
return -1;
#if HAVE_POLL #if HAVE_POLL
/* if you can and wish: */ /* if you can and wish: */

View file

@ -118,7 +118,7 @@ int _xioopen_rawip_sendto(const char *hostname, const char *protname,
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(xfd, opts, PH_INIT) < 0) return -1;
applyopts(-1, opts, PH_INIT); applyopts(xfd, -1, opts, PH_INIT);
xfd->salen = sizeof(xfd->peersa); xfd->salen = sizeof(xfd->peersa);
if ((result = if ((result =

View file

@ -40,6 +40,7 @@ const struct optdesc opt_noecho = { "noecho", NULL, OPT_NOECHO,
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 xioflags, xiofile_t *xfd, groups_t groups, int xioflags, xiofile_t *xfd, groups_t groups,
int dummy1, int dummy2, int dummy3) { int dummy1, int dummy2, int dummy3) {
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;
bool noprompt = false; bool noprompt = false;
@ -85,10 +86,10 @@ static int xioopen_readline(int argc, const char *argv[], struct opt *opts,
} }
#endif /* WITH_TERMIOS */ #endif /* WITH_TERMIOS */
if (applyopts_single(&xfd->stream, opts, PH_INIT) < 0) return -1; if (applyopts_single(sfd, opts, PH_INIT) < 0) return -1;
applyopts(-1, opts, PH_INIT); applyopts(sfd, -1, opts, PH_INIT);
applyopts2(xfd->stream.fd, opts, PH_INIT, PH_FD); applyopts2(sfd, -1, opts, PH_INIT, PH_FD);
Using_history(); Using_history();
applyopts_offset(&xfd->stream, opts); applyopts_offset(&xfd->stream, opts);

View file

@ -167,32 +167,32 @@ const struct optdesc opt_so_peercred = { "so-peercred", "peercred", OPT_SO_PEERC
const struct optdesc opt_so_priority = { "so-priority", "priority", OPT_SO_PRIORITY, GROUP_SOCKET, PH_PASTSOCKET, TYPE_INT, OFUNC_SOCKOPT, SOL_SOCKET, SO_PRIORITY}; const struct optdesc opt_so_priority = { "so-priority", "priority", OPT_SO_PRIORITY, GROUP_SOCKET, PH_PASTSOCKET, TYPE_INT, OFUNC_SOCKOPT, SOL_SOCKET, SO_PRIORITY};
#endif #endif
#ifdef SO_REUSEPORT /* AIX 4.3.3, BSD, HP-UX, Linux >=3.9 */ #ifdef SO_REUSEPORT /* AIX 4.3.3, BSD, HP-UX, Linux >=3.9 */
const struct optdesc opt_so_reuseport= { "so-reuseport","reuseport",OPT_SO_REUSEPORT,GROUP_SOCKET, PH_PREBIND, TYPE_INT, OFUNC_SOCKOPT, SOL_SOCKET, SO_REUSEPORT }; const struct optdesc opt_so_reuseport = { "so-reuseport","reuseport",OPT_SO_REUSEPORT,GROUP_SOCKET, PH_PREBIND, TYPE_INT, OFUNC_SOCKOPT, SOL_SOCKET, SO_REUSEPORT };
#endif /* defined(SO_REUSEPORT) */ #endif /* defined(SO_REUSEPORT) */
#ifdef SO_SECURITY_AUTHENTICATION #ifdef SO_SECURITY_AUTHENTICATION
const struct optdesc opt_so_security_authentication={"so-security-authentication","securityauthentication",OPT_SO_SECURITY_AUTHENTICATION,GROUP_SOCKET,PH_PASTSOCKET,TYPE_INT,OFUNC_SOCKOPT,SOL_SOCKET,SO_SECURITY_AUTHENTICATION}; const struct optdesc opt_so_security_authentication={"so-security-authentication","securityauthentication",OPT_SO_SECURITY_AUTHENTICATION,GROUP_SOCKET,PH_PASTSOCKET,TYPE_INT,OFUNC_SOCKOPT,SOL_SOCKET,SO_SECURITY_AUTHENTICATION};
#endif #endif
#ifdef SO_SECURITY_ENCRYPTION_NETWORK #ifdef SO_SECURITY_ENCRYPTION_NETWORK
const struct optdesc opt_so_security_encryption_network={"so-security-encryption-network","securityencryptionnetwork",OPT_SO_SECURITY_ENCRYPTION_NETWORK,GROUP_SOCKET,PH_PASTSOCKET,TYPE_INT,OFUNC_SOCKOPT,SOL_SOCKET,SO_SECURITY_ENCRYPTION_NETWORK}; const struct optdesc opt_so_security_encryption_network= { "so-security-encryption-network","securityencryptionnetwork",OPT_SO_SECURITY_ENCRYPTION_NETWORK,GROUP_SOCKET,PH_PASTSOCKET,TYPE_INT,OFUNC_SOCKOPT,SOL_SOCKET,SO_SECURITY_ENCRYPTION_NETWORK};
#endif #endif
#ifdef SO_SECURITY_ENCRYPTION_TRANSPORT #ifdef SO_SECURITY_ENCRYPTION_TRANSPORT
const struct optdesc opt_so_security_encryption_transport={"so-security-encryption-transport","securityencryptiontransport",OPT_SO_SECURITY_ENCRYPTION_TRANSPORT,GROUP_SOCKET,PH_PASTSOCKET,TYPE_INT,OFUNC_SOCKOPT,SOL_SOCKET,SO_SECURITY_ENCRYPTION_TRANSPORT}; const struct optdesc opt_so_security_encryption_transport= { "so-security-encryption-transport","securityencryptiontransport",OPT_SO_SECURITY_ENCRYPTION_TRANSPORT,GROUP_SOCKET,PH_PASTSOCKET,TYPE_INT,OFUNC_SOCKOPT,SOL_SOCKET,SO_SECURITY_ENCRYPTION_TRANSPORT};
#endif #endif
#ifdef SO_USE_IFBUFS #ifdef SO_USE_IFBUFS
const struct optdesc opt_so_use_ifbufs={ "so-use-ifbufs","useifbufs",OPT_SO_USE_IFBUFS,GROUP_SOCKET,PH_PASTSOCKET,TYPE_INT, OFUNC_SOCKOPT, SOL_SOCKET, SO_USE_IFBUFS}; const struct optdesc opt_so_use_ifbufs= { "so-use-ifbufs","useifbufs",OPT_SO_USE_IFBUFS,GROUP_SOCKET,PH_PASTSOCKET,TYPE_INT, OFUNC_SOCKOPT, SOL_SOCKET, SO_USE_IFBUFS};
#endif /* SO_USE_IFBUFS */ #endif /* SO_USE_IFBUFS */
#ifdef SO_USELOOPBACK /* AIX433, Solaris, HP-UX */ #ifdef SO_USELOOPBACK /* AIX433, Solaris, HP-UX */
const struct optdesc opt_so_useloopback={"so-useloopback","useloopback",OPT_SO_USELOOPBACK,GROUP_SOCKET,PH_PASTSOCKET,TYPE_INT,OFUNC_SOCKOPT, SOL_SOCKET, SO_USELOOPBACK}; const struct optdesc opt_so_useloopback= { "so-useloopback","useloopback",OPT_SO_USELOOPBACK,GROUP_SOCKET,PH_PASTSOCKET,TYPE_INT,OFUNC_SOCKOPT, SOL_SOCKET, SO_USELOOPBACK};
#endif /* SO_USELOOPBACK */ #endif /* SO_USELOOPBACK */
#ifdef SO_DGRAM_ERRIND /* Solaris */ #ifdef SO_DGRAM_ERRIND /* Solaris */
const struct optdesc opt_so_dgram_errind={"so-dgram-errind","dgramerrind",OPT_SO_DGRAM_ERRIND,GROUP_SOCKET,PH_PASTSOCKET,TYPE_INT,OFUNC_SOCKOPT,SOL_SOCKET,SO_DGRAM_ERRIND}; const struct optdesc opt_so_dgram_errind= { "so-dgram-errind","dgramerrind",OPT_SO_DGRAM_ERRIND,GROUP_SOCKET,PH_PASTSOCKET,TYPE_INT,OFUNC_SOCKOPT,SOL_SOCKET,SO_DGRAM_ERRIND};
#endif /* SO_DGRAM_ERRIND */ #endif /* SO_DGRAM_ERRIND */
#ifdef SO_DONTLINGER /* Solaris */ #ifdef SO_DONTLINGER /* Solaris */
const struct optdesc opt_so_dontlinger = {"so-dontlinger", "dontlinger", OPT_SO_DONTLINGER, GROUP_SOCKET,PH_PASTSOCKET,TYPE_INT,OFUNC_SOCKOPT,SOL_SOCKET,SO_DONTLINGER }; const struct optdesc opt_so_dontlinger = { "so-dontlinger", "dontlinger", OPT_SO_DONTLINGER, GROUP_SOCKET,PH_PASTSOCKET,TYPE_INT,OFUNC_SOCKOPT,SOL_SOCKET,SO_DONTLINGER };
#endif #endif
/* the SO_PROTOTYPE is OS defined on Solaris, HP-UX; we lend this for a more /* the SO_PROTOTYPE is OS defined on Solaris, HP-UX; we lend this for a more
general purpose */ general purpose */
const struct optdesc opt_so_prototype = {"so-protocol", "protocol", OPT_SO_PROTOTYPE, GROUP_SOCKET,PH_SOCKET, TYPE_INT,OFUNC_SPEC, SOL_SOCKET,SO_PROTOCOL }; const struct optdesc opt_so_prototype = { "so-protocol", "protocol", OPT_SO_PROTOTYPE, GROUP_SOCKET,PH_SOCKET, TYPE_INT,OFUNC_SPEC, SOL_SOCKET,SO_PROTOCOL };
#ifdef FIOSETOWN #ifdef FIOSETOWN
const struct optdesc opt_fiosetown = { "fiosetown", NULL, OPT_FIOSETOWN, GROUP_SOCKET, PH_PASTSOCKET, TYPE_INT, OFUNC_IOCTL, FIOSETOWN }; const struct optdesc opt_fiosetown = { "fiosetown", NULL, OPT_FIOSETOWN, GROUP_SOCKET, PH_PASTSOCKET, TYPE_INT, OFUNC_IOCTL, FIOSETOWN };
#endif #endif
@ -219,7 +219,7 @@ static
int xioopen_socket_connect(int argc, const char *argv[], struct opt *opts, int xioopen_socket_connect(int argc, const char *argv[], struct opt *opts,
int xioflags, xiofile_t *xxfd, groups_t groups, int xioflags, xiofile_t *xxfd, groups_t groups,
int dummy1, int dummy2, int dummy3) { int dummy1, int dummy2, int dummy3) {
struct single *xfd = &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];
const char *address = argv[3]; const char *address = argv[3];
@ -251,11 +251,12 @@ int xioopen_socket_connect(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_SHUTDOWN; sfd->howtoend = END_SHUTDOWN;
if (applyopts_single(xfd, opts, PH_INIT) < 0) return -1; if (applyopts_single(sfd, opts, PH_INIT) < 0)
applyopts(-1, opts, PH_INIT); return -1;
applyopts(-1, opts, PH_EARLY); applyopts(sfd, -1, opts, PH_INIT);
applyopts(sfd, -1, opts, PH_EARLY);
themsize = 0; themsize = 0;
if ((result = if ((result =
@ -272,24 +273,24 @@ int xioopen_socket_connect(int argc, const char *argv[], struct opt *opts,
#endif #endif
sizeof(them.soa.sa_family); sizeof(them.soa.sa_family);
xfd->dtype = XIOREAD_STREAM|XIOWRITE_STREAM; sfd->dtype = XIOREAD_STREAM|XIOWRITE_STREAM;
socket_init(0, &us); socket_init(0, &us);
if (retropt_bind(opts, 0 /*pf*/, socktype, proto, (struct sockaddr *)&us, &uslen, 3, if (retropt_bind(opts, 0 /*pf*/, socktype, proto, (struct sockaddr *)&us, &uslen, 3,
xfd->para.socket.ip.ai_flags) sfd->para.socket.ip.ai_flags)
!= STAT_NOACTION) { != STAT_NOACTION) {
needbind = true; needbind = true;
us.soa.sa_family = pf; us.soa.sa_family = pf;
} }
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, socktype, proto, false)) != 0) { opts, pf, socktype, proto, false)) != 0) {
return result; return result;
} }
if ((result = _xio_openlate(xfd, opts)) < 0) { if ((result = _xio_openlate(sfd, opts)) < 0) {
return result; return result;
} }
return STAT_OK; return STAT_OK;
@ -300,7 +301,7 @@ static
int xioopen_socket_listen(int argc, const char *argv[], struct opt *opts, int xioopen_socket_listen(int argc, const char *argv[], struct opt *opts,
int xioflags, xiofile_t *xxfd, groups_t groups, int xioflags, xiofile_t *xxfd, groups_t groups,
int dummy1, int dummy2, int dummy3) { int dummy1, int dummy2, int dummy3) {
struct single *xfd = &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];
const char *usname = argv[3]; const char *usname = argv[3];
@ -331,7 +332,7 @@ int xioopen_socket_listen(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_SHUTDOWN; sfd->howtoend = END_SHUTDOWN;
socket_init(0, &us); socket_init(0, &us);
ussize = 0; ussize = 0;
@ -349,14 +350,15 @@ int xioopen_socket_listen(int argc, const char *argv[], struct opt *opts,
; ;
us.soa.sa_family = pf; us.soa.sa_family = pf;
if (applyopts_single(xfd, opts, PH_INIT) < 0) return -1; if (applyopts_single(sfd, opts, PH_INIT) < 0)
applyopts(-1, opts, PH_INIT); return -1;
applyopts(-1, opts, PH_EARLY); applyopts(sfd, -1, opts, PH_INIT);
applyopts(sfd, -1, opts, PH_EARLY);
opts0 = copyopts(opts, GROUP_ALL); opts0 = copyopts(opts, GROUP_ALL);
if ((result = if ((result =
xioopen_listen(xfd, xioflags, xioopen_listen(sfd, xioflags,
&us.soa, uslen, &us.soa, uslen,
opts, opts0, 0/*instead of pf*/, socktype, proto)) opts, opts0, 0/*instead of pf*/, socktype, proto))
!= STAT_OK) != STAT_OK)
@ -392,7 +394,7 @@ int _xioopen_socket_sendto(const char *pfname, const char *type,
const char *protname, const char *address, const char *protname, const char *address,
struct opt *opts, int xioflags, xiofile_t *xxfd, struct opt *opts, int xioflags, xiofile_t *xxfd,
groups_t groups) { groups_t groups) {
xiosingle_t *xfd = &xxfd->stream; xiosingle_t *sfd = &xxfd->stream;
char *garbage; char *garbage;
union sockaddr_union us = {{0}}; union sockaddr_union us = {{0}};
socklen_t uslen = 0; size_t ussize; socklen_t uslen = 0; size_t ussize;
@ -422,37 +424,37 @@ int _xioopen_socket_sendto(const char *pfname, const char *type,
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_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
+ sizeof(xfd->peersa.soa.sa_len) + sizeof(sfd->peersa.soa.sa_len)
#endif #endif
; ;
#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 (applyopts_single(xfd, opts, PH_INIT) < 0) return -1; if (applyopts_single(sfd, opts, PH_INIT) < 0) return -1;
applyopts(-1, opts, PH_INIT); applyopts(sfd, -1, opts, PH_INIT);
if (pf == PF_UNSPEC) { if (pf == PF_UNSPEC) {
pf = xfd->peersa.soa.sa_family; pf = sfd->peersa.soa.sa_family;
} }
xfd->dtype = XIODATA_RECVFROM; sfd->dtype = XIODATA_RECVFROM;
if (retropt_string(opts, OPT_BIND, &bindstring) == 0) { if (retropt_string(opts, OPT_BIND, &bindstring) == 0) {
ussize = 0; ussize = 0;
@ -474,7 +476,7 @@ int _xioopen_socket_sendto(const char *pfname, const char *type,
return return
_xioopen_dgram_sendto(needbind?&us:NULL, uslen, _xioopen_dgram_sendto(needbind?&us:NULL, uslen,
opts, xioflags, xfd, groups, pf, socktype, proto, 0); opts, xioflags, sfd, groups, pf, socktype, proto, 0);
} }
@ -773,7 +775,7 @@ int xiogetpacketinfo(struct single *sfd, int fd)
Does not fork, does not retry. Does not fork, does not retry.
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, int level) { bool alt, int level) {
@ -790,40 +792,40 @@ int _xioopen_connect(struct single *xfd, union sockaddr_union *us, size_t uslen,
} }
#endif #endif
if ((xfd->fd = xiosocket(opts, pf, socktype, protocol, level)) < 0) { if ((sfd->fd = xiosocket(opts, pf, socktype, protocol, level)) < 0) {
return STAT_RETRYLATER; return STAT_RETRYLATER;
} }
applyopts_offset(xfd, opts); applyopts_offset(sfd, opts);
applyopts(xfd->fd, opts, PH_PASTSOCKET); applyopts(sfd, -1, opts, PH_PASTSOCKET);
applyopts(xfd->fd, opts, PH_FD); applyopts(sfd, -1, opts, PH_FD);
applyopts_cloexec(xfd->fd, opts); applyopts_cloexec(sfd->fd, opts);
if (xiobind(xfd, us, uslen, opts, pf, alt, level) < 0) { if (xiobind(sfd, us, uslen, opts, pf, alt, level) < 0) {
return -1; return -1;
} }
applyopts(xfd->fd, opts, PH_CONNECT); applyopts(sfd, -1, opts, PH_CONNECT);
if (xfd->para.socket.connect_timeout.tv_sec != 0 || if (sfd->para.socket.connect_timeout.tv_sec != 0 ||
xfd->para.socket.connect_timeout.tv_usec != 0) { sfd->para.socket.connect_timeout.tv_usec != 0) {
fcntl_flags = Fcntl(xfd->fd, F_GETFL); fcntl_flags = Fcntl(sfd->fd, F_GETFL);
Fcntl_l(xfd->fd, F_SETFL, fcntl_flags|O_NONBLOCK); Fcntl_l(sfd->fd, F_SETFL, fcntl_flags|O_NONBLOCK);
} }
result = Connect(xfd->fd, them, themlen); result = Connect(sfd->fd, them, themlen);
_errno = errno; _errno = errno;
la.soa.sa_family = them->sa_family; lalen = sizeof(la); la.soa.sa_family = them->sa_family; lalen = sizeof(la);
if (Getsockname(xfd->fd, &la.soa, &lalen) < 0) { if (Getsockname(sfd->fd, &la.soa, &lalen) < 0) {
Msg4(level-1, "getsockname(%d, %p, {%d}): %s", Msg4(level-1, "getsockname(%d, %p, {%d}): %s",
xfd->fd, &la.soa, lalen, strerror(errno)); sfd->fd, &la.soa, lalen, strerror(errno));
} }
errno = _errno; errno = _errno;
if (result < 0) { if (result < 0) {
if (errno == EINPROGRESS) { if (errno == EINPROGRESS) {
if (xfd->para.socket.connect_timeout.tv_sec != 0 || if (sfd->para.socket.connect_timeout.tv_sec != 0 ||
xfd->para.socket.connect_timeout.tv_usec != 0) { sfd->para.socket.connect_timeout.tv_usec != 0) {
struct timeval timeout; struct timeval timeout;
struct pollfd writefd; struct pollfd writefd;
int err; int err;
@ -831,62 +833,62 @@ int _xioopen_connect(struct single *xfd, union sockaddr_union *us, size_t uslen,
int result; int result;
Info4("connect(%d, %s, "F_Zd"): %s", Info4("connect(%d, %s, "F_Zd"): %s",
xfd->fd, sockaddr_info(them, themlen, infobuff, sizeof(infobuff)), sfd->fd, sockaddr_info(them, themlen, infobuff, sizeof(infobuff)),
themlen, strerror(errno)); themlen, strerror(errno));
timeout = xfd->para.socket.connect_timeout; timeout = sfd->para.socket.connect_timeout;
writefd.fd = xfd->fd; writefd.fd = sfd->fd;
writefd.events = (POLLOUT|POLLERR); writefd.events = (POLLOUT|POLLERR);
result = xiopoll(&writefd, 1, &timeout); result = xiopoll(&writefd, 1, &timeout);
if (result < 0) { if (result < 0) {
Msg4(level, "xiopoll({%d,POLLOUT|POLLERR},,{"F_tv_sec"."F_tv_usec"): %s", Msg4(level, "xiopoll({%d,POLLOUT|POLLERR},,{"F_tv_sec"."F_tv_usec"): %s",
xfd->fd, timeout.tv_sec, timeout.tv_usec, strerror(errno)); sfd->fd, timeout.tv_sec, timeout.tv_usec, strerror(errno));
Close(xfd->fd); Close(sfd->fd);
return STAT_RETRYLATER; return STAT_RETRYLATER;
} }
if (result == 0) { if (result == 0) {
Msg2(level, "connecting to %s: %s", Msg2(level, "connecting to %s: %s",
sockaddr_info(them, themlen, infobuff, sizeof(infobuff)), sockaddr_info(them, themlen, infobuff, sizeof(infobuff)),
strerror(ETIMEDOUT)); strerror(ETIMEDOUT));
Close(xfd->fd); Close(sfd->fd);
return STAT_RETRYLATER; return STAT_RETRYLATER;
} }
if (writefd.revents & POLLERR) { if (writefd.revents & POLLERR) {
#if 0 #if 0
unsigned char dummy[1]; unsigned char dummy[1];
Read(xfd->fd, &dummy, 1); /* get error message */ Read(sfd->fd, &dummy, 1); /* get error message */
Msg2(level, "connecting to %s: %s", Msg2(level, "connecting to %s: %s",
sockaddr_info(them, infobuff, sizeof(infobuff)), sockaddr_info(them, infobuff, sizeof(infobuff)),
strerror(errno)); strerror(errno));
#else #else
Connect(xfd->fd, them, themlen); /* get error message */ Connect(sfd->fd, them, themlen); /* get error message */
Msg4(level, "connect(%d, %s, "F_Zd"): %s", Msg4(level, "connect(%d, %s, "F_Zd"): %s",
xfd->fd, sockaddr_info(them, themlen, infobuff, sizeof(infobuff)), sfd->fd, sockaddr_info(them, themlen, infobuff, sizeof(infobuff)),
themlen, strerror(errno)); themlen, strerror(errno));
#endif #endif
Close(xfd->fd); Close(sfd->fd);
return STAT_RETRYLATER; return STAT_RETRYLATER;
} }
/* otherwise OK or network error */ /* otherwise OK or network error */
result = Getsockopt(xfd->fd, SOL_SOCKET, SO_ERROR, &err, &errlen); result = Getsockopt(sfd->fd, SOL_SOCKET, SO_ERROR, &err, &errlen);
if (result != 0) { if (result != 0) {
Msg2(level, "getsockopt(%d, SOL_SOCKET, SO_ERROR, ...): %s", Msg2(level, "getsockopt(%d, SOL_SOCKET, SO_ERROR, ...): %s",
xfd->fd, strerror(err)); sfd->fd, strerror(err));
Close(xfd->fd); Close(sfd->fd);
return STAT_RETRYLATER; return STAT_RETRYLATER;
} }
Debug2("getsockopt(%d, SOL_SOCKET, SO_ERROR, { %d }) -> 0", Debug2("getsockopt(%d, SOL_SOCKET, SO_ERROR, { %d }) -> 0",
xfd->fd, err); sfd->fd, err);
if (err != 0) { if (err != 0) {
Msg4(level, "connect(%d, %s, "F_Zd"): %s", Msg4(level, "connect(%d, %s, "F_Zd"): %s",
xfd->fd, sockaddr_info(them, themlen, infobuff, sizeof(infobuff)), sfd->fd, sockaddr_info(them, themlen, infobuff, sizeof(infobuff)),
themlen, strerror(err)); themlen, strerror(err));
Close(xfd->fd); Close(sfd->fd);
return STAT_RETRYLATER; return STAT_RETRYLATER;
} }
Fcntl_l(xfd->fd, F_SETFL, fcntl_flags); Fcntl_l(sfd->fd, F_SETFL, fcntl_flags);
} else { } else {
Warn4("connect(%d, %s, "F_Zd"): %s", Warn4("connect(%d, %s, "F_Zd"): %s",
xfd->fd, sockaddr_info(them, themlen, infobuff, sizeof(infobuff)), sfd->fd, sockaddr_info(them, themlen, infobuff, sizeof(infobuff)),
themlen, strerror(errno)); themlen, strerror(errno));
} }
} else if (pf == PF_UNIX) { } else if (pf == PF_UNIX) {
@ -896,21 +898,21 @@ int _xioopen_connect(struct single *xfd, union sockaddr_union *us, size_t uslen,
*/ */
int _errno = errno; int _errno = errno;
Info4("connect(%d, %s, "F_Zd"): %s", Info4("connect(%d, %s, "F_Zd"): %s",
xfd->fd, sockaddr_info(them, themlen, infobuff, sizeof(infobuff)), sfd->fd, sockaddr_info(them, themlen, infobuff, sizeof(infobuff)),
themlen, strerror(errno)); themlen, strerror(errno));
/* caller must handle this condition */ /* caller must handle this condition */
Close(xfd->fd); xfd->fd = -1; Close(sfd->fd); sfd->fd = -1;
errno = _errno; errno = _errno;
return STAT_RETRYLATER; return STAT_RETRYLATER;
} else { } else {
/* try to find details about error, especially from ICMP */ /* try to find details about error, especially from ICMP */
xiogetpacketinfo(xfd, xfd->fd); xiogetpacketinfo(sfd, sfd->fd);
/* continue mainstream */ /* continue mainstream */
Msg4(level, "connect(%d, %s, "F_Zd"): %s", Msg4(level, "connect(%d, %s, "F_Zd"): %s",
xfd->fd, sockaddr_info(them, themlen, infobuff, sizeof(infobuff)), sfd->fd, sockaddr_info(them, themlen, infobuff, sizeof(infobuff)),
themlen, strerror(errno)); themlen, strerror(errno));
Close(xfd->fd); Close(sfd->fd);
return STAT_RETRYLATER; return STAT_RETRYLATER;
} }
} else { /* result >= 0 */ } else { /* result >= 0 */
@ -918,14 +920,14 @@ int _xioopen_connect(struct single *xfd, union sockaddr_union *us, size_t uslen,
sockaddr_info(&la.soa, themlen, infobuff, sizeof(infobuff))); sockaddr_info(&la.soa, themlen, infobuff, sizeof(infobuff)));
} }
applyopts_fchown(xfd->fd, opts); /* OPT_USER, OPT_GROUP */ applyopts_fchown(sfd->fd, opts); /* OPT_USER, OPT_GROUP */
applyopts(xfd->fd, opts, PH_CONNECTED); applyopts(sfd, -1, opts, PH_CONNECTED);
#if WITH_UNIX #if WITH_UNIX
if (pf == PF_UNIX && us != NULL) { if (pf == PF_UNIX && us != NULL) {
applyopts_named(us->un.sun_path, opts, PH_LATE); applyopts_named(us->un.sun_path, opts, PH_LATE);
} }
#endif #endif
applyopts(xfd->fd, opts, PH_LATE); applyopts(sfd, -1, opts, PH_LATE);
return STAT_OK; return STAT_OK;
} }
@ -1043,7 +1045,7 @@ int xioopen_connect(struct single *xfd, union sockaddr_union *us, size_t uslen,
int _xioopen_dgram_sendto(/* them is already in xfd->peersa */ int _xioopen_dgram_sendto(/* them is already in xfd->peersa */
union sockaddr_union *us, socklen_t uslen, union sockaddr_union *us, socklen_t uslen,
struct opt *opts, struct opt *opts,
int xioflags, xiosingle_t *xfd, groups_t groups, int xioflags, xiosingle_t *sfd, groups_t groups,
int pf, int socktype, int ipproto, bool alt) { int pf, int socktype, int ipproto, bool alt) {
int level = E_ERROR; int level = E_ERROR;
union sockaddr_union la; socklen_t lalen = sizeof(la); union sockaddr_union la; socklen_t lalen = sizeof(la);
@ -1055,39 +1057,39 @@ int _xioopen_dgram_sendto(/* them is already in xfd->peersa */
} }
#endif #endif
if ((xfd->fd = xiosocket(opts, pf, socktype, ipproto, level)) < 0) { if ((sfd->fd = xiosocket(opts, pf, socktype, ipproto, level)) < 0) {
return STAT_RETRYLATER; return STAT_RETRYLATER;
} }
applyopts_offset(xfd, opts); applyopts_offset(sfd, opts);
applyopts_single(xfd, opts, PH_PASTSOCKET); applyopts_single(sfd, opts, PH_PASTSOCKET);
applyopts(xfd->fd, opts, PH_PASTSOCKET); applyopts(sfd, -1, opts, PH_PASTSOCKET);
applyopts_single(xfd, opts, PH_FD); applyopts_single(sfd, opts, PH_FD);
applyopts(xfd->fd, opts, PH_FD); applyopts(sfd, -1, opts, PH_FD);
applyopts_cloexec(xfd->fd, opts); applyopts_cloexec(sfd->fd, opts);
if (xiobind(xfd, us, uslen, opts, pf, alt, level) < 0) { if (xiobind(sfd, us, uslen, opts, pf, alt, level) < 0) {
return -1; return -1;
} }
/*applyopts(xfd->fd, opts, PH_CONNECT);*/ /*applyopts(sfd, -1, opts, PH_CONNECT);*/
if (Getsockname(xfd->fd, &la.soa, &lalen) < 0) { if (Getsockname(sfd->fd, &la.soa, &lalen) < 0) {
Warn4("getsockname(%d, %p, {%d}): %s", Warn4("getsockname(%d, %p, {%d}): %s",
xfd->fd, &la.soa, lalen, strerror(errno)); sfd->fd, &la.soa, lalen, strerror(errno));
} }
applyopts_fchown(xfd->fd, opts); applyopts_fchown(sfd->fd, opts);
applyopts(xfd->fd, opts, PH_CONNECTED); applyopts(sfd, -1, opts, PH_CONNECTED);
#if WITH_UNIX #if WITH_UNIX
if (pf == PF_UNIX && us != NULL) { if (pf == PF_UNIX && us != NULL) {
applyopts_named(us->un.sun_path, opts, PH_LATE); applyopts_named(us->un.sun_path, opts, PH_LATE);
} }
#endif #endif
/*0 applyopts(xfd->fd, opts, PH_LATE); */ /*0 applyopts(sfd, -1, opts, PH_LATE); */
/* xfd->dtype = DATA_RECVFROM; *//* no, the caller must set this (ev _SKIPIP) */ /* sfd->dtype = DATA_RECVFROM; *//* no, the caller must set this (ev _SKIPIP) */
Notice1("successfully prepared local socket %s", Notice1("successfully prepared local socket %s",
sockaddr_info(&la.soa, lalen, infobuff, sizeof(infobuff))); sockaddr_info(&la.soa, lalen, infobuff, sizeof(infobuff)));
@ -1150,8 +1152,7 @@ int _xioopen_dgram_recvfrom(struct single *xfd, int xioflags,
return STAT_RETRYLATER; return STAT_RETRYLATER;
} }
applyopts_single(xfd, opts, PH_PASTSOCKET); applyopts(xfd, -1, opts, PH_PASTSOCKET);
applyopts(xfd->fd, opts, PH_PASTSOCKET);
applyopts_cloexec(xfd->fd, opts); applyopts_cloexec(xfd->fd, opts);
@ -1160,12 +1161,11 @@ int _xioopen_dgram_recvfrom(struct single *xfd, int xioflags,
return -1; return -1;
} }
applyopts(xfd->fd, opts, PH_PASTBIND); applyopts(xfd, -1, opts, PH_PASTBIND);
#if WITH_UNIX #if WITH_UNIX
if (pf == AF_UNIX && us != NULL) { if (pf == AF_UNIX && us != NULL) {
applyopts_named(((struct sockaddr_un *)us)->sun_path, opts, PH_FD); applyopts_named(((struct sockaddr_un *)us)->sun_path, opts, PH_FD);
/*applyopts_early(((struct sockaddr_un *)us)->sun_path, opts);*/
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);
} }
@ -1283,9 +1283,9 @@ 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->fd, opts, PH_FD); applyopts(xfd, -1, opts, PH_FD);
applyopts(xfd->fd, opts, PH_CONNECTED); applyopts(xfd, -1, opts, PH_CONNECTED);
xfd->peersa = *(union sockaddr_union *)pa; xfd->peersa = *(union sockaddr_union *)pa;
xfd->salen = palen; xfd->salen = palen;
@ -1357,8 +1357,7 @@ int _xioopen_dgram_recv(struct single *xfd, int xioflags,
return STAT_RETRYLATER; return STAT_RETRYLATER;
} }
applyopts_single(xfd, opts, PH_PASTSOCKET); applyopts(xfd, -1, opts, PH_PASTSOCKET);
applyopts(xfd->fd, opts, PH_PASTSOCKET);
applyopts_cloexec(xfd->fd, opts); applyopts_cloexec(xfd->fd, opts);
@ -1369,7 +1368,6 @@ int _xioopen_dgram_recv(struct single *xfd, int xioflags,
#if WITH_UNIX #if WITH_UNIX
if (pf == AF_UNIX && us != NULL) { if (pf == AF_UNIX && us != NULL) {
applyopts_named(((struct sockaddr_un *)us)->sun_path, opts, PH_FD); applyopts_named(((struct sockaddr_un *)us)->sun_path, opts, PH_FD);
/*applyopts_early(((struct sockaddr_un *)us)->sun_path, opts);*/
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);
} }
@ -2023,7 +2021,7 @@ xiosocket(struct opt *opts, int pf, int socktype, int proto, int msglevel) {
retropt_int(opts, OPT_SO_TYPE, &socktype); retropt_int(opts, OPT_SO_TYPE, &socktype);
retropt_int(opts, OPT_SO_PROTOTYPE, &proto); retropt_int(opts, OPT_SO_PROTOTYPE, &proto);
applyopts(-1, opts, PH_PRESOCKET); applyopts(NULL, -1, opts, PH_PRESOCKET);
result = Socket(pf, socktype, proto); result = Socket(pf, socktype, proto);
if (result < 0) { if (result < 0) {
int _errno = errno; int _errno = errno;
@ -2070,8 +2068,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->fd, opts, PH_PREBIND); applyopts(xfd, xfd->fd, opts, PH_PREBIND);
applyopts(xfd->fd, opts, PH_BIND); applyopts(xfd, xfd->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;
@ -2170,7 +2168,7 @@ int xiobind(
} }
#endif #endif
applyopts(xfd->fd, opts, PH_PASTBIND); applyopts(xfd, -1, opts, PH_PASTBIND);
return 0; return 0;
} }

View file

@ -20,7 +20,7 @@ static int xioopen_socketpair(int argc, const char *argv[], struct opt *opts, in
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>") };
/* open a socketpair */ /* Open a socketpair */
static int xioopen_socketpair( static int xioopen_socketpair(
int argc, int argc,
const char *argv[], const char *argv[],
@ -32,7 +32,7 @@ static int xioopen_socketpair(
int dummy2, int dummy2,
int dummy3) int dummy3)
{ {
struct single *sfd; struct single *sfd = &xfd->stream;
struct opt *opts2; struct opt *opts2;
int pf = PF_UNIX; int pf = PF_UNIX;
int protocol = 0; int protocol = 0;
@ -44,10 +44,9 @@ static int xioopen_socketpair(
Error2("%s: wrong number of parameters (%d instead of 1)", argv[0], argc-1); Error2("%s: wrong number of parameters (%d instead of 1)", argv[0], argc-1);
} }
sfd = &xfd->stream;
sfd->para.bipipe.socktype = SOCK_DGRAM; sfd->para.bipipe.socktype = SOCK_DGRAM;
if (applyopts_single(sfd, opts, PH_INIT) < 0) return -1; if (applyopts_single(sfd, opts, PH_INIT) < 0) return -1;
applyopts(-1, opts, PH_INIT); applyopts(sfd, -1, opts, PH_INIT);
retropt_int(opts, OPT_PROTOCOL_FAMILY, &pf); retropt_int(opts, OPT_PROTOCOL_FAMILY, &pf);
retropt_int(opts, OPT_SO_TYPE, &sfd->para.bipipe.socktype); retropt_int(opts, OPT_SO_TYPE, &sfd->para.bipipe.socktype);
retropt_int(opts, OPT_SO_PROTOTYPE, &protocol); retropt_int(opts, OPT_SO_PROTOTYPE, &protocol);
@ -78,7 +77,7 @@ static int xioopen_socketpair(
} }
/* apply options to first FD */ /* apply options to first FD */
if ((result = applyopts(sfd->fd, opts, PH_ALL)) < 0) { if ((result = applyopts(sfd, -1, opts, PH_ALL)) < 0) {
return result; return result;
} }
if ((result = applyopts_single(sfd, opts, PH_ALL)) < 0) { if ((result = applyopts_single(sfd, opts, PH_ALL)) < 0) {
@ -86,10 +85,8 @@ static int xioopen_socketpair(
} }
/* apply options to second FD */ /* apply options to second FD */
if ((result = applyopts(sfd->para.bipipe.fdout, opts2, PH_ALL)) < 0) if (applyopts(sfd, sfd->para.bipipe.fdout, opts2, PH_ALL) < 0)
{ return -1;
return result;
}
if ((numleft = leftopts(opts)) > 0) { if ((numleft = leftopts(opts)) > 0) {
Error1("%d option(s) could not be used", numleft); Error1("%d option(s) could not be used", numleft);

View file

@ -76,7 +76,7 @@ static int xioopen_socks4_connect(int argc, const char *argv[], struct opt *opts
xfd->howtoend = END_SHUTDOWN; xfd->howtoend = END_SHUTDOWN;
if (applyopts_single(xfd, opts, PH_INIT) < 0) return -1; if (applyopts_single(xfd, opts, PH_INIT) < 0) return -1;
applyopts(-1, opts, PH_INIT); applyopts(xfd, 1, opts, PH_INIT);
retropt_int(opts, OPT_SO_TYPE, &socktype); retropt_int(opts, OPT_SO_TYPE, &socktype);
@ -180,6 +180,8 @@ static int xioopen_socks4_connect(int argc, const char *argv[], struct opt *opts
xiofreeaddrinfo(themlist); xiofreeaddrinfo(themlist);
return result; return result;
} }
xiofreeaddrinfo(themlist);
applyopts(xfd, -1, opts, PH_ALL);
if ((result = _xio_openlate(xfd, opts)) < 0) if ((result = _xio_openlate(xfd, opts)) < 0)
return result; return result;

View file

@ -539,7 +539,7 @@ static int xioopen_socks5(
xfd->howtoend = END_SHUTDOWN; xfd->howtoend = END_SHUTDOWN;
if (applyopts_single(xfd, opts, PH_INIT) < 0) return -1; if (applyopts_single(xfd, opts, PH_INIT) < 0) return -1;
applyopts(-1, opts, PH_INIT); applyopts(xfd, -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);
@ -594,7 +594,7 @@ static int xioopen_socks5(
} }
} }
xiofreeaddrinfo(themlist); xiofreeaddrinfo(themlist);
applyopts(xfd->fd, opts, PH_ALL); applyopts(xfd, -1, opts, PH_ALL);
if ((result = _xio_openlate(xfd, opts)) < 0) if ((result = _xio_openlate(xfd, opts)) < 0)
return result; return result;

View file

@ -89,16 +89,16 @@ int xioopen_stdio_bi(xiofile_t *sock) {
sock->dual.stream[1]->opts, PH_INIT) sock->dual.stream[1]->opts, PH_INIT)
< 0) < 0)
return -1; return -1;
applyopts(-1, sock->dual.stream[0]->opts, PH_INIT); applyopts(sock->dual.stream[0], -1, sock->dual.stream[0]->opts, PH_INIT);
applyopts(-1, sock->dual.stream[1]->opts, PH_INIT); applyopts(sock->dual.stream[1], -1, sock->dual.stream[1]->opts, PH_INIT);
if ((result = applyopts(-1, optspr, PH_EARLY)) < 0) if ((result = applyopts(NULL, -1, optspr, PH_EARLY)) < 0)
return result; return result;
if ((result = applyopts(-1, optspr, PH_PREOPEN)) < 0) if ((result = applyopts(NULL, -1, optspr, PH_PREOPEN)) < 0)
return result; return result;
/* apply options to first FD */ /* apply options to first FD */
if ((result = if ((result =
applyopts(sock->dual.stream[0]->fd, applyopts(sock->dual.stream[0], -1,
sock->dual.stream[0]->opts, PH_ALL)) sock->dual.stream[0]->opts, PH_ALL))
< 0) { < 0) {
return result; return result;
@ -113,7 +113,7 @@ int xioopen_stdio_bi(xiofile_t *sock) {
#endif #endif
/* apply options to second FD */ /* apply options to second FD */
if ((result = applyopts(sock->dual.stream[1]->fd, if ((result = applyopts(sock->dual.stream[1], -1,
sock->dual.stream[1]->opts, PH_ALL)) < 0) { sock->dual.stream[1]->opts, PH_ALL)) < 0) {
return result; return result;
} }

View file

@ -43,18 +43,20 @@ void dummy(void) {
if (0) { { ; if (0) { { ;
#endif #endif
#ifdef I_POP #ifdef I_POP
} else if (opt->desc->func == OFUNC_STREAMS_I_POP_ALL) { case OFUNC_STREAMS_I_POP_ALL:
while (Ioctl(fd, I_POP, 0) >= 0) { while (Ioctl(fd, I_POP, 0) >= 0) {
Warn2("ioctl(%d, I_POP, 0): %s", fd, strerror(errno)); Warn2("ioctl(%d, I_POP, 0): %s", fd, strerror(errno));
} }
break;
#endif #endif
#ifdef I_PUSH #ifdef I_PUSH
} else if (opt->desc->func == OFUNC_STREAMS_I_PUSH) { case OFUNC_STREAMS_I_PUSH:
if (Ioctl(fd, I_PUSH, opt->value.u_string) < 0) { if (Ioctl(fd, I_PUSH, opt->value.u_string) < 0) {
Warn3("ioctl(%d, I_PUSH, \"%s\"): %s", Warn3("ioctl(%d, I_PUSH, \"%s\"): %s",
fd, opt->value.u_string, strerror(errno)); fd, opt->value.u_string, strerror(errno));
return -1; rc = -1;
} }
break;
#endif #endif
#if 0 #if 0
} } } } } }

View file

@ -25,18 +25,20 @@ const struct addrdesc xioaddr_system = { "SYSTEM", 3, xioopen_system, GROUP_FD|G
static int xioopen_system(int argc, const char *argv[], struct opt *opts, static int xioopen_system(int argc, const char *argv[], struct opt *opts,
int xioflags, /* XIO_RDONLY etc. */ int xioflags, /* XIO_RDONLY etc. */
xiofile_t *fd, xiofile_t *xfd,
groups_t groups, groups_t groups,
int dummy1, int dummy2, int dummy3 int dummy1, int dummy2, int dummy3
) { ) {
struct single *sfd = &xfd->stream;
int status; int status;
char *path = NULL; char *path = NULL;
int duptostderr; int duptostderr;
int result; int result;
const char *string = argv[1]; const char *string = argv[1];
status = _xioopen_foxec(xioflags, &fd->stream, groups, &opts, &duptostderr); status = _xioopen_foxec(xioflags, sfd, groups, &opts, &duptostderr);
if (status < 0) return status; if (status < 0)
return status;
if (status == 0) { /* child */ if (status == 0) { /* child */
int numleft; int numleft;
@ -72,6 +74,7 @@ static int xioopen_system(int argc, const char *argv[], struct opt *opts,
} }
/* parent */ /* parent */
_xio_openlate(sfd, opts);
return 0; return 0;
} }

View file

@ -12,7 +12,7 @@
/****** TERMIOS addresses ******/ /****** TERMIOS addresses ******/
#if _WITH_TERMIOS #if _WITH_TERMIOS
#if WITH_TERMIOS #if WITH_TERMIOS
const struct optdesc opt_tiocsctty={ "tiocsctty", "ctty",OPT_TIOCSCTTY, GROUP_TERMIOS, PH_LATE2, TYPE_BOOL, OFUNC_SPEC }; const struct optdesc opt_tiocsctty = { "tiocsctty", "ctty",OPT_TIOCSCTTY, GROUP_TERMIOS, PH_LATE2, TYPE_BOOL, OFUNC_SPEC };
/* it is important for handling of these options that they have PH_FD */ /* it is important for handling of these options that they have PH_FD */
const struct optdesc opt_brkint = { "brkint", NULL, OPT_BRKINT, GROUP_TERMIOS, PH_FD, TYPE_BOOL, OFUNC_TERMIOS_FLAG, 0, BRKINT }; const struct optdesc opt_brkint = { "brkint", NULL, OPT_BRKINT, GROUP_TERMIOS, PH_FD, TYPE_BOOL, OFUNC_TERMIOS_FLAG, 0, BRKINT };

View file

@ -46,6 +46,7 @@ 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, groups_t groups, int dummy1, int dummy2, int dummy3) {
struct single *sfd = &xfd->stream;
char *tundevice = NULL; char *tundevice = NULL;
char *tunname = NULL, *tuntype = NULL; char *tunname = NULL, *tuntype = NULL;
int pf = /*! PF_UNSPEC*/ PF_INET; int pf = /*! PF_UNSPEC*/ PF_INET;
@ -79,10 +80,10 @@ static int xioopen_tun(int argc, const char *argv[], struct opt *opts, int xiofl
/*========================= the tunnel interface =========================*/ /*========================= the tunnel interface =========================*/
Notice("creating tunnel network interface"); Notice("creating tunnel network interface");
applyopts_optgroup(-1, opts, PH_PRESOCKET, PH_PRESOCKET, GROUP_PROCESS); applyopts_optgroup(&xfd->stream, -1, opts, GROUP_PROCESS);
if ((result = _xioopen_open(tundevice, rw, opts)) < 0) if ((result = _xioopen_open(tundevice, rw, opts)) < 0)
return result; return result;
xfd->stream.fd = result; sfd->fd = result;
/* prepare configuration of the new network interface */ /* prepare configuration of the new network interface */
memset(&ifr, 0, sizeof(ifr)); memset(&ifr, 0, sizeof(ifr));
@ -113,10 +114,10 @@ static int xioopen_tun(int argc, const char *argv[], struct opt *opts, int xiofl
} }
} }
if (Ioctl(xfd->stream.fd, TUNSETIFF, &ifr) < 0) { if (Ioctl(sfd->fd, TUNSETIFF, &ifr) < 0) {
Error3("ioctl(%d, TUNSETIFF, {\"%s\"}: %s", Error3("ioctl(%d, TUNSETIFF, {\"%s\"}: %s",
xfd->stream.fd, ifr.ifr_name, strerror(errno)); sfd->fd, ifr.ifr_name, strerror(errno));
Close(xfd->stream.fd); Close(sfd->fd);
} }
Notice1("TUN: new device \"%s\"", ifr.ifr_name); Notice1("TUN: new device \"%s\"", ifr.ifr_name);
@ -125,7 +126,7 @@ static int xioopen_tun(int argc, const char *argv[], struct opt *opts, int xiofl
/* we seem to need a socket for manipulating the interface */ /* we seem to need a socket for manipulating the interface */
if ((sockfd = Socket(PF_INET, SOCK_DGRAM, 0)) < 0) { if ((sockfd = Socket(PF_INET, SOCK_DGRAM, 0)) < 0) {
Error1("socket(PF_INET, SOCK_DGRAM, 0): %s", strerror(errno)); Error1("socket(PF_INET, SOCK_DGRAM, 0): %s", strerror(errno));
sockfd = xfd->stream.fd; /* desparate fallback attempt */ sockfd = sfd->fd; /* desparate fallback attempt */
} }
/*--------------------- setting interface address and netmask ------------*/ /*--------------------- setting interface address and netmask ------------*/
@ -135,7 +136,7 @@ static int xioopen_tun(int argc, const char *argv[], struct opt *opts, int xiofl
return STAT_RETRYLATER; return STAT_RETRYLATER;
} }
if ((result = xioparsenetwork(ifaddr, pf, &network, if ((result = xioparsenetwork(ifaddr, pf, &network,
xfd->stream.para.socket.ip.ai_flags)) sfd->para.socket.ip.ai_flags))
!= STAT_OK) { != STAT_OK) {
/*! recover */ /*! recover */
return result; return result;
@ -157,16 +158,16 @@ static int xioopen_tun(int argc, const char *argv[], struct opt *opts, int xiofl
free(ifaddr); free(ifaddr);
} }
/*--------------------- setting interface flags --------------------------*/ /*--------------------- setting interface flags --------------------------*/
applyopts_single(&xfd->stream, opts, PH_FD); applyopts_single(sfd, opts, PH_FD);
_xiointerface_apply_iff(sockfd, ifr.ifr_name, xfd->stream.para.interface.iff_opts); _xiointerface_apply_iff(sockfd, ifr.ifr_name, sfd->para.interface.iff_opts);
applyopts(xfd->stream.fd, opts, PH_FD); applyopts(sfd, -1, opts, PH_FD);
applyopts_cloexec(xfd->stream.fd, opts); applyopts_cloexec(sfd->fd, opts);
applyopts_fchown(xfd->stream.fd, opts); applyopts_fchown(sfd->fd, opts);
if ((result = _xio_openlate(&xfd->stream, opts)) < 0) if ((result = _xio_openlate(sfd, opts)) < 0)
return result; return result;
return 0; return 0;

View file

@ -149,7 +149,7 @@ int _xioopen_ipdgram_listen(struct single *sfd,
} }
doreuseaddr |= (retropt_2integrals(opts, OPT_SO_REUSEADDR, doreuseaddr |= (retropt_2integrals(opts, OPT_SO_REUSEADDR,
&reuseaddr, &notnull) >= 0); &reuseaddr, &notnull) >= 0);
applyopts(sfd->fd, opts, PH_PASTSOCKET); applyopts(sfd, -1, opts, PH_PASTSOCKET);
/* SO_REUSEADDR handling of UDP sockets is helpful on Solaris */ /* SO_REUSEADDR handling of UDP sockets is helpful on Solaris */
if (doreuseaddr) { if (doreuseaddr) {
@ -163,8 +163,8 @@ int _xioopen_ipdgram_listen(struct single *sfd,
} }
} }
applyopts_cloexec(sfd->fd, opts); applyopts_cloexec(sfd->fd, opts);
applyopts(sfd->fd, opts, PH_PREBIND); applyopts(sfd, -1, opts, PH_PREBIND);
applyopts(sfd->fd, opts, PH_BIND); applyopts(sfd, -1, opts, PH_BIND);
if (Bind(sfd->fd, &us->soa, uslen) < 0) { if (Bind(sfd->fd, &us->soa, uslen) < 0) {
Error4("bind(%d, {%s}, "F_socklen"): %s", sfd->fd, Error4("bind(%d, {%s}, "F_socklen"): %s", sfd->fd,
sockaddr_info(&us->soa, uslen, infobuff, sizeof(infobuff)), sockaddr_info(&us->soa, uslen, infobuff, sizeof(infobuff)),
@ -176,7 +176,7 @@ int _xioopen_ipdgram_listen(struct single *sfd,
Error4("getsockname(%d, %p, {%d}): %s", Error4("getsockname(%d, %p, {%d}): %s",
sfd->fd, &us->soa, uslen, strerror(errno)); sfd->fd, &us->soa, uslen, strerror(errno));
} }
applyopts(sfd->fd, opts, PH_PASTBIND); applyopts(sfd, -1, opts, PH_PASTBIND);
if (ipproto == IPPROTO_UDP) { if (ipproto == IPPROTO_UDP) {
Notice1("listening on UDP %s", Notice1("listening on UDP %s",
@ -255,7 +255,7 @@ int _xioopen_ipdgram_listen(struct single *sfd,
break; break;
} /* end of the big while loop */ } /* end of the big while loop */
applyopts(sfd->fd, opts, PH_CONNECT); applyopts(sfd, -1, opts, PH_CONNECT);
if ((result = Connect(sfd->fd, &them->soa, themlen)) < 0) { if ((result = Connect(sfd->fd, &them->soa, themlen)) < 0) {
Error4("connect(%d, {%s}, "F_socklen"): %s", Error4("connect(%d, {%s}, "F_socklen"): %s",
sfd->fd, sfd->fd,
@ -274,7 +274,7 @@ int _xioopen_ipdgram_listen(struct single *sfd,
sfd->howtoend = END_SHUTDOWN; sfd->howtoend = END_SHUTDOWN;
applyopts_fchown(sfd->fd, opts); applyopts_fchown(sfd->fd, opts);
applyopts(sfd->fd, opts, PH_LATE); applyopts(sfd, -1, opts, PH_LATE);
if ((result = _xio_openlate(sfd, opts)) < 0) if ((result = _xio_openlate(sfd, opts)) < 0)
return result; return result;
@ -287,6 +287,7 @@ int xioopen_ipdgram_listen(int argc, const char *argv[], struct opt *opts,
int xioflags, xiofile_t *xfd, int xioflags, xiofile_t *xfd,
groups_t groups, int pf, int ipproto, groups_t groups, int pf, int ipproto,
int protname) { int protname) {
struct single *sfd = &xfd->stream;
const char *portname = argv[1]; const char *portname = argv[1];
union sockaddr_union us; union sockaddr_union us;
int socktype = SOCK_DGRAM; int socktype = SOCK_DGRAM;
@ -314,8 +315,9 @@ int xioopen_ipdgram_listen(int argc, const char *argv[], struct opt *opts,
retropt_socket_pf(opts, &pf); retropt_socket_pf(opts, &pf);
retropt_int(opts, OPT_SO_PROTOTYPE, &ipproto); retropt_int(opts, OPT_SO_PROTOTYPE, &ipproto);
if (applyopts_single(&xfd->stream, opts, PH_INIT) < 0) return -1; if (applyopts_single(sfd, opts, PH_INIT) < 0)
applyopts(-1, opts, PH_INIT); return -1;
applyopts(sfd, -1, opts, PH_INIT);
uslen = socket_init(pf, &us); uslen = socket_init(pf, &us);
retropt_bind(opts, pf, socktype, ipproto, retropt_bind(opts, pf, socktype, ipproto,
@ -383,7 +385,7 @@ int _xioopen_udp_sendto(const char *hostname, const char *servname,
xfd->howtoend = END_SHUTDOWN; xfd->howtoend = END_SHUTDOWN;
if (applyopts_single(xfd, opts, PH_INIT) < 0) return -1; if (applyopts_single(xfd, opts, PH_INIT) < 0) return -1;
applyopts(-1, opts, PH_INIT); applyopts(xfd, -1, opts, PH_INIT);
xfd->salen = sizeof(xfd->peersa); xfd->salen = sizeof(xfd->peersa);
if ((result = if ((result =

View file

@ -148,10 +148,10 @@ static int xioopen_unix_listen(int argc, const char *argv[], struct opt *opts, i
} }
if (applyopts_single(xfd, opts, PH_INIT) < 0) return STAT_NORETRY; if (applyopts_single(xfd, opts, PH_INIT) < 0) return STAT_NORETRY;
applyopts(-1, opts, PH_INIT); applyopts(xfd, -1, opts, PH_INIT);
applyopts_named(name, opts, PH_EARLY); /* umask! */ applyopts_named(name, opts, PH_EARLY); /* umask! */
applyopts_offset(xfd, opts); applyopts_offset(xfd, opts);
applyopts(-1, opts, PH_EARLY); applyopts(xfd, -1, opts, PH_EARLY);
uslen = xiosetunix(pf, &us, name, abstract, xfd->para.socket.un.tight); uslen = xiosetunix(pf, &us, name, abstract, xfd->para.socket.un.tight);
@ -229,9 +229,9 @@ static int xioopen_unix_connect(int argc, const char *argv[], struct opt *opts,
retropt_socket_pf(opts, &pf); retropt_socket_pf(opts, &pf);
xfd->howtoend = END_SHUTDOWN; xfd->howtoend = END_SHUTDOWN;
if (applyopts_single(xfd, opts, PH_INIT) < 0) return STAT_NORETRY; if (applyopts_single(xfd, opts, PH_INIT) < 0) return STAT_NORETRY;
applyopts(-1, opts, PH_INIT); applyopts(xfd, -1, opts, PH_INIT);
applyopts_offset(xfd, opts); applyopts_offset(xfd, opts);
applyopts(-1, opts, PH_EARLY); applyopts(xfd, -1, opts, PH_EARLY);
themlen = xiosetunix(pf, &them, name, abstract, xfd->para.socket.un.tight); themlen = xiosetunix(pf, &them, name, abstract, xfd->para.socket.un.tight);
@ -361,6 +361,7 @@ static int xioopen_unix_sendto(int argc, const char *argv[], struct opt *opts, i
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 = (abstract != 1);
int result;
if (argc != 2) { if (argc != 2) {
Error2("%s: wrong number of parameters (%d instead of 1)", Error2("%s: wrong number of parameters (%d instead of 1)",
@ -394,20 +395,24 @@ 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;
applyopts(xfd, -1, opts, PH_INIT);
result =
_xioopen_dgram_sendto(needbind?(union sockaddr_union *)&us:NULL, uslen,
opts, xioflags, xfd, groups,
pf, socktype, protocol, 0);
if (result != 0) {
return result;
}
if (opt_unlink_close && needbind) { if (opt_unlink_close && needbind) {
if ((xfd->unlink_close = strdup(us.un.sun_path)) == NULL) { if ((xfd->unlink_close = strdup(us.un.sun_path)) == NULL) {
Error1("strdup(\"%s\"): out of memory", name); Error1("strdup(\"%s\"): out of memory", name);
} }
xfd->opt_unlink_close = true; xfd->opt_unlink_close = true;
} }
return STAT_OK;
if (applyopts_single(xfd, opts, PH_INIT) < 0) return -1;
applyopts(-1, opts, PH_INIT);
return
_xioopen_dgram_sendto(needbind?&us:NULL, uslen,
opts, xioflags, xfd, groups,
pf, socktype, protocol, 0);
} }
@ -438,7 +443,7 @@ int xioopen_unix_recvfrom(int argc, const char *argv[], struct opt *opts,
retropt_socket_pf(opts, &pf); retropt_socket_pf(opts, &pf);
xfd->howtoend = END_NONE; xfd->howtoend = END_NONE;
if (applyopts_single(xfd, opts, PH_INIT) < 0) return STAT_NORETRY; if (applyopts_single(xfd, opts, PH_INIT) < 0) return STAT_NORETRY;
applyopts(-1, opts, PH_INIT); applyopts(xfd, -1, opts, PH_INIT);
applyopts_named(name, opts, PH_EARLY); /* umask! */ applyopts_named(name, opts, PH_EARLY); /* umask! */
applyopts_offset(xfd, opts); applyopts_offset(xfd, opts);
@ -447,7 +452,7 @@ int xioopen_unix_recvfrom(int argc, const char *argv[], struct opt *opts,
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(-1, opts, PH_EARLY); applyopts(xfd, -1, opts, PH_EARLY);
uslen = xiosetunix(pf, &us, name, abstract, xfd->para.socket.un.tight); uslen = xiosetunix(pf, &us, name, abstract, xfd->para.socket.un.tight);
@ -519,7 +524,7 @@ int xioopen_unix_recv(int argc, const char *argv[], struct opt *opts,
retropt_socket_pf(opts, &pf); retropt_socket_pf(opts, &pf);
xfd->howtoend = END_SHUTDOWN; xfd->howtoend = END_SHUTDOWN;
if (applyopts_single(xfd, opts, PH_INIT) < 0) return STAT_NORETRY; if (applyopts_single(xfd, opts, PH_INIT) < 0) return STAT_NORETRY;
applyopts(-1, opts, PH_INIT); applyopts(xfd, -1, opts, PH_INIT);
applyopts_named(name, opts, PH_EARLY); /* umask! */ applyopts_named(name, opts, PH_EARLY); /* umask! */
applyopts_offset(xfd, opts); applyopts_offset(xfd, opts);
@ -528,7 +533,7 @@ int xioopen_unix_recv(int argc, const char *argv[], struct opt *opts,
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(-1, opts, PH_EARLY); applyopts(xfd, -1, opts, PH_EARLY);
uslen = xiosetunix(pf, &us.un, name, abstract, xfd->para.socket.un.tight); uslen = xiosetunix(pf, &us.un, name, abstract, xfd->para.socket.un.tight);
@ -607,11 +612,11 @@ _xioopen_unix_client(xiosingle_t *xfd, int xioflags, groups_t groups,
retropt_socket_pf(opts, &pf); retropt_socket_pf(opts, &pf);
xfd->howtoend = END_SHUTDOWN; xfd->howtoend = END_SHUTDOWN;
if (applyopts_single(xfd, opts, PH_INIT) < 0) return STAT_NORETRY; if (applyopts_single(xfd, opts, PH_INIT) < 0) return STAT_NORETRY;
applyopts(-1, opts, PH_INIT); applyopts(xfd, -1, opts, PH_INIT);
applyopts_offset(xfd, opts); applyopts_offset(xfd, 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(-1, opts, PH_EARLY); applyopts(xfd, -1, opts, PH_EARLY);
themlen = xiosetunix(pf, &them.un, name, abstract, xfd->para.socket.un.tight); themlen = xiosetunix(pf, &them.un, name, abstract, xfd->para.socket.un.tight);
if (!(ABSTRACT && abstract)) { if (!(ABSTRACT && abstract)) {

View file

@ -52,8 +52,8 @@ static int vsock_init(struct opt *opts, struct single *xfd) {
if (applyopts_single(xfd, opts, PH_INIT) < 0) if (applyopts_single(xfd, opts, PH_INIT) < 0)
return STAT_NORETRY; return STAT_NORETRY;
applyopts(-1, opts, PH_INIT); applyopts(xfd, -1, opts, PH_INIT);
applyopts(-1, opts, PH_EARLY); applyopts(xfd, -1, opts, PH_EARLY);
xfd->dtype = XIODATA_STREAM; xfd->dtype = XIODATA_STREAM;

2
xio.h
View file

@ -172,7 +172,7 @@ typedef struct single {
size_t actbytes; /* so many bytes still to be read (when readbytes!=0)*/ size_t actbytes; /* so many bytes still to be read (when readbytes!=0)*/
xiolock_t lock; /* parameters of lockfile */ xiolock_t lock; /* parameters of lockfile */
bool havelock; /* we are happy owner of the above lock */ bool havelock; /* we are happy owner of the above lock */
int triggerfd; /* close this FD in child process to notify parent */ int triggerfd; /* in child process close this FD to notify parent */
bool cool_write; /* downlevel EPIPE, ECONNRESET to notice */ bool cool_write; /* downlevel EPIPE, ECONNRESET to notice */
/* until here, keep consistent with bipipe.dual ! */ /* until here, keep consistent with bipipe.dual ! */
int argc; /* number of fields in argv */ int argc; /* number of fields in argv */

View file

@ -111,6 +111,15 @@ static int xiohelp_option(FILE *of, const struct optname *on, const char *name)
return 0; return 0;
} }
const char *xiohelp_opttypename(enum e_types typnum)
{
if (typnum < 0 || typnum >= TYPE_OVERFLOW) {
Warn2("%s(): invalid type number %d", __func__, typnum);
return "<invalid>";
}
return optiontypenames[typnum];
}
int xioopenhelp(FILE *of, int xioopenhelp(FILE *of,
int level /* 0..only addresses, 1..and options */ int level /* 0..only addresses, 1..and options */
) { ) {

View file

@ -5,6 +5,8 @@
#ifndef __xiohelp_h_included #ifndef __xiohelp_h_included
#define __xiohelp_h_included 1 #define __xiohelp_h_included 1
extern const char *xiohelp_opttypename(enum e_types typnum);
extern int xioopenhelp(FILE *of, extern int xioopenhelp(FILE *of,
int level /* 0..only addresses, 1..and options */ int level /* 0..only addresses, 1..and options */
); );

631
xioopts.c
View file

@ -12,6 +12,7 @@
#include "xiomodes.h" #include "xiomodes.h"
#include "xiolockfile.h" #include "xiolockfile.h"
#include "nestlex.h" #include "nestlex.h"
#include "xiohelp.h"
bool xioopts_ignoregroups; bool xioopts_ignoregroups;
@ -151,6 +152,7 @@ bool xioopts_ignoregroups;
static int applyopt_offset(struct single *xfd, struct opt *opt); static int applyopt_offset(struct single *xfd, struct opt *opt);
static int applyopt(struct single *sfd, int fd, struct opt *opt);
/* address options - keep this array strictly alphabetically sorted for /* address options - keep this array strictly alphabetically sorted for
@ -3253,32 +3255,38 @@ int retropt_bind(struct opt *opts,
#endif /* _WITH_SOCKET */ #endif /* _WITH_SOCKET */
/* Applies to FD all options belonging to phase */ int applyopt_seek32(
/* Note: not all options can be applied this way */
int applyopt(
int fd, int fd,
struct opt *opt) struct opt *opt)
{ {
if (opt->desc == ODESC_DONE || opt->desc == ODESC_ERROR)
return 0;
if (opt->desc->func == OFUNC_SEEK32) {
if (Lseek(fd, opt->value.u_off, opt->desc->major) < 0) { if (Lseek(fd, opt->value.u_off, opt->desc->major) < 0) {
Error4("lseek(%d, "F_off", %d): %s", Error4("lseek(%d, "F_off", %d): %s",
fd, opt->value.u_off, opt->desc->major, strerror(errno)); fd, opt->value.u_off, opt->desc->major, strerror(errno));
return -1; return -1;
} }
return 0;
}
#if HAVE_LSEEK64 #if HAVE_LSEEK64
} else if (opt->desc->func == OFUNC_SEEK64) { int applyopt_seek64(
int fd,
struct opt *opt)
{
/*! this depends on off64_t atomic type */ /*! this depends on off64_t atomic type */
if (Lseek64(fd, opt->value.u_off64, opt->desc->major) < 0) { if (Lseek64(fd, opt->value.u_off64, opt->desc->major) < 0) {
Error4("lseek64(%d, "F_off64", %d): %s", Error4("lseek64(%d, "F_off64", %d): %s",
fd, opt->value.u_off64, opt->desc->major, strerror(errno)); fd, opt->value.u_off64, opt->desc->major,
strerror(errno));
return -1; return -1;
} }
return 0;
}
#endif /* HAVE_LSEEK64 */ #endif /* HAVE_LSEEK64 */
} else if (opt->desc->func == OFUNC_FCNTL) { int applyopt_fcntl(
int fd,
struct opt *opt)
{
int flag; int flag;
/* retrieve existing flag setttings */ /* retrieve existing flag setttings */
@ -3294,19 +3302,30 @@ int applyopt(
} }
if (Fcntl_l(fd, opt->desc->major, flag) < 0) { if (Fcntl_l(fd, opt->desc->major, flag) < 0) {
Error4("fcntl(%d, %d, %d): %s", Error4("fcntl(%d, %d, %d): %s",
fd, opt->desc->major, flag, strerror(errno)); fd, opt->desc->major, flag,
strerror(errno));
return -1; return -1;
} }
} }
return 0;
}
} else if (opt->desc->func == OFUNC_IOCTL) { int applyopt_ioctl(
int fd,
struct opt *opt)
{
if (Ioctl(fd, opt->desc->major, (void *)&opt->value) < 0) { if (Ioctl(fd, opt->desc->major, (void *)&opt->value) < 0) {
Error4("ioctl(%d, 0x%x, %p): %s", Error4("ioctl(%d, 0x%x, %p): %s",
fd, opt->desc->major, (void *)&opt->value, strerror(errno)); fd, opt->desc->major, (void *)&opt->value, strerror(errno));
return -1; return -1;
} }
return 0;
}
} else if (opt->desc->func == OFUNC_IOCTL_MASK_LONG) { int applyopt_ioctl_mask_long(
int fd,
struct opt *opt)
{
long val; long val;
int getreq = opt->desc->major; int getreq = opt->desc->major;
int setreq = opt->desc->minor; int setreq = opt->desc->minor;
@ -3318,14 +3337,20 @@ int applyopt(
return -1; return -1;
} }
val &= ~mask; val &= ~mask;
if (opt->value.u_bool) val |= mask; if (opt->value.u_bool)
val |= mask;
if (Ioctl(fd, setreq, (void *)&val) < 0) { if (Ioctl(fd, setreq, (void *)&val) < 0) {
Error4("ioctl(%d, 0x%x, %p): %s", Error4("ioctl(%d, 0x%x, %p): %s",
fd, opt->desc->major, (void *)&val, strerror(errno)); fd, opt->desc->major, (void *)&val, strerror(errno));
return -1; return -1;
} }
return 0;
}
} else if (opt->desc->func == OFUNC_IOCTL_GENERIC) { int applyopt_ioctl_generic(
int fd,
struct opt *opt)
{
switch (opt->desc->type) { switch (opt->desc->type) {
case TYPE_INT: case TYPE_INT:
if (Ioctl(fd, opt->value.u_int, NULL) < 0) { if (Ioctl(fd, opt->value.u_int, NULL) < 0) {
@ -3363,17 +3388,19 @@ int applyopt(
} }
break; break;
default: default:
Error1("ioctl() data type %d not implemented", Error3("%s(opt:%s) data type %d not implemented",
opt->desc->type); __func__, opt->desc->defname, opt->desc->type);
return -1; return -1;
} }
return 0;
}
#if _WITH_SOCKET int applyopt_sockopt(
} else if (opt->desc->func == OFUNC_SOCKOPT) { int fd,
if (0) { struct opt *opt)
; {
#if 0 && HAVE_STRUCT_LINGER #if 0 && HAVE_STRUCT_LINGER
} else if (opt->desc->optcode == OPT_SO_LINGER) { if (opt->desc->optcode == OPT_SO_LINGER) {
struct linger lingstru; struct linger lingstru;
lingstru.l_onoff = (opt->value.u_int>=0 ? 1 : 0); lingstru.l_onoff = (opt->value.u_int>=0 ? 1 : 0);
lingstru.l_linger = opt->value.u_int; lingstru.l_linger = opt->value.u_int;
@ -3384,8 +3411,10 @@ int applyopt(
lingstru.l_linger, sizeof(lingstru)); lingstru.l_linger, sizeof(lingstru));
return -1; return -1;
} }
}
return 0;
#endif /* HAVE_STRUCT_LINGER */ #endif /* HAVE_STRUCT_LINGER */
} else {
switch (opt->desc->type) { switch (opt->desc->type) {
case TYPE_BIN: case TYPE_BIN:
if (Setsockopt(fd, opt->desc->major, opt->desc->minor, if (Setsockopt(fd, opt->desc->major, opt->desc->minor,
@ -3521,17 +3550,24 @@ int applyopt(
#endif /* defined(WITH_IP4) */ #endif /* defined(WITH_IP4) */
default: default:
#if !NDEBUG #if !NDEBUG
Error1("applyopts(): type %d not implemented", Error3("%s(opt:\"%s\"): type %d no implemented",
opt->desc->type); __func__, opt->desc->defname, opt->desc->type);
#else #else
Warn1("applyopts(): type %d not implemented", Warn3("%s(opt:\"%s\"): type %d no implemented",
opt->desc->type); __func__, opt->desc->defname, opt->desc->type);
#endif #endif
return -1; return -1;
} }
} return 0;
}
} else if (opt->desc->func == OFUNC_SOCKOPT_APPEND) { /* Appends the provided data to the current value of this sockopt.
Used (e.g.) for IP_OPTIONS.
*/
int applyopt_sockopt_append(
int fd,
struct opt *opt)
{
switch (opt->desc->type) { switch (opt->desc->type) {
uint8_t data[256]; uint8_t data[256];
socklen_t oldlen, newlen; socklen_t oldlen, newlen;
@ -3562,7 +3598,13 @@ int applyopt(
opt->desc->defname, opt->desc->type); opt->desc->defname, opt->desc->type);
break; break;
} }
} else if (opt->desc->func == OFUNC_SOCKOPT_GENERIC) { return 0;
}
int applyopt_sockopt_generic(
int fd,
struct opt *opt)
{
switch (opt->desc->type) { switch (opt->desc->type) {
case TYPE_INT_INT_INT: case TYPE_INT_INT_INT:
if (Setsockopt(fd, opt->value.u_int, opt->value2.u_int, if (Setsockopt(fd, opt->value.u_int, opt->value2.u_int,
@ -3594,23 +3636,40 @@ int applyopt(
} }
break; break;
default: default:
Error1("setsockopt() data type %d not implemented", Error3("%s(opt:\"%s\"): INTERNAL: data type %d not implemented",
opt->desc->type); __func__, opt->desc->defname, opt->desc->type);
return -1; return -1;
} }
#endif /* _WITH_SOCKET */ return 0;
}
#if HAVE_FLOCK int applyopt_flock(
} else if (opt->desc->func == OFUNC_FLOCK) { int fd,
struct opt *opt)
{
if (Flock(fd, opt->desc->major) < 0) { if (Flock(fd, opt->desc->major) < 0) {
Error3("flock(%d, %d): %s", Error3("flock(%d, %d): %s",
fd, opt->desc->major, strerror(errno)); fd, opt->desc->major, strerror(errno));
return -1; return -1;
} }
#endif /* defined(HAVE_FLOCK) */ return 0;
}
/* Applies an option that needs handling specific to its OPT_* setting.
Does not overwrite the option instance with ODESC_DONE or ODESC_ERROR,
instead:
Returns 0 if option was just applied (caller has to ODESC_DONE);
returns -1 if a problem occurred (caller has to ODESC_ERROR);
returns 1 if the instance has to be kept, this happens when the option desc has
been overwritten to, e.g., undo the option in a later phase. */
int applyopt_spec(
struct single *sfd,
int fd,
struct opt *opt)
{
if (fd < 0 && sfd != NULL)
fd = sfd->fd;
} else if (opt->desc->func == OFUNC_SPEC ||
opt->desc->func == OFUNC_FLAG) {
switch (opt->desc->optcode) { switch (opt->desc->optcode) {
case OPT_USER: case OPT_USER:
case OPT_USER_LATE: case OPT_USER_LATE:
@ -3830,6 +3889,28 @@ int applyopt(
} }
break; break;
#if _WITH_SOCKET
#if WITH_IP4 && (defined(HAVE_STRUCT_IP_MREQ) || defined (HAVE_STRUCT_IP_MREQN))
case OPT_IP_ADD_MEMBERSHIP:
return xioapply_ip_add_membership(sfd, opt);
#endif /* WITH_IP4 && (defined(HAVE_STRUCT_IP_MREQ) || defined (HAVE_STRUCT_IP_MREQN)) */
#if WITH_IP4 && defined(HAVE_STRUCT_IP_MREQ_SOURCE) && defined(IP_ADD_SOURCE_MEMBERSHIP)
case OPT_IP_ADD_SOURCE_MEMBERSHIP:
return xioapply_ip_add_source_membership(sfd, opt);
#endif /* WITH_IP4 && defined(HAVE_STRUCT_IP_MREQ_SOURCE) && defined(IP_ADD_SOURCE_MEMBERSHIP) */
#if WITH_IP6 && defined(HAVE_STRUCT_IPV6_MREQ)
case OPT_IPV6_JOIN_GROUP:
return xioapply_ipv6_join_group(sfd, opt);
#endif /* WITH_IP6 && defined(HAVE_STRUCT_IPV6_MREQ) */
#if WITH_IP6 && defined(HAVE_STRUCT_GROUP_SOURCE_REQ)
case OPT_IPV6_JOIN_SOURCE_GROUP:
return xioapply_ip6_join_source_group(sfd, opt);
#endif /* WITH_IP6 && defined(HAVE_STRUCT_IPV6_MREQ) */
#endif /* _WITH_SOCKET */
#if _WITH_INTERFACE #if _WITH_INTERFACE
case OPT_RETRIEVE_VLAN: case OPT_RETRIEVE_VLAN:
if (!xioparms.experimental) { if (!xioparms.experimental) {
@ -3841,18 +3922,17 @@ int applyopt(
break; break;
#endif /* _WITH_INTERFACE */ #endif /* _WITH_INTERFACE */
default: Error1("INTERNAL: applyopts(): option \"%s\" not implemented", default: Error1("applyopt_spec(opt:%s): INTERNAL option not implemented",
opt->desc->defname); opt->desc->defname);
return -1; return -1;
} }
return 0;
}
#if WITH_TERMIOS int applyopts_termios_value(
} else if (opt->desc->func == OFUNC_TERMIOS_FLAG) { int fd,
if (xiotermiosflag_applyopt(fd, opt) < 0) { struct opt *opt)
return -1; {
}
} else if (opt->desc->func == OFUNC_TERMIOS_VALUE) {
if (((opt->value.u_uint << opt->desc->arg3) & opt->desc->minor) != if (((opt->value.u_uint << opt->desc->arg3) & opt->desc->minor) !=
(opt->value.u_uint << opt->desc->arg3)) { (opt->value.u_uint << opt->desc->arg3)) {
Error2("option %s: invalid value %u", Error2("option %s: invalid value %u",
@ -3863,141 +3943,79 @@ int applyopt(
(opt->value.u_uint << opt->desc->arg3) & opt->desc->minor) < 0) { (opt->value.u_uint << opt->desc->arg3) & opt->desc->minor) < 0) {
return -1; return -1;
} }
} else if (opt->desc->func == OFUNC_TERMIOS_PATTERN) {
if (xiotermios_value(fd, opt->desc->major, opt->desc->arg3, opt->desc->minor) < 0) {
return -1;
}
} else if (opt->desc->func == OFUNC_TERMIOS_CHAR) {
if (xiotermios_char(fd, opt->desc->major, opt->value.u_byte) < 0) {
return -1;
}
#ifdef HAVE_TERMIOS_ISPEED
} else if (opt->desc->func == OFUNC_TERMIOS_SPEED) {
if (xiotermios_speed(fd, opt->desc->major, opt->value.u_uint) < 0) {
return -1;
}
#endif /* HAVE_TERMIOS_ISPEED */
} else if (opt->desc->func == OFUNC_TERMIOS_SPEC) {
if (xiotermios_spec(fd, opt->desc->optcode) < 0) {
return -1;
}
#endif /* WITH_TERMIOS */
#if WITH_STREAMS
#define ENABLE_APPLYOPT
#include "xio-streams.c"
#undef ENABLE_APPLYOPT
#endif /* WITH_STREAMS */
} else {
/*Error1("applyopts(): function %d not implemented",
opt->desc->func);*/
if (opt->desc->func != OFUNC_EXT && opt->desc->func != OFUNC_SIGNAL) {
Error1("applyopts(): internal error: option \"%s\" does not apply",
opt->desc->defname);
return -1;
}
return 0;
}
opt->desc = ODESC_DONE;
return 0; return 0;
} }
/* Note: not all options can be applied this way (e.g. OFUNC_SPEC with PH_OPEN) /* Note: not all options can be applied this way (e.g. OFUNC_SPEC with PH_OPEN)
implemented are: OFUNC_FCNTL, OFUNC_SOCKOPT (probably not all types), implemented are: OFUNC_FCNTL, OFUNC_SOCKOPT (probably not all types),
OFUNC_TERMIOS_FLAG, OFUNC_TERMIOS_PATTERN, and some OFUNC_SPEC */ OFUNC_TERMIOS_FLAG, OFUNC_TERMIOS_PATTERN, and some OFUNC_SPEC */
int applyopts(int fd, struct opt *opts, enum e_phase phase) int applyopts(struct single *sfd, int fd, struct opt *opts, enum e_phase phase)
{ {
struct opt *opt; struct opt *opt;
int rc; int rc = 0;
opt = opts; opt = opts;
while (opt && opt->desc != ODESC_END) { while (opt && opt->desc != ODESC_END) {
if (opt->desc != ODESC_DONE && opt->desc != ODESC_ERROR && if (opt->desc != ODESC_DONE && opt->desc != ODESC_ERROR &&
(phase == PH_ALL || phase == opt->desc->phase)) { (phase == PH_ALL || phase == opt->desc->phase)) {
rc = applyopt(fd, opt); if (applyopt(sfd, fd, opt) < 0)
if (rc < 0) rc = -1;
opt->desc = ODESC_ERROR;
} }
++opt; ++opt;
} }
#if WITH_TERMIOS #if WITH_TERMIOS
if (phase == PH_FD || phase == PH_ALL) { if ((phase == PH_FD || phase == PH_ALL) && (fd >= 0 || sfd != NULL)) {
xiotermios_flush(fd); xiotermios_flush(fd >= 0 ? fd : sfd->fd);
} }
#endif /* WITH_TERMIOS */ #endif /* WITH_TERMIOS */
return 0; return rc;
} }
/* applies to fd all options belonging to phases */ /* applies to fd all options belonging to phases */
/* note: not all options can be applied this way (e.g. OFUNC_SPEC with PH_OPEN) /* note: not all options can be applied this way (e.g. OFUNC_SPEC with PH_OPEN)
implemented are: OFUNC_FCNTL, OFUNC_SOCKOPT (probably not all types), implemented are: OFUNC_FCNTL, OFUNC_SOCKOPT (probably not all types),
OFUNC_TERMIOS_FLAG, OFUNC_TERMIOS_PATTERN, and some OFUNC_SPEC */ OFUNC_TERMIOS_FLAG, OFUNC_TERMIOS_PATTERN, and some OFUNC_SPEC */
int applyopts2(int fd, struct opt *opts, unsigned int from, unsigned int to) { int applyopts2(
unsigned int i; struct single *sfd,
int stat; int fd,
struct opt *opts,
for (i = from; i <= to; ++i) { unsigned int from,
if ((stat = applyopts(fd, opts, i)) < 0) unsigned int to) {
return stat; unsigned int ph;
} int rc = 0;
return 0;
} for (ph = from; ph <= to; ++ph) {
rc |= applyopts(sfd, fd, opts, ph);
/* Apply and consume all options of type FLAG and group. }
Return 0 when everything went right, or -1 if an error occurred. */ return rc;
int applyopts_optgroup( }
int applyopts_optgroup(
struct single *sfd,
int fd, int fd,
struct opt *opts, struct opt *opts,
int from, /* -1: from first phase, not in order */
int to, /* -1: to last phase, not in order */
groups_t groups) groups_t groups)
{ {
struct opt *opt = opts; int i;
unsigned int i; int rc = 0;
if (opts == NULL) if (opts == NULL)
return 0; return 0;
/* Just apply all opts matching from/to phases, in their stored order */ i = 0;
if (from < 0 || to < 0) { while (opts[i].desc != ODESC_END) {
if (from < 0) if (opts[i].desc == ODESC_DONE &&
from = 0; opts[i].desc == ODESC_ERROR) {
if (to < 0) ++i;
to = UINT_MAX;
while (opt->desc != ODESC_END) {
if (opt->desc == ODESC_DONE || opt->desc == ODESC_ERROR)
continue; continue;
if ((opt->desc->group & groups) == 0)
continue;
if (opt->desc->phase < from ||
opt->desc->phase > to)
continue;
applyopt(fd, opt);
/* Dont check rc: on error is should not come here */
++opt;
} }
if (opts[i].desc->group & groups) {
rc |= applyopt(sfd, sfd->fd, &opts[i]);
} }
++i;
/* Just apply all opts from, to phase, in their phases order */
for (i = from; i <= to; ++i) {
while (opt->desc != ODESC_END) {
if (opt->desc != ODESC_DONE && opt->desc != ODESC_ERROR &&
(opt->desc->group & groups) && opt->desc->phase == i) {
applyopt(fd, opt);
/* Dont check rc: on error is should not come here */
} }
++opt; return rc;
}
}
return 0;
} }
/* apply and consume all options of type FLAG and group. /* apply and consume all options of type FLAG and group.
@ -4091,8 +4109,8 @@ static int applyopt_offset(struct single *xfd, struct opt *opt) {
*(int *)ptr = opt->desc->minor; *(int *)ptr = opt->desc->minor;
break; break;
default: default:
Error1("applyopt_offset(): type %d not implemented", Error2("applyopt_offset(opt:%s): type %s not implemented",
opt->desc->type); opt->desc->defname, xiohelp_opttypename(opt->desc->type));
return -1; return -1;
} }
opt->desc = ODESC_DONE; opt->desc = ODESC_DONE;
@ -4118,80 +4136,222 @@ int applyopts_offset(struct single *xfd, struct opt *opts) {
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 *xfd, struct opt *opts, enum e_phase phase) {
struct opt *opt; struct opt *opt;
int lockrc; int rc = 0;
if (!opts) return 0; if (!opts)
return 0;
opt = opts; while (opt->desc != ODESC_END) { opt = opts; while (opt->desc != ODESC_END) {
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)) {
/* option not handled in this function */ if (opt->desc->func < OFUNC_XIO) {
++opt; continue; rc = applyopt(NULL, xfd->fd, opt);
} else { } else {
rc = applyopt(xfd, -1, opt);
}
if (rc == 0)
opt->desc = ODESC_DONE;
else
opt->desc = ODESC_ERROR;
}
++opt;
}
return rc;
}
/* Applies to sfd or fd the given option.
Note: not all options can be applied this way.
Returns 0.
*/
static int applyopt(
struct single *sfd,
int fd,
struct opt *opt)
{
int lockrc;
int rc = 0;
if (opt->desc == ODESC_DONE || opt->desc == ODESC_ERROR)
return 0;
if (sfd != NULL && fd < 0)
fd = sfd->fd;
switch (opt->desc->func) { switch (opt->desc->func) {
case OFUNC_SPEC:
rc = applyopt_spec(sfd, fd, opt);
break;
case OFUNC_SEEK32:
rc = applyopt_seek32(fd, opt);
break;
#if HAVE_LSEEK64
case OFUNC_SEEK64:
rc = applyopt_seek64(fd, opt);
break;
#endif /* HAVE_LSEEK64 */
case OFUNC_FCNTL:
rc = applyopt_fcntl(fd, opt);
break;
case OFUNC_IOCTL:
rc = applyopt_ioctl(fd, opt);
break;
case OFUNC_IOCTL_MASK_LONG:
rc = applyopt_ioctl_mask_long(fd, opt);
break;
case OFUNC_IOCTL_GENERIC:
rc = applyopt_ioctl_generic(fd, opt);
break;
#if _WITH_SOCKET
case OFUNC_SOCKOPT:
rc = applyopt_sockopt(fd, opt);
break;
case OFUNC_SOCKOPT_APPEND:
rc = applyopt_sockopt_append(fd, opt);
break;
case OFUNC_SOCKOPT_GENERIC:
rc = applyopt_sockopt_generic(fd, opt);
break;
#endif /* _WITH_SOCKET */
#if HAVE_FLOCK
case OFUNC_FLOCK:
rc = applyopt_flock(fd, opt);
break;
#endif /* defined(HAVE_FLOCK) */
#if WITH_TERMIOS
case OFUNC_TERMIOS_FLAG:
rc = xiotermiosflag_applyopt(fd, opt);
break;
case OFUNC_TERMIOS_VALUE:
rc = applyopts_termios_value(fd, opt);
break;
case OFUNC_TERMIOS_PATTERN:
rc = xiotermios_value(fd, opt->desc->major,
opt->desc->arg3, opt->desc->minor);
break;
case OFUNC_TERMIOS_CHAR:
rc = xiotermios_char(fd, opt->desc->major, opt->value.u_byte);
break;
#ifdef HAVE_TERMIOS_ISPEED
case OFUNC_TERMIOS_SPEED:
rc = xiotermios_speed(fd, opt->desc->major, opt->value.u_uint);
break;
#endif /* HAVE_TERMIOS_ISPEED */
case OFUNC_TERMIOS_SPEC:
rc = xiotermios_spec(fd, opt->desc->optcode);
break;
#endif /* WITH_TERMIOS */
#if WITH_STREAMS
#define ENABLE_APPLYOPT
#include "xio-streams.c"
#undef ENABLE_APPLYOPT
#endif /* WITH_STREAMS */
case OFUNC_OFFSET: case OFUNC_OFFSET:
applyopt_offset(xfd, opt); rc = applyopt_offset(sfd, opt);
break; break;
case OFUNC_EXT: case OFUNC_EXT:
switch (opt->desc->optcode) { switch (opt->desc->optcode) {
#if 0 #if 0
case OPT_IGNOREEOF: case OPT_IGNOREEOF:
xfd->ignoreeof = true; sfd->ignoreeof = true;
break; return 0;
case OPT_CR: case OPT_CR:
xfd->lineterm = LINETERM_CR; sfd->lineterm = LINETERM_CR;
break; return 0;
case OPT_CRNL: case OPT_CRNL:
xfd->lineterm = LINETERM_CRNL; sfd->lineterm = LINETERM_CRNL;
break; return 0;
#endif /* 0 */ #endif /* 0 */
case OPT_READBYTES: case OPT_READBYTES:
xfd->readbytes = opt->value.u_sizet; sfd->readbytes = opt->value.u_sizet;
xfd->actbytes = xfd->readbytes; sfd->actbytes = sfd->readbytes;
break; break;
case OPT_LOCKFILE: case OPT_LOCKFILE:
if (xfd->lock.lockfile) { if (sfd->lock.lockfile) {
Error("only one use of options lockfile and waitlock allowed"); Error("only one use of options lockfile and waitlock allowed");
} }
xfd->lock.lockfile = strdup(opt->value.u_string); sfd->lock.lockfile = strdup(opt->value.u_string);
xfd->lock.intervall.tv_sec = 1; sfd->lock.intervall.tv_sec = 1;
xfd->lock.intervall.tv_nsec = 0; sfd->lock.intervall.tv_nsec = 0;
if ((lockrc = xiolock(&xfd->lock)) < 0) { if ((lockrc = xiolock(&sfd->lock)) < 0) {
/* error message already printed */ /* error message already printed */
return -1; rc = -1;
} }
if (lockrc) { if (lockrc) {
Error1("could not obtain lock \"%s\"", xfd->lock.lockfile); Error1("could not obtain lock \"%s\"", sfd->lock.lockfile);
rc = -1;
} else { } else {
xfd->havelock = true; sfd->havelock = true;
} }
break; break;
case OPT_WAITLOCK: case OPT_WAITLOCK:
if (xfd->lock.lockfile) { if (sfd->lock.lockfile) {
Error("only one use of options lockfile and waitlock allowed"); Error("only one use of options lockfile and waitlock allowed");
} }
xfd->lock.lockfile = strdup(opt->value.u_string); sfd->lock.lockfile = strdup(opt->value.u_string);
xfd->lock.waitlock = true; sfd->lock.waitlock = true;
xfd->lock.intervall.tv_sec = 1; sfd->lock.intervall.tv_sec = 1;
xfd->lock.intervall.tv_nsec = 0; sfd->lock.intervall.tv_nsec = 0;
/*! this should be integrated into central select()/poll() loop */ /*! this should be integrated into central select()/poll() loop */
if (xiolock(&xfd->lock) < 0) { rc = xiolock(&sfd->lock);
return -1; if (rc < 0)
} break;
xfd->havelock = true; sfd->havelock = true;
break; break;
default: default:
/* just store the value in the correct component of struct single */ /* just store the value in the correct component of struct single */
if (opt->desc->type == TYPE_CONST) { if (opt->desc->type == TYPE_CONST) {
/* only for integral types compatible to int */ /* only for integral types compatible to int */
*(int *)(&((char *)xfd)[opt->desc->major]) = opt->desc->arg3; *(int *)(&((char *)sfd)[opt->desc->major]) = opt->desc->arg3;
} else { } else {
memcpy(&((char *)xfd)[opt->desc->major], &opt->value, opt->desc->minor); memcpy(&((char *)sfd)[opt->desc->major], &opt->value, opt->desc->minor);
}
}
break;
case OFUNC_OFFSET_MASK:
/* Currently not used */
/* Data target is some integer with independent bits in sfd;
set or unset the specified bits. */
{
void *mask = (char *)sfd + opt->desc->major;
size_t masksize = opt->desc->minor;
unsigned long bit = opt->desc->arg3;
switch (masksize) {
case sizeof(int):
if (opt->value.u_bool) {
(*(int *)mask) |= bit;
} else {
(*(int *)mask) &= ~bit;
}
break;
default:
Info1("sizeof(int)="F_Zu, sizeof(int));
Error2("applyopts_single(opt:%s): INTERNAL: OFUNC_OFFSET_MASK size "F_Zu" not implemented",
opt->desc->defname, masksize);
} }
} }
break; break;
@ -4202,7 +4362,7 @@ int applyopts_single(struct single *xfd, struct opt *opts, enum e_phase phase) {
element holds the bit mask to be set, the second one those to be element holds the bit mask to be set, the second one those to be
cleared. Each related option sets or unsets a specific bit. */ cleared. Each related option sets or unsets a specific bit. */
{ {
void *masks = (char *)xfd + opt->desc->major; void *masks = (char *)sfd + opt->desc->major;
size_t masksize = opt->desc->minor; size_t masksize = opt->desc->minor;
unsigned long bit = opt->desc->arg3; unsigned long bit = opt->desc->arg3;
switch (masksize>>1) { switch (masksize>>1) {
@ -4228,104 +4388,53 @@ int applyopts_single(struct single *xfd, struct opt *opts, enum e_phase phase) {
} }
break; break;
default: default:
Error1("applyopts_single: masksize "F_Zu" not implemented", Info1("sizeof(uint32_t)="F_Zu, sizeof(uint32_t));
masksize); Error2("applyopts_single(opt:%s): INTERNAL: OFUNC_OFFSET_MASKS size "F_Zu" not implemented",
opt->desc->defname, masksize);
rc = -1;
break;
} }
} }
break; break;
#if _WITH_SOCKET case OFUNC_SIGNAL:
case OFUNC_SOCKOPT: rc = xio_opt_signal(sfd->para.exec.pid, opt->desc->major);
switch (opt->desc->optcode) {
#if WITH_IP4 && (defined(HAVE_STRUCT_IP_MREQ) || defined (HAVE_STRUCT_IP_MREQN))
case OPT_IP_ADD_MEMBERSHIP:
if (xioapply_ip_add_membership(xfd, opt) < 0) {
continue;
}
break; break;
#endif /* WITH_IP4 && (defined(HAVE_STRUCT_IP_MREQ) || defined (HAVE_STRUCT_IP_MREQN)) */
#if WITH_IP4 && defined(HAVE_STRUCT_IP_MREQ_SOURCE) && defined(IP_ADD_SOURCE_MEMBERSHIP)
case OPT_IP_ADD_SOURCE_MEMBERSHIP:
if (xioapply_ip_add_source_membership(xfd, opt) < 0) {
continue;
}
break;
#endif /* WITH_IP4 && defined(HAVE_STRUCT_IP_MREQ_SOURCE) && defined(IP_ADD_SOURCE_MEMBERSHIP) */
#if WITH_IP6 && defined(HAVE_STRUCT_IPV6_MREQ)
case OPT_IPV6_JOIN_GROUP:
if (xioapply_ipv6_join_group(xfd, opt) < 0) {
continue;
}
break;
#endif /* WITH_IP6 && defined(HAVE_STRUCT_IPV6_MREQ) */
#if WITH_IP6 && defined(HAVE_STRUCT_GROUP_SOURCE_REQ)
case OPT_IPV6_JOIN_SOURCE_GROUP:
if (xioapply_ip6_join_source_group(xfd, opt) < 0) {
continue;
}
break;
#endif /* WITH_IP6 && defined(HAVE_STRUCT_IPV6_MREQ) */
default:
/* ignore here */
++opt; continue;
}
break;
#endif /* _WITH_SOCKET */
default: default:
++opt; Error2("applyopt(opt:%s): INTERNAL: ofunc %d not implemented",
continue; opt->desc->defname, opt->desc->func);
rc = -1;
break;
} }
if (rc == 0)
opt->desc = ODESC_DONE; opt->desc = ODESC_DONE;
++opt; else if (rc < 0)
} opt->desc = ODESC_ERROR;
} /* rc > 0: no action */
return 0; return 0;
} }
/* xfd->para.exec.pid must be set */
int applyopts_signal(struct single *xfd, struct opt *opts) {
struct opt *opt;
if (!opts) return 0;
opt = opts; while (opt->desc != ODESC_END) {
if (opt->desc == ODESC_DONE || opt->desc == ODESC_ERROR ||
opt->desc->func != OFUNC_SIGNAL) {
++opt; continue;
}
if (xio_opt_signal(xfd->para.exec.pid, opt->desc->major) < 0) {
opt->desc = ODESC_ERROR; continue;
}
opt->desc = ODESC_DONE;
++opt;
}
return 0;
}
/* apply remaining options to file descriptor, and tell us if something is /* apply remaining options to file descriptor, and tell us if something is
still unused */ still unused */
int _xio_openlate(struct single *fd, struct opt *opts) { int _xio_openlate(struct single *sfd, struct opt *opts) {
int numleft; int numleft;
int result; int result;
_xioopen_setdelayeduser(); _xioopen_setdelayeduser();
if ((result = applyopts(fd->fd, opts, PH_LATE)) < 0) { if ((result = applyopts(sfd, sfd->fd, opts, PH_LATE)) < 0) {
return result; return result;
} }
if ((result = applyopts_single(fd, opts, PH_LATE)) < 0) { if ((result = applyopts_single(sfd, opts, PH_LATE)) < 0) {
return result; return result;
} }
if ((result = applyopts(fd->fd, opts, PH_LATE2)) < 0) { if ((result = applyopts(sfd, sfd->fd, opts, PH_LATE2)) < 0) {
return result; return result;
} }
if ((result = applyopts(fd->fd, opts, PH_PASTEXEC)) < 0) { if ((result = applyopts(sfd, sfd->fd, opts, PH_PASTEXEC)) < 0) {
return result; return result;
} }
@ -4364,3 +4473,21 @@ int dropopts2(struct opt *opts, unsigned int from, unsigned int to) {
return 0; return 0;
} }
int dumpopts(struct opt *opts)
{
int i;
if (opts == NULL) {
Warn("dumpopts: NULL");
return 0;
}
i = 0;
while (opts[i].desc != ODESC_END) {
if (opts[i].desc != ODESC_DONE &&
opts[i].desc != ODESC_ERROR) {
Warn2("dumpopts(): %d %s", i, opts[i].desc->defname);
}
++i;
}
return 0;
}

View file

@ -82,10 +82,12 @@ enum e_types {
#endif #endif
TYPE_GENERIC, /* type is determined from (text) data provided (dalan syntax) */ TYPE_GENERIC, /* type is determined from (text) data provided (dalan syntax) */
TYPE_OVERFLOW /* marker: beyond last type */
} ; } ;
enum e_func { enum e_func {
OFUNC_NONE, /* no function - should not occur */ OFUNC_NONE, /* no function - should not occur */
/* Options to be applied to FD directly */
OFUNC_FLAG, /* no function, but bitposition, only with bool; arg1 is mask */ OFUNC_FLAG, /* no function, but bitposition, only with bool; arg1 is mask */
OFUNC_FLAG_PATTERN, /* no function, but bitpattern: arg1 is pattern, arg2 is mask */ OFUNC_FLAG_PATTERN, /* no function, but bitpattern: arg1 is pattern, arg2 is mask */
OFUNC_SEEK32, /* lseek(): arg1 is whence (SEEK_SET etc.) */ OFUNC_SEEK32, /* lseek(): arg1 is whence (SEEK_SET etc.) */
@ -100,12 +102,6 @@ enum e_func {
OFUNC_SOCKOPT_APPEND,/* getsockopt(), append data, setsockopt() */ OFUNC_SOCKOPT_APPEND,/* getsockopt(), append data, setsockopt() */
OFUNC_SOCKOPT_GENERIC,/* generic setsockopt() (level, optname on cmdline) */ OFUNC_SOCKOPT_GENERIC,/* generic setsockopt() (level, optname on cmdline) */
OFUNC_FLOCK, /* flock() */ OFUNC_FLOCK, /* flock() */
OFUNC_TERMIO, /* termio() ? */
OFUNC_SPEC, /* special, i.e. no generalizable function call */
OFUNC_OFFSET, /* put a value into xiofile struct; major is offset */
OFUNC_OFFSET_MASKS, /* set pos or neg bit pattern in array[2] */
/*OFUNC_APPL,*/ /* special, i.e. application must know which f. */
OFUNC_EXT, /* with extended file descriptors only */
OFUNC_TERMIOS_FLAG, /* a flag in struct termios: major..tcflag, minor..bit OFUNC_TERMIOS_FLAG, /* a flag in struct termios: major..tcflag, minor..bit
*/ */
OFUNC_TERMIOS_PATTERN, /* a multibit: major..tcflag, minor..pattern, OFUNC_TERMIOS_PATTERN, /* a multibit: major..tcflag, minor..pattern,
@ -114,14 +110,23 @@ enum e_func {
OFUNC_TERMIOS_CHAR, /* a termios functional character: major..c_cc index */ OFUNC_TERMIOS_CHAR, /* a termios functional character: major..c_cc index */
OFUNC_TERMIOS_SPEED, /* termios c_ispeed etc on FreeBSD */ OFUNC_TERMIOS_SPEED, /* termios c_ispeed etc on FreeBSD */
OFUNC_TERMIOS_SPEC, /* termios combined modes */ OFUNC_TERMIOS_SPEC, /* termios combined modes */
OFUNC_EXT, /* with extended file descriptors only */
# define OFUNC_XIO OFUNC_EXT
OFUNC_SPEC, /* special, i.e. no generalizable function call */
OFUNC_OFFSET, /* put a value into xiofile struct; major is offset */
OFUNC_OFFSET_MASK, /* set/unset bit pattern in variable */
OFUNC_OFFSET_MASKS, /* set pos or neg bit pattern in array[2] */
/*OFUNC_APPL,*/ /* special, i.e. application must know which f. */
OFUNC_SIGNAL, /* a signal that should be passed to child process */ OFUNC_SIGNAL, /* a signal that should be passed to child process */
OFUNC_RESOLVER, /* a bit position used on _res.options */ OFUNC_RESOLVER, /* a bit position used on _res.options */
OFUNC_IFFLAG, /* interface flag: locical-or a 1bit mask */ OFUNC_IFFLAG, /* interface flag: logical-or a 1bit mask */
OFUNC_SET_NAMESPACE, /* set/change Linux namespace */
OFUNC_RESET_NAMESPACE, /* set Linux namespace back to default */
# define ENABLE_OFUNC # define ENABLE_OFUNC
# include "xio-streams.h" /* push a POSIX STREAMS module */ # include "xio-streams.h" /* push a POSIX STREAMS module */
# undef ENABLE_OFUNC # undef ENABLE_OFUNC
OFUNC_SET_NAMESPACE, /* set/change Linux namespace */ OFUNC_OVERFLOW /* marker: beyond last func */
OFUNC_RESET_NAMESPACE, /* set Linux namespace back to default */
} ; } ;
/* for simpler handling of option-to-connection-type relations we define /* for simpler handling of option-to-connection-type relations we define
@ -980,12 +985,13 @@ extern int retropt_flag(struct opt *opts, int optcode, flags_t *result);
extern int retropt_string(struct opt *opts, int optcode, char **result); extern int retropt_string(struct opt *opts, int optcode, char **result);
extern int retropt_timespec(struct opt *opts, int optcode, struct timespec *result); extern int retropt_timespec(struct opt *opts, int optcode, struct timespec *result);
extern int retropt_bind(struct opt *opts, int af, int socktype, int ipproto, struct sockaddr *sa, socklen_t *salen, int feats, const int ai_flags[2]); extern int retropt_bind(struct opt *opts, int af, int socktype, int ipproto, struct sockaddr *sa, socklen_t *salen, int feats, const int ai_flags[2]);
extern int applyopts(int fd, struct opt *opts, enum e_phase phase); extern int applyopt_fd(int fd, struct opt *opt);
extern int applyopts2(int fd, struct opt *opts, unsigned int from, unsigned int to); extern int applyopt_single(struct single *sfd, struct opt *opt);
extern int applyopts_optgroup(int fd, struct opt *opts, int from, int to, groups_t groups); extern int applyopts(struct single *sfd, int fd, struct opt *opts, enum e_phase phase);
extern int applyopts2(struct single *sfd, int fd, struct opt *opts, unsigned int from, unsigned int to);
extern int applyopts_optgroup(struct single *sfd, int fd, struct opt *opts, groups_t groups);
extern int applyopts_flags(struct opt *opts, groups_t group, flags_t *result); extern int applyopts_flags(struct opt *opts, groups_t group, flags_t *result);
extern int applyopts_cloexec(int fd, struct opt *opts); extern int applyopts_cloexec(int fd, struct opt *opts);
extern int applyopts_early(const char *path, struct opt *opts);
extern int applyopts_fchown(int fd, struct opt *opts); extern int applyopts_fchown(int fd, struct opt *opts);
extern int applyopts_single(struct single *fd, struct opt *opts, enum e_phase phase); extern int applyopts_single(struct single *fd, struct opt *opts, enum e_phase phase);
extern int applyopts_offset(struct single *xfd, struct opt *opts); extern int applyopts_offset(struct single *xfd, struct opt *opts);
@ -1005,6 +1011,7 @@ extern groups_t groupbits(int fd);
extern groups_t _groupbits(mode_t mode); extern groups_t _groupbits(mode_t mode);
extern int dropopts(struct opt *opts, unsigned int phase); extern int dropopts(struct opt *opts, unsigned int phase);
extern int dropopts2(struct opt *opts, unsigned int from, unsigned int to); extern int dropopts2(struct opt *opts, unsigned int from, unsigned int to);
extern int dumpopts(struct opt *opts);
#if HAVE_BASIC_UID_T==1 #if HAVE_BASIC_UID_T==1
# define retropt_uid(o,c,r) retropt_short(o,c,r) # define retropt_uid(o,c,r) retropt_short(o,c,r)

View file

@ -62,14 +62,19 @@ void socatsignalpass(int sig) {
return; return;
} }
{ /*debug*/
int n = 0;
for (i=0; i<sigdesc->sig_use; ++i) { for (i=0; i<sigdesc->sig_use; ++i) {
if (sigdesc->sig_pids[i]) { if (sigdesc->sig_pids[i]) {
++n;
if (Kill(sigdesc->sig_pids[i], sig) < 0) { if (Kill(sigdesc->sig_pids[i], sig) < 0) {
Warn2("kill("F_pid", %d): %m", Warn2("kill("F_pid", %d): %m",
sigdesc->sig_pids[i], sig); sigdesc->sig_pids[i], sig);
} }
} }
} }
Info1("socatsignalpass(): n=%d", n);
}
#if !HAVE_SIGACTION #if !HAVE_SIGACTION
Signal(sig, socatsignalpass); Signal(sig, socatsignalpass);
#endif /* !HAVE_SIGACTION */ #endif /* !HAVE_SIGACTION */