|
36 | 36 | 6.6 946753a 15/09/23 ensure CONF_USR_DIR honours configure lib path - uses $(LIBDIR)
|
37 | 37 | deb66ac 06/11/23 revert 946753a4
|
38 | 38 | 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 |
40 | 40 |
|
41 | 41 | Debian, Ubuntu, RHEL and openSUSE moved from /etc/iproute2 to /usr/share/iproute2
|
42 | 42 | Mint, Gentoo and Archlinux currently use /etc/iproute2
|
@@ -106,6 +106,12 @@ typedef struct _rt_entry {
|
106 | 106 | list_head_t e_list;
|
107 | 107 | } rt_entry_t;
|
108 | 108 |
|
| 109 | +typedef enum { |
| 110 | + DIRS_NOT_CHECKED, |
| 111 | + DIRS_EXIST, |
| 112 | + DIRS_DONT_EXIST, |
| 113 | +} dir_state_t; |
| 114 | + |
109 | 115 | static rt_entry_t const rtntypes[] = {
|
110 | 116 | { RTN_LOCAL, "local", {0}},
|
111 | 117 | { RTN_NAT, "nat", {0}},
|
@@ -186,6 +192,8 @@ static LIST_HEAD_INITIALIZE(rt_scopes);
|
186 | 192 |
|
187 | 193 | static char ret_buf[11]; /* uint32_t in decimal */
|
188 | 194 |
|
| 195 | +static dir_state_t dir_state = DIRS_NOT_CHECKED; |
| 196 | + |
189 | 197 | static void
|
190 | 198 | free_rt_entry(rt_entry_t *rte)
|
191 | 199 | {
|
@@ -372,68 +380,82 @@ initialise_list(list_head_t *l, const char *file_name, const rt_entry_t *default
|
372 | 380 | if (!list_empty(l))
|
373 | 381 | return;
|
374 | 382 |
|
375 |
| - path = MALLOC(PATH_MAX); |
| 383 | + if (dir_state == DIRS_NOT_CHECKED) { |
376 | 384 | #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 |
378 | 388 | #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 | + } |
379 | 394 |
|
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); |
385 | 397 | #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); |
388 | 404 | if (!stat(path, &statbuf) && (statbuf.st_mode & S_IFMT) == S_IFREG)
|
389 | 405 | 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 | + } |
391 | 412 | #endif
|
392 | 413 |
|
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. */ |
400 | 421 | #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 | + } |
412 | 436 |
|
413 |
| - read_file(path, l, max); |
| 437 | + closedir(dir); |
414 | 438 | }
|
415 |
| - |
416 |
| - closedir(dir); |
417 |
| - } |
418 | 439 | #endif
|
419 | 440 |
|
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; |
426 | 447 |
|
427 |
| - read_file(path, l, max); |
428 |
| - } |
| 448 | + read_file(path, l, max); |
| 449 | + } |
429 | 450 |
|
430 |
| - closedir(dir); |
431 |
| - } |
| 451 | + closedir(dir); |
| 452 | + } |
432 | 453 |
|
433 |
| - FREE_PTR(path); |
| 454 | + FREE_PTR(path); |
434 | 455 | #ifdef IPROUTE_USR_DIR
|
435 |
| - FREE_PTR(etc_path); |
| 456 | + FREE_PTR(etc_path); |
436 | 457 | #endif
|
| 458 | + } |
437 | 459 |
|
438 | 460 | if (default_list)
|
439 | 461 | add_default(l, default_list);
|
@@ -590,7 +612,7 @@ get_rttables_scope(uint32_t id)
|
590 | 612 | static const char *
|
591 | 613 | get_rttables_addrproto(uint32_t id)
|
592 | 614 | {
|
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); |
594 | 616 | }
|
595 | 617 |
|
596 | 618 | static void
|
@@ -635,18 +657,33 @@ write_addrproto_config(const char *name, uint32_t val)
|
635 | 657 | if (sscanf(v, "%d.%d.%d", &ver_maj, &ver_min, &ver_rel) != 3)
|
636 | 658 | return;
|
637 | 659 |
|
638 |
| - if (ver_maj >= 7 || (ver_maj == 6 && ver_min >= 12)) { |
| 660 | + if (ver_maj >= 7 || (ver_maj == 6 && ver_min >= 13)) { |
639 | 661 | dir = IPROUTE_ETC_DIR "/" RT_ADDRPROTOS_FILE ".d";
|
640 | 662 | path = IPROUTE_ETC_DIR "/" RT_ADDRPROTOS_FILE ".d/keepalived.conf" ;
|
641 | 663 | } else if (ver_maj == 6 && ver_min >= 3)
|
642 | 664 | path = IPROUTE_ETC_DIR "/" RT_ADDRPROTOS_FILE;
|
643 | 665 | else
|
644 | 666 | return;
|
645 | 667 |
|
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 | + |
647 | 682 | if (dir) {
|
648 | 683 | if (!mkdir(dir, statbuf.st_mode & ~S_IFMT)) // This may fail if the directory already exists
|
649 | 684 | chmod(dir, statbuf.st_mode & ~S_IFMT);
|
| 685 | + else if (errno == EEXIST) |
| 686 | + file_exists = !stat(path, &statbuf); |
650 | 687 | } else {
|
651 | 688 | /* Check if rt_addrprotos file exists */
|
652 | 689 | file_exists = !stat(path, &statbuf);
|
@@ -698,7 +735,8 @@ create_rttables_addrproto(const char *name, uint8_t *id)
|
698 | 735 | list_add_tail(&rte->e_list, &rt_addrprotos);
|
699 | 736 |
|
700 | 737 | /* 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); |
702 | 740 |
|
703 | 741 | return true;
|
704 | 742 | }
|
|
0 commit comments