RADIUS client: Support SO_BINDTODEVICE
Allow the RADIUS client socket to be bound to a specific netdev. This helps hostapd work better in VRF and other fancy network environments. Signed-off-by: Ben Greear <greearb@candelatech.com> Signed-off-by: Andreas Tobler <andreas.tobler at onway.ch>
This commit is contained in:
parent
3a05f89edc
commit
827b43b3ca
5 changed files with 39 additions and 5 deletions
|
@ -2711,6 +2711,9 @@ static int hostapd_config_fill(struct hostapd_config *conf,
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
bss->radius->force_client_addr = 1;
|
bss->radius->force_client_addr = 1;
|
||||||
|
} else if (os_strcmp(buf, "radius_client_dev") == 0) {
|
||||||
|
os_free(bss->radius->force_client_dev);
|
||||||
|
bss->radius->force_client_dev = os_strdup(pos);
|
||||||
} else if (os_strcmp(buf, "auth_server_addr") == 0) {
|
} else if (os_strcmp(buf, "auth_server_addr") == 0) {
|
||||||
if (hostapd_config_read_radius_addr(
|
if (hostapd_config_read_radius_addr(
|
||||||
&bss->radius->auth_servers,
|
&bss->radius->auth_servers,
|
||||||
|
|
|
@ -1381,6 +1381,12 @@ own_ip_addr=127.0.0.1
|
||||||
# used, e.g., when the device has multiple IP addresses.
|
# used, e.g., when the device has multiple IP addresses.
|
||||||
#radius_client_addr=127.0.0.1
|
#radius_client_addr=127.0.0.1
|
||||||
|
|
||||||
|
# RADIUS client forced local interface. Helps run properly with VRF
|
||||||
|
# Default is none set which allows the network stack to pick the appropriate
|
||||||
|
# interface automatically.
|
||||||
|
# Example below binds to eth0
|
||||||
|
#radius_client_dev=eth0
|
||||||
|
|
||||||
# RADIUS authentication server
|
# RADIUS authentication server
|
||||||
#auth_server_addr=127.0.0.1
|
#auth_server_addr=127.0.0.1
|
||||||
#auth_server_port=1812
|
#auth_server_port=1812
|
||||||
|
|
|
@ -779,6 +779,7 @@ void hostapd_config_free_bss(struct hostapd_bss_config *conf)
|
||||||
conf->radius->num_auth_servers);
|
conf->radius->num_auth_servers);
|
||||||
hostapd_config_free_radius(conf->radius->acct_servers,
|
hostapd_config_free_radius(conf->radius->acct_servers,
|
||||||
conf->radius->num_acct_servers);
|
conf->radius->num_acct_servers);
|
||||||
|
os_free(conf->radius->force_client_dev);
|
||||||
}
|
}
|
||||||
hostapd_config_free_radius_attr(conf->radius_auth_req_attr);
|
hostapd_config_free_radius_attr(conf->radius_auth_req_attr);
|
||||||
hostapd_config_free_radius_attr(conf->radius_acct_req_attr);
|
hostapd_config_free_radius_attr(conf->radius_acct_req_attr);
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "includes.h"
|
#include "includes.h"
|
||||||
|
#include <net/if.h>
|
||||||
|
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "radius.h"
|
#include "radius.h"
|
||||||
|
@ -1168,6 +1169,29 @@ radius_change_server(struct radius_client_data *radius,
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Force a reconnect by disconnecting the socket first */
|
||||||
|
if (connect(sel_sock, (struct sockaddr *) &disconnect_addr,
|
||||||
|
sizeof(disconnect_addr)) < 0)
|
||||||
|
wpa_printf(MSG_INFO, "disconnect[radius]: %s", strerror(errno));
|
||||||
|
|
||||||
|
#ifdef __linux__
|
||||||
|
if (conf->force_client_dev && conf->force_client_dev[0]) {
|
||||||
|
if (setsockopt(sel_sock, SOL_SOCKET, SO_BINDTODEVICE,
|
||||||
|
conf->force_client_dev,
|
||||||
|
os_strlen(conf->force_client_dev)) < 0) {
|
||||||
|
wpa_printf(MSG_ERROR,
|
||||||
|
"RADIUS: setsockopt[SO_BINDTODEVICE]: %s",
|
||||||
|
strerror(errno));
|
||||||
|
/* Probably not a critical error; continue on and hope
|
||||||
|
* for the best. */
|
||||||
|
} else {
|
||||||
|
wpa_printf(MSG_DEBUG,
|
||||||
|
"RADIUS: Bound client socket to device: %s",
|
||||||
|
conf->force_client_dev);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif /* __linux__ */
|
||||||
|
|
||||||
if (conf->force_client_addr) {
|
if (conf->force_client_addr) {
|
||||||
switch (conf->client_addr.af) {
|
switch (conf->client_addr.af) {
|
||||||
case AF_INET:
|
case AF_INET:
|
||||||
|
@ -1200,11 +1224,6 @@ radius_change_server(struct radius_client_data *radius,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Force a reconnect by disconnecting the socket first */
|
|
||||||
if (connect(sel_sock, (struct sockaddr *) &disconnect_addr,
|
|
||||||
sizeof(disconnect_addr)) < 0)
|
|
||||||
wpa_printf(MSG_INFO, "disconnect[radius]: %s", strerror(errno));
|
|
||||||
|
|
||||||
if (connect(sel_sock, addr, addrlen) < 0) {
|
if (connect(sel_sock, addr, addrlen) < 0) {
|
||||||
wpa_printf(MSG_INFO, "connect[radius]: %s", strerror(errno));
|
wpa_printf(MSG_INFO, "connect[radius]: %s", strerror(errno));
|
||||||
return -1;
|
return -1;
|
||||||
|
|
|
@ -174,6 +174,11 @@ struct hostapd_radius_servers {
|
||||||
* force_client_addr - Whether to force client (local) address
|
* force_client_addr - Whether to force client (local) address
|
||||||
*/
|
*/
|
||||||
int force_client_addr;
|
int force_client_addr;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* force_client_dev - Bind the socket to a specified interface, if set
|
||||||
|
*/
|
||||||
|
char *force_client_dev;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue