From patchwork Wed Feb 17 16:58:40 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Roy Marples X-Patchwork-Id: 584232 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from bombadil.infradead.org (bombadil.infradead.org [IPv6:2001:1868:205::9]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 1B8721400DE for ; Thu, 18 Feb 2016 03:59:56 +1100 (AEDT) Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1aW5Rz-0000sk-T1; Wed, 17 Feb 2016 16:59:39 +0000 Received: from uberserver.marples.name ([77.75.106.61] helo=mail.marples.name) by bombadil.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1aW5RU-0008TQ-FY for hostap@lists.infradead.org; Wed, 17 Feb 2016 16:59:23 +0000 Received: from [IPv6:2a01:348:31:2::51] (roy-laptop.marples.name [IPv6:2a01:348:31:2::51]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by mail.marples.name (Postfix) with ESMTPSA id 32BAEA1100 for ; Wed, 17 Feb 2016 16:58:41 +0000 (GMT) To: hostap@lists.infradead.org From: Roy Marples Subject: [PATCH] Add interface matching support with -M Message-ID: <56C4A6C0.2000403@marples.name> Date: Wed, 17 Feb 2016 16:58:40 +0000 User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:38.0) Gecko/20100101 Thunderbird/38.5.1 MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20160217_085909_707314_B89241BC X-CRM114-Status: GOOD ( 17.95 ) X-Spam-Score: -1.9 (-) X-Spam-Report: SpamAssassin version 3.4.0 on bombadil.infradead.org summary: Content analysis details: (-1.9 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 SPF_PASS SPF: sender matches SPF record -0.0 RP_MATCHES_RCVD Envelope sender domain matches handover relay domain -1.9 BAYES_00 BODY: Bayes spam probability is 0 to 1% [score: 0.0000] X-BeenThere: hostap@lists.infradead.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "Hostap" Errors-To: hostap-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org Add interface matching support with -M, guarded by CONFIG_MATCH_IFACE. This is very useful for systems without udev (Linux) or devd (FreeBSD). This patch requires a prior patch I submitted with the subject line: [PATCH] Find correct driver for interface additions/removals which can be found here: http://lists.infradead.org/pipermail/hostap/2016-February/034778.html Roy commit d35f411682da560a8dfdc60e7e2eefeb025ed5f6 Author: Roy Marples Date: Wed Feb 17 16:50:16 2016 +0000 Add interface matching support with -M, guarded by CONFIG_MATCH_IFACE. Signed-off-by: Roy Marples diff --git a/wpa_supplicant/Makefile b/wpa_supplicant/Makefile index 234a0bf..5297f51 100644 --- a/wpa_supplicant/Makefile +++ b/wpa_supplicant/Makefile @@ -315,6 +315,10 @@ CFLAGS += -DCONFIG_IBSS_RSN OBJS += ibss_rsn.o endif +ifdef CONFIG_MATCH_IFACE +CFLAGS += -DCONFIG_MATCH_IFACE +endif + ifdef CONFIG_P2P OBJS += p2p_supplicant.o OBJS += p2p_supplicant_sd.o diff --git a/wpa_supplicant/README b/wpa_supplicant/README index 3223312..c0ea0f4 100644 --- a/wpa_supplicant/README +++ b/wpa_supplicant/README @@ -412,7 +412,7 @@ usage: wpa_supplicant [-BddfhKLqqtuvW] [-P] [-g] \ [-G] \ -i -c [-C] [-D] [-p] \ - [-b [-N -i -c [-C] [-D] \ + [-b [-MN -i -c [-C] [-D] \ [-p] [-b] [-m] ... options: @@ -436,6 +436,7 @@ options: -u = enable DBus control interface -v = show version -W = wait for a control interface monitor before starting + -M = start describing matching interface -N = start describing new interface -m = Configuration file for the P2P Device @@ -478,6 +479,20 @@ wpa_supplicant \ -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 +pattern allows for wildcards. +As an example, the following command would start wpa_supplicant for a +specific wired interface called lan, any interface starting with wlan +and lastly any other interface. Each match has it's 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 interface needs to be configured to wpa_supplicant in addition to the main interface: diff --git a/wpa_supplicant/defconfig b/wpa_supplicant/defconfig index a615c7c..9202bdb 100644 --- a/wpa_supplicant/defconfig +++ b/wpa_supplicant/defconfig @@ -467,6 +467,9 @@ CONFIG_PEERKEY=y # Hotspot 2.0 #CONFIG_HS20=y +# Enable interface matching in wpa_supplicant +#CONFIG_MATCH_IFACE=y + # Disable roaming in wpa_supplicant #CONFIG_NO_ROAMING=y diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c index 718017a..8d00b8d 100644 --- a/wpa_supplicant/events.c +++ b/wpa_supplicant/events.c @@ -3973,6 +3973,34 @@ wpa_supplicant_event_global(void *ctx, enum wpa_event_type event, struct wpa_supplicant *wpa_s; wpa_s = wpa_supplicant_get_iface(ctx, data->interface_status.ifname); +#ifdef CONFIG_MATCH_IFACE + if (event == EVENT_INTERFACE_STATUS) { + struct wpa_interface *wpa_i; + + switch (data->interface_status.ievent) { + case EVENT_INTERFACE_ADDED: + if (wpa_s != NULL) + break; + wpa_i = wpa_supplicant_match_iface(ctx, + data->interface_status.ifname); + if (wpa_i != NULL) { + wpa_s = wpa_supplicant_add_iface(ctx, wpa_i, + NULL); + os_free(wpa_i); + if (wpa_s != NULL) + wpa_s->matched = 1; + } + break; + case EVENT_INTERFACE_REMOVED: + if (wpa_s != NULL && wpa_s->matched) { + wpa_supplicant_remove_iface(ctx, wpa_s, 0); + return; + } + break; + } + } +#endif /* CONFIG_MATCH_IFACE */ + if (wpa_s != NULL) wpa_supplicant_event(wpa_s, event, data); } diff --git a/wpa_supplicant/main.c b/wpa_supplicant/main.c index 3ab80a5..477c278 100644 --- a/wpa_supplicant/main.c +++ b/wpa_supplicant/main.c @@ -81,6 +81,9 @@ static void usage(void) #ifdef CONFIG_P2P " -m = Configuration file for the P2P Device interface\n" #endif /* CONFIG_P2P */ +#ifdef CONFIG_MATCH_IFACE + " -M = start describing new matching interface\n" +#endif /* CONFIG_MATCH_IFACE */ " -N = start describing new interface\n" " -o = override driver parameter for new interfaces\n" " -O = override ctrl_interface parameter for new interfaces\n" @@ -152,6 +155,23 @@ static void wpa_supplicant_fd_workaround(int start) #endif /* __linux__ */ } +#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 / deperature of interfaces. */ + if (wpa_drivers[0]->global_init && global->drv_priv[0] == NULL) { + global->drv_priv[0] = wpa_drivers[0]->global_init(global); + if (global->drv_priv[0] == NULL) { + 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[]) { @@ -176,7 +196,7 @@ int main(int argc, char *argv[]) for (;;) { 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) break; switch (c) { @@ -282,6 +302,19 @@ int main(int argc, char *argv[]) case 'W': params.wait_for_monitor++; break; +#ifdef CONFIG_MATCH_IFACE + case 'M': + params.Miface_count++; + iface = os_realloc_array(params.Mifaces, + params.Miface_count, + sizeof(struct wpa_interface)); + if (iface == NULL) + goto out; + params.Mifaces = iface; + iface = ¶ms.Mifaces[params.Miface_count - 1]; + os_memset(iface, 0, sizeof(*iface)); + break; +#endif /* CONFIG_MATCH_IFACE */ case 'N': iface_count++; iface = os_realloc_array(ifaces, iface_count, @@ -328,6 +361,9 @@ int main(int argc, char *argv[]) ifaces[i].ctrl_interface == NULL) || ifaces[i].ifname == NULL) { if (iface_count == 1 && (params.ctrl_interface || +#ifdef CONFIG_MATCH_IFACE + params.Miface_count || +#endif /* CONFIG_MATCH_IFACE */ params.dbus_ctrl_interface)) break; usage(); @@ -341,6 +377,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) exitcode = wpa_supplicant_run(global); @@ -351,6 +392,9 @@ int main(int argc, char *argv[]) out: wpa_supplicant_fd_workaround(0); os_free(ifaces); +#ifdef CONFIG_MATCH_IFACE + os_free(params.Mifaces); +#endif /* CONFIG_MATCH_IFACE */ os_free(params.pid_file); os_program_deinit(); diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c index 11f330d..32bb06f 100644 --- a/wpa_supplicant/wpa_supplicant.c +++ b/wpa_supplicant/wpa_supplicant.c @@ -56,6 +56,9 @@ #include "wpas_kay.h" #include "mesh.h" +#include +#include + const char *const wpa_supplicant_version = "wpa_supplicant v" VERSION_STR "\n" "Copyright (c) 2003-2016, Jouni Malinen and contributors"; @@ -4847,6 +4850,68 @@ 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.Miface_count; i++) { + miface = &global->params.Mifaces[i]; + if (miface->ifname == NULL || + fnmatch(miface->ifname, ifname, 0) == 0) + { + iface = os_zalloc(sizeof(*iface)); + *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 == NULL) { + 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 != NULL) + continue; + iface = wpa_supplicant_match_iface(global, ifi->if_name); + if (iface != NULL) { + wpa_s = wpa_supplicant_add_iface(global, iface, NULL); + os_free(iface); + if (wpa_s != NULL) + wpa_s->matched = 1; + } + } + if_freenameindex(ifp); + return 0; +} +#endif /* CONFIG_MATCH_IFACE */ + /** * wpa_supplicant_add_iface - Add a new network interface * @global: Pointer to global data from wpa_supplicant_init() @@ -5148,6 +5213,16 @@ struct wpa_global * wpa_supplicant_init(struct wpa_params *params) if (params->override_ctrl_interface) global->params.override_ctrl_interface = os_strdup(params->override_ctrl_interface); +#ifdef CONFIG_MATCH_IFACE + global->params.Miface_count = params->Miface_count; + if (params->Miface_count) { + global->params.Mifaces = os_calloc(params->Miface_count, + sizeof(struct wpa_interface)); + os_memcpy(global->params.Mifaces, + params->Mifaces, + params->Miface_count * sizeof(struct wpa_interface)); + } +#endif /* CONFIG_MATCH_IFACE */ #ifdef CONFIG_P2P if (params->conf_p2p_dev) global->params.conf_p2p_dev = @@ -5227,6 +5302,11 @@ int wpa_supplicant_run(struct wpa_global *global) eloop_sock_requeue())) return -1; +#ifdef CONFIG_MATCH_IFACE + if (wpa_supplicant_match_existing(global)) + return -1; +#endif + if (global->params.wait_for_monitor) { for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) if (wpa_s->ctrl_iface && !wpa_s->p2p_mgmt) diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h index 7b74f38..0595b51 100644 --- a/wpa_supplicant/wpa_supplicant_i.h +++ b/wpa_supplicant/wpa_supplicant_i.h @@ -217,6 +217,18 @@ struct wpa_params { */ char *entropy_file; +#ifdef CONFIG_MATCH_IFACE + /** + * Mifaces - Interface descriptions to match. + */ + struct wpa_interface *Mifaces; + + /** + * Miface_count - Number of defined matching interfaces. + */ + int Miface_count; +#endif /* CONFIG_MATCH_IFACE */ + #ifdef CONFIG_P2P /** * conf_p2p_dev - Configuration file used to hold the @@ -453,6 +465,9 @@ struct wpa_supplicant { unsigned char own_addr[ETH_ALEN]; unsigned char perm_addr[ETH_ALEN]; char ifname[100]; +#ifdef CONFIG_MATCH_IFACE + int matched; +#endif #ifdef CONFIG_CTRL_IFACE_DBUS char *dbus_path; #endif /* CONFIG_CTRL_IFACE_DBUS */ @@ -1081,6 +1096,8 @@ void free_hw_features(struct wpa_supplicant *wpa_s); 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_interface *iface, struct wpa_supplicant *parent);