2023-01-11 10:43:18 +08:00
|
|
|
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
2004-04-16 04:56:59 +08:00
|
|
|
/*
|
|
|
|
* rt_names.c rtnetlink names DB.
|
|
|
|
*
|
|
|
|
* Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
#include <fcntl.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <sys/time.h>
|
2004-06-09 07:50:43 +08:00
|
|
|
#include <sys/socket.h>
|
2023-07-26 14:14:09 +08:00
|
|
|
#include <sys/stat.h>
|
2015-11-25 05:20:01 +08:00
|
|
|
#include <dirent.h>
|
2016-01-22 02:19:48 +08:00
|
|
|
#include <limits.h>
|
2023-07-26 14:14:09 +08:00
|
|
|
#include <errno.h>
|
2004-06-09 07:50:43 +08:00
|
|
|
|
|
|
|
#include <asm/types.h>
|
|
|
|
#include <linux/rtnetlink.h>
|
|
|
|
|
|
|
|
#include "rt_names.h"
|
2015-11-26 22:38:44 +08:00
|
|
|
#include "utils.h"
|
2012-03-01 14:44:43 +08:00
|
|
|
|
2014-12-06 10:05:12 +08:00
|
|
|
#define NAME_MAX_LEN 512
|
|
|
|
|
2019-06-12 17:21:15 +08:00
|
|
|
int numeric;
|
|
|
|
|
2006-08-11 06:14:50 +08:00
|
|
|
struct rtnl_hash_entry {
|
2015-11-30 03:41:23 +08:00
|
|
|
struct rtnl_hash_entry *next;
|
|
|
|
const char *name;
|
2006-08-11 06:14:50 +08:00
|
|
|
unsigned int id;
|
|
|
|
};
|
|
|
|
|
2014-12-06 10:05:12 +08:00
|
|
|
static int fread_id_name(FILE *fp, int *id, char *namebuf)
|
|
|
|
{
|
|
|
|
char buf[NAME_MAX_LEN];
|
|
|
|
|
|
|
|
while (fgets(buf, sizeof(buf), fp)) {
|
|
|
|
char *p = buf;
|
|
|
|
|
|
|
|
while (*p == ' ' || *p == '\t')
|
|
|
|
p++;
|
|
|
|
|
|
|
|
if (*p == '#' || *p == '\n' || *p == 0)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (sscanf(p, "0x%x %s\n", id, namebuf) != 2 &&
|
|
|
|
sscanf(p, "0x%x %s #", id, namebuf) != 2 &&
|
|
|
|
sscanf(p, "%d %s\n", id, namebuf) != 2 &&
|
|
|
|
sscanf(p, "%d %s #", id, namebuf) != 2) {
|
|
|
|
strcpy(namebuf, p);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2023-07-26 14:14:09 +08:00
|
|
|
static int
|
2013-02-13 03:39:07 +08:00
|
|
|
rtnl_hash_initialize(const char *file, struct rtnl_hash_entry **hash, int size)
|
2006-08-11 06:14:50 +08:00
|
|
|
{
|
|
|
|
struct rtnl_hash_entry *entry;
|
|
|
|
FILE *fp;
|
2014-12-06 10:05:12 +08:00
|
|
|
int id;
|
|
|
|
char namebuf[NAME_MAX_LEN] = {0};
|
|
|
|
int ret;
|
2006-08-11 06:14:50 +08:00
|
|
|
|
|
|
|
fp = fopen(file, "r");
|
|
|
|
if (!fp)
|
2023-07-26 14:14:09 +08:00
|
|
|
return -errno;
|
2006-08-11 06:14:50 +08:00
|
|
|
|
2014-12-06 10:05:12 +08:00
|
|
|
while ((ret = fread_id_name(fp, &id, &namebuf[0]))) {
|
|
|
|
if (ret == -1) {
|
2006-08-11 06:14:50 +08:00
|
|
|
fprintf(stderr, "Database %s is corrupted at %s\n",
|
2014-12-06 10:05:12 +08:00
|
|
|
file, namebuf);
|
2011-10-03 13:22:42 +08:00
|
|
|
fclose(fp);
|
2023-07-26 14:14:09 +08:00
|
|
|
return -EINVAL;
|
2006-08-11 06:14:50 +08:00
|
|
|
}
|
|
|
|
|
2015-11-30 03:41:23 +08:00
|
|
|
if (id < 0)
|
2006-08-11 06:14:50 +08:00
|
|
|
continue;
|
2014-12-06 10:05:12 +08:00
|
|
|
|
2006-08-11 06:14:50 +08:00
|
|
|
entry = malloc(sizeof(*entry));
|
2023-06-08 09:33:49 +08:00
|
|
|
if (entry == NULL) {
|
|
|
|
fprintf(stderr, "malloc error: for entry\n");
|
|
|
|
break;
|
|
|
|
}
|
2006-08-11 06:14:50 +08:00
|
|
|
entry->id = id;
|
|
|
|
entry->name = strdup(namebuf);
|
|
|
|
entry->next = hash[id & (size - 1)];
|
|
|
|
hash[id & (size - 1)] = entry;
|
|
|
|
}
|
|
|
|
fclose(fp);
|
2023-07-26 14:14:09 +08:00
|
|
|
|
|
|
|
return 0;
|
2006-08-11 06:14:50 +08:00
|
|
|
}
|
|
|
|
|
2023-07-26 14:14:09 +08:00
|
|
|
static int rtnl_tab_initialize(const char *file, char **tab, int size)
|
2004-04-16 04:56:59 +08:00
|
|
|
{
|
|
|
|
FILE *fp;
|
2014-12-06 10:05:12 +08:00
|
|
|
int id;
|
|
|
|
char namebuf[NAME_MAX_LEN] = {0};
|
|
|
|
int ret;
|
2004-04-16 04:56:59 +08:00
|
|
|
|
|
|
|
fp = fopen(file, "r");
|
|
|
|
if (!fp)
|
2023-07-26 14:14:09 +08:00
|
|
|
return -errno;
|
2004-04-16 04:56:59 +08:00
|
|
|
|
2014-12-06 10:05:12 +08:00
|
|
|
while ((ret = fread_id_name(fp, &id, &namebuf[0]))) {
|
|
|
|
if (ret == -1) {
|
2004-04-16 04:56:59 +08:00
|
|
|
fprintf(stderr, "Database %s is corrupted at %s\n",
|
2014-12-06 10:05:12 +08:00
|
|
|
file, namebuf);
|
2011-10-03 13:22:42 +08:00
|
|
|
fclose(fp);
|
2023-07-26 14:14:09 +08:00
|
|
|
return -EINVAL;
|
2004-04-16 04:56:59 +08:00
|
|
|
}
|
2015-11-30 03:41:23 +08:00
|
|
|
if (id < 0 || id > size)
|
2004-04-16 04:56:59 +08:00
|
|
|
continue;
|
|
|
|
|
|
|
|
tab[id] = strdup(namebuf);
|
|
|
|
}
|
|
|
|
fclose(fp);
|
2023-07-26 14:14:09 +08:00
|
|
|
|
|
|
|
return 0;
|
2004-04-16 04:56:59 +08:00
|
|
|
}
|
|
|
|
|
2015-11-30 03:41:23 +08:00
|
|
|
static char *rtnl_rtprot_tab[256] = {
|
2020-06-25 00:21:25 +08:00
|
|
|
[RTPROT_UNSPEC] = "unspec",
|
|
|
|
[RTPROT_REDIRECT] = "redirect",
|
|
|
|
[RTPROT_KERNEL] = "kernel",
|
|
|
|
[RTPROT_BOOT] = "boot",
|
|
|
|
[RTPROT_STATIC] = "static",
|
|
|
|
|
|
|
|
[RTPROT_GATED] = "gated",
|
|
|
|
[RTPROT_RA] = "ra",
|
|
|
|
[RTPROT_MRT] = "mrt",
|
|
|
|
[RTPROT_ZEBRA] = "zebra",
|
|
|
|
[RTPROT_BIRD] = "bird",
|
|
|
|
[RTPROT_BABEL] = "babel",
|
|
|
|
[RTPROT_DNROUTED] = "dnrouted",
|
|
|
|
[RTPROT_XORP] = "xorp",
|
|
|
|
[RTPROT_NTK] = "ntk",
|
|
|
|
[RTPROT_DHCP] = "dhcp",
|
|
|
|
[RTPROT_KEEPALIVED] = "keepalived",
|
|
|
|
[RTPROT_BGP] = "bgp",
|
|
|
|
[RTPROT_ISIS] = "isis",
|
|
|
|
[RTPROT_OSPF] = "ospf",
|
|
|
|
[RTPROT_RIP] = "rip",
|
|
|
|
[RTPROT_EIGRP] = "eigrp",
|
2004-04-16 04:56:59 +08:00
|
|
|
};
|
|
|
|
|
2023-07-26 14:14:09 +08:00
|
|
|
struct tabhash {
|
|
|
|
enum { TAB, HASH } type;
|
|
|
|
union tab_or_hash {
|
|
|
|
char **tab;
|
|
|
|
struct rtnl_hash_entry **hash;
|
|
|
|
} data;
|
|
|
|
};
|
2004-04-16 04:56:59 +08:00
|
|
|
|
2023-07-26 14:14:09 +08:00
|
|
|
static void
|
|
|
|
rtnl_tabhash_readdir(const char *dirpath_base, const char *dirpath_overload,
|
2024-03-12 00:18:44 +08:00
|
|
|
const struct tabhash tabhash, const int size)
|
2004-04-16 04:56:59 +08:00
|
|
|
{
|
2017-01-10 07:43:09 +08:00
|
|
|
struct dirent *de;
|
|
|
|
DIR *d;
|
|
|
|
|
2023-07-26 14:14:09 +08:00
|
|
|
d = opendir(dirpath_base);
|
|
|
|
while (d && (de = readdir(d)) != NULL) {
|
2017-01-10 07:43:09 +08:00
|
|
|
char path[PATH_MAX];
|
|
|
|
size_t len;
|
2023-07-26 14:14:09 +08:00
|
|
|
struct stat sb;
|
2017-01-10 07:43:09 +08:00
|
|
|
|
|
|
|
if (*de->d_name == '.')
|
|
|
|
continue;
|
|
|
|
|
|
|
|
/* only consider filenames ending in '.conf' */
|
|
|
|
len = strlen(de->d_name);
|
|
|
|
if (len <= 5)
|
|
|
|
continue;
|
|
|
|
if (strcmp(de->d_name + len - 5, ".conf"))
|
|
|
|
continue;
|
|
|
|
|
2023-07-26 14:14:09 +08:00
|
|
|
if (dirpath_overload) {
|
|
|
|
/* only consider filenames not present in
|
|
|
|
the overloading directory, e.g. /etc */
|
|
|
|
snprintf(path, sizeof(path), "%s/%s", dirpath_overload, de->d_name);
|
|
|
|
if (lstat(path, &sb) == 0)
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* load the conf file in the base directory, e.g., /usr */
|
|
|
|
snprintf(path, sizeof(path), "%s/%s", dirpath_base, de->d_name);
|
|
|
|
if (tabhash.type == TAB)
|
|
|
|
rtnl_tab_initialize(path, tabhash.data.tab, size);
|
|
|
|
else
|
|
|
|
rtnl_hash_initialize(path, tabhash.data.hash, size);
|
2017-01-10 07:43:09 +08:00
|
|
|
}
|
2023-07-26 14:14:09 +08:00
|
|
|
if (d)
|
|
|
|
closedir(d);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
rtnl_tabhash_initialize_dir(const char *ddir, const struct tabhash tabhash, const int size)
|
|
|
|
{
|
|
|
|
char dirpath_usr[PATH_MAX], dirpath_etc[PATH_MAX];
|
|
|
|
|
|
|
|
snprintf(dirpath_usr, sizeof(dirpath_usr), "%s/%s", CONF_USR_DIR, ddir);
|
|
|
|
snprintf(dirpath_etc, sizeof(dirpath_etc), "%s/%s", CONF_ETC_DIR, ddir);
|
|
|
|
|
|
|
|
/* load /usr/lib/iproute2/foo.d/X conf files, unless /etc/iproute2/foo.d/X exists */
|
|
|
|
rtnl_tabhash_readdir(dirpath_usr, dirpath_etc, tabhash, size);
|
|
|
|
|
|
|
|
/* load /etc/iproute2/foo.d/X conf files */
|
|
|
|
rtnl_tabhash_readdir(dirpath_etc, NULL, tabhash, size);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2024-03-12 00:18:44 +08:00
|
|
|
rtnl_tab_initialize_dir(const char *ddir, char **tab, const int size)
|
|
|
|
{
|
2023-07-26 14:14:09 +08:00
|
|
|
struct tabhash tab_data = {.type = TAB, .data.tab = tab};
|
|
|
|
rtnl_tabhash_initialize_dir(ddir, tab_data, size);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
rtnl_hash_initialize_dir(const char *ddir, struct rtnl_hash_entry **hash,
|
2024-03-12 00:18:44 +08:00
|
|
|
const int size) {
|
2023-07-26 14:14:09 +08:00
|
|
|
struct tabhash hash_data = {.type = HASH, .data.hash = hash};
|
|
|
|
rtnl_tabhash_initialize_dir(ddir, hash_data, size);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int rtnl_rtprot_init;
|
|
|
|
|
|
|
|
static void rtnl_rtprot_initialize(void)
|
|
|
|
{
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
rtnl_rtprot_init = 1;
|
|
|
|
ret = rtnl_tab_initialize(CONF_ETC_DIR "/rt_protos",
|
2024-03-12 00:18:44 +08:00
|
|
|
rtnl_rtprot_tab, 256);
|
2023-07-26 14:14:09 +08:00
|
|
|
if (ret == -ENOENT)
|
|
|
|
rtnl_tab_initialize(CONF_USR_DIR "/rt_protos",
|
2024-03-12 00:18:44 +08:00
|
|
|
rtnl_rtprot_tab, 256);
|
2023-07-26 14:14:09 +08:00
|
|
|
|
|
|
|
rtnl_tab_initialize_dir("rt_protos.d", rtnl_rtprot_tab, 256);
|
2004-04-16 04:56:59 +08:00
|
|
|
}
|
|
|
|
|
2015-11-30 03:41:23 +08:00
|
|
|
const char *rtnl_rtprot_n2a(int id, char *buf, int len)
|
2004-04-16 04:56:59 +08:00
|
|
|
{
|
2019-06-12 17:21:15 +08:00
|
|
|
if (id < 0 || id >= 256 || numeric) {
|
2013-02-13 03:39:07 +08:00
|
|
|
snprintf(buf, len, "%u", id);
|
2004-04-16 04:56:59 +08:00
|
|
|
return buf;
|
|
|
|
}
|
|
|
|
if (!rtnl_rtprot_tab[id]) {
|
|
|
|
if (!rtnl_rtprot_init)
|
|
|
|
rtnl_rtprot_initialize();
|
|
|
|
}
|
|
|
|
if (rtnl_rtprot_tab[id])
|
|
|
|
return rtnl_rtprot_tab[id];
|
2013-02-13 03:39:07 +08:00
|
|
|
snprintf(buf, len, "%u", id);
|
2004-04-16 04:56:59 +08:00
|
|
|
return buf;
|
|
|
|
}
|
|
|
|
|
2013-02-13 03:39:07 +08:00
|
|
|
int rtnl_rtprot_a2n(__u32 *id, const char *arg)
|
2004-04-16 04:56:59 +08:00
|
|
|
{
|
2015-11-30 03:41:23 +08:00
|
|
|
static char *cache;
|
2004-04-16 04:56:59 +08:00
|
|
|
static unsigned long res;
|
|
|
|
char *end;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
if (cache && strcmp(cache, arg) == 0) {
|
|
|
|
*id = res;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!rtnl_rtprot_init)
|
|
|
|
rtnl_rtprot_initialize();
|
|
|
|
|
2015-11-30 03:41:23 +08:00
|
|
|
for (i = 0; i < 256; i++) {
|
2004-04-16 04:56:59 +08:00
|
|
|
if (rtnl_rtprot_tab[i] &&
|
|
|
|
strcmp(rtnl_rtprot_tab[i], arg) == 0) {
|
|
|
|
cache = rtnl_rtprot_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;
|
|
|
|
}
|
|
|
|
|
2015-11-30 03:41:23 +08:00
|
|
|
|
ip: Support IP address protocol
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 patch, add support for setting the protocol attribute at IP address
addition, replacement, and listing requests.
An example session with the feature in action:
# ip address add dev d 192.0.2.1/28 proto 0xab
# ip address show dev d
26: d: <BROADCAST,NOARP> mtu 1500 qdisc noop state DOWN group default qlen 1000
link/ether 06:29:74:fd:1f:eb brd ff:ff:ff:ff:ff:ff
inet 192.0.2.1/28 scope global proto 0xab d
valid_lft forever preferred_lft forever
# ip address replace dev d 192.0.2.1/28 proto 0x11
# ip address show dev d
26: d: <BROADCAST,NOARP> mtu 1500 qdisc noop state DOWN group default qlen 1000
link/ether 06:29:74:fd:1f:eb brd ff:ff:ff:ff:ff:ff
inet 192.0.2.1/28 scope global proto 0x11 d
valid_lft forever preferred_lft forever
A JSON dump. The protocol value is always provided as a string, even in
numeric mode, to provide a consistent interface.
# ip -j address show dev d | jq
[
{
"ifindex": 26,
"ifname": "d",
"flags": [
"BROADCAST",
"NOARP"
],
"mtu": 1500,
"qdisc": "noop",
"operstate": "DOWN",
"group": "default",
"txqlen": 1000,
"link_type": "ether",
"address": "06:29:74:fd:1f:eb",
"broadcast": "ff:ff:ff:ff:ff:ff",
"addr_info": [
{
"family": "inet",
"local": "192.0.2.1",
"prefixlen": 28,
"scope": "global",
"protocol": "0x11",
"label": "d",
"valid_life_time": 4294967295,
"preferred_life_time": 4294967295
}
]
}
]
Signed-off-by: Petr Machata <petrm@nvidia.com>
Signed-off-by: David Ahern <dsahern@kernel.org>
2023-03-28 00:12:05 +08:00
|
|
|
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)
|
|
|
|
{
|
2023-07-26 14:14:09 +08:00
|
|
|
int ret;
|
|
|
|
|
ip: Support IP address protocol
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 patch, add support for setting the protocol attribute at IP address
addition, replacement, and listing requests.
An example session with the feature in action:
# ip address add dev d 192.0.2.1/28 proto 0xab
# ip address show dev d
26: d: <BROADCAST,NOARP> mtu 1500 qdisc noop state DOWN group default qlen 1000
link/ether 06:29:74:fd:1f:eb brd ff:ff:ff:ff:ff:ff
inet 192.0.2.1/28 scope global proto 0xab d
valid_lft forever preferred_lft forever
# ip address replace dev d 192.0.2.1/28 proto 0x11
# ip address show dev d
26: d: <BROADCAST,NOARP> mtu 1500 qdisc noop state DOWN group default qlen 1000
link/ether 06:29:74:fd:1f:eb brd ff:ff:ff:ff:ff:ff
inet 192.0.2.1/28 scope global proto 0x11 d
valid_lft forever preferred_lft forever
A JSON dump. The protocol value is always provided as a string, even in
numeric mode, to provide a consistent interface.
# ip -j address show dev d | jq
[
{
"ifindex": 26,
"ifname": "d",
"flags": [
"BROADCAST",
"NOARP"
],
"mtu": 1500,
"qdisc": "noop",
"operstate": "DOWN",
"group": "default",
"txqlen": 1000,
"link_type": "ether",
"address": "06:29:74:fd:1f:eb",
"broadcast": "ff:ff:ff:ff:ff:ff",
"addr_info": [
{
"family": "inet",
"local": "192.0.2.1",
"prefixlen": 28,
"scope": "global",
"protocol": "0x11",
"label": "d",
"valid_life_time": 4294967295,
"preferred_life_time": 4294967295
}
]
}
]
Signed-off-by: Petr Machata <petrm@nvidia.com>
Signed-off-by: David Ahern <dsahern@kernel.org>
2023-03-28 00:12:05 +08:00
|
|
|
rtnl_addrprot_tab_initialized = true;
|
2023-07-26 14:14:09 +08:00
|
|
|
|
|
|
|
ret = rtnl_tab_initialize(CONF_ETC_DIR "/rt_addrprotos",
|
2024-03-12 00:18:44 +08:00
|
|
|
rtnl_addrprot_tab,
|
|
|
|
ARRAY_SIZE(rtnl_addrprot_tab));
|
2023-07-26 14:14:09 +08:00
|
|
|
if (ret == -ENOENT)
|
|
|
|
ret = rtnl_tab_initialize(CONF_USR_DIR "/rt_addrprotos",
|
2024-03-12 00:18:44 +08:00
|
|
|
rtnl_addrprot_tab,
|
|
|
|
ARRAY_SIZE(rtnl_addrprot_tab));
|
ip: Support IP address protocol
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 patch, add support for setting the protocol attribute at IP address
addition, replacement, and listing requests.
An example session with the feature in action:
# ip address add dev d 192.0.2.1/28 proto 0xab
# ip address show dev d
26: d: <BROADCAST,NOARP> mtu 1500 qdisc noop state DOWN group default qlen 1000
link/ether 06:29:74:fd:1f:eb brd ff:ff:ff:ff:ff:ff
inet 192.0.2.1/28 scope global proto 0xab d
valid_lft forever preferred_lft forever
# ip address replace dev d 192.0.2.1/28 proto 0x11
# ip address show dev d
26: d: <BROADCAST,NOARP> mtu 1500 qdisc noop state DOWN group default qlen 1000
link/ether 06:29:74:fd:1f:eb brd ff:ff:ff:ff:ff:ff
inet 192.0.2.1/28 scope global proto 0x11 d
valid_lft forever preferred_lft forever
A JSON dump. The protocol value is always provided as a string, even in
numeric mode, to provide a consistent interface.
# ip -j address show dev d | jq
[
{
"ifindex": 26,
"ifname": "d",
"flags": [
"BROADCAST",
"NOARP"
],
"mtu": 1500,
"qdisc": "noop",
"operstate": "DOWN",
"group": "default",
"txqlen": 1000,
"link_type": "ether",
"address": "06:29:74:fd:1f:eb",
"broadcast": "ff:ff:ff:ff:ff:ff",
"addr_info": [
{
"family": "inet",
"local": "192.0.2.1",
"prefixlen": 28,
"scope": "global",
"protocol": "0x11",
"label": "d",
"valid_life_time": 4294967295,
"preferred_life_time": 4294967295
}
]
}
]
Signed-off-by: Petr Machata <petrm@nvidia.com>
Signed-off-by: David Ahern <dsahern@kernel.org>
2023-03-28 00:12:05 +08:00
|
|
|
}
|
|
|
|
|
2023-06-02 23:51:53 +08:00
|
|
|
const char *rtnl_addrprot_n2a(__u8 id, char *buf, int len)
|
ip: Support IP address protocol
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 patch, add support for setting the protocol attribute at IP address
addition, replacement, and listing requests.
An example session with the feature in action:
# ip address add dev d 192.0.2.1/28 proto 0xab
# ip address show dev d
26: d: <BROADCAST,NOARP> mtu 1500 qdisc noop state DOWN group default qlen 1000
link/ether 06:29:74:fd:1f:eb brd ff:ff:ff:ff:ff:ff
inet 192.0.2.1/28 scope global proto 0xab d
valid_lft forever preferred_lft forever
# ip address replace dev d 192.0.2.1/28 proto 0x11
# ip address show dev d
26: d: <BROADCAST,NOARP> mtu 1500 qdisc noop state DOWN group default qlen 1000
link/ether 06:29:74:fd:1f:eb brd ff:ff:ff:ff:ff:ff
inet 192.0.2.1/28 scope global proto 0x11 d
valid_lft forever preferred_lft forever
A JSON dump. The protocol value is always provided as a string, even in
numeric mode, to provide a consistent interface.
# ip -j address show dev d | jq
[
{
"ifindex": 26,
"ifname": "d",
"flags": [
"BROADCAST",
"NOARP"
],
"mtu": 1500,
"qdisc": "noop",
"operstate": "DOWN",
"group": "default",
"txqlen": 1000,
"link_type": "ether",
"address": "06:29:74:fd:1f:eb",
"broadcast": "ff:ff:ff:ff:ff:ff",
"addr_info": [
{
"family": "inet",
"local": "192.0.2.1",
"prefixlen": 28,
"scope": "global",
"protocol": "0x11",
"label": "d",
"valid_life_time": 4294967295,
"preferred_life_time": 4294967295
}
]
}
]
Signed-off-by: Petr Machata <petrm@nvidia.com>
Signed-off-by: David Ahern <dsahern@kernel.org>
2023-03-28 00:12:05 +08:00
|
|
|
{
|
2023-06-02 23:51:53 +08:00
|
|
|
if (numeric)
|
ip: Support IP address protocol
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 patch, add support for setting the protocol attribute at IP address
addition, replacement, and listing requests.
An example session with the feature in action:
# ip address add dev d 192.0.2.1/28 proto 0xab
# ip address show dev d
26: d: <BROADCAST,NOARP> mtu 1500 qdisc noop state DOWN group default qlen 1000
link/ether 06:29:74:fd:1f:eb brd ff:ff:ff:ff:ff:ff
inet 192.0.2.1/28 scope global proto 0xab d
valid_lft forever preferred_lft forever
# ip address replace dev d 192.0.2.1/28 proto 0x11
# ip address show dev d
26: d: <BROADCAST,NOARP> mtu 1500 qdisc noop state DOWN group default qlen 1000
link/ether 06:29:74:fd:1f:eb brd ff:ff:ff:ff:ff:ff
inet 192.0.2.1/28 scope global proto 0x11 d
valid_lft forever preferred_lft forever
A JSON dump. The protocol value is always provided as a string, even in
numeric mode, to provide a consistent interface.
# ip -j address show dev d | jq
[
{
"ifindex": 26,
"ifname": "d",
"flags": [
"BROADCAST",
"NOARP"
],
"mtu": 1500,
"qdisc": "noop",
"operstate": "DOWN",
"group": "default",
"txqlen": 1000,
"link_type": "ether",
"address": "06:29:74:fd:1f:eb",
"broadcast": "ff:ff:ff:ff:ff:ff",
"addr_info": [
{
"family": "inet",
"local": "192.0.2.1",
"prefixlen": 28,
"scope": "global",
"protocol": "0x11",
"label": "d",
"valid_life_time": 4294967295,
"preferred_life_time": 4294967295
}
]
}
]
Signed-off-by: Petr Machata <petrm@nvidia.com>
Signed-off-by: David Ahern <dsahern@kernel.org>
2023-03-28 00:12:05 +08:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2023-06-02 23:51:53 +08:00
|
|
|
int rtnl_addrprot_a2n(__u8 *id, const char *arg)
|
ip: Support IP address protocol
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 patch, add support for setting the protocol attribute at IP address
addition, replacement, and listing requests.
An example session with the feature in action:
# ip address add dev d 192.0.2.1/28 proto 0xab
# ip address show dev d
26: d: <BROADCAST,NOARP> mtu 1500 qdisc noop state DOWN group default qlen 1000
link/ether 06:29:74:fd:1f:eb brd ff:ff:ff:ff:ff:ff
inet 192.0.2.1/28 scope global proto 0xab d
valid_lft forever preferred_lft forever
# ip address replace dev d 192.0.2.1/28 proto 0x11
# ip address show dev d
26: d: <BROADCAST,NOARP> mtu 1500 qdisc noop state DOWN group default qlen 1000
link/ether 06:29:74:fd:1f:eb brd ff:ff:ff:ff:ff:ff
inet 192.0.2.1/28 scope global proto 0x11 d
valid_lft forever preferred_lft forever
A JSON dump. The protocol value is always provided as a string, even in
numeric mode, to provide a consistent interface.
# ip -j address show dev d | jq
[
{
"ifindex": 26,
"ifname": "d",
"flags": [
"BROADCAST",
"NOARP"
],
"mtu": 1500,
"qdisc": "noop",
"operstate": "DOWN",
"group": "default",
"txqlen": 1000,
"link_type": "ether",
"address": "06:29:74:fd:1f:eb",
"broadcast": "ff:ff:ff:ff:ff:ff",
"addr_info": [
{
"family": "inet",
"local": "192.0.2.1",
"prefixlen": 28,
"scope": "global",
"protocol": "0x11",
"label": "d",
"valid_life_time": 4294967295,
"preferred_life_time": 4294967295
}
]
}
]
Signed-off-by: Petr Machata <petrm@nvidia.com>
Signed-off-by: David Ahern <dsahern@kernel.org>
2023-03-28 00:12:05 +08:00
|
|
|
{
|
2023-06-02 23:51:53 +08:00
|
|
|
unsigned long res;
|
ip: Support IP address protocol
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 patch, add support for setting the protocol attribute at IP address
addition, replacement, and listing requests.
An example session with the feature in action:
# ip address add dev d 192.0.2.1/28 proto 0xab
# ip address show dev d
26: d: <BROADCAST,NOARP> mtu 1500 qdisc noop state DOWN group default qlen 1000
link/ether 06:29:74:fd:1f:eb brd ff:ff:ff:ff:ff:ff
inet 192.0.2.1/28 scope global proto 0xab d
valid_lft forever preferred_lft forever
# ip address replace dev d 192.0.2.1/28 proto 0x11
# ip address show dev d
26: d: <BROADCAST,NOARP> mtu 1500 qdisc noop state DOWN group default qlen 1000
link/ether 06:29:74:fd:1f:eb brd ff:ff:ff:ff:ff:ff
inet 192.0.2.1/28 scope global proto 0x11 d
valid_lft forever preferred_lft forever
A JSON dump. The protocol value is always provided as a string, even in
numeric mode, to provide a consistent interface.
# ip -j address show dev d | jq
[
{
"ifindex": 26,
"ifname": "d",
"flags": [
"BROADCAST",
"NOARP"
],
"mtu": 1500,
"qdisc": "noop",
"operstate": "DOWN",
"group": "default",
"txqlen": 1000,
"link_type": "ether",
"address": "06:29:74:fd:1f:eb",
"broadcast": "ff:ff:ff:ff:ff:ff",
"addr_info": [
{
"family": "inet",
"local": "192.0.2.1",
"prefixlen": 28,
"scope": "global",
"protocol": "0x11",
"label": "d",
"valid_life_time": 4294967295,
"preferred_life_time": 4294967295
}
]
}
]
Signed-off-by: Petr Machata <petrm@nvidia.com>
Signed-off-by: David Ahern <dsahern@kernel.org>
2023-03-28 00:12:05 +08:00
|
|
|
char *end;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
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) {
|
2023-06-02 23:51:53 +08:00
|
|
|
*id = i;
|
ip: Support IP address protocol
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 patch, add support for setting the protocol attribute at IP address
addition, replacement, and listing requests.
An example session with the feature in action:
# ip address add dev d 192.0.2.1/28 proto 0xab
# ip address show dev d
26: d: <BROADCAST,NOARP> mtu 1500 qdisc noop state DOWN group default qlen 1000
link/ether 06:29:74:fd:1f:eb brd ff:ff:ff:ff:ff:ff
inet 192.0.2.1/28 scope global proto 0xab d
valid_lft forever preferred_lft forever
# ip address replace dev d 192.0.2.1/28 proto 0x11
# ip address show dev d
26: d: <BROADCAST,NOARP> mtu 1500 qdisc noop state DOWN group default qlen 1000
link/ether 06:29:74:fd:1f:eb brd ff:ff:ff:ff:ff:ff
inet 192.0.2.1/28 scope global proto 0x11 d
valid_lft forever preferred_lft forever
A JSON dump. The protocol value is always provided as a string, even in
numeric mode, to provide a consistent interface.
# ip -j address show dev d | jq
[
{
"ifindex": 26,
"ifname": "d",
"flags": [
"BROADCAST",
"NOARP"
],
"mtu": 1500,
"qdisc": "noop",
"operstate": "DOWN",
"group": "default",
"txqlen": 1000,
"link_type": "ether",
"address": "06:29:74:fd:1f:eb",
"broadcast": "ff:ff:ff:ff:ff:ff",
"addr_info": [
{
"family": "inet",
"local": "192.0.2.1",
"prefixlen": 28,
"scope": "global",
"protocol": "0x11",
"label": "d",
"valid_life_time": 4294967295,
"preferred_life_time": 4294967295
}
]
}
]
Signed-off-by: Petr Machata <petrm@nvidia.com>
Signed-off-by: David Ahern <dsahern@kernel.org>
2023-03-28 00:12:05 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
res = strtoul(arg, &end, 0);
|
|
|
|
if (!end || end == arg || *end || res > 255)
|
|
|
|
return -1;
|
|
|
|
*id = res;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-11-30 03:41:23 +08:00
|
|
|
static char *rtnl_rtscope_tab[256] = {
|
|
|
|
[RT_SCOPE_UNIVERSE] = "global",
|
|
|
|
[RT_SCOPE_NOWHERE] = "nowhere",
|
|
|
|
[RT_SCOPE_HOST] = "host",
|
|
|
|
[RT_SCOPE_LINK] = "link",
|
|
|
|
[RT_SCOPE_SITE] = "site",
|
2004-04-16 04:56:59 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
static int rtnl_rtscope_init;
|
|
|
|
|
|
|
|
static void rtnl_rtscope_initialize(void)
|
|
|
|
{
|
2023-07-26 14:14:09 +08:00
|
|
|
int ret;
|
|
|
|
|
2004-04-16 04:56:59 +08:00
|
|
|
rtnl_rtscope_init = 1;
|
2023-07-26 14:14:09 +08:00
|
|
|
ret = rtnl_tab_initialize(CONF_ETC_DIR "/rt_scopes",
|
2024-03-12 00:18:44 +08:00
|
|
|
rtnl_rtscope_tab, 256);
|
2023-07-26 14:14:09 +08:00
|
|
|
if (ret == -ENOENT)
|
|
|
|
rtnl_tab_initialize(CONF_USR_DIR "/rt_scopes",
|
|
|
|
rtnl_rtscope_tab, 256);
|
2004-04-16 04:56:59 +08:00
|
|
|
}
|
|
|
|
|
2013-02-13 03:39:07 +08:00
|
|
|
const char *rtnl_rtscope_n2a(int id, char *buf, int len)
|
2004-04-16 04:56:59 +08:00
|
|
|
{
|
2019-06-12 17:21:15 +08:00
|
|
|
if (id < 0 || id >= 256 || numeric) {
|
2004-04-16 04:56:59 +08:00
|
|
|
snprintf(buf, len, "%d", id);
|
|
|
|
return buf;
|
|
|
|
}
|
2015-11-30 03:41:23 +08:00
|
|
|
|
2004-04-16 04:56:59 +08:00
|
|
|
if (!rtnl_rtscope_tab[id]) {
|
|
|
|
if (!rtnl_rtscope_init)
|
|
|
|
rtnl_rtscope_initialize();
|
|
|
|
}
|
2015-11-30 03:41:23 +08:00
|
|
|
|
2004-04-16 04:56:59 +08:00
|
|
|
if (rtnl_rtscope_tab[id])
|
|
|
|
return rtnl_rtscope_tab[id];
|
2015-11-30 03:41:23 +08:00
|
|
|
|
2004-04-16 04:56:59 +08:00
|
|
|
snprintf(buf, len, "%d", id);
|
|
|
|
return buf;
|
|
|
|
}
|
|
|
|
|
2013-02-13 03:39:07 +08:00
|
|
|
int rtnl_rtscope_a2n(__u32 *id, const char *arg)
|
2004-04-16 04:56:59 +08:00
|
|
|
{
|
2015-11-30 03:41:23 +08:00
|
|
|
static const char *cache;
|
2004-04-16 04:56:59 +08:00
|
|
|
static unsigned long res;
|
|
|
|
char *end;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
if (cache && strcmp(cache, arg) == 0) {
|
|
|
|
*id = res;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!rtnl_rtscope_init)
|
|
|
|
rtnl_rtscope_initialize();
|
|
|
|
|
2015-11-30 03:41:23 +08:00
|
|
|
for (i = 0; i < 256; i++) {
|
2004-04-16 04:56:59 +08:00
|
|
|
if (rtnl_rtscope_tab[i] &&
|
|
|
|
strcmp(rtnl_rtscope_tab[i], arg) == 0) {
|
|
|
|
cache = rtnl_rtscope_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;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-11-30 03:41:23 +08:00
|
|
|
static char *rtnl_rtrealm_tab[256] = {
|
2004-04-16 04:56:59 +08:00
|
|
|
"unknown",
|
|
|
|
};
|
|
|
|
|
|
|
|
static int rtnl_rtrealm_init;
|
|
|
|
|
|
|
|
static void rtnl_rtrealm_initialize(void)
|
|
|
|
{
|
2023-07-26 14:14:09 +08:00
|
|
|
int ret;
|
|
|
|
|
2004-04-16 04:56:59 +08:00
|
|
|
rtnl_rtrealm_init = 1;
|
2023-07-26 14:14:09 +08:00
|
|
|
ret = rtnl_tab_initialize(CONF_ETC_DIR "/rt_realms",
|
2024-03-12 00:18:44 +08:00
|
|
|
rtnl_rtrealm_tab, 256);
|
2023-07-26 14:14:09 +08:00
|
|
|
if (ret == -ENOENT)
|
|
|
|
rtnl_tab_initialize(CONF_USR_DIR "/rt_realms",
|
2024-03-12 00:18:44 +08:00
|
|
|
rtnl_rtrealm_tab, 256);
|
2004-04-16 04:56:59 +08:00
|
|
|
}
|
|
|
|
|
2013-02-13 03:39:07 +08:00
|
|
|
const char *rtnl_rtrealm_n2a(int id, char *buf, int len)
|
2004-04-16 04:56:59 +08:00
|
|
|
{
|
2019-06-12 17:21:15 +08:00
|
|
|
if (id < 0 || id >= 256 || numeric) {
|
2004-04-16 04:56:59 +08:00
|
|
|
snprintf(buf, len, "%d", id);
|
|
|
|
return buf;
|
|
|
|
}
|
|
|
|
if (!rtnl_rtrealm_tab[id]) {
|
|
|
|
if (!rtnl_rtrealm_init)
|
|
|
|
rtnl_rtrealm_initialize();
|
|
|
|
}
|
|
|
|
if (rtnl_rtrealm_tab[id])
|
|
|
|
return rtnl_rtrealm_tab[id];
|
|
|
|
snprintf(buf, len, "%d", id);
|
|
|
|
return buf;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-02-13 03:39:07 +08:00
|
|
|
int rtnl_rtrealm_a2n(__u32 *id, const char *arg)
|
2004-04-16 04:56:59 +08:00
|
|
|
{
|
2015-11-30 03:41:23 +08:00
|
|
|
static char *cache;
|
2004-04-16 04:56:59 +08:00
|
|
|
static unsigned long res;
|
|
|
|
char *end;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
if (cache && strcmp(cache, arg) == 0) {
|
|
|
|
*id = res;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!rtnl_rtrealm_init)
|
|
|
|
rtnl_rtrealm_initialize();
|
|
|
|
|
2015-11-30 03:41:23 +08:00
|
|
|
for (i = 0; i < 256; i++) {
|
2004-04-16 04:56:59 +08:00
|
|
|
if (rtnl_rtrealm_tab[i] &&
|
|
|
|
strcmp(rtnl_rtrealm_tab[i], arg) == 0) {
|
|
|
|
cache = rtnl_rtrealm_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;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-03-07 18:21:37 +08:00
|
|
|
static struct rtnl_hash_entry dflt_table_entry = { .name = "default" };
|
|
|
|
static struct rtnl_hash_entry main_table_entry = { .name = "main" };
|
|
|
|
static struct rtnl_hash_entry local_table_entry = { .name = "local" };
|
2004-04-16 04:56:59 +08:00
|
|
|
|
2015-11-30 03:41:23 +08:00
|
|
|
static struct rtnl_hash_entry *rtnl_rttable_hash[256] = {
|
2014-03-07 18:21:37 +08:00
|
|
|
[RT_TABLE_DEFAULT] = &dflt_table_entry,
|
|
|
|
[RT_TABLE_MAIN] = &main_table_entry,
|
|
|
|
[RT_TABLE_LOCAL] = &local_table_entry,
|
2004-04-16 04:56:59 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
static int rtnl_rttable_init;
|
|
|
|
|
|
|
|
static void rtnl_rttable_initialize(void)
|
|
|
|
{
|
2014-03-07 18:21:37 +08:00
|
|
|
int i;
|
2023-07-26 14:14:09 +08:00
|
|
|
int ret;
|
2014-03-07 18:21:37 +08:00
|
|
|
|
2004-04-16 04:56:59 +08:00
|
|
|
rtnl_rttable_init = 1;
|
2014-03-07 18:21:37 +08:00
|
|
|
for (i = 0; i < 256; i++) {
|
|
|
|
if (rtnl_rttable_hash[i])
|
|
|
|
rtnl_rttable_hash[i]->id = i;
|
|
|
|
}
|
2023-07-26 14:14:09 +08:00
|
|
|
ret = rtnl_hash_initialize(CONF_ETC_DIR "/rt_tables",
|
2024-03-12 00:18:44 +08:00
|
|
|
rtnl_rttable_hash, 256);
|
2023-07-26 14:14:09 +08:00
|
|
|
if (ret == -ENOENT)
|
|
|
|
rtnl_hash_initialize(CONF_USR_DIR "/rt_tables",
|
2024-03-12 00:18:44 +08:00
|
|
|
rtnl_rttable_hash, 256);
|
2015-11-25 05:20:01 +08:00
|
|
|
|
2023-07-26 14:14:09 +08:00
|
|
|
rtnl_hash_initialize_dir("rt_tables.d", rtnl_rttable_hash, 256);
|
2004-04-16 04:56:59 +08:00
|
|
|
}
|
|
|
|
|
2015-11-30 03:41:23 +08:00
|
|
|
const char *rtnl_rttable_n2a(__u32 id, char *buf, int len)
|
2004-04-16 04:56:59 +08:00
|
|
|
{
|
2006-08-11 06:14:50 +08:00
|
|
|
struct rtnl_hash_entry *entry;
|
|
|
|
|
|
|
|
if (!rtnl_rttable_init)
|
|
|
|
rtnl_rttable_initialize();
|
|
|
|
entry = rtnl_rttable_hash[id & 255];
|
|
|
|
while (entry && entry->id != id)
|
|
|
|
entry = entry->next;
|
2019-06-12 17:21:15 +08:00
|
|
|
if (!numeric && entry)
|
2006-08-11 06:14:50 +08:00
|
|
|
return entry->name;
|
|
|
|
snprintf(buf, len, "%u", id);
|
2004-04-16 04:56:59 +08:00
|
|
|
return buf;
|
|
|
|
}
|
|
|
|
|
2013-02-13 03:39:07 +08:00
|
|
|
int rtnl_rttable_a2n(__u32 *id, const char *arg)
|
2004-04-16 04:56:59 +08:00
|
|
|
{
|
2015-11-30 03:41:23 +08:00
|
|
|
static const char *cache;
|
2004-04-16 04:56:59 +08:00
|
|
|
static unsigned long res;
|
2006-08-11 06:14:50 +08:00
|
|
|
struct rtnl_hash_entry *entry;
|
2004-04-16 04:56:59 +08:00
|
|
|
char *end;
|
2017-01-11 07:33:55 +08:00
|
|
|
unsigned long i;
|
2004-04-16 04:56:59 +08:00
|
|
|
|
|
|
|
if (cache && strcmp(cache, arg) == 0) {
|
|
|
|
*id = res;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!rtnl_rttable_init)
|
|
|
|
rtnl_rttable_initialize();
|
|
|
|
|
2015-11-30 03:41:23 +08:00
|
|
|
for (i = 0; i < 256; i++) {
|
2006-08-11 06:14:50 +08:00
|
|
|
entry = rtnl_rttable_hash[i];
|
|
|
|
while (entry && strcmp(entry->name, arg))
|
|
|
|
entry = entry->next;
|
|
|
|
if (entry) {
|
|
|
|
cache = entry->name;
|
|
|
|
res = entry->id;
|
2004-04-16 04:56:59 +08:00
|
|
|
*id = res;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
i = strtoul(arg, &end, 0);
|
2006-08-11 06:14:50 +08:00
|
|
|
if (!end || end == arg || *end || i > RT_TABLE_MAX)
|
2004-04-16 04:56:59 +08:00
|
|
|
return -1;
|
|
|
|
*id = i;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-11-30 03:41:23 +08:00
|
|
|
static char *rtnl_rtdsfield_tab[256] = {
|
2004-04-16 04:56:59 +08:00
|
|
|
"0",
|
|
|
|
};
|
|
|
|
|
|
|
|
static int rtnl_rtdsfield_init;
|
|
|
|
|
|
|
|
static void rtnl_rtdsfield_initialize(void)
|
|
|
|
{
|
2023-07-26 14:14:09 +08:00
|
|
|
int ret;
|
|
|
|
|
2004-04-16 04:56:59 +08:00
|
|
|
rtnl_rtdsfield_init = 1;
|
2023-07-26 14:14:09 +08:00
|
|
|
ret = rtnl_tab_initialize(CONF_ETC_DIR "/rt_dsfield",
|
2024-03-12 00:18:44 +08:00
|
|
|
rtnl_rtdsfield_tab, 256);
|
2023-07-26 14:14:09 +08:00
|
|
|
if (ret == -ENOENT)
|
|
|
|
rtnl_tab_initialize(CONF_USR_DIR "/rt_dsfield",
|
2024-03-12 00:18:44 +08:00
|
|
|
rtnl_rtdsfield_tab, 256);
|
2004-04-16 04:56:59 +08:00
|
|
|
}
|
|
|
|
|
2013-02-13 03:39:07 +08:00
|
|
|
const char *rtnl_dsfield_n2a(int id, char *buf, int len)
|
2004-04-16 04:56:59 +08:00
|
|
|
{
|
2021-01-02 08:03:35 +08:00
|
|
|
const char *name;
|
|
|
|
|
2015-11-30 03:41:23 +08:00
|
|
|
if (id < 0 || id >= 256) {
|
2004-04-16 04:56:59 +08:00
|
|
|
snprintf(buf, len, "%d", id);
|
|
|
|
return buf;
|
|
|
|
}
|
2021-01-02 08:03:35 +08:00
|
|
|
if (!numeric) {
|
|
|
|
name = rtnl_dsfield_get_name(id);
|
|
|
|
if (name != NULL)
|
|
|
|
return name;
|
|
|
|
}
|
|
|
|
snprintf(buf, len, "0x%02x", id);
|
|
|
|
return buf;
|
|
|
|
}
|
|
|
|
|
|
|
|
const char *rtnl_dsfield_get_name(int id)
|
|
|
|
{
|
|
|
|
if (id < 0 || id >= 256)
|
|
|
|
return NULL;
|
2004-04-16 04:56:59 +08:00
|
|
|
if (!rtnl_rtdsfield_tab[id]) {
|
|
|
|
if (!rtnl_rtdsfield_init)
|
|
|
|
rtnl_rtdsfield_initialize();
|
|
|
|
}
|
2021-01-02 08:03:35 +08:00
|
|
|
return rtnl_rtdsfield_tab[id];
|
2004-04-16 04:56:59 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-02-13 03:39:07 +08:00
|
|
|
int rtnl_dsfield_a2n(__u32 *id, const char *arg)
|
2004-04-16 04:56:59 +08:00
|
|
|
{
|
2015-11-30 03:41:23 +08:00
|
|
|
static char *cache;
|
2004-04-16 04:56:59 +08:00
|
|
|
static unsigned long res;
|
|
|
|
char *end;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
if (cache && strcmp(cache, arg) == 0) {
|
|
|
|
*id = res;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!rtnl_rtdsfield_init)
|
|
|
|
rtnl_rtdsfield_initialize();
|
|
|
|
|
2015-11-30 03:41:23 +08:00
|
|
|
for (i = 0; i < 256; i++) {
|
2004-04-16 04:56:59 +08:00
|
|
|
if (rtnl_rtdsfield_tab[i] &&
|
|
|
|
strcmp(rtnl_rtdsfield_tab[i], arg) == 0) {
|
|
|
|
cache = rtnl_rtdsfield_tab[i];
|
|
|
|
res = i;
|
|
|
|
*id = res;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
res = strtoul(arg, &end, 16);
|
|
|
|
if (!end || end == arg || *end || res > 255)
|
|
|
|
return -1;
|
|
|
|
*id = res;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2011-02-03 02:23:40 +08:00
|
|
|
|
2015-11-30 03:41:23 +08:00
|
|
|
static struct rtnl_hash_entry dflt_group_entry = {
|
|
|
|
.id = 0, .name = "default"
|
|
|
|
};
|
2011-02-03 02:23:40 +08:00
|
|
|
|
2015-11-30 03:41:23 +08:00
|
|
|
static struct rtnl_hash_entry *rtnl_group_hash[256] = {
|
2011-02-03 02:23:40 +08:00
|
|
|
[0] = &dflt_group_entry,
|
|
|
|
};
|
|
|
|
|
|
|
|
static int rtnl_group_init;
|
|
|
|
|
|
|
|
static void rtnl_group_initialize(void)
|
|
|
|
{
|
2023-07-26 14:14:09 +08:00
|
|
|
int ret;
|
|
|
|
|
2011-02-03 02:23:40 +08:00
|
|
|
rtnl_group_init = 1;
|
2023-07-26 14:14:09 +08:00
|
|
|
ret = rtnl_hash_initialize(CONF_ETC_DIR "/group",
|
2024-03-12 00:18:44 +08:00
|
|
|
rtnl_group_hash, 256);
|
2023-07-26 14:14:09 +08:00
|
|
|
if (ret == -ENOENT)
|
|
|
|
rtnl_hash_initialize(CONF_USR_DIR "/group",
|
2024-03-12 00:18:44 +08:00
|
|
|
rtnl_group_hash, 256);
|
2011-02-03 02:23:40 +08:00
|
|
|
}
|
|
|
|
|
2013-02-13 03:39:07 +08:00
|
|
|
int rtnl_group_a2n(int *id, const char *arg)
|
2011-02-03 02:23:40 +08:00
|
|
|
{
|
2015-11-30 03:41:23 +08:00
|
|
|
static const char *cache;
|
2011-02-03 02:23:40 +08:00
|
|
|
static unsigned long res;
|
|
|
|
struct rtnl_hash_entry *entry;
|
|
|
|
char *end;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
if (cache && strcmp(cache, arg) == 0) {
|
|
|
|
*id = res;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!rtnl_group_init)
|
|
|
|
rtnl_group_initialize();
|
|
|
|
|
2015-11-30 03:41:23 +08:00
|
|
|
for (i = 0; i < 256; i++) {
|
2011-02-03 02:23:40 +08:00
|
|
|
entry = rtnl_group_hash[i];
|
|
|
|
while (entry && strcmp(entry->name, arg))
|
|
|
|
entry = entry->next;
|
|
|
|
if (entry) {
|
|
|
|
cache = entry->name;
|
|
|
|
res = entry->id;
|
|
|
|
*id = res;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
i = strtol(arg, &end, 0);
|
|
|
|
if (!end || end == arg || *end || i < 0)
|
|
|
|
return -1;
|
|
|
|
*id = i;
|
|
|
|
return 0;
|
|
|
|
}
|
2013-08-03 20:20:53 +08:00
|
|
|
|
|
|
|
const char *rtnl_group_n2a(int id, char *buf, int len)
|
|
|
|
{
|
|
|
|
struct rtnl_hash_entry *entry;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
if (!rtnl_group_init)
|
|
|
|
rtnl_group_initialize();
|
|
|
|
|
2019-06-12 17:21:15 +08:00
|
|
|
for (i = 0; !numeric && i < 256; i++) {
|
2013-08-03 20:20:53 +08:00
|
|
|
entry = rtnl_group_hash[i];
|
2016-11-18 09:12:53 +08:00
|
|
|
|
|
|
|
while (entry) {
|
|
|
|
if (entry->id == id)
|
|
|
|
return entry->name;
|
|
|
|
entry = entry->next;
|
|
|
|
}
|
2013-08-03 20:20:53 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
snprintf(buf, len, "%d", id);
|
|
|
|
return buf;
|
|
|
|
}
|
2014-10-30 23:33:36 +08:00
|
|
|
|
|
|
|
static char *nl_proto_tab[256] = {
|
|
|
|
[NETLINK_ROUTE] = "rtnl",
|
|
|
|
[NETLINK_UNUSED] = "unused",
|
|
|
|
[NETLINK_USERSOCK] = "usersock",
|
|
|
|
[NETLINK_FIREWALL] = "fw",
|
|
|
|
[NETLINK_SOCK_DIAG] = "tcpdiag",
|
|
|
|
[NETLINK_NFLOG] = "nflog",
|
|
|
|
[NETLINK_XFRM] = "xfrm",
|
|
|
|
[NETLINK_SELINUX] = "selinux",
|
|
|
|
[NETLINK_ISCSI] = "iscsi",
|
|
|
|
[NETLINK_AUDIT] = "audit",
|
|
|
|
[NETLINK_FIB_LOOKUP] = "fiblookup",
|
|
|
|
[NETLINK_CONNECTOR] = "connector",
|
|
|
|
[NETLINK_NETFILTER] = "nft",
|
|
|
|
[NETLINK_IP6_FW] = "ip6fw",
|
|
|
|
[NETLINK_DNRTMSG] = "dec-rt",
|
|
|
|
[NETLINK_KOBJECT_UEVENT] = "uevent",
|
|
|
|
[NETLINK_GENERIC] = "genl",
|
|
|
|
[NETLINK_SCSITRANSPORT] = "scsi-trans",
|
|
|
|
[NETLINK_ECRYPTFS] = "ecryptfs",
|
|
|
|
[NETLINK_RDMA] = "rdma",
|
|
|
|
[NETLINK_CRYPTO] = "crypto",
|
|
|
|
};
|
|
|
|
|
|
|
|
static int nl_proto_init;
|
|
|
|
|
|
|
|
static void nl_proto_initialize(void)
|
|
|
|
{
|
2023-07-26 14:14:09 +08:00
|
|
|
int ret;
|
|
|
|
|
2014-10-30 23:33:36 +08:00
|
|
|
nl_proto_init = 1;
|
2023-07-26 14:14:09 +08:00
|
|
|
ret = rtnl_tab_initialize(CONF_ETC_DIR "/nl_protos",
|
2024-03-12 00:18:44 +08:00
|
|
|
nl_proto_tab, 256);
|
2023-07-26 14:14:09 +08:00
|
|
|
if (ret == -ENOENT)
|
|
|
|
rtnl_tab_initialize(CONF_USR_DIR "/nl_protos",
|
2024-03-12 00:18:44 +08:00
|
|
|
nl_proto_tab, 256);
|
2014-10-30 23:33:36 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
const char *nl_proto_n2a(int id, char *buf, int len)
|
|
|
|
{
|
2019-06-12 17:21:15 +08:00
|
|
|
if (id < 0 || id >= 256 || numeric) {
|
|
|
|
snprintf(buf, len, "%d", id);
|
2014-10-30 23:33:36 +08:00
|
|
|
return buf;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!nl_proto_init)
|
|
|
|
nl_proto_initialize();
|
|
|
|
|
|
|
|
if (nl_proto_tab[id])
|
|
|
|
return nl_proto_tab[id];
|
|
|
|
|
|
|
|
snprintf(buf, len, "%u", id);
|
|
|
|
return buf;
|
|
|
|
}
|
|
|
|
|
|
|
|
int nl_proto_a2n(__u32 *id, const char *arg)
|
|
|
|
{
|
2015-11-30 03:41:23 +08:00
|
|
|
static char *cache;
|
2014-10-30 23:33:36 +08:00
|
|
|
static unsigned long res;
|
|
|
|
char *end;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
if (cache && strcmp(cache, arg) == 0) {
|
|
|
|
*id = res;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!nl_proto_init)
|
|
|
|
nl_proto_initialize();
|
|
|
|
|
|
|
|
for (i = 0; i < 256; i++) {
|
|
|
|
if (nl_proto_tab[i] &&
|
|
|
|
strcmp(nl_proto_tab[i], arg) == 0) {
|
|
|
|
cache = nl_proto_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;
|
|
|
|
}
|
2020-08-29 11:42:56 +08:00
|
|
|
|
|
|
|
#define PROTODOWN_REASON_NUM_BITS 32
|
|
|
|
static char *protodown_reason_tab[PROTODOWN_REASON_NUM_BITS] = {
|
|
|
|
};
|
|
|
|
|
|
|
|
static int protodown_reason_init;
|
|
|
|
|
|
|
|
static void protodown_reason_initialize(void)
|
|
|
|
{
|
|
|
|
protodown_reason_init = 1;
|
|
|
|
|
2023-07-26 14:14:09 +08:00
|
|
|
rtnl_tab_initialize_dir("protodown_reasons.d", protodown_reason_tab,
|
2024-03-12 00:18:44 +08:00
|
|
|
PROTODOWN_REASON_NUM_BITS);
|
2020-08-29 11:42:56 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
int protodown_reason_n2a(int id, char *buf, int len)
|
|
|
|
{
|
|
|
|
if (id < 0 || id >= PROTODOWN_REASON_NUM_BITS)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
if (numeric) {
|
|
|
|
snprintf(buf, len, "%d", id);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!protodown_reason_init)
|
|
|
|
protodown_reason_initialize();
|
|
|
|
|
|
|
|
if (protodown_reason_tab[id])
|
|
|
|
snprintf(buf, len, "%s", protodown_reason_tab[id]);
|
|
|
|
else
|
|
|
|
snprintf(buf, len, "%d", id);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int protodown_reason_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 (!protodown_reason_init)
|
|
|
|
protodown_reason_initialize();
|
|
|
|
|
|
|
|
for (i = 0; i < PROTODOWN_REASON_NUM_BITS; i++) {
|
|
|
|
if (protodown_reason_tab[i] &&
|
|
|
|
strcmp(protodown_reason_tab[i], arg) == 0) {
|
|
|
|
cache = protodown_reason_tab[i];
|
|
|
|
res = i;
|
|
|
|
*id = res;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
res = strtoul(arg, &end, 0);
|
|
|
|
if (!end || end == arg || *end || res >= PROTODOWN_REASON_NUM_BITS)
|
|
|
|
return -1;
|
|
|
|
*id = res;
|
|
|
|
return 0;
|
|
|
|
}
|