diff --git a/man/networkctl.xml b/man/networkctl.xml index 809eb7ec6a..d4fa5e9029 100644 --- a/man/networkctl.xml +++ b/man/networkctl.xml @@ -172,14 +172,40 @@ s - Service VLAN, m - Two-port MAC Relay (TPMR) 1 neighbors listed. + + + + label + + + Show numerical address labels that can be used for address selection. + This is the same information that + ip-addrlabel8 + shows. See RFC 3484 + for a discussion of address labels. + + Produces output similar to: + Prefix/Prefixlen Label + ::/0 1 + fc00::/7 5 + fec0::/10 11 + 2002::/16 2 + 3ffe::/16 12 + 2001:10::/28 7 + 2001::/32 6 +::ffff:0.0.0.0/96 4 + ::/96 3 + ::1/128 0 + + + Exit status - On success, 0 is returned, a non-zero failure - code otherwise. + On success, 0 is returned, a non-zero failure code otherwise. @@ -187,7 +213,8 @@ s - Service VLAN, m - Two-port MAC Relay (TPMR) systemd-networkd.service8, systemd.network5, - systemd.netdev5 + systemd.netdev5, + ip8 diff --git a/shell-completion/bash/networkctl b/shell-completion/bash/networkctl index 942c7e1c00..68e3338471 100644 --- a/shell-completion/bash/networkctl +++ b/shell-completion/bash/networkctl @@ -36,7 +36,7 @@ _networkctl() { ) local -A VERBS=( - [STANDALONE]='list lldp' + [STANDALONE]='list lldp label' [LINKS]='status' ) diff --git a/shell-completion/zsh/_networkctl b/shell-completion/zsh/_networkctl index 61f173b78e..acf7463edb 100644 --- a/shell-completion/zsh/_networkctl +++ b/shell-completion/zsh/_networkctl @@ -6,6 +6,7 @@ _networkctl_command(){ 'list:List existing links' 'status:Show information about the specified links' 'lldp:Show Link Layer Discovery Protocol status' + 'label:Show address labels' ) if (( CURRENT == 1 )); then _describe -t commands 'networkctl command' _networkctl_cmds diff --git a/src/libsystemd/sd-netlink/netlink-message.c b/src/libsystemd/sd-netlink/netlink-message.c index 654a22fe3b..e8c8abac2a 100644 --- a/src/libsystemd/sd-netlink/netlink-message.c +++ b/src/libsystemd/sd-netlink/netlink-message.c @@ -104,7 +104,8 @@ int sd_netlink_message_request_dump(sd_netlink_message *m, int dump) { assert_return(m->hdr->nlmsg_type == RTM_GETLINK || m->hdr->nlmsg_type == RTM_GETADDR || m->hdr->nlmsg_type == RTM_GETROUTE || - m->hdr->nlmsg_type == RTM_GETNEIGH, + m->hdr->nlmsg_type == RTM_GETNEIGH || + m->hdr->nlmsg_type == RTM_GETADDRLABEL , -EINVAL); SET_FLAG(m->hdr->nlmsg_flags, NLM_F_DUMP, dump); diff --git a/src/libsystemd/sd-netlink/rtnl-message.c b/src/libsystemd/sd-netlink/rtnl-message.c index d5f8b7d15e..12c51ffe2e 100644 --- a/src/libsystemd/sd-netlink/rtnl-message.c +++ b/src/libsystemd/sd-netlink/rtnl-message.c @@ -740,3 +740,17 @@ int sd_rtnl_message_addrlabel_set_prefixlen(sd_netlink_message *m, unsigned char return 0; } + +int sd_rtnl_message_addrlabel_get_prefixlen(sd_netlink_message *m, unsigned char *prefixlen) { + struct ifaddrlblmsg *addrlabel; + + assert_return(m, -EINVAL); + assert_return(m->hdr, -EINVAL); + assert_return(rtnl_message_type_is_addrlabel(m->hdr->nlmsg_type), -EINVAL); + + addrlabel = NLMSG_DATA(m->hdr); + + *prefixlen = addrlabel->ifal_prefixlen; + + return 0; +} diff --git a/src/network/networkctl.c b/src/network/networkctl.c index 6f7f41bf7d..54d54c8fd5 100644 --- a/src/network/networkctl.c +++ b/src/network/networkctl.c @@ -18,6 +18,7 @@ ***/ #include +#include #include #include @@ -35,6 +36,7 @@ #include "hwdb-util.h" #include "local-addresses.h" #include "locale-util.h" +#include "macro.h" #include "netlink-util.h" #include "pager.h" #include "parse-util.h" @@ -569,6 +571,76 @@ static int dump_addresses( return 0; } +static int dump_address_labels(sd_netlink *rtnl) { + _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL, *reply = NULL; + sd_netlink_message *m; + int r; + + assert(rtnl); + + r = sd_rtnl_message_new_addrlabel(rtnl, &req, RTM_GETADDRLABEL, 0, AF_INET6); + if (r < 0) + return log_error_errno(r, "Could not allocate RTM_GETADDRLABEL message: %m"); + + r = sd_netlink_message_request_dump(req, true); + if (r < 0) + return r; + + r = sd_netlink_call(rtnl, req, 0, &reply); + if (r < 0) + return r; + + printf("%10s/%s %30s\n", "Prefix", "Prefixlen", "Label"); + + for (m = reply; m; m = sd_netlink_message_next(m)) { + _cleanup_free_ char *pretty = NULL; + union in_addr_union prefix = {}; + uint8_t prefixlen; + uint32_t label; + + r = sd_netlink_message_get_errno(m); + if (r < 0) { + log_error_errno(r, "got error: %m"); + continue; + } + + r = sd_netlink_message_read_u32(m, IFAL_LABEL, &label); + if (r < 0 && r != -ENODATA) { + log_error_errno(r, "Could not read IFAL_LABEL, ignoring: %m"); + continue; + } + + r = sd_netlink_message_read_in6_addr(m, IFAL_ADDRESS, &prefix.in6); + if (r < 0) + continue; + + r = in_addr_to_string(AF_INET6, &prefix, &pretty); + if (r < 0) + continue; + + r = sd_rtnl_message_addrlabel_get_prefixlen(m, &prefixlen); + if (r < 0) + continue; + + printf("%10s/%-5u %30u\n", pretty, prefixlen, label); + } + + return 0; +} + +static int list_address_labels(int argc, char *argv[], void *userdata) { + _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL; + int r; + + r = sd_netlink_open(&rtnl); + if (r < 0) + return log_error_errno(r, "Failed to connect to netlink: %m"); + + dump_address_labels(rtnl); + + return 0; +} + static int open_lldp_neighbors(int ifindex, FILE **ret) { _cleanup_free_ char *p = NULL; FILE *f; @@ -1043,6 +1115,7 @@ static void help(void) { " list [LINK...] List links\n" " status [LINK...] Show link status\n" " lldp [LINK...] Show LLDP neighbors\n" + " label Show current address label entries in the kernel\n" , program_invocation_short_name); } @@ -1107,6 +1180,7 @@ static int networkctl_main(int argc, char *argv[]) { { "list", VERB_ANY, VERB_ANY, VERB_DEFAULT, list_links }, { "status", VERB_ANY, VERB_ANY, 0, link_status }, { "lldp", VERB_ANY, VERB_ANY, 0, link_lldp_status }, + { "label", VERB_ANY, VERB_ANY, 0, list_address_labels}, {} }; diff --git a/src/systemd/sd-netlink.h b/src/systemd/sd-netlink.h index aa39e0a0db..3f5a6673cf 100644 --- a/src/systemd/sd-netlink.h +++ b/src/systemd/sd-netlink.h @@ -157,6 +157,7 @@ int sd_rtnl_message_neigh_get_flags(sd_netlink_message *m, uint8_t *flags); int sd_rtnl_message_new_addrlabel(sd_netlink *rtnl, sd_netlink_message **ret, uint16_t nlmsg_type, int ifindex, int ifal_family); int sd_rtnl_message_addrlabel_set_prefixlen(sd_netlink_message *m, unsigned char prefixlen); +int sd_rtnl_message_addrlabel_get_prefixlen(sd_netlink_message *m, unsigned char *prefixlen); _SD_DEFINE_POINTER_CLEANUP_FUNC(sd_netlink, sd_netlink_unref); _SD_DEFINE_POINTER_CLEANUP_FUNC(sd_netlink_message, sd_netlink_message_unref);