Search code examples
clinuxwifinetlink

How to use libnl and netlink socket for connect devices to AP programatically?


I'm creating a C library that manages a lot of peripherical of my embedded device. The S.O. used, is a Linux distro compiled with yocto. I'm trying to make some functions to connect my device to wifi (well-know) router, with netlink (using the libnl commands). With the help of this community, I've developed a function able to scan the routers in the area. Some of you know how to use the libnl command to connecting my device to router wifi? I've developed the following code, that tries to connect to an AP called "Validator_Test" (that have no authentication password). The software return no error, but my device still remain disconnected from the AP. Some of you know what is wrong in my code? Unfortunately, i've not found any example or documentation for this operation.

static int ap_conn() {

struct nl_msg *msg = nlmsg_alloc();

int if_index = if_nametoindex("wlan0"); // Use this wireless interface for scanning.

// Open socket to kernel.
struct nl_sock *socket = nl_socket_alloc();  // Allocate new netlink socket in memory.
genl_connect(socket);  // Create file descriptor and bind socket.
int driver_id = genl_ctrl_resolve(socket, "nl80211");  // Find the nl80211 driver ID.

genlmsg_put(msg, 0, 0, driver_id, 0, (NLM_F_REQUEST | NLM_F_ACK), NL80211_CMD_CONNECT, 0); 

nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_index);  // Add message attribute, which interface to use.

nla_put(msg, NL80211_ATTR_SSID, strlen("Validator_Test"), "Validator_Test"); 

nla_put(msg, NL80211_ATTR_MAC, strlen("00:1e:42:21:e4:e9"), "00:1e:42:21:e4:e9");  

int ret = nl_send_auto_complete(socket, msg);  // Send the message.
printf("NL80211_CMD_CONNECT sent %d bytes to the kernel.\n", ret);
ret = nl_recvmsgs_default(socket);  // Retrieve the kernel's answer. callback_dump() prints SSIDs to stdout.
nlmsg_free(msg);

if (ret < 0) {
    printf("ERROR: nl_recvmsgs_default() returned %d (%s).\n", ret, nl_geterror(-ret));
    return ret;
}

nla_put_failure:
return -ENOSPC;

}

Thanks to all of you!


Solution

  • Thanks for the code.

    Based on your code, I modified and did the test here; it works. The source code is at: https://github.com/neojou/nl80211/blob/master/test_connect/src/test_connect_nl80211.c

    Some suggestions for this:

    1. Make sure the test environment is correct

      Before test the code, maybe you can try to use iw to do the test. iw is the open source tool, which uses netlink also. you can type "sudo iw wlan0 connect Validator_Test" and then use iwconfig to see if it is connected or not first. ( Suppose there is no security setting at the AP as you said )

    2. there are two differences between your source code and mine

      (1) don't need to set NL80211_ATTR_MAC

      (2) ret = nl_recvmsgs_default(socket);

      not sure if there is any judgement of the return value of your ap_conn(), but it seems better to return 0 in ap_conn(), when nl_recvmsgs_default() returns 0.