📄 radius_client.c
字号:
/*
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation. See README and COPYING for
* more details.
Module Name:
radius_client.c
Revision History:
Who When What
-------- ---------- ----------------------------------------------
Jan, Lee Dec --2003 modified
*/
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <netinet/in.h>
#include <string.h>
#include <time.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include "rt61apd.h"
#include "radius.h"
#include "radius_client.h"
#include "eloop.h"
/* Defaults for RADIUS retransmit values (exponential backoff) */
#define RADIUS_CLIENT_FIRST_WAIT 1 /* seconds */
#define RADIUS_CLIENT_MAX_WAIT 120 /* seconds */
#define RADIUS_CLIENT_MAX_RETRIES 10 /* maximum number of retransmit attempts
* before entry is removed from retransmit list */
#define RADIUS_CLIENT_MAX_ENTRIES 30 /* maximum number of entries in retransmit
* list (oldest will be removed, if this limit is exceeded) */
#define RADIUS_CLIENT_NUM_FAILOVER 4 /* try to change RADIUS server after this
* many failed retry attempts */
static int
Radius_change_server(rtapd *rtapd, struct hostapd_radius_server *nserv,
struct hostapd_radius_server *oserv, int sock, int auth);
static void Radius_client_msg_free(struct radius_msg_list *req)
{
Radius_msg_free(req->msg);
free(req->msg);
free(req);
}
int Radius_client_register(rtapd *apd, RadiusType msg_type,
RadiusRxResult (*handler)(rtapd *apd, struct radius_msg *msg, struct radius_msg *req,
u8 *shared_secret, size_t shared_secret_len, void *data), void *data)
{
struct radius_rx_handler **handlers, *newh;
size_t *num;
handlers = &apd->radius->auth_handlers;
num = &apd->radius->num_auth_handlers;
newh = (struct radius_rx_handler *)
realloc(*handlers, (*num + 1) * sizeof(struct radius_rx_handler));
if (newh == NULL)
return -1;
newh[*num].handler = handler;
newh[*num].data = data;
(*num)++;
*handlers = newh;
return 0;
}
static int Radius_client_retransmit(rtapd *rtapd, struct radius_msg_list *entry, time_t now)
{
int s, res;
struct sockaddr_in addr;
s = rtapd->radius->auth_serv_sock;
if(entry == NULL)
{
//fprintf(stderr, " entry = null\n");
return 1;
}
/*debug cy*/
//fprintf(stderr, " Radius_client_retransmit socket=%d",s);
//fprintf(stderr, " entry=%d\n", entry);
//fprintf(stderr, "buf=%d, len=%d\n",entry->msg->buf,entry->msg->buf_used);
/* retransmit; remove entry if too many attempts */
entry->attempts++;
/* if (send(s, entry->msg->buf, entry->msg->buf_used, 0) < 0)
{
perror("send[retransmit RADIUS]");
fprintf(stderr, "reconnect socket\n");
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = rtapd->conf->auth_server->addr.s_addr;
addr.sin_port = htons(rtapd->conf->auth_server->port);
if (connect(s, (struct sockaddr *) &addr, sizeof(addr)) < 0)
{
perror("connect[radius]");
return -1;
}
}*/
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = rtapd->conf->auth_server->addr.s_addr;
addr.sin_port = htons(rtapd->conf->auth_server->port);
res = sendto(s, entry->msg->buf,entry->msg->buf_used, 0, (struct sockaddr *)&addr, sizeof(addr));
if (res < 0)
{
perror("sendto[RADIUS]");
/*fprintf(stderr, "reconnect socket\n");
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = rtapd->conf->auth_server->addr.s_addr;
addr.sin_port = htons(rtapd->conf->auth_server->port);
if (connect(s, (struct sockaddr *) &addr, sizeof(addr)) < 0)
{
perror("connect[radius]");
return -1;
}*/
}
entry->next_try = now + entry->next_wait;
entry->next_wait *= 2;
if (entry->next_wait > RADIUS_CLIENT_MAX_WAIT)
entry->next_wait = RADIUS_CLIENT_MAX_WAIT;
if (entry->attempts >= RADIUS_CLIENT_MAX_RETRIES)
{
DBGPRINT(RT_DEBUG_ERROR,"Removing un-ACKed RADIUS message due to too many failed retransmit attempts\n");
return 1;
}
//fprintf(stderr, " Radius_client_retransmit complete\n");
return 0;
}
static void Radius_client_timer(void *eloop_ctx, void *timeout_ctx)
{
rtapd *rtapd = eloop_ctx;
time_t now, first;
struct radius_msg_list *entry, *prev, *tmp;
int auth_failover = 0;
entry = rtapd->radius->msgs;
if (!entry)
return;
time(&now);
first = 0;
prev = NULL;
while (entry)
{
if (now >= entry->next_try && Radius_client_retransmit(rtapd, entry, now))
{
if (prev)
prev->next = entry->next;
else
rtapd->radius->msgs = entry->next;
tmp = entry;
entry = entry->next;
Radius_client_msg_free(tmp);
rtapd->radius->num_msgs--;
continue;
}
if (entry->attempts > RADIUS_CLIENT_NUM_FAILOVER)
{
if (entry->msg_type == RADIUS_AUTH)
auth_failover++;
}
if (first == 0 || entry->next_try < first)
first = entry->next_try;
prev = entry;
entry = entry->next;
}
if (rtapd->radius->msgs)
{
if (first < now)
first = now;
eloop_register_timeout(first - now, 0, Radius_client_timer, rtapd, NULL);
}
if (auth_failover && rtapd->conf->num_auth_servers > 1)
{
struct hostapd_radius_server *next, *old;
old = rtapd->conf->auth_server;
next = old + 1;
if (next > &(rtapd->conf->auth_servers[rtapd->conf->num_auth_servers - 1]))
next = rtapd->conf->auth_servers;
rtapd->conf->auth_server = next;
Radius_change_server(rtapd, next, old, rtapd->radius->auth_serv_sock, 1);
}
}
static void Radius_client_list_add(rtapd *rtapd, struct radius_msg *msg,
RadiusType msg_type, u8 *shared_secret, size_t shared_secret_len)
{
struct radius_msg_list *entry, *prev;
if (eloop_terminated())
{
/* No point in adding entries to retransmit queue since event
* loop has already been terminated. */
DBGPRINT(RT_DEBUG_TRACE,"eloop_terminate \n");
Radius_msg_free(msg);
free(msg);
return;
}
entry = malloc(sizeof(*entry));
// fprintf(stderr, " alloc entry=%d",entry);
if (entry == NULL)
{
DBGPRINT(RT_DEBUG_TRACE,"Failed to add RADIUS packet into retransmit list\n");
Radius_msg_free(msg);
free(msg);
return;
}
memset(entry, 0, sizeof(*entry));
entry->msg = msg;
entry->msg_type = msg_type;
entry->shared_secret = shared_secret;
entry->shared_secret_len = shared_secret_len;
time(&entry->first_try);
entry->next_try = entry->first_try + RADIUS_CLIENT_FIRST_WAIT;
entry->attempts = 1;
entry->next_wait = RADIUS_CLIENT_FIRST_WAIT * 2;
if (!rtapd->radius->msgs)
eloop_register_timeout(RADIUS_CLIENT_FIRST_WAIT, 0, Radius_client_timer, rtapd, NULL);
entry->next = rtapd->radius->msgs;
rtapd->radius->msgs = entry;
if (rtapd->radius->num_msgs >= RADIUS_CLIENT_MAX_ENTRIES)
{
DBGPRINT(RT_DEBUG_TRACE,"Removing the oldest un-ACKed RADIUS packet due to retransmit list limits.\n");
prev = NULL;
while (entry->next)
{
prev = entry;
entry = entry->next;
}
if (prev)
{
prev->next = NULL;
Radius_client_msg_free(entry);
}
} else
rtapd->radius->num_msgs++;
}
int Radius_client_send(rtapd *rtapd, struct radius_msg *msg, RadiusType msg_type)
{
u8 *shared_secret;
size_t shared_secret_len;
char *name;
int s, res;
struct sockaddr_in addr;
shared_secret = rtapd->conf->auth_server->shared_secret;
shared_secret_len = rtapd->conf->auth_server->shared_secret_len;
Radius_msg_finish(msg, shared_secret, shared_secret_len);
name = "authentication";
s = rtapd->radius->auth_serv_sock;
/*debug cy*/
//fprintf(stderr, " Radius_client_send socket=%d, buf=%d len=%d\n",s,msg->buf, msg->buf_used);
/* res = send(s, msg->buf, msg->buf_used, 0);
if (res < 0)
{
perror("send[RADIUS]");
fprintf(stderr, "reconnect socket\n");
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = rtapd->conf->auth_server->addr.s_addr;
addr.sin_port = htons(rtapd->conf->auth_server->port);
if (connect(s, (struct sockaddr *) &addr, sizeof(addr)) < 0)
{
perror("connect[radius]");
return -1;
}
}*/
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = rtapd->conf->auth_server->addr.s_addr;
addr.sin_port = htons(rtapd->conf->auth_server->port);
res = sendto(s, msg->buf,msg->buf_used, 0, (struct sockaddr *)&addr, sizeof(addr));
if (res < 0)
{
perror("sendto[RADIUS]");
/*fprintf(stderr, "reconnect socket\n");
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = rtapd->conf->auth_server->addr.s_addr;
addr.sin_port = htons(rtapd->conf->auth_server->port);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -