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

📄 listen.c

📁 使用最广泛的radius的linux的源码
💻 C
📖 第 1 页 / 共 3 页
字号:
	this = listen_alloc(RAD_LISTEN_PROXY);	/*	 *	Find an existing proxy socket to copy.	 *	 *	FIXME: Make it per-realm, or per-home server!	 */	last_proxy_port = 0;	old = NULL;	last = &mainconfig.listen;	for (tmp = mainconfig.listen; tmp != NULL; tmp = tmp->next) {		if (tmp->type == RAD_LISTEN_PROXY) {			sock = tmp->data;			if (sock->port > last_proxy_port) {				last_proxy_port = sock->port + 1;			}			if (!old) old = sock;		}		last = &(tmp->next);	}	if (!old) {		listen_free(&this);		return NULL;	/* This is a serious error. */	}	/*	 *	FIXME: find a new IP address to listen on?	 *	 *	This could likely be done in the "home server"	 *	configuration, to have per-home-server source IP's.	 */	sock = this->data;	memcpy(&sock->ipaddr, &old->ipaddr, sizeof(sock->ipaddr));	/*	 *	Keep going until we find an unused port.	 */	for (port = last_proxy_port; port < 64000; port++) {		sock->port = port;		if (listen_bind(this) == 0) {			/*			 *	Add the new listener to the list of			 *	listeners.			 */			*last = this;			return this;		}	}	listen_free(&this);	return NULL;}static const FR_NAME_NUMBER listen_compare[] = {	{ "auth",	RAD_LISTEN_AUTH },	{ "acct",	RAD_LISTEN_ACCT },	{ "detail",	RAD_LISTEN_DETAIL },	{ "proxy",	RAD_LISTEN_PROXY },#ifdef WITH_VMPS	{ "vmps",	RAD_LISTEN_VQP },#endif#ifdef WITH_DHCP	{ "dhcp",	RAD_LISTEN_DHCP },#else	{ "dhcp",	RAD_LISTEN_NONE },#endif	{ NULL, 0 },};static rad_listen_t *listen_parse(CONF_SECTION *cs, const char *server){	int		type, rcode;	char		*listen_type;	rad_listen_t	*this;	listen_type = NULL;		cf_log_info(cs, "listen {");	rcode = cf_item_parse(cs, "type", PW_TYPE_STRING_PTR,			      &listen_type, "");	if (rcode < 0) return NULL;	if (rcode == 1) {		free(listen_type);		cf_log_err(cf_sectiontoitem(cs),			   "No type specified in listen section");		return NULL;	}	type = fr_str2int(listen_compare, listen_type,			    RAD_LISTEN_NONE);	if (type == RAD_LISTEN_NONE) {		cf_log_err(cf_sectiontoitem(cs),			   "Invalid type \"%s\" in listen section.",			   listen_type);		free(listen_type);		return NULL;	}	free(listen_type);		/*	 *	Allow listen sections in the default config to	 *	refer to a server.	 */	if (!server) {		rcode = cf_item_parse(cs, "virtual_server", PW_TYPE_STRING_PTR,				      &server, NULL);		if (rcode == 1) { /* compatiblity with 2.0-pre */			rcode = cf_item_parse(cs, "server", PW_TYPE_STRING_PTR,					      &server, NULL);		}		if (rcode < 0) return NULL;	}	/*	 *	Set up cross-type data.	 */	this = listen_alloc(type);	this->server = server;	this->fd = -1;	/*	 *	Call per-type parser.	 */	if (master_listen[type].parse(cs, this) < 0) {		listen_free(&this);		return NULL;	}	cf_log_info(cs, "}");	return this;}/* *	Generate a list of listeners.  Takes an input list of *	listeners, too, so we don't close sockets with waiting packets. */int listen_init(CONF_SECTION *config, rad_listen_t **head){	int		override = FALSE;	int		rcode;	CONF_SECTION	*cs;	rad_listen_t	**last;	rad_listen_t	*this;	fr_ipaddr_t	server_ipaddr;	int		auth_port = 0;	int		defined_proxy = 0;	/*	 *	We shouldn't be called with a pre-existing list.	 */	rad_assert(head && (*head == NULL));	last = head;	server_ipaddr.af = AF_UNSPEC;	/*	 *	If the port is specified on the command-line,	 *	it over-rides the configuration file.	 *	 *	FIXME: If argv[0] == "vmpsd", then don't listen on auth/acct!	 */	if (mainconfig.port >= 0) auth_port = mainconfig.port;	/*	 *	If the IP address was configured on the command-line,	 *	use that as the "bind_address"	 */	if (mainconfig.myip.af != AF_UNSPEC) {		memcpy(&server_ipaddr, &mainconfig.myip,		       sizeof(server_ipaddr));		override = TRUE;		goto bind_it;	}	/*	 *	Else look for bind_address and/or listen sections.	 */	server_ipaddr.ipaddr.ip4addr.s_addr = htonl(INADDR_NONE);	rcode = cf_item_parse(config, "bind_address",			      PW_TYPE_IPADDR,			      &server_ipaddr.ipaddr.ip4addr, NULL);	if (rcode < 0) return -1; /* error parsing it */	if (rcode == 0) { /* successfully parsed IPv4 */		listen_socket_t *sock;		server_ipaddr.af = AF_INET;		radlog(L_INFO, "WARNING: The directive 'bind_adress' is deprecated, and will be removed in future versions of FreeRADIUS. Please edit the configuration files to use the directive 'listen'.");	bind_it:#ifdef WITH_VMPS		if (strcmp(progname, "vmpsd") == 0) {			this = listen_alloc(RAD_LISTEN_VQP);			if (!auth_port) auth_port = 1589;		} else#endif			this = listen_alloc(RAD_LISTEN_AUTH);		sock = this->data;		sock->ipaddr = server_ipaddr;		sock->port = auth_port;		sock->clients = clients_parse_section(config);		if (!sock->clients) {			cf_log_err(cf_sectiontoitem(config),				   "Failed to find any clients for this listen section");			return -1;		}		if (listen_bind(this) < 0) {			listen_free(&this);			listen_free(head);			radlog(L_ERR, "There appears to be another RADIUS server running on the authentication port %d", sock->port);			return -1;		}		auth_port = sock->port;	/* may have been updated in listen_bind */		if (override) {			cs = cf_section_sub_find_name2(config, "server",						       mainconfig.name);			if (cs) this->server = mainconfig.name;		}		*last = this;		last = &(this->next);#ifdef WITH_VMPS		/*		 *	No acct for vmpsd		 */		if (strcmp(progname, "vmpsd") == 0) goto do_proxy;#endif		/*		 *	Open Accounting Socket.		 *		 *	If we haven't already gotten acct_port from		 *	/etc/services, then make it auth_port + 1.		 */		this = listen_alloc(RAD_LISTEN_ACCT);		sock = this->data;		/*		 *	Create the accounting socket.		 *		 *	The accounting port is always the		 *	authentication port + 1		 */		sock->ipaddr = server_ipaddr;		sock->port = auth_port + 1;		sock->clients = clients_parse_section(config);		if (!sock->clients) {			cf_log_err(cf_sectiontoitem(config),				   "Failed to find any clients for this listen section");			return -1;		}		if (listen_bind(this) < 0) {			listen_free(&this);			listen_free(head);			radlog(L_ERR, "There appears to be another RADIUS server running on the accounting port %d", sock->port);			return -1;		}		if (override) {			cs = cf_section_sub_find_name2(config, "server",						       mainconfig.name);			if (cs) this->server = mainconfig.name;		}		*last = this;		last = &(this->next);	} else if (mainconfig.port > 0) { /* no bind address, but a port */		radlog(L_ERR, "The command-line says \"-p %d\", but there is no associated IP address to use",		       mainconfig.port);		return -1;	}	/*	 *	They specified an IP on the command-line, ignore	 *	all listen sections except the one in '-n'.	 */	if (mainconfig.myip.af != AF_UNSPEC) {		CONF_SECTION *subcs;		const char *name2 = cf_section_name2(cs);		cs = cf_section_sub_find_name2(config, "server",					       mainconfig.name);		if (!cs) goto do_proxy;		/*		 *	Should really abstract this code...		 */		for (subcs = cf_subsection_find_next(cs, NULL, "listen");		     subcs != NULL;		     subcs = cf_subsection_find_next(cs, subcs, "listen")) {			this = listen_parse(subcs, name2);			if (!this) {				listen_free(head);				return -1;			}			if (this->type == RAD_LISTEN_PROXY) defined_proxy = 1;						*last = this;			last = &(this->next);		} /* loop over "listen" directives in server <foo> */		goto do_proxy;	}	/*	 *	Walk through the "listen" sections, if they exist.	 */	for (cs = cf_subsection_find_next(config, NULL, "listen");	     cs != NULL;	     cs = cf_subsection_find_next(config, cs, "listen")) {		this = listen_parse(cs, NULL);		if (!this) {			listen_free(head);			return -1;		}		if (this->type == RAD_LISTEN_PROXY) defined_proxy = 1;		*last = this;		last = &(this->next);	}	/*	 *	Check virtual servers for "listen" sections, too.	 *	 *	FIXME: Move to virtual server init?	 */	for (cs = cf_subsection_find_next(config, NULL, "server");	     cs != NULL;	     cs = cf_subsection_find_next(config, cs, "server")) {		CONF_SECTION *subcs;		const char *name2 = cf_section_name2(cs);				for (subcs = cf_subsection_find_next(cs, NULL, "listen");		     subcs != NULL;		     subcs = cf_subsection_find_next(cs, subcs, "listen")) {			this = listen_parse(subcs, name2);			if (!this) {				listen_free(head);				return -1;			}						if (this->type == RAD_LISTEN_PROXY) {				radlog(L_ERR, "Error: listen type \"proxy\" Cannot appear in a virtual server section");				listen_free(head);				return -1;			}			*last = this;			last = &(this->next);		} /* loop over "listen" directives in virtual servers */	} /* loop over virtual servers */	/*	 *	If we're proxying requests, open the proxy FD.	 *	Otherwise, don't do anything.	 */ do_proxy:	if (mainconfig.proxy_requests == TRUE) {		int		port = -1;		listen_socket_t *sock = NULL;		/*		 *	No sockets to receive packets, therefore		 *	proxying is pointless.		 */		if (!*head) return -1;		if (defined_proxy) goto do_snmp;		/*		 *	Find the first authentication port,		 *	and use it		 */		for (this = *head; this != NULL; this = this->next) {			if (this->type == RAD_LISTEN_AUTH) {				sock = this->data;				if (server_ipaddr.af == AF_UNSPEC) {					server_ipaddr = sock->ipaddr;				}				port = sock->port + 2; /* skip acct port */				break;			}			if (this->type == RAD_LISTEN_VQP) {				sock = this->data;				if (server_ipaddr.af == AF_UNSPEC) {					server_ipaddr = sock->ipaddr;				}				port = sock->port + 1;				break;			}		}		if (port < 0) port = 1024 + (fr_rand() & 0x1ff);		/*		 *	Address is still unspecified, use IPv4.		 */		if (server_ipaddr.af == AF_UNSPEC) {			server_ipaddr.af = AF_INET;			server_ipaddr.ipaddr.ip4addr.s_addr = htonl(INADDR_ANY);		}		this = listen_alloc(RAD_LISTEN_PROXY);		sock = this->data;		/*		 *	Create the first proxy socket.		 */		sock->ipaddr = server_ipaddr;		/*		 *	Try to find a proxy port (value doesn't matter)		 */		for (sock->port = port;		     sock->port < 64000;		     sock->port++) {			if (listen_bind(this) == 0) {				*last = this;				last = &(this->next); /* just in case */				break;			}		}		if (sock->port >= 64000) {			listen_free(head);			listen_free(&this);			radlog(L_ERR, "Failed to open socket for proxying");			return -1;		}	} do_snmp:#ifdef WITH_SNMP	if (radius_snmp_init(config)) {		this = rad_malloc(sizeof(*this));		memset(this, 0, sizeof(*this));		this->type = RAD_LISTEN_SNMP;		this->fd = rad_snmp.smux_fd;		this->recv = radius_snmp_recv;		this->print = radius_snmp_print;		*last = this;		last = &(this->next);	}#endif	return 0;}/* *	Free a linked list of listeners; */void listen_free(rad_listen_t **head){	rad_listen_t *this;	if (!head || !*head) return;	this = *head;	while (this) {		rad_listen_t *next = this->next;		/*		 *	Other code may have eaten the FD.		 */		if (this->fd >= 0) close(this->fd);		if (master_listen[this->type].free) {			master_listen[this->type].free(this);		}		free(this->data);		free(this);		this = next;	}	*head = NULL;}

⌨️ 快捷键说明

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