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

📄 radius_client.c

📁 一个Linux下无线网卡的设置工具
💻 C
📖 第 1 页 / 共 2 页
字号:
		break;	}	prev_req = NULL;	req = 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_type == RADIUS_ACCT_INTERIM &&		      msg_type == RADIUS_ACCT)) &&		    req->msg->hdr->identifier == msg->hdr->identifier)			break;		prev_req = req;		req = req->next;	}	if (req == NULL) {		hostapd_logger(radius->ctx, NULL, HOSTAPD_MODULE_RADIUS,			       HOSTAPD_LEVEL_DEBUG,			       "No matching RADIUS request found (type=%d "			       "id=%d) - dropping packet",			       msg_type, msg->hdr->identifier);		goto fail;	}	gettimeofday(&tv, NULL);	roundtrip = (tv.tv_sec - req->last_attempt.tv_sec) * 100 +		(tv.tv_usec - req->last_attempt.tv_usec) / 10000;	hostapd_logger(radius->ctx, req->addr, HOSTAPD_MODULE_RADIUS,		       HOSTAPD_LEVEL_DEBUG,		       "Received RADIUS packet matched with a pending "		       "request, round trip time %d.%02d sec",		       roundtrip / 100, roundtrip % 100);	rconf->round_trip_time = roundtrip;	/* Remove ACKed RADIUS packet from retransmit list */	if (prev_req)		prev_req->next = req->next;	else		radius->msgs = req->next;	radius->num_msgs--;	for (i = 0; i < num_handlers; i++) {		RadiusRxResult res;		res = handlers[i].handler(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_INVALID_AUTHENTICATOR:			invalid_authenticator++;			/* continue */		case RADIUS_RX_UNKNOWN:			/* continue with next handler */			break;		}	}	if (invalid_authenticator)		rconf->bad_authenticators++;	else		rconf->unknown_types++;	hostapd_logger(radius->ctx, req->addr, HOSTAPD_MODULE_RADIUS,		       HOSTAPD_LEVEL_DEBUG, "No RADIUS RX handler found "		       "(type=%d code=%d id=%d)%s - dropping packet",		       msg_type, msg->hdr->code, msg->hdr->identifier,		       invalid_authenticator ? " [INVALID AUTHENTICATOR]" :		       "");	radius_client_msg_free(req); fail:	radius_msg_free(msg);	free(msg);}u8 radius_client_get_id(struct radius_client_data *radius){	struct radius_msg_list *entry, *prev, *remove;	u8 id = 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 = radius->msgs;	prev = NULL;	while (entry) {		if (entry->msg->hdr->identifier == id) {			hostapd_logger(radius->ctx, entry->addr,				       HOSTAPD_MODULE_RADIUS,				       HOSTAPD_LEVEL_DEBUG,				       "Removing pending RADIUS message, "				       "since its id (%d) is reused", id);			if (prev)				prev->next = entry->next;			else				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(struct radius_client_data *radius){	struct radius_msg_list *entry, *prev;	if (!radius)		return;	eloop_cancel_timeout(radius_client_timer, radius, NULL);	entry = radius->msgs;	radius->msgs = NULL;	radius->num_msgs = 0;	while (entry) {		prev = entry;		entry = entry->next;		radius_client_msg_free(prev);	}}static intradius_change_server(struct radius_client_data *radius,		     struct hostapd_radius_server *nserv,		     struct hostapd_radius_server *oserv,		     int sock, int sock6, int auth){	struct sockaddr_in serv;#ifdef CONFIG_IPV6	struct sockaddr_in6 serv6;#endif /* CONFIG_IPV6 */	struct sockaddr *addr;	socklen_t addrlen;	char abuf[50];	int sel_sock;	hostapd_logger(radius->ctx, NULL, HOSTAPD_MODULE_RADIUS,		       HOSTAPD_LEVEL_INFO,		       "%s server %s:%d",		       auth ? "Authentication" : "Accounting",		       hostapd_ip_txt(&nserv->addr, abuf, sizeof(abuf)),		       nserv->port);	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(radius);	} else {		/* Reset retry counters for the new server */		struct radius_msg_list *entry;		entry = 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 (radius->msgs) {			eloop_cancel_timeout(radius_client_timer, radius,					     NULL);			eloop_register_timeout(RADIUS_CLIENT_FIRST_WAIT, 0,					       radius_client_timer, radius,					       NULL);		}	}	switch (nserv->addr.af) {	case AF_INET:		memset(&serv, 0, sizeof(serv));		serv.sin_family = AF_INET;		serv.sin_addr.s_addr = nserv->addr.u.v4.s_addr;		serv.sin_port = htons(nserv->port);		addr = (struct sockaddr *) &serv;		addrlen = sizeof(serv);		sel_sock = sock;		break;#ifdef CONFIG_IPV6	case AF_INET6:		memset(&serv6, 0, sizeof(serv6));		serv6.sin6_family = AF_INET6;		memcpy(&serv6.sin6_addr, &nserv->addr.u.v6,		       sizeof(struct in6_addr));		serv6.sin6_port = htons(nserv->port);		addr = (struct sockaddr *) &serv6;		addrlen = sizeof(serv6);		sel_sock = sock6;		break;#endif /* CONFIG_IPV6 */	default:		return -1;	}	if (connect(sel_sock, addr, addrlen) < 0) {		perror("connect[radius]");		return -1;	}	if (auth)		radius->auth_sock = sel_sock;	else		radius->acct_sock = sel_sock;	return 0;}static void radius_retry_primary_timer(void *eloop_ctx, void *timeout_ctx){	struct radius_client_data *radius = eloop_ctx;	struct hostapd_radius_servers *conf = radius->conf;	struct hostapd_radius_server *oserv;	if (radius->auth_sock >= 0 && conf->auth_servers &&	    conf->auth_server != conf->auth_servers) {		oserv = conf->auth_server;		conf->auth_server = conf->auth_servers;		radius_change_server(radius, conf->auth_server, oserv,				     radius->auth_serv_sock,				     radius->auth_serv_sock6, 1);	}	if (radius->acct_sock >= 0 && conf->acct_servers &&	    conf->acct_server != conf->acct_servers) {		oserv = conf->acct_server;		conf->acct_server = conf->acct_servers;		radius_change_server(radius, conf->acct_server, oserv,				     radius->acct_serv_sock,				     radius->acct_serv_sock6, 0);	}	if (conf->retry_primary_interval)		eloop_register_timeout(conf->retry_primary_interval, 0,				       radius_retry_primary_timer, radius,				       NULL);}static int radius_client_init_auth(struct radius_client_data *radius){	struct hostapd_radius_servers *conf = radius->conf;	int ok = 0;	radius->auth_serv_sock = socket(PF_INET, SOCK_DGRAM, 0);	if (radius->auth_serv_sock < 0)		perror("socket[PF_INET,SOCK_DGRAM]");	else		ok++;#ifdef CONFIG_IPV6	radius->auth_serv_sock6 = socket(PF_INET6, SOCK_DGRAM, 0);	if (radius->auth_serv_sock6 < 0)		perror("socket[PF_INET6,SOCK_DGRAM]");	else		ok++;#endif /* CONFIG_IPV6 */	if (ok == 0)		return -1;	radius_change_server(radius, conf->auth_server, NULL,			     radius->auth_serv_sock, radius->auth_serv_sock6,			     1);	if (radius->auth_serv_sock >= 0 &&	    eloop_register_read_sock(radius->auth_serv_sock,				     radius_client_receive, radius,				     (void *) RADIUS_AUTH)) {		printf("Could not register read socket for authentication "		       "server\n");		return -1;	}#ifdef CONFIG_IPV6	if (radius->auth_serv_sock6 >= 0 &&	    eloop_register_read_sock(radius->auth_serv_sock6,				     radius_client_receive, radius,				     (void *) RADIUS_AUTH)) {		printf("Could not register read socket for authentication "		       "server\n");		return -1;	}#endif /* CONFIG_IPV6 */	return 0;}static int radius_client_init_acct(struct radius_client_data *radius){	struct hostapd_radius_servers *conf = radius->conf;	int ok = 0;	radius->acct_serv_sock = socket(PF_INET, SOCK_DGRAM, 0);	if (radius->acct_serv_sock < 0)		perror("socket[PF_INET,SOCK_DGRAM]");	else		ok++;	radius_change_server(radius, conf->acct_server, NULL,			     radius->acct_serv_sock, radius->acct_serv_sock6,			     0);	if (radius->acct_serv_sock >= 0 &&	    eloop_register_read_sock(radius->acct_serv_sock,				     radius_client_receive, radius,				     (void *) RADIUS_ACCT)) {		printf("Could not register read socket for accounting "		       "server\n");		return -1;	}#ifdef CONFIG_IPV6	if (radius->acct_serv_sock6 >= 0 &&	    eloop_register_read_sock(radius->acct_serv_sock6,				     radius_client_receive, radius,				     (void *) RADIUS_ACCT)) {		printf("Could not register read socket for accounting "		       "server\n");		return -1;	}#endif /* CONFIG_IPV6 */	return 0;}struct radius_client_data *radius_client_init(void *ctx, struct hostapd_radius_servers *conf){	struct radius_client_data *radius;	radius = malloc(sizeof(struct radius_client_data));	if (radius == NULL)		return NULL;	memset(radius, 0, sizeof(struct radius_client_data));	radius->ctx = ctx;	radius->conf = conf;	radius->auth_serv_sock = radius->acct_serv_sock =		radius->auth_serv_sock6 = radius->acct_serv_sock6 =		radius->auth_sock = radius->acct_sock = -1;	if (conf->auth_server && radius_client_init_auth(radius)) {		radius_client_deinit(radius);		return NULL;	}	if (conf->acct_server && radius_client_init_acct(radius)) {		radius_client_deinit(radius);		return NULL;	}	if (conf->retry_primary_interval)		eloop_register_timeout(conf->retry_primary_interval, 0,				       radius_retry_primary_timer, radius,				       NULL);	return radius;}void radius_client_deinit(struct radius_client_data *radius){	if (!radius)		return;	eloop_cancel_timeout(radius_retry_primary_timer, radius, NULL);	radius_client_flush(radius);	free(radius->auth_handlers);	free(radius->acct_handlers);	free(radius);}void radius_client_flush_auth(struct radius_client_data *radius, u8 *addr){	struct radius_msg_list *entry, *prev, *tmp;	prev = NULL;	entry = radius->msgs;	while (entry) {		if (entry->msg_type == RADIUS_AUTH &&		    memcmp(entry->addr, addr, ETH_ALEN) == 0) {			hostapd_logger(radius->ctx, addr,				       HOSTAPD_MODULE_RADIUS,				       HOSTAPD_LEVEL_DEBUG,				       "Removing pending RADIUS authentication"				       " message for removed client");			if (prev)				prev->next = entry->next;			else				radius->msgs = entry->next;			tmp = entry;			entry = entry->next;			radius_client_msg_free(tmp);			radius->num_msgs--;			continue;		}		prev = entry;		entry = entry->next;	}}static int radius_client_dump_auth_server(char *buf, size_t buflen,					  struct hostapd_radius_server *serv,					  struct radius_client_data *cli){	int pending = 0;	struct radius_msg_list *msg;	char abuf[50];	if (cli) {		for (msg = cli->msgs; msg; msg = msg->next) {			if (msg->msg_type == RADIUS_AUTH)				pending++;		}	}	return snprintf(buf, buflen,			"radiusAuthServerIndex=%d\n"			"radiusAuthServerAddress=%s\n"			"radiusAuthClientServerPortNumber=%d\n"			"radiusAuthClientRoundTripTime=%d\n"			"radiusAuthClientAccessRequests=%u\n"			"radiusAuthClientAccessRetransmissions=%u\n"			"radiusAuthClientAccessAccepts=%u\n"			"radiusAuthClientAccessRejects=%u\n"			"radiusAuthClientAccessChallenges=%u\n"			"radiusAuthClientMalformedAccessResponses=%u\n"			"radiusAuthClientBadAuthenticators=%u\n"			"radiusAuthClientPendingRequests=%u\n"			"radiusAuthClientTimeouts=%u\n"			"radiusAuthClientUnknownTypes=%u\n"			"radiusAuthClientPacketsDropped=%u\n",			serv->index,			hostapd_ip_txt(&serv->addr, abuf, sizeof(abuf)),			serv->port,			serv->round_trip_time,			serv->requests,			serv->retransmissions,			serv->access_accepts,			serv->access_rejects,			serv->access_challenges,			serv->malformed_responses,			serv->bad_authenticators,			pending,			serv->timeouts,			serv->unknown_types,			serv->packets_dropped);}static int radius_client_dump_acct_server(char *buf, size_t buflen,					  struct hostapd_radius_server *serv,					  struct radius_client_data *cli){	int pending = 0;	struct radius_msg_list *msg;	char abuf[50];	if (cli) {		for (msg = cli->msgs; msg; msg = msg->next) {			if (msg->msg_type == RADIUS_ACCT ||			    msg->msg_type == RADIUS_ACCT_INTERIM)				pending++;		}	}	return snprintf(buf, buflen,			"radiusAccServerIndex=%d\n"			"radiusAccServerAddress=%s\n"			"radiusAccClientServerPortNumber=%d\n"			"radiusAccClientRoundTripTime=%d\n"			"radiusAccClientRequests=%u\n"			"radiusAccClientRetransmissions=%u\n"			"radiusAccClientResponses=%u\n"			"radiusAccClientMalformedResponses=%u\n"			"radiusAccClientBadAuthenticators=%u\n"			"radiusAccClientPendingRequests=%u\n"			"radiusAccClientTimeouts=%u\n"			"radiusAccClientUnknownTypes=%u\n"			"radiusAccClientPacketsDropped=%u\n",			serv->index,			hostapd_ip_txt(&serv->addr, abuf, sizeof(abuf)),			serv->port,			serv->round_trip_time,			serv->requests,			serv->retransmissions,			serv->responses,			serv->malformed_responses,			serv->bad_authenticators,			pending,			serv->timeouts,			serv->unknown_types,			serv->packets_dropped);}int radius_client_get_mib(struct radius_client_data *radius, char *buf,			  size_t buflen){	struct hostapd_radius_servers *conf = radius->conf;	int i;	struct hostapd_radius_server *serv;	int count = 0;	if (conf->auth_servers) {		for (i = 0; i < conf->num_auth_servers; i++) {			serv = &conf->auth_servers[i];			count += radius_client_dump_auth_server(				buf + count, buflen - count, serv,				serv == conf->auth_server ?				radius : NULL);		}	}	if (conf->acct_servers) {		for (i = 0; i < conf->num_acct_servers; i++) {			serv = &conf->acct_servers[i];			count += radius_client_dump_acct_server(				buf + count, buflen - count, serv,				serv == conf->acct_server ?				radius : NULL);		}	}	return count;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -