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 "../bss.h"
18 #include "dbus_new_helpers.h"
19 #include "dbus_new.h"
20 #include "dbus_new_handlers.h"
21 #include "dbus_new_handlers_p2p.h"
22 #include "dbus_dict_helpers.h"
23 #include "p2p/p2p.h"
24 #include "common/ieee802_11_defs.h"
25 #include "ap/hostapd.h"
26 #include "ap/ap_config.h"
27 #include "ap/wps_hostapd.h"
28
29 #include "../p2p_supplicant.h"
30 #include "../wifi_display.h"
31
32
wpas_dbus_validate_dbus_ipaddr(struct wpa_dbus_dict_entry entry)33 static int wpas_dbus_validate_dbus_ipaddr(struct wpa_dbus_dict_entry entry)
34 {
35 if (entry.type != DBUS_TYPE_ARRAY ||
36 entry.array_type != DBUS_TYPE_BYTE ||
37 entry.array_len != 4)
38 return 0;
39
40 return 1;
41 }
42
43
no_p2p_mgmt_interface(DBusError * error)44 static dbus_bool_t no_p2p_mgmt_interface(DBusError *error)
45 {
46 dbus_set_error_const(error, WPAS_DBUS_ERROR_IFACE_UNKNOWN,
47 "Could not find P2P mgmt interface");
48 return FALSE;
49 }
50
51
52 /**
53 * Parses out the mac address from the peer object path.
54 * @peer_path - object path of the form
55 * /fi/w1/wpa_supplicant1/Interfaces/n/Peers/00112233445566 (no colons)
56 * @addr - out param must be of ETH_ALEN size
57 * Returns 0 if valid (including MAC), -1 otherwise
58 */
parse_peer_object_path(const char * peer_path,u8 addr[ETH_ALEN])59 static int parse_peer_object_path(const char *peer_path, u8 addr[ETH_ALEN])
60 {
61 const char *p;
62
63 if (!peer_path)
64 return -1;
65 p = os_strrchr(peer_path, '/');
66 if (!p)
67 return -1;
68 p++;
69 return hwaddr_compact_aton(p, addr);
70 }
71
72
73 /**
74 * wpas_dbus_error_persistent_group_unknown - Return a new PersistentGroupUnknown
75 * error message
76 * @message: Pointer to incoming dbus message this error refers to
77 * Returns: a dbus error message
78 *
79 * Convenience function to create and return an invalid persistent group error.
80 */
81 static DBusMessage *
wpas_dbus_error_persistent_group_unknown(DBusMessage * message)82 wpas_dbus_error_persistent_group_unknown(DBusMessage *message)
83 {
84 return dbus_message_new_error(
85 message, WPAS_DBUS_ERROR_NETWORK_UNKNOWN,
86 "There is no such persistent group in this P2P device.");
87 }
88
89
90 /**
91 * wpas_dbus_error_no_p2p_mgmt_iface - Return a new InterfaceUnknown error
92 * message
93 * @message: Pointer to incoming dbus message this error refers to
94 * Returns: a dbus error message
95 *
96 * Convenience function to create and return an unknown interface error.
97 */
wpas_dbus_error_no_p2p_mgmt_iface(DBusMessage * message)98 static DBusMessage * wpas_dbus_error_no_p2p_mgmt_iface(DBusMessage *message)
99 {
100 wpa_printf(MSG_DEBUG, "dbus: Could not find P2P mgmt interface");
101 return dbus_message_new_error(message, WPAS_DBUS_ERROR_IFACE_UNKNOWN,
102 "Could not find P2P mgmt interface");
103 }
104
105
wpas_dbus_handler_p2p_find(DBusMessage * message,struct wpa_supplicant * wpa_s)106 DBusMessage * wpas_dbus_handler_p2p_find(DBusMessage *message,
107 struct wpa_supplicant *wpa_s)
108 {
109 struct wpa_dbus_dict_entry entry;
110 DBusMessage *reply = NULL;
111 DBusMessageIter iter;
112 DBusMessageIter iter_dict;
113 unsigned int timeout = 0;
114 enum p2p_discovery_type type = P2P_FIND_START_WITH_FULL;
115 int num_req_dev_types = 0;
116 unsigned int i;
117 u8 *req_dev_types = NULL;
118 unsigned int freq = 0;
119
120 dbus_message_iter_init(message, &iter);
121 entry.key = NULL;
122
123 if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL))
124 goto error;
125
126 while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
127 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
128 goto error;
129
130 if (os_strcmp(entry.key, "Timeout") == 0 &&
131 entry.type == DBUS_TYPE_INT32) {
132 timeout = entry.uint32_value;
133 } else if (os_strcmp(entry.key, "RequestedDeviceTypes") == 0) {
134 if (entry.type != DBUS_TYPE_ARRAY ||
135 entry.array_type != WPAS_DBUS_TYPE_BINARRAY)
136 goto error_clear;
137
138 os_free(req_dev_types);
139 req_dev_types =
140 os_malloc(WPS_DEV_TYPE_LEN * entry.array_len);
141 if (!req_dev_types)
142 goto error_clear;
143
144 for (i = 0; i < entry.array_len; i++) {
145 if (wpabuf_len(entry.binarray_value[i]) !=
146 WPS_DEV_TYPE_LEN)
147 goto error_clear;
148 os_memcpy(req_dev_types + i * WPS_DEV_TYPE_LEN,
149 wpabuf_head(entry.binarray_value[i]),
150 WPS_DEV_TYPE_LEN);
151 }
152 num_req_dev_types = entry.array_len;
153 } else if (os_strcmp(entry.key, "DiscoveryType") == 0 &&
154 entry.type == DBUS_TYPE_STRING) {
155 if (os_strcmp(entry.str_value, "start_with_full") == 0)
156 type = P2P_FIND_START_WITH_FULL;
157 else if (os_strcmp(entry.str_value, "social") == 0)
158 type = P2P_FIND_ONLY_SOCIAL;
159 else if (os_strcmp(entry.str_value, "progressive") == 0)
160 type = P2P_FIND_PROGRESSIVE;
161 else
162 goto error_clear;
163 } else if (os_strcmp(entry.key, "freq") == 0 &&
164 (entry.type == DBUS_TYPE_INT32 ||
165 entry.type == DBUS_TYPE_UINT32)) {
166 freq = entry.uint32_value;
167 } else
168 goto error_clear;
169 wpa_dbus_dict_entry_clear(&entry);
170 }
171
172 wpa_s = wpa_s->global->p2p_init_wpa_s;
173 if (!wpa_s) {
174 reply = wpas_dbus_error_no_p2p_mgmt_iface(message);
175 goto error_nop2p;
176 }
177
178 if (wpas_p2p_find(wpa_s, timeout, type, num_req_dev_types,
179 req_dev_types, NULL, 0, 0, NULL, freq, false))
180 reply = wpas_dbus_error_unknown_error(
181 message, "Could not start P2P find");
182
183 os_free(req_dev_types);
184 return reply;
185
186 error_clear:
187 wpa_dbus_dict_entry_clear(&entry);
188 error:
189 reply = wpas_dbus_error_invalid_args(message, entry.key);
190 error_nop2p:
191 os_free(req_dev_types);
192 return reply;
193 }
194
195
wpas_dbus_handler_p2p_stop_find(DBusMessage * message,struct wpa_supplicant * wpa_s)196 DBusMessage * wpas_dbus_handler_p2p_stop_find(DBusMessage *message,
197 struct wpa_supplicant *wpa_s)
198 {
199 wpa_s = wpa_s->global->p2p_init_wpa_s;
200 if (wpa_s)
201 wpas_p2p_stop_find(wpa_s);
202 return NULL;
203 }
204
205
wpas_dbus_handler_p2p_rejectpeer(DBusMessage * message,struct wpa_supplicant * wpa_s)206 DBusMessage * wpas_dbus_handler_p2p_rejectpeer(DBusMessage *message,
207 struct wpa_supplicant *wpa_s)
208 {
209 DBusMessageIter iter;
210 char *peer_object_path = NULL;
211 u8 peer_addr[ETH_ALEN];
212
213 dbus_message_iter_init(message, &iter);
214 dbus_message_iter_get_basic(&iter, &peer_object_path);
215
216 if (parse_peer_object_path(peer_object_path, peer_addr) < 0)
217 return wpas_dbus_error_invalid_args(message, NULL);
218
219 wpa_s = wpa_s->global->p2p_init_wpa_s;
220 if (!wpa_s)
221 return wpas_dbus_error_no_p2p_mgmt_iface(message);
222
223 if (wpas_p2p_reject(wpa_s, peer_addr) < 0)
224 return wpas_dbus_error_unknown_error(message,
225 "Failed to call wpas_p2p_reject method.");
226
227 return NULL;
228 }
229
230
wpas_dbus_handler_p2p_listen(DBusMessage * message,struct wpa_supplicant * wpa_s)231 DBusMessage * wpas_dbus_handler_p2p_listen(DBusMessage *message,
232 struct wpa_supplicant *wpa_s)
233 {
234 dbus_int32_t timeout = 0;
235
236 if (!dbus_message_get_args(message, NULL, DBUS_TYPE_INT32, &timeout,
237 DBUS_TYPE_INVALID))
238 return wpas_dbus_error_no_memory(message);
239
240 wpa_s = wpa_s->global->p2p_init_wpa_s;
241 if (!wpa_s)
242 return wpas_dbus_error_no_p2p_mgmt_iface(message);
243
244 if (wpas_p2p_listen(wpa_s, (unsigned int) timeout)) {
245 return dbus_message_new_error(message,
246 WPAS_DBUS_ERROR_UNKNOWN_ERROR,
247 "Could not start P2P listen");
248 }
249
250 return NULL;
251 }
252
253
wpas_dbus_handler_p2p_extendedlisten(DBusMessage * message,struct wpa_supplicant * wpa_s)254 DBusMessage * wpas_dbus_handler_p2p_extendedlisten(
255 DBusMessage *message, struct wpa_supplicant *wpa_s)
256 {
257 unsigned int period = 0, interval = 0;
258 struct wpa_dbus_dict_entry entry;
259 DBusMessageIter iter;
260 DBusMessageIter iter_dict;
261
262 dbus_message_iter_init(message, &iter);
263 entry.key = NULL;
264
265 if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL))
266 goto error;
267
268 while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
269 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
270 goto error;
271
272 if (os_strcmp(entry.key, "period") == 0 &&
273 entry.type == DBUS_TYPE_INT32)
274 period = entry.uint32_value;
275 else if (os_strcmp(entry.key, "interval") == 0 &&
276 entry.type == DBUS_TYPE_INT32)
277 interval = entry.uint32_value;
278 else
279 goto error_clear;
280 wpa_dbus_dict_entry_clear(&entry);
281 }
282
283 wpa_s = wpa_s->global->p2p_init_wpa_s;
284 if (!wpa_s)
285 return wpas_dbus_error_no_p2p_mgmt_iface(message);
286
287 if (wpas_p2p_ext_listen(wpa_s, period, interval))
288 return wpas_dbus_error_unknown_error(
289 message, "failed to initiate a p2p_ext_listen.");
290
291 return NULL;
292
293 error_clear:
294 wpa_dbus_dict_entry_clear(&entry);
295 error:
296 return wpas_dbus_error_invalid_args(message, entry.key);
297 }
298
299
wpas_dbus_handler_p2p_presence_request(DBusMessage * message,struct wpa_supplicant * wpa_s)300 DBusMessage * wpas_dbus_handler_p2p_presence_request(
301 DBusMessage *message, struct wpa_supplicant *wpa_s)
302 {
303 unsigned int dur1 = 0, int1 = 0, dur2 = 0, int2 = 0;
304 struct wpa_dbus_dict_entry entry;
305 DBusMessageIter iter;
306 DBusMessageIter iter_dict;
307
308 dbus_message_iter_init(message, &iter);
309 entry.key = NULL;
310
311 if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL))
312 goto error;
313
314 while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
315 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
316 goto error;
317
318 if (os_strcmp(entry.key, "duration1") == 0 &&
319 entry.type == DBUS_TYPE_INT32)
320 dur1 = entry.uint32_value;
321 else if (os_strcmp(entry.key, "interval1") == 0 &&
322 entry.type == DBUS_TYPE_INT32)
323 int1 = entry.uint32_value;
324 else if (os_strcmp(entry.key, "duration2") == 0 &&
325 entry.type == DBUS_TYPE_INT32)
326 dur2 = entry.uint32_value;
327 else if (os_strcmp(entry.key, "interval2") == 0 &&
328 entry.type == DBUS_TYPE_INT32)
329 int2 = entry.uint32_value;
330 else
331 goto error_clear;
332
333 wpa_dbus_dict_entry_clear(&entry);
334 }
335
336 if (wpas_p2p_presence_req(wpa_s, dur1, int1, dur2, int2) < 0)
337 return wpas_dbus_error_unknown_error(message,
338 "Failed to invoke presence request.");
339
340 return NULL;
341
342 error_clear:
343 wpa_dbus_dict_entry_clear(&entry);
344 error:
345 return wpas_dbus_error_invalid_args(message, entry.key);
346 }
347
348
wpas_dbus_handler_p2p_group_add(DBusMessage * message,struct wpa_supplicant * wpa_s)349 DBusMessage * wpas_dbus_handler_p2p_group_add(DBusMessage *message,
350 struct wpa_supplicant *wpa_s)
351 {
352 DBusMessageIter iter_dict;
353 DBusMessage *reply = NULL;
354 DBusMessageIter iter;
355 struct wpa_dbus_dict_entry entry;
356 char *pg_object_path = NULL;
357 int persistent_group = 0;
358 int freq = 0;
359 int retry_limit = 0;
360 char *iface = NULL;
361 unsigned int group_id = 0;
362 struct wpa_ssid *ssid;
363 u8 go_bssid_buf[ETH_ALEN], *go_bssid = NULL;
364 bool allow_6ghz = false;
365 int vht = wpa_s->conf->p2p_go_vht;
366 int ht40 = wpa_s->conf->p2p_go_ht40 || vht;
367 int he = wpa_s->conf->p2p_go_he;
368 int edmg = wpa_s->conf->p2p_go_edmg;
369 int max_oper_chwidth, chwidth = 0, freq2 = 0;
370
371 dbus_message_iter_init(message, &iter);
372
373 if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL))
374 goto inv_args;
375
376 while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
377 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
378 goto inv_args;
379
380 if (os_strcmp(entry.key, "persistent") == 0 &&
381 entry.type == DBUS_TYPE_BOOLEAN) {
382 persistent_group = entry.bool_value;
383 } else if (os_strcmp(entry.key, "frequency") == 0 &&
384 entry.type == DBUS_TYPE_INT32) {
385 freq = entry.int32_value;
386 if (freq <= 0)
387 goto inv_args_clear;
388 } else if (os_strcmp(entry.key, "retry_limit") == 0 &&
389 entry.type == DBUS_TYPE_INT32) {
390 retry_limit = entry.int32_value;
391 if (retry_limit <= 0)
392 goto inv_args_clear;
393 } else if (os_strcmp(entry.key, "persistent_group_object") ==
394 0 &&
395 entry.type == DBUS_TYPE_OBJECT_PATH) {
396 pg_object_path = os_strdup(entry.str_value);
397 } else if (os_strcmp(entry.key, "go_bssid") == 0 &&
398 entry.type == DBUS_TYPE_STRING) {
399 if (hwaddr_aton(entry.str_value, go_bssid_buf))
400 goto inv_args_clear;
401 go_bssid = go_bssid_buf;
402 } else if (os_strcmp(entry.key, "ht40") == 0 &&
403 entry.type == DBUS_TYPE_BOOLEAN) {
404 ht40 = entry.bool_value;
405 } else if (os_strcmp(entry.key, "vht") == 0 &&
406 entry.type == DBUS_TYPE_BOOLEAN) {
407 vht = entry.bool_value;
408 ht40 |= vht;
409 } else if (os_strcmp(entry.key, "he") == 0 &&
410 entry.type == DBUS_TYPE_BOOLEAN) {
411 he = entry.bool_value;
412 } else if (os_strcmp(entry.key, "edmg") == 0 &&
413 entry.type == DBUS_TYPE_BOOLEAN) {
414 edmg = entry.bool_value;
415 } else if (os_strcmp(entry.key, "allow_6ghz") == 0 &&
416 entry.type == DBUS_TYPE_BOOLEAN) {
417 allow_6ghz = entry.bool_value;
418 } else if (os_strcmp(entry.key, "freq2") == 0 &&
419 entry.type == DBUS_TYPE_INT32) {
420 freq2 = entry.int32_value;
421 } else if (os_strcmp(entry.key, "max_oper_chwidth") == 0 &&
422 entry.type == DBUS_TYPE_INT32) {
423 chwidth = entry.int32_value;
424 } else {
425 goto inv_args_clear;
426 }
427
428 wpa_dbus_dict_entry_clear(&entry);
429 }
430
431 max_oper_chwidth = chwidth_freq2_to_ch_width(chwidth, freq2);
432 if (max_oper_chwidth < 0)
433 goto inv_args;
434
435 if (allow_6ghz && chwidth == 40)
436 max_oper_chwidth = CONF_OPER_CHWIDTH_40MHZ_6GHZ;
437
438 wpa_s = wpa_s->global->p2p_init_wpa_s;
439 if (!wpa_s) {
440 reply = wpas_dbus_error_no_p2p_mgmt_iface(message);
441 goto out;
442 }
443
444 if (pg_object_path != NULL) {
445 char *net_id_str;
446
447 /*
448 * A persistent group Object Path is defined meaning we want
449 * to re-invoke a persistent group.
450 */
451
452 iface = wpas_dbus_new_decompose_object_path(
453 pg_object_path, WPAS_DBUS_NEW_PERSISTENT_GROUPS_PART,
454 &net_id_str);
455 if (iface == NULL || net_id_str == NULL ||
456 !wpa_s->parent->dbus_new_path ||
457 os_strcmp(iface, wpa_s->parent->dbus_new_path) != 0) {
458 reply =
459 wpas_dbus_error_invalid_args(message,
460 pg_object_path);
461 goto out;
462 }
463
464 group_id = strtoul(net_id_str, NULL, 10);
465 if (errno == EINVAL) {
466 reply = wpas_dbus_error_invalid_args(
467 message, pg_object_path);
468 goto out;
469 }
470
471 /* Get the SSID structure from the persistent group id */
472 ssid = wpa_config_get_network(wpa_s->conf, group_id);
473 if (ssid == NULL || ssid->disabled != 2)
474 goto inv_args;
475
476 if (wpas_p2p_group_add_persistent(wpa_s, ssid, 0, freq, 0,
477 freq2, ht40, vht,
478 max_oper_chwidth, he, edmg,
479 NULL, 0, 0, allow_6ghz,
480 retry_limit, go_bssid)) {
481 reply = wpas_dbus_error_unknown_error(
482 message,
483 "Failed to reinvoke a persistent group");
484 goto out;
485 }
486 } else if (wpas_p2p_group_add(wpa_s, persistent_group, freq, freq2,
487 ht40, vht, max_oper_chwidth, he, edmg,
488 allow_6ghz))
489 goto inv_args;
490
491 out:
492 os_free(pg_object_path);
493 os_free(iface);
494 return reply;
495 inv_args_clear:
496 wpa_dbus_dict_entry_clear(&entry);
497 inv_args:
498 reply = wpas_dbus_error_invalid_args(message, NULL);
499 goto out;
500 }
501
502
wpas_dbus_handler_p2p_disconnect(DBusMessage * message,struct wpa_supplicant * wpa_s)503 DBusMessage * wpas_dbus_handler_p2p_disconnect(DBusMessage *message,
504 struct wpa_supplicant *wpa_s)
505 {
506 if (wpas_p2p_disconnect(wpa_s))
507 return wpas_dbus_error_unknown_error(message,
508 "failed to disconnect");
509
510 return NULL;
511 }
512
513
wpa_dbus_p2p_check_enabled(struct wpa_supplicant * wpa_s,DBusMessage * message,DBusMessage ** out_reply,DBusError * error)514 static dbus_bool_t wpa_dbus_p2p_check_enabled(struct wpa_supplicant *wpa_s,
515 DBusMessage *message,
516 DBusMessage **out_reply,
517 DBusError *error)
518 {
519 /* Return an error message or an error if P2P isn't available */
520 if (wpa_s->global->p2p_disabled || wpa_s->global->p2p == NULL) {
521 if (out_reply) {
522 *out_reply = dbus_message_new_error(
523 message, DBUS_ERROR_FAILED,
524 "P2P is not available for this interface");
525 }
526 dbus_set_error_const(error, DBUS_ERROR_FAILED,
527 "P2P is not available for this interface");
528 return FALSE;
529 }
530 if (!wpa_s->global->p2p_init_wpa_s) {
531 if (out_reply)
532 *out_reply = wpas_dbus_error_no_p2p_mgmt_iface(
533 message);
534 return no_p2p_mgmt_interface(error);
535 }
536 return TRUE;
537 }
538
539
wpas_dbus_handler_p2p_remove_client(DBusMessage * message,struct wpa_supplicant * wpa_s)540 DBusMessage * wpas_dbus_handler_p2p_remove_client(DBusMessage *message,
541 struct wpa_supplicant *wpa_s)
542 {
543 DBusMessageIter iter_dict;
544 DBusMessage *reply = NULL;
545 DBusMessageIter iter;
546 struct wpa_dbus_dict_entry entry;
547 char *peer_object_path = NULL;
548 char *interface_addr = NULL;
549 u8 peer_addr[ETH_ALEN];
550
551 if (!wpa_dbus_p2p_check_enabled(wpa_s, message, &reply, NULL))
552 return reply;
553
554 dbus_message_iter_init(message, &iter);
555
556 if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL))
557 goto err;
558
559 while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
560 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
561 goto err;
562
563 if (os_strcmp(entry.key, "peer") == 0 &&
564 entry.type == DBUS_TYPE_OBJECT_PATH) {
565 os_free(peer_object_path);
566 peer_object_path = os_strdup(entry.str_value);
567 wpa_dbus_dict_entry_clear(&entry);
568 } else if (os_strcmp(entry.key, "iface") == 0 &&
569 entry.type == DBUS_TYPE_STRING) {
570 os_free(interface_addr);
571 interface_addr = os_strdup(entry.str_value);
572 wpa_dbus_dict_entry_clear(&entry);
573 } else {
574 wpa_dbus_dict_entry_clear(&entry);
575 goto err;
576 }
577 }
578
579 if ((!peer_object_path && !interface_addr) ||
580 (peer_object_path &&
581 (parse_peer_object_path(peer_object_path, peer_addr) < 0 ||
582 !p2p_peer_known(wpa_s->global->p2p, peer_addr))) ||
583 (interface_addr && hwaddr_aton(interface_addr, peer_addr) < 0))
584 goto err;
585
586 wpas_p2p_remove_client(wpa_s, peer_addr, interface_addr != NULL);
587 reply = NULL;
588 out:
589 os_free(peer_object_path);
590 os_free(interface_addr);
591 return reply;
592 err:
593 reply = wpas_dbus_error_invalid_args(message, "Invalid address format");
594 goto out;
595 }
596
597
wpas_dbus_handler_p2p_flush(DBusMessage * message,struct wpa_supplicant * wpa_s)598 DBusMessage * wpas_dbus_handler_p2p_flush(DBusMessage *message,
599 struct wpa_supplicant *wpa_s)
600 {
601 DBusMessage *reply = NULL;
602
603 if (!wpa_dbus_p2p_check_enabled(wpa_s, message, &reply, NULL))
604 return reply;
605
606 wpa_s = wpa_s->global->p2p_init_wpa_s;
607
608 wpas_p2p_stop_find(wpa_s);
609 os_memset(wpa_s->p2p_auth_invite, 0, ETH_ALEN);
610 wpa_s->force_long_sd = 0;
611 p2p_flush(wpa_s->global->p2p);
612
613 return NULL;
614 }
615
616
wpas_dbus_handler_p2p_connect(DBusMessage * message,struct wpa_supplicant * wpa_s)617 DBusMessage * wpas_dbus_handler_p2p_connect(DBusMessage *message,
618 struct wpa_supplicant *wpa_s)
619 {
620 DBusMessageIter iter_dict;
621 DBusMessage *reply = NULL;
622 DBusMessageIter iter;
623 struct wpa_dbus_dict_entry entry;
624 char *peer_object_path = NULL;
625 int persistent_group = 0;
626 int join = 0;
627 int authorize_only = 0;
628 int go_intent = -1;
629 int freq = 0;
630 u8 addr[ETH_ALEN];
631 char *pin = NULL;
632 enum p2p_wps_method wps_method = WPS_NOT_READY;
633 int new_pin;
634 char *err_msg = NULL;
635 char *iface = NULL;
636 int ret;
637
638 if (!wpa_dbus_p2p_check_enabled(wpa_s, message, &reply, NULL))
639 return reply;
640
641 dbus_message_iter_init(message, &iter);
642
643 if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL))
644 goto inv_args;
645
646 while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
647 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
648 goto inv_args;
649
650 if (os_strcmp(entry.key, "peer") == 0 &&
651 entry.type == DBUS_TYPE_OBJECT_PATH) {
652 peer_object_path = os_strdup(entry.str_value);
653 } else if (os_strcmp(entry.key, "persistent") == 0 &&
654 entry.type == DBUS_TYPE_BOOLEAN) {
655 persistent_group = entry.bool_value;
656 } else if (os_strcmp(entry.key, "join") == 0 &&
657 entry.type == DBUS_TYPE_BOOLEAN) {
658 join = entry.bool_value;
659 } else if (os_strcmp(entry.key, "authorize_only") == 0 &&
660 entry.type == DBUS_TYPE_BOOLEAN) {
661 authorize_only = entry.bool_value;
662 } else if (os_strcmp(entry.key, "frequency") == 0 &&
663 entry.type == DBUS_TYPE_INT32) {
664 freq = entry.int32_value;
665 if (freq <= 0)
666 goto inv_args_clear;
667 } else if (os_strcmp(entry.key, "go_intent") == 0 &&
668 entry.type == DBUS_TYPE_INT32) {
669 go_intent = entry.int32_value;
670 if ((go_intent < 0) || (go_intent > 15))
671 goto inv_args_clear;
672 } else if (os_strcmp(entry.key, "wps_method") == 0 &&
673 entry.type == DBUS_TYPE_STRING) {
674 if (os_strcmp(entry.str_value, "pbc") == 0)
675 wps_method = WPS_PBC;
676 else if (os_strcmp(entry.str_value, "pin") == 0)
677 wps_method = WPS_PIN_DISPLAY;
678 else if (os_strcmp(entry.str_value, "display") == 0)
679 wps_method = WPS_PIN_DISPLAY;
680 else if (os_strcmp(entry.str_value, "keypad") == 0)
681 wps_method = WPS_PIN_KEYPAD;
682 else
683 goto inv_args_clear;
684 } else if (os_strcmp(entry.key, "pin") == 0 &&
685 entry.type == DBUS_TYPE_STRING) {
686 pin = os_strdup(entry.str_value);
687 } else
688 goto inv_args_clear;
689
690 wpa_dbus_dict_entry_clear(&entry);
691 }
692
693 if (wps_method == WPS_NOT_READY ||
694 parse_peer_object_path(peer_object_path, addr) < 0 ||
695 !p2p_peer_known(wpa_s->global->p2p, addr))
696 goto inv_args;
697
698 /*
699 * Validate the wps_method specified and the pin value.
700 */
701 if ((!pin || !pin[0]) && wps_method == WPS_PIN_KEYPAD)
702 goto inv_args;
703
704 wpa_s = wpa_s->global->p2p_init_wpa_s;
705
706 new_pin = wpas_p2p_connect(wpa_s, addr, pin, wps_method,
707 persistent_group, 0, join, authorize_only,
708 go_intent, freq, 0, -1, 0, 0, 0, 0, 0, 0,
709 NULL, 0, false);
710
711 if (new_pin >= 0) {
712 char npin[9];
713 char *generated_pin;
714
715 ret = os_snprintf(npin, sizeof(npin), "%08d", new_pin);
716 if (os_snprintf_error(sizeof(npin), ret)) {
717 reply = wpas_dbus_error_unknown_error(message,
718 "invalid PIN");
719 goto out;
720 }
721 generated_pin = npin;
722 reply = dbus_message_new_method_return(message);
723 dbus_message_append_args(reply, DBUS_TYPE_STRING,
724 &generated_pin, DBUS_TYPE_INVALID);
725 } else {
726 switch (new_pin) {
727 case -2:
728 err_msg =
729 "connect failed due to channel unavailability.";
730 iface = WPAS_DBUS_ERROR_CONNECT_CHANNEL_UNAVAILABLE;
731 break;
732
733 case -3:
734 err_msg = "connect failed due to unsupported channel.";
735 iface = WPAS_DBUS_ERROR_CONNECT_CHANNEL_UNSUPPORTED;
736 break;
737
738 default:
739 err_msg = "connect failed due to unspecified error.";
740 iface = WPAS_DBUS_ERROR_CONNECT_UNSPECIFIED_ERROR;
741 break;
742 }
743
744 /*
745 * TODO:
746 * Do we need specialized errors corresponding to above
747 * error conditions as against just returning a different
748 * error message?
749 */
750 reply = dbus_message_new_error(message, iface, err_msg);
751 }
752
753 out:
754 os_free(peer_object_path);
755 os_free(pin);
756 return reply;
757 inv_args_clear:
758 wpa_dbus_dict_entry_clear(&entry);
759 inv_args:
760 reply = wpas_dbus_error_invalid_args(message, NULL);
761 goto out;
762 }
763
764
765 /**
766 * wpas_dbus_handler_p2p_cancel - Cancel P2P group formation
767 * @message: Pointer to incoming dbus message
768 * @wpa_s: %wpa_supplicant data structure
769 * Returns: NULL on success or DBus error on failure
770 *
771 * Handler for "Cancel" method call. Returns NULL if P2P cancel succeeds or DBus
772 * error on P2P cancel failure
773 */
wpas_dbus_handler_p2p_cancel(DBusMessage * message,struct wpa_supplicant * wpa_s)774 DBusMessage * wpas_dbus_handler_p2p_cancel(DBusMessage *message,
775 struct wpa_supplicant *wpa_s)
776 {
777 if (wpas_p2p_cancel(wpa_s))
778 return wpas_dbus_error_unknown_error(message,
779 "P2P cancel failed");
780
781 return NULL;
782 }
783
784
wpas_dbus_handler_p2p_invite(DBusMessage * message,struct wpa_supplicant * wpa_s)785 DBusMessage * wpas_dbus_handler_p2p_invite(DBusMessage *message,
786 struct wpa_supplicant *wpa_s)
787 {
788 DBusMessageIter iter_dict;
789 DBusMessage *reply = NULL;
790 DBusMessageIter iter;
791 struct wpa_dbus_dict_entry entry;
792 char *peer_object_path = NULL;
793 char *pg_object_path = NULL;
794 char *iface = NULL;
795 u8 peer_addr[ETH_ALEN];
796 unsigned int group_id = 0;
797 int persistent = 0;
798 struct wpa_ssid *ssid;
799 const char *group_ifname;
800
801 if (!wpa_dbus_p2p_check_enabled(wpa_s, message, &reply, NULL))
802 return reply;
803
804 dbus_message_iter_init(message, &iter);
805
806 if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL))
807 goto err;
808
809 while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
810 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
811 goto err;
812
813 if (os_strcmp(entry.key, "peer") == 0 &&
814 entry.type == DBUS_TYPE_OBJECT_PATH) {
815 peer_object_path = os_strdup(entry.str_value);
816 wpa_dbus_dict_entry_clear(&entry);
817 } else if (os_strcmp(entry.key, "persistent_group_object") ==
818 0 &&
819 entry.type == DBUS_TYPE_OBJECT_PATH) {
820 pg_object_path = os_strdup(entry.str_value);
821 persistent = 1;
822 wpa_dbus_dict_entry_clear(&entry);
823 } else {
824 wpa_dbus_dict_entry_clear(&entry);
825 goto err;
826 }
827 }
828
829 if (parse_peer_object_path(peer_object_path, peer_addr) < 0 ||
830 !p2p_peer_known(wpa_s->global->p2p, peer_addr))
831 goto err;
832
833 /* Capture the interface name for the group first */
834 group_ifname = wpa_s->ifname;
835 wpa_s = wpa_s->global->p2p_init_wpa_s;
836
837 if (persistent) {
838 char *net_id_str;
839 /*
840 * A group ID is defined meaning we want to re-invoke a
841 * persistent group
842 */
843
844 iface = wpas_dbus_new_decompose_object_path(
845 pg_object_path,
846 WPAS_DBUS_NEW_PERSISTENT_GROUPS_PART,
847 &net_id_str);
848 if (iface == NULL || net_id_str == NULL ||
849 !wpa_s->parent->dbus_new_path ||
850 os_strcmp(iface, wpa_s->parent->dbus_new_path) != 0) {
851 reply = wpas_dbus_error_invalid_args(message,
852 pg_object_path);
853 goto out;
854 }
855
856 group_id = strtoul(net_id_str, NULL, 10);
857 if (errno == EINVAL) {
858 reply = wpas_dbus_error_invalid_args(
859 message, pg_object_path);
860 goto out;
861 }
862
863 /* Get the SSID structure from the persistent group id */
864 ssid = wpa_config_get_network(wpa_s->conf, group_id);
865 if (ssid == NULL || ssid->disabled != 2)
866 goto err;
867
868 if (wpas_p2p_invite(wpa_s, peer_addr, ssid, NULL, 0, 0, 0, 0, 0,
869 0, 0, 0, false) < 0) {
870 reply = wpas_dbus_error_unknown_error(
871 message,
872 "Failed to reinvoke a persistent group");
873 goto out;
874 }
875 } else {
876 /*
877 * No group ID means propose to a peer to join my active group
878 */
879 if (wpas_p2p_invite_group(wpa_s, group_ifname,
880 peer_addr, NULL, false)) {
881 reply = wpas_dbus_error_unknown_error(
882 message, "Failed to join to an active group");
883 goto out;
884 }
885 }
886
887 out:
888 os_free(iface);
889 os_free(pg_object_path);
890 os_free(peer_object_path);
891 return reply;
892
893 err:
894 reply = wpas_dbus_error_invalid_args(message, NULL);
895 goto out;
896 }
897
898
wpas_dbus_handler_p2p_prov_disc_req(DBusMessage * message,struct wpa_supplicant * wpa_s)899 DBusMessage * wpas_dbus_handler_p2p_prov_disc_req(DBusMessage *message,
900 struct wpa_supplicant *wpa_s)
901 {
902 DBusMessageIter iter;
903 char *peer_object_path = NULL;
904 char *config_method = NULL;
905 u8 peer_addr[ETH_ALEN];
906
907 dbus_message_iter_init(message, &iter);
908 dbus_message_iter_get_basic(&iter, &peer_object_path);
909
910 if (parse_peer_object_path(peer_object_path, peer_addr) < 0)
911 return wpas_dbus_error_invalid_args(message, NULL);
912
913 dbus_message_iter_next(&iter);
914 dbus_message_iter_get_basic(&iter, &config_method);
915
916 /*
917 * Validation checks on config_method are being duplicated here
918 * to be able to return invalid args reply since the error code
919 * from p2p module are not granular enough (yet).
920 */
921 if (os_strcmp(config_method, "display") &&
922 os_strcmp(config_method, "keypad") &&
923 os_strcmp(config_method, "pbc") &&
924 os_strcmp(config_method, "pushbutton"))
925 return wpas_dbus_error_invalid_args(message, NULL);
926
927 wpa_s = wpa_s->global->p2p_init_wpa_s;
928 if (!wpa_s)
929 return wpas_dbus_error_no_p2p_mgmt_iface(message);
930
931 if (wpas_p2p_prov_disc(wpa_s, peer_addr, config_method,
932 WPAS_P2P_PD_FOR_GO_NEG, NULL) < 0)
933 return wpas_dbus_error_unknown_error(message,
934 "Failed to send provision discovery request");
935
936 return NULL;
937 }
938
939
940 /*
941 * P2P Device property accessor methods.
942 */
943
wpas_dbus_getter_p2p_device_config(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)944 dbus_bool_t wpas_dbus_getter_p2p_device_config(
945 const struct wpa_dbus_property_desc *property_desc,
946 DBusMessageIter *iter, DBusError *error, void *user_data)
947 {
948 struct wpa_supplicant *wpa_s = user_data;
949 DBusMessageIter variant_iter, dict_iter;
950 DBusMessageIter iter_secdev_dict_entry, iter_secdev_dict_val,
951 iter_secdev_dict_array;
952 const char *dev_name;
953 int num_vendor_extensions = 0;
954 int i;
955 const struct wpabuf *vendor_ext[P2P_MAX_WPS_VENDOR_EXT];
956
957 if (!wpa_dbus_p2p_check_enabled(wpa_s, NULL, NULL, error))
958 return FALSE;
959
960 wpa_s = wpa_s->global->p2p_init_wpa_s;
961
962 if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT,
963 "a{sv}", &variant_iter) ||
964 !wpa_dbus_dict_open_write(&variant_iter, &dict_iter))
965 goto err_no_mem;
966
967 /* DeviceName */
968 dev_name = wpa_s->conf->device_name;
969 if (dev_name &&
970 !wpa_dbus_dict_append_string(&dict_iter, "DeviceName", dev_name))
971 goto err_no_mem;
972
973 /* Primary device type */
974 if (!wpa_dbus_dict_append_byte_array(&dict_iter, "PrimaryDeviceType",
975 (char *) wpa_s->conf->device_type,
976 WPS_DEV_TYPE_LEN))
977 goto err_no_mem;
978
979 /* Secondary device types */
980 if (wpa_s->conf->num_sec_device_types) {
981 if (!wpa_dbus_dict_begin_array(&dict_iter,
982 "SecondaryDeviceTypes",
983 DBUS_TYPE_ARRAY_AS_STRING
984 DBUS_TYPE_BYTE_AS_STRING,
985 &iter_secdev_dict_entry,
986 &iter_secdev_dict_val,
987 &iter_secdev_dict_array))
988 goto err_no_mem;
989
990 for (i = 0; i < wpa_s->conf->num_sec_device_types; i++)
991 wpa_dbus_dict_bin_array_add_element(
992 &iter_secdev_dict_array,
993 wpa_s->conf->sec_device_type[i],
994 WPS_DEV_TYPE_LEN);
995
996 if (!wpa_dbus_dict_end_array(&dict_iter,
997 &iter_secdev_dict_entry,
998 &iter_secdev_dict_val,
999 &iter_secdev_dict_array))
1000 goto err_no_mem;
1001 }
1002
1003 /* GO IP address */
1004 if (WPA_GET_BE32(wpa_s->conf->ip_addr_go) &&
1005 !wpa_dbus_dict_append_byte_array(&dict_iter, "IpAddrGo",
1006 (char *) wpa_s->conf->ip_addr_go,
1007 4))
1008 goto err_no_mem;
1009
1010 /* IP address mask */
1011 if (WPA_GET_BE32(wpa_s->conf->ip_addr_mask) &&
1012 !wpa_dbus_dict_append_byte_array(&dict_iter, "IpAddrMask",
1013 (char *) wpa_s->conf->ip_addr_mask,
1014 4))
1015 goto err_no_mem;
1016
1017 /* IP address start */
1018 if (WPA_GET_BE32(wpa_s->conf->ip_addr_start) &&
1019 !wpa_dbus_dict_append_byte_array(&dict_iter, "IpAddrStart",
1020 (char *)
1021 wpa_s->conf->ip_addr_start,
1022 4))
1023 goto err_no_mem;
1024
1025 /* IP address end */
1026 if (WPA_GET_BE32(wpa_s->conf->ip_addr_end) &&
1027 !wpa_dbus_dict_append_byte_array(&dict_iter, "IpAddrEnd",
1028 (char *) wpa_s->conf->ip_addr_end,
1029 4))
1030 goto err_no_mem;
1031
1032 /* Vendor Extensions */
1033 for (i = 0; i < P2P_MAX_WPS_VENDOR_EXT; i++) {
1034 if (wpa_s->conf->wps_vendor_ext[i] == NULL)
1035 continue;
1036 vendor_ext[num_vendor_extensions++] =
1037 wpa_s->conf->wps_vendor_ext[i];
1038 }
1039
1040 if ((num_vendor_extensions &&
1041 !wpa_dbus_dict_append_wpabuf_array(&dict_iter,
1042 "VendorExtension",
1043 vendor_ext,
1044 num_vendor_extensions)) ||
1045 !wpa_dbus_dict_append_uint32(&dict_iter, "GOIntent",
1046 wpa_s->conf->p2p_go_intent) ||
1047 !wpa_dbus_dict_append_bool(&dict_iter, "PersistentReconnect",
1048 wpa_s->conf->persistent_reconnect) ||
1049 !wpa_dbus_dict_append_uint32(&dict_iter, "ListenRegClass",
1050 wpa_s->conf->p2p_listen_reg_class) ||
1051 !wpa_dbus_dict_append_uint32(&dict_iter, "ListenChannel",
1052 wpa_s->conf->p2p_listen_channel) ||
1053 !wpa_dbus_dict_append_uint32(&dict_iter, "OperRegClass",
1054 wpa_s->conf->p2p_oper_reg_class) ||
1055 !wpa_dbus_dict_append_uint32(&dict_iter, "OperChannel",
1056 wpa_s->conf->p2p_oper_channel) ||
1057 (wpa_s->conf->p2p_ssid_postfix &&
1058 !wpa_dbus_dict_append_string(&dict_iter, "SsidPostfix",
1059 wpa_s->conf->p2p_ssid_postfix)) ||
1060 !wpa_dbus_dict_append_bool(&dict_iter, "IntraBss",
1061 wpa_s->conf->p2p_intra_bss) ||
1062 !wpa_dbus_dict_append_uint32(&dict_iter, "GroupIdle",
1063 wpa_s->conf->p2p_group_idle) ||
1064 !wpa_dbus_dict_append_uint32(&dict_iter, "disassoc_low_ack",
1065 wpa_s->conf->disassoc_low_ack) ||
1066 !wpa_dbus_dict_append_bool(&dict_iter, "NoGroupIface",
1067 wpa_s->conf->p2p_no_group_iface) ||
1068 !wpa_dbus_dict_append_uint32(&dict_iter, "p2p_search_delay",
1069 wpa_s->conf->p2p_search_delay) ||
1070 !wpa_dbus_dict_close_write(&variant_iter, &dict_iter) ||
1071 !dbus_message_iter_close_container(iter, &variant_iter))
1072 goto err_no_mem;
1073
1074 return TRUE;
1075
1076 err_no_mem:
1077 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
1078 return FALSE;
1079 }
1080
1081
wpas_dbus_setter_p2p_device_config(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)1082 dbus_bool_t wpas_dbus_setter_p2p_device_config(
1083 const struct wpa_dbus_property_desc *property_desc,
1084 DBusMessageIter *iter, DBusError *error, void *user_data)
1085 {
1086 struct wpa_supplicant *wpa_s = user_data;
1087 DBusMessageIter variant_iter, iter_dict;
1088 struct wpa_dbus_dict_entry entry = {.type = DBUS_TYPE_STRING };
1089 unsigned int i;
1090
1091 if (!wpa_dbus_p2p_check_enabled(wpa_s, NULL, NULL, error))
1092 return FALSE;
1093
1094 wpa_s = wpa_s->global->p2p_init_wpa_s;
1095
1096 dbus_message_iter_recurse(iter, &variant_iter);
1097 if (!wpa_dbus_dict_open_read(&variant_iter, &iter_dict, error))
1098 return FALSE;
1099
1100 while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
1101 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry)) {
1102 dbus_set_error_const(error, DBUS_ERROR_INVALID_ARGS,
1103 "invalid message format");
1104 return FALSE;
1105 }
1106
1107 if (os_strcmp(entry.key, "DeviceName") == 0) {
1108 char *devname;
1109
1110 if (entry.type != DBUS_TYPE_STRING ||
1111 os_strlen(entry.str_value) > WPS_DEV_NAME_MAX_LEN)
1112 goto error;
1113
1114 devname = os_strdup(entry.str_value);
1115 if (devname == NULL)
1116 goto err_no_mem_clear;
1117
1118 os_free(wpa_s->conf->device_name);
1119 wpa_s->conf->device_name = devname;
1120
1121 wpa_s->conf->changed_parameters |=
1122 CFG_CHANGED_DEVICE_NAME;
1123 } else if (os_strcmp(entry.key, "PrimaryDeviceType") == 0) {
1124 if (entry.type != DBUS_TYPE_ARRAY ||
1125 entry.array_type != DBUS_TYPE_BYTE ||
1126 entry.array_len != WPS_DEV_TYPE_LEN)
1127 goto error;
1128
1129 os_memcpy(wpa_s->conf->device_type,
1130 entry.bytearray_value,
1131 WPS_DEV_TYPE_LEN);
1132 wpa_s->conf->changed_parameters |=
1133 CFG_CHANGED_DEVICE_TYPE;
1134 } else if (os_strcmp(entry.key, "SecondaryDeviceTypes") == 0) {
1135 if (entry.type != DBUS_TYPE_ARRAY ||
1136 entry.array_type != WPAS_DBUS_TYPE_BINARRAY ||
1137 entry.array_len > MAX_SEC_DEVICE_TYPES)
1138 goto error;
1139
1140 for (i = 0; i < entry.array_len; i++)
1141 if (wpabuf_len(entry.binarray_value[i]) !=
1142 WPS_DEV_TYPE_LEN)
1143 goto err_no_mem_clear;
1144 for (i = 0; i < entry.array_len; i++)
1145 os_memcpy(wpa_s->conf->sec_device_type[i],
1146 wpabuf_head(entry.binarray_value[i]),
1147 WPS_DEV_TYPE_LEN);
1148 wpa_s->conf->num_sec_device_types = entry.array_len;
1149 wpa_s->conf->changed_parameters |=
1150 CFG_CHANGED_SEC_DEVICE_TYPE;
1151 } else if (os_strcmp(entry.key, "VendorExtension") == 0) {
1152 if (entry.type != DBUS_TYPE_ARRAY ||
1153 entry.array_type != WPAS_DBUS_TYPE_BINARRAY ||
1154 (entry.array_len > P2P_MAX_WPS_VENDOR_EXT))
1155 goto error;
1156
1157 wpa_s->conf->changed_parameters |=
1158 CFG_CHANGED_VENDOR_EXTENSION;
1159
1160 for (i = 0; i < P2P_MAX_WPS_VENDOR_EXT; i++) {
1161 wpabuf_free(wpa_s->conf->wps_vendor_ext[i]);
1162 if (i < entry.array_len) {
1163 wpa_s->conf->wps_vendor_ext[i] =
1164 entry.binarray_value[i];
1165 entry.binarray_value[i] = NULL;
1166 } else
1167 wpa_s->conf->wps_vendor_ext[i] = NULL;
1168 }
1169 } else if (os_strcmp(entry.key, "GOIntent") == 0 &&
1170 entry.type == DBUS_TYPE_UINT32 &&
1171 (entry.uint32_value <= 15))
1172 wpa_s->conf->p2p_go_intent = entry.uint32_value;
1173 else if (os_strcmp(entry.key, "PersistentReconnect") == 0 &&
1174 entry.type == DBUS_TYPE_BOOLEAN)
1175 wpa_s->conf->persistent_reconnect = entry.bool_value;
1176 else if (os_strcmp(entry.key, "ListenRegClass") == 0 &&
1177 entry.type == DBUS_TYPE_UINT32) {
1178 wpa_s->conf->p2p_listen_reg_class = entry.uint32_value;
1179 wpa_s->conf->changed_parameters |=
1180 CFG_CHANGED_P2P_LISTEN_CHANNEL;
1181 } else if (os_strcmp(entry.key, "ListenChannel") == 0 &&
1182 entry.type == DBUS_TYPE_UINT32) {
1183 wpa_s->conf->p2p_listen_channel = entry.uint32_value;
1184 wpa_s->conf->changed_parameters |=
1185 CFG_CHANGED_P2P_LISTEN_CHANNEL;
1186 } else if (os_strcmp(entry.key, "OperRegClass") == 0 &&
1187 entry.type == DBUS_TYPE_UINT32) {
1188 wpa_s->conf->p2p_oper_reg_class = entry.uint32_value;
1189 wpa_s->conf->changed_parameters |=
1190 CFG_CHANGED_P2P_OPER_CHANNEL;
1191 } else if (os_strcmp(entry.key, "OperChannel") == 0 &&
1192 entry.type == DBUS_TYPE_UINT32) {
1193 wpa_s->conf->p2p_oper_channel = entry.uint32_value;
1194 wpa_s->conf->changed_parameters |=
1195 CFG_CHANGED_P2P_OPER_CHANNEL;
1196 } else if (os_strcmp(entry.key, "SsidPostfix") == 0) {
1197 char *postfix;
1198
1199 if (entry.type != DBUS_TYPE_STRING)
1200 goto error;
1201
1202 postfix = os_strdup(entry.str_value);
1203 if (!postfix)
1204 goto err_no_mem_clear;
1205
1206 os_free(wpa_s->conf->p2p_ssid_postfix);
1207 wpa_s->conf->p2p_ssid_postfix = postfix;
1208
1209 wpa_s->conf->changed_parameters |=
1210 CFG_CHANGED_P2P_SSID_POSTFIX;
1211 } else if (os_strcmp(entry.key, "IntraBss") == 0 &&
1212 entry.type == DBUS_TYPE_BOOLEAN) {
1213 wpa_s->conf->p2p_intra_bss = entry.bool_value;
1214 wpa_s->conf->changed_parameters |=
1215 CFG_CHANGED_P2P_INTRA_BSS;
1216 } else if (os_strcmp(entry.key, "IpAddrGo") == 0) {
1217 if (!wpas_dbus_validate_dbus_ipaddr(entry))
1218 goto error;
1219 os_memcpy(wpa_s->conf->ip_addr_go,
1220 entry.bytearray_value, 4);
1221 } else if (os_strcmp(entry.key, "IpAddrMask") == 0) {
1222 if (!wpas_dbus_validate_dbus_ipaddr(entry))
1223 goto error;
1224 os_memcpy(wpa_s->conf->ip_addr_mask,
1225 entry.bytearray_value, 4);
1226 } else if (os_strcmp(entry.key, "IpAddrStart") == 0) {
1227 if (!wpas_dbus_validate_dbus_ipaddr(entry))
1228 goto error;
1229 os_memcpy(wpa_s->conf->ip_addr_start,
1230 entry.bytearray_value, 4);
1231 } else if (os_strcmp(entry.key, "IpAddrEnd") == 0) {
1232 if (!wpas_dbus_validate_dbus_ipaddr(entry))
1233 goto error;
1234 os_memcpy(wpa_s->conf->ip_addr_end,
1235 entry.bytearray_value, 4);
1236 } else if (os_strcmp(entry.key, "GroupIdle") == 0 &&
1237 entry.type == DBUS_TYPE_UINT32)
1238 wpa_s->conf->p2p_group_idle = entry.uint32_value;
1239 else if (os_strcmp(entry.key, "disassoc_low_ack") == 0 &&
1240 entry.type == DBUS_TYPE_UINT32)
1241 wpa_s->conf->disassoc_low_ack = entry.uint32_value;
1242 else if (os_strcmp(entry.key, "NoGroupIface") == 0 &&
1243 entry.type == DBUS_TYPE_BOOLEAN)
1244 wpa_s->conf->p2p_no_group_iface = entry.bool_value;
1245 else if (os_strcmp(entry.key, "p2p_search_delay") == 0 &&
1246 entry.type == DBUS_TYPE_UINT32)
1247 wpa_s->conf->p2p_search_delay = entry.uint32_value;
1248 else
1249 goto error;
1250
1251 wpa_dbus_dict_entry_clear(&entry);
1252 }
1253
1254 if (wpa_s->conf->changed_parameters) {
1255 /* Some changed parameters requires to update config*/
1256 wpa_supplicant_update_config(wpa_s);
1257 }
1258
1259 return TRUE;
1260
1261 error:
1262 dbus_set_error_const(error, DBUS_ERROR_INVALID_ARGS,
1263 "invalid message format");
1264 wpa_dbus_dict_entry_clear(&entry);
1265 return FALSE;
1266
1267 err_no_mem_clear:
1268 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
1269 wpa_dbus_dict_entry_clear(&entry);
1270 return FALSE;
1271 }
1272
1273
wpas_dbus_getter_p2p_peers(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)1274 dbus_bool_t wpas_dbus_getter_p2p_peers(
1275 const struct wpa_dbus_property_desc *property_desc,
1276 DBusMessageIter *iter, DBusError *error, void *user_data)
1277 {
1278 struct wpa_supplicant *wpa_s = user_data;
1279 struct p2p_data *p2p = wpa_s->global->p2p;
1280 int next = 0, i = 0;
1281 int num = 0, out_of_mem = 0;
1282 const u8 *addr;
1283 const struct p2p_peer_info *peer_info = NULL;
1284 dbus_bool_t success = FALSE;
1285
1286 struct dl_list peer_objpath_list;
1287 struct peer_objpath_node {
1288 struct dl_list list;
1289 char path[WPAS_DBUS_OBJECT_PATH_MAX];
1290 } *node, *tmp;
1291
1292 char **peer_obj_paths = NULL;
1293
1294 if (!wpa_dbus_p2p_check_enabled(wpa_s, NULL, NULL, error) ||
1295 !wpa_s->parent->parent->dbus_new_path)
1296 return FALSE;
1297
1298 dl_list_init(&peer_objpath_list);
1299
1300 /* Get the first peer info */
1301 peer_info = p2p_get_peer_found(p2p, NULL, next);
1302
1303 /* Get next and accumulate them */
1304 next = 1;
1305 while (peer_info != NULL) {
1306 node = os_zalloc(sizeof(struct peer_objpath_node));
1307 if (!node) {
1308 out_of_mem = 1;
1309 goto error;
1310 }
1311
1312 addr = peer_info->p2p_device_addr;
1313 os_snprintf(node->path, WPAS_DBUS_OBJECT_PATH_MAX,
1314 "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART
1315 "/" COMPACT_MACSTR,
1316 wpa_s->parent->parent->dbus_new_path,
1317 MAC2STR(addr));
1318 dl_list_add_tail(&peer_objpath_list, &node->list);
1319 num++;
1320
1321 peer_info = p2p_get_peer_found(p2p, addr, next);
1322 }
1323
1324 /*
1325 * Now construct the peer object paths in a form suitable for
1326 * array_property_getter helper below.
1327 */
1328 peer_obj_paths = os_calloc(num, sizeof(char *));
1329
1330 if (!peer_obj_paths) {
1331 out_of_mem = 1;
1332 goto error;
1333 }
1334
1335 dl_list_for_each_safe(node, tmp, &peer_objpath_list,
1336 struct peer_objpath_node, list)
1337 peer_obj_paths[i++] = node->path;
1338
1339 success = wpas_dbus_simple_array_property_getter(iter,
1340 DBUS_TYPE_OBJECT_PATH,
1341 peer_obj_paths, num,
1342 error);
1343
1344 error:
1345 if (peer_obj_paths)
1346 os_free(peer_obj_paths);
1347
1348 dl_list_for_each_safe(node, tmp, &peer_objpath_list,
1349 struct peer_objpath_node, list) {
1350 dl_list_del(&node->list);
1351 os_free(node);
1352 }
1353 if (out_of_mem)
1354 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
1355
1356 return success;
1357 }
1358
1359
1360 enum wpas_p2p_role {
1361 WPAS_P2P_ROLE_DEVICE,
1362 WPAS_P2P_ROLE_GO,
1363 WPAS_P2P_ROLE_CLIENT,
1364 };
1365
wpas_get_p2p_role(struct wpa_supplicant * wpa_s)1366 static enum wpas_p2p_role wpas_get_p2p_role(struct wpa_supplicant *wpa_s)
1367 {
1368 struct wpa_ssid *ssid = wpa_s->current_ssid;
1369
1370 if (!ssid)
1371 return WPAS_P2P_ROLE_DEVICE;
1372 if (wpa_s->wpa_state != WPA_COMPLETED)
1373 return WPAS_P2P_ROLE_DEVICE;
1374
1375 switch (ssid->mode) {
1376 case WPAS_MODE_P2P_GO:
1377 case WPAS_MODE_P2P_GROUP_FORMATION:
1378 return WPAS_P2P_ROLE_GO;
1379 case WPAS_MODE_INFRA:
1380 if (ssid->p2p_group)
1381 return WPAS_P2P_ROLE_CLIENT;
1382 return WPAS_P2P_ROLE_DEVICE;
1383 default:
1384 return WPAS_P2P_ROLE_DEVICE;
1385 }
1386 }
1387
1388
wpas_dbus_getter_p2p_role(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)1389 dbus_bool_t wpas_dbus_getter_p2p_role(
1390 const struct wpa_dbus_property_desc *property_desc,
1391 DBusMessageIter *iter, DBusError *error, void *user_data)
1392 {
1393 struct wpa_supplicant *wpa_s = user_data;
1394 char *str;
1395
1396 switch (wpas_get_p2p_role(wpa_s)) {
1397 case WPAS_P2P_ROLE_GO:
1398 str = "GO";
1399 break;
1400 case WPAS_P2P_ROLE_CLIENT:
1401 str = "client";
1402 break;
1403 default:
1404 str = "device";
1405 break;
1406 }
1407
1408 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING, &str,
1409 error);
1410 }
1411
1412
wpas_dbus_getter_p2p_group(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)1413 dbus_bool_t wpas_dbus_getter_p2p_group(
1414 const struct wpa_dbus_property_desc *property_desc,
1415 DBusMessageIter *iter, DBusError *error, void *user_data)
1416 {
1417 struct wpa_supplicant *wpa_s = user_data;
1418 char path_buf[WPAS_DBUS_OBJECT_PATH_MAX];
1419 char *dbus_groupobj_path = path_buf;
1420
1421 if (wpa_s->dbus_groupobj_path == NULL)
1422 os_snprintf(dbus_groupobj_path, WPAS_DBUS_OBJECT_PATH_MAX,
1423 "/");
1424 else
1425 os_snprintf(dbus_groupobj_path, WPAS_DBUS_OBJECT_PATH_MAX,
1426 "%s", wpa_s->dbus_groupobj_path);
1427
1428 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_OBJECT_PATH,
1429 &dbus_groupobj_path, error);
1430 }
1431
1432
wpas_dbus_getter_p2p_peergo(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)1433 dbus_bool_t wpas_dbus_getter_p2p_peergo(
1434 const struct wpa_dbus_property_desc *property_desc,
1435 DBusMessageIter *iter, DBusError *error, void *user_data)
1436 {
1437 struct wpa_supplicant *wpa_s = user_data;
1438 char go_peer_obj_path[WPAS_DBUS_OBJECT_PATH_MAX], *path;
1439
1440 if (!wpa_s->parent->parent->dbus_new_path)
1441 return FALSE;
1442
1443 if (wpas_get_p2p_role(wpa_s) != WPAS_P2P_ROLE_CLIENT)
1444 os_snprintf(go_peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX, "/");
1445 else
1446 os_snprintf(go_peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
1447 "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART "/"
1448 COMPACT_MACSTR,
1449 wpa_s->parent->parent->dbus_new_path,
1450 MAC2STR(wpa_s->go_dev_addr));
1451
1452 path = go_peer_obj_path;
1453 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_OBJECT_PATH,
1454 &path, error);
1455 }
1456
1457
1458 /*
1459 * Peer object properties accessor methods
1460 */
1461
wpas_dbus_getter_p2p_peer_device_name(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)1462 dbus_bool_t wpas_dbus_getter_p2p_peer_device_name(
1463 const struct wpa_dbus_property_desc *property_desc,
1464 DBusMessageIter *iter, DBusError *error, void *user_data)
1465 {
1466 struct peer_handler_args *peer_args = user_data;
1467 const struct p2p_peer_info *info;
1468 char *tmp;
1469
1470 if (!wpa_dbus_p2p_check_enabled(peer_args->wpa_s, NULL, NULL, error))
1471 return FALSE;
1472
1473 /* get the peer info */
1474 info = p2p_get_peer_found(peer_args->wpa_s->global->p2p,
1475 peer_args->p2p_device_addr, 0);
1476 if (info == NULL) {
1477 dbus_set_error(error, DBUS_ERROR_FAILED,
1478 "failed to find peer");
1479 return FALSE;
1480 }
1481
1482 tmp = os_strdup(info->device_name);
1483 if (!tmp) {
1484 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
1485 return FALSE;
1486 }
1487
1488 if (!wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING, &tmp,
1489 error)) {
1490 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
1491 os_free(tmp);
1492 return FALSE;
1493 }
1494
1495 os_free(tmp);
1496 return TRUE;
1497 }
1498
1499
wpas_dbus_getter_p2p_peer_manufacturer(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)1500 dbus_bool_t wpas_dbus_getter_p2p_peer_manufacturer(
1501 const struct wpa_dbus_property_desc *property_desc,
1502 DBusMessageIter *iter, DBusError *error, void *user_data)
1503 {
1504 struct peer_handler_args *peer_args = user_data;
1505 const struct p2p_peer_info *info;
1506 char *tmp;
1507
1508 if (!wpa_dbus_p2p_check_enabled(peer_args->wpa_s, NULL, NULL, error))
1509 return FALSE;
1510
1511 /* get the peer info */
1512 info = p2p_get_peer_found(peer_args->wpa_s->global->p2p,
1513 peer_args->p2p_device_addr, 0);
1514 if (info == NULL) {
1515 dbus_set_error(error, DBUS_ERROR_FAILED, "failed to find peer");
1516 return FALSE;
1517 }
1518
1519 tmp = os_strdup(info->manufacturer);
1520 if (!tmp) {
1521 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
1522 return FALSE;
1523 }
1524
1525 if (!wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING, &tmp,
1526 error)) {
1527 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
1528 os_free(tmp);
1529 return FALSE;
1530 }
1531
1532 os_free(tmp);
1533 return TRUE;
1534 }
1535
1536
wpas_dbus_getter_p2p_peer_modelname(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)1537 dbus_bool_t wpas_dbus_getter_p2p_peer_modelname(
1538 const struct wpa_dbus_property_desc *property_desc,
1539 DBusMessageIter *iter, DBusError *error, void *user_data)
1540 {
1541 struct peer_handler_args *peer_args = user_data;
1542 const struct p2p_peer_info *info;
1543 char *tmp;
1544
1545 if (!wpa_dbus_p2p_check_enabled(peer_args->wpa_s, NULL, NULL, error))
1546 return FALSE;
1547
1548 /* get the peer info */
1549 info = p2p_get_peer_found(peer_args->wpa_s->global->p2p,
1550 peer_args->p2p_device_addr, 0);
1551 if (info == NULL) {
1552 dbus_set_error(error, DBUS_ERROR_FAILED, "failed to find peer");
1553 return FALSE;
1554 }
1555
1556 tmp = os_strdup(info->model_name);
1557 if (!tmp) {
1558 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
1559 return FALSE;
1560 }
1561
1562 if (!wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING, &tmp,
1563 error)) {
1564 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
1565 os_free(tmp);
1566 return FALSE;
1567 }
1568
1569 os_free(tmp);
1570 return TRUE;
1571 }
1572
1573
wpas_dbus_getter_p2p_peer_modelnumber(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)1574 dbus_bool_t wpas_dbus_getter_p2p_peer_modelnumber(
1575 const struct wpa_dbus_property_desc *property_desc,
1576 DBusMessageIter *iter, DBusError *error, void *user_data)
1577 {
1578 struct peer_handler_args *peer_args = user_data;
1579 const struct p2p_peer_info *info;
1580 char *tmp;
1581
1582 if (!wpa_dbus_p2p_check_enabled(peer_args->wpa_s, NULL, NULL, error))
1583 return FALSE;
1584
1585 /* get the peer info */
1586 info = p2p_get_peer_found(peer_args->wpa_s->global->p2p,
1587 peer_args->p2p_device_addr, 0);
1588 if (info == NULL) {
1589 dbus_set_error(error, DBUS_ERROR_FAILED, "failed to find peer");
1590 return FALSE;
1591 }
1592
1593 tmp = os_strdup(info->model_number);
1594 if (!tmp) {
1595 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
1596 return FALSE;
1597 }
1598
1599 if (!wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING, &tmp,
1600 error)) {
1601 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
1602 os_free(tmp);
1603 return FALSE;
1604 }
1605
1606 os_free(tmp);
1607 return TRUE;
1608 }
1609
1610
wpas_dbus_getter_p2p_peer_serialnumber(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)1611 dbus_bool_t wpas_dbus_getter_p2p_peer_serialnumber(
1612 const struct wpa_dbus_property_desc *property_desc,
1613 DBusMessageIter *iter, DBusError *error, void *user_data)
1614 {
1615 struct peer_handler_args *peer_args = user_data;
1616 const struct p2p_peer_info *info;
1617 char *tmp;
1618
1619 if (!wpa_dbus_p2p_check_enabled(peer_args->wpa_s, NULL, NULL, error))
1620 return FALSE;
1621
1622 /* get the peer info */
1623 info = p2p_get_peer_found(peer_args->wpa_s->global->p2p,
1624 peer_args->p2p_device_addr, 0);
1625 if (info == NULL) {
1626 dbus_set_error(error, DBUS_ERROR_FAILED, "failed to find peer");
1627 return FALSE;
1628 }
1629
1630 tmp = os_strdup(info->serial_number);
1631 if (!tmp) {
1632 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
1633 return FALSE;
1634 }
1635
1636 if (!wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING, &tmp,
1637 error)) {
1638 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
1639 os_free(tmp);
1640 return FALSE;
1641 }
1642
1643 os_free(tmp);
1644 return TRUE;
1645 }
1646
1647
wpas_dbus_getter_p2p_peer_primary_device_type(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)1648 dbus_bool_t wpas_dbus_getter_p2p_peer_primary_device_type(
1649 const struct wpa_dbus_property_desc *property_desc,
1650 DBusMessageIter *iter, DBusError *error, void *user_data)
1651 {
1652 struct peer_handler_args *peer_args = user_data;
1653 const struct p2p_peer_info *info;
1654
1655 info = p2p_get_peer_found(peer_args->wpa_s->global->p2p,
1656 peer_args->p2p_device_addr, 0);
1657 if (info == NULL) {
1658 dbus_set_error(error, DBUS_ERROR_FAILED,
1659 "failed to find peer");
1660 return FALSE;
1661 }
1662
1663 if (!wpas_dbus_simple_array_property_getter(iter, DBUS_TYPE_BYTE,
1664 (char *)
1665 info->pri_dev_type,
1666 WPS_DEV_TYPE_LEN, error)) {
1667 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
1668 return FALSE;
1669 }
1670
1671 return TRUE;
1672 }
1673
1674
wpas_dbus_getter_p2p_peer_config_method(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)1675 dbus_bool_t wpas_dbus_getter_p2p_peer_config_method(
1676 const struct wpa_dbus_property_desc *property_desc,
1677 DBusMessageIter *iter, DBusError *error, void *user_data)
1678 {
1679 struct peer_handler_args *peer_args = user_data;
1680 const struct p2p_peer_info *info;
1681
1682 info = p2p_get_peer_found(peer_args->wpa_s->global->p2p,
1683 peer_args->p2p_device_addr, 0);
1684 if (info == NULL) {
1685 dbus_set_error(error, DBUS_ERROR_FAILED,
1686 "failed to find peer");
1687 return FALSE;
1688 }
1689
1690 if (!wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT16,
1691 &info->config_methods, error)) {
1692 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
1693 return FALSE;
1694 }
1695
1696 return TRUE;
1697 }
1698
1699
wpas_dbus_getter_p2p_peer_level(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)1700 dbus_bool_t wpas_dbus_getter_p2p_peer_level(
1701 const struct wpa_dbus_property_desc *property_desc,
1702 DBusMessageIter *iter, DBusError *error, void *user_data)
1703 {
1704 struct peer_handler_args *peer_args = user_data;
1705 const struct p2p_peer_info *info;
1706
1707 info = p2p_get_peer_found(peer_args->wpa_s->global->p2p,
1708 peer_args->p2p_device_addr, 0);
1709 if (info == NULL) {
1710 dbus_set_error(error, DBUS_ERROR_FAILED,
1711 "failed to find peer");
1712 return FALSE;
1713 }
1714
1715 if (!wpas_dbus_simple_property_getter(iter, DBUS_TYPE_INT32,
1716 &info->level, error)) {
1717 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
1718 return FALSE;
1719 }
1720
1721 return TRUE;
1722 }
1723
1724
wpas_dbus_getter_p2p_peer_device_capability(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)1725 dbus_bool_t wpas_dbus_getter_p2p_peer_device_capability(
1726 const struct wpa_dbus_property_desc *property_desc,
1727 DBusMessageIter *iter, DBusError *error, void *user_data)
1728 {
1729 struct peer_handler_args *peer_args = user_data;
1730 const struct p2p_peer_info *info;
1731
1732 info = p2p_get_peer_found(peer_args->wpa_s->global->p2p,
1733 peer_args->p2p_device_addr, 0);
1734 if (info == NULL) {
1735 dbus_set_error(error, DBUS_ERROR_FAILED,
1736 "failed to find peer");
1737 return FALSE;
1738 }
1739
1740 if (!wpas_dbus_simple_property_getter(iter, DBUS_TYPE_BYTE,
1741 &info->dev_capab, error)) {
1742 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
1743 return FALSE;
1744 }
1745
1746 return TRUE;
1747 }
1748
1749
wpas_dbus_getter_p2p_peer_group_capability(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)1750 dbus_bool_t wpas_dbus_getter_p2p_peer_group_capability(
1751 const struct wpa_dbus_property_desc *property_desc,
1752 DBusMessageIter *iter, DBusError *error, void *user_data)
1753 {
1754 struct peer_handler_args *peer_args = user_data;
1755 const struct p2p_peer_info *info;
1756
1757 info = p2p_get_peer_found(peer_args->wpa_s->global->p2p,
1758 peer_args->p2p_device_addr, 0);
1759 if (info == NULL) {
1760 dbus_set_error(error, DBUS_ERROR_FAILED,
1761 "failed to find peer");
1762 return FALSE;
1763 }
1764
1765 if (!wpas_dbus_simple_property_getter(iter, DBUS_TYPE_BYTE,
1766 &info->group_capab, error)) {
1767 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
1768 return FALSE;
1769 }
1770
1771 return TRUE;
1772 }
1773
1774
wpas_dbus_getter_p2p_peer_secondary_device_types(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)1775 dbus_bool_t wpas_dbus_getter_p2p_peer_secondary_device_types(
1776 const struct wpa_dbus_property_desc *property_desc,
1777 DBusMessageIter *iter, DBusError *error, void *user_data)
1778 {
1779 struct peer_handler_args *peer_args = user_data;
1780 const struct p2p_peer_info *info;
1781 DBusMessageIter variant_iter, array_iter;
1782
1783 info = p2p_get_peer_found(peer_args->wpa_s->global->p2p,
1784 peer_args->p2p_device_addr, 0);
1785 if (info == NULL) {
1786 dbus_set_error(error, DBUS_ERROR_FAILED, "failed to find peer");
1787 return FALSE;
1788 }
1789
1790 if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT,
1791 DBUS_TYPE_ARRAY_AS_STRING
1792 DBUS_TYPE_ARRAY_AS_STRING
1793 DBUS_TYPE_BYTE_AS_STRING,
1794 &variant_iter) ||
1795 !dbus_message_iter_open_container(&variant_iter, DBUS_TYPE_ARRAY,
1796 DBUS_TYPE_ARRAY_AS_STRING
1797 DBUS_TYPE_BYTE_AS_STRING,
1798 &array_iter)) {
1799 dbus_set_error(error, DBUS_ERROR_FAILED,
1800 "%s: failed to construct message 1", __func__);
1801 return FALSE;
1802 }
1803
1804 if (info->wps_sec_dev_type_list_len) {
1805 const u8 *sec_dev_type_list = info->wps_sec_dev_type_list;
1806 int num_sec_device_types =
1807 info->wps_sec_dev_type_list_len / WPS_DEV_TYPE_LEN;
1808 int i;
1809 DBusMessageIter inner_array_iter;
1810
1811 for (i = 0; i < num_sec_device_types; i++) {
1812 if (!dbus_message_iter_open_container(
1813 &array_iter, DBUS_TYPE_ARRAY,
1814 DBUS_TYPE_BYTE_AS_STRING,
1815 &inner_array_iter) ||
1816 !dbus_message_iter_append_fixed_array(
1817 &inner_array_iter, DBUS_TYPE_BYTE,
1818 &sec_dev_type_list, WPS_DEV_TYPE_LEN) ||
1819 !dbus_message_iter_close_container(
1820 &array_iter, &inner_array_iter)) {
1821 dbus_set_error(error, DBUS_ERROR_FAILED,
1822 "%s: failed to construct message 2 (%d)",
1823 __func__, i);
1824 return FALSE;
1825 }
1826
1827 sec_dev_type_list += WPS_DEV_TYPE_LEN;
1828 }
1829 }
1830
1831 if (!dbus_message_iter_close_container(&variant_iter, &array_iter) ||
1832 !dbus_message_iter_close_container(iter, &variant_iter)) {
1833 dbus_set_error(error, DBUS_ERROR_FAILED,
1834 "%s: failed to construct message 3", __func__);
1835 return FALSE;
1836 }
1837
1838 return TRUE;
1839 }
1840
1841
wpas_dbus_getter_p2p_peer_vendor_extension(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)1842 dbus_bool_t wpas_dbus_getter_p2p_peer_vendor_extension(
1843 const struct wpa_dbus_property_desc *property_desc,
1844 DBusMessageIter *iter, DBusError *error, void *user_data)
1845 {
1846 struct wpabuf *vendor_extension[P2P_MAX_WPS_VENDOR_EXT];
1847 unsigned int i, num = 0;
1848 struct peer_handler_args *peer_args = user_data;
1849 const struct p2p_peer_info *info;
1850
1851 info = p2p_get_peer_found(peer_args->wpa_s->global->p2p,
1852 peer_args->p2p_device_addr, 0);
1853 if (info == NULL) {
1854 dbus_set_error(error, DBUS_ERROR_FAILED,
1855 "failed to find peer");
1856 return FALSE;
1857 }
1858
1859 /* Add WPS vendor extensions attribute */
1860 os_memset(vendor_extension, 0, sizeof(vendor_extension));
1861 for (i = 0; i < P2P_MAX_WPS_VENDOR_EXT; i++) {
1862 if (info->wps_vendor_ext[i] == NULL)
1863 continue;
1864 vendor_extension[num] = info->wps_vendor_ext[i];
1865 num++;
1866 }
1867
1868 if (!wpas_dbus_simple_array_array_property_getter(iter, DBUS_TYPE_BYTE,
1869 vendor_extension,
1870 num, error))
1871 return FALSE;
1872
1873 return TRUE;
1874 }
1875
1876
wpas_dbus_getter_p2p_peer_ies(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)1877 dbus_bool_t wpas_dbus_getter_p2p_peer_ies(
1878 const struct wpa_dbus_property_desc *property_desc,
1879 DBusMessageIter *iter, DBusError *error, void *user_data)
1880 {
1881 struct peer_handler_args *peer_args = user_data;
1882 const struct p2p_peer_info *info;
1883
1884 info = p2p_get_peer_found(peer_args->wpa_s->global->p2p,
1885 peer_args->p2p_device_addr, 0);
1886 if (info == NULL) {
1887 dbus_set_error(error, DBUS_ERROR_FAILED,
1888 "failed to find peer");
1889 return FALSE;
1890 }
1891
1892 if (info->wfd_subelems == NULL)
1893 return wpas_dbus_simple_array_property_getter(iter,
1894 DBUS_TYPE_BYTE,
1895 NULL, 0, error);
1896
1897 return wpas_dbus_simple_array_property_getter(
1898 iter, DBUS_TYPE_BYTE, (char *) info->wfd_subelems->buf,
1899 info->wfd_subelems->used, error);
1900 }
1901
1902
wpas_dbus_getter_p2p_peer_device_address(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)1903 dbus_bool_t wpas_dbus_getter_p2p_peer_device_address(
1904 const struct wpa_dbus_property_desc *property_desc,
1905 DBusMessageIter *iter, DBusError *error, void *user_data)
1906 {
1907 struct peer_handler_args *peer_args = user_data;
1908 const struct p2p_peer_info *info;
1909
1910 info = p2p_get_peer_found(peer_args->wpa_s->global->p2p,
1911 peer_args->p2p_device_addr, 0);
1912 if (info == NULL) {
1913 dbus_set_error(error, DBUS_ERROR_FAILED,
1914 "failed to find peer");
1915 return FALSE;
1916 }
1917
1918 return wpas_dbus_simple_array_property_getter(
1919 iter, DBUS_TYPE_BYTE, (char *) info->p2p_device_addr,
1920 ETH_ALEN, error);
1921 }
1922
1923
1924 struct peer_group_data {
1925 struct wpa_supplicant *wpa_s;
1926 const struct p2p_peer_info *info;
1927 char **paths;
1928 unsigned int nb_paths;
1929 int error;
1930 };
1931
1932
match_group_where_peer_is_client(struct p2p_group * group,void * user_data)1933 static int match_group_where_peer_is_client(struct p2p_group *group,
1934 void *user_data)
1935 {
1936 struct peer_group_data *data = user_data;
1937 const struct p2p_group_config *cfg;
1938 struct wpa_supplicant *wpa_s_go;
1939 char **paths;
1940
1941 if (!p2p_group_is_client_connected(group, data->info->p2p_device_addr))
1942 return 1;
1943
1944 cfg = p2p_group_get_config(group);
1945
1946 wpa_s_go = wpas_get_p2p_go_iface(data->wpa_s, cfg->ssid,
1947 cfg->ssid_len);
1948 if (wpa_s_go == NULL)
1949 return 1;
1950
1951 paths = os_realloc_array(data->paths, data->nb_paths + 1,
1952 sizeof(char *));
1953 if (paths == NULL)
1954 goto out_of_memory;
1955
1956 data->paths = paths;
1957 data->paths[data->nb_paths] = wpa_s_go->dbus_groupobj_path;
1958 data->nb_paths++;
1959
1960 return 1;
1961
1962 out_of_memory:
1963 data->error = ENOMEM;
1964 return 0;
1965 }
1966
1967
wpas_dbus_getter_p2p_peer_groups(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)1968 dbus_bool_t wpas_dbus_getter_p2p_peer_groups(
1969 const struct wpa_dbus_property_desc *property_desc,
1970 DBusMessageIter *iter, DBusError *error, void *user_data)
1971 {
1972 struct peer_handler_args *peer_args = user_data;
1973 const struct p2p_peer_info *info;
1974 struct peer_group_data data;
1975 struct wpa_supplicant *wpa_s, *wpa_s_go;
1976 dbus_bool_t success = FALSE;
1977
1978 info = p2p_get_peer_found(peer_args->wpa_s->global->p2p,
1979 peer_args->p2p_device_addr, 0);
1980 if (info == NULL) {
1981 dbus_set_error(error, DBUS_ERROR_FAILED,
1982 "failed to find peer");
1983 return FALSE;
1984 }
1985
1986 os_memset(&data, 0, sizeof(data));
1987
1988 wpa_s = peer_args->wpa_s;
1989 wpa_s = wpa_s->global->p2p_init_wpa_s;
1990 if (!wpa_s)
1991 return no_p2p_mgmt_interface(error);
1992
1993 wpa_s_go = wpas_get_p2p_client_iface(wpa_s, info->p2p_device_addr);
1994 if (wpa_s_go) {
1995 data.paths = os_calloc(1, sizeof(char *));
1996 if (data.paths == NULL)
1997 goto out_of_memory;
1998 data.paths[0] = wpa_s_go->dbus_groupobj_path;
1999 data.nb_paths = 1;
2000 }
2001
2002 data.wpa_s = peer_args->wpa_s;
2003 data.info = info;
2004
2005 p2p_loop_on_all_groups(peer_args->wpa_s->global->p2p,
2006 match_group_where_peer_is_client, &data);
2007 if (data.error)
2008 goto out_of_memory;
2009
2010 if (data.paths == NULL) {
2011 return wpas_dbus_simple_array_property_getter(
2012 iter, DBUS_TYPE_OBJECT_PATH, NULL, 0, error);
2013 }
2014
2015 success = wpas_dbus_simple_array_property_getter(iter,
2016 DBUS_TYPE_OBJECT_PATH,
2017 data.paths,
2018 data.nb_paths, error);
2019 goto out;
2020
2021 out_of_memory:
2022 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
2023 out:
2024 os_free(data.paths);
2025 return success;
2026 }
2027
wpas_dbus_getter_p2p_peer_vsie(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)2028 dbus_bool_t wpas_dbus_getter_p2p_peer_vsie(
2029 const struct wpa_dbus_property_desc *property_desc,
2030 DBusMessageIter *iter, DBusError *error, void *user_data)
2031 {
2032 struct peer_handler_args *peer_args = user_data;
2033 const struct p2p_peer_info *info;
2034
2035 info = p2p_get_peer_found(peer_args->wpa_s->global->p2p,
2036 peer_args->p2p_device_addr, 0);
2037 if (!info) {
2038 dbus_set_error(error, DBUS_ERROR_FAILED, "failed to find peer");
2039 return FALSE;
2040 }
2041
2042 if (!info->vendor_elems)
2043 return wpas_dbus_simple_array_property_getter(iter,
2044 DBUS_TYPE_BYTE,
2045 NULL, 0, error);
2046
2047 return wpas_dbus_simple_array_property_getter(
2048 iter, DBUS_TYPE_BYTE, (char *) info->vendor_elems->buf,
2049 info->vendor_elems->used, error);
2050 }
2051
2052
2053 /**
2054 * wpas_dbus_getter_persistent_groups - Get array of persistent group objects
2055 * @iter: Pointer to incoming dbus message iter
2056 * @error: Location to store error on failure
2057 * @user_data: Function specific data
2058 * Returns: TRUE on success, FALSE on failure
2059 *
2060 * Getter for "PersistentGroups" property.
2061 */
wpas_dbus_getter_persistent_groups(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)2062 dbus_bool_t wpas_dbus_getter_persistent_groups(
2063 const struct wpa_dbus_property_desc *property_desc,
2064 DBusMessageIter *iter, DBusError *error, void *user_data)
2065 {
2066 struct wpa_supplicant *wpa_s = user_data;
2067 struct wpa_ssid *ssid;
2068 char **paths;
2069 unsigned int i = 0, num = 0;
2070 dbus_bool_t success = FALSE;
2071
2072 wpa_s = wpa_s->global->p2p_init_wpa_s;
2073 if (!wpa_s)
2074 return no_p2p_mgmt_interface(error);
2075
2076 if (!wpa_s->parent->dbus_new_path)
2077 return FALSE;
2078
2079 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
2080 if (network_is_persistent_group(ssid))
2081 num++;
2082
2083 paths = os_calloc(num, sizeof(char *));
2084 if (!paths) {
2085 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
2086 return FALSE;
2087 }
2088
2089 /* Loop through configured networks and append object path of each */
2090 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
2091 if (!network_is_persistent_group(ssid))
2092 continue;
2093 paths[i] = os_zalloc(WPAS_DBUS_OBJECT_PATH_MAX);
2094 if (paths[i] == NULL) {
2095 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY,
2096 "no memory");
2097 goto out;
2098 }
2099 /* Construct the object path for this network. */
2100 os_snprintf(paths[i++], WPAS_DBUS_OBJECT_PATH_MAX,
2101 "%s/" WPAS_DBUS_NEW_PERSISTENT_GROUPS_PART "/%d",
2102 wpa_s->parent->dbus_new_path, ssid->id);
2103 }
2104
2105 success = wpas_dbus_simple_array_property_getter(iter,
2106 DBUS_TYPE_OBJECT_PATH,
2107 paths, num, error);
2108
2109 out:
2110 while (i)
2111 os_free(paths[--i]);
2112 os_free(paths);
2113 return success;
2114 }
2115
2116
2117 /**
2118 * wpas_dbus_getter_persistent_group_properties - Get options for a persistent
2119 * group
2120 * @iter: Pointer to incoming dbus message iter
2121 * @error: Location to store error on failure
2122 * @user_data: Function specific data
2123 * Returns: TRUE on success, FALSE on failure
2124 *
2125 * Getter for "Properties" property of a persistent group.
2126 */
wpas_dbus_getter_persistent_group_properties(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)2127 dbus_bool_t wpas_dbus_getter_persistent_group_properties(
2128 const struct wpa_dbus_property_desc *property_desc,
2129 DBusMessageIter *iter, DBusError *error, void *user_data)
2130 {
2131 struct network_handler_args *net = user_data;
2132
2133 /* Leveraging the fact that persistent group object is still
2134 * represented in same manner as network within.
2135 */
2136 return wpas_dbus_getter_network_properties(property_desc, iter, error, net);
2137 }
2138
2139
2140 /**
2141 * wpas_dbus_setter_persistent_group_properties - Set options for a persistent
2142 * group
2143 * @iter: Pointer to incoming dbus message iter
2144 * @error: Location to store error on failure
2145 * @user_data: Function specific data
2146 * Returns: TRUE on success, FALSE on failure
2147 *
2148 * Setter for "Properties" property of a persistent group.
2149 */
wpas_dbus_setter_persistent_group_properties(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)2150 dbus_bool_t wpas_dbus_setter_persistent_group_properties(
2151 const struct wpa_dbus_property_desc *property_desc,
2152 DBusMessageIter *iter, DBusError *error, void *user_data)
2153 {
2154 struct network_handler_args *net = user_data;
2155 struct wpa_ssid *ssid = net->ssid;
2156 DBusMessageIter variant_iter;
2157
2158 /*
2159 * Leveraging the fact that persistent group object is still
2160 * represented in same manner as network within.
2161 */
2162 dbus_message_iter_recurse(iter, &variant_iter);
2163 return set_network_properties(net->wpa_s, ssid, &variant_iter, error);
2164 }
2165
2166
2167 /**
2168 * wpas_dbus_new_iface_add_persistent_group - Add a new configured
2169 * persistent_group
2170 * @message: Pointer to incoming dbus message
2171 * @wpa_s: wpa_supplicant structure for a network interface
2172 * Returns: A dbus message containing the object path of the new
2173 * persistent group
2174 *
2175 * Handler function for "AddPersistentGroup" method call of a P2P Device
2176 * interface.
2177 */
wpas_dbus_handler_add_persistent_group(DBusMessage * message,struct wpa_supplicant * wpa_s)2178 DBusMessage * wpas_dbus_handler_add_persistent_group(
2179 DBusMessage *message, struct wpa_supplicant *wpa_s)
2180 {
2181 DBusMessage *reply = NULL;
2182 DBusMessageIter iter;
2183 struct wpa_ssid *ssid = NULL;
2184 char path_buf[WPAS_DBUS_OBJECT_PATH_MAX], *path = path_buf;
2185 DBusError error;
2186
2187 dbus_message_iter_init(message, &iter);
2188
2189 wpa_s = wpa_s->global->p2p_init_wpa_s;
2190 if (!wpa_s) {
2191 reply = wpas_dbus_error_no_p2p_mgmt_iface(message);
2192 goto err;
2193 }
2194
2195 if (wpa_s->parent->dbus_new_path)
2196 ssid = wpa_config_add_network(wpa_s->conf);
2197 if (ssid == NULL) {
2198 wpa_printf(MSG_ERROR,
2199 "dbus: %s: Cannot add new persistent group",
2200 __func__);
2201 reply = wpas_dbus_error_unknown_error(
2202 message,
2203 "wpa_supplicant could not add a persistent group on this interface.");
2204 goto err;
2205 }
2206
2207 /* Mark the ssid as being a persistent group before the notification */
2208 ssid->disabled = 2;
2209 ssid->p2p_persistent_group = 1;
2210 wpas_notify_persistent_group_added(wpa_s, ssid);
2211
2212 wpa_config_set_network_defaults(ssid);
2213
2214 dbus_error_init(&error);
2215 if (!set_network_properties(wpa_s, ssid, &iter, &error)) {
2216 wpa_printf(MSG_DEBUG,
2217 "dbus: %s: Control interface could not set persistent group properties",
2218 __func__);
2219 reply = wpas_dbus_reply_new_from_error(
2220 message, &error, DBUS_ERROR_INVALID_ARGS,
2221 "Failed to set network properties");
2222 dbus_error_free(&error);
2223 goto err;
2224 }
2225
2226 /* Construct the object path for this network. */
2227 os_snprintf(path, WPAS_DBUS_OBJECT_PATH_MAX,
2228 "%s/" WPAS_DBUS_NEW_PERSISTENT_GROUPS_PART "/%d",
2229 wpa_s->parent->dbus_new_path, ssid->id);
2230
2231 reply = dbus_message_new_method_return(message);
2232 if (reply == NULL) {
2233 reply = wpas_dbus_error_no_memory(message);
2234 goto err;
2235 }
2236 if (!dbus_message_append_args(reply, DBUS_TYPE_OBJECT_PATH, &path,
2237 DBUS_TYPE_INVALID)) {
2238 dbus_message_unref(reply);
2239 reply = wpas_dbus_error_no_memory(message);
2240 goto err;
2241 }
2242
2243 return reply;
2244
2245 err:
2246 if (ssid) {
2247 wpas_notify_persistent_group_removed(wpa_s, ssid);
2248 wpa_config_remove_network(wpa_s->conf, ssid->id);
2249 }
2250 return reply;
2251 }
2252
2253
2254 /**
2255 * wpas_dbus_handler_remove_persistent_group - Remove a configured persistent
2256 * group
2257 * @message: Pointer to incoming dbus message
2258 * @wpa_s: wpa_supplicant structure for a network interface
2259 * Returns: NULL on success or dbus error on failure
2260 *
2261 * Handler function for "RemovePersistentGroup" method call of a P2P Device
2262 * interface.
2263 */
wpas_dbus_handler_remove_persistent_group(DBusMessage * message,struct wpa_supplicant * wpa_s)2264 DBusMessage * wpas_dbus_handler_remove_persistent_group(
2265 DBusMessage *message, struct wpa_supplicant *wpa_s)
2266 {
2267 DBusMessage *reply = NULL;
2268 const char *op;
2269 char *iface = NULL, *persistent_group_id;
2270 int id;
2271 struct wpa_ssid *ssid;
2272
2273 dbus_message_get_args(message, NULL, DBUS_TYPE_OBJECT_PATH, &op,
2274 DBUS_TYPE_INVALID);
2275
2276 wpa_s = wpa_s->global->p2p_init_wpa_s;
2277 if (!wpa_s) {
2278 reply = wpas_dbus_error_no_p2p_mgmt_iface(message);
2279 goto out;
2280 }
2281
2282 /*
2283 * Extract the network ID and ensure the network is actually a child of
2284 * this interface.
2285 */
2286 iface = wpas_dbus_new_decompose_object_path(
2287 op, WPAS_DBUS_NEW_PERSISTENT_GROUPS_PART,
2288 &persistent_group_id);
2289 if (iface == NULL || persistent_group_id == NULL ||
2290 !wpa_s->parent->dbus_new_path ||
2291 os_strcmp(iface, wpa_s->parent->dbus_new_path) != 0) {
2292 reply = wpas_dbus_error_invalid_args(message, op);
2293 goto out;
2294 }
2295
2296 id = strtoul(persistent_group_id, NULL, 10);
2297 if (errno == EINVAL) {
2298 reply = wpas_dbus_error_invalid_args(message, op);
2299 goto out;
2300 }
2301
2302 ssid = wpa_config_get_network(wpa_s->conf, id);
2303 if (ssid == NULL) {
2304 reply = wpas_dbus_error_persistent_group_unknown(message);
2305 goto out;
2306 }
2307
2308 wpas_notify_persistent_group_removed(wpa_s, ssid);
2309
2310 if (wpa_config_remove_network(wpa_s->conf, id) < 0) {
2311 wpa_printf(MSG_ERROR,
2312 "dbus: %s: error occurred when removing persistent group %d",
2313 __func__, id);
2314 reply = wpas_dbus_error_unknown_error(
2315 message,
2316 "error removing the specified persistent group on this interface.");
2317 goto out;
2318 }
2319
2320 out:
2321 os_free(iface);
2322 return reply;
2323 }
2324
2325
remove_persistent_group(struct wpa_supplicant * wpa_s,struct wpa_ssid * ssid)2326 static void remove_persistent_group(struct wpa_supplicant *wpa_s,
2327 struct wpa_ssid *ssid)
2328 {
2329 wpas_notify_persistent_group_removed(wpa_s, ssid);
2330
2331 if (wpa_config_remove_network(wpa_s->conf, ssid->id) < 0) {
2332 wpa_printf(MSG_ERROR,
2333 "dbus: %s: error occurred when removing persistent group %d",
2334 __func__, ssid->id);
2335 return;
2336 }
2337 }
2338
2339
2340 /**
2341 * wpas_dbus_handler_remove_all_persistent_groups - Remove all configured
2342 * persistent groups
2343 * @message: Pointer to incoming dbus message
2344 * @wpa_s: wpa_supplicant structure for a network interface
2345 * Returns: NULL on success or dbus error on failure
2346 *
2347 * Handler function for "RemoveAllPersistentGroups" method call of a
2348 * P2P Device interface.
2349 */
wpas_dbus_handler_remove_all_persistent_groups(DBusMessage * message,struct wpa_supplicant * wpa_s)2350 DBusMessage * wpas_dbus_handler_remove_all_persistent_groups(
2351 DBusMessage *message, struct wpa_supplicant *wpa_s)
2352 {
2353 struct wpa_ssid *ssid, *next;
2354 struct wpa_config *config;
2355
2356 wpa_s = wpa_s->global->p2p_init_wpa_s;
2357 if (!wpa_s)
2358 return wpas_dbus_error_no_p2p_mgmt_iface(message);
2359
2360 config = wpa_s->conf;
2361 ssid = config->ssid;
2362 while (ssid) {
2363 next = ssid->next;
2364 if (network_is_persistent_group(ssid))
2365 remove_persistent_group(wpa_s, ssid);
2366 ssid = next;
2367 }
2368 return NULL;
2369 }
2370
2371
2372 /*
2373 * Group object properties accessor methods
2374 */
2375
wpas_dbus_getter_p2p_group_members(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)2376 dbus_bool_t wpas_dbus_getter_p2p_group_members(
2377 const struct wpa_dbus_property_desc *property_desc,
2378 DBusMessageIter *iter, DBusError *error, void *user_data)
2379 {
2380 struct wpa_supplicant *wpa_s = user_data;
2381 struct wpa_ssid *ssid;
2382 unsigned int num_members;
2383 char **paths;
2384 unsigned int i;
2385 void *next = NULL;
2386 const u8 *addr;
2387 dbus_bool_t success = FALSE;
2388
2389 if (!wpa_s->parent->parent->dbus_new_path)
2390 return FALSE;
2391
2392 /* Verify correct role for this property */
2393 if (wpas_get_p2p_role(wpa_s) != WPAS_P2P_ROLE_GO) {
2394 return wpas_dbus_simple_array_property_getter(
2395 iter, DBUS_TYPE_OBJECT_PATH, NULL, 0, error);
2396 }
2397
2398 ssid = wpa_s->conf->ssid;
2399 /* At present WPAS P2P_GO mode only applicable for p2p_go */
2400 if (ssid->mode != WPAS_MODE_P2P_GO &&
2401 ssid->mode != WPAS_MODE_AP &&
2402 ssid->mode != WPAS_MODE_P2P_GROUP_FORMATION)
2403 return FALSE;
2404
2405 num_members = p2p_get_group_num_members(wpa_s->p2p_group);
2406
2407 paths = os_calloc(num_members, sizeof(char *));
2408 if (!paths)
2409 goto out_of_memory;
2410
2411 i = 0;
2412 while ((addr = p2p_iterate_group_members(wpa_s->p2p_group, &next))) {
2413 paths[i] = os_zalloc(WPAS_DBUS_OBJECT_PATH_MAX);
2414 if (!paths[i])
2415 goto out_of_memory;
2416 os_snprintf(paths[i], WPAS_DBUS_OBJECT_PATH_MAX,
2417 "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART
2418 "/" COMPACT_MACSTR,
2419 wpa_s->parent->parent->dbus_new_path,
2420 MAC2STR(addr));
2421 i++;
2422 }
2423
2424 success = wpas_dbus_simple_array_property_getter(iter,
2425 DBUS_TYPE_OBJECT_PATH,
2426 paths, num_members,
2427 error);
2428
2429 for (i = 0; i < num_members; i++)
2430 os_free(paths[i]);
2431 os_free(paths);
2432 return success;
2433
2434 out_of_memory:
2435 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
2436 if (paths) {
2437 for (i = 0; i < num_members; i++)
2438 os_free(paths[i]);
2439 os_free(paths);
2440 }
2441 return FALSE;
2442 }
2443
2444
wpas_dbus_getter_p2p_group_ssid(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)2445 dbus_bool_t wpas_dbus_getter_p2p_group_ssid(
2446 const struct wpa_dbus_property_desc *property_desc,
2447 DBusMessageIter *iter, DBusError *error, void *user_data)
2448 {
2449 struct wpa_supplicant *wpa_s = user_data;
2450
2451 if (wpa_s->current_ssid == NULL)
2452 return FALSE;
2453 return wpas_dbus_simple_array_property_getter(
2454 iter, DBUS_TYPE_BYTE, wpa_s->current_ssid->ssid,
2455 wpa_s->current_ssid->ssid_len, error);
2456 }
2457
2458
wpas_dbus_getter_p2p_group_bssid(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)2459 dbus_bool_t wpas_dbus_getter_p2p_group_bssid(
2460 const struct wpa_dbus_property_desc *property_desc,
2461 DBusMessageIter *iter, DBusError *error, void *user_data)
2462 {
2463 struct wpa_supplicant *wpa_s = user_data;
2464 u8 role = wpas_get_p2p_role(wpa_s);
2465 u8 *p_bssid;
2466
2467 if (role == WPAS_P2P_ROLE_CLIENT) {
2468 if (!wpa_s->current_bss)
2469 return FALSE;
2470 p_bssid = wpa_s->current_bss->bssid;
2471 } else {
2472 if (wpa_s->ap_iface == NULL)
2473 return FALSE;
2474 p_bssid = wpa_s->ap_iface->bss[0]->own_addr;
2475 }
2476
2477 return wpas_dbus_simple_array_property_getter(iter, DBUS_TYPE_BYTE,
2478 p_bssid, ETH_ALEN,
2479 error);
2480 }
2481
2482
wpas_dbus_getter_p2p_group_frequency(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)2483 dbus_bool_t wpas_dbus_getter_p2p_group_frequency(
2484 const struct wpa_dbus_property_desc *property_desc,
2485 DBusMessageIter *iter, DBusError *error, void *user_data)
2486 {
2487 struct wpa_supplicant *wpa_s = user_data;
2488 u16 op_freq;
2489 u8 role = wpas_get_p2p_role(wpa_s);
2490
2491 if (role == WPAS_P2P_ROLE_CLIENT) {
2492 if (!wpa_s->current_bss)
2493 return FALSE;
2494 op_freq = wpa_s->current_bss->freq;
2495 } else {
2496 if (wpa_s->ap_iface == NULL)
2497 return FALSE;
2498 op_freq = wpa_s->ap_iface->freq;
2499 }
2500
2501 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT16,
2502 &op_freq, error);
2503 }
2504
2505
wpas_dbus_getter_p2p_group_passphrase(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)2506 dbus_bool_t wpas_dbus_getter_p2p_group_passphrase(
2507 const struct wpa_dbus_property_desc *property_desc,
2508 DBusMessageIter *iter, DBusError *error, void *user_data)
2509 {
2510 struct wpa_supplicant *wpa_s = user_data;
2511 struct wpa_ssid *ssid = wpa_s->current_ssid;
2512
2513 if (ssid == NULL)
2514 return FALSE;
2515
2516 return wpas_dbus_string_property_getter(iter, ssid->passphrase, error);
2517 }
2518
2519
wpas_dbus_getter_p2p_group_psk(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)2520 dbus_bool_t wpas_dbus_getter_p2p_group_psk(
2521 const struct wpa_dbus_property_desc *property_desc,
2522 DBusMessageIter *iter, DBusError *error, void *user_data)
2523 {
2524 struct wpa_supplicant *wpa_s = user_data;
2525 u8 *p_psk = NULL;
2526 u8 psk_len = 0;
2527 struct wpa_ssid *ssid = wpa_s->current_ssid;
2528
2529 if (ssid == NULL)
2530 return FALSE;
2531
2532 if (ssid->psk_set) {
2533 p_psk = ssid->psk;
2534 psk_len = sizeof(ssid->psk);
2535 }
2536
2537 return wpas_dbus_simple_array_property_getter(iter, DBUS_TYPE_BYTE,
2538 p_psk, psk_len, error);
2539 }
2540
2541
wpas_dbus_getter_p2p_group_vendor_ext(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)2542 dbus_bool_t wpas_dbus_getter_p2p_group_vendor_ext(
2543 const struct wpa_dbus_property_desc *property_desc,
2544 DBusMessageIter *iter, DBusError *error, void *user_data)
2545 {
2546 struct wpa_supplicant *wpa_s = user_data;
2547 struct hostapd_data *hapd;
2548 struct wpabuf *vendor_ext[MAX_WPS_VENDOR_EXTENSIONS];
2549 unsigned int i, num_vendor_ext = 0;
2550
2551 os_memset(vendor_ext, 0, sizeof(vendor_ext));
2552
2553 /* Verify correct role for this property */
2554 if (wpas_get_p2p_role(wpa_s) == WPAS_P2P_ROLE_GO) {
2555 if (wpa_s->ap_iface == NULL)
2556 return FALSE;
2557 hapd = wpa_s->ap_iface->bss[0];
2558
2559 /* Parse WPS Vendor Extensions sent in Beacon/Probe Response */
2560 for (i = 0; i < MAX_WPS_VENDOR_EXTENSIONS; i++) {
2561 if (hapd->conf->wps_vendor_ext[i] == NULL)
2562 continue;
2563 vendor_ext[num_vendor_ext++] =
2564 hapd->conf->wps_vendor_ext[i];
2565 }
2566 }
2567
2568 /* Return vendor extensions or no data */
2569 return wpas_dbus_simple_array_array_property_getter(iter,
2570 DBUS_TYPE_BYTE,
2571 vendor_ext,
2572 num_vendor_ext,
2573 error);
2574 }
2575
2576
wpas_dbus_setter_p2p_group_vendor_ext(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)2577 dbus_bool_t wpas_dbus_setter_p2p_group_vendor_ext(
2578 const struct wpa_dbus_property_desc *property_desc,
2579 DBusMessageIter *iter, DBusError *error, void *user_data)
2580 {
2581 struct wpa_supplicant *wpa_s = user_data;
2582 DBusMessageIter variant_iter, iter_dict, array_iter, sub;
2583 struct wpa_dbus_dict_entry entry = { .type = DBUS_TYPE_STRING };
2584 unsigned int i;
2585 struct hostapd_data *hapd = NULL;
2586
2587 if (wpas_get_p2p_role(wpa_s) == WPAS_P2P_ROLE_GO &&
2588 wpa_s->ap_iface != NULL)
2589 hapd = wpa_s->ap_iface->bss[0];
2590 else
2591 return FALSE;
2592
2593 dbus_message_iter_recurse(iter, &variant_iter);
2594 if (dbus_message_iter_get_arg_type(&variant_iter) != DBUS_TYPE_ARRAY)
2595 return FALSE;
2596
2597 /*
2598 * This is supposed to be array of bytearrays (aay), but the earlier
2599 * implementation used a dict with "WPSVendorExtensions" as the key in
2600 * this setter function which does not match the format used by the
2601 * getter function. For backwards compatibility, allow both formats to
2602 * be used in the setter.
2603 */
2604 if (dbus_message_iter_get_element_type(&variant_iter) ==
2605 DBUS_TYPE_ARRAY) {
2606 /* This is the proper format matching the getter */
2607 struct wpabuf *vals[MAX_WPS_VENDOR_EXTENSIONS];
2608
2609 dbus_message_iter_recurse(&variant_iter, &array_iter);
2610
2611 if (dbus_message_iter_get_arg_type(&array_iter) !=
2612 DBUS_TYPE_ARRAY ||
2613 dbus_message_iter_get_element_type(&array_iter) !=
2614 DBUS_TYPE_BYTE) {
2615 wpa_printf(MSG_DEBUG,
2616 "dbus: Not an array of array of bytes");
2617 return FALSE;
2618 }
2619
2620 i = 0;
2621 os_memset(vals, 0, sizeof(vals));
2622
2623 while (dbus_message_iter_get_arg_type(&array_iter) ==
2624 DBUS_TYPE_ARRAY) {
2625 char *val;
2626 int len;
2627
2628 if (i == MAX_WPS_VENDOR_EXTENSIONS) {
2629 wpa_printf(MSG_DEBUG,
2630 "dbus: Too many WPSVendorExtensions values");
2631 i = MAX_WPS_VENDOR_EXTENSIONS + 1;
2632 break;
2633 }
2634
2635 dbus_message_iter_recurse(&array_iter, &sub);
2636 dbus_message_iter_get_fixed_array(&sub, &val, &len);
2637 wpa_hexdump(MSG_DEBUG, "dbus: WPSVendorExtentions[]",
2638 val, len);
2639 vals[i] = wpabuf_alloc_copy(val, len);
2640 if (vals[i] == NULL) {
2641 i = MAX_WPS_VENDOR_EXTENSIONS + 1;
2642 break;
2643 }
2644 i++;
2645 dbus_message_iter_next(&array_iter);
2646 }
2647
2648 if (i > MAX_WPS_VENDOR_EXTENSIONS) {
2649 for (i = 0; i < MAX_WPS_VENDOR_EXTENSIONS; i++)
2650 wpabuf_free(vals[i]);
2651 return FALSE;
2652 }
2653
2654 for (i = 0; i < MAX_WPS_VENDOR_EXTENSIONS; i++) {
2655 wpabuf_free(hapd->conf->wps_vendor_ext[i]);
2656 hapd->conf->wps_vendor_ext[i] = vals[i];
2657 }
2658
2659 hostapd_update_wps(hapd);
2660
2661 return TRUE;
2662 }
2663
2664 if (dbus_message_iter_get_element_type(&variant_iter) !=
2665 DBUS_TYPE_DICT_ENTRY)
2666 return FALSE;
2667
2668 wpa_printf(MSG_DEBUG,
2669 "dbus: Try to use backwards compatibility version of WPSVendorExtensions setter");
2670 if (!wpa_dbus_dict_open_read(&variant_iter, &iter_dict, error))
2671 return FALSE;
2672
2673 while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
2674 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry)) {
2675 dbus_set_error_const(error, DBUS_ERROR_INVALID_ARGS,
2676 "invalid message format");
2677 return FALSE;
2678 }
2679
2680 if (os_strcmp(entry.key, "WPSVendorExtensions") == 0) {
2681 if (entry.type != DBUS_TYPE_ARRAY ||
2682 entry.array_type != WPAS_DBUS_TYPE_BINARRAY ||
2683 entry.array_len > MAX_WPS_VENDOR_EXTENSIONS)
2684 goto error;
2685
2686 for (i = 0; i < MAX_WPS_VENDOR_EXTENSIONS; i++) {
2687 wpabuf_free(hapd->conf->wps_vendor_ext[i]);
2688 if (i < entry.array_len) {
2689 hapd->conf->wps_vendor_ext[i] =
2690 entry.binarray_value[i];
2691 entry.binarray_value[i] = NULL;
2692 } else
2693 hapd->conf->wps_vendor_ext[i] = NULL;
2694 }
2695
2696 hostapd_update_wps(hapd);
2697 } else
2698 goto error;
2699
2700 wpa_dbus_dict_entry_clear(&entry);
2701 }
2702
2703 return TRUE;
2704
2705 error:
2706 wpa_dbus_dict_entry_clear(&entry);
2707 dbus_set_error_const(error, DBUS_ERROR_INVALID_ARGS,
2708 "invalid message format");
2709 return FALSE;
2710 }
2711
2712
wpas_dbus_handler_p2p_add_service(DBusMessage * message,struct wpa_supplicant * wpa_s)2713 DBusMessage * wpas_dbus_handler_p2p_add_service(DBusMessage *message,
2714 struct wpa_supplicant *wpa_s)
2715 {
2716 DBusMessageIter iter_dict;
2717 DBusMessage *reply = NULL;
2718 DBusMessageIter iter;
2719 struct wpa_dbus_dict_entry entry;
2720 int upnp = 0;
2721 int bonjour = 0;
2722 char *service = NULL;
2723 struct wpabuf *query = NULL;
2724 struct wpabuf *resp = NULL;
2725 u8 version = 0;
2726
2727 dbus_message_iter_init(message, &iter);
2728
2729 if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL))
2730 goto error;
2731
2732 while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
2733 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
2734 goto error;
2735
2736 if (os_strcmp(entry.key, "service_type") == 0 &&
2737 entry.type == DBUS_TYPE_STRING) {
2738 if (os_strcmp(entry.str_value, "upnp") == 0)
2739 upnp = 1;
2740 else if (os_strcmp(entry.str_value, "bonjour") == 0)
2741 bonjour = 1;
2742 else
2743 goto error_clear;
2744 } else if (os_strcmp(entry.key, "version") == 0 &&
2745 entry.type == DBUS_TYPE_INT32) {
2746 version = entry.uint32_value;
2747 } else if (os_strcmp(entry.key, "service") == 0 &&
2748 entry.type == DBUS_TYPE_STRING) {
2749 os_free(service);
2750 service = os_strdup(entry.str_value);
2751 } else if (os_strcmp(entry.key, "query") == 0) {
2752 if (entry.type != DBUS_TYPE_ARRAY ||
2753 entry.array_type != DBUS_TYPE_BYTE)
2754 goto error_clear;
2755 query = wpabuf_alloc_copy(
2756 entry.bytearray_value,
2757 entry.array_len);
2758 } else if (os_strcmp(entry.key, "response") == 0) {
2759 if (entry.type != DBUS_TYPE_ARRAY ||
2760 entry.array_type != DBUS_TYPE_BYTE)
2761 goto error_clear;
2762 resp = wpabuf_alloc_copy(entry.bytearray_value,
2763 entry.array_len);
2764 }
2765 wpa_dbus_dict_entry_clear(&entry);
2766 }
2767
2768 if (upnp == 1) {
2769 if (version <= 0 || service == NULL)
2770 goto error;
2771
2772 if (wpas_p2p_service_add_upnp(wpa_s, version, service) != 0)
2773 goto error;
2774
2775 } else if (bonjour == 1) {
2776 if (query == NULL || resp == NULL)
2777 goto error;
2778
2779 if (wpas_p2p_service_add_bonjour(wpa_s, query, resp) < 0)
2780 goto error;
2781 } else
2782 goto error;
2783
2784 out:
2785 os_free(service);
2786 wpabuf_free(query);
2787 wpabuf_free(resp);
2788
2789 return reply;
2790 error_clear:
2791 wpa_dbus_dict_entry_clear(&entry);
2792 error:
2793 reply = wpas_dbus_error_invalid_args(message, NULL);
2794 goto out;
2795 }
2796
2797
wpas_dbus_handler_p2p_delete_service(DBusMessage * message,struct wpa_supplicant * wpa_s)2798 DBusMessage * wpas_dbus_handler_p2p_delete_service(
2799 DBusMessage *message, struct wpa_supplicant *wpa_s)
2800 {
2801 DBusMessageIter iter_dict;
2802 DBusMessage *reply = NULL;
2803 DBusMessageIter iter;
2804 struct wpa_dbus_dict_entry entry;
2805 int upnp = 0;
2806 int bonjour = 0;
2807 int ret = 0;
2808 char *service = NULL;
2809 struct wpabuf *query = NULL;
2810 u8 version = 0;
2811
2812 dbus_message_iter_init(message, &iter);
2813
2814 if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL))
2815 goto error;
2816
2817 while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
2818 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
2819 goto error;
2820
2821 if (os_strcmp(entry.key, "service_type") == 0 &&
2822 entry.type == DBUS_TYPE_STRING) {
2823 if (os_strcmp(entry.str_value, "upnp") == 0)
2824 upnp = 1;
2825 else if (os_strcmp(entry.str_value, "bonjour") == 0)
2826 bonjour = 1;
2827 else
2828 goto error_clear;
2829 } else if (os_strcmp(entry.key, "version") == 0 &&
2830 entry.type == DBUS_TYPE_INT32) {
2831 version = entry.uint32_value;
2832 } else if (os_strcmp(entry.key, "service") == 0 &&
2833 entry.type == DBUS_TYPE_STRING) {
2834 os_free(service);
2835 service = os_strdup(entry.str_value);
2836 } else if (os_strcmp(entry.key, "query") == 0) {
2837 if (entry.type != DBUS_TYPE_ARRAY ||
2838 entry.array_type != DBUS_TYPE_BYTE)
2839 goto error_clear;
2840 wpabuf_free(query);
2841 query = wpabuf_alloc_copy(entry.bytearray_value,
2842 entry.array_len);
2843 } else {
2844 goto error_clear;
2845 }
2846
2847 wpa_dbus_dict_entry_clear(&entry);
2848 }
2849 if (upnp == 1) {
2850 if (version <= 0 || service == NULL)
2851 goto error;
2852
2853 ret = wpas_p2p_service_del_upnp(wpa_s, version, service);
2854 if (ret != 0)
2855 goto error;
2856 } else if (bonjour == 1) {
2857 if (query == NULL)
2858 goto error;
2859
2860 ret = wpas_p2p_service_del_bonjour(wpa_s, query);
2861 if (ret != 0)
2862 goto error;
2863 } else
2864 goto error;
2865
2866 wpabuf_free(query);
2867 os_free(service);
2868 return reply;
2869 error_clear:
2870 wpa_dbus_dict_entry_clear(&entry);
2871 error:
2872 wpabuf_free(query);
2873 os_free(service);
2874 return wpas_dbus_error_invalid_args(message, NULL);
2875 }
2876
2877
wpas_dbus_handler_p2p_flush_service(DBusMessage * message,struct wpa_supplicant * wpa_s)2878 DBusMessage * wpas_dbus_handler_p2p_flush_service(DBusMessage *message,
2879 struct wpa_supplicant *wpa_s)
2880 {
2881 wpas_p2p_service_flush(wpa_s);
2882 return NULL;
2883 }
2884
2885
wpas_dbus_handler_p2p_service_sd_req(DBusMessage * message,struct wpa_supplicant * wpa_s)2886 DBusMessage * wpas_dbus_handler_p2p_service_sd_req(
2887 DBusMessage *message, struct wpa_supplicant *wpa_s)
2888 {
2889 DBusMessageIter iter_dict;
2890 DBusMessage *reply = NULL;
2891 DBusMessageIter iter;
2892 struct wpa_dbus_dict_entry entry;
2893 int upnp = 0;
2894 char *service = NULL;
2895 char *peer_object_path = NULL;
2896 struct wpabuf *tlv = NULL;
2897 u8 version = 0;
2898 u64 ref = 0;
2899 u8 addr_buf[ETH_ALEN], *addr;
2900
2901 dbus_message_iter_init(message, &iter);
2902
2903 if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL))
2904 goto error;
2905
2906 while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
2907 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
2908 goto error;
2909 if (os_strcmp(entry.key, "peer_object") == 0 &&
2910 entry.type == DBUS_TYPE_OBJECT_PATH) {
2911 peer_object_path = os_strdup(entry.str_value);
2912 } else if (os_strcmp(entry.key, "service_type") == 0 &&
2913 entry.type == DBUS_TYPE_STRING) {
2914 if (os_strcmp(entry.str_value, "upnp") == 0)
2915 upnp = 1;
2916 else
2917 goto error_clear;
2918 } else if (os_strcmp(entry.key, "version") == 0 &&
2919 entry.type == DBUS_TYPE_INT32) {
2920 version = entry.uint32_value;
2921 } else if (os_strcmp(entry.key, "service") == 0 &&
2922 entry.type == DBUS_TYPE_STRING) {
2923 service = os_strdup(entry.str_value);
2924 } else if (os_strcmp(entry.key, "tlv") == 0) {
2925 if (entry.type != DBUS_TYPE_ARRAY ||
2926 entry.array_type != DBUS_TYPE_BYTE)
2927 goto error_clear;
2928 wpabuf_free(tlv);
2929 tlv = wpabuf_alloc_copy(entry.bytearray_value,
2930 entry.array_len);
2931 } else
2932 goto error_clear;
2933
2934 wpa_dbus_dict_entry_clear(&entry);
2935 }
2936
2937 if (!peer_object_path) {
2938 addr = NULL;
2939 } else {
2940 if (parse_peer_object_path(peer_object_path, addr_buf) < 0 ||
2941 !p2p_peer_known(wpa_s->global->p2p, addr_buf))
2942 goto error;
2943
2944 addr = addr_buf;
2945 }
2946
2947 if (upnp == 1) {
2948 if (version <= 0 || service == NULL)
2949 goto error;
2950
2951 ref = wpas_p2p_sd_request_upnp(wpa_s, addr, version, service);
2952 } else {
2953 if (tlv == NULL)
2954 goto error;
2955 ref = wpas_p2p_sd_request(wpa_s, addr, tlv);
2956 }
2957
2958 if (ref != 0) {
2959 reply = dbus_message_new_method_return(message);
2960 dbus_message_append_args(reply, DBUS_TYPE_UINT64,
2961 &ref, DBUS_TYPE_INVALID);
2962 } else {
2963 reply = wpas_dbus_error_unknown_error(
2964 message, "Unable to send SD request");
2965 }
2966 out:
2967 wpabuf_free(tlv);
2968 os_free(service);
2969 os_free(peer_object_path);
2970 return reply;
2971 error_clear:
2972 wpa_dbus_dict_entry_clear(&entry);
2973 error:
2974 reply = wpas_dbus_error_invalid_args(message, NULL);
2975 goto out;
2976 }
2977
2978
wpas_dbus_handler_p2p_service_sd_res(DBusMessage * message,struct wpa_supplicant * wpa_s)2979 DBusMessage * wpas_dbus_handler_p2p_service_sd_res(
2980 DBusMessage *message, struct wpa_supplicant *wpa_s)
2981 {
2982 DBusMessageIter iter_dict;
2983 DBusMessage *reply = NULL;
2984 DBusMessageIter iter;
2985 struct wpa_dbus_dict_entry entry;
2986 char *peer_object_path = NULL;
2987 struct wpabuf *tlv = NULL;
2988 int freq = 0;
2989 int dlg_tok = 0;
2990 u8 addr[ETH_ALEN];
2991
2992 dbus_message_iter_init(message, &iter);
2993
2994 if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL))
2995 goto error;
2996
2997 while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
2998 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
2999 goto error;
3000
3001 if (os_strcmp(entry.key, "peer_object") == 0 &&
3002 entry.type == DBUS_TYPE_OBJECT_PATH) {
3003 peer_object_path = os_strdup(entry.str_value);
3004 } else if (os_strcmp(entry.key, "frequency") == 0 &&
3005 entry.type == DBUS_TYPE_INT32) {
3006 freq = entry.uint32_value;
3007 } else if (os_strcmp(entry.key, "dialog_token") == 0 &&
3008 (entry.type == DBUS_TYPE_UINT32 ||
3009 entry.type == DBUS_TYPE_INT32)) {
3010 dlg_tok = entry.uint32_value;
3011 } else if (os_strcmp(entry.key, "tlvs") == 0) {
3012 if (entry.type != DBUS_TYPE_ARRAY ||
3013 entry.array_type != DBUS_TYPE_BYTE)
3014 goto error_clear;
3015 wpabuf_free(tlv);
3016 tlv = wpabuf_alloc_copy(entry.bytearray_value,
3017 entry.array_len);
3018 } else
3019 goto error_clear;
3020
3021 wpa_dbus_dict_entry_clear(&entry);
3022 }
3023 if (parse_peer_object_path(peer_object_path, addr) < 0 ||
3024 !p2p_peer_known(wpa_s->global->p2p, addr) ||
3025 tlv == NULL)
3026 goto error;
3027
3028 wpas_p2p_sd_response(wpa_s, freq, addr, (u8) dlg_tok, tlv);
3029 out:
3030 wpabuf_free(tlv);
3031 os_free(peer_object_path);
3032 return reply;
3033 error_clear:
3034 wpa_dbus_dict_entry_clear(&entry);
3035 error:
3036 reply = wpas_dbus_error_invalid_args(message, NULL);
3037 goto out;
3038 }
3039
3040
wpas_dbus_handler_p2p_service_sd_cancel_req(DBusMessage * message,struct wpa_supplicant * wpa_s)3041 DBusMessage * wpas_dbus_handler_p2p_service_sd_cancel_req(
3042 DBusMessage *message, struct wpa_supplicant *wpa_s)
3043 {
3044 DBusMessageIter iter;
3045 u64 req = 0;
3046
3047 dbus_message_iter_init(message, &iter);
3048 dbus_message_iter_get_basic(&iter, &req);
3049
3050 if (req == 0)
3051 goto error;
3052
3053 if (wpas_p2p_sd_cancel_request(wpa_s, req) < 0)
3054 goto error;
3055
3056 return NULL;
3057 error:
3058 return wpas_dbus_error_invalid_args(message, NULL);
3059 }
3060
3061
wpas_dbus_handler_p2p_service_update(DBusMessage * message,struct wpa_supplicant * wpa_s)3062 DBusMessage * wpas_dbus_handler_p2p_service_update(
3063 DBusMessage *message, struct wpa_supplicant *wpa_s)
3064 {
3065 wpas_p2p_sd_service_update(wpa_s);
3066 return NULL;
3067 }
3068
3069
wpas_dbus_handler_p2p_serv_disc_external(DBusMessage * message,struct wpa_supplicant * wpa_s)3070 DBusMessage * wpas_dbus_handler_p2p_serv_disc_external(
3071 DBusMessage *message, struct wpa_supplicant *wpa_s)
3072 {
3073 DBusMessageIter iter;
3074 int ext = 0;
3075
3076 dbus_message_iter_init(message, &iter);
3077 dbus_message_iter_get_basic(&iter, &ext);
3078
3079 wpa_s->p2p_sd_over_ctrl_iface = ext;
3080
3081 return NULL;
3082
3083 }
3084
3085
3086 #ifdef CONFIG_WIFI_DISPLAY
3087
wpas_dbus_getter_global_wfd_ies(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)3088 dbus_bool_t wpas_dbus_getter_global_wfd_ies(
3089 const struct wpa_dbus_property_desc *property_desc,
3090 DBusMessageIter *iter, DBusError *error, void *user_data)
3091 {
3092 struct wpa_global *global = user_data;
3093 struct wpabuf *ie;
3094 dbus_bool_t ret;
3095
3096 ie = wifi_display_get_wfd_ie(global);
3097 if (ie == NULL)
3098 return wpas_dbus_simple_array_property_getter(iter,
3099 DBUS_TYPE_BYTE,
3100 NULL, 0, error);
3101
3102 ret = wpas_dbus_simple_array_property_getter(iter, DBUS_TYPE_BYTE,
3103 wpabuf_head(ie),
3104 wpabuf_len(ie), error);
3105 wpabuf_free(ie);
3106
3107 return ret;
3108 }
3109
3110
wpas_dbus_setter_global_wfd_ies(const struct wpa_dbus_property_desc * property_desc,DBusMessageIter * iter,DBusError * error,void * user_data)3111 dbus_bool_t wpas_dbus_setter_global_wfd_ies(
3112 const struct wpa_dbus_property_desc *property_desc,
3113 DBusMessageIter *iter, DBusError *error, void *user_data)
3114 {
3115 struct wpa_global *global = user_data;
3116 DBusMessageIter variant, array;
3117 struct wpabuf *ie = NULL;
3118 const u8 *data;
3119 int len;
3120
3121 if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_VARIANT)
3122 goto err;
3123
3124 dbus_message_iter_recurse(iter, &variant);
3125 if (dbus_message_iter_get_arg_type(&variant) != DBUS_TYPE_ARRAY)
3126 goto err;
3127
3128 dbus_message_iter_recurse(&variant, &array);
3129 dbus_message_iter_get_fixed_array(&array, &data, &len);
3130 if (len == 0) {
3131 wifi_display_enable(global, 0);
3132 wifi_display_deinit(global);
3133
3134 return TRUE;
3135 }
3136
3137 ie = wpabuf_alloc(len);
3138 if (ie == NULL)
3139 goto err;
3140
3141 wpabuf_put_data(ie, data, len);
3142 if (wifi_display_subelem_set_from_ies(global, ie) != 0)
3143 goto err;
3144
3145 if (global->wifi_display == 0)
3146 wifi_display_enable(global, 1);
3147
3148 wpabuf_free(ie);
3149
3150 return TRUE;
3151 err:
3152 wpabuf_free(ie);
3153
3154 dbus_set_error_const(error, DBUS_ERROR_INVALID_ARGS,
3155 "invalid message format");
3156 return FALSE;
3157 }
3158
3159 #endif /* CONFIG_WIFI_DISPLAY */
3160