summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/rt_names.h2
-rw-r--r--ip/ip_common.h2
-rw-r--r--ip/ipaddress.c34
-rw-r--r--lib/rt_names.c62
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",