mirror of
https://github.com/morgan9e/systemd
synced 2026-04-14 08:25:20 +09:00
Merge pull request #20802 from yuwata/network-receive-nl80211-multicast-messages
network: receive nl80211 multicast messages
This commit is contained in:
@@ -1185,6 +1185,21 @@
|
||||
* passed using %NL80211_ATTR_SAR_SPEC. %NL80211_ATTR_WIPHY is used to
|
||||
* specify the wiphy index to be applied to.
|
||||
*
|
||||
* @NL80211_CMD_OBSS_COLOR_COLLISION: This notification is sent out whenever
|
||||
* mac80211/drv detects a bss color collision.
|
||||
*
|
||||
* @NL80211_CMD_COLOR_CHANGE_REQUEST: This command is used to indicate that
|
||||
* userspace wants to change the BSS color.
|
||||
*
|
||||
* @NL80211_CMD_COLOR_CHANGE_STARTED: Notify userland, that a color change has
|
||||
* started
|
||||
*
|
||||
* @NL80211_CMD_COLOR_CHANGE_ABORTED: Notify userland, that the color change has
|
||||
* been aborted
|
||||
*
|
||||
* @NL80211_CMD_COLOR_CHANGE_COMPLETED: Notify userland that the color change
|
||||
* has completed
|
||||
*
|
||||
* @NL80211_CMD_MAX: highest used command number
|
||||
* @__NL80211_CMD_AFTER_LAST: internal use
|
||||
*/
|
||||
@@ -1417,6 +1432,14 @@ enum nl80211_commands {
|
||||
|
||||
NL80211_CMD_SET_SAR_SPECS,
|
||||
|
||||
NL80211_CMD_OBSS_COLOR_COLLISION,
|
||||
|
||||
NL80211_CMD_COLOR_CHANGE_REQUEST,
|
||||
|
||||
NL80211_CMD_COLOR_CHANGE_STARTED,
|
||||
NL80211_CMD_COLOR_CHANGE_ABORTED,
|
||||
NL80211_CMD_COLOR_CHANGE_COMPLETED,
|
||||
|
||||
/* add new commands above here */
|
||||
|
||||
/* used to define NL80211_CMD_MAX below */
|
||||
@@ -2560,6 +2583,16 @@ enum nl80211_commands {
|
||||
* disassoc events to indicate that an immediate reconnect to the AP
|
||||
* is desired.
|
||||
*
|
||||
* @NL80211_ATTR_OBSS_COLOR_BITMAP: bitmap of the u64 BSS colors for the
|
||||
* %NL80211_CMD_OBSS_COLOR_COLLISION event.
|
||||
*
|
||||
* @NL80211_ATTR_COLOR_CHANGE_COUNT: u8 attribute specifying the number of TBTT's
|
||||
* until the color switch event.
|
||||
* @NL80211_ATTR_COLOR_CHANGE_COLOR: u8 attribute specifying the color that we are
|
||||
* switching to
|
||||
* @NL80211_ATTR_COLOR_CHANGE_ELEMS: Nested set of attributes containing the IE
|
||||
* information for the time while performing a color switch.
|
||||
*
|
||||
* @NUM_NL80211_ATTR: total number of nl80211_attrs available
|
||||
* @NL80211_ATTR_MAX: highest attribute number currently defined
|
||||
* @__NL80211_ATTR_AFTER_LAST: internal use
|
||||
@@ -3057,6 +3090,12 @@ enum nl80211_attrs {
|
||||
|
||||
NL80211_ATTR_DISABLE_HE,
|
||||
|
||||
NL80211_ATTR_OBSS_COLOR_BITMAP,
|
||||
|
||||
NL80211_ATTR_COLOR_CHANGE_COUNT,
|
||||
NL80211_ATTR_COLOR_CHANGE_COLOR,
|
||||
NL80211_ATTR_COLOR_CHANGE_ELEMS,
|
||||
|
||||
/* add attributes here, update the policy in nl80211.c */
|
||||
|
||||
__NL80211_ATTR_AFTER_LAST,
|
||||
@@ -5953,6 +5992,9 @@ enum nl80211_feature_flags {
|
||||
* frame protection for all management frames exchanged during the
|
||||
* negotiation and range measurement procedure.
|
||||
*
|
||||
* @NL80211_EXT_FEATURE_BSS_COLOR: The driver supports BSS color collision
|
||||
* detection and change announcemnts.
|
||||
*
|
||||
* @NUM_NL80211_EXT_FEATURES: number of extended features.
|
||||
* @MAX_NL80211_EXT_FEATURES: highest extended feature index.
|
||||
*/
|
||||
@@ -6017,6 +6059,7 @@ enum nl80211_ext_feature_index {
|
||||
NL80211_EXT_FEATURE_SECURE_LTF,
|
||||
NL80211_EXT_FEATURE_SECURE_RTT,
|
||||
NL80211_EXT_FEATURE_PROT_RANGE_NEGO_AND_MEASURE,
|
||||
NL80211_EXT_FEATURE_BSS_COLOR,
|
||||
|
||||
/* add new features before the definition below */
|
||||
NUM_NL80211_EXT_FEATURES,
|
||||
|
||||
@@ -44,3 +44,8 @@
|
||||
#ifndef BOND_MAX_ARP_TARGETS
|
||||
#define BOND_MAX_ARP_TARGETS 16
|
||||
#endif
|
||||
|
||||
/* Not exposed but defined in include/linux/ieee80211.h */
|
||||
#ifndef IEEE80211_MAX_SSID_LEN
|
||||
#define IEEE80211_MAX_SSID_LEN 32
|
||||
#endif
|
||||
|
||||
@@ -53,6 +53,42 @@ void genl_clear_family(sd_netlink *nl) {
|
||||
nl->genl_family_by_id = hashmap_free_with_destructor(nl->genl_family_by_id, genl_family_free);
|
||||
}
|
||||
|
||||
static int genl_family_new_unsupported(
|
||||
sd_netlink *nl,
|
||||
const char *family_name,
|
||||
const NLTypeSystem *type_system) {
|
||||
|
||||
_cleanup_(genl_family_freep) GenericNetlinkFamily *f = NULL;
|
||||
int r;
|
||||
|
||||
assert(nl);
|
||||
assert(family_name);
|
||||
assert(type_system);
|
||||
|
||||
/* Kernel does not support the genl family? To prevent from resolving the family name again,
|
||||
* let's store the family with zero id to indicate that. */
|
||||
|
||||
f = new(GenericNetlinkFamily, 1);
|
||||
if (!f)
|
||||
return -ENOMEM;
|
||||
|
||||
*f = (GenericNetlinkFamily) {
|
||||
.type_system = type_system,
|
||||
};
|
||||
|
||||
f->name = strdup(family_name);
|
||||
if (!f->name)
|
||||
return -ENOMEM;
|
||||
|
||||
r = hashmap_ensure_put(&nl->genl_family_by_name, &string_hash_ops, f->name, f);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
f->genl = nl;
|
||||
TAKE_PTR(f);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int genl_family_new(
|
||||
sd_netlink *nl,
|
||||
const char *expected_family_name,
|
||||
@@ -79,28 +115,6 @@ static int genl_family_new(
|
||||
.type_system = type_system,
|
||||
};
|
||||
|
||||
if (sd_netlink_message_is_error(message)) {
|
||||
int e;
|
||||
|
||||
/* Kernel does not support the genl family? To prevent from resolving the family name
|
||||
* again, let's store the family with zero id to indicate that. */
|
||||
|
||||
e = sd_netlink_message_get_errno(message);
|
||||
if (e >= 0) /* Huh? */
|
||||
e = -EOPNOTSUPP;
|
||||
|
||||
f->name = strdup(expected_family_name);
|
||||
if (!f->name)
|
||||
return e;
|
||||
|
||||
if (hashmap_ensure_put(&nl->genl_family_by_name, &string_hash_ops, f->name, f) < 0)
|
||||
return e;
|
||||
|
||||
f->genl = nl;
|
||||
TAKE_PTR(f);
|
||||
return e;
|
||||
}
|
||||
|
||||
r = sd_genl_message_get_family_name(nl, message, &family_name);
|
||||
if (r < 0)
|
||||
return r;
|
||||
@@ -261,9 +275,10 @@ static int genl_family_get_by_name_internal(
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = sd_netlink_call(nl, req, 0, &reply);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (sd_netlink_call(nl, req, 0, &reply) < 0) {
|
||||
(void) genl_family_new_unsupported(nl, name, type_system);
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
return genl_family_new(nl, name, type_system, reply, ret);
|
||||
}
|
||||
|
||||
@@ -123,8 +123,8 @@ struct sd_netlink_message {
|
||||
struct nlmsghdr *hdr;
|
||||
struct netlink_container containers[NETLINK_CONTAINER_DEPTH];
|
||||
unsigned n_containers; /* number of containers */
|
||||
uint32_t multicast_group;
|
||||
bool sealed:1;
|
||||
bool broadcast:1;
|
||||
|
||||
sd_netlink_message *next; /* next in a chain of multi-part messages */
|
||||
};
|
||||
|
||||
@@ -116,8 +116,8 @@ int message_new_synthetic_error(sd_netlink *nl, int error, uint32_t serial, sd_n
|
||||
int sd_netlink_message_request_dump(sd_netlink_message *m, int dump) {
|
||||
assert_return(m, -EINVAL);
|
||||
assert_return(m->hdr, -EINVAL);
|
||||
|
||||
assert_return(IN_SET(m->hdr->nlmsg_type,
|
||||
assert_return(m->protocol != NETLINK_ROUTE ||
|
||||
IN_SET(m->hdr->nlmsg_type,
|
||||
RTM_GETLINK, RTM_GETLINKPROP, RTM_GETADDR, RTM_GETROUTE, RTM_GETNEIGH,
|
||||
RTM_GETRULE, RTM_GETADDRLABEL, RTM_GETNEXTHOP), -EINVAL);
|
||||
|
||||
@@ -166,7 +166,7 @@ int sd_netlink_message_set_flags(sd_netlink_message *m, uint16_t flags) {
|
||||
int sd_netlink_message_is_broadcast(sd_netlink_message *m) {
|
||||
assert_return(m, -EINVAL);
|
||||
|
||||
return m->broadcast;
|
||||
return m->multicast_group != 0;
|
||||
}
|
||||
|
||||
/* If successful the updated message will be correctly aligned, if
|
||||
@@ -751,7 +751,7 @@ int sd_netlink_message_read(sd_netlink_message *m, unsigned short type, size_t s
|
||||
}
|
||||
|
||||
int sd_netlink_message_read_data(sd_netlink_message *m, unsigned short type, size_t *ret_size, void **ret_data) {
|
||||
void *attr_data, *data;
|
||||
void *attr_data;
|
||||
int r;
|
||||
|
||||
assert_return(m, -EINVAL);
|
||||
@@ -761,6 +761,8 @@ int sd_netlink_message_read_data(sd_netlink_message *m, unsigned short type, siz
|
||||
return r;
|
||||
|
||||
if (ret_data) {
|
||||
void *data;
|
||||
|
||||
data = memdup(attr_data, r);
|
||||
if (!data)
|
||||
return -ENOMEM;
|
||||
@@ -774,9 +776,34 @@ int sd_netlink_message_read_data(sd_netlink_message *m, unsigned short type, siz
|
||||
return r;
|
||||
}
|
||||
|
||||
int sd_netlink_message_read_data_suffix0(sd_netlink_message *m, unsigned short type, size_t *ret_size, void **ret_data) {
|
||||
void *attr_data;
|
||||
int r;
|
||||
|
||||
assert_return(m, -EINVAL);
|
||||
|
||||
r = netlink_message_read_internal(m, type, &attr_data, NULL);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (ret_data) {
|
||||
void *data;
|
||||
|
||||
data = memdup_suffix0(attr_data, r);
|
||||
if (!data)
|
||||
return -ENOMEM;
|
||||
|
||||
*ret_data = data;
|
||||
}
|
||||
|
||||
if (ret_size)
|
||||
*ret_size = r;
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
int sd_netlink_message_read_string_strdup(sd_netlink_message *m, unsigned short type, char **data) {
|
||||
void *attr_data;
|
||||
char *str;
|
||||
int r;
|
||||
|
||||
assert_return(m, -EINVAL);
|
||||
@@ -790,6 +817,8 @@ int sd_netlink_message_read_string_strdup(sd_netlink_message *m, unsigned short
|
||||
return r;
|
||||
|
||||
if (data) {
|
||||
char *str;
|
||||
|
||||
str = strndup(attr_data, r);
|
||||
if (!str)
|
||||
return -ENOMEM;
|
||||
@@ -801,8 +830,8 @@ int sd_netlink_message_read_string_strdup(sd_netlink_message *m, unsigned short
|
||||
}
|
||||
|
||||
int sd_netlink_message_read_string(sd_netlink_message *m, unsigned short type, const char **data) {
|
||||
int r;
|
||||
void *attr_data;
|
||||
int r;
|
||||
|
||||
assert_return(m, -EINVAL);
|
||||
|
||||
@@ -813,7 +842,8 @@ int sd_netlink_message_read_string(sd_netlink_message *m, unsigned short type, c
|
||||
r = netlink_message_read_internal(m, type, &attr_data, NULL);
|
||||
if (r < 0)
|
||||
return r;
|
||||
else if (strnlen(attr_data, r) >= (size_t) r)
|
||||
|
||||
if (strnlen(attr_data, r) >= (size_t) r)
|
||||
return -EIO;
|
||||
|
||||
if (data)
|
||||
@@ -823,8 +853,8 @@ int sd_netlink_message_read_string(sd_netlink_message *m, unsigned short type, c
|
||||
}
|
||||
|
||||
int sd_netlink_message_read_u8(sd_netlink_message *m, unsigned short type, uint8_t *data) {
|
||||
int r;
|
||||
void *attr_data;
|
||||
int r;
|
||||
|
||||
assert_return(m, -EINVAL);
|
||||
|
||||
@@ -835,7 +865,8 @@ int sd_netlink_message_read_u8(sd_netlink_message *m, unsigned short type, uint8
|
||||
r = netlink_message_read_internal(m, type, &attr_data, NULL);
|
||||
if (r < 0)
|
||||
return r;
|
||||
else if ((size_t) r < sizeof(uint8_t))
|
||||
|
||||
if ((size_t) r < sizeof(uint8_t))
|
||||
return -EIO;
|
||||
|
||||
if (data)
|
||||
@@ -858,7 +889,8 @@ int sd_netlink_message_read_u16(sd_netlink_message *m, unsigned short type, uint
|
||||
r = netlink_message_read_internal(m, type, &attr_data, &net_byteorder);
|
||||
if (r < 0)
|
||||
return r;
|
||||
else if ((size_t) r < sizeof(uint16_t))
|
||||
|
||||
if ((size_t) r < sizeof(uint16_t))
|
||||
return -EIO;
|
||||
|
||||
if (data) {
|
||||
@@ -885,7 +917,8 @@ int sd_netlink_message_read_u32(sd_netlink_message *m, unsigned short type, uint
|
||||
r = netlink_message_read_internal(m, type, &attr_data, &net_byteorder);
|
||||
if (r < 0)
|
||||
return r;
|
||||
else if ((size_t) r < sizeof(uint32_t))
|
||||
|
||||
if ((size_t) r < sizeof(uint32_t))
|
||||
return -EIO;
|
||||
|
||||
if (data) {
|
||||
@@ -899,8 +932,8 @@ int sd_netlink_message_read_u32(sd_netlink_message *m, unsigned short type, uint
|
||||
}
|
||||
|
||||
int sd_netlink_message_read_ether_addr(sd_netlink_message *m, unsigned short type, struct ether_addr *data) {
|
||||
int r;
|
||||
void *attr_data;
|
||||
int r;
|
||||
|
||||
assert_return(m, -EINVAL);
|
||||
|
||||
@@ -911,7 +944,8 @@ int sd_netlink_message_read_ether_addr(sd_netlink_message *m, unsigned short typ
|
||||
r = netlink_message_read_internal(m, type, &attr_data, NULL);
|
||||
if (r < 0)
|
||||
return r;
|
||||
else if ((size_t) r < sizeof(struct ether_addr))
|
||||
|
||||
if ((size_t) r < sizeof(struct ether_addr))
|
||||
return -EIO;
|
||||
|
||||
if (data)
|
||||
@@ -921,8 +955,8 @@ int sd_netlink_message_read_ether_addr(sd_netlink_message *m, unsigned short typ
|
||||
}
|
||||
|
||||
int netlink_message_read_hw_addr(sd_netlink_message *m, unsigned short type, struct hw_addr_data *data) {
|
||||
int r;
|
||||
void *attr_data;
|
||||
int r;
|
||||
|
||||
assert_return(m, -EINVAL);
|
||||
|
||||
@@ -933,7 +967,8 @@ int netlink_message_read_hw_addr(sd_netlink_message *m, unsigned short type, str
|
||||
r = netlink_message_read_internal(m, type, &attr_data, NULL);
|
||||
if (r < 0)
|
||||
return r;
|
||||
else if (r > HW_ADDR_MAX_SIZE)
|
||||
|
||||
if (r > HW_ADDR_MAX_SIZE)
|
||||
return -EIO;
|
||||
|
||||
if (data) {
|
||||
@@ -945,8 +980,8 @@ int netlink_message_read_hw_addr(sd_netlink_message *m, unsigned short type, str
|
||||
}
|
||||
|
||||
int sd_netlink_message_read_cache_info(sd_netlink_message *m, unsigned short type, struct ifa_cacheinfo *info) {
|
||||
int r;
|
||||
void *attr_data;
|
||||
int r;
|
||||
|
||||
assert_return(m, -EINVAL);
|
||||
|
||||
@@ -957,7 +992,8 @@ int sd_netlink_message_read_cache_info(sd_netlink_message *m, unsigned short typ
|
||||
r = netlink_message_read_internal(m, type, &attr_data, NULL);
|
||||
if (r < 0)
|
||||
return r;
|
||||
else if ((size_t) r < sizeof(struct ifa_cacheinfo))
|
||||
|
||||
if ((size_t) r < sizeof(struct ifa_cacheinfo))
|
||||
return -EIO;
|
||||
|
||||
if (info)
|
||||
@@ -980,7 +1016,8 @@ int netlink_message_read_in_addr_union(sd_netlink_message *m, unsigned short typ
|
||||
r = netlink_message_read_internal(m, type, &attr_data, NULL);
|
||||
if (r < 0)
|
||||
return r;
|
||||
else if ((size_t) r < FAMILY_ADDRESS_SIZE(family))
|
||||
|
||||
if ((size_t) r < FAMILY_ADDRESS_SIZE(family))
|
||||
return -EIO;
|
||||
|
||||
if (data)
|
||||
|
||||
@@ -81,13 +81,11 @@ int socket_bind(sd_netlink *nl) {
|
||||
|
||||
addrlen = sizeof(nl->sockaddr);
|
||||
|
||||
r = bind(nl->fd, &nl->sockaddr.sa, addrlen);
|
||||
/* ignore EINVAL to allow binding an already bound socket */
|
||||
if (r < 0 && errno != EINVAL)
|
||||
if (bind(nl->fd, &nl->sockaddr.sa, addrlen) < 0 && errno != EINVAL)
|
||||
return -errno;
|
||||
|
||||
r = getsockname(nl->fd, &nl->sockaddr.sa, &addrlen);
|
||||
if (r < 0)
|
||||
if (getsockname(nl->fd, &nl->sockaddr.sa, &addrlen) < 0)
|
||||
return -errno;
|
||||
|
||||
return broadcast_groups_get(nl);
|
||||
@@ -328,7 +326,7 @@ int socket_read_message(sd_netlink *nl) {
|
||||
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
|
||||
size_t size;
|
||||
|
||||
if (!group && new_msg->nlmsg_pid != nl->sockaddr.nl.nl_pid)
|
||||
if (group == 0 && new_msg->nlmsg_pid != nl->sockaddr.nl.nl_pid)
|
||||
/* not broadcast and not for us */
|
||||
continue;
|
||||
|
||||
@@ -365,8 +363,7 @@ int socket_read_message(sd_netlink *nl) {
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
m->broadcast = !!group;
|
||||
|
||||
m->multicast_group = group;
|
||||
m->hdr = memdup(new_msg, new_msg->nlmsg_len);
|
||||
if (!m->hdr)
|
||||
return -ENOMEM;
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#include <linux/nl80211.h>
|
||||
#include <linux/wireguard.h>
|
||||
|
||||
#include "missing_network.h"
|
||||
#include "netlink-genl.h"
|
||||
#include "netlink-types-internal.h"
|
||||
|
||||
@@ -179,10 +180,15 @@ static const NLType genl_macsec_types[] = {
|
||||
|
||||
/***************** genl nl80211 type systems *****************/
|
||||
static const NLType genl_nl80211_types[] = {
|
||||
[NL80211_ATTR_IFINDEX] = { .type = NETLINK_TYPE_U32 },
|
||||
[NL80211_ATTR_MAC] = { .type = NETLINK_TYPE_ETHER_ADDR },
|
||||
[NL80211_ATTR_SSID] = { .type = NETLINK_TYPE_STRING },
|
||||
[NL80211_ATTR_IFTYPE] = { .type = NETLINK_TYPE_U32 },
|
||||
[NL80211_ATTR_WIPHY] = { .type = NETLINK_TYPE_U32 },
|
||||
[NL80211_ATTR_WIPHY_NAME] = { .type = NETLINK_TYPE_STRING },
|
||||
[NL80211_ATTR_IFINDEX] = { .type = NETLINK_TYPE_U32 },
|
||||
[NL80211_ATTR_IFNAME] = { .type = NETLINK_TYPE_STRING, .size = IFNAMSIZ-1 },
|
||||
[NL80211_ATTR_IFTYPE] = { .type = NETLINK_TYPE_U32 },
|
||||
[NL80211_ATTR_MAC] = { .type = NETLINK_TYPE_ETHER_ADDR, .size = ETH_ALEN },
|
||||
[NL80211_ATTR_SSID] = { .type = NETLINK_TYPE_BINARY, .size = IEEE80211_MAX_SSID_LEN },
|
||||
[NL80211_ATTR_STATUS_CODE] = { .type = NETLINK_TYPE_U16 },
|
||||
[NL80211_ATTR_4ADDR] = { .type = NETLINK_TYPE_U8 },
|
||||
};
|
||||
|
||||
/***************** genl wireguard type systems *****************/
|
||||
|
||||
@@ -116,6 +116,16 @@ int rtnl_log_create_error(int r);
|
||||
userdata, description); \
|
||||
})
|
||||
|
||||
#define genl_add_match(nl, ret_slot, family, group, cmd, callback, destroy_callback, userdata, description) \
|
||||
({ \
|
||||
int (*_callback_)(sd_netlink *, sd_netlink_message *, typeof(userdata)) = callback; \
|
||||
void (*_destroy_)(typeof(userdata)) = destroy_callback; \
|
||||
sd_genl_add_match(nl, ret_slot, family, group, cmd, \
|
||||
(sd_netlink_message_handler_t) _callback_, \
|
||||
(sd_netlink_destroy_t) _destroy_, \
|
||||
userdata, description); \
|
||||
})
|
||||
|
||||
int netlink_message_append_hw_addr(sd_netlink_message *m, unsigned short type, const struct hw_addr_data *data);
|
||||
int netlink_message_append_in_addr_union(sd_netlink_message *m, unsigned short type, int family, const union in_addr_union *data);
|
||||
int netlink_message_append_sockaddr_union(sd_netlink_message *m, unsigned short type, const union sockaddr_union *data);
|
||||
|
||||
@@ -81,8 +81,7 @@ int sd_netlink_new_from_fd(sd_netlink **ret, int fd) {
|
||||
|
||||
addrlen = sizeof(nl->sockaddr);
|
||||
|
||||
r = getsockname(fd, &nl->sockaddr.sa, &addrlen);
|
||||
if (r < 0)
|
||||
if (getsockname(fd, &nl->sockaddr.sa, &addrlen) < 0)
|
||||
return -errno;
|
||||
|
||||
if (nl->sockaddr.nl.nl_family != AF_NETLINK)
|
||||
@@ -446,12 +445,22 @@ static int process_match(sd_netlink *nl, sd_netlink_message *m) {
|
||||
|
||||
LIST_FOREACH(match_callbacks, c, nl->match_callbacks) {
|
||||
sd_netlink_slot *slot;
|
||||
bool found = false;
|
||||
|
||||
if (c->type != type)
|
||||
continue;
|
||||
if (c->cmd != 0 && c->cmd != cmd)
|
||||
continue;
|
||||
|
||||
for (size_t i = 0; i < c->n_groups; i++)
|
||||
if (c->groups[i] == m->multicast_group) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!found)
|
||||
continue;
|
||||
|
||||
slot = container_of(c, sd_netlink_slot, match_callback);
|
||||
|
||||
r = c->callback(nl, m, slot->userdata);
|
||||
@@ -483,15 +492,12 @@ static int process_running(sd_netlink *nl, sd_netlink_message **ret) {
|
||||
if (!m)
|
||||
goto null_message;
|
||||
|
||||
if (sd_netlink_message_is_broadcast(m)) {
|
||||
if (sd_netlink_message_is_broadcast(m))
|
||||
r = process_match(nl, m);
|
||||
if (r != 0)
|
||||
goto null_message;
|
||||
} else {
|
||||
else
|
||||
r = process_reply(nl, m);
|
||||
if (r != 0)
|
||||
goto null_message;
|
||||
}
|
||||
if (r != 0)
|
||||
goto null_message;
|
||||
|
||||
if (ret) {
|
||||
*ret = TAKE_PTR(m);
|
||||
|
||||
@@ -53,7 +53,6 @@
|
||||
#include "networkd-sriov.h"
|
||||
#include "networkd-state-file.h"
|
||||
#include "networkd-sysctl.h"
|
||||
#include "networkd-wifi.h"
|
||||
#include "set.h"
|
||||
#include "socket-util.h"
|
||||
#include "stat-util.h"
|
||||
@@ -1295,28 +1294,15 @@ static int link_reconfigure_impl(Link *link, bool force) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int link_reconfigure_handler_internal(sd_netlink *rtnl, sd_netlink_message *m, Link *link, bool force, bool update_wifi) {
|
||||
bool link_was_lower_up;
|
||||
static int link_reconfigure_handler_internal(sd_netlink *rtnl, sd_netlink_message *m, Link *link, bool force) {
|
||||
int r;
|
||||
|
||||
assert(link);
|
||||
|
||||
link_was_lower_up = link->flags & IFF_LOWER_UP;
|
||||
|
||||
r = link_getlink_handler_internal(rtnl, m, link, "Failed to update link state");
|
||||
if (r <= 0)
|
||||
return r;
|
||||
|
||||
if (update_wifi && link_was_lower_up && link->flags & IFF_LOWER_UP) {
|
||||
/* If the interface's L1 was not up, then wifi_get_info() is already called in
|
||||
* link_update_flags(). So, it is not necessary to re-call here. */
|
||||
r = wifi_get_info(link);
|
||||
if (r < 0) {
|
||||
link_enter_failed(link);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
r = link_reconfigure_impl(link, force);
|
||||
if (r < 0) {
|
||||
link_enter_failed(link);
|
||||
@@ -1327,11 +1313,11 @@ static int link_reconfigure_handler_internal(sd_netlink *rtnl, sd_netlink_messag
|
||||
}
|
||||
|
||||
static int link_reconfigure_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
|
||||
return link_reconfigure_handler_internal(rtnl, m, link, /* force = */ false, /* update_wifi = */ false);
|
||||
return link_reconfigure_handler_internal(rtnl, m, link, /* force = */ false);
|
||||
}
|
||||
|
||||
static int link_force_reconfigure_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
|
||||
return link_reconfigure_handler_internal(rtnl, m, link, /* force = */ true, /* update_wifi = */ false);
|
||||
return link_reconfigure_handler_internal(rtnl, m, link, /* force = */ true);
|
||||
}
|
||||
|
||||
static int link_reconfigure_after_sleep_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
|
||||
@@ -1339,7 +1325,7 @@ static int link_reconfigure_after_sleep_handler(sd_netlink *rtnl, sd_netlink_mes
|
||||
|
||||
assert(link);
|
||||
|
||||
r = link_reconfigure_handler_internal(rtnl, m, link, /* force = */ false, /* update_wifi = */ true);
|
||||
r = link_reconfigure_handler_internal(rtnl, m, link, /* force = */ false);
|
||||
if (r != 0)
|
||||
return r;
|
||||
|
||||
@@ -1421,10 +1407,6 @@ static int link_initialized_and_synced(Link *link) {
|
||||
return r;
|
||||
|
||||
if (!link->network) {
|
||||
r = wifi_get_info(link);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = link_get_network(link, &network);
|
||||
if (r == -ENOENT) {
|
||||
link_set_state(link, LINK_STATE_UNMANAGED);
|
||||
@@ -1893,7 +1875,7 @@ void link_update_operstate(Link *link, bool also_update_master) {
|
||||
: "")
|
||||
|
||||
static int link_update_flags(Link *link, sd_netlink_message *message) {
|
||||
bool link_was_lower_up, link_was_admin_up, had_carrier;
|
||||
bool link_was_admin_up, had_carrier;
|
||||
uint8_t operstate;
|
||||
unsigned flags;
|
||||
int r;
|
||||
@@ -1955,7 +1937,6 @@ static int link_update_flags(Link *link, sd_netlink_message *message) {
|
||||
log_link_debug(link, "Unknown link flags lost, ignoring: %#.5x", unknown_flags_removed);
|
||||
}
|
||||
|
||||
link_was_lower_up = link->flags & IFF_LOWER_UP;
|
||||
link_was_admin_up = link->flags & IFF_UP;
|
||||
had_carrier = link_has_carrier(link);
|
||||
|
||||
@@ -1964,19 +1945,6 @@ static int link_update_flags(Link *link, sd_netlink_message *message) {
|
||||
|
||||
link_update_operstate(link, true);
|
||||
|
||||
if (!link_was_lower_up && (link->flags & IFF_LOWER_UP)) {
|
||||
r = wifi_get_info(link);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r > 0) {
|
||||
/* All link information is up-to-date. So, it is not necessary to call
|
||||
* RTM_GETLINK netlink method again. */
|
||||
r = link_reconfigure_impl(link, /* force = */ false);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
||||
if (!link_was_admin_up && (link->flags & IFF_UP)) {
|
||||
log_link_info(link, "Link UP");
|
||||
|
||||
@@ -1994,6 +1962,15 @@ static int link_update_flags(Link *link, sd_netlink_message *message) {
|
||||
if (!had_carrier && link_has_carrier(link)) {
|
||||
log_link_info(link, "Gained carrier");
|
||||
|
||||
if (IN_SET(link->state, LINK_STATE_CONFIGURING, LINK_STATE_CONFIGURED)) {
|
||||
/* At this stage, both wlan and link information should be up-to-date. Hence,
|
||||
* it is not necessary to call RTM_GETLINK, NL80211_CMD_GET_INTERFACE, or
|
||||
* NL80211_CMD_GET_STATION commands, and simply call link_reconfigure_impl(). */
|
||||
r = link_reconfigure_impl(link, /* force = */ false);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
r = link_carrier_gained(link);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include <linux/if.h>
|
||||
#include <linux/fib_rules.h>
|
||||
#include <linux/nexthop.h>
|
||||
#include <linux/nl80211.h>
|
||||
|
||||
#include "sd-daemon.h"
|
||||
#include "sd-netlink.h"
|
||||
@@ -38,6 +39,7 @@
|
||||
#include "networkd-routing-policy-rule.h"
|
||||
#include "networkd-speed-meter.h"
|
||||
#include "networkd-state-file.h"
|
||||
#include "networkd-wifi.h"
|
||||
#include "ordered-set.h"
|
||||
#include "path-lookup.h"
|
||||
#include "path-util.h"
|
||||
@@ -109,13 +111,11 @@ static int on_connected(sd_bus_message *message, void *userdata, sd_bus_error *r
|
||||
return 0;
|
||||
}
|
||||
|
||||
int manager_connect_bus(Manager *m) {
|
||||
static int manager_connect_bus(Manager *m) {
|
||||
int r;
|
||||
|
||||
assert(m);
|
||||
|
||||
if (m->bus)
|
||||
return 0;
|
||||
assert(!m->bus);
|
||||
|
||||
r = bus_open_system_watch_bind_with_description(&m->bus, "bus-api-network");
|
||||
if (r < 0)
|
||||
@@ -248,6 +248,16 @@ static int manager_connect_genl(Manager *m) {
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = genl_add_match(m->genl, NULL, NL80211_GENL_NAME, NL80211_MULTICAST_GROUP_CONFIG, 0,
|
||||
&manager_genl_process_nl80211_config, NULL, m, "network-genl_process_nl80211_config");
|
||||
if (r < 0 && r != -EOPNOTSUPP)
|
||||
return r;
|
||||
|
||||
r = genl_add_match(m->genl, NULL, NL80211_GENL_NAME, NL80211_MULTICAST_GROUP_MLME, 0,
|
||||
&manager_genl_process_nl80211_mlme, NULL, m, "network-genl_process_nl80211_mlme");
|
||||
if (r < 0 && r != -EOPNOTSUPP)
|
||||
return r;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -372,28 +382,10 @@ static int signal_restart_callback(sd_event_source *s, const struct signalfd_sig
|
||||
return sd_event_exit(sd_event_source_get_event(s), 0);
|
||||
}
|
||||
|
||||
int manager_new(Manager **ret) {
|
||||
_cleanup_(manager_freep) Manager *m = NULL;
|
||||
int manager_setup(Manager *m, bool test_mode) {
|
||||
int r;
|
||||
|
||||
m = new(Manager, 1);
|
||||
if (!m)
|
||||
return -ENOMEM;
|
||||
|
||||
*m = (Manager) {
|
||||
.speed_meter_interval_usec = SPEED_METER_DEFAULT_TIME_INTERVAL,
|
||||
.online_state = _LINK_ONLINE_STATE_INVALID,
|
||||
.manage_foreign_routes = true,
|
||||
.manage_foreign_rules = true,
|
||||
.ethtool_fd = -1,
|
||||
.dhcp_duid.type = DUID_TYPE_EN,
|
||||
.dhcp6_duid.type = DUID_TYPE_EN,
|
||||
.duid_product_uuid.type = DUID_TYPE_UUID,
|
||||
};
|
||||
|
||||
m->state_file = strdup("/run/systemd/netif/state");
|
||||
if (!m->state_file)
|
||||
return -ENOMEM;
|
||||
assert(m);
|
||||
|
||||
r = sd_event_default(&m->event);
|
||||
if (r < 0)
|
||||
@@ -422,6 +414,13 @@ int manager_new(Manager **ret) {
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (test_mode)
|
||||
return 0;
|
||||
|
||||
r = manager_connect_bus(m);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = manager_connect_udev(m);
|
||||
if (r < 0)
|
||||
return r;
|
||||
@@ -438,11 +437,35 @@ int manager_new(Manager **ret) {
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
*ret = TAKE_PTR(m);
|
||||
m->state_file = strdup("/run/systemd/netif/state");
|
||||
if (!m->state_file)
|
||||
return -ENOMEM;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int manager_new(Manager **ret) {
|
||||
_cleanup_(manager_freep) Manager *m = NULL;
|
||||
|
||||
m = new(Manager, 1);
|
||||
if (!m)
|
||||
return -ENOMEM;
|
||||
|
||||
*m = (Manager) {
|
||||
.speed_meter_interval_usec = SPEED_METER_DEFAULT_TIME_INTERVAL,
|
||||
.online_state = _LINK_ONLINE_STATE_INVALID,
|
||||
.manage_foreign_routes = true,
|
||||
.manage_foreign_rules = true,
|
||||
.ethtool_fd = -1,
|
||||
.dhcp_duid.type = DUID_TYPE_EN,
|
||||
.dhcp6_duid.type = DUID_TYPE_EN,
|
||||
.duid_product_uuid.type = DUID_TYPE_UUID,
|
||||
};
|
||||
|
||||
*ret = TAKE_PTR(m);
|
||||
return 0;
|
||||
}
|
||||
|
||||
Manager* manager_free(Manager *m) {
|
||||
Link *link;
|
||||
|
||||
@@ -556,15 +579,15 @@ bool manager_should_reload(Manager *m) {
|
||||
|
||||
static int manager_enumerate_internal(
|
||||
Manager *m,
|
||||
sd_netlink *nl,
|
||||
sd_netlink_message *req,
|
||||
int (*process)(sd_netlink *, sd_netlink_message *, Manager *),
|
||||
const char *name) {
|
||||
int (*process)(sd_netlink *, sd_netlink_message *, Manager *)) {
|
||||
|
||||
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *reply = NULL;
|
||||
int r;
|
||||
int k, r;
|
||||
|
||||
assert(m);
|
||||
assert(m->rtnl);
|
||||
assert(nl);
|
||||
assert(req);
|
||||
assert(process);
|
||||
|
||||
@@ -572,22 +595,14 @@ static int manager_enumerate_internal(
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = sd_netlink_call(m->rtnl, req, 0, &reply);
|
||||
if (r < 0) {
|
||||
if (name && (r == -EOPNOTSUPP || (r == -EINVAL && mac_selinux_enforcing()))) {
|
||||
log_debug_errno(r, "%s are not supported by the kernel. Ignoring.", name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
r = sd_netlink_call(nl, req, 0, &reply);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
for (sd_netlink_message *reply_one = reply; reply_one; reply_one = sd_netlink_message_next(reply_one)) {
|
||||
int k;
|
||||
|
||||
m->enumerating = true;
|
||||
|
||||
k = process(m->rtnl, reply_one, m);
|
||||
k = process(nl, reply_one, m);
|
||||
if (k < 0 && r >= 0)
|
||||
r = k;
|
||||
|
||||
@@ -608,7 +623,7 @@ static int manager_enumerate_links(Manager *m) {
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
return manager_enumerate_internal(m, req, manager_rtnl_process_link, NULL);
|
||||
return manager_enumerate_internal(m, m->rtnl, req, manager_rtnl_process_link);
|
||||
}
|
||||
|
||||
static int manager_enumerate_addresses(Manager *m) {
|
||||
@@ -622,7 +637,7 @@ static int manager_enumerate_addresses(Manager *m) {
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
return manager_enumerate_internal(m, req, manager_rtnl_process_address, NULL);
|
||||
return manager_enumerate_internal(m, m->rtnl, req, manager_rtnl_process_address);
|
||||
}
|
||||
|
||||
static int manager_enumerate_neighbors(Manager *m) {
|
||||
@@ -636,7 +651,7 @@ static int manager_enumerate_neighbors(Manager *m) {
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
return manager_enumerate_internal(m, req, manager_rtnl_process_neighbor, NULL);
|
||||
return manager_enumerate_internal(m, m->rtnl, req, manager_rtnl_process_neighbor);
|
||||
}
|
||||
|
||||
static int manager_enumerate_routes(Manager *m) {
|
||||
@@ -653,7 +668,7 @@ static int manager_enumerate_routes(Manager *m) {
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
return manager_enumerate_internal(m, req, manager_rtnl_process_route, NULL);
|
||||
return manager_enumerate_internal(m, m->rtnl, req, manager_rtnl_process_route);
|
||||
}
|
||||
|
||||
static int manager_enumerate_rules(Manager *m) {
|
||||
@@ -670,7 +685,7 @@ static int manager_enumerate_rules(Manager *m) {
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
return manager_enumerate_internal(m, req, manager_rtnl_process_rule, "Routing policy rules");
|
||||
return manager_enumerate_internal(m, m->rtnl, req, manager_rtnl_process_rule);
|
||||
}
|
||||
|
||||
static int manager_enumerate_nexthop(Manager *m) {
|
||||
@@ -684,7 +699,50 @@ static int manager_enumerate_nexthop(Manager *m) {
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
return manager_enumerate_internal(m, req, manager_rtnl_process_nexthop, "Nexthop rules");
|
||||
return manager_enumerate_internal(m, m->rtnl, req, manager_rtnl_process_nexthop);
|
||||
}
|
||||
|
||||
static int manager_enumerate_nl80211_config(Manager *m) {
|
||||
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
|
||||
int r;
|
||||
|
||||
assert(m);
|
||||
assert(m->genl);
|
||||
|
||||
r = sd_genl_message_new(m->genl, NL80211_GENL_NAME, NL80211_CMD_GET_INTERFACE, &req);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
return manager_enumerate_internal(m, m->genl, req, manager_genl_process_nl80211_config);
|
||||
}
|
||||
|
||||
static int manager_enumerate_nl80211_mlme(Manager *m) {
|
||||
Link *link;
|
||||
int r;
|
||||
|
||||
assert(m);
|
||||
assert(m->genl);
|
||||
|
||||
HASHMAP_FOREACH(link, m->links_by_index) {
|
||||
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
|
||||
|
||||
if (link->wlan_iftype != NL80211_IFTYPE_STATION)
|
||||
continue;
|
||||
|
||||
r = sd_genl_message_new(m->genl, NL80211_GENL_NAME, NL80211_CMD_GET_STATION, &req);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = sd_netlink_message_append_u32(req, NL80211_ATTR_IFINDEX, link->ifindex);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = manager_enumerate_internal(m, m->genl, req, manager_genl_process_nl80211_mlme);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int manager_enumerate(Manager *m) {
|
||||
@@ -702,18 +760,37 @@ int manager_enumerate(Manager *m) {
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Could not enumerate neighbors: %m");
|
||||
|
||||
/* NextHop support is added in kernel v5.3 (65ee00a9409f751188a8cdc0988167858eb4a536),
|
||||
* and older kernels return -EOPNOTSUPP, or -EINVAL if SELinux is enabled. */
|
||||
r = manager_enumerate_nexthop(m);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Could not enumerate nexthop rules: %m");
|
||||
if (r == -EOPNOTSUPP || (r == -EINVAL && mac_selinux_enforcing()))
|
||||
log_debug_errno(r, "Could not enumerate nexthops, ignoring: %m");
|
||||
else if (r < 0)
|
||||
return log_error_errno(r, "Could not enumerate nexthops: %m");
|
||||
|
||||
r = manager_enumerate_routes(m);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Could not enumerate routes: %m");
|
||||
|
||||
/* If kernel is built with CONFIG_FIB_RULES=n, it returns -EOPNOTSUPP. */
|
||||
r = manager_enumerate_rules(m);
|
||||
if (r < 0)
|
||||
if (r == -EOPNOTSUPP)
|
||||
log_debug_errno(r, "Could not enumerate routing policy rules, ignoring: %m");
|
||||
else if (r < 0)
|
||||
return log_error_errno(r, "Could not enumerate routing policy rules: %m");
|
||||
|
||||
r = manager_enumerate_nl80211_config(m);
|
||||
if (r == -EOPNOTSUPP)
|
||||
log_debug_errno(r, "Could not enumerate wireless LAN interfaces, ignoring: %m");
|
||||
else if (r < 0)
|
||||
return log_error_errno(r, "Could not enumerate wireless LAN interfaces: %m");
|
||||
|
||||
r = manager_enumerate_nl80211_mlme(m);
|
||||
if (r == -EOPNOTSUPP)
|
||||
log_debug_errno(r, "Could not enumerate wireless LAN stations, ignoring: %m");
|
||||
else if (r < 0)
|
||||
return log_error_errno(r, "Could not enumerate wireless LAN stations: %m");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -99,7 +99,7 @@ struct Manager {
|
||||
int manager_new(Manager **ret);
|
||||
Manager* manager_free(Manager *m);
|
||||
|
||||
int manager_connect_bus(Manager *m);
|
||||
int manager_setup(Manager *m, bool test_mode);
|
||||
int manager_start(Manager *m);
|
||||
|
||||
int manager_load_config(Manager *m);
|
||||
|
||||
@@ -49,7 +49,7 @@ Match.PermanentMACAddress, config_parse_hwaddrs,
|
||||
Match.Path, config_parse_match_strv, 0, offsetof(Network, match.path)
|
||||
Match.Driver, config_parse_match_strv, 0, offsetof(Network, match.driver)
|
||||
Match.Type, config_parse_match_strv, 0, offsetof(Network, match.iftype)
|
||||
Match.WLANInterfaceType, config_parse_match_strv, 0, offsetof(Network, match.wifi_iftype)
|
||||
Match.WLANInterfaceType, config_parse_match_strv, 0, offsetof(Network, match.wlan_iftype)
|
||||
Match.SSID, config_parse_match_strv, 0, offsetof(Network, match.ssid)
|
||||
Match.BSSID, config_parse_hwaddrs, 0, offsetof(Network, match.bssid)
|
||||
Match.Name, config_parse_match_ifnames, IFNAME_VALID_ALTERNATIVE, offsetof(Network, match.ifname)
|
||||
|
||||
@@ -3,11 +3,7 @@
|
||||
#include <net/ethernet.h>
|
||||
#include <linux/nl80211.h>
|
||||
|
||||
#include "sd-bus.h"
|
||||
|
||||
#include "bus-util.h"
|
||||
#include "ether-addr-util.h"
|
||||
#include "netlink-internal.h"
|
||||
#include "netlink-util.h"
|
||||
#include "networkd-link.h"
|
||||
#include "networkd-manager.h"
|
||||
@@ -15,56 +11,275 @@
|
||||
#include "string-util.h"
|
||||
#include "wifi-util.h"
|
||||
|
||||
int wifi_get_info(Link *link) {
|
||||
_cleanup_free_ char *ssid = NULL;
|
||||
enum nl80211_iftype iftype;
|
||||
bool updated = false;
|
||||
const char *type;
|
||||
static int link_get_wlan_interface(Link *link) {
|
||||
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL, *reply = NULL;
|
||||
int r;
|
||||
|
||||
assert(link);
|
||||
|
||||
if (!link->sd_device)
|
||||
return 0;
|
||||
|
||||
r = sd_device_get_devtype(link->sd_device, &type);
|
||||
if (r == -ENOENT)
|
||||
return 0;
|
||||
else if (r < 0)
|
||||
return r;
|
||||
|
||||
if (!streq(type, "wlan"))
|
||||
return 0;
|
||||
|
||||
r = wifi_get_interface(link->manager->genl, link->ifindex, &iftype, &ssid);
|
||||
r = sd_genl_message_new(link->manager->genl, NL80211_GENL_NAME, NL80211_CMD_GET_INTERFACE, &req);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r == 0)
|
||||
iftype = link->wlan_iftype; /* Assume iftype is not changed. */
|
||||
return log_link_debug_errno(link, r, "Failed to create generic netlink message: %m");
|
||||
|
||||
if (iftype == NL80211_IFTYPE_STATION) {
|
||||
struct ether_addr bssid;
|
||||
r = sd_netlink_message_append_u32(req, NL80211_ATTR_IFINDEX, link->ifindex);
|
||||
if (r < 0)
|
||||
return log_link_debug_errno(link, r, "Could not append NL80211_ATTR_IFINDEX attribute: %m");
|
||||
|
||||
r = wifi_get_station(link->manager->genl, link->ifindex, &bssid);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
updated = !ether_addr_equal(&link->bssid, &bssid);
|
||||
link->bssid = bssid;
|
||||
r = sd_netlink_call(link->manager->genl, req, 0, &reply);
|
||||
if (r < 0)
|
||||
return log_link_debug_errno(link, r, "Failed to request information about wlan interface: %m");
|
||||
if (!reply) {
|
||||
log_link_debug(link, "No reply received to request for information about wifi interface, ignoring.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
updated = updated || link->wlan_iftype != iftype;
|
||||
link->wlan_iftype = iftype;
|
||||
updated = updated || !streq_ptr(link->ssid, ssid);
|
||||
free_and_replace(link->ssid, ssid);
|
||||
return manager_genl_process_nl80211_config(link->manager->genl, reply, link->manager);
|
||||
}
|
||||
|
||||
int manager_genl_process_nl80211_config(sd_netlink *genl, sd_netlink_message *message, Manager *manager) {
|
||||
_cleanup_free_ char *ssid = NULL;
|
||||
uint32_t ifindex, wlan_iftype;
|
||||
const char *family, *ifname;
|
||||
uint8_t cmd;
|
||||
size_t len;
|
||||
Link *link;
|
||||
int r;
|
||||
|
||||
assert(genl);
|
||||
assert(message);
|
||||
assert(manager);
|
||||
|
||||
if (sd_netlink_message_is_error(message)) {
|
||||
r = sd_netlink_message_get_errno(message);
|
||||
if (r < 0)
|
||||
log_message_warning_errno(message, r, "nl80211: received error message, ignoring");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
r = sd_genl_message_get_family_name(genl, message, &family);
|
||||
if (r < 0) {
|
||||
log_debug_errno(r, "nl80211: failed to determine genl family, ignoring: %m");
|
||||
return 0;
|
||||
}
|
||||
if (!streq(family, NL80211_GENL_NAME)) {
|
||||
log_debug("nl80211: received message of unexpected genl family '%s', ignoring.", family);
|
||||
return 0;
|
||||
}
|
||||
|
||||
r = sd_genl_message_get_command(genl, message, &cmd);
|
||||
if (r < 0) {
|
||||
log_debug_errno(r, "nl80211: failed to determine genl message command, ignoring: %m");
|
||||
return 0;
|
||||
}
|
||||
if (!IN_SET(cmd, NL80211_CMD_SET_INTERFACE, NL80211_CMD_NEW_INTERFACE, NL80211_CMD_DEL_INTERFACE)) {
|
||||
log_debug("nl80211: ignoring nl80211 %s(%u) message.",
|
||||
strna(nl80211_cmd_to_string(cmd)), cmd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
r = sd_netlink_message_read_u32(message, NL80211_ATTR_IFINDEX, &ifindex);
|
||||
if (r < 0) {
|
||||
log_debug_errno(r, "nl80211: received %s(%u) message without valid ifindex, ignoring: %m",
|
||||
strna(nl80211_cmd_to_string(cmd)), cmd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
r = link_get_by_index(manager, ifindex, &link);
|
||||
if (r < 0) {
|
||||
log_debug_errno(r, "nl80211: received %s(%u) message for link '%"PRIu32"' we don't know about, ignoring.",
|
||||
strna(nl80211_cmd_to_string(cmd)), cmd, ifindex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
r = sd_netlink_message_read_string(message, NL80211_ATTR_IFNAME, &ifname);
|
||||
if (r < 0) {
|
||||
log_link_debug_errno(link, r, "nl80211: received %s(%u) message without valid interface name, ignoring: %m",
|
||||
strna(nl80211_cmd_to_string(cmd)), cmd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!streq(ifname, link->ifname)) {
|
||||
log_link_debug_errno(link, r, "nl80211: received %s(%u) message with invalid interface name '%s', ignoring: %m",
|
||||
strna(nl80211_cmd_to_string(cmd)), cmd, ifname);
|
||||
return 0;
|
||||
}
|
||||
|
||||
r = sd_netlink_message_read_u32(message, NL80211_ATTR_IFTYPE, &wlan_iftype);
|
||||
if (r < 0) {
|
||||
log_link_debug_errno(link, r, "nl80211: received %s(%u) message without valid wlan interface type, ignoring: %m",
|
||||
strna(nl80211_cmd_to_string(cmd)), cmd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
r = sd_netlink_message_read_data_suffix0(message, NL80211_ATTR_SSID, &len, (void**) &ssid);
|
||||
if (r < 0 && r != -ENODATA) {
|
||||
log_link_debug_errno(link, r, "nl80211: received %s(%u) message without valid SSID, ignoring: %m",
|
||||
strna(nl80211_cmd_to_string(cmd)), cmd);
|
||||
return 0;
|
||||
}
|
||||
if (r >= 0) {
|
||||
if (len == 0) {
|
||||
log_link_debug(link, "nl80211: received SSID has zero length, ignoring the received SSID: %m");
|
||||
ssid = mfree(ssid);
|
||||
} else if (strlen_ptr(ssid) != len) {
|
||||
log_link_debug(link, "nl80211: received SSID contains NUL character(s), ignoring the received SSID.");
|
||||
ssid = mfree(ssid);
|
||||
}
|
||||
}
|
||||
|
||||
log_link_debug(link, "nl80211: received %s(%u) message: iftype=%s, ssid=%s",
|
||||
strna(nl80211_cmd_to_string(cmd)), cmd,
|
||||
strna(nl80211_iftype_to_string(wlan_iftype)), ssid);
|
||||
|
||||
switch(cmd) {
|
||||
case NL80211_CMD_SET_INTERFACE:
|
||||
case NL80211_CMD_NEW_INTERFACE:
|
||||
link->wlan_iftype = wlan_iftype;
|
||||
free_and_replace(link->ssid, ssid);
|
||||
break;
|
||||
|
||||
case NL80211_CMD_DEL_INTERFACE:
|
||||
link->wlan_iftype = NL80211_IFTYPE_UNSPECIFIED;
|
||||
link->ssid = mfree(link->ssid);
|
||||
break;
|
||||
|
||||
default:
|
||||
assert_not_reached();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int manager_genl_process_nl80211_mlme(sd_netlink *genl, sd_netlink_message *message, Manager *manager) {
|
||||
const char *family;
|
||||
uint32_t ifindex;
|
||||
uint8_t cmd;
|
||||
Link *link;
|
||||
int r;
|
||||
|
||||
assert(genl);
|
||||
assert(message);
|
||||
assert(manager);
|
||||
|
||||
if (sd_netlink_message_is_error(message)) {
|
||||
r = sd_netlink_message_get_errno(message);
|
||||
if (r < 0)
|
||||
log_message_warning_errno(message, r, "nl80211: received error message, ignoring");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
r = sd_genl_message_get_family_name(genl, message, &family);
|
||||
if (r < 0) {
|
||||
log_debug_errno(r, "nl80211: failed to determine genl family, ignoring: %m");
|
||||
return 0;
|
||||
}
|
||||
if (!streq(family, NL80211_GENL_NAME)) {
|
||||
log_debug("nl80211: Received message of unexpected genl family '%s', ignoring.", family);
|
||||
return 0;
|
||||
}
|
||||
|
||||
r = sd_genl_message_get_command(genl, message, &cmd);
|
||||
if (r < 0) {
|
||||
log_debug_errno(r, "nl80211: failed to determine genl message command, ignoring: %m");
|
||||
return 0;
|
||||
}
|
||||
|
||||
r = sd_netlink_message_read_u32(message, NL80211_ATTR_IFINDEX, &ifindex);
|
||||
if (r < 0) {
|
||||
log_debug_errno(r, "nl80211: received %s(%u) message without valid ifindex, ignoring: %m",
|
||||
strna(nl80211_cmd_to_string(cmd)), cmd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
r = link_get_by_index(manager, ifindex, &link);
|
||||
if (r < 0) {
|
||||
log_debug_errno(r, "nl80211: received %s(%u) message for link '%"PRIu32"' we don't know about, ignoring.",
|
||||
strna(nl80211_cmd_to_string(cmd)), cmd, ifindex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
switch(cmd) {
|
||||
case NL80211_CMD_NEW_STATION:
|
||||
case NL80211_CMD_DEL_STATION: {
|
||||
struct ether_addr bssid;
|
||||
|
||||
r = sd_netlink_message_read_ether_addr(message, NL80211_ATTR_MAC, &bssid);
|
||||
if (r < 0) {
|
||||
log_link_debug_errno(link, r, "nl80211: received %s(%u) message without valid BSSID, ignoring: %m",
|
||||
strna(nl80211_cmd_to_string(cmd)), cmd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
log_link_debug(link, "nl80211: received %s(%u) message: bssid=%s",
|
||||
strna(nl80211_cmd_to_string(cmd)), cmd, ETHER_ADDR_TO_STR(&bssid));
|
||||
|
||||
if (cmd == NL80211_CMD_DEL_STATION) {
|
||||
link->bssid = ETHER_ADDR_NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
link->bssid = bssid;
|
||||
|
||||
if (manager->enumerating &&
|
||||
link->wlan_iftype == NL80211_IFTYPE_STATION && link->ssid)
|
||||
log_link_info(link, "Connected WiFi access point: %s (%s)",
|
||||
link->ssid, ETHER_ADDR_TO_STR(&link->bssid));
|
||||
break;
|
||||
}
|
||||
case NL80211_CMD_CONNECT: {
|
||||
struct ether_addr bssid;
|
||||
uint16_t status_code;
|
||||
|
||||
r = sd_netlink_message_read_ether_addr(message, NL80211_ATTR_MAC, &bssid);
|
||||
if (r < 0 && r != -ENODATA) {
|
||||
log_link_debug_errno(link, r, "nl80211: received %s(%u) message without valid BSSID, ignoring: %m",
|
||||
strna(nl80211_cmd_to_string(cmd)), cmd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
r = sd_netlink_message_read_u16(message, NL80211_ATTR_STATUS_CODE, &status_code);
|
||||
if (r < 0) {
|
||||
log_link_debug_errno(link, r, "nl80211: received %s(%u) message without valid status code, ignoring: %m",
|
||||
strna(nl80211_cmd_to_string(cmd)), cmd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
log_link_debug(link, "nl80211: received %s(%u) message: status=%u, bssid=%s",
|
||||
strna(nl80211_cmd_to_string(cmd)), cmd, status_code, ETHER_ADDR_TO_STR(&bssid));
|
||||
|
||||
if (status_code != 0)
|
||||
return 0;
|
||||
|
||||
link->bssid = bssid;
|
||||
|
||||
if (!manager->enumerating) {
|
||||
r = link_get_wlan_interface(link);
|
||||
if (r < 0) {
|
||||
log_link_warning_errno(link, r, "Failed to update wireless LAN interface: %m");
|
||||
link_enter_failed(link);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (updated) {
|
||||
if (link->wlan_iftype == NL80211_IFTYPE_STATION && link->ssid)
|
||||
log_link_info(link, "Connected WiFi access point: %s (%s)",
|
||||
link->ssid, ETHER_ADDR_TO_STR(&link->bssid));
|
||||
break;
|
||||
}
|
||||
case NL80211_CMD_DISCONNECT:
|
||||
log_link_debug(link, "nl80211: received %s(%u) message.",
|
||||
strna(nl80211_cmd_to_string(cmd)), cmd);
|
||||
|
||||
return 1; /* Some information is updated. */
|
||||
link->bssid = ETHER_ADDR_NULL;
|
||||
link->ssid = mfree(link->ssid);
|
||||
break;
|
||||
|
||||
default:
|
||||
log_link_debug(link, "nl80211: received %s(%u) message.",
|
||||
strna(nl80211_cmd_to_string(cmd)), cmd);
|
||||
}
|
||||
|
||||
return 0; /* No new information. */
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
#pragma once
|
||||
|
||||
#include "sd-bus.h"
|
||||
#include "sd-netlink.h"
|
||||
|
||||
typedef struct Link Link;
|
||||
typedef struct Manager Manager;
|
||||
|
||||
int wifi_get_info(Link *link);
|
||||
int manager_genl_process_nl80211_config(sd_netlink *genl, sd_netlink_message *message, Manager *manager);
|
||||
int manager_genl_process_nl80211_mlme(sd_netlink *genl, sd_netlink_message *message, Manager *manager);
|
||||
|
||||
@@ -77,9 +77,9 @@ static int run(int argc, char *argv[]) {
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Could not create manager: %m");
|
||||
|
||||
r = manager_connect_bus(m);
|
||||
r = manager_setup(m, /* test_mode = */ false);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Could not connect to bus: %m");
|
||||
return log_error_errno(r, "Could not setup manager: %m");
|
||||
|
||||
r = manager_parse_config_file(m);
|
||||
if (r < 0)
|
||||
|
||||
@@ -270,6 +270,7 @@ int main(void) {
|
||||
test_dhcp_hostname_shorten_overlong();
|
||||
|
||||
assert_se(manager_new(&manager) >= 0);
|
||||
assert_se(manager_setup(manager, /* test_mode = */ true) >= 0);
|
||||
|
||||
test_route_tables(manager);
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#include "socket-util.h"
|
||||
#include "string-table.h"
|
||||
#include "strv.h"
|
||||
#include "wifi-util.h"
|
||||
|
||||
void net_match_clear(NetMatch *match) {
|
||||
if (!match)
|
||||
@@ -22,7 +23,7 @@ void net_match_clear(NetMatch *match) {
|
||||
match->iftype = strv_free(match->iftype);
|
||||
match->ifname = strv_free(match->ifname);
|
||||
match->property = strv_free(match->property);
|
||||
match->wifi_iftype = strv_free(match->wifi_iftype);
|
||||
match->wlan_iftype = strv_free(match->wlan_iftype);
|
||||
match->ssid = strv_free(match->ssid);
|
||||
match->bssid = set_free_free(match->bssid);
|
||||
}
|
||||
@@ -38,7 +39,7 @@ bool net_match_is_empty(const NetMatch *match) {
|
||||
strv_isempty(match->iftype) &&
|
||||
strv_isempty(match->ifname) &&
|
||||
strv_isempty(match->property) &&
|
||||
strv_isempty(match->wifi_iftype) &&
|
||||
strv_isempty(match->wlan_iftype) &&
|
||||
strv_isempty(match->ssid) &&
|
||||
set_isempty(match->bssid);
|
||||
}
|
||||
@@ -117,23 +118,6 @@ static int net_condition_test_property(char * const *match_property, sd_device *
|
||||
return true;
|
||||
}
|
||||
|
||||
static const char *const wifi_iftype_table[NL80211_IFTYPE_MAX+1] = {
|
||||
[NL80211_IFTYPE_ADHOC] = "ad-hoc",
|
||||
[NL80211_IFTYPE_STATION] = "station",
|
||||
[NL80211_IFTYPE_AP] = "ap",
|
||||
[NL80211_IFTYPE_AP_VLAN] = "ap-vlan",
|
||||
[NL80211_IFTYPE_WDS] = "wds",
|
||||
[NL80211_IFTYPE_MONITOR] = "monitor",
|
||||
[NL80211_IFTYPE_MESH_POINT] = "mesh-point",
|
||||
[NL80211_IFTYPE_P2P_CLIENT] = "p2p-client",
|
||||
[NL80211_IFTYPE_P2P_GO] = "p2p-go",
|
||||
[NL80211_IFTYPE_P2P_DEVICE] = "p2p-device",
|
||||
[NL80211_IFTYPE_OCB] = "ocb",
|
||||
[NL80211_IFTYPE_NAN] = "nan",
|
||||
};
|
||||
|
||||
DEFINE_PRIVATE_STRING_TABLE_LOOKUP_TO_STRING(wifi_iftype, enum nl80211_iftype);
|
||||
|
||||
int net_match_config(
|
||||
const NetMatch *match,
|
||||
sd_device *device,
|
||||
@@ -143,7 +127,7 @@ int net_match_config(
|
||||
unsigned short iftype,
|
||||
const char *ifname,
|
||||
char * const *alternative_names,
|
||||
enum nl80211_iftype wifi_iftype,
|
||||
enum nl80211_iftype wlan_iftype,
|
||||
const char *ssid,
|
||||
const struct ether_addr *bssid) {
|
||||
|
||||
@@ -194,7 +178,7 @@ int net_match_config(
|
||||
if (!net_condition_test_property(match->property, device))
|
||||
return false;
|
||||
|
||||
if (!net_condition_test_strv(match->wifi_iftype, wifi_iftype_to_string(wifi_iftype)))
|
||||
if (!net_condition_test_strv(match->wlan_iftype, nl80211_iftype_to_string(wlan_iftype)))
|
||||
return false;
|
||||
|
||||
if (!net_condition_test_strv(match->ssid, ssid))
|
||||
|
||||
@@ -18,7 +18,7 @@ typedef struct NetMatch {
|
||||
char **iftype;
|
||||
char **ifname;
|
||||
char **property;
|
||||
char **wifi_iftype;
|
||||
char **wlan_iftype;
|
||||
char **ssid;
|
||||
Set *bssid;
|
||||
} NetMatch;
|
||||
@@ -35,7 +35,7 @@ int net_match_config(
|
||||
unsigned short iftype,
|
||||
const char *ifname,
|
||||
char * const *alternative_names,
|
||||
enum nl80211_iftype wifi_iftype,
|
||||
enum nl80211_iftype wlan_iftype,
|
||||
const char *ssid,
|
||||
const struct ether_addr *bssid);
|
||||
|
||||
|
||||
@@ -1,12 +1,16 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
|
||||
#include "log.h"
|
||||
#include "string-table.h"
|
||||
#include "string-util.h"
|
||||
#include "wifi-util.h"
|
||||
|
||||
int wifi_get_interface(sd_netlink *genl, int ifindex, enum nl80211_iftype *iftype, char **ssid) {
|
||||
int wifi_get_interface(sd_netlink *genl, int ifindex, enum nl80211_iftype *ret_iftype, char **ret_ssid) {
|
||||
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL, *reply = NULL;
|
||||
_cleanup_free_ char *ssid = NULL;
|
||||
const char *family;
|
||||
uint32_t iftype;
|
||||
size_t len;
|
||||
int r;
|
||||
|
||||
assert(genl);
|
||||
@@ -47,41 +51,47 @@ int wifi_get_interface(sd_netlink *genl, int ifindex, enum nl80211_iftype *iftyp
|
||||
goto nodata;
|
||||
}
|
||||
|
||||
if (iftype) {
|
||||
uint32_t t;
|
||||
r = sd_netlink_message_read_u32(reply, NL80211_ATTR_IFTYPE, &iftype);
|
||||
if (r < 0)
|
||||
return log_debug_errno(r, "Failed to get NL80211_ATTR_IFTYPE attribute: %m");
|
||||
|
||||
r = sd_netlink_message_read_u32(reply, NL80211_ATTR_IFTYPE, &t);
|
||||
if (r < 0)
|
||||
return log_debug_errno(r, "Failed to get NL80211_ATTR_IFTYPE attribute: %m");
|
||||
*iftype = t;
|
||||
r = sd_netlink_message_read_data_suffix0(reply, NL80211_ATTR_SSID, &len, (void**) &ssid);
|
||||
if (r < 0 && r != -ENODATA)
|
||||
return log_debug_errno(r, "Failed to get NL80211_ATTR_SSID attribute: %m");
|
||||
if (r >= 0) {
|
||||
if (len == 0) {
|
||||
log_debug("SSID has zero length, ignoring the received SSID.");
|
||||
ssid = mfree(ssid);
|
||||
} else if (strlen_ptr(ssid) != len) {
|
||||
log_debug("SSID contains NUL character(s), ignoring the received SSID.");
|
||||
ssid = mfree(ssid);
|
||||
}
|
||||
}
|
||||
|
||||
if (ssid) {
|
||||
r = sd_netlink_message_read_string_strdup(reply, NL80211_ATTR_SSID, ssid);
|
||||
if (r == -ENODATA)
|
||||
*ssid = NULL;
|
||||
else if (r < 0)
|
||||
return log_debug_errno(r, "Failed to get NL80211_ATTR_SSID attribute: %m");
|
||||
}
|
||||
if (ret_iftype)
|
||||
*ret_iftype = iftype;
|
||||
|
||||
if (ret_ssid)
|
||||
*ret_ssid = TAKE_PTR(ssid);
|
||||
|
||||
return 1;
|
||||
|
||||
nodata:
|
||||
if (iftype)
|
||||
*iftype = 0;
|
||||
if (ssid)
|
||||
*ssid = NULL;
|
||||
if (ret_iftype)
|
||||
*ret_iftype = 0;
|
||||
if (ret_ssid)
|
||||
*ret_ssid = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int wifi_get_station(sd_netlink *genl, int ifindex, struct ether_addr *bssid) {
|
||||
int wifi_get_station(sd_netlink *genl, int ifindex, struct ether_addr *ret_bssid) {
|
||||
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL, *reply = NULL;
|
||||
const char *family;
|
||||
int r;
|
||||
|
||||
assert(genl);
|
||||
assert(ifindex > 0);
|
||||
assert(bssid);
|
||||
assert(ret_bssid);
|
||||
|
||||
r = sd_genl_message_new(genl, NL80211_GENL_NAME, NL80211_CMD_GET_STATION, &m);
|
||||
if (r < 0)
|
||||
@@ -115,7 +125,7 @@ int wifi_get_station(sd_netlink *genl, int ifindex, struct ether_addr *bssid) {
|
||||
goto nodata;
|
||||
}
|
||||
|
||||
r = sd_netlink_message_read_ether_addr(reply, NL80211_ATTR_MAC, bssid);
|
||||
r = sd_netlink_message_read_ether_addr(reply, NL80211_ATTR_MAC, ret_bssid);
|
||||
if (r == -ENODATA)
|
||||
goto nodata;
|
||||
if (r < 0)
|
||||
@@ -124,6 +134,173 @@ int wifi_get_station(sd_netlink *genl, int ifindex, struct ether_addr *bssid) {
|
||||
return 1;
|
||||
|
||||
nodata:
|
||||
*bssid = (struct ether_addr) {};
|
||||
*ret_bssid = ETHER_ADDR_NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const char * const nl80211_iftype_table[NUM_NL80211_IFTYPES] = {
|
||||
[NL80211_IFTYPE_ADHOC] = "ad-hoc",
|
||||
[NL80211_IFTYPE_STATION] = "station",
|
||||
[NL80211_IFTYPE_AP] = "ap",
|
||||
[NL80211_IFTYPE_AP_VLAN] = "ap-vlan",
|
||||
[NL80211_IFTYPE_WDS] = "wds",
|
||||
[NL80211_IFTYPE_MONITOR] = "monitor",
|
||||
[NL80211_IFTYPE_MESH_POINT] = "mesh-point",
|
||||
[NL80211_IFTYPE_P2P_CLIENT] = "p2p-client",
|
||||
[NL80211_IFTYPE_P2P_GO] = "p2p-go",
|
||||
[NL80211_IFTYPE_P2P_DEVICE] = "p2p-device",
|
||||
[NL80211_IFTYPE_OCB] = "ocb",
|
||||
[NL80211_IFTYPE_NAN] = "nan",
|
||||
};
|
||||
|
||||
DEFINE_STRING_TABLE_LOOKUP_TO_STRING(nl80211_iftype, enum nl80211_iftype);
|
||||
|
||||
static const char * const nl80211_cmd_table[__NL80211_CMD_AFTER_LAST] = {
|
||||
[NL80211_CMD_GET_WIPHY] = "get_wiphy",
|
||||
[NL80211_CMD_SET_WIPHY] = "set_wiphy",
|
||||
[NL80211_CMD_NEW_WIPHY] = "new_wiphy",
|
||||
[NL80211_CMD_DEL_WIPHY] = "del_wiphy",
|
||||
[NL80211_CMD_GET_INTERFACE] = "get_interface",
|
||||
[NL80211_CMD_SET_INTERFACE] = "set_interface",
|
||||
[NL80211_CMD_NEW_INTERFACE] = "new_interface",
|
||||
[NL80211_CMD_DEL_INTERFACE] = "del_interface",
|
||||
[NL80211_CMD_GET_KEY] = "get_key",
|
||||
[NL80211_CMD_SET_KEY] = "set_key",
|
||||
[NL80211_CMD_NEW_KEY] = "new_key",
|
||||
[NL80211_CMD_DEL_KEY] = "del_key",
|
||||
[NL80211_CMD_GET_BEACON] = "get_beacon",
|
||||
[NL80211_CMD_SET_BEACON] = "set_beacon",
|
||||
[NL80211_CMD_START_AP] = "start_ap",
|
||||
[NL80211_CMD_STOP_AP] = "stop_ap",
|
||||
[NL80211_CMD_GET_STATION] = "get_station",
|
||||
[NL80211_CMD_SET_STATION] = "set_station",
|
||||
[NL80211_CMD_NEW_STATION] = "new_station",
|
||||
[NL80211_CMD_DEL_STATION] = "del_station",
|
||||
[NL80211_CMD_GET_MPATH] = "get_mpath",
|
||||
[NL80211_CMD_SET_MPATH] = "set_mpath",
|
||||
[NL80211_CMD_NEW_MPATH] = "new_mpath",
|
||||
[NL80211_CMD_DEL_MPATH] = "del_mpath",
|
||||
[NL80211_CMD_SET_BSS] = "set_bss",
|
||||
[NL80211_CMD_SET_REG] = "set_reg",
|
||||
[NL80211_CMD_REQ_SET_REG] = "req_set_reg",
|
||||
[NL80211_CMD_GET_MESH_CONFIG] = "get_mesh_config",
|
||||
[NL80211_CMD_SET_MESH_CONFIG] = "set_mesh_config",
|
||||
[NL80211_CMD_SET_MGMT_EXTRA_IE] = "set_mgmt_extra_ie",
|
||||
[NL80211_CMD_GET_REG] = "get_reg",
|
||||
[NL80211_CMD_GET_SCAN] = "get_scan",
|
||||
[NL80211_CMD_TRIGGER_SCAN] = "trigger_scan",
|
||||
[NL80211_CMD_NEW_SCAN_RESULTS] = "new_scan_results",
|
||||
[NL80211_CMD_SCAN_ABORTED] = "scan_aborted",
|
||||
[NL80211_CMD_REG_CHANGE] = "reg_change",
|
||||
[NL80211_CMD_AUTHENTICATE] = "authenticate",
|
||||
[NL80211_CMD_ASSOCIATE] = "associate",
|
||||
[NL80211_CMD_DEAUTHENTICATE] = "deauthenticate",
|
||||
[NL80211_CMD_DISASSOCIATE] = "disassociate",
|
||||
[NL80211_CMD_MICHAEL_MIC_FAILURE] = "michael_mic_failure",
|
||||
[NL80211_CMD_REG_BEACON_HINT] = "reg_beacon_hint",
|
||||
[NL80211_CMD_JOIN_IBSS] = "join_ibss",
|
||||
[NL80211_CMD_LEAVE_IBSS] = "leave_ibss",
|
||||
[NL80211_CMD_TESTMODE] = "testmode",
|
||||
[NL80211_CMD_CONNECT] = "connect",
|
||||
[NL80211_CMD_ROAM] = "roam",
|
||||
[NL80211_CMD_DISCONNECT] = "disconnect",
|
||||
[NL80211_CMD_SET_WIPHY_NETNS] = "set_wiphy_netns",
|
||||
[NL80211_CMD_GET_SURVEY] = "get_survey",
|
||||
[NL80211_CMD_NEW_SURVEY_RESULTS] = "new_survey_results",
|
||||
[NL80211_CMD_SET_PMKSA] = "set_pmksa",
|
||||
[NL80211_CMD_DEL_PMKSA] = "del_pmksa",
|
||||
[NL80211_CMD_FLUSH_PMKSA] = "flush_pmksa",
|
||||
[NL80211_CMD_REMAIN_ON_CHANNEL] = "remain_on_channel",
|
||||
[NL80211_CMD_CANCEL_REMAIN_ON_CHANNEL] = "cancel_remain_on_channel",
|
||||
[NL80211_CMD_SET_TX_BITRATE_MASK] = "set_tx_bitrate_mask",
|
||||
[NL80211_CMD_REGISTER_FRAME] = "register_frame",
|
||||
[NL80211_CMD_FRAME] = "frame",
|
||||
[NL80211_CMD_FRAME_TX_STATUS] = "frame_tx_status",
|
||||
[NL80211_CMD_SET_POWER_SAVE] = "set_power_save",
|
||||
[NL80211_CMD_GET_POWER_SAVE] = "get_power_save",
|
||||
[NL80211_CMD_SET_CQM] = "set_cqm",
|
||||
[NL80211_CMD_NOTIFY_CQM] = "notify_cqm",
|
||||
[NL80211_CMD_SET_CHANNEL] = "set_channel",
|
||||
[NL80211_CMD_SET_WDS_PEER] = "set_wds_peer",
|
||||
[NL80211_CMD_FRAME_WAIT_CANCEL] = "frame_wait_cancel",
|
||||
[NL80211_CMD_JOIN_MESH] = "join_mesh",
|
||||
[NL80211_CMD_LEAVE_MESH] = "leave_mesh",
|
||||
[NL80211_CMD_UNPROT_DEAUTHENTICATE] = "unprot_deauthenticate",
|
||||
[NL80211_CMD_UNPROT_DISASSOCIATE] = "unprot_disassociate",
|
||||
[NL80211_CMD_NEW_PEER_CANDIDATE] = "new_peer_candidate",
|
||||
[NL80211_CMD_GET_WOWLAN] = "get_wowlan",
|
||||
[NL80211_CMD_SET_WOWLAN] = "set_wowlan",
|
||||
[NL80211_CMD_START_SCHED_SCAN] = "start_sched_scan",
|
||||
[NL80211_CMD_STOP_SCHED_SCAN] = "stop_sched_scan",
|
||||
[NL80211_CMD_SCHED_SCAN_RESULTS] = "sched_scan_results",
|
||||
[NL80211_CMD_SCHED_SCAN_STOPPED] = "sched_scan_stopped",
|
||||
[NL80211_CMD_SET_REKEY_OFFLOAD] = "set_rekey_offload",
|
||||
[NL80211_CMD_PMKSA_CANDIDATE] = "pmksa_candidate",
|
||||
[NL80211_CMD_TDLS_OPER] = "tdls_oper",
|
||||
[NL80211_CMD_TDLS_MGMT] = "tdls_mgmt",
|
||||
[NL80211_CMD_UNEXPECTED_FRAME] = "unexpected_frame",
|
||||
[NL80211_CMD_PROBE_CLIENT] = "probe_client",
|
||||
[NL80211_CMD_REGISTER_BEACONS] = "register_beacons",
|
||||
[NL80211_CMD_UNEXPECTED_4ADDR_FRAME] = "unexpected_4addr_frame",
|
||||
[NL80211_CMD_SET_NOACK_MAP] = "set_noack_map",
|
||||
[NL80211_CMD_CH_SWITCH_NOTIFY] = "ch_switch_notify",
|
||||
[NL80211_CMD_START_P2P_DEVICE] = "start_p2p_device",
|
||||
[NL80211_CMD_STOP_P2P_DEVICE] = "stop_p2p_device",
|
||||
[NL80211_CMD_CONN_FAILED] = "conn_failed",
|
||||
[NL80211_CMD_SET_MCAST_RATE] = "set_mcast_rate",
|
||||
[NL80211_CMD_SET_MAC_ACL] = "set_mac_acl",
|
||||
[NL80211_CMD_RADAR_DETECT] = "radar_detect",
|
||||
[NL80211_CMD_GET_PROTOCOL_FEATURES] = "get_protocol_features",
|
||||
[NL80211_CMD_UPDATE_FT_IES] = "update_ft_ies",
|
||||
[NL80211_CMD_FT_EVENT] = "ft_event",
|
||||
[NL80211_CMD_CRIT_PROTOCOL_START] = "crit_protocol_start",
|
||||
[NL80211_CMD_CRIT_PROTOCOL_STOP] = "crit_protocol_stop",
|
||||
[NL80211_CMD_GET_COALESCE] = "get_coalesce",
|
||||
[NL80211_CMD_SET_COALESCE] = "set_coalesce",
|
||||
[NL80211_CMD_CHANNEL_SWITCH] = "channel_switch",
|
||||
[NL80211_CMD_VENDOR] = "vendor",
|
||||
[NL80211_CMD_SET_QOS_MAP] = "set_qos_map",
|
||||
[NL80211_CMD_ADD_TX_TS] = "add_tx_ts",
|
||||
[NL80211_CMD_DEL_TX_TS] = "del_tx_ts",
|
||||
[NL80211_CMD_GET_MPP] = "get_mpp",
|
||||
[NL80211_CMD_JOIN_OCB] = "join_ocb",
|
||||
[NL80211_CMD_LEAVE_OCB] = "leave_ocb",
|
||||
[NL80211_CMD_CH_SWITCH_STARTED_NOTIFY] = "ch_switch_started_notify",
|
||||
[NL80211_CMD_TDLS_CHANNEL_SWITCH] = "tdls_channel_switch",
|
||||
[NL80211_CMD_TDLS_CANCEL_CHANNEL_SWITCH] = "tdls_cancel_channel_switch",
|
||||
[NL80211_CMD_WIPHY_REG_CHANGE] = "wiphy_reg_change",
|
||||
[NL80211_CMD_ABORT_SCAN] = "abort_scan",
|
||||
[NL80211_CMD_START_NAN] = "start_nan",
|
||||
[NL80211_CMD_STOP_NAN] = "stop_nan",
|
||||
[NL80211_CMD_ADD_NAN_FUNCTION] = "add_nan_function",
|
||||
[NL80211_CMD_DEL_NAN_FUNCTION] = "del_nan_function",
|
||||
[NL80211_CMD_CHANGE_NAN_CONFIG] = "change_nan_config",
|
||||
[NL80211_CMD_NAN_MATCH] = "nan_match",
|
||||
[NL80211_CMD_SET_MULTICAST_TO_UNICAST] = "set_multicast_to_unicast",
|
||||
[NL80211_CMD_UPDATE_CONNECT_PARAMS] = "update_connect_params",
|
||||
[NL80211_CMD_SET_PMK] = "set_pmk",
|
||||
[NL80211_CMD_DEL_PMK] = "del_pmk",
|
||||
[NL80211_CMD_PORT_AUTHORIZED] = "port_authorized",
|
||||
[NL80211_CMD_RELOAD_REGDB] = "reload_regdb",
|
||||
[NL80211_CMD_EXTERNAL_AUTH] = "external_auth",
|
||||
[NL80211_CMD_STA_OPMODE_CHANGED] = "sta_opmode_changed",
|
||||
[NL80211_CMD_CONTROL_PORT_FRAME] = "control_port_frame",
|
||||
[NL80211_CMD_GET_FTM_RESPONDER_STATS] = "get_ftm_responder_stats",
|
||||
[NL80211_CMD_PEER_MEASUREMENT_START] = "peer_measurement_start",
|
||||
[NL80211_CMD_PEER_MEASUREMENT_RESULT] = "peer_measurement_result",
|
||||
[NL80211_CMD_PEER_MEASUREMENT_COMPLETE] = "peer_measurement_complete",
|
||||
[NL80211_CMD_NOTIFY_RADAR] = "notify_radar",
|
||||
[NL80211_CMD_UPDATE_OWE_INFO] = "update_owe_info",
|
||||
[NL80211_CMD_PROBE_MESH_LINK] = "probe_mesh_link",
|
||||
[NL80211_CMD_SET_TID_CONFIG] = "set_tid_config",
|
||||
[NL80211_CMD_UNPROT_BEACON] = "unprot_beacon",
|
||||
[NL80211_CMD_CONTROL_PORT_FRAME_TX_STATUS] = "control_port_frame_tx_status",
|
||||
[NL80211_CMD_SET_SAR_SPECS] = "set_sar_specs",
|
||||
[NL80211_CMD_OBSS_COLOR_COLLISION] = "obss_color_collision",
|
||||
[NL80211_CMD_COLOR_CHANGE_REQUEST] = "color_change_request",
|
||||
[NL80211_CMD_COLOR_CHANGE_STARTED] = "color_change_started",
|
||||
[NL80211_CMD_COLOR_CHANGE_ABORTED] = "color_change_aborted",
|
||||
[NL80211_CMD_COLOR_CHANGE_COMPLETED] = "color_change_completed",
|
||||
};
|
||||
|
||||
DEFINE_STRING_TABLE_LOOKUP_TO_STRING(nl80211_cmd, int);
|
||||
|
||||
@@ -3,9 +3,13 @@
|
||||
#pragma once
|
||||
|
||||
#include <linux/nl80211.h>
|
||||
#include <net/ethernet.h>
|
||||
|
||||
#include "sd-netlink.h"
|
||||
|
||||
int wifi_get_interface(sd_netlink *genl, int ifindex, enum nl80211_iftype *iftype, char **ssid);
|
||||
int wifi_get_station(sd_netlink *genl, int ifindex, struct ether_addr *bssid);
|
||||
#include "ether-addr-util.h"
|
||||
|
||||
int wifi_get_interface(sd_netlink *genl, int ifindex, enum nl80211_iftype *ret_iftype, char **ret_ssid);
|
||||
int wifi_get_station(sd_netlink *genl, int ifindex, struct ether_addr *ret_bssid);
|
||||
|
||||
const char *nl80211_iftype_to_string(enum nl80211_iftype iftype) _const_;
|
||||
const char *nl80211_cmd_to_string(int cmd) _const_;
|
||||
|
||||
@@ -95,6 +95,7 @@ int sd_netlink_message_close_container(sd_netlink_message *m);
|
||||
|
||||
int sd_netlink_message_read(sd_netlink_message *m, unsigned short type, size_t size, void *data);
|
||||
int sd_netlink_message_read_data(sd_netlink_message *m, unsigned short type, size_t *ret_size, void **ret_data);
|
||||
int sd_netlink_message_read_data_suffix0(sd_netlink_message *m, unsigned short type, size_t *ret_size, void **ret_data);
|
||||
int sd_netlink_message_read_string_strdup(sd_netlink_message *m, unsigned short type, char **data);
|
||||
int sd_netlink_message_read_string(sd_netlink_message *m, unsigned short type, const char **data);
|
||||
int sd_netlink_message_read_strv(sd_netlink_message *m, unsigned short container_type, unsigned short type_id, char ***ret);
|
||||
|
||||
Reference in New Issue
Block a user