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