Add interface matching support with -M, guarded by CONFIG_MATCH_IFACE
The new wpa_supplicant command line argument -M can be used to describe matching rules with a wildcard interface name (e.g., "wlan*"). This is very useful for systems without udev (Linux) or devd (FreeBSD). Signed-off-by: Roy Marples <roy@marples.name>
This commit is contained in:
parent
45e3fc72c6
commit
2e997eece5
7 changed files with 205 additions and 2 deletions
|
@ -316,6 +316,10 @@ CFLAGS += -DCONFIG_NO_VLAN
|
||||||
OBJS += ibss_rsn.o
|
OBJS += ibss_rsn.o
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
ifdef CONFIG_MATCH_IFACE
|
||||||
|
CFLAGS += -DCONFIG_MATCH_IFACE
|
||||||
|
endif
|
||||||
|
|
||||||
ifdef CONFIG_P2P
|
ifdef CONFIG_P2P
|
||||||
OBJS += p2p_supplicant.o
|
OBJS += p2p_supplicant.o
|
||||||
OBJS += p2p_supplicant_sd.o
|
OBJS += p2p_supplicant_sd.o
|
||||||
|
|
|
@ -410,7 +410,7 @@ usage:
|
||||||
wpa_supplicant [-BddfhKLqqtuvW] [-P<pid file>] [-g<global ctrl>] \
|
wpa_supplicant [-BddfhKLqqtuvW] [-P<pid file>] [-g<global ctrl>] \
|
||||||
[-G<group>] \
|
[-G<group>] \
|
||||||
-i<ifname> -c<config file> [-C<ctrl>] [-D<driver>] [-p<driver_param>] \
|
-i<ifname> -c<config file> [-C<ctrl>] [-D<driver>] [-p<driver_param>] \
|
||||||
[-b<br_ifname> [-N -i<ifname> -c<conf> [-C<ctrl>] [-D<driver>] \
|
[-b<br_ifname> [-MN -i<ifname> -c<conf> [-C<ctrl>] [-D<driver>] \
|
||||||
[-p<driver_param>] [-b<br_ifname>] [-m<P2P Device config file>] ...
|
[-p<driver_param>] [-b<br_ifname>] [-m<P2P Device config file>] ...
|
||||||
|
|
||||||
options:
|
options:
|
||||||
|
@ -434,6 +434,7 @@ options:
|
||||||
-u = enable DBus control interface
|
-u = enable DBus control interface
|
||||||
-v = show version
|
-v = show version
|
||||||
-W = wait for a control interface monitor before starting
|
-W = wait for a control interface monitor before starting
|
||||||
|
-M = start describing matching interface
|
||||||
-N = start describing new interface
|
-N = start describing new interface
|
||||||
-m = Configuration file for the P2P Device
|
-m = Configuration file for the P2P Device
|
||||||
|
|
||||||
|
@ -476,6 +477,22 @@ wpa_supplicant \
|
||||||
-c wpa2.conf -i wlan1 -D wext
|
-c wpa2.conf -i wlan1 -D wext
|
||||||
|
|
||||||
|
|
||||||
|
If the interfaces on which wpa_supplicant is to run are not known or do
|
||||||
|
not exist, wpa_supplicant can match an interface when it arrives. Each
|
||||||
|
matched interface is separated with -M argument and the -i argument now
|
||||||
|
allows for pattern matching.
|
||||||
|
|
||||||
|
As an example, the following command would start wpa_supplicant for a
|
||||||
|
specific wired interface called lan0, any interface starting with wlan
|
||||||
|
and lastly any other interface. Each match has its own configuration
|
||||||
|
file, and for the wired interface a specific driver has also been given.
|
||||||
|
|
||||||
|
wpa_supplicant \
|
||||||
|
-M -c wpa_wired.conf -ilan0 -D wired \
|
||||||
|
-M -c wpa1.conf -iwlan* \
|
||||||
|
-M -c wpa2.conf
|
||||||
|
|
||||||
|
|
||||||
If the interface is added in a Linux bridge (e.g., br0), the bridge
|
If the interface is added in a Linux bridge (e.g., br0), the bridge
|
||||||
interface needs to be configured to wpa_supplicant in addition to the
|
interface needs to be configured to wpa_supplicant in addition to the
|
||||||
main interface:
|
main interface:
|
||||||
|
|
|
@ -467,6 +467,9 @@ CONFIG_PEERKEY=y
|
||||||
# Hotspot 2.0
|
# Hotspot 2.0
|
||||||
#CONFIG_HS20=y
|
#CONFIG_HS20=y
|
||||||
|
|
||||||
|
# Enable interface matching in wpa_supplicant
|
||||||
|
#CONFIG_MATCH_IFACE=y
|
||||||
|
|
||||||
# Disable roaming in wpa_supplicant
|
# Disable roaming in wpa_supplicant
|
||||||
#CONFIG_NO_ROAMING=y
|
#CONFIG_NO_ROAMING=y
|
||||||
|
|
||||||
|
|
|
@ -2758,6 +2758,13 @@ wpa_supplicant_event_interface_status(struct wpa_supplicant *wpa_s,
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_P2P */
|
#endif /* CONFIG_P2P */
|
||||||
|
|
||||||
|
#ifdef CONFIG_MATCH_IFACE
|
||||||
|
if (wpa_s->matched) {
|
||||||
|
wpa_supplicant_remove_iface(wpa_s->global, wpa_s, 0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_MATCH_IFACE */
|
||||||
|
|
||||||
#ifdef CONFIG_TERMINATE_ONLASTIF
|
#ifdef CONFIG_TERMINATE_ONLASTIF
|
||||||
/* check if last interface */
|
/* check if last interface */
|
||||||
if (!any_interfaces(wpa_s->global->ifaces))
|
if (!any_interfaces(wpa_s->global->ifaces))
|
||||||
|
@ -4030,6 +4037,20 @@ void wpa_supplicant_event_global(void *ctx, enum wpa_event_type event,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#ifdef CONFIG_MATCH_IFACE
|
||||||
|
else if (data->interface_status.ievent == EVENT_INTERFACE_ADDED) {
|
||||||
|
struct wpa_interface *wpa_i;
|
||||||
|
|
||||||
|
wpa_i = wpa_supplicant_match_iface(
|
||||||
|
ctx, data->interface_status.ifname);
|
||||||
|
if (!wpa_i)
|
||||||
|
return;
|
||||||
|
wpa_s = wpa_supplicant_add_iface(ctx, wpa_i, NULL);
|
||||||
|
os_free(wpa_i);
|
||||||
|
if (wpa_s)
|
||||||
|
wpa_s->matched = 1;
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_MATCH_IFACE */
|
||||||
|
|
||||||
if (wpa_s)
|
if (wpa_s)
|
||||||
wpa_supplicant_event(wpa_s, event, data);
|
wpa_supplicant_event(wpa_s, event, data);
|
||||||
|
|
|
@ -81,6 +81,9 @@ static void usage(void)
|
||||||
#ifdef CONFIG_P2P
|
#ifdef CONFIG_P2P
|
||||||
" -m = Configuration file for the P2P Device interface\n"
|
" -m = Configuration file for the P2P Device interface\n"
|
||||||
#endif /* CONFIG_P2P */
|
#endif /* CONFIG_P2P */
|
||||||
|
#ifdef CONFIG_MATCH_IFACE
|
||||||
|
" -M = start describing new matching interface\n"
|
||||||
|
#endif /* CONFIG_MATCH_IFACE */
|
||||||
" -N = start describing new interface\n"
|
" -N = start describing new interface\n"
|
||||||
" -o = override driver parameter for new interfaces\n"
|
" -o = override driver parameter for new interfaces\n"
|
||||||
" -O = override ctrl_interface parameter for new interfaces\n"
|
" -O = override ctrl_interface parameter for new interfaces\n"
|
||||||
|
@ -153,6 +156,28 @@ static void wpa_supplicant_fd_workaround(int start)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef CONFIG_MATCH_IFACE
|
||||||
|
static int wpa_supplicant_init_match(struct wpa_global *global)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* The assumption is that the first driver is the primary driver and
|
||||||
|
* will handle the arrival / departure of interfaces.
|
||||||
|
*/
|
||||||
|
if (wpa_drivers[0]->global_init && !global->drv_priv[0]) {
|
||||||
|
global->drv_priv[0] = wpa_drivers[0]->global_init(global);
|
||||||
|
if (!global->drv_priv[0]) {
|
||||||
|
wpa_printf(MSG_ERROR,
|
||||||
|
"Failed to initialize driver '%s'",
|
||||||
|
wpa_drivers[0]->name);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_MATCH_IFACE */
|
||||||
|
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
int c, i;
|
int c, i;
|
||||||
|
@ -176,7 +201,7 @@ int main(int argc, char *argv[])
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
c = getopt(argc, argv,
|
c = getopt(argc, argv,
|
||||||
"b:Bc:C:D:de:f:g:G:hi:I:KLm:No:O:p:P:qsTtuvW");
|
"b:Bc:C:D:de:f:g:G:hi:I:KLMm:No:O:p:P:qsTtuvW");
|
||||||
if (c < 0)
|
if (c < 0)
|
||||||
break;
|
break;
|
||||||
switch (c) {
|
switch (c) {
|
||||||
|
@ -282,6 +307,20 @@ int main(int argc, char *argv[])
|
||||||
case 'W':
|
case 'W':
|
||||||
params.wait_for_monitor++;
|
params.wait_for_monitor++;
|
||||||
break;
|
break;
|
||||||
|
#ifdef CONFIG_MATCH_IFACE
|
||||||
|
case 'M':
|
||||||
|
params.match_iface_count++;
|
||||||
|
iface = os_realloc_array(params.match_ifaces,
|
||||||
|
params.match_iface_count,
|
||||||
|
sizeof(struct wpa_interface));
|
||||||
|
if (!iface)
|
||||||
|
goto out;
|
||||||
|
params.match_ifaces = iface;
|
||||||
|
iface = ¶ms.match_ifaces[params.match_iface_count -
|
||||||
|
1];
|
||||||
|
os_memset(iface, 0, sizeof(*iface));
|
||||||
|
break;
|
||||||
|
#endif /* CONFIG_MATCH_IFACE */
|
||||||
case 'N':
|
case 'N':
|
||||||
iface_count++;
|
iface_count++;
|
||||||
iface = os_realloc_array(ifaces, iface_count,
|
iface = os_realloc_array(ifaces, iface_count,
|
||||||
|
@ -328,6 +367,9 @@ int main(int argc, char *argv[])
|
||||||
ifaces[i].ctrl_interface == NULL) ||
|
ifaces[i].ctrl_interface == NULL) ||
|
||||||
ifaces[i].ifname == NULL) {
|
ifaces[i].ifname == NULL) {
|
||||||
if (iface_count == 1 && (params.ctrl_interface ||
|
if (iface_count == 1 && (params.ctrl_interface ||
|
||||||
|
#ifdef CONFIG_MATCH_IFACE
|
||||||
|
params.match_iface_count ||
|
||||||
|
#endif /* CONFIG_MATCH_IFACE */
|
||||||
params.dbus_ctrl_interface))
|
params.dbus_ctrl_interface))
|
||||||
break;
|
break;
|
||||||
usage();
|
usage();
|
||||||
|
@ -341,6 +383,11 @@ int main(int argc, char *argv[])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_MATCH_IFACE
|
||||||
|
if (exitcode == 0)
|
||||||
|
exitcode = wpa_supplicant_init_match(global);
|
||||||
|
#endif /* CONFIG_MATCH_IFACE */
|
||||||
|
|
||||||
if (exitcode == 0)
|
if (exitcode == 0)
|
||||||
exitcode = wpa_supplicant_run(global);
|
exitcode = wpa_supplicant_run(global);
|
||||||
|
|
||||||
|
@ -351,6 +398,9 @@ int main(int argc, char *argv[])
|
||||||
out:
|
out:
|
||||||
wpa_supplicant_fd_workaround(0);
|
wpa_supplicant_fd_workaround(0);
|
||||||
os_free(ifaces);
|
os_free(ifaces);
|
||||||
|
#ifdef CONFIG_MATCH_IFACE
|
||||||
|
os_free(params.match_ifaces);
|
||||||
|
#endif /* CONFIG_MATCH_IFACE */
|
||||||
os_free(params.pid_file);
|
os_free(params.pid_file);
|
||||||
|
|
||||||
os_program_deinit();
|
os_program_deinit();
|
||||||
|
|
|
@ -11,6 +11,10 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "includes.h"
|
#include "includes.h"
|
||||||
|
#ifdef CONFIG_MATCH_IFACE
|
||||||
|
#include <net/if.h>
|
||||||
|
#include <fnmatch.h>
|
||||||
|
#endif /* CONFIG_MATCH_IFACE */
|
||||||
|
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "crypto/random.h"
|
#include "crypto/random.h"
|
||||||
|
@ -4911,6 +4915,74 @@ static void wpa_supplicant_deinit_iface(struct wpa_supplicant *wpa_s,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef CONFIG_MATCH_IFACE
|
||||||
|
|
||||||
|
/**
|
||||||
|
* wpa_supplicant_match_iface - Match an interface description to a name
|
||||||
|
* @global: Pointer to global data from wpa_supplicant_init()
|
||||||
|
* @ifname: Name of the interface to match
|
||||||
|
* Returns: Pointer to the created interface description or %NULL on failure
|
||||||
|
*/
|
||||||
|
struct wpa_interface * wpa_supplicant_match_iface(struct wpa_global *global,
|
||||||
|
const char *ifname)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
struct wpa_interface *iface, *miface;
|
||||||
|
|
||||||
|
for (i = 0; i < global->params.match_iface_count; i++) {
|
||||||
|
miface = &global->params.match_ifaces[i];
|
||||||
|
if (!miface->ifname ||
|
||||||
|
fnmatch(miface->ifname, ifname, 0) == 0) {
|
||||||
|
iface = os_zalloc(sizeof(*iface));
|
||||||
|
if (!iface)
|
||||||
|
return NULL;
|
||||||
|
*iface = *miface;
|
||||||
|
iface->ifname = ifname;
|
||||||
|
return iface;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* wpa_supplicant_match_existing - Match existing interfaces
|
||||||
|
* @global: Pointer to global data from wpa_supplicant_init()
|
||||||
|
* Returns: 0 on success, -1 on failure
|
||||||
|
*/
|
||||||
|
static int wpa_supplicant_match_existing(struct wpa_global *global)
|
||||||
|
{
|
||||||
|
struct if_nameindex *ifi, *ifp;
|
||||||
|
struct wpa_supplicant *wpa_s;
|
||||||
|
struct wpa_interface *iface;
|
||||||
|
|
||||||
|
ifp = if_nameindex();
|
||||||
|
if (!ifp) {
|
||||||
|
wpa_printf(MSG_ERROR, "if_nameindex: %s", strerror(errno));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (ifi = ifp; ifi->if_name; ifi++) {
|
||||||
|
wpa_s = wpa_supplicant_get_iface(global, ifi->if_name);
|
||||||
|
if (wpa_s)
|
||||||
|
continue;
|
||||||
|
iface = wpa_supplicant_match_iface(global, ifi->if_name);
|
||||||
|
if (iface) {
|
||||||
|
wpa_s = wpa_supplicant_add_iface(global, iface, NULL);
|
||||||
|
os_free(iface);
|
||||||
|
if (wpa_s)
|
||||||
|
wpa_s->matched = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if_freenameindex(ifp);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* CONFIG_MATCH_IFACE */
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* wpa_supplicant_add_iface - Add a new network interface
|
* wpa_supplicant_add_iface - Add a new network interface
|
||||||
* @global: Pointer to global data from wpa_supplicant_init()
|
* @global: Pointer to global data from wpa_supplicant_init()
|
||||||
|
@ -5212,6 +5284,18 @@ struct wpa_global * wpa_supplicant_init(struct wpa_params *params)
|
||||||
if (params->override_ctrl_interface)
|
if (params->override_ctrl_interface)
|
||||||
global->params.override_ctrl_interface =
|
global->params.override_ctrl_interface =
|
||||||
os_strdup(params->override_ctrl_interface);
|
os_strdup(params->override_ctrl_interface);
|
||||||
|
#ifdef CONFIG_MATCH_IFACE
|
||||||
|
global->params.match_iface_count = params->match_iface_count;
|
||||||
|
if (params->match_iface_count) {
|
||||||
|
global->params.match_ifaces =
|
||||||
|
os_calloc(params->match_iface_count,
|
||||||
|
sizeof(struct wpa_interface));
|
||||||
|
os_memcpy(global->params.match_ifaces,
|
||||||
|
params->match_ifaces,
|
||||||
|
params->match_iface_count *
|
||||||
|
sizeof(struct wpa_interface));
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_MATCH_IFACE */
|
||||||
#ifdef CONFIG_P2P
|
#ifdef CONFIG_P2P
|
||||||
if (params->conf_p2p_dev)
|
if (params->conf_p2p_dev)
|
||||||
global->params.conf_p2p_dev =
|
global->params.conf_p2p_dev =
|
||||||
|
@ -5291,6 +5375,11 @@ int wpa_supplicant_run(struct wpa_global *global)
|
||||||
eloop_sock_requeue()))
|
eloop_sock_requeue()))
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
#ifdef CONFIG_MATCH_IFACE
|
||||||
|
if (wpa_supplicant_match_existing(global))
|
||||||
|
return -1;
|
||||||
|
#endif
|
||||||
|
|
||||||
if (global->params.wait_for_monitor) {
|
if (global->params.wait_for_monitor) {
|
||||||
for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next)
|
for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next)
|
||||||
if (wpa_s->ctrl_iface && !wpa_s->p2p_mgmt)
|
if (wpa_s->ctrl_iface && !wpa_s->p2p_mgmt)
|
||||||
|
@ -5359,6 +5448,9 @@ void wpa_supplicant_deinit(struct wpa_global *global)
|
||||||
os_free(global->params.ctrl_interface_group);
|
os_free(global->params.ctrl_interface_group);
|
||||||
os_free(global->params.override_driver);
|
os_free(global->params.override_driver);
|
||||||
os_free(global->params.override_ctrl_interface);
|
os_free(global->params.override_ctrl_interface);
|
||||||
|
#ifdef CONFIG_MATCH_IFACE
|
||||||
|
os_free(global->params.match_ifaces);
|
||||||
|
#endif /* CONFIG_MATCH_IFACE */
|
||||||
#ifdef CONFIG_P2P
|
#ifdef CONFIG_P2P
|
||||||
os_free(global->params.conf_p2p_dev);
|
os_free(global->params.conf_p2p_dev);
|
||||||
#endif /* CONFIG_P2P */
|
#endif /* CONFIG_P2P */
|
||||||
|
|
|
@ -228,6 +228,17 @@ struct wpa_params {
|
||||||
char *conf_p2p_dev;
|
char *conf_p2p_dev;
|
||||||
#endif /* CONFIG_P2P */
|
#endif /* CONFIG_P2P */
|
||||||
|
|
||||||
|
#ifdef CONFIG_MATCH_IFACE
|
||||||
|
/**
|
||||||
|
* match_ifaces - Interface descriptions to match
|
||||||
|
*/
|
||||||
|
struct wpa_interface *match_ifaces;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* match_iface_count - Number of defined matching interfaces
|
||||||
|
*/
|
||||||
|
int match_iface_count;
|
||||||
|
#endif /* CONFIG_MATCH_IFACE */
|
||||||
};
|
};
|
||||||
|
|
||||||
struct p2p_srv_bonjour {
|
struct p2p_srv_bonjour {
|
||||||
|
@ -458,6 +469,9 @@ struct wpa_supplicant {
|
||||||
unsigned char own_addr[ETH_ALEN];
|
unsigned char own_addr[ETH_ALEN];
|
||||||
unsigned char perm_addr[ETH_ALEN];
|
unsigned char perm_addr[ETH_ALEN];
|
||||||
char ifname[100];
|
char ifname[100];
|
||||||
|
#ifdef CONFIG_MATCH_IFACE
|
||||||
|
int matched;
|
||||||
|
#endif /* CONFIG_MATCH_IFACE */
|
||||||
#ifdef CONFIG_CTRL_IFACE_DBUS
|
#ifdef CONFIG_CTRL_IFACE_DBUS
|
||||||
char *dbus_path;
|
char *dbus_path;
|
||||||
#endif /* CONFIG_CTRL_IFACE_DBUS */
|
#endif /* CONFIG_CTRL_IFACE_DBUS */
|
||||||
|
@ -1108,6 +1122,8 @@ void free_hw_features(struct wpa_supplicant *wpa_s);
|
||||||
|
|
||||||
void wpa_show_license(void);
|
void wpa_show_license(void);
|
||||||
|
|
||||||
|
struct wpa_interface * wpa_supplicant_match_iface(struct wpa_global *global,
|
||||||
|
const char *ifname);
|
||||||
struct wpa_supplicant * wpa_supplicant_add_iface(struct wpa_global *global,
|
struct wpa_supplicant * wpa_supplicant_add_iface(struct wpa_global *global,
|
||||||
struct wpa_interface *iface,
|
struct wpa_interface *iface,
|
||||||
struct wpa_supplicant *parent);
|
struct wpa_supplicant *parent);
|
||||||
|
|
Loading…
Reference in a new issue