mirror of
https://repo.or.cz/socat.git
synced 2024-12-22 15:32:35 +00:00
Combined Bind() calls in xiobind(); fixed UDP-SENDTO lowport bug
This commit is contained in:
parent
56a56e127c
commit
d8ee49007e
8 changed files with 194 additions and 180 deletions
4
CHANGES
4
CHANGES
|
@ -27,6 +27,10 @@ Corrections:
|
|||
The rawer option failed because it tried to clear CREAD.
|
||||
Test: RAWER
|
||||
|
||||
UDP-SEND and UPD-SENDTO with option lowport always bound to port 1
|
||||
instead of a free port in range 640..1023
|
||||
Test: UDP_LOWPORT
|
||||
|
||||
Porting:
|
||||
OpenSSL, at least 1.1 on Ubuntu, crashed with SIGSEGV under certain
|
||||
conditions: client connection to server with certificate with empty
|
||||
|
|
41
test.sh
41
test.sh
|
@ -15496,6 +15496,47 @@ esac
|
|||
PORT=$((PORT+1))
|
||||
N=$((N+1))
|
||||
|
||||
# Up to 1.7.4.3 there was a bug with the lowport option:
|
||||
# Active addresses UDP-SEND, UDP-SENDTO always bound to port 1 instead of
|
||||
# 640..1023
|
||||
NAME=UDP_LOWPORT
|
||||
case "$TESTS" in
|
||||
*%$N%*|*%functions%*|*%bugs%*|*%socket%*|*%$NAME%*)
|
||||
TEST="$NAME: UDP4-SEND with lowport"
|
||||
# Run Socat with UDP4-SEND:...,lowport and full logging and check the
|
||||
# parameters of bind() call. It port is in the range 640..1023 the test
|
||||
# succeeded.
|
||||
if ! eval $NUMCOND; then :; else
|
||||
tf="$td/test$N.stdout"
|
||||
te="$td/test$N.stderr"
|
||||
tdiff="$td/test$N.diff"
|
||||
da="test$N $(date) $RANDOM"
|
||||
CMD="$TRACE $SOCAT $opts -d -d -d -d /dev/null UDP4-SENDTO:$LOCALHOST:$PORT,lowport"
|
||||
printf "test $F_n $TEST... " $N
|
||||
$CMD >/dev/null 2>"${te}"
|
||||
rc1=$?
|
||||
LOWPORT=$(grep 'D bind(.*:' $te |sed 's/.*:\([0-9][0-9]*\),.*/\1/')
|
||||
#echo "LOWPORT=\"$LOWPORT\"" >&2
|
||||
#type socat >&2
|
||||
if [[ $LOWPORT =~ [0-9][0-9]* ]] && [ "$LOWPORT" -ge 640 -a "$LOWPORT" -le 1023 ]; then
|
||||
$PRINTF "$OK\n"
|
||||
if [ "$VERBOSE" ]; then
|
||||
echo "$CMD" >&2
|
||||
fi
|
||||
numOK=$((numOK+1))
|
||||
else
|
||||
$PRINTF "$FAILED\n"
|
||||
echo "$CMD" >&2
|
||||
cat "${te}" >&2
|
||||
numFAIL=$((numFAIL+1))
|
||||
listFAIL="$listFAIL $N"
|
||||
fi
|
||||
fi # NUMCOND
|
||||
;;
|
||||
esac
|
||||
PORT=$((PORT+1))
|
||||
N=$((N+1))
|
||||
|
||||
# end of common tests
|
||||
|
||||
##################################################################################
|
||||
|
|
|
@ -69,7 +69,7 @@ int _xioopen_interface(const char *ifname,
|
|||
|
||||
return
|
||||
_xioopen_dgram_sendto(needbind?&us:NULL, uslen,
|
||||
opts, xioflags, xfd, groups, pf, socktype, 0);
|
||||
opts, xioflags, xfd, groups, pf, socktype, 0, 0);
|
||||
}
|
||||
|
||||
static
|
||||
|
|
|
@ -143,7 +143,7 @@ int _xioopen_rawip_sendto(const char *hostname, const char *protname,
|
|||
}
|
||||
return
|
||||
_xioopen_dgram_sendto(needbind?&us:NULL, uslen,
|
||||
opts, xioflags, xfd, groups, *pf, socktype, ipproto);
|
||||
opts, xioflags, xfd, groups, *pf, socktype, ipproto, 0);
|
||||
}
|
||||
|
||||
|
||||
|
|
301
xio-socket.c
301
xio-socket.c
|
@ -63,6 +63,14 @@ xiolog_ancillary_socket(struct cmsghdr *cmsg, int *num,
|
|||
char *nambuff, int namlen,
|
||||
char *envbuff, int envlen,
|
||||
char *valbuff, int vallen);
|
||||
static int xiobind(
|
||||
struct single *xfd,
|
||||
union sockaddr_union *us,
|
||||
size_t uslen,
|
||||
struct opt *opts,
|
||||
int pf,
|
||||
bool alt,
|
||||
int level);
|
||||
|
||||
|
||||
#if WITH_GENERICSOCKET
|
||||
|
@ -457,7 +465,7 @@ int _xioopen_socket_sendto(const char *pfname, const char *type,
|
|||
|
||||
return
|
||||
_xioopen_dgram_sendto(needbind?&us:NULL, uslen,
|
||||
opts, xioflags, xfd, groups, pf, socktype, proto);
|
||||
opts, xioflags, xfd, groups, pf, socktype, proto, 0);
|
||||
}
|
||||
|
||||
|
||||
|
@ -775,111 +783,9 @@ int _xioopen_connect(struct single *xfd, union sockaddr_union *us, size_t uslen,
|
|||
|
||||
applyopts_cloexec(xfd->fd, opts);
|
||||
|
||||
#if WITH_UNIX
|
||||
if (pf == PF_UNIX && us != NULL) {
|
||||
applyopts_named(us->un.sun_path, opts, PH_PREOPEN);
|
||||
if (xiobind(xfd, us, uslen, opts, pf, alt, level) < 0) {
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
applyopts(xfd->fd, opts, PH_PREBIND);
|
||||
applyopts(xfd->fd, opts, PH_BIND);
|
||||
#if WITH_TCP || WITH_UDP
|
||||
if (alt) {
|
||||
union sockaddr_union sin, *sinp;
|
||||
unsigned short *port, i, N;
|
||||
div_t dv;
|
||||
|
||||
/* prepare sockaddr for bind probing */
|
||||
if (us) {
|
||||
sinp = us;
|
||||
} else {
|
||||
if (them->sa_family == AF_INET) {
|
||||
socket_in_init(&sin.ip4);
|
||||
#if WITH_IP6
|
||||
} else {
|
||||
socket_in6_init(&sin.ip6);
|
||||
#endif
|
||||
}
|
||||
sinp = &sin;
|
||||
}
|
||||
if (them->sa_family == AF_INET) {
|
||||
port = &sin.ip4.sin_port;
|
||||
#if WITH_IP6
|
||||
} else if (them->sa_family == AF_INET6) {
|
||||
port = &sin.ip6.sin6_port;
|
||||
#endif
|
||||
} else {
|
||||
port = 0; /* just to make compiler happy */
|
||||
}
|
||||
/* combine random+step variant to quickly find a free port when only
|
||||
few are in use, and certainly find a free port in defined time even
|
||||
if there are almost all in use */
|
||||
/* dirt 1: having tcp/udp code in socket function */
|
||||
/* dirt 2: using a time related system call for init of random */
|
||||
{
|
||||
/* generate a random port, with millisecond random init */
|
||||
#if 0
|
||||
struct timeb tb;
|
||||
ftime(&tb);
|
||||
srandom(tb.time*1000+tb.millitm);
|
||||
#else
|
||||
struct timeval tv;
|
||||
struct timezone tz;
|
||||
tz.tz_minuteswest = 0;
|
||||
tz.tz_dsttime = 0;
|
||||
if ((result = Gettimeofday(&tv, &tz)) < 0) {
|
||||
Warn2("gettimeofday(%p, {0,0}): %s", &tv, strerror(errno));
|
||||
}
|
||||
srandom(tv.tv_sec*1000000+tv.tv_usec);
|
||||
#endif
|
||||
}
|
||||
dv = div(random(), IPPORT_RESERVED-XIO_IPPORT_LOWER);
|
||||
i = N = XIO_IPPORT_LOWER + dv.rem;
|
||||
do { /* loop over lowport bind() attempts */
|
||||
*port = htons(i);
|
||||
if (Bind(xfd->fd, &sinp->soa, sizeof(*sinp)) < 0) {
|
||||
Msg4(errno==EADDRINUSE?E_INFO:level,
|
||||
"bind(%d, {%s}, "F_Zd"): %s", xfd->fd,
|
||||
sockaddr_info(&sinp->soa, sizeof(*sinp), infobuff, sizeof(infobuff)),
|
||||
sizeof(*sinp), strerror(errno));
|
||||
if (errno != EADDRINUSE) {
|
||||
Close(xfd->fd);
|
||||
return STAT_RETRYLATER;
|
||||
}
|
||||
} else {
|
||||
break; /* could bind to port, good, continue past loop */
|
||||
}
|
||||
--i; if (i < XIO_IPPORT_LOWER) i = IPPORT_RESERVED-1;
|
||||
if (i == N) {
|
||||
Msg(level, "no low port available");
|
||||
/*errno = EADDRINUSE; still assigned */
|
||||
Close(xfd->fd);
|
||||
return STAT_RETRYLATER;
|
||||
}
|
||||
} while (i != N);
|
||||
} else
|
||||
#endif /* WITH_TCP || WITH_UDP */
|
||||
|
||||
if (us) {
|
||||
#if WITH_UNIX
|
||||
if (pf == PF_UNIX && us != NULL) {
|
||||
applyopts_named(us->un.sun_path, opts, PH_PREOPEN);
|
||||
}
|
||||
#endif
|
||||
if (Bind(xfd->fd, &us->soa, uslen) < 0) {
|
||||
Msg4(level, "bind(%d, {%s}, "F_Zd"): %s",
|
||||
xfd->fd, sockaddr_info(&us->soa, uslen, infobuff, sizeof(infobuff)),
|
||||
uslen, strerror(errno));
|
||||
Close(xfd->fd);
|
||||
return STAT_RETRYLATER;
|
||||
}
|
||||
}
|
||||
#if WITH_UNIX
|
||||
if (pf == PF_UNIX && us != NULL) {
|
||||
applyopts_named(us->un.sun_path, opts, PH_PASTOPEN);
|
||||
}
|
||||
#endif
|
||||
|
||||
applyopts(xfd->fd, opts, PH_PASTBIND);
|
||||
|
||||
applyopts(xfd->fd, opts, PH_CONNECT);
|
||||
|
||||
|
@ -1116,7 +1022,7 @@ int _xioopen_dgram_sendto(/* them is already in xfd->peersa */
|
|||
union sockaddr_union *us, socklen_t uslen,
|
||||
struct opt *opts,
|
||||
int xioflags, xiosingle_t *xfd, unsigned groups,
|
||||
int pf, int socktype, int ipproto) {
|
||||
int pf, int socktype, int ipproto, bool alt) {
|
||||
int level = E_ERROR;
|
||||
union sockaddr_union la; socklen_t lalen = sizeof(la);
|
||||
char infobuff[256];
|
||||
|
@ -1138,30 +1044,9 @@ int _xioopen_dgram_sendto(/* them is already in xfd->peersa */
|
|||
|
||||
applyopts_cloexec(xfd->fd, opts);
|
||||
|
||||
#if WITH_UNIX
|
||||
if (pf == PF_UNIX && us != NULL) {
|
||||
applyopts_named(us->un.sun_path, opts, PH_PREOPEN);
|
||||
if (xiobind(xfd, us, uslen, opts, pf, alt, level) < 0) {
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
applyopts(xfd->fd, opts, PH_PREBIND);
|
||||
applyopts(xfd->fd, opts, PH_BIND);
|
||||
|
||||
if (us) {
|
||||
if (Bind(xfd->fd, &us->soa, uslen) < 0) {
|
||||
Msg4(level, "bind(%d, {%s}, "F_socklen"): %s",
|
||||
xfd->fd, sockaddr_info(&us->soa, uslen, infobuff, sizeof(infobuff)),
|
||||
uslen, strerror(errno));
|
||||
Close(xfd->fd);
|
||||
return STAT_RETRYLATER;
|
||||
}
|
||||
}
|
||||
#if WITH_UNIX
|
||||
if (pf == PF_UNIX && us != NULL) {
|
||||
applyopts_named(us->un.sun_path, opts, PH_PASTOPEN);
|
||||
}
|
||||
#endif
|
||||
|
||||
applyopts(xfd->fd, opts, PH_PASTBIND);
|
||||
|
||||
/*applyopts(xfd->fd, opts, PH_CONNECT);*/
|
||||
|
||||
|
@ -1333,25 +1218,16 @@ int _xioopen_dgram_recvfrom(struct single *xfd, int xioflags,
|
|||
|
||||
applyopts_cloexec(xfd->fd, opts);
|
||||
|
||||
applyopts(xfd->fd, opts, PH_PREBIND);
|
||||
applyopts(xfd->fd, opts, PH_BIND);
|
||||
if ((us != NULL) && Bind(xfd->fd, us, uslen) < 0) {
|
||||
Msg4(level, "bind(%d, {%s}, "F_socklen"): %s", xfd->fd,
|
||||
sockaddr_info(us, uslen, infobuff, sizeof(infobuff)), uslen,
|
||||
strerror(errno));
|
||||
Close(xfd->fd);
|
||||
return STAT_RETRYLATER;
|
||||
if (xiobind(xfd, (union sockaddr_union *)us, uslen,
|
||||
opts, pf, 0, level) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
applyopts(xfd->fd, opts, PH_PASTBIND);
|
||||
|
||||
#if WITH_UNIX
|
||||
if (pf == AF_UNIX && us != NULL) {
|
||||
applyopts_named(((struct sockaddr_un *)us)->sun_path, opts, PH_FD);
|
||||
}
|
||||
#endif
|
||||
|
||||
applyopts(xfd->fd, opts, PH_PASTBIND);
|
||||
#if WITH_UNIX
|
||||
if (pf == AF_UNIX && us != NULL) {
|
||||
/*applyopts_early(((struct sockaddr_un *)us)->sun_path, opts);*/
|
||||
applyopts_named(((struct sockaddr_un *)us)->sun_path, opts, PH_EARLY);
|
||||
applyopts_named(((struct sockaddr_un *)us)->sun_path, opts, PH_PREOPEN);
|
||||
|
@ -1592,7 +1468,6 @@ int _xioopen_dgram_recv(struct single *xfd, int xioflags,
|
|||
struct opt *opts, int pf, int socktype, int proto,
|
||||
int level) {
|
||||
char *rangename;
|
||||
char infobuff[256];
|
||||
|
||||
if (applyopts_single(xfd, opts, PH_INIT) < 0) return STAT_NORETRY;
|
||||
|
||||
|
@ -1605,26 +1480,13 @@ int _xioopen_dgram_recv(struct single *xfd, int xioflags,
|
|||
|
||||
applyopts_cloexec(xfd->fd, opts);
|
||||
|
||||
applyopts(xfd->fd, opts, PH_PREBIND);
|
||||
applyopts(xfd->fd, opts, PH_BIND);
|
||||
if ((us != NULL) && Bind(xfd->fd, us, uslen) < 0) {
|
||||
Msg4(level, "bind(%d, {%s}, "F_socklen"): %s", xfd->fd,
|
||||
sockaddr_info(us, uslen, infobuff, sizeof(infobuff)), uslen,
|
||||
strerror(errno));
|
||||
Close(xfd->fd);
|
||||
return STAT_RETRYLATER;
|
||||
if (xiobind(xfd, (union sockaddr_union *)us, uslen, opts, pf, 0, level) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
#if WITH_UNIX
|
||||
if (pf == AF_UNIX && us != NULL) {
|
||||
applyopts_named(((struct sockaddr_un *)us)->sun_path, opts, PH_FD);
|
||||
}
|
||||
#endif
|
||||
|
||||
applyopts_single(xfd, opts, PH_PASTBIND);
|
||||
applyopts(xfd->fd, opts, PH_PASTBIND);
|
||||
#if WITH_UNIX
|
||||
if (pf == AF_UNIX && us != NULL) {
|
||||
/*applyopts_early(((struct sockaddr_un *)us)->sun_path, opts);*/
|
||||
applyopts_named(((struct sockaddr_un *)us)->sun_path, opts, PH_EARLY);
|
||||
applyopts_named(((struct sockaddr_un *)us)->sun_path, opts, PH_PREOPEN);
|
||||
|
@ -2262,3 +2124,124 @@ xiosocketpair(struct opt *opts, int pf, int socktype, int proto, int sv[2]) {
|
|||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
int xiobind(
|
||||
struct single *xfd,
|
||||
union sockaddr_union *us,
|
||||
size_t uslen,
|
||||
struct opt *opts,
|
||||
int pf,
|
||||
bool alt,
|
||||
int level)
|
||||
{
|
||||
char infobuff[256];
|
||||
int result;
|
||||
|
||||
#if WITH_UNIX
|
||||
if (pf == PF_UNIX && us != NULL) {
|
||||
applyopts_named(us->un.sun_path, opts, PH_PREOPEN);
|
||||
}
|
||||
#endif
|
||||
applyopts(xfd->fd, opts, PH_PREBIND);
|
||||
applyopts(xfd->fd, opts, PH_BIND);
|
||||
#if WITH_TCP || WITH_UDP
|
||||
if (alt) {
|
||||
union sockaddr_union sin, *sinp;
|
||||
unsigned short *port, i, N;
|
||||
div_t dv;
|
||||
|
||||
/* prepare sockaddr for bind probing */
|
||||
if (us) {
|
||||
sinp = us;
|
||||
} else {
|
||||
if (pf == AF_INET) {
|
||||
socket_in_init(&sin.ip4);
|
||||
#if WITH_IP6
|
||||
} else {
|
||||
socket_in6_init(&sin.ip6);
|
||||
#endif
|
||||
}
|
||||
sinp = &sin;
|
||||
}
|
||||
if (pf == AF_INET) {
|
||||
port = &sin.ip4.sin_port;
|
||||
#if WITH_IP6
|
||||
} else if (pf == AF_INET6) {
|
||||
port = &sin.ip6.sin6_port;
|
||||
#endif
|
||||
} else {
|
||||
port = 0; /* just to make compiler happy */
|
||||
}
|
||||
/* combine random+step variant to quickly find a free port when only
|
||||
few are in use, and certainly find a free port in defined time even
|
||||
if there are almost all in use */
|
||||
/* dirt 1: having tcp/udp code in socket function */
|
||||
/* dirt 2: using a time related system call for init of random */
|
||||
{
|
||||
/* generate a random port, with millisecond random init */
|
||||
#if 0
|
||||
struct timeb tb;
|
||||
ftime(&tb);
|
||||
srandom(tb.time*1000+tb.millitm);
|
||||
#else
|
||||
struct timeval tv;
|
||||
struct timezone tz;
|
||||
tz.tz_minuteswest = 0;
|
||||
tz.tz_dsttime = 0;
|
||||
if ((result = Gettimeofday(&tv, &tz)) < 0) {
|
||||
Warn2("gettimeofday(%p, {0,0}): %s", &tv, strerror(errno));
|
||||
}
|
||||
srandom(tv.tv_sec*1000000+tv.tv_usec);
|
||||
#endif
|
||||
}
|
||||
/* Note: IPPORT_RESERVED is from includes, 1024 */
|
||||
dv = div(random(), IPPORT_RESERVED-XIO_IPPORT_LOWER);
|
||||
i = N = XIO_IPPORT_LOWER + dv.rem;
|
||||
do { /* loop over lowport bind() attempts */
|
||||
*port = htons(i);
|
||||
if (Bind(xfd->fd, &sinp->soa, sizeof(*sinp)) < 0) {
|
||||
Msg4(errno==EADDRINUSE?E_INFO:level,
|
||||
"bind(%d, {%s}, "F_Zd"): %s", xfd->fd,
|
||||
sockaddr_info(&sinp->soa, sizeof(*sinp), infobuff, sizeof(infobuff)),
|
||||
sizeof(*sinp), strerror(errno));
|
||||
if (errno != EADDRINUSE) {
|
||||
Close(xfd->fd);
|
||||
return STAT_RETRYLATER;
|
||||
}
|
||||
} else {
|
||||
break; /* could bind to port, good, continue past loop */
|
||||
}
|
||||
--i; if (i < XIO_IPPORT_LOWER) i = IPPORT_RESERVED-1;
|
||||
if (i == N) {
|
||||
Msg(level, "no low port available");
|
||||
/*errno = EADDRINUSE; still assigned */
|
||||
Close(xfd->fd);
|
||||
return STAT_RETRYLATER;
|
||||
}
|
||||
} while (i != N);
|
||||
} else
|
||||
#endif /* WITH_TCP || WITH_UDP */
|
||||
|
||||
if (us) {
|
||||
#if WITH_UNIX
|
||||
if (pf == PF_UNIX && us != NULL) {
|
||||
applyopts_named(us->un.sun_path, opts, PH_PREOPEN);
|
||||
}
|
||||
#endif
|
||||
if (Bind(xfd->fd, &us->soa, uslen) < 0) {
|
||||
Msg4(level, "bind(%d, {%s}, "F_Zd"): %s",
|
||||
xfd->fd, sockaddr_info(&us->soa, uslen, infobuff, sizeof(infobuff)),
|
||||
uslen, strerror(errno));
|
||||
Close(xfd->fd);
|
||||
return STAT_RETRYLATER;
|
||||
}
|
||||
}
|
||||
#if WITH_UNIX
|
||||
if (pf == PF_UNIX && us != NULL) {
|
||||
applyopts_named(us->un.sun_path, opts, PH_PASTOPEN);
|
||||
}
|
||||
#endif
|
||||
|
||||
applyopts(xfd->fd, opts, PH_PASTBIND);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -102,7 +102,7 @@ int _xioopen_dgram_sendto(/* them is already in xfd->peersa */
|
|||
union sockaddr_union *us, socklen_t uslen,
|
||||
struct opt *opts,
|
||||
int xioflags, xiosingle_t *xfd, unsigned groups,
|
||||
int pf, int socktype, int ipproto);
|
||||
int pf, int socktype, int ipproto, bool alt);
|
||||
extern
|
||||
int _xioopen_dgram_recvfrom(struct single *xfd, int xioflags,
|
||||
struct sockaddr *us, socklen_t uslen,
|
||||
|
|
18
xio-udp.c
18
xio-udp.c
|
@ -410,26 +410,12 @@ int _xioopen_udp_sendto(const char *hostname, const char *servname,
|
|||
}
|
||||
|
||||
retropt_bool(opts, OPT_LOWPORT, &xfd->para.socket.ip.lowport);
|
||||
if (xfd->para.socket.ip.lowport) {
|
||||
switch (pf) {
|
||||
#if WITH_IP4
|
||||
case PF_INET:
|
||||
/*!!! this is buggy */
|
||||
us.ip4.sin_port = htons(xfd->para.socket.ip.lowport); break;
|
||||
#endif
|
||||
#if WITH_IP6
|
||||
case PF_INET6:
|
||||
/*!!! this is buggy */
|
||||
us.ip6.sin6_port = htons(xfd->para.socket.ip.lowport); break;
|
||||
#endif
|
||||
}
|
||||
needbind = true;
|
||||
}
|
||||
|
||||
xfd->dtype = XIODATA_RECVFROM;
|
||||
return _xioopen_dgram_sendto(needbind?&us:NULL, uslen,
|
||||
opts, xioflags, xfd, groups,
|
||||
pf, socktype, ipproto);
|
||||
pf, socktype, ipproto,
|
||||
xfd->para.socket.ip.lowport);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -411,7 +411,7 @@ static int xioopen_unix_sendto(int argc, const char *argv[], struct opt *opts, i
|
|||
return
|
||||
_xioopen_dgram_sendto(needbind?&us:NULL, uslen,
|
||||
opts, xioflags, xfd, groups,
|
||||
pf, socktype, protocol);
|
||||
pf, socktype, protocol, 0);
|
||||
}
|
||||
|
||||
|
||||
|
@ -690,7 +690,7 @@ _xioopen_unix_client(xiosingle_t *xfd, int xioflags, unsigned groups,
|
|||
if ((result =
|
||||
_xioopen_dgram_sendto(needbind?&us:NULL, uslen,
|
||||
opts, xioflags, xfd, groups,
|
||||
pf, SOCK_DGRAM, protocol))
|
||||
pf, SOCK_DGRAM, protocol, 0))
|
||||
== 0) {
|
||||
xfd->dtype = XIODATA_RECVFROM;
|
||||
break;
|
||||
|
|
Loading…
Reference in a new issue