⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 radius_client.c

📁 802.1x 源码,基于linux平台开发
💻 C
📖 第 1 页 / 共 2 页
字号:
/*
 *
 * 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 + -