nl80211: Clean up netlink parsing and debug prints
This makes the RTM_NEWLINK, RTM_DELLINK, and operstate debug messages easier to understand. Signed-hostap: Jouni Malinen <j@w1.fi>
This commit is contained in:
parent
b6a9590b34
commit
90a545ccba
3 changed files with 147 additions and 74 deletions
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* Driver interaction with Linux nl80211/cfg80211
|
* Driver interaction with Linux nl80211/cfg80211
|
||||||
* Copyright (c) 2002-2012, Jouni Malinen <j@w1.fi>
|
* Copyright (c) 2002-2014, Jouni Malinen <j@w1.fi>
|
||||||
* Copyright (c) 2003-2004, Instant802 Networks, Inc.
|
* Copyright (c) 2003-2004, Instant802 Networks, Inc.
|
||||||
* Copyright (c) 2005-2006, Devicescape Software, Inc.
|
* Copyright (c) 2005-2006, Devicescape Software, Inc.
|
||||||
* Copyright (c) 2007, Johannes Berg <johannes@sipsolutions.net>
|
* Copyright (c) 2007, Johannes Berg <johannes@sipsolutions.net>
|
||||||
|
@ -1049,49 +1049,55 @@ static int wpa_driver_nl80211_get_ssid(void *priv, u8 *ssid)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void wpa_driver_nl80211_event_link(struct wpa_driver_nl80211_data *drv,
|
static void wpa_driver_nl80211_event_newlink(
|
||||||
char *buf, size_t len, int del)
|
struct wpa_driver_nl80211_data *drv, char *ifname)
|
||||||
{
|
{
|
||||||
union wpa_event_data event;
|
union wpa_event_data event;
|
||||||
|
|
||||||
os_memset(&event, 0, sizeof(event));
|
if (os_strcmp(drv->first_bss->ifname, ifname) == 0) {
|
||||||
if (len > sizeof(event.interface_status.ifname))
|
if (if_nametoindex(drv->first_bss->ifname) == 0) {
|
||||||
len = sizeof(event.interface_status.ifname) - 1;
|
wpa_printf(MSG_DEBUG, "nl80211: Interface %s does not exist - ignore RTM_NEWLINK",
|
||||||
os_memcpy(event.interface_status.ifname, buf, len);
|
drv->first_bss->ifname);
|
||||||
event.interface_status.ievent = del ? EVENT_INTERFACE_REMOVED :
|
return;
|
||||||
EVENT_INTERFACE_ADDED;
|
|
||||||
|
|
||||||
wpa_printf(MSG_DEBUG, "RTM_%sLINK, IFLA_IFNAME: Interface '%s' %s",
|
|
||||||
del ? "DEL" : "NEW",
|
|
||||||
event.interface_status.ifname,
|
|
||||||
del ? "removed" : "added");
|
|
||||||
|
|
||||||
if (os_strcmp(drv->first_bss->ifname, event.interface_status.ifname) ==
|
|
||||||
0) {
|
|
||||||
if (del) {
|
|
||||||
if (drv->if_removed) {
|
|
||||||
wpa_printf(MSG_DEBUG, "nl80211: if_removed "
|
|
||||||
"already set - ignore event");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
drv->if_removed = 1;
|
|
||||||
} else {
|
|
||||||
if (if_nametoindex(drv->first_bss->ifname) == 0) {
|
|
||||||
wpa_printf(MSG_DEBUG, "nl80211: Interface %s "
|
|
||||||
"does not exist - ignore "
|
|
||||||
"RTM_NEWLINK",
|
|
||||||
drv->first_bss->ifname);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!drv->if_removed) {
|
|
||||||
wpa_printf(MSG_DEBUG, "nl80211: if_removed "
|
|
||||||
"already cleared - ignore event");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
drv->if_removed = 0;
|
|
||||||
}
|
}
|
||||||
|
if (!drv->if_removed)
|
||||||
|
return;
|
||||||
|
wpa_printf(MSG_DEBUG, "nl80211: Mark if_removed=0 for %s based on RTM_NEWLINK event",
|
||||||
|
drv->first_bss->ifname);
|
||||||
|
drv->if_removed = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
os_memset(&event, 0, sizeof(event));
|
||||||
|
os_strlcpy(event.interface_status.ifname, ifname,
|
||||||
|
sizeof(event.interface_status.ifname));
|
||||||
|
event.interface_status.ievent = EVENT_INTERFACE_ADDED;
|
||||||
|
wpa_supplicant_event(drv->ctx, EVENT_INTERFACE_STATUS, &event);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void wpa_driver_nl80211_event_dellink(
|
||||||
|
struct wpa_driver_nl80211_data *drv, char *ifname)
|
||||||
|
{
|
||||||
|
union wpa_event_data event;
|
||||||
|
|
||||||
|
if (os_strcmp(drv->first_bss->ifname, ifname) == 0) {
|
||||||
|
if (drv->if_removed) {
|
||||||
|
wpa_printf(MSG_DEBUG, "nl80211: if_removed already set - ignore RTM_DELLINK event for %s",
|
||||||
|
ifname);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
wpa_printf(MSG_DEBUG, "RTM_DELLINK: Interface '%s' removed - mark if_removed=1",
|
||||||
|
ifname);
|
||||||
|
drv->if_removed = 1;
|
||||||
|
} else {
|
||||||
|
wpa_printf(MSG_DEBUG, "RTM_DELLINK: Interface '%s' removed",
|
||||||
|
ifname);
|
||||||
|
}
|
||||||
|
|
||||||
|
os_memset(&event, 0, sizeof(event));
|
||||||
|
os_strlcpy(event.interface_status.ifname, ifname,
|
||||||
|
sizeof(event.interface_status.ifname));
|
||||||
|
event.interface_status.ievent = EVENT_INTERFACE_REMOVED;
|
||||||
wpa_supplicant_event(drv->ctx, EVENT_INTERFACE_STATUS, &event);
|
wpa_supplicant_event(drv->ctx, EVENT_INTERFACE_STATUS, &event);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1158,21 +1164,57 @@ static void wpa_driver_nl80211_event_rtm_newlink(void *ctx,
|
||||||
{
|
{
|
||||||
struct nl80211_global *global = ctx;
|
struct nl80211_global *global = ctx;
|
||||||
struct wpa_driver_nl80211_data *drv;
|
struct wpa_driver_nl80211_data *drv;
|
||||||
int attrlen, rta_len;
|
int attrlen;
|
||||||
struct rtattr *attr;
|
struct rtattr *attr;
|
||||||
u32 brid = 0;
|
u32 brid = 0;
|
||||||
char namebuf[IFNAMSIZ];
|
char namebuf[IFNAMSIZ];
|
||||||
|
char ifname[IFNAMSIZ + 1];
|
||||||
|
char extra[100], *pos, *end;
|
||||||
|
|
||||||
drv = nl80211_find_drv(global, ifi->ifi_index, buf, len);
|
drv = nl80211_find_drv(global, ifi->ifi_index, buf, len);
|
||||||
if (!drv) {
|
if (!drv) {
|
||||||
wpa_printf(MSG_DEBUG, "nl80211: Ignore event for foreign "
|
wpa_printf(MSG_DEBUG, "nl80211: Ignore RTM_NEWLINK event for foreign ifindex %d",
|
||||||
"ifindex %d", ifi->ifi_index);
|
ifi->ifi_index);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
wpa_printf(MSG_DEBUG, "RTM_NEWLINK: operstate=%d ifi_flags=0x%x "
|
extra[0] = '\0';
|
||||||
"(%s%s%s%s)",
|
pos = extra;
|
||||||
drv->operstate, ifi->ifi_flags,
|
end = pos + sizeof(extra);
|
||||||
|
ifname[0] = '\0';
|
||||||
|
|
||||||
|
attrlen = len;
|
||||||
|
attr = (struct rtattr *) buf;
|
||||||
|
while (RTA_OK(attr, attrlen)) {
|
||||||
|
switch (attr->rta_type) {
|
||||||
|
case IFLA_IFNAME:
|
||||||
|
if (RTA_PAYLOAD(attr) >= IFNAMSIZ)
|
||||||
|
break;
|
||||||
|
os_memcpy(ifname, RTA_DATA(attr), RTA_PAYLOAD(attr));
|
||||||
|
ifname[RTA_PAYLOAD(attr)] = '\0';
|
||||||
|
break;
|
||||||
|
case IFLA_MASTER:
|
||||||
|
brid = nla_get_u32((struct nlattr *) attr);
|
||||||
|
pos += os_snprintf(pos, end - pos, " master=%u", brid);
|
||||||
|
break;
|
||||||
|
case IFLA_WIRELESS:
|
||||||
|
pos += os_snprintf(pos, end - pos, " wext");
|
||||||
|
break;
|
||||||
|
case IFLA_OPERSTATE:
|
||||||
|
pos += os_snprintf(pos, end - pos, " operstate=%u",
|
||||||
|
nla_get_u32((struct nlattr *) attr));
|
||||||
|
break;
|
||||||
|
case IFLA_LINKMODE:
|
||||||
|
pos += os_snprintf(pos, end - pos, " linkmode=%u",
|
||||||
|
nla_get_u32((struct nlattr *) attr));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
attr = RTA_NEXT(attr, attrlen);
|
||||||
|
}
|
||||||
|
extra[sizeof(extra) - 1] = '\0';
|
||||||
|
|
||||||
|
wpa_printf(MSG_DEBUG, "RTM_NEWLINK: ifi_index=%d ifname=%s%s ifi_flags=0x%x (%s%s%s%s)",
|
||||||
|
ifi->ifi_index, ifname, extra, ifi->ifi_flags,
|
||||||
(ifi->ifi_flags & IFF_UP) ? "[UP]" : "",
|
(ifi->ifi_flags & IFF_UP) ? "[UP]" : "",
|
||||||
(ifi->ifi_flags & IFF_RUNNING) ? "[RUNNING]" : "",
|
(ifi->ifi_flags & IFF_RUNNING) ? "[RUNNING]" : "",
|
||||||
(ifi->ifi_flags & IFF_LOWER_UP) ? "[LOWER_UP]" : "",
|
(ifi->ifi_flags & IFF_LOWER_UP) ? "[LOWER_UP]" : "",
|
||||||
|
@ -1229,24 +1271,15 @@ static void wpa_driver_nl80211_event_rtm_newlink(void *ctx,
|
||||||
*/
|
*/
|
||||||
if (drv->operstate == 1 &&
|
if (drv->operstate == 1 &&
|
||||||
(ifi->ifi_flags & (IFF_LOWER_UP | IFF_DORMANT)) == IFF_LOWER_UP &&
|
(ifi->ifi_flags & (IFF_LOWER_UP | IFF_DORMANT)) == IFF_LOWER_UP &&
|
||||||
!(ifi->ifi_flags & IFF_RUNNING))
|
!(ifi->ifi_flags & IFF_RUNNING)) {
|
||||||
|
wpa_printf(MSG_DEBUG, "nl80211: Set IF_OPER_UP again based on ifi_flags and expected operstate");
|
||||||
netlink_send_oper_ifla(drv->global->netlink, drv->ifindex,
|
netlink_send_oper_ifla(drv->global->netlink, drv->ifindex,
|
||||||
-1, IF_OPER_UP);
|
-1, IF_OPER_UP);
|
||||||
|
|
||||||
attrlen = len;
|
|
||||||
attr = (struct rtattr *) buf;
|
|
||||||
rta_len = RTA_ALIGN(sizeof(struct rtattr));
|
|
||||||
while (RTA_OK(attr, attrlen)) {
|
|
||||||
if (attr->rta_type == IFLA_IFNAME) {
|
|
||||||
wpa_driver_nl80211_event_link(
|
|
||||||
drv,
|
|
||||||
((char *) attr) + rta_len,
|
|
||||||
attr->rta_len - rta_len, 0);
|
|
||||||
} else if (attr->rta_type == IFLA_MASTER)
|
|
||||||
brid = nla_get_u32((struct nlattr *) attr);
|
|
||||||
attr = RTA_NEXT(attr, attrlen);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ifname[0])
|
||||||
|
wpa_driver_nl80211_event_newlink(drv, ifname);
|
||||||
|
|
||||||
if (ifi->ifi_family == AF_BRIDGE && brid) {
|
if (ifi->ifi_family == AF_BRIDGE && brid) {
|
||||||
/* device has been added to bridge */
|
/* device has been added to bridge */
|
||||||
if_indextoname(brid, namebuf);
|
if_indextoname(brid, namebuf);
|
||||||
|
@ -1263,32 +1296,40 @@ static void wpa_driver_nl80211_event_rtm_dellink(void *ctx,
|
||||||
{
|
{
|
||||||
struct nl80211_global *global = ctx;
|
struct nl80211_global *global = ctx;
|
||||||
struct wpa_driver_nl80211_data *drv;
|
struct wpa_driver_nl80211_data *drv;
|
||||||
int attrlen, rta_len;
|
int attrlen;
|
||||||
struct rtattr *attr;
|
struct rtattr *attr;
|
||||||
u32 brid = 0;
|
u32 brid = 0;
|
||||||
|
char ifname[IFNAMSIZ + 1];
|
||||||
|
|
||||||
drv = nl80211_find_drv(global, ifi->ifi_index, buf, len);
|
drv = nl80211_find_drv(global, ifi->ifi_index, buf, len);
|
||||||
if (!drv) {
|
if (!drv) {
|
||||||
wpa_printf(MSG_DEBUG, "nl80211: Ignore dellink event for "
|
wpa_printf(MSG_DEBUG, "nl80211: Ignore RTM_DELLINK event for foreign ifindex %d",
|
||||||
"foreign ifindex %d", ifi->ifi_index);
|
ifi->ifi_index);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ifname[0] = '\0';
|
||||||
|
|
||||||
attrlen = len;
|
attrlen = len;
|
||||||
attr = (struct rtattr *) buf;
|
attr = (struct rtattr *) buf;
|
||||||
|
|
||||||
rta_len = RTA_ALIGN(sizeof(struct rtattr));
|
|
||||||
while (RTA_OK(attr, attrlen)) {
|
while (RTA_OK(attr, attrlen)) {
|
||||||
if (attr->rta_type == IFLA_IFNAME) {
|
switch (attr->rta_type) {
|
||||||
wpa_driver_nl80211_event_link(
|
case IFLA_IFNAME:
|
||||||
drv,
|
if (RTA_PAYLOAD(attr) >= IFNAMSIZ)
|
||||||
((char *) attr) + rta_len,
|
break;
|
||||||
attr->rta_len - rta_len, 1);
|
os_memcpy(ifname, RTA_DATA(attr), RTA_PAYLOAD(attr));
|
||||||
} else if (attr->rta_type == IFLA_MASTER)
|
ifname[RTA_PAYLOAD(attr)] = '\0';
|
||||||
|
break;
|
||||||
|
case IFLA_MASTER:
|
||||||
brid = nla_get_u32((struct nlattr *) attr);
|
brid = nla_get_u32((struct nlattr *) attr);
|
||||||
|
break;
|
||||||
|
}
|
||||||
attr = RTA_NEXT(attr, attrlen);
|
attr = RTA_NEXT(attr, attrlen);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ifname[0])
|
||||||
|
wpa_driver_nl80211_event_dellink(drv, ifname);
|
||||||
|
|
||||||
if (ifi->ifi_family == AF_BRIDGE && brid) {
|
if (ifi->ifi_family == AF_BRIDGE && brid) {
|
||||||
/* device has been removed from bridge */
|
/* device has been removed from bridge */
|
||||||
char namebuf[IFNAMSIZ];
|
char namebuf[IFNAMSIZ];
|
||||||
|
@ -8611,8 +8652,9 @@ static int wpa_driver_nl80211_set_operstate(void *priv, int state)
|
||||||
struct i802_bss *bss = priv;
|
struct i802_bss *bss = priv;
|
||||||
struct wpa_driver_nl80211_data *drv = bss->drv;
|
struct wpa_driver_nl80211_data *drv = bss->drv;
|
||||||
|
|
||||||
wpa_printf(MSG_DEBUG, "%s: operstate %d->%d (%s)",
|
wpa_printf(MSG_DEBUG, "nl80211: Set %s operstate %d->%d (%s)",
|
||||||
__func__, drv->operstate, state, state ? "UP" : "DORMANT");
|
bss->ifname, drv->operstate, state,
|
||||||
|
state ? "UP" : "DORMANT");
|
||||||
drv->operstate = state;
|
drv->operstate = state;
|
||||||
return netlink_send_oper_ifla(drv->global->netlink, drv->ifindex, -1,
|
return netlink_send_oper_ifla(drv->global->netlink, drv->ifindex, -1,
|
||||||
state ? IF_OPER_UP : IF_OPER_DORMANT);
|
state ? IF_OPER_UP : IF_OPER_DORMANT);
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* Netlink helper functions for driver wrappers
|
* Netlink helper functions for driver wrappers
|
||||||
* Copyright (c) 2002-2009, Jouni Malinen <j@w1.fi>
|
* Copyright (c) 2002-2014, Jouni Malinen <j@w1.fi>
|
||||||
*
|
*
|
||||||
* This software may be distributed under the terms of the BSD license.
|
* This software may be distributed under the terms of the BSD license.
|
||||||
* See README for more details.
|
* See README for more details.
|
||||||
|
@ -137,6 +137,35 @@ void netlink_deinit(struct netlink_data *netlink)
|
||||||
os_free(netlink);
|
os_free(netlink);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static const char * linkmode_str(int mode)
|
||||||
|
{
|
||||||
|
switch (mode) {
|
||||||
|
case -1:
|
||||||
|
return "no change";
|
||||||
|
case 0:
|
||||||
|
return "kernel-control";
|
||||||
|
case 1:
|
||||||
|
return "userspace-control";
|
||||||
|
}
|
||||||
|
return "?";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static const char * operstate_str(int state)
|
||||||
|
{
|
||||||
|
switch (state) {
|
||||||
|
case -1:
|
||||||
|
return "no change";
|
||||||
|
case IF_OPER_DORMANT:
|
||||||
|
return "IF_OPER_DORMANT";
|
||||||
|
case IF_OPER_UP:
|
||||||
|
return "IF_OPER_UP";
|
||||||
|
}
|
||||||
|
return "?";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int netlink_send_oper_ifla(struct netlink_data *netlink, int ifindex,
|
int netlink_send_oper_ifla(struct netlink_data *netlink, int ifindex,
|
||||||
int linkmode, int operstate)
|
int linkmode, int operstate)
|
||||||
{
|
{
|
||||||
|
@ -184,8 +213,9 @@ int netlink_send_oper_ifla(struct netlink_data *netlink, int ifindex,
|
||||||
RTA_LENGTH(sizeof(char));
|
RTA_LENGTH(sizeof(char));
|
||||||
}
|
}
|
||||||
|
|
||||||
wpa_printf(MSG_DEBUG, "netlink: Operstate: linkmode=%d, operstate=%d",
|
wpa_printf(MSG_DEBUG, "netlink: Operstate: ifindex=%d linkmode=%d (%s), operstate=%d (%s)",
|
||||||
linkmode, operstate);
|
ifindex, linkmode, linkmode_str(linkmode),
|
||||||
|
operstate, operstate_str(operstate));
|
||||||
|
|
||||||
ret = send(netlink->sock, &req, req.hdr.nlmsg_len, 0);
|
ret = send(netlink->sock, &req, req.hdr.nlmsg_len, 0);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
|
|
|
@ -69,6 +69,7 @@
|
||||||
(struct rtattr *) (((char *)(rta)) + RTA_ALIGN((rta)->rta_len)))
|
(struct rtattr *) (((char *)(rta)) + RTA_ALIGN((rta)->rta_len)))
|
||||||
#define RTA_LENGTH(len) (RTA_ALIGN(sizeof(struct rtattr)) + (len))
|
#define RTA_LENGTH(len) (RTA_ALIGN(sizeof(struct rtattr)) + (len))
|
||||||
#define RTA_DATA(rta) ((void *) (((char *) (rta)) + RTA_LENGTH(0)))
|
#define RTA_DATA(rta) ((void *) (((char *) (rta)) + RTA_LENGTH(0)))
|
||||||
|
#define RTA_PAYLOAD(rta) ((int) ((rta)->rta_len) - RTA_LENGTH(0))
|
||||||
|
|
||||||
|
|
||||||
struct sockaddr_nl
|
struct sockaddr_nl
|
||||||
|
|
Loading…
Reference in a new issue