libradius: Use poll(2) to wait for RADIUS responses
This commit is contained in:
@@ -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,64 +166,59 @@ 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;
|
if (res < 0)
|
||||||
|
|
||||||
while (TRUE)
|
|
||||||
{
|
{
|
||||||
FD_ZERO(&fds);
|
DBG1(DBG_CFG, "waiting for RADIUS message failed: %s",
|
||||||
FD_SET(*fd, &fds);
|
strerror(errno));
|
||||||
res = select((*fd) + 1, &fds, NULL, NULL, &tv);
|
return NULL;
|
||||||
/* TODO: updated tv to time not waited. Linux does this for us. */
|
|
||||||
if (res < 0)
|
|
||||||
{ /* failed */
|
|
||||||
DBG1(DBG_CFG, "waiting for RADIUS message failed: %s",
|
|
||||||
strerror(errno));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (res == 0)
|
|
||||||
{ /* timeout */
|
|
||||||
DBG1(DBG_CFG, "retransmitting RADIUS message");
|
|
||||||
retransmit = TRUE;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
res = recv(*fd, buf, sizeof(buf), MSG_DONTWAIT);
|
|
||||||
if (res <= 0)
|
|
||||||
{
|
|
||||||
DBG1(DBG_CFG, "receiving RADIUS message failed: %s",
|
|
||||||
strerror(errno));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
response = radius_message_parse(chunk_create(buf, res));
|
|
||||||
if (response)
|
|
||||||
{
|
|
||||||
if (response->verify(response,
|
|
||||||
request->get_authenticator(request), this->secret,
|
|
||||||
this->hasher, this->signer))
|
|
||||||
{
|
|
||||||
return response;
|
|
||||||
}
|
|
||||||
response->destroy(response);
|
|
||||||
}
|
|
||||||
DBG1(DBG_CFG, "received invalid RADIUS message, ignored");
|
|
||||||
}
|
}
|
||||||
if (!retransmit)
|
if (res == 0)
|
||||||
|
{ /* timeout */
|
||||||
|
retransmit++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
res = recv(*fd, buf, sizeof(buf), MSG_DONTWAIT);
|
||||||
|
if (res <= 0)
|
||||||
{
|
{
|
||||||
break;
|
DBG1(DBG_CFG, "receiving RADIUS message failed: %s",
|
||||||
|
strerror(errno));
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
response = radius_message_parse(chunk_create(buf, res));
|
||||||
|
if (response)
|
||||||
|
{
|
||||||
|
if (response->verify(response,
|
||||||
|
request->get_authenticator(request), this->secret,
|
||||||
|
this->hasher, this->signer))
|
||||||
|
{
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
response->destroy(response);
|
||||||
|
}
|
||||||
|
DBG1(DBG_CFG, "received invalid RADIUS message, ignored");
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
DBG1(DBG_CFG, "RADIUS server is not responding");
|
DBG1(DBG_CFG, "RADIUS %N timed out after %d retransmits",
|
||||||
|
radius_message_code_names, request->get_code(request), retransmit - 1);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user