--- quagga-0.99.21/ospf6d/ospf6_interface.c 2012-03-24 01:13:19.000000000 +0530 +++ quagga-rfc6506/ospf6d/ospf6_interface.c 2013-07-29 15:31:01.172733514 +0530 @@ -29,6 +29,18 @@ #include "prefix.h" #include "plist.h" +#include "sockunion.h" +#include "network.h" +#include "table.h" +#include "stream.h" +#include "zclient.h" +#include "filter.h" +#include "sockopt.h" +#include "privs.h" +#include "cryptohash.h" + +#include "zebra/connected.h" + #include "ospf6_lsa.h" #include "ospf6_lsdb.h" #include "ospf6_network.h" @@ -41,6 +53,7 @@ #include "ospf6_intra.h" #include "ospf6_spf.h" #include "ospf6d.h" +#include "memtypes.h" unsigned char conf_debug_ospf6_interface = 0; @@ -141,6 +154,13 @@ ospf6_interface_create (struct interface oi->route_connected = OSPF6_ROUTE_TABLE_CREATE (INTERFACE, CONNECTED_ROUTES); oi->route_connected->scope = oi; + oi->auth_crypt = list_new (); + + oi->low_order_seqnum = time (NULL); + oi->high_order_seqnum = 0; + oi->auth_type = 0; + oi->hash_algo = 0; + /* link both */ oi->interface = ifp; ifp->info = oi; @@ -840,6 +860,50 @@ ospf6_interface_show (struct vty *vty, s return 0; } +struct ospf6_crypt_key * +ospf6_crypt_key_new () +{ + return XCALLOC (MTYPE_OSPF6_CRYPT_KEY, sizeof (struct ospf6_crypt_key)); +} + +void +ospf6_crypt_key_add (struct list *crypt, struct ospf6_crypt_key *ck) +{ + listnode_add (crypt, ck); +} + +struct ospf6_crypt_key * +ospf6_crypt_key_lookup (struct list *auth_crypt, u_char key_id) +{ + struct listnode *node; + struct ospf6_crypt_key *ck; + + for (ALL_LIST_ELEMENTS_RO (auth_crypt, node, ck)) + if (ck->key_id == key_id) + return ck; + + return NULL; +} + +int +ospf6_crypt_key_delete (struct list *auth_crypt, u_char key_id) +{ + struct listnode *node, *nnode; + struct ospf6_crypt_key *ck; + + for (ALL_LIST_ELEMENTS (auth_crypt, node, nnode, ck)) + { + if (ck->key_id == key_id) + { + listnode_delete (auth_crypt, ck); + XFREE (MTYPE_OSPF6_CRYPT_KEY, ck); + return 1; + } + } + + return 0; +} + /* show interface */ DEFUN (show_ipv6_ospf6_interface, show_ipv6_ospf6_interface_ifname_cmd, @@ -1504,10 +1568,187 @@ DEFUN (no_ipv6_ospf6_advertise_prefix_li return CMD_SUCCESS; } +DEFUN (ipv6_ospf6_sha_authentication_mode, + ipv6_ospf6_sha_authentication_mode_cmd, + "ipv6 ospf6 authentication-mode (sha1|sha256|sha384|sha512|default)", + IP_STR + "IPv6 Information\n" + "OSPF6 interface commands\n" + "Authentication mode\n" + "HMAC-SHA-1 authentication\n" + "HMAC-SHA-256 authentication\n" + "HMAC-SHA-384 authentication\n" + "HMAC-SHA-512 authentication\n" + "Enable SHA algorithm for authentication\n" + ) +{ + struct ospf6_interface *oi; + struct interface *ifp; + unsigned hash_algo; + struct ospf6_crypt_key *ck; + struct listnode *node, *nnode; + struct list *auth_crypt; + u_char key_id; + + ifp = (struct interface *)vty->index; + assert (ifp); + + oi = (struct ospf6_interface *)ifp->info; + if (oi == NULL) + oi = ospf6_interface_create (ifp); + assert (oi); + + /* As per RFC-6506, default sha algorithm is sha-256 */ + if(strcmp(argv[0],"default")==0) + hash_algo = hash_algo_byname ("sha256"); + else + hash_algo = hash_algo_byname (argv[0]); + + if (! hash_algo_enabled (hash_algo)) + { + vty_out (vty, "Algorithm '%s' is not enabled in this build%s", argv[0], VTY_NEWLINE); + return CMD_ERR_NO_MATCH; + } + + /*If hash algorithm is changed, the key attached with previous algorithm is deleted and the user will have to re-enter the key*/ + if(oi->auth_crypt!=NULL) + { + for (ALL_LIST_ELEMENTS (oi->auth_crypt, node, nnode, ck)) + { + listnode_delete (oi->auth_crypt, ck); + XFREE (MTYPE_OSPF6_CRYPT_KEY, ck); + } + } + + oi->auth_type = OSPF6_AUTH_CRYPTOGRAPHIC; + oi->hash_algo = hash_algo; + return CMD_SUCCESS; +} + +DEFUN (no_ipv6_ospf6_sha_authentication_mode, + no_ipv6_ospf6_sha_authentication_mode_cmd, + "no ipv6 ospf6 authentication-mode", + NO_STR + "IPv6 Information\n" + "OSPF6 interface commands\n" + "Disable SHA algorithm for authentication\n" + ) +{ + struct ospf6_interface *oi; + struct interface *ifp; + + ifp = (struct interface *) vty->index; + assert (ifp); + + oi = (struct ospf6_interface *) ifp->info; + if (oi == NULL) + oi = ospf6_interface_create (ifp); + assert (oi); + + oi->auth_type = OSPF6_AUTH_NULL ; + return CMD_SUCCESS; +} + +DEFUN (ipv6_ospf6_sha_key, + ipv6_ospf6_sha_key_cmd, + "ipv6 ospf6 sha-key <1-255> sha KEY", + "IPv6 Information\n" + "OSPF6 interface commands\n" + "SHA-algorithm authentication key-ID\n" + "Key ID\n" + "Enable SHA algorithm\n" + "The authentication password (key)" + ) +{ + struct ospf6_interface *oi; + struct interface *ifp; + struct ospf6_crypt_key *ck; + u_char key_id; + + ifp = (struct interface *)vty->index; + assert (ifp); + + oi = (struct ospf6_interface *)ifp->info; + if (oi == NULL) + oi = ospf6_interface_create (ifp); + assert (oi); + + if (oi->hash_algo==0) + { + vty_out (vty, "Please specify authentication mode first%s", VTY_NEWLINE); + return CMD_WARNING; + } + + key_id = strtol (argv[0], NULL, 10); + if (ospf6_crypt_key_lookup (oi->auth_crypt, key_id)!= NULL) + { + vty_out (vty, "OSPF6: Key %d already exists%s", key_id, VTY_NEWLINE); + return CMD_WARNING; + } + + ck = ospf6_crypt_key_new (); + ck->key_id = (u_char) key_id; + memset (ck->auth_key, 0, hash_digest_length[oi->hash_algo]); + strncpy ((char *) ck->auth_key, argv[1], hash_digest_length[oi->hash_algo]); + + ospf6_crypt_key_add (oi->auth_crypt, ck); + + return CMD_SUCCESS; +} + +DEFUN (no_ipv6_ospf6_sha_key, + no_ipv6_ospf6_sha_key_cmd, + "no ipv6 ospf6 sha-key <1-255>", + NO_STR + "IPv6 Information\n" + "OSPF6 interface commands\n" + "Disable SHA authentication password (key)\n" + "Key ID\n" + ) + +{ + struct ospf6_interface *oi; + struct interface *ifp; + u_char key_id; + + ifp = (struct interface *) vty->index; + assert (ifp); + + oi = (struct ospf6_interface *) ifp->info; + if (oi == NULL) + oi = ospf6_interface_create (ifp); + assert (oi); + + key_id = strtol (argv[0], NULL, 10); + if (ospf6_crypt_key_lookup (oi->auth_crypt, key_id)== NULL) + { + vty_out (vty, "OSPF6: Key %d does not exist%s", key_id, VTY_NEWLINE); + return CMD_WARNING; + } + + ospf6_crypt_key_delete (oi->auth_crypt, key_id); + + return CMD_SUCCESS; +} + +ALIAS ( no_ipv6_ospf6_sha_authentication_mode, + no_ipv6_ospf6_sha_authentication_mode_type_cmd, + "no ipv6 ospf6 authentication-mode (sha1|sha256|sha384|sha512)", + NO_STR + IP_STR + "IPv6 Information\n" + "OSPF6 interface commands\n" + "Disable SHA algorithm for authentication\n" + "HMAC-SHA-1 authentication\n" + "HMAC-SHA-256 authentication\n" + "HMAC-SHA-384 authentication\n" + "HMAC-SHA-512 authentication\n" ) + static int config_write_ospf6_interface (struct vty *vty) { - struct listnode *i; + struct listnode *i,*n1; + struct ospf6_crypt_key *ck; struct ospf6_interface *oi; struct interface *ifp; @@ -1563,6 +1804,16 @@ config_write_ospf6_interface (struct vty if (oi->mtu_ignore) vty_out (vty, " ipv6 ospf6 mtu-ignore%s", VNL); + for (ALL_LIST_ELEMENTS_RO (oi->auth_crypt, n1, ck)) + { + vty_out (vty, " ipv6 ospf6 sha-key %d sha %s%s", + ck->key_id, ck->auth_key, VNL); + } + + if (oi->auth_type) + vty_out (vty, " ipv6 ospf6 authentication-mode %s %s", LOOKUP (hash_algo_cli_str, oi->hash_algo), VNL); + + vty_out (vty, "!%s", VNL); } return 0; @@ -1620,6 +1871,13 @@ ospf6_interface_init (void) install_element (INTERFACE_NODE, &ipv6_ospf6_advertise_prefix_list_cmd); install_element (INTERFACE_NODE, &no_ipv6_ospf6_advertise_prefix_list_cmd); + + install_element (INTERFACE_NODE, &ipv6_ospf6_sha_key_cmd); + install_element (INTERFACE_NODE, &no_ipv6_ospf6_sha_key_cmd); + + install_element (INTERFACE_NODE, &ipv6_ospf6_sha_authentication_mode_cmd); + install_element (INTERFACE_NODE, &no_ipv6_ospf6_sha_authentication_mode_cmd); + install_element (INTERFACE_NODE, &no_ipv6_ospf6_sha_authentication_mode_type_cmd); } DEFUN (debug_ospf6_interface, --- quagga-0.99.21/ospf6d/ospf6_proto.h 2012-03-24 01:13:20.000000000 +0530 +++ quagga-rfc6506/ospf6d/ospf6_proto.h 2013-07-10 10:16:00.000000000 +0530 @@ -60,6 +60,12 @@ /* OSPF options */ /* present in HELLO, DD, LSA */ +#define OSPF6_OPT_SET_AT(x,opt) ((x)[1] |= (opt)) +#define OSPF6_OPT_ISSET_AT(x,opt) ((x)[1] & (opt)) +#define OSPF6_OPT_CLEAR_AT(x,opt) ((x)[1] &= ~(opt)) + +/* OSPF options */ +/* present in HELLO, DD, LSA */ #define OSPF6_OPT_SET(x,opt) ((x)[2] |= (opt)) #define OSPF6_OPT_ISSET(x,opt) ((x)[2] & (opt)) #define OSPF6_OPT_CLEAR(x,opt) ((x)[2] &= ~(opt)) @@ -72,6 +78,8 @@ #define OSPF6_OPT_E (1 << 1) /* AS External Capability */ #define OSPF6_OPT_V6 (1 << 0) /* IPv6 forwarding Capability */ +#define OSPF6_OPT_AT (1 << 2) /* Authentication Capability */ + /* OSPF6 Prefix */ #define OSPF6_PREFIX_MIN_SIZE 4U /* .length == 0 */ struct ospf6_prefix --- quagga-0.99.21/ospf6d/ospf6_proto.c 2012-03-24 01:13:20.000000000 +0530 +++ quagga-rfc6506/ospf6d/ospf6_proto.c 2013-07-10 10:16:00.000000000 +0530 @@ -71,14 +71,17 @@ ospf6_capability_printbuf (char capabili void ospf6_options_printbuf (u_char *options, char *buf, int size) { - const char *dc, *r, *n, *mc, *e, *v6; + const char *dc, *r, *n, *mc, *e, *v6, *at; + dc = (OSPF6_OPT_ISSET (options, OSPF6_OPT_DC) ? "DC" : "--"); r = (OSPF6_OPT_ISSET (options, OSPF6_OPT_R) ? "R" : "-" ); n = (OSPF6_OPT_ISSET (options, OSPF6_OPT_N) ? "N" : "-" ); mc = (OSPF6_OPT_ISSET (options, OSPF6_OPT_MC) ? "MC" : "--"); e = (OSPF6_OPT_ISSET (options, OSPF6_OPT_E) ? "E" : "-" ); v6 = (OSPF6_OPT_ISSET (options, OSPF6_OPT_V6) ? "V6" : "--"); - snprintf (buf, size, "%s|%s|%s|%s|%s|%s", dc, r, n, mc, e, v6); -} + at = (OSPF6_OPT_ISSET_AT (options, OSPF6_OPT_AT) ? "AT" : "--"); + snprintf (buf, size, "|%s|-|--|--|--|%s|%s|%s|%s|%s|%s", at, dc, r, n, mc, e, v6); + +}