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