diff --git a/CHANGELOG.md b/CHANGELOG.md index 5dff40c..461e6db 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,7 @@ * Log output now respects the [`NO_COLOR`](http://no-color.org/) environment variable. * network: `type` tag ([#380][380]). +* network: `type` and `kind` tags ([#380][380]). [96]: https://codeberg.org/dnkl/yambar/issues/96 [380]: https://codeberg.org/dnkl/yambar/issues/380 diff --git a/doc/yambar-modules-network.5.scd b/doc/yambar-modules-network.5.scd index eda6fd5..7e500f0 100644 --- a/doc/yambar-modules-network.5.scd +++ b/doc/yambar-modules-network.5.scd @@ -25,6 +25,12 @@ address per network interface. : string : Interface type (*ether*, *wlan*, *loopback*, or *ARPHRD_NNN*, where *N* is a number). +| kind +: string +: Interface kind. Empty for non-virtual interfaces. For virtual + interfaces, this value is taken from the _IFLA\_INFO\_KIND_ netlink + attribute. Examples of valid values are *bond*, *bridge*, *gre*, *tun* + and *veth*. | index : int : Network interface index diff --git a/modules/network.c b/modules/network.c index 8a05dd7..dfbd5da 100644 --- a/modules/network.c +++ b/modules/network.c @@ -53,7 +53,8 @@ struct af_addr { struct iface { char *name; - char *type; + char *type; /* ARPHRD_NNN */ + char *kind; /* IFLA_LINKINFO::IFLA_INFO_KIND */ uint32_t get_stats_seq_nr; @@ -106,6 +107,7 @@ free_iface(struct iface iface) { tll_free(iface.addrs); free(iface.ssid); + free(iface.kind); free(iface.type); free(iface.name); } @@ -211,6 +213,7 @@ content(struct module *mod) .tags = (struct tag *[]){ tag_new_string(mod, "name", iface->name), tag_new_string(mod, "type", iface->type), + tag_new_string(mod, "kind", iface->kind), tag_new_int(mod, "index", iface->index), tag_new_bool(mod, "carrier", iface->carrier), tag_new_string(mod, "state", state), @@ -225,7 +228,7 @@ content(struct module *mod) tag_new_float(mod, "dl-speed", iface->dl_speed), tag_new_float(mod, "ul-speed", iface->ul_speed), }, - .count = 15, + .count = 16, }; exposables[idx++] = m->label->instantiate(m->label, &tags); tag_set_destroy(&tags); @@ -553,6 +556,78 @@ send_nl80211_get_scan(struct private *m) return true; } +static bool +foreach_nlattr(struct module *mod, struct iface *iface, const struct genlmsghdr *genl, size_t len, + bool (*cb)(struct module *mod, struct iface *iface, uint16_t type, bool nested, const void *payload, + size_t len, void *ctx), + void *ctx) +{ + const uint8_t *raw = (const uint8_t *)genl + GENL_HDRLEN; + const uint8_t *end = (const uint8_t *)genl + len; + + for (const struct nlattr *attr = (const struct nlattr *)raw; raw < end; + raw += NLA_ALIGN(attr->nla_len), attr = (const struct nlattr *)raw) { + uint16_t type = attr->nla_type & NLA_TYPE_MASK; + bool nested = (attr->nla_type & NLA_F_NESTED) != 0; + ; + const void *payload = raw + NLA_HDRLEN; + + if (!cb(mod, iface, type, nested, payload, attr->nla_len - NLA_HDRLEN, ctx)) + return false; + } + + return true; +} + +static bool +foreach_nlattr_nested(struct module *mod, struct iface *iface, const void *parent_payload, size_t len, + bool (*cb)(struct module *mod, struct iface *iface, uint16_t type, bool nested, + const void *payload, size_t len, void *ctx), + void *ctx) +{ + const uint8_t *raw = parent_payload; + const uint8_t *end = parent_payload + len; + + for (const struct nlattr *attr = (const struct nlattr *)raw; raw < end; + raw += NLA_ALIGN(attr->nla_len), attr = (const struct nlattr *)raw) { + uint16_t type = attr->nla_type & NLA_TYPE_MASK; + bool nested = (attr->nla_type & NLA_F_NESTED) != 0; + const void *payload = raw + NLA_HDRLEN; + + if (!cb(mod, iface, type, nested, payload, attr->nla_len - NLA_HDRLEN, ctx)) + return false; + } + + return true; +} + +static bool +parse_linkinfo(struct module *mod, struct iface *iface, uint16_t type, + bool nested, const void *payload, size_t len, void *_void) +{ + switch (type) { + case IFLA_INFO_KIND: { + const char *kind = payload; + free(iface->kind); + iface->kind = strndup(kind, len); + + LOG_DBG("%s: IFLA_INFO_KIND: %s", iface->name, iface->kind); + break; + } + + case IFLA_INFO_DATA: + //LOG_DBG("%s: IFLA_INFO_DATA", iface->name); + break; + + default: + LOG_WARN("unrecognized IFLA_LINKINFO attribute: " + "type=%hu, nested=%d, len=%zu", + type, nested, len); + break; + } + + return true; +} static void handle_link(struct module *mod, uint16_t type, const struct ifinfomsg *msg, size_t len) @@ -661,7 +736,8 @@ handle_link(struct module *mod, uint16_t type, const struct ifinfomsg *msg, size if (memcmp(iface->mac, mac, sizeof(iface->mac)) == 0) break; - LOG_DBG("%s: IFLA_ADDRESS: %02x:%02x:%02x:%02x:%02x:%02x", iface->name, mac[0], mac[1], mac[2], mac[3], + LOG_DBG("%s: IFLA_ADDRESS: %02x:%02x:%02x:%02x:%02x:%02x", + iface->name, mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); mtx_lock(&mod->lock); @@ -669,6 +745,13 @@ handle_link(struct module *mod, uint16_t type, const struct ifinfomsg *msg, size mtx_unlock(&mod->lock); break; } + + case IFLA_LINKINFO: { + foreach_nlattr_nested( + mod, iface, RTA_DATA(attr), RTA_PAYLOAD(attr), + &parse_linkinfo, NULL); + break; + } } } @@ -751,51 +834,6 @@ handle_address(struct module *mod, uint16_t type, const struct ifaddrmsg *msg, s mod->bar->refresh(mod->bar); } -static bool -foreach_nlattr(struct module *mod, struct iface *iface, const struct genlmsghdr *genl, size_t len, - bool (*cb)(struct module *mod, struct iface *iface, uint16_t type, bool nested, const void *payload, - size_t len, void *ctx), - void *ctx) -{ - const uint8_t *raw = (const uint8_t *)genl + GENL_HDRLEN; - const uint8_t *end = (const uint8_t *)genl + len; - - for (const struct nlattr *attr = (const struct nlattr *)raw; raw < end; - raw += NLA_ALIGN(attr->nla_len), attr = (const struct nlattr *)raw) { - uint16_t type = attr->nla_type & NLA_TYPE_MASK; - bool nested = (attr->nla_type & NLA_F_NESTED) != 0; - ; - const void *payload = raw + NLA_HDRLEN; - - if (!cb(mod, iface, type, nested, payload, attr->nla_len - NLA_HDRLEN, ctx)) - return false; - } - - return true; -} - -static bool -foreach_nlattr_nested(struct module *mod, struct iface *iface, const void *parent_payload, size_t len, - bool (*cb)(struct module *mod, struct iface *iface, uint16_t type, bool nested, - const void *payload, size_t len, void *ctx), - void *ctx) -{ - const uint8_t *raw = parent_payload; - const uint8_t *end = parent_payload + len; - - for (const struct nlattr *attr = (const struct nlattr *)raw; raw < end; - raw += NLA_ALIGN(attr->nla_len), attr = (const struct nlattr *)raw) { - uint16_t type = attr->nla_type & NLA_TYPE_MASK; - bool nested = (attr->nla_type & NLA_F_NESTED) != 0; - const void *payload = raw + NLA_HDRLEN; - - if (!cb(mod, iface, type, nested, payload, attr->nla_len - NLA_HDRLEN, ctx)) - return false; - } - - return true; -} - struct mcast_group { uint32_t id; const char *name;