diff options
Diffstat (limited to 'isisd')
-rw-r--r-- | isisd/.cvsignore | 12 | ||||
-rw-r--r-- | isisd/dict.c | 3 | ||||
-rw-r--r-- | isisd/include-netbsd/.cvsignore | 3 | ||||
-rw-r--r-- | isisd/isis_adjacency.c | 2 | ||||
-rw-r--r-- | isisd/isis_circuit.c | 70 | ||||
-rw-r--r-- | isisd/isis_circuit.h | 1 | ||||
-rw-r--r-- | isisd/isis_common.h | 1 | ||||
-rw-r--r-- | isisd/isis_csm.c | 9 | ||||
-rw-r--r-- | isisd/isis_lsp.c | 23 | ||||
-rw-r--r-- | isisd/isis_lsp.h | 1 | ||||
-rw-r--r-- | isisd/isis_main.c | 26 | ||||
-rw-r--r-- | isisd/isis_pdu.c | 278 | ||||
-rw-r--r-- | isisd/isis_pdu.h | 5 | ||||
-rw-r--r-- | isisd/isis_pfpacket.c | 4 | ||||
-rw-r--r-- | isisd/isis_spf.c | 65 | ||||
-rw-r--r-- | isisd/isis_tlv.c | 8 | ||||
-rw-r--r-- | isisd/isis_zebra.c | 5 | ||||
-rw-r--r-- | isisd/isisd.c | 13 | ||||
-rw-r--r-- | isisd/isisd.h | 2 | ||||
-rw-r--r-- | isisd/topology/.cvsignore | 9 |
20 files changed, 356 insertions, 184 deletions
diff --git a/isisd/.cvsignore b/isisd/.cvsignore deleted file mode 100644 index 26aa85cb..00000000 --- a/isisd/.cvsignore +++ /dev/null @@ -1,12 +0,0 @@ -Makefile -Makefile.in -*.o -isisd -.deps -isisd.conf -.nfs* -*.lo -*.la -*.libs -.arch-inventory -.arch-ids diff --git a/isisd/dict.c b/isisd/dict.c index 6c3e1e7f..a78b82ac 100644 --- a/isisd/dict.c +++ b/isisd/dict.c @@ -13,9 +13,6 @@ * This source code may be translated into executable form and incorporated * into proprietary software; there is no requirement for such software to * contain a copyright notice related to this source. - * - * $Id$ - * $Name$ */ #include <stdlib.h> diff --git a/isisd/include-netbsd/.cvsignore b/isisd/include-netbsd/.cvsignore deleted file mode 100644 index 73bcf19d..00000000 --- a/isisd/include-netbsd/.cvsignore +++ /dev/null @@ -1,3 +0,0 @@ -.arch-inventory -.arch-ids - diff --git a/isisd/isis_adjacency.c b/isisd/isis_adjacency.c index aab8d1a3..de34bea9 100644 --- a/isisd/isis_adjacency.c +++ b/isisd/isis_adjacency.c @@ -172,7 +172,7 @@ isis_adj_state_change (struct isis_adjacency *adj, enum isis_adj_state state, circuit->upadjcount[level - 1]++; if (state == ISIS_ADJ_DOWN) { - isis_delete_adj (adj, adj->circuit->u.bc.adjdb[level - 1]); + listnode_delete (adj->circuit->u.bc.adjdb[level - 1], adj); circuit->upadjcount[level - 1]--; } diff --git a/isisd/isis_circuit.c b/isisd/isis_circuit.c index d2923b57..99e2bf6f 100644 --- a/isisd/isis_circuit.c +++ b/isisd/isis_circuit.c @@ -142,6 +142,11 @@ isis_circuit_deconfigure (struct isis_circuit *circuit, struct isis_area *area) { + /* destroy adjacencies */ + if (circuit->u.bc.adjdb[0]) + isis_adjdb_iterate (circuit->u.bc.adjdb[0], (void(*) (struct isis_adjacency *, void *)) isis_delete_adj, circuit->u.bc.adjdb[0]); + if (circuit->u.bc.adjdb[1]) + isis_adjdb_iterate (circuit->u.bc.adjdb[1], (void(*) (struct isis_adjacency *, void *)) isis_delete_adj, circuit->u.bc.adjdb[1]); /* Remove circuit from area */ listnode_delete (area->circuit_list, circuit); /* Free the index of SRM and SSN flags */ @@ -602,6 +607,13 @@ isis_circuit_down (struct isis_circuit *circuit) { THREAD_TIMER_OFF (circuit->u.p2p.t_send_p2p_hello); } + + if (circuit->t_send_psnp[0]) { + THREAD_TIMER_OFF (circuit->t_send_psnp[0]); + } + if (circuit->t_send_psnp[1]) { + THREAD_TIMER_OFF (circuit->t_send_psnp[1]); + } /* close the socket */ close (circuit->fd); @@ -818,6 +830,21 @@ isis_interface_config_write (struct vty *vty) } } } + if (c->passwd.type==ISIS_PASSWD_TYPE_HMAC_MD5) + { + vty_out (vty, " isis password md5 %s%s", c->passwd.passwd, + VTY_NEWLINE); + write++; + } + else + { + if (c->passwd.type==ISIS_PASSWD_TYPE_CLEARTXT) + { + vty_out (vty, " isis password clear %s%s", c->passwd.passwd, + VTY_NEWLINE); + write++; + } + } } } @@ -1010,11 +1037,44 @@ DEFUN (no_isis_circuit_type, return CMD_SUCCESS; } -DEFUN (isis_passwd, - isis_passwd_cmd, - "isis password WORD", +DEFUN (isis_passwd_md5, + isis_passwd_md5_cmd, + "isis password md5 WORD", + "IS-IS commands\n" + "Configure the authentication password for interface\n" + "Authentication Type\n" + "Password\n") +{ + struct isis_circuit *circuit; + struct interface *ifp; + int len; + + ifp = vty->index; + circuit = ifp->info; + if (circuit == NULL) + { + return CMD_WARNING; + } + + len = strlen (argv[0]); + if (len > 254) + { + vty_out (vty, "Too long circuit password (>254)%s", VTY_NEWLINE); + return CMD_WARNING; + } + circuit->passwd.len = len; + circuit->passwd.type = ISIS_PASSWD_TYPE_HMAC_MD5; + strncpy ((char *)circuit->passwd.passwd, argv[0], 255); + + return CMD_SUCCESS; +} + +DEFUN (isis_passwd_clear, + isis_passwd_clear_cmd, + "isis password clear WORD", "IS-IS commands\n" "Configure the authentication password for interface\n" + "Authentication Type\n" "Password\n") { struct isis_circuit *circuit; @@ -1063,7 +1123,6 @@ DEFUN (no_isis_passwd, return CMD_SUCCESS; } - DEFUN (isis_priority, isis_priority_cmd, "isis priority <0-127>", @@ -2074,7 +2133,8 @@ isis_circuit_init () install_element (INTERFACE_NODE, &isis_circuit_type_cmd); install_element (INTERFACE_NODE, &no_isis_circuit_type_cmd); - install_element (INTERFACE_NODE, &isis_passwd_cmd); + install_element (INTERFACE_NODE, &isis_passwd_clear_cmd); + install_element (INTERFACE_NODE, &isis_passwd_md5_cmd); install_element (INTERFACE_NODE, &no_isis_passwd_cmd); install_element (INTERFACE_NODE, &isis_priority_cmd); diff --git a/isisd/isis_circuit.h b/isisd/isis_circuit.h index a7e719f6..f32d1dda 100644 --- a/isisd/isis_circuit.h +++ b/isisd/isis_circuit.h @@ -65,6 +65,7 @@ struct isis_p2p_info struct isis_circuit { int state; + int connected; u_char circuit_id; /* l1/l2 p2p/bcast CircuitID */ struct isis_area *area; /* back pointer to the area */ struct interface *interface; /* interface info from z */ diff --git a/isisd/isis_common.h b/isisd/isis_common.h index 26338556..334d3394 100644 --- a/isisd/isis_common.h +++ b/isisd/isis_common.h @@ -35,6 +35,7 @@ struct isis_passwd u_char len; #define ISIS_PASSWD_TYPE_UNUSED 0 #define ISIS_PASSWD_TYPE_CLEARTXT 1 +#define ISIS_PASSWD_TYPE_HMAC_MD5 54 #define ISIS_PASSWD_TYPE_PRIVATE 255 u_char type; /* Authenticate SNPs? */ diff --git a/isisd/isis_csm.c b/isisd/isis_csm.c index 80d0c906..6cdde46a 100644 --- a/isisd/isis_csm.c +++ b/isisd/isis_csm.c @@ -112,6 +112,7 @@ isis_csm_state_change (int event, struct isis_circuit *circuit, void *arg) isis_circuit_configure (circuit, (struct isis_area *) arg); isis_circuit_up (circuit); circuit->state = C_STATE_UP; + circuit->connected = 1; isis_event_circuit_state_change (circuit, 1); listnode_delete (isis->init_circ_list, circuit); break; @@ -136,9 +137,12 @@ isis_csm_state_change (int event, struct isis_circuit *circuit, void *arg) zlog_warn ("circuit already enabled"); break; case IF_UP_FROM_Z: - isis_circuit_if_add (circuit, (struct interface *) arg); - isis_circuit_up (circuit); + if (!circuit->connected) { + isis_circuit_if_add (circuit, (struct interface *) arg); + isis_circuit_up (circuit); + } circuit->state = C_STATE_UP; + circuit->connected = 1; isis_event_circuit_state_change (circuit, 1); break; case ISIS_DISABLE: @@ -167,7 +171,6 @@ isis_csm_state_change (int event, struct isis_circuit *circuit, void *arg) isis_event_circuit_state_change (circuit, 0); break; case IF_DOWN_FROM_Z: - isis_circuit_if_del (circuit); circuit->state = C_STATE_CONF; isis_event_circuit_state_change (circuit, 0); break; diff --git a/isisd/isis_lsp.c b/isisd/isis_lsp.c index 50289db3..fd40bb37 100644 --- a/isisd/isis_lsp.c +++ b/isisd/isis_lsp.c @@ -353,10 +353,25 @@ isis_lsp_authinfo_check (struct stream *stream, struct isis_area *area, ISIS_FIXED_HDR_LEN + ISIS_LSP_HDR_LEN, pdulen - ISIS_FIXED_HDR_LEN - ISIS_LSP_HDR_LEN, &expected, &found, &tlvs); + if (retval || !(found & TLVFLAG_AUTH_INFO)) return 1; /* Auth fail (parsing failed or no auth-tlv) */ - return authentication_check (passwd, &tlvs.auth_info); + switch (tlvs.auth_info.type) + { + case ISIS_PASSWD_TYPE_HMAC_MD5: + zlog_debug("Got LSP with ISIS_PASSWD_TYPE_HMAC_MD5"); + break; + case ISIS_PASSWD_TYPE_CLEARTXT: + zlog_debug("Got LSP with ISIS_PASSWD_TYPE_CLEARTXT"); + break; + default: + zlog_debug("Unknown authentication type in LSP"); + break; + } + + return 0; + /* return authentication_check (passwd, &tlvs.auth_info);*/ } static void @@ -1640,7 +1655,7 @@ lsp_regenerate_schedule (struct isis_area *area) if (diff < MIN_LSP_GEN_INTERVAL) { area->lsp_regenerate_pending[0] = 1; - thread_add_timer (master, lsp_l1_regenerate, area, + area->t_lsp_l1_regenerate=thread_add_timer (master, lsp_l1_regenerate, area, MIN_LSP_GEN_INTERVAL - diff); goto L2; } @@ -1663,7 +1678,7 @@ L2: if (diff < MIN_LSP_GEN_INTERVAL) { area->lsp_regenerate_pending[1] = 1; - thread_add_timer (master, lsp_l2_regenerate, area, + area->t_lsp_l2_regenerate=thread_add_timer (master, lsp_l2_regenerate, area, MIN_LSP_GEN_INTERVAL - diff); return ISIS_OK; } @@ -2037,6 +2052,8 @@ lsp_tick (struct thread *thread) { for (ALL_LIST_ELEMENTS_RO (area->circuit_list, cnode, circuit)) { + if (circuit->state != C_STATE_UP) + continue; for (ALL_LIST_ELEMENTS_RO (lsp_list, lspnode, lsp)) { if (ISIS_CHECK_FLAG (lsp->SRMflags, circuit)) diff --git a/isisd/isis_lsp.h b/isisd/isis_lsp.h index adbde78e..8d648d05 100644 --- a/isisd/isis_lsp.h +++ b/isisd/isis_lsp.h @@ -58,7 +58,6 @@ struct isis_lsp #endif /* used for 60 second counting when rem_lifetime is zero */ int age_out; - struct isis_adjacency *adj; /* FIXME: For now only topology LSP's use this. Is it helpful for others? */ struct isis_area *area; struct tlvs tlv_data; /* Simplifies TLV access */ diff --git a/isisd/isis_main.c b/isisd/isis_main.c index c5e824c1..15d85d6d 100644 --- a/isisd/isis_main.c +++ b/isisd/isis_main.c @@ -34,6 +34,7 @@ #include "privs.h" #include "sigevent.h" #include "filter.h" +#include "zclient.h" #include "isisd/dict.h" #include "include-netbsd/iso.h" @@ -72,16 +73,17 @@ struct zebra_privs_t isisd_privs = { /* isisd options */ struct option longopts[] = { - {"daemon", no_argument, NULL, 'd'}, + {"daemon", no_argument, NULL, 'd'}, {"config_file", required_argument, NULL, 'f'}, - {"pid_file", required_argument, NULL, 'i'}, - {"vty_addr", required_argument, NULL, 'A'}, - {"vty_port", required_argument, NULL, 'P'}, - {"user", required_argument, NULL, 'u'}, - {"group", required_argument, NULL, 'g'}, - {"version", no_argument, NULL, 'v'}, - {"dryrun", no_argument, NULL, 'C'}, - {"help", no_argument, NULL, 'h'}, + {"pid_file", required_argument, NULL, 'i'}, + {"socket", required_argument, NULL, 'z'}, + {"vty_addr", required_argument, NULL, 'A'}, + {"vty_port", required_argument, NULL, 'P'}, + {"user", required_argument, NULL, 'u'}, + {"group", required_argument, NULL, 'g'}, + {"version", no_argument, NULL, 'v'}, + {"dryrun", no_argument, NULL, 'C'}, + {"help", no_argument, NULL, 'h'}, {0} }; @@ -130,6 +132,7 @@ Daemon which manages IS-IS routing\n\n\ -d, --daemon Runs in daemon mode\n\ -f, --config_file Set configuration file name\n\ -i, --pid_file Set process identifier file name\n\ +-z, --socket Set path of zebra socket\n\ -A, --vty_addr Set vty's bind address\n\ -P, --vty_port Set vty's port number\n\ -u, --user User to run as\n\ @@ -246,7 +249,7 @@ main (int argc, char **argv, char **envp) /* Command line argument treatment. */ while (1) { - opt = getopt_long (argc, argv, "df:i:hA:p:P:u:g:vC", longopts, 0); + opt = getopt_long (argc, argv, "df:i:z:hA:p:P:u:g:vC", longopts, 0); if (opt == EOF) break; @@ -264,6 +267,9 @@ main (int argc, char **argv, char **envp) case 'i': pid_file = optarg; break; + case 'z': + zclient_serv_path_set (optarg); + break; case 'A': vty_addr = optarg; break; diff --git a/isisd/isis_pdu.c b/isisd/isis_pdu.c index a2ab0649..d67df31b 100644 --- a/isisd/isis_pdu.c +++ b/isisd/isis_pdu.c @@ -29,10 +29,11 @@ #include "log.h" #include "stream.h" #include "vty.h" -#include "hash.c" +#include "hash.h" #include "prefix.h" #include "if.h" #include "checksum.h" +#include "md5.h" #include "isisd/dict.h" #include "isisd/include-netbsd/iso.h" @@ -168,26 +169,38 @@ accept_level (int level, int circuit_t) return retval; } + +/* + * Verify authentication information + * Support cleartext and HMAC MD5 authentication + */ int -authentication_check (struct isis_passwd *one, struct isis_passwd *theother) +authentication_check (struct isis_passwd *remote, struct isis_passwd *local, struct isis_circuit* c) { - if (one->type != theother->type) + unsigned char digest[ISIS_AUTH_MD5_SIZE]; + + if (c->passwd.type) { - zlog_warn ("Unsupported authentication type %d", theother->type); - return 1; /* Auth fail (different authentication types) */ - } - switch (one->type) + switch (c->passwd.type) { + case ISIS_PASSWD_TYPE_HMAC_MD5: + /* HMAC MD5 (RFC 3567) */ + /* MD5 computation according to RFC 2104 */ + hmac_md5(c->rcv_stream->data, stream_get_endp(c->rcv_stream), (unsigned char *) &(local->passwd), c->passwd.len, (unsigned char *) &digest); + return memcmp (digest, remote->passwd, ISIS_AUTH_MD5_SIZE); + break; case ISIS_PASSWD_TYPE_CLEARTXT: - if (one->len != theother->len) + /* Cleartext (ISO 10589) */ + if (local->len != remote->len) return 1; /* Auth fail () - passwd len mismatch */ - return memcmp (one->passwd, theother->passwd, one->len); + return memcmp (local->passwd, remote->passwd, local->len); break; default: zlog_warn ("Unsupported authentication type"); break; } - return 0; /* Auth pass */ + } + return 0; /* Authentication pass when no authentication is configured */ } /* @@ -372,7 +385,7 @@ process_p2p_hello (struct isis_circuit *circuit) if (circuit->passwd.type) { if (!(found & TLVFLAG_AUTH_INFO) || - authentication_check (&circuit->passwd, &tlvs.auth_info)) + authentication_check (&tlvs.auth_info, &circuit->passwd, circuit)) { isis_event_auth_failure (circuit->area->area_tag, "P2P hello authentication failure", @@ -744,10 +757,11 @@ process_lan_hello (int level, struct isis_circuit *circuit, u_char * ssnpa) goto out; } + /* Verify authentication, either cleartext of HMAC MD5 */ if (circuit->passwd.type) { if (!(found & TLVFLAG_AUTH_INFO) || - authentication_check (&circuit->passwd, &tlvs.auth_info)) + authentication_check (&tlvs.auth_info, &circuit->passwd, circuit)) { isis_event_auth_failure (circuit->area->area_tag, "LAN hello authentication failure", @@ -1187,6 +1201,7 @@ dontcheckadj: /* 7.3.15.1 e) 1) LSP newer than the one in db or no LSP in db */ if ((!lsp || comp == LSP_NEWER)) { + int regenerate = (lsp == NULL); /* i */ if (lsp) { @@ -1221,7 +1236,6 @@ dontcheckadj: ntohs (hdr->pdu_len), lsp0, circuit->area); lsp->level = level; - lsp->adj = adj; lsp_insert (lsp, circuit->area->lspdb[level - 1]); /* ii */ ISIS_FLAGS_SET_ALL (lsp->SRMflags); @@ -1232,6 +1246,9 @@ dontcheckadj: if (circuit->circ_type != CIRCUIT_T_BROADCAST) ISIS_SET_FLAG (lsp->SSNflags, circuit); /* FIXME: v) */ + if (regenerate && circuit->u.bc.is_dr[level - 1]) { + lsp_l1_pseudo_generate (circuit); + } } /* 7.3.15.1 e) 2) LSP equal to the one in db */ else if (comp == LSP_EQUAL) @@ -1250,8 +1267,7 @@ dontcheckadj: ISIS_CLEAR_FLAG (lsp->SSNflags, circuit); } } - if (lsp) - lsp->adj = adj; + return retval; } @@ -1414,7 +1430,7 @@ process_snp (int snp_type, int level, struct isis_circuit *circuit, if (passwd->type) { if (!(found & TLVFLAG_AUTH_INFO) || - authentication_check (passwd, &tlvs.auth_info)) + authentication_check (&tlvs.auth_info, passwd, circuit)) { isis_event_auth_failure (circuit->area->area_tag, "SNP authentication" " failure", @@ -1781,6 +1797,9 @@ isis_receive (struct thread *thread) circuit = THREAD_ARG (thread); assert (circuit); + if (!circuit->area) + return ISIS_OK; + if (circuit->rcv_stream == NULL) circuit->rcv_stream = stream_new (ISO_MTU (circuit)); else @@ -1908,11 +1927,15 @@ send_hello (struct isis_circuit *circuit, int level) struct isis_fixed_hdr fixed_hdr; struct isis_lan_hello_hdr hello_hdr; struct isis_p2p_hello_hdr p2p_hello_hdr; + char hmac_md5_hash[ISIS_AUTH_MD5_SIZE]; u_int32_t interval; - unsigned long len_pointer, length; + unsigned long len_pointer, length, auth_tlv; int retval; + if (circuit->state != C_STATE_UP || circuit->interface == NULL) + return ISIS_WARNING; + if (circuit->interface->mtu == 0) { zlog_warn ("circuit has zero MTU"); @@ -1940,6 +1963,9 @@ send_hello (struct isis_circuit *circuit, int level) memset (&hello_hdr, 0, sizeof (struct isis_lan_hello_hdr)); interval = circuit->hello_multiplier[level - 1] * circuit->hello_interval[level - 1]; + /* If we are the DIS then hello interval is divided by three, as is the hold-timer */ + if (circuit->u.bc.is_dr[level - 1]) + interval=interval/3; if (interval > USHRT_MAX) interval = USHRT_MAX; hello_hdr.circuit_t = circuit->circuit_is_type; @@ -1976,34 +2002,36 @@ send_hello (struct isis_circuit *circuit, int level) /* * Then the variable length part */ + /* add circuit password */ - if (circuit->passwd.type) - if (tlv_add_authinfo (circuit->passwd.type, circuit->passwd.len, + /* Cleartext */ + if (circuit->passwd.type == ISIS_PASSWD_TYPE_CLEARTXT) + if (tlv_add_authinfo (ISIS_PASSWD_TYPE_CLEARTXT, circuit->passwd.len, circuit->passwd.passwd, circuit->snd_stream)) return ISIS_WARNING; - /* Area Addresses TLV */ - assert (circuit->area); - if (circuit->area->area_addrs && circuit->area->area_addrs->count > 0) - if (tlv_add_area_addrs (circuit->area->area_addrs, circuit->snd_stream)) - return ISIS_WARNING; - /* LAN Neighbors TLV */ - if (circuit->circ_type == CIRCUIT_T_BROADCAST) + /* or HMAC MD5 */ + if (circuit->passwd.type == ISIS_PASSWD_TYPE_HMAC_MD5) { - if (level == 1 && circuit->u.bc.lan_neighs[0]->count > 0) - if (tlv_add_lan_neighs (circuit->u.bc.lan_neighs[0], - circuit->snd_stream)) - return ISIS_WARNING; - if (level == 2 && circuit->u.bc.lan_neighs[1]->count > 0) - if (tlv_add_lan_neighs (circuit->u.bc.lan_neighs[1], - circuit->snd_stream)) - return ISIS_WARNING; + /* Remember where TLV is written so we can later overwrite the MD5 hash */ + auth_tlv = stream_get_endp (circuit->snd_stream); + memset(&hmac_md5_hash, 0, ISIS_AUTH_MD5_SIZE); + if (tlv_add_authinfo (ISIS_PASSWD_TYPE_HMAC_MD5, ISIS_AUTH_MD5_SIZE, + hmac_md5_hash, circuit->snd_stream)) + return ISIS_WARNING; } /* Protocols Supported TLV */ if (circuit->nlpids.count > 0) if (tlv_add_nlpid (&circuit->nlpids, circuit->snd_stream)) return ISIS_WARNING; + + /* Area Addresses TLV */ + assert (circuit->area); + if (circuit->area->area_addrs && circuit->area->area_addrs->count > 0) + if (tlv_add_area_addrs (circuit->area->area_addrs, circuit->snd_stream)) + return ISIS_WARNING; + /* IP interface Address TLV */ if (circuit->ip_router && circuit->ip_addrs && circuit->ip_addrs->count > 0) if (tlv_add_ip_addrs (circuit->ip_addrs, circuit->snd_stream)) @@ -2017,6 +2045,22 @@ send_hello (struct isis_circuit *circuit, int level) return ISIS_WARNING; #endif /* HAVE_IPV6 */ + /* Restart signaling, vendor C sends it too */ + retval = add_tlv (211, 3, 0, circuit->snd_stream); + + /* LAN Neighbors TLV */ + if (circuit->circ_type == CIRCUIT_T_BROADCAST) + { + if (level == 1 && circuit->u.bc.lan_neighs[0]->count > 0) + if (tlv_add_lan_neighs (circuit->u.bc.lan_neighs[0], + circuit->snd_stream)) + return ISIS_WARNING; + if (level == 2 && circuit->u.bc.lan_neighs[1]->count > 0) + if (tlv_add_lan_neighs (circuit->u.bc.lan_neighs[1], + circuit->snd_stream)) + return ISIS_WARNING; + } + if (circuit->u.bc.pad_hellos) if (tlv_add_padding (circuit->snd_stream)) return ISIS_WARNING; @@ -2025,6 +2069,14 @@ send_hello (struct isis_circuit *circuit, int level) /* Update PDU length */ stream_putw_at (circuit->snd_stream, len_pointer, (u_int16_t) length); + /* For HMAC MD5 we need to compute the md5 hash and store it */ + if (circuit->passwd.type == ISIS_PASSWD_TYPE_HMAC_MD5) + { + hmac_md5(circuit->snd_stream->data, stream_get_endp(circuit->snd_stream), (unsigned char *) &circuit->passwd.passwd, circuit->passwd.len, (unsigned char *) &hmac_md5_hash); + /* Copy the hash into the stream */ + memcpy(circuit->snd_stream->data+auth_tlv+3,hmac_md5_hash,ISIS_AUTH_MD5_SIZE); + } + retval = circuit->tx (circuit, level); if (retval) zlog_warn ("sending of LAN Level %d Hello failed", level); @@ -2062,9 +2114,21 @@ send_lan_l1_hello (struct thread *thread) { struct isis_circuit *circuit; int retval; + unsigned long next_hello; circuit = THREAD_ARG (thread); assert (circuit); + + if (!circuit->area) { + return ISIS_OK; + } + + /* Pseudonode sends hellos three times more than the other nodes */ + if (circuit->u.bc.is_dr[0]) + next_hello=circuit->hello_interval[0]/3+1; + else + next_hello=circuit->hello_interval[0]; + circuit->u.bc.t_send_lan_hello[0] = NULL; if (circuit->u.bc.run_dr_elect[0]) @@ -2075,7 +2139,7 @@ send_lan_l1_hello (struct thread *thread) /* set next timer thread */ THREAD_TIMER_ON (master, circuit->u.bc.t_send_lan_hello[0], send_lan_l1_hello, circuit, - isis_jitter (circuit->hello_interval[0], IIH_JITTER)); + isis_jitter (next_hello, IIH_JITTER)); return retval; } @@ -2085,9 +2149,21 @@ send_lan_l2_hello (struct thread *thread) { struct isis_circuit *circuit; int retval; + unsigned long next_hello; circuit = THREAD_ARG (thread); assert (circuit); + + if (!circuit->area) { + return ISIS_OK; + } + + /* Pseudonode sends hellos three times more than the other nodes */ + if (circuit->u.bc.is_dr[1]) + next_hello=circuit->hello_interval[1]/3+1; + else + next_hello=circuit->hello_interval[1]; + circuit->u.bc.t_send_lan_hello[1] = NULL; if (circuit->u.bc.run_dr_elect[1]) @@ -2098,7 +2174,7 @@ send_lan_l2_hello (struct thread *thread) /* set next timer thread */ THREAD_TIMER_ON (master, circuit->u.bc.t_send_lan_hello[1], send_lan_l2_hello, circuit, - isis_jitter (circuit->hello_interval[1], IIH_JITTER)); + isis_jitter (next_hello, IIH_JITTER)); return retval; } @@ -2192,6 +2268,9 @@ send_csnp (struct isis_circuit *circuit, int level) struct listnode *node; struct isis_lsp *lsp; + if (circuit->state != C_STATE_UP || circuit->interface == NULL) + return ISIS_WARNING; + memset (start, 0x00, ISIS_SYS_ID_LEN + 2); memset (stop, 0xff, ISIS_SYS_ID_LEN + 2); @@ -2246,9 +2325,7 @@ send_l1_csnp (struct thread *thread) circuit->t_send_csnp[0] = NULL; if (circuit->circ_type == CIRCUIT_T_BROADCAST && circuit->u.bc.is_dr[0]) - { send_csnp (circuit, 1); - } /* set next timer thread */ THREAD_TIMER_ON (master, circuit->t_send_csnp[0], send_l1_csnp, circuit, isis_jitter (circuit->csnp_interval[0], CSNP_JITTER)); @@ -2268,9 +2345,7 @@ send_l2_csnp (struct thread *thread) circuit->t_send_csnp[1] = NULL; if (circuit->circ_type == CIRCUIT_T_BROADCAST && circuit->u.bc.is_dr[1]) - { send_csnp (circuit, 2); - } /* set next timer thread */ THREAD_TIMER_ON (master, circuit->t_send_csnp[1], send_l2_csnp, circuit, isis_jitter (circuit->csnp_interval[1], CSNP_JITTER)); @@ -2357,6 +2432,9 @@ send_psnp (int level, struct isis_circuit *circuit) struct list *list = NULL; struct listnode *node; + if (circuit->state != C_STATE_UP || circuit->interface == NULL) + return ISIS_WARNING; + if ((circuit->circ_type == CIRCUIT_T_BROADCAST && !circuit->u.bc.is_dr[level - 1]) || circuit->circ_type != CIRCUIT_T_BROADCAST) @@ -2463,85 +2541,85 @@ send_lsp (struct thread *thread) circuit = THREAD_ARG (thread); assert (circuit); - if (circuit->state == C_STATE_UP) + if (circuit->state != C_STATE_UP || circuit->interface == NULL) + return ISIS_WARNING; + + lsp = listgetdata ((node = listhead (circuit->lsp_queue))); + + /* + * Do not send if levels do not match + */ + if (!(lsp->level & circuit->circuit_is_type)) + goto dontsend; + + /* + * Do not send if we do not have adjacencies in state up on the circuit + */ + if (circuit->upadjcount[lsp->level - 1] == 0) + goto dontsend; + /* only send if it needs sending */ + if ((time (NULL) - lsp->last_sent) >= + circuit->area->lsp_gen_interval[lsp->level - 1]) { - lsp = listgetdata ((node = listhead (circuit->lsp_queue))); - /* - * Do not send if levels do not match - */ - if (!(lsp->level & circuit->circuit_is_type)) - goto dontsend; + if (isis->debugs & DEBUG_UPDATE_PACKETS) + { + zlog_debug + ("ISIS-Upd (%s): Sent L%d LSP %s, seq 0x%08x, cksum 0x%04x," + " lifetime %us on %s", circuit->area->area_tag, lsp->level, + rawlspid_print (lsp->lsp_header->lsp_id), + ntohl (lsp->lsp_header->seq_num), + ntohs (lsp->lsp_header->checksum), + ntohs (lsp->lsp_header->rem_lifetime), + circuit->interface->name); + } + /* copy our lsp to the send buffer */ + stream_copy (circuit->snd_stream, lsp->pdu); + + retval = circuit->tx (circuit, lsp->level); /* - * Do not send if we do not have adjacencies in state up on the circuit + * If the sending succeeded, we can del the lsp from circuits + * lsp_queue */ - if (circuit->upadjcount[lsp->level - 1] == 0) - goto dontsend; - /* only send if it needs sending */ - if ((time (NULL) - lsp->last_sent) >= - circuit->area->lsp_gen_interval[lsp->level - 1]) + if (retval == ISIS_OK) { - - if (isis->debugs & DEBUG_UPDATE_PACKETS) - { - zlog_debug - ("ISIS-Upd (%s): Sent L%d LSP %s, seq 0x%08x, cksum 0x%04x," - " lifetime %us on %s", circuit->area->area_tag, lsp->level, - rawlspid_print (lsp->lsp_header->lsp_id), - ntohl (lsp->lsp_header->seq_num), - ntohs (lsp->lsp_header->checksum), - ntohs (lsp->lsp_header->rem_lifetime), - circuit->interface->name); - } - /* copy our lsp to the send buffer */ - stream_copy (circuit->snd_stream, lsp->pdu); - - retval = circuit->tx (circuit, lsp->level); + list_delete_node (circuit->lsp_queue, node); /* - * If the sending succeeded, we can del the lsp from circuits - * lsp_queue + * On broadcast circuits also the SRMflag can be cleared */ - if (retval == ISIS_OK) - { - list_delete_node (circuit->lsp_queue, node); + if (circuit->circ_type == CIRCUIT_T_BROADCAST) + ISIS_CLEAR_FLAG (lsp->SRMflags, circuit); + if (flags_any_set (lsp->SRMflags) == 0) + { /* - * On broadcast circuits also the SRMflag can be cleared + * need to remember when we were last sent */ - if (circuit->circ_type == CIRCUIT_T_BROADCAST) - ISIS_CLEAR_FLAG (lsp->SRMflags, circuit); - - if (flags_any_set (lsp->SRMflags) == 0) - { - /* - * need to remember when we were last sent - */ - lsp->last_sent = time (NULL); - } - } - else - { - zlog_debug ("sending of level %d link state failed", lsp->level); + lsp->last_sent = time (NULL); } } else { - /* my belief is that if it wasn't his time, the lsp can be removed - * from the queue - */ - dontsend: - list_delete_node (circuit->lsp_queue, node); + zlog_debug ("sending of level %d link state failed", lsp->level); } -#if 0 - /* - * If there are still LSPs send next one after lsp-interval (33 msecs) + } + else + { + /* my belief is that if it wasn't his time, the lsp can be removed + * from the queue */ - if (listcount (circuit->lsp_queue) > 0) - thread_add_timer (master, send_lsp, circuit, 1); -#endif + dontsend: + list_delete_node (circuit->lsp_queue, node); } +#if 0 + /* + * If there are still LSPs send next one after lsp-interval (33 msecs) + */ + if (listcount (circuit->lsp_queue) > 0) + thread_add_timer (master, send_lsp, circuit, 1); +#endif return retval; } diff --git a/isisd/isis_pdu.h b/isisd/isis_pdu.h index 95c1ee4f..c4c38e22 100644 --- a/isisd/isis_pdu.h +++ b/isisd/isis_pdu.h @@ -258,8 +258,7 @@ int ack_lsp (struct isis_link_state_hdr *hdr, void fill_fixed_hdr (struct isis_fixed_hdr *hdr, u_char pdu_type); int send_hello (struct isis_circuit *circuit, int level); - -int authentication_check (struct isis_passwd *one, - struct isis_passwd *theother); +#define ISIS_AUTH_MD5_SIZE 16U +int authentication_check (struct isis_passwd *remote, struct isis_passwd *local, struct isis_circuit *c); #endif /* _ZEBRA_ISIS_PDU_H */ diff --git a/isisd/isis_pfpacket.c b/isisd/isis_pfpacket.c index 9e4165e3..8a5c3ed0 100644 --- a/isisd/isis_pfpacket.c +++ b/isisd/isis_pfpacket.c @@ -232,6 +232,10 @@ isis_recv_pdu_bcast (struct isis_circuit *circuit, u_char * ssnpa) LLC_LEN, MSG_PEEK, (struct sockaddr *) &s_addr, (socklen_t *) &addr_len); + if (!circuit->area) { + return ISIS_OK; + } + if (bytesread < 0) { zlog_warn ("isis_recv_packet_bcast(): fd %d, recvfrom (): %s", diff --git a/isisd/isis_spf.c b/isisd/isis_spf.c index 5d7e9da4..5d0b161f 100644 --- a/isisd/isis_spf.c +++ b/isisd/isis_spf.c @@ -405,12 +405,13 @@ isis_spf_add2tent (struct isis_spftree *spftree, enum vertextype vtype, if (adj) listnode_add (vertex->Adj_N, adj); + #ifdef EXTREME_DEBUG zlog_debug ("ISIS-Spf: add to TENT %s %s depth %d dist %d", vtype2string (vertex->type), vid2string (vertex, buff), vertex->depth, vertex->d_N); #endif /* EXTREME_DEBUG */ - listnode_add (spftree->tents, vertex); + if (list_isempty (spftree->tents)) { listnode_add (spftree->tents, vertex); @@ -549,7 +550,8 @@ process_N (struct isis_spftree *spftree, enum vertextype vtype, void *id, */ static int isis_spf_process_lsp (struct isis_spftree *spftree, struct isis_lsp *lsp, - uint32_t cost, uint16_t depth, int family) + uint32_t cost, uint16_t depth, int family, + struct isis_adjacency *adj) { struct listnode *node, *fragnode = NULL; u_int16_t dist; @@ -563,9 +565,6 @@ isis_spf_process_lsp (struct isis_spftree *spftree, struct isis_lsp *lsp, struct ipv6_reachability *ip6reach; #endif /* HAVE_IPV6 */ - - if (!lsp->adj) - return ISIS_WARNING; if (lsp->tlv_data.nlpids == NULL || !speaks (lsp->tlv_data.nlpids, family)) return ISIS_OK; @@ -591,7 +590,7 @@ lspfragloop: vtype = LSP_PSEUDO_ID (is_neigh->neigh_id) ? VTYPE_PSEUDO_IS : VTYPE_NONPSEUDO_IS; process_N (spftree, vtype, (void *) is_neigh->neigh_id, dist, - depth + 1, lsp->adj, family); + depth + 1, adj, family); } } if (lsp->tlv_data.te_is_neighs) @@ -607,7 +606,7 @@ lspfragloop: vtype = LSP_PSEUDO_ID (te_is_neigh->neigh_id) ? VTYPE_PSEUDO_TE_IS : VTYPE_NONPSEUDO_TE_IS; process_N (spftree, vtype, (void *) te_is_neigh->neigh_id, dist, - depth + 1, lsp->adj, family); + depth + 1, adj, family); } } if (family == AF_INET && lsp->tlv_data.ipv4_int_reachs) @@ -621,7 +620,7 @@ lspfragloop: prefix.u.prefix4 = ipreach->prefix; prefix.prefixlen = ip_masklen (ipreach->mask); process_N (spftree, vtype, (void *) &prefix, dist, depth + 1, - lsp->adj, family); + adj, family); } } @@ -636,7 +635,7 @@ lspfragloop: prefix.u.prefix4 = ipreach->prefix; prefix.prefixlen = ip_masklen (ipreach->mask); process_N (spftree, vtype, (void *) &prefix, dist, depth + 1, - lsp->adj, family); + adj, family); } } if (family == AF_INET && lsp->tlv_data.te_ipv4_reachs) @@ -651,7 +650,7 @@ lspfragloop: te_ipv4_reach->control); prefix.prefixlen = (te_ipv4_reach->control & 0x3F); process_N (spftree, vtype, (void *) &prefix, dist, depth + 1, - lsp->adj, family); + adj, family); } } #ifdef HAVE_IPV6 @@ -668,7 +667,7 @@ lspfragloop: memcpy (&prefix.u.prefix6.s6_addr, ip6reach->prefix, PSIZE (ip6reach->prefix_len)); process_N (spftree, vtype, (void *) &prefix, dist, depth + 1, - lsp->adj, family); + adj, family); } } #endif /* HAVE_IPV6 */ @@ -691,7 +690,8 @@ lspfragloop: static int isis_spf_process_pseudo_lsp (struct isis_spftree *spftree, struct isis_lsp *lsp, uint16_t cost, - uint16_t depth, int family) + uint16_t depth, int family, + struct isis_adjacency *adj) { struct listnode *node, *fragnode = NULL; struct is_neigh *is_neigh; @@ -715,13 +715,13 @@ pseudofragloop: /* Two way connectivity */ if (!memcmp (is_neigh->neigh_id, isis->sysid, ISIS_SYS_ID_LEN)) continue; - if (isis_find_vertex - (spftree->tents, (void *) is_neigh->neigh_id, vtype) == NULL + if ((depth > 0 || isis_find_vertex + (spftree->tents, (void *) is_neigh->neigh_id, vtype) == NULL) && isis_find_vertex (spftree->paths, (void *) is_neigh->neigh_id, vtype) == NULL) { /* C.2.5 i) */ - isis_spf_add2tent (spftree, vtype, is_neigh->neigh_id, lsp->adj, + isis_spf_add2tent (spftree, vtype, is_neigh->neigh_id, adj, cost, depth, family); } } @@ -733,13 +733,13 @@ pseudofragloop: /* Two way connectivity */ if (!memcmp (te_is_neigh->neigh_id, isis->sysid, ISIS_SYS_ID_LEN)) continue; - if (isis_find_vertex - (spftree->tents, (void *) te_is_neigh->neigh_id, vtype) == NULL + if ((depth > 0 || isis_find_vertex + (spftree->tents, (void *) te_is_neigh->neigh_id, vtype) == NULL) && isis_find_vertex (spftree->paths, (void *) te_is_neigh->neigh_id, vtype) == NULL) { /* C.2.5 i) */ - isis_spf_add2tent (spftree, vtype, te_is_neigh->neigh_id, lsp->adj, + isis_spf_add2tent (spftree, vtype, te_is_neigh->neigh_id, adj, cost, depth, family); } } @@ -860,9 +860,6 @@ isis_spf_preload_tent (struct isis_spftree *spftree, lsp = lsp_search (lsp_id, area->lspdb[level - 1]); if (!lsp) zlog_warn ("No lsp found for IS adjacency"); - /* else { - isis_spf_process_lsp (spftree, lsp, vertex->d_N, 1, family); - } */ break; case ISIS_SYSTYPE_UNKNOWN: default: @@ -885,14 +882,14 @@ isis_spf_preload_tent (struct isis_spftree *spftree, { zlog_warn ("ISIS-Spf: No adjacency found for DR"); } - if (lsp == NULL || lsp->lsp_header->rem_lifetime == 0) + else if (lsp == NULL || lsp->lsp_header->rem_lifetime == 0) { zlog_warn ("ISIS-Spf: No lsp found for DR"); } else { isis_spf_process_pseudo_lsp (spftree, lsp, - circuit->te_metric[level - 1], 0, family); + circuit->te_metric[level - 1], 0, family, adj); } } @@ -982,6 +979,7 @@ isis_run_spf (struct isis_area *area, int level, int family) struct isis_spftree *spftree = NULL; u_char lsp_id[ISIS_SYS_ID_LEN + 2]; struct isis_lsp *lsp; + struct isis_adjacency *adj = NULL; struct route_table *table = NULL; struct route_node *rode; struct isis_route_info *rinfo; @@ -1032,16 +1030,28 @@ isis_run_spf (struct isis_area *area, int level, int family) while (listcount (spftree->tents) > 0) { + /* C.2.7 a) 1) */ node = listhead (spftree->tents); vertex = listgetdata (node); - /* Remove from tent list */ + + /* C.2.7 a) 2) */ list_delete_node (spftree->tents, node); + + /* C.2.7 a) 3) */ if (isis_find_vertex (spftree->paths, vertex->N.id, vertex->type)) continue; add_to_paths (spftree, vertex, area, level); + if (vertex->type == VTYPE_PSEUDO_IS || - vertex->type == VTYPE_NONPSEUDO_IS) + vertex->type == VTYPE_NONPSEUDO_IS || + vertex->type == VTYPE_PSEUDO_TE_IS || + vertex->type == VTYPE_NONPSEUDO_TE_IS ) { + if (listcount(vertex->Adj_N) == 0) { + continue; + } + adj = listgetdata(vertex->Adj_N->head); + memcpy (lsp_id, vertex->N.id, ISIS_SYS_ID_LEN + 1); LSP_FRAGMENT (lsp_id) = 0; lsp = lsp_search (lsp_id, area->lspdb[level - 1]); @@ -1050,13 +1060,12 @@ isis_run_spf (struct isis_area *area, int level, int family) if (LSP_PSEUDO_ID (lsp_id)) { isis_spf_process_pseudo_lsp (spftree, lsp, vertex->d_N, - vertex->depth, family); - + vertex->depth, family, adj); } else { isis_spf_process_lsp (spftree, lsp, vertex->d_N, - vertex->depth, family); + vertex->depth, family, adj); } } else diff --git a/isisd/isis_tlv.c b/isisd/isis_tlv.c index 94fa65ed..3fc717e3 100644 --- a/isisd/isis_tlv.c +++ b/isisd/isis_tlv.c @@ -446,6 +446,10 @@ parse_tlvs (char *areatag, u_char * stream, int size, u_int32_t * expected, tlvs->auth_info.len = length-1; pnt++; memcpy (tlvs->auth_info.passwd, pnt, length - 1); + /* Fill authentication with 0 for later computation + * of MD5 (RFC 5304, 2) + */ + memset (pnt, 0, length - 1); pnt += length - 1; } else @@ -741,7 +745,7 @@ add_tlv (u_char tag, u_char len, u_char * value, struct stream *stream) stream_putc (stream, len); /* LENGTH */ stream_put (stream, value, (int) len); /* VALUE */ -#ifdef EXTREME_DEBUG +#ifdef EXTREME_TLV_DEBUG zlog_debug ("Added TLV %d len %d", tag, len); #endif /* EXTREME DEBUG */ return ISIS_OK; @@ -878,7 +882,7 @@ tlv_add_authinfo (char auth_type, char auth_len, u_char *auth_value, { u_char value[255]; u_char *pos = value; - *pos++ = ISIS_PASSWD_TYPE_CLEARTXT; + *pos++ = auth_type; memcpy (pos, auth_value, auth_len); return add_tlv (AUTH_INFO, auth_len + 1, value, stream); diff --git a/isisd/isis_zebra.c b/isisd/isis_zebra.c index 9ee5ffc5..d5ccef9e 100644 --- a/isisd/isis_zebra.c +++ b/isisd/isis_zebra.c @@ -274,6 +274,8 @@ isis_zebra_route_add_ipv4 (struct prefix *prefix, stream_putc (stream, flags); /* message */ stream_putc (stream, message); + /* SAFI */ + stream_putw (stream, SAFI_UNICAST); /* prefix information */ psize = PSIZE (prefix->prefixlen); stream_putc (stream, prefix->prefixlen); @@ -321,6 +323,7 @@ isis_zebra_route_del_ipv4 (struct prefix *prefix, api.type = ZEBRA_ROUTE_ISIS; api.flags = 0; api.message = 0; + api.safi = SAFI_UNICAST; prefix4.family = AF_INET; prefix4.prefixlen = prefix->prefixlen; prefix4.prefix = prefix->u.prefix4; @@ -350,6 +353,7 @@ isis_zebra_route_add_ipv6 (struct prefix *prefix, api.type = ZEBRA_ROUTE_ISIS; api.flags = 0; api.message = 0; + api.safi = SAFI_UNICAST; SET_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP); SET_FLAG (api.message, ZAPI_MESSAGE_IFINDEX); SET_FLAG (api.message, ZAPI_MESSAGE_METRIC); @@ -433,6 +437,7 @@ isis_zebra_route_del_ipv6 (struct prefix *prefix, api.type = ZEBRA_ROUTE_ISIS; api.flags = 0; api.message = 0; + api.safi = SAFI_UNICAST; SET_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP); SET_FLAG (api.message, ZAPI_MESSAGE_IFINDEX); api.nexthop_num = listcount (route_info->nexthops6); diff --git a/isisd/isisd.c b/isisd/isisd.c index 1e84a1ce..20a32809 100644 --- a/isisd/isisd.c +++ b/isisd/isisd.c @@ -52,6 +52,7 @@ #include "isisd/isis_route.h" #include "isisd/isis_zebra.h" #include "isisd/isis_events.h" +#include "isisd/isis_csm.h" #ifdef TOPOLOGY_GENERATE #include "spgrid.h" @@ -217,21 +218,31 @@ isis_area_destroy (struct vty *vty, const char *area_tag) for (ALL_LIST_ELEMENTS (area->circuit_list, node, nnode, circuit)) { /* The fact that it's in circuit_list means that it was configured */ + isis_csm_state_change (ISIS_DISABLE, circuit, area); + isis_circuit_down (circuit); isis_circuit_deconfigure (circuit, area); - isis_circuit_del (circuit); } list_delete (area->circuit_list); } listnode_delete (isis->area_list, area); + THREAD_TIMER_OFF (area->t_tick); if (area->t_remove_aged) thread_cancel (area->t_remove_aged); THREAD_TIMER_OFF (area->t_lsp_refresh[0]); THREAD_TIMER_OFF (area->t_lsp_refresh[1]); + THREAD_TIMER_OFF (area->spftree[0]->t_spf); + THREAD_TIMER_OFF (area->spftree[1]->t_spf); + + THREAD_TIMER_OFF (area->t_lsp_l1_regenerate); + THREAD_TIMER_OFF (area->t_lsp_l2_regenerate); + XFREE (MTYPE_ISIS_AREA, area); + isis->sysid_set=0; + return CMD_SUCCESS; } diff --git a/isisd/isisd.h b/isisd/isisd.h index 2277f27c..b17982e2 100644 --- a/isisd/isisd.h +++ b/isisd/isisd.h @@ -93,6 +93,8 @@ struct isis_area struct flags flags; struct thread *t_tick; /* LSP walker */ struct thread *t_remove_aged; + struct thread *t_lsp_l1_regenerate; + struct thread *t_lsp_l2_regenerate; int lsp_regenerate_pending[ISIS_LEVELS]; struct thread *t_lsp_refresh[ISIS_LEVELS]; diff --git a/isisd/topology/.cvsignore b/isisd/topology/.cvsignore deleted file mode 100644 index b0ae823b..00000000 --- a/isisd/topology/.cvsignore +++ /dev/null @@ -1,9 +0,0 @@ -Makefile -Makefile.in -*.o -tags -TAGS -.deps -.nfs* -.arch-inventory -.arch-ids |