diff options
| -rw-r--r-- | eigrpd/eigrp_main.c | 2 | ||||
| -rw-r--r-- | lib/keychain.c | 1011 | ||||
| -rw-r--r-- | lib/keychain.h | 38 | ||||
| -rw-r--r-- | lib/keychain_cli.c | 1033 | ||||
| -rw-r--r-- | lib/keychain_nb.c | 1153 | ||||
| -rw-r--r-- | lib/subdir.am | 5 | ||||
| -rw-r--r-- | lib/yang_wrappers.c | 56 | ||||
| -rw-r--r-- | lib/yang_wrappers.h | 10 | ||||
| -rw-r--r-- | mgmtd/mgmt_be_adapter.c | 2 | ||||
| -rw-r--r-- | mgmtd/mgmt_main.c | 23 | ||||
| -rw-r--r-- | mgmtd/mgmt_vty.c | 2 | ||||
| -rw-r--r-- | ospf6d/ospf6_main.c | 20 | ||||
| -rw-r--r-- | ospfd/ospf_main.c | 2 | ||||
| -rw-r--r-- | python/xref2vtysh.py | 2 | ||||
| -rw-r--r-- | ripd/rip_main.c | 4 | ||||
| -rw-r--r-- | vtysh/vtysh.h | 2 | ||||
| -rw-r--r-- | zebra/zebra_nb_state.c | 2 | 
17 files changed, 1678 insertions, 1689 deletions
diff --git a/eigrpd/eigrp_main.c b/eigrpd/eigrp_main.c index 552ba7cd96..1491c569ec 100644 --- a/eigrpd/eigrp_main.c +++ b/eigrpd/eigrp_main.c @@ -132,6 +132,8 @@ static const struct frr_yang_module_info *const eigrpd_yang_modules[] = {  	&frr_interface_info,  	&frr_route_map_info,  	&frr_vrf_info, +	&ietf_key_chain_info, +	&ietf_key_chain_deviation_info,  };  /* clang-format off */ diff --git a/lib/keychain.c b/lib/keychain.c index 5ff0d1e43e..1982220bc7 100644 --- a/lib/keychain.c +++ b/lib/keychain.c @@ -6,19 +6,19 @@  #include "config.h"  #include <zebra.h> -#include "command.h" -#include "memory.h" -#include "linklist.h"  #include "keychain.h" +#include "linklist.h" +#include "memory.h" -DEFINE_MTYPE_STATIC(LIB, KEY, "Key"); -DEFINE_MTYPE_STATIC(LIB, KEYCHAIN, "Key chain"); +DEFINE_MTYPE(LIB, KEY, "Key"); +DEFINE_MTYPE(LIB, KEYCHAIN, "Key chain"); +DEFINE_MTYPE(LIB, KEYCHAIN_DESC, "Key chain description");  DEFINE_QOBJ_TYPE(keychain);  DEFINE_QOBJ_TYPE(key);  /* Master list of key chain. */ -static struct list *keychain_list; +struct list *keychain_list;  static struct keychain *keychain_new(void)  { @@ -82,7 +82,7 @@ static void key_delete_func(struct key *key)  	key_free(key);  } -static struct keychain *keychain_get(const char *name) +struct keychain *keychain_get(const char *name)  {  	struct keychain *keychain; @@ -101,7 +101,7 @@ static struct keychain *keychain_get(const char *name)  	return keychain;  } -static void keychain_delete(struct keychain *keychain) +void keychain_delete(struct keychain *keychain)  {  	XFREE(MTYPE_KEYCHAIN, keychain->name); @@ -110,7 +110,7 @@ static void keychain_delete(struct keychain *keychain)  	keychain_free(keychain);  } -static struct key *key_lookup(const struct keychain *keychain, uint32_t index) +struct key *key_lookup(const struct keychain *keychain, uint32_t index)  {  	struct listnode *node;  	struct key *key; @@ -183,7 +183,7 @@ struct key *key_lookup_for_send(const struct keychain *keychain)  	return NULL;  } -static struct key *key_get(const struct keychain *keychain, uint32_t index) +struct key *key_get(const struct keychain *keychain, uint32_t index)  {  	struct key *key; @@ -200,7 +200,7 @@ static struct key *key_get(const struct keychain *keychain, uint32_t index)  	return key;  } -static void key_delete(struct keychain *keychain, struct key *key) +void key_delete(struct keychain *keychain, struct key *key)  {  	listnode_delete(keychain->key, key); @@ -208,122 +208,6 @@ static void key_delete(struct keychain *keychain, struct key *key)  	key_free(key);  } -DEFUN_NOSH (key_chain, -       key_chain_cmd, -       "key chain WORD", -       "Authentication key management\n" -       "Key-chain management\n" -       "Key-chain name\n") -{ -	int idx_word = 2; -	struct keychain *keychain; - -	keychain = keychain_get(argv[idx_word]->arg); -	VTY_PUSH_CONTEXT(KEYCHAIN_NODE, keychain); - -	return CMD_SUCCESS; -} - -DEFUN (no_key_chain, -       no_key_chain_cmd, -       "no key chain WORD", -       NO_STR -       "Authentication key management\n" -       "Key-chain management\n" -       "Key-chain name\n") -{ -	int idx_word = 3; -	struct keychain *keychain; - -	keychain = keychain_lookup(argv[idx_word]->arg); - -	if (!keychain) { -		vty_out(vty, "Can't find keychain %s\n", argv[idx_word]->arg); -		return CMD_WARNING_CONFIG_FAILED; -	} - -	keychain_delete(keychain); - -	return CMD_SUCCESS; -} - -DEFUN_NOSH (key, -       key_cmd, -       "key (0-2147483647)", -       "Configure a key\n" -       "Key identifier number\n") -{ -	int idx_number = 1; -	VTY_DECLVAR_CONTEXT(keychain, keychain); -	struct key *key; -	uint32_t index; - -	index = strtoul(argv[idx_number]->arg, NULL, 10); -	key = key_get(keychain, index); -	VTY_PUSH_CONTEXT_SUB(KEYCHAIN_KEY_NODE, key); - -	return CMD_SUCCESS; -} - -DEFUN (no_key, -       no_key_cmd, -       "no key (0-2147483647)", -       NO_STR -       "Delete a key\n" -       "Key identifier number\n") -{ -	int idx_number = 2; -	VTY_DECLVAR_CONTEXT(keychain, keychain); -	struct key *key; -	uint32_t index; - -	index = strtoul(argv[idx_number]->arg, NULL, 10); -	key = key_lookup(keychain, index); -	if (!key) { -		vty_out(vty, "Can't find key %d\n", index); -		return CMD_WARNING_CONFIG_FAILED; -	} - -	key_delete(keychain, key); - -	vty->node = KEYCHAIN_NODE; - -	return CMD_SUCCESS; -} - -DEFUN (key_string, -       key_string_cmd, -       "key-string LINE", -       "Set key string\n" -       "The key\n") -{ -	int idx_line = 1; -	VTY_DECLVAR_CONTEXT_SUB(key, key); - -	if (key->string) -		XFREE(MTYPE_KEY, key->string); -	key->string = XSTRDUP(MTYPE_KEY, argv[idx_line]->arg); - -	return CMD_SUCCESS; -} - -DEFUN (no_key_string, -       no_key_string_cmd, -       "no key-string [LINE]", -       NO_STR -       "Unset key string\n" -       "The key\n") -{ -	VTY_DECLVAR_CONTEXT_SUB(key, key); - -	if (key->string) { -		XFREE(MTYPE_KEY, key->string); -		key->string = NULL; -	} - -	return CMD_SUCCESS; -} -  const struct keychain_algo_info algo_info[] = {  	{KEYCHAIN_ALGO_NULL, "null", 0, 0, "NULL"},  	{KEYCHAIN_ALGO_MD5, "md5", KEYCHAIN_MD5_HASH_SIZE, @@ -394,800 +278,6 @@ const char *keychain_get_algo_name_by_id(enum keychain_hash_algo key)  	return algo_info[key].name;  } -DEFUN(cryptographic_algorithm, cryptographic_algorithm_cmd, -      "cryptographic-algorithm " -      "<md5|hmac-sha-1|hmac-sha-256|hmac-sha-384|hmac-sha-512>", -      "Cryptographic-algorithm\n" -      "Use MD5 algorithm\n" -      "Use HMAC-SHA-1 algorithm\n" -      "Use HMAC-SHA-256 algorithm\n" -      "Use HMAC-SHA-384 algorithm\n" -      "Use HMAC-SHA-512 algorithm\n") -{ -	int algo_idx = 1; -	uint8_t hash_algo = KEYCHAIN_ALGO_NULL; - -	VTY_DECLVAR_CONTEXT_SUB(key, key); -	hash_algo = keychain_get_algo_id_by_name(argv[algo_idx]->arg); -#ifndef CRYPTO_OPENSSL -	if (hash_algo == KEYCHAIN_ALGO_NULL) { -		vty_out(vty, -			"Hash algorithm not supported, compile with --with-crypto=openssl\n"); -		return CMD_WARNING_CONFIG_FAILED; -	} -#endif /* CRYPTO_OPENSSL */ -	key->hash_algo = hash_algo; -	return CMD_SUCCESS; -} - -DEFUN(no_cryptographic_algorithm, no_cryptographic_algorithm_cmd, -      "no cryptographic-algorithm " -      "[<md5|hmac-sha-1|hmac-sha-256|hmac-sha-384|hmac-sha-512>]", -      NO_STR -      "Cryptographic-algorithm\n" -      "Use MD5 algorithm\n" -      "Use HMAC-SHA-1 algorithm\n" -      "Use HMAC-SHA-256 algorithm\n" -      "Use HMAC-SHA-384 algorithm\n" -      "Use HMAC-SHA-512 algorithm\n") -{ -	int algo_idx = 2; -	uint8_t hash_algo = KEYCHAIN_ALGO_NULL; - -	VTY_DECLVAR_CONTEXT_SUB(key, key); -	if (argc > algo_idx) { -		hash_algo = keychain_get_algo_id_by_name(argv[algo_idx]->arg); -		if (hash_algo == KEYCHAIN_ALGO_NULL) { -			vty_out(vty, -				"Hash algorithm not supported, try compiling with --with-crypto=openssl\n"); -			return CMD_WARNING_CONFIG_FAILED; -		} -	} - -	if ((hash_algo != KEYCHAIN_ALGO_NULL) && (hash_algo != key->hash_algo)) -		return CMD_SUCCESS; - -	key->hash_algo = KEYCHAIN_ALGO_NULL; -	return CMD_SUCCESS; -} - -/* Convert HH:MM:SS MON DAY YEAR to time_t value.  -1 is returned when -   given string is malformed. */ -static time_t key_str2time(const char *time_str, const char *day_str, -			   const char *month_str, const char *year_str) -{ -	int i = 0; -	char *colon; -	struct tm tm; -	time_t time; -	unsigned int sec, min, hour; -	unsigned int day, month, year; - -	const char *month_name[] = { -		"January",  "February", "March",  "April",     "May", -		"June",     "July",     "August", "September", "October", -		"November", "December", NULL}; - -#define _GET_LONG_RANGE(V, STR, MMCOND)                                        \ -	{                                                                      \ -		unsigned long tmpl;                                            \ -		char *endptr = NULL;                                           \ -		tmpl = strtoul((STR), &endptr, 10);                            \ -		if (*endptr != '\0' || tmpl == ULONG_MAX)                      \ -			return -1;                                             \ -		if (MMCOND)                                                    \ -			return -1;                                             \ -		(V) = tmpl;                                                    \ -	} -#define GET_LONG_RANGE(V, STR, MIN, MAX)                                       \ -	_GET_LONG_RANGE(V, STR, tmpl<(MIN) || tmpl>(MAX)) -#define GET_LONG_RANGE0(V, STR, MAX) _GET_LONG_RANGE(V, STR, tmpl > (MAX)) - -	/* Check hour field of time_str. */ -	colon = strchr(time_str, ':'); -	if (colon == NULL) -		return -1; -	*colon = '\0'; - -	/* Hour must be between 0 and 23. */ -	GET_LONG_RANGE0(hour, time_str, 23); - -	/* Check min field of time_str. */ -	time_str = colon + 1; -	colon = strchr(time_str, ':'); -	if (*time_str == '\0' || colon == NULL) -		return -1; -	*colon = '\0'; - -	/* Min must be between 0 and 59. */ -	GET_LONG_RANGE0(min, time_str, 59); - -	/* Check sec field of time_str. */ -	time_str = colon + 1; -	if (*time_str == '\0') -		return -1; - -	/* Sec must be between 0 and 59. */ -	GET_LONG_RANGE0(sec, time_str, 59); - -	/* Check day_str.  Day must be <1-31>. */ -	GET_LONG_RANGE(day, day_str, 1, 31); - -	/* Check month_str.  Month must match month_name. */ -	month = 0; -	if (strlen(month_str) >= 3) -		for (i = 0; month_name[i]; i++) -			if (strncmp(month_str, month_name[i], strlen(month_str)) -			    == 0) { -				month = i; -				break; -			} -	if (!month_name[i]) -		return -1; - -	/* Check year_str.  Year must be <1993-2035>. */ -	GET_LONG_RANGE(year, year_str, 1993, 2035); - -	memset(&tm, 0, sizeof(tm)); -	tm.tm_sec = sec; -	tm.tm_min = min; -	tm.tm_hour = hour; -	tm.tm_mon = month; -	tm.tm_mday = day; -	tm.tm_year = year - 1900; - -	time = mktime(&tm); - -	return time; -#undef GET_LONG_RANGE -} - -static int key_lifetime_set(struct vty *vty, struct key_range *krange, -			    const char *stime_str, const char *sday_str, -			    const char *smonth_str, const char *syear_str, -			    const char *etime_str, const char *eday_str, -			    const char *emonth_str, const char *eyear_str) -{ -	time_t time_start; -	time_t time_end; - -	time_start = key_str2time(stime_str, sday_str, smonth_str, syear_str); -	if (time_start < 0) { -		vty_out(vty, "Malformed time value\n"); -		return CMD_WARNING_CONFIG_FAILED; -	} -	time_end = key_str2time(etime_str, eday_str, emonth_str, eyear_str); - -	if (time_end < 0) { -		vty_out(vty, "Malformed time value\n"); -		return CMD_WARNING_CONFIG_FAILED; -	} - -	if (time_end <= time_start) { -		vty_out(vty, "Expire time is not later than start time\n"); -		return CMD_WARNING_CONFIG_FAILED; -	} - -	krange->start = time_start; -	krange->end = time_end; - -	return CMD_SUCCESS; -} - -static int key_lifetime_duration_set(struct vty *vty, struct key_range *krange, -				     const char *stime_str, -				     const char *sday_str, -				     const char *smonth_str, -				     const char *syear_str, -				     const char *duration_str) -{ -	time_t time_start; -	uint32_t duration; - -	time_start = key_str2time(stime_str, sday_str, smonth_str, syear_str); -	if (time_start < 0) { -		vty_out(vty, "Malformed time value\n"); -		return CMD_WARNING_CONFIG_FAILED; -	} -	krange->start = time_start; - -	duration = strtoul(duration_str, NULL, 10); -	krange->duration = 1; -	krange->end = time_start + duration; - -	return CMD_SUCCESS; -} - -static int key_lifetime_infinite_set(struct vty *vty, struct key_range *krange, -				     const char *stime_str, -				     const char *sday_str, -				     const char *smonth_str, -				     const char *syear_str) -{ -	time_t time_start; - -	time_start = key_str2time(stime_str, sday_str, smonth_str, syear_str); -	if (time_start < 0) { -		vty_out(vty, "Malformed time value\n"); -		return CMD_WARNING_CONFIG_FAILED; -	} -	krange->start = time_start; - -	krange->end = -1; - -	return CMD_SUCCESS; -} - -DEFUN (accept_lifetime_day_month_day_month, -       accept_lifetime_day_month_day_month_cmd, -       "accept-lifetime HH:MM:SS (1-31) MONTH (1993-2035) HH:MM:SS (1-31) MONTH (1993-2035)", -       "Set accept lifetime of the key\n" -       "Time to start\n" -       "Day of th month to start\n" -       "Month of the year to start\n" -       "Year to start\n" -       "Time to expire\n" -       "Day of th month to expire\n" -       "Month of the year to expire\n" -       "Year to expire\n") -{ -	int idx_hhmmss = 1; -	int idx_number = 2; -	int idx_month = 3; -	int idx_number_2 = 4; -	int idx_hhmmss_2 = 5; -	int idx_number_3 = 6; -	int idx_month_2 = 7; -	int idx_number_4 = 8; -	VTY_DECLVAR_CONTEXT_SUB(key, key); - -	return key_lifetime_set( -		vty, &key->accept, argv[idx_hhmmss]->arg, argv[idx_number]->arg, -		argv[idx_month]->arg, argv[idx_number_2]->arg, -		argv[idx_hhmmss_2]->arg, argv[idx_number_3]->arg, -		argv[idx_month_2]->arg, argv[idx_number_4]->arg); -} - -DEFUN (accept_lifetime_day_month_month_day, -       accept_lifetime_day_month_month_day_cmd, -       "accept-lifetime HH:MM:SS (1-31) MONTH (1993-2035) HH:MM:SS MONTH (1-31) (1993-2035)", -       "Set accept lifetime of the key\n" -       "Time to start\n" -       "Day of th month to start\n" -       "Month of the year to start\n" -       "Year to start\n" -       "Time to expire\n" -       "Month of the year to expire\n" -       "Day of th month to expire\n" -       "Year to expire\n") -{ -	int idx_hhmmss = 1; -	int idx_number = 2; -	int idx_month = 3; -	int idx_number_2 = 4; -	int idx_hhmmss_2 = 5; -	int idx_month_2 = 6; -	int idx_number_3 = 7; -	int idx_number_4 = 8; -	VTY_DECLVAR_CONTEXT_SUB(key, key); - -	return key_lifetime_set( -		vty, &key->accept, argv[idx_hhmmss]->arg, argv[idx_number]->arg, -		argv[idx_month]->arg, argv[idx_number_2]->arg, -		argv[idx_hhmmss_2]->arg, argv[idx_number_3]->arg, -		argv[idx_month_2]->arg, argv[idx_number_4]->arg); -} - -DEFUN (accept_lifetime_month_day_day_month, -       accept_lifetime_month_day_day_month_cmd, -       "accept-lifetime HH:MM:SS MONTH (1-31) (1993-2035) HH:MM:SS (1-31) MONTH (1993-2035)", -       "Set accept lifetime of the key\n" -       "Time to start\n" -       "Month of the year to start\n" -       "Day of th month to start\n" -       "Year to start\n" -       "Time to expire\n" -       "Day of th month to expire\n" -       "Month of the year to expire\n" -       "Year to expire\n") -{ -	int idx_hhmmss = 1; -	int idx_month = 2; -	int idx_number = 3; -	int idx_number_2 = 4; -	int idx_hhmmss_2 = 5; -	int idx_number_3 = 6; -	int idx_month_2 = 7; -	int idx_number_4 = 8; -	VTY_DECLVAR_CONTEXT_SUB(key, key); - -	return key_lifetime_set( -		vty, &key->accept, argv[idx_hhmmss]->arg, argv[idx_number]->arg, -		argv[idx_month]->arg, argv[idx_number_2]->arg, -		argv[idx_hhmmss_2]->arg, argv[idx_number_3]->arg, -		argv[idx_month_2]->arg, argv[idx_number_4]->arg); -} - -DEFUN (accept_lifetime_month_day_month_day, -       accept_lifetime_month_day_month_day_cmd, -       "accept-lifetime HH:MM:SS MONTH (1-31) (1993-2035) HH:MM:SS MONTH (1-31) (1993-2035)", -       "Set accept lifetime of the key\n" -       "Time to start\n" -       "Month of the year to start\n" -       "Day of th month to start\n" -       "Year to start\n" -       "Time to expire\n" -       "Month of the year to expire\n" -       "Day of th month to expire\n" -       "Year to expire\n") -{ -	int idx_hhmmss = 1; -	int idx_month = 2; -	int idx_number = 3; -	int idx_number_2 = 4; -	int idx_hhmmss_2 = 5; -	int idx_month_2 = 6; -	int idx_number_3 = 7; -	int idx_number_4 = 8; -	VTY_DECLVAR_CONTEXT_SUB(key, key); - -	return key_lifetime_set( -		vty, &key->accept, argv[idx_hhmmss]->arg, argv[idx_number]->arg, -		argv[idx_month]->arg, argv[idx_number_2]->arg, -		argv[idx_hhmmss_2]->arg, argv[idx_number_3]->arg, -		argv[idx_month_2]->arg, argv[idx_number_4]->arg); -} - -DEFUN (accept_lifetime_infinite_day_month, -       accept_lifetime_infinite_day_month_cmd, -       "accept-lifetime HH:MM:SS (1-31) MONTH (1993-2035) infinite", -       "Set accept lifetime of the key\n" -       "Time to start\n" -       "Day of th month to start\n" -       "Month of the year to start\n" -       "Year to start\n" -       "Never expires\n") -{ -	int idx_hhmmss = 1; -	int idx_number = 2; -	int idx_month = 3; -	int idx_number_2 = 4; -	VTY_DECLVAR_CONTEXT_SUB(key, key); - -	return key_lifetime_infinite_set( -		vty, &key->accept, argv[idx_hhmmss]->arg, argv[idx_number]->arg, -		argv[idx_month]->arg, argv[idx_number_2]->arg); -} - -DEFUN (accept_lifetime_infinite_month_day, -       accept_lifetime_infinite_month_day_cmd, -       "accept-lifetime HH:MM:SS MONTH (1-31) (1993-2035) infinite", -       "Set accept lifetime of the key\n" -       "Time to start\n" -       "Month of the year to start\n" -       "Day of th month to start\n" -       "Year to start\n" -       "Never expires\n") -{ -	int idx_hhmmss = 1; -	int idx_month = 2; -	int idx_number = 3; -	int idx_number_2 = 4; -	VTY_DECLVAR_CONTEXT_SUB(key, key); - -	return key_lifetime_infinite_set( -		vty, &key->accept, argv[idx_hhmmss]->arg, argv[idx_number]->arg, -		argv[idx_month]->arg, argv[idx_number_2]->arg); -} - -DEFUN (accept_lifetime_duration_day_month, -       accept_lifetime_duration_day_month_cmd, -       "accept-lifetime HH:MM:SS (1-31) MONTH (1993-2035) duration (1-2147483646)", -       "Set accept lifetime of the key\n" -       "Time to start\n" -       "Day of th month to start\n" -       "Month of the year to start\n" -       "Year to start\n" -       "Duration of the key\n" -       "Duration seconds\n") -{ -	int idx_hhmmss = 1; -	int idx_number = 2; -	int idx_month = 3; -	int idx_number_2 = 4; -	int idx_number_3 = 6; -	VTY_DECLVAR_CONTEXT_SUB(key, key); - -	return key_lifetime_duration_set( -		vty, &key->accept, argv[idx_hhmmss]->arg, argv[idx_number]->arg, -		argv[idx_month]->arg, argv[idx_number_2]->arg, -		argv[idx_number_3]->arg); -} - -DEFUN (accept_lifetime_duration_month_day, -       accept_lifetime_duration_month_day_cmd, -       "accept-lifetime HH:MM:SS MONTH (1-31) (1993-2035) duration (1-2147483646)", -       "Set accept lifetime of the key\n" -       "Time to start\n" -       "Month of the year to start\n" -       "Day of th month to start\n" -       "Year to start\n" -       "Duration of the key\n" -       "Duration seconds\n") -{ -	int idx_hhmmss = 1; -	int idx_month = 2; -	int idx_number = 3; -	int idx_number_2 = 4; -	int idx_number_3 = 6; -	VTY_DECLVAR_CONTEXT_SUB(key, key); - -	return key_lifetime_duration_set( -		vty, &key->accept, argv[idx_hhmmss]->arg, argv[idx_number]->arg, -		argv[idx_month]->arg, argv[idx_number_2]->arg, -		argv[idx_number_3]->arg); -} - -DEFUN (no_accept_lifetime, -       no_accept_lifetime_cmd, -       "no accept-lifetime", -       NO_STR -       "Unset accept-lifetime\n") -{ -	VTY_DECLVAR_CONTEXT_SUB(key, key); - -	if (key->accept.start) -		key->accept.start = 0; -	if (key->accept.end) -		key->accept.end = 0; -	if (key->accept.duration) -		key->accept.duration = 0; - -	return CMD_SUCCESS; -} - -DEFUN (send_lifetime_day_month_day_month, -       send_lifetime_day_month_day_month_cmd, -       "send-lifetime HH:MM:SS (1-31) MONTH (1993-2035) HH:MM:SS (1-31) MONTH (1993-2035)", -       "Set send lifetime of the key\n" -       "Time to start\n" -       "Day of th month to start\n" -       "Month of the year to start\n" -       "Year to start\n" -       "Time to expire\n" -       "Day of th month to expire\n" -       "Month of the year to expire\n" -       "Year to expire\n") -{ -	int idx_hhmmss = 1; -	int idx_number = 2; -	int idx_month = 3; -	int idx_number_2 = 4; -	int idx_hhmmss_2 = 5; -	int idx_number_3 = 6; -	int idx_month_2 = 7; -	int idx_number_4 = 8; -	VTY_DECLVAR_CONTEXT_SUB(key, key); - -	return key_lifetime_set( -		vty, &key->send, argv[idx_hhmmss]->arg, argv[idx_number]->arg, -		argv[idx_month]->arg, argv[idx_number_2]->arg, -		argv[idx_hhmmss_2]->arg, argv[idx_number_3]->arg, -		argv[idx_month_2]->arg, argv[idx_number_4]->arg); -} - -DEFUN (send_lifetime_day_month_month_day, -       send_lifetime_day_month_month_day_cmd, -       "send-lifetime HH:MM:SS (1-31) MONTH (1993-2035) HH:MM:SS MONTH (1-31) (1993-2035)", -       "Set send lifetime of the key\n" -       "Time to start\n" -       "Day of th month to start\n" -       "Month of the year to start\n" -       "Year to start\n" -       "Time to expire\n" -       "Month of the year to expire\n" -       "Day of th month to expire\n" -       "Year to expire\n") -{ -	int idx_hhmmss = 1; -	int idx_number = 2; -	int idx_month = 3; -	int idx_number_2 = 4; -	int idx_hhmmss_2 = 5; -	int idx_month_2 = 6; -	int idx_number_3 = 7; -	int idx_number_4 = 8; -	VTY_DECLVAR_CONTEXT_SUB(key, key); - -	return key_lifetime_set( -		vty, &key->send, argv[idx_hhmmss]->arg, argv[idx_number]->arg, -		argv[idx_month]->arg, argv[idx_number_2]->arg, -		argv[idx_hhmmss_2]->arg, argv[idx_number_3]->arg, -		argv[idx_month_2]->arg, argv[idx_number_4]->arg); -} - -DEFUN (send_lifetime_month_day_day_month, -       send_lifetime_month_day_day_month_cmd, -       "send-lifetime HH:MM:SS MONTH (1-31) (1993-2035) HH:MM:SS (1-31) MONTH (1993-2035)", -       "Set send lifetime of the key\n" -       "Time to start\n" -       "Month of the year to start\n" -       "Day of th month to start\n" -       "Year to start\n" -       "Time to expire\n" -       "Day of th month to expire\n" -       "Month of the year to expire\n" -       "Year to expire\n") -{ -	int idx_hhmmss = 1; -	int idx_month = 2; -	int idx_number = 3; -	int idx_number_2 = 4; -	int idx_hhmmss_2 = 5; -	int idx_number_3 = 6; -	int idx_month_2 = 7; -	int idx_number_4 = 8; -	VTY_DECLVAR_CONTEXT_SUB(key, key); - -	return key_lifetime_set( -		vty, &key->send, argv[idx_hhmmss]->arg, argv[idx_number]->arg, -		argv[idx_month]->arg, argv[idx_number_2]->arg, -		argv[idx_hhmmss_2]->arg, argv[idx_number_3]->arg, -		argv[idx_month_2]->arg, argv[idx_number_4]->arg); -} - -DEFUN (send_lifetime_month_day_month_day, -       send_lifetime_month_day_month_day_cmd, -       "send-lifetime HH:MM:SS MONTH (1-31) (1993-2035) HH:MM:SS MONTH (1-31) (1993-2035)", -       "Set send lifetime of the key\n" -       "Time to start\n" -       "Month of the year to start\n" -       "Day of th month to start\n" -       "Year to start\n" -       "Time to expire\n" -       "Month of the year to expire\n" -       "Day of th month to expire\n" -       "Year to expire\n") -{ -	int idx_hhmmss = 1; -	int idx_month = 2; -	int idx_number = 3; -	int idx_number_2 = 4; -	int idx_hhmmss_2 = 5; -	int idx_month_2 = 6; -	int idx_number_3 = 7; -	int idx_number_4 = 8; -	VTY_DECLVAR_CONTEXT_SUB(key, key); - -	return key_lifetime_set( -		vty, &key->send, argv[idx_hhmmss]->arg, argv[idx_number]->arg, -		argv[idx_month]->arg, argv[idx_number_2]->arg, -		argv[idx_hhmmss_2]->arg, argv[idx_number_3]->arg, -		argv[idx_month_2]->arg, argv[idx_number_4]->arg); -} - -DEFUN (send_lifetime_infinite_day_month, -       send_lifetime_infinite_day_month_cmd, -       "send-lifetime HH:MM:SS (1-31) MONTH (1993-2035) infinite", -       "Set send lifetime of the key\n" -       "Time to start\n" -       "Day of th month to start\n" -       "Month of the year to start\n" -       "Year to start\n" -       "Never expires\n") -{ -	int idx_hhmmss = 1; -	int idx_number = 2; -	int idx_month = 3; -	int idx_number_2 = 4; -	VTY_DECLVAR_CONTEXT_SUB(key, key); - -	return key_lifetime_infinite_set( -		vty, &key->send, argv[idx_hhmmss]->arg, argv[idx_number]->arg, -		argv[idx_month]->arg, argv[idx_number_2]->arg); -} - -DEFUN (send_lifetime_infinite_month_day, -       send_lifetime_infinite_month_day_cmd, -       "send-lifetime HH:MM:SS MONTH (1-31) (1993-2035) infinite", -       "Set send lifetime of the key\n" -       "Time to start\n" -       "Month of the year to start\n" -       "Day of th month to start\n" -       "Year to start\n" -       "Never expires\n") -{ -	int idx_hhmmss = 1; -	int idx_month = 2; -	int idx_number = 3; -	int idx_number_2 = 4; -	VTY_DECLVAR_CONTEXT_SUB(key, key); - -	return key_lifetime_infinite_set( -		vty, &key->send, argv[idx_hhmmss]->arg, argv[idx_number]->arg, -		argv[idx_month]->arg, argv[idx_number_2]->arg); -} - -DEFUN (send_lifetime_duration_day_month, -       send_lifetime_duration_day_month_cmd, -       "send-lifetime HH:MM:SS (1-31) MONTH (1993-2035) duration (1-2147483646)", -       "Set send lifetime of the key\n" -       "Time to start\n" -       "Day of th month to start\n" -       "Month of the year to start\n" -       "Year to start\n" -       "Duration of the key\n" -       "Duration seconds\n") -{ -	int idx_hhmmss = 1; -	int idx_number = 2; -	int idx_month = 3; -	int idx_number_2 = 4; -	int idx_number_3 = 6; -	VTY_DECLVAR_CONTEXT_SUB(key, key); - -	return key_lifetime_duration_set( -		vty, &key->send, argv[idx_hhmmss]->arg, argv[idx_number]->arg, -		argv[idx_month]->arg, argv[idx_number_2]->arg, -		argv[idx_number_3]->arg); -} - -DEFUN (send_lifetime_duration_month_day, -       send_lifetime_duration_month_day_cmd, -       "send-lifetime HH:MM:SS MONTH (1-31) (1993-2035) duration (1-2147483646)", -       "Set send lifetime of the key\n" -       "Time to start\n" -       "Month of the year to start\n" -       "Day of th month to start\n" -       "Year to start\n" -       "Duration of the key\n" -       "Duration seconds\n") -{ -	int idx_hhmmss = 1; -	int idx_month = 2; -	int idx_number = 3; -	int idx_number_2 = 4; -	int idx_number_3 = 6; -	VTY_DECLVAR_CONTEXT_SUB(key, key); - -	return key_lifetime_duration_set( -		vty, &key->send, argv[idx_hhmmss]->arg, argv[idx_number]->arg, -		argv[idx_month]->arg, argv[idx_number_2]->arg, -		argv[idx_number_3]->arg); -} - -DEFUN (no_send_lifetime, -       no_send_lifetime_cmd, -       "no send-lifetime", -       NO_STR -       "Unset send-lifetime\n") -{ -	VTY_DECLVAR_CONTEXT_SUB(key, key); - -	if (key->send.start) -		key->send.start = 0; -	if (key->send.end) -		key->send.end = 0; -	if (key->send.duration) -		key->send.duration = 0; - -	return CMD_SUCCESS; -} - -static int keychain_config_write(struct vty *vty); -static struct cmd_node keychain_node = { -	.name = "keychain", -	.node = KEYCHAIN_NODE, -	.parent_node = CONFIG_NODE, -	.prompt = "%s(config-keychain)# ", -	.config_write = keychain_config_write, -}; - -static struct cmd_node keychain_key_node = { -	.name = "keychain key", -	.node = KEYCHAIN_KEY_NODE, -	.parent_node = KEYCHAIN_NODE, -	.prompt = "%s(config-keychain-key)# ", -}; - -static int keychain_strftime(char *buf, int bufsiz, time_t *time) -{ -	struct tm tm; -	size_t len; - -	localtime_r(time, &tm); - -	len = strftime(buf, bufsiz, "%T %b %d %Y", &tm); - -	return len; -} - -static int keychain_config_write(struct vty *vty) -{ -	struct keychain *keychain; -	struct key *key; -	struct listnode *node; -	struct listnode *knode; -	char buf[BUFSIZ]; - -	for (ALL_LIST_ELEMENTS_RO(keychain_list, node, keychain)) { -		vty_out(vty, "key chain %s\n", keychain->name); - -		for (ALL_LIST_ELEMENTS_RO(keychain->key, knode, key)) { -			vty_out(vty, " key %d\n", key->index); - -			if (key->string) -				vty_out(vty, "  key-string %s\n", key->string); - -			if (key->hash_algo != KEYCHAIN_ALGO_NULL) -				vty_out(vty, "  cryptographic-algorithm %s\n", -					keychain_get_algo_name_by_id( -						key->hash_algo)); - -			if (key->accept.start) { -				keychain_strftime(buf, BUFSIZ, -						  &key->accept.start); -				vty_out(vty, "  accept-lifetime %s", buf); - -				if (key->accept.end == -1) -					vty_out(vty, " infinite"); -				else if (key->accept.duration) -					vty_out(vty, " duration %ld", -						(long)(key->accept.end -						       - key->accept.start)); -				else { -					keychain_strftime(buf, BUFSIZ, -							  &key->accept.end); -					vty_out(vty, " %s", buf); -				} -				vty_out(vty, "\n"); -			} - -			if (key->send.start) { -				keychain_strftime(buf, BUFSIZ, -						  &key->send.start); -				vty_out(vty, "  send-lifetime %s", buf); - -				if (key->send.end == -1) -					vty_out(vty, " infinite"); -				else if (key->send.duration) -					vty_out(vty, " duration %ld", -						(long)(key->send.end -						       - key->send.start)); -				else { -					keychain_strftime(buf, BUFSIZ, -							  &key->send.end); -					vty_out(vty, " %s", buf); -				} -				vty_out(vty, "\n"); -			} - -			vty_out(vty, " exit\n"); -		} -		vty_out(vty, "exit\n"); -		vty_out(vty, "!\n"); -	} - -	return 0; -} - - -static void keychain_active_config(vector comps, struct cmd_token *token) -{ -	struct keychain *keychain; -	struct listnode *node; - -	for (ALL_LIST_ELEMENTS_RO(keychain_list, node, keychain)) -		vector_set(comps, XSTRDUP(MTYPE_COMPLETION, keychain->name)); -} - -static const struct cmd_variable_handler keychain_var_handlers[] = { -	{.varname = "key_chain", .completions = keychain_active_config}, -	{.tokenname = "KEYCHAIN_NAME", .completions = keychain_active_config}, -	{.tokenname = "KCHAIN_NAME", .completions = keychain_active_config}, -	{.completions = NULL} -}; -  void keychain_terminate(void)  {  	struct keychain *keychain; @@ -1202,70 +292,25 @@ void keychain_terminate(void)  	list_delete(&keychain_list);  } -void keychain_init(void) +void keychain_init_new(bool in_backend)  {  	keychain_list = list_new(); -	/* Register handler for keychain auto config support */ -	cmd_variable_handler_register(keychain_var_handlers); -	install_node(&keychain_node); -	install_node(&keychain_key_node); - -	install_default(KEYCHAIN_NODE); -	install_default(KEYCHAIN_KEY_NODE); - -	install_element(CONFIG_NODE, &key_chain_cmd); -	install_element(CONFIG_NODE, &no_key_chain_cmd); -	install_element(KEYCHAIN_NODE, &key_cmd); -	install_element(KEYCHAIN_NODE, &no_key_cmd); - -	install_element(KEYCHAIN_NODE, &key_chain_cmd); -	install_element(KEYCHAIN_NODE, &no_key_chain_cmd); - -	install_element(KEYCHAIN_KEY_NODE, &key_string_cmd); -	install_element(KEYCHAIN_KEY_NODE, &no_key_string_cmd); - -	install_element(KEYCHAIN_KEY_NODE, &key_chain_cmd); -	install_element(KEYCHAIN_KEY_NODE, &no_key_chain_cmd); - -	install_element(KEYCHAIN_KEY_NODE, &key_cmd); -	install_element(KEYCHAIN_KEY_NODE, &no_key_cmd); - -	install_element(KEYCHAIN_KEY_NODE, -			&accept_lifetime_day_month_day_month_cmd); -	install_element(KEYCHAIN_KEY_NODE, -			&accept_lifetime_day_month_month_day_cmd); -	install_element(KEYCHAIN_KEY_NODE, -			&accept_lifetime_month_day_day_month_cmd); -	install_element(KEYCHAIN_KEY_NODE, -			&accept_lifetime_month_day_month_day_cmd); -	install_element(KEYCHAIN_KEY_NODE, -			&accept_lifetime_infinite_day_month_cmd); -	install_element(KEYCHAIN_KEY_NODE, -			&accept_lifetime_infinite_month_day_cmd); -	install_element(KEYCHAIN_KEY_NODE, -			&accept_lifetime_duration_day_month_cmd); -	install_element(KEYCHAIN_KEY_NODE, -			&accept_lifetime_duration_month_day_cmd); -	install_element(KEYCHAIN_KEY_NODE, &no_accept_lifetime_cmd); +	if (!in_backend) +		keychain_cli_init(); +} -	install_element(KEYCHAIN_KEY_NODE, -			&send_lifetime_day_month_day_month_cmd); -	install_element(KEYCHAIN_KEY_NODE, -			&send_lifetime_day_month_month_day_cmd); -	install_element(KEYCHAIN_KEY_NODE, -			&send_lifetime_month_day_day_month_cmd); -	install_element(KEYCHAIN_KEY_NODE, -			&send_lifetime_month_day_month_day_cmd); -	install_element(KEYCHAIN_KEY_NODE, -			&send_lifetime_infinite_day_month_cmd); -	install_element(KEYCHAIN_KEY_NODE, -			&send_lifetime_infinite_month_day_cmd); -	install_element(KEYCHAIN_KEY_NODE, -			&send_lifetime_duration_day_month_cmd); -	install_element(KEYCHAIN_KEY_NODE, -			&send_lifetime_duration_month_day_cmd); -	install_element(KEYCHAIN_KEY_NODE, &no_send_lifetime_cmd); -	install_element(KEYCHAIN_KEY_NODE, &cryptographic_algorithm_cmd); -	install_element(KEYCHAIN_KEY_NODE, &no_cryptographic_algorithm_cmd); +void keychain_init(void) +{ +	keychain_init_new(false);  } + +const struct frr_yang_module_info ietf_key_chain_deviation_info = { +	.name = "frr-deviations-ietf-key-chain", +	.ignore_cfg_cbs = true, +	.nodes = { +		{ +			.xpath = NULL, +		}, +	}, +}; diff --git a/lib/keychain.h b/lib/keychain.h index c96b74ecce..dc35c2ea39 100644 --- a/lib/keychain.h +++ b/lib/keychain.h @@ -6,6 +6,8 @@  #ifndef _ZEBRA_KEYCHAIN_H  #define _ZEBRA_KEYCHAIN_H +#include "memory.h" +#include "northbound.h"  #include "qobj.h"  #ifdef __cplusplus @@ -44,6 +46,10 @@ struct keychain_algo_info {  	const char *desc;  }; +extern const struct frr_yang_module_info ietf_key_chain_info; +extern const struct frr_yang_module_info ietf_key_chain_cli_info; +extern const struct frr_yang_module_info ietf_key_chain_deviation_info; +  extern const struct keychain_algo_info algo_info[];  uint16_t keychain_get_block_size(enum keychain_hash_algo key);  uint16_t keychain_get_hash_len(enum keychain_hash_algo key); @@ -55,6 +61,8 @@ const char *keychain_get_algo_name_by_id(enum keychain_hash_algo key);  struct keychain {  	char *name; +	char *desc; +	time_t last_touch;  	struct list *key; @@ -81,13 +89,43 @@ struct key {  };  DECLARE_QOBJ_TYPE(key); +DECLARE_MTYPE(KEY); +DECLARE_MTYPE(KEYCHAIN); +DECLARE_MTYPE(KEYCHAIN_DESC); + +/* keychain implementation */ +extern struct list *keychain_list; +struct keychain *keychain_lookup(const char *name); +struct keychain *keychain_get(const char *name); +void keychain_delete(struct keychain *keychain); +struct key *key_lookup(const struct keychain *keychain, uint32_t index); +struct key *key_get(const struct keychain *keychain, uint32_t index); +void key_delete(struct keychain *keychain, struct key *key); + +void keychain_cli_init(void); +extern void key_chains_key_chain_cli_write(struct vty *vty, const struct lyd_node *dnode, bool show_defaults); +extern void key_chains_key_chain_cli_write_end(struct vty *vty, const struct lyd_node *dnode); +extern void key_chains_key_chain_description_cli_write(struct vty *vty, const struct lyd_node *dnode, bool show_defaults); +void key_chains_key_chain_key_cli_write(struct vty *vty, const struct lyd_node *dnode, bool show_defaults); +extern void key_chains_key_chain_key_cli_write_end(struct vty *vty, const struct lyd_node *dnode); +extern void key_chains_key_chain_key_lifetime_send_accept_lifetime_start_date_time_cli_write(struct vty *vty, const struct lyd_node *dnode, bool show_defaults); +extern void key_chains_key_chain_key_lifetime_send_lifetime_start_date_time_cli_write(struct vty *vty, const struct lyd_node *dnode, bool show_defaults); +extern void key_chains_key_chain_key_lifetime_accept_lifetime_start_date_time_cli_write(struct vty *vty, const struct lyd_node *dnode, bool show_defaults); +extern void key_chains_key_chain_key_crypto_algorithm_cli_write(struct vty *vty, const struct lyd_node *dnode, bool show_defaults); +extern void key_chains_key_chain_key_key_string_keystring_cli_write(struct vty *vty, const struct lyd_node *dnode, bool show_defaults); + +/* keychain users */  extern void keychain_init(void); +extern void keychain_init_new(bool in_backend);  extern void keychain_terminate(void);  extern struct keychain *keychain_lookup(const char *);  extern struct key *key_lookup_for_accept(const struct keychain *, uint32_t);  extern struct key *key_match_for_accept(const struct keychain *, const char *);  extern struct key *key_lookup_for_send(const struct keychain *);  const char *keychain_algo_str(enum keychain_hash_algo hash_algo); + + +  #ifdef __cplusplus  }  #endif diff --git a/lib/keychain_cli.c b/lib/keychain_cli.c new file mode 100644 index 0000000000..26f56f182a --- /dev/null +++ b/lib/keychain_cli.c @@ -0,0 +1,1033 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * February 22 2024, Christian Hopps <chopps@labn.net> + * + * Copyright (C) 2024 LabN Consulting, L.L.C. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; see the file COPYING; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ +#include <zebra.h> +#include "command.h" +#include "keychain.h" +#include "northbound.h" +#include "northbound_cli.h" +#include "vty.h" + +#include "lib/keychain_cli_clippy.c" + +DEFPY_YANG_NOSH( +       key_chain, +       key_chain_cmd, +       "key chain WORD", +       "Authentication key management\n" +       "Key-chain management\n" +       "Key-chain name\n") +{ +	char *xpath; +	int ret; + +	xpath = asprintfrr(MTYPE_TMP, +			   "/ietf-key-chain:key-chains/key-chain[name='%s']", +			   chain); +	nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL); +	ret = nb_cli_apply_changes(vty, NULL); +	if (ret == CMD_SUCCESS) +		VTY_PUSH_XPATH(KEYCHAIN_NODE, xpath); +	XFREE(MTYPE_TMP, xpath); +	return ret; +} + +DEFPY_YANG( +       no_key_chain, +       no_key_chain_cmd, +       "no key chain WORD", +       NO_STR +       "Authentication key management\n" +       "Key-chain management\n" +       "Key-chain name\n") +{ +	char *xpath; + +	xpath = asprintfrr(MTYPE_TMP, +			   "/ietf-key-chain:key-chains/key-chain[name='%s']", +			   chain); +	nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL); +	XFREE(MTYPE_TMP, xpath); +	return nb_cli_apply_changes_clear_pending(vty, NULL); +} + +DEFPY_YANG_NOSH( +       key, +       key_cmd, +       "key (0-2147483647)", +       "Configure a key\n" +       "Key identifier number\n") +{ +	char *xpath; +	int ret; + +	xpath = asprintfrr(MTYPE_TMP, "%s/key[key-id='%s']", VTY_CURR_XPATH, +			   key_str); +	nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL); +	ret = nb_cli_apply_changes(vty, NULL); +	if (ret == CMD_SUCCESS) +		VTY_PUSH_XPATH(KEYCHAIN_KEY_NODE, xpath); +	XFREE(MTYPE_TMP, xpath); +	return ret; +} + +DEFPY_YANG( +       no_key, +       no_key_cmd, +       "no key (0-2147483647)", +       NO_STR +       "Delete a key\n" +       "Key identifier number\n") +{ +	char *xpath; + +	xpath = asprintfrr(MTYPE_TMP, "%s/key[key-id='%s']", VTY_CURR_XPATH, +			   key_str); +	nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL); +	XFREE(MTYPE_TMP, xpath); +	return nb_cli_apply_changes_clear_pending(vty, NULL); +} + +DEFPY_YANG( +       key_string, +       key_string_cmd, +       "key-string LINE", +       "Set key string\n" +       "The key\n") +{ +	nb_cli_enqueue_change(vty, "./key-string/keystring", NB_OP_CREATE, line); +	return nb_cli_apply_changes(vty, NULL); +} + +DEFPY_YANG( +       no_key_string, +       no_key_string_cmd, +       "no key-string [LINE]", +       NO_STR +       "Unset key string\n" +       "The key\n") +{ +	nb_cli_enqueue_change(vty, "./key-string/keystring", NB_OP_DESTROY, line); +	return nb_cli_apply_changes(vty, NULL); +} + +DEFPY_YANG( +      cryptographic_algorithm, +      cryptographic_algorithm_cmd, +      "cryptographic-algorithm " +      "<md5|hmac-sha-1|hmac-sha-256|hmac-sha-384|hmac-sha-512>$algo", +      "Cryptographic-algorithm\n" +      "Use MD5 algorithm\n" +      "Use HMAC-SHA-1 algorithm\n" +      "Use HMAC-SHA-256 algorithm\n" +      "Use HMAC-SHA-384 algorithm\n" +      "Use HMAC-SHA-512 algorithm\n") +{ +	nb_cli_enqueue_change(vty, "./crypto-algorithm", NB_OP_CREATE, algo); +	return nb_cli_apply_changes(vty, NULL); +} + +DEFPY_YANG( +      no_cryptographic_algorithm, +      no_cryptographic_algorithm_cmd, +      "no cryptographic-algorithm " +      "[<md5|hmac-sha-1|hmac-sha-256|hmac-sha-384|hmac-sha-512>$algo]", +      NO_STR +      "Cryptographic-algorithm\n" +      "Use MD5 algorithm\n" +      "Use HMAC-SHA-1 algorithm\n" +      "Use HMAC-SHA-256 algorithm\n" +      "Use HMAC-SHA-384 algorithm\n" +      "Use HMAC-SHA-512 algorithm\n") +{ +	nb_cli_enqueue_change(vty, "./crypto-algorithm", NB_OP_DESTROY, algo); +	return nb_cli_apply_changes(vty, NULL); +} + +const char *month_name[] = { +	"january", "february", "march", "april", "may", "june", "july", +	"august", "september", "october", "november", "december", NULL +}; + +static int __get_month(const char *month_str) +{ +	int i, len; + +	len = strlen(month_str); +	if (len < 3) +		return -1; +	for (i = 1; month_name[i-1]; i++) +		if (strncasecmp(month_str, month_name[i-1], len) == 0) +			return i; +	return -1; +} + + +static long __timezone_offset(void) +{ +	time_t now; +	struct tm *tm_now; + +	time(&now); +	tm_now = localtime(&now); +	return tm_now->tm_gmtoff; +} + +static int __lifetime_set(struct vty *vty, char timebuf[32], +			  const char *time_node, const char *leaf_node, +			  const char *time_str, const char *day_str, +			  const char *month_str, const char *year_str) +{ +	char xpath[128]; +	int month = __get_month(month_str); +	int hoff, moff; +	long offset; + +	if (month < 1) { +		vty_out(vty, "Bad month value: %s\n", month_str); +		return -1; +	} + +	offset = __timezone_offset(); +	hoff = offset / 3600; +	if (offset < 0) +		offset = -offset; +	moff = (offset % 3600) / 60; + +	snprintf(timebuf, 32, "%s-%02d-%02dT%s%+03d:%02d", year_str, month, +		 atoi(day_str), time_str, hoff, moff); +	snprintf(xpath, sizeof(xpath), "./lifetime/%s/%s", time_node, leaf_node); +	nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, timebuf); +	return 0; +} + + +static int key_lifetime_set(struct vty *vty, const char *time_node, +			    const char *stime_str, const char *sday_str, +			    const char *smonth_str, const char *syear_str, +			    const char *etime_str, const char *eday_str, +			    const char *emonth_str, const char *eyear_str) +{ +	char time1[32]; +	char time2[32]; + +	if (__lifetime_set(vty, time1, time_node, "start-date-time", stime_str, +			   sday_str, smonth_str, syear_str)) +		return CMD_WARNING_CONFIG_FAILED; + +	if (__lifetime_set(vty, time2, time_node, "end-date-time", etime_str, +			   eday_str, emonth_str, eyear_str)) +		return CMD_WARNING_CONFIG_FAILED; + +	return nb_cli_apply_changes(vty, NULL); +} + +static int key_lifetime_duration_set(struct vty *vty, const char *time_node, +				     const char *stime_str, const char *sday_str, +				     const char *smonth_str, +				     const char *syear_str, +				     const char *duration_str) +{ +	char xpath[128]; +	char time[32]; + +	if (__lifetime_set(vty, time, time_node, "start-date-time", stime_str, +			   sday_str, smonth_str, syear_str)) +		return CMD_WARNING_CONFIG_FAILED; + +	/* End time. */ +	snprintf(xpath, sizeof(xpath), "./lifetime/%s/duration", time_node); +	nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, duration_str); + +	return nb_cli_apply_changes(vty, NULL); +} + +static int key_lifetime_infinite_set(struct vty *vty, const char *time_node, +				     const char *stime_str, const char *sday_str, +				     const char *smonth_str, +				     const char *syear_str) +{ +	char xpath[128]; +	char time[32]; + +	if (__lifetime_set(vty, time, time_node, "start-date-time", stime_str, +			   sday_str, smonth_str, syear_str)) +		return CMD_WARNING_CONFIG_FAILED; + +	/* End time. */ +	snprintf(xpath, sizeof(xpath), "./lifetime/%s/no-end-time", time_node); +	nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY, NULL); + +	return nb_cli_apply_changes(vty, NULL); +} + +DEFPY_YANG( +       accept_lifetime_day_month_day_month, +       accept_lifetime_day_month_day_month_cmd, +       "accept-lifetime HH:MM:SS (1-31) MONTH (1993-2035) HH:MM:SS (1-31) MONTH (1993-2035)", +       "Set accept lifetime of the key\n" +       "Time to start\n" +       "Day of th month to start\n" +       "Month of the year to start\n" +       "Year to start\n" +       "Time to expire\n" +       "Day of th month to expire\n" +       "Month of the year to expire\n" +       "Year to expire\n") +{ +	int idx_hhmmss = 1; +	int idx_number = 2; +	int idx_month = 3; +	int idx_number_2 = 4; +	int idx_hhmmss_2 = 5; +	int idx_number_3 = 6; +	int idx_month_2 = 7; +	int idx_number_4 = 8; + +	return key_lifetime_set(vty, "accept-lifetime", argv[idx_hhmmss]->arg, +				argv[idx_number]->arg, argv[idx_month]->arg, +				argv[idx_number_2]->arg, argv[idx_hhmmss_2]->arg, +				argv[idx_number_3]->arg, argv[idx_month_2]->arg, +				argv[idx_number_4]->arg); +} + +DEFPY_YANG(accept_lifetime_day_month_month_day, +       accept_lifetime_day_month_month_day_cmd, +       "accept-lifetime HH:MM:SS (1-31) MONTH (1993-2035) HH:MM:SS MONTH (1-31) (1993-2035)", +       "Set accept lifetime of the key\n" +       "Time to start\n" +       "Day of th month to start\n" +       "Month of the year to start\n" +       "Year to start\n" +       "Time to expire\n" +       "Month of the year to expire\n" +       "Day of th month to expire\n" +       "Year to expire\n") +{ +	int idx_hhmmss = 1; +	int idx_number = 2; +	int idx_month = 3; +	int idx_number_2 = 4; +	int idx_hhmmss_2 = 5; +	int idx_month_2 = 6; +	int idx_number_3 = 7; +	int idx_number_4 = 8; + +	return key_lifetime_set(vty, "accept-lifetime", argv[idx_hhmmss]->arg, +				argv[idx_number]->arg, argv[idx_month]->arg, +				argv[idx_number_2]->arg, argv[idx_hhmmss_2]->arg, +				argv[idx_number_3]->arg, argv[idx_month_2]->arg, +				argv[idx_number_4]->arg); +} + +DEFPY_YANG(accept_lifetime_month_day_day_month, +       accept_lifetime_month_day_day_month_cmd, +       "accept-lifetime HH:MM:SS MONTH (1-31) (1993-2035) HH:MM:SS (1-31) MONTH (1993-2035)", +       "Set accept lifetime of the key\n" +       "Time to start\n" +       "Month of the year to start\n" +       "Day of th month to start\n" +       "Year to start\n" +       "Time to expire\n" +       "Day of th month to expire\n" +       "Month of the year to expire\n" +       "Year to expire\n") +{ +	int idx_hhmmss = 1; +	int idx_month = 2; +	int idx_number = 3; +	int idx_number_2 = 4; +	int idx_hhmmss_2 = 5; +	int idx_number_3 = 6; +	int idx_month_2 = 7; +	int idx_number_4 = 8; + +	return key_lifetime_set(vty, "accept-lifetime", argv[idx_hhmmss]->arg, +				argv[idx_number]->arg, argv[idx_month]->arg, +				argv[idx_number_2]->arg, argv[idx_hhmmss_2]->arg, +				argv[idx_number_3]->arg, argv[idx_month_2]->arg, +				argv[idx_number_4]->arg); +} + +DEFPY_YANG(accept_lifetime_month_day_month_day, +       accept_lifetime_month_day_month_day_cmd, +       "accept-lifetime HH:MM:SS MONTH (1-31) (1993-2035) HH:MM:SS MONTH (1-31) (1993-2035)", +       "Set accept lifetime of the key\n" +       "Time to start\n" +       "Month of the year to start\n" +       "Day of th month to start\n" +       "Year to start\n" +       "Time to expire\n" +       "Month of the year to expire\n" +       "Day of th month to expire\n" +       "Year to expire\n") +{ +	int idx_hhmmss = 1; +	int idx_month = 2; +	int idx_number = 3; +	int idx_number_2 = 4; +	int idx_hhmmss_2 = 5; +	int idx_month_2 = 6; +	int idx_number_3 = 7; +	int idx_number_4 = 8; + +	return key_lifetime_set(vty, "accept-lifetime", argv[idx_hhmmss]->arg, +				argv[idx_number]->arg, argv[idx_month]->arg, +				argv[idx_number_2]->arg, argv[idx_hhmmss_2]->arg, +				argv[idx_number_3]->arg, argv[idx_month_2]->arg, +				argv[idx_number_4]->arg); +} + +DEFPY_YANG(accept_lifetime_infinite_day_month, +       accept_lifetime_infinite_day_month_cmd, +       "accept-lifetime HH:MM:SS (1-31) MONTH (1993-2035) infinite", +       "Set accept lifetime of the key\n" +       "Time to start\n" +       "Day of th month to start\n" +       "Month of the year to start\n" +       "Year to start\n" +       "Never expires\n") +{ +	int idx_hhmmss = 1; +	int idx_number = 2; +	int idx_month = 3; +	int idx_number_2 = 4; + +	return key_lifetime_infinite_set(vty, "accept-lifetime", +					 argv[idx_hhmmss]->arg, +					 argv[idx_number]->arg, +					 argv[idx_month]->arg, +					 argv[idx_number_2]->arg); +} + +DEFPY_YANG(accept_lifetime_infinite_month_day, +       accept_lifetime_infinite_month_day_cmd, +       "accept-lifetime HH:MM:SS MONTH (1-31) (1993-2035) infinite", +       "Set accept lifetime of the key\n" +       "Time to start\n" +       "Month of the year to start\n" +       "Day of th month to start\n" +       "Year to start\n" +       "Never expires\n") +{ +	int idx_hhmmss = 1; +	int idx_month = 2; +	int idx_number = 3; +	int idx_number_2 = 4; + +	return key_lifetime_infinite_set(vty, "accept-lifetime", +					 argv[idx_hhmmss]->arg, +					 argv[idx_number]->arg, +					 argv[idx_month]->arg, +					 argv[idx_number_2]->arg); +} + +DEFPY_YANG(accept_lifetime_duration_day_month, +       accept_lifetime_duration_day_month_cmd, +       "accept-lifetime HH:MM:SS (1-31) MONTH (1993-2035) duration (1-2147483646)", +       "Set accept lifetime of the key\n" +       "Time to start\n" +       "Day of th month to start\n" +       "Month of the year to start\n" +       "Year to start\n" +       "Duration of the key\n" +       "Duration seconds\n") +{ +	int idx_hhmmss = 1; +	int idx_number = 2; +	int idx_month = 3; +	int idx_number_2 = 4; +	int idx_number_3 = 6; + +	return key_lifetime_duration_set(vty, "accept-lifetime", +					 argv[idx_hhmmss]->arg, +					 argv[idx_number]->arg, +					 argv[idx_month]->arg, +					 argv[idx_number_2]->arg, +					 argv[idx_number_3]->arg); +} + +DEFPY_YANG(accept_lifetime_duration_month_day, +       accept_lifetime_duration_month_day_cmd, +       "accept-lifetime HH:MM:SS MONTH (1-31) (1993-2035) duration (1-2147483646)", +       "Set accept lifetime of the key\n" +       "Time to start\n" +       "Month of the year to start\n" +       "Day of th month to start\n" +       "Year to start\n" +       "Duration of the key\n" +       "Duration seconds\n") +{ +	int idx_hhmmss = 1; +	int idx_month = 2; +	int idx_number = 3; +	int idx_number_2 = 4; +	int idx_number_3 = 6; + +	return key_lifetime_duration_set(vty, "accept-lifetime", +					 argv[idx_hhmmss]->arg, +					 argv[idx_number]->arg, +					 argv[idx_month]->arg, +					 argv[idx_number_2]->arg, +					 argv[idx_number_3]->arg); +} + +DEFPY_YANG(no_accept_lifetime, +       no_accept_lifetime_cmd, +       "no accept-lifetime", +       NO_STR +       "Unset accept-lifetime\n") +{ +	nb_cli_enqueue_change(vty, "accept-lifetime", NB_OP_DESTROY, NULL); +	return nb_cli_apply_changes(vty, NULL); +} + +DEFPY_YANG( +	send_lifetime_day_month_day_month, send_lifetime_day_month_day_month_cmd, +	"send-lifetime HH:MM:SS (1-31) MONTH (1993-2035) HH:MM:SS (1-31) MONTH (1993-2035)", +	"Set send lifetime of the key\n" +	"Time to start\n" +	"Day of th month to start\n" +	"Month of the year to start\n" +	"Year to start\n" +	"Time to expire\n" +	"Day of th month to expire\n" +	"Month of the year to expire\n" +	"Year to expire\n") +{ +	int idx_hhmmss = 1; +	int idx_number = 2; +	int idx_month = 3; +	int idx_number_2 = 4; +	int idx_hhmmss_2 = 5; +	int idx_number_3 = 6; +	int idx_month_2 = 7; +	int idx_number_4 = 8; + +	return key_lifetime_set(vty, "send-lifetime", argv[idx_hhmmss]->arg, +				argv[idx_number]->arg, argv[idx_month]->arg, +				argv[idx_number_2]->arg, argv[idx_hhmmss_2]->arg, +				argv[idx_number_3]->arg, argv[idx_month_2]->arg, +				argv[idx_number_4]->arg); +} + +DEFPY_YANG(send_lifetime_day_month_month_day, +       send_lifetime_day_month_month_day_cmd, +       "send-lifetime HH:MM:SS (1-31) MONTH (1993-2035) HH:MM:SS MONTH (1-31) (1993-2035)", +       "Set send lifetime of the key\n" +       "Time to start\n" +       "Day of th month to start\n" +       "Month of the year to start\n" +       "Year to start\n" +       "Time to expire\n" +       "Month of the year to expire\n" +       "Day of th month to expire\n" +       "Year to expire\n") +{ +	int idx_hhmmss = 1; +	int idx_number = 2; +	int idx_month = 3; +	int idx_number_2 = 4; +	int idx_hhmmss_2 = 5; +	int idx_month_2 = 6; +	int idx_number_3 = 7; +	int idx_number_4 = 8; + +	return key_lifetime_set(vty, "send-lifetime", argv[idx_hhmmss]->arg, +				argv[idx_number]->arg, argv[idx_month]->arg, +				argv[idx_number_2]->arg, argv[idx_hhmmss_2]->arg, +				argv[idx_number_3]->arg, argv[idx_month_2]->arg, +				argv[idx_number_4]->arg); +} + +DEFPY_YANG(send_lifetime_month_day_day_month, +       send_lifetime_month_day_day_month_cmd, +       "send-lifetime HH:MM:SS MONTH (1-31) (1993-2035) HH:MM:SS (1-31) MONTH (1993-2035)", +       "Set send lifetime of the key\n" +       "Time to start\n" +       "Month of the year to start\n" +       "Day of th month to start\n" +       "Year to start\n" +       "Time to expire\n" +       "Day of th month to expire\n" +       "Month of the year to expire\n" +       "Year to expire\n") +{ +	int idx_hhmmss = 1; +	int idx_month = 2; +	int idx_number = 3; +	int idx_number_2 = 4; +	int idx_hhmmss_2 = 5; +	int idx_number_3 = 6; +	int idx_month_2 = 7; +	int idx_number_4 = 8; + +	return key_lifetime_set(vty, "send-lifetime", argv[idx_hhmmss]->arg, +				argv[idx_number]->arg, argv[idx_month]->arg, +				argv[idx_number_2]->arg, argv[idx_hhmmss_2]->arg, +				argv[idx_number_3]->arg, argv[idx_month_2]->arg, +				argv[idx_number_4]->arg); +} + +DEFPY_YANG(send_lifetime_month_day_month_day, +       send_lifetime_month_day_month_day_cmd, +       "send-lifetime HH:MM:SS MONTH (1-31) (1993-2035) HH:MM:SS MONTH (1-31) (1993-2035)", +       "Set send lifetime of the key\n" +       "Time to start\n" +       "Month of the year to start\n" +       "Day of th month to start\n" +       "Year to start\n" +       "Time to expire\n" +       "Month of the year to expire\n" +       "Day of th month to expire\n" +       "Year to expire\n") +{ +	int idx_hhmmss = 1; +	int idx_month = 2; +	int idx_number = 3; +	int idx_number_2 = 4; +	int idx_hhmmss_2 = 5; +	int idx_month_2 = 6; +	int idx_number_3 = 7; +	int idx_number_4 = 8; + +	return key_lifetime_set(vty, "send-lifetime", argv[idx_hhmmss]->arg, +				argv[idx_number]->arg, argv[idx_month]->arg, +				argv[idx_number_2]->arg, argv[idx_hhmmss_2]->arg, +				argv[idx_number_3]->arg, argv[idx_month_2]->arg, +				argv[idx_number_4]->arg); +} + +DEFPY_YANG(send_lifetime_infinite_day_month, +       send_lifetime_infinite_day_month_cmd, +       "send-lifetime HH:MM:SS (1-31) MONTH (1993-2035) infinite", +       "Set send lifetime of the key\n" +       "Time to start\n" +       "Day of th month to start\n" +       "Month of the year to start\n" +       "Year to start\n" +       "Never expires\n") +{ +	int idx_hhmmss = 1; +	int idx_number = 2; +	int idx_month = 3; +	int idx_number_2 = 4; + +	return key_lifetime_infinite_set(vty, "send-lifetime", +					 argv[idx_hhmmss]->arg, +					 argv[idx_number]->arg, +					 argv[idx_month]->arg, +					 argv[idx_number_2]->arg); +} + +DEFPY_YANG(send_lifetime_infinite_month_day, +       send_lifetime_infinite_month_day_cmd, +       "send-lifetime HH:MM:SS MONTH (1-31) (1993-2035) infinite", +       "Set send lifetime of the key\n" +       "Time to start\n" +       "Month of the year to start\n" +       "Day of th month to start\n" +       "Year to start\n" +       "Never expires\n") +{ +	int idx_hhmmss = 1; +	int idx_month = 2; +	int idx_number = 3; +	int idx_number_2 = 4; + +	return key_lifetime_infinite_set(vty, "send-lifetime", +					 argv[idx_hhmmss]->arg, +					 argv[idx_number]->arg, +					 argv[idx_month]->arg, +					 argv[idx_number_2]->arg); +} + +DEFPY_YANG(send_lifetime_duration_day_month, +       send_lifetime_duration_day_month_cmd, +       "send-lifetime HH:MM:SS (1-31) MONTH (1993-2035) duration (1-2147483646)", +       "Set send lifetime of the key\n" +       "Time to start\n" +       "Day of th month to start\n" +       "Month of the year to start\n" +       "Year to start\n" +       "Duration of the key\n" +       "Duration seconds\n") +{ +	int idx_hhmmss = 1; +	int idx_number = 2; +	int idx_month = 3; +	int idx_number_2 = 4; +	int idx_number_3 = 6; + +	return key_lifetime_duration_set(vty, "send-lifetime", +					 argv[idx_hhmmss]->arg, +					 argv[idx_number]->arg, +					 argv[idx_month]->arg, +					 argv[idx_number_2]->arg, +					 argv[idx_number_3]->arg); +} + +DEFPY_YANG(send_lifetime_duration_month_day, +       send_lifetime_duration_month_day_cmd, +       "send-lifetime HH:MM:SS MONTH (1-31) (1993-2035) duration (1-2147483646)", +       "Set send lifetime of the key\n" +       "Time to start\n" +       "Month of the year to start\n" +       "Day of th month to start\n" +       "Year to start\n" +       "Duration of the key\n" +       "Duration seconds\n") +{ +	int idx_hhmmss = 1; +	int idx_month = 2; +	int idx_number = 3; +	int idx_number_2 = 4; +	int idx_number_3 = 6; + +	return key_lifetime_duration_set(vty, "send-lifetime", +					 argv[idx_hhmmss]->arg, +					 argv[idx_number]->arg, +					 argv[idx_month]->arg, +					 argv[idx_number_2]->arg, +					 argv[idx_number_3]->arg); +} + +DEFUN (no_send_lifetime, +       no_send_lifetime_cmd, +       "no send-lifetime", +       NO_STR +       "Unset send-lifetime\n") +{ +	nb_cli_enqueue_change(vty, "send-lifetime", NB_OP_DESTROY, NULL); +	return nb_cli_apply_changes(vty, NULL); +} + +/* + * XPath: /ietf-key-chain:key-chains/key-chain + */ +void key_chains_key_chain_cli_write(struct vty *vty, +				    const struct lyd_node *dnode, +				    bool show_defaults) +{ +	vty_out(vty, "key chain %s\n", yang_dnode_get_string(dnode, "name")); +} + +void key_chains_key_chain_cli_write_end(struct vty *vty, +					const struct lyd_node *dnode) +{ +	vty_out(vty, "exit\n"); +	vty_out(vty, "!\n"); +} + +/* + * XPath: /ietf-key-chain:key-chains/key-chain/description + */ +void key_chains_key_chain_description_cli_write(struct vty *vty, +						const struct lyd_node *dnode, +						bool show_defaults) +{ +	/* Implement CLI */ +	/* vty_out(vty, " description %s\n", yang_dnode_get_string(dnode)); */ +} + +/* + * XPath: /ietf-key-chain:key-chains/key-chain/key + */ +void key_chains_key_chain_key_cli_write(struct vty *vty, +					const struct lyd_node *dnode, +					bool show_defaults) +{ +	vty_out(vty, " key %s\n", yang_dnode_get_string(dnode, "key-id")); +} + +void key_chains_key_chain_key_cli_write_end(struct vty *vty, +					    const struct lyd_node *dnode) +{ +	vty_out(vty, " exit\n"); +} + +static const char *__dnode_to_key_strftime(char *buf, size_t bufsize, +					   const struct lyd_node *lt_start_dnode) +{ +	const char *timestr; +	struct lyd_node *end_node; +	struct tm tm; +	uint32_t duration; +	time_t time; +	int len, sz; +	char *s; + +	s = buf; +	sz = bufsize; + +	timestr = yang_dnode_get_string(lt_start_dnode, NULL); +	(void)ly_time_str2time(timestr, &time, NULL); +	localtime_r(&time, &tm); +	len = strftime(s, sz, "%T %b %e %Y", &tm); +	s += len; +	sz -= len; + +	if (yang_dnode_exists(lt_start_dnode, "../no-end-time")) { +		strlcat(s, " infinite", sz); +		return buf; +	} + +	end_node = yang_dnode_get(lt_start_dnode, "../duration"); +	if (end_node) { +		duration = yang_dnode_get_uint32(end_node, NULL); +		snprintf(s, sz, " duration %u", (uint)duration); +		return buf; +	} + +	timestr = yang_dnode_get_string(lt_start_dnode, "../end-date-time"); +	(void)ly_time_str2time(timestr, &time, NULL); +	localtime_r(&time, &tm); +	strftime(s, sz, " %T %b %e %Y", &tm); +	return buf; +} + +/* + * XPath: /ietf-key-chain:key-chains/key-chain/key/lifetime/send-accept-lifetime/start-date-time + */ +void key_chains_key_chain_key_lifetime_send_accept_lifetime_start_date_time_cli_write( +	struct vty *vty, const struct lyd_node *dnode, bool show_defaults) +{ +	char s[256]; + +	vty_out(vty, "  send-lifetime %s\n", +		__dnode_to_key_strftime(s, sizeof(s), dnode)); +	vty_out(vty, "  accept-lifetime %s\n", s); +} + +/* + * XPath: /ietf-key-chain:key-chains/key-chain/key/lifetime/send-lifetime/start-date-time + */ +void key_chains_key_chain_key_lifetime_send_lifetime_start_date_time_cli_write( +	struct vty *vty, const struct lyd_node *dnode, bool show_defaults) +{ +	char s[256]; + +	vty_out(vty, "  send-lifetime %s\n", +		__dnode_to_key_strftime(s, sizeof(s), dnode)); +} + +/* + * XPath: /ietf-key-chain:key-chains/key-chain/key/lifetime/accept-lifetime/start-date-time + */ +void key_chains_key_chain_key_lifetime_accept_lifetime_start_date_time_cli_write( +	struct vty *vty, const struct lyd_node *dnode, bool show_defaults) +{ +	char s[256]; + +	vty_out(vty, "  accept-lifetime %s\n", +		__dnode_to_key_strftime(s, sizeof(s), dnode)); +} + +/* + * XPath: /ietf-key-chain:key-chains/key-chain/key/crypto-algorithm + */ +void key_chains_key_chain_key_crypto_algorithm_cli_write( +	struct vty *vty, const struct lyd_node *dnode, bool show_defaults) +{ +	static const char prefix[] = "ietf-key-chain:"; +	static const int prefix_len = sizeof(prefix) - 1; +	const char *name = yang_dnode_get_string(dnode, NULL); + +	if (!strncmp(name, prefix, prefix_len)) +		name += prefix_len; +	vty_out(vty, "  cryptographic-algorithm %s\n", name); +} + +/* + * XPath: /ietf-key-chain:key-chains/key-chain/key/key-string/keystring + */ +void key_chains_key_chain_key_key_string_keystring_cli_write( +	struct vty *vty, const struct lyd_node *dnode, bool show_defaults) +{ +	vty_out(vty, "  key-string %s\n", yang_dnode_get_string(dnode, NULL)); +} + +static const char * const keychain_features[] = { +	"independent-send-accept-lifetime", +	NULL, +}; + +/* clang-format off */ +const struct frr_yang_module_info ietf_key_chain_cli_info = { +	.name = "ietf-key-chain", +	.features = (const char **)keychain_features, +	.ignore_cfg_cbs = true, +	.nodes = { +		{ +			.xpath = "/ietf-key-chain:key-chains/key-chain", +			.cbs = { +				.cli_show = key_chains_key_chain_cli_write, +				.cli_show_end = key_chains_key_chain_cli_write_end, +			} +		}, +		{ +			.xpath = "/ietf-key-chain:key-chains/key-chain/description", +			.cbs = { +				.cli_show = key_chains_key_chain_description_cli_write, +			} +		}, +		{ +			.xpath = "/ietf-key-chain:key-chains/key-chain/key", +			.cbs = { +				.cli_show = key_chains_key_chain_key_cli_write, +				.cli_show_end = key_chains_key_chain_key_cli_write_end, +			} +		}, +		{ +			.xpath = "/ietf-key-chain:key-chains/key-chain/key/lifetime/send-accept-lifetime/start-date-time", +			.cbs = { +				.cli_show = key_chains_key_chain_key_lifetime_send_accept_lifetime_start_date_time_cli_write, +			} +		}, +		{ +			.xpath = "/ietf-key-chain:key-chains/key-chain/key/lifetime/send-lifetime/start-date-time", +			.cbs = { +				.cli_show = key_chains_key_chain_key_lifetime_send_lifetime_start_date_time_cli_write, +			} +		}, +		{ +			.xpath = "/ietf-key-chain:key-chains/key-chain/key/lifetime/accept-lifetime/start-date-time", +			.cbs = { +				.cli_show = key_chains_key_chain_key_lifetime_accept_lifetime_start_date_time_cli_write, +			} +		}, +		{ +			.xpath = "/ietf-key-chain:key-chains/key-chain/key/crypto-algorithm", +			.cbs = { +				.cli_show = key_chains_key_chain_key_crypto_algorithm_cli_write, +			} +		}, +		{ +			.xpath = "/ietf-key-chain:key-chains/key-chain/key/key-string/keystring", +			.cbs = { +				.cli_show = key_chains_key_chain_key_key_string_keystring_cli_write, +			} +		}, +		{ +			.xpath = NULL, +		}, +	} +}; + +static int keychain_config_write(struct vty *vty) +{ +	const struct lyd_node *dnode; +	int written = 0; + +	dnode = yang_dnode_get(running_config->dnode, +			       "/ietf-key-chain:key-chains"); +	if (dnode) { +		nb_cli_show_dnode_cmds(vty, dnode, false); +		written = 1; +	} +	return written; +} + +static struct cmd_node keychain_node = { +	.name = "keychain", +	.node = KEYCHAIN_NODE, +	.parent_node = CONFIG_NODE, +	.prompt = "%s(config-keychain)# ", +	.config_write = keychain_config_write, +}; + +static struct cmd_node keychain_key_node = { +	.name = "keychain key", +	.node = KEYCHAIN_KEY_NODE, +	.parent_node = KEYCHAIN_NODE, +	.prompt = "%s(config-keychain-key)# ", +}; + +static const struct cmd_variable_handler keychain_var_handlers[] = { +	{.varname = "key_chain", .xpath = "/ietf-key-chain:key-chains/key-chain/name" }, +	{.tokenname = "KEYCHAIN_NAME", .xpath = "/ietf-key-chain:key-chains/key-chain/name" }, +	{.completions = NULL} +}; + +void keychain_cli_init(void) +{ +	/* Register handler for keychain auto config support */ +	cmd_variable_handler_register(keychain_var_handlers); +	install_node(&keychain_node); +	install_node(&keychain_key_node); + +	install_default(KEYCHAIN_NODE); +	install_default(KEYCHAIN_KEY_NODE); + +	install_element(CONFIG_NODE, &key_chain_cmd); +	install_element(CONFIG_NODE, &no_key_chain_cmd); +	install_element(KEYCHAIN_NODE, &key_cmd); +	install_element(KEYCHAIN_NODE, &no_key_cmd); + +	install_element(KEYCHAIN_NODE, &key_chain_cmd); +	install_element(KEYCHAIN_NODE, &no_key_chain_cmd); + +	install_element(KEYCHAIN_KEY_NODE, &key_string_cmd); +	install_element(KEYCHAIN_KEY_NODE, &no_key_string_cmd); + +	install_element(KEYCHAIN_KEY_NODE, &key_chain_cmd); +	install_element(KEYCHAIN_KEY_NODE, &no_key_chain_cmd); + +	install_element(KEYCHAIN_KEY_NODE, &key_cmd); +	install_element(KEYCHAIN_KEY_NODE, &no_key_cmd); + +	install_element(KEYCHAIN_KEY_NODE, +			&accept_lifetime_day_month_day_month_cmd); +	install_element(KEYCHAIN_KEY_NODE, +			&accept_lifetime_day_month_month_day_cmd); +	install_element(KEYCHAIN_KEY_NODE, +			&accept_lifetime_month_day_day_month_cmd); +	install_element(KEYCHAIN_KEY_NODE, +			&accept_lifetime_month_day_month_day_cmd); +	install_element(KEYCHAIN_KEY_NODE, +			&accept_lifetime_infinite_day_month_cmd); +	install_element(KEYCHAIN_KEY_NODE, +			&accept_lifetime_infinite_month_day_cmd); +	install_element(KEYCHAIN_KEY_NODE, +			&accept_lifetime_duration_day_month_cmd); +	install_element(KEYCHAIN_KEY_NODE, +			&accept_lifetime_duration_month_day_cmd); +	install_element(KEYCHAIN_KEY_NODE, &no_accept_lifetime_cmd); + +	install_element(KEYCHAIN_KEY_NODE, +			&send_lifetime_day_month_day_month_cmd); +	install_element(KEYCHAIN_KEY_NODE, +			&send_lifetime_day_month_month_day_cmd); +	install_element(KEYCHAIN_KEY_NODE, +			&send_lifetime_month_day_day_month_cmd); +	install_element(KEYCHAIN_KEY_NODE, +			&send_lifetime_month_day_month_day_cmd); +	install_element(KEYCHAIN_KEY_NODE, +			&send_lifetime_infinite_day_month_cmd); +	install_element(KEYCHAIN_KEY_NODE, +			&send_lifetime_infinite_month_day_cmd); +	install_element(KEYCHAIN_KEY_NODE, +			&send_lifetime_duration_day_month_cmd); +	install_element(KEYCHAIN_KEY_NODE, +			&send_lifetime_duration_month_day_cmd); +	install_element(KEYCHAIN_KEY_NODE, &no_send_lifetime_cmd); +	install_element(KEYCHAIN_KEY_NODE, &cryptographic_algorithm_cmd); +	install_element(KEYCHAIN_KEY_NODE, &no_cryptographic_algorithm_cmd); +} diff --git a/lib/keychain_nb.c b/lib/keychain_nb.c index 1a2853a905..6838268a93 100644 --- a/lib/keychain_nb.c +++ b/lib/keychain_nb.c @@ -1,92 +1,165 @@  // SPDX-License-Identifier: GPL-2.0-or-later +/* + * February 22 2024, Christian Hopps <chopps@labn.net> + * + * Copyright (C) 2024 LabN Consulting, L.L.C. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; see the file COPYING; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ +#include <zebra.h> +#include "lib_errors.h" +#include "northbound.h" +#include "keychain.h" + +static void keychain_touch(struct keychain *keychain) +{ +	keychain->last_touch = time(NULL); +}  /*   * XPath: /ietf-key-chain:key-chains/key-chain   */  static int key_chains_key_chain_create(struct nb_cb_create_args *args)  { -	switch (args->event) { -	case NB_EV_VALIDATE: -	case NB_EV_PREPARE: -	case NB_EV_ABORT: -	case NB_EV_APPLY: -		/* TODO: implement me. */ -		break; -	} +	const char *name; +	struct keychain *keychain; -	return NB_OK; -} +	if (args->event != NB_EV_APPLY) +		return NB_OK; -static void key_chains_key_chain_cli_write(struct vty *vty, const struct lyd_node *dnode, bool show_defaults) -{ -	/* TODO: this cli callback is optional; the cli output may not need to be done at each node. */ +	name = yang_dnode_get_string(args->dnode, "name"); +	keychain = keychain_get(name); +	keychain_touch(keychain); +	return NB_OK;  }  static int key_chains_key_chain_destroy(struct nb_cb_destroy_args *args)  { -	switch (args->event) { -	case NB_EV_VALIDATE: -	case NB_EV_PREPARE: -	case NB_EV_ABORT: -	case NB_EV_APPLY: -		/* TODO: implement me. */ -		break; -	} +	const char *name; + +	if (args->event != NB_EV_APPLY) +		return NB_OK; +	name = yang_dnode_get_string(args->dnode, "name"); +	keychain_delete(keychain_lookup(name));  	return NB_OK;  }  static const void *key_chains_key_chain_get_next(struct nb_cb_get_next_args *args)  { -	/* TODO: implement me. */ -	return NULL; +	const struct listnode *prev = args->list_entry; + +	return prev ? prev->next : keychain_list->head;  }  static int key_chains_key_chain_get_keys(struct nb_cb_get_keys_args *args)  { -	/* TODO: implement me. */ +	const struct listnode *node = args->list_entry; +	const struct keychain *keychain = node->data; + +	args->keys->num = 1; +	strlcpy(args->keys->key[0], keychain->name, sizeof(args->keys->key[0]));  	return NB_OK;  }  static const void *key_chains_key_chain_lookup_entry(struct nb_cb_lookup_entry_args *args)  { -	/* TODO: implement me. */ +	const char *name = args->keys->key[0]; +	struct keychain *keychain; +	struct listnode *node; + +	for (ALL_LIST_ELEMENTS_RO(keychain_list, node, keychain)) { +		if (strcmp(keychain->name, name) == 0) +			return node; +	}  	return NULL;  } + +static int __destroy_nop(struct nb_cb_destroy_args *args) +{ +	/* modified by sibling or cleaned up by container destroy */ +	return NB_OK; +} + +static struct key *__dnode_get_key2(const struct lyd_node *dnode, bool touch) +{ +	struct keychain *keychain; +	const char *name; +	struct key *key; +	uint32_t index; + +	name = yang_dnode_get_string(dnode, "../../../name"); +	keychain = keychain_lookup(name); +	index = (uint32_t)yang_dnode_get_uint64(dnode, "../../key-id"); +	key = key_lookup(keychain, index); +	if (touch) +		keychain_touch(keychain); +	return key; +} + +static struct key *__dnode_get_key3(const struct lyd_node *dnode, bool touch) +{ +	struct keychain *keychain; +	const char *name; +	struct key *key; +	uint32_t index; + +	name = yang_dnode_get_string(dnode, "../../../../name"); +	keychain = keychain_lookup(name); +	index = (uint32_t)yang_dnode_get_uint64(dnode, "../../../key-id"); +	key = key_lookup(keychain, index); +	if (touch) +		keychain_touch(keychain); +	return key; +} +  /*   * XPath: /ietf-key-chain:key-chains/key-chain/description   */  static int key_chains_key_chain_description_modify(struct nb_cb_modify_args *args)  { -	switch (args->event) { -	case NB_EV_VALIDATE: -	case NB_EV_PREPARE: -	case NB_EV_ABORT: -	case NB_EV_APPLY: -		/* TODO: implement me. */ -		break; -	} +	struct keychain *keychain; +	const char *name; -	return NB_OK; -} +	if (args->event != NB_EV_APPLY) +		return NB_OK; -static void key_chains_key_chain_description_cli_write(struct vty *vty, const struct lyd_node *dnode, bool show_defaults) -{ -	/* TODO: this cli callback is optional; the cli output may not need to be done at each node. */ +	name = yang_dnode_get_string(args->dnode, "../name"); +	keychain = keychain_lookup(name); +	XFREE(MTYPE_KEYCHAIN_DESC, keychain->desc); +	keychain->desc = XSTRDUP(MTYPE_KEYCHAIN_DESC, +				 yang_dnode_get_string(args->dnode, NULL)); + +	keychain_touch(keychain); +	return NB_OK;  }  static int key_chains_key_chain_description_destroy(struct nb_cb_destroy_args *args)  { -	switch (args->event) { -	case NB_EV_VALIDATE: -	case NB_EV_PREPARE: -	case NB_EV_ABORT: -	case NB_EV_APPLY: -		/* TODO: implement me. */ -		break; -	} +	struct keychain *keychain; +	const char *name; + +	if (args->event != NB_EV_APPLY) +		return NB_OK; +	name = yang_dnode_get_string(args->dnode, "../name"); +	keychain = keychain_lookup(name); +	XFREE(MTYPE_KEYCHAIN_DESC, keychain->desc); + +	keychain_touch(keychain);  	return NB_OK;  } @@ -95,8 +168,11 @@ static int key_chains_key_chain_description_destroy(struct nb_cb_destroy_args *a   */  static struct yang_data *key_chains_key_chain_last_modified_timestamp_get_elem(struct nb_cb_get_elem_args *args)  { -	/* TODO: implement me. */ -	return NULL; +	const struct listnode *kcnode = args->list_entry; +	const struct keychain *keychain = kcnode->data; + +	return yang_data_new_date_and_time(args->xpath, keychain->last_touch, +					   false);  }  /* @@ -104,269 +180,271 @@ static struct yang_data *key_chains_key_chain_last_modified_timestamp_get_elem(s   */  static int key_chains_key_chain_key_create(struct nb_cb_create_args *args)  { -	switch (args->event) { -	case NB_EV_VALIDATE: -	case NB_EV_PREPARE: -	case NB_EV_ABORT: -	case NB_EV_APPLY: -		/* TODO: implement me. */ -		break; +	struct keychain *keychain; +	struct key *key; +	const char *name; +	uint64_t keyid; + +	if (args->event != NB_EV_VALIDATE && args->event != NB_EV_APPLY) +		return NB_OK; + +	keyid = yang_dnode_get_uint64(args->dnode, "key-id"); +	if (args->event == NB_EV_VALIDATE) { +		if (keyid > UINT32_MAX) { +			/* Warn most protocols can't use this value */ +			flog_err(EC_LIB_NB_CB_CONFIG_VALIDATE, +				 "Protocols do not accept > 32-bit key-id values"); +			return NB_EV_VALIDATE; +		} +		return NB_OK;  	} +	if (args->event != NB_EV_APPLY) +		return NB_OK; -	return NB_OK; -} +	name = yang_dnode_get_string(args->dnode, "../name"); +	keychain = keychain_lookup(name); +	assert(keyid <= UINT32_MAX); +	key = key_get(keychain, (uint32_t)keyid); +	assert(key); -static void key_chains_key_chain_key_cli_write(struct vty *vty, const struct lyd_node *dnode, bool show_defaults) -{ -	/* TODO: this cli callback is optional; the cli output may not need to be done at each node. */ +	keychain_touch(keychain); +	return NB_OK;  }  static int key_chains_key_chain_key_destroy(struct nb_cb_destroy_args *args)  { -	switch (args->event) { -	case NB_EV_VALIDATE: -	case NB_EV_PREPARE: -	case NB_EV_ABORT: -	case NB_EV_APPLY: -		/* TODO: implement me. */ -		break; -	} +	struct keychain *keychain; +	struct key *key; +	const char *name; +	uint64_t keyid; + +	if (args->event != NB_EV_APPLY) +		return NB_OK; + +	keyid = yang_dnode_get_uint64(args->dnode, "key-id"); +	if (keyid > UINT32_MAX) +		return NB_ERR_NOT_FOUND; +	name = yang_dnode_get_string(args->dnode, "../name"); +	keychain = keychain_lookup(name); +	key = key_lookup(keychain, (uint32_t)keyid); +	key_delete(keychain, key); +	keychain_touch(keychain);  	return NB_OK;  }  static const void *key_chains_key_chain_key_get_next(struct nb_cb_get_next_args *args)  { -	/* TODO: implement me. */ -	return NULL; +	const struct listnode *kcnode = args->parent_list_entry; +	const struct keychain *keychain = kcnode->data; +	const struct listnode *prev = args->list_entry; + +	return prev ? prev->next : keychain->key->head;  }  static int key_chains_key_chain_key_get_keys(struct nb_cb_get_keys_args *args)  { -	/* TODO: implement me. */ +	const struct listnode *node = args->list_entry; +	const struct key *key = node->data; + +	args->keys->num = 1; +	snprintf(args->keys->key[0], sizeof(args->keys->key[0]), "%" PRIu32, +		 key->index); +  	return NB_OK;  }  static const void *key_chains_key_chain_key_lookup_entry(struct nb_cb_lookup_entry_args *args)  { -	/* TODO: implement me. */ +	const struct listnode *kcnode = args->parent_list_entry; +	const struct keychain *keychain = kcnode->data; +	struct listnode *node; +	struct key *key; +	uint32_t index; + +	index = strtoul(args->keys->key[0], NULL, 0); +	for (ALL_LIST_ELEMENTS_RO(keychain->key, node, key)) +		if (key->index == index) +			return node;  	return NULL;  } -/* - * XPath: /ietf-key-chain:key-chains/key-chain/key/lifetime/send-accept-lifetime/always - */ -static int key_chains_key_chain_key_lifetime_send_accept_lifetime_always_create(struct nb_cb_create_args *args) +static int __lifetime_create(struct nb_cb_create_args *args, bool send, +			     bool accept, bool always)  { -	switch (args->event) { -	case NB_EV_VALIDATE: -	case NB_EV_PREPARE: -	case NB_EV_ABORT: -	case NB_EV_APPLY: -		/* TODO: implement me. */ -		break; -	} +	struct key *key; + +	if (args->event != NB_EV_APPLY) +		return NB_OK; +	if (always) +		key = __dnode_get_key3(args->dnode, true); +	else +		key = __dnode_get_key2(args->dnode, true); +	if (send) { +		key->send.start = 0; +		key->send.end = -1; +		key->send.duration = 0; +	} +	if (accept) { +		key->accept.start = 0; +		key->accept.end = -1; +		key->accept.duration = 0; +	}  	return NB_OK;  } -static void key_chains_key_chain_key_lifetime_send_accept_lifetime_always_cli_write(struct vty *vty, const struct lyd_node *dnode, bool show_defaults) +static int __lifetime_start_date_time_modify(struct nb_cb_modify_args *args, +					     bool send, bool accept)  { -	/* TODO: this cli callback is optional; the cli output may not need to be done at each node. */ -} +	struct key *key; +	time_t time; -static int key_chains_key_chain_key_lifetime_send_accept_lifetime_always_destroy(struct nb_cb_destroy_args *args) -{ -	switch (args->event) { -	case NB_EV_VALIDATE: -	case NB_EV_PREPARE: -	case NB_EV_ABORT: -	case NB_EV_APPLY: -		/* TODO: implement me. */ -		break; -	} +	if (args->event != NB_EV_APPLY) +		return NB_OK; -	return NB_OK; -} +	key = __dnode_get_key3(args->dnode, true); +	time = yang_dnode_get_date_and_time(args->dnode, NULL); -/* - * XPath: /ietf-key-chain:key-chains/key-chain/key/lifetime/send-accept-lifetime/start-date-time - */ -static int key_chains_key_chain_key_lifetime_send_accept_lifetime_start_date_time_modify(struct nb_cb_modify_args *args) -{ -	switch (args->event) { -	case NB_EV_VALIDATE: -	case NB_EV_PREPARE: -	case NB_EV_ABORT: -	case NB_EV_APPLY: -		/* TODO: implement me. */ -		break; -	} +	if (send) +		key->send.start = time; +	if (accept) +		key->accept.start = time;  	return NB_OK;  } -static void key_chains_key_chain_key_lifetime_send_accept_lifetime_start_date_time_cli_write(struct vty *vty, const struct lyd_node *dnode, bool show_defaults) +static int __lifetime_no_end_time_create(struct nb_cb_create_args *args, +					 bool send, bool accept)  { -	/* TODO: this cli callback is optional; the cli output may not need to be done at each node. */ -} +	struct key *key; -static int key_chains_key_chain_key_lifetime_send_accept_lifetime_start_date_time_destroy(struct nb_cb_destroy_args *args) -{ -	switch (args->event) { -	case NB_EV_VALIDATE: -	case NB_EV_PREPARE: -	case NB_EV_ABORT: -	case NB_EV_APPLY: -		/* TODO: implement me. */ -		break; -	} +	if (args->event != NB_EV_APPLY) +		return NB_OK; +	key = __dnode_get_key3(args->dnode, true); +	if (send) +		key->send.end = -1; +	if (accept) +		key->accept.end = -1;  	return NB_OK;  } -/* - * XPath: /ietf-key-chain:key-chains/key-chain/key/lifetime/send-accept-lifetime/no-end-time - */ -static int key_chains_key_chain_key_lifetime_send_accept_lifetime_no_end_time_create(struct nb_cb_create_args *args) +static int __lifetime_duration_modify(struct nb_cb_modify_args *args, bool send, +				      bool accept)  { -	switch (args->event) { -	case NB_EV_VALIDATE: -	case NB_EV_PREPARE: -	case NB_EV_ABORT: -	case NB_EV_APPLY: -		/* TODO: implement me. */ -		break; -	} +	struct key *key; +	uint32_t duration; +	time_t time; + +	if (args->event != NB_EV_APPLY) +		return NB_OK; + +	key = __dnode_get_key3(args->dnode, true); +	time = yang_dnode_get_date_and_time(args->dnode, "../start-date-time"); +	duration = yang_dnode_get_uint32(args->dnode, NULL); +	if (send) +		key->send.end = time + duration; +	if (accept) +		key->accept.end = time + duration;  	return NB_OK;  } -static void key_chains_key_chain_key_lifetime_send_accept_lifetime_no_end_time_cli_write(struct vty *vty, const struct lyd_node *dnode, bool show_defaults) +static int __lifetime_end_date_time_modify(struct nb_cb_modify_args *args, +					   bool send, bool accept)  { -	/* TODO: this cli callback is optional; the cli output may not need to be done at each node. */ -} +	struct key *key; +	time_t time; -static int key_chains_key_chain_key_lifetime_send_accept_lifetime_no_end_time_destroy(struct nb_cb_destroy_args *args) -{ -	switch (args->event) { -	case NB_EV_VALIDATE: -	case NB_EV_PREPARE: -	case NB_EV_ABORT: -	case NB_EV_APPLY: -		/* TODO: implement me. */ -		break; -	} +	if (args->event != NB_EV_APPLY) +		return NB_OK; +	key = __dnode_get_key3(args->dnode, true); +	time = yang_dnode_get_date_and_time(args->dnode, NULL); + +	if (send) +		key->send.end = time; +	if (accept) +		key->accept.end = time;  	return NB_OK;  }  /* - * XPath: /ietf-key-chain:key-chains/key-chain/key/lifetime/send-accept-lifetime/duration + * XPath: /ietf-key-chain:key-chains/key-chain/key/lifetime/send-accept-lifetime   */ -static int key_chains_key_chain_key_lifetime_send_accept_lifetime_duration_modify(struct nb_cb_modify_args *args) +static int key_chains_key_chain_key_lifetime_send_accept_lifetime_create( +	struct nb_cb_create_args *args)  { -	switch (args->event) { -	case NB_EV_VALIDATE: -	case NB_EV_PREPARE: -	case NB_EV_ABORT: -	case NB_EV_APPLY: -		/* TODO: implement me. */ -		break; -	} -	return NB_OK; +	return __lifetime_create(args, true, true, false);  } -static void key_chains_key_chain_key_lifetime_send_accept_lifetime_duration_cli_write(struct vty *vty, const struct lyd_node *dnode, bool show_defaults) +/* + * XPath: /ietf-key-chain:key-chains/key-chain/key/lifetime/send-accept-lifetime/always + */ +static int key_chains_key_chain_key_lifetime_send_accept_lifetime_always_create( +	struct nb_cb_create_args *args)  { -	/* TODO: this cli callback is optional; the cli output may not need to be done at each node. */ +	return __lifetime_create(args, true, true, true);  } -static int key_chains_key_chain_key_lifetime_send_accept_lifetime_duration_destroy(struct nb_cb_destroy_args *args) +/* + * XPath: /ietf-key-chain:key-chains/key-chain/key/lifetime/send-accept-lifetime/start-date-time + */ +static int +key_chains_key_chain_key_lifetime_send_accept_lifetime_start_date_time_modify( +	struct nb_cb_modify_args *args)  { -	switch (args->event) { -	case NB_EV_VALIDATE: -	case NB_EV_PREPARE: -	case NB_EV_ABORT: -	case NB_EV_APPLY: -		/* TODO: implement me. */ -		break; -	} - -	return NB_OK; +	return __lifetime_start_date_time_modify(args, true, true);  }  /* - * XPath: /ietf-key-chain:key-chains/key-chain/key/lifetime/send-accept-lifetime/end-date-time + * XPath: /ietf-key-chain:key-chains/key-chain/key/lifetime/send-accept-lifetime/no-end-time   */ -static int key_chains_key_chain_key_lifetime_send_accept_lifetime_end_date_time_modify(struct nb_cb_modify_args *args) +static int +key_chains_key_chain_key_lifetime_send_accept_lifetime_no_end_time_create( +	struct nb_cb_create_args *args)  { -	switch (args->event) { -	case NB_EV_VALIDATE: -	case NB_EV_PREPARE: -	case NB_EV_ABORT: -	case NB_EV_APPLY: -		/* TODO: implement me. */ -		break; -	} - -	return NB_OK; +	return __lifetime_no_end_time_create(args, true, true);  } -static void key_chains_key_chain_key_lifetime_send_accept_lifetime_end_date_time_cli_write(struct vty *vty, const struct lyd_node *dnode, bool show_defaults) +/* + * XPath: /ietf-key-chain:key-chains/key-chain/key/lifetime/send-accept-lifetime/duration + */ +static int key_chains_key_chain_key_lifetime_send_accept_lifetime_duration_modify( +	struct nb_cb_modify_args *args)  { -	/* TODO: this cli callback is optional; the cli output may not need to be done at each node. */ +	return __lifetime_duration_modify(args, true, true);  } -static int key_chains_key_chain_key_lifetime_send_accept_lifetime_end_date_time_destroy(struct nb_cb_destroy_args *args) +/* + * XPath: /ietf-key-chain:key-chains/key-chain/key/lifetime/send-accept-lifetime/end-date-time + */ +static int +key_chains_key_chain_key_lifetime_send_accept_lifetime_end_date_time_modify( +	struct nb_cb_modify_args *args)  { -	switch (args->event) { -	case NB_EV_VALIDATE: -	case NB_EV_PREPARE: -	case NB_EV_ABORT: -	case NB_EV_APPLY: -		/* TODO: implement me. */ -		break; -	} - -	return NB_OK; +	return __lifetime_end_date_time_modify(args, true, true);  }  /* - * XPath: /ietf-key-chain:key-chains/key-chain/key/lifetime/send-lifetime/always + * XPath: /ietf-key-chain:key-chains/key-chain/key/lifetime/send-lifetime   */ -static int key_chains_key_chain_key_lifetime_send_lifetime_always_create(struct nb_cb_create_args *args) +static int key_chains_key_chain_key_lifetime_send_lifetime_create( +	struct nb_cb_create_args *args)  { -	switch (args->event) { -	case NB_EV_VALIDATE: -	case NB_EV_PREPARE: -	case NB_EV_ABORT: -	case NB_EV_APPLY: -		/* TODO: implement me. */ -		break; -	} - -	return NB_OK; -} -static void key_chains_key_chain_key_lifetime_send_lifetime_always_cli_write(struct vty *vty, const struct lyd_node *dnode, bool show_defaults) -{ -	/* TODO: this cli callback is optional; the cli output may not need to be done at each node. */ +	return __lifetime_create(args, true, false, false);  } -static int key_chains_key_chain_key_lifetime_send_lifetime_always_destroy(struct nb_cb_destroy_args *args) +/* + * XPath: /ietf-key-chain:key-chains/key-chain/key/lifetime/send-lifetime/always + */ +static int key_chains_key_chain_key_lifetime_send_lifetime_always_create( +	struct nb_cb_create_args *args)  { -	switch (args->event) { -	case NB_EV_VALIDATE: -	case NB_EV_PREPARE: -	case NB_EV_ABORT: -	case NB_EV_APPLY: -		/* TODO: implement me. */ -		break; -	} - -	return NB_OK; +	return __lifetime_create(args, true, false, true);  }  /* @@ -374,35 +452,7 @@ static int key_chains_key_chain_key_lifetime_send_lifetime_always_destroy(struct   */  static int key_chains_key_chain_key_lifetime_send_lifetime_start_date_time_modify(struct nb_cb_modify_args *args)  { -	switch (args->event) { -	case NB_EV_VALIDATE: -	case NB_EV_PREPARE: -	case NB_EV_ABORT: -	case NB_EV_APPLY: -		/* TODO: implement me. */ -		break; -	} - -	return NB_OK; -} - -static void key_chains_key_chain_key_lifetime_send_lifetime_start_date_time_cli_write(struct vty *vty, const struct lyd_node *dnode, bool show_defaults) -{ -	/* TODO: this cli callback is optional; the cli output may not need to be done at each node. */ -} - -static int key_chains_key_chain_key_lifetime_send_lifetime_start_date_time_destroy(struct nb_cb_destroy_args *args) -{ -	switch (args->event) { -	case NB_EV_VALIDATE: -	case NB_EV_PREPARE: -	case NB_EV_ABORT: -	case NB_EV_APPLY: -		/* TODO: implement me. */ -		break; -	} - -	return NB_OK; +	return __lifetime_start_date_time_modify(args, true, false);  }  /* @@ -410,35 +460,7 @@ static int key_chains_key_chain_key_lifetime_send_lifetime_start_date_time_destr   */  static int key_chains_key_chain_key_lifetime_send_lifetime_no_end_time_create(struct nb_cb_create_args *args)  { -	switch (args->event) { -	case NB_EV_VALIDATE: -	case NB_EV_PREPARE: -	case NB_EV_ABORT: -	case NB_EV_APPLY: -		/* TODO: implement me. */ -		break; -	} - -	return NB_OK; -} - -static void key_chains_key_chain_key_lifetime_send_lifetime_no_end_time_cli_write(struct vty *vty, const struct lyd_node *dnode, bool show_defaults) -{ -	/* TODO: this cli callback is optional; the cli output may not need to be done at each node. */ -} - -static int key_chains_key_chain_key_lifetime_send_lifetime_no_end_time_destroy(struct nb_cb_destroy_args *args) -{ -	switch (args->event) { -	case NB_EV_VALIDATE: -	case NB_EV_PREPARE: -	case NB_EV_ABORT: -	case NB_EV_APPLY: -		/* TODO: implement me. */ -		break; -	} - -	return NB_OK; +	return __lifetime_no_end_time_create(args, true, false);  }  /* @@ -446,35 +468,7 @@ static int key_chains_key_chain_key_lifetime_send_lifetime_no_end_time_destroy(s   */  static int key_chains_key_chain_key_lifetime_send_lifetime_duration_modify(struct nb_cb_modify_args *args)  { -	switch (args->event) { -	case NB_EV_VALIDATE: -	case NB_EV_PREPARE: -	case NB_EV_ABORT: -	case NB_EV_APPLY: -		/* TODO: implement me. */ -		break; -	} - -	return NB_OK; -} - -static void key_chains_key_chain_key_lifetime_send_lifetime_duration_cli_write(struct vty *vty, const struct lyd_node *dnode, bool show_defaults) -{ -	/* TODO: this cli callback is optional; the cli output may not need to be done at each node. */ -} - -static int key_chains_key_chain_key_lifetime_send_lifetime_duration_destroy(struct nb_cb_destroy_args *args) -{ -	switch (args->event) { -	case NB_EV_VALIDATE: -	case NB_EV_PREPARE: -	case NB_EV_ABORT: -	case NB_EV_APPLY: -		/* TODO: implement me. */ -		break; -	} - -	return NB_OK; +	return __lifetime_duration_modify(args, true, false);  }  /* @@ -482,35 +476,17 @@ static int key_chains_key_chain_key_lifetime_send_lifetime_duration_destroy(stru   */  static int key_chains_key_chain_key_lifetime_send_lifetime_end_date_time_modify(struct nb_cb_modify_args *args)  { -	switch (args->event) { -	case NB_EV_VALIDATE: -	case NB_EV_PREPARE: -	case NB_EV_ABORT: -	case NB_EV_APPLY: -		/* TODO: implement me. */ -		break; -	} - -	return NB_OK; +	return __lifetime_end_date_time_modify(args, true, false);  } -static void key_chains_key_chain_key_lifetime_send_lifetime_end_date_time_cli_write(struct vty *vty, const struct lyd_node *dnode, bool show_defaults) -{ -	/* TODO: this cli callback is optional; the cli output may not need to be done at each node. */ -} - -static int key_chains_key_chain_key_lifetime_send_lifetime_end_date_time_destroy(struct nb_cb_destroy_args *args) +/* + * XPath: /ietf-key-chain:key-chains/key-chain/key/lifetime/accept-lifetime + */ +static int key_chains_key_chain_key_lifetime_accept_lifetime_create( +	struct nb_cb_create_args *args)  { -	switch (args->event) { -	case NB_EV_VALIDATE: -	case NB_EV_PREPARE: -	case NB_EV_ABORT: -	case NB_EV_APPLY: -		/* TODO: implement me. */ -		break; -	} -	return NB_OK; +	return __lifetime_create(args, false, true, false);  }  /* @@ -518,35 +494,7 @@ static int key_chains_key_chain_key_lifetime_send_lifetime_end_date_time_destroy   */  static int key_chains_key_chain_key_lifetime_accept_lifetime_always_create(struct nb_cb_create_args *args)  { -	switch (args->event) { -	case NB_EV_VALIDATE: -	case NB_EV_PREPARE: -	case NB_EV_ABORT: -	case NB_EV_APPLY: -		/* TODO: implement me. */ -		break; -	} - -	return NB_OK; -} - -static void key_chains_key_chain_key_lifetime_accept_lifetime_always_cli_write(struct vty *vty, const struct lyd_node *dnode, bool show_defaults) -{ -	/* TODO: this cli callback is optional; the cli output may not need to be done at each node. */ -} - -static int key_chains_key_chain_key_lifetime_accept_lifetime_always_destroy(struct nb_cb_destroy_args *args) -{ -	switch (args->event) { -	case NB_EV_VALIDATE: -	case NB_EV_PREPARE: -	case NB_EV_ABORT: -	case NB_EV_APPLY: -		/* TODO: implement me. */ -		break; -	} - -	return NB_OK; +	return __lifetime_create(args, false, true, true);  }  /* @@ -554,35 +502,7 @@ static int key_chains_key_chain_key_lifetime_accept_lifetime_always_destroy(stru   */  static int key_chains_key_chain_key_lifetime_accept_lifetime_start_date_time_modify(struct nb_cb_modify_args *args)  { -	switch (args->event) { -	case NB_EV_VALIDATE: -	case NB_EV_PREPARE: -	case NB_EV_ABORT: -	case NB_EV_APPLY: -		/* TODO: implement me. */ -		break; -	} - -	return NB_OK; -} - -static void key_chains_key_chain_key_lifetime_accept_lifetime_start_date_time_cli_write(struct vty *vty, const struct lyd_node *dnode, bool show_defaults) -{ -	/* TODO: this cli callback is optional; the cli output may not need to be done at each node. */ -} - -static int key_chains_key_chain_key_lifetime_accept_lifetime_start_date_time_destroy(struct nb_cb_destroy_args *args) -{ -	switch (args->event) { -	case NB_EV_VALIDATE: -	case NB_EV_PREPARE: -	case NB_EV_ABORT: -	case NB_EV_APPLY: -		/* TODO: implement me. */ -		break; -	} - -	return NB_OK; +	return __lifetime_start_date_time_modify(args, false, true);  }  /* @@ -590,35 +510,7 @@ static int key_chains_key_chain_key_lifetime_accept_lifetime_start_date_time_des   */  static int key_chains_key_chain_key_lifetime_accept_lifetime_no_end_time_create(struct nb_cb_create_args *args)  { -	switch (args->event) { -	case NB_EV_VALIDATE: -	case NB_EV_PREPARE: -	case NB_EV_ABORT: -	case NB_EV_APPLY: -		/* TODO: implement me. */ -		break; -	} - -	return NB_OK; -} - -static void key_chains_key_chain_key_lifetime_accept_lifetime_no_end_time_cli_write(struct vty *vty, const struct lyd_node *dnode, bool show_defaults) -{ -	/* TODO: this cli callback is optional; the cli output may not need to be done at each node. */ -} - -static int key_chains_key_chain_key_lifetime_accept_lifetime_no_end_time_destroy(struct nb_cb_destroy_args *args) -{ -	switch (args->event) { -	case NB_EV_VALIDATE: -	case NB_EV_PREPARE: -	case NB_EV_ABORT: -	case NB_EV_APPLY: -		/* TODO: implement me. */ -		break; -	} - -	return NB_OK; +	return __lifetime_no_end_time_create(args, false, true);  }  /* @@ -626,35 +518,7 @@ static int key_chains_key_chain_key_lifetime_accept_lifetime_no_end_time_destroy   */  static int key_chains_key_chain_key_lifetime_accept_lifetime_duration_modify(struct nb_cb_modify_args *args)  { -	switch (args->event) { -	case NB_EV_VALIDATE: -	case NB_EV_PREPARE: -	case NB_EV_ABORT: -	case NB_EV_APPLY: -		/* TODO: implement me. */ -		break; -	} - -	return NB_OK; -} - -static void key_chains_key_chain_key_lifetime_accept_lifetime_duration_cli_write(struct vty *vty, const struct lyd_node *dnode, bool show_defaults) -{ -	/* TODO: this cli callback is optional; the cli output may not need to be done at each node. */ -} - -static int key_chains_key_chain_key_lifetime_accept_lifetime_duration_destroy(struct nb_cb_destroy_args *args) -{ -	switch (args->event) { -	case NB_EV_VALIDATE: -	case NB_EV_PREPARE: -	case NB_EV_ABORT: -	case NB_EV_APPLY: -		/* TODO: implement me. */ -		break; -	} - -	return NB_OK; +	return __lifetime_duration_modify(args, false, true);  }  /* @@ -662,35 +526,7 @@ static int key_chains_key_chain_key_lifetime_accept_lifetime_duration_destroy(st   */  static int key_chains_key_chain_key_lifetime_accept_lifetime_end_date_time_modify(struct nb_cb_modify_args *args)  { -	switch (args->event) { -	case NB_EV_VALIDATE: -	case NB_EV_PREPARE: -	case NB_EV_ABORT: -	case NB_EV_APPLY: -		/* TODO: implement me. */ -		break; -	} - -	return NB_OK; -} - -static void key_chains_key_chain_key_lifetime_accept_lifetime_end_date_time_cli_write(struct vty *vty, const struct lyd_node *dnode, bool show_defaults) -{ -	/* TODO: this cli callback is optional; the cli output may not need to be done at each node. */ -} - -static int key_chains_key_chain_key_lifetime_accept_lifetime_end_date_time_destroy(struct nb_cb_destroy_args *args) -{ -	switch (args->event) { -	case NB_EV_VALIDATE: -	case NB_EV_PREPARE: -	case NB_EV_ABORT: -	case NB_EV_APPLY: -		/* TODO: implement me. */ -		break; -	} - -	return NB_OK; +	return __lifetime_end_date_time_modify(args, false, true);  }  /* @@ -698,21 +534,67 @@ static int key_chains_key_chain_key_lifetime_accept_lifetime_end_date_time_destr   */  static int key_chains_key_chain_key_crypto_algorithm_modify(struct nb_cb_modify_args *args)  { -	switch (args->event) { -	case NB_EV_VALIDATE: -	case NB_EV_PREPARE: -	case NB_EV_ABORT: -	case NB_EV_APPLY: -		/* TODO: implement me. */ -		break; +	static const char prefix[] = "ietf-key-chain:"; +	static const int prefix_len = sizeof(prefix) - 1; +	struct keychain *keychain; +	const char *name; +	struct key *key; +	uint32_t index; +	uint8_t hash_algo; + +	if (args->event != NB_EV_VALIDATE && args->event != NB_EV_APPLY) +		return NB_OK; + +	name = yang_dnode_get_string(args->dnode, "../../name"); +	keychain = keychain_lookup(name); +	index = (uint32_t)yang_dnode_get_uint64(args->dnode, "../key-id"); +	key = key_lookup(keychain, index); +	name = yang_dnode_get_string(args->dnode, NULL); +	if (!strncmp(name, prefix, prefix_len)) +		name += prefix_len; +	hash_algo = keychain_get_algo_id_by_name(name); + +	if (args->event == NB_EV_VALIDATE) { +		if (!hash_algo) { +			zlog_err("\"%s\" hash algo not supported", name); +			return NB_ERR_VALIDATION; +		} +#ifndef CRYPTO_OPENSSL +		if (hash_algo == KEYCHAIN_ALGO_NULL) { +			zlog_err("\"%s\" algo not supported, compile with --with-crypto=openssl", +				 name); +			return NB_ERR_VALIDATION; +		} +#endif /* CRYPTO_OPENSSL */ +		return NB_OK;  	} +	assert(args->event == NB_EV_APPLY); +	key->hash_algo = hash_algo; + +	keychain_touch(keychain);  	return NB_OK;  } -static void key_chains_key_chain_key_crypto_algorithm_cli_write(struct vty *vty, const struct lyd_node *dnode, bool show_defaults) +static int key_chains_key_chain_key_crypto_algorithm_destroy( +	struct nb_cb_destroy_args *args)  { -	/* TODO: this cli callback is optional; the cli output may not need to be done at each node. */ +	struct keychain *keychain; +	const char *name; +	struct key *key; +	uint32_t index; + +	if (args->event != NB_EV_APPLY) +		return NB_OK; + +	name = yang_dnode_get_string(args->dnode, "../../../name"); +	keychain = keychain_lookup(name); +	index = (uint32_t)yang_dnode_get_uint64(args->dnode, "../../key-id"); +	key = key_lookup(keychain, index); +	key->hash_algo = KEYCHAIN_ALGO_NULL; +	keychain_touch(keychain); + +	return NB_OK;  }  /* @@ -720,33 +602,48 @@ static void key_chains_key_chain_key_crypto_algorithm_cli_write(struct vty *vty,   */  static int key_chains_key_chain_key_key_string_keystring_modify(struct nb_cb_modify_args *args)  { -	switch (args->event) { -	case NB_EV_VALIDATE: -	case NB_EV_PREPARE: -	case NB_EV_ABORT: -	case NB_EV_APPLY: -		/* TODO: implement me. */ -		break; -	} +	struct keychain *keychain; +	const char *name; +	struct key *key; +	uint32_t index; -	return NB_OK; -} +	if (args->event != NB_EV_APPLY) +		return NB_OK; -static void key_chains_key_chain_key_key_string_keystring_cli_write(struct vty *vty, const struct lyd_node *dnode, bool show_defaults) -{ -	/* TODO: this cli callback is optional; the cli output may not need to be done at each node. */ +	name = yang_dnode_get_string(args->dnode, "../../../name"); +	keychain = keychain_lookup(name); +	index = (uint32_t)yang_dnode_get_uint64(args->dnode, "../../key-id"); +	key = key_lookup(keychain, index); +	assert(key); + + +	if (key->string) +		XFREE(MTYPE_KEY, key->string); +	key->string = XSTRDUP(MTYPE_KEY, +			      yang_dnode_get_string(args->dnode, NULL)); + +	keychain_touch(keychain); +	return NB_OK;  }  static int key_chains_key_chain_key_key_string_keystring_destroy(struct nb_cb_destroy_args *args)  { -	switch (args->event) { -	case NB_EV_VALIDATE: -	case NB_EV_PREPARE: -	case NB_EV_ABORT: -	case NB_EV_APPLY: -		/* TODO: implement me. */ -		break; -	} +	struct keychain *keychain; +	const char *name; +	struct key *key; +	uint32_t index; + +	if (args->event != NB_EV_APPLY) +		return NB_OK; + +	name = yang_dnode_get_string(args->dnode, "../../../name"); +	keychain = keychain_lookup(name); +	index = (uint32_t)yang_dnode_get_uint64(args->dnode, "../../key-id"); +	key = key_lookup(keychain, index); +	assert(key); + +	XFREE(MTYPE_KEY, key->string); +	keychain_touch(keychain);  	return NB_OK;  } @@ -756,8 +653,18 @@ static int key_chains_key_chain_key_key_string_keystring_destroy(struct nb_cb_de   */  static struct yang_data *key_chains_key_chain_key_send_lifetime_active_get_elem(struct nb_cb_get_elem_args *args)  { -	/* TODO: implement me. */ -	return NULL; +	const struct listnode *node = args->list_entry; +	const struct key *key = node->data; +	time_t now = time(NULL); +	bool active = false; + +	if (key->send.start == 0) +		active = true; +	else if (key->send.start <= now) +		if (key->send.end >= now || key->send.end == -1) +			active = true; + +	return yang_data_new_bool(args->xpath, active);  }  /* @@ -765,13 +672,29 @@ static struct yang_data *key_chains_key_chain_key_send_lifetime_active_get_elem(   */  static struct yang_data *key_chains_key_chain_key_accept_lifetime_active_get_elem(struct nb_cb_get_elem_args *args)  { -	/* TODO: implement me. */ -	return NULL; +	const struct listnode *node = args->list_entry; +	const struct key *key = node->data; +	time_t now = time(NULL); +	bool active = false; + +	if (key->accept.start == 0) +		active = true; +	else if (key->accept.start <= now) +		if (key->accept.end >= now || key->accept.end == -1) +			active = true; + +	return yang_data_new_bool(args->xpath, active);  } +static const char * const keychain_features[] = { +	"independent-send-accept-lifetime", +	NULL, +}; +  /* clang-format off */ -const struct frr_yang_module_info ietf_key_chain_nb_info = { +const struct frr_yang_module_info ietf_key_chain_info = {  	.name = "ietf-key-chain", +	.features = (const char **)keychain_features,  	.nodes = {  		{  			.xpath = "/ietf-key-chain:key-chains/key-chain", @@ -781,6 +704,8 @@ const struct frr_yang_module_info ietf_key_chain_nb_info = {  				.get_next = key_chains_key_chain_get_next,  				.get_keys = key_chains_key_chain_get_keys,  				.lookup_entry = key_chains_key_chain_lookup_entry, +				.cli_show = key_chains_key_chain_cli_write, +				.cli_show_end = key_chains_key_chain_cli_write_end,  			}  		},  		{ @@ -788,6 +713,7 @@ const struct frr_yang_module_info ietf_key_chain_nb_info = {  			.cbs = {  				.modify = key_chains_key_chain_description_modify,  				.destroy = key_chains_key_chain_description_destroy, +				.cli_show = key_chains_key_chain_description_cli_write,  			}  		},  		{ @@ -804,117 +730,145 @@ const struct frr_yang_module_info ietf_key_chain_nb_info = {  				.get_next = key_chains_key_chain_key_get_next,  				.get_keys = key_chains_key_chain_key_get_keys,  				.lookup_entry = key_chains_key_chain_key_lookup_entry, +				.cli_show = key_chains_key_chain_key_cli_write, +				.cli_show_end = key_chains_key_chain_key_cli_write_end, +			} +		}, +		{ +			.xpath = "/ietf-key-chain:key-chains/key-chain/key/lifetime/send-accept-lifetime", +			.cbs = { +				.create = key_chains_key_chain_key_lifetime_send_accept_lifetime_create, +				.destroy = __destroy_nop,  			}  		},  		{  			.xpath = "/ietf-key-chain:key-chains/key-chain/key/lifetime/send-accept-lifetime/always",  			.cbs = {  				.create = key_chains_key_chain_key_lifetime_send_accept_lifetime_always_create, -				.destroy = key_chains_key_chain_key_lifetime_send_accept_lifetime_always_destroy, +				.destroy = __destroy_nop,  			}  		},  		{  			.xpath = "/ietf-key-chain:key-chains/key-chain/key/lifetime/send-accept-lifetime/start-date-time",  			.cbs = {  				.modify = key_chains_key_chain_key_lifetime_send_accept_lifetime_start_date_time_modify, -				.destroy = key_chains_key_chain_key_lifetime_send_accept_lifetime_start_date_time_destroy, +				.destroy = __destroy_nop, +				.cli_show = key_chains_key_chain_key_lifetime_send_accept_lifetime_start_date_time_cli_write,  			}  		},  		{  			.xpath = "/ietf-key-chain:key-chains/key-chain/key/lifetime/send-accept-lifetime/no-end-time",  			.cbs = {  				.create = key_chains_key_chain_key_lifetime_send_accept_lifetime_no_end_time_create, -				.destroy = key_chains_key_chain_key_lifetime_send_accept_lifetime_no_end_time_destroy, +				.destroy = __destroy_nop,  			}  		},  		{  			.xpath = "/ietf-key-chain:key-chains/key-chain/key/lifetime/send-accept-lifetime/duration",  			.cbs = {  				.modify = key_chains_key_chain_key_lifetime_send_accept_lifetime_duration_modify, -				.destroy = key_chains_key_chain_key_lifetime_send_accept_lifetime_duration_destroy, +				.destroy = __destroy_nop,  			}  		},  		{  			.xpath = "/ietf-key-chain:key-chains/key-chain/key/lifetime/send-accept-lifetime/end-date-time",  			.cbs = {  				.modify = key_chains_key_chain_key_lifetime_send_accept_lifetime_end_date_time_modify, -				.destroy = key_chains_key_chain_key_lifetime_send_accept_lifetime_end_date_time_destroy, +				.destroy = __destroy_nop, +			} +		}, +		{ +			.xpath = "/ietf-key-chain:key-chains/key-chain/key/lifetime/send-lifetime", +			.cbs = { +				.create = key_chains_key_chain_key_lifetime_send_lifetime_create, +				.destroy = __destroy_nop,  			}  		},  		{  			.xpath = "/ietf-key-chain:key-chains/key-chain/key/lifetime/send-lifetime/always",  			.cbs = {  				.create = key_chains_key_chain_key_lifetime_send_lifetime_always_create, -				.destroy = key_chains_key_chain_key_lifetime_send_lifetime_always_destroy, +				.destroy = __destroy_nop,  			}  		},  		{  			.xpath = "/ietf-key-chain:key-chains/key-chain/key/lifetime/send-lifetime/start-date-time",  			.cbs = {  				.modify = key_chains_key_chain_key_lifetime_send_lifetime_start_date_time_modify, -				.destroy = key_chains_key_chain_key_lifetime_send_lifetime_start_date_time_destroy, +				.destroy = __destroy_nop, +				.cli_show = key_chains_key_chain_key_lifetime_send_lifetime_start_date_time_cli_write,  			}  		},  		{  			.xpath = "/ietf-key-chain:key-chains/key-chain/key/lifetime/send-lifetime/no-end-time",  			.cbs = {  				.create = key_chains_key_chain_key_lifetime_send_lifetime_no_end_time_create, -				.destroy = key_chains_key_chain_key_lifetime_send_lifetime_no_end_time_destroy, +				.destroy = __destroy_nop,  			}  		},  		{  			.xpath = "/ietf-key-chain:key-chains/key-chain/key/lifetime/send-lifetime/duration",  			.cbs = {  				.modify = key_chains_key_chain_key_lifetime_send_lifetime_duration_modify, -				.destroy = key_chains_key_chain_key_lifetime_send_lifetime_duration_destroy, +				.destroy = __destroy_nop,  			}  		},  		{  			.xpath = "/ietf-key-chain:key-chains/key-chain/key/lifetime/send-lifetime/end-date-time",  			.cbs = {  				.modify = key_chains_key_chain_key_lifetime_send_lifetime_end_date_time_modify, -				.destroy = key_chains_key_chain_key_lifetime_send_lifetime_end_date_time_destroy, +				.destroy = __destroy_nop, +			} +		}, +		{ +			.xpath = "/ietf-key-chain:key-chains/key-chain/key/lifetime/accept-lifetime", +			.cbs = { +				.create = key_chains_key_chain_key_lifetime_accept_lifetime_create, +				.destroy = __destroy_nop,  			}  		},  		{  			.xpath = "/ietf-key-chain:key-chains/key-chain/key/lifetime/accept-lifetime/always",  			.cbs = {  				.create = key_chains_key_chain_key_lifetime_accept_lifetime_always_create, -				.destroy = key_chains_key_chain_key_lifetime_accept_lifetime_always_destroy, +				.destroy = __destroy_nop,  			}  		},  		{  			.xpath = "/ietf-key-chain:key-chains/key-chain/key/lifetime/accept-lifetime/start-date-time",  			.cbs = {  				.modify = key_chains_key_chain_key_lifetime_accept_lifetime_start_date_time_modify, -				.destroy = key_chains_key_chain_key_lifetime_accept_lifetime_start_date_time_destroy, +				.destroy = __destroy_nop, +				.cli_show = key_chains_key_chain_key_lifetime_accept_lifetime_start_date_time_cli_write,  			}  		},  		{  			.xpath = "/ietf-key-chain:key-chains/key-chain/key/lifetime/accept-lifetime/no-end-time",  			.cbs = {  				.create = key_chains_key_chain_key_lifetime_accept_lifetime_no_end_time_create, -				.destroy = key_chains_key_chain_key_lifetime_accept_lifetime_no_end_time_destroy, +				.destroy = __destroy_nop,  			}  		},  		{  			.xpath = "/ietf-key-chain:key-chains/key-chain/key/lifetime/accept-lifetime/duration",  			.cbs = {  				.modify = key_chains_key_chain_key_lifetime_accept_lifetime_duration_modify, -				.destroy = key_chains_key_chain_key_lifetime_accept_lifetime_duration_destroy, +				.destroy = __destroy_nop,  			}  		},  		{  			.xpath = "/ietf-key-chain:key-chains/key-chain/key/lifetime/accept-lifetime/end-date-time",  			.cbs = {  				.modify = key_chains_key_chain_key_lifetime_accept_lifetime_end_date_time_modify, -				.destroy = key_chains_key_chain_key_lifetime_accept_lifetime_end_date_time_destroy, +				.destroy = __destroy_nop,  			}  		},  		{  			.xpath = "/ietf-key-chain:key-chains/key-chain/key/crypto-algorithm",  			.cbs = {  				.modify = key_chains_key_chain_key_crypto_algorithm_modify, +				.destroy = key_chains_key_chain_key_crypto_algorithm_destroy, +				.cli_show = key_chains_key_chain_key_crypto_algorithm_cli_write,  			}  		},  		{ @@ -922,6 +876,7 @@ const struct frr_yang_module_info ietf_key_chain_nb_info = {  			.cbs = {  				.modify = key_chains_key_chain_key_key_string_keystring_modify,  				.destroy = key_chains_key_chain_key_key_string_keystring_destroy, +				.cli_show = key_chains_key_chain_key_key_string_keystring_cli_write,  			}  		},  		{ @@ -939,135 +894,5 @@ const struct frr_yang_module_info ietf_key_chain_nb_info = {  		{  			.xpath = NULL,  		}, -	} -}; - -/* clang-format off */ -const struct frr_yang_module_info ietf_key_chain_cli_info = { -	.name = "ietf-key-chain", -	.nodes = { -		{ -			.xpath = "/ietf-key-chain:key-chains/key-chain", -			.cbs = { -				.cli_show = key_chains_key_chain_cli_write, -			} -		}, -		{ -			.xpath = "/ietf-key-chain:key-chains/key-chain/description", -			.cbs = { -				.cli_show = key_chains_key_chain_description_cli_write, -			} -		}, -		{ -			.xpath = "/ietf-key-chain:key-chains/key-chain/key", -			.cbs = { -				.cli_show = key_chains_key_chain_key_cli_write, -			} -		}, -		{ -			.xpath = "/ietf-key-chain:key-chains/key-chain/key/lifetime/send-accept-lifetime/always", -			.cbs = { -				.cli_show = key_chains_key_chain_key_lifetime_send_accept_lifetime_always_cli_write, -			} -		}, -		{ -			.xpath = "/ietf-key-chain:key-chains/key-chain/key/lifetime/send-accept-lifetime/start-date-time", -			.cbs = { -				.cli_show = key_chains_key_chain_key_lifetime_send_accept_lifetime_start_date_time_cli_write, -			} -		}, -		{ -			.xpath = "/ietf-key-chain:key-chains/key-chain/key/lifetime/send-accept-lifetime/no-end-time", -			.cbs = { -				.cli_show = key_chains_key_chain_key_lifetime_send_accept_lifetime_no_end_time_cli_write, -			} -		}, -		{ -			.xpath = "/ietf-key-chain:key-chains/key-chain/key/lifetime/send-accept-lifetime/duration", -			.cbs = { -				.cli_show = key_chains_key_chain_key_lifetime_send_accept_lifetime_duration_cli_write, -			} -		}, -		{ -			.xpath = "/ietf-key-chain:key-chains/key-chain/key/lifetime/send-accept-lifetime/end-date-time", -			.cbs = { -				.cli_show = key_chains_key_chain_key_lifetime_send_accept_lifetime_end_date_time_cli_write, -			} -		}, -		{ -			.xpath = "/ietf-key-chain:key-chains/key-chain/key/lifetime/send-lifetime/always", -			.cbs = { -				.cli_show = key_chains_key_chain_key_lifetime_send_lifetime_always_cli_write, -			} -		}, -		{ -			.xpath = "/ietf-key-chain:key-chains/key-chain/key/lifetime/send-lifetime/start-date-time", -			.cbs = { -				.cli_show = key_chains_key_chain_key_lifetime_send_lifetime_start_date_time_cli_write, -			} -		}, -		{ -			.xpath = "/ietf-key-chain:key-chains/key-chain/key/lifetime/send-lifetime/no-end-time", -			.cbs = { -				.cli_show = key_chains_key_chain_key_lifetime_send_lifetime_no_end_time_cli_write, -			} -		}, -		{ -			.xpath = "/ietf-key-chain:key-chains/key-chain/key/lifetime/send-lifetime/duration", -			.cbs = { -				.cli_show = key_chains_key_chain_key_lifetime_send_lifetime_duration_cli_write, -			} -		}, -		{ -			.xpath = "/ietf-key-chain:key-chains/key-chain/key/lifetime/send-lifetime/end-date-time", -			.cbs = { -				.cli_show = key_chains_key_chain_key_lifetime_send_lifetime_end_date_time_cli_write, -			} -		}, -		{ -			.xpath = "/ietf-key-chain:key-chains/key-chain/key/lifetime/accept-lifetime/always", -			.cbs = { -				.cli_show = key_chains_key_chain_key_lifetime_accept_lifetime_always_cli_write, -			} -		}, -		{ -			.xpath = "/ietf-key-chain:key-chains/key-chain/key/lifetime/accept-lifetime/start-date-time", -			.cbs = { -				.cli_show = key_chains_key_chain_key_lifetime_accept_lifetime_start_date_time_cli_write, -			} -		}, -		{ -			.xpath = "/ietf-key-chain:key-chains/key-chain/key/lifetime/accept-lifetime/no-end-time", -			.cbs = { -				.cli_show = key_chains_key_chain_key_lifetime_accept_lifetime_no_end_time_cli_write, -			} -		}, -		{ -			.xpath = "/ietf-key-chain:key-chains/key-chain/key/lifetime/accept-lifetime/duration", -			.cbs = { -				.cli_show = key_chains_key_chain_key_lifetime_accept_lifetime_duration_cli_write, -			} -		}, -		{ -			.xpath = "/ietf-key-chain:key-chains/key-chain/key/lifetime/accept-lifetime/end-date-time", -			.cbs = { -				.cli_show = key_chains_key_chain_key_lifetime_accept_lifetime_end_date_time_cli_write, -			} -		}, -		{ -			.xpath = "/ietf-key-chain:key-chains/key-chain/key/crypto-algorithm", -			.cbs = { -				.cli_show = key_chains_key_chain_key_crypto_algorithm_cli_write, -			} -		}, -		{ -			.xpath = "/ietf-key-chain:key-chains/key-chain/key/key-string/keystring", -			.cbs = { -				.cli_show = key_chains_key_chain_key_key_string_keystring_cli_write, -			} -		}, -		{ -			.xpath = NULL, -		}, -	} +	},  }; diff --git a/lib/subdir.am b/lib/subdir.am index 6893049c7e..db11def741 100644 --- a/lib/subdir.am +++ b/lib/subdir.am @@ -53,6 +53,8 @@ lib_libfrr_la_SOURCES = \  	lib/jhash.c \  	lib/json.c \  	lib/keychain.c \ +	lib/keychain_cli.c \ +	lib/keychain_nb.c \  	lib/ldp_sync.c \  	lib/lib_errors.c \  	lib/lib_vty.c \ @@ -148,7 +150,9 @@ nodist_lib_libfrr_la_SOURCES = \  	yang/frr-vrf.yang.c \  	yang/frr-routing.yang.c \  	yang/frr-nexthop.yang.c \ +	yang/ietf/frr-deviations-ietf-key-chain.yang.c \  	yang/ietf/ietf-routing-types.yang.c \ +	yang/ietf/ietf-key-chain.yang.c \  	yang/ietf/ietf-interfaces.yang.c \  	yang/ietf/ietf-bgp-types.yang.c \  	yang/frr-module-translator.yang.c \ @@ -181,6 +185,7 @@ clippy_scan += \  	lib/if.c \  	lib/filter_cli.c \  	lib/if_rmap.c \ +	lib/keychain_cli.c \  	lib/log_vty.c \  	lib/mgmt_be_client.c \  	lib/mgmt_fe_client.c \ diff --git a/lib/yang_wrappers.c b/lib/yang_wrappers.c index a0133954c3..4e49a129c2 100644 --- a/lib/yang_wrappers.c +++ b/lib/yang_wrappers.c @@ -1026,30 +1026,50 @@ void yang_dnode_get_mac(struct ethaddr *mac, const struct lyd_node *dnode,  	(void)prefix_str2mac(canon, mac);  } -struct yang_data *yang_data_new_date_and_time(const char *xpath, time_t time) +struct yang_data *yang_data_new_date_and_time(const char *xpath, time_t time, bool is_monotime)  { -	struct tm tm; -	char timebuf[MONOTIME_STRLEN]; -	struct timeval _time, time_real; -	char *ts_dot; -	uint16_t buflen; +	struct yang_data *yd; +	char *times = NULL; -	_time.tv_sec = time; -	_time.tv_usec = 0; -	monotime_to_realtime(&_time, &time_real); +	if (is_monotime) { +		struct timeval _time = { time, 0 }; +		struct timeval time_real; -	gmtime_r(&time_real.tv_sec, &tm); +		monotime_to_realtime(&_time, &time_real); +		time = time_real.tv_sec; +	} + +	(void)ly_time_time2str(time, NULL, ×); +	yd = yang_data_new(xpath, times); +	free(times); + +	return yd; +} + +struct timespec yang_dnode_get_date_and_timespec(const struct lyd_node *dnode, +						 const char *xpath_fmt, ...) +{ +	const char *canon = YANG_DNODE_XPATH_GET_CANON(dnode, xpath_fmt); +	struct timespec ts; +	LY_ERR err; + +	err = ly_time_str2ts(canon, &ts); +	assert(!err); + +	return ts; +} -	/* rfc-3339 format */ -	strftime(timebuf, sizeof(timebuf), "%Y-%m-%dT%H:%M:%S", &tm); -	buflen = strlen(timebuf); -	ts_dot = timebuf + buflen; +time_t yang_dnode_get_date_and_time(const struct lyd_node *dnode, +				    const char *xpath_fmt, ...) +{ +	const char *canon = YANG_DNODE_XPATH_GET_CANON(dnode, xpath_fmt); +	time_t time; +	LY_ERR err; -	/* microseconds and appends Z */ -	snprintfrr(ts_dot, sizeof(timebuf) - buflen, ".%06luZ", -		   (unsigned long)time_real.tv_usec); +	err = ly_time_str2time(canon, &time, NULL); +	assert(!err); -	return yang_data_new(xpath, timebuf); +	return time;  }  float yang_dnode_get_bandwidth_ieee_float32(const struct lyd_node *dnode, diff --git a/lib/yang_wrappers.h b/lib/yang_wrappers.h index 59b5b13acd..d3d841995b 100644 --- a/lib/yang_wrappers.h +++ b/lib/yang_wrappers.h @@ -7,6 +7,7 @@  #ifndef _FRR_NORTHBOUND_WRAPPERS_H_  #define _FRR_NORTHBOUND_WRAPPERS_H_ +#include <libyang/libyang.h>  #include "prefix.h"  #ifdef __cplusplus @@ -200,7 +201,14 @@ extern void yang_dnode_get_mac(struct ethaddr *mac, const struct lyd_node *dnode  /*data-and-time */  extern struct yang_data *yang_data_new_date_and_time(const char *xpath, -						     time_t time); +						     time_t time, +						     bool is_monotime); +struct timespec yang_dnode_get_date_and_timespec(const struct lyd_node *dnode, +						 const char *xpath_fmt, ...) +	PRINTFRR(2, 3); +time_t yang_dnode_get_date_and_time(const struct lyd_node *dnode, +				    const char *xpath_fmt, ...) +	PRINTFRR(2, 3);  /* rt-types:bandwidth-ieee-float32 */  extern float yang_dnode_get_bandwidth_ieee_float32(const struct lyd_node *dnode, diff --git a/mgmtd/mgmt_be_adapter.c b/mgmtd/mgmt_be_adapter.c index b311bf4698..830c410676 100644 --- a/mgmtd/mgmt_be_adapter.c +++ b/mgmtd/mgmt_be_adapter.c @@ -90,10 +90,12 @@ static const char *const ripd_config_xpaths[] = {  	"/frr-ripd:ripd",  	"/frr-route-map:lib",  	"/frr-vrf:lib", +	"/ietf-key-chain:key-chains",  	NULL,  };  static const char *const ripd_oper_xpaths[] = {  	"/frr-ripd:ripd", +	"/ietf-key-chain:key-chains",  	NULL,  };  #endif diff --git a/mgmtd/mgmt_main.c b/mgmtd/mgmt_main.c index cce16f51f6..e181d0da5e 100644 --- a/mgmtd/mgmt_main.c +++ b/mgmtd/mgmt_main.c @@ -10,6 +10,7 @@  #include "lib/version.h"  #include "routemap.h"  #include "filter.h" +#include "keychain.h"  #include "libfrr.h"  #include "frr_pthread.h"  #include "mgmtd/mgmt.h" @@ -185,6 +186,8 @@ static const struct frr_yang_module_info *const mgmt_yang_modules[] = {  	&frr_zebra_cli_info,  	&zebra_route_map_info, +	&ietf_key_chain_cli_info, +	&ietf_key_chain_deviation_info,  #ifdef HAVE_RIPD  	&frr_ripd_cli_info, @@ -199,20 +202,20 @@ static const struct frr_yang_module_info *const mgmt_yang_modules[] = {  /* clang-format off */  FRR_DAEMON_INFO(mgmtd, MGMTD, -	.vty_port = MGMTD_VTY_PORT, -	.proghelp = "FRR Management Daemon.", +		.vty_port = MGMTD_VTY_PORT, +		.proghelp = "FRR Management Daemon.", -	.signals = mgmt_signals, -	.n_signals = array_size(mgmt_signals), +		.signals = mgmt_signals, +		.n_signals = array_size(mgmt_signals), -	.privs = &mgmt_privs, +		.privs = &mgmt_privs, -	.yang_modules = mgmt_yang_modules, -	.n_yang_modules = array_size(mgmt_yang_modules), +		.yang_modules = mgmt_yang_modules, +		.n_yang_modules = array_size(mgmt_yang_modules), -	/* avoid libfrr trying to read our config file for us */ -	.flags = FRR_MANUAL_VTY_START | FRR_NO_SPLIT_CONFIG, -); +		/* avoid libfrr trying to read our config file for us */ +		.flags = FRR_MANUAL_VTY_START | FRR_NO_SPLIT_CONFIG, +	);  /* clang-format on */  #define DEPRECATED_OPTIONS "" diff --git a/mgmtd/mgmt_vty.c b/mgmtd/mgmt_vty.c index 12ea62ecef..0e5c06bf83 100644 --- a/mgmtd/mgmt_vty.c +++ b/mgmtd/mgmt_vty.c @@ -12,6 +12,7 @@  #include "command.h"  #include "filter.h"  #include "json.h" +#include "keychain.h"  #include "network.h"  #include "northbound_cli.h"  #include "routemap.h" @@ -600,6 +601,7 @@ void mgmt_vty_init(void)  	filter_cli_init();  	route_map_cli_init();  	affinity_map_init(); +	keychain_cli_init();  	/*  	 * Initialize command handling from VTYSH connection. diff --git a/ospf6d/ospf6_main.c b/ospf6d/ospf6_main.c index 17966e741e..0e8504c529 100644 --- a/ospf6d/ospf6_main.c +++ b/ospf6d/ospf6_main.c @@ -169,6 +169,8 @@ static const struct frr_yang_module_info *const ospf6d_yang_modules[] = {  	&frr_vrf_info,  	&frr_ospf_route_map_info,  	&frr_ospf6_route_map_info, +	&ietf_key_chain_info, +	&ietf_key_chain_deviation_info,  };  /* actual paths filled in main() */ @@ -182,19 +184,19 @@ static char *state_paths[] = {  /* clang-format off */  FRR_DAEMON_INFO(ospf6d, OSPF6, -	.vty_port = OSPF6_VTY_PORT, -	.proghelp = "Implementation of the OSPFv3 routing protocol.", +		.vty_port = OSPF6_VTY_PORT, +		.proghelp = "Implementation of the OSPFv3 routing protocol.", -	.signals = ospf6_signals, -	.n_signals = array_size(ospf6_signals), +		.signals = ospf6_signals, +		.n_signals = array_size(ospf6_signals), -	.privs = &ospf6d_privs, +		.privs = &ospf6d_privs, -	.yang_modules = ospf6d_yang_modules, -	.n_yang_modules = array_size(ospf6d_yang_modules), +		.yang_modules = ospf6d_yang_modules, +		.n_yang_modules = array_size(ospf6d_yang_modules), -	.state_paths = state_paths, -); +		.state_paths = state_paths, +	);  /* clang-format on */  /* Max wait time for config to load before accepting hellos */ diff --git a/ospfd/ospf_main.c b/ospfd/ospf_main.c index 6a4a9a1481..abad6c5b90 100644 --- a/ospfd/ospf_main.c +++ b/ospfd/ospf_main.c @@ -134,6 +134,8 @@ static const struct frr_yang_module_info *const ospfd_yang_modules[] = {  	&frr_route_map_info,  	&frr_vrf_info,  	&frr_ospf_route_map_info, +	&ietf_key_chain_info, +	&ietf_key_chain_deviation_info,  };  /* actual paths filled in main() */ diff --git a/python/xref2vtysh.py b/python/xref2vtysh.py index 91ccba64f0..177de757b0 100644 --- a/python/xref2vtysh.py +++ b/python/xref2vtysh.py @@ -36,7 +36,7 @@ daemon_flags = {      "lib/filter.c": "VTYSH_ACL_SHOW",      "lib/filter_cli.c": "VTYSH_ACL_CONFIG",      "lib/if.c": "VTYSH_INTERFACE", -    "lib/keychain.c": "VTYSH_KEYS", +    "lib/keychain_cli.c": "VTYSH_KEYS",      "lib/mgmt_be_client.c": "VTYSH_MGMT_BACKEND",      "lib/mgmt_fe_client.c": "VTYSH_MGMT_FRONTEND",      "lib/lib_vty.c": "VTYSH_ALL", diff --git a/ripd/rip_main.c b/ripd/rip_main.c index 845c5078a5..734e7ac4d9 100644 --- a/ripd/rip_main.c +++ b/ripd/rip_main.c @@ -131,6 +131,8 @@ static const struct frr_yang_module_info *const ripd_yang_modules[] = {  	&frr_ripd_info,  	&frr_route_map_info,  	&frr_vrf_info, +	&ietf_key_chain_info, +	&ietf_key_chain_deviation_info,  };  /* clang-format off */ @@ -189,7 +191,7 @@ int main(int argc, char **argv)  	/* Library initialization. */  	rip_error_init(); -	keychain_init(); +	keychain_init_new(true);  	rip_vrf_init();  	/* RIP related initialization. */ diff --git a/vtysh/vtysh.h b/vtysh/vtysh.h index 7758ceaea5..b35d56672a 100644 --- a/vtysh/vtysh.h +++ b/vtysh/vtysh.h @@ -75,7 +75,7 @@ extern struct event_loop *master;  		VTYSH_VRRPD | VTYSH_MGMTD  #define VTYSH_INTERFACE VTYSH_INTERFACE_SUBSET | VTYSH_BGPD  #define VTYSH_VRF	VTYSH_INTERFACE_SUBSET | VTYSH_BGPD -#define VTYSH_KEYS VTYSH_RIPD | VTYSH_EIGRPD | VTYSH_OSPF6D | VTYSH_OSPFD +#define VTYSH_KEYS VTYSH_MGMTD | VTYSH_EIGRPD | VTYSH_OSPF6D | VTYSH_OSPFD  /* Daemons who can process nexthop-group configs */  #define VTYSH_NH_GROUP    VTYSH_PBRD|VTYSH_SHARPD  #define VTYSH_SR          VTYSH_ZEBRA|VTYSH_PATHD diff --git a/zebra/zebra_nb_state.c b/zebra/zebra_nb_state.c index 00df9bfc55..e702080afd 100644 --- a/zebra/zebra_nb_state.c +++ b/zebra/zebra_nb_state.c @@ -548,7 +548,7 @@ struct yang_data *lib_vrf_zebra_ribs_rib_route_route_entry_uptime_get_elem(  {  	struct route_entry *re = (struct route_entry *)args->list_entry; -	return yang_data_new_date_and_time(args->xpath, re->uptime); +	return yang_data_new_date_and_time(args->xpath, re->uptime, true);  }  /*  | 
