summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Ahern <dsahern@kernel.org>2023-03-30 09:57:02 -0600
committerDavid Ahern <dsahern@kernel.org>2023-03-30 09:57:02 -0600
commit9d3bb8da961846820514ff73f630ed52ed018d36 (patch)
tree9975a91e2350eb2f28bd75bb40315f5c19f9d1fc
parente8a3fb470b4e96aa35a2731c7cc175b946c0a62d (diff)
parent1fbb61058d34e3eb9a34f5e930bbbb8d90c4a961 (diff)
downloadiproute2-9d3bb8da961846820514ff73f630ed52ed018d36.tar.gz
Merge branch 'ip-addr-proto' into next
Petr Machata says: ==================== IPv4 and IPv6 addresses can be assigned a protocol value that indicates the provenance of the IP address. The attribute is modeled after ip route protocols, and essentially allows the administrator or userspace stack to tag addresses in some way that makes sense to the actor in question. Support for this feature was merged with commit 47f0bd503210 ("net: Add new protocol attribute to IP addresses"), for kernel 5.18. In this patchset, add support for setting the protocol attribute at IP address addition, replacement, and listing requests. ==================== Signed-off-by: David Ahern <dsahern@kernel.org>
-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
-rw-r--r--man/man8/ip-address.8.in49
5 files changed, 145 insertions, 4 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",
diff --git a/man/man8/ip-address.8.in b/man/man8/ip-address.8.in
index 1846252d..abdd6a20 100644
--- a/man/man8/ip-address.8.in
+++ b/man/man8/ip-address.8.in
@@ -50,7 +50,9 @@ ip-address \- protocol address management
.B vrf
.IR NAME " ] [ "
.BR up " ] ["
-.BR nomaster " ] ]"
+.BR nomaster " ]"
+.B proto
+.IR ADDRPROTO " ] ]"
.ti -8
.BR "ip address" " { " showdump " | " restore " }"
@@ -66,7 +68,9 @@ ip-address \- protocol address management
.B label
.IR LABEL " ] [ "
.B scope
-.IR SCOPE-ID " ]"
+.IR SCOPE-ID " ] [ "
+.B proto
+.IR ADDRPROTO " ]"
.ti -8
.IR SCOPE-ID " := "
@@ -74,6 +78,10 @@ ip-address \- protocol address management
.IR NUMBER " ]"
.ti -8
+.IR ADDRPROTO " := [ "
+.IR NAME " | " NUMBER " ]"
+
+.ti -8
.IR FLAG-LIST " := [ " FLAG-LIST " ] " FLAG
.ti -8
@@ -288,6 +296,36 @@ flag when adding a multicast address enables similar functionality for
Openvswitch VXLAN interfaces as well as other tunneling mechanisms that need to
receive multicast traffic.
+.TP
+.BI proto " ADDRPROTO"
+the protocol identifier of this route.
+.I ADDRPROTO
+may be a number or a string from the file
+.BR "/etc/iproute2/rt_addrprotos" .
+If the protocol ID is not given,
+
+.B ip assumes protocol 0. Several protocol
+values have a fixed interpretation. Namely:
+
+.in +8
+.B kernel_lo
+- The ::1 address that kernel installs on a loopback netdevice has this
+ protocol value
+.sp
+
+.B kernel_ra
+- IPv6 addresses installed in response to router advertisement messages
+.sp
+
+.B kernel_ll
+- Link-local addresses have this protocol value
+.sp
+.in -8
+
+.sp
+The rest of the values are not reserved and the administrator is free
+to assign (or not to assign) protocol tags.
+
.SS ip address delete - delete protocol address
.B Arguments:
coincide with the arguments of
@@ -400,6 +438,13 @@ inverse of
This is an alias for
.BR temporary " or " secondary .
+.TP
+.BI proto " ADDRPROTO"
+Only show addresses with a given protocol, or those for which the kernel
+response did not include protocol. See the corresponding argument to
+.B ip addr add
+for details about address protocols.
+
.SS ip address flush - flush protocol addresses
This command flushes the protocol addresses selected by some criteria.