make neigh detection more stable and remove wifi handling

Signed-off-by: John Crispin <john@phrozen.org>
This commit is contained in:
John Crispin
2021-02-01 14:32:11 +01:00
parent d93583f7c8
commit 5ca087499e
6 changed files with 1 additions and 592 deletions

View File

@@ -6,7 +6,7 @@ ADD_DEFINITIONS(-Os -ggdb -Wall -Werror --std=gnu99 -Wmissing-declarations)
SET(LIBS ubox ubus json-c blobmsg_json uci nl-tiny)
ADD_EXECUTABLE(udevmand main.c mac.c neigh.c ubus.c nl80211.c blob.c netlink.c bridge.c dhcp.c netifd.c ethers.c netdev.c)
ADD_EXECUTABLE(udevmand main.c mac.c neigh.c ubus.c blob.c netlink.c bridge.c dhcp.c netifd.c ethers.c netdev.c)
TARGET_LINK_LIBRARIES(udevmand ${LIBS})
INSTALL(TARGETS udevmand
RUNTIME DESTINATION ${CMAKE_INSTALL_SBINDIR}

9
mac.c
View File

@@ -28,7 +28,6 @@ mac_find(uint8_t *addr)
*mac->interface = '\0';
INIT_LIST_HEAD(&mac->neigh4);
INIT_LIST_HEAD(&mac->neigh6);
INIT_LIST_HEAD(&mac->wifi);
INIT_LIST_HEAD(&mac->dhcpv4);
INIT_LIST_HEAD(&mac->bridge_mac);
@@ -88,14 +87,6 @@ mac_dump(struct mac *mac, int interface)
blobmsg_close_array(&b, d);
}
if (!list_empty(&mac->wifi)) {
struct wifi_station *sta;
sta = list_first_entry(&mac->wifi, struct wifi_station, mac);
blobmsg_add_field(&b, BLOBMSG_TYPE_TABLE, "wifi",
blobmsg_data(sta->info), blobmsg_data_len(sta->info));
}
if (!list_empty(&mac->dhcpv4)) {
struct dhcpv4 *dhcpv4;

1
main.c
View File

@@ -22,7 +22,6 @@ int main(int argc, char **argv)
ethers_init();
neigh_init();
bridge_init();
nl80211_init();
neigh_enum();
dhcp_init();
uloop_run();

View File

@@ -133,7 +133,6 @@ iface_dump(void)
blob_buf_init(&b, 0);
avl_for_each_element(&iface_tree, iface, avl) {
struct wifi_iface *wif;
struct iface_ip *ip;
void *c, *d;
@@ -166,15 +165,6 @@ iface_dump(void)
blobmsg_add_u32(&b, "collisions", iface->stats.collisions);
blobmsg_close_table(&b, d);
wif = wifi_get_interface(iface->name);
if (wif) {
static char buf[10];
blobmsg_add_field(&b, BLOBMSG_TYPE_TABLE, "wifi",
blobmsg_data(wif->info), blobmsg_data_len(wif->info));
snprintf(buf, sizeof(buf), "%d", wif->noise);
blobmsg_add_string(&b, "noise", buf);
}
bridge_dump_if(iface->name);
blobmsg_close_table(&b, c);
}

545
nl80211.c
View File

@@ -1,545 +0,0 @@
/*
* Copyright (C) 2017 John Crispin <john@phrozen.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License version 2.1
* as published by the Free Software Foundation
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include "udevmand.h"
struct family_data {
const char *group;
int id;
};
static struct nl_socket nl80211_status;
static uint8_t nl80211_arg[4096];
static struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
static struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];
static struct nla_policy stats_policy[NL80211_STA_INFO_MAX + 1] = {
[NL80211_STA_INFO_INACTIVE_TIME] = { .type = NLA_U32 },
[NL80211_STA_INFO_RX_PACKETS] = { .type = NLA_U32 },
[NL80211_STA_INFO_TX_PACKETS] = { .type = NLA_U32 },
[NL80211_STA_INFO_RX_BITRATE] = { .type = NLA_NESTED },
[NL80211_STA_INFO_TX_BITRATE] = { .type = NLA_NESTED },
[NL80211_STA_INFO_SIGNAL] = { .type = NLA_U8 },
[NL80211_STA_INFO_RX_BYTES] = { .type = NLA_U32 },
[NL80211_STA_INFO_TX_BYTES] = { .type = NLA_U32 },
[NL80211_STA_INFO_TX_RETRIES] = { .type = NLA_U32 },
[NL80211_STA_INFO_TX_FAILED] = { .type = NLA_U32 },
[NL80211_STA_INFO_T_OFFSET] = { .type = NLA_U64 },
[NL80211_STA_INFO_STA_FLAGS] =
{ .minlen = sizeof(struct nl80211_sta_flag_update) },
};
static struct nla_policy rate_policy[NL80211_RATE_INFO_MAX + 1] = {
[NL80211_RATE_INFO_BITRATE] = { .type = NLA_U16 },
[NL80211_RATE_INFO_MCS] = { .type = NLA_U8 },
[NL80211_RATE_INFO_40_MHZ_WIDTH] = { .type = NLA_FLAG },
[NL80211_RATE_INFO_SHORT_GI] = { .type = NLA_FLAG },
};
static int
avl_addrcmp(const void *k1, const void *k2, void *ptr)
{
return memcmp(k1, k2, 6);
}
static struct avl_tree wif_tree = AVL_TREE_INIT(wif_tree, avl_strcmp, false, NULL);
static struct avl_tree sta_tree = AVL_TREE_INIT(sta_tree, avl_addrcmp, false, NULL);
static int
nl80211_freq2channel(int freq)
{
if (freq == 2484)
return 14;
else if (freq < 2484)
return (freq - 2407) / 5;
else if (freq >= 4910 && freq <= 4980)
return (freq - 4000) / 5;
else if(freq >= 56160 + 2160 * 1 && freq <= 56160 + 2160 * 6)
return (freq - 56160) / 2160;
else
return (freq - 5000) / 5;
}
static void
nl80211_parse_rateinfo(struct nlattr **ri, char *table)
{
int mhz = 0;
void *cookie = blobmsg_open_table(&b, table);
if (ri[NL80211_RATE_INFO_BITRATE32])
blobmsg_add_u32(&b, "bitrate", nla_get_u32(ri[NL80211_RATE_INFO_BITRATE32]) * 100);
else if (ri[NL80211_RATE_INFO_BITRATE])
blobmsg_add_u16(&b, "bitrate", nla_get_u16(ri[NL80211_RATE_INFO_BITRATE]) * 100);
if (ri[NL80211_RATE_INFO_VHT_MCS]) {
blobmsg_add_u8(&b, "vht", 1);
blobmsg_add_u8(&b, "mcs", nla_get_u8(ri[NL80211_RATE_INFO_VHT_MCS]));
if (ri[NL80211_RATE_INFO_VHT_NSS])
blobmsg_add_u8(&b, "nss", nla_get_u8(ri[NL80211_RATE_INFO_VHT_NSS]));
} else if (ri[NL80211_RATE_INFO_MCS]) {
blobmsg_add_u8(&b, "ht", 1);
blobmsg_add_u8(&b, "mcs", nla_get_u8(ri[NL80211_RATE_INFO_MCS]));
}
if (ri[NL80211_RATE_INFO_5_MHZ_WIDTH])
mhz = 5;
else if (ri[NL80211_RATE_INFO_10_MHZ_WIDTH])
mhz = 10;
else if (ri[NL80211_RATE_INFO_40_MHZ_WIDTH])
mhz = 40;
else if (ri[NL80211_RATE_INFO_80_MHZ_WIDTH])
mhz = 80;
else if (ri[NL80211_RATE_INFO_80P80_MHZ_WIDTH] ||
ri[NL80211_RATE_INFO_160_MHZ_WIDTH])
mhz = 160;
else
mhz = 20;
blobmsg_add_u32(&b, "mhz", mhz);
if (ri[NL80211_RATE_INFO_SHORT_GI])
blobmsg_add_u8(&b, "short_gi", 1);
blobmsg_close_table(&b, cookie);
}
static void
nl80211_to_blob(struct nlattr **tb, char *ifname)
{
memset(sinfo, 0, sizeof(sinfo));
memset(rinfo, 0, sizeof(rinfo));
blob_buf_init(&b, 0);
if (tb[NL80211_ATTR_IFINDEX]) {
int idx = nla_get_u32(tb[NL80211_ATTR_IFINDEX]);
if (ifname)
if_indextoname(idx, ifname);
} else if (tb[NL80211_ATTR_IFNAME]) {
if (ifname)
ifname = nla_get_string(tb[NL80211_ATTR_IFNAME]);
}
if (tb[NL80211_ATTR_WIPHY])
blobmsg_add_u32(&b, "phy", nla_get_u32(tb[NL80211_ATTR_WIPHY]));
if (tb[NL80211_ATTR_SSID])
blobmsg_add_string(&b, "ssid", nla_get_string(tb[NL80211_ATTR_SSID]));
if (tb[NL80211_ATTR_IFTYPE])
blobmsg_add_iftype(&b, "iftype", nla_get_u32(tb[NL80211_ATTR_IFTYPE]));
if (tb[NL80211_ATTR_WIPHY_TX_POWER_LEVEL])
blobmsg_add_u32(&b, "txpower", nla_get_u32(tb[NL80211_ATTR_WIPHY_TX_POWER_LEVEL]) / 100);
if (tb[NL80211_ATTR_WIPHY_FREQ]) {
blobmsg_add_u32(&b, "frequency", nla_get_u32(tb[NL80211_ATTR_WIPHY_FREQ]));
blobmsg_add_u32(&b, "channel", nl80211_freq2channel(nla_get_u32(tb[NL80211_ATTR_WIPHY_FREQ])));
}
if (tb[NL80211_ATTR_CENTER_FREQ1])
blobmsg_add_u32(&b, "center_freq1", nla_get_u32(tb[NL80211_ATTR_CENTER_FREQ1]));
if (tb[NL80211_ATTR_CENTER_FREQ2])
blobmsg_add_u32(&b, "center_freq2", nla_get_u32(tb[NL80211_ATTR_CENTER_FREQ2]));
if (tb[NL80211_ATTR_CHANNEL_WIDTH])
switch(nla_get_u32(tb[NL80211_ATTR_CHANNEL_WIDTH])) {
case NL80211_CHAN_WIDTH_20:
blobmsg_add_string(&b, "channel_width", "20");
break;
case NL80211_CHAN_WIDTH_40:
blobmsg_add_string(&b, "channel_width", "40");
break;
case NL80211_CHAN_WIDTH_80:
blobmsg_add_string(&b, "channel_width", "80");
break;
case NL80211_CHAN_WIDTH_80P80:
blobmsg_add_string(&b, "channel_width", "80p80");
break;
case NL80211_CHAN_WIDTH_160:
blobmsg_add_string(&b, "channel_width", "160");
break;
}
if (tb[NL80211_ATTR_WIPHY_CHANNEL_TYPE])
blobmsg_add_u32(&b, "channel_type", nla_get_u32(tb[NL80211_ATTR_WIPHY_CHANNEL_TYPE]));
if (tb[NL80211_ATTR_STA_INFO] != NULL &&
!nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,
tb[NL80211_ATTR_STA_INFO], stats_policy))
{
if (sinfo[NL80211_STA_INFO_SIGNAL])
blobmsg_add_u32(&b, "signal", (signed char)nla_get_u8(sinfo[NL80211_STA_INFO_SIGNAL]));
if (sinfo[NL80211_STA_INFO_INACTIVE_TIME])
blobmsg_add_u32(&b, "inactive", nla_get_u32(sinfo[NL80211_STA_INFO_INACTIVE_TIME]));
if (sinfo[NL80211_STA_INFO_RX_PACKETS])
blobmsg_add_u32(&b, "rx_pkt", nla_get_u32(sinfo[NL80211_STA_INFO_RX_PACKETS]));
if (sinfo[NL80211_STA_INFO_TX_PACKETS])
blobmsg_add_u32(&b, "tx_pkt", nla_get_u32(sinfo[NL80211_STA_INFO_TX_PACKETS]));
if (sinfo[NL80211_STA_INFO_RX_BITRATE] &&
!nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_RX_BITRATE],
rate_policy))
nl80211_parse_rateinfo(rinfo, "rx_rate");
if (sinfo[NL80211_STA_INFO_TX_BITRATE] &&
!nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_TX_BITRATE],
rate_policy))
nl80211_parse_rateinfo(rinfo, "tx_rate");
if (sinfo[NL80211_STA_INFO_RX_BYTES])
blobmsg_add_u32(&b, "rx_bytes", nla_get_u32(sinfo[NL80211_STA_INFO_RX_BYTES]));
if (sinfo[NL80211_STA_INFO_TX_BYTES])
blobmsg_add_u32(&b, "tx_bytes", nla_get_u32(sinfo[NL80211_STA_INFO_TX_BYTES]));
if (sinfo[NL80211_STA_INFO_TX_RETRIES])
blobmsg_add_u32(&b, "tx_retries", nla_get_u32(sinfo[NL80211_STA_INFO_TX_RETRIES]));
if (sinfo[NL80211_STA_INFO_TX_FAILED])
blobmsg_add_u32(&b, "tx_failed", nla_get_u32(sinfo[NL80211_STA_INFO_TX_FAILED]));
if (sinfo[NL80211_STA_INFO_T_OFFSET])
blobmsg_add_u32(&b, "tx_offset", nla_get_u32(sinfo[NL80211_STA_INFO_T_OFFSET]));
}
if (tb[NL80211_ATTR_REG_ALPHA2])
blobmsg_add_string(&b, "country", nla_get_string(tb[NL80211_ATTR_REG_ALPHA2]));
if (tb[NL80211_ATTR_DFS_REGION])
blobmsg_add_u16(&b, "dfs-region", nla_get_u8(tb[NL80211_ATTR_DFS_REGION]));
}
static void
nl80211_list_wif(void)
{
struct nl_msg *msg;
msg = nlmsg_alloc();
if (!msg)
return;
if (!genlmsg_put(msg, 0, 0, genl_ctrl_resolve(nl80211_status.sock, "nl80211"),
0, NLM_F_DUMP, NL80211_CMD_GET_INTERFACE, 0)) {
nlmsg_free(msg);
return;
}
genl_send_and_recv(&nl80211_status, msg);
}
static void
nl80211_assoc_list(struct uloop_timeout *t)
{
struct wifi_iface *wif = container_of(t, struct wifi_iface, assoc);
struct nl_msg *msg;
int idx = if_nametoindex(wif->ifname);
msg = nlmsg_alloc();
if (!msg)
goto out;
if (!genlmsg_put(msg, 0, 0, genl_ctrl_resolve(nl80211_status.sock, "nl80211"),
0, NLM_F_DUMP, NL80211_CMD_GET_STATION, 0) ||
nla_put_u32(msg, NL80211_ATTR_IFINDEX, idx)) {
nlmsg_free(msg);
goto out;
}
genl_send_and_recv(&nl80211_status, msg);
msg = nlmsg_alloc();
if (!msg)
goto out;
if (!genlmsg_put(msg, 0, 0, genl_ctrl_resolve(nl80211_status.sock, "nl80211"),
0, NLM_F_DUMP, NL80211_CMD_GET_SURVEY, 0) ||
nla_put_u32(msg, NL80211_ATTR_IFINDEX, idx)) {
nlmsg_free(msg);
goto out;
}
genl_send_and_recv(&nl80211_status, msg);
out:
uloop_timeout_set(t, 30 * 1000);
}
static void
nl80211_add_station(struct nlattr **tb, char *ifname)
{
struct wifi_station *sta;
struct mac *mac;
uint8_t *addr;
if (tb[NL80211_ATTR_MAC] == NULL)
return;
nl80211_to_blob(tb, ifname);
addr = nla_data(tb[NL80211_ATTR_MAC]);
mac = mac_find(addr);
sta = avl_find_element(&sta_tree, addr, sta, avl);
if (!sta) {
struct wifi_iface *wif;
wif = avl_find_element(&wif_tree, ifname, wif, avl);
if (!wif)
return;
sta = malloc(sizeof(*sta));
if (!sta)
return;
memset(sta, 0, sizeof(*sta));
memcpy(sta->addr, addr, 6);
sta->avl.key = sta->addr;
sta->wif = wif;
sta->info = NULL;
avl_insert(&sta_tree, &sta->avl);
list_add(&sta->mac, &mac->wifi);
list_add(&sta->iface, &wif->stas);
ULOG_INFO("new station %s "MAC_FMT"\n", ifname, MAC_VAR(sta->addr));
}
if (sta->info)
free(sta->info);
sta->info = malloc(blob_pad_len(b.head));
memcpy(sta->info, b.head, blob_pad_len(b.head));
}
static void
nl80211_del_station(struct wifi_station *sta, char *ifname)
{
ULOG_INFO("del station %s "MAC_FMT"\n", ifname, MAC_VAR(sta->addr));
list_del(&sta->mac);
list_del(&sta->iface);
avl_delete(&sta_tree, &sta->avl);
free(sta);
}
static void
_nl80211_del_station(struct nlattr **tb, char *ifname)
{
struct wifi_station *sta;
uint8_t *addr;
if (tb[NL80211_ATTR_MAC] == NULL)
return;
addr = nla_data(tb[NL80211_ATTR_MAC]);
sta = avl_find_element(&sta_tree, addr, sta, avl);
if (!sta)
return;
nl80211_del_station(sta, ifname);
}
struct wifi_iface*
wifi_get_interface(char *ifname)
{
struct wifi_iface *wif;
return avl_find_element(&wif_tree, ifname, wif, avl);
}
static void
nl80211_add_iface(struct nlattr **tb, char *ifname)
{
struct wifi_iface *wif;
uint8_t *addr;
if (tb[NL80211_ATTR_MAC] == NULL)
return;
addr = nla_data(tb[NL80211_ATTR_MAC]);
wif = avl_find_element(&wif_tree, ifname, wif, avl);
if (!wif) {
wif = malloc(sizeof(*wif));
if (!wif)
return;
memset(wif, 0, sizeof(*wif));
memcpy(wif->addr, addr, 6);
strncpy(wif->ifname, ifname, IF_NAMESIZE);
wif->avl.key = wif->ifname;
wif->assoc.cb = nl80211_assoc_list;
wif->info = NULL;
INIT_LIST_HEAD(&wif->stas);
nl80211_assoc_list(&wif->assoc);
avl_insert(&wif_tree, &wif->avl);
ULOG_INFO("new wifi %s "MAC_FMT"\n", wif->ifname, MAC_VAR(wif->addr));
nl80211_to_blob(tb, NULL);
memcpy(wif->addr, addr, 6);
}
if (wif->info)
free(wif->info);
wif->info = malloc(blob_pad_len(b.head));
memcpy(wif->info, b.head, blob_pad_len(b.head));
}
static void
nl80211_del_iface(struct nlattr **tb, char *ifname)
{
struct wifi_station *sta, *tmp;
struct wifi_iface *wif;
wif = avl_find_element(&wif_tree, ifname, wif, avl);
if (!wif)
return;
list_for_each_entry_safe(sta, tmp, &wif->stas, iface)
nl80211_del_station(sta, wif->ifname);
ULOG_INFO("del wifi %s "MAC_FMT"\n", wif->ifname, MAC_VAR(wif->addr));
avl_delete(&wif_tree, &wif->avl);
uloop_timeout_cancel(&wif->assoc);
free(wif);
}
static int
nl80211_get_noise_cb(struct nlattr **tb, char *ifname)
{
struct nlattr *si[NL80211_SURVEY_INFO_MAX + 1];
struct wifi_iface *wif;
static struct nla_policy sp[NL80211_SURVEY_INFO_MAX + 1] = {
[NL80211_SURVEY_INFO_FREQUENCY] = { .type = NLA_U32 },
[NL80211_SURVEY_INFO_NOISE] = { .type = NLA_U8 },
};
wif = avl_find_element(&wif_tree, ifname, wif, avl);
if (!wif)
return NL_SKIP;
if (!tb[NL80211_ATTR_SURVEY_INFO])
return NL_SKIP;
if (nla_parse_nested(si, NL80211_SURVEY_INFO_MAX,
tb[NL80211_ATTR_SURVEY_INFO], sp))
return NL_SKIP;
if (!si[NL80211_SURVEY_INFO_NOISE])
return NL_SKIP;
wif->noise = 0;
if (si[NL80211_SURVEY_INFO_IN_USE])
wif->noise = (int8_t)nla_get_u8(si[NL80211_SURVEY_INFO_NOISE]);
return NL_SKIP;
}
static int
nl80211_mcast_grp(struct nlattr **tb, struct family_data *res)
{
struct nlattr *mcgrp;
int i;
nla_for_each_nested(mcgrp, tb[CTRL_ATTR_MCAST_GROUPS], i) {
struct nlattr *tb2[CTRL_ATTR_MCAST_GRP_MAX + 1];
nla_parse(tb2, CTRL_ATTR_MCAST_GRP_MAX, nla_data(mcgrp),
nla_len(mcgrp), NULL);
if (!tb2[CTRL_ATTR_MCAST_GRP_NAME] ||
!tb2[CTRL_ATTR_MCAST_GRP_ID] ||
strncmp(nla_data(tb2[CTRL_ATTR_MCAST_GRP_NAME]), res->group, nla_len(tb2[CTRL_ATTR_MCAST_GRP_NAME])) != 0)
continue;
res->id = nla_get_u32(tb2[CTRL_ATTR_MCAST_GRP_ID]);
break;
}
return NL_SKIP;
}
static int
cb_nl80211_status(struct nl_msg *msg, void *arg)
{
struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
struct nlattr *tb[NL80211_ATTR_MAX + 1];
char ifname[IFNAMSIZ] = {};
int ifidx = -1;
nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
genlmsg_attrlen(gnlh, 0), NULL);
if (tb[CTRL_ATTR_MCAST_GROUPS]) {
return nl80211_mcast_grp(tb, arg);
} else if (tb[NL80211_ATTR_IFINDEX]) {
ifidx = nla_get_u32(tb[NL80211_ATTR_IFINDEX]);
if_indextoname(ifidx, ifname);
} else if (tb[NL80211_ATTR_IFNAME]) {
strncpy(ifname, nla_get_string(tb[NL80211_ATTR_IFNAME]), IFNAMSIZ);
} else
return 0;
switch (gnlh->cmd) {
case NL80211_CMD_NEW_STATION:
nl80211_add_station(tb, ifname);
break;
case NL80211_CMD_DEL_STATION:
_nl80211_del_station(tb, ifname);
break;
case NL80211_CMD_NEW_INTERFACE:
nl80211_add_iface(tb, ifname);
break;
case NL80211_CMD_DEL_INTERFACE:
nl80211_del_iface(tb, ifname);
break;
case NL80211_CMD_NEW_SURVEY_RESULTS:
nl80211_get_noise_cb(tb, ifname);
break;
default:
break;
}
return 0;
}
static int
genl_get_multicast_id(struct nl_socket *ev,
const char *family, const char *group)
{
struct nl_msg *msg;
struct family_data *genl_res = (struct family_data *) &nl80211_arg;
genl_res->group = group;
genl_res->id = -ENOENT;
msg = nlmsg_alloc();
if (!msg)
return -ENOMEM;
if (!genlmsg_put(msg, 0, 0, genl_ctrl_resolve(ev->sock, "nlctrl"),
0, 0, CTRL_CMD_GETFAMILY, 0) ||
nla_put_string(msg, CTRL_ATTR_FAMILY_NAME, family)) {
nlmsg_free(msg);
return -1;
}
genl_send_and_recv(ev, msg);
return genl_res->id;
}
int nl80211_init(void)
{
int id;
if (!nl_status_socket(&nl80211_status, NETLINK_GENERIC, cb_nl80211_status, &nl80211_arg))
return -1;
id = genl_get_multicast_id(&nl80211_status, "nl80211", "config");
if (id >= 0)
nl_socket_add_membership(nl80211_status.sock, id);
id = genl_get_multicast_id(&nl80211_status, "nl80211", "mlme");
if (id >= 0)
nl_socket_add_membership(nl80211_status.sock, id);
id = genl_get_multicast_id(&nl80211_status, "nl80211", "vendor");
if (id >= 0)
nl_socket_add_membership(nl80211_status.sock, id);
nl80211_list_wif();
return 0;
}

View File

@@ -57,7 +57,6 @@ struct mac {
struct timespec ts;
struct list_head neigh4;
struct list_head neigh6;
struct list_head wifi;
struct list_head dhcpv4;
struct list_head bridge_mac;
};
@@ -74,29 +73,6 @@ struct neigh {
struct uloop_timeout ageing;
};
struct wifi_iface {
struct avl_node avl;
uint8_t addr[6];
struct blob_attr *info;
int noise;
char ifname[IF_NAMESIZE];
struct list_head stas;
struct uloop_timeout assoc;
};
struct wifi_station {
struct avl_node avl;
uint8_t addr[6];
struct blob_attr *info;
struct wifi_iface *wif;
struct list_head mac;
struct list_head iface;
};
struct dhcpv4 {
struct avl_node avl;
struct list_head mac;
@@ -167,5 +143,3 @@ extern char *interface_resolve(char *device);
extern void ethers_init(void);
extern void iface_dump(void);
extern struct wifi_iface *wifi_get_interface(char *name);