]> git.puffer.fish Git - matthieu/frr.git/commitdiff
lib: add keychain northbound support
authorChristian Hopps <chopps@labn.net>
Sat, 24 Feb 2024 10:48:40 +0000 (05:48 -0500)
committerChristian Hopps <chopps@labn.net>
Tue, 5 Mar 2024 01:00:15 +0000 (20:00 -0500)
Signed-off-by: Christian Hopps <chopps@labn.net>
17 files changed:
eigrpd/eigrp_main.c
lib/keychain.c
lib/keychain.h
lib/keychain_cli.c [new file with mode: 0644]
lib/keychain_nb.c
lib/subdir.am
lib/yang_wrappers.c
lib/yang_wrappers.h
mgmtd/mgmt_be_adapter.c
mgmtd/mgmt_main.c
mgmtd/mgmt_vty.c
ospf6d/ospf6_main.c
ospfd/ospf_main.c
python/xref2vtysh.py
ripd/rip_main.c
vtysh/vtysh.h
zebra/zebra_nb_state.c

index 552ba7cd96a799cbc5b7187fcabf31a135fb1632..1491c569ec5984d52c23d1f141c69bad4b4a3f6c 100644 (file)
@@ -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 */
index 5ff0d1e43e9d7e5a6d188af6662a30fa6b70060d..1982220bc7e3a022d66901830b45e79fff2d1d7b 100644 (file)
@@ -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,
+               },
+       },
+};
index c96b74ecce19177be054f486b67717ab4221294d..dc35c2ea392eace7d5d57af455b4ae52c9cbddc2 100644 (file)
@@ -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 (file)
index 0000000..26f56f1
--- /dev/null
@@ -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);
+}
index 1a2853a9052d1f4523b97ce363d24576be4b8f8d..6838268a93919f74d86585b0606114ce627dad9a 100644 (file)
 // 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,
-               },
-       }
+       },
 };
index 6893049c7e567e313a0d8bfde3cee7386db0e698..db11def74197d304c8ce76437fae7e96e5c6f359 100644 (file)
@@ -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 \
index a0133954c328f7e244188502922fe9ba631abd1e..4e49a129c24c68cc34240645d18003788fa4d201 100644 (file)
@@ -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, &times);
+       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,
index 59b5b13acdd901e0bf4352ffd55ebb0804558692..d3d841995b209039e38e2fabcd146ded982d6396 100644 (file)
@@ -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,
index b311bf4698781f47c272a2f018e8d981f680651c..830c410676e7472dd3a8d1efbd5f3774b97f7c14 100644 (file)
@@ -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
index cce16f51f604cfb86f3a5c3e131f0f311360db4b..e181d0da5ef026a7c5b952f198a2894afa0ae820 100644 (file)
@@ -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 ""
index 12ea62eceff541e46496572cf6c8ef03ce365d74..0e5c06bf83455503579d2ac275020703b3064ddb 100644 (file)
@@ -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.
index 17966e741e37eef937e84905647d1350fbba80ac..0e8504c5298ff919b32c05fd85e7ff8484f64ef0 100644 (file)
@@ -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 */
index 6a4a9a148177c90946b6cf5dad2141c2dde268f3..abad6c5b902fbe59ba9cbb1a8a8c31b951c055cd 100644 (file)
@@ -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() */
index 91ccba64f0d07dbb2c5efc6c7a8faae5714fc487..177de757b04def886c9416378e1c6d51709a7233 100644 (file)
@@ -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",
index 845c5078a574764391d7b1069e3b4c38bd7f0ccc..734e7ac4d92619ead19015073b817ad78dc458ee 100644 (file)
@@ -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. */
index 7758ceaea502b99c264a55e853d9eccd1bfb6659..b35d56672a3ce473faaa39b779bc89fcc934dd9b 100644 (file)
@@ -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
index 00df9bfc55c57b600aa67b6037e81e458ae1ad95..e702080afde7eb7439d6e7de8e3aa6a76986d69f 100644 (file)
@@ -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);
 }
 
 /*