11c65c71a01b05ab83b9f585fa6b89bfab818ec3
[oweals/openwrt.git] /
1 From 6c4c98db9420a3321bbf091cfc254de5eba4b404 Mon Sep 17 00:00:00 2001
2 From: Davina Lu <ylu@quantenna.com>
3 Date: Tue, 15 Jan 2019 19:17:51 +0100
4 Subject: [PATCH] wpa_supplicant: support Multi-AP backhaul STA onboarding
5
6 The Wi-Fi Alliance Multi-AP Specification v1.0 allows onboarding of a
7 backhaul STA through WPS. To enable this, the backhaul STA needs to add
8 a Multi-AP IE to the WFA vendor extension element in the WSC M1 message
9 that indicates it supports the Multi-AP backhaul STA role. The registrar
10 (if it support Multi-AP onboarding) will respond to that with a WSC M8
11 message that also contains the Multi-AP IE, and that contains the
12 credentials for the backhaul SSID (which may be different from the SSID
13 on which WPS is performed).
14
15 Introduce a new parameter to wpas_wps_start_pbc() and allow it to be
16 set via control interface's new multi_ap=1 parameter of WPS_PBC call.
17 multi_ap_backhaul_sta is set to 1 in the automatically created SSID.
18 Thus, if the AP does not support Multi-AP, association will fail and
19 WPS will be terminated.
20
21 Only wps_pbc is supported.
22
23 The multi_ap argument is only added to the socket interface, not to the
24 dbus interface.
25
26 Signed-off-by: Davina Lu <ylu@quantenna.com>
27 Signed-off-by: Igor Mitsyanko <igor.mitsyanko.os@quantenna.com>
28 Signed-off-by: Arnout Vandecappelle (Essensium/Mind) <arnout@mind.be>
29 Signed-off-by: Daniel Golle <daniel@makrotopia.org>
30 ---
31 v4: use argument to wps_pbc instead of a global configuration option
32  (requested by Jouni)
33 ---
34  src/eap_peer/eap_wsc.c                      | 3 +++
35  src/wps/wps.h                               | 6 ++++++
36  src/wps/wps_enrollee.c                      | 6 +++++-
37  wpa_supplicant/ctrl_iface.c                 | 5 ++++-
38  wpa_supplicant/dbus/dbus_new_handlers_wps.c | 2 +-
39  wpa_supplicant/dbus/dbus_old_handlers_wps.c | 4 ++--
40  wpa_supplicant/events.c                     | 2 +-
41  wpa_supplicant/p2p_supplicant.c             | 2 +-
42  wpa_supplicant/wps_supplicant.c             | 9 +++++++--
43  wpa_supplicant/wps_supplicant.h             | 2 +-
44  10 files changed, 31 insertions(+), 10 deletions(-)
45
46 --- a/src/eap_peer/eap_wsc.c
47 +++ b/src/eap_peer/eap_wsc.c
48 @@ -274,6 +274,9 @@ static void * eap_wsc_init(struct eap_sm
49                                       cfg.pin, cfg.pin_len, 0);
50         }
51  
52 +       if (os_strstr(phase1, "multi_ap=1"))
53 +               wps->multi_ap_backhaul_sta = 1;
54 +
55         /* Use reduced client timeout for WPS to avoid long wait */
56         if (sm->ClientTimeout > 30)
57                 sm->ClientTimeout = 30;
58 --- a/src/wps/wps.h
59 +++ b/src/wps/wps.h
60 @@ -613,6 +613,12 @@ struct wps_context {
61         int ap_setup_locked;
62  
63         /**
64 +        * multi_ap_backhaul_sta - Whether this is a Multi-AP backhaul STA
65 +        * enrollee
66 +        */
67 +       int multi_ap_backhaul_sta;
68 +
69 +       /**
70          * uuid - Own UUID
71          */
72         u8 uuid[16];
73 --- a/src/wps/wps_enrollee.c
74 +++ b/src/wps/wps_enrollee.c
75 @@ -105,6 +105,7 @@ static struct wpabuf * wps_build_m1(stru
76  {
77         struct wpabuf *msg;
78         u16 config_methods;
79 +       u8 multi_ap_backhaul_sta = 0;
80  
81         if (random_get_bytes(wps->nonce_e, WPS_NONCE_LEN) < 0)
82                 return NULL;
83 @@ -134,6 +135,9 @@ static struct wpabuf * wps_build_m1(stru
84                                     WPS_CONFIG_PHY_PUSHBUTTON);
85         }
86  
87 +       if (wps->wps->multi_ap_backhaul_sta)
88 +               multi_ap_backhaul_sta = MULTI_AP_BACKHAUL_STA;
89 +
90         if (wps_build_version(msg) ||
91             wps_build_msg_type(msg, WPS_M1) ||
92             wps_build_uuid_e(msg, wps->uuid_e) ||
93 @@ -152,7 +156,7 @@ static struct wpabuf * wps_build_m1(stru
94             wps_build_dev_password_id(msg, wps->dev_pw_id) ||
95             wps_build_config_error(msg, WPS_CFG_NO_ERROR) ||
96             wps_build_os_version(&wps->wps->dev, msg) ||
97 -           wps_build_wfa_ext(msg, 0, NULL, 0, 0) ||
98 +           wps_build_wfa_ext(msg, 0, NULL, 0, multi_ap_backhaul_sta) ||
99             wps_build_vendor_ext_m1(&wps->wps->dev, msg)) {
100                 wpabuf_free(msg);
101                 return NULL;
102 --- a/wpa_supplicant/ctrl_iface.c
103 +++ b/wpa_supplicant/ctrl_iface.c
104 @@ -1167,6 +1167,7 @@ static int wpa_supplicant_ctrl_iface_wps
105  #ifdef CONFIG_AP
106         u8 *_p2p_dev_addr = NULL;
107  #endif /* CONFIG_AP */
108 +       int multi_ap = 0;
109  
110         if (cmd == NULL || os_strcmp(cmd, "any") == 0) {
111                 _bssid = NULL;
112 @@ -1184,6 +1185,8 @@ static int wpa_supplicant_ctrl_iface_wps
113                 wpa_printf(MSG_DEBUG, "CTRL_IFACE WPS_PBC: invalid BSSID '%s'",
114                            cmd);
115                 return -1;
116 +       } else if (os_strncmp(cmd, "multi_ap=", 9) == 0) {
117 +               multi_ap = atoi(cmd + 9);
118         }
119  
120  #ifdef CONFIG_AP
121 @@ -1191,7 +1194,7 @@ static int wpa_supplicant_ctrl_iface_wps
122                 return wpa_supplicant_ap_wps_pbc(wpa_s, _bssid, _p2p_dev_addr);
123  #endif /* CONFIG_AP */
124  
125 -       return wpas_wps_start_pbc(wpa_s, _bssid, 0);
126 +       return wpas_wps_start_pbc(wpa_s, _bssid, 0, multi_ap);
127  }
128  
129  
130 --- a/wpa_supplicant/dbus/dbus_new_handlers_wps.c
131 +++ b/wpa_supplicant/dbus/dbus_new_handlers_wps.c
132 @@ -289,7 +289,7 @@ DBusMessage * wpas_dbus_handler_wps_star
133                 if (ret > 0)
134                         os_snprintf(npin, sizeof(npin), "%08d", ret);
135         } else {
136 -               ret = wpas_wps_start_pbc(wpa_s, params.bssid, 0);
137 +               ret = wpas_wps_start_pbc(wpa_s, params.bssid, 0, 0);
138         }
139  
140         if (ret < 0) {
141 --- a/wpa_supplicant/dbus/dbus_old_handlers_wps.c
142 +++ b/wpa_supplicant/dbus/dbus_old_handlers_wps.c
143 @@ -37,9 +37,9 @@ DBusMessage * wpas_dbus_iface_wps_pbc(DB
144                 return wpas_dbus_new_invalid_opts_error(message, NULL);
145  
146         if (os_strcmp(arg_bssid, "any") == 0)
147 -               ret = wpas_wps_start_pbc(wpa_s, NULL, 0);
148 +               ret = wpas_wps_start_pbc(wpa_s, NULL, 0, 0);
149         else if (!hwaddr_aton(arg_bssid, bssid))
150 -               ret = wpas_wps_start_pbc(wpa_s, bssid, 0);
151 +               ret = wpas_wps_start_pbc(wpa_s, bssid, 0, 0);
152         else {
153                 return wpas_dbus_new_invalid_opts_error(message,
154                                                         "Invalid BSSID");
155 --- a/wpa_supplicant/events.c
156 +++ b/wpa_supplicant/events.c
157 @@ -4816,7 +4816,7 @@ void supplicant_event(void *ctx, enum wp
158                 break;
159         case EVENT_WPS_BUTTON_PUSHED:
160  #ifdef CONFIG_WPS
161 -               wpas_wps_start_pbc(wpa_s, NULL, 0);
162 +               wpas_wps_start_pbc(wpa_s, NULL, 0, 0);
163  #endif /* CONFIG_WPS */
164                 break;
165         case EVENT_AVOID_FREQUENCIES:
166 --- a/wpa_supplicant/p2p_supplicant.c
167 +++ b/wpa_supplicant/p2p_supplicant.c
168 @@ -1649,7 +1649,7 @@ static void wpas_start_wps_enrollee(stru
169         wpa_supplicant_ap_deinit(wpa_s);
170         wpas_copy_go_neg_results(wpa_s, res);
171         if (res->wps_method == WPS_PBC) {
172 -               wpas_wps_start_pbc(wpa_s, res->peer_interface_addr, 1);
173 +               wpas_wps_start_pbc(wpa_s, res->peer_interface_addr, 1, 0);
174  #ifdef CONFIG_WPS_NFC
175         } else if (res->wps_method == WPS_NFC) {
176                 wpas_wps_start_nfc(wpa_s, res->peer_device_addr,
177 --- a/wpa_supplicant/wps_supplicant.c
178 +++ b/wpa_supplicant/wps_supplicant.c
179 @@ -1137,9 +1137,10 @@ static void wpas_wps_reassoc(struct wpa_
180  
181  
182  int wpas_wps_start_pbc(struct wpa_supplicant *wpa_s, const u8 *bssid,
183 -                      int p2p_group)
184 +                      int p2p_group, int multi_ap_backhaul_sta)
185  {
186         struct wpa_ssid *ssid;
187 +       char phase1[32];
188  
189  #ifdef CONFIG_AP
190         if (wpa_s->ap_iface) {
191 @@ -1177,10 +1178,14 @@ int wpas_wps_start_pbc(struct wpa_suppli
192                 }
193         }
194  #endif /* CONFIG_P2P */
195 -       if (wpa_config_set(ssid, "phase1", "\"pbc=1\"", 0) < 0)
196 +       if (os_snprintf(phase1, sizeof(phase1), "pbc=1%s",
197 +                       multi_ap_backhaul_sta ? " multi_ap=1" : "") ||
198 +           wpa_config_set_quoted(ssid, "phase1", phase1) < 0)
199                 return -1;
200         if (wpa_s->wps_fragment_size)
201                 ssid->eap.fragment_size = wpa_s->wps_fragment_size;
202 +       if (multi_ap_backhaul_sta)
203 +               ssid->multi_ap_backhaul_sta = 1;
204         wpa_supplicant_wps_event(wpa_s, WPS_EV_PBC_ACTIVE, NULL);
205         eloop_register_timeout(WPS_PBC_WALK_TIME, 0, wpas_wps_timeout,
206                                wpa_s, NULL);
207 --- a/wpa_supplicant/wps_supplicant.h
208 +++ b/wpa_supplicant/wps_supplicant.h
209 @@ -30,7 +30,7 @@ void wpas_wps_deinit(struct wpa_supplica
210  int wpas_wps_eapol_cb(struct wpa_supplicant *wpa_s);
211  enum wps_request_type wpas_wps_get_req_type(struct wpa_ssid *ssid);
212  int wpas_wps_start_pbc(struct wpa_supplicant *wpa_s, const u8 *bssid,
213 -                      int p2p_group);
214 +                      int p2p_group, int multi_ap_backhaul_sta);
215  int wpas_wps_start_pin(struct wpa_supplicant *wpa_s, const u8 *bssid,
216                        const char *pin, int p2p_group, u16 dev_pw_id);
217  void wpas_wps_pbc_overlap(struct wpa_supplicant *wpa_s);