libradius: Use poll(2) to wait for RADIUS responses

This commit is contained in:
Martin Willi
2014-11-21 11:16:48 +01:00
parent fc829ec9fb
commit 1abaff6a3c
+20 -25
View File
@@ -129,7 +129,7 @@ METHOD(radius_socket_t, request, radius_message_t*,
private_radius_socket_t *this, radius_message_t *request) private_radius_socket_t *this, radius_message_t *request)
{ {
chunk_t data; chunk_t data;
int i, *fd; int i, *fd, retransmit = 0;
u_int16_t port; u_int16_t port;
rng_t *rng = NULL; rng_t *rng = NULL;
@@ -166,44 +166,42 @@ METHOD(radius_socket_t, request, radius_message_t*,
for (i = 2; i <= 5; i++) for (i = 2; i <= 5; i++)
{ {
radius_message_t *response; radius_message_t *response;
bool retransmit = FALSE;
struct timeval tv;
char buf[4096]; char buf[4096];
fd_set fds;
int res; int res;
struct pollfd pfd = {
.fd = *fd,
.events = POLLIN,
};
if (retransmit)
{
DBG1(DBG_CFG, "retransmitting RADIUS %N (attempt %d)",
radius_message_code_names, request->get_code(request),
retransmit);
}
if (send(*fd, data.ptr, data.len, 0) != data.len) if (send(*fd, data.ptr, data.len, 0) != data.len)
{ {
DBG1(DBG_CFG, "sending RADIUS message failed: %s", strerror(errno)); DBG1(DBG_CFG, "sending RADIUS message failed: %s", strerror(errno));
return NULL; return NULL;
} }
tv.tv_sec = i; res = poll(&pfd, 1, i * 1000);
tv.tv_usec = 0;
while (TRUE)
{
FD_ZERO(&fds);
FD_SET(*fd, &fds);
res = select((*fd) + 1, &fds, NULL, NULL, &tv);
/* TODO: updated tv to time not waited. Linux does this for us. */
if (res < 0) if (res < 0)
{ /* failed */ {
DBG1(DBG_CFG, "waiting for RADIUS message failed: %s", DBG1(DBG_CFG, "waiting for RADIUS message failed: %s",
strerror(errno)); strerror(errno));
break; return NULL;
} }
if (res == 0) if (res == 0)
{ /* timeout */ { /* timeout */
DBG1(DBG_CFG, "retransmitting RADIUS message"); retransmit++;
retransmit = TRUE; continue;
break;
} }
res = recv(*fd, buf, sizeof(buf), MSG_DONTWAIT); res = recv(*fd, buf, sizeof(buf), MSG_DONTWAIT);
if (res <= 0) if (res <= 0)
{ {
DBG1(DBG_CFG, "receiving RADIUS message failed: %s", DBG1(DBG_CFG, "receiving RADIUS message failed: %s",
strerror(errno)); strerror(errno));
break; return NULL;
} }
response = radius_message_parse(chunk_create(buf, res)); response = radius_message_parse(chunk_create(buf, res));
if (response) if (response)
@@ -217,13 +215,10 @@ METHOD(radius_socket_t, request, radius_message_t*,
response->destroy(response); response->destroy(response);
} }
DBG1(DBG_CFG, "received invalid RADIUS message, ignored"); DBG1(DBG_CFG, "received invalid RADIUS message, ignored");
return NULL;
} }
if (!retransmit) DBG1(DBG_CFG, "RADIUS %N timed out after %d retransmits",
{ radius_message_code_names, request->get_code(request), retransmit - 1);
break;
}
}
DBG1(DBG_CFG, "RADIUS server is not responding");
return NULL; return NULL;
} }