Branch data Line data Source code
1 : : /*
2 : : * WPA Supplicant / dbus-based control interface (P2P)
3 : : * Copyright (c) 2011-2012, Intel Corporation
4 : : *
5 : : * This software may be distributed under the terms of the BSD license.
6 : : * See README for more details.
7 : : */
8 : :
9 : : #include "includes.h"
10 : :
11 : : #include "utils/includes.h"
12 : : #include "common.h"
13 : : #include "../config.h"
14 : : #include "../wpa_supplicant_i.h"
15 : : #include "../wps_supplicant.h"
16 : : #include "../notify.h"
17 : : #include "dbus_new_helpers.h"
18 : : #include "dbus_new.h"
19 : : #include "dbus_new_handlers.h"
20 : : #include "dbus_new_handlers_p2p.h"
21 : : #include "dbus_dict_helpers.h"
22 : : #include "p2p/p2p.h"
23 : : #include "common/ieee802_11_defs.h"
24 : : #include "ap/hostapd.h"
25 : : #include "ap/ap_config.h"
26 : : #include "ap/wps_hostapd.h"
27 : :
28 : : #include "../p2p_supplicant.h"
29 : :
30 : : /**
31 : : * Parses out the mac address from the peer object path.
32 : : * @peer_path - object path of the form
33 : : * /fi/w1/wpa_supplicant1/Interfaces/n/Peers/00112233445566 (no colons)
34 : : * @addr - out param must be of ETH_ALEN size
35 : : * Returns 0 if valid (including MAC), -1 otherwise
36 : : */
37 : 0 : static int parse_peer_object_path(char *peer_path, u8 addr[ETH_ALEN])
38 : : {
39 : : char *p;
40 : :
41 [ # # ]: 0 : if (!peer_path)
42 : 0 : return -1;
43 : 0 : p = os_strrchr(peer_path, '/');
44 [ # # ]: 0 : if (!p)
45 : 0 : return -1;
46 : 0 : p++;
47 : 0 : return hwaddr_compact_aton(p, addr);
48 : : }
49 : :
50 : :
51 : : /**
52 : : * wpas_dbus_error_persistent_group_unknown - Return a new PersistentGroupUnknown
53 : : * error message
54 : : * @message: Pointer to incoming dbus message this error refers to
55 : : * Returns: a dbus error message
56 : : *
57 : : * Convenience function to create and return an invalid persistent group error.
58 : : */
59 : 0 : static DBusMessage * wpas_dbus_error_persistent_group_unknown(
60 : : DBusMessage *message)
61 : : {
62 : 0 : return dbus_message_new_error(message, WPAS_DBUS_ERROR_NETWORK_UNKNOWN,
63 : : "There is no such persistent group in "
64 : : "this P2P device.");
65 : : }
66 : :
67 : :
68 : 0 : DBusMessage * wpas_dbus_handler_p2p_find(DBusMessage *message,
69 : : struct wpa_supplicant *wpa_s)
70 : : {
71 : : struct wpa_dbus_dict_entry entry;
72 : 0 : DBusMessage *reply = NULL;
73 : : DBusMessageIter iter;
74 : : DBusMessageIter iter_dict;
75 : 0 : unsigned int timeout = 0;
76 : 0 : enum p2p_discovery_type type = P2P_FIND_ONLY_SOCIAL;
77 : 0 : int num_req_dev_types = 0;
78 : : unsigned int i;
79 : 0 : u8 *req_dev_types = NULL;
80 : :
81 : 0 : dbus_message_iter_init(message, &iter);
82 : 0 : entry.key = NULL;
83 : :
84 [ # # ]: 0 : if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL))
85 : 0 : goto error;
86 : :
87 [ # # ]: 0 : while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
88 [ # # ]: 0 : if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
89 : 0 : goto error;
90 : :
91 [ # # ][ # # ]: 0 : if (!os_strcmp(entry.key, "Timeout") &&
92 : 0 : (entry.type == DBUS_TYPE_INT32)) {
93 : 0 : timeout = entry.uint32_value;
94 [ # # ]: 0 : } else if (os_strcmp(entry.key, "RequestedDeviceTypes") == 0) {
95 [ # # ][ # # ]: 0 : if ((entry.type != DBUS_TYPE_ARRAY) ||
96 : 0 : (entry.array_type != WPAS_DBUS_TYPE_BINARRAY))
97 : : goto error_clear;
98 : :
99 : 0 : os_free(req_dev_types);
100 : 0 : req_dev_types =
101 : 0 : os_malloc(WPS_DEV_TYPE_LEN * entry.array_len);
102 [ # # ]: 0 : if (!req_dev_types)
103 : 0 : goto error_clear;
104 : :
105 [ # # ]: 0 : for (i = 0; i < entry.array_len; i++) {
106 [ # # ]: 0 : if (wpabuf_len(entry.binarray_value[i]) !=
107 : : WPS_DEV_TYPE_LEN)
108 : 0 : goto error_clear;
109 : 0 : os_memcpy(req_dev_types + i * WPS_DEV_TYPE_LEN,
110 : : wpabuf_head(entry.binarray_value[i]),
111 : : WPS_DEV_TYPE_LEN);
112 : : }
113 : 0 : num_req_dev_types = entry.array_len;
114 [ # # ][ # # ]: 0 : } else if (!os_strcmp(entry.key, "DiscoveryType") &&
115 : 0 : (entry.type == DBUS_TYPE_STRING)) {
116 [ # # ]: 0 : if (!os_strcmp(entry.str_value, "start_with_full"))
117 : 0 : type = P2P_FIND_START_WITH_FULL;
118 [ # # ]: 0 : else if (!os_strcmp(entry.str_value, "social"))
119 : 0 : type = P2P_FIND_ONLY_SOCIAL;
120 [ # # ]: 0 : else if (!os_strcmp(entry.str_value, "progressive"))
121 : 0 : type = P2P_FIND_PROGRESSIVE;
122 : : else
123 : 0 : goto error_clear;
124 : : } else
125 : : goto error_clear;
126 : 0 : wpa_dbus_dict_entry_clear(&entry);
127 : : }
128 : :
129 : 0 : wpas_p2p_find(wpa_s, timeout, type, num_req_dev_types, req_dev_types,
130 : : NULL, 0);
131 : 0 : os_free(req_dev_types);
132 : 0 : return reply;
133 : :
134 : : error_clear:
135 : 0 : wpa_dbus_dict_entry_clear(&entry);
136 : : error:
137 : 0 : os_free(req_dev_types);
138 : 0 : reply = wpas_dbus_error_invalid_args(message, entry.key);
139 : 0 : return reply;
140 : : }
141 : :
142 : :
143 : 0 : DBusMessage * wpas_dbus_handler_p2p_stop_find(DBusMessage *message,
144 : : struct wpa_supplicant *wpa_s)
145 : : {
146 : 0 : wpas_p2p_stop_find(wpa_s);
147 : 0 : return NULL;
148 : : }
149 : :
150 : :
151 : 0 : DBusMessage * wpas_dbus_handler_p2p_rejectpeer(DBusMessage *message,
152 : : struct wpa_supplicant *wpa_s)
153 : : {
154 : : DBusMessageIter iter;
155 : 0 : char *peer_object_path = NULL;
156 : : u8 peer_addr[ETH_ALEN];
157 : :
158 : 0 : dbus_message_iter_init(message, &iter);
159 : 0 : dbus_message_iter_get_basic(&iter, &peer_object_path);
160 : :
161 [ # # ]: 0 : if (parse_peer_object_path(peer_object_path, peer_addr) < 0)
162 : 0 : return wpas_dbus_error_invalid_args(message, NULL);
163 : :
164 [ # # ]: 0 : if (wpas_p2p_reject(wpa_s, peer_addr) < 0)
165 : 0 : return wpas_dbus_error_unknown_error(message,
166 : : "Failed to call wpas_p2p_reject method.");
167 : :
168 : 0 : return NULL;
169 : : }
170 : :
171 : :
172 : 0 : DBusMessage * wpas_dbus_handler_p2p_listen(DBusMessage *message,
173 : : struct wpa_supplicant *wpa_s)
174 : : {
175 : 0 : dbus_int32_t timeout = 0;
176 : :
177 [ # # ]: 0 : if (!dbus_message_get_args(message, NULL, DBUS_TYPE_INT32, &timeout,
178 : : DBUS_TYPE_INVALID))
179 : 0 : return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
180 : : NULL);
181 : :
182 [ # # ]: 0 : if (wpas_p2p_listen(wpa_s, (unsigned int)timeout))
183 : 0 : return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
184 : : NULL);
185 : :
186 : 0 : return NULL;
187 : : }
188 : :
189 : :
190 : 0 : DBusMessage * wpas_dbus_handler_p2p_extendedlisten(
191 : : DBusMessage *message, struct wpa_supplicant *wpa_s)
192 : : {
193 : 0 : unsigned int period = 0, interval = 0;
194 : : struct wpa_dbus_dict_entry entry;
195 : : DBusMessageIter iter;
196 : : DBusMessageIter iter_dict;
197 : :
198 : 0 : dbus_message_iter_init(message, &iter);
199 : 0 : entry.key = NULL;
200 : :
201 [ # # ]: 0 : if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL))
202 : 0 : goto error;
203 : :
204 [ # # ]: 0 : while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
205 [ # # ]: 0 : if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
206 : 0 : goto error;
207 : :
208 [ # # ][ # # ]: 0 : if (!os_strcmp(entry.key, "period") &&
209 : 0 : (entry.type == DBUS_TYPE_INT32))
210 : 0 : period = entry.uint32_value;
211 [ # # ][ # # ]: 0 : else if (!os_strcmp(entry.key, "interval") &&
212 : 0 : (entry.type == DBUS_TYPE_INT32))
213 : 0 : interval = entry.uint32_value;
214 : : else
215 : : goto error_clear;
216 : 0 : wpa_dbus_dict_entry_clear(&entry);
217 : : }
218 : :
219 [ # # ]: 0 : if (wpas_p2p_ext_listen(wpa_s, period, interval))
220 : 0 : return wpas_dbus_error_unknown_error(
221 : : message, "failed to initiate a p2p_ext_listen.");
222 : :
223 : 0 : return NULL;
224 : :
225 : : error_clear:
226 : 0 : wpa_dbus_dict_entry_clear(&entry);
227 : : error:
228 : 0 : return wpas_dbus_error_invalid_args(message, entry.key);
229 : : }
230 : :
231 : :
232 : 0 : DBusMessage * wpas_dbus_handler_p2p_presence_request(
233 : : DBusMessage *message, struct wpa_supplicant *wpa_s)
234 : : {
235 : 0 : unsigned int dur1 = 0, int1 = 0, dur2 = 0, int2 = 0;
236 : : struct wpa_dbus_dict_entry entry;
237 : : DBusMessageIter iter;
238 : : DBusMessageIter iter_dict;
239 : :
240 : 0 : dbus_message_iter_init(message, &iter);
241 : 0 : entry.key = NULL;
242 : :
243 [ # # ]: 0 : if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL))
244 : 0 : goto error;
245 : :
246 [ # # ]: 0 : while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
247 [ # # ]: 0 : if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
248 : 0 : goto error;
249 : :
250 [ # # ][ # # ]: 0 : if (!os_strcmp(entry.key, "duration1") &&
251 : 0 : (entry.type == DBUS_TYPE_INT32))
252 : 0 : dur1 = entry.uint32_value;
253 [ # # ][ # # ]: 0 : else if (!os_strcmp(entry.key, "interval1") &&
254 : 0 : entry.type == DBUS_TYPE_INT32)
255 : 0 : int1 = entry.uint32_value;
256 [ # # ][ # # ]: 0 : else if (!os_strcmp(entry.key, "duration2") &&
257 : 0 : entry.type == DBUS_TYPE_INT32)
258 : 0 : dur2 = entry.uint32_value;
259 [ # # ][ # # ]: 0 : else if (!os_strcmp(entry.key, "interval2") &&
260 : 0 : entry.type == DBUS_TYPE_INT32)
261 : 0 : int2 = entry.uint32_value;
262 : : else
263 : : goto error_clear;
264 : :
265 : 0 : wpa_dbus_dict_entry_clear(&entry);
266 : : }
267 [ # # ]: 0 : if (wpas_p2p_presence_req(wpa_s, dur1, int1, dur2, int2) < 0)
268 : 0 : return wpas_dbus_error_unknown_error(message,
269 : : "Failed to invoke presence request.");
270 : :
271 : 0 : return NULL;
272 : :
273 : : error_clear:
274 : 0 : wpa_dbus_dict_entry_clear(&entry);
275 : : error:
276 : 0 : return wpas_dbus_error_invalid_args(message, entry.key);
277 : : }
278 : :
279 : :
280 : 0 : DBusMessage * wpas_dbus_handler_p2p_group_add(DBusMessage *message,
281 : : struct wpa_supplicant *wpa_s)
282 : : {
283 : : DBusMessageIter iter_dict;
284 : 0 : DBusMessage *reply = NULL;
285 : : DBusMessageIter iter;
286 : : struct wpa_dbus_dict_entry entry;
287 : 0 : char *pg_object_path = NULL;
288 : 0 : int persistent_group = 0;
289 : 0 : int freq = 0;
290 : 0 : char *iface = NULL;
291 : 0 : char *net_id_str = NULL;
292 : 0 : unsigned int group_id = 0;
293 : : struct wpa_ssid *ssid;
294 : :
295 : 0 : dbus_message_iter_init(message, &iter);
296 : :
297 [ # # ]: 0 : if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL))
298 : 0 : goto inv_args;
299 : :
300 [ # # ]: 0 : while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
301 [ # # ]: 0 : if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
302 : 0 : goto inv_args;
303 : :
304 [ # # ][ # # ]: 0 : if (!os_strcmp(entry.key, "persistent") &&
305 : 0 : (entry.type == DBUS_TYPE_BOOLEAN)) {
306 : 0 : persistent_group = (entry.bool_value == TRUE) ? 1 : 0;
307 [ # # ][ # # ]: 0 : } else if (!os_strcmp(entry.key, "frequency") &&
308 : 0 : (entry.type == DBUS_TYPE_INT32)) {
309 : 0 : freq = entry.int32_value;
310 [ # # ]: 0 : if (freq <= 0)
311 : 0 : goto inv_args_clear;
312 [ # # ][ # # ]: 0 : } else if (!os_strcmp(entry.key, "persistent_group_object") &&
313 : 0 : entry.type == DBUS_TYPE_OBJECT_PATH)
314 : 0 : pg_object_path = os_strdup(entry.str_value);
315 : : else
316 : : goto inv_args_clear;
317 : :
318 : 0 : wpa_dbus_dict_entry_clear(&entry);
319 : : }
320 : :
321 [ # # ]: 0 : if (pg_object_path != NULL) {
322 : : /*
323 : : * A persistent group Object Path is defined meaning we want
324 : : * to re-invoke a persistent group.
325 : : */
326 : :
327 : 0 : iface = wpas_dbus_new_decompose_object_path(pg_object_path, 1,
328 : : &net_id_str, NULL);
329 [ # # ][ # # ]: 0 : if (iface == NULL ||
330 : 0 : os_strcmp(iface, wpa_s->dbus_new_path) != 0) {
331 : 0 : reply =
332 : : wpas_dbus_error_invalid_args(message,
333 : : pg_object_path);
334 : 0 : goto out;
335 : : }
336 : :
337 : 0 : group_id = strtoul(net_id_str, NULL, 10);
338 [ # # ]: 0 : if (errno == EINVAL) {
339 : 0 : reply = wpas_dbus_error_invalid_args(
340 : : message, pg_object_path);
341 : 0 : goto out;
342 : : }
343 : :
344 : : /* Get the SSID structure from the persistent group id */
345 : 0 : ssid = wpa_config_get_network(wpa_s->conf, group_id);
346 [ # # ][ # # ]: 0 : if (ssid == NULL || ssid->disabled != 2)
347 : : goto inv_args;
348 : :
349 [ # # ]: 0 : if (wpas_p2p_group_add_persistent(wpa_s, ssid, 0, freq, 0, 0,
350 : : NULL, 0)) {
351 : 0 : reply = wpas_dbus_error_unknown_error(
352 : : message,
353 : : "Failed to reinvoke a persistent group");
354 : 0 : goto out;
355 : : }
356 [ # # ]: 0 : } else if (wpas_p2p_group_add(wpa_s, persistent_group, freq, 0, 0))
357 : 0 : goto inv_args;
358 : :
359 : : out:
360 : 0 : os_free(pg_object_path);
361 : 0 : os_free(net_id_str);
362 : 0 : os_free(iface);
363 : 0 : return reply;
364 : : inv_args_clear:
365 : 0 : wpa_dbus_dict_entry_clear(&entry);
366 : : inv_args:
367 : 0 : reply = wpas_dbus_error_invalid_args(message, NULL);
368 : 0 : goto out;
369 : : }
370 : :
371 : :
372 : 0 : DBusMessage * wpas_dbus_handler_p2p_disconnect(DBusMessage *message,
373 : : struct wpa_supplicant *wpa_s)
374 : : {
375 [ # # ]: 0 : if (wpas_p2p_disconnect(wpa_s))
376 : 0 : return wpas_dbus_error_unknown_error(message,
377 : : "failed to disconnect");
378 : :
379 : 0 : return NULL;
380 : : }
381 : :
382 : :
383 : 0 : static dbus_bool_t wpa_dbus_p2p_check_enabled(struct wpa_supplicant *wpa_s,
384 : : DBusMessage *message,
385 : : DBusMessage **out_reply,
386 : : DBusError *error)
387 : : {
388 : : /* Return an error message or an error if P2P isn't available */
389 [ # # ][ # # ]: 0 : if (wpa_s->global->p2p_disabled || wpa_s->global->p2p == NULL) {
390 [ # # ]: 0 : if (out_reply) {
391 : 0 : *out_reply = dbus_message_new_error(
392 : : message, DBUS_ERROR_FAILED,
393 : : "P2P is not available for this interface");
394 : : }
395 : 0 : dbus_set_error_const(error, DBUS_ERROR_FAILED,
396 : : "P2P is not available for this "
397 : : "interface");
398 : 0 : return FALSE;
399 : : }
400 : 0 : return TRUE;
401 : : }
402 : :
403 : :
404 : 0 : DBusMessage * wpas_dbus_handler_p2p_flush(DBusMessage *message,
405 : : struct wpa_supplicant *wpa_s)
406 : : {
407 : 0 : DBusMessage *reply = NULL;
408 : :
409 [ # # ]: 0 : if (!wpa_dbus_p2p_check_enabled(wpa_s, message, &reply, NULL))
410 : 0 : return reply;
411 : :
412 : 0 : os_memset(wpa_s->p2p_auth_invite, 0, ETH_ALEN);
413 : 0 : wpa_s->force_long_sd = 0;
414 : 0 : p2p_flush(wpa_s->global->p2p);
415 : :
416 : 0 : return NULL;
417 : : }
418 : :
419 : :
420 : 0 : DBusMessage * wpas_dbus_handler_p2p_connect(DBusMessage *message,
421 : : struct wpa_supplicant *wpa_s)
422 : : {
423 : : DBusMessageIter iter_dict;
424 : 0 : DBusMessage *reply = NULL;
425 : : DBusMessageIter iter;
426 : : struct wpa_dbus_dict_entry entry;
427 : 0 : char *peer_object_path = NULL;
428 : 0 : int persistent_group = 0;
429 : 0 : int join = 0;
430 : 0 : int authorize_only = 0;
431 : 0 : int go_intent = -1;
432 : 0 : int freq = 0;
433 : : u8 addr[ETH_ALEN];
434 : 0 : char *pin = NULL;
435 : 0 : enum p2p_wps_method wps_method = WPS_NOT_READY;
436 : : int new_pin;
437 : 0 : char *err_msg = NULL;
438 : 0 : char *iface = NULL;
439 : :
440 [ # # ]: 0 : if (!wpa_dbus_p2p_check_enabled(wpa_s, message, &reply, NULL))
441 : 0 : return reply;
442 : :
443 : 0 : dbus_message_iter_init(message, &iter);
444 : :
445 [ # # ]: 0 : if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL))
446 : 0 : goto inv_args;
447 : :
448 [ # # ]: 0 : while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
449 [ # # ]: 0 : if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
450 : 0 : goto inv_args;
451 : :
452 [ # # ][ # # ]: 0 : if (!os_strcmp(entry.key, "peer") &&
453 : 0 : (entry.type == DBUS_TYPE_OBJECT_PATH)) {
454 : 0 : peer_object_path = os_strdup(entry.str_value);
455 [ # # ][ # # ]: 0 : } else if (!os_strcmp(entry.key, "persistent") &&
456 : 0 : (entry.type == DBUS_TYPE_BOOLEAN)) {
457 : 0 : persistent_group = (entry.bool_value == TRUE) ? 1 : 0;
458 [ # # ][ # # ]: 0 : } else if (!os_strcmp(entry.key, "join") &&
459 : 0 : (entry.type == DBUS_TYPE_BOOLEAN)) {
460 : 0 : join = (entry.bool_value == TRUE) ? 1 : 0;
461 [ # # ][ # # ]: 0 : } else if (!os_strcmp(entry.key, "authorize_only") &&
462 : 0 : (entry.type == DBUS_TYPE_BOOLEAN)) {
463 : 0 : authorize_only = (entry.bool_value == TRUE) ? 1 : 0;
464 [ # # ][ # # ]: 0 : } else if (!os_strcmp(entry.key, "frequency") &&
465 : 0 : (entry.type == DBUS_TYPE_INT32)) {
466 : 0 : freq = entry.int32_value;
467 [ # # ]: 0 : if (freq <= 0)
468 : 0 : goto inv_args_clear;
469 [ # # ][ # # ]: 0 : } else if (!os_strcmp(entry.key, "go_intent") &&
470 : 0 : (entry.type == DBUS_TYPE_INT32)) {
471 : 0 : go_intent = entry.int32_value;
472 [ # # ][ # # ]: 0 : if ((go_intent < 0) || (go_intent > 15))
473 : : goto inv_args_clear;
474 [ # # ][ # # ]: 0 : } else if (!os_strcmp(entry.key, "wps_method") &&
475 : 0 : (entry.type == DBUS_TYPE_STRING)) {
476 [ # # ]: 0 : if (!os_strcmp(entry.str_value, "pbc"))
477 : 0 : wps_method = WPS_PBC;
478 [ # # ]: 0 : else if (!os_strcmp(entry.str_value, "pin"))
479 : 0 : wps_method = WPS_PIN_DISPLAY;
480 [ # # ]: 0 : else if (!os_strcmp(entry.str_value, "display"))
481 : 0 : wps_method = WPS_PIN_DISPLAY;
482 [ # # ]: 0 : else if (!os_strcmp(entry.str_value, "keypad"))
483 : 0 : wps_method = WPS_PIN_KEYPAD;
484 : : else
485 : 0 : goto inv_args_clear;
486 [ # # ][ # # ]: 0 : } else if (!os_strcmp(entry.key, "pin") &&
487 : 0 : (entry.type == DBUS_TYPE_STRING)) {
488 : 0 : pin = os_strdup(entry.str_value);
489 : : } else
490 : : goto inv_args_clear;
491 : :
492 : 0 : wpa_dbus_dict_entry_clear(&entry);
493 : : }
494 : :
495 [ # # ]: 0 : if (!peer_object_path || (wps_method == WPS_NOT_READY) ||
[ # # # # ]
496 [ # # ]: 0 : (parse_peer_object_path(peer_object_path, addr) < 0) ||
497 : 0 : !p2p_peer_known(wpa_s->global->p2p, addr))
498 : : goto inv_args;
499 : :
500 : : /*
501 : : * Validate the wps_method specified and the pin value.
502 : : */
503 [ # # ][ # # ]: 0 : if ((!pin || !pin[0]) && (wps_method == WPS_PIN_KEYPAD))
[ # # ]
504 : 0 : goto inv_args;
505 : :
506 : 0 : new_pin = wpas_p2p_connect(wpa_s, addr, pin, wps_method,
507 : : persistent_group, 0, join, authorize_only,
508 : : go_intent, freq, -1, 0, 0, 0);
509 : :
510 [ # # ]: 0 : if (new_pin >= 0) {
511 : : char npin[9];
512 : : char *generated_pin;
513 : 0 : os_snprintf(npin, sizeof(npin), "%08d", new_pin);
514 : 0 : generated_pin = npin;
515 : 0 : reply = dbus_message_new_method_return(message);
516 : 0 : dbus_message_append_args(reply, DBUS_TYPE_STRING,
517 : : &generated_pin, DBUS_TYPE_INVALID);
518 : : } else {
519 [ # # # ]: 0 : switch (new_pin) {
520 : : case -2:
521 : 0 : err_msg = "connect failed due to channel "
522 : : "unavailability.";
523 : 0 : iface = WPAS_DBUS_ERROR_CONNECT_CHANNEL_UNAVAILABLE;
524 : 0 : break;
525 : :
526 : : case -3:
527 : 0 : err_msg = "connect failed due to unsupported channel.";
528 : 0 : iface = WPAS_DBUS_ERROR_CONNECT_CHANNEL_UNSUPPORTED;
529 : 0 : break;
530 : :
531 : : default:
532 : 0 : err_msg = "connect failed due to unspecified error.";
533 : 0 : iface = WPAS_DBUS_ERROR_CONNECT_UNSPECIFIED_ERROR;
534 : 0 : break;
535 : : }
536 : :
537 : : /*
538 : : * TODO:
539 : : * Do we need specialized errors corresponding to above
540 : : * error conditions as against just returning a different
541 : : * error message?
542 : : */
543 : 0 : reply = dbus_message_new_error(message, iface, err_msg);
544 : : }
545 : :
546 : : out:
547 : 0 : os_free(peer_object_path);
548 : 0 : os_free(pin);
549 : 0 : return reply;
550 : : inv_args_clear:
551 : 0 : wpa_dbus_dict_entry_clear(&entry);
552 : : inv_args:
553 : 0 : reply = wpas_dbus_error_invalid_args(message, NULL);
554 : 0 : goto out;
555 : : }
556 : :
557 : :
558 : 0 : DBusMessage * wpas_dbus_handler_p2p_invite(DBusMessage *message,
559 : : struct wpa_supplicant *wpa_s)
560 : : {
561 : : DBusMessageIter iter_dict;
562 : 0 : DBusMessage *reply = NULL;
563 : : DBusMessageIter iter;
564 : : struct wpa_dbus_dict_entry entry;
565 : 0 : char *peer_object_path = NULL;
566 : 0 : char *pg_object_path = NULL;
567 : 0 : char *iface = NULL;
568 : 0 : char *net_id_str = NULL;
569 : : u8 peer_addr[ETH_ALEN];
570 : 0 : unsigned int group_id = 0;
571 : 0 : int persistent = 0;
572 : : struct wpa_ssid *ssid;
573 : :
574 [ # # ]: 0 : if (!wpa_dbus_p2p_check_enabled(wpa_s, message, &reply, NULL))
575 : 0 : return reply;
576 : :
577 : 0 : dbus_message_iter_init(message, &iter);
578 : :
579 [ # # ]: 0 : if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL))
580 : 0 : goto err;
581 : :
582 [ # # ]: 0 : while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
583 [ # # ]: 0 : if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
584 : 0 : goto err;
585 : :
586 [ # # ][ # # ]: 0 : if (!os_strcmp(entry.key, "peer") &&
587 : 0 : (entry.type == DBUS_TYPE_OBJECT_PATH)) {
588 : 0 : peer_object_path = os_strdup(entry.str_value);
589 : 0 : wpa_dbus_dict_entry_clear(&entry);
590 [ # # ][ # # ]: 0 : } else if (!os_strcmp(entry.key, "persistent_group_object") &&
591 : 0 : (entry.type == DBUS_TYPE_OBJECT_PATH)) {
592 : 0 : pg_object_path = os_strdup(entry.str_value);
593 : 0 : persistent = 1;
594 : 0 : wpa_dbus_dict_entry_clear(&entry);
595 : : } else {
596 : 0 : wpa_dbus_dict_entry_clear(&entry);
597 : 0 : goto err;
598 : : }
599 : : }
600 : :
601 [ # # # # ]: 0 : if (!peer_object_path ||
602 [ # # ]: 0 : (parse_peer_object_path(peer_object_path, peer_addr) < 0) ||
603 : 0 : !p2p_peer_known(wpa_s->global->p2p, peer_addr)) {
604 : : goto err;
605 : : }
606 : :
607 [ # # ]: 0 : if (persistent) {
608 : : /*
609 : : * A group ID is defined meaning we want to re-invoke a
610 : : * persistent group
611 : : */
612 : :
613 : 0 : iface = wpas_dbus_new_decompose_object_path(pg_object_path, 1,
614 : : &net_id_str, NULL);
615 [ # # ][ # # ]: 0 : if (iface == NULL ||
616 : 0 : os_strcmp(iface, wpa_s->dbus_new_path) != 0) {
617 : 0 : reply = wpas_dbus_error_invalid_args(message,
618 : : pg_object_path);
619 : 0 : goto out;
620 : : }
621 : :
622 : 0 : group_id = strtoul(net_id_str, NULL, 10);
623 [ # # ]: 0 : if (errno == EINVAL) {
624 : 0 : reply = wpas_dbus_error_invalid_args(
625 : : message, pg_object_path);
626 : 0 : goto out;
627 : : }
628 : :
629 : : /* Get the SSID structure from the persistent group id */
630 : 0 : ssid = wpa_config_get_network(wpa_s->conf, group_id);
631 [ # # ][ # # ]: 0 : if (ssid == NULL || ssid->disabled != 2)
632 : : goto err;
633 : :
634 [ # # ]: 0 : if (wpas_p2p_invite(wpa_s, peer_addr, ssid, NULL, 0, 0, 0, 0) <
635 : : 0) {
636 : 0 : reply = wpas_dbus_error_unknown_error(
637 : : message,
638 : : "Failed to reinvoke a persistent group");
639 : 0 : goto out;
640 : : }
641 : : } else {
642 : : /*
643 : : * No group ID means propose to a peer to join my active group
644 : : */
645 [ # # ]: 0 : if (wpas_p2p_invite_group(wpa_s, wpa_s->ifname,
646 : : peer_addr, NULL)) {
647 : 0 : reply = wpas_dbus_error_unknown_error(
648 : : message, "Failed to join to an active group");
649 : 0 : goto out;
650 : : }
651 : : }
652 : :
653 : : out:
654 : 0 : os_free(pg_object_path);
655 : 0 : os_free(peer_object_path);
656 : 0 : return reply;
657 : :
658 : : err:
659 : 0 : reply = wpas_dbus_error_invalid_args(message, NULL);
660 : 0 : goto out;
661 : : }
662 : :
663 : :
664 : 0 : DBusMessage * wpas_dbus_handler_p2p_prov_disc_req(DBusMessage *message,
665 : : struct wpa_supplicant *wpa_s)
666 : : {
667 : : DBusMessageIter iter;
668 : 0 : char *peer_object_path = NULL;
669 : 0 : char *config_method = NULL;
670 : : u8 peer_addr[ETH_ALEN];
671 : :
672 : 0 : dbus_message_iter_init(message, &iter);
673 : 0 : dbus_message_iter_get_basic(&iter, &peer_object_path);
674 : :
675 [ # # ]: 0 : if (parse_peer_object_path(peer_object_path, peer_addr) < 0)
676 : 0 : return wpas_dbus_error_invalid_args(message, NULL);
677 : :
678 : 0 : dbus_message_iter_next(&iter);
679 : 0 : dbus_message_iter_get_basic(&iter, &config_method);
680 : :
681 : : /*
682 : : * Validation checks on config_method are being duplicated here
683 : : * to be able to return invalid args reply since the error code
684 : : * from p2p module are not granular enough (yet).
685 : : */
686 [ # # ][ # # ]: 0 : if (os_strcmp(config_method, "display") &&
687 [ # # ]: 0 : os_strcmp(config_method, "keypad") &&
688 [ # # ]: 0 : os_strcmp(config_method, "pbc") &&
689 : 0 : os_strcmp(config_method, "pushbutton"))
690 : 0 : return wpas_dbus_error_invalid_args(message, NULL);
691 : :
692 [ # # ]: 0 : if (wpas_p2p_prov_disc(wpa_s, peer_addr, config_method,
693 : : WPAS_P2P_PD_FOR_GO_NEG) < 0)
694 : 0 : return wpas_dbus_error_unknown_error(message,
695 : : "Failed to send provision discovery request");
696 : :
697 : 0 : return NULL;
698 : : }
699 : :
700 : :
701 : : /*
702 : : * P2P Device property accessor methods.
703 : : */
704 : :
705 : 0 : dbus_bool_t wpas_dbus_getter_p2p_device_config(DBusMessageIter *iter,
706 : : DBusError *error,
707 : : void *user_data)
708 : : {
709 : 0 : struct wpa_supplicant *wpa_s = user_data;
710 : : DBusMessageIter variant_iter, dict_iter;
711 : : DBusMessageIter iter_secdev_dict_entry, iter_secdev_dict_val,
712 : : iter_secdev_dict_array;
713 : : const char *dev_name;
714 : 0 : int num_vendor_extensions = 0;
715 : : int i;
716 : : const struct wpabuf *vendor_ext[P2P_MAX_WPS_VENDOR_EXT];
717 : :
718 [ # # ]: 0 : if (!wpa_dbus_p2p_check_enabled(wpa_s, NULL, NULL, error))
719 : 0 : return FALSE;
720 : :
721 [ # # ]: 0 : if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT,
722 [ # # ]: 0 : "a{sv}", &variant_iter) ||
723 : 0 : !wpa_dbus_dict_open_write(&variant_iter, &dict_iter))
724 : : goto err_no_mem;
725 : :
726 : : /* DeviceName */
727 : 0 : dev_name = wpa_s->conf->device_name;
728 [ # # # # ]: 0 : if (dev_name &&
729 : 0 : !wpa_dbus_dict_append_string(&dict_iter, "DeviceName", dev_name))
730 : 0 : goto err_no_mem;
731 : :
732 : : /* Primary device type */
733 [ # # ]: 0 : if (!wpa_dbus_dict_append_byte_array(&dict_iter, "PrimaryDeviceType",
734 : 0 : (char *)wpa_s->conf->device_type,
735 : : WPS_DEV_TYPE_LEN))
736 : 0 : goto err_no_mem;
737 : :
738 : : /* Secondary device types */
739 [ # # ]: 0 : if (wpa_s->conf->num_sec_device_types) {
740 [ # # ]: 0 : if (!wpa_dbus_dict_begin_array(&dict_iter,
741 : : "SecondaryDeviceTypes",
742 : : DBUS_TYPE_ARRAY_AS_STRING
743 : : DBUS_TYPE_BYTE_AS_STRING,
744 : : &iter_secdev_dict_entry,
745 : : &iter_secdev_dict_val,
746 : : &iter_secdev_dict_array))
747 : 0 : goto err_no_mem;
748 : :
749 [ # # ]: 0 : for (i = 0; i < wpa_s->conf->num_sec_device_types; i++)
750 : 0 : wpa_dbus_dict_bin_array_add_element(
751 : : &iter_secdev_dict_array,
752 : 0 : wpa_s->conf->sec_device_type[i],
753 : : WPS_DEV_TYPE_LEN);
754 : :
755 [ # # ]: 0 : if (!wpa_dbus_dict_end_array(&dict_iter,
756 : : &iter_secdev_dict_entry,
757 : : &iter_secdev_dict_val,
758 : : &iter_secdev_dict_array))
759 : 0 : goto err_no_mem;
760 : : }
761 : :
762 : : /* Vendor Extensions */
763 [ # # ]: 0 : for (i = 0; i < P2P_MAX_WPS_VENDOR_EXT; i++) {
764 [ # # ]: 0 : if (wpa_s->conf->wps_vendor_ext[i] == NULL)
765 : 0 : continue;
766 : 0 : vendor_ext[num_vendor_extensions++] =
767 : 0 : wpa_s->conf->wps_vendor_ext[i];
768 : : }
769 : :
770 [ # # # # ]: 0 : if (num_vendor_extensions &&
771 : 0 : !wpa_dbus_dict_append_wpabuf_array(&dict_iter,
772 : : "VendorExtension",
773 : : vendor_ext,
774 : : num_vendor_extensions))
775 : 0 : goto err_no_mem;
776 : :
777 : : /* GO Intent */
778 [ # # ]: 0 : if (!wpa_dbus_dict_append_uint32(&dict_iter, "GOIntent",
779 : 0 : wpa_s->conf->p2p_go_intent))
780 : 0 : goto err_no_mem;
781 : :
782 : : /* Persistent Reconnect */
783 [ # # ]: 0 : if (!wpa_dbus_dict_append_bool(&dict_iter, "PersistentReconnect",
784 : 0 : wpa_s->conf->persistent_reconnect))
785 : 0 : goto err_no_mem;
786 : :
787 : : /* Listen Reg Class */
788 [ # # ]: 0 : if (!wpa_dbus_dict_append_uint32(&dict_iter, "ListenRegClass",
789 : 0 : wpa_s->conf->p2p_listen_reg_class))
790 : 0 : goto err_no_mem;
791 : :
792 : : /* Listen Channel */
793 [ # # ]: 0 : if (!wpa_dbus_dict_append_uint32(&dict_iter, "ListenChannel",
794 : 0 : wpa_s->conf->p2p_listen_channel))
795 : 0 : goto err_no_mem;
796 : :
797 : : /* Oper Reg Class */
798 [ # # ]: 0 : if (!wpa_dbus_dict_append_uint32(&dict_iter, "OperRegClass",
799 : 0 : wpa_s->conf->p2p_oper_reg_class))
800 : 0 : goto err_no_mem;
801 : :
802 : : /* Oper Channel */
803 [ # # ]: 0 : if (!wpa_dbus_dict_append_uint32(&dict_iter, "OperChannel",
804 : 0 : wpa_s->conf->p2p_oper_channel))
805 : 0 : goto err_no_mem;
806 : :
807 : : /* SSID Postfix */
808 [ # # # # ]: 0 : if (wpa_s->conf->p2p_ssid_postfix &&
809 : 0 : !wpa_dbus_dict_append_string(&dict_iter, "SsidPostfix",
810 : 0 : wpa_s->conf->p2p_ssid_postfix))
811 : 0 : goto err_no_mem;
812 : :
813 : : /* Intra Bss */
814 [ # # ]: 0 : if (!wpa_dbus_dict_append_bool(&dict_iter, "IntraBss",
815 : 0 : wpa_s->conf->p2p_intra_bss))
816 : 0 : goto err_no_mem;
817 : :
818 : : /* Group Idle */
819 [ # # ]: 0 : if (!wpa_dbus_dict_append_uint32(&dict_iter, "GroupIdle",
820 : 0 : wpa_s->conf->p2p_group_idle))
821 : 0 : goto err_no_mem;
822 : :
823 : : /* Dissasociation low ack */
824 [ # # ]: 0 : if (!wpa_dbus_dict_append_uint32(&dict_iter, "disassoc_low_ack",
825 : 0 : wpa_s->conf->disassoc_low_ack))
826 : 0 : goto err_no_mem;
827 : :
828 [ # # # # ]: 0 : if (!wpa_dbus_dict_close_write(&variant_iter, &dict_iter) ||
829 : 0 : !dbus_message_iter_close_container(iter, &variant_iter))
830 : : goto err_no_mem;
831 : :
832 : 0 : return TRUE;
833 : :
834 : : err_no_mem:
835 : 0 : dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
836 : 0 : return FALSE;
837 : : }
838 : :
839 : :
840 : 0 : dbus_bool_t wpas_dbus_setter_p2p_device_config(DBusMessageIter *iter,
841 : : DBusError *error,
842 : : void *user_data)
843 : : {
844 : 0 : struct wpa_supplicant *wpa_s = user_data;
845 : : DBusMessageIter variant_iter, iter_dict;
846 : 0 : struct wpa_dbus_dict_entry entry = {.type = DBUS_TYPE_STRING };
847 : : unsigned int i;
848 : :
849 [ # # ]: 0 : if (!wpa_dbus_p2p_check_enabled(wpa_s, NULL, NULL, error))
850 : 0 : return FALSE;
851 : :
852 : 0 : dbus_message_iter_recurse(iter, &variant_iter);
853 [ # # ]: 0 : if (!wpa_dbus_dict_open_read(&variant_iter, &iter_dict, error))
854 : 0 : return FALSE;
855 : :
856 [ # # ]: 0 : while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
857 [ # # ]: 0 : if (!wpa_dbus_dict_get_entry(&iter_dict, &entry)) {
858 : 0 : dbus_set_error_const(error, DBUS_ERROR_INVALID_ARGS,
859 : : "invalid message format");
860 : 0 : return FALSE;
861 : : }
862 : :
863 [ # # ]: 0 : if (os_strcmp(entry.key, "DeviceName") == 0) {
864 : : char *devname;
865 : :
866 [ # # ]: 0 : if (entry.type != DBUS_TYPE_STRING)
867 : 0 : goto error;
868 : :
869 : 0 : devname = os_strdup(entry.str_value);
870 [ # # ]: 0 : if (devname == NULL)
871 : 0 : goto err_no_mem_clear;
872 : :
873 : 0 : os_free(wpa_s->conf->device_name);
874 : 0 : wpa_s->conf->device_name = devname;
875 : :
876 : 0 : wpa_s->conf->changed_parameters |=
877 : : CFG_CHANGED_DEVICE_NAME;
878 [ # # ]: 0 : } else if (os_strcmp(entry.key, "PrimaryDeviceType") == 0) {
879 [ # # ][ # # ]: 0 : if (entry.type != DBUS_TYPE_ARRAY ||
880 [ # # ]: 0 : entry.array_type != DBUS_TYPE_BYTE ||
881 : 0 : entry.array_len != WPS_DEV_TYPE_LEN)
882 : : goto error;
883 : :
884 : 0 : os_memcpy(wpa_s->conf->device_type,
885 : : entry.bytearray_value,
886 : : WPS_DEV_TYPE_LEN);
887 : 0 : wpa_s->conf->changed_parameters |=
888 : : CFG_CHANGED_DEVICE_TYPE;
889 [ # # ]: 0 : } else if (os_strcmp(entry.key, "SecondaryDeviceTypes") == 0) {
890 [ # # ][ # # ]: 0 : if (entry.type != DBUS_TYPE_ARRAY ||
891 [ # # ]: 0 : entry.array_type != WPAS_DBUS_TYPE_BINARRAY ||
892 : 0 : entry.array_len > MAX_SEC_DEVICE_TYPES)
893 : : goto error;
894 : :
895 [ # # ]: 0 : for (i = 0; i < entry.array_len; i++)
896 [ # # ]: 0 : if (wpabuf_len(entry.binarray_value[i]) !=
897 : : WPS_DEV_TYPE_LEN)
898 : 0 : goto err_no_mem_clear;
899 [ # # ]: 0 : for (i = 0; i < entry.array_len; i++)
900 : 0 : os_memcpy(wpa_s->conf->sec_device_type[i],
901 : : wpabuf_head(entry.binarray_value[i]),
902 : : WPS_DEV_TYPE_LEN);
903 : 0 : wpa_s->conf->num_sec_device_types = entry.array_len;
904 : 0 : wpa_s->conf->changed_parameters |=
905 : : CFG_CHANGED_SEC_DEVICE_TYPE;
906 [ # # ]: 0 : } else if (os_strcmp(entry.key, "VendorExtension") == 0) {
907 [ # # ][ # # ]: 0 : if ((entry.type != DBUS_TYPE_ARRAY) ||
908 [ # # ]: 0 : (entry.array_type != WPAS_DBUS_TYPE_BINARRAY) ||
909 : 0 : (entry.array_len > P2P_MAX_WPS_VENDOR_EXT))
910 : : goto error;
911 : :
912 : 0 : wpa_s->conf->changed_parameters |=
913 : : CFG_CHANGED_VENDOR_EXTENSION;
914 : :
915 [ # # ]: 0 : for (i = 0; i < P2P_MAX_WPS_VENDOR_EXT; i++) {
916 : 0 : wpabuf_free(wpa_s->conf->wps_vendor_ext[i]);
917 [ # # ]: 0 : if (i < entry.array_len) {
918 : 0 : wpa_s->conf->wps_vendor_ext[i] =
919 : 0 : entry.binarray_value[i];
920 : 0 : entry.binarray_value[i] = NULL;
921 : : } else
922 : 0 : wpa_s->conf->wps_vendor_ext[i] = NULL;
923 : : }
924 [ # # ][ # # ]: 0 : } else if ((os_strcmp(entry.key, "GOIntent") == 0) &&
925 [ # # ]: 0 : (entry.type == DBUS_TYPE_UINT32) &&
926 : 0 : (entry.uint32_value <= 15))
927 : 0 : wpa_s->conf->p2p_go_intent = entry.uint32_value;
928 [ # # ][ # # ]: 0 : else if ((os_strcmp(entry.key, "PersistentReconnect") == 0) &&
929 : 0 : (entry.type == DBUS_TYPE_BOOLEAN))
930 : 0 : wpa_s->conf->persistent_reconnect = entry.bool_value;
931 [ # # ][ # # ]: 0 : else if ((os_strcmp(entry.key, "ListenRegClass") == 0) &&
932 : 0 : (entry.type == DBUS_TYPE_UINT32)) {
933 : 0 : wpa_s->conf->p2p_listen_reg_class = entry.uint32_value;
934 : 0 : wpa_s->conf->changed_parameters |=
935 : : CFG_CHANGED_P2P_LISTEN_CHANNEL;
936 [ # # ][ # # ]: 0 : } else if ((os_strcmp(entry.key, "ListenChannel") == 0) &&
937 : 0 : (entry.type == DBUS_TYPE_UINT32)) {
938 : 0 : wpa_s->conf->p2p_listen_channel = entry.uint32_value;
939 : 0 : wpa_s->conf->changed_parameters |=
940 : : CFG_CHANGED_P2P_LISTEN_CHANNEL;
941 [ # # ][ # # ]: 0 : } else if ((os_strcmp(entry.key, "OperRegClass") == 0) &&
942 : 0 : (entry.type == DBUS_TYPE_UINT32)) {
943 : 0 : wpa_s->conf->p2p_oper_reg_class = entry.uint32_value;
944 : 0 : wpa_s->conf->changed_parameters |=
945 : : CFG_CHANGED_P2P_OPER_CHANNEL;
946 [ # # ][ # # ]: 0 : } else if ((os_strcmp(entry.key, "OperChannel") == 0) &&
947 : 0 : (entry.type == DBUS_TYPE_UINT32)) {
948 : 0 : wpa_s->conf->p2p_oper_channel = entry.uint32_value;
949 : 0 : wpa_s->conf->changed_parameters |=
950 : : CFG_CHANGED_P2P_OPER_CHANNEL;
951 [ # # ]: 0 : } else if (os_strcmp(entry.key, "SsidPostfix") == 0) {
952 : : char *postfix;
953 : :
954 [ # # ]: 0 : if (entry.type != DBUS_TYPE_STRING)
955 : 0 : goto error;
956 : :
957 : 0 : postfix = os_strdup(entry.str_value);
958 [ # # ]: 0 : if (!postfix)
959 : 0 : goto err_no_mem_clear;
960 : :
961 : 0 : os_free(wpa_s->conf->p2p_ssid_postfix);
962 : 0 : wpa_s->conf->p2p_ssid_postfix = postfix;
963 : :
964 : 0 : wpa_s->conf->changed_parameters |=
965 : : CFG_CHANGED_P2P_SSID_POSTFIX;
966 [ # # ][ # # ]: 0 : } else if ((os_strcmp(entry.key, "IntraBss") == 0) &&
967 : 0 : (entry.type == DBUS_TYPE_BOOLEAN)) {
968 : 0 : wpa_s->conf->p2p_intra_bss = entry.bool_value;
969 : 0 : wpa_s->conf->changed_parameters |=
970 : : CFG_CHANGED_P2P_INTRA_BSS;
971 [ # # ][ # # ]: 0 : } else if ((os_strcmp(entry.key, "GroupIdle") == 0) &&
972 : 0 : (entry.type == DBUS_TYPE_UINT32))
973 : 0 : wpa_s->conf->p2p_group_idle = entry.uint32_value;
974 [ # # ][ # # ]: 0 : else if (os_strcmp(entry.key, "disassoc_low_ack") == 0 &&
975 : 0 : entry.type == DBUS_TYPE_UINT32)
976 : 0 : wpa_s->conf->disassoc_low_ack = entry.uint32_value;
977 : : else
978 : : goto error;
979 : :
980 : 0 : wpa_dbus_dict_entry_clear(&entry);
981 : : }
982 : :
983 [ # # ]: 0 : if (wpa_s->conf->changed_parameters) {
984 : : /* Some changed parameters requires to update config*/
985 : 0 : wpa_supplicant_update_config(wpa_s);
986 : : }
987 : :
988 : 0 : return TRUE;
989 : :
990 : : error:
991 : 0 : dbus_set_error_const(error, DBUS_ERROR_INVALID_ARGS,
992 : : "invalid message format");
993 : 0 : wpa_dbus_dict_entry_clear(&entry);
994 : 0 : return FALSE;
995 : :
996 : : err_no_mem_clear:
997 : 0 : dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
998 : 0 : wpa_dbus_dict_entry_clear(&entry);
999 : 0 : return FALSE;
1000 : : }
1001 : :
1002 : :
1003 : 0 : dbus_bool_t wpas_dbus_getter_p2p_peers(DBusMessageIter *iter, DBusError *error,
1004 : : void *user_data)
1005 : : {
1006 : 0 : struct wpa_supplicant *wpa_s = user_data;
1007 : 0 : struct p2p_data *p2p = wpa_s->global->p2p;
1008 : 0 : int next = 0, i = 0;
1009 : 0 : int num = 0, out_of_mem = 0;
1010 : : const u8 *addr;
1011 : 0 : const struct p2p_peer_info *peer_info = NULL;
1012 : 0 : dbus_bool_t success = FALSE;
1013 : :
1014 : : struct dl_list peer_objpath_list;
1015 : : struct peer_objpath_node {
1016 : : struct dl_list list;
1017 : : char path[WPAS_DBUS_OBJECT_PATH_MAX];
1018 : : } *node, *tmp;
1019 : :
1020 : 0 : char **peer_obj_paths = NULL;
1021 : :
1022 [ # # ]: 0 : if (!wpa_dbus_p2p_check_enabled(wpa_s, NULL, NULL, error))
1023 : 0 : return FALSE;
1024 : :
1025 : 0 : dl_list_init(&peer_objpath_list);
1026 : :
1027 : : /* Get the first peer info */
1028 : 0 : peer_info = p2p_get_peer_found(p2p, NULL, next);
1029 : :
1030 : : /* Get next and accumulate them */
1031 : 0 : next = 1;
1032 [ # # ]: 0 : while (peer_info != NULL) {
1033 : 0 : node = os_zalloc(sizeof(struct peer_objpath_node));
1034 [ # # ]: 0 : if (!node) {
1035 : 0 : out_of_mem = 1;
1036 : 0 : goto error;
1037 : : }
1038 : :
1039 : 0 : addr = peer_info->p2p_device_addr;
1040 : 0 : os_snprintf(node->path, WPAS_DBUS_OBJECT_PATH_MAX,
1041 : : "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART
1042 : : "/" COMPACT_MACSTR,
1043 : 0 : wpa_s->dbus_new_path, MAC2STR(addr));
1044 : 0 : dl_list_add_tail(&peer_objpath_list, &node->list);
1045 : 0 : num++;
1046 : :
1047 : 0 : peer_info = p2p_get_peer_found(p2p, addr, next);
1048 : : }
1049 : :
1050 : : /*
1051 : : * Now construct the peer object paths in a form suitable for
1052 : : * array_property_getter helper below.
1053 : : */
1054 : 0 : peer_obj_paths = os_calloc(num, sizeof(char *));
1055 : :
1056 [ # # ]: 0 : if (!peer_obj_paths) {
1057 : 0 : out_of_mem = 1;
1058 : 0 : goto error;
1059 : : }
1060 : :
1061 [ # # ]: 0 : dl_list_for_each_safe(node, tmp, &peer_objpath_list,
1062 : : struct peer_objpath_node, list)
1063 : 0 : peer_obj_paths[i++] = node->path;
1064 : :
1065 : 0 : success = wpas_dbus_simple_array_property_getter(iter,
1066 : : DBUS_TYPE_OBJECT_PATH,
1067 : : peer_obj_paths, num,
1068 : : error);
1069 : :
1070 : : error:
1071 [ # # ]: 0 : if (peer_obj_paths)
1072 : 0 : os_free(peer_obj_paths);
1073 : :
1074 [ # # ]: 0 : dl_list_for_each_safe(node, tmp, &peer_objpath_list,
1075 : : struct peer_objpath_node, list) {
1076 : 0 : dl_list_del(&node->list);
1077 : 0 : os_free(node);
1078 : : }
1079 [ # # ]: 0 : if (out_of_mem)
1080 : 0 : dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
1081 : :
1082 : 0 : return success;
1083 : : }
1084 : :
1085 : :
1086 : : enum wpas_p2p_role {
1087 : : WPAS_P2P_ROLE_DEVICE,
1088 : : WPAS_P2P_ROLE_GO,
1089 : : WPAS_P2P_ROLE_CLIENT,
1090 : : };
1091 : :
1092 : 0 : static enum wpas_p2p_role wpas_get_p2p_role(struct wpa_supplicant *wpa_s)
1093 : : {
1094 : 0 : struct wpa_ssid *ssid = wpa_s->current_ssid;
1095 : :
1096 [ # # ]: 0 : if (!ssid)
1097 : 0 : return WPAS_P2P_ROLE_DEVICE;
1098 [ # # ]: 0 : if (wpa_s->wpa_state != WPA_COMPLETED)
1099 : 0 : return WPAS_P2P_ROLE_DEVICE;
1100 : :
1101 [ # # # ]: 0 : switch (ssid->mode) {
1102 : : case WPAS_MODE_P2P_GO:
1103 : : case WPAS_MODE_P2P_GROUP_FORMATION:
1104 : 0 : return WPAS_P2P_ROLE_GO;
1105 : : case WPAS_MODE_INFRA:
1106 [ # # ]: 0 : if (ssid->p2p_group)
1107 : 0 : return WPAS_P2P_ROLE_CLIENT;
1108 : 0 : return WPAS_P2P_ROLE_DEVICE;
1109 : : default:
1110 : 0 : return WPAS_P2P_ROLE_DEVICE;
1111 : : }
1112 : : }
1113 : :
1114 : :
1115 : 0 : dbus_bool_t wpas_dbus_getter_p2p_role(DBusMessageIter *iter, DBusError *error,
1116 : : void *user_data)
1117 : : {
1118 : 0 : struct wpa_supplicant *wpa_s = user_data;
1119 : : char *str;
1120 : :
1121 [ # # # ]: 0 : switch (wpas_get_p2p_role(wpa_s)) {
1122 : : case WPAS_P2P_ROLE_GO:
1123 : 0 : str = "GO";
1124 : 0 : break;
1125 : : case WPAS_P2P_ROLE_CLIENT:
1126 : 0 : str = "client";
1127 : 0 : break;
1128 : : default:
1129 : 0 : str = "device";
1130 : : }
1131 : :
1132 : 0 : return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING, &str,
1133 : : error);
1134 : : }
1135 : :
1136 : :
1137 : 0 : dbus_bool_t wpas_dbus_getter_p2p_group(DBusMessageIter *iter, DBusError *error,
1138 : : void *user_data)
1139 : : {
1140 : 0 : struct wpa_supplicant *wpa_s = user_data;
1141 : : char path_buf[WPAS_DBUS_OBJECT_PATH_MAX];
1142 : 0 : char *dbus_groupobj_path = path_buf;
1143 : :
1144 [ # # ]: 0 : if (wpa_s->dbus_groupobj_path == NULL)
1145 : 0 : os_snprintf(dbus_groupobj_path, WPAS_DBUS_OBJECT_PATH_MAX,
1146 : : "/");
1147 : : else
1148 : 0 : os_snprintf(dbus_groupobj_path, WPAS_DBUS_OBJECT_PATH_MAX,
1149 : : "%s", wpa_s->dbus_groupobj_path);
1150 : :
1151 : 0 : return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_OBJECT_PATH,
1152 : : &dbus_groupobj_path, error);
1153 : : }
1154 : :
1155 : :
1156 : 0 : dbus_bool_t wpas_dbus_getter_p2p_peergo(DBusMessageIter *iter,
1157 : : DBusError *error, void *user_data)
1158 : : {
1159 : 0 : struct wpa_supplicant *wpa_s = user_data;
1160 : : char go_peer_obj_path[WPAS_DBUS_OBJECT_PATH_MAX], *path;
1161 : :
1162 [ # # ]: 0 : if (wpas_get_p2p_role(wpa_s) != WPAS_P2P_ROLE_CLIENT)
1163 : 0 : os_snprintf(go_peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX, "/");
1164 : : else
1165 : 0 : os_snprintf(go_peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
1166 : : "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART "/"
1167 : : COMPACT_MACSTR,
1168 : 0 : wpa_s->dbus_new_path, MAC2STR(wpa_s->go_dev_addr));
1169 : :
1170 : 0 : path = go_peer_obj_path;
1171 : 0 : return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_OBJECT_PATH,
1172 : : &path, error);
1173 : : }
1174 : :
1175 : :
1176 : : /*
1177 : : * Peer object properties accessor methods
1178 : : */
1179 : :
1180 : 0 : dbus_bool_t wpas_dbus_getter_p2p_peer_device_name(DBusMessageIter *iter,
1181 : : DBusError *error,
1182 : : void *user_data)
1183 : : {
1184 : 0 : struct peer_handler_args *peer_args = user_data;
1185 : : const struct p2p_peer_info *info;
1186 : : char *tmp;
1187 : :
1188 [ # # ]: 0 : if (!wpa_dbus_p2p_check_enabled(peer_args->wpa_s, NULL, NULL, error))
1189 : 0 : return FALSE;
1190 : :
1191 : : /* get the peer info */
1192 : 0 : info = p2p_get_peer_found(peer_args->wpa_s->global->p2p,
1193 : 0 : peer_args->p2p_device_addr, 0);
1194 [ # # ]: 0 : if (info == NULL) {
1195 : 0 : dbus_set_error(error, DBUS_ERROR_FAILED,
1196 : : "failed to find peer");
1197 : 0 : return FALSE;
1198 : : }
1199 : :
1200 : 0 : tmp = os_strdup(info->device_name);
1201 [ # # ]: 0 : if (!tmp) {
1202 : 0 : dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
1203 : 0 : return FALSE;
1204 : : }
1205 : :
1206 [ # # ]: 0 : if (!wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING, &tmp,
1207 : : error)) {
1208 : 0 : dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
1209 : 0 : os_free(tmp);
1210 : 0 : return FALSE;
1211 : : }
1212 : :
1213 : 0 : os_free(tmp);
1214 : 0 : return TRUE;
1215 : : }
1216 : :
1217 : :
1218 : 0 : dbus_bool_t wpas_dbus_getter_p2p_peer_primary_device_type(
1219 : : DBusMessageIter *iter, DBusError *error, void *user_data)
1220 : : {
1221 : 0 : struct peer_handler_args *peer_args = user_data;
1222 : : const struct p2p_peer_info *info;
1223 : :
1224 : 0 : info = p2p_get_peer_found(peer_args->wpa_s->global->p2p,
1225 : 0 : peer_args->p2p_device_addr, 0);
1226 [ # # ]: 0 : if (info == NULL) {
1227 : 0 : dbus_set_error(error, DBUS_ERROR_FAILED,
1228 : : "failed to find peer");
1229 : 0 : return FALSE;
1230 : : }
1231 : :
1232 [ # # ]: 0 : if (!wpas_dbus_simple_array_property_getter(iter, DBUS_TYPE_BYTE,
1233 : : (char *)
1234 : 0 : info->pri_dev_type,
1235 : : WPS_DEV_TYPE_LEN, error)) {
1236 : 0 : dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
1237 : 0 : return FALSE;
1238 : : }
1239 : :
1240 : 0 : return TRUE;
1241 : : }
1242 : :
1243 : :
1244 : 0 : dbus_bool_t wpas_dbus_getter_p2p_peer_config_method(DBusMessageIter *iter,
1245 : : DBusError *error,
1246 : : void *user_data)
1247 : : {
1248 : 0 : struct peer_handler_args *peer_args = user_data;
1249 : : const struct p2p_peer_info *info;
1250 : :
1251 : 0 : info = p2p_get_peer_found(peer_args->wpa_s->global->p2p,
1252 : 0 : peer_args->p2p_device_addr, 0);
1253 [ # # ]: 0 : if (info == NULL) {
1254 : 0 : dbus_set_error(error, DBUS_ERROR_FAILED,
1255 : : "failed to find peer");
1256 : 0 : return FALSE;
1257 : : }
1258 : :
1259 [ # # ]: 0 : if (!wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT16,
1260 : 0 : &info->config_methods, error)) {
1261 : 0 : dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
1262 : 0 : return FALSE;
1263 : : }
1264 : :
1265 : 0 : return TRUE;
1266 : : }
1267 : :
1268 : :
1269 : 0 : dbus_bool_t wpas_dbus_getter_p2p_peer_level(DBusMessageIter *iter,
1270 : : DBusError *error,
1271 : : void *user_data)
1272 : : {
1273 : 0 : struct peer_handler_args *peer_args = user_data;
1274 : : const struct p2p_peer_info *info;
1275 : :
1276 : 0 : info = p2p_get_peer_found(peer_args->wpa_s->global->p2p,
1277 : 0 : peer_args->p2p_device_addr, 0);
1278 [ # # ]: 0 : if (info == NULL) {
1279 : 0 : dbus_set_error(error, DBUS_ERROR_FAILED,
1280 : : "failed to find peer");
1281 : 0 : return FALSE;
1282 : : }
1283 : :
1284 [ # # ]: 0 : if (!wpas_dbus_simple_property_getter(iter, DBUS_TYPE_INT32,
1285 : 0 : &info->level, error)) {
1286 : 0 : dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
1287 : 0 : return FALSE;
1288 : : }
1289 : :
1290 : 0 : return TRUE;
1291 : : }
1292 : :
1293 : :
1294 : 0 : dbus_bool_t wpas_dbus_getter_p2p_peer_device_capability(DBusMessageIter *iter,
1295 : : DBusError *error,
1296 : : void *user_data)
1297 : : {
1298 : 0 : struct peer_handler_args *peer_args = user_data;
1299 : : const struct p2p_peer_info *info;
1300 : :
1301 : 0 : info = p2p_get_peer_found(peer_args->wpa_s->global->p2p,
1302 : 0 : peer_args->p2p_device_addr, 0);
1303 [ # # ]: 0 : if (info == NULL) {
1304 : 0 : dbus_set_error(error, DBUS_ERROR_FAILED,
1305 : : "failed to find peer");
1306 : 0 : return FALSE;
1307 : : }
1308 : :
1309 [ # # ]: 0 : if (!wpas_dbus_simple_property_getter(iter, DBUS_TYPE_BYTE,
1310 : 0 : &info->dev_capab, error)) {
1311 : 0 : dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
1312 : 0 : return FALSE;
1313 : : }
1314 : :
1315 : 0 : return TRUE;
1316 : : }
1317 : :
1318 : :
1319 : 0 : dbus_bool_t wpas_dbus_getter_p2p_peer_group_capability(DBusMessageIter *iter,
1320 : : DBusError *error,
1321 : : void *user_data)
1322 : : {
1323 : 0 : struct peer_handler_args *peer_args = user_data;
1324 : : const struct p2p_peer_info *info;
1325 : :
1326 : 0 : info = p2p_get_peer_found(peer_args->wpa_s->global->p2p,
1327 : 0 : peer_args->p2p_device_addr, 0);
1328 [ # # ]: 0 : if (info == NULL) {
1329 : 0 : dbus_set_error(error, DBUS_ERROR_FAILED,
1330 : : "failed to find peer");
1331 : 0 : return FALSE;
1332 : : }
1333 : :
1334 [ # # ]: 0 : if (!wpas_dbus_simple_property_getter(iter, DBUS_TYPE_BYTE,
1335 : 0 : &info->group_capab, error)) {
1336 : 0 : dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
1337 : 0 : return FALSE;
1338 : : }
1339 : :
1340 : 0 : return TRUE;
1341 : : }
1342 : :
1343 : :
1344 : 0 : dbus_bool_t wpas_dbus_getter_p2p_peer_secondary_device_types(
1345 : : DBusMessageIter *iter, DBusError *error, void *user_data)
1346 : : {
1347 : 0 : struct peer_handler_args *peer_args = user_data;
1348 : : const struct p2p_peer_info *info;
1349 : : DBusMessageIter variant_iter, array_iter;
1350 : :
1351 : 0 : info = p2p_get_peer_found(peer_args->wpa_s->global->p2p,
1352 : 0 : peer_args->p2p_device_addr, 0);
1353 [ # # ]: 0 : if (info == NULL) {
1354 : 0 : dbus_set_error(error, DBUS_ERROR_FAILED,
1355 : : "failed to find peer");
1356 : 0 : return FALSE;
1357 : : }
1358 : :
1359 [ # # ]: 0 : if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT,
1360 : : DBUS_TYPE_ARRAY_AS_STRING
1361 : : DBUS_TYPE_ARRAY_AS_STRING
1362 : : DBUS_TYPE_BYTE_AS_STRING,
1363 : : &variant_iter)) {
1364 : 0 : dbus_set_error(error, DBUS_ERROR_FAILED,
1365 : : "%s: failed to construct message 1", __func__);
1366 : 0 : return FALSE;
1367 : : }
1368 : :
1369 [ # # ]: 0 : if (!dbus_message_iter_open_container(&variant_iter, DBUS_TYPE_ARRAY,
1370 : : DBUS_TYPE_ARRAY_AS_STRING
1371 : : DBUS_TYPE_BYTE_AS_STRING,
1372 : : &array_iter)) {
1373 : 0 : dbus_set_error(error, DBUS_ERROR_FAILED,
1374 : : "%s: failed to construct message 2", __func__);
1375 : 0 : return FALSE;
1376 : : }
1377 : :
1378 [ # # ]: 0 : if (info->wps_sec_dev_type_list_len) {
1379 : 0 : const u8 *sec_dev_type_list = info->wps_sec_dev_type_list;
1380 : 0 : int num_sec_device_types =
1381 : 0 : info->wps_sec_dev_type_list_len / WPS_DEV_TYPE_LEN;
1382 : : int i;
1383 : : DBusMessageIter inner_array_iter;
1384 : :
1385 [ # # ]: 0 : for (i = 0; i < num_sec_device_types; i++) {
1386 [ # # ]: 0 : if (!dbus_message_iter_open_container(
1387 : : &array_iter, DBUS_TYPE_ARRAY,
1388 : : DBUS_TYPE_BYTE_AS_STRING,
1389 : : &inner_array_iter)) {
1390 : 0 : dbus_set_error(error, DBUS_ERROR_FAILED,
1391 : : "%s: failed to construct "
1392 : : "message 3 (%d)",
1393 : : __func__, i);
1394 : 0 : return FALSE;
1395 : : }
1396 : :
1397 [ # # ]: 0 : if (!dbus_message_iter_append_fixed_array(
1398 : : &inner_array_iter, DBUS_TYPE_BYTE,
1399 : : &sec_dev_type_list, WPS_DEV_TYPE_LEN)) {
1400 : 0 : dbus_set_error(error, DBUS_ERROR_FAILED,
1401 : : "%s: failed to construct "
1402 : : "message 4 (%d)",
1403 : : __func__, i);
1404 : 0 : return FALSE;
1405 : : }
1406 : :
1407 [ # # ]: 0 : if (!dbus_message_iter_close_container(
1408 : : &array_iter, &inner_array_iter)) {
1409 : 0 : dbus_set_error(error, DBUS_ERROR_FAILED,
1410 : : "%s: failed to construct "
1411 : : "message 5 (%d)",
1412 : : __func__, i);
1413 : 0 : return FALSE;
1414 : : }
1415 : :
1416 : 0 : sec_dev_type_list += WPS_DEV_TYPE_LEN;
1417 : : }
1418 : : }
1419 : :
1420 [ # # ]: 0 : if (!dbus_message_iter_close_container(&variant_iter, &array_iter)) {
1421 : 0 : dbus_set_error(error, DBUS_ERROR_FAILED,
1422 : : "%s: failed to construct message 6", __func__);
1423 : 0 : return FALSE;
1424 : : }
1425 : :
1426 [ # # ]: 0 : if (!dbus_message_iter_close_container(iter, &variant_iter)) {
1427 : 0 : dbus_set_error(error, DBUS_ERROR_FAILED,
1428 : : "%s: failed to construct message 7", __func__);
1429 : 0 : return FALSE;
1430 : : }
1431 : :
1432 : 0 : return TRUE;
1433 : : }
1434 : :
1435 : :
1436 : 0 : dbus_bool_t wpas_dbus_getter_p2p_peer_vendor_extension(DBusMessageIter *iter,
1437 : : DBusError *error,
1438 : : void *user_data)
1439 : : {
1440 : : struct wpabuf *vendor_extension[P2P_MAX_WPS_VENDOR_EXT];
1441 : : int i, num;
1442 : 0 : struct peer_handler_args *peer_args = user_data;
1443 : : const struct p2p_peer_info *info;
1444 : :
1445 : 0 : info = p2p_get_peer_found(peer_args->wpa_s->global->p2p,
1446 : 0 : peer_args->p2p_device_addr, 0);
1447 [ # # ]: 0 : if (info == NULL) {
1448 : 0 : dbus_set_error(error, DBUS_ERROR_FAILED,
1449 : : "failed to find peer");
1450 : 0 : return FALSE;
1451 : : }
1452 : :
1453 : : /* Add WPS vendor extensions attribute */
1454 [ # # ]: 0 : for (i = 0, num = 0; i < P2P_MAX_WPS_VENDOR_EXT; i++) {
1455 [ # # ]: 0 : if (info->wps_vendor_ext[i] == NULL)
1456 : 0 : continue;
1457 : 0 : vendor_extension[num] = info->wps_vendor_ext[i];
1458 : 0 : num++;
1459 : : }
1460 : :
1461 [ # # ]: 0 : if (!wpas_dbus_simple_array_array_property_getter(iter, DBUS_TYPE_BYTE,
1462 : : vendor_extension,
1463 : : num, error))
1464 : 0 : return FALSE;
1465 : :
1466 : 0 : return TRUE;
1467 : : }
1468 : :
1469 : :
1470 : 0 : dbus_bool_t wpas_dbus_getter_p2p_peer_ies(DBusMessageIter *iter,
1471 : : DBusError *error, void *user_data)
1472 : : {
1473 : : dbus_bool_t success;
1474 : : /* struct peer_handler_args *peer_args = user_data; */
1475 : :
1476 : 0 : success = wpas_dbus_simple_array_property_getter(iter, DBUS_TYPE_BYTE,
1477 : : NULL, 0, error);
1478 : 0 : return success;
1479 : : }
1480 : :
1481 : :
1482 : : /**
1483 : : * wpas_dbus_getter_persistent_groups - Get array of persistent group objects
1484 : : * @iter: Pointer to incoming dbus message iter
1485 : : * @error: Location to store error on failure
1486 : : * @user_data: Function specific data
1487 : : * Returns: TRUE on success, FALSE on failure
1488 : : *
1489 : : * Getter for "PersistentGroups" property.
1490 : : */
1491 : 0 : dbus_bool_t wpas_dbus_getter_persistent_groups(DBusMessageIter *iter,
1492 : : DBusError *error,
1493 : : void *user_data)
1494 : : {
1495 : 0 : struct wpa_supplicant *wpa_s = user_data;
1496 : : struct wpa_ssid *ssid;
1497 : : char **paths;
1498 : 0 : unsigned int i = 0, num = 0;
1499 : 0 : dbus_bool_t success = FALSE;
1500 : :
1501 [ # # ]: 0 : if (wpa_s->conf == NULL) {
1502 : 0 : wpa_printf(MSG_ERROR, "dbus: %s: "
1503 : : "An error occurred getting persistent groups list",
1504 : : __func__);
1505 : 0 : dbus_set_error_const(error, DBUS_ERROR_FAILED, "an error "
1506 : : "occurred getting persistent groups list");
1507 : 0 : return FALSE;
1508 : : }
1509 : :
1510 [ # # ]: 0 : for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
1511 [ # # ]: 0 : if (network_is_persistent_group(ssid))
1512 : 0 : num++;
1513 : :
1514 : 0 : paths = os_calloc(num, sizeof(char *));
1515 [ # # ]: 0 : if (!paths) {
1516 : 0 : dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
1517 : 0 : return FALSE;
1518 : : }
1519 : :
1520 : : /* Loop through configured networks and append object path of each */
1521 [ # # ]: 0 : for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
1522 [ # # ]: 0 : if (!network_is_persistent_group(ssid))
1523 : 0 : continue;
1524 : 0 : paths[i] = os_zalloc(WPAS_DBUS_OBJECT_PATH_MAX);
1525 [ # # ]: 0 : if (paths[i] == NULL) {
1526 : 0 : dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY,
1527 : : "no memory");
1528 : 0 : goto out;
1529 : : }
1530 : : /* Construct the object path for this network. */
1531 : 0 : os_snprintf(paths[i++], WPAS_DBUS_OBJECT_PATH_MAX,
1532 : : "%s/" WPAS_DBUS_NEW_PERSISTENT_GROUPS_PART "/%d",
1533 : : wpa_s->dbus_new_path, ssid->id);
1534 : : }
1535 : :
1536 : 0 : success = wpas_dbus_simple_array_property_getter(iter,
1537 : : DBUS_TYPE_OBJECT_PATH,
1538 : : paths, num, error);
1539 : :
1540 : : out:
1541 [ # # ]: 0 : while (i)
1542 : 0 : os_free(paths[--i]);
1543 : 0 : os_free(paths);
1544 : 0 : return success;
1545 : : }
1546 : :
1547 : :
1548 : : /**
1549 : : * wpas_dbus_getter_persistent_group_properties - Get options for a persistent
1550 : : * group
1551 : : * @iter: Pointer to incoming dbus message iter
1552 : : * @error: Location to store error on failure
1553 : : * @user_data: Function specific data
1554 : : * Returns: TRUE on success, FALSE on failure
1555 : : *
1556 : : * Getter for "Properties" property of a persistent group.
1557 : : */
1558 : 0 : dbus_bool_t wpas_dbus_getter_persistent_group_properties(DBusMessageIter *iter,
1559 : : DBusError *error,
1560 : : void *user_data)
1561 : : {
1562 : 0 : struct network_handler_args *net = user_data;
1563 : :
1564 : : /* Leveraging the fact that persistent group object is still
1565 : : * represented in same manner as network within.
1566 : : */
1567 : 0 : return wpas_dbus_getter_network_properties(iter, error, net);
1568 : : }
1569 : :
1570 : :
1571 : : /**
1572 : : * wpas_dbus_setter_persistent_group_properties - Get options for a persistent
1573 : : * group
1574 : : * @iter: Pointer to incoming dbus message iter
1575 : : * @error: Location to store error on failure
1576 : : * @user_data: Function specific data
1577 : : * Returns: TRUE on success, FALSE on failure
1578 : : *
1579 : : * Setter for "Properties" property of a persistent group.
1580 : : */
1581 : 0 : dbus_bool_t wpas_dbus_setter_persistent_group_properties(DBusMessageIter *iter,
1582 : : DBusError *error,
1583 : : void *user_data)
1584 : : {
1585 : 0 : struct network_handler_args *net = user_data;
1586 : 0 : struct wpa_ssid *ssid = net->ssid;
1587 : : DBusMessageIter variant_iter;
1588 : :
1589 : : /*
1590 : : * Leveraging the fact that persistent group object is still
1591 : : * represented in same manner as network within.
1592 : : */
1593 : 0 : dbus_message_iter_recurse(iter, &variant_iter);
1594 : 0 : return set_network_properties(net->wpa_s, ssid, &variant_iter, error);
1595 : : }
1596 : :
1597 : :
1598 : : /**
1599 : : * wpas_dbus_new_iface_add_persistent_group - Add a new configured
1600 : : * persistent_group
1601 : : * @message: Pointer to incoming dbus message
1602 : : * @wpa_s: wpa_supplicant structure for a network interface
1603 : : * Returns: A dbus message containing the object path of the new
1604 : : * persistent group
1605 : : *
1606 : : * Handler function for "AddPersistentGroup" method call of a P2P Device
1607 : : * interface.
1608 : : */
1609 : 0 : DBusMessage * wpas_dbus_handler_add_persistent_group(
1610 : : DBusMessage *message, struct wpa_supplicant *wpa_s)
1611 : : {
1612 : 0 : DBusMessage *reply = NULL;
1613 : : DBusMessageIter iter;
1614 : 0 : struct wpa_ssid *ssid = NULL;
1615 : 0 : char path_buf[WPAS_DBUS_OBJECT_PATH_MAX], *path = path_buf;
1616 : : DBusError error;
1617 : :
1618 : 0 : dbus_message_iter_init(message, &iter);
1619 : :
1620 : 0 : ssid = wpa_config_add_network(wpa_s->conf);
1621 [ # # ]: 0 : if (ssid == NULL) {
1622 : 0 : wpa_printf(MSG_ERROR, "dbus: %s: "
1623 : : "Cannot add new persistent group", __func__);
1624 : 0 : reply = wpas_dbus_error_unknown_error(
1625 : : message,
1626 : : "wpa_supplicant could not add "
1627 : : "a persistent group on this interface.");
1628 : 0 : goto err;
1629 : : }
1630 : :
1631 : : /* Mark the ssid as being a persistent group before the notification */
1632 : 0 : ssid->disabled = 2;
1633 : 0 : ssid->p2p_persistent_group = 1;
1634 : 0 : wpas_notify_persistent_group_added(wpa_s, ssid);
1635 : :
1636 : 0 : wpa_config_set_network_defaults(ssid);
1637 : :
1638 : 0 : dbus_error_init(&error);
1639 [ # # ]: 0 : if (!set_network_properties(wpa_s, ssid, &iter, &error)) {
1640 : 0 : wpa_printf(MSG_DEBUG, "dbus: %s: "
1641 : : "Control interface could not set persistent group "
1642 : : "properties", __func__);
1643 : 0 : reply = wpas_dbus_reply_new_from_error(message, &error,
1644 : : DBUS_ERROR_INVALID_ARGS,
1645 : : "Failed to set network "
1646 : : "properties");
1647 : 0 : dbus_error_free(&error);
1648 : 0 : goto err;
1649 : : }
1650 : :
1651 : : /* Construct the object path for this network. */
1652 : 0 : os_snprintf(path, WPAS_DBUS_OBJECT_PATH_MAX,
1653 : : "%s/" WPAS_DBUS_NEW_PERSISTENT_GROUPS_PART "/%d",
1654 : : wpa_s->dbus_new_path, ssid->id);
1655 : :
1656 : 0 : reply = dbus_message_new_method_return(message);
1657 [ # # ]: 0 : if (reply == NULL) {
1658 : 0 : reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
1659 : : NULL);
1660 : 0 : goto err;
1661 : : }
1662 [ # # ]: 0 : if (!dbus_message_append_args(reply, DBUS_TYPE_OBJECT_PATH, &path,
1663 : : DBUS_TYPE_INVALID)) {
1664 : 0 : dbus_message_unref(reply);
1665 : 0 : reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
1666 : : NULL);
1667 : 0 : goto err;
1668 : : }
1669 : :
1670 : 0 : return reply;
1671 : :
1672 : : err:
1673 [ # # ]: 0 : if (ssid) {
1674 : 0 : wpas_notify_persistent_group_removed(wpa_s, ssid);
1675 : 0 : wpa_config_remove_network(wpa_s->conf, ssid->id);
1676 : : }
1677 : 0 : return reply;
1678 : : }
1679 : :
1680 : :
1681 : : /**
1682 : : * wpas_dbus_handler_remove_persistent_group - Remove a configured persistent
1683 : : * group
1684 : : * @message: Pointer to incoming dbus message
1685 : : * @wpa_s: wpa_supplicant structure for a network interface
1686 : : * Returns: NULL on success or dbus error on failure
1687 : : *
1688 : : * Handler function for "RemovePersistentGroup" method call of a P2P Device
1689 : : * interface.
1690 : : */
1691 : 0 : DBusMessage * wpas_dbus_handler_remove_persistent_group(
1692 : : DBusMessage *message, struct wpa_supplicant *wpa_s)
1693 : : {
1694 : 0 : DBusMessage *reply = NULL;
1695 : : const char *op;
1696 : 0 : char *iface = NULL, *persistent_group_id = NULL;
1697 : : int id;
1698 : : struct wpa_ssid *ssid;
1699 : :
1700 : 0 : dbus_message_get_args(message, NULL, DBUS_TYPE_OBJECT_PATH, &op,
1701 : : DBUS_TYPE_INVALID);
1702 : :
1703 : : /*
1704 : : * Extract the network ID and ensure the network is actually a child of
1705 : : * this interface.
1706 : : */
1707 : 0 : iface = wpas_dbus_new_decompose_object_path(op, 1,
1708 : : &persistent_group_id,
1709 : : NULL);
1710 [ # # ][ # # ]: 0 : if (iface == NULL || os_strcmp(iface, wpa_s->dbus_new_path) != 0) {
1711 : 0 : reply = wpas_dbus_error_invalid_args(message, op);
1712 : 0 : goto out;
1713 : : }
1714 : :
1715 : 0 : id = strtoul(persistent_group_id, NULL, 10);
1716 [ # # ]: 0 : if (errno == EINVAL) {
1717 : 0 : reply = wpas_dbus_error_invalid_args(message, op);
1718 : 0 : goto out;
1719 : : }
1720 : :
1721 : 0 : ssid = wpa_config_get_network(wpa_s->conf, id);
1722 [ # # ]: 0 : if (ssid == NULL) {
1723 : 0 : reply = wpas_dbus_error_persistent_group_unknown(message);
1724 : 0 : goto out;
1725 : : }
1726 : :
1727 : 0 : wpas_notify_persistent_group_removed(wpa_s, ssid);
1728 : :
1729 [ # # ]: 0 : if (wpa_config_remove_network(wpa_s->conf, id) < 0) {
1730 : 0 : wpa_printf(MSG_ERROR, "dbus: %s: "
1731 : : "error occurred when removing persistent group %d",
1732 : : __func__, id);
1733 : 0 : reply = wpas_dbus_error_unknown_error(
1734 : : message,
1735 : : "error removing the specified persistent group on "
1736 : : "this interface.");
1737 : 0 : goto out;
1738 : : }
1739 : :
1740 : : out:
1741 : 0 : os_free(iface);
1742 : 0 : os_free(persistent_group_id);
1743 : 0 : return reply;
1744 : : }
1745 : :
1746 : :
1747 : 0 : static void remove_persistent_group(struct wpa_supplicant *wpa_s,
1748 : : struct wpa_ssid *ssid)
1749 : : {
1750 : 0 : wpas_notify_persistent_group_removed(wpa_s, ssid);
1751 : :
1752 [ # # ]: 0 : if (wpa_config_remove_network(wpa_s->conf, ssid->id) < 0) {
1753 : 0 : wpa_printf(MSG_ERROR, "dbus: %s: "
1754 : : "error occurred when removing persistent group %d",
1755 : : __func__, ssid->id);
1756 : 0 : return;
1757 : : }
1758 : : }
1759 : :
1760 : :
1761 : : /**
1762 : : * wpas_dbus_handler_remove_all_persistent_groups - Remove all configured
1763 : : * persistent groups
1764 : : * @message: Pointer to incoming dbus message
1765 : : * @wpa_s: wpa_supplicant structure for a network interface
1766 : : * Returns: NULL on success or dbus error on failure
1767 : : *
1768 : : * Handler function for "RemoveAllPersistentGroups" method call of a
1769 : : * P2P Device interface.
1770 : : */
1771 : 0 : DBusMessage * wpas_dbus_handler_remove_all_persistent_groups(
1772 : : DBusMessage *message, struct wpa_supplicant *wpa_s)
1773 : : {
1774 : : struct wpa_ssid *ssid, *next;
1775 : : struct wpa_config *config;
1776 : :
1777 : 0 : config = wpa_s->conf;
1778 : 0 : ssid = config->ssid;
1779 [ # # ]: 0 : while (ssid) {
1780 : 0 : next = ssid->next;
1781 [ # # ]: 0 : if (network_is_persistent_group(ssid))
1782 : 0 : remove_persistent_group(wpa_s, ssid);
1783 : 0 : ssid = next;
1784 : : }
1785 : 0 : return NULL;
1786 : : }
1787 : :
1788 : :
1789 : : /*
1790 : : * Group object properties accessor methods
1791 : : */
1792 : :
1793 : 0 : dbus_bool_t wpas_dbus_getter_p2p_group_members(DBusMessageIter *iter,
1794 : : DBusError *error,
1795 : : void *user_data)
1796 : : {
1797 : 0 : struct wpa_supplicant *wpa_s = user_data;
1798 : : struct wpa_ssid *ssid;
1799 : : unsigned int num_members;
1800 : : char **paths;
1801 : : unsigned int i;
1802 : 0 : void *next = NULL;
1803 : : const u8 *addr;
1804 : 0 : dbus_bool_t success = FALSE;
1805 : :
1806 : : /* Verify correct role for this property */
1807 [ # # ]: 0 : if (wpas_get_p2p_role(wpa_s) != WPAS_P2P_ROLE_GO) {
1808 : 0 : return wpas_dbus_simple_array_property_getter(
1809 : : iter, DBUS_TYPE_OBJECT_PATH, NULL, 0, error);
1810 : : }
1811 : :
1812 : 0 : ssid = wpa_s->conf->ssid;
1813 : : /* At present WPAS P2P_GO mode only applicable for p2p_go */
1814 [ # # ][ # # ]: 0 : if (ssid->mode != WPAS_MODE_P2P_GO &&
1815 [ # # ]: 0 : ssid->mode != WPAS_MODE_AP &&
1816 : 0 : ssid->mode != WPAS_MODE_P2P_GROUP_FORMATION)
1817 : 0 : return FALSE;
1818 : :
1819 : 0 : num_members = p2p_get_group_num_members(wpa_s->p2p_group);
1820 : :
1821 : 0 : paths = os_calloc(num_members, sizeof(char *));
1822 [ # # ]: 0 : if (!paths)
1823 : 0 : goto out_of_memory;
1824 : :
1825 : 0 : i = 0;
1826 [ # # ]: 0 : while ((addr = p2p_iterate_group_members(wpa_s->p2p_group, &next))) {
1827 : 0 : paths[i] = os_zalloc(WPAS_DBUS_OBJECT_PATH_MAX);
1828 [ # # ]: 0 : if (!paths[i])
1829 : 0 : goto out_of_memory;
1830 : 0 : os_snprintf(paths[i], WPAS_DBUS_OBJECT_PATH_MAX,
1831 : : "%s/" WPAS_DBUS_NEW_P2P_GROUPMEMBERS_PART
1832 : : "/" COMPACT_MACSTR,
1833 : 0 : wpa_s->dbus_groupobj_path, MAC2STR(addr));
1834 : 0 : i++;
1835 : : }
1836 : :
1837 : 0 : success = wpas_dbus_simple_array_property_getter(iter,
1838 : : DBUS_TYPE_OBJECT_PATH,
1839 : : paths, num_members,
1840 : : error);
1841 : :
1842 [ # # ]: 0 : for (i = 0; i < num_members; i++)
1843 : 0 : os_free(paths[i]);
1844 : 0 : os_free(paths);
1845 : 0 : return success;
1846 : :
1847 : : out_of_memory:
1848 : 0 : dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
1849 [ # # ]: 0 : if (paths) {
1850 [ # # ]: 0 : for (i = 0; i < num_members; i++)
1851 : 0 : os_free(paths[i]);
1852 : 0 : os_free(paths);
1853 : : }
1854 : 0 : return FALSE;
1855 : : }
1856 : :
1857 : :
1858 : 0 : dbus_bool_t wpas_dbus_getter_p2p_group_ssid(DBusMessageIter *iter,
1859 : : DBusError *error, void *user_data)
1860 : : {
1861 : 0 : struct wpa_supplicant *wpa_s = user_data;
1862 [ # # ]: 0 : if (wpa_s->current_ssid == NULL)
1863 : 0 : return FALSE;
1864 : 0 : return wpas_dbus_simple_array_property_getter(
1865 : 0 : iter, DBUS_TYPE_BYTE, wpa_s->current_ssid->ssid,
1866 : 0 : wpa_s->current_ssid->ssid_len, error);
1867 : : }
1868 : :
1869 : :
1870 : 0 : dbus_bool_t wpas_dbus_getter_p2p_group_bssid(DBusMessageIter *iter,
1871 : : DBusError *error,
1872 : : void *user_data)
1873 : : {
1874 : 0 : struct wpa_supplicant *wpa_s = user_data;
1875 : 0 : u8 role = wpas_get_p2p_role(wpa_s);
1876 : : u8 *p_bssid;
1877 : :
1878 [ # # ]: 0 : if (role == WPAS_P2P_ROLE_CLIENT) {
1879 [ # # ]: 0 : if (wpa_s->current_ssid == NULL)
1880 : 0 : return FALSE;
1881 : 0 : p_bssid = wpa_s->current_ssid->bssid;
1882 : : } else {
1883 [ # # ]: 0 : if (wpa_s->ap_iface == NULL)
1884 : 0 : return FALSE;
1885 : 0 : p_bssid = wpa_s->ap_iface->bss[0]->own_addr;
1886 : : }
1887 : :
1888 : 0 : return wpas_dbus_simple_array_property_getter(iter, DBUS_TYPE_BYTE,
1889 : : p_bssid, ETH_ALEN,
1890 : : error);
1891 : : }
1892 : :
1893 : :
1894 : 0 : dbus_bool_t wpas_dbus_getter_p2p_group_frequency(DBusMessageIter *iter,
1895 : : DBusError *error,
1896 : : void *user_data)
1897 : : {
1898 : 0 : struct wpa_supplicant *wpa_s = user_data;
1899 : : u16 op_freq;
1900 : 0 : u8 role = wpas_get_p2p_role(wpa_s);
1901 : :
1902 [ # # ]: 0 : if (role == WPAS_P2P_ROLE_CLIENT) {
1903 [ # # ]: 0 : if (wpa_s->go_params == NULL)
1904 : 0 : return FALSE;
1905 : 0 : op_freq = wpa_s->go_params->freq;
1906 : : } else {
1907 [ # # ]: 0 : if (wpa_s->ap_iface == NULL)
1908 : 0 : return FALSE;
1909 : 0 : op_freq = wpa_s->ap_iface->freq;
1910 : : }
1911 : :
1912 : 0 : return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT16,
1913 : : &op_freq, error);
1914 : : }
1915 : :
1916 : :
1917 : 0 : dbus_bool_t wpas_dbus_getter_p2p_group_passphrase(DBusMessageIter *iter,
1918 : : DBusError *error,
1919 : : void *user_data)
1920 : : {
1921 : 0 : struct wpa_supplicant *wpa_s = user_data;
1922 : 0 : u8 role = wpas_get_p2p_role(wpa_s);
1923 : 0 : char *p_pass = NULL;
1924 : :
1925 : : /* Verify correct role for this property */
1926 [ # # ]: 0 : if (role == WPAS_P2P_ROLE_GO) {
1927 [ # # ]: 0 : if (wpa_s->current_ssid == NULL)
1928 : 0 : return FALSE;
1929 : 0 : p_pass = wpa_s->current_ssid->passphrase;
1930 : : } else
1931 : 0 : p_pass = "";
1932 : :
1933 : 0 : return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING,
1934 : : &p_pass, error);
1935 : :
1936 : : }
1937 : :
1938 : :
1939 : 0 : dbus_bool_t wpas_dbus_getter_p2p_group_psk(DBusMessageIter *iter,
1940 : : DBusError *error, void *user_data)
1941 : : {
1942 : 0 : struct wpa_supplicant *wpa_s = user_data;
1943 : 0 : u8 role = wpas_get_p2p_role(wpa_s);
1944 : 0 : u8 *p_psk = NULL;
1945 : 0 : u8 psk_len = 0;
1946 : :
1947 : : /* Verify correct role for this property */
1948 [ # # ]: 0 : if (role == WPAS_P2P_ROLE_CLIENT) {
1949 [ # # ]: 0 : if (wpa_s->current_ssid == NULL)
1950 : 0 : return FALSE;
1951 : 0 : p_psk = wpa_s->current_ssid->psk;
1952 : 0 : psk_len = 32;
1953 : : }
1954 : :
1955 : 0 : return wpas_dbus_simple_array_property_getter(iter, DBUS_TYPE_BYTE,
1956 : : &p_psk, psk_len, error);
1957 : : }
1958 : :
1959 : :
1960 : 0 : dbus_bool_t wpas_dbus_getter_p2p_group_vendor_ext(DBusMessageIter *iter,
1961 : : DBusError *error,
1962 : : void *user_data)
1963 : : {
1964 : 0 : struct wpa_supplicant *wpa_s = user_data;
1965 : : struct hostapd_data *hapd;
1966 : : struct wpabuf *vendor_ext[MAX_WPS_VENDOR_EXTENSIONS];
1967 : 0 : int num_vendor_ext = 0;
1968 : : int i;
1969 : :
1970 : : /* Verify correct role for this property */
1971 [ # # ]: 0 : if (wpas_get_p2p_role(wpa_s) == WPAS_P2P_ROLE_GO) {
1972 [ # # ]: 0 : if (wpa_s->ap_iface == NULL)
1973 : 0 : return FALSE;
1974 : 0 : hapd = wpa_s->ap_iface->bss[0];
1975 : :
1976 : : /* Parse WPS Vendor Extensions sent in Beacon/Probe Response */
1977 [ # # ]: 0 : for (i = 0; i < MAX_WPS_VENDOR_EXTENSIONS; i++) {
1978 [ # # ]: 0 : if (hapd->conf->wps_vendor_ext[i] == NULL)
1979 : 0 : vendor_ext[i] = NULL;
1980 : : else {
1981 : 0 : vendor_ext[num_vendor_ext++] =
1982 : 0 : hapd->conf->wps_vendor_ext[i];
1983 : : }
1984 : : }
1985 : : }
1986 : :
1987 : : /* Return vendor extensions or no data */
1988 : 0 : return wpas_dbus_simple_array_array_property_getter(iter,
1989 : : DBUS_TYPE_BYTE,
1990 : : vendor_ext,
1991 : : num_vendor_ext,
1992 : : error);
1993 : : }
1994 : :
1995 : :
1996 : 0 : dbus_bool_t wpas_dbus_setter_p2p_group_vendor_ext(DBusMessageIter *iter,
1997 : : DBusError *error,
1998 : : void *user_data)
1999 : : {
2000 : 0 : struct wpa_supplicant *wpa_s = user_data;
2001 : : DBusMessageIter variant_iter, iter_dict;
2002 : 0 : struct wpa_dbus_dict_entry entry = { .type = DBUS_TYPE_STRING };
2003 : : unsigned int i;
2004 : 0 : struct hostapd_data *hapd = NULL;
2005 : :
2006 [ # # ][ # # ]: 0 : if (wpas_get_p2p_role(wpa_s) == WPAS_P2P_ROLE_GO &&
2007 : 0 : wpa_s->ap_iface != NULL)
2008 : 0 : hapd = wpa_s->ap_iface->bss[0];
2009 : : else
2010 : 0 : return FALSE;
2011 : :
2012 : 0 : dbus_message_iter_recurse(iter, &variant_iter);
2013 [ # # ]: 0 : if (!wpa_dbus_dict_open_read(&variant_iter, &iter_dict, error))
2014 : 0 : return FALSE;
2015 : :
2016 [ # # ]: 0 : while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
2017 [ # # ]: 0 : if (!wpa_dbus_dict_get_entry(&iter_dict, &entry)) {
2018 : 0 : dbus_set_error_const(error, DBUS_ERROR_INVALID_ARGS,
2019 : : "invalid message format");
2020 : 0 : return FALSE;
2021 : : }
2022 : :
2023 [ # # ]: 0 : if (os_strcmp(entry.key, "WPSVendorExtensions") == 0) {
2024 [ # # ][ # # ]: 0 : if (entry.type != DBUS_TYPE_ARRAY ||
2025 [ # # ]: 0 : entry.array_type != WPAS_DBUS_TYPE_BINARRAY ||
2026 : 0 : entry.array_len > MAX_WPS_VENDOR_EXTENSIONS)
2027 : : goto error;
2028 : :
2029 [ # # ]: 0 : for (i = 0; i < MAX_WPS_VENDOR_EXTENSIONS; i++) {
2030 [ # # ]: 0 : if (i < entry.array_len) {
2031 : 0 : hapd->conf->wps_vendor_ext[i] =
2032 : 0 : entry.binarray_value[i];
2033 : 0 : entry.binarray_value[i] = NULL;
2034 : : } else
2035 : 0 : hapd->conf->wps_vendor_ext[i] = NULL;
2036 : : }
2037 : :
2038 : 0 : hostapd_update_wps(hapd);
2039 : : } else
2040 : 0 : goto error;
2041 : :
2042 : 0 : wpa_dbus_dict_entry_clear(&entry);
2043 : : }
2044 : :
2045 : 0 : return TRUE;
2046 : :
2047 : : error:
2048 : 0 : wpa_dbus_dict_entry_clear(&entry);
2049 : 0 : dbus_set_error_const(error, DBUS_ERROR_INVALID_ARGS,
2050 : : "invalid message format");
2051 : 0 : return FALSE;
2052 : : }
2053 : :
2054 : :
2055 : 0 : DBusMessage * wpas_dbus_handler_p2p_add_service(DBusMessage *message,
2056 : : struct wpa_supplicant *wpa_s)
2057 : : {
2058 : : DBusMessageIter iter_dict;
2059 : 0 : DBusMessage *reply = NULL;
2060 : : DBusMessageIter iter;
2061 : : struct wpa_dbus_dict_entry entry;
2062 : 0 : int upnp = 0;
2063 : 0 : int bonjour = 0;
2064 : 0 : char *service = NULL;
2065 : 0 : struct wpabuf *query = NULL;
2066 : 0 : struct wpabuf *resp = NULL;
2067 : 0 : u8 version = 0;
2068 : :
2069 : 0 : dbus_message_iter_init(message, &iter);
2070 : :
2071 [ # # ]: 0 : if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL))
2072 : 0 : goto error;
2073 : :
2074 [ # # ]: 0 : while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
2075 [ # # ]: 0 : if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
2076 : 0 : goto error;
2077 : :
2078 [ # # ][ # # ]: 0 : if (!os_strcmp(entry.key, "service_type") &&
2079 : 0 : (entry.type == DBUS_TYPE_STRING)) {
2080 [ # # ]: 0 : if (!os_strcmp(entry.str_value, "upnp"))
2081 : 0 : upnp = 1;
2082 [ # # ]: 0 : else if (!os_strcmp(entry.str_value, "bonjour"))
2083 : 0 : bonjour = 1;
2084 : : else
2085 : 0 : goto error_clear;
2086 [ # # ][ # # ]: 0 : } else if (!os_strcmp(entry.key, "version") &&
2087 : 0 : entry.type == DBUS_TYPE_INT32) {
2088 : 0 : version = entry.uint32_value;
2089 [ # # ][ # # ]: 0 : } else if (!os_strcmp(entry.key, "service") &&
2090 : 0 : (entry.type == DBUS_TYPE_STRING)) {
2091 : 0 : service = os_strdup(entry.str_value);
2092 [ # # ]: 0 : } else if (!os_strcmp(entry.key, "query")) {
2093 [ # # ][ # # ]: 0 : if ((entry.type != DBUS_TYPE_ARRAY) ||
2094 : 0 : (entry.array_type != DBUS_TYPE_BYTE))
2095 : : goto error_clear;
2096 : 0 : query = wpabuf_alloc_copy(
2097 : 0 : entry.bytearray_value,
2098 : 0 : entry.array_len);
2099 [ # # ]: 0 : } else if (!os_strcmp(entry.key, "response")) {
2100 [ # # ][ # # ]: 0 : if ((entry.type != DBUS_TYPE_ARRAY) ||
2101 : 0 : (entry.array_type != DBUS_TYPE_BYTE))
2102 : : goto error_clear;
2103 : 0 : resp = wpabuf_alloc_copy(entry.bytearray_value,
2104 : 0 : entry.array_len);
2105 : : }
2106 : 0 : wpa_dbus_dict_entry_clear(&entry);
2107 : : }
2108 : :
2109 [ # # ]: 0 : if (upnp == 1) {
2110 [ # # ][ # # ]: 0 : if (version <= 0 || service == NULL)
2111 : : goto error;
2112 : :
2113 [ # # ]: 0 : if (wpas_p2p_service_add_upnp(wpa_s, version, service) != 0)
2114 : 0 : goto error;
2115 : :
2116 : 0 : os_free(service);
2117 : 0 : service = NULL;
2118 [ # # ]: 0 : } else if (bonjour == 1) {
2119 [ # # ][ # # ]: 0 : if (query == NULL || resp == NULL)
2120 : : goto error;
2121 : :
2122 [ # # ]: 0 : if (wpas_p2p_service_add_bonjour(wpa_s, query, resp) < 0)
2123 : 0 : goto error;
2124 : 0 : query = NULL;
2125 : 0 : resp = NULL;
2126 : : } else
2127 : 0 : goto error;
2128 : :
2129 : 0 : return reply;
2130 : : error_clear:
2131 : 0 : wpa_dbus_dict_entry_clear(&entry);
2132 : : error:
2133 : 0 : os_free(service);
2134 : 0 : wpabuf_free(query);
2135 : 0 : wpabuf_free(resp);
2136 : 0 : return wpas_dbus_error_invalid_args(message, NULL);
2137 : : }
2138 : :
2139 : :
2140 : 0 : DBusMessage * wpas_dbus_handler_p2p_delete_service(
2141 : : DBusMessage *message, struct wpa_supplicant *wpa_s)
2142 : : {
2143 : : DBusMessageIter iter_dict;
2144 : 0 : DBusMessage *reply = NULL;
2145 : : DBusMessageIter iter;
2146 : : struct wpa_dbus_dict_entry entry;
2147 : 0 : int upnp = 0;
2148 : 0 : int bonjour = 0;
2149 : 0 : int ret = 0;
2150 : 0 : char *service = NULL;
2151 : 0 : struct wpabuf *query = NULL;
2152 : 0 : u8 version = 0;
2153 : :
2154 : 0 : dbus_message_iter_init(message, &iter);
2155 : :
2156 [ # # ]: 0 : if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL))
2157 : 0 : goto error;
2158 : :
2159 [ # # ]: 0 : if (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
2160 [ # # ]: 0 : if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
2161 : 0 : goto error;
2162 : :
2163 [ # # ][ # # ]: 0 : if (!os_strcmp(entry.key, "service_type") &&
2164 : 0 : (entry.type == DBUS_TYPE_STRING)) {
2165 [ # # ]: 0 : if (!os_strcmp(entry.str_value, "upnp"))
2166 : 0 : upnp = 1;
2167 [ # # ]: 0 : else if (!os_strcmp(entry.str_value, "bonjour"))
2168 : 0 : bonjour = 1;
2169 : : else
2170 : 0 : goto error_clear;
2171 : 0 : wpa_dbus_dict_entry_clear(&entry);
2172 : : }
2173 : : }
2174 [ # # ]: 0 : if (upnp == 1) {
2175 [ # # ]: 0 : while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
2176 [ # # ]: 0 : if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
2177 : 0 : goto error;
2178 [ # # ][ # # ]: 0 : if (!os_strcmp(entry.key, "version") &&
2179 : 0 : entry.type == DBUS_TYPE_INT32)
2180 : 0 : version = entry.uint32_value;
2181 [ # # ][ # # ]: 0 : else if (!os_strcmp(entry.key, "service") &&
2182 : 0 : entry.type == DBUS_TYPE_STRING)
2183 : 0 : service = os_strdup(entry.str_value);
2184 : : else
2185 : : goto error_clear;
2186 : :
2187 : 0 : wpa_dbus_dict_entry_clear(&entry);
2188 : : }
2189 : :
2190 [ # # ][ # # ]: 0 : if (version <= 0 || service == NULL)
2191 : : goto error;
2192 : :
2193 : 0 : ret = wpas_p2p_service_del_upnp(wpa_s, version, service);
2194 : 0 : os_free(service);
2195 [ # # ]: 0 : if (ret != 0)
2196 : 0 : goto error;
2197 [ # # ]: 0 : } else if (bonjour == 1) {
2198 [ # # ]: 0 : while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
2199 [ # # ]: 0 : if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
2200 : 0 : goto error;
2201 : :
2202 [ # # ]: 0 : if (!os_strcmp(entry.key, "query")) {
2203 [ # # ][ # # ]: 0 : if ((entry.type != DBUS_TYPE_ARRAY) ||
2204 : 0 : (entry.array_type != DBUS_TYPE_BYTE))
2205 : : goto error_clear;
2206 : 0 : query = wpabuf_alloc_copy(
2207 : 0 : entry.bytearray_value,
2208 : 0 : entry.array_len);
2209 : : } else
2210 : 0 : goto error_clear;
2211 : :
2212 : 0 : wpa_dbus_dict_entry_clear(&entry);
2213 : : }
2214 : :
2215 [ # # ]: 0 : if (query == NULL)
2216 : 0 : goto error;
2217 : :
2218 : 0 : ret = wpas_p2p_service_del_bonjour(wpa_s, query);
2219 [ # # ]: 0 : if (ret != 0)
2220 : 0 : goto error;
2221 : 0 : wpabuf_free(query);
2222 : : } else
2223 : 0 : goto error;
2224 : :
2225 : 0 : return reply;
2226 : : error_clear:
2227 : 0 : wpa_dbus_dict_entry_clear(&entry);
2228 : : error:
2229 : 0 : return wpas_dbus_error_invalid_args(message, NULL);
2230 : : }
2231 : :
2232 : :
2233 : 0 : DBusMessage * wpas_dbus_handler_p2p_flush_service(DBusMessage *message,
2234 : : struct wpa_supplicant *wpa_s)
2235 : : {
2236 : 0 : wpas_p2p_service_flush(wpa_s);
2237 : 0 : return NULL;
2238 : : }
2239 : :
2240 : :
2241 : 0 : DBusMessage * wpas_dbus_handler_p2p_service_sd_req(
2242 : : DBusMessage *message, struct wpa_supplicant *wpa_s)
2243 : : {
2244 : : DBusMessageIter iter_dict;
2245 : 0 : DBusMessage *reply = NULL;
2246 : : DBusMessageIter iter;
2247 : : struct wpa_dbus_dict_entry entry;
2248 : 0 : int upnp = 0;
2249 : 0 : char *service = NULL;
2250 : 0 : char *peer_object_path = NULL;
2251 : 0 : struct wpabuf *tlv = NULL;
2252 : 0 : u8 version = 0;
2253 : 0 : u64 ref = 0;
2254 : : u8 addr_buf[ETH_ALEN], *addr;
2255 : :
2256 : 0 : dbus_message_iter_init(message, &iter);
2257 : :
2258 [ # # ]: 0 : if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL))
2259 : 0 : goto error;
2260 : :
2261 [ # # ]: 0 : while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
2262 [ # # ]: 0 : if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
2263 : 0 : goto error;
2264 [ # # ][ # # ]: 0 : if (!os_strcmp(entry.key, "peer_object") &&
2265 : 0 : entry.type == DBUS_TYPE_OBJECT_PATH) {
2266 : 0 : peer_object_path = os_strdup(entry.str_value);
2267 [ # # ][ # # ]: 0 : } else if (!os_strcmp(entry.key, "service_type") &&
2268 : 0 : entry.type == DBUS_TYPE_STRING) {
2269 [ # # ]: 0 : if (!os_strcmp(entry.str_value, "upnp"))
2270 : 0 : upnp = 1;
2271 : : else
2272 : 0 : goto error_clear;
2273 [ # # ][ # # ]: 0 : } else if (!os_strcmp(entry.key, "version") &&
2274 : 0 : entry.type == DBUS_TYPE_INT32) {
2275 : 0 : version = entry.uint32_value;
2276 [ # # ][ # # ]: 0 : } else if (!os_strcmp(entry.key, "service") &&
2277 : 0 : entry.type == DBUS_TYPE_STRING) {
2278 : 0 : service = os_strdup(entry.str_value);
2279 [ # # ]: 0 : } else if (!os_strcmp(entry.key, "tlv")) {
2280 [ # # ][ # # ]: 0 : if (entry.type != DBUS_TYPE_ARRAY ||
2281 : 0 : entry.array_type != DBUS_TYPE_BYTE)
2282 : : goto error_clear;
2283 : 0 : tlv = wpabuf_alloc_copy(entry.bytearray_value,
2284 : 0 : entry.array_len);
2285 : : } else
2286 : 0 : goto error_clear;
2287 : :
2288 : 0 : wpa_dbus_dict_entry_clear(&entry);
2289 : : }
2290 : :
2291 [ # # ]: 0 : if (!peer_object_path) {
2292 : 0 : addr = NULL;
2293 : : } else {
2294 [ # # # # ]: 0 : if (parse_peer_object_path(peer_object_path, addr_buf) < 0 ||
2295 : 0 : !p2p_peer_known(wpa_s->global->p2p, addr_buf))
2296 : : goto error;
2297 : :
2298 : 0 : addr = addr_buf;
2299 : : }
2300 : :
2301 [ # # ]: 0 : if (upnp == 1) {
2302 [ # # ][ # # ]: 0 : if (version <= 0 || service == NULL)
2303 : : goto error;
2304 : :
2305 : 0 : ref = wpas_p2p_sd_request_upnp(wpa_s, addr, version, service);
2306 : : } else {
2307 [ # # ]: 0 : if (tlv == NULL)
2308 : 0 : goto error;
2309 : 0 : ref = wpas_p2p_sd_request(wpa_s, addr, tlv);
2310 : 0 : wpabuf_free(tlv);
2311 : : }
2312 : :
2313 [ # # ]: 0 : if (ref != 0) {
2314 : 0 : reply = dbus_message_new_method_return(message);
2315 : 0 : dbus_message_append_args(reply, DBUS_TYPE_UINT64,
2316 : : &ref, DBUS_TYPE_INVALID);
2317 : : } else {
2318 : 0 : reply = wpas_dbus_error_unknown_error(
2319 : : message, "Unable to send SD request");
2320 : : }
2321 : : out:
2322 : 0 : os_free(service);
2323 : 0 : os_free(peer_object_path);
2324 : 0 : return reply;
2325 : : error_clear:
2326 : 0 : wpa_dbus_dict_entry_clear(&entry);
2327 : : error:
2328 [ # # ]: 0 : if (tlv)
2329 : 0 : wpabuf_free(tlv);
2330 : 0 : reply = wpas_dbus_error_invalid_args(message, NULL);
2331 : 0 : goto out;
2332 : : }
2333 : :
2334 : :
2335 : 0 : DBusMessage * wpas_dbus_handler_p2p_service_sd_res(
2336 : : DBusMessage *message, struct wpa_supplicant *wpa_s)
2337 : : {
2338 : : DBusMessageIter iter_dict;
2339 : 0 : DBusMessage *reply = NULL;
2340 : : DBusMessageIter iter;
2341 : : struct wpa_dbus_dict_entry entry;
2342 : 0 : char *peer_object_path = NULL;
2343 : 0 : struct wpabuf *tlv = NULL;
2344 : 0 : int freq = 0;
2345 : 0 : int dlg_tok = 0;
2346 : : u8 addr[ETH_ALEN];
2347 : :
2348 : 0 : dbus_message_iter_init(message, &iter);
2349 : :
2350 [ # # ]: 0 : if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL))
2351 : 0 : goto error;
2352 : :
2353 [ # # ]: 0 : while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
2354 [ # # ]: 0 : if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
2355 : 0 : goto error;
2356 : :
2357 [ # # ][ # # ]: 0 : if (!os_strcmp(entry.key, "peer_object") &&
2358 : 0 : entry.type == DBUS_TYPE_OBJECT_PATH) {
2359 : 0 : peer_object_path = os_strdup(entry.str_value);
2360 [ # # ][ # # ]: 0 : } else if (!os_strcmp(entry.key, "frequency") &&
2361 : 0 : entry.type == DBUS_TYPE_INT32) {
2362 : 0 : freq = entry.uint32_value;
2363 [ # # ][ # # ]: 0 : } else if (!os_strcmp(entry.key, "dialog_token") &&
2364 : 0 : entry.type == DBUS_TYPE_UINT32) {
2365 : 0 : dlg_tok = entry.uint32_value;
2366 [ # # ]: 0 : } else if (!os_strcmp(entry.key, "tlvs")) {
2367 [ # # ][ # # ]: 0 : if (entry.type != DBUS_TYPE_ARRAY ||
2368 : 0 : entry.array_type != DBUS_TYPE_BYTE)
2369 : : goto error_clear;
2370 : 0 : tlv = wpabuf_alloc_copy(entry.bytearray_value,
2371 : 0 : entry.array_len);
2372 : : } else
2373 : 0 : goto error_clear;
2374 : :
2375 : 0 : wpa_dbus_dict_entry_clear(&entry);
2376 : : }
2377 [ # # # # ]: 0 : if (!peer_object_path ||
2378 [ # # ]: 0 : (parse_peer_object_path(peer_object_path, addr) < 0) ||
2379 : 0 : !p2p_peer_known(wpa_s->global->p2p, addr))
2380 : : goto error;
2381 : :
2382 [ # # ]: 0 : if (tlv == NULL)
2383 : 0 : goto error;
2384 : :
2385 : 0 : wpas_p2p_sd_response(wpa_s, freq, addr, (u8) dlg_tok, tlv);
2386 : 0 : wpabuf_free(tlv);
2387 : : out:
2388 : 0 : os_free(peer_object_path);
2389 : 0 : return reply;
2390 : : error_clear:
2391 : 0 : wpa_dbus_dict_entry_clear(&entry);
2392 : : error:
2393 : 0 : reply = wpas_dbus_error_invalid_args(message, NULL);
2394 : 0 : goto out;
2395 : : }
2396 : :
2397 : :
2398 : 0 : DBusMessage * wpas_dbus_handler_p2p_service_sd_cancel_req(
2399 : : DBusMessage *message, struct wpa_supplicant *wpa_s)
2400 : : {
2401 : : DBusMessageIter iter;
2402 : 0 : u64 req = 0;
2403 : :
2404 : 0 : dbus_message_iter_init(message, &iter);
2405 : 0 : dbus_message_iter_get_basic(&iter, &req);
2406 : :
2407 [ # # ]: 0 : if (req == 0)
2408 : 0 : goto error;
2409 : :
2410 [ # # ]: 0 : if (!wpas_p2p_sd_cancel_request(wpa_s, req))
2411 : 0 : goto error;
2412 : :
2413 : 0 : return NULL;
2414 : : error:
2415 : 0 : return wpas_dbus_error_invalid_args(message, NULL);
2416 : : }
2417 : :
2418 : :
2419 : 0 : DBusMessage * wpas_dbus_handler_p2p_service_update(
2420 : : DBusMessage *message, struct wpa_supplicant *wpa_s)
2421 : : {
2422 : 0 : wpas_p2p_sd_service_update(wpa_s);
2423 : 0 : return NULL;
2424 : : }
2425 : :
2426 : :
2427 : 0 : DBusMessage * wpas_dbus_handler_p2p_serv_disc_external(
2428 : : DBusMessage *message, struct wpa_supplicant *wpa_s)
2429 : : {
2430 : : DBusMessageIter iter;
2431 : 0 : int ext = 0;
2432 : :
2433 : 0 : dbus_message_iter_init(message, &iter);
2434 : 0 : dbus_message_iter_get_basic(&iter, &ext);
2435 : :
2436 : 0 : wpa_s->p2p_sd_over_ctrl_iface = ext;
2437 : :
2438 : 0 : return NULL;
2439 : :
2440 : : }
|