Re: [PATCH] hostapd: Support SO_BINDTODEVICE for radius client.

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi Ben,

thanks for this patch. We applied it locally and with some modifications we got it to work.

The most important modification for us was to move the 'force disconnect part', the one which follows after the client-addr bind, before we do the SO_BINDTODEVICE. If we do a connect with the disconnect_addr which has a sin_family AF_UNSPEC, we loose the SO_BINDTODEVICE on the socket.
This is the reason we moved it right before we bind the device.

The second modification is the usage of setsockopt(). Your's was not wrong but irritating while reading the first time. We just use the devicename and its length for the 4th and 5th argument instead of the irfeq.

Attached the updated patch with our modifications.

Cool thing!

Thanks,
Andreas

On 13.05.20 22:48, greearb@xxxxxxxxxxxxxxx wrote:
From: Ben Greear <greearb@xxxxxxxxxxxxxxx>

This helps hostapd work better in VRF and other fancy
network environments.

Signed-off-by: Ben Greear <greearb@xxxxxxxxxxxxxxx>
---
  hostapd/config_file.c      |  2 ++
  hostapd/hostapd.conf       |  5 +++++
  src/radius/radius_client.c | 20 ++++++++++++++++++++
  src/radius/radius_client.h |  5 +++++
  4 files changed, 32 insertions(+)

diff --git a/hostapd/config_file.c b/hostapd/config_file.c
index 905402cf6..a2c8fbb79 100644
--- a/hostapd/config_file.c
+++ b/hostapd/config_file.c
@@ -2727,6 +2727,8 @@ static int hostapd_config_fill(struct hostapd_config *conf,
  			return 1;
  		}
  		bss->radius->force_client_addr = 1;
+	} else if (os_strcmp(buf, "radius_client_dev") == 0) {
+			bss->radius->force_client_dev = os_strdup(pos);
  	} else if (os_strcmp(buf, "auth_server_addr") == 0) {
  		if (hostapd_config_read_radius_addr(
  			    &bss->radius->auth_servers,
diff --git a/hostapd/hostapd.conf b/hostapd/hostapd.conf
index 769a59ae8..b5719f8e7 100644
--- a/hostapd/hostapd.conf
+++ b/hostapd/hostapd.conf
@@ -1312,6 +1312,11 @@ own_ip_addr=127.0.0.1
  # used, e.g., when the device has multiple IP addresses.
  #radius_client_addr=127.0.0.1
+# RADIUS client forced local interface. Helps run properly with VRF
+# Default is none set.
+# Example below binds to eth0
+#radius_client_dev=eth0
+
  # RADIUS authentication server
  #auth_server_addr=127.0.0.1
  #auth_server_port=1812
diff --git a/src/radius/radius_client.c b/src/radius/radius_client.c
index 2b7a604ed..a2ed9d410 100644
--- a/src/radius/radius_client.c
+++ b/src/radius/radius_client.c
@@ -12,6 +12,7 @@
  #include "radius.h"
  #include "radius_client.h"
  #include "eloop.h"
+#include <net/if.h>
/* Defaults for RADIUS retransmit values (exponential backoff) */ @@ -1159,6 +1160,25 @@ radius_change_server(struct radius_client_data *radius,
  		return -1;
  	}
+#ifdef __linux__
+	if (conf->force_client_dev && conf->force_client_dev[0]) {
+		struct ifreq ifr;
+		os_memset(&ifr, 0, sizeof(ifr));
+		os_strlcpy(ifr.ifr_ifrn.ifrn_name, conf->force_client_dev, IFNAMSIZ);
+		if (setsockopt(sel_sock, SOL_SOCKET, SO_BINDTODEVICE,
+			       (char *) &ifr, sizeof(ifr)) < 0) {
+			wpa_printf(MSG_ERROR,
+				   "setsockopt[RADIUS CLIENT, SO_BINDTODEVICE]: %s",
+				   strerror(errno));
+			/* probably not critical error, continue on and hope for the best. */
+		}
+		else {
+			wpa_printf(MSG_ERROR,
+				   "Bound radius client socket to device: %s", conf->force_client_dev);
+		}
+	}
+#endif
+
  	if (conf->force_client_addr) {
  		switch (conf->client_addr.af) {
  		case AF_INET:
diff --git a/src/radius/radius_client.h b/src/radius/radius_client.h
index 8ca0874db..4d050545b 100644
--- a/src/radius/radius_client.h
+++ b/src/radius/radius_client.h
@@ -174,6 +174,11 @@ struct hostapd_radius_servers {
  	 * force_client_addr - Whether to force client (local) address
  	 */
  	int force_client_addr;
+
+	/**
+	 * Will call SO_BINDTODEVICE on this if non null and non-empty string.
+	 */
+	char* force_client_dev;
  };

From 810efc8ae1c27064fa800328c6c924326cf8a162 Mon Sep 17 00:00:00 2001
From: Ben Greear <greearb at candelatech.com>
Date: Wed, 13 May 2020 13:48:12 -0700
Subject: [PATCH] hostapd: Support SO_BINDTODEVICE for radius client.

This helps hostapd work better in VRF and other fancy
network environments.

Signed-off-by: Ben Greear <greearb at candelatech.com>
Signed-off-by: Andreas Tobler <andreas.tobler at onway.ch>
---
 hostapd/config_file.c      |  2 ++
 hostapd/hostapd.conf       |  5 +++++
 src/radius/radius_client.c | 28 +++++++++++++++++++++++-----
 src/radius/radius_client.h |  5 +++++
 4 files changed, 35 insertions(+), 5 deletions(-)

diff --git a/hostapd/config_file.c b/hostapd/config_file.c
index 8f7fcd8b7..76f695804 100644
--- a/hostapd/config_file.c
+++ b/hostapd/config_file.c
@@ -2677,6 +2677,8 @@ static int hostapd_config_fill(struct hostapd_config *conf,
 			return 1;
 		}
 		bss->radius->force_client_addr = 1;
+	} else if (os_strcmp(buf, "radius_client_dev") == 0) {
+			bss->radius->force_client_dev = os_strdup(pos);
 	} else if (os_strcmp(buf, "auth_server_addr") == 0) {
 		if (hostapd_config_read_radius_addr(
 			    &bss->radius->auth_servers,
diff --git a/hostapd/hostapd.conf b/hostapd/hostapd.conf
index 2b0f762e5..895d13290 100644
--- a/hostapd/hostapd.conf
+++ b/hostapd/hostapd.conf
@@ -1305,6 +1305,11 @@ own_ip_addr=127.0.0.1
 # used, e.g., when the device has multiple IP addresses.
 #radius_client_addr=127.0.0.1
 
+# RADIUS client forced local interface.  Helps run properly with VRF
+# Default is none set.
+# Example below binds to eth0
+#radius_client_dev=eth0
+
 # RADIUS authentication server
 #auth_server_addr=127.0.0.1
 #auth_server_port=1812
diff --git a/src/radius/radius_client.c b/src/radius/radius_client.c
index 2b7a604ed..dc685b288 100644
--- a/src/radius/radius_client.c
+++ b/src/radius/radius_client.c
@@ -12,6 +12,7 @@
 #include "radius.h"
 #include "radius_client.h"
 #include "eloop.h"
+#include <net/if.h>
 
 /* Defaults for RADIUS retransmit values (exponential backoff) */
 
@@ -1159,6 +1160,28 @@ radius_change_server(struct radius_client_data *radius,
 		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,
+			       strlen(conf->force_client_dev)) < 0) {
+			wpa_printf(MSG_ERROR,
+				   "setsockopt[RADIUS CLIENT, SO_BINDTODEVICE]: %s",
+				   strerror(errno));
+			/* probably not critical error, continue on and hope for the best. */
+		}
+		else {
+			wpa_printf(MSG_ERROR,
+				   "Bound radius client socket to device: %s", conf->force_client_dev);
+		}
+	}
+#endif
+
 	if (conf->force_client_addr) {
 		switch (conf->client_addr.af) {
 		case AF_INET:
@@ -1191,11 +1214,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) {
 		wpa_printf(MSG_INFO, "connect[radius]: %s", strerror(errno));
 		return -1;
diff --git a/src/radius/radius_client.h b/src/radius/radius_client.h
index 8ca0874db..4d050545b 100644
--- a/src/radius/radius_client.h
+++ b/src/radius/radius_client.h
@@ -174,6 +174,11 @@ struct hostapd_radius_servers {
 	 * force_client_addr - Whether to force client (local) address
 	 */
 	int force_client_addr;
+
+	/**
+	 * Will call SO_BINDTODEVICE on this if non null and non-empty string.
+	 */
+	char* force_client_dev;
 };
 
 
-- 
2.25.1

_______________________________________________
Hostap mailing list
Hostap@xxxxxxxxxxxxxxxxxxx
http://lists.infradead.org/mailman/listinfo/hostap

[Index of Archives]     [Linux Wireless]     [Linux Kernel]     [ATH6KL]     [Linux Bluetooth]     [Linux Netdev]     [Kernel Newbies]     [IDE]     [Security]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux ATA RAID]     [Samba]     [Device Mapper]

  Powered by Linux