Blame libnm-core/nm-libnm-core-aux/nm-libnm-core-aux.c

Packit Service b23acc
// SPDX-License-Identifier: LGPL-2.1+
Packit Service b23acc
/*
Packit Service b23acc
 * Copyright (C) 2019 Red Hat, Inc.
Packit Service b23acc
 */
Packit Service b23acc
Packit Service b23acc
#include "nm-default.h"
Packit Service b23acc
Packit Service b23acc
#include "nm-libnm-core-aux.h"
Packit Service b23acc
Packit Service b23acc
#include "nm-libnm-core-intern/nm-libnm-core-utils.h"
Packit Service b23acc
Packit Service b23acc
/*****************************************************************************/
Packit Service b23acc
Packit Service b23acc
typedef enum {
Packit Service b23acc
	KEY_TYPE_STRING,
Packit Service b23acc
	KEY_TYPE_INT,
Packit Service b23acc
	KEY_TYPE_BOOL,
Packit Service b23acc
} KeyType;
Packit Service b23acc
Packit Service b23acc
typedef struct {
Packit Service b23acc
	const char *str_val;
Packit Service b23acc
	union {
Packit Service b23acc
		int vint;
Packit Service b23acc
		bool vbool;
Packit Service b23acc
	} typ_val;
Packit Service b23acc
} ParseData;
Packit Service b23acc
Packit Service b23acc
typedef struct {
Packit Service b23acc
	const char *name;
Packit Service b23acc
	NMTeamLinkWatcherType watcher_type;
Packit Service b23acc
	KeyType key_type;
Packit Service b23acc
	union {
Packit Service b23acc
		int         (*fint)    (const NMTeamLinkWatcher *watcher);
Packit Service b23acc
		gboolean    (*fbool)   (const NMTeamLinkWatcher *watcher);
Packit Service b23acc
		const char *(*fstring) (const NMTeamLinkWatcher *watcher);
Packit Service b23acc
	} get_fcn;
Packit Service b23acc
	union {
Packit Service b23acc
		int vint;
Packit Service b23acc
		bool vbool;
Packit Service b23acc
	} def_val;
Packit Service b23acc
} TeamLinkWatcherKeyInfo;
Packit Service b23acc
Packit Service b23acc
static gboolean
Packit Service b23acc
_team_link_watcher_validate_active (const NMTeamLinkWatcher *watcher)
Packit Service b23acc
{
Packit Service b23acc
	return NM_FLAGS_HAS (nm_team_link_watcher_get_flags (watcher), NM_TEAM_LINK_WATCHER_ARP_PING_FLAG_VALIDATE_ACTIVE);
Packit Service b23acc
}
Packit Service b23acc
Packit Service b23acc
static gboolean
Packit Service b23acc
_team_link_watcher_validate_inactive (const NMTeamLinkWatcher *watcher)
Packit Service b23acc
{
Packit Service b23acc
	return NM_FLAGS_HAS (nm_team_link_watcher_get_flags (watcher), NM_TEAM_LINK_WATCHER_ARP_PING_FLAG_VALIDATE_INACTIVE);
Packit Service b23acc
}
Packit Service b23acc
Packit Service b23acc
static gboolean
Packit Service b23acc
_team_link_watcher_send_always (const NMTeamLinkWatcher *watcher)
Packit Service b23acc
{
Packit Service b23acc
	return NM_FLAGS_HAS (nm_team_link_watcher_get_flags (watcher), NM_TEAM_LINK_WATCHER_ARP_PING_FLAG_SEND_ALWAYS);
Packit Service b23acc
}
Packit Service b23acc
Packit Service b23acc
static const TeamLinkWatcherKeyInfo _team_link_watcher_key_infos[_NM_TEAM_LINK_WATCHER_KEY_NUM] = {
Packit Service b23acc
Packit Service b23acc
#define _KEY_INFO(key_id, _name, _watcher_type, _key_type, ...) \
Packit Service b23acc
	[key_id] = { .name = ""_name"", .watcher_type = (_watcher_type), .key_type = _key_type, ##__VA_ARGS__ }
Packit Service b23acc
Packit Service b23acc
	_KEY_INFO (NM_TEAM_LINK_WATCHER_KEY_NAME,              "name",              NM_TEAM_LINK_WATCHER_TYPE_ETHTOOL | NM_TEAM_LINK_WATCHER_TYPE_NSNAPING | NM_TEAM_LINK_WATCHER_TYPE_ARPING, KEY_TYPE_STRING, .get_fcn.fstring = nm_team_link_watcher_get_name,        ),
Packit Service b23acc
	_KEY_INFO (NM_TEAM_LINK_WATCHER_KEY_DELAY_UP,          "delay-up",          NM_TEAM_LINK_WATCHER_TYPE_ETHTOOL,                                                                         KEY_TYPE_INT,    .get_fcn.fint    = nm_team_link_watcher_get_delay_up,    ),
Packit Service b23acc
	_KEY_INFO (NM_TEAM_LINK_WATCHER_KEY_DELAY_DOWN,        "delay-down",        NM_TEAM_LINK_WATCHER_TYPE_ETHTOOL,                                                                         KEY_TYPE_INT,    .get_fcn.fint    = nm_team_link_watcher_get_delay_down,  ),
Packit Service b23acc
	_KEY_INFO (NM_TEAM_LINK_WATCHER_KEY_INIT_WAIT,         "init-wait",         NM_TEAM_LINK_WATCHER_TYPE_NSNAPING | NM_TEAM_LINK_WATCHER_TYPE_ARPING,                                     KEY_TYPE_INT,    .get_fcn.fint    = nm_team_link_watcher_get_init_wait,   ),
Packit Service b23acc
	_KEY_INFO (NM_TEAM_LINK_WATCHER_KEY_INTERVAL,          "interval",          NM_TEAM_LINK_WATCHER_TYPE_NSNAPING | NM_TEAM_LINK_WATCHER_TYPE_ARPING,                                     KEY_TYPE_INT,    .get_fcn.fint    = nm_team_link_watcher_get_interval,    ),
Packit Service b23acc
	_KEY_INFO (NM_TEAM_LINK_WATCHER_KEY_MISSED_MAX,        "missed-max",        NM_TEAM_LINK_WATCHER_TYPE_NSNAPING | NM_TEAM_LINK_WATCHER_TYPE_ARPING,                                     KEY_TYPE_INT,    .get_fcn.fint    = nm_team_link_watcher_get_missed_max,  .def_val.vint = 3, ),
Packit Service b23acc
	_KEY_INFO (NM_TEAM_LINK_WATCHER_KEY_TARGET_HOST,       "target-host",       NM_TEAM_LINK_WATCHER_TYPE_NSNAPING | NM_TEAM_LINK_WATCHER_TYPE_ARPING,                                     KEY_TYPE_STRING, .get_fcn.fstring = nm_team_link_watcher_get_target_host, ),
Packit Service b23acc
	_KEY_INFO (NM_TEAM_LINK_WATCHER_KEY_VLANID,            "vlanid",            NM_TEAM_LINK_WATCHER_TYPE_ARPING,                                                                          KEY_TYPE_INT,    .get_fcn.fint    = nm_team_link_watcher_get_vlanid,      .def_val.vint = -1, ),
Packit Service b23acc
	_KEY_INFO (NM_TEAM_LINK_WATCHER_KEY_SOURCE_HOST,       "source-host",       NM_TEAM_LINK_WATCHER_TYPE_ARPING,                                                                          KEY_TYPE_STRING, .get_fcn.fstring = nm_team_link_watcher_get_source_host, ),
Packit Service b23acc
	_KEY_INFO (NM_TEAM_LINK_WATCHER_KEY_VALIDATE_ACTIVE,   "validate-active",   NM_TEAM_LINK_WATCHER_TYPE_ARPING,                                                                          KEY_TYPE_BOOL,   .get_fcn.fbool   = _team_link_watcher_validate_active,   ),
Packit Service b23acc
	_KEY_INFO (NM_TEAM_LINK_WATCHER_KEY_VALIDATE_INACTIVE, "validate-inactive", NM_TEAM_LINK_WATCHER_TYPE_ARPING,                                                                          KEY_TYPE_BOOL,   .get_fcn.fbool   = _team_link_watcher_validate_inactive, ),
Packit Service b23acc
	_KEY_INFO (NM_TEAM_LINK_WATCHER_KEY_SEND_ALWAYS,       "send-always",       NM_TEAM_LINK_WATCHER_TYPE_ARPING,                                                                          KEY_TYPE_BOOL,   .get_fcn.fbool   = _team_link_watcher_send_always,       ),
Packit Service b23acc
Packit Service b23acc
};
Packit Service b23acc
Packit Service b23acc
static NMTeamLinkWatcherType
Packit Service b23acc
_team_link_watcher_get_watcher_type_from_name (const char *name)
Packit Service b23acc
{
Packit Service b23acc
	if (name) {
Packit Service b23acc
		if (nm_streq (name, NM_TEAM_LINK_WATCHER_ETHTOOL))
Packit Service b23acc
			return NM_TEAM_LINK_WATCHER_TYPE_ETHTOOL;
Packit Service b23acc
		if (nm_streq (name, NM_TEAM_LINK_WATCHER_NSNA_PING))
Packit Service b23acc
			return NM_TEAM_LINK_WATCHER_TYPE_NSNAPING;
Packit Service b23acc
		if (nm_streq (name, NM_TEAM_LINK_WATCHER_ARP_PING))
Packit Service b23acc
			return NM_TEAM_LINK_WATCHER_TYPE_ARPING;
Packit Service b23acc
	}
Packit Service b23acc
	return NM_TEAM_LINK_WATCHER_TYPE_NONE;
Packit Service b23acc
}
Packit Service b23acc
Packit Service b23acc
static const char *
Packit Service b23acc
_parse_data_get_str (const ParseData parse_data[static _NM_TEAM_LINK_WATCHER_KEY_NUM],
Packit Service b23acc
                     NMTeamLinkWatcherKeyId key_id)
Packit Service b23acc
{
Packit Service b23acc
	nm_assert (_NM_INT_NOT_NEGATIVE (key_id) && key_id < _NM_TEAM_LINK_WATCHER_KEY_NUM);
Packit Service b23acc
	nm_assert (_team_link_watcher_key_infos[key_id].key_type == KEY_TYPE_STRING);
Packit Service b23acc
Packit Service b23acc
	return parse_data[key_id].str_val;
Packit Service b23acc
}
Packit Service b23acc
Packit Service b23acc
static int
Packit Service b23acc
_parse_data_get_int (const ParseData parse_data[static _NM_TEAM_LINK_WATCHER_KEY_NUM],
Packit Service b23acc
                     NMTeamLinkWatcherKeyId key_id)
Packit Service b23acc
{
Packit Service b23acc
	nm_assert (_NM_INT_NOT_NEGATIVE (key_id) && key_id < _NM_TEAM_LINK_WATCHER_KEY_NUM);
Packit Service b23acc
	nm_assert (_team_link_watcher_key_infos[key_id].key_type == KEY_TYPE_INT);
Packit Service b23acc
Packit Service b23acc
	if (parse_data[key_id].str_val)
Packit Service b23acc
		return parse_data[key_id].typ_val.vint;
Packit Service b23acc
	return _team_link_watcher_key_infos[key_id].def_val.vint;
Packit Service b23acc
}
Packit Service b23acc
Packit Service b23acc
static int
Packit Service b23acc
_parse_data_get_bool (const ParseData parse_data[static _NM_TEAM_LINK_WATCHER_KEY_NUM],
Packit Service b23acc
                      NMTeamLinkWatcherKeyId key_id)
Packit Service b23acc
{
Packit Service b23acc
	nm_assert (_NM_INT_NOT_NEGATIVE (key_id) && key_id < _NM_TEAM_LINK_WATCHER_KEY_NUM);
Packit Service b23acc
	nm_assert (_team_link_watcher_key_infos[key_id].key_type == KEY_TYPE_BOOL);
Packit Service b23acc
Packit Service b23acc
	if (parse_data[key_id].str_val)
Packit Service b23acc
		return parse_data[key_id].typ_val.vbool;
Packit Service b23acc
	return _team_link_watcher_key_infos[key_id].def_val.vbool;
Packit Service b23acc
}
Packit Service b23acc
Packit Service b23acc
char *
Packit Service b23acc
nm_utils_team_link_watcher_to_string (const NMTeamLinkWatcher *watcher)
Packit Service b23acc
{
Packit Service b23acc
	nm_auto_free_gstring GString *str = NULL;
Packit Service b23acc
	const char *name;
Packit Service b23acc
	NMTeamLinkWatcherType watcher_type;
Packit Service b23acc
	NMTeamLinkWatcherKeyId key_id;
Packit Service b23acc
Packit Service b23acc
	if (!watcher)
Packit Service b23acc
		return NULL;
Packit Service b23acc
Packit Service b23acc
	str = g_string_new (NULL);
Packit Service b23acc
Packit Service b23acc
	name = nm_team_link_watcher_get_name (watcher);
Packit Service b23acc
	g_string_append_printf (str, "name=%s", name ?: "");
Packit Service b23acc
Packit Service b23acc
	watcher_type = _team_link_watcher_get_watcher_type_from_name (name);
Packit Service b23acc
Packit Service b23acc
	for (key_id = 0; key_id < _NM_TEAM_LINK_WATCHER_KEY_NUM; key_id++) {
Packit Service b23acc
		const TeamLinkWatcherKeyInfo *info = &_team_link_watcher_key_infos[key_id];
Packit Service b23acc
		const char *vstr;
Packit Service b23acc
		int vint;
Packit Service b23acc
		bool vbool;
Packit Service b23acc
Packit Service b23acc
		nm_assert (info->name && info->name && NM_STRCHAR_ALL (info->name, ch,((ch >= 'a' && ch <= 'z') || NM_IN_SET (ch, '-'))));
Packit Service b23acc
		nm_assert (NM_IN_SET (info->key_type, KEY_TYPE_STRING,
Packit Service b23acc
		                                      KEY_TYPE_INT,
Packit Service b23acc
		                                      KEY_TYPE_BOOL));
Packit Service b23acc
Packit Service b23acc
		if (key_id == NM_TEAM_LINK_WATCHER_KEY_NAME)
Packit Service b23acc
			continue;
Packit Service b23acc
Packit Service b23acc
		if (!NM_FLAGS_ALL (info->watcher_type, watcher_type))
Packit Service b23acc
			continue;
Packit Service b23acc
Packit Service b23acc
		switch (info->key_type) {
Packit Service b23acc
		case KEY_TYPE_STRING:
Packit Service b23acc
			vstr = info->get_fcn.fstring (watcher);
Packit Service b23acc
			if (vstr) {
Packit Service b23acc
				g_string_append_printf (nm_gstring_add_space_delimiter (str),
Packit Service b23acc
				                        "%s=%s", info->name, vstr);
Packit Service b23acc
			}
Packit Service b23acc
			break;
Packit Service b23acc
		case KEY_TYPE_INT:
Packit Service b23acc
			vint = info->get_fcn.fint (watcher);
Packit Service b23acc
			if (vint != info->def_val.vint) {
Packit Service b23acc
				g_string_append_printf (nm_gstring_add_space_delimiter (str),
Packit Service b23acc
				                        "%s=%d", info->name, vint);
Packit Service b23acc
			}
Packit Service b23acc
			break;
Packit Service b23acc
		case KEY_TYPE_BOOL:
Packit Service b23acc
			vbool = info->get_fcn.fbool (watcher);
Packit Service b23acc
			if (vbool != info->def_val.vbool) {
Packit Service b23acc
				g_string_append_printf (nm_gstring_add_space_delimiter (str),
Packit Service b23acc
				                        "%s=%s", info->name, vbool ? "true" : "false");
Packit Service b23acc
			}
Packit Service b23acc
			break;
Packit Service b23acc
		}
Packit Service b23acc
	}
Packit Service b23acc
Packit Service b23acc
	return g_string_free (g_steal_pointer (&str), FALSE);
Packit Service b23acc
}
Packit Service b23acc
Packit Service b23acc
NMTeamLinkWatcher *
Packit Service b23acc
nm_utils_team_link_watcher_from_string (const char *str,
Packit Service b23acc
                                        GError **error)
Packit Service b23acc
{
Packit Service b23acc
	gs_free const char **tokens = NULL;
Packit Service b23acc
	ParseData parse_data[_NM_TEAM_LINK_WATCHER_KEY_NUM] = { };
Packit Service b23acc
	NMTeamLinkWatcherType watcher_type;
Packit Service b23acc
	NMTeamLinkWatcherKeyId key_id;
Packit Service b23acc
	gsize i_token;
Packit Service b23acc
	NMTeamLinkWatcher *watcher;
Packit Service b23acc
	int errsv;
Packit Service b23acc
Packit Service b23acc
	g_return_val_if_fail (str, NULL);
Packit Service b23acc
	g_return_val_if_fail (!error || !*error, NULL);
Packit Service b23acc
Packit Service b23acc
	tokens = nm_utils_escaped_tokens_split (str, NM_ASCII_SPACES);
Packit Service b23acc
	if (!tokens) {
Packit Service b23acc
		g_set_error (error, 1, 0, "'%s' is not valid", str);
Packit Service b23acc
		return NULL;
Packit Service b23acc
	}
Packit Service b23acc
Packit Service b23acc
	for (i_token = 0; tokens[i_token]; i_token++) {
Packit Service b23acc
		const TeamLinkWatcherKeyInfo *info;
Packit Service b23acc
		const char *key = tokens[i_token];
Packit Service b23acc
		const char *val;
Packit Service b23acc
Packit Service b23acc
		val = strchr (key, '=');
Packit Service b23acc
		if (!val) {
Packit Service b23acc
			nm_utils_error_set (error, NM_UTILS_ERROR_UNKNOWN,
Packit Service b23acc
			                    _("'%s' is not valid: properties should be specified as 'key=value'"),
Packit Service b23acc
			                    key);
Packit Service b23acc
			return NULL;
Packit Service b23acc
		}
Packit Service b23acc
		((char *) val)[0] = '\0';
Packit Service b23acc
		val++;
Packit Service b23acc
Packit Service b23acc
		for (key_id = 0; key_id < _NM_TEAM_LINK_WATCHER_KEY_NUM; key_id++) {
Packit Service b23acc
			info = &_team_link_watcher_key_infos[key_id];
Packit Service b23acc
			if (nm_streq (key, info->name))
Packit Service b23acc
				break;
Packit Service b23acc
		}
Packit Service b23acc
Packit Service b23acc
		if (key_id == _NM_TEAM_LINK_WATCHER_KEY_NUM) {
Packit Service b23acc
			nm_utils_error_set (error, NM_UTILS_ERROR_UNKNOWN,
Packit Service b23acc
			                    _("'%s' is not a valid key"), key);
Packit Service b23acc
			return NULL;
Packit Service b23acc
		}
Packit Service b23acc
Packit Service b23acc
		if (parse_data[key_id].str_val) {
Packit Service b23acc
			nm_utils_error_set (error, NM_UTILS_ERROR_UNKNOWN,
Packit Service b23acc
			                    _("duplicate key '%s'"), key);
Packit Service b23acc
			return NULL;
Packit Service b23acc
		}
Packit Service b23acc
Packit Service b23acc
		parse_data[key_id].str_val = val;
Packit Service b23acc
Packit Service b23acc
		if (info->key_type == KEY_TYPE_INT) {
Packit Service b23acc
			gint64 v64;
Packit Service b23acc
Packit Service b23acc
			v64 = _nm_utils_ascii_str_to_int64 (val, 10, G_MININT, G_MAXINT, G_MAXINT64);
Packit Service b23acc
			if (   v64 == G_MAXINT64
Packit Service b23acc
			    && ((errsv = errno) != 0)) {
Packit Service b23acc
				if (errsv == ERANGE) {
Packit Service b23acc
					nm_utils_error_set (error, NM_UTILS_ERROR_UNKNOWN,
Packit Service b23acc
					                    _("number for '%s' is out of range"), key);
Packit Service b23acc
				} else {
Packit Service b23acc
					nm_utils_error_set (error, NM_UTILS_ERROR_UNKNOWN,
Packit Service b23acc
					                    _("value for '%s' must be a number"), key);
Packit Service b23acc
				}
Packit Service b23acc
				return NULL;
Packit Service b23acc
			}
Packit Service b23acc
			parse_data[key_id].typ_val.vint = v64;
Packit Service b23acc
		} else if (info->key_type == KEY_TYPE_BOOL) {
Packit Service b23acc
			int vbool;
Packit Service b23acc
Packit Service b23acc
			vbool = _nm_utils_ascii_str_to_bool (val, -1);
Packit Service b23acc
			if (vbool == -1) {
Packit Service b23acc
				nm_utils_error_set (error, NM_UTILS_ERROR_UNKNOWN,
Packit Service b23acc
				                    _("value for '%s' must be a boolean"), key);
Packit Service b23acc
				return NULL;
Packit Service b23acc
			}
Packit Service b23acc
			parse_data[key_id].typ_val.vbool = vbool;
Packit Service b23acc
		}
Packit Service b23acc
	}
Packit Service b23acc
Packit Service b23acc
	if (!parse_data[NM_TEAM_LINK_WATCHER_KEY_NAME].str_val) {
Packit Service b23acc
		nm_utils_error_set (error, NM_UTILS_ERROR_UNKNOWN,
Packit Service b23acc
		                    _("missing 'name' attribute"));
Packit Service b23acc
		return NULL;
Packit Service b23acc
	}
Packit Service b23acc
Packit Service b23acc
	watcher_type = _team_link_watcher_get_watcher_type_from_name (parse_data[NM_TEAM_LINK_WATCHER_KEY_NAME].str_val);
Packit Service b23acc
	if (watcher_type == NM_TEAM_LINK_WATCHER_TYPE_NONE) {
Packit Service b23acc
		nm_utils_error_set (error, NM_UTILS_ERROR_UNKNOWN,
Packit Service b23acc
		                    _("invalid 'name' \"%s\""),
Packit Service b23acc
		                    parse_data[NM_TEAM_LINK_WATCHER_KEY_NAME].str_val);
Packit Service b23acc
		return NULL;
Packit Service b23acc
	}
Packit Service b23acc
Packit Service b23acc
	for (key_id = 0; key_id < _NM_TEAM_LINK_WATCHER_KEY_NUM; key_id++) {
Packit Service b23acc
		const TeamLinkWatcherKeyInfo *info = &_team_link_watcher_key_infos[key_id];
Packit Service b23acc
Packit Service b23acc
		if (!parse_data[key_id].str_val)
Packit Service b23acc
			continue;
Packit Service b23acc
		if (!NM_FLAGS_ALL (info->watcher_type, watcher_type)) {
Packit Service b23acc
			nm_utils_error_set (error, NM_UTILS_ERROR_UNKNOWN,
Packit Service b23acc
			                    _("attribute '%s' is invalid for \"%s\""),
Packit Service b23acc
			                    info->name,
Packit Service b23acc
			                    parse_data[NM_TEAM_LINK_WATCHER_KEY_NAME].str_val);
Packit Service b23acc
			return NULL;
Packit Service b23acc
		}
Packit Service b23acc
	}
Packit Service b23acc
Packit Service b23acc
	switch (watcher_type) {
Packit Service b23acc
	case NM_TEAM_LINK_WATCHER_TYPE_ETHTOOL:
Packit Service b23acc
		watcher = nm_team_link_watcher_new_ethtool (_parse_data_get_int (parse_data, NM_TEAM_LINK_WATCHER_KEY_DELAY_UP),
Packit Service b23acc
		                                            _parse_data_get_int (parse_data, NM_TEAM_LINK_WATCHER_KEY_DELAY_DOWN),
Packit Service b23acc
		                                            error);
Packit Service b23acc
		break;
Packit Service b23acc
	case NM_TEAM_LINK_WATCHER_TYPE_NSNAPING:
Packit Service b23acc
		watcher = nm_team_link_watcher_new_nsna_ping (_parse_data_get_int (parse_data, NM_TEAM_LINK_WATCHER_KEY_INIT_WAIT),
Packit Service b23acc
		                                              _parse_data_get_int (parse_data, NM_TEAM_LINK_WATCHER_KEY_INTERVAL),
Packit Service b23acc
		                                              _parse_data_get_int (parse_data, NM_TEAM_LINK_WATCHER_KEY_MISSED_MAX),
Packit Service b23acc
		                                              _parse_data_get_str (parse_data, NM_TEAM_LINK_WATCHER_KEY_TARGET_HOST),
Packit Service b23acc
		                                              error);
Packit Service b23acc
		break;
Packit Service b23acc
	default:
Packit Service b23acc
		nm_assert (watcher_type == NM_TEAM_LINK_WATCHER_TYPE_ARPING);
Packit Service b23acc
		watcher = nm_team_link_watcher_new_arp_ping2 (_parse_data_get_int (parse_data, NM_TEAM_LINK_WATCHER_KEY_INIT_WAIT),
Packit Service b23acc
		                                              _parse_data_get_int (parse_data, NM_TEAM_LINK_WATCHER_KEY_INTERVAL),
Packit Service b23acc
		                                              _parse_data_get_int (parse_data, NM_TEAM_LINK_WATCHER_KEY_MISSED_MAX),
Packit Service b23acc
		                                              _parse_data_get_int (parse_data, NM_TEAM_LINK_WATCHER_KEY_VLANID),
Packit Service b23acc
		                                              _parse_data_get_str (parse_data, NM_TEAM_LINK_WATCHER_KEY_TARGET_HOST),
Packit Service b23acc
		                                              _parse_data_get_str (parse_data, NM_TEAM_LINK_WATCHER_KEY_SOURCE_HOST),
Packit Service b23acc
		                                              (  NM_TEAM_LINK_WATCHER_ARP_PING_FLAG_NONE
Packit Service b23acc
		                                               | (_parse_data_get_bool (parse_data, NM_TEAM_LINK_WATCHER_KEY_VALIDATE_ACTIVE)   ? NM_TEAM_LINK_WATCHER_ARP_PING_FLAG_VALIDATE_ACTIVE   : NM_TEAM_LINK_WATCHER_ARP_PING_FLAG_NONE)
Packit Service b23acc
		                                               | (_parse_data_get_bool (parse_data, NM_TEAM_LINK_WATCHER_KEY_VALIDATE_INACTIVE) ? NM_TEAM_LINK_WATCHER_ARP_PING_FLAG_VALIDATE_INACTIVE : NM_TEAM_LINK_WATCHER_ARP_PING_FLAG_NONE)
Packit Service b23acc
		                                               | (_parse_data_get_bool (parse_data, NM_TEAM_LINK_WATCHER_KEY_SEND_ALWAYS)       ? NM_TEAM_LINK_WATCHER_ARP_PING_FLAG_SEND_ALWAYS       : NM_TEAM_LINK_WATCHER_ARP_PING_FLAG_NONE)
Packit Service b23acc
		                                              ),
Packit Service b23acc
		                                              error);
Packit Service b23acc
		break;
Packit Service b23acc
	}
Packit Service b23acc
Packit Service b23acc
#if NM_MORE_ASSERTS > 5
Packit Service b23acc
	if (watcher) {
Packit Service b23acc
		gs_free char *str2 = NULL;
Packit Service b23acc
		nm_auto_unref_team_link_watcher NMTeamLinkWatcher *watcher2 = NULL;
Packit Service b23acc
		static _nm_thread_local int recursive;
Packit Service b23acc
Packit Service b23acc
		nm_assert (!error || !*error);
Packit Service b23acc
		if (recursive == 0) {
Packit Service b23acc
			recursive = 1;
Packit Service b23acc
			str2 = nm_utils_team_link_watcher_to_string (watcher);
Packit Service b23acc
			nm_assert (str2);
Packit Service b23acc
			watcher2 = nm_utils_team_link_watcher_from_string (str2, NULL);
Packit Service b23acc
			nm_assert (watcher2);
Packit Service b23acc
			nm_assert (nm_team_link_watcher_equal (watcher, watcher2));
Packit Service b23acc
			nm_assert (nm_team_link_watcher_equal (watcher2, watcher));
Packit Service b23acc
			nm_assert (recursive == 1);
Packit Service b23acc
			recursive = 0;
Packit Service b23acc
		}
Packit Service b23acc
	} else
Packit Service b23acc
		nm_assert (!error || *error);
Packit Service b23acc
#endif
Packit Service b23acc
Packit Service b23acc
	return watcher;
Packit Service b23acc
}