]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
RADIUS client: Support SO_BINDTODEVICE
authorBen Greear <greearb@candelatech.com>
Wed, 13 May 2020 20:48:12 +0000 (13:48 -0700)
committerJouni Malinen <j@w1.fi>
Sat, 27 Feb 2021 08:51:15 +0000 (10:51 +0200)
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>
hostapd/config_file.c
hostapd/hostapd.conf
src/ap/ap_config.c
src/radius/radius_client.c
src/radius/radius_client.h

index 64704fb3dc9e688eae99f1976cda2fc649dab1d6..80842b8f499201846a32f7935e76e7f8e4ad4f80 100644 (file)
@@ -2711,6 +2711,9 @@ 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) {
+                       os_free(bss->radius->force_client_dev);
+                       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,
index a3d28efed5435871a66ad3e093775e22e0b1e094..8958abd162259696d441ab4cea04f537a2af38cc 100644 (file)
@@ -1381,6 +1381,12 @@ 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 which allows the network stack to pick the appropriate
+# interface automatically.
+# Example below binds to eth0
+#radius_client_dev=eth0
+
 # RADIUS authentication server
 #auth_server_addr=127.0.0.1
 #auth_server_port=1812
index 419bf7cad4d350fbc650a0969d94dc982d04c1a1..611fa2e2c22916381a0e20fdcac6df3bde5fb70c 100644 (file)
@@ -779,6 +779,7 @@ void hostapd_config_free_bss(struct hostapd_bss_config *conf)
                                           conf->radius->num_auth_servers);
                hostapd_config_free_radius(conf->radius->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_acct_req_attr);
index bfcb9442ba9f3dd49d64b28f5df934bd72549b61..4f0ff07547da02249b527b5d1946e3f22d33cb81 100644 (file)
@@ -7,6 +7,7 @@
  */
 
 #include "includes.h"
+#include <net/if.h>
 
 #include "common.h"
 #include "radius.h"
@@ -1168,6 +1169,29 @@ 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,
+                              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) {
                switch (conf->client_addr.af) {
                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) {
                wpa_printf(MSG_INFO, "connect[radius]: %s", strerror(errno));
                return -1;
index 8ca0874db498a10ee9b58c4fab673438aa87e43b..687cd81aed915be03be4fcbe2011380a11c8940c 100644 (file)
@@ -174,6 +174,11 @@ struct hostapd_radius_servers {
         * force_client_addr - Whether to force client (local) address
         */
        int force_client_addr;
+
+       /**
+        * force_client_dev - Bind the socket to a specified interface, if set
+        */
+       char *force_client_dev;
 };