📄 radius_client.c
字号:
if (connect(s, (struct sockaddr *) &addr, sizeof(addr)) < 0)
{
perror("connect[radius]");
return -1;
}*/
}
Radius_client_list_add(rtapd, msg, msg_type, shared_secret, shared_secret_len);
/*debug cy*/
//fprintf(stderr, " Radius_client_send complete\n");
return res;
}
void Radius_client_receive(int sock, void *eloop_ctx, void *sock_ctx)
{
rtapd *rtapd = eloop_ctx;
RadiusType msg_type = (RadiusType) sock_ctx;
int len, i,len_80211hdr=24;
unsigned char buf[3000];
struct radius_msg *msg;
struct radius_rx_handler *handlers;
size_t num_handlers;
struct radius_msg_list *req, *prev_req;
struct sockaddr_in addr;
int length = sizeof(addr);
/*debug cy*/
//fprintf(stderr, " Radius_client_receive sock=%d\n",sock);
DBGPRINT(RT_DEBUG_INFO,"RADIUS_CLIENT_RECEIVE : msg_type= %d \n", msg_type);
/* len = recv(sock, buf, sizeof(buf), 0);*/
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);
len = recvfrom(sock, buf, sizeof(buf), 0, (struct sockaddr *)&addr, &length);
//fprintf(stderr, " Radius_client_receive1\n");
if (len < 0)
{
perror("recv[RADIUS]");
return;
}
if (len == sizeof(buf))
{
DBGPRINT(RT_DEBUG_ERROR,"Possibly too long UDP frame for our buffer - dropping it\n");
return;
}
if(addr.sin_addr.s_addr != rtapd->conf->auth_server->addr.s_addr)
{
fprintf(stderr, "addr not same\n");
return;
}
if(buf[0]!=0xff)
{
int i;
DBGPRINT(RT_DEBUG_INFO," r_dump %d bytes:",len);
for (i = 0; i < len_80211hdr; i++)
DBGPRINT(RT_DEBUG_INFO," %02x", buf[i]);
DBGPRINT(RT_DEBUG_INFO,"\n");
}
msg = Radius_msg_parse(buf, len);
if (msg == NULL)
{
DBGPRINT(RT_DEBUG_ERROR,"Parsing incoming RADIUS frame failed\n");
return;
}
handlers = rtapd->radius->auth_handlers;
num_handlers = rtapd->radius->num_auth_handlers;
prev_req = NULL;
req = rtapd->radius->msgs;
while (req)
{
/* TODO: also match by src addr:port of the packet when using
* alternative RADIUS servers (?) */
if ((req->msg_type == msg_type) && (req->msg->hdr->identifier == msg->hdr->identifier))
break;
prev_req = req;
req = req->next;
}
if (req == NULL)
{
goto fail;
}
/* Remove ACKed RADIUS packet from retransmit list */
if (prev_req)
prev_req->next = req->next;
else
rtapd->radius->msgs = req->next;
rtapd->radius->num_msgs--;
for (i = 0; i < num_handlers; i++)
{
RadiusRxResult res;
res = handlers[i].handler(rtapd, msg, req->msg, req->shared_secret, req->shared_secret_len, handlers[i].data);
switch (res)
{
case RADIUS_RX_PROCESSED:
Radius_msg_free(msg);
free(msg);
/* continue */
case RADIUS_RX_QUEUED:
Radius_client_msg_free(req);
return;
case RADIUS_RX_UNKNOWN:
/* continue with next handler */
break;
}
}
DBGPRINT(RT_DEBUG_ERROR,"No RADIUS RX handler found (type=%d code=%d id=%d) - dropping "
"packet\n", msg_type, msg->hdr->code, msg->hdr->identifier);
Radius_client_msg_free(req);
fail:
Radius_msg_free(msg);
free(msg);
}
u8 Radius_client_get_id(rtapd *rtapd)
{
struct radius_msg_list *entry, *prev, *remove;
u8 id = rtapd->radius->next_radius_identifier++;
/* remove entries with matching id from retransmit list to avoid
* using new reply from the RADIUS server with an old request */
entry = rtapd->radius->msgs;
prev = NULL;
while (entry)
{
if (entry->msg->hdr->identifier == id)
{
if (prev)
prev->next = entry->next;
else
rtapd->radius->msgs = entry->next;
remove = entry;
} else
remove = NULL;
prev = entry;
entry = entry->next;
if (remove)
Radius_client_msg_free(remove);
}
return id;
}
void Radius_client_flush(rtapd *rtapd)
{
struct radius_msg_list *entry, *prev;
if (!rtapd->radius)
return;
eloop_cancel_timeout(Radius_client_timer, rtapd, NULL);
entry = rtapd->radius->msgs;
rtapd->radius->msgs = NULL;
rtapd->radius->num_msgs = 0;
while (entry)
{
prev = entry;
entry = entry->next;
Radius_client_msg_free(prev);
}
}
static int
Radius_change_server(rtapd *rtapd, struct hostapd_radius_server *nserv,
struct hostapd_radius_server *oserv, int sock, int auth)
{
struct sockaddr_in serv;
if (!oserv || nserv->shared_secret_len != oserv->shared_secret_len ||
memcmp(nserv->shared_secret, oserv->shared_secret, nserv->shared_secret_len) != 0)
{
/* Pending RADIUS packets used different shared
* secret, so they would need to be modified. Could
* update all message authenticators and
* User-Passwords, etc. and retry with new server. For
* now, just drop all pending packets. */
Radius_client_flush(rtapd);
}
else
{
/* Reset retry counters for the new server */
struct radius_msg_list *entry;
entry = rtapd->radius->msgs;
while (entry)
{
entry->next_try = entry->first_try + RADIUS_CLIENT_FIRST_WAIT;
entry->attempts = 0;
entry->next_wait = RADIUS_CLIENT_FIRST_WAIT * 2;
entry = entry->next;
}
if (rtapd->radius->msgs)
{
eloop_cancel_timeout(Radius_client_timer, rtapd, NULL);
eloop_register_timeout(RADIUS_CLIENT_FIRST_WAIT, 0, Radius_client_timer, rtapd, NULL);
}
}
// bind before connect to assign local port
/*Comment by rory*/
memset(&serv, 0, sizeof(serv));
serv.sin_family = AF_INET;
//serv.sin_addr.s_addr = inet_addr("192.168.1.138");
serv.sin_addr.s_addr = htonl(INADDR_ANY);
serv.sin_port = htons(nserv->port);
if (bind(sock, (struct sockaddr *) &serv, sizeof(serv)) < 0)
{
perror("bind");
return -1;
}
/* memset(&serv, 0, sizeof(serv));
serv.sin_family = AF_INET;
serv.sin_addr.s_addr = nserv->addr.s_addr;
serv.sin_port = htons(nserv->port);
if (connect(sock, (struct sockaddr *) &serv, sizeof(serv)) < 0)
{
perror("connect[radius]");
return -1;
}*/
return 0;
}
static void Radius_retry_primary_timer(void *eloop_ctx, void *timeout_ctx)
{
rtapd *rtapd = eloop_ctx;
struct hostapd_radius_server *oserv;
if (rtapd->radius->auth_serv_sock >= 0 && rtapd->conf->auth_servers &&
rtapd->conf->auth_server != rtapd->conf->auth_servers)
{
oserv = rtapd->conf->auth_server;
rtapd->conf->auth_server = rtapd->conf->auth_servers;
Radius_change_server(rtapd, rtapd->conf->auth_server, oserv, rtapd->radius->auth_serv_sock, 1);
}
if (rtapd->conf->radius_retry_primary_interval)
eloop_register_timeout(rtapd->conf->radius_retry_primary_interval, 0, Radius_retry_primary_timer, rtapd, NULL);
}
static int Radius_client_init_auth(rtapd *rtapd)
{
rtapd->radius->auth_serv_sock = socket(PF_INET, SOCK_DGRAM, 0);
if (rtapd->radius->auth_serv_sock < 0)
{
perror("socket[PF_INET,SOCK_DGRAM]");
return -1;
}
Radius_change_server(rtapd, rtapd->conf->auth_server, NULL, rtapd->radius->auth_serv_sock, 1);
if (eloop_register_read_sock(rtapd->radius->auth_serv_sock, Radius_client_receive, rtapd, (void *) RADIUS_AUTH))
{
DBGPRINT(RT_DEBUG_ERROR,"Could not register read socket for authentication server\n");
return -1;
}
return 0;
}
int Radius_client_init(rtapd *rtapd)
{
if (rtapd->radius == NULL)
{
rtapd->radius = malloc(sizeof(struct radius_client_data));
memset(rtapd->radius, 0, sizeof(struct radius_client_data));
rtapd->radius->auth_serv_sock = -1;
}
if (rtapd->radius == NULL)
return -1;
if( rtapd->radius->auth_serv_sock < 0)
{
if (rtapd->conf->auth_server && Radius_client_init_auth(rtapd))
return -1;
if (rtapd->conf->radius_retry_primary_interval)
eloop_register_timeout(rtapd->conf->radius_retry_primary_interval, 0, Radius_retry_primary_timer, rtapd, NULL);
}
return 0;
}
void Radius_client_deinit(rtapd *rtapd)
{
if (!rtapd->radius)
return;
eloop_cancel_timeout(Radius_retry_primary_timer, rtapd, NULL);
Radius_client_flush(rtapd);
free(rtapd->radius->auth_handlers);
free(rtapd->radius);
rtapd->radius = NULL;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -