diff options
-rw-r--r-- | include/rt_names.h | 2 | ||||
-rw-r--r-- | ip/ip_common.h | 2 | ||||
-rw-r--r-- | ip/ipaddress.c | 34 | ||||
-rw-r--r-- | lib/rt_names.c | 62 |
4 files changed, 98 insertions, 2 deletions
diff --git a/include/rt_names.h b/include/rt_names.h index 6358650d..e96d80f3 100644 --- a/include/rt_names.h +++ b/include/rt_names.h @@ -5,6 +5,7 @@ #include <asm/types.h> const char *rtnl_rtprot_n2a(int id, char *buf, int len); +const char *rtnl_addrprot_n2a(int id, char *buf, int len); const char *rtnl_rtscope_n2a(int id, char *buf, int len); const char *rtnl_rttable_n2a(__u32 id, char *buf, int len); const char *rtnl_rtrealm_n2a(int id, char *buf, int len); @@ -13,6 +14,7 @@ const char *rtnl_dsfield_get_name(int id); const char *rtnl_group_n2a(int id, char *buf, int len); int rtnl_rtprot_a2n(__u32 *id, const char *arg); +int rtnl_addrprot_a2n(__u32 *id, const char *arg); int rtnl_rtscope_a2n(__u32 *id, const char *arg); int rtnl_rttable_a2n(__u32 *id, const char *arg); int rtnl_rtrealm_a2n(__u32 *id, const char *arg); diff --git a/ip/ip_common.h b/ip/ip_common.h index c4cb1bcb..4a20ec3c 100644 --- a/ip/ip_common.h +++ b/ip/ip_common.h @@ -28,6 +28,8 @@ struct link_filter { char *kind; char *slave_kind; int target_nsid; + bool have_proto; + int proto; }; const char *get_ip_lib_dir(void); diff --git a/ip/ipaddress.c b/ip/ipaddress.c index 9ba81438..41055c43 100644 --- a/ip/ipaddress.c +++ b/ip/ipaddress.c @@ -57,11 +57,13 @@ static void usage(void) " ip address [ show [ dev IFNAME ] [ scope SCOPE-ID ] [ master DEVICE ]\n" " [ nomaster ]\n" " [ type TYPE ] [ to PREFIX ] [ FLAG-LIST ]\n" - " [ label LABEL ] [up] [ vrf NAME ] ]\n" + " [ label LABEL ] [up] [ vrf NAME ]\n" + " [ proto ADDRPROTO ] ]\n" " ip address {showdump|restore}\n" "IFADDR := PREFIX | ADDR peer PREFIX\n" " [ broadcast ADDR ] [ anycast ADDR ]\n" " [ label IFNAME ] [ scope SCOPE-ID ] [ metric METRIC ]\n" + " [ proto ADDRPROTO ]\n" "SCOPE-ID := [ host | link | global | NUMBER ]\n" "FLAG-LIST := [ FLAG-LIST ] FLAG\n" "FLAG := [ permanent | dynamic | secondary | primary |\n" @@ -70,7 +72,9 @@ static void usage(void) "CONFFLAG-LIST := [ CONFFLAG-LIST ] CONFFLAG\n" "CONFFLAG := [ home | nodad | mngtmpaddr | noprefixroute | autojoin ]\n" "LIFETIME := [ valid_lft LFT ] [ preferred_lft LFT ]\n" - "LFT := forever | SECONDS\n"); + "LFT := forever | SECONDS\n" + "ADDRPROTO := [ NAME | NUMBER ]\n" + ); iplink_types_usage(); exit(-1); @@ -1568,6 +1572,9 @@ int print_addrinfo(struct nlmsghdr *n, void *arg) if (filter.family && filter.family != ifa->ifa_family) return 0; + if (filter.have_proto && rta_tb[IFA_PROTO] && + filter.proto != rta_getattr_u8(rta_tb[IFA_PROTO])) + return 0; if (ifa_label_match_rta(ifa->ifa_index, rta_tb[IFA_LABEL])) return 0; @@ -1675,6 +1682,14 @@ int print_addrinfo(struct nlmsghdr *n, void *arg) print_ifa_flags(fp, ifa, ifa_flags); + if (rta_tb[IFA_PROTO]) { + __u8 proto = rta_getattr_u8(rta_tb[IFA_PROTO]); + + if (proto || is_json_context()) + print_string(PRINT_ANY, "protocol", "proto %s ", + rtnl_addrprot_n2a(proto, b1, sizeof(b1))); + } + if (rta_tb[IFA_LABEL]) print_string(PRINT_ANY, "label", @@ -2196,6 +2211,14 @@ static int ipaddr_list_flush_or_save(int argc, char **argv, int action) } else { filter.kind = *argv; } + } else if (strcmp(*argv, "proto") == 0) { + __u8 proto; + + NEXT_ARG(); + if (get_u8(&proto, *argv, 0)) + invarg("\"proto\" value is invalid\n", *argv); + filter.have_proto = true; + filter.proto = proto; } else { if (strcmp(*argv, "dev") == 0) NEXT_ARG(); @@ -2520,6 +2543,13 @@ static int ipaddr_modify(int cmd, int flags, int argc, char **argv) } else { ifa_flags |= flag_data->mask; } + } else if (strcmp(*argv, "proto") == 0) { + __u8 proto; + + NEXT_ARG(); + if (get_u8(&proto, *argv, 0)) + invarg("\"proto\" value is invalid\n", *argv); + addattr8(&req.n, sizeof(req), IFA_PROTO, proto); } else { if (strcmp(*argv, "local") == 0) NEXT_ARG(); diff --git a/lib/rt_names.c b/lib/rt_names.c index 2432224a..51d11fd0 100644 --- a/lib/rt_names.c +++ b/lib/rt_names.c @@ -226,6 +226,68 @@ int rtnl_rtprot_a2n(__u32 *id, const char *arg) } +static char *rtnl_addrprot_tab[256] = { + [IFAPROT_UNSPEC] = "unspec", + [IFAPROT_KERNEL_LO] = "kernel_lo", + [IFAPROT_KERNEL_RA] = "kernel_ra", + [IFAPROT_KERNEL_LL] = "kernel_ll", +}; +static bool rtnl_addrprot_tab_initialized; + +static void rtnl_addrprot_initialize(void) +{ + rtnl_tab_initialize(CONFDIR "/rt_addrprotos", + rtnl_addrprot_tab, + ARRAY_SIZE(rtnl_addrprot_tab)); + rtnl_addrprot_tab_initialized = true; +} + +const char *rtnl_addrprot_n2a(int id, char *buf, int len) +{ + if (id < 0 || id >= 256 || numeric) + goto numeric; + if (!rtnl_addrprot_tab_initialized) + rtnl_addrprot_initialize(); + if (rtnl_addrprot_tab[id]) + return rtnl_addrprot_tab[id]; +numeric: + snprintf(buf, len, "%#x", id); + return buf; +} + +int rtnl_addrprot_a2n(__u32 *id, const char *arg) +{ + static char *cache; + static unsigned long res; + char *end; + int i; + + if (cache && strcmp(cache, arg) == 0) { + *id = res; + return 0; + } + + if (!rtnl_addrprot_tab_initialized) + rtnl_addrprot_initialize(); + + for (i = 0; i < 256; i++) { + if (rtnl_addrprot_tab[i] && + strcmp(rtnl_addrprot_tab[i], arg) == 0) { + cache = rtnl_addrprot_tab[i]; + res = i; + *id = res; + return 0; + } + } + + res = strtoul(arg, &end, 0); + if (!end || end == arg || *end || res > 255) + return -1; + *id = res; + return 0; +} + + static char *rtnl_rtscope_tab[256] = { [RT_SCOPE_UNIVERSE] = "global", [RT_SCOPE_NOWHERE] = "nowhere", |