aboutsummaryrefslogtreecommitdiffstats
path: root/caputils/ws80211_utils.c
diff options
context:
space:
mode:
Diffstat (limited to 'caputils/ws80211_utils.c')
-rw-r--r--caputils/ws80211_utils.c1275
1 files changed, 0 insertions, 1275 deletions
diff --git a/caputils/ws80211_utils.c b/caputils/ws80211_utils.c
deleted file mode 100644
index 6c34b8e929..0000000000
--- a/caputils/ws80211_utils.c
+++ /dev/null
@@ -1,1275 +0,0 @@
-/*
- * ws80211 utilities
- * Copyright 2012, Pontus Fuchs <pontus.fuchs@gmail.com>
-
-Parts of this file was copied from iw:
-
-Copyright (c) 2007, 2008 Johannes Berg
-Copyright (c) 2007 Andy Lutomirski
-Copyright (c) 2007 Mike Kershaw
-Copyright (c) 2008-2009 Luis R. Rodriguez
-
-SPDX-License-Identifier: ISC
-*/
-
-#include <config.h>
-
-#include <stdio.h>
-
-#include <glib.h>
-#include <glib/gstdio.h>
-
-#include "ws80211_utils.h"
-
-#if defined(HAVE_LIBNL) && defined(HAVE_NL80211)
-#include <string.h>
-#include <errno.h>
-#include <unistd.h>
-
-#include <net/if.h>
-#include <sys/ioctl.h>
-
-DIAG_OFF_PEDANTIC
-#include <netlink/genl/genl.h>
-DIAG_ON_PEDANTIC
-#include <netlink/genl/family.h>
-#include <netlink/genl/ctrl.h>
-DIAG_OFF_PEDANTIC
-#include <netlink/msg.h>
-DIAG_ON_PEDANTIC
-#include <netlink/attr.h>
-
-#include <linux/nl80211.h>
-
-#include <wsutil/netlink.h>
-
-#ifdef HAVE_NL80211_SPLIT_WIPHY_DUMP
-static int ws80211_get_protocol_features(int* features);
-#endif /* HAVE_NL80211_SPLIT_WIPHY_DUMP */
-
-/* libnl 1.x compatibility code */
-#ifdef HAVE_LIBNL1
-#define nl_sock nl_handle
-static inline struct nl_handle *nl_socket_alloc(void)
-{
- return nl_handle_alloc();
-}
-
-static inline void nl_socket_free(struct nl_sock *h)
-{
- nl_handle_destroy(h);
-}
-#endif /* HAVE_LIBNL1 */
-
-struct nl80211_state {
- struct nl_sock *nl_sock;
- int nl80211_id;
- int have_split_wiphy;
-};
-
-static struct nl80211_state nl_state;
-
-int ws80211_init(void)
-{
- int err;
-#ifdef HAVE_NL80211_SPLIT_WIPHY_DUMP
- int features = 0;
-#endif /* HAVE_NL80211_SPLIT_WIPHY_DUMP */
-
- struct nl80211_state *state = &nl_state;
-
- state->nl_sock = nl_socket_alloc();
- if (!state->nl_sock) {
- fprintf(stderr, "Failed to allocate netlink socket.\n");
- return -ENOMEM;
- }
-
- if (genl_connect(state->nl_sock)) {
- fprintf(stderr, "Failed to connect to generic netlink.\n");
- err = -ENOLINK;
- goto out_handle_destroy;
- }
-
- state->nl80211_id = genl_ctrl_resolve(state->nl_sock, "nl80211");
- if (state->nl80211_id < 0) {
- fprintf(stderr, "nl80211 not found.\n");
- err = -ENOENT;
- goto out_handle_destroy;
- }
-#ifdef HAVE_NL80211_SPLIT_WIPHY_DUMP
- ws80211_get_protocol_features(&features);
- if (features & NL80211_PROTOCOL_FEATURE_SPLIT_WIPHY_DUMP)
- state->have_split_wiphy = TRUE;
-#endif /* HAVE_NL80211_SPLIT_WIPHY_DUMP */
-
- return WS80211_INIT_OK;
-
- out_handle_destroy:
- nl_socket_free(state->nl_sock);
- state->nl_sock = 0;
- return err;
-}
-
-static int error_handler(struct sockaddr_nl *nla _U_, struct nlmsgerr *err,
- void *arg)
-{
- int *ret = (int *)arg;
- *ret = err->error;
- return NL_STOP;
-}
-
-static int finish_handler(struct nl_msg *msg _U_, void *arg)
-{
- int *ret = (int *)arg;
- *ret = 0;
- return NL_SKIP;
-}
-
-static int ack_handler(struct nl_msg *msg _U_, void *arg)
-{
- int *ret = (int *)arg;
- *ret = 0;
- return NL_STOP;
-}
-
-static int nl80211_do_cmd(struct nl_msg *msg, struct nl_cb *cb)
-{
- /*
- * XXX - Coverity doesn't understand how libnl works, so it
- * doesn't know that nl_recvmsgs() calls the callback, and
- * that the callback has had a pointer to err registered
- * with it, and therefore that nl_recvmsgs() can change
- * err as a side-effect, so it thinks this can loop
- * infinitely.
- *
- * The proper way to address this is to help Coverity to
- * understand the behaviour of nl_recvmsgs(), in that it
- * does call the callback, setting err. This help would be
- * provided through a so called 'model' of this function.
- * We declare err to be volatile to work around it.
- *
- * XXX - that workaround provokes a compiler complaint that
- * casting a pointer to it to "void *" discards the
- * volatile qualifier. Perhaps we should just re-close
- * Coverity CID 997052 as "false positive".
- */
- volatile int err;
-
- if (!nl_state.nl_sock)
- return -ENOLINK;
-
- err = nl_send_auto_complete(nl_state.nl_sock, msg);
- if (err < 0)
- goto out;
-
- err = 1;
-
- nl_cb_err(cb, NL_CB_CUSTOM, error_handler, (void *)&err);
- nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, finish_handler, (void *)&err);
- nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, ack_handler, (void *)&err);
-
- while (err > 0)
- nl_recvmsgs(nl_state.nl_sock, cb);
- out:
- nl_cb_put(cb);
-
- return err;
-}
-
-struct nliface_cookie
-{
- char *ifname;
- GArray *interfaces;
-};
-
-static struct ws80211_interface *
- get_interface_by_name(GArray *interfaces,
- char* ifname)
-{
- unsigned int i;
- struct ws80211_interface *iface;
-
- for (i = 0; i < interfaces->len; i++) {
- iface = g_array_index(interfaces, struct ws80211_interface *, i);
- if (!strcmp(iface->ifname, ifname))
- return iface;
- }
- return NULL;
-}
-
-#ifdef HAVE_NL80211_SPLIT_WIPHY_DUMP
-static int get_features_handler(struct nl_msg *msg, void *arg)
-{
- int *feat = (int*) arg;
- struct nlattr *tb_msg[NL80211_ATTR_MAX + 1];
- struct genlmsghdr *gnlh = (struct genlmsghdr *)nlmsg_data(nlmsg_hdr(msg));
-
- nla_parse(tb_msg, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
- genlmsg_attrlen(gnlh, 0), NULL);
-
- if (tb_msg[NL80211_ATTR_PROTOCOL_FEATURES])
- *feat = nla_get_u32(tb_msg[NL80211_ATTR_PROTOCOL_FEATURES]);
-
- return NL_SKIP;
-}
-
-static int ws80211_get_protocol_features(int* features)
-{
- struct nl_msg *msg;
- struct nl_cb *cb;
- int ret;
-
- msg = nlmsg_alloc();
- if (!msg) {
- fprintf(stderr, "failed to allocate netlink message\n");
- return 2;
- }
-
- cb = nl_cb_alloc(NL_CB_DEFAULT);
-
- genlmsg_put(msg, 0, 0, nl_state.nl80211_id, 0, 0,
- NL80211_CMD_GET_PROTOCOL_FEATURES, 0);
-
- nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, get_features_handler, features);
-
- ret = nl80211_do_cmd(msg, cb);
- nlmsg_free(msg);
- return ret;
-}
-#endif /* HAVE_NL80211_SPLIT_WIPHY_DUMP */
-
-#ifdef NL80211_BAND_ATTR_HT_CAPA
-static void parse_band_ht_capa(struct ws80211_interface *iface,
- struct nlattr *tb)
-{
- gboolean ht40;
-
- if (!tb) return;
-
- iface->channel_types |= 1 << WS80211_CHAN_HT20;
- ht40 = !!(nla_get_u16(tb) & 0x02);
- if (ht40) {
- iface->channel_types |= 1 << WS80211_CHAN_HT40MINUS;
- iface->channel_types |= 1 << WS80211_CHAN_HT40PLUS;
- }
-}
-#endif /* NL80211_BAND_ATTR_HT_CAPA */
-
-#ifdef HAVE_NL80211_VHT_CAPABILITY
-static void parse_band_vht_capa(struct ws80211_interface *iface,
- struct nlattr *tb)
-{
- guint32 chan_capa;
- if (!tb) return;
-
- chan_capa = (nla_get_u32(tb) >> 2) & 3;
- if (chan_capa == 1) {
- iface->channel_types |= 1 << WS80211_CHAN_VHT160;
- }
- if (chan_capa == 2) {
- iface->channel_types |= 1 << WS80211_CHAN_VHT160;
- iface->channel_types |= 1 << WS80211_CHAN_VHT80P80;
- }
- iface->channel_types |= 1 << WS80211_CHAN_VHT80;
-}
-#endif /* HAVE_NL80211_VHT_CAPABILITY */
-
-static void parse_supported_iftypes(struct ws80211_interface *iface,
- struct nlattr *tb)
-{
- struct nlattr *nl_mode;
- int rem_mode;
-
- if (!tb) return;
-
- nla_for_each_nested(nl_mode, tb, rem_mode) {
- if (nla_type(nl_mode) == NL80211_IFTYPE_MONITOR)
- iface->cap_monitor = 1;
- }
-}
-
-static void parse_band_freqs(struct ws80211_interface *iface,
- struct nlattr *tb)
-{
- struct nlattr *nl_freq;
- struct nlattr *tb_freq[NL80211_FREQUENCY_ATTR_MAX + 1];
- static struct nla_policy freq_policy[NL80211_FREQUENCY_ATTR_MAX + 1] = {
- {NLA_UNSPEC, 0, 0}, /* __NL80211_FREQUENCY_ATTR_INVALID */
- {NLA_U32, 0, 0}, /* NL80211_FREQUENCY_ATTR_FREQ */
- {NLA_FLAG, 0, 0}, /* NL80211_FREQUENCY_ATTR_DISABLED */
- {NLA_FLAG, 0, 0}, /* NL80211_FREQUENCY_ATTR_PASSIVE_SCAN */
- {NLA_FLAG, 0, 0}, /* NL80211_FREQUENCY_ATTR_NO_IBSS */
- {NLA_FLAG, 0, 0}, /* NL80211_FREQUENCY_ATTR_RADAR */
- {NLA_U32, 0, 0} /* NL80211_FREQUENCY_ATTR_MAX_TX_POWER */
- };
- int rem_freq;
-
- if (!tb) return;
-
- nla_for_each_nested(nl_freq, tb, rem_freq) {
- uint32_t freq;
- nla_parse(tb_freq, NL80211_FREQUENCY_ATTR_MAX,
- (struct nlattr *)nla_data(nl_freq),
- nla_len(nl_freq), freq_policy);
- if (!tb_freq[NL80211_FREQUENCY_ATTR_FREQ])
- continue;
- if (tb_freq[NL80211_FREQUENCY_ATTR_DISABLED])
- continue;
-
- freq = nla_get_u32(tb_freq[NL80211_FREQUENCY_ATTR_FREQ]);
- g_array_append_val(iface->frequencies, freq);
- }
-}
-
-static void parse_wiphy_bands(struct ws80211_interface *iface,
- struct nlattr *tb)
-{
- struct nlattr *nl_band;
- struct nlattr *tb_band[NL80211_BAND_ATTR_MAX + 1];
- int bandidx = 1;
- int rem_band;
-
- if (!tb) return;
-
- nla_for_each_nested(nl_band, tb, rem_band) {
- bandidx++;
-
- nla_parse(tb_band, NL80211_BAND_ATTR_MAX,
- (struct nlattr *)nla_data(nl_band),
- nla_len(nl_band), NULL);
-
-#ifdef NL80211_BAND_ATTR_HT_CAPA
- parse_band_ht_capa(iface, tb_band[NL80211_BAND_ATTR_HT_CAPA]);
-#endif /* NL80211_BAND_ATTR_HT_CAPA */
-#ifdef HAVE_NL80211_VHT_CAPABILITY
- parse_band_vht_capa(iface, tb_band[NL80211_BAND_ATTR_VHT_CAPA]);
-#endif /* HAVE_NL80211_VHT_CAPABILITY */
- parse_band_freqs(iface, tb_band[NL80211_BAND_ATTR_FREQS]);
- }
-}
-
-static void parse_supported_commands(struct ws80211_interface *iface,
- struct nlattr *tb)
-{
- /* Can frequency be set? Only newer versions of cfg80211 supports this */
-#ifdef HAVE_NL80211_CMD_SET_CHANNEL
- int cmd;
- struct nlattr *nl_cmd;
-
- if (!tb) return;
-
- nla_for_each_nested(nl_cmd, tb, cmd) {
- if(nla_get_u32(nl_cmd) == NL80211_CMD_SET_CHANNEL)
- iface->can_set_freq = TRUE;
- }
-#else
- iface->can_set_freq = TRUE;
-#endif
-}
-
-static int get_phys_handler(struct nl_msg *msg, void *arg)
-{
- struct nlattr *tb_msg[NL80211_ATTR_MAX + 1];
- struct genlmsghdr *gnlh = (struct genlmsghdr *)nlmsg_data(nlmsg_hdr(msg));
-
- struct nliface_cookie *cookie = (struct nliface_cookie *)arg;
-
- struct ws80211_interface *iface;
- char* ifname;
- int added = 0;
-
- nla_parse(tb_msg, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
- genlmsg_attrlen(gnlh, 0), NULL);
-
- if (!tb_msg[NL80211_ATTR_WIPHY_NAME])
- return NL_SKIP;
-
- ifname = g_strdup_printf("%s.mon", nla_get_string(tb_msg[NL80211_ATTR_WIPHY_NAME]));
- iface = get_interface_by_name(cookie->interfaces, ifname);
-
- if (!iface) {
- iface = (struct ws80211_interface *)g_malloc0(sizeof(*iface));
- if (!iface) {
- g_free(ifname);
- return NL_SKIP;
- }
- added = 1;
- iface->ifname = ifname;
- iface->frequencies = g_array_new(FALSE, FALSE, sizeof(uint32_t));
- iface->channel_types = 1 << WS80211_CHAN_NO_HT;
- } else {
- g_free(ifname);
- }
-
- parse_supported_iftypes(iface, tb_msg[NL80211_ATTR_SUPPORTED_IFTYPES]);
- parse_wiphy_bands(iface, tb_msg[NL80211_ATTR_WIPHY_BANDS]);
- parse_supported_commands(iface, tb_msg[NL80211_ATTR_SUPPORTED_COMMANDS]);
-
- if (added)
- g_array_append_val(cookie->interfaces, iface);
-
- return NL_SKIP;
-}
-
-static int ws80211_get_phys(GArray *interfaces)
-{
- struct nliface_cookie cookie;
- struct nl_msg *msg;
- struct nl_cb *cb;
- int ret;
- msg = nlmsg_alloc();
- if (!msg) {
- fprintf(stderr, "failed to allocate netlink message\n");
- return 2;
- }
-
- cb = nl_cb_alloc(NL_CB_DEFAULT);
-
- cookie.interfaces = interfaces;
-
- genlmsg_put(msg, 0, 0, nl_state.nl80211_id, 0,
- NLM_F_DUMP, NL80211_CMD_GET_WIPHY, 0);
-
-#ifdef HAVE_NL80211_SPLIT_WIPHY_DUMP
- if (nl_state.have_split_wiphy) {
- NLA_PUT_FLAG(msg, NL80211_ATTR_SPLIT_WIPHY_DUMP);
- }
-#endif /* #ifdef HAVE_NL80211_SPLIT_WIPHY_DUMP */
- nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, get_phys_handler, &cookie);
-
- ret = nl80211_do_cmd(msg, cb);
- nlmsg_free(msg);
- return ret;
-
-#ifdef HAVE_NL80211_SPLIT_WIPHY_DUMP
-nla_put_failure:
- nlmsg_free(msg);
- fprintf(stderr, "building message failed\n");
- return -1;
-#endif /* HAVE_NL80211_SPLIT_WIPHY_DUMP */
-}
-
-static int get_freq_wext(const char *ifname)
-{
- int fd;
- int ret = -1;
- /* Ugly hack to avoid including wireless.h */
- struct {
- char name1[IFNAMSIZ];
- __s32 m;
- __s16 e;
- __u8 i;
- __u8 flags;
- } wrq;
-
- fd = socket(AF_INET, SOCK_DGRAM, 0);
- if (fd == -1)
- return -1;
-
- g_strlcpy(wrq.name1, ifname, IFNAMSIZ);
- /* SIOCGIWFREQ */
- if (ioctl(fd, 0x8B05, &wrq) == 0) {
- if (wrq.e == 6)
- ret = wrq.m;
- }
- close(fd);
- return ret;
-}
-
-struct __iface_info
-{
- struct ws80211_iface_info *pub;
- int type;
- int phyidx;
-};
-
-static int get_iface_info_handler(struct nl_msg *msg, void *arg)
-{
- struct genlmsghdr *gnlh = (struct genlmsghdr *)nlmsg_data(nlmsg_hdr(msg));
- struct nlattr *tb_msg[NL80211_ATTR_MAX + 1];
- struct __iface_info *iface_info = (struct __iface_info *)arg;
-
- nla_parse(tb_msg, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
- genlmsg_attrlen(gnlh, 0), NULL);
-
- if (tb_msg[NL80211_ATTR_IFTYPE]) {
- iface_info->type = nla_get_u32(tb_msg[NL80211_ATTR_IFTYPE]);
- }
- if (tb_msg[NL80211_ATTR_WIPHY]) {
- iface_info->phyidx = nla_get_u32(tb_msg[NL80211_ATTR_WIPHY]);
- }
-
- if (tb_msg[NL80211_ATTR_WIPHY_FREQ]) {
- gboolean found_ch_width = FALSE;
- iface_info->pub->current_freq = nla_get_u32(tb_msg[NL80211_ATTR_WIPHY_FREQ]);
- iface_info->pub->current_chan_type = WS80211_CHAN_NO_HT;
-#ifdef HAVE_NL80211_VHT_CAPABILITY
- if (tb_msg[NL80211_ATTR_CHANNEL_WIDTH]) {
- switch (nla_get_u32(tb_msg[NL80211_ATTR_CHANNEL_WIDTH])) {
- case NL80211_CHAN_WIDTH_80:
- iface_info->pub->current_chan_type = WS80211_CHAN_VHT80;
- found_ch_width = TRUE;
- break;
- case NL80211_CHAN_WIDTH_80P80:
- iface_info->pub->current_chan_type = WS80211_CHAN_VHT80P80;
- found_ch_width = TRUE;
- break;
- case NL80211_CHAN_WIDTH_160:
- iface_info->pub->current_chan_type = WS80211_CHAN_VHT160;
- found_ch_width = TRUE;
- break;
- }
- }
- if (tb_msg[NL80211_ATTR_CENTER_FREQ1]) {
- iface_info->pub->current_center_freq1 =
- nla_get_u32(tb_msg[NL80211_ATTR_CENTER_FREQ1]);
- }
- if (tb_msg[NL80211_ATTR_CENTER_FREQ2]) {
- iface_info->pub->current_center_freq2 =
- nla_get_u32(tb_msg[NL80211_ATTR_CENTER_FREQ2]);
- }
-#endif
- if (!found_ch_width && tb_msg[NL80211_ATTR_WIPHY_CHANNEL_TYPE]) {
- switch (nla_get_u32(tb_msg[NL80211_ATTR_WIPHY_CHANNEL_TYPE])) {
-
- case NL80211_CHAN_NO_HT:
- iface_info->pub->current_chan_type = WS80211_CHAN_NO_HT;
- break;
-
- case NL80211_CHAN_HT20:
- iface_info->pub->current_chan_type = WS80211_CHAN_HT20;
- break;
-
- case NL80211_CHAN_HT40MINUS:
- iface_info->pub->current_chan_type = WS80211_CHAN_HT40MINUS;
- break;
-
- case NL80211_CHAN_HT40PLUS:
- iface_info->pub->current_chan_type = WS80211_CHAN_HT40PLUS;
- break;
- }
- }
-
- }
- return NL_SKIP;
-}
-
-
-static int __ws80211_get_iface_info(const char *name, struct __iface_info *iface_info)
-{
- int devidx;
- struct nl_msg *msg;
- struct nl_cb *cb;
- msg = nlmsg_alloc();
- if (!msg) {
- fprintf(stderr, "failed to allocate netlink message\n");
- return 2;
- }
-
- cb = nl_cb_alloc(NL_CB_DEFAULT);
-
- devidx = if_nametoindex(name);
-
- genlmsg_put(msg, 0, 0, nl_state.nl80211_id, 0,
- 0, NL80211_CMD_GET_INTERFACE, 0);
- NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, devidx);
-
- nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, get_iface_info_handler, iface_info);
-
- if (nl80211_do_cmd(msg, cb)) {
- nlmsg_free(msg);
- return -1;
- }
-
- /* Old kernels can't get the current freq via netlink. Try WEXT too :( */
- if (iface_info->pub->current_freq == -1)
- iface_info->pub->current_freq = get_freq_wext(name);
- nlmsg_free(msg);
- return 0;
-
-nla_put_failure:
- nlmsg_free(msg);
- fprintf(stderr, "building message failed\n");
- return -1;
-}
-
-int ws80211_get_iface_info(const char *name, struct ws80211_iface_info *iface_info)
-{
- struct __iface_info __iface_info;
-
- memset(iface_info, 0, sizeof(*iface_info));
- __iface_info.pub = iface_info;
- __iface_info.type = -1;
- __iface_info.phyidx= -1;
- __iface_info.pub->current_freq = -1;
- __iface_info.pub->current_chan_type = WS80211_CHAN_NO_HT;
-
- return __ws80211_get_iface_info(name, &__iface_info);
-}
-
-static int ws80211_keep_only_monitor(GArray *interfaces)
-{
- unsigned int j;
- struct ws80211_interface *iface;
-restart:
- for (j = 0; j < interfaces->len; j++) {
- iface = g_array_index(interfaces, struct ws80211_interface *, j);
- if (!iface->cap_monitor) {
- g_array_remove_index(interfaces, j);
- g_array_free(iface->frequencies, TRUE);
- g_free(iface->ifname);
- g_free(iface);
- goto restart;
- }
- }
- return 0;
-}
-
-static int ws80211_populate_devices(GArray *interfaces)
-{
- FILE *fh;
- char line[200];
- char *t;
- gchar *t2;
- char *ret;
- int i;
- unsigned int j;
-
- struct ws80211_iface_info pub = {-1, WS80211_CHAN_NO_HT, -1, -1, WS80211_FCS_ALL};
- struct __iface_info iface_info;
- struct ws80211_interface *iface;
-
- /* Get a list of phy's that can handle monitor mode */
- ws80211_get_phys(interfaces);
- ws80211_keep_only_monitor(interfaces);
-
- fh = g_fopen("/proc/net/dev", "r");
- if(!fh) {
- fprintf(stderr, "Cannot open /proc/net/dev");
- return -ENOENT;
- }
-
- /* Skip the first two lines */
- for (i = 0; i < 2; i++) {
- ret = fgets(line, sizeof(line), fh);
- if (ret == NULL) {
- fprintf(stderr, "Error parsing /proc/net/dev");
- fclose(fh);
- return -1;
- }
- }
-
- /* Update names of user created monitor interfaces */
- while(fgets(line, sizeof(line), fh)) {
- t = index(line, ':');
- if (!t)
- continue;
- *t = 0;
- t = line;
- while (*t == ' ')
- t++;
- memset(&iface_info, 0, sizeof(iface_info));
- iface_info.pub = &pub;
- __ws80211_get_iface_info(t, &iface_info);
-
- if (iface_info.type == NL80211_IFTYPE_MONITOR) {
- for (j = 0; j < interfaces->len; j++) {
- iface = g_array_index(interfaces, struct ws80211_interface *, j);
- t2 = g_strdup_printf("phy%d.mon", iface_info.phyidx);
- if (t2) {
- if (!strcmp(t2, iface->ifname)) {
- g_free(iface->ifname);
- iface->ifname = g_strdup(t);
- }
- g_free(t2);
- }
- }
- }
- }
- fclose(fh);
- return 0;
-}
-
-static int ws80211_iface_up(const char *ifname)
-{
- int sock;
- struct ifreq ifreq;
-
- sock = socket(AF_PACKET, SOCK_RAW, 0);
- if (sock == -1)
- return -1;
-
- g_strlcpy(ifreq.ifr_name, ifname, sizeof(ifreq.ifr_name));
-
- if (ioctl(sock, SIOCGIFFLAGS, &ifreq))
- goto out_err;
-
- ifreq.ifr_flags |= IFF_UP;
-
- if (ioctl(sock, SIOCSIFFLAGS, &ifreq))
- goto out_err;
-
- close(sock);
- return 0;
-
-out_err:
- close(sock);
- return -1;
-}
-
-/* Needed for NLA_PUT_STRING, which passes strlen as an int */
-DIAG_OFF_CLANG(shorten-64-to-32)
-static int ws80211_create_on_demand_interface(const char *name)
-{
- int devidx, phyidx, err;
- struct nl_msg *msg;
- struct nl_cb *cb;
-
- devidx = if_nametoindex(name);
- if (devidx)
- return ws80211_iface_up(name);
-
- if (sscanf(name, "phy%d.mon", &phyidx) != 1)
- return -EINVAL;
-
- cb = nl_cb_alloc(NL_CB_DEFAULT);
- msg = nlmsg_alloc();
- if (!msg) {
- fprintf(stderr, "failed to allocate netlink message\n");
- return 2;
- }
-
- genlmsg_put(msg, 0, 0, nl_state.nl80211_id, 0,
- 0, NL80211_CMD_NEW_INTERFACE, 0);
- NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, phyidx);
-
- NLA_PUT_STRING(msg, NL80211_ATTR_IFNAME, name);
- NLA_PUT_U32(msg, NL80211_ATTR_IFTYPE, NL80211_IFTYPE_MONITOR);
-
- err = nl80211_do_cmd(msg, cb);
- nlmsg_free(msg);
- if (err)
- return err;
- return ws80211_iface_up(name);
-
-nla_put_failure:
- nlmsg_free(msg);
- fprintf(stderr, "building message failed\n");
- return 2;
-}
-DIAG_ON_CLANG(shorten-64-to-32)
-
-int ws80211_set_freq(const char *name, guint32 freq, int chan_type, guint32 _U_ center_freq, guint32 _U_ center_freq2)
-{
- int devidx, err;
- struct nl_msg *msg;
- struct nl_cb *cb;
-
- err = ws80211_create_on_demand_interface(name);
- if (err)
- return err;
-
- msg = nlmsg_alloc();
- if (!msg) {
- fprintf(stderr, "failed to allocate netlink message\n");
- return 2;
- }
-
- cb = nl_cb_alloc(NL_CB_DEFAULT);
-
- devidx = if_nametoindex(name);
-
-#ifdef HAVE_NL80211_CMD_SET_CHANNEL
- genlmsg_put(msg, 0, 0, nl_state.nl80211_id, 0,
- 0, NL80211_CMD_SET_CHANNEL, 0);
-#else
- genlmsg_put(msg, 0, 0, nl_state.nl80211_id, 0,
- 0, NL80211_CMD_SET_WIPHY, 0);
-#endif
-
- NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, devidx);
- NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_FREQ, freq);
-
- switch (chan_type) {
-
-#ifdef NL80211_BAND_ATTR_HT_CAPA
- case WS80211_CHAN_NO_HT:
- NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_CHANNEL_TYPE, NL80211_CHAN_NO_HT);
- break;
-
- case WS80211_CHAN_HT20:
- NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_CHANNEL_TYPE, NL80211_CHAN_HT20);
- break;
-
- case WS80211_CHAN_HT40MINUS:
- NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_CHANNEL_TYPE, NL80211_CHAN_HT40MINUS);
- break;
-
- case WS80211_CHAN_HT40PLUS:
- NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_CHANNEL_TYPE, NL80211_CHAN_HT40PLUS);
- break;
-#endif
-#ifdef HAVE_NL80211_VHT_CAPABILITY
- case WS80211_CHAN_VHT80:
- NLA_PUT_U32(msg, NL80211_ATTR_CHANNEL_WIDTH, NL80211_CHAN_WIDTH_80);
- NLA_PUT_U32(msg, NL80211_ATTR_CENTER_FREQ1, center_freq);
- break;
-
- case WS80211_CHAN_VHT80P80:
- NLA_PUT_U32(msg, NL80211_ATTR_CHANNEL_WIDTH, NL80211_CHAN_WIDTH_80P80);
- NLA_PUT_U32(msg, NL80211_ATTR_CENTER_FREQ1, center_freq);
- NLA_PUT_U32(msg, NL80211_ATTR_CENTER_FREQ2, center_freq2);
- break;
-
- case WS80211_CHAN_VHT160:
- NLA_PUT_U32(msg, NL80211_ATTR_CHANNEL_WIDTH, NL80211_CHAN_WIDTH_160);
- NLA_PUT_U32(msg, NL80211_ATTR_CENTER_FREQ1, center_freq);
- break;
-#endif
- default:
- break;
- }
- err = nl80211_do_cmd(msg, cb);
- nlmsg_free(msg);
- return err;
-
-nla_put_failure:
- nlmsg_free(msg);
- fprintf(stderr, "building message failed\n");
- return 2;
-
-}
-
-GArray* ws80211_find_interfaces(void)
-{
- GArray *interfaces;
-
- if (!nl_state.nl_sock)
- return NULL;
-
- interfaces = g_array_new(FALSE, FALSE, sizeof(struct ws80211_interface *));
- if (!interfaces)
- return NULL;
-
- if (ws80211_populate_devices(interfaces)) {
- ws80211_free_interfaces(interfaces);
- return NULL;
- }
- return interfaces;
-}
-
-int
-ws80211_str_to_chan_type(const gchar *s)
-{
- int ret = -1;
- if (!s)
- return -1;
-
- if (!strcmp(s, CHAN_NO_HT))
- ret = WS80211_CHAN_NO_HT;
- if (!strcmp(s, CHAN_HT20))
- ret = WS80211_CHAN_HT20;
- if (!strcmp(s, CHAN_HT40MINUS))
- ret = WS80211_CHAN_HT40MINUS;
- if (!strcmp(s, CHAN_HT40PLUS))
- ret = WS80211_CHAN_HT40PLUS;
- if (!strcmp(s, CHAN_VHT80))
- ret = WS80211_CHAN_VHT80;
- if (!strcmp(s, CHAN_VHT80P80))
- ret = WS80211_CHAN_VHT80P80;
- if (!strcmp(s, CHAN_VHT160))
- ret = WS80211_CHAN_VHT160;
-
- return ret;
-}
-
-const gchar
-*ws80211_chan_type_to_str(int type)
-{
- switch (type) {
- case WS80211_CHAN_NO_HT:
- return CHAN_NO_HT;
- case WS80211_CHAN_HT20:
- return CHAN_HT20;
- case WS80211_CHAN_HT40MINUS:
- return CHAN_HT40MINUS;
- case WS80211_CHAN_HT40PLUS:
- return CHAN_HT40PLUS;
- case WS80211_CHAN_VHT80:
- return CHAN_VHT80;
- case WS80211_CHAN_VHT80P80:
- return CHAN_VHT80P80;
- case WS80211_CHAN_VHT160:
- return CHAN_VHT160;
- }
- return NULL;
-}
-
-gboolean ws80211_has_fcs_filter(void)
-{
- return FALSE;
-}
-
-int ws80211_set_fcs_validation(const char *name _U_, enum ws80211_fcs_validation fcs_validation _U_)
-{
- return -1;
-}
-
-const char *network_manager_path = "/usr/sbin/NetworkManager"; /* Is this correct? */
-const char *ws80211_get_helper_path(void) {
- if (g_file_test(network_manager_path, G_FILE_TEST_IS_EXECUTABLE)) {
- return network_manager_path;
- }
- return NULL;
-}
-
-#elif defined(HAVE_AIRPCAP)
-
-#include <wsutil/unicode-utils.h>
-
-#include "airpcap.h"
-#include "airpcap_loader.h"
-
-int ws80211_init(void)
-{
- if (airpcap_get_dll_state() == AIRPCAP_DLL_OK) {
- return WS80211_INIT_OK;
- }
- return WS80211_INIT_NOT_SUPPORTED;
-}
-
-static const char *airpcap_dev_prefix_ = "\\\\.\\";
-
-GArray* ws80211_find_interfaces(void)
-{
- GArray *interfaces;
- GList *airpcap_if_list, *cur_if;
- int err;
- gchar *err_str = NULL;
-
- interfaces = g_array_new(FALSE, FALSE, sizeof(struct ws80211_interface *));
- if (!interfaces)
- return NULL;
-
- airpcap_if_list = get_airpcap_interface_list(&err, &err_str);
-
- if (airpcap_if_list == NULL || g_list_length(airpcap_if_list) == 0){
- g_free(err_str);
- g_array_free(interfaces, TRUE);
- return NULL;
- }
-
- for (cur_if = airpcap_if_list; cur_if; cur_if = g_list_next(cur_if)) {
- struct ws80211_interface *iface;
- airpcap_if_info_t *airpcap_if_info = (airpcap_if_info_t *) cur_if->data;
- char *ifname;
- guint32 chan;
- guint32 i;
-
- if (!airpcap_if_info) continue;
- ifname = airpcap_if_info->name;
- if (strlen(ifname) > 4 && g_str_has_prefix(ifname, airpcap_dev_prefix_)) ifname += 4;
-
- iface = (struct ws80211_interface *)g_malloc0(sizeof(*iface));
- iface->ifname = g_strdup(ifname);
- iface->can_set_freq = TRUE;
- iface->frequencies = g_array_new(FALSE, FALSE, sizeof(guint32));
-
- iface->channel_types = 1 << WS80211_CHAN_NO_HT;
- /*
- * AirPcap stores per-channel capabilities. We should probably
- * do the same. */
- for (i = 0; i < airpcap_if_info->numSupportedChannels; i++) {
- if (airpcap_if_info->pSupportedChannels[i].Flags & FLAG_CAN_BE_HIGH) {
- iface->channel_types |= 1 << WS80211_CHAN_HT40MINUS;
- iface->channel_types |= 1 << WS80211_CHAN_HT40PLUS;
- break;
- }
- }
-
- iface->cap_monitor = 1;
-
- for (chan = 0; chan < airpcap_if_info->numSupportedChannels; chan++) {
- g_array_append_val(iface->frequencies, airpcap_if_info->pSupportedChannels[chan].Frequency);
- }
-
- g_array_append_val(interfaces, iface);
- }
-
- return interfaces;
-}
-
-int ws80211_get_iface_info(const char *name, struct ws80211_iface_info *iface_info)
-{
- GList *airpcap_if_list;
- int err;
- gchar *err_str = NULL;
- airpcap_if_info_t *airpcap_if_info;
-
- if (!iface_info) return -1;
-
- airpcap_if_list = get_airpcap_interface_list(&err, &err_str);
-
- if (airpcap_if_list == NULL || g_list_length(airpcap_if_list) == 0){
- g_free(err_str);
- return -1;
- }
-
- airpcap_if_info = get_airpcap_if_from_name(airpcap_if_list, name);
-
- if (!airpcap_if_info) {
- free_airpcap_interface_list(airpcap_if_list);
- return -1;
- }
-
- memset(iface_info, 0, sizeof(*iface_info));
- iface_info->current_freq = airpcap_if_info->channelInfo.Frequency;
- switch (airpcap_if_info->channelInfo.ExtChannel) {
- case 0:
- iface_info->current_chan_type = WS80211_CHAN_NO_HT;
- break;
- case -1:
- iface_info->current_chan_type = WS80211_CHAN_HT40MINUS;
- break;
- case 1:
- iface_info->current_chan_type = WS80211_CHAN_HT40PLUS;
- break;
- default:
- return -1;
- }
-
- switch (airpcap_if_info->CrcValidationOn) {
- case AIRPCAP_VT_ACCEPT_CORRECT_FRAMES:
- iface_info->current_fcs_validation = WS80211_FCS_VALID;
- break;
- case AIRPCAP_VT_ACCEPT_CORRUPT_FRAMES:
- iface_info->current_fcs_validation = WS80211_FCS_INVALID;
- break;
- default:
- iface_info->current_fcs_validation = WS80211_FCS_ALL;
- break;
- }
-
- return 0;
-}
-
-int ws80211_set_freq(const char *name, guint32 freq, int chan_type, guint32 _U_ center_freq, guint32 _U_ center_freq2)
-{
- GList *airpcap_if_list;
- int err;
- gchar *err_str = NULL;
- airpcap_if_info_t *airpcap_if_info;
- gchar err_buf[AIRPCAP_ERRBUF_SIZE];
- PAirpcapHandle adapter;
- int ret_val = -1;
-
- airpcap_if_list = get_airpcap_interface_list(&err, &err_str);
-
- if (airpcap_if_list == NULL || g_list_length(airpcap_if_list) == 0){
- g_free(err_str);
- return ret_val;
- }
-
- airpcap_if_info = get_airpcap_if_from_name(airpcap_if_list, name);
-
- if (!airpcap_if_info) {
- free_airpcap_interface_list(airpcap_if_list);
- return ret_val;
- }
-
- adapter = airpcap_if_open(airpcap_if_info->name, err_buf);
- if (adapter) {
- airpcap_if_info->channelInfo.Frequency = freq;
- switch (chan_type) {
- case WS80211_CHAN_HT40MINUS:
- airpcap_if_info->channelInfo.ExtChannel = -1;
- break;
- case WS80211_CHAN_HT40PLUS:
- airpcap_if_info->channelInfo.ExtChannel = 1;
- break;
- default:
- airpcap_if_info->channelInfo.ExtChannel = 0;
- break;
- }
-
- if (airpcap_if_set_device_channel_ex(adapter, airpcap_if_info->channelInfo)) {
- ret_val = 0;
- }
- airpcap_if_close(adapter);
- }
-
- free_airpcap_interface_list(airpcap_if_list);
- return ret_val;
-}
-
-int ws80211_str_to_chan_type(const gchar *s _U_)
-{
- return -1;
-}
-
-const gchar *ws80211_chan_type_to_str(int type _U_)
-{
- return NULL;
-}
-
-gboolean ws80211_has_fcs_filter(void)
-{
- return TRUE;
-}
-
-int ws80211_set_fcs_validation(const char *name, enum ws80211_fcs_validation fcs_validation)
-{
- GList *airpcap_if_list;
- int err;
- gchar *err_str = NULL;
- airpcap_if_info_t *airpcap_if_info;
- gchar err_buf[AIRPCAP_ERRBUF_SIZE];
- PAirpcapHandle adapter;
- int ret_val = -1;
-
- airpcap_if_list = get_airpcap_interface_list(&err, &err_str);
-
- if (airpcap_if_list == NULL || g_list_length(airpcap_if_list) == 0){
- g_free(err_str);
- return ret_val;
- }
-
- airpcap_if_info = get_airpcap_if_from_name(airpcap_if_list, name);
-
- if (!airpcap_if_info) {
- free_airpcap_interface_list(airpcap_if_list);
- return ret_val;
- }
-
- adapter = airpcap_if_open(airpcap_if_info->name, err_buf);
- if (adapter) {
- AirpcapValidationType val_type = AIRPCAP_VT_ACCEPT_EVERYTHING;
- switch (fcs_validation) {
- case WS80211_FCS_VALID:
- val_type = AIRPCAP_VT_ACCEPT_CORRECT_FRAMES;
- break;
- case WS80211_FCS_INVALID:
- val_type = AIRPCAP_VT_ACCEPT_CORRUPT_FRAMES;
- break;
- default:
- break;
- }
-
- if (airpcap_if_set_fcs_validation(adapter, val_type)) {
- /* Appears to be necessary for this to take effect. */
- airpcap_if_store_cur_config_as_adapter_default(adapter);
- ret_val = 0;
- }
- airpcap_if_close(adapter);
- }
-
- free_airpcap_interface_list(airpcap_if_list);
- return ret_val;
-}
-
-static char *airpcap_conf_path = NULL;
-const char *ws80211_get_helper_path(void)
-{
- HKEY h_key = NULL;
-
- if (!airpcap_conf_path && RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T("SOFTWARE\\AirPcap"), 0, KEY_QUERY_VALUE|KEY_WOW64_32KEY, &h_key) == ERROR_SUCCESS) {
- DWORD reg_ret;
- TCHAR airpcap_dir_utf16[MAX_PATH];
- DWORD ad_size = sizeof(airpcap_dir_utf16)/sizeof(TCHAR);
-
- reg_ret = RegQueryValueEx(h_key, NULL, NULL, NULL,
- (LPBYTE) &airpcap_dir_utf16, &ad_size);
-
- if (reg_ret == ERROR_SUCCESS) {
- airpcap_dir_utf16[ad_size-1] = L'\0';
- g_free(airpcap_conf_path);
- airpcap_conf_path = g_strdup_printf("%s\\AirpcapConf.exe", utf_16to8(airpcap_dir_utf16));
-
- if (!g_file_test(airpcap_conf_path, G_FILE_TEST_IS_EXECUTABLE)) {
- g_free(airpcap_conf_path);
- airpcap_conf_path = NULL;
- }
- }
- }
-
- return airpcap_conf_path;
-}
-
-#else /* Everyone else. */
-int ws80211_init(void)
-{
- return WS80211_INIT_NOT_SUPPORTED;
-}
-
-GArray* ws80211_find_interfaces(void)
-{
- return NULL;
-}
-
-int ws80211_get_iface_info(const char *name _U_, struct ws80211_iface_info *iface_info _U_)
-{
- return -1;
-}
-
-int ws80211_set_freq(const char *name _U_, guint32 freq _U_, int _U_ chan_type, guint32 _U_ center_freq, guint32 _U_ center_freq2)
-{
- return -1;
-}
-
-int ws80211_str_to_chan_type(const gchar *s _U_)
-{
- return -1;
-}
-
-const gchar *ws80211_chan_type_to_str(int type _U_)
-{
- return NULL;
-}
-
-gboolean ws80211_has_fcs_filter(void)
-{
- return FALSE;
-}
-
-int ws80211_set_fcs_validation(const char *name _U_, enum ws80211_fcs_validation fcs_validation _U_)
-{
- return -1;
-}
-
-const char *ws80211_get_helper_path(void) {
- return NULL;
-}
-
-#endif /* HAVE_LIBNL && HAVE_NL80211 */
-
-/* Common to everyone */
-
-void ws80211_free_interfaces(GArray *interfaces)
-{
- struct ws80211_interface *iface;
-
- if (!interfaces)
- return;
-
- while (interfaces->len) {
- iface = g_array_index(interfaces, struct ws80211_interface *, 0);
- g_array_remove_index(interfaces, 0);
- g_array_free(iface->frequencies, TRUE);
- g_free(iface->ifname);
- g_free(iface);
- }
- g_array_free(interfaces, TRUE);
-}
-
-/*
- * Editor modelines - https://www.wireshark.org/tools/modelines.html
- *
- * Local variables:
- * c-basic-offset: 8
- * tab-width: 8
- * indent-tabs-mode: t
- * End:
- *
- * vi: set shiftwidth=8 tabstop=8 noexpandtab:
- * :indentSize=8:tabSize=8:noTabs=false:
- */