ifcfg-rh: separately handle static information during parsing ip-route commandline

There is an "info" part and a part with the data that we parsed.
Don't track the static and mutable data in the same variable.

Also, this allows to mark the static part as "const static".
This commit is contained in:
Thomas Haller
2019-11-27 15:18:32 +01:00
parent 7cadc5e465
commit b8c0078008

View File

@@ -739,25 +739,36 @@ parse_route_line_is_comment (const char *line)
/*****************************************************************************/ /*****************************************************************************/
typedef enum {
PARSE_LINE_AF_FLAG_FOR_IPV4 = 0x01,
PARSE_LINE_AF_FLAG_FOR_IPV6 = 0x02,
} ParseLineAFFlag;
typedef struct { typedef struct {
const char *key; const char *key;
/* the element is not available in this case. */ /* the element is not available in this case. */
bool disabled:1; ParseLineAFFlag disabled:3;
bool disabled_with_options_route:1;
/* whether the element is to be ignored. Ignord is different from /* whether the element is to be ignored. Ignord is different from
* "disabled", because we still parse the option, but don't use it. */ * "disabled", because we still parse the option, but don't use it. */
bool ignore:1; ParseLineAFFlag ignore:3;
bool int_base_16:1; bool int_base_16:1;
/* the type, one of PARSE_LINE_TYPE_* */
char type;
} ParseLineInfo;
typedef struct {
/* whether the command line option was found, and @v is /* whether the command line option was found, and @v is
* initialized. */ * initialized. */
bool has:1; bool has:1;
/* the type, one of PARSE_LINE_TYPE_* */
char type;
union { union {
guint8 uint8; guint8 uint8;
guint32 uint32; guint32 uint32;
@@ -772,7 +783,7 @@ typedef struct {
} addr; } addr;
} v; } v;
} ParseLineInfo; } ParseLineData;
enum { enum {
/* route attributes */ /* route attributes */
@@ -833,26 +844,18 @@ parse_route_line (const char *line,
NMIPRoute **out_route, NMIPRoute **out_route,
GError **error) GError **error)
{ {
nm_auto_unref_ip_route NMIPRoute *route = NULL; static const ParseLineInfo parse_infos[] = {
gs_free const char **words_free = NULL;
const char *const*words;
const char *s;
gsize i_words;
guint i;
char buf1[256];
char buf2[256];
ParseLineInfo infos[] = {
[PARSE_LINE_ATTR_ROUTE_TABLE] = { .key = NM_IP_ROUTE_ATTRIBUTE_TABLE, [PARSE_LINE_ATTR_ROUTE_TABLE] = { .key = NM_IP_ROUTE_ATTRIBUTE_TABLE,
.type = PARSE_LINE_TYPE_UINT32, }, .type = PARSE_LINE_TYPE_UINT32, },
[PARSE_LINE_ATTR_ROUTE_SRC] = { .key = NM_IP_ROUTE_ATTRIBUTE_SRC, [PARSE_LINE_ATTR_ROUTE_SRC] = { .key = NM_IP_ROUTE_ATTRIBUTE_SRC,
.type = PARSE_LINE_TYPE_ADDR, }, .type = PARSE_LINE_TYPE_ADDR, },
[PARSE_LINE_ATTR_ROUTE_FROM] = { .key = NM_IP_ROUTE_ATTRIBUTE_FROM, [PARSE_LINE_ATTR_ROUTE_FROM] = { .key = NM_IP_ROUTE_ATTRIBUTE_FROM,
.type = PARSE_LINE_TYPE_ADDR_WITH_PREFIX, .type = PARSE_LINE_TYPE_ADDR_WITH_PREFIX,
.disabled = (addr_family != AF_INET6), }, .disabled = PARSE_LINE_AF_FLAG_FOR_IPV4, },
[PARSE_LINE_ATTR_ROUTE_TOS] = { .key = NM_IP_ROUTE_ATTRIBUTE_TOS, [PARSE_LINE_ATTR_ROUTE_TOS] = { .key = NM_IP_ROUTE_ATTRIBUTE_TOS,
.type = PARSE_LINE_TYPE_UINT8, .type = PARSE_LINE_TYPE_UINT8,
.int_base_16 = TRUE, .int_base_16 = TRUE,
.ignore = (addr_family != AF_INET), }, .ignore = PARSE_LINE_AF_FLAG_FOR_IPV6, },
[PARSE_LINE_ATTR_ROUTE_ONLINK] = { .key = NM_IP_ROUTE_ATTRIBUTE_ONLINK, [PARSE_LINE_ATTR_ROUTE_ONLINK] = { .key = NM_IP_ROUTE_ATTRIBUTE_ONLINK,
.type = PARSE_LINE_TYPE_FLAG, }, .type = PARSE_LINE_TYPE_FLAG, },
[PARSE_LINE_ATTR_ROUTE_WINDOW] = { .key = NM_IP_ROUTE_ATTRIBUTE_WINDOW, [PARSE_LINE_ATTR_ROUTE_WINDOW] = { .key = NM_IP_ROUTE_ATTRIBUTE_WINDOW,
@@ -868,19 +871,31 @@ parse_route_line (const char *line,
[PARSE_LINE_ATTR_ROUTE_TO] = { .key = "to", [PARSE_LINE_ATTR_ROUTE_TO] = { .key = "to",
.type = PARSE_LINE_TYPE_ADDR_WITH_PREFIX, .type = PARSE_LINE_TYPE_ADDR_WITH_PREFIX,
.disabled = (options_route != NULL), }, .disabled_with_options_route = TRUE, },
[PARSE_LINE_ATTR_ROUTE_VIA] = { .key = "via", [PARSE_LINE_ATTR_ROUTE_VIA] = { .key = "via",
.type = PARSE_LINE_TYPE_ADDR, .type = PARSE_LINE_TYPE_ADDR,
.disabled = (options_route != NULL), }, .disabled_with_options_route = TRUE, },
[PARSE_LINE_ATTR_ROUTE_METRIC] = { .key = "metric", [PARSE_LINE_ATTR_ROUTE_METRIC] = { .key = "metric",
.type = PARSE_LINE_TYPE_UINT32, .type = PARSE_LINE_TYPE_UINT32,
.disabled = (options_route != NULL), }, .disabled_with_options_route = TRUE, },
[PARSE_LINE_ATTR_ROUTE_DEV] = { .key = "dev", [PARSE_LINE_ATTR_ROUTE_DEV] = { .key = "dev",
.type = PARSE_LINE_TYPE_IFNAME, .type = PARSE_LINE_TYPE_IFNAME,
.ignore = TRUE, .ignore = PARSE_LINE_AF_FLAG_FOR_IPV4 | PARSE_LINE_AF_FLAG_FOR_IPV6,
.disabled = (options_route != NULL), }, .disabled_with_options_route = TRUE, },
}; };
nm_auto_unref_ip_route NMIPRoute *route = NULL;
gs_free const char **words_free = NULL;
const char *const*words;
const char *s;
gsize i_words;
guint i;
char buf1[256];
char buf2[256];
ParseLineData parse_datas[G_N_ELEMENTS (parse_infos)] = { };
const ParseLineAFFlag af_flag = (addr_family == AF_INET)
? PARSE_LINE_AF_FLAG_FOR_IPV4
: PARSE_LINE_AF_FLAG_FOR_IPV6;
nm_assert (line); nm_assert (line);
nm_assert_addr_family (addr_family); nm_assert_addr_family (addr_family);
@@ -908,19 +923,22 @@ parse_route_line (const char *line,
for (i_words = 0; words[i_words]; ) { for (i_words = 0; words[i_words]; ) {
const gsize i_words0 = i_words; const gsize i_words0 = i_words;
const char *const w = words[i_words0]; const char *const w = words[i_words0];
ParseLineInfo *info; const ParseLineInfo *p_info;
ParseLineData *p_data;
gboolean unqualified_addr = FALSE; gboolean unqualified_addr = FALSE;
for (i = 0; i < G_N_ELEMENTS (infos); i++) { for (i = 0; i < G_N_ELEMENTS (parse_infos); i++) {
info = &infos[i]; p_info = &parse_infos[i];
p_data = &parse_datas[i];
if (info->disabled) if ( (p_info->disabled & af_flag)
|| (p_info->disabled_with_options_route && options_route))
continue; continue;
if (!nm_streq (w, info->key)) if (!nm_streq (w, p_info->key))
continue; continue;
if (info->has) { if (p_data->has) {
/* iproute2 for most arguments allows specifying them multiple times. /* iproute2 for most arguments allows specifying them multiple times.
* Let's not do that. */ * Let's not do that. */
g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION, g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION,
@@ -928,8 +946,8 @@ parse_route_line (const char *line,
return -EINVAL; return -EINVAL;
} }
info->has = TRUE; p_data->has = TRUE;
switch (info->type) { switch (p_info->type) {
case PARSE_LINE_TYPE_UINT8: case PARSE_LINE_TYPE_UINT8:
i_words++; i_words++;
goto parse_line_type_uint8; goto parse_line_type_uint8;
@@ -957,10 +975,13 @@ parse_route_line (const char *line,
} }
/* "to" is also accepted unqualified... (once) */ /* "to" is also accepted unqualified... (once) */
info = &infos[PARSE_LINE_ATTR_ROUTE_TO]; p_info = &parse_infos[PARSE_LINE_ATTR_ROUTE_TO];
if (!info->has && !info->disabled) { p_data = &parse_datas[PARSE_LINE_ATTR_ROUTE_TO];
if ( !p_data->has
&& !(p_info->disabled & af_flag)
&& !(p_info->disabled_with_options_route && options_route)) {
unqualified_addr = TRUE; unqualified_addr = TRUE;
info->has = TRUE; p_data->has = TRUE;
goto parse_line_type_addr; goto parse_line_type_addr;
} }
@@ -972,11 +993,11 @@ parse_line_type_uint8:
s = words[i_words]; s = words[i_words];
if (!s) if (!s)
goto err_word_missing_argument; goto err_word_missing_argument;
info->v.uint8 = _nm_utils_ascii_str_to_int64 (s, p_data->v.uint8 = _nm_utils_ascii_str_to_int64 (s,
info->int_base_16 ? 16 : 10, p_info->int_base_16 ? 16 : 10,
0, 0,
G_MAXUINT8, G_MAXUINT8,
0);; 0);;
if (errno) { if (errno) {
g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION, g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION,
"Argument for \"%s\" is not a valid number", w); "Argument for \"%s\" is not a valid number", w);
@@ -990,17 +1011,17 @@ parse_line_type_uint32_with_lock:
s = words[i_words]; s = words[i_words];
if (!s) if (!s)
goto err_word_missing_argument; goto err_word_missing_argument;
if (info->type == PARSE_LINE_TYPE_UINT32_WITH_LOCK) { if (p_info->type == PARSE_LINE_TYPE_UINT32_WITH_LOCK) {
if (nm_streq (s, "lock")) { if (nm_streq (s, "lock")) {
s = words[++i_words]; s = words[++i_words];
if (!s) if (!s)
goto err_word_missing_argument; goto err_word_missing_argument;
info->v.uint32_with_lock.lock = TRUE; p_data->v.uint32_with_lock.lock = TRUE;
} else } else
info->v.uint32_with_lock.lock = FALSE; p_data->v.uint32_with_lock.lock = FALSE;
info->v.uint32_with_lock.uint32 = _nm_utils_ascii_str_to_int64 (s, 10, 0, G_MAXUINT32, 0);; p_data->v.uint32_with_lock.uint32 = _nm_utils_ascii_str_to_int64 (s, 10, 0, G_MAXUINT32, 0);;
} else { } else {
info->v.uint32 = _nm_utils_ascii_str_to_int64 (s, 10, 0, G_MAXUINT32, 0); p_data->v.uint32 = _nm_utils_ascii_str_to_int64 (s, 10, 0, G_MAXUINT32, 0);
} }
if (errno) { if (errno) {
g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION, g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION,
@@ -1025,16 +1046,16 @@ parse_line_type_addr_with_prefix:
{ {
int prefix = -1; int prefix = -1;
if (info->type == PARSE_LINE_TYPE_ADDR) { if (p_info->type == PARSE_LINE_TYPE_ADDR) {
if (!nm_utils_parse_inaddr_bin (addr_family, if (!nm_utils_parse_inaddr_bin (addr_family,
s, s,
NULL, NULL,
&info->v.addr.addr)) { &p_data->v.addr.addr)) {
if ( info == &infos[PARSE_LINE_ATTR_ROUTE_VIA] if ( p_info == &parse_infos[PARSE_LINE_ATTR_ROUTE_VIA]
&& nm_streq (s, "(null)")) { && nm_streq (s, "(null)")) {
/* Due to a bug, would older versions of NM write "via (null)" /* Due to a bug, would older versions of NM write "via (null)"
* (rh#1452648). Workaround that, and accept it.*/ * (rh#1452648). Workaround that, and accept it.*/
memset (&info->v.addr.addr, 0, sizeof (info->v.addr.addr)); memset (&p_data->v.addr.addr, 0, sizeof (p_data->v.addr.addr));
} else { } else {
if (unqualified_addr) { if (unqualified_addr) {
g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION, g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION,
@@ -1049,15 +1070,15 @@ parse_line_type_addr_with_prefix:
} }
} }
} else { } else {
nm_assert (info->type == PARSE_LINE_TYPE_ADDR_WITH_PREFIX); nm_assert (p_info->type == PARSE_LINE_TYPE_ADDR_WITH_PREFIX);
if ( info == &infos[PARSE_LINE_ATTR_ROUTE_TO] if ( p_info == &parse_infos[PARSE_LINE_ATTR_ROUTE_TO]
&& nm_streq (s, "default")) { && nm_streq (s, "default")) {
memset (&info->v.addr.addr, 0, sizeof (info->v.addr.addr)); memset (&p_data->v.addr.addr, 0, sizeof (p_data->v.addr.addr));
prefix = 0; prefix = 0;
} else if (!nm_utils_parse_inaddr_prefix_bin (addr_family, } else if (!nm_utils_parse_inaddr_prefix_bin (addr_family,
s, s,
NULL, NULL,
&info->v.addr.addr, &p_data->v.addr.addr,
&prefix)) { &prefix)) {
g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION, g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION,
"Argument for \"%s\" is not ADDR/PREFIX format", w); "Argument for \"%s\" is not ADDR/PREFIX format", w);
@@ -1065,10 +1086,10 @@ parse_line_type_addr_with_prefix:
} }
} }
if (prefix == -1) if (prefix == -1)
info->v.addr.has_plen = FALSE; p_data->v.addr.has_plen = FALSE;
else { else {
info->v.addr.has_plen = TRUE; p_data->v.addr.has_plen = TRUE;
info->v.addr.plen = prefix; p_data->v.addr.plen = prefix;
} }
} }
i_words++; i_words++;
@@ -1086,70 +1107,75 @@ next:
route = options_route; route = options_route;
nm_ip_route_ref (route); nm_ip_route_ref (route);
} else { } else {
ParseLineInfo *info_to = &infos[PARSE_LINE_ATTR_ROUTE_TO]; ParseLineData *data_to = &parse_datas[PARSE_LINE_ATTR_ROUTE_TO];
ParseLineInfo *info_via = &infos[PARSE_LINE_ATTR_ROUTE_VIA]; ParseLineData *data_via = &parse_datas[PARSE_LINE_ATTR_ROUTE_VIA];
ParseLineInfo *info_metric = &infos[PARSE_LINE_ATTR_ROUTE_METRIC]; ParseLineData *data_metric = &parse_datas[PARSE_LINE_ATTR_ROUTE_METRIC];
guint prefix; guint prefix;
if (!info_to->has) { if (!data_to->has) {
g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION, g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION,
"Missing destination prefix"); "Missing destination prefix");
return -EINVAL; return -EINVAL;
} }
prefix = info_to->v.addr.has_plen prefix = data_to->v.addr.has_plen
? info_to->v.addr.plen ? data_to->v.addr.plen
: (addr_family == AF_INET ? 32 : 128); : (addr_family == AF_INET ? 32 : 128);
route = nm_ip_route_new_binary (addr_family, route = nm_ip_route_new_binary (addr_family,
&info_to->v.addr.addr, &data_to->v.addr.addr,
prefix, prefix,
info_via->has ? &info_via->v.addr.addr : NULL, data_via->has ? &data_via->v.addr.addr : NULL,
info_metric->has ? (gint64) info_metric->v.uint32 : (gint64) -1, data_metric->has ? (gint64) data_metric->v.uint32 : (gint64) -1,
error); error);
info_to->has = FALSE; data_to->has = FALSE;
info_via->has = FALSE; data_via->has = FALSE;
info_metric->has = FALSE; data_metric->has = FALSE;
if (!route) if (!route)
return -EINVAL; return -EINVAL;
} }
for (i = 0; i < G_N_ELEMENTS (infos); i++) { for (i = 0; i < G_N_ELEMENTS (parse_infos); i++) {
ParseLineInfo *info = &infos[i]; const ParseLineInfo *p_info = &parse_infos[i];
ParseLineData *p_data = &parse_datas[i];
if (!info->has) if (!p_data->has)
continue; continue;
if (info->ignore || info->disabled)
if ( (p_info->ignore & af_flag)
|| (p_info->disabled & af_flag)
|| (p_info->disabled_with_options_route && options_route))
continue; continue;
switch (info->type) {
switch (p_info->type) {
case PARSE_LINE_TYPE_UINT8: case PARSE_LINE_TYPE_UINT8:
nm_ip_route_set_attribute (route, nm_ip_route_set_attribute (route,
info->key, p_info->key,
g_variant_new_byte (info->v.uint8)); g_variant_new_byte (p_data->v.uint8));
break; break;
case PARSE_LINE_TYPE_UINT32: case PARSE_LINE_TYPE_UINT32:
nm_ip_route_set_attribute (route, nm_ip_route_set_attribute (route,
info->key, p_info->key,
g_variant_new_uint32 (info->v.uint32)); g_variant_new_uint32 (p_data->v.uint32));
break; break;
case PARSE_LINE_TYPE_UINT32_WITH_LOCK: case PARSE_LINE_TYPE_UINT32_WITH_LOCK:
if (info->v.uint32_with_lock.lock) { if (p_data->v.uint32_with_lock.lock) {
nm_ip_route_set_attribute (route, nm_ip_route_set_attribute (route,
nm_sprintf_buf (buf1, "lock-%s", info->key), nm_sprintf_buf (buf1, "lock-%s", p_info->key),
g_variant_new_boolean (TRUE)); g_variant_new_boolean (TRUE));
} }
nm_ip_route_set_attribute (route, nm_ip_route_set_attribute (route,
info->key, p_info->key,
g_variant_new_uint32 (info->v.uint32_with_lock.uint32)); g_variant_new_uint32 (p_data->v.uint32_with_lock.uint32));
break; break;
case PARSE_LINE_TYPE_ADDR: case PARSE_LINE_TYPE_ADDR:
case PARSE_LINE_TYPE_ADDR_WITH_PREFIX: case PARSE_LINE_TYPE_ADDR_WITH_PREFIX:
nm_ip_route_set_attribute (route, nm_ip_route_set_attribute (route,
info->key, p_info->key,
g_variant_new_printf ("%s%s", g_variant_new_printf ("%s%s",
inet_ntop (addr_family, &info->v.addr.addr, buf1, sizeof (buf1)), inet_ntop (addr_family, &p_data->v.addr.addr, buf1, sizeof (buf1)),
info->v.addr.has_plen p_data->v.addr.has_plen
? nm_sprintf_buf (buf2, "/%u", (unsigned) info->v.addr.plen) ? nm_sprintf_buf (buf2, "/%u", (unsigned) p_data->v.addr.plen)
: "")); : ""));
break; break;
case PARSE_LINE_TYPE_FLAG: case PARSE_LINE_TYPE_FLAG:
@@ -1158,7 +1184,7 @@ next:
* of this attribute, hence, the file format cannot encode * of this attribute, hence, the file format cannot encode
* that configuration. */ * that configuration. */
nm_ip_route_set_attribute (route, nm_ip_route_set_attribute (route,
info->key, p_info->key,
g_variant_new_boolean (TRUE)); g_variant_new_boolean (TRUE));
break; break;
default: default: