Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

vrrp: handle checking ip utility version properly with BusyBox #2507

Merged
merged 1 commit into from
Nov 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions doc/man/man5/keepalived.conf.5.in
Original file line number Diff line number Diff line change
Expand Up @@ -964,8 +964,25 @@ possibly following any cleanup actions needed.
# if more than one keepalived instance is running on a system.
# In order to alleviate this, enabling data_use_instance includes the
# instance name and network namespace in the file name of the .data files.
# This also applies to SIGUSR2 for outputting stats.
\fBdata_use_instance \fR[<BOOL>]

# If the files produced by SIGUSR1 and SIGUSR2 are on slow storage, then writing to
# them may cause keepalived processes to block. This option allows specifying the
# location to which the files should be written, and should ideally be a tmpfs rather
# than a real disc, and definitely not network attached storage or other storage that
# can block for more than a few microseconds.
# If path ends in a / it is considered to be a directory and the normal filenames
# in that directory will be used, otherwise it will be used as the full path name
# of the file to be written. Note that \fBdata_use_instance\fR may also modify the
# file name.
# For the state files, these are template names and "_checker" will be added
# for the checker process, "_bfd" will be added for the BFD process and
# "_parent" will be added for the parent process.
\fBstate_file_location \fRpath
\fBstats_file_location \fRpath
\fBjson_file_location \fRpath

# json_version 2 puts the VRRP data in a named array and adds
# track_process details. Default is version 1.
\fBjson_version \fR{1|2}
Expand Down
8 changes: 4 additions & 4 deletions doc/man/man8/keepalived.8.in
Original file line number Diff line number Diff line change
Expand Up @@ -372,20 +372,20 @@ will shut down.
.TP
.B USR1\fP or \fBSIGFUNC=DATA
Write configuration data to
.B @KA_TMP_DIR@/keepalived.data
.B @KA_TMP_DIR@/keepalived.data or file configured by state_dump_file
.TP
.B USR2\fP or \fBSIGFUNC=STATS
Write statistics info to
.B @KA_TMP_DIR@/keepalived.stats
.B @KA_TMP_DIR@/keepalived.stats or file configured by stats_dump_file
.TP
.B SIGFUNC=STATS_CLEAR
Write statistics info to
.B @KA_TMP_DIR@/keepalived.stats
.B @KA_TMP_DIR@/keepalived.stats or file configured by stats_dump_file
and clear the statistics counters
.TP
.B SIGFUNC=JSON
Write configuration data in JSON format to
.B @KA_TMP_DIR@/keepalived.json
.B @KA_TMP_DIR@/keepalived.json or file configured by json_dump_file
.TP
.B SIGFUNC=TDATA
This causes
Expand Down
2 changes: 1 addition & 1 deletion keepalived/bfd/bfd_data.c
Original file line number Diff line number Diff line change
Expand Up @@ -299,7 +299,7 @@ bfd_print_data(void)
{
FILE *fp;

fp = open_dump_file("keepalived_bfd.data");
fp = open_dump_file("_bfd");

if (!fp)
return;
Expand Down
2 changes: 1 addition & 1 deletion keepalived/check/check_print.c
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ check_print_data(void)
{
FILE *fp;

fp = open_dump_file("keepalived_check.data");
fp = open_dump_file("_check");

if (!fp)
return;
Expand Down
76 changes: 57 additions & 19 deletions keepalived/core/global_data.c
Original file line number Diff line number Diff line change
Expand Up @@ -516,46 +516,78 @@ free_global_data(data_t **datap)
FREE_CONST_PTR(data->iproute_usr_dir);
FREE_CONST_PTR(data->iproute_etc_dir);
#endif
FREE_CONST_PTR(data->state_dump_file);
FREE_CONST_PTR(data->stats_dump_file);
FREE_CONST_PTR(data->json_dump_file);

FREE(data);

*datap = NULL;
}

FILE * __attribute__((malloc))
open_dump_file(const char *file_name)
open_dump_file(const char *default_file_name)
{
FILE *fp;
const char *full_file_name;
char *tmp_file_name;
const char *file_name;
char *full_file_name;
const char *dot;
int len;
size_t len;
const char *dir;
size_t dir_len;

/*
* If no leading /, use tmp_dir
* If trailing /, add "keepalived%s.data", default_file_name
*/

if (global_data->state_dump_file &&
global_data->state_dump_file[0] == '/') {
dir = global_data->state_dump_file;
dir_len = strlen(dir);
if (dir[dir_len - 1] != '/')
dir_len = strrchr(dir, '/') - dir;
} else {
dir = tmp_dir;
dir_len = strlen(tmp_dir);
}

if (global_data->data_use_instance &&
(global_data->instance_name || global_data->network_namespace)) {
len = strlen(tmp_dir) + 1 + strlen(file_name) + 1;
if (global_data->state_dump_file &&
global_data->state_dump_file[strlen(global_data->state_dump_file) - 1] != '/') {
if (!(file_name = strrchr(global_data->state_dump_file, '/')))
file_name = global_data->state_dump_file;
else
file_name++; /* Skip to last '/' */
} else
file_name = "keepalived.data";

if (!(dot = strrchr(file_name, '.')))
dot = file_name + strlen(file_name);

len = dir_len + 1 + strlen(file_name) + 1 + strlen(default_file_name);
if (global_data->data_use_instance) {
if (global_data->instance_name)
len += strlen(global_data->instance_name) + 1;
if (global_data->network_namespace)
len += strlen(global_data->network_namespace) + 1;
}

tmp_file_name = MALLOC(len);
full_file_name = MALLOC(len);

dot = strrchr(file_name, '.');
sprintf(tmp_file_name, "%s/%.*s.%s%s%s%s", tmp_dir,
(int)(dot - file_name), file_name,
global_data->network_namespace ? global_data->network_namespace : "",
global_data->instance_name && global_data->network_namespace ? "_" : "",
global_data->instance_name ? global_data->instance_name : "",
dot);
full_file_name = tmp_file_name;
} else
full_file_name = make_tmp_filename(file_name);
snprintf(full_file_name, len, "%.*s/%.*s%s%s%s%s%s%s", (int)dir_len, dir,
(int)(dot - file_name), file_name,
default_file_name,
global_data->data_use_instance && (global_data->instance_name || global_data->network_namespace) ? "." : "",
global_data->data_use_instance && global_data->network_namespace ? global_data->network_namespace : "",
global_data->data_use_instance && global_data->instance_name && global_data->network_namespace ? "_" : "",
global_data->data_use_instance && global_data->instance_name ? global_data->instance_name : "",
dot);

fp = fopen_safe(full_file_name, "w");

if (!fp)
log_message(LOG_INFO, "Can't open dump file %s (%d: %s)",
file_name, errno, strerror(errno));
full_file_name, errno, strerror(errno));

FREE_CONST(full_file_name);

Expand Down Expand Up @@ -941,4 +973,10 @@ dump_global_data(FILE *fp, data_t * data)
conf_write(fp, " iproute usr directory %s", global_data->iproute_usr_dir ? global_data->iproute_usr_dir : "(none)");
conf_write(fp, " iproute etc directory %s", global_data->iproute_etc_dir ? global_data->iproute_etc_dir : "(none)");
#endif
if (global_data->state_dump_file)
conf_write(fp, " state dump file %s", global_data->state_dump_file);
if (global_data->stats_dump_file)
conf_write(fp, " stats dump file %s", global_data->stats_dump_file);
if (global_data->json_dump_file)
conf_write(fp, " json dump file %s", global_data->json_dump_file);
}
39 changes: 39 additions & 0 deletions keepalived/core/global_parser.c
Original file line number Diff line number Diff line change
Expand Up @@ -2469,6 +2469,42 @@ iproute_etc_handler(const vector_t *strvec)
}
#endif

static void
state_dump_file_handler(const vector_t *strvec)
{
if (vector_size(strvec) != 2 ||
!strvec_slot(strvec, 1)[0]) {
report_config_error(CONFIG_GENERAL_ERROR, "%s requires a non-empty path", strvec_slot(strvec, 0));
return;
}

global_data->state_dump_file = STRDUP(strvec_slot(strvec, 1));
}

static void
stats_dump_file_handler(const vector_t *strvec)
{
if (vector_size(strvec) != 2 ||
!strvec_slot(strvec, 1)[0]) {
report_config_error(CONFIG_GENERAL_ERROR, "%s requires a non-empty path", strvec_slot(strvec, 0));
return;
}

global_data->stats_dump_file = STRDUP(strvec_slot(strvec, 1));
}

static void
json_dump_file_handler(const vector_t *strvec)
{
if (vector_size(strvec) != 2 ||
!strvec_slot(strvec, 1)[0]) {
report_config_error(CONFIG_GENERAL_ERROR, "%s requires a non-empty path", strvec_slot(strvec, 0));
return;
}

global_data->json_dump_file = STRDUP(strvec_slot(strvec, 1));
}

void
init_global_keywords(bool global_active)
{
Expand Down Expand Up @@ -2688,4 +2724,7 @@ init_global_keywords(bool global_active)
install_keyword("iproute_usr_dir", &iproute_usr_handler);
install_keyword("iproute_etc_dir", &iproute_etc_handler);
#endif
install_keyword("state_dump_file", &state_dump_file_handler);
install_keyword("stats_dump_file", &stats_dump_file_handler);
install_keyword("json_dump_file", &json_dump_file_handler);
}
2 changes: 1 addition & 1 deletion keepalived/core/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -876,7 +876,7 @@ print_parent_data(__attribute__((unused)) thread_ref_t thread)

log_message(LOG_INFO, "Printing parent data for process(%d) on signal", getpid());

fp = open_dump_file("keepalived_parent.data");
fp = open_dump_file("_parent");

if (!fp)
return;
Expand Down
3 changes: 3 additions & 0 deletions keepalived/include/global_data.h
Original file line number Diff line number Diff line change
Expand Up @@ -298,6 +298,9 @@ typedef struct _data {
const char *iproute_usr_dir;
const char *iproute_etc_dir;
#endif
const char *state_dump_file;
const char *stats_dump_file;
const char *json_dump_file;
} data_t;

/* Global vars exported */
Expand Down
2 changes: 1 addition & 1 deletion keepalived/vrrp/vrrp_print.c
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ vrrp_print_data(void)
{
FILE *fp;

fp = open_dump_file("keepalived.data");
fp = open_dump_file("");

if (!fp)
return;
Expand Down
17 changes: 14 additions & 3 deletions lib/rttables.c
Original file line number Diff line number Diff line change
Expand Up @@ -605,7 +605,7 @@ write_addrproto_config(const char *name, uint32_t val)
bool file_exists = false;
struct stat statbuf;

fp = popen("ip -V", "re");
fp = popen("ip -V 2>&1", "re");
res = fgets(buf, sizeof(buf), fp);
pclose(fp);

Expand All @@ -616,14 +616,25 @@ write_addrproto_config(const char *name, uint32_t val)
* ip utility, iproute2-5.10.0
* or
* ip utility, iproute2-6.7.0, libbpf 1.2.3
*/
* or
* BusyBox v1.36.1 (2024-06-10 07:11:47 UTC) multi-call binary
*
* Busybox does not support the iproute2 configuration files.
*/
if (!strstr(buf, "iproute2"))
return;
if (strstr(buf, "BusyBox"))
return;

if (!(v = strchr(buf, '-')))
return;

v++;
if ((e = strchr(v, ',')))
*e = '\0';
sscanf(v, "%d.%d.%d", &ver_maj, &ver_min, &ver_rel);
if (sscanf(v, "%d.%d.%d", &ver_maj, &ver_min, &ver_rel) != 3)
return;

if (ver_maj >= 7 || (ver_maj == 6 && ver_min >= 12)) {
dir = IPROUTE_ETC_DIR "/" RT_ADDRPROTOS_FILE ".d";
path = IPROUTE_ETC_DIR "/" RT_ADDRPROTOS_FILE ".d/keepalived.conf" ;
Expand Down
Loading