hostapd: add support for automatically setting RADIUS own-ip dynamically
Some servers use the NAS-IP-Address attribute as a destination address Signed-off-by: Felix Fietkau <nbd@nbd.name>
This commit is contained in:
		| @@ -687,7 +687,7 @@ hostapd_set_bss_options() { | |||||||
| 			json_get_vars \ | 			json_get_vars \ | ||||||
| 				auth_server auth_secret auth_port \ | 				auth_server auth_secret auth_port \ | ||||||
| 				dae_client dae_secret dae_port \ | 				dae_client dae_secret dae_port \ | ||||||
| 				ownip radius_client_addr \ | 				dynamic_ownip ownip radius_client_addr \ | ||||||
| 				eap_reauth_period request_cui \ | 				eap_reauth_period request_cui \ | ||||||
| 				erp_domain mobility_domain \ | 				erp_domain mobility_domain \ | ||||||
| 				fils_realm fils_dhcp | 				fils_realm fils_dhcp | ||||||
| @@ -695,6 +695,8 @@ hostapd_set_bss_options() { | |||||||
| 			# radius can provide VLAN ID for clients | 			# radius can provide VLAN ID for clients | ||||||
| 			vlan_possible=1 | 			vlan_possible=1 | ||||||
|  |  | ||||||
|  | 			set_default dynamic_ownip 1 | ||||||
|  |  | ||||||
| 			# legacy compatibility | 			# legacy compatibility | ||||||
| 			[ -n "$auth_server" ] || json_get_var auth_server server | 			[ -n "$auth_server" ] || json_get_var auth_server server | ||||||
| 			[ -n "$auth_port" ] || json_get_var auth_port port | 			[ -n "$auth_port" ] || json_get_var auth_port port | ||||||
| @@ -743,7 +745,12 @@ hostapd_set_bss_options() { | |||||||
| 			} | 			} | ||||||
| 			json_for_each_item append_radius_auth_req_attr radius_auth_req_attr | 			json_for_each_item append_radius_auth_req_attr radius_auth_req_attr | ||||||
|  |  | ||||||
| 			[ -n "$ownip" ] && append bss_conf "own_ip_addr=$ownip" "$N" | 			if [ -n "$ownip" ]; then | ||||||
|  | 				append bss_conf "own_ip_addr=$ownip" "$N" | ||||||
|  | 			elif [ "$dynamic_ownip" -gt 0 ]; then | ||||||
|  | 				append bss_conf "dynamic_own_ip_addr=$dynamic_ownip" "$N" | ||||||
|  | 			fi | ||||||
|  |  | ||||||
| 			[ -n "$radius_client_addr" ] && append bss_conf "radius_client_addr=$radius_client_addr" "$N" | 			[ -n "$radius_client_addr" ] && append bss_conf "radius_client_addr=$radius_client_addr" "$N" | ||||||
| 			append bss_conf "eapol_key_index_workaround=1" "$N" | 			append bss_conf "eapol_key_index_workaround=1" "$N" | ||||||
| 			append bss_conf "ieee8021x=1" "$N" | 			append bss_conf "ieee8021x=1" "$N" | ||||||
|   | |||||||
| @@ -0,0 +1,109 @@ | |||||||
|  | --- a/src/ap/ap_config.h | ||||||
|  | +++ b/src/ap/ap_config.h | ||||||
|  | @@ -311,6 +311,7 @@ struct hostapd_bss_config { | ||||||
|  |  	unsigned int eap_sim_db_timeout; | ||||||
|  |  	int eap_server_erp; /* Whether ERP is enabled on internal EAP server */ | ||||||
|  |  	struct hostapd_ip_addr own_ip_addr; | ||||||
|  | +	int dynamic_own_ip_addr; | ||||||
|  |  	char *nas_identifier; | ||||||
|  |  	struct hostapd_radius_servers *radius; | ||||||
|  |  	int acct_interim_interval; | ||||||
|  | --- a/src/radius/radius_client.c | ||||||
|  | +++ b/src/radius/radius_client.c | ||||||
|  | @@ -163,6 +163,8 @@ struct radius_client_data { | ||||||
|  |  	 */ | ||||||
|  |  	void *ctx; | ||||||
|  |   | ||||||
|  | +	struct hostapd_ip_addr local_ip; | ||||||
|  | + | ||||||
|  |  	/** | ||||||
|  |  	 * conf - RADIUS client configuration (list of RADIUS servers to use) | ||||||
|  |  	 */ | ||||||
|  | @@ -720,6 +722,30 @@ static void radius_client_list_add(struc | ||||||
|  |   | ||||||
|  |   | ||||||
|  |  /** | ||||||
|  | + * radius_client_send - Get local address for the RADIUS auth socket | ||||||
|  | + * @radius: RADIUS client context from radius_client_init() | ||||||
|  | + * @addr: pointer to store the address | ||||||
|  | + * | ||||||
|  | + * This function returns the local address for the connection to the RADIUS | ||||||
|  | + * auth server. It also opens the socket if it's not available yet. | ||||||
|  | + */ | ||||||
|  | +int radius_client_get_local_addr(struct radius_client_data *radius, | ||||||
|  | +				 struct hostapd_ip_addr *addr) | ||||||
|  | +{ | ||||||
|  | +	struct hostapd_radius_servers *conf = radius->conf; | ||||||
|  | + | ||||||
|  | +	if (conf->auth_server && radius->auth_sock < 0) | ||||||
|  | +		radius_client_init_auth(radius); | ||||||
|  | + | ||||||
|  | +	if (radius->auth_sock < 0) | ||||||
|  | +		return -1; | ||||||
|  | + | ||||||
|  | +	memcpy(addr, &radius->local_ip, sizeof(*addr)); | ||||||
|  | + | ||||||
|  | +	return 0; | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +/** | ||||||
|  |   * radius_client_send - Send a RADIUS request | ||||||
|  |   * @radius: RADIUS client context from radius_client_init() | ||||||
|  |   * @msg: RADIUS message to be sent | ||||||
|  | @@ -1238,6 +1264,10 @@ radius_change_server(struct radius_clien | ||||||
|  |  			wpa_printf(MSG_DEBUG, "RADIUS local address: %s:%u", | ||||||
|  |  				   inet_ntoa(claddr.sin_addr), | ||||||
|  |  				   ntohs(claddr.sin_port)); | ||||||
|  | +			if (auth) { | ||||||
|  | +				radius->local_ip.af = AF_INET; | ||||||
|  | +				radius->local_ip.u.v4 = claddr.sin_addr; | ||||||
|  | +			} | ||||||
|  |  		} | ||||||
|  |  		break; | ||||||
|  |  #ifdef CONFIG_IPV6 | ||||||
|  | @@ -1249,6 +1279,10 @@ radius_change_server(struct radius_clien | ||||||
|  |  				   inet_ntop(AF_INET6, &claddr6.sin6_addr, | ||||||
|  |  					     abuf, sizeof(abuf)), | ||||||
|  |  				   ntohs(claddr6.sin6_port)); | ||||||
|  | +			if (auth) { | ||||||
|  | +				radius->local_ip.af = AF_INET6; | ||||||
|  | +				radius->local_ip.u.v6 = claddr6.sin6_addr; | ||||||
|  | +			} | ||||||
|  |  		} | ||||||
|  |  		break; | ||||||
|  |  	} | ||||||
|  | --- a/src/radius/radius_client.h | ||||||
|  | +++ b/src/radius/radius_client.h | ||||||
|  | @@ -249,6 +249,8 @@ int radius_client_register(struct radius | ||||||
|  |  void radius_client_set_interim_error_cb(struct radius_client_data *radius, | ||||||
|  |  					void (*cb)(const u8 *addr, void *ctx), | ||||||
|  |  					void *ctx); | ||||||
|  | +int radius_client_get_local_addr(struct radius_client_data *radius, | ||||||
|  | +				 struct hostapd_ip_addr * addr); | ||||||
|  |  int radius_client_send(struct radius_client_data *radius, | ||||||
|  |  		       struct radius_msg *msg, | ||||||
|  |  		       RadiusType msg_type, const u8 *addr); | ||||||
|  | --- a/src/ap/ieee802_1x.c | ||||||
|  | +++ b/src/ap/ieee802_1x.c | ||||||
|  | @@ -535,6 +535,10 @@ int add_common_radius_attr(struct hostap | ||||||
|  |  	struct hostapd_radius_attr *attr; | ||||||
|  |  	int len; | ||||||
|  |   | ||||||
|  | +	if (hapd->conf->dynamic_own_ip_addr) | ||||||
|  | +		radius_client_get_local_addr(hapd->radius, | ||||||
|  | +					     &hapd->conf->own_ip_addr); | ||||||
|  | + | ||||||
|  |  	if (!hostapd_config_get_radius_attr(req_attr, | ||||||
|  |  					    RADIUS_ATTR_NAS_IP_ADDRESS) && | ||||||
|  |  	    hapd->conf->own_ip_addr.af == AF_INET && | ||||||
|  | --- a/hostapd/config_file.c | ||||||
|  | +++ b/hostapd/config_file.c | ||||||
|  | @@ -2681,6 +2681,8 @@ static int hostapd_config_fill(struct ho | ||||||
|  |  	} else if (os_strcmp(buf, "iapp_interface") == 0) { | ||||||
|  |  		wpa_printf(MSG_INFO, "DEPRECATED: iapp_interface not used"); | ||||||
|  |  #endif /* CONFIG_IAPP */ | ||||||
|  | +	} else if (os_strcmp(buf, "dynamic_own_ip_addr") == 0) { | ||||||
|  | +		bss->dynamic_own_ip_addr = atoi(pos); | ||||||
|  |  	} else if (os_strcmp(buf, "own_ip_addr") == 0) { | ||||||
|  |  		if (hostapd_parse_ip_addr(pos, &bss->own_ip_addr)) { | ||||||
|  |  			wpa_printf(MSG_ERROR, | ||||||
		Reference in New Issue
	
	Block a user
	 Felix Fietkau
					Felix Fietkau