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

📄 realms.c

📁 使用最广泛的radius的linux的源码
💻 C
📖 第 1 页 / 共 3 页
字号:
		}	}	if (pool->server_type != server_type) {		cf_log_err(cf_sectiontoitem(cs), "Incompatible home_server_pool \"%s\" (mixed auth_pool / acct_pool)", name);		return 0;	}	*dest = pool;	return 1;}static int realm_add(realm_config_t *rc, CONF_SECTION *cs){	const char *name2;	REALM *r = NULL;	CONF_PAIR *cp;	home_pool_t *auth_pool, *acct_pool;	const char *auth_pool_name, *acct_pool_name;	name2 = cf_section_name1(cs);	if (!name2 || (strcasecmp(name2, "realm") != 0)) {		cf_log_err(cf_sectiontoitem(cs), "Section is not a realm.");		return 0;	}	name2 = cf_section_name2(cs);	if (!name2) {		cf_log_err(cf_sectiontoitem(cs), "Realm section is missing the realm name.");		return 0;	}	auth_pool = acct_pool = NULL;	auth_pool_name = acct_pool_name = NULL;	/*	 *	Prefer new configuration to old one.	 */	cp = cf_pair_find(cs, "pool");	if (!cp) cp = cf_pair_find(cs, "home_server_pool");	if (cp) auth_pool_name = cf_pair_value(cp);	if (cp && auth_pool_name) {		acct_pool_name = auth_pool_name;		if (!add_pool_to_realm(rc, cs,				       auth_pool_name, &auth_pool,				       HOME_TYPE_AUTH, 1)) {			return 0;		}		if (!add_pool_to_realm(rc, cs,				       auth_pool_name, &acct_pool,				       HOME_TYPE_ACCT, 0)) {			return 0;		}	}	cp = cf_pair_find(cs, "auth_pool");	if (cp) auth_pool_name = cf_pair_value(cp);	if (cp && auth_pool_name) {		if (auth_pool) {			cf_log_err(cf_sectiontoitem(cs), "Cannot use \"pool\" and \"auth_pool\" at the same time.");			return 0;		}		if (!add_pool_to_realm(rc, cs,				       auth_pool_name, &auth_pool,				       HOME_TYPE_AUTH, 1)) {			return 0;		}	}	cp = cf_pair_find(cs, "acct_pool");	if (cp) acct_pool_name = cf_pair_value(cp);	if (cp && acct_pool_name) {		int do_print = TRUE;		if (acct_pool) {			cf_log_err(cf_sectiontoitem(cs), "Cannot use \"pool\" and \"acct_pool\" at the same time.");			return 0;		}		if (!auth_pool ||		    (strcmp(auth_pool_name, acct_pool_name) != 0)) {			do_print = TRUE;		}		if (!add_pool_to_realm(rc, cs,				       acct_pool_name, &acct_pool,				       HOME_TYPE_ACCT, do_print)) {			return 0;		}	}	cf_log_info(cs, " realm %s {", name2);	/*	 *	The realm MAY already exist if it's an old-style realm.	 *	In that case, merge the old-style realm with this one.	 */	r = realm_find2(name2);	if (r && (strcmp(r->name, name2) == 0)) {		if (cf_pair_find(cs, "auth_pool") ||		    cf_pair_find(cs, "acct_pool")) {			cf_log_err(cf_sectiontoitem(cs), "Duplicate realm \"%s\"", name2);			goto error;		}		if (!old_realm_config(rc, cs, r)) {			goto error;		}		cf_log_info(cs, " } # realm %s", name2);		return 1;	}#ifdef HAVE_REGEX_H	if (name2[0] == '~') {		regex_t reg;				/*		 *	Include substring matches.		 */		if (regcomp(&reg, name2 + 1,			    REG_EXTENDED | REG_NOSUB | REG_ICASE) != 0) {			cf_log_err(cf_sectiontoitem(cs),				   "Invalid regex in realm \"%s\"", name2);			goto error;		}		regfree(&reg);	}#endif	r = rad_malloc(sizeof(*r));	memset(r, 0, sizeof(*r));	r->name = name2;	r->auth_pool = auth_pool;	r->acct_pool = acct_pool;	r->striprealm = 1;	if (auth_pool_name &&	    (auth_pool_name == acct_pool_name)) { /* yes, ptr comparison */		cf_log_info(cs, "\tpool = %s", auth_pool_name);	} else {		if (auth_pool_name) cf_log_info(cs, "\tauth_pool = %s", auth_pool_name);		if (acct_pool_name) cf_log_info(cs, "\tacct_pool = %s", acct_pool_name);	}	cp = cf_pair_find(cs, "nostrip");	if (cp && (cf_pair_value(cp) == NULL)) {		r->striprealm = 0;		cf_log_info(cs, "\tnostrip");	}	/*	 *	We're a new-style realm.  Complain if we see the old	 *	directives.	 */	if (r->auth_pool || r->acct_pool) {		if (((cp = cf_pair_find(cs, "authhost")) != NULL) ||		    ((cp = cf_pair_find(cs, "accthost")) != NULL) ||		    ((cp = cf_pair_find(cs, "secret")) != NULL) ||		    ((cp = cf_pair_find(cs, "ldflag")) != NULL)) {			DEBUG2("WARNING: Ignoring old-style configuration entry \"%s\" in realm \"%s\"", cf_pair_attr(cp), r->name);		}		/*		 *	The realm MAY be an old-style realm, as there		 *	was no auth_pool or acct_pool.  Double-check		 *	it, just to be safe.		 */	} else if (!old_realm_config(rc, cs, r)) {		goto error;	}#ifdef HAVE_REGEX_H	/*	 *	It's a regex.  Add it to a separate list.	 */	if (name2[0] == '~') {		realm_regex_t *rr, **last;		rr = rad_malloc(sizeof(*rr));				last = &realms_regex;		while (*last) last = &((*last)->next);  /* O(N^2)... sue me. */		r->name = name2;		rr->realm = r;		rr->next = NULL;		*last = rr;		cf_log_info(cs, " }");		return 1;	}#endif	if (!rbtree_insert(realms_byname, r)) {		rad_assert("Internal sanity check failed");		goto error;	}	cf_log_info(cs, " }");	return 1; error:	cf_log_info(cs, " } # realm %s", name2);	free(r);	return 0;}int realms_init(CONF_SECTION *config){	CONF_SECTION *cs;	realm_config_t *rc, *old_rc;	if (realms_byname) return 1;	realms_byname = rbtree_create(realm_name_cmp, free, 0);	if (!realms_byname) {		realms_free();		return 0;	}	home_servers_byaddr = rbtree_create(home_server_addr_cmp, free, 0);	if (!home_servers_byaddr) {		realms_free();		return 0;	}	home_servers_byname = rbtree_create(home_server_name_cmp, NULL, 0);	if (!home_servers_byname) {		realms_free();		return 0;	}	home_pools_byname = rbtree_create(home_pool_name_cmp, free, 0);	if (!home_pools_byname) {		realms_free();		return 0;	}	rc = rad_malloc(sizeof(*rc));	memset(rc, 0, sizeof(*rc));	rc->cs = config;	cs = cf_subsection_find_next(config, NULL, "proxy");	if (cs) {		cf_section_parse(cs, rc, proxy_config);	} else {		rc->dead_time = DEAD_TIME;		rc->retry_count = RETRY_COUNT;		rc->retry_delay = RETRY_DELAY;		rc->fallback = 0;		rc->wake_all_if_all_dead= 0;	}	for (cs = cf_subsection_find_next(config, NULL, "realm");	     cs != NULL;	     cs = cf_subsection_find_next(config, cs, "realm")) {		if (!realm_add(rc, cs)) {			free(rc);			realms_free();			return 0;		}	}	xlat_register("home_server", xlat_home_server, NULL);	xlat_register("home_server_pool", xlat_server_pool, NULL);	/*	 *	Swap pointers atomically.	 */	old_rc = realm_config;	realm_config = rc;	free(old_rc);	return 1;}/* *	Find a realm where "name" might be the regex. */REALM *realm_find2(const char *name){	REALM myrealm;	REALM *realm;		if (!name) name = "NULL";	myrealm.name = name;	realm = rbtree_finddata(realms_byname, &myrealm);	if (realm) return realm;#ifdef HAVE_REGEX_H	if (realms_regex) {		realm_regex_t *this;		for (this = realms_regex; this != NULL; this = this->next) {			if (strcmp(this->realm->name, name) == 0) {				return this->realm;			}		}	}#endif	/*	 *	Couldn't find a realm.  Look for DEFAULT.	 */	myrealm.name = "DEFAULT";	return rbtree_finddata(realms_byname, &myrealm);}/* *	Find a realm in the REALM list. */REALM *realm_find(const char *name){	REALM myrealm;	REALM *realm;		if (!name) name = "NULL";	myrealm.name = name;	realm = rbtree_finddata(realms_byname, &myrealm);	if (realm) return realm;#ifdef HAVE_REGEX_H	if (realms_regex) {		realm_regex_t *this;		for (this = realms_regex; this != NULL; this = this->next) {			int compare;			regex_t reg;			/*			 *	Include substring matches.			 */			if (regcomp(&reg, this->realm->name + 1,				    REG_EXTENDED | REG_NOSUB | REG_ICASE) != 0) {				continue;			}			compare = regexec(&reg, name, 0, NULL, 0);			regfree(&reg);			if (compare == 0) return this->realm;		}	}#endif	/*	 *	Couldn't find a realm.  Look for DEFAULT.	 */	myrealm.name = "DEFAULT";	return rbtree_finddata(realms_byname, &myrealm);}home_server *home_server_ldb(const char *realmname,			     home_pool_t *pool, REQUEST *request){	int		start;	int		count;	home_server	*found = NULL;	VALUE_PAIR	*vp;	start = 0;	/*	 *	Determine how to pick choose the home server.	 */	switch (pool->type) {		uint32_t hash;		/*		 *	For load-balancing by client IP address, we		 *	pick a home server by hashing the client IP.		 *		 *	This isn't as even a load distribution as		 *	tracking the State attribute, but it's better		 *	than nothing.		 */	case HOME_POOL_CLIENT_BALANCE:		switch (request->packet->src_ipaddr.af) {		case AF_INET:			hash = fr_hash(&request->packet->src_ipaddr.ipaddr.ip4addr,					 sizeof(request->packet->src_ipaddr.ipaddr.ip4addr));			break;		case AF_INET6:			hash = fr_hash(&request->packet->src_ipaddr.ipaddr.ip6addr,					 sizeof(request->packet->src_ipaddr.ipaddr.ip6addr));			break;		default:			hash = 0;			break;		}		start = hash % pool->num_home_servers;		break;	case HOME_POOL_CLIENT_PORT_BALANCE:		switch (request->packet->src_ipaddr.af) {		case AF_INET:			hash = fr_hash(&request->packet->src_ipaddr.ipaddr.ip4addr,					 sizeof(request->packet->src_ipaddr.ipaddr.ip4addr));			break;		case AF_INET6:			hash = fr_hash(&request->packet->src_ipaddr.ipaddr.ip6addr,					 sizeof(request->packet->src_ipaddr.ipaddr.ip6addr));			break;		default:			hash = 0;			break;		}		fr_hash_update(&request->packet->src_port,				 sizeof(request->packet->src_port), hash);		start = hash % pool->num_home_servers;		break;	case HOME_POOL_KEYED_BALANCE:		if ((vp = pairfind(request->config_items, PW_LOAD_BALANCE_KEY)) != NULL) {			hash = fr_hash(vp->vp_strvalue, vp->length);			start = hash % pool->num_home_servers;			break;		}		/* FALL-THROUGH */					case HOME_POOL_LOAD_BALANCE:		found = pool->servers[0];	default:		start = 0;		break;	}	/*	 *	Starting with the home server we chose, loop through	 *	all home servers.  If the current one is dead, skip	 *	it.  If it is too busy, skip it.	 *	 *	Otherwise, use it.	 */	for (count = 0; count < pool->num_home_servers; count++) {		home_server *home = pool->servers[(start + count) % pool->num_home_servers];		if (home->state == HOME_STATE_IS_DEAD) {			continue;		}		/*		 *	This home server is too busy.  Choose another one.		 */		if (home->currently_outstanding >= home->max_outstanding) {			continue;		}		if (pool->type != HOME_POOL_LOAD_BALANCE) {			return home;		}		DEBUG3("PROXY %s %d\t%s %d",		       found->name, found->currently_outstanding,		       home->name, home->currently_outstanding);		/*		 *	Prefer this server if it's less busy than the		 *	one we previously found.		 */		if (home->currently_outstanding < found->currently_outstanding) {			DEBUG3("Choosing %s: It's less busy than %s",			       home->name, found->name);			found = home;			continue;		}		/*		 *	Ignore servers which are busier than the one		 *	we found.		 */		if (home->currently_outstanding > found->currently_outstanding) {			DEBUG3("Skipping %s: It's busier than %s",			       home->name, found->name);			continue;		}		if (home->total_requests_sent < found->total_requests_sent) {			DEBUG3("Choosing %s: It's been less busy than %s",			       home->name, found->name);			found = home;			continue;		}		if (home->total_requests_sent > found->total_requests_sent) {			DEBUG3("Skipping %s: It's been busier than %s",			       home->name, found->name);			continue;		}		/*		 *	From the list of servers which have the same		 *	load, choose one at random.		 */		if (((count + 1) * (fr_rand() & 0xffff)) < (uint32_t) 0x10000) {			found = home;		}	} /* loop over the home servers */	if (found) return found;	/*	 *	There's a fallback if they're all dead.	 */	if (pool->fallback &&	    (pool->fallback->state == HOME_STATE_ALIVE)) {		return pool->fallback;	}	/*	 *	No live match found, and no fallback to the "DEFAULT"	 *	realm.  We fix this by blindly marking all servers as	 *	"live".  But only do it for ones that don't support	 *	"pings", as they will be marked live when they	 *	actually are live.	 */	if (!realm_config->fallback &&	    realm_config->wake_all_if_all_dead) {		home_server *lb = NULL;		for (count = 0; count < pool->num_home_servers; count++) {			home_server *home = pool->servers[count];			if ((home->state == HOME_STATE_IS_DEAD) &&			    (home->ping_check == HOME_PING_CHECK_NONE)) {				home->state = HOME_STATE_ALIVE;				if (!lb) lb = home;			}		}		if (lb) return lb;	}	/*	 *	Still nothing.  Look up the DEFAULT realm, but only	 *	if we weren't looking up the NULL or DEFAULT realms.	 */	if (realm_config->fallback &&	    realmname &&	    (strcmp(realmname, "NULL") != 0) &&	    (strcmp(realmname, "DEFAULT") != 0)) {		REALM *rd = realm_find("DEFAULT");		if (!rd) return NULL;		pool = NULL;		if (request->packet->code == PW_AUTHENTICATION_REQUEST) {			pool = rd->auth_pool;		} else if (request->packet->code == PW_ACCOUNTING_REQUEST) {			pool = rd->acct_pool;		}		if (!pool) return NULL;		DEBUG2("  Realm %s has no live home servers.  Falling back to the DEFAULT realm.", realmname);		return home_server_ldb(rd->name, pool, request);	}	/*	 *	Still haven't found anything.  Oh well.	 */	return NULL;}home_server *home_server_find(fr_ipaddr_t *ipaddr, int port){	home_server myhome;	memset(&myhome, 0, sizeof(myhome));	myhome.ipaddr = *ipaddr;	myhome.port = port;	myhome.server = NULL;	/* we're not called for internal proxying */	return rbtree_finddata(home_servers_byaddr, &myhome);}

⌨️ 快捷键说明

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