Skip to content

Commit c73d1bb

Browse files
authored
Merge pull request #2545 from pqarmitage/updates
Improve reading iproute2 config files and FORTIFY_SOURCE definition
2 parents bee7c79 + d003ec4 commit c73d1bb

File tree

2 files changed

+113
-51
lines changed

2 files changed

+113
-51
lines changed

configure.ac

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -446,7 +446,7 @@ AC_COMPILE_IFELSE([AC_LANG_SOURCE([[
446446
[
447447
AC_MSG_RESULT([yes])
448448
ADD_FORTIFY_SOURCE=0
449-
FORTIFY_SOURCE=$(echo | gcc -O3 -dM -E - | grep _FORTIFY_SOURCE | sed -e "s/.* //")
449+
FORTIFY_SOURCE=$(echo | $CC -O3 -dM -E - | grep _FORTIFY_SOURCE | sed -e "s/.* //")
450450
],
451451
[
452452
AC_MSG_RESULT([no])
@@ -460,7 +460,31 @@ AS_IF([test $ADD_FORTIFY_SOURCE -eq 1],
460460
[
461461
FORTIFY_SOURCE=$(echo $CPPFLAGS | $SED -e "s/.*-D *_FORTIFY_SOURCE=//" -e "s/ .*//")
462462
ADD_FORTIFY_SOURCE=0
463-
],[FORTIFY_SOURCE=3])
463+
],
464+
[
465+
SAV_CFLAGS=$CFLAGS
466+
SAV_CPPFLAGS=$CPPFLAGS
467+
CFLAGS="$CFLAGS -Werror -O2"
468+
CPPFLAGS="$SAV_CPPFLAGS -D_FORTIFY_SOURCE=3"
469+
AC_COMPILE_IFELSE([
470+
AC_LANG_SOURCE([[
471+
#include <stdio.h>
472+
int main(void) {}
473+
]])],
474+
[FORTIFY_SOURCE=3],
475+
[
476+
CPPFLAGS="$SAV_CPPFLAGS -D_FORTIFY_SOURCE=2"
477+
AC_COMPILE_IFELSE([
478+
AC_LANG_SOURCE([[
479+
#include <stdio.h>
480+
int main(void) {}
481+
]])],
482+
[FORTIFY_SOURCE=2],
483+
[FORTIFY_SOURCE=1])
484+
])
485+
CPPFLAGS=$SAV_CPPFLAGS
486+
CFLAGS=$SAV_CFLAGS
487+
])
464488
])
465489
466490
#

lib/rttables.c

Lines changed: 87 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@
3636
6.6 946753a 15/09/23 ensure CONF_USR_DIR honours configure lib path - uses $(LIBDIR)
3737
deb66ac 06/11/23 revert 946753a4
3838
6.7 9626923 15/11/23 change using /usr/lib/iproute2 to /usr/share/iproute2
39-
6.12 b43f84a 14/10/24 add rt_addrprotos.d subdirectories
39+
6.13 b43f84a 14/10/24 add rt_addrprotos.d subdirectories
4040
4141
Debian, Ubuntu, RHEL and openSUSE moved from /etc/iproute2 to /usr/share/iproute2
4242
Mint, Gentoo and Archlinux currently use /etc/iproute2
@@ -106,6 +106,12 @@ typedef struct _rt_entry {
106106
list_head_t e_list;
107107
} rt_entry_t;
108108

109+
typedef enum {
110+
DIRS_NOT_CHECKED,
111+
DIRS_EXIST,
112+
DIRS_DONT_EXIST,
113+
} dir_state_t;
114+
109115
static rt_entry_t const rtntypes[] = {
110116
{ RTN_LOCAL, "local", {0}},
111117
{ RTN_NAT, "nat", {0}},
@@ -186,6 +192,8 @@ static LIST_HEAD_INITIALIZE(rt_scopes);
186192

187193
static char ret_buf[11]; /* uint32_t in decimal */
188194

195+
static dir_state_t dir_state = DIRS_NOT_CHECKED;
196+
189197
static void
190198
free_rt_entry(rt_entry_t *rte)
191199
{
@@ -372,68 +380,82 @@ initialise_list(list_head_t *l, const char *file_name, const rt_entry_t *default
372380
if (!list_empty(l))
373381
return;
374382

375-
path = MALLOC(PATH_MAX);
383+
if (dir_state == DIRS_NOT_CHECKED) {
376384
#ifdef IPROUTE_USR_DIR
377-
etc_path = MALLOC(PATH_MAX);
385+
if (!stat(IPROUTE_USR_DIR, &statbuf) && (statbuf.st_mode & S_IFMT) == S_IFDIR)
386+
dir_state = DIRS_EXIST;
387+
else
378388
#endif
389+
if (!stat(IPROUTE_ETC_DIR, &statbuf) && (statbuf.st_mode & S_IFMT) == S_IFDIR)
390+
dir_state = DIRS_EXIST;
391+
else
392+
dir_state = DIRS_DONT_EXIST;
393+
}
379394

380-
/* The default location is IPROUTE_USR_DIR, but it is overridden
381-
* if the file exists in IPROUTE_USR_DIR. */
382-
snprintf(path, PATH_MAX, "%s/%s", IPROUTE_ETC_DIR, file_name);
383-
if (!stat(path, &statbuf) && (statbuf.st_mode & S_IFMT) == S_IFREG)
384-
read_file(path, l, max);
395+
if (dir_state == DIRS_EXIST) {
396+
path = MALLOC(PATH_MAX);
385397
#ifdef IPROUTE_USR_DIR
386-
else {
387-
snprintf(path, PATH_MAX, "%s/%s", IPROUTE_USR_DIR, file_name);
398+
etc_path = MALLOC(PATH_MAX);
399+
#endif
400+
401+
/* The default location is IPROUTE_USR_DIR, but it is overridden
402+
* if the file exists in IPROUTE_USR_DIR. */
403+
snprintf(path, PATH_MAX, "%s/%s", IPROUTE_ETC_DIR, file_name);
388404
if (!stat(path, &statbuf) && (statbuf.st_mode & S_IFMT) == S_IFREG)
389405
read_file(path, l, max);
390-
}
406+
#ifdef IPROUTE_USR_DIR
407+
else {
408+
snprintf(path, PATH_MAX, "%s/%s", IPROUTE_USR_DIR, file_name);
409+
if (!stat(path, &statbuf) && (statbuf.st_mode & S_IFMT) == S_IFREG)
410+
read_file(path, l, max);
411+
}
391412
#endif
392413

393-
/* iproute2 uses subdirectories for rt_protos, rt_addrprotos, rt_tables
394-
* (and protodown_reasons) as at v6.11.
395-
* To futureproof our code, we will read subdirectories for all files,
396-
* in case iproute2 introduces support for them in the future.
397-
* We need to check all files ending .conf under IPROUTE_USR_DIR and read
398-
* them unless the matching file exists under IPROUTE_ETC_DIR. We then read
399-
* all relevant files under IPROUTE_ETC_DIR. */
414+
/* iproute2 uses subdirectories for rt_protos, rt_addrprotos, rt_tables
415+
* (and protodown_reasons) as at v6.11.
416+
* To futureproof our code, we will read subdirectories for all files,
417+
* in case iproute2 introduces support for them in the future.
418+
* We need to check all files ending .conf under IPROUTE_USR_DIR and read
419+
* them unless the matching file exists under IPROUTE_ETC_DIR. We then read
420+
* all relevant files under IPROUTE_ETC_DIR. */
400421
#ifdef IPROUTE_USR_DIR
401-
snprintf(path, PATH_MAX, "%s/%s.d", IPROUTE_USR_DIR, file_name);
402-
if ((dir = opendir(path))) {
403-
while ((ent = readdir(dir))) {
404-
if (!wanted_file(path, IPROUTE_USR_DIR, file_name, ent->d_name))
405-
continue;
406-
407-
/* Check if the file exists in IPROUTE_ETC_DIR. We just check if there is a matching
408-
* entry, and don't care what type the entry is */
409-
snprintf(etc_path, PATH_MAX, "%s/%s.d/%s", IPROUTE_ETC_DIR, file_name, ent->d_name);
410-
if (!stat(etc_path, &statbuf))
411-
continue;
422+
snprintf(path, PATH_MAX, "%s/%s.d", IPROUTE_USR_DIR, file_name);
423+
if ((dir = opendir(path))) {
424+
while ((ent = readdir(dir))) {
425+
if (!wanted_file(path, IPROUTE_USR_DIR, file_name, ent->d_name))
426+
continue;
427+
428+
/* Check if the file exists in IPROUTE_ETC_DIR. We just check if there is a matching
429+
* entry, and don't care what type the entry is */
430+
snprintf(etc_path, PATH_MAX, "%s/%s.d/%s", IPROUTE_ETC_DIR, file_name, ent->d_name);
431+
if (!stat(etc_path, &statbuf))
432+
continue;
433+
434+
read_file(path, l, max);
435+
}
412436

413-
read_file(path, l, max);
437+
closedir(dir);
414438
}
415-
416-
closedir(dir);
417-
}
418439
#endif
419440

420-
/* Now read the entries in the IPROUTE_ETC_DIR subdirectory */
421-
snprintf(path, PATH_MAX, "%s/%s.d", IPROUTE_ETC_DIR, file_name);
422-
if ((dir = opendir(path))) {
423-
while ((ent = readdir(dir))) {
424-
if (!wanted_file(path, IPROUTE_ETC_DIR, file_name, ent->d_name))
425-
continue;
441+
/* Now read the entries in the IPROUTE_ETC_DIR subdirectory */
442+
snprintf(path, PATH_MAX, "%s/%s.d", IPROUTE_ETC_DIR, file_name);
443+
if ((dir = opendir(path))) {
444+
while ((ent = readdir(dir))) {
445+
if (!wanted_file(path, IPROUTE_ETC_DIR, file_name, ent->d_name))
446+
continue;
426447

427-
read_file(path, l, max);
428-
}
448+
read_file(path, l, max);
449+
}
429450

430-
closedir(dir);
431-
}
451+
closedir(dir);
452+
}
432453

433-
FREE_PTR(path);
454+
FREE_PTR(path);
434455
#ifdef IPROUTE_USR_DIR
435-
FREE_PTR(etc_path);
456+
FREE_PTR(etc_path);
436457
#endif
458+
}
437459

438460
if (default_list)
439461
add_default(l, default_list);
@@ -590,7 +612,7 @@ get_rttables_scope(uint32_t id)
590612
static const char *
591613
get_rttables_addrproto(uint32_t id)
592614
{
593-
return get_entry(id, &rt_scopes, RT_ADDRPROTOS_FILE, rtscope_default, 255);
615+
return get_entry(id, &rt_addrprotos, RT_ADDRPROTOS_FILE, rtaddrproto_default, 255);
594616
}
595617

596618
static void
@@ -635,18 +657,33 @@ write_addrproto_config(const char *name, uint32_t val)
635657
if (sscanf(v, "%d.%d.%d", &ver_maj, &ver_min, &ver_rel) != 3)
636658
return;
637659

638-
if (ver_maj >= 7 || (ver_maj == 6 && ver_min >= 12)) {
660+
if (ver_maj >= 7 || (ver_maj == 6 && ver_min >= 13)) {
639661
dir = IPROUTE_ETC_DIR "/" RT_ADDRPROTOS_FILE ".d";
640662
path = IPROUTE_ETC_DIR "/" RT_ADDRPROTOS_FILE ".d/keepalived.conf" ;
641663
} else if (ver_maj == 6 && ver_min >= 3)
642664
path = IPROUTE_ETC_DIR "/" RT_ADDRPROTOS_FILE;
643665
else
644666
return;
645667

646-
stat(IPROUTE_ETC_DIR, &statbuf);
668+
/* If IPROUTE_ETC_DIR doesn't exist, create it */
669+
if (stat(IPROUTE_ETC_DIR, &statbuf)) {
670+
if (stat(IPROUTE_USR_DIR, &statbuf)) {
671+
/* Use sensible defaults for directory permission */
672+
statbuf.st_mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
673+
}
674+
675+
/* Create directory */
676+
if (mkdir(IPROUTE_ETC_DIR, statbuf.st_mode & ~S_IFMT)) {
677+
log_message(LOG_INFO, "Unable to create directory " IPROUTE_ETC_DIR " for rt_addrproto keepalived");
678+
return;
679+
}
680+
}
681+
647682
if (dir) {
648683
if (!mkdir(dir, statbuf.st_mode & ~S_IFMT)) // This may fail if the directory already exists
649684
chmod(dir, statbuf.st_mode & ~S_IFMT);
685+
else if (errno == EEXIST)
686+
file_exists = !stat(path, &statbuf);
650687
} else {
651688
/* Check if rt_addrprotos file exists */
652689
file_exists = !stat(path, &statbuf);
@@ -698,7 +735,8 @@ create_rttables_addrproto(const char *name, uint8_t *id)
698735
list_add_tail(&rte->e_list, &rt_addrprotos);
699736

700737
/* Save the entry so iproute can use it */
701-
write_addrproto_config(name, *id);
738+
if (dir_state != DIRS_DONT_EXIST)
739+
write_addrproto_config(name, *id);
702740

703741
return true;
704742
}

0 commit comments

Comments
 (0)