23 #include <netlink/netlink.h> 24 #include <netlink/genl/genl.h> 25 #include <netlink/genl/ctrl.h> 26 #include <netlink/genl/family.h> 27 #include <boost/filesystem.hpp> 28 #include <boost/filesystem/fstream.hpp> 29 #include <senf/Utils/Cpp11Support/cast.hh> 38 #define FOREACH_ID(x) BOOST_PP_CAT(x, __LINE__) 39 #define FOREACH_NESTED_ATTR(attr, nla) \ 41 for (int FOREACH_ID(_remaining) = nla_len(nla), \ 42 FOREACH_ID(_loop_done) = 0; \ 43 FOREACH_ID(_loop_done)==0; ++FOREACH_ID(_loop_done)) \ 44 for (nlattr * attr = nla_attr_data(nla); \ 45 nla_ok(attr, FOREACH_ID(_remaining)); \ 46 attr = nla_next(attr, &(FOREACH_ID(_remaining)))) 50 #define NLA_PUT(msg, attrtype, attrlen, data) \ 53 if ((r = nla_put(msg.get(), attrtype, attrlen, data)) < 0) \ 54 throw NetlinkException(r, "Failed to build the netlink message"); \ 57 #define NLA_PUT_NESTED(msg, attrtype, nestedMsg) \ 60 if ((r = nla_put_nested(msg.get(), attrtype, nestedMsg.get())) < 0) \ 61 throw NetlinkException(r, "Failed to build the netlink message"); \ 64 #define KHZ_TO_MHZ(freq) ((freq) / 1000) 65 #define MHZ_TO_KHZ(freq) ((freq) * 1000) 67 #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof(arr[0])) 74 T & get_optional_value(boost::optional<T> & opt)
81 static int static_netlink_cb(nl_msg * msg,
void * arg) {
82 auto * cb (reinterpret_cast<senf::emu::WirelessNLController::NetlinkMsgCallback *>(arg));
86 static nlattr * nla_attr_data(
const nlattr * nla) {
87 return reinterpret_cast<nlattr *
>(nla_data(nla));
90 struct nl_nested_attr_ptr
92 typedef boost::shared_ptr<nl_msg> nl_msg_ptr;
96 nl_nested_attr_ptr(nl_msg_ptr msg_,
int attrtype)
97 : msg(msg_), attr(nla_nest_start(msg.get(), attrtype))
101 ~nl_nested_attr_ptr()
103 nla_nest_end(msg.get(), attr);
108 struct NLAttributePolicies
117 memset( freqPolicy, 0,
sizeof(freqPolicy));
127 memset( ratePolicy, 0,
sizeof(ratePolicy));
131 memset( surveyPolicy, 0,
sizeof(surveyPolicy));
135 memset( regRulePolicy, 0,
sizeof(regRulePolicy));
144 memset( bssPolicy, 0,
sizeof(bssPolicy));
168 _nlAttributePolicies_initialized (NLAttributePolicies::init());
175 : radarEvent(*this), regulatoryDomainChangeEvent(*this), scanEvent(*this),
176 ifIndex_(0), phyIndex_(-1),
177 nl_sock_(nullptr, nl_socket_free), nl_cache_(nullptr, nl_cache_free), nl_cb_(nullptr, nl_cb_put),
178 nl_event_sock_(nullptr, nl_socket_free), nl_event_cb_(nullptr, nl_cb_put)
180 ifIndex_ = if_nametoindex(interface.c_str());
186 phyName_ = interface;
196 ifIndex_(0), phyIndex_(-1),
197 nl_sock_(nullptr, nl_socket_free), nl_cache_(nullptr, nl_cache_free), nl_cb_(nullptr, nl_cb_put),
198 nl_event_sock_(nullptr, nl_socket_free), nl_event_cb_(nullptr, nl_cb_put)
200 init(disableSeqNoCheck);
203 prefix_ void senf::emu::WirelessNLController::init(
bool disableSeqNoCheck)
207 hasHTCapabilities_ =
false;
208 hasVHTCapabilities_ =
false;
210 netlinkMsgCb_ =
senf::membind(&WirelessNLController::netlink_cb,
this);
211 netlinkEventCb_ =
senf::membind(&WirelessNLController::netlink_event_cb,
this);
213 initNlSock(nl_sock_, disableSeqNoCheck);
214 initNlCb(nl_sock_, nl_cb_, netlinkMsgCb_);
215 initNlCache(nl_sock_, nl_cache_);
217 nl80211Id_ = genl_ctrl_resolve(nl_sock_.get(),
"nl80211");
222 prefix_ void senf::emu::WirelessNLController::initNlSock(nl_sock_ptr & sock,
bool disableSeqNoCheck)
224 sock.reset(nl_socket_alloc());
228 if (genl_connect(sock.get()))
231 if (disableSeqNoCheck)
232 nl_socket_disable_seq_check(sock.get());
233 nl_socket_disable_auto_ack(sock.get());
236 prefix_ void senf::emu::WirelessNLController::initNlCache(nl_sock_ptr & sock, nl_cache_ptr & cache)
239 if (genl_ctrl_alloc_cache(sock.get(), &c))
246 cb.reset(nl_cb_alloc(NL_CB_DEFAULT));
249 nl_cb_set(cb.get(), NL_CB_VALID, NL_CB_CUSTOM, static_netlink_cb, &msgcb);
250 nl_socket_set_cb(sock.get(), cb.get());
265 prefix_ senf::emu::WirelessNLController::nl_msg_ptr senf::emu::WirelessNLController::nlMsg()
267 nl_msg_ptr msg (nlmsg_alloc(), &nlmsg_free);
273 prefix_ senf::emu::WirelessNLController::nl_msg_ptr
274 senf::emu::WirelessNLController::nlMsgHeader(uint8_t cmd, CmdIdBy idBy,
int flags)
277 nl_msg_ptr msg (nlMsg());
278 genlmsg_put( msg.get(),
304 prefix_ void senf::emu::WirelessNLController::send_and_wait4response(nl_msg_ptr
const & msg, CallbackMemPtr cb)
308 if ((r = nl_send_auto_complete(nl_sock_.get(), msg.get())) > 0) {
309 if ((r = nl_recvmsgs_default( nl_sock_.get())) != 0)
317 prefix_ void senf::emu::WirelessNLController::send(nl_msg_ptr
const & msg)
320 if ((r = nl_send_auto_complete(nl_sock_.get(), msg.get())) > 0) {
321 if ((r = nl_wait_for_ack( nl_sock_.get())) != 0)
340 prefix_ int senf::emu::WirelessNLController::netlink_cb(nl_msg * msg)
343 return (this->*callback_)(msg);
350 DFSStateMap::const_iterator state (dfsStates_.find(freq));
351 if (state != dfsStates_.end()) {
352 return state->second;
361 nlPutChannelDef(msg, freq, channelMode);
363 send_and_wait4response(msg);
374 send_and_wait4response(msg);
384 send_and_wait4response(msg);
391 nlPutChannelDef(msg, freq, channelMode);
393 send_and_wait4response(msg);
398 if (alpha2Country.size() != 2)
405 send_and_wait4response(msg);
421 nl_nested_attr_ptr params (msg, i);
432 send_and_wait4response(msg);
439 send_and_wait4response(msg, &WirelessNLController::getRegDomain_cb);
449 boost::uint16_t cwMin, boost::uint16_t cwMax, boost::uint8_t aifs, boost::uint16_t txop)
455 nl_nested_attr_ptr params (msg, 1);
463 send_and_wait4response(msg);
469 uint8_t transform_bitrate(uint32_t r) {
474 #define NLA_PUT_OPTIONAL_VECTOR(msg, attrtype, optvector) \ 476 if (optvector) NLA_PUT( msg, attrtype, optvector->size(), \ 477 optvector->empty() ? NULL : &(*optvector)[0]); \ 485 typedef std::vector<uint8_t> LegacyBitrateVector;
486 boost::optional<LegacyBitrateVector> legacy_24, legacy_5;
487 typedef std::vector<BitrateParameters::MCSIndex> MCSIndexVector;
488 boost::optional<MCSIndexVector> mcs_24, mcs_5;
492 legacy_24.reset( LegacyBitrateVector(p.
legacy_24->size()));
493 std::transform(p.
legacy_24->begin(), p.
legacy_24->end(), legacy_24->begin(), transform_bitrate);
496 legacy_5.reset( LegacyBitrateVector(p.
legacy_5->size()));
497 std::transform(p.
legacy_5->begin(), p.
legacy_5->end(), legacy_5->begin(), transform_bitrate);
500 mcs_24.reset(MCSIndexVector(p.
mcs_24->size()));
501 std::copy(p.
mcs_24->begin(), p.
mcs_24->end(), mcs_24->begin());
504 mcs_5.reset(MCSIndexVector(p.
mcs_5->size()));
505 std::copy(p.
mcs_5->begin(), p.
mcs_5->end(), mcs_5->begin());
537 send_and_wait4response(msg);
543 return supportedBands_;
555 return senf::make_transform_range(frequencies_,
556 ::__gnu_cxx::select2nd<Frequencies::value_type>());
562 return senf::make_transform_range(frequencies_.equal_range(band),
563 ::__gnu_cxx::select2nd<Frequencies::value_type>());
567 # define BIT(x) (1ULL<<(x)) 613 #define GET_RULE_ATTR_OR_SKIP( var, attr ) \ 615 if (not ruleAttr[attr]) continue; \ 616 var = nla_get_u32(ruleAttr[attr]); 618 prefix_ int senf::emu::WirelessNLController::getRegDomain_cb(nl_msg * msg)
623 genlmsghdr * msgHdr =
reinterpret_cast<genlmsghdr *
>(nlmsg_data(nlmsg_hdr(msg)));
624 nla_parse(msgAttr,
NL80211_ATTR_MAX, genlmsg_attrdata(msgHdr, 0), genlmsg_attrlen(msgHdr, 0), NULL);
632 regDomain_.alpha2Country = std::string(alpha2, 2);
651 .frequencyRange(start_freq_khz, end_freq_khz)
652 .maxBandwidth(max_bw_khz)
653 .maxAntennaGain(max_ant_gain_mbi)
654 .maxEIRP(max_eirp_mbm)
655 .cacTime(cac_time_ms)
662 prefix_ int senf::emu::WirelessNLController::getWiphy_cb(nl_msg * msg)
671 uint32_t vhtCapa = 0;
673 genlmsghdr * msgHdr =
reinterpret_cast<genlmsghdr *
>(nlmsg_data(nlmsg_hdr(msg)));
674 nla_parse(msgAttr,
NL80211_ATTR_MAX, genlmsg_attrdata(msgHdr, 0), genlmsg_attrlen(msgHdr, 0), NULL);
679 if (firstMutlipartMsg_) {
680 firstMutlipartMsg_ =
false;
682 frequencies_.clear();
683 supportedBands_.clear();
686 tmpMCSRates_.reset();
687 tmpLegacyRates_.reset();
693 bool firstBand (
true);
702 NLAttributePolicies::freqPolicy);
705 uint32_t f (nla_get_u32(freqAttr[NL80211_FREQUENCY_ATTR_FREQ]));
716 uint32_t state = nla_get_u32(freqAttr[NL80211_FREQUENCY_ATTR_DFS_STATE]);
722 if (bandtype_ != -1) {
723 supportedBands_.insert(
Band_t(bandtype_));
726 if (tmpLegacyRates_) bitrates_.legacy_24 = tmpLegacyRates_;
727 if (tmpMCSRates_) bitrates_.mcs_24 = tmpMCSRates_;
730 if (tmpLegacyRates_) bitrates_.legacy_5 = tmpLegacyRates_;
731 if (tmpMCSRates_) bitrates_.mcs_5 = tmpMCSRates_;
739 NLAttributePolicies::ratePolicy);
741 uint32_t r (nla_get_u32(rateAttr[NL80211_BITRATE_ATTR_RATE]));
744 get_optional_value(tmpLegacyRates_).insert( r*100);
747 get_optional_value(bitrates_.legacy_24).insert( r*100);
750 get_optional_value(bitrates_.legacy_5).insert( r*100);
759 uint16_t bandHTCapa (nla_get_u16( bandAttr[NL80211_BAND_ATTR_HT_CAPA]));
761 htCapabilities_ = parseHTCapabilities(bandHTCapa);
762 hasHTCapabilities_ =
true;
765 if (bandHTCapa != htCapa)
769 uint32_t bandVHTCapa (nla_get_u32( bandAttr[NL80211_BAND_ATTR_VHT_CAPA]));
771 vhtCapabilities_ = parseVHTCapabilities(bandVHTCapa);
772 hasVHTCapabilities_ =
true;
773 vhtCapa = bandVHTCapa;
775 if (bandVHTCapa != vhtCapa)
779 unsigned char *
mcs (reinterpret_cast<unsigned char*>(nla_data(bandAttr[NL80211_BAND_ATTR_VHT_MCS_SET])));
780 boost::uint16_t tmp = mcs[0] | (mcs[1] << 8);
782 bandtype_ ==
BAND_2GHZ ? bitrates_.vht_mcs_table_24 : bitrates_.vht_mcs_table_5));
784 switch ((tmp >> (nss * 2)) & 3) {
786 mcsBitmapTable[nss] = 0xff;
789 mcsBitmapTable[nss] = 0x1ff;
792 mcsBitmapTable[nss] = 0x3ff;
800 unsigned char *
mcs (reinterpret_cast<unsigned char*>(nla_data(bandAttr[NL80211_BAND_ATTR_HT_MCS_SET])));
801 if (!(mcs[12] & (1 << 0))) {
805 if (mcs[12] & (1 << 1)) {
809 for (
unsigned mcs_bit = 0; mcs_bit <= 76; ++mcs_bit) {
810 if (!!(mcs[mcs_bit/8] & (1 << mcs_bit % 8))) {
813 get_optional_value(tmpMCSRates_).insert( mcs_bit);
816 get_optional_value(bitrates_.mcs_24).insert( mcs_bit);
819 get_optional_value(bitrates_.mcs_5).insert( mcs_bit);
830 coverageClass_ = nla_get_u8(msgAttr[NL80211_ATTR_WIPHY_COVERAGE_CLASS]);
836 prefix_ void senf::emu::WirelessNLController::getWiphy()
838 firstMutlipartMsg_ =
true;
843 send_and_wait4response(msg, &WirelessNLController::getWiphy_cb);
846 prefix_ int senf::emu::WirelessNLController::getSurvey_cb(nl_msg * msg)
851 genlmsghdr * msgHdr =
reinterpret_cast<genlmsghdr *
>(nlmsg_data(nlmsg_hdr(msg)));
852 nla_parse(msgAttr,
NL80211_ATTR_MAX, genlmsg_attrdata(msgHdr, 0), genlmsg_attrlen(msgHdr, 0), NULL);
858 NLAttributePolicies::surveyPolicy) != 0)
864 survey.frequency =
MHZ_TO_KHZ(nla_get_u32(sinfo[NL80211_SURVEY_INFO_FREQUENCY]));
866 survey.noise = nla_get_u8(sinfo[NL80211_SURVEY_INFO_NOISE]);
868 survey.channelTime = nla_get_u64(sinfo[NL80211_SURVEY_INFO_CHANNEL_TIME]);
870 survey.channelTimeBusy = nla_get_u64(sinfo[NL80211_SURVEY_INFO_CHANNEL_TIME_BUSY]);
872 survey.channelTimeExtBusy = nla_get_u64(sinfo[NL80211_SURVEY_INFO_CHANNEL_TIME_EXT_BUSY]);
874 survey.channelTimeRx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_CHANNEL_TIME_RX]);
876 survey.channelTimeTx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_CHANNEL_TIME_TX]);
878 survey_.insert(survey);
887 send_and_wait4response(msg, &WirelessNLController::getSurvey_cb);
893 for (
auto const & s :
survey()) {
904 case Unspecified:
return "unspecified";
905 case AdHoc:
return "IBSS";
906 case Station:
return "managed";
907 case AP:
return "AP";
908 case APVLan:
return "AP/VLAN";
909 case WDS:
return "WDS";
910 case Monitor:
return "monitor";
911 case MeshPoint:
return "mesh point";
912 case Unknown:
return "unknown mode";
914 return "Unknown mode (" + senf::str(type) +
")";
920 case NoDFS:
return "NoDFS";
921 case Usable:
return "Usable";
922 case Unavailable:
return "Unavailable";
923 case Available:
return "Available";
925 return "Unknown state (" + senf::str(state) +
")";
928 prefix_ int senf::emu::WirelessNLController::getIface_cb(nl_msg * msg)
932 genlmsghdr * msgHdr =
reinterpret_cast<genlmsghdr *
>(nlmsg_data(nlmsg_hdr(msg)));
933 nla_parse(msgAttr,
NL80211_ATTR_MAX, genlmsg_attrdata(msgHdr, 0), genlmsg_attrlen(msgHdr, 0), NULL);
936 uint32_t
type (nla_get_u32(msgAttr[NL80211_ATTR_IFTYPE]));
945 send_and_wait4response(msg, &WirelessNLController::getIface_cb);
954 case IfaceType::Enum::AdHoc:
957 case IfaceType::Enum::Station:
960 case IfaceType::Enum::AP:
963 case IfaceType::Enum::APVLan:
966 case IfaceType::Enum::WDS:
969 case IfaceType::Enum::Monitor:
972 case IfaceType::Enum::MeshPoint:
975 case IfaceType::Enum::Unspecified:
976 case IfaceType::Enum::Unknown:
982 send_and_wait4response(msg);
992 nl_msg_ptr flagMsg (nlMsg());
994 if (flags & (1 << flag))
995 NLA_PUT_FLAG(flagMsg, flag);
999 send_and_wait4response(msg);
1009 send_and_wait4response(msg);
1019 send_and_wait4response(msg);
1028 if (not meshId.empty())
1031 send_and_wait4response(msg);
1037 int ifindex = if_nametoindex(name.c_str());
1045 send_and_wait4response(msg);
1053 boost::filesystem::directory_iterator end_itr;
1054 for (boost::filesystem::directory_iterator itr (
"/sys/class/net"); itr != end_itr; ++itr ) {
1056 # if BOOST_FILESYSTEM_VERSION == 3 1057 std::string ifname (itr->path().filename().string());
1059 std::string ifname (itr->path().filename());
1062 ifaceNames.insert( ifname);
1069 return std::min( ((distance + 449) / 450), 255u);
1078 send_and_wait4response(msg);
1084 return coverageClass_;
1090 return hasHTCapabilities_;
1096 return hasVHTCapabilities_;
1102 return htCapabilities_;
1108 return vhtCapabilities_;
1112 template <
typename T>
1113 T readTokenFromFile(boost::filesystem::path
const & path)
1115 boost::filesystem::ifstream file;
1116 file.exceptions(std::ifstream::failbit | std::ifstream::badbit);
1117 file.open(path, std::ios::in);
1124 int readIntFromFile(boost::filesystem::path
const & path)
1127 return readTokenFromFile<int>(path);
1128 }
catch (std::exception & e) {}
1132 std::string readStringFromFile(boost::filesystem::path
const & path)
1135 return readTokenFromFile<std::string>(path);
1136 }
catch (std::exception & e) {}
1140 namespace fs = ::boost::filesystem;
1145 file.exceptions( std::ifstream::failbit | std::ifstream::badbit);
1146 file.open(path, std::ios::in);
1156 return readIntFromFile(
1157 boost::filesystem::path(
"/sys/class/net")/ifname/
"phy80211/index");
1162 return readIntFromFile(
1163 boost::filesystem::path(
"/sys/class/ieee80211")/phyname/
"index");
1168 return readStringFromFile(
1169 boost::filesystem::path(
"/sys/class/net")/ifname/
"phy80211/name");
1174 fs::directory_iterator end_itr;
1175 for (fs::directory_iterator itr (
"/sys/class/ieee80211/"); itr != end_itr; ++itr) {
1177 if (readMACAddressFromFile(itr->path()/
"macaddress") == mac)
1178 return itr->path().filename().string();
1179 }
catch (std::exception &) {}
1181 return "unknown mac";
1186 switch (channelMode) {
1202 switch (channelMode) {
1220 unsigned int vht80[] = {
1225 switch (channelMode) {
1235 if (freq >= vht80[j] && freq < vht80[j] +
MHZ_TO_KHZ(80))
1249 send_and_wait4response(msg);
1255 return JoinParameters::ptr(
new MeshJoinParameters(
1256 membind(&WirelessNLController::do_mesh_join,
this), meshId, freq, channelMode, success) );
1259 prefix_ void senf::emu::WirelessNLController::do_mesh_join(JoinParameters
const & jp)
1261 MeshJoinParameters
const & parameters (static_cast<MeshJoinParameters const &>(jp));
1266 nlPutChannelDef(msg, parameters.freq_, parameters.channelMode_);
1268 if (parameters.beaconInterval_)
1271 if (parameters.handleDFS_)
1274 if (parameters.htCapabilities_) {
1276 sizeof(parameters.htCapabilities_.get()),
1277 parameters.htCapabilities_.get_ptr());
1279 sizeof(parameters.htCapabilitiesMask_.get()),
1280 parameters.htCapabilitiesMask_.get_ptr());
1285 if (! boost::empty(parameters.ies_))
1287 if (parameters.vendorMetric_)
1289 if (parameters.vendorPathSelection_)
1291 if (parameters.vendorSynchronization_)
1295 send_and_wait4response(msg);
1301 send_and_wait4response(msg);
1307 return JoinParameters::ptr(
new IbssJoinParameters(
1308 membind(&WirelessNLController::do_ibss_join,
this), ssid, freq, channelMode, success) );
1311 prefix_ void senf::emu::WirelessNLController::do_ibss_join(JoinParameters
const & jp)
1313 IbssJoinParameters
const & parameters (static_cast<IbssJoinParameters const &>(jp));
1318 nlPutChannelDef(msg, parameters.freq_, parameters.channelMode_);
1322 if (parameters.handleDFS_)
1325 if (! boost::empty(parameters.ies_))
1328 if (parameters.bssid_)
1331 if (parameters.beaconInterval_)
1334 if (parameters.htCapabilities_) {
1336 sizeof(parameters.htCapabilities_.get()),
1337 parameters.htCapabilities_.get_ptr());
1339 sizeof(parameters.htCapabilitiesMask_.get()),
1340 parameters.htCapabilitiesMask_.get_ptr());
1343 send_and_wait4response(msg);
1350 if (not ssids.empty()) {
1351 nl_msg_ptr ms (nlMsg());
1352 for (
auto const & s : ssids){
1358 if (not frequencies.empty()) {
1359 nl_msg_ptr freqs (nlMsg());
1371 scanResults_.clear();
1373 send_and_wait4response(msg, &WirelessNLController::getScan_cb);
1374 return scanResults_;
1377 prefix_ int senf::emu::WirelessNLController::getScan_cb(nl_msg * msg)
1382 genlmsghdr * msgHdr =
reinterpret_cast<genlmsghdr *
>(nlmsg_data(nlmsg_hdr(msg)));
1383 nla_parse(msgAttr,
NL80211_ATTR_MAX, genlmsg_attrdata(msgHdr, 0), genlmsg_attrlen(msgHdr, 0), NULL);
1389 NLAttributePolicies::bssPolicy) != 0)
1397 res.
tsf = nla_get_u64(bss[NL80211_BSS_TSF]);
1401 res.
beaconInterval = nla_get_u16(bss[NL80211_BSS_BEACON_INTERVAL]);
1403 res.
capability = nla_get_u16(bss[NL80211_BSS_CAPABILITY]);
1405 res.
signal = int(nla_get_u32(bss[NL80211_BSS_SIGNAL_MBM])) / 100;
1407 res.
signalUnspec = nla_get_u8(bss[NL80211_BSS_SIGNAL_UNSPEC]);
1418 scanResults_.insert(res);
1423 prefix_ int senf::emu::WirelessNLController::processScanResponse(std::uint8_t cmd, nlattr ** msgAttr)
1427 event.
type = ScanEvent::Type::ABORTED;
1430 event.type = ScanEvent::Type::COMPLETED;
1441 prefix_ void senf::emu::WirelessNLController::get_multicastGroups()
1443 int ctrlid = genl_ctrl_resolve(nl_sock_.get(),
"nlctrl");
1447 nl_msg_ptr msg (nlMsg());
1448 genlmsg_put( msg.get(),
1449 NL_AUTO_PID, NL_AUTO_SEQ,
1450 ctrlid, 0, 0, CTRL_CMD_GETFAMILY, 0);
1452 NLA_PUT_STRING(msg, CTRL_ATTR_FAMILY_NAME,
"nl80211");
1454 send_and_wait4response(msg, &WirelessNLController::getMCGroups_cb);
1457 prefix_ int senf::emu::WirelessNLController::getMCGroups_cb(nl_msg * msg)
1459 nlattr * msgAttr[CTRL_ATTR_MAX + 1];
1461 genlmsghdr * msgHdr =
reinterpret_cast<genlmsghdr *
>(nlmsg_data(nlmsg_hdr(msg)));
1462 nla_parse(msgAttr, CTRL_ATTR_MAX, genlmsg_attrdata(msgHdr, 0), genlmsg_attrlen(msgHdr, 0), NULL);
1464 if (not msgAttr[CTRL_ATTR_MCAST_GROUPS])
1467 multicastGroups_.clear();
1469 nlattr * grpAttr[CTRL_ATTR_MCAST_GRP_MAX + 1];
1470 nla_parse(grpAttr, CTRL_ATTR_MCAST_GRP_MAX, nla_attr_data(mcgrp), nla_len(mcgrp), NULL);
1472 if (not grpAttr[CTRL_ATTR_MCAST_GRP_NAME] or not grpAttr[CTRL_ATTR_MCAST_GRP_ID])
1475 std::string grpName (
1476 reinterpret_cast<const char*>(nla_data(grpAttr[CTRL_ATTR_MCAST_GRP_NAME])),
1477 nla_len(grpAttr[CTRL_ATTR_MCAST_GRP_NAME])-1);
1478 int grpId (nla_get_u32(grpAttr[CTRL_ATTR_MCAST_GRP_ID]));
1479 multicastGroups_[grpName] = grpId;
1485 prefix_ void senf::emu::WirelessNLController::processReadEvent(
int eventMask)
1487 nl_recvmsgs(nl_event_sock_.get(), nl_event_cb_.get());
1490 prefix_ int senf::emu::WirelessNLController::netlink_event_cb(nl_msg * msg)
1493 genlmsghdr * msgHdr =
reinterpret_cast<genlmsghdr *
>(nlmsg_data(nlmsg_hdr(msg)));
1494 nla_parse(msgAttr,
NL80211_ATTR_MAX, genlmsg_attrdata(msgHdr, 0), genlmsg_attrlen(msgHdr, 0), NULL);
1497 if (phyIndex_ !=
int(nla_get_u32(msgAttr[NL80211_ATTR_WIPHY])))
1501 if (ifIndex_ !=
int(nla_get_u32(msgAttr[NL80211_ATTR_IFINDEX])))
1505 switch (msgHdr->cmd) {
1507 return processRadarEvent(msgAttr);
1509 return processRegDomainEvent(msgAttr);
1515 prefix_ int senf::emu::WirelessNLController::processRadarEvent(nlattr ** msgAttr)
1522 event.frequency = nla_get_u32(msgAttr[NL80211_ATTR_WIPHY_FREQ]);
1529 prefix_ int senf::emu::WirelessNLController::processRegDomainEvent(nlattr ** msgAttr)
1542 prefix_ void senf::emu::WirelessNLController::initEventHandling()
1546 initNlSock(nl_event_sock_);
1547 initNlCb(nl_event_sock_, nl_event_cb_, netlinkEventCb_);
1549 "WirelessNLControllerEvent",
senf::membind(&WirelessNLController::processReadEvent,
this),
1553 prefix_ void senf::emu::WirelessNLController::deinitEventHandling()
1556 nl_event_cb_.release();
1557 nl_event_sock_.release();
1562 get_multicastGroups();
1564 std::string groupName;
1567 groupName =
"config";
1573 groupName =
"regulatory";
1579 groupName =
"vendor";
1582 if (not senf::contains(multicastGroups_, groupName))
1584 return multicastGroups_[groupName];
1589 if (senf::contains(joinedMCGroups_, group))
1592 if (joinedMCGroups_.empty())
1593 initEventHandling();
1595 int r = nl_socket_add_membership(nl_event_sock_.get(), multicastGroupId(group));
1597 if (joinedMCGroups_.empty())
1598 deinitEventHandling();
1602 joinedMCGroups_.insert(group);
1607 if (not senf::contains(joinedMCGroups_, group))
1610 int r = nl_socket_drop_memberships(nl_event_sock_.get(), multicastGroupId(group));
1614 joinedMCGroups_.erase(group);
1616 if (joinedMCGroups_.empty())
1617 deinitEventHandling();
1623 prefix_ senf::emu::WirelessNLController::JoinParameters::JoinParameters(
1625 : callback_(cb), handleDFS_(
false), freq_(
freq), channelMode_(channelMode), success_(success)
1628 prefix_ senf::emu::WirelessNLController::JoinParameters::~JoinParameters()
1638 prefix_ senf::emu::WirelessNLController::JoinParameters::ptr senf::emu::WirelessNLController::JoinParameters::handleDFS(
bool flag)
1641 return shared_from_this();
1644 prefix_ senf::emu::WirelessNLController::JoinParameters::ptr senf::emu::WirelessNLController::JoinParameters::beaconInterval(boost::optional<boost::uint32_t> interval)
1646 beaconInterval_ = interval;
1647 return shared_from_this();
1650 prefix_ void senf::emu::WirelessNLController::JoinParameters::initHTCapabilities()
1652 if (htCapabilities_)
1656 memset(htCapabilities_.get_ptr(), 0,
sizeof(htCapabilities_.get()));
1657 memset(htCapabilitiesMask_.get_ptr(), 0,
sizeof(htCapabilitiesMask_.get()));
1660 prefix_ senf::emu::WirelessNLController::JoinParameters::ptr senf::emu::WirelessNLController::JoinParameters::ampduFactor(
unsigned factor)
1664 initHTCapabilities();
1665 htCapabilities_->ampdu_params_info |= factor & 0x3;
1666 htCapabilitiesMask_->ampdu_params_info |= 0x3;
1667 return shared_from_this();
1673 prefix_ senf::emu::WirelessNLController::IbssJoinParameters::IbssJoinParameters(
1675 : JoinParameters(cb,
freq, channelMode, success),
1682 return IbssJoinParameters::ptrI(
this);
1689 prefix_ senf::emu::WirelessNLController::MeshJoinParameters::MeshJoinParameters(
1691 : JoinParameters(cb,
freq, channelMode, success),
1695 prefix_ senf::emu::WirelessNLController::MeshJoinParameters::ptrM senf::emu::WirelessNLController::MeshJoinParameters::vendorMetric(
bool enable)
1697 vendorMetric_ = enable ? 1 : 0;
1698 return MeshJoinParameters::ptrM(
this);
1701 prefix_ senf::emu::WirelessNLController::MeshJoinParameters::ptrM senf::emu::WirelessNLController::MeshJoinParameters::vendorPathSelection(
bool enable)
1703 vendorPathSelection_ = enable ? 1 : 0;
1704 return MeshJoinParameters::ptrM(
this);
1707 prefix_ senf::emu::WirelessNLController::MeshJoinParameters::ptrM senf::emu::WirelessNLController::MeshJoinParameters::vendorSynchronization(
bool enable)
1709 vendorSynchronization_ = enable ? 1 : 0;
1710 return MeshJoinParameters::ptrM(
this);
1732 return nl_geterror(code_);
void set_regulatory(RegulatoryDomain const ®Domain)
void add_apInterface(std::string const &name)
static MACAddress const None
#define NL80211_TXQ_ATTR_QUEUE
bool lSIG_TXOP_Protection
RegulatoryRule & maxEIRP(std::int32_t eirp)
void add_meshInterface(std::string const &name, std::string const &meshId="")
#define FOREACH_NESTED_ATTR(attr, nla)
#define SENF_THROW_SYSTEM_EXCEPTION(desc)
void set_bitrates(BitrateParameters parameters)
void add_adhocInterface(std::string const &name)
IfaceNameSet all_interfaces() const
#define NL80211_FREQUENCY_ATTR_NO_IBSS
#define NLA_PUT_NESTED(msg, attrtype, nestedMsg)
static int phy_nametoindex(std::string const &phyname)
void del_interface(std::string const &name)
static unsigned distanceToCoverageClass(unsigned distance)
ChannelWidth channelWidth
std::set< Band_t > const & supportedBands()
void do_trigger_scan(std::set< frequency_type > const &frequencies, std::set< std::string > const &ssids={})
#define NL80211_SURVEY_INFO_CHANNEL_TIME_TX
boost::function< int(nl_msg *)> NetlinkMsgCallback
boost::function< R(Args)> membind(R(T::*fn)(Args), T *ob)
boost::optional< MCSIndexSet > mcs_24
char const * errorString() const
#define NL80211_FREQUENCY_ATTR_PASSIVE_SCAN
#define NL80211_SURVEY_INFO_CHANNEL_TIME_RX
std::pair< DFSState::Enum, std::uint32_t > dfsState(frequency_type freq)
frequency_type frequency()
BitrateParameters const & bitrates()
Return valid bitrates.
void add_monInterface(std::string const &name, int flags=MonitorFlags::None)
bool shortGIfor160_8080MHz
boost::optional< LegacyBitrateSet > legacy_5
std::set< RegulatoryRule > rules
void set_regulatory_request(std::string const &alpha2Country)
std::uint32_t frequencyRangeEnd() const
std::array< VHT_MCSBitmap, NL80211_VHT_NSS_MAX > VHT_MCSBitmapTable
RegulatoryRule & maxAntennaGain(std::int32_t gain)
NetlinkEvent< ScanEvent > scanEvent
boost::optional< VHT_MCSBitmapTable > vht_mcs_table_24
std::uint16_t beaconInterval
std::multiset< ScanResults > const & getScan()
NetlinkEvent< RadarEvent > radarEvent
void set_txpower(TxPowerSetting::Enum setting, unsigned int mBm)
#define NL80211_SURVEY_INFO_CHANNEL_TIME_BUSY
static frequency_type centerFreq(frequency_type freq, ChannelMode::Enum channelMode)
static std::string macToPhy(senf::MACAddress const &mac)
boost::optional< MCSIndexSet > mcs_5
FrequencyRange frequencies()
RegulatoryRule & cacTime(std::uint32_t cac)
VHTCapabilitiesInfo const & vhtCapabilities()
void set_txQueueParameters(boost::uint8_t queue, boost::uint16_t cwMin, boost::uint16_t cwMax, boost::uint8_t aifs, boost::uint16_t txop)
struct senf::emu::MonitorDataFilterStatistics __attribute__
std::uint8_t informationElements[4096]
enum SupportedChannelWidth supportedChannelWidth
std::uint32_t frequencyRangeBegin() const
JoinParameters::ptr mesh_join(std::string const &meshId, frequency_type freq, ChannelMode::Enum channelMode, bool &success)
std::set< std::string > IfaceNameSet
static std::string str(Enum type)
#define NLA_PUT_OPTIONAL_VECTOR(msg, attrtype, optvector)
std::string alpha2Country
std::uint8_t beaconInformationElements[4096]
RegulatoryRule & flags(std::uint32_t f)
WirelessNLController(bool disableSeqNoCheck=true)
#define NL80211_SURVEY_INFO_CHANNEL_TIME
static int channelType(ChannelMode::Enum channelMode)
MaxAMSDULength maxAMSDULength
RegulatoryRule & maxBandwidth(std::uint32_t bandwidth)
JoinParameters::ptr ibss_join(std::string const &ssid, frequency_type freq, ChannelMode::Enum channelMode, bool &success)
boost::optional< VHT_MCSBitmapTable > vht_mcs_table_5
static int if_nameto_phy_index(std::string const &ifname)
static int channelWidth(ChannelMode::Enum channelMode)
boost::optional< GICfg > gi_5
static std::string str(Enum state)
NetlinkException(int code, std::string const &descr="")
WirelessNLController public header.
HTCapabilitiesInfo const & htCapabilities()
void set_retryLimit(boost::uint8_t shortLimit, boost::uint8_t longLimit)
std::set< Survey > const & survey()
bool rxAntennaPatternConsistency
#define NLA_PUT(msg, attrtype, attrlen, data)
bool txAntennaPatternConsistency
void set_frequency(frequency_type freq, ChannelMode::Enum=ChannelMode::NoHT20)
boost::optional< GICfg > gi_24
#define NL80211_SURVEY_INFO_CHANNEL_TIME_EXT_BUSY
NetlinkEvent< RegulatoryDomainChangeEvent > regulatoryDomainChangeEvent
struct ieee80211_mcs_info mcs
void start_radarDetection(unsigned int freq, ChannelMode::Enum=ChannelMode::NoHT20)
std::string const & phyName() const
enum MaxMPDULength maxMPDULength
static MACAddress from_data(InputIterator i)
RegulatoryDomain get_regulatory()
boost::optional< LegacyBitrateSet > legacy_24
int beaconInformationElementsLength
__u16 mcs[NL80211_VHT_NSS_MAX]
std::uint8_t signalUnspec
#define GET_RULE_ATTR_OR_SKIP(var, attr)
int informationElementsLength
static std::string if_nameto_phy_name(std::string const &ifname)
boost::iterator_range< Frequencies_iterator > FrequencyRange
bool hasVHTCapabilities()
#define NL80211_VHT_NSS_MAX