Use recvfrom() in UDP listening mode to get remote address.

Also move a few #ifdef from .c to .h to make the code slightly more readable.
This commit is contained in:
Sam Hocevar 2017-09-06 13:55:49 +02:00
parent 6909d2c3de
commit 00dec123da
2 changed files with 48 additions and 30 deletions

View File

@ -36,6 +36,18 @@
# include <sys/filio.h> # include <sys/filio.h>
#endif /* FIONBIO */ #endif /* FIONBIO */
#if HAVE_SOCKLEN_T
# define SOCKLEN_T socklen_t
#else
# define SOCKLEN_T int
#endif
#if _WIN32
# define FIONBIO_ARG_T u_long
#else
# define FIONBIO_ARG_T int
#endif
#if _WIN32 #if _WIN32
/* _WIN32 doesn't really have WSAEAGAIN */ /* _WIN32 doesn't really have WSAEAGAIN */
# ifndef WSAEAGAIN # ifndef WSAEAGAIN

View File

@ -287,11 +287,8 @@ void addServer(char *bindAddress, int bindPort, int bindProto,
closesocket(fd); closesocket(fd);
} }
} }
#if _WIN32
u_long ioctltmp; FIONBIO_ARG_T ioctltmp;
#else
int ioctltmp;
#endif
ioctlsocket(fd, FIONBIO, &ioctltmp); ioctlsocket(fd, FIONBIO, &ioctltmp);
if (getAddress(connectAddress, &iaddr) < 0) { if (getAddress(connectAddress, &iaddr) < 0) {
/* Warn -- don't exit. */ /* Warn -- don't exit. */
@ -543,8 +540,12 @@ static void handleWrite(ConnectionInfo *cnx, Socket *socket, Socket *other_socke
static void handleClose(ConnectionInfo *cnx, Socket *socket, Socket *other_socket) static void handleClose(ConnectionInfo *cnx, Socket *socket, Socket *other_socket)
{ {
cnx->coClosing = 1; cnx->coClosing = 1;
/* One end fizzled out, so make sure we're all done with that */ if (socket->proto == protoTcp) {
closesocket(socket->fd); /* One end fizzled out, so make sure we're all done with that */
closesocket(socket->fd);
} else /* if (socket->proto == protoUdp) */ {
/* Nothing to do in UDP mode */
}
socket->fd = INVALID_SOCKET; socket->fd = INVALID_SOCKET;
if (other_socket->fd != INVALID_SOCKET) { if (other_socket->fd != INVALID_SOCKET) {
#ifndef __linux__ #ifndef __linux__
@ -572,30 +573,35 @@ static void handleAccept(ServerInfo const *srv)
} }
struct sockaddr addr; struct sockaddr addr;
#if HAVE_SOCKLEN_T SOCKLEN_T addrlen = sizeof(addr);
socklen_t addrlen;
#else
int addrlen;
#endif
addrlen = sizeof(addr);
SOCKET nfd = accept(srv->fd, &addr, &addrlen);
if (nfd == INVALID_SOCKET) {
syslog(LOG_ERR, "accept(%d): %m", srv->fd);
logEvent(NULL, srv, logAcceptFailed);
return;
}
#if _WIN32 SOCKET nfd;
u_long ioctltmp; /* Get remote address using accept() in TCP mode, recvfrom()
#else in UDP mode. */
int ioctltmp; if (srv->fromProto == protoTcp) {
#endif nfd = accept(srv->fd, &addr, &addrlen);
ioctlsocket(nfd, FIONBIO, &ioctltmp); if (nfd == INVALID_SOCKET) {
syslog(LOG_ERR, "accept(%d): %m", srv->fd);
logEvent(NULL, srv, logAcceptFailed);
return;
}
FIONBIO_ARG_T ioctltmp;
ioctlsocket(nfd, FIONBIO, &ioctltmp);
#ifndef _WIN32 #ifndef _WIN32
int tmp = 0; int tmp = 0;
setsockopt(nfd, SOL_SOCKET, SO_LINGER, &tmp, sizeof(tmp)); setsockopt(nfd, SOL_SOCKET, SO_LINGER, &tmp, sizeof(tmp));
#endif #endif
} else /* if (srv->fromProto == protoUdp) */ {
nfd = srv->fd;
ssize_t ret = recvfrom(srv->fd, NULL, 0, MSG_PEEK,
&addr, &addrlen);
if (ret < 0) {
syslog(LOG_ERR, "recvfrom(%d): %m", srv->fd);
logEvent(NULL, srv, logAcceptFailed);
return;
}
}
cnx->local.fd = INVALID_SOCKET; cnx->local.fd = INVALID_SOCKET;
cnx->local.proto = srv->toProto; cnx->local.proto = srv->toProto;
@ -653,15 +659,15 @@ static void handleAccept(ServerInfo const *srv)
#ifndef _WIN32 #ifndef _WIN32
#ifdef __linux__ #ifdef __linux__
tmp = 0; int tmp = 0;
setsockopt(cnx->local.fd, SOL_SOCKET, SO_LINGER, &tmp, sizeof(tmp)); setsockopt(cnx->local.fd, SOL_SOCKET, SO_LINGER, &tmp, sizeof(tmp));
#else #else
tmp = 1024; int tmp = 1024;
setsockopt(cnx->local.fd, SOL_SOCKET, SO_SNDBUF, &tmp, sizeof(tmp)); setsockopt(cnx->local.fd, SOL_SOCKET, SO_SNDBUF, &tmp, sizeof(tmp));
#endif /* __linux__ */ #endif /* __linux__ */
#endif /* _WIN32 */ #endif /* _WIN32 */
ioctltmp = 1; FIONBIO_ARG_T ioctltmp = 1;
ioctlsocket(cnx->local.fd, FIONBIO, &ioctltmp); ioctlsocket(cnx->local.fd, FIONBIO, &ioctltmp);
if (connect(cnx->local.fd, (struct sockaddr *)&saddr, if (connect(cnx->local.fd, (struct sockaddr *)&saddr,