diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c index 56295885c..ed7359781 100644 --- a/src/drivers/driver_nl80211.c +++ b/src/drivers/driver_nl80211.c @@ -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_flush_pmkid(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); @@ -1548,10 +1548,14 @@ static void * wpa_driver_nl80211_init(void *ctx, const char *ifname) ctx); drv->wext_event_sock = s; - wpa_driver_nl80211_finish_drv_init(drv); + if (wpa_driver_nl80211_finish_drv_init(drv)) + goto err7; return drv; +err7: + eloop_unregister_read_sock(drv->wext_event_sock); + close(drv->wext_event_sock); err6: close(drv->ioctl_sock); err5: @@ -1568,17 +1572,21 @@ err1: } -static void +static int wpa_driver_nl80211_finish_drv_init(struct wpa_driver_nl80211_data *drv) { int flags; - if (wpa_driver_nl80211_get_ifflags(drv, &flags) != 0) - printf("Could not get interface '%s' flags\n", drv->ifname); - else if (!(flags & IFF_UP)) { + if (wpa_driver_nl80211_get_ifflags(drv, &flags) != 0) { + wpa_printf(MSG_ERROR, "Could not get interface '%s' flags", + drv->ifname); + return -1; + } + 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); + 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_send_oper_ifla(drv, 1, IF_OPER_DORMANT); + + return 0; } diff --git a/src/drivers/driver_wext.c b/src/drivers/driver_wext.c index bc2137b02..f21c379d1 100644 --- a/src/drivers/driver_wext.c +++ b/src/drivers/driver_wext.c @@ -34,7 +34,7 @@ static int wpa_driver_wext_flush_pmkid(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, @@ -913,50 +913,60 @@ void * wpa_driver_wext_init(void *ctx, const char *ifname) drv->ioctl_sock = socket(PF_INET, SOCK_DGRAM, 0); if (drv->ioctl_sock < 0) { perror("socket(PF_INET,SOCK_DGRAM)"); - os_free(drv); - return NULL; + goto err1; } s = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE); if (s < 0) { perror("socket(PF_NETLINK,SOCK_RAW,NETLINK_ROUTE)"); - close(drv->ioctl_sock); - os_free(drv); - return NULL; + goto err2; } + drv->event_sock = s; os_memset(&local, 0, sizeof(local)); local.nl_family = AF_NETLINK; local.nl_groups = RTMGRP_LINK; if (bind(s, (struct sockaddr *) &local, sizeof(local)) < 0) { perror("bind(netlink)"); - close(s); - close(drv->ioctl_sock); - os_free(drv); - return NULL; + goto err3; } eloop_register_read_sock(s, wpa_driver_wext_event_receive, drv, ctx); - drv->event_sock = s; drv->mlme_sock = -1; - wpa_driver_wext_finish_drv_init(drv); + if (wpa_driver_wext_finish_drv_init(drv) < 0) + goto err4; 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; - if (wpa_driver_wext_get_ifflags(drv, &flags) != 0) - printf("Could not get interface '%s' flags\n", drv->ifname); - else if (!(flags & IFF_UP)) { + if (wpa_driver_wext_get_ifflags(drv, &flags) != 0) { + wpa_printf(MSG_ERROR, "Could not get interface '%s' flags", + drv->ifname); + return -1; + } + + 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); + wpa_printf(MSG_ERROR, "Could not set interface '%s' " + "UP", drv->ifname); + return -1; } else { /* * 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); 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); @@ -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); + + return 0; } diff --git a/wpa_supplicant/ChangeLog b/wpa_supplicant/ChangeLog index 1d46ff930..c96c6f79d 100644 --- a/wpa_supplicant/ChangeLog +++ b/wpa_supplicant/ChangeLog @@ -5,6 +5,9 @@ ChangeLog for wpa_supplicant configurable with a new command line options (-G) * fixed scan buffer processing with WEXT to handle up to 65535 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 * added support for Wi-Fi Protected Setup (WPS) diff --git a/wpa_supplicant/README b/wpa_supplicant/README index 2b94c2309..760d64a37 100644 --- a/wpa_supplicant/README +++ b/wpa_supplicant/README @@ -500,7 +500,7 @@ options: -C = ctrl_interface parameter (only used if -c is not) -i = interface name -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) -g = global ctrl_interface -K = include keys (passwords, etc.) in debug output @@ -544,6 +544,13 @@ enabled: 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 running one process for each interface separately or by running just diff --git a/wpa_supplicant/doc/docbook/wpa_supplicant.sgml b/wpa_supplicant/doc/docbook/wpa_supplicant.sgml index 9798cedf1..3aae51ba1 100644 --- a/wpa_supplicant/doc/docbook/wpa_supplicant.sgml +++ b/wpa_supplicant/doc/docbook/wpa_supplicant.sgml @@ -388,8 +388,8 @@ -D driver - Driver to use. (Per interface, see the available options - below.) + Driver to use (can be multiple drivers: nl80211,wext). + (Per interface, see the available options below.) @@ -507,6 +507,15 @@ wpa_supplicant -B -c/etc/wpa_supplicant.conf -iwlan0
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 diff --git a/wpa_supplicant/main.c b/wpa_supplicant/main.c index 6f90cc509..7e9919b32 100644 --- a/wpa_supplicant/main.c +++ b/wpa_supplicant/main.c @@ -52,7 +52,7 @@ static void usage(void) " -C = ctrl_interface parameter (only used if -c is not)\n" " -i = interface name\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 " -f = log output to debug file instead of stdout\n" #endif /* CONFIG_DEBUG_FILE */ diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c index 6eb0eec72..9b6f08869 100644 --- a/wpa_supplicant/wpa_supplicant.c +++ b/wpa_supplicant/wpa_supplicant.c @@ -1491,6 +1491,8 @@ static int wpa_supplicant_set_driver(struct wpa_supplicant *wpa_s, const char *name) { int i; + size_t len; + const char *pos; if (wpa_s == NULL) return -1; @@ -1507,14 +1509,21 @@ static int wpa_supplicant_set_driver(struct wpa_supplicant *wpa_s, return 0; } + pos = os_strchr(name, ','); + if (pos) + len = pos - name; + else + len = os_strlen(name); 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]; return 0; } } - wpa_printf(MSG_ERROR, "Unsupported driver '%s'.\n", name); + wpa_printf(MSG_ERROR, "Unsupported driver '%s'.", name); 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, struct wpa_interface *iface) { + const char *ifname, *driver; + struct wpa_driver_capa capa; + wpa_printf(MSG_DEBUG, "Initializing interface '%s' conf '%s' driver " "'%s' ctrl_interface '%s' bridge '%s'", iface->ifname, 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->bridge_ifname ? iface->bridge_ifname : "N/A"); - if (wpa_supplicant_set_driver(wpa_s, iface->driver) < 0) { - return -1; - } - if (iface->confname) { #ifdef CONFIG_BACKEND_FILE 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)); } - 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 */ eapol_sm_notify_portEnabled(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 * EAPOL-Key packets if both become available for the same select() * 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); 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"); return -1; } @@ -1965,8 +1974,7 @@ struct wpa_supplicant * wpa_supplicant_add_iface(struct wpa_global *global, if (wpa_s == NULL) return NULL; - if (wpa_supplicant_init_iface(wpa_s, iface) || - wpa_supplicant_init_iface2(wpa_s)) { + if (wpa_supplicant_init_iface(wpa_s, iface)) { wpa_printf(MSG_DEBUG, "Failed to add interface %s", iface->ifname); wpa_supplicant_deinit_iface(wpa_s);