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

📄 radius_client.c

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