dbus_new_handlers.c 88 KB

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