wpa_supplicant modificar instalar etc create conf comando arch linux embedded dbus

linux - modificar - D-Bus tutorial en C para comunicarse con wpa_supplicant



wireless arch linux (3)

Estoy tratando de escribir algún código para comunicarme con wpa_supplicant usando DBUS. Como estoy trabajando en un sistema integrado (ARM), me gustaría evitar el uso de Python o GLib. Me pregunto si soy estúpido porque realmente tengo la sensación de que no hay documentación clara y clara sobre D-Bus. Incluso con el oficial, ¡o bien la documentación es demasiado alta o los ejemplos que se muestran están usando Glib! Documentación que he consultado: http://www.freedesktop.org/wiki/Software/dbus

Encontré un buen artículo sobre el uso de D-Bus en C: http://www.matthew.ath.cx/articles/dbus

Sin embargo, este artículo es bastante antiguo y no está lo suficientemente completo. También encontré la API de c ++ - dbus pero también aquí, ¡no encuentro NINGUNA documentación! He estado buscando en wpa_supplicant y en el código fuente de NetworkManager, ¡pero es una pesadilla! También he estado buscando en la "API de D-Bus de bajo nivel", ¡pero esto no me dice cómo extraer un parámetro de cadena de un mensaje de D-Bus! http://dbus.freedesktop.org/doc/api/html/index.html

Aquí hay un código que escribí para probar un poco, pero realmente tengo problemas para extraer valores de cadena. Lo siento por el código fuente largo, pero si alguien quiere probarlo ... Mi configuración de D-Bus parece estar bien porque "ya" detecta las señales de "StateChanged" de wpa_supplicant pero no puede imprimir el estado:

#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <signal.h> #include <string.h> #include <dbus/dbus.h> //#include "wpa_supp_dbus.h" /* Content of wpa_supp_dbus.h */ #define WPAS_DBUS_SERVICE "fi.epitest.hostap.WPASupplicant" #define WPAS_DBUS_PATH "/fi/epitest/hostap/WPASupplicant" #define WPAS_DBUS_INTERFACE "fi.epitest.hostap.WPASupplicant" #define WPAS_DBUS_PATH_INTERFACES WPAS_DBUS_PATH "/Interfaces" #define WPAS_DBUS_IFACE_INTERFACE WPAS_DBUS_INTERFACE ".Interface" #define WPAS_DBUS_NETWORKS_PART "Networks" #define WPAS_DBUS_IFACE_NETWORK WPAS_DBUS_INTERFACE ".Network" #define WPAS_DBUS_BSSIDS_PART "BSSIDs" #define WPAS_DBUS_IFACE_BSSID WPAS_DBUS_INTERFACE ".BSSID" int running = 1; void stopLoop(int sig) { running = 0; } void sendScan() { // TODO ! } void loop(DBusConnection* conn) { DBusMessage* msg; DBusMessageIter args; DBusMessageIter subArgs; int argType; int i; int buffSize = 1024; char strValue[buffSize]; const char* member = 0; sendScan(); while (running) { // non blocking read of the next available message dbus_connection_read_write(conn, 0); msg = dbus_connection_pop_message(conn); // loop again if we haven''t read a message if (!msg) { printf("No message received, waiting a little .../n"); sleep(1); continue; } else printf("Got a message, will analyze it .../n"); // Print the message member printf("Got message for interface %s/n", dbus_message_get_interface(msg)); member = dbus_message_get_member(msg); if(member) printf("Got message member %s/n", member); // Check has argument if (!dbus_message_iter_init(msg, &args)) { printf("Message has no argument/n"); continue; } else { // Go through arguments while(1) { argType = dbus_message_iter_get_arg_type(&args); if (argType == DBUS_TYPE_STRING) { printf("Got string argument, extracting .../n"); /* FIXME : got weird characters dbus_message_iter_get_basic(&args, &strValue); */ /* FIXME : segmentation fault ! dbus_message_iter_get_fixed_array( &args, &strValue, buffSize); */ /* FIXME : segmentation fault ! dbus_message_iter_recurse(&args, &subArgs); */ /* FIXME : deprecated! if(dbus_message_iter_get_array_len(&args) > buffSize) printf("message content to big for local buffer!"); */ //printf("String value was %s/n", strValue); } else printf("Arg type not implemented yet !/n"); if(dbus_message_iter_has_next(&args)) dbus_message_iter_next(&args); else break; } printf("No more arguments!/n"); } // free the message dbus_message_unref(msg); } } int main(int argc, char* argv[]) { DBusError err; DBusConnection* conn; int ret; char signalDesc[1024]; // Signal description as string // Signal handling signal(SIGKILL, stopLoop); signal(SIGTERM, stopLoop); // Initialize err struct dbus_error_init(&err); // connect to the bus conn = dbus_bus_get(DBUS_BUS_SYSTEM, &err); if (dbus_error_is_set(&err)) { fprintf(stderr, "Connection Error (%s)/n", err.message); dbus_error_free(&err); } if (!conn) { exit(1); } // request a name on the bus ret = dbus_bus_request_name(conn, WPAS_DBUS_SERVICE, 0, &err); if (dbus_error_is_set(&err)) { fprintf(stderr, "Name Error (%s)/n", err.message); dbus_error_free(&err); } /* Connect to signal */ // Interface signal .. sprintf(signalDesc, "type=''signal'',interface=''%s''", WPAS_DBUS_IFACE_INTERFACE); dbus_bus_add_match(conn, signalDesc, &err); dbus_connection_flush(conn); if (dbus_error_is_set(&err)) { fprintf(stderr, "Match Error (%s)/n", err.message); exit(1); } // Network signal .. sprintf(signalDesc, "type=''signal'',interface=''%s''", WPAS_DBUS_IFACE_NETWORK); dbus_bus_add_match(conn, signalDesc, &err); dbus_connection_flush(conn); if (dbus_error_is_set(&err)) { fprintf(stderr, "Match Error (%s)/n", err.message); exit(1); } // Bssid signal .. sprintf(signalDesc, "type=''signal'',interface=''%s''", WPAS_DBUS_IFACE_BSSID); dbus_bus_add_match(conn, signalDesc, &err); dbus_connection_flush(conn); if (dbus_error_is_set(&err)) { fprintf(stderr, "Match Error (%s)/n", err.message); exit(1); } // Do main loop loop(conn); // Main loop exited printf("Main loop stopped, exiting .../n"); dbus_connection_close(conn); return 0; }

¡Cualquier puntero a cualquier tutorial agradable, completo y de bajo nivel de C es muy apreciado! También estoy planeando hacer una llamada a un método remoto, así que si el tutorial cubre este tema, ¡sería genial! Decir que no soy muy inteligente porque no lo consigo con el tutorial oficial también se agradece :-p!

¿O hay otra forma de comunicarse con wpa_supplicant (excepto el uso de wpa_cli)?

EDITAR 1:

Usando ''qdbusviewer'' y la capacidad de introspección, esto me ayudó mucho a descubrir qué y cómo funciona wpa_supplicant usando dbus. ¡Saltando que esto ayudaría a alguien más!

Edición 2:

¡Probablemente vendrá cuando encuentre una manera de leer valores de cadena en D-Bus!


El siguiente fragmento de código funciona para mí

if (argType == DBUS_TYPE_STRING) { printf("Got string argument, extracting .../n"); char* strBuffer = NULL; dbus_message_iter_get_basic(&args, &strBuffer); printf("Received string: /n %s /n",strBuffer); }


Ha renunciado a las herramientas que lo ayudarían a aprender D-Bus con mayor facilidad y está utilizando la implementación de bajo nivel de libdbus, por lo que quizás merezca ser molestado. Por cierto, ¿estás hablando de ARM, como un teléfono celular ARM? Con tal vez 500 Mhz y 256 MB de RAM? En este caso, el procesador es adecuado para usar glib, Qt o incluso python. Y D-Bus es más útil cuando está escribiendo código controlado por eventos asíncronos, con un bucle principal integrado, por ejemplo desde glib, incluso cuando está utilizando el libdbus de bajo nivel (tiene funciones para conectarse al bucle principal de glib, por ejemplo).

Ya que estás usando la biblioteca de bajo nivel, entonces la documentación es lo que ya tienes:

http://dbus.freedesktop.org/doc/api/html/index.html

Además, el código fuente de libdbus también forma parte de la documentación:

http://dbus.freedesktop.org/doc/api/html/files.html

El principal punto de entrada para la documentación es la página de Módulos (en particular, la sección de API pública):

http://dbus.freedesktop.org/doc/api/html/modules.html

Para el manejo de mensajes, la sección DBusMessage es la relevante: DBusMessage

Ahí tienes la documentación para las funciones que analizan valores de elementos. En su caso, comenzó con un dbus_message_iter_get_basic. Como se describe en los documentos, la recuperación de la cadena requiere una variable const char **, ya que el valor devuelto apuntará a la cadena asignada previamente en el mensaje recibido:

Así que para int32 debería ser un "dbus_int32_t *" y para un "const char **". El valor devuelto es por referencia y no debe liberarse.

Por lo tanto, no puede definir una matriz, porque libdbus no copiará el texto a su matriz. Si necesita guardar la cadena, primero obtenga la referencia de la cadena constante, luego seleccione su propia matriz.

Luego intentaste obtener una matriz fija sin mover el iterador. Necesita una llamada al siguiente iterador (dbus_message_iter_next) entre la cadena básica y la matriz fija. Mismo derecho antes de recurrir en el sub iterador.

Finalmente, no llama a get_array_len para obtener el número de elementos en la matriz. A partir de los documentos, solo devuelve los conteos de bytes. En su lugar, recorre el iterador secundario utilizando iter_next de la misma manera que debería haberlo hecho con el iterador principal. Una vez que haya iterado más allá del final de la matriz, dbus_message_iter_get_arg_type devolverá DBUS_TYPE_INVALID.

Para obtener más información, lea el manual de referencia, no busque un tutorial. O simplemente use una implementación de d-bus razonable:

https://developer.gnome.org/gio/2.36/gdbus-codegen.html

El GDBus de GIO crea automáticamente envoltorios para sus llamadas de d-bus.

http://qt-project.org/doc/qt-4.8/intro-to-dbus.html

http://dbus.freedesktop.org/doc/dbus-python/doc/tutorial.html

etc.


No necesita utilizar / entender el funcionamiento de dbus si solo necesita escribir un programa en C para comunicarse con wpa_supplicant. Realicé ingeniería inversa del código fuente de wpa_cli. Pasó por su implementación y usó las funciones provistas en wpa_ctrl.h / c. Esta implementación se encarga de todo. ¡Puedes usar / modificar lo que quieras, construir tu ejecutable y listo!

Aquí está el enlace oficial a ctrl_interface de wpa_supplicant: http://hostap.epitest.fi/wpa_supplicant/devel/ctrl_iface_page.html