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