• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * WPA Supplicant / dbus-based control interface
3  * Copyright (c) 2006, Dan Williams <dcbw@redhat.com> and Red Hat, Inc.
4  * Copyright (c) 2009-2010, Witold Sowa <witold.sowa@gmail.com>
5  * Copyright (c) 2009, Jouni Malinen <j@w1.fi>
6  *
7  * This software may be distributed under the terms of the BSD license.
8  * See README for more details.
9  */
10 
11 #include "includes.h"
12 
13 #include "common.h"
14 #include "common/ieee802_11_defs.h"
15 #include "eap_peer/eap_methods.h"
16 #include "eapol_supp/eapol_supp_sm.h"
17 #include "rsn_supp/wpa.h"
18 #include "../config.h"
19 #include "../wpa_supplicant_i.h"
20 #include "../driver_i.h"
21 #include "../notify.h"
22 #include "../bss.h"
23 #include "../scan.h"
24 #include "../ctrl_iface.h"
25 #include "../autoscan.h"
26 #include "dbus_new_helpers.h"
27 #include "dbus_new.h"
28 #include "dbus_new_handlers.h"
29 #include "dbus_dict_helpers.h"
30 #include "dbus_common_i.h"
31 
32 extern int wpa_debug_level;
33 extern int wpa_debug_show_keys;
34 extern int wpa_debug_timestamp;
35 
36 static const char *debug_strings[] = {
37 	"excessive", "msgdump", "debug", "info", "warning", "error", NULL
38 };
39 
40 
41 /**
42  * wpas_dbus_error_unknown_error - Return a new InvalidArgs error message
43  * @message: Pointer to incoming dbus message this error refers to
44  * @arg: Optional string appended to error message
45  * Returns: a dbus error message
46  *
47  * Convenience function to create and return an UnknownError
48  */
wpas_dbus_error_unknown_error(DBusMessage * message,const char * arg)49 DBusMessage * wpas_dbus_error_unknown_error(DBusMessage *message,
50 					    const char *arg)
51 {
52 	/*
53 	 * This function can be called as a result of a failure
54 	 * within internal getter calls, which will call this function
55 	 * with a NULL message parameter.  However, dbus_message_new_error
56 	 * looks very unkindly (i.e, abort()) on a NULL message, so
57 	 * in this case, we should not call it.
58 	 */
59 	if (message == NULL) {
60 		wpa_printf(MSG_INFO, "dbus: wpas_dbus_error_unknown_error "
61 			   "called with NULL message (arg=%s)",
62 			   arg ? arg : "N/A");
63 		return NULL;
64 	}
65 
66 	return dbus_message_new_error(message, WPAS_DBUS_ERROR_UNKNOWN_ERROR,
67 				      arg);
68 }
69 
70 
71 /**
72  * wpas_dbus_error_iface_unknown - Return a new invalid interface error message
73  * @message: Pointer to incoming dbus message this error refers to
74  * Returns: A dbus error message
75  *
76  * Convenience function to create and return an invalid interface error
77  */
wpas_dbus_error_iface_unknown(DBusMessage * message)78 static DBusMessage * wpas_dbus_error_iface_unknown(DBusMessage *message)
79 {
80 	return dbus_message_new_error(message, WPAS_DBUS_ERROR_IFACE_UNKNOWN,
81 				      "wpa_supplicant knows nothing about "
82 				      "this interface.");
83 }
84 
85 
86 /**
87  * wpas_dbus_error_network_unknown - Return a new NetworkUnknown error message
88  * @message: Pointer to incoming dbus message this error refers to
89  * Returns: a dbus error message
90  *
91  * Convenience function to create and return an invalid network error
92  */
wpas_dbus_error_network_unknown(DBusMessage * message)93 static DBusMessage * wpas_dbus_error_network_unknown(DBusMessage *message)
94 {
95 	return dbus_message_new_error(message, WPAS_DBUS_ERROR_NETWORK_UNKNOWN,
96 				      "There is no such a network in this "
97 				      "interface.");
98 }
99 
100 
101 /**
102  * wpas_dbus_error_invalid_args - Return a new InvalidArgs error message
103  * @message: Pointer to incoming dbus message this error refers to
104  * Returns: a dbus error message
105  *
106  * Convenience function to create and return an invalid options error
107  */
wpas_dbus_error_invalid_args(DBusMessage * message,const char * arg)108 DBusMessage * wpas_dbus_error_invalid_args(DBusMessage *message,
109 					  const char *arg)
110 {
111 	DBusMessage *reply;
112 
113 	reply = dbus_message_new_error(message, WPAS_DBUS_ERROR_INVALID_ARGS,
114 				       "Did not receive correct message "
115 				       "arguments.");
116 	if (arg != NULL)
117 		dbus_message_append_args(reply, DBUS_TYPE_STRING, &arg,
118 					 DBUS_TYPE_INVALID);
119 
120 	return reply;
121 }
122 
123 
124 static const char *dont_quote[] = {
125 	"key_mgmt", "proto", "pairwise", "auth_alg", "group", "eap",
126 	"opensc_engine_path", "pkcs11_engine_path", "pkcs11_module_path",
127 	"bssid", NULL
128 };
129 
should_quote_opt(const char * key)130 static dbus_bool_t should_quote_opt(const char *key)
131 {
132 	int i = 0;
133 	while (dont_quote[i] != NULL) {
134 		if (os_strcmp(key, dont_quote[i]) == 0)
135 			return FALSE;
136 		i++;
137 	}
138 	return TRUE;
139 }
140 
141 /**
142  * get_iface_by_dbus_path - Get a new network interface
143  * @global: Pointer to global data from wpa_supplicant_init()
144  * @path: Pointer to a dbus object path representing an interface
145  * Returns: Pointer to the interface or %NULL if not found
146  */
get_iface_by_dbus_path(struct wpa_global * global,const char * path)147 static struct wpa_supplicant * get_iface_by_dbus_path(
148 	struct wpa_global *global, const char *path)
149 {
150 	struct wpa_supplicant *wpa_s;
151 
152 	for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
153 		if (os_strcmp(wpa_s->dbus_new_path, path) == 0)
154 			return wpa_s;
155 	}
156 	return NULL;
157 }
158 
159 
160 /**
161  * set_network_properties - Set properties of a configured network
162  * @wpa_s: wpa_supplicant structure for a network interface
163  * @ssid: wpa_ssid structure for a configured network
164  * @iter: DBus message iterator containing dictionary of network
165  * properties to set.
166  * @error: On failure, an error describing the failure
167  * Returns: TRUE if the request succeeds, FALSE if it failed
168  *
169  * Sets network configuration with parameters given id DBus dictionary
170  */
set_network_properties(struct wpa_supplicant * wpa_s,struct wpa_ssid * ssid,DBusMessageIter * iter,DBusError * error)171 dbus_bool_t set_network_properties(struct wpa_supplicant *wpa_s,
172 				   struct wpa_ssid *ssid,
173 				   DBusMessageIter *iter,
174 				   DBusError *error)
175 {
176 	struct wpa_dbus_dict_entry entry = { .type = DBUS_TYPE_STRING };
177 	DBusMessageIter	iter_dict;
178 	char *value = NULL;
179 
180 	if (!wpa_dbus_dict_open_read(iter, &iter_dict, error))
181 		return FALSE;
182 
183 	while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
184 		size_t size = 50;
185 		int ret;
186 
187 		if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
188 			goto error;
189 
190 		value = NULL;
191 		if (entry.type == DBUS_TYPE_ARRAY &&
192 		    entry.array_type == DBUS_TYPE_BYTE) {
193 			if (entry.array_len <= 0)
194 				goto error;
195 
196 			size = entry.array_len * 2 + 1;
197 			value = os_zalloc(size);
198 			if (value == NULL)
199 				goto error;
200 
201 			ret = wpa_snprintf_hex(value, size,
202 					       (u8 *) entry.bytearray_value,
203 					       entry.array_len);
204 			if (ret <= 0)
205 				goto error;
206 		} else if (entry.type == DBUS_TYPE_STRING) {
207 			if (should_quote_opt(entry.key)) {
208 				size = os_strlen(entry.str_value);
209 				if (size <= 0)
210 					goto error;
211 
212 				size += 3;
213 				value = os_zalloc(size);
214 				if (value == NULL)
215 					goto error;
216 
217 				ret = os_snprintf(value, size, "\"%s\"",
218 						  entry.str_value);
219 				if (ret < 0 || (size_t) ret != (size - 1))
220 					goto error;
221 			} else {
222 				value = os_strdup(entry.str_value);
223 				if (value == NULL)
224 					goto error;
225 			}
226 		} else if (entry.type == DBUS_TYPE_UINT32) {
227 			value = os_zalloc(size);
228 			if (value == NULL)
229 				goto error;
230 
231 			ret = os_snprintf(value, size, "%u",
232 					  entry.uint32_value);
233 			if (ret <= 0)
234 				goto error;
235 		} else if (entry.type == DBUS_TYPE_INT32) {
236 			value = os_zalloc(size);
237 			if (value == NULL)
238 				goto error;
239 
240 			ret = os_snprintf(value, size, "%d",
241 					  entry.int32_value);
242 			if (ret <= 0)
243 				goto error;
244 		} else
245 			goto error;
246 
247 		if (wpa_config_set(ssid, entry.key, value, 0) < 0)
248 			goto error;
249 
250 		if ((os_strcmp(entry.key, "psk") == 0 &&
251 		     value[0] == '"' && ssid->ssid_len) ||
252 		    (os_strcmp(entry.key, "ssid") == 0 && ssid->passphrase))
253 			wpa_config_update_psk(ssid);
254 		else if (os_strcmp(entry.key, "priority") == 0)
255 			wpa_config_update_prio_list(wpa_s->conf);
256 
257 		os_free(value);
258 		wpa_dbus_dict_entry_clear(&entry);
259 	}
260 
261 	return TRUE;
262 
263 error:
264 	os_free(value);
265 	wpa_dbus_dict_entry_clear(&entry);
266 	dbus_set_error_const(error, DBUS_ERROR_INVALID_ARGS,
267 			     "invalid message format");
268 	return FALSE;
269 }
270 
271 
272 /**
273  * wpas_dbus_simple_property_getter - Get basic type property
274  * @iter: Message iter to use when appending arguments
275  * @type: DBus type of property (must be basic type)
276  * @val: pointer to place holding property value
277  * @error: On failure an error describing the failure
278  * Returns: TRUE if the request was successful, FALSE if it failed
279  *
280  * Generic getter for basic type properties. Type is required to be basic.
281  */
wpas_dbus_simple_property_getter(DBusMessageIter * iter,const int type,const void * val,DBusError * error)282 dbus_bool_t wpas_dbus_simple_property_getter(DBusMessageIter *iter,
283 					     const int type,
284 					     const void *val,
285 					     DBusError *error)
286 {
287 	DBusMessageIter variant_iter;
288 
289 	if (!dbus_type_is_basic(type)) {
290 		dbus_set_error(error, DBUS_ERROR_FAILED,
291 		               "%s: given type is not basic", __func__);
292 		return FALSE;
293 	}
294 
295 	if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT,
296 	                                      wpa_dbus_type_as_string(type),
297 	                                      &variant_iter))
298 		goto error;
299 
300 	if (!dbus_message_iter_append_basic(&variant_iter, type, val))
301 		goto error;
302 
303 	if (!dbus_message_iter_close_container(iter, &variant_iter))
304 		goto error;
305 
306 	return TRUE;
307 
308 error:
309 	dbus_set_error(error, DBUS_ERROR_FAILED,
310 	               "%s: error constructing reply", __func__);
311 	return FALSE;
312 }
313 
314 
315 /**
316  * wpas_dbus_simple_property_setter - Set basic type property
317  * @message: Pointer to incoming dbus message
318  * @type: DBus type of property (must be basic type)
319  * @val: pointer to place where value being set will be stored
320  * Returns: TRUE if the request was successful, FALSE if it failed
321  *
322  * Generic setter for basic type properties. Type is required to be basic.
323  */
wpas_dbus_simple_property_setter(DBusMessageIter * iter,DBusError * error,const int type,void * val)324 dbus_bool_t wpas_dbus_simple_property_setter(DBusMessageIter *iter,
325 					     DBusError *error,
326 					     const int type, void *val)
327 {
328 	DBusMessageIter variant_iter;
329 
330 	if (!dbus_type_is_basic(type)) {
331 		dbus_set_error(error, DBUS_ERROR_FAILED,
332 			       "%s: given type is not basic", __func__);
333 		return FALSE;
334 	}
335 
336 	/* Look at the new value */
337 	dbus_message_iter_recurse(iter, &variant_iter);
338 	if (dbus_message_iter_get_arg_type(&variant_iter) != type) {
339 		dbus_set_error_const(error, DBUS_ERROR_FAILED,
340 				     "wrong property type");
341 		return FALSE;
342 	}
343 	dbus_message_iter_get_basic(&variant_iter, val);
344 
345 	return TRUE;
346 }
347 
348 
349 /**
350  * wpas_dbus_simple_array_property_getter - Get array type property
351  * @iter: Pointer to incoming dbus message iterator
352  * @type: DBus type of property array elements (must be basic type)
353  * @array: pointer to array of elements to put into response message
354  * @array_len: length of above array
355  * @error: a pointer to an error to fill on failure
356  * Returns: TRUE if the request succeeded, FALSE if it failed
357  *
358  * Generic getter for array type properties. Array elements type is
359  * required to be basic.
360  */
wpas_dbus_simple_array_property_getter(DBusMessageIter * iter,const int type,const void * array,size_t array_len,DBusError * error)361 dbus_bool_t wpas_dbus_simple_array_property_getter(DBusMessageIter *iter,
362 						   const int type,
363 						   const void *array,
364 						   size_t array_len,
365 						   DBusError *error)
366 {
367 	DBusMessageIter variant_iter, array_iter;
368 	char type_str[] = "a?"; /* ? will be replaced with subtype letter; */
369 	const char *sub_type_str;
370 	size_t element_size, i;
371 
372 	if (!dbus_type_is_basic(type)) {
373 		dbus_set_error(error, DBUS_ERROR_FAILED,
374 		               "%s: given type is not basic", __func__);
375 		return FALSE;
376 	}
377 
378 	sub_type_str = wpa_dbus_type_as_string(type);
379 	type_str[1] = sub_type_str[0];
380 
381 	if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT,
382 					      type_str, &variant_iter)) {
383 		dbus_set_error(error, DBUS_ERROR_FAILED,
384 		               "%s: failed to construct message 1", __func__);
385 		return FALSE;
386 	}
387 
388 	if (!dbus_message_iter_open_container(&variant_iter, DBUS_TYPE_ARRAY,
389 					      sub_type_str, &array_iter)) {
390 		dbus_set_error(error, DBUS_ERROR_FAILED,
391 		               "%s: failed to construct message 2", __func__);
392 		return FALSE;
393 	}
394 
395 	switch(type) {
396 	case DBUS_TYPE_BYTE:
397 	case DBUS_TYPE_BOOLEAN:
398 		element_size = 1;
399 		break;
400 	case DBUS_TYPE_INT16:
401 	case DBUS_TYPE_UINT16:
402 		element_size = sizeof(uint16_t);
403 		break;
404 	case DBUS_TYPE_INT32:
405 	case DBUS_TYPE_UINT32:
406 		element_size = sizeof(uint32_t);
407 		break;
408 	case DBUS_TYPE_INT64:
409 	case DBUS_TYPE_UINT64:
410 		element_size = sizeof(uint64_t);
411 		break;
412 	case DBUS_TYPE_DOUBLE:
413 		element_size = sizeof(double);
414 		break;
415 	case DBUS_TYPE_STRING:
416 	case DBUS_TYPE_OBJECT_PATH:
417 		element_size = sizeof(char *);
418 		break;
419 	default:
420 		dbus_set_error(error, DBUS_ERROR_FAILED,
421 		               "%s: unknown element type %d", __func__, type);
422 		return FALSE;
423 	}
424 
425 	for (i = 0; i < array_len; i++) {
426 		dbus_message_iter_append_basic(&array_iter, type,
427 					       array + i * element_size);
428 	}
429 
430 	if (!dbus_message_iter_close_container(&variant_iter, &array_iter)) {
431 		dbus_set_error(error, DBUS_ERROR_FAILED,
432 		               "%s: failed to construct message 3", __func__);
433 		return FALSE;
434 	}
435 
436 	if (!dbus_message_iter_close_container(iter, &variant_iter)) {
437 		dbus_set_error(error, DBUS_ERROR_FAILED,
438 		               "%s: failed to construct message 4", __func__);
439 		return FALSE;
440 	}
441 
442 	return TRUE;
443 }
444 
445 
446 /**
447  * wpas_dbus_simple_array_array_property_getter - Get array array type property
448  * @iter: Pointer to incoming dbus message iterator
449  * @type: DBus type of property array elements (must be basic type)
450  * @array: pointer to array of elements to put into response message
451  * @array_len: length of above array
452  * @error: a pointer to an error to fill on failure
453  * Returns: TRUE if the request succeeded, FALSE if it failed
454  *
455  * Generic getter for array type properties. Array elements type is
456  * required to be basic.
457  */
wpas_dbus_simple_array_array_property_getter(DBusMessageIter * iter,const int type,struct wpabuf ** array,size_t array_len,DBusError * error)458 dbus_bool_t wpas_dbus_simple_array_array_property_getter(DBusMessageIter *iter,
459 							 const int type,
460 							 struct wpabuf **array,
461 							 size_t array_len,
462 							 DBusError *error)
463 {
464 	DBusMessageIter variant_iter, array_iter;
465 	char type_str[] = "aa?";
466 	char inner_type_str[] = "a?";
467 	const char *sub_type_str;
468 	size_t i;
469 
470 	if (!dbus_type_is_basic(type)) {
471 		dbus_set_error(error, DBUS_ERROR_FAILED,
472 			       "%s: given type is not basic", __func__);
473 		return FALSE;
474 	}
475 
476 	sub_type_str = wpa_dbus_type_as_string(type);
477 	type_str[2] = sub_type_str[0];
478 	inner_type_str[1] = sub_type_str[0];
479 
480 	if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT,
481 					      type_str, &variant_iter)) {
482 		dbus_set_error(error, DBUS_ERROR_FAILED,
483 			       "%s: failed to construct message 1", __func__);
484 		return FALSE;
485 	}
486 	if (!dbus_message_iter_open_container(&variant_iter, DBUS_TYPE_ARRAY,
487 					      inner_type_str, &array_iter)) {
488 		dbus_set_error(error, DBUS_ERROR_FAILED,
489 			       "%s: failed to construct message 2", __func__);
490 		return FALSE;
491 	}
492 
493 	for (i = 0; i < array_len; i++) {
494 		wpa_dbus_dict_bin_array_add_element(&array_iter,
495 						    wpabuf_head(array[i]),
496 						    wpabuf_len(array[i]));
497 
498 	}
499 
500 	if (!dbus_message_iter_close_container(&variant_iter, &array_iter)) {
501 		dbus_set_error(error, DBUS_ERROR_FAILED,
502 			       "%s: failed to close message 2", __func__);
503 		return FALSE;
504 	}
505 
506 	if (!dbus_message_iter_close_container(iter, &variant_iter)) {
507 		dbus_set_error(error, DBUS_ERROR_FAILED,
508 			       "%s: failed to close message 1", __func__);
509 		return FALSE;
510 	}
511 
512 	return TRUE;
513 }
514 
515 
516 /**
517  * wpas_dbus_handler_create_interface - Request registration of a network iface
518  * @message: Pointer to incoming dbus message
519  * @global: %wpa_supplicant global data structure
520  * Returns: The object path of the new interface object,
521  *          or a dbus error message with more information
522  *
523  * Handler function for "CreateInterface" method call. Handles requests
524  * by dbus clients to register a network interface that wpa_supplicant
525  * will manage.
526  */
wpas_dbus_handler_create_interface(DBusMessage * message,struct wpa_global * global)527 DBusMessage * wpas_dbus_handler_create_interface(DBusMessage *message,
528 						 struct wpa_global *global)
529 {
530 	DBusMessageIter iter_dict;
531 	DBusMessage *reply = NULL;
532 	DBusMessageIter iter;
533 	struct wpa_dbus_dict_entry entry;
534 	char *driver = NULL;
535 	char *ifname = NULL;
536 	char *confname = NULL;
537 	char *bridge_ifname = NULL;
538 
539 	dbus_message_iter_init(message, &iter);
540 
541 	if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL))
542 		goto error;
543 	while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
544 		if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
545 			goto error;
546 		if (!os_strcmp(entry.key, "Driver") &&
547 		    (entry.type == DBUS_TYPE_STRING)) {
548 			driver = os_strdup(entry.str_value);
549 			wpa_dbus_dict_entry_clear(&entry);
550 			if (driver == NULL)
551 				goto error;
552 		} else if (!os_strcmp(entry.key, "Ifname") &&
553 			   (entry.type == DBUS_TYPE_STRING)) {
554 			ifname = os_strdup(entry.str_value);
555 			wpa_dbus_dict_entry_clear(&entry);
556 			if (ifname == NULL)
557 				goto error;
558 		} else if (!os_strcmp(entry.key, "ConfigFile") &&
559 			   (entry.type == DBUS_TYPE_STRING)) {
560 			confname = os_strdup(entry.str_value);
561 			wpa_dbus_dict_entry_clear(&entry);
562 			if (confname == NULL)
563 				goto error;
564 		} else if (!os_strcmp(entry.key, "BridgeIfname") &&
565 			   (entry.type == DBUS_TYPE_STRING)) {
566 			bridge_ifname = os_strdup(entry.str_value);
567 			wpa_dbus_dict_entry_clear(&entry);
568 			if (bridge_ifname == NULL)
569 				goto error;
570 		} else {
571 			wpa_dbus_dict_entry_clear(&entry);
572 			goto error;
573 		}
574 	}
575 
576 	if (ifname == NULL)
577 		goto error; /* Required Ifname argument missing */
578 
579 	/*
580 	 * Try to get the wpa_supplicant record for this iface, return
581 	 * an error if we already control it.
582 	 */
583 	if (wpa_supplicant_get_iface(global, ifname) != NULL) {
584 		reply = dbus_message_new_error(message,
585 					       WPAS_DBUS_ERROR_IFACE_EXISTS,
586 					       "wpa_supplicant already "
587 					       "controls this interface.");
588 	} else {
589 		struct wpa_supplicant *wpa_s;
590 		struct wpa_interface iface;
591 		os_memset(&iface, 0, sizeof(iface));
592 		iface.driver = driver;
593 		iface.ifname = ifname;
594 		iface.confname = confname;
595 		iface.bridge_ifname = bridge_ifname;
596 		/* Otherwise, have wpa_supplicant attach to it. */
597 		if ((wpa_s = wpa_supplicant_add_iface(global, &iface))) {
598 			const char *path = wpa_s->dbus_new_path;
599 			reply = dbus_message_new_method_return(message);
600 			dbus_message_append_args(reply, DBUS_TYPE_OBJECT_PATH,
601 			                         &path, DBUS_TYPE_INVALID);
602 		} else {
603 			reply = wpas_dbus_error_unknown_error(
604 				message, "wpa_supplicant couldn't grab this "
605 				"interface.");
606 		}
607 	}
608 
609 out:
610 	os_free(driver);
611 	os_free(ifname);
612 	os_free(confname);
613 	os_free(bridge_ifname);
614 	return reply;
615 
616 error:
617 	reply = wpas_dbus_error_invalid_args(message, NULL);
618 	goto out;
619 }
620 
621 
622 /**
623  * wpas_dbus_handler_remove_interface - Request deregistration of an interface
624  * @message: Pointer to incoming dbus message
625  * @global: wpa_supplicant global data structure
626  * Returns: a dbus message containing a UINT32 indicating success (1) or
627  *          failure (0), or returns a dbus error message with more information
628  *
629  * Handler function for "removeInterface" method call.  Handles requests
630  * by dbus clients to deregister a network interface that wpa_supplicant
631  * currently manages.
632  */
wpas_dbus_handler_remove_interface(DBusMessage * message,struct wpa_global * global)633 DBusMessage * wpas_dbus_handler_remove_interface(DBusMessage *message,
634 						 struct wpa_global *global)
635 {
636 	struct wpa_supplicant *wpa_s;
637 	char *path;
638 	DBusMessage *reply = NULL;
639 
640 	dbus_message_get_args(message, NULL, DBUS_TYPE_OBJECT_PATH, &path,
641 			      DBUS_TYPE_INVALID);
642 
643 	wpa_s = get_iface_by_dbus_path(global, path);
644 	if (wpa_s == NULL)
645 		reply = wpas_dbus_error_iface_unknown(message);
646 	else if (wpa_supplicant_remove_iface(global, wpa_s, 0)) {
647 		reply = wpas_dbus_error_unknown_error(
648 			message, "wpa_supplicant couldn't remove this "
649 			"interface.");
650 	}
651 
652 	return reply;
653 }
654 
655 
656 /**
657  * wpas_dbus_handler_get_interface - Get the object path for an interface name
658  * @message: Pointer to incoming dbus message
659  * @global: %wpa_supplicant global data structure
660  * Returns: The object path of the interface object,
661  *          or a dbus error message with more information
662  *
663  * Handler function for "getInterface" method call.
664  */
wpas_dbus_handler_get_interface(DBusMessage * message,struct wpa_global * global)665 DBusMessage * wpas_dbus_handler_get_interface(DBusMessage *message,
666 					      struct wpa_global *global)
667 {
668 	DBusMessage *reply = NULL;
669 	const char *ifname;
670 	const char *path;
671 	struct wpa_supplicant *wpa_s;
672 
673 	dbus_message_get_args(message, NULL, DBUS_TYPE_STRING, &ifname,
674 			      DBUS_TYPE_INVALID);
675 
676 	wpa_s = wpa_supplicant_get_iface(global, ifname);
677 	if (wpa_s == NULL)
678 		return wpas_dbus_error_iface_unknown(message);
679 
680 	path = wpa_s->dbus_new_path;
681 	reply = dbus_message_new_method_return(message);
682 	if (reply == NULL)
683 		return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
684 					      NULL);
685 	if (!dbus_message_append_args(reply, DBUS_TYPE_OBJECT_PATH, &path,
686 				      DBUS_TYPE_INVALID)) {
687 		dbus_message_unref(reply);
688 		return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
689 					      NULL);
690 	}
691 
692 	return reply;
693 }
694 
695 
696 /**
697  * wpas_dbus_getter_debug_level - Get debug level
698  * @iter: Pointer to incoming dbus message iter
699  * @error: Location to store error on failure
700  * @user_data: Function specific data
701  * Returns: TRUE on success, FALSE on failure
702  *
703  * Getter for "DebugLevel" property.
704  */
wpas_dbus_getter_debug_level(DBusMessageIter * iter,DBusError * error,void * user_data)705 dbus_bool_t wpas_dbus_getter_debug_level(DBusMessageIter *iter,
706 					 DBusError *error,
707 					 void *user_data)
708 {
709 	const char *str;
710 	int idx = wpa_debug_level;
711 
712 	if (idx < 0)
713 		idx = 0;
714 	if (idx > 5)
715 		idx = 5;
716 	str = debug_strings[idx];
717 	return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING,
718 						&str, error);
719 }
720 
721 
722 /**
723  * wpas_dbus_getter_debug_timestamp - Get debug timestamp
724  * @iter: Pointer to incoming dbus message iter
725  * @error: Location to store error on failure
726  * @user_data: Function specific data
727  * Returns: TRUE on success, FALSE on failure
728  *
729  * Getter for "DebugTimestamp" property.
730  */
wpas_dbus_getter_debug_timestamp(DBusMessageIter * iter,DBusError * error,void * user_data)731 dbus_bool_t wpas_dbus_getter_debug_timestamp(DBusMessageIter *iter,
732                                              DBusError *error,
733                                              void *user_data)
734 {
735 	return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_BOOLEAN,
736 						&wpa_debug_timestamp, error);
737 
738 }
739 
740 
741 /**
742  * wpas_dbus_getter_debug_show_keys - Get debug show keys
743  * @iter: Pointer to incoming dbus message iter
744  * @error: Location to store error on failure
745  * @user_data: Function specific data
746  * Returns: TRUE on success, FALSE on failure
747  *
748  * Getter for "DebugShowKeys" property.
749  */
wpas_dbus_getter_debug_show_keys(DBusMessageIter * iter,DBusError * error,void * user_data)750 dbus_bool_t wpas_dbus_getter_debug_show_keys(DBusMessageIter *iter,
751 					     DBusError *error,
752 					     void *user_data)
753 {
754 	return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_BOOLEAN,
755 						&wpa_debug_show_keys, error);
756 
757 }
758 
759 /**
760  * wpas_dbus_setter_debug_level - Set debug level
761  * @iter: Pointer to incoming dbus message iter
762  * @error: Location to store error on failure
763  * @user_data: Function specific data
764  * Returns: TRUE on success, FALSE on failure
765  *
766  * Setter for "DebugLevel" property.
767  */
wpas_dbus_setter_debug_level(DBusMessageIter * iter,DBusError * error,void * user_data)768 dbus_bool_t wpas_dbus_setter_debug_level(DBusMessageIter *iter,
769 					 DBusError *error, void *user_data)
770 {
771 	struct wpa_global *global = user_data;
772 	const char *str = NULL;
773 	int i, val = -1;
774 
775 	if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_STRING,
776 					      &str))
777 		return FALSE;
778 
779 	for (i = 0; debug_strings[i]; i++)
780 		if (os_strcmp(debug_strings[i], str) == 0) {
781 			val = i;
782 			break;
783 		}
784 
785 	if (val < 0 ||
786 	    wpa_supplicant_set_debug_params(global, val, wpa_debug_timestamp,
787 					    wpa_debug_show_keys)) {
788 		dbus_set_error_const(error, DBUS_ERROR_FAILED, "wrong debug "
789 				     "level value");
790 		return FALSE;
791 	}
792 
793 	return TRUE;
794 }
795 
796 
797 /**
798  * wpas_dbus_setter_debug_timestamp - Set debug timestamp
799  * @iter: Pointer to incoming dbus message iter
800  * @error: Location to store error on failure
801  * @user_data: Function specific data
802  * Returns: TRUE on success, FALSE on failure
803  *
804  * Setter for "DebugTimestamp" property.
805  */
wpas_dbus_setter_debug_timestamp(DBusMessageIter * iter,DBusError * error,void * user_data)806 dbus_bool_t wpas_dbus_setter_debug_timestamp(DBusMessageIter *iter,
807 					     DBusError *error,
808 					     void *user_data)
809 {
810 	struct wpa_global *global = user_data;
811 	dbus_bool_t val;
812 
813 	if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_BOOLEAN,
814 					      &val))
815 		return FALSE;
816 
817 	wpa_supplicant_set_debug_params(global, wpa_debug_level, val ? 1 : 0,
818 					wpa_debug_show_keys);
819 	return TRUE;
820 }
821 
822 
823 /**
824  * wpas_dbus_setter_debug_show_keys - Set debug show keys
825  * @iter: Pointer to incoming dbus message iter
826  * @error: Location to store error on failure
827  * @user_data: Function specific data
828  * Returns: TRUE on success, FALSE on failure
829  *
830  * Setter for "DebugShowKeys" property.
831  */
wpas_dbus_setter_debug_show_keys(DBusMessageIter * iter,DBusError * error,void * user_data)832 dbus_bool_t wpas_dbus_setter_debug_show_keys(DBusMessageIter *iter,
833 					     DBusError *error,
834 					     void *user_data)
835 {
836 	struct wpa_global *global = user_data;
837 	dbus_bool_t val;
838 
839 	if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_BOOLEAN,
840 					      &val))
841 		return FALSE;
842 
843 	wpa_supplicant_set_debug_params(global, wpa_debug_level,
844 					wpa_debug_timestamp,
845 					val ? 1 : 0);
846 	return TRUE;
847 }
848 
849 
850 /**
851  * wpas_dbus_getter_interfaces - Request registered interfaces list
852  * @iter: Pointer to incoming dbus message iter
853  * @error: Location to store error on failure
854  * @user_data: Function specific data
855  * Returns: TRUE on success, FALSE on failure
856  *
857  * Getter for "Interfaces" property. Handles requests
858  * by dbus clients to return list of registered interfaces objects
859  * paths
860  */
wpas_dbus_getter_interfaces(DBusMessageIter * iter,DBusError * error,void * user_data)861 dbus_bool_t wpas_dbus_getter_interfaces(DBusMessageIter *iter,
862 					DBusError *error,
863 					void *user_data)
864 {
865 	struct wpa_global *global = user_data;
866 	struct wpa_supplicant *wpa_s;
867 	const char **paths;
868 	unsigned int i = 0, num = 0;
869 	dbus_bool_t success;
870 
871 	for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next)
872 		num++;
873 
874 	paths = os_calloc(num, sizeof(char *));
875 	if (!paths) {
876 		dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
877 		return FALSE;
878 	}
879 
880 	for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next)
881 		paths[i++] = wpa_s->dbus_new_path;
882 
883 	success = wpas_dbus_simple_array_property_getter(iter,
884 							 DBUS_TYPE_OBJECT_PATH,
885 							 paths, num, error);
886 
887 	os_free(paths);
888 	return success;
889 }
890 
891 
892 /**
893  * wpas_dbus_getter_eap_methods - Request supported EAP methods list
894  * @iter: Pointer to incoming dbus message iter
895  * @error: Location to store error on failure
896  * @user_data: Function specific data
897  * Returns: TRUE on success, FALSE on failure
898  *
899  * Getter for "EapMethods" property. Handles requests
900  * by dbus clients to return list of strings with supported EAP methods
901  */
wpas_dbus_getter_eap_methods(DBusMessageIter * iter,DBusError * error,void * user_data)902 dbus_bool_t wpas_dbus_getter_eap_methods(DBusMessageIter *iter,
903 					 DBusError *error, void *user_data)
904 {
905 	char **eap_methods;
906 	size_t num_items = 0;
907 	dbus_bool_t success;
908 
909 	eap_methods = eap_get_names_as_string_array(&num_items);
910 	if (!eap_methods) {
911 		dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
912 		return FALSE;
913 	}
914 
915 	success = wpas_dbus_simple_array_property_getter(iter,
916 							 DBUS_TYPE_STRING,
917 							 eap_methods,
918 							 num_items, error);
919 
920 	while (num_items)
921 		os_free(eap_methods[--num_items]);
922 	os_free(eap_methods);
923 	return success;
924 }
925 
926 
wpas_dbus_get_scan_type(DBusMessage * message,DBusMessageIter * var,char ** type,DBusMessage ** reply)927 static int wpas_dbus_get_scan_type(DBusMessage *message, DBusMessageIter *var,
928 				   char **type, DBusMessage **reply)
929 {
930 	if (dbus_message_iter_get_arg_type(var) != DBUS_TYPE_STRING) {
931 		wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: "
932 			   "Type must be a string");
933 		*reply = wpas_dbus_error_invalid_args(
934 			message, "Wrong Type value type. String required");
935 		return -1;
936 	}
937 	dbus_message_iter_get_basic(var, type);
938 	return 0;
939 }
940 
941 
wpas_dbus_get_scan_ssids(DBusMessage * message,DBusMessageIter * var,struct wpa_driver_scan_params * params,DBusMessage ** reply)942 static int wpas_dbus_get_scan_ssids(DBusMessage *message, DBusMessageIter *var,
943 				    struct wpa_driver_scan_params *params,
944 				    DBusMessage **reply)
945 {
946 	struct wpa_driver_scan_ssid *ssids = params->ssids;
947 	size_t ssids_num = 0;
948 	u8 *ssid;
949 	DBusMessageIter array_iter, sub_array_iter;
950 	char *val;
951 	int len;
952 
953 	if (dbus_message_iter_get_arg_type(var) != DBUS_TYPE_ARRAY) {
954 		wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: ssids "
955 			   "must be an array of arrays of bytes");
956 		*reply = wpas_dbus_error_invalid_args(
957 			message, "Wrong SSIDs value type. Array of arrays of "
958 			"bytes required");
959 		return -1;
960 	}
961 
962 	dbus_message_iter_recurse(var, &array_iter);
963 
964 	if (dbus_message_iter_get_arg_type(&array_iter) != DBUS_TYPE_ARRAY ||
965 	    dbus_message_iter_get_element_type(&array_iter) != DBUS_TYPE_BYTE)
966 	{
967 		wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: ssids "
968 			   "must be an array of arrays of bytes");
969 		*reply = wpas_dbus_error_invalid_args(
970 			message, "Wrong SSIDs value type. Array of arrays of "
971 			"bytes required");
972 		return -1;
973 	}
974 
975 	while (dbus_message_iter_get_arg_type(&array_iter) == DBUS_TYPE_ARRAY)
976 	{
977 		if (ssids_num >= WPAS_MAX_SCAN_SSIDS) {
978 			wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: "
979 				   "Too many ssids specified on scan dbus "
980 				   "call");
981 			*reply = wpas_dbus_error_invalid_args(
982 				message, "Too many ssids specified. Specify "
983 				"at most four");
984 			return -1;
985 		}
986 
987 		dbus_message_iter_recurse(&array_iter, &sub_array_iter);
988 
989 		dbus_message_iter_get_fixed_array(&sub_array_iter, &val, &len);
990 
991 		if (len > MAX_SSID_LEN) {
992 			wpa_printf(MSG_DEBUG,
993 				   "wpas_dbus_handler_scan[dbus]: "
994 				   "SSID too long (len=%d max_len=%d)",
995 				   len, MAX_SSID_LEN);
996 			*reply = wpas_dbus_error_invalid_args(
997 				message, "Invalid SSID: too long");
998 			return -1;
999 		}
1000 
1001 		if (len != 0) {
1002 			ssid = os_malloc(len);
1003 			if (ssid == NULL) {
1004 				wpa_printf(MSG_DEBUG,
1005 					   "wpas_dbus_handler_scan[dbus]: "
1006 					   "out of memory. Cannot allocate "
1007 					   "memory for SSID");
1008 				*reply = dbus_message_new_error(
1009 					message, DBUS_ERROR_NO_MEMORY, NULL);
1010 				return -1;
1011 			}
1012 			os_memcpy(ssid, val, len);
1013 		} else {
1014 			/* Allow zero-length SSIDs */
1015 			ssid = NULL;
1016 		}
1017 
1018 		ssids[ssids_num].ssid = ssid;
1019 		ssids[ssids_num].ssid_len = len;
1020 
1021 		dbus_message_iter_next(&array_iter);
1022 		ssids_num++;
1023 	}
1024 
1025 	params->num_ssids = ssids_num;
1026 	return 0;
1027 }
1028 
1029 
wpas_dbus_get_scan_ies(DBusMessage * message,DBusMessageIter * var,struct wpa_driver_scan_params * params,DBusMessage ** reply)1030 static int wpas_dbus_get_scan_ies(DBusMessage *message, DBusMessageIter *var,
1031 				  struct wpa_driver_scan_params *params,
1032 				  DBusMessage **reply)
1033 {
1034 	u8 *ies = NULL, *nies;
1035 	int ies_len = 0;
1036 	DBusMessageIter array_iter, sub_array_iter;
1037 	char *val;
1038 	int len;
1039 
1040 	if (dbus_message_iter_get_arg_type(var) != DBUS_TYPE_ARRAY) {
1041 		wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: ies must "
1042 			   "be an array of arrays of bytes");
1043 		*reply = wpas_dbus_error_invalid_args(
1044 			message, "Wrong IEs value type. Array of arrays of "
1045 			"bytes required");
1046 		return -1;
1047 	}
1048 
1049 	dbus_message_iter_recurse(var, &array_iter);
1050 
1051 	if (dbus_message_iter_get_arg_type(&array_iter) != DBUS_TYPE_ARRAY ||
1052 	    dbus_message_iter_get_element_type(&array_iter) != DBUS_TYPE_BYTE)
1053 	{
1054 		wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: ies must "
1055 			   "be an array of arrays of bytes");
1056 		*reply = wpas_dbus_error_invalid_args(
1057 			message, "Wrong IEs value type. Array required");
1058 		return -1;
1059 	}
1060 
1061 	while (dbus_message_iter_get_arg_type(&array_iter) == DBUS_TYPE_ARRAY)
1062 	{
1063 		dbus_message_iter_recurse(&array_iter, &sub_array_iter);
1064 
1065 		dbus_message_iter_get_fixed_array(&sub_array_iter, &val, &len);
1066 		if (len == 0) {
1067 			dbus_message_iter_next(&array_iter);
1068 			continue;
1069 		}
1070 
1071 		nies = os_realloc(ies, ies_len + len);
1072 		if (nies == NULL) {
1073 			wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: "
1074 				   "out of memory. Cannot allocate memory for "
1075 				   "IE");
1076 			os_free(ies);
1077 			*reply = dbus_message_new_error(
1078 				message, DBUS_ERROR_NO_MEMORY, NULL);
1079 			return -1;
1080 		}
1081 		ies = nies;
1082 		os_memcpy(ies + ies_len, val, len);
1083 		ies_len += len;
1084 
1085 		dbus_message_iter_next(&array_iter);
1086 	}
1087 
1088 	params->extra_ies = ies;
1089 	params->extra_ies_len = ies_len;
1090 	return 0;
1091 }
1092 
1093 
wpas_dbus_get_scan_channels(DBusMessage * message,DBusMessageIter * var,struct wpa_driver_scan_params * params,DBusMessage ** reply)1094 static int wpas_dbus_get_scan_channels(DBusMessage *message,
1095 				       DBusMessageIter *var,
1096 				       struct wpa_driver_scan_params *params,
1097 				       DBusMessage **reply)
1098 {
1099 	DBusMessageIter array_iter, sub_array_iter;
1100 	int *freqs = NULL, *nfreqs;
1101 	int freqs_num = 0;
1102 
1103 	if (dbus_message_iter_get_arg_type(var) != DBUS_TYPE_ARRAY) {
1104 		wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: "
1105 			   "Channels must be an array of structs");
1106 		*reply = wpas_dbus_error_invalid_args(
1107 			message, "Wrong Channels value type. Array of structs "
1108 			"required");
1109 		return -1;
1110 	}
1111 
1112 	dbus_message_iter_recurse(var, &array_iter);
1113 
1114 	if (dbus_message_iter_get_arg_type(&array_iter) != DBUS_TYPE_STRUCT) {
1115 		wpa_printf(MSG_DEBUG,
1116 			   "wpas_dbus_handler_scan[dbus]: Channels must be an "
1117 			   "array of structs");
1118 		*reply = wpas_dbus_error_invalid_args(
1119 			message, "Wrong Channels value type. Array of structs "
1120 			"required");
1121 		return -1;
1122 	}
1123 
1124 	while (dbus_message_iter_get_arg_type(&array_iter) == DBUS_TYPE_STRUCT)
1125 	{
1126 		int freq, width;
1127 
1128 		dbus_message_iter_recurse(&array_iter, &sub_array_iter);
1129 
1130 		if (dbus_message_iter_get_arg_type(&sub_array_iter) !=
1131 		    DBUS_TYPE_UINT32) {
1132 			wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: "
1133 				   "Channel must by specified by struct of "
1134 				   "two UINT32s %c",
1135 				   dbus_message_iter_get_arg_type(
1136 					   &sub_array_iter));
1137 			*reply = wpas_dbus_error_invalid_args(
1138 				message, "Wrong Channel struct. Two UINT32s "
1139 				"required");
1140 			os_free(freqs);
1141 			return -1;
1142 		}
1143 		dbus_message_iter_get_basic(&sub_array_iter, &freq);
1144 
1145 		if (!dbus_message_iter_next(&sub_array_iter) ||
1146 		    dbus_message_iter_get_arg_type(&sub_array_iter) !=
1147 		    DBUS_TYPE_UINT32) {
1148 			wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: "
1149 				   "Channel must by specified by struct of "
1150 				   "two UINT32s");
1151 			*reply = wpas_dbus_error_invalid_args(
1152 				message,
1153 				"Wrong Channel struct. Two UINT32s required");
1154 			os_free(freqs);
1155 			return -1;
1156 		}
1157 
1158 		dbus_message_iter_get_basic(&sub_array_iter, &width);
1159 
1160 #define FREQS_ALLOC_CHUNK 32
1161 		if (freqs_num % FREQS_ALLOC_CHUNK == 0) {
1162 			nfreqs = os_realloc_array(
1163 				freqs, freqs_num + FREQS_ALLOC_CHUNK,
1164 				sizeof(int));
1165 			if (nfreqs == NULL)
1166 				os_free(freqs);
1167 			freqs = nfreqs;
1168 		}
1169 		if (freqs == NULL) {
1170 			wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: "
1171 				   "out of memory. can't allocate memory for "
1172 				   "freqs");
1173 			*reply = dbus_message_new_error(
1174 				message, DBUS_ERROR_NO_MEMORY, NULL);
1175 			return -1;
1176 		}
1177 
1178 		freqs[freqs_num] = freq;
1179 
1180 		freqs_num++;
1181 		dbus_message_iter_next(&array_iter);
1182 	}
1183 
1184 	nfreqs = os_realloc_array(freqs, freqs_num + 1, sizeof(int));
1185 	if (nfreqs == NULL)
1186 		os_free(freqs);
1187 	freqs = nfreqs;
1188 	if (freqs == NULL) {
1189 		wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: "
1190 			   "out of memory. Can't allocate memory for freqs");
1191 		*reply = dbus_message_new_error(
1192 			message, DBUS_ERROR_NO_MEMORY, NULL);
1193 		return -1;
1194 	}
1195 	freqs[freqs_num] = 0;
1196 
1197 	params->freqs = freqs;
1198 	return 0;
1199 }
1200 
1201 
1202 /**
1203  * wpas_dbus_handler_scan - Request a wireless scan on an interface
1204  * @message: Pointer to incoming dbus message
1205  * @wpa_s: wpa_supplicant structure for a network interface
1206  * Returns: NULL indicating success or DBus error message on failure
1207  *
1208  * Handler function for "Scan" method call of a network device. Requests
1209  * that wpa_supplicant perform a wireless scan as soon as possible
1210  * on a particular wireless interface.
1211  */
wpas_dbus_handler_scan(DBusMessage * message,struct wpa_supplicant * wpa_s)1212 DBusMessage * wpas_dbus_handler_scan(DBusMessage *message,
1213 				     struct wpa_supplicant *wpa_s)
1214 {
1215 	DBusMessage *reply = NULL;
1216 	DBusMessageIter iter, dict_iter, entry_iter, variant_iter;
1217 	char *key = NULL, *type = NULL;
1218 	struct wpa_driver_scan_params params;
1219 	size_t i;
1220 
1221 	os_memset(&params, 0, sizeof(params));
1222 
1223 	dbus_message_iter_init(message, &iter);
1224 
1225 	dbus_message_iter_recurse(&iter, &dict_iter);
1226 
1227 	while (dbus_message_iter_get_arg_type(&dict_iter) ==
1228 			DBUS_TYPE_DICT_ENTRY) {
1229 		dbus_message_iter_recurse(&dict_iter, &entry_iter);
1230 		dbus_message_iter_get_basic(&entry_iter, &key);
1231 		dbus_message_iter_next(&entry_iter);
1232 		dbus_message_iter_recurse(&entry_iter, &variant_iter);
1233 
1234 		if (os_strcmp(key, "Type") == 0) {
1235 			if (wpas_dbus_get_scan_type(message, &variant_iter,
1236 						    &type, &reply) < 0)
1237 				goto out;
1238 		} else if (os_strcmp(key, "SSIDs") == 0) {
1239 			if (wpas_dbus_get_scan_ssids(message, &variant_iter,
1240 						     &params, &reply) < 0)
1241 				goto out;
1242 		} else if (os_strcmp(key, "IEs") == 0) {
1243 			if (wpas_dbus_get_scan_ies(message, &variant_iter,
1244 						   &params, &reply) < 0)
1245 				goto out;
1246 		} else if (os_strcmp(key, "Channels") == 0) {
1247 			if (wpas_dbus_get_scan_channels(message, &variant_iter,
1248 							&params, &reply) < 0)
1249 				goto out;
1250 		} else {
1251 			wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: "
1252 				   "Unknown argument %s", key);
1253 			reply = wpas_dbus_error_invalid_args(message, key);
1254 			goto out;
1255 		}
1256 
1257 		dbus_message_iter_next(&dict_iter);
1258 	}
1259 
1260 	if (!type) {
1261 		wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: "
1262 			   "Scan type not specified");
1263 		reply = wpas_dbus_error_invalid_args(message, key);
1264 		goto out;
1265 	}
1266 
1267 	if (!os_strcmp(type, "passive")) {
1268 		if (params.num_ssids || params.extra_ies_len) {
1269 			wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: "
1270 				   "SSIDs or IEs specified for passive scan.");
1271 			reply = wpas_dbus_error_invalid_args(
1272 				message, "You can specify only Channels in "
1273 				"passive scan");
1274 			goto out;
1275 		} else if (params.freqs && params.freqs[0]) {
1276 			wpa_supplicant_trigger_scan(wpa_s, &params);
1277 		} else {
1278 			wpa_s->scan_req = 2;
1279 			wpa_supplicant_req_scan(wpa_s, 0, 0);
1280 		}
1281 	} else if (!os_strcmp(type, "active")) {
1282 		if (!params.num_ssids) {
1283 			/* Add wildcard ssid */
1284 			params.num_ssids++;
1285 		}
1286 #ifdef CONFIG_AUTOSCAN
1287 		autoscan_deinit(wpa_s);
1288 #endif /* CONFIG_AUTOSCAN */
1289 		wpa_supplicant_trigger_scan(wpa_s, &params);
1290 	} else {
1291 		wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: "
1292 			   "Unknown scan type: %s", type);
1293 		reply = wpas_dbus_error_invalid_args(message,
1294 						     "Wrong scan type");
1295 		goto out;
1296 	}
1297 
1298 out:
1299 	for (i = 0; i < WPAS_MAX_SCAN_SSIDS; i++)
1300 		os_free((u8 *) params.ssids[i].ssid);
1301 	os_free((u8 *) params.extra_ies);
1302 	os_free(params.freqs);
1303 	return reply;
1304 }
1305 
1306 
1307 /*
1308  * wpas_dbus_handler_disconnect - Terminate the current connection
1309  * @message: Pointer to incoming dbus message
1310  * @wpa_s: wpa_supplicant structure for a network interface
1311  * Returns: NotConnected DBus error message if already not connected
1312  * or NULL otherwise.
1313  *
1314  * Handler function for "Disconnect" method call of network interface.
1315  */
wpas_dbus_handler_disconnect(DBusMessage * message,struct wpa_supplicant * wpa_s)1316 DBusMessage * wpas_dbus_handler_disconnect(DBusMessage *message,
1317 					   struct wpa_supplicant *wpa_s)
1318 {
1319 	if (wpa_s->current_ssid != NULL) {
1320 		wpa_s->disconnected = 1;
1321 		wpa_supplicant_deauthenticate(wpa_s,
1322 					      WLAN_REASON_DEAUTH_LEAVING);
1323 
1324 		return NULL;
1325 	}
1326 
1327 	return dbus_message_new_error(message, WPAS_DBUS_ERROR_NOT_CONNECTED,
1328 				      "This interface is not connected");
1329 }
1330 
1331 
1332 /**
1333  * wpas_dbus_new_iface_add_network - Add a new configured network
1334  * @message: Pointer to incoming dbus message
1335  * @wpa_s: wpa_supplicant structure for a network interface
1336  * Returns: A dbus message containing the object path of the new network
1337  *
1338  * Handler function for "AddNetwork" method call of a network interface.
1339  */
wpas_dbus_handler_add_network(DBusMessage * message,struct wpa_supplicant * wpa_s)1340 DBusMessage * wpas_dbus_handler_add_network(DBusMessage *message,
1341 					    struct wpa_supplicant *wpa_s)
1342 {
1343 	DBusMessage *reply = NULL;
1344 	DBusMessageIter	iter;
1345 	struct wpa_ssid *ssid = NULL;
1346 	char path_buf[WPAS_DBUS_OBJECT_PATH_MAX], *path = path_buf;
1347 	DBusError error;
1348 
1349 	dbus_message_iter_init(message, &iter);
1350 
1351 	ssid = wpa_config_add_network(wpa_s->conf);
1352 	if (ssid == NULL) {
1353 		wpa_printf(MSG_ERROR, "wpas_dbus_handler_add_network[dbus]: "
1354 			   "can't add new interface.");
1355 		reply = wpas_dbus_error_unknown_error(
1356 			message,
1357 			"wpa_supplicant could not add "
1358 			"a network on this interface.");
1359 		goto err;
1360 	}
1361 	wpas_notify_network_added(wpa_s, ssid);
1362 	ssid->disabled = 1;
1363 	wpa_config_set_network_defaults(ssid);
1364 
1365 	dbus_error_init(&error);
1366 	if (!set_network_properties(wpa_s, ssid, &iter, &error)) {
1367 		wpa_printf(MSG_DEBUG, "wpas_dbus_handler_add_network[dbus]:"
1368 			   "control interface couldn't set network "
1369 			   "properties");
1370 		reply = wpas_dbus_reply_new_from_error(message, &error,
1371 						       DBUS_ERROR_INVALID_ARGS,
1372 						       "Failed to add network");
1373 		dbus_error_free(&error);
1374 		goto err;
1375 	}
1376 
1377 	/* Construct the object path for this network. */
1378 	os_snprintf(path, WPAS_DBUS_OBJECT_PATH_MAX,
1379 		    "%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%d",
1380 		    wpa_s->dbus_new_path, ssid->id);
1381 
1382 	reply = dbus_message_new_method_return(message);
1383 	if (reply == NULL) {
1384 		reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
1385 					       NULL);
1386 		goto err;
1387 	}
1388 	if (!dbus_message_append_args(reply, DBUS_TYPE_OBJECT_PATH, &path,
1389 				      DBUS_TYPE_INVALID)) {
1390 		dbus_message_unref(reply);
1391 		reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
1392 					       NULL);
1393 		goto err;
1394 	}
1395 
1396 	return reply;
1397 
1398 err:
1399 	if (ssid) {
1400 		wpas_notify_network_removed(wpa_s, ssid);
1401 		wpa_config_remove_network(wpa_s->conf, ssid->id);
1402 	}
1403 	return reply;
1404 }
1405 
1406 
1407 /**
1408  * wpas_dbus_handler_reassociate - Reassociate to current AP
1409  * @message: Pointer to incoming dbus message
1410  * @wpa_s: wpa_supplicant structure for a network interface
1411  * Returns: NotConnected DBus error message if not connected
1412  * or NULL otherwise.
1413  *
1414  * Handler function for "Reassociate" method call of network interface.
1415  */
wpas_dbus_handler_reassociate(DBusMessage * message,struct wpa_supplicant * wpa_s)1416 DBusMessage * wpas_dbus_handler_reassociate(DBusMessage *message,
1417 					    struct wpa_supplicant *wpa_s)
1418 {
1419 	if (wpa_s->current_ssid != NULL) {
1420 		wpa_s->normal_scans = 0;
1421 		wpa_supplicant_reinit_autoscan(wpa_s);
1422 		wpa_s->disconnected = 0;
1423 		wpa_s->reassociate = 1;
1424 		wpa_supplicant_req_scan(wpa_s, 0, 0);
1425 
1426 		return NULL;
1427 	}
1428 
1429 	return dbus_message_new_error(message, WPAS_DBUS_ERROR_NOT_CONNECTED,
1430 				      "This interface is not connected");
1431 }
1432 
1433 
1434 /**
1435  * wpas_dbus_handler_remove_network - Remove a configured network
1436  * @message: Pointer to incoming dbus message
1437  * @wpa_s: wpa_supplicant structure for a network interface
1438  * Returns: NULL on success or dbus error on failure
1439  *
1440  * Handler function for "RemoveNetwork" method call of a network interface.
1441  */
wpas_dbus_handler_remove_network(DBusMessage * message,struct wpa_supplicant * wpa_s)1442 DBusMessage * wpas_dbus_handler_remove_network(DBusMessage *message,
1443 					       struct wpa_supplicant *wpa_s)
1444 {
1445 	DBusMessage *reply = NULL;
1446 	const char *op;
1447 	char *iface = NULL, *net_id = NULL;
1448 	int id;
1449 	struct wpa_ssid *ssid;
1450 
1451 	dbus_message_get_args(message, NULL, DBUS_TYPE_OBJECT_PATH, &op,
1452 			      DBUS_TYPE_INVALID);
1453 
1454 	/* Extract the network ID and ensure the network */
1455 	/* is actually a child of this interface */
1456 	iface = wpas_dbus_new_decompose_object_path(op, 0, &net_id, NULL);
1457 	if (iface == NULL || os_strcmp(iface, wpa_s->dbus_new_path) != 0) {
1458 		reply = wpas_dbus_error_invalid_args(message, op);
1459 		goto out;
1460 	}
1461 
1462 	id = strtoul(net_id, NULL, 10);
1463 	if (errno == EINVAL) {
1464 		reply = wpas_dbus_error_invalid_args(message, op);
1465 		goto out;
1466 	}
1467 
1468 	ssid = wpa_config_get_network(wpa_s->conf, id);
1469 	if (ssid == NULL) {
1470 		reply = wpas_dbus_error_network_unknown(message);
1471 		goto out;
1472 	}
1473 
1474 	wpas_notify_network_removed(wpa_s, ssid);
1475 
1476 	if (wpa_config_remove_network(wpa_s->conf, id) < 0) {
1477 		wpa_printf(MSG_ERROR,
1478 			   "wpas_dbus_handler_remove_network[dbus]: "
1479 			   "error occurred when removing network %d", id);
1480 		reply = wpas_dbus_error_unknown_error(
1481 			message, "error removing the specified network on "
1482 			"this interface.");
1483 		goto out;
1484 	}
1485 
1486 	if (ssid == wpa_s->current_ssid)
1487 		wpa_supplicant_deauthenticate(wpa_s,
1488 					      WLAN_REASON_DEAUTH_LEAVING);
1489 
1490 out:
1491 	os_free(iface);
1492 	os_free(net_id);
1493 	return reply;
1494 }
1495 
1496 
remove_network(void * arg,struct wpa_ssid * ssid)1497 static void remove_network(void *arg, struct wpa_ssid *ssid)
1498 {
1499 	struct wpa_supplicant *wpa_s = arg;
1500 
1501 	wpas_notify_network_removed(wpa_s, ssid);
1502 
1503 	if (wpa_config_remove_network(wpa_s->conf, ssid->id) < 0) {
1504 		wpa_printf(MSG_ERROR,
1505 			   "wpas_dbus_handler_remove_all_networks[dbus]: "
1506 			   "error occurred when removing network %d",
1507 			   ssid->id);
1508 		return;
1509 	}
1510 
1511 	if (ssid == wpa_s->current_ssid)
1512 		wpa_supplicant_disassociate(wpa_s, WLAN_REASON_DEAUTH_LEAVING);
1513 }
1514 
1515 
1516 /**
1517  * wpas_dbus_handler_remove_all_networks - Remove all configured networks
1518  * @message: Pointer to incoming dbus message
1519  * @wpa_s: wpa_supplicant structure for a network interface
1520  * Returns: NULL on success or dbus error on failure
1521  *
1522  * Handler function for "RemoveAllNetworks" method call of a network interface.
1523  */
wpas_dbus_handler_remove_all_networks(DBusMessage * message,struct wpa_supplicant * wpa_s)1524 DBusMessage * wpas_dbus_handler_remove_all_networks(
1525 	DBusMessage *message, struct wpa_supplicant *wpa_s)
1526 {
1527 	/* NB: could check for failure and return an error */
1528 	wpa_config_foreach_network(wpa_s->conf, remove_network, wpa_s);
1529 	return NULL;
1530 }
1531 
1532 
1533 /**
1534  * wpas_dbus_handler_select_network - Attempt association with a network
1535  * @message: Pointer to incoming dbus message
1536  * @wpa_s: wpa_supplicant structure for a network interface
1537  * Returns: NULL on success or dbus error on failure
1538  *
1539  * Handler function for "SelectNetwork" method call of network interface.
1540  */
wpas_dbus_handler_select_network(DBusMessage * message,struct wpa_supplicant * wpa_s)1541 DBusMessage * wpas_dbus_handler_select_network(DBusMessage *message,
1542 					       struct wpa_supplicant *wpa_s)
1543 {
1544 	DBusMessage *reply = NULL;
1545 	const char *op;
1546 	char *iface = NULL, *net_id = NULL;
1547 	int id;
1548 	struct wpa_ssid *ssid;
1549 
1550 	dbus_message_get_args(message, NULL, DBUS_TYPE_OBJECT_PATH, &op,
1551 			      DBUS_TYPE_INVALID);
1552 
1553 	/* Extract the network ID and ensure the network */
1554 	/* is actually a child of this interface */
1555 	iface = wpas_dbus_new_decompose_object_path(op, 0, &net_id, NULL);
1556 	if (iface == NULL || os_strcmp(iface, wpa_s->dbus_new_path) != 0) {
1557 		reply = wpas_dbus_error_invalid_args(message, op);
1558 		goto out;
1559 	}
1560 
1561 	id = strtoul(net_id, NULL, 10);
1562 	if (errno == EINVAL) {
1563 		reply = wpas_dbus_error_invalid_args(message, op);
1564 		goto out;
1565 	}
1566 
1567 	ssid = wpa_config_get_network(wpa_s->conf, id);
1568 	if (ssid == NULL) {
1569 		reply = wpas_dbus_error_network_unknown(message);
1570 		goto out;
1571 	}
1572 
1573 	/* Finally, associate with the network */
1574 	wpa_supplicant_select_network(wpa_s, ssid);
1575 
1576 out:
1577 	os_free(iface);
1578 	os_free(net_id);
1579 	return reply;
1580 }
1581 
1582 
1583 /**
1584  * wpas_dbus_handler_network_reply - Reply to a NetworkRequest signal
1585  * @message: Pointer to incoming dbus message
1586  * @wpa_s: wpa_supplicant structure for a network interface
1587  * Returns: NULL on success or dbus error on failure
1588  *
1589  * Handler function for "NetworkReply" method call of network interface.
1590  */
wpas_dbus_handler_network_reply(DBusMessage * message,struct wpa_supplicant * wpa_s)1591 DBusMessage * wpas_dbus_handler_network_reply(DBusMessage *message,
1592 					      struct wpa_supplicant *wpa_s)
1593 {
1594 #ifdef IEEE8021X_EAPOL
1595 	DBusMessage *reply = NULL;
1596 	const char *op, *field, *value;
1597 	char *iface = NULL, *net_id = NULL;
1598 	int id;
1599 	struct wpa_ssid *ssid;
1600 
1601 	if (!dbus_message_get_args(message, NULL,
1602 	                           DBUS_TYPE_OBJECT_PATH, &op,
1603 	                           DBUS_TYPE_STRING, &field,
1604 	                           DBUS_TYPE_STRING, &value,
1605 			           DBUS_TYPE_INVALID))
1606 		return wpas_dbus_error_invalid_args(message, NULL);
1607 
1608 	/* Extract the network ID and ensure the network */
1609 	/* is actually a child of this interface */
1610 	iface = wpas_dbus_new_decompose_object_path(op, 0, &net_id, NULL);
1611 	if (iface == NULL || os_strcmp(iface, wpa_s->dbus_new_path) != 0) {
1612 		reply = wpas_dbus_error_invalid_args(message, op);
1613 		goto out;
1614 	}
1615 
1616 	id = strtoul(net_id, NULL, 10);
1617 	if (errno == EINVAL) {
1618 		reply = wpas_dbus_error_invalid_args(message, net_id);
1619 		goto out;
1620 	}
1621 
1622 	ssid = wpa_config_get_network(wpa_s->conf, id);
1623 	if (ssid == NULL) {
1624 		reply = wpas_dbus_error_network_unknown(message);
1625 		goto out;
1626 	}
1627 
1628 	if (wpa_supplicant_ctrl_iface_ctrl_rsp_handle(wpa_s, ssid,
1629 						      field, value) < 0)
1630 		reply = wpas_dbus_error_invalid_args(message, field);
1631 	else {
1632 		/* Tell EAP to retry immediately */
1633 		eapol_sm_notify_ctrl_response(wpa_s->eapol);
1634 	}
1635 
1636 out:
1637 	os_free(iface);
1638 	os_free(net_id);
1639 	return reply;
1640 #else /* IEEE8021X_EAPOL */
1641 	wpa_printf(MSG_DEBUG, "CTRL_IFACE: 802.1X not included");
1642 	return wpas_dbus_error_unknown_error(message, "802.1X not included");
1643 #endif /* IEEE8021X_EAPOL */
1644 }
1645 
1646 
1647 /**
1648  * wpas_dbus_handler_add_blob - Store named binary blob (ie, for certificates)
1649  * @message: Pointer to incoming dbus message
1650  * @wpa_s: %wpa_supplicant data structure
1651  * Returns: A dbus message containing an error on failure or NULL on success
1652  *
1653  * Asks wpa_supplicant to internally store a binary blobs.
1654  */
wpas_dbus_handler_add_blob(DBusMessage * message,struct wpa_supplicant * wpa_s)1655 DBusMessage * wpas_dbus_handler_add_blob(DBusMessage *message,
1656 					 struct wpa_supplicant *wpa_s)
1657 {
1658 	DBusMessage *reply = NULL;
1659 	DBusMessageIter	iter, array_iter;
1660 
1661 	char *blob_name;
1662 	u8 *blob_data;
1663 	int blob_len;
1664 	struct wpa_config_blob *blob = NULL;
1665 
1666 	dbus_message_iter_init(message, &iter);
1667 	dbus_message_iter_get_basic(&iter, &blob_name);
1668 
1669 	if (wpa_config_get_blob(wpa_s->conf, blob_name)) {
1670 		return dbus_message_new_error(message,
1671 					      WPAS_DBUS_ERROR_BLOB_EXISTS,
1672 					      NULL);
1673 	}
1674 
1675 	dbus_message_iter_next(&iter);
1676 	dbus_message_iter_recurse(&iter, &array_iter);
1677 
1678 	dbus_message_iter_get_fixed_array(&array_iter, &blob_data, &blob_len);
1679 
1680 	blob = os_zalloc(sizeof(*blob));
1681 	if (!blob) {
1682 		reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
1683 					       NULL);
1684 		goto err;
1685 	}
1686 
1687 	blob->data = os_malloc(blob_len);
1688 	if (!blob->data) {
1689 		reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
1690 					       NULL);
1691 		goto err;
1692 	}
1693 	os_memcpy(blob->data, blob_data, blob_len);
1694 
1695 	blob->len = blob_len;
1696 	blob->name = os_strdup(blob_name);
1697 	if (!blob->name) {
1698 		reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
1699 					       NULL);
1700 		goto err;
1701 	}
1702 
1703 	wpa_config_set_blob(wpa_s->conf, blob);
1704 	wpas_notify_blob_added(wpa_s, blob->name);
1705 
1706 	return reply;
1707 
1708 err:
1709 	if (blob) {
1710 		os_free(blob->name);
1711 		os_free(blob->data);
1712 		os_free(blob);
1713 	}
1714 	return reply;
1715 }
1716 
1717 
1718 /**
1719  * wpas_dbus_handler_get_blob - Get named binary blob (ie, for certificates)
1720  * @message: Pointer to incoming dbus message
1721  * @wpa_s: %wpa_supplicant data structure
1722  * Returns: A dbus message containing array of bytes (blob)
1723  *
1724  * Gets one wpa_supplicant's binary blobs.
1725  */
wpas_dbus_handler_get_blob(DBusMessage * message,struct wpa_supplicant * wpa_s)1726 DBusMessage * wpas_dbus_handler_get_blob(DBusMessage *message,
1727 					 struct wpa_supplicant *wpa_s)
1728 {
1729 	DBusMessage *reply = NULL;
1730 	DBusMessageIter	iter, array_iter;
1731 
1732 	char *blob_name;
1733 	const struct wpa_config_blob *blob;
1734 
1735 	dbus_message_get_args(message, NULL, DBUS_TYPE_STRING, &blob_name,
1736 			      DBUS_TYPE_INVALID);
1737 
1738 	blob = wpa_config_get_blob(wpa_s->conf, blob_name);
1739 	if (!blob) {
1740 		return dbus_message_new_error(message,
1741 					      WPAS_DBUS_ERROR_BLOB_UNKNOWN,
1742 					      "Blob id not set");
1743 	}
1744 
1745 	reply = dbus_message_new_method_return(message);
1746 	if (!reply) {
1747 		reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
1748 					       NULL);
1749 		goto out;
1750 	}
1751 
1752 	dbus_message_iter_init_append(reply, &iter);
1753 
1754 	if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
1755 					      DBUS_TYPE_BYTE_AS_STRING,
1756 					      &array_iter)) {
1757 		dbus_message_unref(reply);
1758 		reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
1759 					       NULL);
1760 		goto out;
1761 	}
1762 
1763 	if (!dbus_message_iter_append_fixed_array(&array_iter, DBUS_TYPE_BYTE,
1764 						  &(blob->data), blob->len)) {
1765 		dbus_message_unref(reply);
1766 		reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
1767 					       NULL);
1768 		goto out;
1769 	}
1770 
1771 	if (!dbus_message_iter_close_container(&iter, &array_iter)) {
1772 		dbus_message_unref(reply);
1773 		reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
1774 					       NULL);
1775 		goto out;
1776 	}
1777 
1778 out:
1779 	return reply;
1780 }
1781 
1782 
1783 /**
1784  * wpas_remove_handler_remove_blob - Remove named binary blob
1785  * @message: Pointer to incoming dbus message
1786  * @wpa_s: %wpa_supplicant data structure
1787  * Returns: NULL on success or dbus error
1788  *
1789  * Asks wpa_supplicant to internally remove a binary blobs.
1790  */
wpas_dbus_handler_remove_blob(DBusMessage * message,struct wpa_supplicant * wpa_s)1791 DBusMessage * wpas_dbus_handler_remove_blob(DBusMessage *message,
1792 					    struct wpa_supplicant *wpa_s)
1793 {
1794 	DBusMessage *reply = NULL;
1795 	char *blob_name;
1796 
1797 	dbus_message_get_args(message, NULL, DBUS_TYPE_STRING, &blob_name,
1798 			      DBUS_TYPE_INVALID);
1799 
1800 	if (wpa_config_remove_blob(wpa_s->conf, blob_name)) {
1801 		return dbus_message_new_error(message,
1802 					      WPAS_DBUS_ERROR_BLOB_UNKNOWN,
1803 					      "Blob id not set");
1804 	}
1805 	wpas_notify_blob_removed(wpa_s, blob_name);
1806 
1807 	return reply;
1808 
1809 }
1810 
1811 /*
1812  * wpas_dbus_handler_flush_bss - Flush the BSS cache
1813  * @message: Pointer to incoming dbus message
1814  * @wpa_s: wpa_supplicant structure for a network interface
1815  * Returns: NULL
1816  *
1817  * Handler function for "FlushBSS" method call of network interface.
1818  */
wpas_dbus_handler_flush_bss(DBusMessage * message,struct wpa_supplicant * wpa_s)1819 DBusMessage * wpas_dbus_handler_flush_bss(DBusMessage *message,
1820 					  struct wpa_supplicant *wpa_s)
1821 {
1822 	dbus_uint32_t age;
1823 
1824 	dbus_message_get_args(message, NULL, DBUS_TYPE_UINT32, &age,
1825 			      DBUS_TYPE_INVALID);
1826 
1827 	if (age == 0)
1828 		wpa_bss_flush(wpa_s);
1829 	else
1830 		wpa_bss_flush_by_age(wpa_s, age);
1831 
1832 	return NULL;
1833 }
1834 
1835 
1836 #ifdef CONFIG_AUTOSCAN
1837 /**
1838  * wpas_dbus_handler_autoscan - Set autoscan parameters for the interface
1839  * @message: Pointer to incoming dbus message
1840  * @wpa_s: wpa_supplicant structure for a network interface
1841  * Returns: NULL
1842  *
1843  * Handler function for "AutoScan" method call of network interface.
1844  */
wpas_dbus_handler_autoscan(DBusMessage * message,struct wpa_supplicant * wpa_s)1845 DBusMessage * wpas_dbus_handler_autoscan(DBusMessage *message,
1846 					 struct wpa_supplicant *wpa_s)
1847 {
1848 	DBusMessage *reply = NULL;
1849 	enum wpa_states state = wpa_s->wpa_state;
1850 	char *arg;
1851 
1852 	dbus_message_get_args(message, NULL, DBUS_TYPE_STRING, &arg,
1853 			      DBUS_TYPE_INVALID);
1854 
1855 	if (arg != NULL && os_strlen(arg) > 0) {
1856 		char *tmp;
1857 		tmp = os_strdup(arg);
1858 		if (tmp == NULL) {
1859 			reply = dbus_message_new_error(message,
1860 						       DBUS_ERROR_NO_MEMORY,
1861 						       NULL);
1862 		} else {
1863 			os_free(wpa_s->conf->autoscan);
1864 			wpa_s->conf->autoscan = tmp;
1865 			if (state == WPA_DISCONNECTED || state == WPA_INACTIVE)
1866 				autoscan_init(wpa_s, 1);
1867 			else if (state == WPA_SCANNING)
1868 				wpa_supplicant_reinit_autoscan(wpa_s);
1869 		}
1870 	} else if (arg != NULL && os_strlen(arg) == 0) {
1871 		os_free(wpa_s->conf->autoscan);
1872 		wpa_s->conf->autoscan = NULL;
1873 		autoscan_deinit(wpa_s);
1874 	} else
1875 		reply = dbus_message_new_error(message,
1876 					       DBUS_ERROR_INVALID_ARGS,
1877 					       NULL);
1878 
1879 	return reply;
1880 }
1881 #endif /* CONFIG_AUTOSCAN */
1882 
1883 
1884 /**
1885  * wpas_dbus_getter_capabilities - Return interface capabilities
1886  * @iter: Pointer to incoming dbus message iter
1887  * @error: Location to store error on failure
1888  * @user_data: Function specific data
1889  * Returns: TRUE on success, FALSE on failure
1890  *
1891  * Getter for "Capabilities" property of an interface.
1892  */
wpas_dbus_getter_capabilities(DBusMessageIter * iter,DBusError * error,void * user_data)1893 dbus_bool_t wpas_dbus_getter_capabilities(DBusMessageIter *iter,
1894 					  DBusError *error, void *user_data)
1895 {
1896 	struct wpa_supplicant *wpa_s = user_data;
1897 	struct wpa_driver_capa capa;
1898 	int res;
1899 	DBusMessageIter iter_dict, iter_dict_entry, iter_dict_val, iter_array,
1900 		variant_iter;
1901 	const char *scans[] = { "active", "passive", "ssid" };
1902 
1903 	if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT,
1904 					      "a{sv}", &variant_iter))
1905 		goto nomem;
1906 
1907 	if (!wpa_dbus_dict_open_write(&variant_iter, &iter_dict))
1908 		goto nomem;
1909 
1910 	res = wpa_drv_get_capa(wpa_s, &capa);
1911 
1912 	/***** pairwise cipher */
1913 	if (res < 0) {
1914 		const char *args[] = {"ccmp", "tkip", "none"};
1915 		if (!wpa_dbus_dict_append_string_array(
1916 			    &iter_dict, "Pairwise", args,
1917 			    sizeof(args) / sizeof(char*)))
1918 			goto nomem;
1919 	} else {
1920 		if (!wpa_dbus_dict_begin_string_array(&iter_dict, "Pairwise",
1921 						      &iter_dict_entry,
1922 						      &iter_dict_val,
1923 						      &iter_array))
1924 			goto nomem;
1925 
1926 		if (capa.enc & WPA_DRIVER_CAPA_ENC_CCMP) {
1927 			if (!wpa_dbus_dict_string_array_add_element(
1928 				    &iter_array, "ccmp"))
1929 				goto nomem;
1930 		}
1931 
1932 		if (capa.enc & WPA_DRIVER_CAPA_ENC_GCMP) {
1933 			if (!wpa_dbus_dict_string_array_add_element(
1934 				    &iter_array, "gcmp"))
1935 				goto nomem;
1936 		}
1937 
1938 		if (capa.enc & WPA_DRIVER_CAPA_ENC_TKIP) {
1939 			if (!wpa_dbus_dict_string_array_add_element(
1940 				    &iter_array, "tkip"))
1941 				goto nomem;
1942 		}
1943 
1944 		if (capa.key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE) {
1945 			if (!wpa_dbus_dict_string_array_add_element(
1946 				    &iter_array, "none"))
1947 				goto nomem;
1948 		}
1949 
1950 		if (!wpa_dbus_dict_end_string_array(&iter_dict,
1951 						    &iter_dict_entry,
1952 						    &iter_dict_val,
1953 						    &iter_array))
1954 			goto nomem;
1955 	}
1956 
1957 	/***** group cipher */
1958 	if (res < 0) {
1959 		const char *args[] = {
1960 			"ccmp", "tkip", "wep104", "wep40"
1961 		};
1962 		if (!wpa_dbus_dict_append_string_array(
1963 			    &iter_dict, "Group", args,
1964 			    sizeof(args) / sizeof(char*)))
1965 			goto nomem;
1966 	} else {
1967 		if (!wpa_dbus_dict_begin_string_array(&iter_dict, "Group",
1968 						      &iter_dict_entry,
1969 						      &iter_dict_val,
1970 						      &iter_array))
1971 			goto nomem;
1972 
1973 		if (capa.enc & WPA_DRIVER_CAPA_ENC_CCMP) {
1974 			if (!wpa_dbus_dict_string_array_add_element(
1975 				    &iter_array, "ccmp"))
1976 				goto nomem;
1977 		}
1978 
1979 		if (capa.enc & WPA_DRIVER_CAPA_ENC_GCMP) {
1980 			if (!wpa_dbus_dict_string_array_add_element(
1981 				    &iter_array, "gcmp"))
1982 				goto nomem;
1983 		}
1984 
1985 		if (capa.enc & WPA_DRIVER_CAPA_ENC_TKIP) {
1986 			if (!wpa_dbus_dict_string_array_add_element(
1987 				    &iter_array, "tkip"))
1988 				goto nomem;
1989 		}
1990 
1991 		if (capa.enc & WPA_DRIVER_CAPA_ENC_WEP104) {
1992 			if (!wpa_dbus_dict_string_array_add_element(
1993 				    &iter_array, "wep104"))
1994 				goto nomem;
1995 		}
1996 
1997 		if (capa.enc & WPA_DRIVER_CAPA_ENC_WEP40) {
1998 			if (!wpa_dbus_dict_string_array_add_element(
1999 				    &iter_array, "wep40"))
2000 				goto nomem;
2001 		}
2002 
2003 		if (!wpa_dbus_dict_end_string_array(&iter_dict,
2004 						    &iter_dict_entry,
2005 						    &iter_dict_val,
2006 						    &iter_array))
2007 			goto nomem;
2008 	}
2009 
2010 	/***** key management */
2011 	if (res < 0) {
2012 		const char *args[] = {
2013 			"wpa-psk", "wpa-eap", "ieee8021x", "wpa-none",
2014 #ifdef CONFIG_WPS
2015 			"wps",
2016 #endif /* CONFIG_WPS */
2017 			"none"
2018 		};
2019 		if (!wpa_dbus_dict_append_string_array(
2020 			    &iter_dict, "KeyMgmt", args,
2021 			    sizeof(args) / sizeof(char*)))
2022 			goto nomem;
2023 	} else {
2024 		if (!wpa_dbus_dict_begin_string_array(&iter_dict, "KeyMgmt",
2025 						      &iter_dict_entry,
2026 						      &iter_dict_val,
2027 						      &iter_array))
2028 			goto nomem;
2029 
2030 		if (!wpa_dbus_dict_string_array_add_element(&iter_array,
2031 							    "none"))
2032 			goto nomem;
2033 
2034 		if (!wpa_dbus_dict_string_array_add_element(&iter_array,
2035 							    "ieee8021x"))
2036 			goto nomem;
2037 
2038 		if (capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA |
2039 				     WPA_DRIVER_CAPA_KEY_MGMT_WPA2)) {
2040 			if (!wpa_dbus_dict_string_array_add_element(
2041 				    &iter_array, "wpa-eap"))
2042 				goto nomem;
2043 
2044 			if (capa.key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FT)
2045 				if (!wpa_dbus_dict_string_array_add_element(
2046 					    &iter_array, "wpa-ft-eap"))
2047 					goto nomem;
2048 
2049 /* TODO: Ensure that driver actually supports sha256 encryption. */
2050 #ifdef CONFIG_IEEE80211W
2051 			if (!wpa_dbus_dict_string_array_add_element(
2052 				    &iter_array, "wpa-eap-sha256"))
2053 				goto nomem;
2054 #endif /* CONFIG_IEEE80211W */
2055 		}
2056 
2057 		if (capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK |
2058 				     WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) {
2059 			if (!wpa_dbus_dict_string_array_add_element(
2060 				    &iter_array, "wpa-psk"))
2061 				goto nomem;
2062 
2063 			if (capa.key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FT_PSK)
2064 				if (!wpa_dbus_dict_string_array_add_element(
2065 					    &iter_array, "wpa-ft-psk"))
2066 					goto nomem;
2067 
2068 /* TODO: Ensure that driver actually supports sha256 encryption. */
2069 #ifdef CONFIG_IEEE80211W
2070 			if (!wpa_dbus_dict_string_array_add_element(
2071 				    &iter_array, "wpa-psk-sha256"))
2072 				goto nomem;
2073 #endif /* CONFIG_IEEE80211W */
2074 		}
2075 
2076 		if (capa.key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE) {
2077 			if (!wpa_dbus_dict_string_array_add_element(
2078 				    &iter_array, "wpa-none"))
2079 				goto nomem;
2080 		}
2081 
2082 
2083 #ifdef CONFIG_WPS
2084 		if (!wpa_dbus_dict_string_array_add_element(&iter_array,
2085 							    "wps"))
2086 			goto nomem;
2087 #endif /* CONFIG_WPS */
2088 
2089 		if (!wpa_dbus_dict_end_string_array(&iter_dict,
2090 						    &iter_dict_entry,
2091 						    &iter_dict_val,
2092 						    &iter_array))
2093 			goto nomem;
2094 	}
2095 
2096 	/***** WPA protocol */
2097 	if (res < 0) {
2098 		const char *args[] = { "rsn", "wpa" };
2099 		if (!wpa_dbus_dict_append_string_array(
2100 			    &iter_dict, "Protocol", args,
2101 			    sizeof(args) / sizeof(char*)))
2102 			goto nomem;
2103 	} else {
2104 		if (!wpa_dbus_dict_begin_string_array(&iter_dict, "Protocol",
2105 						      &iter_dict_entry,
2106 						      &iter_dict_val,
2107 						      &iter_array))
2108 			goto nomem;
2109 
2110 		if (capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA2 |
2111 				     WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) {
2112 			if (!wpa_dbus_dict_string_array_add_element(
2113 				    &iter_array, "rsn"))
2114 				goto nomem;
2115 		}
2116 
2117 		if (capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA |
2118 				     WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK)) {
2119 			if (!wpa_dbus_dict_string_array_add_element(
2120 				    &iter_array, "wpa"))
2121 				goto nomem;
2122 		}
2123 
2124 		if (!wpa_dbus_dict_end_string_array(&iter_dict,
2125 						    &iter_dict_entry,
2126 						    &iter_dict_val,
2127 						    &iter_array))
2128 			goto nomem;
2129 	}
2130 
2131 	/***** auth alg */
2132 	if (res < 0) {
2133 		const char *args[] = { "open", "shared", "leap" };
2134 		if (!wpa_dbus_dict_append_string_array(
2135 			    &iter_dict, "AuthAlg", args,
2136 			    sizeof(args) / sizeof(char*)))
2137 			goto nomem;
2138 	} else {
2139 		if (!wpa_dbus_dict_begin_string_array(&iter_dict, "AuthAlg",
2140 						      &iter_dict_entry,
2141 						      &iter_dict_val,
2142 						      &iter_array))
2143 			goto nomem;
2144 
2145 		if (capa.auth & (WPA_DRIVER_AUTH_OPEN)) {
2146 			if (!wpa_dbus_dict_string_array_add_element(
2147 				    &iter_array, "open"))
2148 				goto nomem;
2149 		}
2150 
2151 		if (capa.auth & (WPA_DRIVER_AUTH_SHARED)) {
2152 			if (!wpa_dbus_dict_string_array_add_element(
2153 				    &iter_array, "shared"))
2154 				goto nomem;
2155 		}
2156 
2157 		if (capa.auth & (WPA_DRIVER_AUTH_LEAP)) {
2158 			if (!wpa_dbus_dict_string_array_add_element(
2159 				    &iter_array, "leap"))
2160 				goto nomem;
2161 		}
2162 
2163 		if (!wpa_dbus_dict_end_string_array(&iter_dict,
2164 						    &iter_dict_entry,
2165 						    &iter_dict_val,
2166 						    &iter_array))
2167 			goto nomem;
2168 	}
2169 
2170 	/***** Scan */
2171 	if (!wpa_dbus_dict_append_string_array(&iter_dict, "Scan", scans,
2172 					       sizeof(scans) / sizeof(char *)))
2173 		goto nomem;
2174 
2175 	/***** Modes */
2176 	if (!wpa_dbus_dict_begin_string_array(&iter_dict, "Modes",
2177 					      &iter_dict_entry,
2178 					      &iter_dict_val,
2179 					      &iter_array))
2180 		goto nomem;
2181 
2182 	if (!wpa_dbus_dict_string_array_add_element(
2183 			    &iter_array, "infrastructure"))
2184 		goto nomem;
2185 
2186 	if (!wpa_dbus_dict_string_array_add_element(
2187 			    &iter_array, "ad-hoc"))
2188 		goto nomem;
2189 
2190 	if (res >= 0) {
2191 		if (capa.flags & (WPA_DRIVER_FLAGS_AP)) {
2192 			if (!wpa_dbus_dict_string_array_add_element(
2193 				    &iter_array, "ap"))
2194 				goto nomem;
2195 		}
2196 
2197 		if (capa.flags & (WPA_DRIVER_FLAGS_P2P_CAPABLE)) {
2198 			if (!wpa_dbus_dict_string_array_add_element(
2199 				    &iter_array, "p2p"))
2200 				goto nomem;
2201 		}
2202 	}
2203 
2204 	if (!wpa_dbus_dict_end_string_array(&iter_dict,
2205 					    &iter_dict_entry,
2206 					    &iter_dict_val,
2207 					    &iter_array))
2208 		goto nomem;
2209 	/***** Modes end */
2210 
2211 	if (res >= 0) {
2212 		dbus_int32_t max_scan_ssid = capa.max_scan_ssids;
2213 
2214 		if (!wpa_dbus_dict_append_int32(&iter_dict, "MaxScanSSID",
2215 						max_scan_ssid))
2216 			goto nomem;
2217 	}
2218 
2219 	if (!wpa_dbus_dict_close_write(&variant_iter, &iter_dict))
2220 		goto nomem;
2221 	if (!dbus_message_iter_close_container(iter, &variant_iter))
2222 		goto nomem;
2223 
2224 	return TRUE;
2225 
2226 nomem:
2227 	dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
2228 	return FALSE;
2229 }
2230 
2231 
2232 /**
2233  * wpas_dbus_getter_state - Get interface state
2234  * @iter: Pointer to incoming dbus message iter
2235  * @error: Location to store error on failure
2236  * @user_data: Function specific data
2237  * Returns: TRUE on success, FALSE on failure
2238  *
2239  * Getter for "State" property.
2240  */
wpas_dbus_getter_state(DBusMessageIter * iter,DBusError * error,void * user_data)2241 dbus_bool_t wpas_dbus_getter_state(DBusMessageIter *iter, DBusError *error,
2242 				   void *user_data)
2243 {
2244 	struct wpa_supplicant *wpa_s = user_data;
2245 	const char *str_state;
2246 	char *state_ls, *tmp;
2247 	dbus_bool_t success = FALSE;
2248 
2249 	str_state = wpa_supplicant_state_txt(wpa_s->wpa_state);
2250 
2251 	/* make state string lowercase to fit new DBus API convention
2252 	 */
2253 	state_ls = tmp = os_strdup(str_state);
2254 	if (!tmp) {
2255 		dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
2256 		return FALSE;
2257 	}
2258 	while (*tmp) {
2259 		*tmp = tolower(*tmp);
2260 		tmp++;
2261 	}
2262 
2263 	success = wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING,
2264 						   &state_ls, error);
2265 
2266 	os_free(state_ls);
2267 
2268 	return success;
2269 }
2270 
2271 
2272 /**
2273  * wpas_dbus_new_iface_get_scanning - Get interface scanning state
2274  * @iter: Pointer to incoming dbus message iter
2275  * @error: Location to store error on failure
2276  * @user_data: Function specific data
2277  * Returns: TRUE on success, FALSE on failure
2278  *
2279  * Getter for "scanning" property.
2280  */
wpas_dbus_getter_scanning(DBusMessageIter * iter,DBusError * error,void * user_data)2281 dbus_bool_t wpas_dbus_getter_scanning(DBusMessageIter *iter, DBusError *error,
2282                                       void *user_data)
2283 {
2284 	struct wpa_supplicant *wpa_s = user_data;
2285 	dbus_bool_t scanning = wpa_s->scanning ? TRUE : FALSE;
2286 
2287 	return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_BOOLEAN,
2288 						&scanning, error);
2289 }
2290 
2291 
2292 /**
2293  * wpas_dbus_getter_ap_scan - Control roaming mode
2294  * @iter: Pointer to incoming dbus message iter
2295  * @error: Location to store error on failure
2296  * @user_data: Function specific data
2297  * Returns: TRUE on success, FALSE on failure
2298  *
2299  * Getter function for "ApScan" property.
2300  */
wpas_dbus_getter_ap_scan(DBusMessageIter * iter,DBusError * error,void * user_data)2301 dbus_bool_t wpas_dbus_getter_ap_scan(DBusMessageIter *iter, DBusError *error,
2302 				     void *user_data)
2303 {
2304 	struct wpa_supplicant *wpa_s = user_data;
2305 	dbus_uint32_t ap_scan = wpa_s->conf->ap_scan;
2306 
2307 	return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT32,
2308 						&ap_scan, error);
2309 }
2310 
2311 
2312 /**
2313  * wpas_dbus_setter_ap_scan - Control roaming mode
2314  * @iter: Pointer to incoming dbus message iter
2315  * @error: Location to store error on failure
2316  * @user_data: Function specific data
2317  * Returns: TRUE on success, FALSE on failure
2318  *
2319  * Setter function for "ApScan" property.
2320  */
wpas_dbus_setter_ap_scan(DBusMessageIter * iter,DBusError * error,void * user_data)2321 dbus_bool_t wpas_dbus_setter_ap_scan(DBusMessageIter *iter, DBusError *error,
2322 				     void *user_data)
2323 {
2324 	struct wpa_supplicant *wpa_s = user_data;
2325 	dbus_uint32_t ap_scan;
2326 
2327 	if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_UINT32,
2328 					      &ap_scan))
2329 		return FALSE;
2330 
2331 	if (wpa_supplicant_set_ap_scan(wpa_s, ap_scan)) {
2332 		dbus_set_error_const(error, DBUS_ERROR_FAILED,
2333 				     "ap_scan must be 0, 1, or 2");
2334 		return FALSE;
2335 	}
2336 	return TRUE;
2337 }
2338 
2339 
2340 /**
2341  * wpas_dbus_getter_fast_reauth - Control fast
2342  * reauthentication (TLS session resumption)
2343  * @iter: Pointer to incoming dbus message iter
2344  * @error: Location to store error on failure
2345  * @user_data: Function specific data
2346  * Returns: TRUE on success, FALSE on failure
2347  *
2348  * Getter function for "FastReauth" property.
2349  */
wpas_dbus_getter_fast_reauth(DBusMessageIter * iter,DBusError * error,void * user_data)2350 dbus_bool_t wpas_dbus_getter_fast_reauth(DBusMessageIter *iter,
2351 					 DBusError *error,
2352 					 void *user_data)
2353 {
2354 	struct wpa_supplicant *wpa_s = user_data;
2355 	dbus_bool_t fast_reauth = wpa_s->conf->fast_reauth ? TRUE : FALSE;
2356 
2357 	return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_BOOLEAN,
2358 						&fast_reauth, error);
2359 }
2360 
2361 
2362 /**
2363  * wpas_dbus_setter_fast_reauth - Control fast
2364  * reauthentication (TLS session resumption)
2365  * @iter: Pointer to incoming dbus message iter
2366  * @error: Location to store error on failure
2367  * @user_data: Function specific data
2368  * Returns: TRUE on success, FALSE on failure
2369  *
2370  * Setter function for "FastReauth" property.
2371  */
wpas_dbus_setter_fast_reauth(DBusMessageIter * iter,DBusError * error,void * user_data)2372 dbus_bool_t wpas_dbus_setter_fast_reauth(DBusMessageIter *iter,
2373 				     DBusError *error,
2374 				     void *user_data)
2375 {
2376 	struct wpa_supplicant *wpa_s = user_data;
2377 	dbus_bool_t fast_reauth;
2378 
2379 	if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_BOOLEAN,
2380 					      &fast_reauth))
2381 		return FALSE;
2382 
2383 	wpa_s->conf->fast_reauth = fast_reauth;
2384 	return TRUE;
2385 }
2386 
2387 
2388 /**
2389  * wpas_dbus_getter_disconnect_reason - Get most recent reason for disconnect
2390  * @iter: Pointer to incoming dbus message iter
2391  * @error: Location to store error on failure
2392  * @user_data: Function specific data
2393  * Returns: TRUE on success, FALSE on failure
2394  *
2395  * Getter for "DisconnectReason" property.  The reason is negative if it is
2396  * locally generated.
2397  */
wpas_dbus_getter_disconnect_reason(DBusMessageIter * iter,DBusError * error,void * user_data)2398 dbus_bool_t wpas_dbus_getter_disconnect_reason(DBusMessageIter *iter,
2399 					       DBusError *error,
2400 					       void *user_data)
2401 {
2402 	struct wpa_supplicant *wpa_s = user_data;
2403 	dbus_int32_t reason = wpa_s->disconnect_reason;
2404 	return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_INT32,
2405 						&reason, error);
2406 }
2407 
2408 
2409 /**
2410  * wpas_dbus_getter_bss_expire_age - Get BSS entry expiration age
2411  * @iter: Pointer to incoming dbus message iter
2412  * @error: Location to store error on failure
2413  * @user_data: Function specific data
2414  * Returns: TRUE on success, FALSE on failure
2415  *
2416  * Getter function for "BSSExpireAge" property.
2417  */
wpas_dbus_getter_bss_expire_age(DBusMessageIter * iter,DBusError * error,void * user_data)2418 dbus_bool_t wpas_dbus_getter_bss_expire_age(DBusMessageIter *iter,
2419 					    DBusError *error,
2420 					    void *user_data)
2421 {
2422 	struct wpa_supplicant *wpa_s = user_data;
2423 	dbus_uint32_t expire_age = wpa_s->conf->bss_expiration_age;
2424 
2425 	return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT32,
2426 						&expire_age, error);
2427 }
2428 
2429 
2430 /**
2431  * wpas_dbus_setter_bss_expire_age - Control BSS entry expiration age
2432  * @iter: Pointer to incoming dbus message iter
2433  * @error: Location to store error on failure
2434  * @user_data: Function specific data
2435  * Returns: TRUE on success, FALSE on failure
2436  *
2437  * Setter function for "BSSExpireAge" property.
2438  */
wpas_dbus_setter_bss_expire_age(DBusMessageIter * iter,DBusError * error,void * user_data)2439 dbus_bool_t wpas_dbus_setter_bss_expire_age(DBusMessageIter *iter,
2440 					    DBusError *error,
2441 					    void *user_data)
2442 {
2443 	struct wpa_supplicant *wpa_s = user_data;
2444 	dbus_uint32_t expire_age;
2445 
2446 	if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_UINT32,
2447 					      &expire_age))
2448 		return FALSE;
2449 
2450 	if (wpa_supplicant_set_bss_expiration_age(wpa_s, expire_age)) {
2451 		dbus_set_error_const(error, DBUS_ERROR_FAILED,
2452 				     "BSSExpireAge must be >= 10");
2453 		return FALSE;
2454 	}
2455 	return TRUE;
2456 }
2457 
2458 
2459 /**
2460  * wpas_dbus_getter_bss_expire_count - Get BSS entry expiration scan count
2461  * @iter: Pointer to incoming dbus message iter
2462  * @error: Location to store error on failure
2463  * @user_data: Function specific data
2464  * Returns: TRUE on success, FALSE on failure
2465  *
2466  * Getter function for "BSSExpireCount" property.
2467  */
wpas_dbus_getter_bss_expire_count(DBusMessageIter * iter,DBusError * error,void * user_data)2468 dbus_bool_t wpas_dbus_getter_bss_expire_count(DBusMessageIter *iter,
2469 					      DBusError *error,
2470 					      void *user_data)
2471 {
2472 	struct wpa_supplicant *wpa_s = user_data;
2473 	dbus_uint32_t expire_count = wpa_s->conf->bss_expiration_scan_count;
2474 
2475 	return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT32,
2476 						&expire_count, error);
2477 }
2478 
2479 
2480 /**
2481  * wpas_dbus_setter_bss_expire_count - Control BSS entry expiration scan count
2482  * @iter: Pointer to incoming dbus message iter
2483  * @error: Location to store error on failure
2484  * @user_data: Function specific data
2485  * Returns: TRUE on success, FALSE on failure
2486  *
2487  * Setter function for "BSSExpireCount" property.
2488  */
wpas_dbus_setter_bss_expire_count(DBusMessageIter * iter,DBusError * error,void * user_data)2489 dbus_bool_t wpas_dbus_setter_bss_expire_count(DBusMessageIter *iter,
2490 					      DBusError *error,
2491 					      void *user_data)
2492 {
2493 	struct wpa_supplicant *wpa_s = user_data;
2494 	dbus_uint32_t expire_count;
2495 
2496 	if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_UINT32,
2497 					      &expire_count))
2498 		return FALSE;
2499 
2500 	if (wpa_supplicant_set_bss_expiration_count(wpa_s, expire_count)) {
2501 		dbus_set_error_const(error, DBUS_ERROR_FAILED,
2502 				     "BSSExpireCount must be > 0");
2503 		return FALSE;
2504 	}
2505 	return TRUE;
2506 }
2507 
2508 
2509 /**
2510  * wpas_dbus_getter_country - Control country code
2511  * @iter: Pointer to incoming dbus message iter
2512  * @error: Location to store error on failure
2513  * @user_data: Function specific data
2514  * Returns: TRUE on success, FALSE on failure
2515  *
2516  * Getter function for "Country" property.
2517  */
wpas_dbus_getter_country(DBusMessageIter * iter,DBusError * error,void * user_data)2518 dbus_bool_t wpas_dbus_getter_country(DBusMessageIter *iter, DBusError *error,
2519 				     void *user_data)
2520 {
2521 	struct wpa_supplicant *wpa_s = user_data;
2522 	char country[3];
2523 	char *str = country;
2524 
2525 	country[0] = wpa_s->conf->country[0];
2526 	country[1] = wpa_s->conf->country[1];
2527 	country[2] = '\0';
2528 
2529 	return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING,
2530 						&str, error);
2531 }
2532 
2533 
2534 /**
2535  * wpas_dbus_setter_country - Control country code
2536  * @iter: Pointer to incoming dbus message iter
2537  * @error: Location to store error on failure
2538  * @user_data: Function specific data
2539  * Returns: TRUE on success, FALSE on failure
2540  *
2541  * Setter function for "Country" property.
2542  */
wpas_dbus_setter_country(DBusMessageIter * iter,DBusError * error,void * user_data)2543 dbus_bool_t wpas_dbus_setter_country(DBusMessageIter *iter, DBusError *error,
2544 				     void *user_data)
2545 {
2546 	struct wpa_supplicant *wpa_s = user_data;
2547 	const char *country;
2548 
2549 	if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_STRING,
2550 					      &country))
2551 		return FALSE;
2552 
2553 	if (!country[0] || !country[1]) {
2554 		dbus_set_error_const(error, DBUS_ERROR_FAILED,
2555 				     "invalid country code");
2556 		return FALSE;
2557 	}
2558 
2559 	if (wpa_s->drv_priv != NULL && wpa_drv_set_country(wpa_s, country)) {
2560 		wpa_printf(MSG_DEBUG, "Failed to set country");
2561 		dbus_set_error_const(error, DBUS_ERROR_FAILED,
2562 				     "failed to set country code");
2563 		return FALSE;
2564 	}
2565 
2566 	wpa_s->conf->country[0] = country[0];
2567 	wpa_s->conf->country[1] = country[1];
2568 	return TRUE;
2569 }
2570 
2571 
2572 /**
2573  * wpas_dbus_getter_scan_interval - Get scan interval
2574  * @iter: Pointer to incoming dbus message iter
2575  * @error: Location to store error on failure
2576  * @user_data: Function specific data
2577  * Returns: TRUE on success, FALSE on failure
2578  *
2579  * Getter function for "ScanInterval" property.
2580  */
wpas_dbus_getter_scan_interval(DBusMessageIter * iter,DBusError * error,void * user_data)2581 dbus_bool_t wpas_dbus_getter_scan_interval(DBusMessageIter *iter,
2582 					   DBusError *error,
2583 					   void *user_data)
2584 {
2585 	struct wpa_supplicant *wpa_s = user_data;
2586 	dbus_int32_t scan_interval = wpa_s->scan_interval;
2587 
2588 	return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_INT32,
2589 						&scan_interval, error);
2590 }
2591 
2592 
2593 /**
2594  * wpas_dbus_setter_scan_interval - Control scan interval
2595  * @iter: Pointer to incoming dbus message iter
2596  * @error: Location to store error on failure
2597  * @user_data: Function specific data
2598  * Returns: TRUE on success, FALSE on failure
2599  *
2600  * Setter function for "ScanInterval" property.
2601  */
wpas_dbus_setter_scan_interval(DBusMessageIter * iter,DBusError * error,void * user_data)2602 dbus_bool_t wpas_dbus_setter_scan_interval(DBusMessageIter *iter,
2603 					   DBusError *error,
2604 					   void *user_data)
2605 {
2606 	struct wpa_supplicant *wpa_s = user_data;
2607 	dbus_int32_t scan_interval;
2608 
2609 	if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_INT32,
2610 					      &scan_interval))
2611 		return FALSE;
2612 
2613 	if (wpa_supplicant_set_scan_interval(wpa_s, scan_interval)) {
2614 		dbus_set_error_const(error, DBUS_ERROR_FAILED,
2615 				     "scan_interval must be >= 0");
2616 		return FALSE;
2617 	}
2618 	return TRUE;
2619 }
2620 
2621 
2622 /**
2623  * wpas_dbus_getter_ifname - Get interface name
2624  * @iter: Pointer to incoming dbus message iter
2625  * @error: Location to store error on failure
2626  * @user_data: Function specific data
2627  * Returns: TRUE on success, FALSE on failure
2628  *
2629  * Getter for "Ifname" property.
2630  */
wpas_dbus_getter_ifname(DBusMessageIter * iter,DBusError * error,void * user_data)2631 dbus_bool_t wpas_dbus_getter_ifname(DBusMessageIter *iter, DBusError *error,
2632 				    void *user_data)
2633 {
2634 	struct wpa_supplicant *wpa_s = user_data;
2635 	const char *ifname = wpa_s->ifname;
2636 
2637 	return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING,
2638 						&ifname, error);
2639 }
2640 
2641 
2642 /**
2643  * wpas_dbus_getter_driver - Get interface name
2644  * @iter: Pointer to incoming dbus message iter
2645  * @error: Location to store error on failure
2646  * @user_data: Function specific data
2647  * Returns: TRUE on success, FALSE on failure
2648  *
2649  * Getter for "Driver" property.
2650  */
wpas_dbus_getter_driver(DBusMessageIter * iter,DBusError * error,void * user_data)2651 dbus_bool_t wpas_dbus_getter_driver(DBusMessageIter *iter, DBusError *error,
2652 				    void *user_data)
2653 {
2654 	struct wpa_supplicant *wpa_s = user_data;
2655 	const char *driver;
2656 
2657 	if (wpa_s->driver == NULL || wpa_s->driver->name == NULL) {
2658 		wpa_printf(MSG_DEBUG, "wpas_dbus_getter_driver[dbus]: "
2659 			   "wpa_s has no driver set");
2660 		dbus_set_error(error, DBUS_ERROR_FAILED, "%s: no driver set",
2661 			       __func__);
2662 		return FALSE;
2663 	}
2664 
2665 	driver = wpa_s->driver->name;
2666 	return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING,
2667 						&driver, error);
2668 }
2669 
2670 
2671 /**
2672  * wpas_dbus_getter_current_bss - Get current bss object path
2673  * @iter: Pointer to incoming dbus message iter
2674  * @error: Location to store error on failure
2675  * @user_data: Function specific data
2676  * Returns: TRUE on success, FALSE on failure
2677  *
2678  * Getter for "CurrentBSS" property.
2679  */
wpas_dbus_getter_current_bss(DBusMessageIter * iter,DBusError * error,void * user_data)2680 dbus_bool_t wpas_dbus_getter_current_bss(DBusMessageIter *iter,
2681 					 DBusError *error,
2682 					 void *user_data)
2683 {
2684 	struct wpa_supplicant *wpa_s = user_data;
2685 	char path_buf[WPAS_DBUS_OBJECT_PATH_MAX], *bss_obj_path = path_buf;
2686 
2687 	if (wpa_s->current_bss)
2688 		os_snprintf(bss_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
2689 			    "%s/" WPAS_DBUS_NEW_BSSIDS_PART "/%u",
2690 			    wpa_s->dbus_new_path, wpa_s->current_bss->id);
2691 	else
2692 		os_snprintf(bss_obj_path, WPAS_DBUS_OBJECT_PATH_MAX, "/");
2693 
2694 	return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_OBJECT_PATH,
2695 						&bss_obj_path, error);
2696 }
2697 
2698 
2699 /**
2700  * wpas_dbus_getter_current_network - Get current network object path
2701  * @iter: Pointer to incoming dbus message iter
2702  * @error: Location to store error on failure
2703  * @user_data: Function specific data
2704  * Returns: TRUE on success, FALSE on failure
2705  *
2706  * Getter for "CurrentNetwork" property.
2707  */
wpas_dbus_getter_current_network(DBusMessageIter * iter,DBusError * error,void * user_data)2708 dbus_bool_t wpas_dbus_getter_current_network(DBusMessageIter *iter,
2709 					     DBusError *error,
2710 					     void *user_data)
2711 {
2712 	struct wpa_supplicant *wpa_s = user_data;
2713 	char path_buf[WPAS_DBUS_OBJECT_PATH_MAX], *net_obj_path = path_buf;
2714 
2715 	if (wpa_s->current_ssid)
2716 		os_snprintf(net_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
2717 			    "%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%u",
2718 			    wpa_s->dbus_new_path, wpa_s->current_ssid->id);
2719 	else
2720 		os_snprintf(net_obj_path, WPAS_DBUS_OBJECT_PATH_MAX, "/");
2721 
2722 	return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_OBJECT_PATH,
2723 						&net_obj_path, error);
2724 }
2725 
2726 
2727 /**
2728  * wpas_dbus_getter_current_auth_mode - Get current authentication type
2729  * @iter: Pointer to incoming dbus message iter
2730  * @error: Location to store error on failure
2731  * @user_data: Function specific data
2732  * Returns: TRUE on success, FALSE on failure
2733  *
2734  * Getter for "CurrentAuthMode" property.
2735  */
wpas_dbus_getter_current_auth_mode(DBusMessageIter * iter,DBusError * error,void * user_data)2736 dbus_bool_t wpas_dbus_getter_current_auth_mode(DBusMessageIter *iter,
2737 					       DBusError *error,
2738 					       void *user_data)
2739 {
2740 	struct wpa_supplicant *wpa_s = user_data;
2741 	const char *eap_mode;
2742 	const char *auth_mode;
2743 	char eap_mode_buf[WPAS_DBUS_AUTH_MODE_MAX];
2744 
2745 	if (wpa_s->wpa_state != WPA_COMPLETED) {
2746 		auth_mode = "INACTIVE";
2747 	} else if (wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X ||
2748 	    wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
2749 		eap_mode = wpa_supplicant_get_eap_mode(wpa_s);
2750 		os_snprintf(eap_mode_buf, WPAS_DBUS_AUTH_MODE_MAX,
2751 			    "EAP-%s", eap_mode);
2752 		auth_mode = eap_mode_buf;
2753 
2754 	} else {
2755 		auth_mode = wpa_key_mgmt_txt(wpa_s->key_mgmt,
2756 					     wpa_s->current_ssid->proto);
2757 	}
2758 
2759 	return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING,
2760 						&auth_mode, error);
2761 }
2762 
2763 
2764 /**
2765  * wpas_dbus_getter_bridge_ifname - Get interface name
2766  * @iter: Pointer to incoming dbus message iter
2767  * @error: Location to store error on failure
2768  * @user_data: Function specific data
2769  * Returns: TRUE on success, FALSE on failure
2770  *
2771  * Getter for "BridgeIfname" property.
2772  */
wpas_dbus_getter_bridge_ifname(DBusMessageIter * iter,DBusError * error,void * user_data)2773 dbus_bool_t wpas_dbus_getter_bridge_ifname(DBusMessageIter *iter,
2774 					   DBusError *error,
2775 					   void *user_data)
2776 {
2777 	struct wpa_supplicant *wpa_s = user_data;
2778 	const char *bridge_ifname = wpa_s->bridge_ifname;
2779 	return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING,
2780 						&bridge_ifname, error);
2781 }
2782 
2783 
2784 /**
2785  * wpas_dbus_getter_bsss - Get array of BSSs objects
2786  * @iter: Pointer to incoming dbus message iter
2787  * @error: Location to store error on failure
2788  * @user_data: Function specific data
2789  * Returns: TRUE on success, FALSE on failure
2790  *
2791  * Getter for "BSSs" property.
2792  */
wpas_dbus_getter_bsss(DBusMessageIter * iter,DBusError * error,void * user_data)2793 dbus_bool_t wpas_dbus_getter_bsss(DBusMessageIter *iter, DBusError *error,
2794 				  void *user_data)
2795 {
2796 	struct wpa_supplicant *wpa_s = user_data;
2797 	struct wpa_bss *bss;
2798 	char **paths;
2799 	unsigned int i = 0;
2800 	dbus_bool_t success = FALSE;
2801 
2802 	paths = os_calloc(wpa_s->num_bss, sizeof(char *));
2803 	if (!paths) {
2804 		dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
2805 		return FALSE;
2806 	}
2807 
2808 	/* Loop through scan results and append each result's object path */
2809 	dl_list_for_each(bss, &wpa_s->bss_id, struct wpa_bss, list_id) {
2810 		paths[i] = os_zalloc(WPAS_DBUS_OBJECT_PATH_MAX);
2811 		if (paths[i] == NULL) {
2812 			dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY,
2813 					     "no memory");
2814 			goto out;
2815 		}
2816 		/* Construct the object path for this BSS. */
2817 		os_snprintf(paths[i++], WPAS_DBUS_OBJECT_PATH_MAX,
2818 			    "%s/" WPAS_DBUS_NEW_BSSIDS_PART "/%u",
2819 			    wpa_s->dbus_new_path, bss->id);
2820 	}
2821 
2822 	success = wpas_dbus_simple_array_property_getter(iter,
2823 							 DBUS_TYPE_OBJECT_PATH,
2824 							 paths, wpa_s->num_bss,
2825 							 error);
2826 
2827 out:
2828 	while (i)
2829 		os_free(paths[--i]);
2830 	os_free(paths);
2831 	return success;
2832 }
2833 
2834 
2835 /**
2836  * wpas_dbus_getter_networks - Get array of networks objects
2837  * @iter: Pointer to incoming dbus message iter
2838  * @error: Location to store error on failure
2839  * @user_data: Function specific data
2840  * Returns: TRUE on success, FALSE on failure
2841  *
2842  * Getter for "Networks" property.
2843  */
wpas_dbus_getter_networks(DBusMessageIter * iter,DBusError * error,void * user_data)2844 dbus_bool_t wpas_dbus_getter_networks(DBusMessageIter *iter, DBusError *error,
2845 				      void *user_data)
2846 {
2847 	struct wpa_supplicant *wpa_s = user_data;
2848 	struct wpa_ssid *ssid;
2849 	char **paths;
2850 	unsigned int i = 0, num = 0;
2851 	dbus_bool_t success = FALSE;
2852 
2853 	if (wpa_s->conf == NULL) {
2854 		wpa_printf(MSG_ERROR, "%s[dbus]: An error occurred getting "
2855 			   "networks list.", __func__);
2856 		dbus_set_error(error, DBUS_ERROR_FAILED, "%s: an error "
2857 			       "occurred getting the networks list", __func__);
2858 		return FALSE;
2859 	}
2860 
2861 	for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
2862 		if (!network_is_persistent_group(ssid))
2863 			num++;
2864 
2865 	paths = os_calloc(num, sizeof(char *));
2866 	if (!paths) {
2867 		dbus_set_error(error, DBUS_ERROR_NO_MEMORY, "no memory");
2868 		return FALSE;
2869 	}
2870 
2871 	/* Loop through configured networks and append object path of each */
2872 	for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
2873 		if (network_is_persistent_group(ssid))
2874 			continue;
2875 		paths[i] = os_zalloc(WPAS_DBUS_OBJECT_PATH_MAX);
2876 		if (paths[i] == NULL) {
2877 			dbus_set_error(error, DBUS_ERROR_NO_MEMORY, "no memory");
2878 			goto out;
2879 		}
2880 
2881 		/* Construct the object path for this network. */
2882 		os_snprintf(paths[i++], WPAS_DBUS_OBJECT_PATH_MAX,
2883 			    "%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%d",
2884 			    wpa_s->dbus_new_path, ssid->id);
2885 	}
2886 
2887 	success = wpas_dbus_simple_array_property_getter(iter,
2888 							 DBUS_TYPE_OBJECT_PATH,
2889 							 paths, num, error);
2890 
2891 out:
2892 	while (i)
2893 		os_free(paths[--i]);
2894 	os_free(paths);
2895 	return success;
2896 }
2897 
2898 
2899 /**
2900  * wpas_dbus_getter_blobs - Get all blobs defined for this interface
2901  * @iter: Pointer to incoming dbus message iter
2902  * @error: Location to store error on failure
2903  * @user_data: Function specific data
2904  * Returns: TRUE on success, FALSE on failure
2905  *
2906  * Getter for "Blobs" property.
2907  */
wpas_dbus_getter_blobs(DBusMessageIter * iter,DBusError * error,void * user_data)2908 dbus_bool_t wpas_dbus_getter_blobs(DBusMessageIter *iter, DBusError *error,
2909 				   void *user_data)
2910 {
2911 	struct wpa_supplicant *wpa_s = user_data;
2912 	DBusMessageIter variant_iter, dict_iter, entry_iter, array_iter;
2913 	struct wpa_config_blob *blob;
2914 
2915 	if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT,
2916 					      "a{say}", &variant_iter) ||
2917 	    !dbus_message_iter_open_container(&variant_iter, DBUS_TYPE_ARRAY,
2918 					      "{say}", &dict_iter)) {
2919 		dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
2920 		return FALSE;
2921 	}
2922 
2923 	blob = wpa_s->conf->blobs;
2924 	while (blob) {
2925 		if (!dbus_message_iter_open_container(&dict_iter,
2926 						      DBUS_TYPE_DICT_ENTRY,
2927 						      NULL, &entry_iter) ||
2928 		    !dbus_message_iter_append_basic(&entry_iter,
2929 						    DBUS_TYPE_STRING,
2930 						    &(blob->name)) ||
2931 		    !dbus_message_iter_open_container(&entry_iter,
2932 						      DBUS_TYPE_ARRAY,
2933 						      DBUS_TYPE_BYTE_AS_STRING,
2934 						      &array_iter) ||
2935 		    !dbus_message_iter_append_fixed_array(&array_iter,
2936 							  DBUS_TYPE_BYTE,
2937 							  &(blob->data),
2938 							  blob->len) ||
2939 		    !dbus_message_iter_close_container(&entry_iter,
2940 						       &array_iter) ||
2941 		    !dbus_message_iter_close_container(&dict_iter,
2942 						       &entry_iter)) {
2943 			dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY,
2944 					     "no memory");
2945 			return FALSE;
2946 		}
2947 
2948 		blob = blob->next;
2949 	}
2950 
2951 	if (!dbus_message_iter_close_container(&variant_iter, &dict_iter) ||
2952 	    !dbus_message_iter_close_container(iter, &variant_iter)) {
2953 		dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
2954 		return FALSE;
2955 	}
2956 
2957 	return TRUE;
2958 }
2959 
2960 
get_bss_helper(struct bss_handler_args * args,DBusError * error,const char * func_name)2961 static struct wpa_bss * get_bss_helper(struct bss_handler_args *args,
2962 				       DBusError *error, const char *func_name)
2963 {
2964 	struct wpa_bss *res = wpa_bss_get_id(args->wpa_s, args->id);
2965 
2966 	if (!res) {
2967 		wpa_printf(MSG_ERROR, "%s[dbus]: no bss with id %d found",
2968 		           func_name, args->id);
2969 		dbus_set_error(error, DBUS_ERROR_FAILED,
2970 			       "%s: BSS %d not found",
2971 			       func_name, args->id);
2972 	}
2973 
2974 	return res;
2975 }
2976 
2977 
2978 /**
2979  * wpas_dbus_getter_bss_bssid - Return the BSSID of a BSS
2980  * @iter: Pointer to incoming dbus message iter
2981  * @error: Location to store error on failure
2982  * @user_data: Function specific data
2983  * Returns: TRUE on success, FALSE on failure
2984  *
2985  * Getter for "BSSID" property.
2986  */
wpas_dbus_getter_bss_bssid(DBusMessageIter * iter,DBusError * error,void * user_data)2987 dbus_bool_t wpas_dbus_getter_bss_bssid(DBusMessageIter *iter, DBusError *error,
2988 				       void *user_data)
2989 {
2990 	struct bss_handler_args *args = user_data;
2991 	struct wpa_bss *res;
2992 
2993 	res = get_bss_helper(args, error, __func__);
2994 	if (!res)
2995 		return FALSE;
2996 
2997 	return wpas_dbus_simple_array_property_getter(iter, DBUS_TYPE_BYTE,
2998 						      res->bssid, ETH_ALEN,
2999 						      error);
3000 }
3001 
3002 
3003 /**
3004  * wpas_dbus_getter_bss_ssid - Return the SSID of a BSS
3005  * @iter: Pointer to incoming dbus message iter
3006  * @error: Location to store error on failure
3007  * @user_data: Function specific data
3008  * Returns: TRUE on success, FALSE on failure
3009  *
3010  * Getter for "SSID" property.
3011  */
wpas_dbus_getter_bss_ssid(DBusMessageIter * iter,DBusError * error,void * user_data)3012 dbus_bool_t wpas_dbus_getter_bss_ssid(DBusMessageIter *iter, DBusError *error,
3013 				      void *user_data)
3014 {
3015 	struct bss_handler_args *args = user_data;
3016 	struct wpa_bss *res;
3017 
3018 	res = get_bss_helper(args, error, __func__);
3019 	if (!res)
3020 		return FALSE;
3021 
3022 	return wpas_dbus_simple_array_property_getter(iter, DBUS_TYPE_BYTE,
3023 						      res->ssid, res->ssid_len,
3024 						      error);
3025 }
3026 
3027 
3028 /**
3029  * wpas_dbus_getter_bss_privacy - Return the privacy flag of a BSS
3030  * @iter: Pointer to incoming dbus message iter
3031  * @error: Location to store error on failure
3032  * @user_data: Function specific data
3033  * Returns: TRUE on success, FALSE on failure
3034  *
3035  * Getter for "Privacy" property.
3036  */
wpas_dbus_getter_bss_privacy(DBusMessageIter * iter,DBusError * error,void * user_data)3037 dbus_bool_t wpas_dbus_getter_bss_privacy(DBusMessageIter *iter,
3038 					 DBusError *error, void *user_data)
3039 {
3040 	struct bss_handler_args *args = user_data;
3041 	struct wpa_bss *res;
3042 	dbus_bool_t privacy;
3043 
3044 	res = get_bss_helper(args, error, __func__);
3045 	if (!res)
3046 		return FALSE;
3047 
3048 	privacy = (res->caps & IEEE80211_CAP_PRIVACY) ? TRUE : FALSE;
3049 	return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_BOOLEAN,
3050 						&privacy, error);
3051 }
3052 
3053 
3054 /**
3055  * wpas_dbus_getter_bss_mode - Return the mode of a BSS
3056  * @iter: Pointer to incoming dbus message iter
3057  * @error: Location to store error on failure
3058  * @user_data: Function specific data
3059  * Returns: TRUE on success, FALSE on failure
3060  *
3061  * Getter for "Mode" property.
3062  */
wpas_dbus_getter_bss_mode(DBusMessageIter * iter,DBusError * error,void * user_data)3063 dbus_bool_t wpas_dbus_getter_bss_mode(DBusMessageIter *iter, DBusError *error,
3064 				      void *user_data)
3065 {
3066 	struct bss_handler_args *args = user_data;
3067 	struct wpa_bss *res;
3068 	const char *mode;
3069 
3070 	res = get_bss_helper(args, error, __func__);
3071 	if (!res)
3072 		return FALSE;
3073 
3074 	if (res->caps & IEEE80211_CAP_IBSS)
3075 		mode = "ad-hoc";
3076 	else
3077 		mode = "infrastructure";
3078 
3079 	return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING,
3080 						&mode, error);
3081 }
3082 
3083 
3084 /**
3085  * wpas_dbus_getter_bss_level - Return the signal strength of a BSS
3086  * @iter: Pointer to incoming dbus message iter
3087  * @error: Location to store error on failure
3088  * @user_data: Function specific data
3089  * Returns: TRUE on success, FALSE on failure
3090  *
3091  * Getter for "Level" property.
3092  */
wpas_dbus_getter_bss_signal(DBusMessageIter * iter,DBusError * error,void * user_data)3093 dbus_bool_t wpas_dbus_getter_bss_signal(DBusMessageIter *iter,
3094 					DBusError *error, void *user_data)
3095 {
3096 	struct bss_handler_args *args = user_data;
3097 	struct wpa_bss *res;
3098 	s16 level;
3099 
3100 	res = get_bss_helper(args, error, __func__);
3101 	if (!res)
3102 		return FALSE;
3103 
3104 	level = (s16) res->level;
3105 	return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_INT16,
3106 						&level, error);
3107 }
3108 
3109 
3110 /**
3111  * wpas_dbus_getter_bss_frequency - Return the frequency of a BSS
3112  * @iter: Pointer to incoming dbus message iter
3113  * @error: Location to store error on failure
3114  * @user_data: Function specific data
3115  * Returns: TRUE on success, FALSE on failure
3116  *
3117  * Getter for "Frequency" property.
3118  */
wpas_dbus_getter_bss_frequency(DBusMessageIter * iter,DBusError * error,void * user_data)3119 dbus_bool_t wpas_dbus_getter_bss_frequency(DBusMessageIter *iter,
3120 					   DBusError *error, void *user_data)
3121 {
3122 	struct bss_handler_args *args = user_data;
3123 	struct wpa_bss *res;
3124 	u16 freq;
3125 
3126 	res = get_bss_helper(args, error, __func__);
3127 	if (!res)
3128 		return FALSE;
3129 
3130 	freq = (u16) res->freq;
3131 	return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT16,
3132 						&freq, error);
3133 }
3134 
3135 
cmp_u8s_desc(const void * a,const void * b)3136 static int cmp_u8s_desc(const void *a, const void *b)
3137 {
3138 	return (*(u8 *) b - *(u8 *) a);
3139 }
3140 
3141 
3142 /**
3143  * wpas_dbus_getter_bss_rates - Return available bit rates of a BSS
3144  * @iter: Pointer to incoming dbus message iter
3145  * @error: Location to store error on failure
3146  * @user_data: Function specific data
3147  * Returns: TRUE on success, FALSE on failure
3148  *
3149  * Getter for "Rates" property.
3150  */
wpas_dbus_getter_bss_rates(DBusMessageIter * iter,DBusError * error,void * user_data)3151 dbus_bool_t wpas_dbus_getter_bss_rates(DBusMessageIter *iter,
3152 				       DBusError *error, void *user_data)
3153 {
3154 	struct bss_handler_args *args = user_data;
3155 	struct wpa_bss *res;
3156 	u8 *ie_rates = NULL;
3157 	u32 *real_rates;
3158 	int rates_num, i;
3159 	dbus_bool_t success = FALSE;
3160 
3161 	res = get_bss_helper(args, error, __func__);
3162 	if (!res)
3163 		return FALSE;
3164 
3165 	rates_num = wpa_bss_get_bit_rates(res, &ie_rates);
3166 	if (rates_num < 0)
3167 		return FALSE;
3168 
3169 	qsort(ie_rates, rates_num, 1, cmp_u8s_desc);
3170 
3171 	real_rates = os_malloc(sizeof(u32) * rates_num);
3172 	if (!real_rates) {
3173 		os_free(ie_rates);
3174 		dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
3175 		return FALSE;
3176 	}
3177 
3178 	for (i = 0; i < rates_num; i++)
3179 		real_rates[i] = ie_rates[i] * 500000;
3180 
3181 	success = wpas_dbus_simple_array_property_getter(iter, DBUS_TYPE_UINT32,
3182 							 real_rates, rates_num,
3183 							 error);
3184 
3185 	os_free(ie_rates);
3186 	os_free(real_rates);
3187 	return success;
3188 }
3189 
3190 
wpas_dbus_get_bss_security_prop(DBusMessageIter * iter,struct wpa_ie_data * ie_data,DBusError * error)3191 static dbus_bool_t wpas_dbus_get_bss_security_prop(DBusMessageIter *iter,
3192 						   struct wpa_ie_data *ie_data,
3193 						   DBusError *error)
3194 {
3195 	DBusMessageIter iter_dict, variant_iter;
3196 	const char *group;
3197 	const char *pairwise[3]; /* max 3 pairwise ciphers is supported */
3198 	const char *key_mgmt[7]; /* max 7 key managements may be supported */
3199 	int n;
3200 
3201 	if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT,
3202 					      "a{sv}", &variant_iter))
3203 		goto nomem;
3204 
3205 	if (!wpa_dbus_dict_open_write(&variant_iter, &iter_dict))
3206 		goto nomem;
3207 
3208 	/* KeyMgmt */
3209 	n = 0;
3210 	if (ie_data->key_mgmt & WPA_KEY_MGMT_PSK)
3211 		key_mgmt[n++] = "wpa-psk";
3212 	if (ie_data->key_mgmt & WPA_KEY_MGMT_FT_PSK)
3213 		key_mgmt[n++] = "wpa-ft-psk";
3214 	if (ie_data->key_mgmt & WPA_KEY_MGMT_PSK_SHA256)
3215 		key_mgmt[n++] = "wpa-psk-sha256";
3216 	if (ie_data->key_mgmt & WPA_KEY_MGMT_IEEE8021X)
3217 		key_mgmt[n++] = "wpa-eap";
3218 	if (ie_data->key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X)
3219 		key_mgmt[n++] = "wpa-ft-eap";
3220 	if (ie_data->key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA256)
3221 		key_mgmt[n++] = "wpa-eap-sha256";
3222 	if (ie_data->key_mgmt & WPA_KEY_MGMT_NONE)
3223 		key_mgmt[n++] = "wpa-none";
3224 
3225 	if (!wpa_dbus_dict_append_string_array(&iter_dict, "KeyMgmt",
3226 					       key_mgmt, n))
3227 		goto nomem;
3228 
3229 	/* Group */
3230 	switch (ie_data->group_cipher) {
3231 	case WPA_CIPHER_WEP40:
3232 		group = "wep40";
3233 		break;
3234 	case WPA_CIPHER_TKIP:
3235 		group = "tkip";
3236 		break;
3237 	case WPA_CIPHER_CCMP:
3238 		group = "ccmp";
3239 		break;
3240 	case WPA_CIPHER_GCMP:
3241 		group = "gcmp";
3242 		break;
3243 	case WPA_CIPHER_WEP104:
3244 		group = "wep104";
3245 		break;
3246 	default:
3247 		group = "";
3248 		break;
3249 	}
3250 
3251 	if (!wpa_dbus_dict_append_string(&iter_dict, "Group", group))
3252 		goto nomem;
3253 
3254 	/* Pairwise */
3255 	n = 0;
3256 	if (ie_data->pairwise_cipher & WPA_CIPHER_TKIP)
3257 		pairwise[n++] = "tkip";
3258 	if (ie_data->pairwise_cipher & WPA_CIPHER_CCMP)
3259 		pairwise[n++] = "ccmp";
3260 	if (ie_data->pairwise_cipher & WPA_CIPHER_GCMP)
3261 		pairwise[n++] = "gcmp";
3262 
3263 	if (!wpa_dbus_dict_append_string_array(&iter_dict, "Pairwise",
3264 					       pairwise, n))
3265 		goto nomem;
3266 
3267 	/* Management group (RSN only) */
3268 	if (ie_data->proto == WPA_PROTO_RSN) {
3269 		switch (ie_data->mgmt_group_cipher) {
3270 #ifdef CONFIG_IEEE80211W
3271 		case WPA_CIPHER_AES_128_CMAC:
3272 			group = "aes128cmac";
3273 			break;
3274 #endif /* CONFIG_IEEE80211W */
3275 		default:
3276 			group = "";
3277 			break;
3278 		}
3279 
3280 		if (!wpa_dbus_dict_append_string(&iter_dict, "MgmtGroup",
3281 						 group))
3282 			goto nomem;
3283 	}
3284 
3285 	if (!wpa_dbus_dict_close_write(&variant_iter, &iter_dict))
3286 		goto nomem;
3287 	if (!dbus_message_iter_close_container(iter, &variant_iter))
3288 		goto nomem;
3289 
3290 	return TRUE;
3291 
3292 nomem:
3293 	dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
3294 	return FALSE;
3295 }
3296 
3297 
3298 /**
3299  * wpas_dbus_getter_bss_wpa - Return the WPA options of a BSS
3300  * @iter: Pointer to incoming dbus message iter
3301  * @error: Location to store error on failure
3302  * @user_data: Function specific data
3303  * Returns: TRUE on success, FALSE on failure
3304  *
3305  * Getter for "WPA" property.
3306  */
wpas_dbus_getter_bss_wpa(DBusMessageIter * iter,DBusError * error,void * user_data)3307 dbus_bool_t wpas_dbus_getter_bss_wpa(DBusMessageIter *iter, DBusError *error,
3308 				     void *user_data)
3309 {
3310 	struct bss_handler_args *args = user_data;
3311 	struct wpa_bss *res;
3312 	struct wpa_ie_data wpa_data;
3313 	const u8 *ie;
3314 
3315 	res = get_bss_helper(args, error, __func__);
3316 	if (!res)
3317 		return FALSE;
3318 
3319 	os_memset(&wpa_data, 0, sizeof(wpa_data));
3320 	ie = wpa_bss_get_vendor_ie(res, WPA_IE_VENDOR_TYPE);
3321 	if (ie) {
3322 		if (wpa_parse_wpa_ie(ie, 2 + ie[1], &wpa_data) < 0) {
3323 			dbus_set_error_const(error, DBUS_ERROR_FAILED,
3324 					     "failed to parse WPA IE");
3325 			return FALSE;
3326 		}
3327 	}
3328 
3329 	return wpas_dbus_get_bss_security_prop(iter, &wpa_data, error);
3330 }
3331 
3332 
3333 /**
3334  * wpas_dbus_getter_bss_rsn - Return the RSN options of a BSS
3335  * @iter: Pointer to incoming dbus message iter
3336  * @error: Location to store error on failure
3337  * @user_data: Function specific data
3338  * Returns: TRUE on success, FALSE on failure
3339  *
3340  * Getter for "RSN" property.
3341  */
wpas_dbus_getter_bss_rsn(DBusMessageIter * iter,DBusError * error,void * user_data)3342 dbus_bool_t wpas_dbus_getter_bss_rsn(DBusMessageIter *iter, DBusError *error,
3343 				     void *user_data)
3344 {
3345 	struct bss_handler_args *args = user_data;
3346 	struct wpa_bss *res;
3347 	struct wpa_ie_data wpa_data;
3348 	const u8 *ie;
3349 
3350 	res = get_bss_helper(args, error, __func__);
3351 	if (!res)
3352 		return FALSE;
3353 
3354 	os_memset(&wpa_data, 0, sizeof(wpa_data));
3355 	ie = wpa_bss_get_ie(res, WLAN_EID_RSN);
3356 	if (ie) {
3357 		if (wpa_parse_wpa_ie(ie, 2 + ie[1], &wpa_data) < 0) {
3358 			dbus_set_error_const(error, DBUS_ERROR_FAILED,
3359 					     "failed to parse RSN IE");
3360 			return FALSE;
3361 		}
3362 	}
3363 
3364 	return wpas_dbus_get_bss_security_prop(iter, &wpa_data, error);
3365 }
3366 
3367 
3368 /**
3369  * wpas_dbus_getter_bss_ies - Return all IEs of a BSS
3370  * @iter: Pointer to incoming dbus message iter
3371  * @error: Location to store error on failure
3372  * @user_data: Function specific data
3373  * Returns: TRUE on success, FALSE on failure
3374  *
3375  * Getter for "IEs" property.
3376  */
wpas_dbus_getter_bss_ies(DBusMessageIter * iter,DBusError * error,void * user_data)3377 dbus_bool_t wpas_dbus_getter_bss_ies(DBusMessageIter *iter, DBusError *error,
3378 				     void *user_data)
3379 {
3380 	struct bss_handler_args *args = user_data;
3381 	struct wpa_bss *res;
3382 
3383 	res = get_bss_helper(args, error, __func__);
3384 	if (!res)
3385 		return FALSE;
3386 
3387 	return wpas_dbus_simple_array_property_getter(iter, DBUS_TYPE_BYTE,
3388 						      res + 1, res->ie_len,
3389 						      error);
3390 }
3391 
3392 
3393 /**
3394  * wpas_dbus_getter_enabled - Check whether network is enabled or disabled
3395  * @iter: Pointer to incoming dbus message iter
3396  * @error: Location to store error on failure
3397  * @user_data: Function specific data
3398  * Returns: TRUE on success, FALSE on failure
3399  *
3400  * Getter for "enabled" property of a configured network.
3401  */
wpas_dbus_getter_enabled(DBusMessageIter * iter,DBusError * error,void * user_data)3402 dbus_bool_t wpas_dbus_getter_enabled(DBusMessageIter *iter, DBusError *error,
3403 				     void *user_data)
3404 {
3405 	struct network_handler_args *net = user_data;
3406 	dbus_bool_t enabled = net->ssid->disabled ? FALSE : TRUE;
3407 
3408 	return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_BOOLEAN,
3409 						&enabled, error);
3410 }
3411 
3412 
3413 /**
3414  * wpas_dbus_setter_enabled - Mark a configured network as enabled or disabled
3415  * @iter: Pointer to incoming dbus message iter
3416  * @error: Location to store error on failure
3417  * @user_data: Function specific data
3418  * Returns: TRUE on success, FALSE on failure
3419  *
3420  * Setter for "Enabled" property of a configured network.
3421  */
wpas_dbus_setter_enabled(DBusMessageIter * iter,DBusError * error,void * user_data)3422 dbus_bool_t wpas_dbus_setter_enabled(DBusMessageIter *iter, DBusError *error,
3423 				     void *user_data)
3424 {
3425 	struct network_handler_args *net = user_data;
3426 	struct wpa_supplicant *wpa_s;
3427 	struct wpa_ssid *ssid;
3428 	dbus_bool_t enable;
3429 
3430 	if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_BOOLEAN,
3431 					      &enable))
3432 		return FALSE;
3433 
3434 	wpa_s = net->wpa_s;
3435 	ssid = net->ssid;
3436 
3437 	if (enable)
3438 		wpa_supplicant_enable_network(wpa_s, ssid);
3439 	else
3440 		wpa_supplicant_disable_network(wpa_s, ssid);
3441 
3442 	return TRUE;
3443 }
3444 
3445 
3446 /**
3447  * wpas_dbus_getter_network_properties - Get options for a configured network
3448  * @iter: Pointer to incoming dbus message iter
3449  * @error: Location to store error on failure
3450  * @user_data: Function specific data
3451  * Returns: TRUE on success, FALSE on failure
3452  *
3453  * Getter for "Properties" property of a configured network.
3454  */
wpas_dbus_getter_network_properties(DBusMessageIter * iter,DBusError * error,void * user_data)3455 dbus_bool_t wpas_dbus_getter_network_properties(DBusMessageIter *iter,
3456 						DBusError *error,
3457 						void *user_data)
3458 {
3459 	struct network_handler_args *net = user_data;
3460 	DBusMessageIter	variant_iter, dict_iter;
3461 	char **iterator;
3462 	char **props = wpa_config_get_all(net->ssid, 1);
3463 	dbus_bool_t success = FALSE;
3464 
3465 	if (!props) {
3466 		dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
3467 		return FALSE;
3468 	}
3469 
3470 	if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, "a{sv}",
3471 					      &variant_iter) ||
3472 	    !wpa_dbus_dict_open_write(&variant_iter, &dict_iter)) {
3473 		dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
3474 		goto out;
3475 	}
3476 
3477 	iterator = props;
3478 	while (*iterator) {
3479 		if (!wpa_dbus_dict_append_string(&dict_iter, *iterator,
3480 						 *(iterator + 1))) {
3481 			dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY,
3482 					     "no memory");
3483 			goto out;
3484 		}
3485 		iterator += 2;
3486 	}
3487 
3488 
3489 	if (!wpa_dbus_dict_close_write(&variant_iter, &dict_iter) ||
3490 	    !dbus_message_iter_close_container(iter, &variant_iter)) {
3491 		dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
3492 		goto out;
3493 	}
3494 
3495 	success = TRUE;
3496 
3497 out:
3498 	iterator = props;
3499 	while (*iterator) {
3500 		os_free(*iterator);
3501 		iterator++;
3502 	}
3503 	os_free(props);
3504 	return success;
3505 }
3506 
3507 
3508 /**
3509  * wpas_dbus_setter_network_properties - Set options for a configured network
3510  * @iter: Pointer to incoming dbus message iter
3511  * @error: Location to store error on failure
3512  * @user_data: Function specific data
3513  * Returns: TRUE on success, FALSE on failure
3514  *
3515  * Setter for "Properties" property of a configured network.
3516  */
wpas_dbus_setter_network_properties(DBusMessageIter * iter,DBusError * error,void * user_data)3517 dbus_bool_t wpas_dbus_setter_network_properties(DBusMessageIter *iter,
3518 						DBusError *error,
3519 						void *user_data)
3520 {
3521 	struct network_handler_args *net = user_data;
3522 	struct wpa_ssid *ssid = net->ssid;
3523 	DBusMessageIter	variant_iter;
3524 
3525 	dbus_message_iter_recurse(iter, &variant_iter);
3526 	return set_network_properties(net->wpa_s, ssid, &variant_iter, error);
3527 }
3528 
3529 
3530 #ifdef CONFIG_AP
3531 
wpas_dbus_handler_subscribe_preq(DBusMessage * message,struct wpa_supplicant * wpa_s)3532 DBusMessage * wpas_dbus_handler_subscribe_preq(
3533 	DBusMessage *message, struct wpa_supplicant *wpa_s)
3534 {
3535 	struct wpas_dbus_priv *priv = wpa_s->global->dbus;
3536 	char *name;
3537 
3538 	if (wpa_s->preq_notify_peer != NULL) {
3539 		if (os_strcmp(dbus_message_get_sender(message),
3540 			      wpa_s->preq_notify_peer) == 0)
3541 			return NULL;
3542 
3543 		return dbus_message_new_error(message,
3544 			WPAS_DBUS_ERROR_SUBSCRIPTION_IN_USE,
3545 			"Another application is already subscribed");
3546 	}
3547 
3548 	name = os_strdup(dbus_message_get_sender(message));
3549 	if (!name)
3550 		return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
3551 					      "out of memory");
3552 
3553 	wpa_s->preq_notify_peer = name;
3554 
3555 	/* Subscribe to clean up if application closes socket */
3556 	wpas_dbus_subscribe_noc(priv);
3557 
3558 	/*
3559 	 * Double-check it's still alive to make sure that we didn't
3560 	 * miss the NameOwnerChanged signal, e.g. while strdup'ing.
3561 	 */
3562 	if (!dbus_bus_name_has_owner(priv->con, name, NULL)) {
3563 		/*
3564 		 * Application no longer exists, clean up.
3565 		 * The return value is irrelevant now.
3566 		 *
3567 		 * Need to check if the NameOwnerChanged handling
3568 		 * already cleaned up because we have processed
3569 		 * DBus messages while checking if the name still
3570 		 * has an owner.
3571 		 */
3572 		if (!wpa_s->preq_notify_peer)
3573 			return NULL;
3574 		os_free(wpa_s->preq_notify_peer);
3575 		wpa_s->preq_notify_peer = NULL;
3576 		wpas_dbus_unsubscribe_noc(priv);
3577 	}
3578 
3579 	return NULL;
3580 }
3581 
3582 
wpas_dbus_handler_unsubscribe_preq(DBusMessage * message,struct wpa_supplicant * wpa_s)3583 DBusMessage * wpas_dbus_handler_unsubscribe_preq(
3584 	DBusMessage *message, struct wpa_supplicant *wpa_s)
3585 {
3586 	struct wpas_dbus_priv *priv = wpa_s->global->dbus;
3587 
3588 	if (!wpa_s->preq_notify_peer)
3589 		return dbus_message_new_error(message,
3590 			WPAS_DBUS_ERROR_NO_SUBSCRIPTION,
3591 			"Not subscribed");
3592 
3593 	if (os_strcmp(wpa_s->preq_notify_peer,
3594 		      dbus_message_get_sender(message)))
3595 		return dbus_message_new_error(message,
3596 			WPAS_DBUS_ERROR_SUBSCRIPTION_EPERM,
3597 			"Can't unsubscribe others");
3598 
3599 	os_free(wpa_s->preq_notify_peer);
3600 	wpa_s->preq_notify_peer = NULL;
3601 	wpas_dbus_unsubscribe_noc(priv);
3602 	return NULL;
3603 }
3604 
3605 
wpas_dbus_signal_preq(struct wpa_supplicant * wpa_s,const u8 * addr,const u8 * dst,const u8 * bssid,const u8 * ie,size_t ie_len,u32 ssi_signal)3606 void wpas_dbus_signal_preq(struct wpa_supplicant *wpa_s,
3607 			   const u8 *addr, const u8 *dst, const u8 *bssid,
3608 			   const u8 *ie, size_t ie_len, u32 ssi_signal)
3609 {
3610 	DBusMessage *msg;
3611 	DBusMessageIter iter, dict_iter;
3612 	struct wpas_dbus_priv *priv = wpa_s->global->dbus;
3613 
3614 	/* Do nothing if the control interface is not turned on */
3615 	if (priv == NULL)
3616 		return;
3617 
3618 	if (wpa_s->preq_notify_peer == NULL)
3619 		return;
3620 
3621 	msg = dbus_message_new_signal(wpa_s->dbus_new_path,
3622 				      WPAS_DBUS_NEW_IFACE_INTERFACE,
3623 				      "ProbeRequest");
3624 	if (msg == NULL)
3625 		return;
3626 
3627 	dbus_message_set_destination(msg, wpa_s->preq_notify_peer);
3628 
3629 	dbus_message_iter_init_append(msg, &iter);
3630 
3631 	if (!wpa_dbus_dict_open_write(&iter, &dict_iter))
3632 		goto fail;
3633 	if (addr && !wpa_dbus_dict_append_byte_array(&dict_iter, "addr",
3634 						     (const char *) addr,
3635 						     ETH_ALEN))
3636 		goto fail;
3637 	if (dst && !wpa_dbus_dict_append_byte_array(&dict_iter, "dst",
3638 						    (const char *) dst,
3639 						    ETH_ALEN))
3640 		goto fail;
3641 	if (bssid && !wpa_dbus_dict_append_byte_array(&dict_iter, "bssid",
3642 						      (const char *) bssid,
3643 						      ETH_ALEN))
3644 		goto fail;
3645 	if (ie && ie_len && !wpa_dbus_dict_append_byte_array(&dict_iter, "ies",
3646 							     (const char *) ie,
3647 							     ie_len))
3648 		goto fail;
3649 	if (ssi_signal && !wpa_dbus_dict_append_int32(&dict_iter, "signal",
3650 						      ssi_signal))
3651 		goto fail;
3652 	if (!wpa_dbus_dict_close_write(&iter, &dict_iter))
3653 		goto fail;
3654 
3655 	dbus_connection_send(priv->con, msg, NULL);
3656 	goto out;
3657 fail:
3658 	wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
3659 out:
3660 	dbus_message_unref(msg);
3661 }
3662 
3663 #endif /* CONFIG_AP */
3664