added apgetconnected to git
This commit is contained in:
172
src/apgetconnected.cpp
Normal file
172
src/apgetconnected.cpp
Normal file
@ -0,0 +1,172 @@
|
||||
#include "apgetconnected.h"
|
||||
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <iomanip>
|
||||
|
||||
#include <linux/nl80211.h>
|
||||
#include <net/if.h>
|
||||
|
||||
#include <netlink/genl/genl.h>
|
||||
#include <netlink/genl/ctrl.h>
|
||||
#include <netlink/msg.h>
|
||||
|
||||
|
||||
namespace ap
|
||||
{
|
||||
|
||||
static int nl80211Init(struct nl_sock* nl_sock, int* nl80211_id)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (!nl_sock)
|
||||
{
|
||||
std::cerr<<"Failed to allocate netlink socket.\n";
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
if (genl_connect(nl_sock))
|
||||
{
|
||||
std::cerr<<"Failed to connect to generic netlink.\n";
|
||||
err = -ENOLINK;
|
||||
nl_socket_free(nl_sock);
|
||||
return err;
|
||||
}
|
||||
|
||||
nl_socket_set_buffer_size(nl_sock, 8192, 8192);
|
||||
|
||||
/* try to set NETLINK_EXT_ACK to 1, ignoring errors */
|
||||
err = 1;
|
||||
setsockopt(nl_socket_get_fd(nl_sock), SOL_NETLINK, NETLINK_EXT_ACK, &err, sizeof(err));
|
||||
|
||||
*nl80211_id = genl_ctrl_resolve(nl_sock, "nl80211");
|
||||
if (*nl80211_id < 0)
|
||||
{
|
||||
std::cerr<<"nl80211 not found.\n";
|
||||
err = -ENOENT;
|
||||
nl_socket_free(nl_sock);
|
||||
return err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int errorHandler(struct sockaddr_nl *nla, struct nlmsgerr *err, void *arg)
|
||||
{
|
||||
printf("netlink error\n");
|
||||
*reinterpret_cast<int*>(arg) = 0;
|
||||
return NL_STOP;
|
||||
}
|
||||
|
||||
static int finishHandler(struct nl_msg *msg, void *arg)
|
||||
{
|
||||
*reinterpret_cast<int*>(arg) = 0;
|
||||
return NL_SKIP;
|
||||
}
|
||||
|
||||
static int ackHandler(struct nl_msg *msg, void *arg)
|
||||
{
|
||||
*reinterpret_cast<int*>(arg) = 0;
|
||||
return NL_STOP;
|
||||
}
|
||||
|
||||
|
||||
static int extractDeviceMac(struct nl_msg *msg, void *arg)
|
||||
{
|
||||
struct nlattr* tb[NL80211_ATTR_MAX + 1];
|
||||
struct genlmsghdr* gnlh = (struct genlmsghdr*)nlmsg_data(nlmsg_hdr(msg));
|
||||
|
||||
std::vector<uint64_t>* deviceMacAddrs = reinterpret_cast<std::vector<uint64_t>*>(arg);
|
||||
|
||||
nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0), genlmsg_attrlen(gnlh, 0), NULL);
|
||||
if (!tb[NL80211_ATTR_STA_INFO])
|
||||
{
|
||||
std::cerr<<"sta stats missing!\n";
|
||||
return -1;
|
||||
}
|
||||
|
||||
const unsigned char* macChar = reinterpret_cast<const unsigned char*>(nla_data(tb[NL80211_ATTR_MAC]));
|
||||
uint64_t macAddr = 0;
|
||||
memcpy(&macAddr, macChar, 6);
|
||||
deviceMacAddrs->push_back(macAddr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::vector<uint64_t> connectedDevices(const std::string& ifDevice, int& error)
|
||||
{
|
||||
struct nl_sock* nl_sock = nl_socket_alloc();
|
||||
int nl80211_id = 0;
|
||||
error = 0;
|
||||
|
||||
if(nl80211Init(nl_sock, &nl80211_id))
|
||||
{
|
||||
std::cerr<<"Can not init nl80211\n";
|
||||
error = ERR_INIT;
|
||||
}
|
||||
|
||||
signed long long devidx = if_nametoindex(ifDevice.c_str());
|
||||
if(!devidx)
|
||||
{
|
||||
std::cerr<<ifDevice<<" is not a valid if device\n";
|
||||
error = ERR_NO_DEV;
|
||||
}
|
||||
|
||||
struct nl_msg *msg;
|
||||
msg = nlmsg_alloc();
|
||||
if(!msg) error = ERR_ALLOC;
|
||||
|
||||
struct nl_cb *cb = nl_cb_alloc(NL_CB_DEFAULT);
|
||||
struct nl_cb *s_cb = nl_cb_alloc(NL_CB_DEFAULT);
|
||||
if (!cb || !s_cb) error = ERR_ALLOC;
|
||||
|
||||
std::vector<uint64_t> deviceMacAddrs;
|
||||
|
||||
if(error == 0)
|
||||
{
|
||||
if(!genlmsg_put(msg, 0, 0, nl80211_id, 0, NLM_F_DUMP, NL80211_CMD_GET_STATION, 0))
|
||||
{
|
||||
std::cerr<<"genlmsg_put() failed\n";
|
||||
error = ERR_GENERAL;
|
||||
}
|
||||
|
||||
if(error == 0)
|
||||
{
|
||||
NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, devidx);
|
||||
|
||||
nl_socket_set_cb(nl_sock, s_cb);
|
||||
nl_send_auto_complete(nl_sock, msg);
|
||||
|
||||
{
|
||||
int ret = 1;
|
||||
|
||||
nl_cb_err(cb, NL_CB_CUSTOM, errorHandler, &ret);
|
||||
nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, finishHandler, &ret);
|
||||
nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, ackHandler, &ret);
|
||||
nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, extractDeviceMac, &deviceMacAddrs);
|
||||
|
||||
while (ret > 0) nl_recvmsgs(nl_sock, cb);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
nla_put_failure:
|
||||
nl_cb_put(cb);
|
||||
nl_cb_put(s_cb);
|
||||
nlmsg_free(msg);
|
||||
nl_socket_free(nl_sock);
|
||||
return deviceMacAddrs;
|
||||
}
|
||||
|
||||
std::string macAddrToString(uint64_t macAddr)
|
||||
{
|
||||
unsigned char* macAddrPtr = reinterpret_cast<unsigned char*>(&macAddr);
|
||||
std::stringstream ss;
|
||||
ss<<std::uppercase<<std::setfill('0')<<std::setw(2)<<std::hex;
|
||||
for(unsigned int i = 0; i < 6; ++i) ss<<+macAddrPtr[i]<<':';
|
||||
std::string macString = ss.str();
|
||||
macString.pop_back();
|
||||
return macString;
|
||||
}
|
||||
|
||||
}
|
19
src/apgetconnected.h
Normal file
19
src/apgetconnected.h
Normal file
@ -0,0 +1,19 @@
|
||||
#pragma once
|
||||
|
||||
#include<vector>
|
||||
#include<string>
|
||||
#include<stdint.h>
|
||||
|
||||
namespace ap
|
||||
{
|
||||
enum ERRORS
|
||||
{
|
||||
SUCESS,
|
||||
ERR_INIT,
|
||||
ERR_NO_DEV,
|
||||
ERR_ALLOC,
|
||||
ERR_GENERAL
|
||||
};
|
||||
std::vector<uint64_t> connectedDevices(const std::string& ifDevice, int& error);
|
||||
std::string macAddrToString(uint64_t macAddr);
|
||||
}
|
Reference in New Issue
Block a user