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