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