diff --git a/docs/changes.txt b/docs/changes.txt index 53dc0b5..d34a9c9 100644 --- a/docs/changes.txt +++ b/docs/changes.txt @@ -98,3 +98,4 @@ v0.7.1 * nfqws2: add EOL at the end of truncated buffered DLOG line if it's too large. increase log line buffer * nfqws2: autohostlist reset fail counter if udp_in > threshold * nfqws2: reduced default retrans maxseq to 32768 +* nfqws2: solved inability to get SSID using nl80211 on kernels 5.19+ diff --git a/docs/manual.md b/docs/manual.md index 311eab8..c021e24 100644 --- a/docs/manual.md +++ b/docs/manual.md @@ -530,7 +530,7 @@ nfqws2 <глобальные_параметры> Когда имеется много сложных и повторяющихся стратегий, может быть удобно использовать шаблоны. Шаблон - это такой же профиль, только он не идет в работу, а попадает в отдельный список шаблонов. Шаблоном профиль становится через задание параметра `--template=`. -Далее он может быть имортирован (`--import=`). Импорт предполагает копирование профиля полностью, +Далее он может быть импортирован (`--import=`). Импорт предполагает копирование профиля полностью, а не только тех настроек, которые в нем были указаны - все остальные настройки имеют значения по умолчанию. Любые настройки текущего профиля стираются, включая и имя. Поэтому `--import` надо писать в начале, а потом добавлять уникальные для профиля параметры. diff --git a/nfq2/darkmagic.c b/nfq2/darkmagic.c index 3a77724..94de3d1 100644 --- a/nfq2/darkmagic.c +++ b/nfq2/darkmagic.c @@ -40,9 +40,6 @@ #include #include #include -#define _LINUX_IF_H // prevent conflict between linux/if.h and net/if.h in old gcc 4.x -#include -#include #endif uint32_t net32_add(uint32_t netorder_value, uint32_t cpuorder_increment) @@ -1578,9 +1575,9 @@ bool rawsend_queue(struct rawpacket_tailhead *q) // linux-specific wlan retrieval implementation -typedef void netlink_prepare_nlh_cb_t(struct nlmsghdr *nlh); +typedef void netlink_prepare_nlh_cb_t(struct nlmsghdr *nlh, void *param); -static bool netlink_genl_simple_transact(struct mnl_socket* nl, uint16_t type, uint16_t flags, uint8_t cmd, uint8_t version, netlink_prepare_nlh_cb_t cb_prepare_nlh, mnl_cb_t cb_data, void *data) +static bool netlink_genl_simple_transact(struct mnl_socket* nl, uint16_t type, uint16_t flags, uint8_t cmd, uint8_t version, netlink_prepare_nlh_cb_t cb_prepare_nlh, void *prepare_data, mnl_cb_t cb_data, void *data) { char buf[MNL_SOCKET_BUFFER_SIZE]; struct nlmsghdr *nlh; @@ -1595,7 +1592,7 @@ static bool netlink_genl_simple_transact(struct mnl_socket* nl, uint16_t type, u genl->cmd = cmd; genl->version = version; - if (cb_prepare_nlh) cb_prepare_nlh(nlh); + if (cb_prepare_nlh) cb_prepare_nlh(nlh, prepare_data); if (mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0) { @@ -1619,7 +1616,7 @@ static bool netlink_genl_simple_transact(struct mnl_socket* nl, uint16_t type, u return false; } -static void wlan_id_prepare(struct nlmsghdr *nlh) +static void wlan_id_prepare(struct nlmsghdr *nlh, void *param) { mnl_attr_put_strz(nlh, CTRL_ATTR_FAMILY_NAME, "nl80211"); } @@ -1651,7 +1648,7 @@ static int wlan_id_cb(const struct nlmsghdr *nlh, void *data) static uint16_t wlan_get_family_id(struct mnl_socket* nl) { uint16_t id; - return netlink_genl_simple_transact(nl, GENL_ID_CTRL, NLM_F_REQUEST | NLM_F_ACK, CTRL_CMD_GETFAMILY, 1, wlan_id_prepare, wlan_id_cb, &id) ? id : 0; + return netlink_genl_simple_transact(nl, GENL_ID_CTRL, NLM_F_REQUEST | NLM_F_ACK, CTRL_CMD_GETFAMILY, 1, wlan_id_prepare, NULL, wlan_id_cb, &id) ? id : 0; } static int wlan_info_attr_cb(const struct nlattr *attr, void *data) @@ -1686,42 +1683,130 @@ static int wlan_info_attr_cb(const struct nlattr *attr, void *data) } return MNL_CB_OK; } +struct wlan_info_req +{ + struct wlan_interface_collection *wc; + bool bReqSSID; +}; static int wlan_info_cb(const struct nlmsghdr *nlh, void *data) +{ + int ret; + struct wlan_info_req *wr = (struct wlan_info_req*)data; + if (wr->wc->count>=WLAN_INTERFACE_MAX) return MNL_CB_OK; + memset(wr->wc->wlan + wr->wc->count,0,sizeof(struct wlan_interface)); + ret = mnl_attr_parse(nlh, sizeof(struct genlmsghdr), wlan_info_attr_cb, wr->wc->wlan + wr->wc->count); + if (ret>=0 && (!wr->bReqSSID || *wr->wc->wlan[wr->wc->count].ssid) && *wr->wc->wlan[wr->wc->count].ifname && wr->wc->wlan[wr->wc->count].ifindex) + wr->wc->count++; + return ret; +} +static bool wlan_info(struct mnl_socket* nl, uint16_t wlan_family_id, struct wlan_interface_collection* w, bool bReqSSID) +{ + struct wlan_info_req req = { .bReqSSID = bReqSSID, .wc = w }; + return netlink_genl_simple_transact(nl, wlan_family_id, NLM_F_REQUEST | NLM_F_ACK | NLM_F_DUMP, NL80211_CMD_GET_INTERFACE, 0, NULL, NULL, wlan_info_cb, &req); +} + + +static void scan_prepare(struct nlmsghdr *nlh, void *param) +{ + mnl_attr_put_u32(nlh, NL80211_ATTR_IFINDEX, *(int*)param); +} +static uint8_t *find_ie(uint8_t *buf, size_t len, uint8_t ie) +{ + while (len>=2) + { + if (len<(2+buf[1])) break; + if (buf[0]==ie) return buf; + buf+=buf[1]+2; + len-=buf[1]+2; + } + return NULL; +} +static int scan_info_attr_cb(const struct nlattr *attr, void *data) +{ + struct wlan_interface *wlan = (struct wlan_interface *)data; + const struct nlattr *nested; + uint8_t *payload, *ie; + uint16_t payload_len; + bool ok; + + switch(mnl_attr_get_type(attr)) + { + case NL80211_ATTR_IFINDEX: + if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0) + { + DLOG_PERROR("mnl_attr_validate"); + return MNL_CB_ERROR; + } + wlan->ifindex = mnl_attr_get_u32(attr); + if (!if_indextoname(wlan->ifindex, wlan->ifname)) + DLOG_PERROR("if_indextoname"); + break; + case NL80211_ATTR_BSS: + if (mnl_attr_validate(attr, MNL_TYPE_NESTED) < 0) + { + DLOG_PERROR("mnl_attr_validate"); + return MNL_CB_ERROR; + } + ok = false; + mnl_attr_for_each_nested(nested, attr) + { + if (mnl_attr_get_type(nested)==NL80211_BSS_STATUS) + { + uint32_t status = mnl_attr_get_u32(nested); + if (status==NL80211_BSS_STATUS_ASSOCIATED || status==NL80211_BSS_STATUS_AUTHENTICATED || status==NL80211_BSS_STATUS_IBSS_JOINED) + { + ok=1; + break; + } + } + } + if (!ok) break; + mnl_attr_for_each_nested(nested, attr) + { + switch(mnl_attr_get_type(nested)) + { + case NL80211_BSS_INFORMATION_ELEMENTS: + payload_len = mnl_attr_get_payload_len(nested); + payload = mnl_attr_get_payload(nested); + ie = find_ie(payload,payload_len,0); + if (ie) + { + uint8_t l = ie[1]; + if (l>=(sizeof(wlan->ssid))) l=sizeof(wlan->ssid)-1; + memcpy(wlan->ssid,ie+2,l); + wlan->ssid[l]=0; + } + break; + } + } + break; + } + return MNL_CB_OK; +} +static int scan_info_cb(const struct nlmsghdr *nlh, void *data) { int ret; struct wlan_interface_collection *wc = (struct wlan_interface_collection*)data; if (wc->count>=WLAN_INTERFACE_MAX) return MNL_CB_OK; memset(wc->wlan+wc->count,0,sizeof(wc->wlan[0])); - ret = mnl_attr_parse(nlh, sizeof(struct genlmsghdr), wlan_info_attr_cb, wc->wlan+wc->count); - if (ret>=0 && *wc->wlan[wc->count].ifname && wc->wlan[wc->count].ifindex) - { - if (*wc->wlan[wc->count].ssid) - wc->count++; - else - { - // sometimes nl80211 does not return SSID but wireless ext does - int wext_fd = socket(AF_INET, SOCK_DGRAM, 0); - if (wext_fd!=-1) - { - struct iwreq req; - snprintf(req.ifr_ifrn.ifrn_name,sizeof(req.ifr_ifrn.ifrn_name),"%s",wc->wlan[wc->count].ifname); - req.u.essid.pointer = wc->wlan[wc->count].ssid; - req.u.essid.length = sizeof(wc->wlan[wc->count].ssid); - req.u.essid.flags = 0; - if (ioctl(wext_fd, SIOCGIWESSID, &req)!=-1) - if (*wc->wlan[wc->count].ssid) - wc->count++; - close(wext_fd); - } - } - } + ret = mnl_attr_parse(nlh, sizeof(struct genlmsghdr), scan_info_attr_cb, wc->wlan+wc->count); + if (ret>=0 && *wc->wlan[wc->count].ssid && *wc->wlan[wc->count].ifname && wc->wlan[wc->count].ifindex) + wc->count++; return ret; } -static bool wlan_info(struct mnl_socket* nl, uint16_t wlan_family_id, struct wlan_interface_collection* w) +static bool scan_info(struct mnl_socket* nl, uint16_t wlan_family_id, struct wlan_interface_collection* w) { - return netlink_genl_simple_transact(nl, wlan_family_id, NLM_F_REQUEST | NLM_F_ACK | NLM_F_DUMP, NL80211_CMD_GET_INTERFACE, 0, NULL, wlan_info_cb, w); + struct wlan_interface_collection wc_all = { .count = 0 }; + // wlan_info does not return ssid since kernel 5.19 + // it's used to enumerate all wifi interfaces then call scan_info on each + if (!wlan_info(nl, wlan_family_id, &wc_all, false)) return false; + for(int i=0;i