Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Getting started with wpa_supplicant using C

Before people jump to conclusion saying this is a duplicate post, I'd like to point out that I have gone through the other posts on this topic but really haven't found a solution.


What I need

My goal is to access the wpa_supplicant from a C program to do the following:

  1. See active connections
  2. Detect when interfaces goes down
  3. Connect to AP/Setup an AP and so on

What I've found out

  • I don't need DBus if I need to write a C program to communicate with wpa_supplicant
  • I can make use of the functions in wpa_ctrl.h by just including these files in my project directory
  • Here are some links I found related to this question. 1, 2, 3
  • I've also gone through the official documentation which talks about external programs using wpa_ctrl.c

Why the above does not actually solve the problem

  • Most of the posts I found on SO and other related websites regarding this issue point to resources like official documentation which is good but does not solve the problem
  • In a lot of these posts, people have given up pursuing this or have worked out a solution but haven't posted it online.
  • For a novice in this topic, it'll be helpful if one can post a working example -- the 'hello world' of wpa_supplicant.

What I've done so far

  • From this link, I copied wpa_supplicant-2.5/src/common/wpa_ctrl.h into wpa_supplicant-2.5/src/utils directory (since common.h had many dependencies). I then wrote a simple C program hostapd_cli.c in the same directory which is shown below. I get an undefined reference to 'wpa_ctrl_open' error

    #include "includes.h"
    #include <dirent.h>
    #include "wpa_ctrl.h"
    #include "common.h"
    static struct wpa_ctrl *ctrl_conn;
    static int hostapd_cli_quit = 0;
    static int hostapd_cli_attached = 0;
    static const char *ctrl_iface_dir = "/var/run/wpa_supplicant";
    static char *ctrl_ifname = NULL;
    static int ping_interval = 5;
    
    int main()
    {
        ctrl_conn = wpa_ctrl_open(ctrl_iface_dir);
        if (!ctrl_conn){
            printf("Could not get ctrl interface!\n");
            return -1;
        }
        return 0;
    }
    

Makefile

C=gcc
CFLAGS=-lpthread
DEPS = includes.h wpa_ctrl.h common.h
OBJ = wpa_ctrl.o hostapd_cli.o

%.o: %.c $(DEPS)
$(CC) -c -o $@ $< $(CFLAGS)

main: $(OBJ)
gcc -o $@ $^ $(CFLAGS)

.PHONY: clean

clean:
rm -f *.o *~ core $(INCDIR)/*~ 

Build log

 gcc -o main wpa_ctrl.o hostapd_cli.o -lpthread
 hostapd_cli.o: In function `main':
 hostapd_cli.c:(.text+0xf): undefined reference to `wpa_ctrl_open'
 collect2: error: ld returned 1 exit status
 Makefile:10: recipe for target 'main' failed
 make: *** [main] Error 1

There's not much material on how to use these files and integrate it to an external project or how to compile it and I'm kinda clueless. Any help on how to proceed will be really appreciated.

Edit 1: Corrected typo and added build log

like image 289
am3 Avatar asked Jul 06 '16 02:07

am3


People also ask

How do I start WPA Supplicant?

You can use wpa_supplicant to connect to hidden networks. To do it you need to edit the configuration file /etc/wpa_supplicant. conf, commenting your current lines and adding the following lines, then run: wpa_supplicant -c /etc/wpa_supplicant.

Is IWD better than wpa_supplicant?

IWD is the iNet Wireless Daemon maintained by Intel and designed to offer better efficiency and modern features over the commonly used WPA_Supplicant.

How does wpa_supplicant work?

wpa_supplicant selects a BSS based on its configuration. wpa_supplicant requests the driver to associate with the chosen BSS. If WPA-EAP: the integrated IEEE 802.1X Supplicant or external Xsupplicant completes EAP authentication with the authentication server (proxied by the Authenticator in the AP).

Where do I put WPA Supplicant?

This wpa_supplicant. conf file can be created and placed on the SD card using the same system you used to copy the Raspbian image to the SD card, allowing you to boot up a Raspberry Pi for the first time and have it automatically connect to your wifi network.


3 Answers

This answer comes too late for OP to find useful, but perhaps it will help others who stumble on this same problem.

In wpa_supplicant-2.9, you don't need to compile wpa_ctrl.c with your own source files. Instead, first build libwpa_client.so (or libwpa_client.a) from the wpa_supplicant sources: $make -C wpa_supplicant libwpa_client.so

Then, link the shared libraries to building your own program. You will need to add the include paths too. Eg) $gcc main.c -Iwpa_supplicant-2.9/src/common -I.wpa_supplicant2-9/src/utils -lwpa_client

like image 89
Lenny Avatar answered Oct 25 '22 09:10

Lenny


undefined reference to `wpa_ctrl_open'

That's a linker error. If the command,

$ nm wpa_ctrl.o

reveals that it defines wpa_ctrl_open, then your immediate problem may be just the command-line order. Try:

gcc -o main hostapd_cli.o wpa_ctrl.o -lpthread

because hostapd_cli references symbols in wpa_ctrl.o. Otherwise, you need to find the source code that does define that symbol, so you can link to it.

Edit: Apparently you need to define a couple of symbols.

HTH.

like image 26
James K. Lowden Avatar answered Oct 25 '22 07:10

James K. Lowden


Okay, so I got it to work on my raspberry pi. All credit goes to Gyph on the raspberry pi forums (link: https://www.raspberrypi.org/forums/viewtopic.php?t=42949).

Files needed

in wpa_supplicant/src/common : 
wpa_ctrl.h 
wpa_ctrl.c


in wpa_supplicant/src/utils : 
build_config.h 
common.h 
includes.h 
os.h 
os_unix.c 
wpabuf.h 
wpa_debug.h
your own file

Run following commands to compile:

gcc -Wall -Wextra -I ./ -MMD -c -g -o wpa_ctrl.o wpa_ctrl.c -D CONFIG_CTRL_IFACE -D CONFIG_CTRL_IFACE_UNIX
gcc -Wall -Wextra -I ./ -MMD -c -g -o os_unix.o os_unix.c -D CONFIG_CTRL_IFACE -D CONFIG_CTRL_IFACE_UNIX
gcc -Wall -Wextra -o your_file your_file.c os_unix.o wpa_ctrol.o

To work with wpa_supplicant, I've found it easiest to just copy hostapd_cli, and adjust it to my needs. Note that if you are with wpa_supplicant and not hostapd, you will have to adjust the ctrl_iface_dir variable. (For me it is " /var/run/wpa_supplicant").

like image 42
Tigris Avatar answered Oct 25 '22 09:10

Tigris