Search code examples
c++linuxarmlinux-device-driverandroid-wifi

Writing an external program to interface with wpa_supplicant in C++


As I understand it one can simply link wpa_ctrl.c into an external program and then you are able to use it's functions to control and receive information from wpa_supplicant.

Could someone please provide an example, preferably in C++, how you would:

  1. Link the external program to the wpa_ctrl.c file.
  2. What the code would look like to do a 'scan' and then print 'scan_results'.

I'm new to coding on an embedded linux platform and there are no examples of this anywhere. Many thanks in advance!


Solution

  • The program wpa_cli is an example of exactly what you want. The wpa_supplicant project support the V=1 option to see what is needed to create this executable. Here is the result for my ARM build,

    gcc -c -o wpa_cli.o -MMD -O2 -Wall -g -I src -I src/utils \
      -Iusr_ARM/include/libnl3 \
      -DCONFIG_BACKEND_FILE -DCONFIG_IEEE80211W  -DCONFIG_DRIVER_WEXT \
      -DCONFIG_WIRELESS_EXTENSION  -DCONFIG_DRIVER_NL80211 -DCONFIG_LIBNL20 \
      -DEAP_PSK -DIEEE8021X_EAPOL -DCONFIG_SHA256 -DCONFIG_CTRL_IFACE \
      -DCONFIG_CTRL_IFACE_UNIX  -DCONFIG_SME \
       wpa_cli.c
    
    gcc  -o wpa_cli wpa_cli.o ../src/common/wpa_ctrl.o ../src/utils/wpa_debug.o \
       ../src/utils/common.o ../src/utils/os_unix.o ../src/utils/eloop.o \
       ../src/utils/edit_simple.o -lrt
    

    Substitute your paths to get headers for the version of the wpa_supplicant used on your target ARM device (in the first command). Link with all of the object files listed in the second command and link with the real-time library (with -lrt). You can also look at the wpa_cli.c for your version of the wpa_supplicant to get examples of how to send commands to the supplicant process.

    The object list includes wpa_ctrl.o (as you guessed) and many others. Some of them may not be needed, depending on features you use, but I would start with the complete list and then trim them after you have a functioning example.

    The license is the generous BSD on this source.

    Here is wpa_cli_cmd_scan() which sends the scan request,

    static int wpa_cli_cmd_scan(struct wpa_ctrl *ctrl, int argc, char *argv[])
    {
        return wpa_cli_cmd(ctrl, "SCAN", 0, argc, argv);
    }
    

    You probably also want the scan_results; it is in the same file as wpa_cli_cmd_scan_results().

    The API is also well documented under wpa_supplicant control interface, where you can extend your working example. Make sure you get source that matches the version of the wpa_supplicant in use on your system. The commands above are for an eglibc Linux system; It looks like bionic (Android library) supplies the -lrt by default. If you can run the commands, rm wpa_cli.o; rm wpa_cli; make V=1 in the wpa_supplicant directory of a build for your device you will see the exact commands needed.

    You probably don't need the edit_simple.o file. However, the eloop is likely needed to get unsolicited events from the drivers when the scan request is completed; at least if you want to work with many different Wifi chips. The steps are,

    1. Send SCAN.
    2. Wait for <SCAN_COMPLETE>.
    3. Send SCAN_RESULTS.