Allow multiple driver wrappers to be specified on command line

For example, -Dnl80211,wext could be used to automatically select
between nl80211 and wext. The first driver wrapper that is able to
initialize the interface will be used.
This commit is contained in:
Jouni Malinen 2009-02-14 16:43:43 +02:00
parent 7d315b7b42
commit 362f781e1c
7 changed files with 102 additions and 51 deletions

View file

@ -89,7 +89,7 @@ static void wpa_driver_nl80211_scan_timeout(void *eloop_ctx,
static int wpa_driver_nl80211_set_mode(void *priv, int mode); static int wpa_driver_nl80211_set_mode(void *priv, int mode);
static int wpa_driver_nl80211_flush_pmkid(void *priv); static int wpa_driver_nl80211_flush_pmkid(void *priv);
static int wpa_driver_nl80211_get_range(void *priv); static int wpa_driver_nl80211_get_range(void *priv);
static void static int
wpa_driver_nl80211_finish_drv_init(struct wpa_driver_nl80211_data *drv); wpa_driver_nl80211_finish_drv_init(struct wpa_driver_nl80211_data *drv);
@ -1548,10 +1548,14 @@ static void * wpa_driver_nl80211_init(void *ctx, const char *ifname)
ctx); ctx);
drv->wext_event_sock = s; drv->wext_event_sock = s;
wpa_driver_nl80211_finish_drv_init(drv); if (wpa_driver_nl80211_finish_drv_init(drv))
goto err7;
return drv; return drv;
err7:
eloop_unregister_read_sock(drv->wext_event_sock);
close(drv->wext_event_sock);
err6: err6:
close(drv->ioctl_sock); close(drv->ioctl_sock);
err5: err5:
@ -1568,17 +1572,21 @@ err1:
} }
static void static int
wpa_driver_nl80211_finish_drv_init(struct wpa_driver_nl80211_data *drv) wpa_driver_nl80211_finish_drv_init(struct wpa_driver_nl80211_data *drv)
{ {
int flags; int flags;
if (wpa_driver_nl80211_get_ifflags(drv, &flags) != 0) if (wpa_driver_nl80211_get_ifflags(drv, &flags) != 0) {
printf("Could not get interface '%s' flags\n", drv->ifname); wpa_printf(MSG_ERROR, "Could not get interface '%s' flags",
else if (!(flags & IFF_UP)) {
if (wpa_driver_nl80211_set_ifflags(drv, flags | IFF_UP) != 0) {
printf("Could not set interface '%s' UP\n",
drv->ifname); drv->ifname);
return -1;
}
if (!(flags & IFF_UP)) {
if (wpa_driver_nl80211_set_ifflags(drv, flags | IFF_UP) != 0) {
wpa_printf(MSG_ERROR, "Could not set interface '%s' "
"UP", drv->ifname);
return -1;
} }
} }
@ -1598,6 +1606,8 @@ wpa_driver_nl80211_finish_drv_init(struct wpa_driver_nl80211_data *drv)
wpa_driver_nl80211_capa(drv); wpa_driver_nl80211_capa(drv);
wpa_driver_nl80211_send_oper_ifla(drv, 1, IF_OPER_DORMANT); wpa_driver_nl80211_send_oper_ifla(drv, 1, IF_OPER_DORMANT);
return 0;
} }

View file

@ -34,7 +34,7 @@
static int wpa_driver_wext_flush_pmkid(void *priv); static int wpa_driver_wext_flush_pmkid(void *priv);
static int wpa_driver_wext_get_range(void *priv); static int wpa_driver_wext_get_range(void *priv);
static void wpa_driver_wext_finish_drv_init(struct wpa_driver_wext_data *drv); static int wpa_driver_wext_finish_drv_init(struct wpa_driver_wext_data *drv);
static int wpa_driver_wext_send_oper_ifla(struct wpa_driver_wext_data *drv, static int wpa_driver_wext_send_oper_ifla(struct wpa_driver_wext_data *drv,
@ -913,50 +913,60 @@ void * wpa_driver_wext_init(void *ctx, const char *ifname)
drv->ioctl_sock = socket(PF_INET, SOCK_DGRAM, 0); drv->ioctl_sock = socket(PF_INET, SOCK_DGRAM, 0);
if (drv->ioctl_sock < 0) { if (drv->ioctl_sock < 0) {
perror("socket(PF_INET,SOCK_DGRAM)"); perror("socket(PF_INET,SOCK_DGRAM)");
os_free(drv); goto err1;
return NULL;
} }
s = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE); s = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
if (s < 0) { if (s < 0) {
perror("socket(PF_NETLINK,SOCK_RAW,NETLINK_ROUTE)"); perror("socket(PF_NETLINK,SOCK_RAW,NETLINK_ROUTE)");
close(drv->ioctl_sock); goto err2;
os_free(drv);
return NULL;
} }
drv->event_sock = s;
os_memset(&local, 0, sizeof(local)); os_memset(&local, 0, sizeof(local));
local.nl_family = AF_NETLINK; local.nl_family = AF_NETLINK;
local.nl_groups = RTMGRP_LINK; local.nl_groups = RTMGRP_LINK;
if (bind(s, (struct sockaddr *) &local, sizeof(local)) < 0) { if (bind(s, (struct sockaddr *) &local, sizeof(local)) < 0) {
perror("bind(netlink)"); perror("bind(netlink)");
close(s); goto err3;
close(drv->ioctl_sock);
os_free(drv);
return NULL;
} }
eloop_register_read_sock(s, wpa_driver_wext_event_receive, drv, ctx); eloop_register_read_sock(s, wpa_driver_wext_event_receive, drv, ctx);
drv->event_sock = s;
drv->mlme_sock = -1; drv->mlme_sock = -1;
wpa_driver_wext_finish_drv_init(drv); if (wpa_driver_wext_finish_drv_init(drv) < 0)
goto err4;
return drv; return drv;
err4:
eloop_unregister_read_sock(drv->event_sock);
err3:
close(drv->event_sock);
err2:
close(drv->ioctl_sock);
err1:
os_free(drv);
return NULL;
} }
static void wpa_driver_wext_finish_drv_init(struct wpa_driver_wext_data *drv) static int wpa_driver_wext_finish_drv_init(struct wpa_driver_wext_data *drv)
{ {
int flags; int flags;
if (wpa_driver_wext_get_ifflags(drv, &flags) != 0) if (wpa_driver_wext_get_ifflags(drv, &flags) != 0) {
printf("Could not get interface '%s' flags\n", drv->ifname); wpa_printf(MSG_ERROR, "Could not get interface '%s' flags",
else if (!(flags & IFF_UP)) {
if (wpa_driver_wext_set_ifflags(drv, flags | IFF_UP) != 0) {
printf("Could not set interface '%s' UP\n",
drv->ifname); drv->ifname);
return -1;
}
if (!(flags & IFF_UP)) {
if (wpa_driver_wext_set_ifflags(drv, flags | IFF_UP) != 0) {
wpa_printf(MSG_ERROR, "Could not set interface '%s' "
"UP", drv->ifname);
return -1;
} else { } else {
/* /*
* Wait some time to allow driver to initialize before * Wait some time to allow driver to initialize before
@ -977,7 +987,9 @@ static void wpa_driver_wext_finish_drv_init(struct wpa_driver_wext_data *drv)
wpa_driver_wext_flush_pmkid(drv); wpa_driver_wext_flush_pmkid(drv);
if (wpa_driver_wext_set_mode(drv, 0) < 0) { if (wpa_driver_wext_set_mode(drv, 0) < 0) {
printf("Could not configure driver to use managed mode\n"); wpa_printf(MSG_DEBUG, "Could not configure driver to use "
"managed mode");
/* Try to use it anyway */
} }
wpa_driver_wext_get_range(drv); wpa_driver_wext_get_range(drv);
@ -1000,6 +1012,8 @@ static void wpa_driver_wext_finish_drv_init(struct wpa_driver_wext_data *drv)
} }
wpa_driver_wext_send_oper_ifla(drv, 1, IF_OPER_DORMANT); wpa_driver_wext_send_oper_ifla(drv, 1, IF_OPER_DORMANT);
return 0;
} }

View file

@ -5,6 +5,9 @@ ChangeLog for wpa_supplicant
configurable with a new command line options (-G<seconds>) configurable with a new command line options (-G<seconds>)
* fixed scan buffer processing with WEXT to handle up to 65535 * fixed scan buffer processing with WEXT to handle up to 65535
byte result buffer (previously, limited to 32768 bytes) byte result buffer (previously, limited to 32768 bytes)
* allow multiple driver wrappers to be specified on command line
(e.g., -Dnl80211,wext); the first one that is able to initialize the
interface will be used
2009-01-06 - v0.6.7 2009-01-06 - v0.6.7
* added support for Wi-Fi Protected Setup (WPS) * added support for Wi-Fi Protected Setup (WPS)

View file

@ -500,7 +500,7 @@ options:
-C = ctrl_interface parameter (only used if -c is not) -C = ctrl_interface parameter (only used if -c is not)
-i = interface name -i = interface name
-d = increase debugging verbosity (-dd even more) -d = increase debugging verbosity (-dd even more)
-D = driver name -D = driver name (can be multiple drivers: nl80211,wext)
-f = Log output to default log location (normally /tmp) -f = Log output to default log location (normally /tmp)
-g = global ctrl_interface -g = global ctrl_interface
-K = include keys (passwords, etc.) in debug output -K = include keys (passwords, etc.) in debug output
@ -544,6 +544,13 @@ enabled:
wpa_supplicant -c/etc/wpa_supplicant.conf -iwlan0 -d wpa_supplicant -c/etc/wpa_supplicant.conf -iwlan0 -d
If the specific driver wrapper is not known beforehand, it is possible
to specify multiple comma separated driver wrappers on the command
line. wpa_supplicant will use the first driver wrapper that is able to
initialize the interface.
wpa_supplicant -Dnl80211,wext -c/etc/wpa_supplicant.conf -iwlan0
wpa_supplicant can control multiple interfaces (radios) either by wpa_supplicant can control multiple interfaces (radios) either by
running one process for each interface separately or by running just running one process for each interface separately or by running just

View file

@ -388,8 +388,8 @@
<varlistentry> <varlistentry>
<term>-D driver</term> <term>-D driver</term>
<listitem> <listitem>
<para>Driver to use. (Per interface, see the available options <para>Driver to use (can be multiple drivers: nl80211,wext).
below.)</para> (Per interface, see the available options below.)</para>
</listitem> </listitem>
</varlistentry> </varlistentry>
@ -507,6 +507,15 @@ wpa_supplicant -B -c/etc/wpa_supplicant.conf -iwlan0
<blockquote><programlisting> <blockquote><programlisting>
wpa_supplicant -c/etc/wpa_supplicant.conf -iwlan0 -d wpa_supplicant -c/etc/wpa_supplicant.conf -iwlan0 -d
</programlisting></blockquote>
<para>If the specific driver wrapper is not known beforehand, it is
possible to specify multiple comma separated driver wrappers on the command
line. <command>wpa_supplicant</command> will use the first driver
wrapper that is able to initialize the interface.</para>
<blockquote><programlisting>
wpa_supplicant -Dnl80211,wext -c/etc/wpa_supplicant.conf -iwlan0
</programlisting></blockquote> </programlisting></blockquote>
<para><command>wpa_supplicant</command> can control multiple <para><command>wpa_supplicant</command> can control multiple

View file

@ -52,7 +52,7 @@ static void usage(void)
" -C = ctrl_interface parameter (only used if -c is not)\n" " -C = ctrl_interface parameter (only used if -c is not)\n"
" -i = interface name\n" " -i = interface name\n"
" -d = increase debugging verbosity (-dd even more)\n" " -d = increase debugging verbosity (-dd even more)\n"
" -D = driver name\n" " -D = driver name (can be multiple drivers: nl80211,wext)\n"
#ifdef CONFIG_DEBUG_FILE #ifdef CONFIG_DEBUG_FILE
" -f = log output to debug file instead of stdout\n" " -f = log output to debug file instead of stdout\n"
#endif /* CONFIG_DEBUG_FILE */ #endif /* CONFIG_DEBUG_FILE */

View file

@ -1491,6 +1491,8 @@ static int wpa_supplicant_set_driver(struct wpa_supplicant *wpa_s,
const char *name) const char *name)
{ {
int i; int i;
size_t len;
const char *pos;
if (wpa_s == NULL) if (wpa_s == NULL)
return -1; return -1;
@ -1507,14 +1509,21 @@ static int wpa_supplicant_set_driver(struct wpa_supplicant *wpa_s,
return 0; return 0;
} }
pos = os_strchr(name, ',');
if (pos)
len = pos - name;
else
len = os_strlen(name);
for (i = 0; wpa_supplicant_drivers[i]; i++) { for (i = 0; wpa_supplicant_drivers[i]; i++) {
if (os_strcmp(name, wpa_supplicant_drivers[i]->name) == 0) { if (os_strlen(wpa_supplicant_drivers[i]->name) == len &&
os_strncmp(name, wpa_supplicant_drivers[i]->name, len) ==
0) {
wpa_s->driver = wpa_supplicant_drivers[i]; wpa_s->driver = wpa_supplicant_drivers[i];
return 0; return 0;
} }
} }
wpa_printf(MSG_ERROR, "Unsupported driver '%s'.\n", name); wpa_printf(MSG_ERROR, "Unsupported driver '%s'.", name);
return -1; return -1;
} }
@ -1710,6 +1719,9 @@ static struct wpa_supplicant * wpa_supplicant_alloc(void)
static int wpa_supplicant_init_iface(struct wpa_supplicant *wpa_s, static int wpa_supplicant_init_iface(struct wpa_supplicant *wpa_s,
struct wpa_interface *iface) struct wpa_interface *iface)
{ {
const char *ifname, *driver;
struct wpa_driver_capa capa;
wpa_printf(MSG_DEBUG, "Initializing interface '%s' conf '%s' driver " wpa_printf(MSG_DEBUG, "Initializing interface '%s' conf '%s' driver "
"'%s' ctrl_interface '%s' bridge '%s'", iface->ifname, "'%s' ctrl_interface '%s' bridge '%s'", iface->ifname,
iface->confname ? iface->confname : "N/A", iface->confname ? iface->confname : "N/A",
@ -1717,10 +1729,6 @@ static int wpa_supplicant_init_iface(struct wpa_supplicant *wpa_s,
iface->ctrl_interface ? iface->ctrl_interface : "N/A", iface->ctrl_interface ? iface->ctrl_interface : "N/A",
iface->bridge_ifname ? iface->bridge_ifname : "N/A"); iface->bridge_ifname ? iface->bridge_ifname : "N/A");
if (wpa_supplicant_set_driver(wpa_s, iface->driver) < 0) {
return -1;
}
if (iface->confname) { if (iface->confname) {
#ifdef CONFIG_BACKEND_FILE #ifdef CONFIG_BACKEND_FILE
wpa_s->confname = os_rel2abs_path(iface->confname); wpa_s->confname = os_rel2abs_path(iface->confname);
@ -1788,18 +1796,6 @@ static int wpa_supplicant_init_iface(struct wpa_supplicant *wpa_s,
sizeof(wpa_s->bridge_ifname)); sizeof(wpa_s->bridge_ifname));
} }
return 0;
}
static int wpa_supplicant_init_iface2(struct wpa_supplicant *wpa_s)
{
const char *ifname;
struct wpa_driver_capa capa;
wpa_printf(MSG_DEBUG, "Initializing interface (2) '%s'",
wpa_s->ifname);
/* RSNA Supplicant Key Management - INITIALIZE */ /* RSNA Supplicant Key Management - INITIALIZE */
eapol_sm_notify_portEnabled(wpa_s->eapol, FALSE); eapol_sm_notify_portEnabled(wpa_s->eapol, FALSE);
eapol_sm_notify_portValid(wpa_s->eapol, FALSE); eapol_sm_notify_portValid(wpa_s->eapol, FALSE);
@ -1808,8 +1804,21 @@ static int wpa_supplicant_init_iface2(struct wpa_supplicant *wpa_s)
* L2 receive handler so that association events are processed before * L2 receive handler so that association events are processed before
* EAPOL-Key packets if both become available for the same select() * EAPOL-Key packets if both become available for the same select()
* call. */ * call. */
driver = iface->driver;
next_driver:
if (wpa_supplicant_set_driver(wpa_s, driver) < 0)
return -1;
wpa_s->drv_priv = wpa_drv_init(wpa_s, wpa_s->ifname); wpa_s->drv_priv = wpa_drv_init(wpa_s, wpa_s->ifname);
if (wpa_s->drv_priv == NULL) { if (wpa_s->drv_priv == NULL) {
const char *pos;
pos = os_strchr(driver, ',');
if (pos) {
wpa_printf(MSG_DEBUG, "Failed to initialize driver "
"interface - try next driver wrapper");
driver = pos + 1;
goto next_driver;
}
wpa_printf(MSG_ERROR, "Failed to initialize driver interface"); wpa_printf(MSG_ERROR, "Failed to initialize driver interface");
return -1; return -1;
} }
@ -1965,8 +1974,7 @@ struct wpa_supplicant * wpa_supplicant_add_iface(struct wpa_global *global,
if (wpa_s == NULL) if (wpa_s == NULL)
return NULL; return NULL;
if (wpa_supplicant_init_iface(wpa_s, iface) || if (wpa_supplicant_init_iface(wpa_s, iface)) {
wpa_supplicant_init_iface2(wpa_s)) {
wpa_printf(MSG_DEBUG, "Failed to add interface %s", wpa_printf(MSG_DEBUG, "Failed to add interface %s",
iface->ifname); iface->ifname);
wpa_supplicant_deinit_iface(wpa_s); wpa_supplicant_deinit_iface(wpa_s);