return NL_SKIP;
}
-static int __netconfig_request_netlink_scan(struct nl_sock *socket, int if_index, int id)
+static int __netconfig_request_netlink_scan(struct nl_sock *socket, int if_index, int id, char *ssid)
{
struct netconfig_netlink_scan_results results = { .done = 0, .aborted = 0 };
struct nl_msg *msg = NULL;
/** Set nl message and callback functions. */
genlmsg_put(msg, 0, 0, id, 0, 0, NL80211_CMD_TRIGGER_SCAN, 0);
nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_index);
- nla_put(ssids, 1, 0, "");
+ if (!ssid)
+ nla_put(ssids, 1, 0, "");
+ else
+ nla_put(ssids, 1, strlen(ssid), ssid);
nla_put_nested(msg, NL80211_ATTR_SCAN_SSIDS, ssids);
nlmsg_free(ssids);
return 0;
}
-gboolean handle_netlink_scan(Wifi *wifi, GDBusMethodInvocation *context)
+static int __netconfig_initialize_nl80211(netconfig_nl_global *global)
+{
+ int err = 0;
+
+ global->if_index = __netconfig_get_interface_index(WIFI_IFNAME);
+ if (global->if_index < 0) {
+ DBG("Failed to get interface index");
+ return -1;
+ }
+
+ global->socket = nl_socket_alloc();
+ if (!global->socket) {
+ DBG("Failed to allocate netlink socket.");
+ return -ENOMEM;
+ }
+
+ if (genl_connect(global->socket)) {
+ DBG("Failed to connect to generic netlink.");
+ err = -ENOLINK;
+ goto fail;
+ }
+
+ global->id = genl_ctrl_resolve(global->socket, "nl80211");
+ if (global->id < 0) {
+ DBG("Failed to find the nl80211 driver");
+ err = -ENOENT;
+ goto fail;
+ }
+
+ return 0;
+
+fail:
+ nl_socket_free(global->socket);
+ return err;
+}
+
+static int __netconfig_initialize_nl_msg(netconfig_nl_global *global)
+{
+ if (global == NULL) {
+ DBG("Invalid parameter.");
+ return -EINVAL;
+ }
+
+ global->msg = nlmsg_alloc();
+ if (global->msg == NULL) {
+ DBG("Failed to allocate netlink message");
+ return -ENOMEM;
+ }
+
+ /* Set command into message */
+ genlmsg_put(global->msg, 0, 0, global->id, 0, NLM_F_DUMP, NL80211_CMD_GET_SCAN, 0);
+ nla_put_u32(global->msg, NL80211_ATTR_IFINDEX, global->if_index);
+ nl_socket_modify_cb(global->socket, NL_CB_VALID, NL_CB_CUSTOM, __netconfig_netlink_scan_cb, NULL);
+
+ return 0;
+}
+
+int handle_netlink_scan(Wifi *wifi, GDBusMethodInvocation *context)
{
DBG("");
- int if_index = __netconfig_get_interface_index(WIFI_IFNAME);
+ netconfig_nl_global global = {
+ .id = -1,
+ .if_index = -1,
+ .socket = NULL,
+ .msg = NULL,
+ };
- /** Open socket to kernel. */
- struct nl_sock *socket = nl_socket_alloc();
- genl_connect(socket);
- int id = genl_ctrl_resolve(socket, "nl80211");
+ /** Initialize netlink socket */
+ int ret = __netconfig_initialize_nl80211(&global);
+ if (ret < 0) {
+ DBG("__netconfig_initialize_nl80211() failed, error %d", ret);
+ wifi_complete_netlink_specific_scan(wifi, context);
+ return ret;
+ }
/** Request NL80211_CMD_TRIGGER_SCAN to the kernel. */
- int err = __netconfig_request_netlink_scan(socket, if_index, id);
- if (err != 0) {
- DBG("__netconfig_request_netlink_scan() failed, error %d", err);
+ ret = __netconfig_request_netlink_scan(global.socket, global.if_index, global.id, NULL);
+ if (ret < 0) {
+ DBG("__netconfig_request_netlink_scan() failed, error %d", ret);
wifi_complete_netlink_scan(wifi, context);
- return err;
+ return ret;
}
- /** Get info of all available APs. */
- struct nl_msg *msg = nlmsg_alloc();
- genlmsg_put(msg, 0, 0, id, 0, NLM_F_DUMP, NL80211_CMD_GET_SCAN, 0);
- nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_index);
- nl_socket_modify_cb(socket, NL_CB_VALID, NL_CB_CUSTOM, __netconfig_netlink_scan_cb, NULL);
+ ret = __netconfig_initialize_nl_msg(&global);
+ if (ret < 0) {
+ DBG("__netconfig_initialize_nl_msg() failed, error %d", ret);
+ wifi_complete_netlink_specific_scan(wifi, context);
+ return ret;
+ }
- int ret = nl_send_auto_complete(socket, msg);
+ ret = nl_send_auto_complete(global.socket, global.msg);
DBG("NL80211_CMD_GET_SCAN sent %d bytes to the kernel", ret);
/** Receive the kernel message. */
- ret = nl_recvmsgs_default(socket);
- nlmsg_free(msg);
+ ret = nl_recvmsgs_default(global.socket);
+ nlmsg_free(global.msg);
if (ret < 0) {
DBG("nl_recvmsgs_default() failed. ret: %d (error: %s)", ret, nl_geterror(-ret));
wifi_complete_netlink_scan(wifi, context);
}
wifi_complete_netlink_scan(wifi, context);
- return TRUE;
+ return 1;
+}
+
+int handle_netlink_specific_scan(Wifi *wifi, GDBusMethodInvocation *context, gchar *ssid)
+{
+ DBG("ssid: %s", ssid);
+ netconfig_nl_global global = {
+ .id = -1,
+ .if_index = -1,
+ .socket = NULL,
+ .msg = NULL,
+ };
+
+ /** Initialize netlink socket */
+ int ret = __netconfig_initialize_nl80211(&global);
+ if (ret < 0) {
+ DBG("__netconfig_initialize_nl80211() failed, error %d", ret);
+ wifi_complete_netlink_specific_scan(wifi, context);
+ return ret;
+ }
+
+ /** Request NL80211_CMD_TRIGGER_SCAN to the kernel. */
+ ret = __netconfig_request_netlink_scan(global.socket, global.if_index, global.id, ssid);
+ if (ret != 0) {
+ DBG("__netconfig_request_netlink_scan() failed, error %d", ret);
+ wifi_complete_netlink_specific_scan(wifi, context);
+ return ret;
+ }
+
+ ret = __netconfig_initialize_nl_msg(&global);
+ if (ret < 0) {
+ DBG("__netconfig_initialize_nl_msg() failed, error %d", ret);
+ wifi_complete_netlink_specific_scan(wifi, context);
+ return ret;
+ }
+
+ ret = nl_send_auto_complete(global.socket, global.msg);
+ DBG("NL80211_CMD_GET_SCAN sent %d bytes to the kernel", ret);
+
+ /** Receive the kernel message. */
+ ret = nl_recvmsgs_default(global.socket);
+ nlmsg_free(global.msg);
+ if (ret < 0) {
+ DBG("nl_recvmsgs_default() failed. ret: %d (error: %s)", ret, nl_geterror(-ret));
+ wifi_complete_netlink_specific_scan(wifi, context);
+ return ret;
+ }
+
+ wifi_complete_netlink_specific_scan(wifi, context);
+ return 1;
}