[<prev] [next>] [day] [month] [year] [list]
Message-Id: <20230726061409.175839-1-gioele@svario.it>
Date: Wed, 26 Jul 2023 08:14:09 +0200
From: Gioele Barabucci <gioele@...rio.it>
To: Stephen Hemminger <stephen@...workplumber.org>
Cc: netdev@...r.kernel.org,
Gioele Barabucci <gioele@...rio.it>
Subject: [iproute2 v4] Read configuration files from /etc and /usr
Add support for the so called "stateless" configuration pattern (read
from /etc, fall back to /usr), giving system administrators a way to
define local configuration without changing any distro-provided files.
In practice this means that each configuration file FOO is loaded
from /usr/lib/iproute2/FOO unless /etc/iproute2/FOO exists.
Signed-off-by: Gioele Barabucci <gioele@...rio.it>
--
v4: fix order of bpf_hash_init, use union instead of void* for tabhash,
return -EINVAL instead of -1, move .d scan to separate function
v3: avoid hardcoded paths, suggested by Petr Machata
v2: squash into one patch
---
Makefile | 10 +-
include/utils.h | 7 +-
lib/bpf_legacy.c | 12 +-
lib/rt_names.c | 250 +++++++++++++++++++++++----------------
man/man8/Makefile | 3 +-
man/man8/ip-address.8.in | 5 +-
man/man8/ip-link.8.in | 12 +-
man/man8/ip-route.8.in | 43 ++++---
tc/m_ematch.c | 17 ++-
tc/tc_util.c | 18 ++-
10 files changed, 232 insertions(+), 145 deletions(-)
diff --git a/Makefile b/Makefile
index 8a17d614..7d1819ce 100644
--- a/Makefile
+++ b/Makefile
@@ -16,7 +16,8 @@ endif
PREFIX?=/usr
SBINDIR?=/sbin
-CONFDIR?=/etc/iproute2
+CONF_ETC_DIR?=/etc/iproute2
+CONF_USR_DIR?=$(PREFIX)/lib/iproute2
NETNS_RUN_DIR?=/var/run/netns
NETNS_ETC_DIR?=/etc/netns
DATADIR?=$(PREFIX)/share
@@ -37,7 +38,8 @@ ifneq ($(SHARED_LIBS),y)
DEFINES+= -DNO_SHARED_LIBS
endif
-DEFINES+=-DCONFDIR=\"$(CONFDIR)\" \
+DEFINES+=-DCONF_USR_DIR=\"$(CONF_USR_DIR)\" \
+ -DCONF_ETC_DIR=\"$(CONF_ETC_DIR)\" \
-DNETNS_RUN_DIR=\"$(NETNS_RUN_DIR)\" \
-DNETNS_ETC_DIR=\"$(NETNS_ETC_DIR)\"
@@ -100,11 +102,11 @@ config.mk:
install: all
install -m 0755 -d $(DESTDIR)$(SBINDIR)
- install -m 0755 -d $(DESTDIR)$(CONFDIR)
+ install -m 0755 -d $(DESTDIR)$(CONF_USR_DIR)
install -m 0755 -d $(DESTDIR)$(ARPDDIR)
install -m 0755 -d $(DESTDIR)$(HDRDIR)
@for i in $(SUBDIRS); do $(MAKE) -C $$i install; done
- install -m 0644 $(shell find etc/iproute2 -maxdepth 1 -type f) $(DESTDIR)$(CONFDIR)
+ install -m 0644 $(shell find etc/iproute2 -maxdepth 1 -type f) $(DESTDIR)$(CONF_USR_DIR)
install -m 0755 -d $(DESTDIR)$(BASH_COMPDIR)
install -m 0644 bash-completion/tc $(DESTDIR)$(BASH_COMPDIR)
install -m 0644 bash-completion/devlink $(DESTDIR)$(BASH_COMPDIR)
diff --git a/include/utils.h b/include/utils.h
index 0b5d86a2..3159dbab 100644
--- a/include/utils.h
+++ b/include/utils.h
@@ -38,8 +38,11 @@ extern int numeric;
extern bool do_all;
extern int echo_request;
-#ifndef CONFDIR
-#define CONFDIR "/etc/iproute2"
+#ifndef CONF_USR_DIR
+#define CONF_USR_DIR "/usr/lib/iproute2"
+#endif
+#ifndef CONF_ETC_DIR
+#define CONF_ETC_DIR "/etc/iproute2"
#endif
#define SPRINT_BSIZE 64
diff --git a/lib/bpf_legacy.c b/lib/bpf_legacy.c
index 8ac64235..3542b12f 100644
--- a/lib/bpf_legacy.c
+++ b/lib/bpf_legacy.c
@@ -2751,7 +2751,7 @@ static bool bpf_pinning_reserved(uint32_t pinning)
}
}
-static void bpf_hash_init(struct bpf_elf_ctx *ctx, const char *db_file)
+static int bpf_hash_init(struct bpf_elf_ctx *ctx, const char *db_file)
{
struct bpf_hash_entry *entry;
char subpath[PATH_MAX] = {};
@@ -2761,14 +2761,14 @@ static void bpf_hash_init(struct bpf_elf_ctx *ctx, const char *db_file)
fp = fopen(db_file, "r");
if (!fp)
- return;
+ return -errno;
while ((ret = bpf_read_pin_mapping(fp, &pinning, subpath))) {
if (ret == -1) {
fprintf(stderr, "Database %s is corrupted at: %s\n",
db_file, subpath);
fclose(fp);
- return;
+ return -EINVAL;
}
if (bpf_pinning_reserved(pinning)) {
@@ -2796,6 +2796,8 @@ static void bpf_hash_init(struct bpf_elf_ctx *ctx, const char *db_file)
}
fclose(fp);
+
+ return 0;
}
static void bpf_hash_destroy(struct bpf_elf_ctx *ctx)
@@ -2924,7 +2926,9 @@ static int bpf_elf_ctx_init(struct bpf_elf_ctx *ctx, const char *pathname,
}
bpf_save_finfo(ctx);
- bpf_hash_init(ctx, CONFDIR "/bpf_pinning");
+ bpf_hash_init(ctx, CONF_ETC_DIR "/bpf_pinning");
+ if (ret == -ENOENT)
+ ret = bpf_hash_init(ctx, CONF_USR_DIR "/bpf_pinning");
return 0;
out_free:
diff --git a/lib/rt_names.c b/lib/rt_names.c
index 68db74e3..dafef3f1 100644
--- a/lib/rt_names.c
+++ b/lib/rt_names.c
@@ -12,8 +12,10 @@
#include <string.h>
#include <sys/time.h>
#include <sys/socket.h>
+#include <sys/stat.h>
#include <dirent.h>
#include <limits.h>
+#include <errno.h>
#include <asm/types.h>
#include <linux/rtnetlink.h>
@@ -56,7 +58,7 @@ static int fread_id_name(FILE *fp, int *id, char *namebuf)
return 0;
}
-static void
+static int
rtnl_hash_initialize(const char *file, struct rtnl_hash_entry **hash, int size)
{
struct rtnl_hash_entry *entry;
@@ -67,14 +69,14 @@ rtnl_hash_initialize(const char *file, struct rtnl_hash_entry **hash, int size)
fp = fopen(file, "r");
if (!fp)
- return;
+ return -errno;
while ((ret = fread_id_name(fp, &id, &namebuf[0]))) {
if (ret == -1) {
fprintf(stderr, "Database %s is corrupted at %s\n",
file, namebuf);
fclose(fp);
- return;
+ return -EINVAL;
}
if (id < 0)
@@ -91,9 +93,11 @@ rtnl_hash_initialize(const char *file, struct rtnl_hash_entry **hash, int size)
hash[id & (size - 1)] = entry;
}
fclose(fp);
+
+ return 0;
}
-static void rtnl_tab_initialize(const char *file, char **tab, int size)
+static int rtnl_tab_initialize(const char *file, char **tab, int size)
{
FILE *fp;
int id;
@@ -102,14 +106,14 @@ static void rtnl_tab_initialize(const char *file, char **tab, int size)
fp = fopen(file, "r");
if (!fp)
- return;
+ return -errno;
while ((ret = fread_id_name(fp, &id, &namebuf[0]))) {
if (ret == -1) {
fprintf(stderr, "Database %s is corrupted at %s\n",
file, namebuf);
fclose(fp);
- return;
+ return -EINVAL;
}
if (id < 0 || id > size)
continue;
@@ -117,6 +121,8 @@ static void rtnl_tab_initialize(const char *file, char **tab, int size)
tab[id] = strdup(namebuf);
}
fclose(fp);
+
+ return 0;
}
static char *rtnl_rtprot_tab[256] = {
@@ -144,41 +150,98 @@ static char *rtnl_rtprot_tab[256] = {
[RTPROT_EIGRP] = "eigrp",
};
+struct tabhash {
+ enum { TAB, HASH } type;
+ union tab_or_hash {
+ char **tab;
+ struct rtnl_hash_entry **hash;
+ } data;
+};
+
+static void
+rtnl_tabhash_readdir(const char *dirpath_base, const char *dirpath_overload,
+ const struct tabhash tabhash, const int size)
+{
+ struct dirent *de;
+ DIR *d;
+
+ d = opendir(dirpath_base);
+ while (d && (de = readdir(d)) != NULL) {
+ char path[PATH_MAX];
+ size_t len;
+ struct stat sb;
+
+ 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;
+
+ 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);
+ }
+ 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
+rtnl_tab_initialize_dir(const char *ddir, char **tab, const int size) {
+ 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,
+ const int size) {
+ 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)
{
- struct dirent *de;
- DIR *d;
+ int ret;
rtnl_rtprot_init = 1;
- rtnl_tab_initialize(CONFDIR "/rt_protos",
- rtnl_rtprot_tab, 256);
+ ret = rtnl_tab_initialize(CONF_ETC_DIR "/rt_protos",
+ rtnl_rtprot_tab, 256);
+ if (ret == -ENOENT)
+ rtnl_tab_initialize(CONF_USR_DIR "/rt_protos",
+ rtnl_rtprot_tab, 256);
- d = opendir(CONFDIR "/rt_protos.d");
- if (!d)
- return;
-
- while ((de = readdir(d)) != NULL) {
- char path[PATH_MAX];
- size_t len;
-
- 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;
-
- snprintf(path, sizeof(path), CONFDIR "/rt_protos.d/%s",
- de->d_name);
- rtnl_tab_initialize(path, rtnl_rtprot_tab, 256);
- }
- closedir(d);
+ rtnl_tab_initialize_dir("rt_protos.d", rtnl_rtprot_tab, 256);
}
const char *rtnl_rtprot_n2a(int id, char *buf, int len)
@@ -240,10 +303,17 @@ 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));
+ int ret;
+
rtnl_addrprot_tab_initialized = true;
+
+ ret = rtnl_tab_initialize(CONF_ETC_DIR "/rt_addrprotos",
+ rtnl_addrprot_tab,
+ ARRAY_SIZE(rtnl_addrprot_tab));
+ if (ret == -ENOENT)
+ ret = rtnl_tab_initialize(CONF_USR_DIR "/rt_addrprotos",
+ rtnl_addrprot_tab,
+ ARRAY_SIZE(rtnl_addrprot_tab));
}
const char *rtnl_addrprot_n2a(__u8 id, char *buf, int len)
@@ -296,9 +366,14 @@ static int rtnl_rtscope_init;
static void rtnl_rtscope_initialize(void)
{
+ int ret;
+
rtnl_rtscope_init = 1;
- rtnl_tab_initialize(CONFDIR "/rt_scopes",
- rtnl_rtscope_tab, 256);
+ ret = rtnl_tab_initialize(CONF_ETC_DIR "/rt_scopes",
+ rtnl_rtscope_tab, 256);
+ if (ret == -ENOENT)
+ rtnl_tab_initialize(CONF_USR_DIR "/rt_scopes",
+ rtnl_rtscope_tab, 256);
}
const char *rtnl_rtscope_n2a(int id, char *buf, int len)
@@ -361,9 +436,14 @@ static int rtnl_rtrealm_init;
static void rtnl_rtrealm_initialize(void)
{
+ int ret;
+
rtnl_rtrealm_init = 1;
- rtnl_tab_initialize(CONFDIR "/rt_realms",
- rtnl_rtrealm_tab, 256);
+ ret = rtnl_tab_initialize(CONF_ETC_DIR "/rt_realms",
+ rtnl_rtrealm_tab, 256);
+ if (ret == -ENOENT)
+ rtnl_tab_initialize(CONF_USR_DIR "/rt_realms",
+ rtnl_rtrealm_tab, 256);
}
const char *rtnl_rtrealm_n2a(int id, char *buf, int len)
@@ -430,41 +510,21 @@ static int rtnl_rttable_init;
static void rtnl_rttable_initialize(void)
{
- struct dirent *de;
- DIR *d;
int i;
+ int ret;
rtnl_rttable_init = 1;
for (i = 0; i < 256; i++) {
if (rtnl_rttable_hash[i])
rtnl_rttable_hash[i]->id = i;
}
- rtnl_hash_initialize(CONFDIR "/rt_tables",
- rtnl_rttable_hash, 256);
+ ret = rtnl_hash_initialize(CONF_ETC_DIR "/rt_tables",
+ rtnl_rttable_hash, 256);
+ if (ret == -ENOENT)
+ rtnl_hash_initialize(CONF_USR_DIR "/rt_tables",
+ rtnl_rttable_hash, 256);
- d = opendir(CONFDIR "/rt_tables.d");
- if (!d)
- return;
-
- while ((de = readdir(d)) != NULL) {
- char path[PATH_MAX];
- size_t len;
-
- 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;
-
- snprintf(path, sizeof(path),
- CONFDIR "/rt_tables.d/%s", de->d_name);
- rtnl_hash_initialize(path, rtnl_rttable_hash, 256);
- }
- closedir(d);
+ rtnl_hash_initialize_dir("rt_tables.d", rtnl_rttable_hash, 256);
}
const char *rtnl_rttable_n2a(__u32 id, char *buf, int len)
@@ -526,9 +586,14 @@ static int rtnl_rtdsfield_init;
static void rtnl_rtdsfield_initialize(void)
{
+ int ret;
+
rtnl_rtdsfield_init = 1;
- rtnl_tab_initialize(CONFDIR "/rt_dsfield",
- rtnl_rtdsfield_tab, 256);
+ ret = rtnl_tab_initialize(CONF_ETC_DIR "/rt_dsfield",
+ rtnl_rtdsfield_tab, 256);
+ if (ret == -ENOENT)
+ rtnl_tab_initialize(CONF_USR_DIR "/rt_dsfield",
+ rtnl_rtdsfield_tab, 256);
}
const char *rtnl_dsfield_n2a(int id, char *buf, int len)
@@ -605,9 +670,14 @@ static int rtnl_group_init;
static void rtnl_group_initialize(void)
{
+ int ret;
+
rtnl_group_init = 1;
- rtnl_hash_initialize(CONFDIR "/group",
- rtnl_group_hash, 256);
+ ret = rtnl_hash_initialize(CONF_ETC_DIR "/group",
+ rtnl_group_hash, 256);
+ if (ret == -ENOENT)
+ rtnl_hash_initialize(CONF_USR_DIR "/group",
+ rtnl_group_hash, 256);
}
int rtnl_group_a2n(int *id, const char *arg)
@@ -695,9 +765,14 @@ static int nl_proto_init;
static void nl_proto_initialize(void)
{
+ int ret;
+
nl_proto_init = 1;
- rtnl_tab_initialize(CONFDIR "/nl_protos",
- nl_proto_tab, 256);
+ ret = rtnl_tab_initialize(CONF_ETC_DIR "/nl_protos",
+ nl_proto_tab, 256);
+ if (ret == -ENOENT)
+ rtnl_tab_initialize(CONF_USR_DIR "/nl_protos",
+ nl_proto_tab, 256);
}
const char *nl_proto_n2a(int id, char *buf, int len)
@@ -757,35 +832,10 @@ static int protodown_reason_init;
static void protodown_reason_initialize(void)
{
- struct dirent *de;
- DIR *d;
-
protodown_reason_init = 1;
- d = opendir(CONFDIR "/protodown_reasons.d");
- if (!d)
- return;
-
- while ((de = readdir(d)) != NULL) {
- char path[PATH_MAX];
- size_t len;
-
- 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;
-
- snprintf(path, sizeof(path), CONFDIR "/protodown_reasons.d/%s",
- de->d_name);
- rtnl_tab_initialize(path, protodown_reason_tab,
- PROTODOWN_REASON_NUM_BITS);
- }
- closedir(d);
+ rtnl_tab_initialize_dir("protodown_reasons.d", protodown_reason_tab,
+ PROTODOWN_REASON_NUM_BITS);
}
int protodown_reason_n2a(int id, char *buf, int len)
diff --git a/man/man8/Makefile b/man/man8/Makefile
index b1fd87bd..6dab182f 100644
--- a/man/man8/Makefile
+++ b/man/man8/Makefile
@@ -9,7 +9,8 @@ all: $(TARGETS)
sed \
-e "s|@...NS_ETC_DIR@|$(NETNS_ETC_DIR)|g" \
-e "s|@...NS_RUN_DIR@|$(NETNS_RUN_DIR)|g" \
- -e "s|@...CONFDIR@|$(CONFDIR)|g" \
+ -e "s|@...CONF_ETC_DIR@|$(CONF_ETC_DIR)|g" \
+ -e "s|@...CONF_USR_DIR@|$(CONF_USR_DIR)|g" \
$< > $@
distclean: clean
diff --git a/man/man8/ip-address.8.in b/man/man8/ip-address.8.in
index abdd6a20..b9a476a5 100644
--- a/man/man8/ip-address.8.in
+++ b/man/man8/ip-address.8.in
@@ -208,8 +208,9 @@ The maximum allowed total length of label is 15 characters.
.TP
.BI scope " SCOPE_VALUE"
the scope of the area where this address is valid.
-The available scopes are listed in file
-.BR "@SYSCONFDIR@..._scopes" .
+The available scopes are listed in
+.BR "@SYSCONF_USR_DIR@..._scopes" or
+.BR "@SYSCONF_ETC_DIR@..._scopes" (has precedence if exists).
Predefined scope values are:
.in +8
diff --git a/man/man8/ip-link.8.in b/man/man8/ip-link.8.in
index 6a82ddc4..8f07de9a 100644
--- a/man/man8/ip-link.8.in
+++ b/man/man8/ip-link.8.in
@@ -2250,8 +2250,9 @@ give the device a symbolic name for easy reference.
.TP
.BI group " GROUP"
specify the group the device belongs to.
-The available groups are listed in file
-.BR "@SYSCONFDIR@...oup" .
+The available groups are listed in
+.BR "@SYSCONF_USR_DIR@...oup" or
+.BR "@SYSCONF_ETC_DIR@...oup" (has precedence if exists).
.TP
.BI vf " NUM"
@@ -2851,9 +2852,10 @@ specifies which help of link type to display.
.SS
.I GROUP
-may be a number or a string from the file
-.B @SYSCONFDIR@...oup
-which can be manually filled.
+may be a number or a string from
+.B @SYSCONF_USR_DIR@...oup or
+.B @SYSCONF_ETC_DIR@...oup
+which can be manually filled and has precedence if exists.
.SH "EXAMPLES"
.PP
diff --git a/man/man8/ip-route.8.in b/man/man8/ip-route.8.in
index c2b00833..76151689 100644
--- a/man/man8/ip-route.8.in
+++ b/man/man8/ip-route.8.in
@@ -356,8 +356,9 @@ normal routing tables.
.P
.B Route tables:
Linux-2.x can pack routes into several routing tables identified
-by a number in the range from 1 to 2^32-1 or by name from the file
-.B @SYSCONFDIR@..._tables
+by a number in the range from 1 to 2^32-1 or by name from
+.B @SYSCONF_USR_DIR@..._tables or
+.B @SYSCONF_ETC_DIR@..._tables (has precedence if exists).
By default all normal routes are inserted into the
.B main
table (ID 254) and the kernel only uses this table when calculating routes.
@@ -420,7 +421,8 @@ may still match a route with a zero TOS.
.I TOS
is either an 8 bit hexadecimal number or an identifier
from
-.BR "@SYSCONFDIR@..._dsfield" .
+.BR "@SYSCONF_USR_DIR@..._dsfield" or
+.BR "@SYSCONF_ETC_DIR@..._dsfield" (has precedence if exists).
.TP
.BI metric " NUMBER"
@@ -434,8 +436,9 @@ is an arbitrary 32bit number, where routes with lower values are preferred.
.BI table " TABLEID"
the table to add this route to.
.I TABLEID
-may be a number or a string from the file
-.BR "@SYSCONFDIR@..._tables" .
+may be a number or a string from
+.BR "@SYSCONF_USR_DIR@..._tables" or
+.BR "@SYSCONF_ETC_DIR@..._tables" (has precedence if exists).
If this parameter is omitted,
.B ip
assumes the
@@ -475,8 +478,9 @@ covered by the route prefix.
.BI realm " REALMID"
the realm to which this route is assigned.
.I REALMID
-may be a number or a string from the file
-.BR "@SYSCONFDIR@..._realms" .
+may be a number or a string from
+.BR "@SYSCONF_USR_DIR@..._realms" or
+.BR "@SYSCONF_ETC_DIR@..._realms" (has precedence if exists).
.TP
.BI mtu " MTU"
@@ -626,8 +630,9 @@ command.
.BI scope " SCOPE_VAL"
the scope of the destinations covered by the route prefix.
.I SCOPE_VAL
-may be a number or a string from the file
-.BR "@SYSCONFDIR@..._scopes" .
+may be a number or a string from
+.BR "@SYSCONF_USR_DIR@..._scopes" or
+.BR "@SYSCONF_ETC_DIR@..._scopes" (has precedence if exists).
If this parameter is omitted,
.B ip
assumes scope
@@ -646,8 +651,9 @@ routes.
.BI protocol " RTPROTO"
the routing protocol identifier of this route.
.I RTPROTO
-may be a number or a string from the file
-.BR "@SYSCONFDIR@..._protos" .
+may be a number or a string from
+.BR "@SYSCONF_ETC_DIR@..._protos" or
+.BR "@SYSCONF_ETC_DIR@..._protos" (has precedence if exists).
If the routing protocol ID is not given,
.B ip assumes protocol
.B boot
@@ -879,8 +885,9 @@ matching packets are dropped.
- Decapsulate the inner IPv6 packet and forward it according to the
specified lookup table.
.I TABLEID
-is either a number or a string from the file
-.BR "@SYSCONFDIR@..._tables" .
+is either a number or a string from
+.BR "@SYSCONF_USR_DIR@..._tables" or
+.BR "@SYSCONF_ETC_DIR@..._tables" (has precedence if exists).
If
.B vrftable
is used, the argument must be a VRF device associated with
@@ -895,8 +902,9 @@ and an inner IPv6 packet. Other matching packets are dropped.
- Decapsulate the inner IPv4 packet and forward it according to the
specified lookup table.
.I TABLEID
-is either a number or a string from the file
-.BR "@SYSCONFDIR@..._tables" .
+is either a number or a string from
+.BR "@SYSCONF_USR_DIR@..._tables" or
+.BR "@SYSCONF_ETC_DIR@..._tables" (has precedence if exists).
The argument must be a VRF device associated with the table id.
Moreover, the VRF table associated with the table id must be configured
with the VRF strict mode turned on (net.vrf.strict_mode=1). This action
@@ -908,8 +916,9 @@ at all, and an inner IPv4 packet. Other matching packets are dropped.
- Decapsulate the inner IPv4 or IPv6 packet and forward it according
to the specified lookup table.
.I TABLEID
-is either a number or a string from the file
-.BR "@SYSCONFDIR@..._tables" .
+is either a number or a string from
+.BR "@SYSCONF_USR_DIR@..._tables" or
+.BR "@SYSCONF_ETC_DIR@..._tables" (has precedence if exists).
The argument must be a VRF device associated with the table id.
Moreover, the VRF table associated with the table id must be configured
with the VRF strict mode turned on (net.vrf.strict_mode=1). This action
diff --git a/tc/m_ematch.c b/tc/m_ematch.c
index e30ee205..fefc7860 100644
--- a/tc/m_ematch.c
+++ b/tc/m_ematch.c
@@ -21,7 +21,8 @@
#include "tc_util.h"
#include "m_ematch.h"
-#define EMATCH_MAP "/etc/iproute2/ematch_map"
+#define EMATCH_MAP_USR CONF_USR_DIR "/ematch_map"
+#define EMATCH_MAP_ETC CONF_ETC_DIR "/ematch_map"
static struct ematch_util *ematch_list;
@@ -39,11 +40,11 @@ static void bstr_print(FILE *fd, const struct bstr *b, int ascii);
static inline void map_warning(int num, char *kind)
{
fprintf(stderr,
- "Error: Unable to find ematch \"%s\" in %s\n" \
+ "Error: Unable to find ematch \"%s\" in %s or %s\n" \
"Please assign a unique ID to the ematch kind the suggested " \
"entry is:\n" \
"\t%d\t%s\n",
- kind, EMATCH_MAP, num, kind);
+ kind, EMATCH_MAP_ETC, EMATCH_MAP_USR, num, kind);
}
static int lookup_map(__u16 num, char *dst, int len, const char *file)
@@ -160,8 +161,12 @@ static struct ematch_util *get_ematch_kind(char *kind)
static struct ematch_util *get_ematch_kind_num(__u16 kind)
{
char name[513];
+ int ret;
- if (lookup_map(kind, name, sizeof(name), EMATCH_MAP) < 0)
+ ret = lookup_map(kind, name, sizeof(name), EMATCH_MAP_ETC);
+ if (ret == -ENOENT)
+ ret = lookup_map(kind, name, sizeof(name), EMATCH_MAP_USR);
+ if (ret < 0)
return NULL;
return get_ematch_kind(name);
@@ -227,7 +232,9 @@ static int parse_tree(struct nlmsghdr *n, struct ematch *tree)
return -1;
}
- err = lookup_map_id(buf, &num, EMATCH_MAP);
+ err = lookup_map_id(buf, &num, EMATCH_MAP_ETC);
+ if (err == -ENOENT)
+ err = lookup_map_id(buf, &num, EMATCH_MAP_USR);
if (err < 0) {
if (err == -ENOENT)
map_warning(e->kind_num, buf);
diff --git a/tc/tc_util.c b/tc/tc_util.c
index ed9efa70..8c0e19e4 100644
--- a/tc/tc_util.c
+++ b/tc/tc_util.c
@@ -28,7 +28,8 @@
static struct db_names *cls_names;
-#define NAMES_DB "/etc/iproute2/tc_cls"
+#define NAMES_DB_USR CONF_USR_DIR "/tc_cls"
+#define NAMES_DB_ETC CONF_ETC_DIR "/tc_cls"
int cls_names_init(char *path)
{
@@ -38,11 +39,18 @@ int cls_names_init(char *path)
if (!cls_names)
return -1;
- ret = db_names_load(cls_names, path ?: NAMES_DB);
- if (ret == -ENOENT && path) {
- fprintf(stderr, "Can't open class names file: %s\n", path);
- return -1;
+ if (path) {
+ ret = db_names_load(cls_names, path);
+ if (ret == -ENOENT) {
+ fprintf(stderr, "Can't open class names file: %s\n", path);
+ return -1;
+ }
}
+
+ ret = db_names_load(cls_names, NAMES_DB_ETC);
+ if (ret == -ENOENT)
+ ret = db_names_load(cls_names, NAMES_DB_USR);
+
if (ret) {
db_names_free(cls_names);
cls_names = NULL;
--
2.39.2
Powered by blists - more mailing lists