mirror of
https://repo.or.cz/socat.git
synced 2024-12-22 15:32:35 +00:00
reworked so-type, so-prototype
This commit is contained in:
parent
b6c2d46008
commit
376b9d50c3
22 changed files with 293 additions and 253 deletions
5
CHANGES
5
CHANGES
|
@ -1,4 +1,9 @@
|
|||
|
||||
new features:
|
||||
so-type now only affect the socket() and socketpair() calls, not the
|
||||
name resolution. so-type and so-prototype can be applied to all socket
|
||||
based addresses.
|
||||
|
||||
corrections:
|
||||
some raw IP and UNIX datagram modes failed on BSD systems
|
||||
|
||||
|
|
2
VERSION
2
VERSION
|
@ -1 +1 @@
|
|||
"1.6.0.1+ip4bind+recvfromfork+x64+execstderr+execspaces+cosmetics+poll+udplistencont+ignoreeofunblock"
|
||||
"1.6.0.1+ip4bind+recvfromfork+x64+execstderr+execspaces+cosmetics+poll+udplistencont+ignoreeofunblock+protocol"
|
||||
|
|
23
doc/socat.yo
23
doc/socat.yo
|
@ -1585,11 +1585,23 @@ label(OPTION_SNDLOWAT)dit(bf(tt(sndlowat=<bytes>)))
|
|||
layer will send the data to <bytes> [link(int)(TYPE_INT)].
|
||||
label(OPTION_SNDTIMEO)dit(bf(tt(sndtimeo=<seconds>)))
|
||||
Sets the send timeout to seconds [link(timeval)(TYPE_TIMEVAL)].
|
||||
label(OPTION_TYPE)dit(bf(tt(type=<type>)))
|
||||
Sets the type of the socket, usually as argument to the code(socket()) or
|
||||
code(socketpair()) call, to <type> [link(int)(TYPE_INT)].
|
||||
label(OPTION_PROTOCOL_FAMILY)dit(bf(tt(pf=<string>)))
|
||||
Forces the use of the specified IP version or protocol. <string> can be
|
||||
something like "ip4" or "ip6". The resulting value is
|
||||
used as first argument to the code(socket()) or code(socketpair()) calls.
|
||||
This option affects address resolution and the required syntax of bind and
|
||||
range options.
|
||||
label(OPTION_SO_TYPE)dit(bf(tt(type=<type>)))
|
||||
Sets the type of the socket, specified as second argument to the
|
||||
code(socket()) or code(socketpair()) calls, to <type>
|
||||
[link(int)(TYPE_INT)]. Address resolution is not affected by this option.
|
||||
Under Linux, 1 means stream oriented socket, 2 means datagram socket, and 3
|
||||
means raw socket.
|
||||
label(OPTION_SO_PROTOTYPE)dit(bf(tt(prototype)))
|
||||
Sets the protocol of the socket, specified as third argument to the
|
||||
code(socket()) or code(socketpair()) calls, to <prototype>
|
||||
[link(int)(TYPE_INT)]. Address resolution is not affected by this option.
|
||||
6 means TCP, 17 means UDP.
|
||||
COMMENT(label(OPTION_USELOOPBACK)dit(bf(tt(useloopback)))
|
||||
Sets the code(SO_USELOOPBACK) socket option.)
|
||||
COMMENT(label(OPTION_ACCEPTCONN)dit(bf(tt(acceptconn)))
|
||||
|
@ -1618,8 +1630,6 @@ COMMENT(label(OPTION_PASSCRED)dit(bf(tt(passcred)))
|
|||
Set the code(SO_PASSCRED) socket option.)
|
||||
COMMENT(label(OPTION_PEERCRED)dit(bf(tt(peercred)))
|
||||
This is a read-only socket option.)
|
||||
COMMENT(label(OPTION_PROTOTYPE)dit(bf(tt(prototype)))
|
||||
Tries to set the code(SO_PROTOTYPE) socket option.)
|
||||
COMMENT(label(OPTION_REUSEPORT)dit(bf(tt(reuseport)))
|
||||
Set the code(SO_REUSEPORT) socket option.)
|
||||
COMMENT(label(OPTION_SECUTIYAUTHENTICATION)dit(bf(tt(securityauthentication)))
|
||||
|
@ -1632,9 +1642,6 @@ COMMENT(label(OPTION_SIOCSPGRP)dit(bf(tt(siocspgrp=<pid_t>)))
|
|||
Set the SIOCSPGRP with code(ioclt()) to enable SIGIO.)
|
||||
COMMENT(label(OPTION_USEIFBUFS)dit(bf(tt(useifbufs)))
|
||||
Set the code(SO_USE_IFBUFS) socket option.)
|
||||
label(OPTION_PROTOCOL_FAMILY)dit(bf(tt(pf=<string>)))
|
||||
Forces the use of the specified IP version. <string> can be
|
||||
something like "ip4" or "ip6".
|
||||
enddit()
|
||||
|
||||
startdit()enddit()nl()
|
||||
|
|
3
filan.c
3
filan.c
|
@ -479,6 +479,9 @@ int sockan(int fd, FILE *outfile) {
|
|||
{SO_REUSEADDR, "REUSEADDR"},
|
||||
{SO_TYPE, "TYPE"},
|
||||
{SO_ERROR, "ERROR"},
|
||||
#ifdef SO_PROTOTYPE
|
||||
{SO_PROTOTYPE, "PROTOTYPE"},
|
||||
#endif
|
||||
{SO_DONTROUTE, "DONTROUTE"},
|
||||
{SO_BROADCAST, "BROADCAST"},
|
||||
{SO_SNDBUF, "SNDBUF"},
|
||||
|
|
4
test.sh
4
test.sh
|
@ -2362,7 +2362,7 @@ N=$((N+1))
|
|||
#}
|
||||
|
||||
|
||||
NAME=UNIXSOCKET
|
||||
NAME=UNIXSTREAM
|
||||
case "$TESTS" in
|
||||
*%functions%*|*%unix%*|*%$NAME%*)
|
||||
TEST="$NAME: echo via connection to UNIX domain socket"
|
||||
|
@ -2372,7 +2372,7 @@ ts="$td/test$N.socket"
|
|||
tdiff="$td/test$N.diff"
|
||||
da="test$N $(date) $RANDOM"
|
||||
CMD1="$SOCAT $opts UNIX-LISTEN:$ts PIPE"
|
||||
CMD2="$SOCAT $opts -!!- UNIX:$ts"
|
||||
CMD2="$SOCAT $opts -!!- UNIX-CONNECT:$ts"
|
||||
printf "test $F_n $TEST... " $N
|
||||
$CMD1 </dev/null >$tf 2>"${te}1" &
|
||||
bg=$! # background process id
|
||||
|
|
113
xio-gopen.c
113
xio-gopen.c
|
@ -45,113 +45,17 @@ static int xioopen_gopen(int argc, const char *argv[], struct opt *opts, int xio
|
|||
/* note: when S_ISSOCK was undefined, it always gives 0 */
|
||||
if (exists && S_ISSOCK(st_mode)) {
|
||||
#if WITH_UNIX
|
||||
int socktype = SOCK_STREAM;
|
||||
int optsotype = -1;
|
||||
struct sockaddr_un sa, us;
|
||||
socklen_t salen, uslen = sizeof(us);
|
||||
bool needbind = false;
|
||||
union sockaddr_union us;
|
||||
socklen_t uslen;
|
||||
char infobuff[256];
|
||||
struct opt *opts2;
|
||||
|
||||
socket_un_init(&sa);
|
||||
socket_un_init(&us);
|
||||
|
||||
Info1("\"%s\" is a socket, connecting to it", filename);
|
||||
if (retropt_int(opts, OPT_SO_TYPE, &optsotype) == 0) {
|
||||
socktype = optsotype;
|
||||
|
||||
result =
|
||||
_xioopen_unix_client(&fd->stream, xioflags, groups, 0, opts, filename);
|
||||
if (result < 0) {
|
||||
return result;
|
||||
}
|
||||
|
||||
if (retropt_bind(opts, AF_UNIX, socktype, 0, (struct sockaddr *)&us, &uslen, 0, 0, 0) != STAT_NOACTION) {
|
||||
needbind = true;
|
||||
}
|
||||
|
||||
retropt_bool(opts, OPT_UNLINK_CLOSE, &opt_unlink_close);
|
||||
if (opt_unlink_close) {
|
||||
if ((fd->stream.unlink_close = strdup(filename)) == NULL) {
|
||||
Error1("strdup(\"%s\"): out of memory", filename);
|
||||
}
|
||||
fd->stream.opt_unlink_close = true;
|
||||
}
|
||||
|
||||
/* save options, because we might have to start again with Socket() */
|
||||
opts2 = copyopts(opts, GROUP_ALL);
|
||||
|
||||
if ((fd->stream.fd = Socket(PF_UNIX, socktype, 0)) < 0) {
|
||||
Error2("socket(PF_UNIX, %d, 0): %s", socktype, strerror(errno));
|
||||
return STAT_RETRYLATER;
|
||||
}
|
||||
/*0 Info2("socket(PF_UNIX, %d, 0) -> %d", socktype, fd->stream.fd);*/
|
||||
applyopts(fd->stream.fd, opts, PH_PASTSOCKET);
|
||||
applyopts(fd->stream.fd, opts, PH_FD);
|
||||
|
||||
applyopts_cloexec(fd->stream.fd, opts);
|
||||
|
||||
sa.sun_family = AF_UNIX;
|
||||
salen = xiosetunix(&sa, filename, false, false);
|
||||
|
||||
#if 0
|
||||
applyopts(fd->stream.fd, opts, PH_PREBIND);
|
||||
applyopts(fd->stream.fd, opts, PH_BIND);
|
||||
if (us) {
|
||||
if (Bind(fd->stream.fd, us, uslen) < 0) {
|
||||
Error4("bind(%d, {%s}, "F_Zd"): %s",
|
||||
fd->fd, sockaddr_info(us, infobuff, sizeof(infobuff)),
|
||||
uslen, strerror(errno));
|
||||
if (fd->forever || --fd->retry) {
|
||||
Nanosleep(&fd->intervall, NULL);
|
||||
continue;
|
||||
} else
|
||||
return STAT_RETRYLATER;
|
||||
}
|
||||
}
|
||||
applyopts(fd->stream.fd, opts, PH_PASTBIND);
|
||||
#endif /* 0 */
|
||||
|
||||
applyopts(fd->stream.fd, opts, PH_CONNECT);
|
||||
if ((result = Connect(fd->stream.fd, (struct sockaddr *)&sa, salen)) < 0) {
|
||||
if (errno == EINPROGRESS) {
|
||||
Warn4("connect(%d, %s, "F_Zd"): %s",
|
||||
fd->stream.fd, sockaddr_unix_info(&sa, salen, infobuff, sizeof(infobuff)),
|
||||
sizeof(sa), strerror(errno));
|
||||
} else if (errno == EPROTOTYPE && optsotype != SOCK_STREAM) {
|
||||
Warn4("connect(%d, %s, "F_Zd"): %s",
|
||||
fd->stream.fd, sockaddr_unix_info(&sa, salen, infobuff, sizeof(infobuff)),
|
||||
sizeof(sa), strerror(errno));
|
||||
Info("assuming datagram socket");
|
||||
Close(fd->stream.fd);
|
||||
|
||||
opts = opts2;
|
||||
if ((fd->stream.fd = Socket(PF_UNIX, SOCK_DGRAM, 0)) < 0) {
|
||||
Error1("socket(PF_UNIX, SOCK_DGRAM, 0): %s", strerror(errno));
|
||||
return STAT_RETRYLATER;
|
||||
}
|
||||
/*0 Info1("socket(PF_UNIX, SOCK_DGRAM, 0) -> %d", fd->stream.fd);*/
|
||||
|
||||
applyopts(fd->stream.fd, opts, PH_PASTSOCKET);
|
||||
applyopts(fd->stream.fd, opts, PH_FD);
|
||||
|
||||
applyopts_cloexec(fd->stream.fd, opts);
|
||||
|
||||
sa.sun_family = AF_UNIX;
|
||||
strncpy(sa.sun_path, filename, sizeof(sa.sun_path));
|
||||
|
||||
fd->stream.dtype = XIODATA_RECVFROM;
|
||||
fd->stream.salen = sizeof(sa);
|
||||
memcpy(&fd->stream.peersa.soa, &sa, fd->stream.salen);
|
||||
} else {
|
||||
Error4("connect(%d, %s, "F_Zd"): %s",
|
||||
fd->stream.fd, sockaddr_unix_info(&sa, fd->stream.salen, infobuff, sizeof(infobuff)),
|
||||
sizeof(sa), strerror(errno));
|
||||
return STAT_RETRYLATER;
|
||||
}
|
||||
}
|
||||
if (fd->stream.howtoend == END_UNSPEC) {
|
||||
fd->stream.howtoend = END_SHUTDOWN;
|
||||
}
|
||||
|
||||
applyopts_fchown(fd->stream.fd, opts);
|
||||
applyopts(fd->stream.fd, opts, PH_CONNECTED);
|
||||
applyopts(fd->stream.fd, opts, PH_LATE);
|
||||
applyopts_named(filename, opts, PH_PASTOPEN); /* unlink-late */
|
||||
|
||||
if (Getsockname(fd->stream.fd, (struct sockaddr *)&us, &uslen) < 0) {
|
||||
|
@ -159,7 +63,8 @@ static int xioopen_gopen(int argc, const char *argv[], struct opt *opts, int xio
|
|||
fd->stream.fd, &us, uslen, strerror(errno));
|
||||
} else {
|
||||
Notice1("successfully connected via %s",
|
||||
sockaddr_unix_info(&us, uslen, infobuff, sizeof(infobuff)));
|
||||
sockaddr_unix_info(&us.un, uslen,
|
||||
infobuff, sizeof(infobuff)));
|
||||
}
|
||||
#else
|
||||
Error("\"%s\" is a socket, but UNIX socket support is not compiled in");
|
||||
|
|
12
xio-ip.c
12
xio-ip.c
|
@ -205,6 +205,18 @@ int xiogetaddrinfo(const char *node, const char *service,
|
|||
if (node != NULL || service != NULL) {
|
||||
struct addrinfo *record;
|
||||
|
||||
if (socktype != SOCK_STREAM && socktype != SOCK_DGRAM) {
|
||||
/* actual socket type value is not supported - fallback to a good one */
|
||||
socktype = SOCK_DGRAM;
|
||||
}
|
||||
if (protocol != IPPROTO_TCP && protocol != IPPROTO_UDP) {
|
||||
/* actual protocol value is not supported - fallback to a good one */
|
||||
if (socktype == SOCK_DGRAM) {
|
||||
protocol = IPPROTO_UDP;
|
||||
} else {
|
||||
protocol = IPPROTO_TCP;
|
||||
}
|
||||
}
|
||||
hints.ai_flags |= AI_PASSIVE;
|
||||
hints.ai_family = family;
|
||||
hints.ai_socktype = socktype;
|
||||
|
|
29
xio-ipapp.c
29
xio-ipapp.c
|
@ -52,8 +52,8 @@ int xioopen_ipapp_connect(int argc, const char *argv[], struct opt *opts,
|
|||
if (_xioopen_ipapp_prepare(opts, &opts0, hostname, portname, &pf, ipproto,
|
||||
xfd->para.socket.ip.res_opts[1],
|
||||
xfd->para.socket.ip.res_opts[0],
|
||||
them, &themlen, us, &uslen, &needbind, &lowport,
|
||||
&socktype) != STAT_OK) {
|
||||
them, &themlen, us, &uslen, &needbind, &lowport,
|
||||
socktype) != STAT_OK) {
|
||||
return STAT_NORETRY;
|
||||
}
|
||||
|
||||
|
@ -147,7 +147,11 @@ int xioopen_ipapp_connect(int argc, const char *argv[], struct opt *opts,
|
|||
}
|
||||
|
||||
|
||||
/* returns STAT_OK on success or some other value on failure */
|
||||
/* returns STAT_OK on success or some other value on failure
|
||||
applies and consumes the following options:
|
||||
PH_EARLY
|
||||
OPT_PROTOCOL_FAMILY, OPT_BIND, OPT_SOURCEPORT, OPT_LOWPORT
|
||||
*/
|
||||
int
|
||||
_xioopen_ipapp_prepare(struct opt *opts, struct opt **opts0,
|
||||
const char *hostname,
|
||||
|
@ -158,7 +162,7 @@ int
|
|||
union sockaddr_union *them, socklen_t *themlen,
|
||||
union sockaddr_union *us, socklen_t *uslen,
|
||||
bool *needbind, bool *lowport,
|
||||
int *socktype) {
|
||||
int socktype) {
|
||||
uint16_t port;
|
||||
char infobuff[256];
|
||||
int result;
|
||||
|
@ -167,7 +171,7 @@ int
|
|||
|
||||
if ((result =
|
||||
xiogetaddrinfo(hostname, portname,
|
||||
*pf, *socktype, protocol,
|
||||
*pf, socktype, protocol,
|
||||
(union sockaddr_union *)them, themlen,
|
||||
res_opts0, res_opts1
|
||||
))
|
||||
|
@ -181,7 +185,7 @@ int
|
|||
applyopts(-1, opts, PH_EARLY);
|
||||
|
||||
/* 3 means: IP address AND port accepted */
|
||||
if (retropt_bind(opts, *pf, *socktype, protocol, (struct sockaddr *)us, uslen, 3,
|
||||
if (retropt_bind(opts, *pf, socktype, protocol, (struct sockaddr *)us, uslen, 3,
|
||||
res_opts0, res_opts1)
|
||||
!= STAT_NOACTION) {
|
||||
*needbind = true;
|
||||
|
@ -210,7 +214,6 @@ int
|
|||
}
|
||||
|
||||
retropt_bool(opts, OPT_LOWPORT, lowport);
|
||||
retropt_int(opts, OPT_SO_TYPE, socktype);
|
||||
|
||||
*opts0 = copyopts(opts, GROUP_ALL);
|
||||
|
||||
|
@ -222,22 +225,24 @@ int
|
|||
|
||||
|
||||
#if WITH_TCP && WITH_LISTEN
|
||||
/*
|
||||
applies and consumes the following options:
|
||||
OPT_PROTOCOL_FAMILY, OPT_BIND
|
||||
*/
|
||||
int _xioopen_ipapp_listen_prepare(struct opt *opts, struct opt **opts0,
|
||||
const char *portname, int *pf, int ipproto,
|
||||
unsigned long res_opts0,
|
||||
unsigned long res_opts1,
|
||||
union sockaddr_union *us, socklen_t *uslen,
|
||||
int *socktype) {
|
||||
int socktype) {
|
||||
char *bindname = NULL;
|
||||
int result;
|
||||
|
||||
retropt_int(opts, OPT_SO_TYPE, socktype);
|
||||
|
||||
retropt_socket_pf(opts, pf);
|
||||
|
||||
retropt_string(opts, OPT_BIND, &bindname);
|
||||
if ((result =
|
||||
xiogetaddrinfo(bindname, portname, *pf, *socktype, ipproto,
|
||||
xiogetaddrinfo(bindname, portname, *pf, socktype, ipproto,
|
||||
(union sockaddr_union *)us, uslen,
|
||||
res_opts0, res_opts1))
|
||||
!= STAT_OK) {
|
||||
|
@ -284,7 +289,7 @@ int xioopen_ipapp_listen(int argc, const char *argv[], struct opt *opts,
|
|||
if (_xioopen_ipapp_listen_prepare(opts, &opts0, argv[1], &pf, ipproto,
|
||||
fd->stream.para.socket.ip.res_opts[1],
|
||||
fd->stream.para.socket.ip.res_opts[0],
|
||||
us, &uslen, &socktype)
|
||||
us, &uslen, socktype)
|
||||
!= STAT_OK) {
|
||||
return STAT_NORETRY;
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/* source: xio-ipapp.h */
|
||||
/* Copyright Gerhard Rieger 2001-2006 */
|
||||
/* Copyright Gerhard Rieger 2001-2008 */
|
||||
/* Published under the GNU General Public License V.2, see file COPYING */
|
||||
|
||||
#ifndef __xio_ipapp_h_included
|
||||
|
@ -25,7 +25,7 @@ extern int
|
|||
union sockaddr_union *them, socklen_t *themlen,
|
||||
union sockaddr_union *us, socklen_t *uslen,
|
||||
bool *needbind, bool *lowport,
|
||||
int *socktype);
|
||||
int socktype);
|
||||
extern int _xioopen_ip4app_connect(const char *hostname, const char *portname,
|
||||
struct single *xfd,
|
||||
int socktype, int ipproto, void *protname,
|
||||
|
@ -39,7 +39,7 @@ extern int _xioopen_ipapp_listen_prepare(struct opt *opts, struct opt **opts0,
|
|||
unsigned long res_opts0,
|
||||
unsigned long res_opts1,
|
||||
union sockaddr_union *us, socklen_t *uslen,
|
||||
int *socktype);
|
||||
int socktype);
|
||||
extern int xioopen_ip6app_connect(int argc, const char *argv[], struct opt *opts,
|
||||
int rw, xiofile_t *fd,
|
||||
unsigned groups, int socktype, int ipproto,
|
||||
|
|
25
xio-listen.c
25
xio-listen.c
|
@ -25,6 +25,13 @@ const struct optdesc opt_range = { "range", NULL, OPT_RANGE, GROUP_R
|
|||
#endif
|
||||
|
||||
|
||||
/*
|
||||
applies and consumes the following option:
|
||||
PH_INIT, PH_PASTSOCKET, PH_PREBIND, PH_BIND, PH_PASTBIND, PH_EARLY,
|
||||
PH_PREOPEN, PH_FD, PH_CONNECTED, PH_LATE, PH_LATE2
|
||||
OPT_FORK, OPT_SO_TYPE, OPT_SO_PROTOTYPE, OPT_BACKLOG, OPT_RANGE, tcpwrap,
|
||||
OPT_SOURCEPORT, OPT_LOWPORT, cloexec
|
||||
*/
|
||||
int
|
||||
xioopen_listen(struct single *xfd, int xioflags,
|
||||
struct sockaddr *us, socklen_t uslen,
|
||||
|
@ -81,15 +88,21 @@ int
|
|||
}
|
||||
|
||||
|
||||
/* waits for incoming connection, checks its source address and port. Depending
|
||||
on fork option, it may fork a subprocess.
|
||||
/* creates the listening socket, bind, applies options; waits for incoming
|
||||
connection, checks its source address and port. Depending on fork option, it
|
||||
may fork a subprocess.
|
||||
Returns 0 if a connection was accepted; with fork option, this is always in
|
||||
a subprocess!
|
||||
Other return values indicate a problem; this can happen in the master
|
||||
process or in a subprocess.
|
||||
This function does not retry. If you need retries, handle this is a
|
||||
loop in the calling function.
|
||||
This function does not retry. If you need retries, handle this in a
|
||||
loop in the calling function (and always provide the options...)
|
||||
after fork, we set the forever/retry of the child process to 0
|
||||
applies and consumes the following option:
|
||||
PH_INIT, PH_PASTSOCKET, PH_PREBIND, PH_BIND, PH_PASTBIND, PH_EARLY,
|
||||
PH_PREOPEN, PH_FD, PH_CONNECTED, PH_LATE, PH_LATE2
|
||||
OPT_FORK, OPT_SO_TYPE, OPT_SO_PROTOTYPE, OPT_BACKLOG, OPT_RANGE, tcpwrap,
|
||||
OPT_SOURCEPORT, OPT_LOWPORT, cloexec
|
||||
*/
|
||||
int _xioopen_listen(struct single *xfd, int xioflags, struct sockaddr *us, socklen_t uslen,
|
||||
struct opt *opts, int pf, int socktype, int proto, int level) {
|
||||
|
@ -119,9 +132,7 @@ int _xioopen_listen(struct single *xfd, int xioflags, struct sockaddr *us, sockl
|
|||
xiosetchilddied(); /* set SIGCHLD handler */
|
||||
}
|
||||
|
||||
if ((xfd->fd = Socket(pf, socktype, proto)) < 0) {
|
||||
Msg4(level,
|
||||
"socket(%d, %d, %d): %s", pf, socktype, proto, strerror(errno));
|
||||
if ((xfd->fd = xiosocket(opts, pf, socktype, proto, level)) < 0) {
|
||||
return STAT_RETRYLATER;
|
||||
}
|
||||
|
||||
|
|
|
@ -200,7 +200,7 @@ static int
|
|||
xfd->para.socket.ip.res_opts[1],
|
||||
xfd->para.socket.ip.res_opts[0],
|
||||
them, &themlen, us, &uslen,
|
||||
&needbind, &lowport, &socktype);
|
||||
&needbind, &lowport, socktype);
|
||||
if (result != STAT_OK) return STAT_NORETRY;
|
||||
|
||||
if (xioopts.logopt == 'm') {
|
||||
|
@ -440,7 +440,7 @@ static int
|
|||
if (_xioopen_ipapp_listen_prepare(opts, &opts0, portname, &pf, ipproto,
|
||||
xfd->para.socket.ip.res_opts[1],
|
||||
xfd->para.socket.ip.res_opts[0],
|
||||
us, &uslen, &socktype)
|
||||
us, &uslen, socktype)
|
||||
!= STAT_OK) {
|
||||
return STAT_NORETRY;
|
||||
}
|
||||
|
|
|
@ -10,6 +10,9 @@
|
|||
#include "xio-process.h"
|
||||
#include "xio-progcall.h"
|
||||
|
||||
#include "xio-socket.h"
|
||||
|
||||
|
||||
/* these options are used by address pty too */
|
||||
#if HAVE_OPENPTY
|
||||
const struct optdesc opt_openpty = { "openpty", NULL, OPT_OPENPTY, GROUP_PTY, PH_BIGEN, TYPE_BOOL, OFUNC_SPEC };
|
||||
|
@ -49,7 +52,7 @@ int _xioopen_foxec(int xioflags, /* XIO_RDONLY etc. */
|
|||
) {
|
||||
struct opt *popts; /* parent process options */
|
||||
int numleft;
|
||||
int d, type, protocol, sv[2], rdpip[2], wrpip[2];
|
||||
int d, sv[2], rdpip[2], wrpip[2];
|
||||
int rw = (xioflags & XIO_ACCMODE);
|
||||
bool usepipes = false;
|
||||
#if HAVE_PTY
|
||||
|
@ -358,13 +361,10 @@ int _xioopen_foxec(int xioflags, /* XIO_RDONLY etc. */
|
|||
applyopts(fd->fd, popts, PH_LATE);
|
||||
if (applyopts_single(fd, popts, PH_LATE) < 0) return -1;
|
||||
} else {
|
||||
d = AF_UNIX; type = SOCK_STREAM;
|
||||
protocol = 0; /* PF_UNIX does not work on AIX */
|
||||
retropt_int(popts, OPT_SO_TYPE, &type);
|
||||
result = Socketpair(d, type, protocol, sv);
|
||||
d = AF_UNIX;
|
||||
retropt_int(popts, OPT_PROTOCOL_FAMILY, &d);
|
||||
result = xiosocketpair(popts, d, SOCK_STREAM, 0, sv);
|
||||
if (result < 0) {
|
||||
Error5("socketpair(%d, %d, %d, %p): %s",
|
||||
d, type, protocol, sv, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
/*0 Info5("socketpair(%d, %d, %d, {%d,%d})",
|
||||
|
|
|
@ -131,7 +131,7 @@ static int xioopen_proxy_connect(int argc, const char *argv[], struct opt *opts,
|
|||
xfd->para.socket.ip.res_opts[1],
|
||||
xfd->para.socket.ip.res_opts[0],
|
||||
them, &themlen, us, &uslen,
|
||||
&needbind, &lowport, &socktype);
|
||||
&needbind, &lowport, socktype);
|
||||
if (result != STAT_OK) return result;
|
||||
|
||||
Notice4("opening connection to %s:%u via proxy %s:%s",
|
||||
|
|
32
xio-rawip.c
32
xio-rawip.c
|
@ -17,7 +17,6 @@
|
|||
#include "xio-rawip.h"
|
||||
|
||||
|
||||
|
||||
static
|
||||
int xioopen_rawip_sendto(int argc, const char *argv[], struct opt *opts,
|
||||
int xioflags, xiofile_t *fd, unsigned groups, int pf,
|
||||
|
@ -38,7 +37,7 @@ int xioopen_rawip_recv(int argc, const char *argv[], struct opt *opts,
|
|||
static
|
||||
int _xioopen_rawip_sendto(const char *hostname, const char *protname,
|
||||
struct opt *opts, int xioflags,
|
||||
xiofile_t *xxfd, unsigned groups, int pf);
|
||||
xiofile_t *xxfd, unsigned groups, int *pf);
|
||||
|
||||
const struct addrdesc addr_rawip_sendto = { "ip-sendto", 3, xioopen_rawip_sendto, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP4|GROUP_SOCK_IP6, PF_UNSPEC, 0, 0 HELP(":<host>:<protocol>") };
|
||||
const struct addrdesc addr_rawip_datagram= { "ip-datagram", 3, xioopen_rawip_datagram, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP4|GROUP_SOCK_IP6|GROUP_RANGE, PF_UNSPEC, 0, 0 HELP(":<host>:<protocol>") };
|
||||
|
@ -75,17 +74,24 @@ int xioopen_rawip_sendto(int argc, const char *argv[], struct opt *opts,
|
|||
return STAT_NORETRY;
|
||||
}
|
||||
if ((result = _xioopen_rawip_sendto(argv[1], argv[2], opts, xioflags, xxfd,
|
||||
groups, pf)) != STAT_OK) {
|
||||
groups, &pf)) != STAT_OK) {
|
||||
return result;
|
||||
}
|
||||
_xio_openlate(&xxfd->stream, opts);
|
||||
return STAT_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
applies and consumes the following options:
|
||||
PH_PASTSOCKET, PH_FD, PH_PREBIND, PH_BIND, PH_PASTBIND, PH_CONNECTED, PH_LATE
|
||||
OFUNC_OFFSET
|
||||
OPT_PROTOCOL_FAMILY, OPT_BIND, OPT_SO_TYPE, OPT_SO_PROTOTYPE, OPT_USER,
|
||||
OPT_GROUP, OPT_CLOEXEC
|
||||
*/
|
||||
static
|
||||
int _xioopen_rawip_sendto(const char *hostname, const char *protname,
|
||||
struct opt *opts, int xioflags, xiofile_t *xxfd,
|
||||
unsigned groups, int pf) {
|
||||
unsigned groups, int *pf) {
|
||||
char *garbage;
|
||||
xiosingle_t *xfd = &xxfd->stream;
|
||||
union sockaddr_union us;
|
||||
|
@ -107,7 +113,7 @@ int _xioopen_rawip_sendto(const char *hostname, const char *protname,
|
|||
}
|
||||
|
||||
xfd->howtoend = END_SHUTDOWN;
|
||||
retropt_int(opts, OPT_SO_TYPE, &socktype);
|
||||
retropt_int(opts, OPT_PROTOCOL_FAMILY, pf);
|
||||
|
||||
/* ...res_opts[] */
|
||||
if (applyopts_single(xfd, opts, PH_INIT) < 0) return -1;
|
||||
|
@ -115,29 +121,29 @@ int _xioopen_rawip_sendto(const char *hostname, const char *protname,
|
|||
|
||||
xfd->salen = sizeof(xfd->peersa);
|
||||
if ((result =
|
||||
xiogetaddrinfo(hostname, NULL, pf, socktype, ipproto,
|
||||
xiogetaddrinfo(hostname, NULL, *pf, socktype, ipproto,
|
||||
&xfd->peersa, &xfd->salen,
|
||||
xfd->para.socket.ip.res_opts[0],
|
||||
xfd->para.socket.ip.res_opts[1]))
|
||||
!= STAT_OK) {
|
||||
return result;
|
||||
}
|
||||
if (pf == PF_UNSPEC) {
|
||||
pf = xfd->peersa.soa.sa_family;
|
||||
if (*pf == PF_UNSPEC) {
|
||||
*pf = xfd->peersa.soa.sa_family;
|
||||
}
|
||||
|
||||
uslen = socket_init(pf, &us);
|
||||
uslen = socket_init(*pf, &us);
|
||||
|
||||
xfd->dtype = XIODATA_RECVFROM_SKIPIP;
|
||||
|
||||
if (retropt_bind(opts, pf, socktype, ipproto, &us.soa, &uslen, feats,
|
||||
if (retropt_bind(opts, *pf, socktype, ipproto, &us.soa, &uslen, feats,
|
||||
xfd->para.socket.ip.res_opts[0],
|
||||
xfd->para.socket.ip.res_opts[1]) != STAT_NOACTION) {
|
||||
needbind = true;
|
||||
}
|
||||
return
|
||||
_xioopen_dgram_sendto(needbind?&us:NULL, uslen,
|
||||
opts, xioflags, xfd, groups, pf, socktype, ipproto);
|
||||
opts, xioflags, xfd, groups, *pf, socktype, ipproto);
|
||||
}
|
||||
|
||||
|
||||
|
@ -157,7 +163,7 @@ int xioopen_rawip_datagram(int argc, const char *argv[], struct opt *opts,
|
|||
}
|
||||
if ((result =
|
||||
_xioopen_rawip_sendto(argv[1], argv[2], opts, xioflags, xxfd,
|
||||
groups, pf)) != STAT_OK) {
|
||||
groups, &pf)) != STAT_OK) {
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -216,7 +222,6 @@ int xioopen_rawip_recvfrom(int argc, const char *argv[], struct opt *opts,
|
|||
/*return STAT_NORETRY;*/
|
||||
}
|
||||
xfd->stream.howtoend = END_NONE;
|
||||
retropt_int(opts, OPT_SO_TYPE, &socktype);
|
||||
|
||||
retropt_socket_pf(opts, &pf);
|
||||
if (pf == PF_UNSPEC) {
|
||||
|
@ -274,7 +279,6 @@ int xioopen_rawip_recv(int argc, const char *argv[], struct opt *opts,
|
|||
protname);
|
||||
/*return STAT_NORETRY;*/
|
||||
}
|
||||
retropt_int(opts, OPT_SO_TYPE, &socktype);
|
||||
|
||||
retropt_socket_pf(opts, &pf);
|
||||
if (pf == PF_UNSPEC) {
|
||||
|
|
93
xio-socket.c
93
xio-socket.c
|
@ -39,7 +39,7 @@ const struct optdesc opt_so_sndbuf_late={ "so-sndbuf-late","sndbuf-late",OPT_SO_
|
|||
const struct optdesc opt_so_rcvbuf = { "so-rcvbuf", "rcvbuf", OPT_SO_RCVBUF, GROUP_SOCKET, PH_PASTSOCKET, TYPE_INT, OFUNC_SOCKOPT, SOL_SOCKET, SO_RCVBUF};
|
||||
const struct optdesc opt_so_rcvbuf_late={"so-rcvbuf-late","rcvbuf-late",OPT_SO_RCVBUF_LATE,GROUP_SOCKET,PH_LATE,TYPE_INT,OFUNC_SOCKOPT,SOL_SOCKET,SO_RCVBUF };
|
||||
const struct optdesc opt_so_error = { "so-error", "error", OPT_SO_ERROR, GROUP_SOCKET, PH_PASTSOCKET, TYPE_INT, OFUNC_SOCKOPT, SOL_SOCKET, SO_ERROR};
|
||||
const struct optdesc opt_so_type = { "so-type", "type", OPT_SO_TYPE, GROUP_SOCKET, PH_PASTSOCKET, TYPE_INT, OFUNC_SOCKOPT, SOL_SOCKET, SO_TYPE };
|
||||
const struct optdesc opt_so_type = { "so-type", "type", OPT_SO_TYPE, GROUP_SOCKET, PH_SOCKET, TYPE_INT, OFUNC_SPEC, SOL_SOCKET, SO_TYPE };
|
||||
const struct optdesc opt_so_dontroute= { "so-dontroute", "dontroute", OPT_SO_DONTROUTE,GROUP_SOCKET, PH_PASTSOCKET, TYPE_INT, OFUNC_SOCKOPT, SOL_SOCKET, SO_DONTROUTE };
|
||||
#ifdef SO_RCVLOWAT
|
||||
const struct optdesc opt_so_rcvlowat = { "so-rcvlowat", "rcvlowat", OPT_SO_RCVLOWAT, GROUP_SOCKET, PH_PASTSOCKET, TYPE_INT, OFUNC_SOCKOPT, SOL_SOCKET, SO_RCVLOWAT };
|
||||
|
@ -115,9 +115,9 @@ const struct optdesc opt_so_dgram_errind={"so-dgram-errind","dgramerrind",OPT_SO
|
|||
#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 };
|
||||
#endif
|
||||
#ifdef SO_PROTOTYPE /* Solaris, HP-UX */
|
||||
const struct optdesc opt_so_prototype = {"so-prototype", "prototype", OPT_SO_PROTOTYPE, GROUP_SOCKET,PH_PASTSOCKET,TYPE_INT,OFUNC_SOCKOPT,SOL_SOCKET,SO_PROTOTYPE };
|
||||
#endif
|
||||
/* the SO_PROTOTYPE is OS defined on Solaris, HP-UX; we lend this for a more
|
||||
general purpose */
|
||||
const struct optdesc opt_so_prototype = {"so-prototype", "prototype", OPT_SO_PROTOTYPE, GROUP_SOCKET,PH_SOCKET, TYPE_INT,OFUNC_SPEC, SOL_SOCKET,SO_PROTOTYPE };
|
||||
#ifdef FIOSETOWN
|
||||
const struct optdesc opt_fiosetown = { "fiosetown", NULL, OPT_FIOSETOWN, GROUP_SOCKET, PH_PASTSOCKET, TYPE_INT, OFUNC_IOCTL, FIOSETOWN };
|
||||
#endif
|
||||
|
@ -127,15 +127,21 @@ const struct optdesc opt_siocspgrp = { "siocspgrp", NULL, OPT_SIOCSPGRP, GRO
|
|||
const struct optdesc opt_bind = { "bind", NULL, OPT_BIND, GROUP_SOCKET, PH_BIND, TYPE_STRING,OFUNC_SPEC };
|
||||
const struct optdesc opt_connect_timeout = { "connect-timeout", NULL, OPT_CONNECT_TIMEOUT, GROUP_SOCKET, PH_PASTSOCKET, TYPE_TIMEVAL, OFUNC_OFFSET, (int)&((xiofile_t *)0)->stream.para.socket.connect_timeout };
|
||||
const struct optdesc opt_protocol_family = { "protocol-family", "pf", OPT_PROTOCOL_FAMILY, GROUP_SOCKET, PH_PRESOCKET, TYPE_STRING, OFUNC_SPEC };
|
||||
const struct optdesc opt_protocol = { "protocol", NULL, OPT_PROTOCOL, GROUP_SOCKET, PH_PRESOCKET, TYPE_STRING, OFUNC_SPEC };
|
||||
|
||||
/* a subroutine that is common to all socket addresses that want to connect
|
||||
to a peer address.
|
||||
might fork.
|
||||
applies and consumes the following options:
|
||||
PH_PASTSOCKET, PH_FD, PH_PREBIND, PH_BIND, PH_PASTBIND, PH_CONNECT,
|
||||
PH_CONNECTED, PH_LATE,
|
||||
OFUNC_OFFSET,
|
||||
OPT_SO_TYPE, OPT_SO_PROTOTYPE, OPT_USER, OPT_GROUP, OPT_CLOEXEC
|
||||
returns 0 on success.
|
||||
*/
|
||||
int _xioopen_connect(struct single *xfd, struct sockaddr *us, size_t uslen,
|
||||
struct sockaddr *them, size_t themlen,
|
||||
struct opt *opts, int pf, int stype, int proto,
|
||||
struct opt *opts, int pf, int socktype, int protocol,
|
||||
bool alt, int level) {
|
||||
int fcntl_flags = 0;
|
||||
char infobuff[256];
|
||||
|
@ -144,9 +150,7 @@ int _xioopen_connect(struct single *xfd, struct sockaddr *us, size_t uslen,
|
|||
int _errno;
|
||||
int result;
|
||||
|
||||
if ((xfd->fd = Socket(pf, stype, proto)) < 0) {
|
||||
Msg4(level,
|
||||
"socket(%d, %d, %d): %s", pf, stype, proto, strerror(errno));
|
||||
if ((xfd->fd = xiosocket(opts, pf, socktype, protocol, level)) < 0) {
|
||||
return STAT_RETRYLATER;
|
||||
}
|
||||
|
||||
|
@ -340,7 +344,7 @@ int _xioopen_connect(struct single *xfd, struct sockaddr *us, size_t uslen,
|
|||
}
|
||||
}
|
||||
|
||||
applyopts_fchown(xfd->fd, opts);
|
||||
applyopts_fchown(xfd->fd, opts); /* OPT_USER, OPT_GROUP */
|
||||
applyopts(xfd->fd, opts, PH_CONNECTED);
|
||||
applyopts(xfd->fd, opts, PH_LATE);
|
||||
|
||||
|
@ -354,11 +358,16 @@ int _xioopen_connect(struct single *xfd, struct sockaddr *us, size_t uslen,
|
|||
/* a subroutine that is common to all socket addresses that want to connect
|
||||
to a peer address.
|
||||
might fork.
|
||||
applies and consumes the following option:
|
||||
PH_PASTSOCKET, PH_FD, PH_PREBIND, PH_BIND, PH_PASTBIND, PH_CONNECT,
|
||||
PH_CONNECTED, PH_LATE,
|
||||
OFUNC_OFFSET,
|
||||
OPT_FORK, OPT_SO_TYPE, OPT_SO_PROTOTYPE, OPT_USER, OPT_GROUP, OPT_CLOEXEC
|
||||
returns 0 on success.
|
||||
*/
|
||||
int xioopen_connect(struct single *xfd, struct sockaddr *us, size_t uslen,
|
||||
struct sockaddr *them, size_t themlen,
|
||||
struct opt *opts, int pf, int stype, int proto,
|
||||
struct opt *opts, int pf, int socktype, int protocol,
|
||||
bool alt) {
|
||||
bool dofork = false;
|
||||
struct opt *opts0;
|
||||
|
@ -367,7 +376,6 @@ int xioopen_connect(struct single *xfd, struct sockaddr *us, size_t uslen,
|
|||
int result;
|
||||
|
||||
retropt_bool(opts, OPT_FORK, &dofork);
|
||||
retropt_int(opts, OPT_SO_TYPE, &stype);
|
||||
|
||||
opts0 = copyopts(opts, GROUP_ALL);
|
||||
|
||||
|
@ -384,7 +392,7 @@ int xioopen_connect(struct single *xfd, struct sockaddr *us, size_t uslen,
|
|||
level = E_ERROR;
|
||||
result =
|
||||
_xioopen_connect(xfd, us, uslen, them, themlen, opts,
|
||||
pf, stype, proto, alt, level);
|
||||
pf, socktype, protocol, alt, level);
|
||||
switch (result) {
|
||||
case STAT_OK: break;
|
||||
#if WITH_RETRY
|
||||
|
@ -454,7 +462,12 @@ int xioopen_connect(struct single *xfd, struct sockaddr *us, size_t uslen,
|
|||
}
|
||||
|
||||
|
||||
/* common to xioopen_udp_sendto, ..unix_sendto, ..rawip */
|
||||
/* common to xioopen_udp_sendto, ..unix_sendto, ..rawip
|
||||
applies and consumes the following option:
|
||||
PH_PASTSOCKET, PH_FD, PH_PREBIND, PH_BIND, PH_PASTBIND, PH_CONNECTED, PH_LATE
|
||||
OFUNC_OFFSET
|
||||
OPT_SO_TYPE, OPT_SO_PROTOTYPE, OPT_USER, OPT_GROUP, OPT_CLOEXEC
|
||||
*/
|
||||
int _xioopen_dgram_sendto(/* them is already in xfd->peersa */
|
||||
union sockaddr_union *us, socklen_t uslen,
|
||||
struct opt *opts,
|
||||
|
@ -464,9 +477,7 @@ int _xioopen_dgram_sendto(/* them is already in xfd->peersa */
|
|||
union sockaddr_union la; socklen_t lalen = sizeof(la);
|
||||
char infobuff[256];
|
||||
|
||||
if ((xfd->fd = Socket(pf, socktype, ipproto)) < 0) {
|
||||
Msg4(level,
|
||||
"socket(%d, %d, %d): %s", pf, socktype, ipproto, strerror(errno));
|
||||
if ((xfd->fd = xiosocket(opts, pf, socktype, ipproto, level)) < 0) {
|
||||
return STAT_RETRYLATER;
|
||||
}
|
||||
|
||||
|
@ -590,6 +601,10 @@ void xiosigaction_hasread(int signum, siginfo_t *siginfo, void *ucontext) {
|
|||
This function does not retry. If you need retries, handle this is a
|
||||
loop in the calling function.
|
||||
after fork, we set the forever/retry of the child process to 0
|
||||
applies and consumes the following options:
|
||||
PH_INIT, PH_PREBIND, PH_BIND, PH_PASTBIND, PH_EARLY, PH_PREOPEN, PH_FD,
|
||||
PH_CONNECTED, PH_LATE, PH_LATE2
|
||||
OPT_FORK, OPT_SO_TYPE, OPT_SO_PROTOTYPE, cloexec, OPT_RANGE, tcpwrap
|
||||
*/
|
||||
int _xioopen_dgram_recvfrom(struct single *xfd, int xioflags,
|
||||
struct sockaddr *us, socklen_t uslen,
|
||||
|
@ -616,9 +631,7 @@ int _xioopen_dgram_recvfrom(struct single *xfd, int xioflags,
|
|||
|
||||
if (applyopts_single(xfd, opts, PH_INIT) < 0) return STAT_NORETRY;
|
||||
|
||||
if ((xfd->fd = Socket(pf, socktype, proto)) < 0) {
|
||||
Msg4(level,
|
||||
"socket(%d, %d, %d): %s", pf, socktype, proto, strerror(errno));
|
||||
if ((xfd->fd = xiosocket(opts, pf, socktype, proto, level)) < 0) {
|
||||
return STAT_RETRYLATER;
|
||||
}
|
||||
|
||||
|
@ -869,9 +882,7 @@ int _xioopen_dgram_recv(struct single *xfd, int xioflags,
|
|||
|
||||
if (applyopts_single(xfd, opts, PH_INIT) < 0) return STAT_NORETRY;
|
||||
|
||||
if ((xfd->fd = Socket(pf, socktype, proto)) < 0) {
|
||||
Msg4(level,
|
||||
"socket(%d, %d, %d): %s", pf, socktype, proto, strerror(errno));
|
||||
if ((xfd->fd = xiosocket(opts, pf, socktype, proto, level)) < 0) {
|
||||
return STAT_RETRYLATER;
|
||||
}
|
||||
|
||||
|
@ -1128,3 +1139,41 @@ int xiocheckpeer(xiosingle_t *xfd,
|
|||
}
|
||||
|
||||
#endif /* _WITH_SOCKET */
|
||||
|
||||
/* these do sockets internally */
|
||||
|
||||
/* retrieves options so-type and so-prototype from opts, calls socketpair, and
|
||||
ev. generates an appropriate error message.
|
||||
returns 0 on success or -1 if an error occurred. */
|
||||
int
|
||||
xiosocket(struct opt *opts, int pf, int socktype, int proto, int msglevel) {
|
||||
int result;
|
||||
|
||||
retropt_int(opts, OPT_SO_TYPE, &socktype);
|
||||
retropt_int(opts, OPT_SO_PROTOTYPE, &proto);
|
||||
result = Socket(pf, socktype, proto);
|
||||
if (result < 0) {
|
||||
Msg4(msglevel, "socket(%d, %d, %d): %s",
|
||||
pf, socktype, proto, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/* retrieves options so-type and so-prototype from opts, calls socketpair, and
|
||||
ev. generates an appropriate error message.
|
||||
returns 0 on success or -1 if an error occurred. */
|
||||
int
|
||||
xiosocketpair(struct opt *opts, int pf, int socktype, int proto, int sv[2]) {
|
||||
int result;
|
||||
|
||||
retropt_int(opts, OPT_SO_TYPE, &socktype);
|
||||
retropt_int(opts, OPT_SO_PROTOTYPE, &proto);
|
||||
result = Socketpair(pf, socktype, proto, sv);
|
||||
if (result < 0) {
|
||||
Error5("socketpair(%d, %d, %d, %p): %s",
|
||||
pf, socktype, proto, sv, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
|
18
xio-socket.h
18
xio-socket.h
|
@ -1,10 +1,16 @@
|
|||
/* source: xio-socket.h */
|
||||
/* Copyright Gerhard Rieger 2001-2006 */
|
||||
/* Copyright Gerhard Rieger 2001-2008 */
|
||||
/* Published under the GNU General Public License V.2, see file COPYING */
|
||||
|
||||
#ifndef __xio_socket_h_included
|
||||
#define __xio_socket_h_included 1
|
||||
|
||||
/* SO_PROTOTYPE is OS defined on Solaris, HP-UX; we lend this for a more
|
||||
general purpose */
|
||||
#ifndef SO_PROTOTYPE
|
||||
#define SO_PROTOTYPE 0x9999
|
||||
#endif
|
||||
|
||||
extern const struct optdesc opt_connect_timeout;
|
||||
extern const struct optdesc opt_so_debug;
|
||||
extern const struct optdesc opt_so_acceptconn;
|
||||
|
@ -56,12 +62,14 @@ extern int retropt_socket_pf(struct opt *opts, int *pf);
|
|||
extern int xioopen_connect(struct single *fd,
|
||||
struct sockaddr *us, size_t uslen,
|
||||
struct sockaddr *them, size_t themlen,
|
||||
struct opt *opts, int pf, int stype, int proto,
|
||||
struct opt *opts,
|
||||
int pf, int socktype, int protocol,
|
||||
bool alt);
|
||||
extern int _xioopen_connect(struct single *fd,
|
||||
struct sockaddr *us, size_t uslen,
|
||||
struct sockaddr *them, size_t themlen,
|
||||
struct opt *opts, int pf, int stype, int proto,
|
||||
struct opt *opts,
|
||||
int pf, int socktype, int protocol,
|
||||
bool alt, int level);
|
||||
|
||||
/* common to xioopen_udp_sendto, ..unix_sendto, ..rawip */
|
||||
|
@ -86,5 +94,9 @@ int xiogetpacketsrc(int fd, union sockaddr_union *pa, socklen_t *palen);
|
|||
extern
|
||||
int xiocheckpeer(xiosingle_t *xfd,
|
||||
union sockaddr_union *pa, union sockaddr_union *la);
|
||||
extern int
|
||||
xiosocket(struct opt *opts, int pf, int socktype, int proto, int level);
|
||||
extern int
|
||||
xiosocketpair(struct opt *opts, int pf, int socktype, int proto, int sv[2]);
|
||||
|
||||
#endif /* !defined(__xio_socket_h_included) */
|
||||
|
|
|
@ -88,7 +88,7 @@ static int xioopen_socks4_connect(int argc, const char *argv[], struct opt *opts
|
|||
xfd->para.socket.ip.res_opts[1],
|
||||
xfd->para.socket.ip.res_opts[0],
|
||||
them, &themlen, us, &uslen,
|
||||
&needbind, &lowport, &socktype);
|
||||
&needbind, &lowport, socktype);
|
||||
|
||||
Notice5("opening connection to %s:%u via socks4 server %s:%s as user \"%s\"",
|
||||
targetname,
|
||||
|
|
16
xio-udp.c
16
xio-udp.c
|
@ -114,7 +114,6 @@ int xioopen_ipdgram_listen(int argc, const char *argv[], struct opt *opts,
|
|||
applyopts(-1, opts, PH_INIT);
|
||||
|
||||
uslen = socket_init(pf, &us);
|
||||
retropt_int(opts, OPT_SO_TYPE, &socktype);
|
||||
retropt_bind(opts, pf, socktype, IPPROTO_UDP,
|
||||
(struct sockaddr *)&us, &uslen, 1,
|
||||
fd->stream.para.socket.ip.res_opts[1],
|
||||
|
@ -176,8 +175,7 @@ int xioopen_ipdgram_listen(int argc, const char *argv[], struct opt *opts,
|
|||
union sockaddr_union _sockname;
|
||||
union sockaddr_union *la = &_sockname; /* local address */
|
||||
|
||||
if ((fd->stream.fd = Socket(pf, socktype, ipproto)) < 0) {
|
||||
Error4("socket(%d, %d, %d): %s", pf, socktype, ipproto, strerror(errno));
|
||||
if ((fd->stream.fd = xiosocket(opts, pf, socktype, ipproto, E_ERROR)) < 0) {
|
||||
return STAT_RETRYLATER;
|
||||
}
|
||||
applyopts(fd->stream.fd, opts, PH_PASTSOCKET);
|
||||
|
@ -230,7 +228,7 @@ int xioopen_ipdgram_listen(int argc, const char *argv[], struct opt *opts,
|
|||
if (xiocheckpeer(&fd->stream, them, la) < 0) {
|
||||
/* drop packet */
|
||||
char buff[512];
|
||||
Recv(fd->stream.fd, buff, sizeof(buff), 0);
|
||||
Recv(fd->stream.fd, buff, sizeof(buff), 0); /* drop packet */
|
||||
Close(fd->stream.fd);
|
||||
continue;
|
||||
}
|
||||
|
@ -296,6 +294,8 @@ int xioopen_udp_sendto(int argc, const char *argv[], struct opt *opts,
|
|||
argv[0], argc-1);
|
||||
return STAT_NORETRY;
|
||||
}
|
||||
|
||||
retropt_socket_pf(opts, &pf);
|
||||
if ((result = _xioopen_udp_sendto(argv[1], argv[2], opts, xioflags, xxfd,
|
||||
groups, pf, socktype, ipproto))
|
||||
!= STAT_OK) {
|
||||
|
@ -305,6 +305,12 @@ int xioopen_udp_sendto(int argc, const char *argv[], struct opt *opts,
|
|||
return STAT_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
applies and consumes the following option:
|
||||
PH_INIT, PH_PASTSOCKET, PH_FD, PH_PREBIND, PH_BIND, PH_PASTBIND, PH_CONNECTED, PH_LATE
|
||||
OFUNC_OFFSET
|
||||
OPT_BIND, OPT_SOURCEPORT, OPT_LOWPORT, OPT_SO_TYPE, OPT_SO_PROTOTYPE, OPT_USER, OPT_GROUP, OPT_CLOEXEC
|
||||
*/
|
||||
static
|
||||
int _xioopen_udp_sendto(const char *hostname, const char *servname,
|
||||
struct opt *opts,
|
||||
|
@ -318,7 +324,6 @@ int _xioopen_udp_sendto(const char *hostname, const char *servname,
|
|||
int result;
|
||||
|
||||
xfd->howtoend = END_SHUTDOWN;
|
||||
retropt_int(opts, OPT_SO_TYPE, &socktype);
|
||||
|
||||
/* ...res_opts[] */
|
||||
if (applyopts_single(xfd, opts, PH_INIT) < 0) return -1;
|
||||
|
@ -405,6 +410,7 @@ int xioopen_udp_datagram(int argc, const char *argv[], struct opt *opts,
|
|||
return STAT_RETRYLATER;
|
||||
}
|
||||
|
||||
retropt_socket_pf(opts, &pf);
|
||||
result =
|
||||
_xioopen_udp_sendto(hostname, argv[2], opts, xioflags, xxfd, groups,
|
||||
pf, socktype, ipproto);
|
||||
|
|
116
xio-unix.c
116
xio-unix.c
|
@ -62,17 +62,20 @@ const struct optdesc xioopt_unix_tightsocklen = { "unix-tightsocklen", "tight
|
|||
|
||||
/* fills the socket address struct and returns its effective length.
|
||||
abstract is usually 0; != 0 generates an abstract socket address on Linux.
|
||||
tight calculates the resulting length from the path length, not from the
|
||||
struct length.
|
||||
tight!=0 calculates the resulting length from the path length, not from the
|
||||
structures length; this is more common.
|
||||
the struct need not be initialized when calling this function.
|
||||
*/
|
||||
socklen_t
|
||||
xiosetunix(struct sockaddr_un *saun,
|
||||
xiosetunix(int pf,
|
||||
struct sockaddr_un *saun,
|
||||
const char *path,
|
||||
bool abstract,
|
||||
bool tight) {
|
||||
size_t pathlen;
|
||||
socklen_t len;
|
||||
|
||||
socket_un_init(saun);
|
||||
#ifdef WITH_ABSTRACT_UNIXSOCKET
|
||||
if (abstract) {
|
||||
if ((pathlen = strlen(path)) >= sizeof(saun->sun_path)) {
|
||||
|
@ -130,11 +133,10 @@ static int xioopen_unix_listen(int argc, const char *argv[], struct opt *opts, i
|
|||
return STAT_NORETRY;
|
||||
}
|
||||
|
||||
socket_un_init(&us);
|
||||
|
||||
retropt_bool(opts, OPT_UNIX_TIGHTSOCKLEN, &tight);
|
||||
name = argv[1];
|
||||
uslen = xiosetunix(&us, name, abstract, tight);
|
||||
retropt_socket_pf(opts, &pf);
|
||||
retropt_bool(opts, OPT_UNIX_TIGHTSOCKLEN, &tight);
|
||||
uslen = xiosetunix(pf, &us, name, abstract, tight);
|
||||
|
||||
xfd->howtoend = END_SHUTDOWN;
|
||||
|
||||
|
@ -151,7 +153,6 @@ static int xioopen_unix_listen(int argc, const char *argv[], struct opt *opts, i
|
|||
}
|
||||
|
||||
applyopts(-1, opts, PH_INIT);
|
||||
if (applyopts_single(xfd, opts, PH_INIT) < 0) return -1;
|
||||
applyopts(-1, opts, PH_EARLY);
|
||||
|
||||
if (!(ABSTRACT && abstract)) {
|
||||
|
@ -170,8 +171,6 @@ static int xioopen_unix_listen(int argc, const char *argv[], struct opt *opts, i
|
|||
applyopts_named(name, opts, PH_EARLY); /* umask! */
|
||||
}
|
||||
|
||||
retropt_int(opts, OPT_SO_TYPE, &socktype);
|
||||
|
||||
opts0 = copyopts(opts, GROUP_ALL);
|
||||
|
||||
if ((result =
|
||||
|
@ -205,17 +204,15 @@ static int xioopen_unix_connect(int argc, const char *argv[], struct opt *opts,
|
|||
return STAT_NORETRY;
|
||||
}
|
||||
|
||||
socket_un_init(&us);
|
||||
socket_un_init(&them);
|
||||
|
||||
retropt_bool(opts, OPT_UNIX_TIGHTSOCKLEN, &tight);
|
||||
name = argv[1];
|
||||
themlen = xiosetunix(&them, name, abstract, tight);
|
||||
retropt_socket_pf(opts, &pf);
|
||||
retropt_bool(opts, OPT_UNIX_TIGHTSOCKLEN, &tight);
|
||||
themlen = xiosetunix(pf, &them, name, abstract, tight);
|
||||
if (!(ABSTRACT && abstract)) {
|
||||
/* only for non abstract because abstract do not work in file system */
|
||||
retropt_bool(opts, OPT_UNLINK_CLOSE, &opt_unlink_close);
|
||||
}
|
||||
if (retropt_bind(opts, AF_UNIX, socktype, 0, (struct sockaddr *)&us, &uslen, 0, 0, 0)
|
||||
if (retropt_bind(opts, pf, socktype, protocol, (struct sockaddr *)&us, &uslen, 0, 0, 0)
|
||||
!= STAT_NOACTION) {
|
||||
needbind = true;
|
||||
}
|
||||
|
@ -264,16 +261,12 @@ static int xioopen_unix_sendto(int argc, const char *argv[], struct opt *opts, i
|
|||
return STAT_NORETRY;
|
||||
}
|
||||
|
||||
uslen = socket_init(pf, &us);
|
||||
xfd->salen = socket_init(pf, &xfd->peersa);
|
||||
|
||||
xfd->howtoend = END_SHUTDOWN;
|
||||
|
||||
retropt_int(opts, OPT_SO_TYPE, &socktype);
|
||||
|
||||
retropt_bool(opts, OPT_UNIX_TIGHTSOCKLEN, &tight);
|
||||
name = argv[1];
|
||||
xfd->salen = xiosetunix(&xfd->peersa.un, name, abstract, tight);
|
||||
retropt_socket_pf(opts, &pf);
|
||||
xfd->salen = xiosetunix(pf, &xfd->peersa.un, name, abstract, tight);
|
||||
|
||||
xfd->howtoend = END_SHUTDOWN;
|
||||
|
||||
if (!(ABSTRACT && abstract)) {
|
||||
/* only for non abstract because abstract do not work in file system */
|
||||
|
@ -282,7 +275,7 @@ static int xioopen_unix_sendto(int argc, const char *argv[], struct opt *opts, i
|
|||
|
||||
xfd->dtype = XIODATA_RECVFROM;
|
||||
|
||||
if (retropt_bind(opts, pf, socktype, 0, &us.soa, &uslen, 0, 0, 0)
|
||||
if (retropt_bind(opts, pf, socktype, protocol, &us.soa, &uslen, 0, 0, 0)
|
||||
!= STAT_NOACTION) {
|
||||
needbind = true;
|
||||
}
|
||||
|
@ -327,15 +320,14 @@ int xioopen_unix_recvfrom(int argc, const char *argv[], struct opt *opts,
|
|||
return STAT_NORETRY;
|
||||
}
|
||||
|
||||
socket_un_init(&us);
|
||||
|
||||
retropt_bool(opts, OPT_UNIX_TIGHTSOCKLEN, &tight);
|
||||
name = argv[1];
|
||||
uslen = xiosetunix(&us, name, abstract, tight);
|
||||
retropt_socket_pf(opts, &pf);
|
||||
retropt_bool(opts, OPT_UNIX_TIGHTSOCKLEN, &tight);
|
||||
uslen = xiosetunix(pf, &us, name, abstract, tight);
|
||||
|
||||
xfd->howtoend = END_NONE;
|
||||
retropt_int(opts, OPT_SO_TYPE, &socktype);
|
||||
retropt_bind(opts, pf, socktype, 0, (struct sockaddr *)&us, &uslen, 1, 0, 0);
|
||||
retropt_bind(opts, pf, socktype, protocol, (struct sockaddr *)&us, &uslen,
|
||||
1, 0, 0);
|
||||
|
||||
if (!(ABSTRACT && abstract)) {
|
||||
/* only for non abstract because abstract do not work in file system */
|
||||
|
@ -362,9 +354,10 @@ int xioopen_unix_recvfrom(int argc, const char *argv[], struct opt *opts,
|
|||
xfd->para.socket.la.soa.sa_family = pf;
|
||||
|
||||
xfd->dtype = XIODATA_RECVFROM_ONE;
|
||||
return _xioopen_dgram_recvfrom(xfd, xioflags,
|
||||
needbind?(struct sockaddr *)&us:NULL, uslen,
|
||||
opts, pf, socktype, protocol, E_ERROR);
|
||||
return
|
||||
_xioopen_dgram_recvfrom(xfd, xioflags,
|
||||
needbind?(struct sockaddr *)&us:NULL, uslen,
|
||||
opts, pf, socktype, protocol, E_ERROR);
|
||||
}
|
||||
|
||||
|
||||
|
@ -391,13 +384,10 @@ int xioopen_unix_recv(int argc, const char *argv[], struct opt *opts,
|
|||
return STAT_NORETRY;
|
||||
}
|
||||
|
||||
retropt_int(opts, OPT_SO_TYPE, &socktype);
|
||||
|
||||
socket_un_init(&us.un);
|
||||
|
||||
retropt_bool(opts, OPT_UNIX_TIGHTSOCKLEN, &tight);
|
||||
name = argv[1];
|
||||
uslen = xiosetunix(&us.un, name, abstract, tight);
|
||||
retropt_socket_pf(opts, &pf);
|
||||
retropt_bool(opts, OPT_UNIX_TIGHTSOCKLEN, &tight);
|
||||
uslen = xiosetunix(pf, &us.un, name, abstract, tight);
|
||||
|
||||
#if 1 /*!!! why bind option? */
|
||||
retropt_bind(opts, pf, socktype, protocol, &us.soa, &uslen, 1, 0, 0);
|
||||
|
@ -437,8 +427,28 @@ int xioopen_unix_recv(int argc, const char *argv[], struct opt *opts,
|
|||
|
||||
static int xioopen_unix_client(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *xxfd, unsigned groups, int abstract, int dummy2, int dummy3) {
|
||||
/* we expect the form: filename */
|
||||
const char *name;
|
||||
xiosingle_t *xfd = &xxfd->stream;
|
||||
if (argc != 2) {
|
||||
Error2("%s: wrong number of parameters (%d instead of 1)", argv[0], argc-1);
|
||||
}
|
||||
|
||||
return
|
||||
_xioopen_unix_client(&xxfd->stream, xioflags, groups, abstract, opts,
|
||||
argv[1]);
|
||||
}
|
||||
|
||||
/* establishes communication with an existing UNIX type socket. supports stream
|
||||
and datagram socket types: first tries to connect(), but when this fails it
|
||||
falls back to sendto().
|
||||
applies and consumes the following option:
|
||||
PH_INIT, PH_PASTSOCKET, PH_FD, PH_PREBIND, PH_BIND, PH_PASTBIND,
|
||||
PH_CONNECTED, PH_LATE, ?PH_CONNECT
|
||||
OFUNC_OFFSET,
|
||||
OPT_PROTOCOL_FAMILY, OPT_UNIX_TIGHTSOCKLEN, OPT_UNLINK_CLOSE, OPT_BIND,
|
||||
OPT_SO_TYPE, OPT_SO_PROTOTYPE, OPT_CLOEXEC, OPT_USER, OPT_GROUP, ?OPT_FORK,
|
||||
*/
|
||||
int
|
||||
_xioopen_unix_client(xiosingle_t *xfd, int xioflags, unsigned groups,
|
||||
int abstract, struct opt *opts, const char *name) {
|
||||
int pf = PF_UNIX;
|
||||
int socktype = 0; /* to be determined by server socket type */
|
||||
int protocol = 0;
|
||||
|
@ -447,28 +457,24 @@ static int xioopen_unix_client(int argc, const char *argv[], struct opt *opts, i
|
|||
bool tight = true;
|
||||
bool needbind = false;
|
||||
bool opt_unlink_close = false;
|
||||
struct opt *opts0;
|
||||
int result;
|
||||
|
||||
if (argc != 2) {
|
||||
Error2("%s: wrong number of parameters (%d instead of 1)", argv[0], argc-1);
|
||||
}
|
||||
applyopts(-1, opts, PH_INIT);
|
||||
if (applyopts_single(xfd, opts, PH_INIT) < 0) return -1;
|
||||
|
||||
xfd->howtoend = END_SHUTDOWN;
|
||||
retropt_int(opts, OPT_SO_TYPE, &socktype);
|
||||
|
||||
uslen = socket_init(pf, &us);
|
||||
themlen = socket_init(pf, &them);
|
||||
retropt_socket_pf(opts, &pf);
|
||||
|
||||
retropt_bool(opts, OPT_UNIX_TIGHTSOCKLEN, &tight);
|
||||
name = argv[1];
|
||||
themlen = xiosetunix(&them.un, name, abstract, tight);
|
||||
themlen = xiosetunix(pf, &them.un, name, abstract, tight);
|
||||
|
||||
if (!(ABSTRACT && abstract)) {
|
||||
/* only for non abstract because abstract do not work in file system */
|
||||
retropt_bool(opts, OPT_UNLINK_CLOSE, &opt_unlink_close);
|
||||
}
|
||||
|
||||
if (retropt_bind(opts, pf, socktype, 0, &us.soa, &uslen, 0, 0, 0)
|
||||
if (retropt_bind(opts, pf, socktype, protocol, &us.soa, &uslen, 0, 0, 0)
|
||||
!= STAT_NOACTION) {
|
||||
needbind = true;
|
||||
}
|
||||
|
@ -480,6 +486,9 @@ static int xioopen_unix_client(int argc, const char *argv[], struct opt *opts, i
|
|||
xfd->opt_unlink_close = true;
|
||||
}
|
||||
|
||||
/* save options, because we might have to start again */
|
||||
opts0 = copyopts(opts, GROUP_ALL);
|
||||
|
||||
/* xfd->dtype = DATA_STREAM; // is default */
|
||||
if ((result =
|
||||
xioopen_connect(xfd,
|
||||
|
@ -492,8 +501,7 @@ static int xioopen_unix_client(int argc, const char *argv[], struct opt *opts, i
|
|||
Unlink(us.un.sun_path);
|
||||
}
|
||||
|
||||
applyopts(-1, opts, PH_INIT);
|
||||
if (applyopts_single(xfd, opts, PH_INIT) < 0) return -1;
|
||||
dropopts2(opts, PH_INIT, PH_SPEC); opts = opts0;
|
||||
|
||||
xfd->peersa = them;
|
||||
xfd->salen = sizeof(struct sockaddr_un);
|
||||
|
|
|
@ -21,9 +21,14 @@ extern const struct addrdesc xioaddr_abstract_client;
|
|||
extern const struct optdesc xioopt_unix_tightsocklen;
|
||||
|
||||
extern socklen_t
|
||||
xiosetunix(struct sockaddr_un *saun,
|
||||
xiosetunix(int pf,
|
||||
struct sockaddr_un *saun,
|
||||
const char *path,
|
||||
bool abstract,
|
||||
bool tight);
|
||||
|
||||
extern int
|
||||
_xioopen_unix_client(xiosingle_t *xfd, int xioflags, unsigned groups,
|
||||
int abstract, struct opt *opts, const char *name);
|
||||
|
||||
#endif /* !defined(__xio_unix_h_included) */
|
||||
|
|
12
xioopts.c
12
xioopts.c
|
@ -2333,7 +2333,15 @@ int retropt_int(struct opt *opts, int optcode, int *result) {
|
|||
|
||||
while (opt->desc != ODESC_END) {
|
||||
if (opt->desc != ODESC_DONE && opt->desc->optcode == optcode) {
|
||||
*result = opt->value.u_int;
|
||||
switch (opt->desc->type) {
|
||||
case TYPE_INT: *result = opt->value.u_int; break;
|
||||
case TYPE_STRING: *result = strtol(opt->value.u_string, NULL, 0);
|
||||
break;
|
||||
default: Error2("cannot convert type %d of option %s to int",
|
||||
opt->desc->type, opt->desc->defname);
|
||||
opt->desc = ODESC_ERROR;
|
||||
return -1;
|
||||
}
|
||||
opt->desc = ODESC_DONE;
|
||||
return 0;
|
||||
}
|
||||
|
@ -2515,7 +2523,7 @@ int retropt_bind(struct opt *opts,
|
|||
{
|
||||
bool tight = false;
|
||||
struct sockaddr_un *s_un = (struct sockaddr_un *)sa;
|
||||
*salen = xiosetunix(s_un, bindname, false, tight);
|
||||
*salen = xiosetunix(af, s_un, bindname, false, tight);
|
||||
}
|
||||
break;
|
||||
#endif /* WITH_UNIX */
|
||||
|
|
|
@ -499,7 +499,8 @@ enum e_optcode {
|
|||
OPT_PIPES,
|
||||
/*OPT_PORT,*/
|
||||
OPT_PROMPT, /* readline */
|
||||
OPT_PROTOCOL_FAMILY,
|
||||
OPT_PROTOCOL, /* 6=TCP, 17=UDP */
|
||||
OPT_PROTOCOL_FAMILY, /* 1=PF_UNIX, 2=PF_INET, 10=PF_INET6 */
|
||||
OPT_PROXYPORT,
|
||||
OPT_PROXY_AUTHORIZATION,
|
||||
OPT_PROXY_RESOLVE,
|
||||
|
@ -593,9 +594,7 @@ enum e_optcode {
|
|||
#ifdef SO_PRIORITY
|
||||
OPT_SO_PRIORITY,
|
||||
#endif
|
||||
#ifdef SO_PROTOTYPE
|
||||
OPT_SO_PROTOTYPE,
|
||||
#endif
|
||||
OPT_SO_RCVBUF,
|
||||
OPT_SO_RCVBUF_LATE,
|
||||
#ifdef SO_RCVLOWAT
|
||||
|
@ -771,7 +770,8 @@ enum e_optcode {
|
|||
|
||||
/* keep consistent with xiohelp.c:optionphasenames ! */
|
||||
enum e_phase {
|
||||
PH_ALL, /* not for options; use in apply funcs to say "all phases" */
|
||||
PH_ALL, /* not for option definitions; use in apply funcs to
|
||||
say "all phases" */
|
||||
PH_INIT, /* retrieving info from original state */
|
||||
PH_EARLY, /* before any other processing */
|
||||
PH_PREOPEN, /* before file descriptor is created/opened */
|
||||
|
|
Loading…
Reference in a new issue