reworked so-type, so-prototype

This commit is contained in:
Gerhard Rieger 2008-09-20 23:47:06 +02:00
parent b6c2d46008
commit 376b9d50c3
22 changed files with 293 additions and 253 deletions

View file

@ -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

View file

@ -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"

View file

@ -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()

View file

@ -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"},

View file

@ -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

View file

@ -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");

View file

@ -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;

View file

@ -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;
}

View file

@ -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,

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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})",

View file

@ -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",

View file

@ -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) {

View file

@ -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;
}

View file

@ -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) */

View file

@ -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,

View file

@ -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);

View file

@ -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);

View file

@ -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) */

View file

@ -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 */

View file

@ -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 */