diff options
author | Christian Franke <chris@opensourcerouting.org> | 2017-07-05 18:37:36 +0200 |
---|---|---|
committer | Christian Franke <chris@opensourcerouting.org> | 2017-08-03 11:34:04 +0200 |
commit | af8ac8f98fbe565b182020895553d862ad743012 (patch) | |
tree | 1e934f37d3015ee84edb4b0ef4e03ddf94e35897 /isisd | |
parent | isisd: send/receive *SNPs with new parser (diff) | |
download | frr-af8ac8f98fbe565b182020895553d862ad743012.tar.xz frr-af8ac8f98fbe565b182020895553d862ad743012.zip |
isisd: send/receive LSPs with new parser
Signed-off-by: Christian Franke <chris@opensourcerouting.org>
Diffstat (limited to 'isisd')
-rw-r--r-- | isisd/Makefile.am | 4 | ||||
-rw-r--r-- | isisd/isis_adjacency.c | 10 | ||||
-rw-r--r-- | isisd/isis_circuit.c | 1 | ||||
-rw-r--r-- | isisd/isis_common.h | 10 | ||||
-rw-r--r-- | isisd/isis_csm.c | 1 | ||||
-rw-r--r-- | isisd/isis_dr.c | 1 | ||||
-rw-r--r-- | isisd/isis_dynhn.c | 29 | ||||
-rw-r--r-- | isisd/isis_dynhn.h | 4 | ||||
-rw-r--r-- | isisd/isis_events.c | 1 | ||||
-rw-r--r-- | isisd/isis_lsp.c | 1919 | ||||
-rw-r--r-- | isisd/isis_lsp.h | 36 | ||||
-rw-r--r-- | isisd/isis_main.c | 1 | ||||
-rw-r--r-- | isisd/isis_misc.c | 22 | ||||
-rw-r--r-- | isisd/isis_misc.h | 1 | ||||
-rw-r--r-- | isisd/isis_mt.c | 199 | ||||
-rw-r--r-- | isisd/isis_mt.h | 43 | ||||
-rw-r--r-- | isisd/isis_pdu.c | 498 | ||||
-rw-r--r-- | isisd/isis_pdu.h | 34 | ||||
-rw-r--r-- | isisd/isis_redist.c | 1 | ||||
-rw-r--r-- | isisd/isis_route.c | 1 | ||||
-rw-r--r-- | isisd/isis_routemap.c | 1 | ||||
-rw-r--r-- | isisd/isis_spf.c | 235 | ||||
-rw-r--r-- | isisd/isis_te.c | 392 | ||||
-rw-r--r-- | isisd/isis_te.h | 11 | ||||
-rw-r--r-- | isisd/isis_tlv.c | 1453 | ||||
-rw-r--r-- | isisd/isis_tlv.h | 340 | ||||
-rw-r--r-- | isisd/isis_zebra.c | 1 | ||||
-rw-r--r-- | isisd/isisd.c | 1 | ||||
-rw-r--r-- | isisd/iso_checksum.c | 2 |
29 files changed, 977 insertions, 4275 deletions
diff --git a/isisd/Makefile.am b/isisd/Makefile.am index 4e8665cd8..ca212f5b4 100644 --- a/isisd/Makefile.am +++ b/isisd/Makefile.am @@ -13,7 +13,7 @@ sbin_PROGRAMS = isisd libisis_a_SOURCES = \ isis_memory.c \ isis_adjacency.c isis_lsp.c dict.c isis_circuit.c isis_pdu.c \ - isis_tlv.c isisd.c isis_misc.c isis_zebra.c isis_dr.c \ + isisd.c isis_misc.c isis_zebra.c isis_dr.c \ isis_flags.c isis_dynhn.c iso_checksum.c isis_csm.c isis_events.c \ isis_spf.c isis_redist.c isis_route.c isis_routemap.c isis_te.c \ isis_vty.c isis_mt.c \ @@ -22,7 +22,7 @@ libisis_a_SOURCES = \ noinst_HEADERS = \ isis_memory.h \ - isisd.h isis_pdu.h isis_tlv.h isis_adjacency.h isis_constants.h \ + isisd.h isis_pdu.h isis_adjacency.h isis_constants.h \ isis_lsp.h dict.h isis_circuit.h isis_misc.h isis_network.h \ isis_zebra.h isis_dr.h isis_flags.h isis_dynhn.h isis_common.h \ iso_checksum.h isis_csm.h isis_events.h isis_spf.h isis_redist.h \ diff --git a/isisd/isis_adjacency.c b/isisd/isis_adjacency.c index e13b3769e..0afa65d72 100644 --- a/isisd/isis_adjacency.c +++ b/isisd/isis_adjacency.c @@ -43,7 +43,6 @@ #include "isisd/isis_dr.h" #include "isisd/isis_dynhn.h" #include "isisd/isis_pdu.h" -#include "isisd/isis_tlv.h" #include "isisd/isis_lsp.h" #include "isisd/isis_spf.h" #include "isisd/isis_events.h" @@ -187,7 +186,7 @@ void isis_adj_state_change(struct isis_adjacency *adj, dyn = dynhn_find_by_id(adj->sysid); if (dyn) - adj_name = (const char *)dyn->name.name; + adj_name = dyn->hostname; else adj_name = sysid_print(adj->sysid); @@ -301,7 +300,7 @@ void isis_adj_print(struct isis_adjacency *adj) return; dyn = dynhn_find_by_id(adj->sysid); if (dyn) - zlog_debug("%s", dyn->name.name); + zlog_debug("%s", dyn->hostname); zlog_debug("SystemId %20s SNPA %s, level %d\nHolding Time %d", sysid_print(adj->sysid), snpa_print(adj->snpa), adj->level, @@ -355,7 +354,7 @@ void isis_adj_print_vty(struct isis_adjacency *adj, struct vty *vty, dyn = dynhn_find_by_id(adj->sysid); if (dyn) - vty_out(vty, " %-20s", dyn->name.name); + vty_out(vty, " %-20s", dyn->hostname); else vty_out(vty, " %-20s", sysid_print(adj->sysid)); @@ -416,8 +415,7 @@ void isis_adj_print_vty(struct isis_adjacency *adj, struct vty *vty, && (adj->circuit->circ_type == CIRCUIT_T_BROADCAST)) { dyn = dynhn_find_by_id(adj->lanid); if (dyn) - vty_out(vty, ", LAN id: %s.%02x", - dyn->name.name, + vty_out(vty, ", LAN id: %s.%02x", dyn->hostname, adj->lanid[ISIS_SYS_ID_LEN]); else vty_out(vty, ", LAN id: %s.%02x", diff --git a/isisd/isis_circuit.c b/isisd/isis_circuit.c index 72810532b..c321677de 100644 --- a/isisd/isis_circuit.c +++ b/isisd/isis_circuit.c @@ -48,7 +48,6 @@ #include "isisd/isis_common.h" #include "isisd/isis_flags.h" #include "isisd/isis_circuit.h" -#include "isisd/isis_tlv.h" #include "isisd/isis_lsp.h" #include "isisd/isis_pdu.h" #include "isisd/isis_network.h" diff --git a/isisd/isis_common.h b/isisd/isis_common.h index ba6c5f876..b157bb183 100644 --- a/isisd/isis_common.h +++ b/isisd/isis_common.h @@ -47,16 +47,6 @@ struct isis_passwd { }; /* - * (Dynamic) Hostname - * one struct for cache list - * one struct for LSP TLV - */ -struct hostname { - u_char namelen; - u_char name[255]; -}; - -/* * Supported Protocol IDs */ struct nlpids { diff --git a/isisd/isis_csm.c b/isisd/isis_csm.c index b0ccdee76..10870d5c5 100644 --- a/isisd/isis_csm.c +++ b/isisd/isis_csm.c @@ -37,7 +37,6 @@ #include "isisd/isis_common.h" #include "isisd/isis_flags.h" #include "isisd/isis_circuit.h" -#include "isisd/isis_tlv.h" #include "isisd/isis_lsp.h" #include "isisd/isis_pdu.h" #include "isisd/isis_network.h" diff --git a/isisd/isis_dr.c b/isisd/isis_dr.c index 3f532ecf8..2db827191 100644 --- a/isisd/isis_dr.c +++ b/isisd/isis_dr.c @@ -42,7 +42,6 @@ #include "isisd/isis_adjacency.h" #include "isisd/isis_constants.h" #include "isisd/isis_pdu.h" -#include "isisd/isis_tlv.h" #include "isisd/isis_lsp.h" #include "isisd/isis_dr.h" #include "isisd/isis_events.h" diff --git a/isisd/isis_dynhn.c b/isisd/isis_dynhn.c index 9249ad629..6fa798830 100644 --- a/isisd/isis_dynhn.c +++ b/isisd/isis_dynhn.c @@ -94,38 +94,26 @@ struct isis_dynhn *dynhn_find_by_name(const char *hostname) struct isis_dynhn *dyn = NULL; for (ALL_LIST_ELEMENTS_RO(dyn_cache, node, dyn)) - if (strncmp((char *)dyn->name.name, hostname, 255) == 0) + if (strncmp(dyn->hostname, hostname, 255) == 0) return dyn; return NULL; } -void isis_dynhn_insert(const u_char *id, struct hostname *hostname, int level) +void isis_dynhn_insert(const u_char *id, const char *hostname, int level) { struct isis_dynhn *dyn; dyn = dynhn_find_by_id(id); - if (dyn) { - memcpy(&dyn->name, hostname, hostname->namelen + 1); - memcpy(dyn->id, id, ISIS_SYS_ID_LEN); - dyn->refresh = time(NULL); - return; - } - dyn = XCALLOC(MTYPE_ISIS_DYNHN, sizeof(struct isis_dynhn)); if (!dyn) { - zlog_warn("isis_dynhn_insert(): out of memory!"); - return; + dyn = XCALLOC(MTYPE_ISIS_DYNHN, sizeof(struct isis_dynhn)); + memcpy(dyn->id, id, ISIS_SYS_ID_LEN); + dyn->level = level; + listnode_add(dyn_cache, dyn); } - /* we also copy the length */ - memcpy(&dyn->name, hostname, hostname->namelen + 1); - memcpy(dyn->id, id, ISIS_SYS_ID_LEN); + snprintf(dyn->hostname, sizeof(dyn->hostname), "%s", hostname); dyn->refresh = time(NULL); - dyn->level = level; - - listnode_add(dyn_cache, dyn); - - return; } void isis_dynhn_remove(const u_char *id) @@ -137,7 +125,6 @@ void isis_dynhn_remove(const u_char *id) return; listnode_delete(dyn_cache, dyn); XFREE(MTYPE_ISIS_DYNHN, dyn); - return; } /* @@ -155,7 +142,7 @@ void dynhn_print_all(struct vty *vty) for (ALL_LIST_ELEMENTS_RO(dyn_cache, node, dyn)) { vty_out(vty, "%-7d", dyn->level); vty_out(vty, "%-15s%-15s\n", sysid_print(dyn->id), - dyn->name.name); + dyn->hostname); } vty_out(vty, " * %s %s\n", sysid_print(isis->sysid), diff --git a/isisd/isis_dynhn.h b/isisd/isis_dynhn.h index f3ca94d40..635d79f3f 100644 --- a/isisd/isis_dynhn.h +++ b/isisd/isis_dynhn.h @@ -25,13 +25,13 @@ struct isis_dynhn { u_char id[ISIS_SYS_ID_LEN]; - struct hostname name; + char hostname[256]; time_t refresh; int level; }; void dyn_cache_init(void); -void isis_dynhn_insert(const u_char *id, struct hostname *hostname, int level); +void isis_dynhn_insert(const u_char *id, const char *hostname, int level); void isis_dynhn_remove(const u_char *id); struct isis_dynhn *dynhn_find_by_id(const u_char *id); struct isis_dynhn *dynhn_find_by_name(const char *hostname); diff --git a/isisd/isis_events.c b/isisd/isis_events.c index 9af256ba3..1cc90d031 100644 --- a/isisd/isis_events.c +++ b/isisd/isis_events.c @@ -37,7 +37,6 @@ #include "isisd/isis_common.h" #include "isisd/isis_flags.h" #include "isisd/isis_circuit.h" -#include "isisd/isis_tlv.h" #include "isisd/isis_lsp.h" #include "isisd/isis_pdu.h" #include "isisd/isis_network.h" diff --git a/isisd/isis_lsp.c b/isisd/isis_lsp.c index 76022bdea..243853c97 100644 --- a/isisd/isis_lsp.c +++ b/isisd/isis_lsp.c @@ -44,7 +44,6 @@ #include "isisd/isis_flags.h" #include "isisd/isis_circuit.h" #include "isisd/isisd.h" -#include "isisd/isis_tlv.h" #include "isisd/isis_lsp.h" #include "isisd/isis_pdu.h" #include "isisd/isis_dynhn.h" @@ -54,6 +53,7 @@ #include "isisd/isis_spf.h" #include "isisd/isis_te.h" #include "isisd/isis_mt.h" +#include "isisd/isis_tlvs2.h" /* staticly assigned vars for printing purposes */ char lsp_bits_string[200]; /* FIXME: enough ? */ @@ -105,19 +105,8 @@ static void lsp_clear_data(struct isis_lsp *lsp) if (!lsp) return; - if (lsp->tlv_data.hostname) - isis_dynhn_remove(lsp->lsp_header->lsp_id); - - if (lsp->own_lsp) { - if (lsp->tlv_data.nlpids) - XFREE(MTYPE_ISIS_TLV, lsp->tlv_data.nlpids); - if (lsp->tlv_data.hostname) - XFREE(MTYPE_ISIS_TLV, lsp->tlv_data.hostname); - if (lsp->tlv_data.router_id) - XFREE(MTYPE_ISIS_TLV, lsp->tlv_data.router_id); - } - - free_tlvs(&lsp->tlv_data); + isis_free_tlvs(lsp->tlvs); + lsp->tlvs = NULL; } static void lsp_destroy(struct isis_lsp *lsp) @@ -146,7 +135,7 @@ static void lsp_destroy(struct isis_lsp *lsp) lsp_clear_data(lsp); - if (LSP_FRAGMENT(lsp->lsp_header->lsp_id) == 0 && lsp->lspu.frags) { + if (LSP_FRAGMENT(lsp->hdr.lsp_id) == 0 && lsp->lspu.frags) { list_delete(lsp->lspu.frags); lsp->lspu.frags = NULL; } @@ -187,7 +176,7 @@ static void lsp_remove_frags(struct list *frags, dict_t *lspdb) struct isis_lsp *lsp; for (ALL_LIST_ELEMENTS(frags, lnode, lnnode, lsp)) { - dnode = dict_lookup(lspdb, lsp->lsp_header->lsp_id); + dnode = dict_lookup(lspdb, lsp->hdr.lsp_id); lsp_destroy(lsp); dnode_destroy(dict_delete(lspdb, dnode)); } @@ -209,7 +198,7 @@ void lsp_search_and_destroy(u_char *id, dict_t *lspdb) /* * If this is a zero lsp, remove all the frags now */ - if (LSP_FRAGMENT(lsp->lsp_header->lsp_id) == 0) { + if (LSP_FRAGMENT(lsp->hdr.lsp_id) == 0) { if (lsp->lspu.frags) lsp_remove_frags(lsp->lspu.frags, lspdb); } else { @@ -231,33 +220,25 @@ void lsp_search_and_destroy(u_char *id, dict_t *lspdb) * Compares a LSP to given values * Params are given in net order */ -int lsp_compare(char *areatag, struct isis_lsp *lsp, u_int32_t seq_num, - u_int16_t checksum, u_int16_t rem_lifetime) +int lsp_compare(char *areatag, struct isis_lsp *lsp, uint32_t seqno, + uint16_t checksum, uint16_t rem_lifetime) { - seq_num = htonl(seq_num); - checksum = htons(checksum); - rem_lifetime = htons(rem_lifetime); - - /* no point in double ntohl on seqnum */ - if (lsp->lsp_header->seq_num == seq_num - && lsp->lsp_header->checksum == checksum && - /*comparing with 0, no need to do ntohl */ - ((lsp->lsp_header->rem_lifetime == 0 && rem_lifetime == 0) - || (lsp->lsp_header->rem_lifetime != 0 && rem_lifetime != 0))) { + if (lsp->hdr.seqno == seqno && lsp->hdr.checksum == checksum + && ((lsp->hdr.rem_lifetime == 0 && rem_lifetime == 0) + || (lsp->hdr.rem_lifetime != 0 && rem_lifetime != 0))) { if (isis->debugs & DEBUG_SNP_PACKETS) { zlog_debug( - "ISIS-Snp (%s): Compare LSP %s seq 0x%08x, cksum 0x%04x," - " lifetime %us", - areatag, - rawlspid_print(lsp->lsp_header->lsp_id), - ntohl(lsp->lsp_header->seq_num), - ntohs(lsp->lsp_header->checksum), - ntohs(lsp->lsp_header->rem_lifetime)); + "ISIS-Snp (%s): Compare LSP %s seq 0x%08" PRIx32 + ", cksum 0x%04" PRIx16 ", lifetime %" PRIu16 + "s", + areatag, rawlspid_print(lsp->hdr.lsp_id), + lsp->hdr.seqno, lsp->hdr.checksum, + lsp->hdr.rem_lifetime); zlog_debug( - "ISIS-Snp (%s): is equal to ours seq 0x%08x," - " cksum 0x%04x, lifetime %us", - areatag, ntohl(seq_num), ntohs(checksum), - ntohs(rem_lifetime)); + "ISIS-Snp (%s): is equal to ours seq 0x%08" PRIx32 + ", cksum 0x%04" PRIx16 ", lifetime %" PRIu16 + "s", + areatag, seqno, checksum, rem_lifetime); } return LSP_EQUAL; } @@ -274,171 +255,136 @@ int lsp_compare(char *areatag, struct isis_lsp *lsp, u_int32_t seq_num, * as given * in 7.3.16.2. */ - if (ntohl(seq_num) > ntohl(lsp->lsp_header->seq_num) - || (ntohl(seq_num) == ntohl(lsp->lsp_header->seq_num) - && ((lsp->lsp_header->rem_lifetime != 0 && rem_lifetime == 0) - || lsp->lsp_header->checksum != checksum))) { + if (seqno > lsp->hdr.seqno + || (seqno == lsp->hdr.seqno + && ((lsp->hdr.rem_lifetime != 0 && rem_lifetime == 0) + || lsp->hdr.checksum != checksum))) { if (isis->debugs & DEBUG_SNP_PACKETS) { zlog_debug( - "ISIS-Snp (%s): Compare LSP %s seq 0x%08x, cksum 0x%04x," - " lifetime %us", - areatag, - rawlspid_print(lsp->lsp_header->lsp_id), - ntohl(seq_num), ntohs(checksum), - ntohs(rem_lifetime)); + "ISIS-Snp (%s): Compare LSP %s seq 0x%08" PRIx32 + ", cksum 0x%04" PRIx16 ", lifetime %" PRIu16 + "s", + areatag, rawlspid_print(lsp->hdr.lsp_id), seqno, + checksum, rem_lifetime); zlog_debug( - "ISIS-Snp (%s): is newer than ours seq 0x%08x, " - "cksum 0x%04x, lifetime %us", - areatag, ntohl(lsp->lsp_header->seq_num), - ntohs(lsp->lsp_header->checksum), - ntohs(lsp->lsp_header->rem_lifetime)); + "ISIS-Snp (%s): is newer than ours seq 0x%08" PRIx32 + ", cksum 0x%04" PRIx16 ", lifetime %" PRIu16 + "s", + areatag, lsp->hdr.seqno, lsp->hdr.checksum, + lsp->hdr.rem_lifetime); } return LSP_NEWER; } if (isis->debugs & DEBUG_SNP_PACKETS) { + zlog_debug("ISIS-Snp (%s): Compare LSP %s seq 0x%08" PRIx32 + ", cksum 0x%04" PRIx16 ", lifetime %" PRIu16 "s", + areatag, rawlspid_print(lsp->hdr.lsp_id), seqno, + checksum, rem_lifetime); zlog_debug( - "ISIS-Snp (%s): Compare LSP %s seq 0x%08x, cksum 0x%04x, lifetime %us", - areatag, rawlspid_print(lsp->lsp_header->lsp_id), - ntohl(seq_num), ntohs(checksum), ntohs(rem_lifetime)); - zlog_debug( - "ISIS-Snp (%s): is older than ours seq 0x%08x," - " cksum 0x%04x, lifetime %us", - areatag, ntohl(lsp->lsp_header->seq_num), - ntohs(lsp->lsp_header->checksum), - ntohs(lsp->lsp_header->rem_lifetime)); + "ISIS-Snp (%s): is older than ours seq 0x%08" PRIx32 + ", cksum 0x%04" PRIx16 ", lifetime %" PRIu16 "s", + areatag, lsp->hdr.seqno, lsp->hdr.checksum, + lsp->hdr.rem_lifetime); } return LSP_OLDER; } -static void lsp_auth_add(struct isis_lsp *lsp) +static void put_lsp_hdr(struct isis_lsp *lsp, size_t *len_pointer) { - struct isis_passwd *passwd; - unsigned char hmac_md5_hash[ISIS_AUTH_MD5_SIZE]; - - /* - * Add the authentication info if its present - */ - (lsp->level == IS_LEVEL_1) ? (passwd = &lsp->area->area_passwd) - : (passwd = &lsp->area->domain_passwd); - switch (passwd->type) { - /* Cleartext */ - case ISIS_PASSWD_TYPE_CLEARTXT: - memcpy(&lsp->tlv_data.auth_info, passwd, - sizeof(struct isis_passwd)); - tlv_add_authinfo(passwd->type, passwd->len, passwd->passwd, - lsp->pdu); - break; - - /* HMAC MD5 */ - case ISIS_PASSWD_TYPE_HMAC_MD5: - /* Remember where TLV is written so we can later - * overwrite the MD5 hash */ - lsp->auth_tlv_offset = stream_get_endp(lsp->pdu); - memset(&hmac_md5_hash, 0, ISIS_AUTH_MD5_SIZE); - lsp->tlv_data.auth_info.type = ISIS_PASSWD_TYPE_HMAC_MD5; - lsp->tlv_data.auth_info.len = ISIS_AUTH_MD5_SIZE; - memcpy(&lsp->tlv_data.auth_info.passwd, hmac_md5_hash, - ISIS_AUTH_MD5_SIZE); - tlv_add_authinfo(passwd->type, ISIS_AUTH_MD5_SIZE, - hmac_md5_hash, lsp->pdu); - break; - - default: - break; - } + uint8_t pdu_type = + (lsp->level == IS_LEVEL_1) ? L1_LINK_STATE : L2_LINK_STATE; + struct isis_lsp_hdr *hdr = &lsp->hdr; + struct stream *stream = lsp->pdu; + + fill_fixed_hdr(pdu_type, stream); + + if (len_pointer) + *len_pointer = stream_get_endp(stream); + stream_putw(stream, hdr->pdu_len); + stream_putw(stream, hdr->rem_lifetime); + stream_put(stream, hdr->lsp_id, sizeof(hdr->lsp_id)); + stream_putl(stream, hdr->seqno); + stream_putw(stream, hdr->checksum); + stream_putc(stream, hdr->lsp_bits); } -static void lsp_auth_update(struct isis_lsp *lsp) +static void lsp_add_auth(struct isis_lsp *lsp) { struct isis_passwd *passwd; - unsigned char hmac_md5_hash[ISIS_AUTH_MD5_SIZE]; - uint16_t checksum, rem_lifetime; + passwd = (lsp->level == IS_LEVEL_1) ? &lsp->area->area_passwd + : &lsp->area->domain_passwd; + isis_tlvs_add_auth(lsp->tlvs, passwd); +} - /* For HMAC MD5 we need to recompute the md5 hash and store it */ - (lsp->level == IS_LEVEL_1) ? (passwd = &lsp->area->area_passwd) - : (passwd = &lsp->area->domain_passwd); - if (passwd->type != ISIS_PASSWD_TYPE_HMAC_MD5) - return; +static void lsp_pack_pdu(struct isis_lsp *lsp) +{ + if (!lsp->tlvs) + lsp->tlvs = isis_alloc_tlvs(); - /* - * In transient conditions (when net is configured where authentication - * config and lsp regenerate schedule is not yet run), there could be - * an own_lsp with auth_tlv_offset set to 0. In such a case, simply - * return, when lsp_regenerate is run, lsp will have auth tlv. - */ - if (lsp->auth_tlv_offset == 0) - return; + lsp_add_auth(lsp); - /* - * RFC 5304 set auth value, checksum and remaining lifetime to zero - * before computation and reset to old values after computation. - */ - checksum = lsp->lsp_header->checksum; - rem_lifetime = lsp->lsp_header->rem_lifetime; - lsp->lsp_header->checksum = 0; - lsp->lsp_header->rem_lifetime = 0; - /* Set the authentication value as well to zero */ - memset(STREAM_DATA(lsp->pdu) + lsp->auth_tlv_offset + 3, 0, - ISIS_AUTH_MD5_SIZE); - /* Compute autentication value */ - hmac_md5(STREAM_DATA(lsp->pdu), stream_get_endp(lsp->pdu), - (unsigned char *)&passwd->passwd, passwd->len, - (unsigned char *)&hmac_md5_hash); - /* Copy the hash into the stream */ - memcpy(STREAM_DATA(lsp->pdu) + lsp->auth_tlv_offset + 3, hmac_md5_hash, - ISIS_AUTH_MD5_SIZE); - memcpy(&lsp->tlv_data.auth_info.passwd, hmac_md5_hash, - ISIS_AUTH_MD5_SIZE); - /* Copy back the checksum and remaining lifetime */ - lsp->lsp_header->checksum = checksum; - lsp->lsp_header->rem_lifetime = rem_lifetime; + size_t len_pointer; + stream_reset(lsp->pdu); + put_lsp_hdr(lsp, &len_pointer); + isis_pack_tlvs(lsp->tlvs, lsp->pdu, len_pointer, false, true); + + lsp->hdr.pdu_len = stream_get_endp(lsp->pdu); + lsp->hdr.checksum = + ntohs(fletcher_checksum(STREAM_DATA(lsp->pdu) + 12, + stream_get_endp(lsp->pdu) - 12, 12)); } -void lsp_inc_seqnum(struct isis_lsp *lsp, u_int32_t seq_num) +void lsp_inc_seqno(struct isis_lsp *lsp, uint32_t seqno) { - u_int32_t newseq; + uint32_t newseq; - if (seq_num == 0 || ntohl(lsp->lsp_header->seq_num) > seq_num) - newseq = ntohl(lsp->lsp_header->seq_num) + 1; + if (seqno == 0 || lsp->hdr.seqno > seqno) + newseq = lsp->hdr.seqno + 1; else - newseq = seq_num + 1; - - lsp->lsp_header->seq_num = htonl(newseq); - - /* Recompute authentication and checksum information */ - lsp_auth_update(lsp); - /* ISO 10589 - 7.3.11 Generation of the checksum - * The checksum shall be computed over all fields in the LSP which - * appear - * after the Remaining Lifetime field. This field (and those appearing - * before it) are excluded so that the LSP may be aged by systems - * without - * requiring recomputation. - */ - fletcher_checksum(STREAM_DATA(lsp->pdu) + 12, - ntohs(lsp->lsp_header->pdu_len) - 12, 12); + newseq = seqno + 1; + lsp->hdr.seqno = newseq; + + lsp_pack_pdu(lsp); isis_spf_schedule(lsp->area, lsp->level); +} - return; +static void lsp_purge(struct isis_lsp *lsp, int level) +{ + /* reset stream */ + lsp_clear_data(lsp); + stream_reset(lsp->pdu); + + /* update header */ + lsp->hdr.checksum = 0; + lsp->hdr.rem_lifetime = 0; + lsp->level = level; + lsp->age_out = lsp->area->max_lsp_lifetime[level - 1]; + + lsp_pack_pdu(lsp); + lsp_set_all_srmflags(lsp); } /* - * Genetates checksum for LSP and its frags + * Generates checksum for LSP and its frags */ -static void lsp_seqnum_update(struct isis_lsp *lsp0) +static void lsp_seqno_update(struct isis_lsp *lsp0) { struct isis_lsp *lsp; struct listnode *node; - lsp_inc_seqnum(lsp0, 0); + lsp_inc_seqno(lsp0, 0); if (!lsp0->lspu.frags) return; - for (ALL_LIST_ELEMENTS_RO(lsp0->lspu.frags, node, lsp)) - lsp_inc_seqnum(lsp, 0); + for (ALL_LIST_ELEMENTS_RO(lsp0->lspu.frags, node, lsp)) { + if (lsp->tlvs) + lsp_inc_seqno(lsp, 0); + else + lsp_purge(lsp, lsp0->level); + } return; } @@ -457,12 +403,10 @@ static u_int8_t lsp_bits_generate(int level, int overload_bit, int attached_bit) return lsp_bits; } -static void lsp_update_data(struct isis_lsp *lsp, struct stream *stream, +static void lsp_update_data(struct isis_lsp *lsp, struct isis_lsp_hdr *hdr, + struct isis_tlvs *tlvs, struct stream *stream, struct isis_area *area, int level) { - uint32_t expected = 0, found; - int retval; - /* free the old lsp data */ lsp_clear_data(lsp); @@ -471,49 +415,17 @@ static void lsp_update_data(struct isis_lsp *lsp, struct stream *stream, stream_free(lsp->pdu); lsp->pdu = stream_dup(stream); - /* setting pointers to the correct place */ - lsp->lsp_header = (struct isis_link_state_hdr *)(STREAM_DATA(lsp->pdu) - + ISIS_FIXED_HDR_LEN); + memcpy(&lsp->hdr, hdr, sizeof(lsp->hdr)); lsp->area = area; lsp->level = level; lsp->age_out = ZERO_AGE_LIFETIME; lsp->installed = time(NULL); - /* - * Get LSP data i.e. TLVs - */ - expected |= TLVFLAG_AUTH_INFO; - expected |= TLVFLAG_AREA_ADDRS; - expected |= TLVFLAG_IS_NEIGHS; - expected |= TLVFLAG_NLPID; - if (area->dynhostname) - expected |= TLVFLAG_DYN_HOSTNAME; - if (area->newmetric) { - expected |= TLVFLAG_TE_IS_NEIGHS; - expected |= TLVFLAG_TE_IPV4_REACHABILITY; - expected |= TLVFLAG_TE_ROUTER_ID; - } - expected |= TLVFLAG_MT_ROUTER_INFORMATION; - expected |= TLVFLAG_IPV4_ADDR; - expected |= TLVFLAG_IPV4_INT_REACHABILITY; - expected |= TLVFLAG_IPV4_EXT_REACHABILITY; - expected |= TLVFLAG_IPV6_ADDR; - expected |= TLVFLAG_IPV6_REACHABILITY; - - retval = parse_tlvs(area->area_tag, - STREAM_DATA(lsp->pdu) + ISIS_FIXED_HDR_LEN - + ISIS_LSP_HDR_LEN, - ntohs(lsp->lsp_header->pdu_len) - ISIS_FIXED_HDR_LEN - - ISIS_LSP_HDR_LEN, - &expected, &found, &lsp->tlv_data, NULL); - if (retval != ISIS_OK) { - zlog_warn("Could not parse LSP"); - return; - } - if ((found & TLVFLAG_DYN_HOSTNAME) && (area->dynhostname)) { - isis_dynhn_insert(lsp->lsp_header->lsp_id, - lsp->tlv_data.hostname, - (lsp->lsp_header->lsp_bits & LSPBIT_IST) + lsp->tlvs = tlvs; + + if (area->dynhostname && lsp->tlvs->hostname) { + isis_dynhn_insert(lsp->hdr.lsp_id, lsp->tlvs->hostname, + (lsp->hdr.lsp_bits & LSPBIT_IST) == IS_LEVEL_1_AND_2 ? IS_LEVEL_2 : IS_LEVEL_1); @@ -522,7 +434,8 @@ static void lsp_update_data(struct isis_lsp *lsp, struct stream *stream, return; } -void lsp_update(struct isis_lsp *lsp, struct stream *stream, +void lsp_update(struct isis_lsp *lsp, struct isis_lsp_hdr *hdr, + struct isis_tlvs *tlvs, struct stream *stream, struct isis_area *area, int level) { dnode_t *dnode = NULL; @@ -530,36 +443,35 @@ void lsp_update(struct isis_lsp *lsp, struct stream *stream, /* Remove old LSP from database. This is required since the * lsp_update_data will free the lsp->pdu (which has the key, lsp_id) * and will update it with the new data in the stream. */ - dnode = dict_lookup(area->lspdb[level - 1], lsp->lsp_header->lsp_id); + dnode = dict_lookup(area->lspdb[level - 1], lsp->hdr.lsp_id); if (dnode) dnode_destroy(dict_delete(area->lspdb[level - 1], dnode)); if (lsp->own_lsp) { zlog_err( "ISIS-Upd (%s): BUG updating LSP %s still marked as own LSP", - area->area_tag, - rawlspid_print(lsp->lsp_header->lsp_id)); + area->area_tag, rawlspid_print(lsp->hdr.lsp_id)); lsp_clear_data(lsp); lsp->own_lsp = 0; } /* rebuild the lsp data */ - lsp_update_data(lsp, stream, area, level); + lsp_update_data(lsp, hdr, tlvs, stream, area, level); /* insert the lsp back into the database */ lsp_insert(lsp, area->lspdb[level - 1]); } /* creation of LSP directly from what we received */ -struct isis_lsp *lsp_new_from_stream_ptr(struct stream *stream, - u_int16_t pdu_len, - struct isis_lsp *lsp0, - struct isis_area *area, int level) +struct isis_lsp *lsp_new_from_recv(struct isis_lsp_hdr *hdr, + struct isis_tlvs *tlvs, + struct stream *stream, struct isis_lsp *lsp0, + struct isis_area *area, int level) { struct isis_lsp *lsp; lsp = XCALLOC(MTYPE_ISIS_LSP, sizeof(struct isis_lsp)); - lsp_update_data(lsp, stream, area, level); + lsp_update_data(lsp, hdr, tlvs, stream, area, level); if (lsp0 == NULL) { /* @@ -579,12 +491,10 @@ struct isis_lsp *lsp_new_from_stream_ptr(struct stream *stream, } struct isis_lsp *lsp_new(struct isis_area *area, u_char *lsp_id, - u_int16_t rem_lifetime, u_int32_t seq_num, - u_int8_t lsp_bits, u_int16_t checksum, int level) + uint16_t rem_lifetime, uint32_t seqno, + uint8_t lsp_bits, uint16_t checksum, int level) { struct isis_lsp *lsp; - uint8_t pdu_type = - (level == IS_LEVEL_1) ? L1_LINK_STATE : L2_LINK_STATE; lsp = XCALLOC(MTYPE_ISIS_LSP, sizeof(struct isis_lsp)); lsp->area = area; @@ -593,40 +503,31 @@ struct isis_lsp *lsp_new(struct isis_area *area, u_char *lsp_id, if (LSP_FRAGMENT(lsp_id) == 0) lsp->lspu.frags = list_new(); - fill_fixed_hdr(pdu_type, lsp->pdu); - - /* now for the LSP HEADER */ /* Minimal LSP PDU size */ - lsp->lsp_header = (struct isis_link_state_hdr *)(STREAM_DATA(lsp->pdu) - + ISIS_FIXED_HDR_LEN); - lsp->lsp_header->pdu_len = htons(ISIS_FIXED_HDR_LEN + ISIS_LSP_HDR_LEN); - memcpy(lsp->lsp_header->lsp_id, lsp_id, ISIS_SYS_ID_LEN + 2); - lsp->lsp_header->checksum = htons(checksum); - lsp->lsp_header->seq_num = htonl(seq_num); - lsp->lsp_header->rem_lifetime = htons(rem_lifetime); - lsp->lsp_header->lsp_bits = lsp_bits; + lsp->hdr.pdu_len = ISIS_FIXED_HDR_LEN + ISIS_LSP_HDR_LEN; + memcpy(lsp->hdr.lsp_id, lsp_id, sizeof(lsp->hdr.lsp_id)); + lsp->hdr.checksum = checksum; + lsp->hdr.seqno = seqno; + lsp->hdr.rem_lifetime = rem_lifetime; + lsp->hdr.lsp_bits = lsp_bits; lsp->level = level; lsp->age_out = ZERO_AGE_LIFETIME; - - stream_forward_endp(lsp->pdu, ISIS_FIXED_HDR_LEN + ISIS_LSP_HDR_LEN); + put_lsp_hdr(lsp, NULL); if (isis->debugs & DEBUG_EVENTS) zlog_debug("New LSP with ID %s-%02x-%02x len %d seqnum %08x", - sysid_print(lsp_id), - LSP_PSEUDO_ID(lsp->lsp_header->lsp_id), - LSP_FRAGMENT(lsp->lsp_header->lsp_id), - ntohl(lsp->lsp_header->pdu_len), - ntohl(lsp->lsp_header->seq_num)); + sysid_print(lsp_id), LSP_PSEUDO_ID(lsp->hdr.lsp_id), + LSP_FRAGMENT(lsp->hdr.lsp_id), lsp->hdr.pdu_len, + lsp->hdr.seqno); return lsp; } void lsp_insert(struct isis_lsp *lsp, dict_t *lspdb) { - dict_alloc_insert(lspdb, lsp->lsp_header->lsp_id, lsp); - if (lsp->lsp_header->seq_num != 0) { + dict_alloc_insert(lspdb, lsp->hdr.lsp_id, lsp); + if (lsp->hdr.seqno) isis_spf_schedule(lsp->area, lsp->level); - } } /* @@ -645,14 +546,13 @@ void lsp_build_list_nonzero_ht(u_char *start_id, u_char *stop_id, curr = first; - if (((struct isis_lsp *)(curr->dict_data))->lsp_header->rem_lifetime) + if (((struct isis_lsp *)(curr->dict_data))->hdr.rem_lifetime) listnode_add(list, first->dict_data); while (curr) { curr = dict_next(lspdb, curr); if (curr - && ((struct isis_lsp *)(curr->dict_data)) - ->lsp_header->rem_lifetime) + && ((struct isis_lsp *)(curr->dict_data))->hdr.rem_lifetime) listnode_add(list, curr->dict_data); if (curr == last) break; @@ -665,14 +565,15 @@ static void lsp_set_time(struct isis_lsp *lsp) { assert(lsp); - if (lsp->lsp_header->rem_lifetime == 0) { + if (lsp->hdr.rem_lifetime == 0) { if (lsp->age_out > 0) lsp->age_out--; return; } - lsp->lsp_header->rem_lifetime = - htons(ntohs(lsp->lsp_header->rem_lifetime) - 1); + lsp->hdr.rem_lifetime--; + if (lsp->pdu && stream_get_endp(lsp->pdu) >= 12) + stream_putw_at(lsp->pdu, 10, lsp->hdr.rem_lifetime); } static void lspid_print(u_char *lsp_id, u_char *trg, char dynhost, char frag) @@ -686,7 +587,7 @@ static void lspid_print(u_char *lsp_id, u_char *trg, char dynhost, char frag) dyn = NULL; if (dyn) - sprintf((char *)id, "%.14s", dyn->name.name); + sprintf((char *)id, "%.14s", dyn->hostname); else if (!memcmp(isis->sysid, lsp_id, ISIS_SYS_ID_LEN) && dynhost) sprintf((char *)id, "%.14s", unix_hostname()); else @@ -699,21 +600,21 @@ static void lspid_print(u_char *lsp_id, u_char *trg, char dynhost, char frag) } /* Convert the lsp attribute bits to attribute string */ -const char *lsp_bits2string(u_char *lsp_bits) +static const char *lsp_bits2string(uint8_t lsp_bits) { char *pos = lsp_bits_string; - if (!*lsp_bits) + if (!lsp_bits) return " none"; /* we only focus on the default metric */ pos += sprintf(pos, "%d/", - ISIS_MASK_LSP_ATT_DEFAULT_BIT(*lsp_bits) ? 1 : 0); + ISIS_MASK_LSP_ATT_DEFAULT_BIT(lsp_bits) ? 1 : 0); pos += sprintf(pos, "%d/", - ISIS_MASK_LSP_PARTITION_BIT(*lsp_bits) ? 1 : 0); + ISIS_MASK_LSP_PARTITION_BIT(lsp_bits) ? 1 : 0); - pos += sprintf(pos, "%d", ISIS_MASK_LSP_OL_BIT(*lsp_bits) ? 1 : 0); + pos += sprintf(pos, "%d", ISIS_MASK_LSP_OL_BIT(lsp_bits) ? 1 : 0); *(pos) = '\0'; @@ -726,276 +627,26 @@ void lsp_print(struct isis_lsp *lsp, struct vty *vty, char dynhost) u_char LSPid[255]; char age_out[8]; - lspid_print(lsp->lsp_header->lsp_id, LSPid, dynhost, 1); + lspid_print(lsp->hdr.lsp_id, LSPid, dynhost, 1); vty_out(vty, "%-21s%c ", LSPid, lsp->own_lsp ? '*' : ' '); - vty_out(vty, "%5u ", ntohs(lsp->lsp_header->pdu_len)); - vty_out(vty, "0x%08x ", ntohl(lsp->lsp_header->seq_num)); - vty_out(vty, "0x%04x ", ntohs(lsp->lsp_header->checksum)); - if (ntohs(lsp->lsp_header->rem_lifetime) == 0) { - snprintf(age_out, 8, "(%u)", lsp->age_out); + vty_out(vty, "%5" PRIu16 " ", lsp->hdr.pdu_len); + vty_out(vty, "0x%08" PRIx32 " ", lsp->hdr.seqno); + vty_out(vty, "0x%04" PRIx16 " ", lsp->hdr.checksum); + if (lsp->hdr.rem_lifetime == 0) { + snprintf(age_out, 8, "(%d)", lsp->age_out); age_out[7] = '\0'; vty_out(vty, "%7s ", age_out); } else - vty_out(vty, " %5u ", ntohs(lsp->lsp_header->rem_lifetime)); - vty_out(vty, "%s\n", lsp_bits2string(&lsp->lsp_header->lsp_bits)); -} - -static void lsp_print_mt_reach(struct list *list, struct vty *vty, char dynhost, - uint16_t mtid) -{ - struct listnode *node; - struct te_is_neigh *neigh; - - for (ALL_LIST_ELEMENTS_RO(list, node, neigh)) { - u_char lspid[255]; - - lspid_print(neigh->neigh_id, lspid, dynhost, 0); - if (mtid == ISIS_MT_IPV4_UNICAST) { - vty_out(vty, - " Metric : %-8u IS-Extended : %s\n", - GET_TE_METRIC(neigh), lspid); - } else { - vty_out(vty, - " Metric : %-8u MT-Reach : %s %s\n", - GET_TE_METRIC(neigh), lspid, - isis_mtid2str(mtid)); - } - if (IS_MPLS_TE(isisMplsTE)) - mpls_te_print_detail(vty, neigh); - } -} - -static void lsp_print_mt_ipv6_reach(struct list *list, struct vty *vty, - uint16_t mtid) -{ - struct listnode *node; - struct ipv6_reachability *ipv6_reach; - struct in6_addr in6; - u_char buff[BUFSIZ]; - - for (ALL_LIST_ELEMENTS_RO(list, node, ipv6_reach)) { - memset(&in6, 0, sizeof(in6)); - memcpy(in6.s6_addr, ipv6_reach->prefix, - PSIZE(ipv6_reach->prefix_len)); - inet_ntop(AF_INET6, &in6, (char *)buff, BUFSIZ); - if (mtid == ISIS_MT_IPV4_UNICAST) { - if ((ipv6_reach->control_info & CTRL_INFO_DISTRIBUTION) - == DISTRIBUTION_INTERNAL) - vty_out(vty, " Metric : %-8" PRIu32 - " IPv6-Internal : %s/%d\n", - ntohl(ipv6_reach->metric), buff, - ipv6_reach->prefix_len); - else - vty_out(vty, " Metric : %-8" PRIu32 - " IPv6-External : %s/%d\n", - ntohl(ipv6_reach->metric), buff, - ipv6_reach->prefix_len); - } else { - if ((ipv6_reach->control_info & CTRL_INFO_DISTRIBUTION) - == DISTRIBUTION_INTERNAL) - vty_out(vty, " Metric : %-8" PRIu32 - " IPv6-MT-Int : %s/%d %s\n", - ntohl(ipv6_reach->metric), buff, - ipv6_reach->prefix_len, - isis_mtid2str(mtid)); - else - vty_out(vty, " Metric : %-8" PRIu32 - " IPv6-MT-Ext : %s/%d %s\n", - ntohl(ipv6_reach->metric), buff, - ipv6_reach->prefix_len, - isis_mtid2str(mtid)); - } - } -} - -static void lsp_print_mt_ipv4_reach(struct list *list, struct vty *vty, - uint16_t mtid) -{ - struct listnode *node; - struct te_ipv4_reachability *te_ipv4_reach; - - for (ALL_LIST_ELEMENTS_RO(list, node, te_ipv4_reach)) { - if (mtid == ISIS_MT_IPV4_UNICAST) { - /* FIXME: There should be better way to output this - * stuff. */ - vty_out(vty, " Metric : %-8" PRIu32 - " IPv4-Extended : %s/%d\n", - ntohl(te_ipv4_reach->te_metric), - inet_ntoa(newprefix2inaddr( - &te_ipv4_reach->prefix_start, - te_ipv4_reach->control)), - te_ipv4_reach->control & 0x3F); - } else { - /* FIXME: There should be better way to output this - * stuff. */ - vty_out(vty, " Metric : %-8" PRIu32 - " IPv4-MT : %s/%d %s\n", - ntohl(te_ipv4_reach->te_metric), - inet_ntoa(newprefix2inaddr( - &te_ipv4_reach->prefix_start, - te_ipv4_reach->control)), - te_ipv4_reach->control & 0x3F, - isis_mtid2str(mtid)); - } - } + vty_out(vty, " %5" PRIu16 " ", lsp->hdr.rem_lifetime); + vty_out(vty, "%s\n", lsp_bits2string(lsp->hdr.lsp_bits)); } void lsp_print_detail(struct isis_lsp *lsp, struct vty *vty, char dynhost) { - struct area_addr *area_addr; - int i; - struct listnode *lnode; - struct is_neigh *is_neigh; - struct ipv4_reachability *ipv4_reach; - struct in_addr *ipv4_addr; - struct mt_router_info *mt_router_info; - struct tlv_mt_ipv6_reachs *mt_ipv6_reachs; - struct tlv_mt_neighbors *mt_is_neigh; - struct tlv_mt_ipv4_reachs *mt_ipv4_reachs; - u_char LSPid[255]; - u_char hostname[255]; - u_char ipv4_reach_prefix[20]; - u_char ipv4_reach_mask[20]; - u_char ipv4_address[20]; - - lspid_print(lsp->lsp_header->lsp_id, LSPid, dynhost, 1); lsp_print(lsp, vty, dynhost); - - /* for all area address */ - if (lsp->tlv_data.area_addrs) - for (ALL_LIST_ELEMENTS_RO(lsp->tlv_data.area_addrs, lnode, - area_addr)) { - vty_out(vty, " Area Address: %s\n", - isonet_print(area_addr->area_addr, - area_addr->addr_len)); - } - - /* for the nlpid tlv */ - if (lsp->tlv_data.nlpids) { - for (i = 0; i < lsp->tlv_data.nlpids->count; i++) { - switch (lsp->tlv_data.nlpids->nlpids[i]) { - case NLPID_IP: - case NLPID_IPV6: - vty_out(vty, " NLPID : 0x%X\n", - lsp->tlv_data.nlpids->nlpids[i]); - break; - default: - vty_out(vty, " NLPID : %s\n", "unknown"); - break; - } - } - } - - for (ALL_LIST_ELEMENTS_RO(lsp->tlv_data.mt_router_info, lnode, - mt_router_info)) { - vty_out(vty, " MT : %s%s\n", - isis_mtid2str(mt_router_info->mtid), - mt_router_info->overload ? " (overload)" : ""); - } - - /* for the hostname tlv */ - if (lsp->tlv_data.hostname) { - bzero(hostname, sizeof(hostname)); - memcpy(hostname, lsp->tlv_data.hostname->name, - lsp->tlv_data.hostname->namelen); - vty_out(vty, " Hostname : %s\n", hostname); - } - - /* authentication tlv */ - if (lsp->tlv_data.auth_info.type != ISIS_PASSWD_TYPE_UNUSED) { - if (lsp->tlv_data.auth_info.type == ISIS_PASSWD_TYPE_HMAC_MD5) - vty_out(vty, " Auth type : md5\n"); - else if (lsp->tlv_data.auth_info.type - == ISIS_PASSWD_TYPE_CLEARTXT) - vty_out(vty, " Auth type : clear text\n"); - } - - /* TE router id */ - if (lsp->tlv_data.router_id) { - memcpy(ipv4_address, inet_ntoa(lsp->tlv_data.router_id->id), - sizeof(ipv4_address)); - vty_out(vty, " Router ID : %s\n", ipv4_address); - } - - if (lsp->tlv_data.ipv4_addrs) - for (ALL_LIST_ELEMENTS_RO(lsp->tlv_data.ipv4_addrs, lnode, - ipv4_addr)) { - memcpy(ipv4_address, inet_ntoa(*ipv4_addr), - sizeof(ipv4_address)); - vty_out(vty, " IPv4 Address: %s\n", ipv4_address); - } - - /* for the IS neighbor tlv */ - if (lsp->tlv_data.is_neighs) - for (ALL_LIST_ELEMENTS_RO(lsp->tlv_data.is_neighs, lnode, - is_neigh)) { - lspid_print(is_neigh->neigh_id, LSPid, dynhost, 0); - vty_out(vty, " Metric : %-8" PRIu8 - " IS : %s\n", - is_neigh->metrics.metric_default, LSPid); - } - - /* for the internal reachable tlv */ - if (lsp->tlv_data.ipv4_int_reachs) - for (ALL_LIST_ELEMENTS_RO(lsp->tlv_data.ipv4_int_reachs, lnode, - ipv4_reach)) { - memcpy(ipv4_reach_prefix, inet_ntoa(ipv4_reach->prefix), - sizeof(ipv4_reach_prefix)); - memcpy(ipv4_reach_mask, inet_ntoa(ipv4_reach->mask), - sizeof(ipv4_reach_mask)); - vty_out(vty, " Metric : %-8" PRIu8 - " IPv4-Internal : %s %s\n", - ipv4_reach->metrics.metric_default, - ipv4_reach_prefix, ipv4_reach_mask); - } - - /* for the external reachable tlv */ - if (lsp->tlv_data.ipv4_ext_reachs) - for (ALL_LIST_ELEMENTS_RO(lsp->tlv_data.ipv4_ext_reachs, lnode, - ipv4_reach)) { - memcpy(ipv4_reach_prefix, inet_ntoa(ipv4_reach->prefix), - sizeof(ipv4_reach_prefix)); - memcpy(ipv4_reach_mask, inet_ntoa(ipv4_reach->mask), - sizeof(ipv4_reach_mask)); - vty_out(vty, " Metric : %-8" PRIu8 - " IPv4-External : %s %s\n", - ipv4_reach->metrics.metric_default, - ipv4_reach_prefix, ipv4_reach_mask); - } - - /* IPv6 tlv */ - lsp_print_mt_ipv6_reach(lsp->tlv_data.ipv6_reachs, vty, - ISIS_MT_IPV4_UNICAST); - - /* MT IPv6 reachability tlv */ - for (ALL_LIST_ELEMENTS_RO(lsp->tlv_data.mt_ipv6_reachs, lnode, - mt_ipv6_reachs)) - lsp_print_mt_ipv6_reach(mt_ipv6_reachs->list, vty, - mt_ipv6_reachs->mtid); - - /* TE IS neighbor tlv */ - lsp_print_mt_reach(lsp->tlv_data.te_is_neighs, vty, dynhost, - ISIS_MT_IPV4_UNICAST); - - /* MT IS neighbor tlv */ - for (ALL_LIST_ELEMENTS_RO(lsp->tlv_data.mt_is_neighs, lnode, - mt_is_neigh)) - lsp_print_mt_reach(mt_is_neigh->list, vty, dynhost, - mt_is_neigh->mtid); - - /* TE IPv4 tlv */ - lsp_print_mt_ipv4_reach(lsp->tlv_data.te_ipv4_reachs, vty, - ISIS_MT_IPV4_UNICAST); - - /* MT IPv4 reachability tlv */ - for (ALL_LIST_ELEMENTS_RO(lsp->tlv_data.mt_ipv4_reachs, lnode, - mt_ipv4_reachs)) - lsp_print_mt_ipv4_reach(mt_ipv4_reachs->list, vty, - mt_ipv4_reachs->mtid); - + if (lsp->tlvs) + vty_multiline(vty, " ", "%s", isis_format_tlvs(lsp->tlvs)); vty_out(vty, "\n"); - - return; } /* print all the lsps info in the local lspdb */ @@ -1026,85 +677,6 @@ int lsp_print_all(struct vty *vty, dict_t *lspdb, char detail, char dynhost) return lsp_count; } -static void _lsp_tlv_fit(struct isis_lsp *lsp, struct list **from, - struct list **to, int frag_thold, - unsigned int tlv_build_func(struct list *, - struct stream *, - void *arg), - void *arg) -{ - while (*from && listcount(*from)) { - unsigned int count; - - count = tlv_build_func(*from, lsp->pdu, arg); - - if (listcount(*to) != 0 || count != listcount(*from)) { - struct listnode *node, *nnode; - void *elem; - - for (ALL_LIST_ELEMENTS(*from, node, nnode, elem)) { - if (!count) - break; - listnode_add(*to, elem); - list_delete_node(*from, node); - --count; - } - } else { - list_free(*to); - *to = *from; - *from = NULL; - } - } -} - -#define FRAG_THOLD(S, T) ((STREAM_SIZE(S) * T) / 100) - -/* stream*, area->lsp_frag_threshold, increment */ -#define FRAG_NEEDED(S, T, I) \ - (STREAM_SIZE(S) - STREAM_REMAIN(S) + (I) > FRAG_THOLD(S, T)) - -/* FIXME: It shouldn't be necessary to pass tlvsize here, TLVs can have - * variable length (TE TLVs, sub TLVs). */ -static void lsp_tlv_fit(struct isis_lsp *lsp, struct list **from, - struct list **to, int tlvsize, int frag_thold, - int tlv_build_func(struct list *, struct stream *)) -{ - int count, i; - - /* can we fit all ? */ - if (!FRAG_NEEDED(lsp->pdu, frag_thold, - listcount(*from) * tlvsize + 2)) { - tlv_build_func(*from, lsp->pdu); - if (listcount(*to) != 0) { - struct listnode *node, *nextnode; - void *elem; - - for (ALL_LIST_ELEMENTS(*from, node, nextnode, elem)) { - listnode_add(*to, elem); - list_delete_node(*from, node); - } - } else { - list_free(*to); - *to = *from; - *from = NULL; - } - } else if (!FRAG_NEEDED(lsp->pdu, frag_thold, tlvsize + 2)) { - /* fit all we can */ - count = FRAG_THOLD(lsp->pdu, frag_thold) - 2 - - (STREAM_SIZE(lsp->pdu) - STREAM_REMAIN(lsp->pdu)); - count = count / tlvsize; - if (count > (int)listcount(*from)) - count = listcount(*from); - for (i = 0; i < count; i++) { - listnode_add(*to, listgetdata(listhead(*from))); - listnode_delete(*from, listgetdata(listhead(*from))); - } - tlv_build_func(*to, lsp->pdu); - } - lsp->lsp_header->pdu_len = htons(stream_get_endp(lsp->pdu)); - return; -} - static u_int16_t lsp_rem_lifetime(struct isis_area *area, int level) { u_int16_t rem_lifetime; @@ -1147,155 +719,90 @@ static u_int16_t lsp_refresh_time(struct isis_lsp *lsp, u_int16_t rem_lifetime) return refresh_time; } -static struct isis_lsp *lsp_next_frag(u_char frag_num, struct isis_lsp *lsp0, - struct isis_area *area, int level) -{ - struct isis_lsp *lsp; - u_char frag_id[ISIS_SYS_ID_LEN + 2]; - - memcpy(frag_id, lsp0->lsp_header->lsp_id, ISIS_SYS_ID_LEN + 1); - LSP_FRAGMENT(frag_id) = frag_num; - /* FIXME add authentication TLV for fragment LSPs */ - lsp = lsp_search(frag_id, area->lspdb[level - 1]); - if (lsp) { - /* Clear the TLVs */ - lsp_clear_data(lsp); - return lsp; - } - lsp = lsp_new(area, frag_id, ntohs(lsp0->lsp_header->rem_lifetime), 0, - lsp_bits_generate(level, area->overload_bit, - area->attached_bit), - 0, level); - lsp->area = area; - lsp->own_lsp = 1; - lsp_insert(lsp, area->lspdb[level - 1]); - listnode_add(lsp0->lspu.frags, lsp); - lsp->lspu.zero_lsp = lsp0; - return lsp; -} - static void lsp_build_ext_reach_ipv4(struct isis_lsp *lsp, - struct isis_area *area, - struct tlvs *tlv_data) + struct isis_area *area) { - struct route_table *er_table; - struct route_node *rn; - struct prefix_ipv4 *ipv4; - struct isis_ext_info *info; - struct ipv4_reachability *ipreach; - struct te_ipv4_reachability *te_ipreach; - - er_table = get_ext_reach(area, AF_INET, lsp->level); + struct route_table *er_table = get_ext_reach(area, AF_INET, lsp->level); if (!er_table) return; - for (rn = route_top(er_table); rn; rn = route_next(rn)) { + for (struct route_node *rn = route_top(er_table); rn; + rn = route_next(rn)) { if (!rn->info) continue; - ipv4 = (struct prefix_ipv4 *)&rn->p; - info = rn->info; - if (area->oldmetric) { - if (tlv_data->ipv4_ext_reachs == NULL) { - tlv_data->ipv4_ext_reachs = list_new(); - tlv_data->ipv4_ext_reachs->del = free_tlv; - } - ipreach = XMALLOC(MTYPE_ISIS_TLV, sizeof(*ipreach)); - - ipreach->prefix.s_addr = ipv4->prefix.s_addr; - masklen2ip(ipv4->prefixlen, &ipreach->mask); - ipreach->prefix.s_addr &= ipreach->mask.s_addr; - - if ((info->metric & 0x3f) != info->metric) - ipreach->metrics.metric_default = 0x3f; - else - ipreach->metrics.metric_default = info->metric; - ipreach->metrics.metric_expense = METRICS_UNSUPPORTED; - ipreach->metrics.metric_error = METRICS_UNSUPPORTED; - ipreach->metrics.metric_delay = METRICS_UNSUPPORTED; - listnode_add(tlv_data->ipv4_ext_reachs, ipreach); - } - if (area->newmetric) { - if (tlv_data->te_ipv4_reachs == NULL) { - tlv_data->te_ipv4_reachs = list_new(); - tlv_data->te_ipv4_reachs->del = free_tlv; - } - te_ipreach = XCALLOC(MTYPE_ISIS_TLV, - sizeof(*te_ipreach) - 1 - + PSIZE(ipv4->prefixlen)); - if (info->metric > MAX_WIDE_PATH_METRIC) - te_ipreach->te_metric = - htonl(MAX_WIDE_PATH_METRIC); - else - te_ipreach->te_metric = htonl(info->metric); - te_ipreach->control = ipv4->prefixlen & 0x3f; - memcpy(&te_ipreach->prefix_start, &ipv4->prefix.s_addr, - PSIZE(ipv4->prefixlen)); - listnode_add(tlv_data->te_ipv4_reachs, te_ipreach); - } - } -} + struct prefix_ipv4 *ipv4 = (struct prefix_ipv4 *)&rn->p; + struct isis_ext_info *info = rn->info; -static struct list *tlv_get_ipv6_reach_list(struct isis_area *area, - struct tlvs *tlv_data) -{ - uint16_t mtid = isis_area_ipv6_topology(area); - if (mtid == ISIS_MT_IPV4_UNICAST) { - if (!tlv_data->ipv6_reachs) { - tlv_data->ipv6_reachs = list_new(); - tlv_data->ipv6_reachs->del = free_tlv; - } - return tlv_data->ipv6_reachs; - } + uint32_t metric = info->metric; + if (metric > MAX_WIDE_PATH_METRIC) + metric = MAX_WIDE_PATH_METRIC; + if (area->oldmetric && metric > 0x3f) + metric = 0x3f; - struct tlv_mt_ipv6_reachs *reachs = - tlvs_get_mt_ipv6_reachs(tlv_data, mtid); - return reachs->list; + if (area->oldmetric) + isis_tlvs_add_oldstyle_ip_reach(lsp->tlvs, ipv4, + metric); + if (area->newmetric) + isis_tlvs_add_extended_ip_reach(lsp->tlvs, ipv4, + metric); + } } static void lsp_build_ext_reach_ipv6(struct isis_lsp *lsp, - struct isis_area *area, - struct tlvs *tlv_data) + struct isis_area *area) { - struct route_table *er_table; - struct route_node *rn; - struct prefix_ipv6 *ipv6; - struct isis_ext_info *info; - struct ipv6_reachability *ip6reach; - struct list *reach_list = NULL; - - er_table = get_ext_reach(area, AF_INET6, lsp->level); + struct route_table *er_table = + get_ext_reach(area, AF_INET6, lsp->level); if (!er_table) return; - for (rn = route_top(er_table); rn; rn = route_next(rn)) { + for (struct route_node *rn = route_top(er_table); rn; + rn = route_next(rn)) { if (!rn->info) continue; - ipv6 = (struct prefix_ipv6 *)&rn->p; - info = rn->info; + struct prefix_ipv6 *ipv6 = (struct prefix_ipv6 *)&rn->p; + struct isis_ext_info *info = rn->info; - if (!reach_list) - reach_list = tlv_get_ipv6_reach_list(area, tlv_data); - - ip6reach = XCALLOC(MTYPE_ISIS_TLV, sizeof(*ip6reach)); + uint32_t metric = info->metric; if (info->metric > MAX_WIDE_PATH_METRIC) - ip6reach->metric = htonl(MAX_WIDE_PATH_METRIC); - else - ip6reach->metric = htonl(info->metric); - ip6reach->control_info = DISTRIBUTION_EXTERNAL; - ip6reach->prefix_len = ipv6->prefixlen; - memcpy(ip6reach->prefix, ipv6->prefix.s6_addr, - sizeof(ip6reach->prefix)); - listnode_add(reach_list, ip6reach); + metric = MAX_WIDE_PATH_METRIC; + isis_tlvs_add_ipv6_reach( + lsp->tlvs, isis_area_ipv6_topology(area), ipv6, metric); } } -static void lsp_build_ext_reach(struct isis_lsp *lsp, struct isis_area *area, - struct tlvs *tlv_data) +static void lsp_build_ext_reach(struct isis_lsp *lsp, struct isis_area *area) { - lsp_build_ext_reach_ipv4(lsp, area, tlv_data); - lsp_build_ext_reach_ipv6(lsp, area, tlv_data); + lsp_build_ext_reach_ipv4(lsp, area); + lsp_build_ext_reach_ipv6(lsp, area); +} + +static struct isis_lsp *lsp_next_frag(uint8_t frag_num, struct isis_lsp *lsp0, + struct isis_area *area, int level) +{ + struct isis_lsp *lsp; + uint8_t frag_id[ISIS_SYS_ID_LEN + 2]; + + memcpy(frag_id, lsp0->hdr.lsp_id, ISIS_SYS_ID_LEN + 1); + LSP_FRAGMENT(frag_id) = frag_num; + + lsp = lsp_search(frag_id, area->lspdb[level - 1]); + if (lsp) { + lsp_clear_data(lsp); + return lsp; + } + + lsp = lsp_new(area, frag_id, lsp0->hdr.rem_lifetime, 0, + lsp_bits_generate(level, area->overload_bit, + area->attached_bit), + 0, level); + lsp->own_lsp = 1; + lsp_insert(lsp, area->lspdb[level - 1]); + listnode_add(lsp0->lspu.frags, lsp); + lsp->lspu.zero_lsp = lsp0; + return lsp; } /* @@ -1304,126 +811,69 @@ static void lsp_build_ext_reach(struct isis_lsp *lsp, struct isis_area *area, */ static void lsp_build(struct isis_lsp *lsp, struct isis_area *area) { - struct is_neigh *is_neigh; - struct te_is_neigh *te_is_neigh; - struct listnode *node, *ipnode; int level = lsp->level; - struct isis_circuit *circuit; - struct prefix_ipv4 *ipv4; - struct ipv4_reachability *ipreach; - struct te_ipv4_reachability *te_ipreach; - struct isis_adjacency *nei; - struct prefix_ipv6 *ipv6, ip6prefix; - struct list *ipv6_reachs = NULL; - struct ipv6_reachability *ip6reach; - struct tlvs tlv_data; - struct isis_lsp *lsp0 = lsp; - struct in_addr *routerid; - uint32_t expected = 0, found = 0; - uint32_t metric; - u_char zero_id[ISIS_SYS_ID_LEN + 1]; - int retval = ISIS_OK; - char buf[BUFSIZ]; + char buf[PREFIX2STR_BUFFER]; + struct listnode *node; + struct isis_lsp *frag; + + lsp_clear_data(lsp); + for (ALL_LIST_ELEMENTS_RO(lsp->lspu.frags, node, frag)) + lsp_clear_data(frag); + lsp->tlvs = isis_alloc_tlvs(); lsp_debug("ISIS (%s): Constructing local system LSP for level %d", area->area_tag, level); - /* - * Building the zero lsp - */ - memset(zero_id, 0, ISIS_SYS_ID_LEN + 1); - - /* Reset stream endp. Stream is always there and on every LSP refresh - * only - * TLV part of it is overwritten. So we must seek past header we will - * not - * touch. */ - stream_reset(lsp->pdu); - stream_forward_endp(lsp->pdu, ISIS_FIXED_HDR_LEN + ISIS_LSP_HDR_LEN); + lsp->hdr.lsp_bits = lsp_bits_generate(level, area->overload_bit, + area->attached_bit); - /* - * Add the authentication info if its present - */ - lsp_auth_add(lsp); + lsp_add_auth(lsp); - /* - * First add the tlvs related to area - */ - - /* Area addresses */ - if (lsp->tlv_data.area_addrs == NULL) - lsp->tlv_data.area_addrs = list_new(); - list_add_list(lsp->tlv_data.area_addrs, area->area_addrs); - if (listcount(lsp->tlv_data.area_addrs) > 0) - tlv_add_area_addrs(lsp->tlv_data.area_addrs, lsp->pdu); + isis_tlvs_add_area_addresses(lsp->tlvs, area->area_addrs); /* Protocols Supported */ if (area->ip_circuits > 0 || area->ipv6_circuits > 0) { - lsp->tlv_data.nlpids = - XCALLOC(MTYPE_ISIS_TLV, sizeof(struct nlpids)); - lsp->tlv_data.nlpids->count = 0; + struct nlpids nlpids = {.count = 0}; if (area->ip_circuits > 0) { lsp_debug( "ISIS (%s): Found IPv4 circuit, adding IPv4 to NLPIDs", area->area_tag); - lsp->tlv_data.nlpids->count++; - lsp->tlv_data.nlpids->nlpids[0] = NLPID_IP; + nlpids.nlpids[nlpids.count] = NLPID_IP; + nlpids.count++; } if (area->ipv6_circuits > 0) { lsp_debug( "ISIS (%s): Found IPv6 circuit, adding IPv6 to NLPIDs", area->area_tag); - lsp->tlv_data.nlpids->count++; - lsp->tlv_data.nlpids - ->nlpids[lsp->tlv_data.nlpids->count - 1] = - NLPID_IPV6; + nlpids.nlpids[nlpids.count] = NLPID_IPV6; + nlpids.count++; } - tlv_add_nlpid(lsp->tlv_data.nlpids, lsp->pdu); + isis_tlvs_set_protocols_supported(lsp->tlvs, &nlpids); } if (area_is_mt(area)) { lsp_debug("ISIS (%s): Adding MT router tlv...", area->area_tag); - lsp->tlv_data.mt_router_info = list_new(); - lsp->tlv_data.mt_router_info->del = free_tlv; struct isis_area_mt_setting **mt_settings; unsigned int mt_count; mt_settings = area_mt_settings(area, &mt_count); for (unsigned int i = 0; i < mt_count; i++) { - struct mt_router_info *info; - - info = XCALLOC(MTYPE_ISIS_TLV, sizeof(*info)); - info->mtid = mt_settings[i]->mtid; - info->overload = mt_settings[i]->overload; - listnode_add(lsp->tlv_data.mt_router_info, info); + isis_tlvs_add_mt_router_info( + lsp->tlvs, mt_settings[i]->mtid, + mt_settings[i]->overload, false); lsp_debug("ISIS (%s): MT %s", area->area_tag, - isis_mtid2str(info->mtid)); + isis_mtid2str(mt_settings[i]->mtid)); } - tlv_add_mt_router_info(lsp->tlv_data.mt_router_info, lsp->pdu); } else { lsp_debug("ISIS (%s): Not adding MT router tlv (disabled)", area->area_tag); } /* Dynamic Hostname */ if (area->dynhostname) { - const char *hostname = unix_hostname(); - size_t hostname_len = strlen(hostname); - - lsp->tlv_data.hostname = - XMALLOC(MTYPE_ISIS_TLV, sizeof(struct hostname)); - - strncpy((char *)lsp->tlv_data.hostname->name, hostname, - sizeof(lsp->tlv_data.hostname->name)); - if (hostname_len <= MAX_TLV_LEN) - lsp->tlv_data.hostname->namelen = hostname_len; - else - lsp->tlv_data.hostname->namelen = MAX_TLV_LEN; - - lsp_debug("ISIS (%s): Adding dynamic hostname '%.*s'", - area->area_tag, lsp->tlv_data.hostname->namelen, - lsp->tlv_data.hostname->name); - tlv_add_dynamic_hostname(lsp->tlv_data.hostname, lsp->pdu); + isis_tlvs_set_dynamic_hostname(lsp->tlvs, unix_hostname()); + lsp_debug("ISIS (%s): Adding dynamic hostname '%s'", + area->area_tag, unix_hostname()); } else { lsp_debug("ISIS (%s): Not adding dynamic hostname (disabled)", area->area_tag); @@ -1434,45 +884,31 @@ static void lsp_build(struct isis_lsp *lsp, struct isis_area *area) * into * LSP and this address is same as router id. */ if (isis->router_id != 0) { - inet_ntop(AF_INET, &isis->router_id, buf, sizeof(buf)); + struct in_addr id = {.s_addr = isis->router_id}; + inet_ntop(AF_INET, &id, buf, sizeof(buf)); lsp_debug("ISIS (%s): Adding router ID %s as IPv4 tlv.", area->area_tag, buf); - if (lsp->tlv_data.ipv4_addrs == NULL) { - lsp->tlv_data.ipv4_addrs = list_new(); - lsp->tlv_data.ipv4_addrs->del = free_tlv; - } - - routerid = XMALLOC(MTYPE_ISIS_TLV, sizeof(struct in_addr)); - routerid->s_addr = isis->router_id; - listnode_add(lsp->tlv_data.ipv4_addrs, routerid); - tlv_add_in_addr(routerid, lsp->pdu, IPV4_ADDR); + isis_tlvs_add_ipv4_address(lsp->tlvs, &id); /* Exactly same data is put into TE router ID TLV, but only if * new style * TLV's are in use. */ if (area->newmetric) { + lsp_debug( "ISIS (%s): Adding router ID also as TE router ID tlv.", area->area_tag); - lsp->tlv_data.router_id = - XMALLOC(MTYPE_ISIS_TLV, sizeof(struct in_addr)); - lsp->tlv_data.router_id->id.s_addr = isis->router_id; - tlv_add_in_addr(&lsp->tlv_data.router_id->id, lsp->pdu, - TE_ROUTER_ID); + isis_tlvs_set_te_router_id(lsp->tlvs, &id); } } else { lsp_debug("ISIS (%s): Router ID is unset. Not adding tlv.", area->area_tag); } - memset(&tlv_data, 0, sizeof(struct tlvs)); - lsp_debug("ISIS (%s): Adding circuit specific information.", area->area_tag); - /* - * Then build lists of tlvs related to circuits - */ + struct isis_circuit *circuit; for (ALL_LIST_ELEMENTS_RO(area->circuit_list, node, circuit)) { if (!circuit->interface) lsp_debug( @@ -1492,245 +928,94 @@ static void lsp_build(struct isis_lsp *lsp, struct isis_area *area) continue; } - /* - * Add IPv4 internal reachability of this circuit - */ + uint32_t metric = area->oldmetric + ? circuit->metric[level - 1] + : circuit->te_metric[level - 1]; + if (circuit->ip_router && circuit->ip_addrs && circuit->ip_addrs->count > 0) { lsp_debug( "ISIS (%s): Circuit has IPv4 active, adding respective TLVs.", area->area_tag); - if (area->oldmetric) { - if (tlv_data.ipv4_int_reachs == NULL) { - tlv_data.ipv4_int_reachs = list_new(); - tlv_data.ipv4_int_reachs->del = - free_tlv; - } - for (ALL_LIST_ELEMENTS_RO(circuit->ip_addrs, - ipnode, ipv4)) { - ipreach = XMALLOC( - MTYPE_ISIS_TLV, - sizeof(struct - ipv4_reachability)); - ipreach->metrics.metric_default = - circuit->metric[level - 1]; - ipreach->metrics.metric_expense = - METRICS_UNSUPPORTED; - ipreach->metrics.metric_error = - METRICS_UNSUPPORTED; - ipreach->metrics.metric_delay = - METRICS_UNSUPPORTED; - masklen2ip(ipv4->prefixlen, - &ipreach->mask); - ipreach->prefix.s_addr = - ((ipreach->mask.s_addr) - & (ipv4->prefix.s_addr)); - inet_ntop(AF_INET, - &ipreach->prefix.s_addr, buf, - sizeof(buf)); + struct listnode *ipnode; + struct prefix_ipv4 *ipv4; + for (ALL_LIST_ELEMENTS_RO(circuit->ip_addrs, ipnode, + ipv4)) { + if (area->oldmetric) { lsp_debug( - "ISIS (%s): Adding old-style IP reachability for %s/%d", - area->area_tag, buf, - ipv4->prefixlen); - listnode_add(tlv_data.ipv4_int_reachs, - ipreach); - } - } - if (area->newmetric) { - if (tlv_data.te_ipv4_reachs == NULL) { - tlv_data.te_ipv4_reachs = list_new(); - tlv_data.te_ipv4_reachs->del = free_tlv; + "ISIS (%s): Adding old-style IP reachability for %s", + area->area_tag, + prefix2str(ipv4, buf, + sizeof(buf))); + isis_tlvs_add_oldstyle_ip_reach( + lsp->tlvs, ipv4, metric); } - for (ALL_LIST_ELEMENTS_RO(circuit->ip_addrs, - ipnode, ipv4)) { - /* FIXME All this assumes that we have - * no sub TLVs. */ - te_ipreach = XCALLOC( - MTYPE_ISIS_TLV, - sizeof(struct - te_ipv4_reachability) - + ((ipv4->prefixlen + 7) - / 8) - - 1); - - if (area->oldmetric) - te_ipreach->te_metric = htonl( - circuit->metric[level - - 1]); - else - te_ipreach->te_metric = htonl( - circuit->te_metric - [level - 1]); - - te_ipreach->control = - (ipv4->prefixlen & 0x3F); - memcpy(&te_ipreach->prefix_start, - &ipv4->prefix.s_addr, - (ipv4->prefixlen + 7) / 8); - inet_ntop(AF_INET, &ipv4->prefix.s_addr, - buf, sizeof(buf)); + + if (area->newmetric) { lsp_debug( - "ISIS (%s): Adding te-style IP reachability for %s/%d", - area->area_tag, buf, - ipv4->prefixlen); - listnode_add(tlv_data.te_ipv4_reachs, - te_ipreach); + "ISIS (%s): Adding te-style IP reachability for %s", + area->area_tag, + prefix2str(ipv4, buf, + sizeof(buf))); + isis_tlvs_add_extended_ip_reach( + lsp->tlvs, ipv4, metric); } } } - /* - * Add IPv6 reachability of this circuit - */ if (circuit->ipv6_router && circuit->ipv6_non_link && circuit->ipv6_non_link->count > 0) { - if (!ipv6_reachs) - ipv6_reachs = tlv_get_ipv6_reach_list( - area, &tlv_data); - + struct listnode *ipnode; + struct prefix_ipv6 *ipv6; for (ALL_LIST_ELEMENTS_RO(circuit->ipv6_non_link, ipnode, ipv6)) { - ip6reach = XCALLOC( - MTYPE_ISIS_TLV, - sizeof(struct ipv6_reachability)); - - if (area->oldmetric) - ip6reach->metric = htonl( - circuit->metric[level - 1]); - else - ip6reach->metric = htonl( - circuit->te_metric[level - 1]); - - ip6reach->control_info = 0; - ip6reach->prefix_len = ipv6->prefixlen; - memcpy(&ip6prefix, ipv6, sizeof(ip6prefix)); - apply_mask_ipv6(&ip6prefix); - - inet_ntop(AF_INET6, &ip6prefix.prefix.s6_addr, - buf, sizeof(buf)); lsp_debug( - "ISIS (%s): Adding IPv6 reachability for %s/%d", - area->area_tag, buf, ipv6->prefixlen); - - memcpy(ip6reach->prefix, - ip6prefix.prefix.s6_addr, - sizeof(ip6reach->prefix)); - listnode_add(ipv6_reachs, ip6reach); + "ISIS (%s): Adding IPv6 reachability for %s", + area->area_tag, + prefix2str(ipv6, buf, sizeof(buf))); + isis_tlvs_add_ipv6_reach( + lsp->tlvs, + isis_area_ipv6_topology(area), ipv6, + metric); } } switch (circuit->circ_type) { case CIRCUIT_T_BROADCAST: if (level & circuit->is_type) { - if (area->oldmetric) { - if (tlv_data.is_neighs == NULL) { - tlv_data.is_neighs = list_new(); - tlv_data.is_neighs->del = - free_tlv; - } - is_neigh = XCALLOC( - MTYPE_ISIS_TLV, - sizeof(struct is_neigh)); - if (level == IS_LEVEL_1) - memcpy(is_neigh->neigh_id, - circuit->u.bc - .l1_desig_is, - ISIS_SYS_ID_LEN + 1); - else - memcpy(is_neigh->neigh_id, - circuit->u.bc - .l2_desig_is, - ISIS_SYS_ID_LEN + 1); - is_neigh->metrics.metric_default = - circuit->metric[level - 1]; - is_neigh->metrics.metric_expense = - METRICS_UNSUPPORTED; - is_neigh->metrics.metric_error = - METRICS_UNSUPPORTED; - is_neigh->metrics.metric_delay = - METRICS_UNSUPPORTED; - if (!memcmp(is_neigh->neigh_id, zero_id, - ISIS_SYS_ID_LEN + 1)) { - XFREE(MTYPE_ISIS_TLV, is_neigh); - lsp_debug( - "ISIS (%s): No DIS for circuit, not adding old-style IS neighbor.", - area->area_tag); - } else { - listnode_add(tlv_data.is_neighs, - is_neigh); + uint8_t *ne_id = + (level == IS_LEVEL_1) + ? circuit->u.bc.l1_desig_is + : circuit->u.bc.l2_desig_is; + + if (LSP_PSEUDO_ID(ne_id)) { + if (area->oldmetric) { lsp_debug( "ISIS (%s): Adding DIS %s.%02x as old-style neighbor", area->area_tag, - sysid_print( - is_neigh->neigh_id), - LSP_PSEUDO_ID( - is_neigh->neigh_id)); - } - } - if (area->newmetric) { - if (tlv_data.te_is_neighs == NULL) { - tlv_data.te_is_neighs = - list_new(); - tlv_data.te_is_neighs->del = - free_tlv; + sysid_print(ne_id), + LSP_PSEUDO_ID(ne_id)); + isis_tlvs_add_oldstyle_reach( + lsp->tlvs, ne_id, + metric); } - te_is_neigh = XCALLOC( - MTYPE_ISIS_TLV, - sizeof(struct te_is_neigh)); - if (level == IS_LEVEL_1) - memcpy(te_is_neigh->neigh_id, - circuit->u.bc - .l1_desig_is, - ISIS_SYS_ID_LEN + 1); - else - memcpy(te_is_neigh->neigh_id, - circuit->u.bc - .l2_desig_is, - ISIS_SYS_ID_LEN + 1); - if (area->oldmetric) - metric = circuit->metric[level - - 1]; - else - metric = - circuit->te_metric[level - - 1]; - SET_TE_METRIC(te_is_neigh, metric); - if (!memcmp(te_is_neigh->neigh_id, - zero_id, - ISIS_SYS_ID_LEN + 1)) { - XFREE(MTYPE_ISIS_TLV, - te_is_neigh); - lsp_debug( - "ISIS (%s): No DIS for circuit, not adding te-style IS neighbor.", - area->area_tag); - } else { - /* Check if MPLS_TE is activate - */ + if (area->newmetric) { + uint8_t subtlvs[256]; + uint8_t subtlv_len; + if (IS_MPLS_TE(isisMplsTE) && HAS_LINK_PARAMS( circuit->interface)) - /* Add SubTLVs & Adjust - * real size of SubTLVs - */ - te_is_neigh - ->sub_tlvs_length = add_te_subtlvs( - te_is_neigh - ->sub_tlvs, + subtlv_len = add_te_subtlvs( + subtlvs, circuit->mtc); else - /* Or keep only TE - * metric with no - * SubTLVs if MPLS_TE is - * off */ - te_is_neigh - ->sub_tlvs_length = - 0; + subtlv_len = 0; tlvs_add_mt_bcast( - &tlv_data, circuit, - level, te_is_neigh); - XFREE(MTYPE_ISIS_TLV, - te_is_neigh); + lsp->tlvs, circuit, + level, ne_id, metric, + subtlvs, subtlv_len); } } } else { @@ -1739,53 +1024,25 @@ static void lsp_build(struct isis_lsp *lsp, struct isis_area *area) area->area_tag); } break; - case CIRCUIT_T_P2P: - nei = circuit->u.p2p.neighbor; + case CIRCUIT_T_P2P: { + struct isis_adjacency *nei = circuit->u.p2p.neighbor; if (nei && (level & nei->circuit_t)) { + uint8_t ne_id[7]; + memcpy(ne_id, nei->sysid, ISIS_SYS_ID_LEN); + LSP_PSEUDO_ID(ne_id) = 0; + if (area->oldmetric) { - if (tlv_data.is_neighs == NULL) { - tlv_data.is_neighs = list_new(); - tlv_data.is_neighs->del = - free_tlv; - } - is_neigh = XCALLOC( - MTYPE_ISIS_TLV, - sizeof(struct is_neigh)); - memcpy(is_neigh->neigh_id, nei->sysid, - ISIS_SYS_ID_LEN); - is_neigh->metrics.metric_default = - circuit->metric[level - 1]; - is_neigh->metrics.metric_expense = - METRICS_UNSUPPORTED; - is_neigh->metrics.metric_error = - METRICS_UNSUPPORTED; - is_neigh->metrics.metric_delay = - METRICS_UNSUPPORTED; - listnode_add(tlv_data.is_neighs, - is_neigh); lsp_debug( "ISIS (%s): Adding old-style is reach for %s", area->area_tag, - sysid_print( - is_neigh->neigh_id)); + sysid_print(ne_id)); + isis_tlvs_add_oldstyle_reach( + lsp->tlvs, ne_id, metric); } if (area->newmetric) { - uint32_t metric; + uint8_t subtlvs[256]; + uint8_t subtlv_len; - if (tlv_data.te_is_neighs == NULL) { - tlv_data.te_is_neighs = - list_new(); - tlv_data.te_is_neighs->del = - free_tlv; - } - te_is_neigh = XCALLOC( - MTYPE_ISIS_TLV, - sizeof(struct te_is_neigh)); - memcpy(te_is_neigh->neigh_id, - nei->sysid, ISIS_SYS_ID_LEN); - metric = circuit->te_metric[level - 1]; - SET_TE_METRIC(te_is_neigh, metric); - /* Check if MPLS_TE is activate */ if (IS_MPLS_TE(isisMplsTE) && HAS_LINK_PARAMS( circuit->interface)) @@ -1804,28 +1061,24 @@ static void lsp_build(struct isis_lsp *lsp, struct isis_area *area) /* Add SubTLVs & Adjust real * size of SubTLVs */ - te_is_neigh->sub_tlvs_length = - add_te_subtlvs( - te_is_neigh - ->sub_tlvs, - circuit->mtc); + subtlv_len = add_te_subtlvs( + subtlvs, circuit->mtc); else /* Or keep only TE metric with * no SubTLVs if MPLS_TE is off */ - te_is_neigh->sub_tlvs_length = - 0; + subtlv_len = 0; - tlvs_add_mt_p2p(&tlv_data, circuit, - te_is_neigh); - XFREE(MTYPE_ISIS_TLV, te_is_neigh); + tlvs_add_mt_p2p(lsp->tlvs, circuit, + ne_id, metric, subtlvs, + subtlv_len); } } else { lsp_debug( "ISIS (%s): No adjacency for given level on this circuit. Not adding IS neighbors", area->area_tag); } - break; + } break; case CIRCUIT_T_LOOPBACK: break; default: @@ -1833,169 +1086,36 @@ static void lsp_build(struct isis_lsp *lsp, struct isis_area *area) } } - lsp_build_ext_reach(lsp, area, &tlv_data); - - lsp_debug("ISIS (%s): LSP construction is complete. Serializing...", - area->area_tag); - - while (tlv_data.ipv4_int_reachs - && listcount(tlv_data.ipv4_int_reachs)) { - if (lsp->tlv_data.ipv4_int_reachs == NULL) - lsp->tlv_data.ipv4_int_reachs = list_new(); - lsp_tlv_fit(lsp, &tlv_data.ipv4_int_reachs, - &lsp->tlv_data.ipv4_int_reachs, IPV4_REACH_LEN, - area->lsp_frag_threshold, tlv_add_ipv4_int_reachs); - if (tlv_data.ipv4_int_reachs - && listcount(tlv_data.ipv4_int_reachs)) - lsp = lsp_next_frag( - LSP_FRAGMENT(lsp->lsp_header->lsp_id) + 1, lsp0, - area, level); - } - - while (tlv_data.ipv4_ext_reachs - && listcount(tlv_data.ipv4_ext_reachs)) { - if (lsp->tlv_data.ipv4_ext_reachs == NULL) - lsp->tlv_data.ipv4_ext_reachs = list_new(); - lsp_tlv_fit(lsp, &tlv_data.ipv4_ext_reachs, - &lsp->tlv_data.ipv4_ext_reachs, IPV4_REACH_LEN, - area->lsp_frag_threshold, tlv_add_ipv4_ext_reachs); - if (tlv_data.ipv4_ext_reachs - && listcount(tlv_data.ipv4_ext_reachs)) - lsp = lsp_next_frag( - LSP_FRAGMENT(lsp->lsp_header->lsp_id) + 1, lsp0, - area, level); - } - - while (tlv_data.te_ipv4_reachs && listcount(tlv_data.te_ipv4_reachs)) { - if (lsp->tlv_data.te_ipv4_reachs == NULL) - lsp->tlv_data.te_ipv4_reachs = list_new(); - _lsp_tlv_fit(lsp, &tlv_data.te_ipv4_reachs, - &lsp->tlv_data.te_ipv4_reachs, - area->lsp_frag_threshold, tlv_add_te_ipv4_reachs, - NULL); - if (tlv_data.te_ipv4_reachs - && listcount(tlv_data.te_ipv4_reachs)) - lsp = lsp_next_frag( - LSP_FRAGMENT(lsp->lsp_header->lsp_id) + 1, lsp0, - area, level); - } - - struct tlv_mt_ipv4_reachs *mt_ipv4_reachs; - for (ALL_LIST_ELEMENTS_RO(tlv_data.mt_ipv4_reachs, node, - mt_ipv4_reachs)) { - while (mt_ipv4_reachs->list - && listcount(mt_ipv4_reachs->list)) { - struct tlv_mt_ipv4_reachs *frag_mt_ipv4_reachs; - - frag_mt_ipv4_reachs = tlvs_get_mt_ipv4_reachs( - &lsp->tlv_data, mt_ipv4_reachs->mtid); - _lsp_tlv_fit(lsp, &mt_ipv4_reachs->list, - &frag_mt_ipv4_reachs->list, - area->lsp_frag_threshold, - tlv_add_te_ipv4_reachs, - &mt_ipv4_reachs->mtid); - if (mt_ipv4_reachs->list - && listcount(mt_ipv4_reachs->list)) - lsp = lsp_next_frag( - LSP_FRAGMENT(lsp->lsp_header->lsp_id) - + 1, - lsp0, area, level); - } - } - - while (tlv_data.ipv6_reachs && listcount(tlv_data.ipv6_reachs)) { - if (lsp->tlv_data.ipv6_reachs == NULL) - lsp->tlv_data.ipv6_reachs = list_new(); - _lsp_tlv_fit( - lsp, &tlv_data.ipv6_reachs, &lsp->tlv_data.ipv6_reachs, - area->lsp_frag_threshold, tlv_add_ipv6_reachs, NULL); - if (tlv_data.ipv6_reachs && listcount(tlv_data.ipv6_reachs)) - lsp = lsp_next_frag( - LSP_FRAGMENT(lsp->lsp_header->lsp_id) + 1, lsp0, - area, level); - } + lsp_build_ext_reach(lsp, area); - struct tlv_mt_ipv6_reachs *mt_ipv6_reachs; - for (ALL_LIST_ELEMENTS_RO(tlv_data.mt_ipv6_reachs, node, - mt_ipv6_reachs)) { - while (mt_ipv6_reachs->list - && listcount(mt_ipv6_reachs->list)) { - struct tlv_mt_ipv6_reachs *frag_mt_ipv6_reachs; - - frag_mt_ipv6_reachs = tlvs_get_mt_ipv6_reachs( - &lsp->tlv_data, mt_ipv6_reachs->mtid); - _lsp_tlv_fit(lsp, &mt_ipv6_reachs->list, - &frag_mt_ipv6_reachs->list, - area->lsp_frag_threshold, - tlv_add_ipv6_reachs, - &mt_ipv6_reachs->mtid); - if (mt_ipv6_reachs->list - && listcount(mt_ipv6_reachs->list)) - lsp = lsp_next_frag( - LSP_FRAGMENT(lsp->lsp_header->lsp_id) - + 1, - lsp0, area, level); - } - } + struct isis_tlvs *tlvs = lsp->tlvs; + lsp->tlvs = NULL; - while (tlv_data.is_neighs && listcount(tlv_data.is_neighs)) { - if (lsp->tlv_data.is_neighs == NULL) - lsp->tlv_data.is_neighs = list_new(); - lsp_tlv_fit(lsp, &tlv_data.is_neighs, &lsp->tlv_data.is_neighs, - IS_NEIGHBOURS_LEN, area->lsp_frag_threshold, - tlv_add_is_neighs); - if (tlv_data.is_neighs && listcount(tlv_data.is_neighs)) - lsp = lsp_next_frag( - LSP_FRAGMENT(lsp->lsp_header->lsp_id) + 1, lsp0, - area, level); - } + lsp_pack_pdu(lsp); + size_t tlv_space = STREAM_WRITEABLE(lsp->pdu) - LLC_LEN; + lsp_clear_data(lsp); - while (tlv_data.te_is_neighs && listcount(tlv_data.te_is_neighs)) { - if (lsp->tlv_data.te_is_neighs == NULL) - lsp->tlv_data.te_is_neighs = list_new(); - _lsp_tlv_fit(lsp, &tlv_data.te_is_neighs, - &lsp->tlv_data.te_is_neighs, - area->lsp_frag_threshold, tlv_add_te_is_neighs, - NULL); - if (tlv_data.te_is_neighs && listcount(tlv_data.te_is_neighs)) - lsp = lsp_next_frag( - LSP_FRAGMENT(lsp->lsp_header->lsp_id) + 1, lsp0, - area, level); + struct list *fragments = isis_fragment_tlvs(tlvs, tlv_space); + if (!fragments) { + zlog_warn("BUG: could not fragment own LSP:"); + log_multiline(LOG_WARNING, " ", "%s", isis_format_tlvs(tlvs)); + isis_free_tlvs(tlvs); + return; } + isis_free_tlvs(tlvs); - struct tlv_mt_neighbors *mt_neighs; - for (ALL_LIST_ELEMENTS_RO(tlv_data.mt_is_neighs, node, mt_neighs)) { - while (mt_neighs->list && listcount(mt_neighs->list)) { - struct tlv_mt_neighbors *frag_mt_neighs; - - frag_mt_neighs = tlvs_get_mt_neighbors(&lsp->tlv_data, - mt_neighs->mtid); - _lsp_tlv_fit(lsp, &mt_neighs->list, - &frag_mt_neighs->list, - area->lsp_frag_threshold, - tlv_add_te_is_neighs, &mt_neighs->mtid); - if (mt_neighs->list && listcount(mt_neighs->list)) - lsp = lsp_next_frag( - LSP_FRAGMENT(lsp->lsp_header->lsp_id) - + 1, - lsp0, area, level); + frag = lsp; + for (ALL_LIST_ELEMENTS_RO(fragments, node, tlvs)) { + if (node != listhead(fragments)) { + frag = lsp_next_frag(LSP_FRAGMENT(frag->hdr.lsp_id) + 1, + lsp, area, level); } + frag->tlvs = tlvs; } - - lsp->lsp_header->pdu_len = htons(stream_get_endp(lsp->pdu)); - - free_tlvs(&tlv_data); - - /* Validate the LSP */ - retval = parse_tlvs(area->area_tag, - STREAM_DATA(lsp->pdu) + ISIS_FIXED_HDR_LEN - + ISIS_LSP_HDR_LEN, - stream_get_endp(lsp->pdu) - ISIS_FIXED_HDR_LEN - - ISIS_LSP_HDR_LEN, - &expected, &found, &tlv_data, NULL); - assert(retval == ISIS_OK); - + list_delete(fragments); + lsp_debug("ISIS (%s): LSP construction is complete. Serializing...", + area->area_tag); return; } @@ -2019,8 +1139,8 @@ int lsp_generate(struct isis_area *area, int level) oldlsp = lsp_search(lspid, area->lspdb[level - 1]); if (oldlsp) { /* FIXME: we should actually initiate a purge */ - seq_num = ntohl(oldlsp->lsp_header->seq_num); - lsp_search_and_destroy(oldlsp->lsp_header->lsp_id, + seq_num = oldlsp->hdr.seqno; + lsp_search_and_destroy(oldlsp->hdr.lsp_id, area->lspdb[level - 1]); } rem_lifetime = lsp_rem_lifetime(area, level); @@ -2035,7 +1155,7 @@ int lsp_generate(struct isis_area *area, int level) /* build_lsp_data (newlsp, area); */ lsp_build(newlsp, area); /* time to calculate our checksum */ - lsp_seqnum_update(newlsp); + lsp_seqno_update(newlsp); newlsp->last_generated = time(NULL); lsp_set_all_srmflags(newlsp); @@ -2051,15 +1171,14 @@ int lsp_generate(struct isis_area *area, int level) &area->t_lsp_refresh[level - 1]); if (isis->debugs & DEBUG_UPDATE_PACKETS) { - zlog_debug( - "ISIS-Upd (%s): Building L%d LSP %s, len %d, " - "seq 0x%08x, cksum 0x%04x, lifetime %us refresh %us", - area->area_tag, level, - rawlspid_print(newlsp->lsp_header->lsp_id), - ntohl(newlsp->lsp_header->pdu_len), - ntohl(newlsp->lsp_header->seq_num), - ntohs(newlsp->lsp_header->checksum), - ntohs(newlsp->lsp_header->rem_lifetime), refresh_time); + zlog_debug("ISIS-Upd (%s): Building L%d LSP %s, len %" PRIu16 + ", seq 0x%08" PRIx32 ", cksum 0x%04" PRIx16 + ", lifetime %" PRIu16 "s refresh %" PRIu16 "s", + area->area_tag, level, + rawlspid_print(newlsp->hdr.lsp_id), + newlsp->hdr.pdu_len, newlsp->hdr.seqno, + newlsp->hdr.checksum, newlsp->hdr.rem_lifetime, + refresh_time); } sched_debug( "ISIS (%s): Built L%d LSP. Set triggered regenerate to non-pending.", @@ -2097,24 +1216,21 @@ static int lsp_regenerate(struct isis_area *area, int level) lsp_clear_data(lsp); lsp_build(lsp, area); - lsp->lsp_header->lsp_bits = lsp_bits_generate(level, area->overload_bit, - area->attached_bit); rem_lifetime = lsp_rem_lifetime(area, level); - lsp->lsp_header->rem_lifetime = htons(rem_lifetime); - lsp_seqnum_update(lsp); - + lsp->hdr.rem_lifetime = rem_lifetime; lsp->last_generated = time(NULL); lsp_set_all_srmflags(lsp); for (ALL_LIST_ELEMENTS_RO(lsp->lspu.frags, node, frag)) { - frag->lsp_header->lsp_bits = lsp_bits_generate( + frag->hdr.lsp_bits = lsp_bits_generate( level, area->overload_bit, area->attached_bit); /* Set the lifetime values of all the fragments to the same * value, * so that no fragment expires before the lsp is refreshed. */ - frag->lsp_header->rem_lifetime = htons(rem_lifetime); + frag->hdr.rem_lifetime = rem_lifetime; lsp_set_all_srmflags(frag); } + lsp_seqno_update(lsp); refresh_time = lsp_refresh_time(lsp, rem_lifetime); if (level == IS_LEVEL_1) @@ -2127,14 +1243,12 @@ static int lsp_regenerate(struct isis_area *area, int level) if (isis->debugs & DEBUG_UPDATE_PACKETS) { zlog_debug( - "ISIS-Upd (%s): Refreshing our L%d LSP %s, len %d, " - "seq 0x%08x, cksum 0x%04x, lifetime %us refresh %us", - area->area_tag, level, - rawlspid_print(lsp->lsp_header->lsp_id), - ntohl(lsp->lsp_header->pdu_len), - ntohl(lsp->lsp_header->seq_num), - ntohs(lsp->lsp_header->checksum), - ntohs(lsp->lsp_header->rem_lifetime), refresh_time); + "ISIS-Upd (%s): Refreshed our L%d LSP %s, len %" PRIu16 + ", seq 0x%08" PRIx32 ", cksum 0x%04" PRIx16 + ", lifetime %" PRIu16 "s refresh %" PRIu16 "s", + area->area_tag, level, rawlspid_print(lsp->hdr.lsp_id), + lsp->hdr.pdu_len, lsp->hdr.seqno, lsp->hdr.checksum, + lsp->hdr.rem_lifetime, refresh_time); } sched_debug( "ISIS (%s): Rebuilt L%d LSP. Set triggered regenerate to non-pending.", @@ -2294,164 +1408,89 @@ static void lsp_build_pseudo(struct isis_lsp *lsp, struct isis_circuit *circuit, int level) { struct isis_adjacency *adj; - struct is_neigh *is_neigh; - struct te_is_neigh *te_is_neigh; - struct es_neigh *es_neigh; struct list *adj_list; struct listnode *node; struct isis_area *area = circuit->area; + lsp_clear_data(lsp); + lsp->tlvs = isis_alloc_tlvs(); lsp_debug( "ISIS (%s): Constructing pseudo LSP %s for interface %s level %d", - area->area_tag, rawlspid_print(lsp->lsp_header->lsp_id), + area->area_tag, rawlspid_print(lsp->hdr.lsp_id), circuit->interface->name, level); lsp->level = level; /* RFC3787 section 4 SHOULD not set overload bit in pseudo LSPs */ - lsp->lsp_header->lsp_bits = + lsp->hdr.lsp_bits = lsp_bits_generate(level, 0, circuit->area->attached_bit); /* * add self to IS neighbours */ - if (circuit->area->oldmetric) { - if (lsp->tlv_data.is_neighs == NULL) { - lsp->tlv_data.is_neighs = list_new(); - lsp->tlv_data.is_neighs->del = free_tlv; - } - is_neigh = XCALLOC(MTYPE_ISIS_TLV, sizeof(struct is_neigh)); + uint8_t ne_id[ISIS_SYS_ID_LEN + 1]; + + memcpy(ne_id, isis->sysid, ISIS_SYS_ID_LEN); + LSP_PSEUDO_ID(ne_id) = 0; - memcpy(&is_neigh->neigh_id, isis->sysid, ISIS_SYS_ID_LEN); - listnode_add(lsp->tlv_data.is_neighs, is_neigh); + if (circuit->area->oldmetric) { + isis_tlvs_add_oldstyle_reach(lsp->tlvs, ne_id, 0); lsp_debug( "ISIS (%s): Adding %s.%02x as old-style neighbor (self)", - area->area_tag, sysid_print(is_neigh->neigh_id), - LSP_PSEUDO_ID(is_neigh->neigh_id)); + area->area_tag, sysid_print(ne_id), + LSP_PSEUDO_ID(ne_id)); } if (circuit->area->newmetric) { - if (lsp->tlv_data.te_is_neighs == NULL) { - lsp->tlv_data.te_is_neighs = list_new(); - lsp->tlv_data.te_is_neighs->del = free_tlv; - } - te_is_neigh = - XCALLOC(MTYPE_ISIS_TLV, sizeof(struct te_is_neigh)); - - memcpy(&te_is_neigh->neigh_id, isis->sysid, ISIS_SYS_ID_LEN); - listnode_add(lsp->tlv_data.te_is_neighs, te_is_neigh); + isis_tlvs_add_extended_reach(lsp->tlvs, ISIS_MT_IPV4_UNICAST, + ne_id, 0, NULL, 0); lsp_debug( "ISIS (%s): Adding %s.%02x as te-style neighbor (self)", - area->area_tag, sysid_print(te_is_neigh->neigh_id), - LSP_PSEUDO_ID(te_is_neigh->neigh_id)); + area->area_tag, sysid_print(ne_id), + LSP_PSEUDO_ID(ne_id)); } adj_list = list_new(); isis_adj_build_up_list(circuit->u.bc.adjdb[level - 1], adj_list); for (ALL_LIST_ELEMENTS_RO(adj_list, node, adj)) { - if (adj->level & level) { - if ((level == IS_LEVEL_1 - && adj->sys_type == ISIS_SYSTYPE_L1_IS) - || (level == IS_LEVEL_1 - && adj->sys_type == ISIS_SYSTYPE_L2_IS - && adj->adj_usage == ISIS_ADJ_LEVEL1AND2) - || (level == IS_LEVEL_2 - && adj->sys_type == ISIS_SYSTYPE_L2_IS)) { - /* an IS neighbour -> add it */ - if (circuit->area->oldmetric) { - is_neigh = XCALLOC( - MTYPE_ISIS_TLV, - sizeof(struct is_neigh)); - - memcpy(&is_neigh->neigh_id, adj->sysid, - ISIS_SYS_ID_LEN); - listnode_add(lsp->tlv_data.is_neighs, - is_neigh); - lsp_debug( - "ISIS (%s): Adding %s.%02x as old-style neighbor (peer)", - area->area_tag, - sysid_print(is_neigh->neigh_id), - LSP_PSEUDO_ID( - is_neigh->neigh_id)); - } - if (circuit->area->newmetric) { - te_is_neigh = XCALLOC( - MTYPE_ISIS_TLV, - sizeof(struct te_is_neigh)); - memcpy(&te_is_neigh->neigh_id, - adj->sysid, ISIS_SYS_ID_LEN); - listnode_add(lsp->tlv_data.te_is_neighs, - te_is_neigh); - lsp_debug( - "ISIS (%s): Adding %s.%02x as te-style neighbor (peer)", - area->area_tag, - sysid_print( - te_is_neigh->neigh_id), - LSP_PSEUDO_ID( - te_is_neigh->neigh_id)); - } - } else if (level == IS_LEVEL_1 - && adj->sys_type == ISIS_SYSTYPE_ES) { - /* an ES neigbour add it, if we are building - * level 1 LSP */ - /* FIXME: the tlv-format is hard to use here */ - if (lsp->tlv_data.es_neighs == NULL) { - lsp->tlv_data.es_neighs = list_new(); - lsp->tlv_data.es_neighs->del = free_tlv; - } - es_neigh = XCALLOC(MTYPE_ISIS_TLV, - sizeof(struct es_neigh)); - - memcpy(&es_neigh->first_es_neigh, adj->sysid, - ISIS_SYS_ID_LEN); - listnode_add(lsp->tlv_data.es_neighs, es_neigh); - lsp_debug( - "ISIS (%s): Adding %s as ES neighbor (peer)", - area->area_tag, - sysid_print(es_neigh->first_es_neigh)); - } else { - lsp_debug( - "ISIS (%s): Ignoring neighbor %s, level does not match", - area->area_tag, - sysid_print(adj->sysid)); - } - } else { + if (!(adj->level & level)) { lsp_debug( "ISIS (%s): Ignoring neighbor %s, level does not intersect", area->area_tag, sysid_print(adj->sysid)); + continue; } - } - list_delete(adj_list); - - lsp_debug("ISIS (%s): Pseudo LSP construction is complete.", - area->area_tag); - - /* Reset endp of stream to overwrite only TLV part of it. */ - stream_reset(lsp->pdu); - stream_forward_endp(lsp->pdu, ISIS_FIXED_HDR_LEN + ISIS_LSP_HDR_LEN); - /* - * Add the authentication info if it's present - */ - lsp_auth_add(lsp); - - if (lsp->tlv_data.is_neighs && listcount(lsp->tlv_data.is_neighs) > 0) - tlv_add_is_neighs(lsp->tlv_data.is_neighs, lsp->pdu); - - if (lsp->tlv_data.te_is_neighs - && listcount(lsp->tlv_data.te_is_neighs) > 0) - tlv_add_te_is_neighs(lsp->tlv_data.te_is_neighs, lsp->pdu, - NULL); - - if (lsp->tlv_data.es_neighs && listcount(lsp->tlv_data.es_neighs) > 0) - tlv_add_is_neighs(lsp->tlv_data.es_neighs, lsp->pdu); - - lsp->lsp_header->pdu_len = htons(stream_get_endp(lsp->pdu)); - - /* Recompute authentication and checksum information */ - lsp_auth_update(lsp); - fletcher_checksum(STREAM_DATA(lsp->pdu) + 12, - ntohs(lsp->lsp_header->pdu_len) - 12, 12); + if (!(level == IS_LEVEL_1 + && adj->sys_type == ISIS_SYSTYPE_L1_IS) + && !(level == IS_LEVEL_1 + && adj->sys_type == ISIS_SYSTYPE_L2_IS + && adj->adj_usage == ISIS_ADJ_LEVEL1AND2) + && !(level == IS_LEVEL_2 + && adj->sys_type == ISIS_SYSTYPE_L2_IS)) { + lsp_debug( + "ISIS (%s): Ignoring neighbor %s, level does not match", + area->area_tag, sysid_print(adj->sysid)); + continue; + } + memcpy(ne_id, adj->sysid, ISIS_SYS_ID_LEN); + if (circuit->area->oldmetric) { + isis_tlvs_add_oldstyle_reach(lsp->tlvs, ne_id, 0); + lsp_debug( + "ISIS (%s): Adding %s.%02x as old-style neighbor (peer)", + area->area_tag, sysid_print(ne_id), + LSP_PSEUDO_ID(ne_id)); + } + if (circuit->area->newmetric) { + isis_tlvs_add_extended_reach(lsp->tlvs, + ISIS_MT_IPV4_UNICAST, + ne_id, 0, NULL, 0); + lsp_debug( + "ISIS (%s): Adding %s.%02x as te-style neighbor (peer)", + area->area_tag, sysid_print(ne_id), + LSP_PSEUDO_ID(ne_id)); + } + } + list_delete(adj_list); return; } @@ -2486,7 +1525,7 @@ int lsp_generate_pseudo(struct isis_circuit *circuit, int level) lsp->area = circuit->area; lsp_build_pseudo(lsp, circuit, level); - + lsp_pack_pdu(lsp); lsp->own_lsp = 1; lsp_insert(lsp, lspdb); lsp_set_all_srmflags(lsp); @@ -2505,14 +1544,13 @@ int lsp_generate_pseudo(struct isis_circuit *circuit, int level) if (isis->debugs & DEBUG_UPDATE_PACKETS) { zlog_debug( - "ISIS-Upd (%s): Building L%d Pseudo LSP %s, len %d, " - "seq 0x%08x, cksum 0x%04x, lifetime %us, refresh %us", + "ISIS-Upd (%s): Built L%d Pseudo LSP %s, len %" PRIu16 + ", seq 0x%08" PRIx32 ", cksum 0x%04" PRIx16 + ", lifetime %" PRIu16 "s, refresh %" PRIu16 "s", circuit->area->area_tag, level, - rawlspid_print(lsp->lsp_header->lsp_id), - ntohl(lsp->lsp_header->pdu_len), - ntohl(lsp->lsp_header->seq_num), - ntohs(lsp->lsp_header->checksum), - ntohs(lsp->lsp_header->rem_lifetime), refresh_time); + rawlspid_print(lsp->hdr.lsp_id), lsp->hdr.pdu_len, + lsp->hdr.seqno, lsp->hdr.checksum, + lsp->hdr.rem_lifetime, refresh_time); } return ISIS_OK; @@ -2542,16 +1580,11 @@ static int lsp_regenerate_pseudo(struct isis_circuit *circuit, int level) rawlspid_print(lsp_id)); return ISIS_ERROR; } - lsp_clear_data(lsp); - lsp_build_pseudo(lsp, circuit, level); - - /* RFC3787 section 4 SHOULD not set overload bit in pseudo LSPs */ - lsp->lsp_header->lsp_bits = - lsp_bits_generate(level, 0, circuit->area->attached_bit); rem_lifetime = lsp_rem_lifetime(circuit->area, level); - lsp->lsp_header->rem_lifetime = htons(rem_lifetime); - lsp_inc_seqnum(lsp, 0); + lsp->hdr.rem_lifetime = rem_lifetime; + lsp_build_pseudo(lsp, circuit, level); + lsp_inc_seqno(lsp, 0); lsp->last_generated = time(NULL); lsp_set_all_srmflags(lsp); @@ -2567,14 +1600,13 @@ static int lsp_regenerate_pseudo(struct isis_circuit *circuit, int level) if (isis->debugs & DEBUG_UPDATE_PACKETS) { zlog_debug( - "ISIS-Upd (%s): Refreshing L%d Pseudo LSP %s, len %d, " - "seq 0x%08x, cksum 0x%04x, lifetime %us, refresh %us", + "ISIS-Upd (%s): Refreshed L%d Pseudo LSP %s, len %" PRIu16 + ", seq 0x%08" PRIx32 ", cksum 0x%04" PRIx16 + ", lifetime %" PRIu16 "s, refresh %" PRIu16 "s", circuit->area->area_tag, level, - rawlspid_print(lsp->lsp_header->lsp_id), - ntohl(lsp->lsp_header->pdu_len), - ntohl(lsp->lsp_header->seq_num), - ntohs(lsp->lsp_header->checksum), - ntohs(lsp->lsp_header->rem_lifetime), refresh_time); + rawlspid_print(lsp->hdr.lsp_id), lsp->hdr.pdu_len, + lsp->hdr.seqno, lsp->hdr.checksum, + lsp->hdr.rem_lifetime, refresh_time); } return ISIS_OK; @@ -2771,8 +1803,7 @@ int lsp_tick(struct thread *thread) * when * the first time rem_lifetime becomes 0. */ - rem_lifetime = - ntohs(lsp->lsp_header->rem_lifetime); + rem_lifetime = lsp->hdr.rem_lifetime; lsp_set_time(lsp); /* @@ -2782,8 +1813,7 @@ int lsp_tick(struct thread *thread) * time. * ISO 10589 - 7.3.16.4 first paragraph. */ - if (rem_lifetime == 1 - && lsp->lsp_header->seq_num != 0) { + if (rem_lifetime == 1 && lsp->hdr.seqno != 0) { /* 7.3.16.4 a) set SRM flags on all */ lsp_set_all_srmflags(lsp); /* 7.3.16.4 b) retain only the header @@ -2800,13 +1830,11 @@ int lsp_tick(struct thread *thread) if (lsp->age_out == 0) { zlog_debug( - "ISIS-Upd (%s): L%u LSP %s seq 0x%08x aged out", + "ISIS-Upd (%s): L%u LSP %s seq " + "0x%08" PRIx32 " aged out", area->area_tag, lsp->level, - rawlspid_print( - lsp->lsp_header - ->lsp_id), - ntohl(lsp->lsp_header - ->seq_num)); + rawlspid_print(lsp->hdr.lsp_id), + lsp->hdr.seqno); lsp_destroy(lsp); lsp = NULL; dict_delete_free(area->lspdb[level], @@ -2867,56 +1895,22 @@ int lsp_tick(struct thread *thread) void lsp_purge_pseudo(u_char *id, struct isis_circuit *circuit, int level) { struct isis_lsp *lsp; - u_int16_t seq_num; - u_int8_t lsp_bits; lsp = lsp_search(id, circuit->area->lspdb[level - 1]); if (!lsp) return; - /* store old values */ - seq_num = lsp->lsp_header->seq_num; - lsp_bits = lsp->lsp_header->lsp_bits; - - /* reset stream */ - lsp_clear_data(lsp); - stream_reset(lsp->pdu); - - /* update header */ - lsp->lsp_header->pdu_len = htons(ISIS_FIXED_HDR_LEN + ISIS_LSP_HDR_LEN); - memcpy(lsp->lsp_header->lsp_id, id, ISIS_SYS_ID_LEN + 2); - lsp->lsp_header->checksum = 0; - lsp->lsp_header->seq_num = seq_num; - lsp->lsp_header->rem_lifetime = 0; - lsp->lsp_header->lsp_bits = lsp_bits; - lsp->level = level; - lsp->age_out = lsp->area->max_lsp_lifetime[level - 1]; - stream_forward_endp(lsp->pdu, ISIS_FIXED_HDR_LEN + ISIS_LSP_HDR_LEN); - - /* - * Add and update the authentication info if its present - */ - lsp_auth_add(lsp); - lsp->lsp_header->pdu_len = htons(stream_get_endp(lsp->pdu)); - lsp_auth_update(lsp); - fletcher_checksum(STREAM_DATA(lsp->pdu) + 12, - ntohs(lsp->lsp_header->pdu_len) - 12, 12); - - lsp_set_all_srmflags(lsp); - - return; + lsp_purge(lsp, level); } /* * Purge own LSP that is received and we don't have. * -> Do as in 7.3.16.4 */ -void lsp_purge_non_exist(int level, struct isis_link_state_hdr *lsp_hdr, +void lsp_purge_non_exist(int level, struct isis_lsp_hdr *hdr, struct isis_area *area) { struct isis_lsp *lsp; - uint8_t pdu_type = - (level == IS_LEVEL_1) ? L1_LINK_STATE : L2_LINK_STATE; /* * We need to create the LSP to be purged @@ -2925,37 +1919,14 @@ void lsp_purge_non_exist(int level, struct isis_link_state_hdr *lsp_hdr, lsp->area = area; lsp->level = level; lsp->pdu = stream_new(LLC_LEN + area->lsp_mtu); - fill_fixed_hdr(pdu_type, lsp->pdu); - - lsp->lsp_header = (struct isis_link_state_hdr *)(STREAM_DATA(lsp->pdu) - + ISIS_FIXED_HDR_LEN); - memcpy(lsp->lsp_header, lsp_hdr, ISIS_LSP_HDR_LEN); - stream_forward_endp(lsp->pdu, ISIS_FIXED_HDR_LEN + ISIS_LSP_HDR_LEN); - - /* - * Set the remaining lifetime to 0 - */ - lsp->lsp_header->rem_lifetime = 0; + lsp->age_out = ZERO_AGE_LIFETIME; - /* - * Add and update the authentication info if its present - */ - lsp_auth_add(lsp); - lsp_auth_update(lsp); + memcpy(&lsp->hdr, hdr, sizeof(lsp->hdr)); + lsp->hdr.rem_lifetime = 0; - /* - * Update the PDU length to header plus any authentication TLV. - */ - lsp->lsp_header->pdu_len = htons(stream_get_endp(lsp->pdu)); + lsp_pack_pdu(lsp); - /* - * Put the lsp into LSPdb - */ lsp_insert(lsp, area->lspdb[lsp->level - 1]); - - /* - * Send in to whole area - */ lsp_set_all_srmflags(lsp); return; diff --git a/isisd/isis_lsp.h b/isisd/isis_lsp.h index 429cd1942..8b62ed551 100644 --- a/isisd/isis_lsp.h +++ b/isisd/isis_lsp.h @@ -24,18 +24,19 @@ #ifndef _ZEBRA_ISIS_LSP_H #define _ZEBRA_ISIS_LSP_H +#include "isisd/isis_pdu.h" + /* Structure for isis_lsp, this structure will only support the fixed * System ID (Currently 6) (atleast for now). In order to support more * We will have to split the header into two parts, and for readability * sake it should better be avoided */ struct isis_lsp { - struct isis_link_state_hdr *lsp_header; /* pdu + isis_header_len */ - struct stream *pdu; /* full pdu lsp */ + struct isis_lsp_hdr hdr; + struct stream *pdu; /* full pdu lsp */ union { struct list *frags; struct isis_lsp *zero_lsp; } lspu; - u_int32_t auth_tlv_offset; /* authentication TLV position in the pdu */ u_int32_t SRMflags[ISIS_MAX_CIRCUITS]; u_int32_t SSNflags[ISIS_MAX_CIRCUITS]; int level; /* L1 or L2? */ @@ -46,7 +47,7 @@ struct isis_lsp { /* used for 60 second counting when rem_lifetime is zero */ int age_out; struct isis_area *area; - struct tlvs tlv_data; /* Simplifies TLV access */ + struct isis_tlvs *tlvs; }; dict_t *lsp_db_init(void); @@ -58,13 +59,13 @@ int lsp_regenerate_schedule(struct isis_area *area, int level, int all_pseudo); int lsp_generate_pseudo(struct isis_circuit *circuit, int level); int lsp_regenerate_schedule_pseudo(struct isis_circuit *circuit, int level); -struct isis_lsp *lsp_new(struct isis_area *area, u_char *lsp_id, - u_int16_t rem_lifetime, u_int32_t seq_num, - u_int8_t lsp_bits, u_int16_t checksum, int level); -struct isis_lsp *lsp_new_from_stream_ptr(struct stream *stream, - u_int16_t pdu_len, - struct isis_lsp *lsp0, - struct isis_area *area, int level); +struct isis_lsp *lsp_new(struct isis_area *area, uint8_t *lsp_id, + uint16_t rem_lifetime, uint32_t seq_num, + uint8_t lsp_bits, uint16_t checksum, int level); +struct isis_lsp *lsp_new_from_recv(struct isis_lsp_hdr *hdr, + struct isis_tlvs *tlvs, + struct stream *stream, struct isis_lsp *lsp0, + struct isis_area *area, int level); void lsp_insert(struct isis_lsp *lsp, dict_t *lspdb); struct isis_lsp *lsp_search(u_char *id, dict_t *lspdb); @@ -74,7 +75,7 @@ void lsp_build_list_nonzero_ht(u_char *start_id, u_char *stop_id, struct list *list, dict_t *lspdb); void lsp_search_and_destroy(u_char *id, dict_t *lspdb); void lsp_purge_pseudo(u_char *id, struct isis_circuit *circuit, int level); -void lsp_purge_non_exist(int level, struct isis_link_state_hdr *lsp_hdr, +void lsp_purge_non_exist(int level, struct isis_lsp_hdr *hdr, struct isis_area *area); #define LSP_EQUAL 1 @@ -88,16 +89,15 @@ void lsp_purge_non_exist(int level, struct isis_link_state_hdr *lsp_hdr, (I)[ISIS_SYS_ID_LEN] = 0; \ (I)[ISIS_SYS_ID_LEN + 1] = 0 int lsp_id_cmp(u_char *id1, u_char *id2); -int lsp_compare(char *areatag, struct isis_lsp *lsp, u_int32_t seq_num, - u_int16_t checksum, u_int16_t rem_lifetime); -void lsp_update(struct isis_lsp *lsp, struct stream *stream, +int lsp_compare(char *areatag, struct isis_lsp *lsp, uint32_t seqno, + uint16_t checksum, uint16_t rem_lifetime); +void lsp_update(struct isis_lsp *lsp, struct isis_lsp_hdr *hdr, + struct isis_tlvs *tlvs, struct stream *stream, struct isis_area *area, int level); -void lsp_inc_seqnum(struct isis_lsp *lsp, u_int32_t seq_num); +void lsp_inc_seqno(struct isis_lsp *lsp, uint32_t seqno); void lsp_print(struct isis_lsp *lsp, struct vty *vty, char dynhost); void lsp_print_detail(struct isis_lsp *lsp, struct vty *vty, char dynhost); int lsp_print_all(struct vty *vty, dict_t *lspdb, char detail, char dynhost); -const char *lsp_bits2string(u_char *); - /* sets SRMflags for all active circuits of an lsp */ void lsp_set_all_srmflags(struct isis_lsp *lsp); diff --git a/isisd/isis_main.c b/isisd/isis_main.c index 463e3abcf..40ceb99fb 100644 --- a/isisd/isis_main.c +++ b/isisd/isis_main.c @@ -52,7 +52,6 @@ #include "isisd/isis_route.h" #include "isisd/isis_routemap.h" #include "isisd/isis_zebra.h" -#include "isisd/isis_tlv.h" #include "isisd/isis_te.h" /* Default configuration file name */ diff --git a/isisd/isis_misc.c b/isisd/isis_misc.c index cf6558c13..4d7b4c381 100644 --- a/isisd/isis_misc.c +++ b/isisd/isis_misc.c @@ -39,7 +39,6 @@ #include "isisd/isisd.h" #include "isisd/isis_misc.h" -#include "isisd/isis_tlv.h" #include "isisd/isis_lsp.h" #include "isisd/isis_constants.h" #include "isisd/isis_adjacency.h" @@ -216,25 +215,6 @@ char *nlpid2string(struct nlpids *nlpids) } /* - * supports the given af ? - */ -int speaks(struct nlpids *nlpids, int family) -{ - int i, speaks = 0; - - if (nlpids == (struct nlpids *)NULL) - return speaks; - for (i = 0; i < nlpids->count; i++) { - if (family == AF_INET && nlpids->nlpids[i] == NLPID_IP) - speaks = 1; - if (family == AF_INET6 && nlpids->nlpids[i] == NLPID_IPV6) - speaks = 1; - } - - return speaks; -} - -/* * Returns 0 on error, IS-IS Circuit Type on ok */ int string2circuit_t(const char *str) @@ -486,7 +466,7 @@ const char *print_sys_hostname(const u_char *sysid) dyn = dynhn_find_by_id(sysid); if (dyn) - return (const char *)dyn->name.name; + return dyn->hostname; return sysid_print(sysid); } diff --git a/isisd/isis_misc.h b/isisd/isis_misc.h index 0ff33f831..7de534ec7 100644 --- a/isisd/isis_misc.h +++ b/isisd/isis_misc.h @@ -55,7 +55,6 @@ void zlog_dump_data(void *data, int len); /* * misc functions */ -int speaks(struct nlpids *nlpids, int family); unsigned long isis_jitter(unsigned long timer, unsigned long jitter); const char *unix_hostname(void); diff --git a/isisd/isis_mt.c b/isisd/isis_mt.c index ff0b95487..e1ff81e23 100644 --- a/isisd/isis_mt.c +++ b/isisd/isis_mt.c @@ -24,7 +24,6 @@ #include "isisd/isis_memory.h" #include "isisd/isis_circuit.h" #include "isisd/isis_adjacency.h" -#include "isisd/isis_tlv.h" #include "isisd/isis_misc.h" #include "isisd/isis_lsp.h" #include "isisd/isis_mt.h" @@ -33,11 +32,6 @@ DEFINE_MTYPE_STATIC(ISISD, MT_AREA_SETTING, "ISIS MT Area Setting") DEFINE_MTYPE_STATIC(ISISD, MT_CIRCUIT_SETTING, "ISIS MT Circuit Setting") DEFINE_MTYPE_STATIC(ISISD, MT_ADJ_INFO, "ISIS MT Adjacency Info") -DEFINE_MTYPE_STATIC(ISISD, MT_NEIGHBORS, "ISIS MT Neighbors for TLV") -DEFINE_MTYPE_STATIC(ISISD, MT_IPV4_REACHS, - "ISIS MT IPv4 Reachabilities for TLV") -DEFINE_MTYPE_STATIC(ISISD, MT_IPV6_REACHS, - "ISIS MT IPv6 Reachabilities for TLV") uint16_t isis_area_ipv6_topology(struct isis_area *area) { @@ -389,7 +383,8 @@ bool tlvs_to_adj_mt_set(struct isis_tlvs *tlvs, bool v4_usable, bool v6_usable, mt_settings = circuit_mt_settings(adj->circuit, &circuit_mt_count); for (unsigned int i = 0; i < circuit_mt_count; i++) { - if (tlvs->mt_router_info.count && !tlvs->mt_router_info_empty) { + if (!tlvs->mt_router_info.count + && !tlvs->mt_router_info_empty) { /* Other end does not have MT enabled */ if (mt_settings[i]->mtid == ISIS_MT_IPV4_UNICAST && v4_usable) @@ -459,153 +454,6 @@ void adj_mt_finish(struct isis_adjacency *adj) adj->mt_count = 0; } -/* TLV Router info api */ -struct mt_router_info *tlvs_lookup_mt_router_info(struct tlvs *tlvs, - uint16_t mtid) -{ - return lookup_mt_setting(tlvs->mt_router_info, mtid); -} - -/* TLV MT Neighbors api */ -struct tlv_mt_neighbors *tlvs_lookup_mt_neighbors(struct tlvs *tlvs, - uint16_t mtid) -{ - return lookup_mt_setting(tlvs->mt_is_neighs, mtid); -} - -static struct tlv_mt_neighbors *tlvs_new_mt_neighbors(uint16_t mtid) -{ - struct tlv_mt_neighbors *rv; - - rv = XCALLOC(MTYPE_MT_NEIGHBORS, sizeof(*rv)); - rv->mtid = mtid; - rv->list = list_new(); - - return rv; -}; - -static void tlvs_free_mt_neighbors(void *arg) -{ - struct tlv_mt_neighbors *neighbors = arg; - - if (neighbors && neighbors->list) - list_delete(neighbors->list); - XFREE(MTYPE_MT_NEIGHBORS, neighbors); -} - -static void tlvs_add_mt_neighbors(struct tlvs *tlvs, - struct tlv_mt_neighbors *neighbors) -{ - add_mt_setting(&tlvs->mt_is_neighs, neighbors); - tlvs->mt_is_neighs->del = tlvs_free_mt_neighbors; -} - -struct tlv_mt_neighbors *tlvs_get_mt_neighbors(struct tlvs *tlvs, uint16_t mtid) -{ - struct tlv_mt_neighbors *neighbors; - - neighbors = tlvs_lookup_mt_neighbors(tlvs, mtid); - if (!neighbors) { - neighbors = tlvs_new_mt_neighbors(mtid); - tlvs_add_mt_neighbors(tlvs, neighbors); - } - return neighbors; -} - -/* TLV MT IPv4 reach api */ -struct tlv_mt_ipv4_reachs *tlvs_lookup_mt_ipv4_reachs(struct tlvs *tlvs, - uint16_t mtid) -{ - return lookup_mt_setting(tlvs->mt_ipv4_reachs, mtid); -} - -static struct tlv_mt_ipv4_reachs *tlvs_new_mt_ipv4_reachs(uint16_t mtid) -{ - struct tlv_mt_ipv4_reachs *rv; - - rv = XCALLOC(MTYPE_MT_IPV4_REACHS, sizeof(*rv)); - rv->mtid = mtid; - rv->list = list_new(); - - return rv; -}; - -static void tlvs_free_mt_ipv4_reachs(void *arg) -{ - struct tlv_mt_ipv4_reachs *reachs = arg; - - if (reachs && reachs->list) - list_delete(reachs->list); - XFREE(MTYPE_MT_IPV4_REACHS, reachs); -} - -static void tlvs_add_mt_ipv4_reachs(struct tlvs *tlvs, - struct tlv_mt_ipv4_reachs *reachs) -{ - add_mt_setting(&tlvs->mt_ipv4_reachs, reachs); - tlvs->mt_ipv4_reachs->del = tlvs_free_mt_ipv4_reachs; -} - -struct tlv_mt_ipv4_reachs *tlvs_get_mt_ipv4_reachs(struct tlvs *tlvs, - uint16_t mtid) -{ - struct tlv_mt_ipv4_reachs *reachs; - - reachs = tlvs_lookup_mt_ipv4_reachs(tlvs, mtid); - if (!reachs) { - reachs = tlvs_new_mt_ipv4_reachs(mtid); - tlvs_add_mt_ipv4_reachs(tlvs, reachs); - } - return reachs; -} - -/* TLV MT IPv6 reach api */ -struct tlv_mt_ipv6_reachs *tlvs_lookup_mt_ipv6_reachs(struct tlvs *tlvs, - uint16_t mtid) -{ - return lookup_mt_setting(tlvs->mt_ipv6_reachs, mtid); -} - -static struct tlv_mt_ipv6_reachs *tlvs_new_mt_ipv6_reachs(uint16_t mtid) -{ - struct tlv_mt_ipv6_reachs *rv; - - rv = XCALLOC(MTYPE_MT_IPV6_REACHS, sizeof(*rv)); - rv->mtid = mtid; - rv->list = list_new(); - - return rv; -}; - -static void tlvs_free_mt_ipv6_reachs(void *arg) -{ - struct tlv_mt_ipv6_reachs *reachs = arg; - - if (reachs && reachs->list) - list_delete(reachs->list); - XFREE(MTYPE_MT_IPV6_REACHS, reachs); -} - -static void tlvs_add_mt_ipv6_reachs(struct tlvs *tlvs, - struct tlv_mt_ipv6_reachs *reachs) -{ - add_mt_setting(&tlvs->mt_ipv6_reachs, reachs); - tlvs->mt_ipv6_reachs->del = tlvs_free_mt_ipv6_reachs; -} - -struct tlv_mt_ipv6_reachs *tlvs_get_mt_ipv6_reachs(struct tlvs *tlvs, - uint16_t mtid) -{ - struct tlv_mt_ipv6_reachs *reachs; - - reachs = tlvs_lookup_mt_ipv6_reachs(tlvs, mtid); - if (!reachs) { - reachs = tlvs_new_mt_ipv6_reachs(mtid); - tlvs_add_mt_ipv6_reachs(tlvs, reachs); - } - return reachs; -} - static void mt_set_add(uint16_t **mt_set, unsigned int *size, unsigned int *index, uint16_t mtid) { @@ -650,51 +498,46 @@ static uint16_t *circuit_bcast_mt_set(struct isis_circuit *circuit, int level, return rv; } -static void tlvs_add_mt_set(struct isis_area *area, struct tlvs *tlvs, +static void tlvs_add_mt_set(struct isis_area *area, struct isis_tlvs *tlvs, unsigned int mt_count, uint16_t *mt_set, - struct te_is_neigh *neigh) + uint8_t *id, uint32_t metric, uint8_t *subtlvs, + uint8_t subtlv_len) { for (unsigned int i = 0; i < mt_count; i++) { uint16_t mtid = mt_set[i]; - struct te_is_neigh *ne_copy; - - ne_copy = XCALLOC(MTYPE_ISIS_TLV, sizeof(*ne_copy)); - memcpy(ne_copy, neigh, sizeof(*ne_copy)); - if (mt_set[i] == ISIS_MT_IPV4_UNICAST) { - listnode_add(tlvs->te_is_neighs, ne_copy); lsp_debug( "ISIS (%s): Adding %s.%02x as te-style neighbor", - area->area_tag, sysid_print(ne_copy->neigh_id), - LSP_PSEUDO_ID(ne_copy->neigh_id)); + area->area_tag, sysid_print(id), + LSP_PSEUDO_ID(id)); } else { - struct tlv_mt_neighbors *neighbors; - - neighbors = tlvs_get_mt_neighbors(tlvs, mtid); - neighbors->list->del = free_tlv; - listnode_add(neighbors->list, ne_copy); lsp_debug( "ISIS (%s): Adding %s.%02x as mt-style neighbor for %s", - area->area_tag, sysid_print(ne_copy->neigh_id), - LSP_PSEUDO_ID(ne_copy->neigh_id), - isis_mtid2str(mtid)); + area->area_tag, sysid_print(id), + LSP_PSEUDO_ID(id), isis_mtid2str(mtid)); } + isis_tlvs_add_extended_reach(tlvs, mtid, id, metric, subtlvs, + subtlv_len); } } -void tlvs_add_mt_bcast(struct tlvs *tlvs, struct isis_circuit *circuit, - int level, struct te_is_neigh *neigh) +void tlvs_add_mt_bcast(struct isis_tlvs *tlvs, struct isis_circuit *circuit, + int level, uint8_t *id, uint32_t metric, + uint8_t *subtlvs, uint8_t subtlv_len) { unsigned int mt_count; uint16_t *mt_set = circuit_bcast_mt_set(circuit, level, &mt_count); - tlvs_add_mt_set(circuit->area, tlvs, mt_count, mt_set, neigh); + tlvs_add_mt_set(circuit->area, tlvs, mt_count, mt_set, id, metric, + subtlvs, subtlv_len); } -void tlvs_add_mt_p2p(struct tlvs *tlvs, struct isis_circuit *circuit, - struct te_is_neigh *neigh) +void tlvs_add_mt_p2p(struct isis_tlvs *tlvs, struct isis_circuit *circuit, + uint8_t *id, uint32_t metric, uint8_t *subtlvs, + uint8_t subtlv_len) { struct isis_adjacency *adj = circuit->u.p2p.neighbor; - tlvs_add_mt_set(circuit->area, tlvs, adj->mt_count, adj->mt_set, neigh); + tlvs_add_mt_set(circuit->area, tlvs, adj->mt_count, adj->mt_set, id, + metric, subtlvs, subtlv_len); } diff --git a/isisd/isis_mt.h b/isisd/isis_mt.h index 496da8558..95aa99dba 100644 --- a/isisd/isis_mt.h +++ b/isisd/isis_mt.h @@ -65,21 +65,6 @@ struct isis_circuit_mt_setting { bool enabled; }; -struct tlv_mt_neighbors { - ISIS_MT_INFO_FIELDS - struct list *list; -}; - -struct tlv_mt_ipv4_reachs { - ISIS_MT_INFO_FIELDS - struct list *list; -}; - -struct tlv_mt_ipv6_reachs { - ISIS_MT_INFO_FIELDS - struct list *list; -}; - const char *isis_mtid2str(uint16_t mtid); uint16_t isis_str2mtid(const char *name); @@ -92,24 +77,6 @@ struct isis_tlvs; uint16_t isis_area_ipv6_topology(struct isis_area *area); -struct mt_router_info *tlvs_lookup_mt_router_info(struct tlvs *tlvs, - uint16_t mtid); - -struct tlv_mt_neighbors *tlvs_lookup_mt_neighbors(struct tlvs *tlvs, - uint16_t mtid); -struct tlv_mt_neighbors *tlvs_get_mt_neighbors(struct tlvs *tlvs, - uint16_t mtid); - -struct tlv_mt_ipv4_reachs *tlvs_lookup_mt_ipv4_reachs(struct tlvs *tlvs, - uint16_t mtid); -struct tlv_mt_ipv4_reachs *tlvs_get_mt_ipv4_reachs(struct tlvs *tlvs, - uint16_t mtid); - -struct tlv_mt_ipv6_reachs *tlvs_lookup_mt_ipv6_reachs(struct tlvs *tlvs, - uint16_t mtid); -struct tlv_mt_ipv6_reachs *tlvs_get_mt_ipv6_reachs(struct tlvs *tlvs, - uint16_t mtid); - struct isis_area_mt_setting *area_lookup_mt_setting(struct isis_area *area, uint16_t mtid); struct isis_area_mt_setting *area_new_mt_setting(struct isis_area *area, @@ -143,8 +110,10 @@ bool tlvs_to_adj_mt_set(struct isis_tlvs *tlvs, bool v4_usable, bool v6_usable, struct isis_adjacency *adj); bool adj_has_mt(struct isis_adjacency *adj, uint16_t mtid); void adj_mt_finish(struct isis_adjacency *adj); -void tlvs_add_mt_bcast(struct tlvs *tlvs, struct isis_circuit *circuit, - int level, struct te_is_neigh *neigh); -void tlvs_add_mt_p2p(struct tlvs *tlvs, struct isis_circuit *circuit, - struct te_is_neigh *neigh); +void tlvs_add_mt_bcast(struct isis_tlvs *tlvs, struct isis_circuit *circuit, + int level, uint8_t *id, uint32_t metric, + uint8_t *subtlvs, uint8_t subtlv_len); +void tlvs_add_mt_p2p(struct isis_tlvs *tlvs, struct isis_circuit *circuit, + uint8_t *id, uint32_t metric, uint8_t *subtlvs, + uint8_t subtlv_len); #endif diff --git a/isisd/isis_pdu.c b/isisd/isis_pdu.c index 5ab5a1e99..aee2cf381 100644 --- a/isisd/isis_pdu.c +++ b/isisd/isis_pdu.c @@ -44,7 +44,6 @@ #include "isisd/isis_network.h" #include "isisd/isis_misc.h" #include "isisd/isis_dr.h" -#include "isisd/isis_tlv.h" #include "isisd/isisd.h" #include "isisd/isis_dynhn.h" #include "isisd/isis_lsp.h" @@ -56,135 +55,40 @@ #include "isisd/isis_mt.h" #include "isisd/isis_tlvs2.h" -#define ISIS_MINIMUM_FIXED_HDR_LEN 15 -#define ISIS_MIN_PDU_LEN 13 /* partial seqnum pdu with id_len=2 */ - -#ifndef PNBBY -#define PNBBY 8 -#endif /* PNBBY */ - -/* - * HELPER FUNCS - */ - -/* - * Checks whether we should accept a PDU of given level - */ -static int accept_level(int level, int circuit_t) -{ - int retval = ((circuit_t & level) == level); /* simple approach */ - - return retval; -} - -/* - * Verify authentication information - * Support cleartext and HMAC MD5 authentication - */ -static int authentication_check(struct isis_passwd *remote, - struct isis_passwd *local, - struct stream *stream, uint32_t auth_tlv_offset) +static int ack_lsp(struct isis_lsp_hdr *hdr, struct isis_circuit *circuit, + int level) { - unsigned char digest[ISIS_AUTH_MD5_SIZE]; - - /* Auth fail () - passwd type mismatch */ - if (local->type != remote->type) - return ISIS_ERROR; - - switch (local->type) { - /* No authentication required */ - case ISIS_PASSWD_TYPE_UNUSED: - break; - - /* Cleartext (ISO 10589) */ - case ISIS_PASSWD_TYPE_CLEARTXT: - /* Auth fail () - passwd len mismatch */ - if (remote->len != local->len) - return ISIS_ERROR; - return memcmp(local->passwd, remote->passwd, local->len); - - /* HMAC MD5 (RFC 3567) */ - case ISIS_PASSWD_TYPE_HMAC_MD5: - /* Auth fail () - passwd len mismatch */ - if (remote->len != ISIS_AUTH_MD5_SIZE) - return ISIS_ERROR; - /* Set the authentication value to 0 before the check */ - memset(STREAM_DATA(stream) + auth_tlv_offset + 3, 0, - ISIS_AUTH_MD5_SIZE); - /* Compute the digest */ - hmac_md5(STREAM_DATA(stream), stream_get_endp(stream), - (unsigned char *)&(local->passwd), local->len, - (unsigned char *)&digest); - /* Copy back the authentication value after the check */ - memcpy(STREAM_DATA(stream) + auth_tlv_offset + 3, - remote->passwd, ISIS_AUTH_MD5_SIZE); - return memcmp(digest, remote->passwd, ISIS_AUTH_MD5_SIZE); - - default: - zlog_err("Unsupported authentication type"); - return ISIS_ERROR; - } + unsigned long lenp; + int retval; + u_int16_t length; + uint8_t pdu_type = + (level == IS_LEVEL_1) ? L1_PARTIAL_SEQ_NUM : L2_PARTIAL_SEQ_NUM; - /* Authentication pass when no authentication is configured */ - return ISIS_OK; -} + isis_circuit_stream(circuit, &circuit->snd_stream); -static int lsp_authentication_check(struct stream *stream, - struct isis_area *area, int level, - struct isis_passwd *passwd) -{ - struct isis_link_state_hdr *hdr; - uint32_t expected = 0, found = 0, auth_tlv_offset = 0; - uint16_t checksum, rem_lifetime, pdu_len; - struct tlvs tlvs; - int retval = ISIS_OK; + fill_fixed_hdr(pdu_type, circuit->snd_stream); - hdr = (struct isis_link_state_hdr *)(STREAM_PNT(stream)); - pdu_len = ntohs(hdr->pdu_len); - expected |= TLVFLAG_AUTH_INFO; - auth_tlv_offset = stream_get_getp(stream) + ISIS_LSP_HDR_LEN; - retval = parse_tlvs(area->area_tag, - STREAM_PNT(stream) + ISIS_LSP_HDR_LEN, - pdu_len - ISIS_FIXED_HDR_LEN - ISIS_LSP_HDR_LEN, - &expected, &found, &tlvs, &auth_tlv_offset); + lenp = stream_get_endp(circuit->snd_stream); + stream_putw(circuit->snd_stream, 0); /* PDU length */ + stream_put(circuit->snd_stream, isis->sysid, ISIS_SYS_ID_LEN); + stream_putc(circuit->snd_stream, circuit->idx); + stream_putc(circuit->snd_stream, 9); /* code */ + stream_putc(circuit->snd_stream, 16); /* len */ - if (retval != ISIS_OK) { - zlog_err( - "ISIS-Upd (%s): Parse failed L%d LSP %s, seq 0x%08x, " - "cksum 0x%04x, lifetime %us, len %u", - area->area_tag, level, rawlspid_print(hdr->lsp_id), - ntohl(hdr->seq_num), ntohs(hdr->checksum), - ntohs(hdr->rem_lifetime), pdu_len); - if ((isis->debugs & DEBUG_UPDATE_PACKETS) - && (isis->debugs & DEBUG_PACKET_DUMP)) - zlog_dump_data(STREAM_DATA(stream), - stream_get_endp(stream)); - return retval; - } - - if (!(found & TLVFLAG_AUTH_INFO)) { - zlog_err("No authentication tlv in LSP"); - return ISIS_ERROR; - } + stream_putw(circuit->snd_stream, hdr->rem_lifetime); + stream_put(circuit->snd_stream, hdr->lsp_id, ISIS_SYS_ID_LEN + 2); + stream_putl(circuit->snd_stream, hdr->seqno); + stream_putw(circuit->snd_stream, hdr->checksum); - if (tlvs.auth_info.type != ISIS_PASSWD_TYPE_CLEARTXT - && tlvs.auth_info.type != ISIS_PASSWD_TYPE_HMAC_MD5) { - zlog_err("Unknown authentication type in LSP"); - return ISIS_ERROR; - } + length = (u_int16_t)stream_get_endp(circuit->snd_stream); + /* Update PDU length */ + stream_putw_at(circuit->snd_stream, lenp, length); - /* - * RFC 5304 set checksum and remaining lifetime to zero before - * verification and reset to old values after verification. - */ - checksum = hdr->checksum; - rem_lifetime = hdr->rem_lifetime; - hdr->checksum = 0; - hdr->rem_lifetime = 0; - retval = authentication_check(&tlvs.auth_info, passwd, stream, - auth_tlv_offset); - hdr->checksum = checksum; - hdr->rem_lifetime = rem_lifetime; + retval = circuit->tx(circuit, level); + if (retval != ISIS_OK) + zlog_err("ISIS-Upd (%s): Send L%d LSP PSNP on %s failed", + circuit->area->area_tag, level, + circuit->interface->name); return retval; } @@ -670,7 +574,7 @@ static int process_hello(uint8_t pdu_type, struct isis_circuit *circuit, return ISIS_WARNING; } - if (!accept_level(level, circuit->is_type)) { + if (!(circuit->is_type & level)) { if (isis->debugs & DEBUG_ADJ_PACKETS) { zlog_debug( "ISIS-Adj (%s): Interface level mismatch, %s", @@ -731,7 +635,7 @@ static int process_hello(uint8_t pdu_type, struct isis_circuit *circuit, } if (!isis_tlvs_auth_is_valid(iih.tlvs, &circuit->passwd, - circuit->rcv_stream)) { + circuit->rcv_stream, false)) { isis_event_auth_failure(circuit->area->area_tag, "IIH authentication failure", iih.sys_id); @@ -780,17 +684,10 @@ out: * ISO - 10589 * Section 7.3.15.1 - Action on receipt of a link state PDU */ -static int process_lsp(int level, struct isis_circuit *circuit, +static int process_lsp(uint8_t pdu_type, struct isis_circuit *circuit, const u_char *ssnpa) { - struct isis_link_state_hdr *hdr; - struct isis_adjacency *adj = NULL; - struct isis_lsp *lsp, *lsp0 = NULL; - int retval = ISIS_OK, comp = 0; - u_char lspid[ISIS_SYS_ID_LEN + 2]; - struct isis_passwd *passwd; - uint16_t pdu_len; - int lsp_confusion; + int level = (pdu_type == L1_LINK_STATE) ? ISIS_LEVEL1 : ISIS_LEVEL2; if (isis->debugs & DEBUG_UPDATE_PACKETS) { zlog_debug( @@ -804,65 +701,50 @@ static int process_lsp(int level, struct isis_circuit *circuit, stream_get_endp(circuit->rcv_stream)); } - if ((stream_get_endp(circuit->rcv_stream) - - stream_get_getp(circuit->rcv_stream)) - < ISIS_LSP_HDR_LEN) { - zlog_warn("Packet too short"); - return ISIS_WARNING; - } - - /* Reference the header */ - hdr = (struct isis_link_state_hdr *)STREAM_PNT(circuit->rcv_stream); - pdu_len = ntohs(hdr->pdu_len); + struct isis_lsp_hdr hdr = {}; - /* lsp length check */ - if (pdu_len < (ISIS_FIXED_HDR_LEN + ISIS_LSP_HDR_LEN) - || pdu_len > ISO_MTU(circuit) - || pdu_len > stream_get_endp(circuit->rcv_stream)) { - zlog_debug("ISIS-Upd (%s): LSP %s invalid LSP length %d", - circuit->area->area_tag, rawlspid_print(hdr->lsp_id), - pdu_len); + hdr.pdu_len = stream_getw(circuit->rcv_stream); + hdr.rem_lifetime = stream_getw(circuit->rcv_stream); + stream_get(hdr.lsp_id, circuit->rcv_stream, sizeof(hdr.lsp_id)); + hdr.seqno = stream_getl(circuit->rcv_stream); + hdr.checksum = stream_getw(circuit->rcv_stream); + hdr.lsp_bits = stream_getc(circuit->rcv_stream); + if (pdu_len_validate(hdr.pdu_len, circuit)) { + zlog_debug("ISIS-Upd (%s): LSP %s invalid LSP length %" PRIu16, + circuit->area->area_tag, rawlspid_print(hdr.lsp_id), + hdr.pdu_len); return ISIS_WARNING; } - /* - * Set the stream endp to PDU length, ignoring additional padding - * introduced by transport chips. - */ - if (pdu_len < stream_get_endp(circuit->rcv_stream)) - stream_set_endp(circuit->rcv_stream, pdu_len); - if (isis->debugs & DEBUG_UPDATE_PACKETS) { - zlog_debug( - "ISIS-Upd (%s): Rcvd L%d LSP %s, seq 0x%08x, cksum 0x%04x, " - "lifetime %us, len %u, on %s", - circuit->area->area_tag, level, - rawlspid_print(hdr->lsp_id), ntohl(hdr->seq_num), - ntohs(hdr->checksum), ntohs(hdr->rem_lifetime), pdu_len, - circuit->interface->name); + zlog_debug("ISIS-Upd (%s): Rcvd L%d LSP %s, seq 0x%08" PRIx32 + ", cksum 0x%04" PRIx16 ", lifetime %" PRIu16 + "s, len %" PRIu16 ", on %s", + circuit->area->area_tag, level, + rawlspid_print(hdr.lsp_id), hdr.seqno, hdr.checksum, + hdr.rem_lifetime, hdr.pdu_len, + circuit->interface->name); } /* lsp is_type check */ - if ((hdr->lsp_bits & IS_LEVEL_1_AND_2) != IS_LEVEL_1 - && (hdr->lsp_bits & IS_LEVEL_1_AND_2) != IS_LEVEL_1_AND_2) { - zlog_debug("ISIS-Upd (%s): LSP %s invalid LSP is type %x", - circuit->area->area_tag, rawlspid_print(hdr->lsp_id), - hdr->lsp_bits); + if ((hdr.lsp_bits & IS_LEVEL_1) != IS_LEVEL_1) { + zlog_debug( + "ISIS-Upd (%s): LSP %s invalid LSP is type 0x%" PRIx8, + circuit->area->area_tag, rawlspid_print(hdr.lsp_id), + hdr.lsp_bits & IS_LEVEL_1_AND_2); /* continue as per RFC1122 Be liberal in what you accept, and * conservative in what you send */ } /* Checksum sanity check - FIXME: move to correct place */ /* 12 = sysid+pdu+remtime */ - if (iso_csum_verify(STREAM_PNT(circuit->rcv_stream) + 4, pdu_len - 12, - hdr->checksum, - offsetof(struct isis_link_state_hdr, checksum) - - 4)) { - zlog_debug("ISIS-Upd (%s): LSP %s invalid LSP checksum 0x%04x", - circuit->area->area_tag, rawlspid_print(hdr->lsp_id), - ntohs(hdr->checksum)); - + if (iso_csum_verify(STREAM_DATA(circuit->rcv_stream) + 12, + hdr.pdu_len - 12, hdr.checksum, 12)) { + zlog_debug( + "ISIS-Upd (%s): LSP %s invalid LSP checksum 0x%04" PRIx16, + circuit->area->area_tag, rawlspid_print(hdr.lsp_id), + hdr.checksum); return ISIS_WARNING; } @@ -871,47 +753,56 @@ static int process_lsp(int level, struct isis_circuit *circuit, zlog_debug( "ISIS-Upd (%s): LSP %s received at level %d over circuit with " "externalDomain = true", - circuit->area->area_tag, rawlspid_print(hdr->lsp_id), + circuit->area->area_tag, rawlspid_print(hdr.lsp_id), level); - return ISIS_WARNING; } /* 7.3.15.1 a) 2,3 - manualL2OnlyMode not implemented */ - if (!accept_level(level, circuit->is_type)) { + if (!(circuit->is_type & level)) { zlog_debug( "ISIS-Upd (%s): LSP %s received at level %d over circuit of" " type %s", - circuit->area->area_tag, rawlspid_print(hdr->lsp_id), + circuit->area->area_tag, rawlspid_print(hdr.lsp_id), level, circuit_t2string(circuit->is_type)); - return ISIS_WARNING; } + struct isis_tlvs *tlvs = NULL; + int retval = ISIS_WARNING; + const char *error_log; + + if (isis_unpack_tlvs(STREAM_READABLE(circuit->rcv_stream), + circuit->rcv_stream, &tlvs, &error_log)) { + zlog_warn("Something went wrong unpacking the LSP: %s", + error_log); + goto out; + } + /* 7.3.15.1 a) 4 - need to make sure IDLength matches */ /* 7.3.15.1 a) 5 - maximum area match, can be ommited since we only use * 3 */ /* 7.3.15.1 a) 7 - password check */ - (level == IS_LEVEL_1) ? (passwd = &circuit->area->area_passwd) - : (passwd = &circuit->area->domain_passwd); - if (passwd->type) { - if (lsp_authentication_check(circuit->rcv_stream, circuit->area, - level, passwd)) { - isis_event_auth_failure(circuit->area->area_tag, - "LSP authentication failure", - hdr->lsp_id); - return ISIS_WARNING; - } + struct isis_passwd *passwd = (level == ISIS_LEVEL1) + ? &circuit->area->area_passwd + : &circuit->area->domain_passwd; + if (!isis_tlvs_auth_is_valid(tlvs, passwd, circuit->rcv_stream, true)) { + isis_event_auth_failure(circuit->area->area_tag, + "LSP authentication failure", + hdr.lsp_id); + goto out; } + /* Find the LSP in our database and compare it to this Link State header */ - lsp = lsp_search(hdr->lsp_id, circuit->area->lspdb[level - 1]); + struct isis_lsp *lsp = + lsp_search(hdr.lsp_id, circuit->area->lspdb[level - 1]); + int comp = 0; if (lsp) - comp = lsp_compare(circuit->area->area_tag, lsp, - ntohl(hdr->seq_num), ntohs(hdr->checksum), - ntohs(hdr->rem_lifetime)); + comp = lsp_compare(circuit->area->area_tag, lsp, hdr.seqno, + hdr.checksum, hdr.rem_lifetime); if (lsp && (lsp->own_lsp)) goto dontcheckadj; @@ -920,25 +811,24 @@ static int process_lsp(int level, struct isis_circuit *circuit, /* for broadcast circuits, snpa should be compared */ if (circuit->circ_type == CIRCUIT_T_BROADCAST) { - adj = isis_adj_lookup_snpa(ssnpa, - circuit->u.bc.adjdb[level - 1]); - if (!adj) { - zlog_debug( - "(%s): DS ======= LSP %s, seq 0x%08x, cksum 0x%04x, " - "lifetime %us on %s", - circuit->area->area_tag, - rawlspid_print(hdr->lsp_id), - ntohl(hdr->seq_num), ntohs(hdr->checksum), - ntohs(hdr->rem_lifetime), - circuit->interface->name); - return ISIS_WARNING; /* Silently discard */ + if (!isis_adj_lookup_snpa(ssnpa, + circuit->u.bc.adjdb[level - 1])) { + zlog_debug("(%s): DS ======= LSP %s, seq 0x%08" PRIx32 + ", cksum 0x%04" PRIx16 ", lifetime %" PRIu16 + "s on %s", + circuit->area->area_tag, + rawlspid_print(hdr.lsp_id), hdr.seqno, + hdr.checksum, hdr.rem_lifetime, + circuit->interface->name); + goto out; /* Silently discard */ } } /* for non broadcast, we just need to find same level adj */ else { /* If no adj, or no sharing of level */ if (!circuit->u.p2p.neighbor) { - return ISIS_OK; /* Silently discard */ + retval = ISIS_OK; + goto out; } else { if (((level == IS_LEVEL_1) && (circuit->u.p2p.neighbor->adj_usage @@ -946,10 +836,12 @@ static int process_lsp(int level, struct isis_circuit *circuit, || ((level == IS_LEVEL_2) && (circuit->u.p2p.neighbor->adj_usage == ISIS_ADJ_LEVEL1))) - return ISIS_WARNING; /* Silently discard */ + goto out; } } + bool lsp_confusion; + dontcheckadj: /* 7.3.15.1 a) 7 - Passwords for level 1 - not implemented */ @@ -961,33 +853,35 @@ dontcheckadj: /* 7.3.16.2 - If this is an LSP from another IS with identical seq_num * but * wrong checksum, initiate a purge. */ - if (lsp && (lsp->lsp_header->seq_num == hdr->seq_num) - && (lsp->lsp_header->checksum != hdr->checksum)) { - zlog_warn( - "ISIS-Upd (%s): LSP %s seq 0x%08x with confused checksum received.", - circuit->area->area_tag, rawlspid_print(hdr->lsp_id), - ntohl(hdr->seq_num)); - hdr->rem_lifetime = 0; - lsp_confusion = 1; + if (lsp && (lsp->hdr.seqno == hdr.seqno) + && (lsp->hdr.checksum != hdr.checksum)) { + zlog_warn("ISIS-Upd (%s): LSP %s seq 0x%08" PRIx32 + " with confused checksum received.", + circuit->area->area_tag, rawlspid_print(hdr.lsp_id), + hdr.seqno); + hdr.rem_lifetime = 0; + lsp_confusion = true; } else - lsp_confusion = 0; + lsp_confusion = false; /* 7.3.15.1 b) - If the remaining life time is 0, we perform 7.3.16.4 */ - if (hdr->rem_lifetime == 0) { + if (hdr.rem_lifetime == 0) { if (!lsp) { /* 7.3.16.4 a) 1) No LSP in db -> send an ack, but don't * save */ /* only needed on explicit update, eg - p2p */ if (circuit->circ_type == CIRCUIT_T_P2P) - ack_lsp(hdr, circuit, level); - return retval; /* FIXME: do we need a purge? */ + ack_lsp(&hdr, circuit, level); + goto out; /* FIXME: do we need a purge? */ } else { - if (memcmp(hdr->lsp_id, isis->sysid, ISIS_SYS_ID_LEN)) { + if (memcmp(hdr.lsp_id, isis->sysid, ISIS_SYS_ID_LEN)) { /* LSP by some other system -> do 7.3.16.4 b) */ /* 7.3.16.4 b) 1) */ if (comp == LSP_NEWER) { - lsp_update(lsp, circuit->rcv_stream, + lsp_update(lsp, &hdr, tlvs, + circuit->rcv_stream, circuit->area, level); + tlvs = NULL; /* ii */ lsp_set_all_srmflags(lsp); /* v */ @@ -1028,11 +922,10 @@ dontcheckadj: ISIS_SET_FLAG(lsp->SRMflags, circuit); ISIS_CLEAR_FLAG(lsp->SSNflags, circuit); } - } else if (lsp->lsp_header->rem_lifetime != 0) { + } else if (lsp->hdr.rem_lifetime != 0) { /* our own LSP -> 7.3.16.4 c) */ if (comp == LSP_NEWER) { - lsp_inc_seqnum(lsp, - ntohl(hdr->seq_num)); + lsp_inc_seqno(lsp, hdr.seqno); lsp_set_all_srmflags(lsp); } else { ISIS_SET_FLAG(lsp->SRMflags, circuit); @@ -1040,23 +933,22 @@ dontcheckadj: } if (isis->debugs & DEBUG_UPDATE_PACKETS) zlog_debug( - "ISIS-Upd (%s): (1) re-originating LSP %s new " - "seq 0x%08x", + "ISIS-Upd (%s): (1) re-originating LSP %s new seq 0x%08" PRIx32, circuit->area->area_tag, - rawlspid_print(hdr->lsp_id), - ntohl(lsp->lsp_header - ->seq_num)); + rawlspid_print(hdr.lsp_id), + lsp->hdr.seqno); } } - return retval; + goto out; } /* 7.3.15.1 c) - If this is our own lsp and we don't have it initiate a * purge */ - if (memcmp(hdr->lsp_id, isis->sysid, ISIS_SYS_ID_LEN) == 0) { + if (memcmp(hdr.lsp_id, isis->sysid, ISIS_SYS_ID_LEN) == 0) { if (!lsp) { /* 7.3.16.4: initiate a purge */ - lsp_purge_non_exist(level, hdr, circuit->area); - return ISIS_OK; + lsp_purge_non_exist(level, &hdr, circuit->area); + retval = ISIS_OK; + goto out; } /* 7.3.15.1 d) - If this is our own lsp and we have it */ @@ -1066,16 +958,15 @@ dontcheckadj: * is * "greater" than that held by S, ... */ - if (ntohl(hdr->seq_num) > ntohl(lsp->lsp_header->seq_num)) { + if (hdr.seqno > lsp->hdr.seqno) { /* 7.3.16.1 */ - lsp_inc_seqnum(lsp, ntohl(hdr->seq_num)); + lsp_inc_seqno(lsp, hdr.seqno); if (isis->debugs & DEBUG_UPDATE_PACKETS) zlog_debug( - "ISIS-Upd (%s): (2) re-originating LSP %s new seq " - "0x%08x", + "ISIS-Upd (%s): (2) re-originating LSP %s new seq 0x%08" PRIx32, circuit->area->area_tag, - rawlspid_print(hdr->lsp_id), - ntohl(lsp->lsp_header->seq_num)); + rawlspid_print(hdr.lsp_id), + lsp->hdr.seqno); } /* If the received LSP is older or equal, * resend the LSP which will act as ACK */ @@ -1090,8 +981,10 @@ dontcheckadj: * If this lsp is a frag, need to see if we have zero * lsp present */ - if (LSP_FRAGMENT(hdr->lsp_id) != 0) { - memcpy(lspid, hdr->lsp_id, ISIS_SYS_ID_LEN + 1); + struct isis_lsp *lsp0 = NULL; + if (LSP_FRAGMENT(hdr.lsp_id) != 0) { + uint8_t lspid[ISIS_SYS_ID_LEN + 2]; + memcpy(lspid, hdr.lsp_id, ISIS_SYS_ID_LEN + 1); LSP_FRAGMENT(lspid) = 0; lsp0 = lsp_search( lspid, circuit->area->lspdb[level - 1]); @@ -1103,15 +996,17 @@ dontcheckadj: } /* i */ if (!lsp) { - lsp = lsp_new_from_stream_ptr( - circuit->rcv_stream, pdu_len, lsp0, + lsp = lsp_new_from_recv( + &hdr, tlvs, circuit->rcv_stream, lsp0, circuit->area, level); + tlvs = NULL; lsp_insert(lsp, circuit->area->lspdb[level - 1]); } else /* exists, so we overwrite */ { - lsp_update(lsp, circuit->rcv_stream, + lsp_update(lsp, &hdr, tlvs, circuit->rcv_stream, circuit->area, level); + tlvs = NULL; } /* ii */ lsp_set_all_srmflags(lsp); @@ -1126,8 +1021,9 @@ dontcheckadj: /* 7.3.15.1 e) 2) LSP equal to the one in db */ else if (comp == LSP_EQUAL) { ISIS_CLEAR_FLAG(lsp->SRMflags, circuit); - lsp_update(lsp, circuit->rcv_stream, circuit->area, - level); + lsp_update(lsp, &hdr, tlvs, circuit->rcv_stream, + circuit->area, level); + tlvs = NULL; if (circuit->circ_type != CIRCUIT_T_BROADCAST) ISIS_SET_FLAG(lsp->SSNflags, circuit); } @@ -1137,6 +1033,11 @@ dontcheckadj: ISIS_CLEAR_FLAG(lsp->SSNflags, circuit); } } + + retval = ISIS_OK; + +out: + isis_free_tlvs(tlvs); return retval; } @@ -1202,8 +1103,7 @@ static int process_snp(uint8_t pdu_type, struct isis_circuit *circuit, } /* 7.3.15.2 a) 2,3 - manualL2OnlyMode not implemented */ - if (!accept_level(level, circuit->is_type)) { - + if (!(circuit->is_type & level)) { zlog_debug( "ISIS-Snp (%s): Rcvd L%d %cSNP on %s, " "skipping: circuit type %s does not match level %d", @@ -1264,7 +1164,8 @@ static int process_snp(uint8_t pdu_type, struct isis_circuit *circuit, ? &circuit->area->area_passwd : &circuit->area->domain_passwd; if (CHECK_FLAG(passwd->snp_auth, SNP_AUTH_RECV) - && !isis_tlvs_auth_is_valid(tlvs, passwd, circuit->rcv_stream)) { + && !isis_tlvs_auth_is_valid(tlvs, passwd, circuit->rcv_stream, + false)) { isis_event_auth_failure(circuit->area->area_tag, "SNP authentication failure", rem_sys_id); @@ -1317,7 +1218,7 @@ static int process_snp(uint8_t pdu_type, struct isis_circuit *circuit, on p2p */ else { if (own_lsp) { - lsp_inc_seqnum(lsp, entry->seqno); + lsp_inc_seqno(lsp, entry->seqno); ISIS_SET_FLAG(lsp->SRMflags, circuit); } else { ISIS_SET_FLAG(lsp->SSNflags, circuit); @@ -1362,8 +1263,7 @@ static int process_snp(uint8_t pdu_type, struct isis_circuit *circuit, for (struct isis_lsp_entry *entry = entry_head; entry; entry = entry->next) { for (ALL_LIST_ELEMENTS(lsp_list, node, nnode, lsp)) { - if (lsp_id_cmp(lsp->lsp_header->lsp_id, - entry->id) + if (lsp_id_cmp(lsp->hdr.lsp_id, entry->id) == 0) { list_delete_node(lsp_list, node); break; @@ -1506,10 +1406,8 @@ static int isis_handle_pdu(struct isis_circuit *circuit, u_char *ssnpa) retval = process_hello(pdu_type, circuit, ssnpa); break; case L1_LINK_STATE: - retval = process_lsp(ISIS_LEVEL1, circuit, ssnpa); - break; case L2_LINK_STATE: - retval = process_lsp(ISIS_LEVEL2, circuit, ssnpa); + retval = process_lsp(pdu_type, circuit, ssnpa); break; case L1_COMPLETE_SEQ_NUM: case L2_COMPLETE_SEQ_NUM: @@ -1669,7 +1567,7 @@ int send_hello(struct isis_circuit *circuit, int level) isis_tlvs_add_ipv6_addresses(tlvs, circuit->ipv6_link); if (isis_pack_tlvs(tlvs, circuit->snd_stream, len_pointer, - circuit->pad_hellos)) { + circuit->pad_hellos, false)) { isis_free_tlvs(tlvs); return ISIS_WARNING; /* XXX: Maybe Log TLV structure? */ } @@ -1782,6 +1680,7 @@ int send_p2p_hello(struct thread *thread) /* * Count the maximum number of lsps that can be accomodated by a given size. */ +#define LSP_ENTRIES_LEN (10 + ISIS_SYS_ID_LEN) static uint16_t get_max_lsp_count(uint16_t size) { uint16_t tlv_count; @@ -1832,7 +1731,8 @@ int send_csnp(struct isis_circuit *circuit, int level) isis_tlvs_add_auth(tlvs, passwd); size_t tlv_start = stream_get_endp(circuit->snd_stream); - if (isis_pack_tlvs(tlvs, circuit->snd_stream, len_pointer, false)) { + if (isis_pack_tlvs(tlvs, circuit->snd_stream, len_pointer, false, + false)) { isis_free_tlvs(tlvs); return ISIS_WARNING; } @@ -1862,8 +1762,7 @@ int send_csnp(struct isis_circuit *circuit, int level) if (tlvs->lsp_entries.count < num_lsps) { memset(stop, 0xff, ISIS_SYS_ID_LEN + 2); } else { - memcpy(stop, last_lsp->lsp_header->lsp_id, - ISIS_SYS_ID_LEN + 2); + memcpy(stop, last_lsp->hdr.lsp_id, sizeof(stop)); } memcpy(STREAM_DATA(circuit->snd_stream) + start_pointer, start, @@ -1872,7 +1771,7 @@ int send_csnp(struct isis_circuit *circuit, int level) ISIS_SYS_ID_LEN + 2); stream_set_endp(circuit->snd_stream, tlv_start); if (isis_pack_tlvs(tlvs, circuit->snd_stream, len_pointer, - false)) { + false, false)) { isis_free_tlvs(tlvs); return ISIS_WARNING; } @@ -2001,7 +1900,8 @@ static int send_psnp(int level, struct isis_circuit *circuit) isis_tlvs_add_auth(tlvs, passwd); size_t tlv_start = stream_get_endp(circuit->snd_stream); - if (isis_pack_tlvs(tlvs, circuit->snd_stream, len_pointer, false)) { + if (isis_pack_tlvs(tlvs, circuit->snd_stream, len_pointer, false, + false)) { isis_free_tlvs(tlvs); return ISIS_WARNING; } @@ -2035,7 +1935,7 @@ static int send_psnp(int level, struct isis_circuit *circuit) stream_set_endp(circuit->snd_stream, tlv_start); if (isis_pack_tlvs(tlvs, circuit->snd_stream, len_pointer, - false)) { + false, false)) { isis_free_tlvs(tlvs); return ISIS_WARNING; } @@ -2183,14 +2083,12 @@ int send_lsp(struct thread *thread) * the circuit's MTU. So handle and log this case here. */ if (stream_get_endp(lsp->pdu) > stream_get_size(circuit->snd_stream)) { zlog_err( - "ISIS-Upd (%s): Can't send L%d LSP %s, seq 0x%08x," - " cksum 0x%04x, lifetime %us on %s. LSP Size is %zu" - " while interface stream size is %zu.", + "ISIS-Upd (%s): Can't send L%d LSP %s, seq 0x%08" PRIx32 + ", cksum 0x%04" PRIx16 ", lifetime %" PRIu16 + "s on %s. LSP Size is %zu while interface stream size is %zu.", 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), + rawlspid_print(lsp->hdr.lsp_id), lsp->hdr.seqno, + lsp->hdr.checksum, lsp->hdr.rem_lifetime, circuit->interface->name, stream_get_endp(lsp->pdu), stream_get_size(circuit->snd_stream)); if (isis->debugs & DEBUG_PACKET_DUMP) @@ -2204,15 +2102,13 @@ int send_lsp(struct thread *thread) stream_copy(circuit->snd_stream, lsp->pdu); if (isis->debugs & DEBUG_UPDATE_PACKETS) { - zlog_debug( - "ISIS-Upd (%s): Sending 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); + zlog_debug("ISIS-Upd (%s): Sending L%d LSP %s, seq 0x%08" PRIx32 + ", cksum 0x%04" PRIx16 ", lifetime %" PRIu16 + "s on %s", + circuit->area->area_tag, lsp->level, + rawlspid_print(lsp->hdr.lsp_id), lsp->hdr.seqno, + lsp->hdr.checksum, lsp->hdr.rem_lifetime, + circuit->interface->name); if (isis->debugs & DEBUG_PACKET_DUMP) zlog_dump_data(STREAM_DATA(circuit->snd_stream), stream_get_endp(circuit->snd_stream)); @@ -2246,41 +2142,3 @@ out: return retval; } - -int ack_lsp(struct isis_link_state_hdr *hdr, struct isis_circuit *circuit, - int level) -{ - unsigned long lenp; - int retval; - u_int16_t length; - uint8_t pdu_type = - (level == IS_LEVEL_1) ? L1_PARTIAL_SEQ_NUM : L2_PARTIAL_SEQ_NUM; - - isis_circuit_stream(circuit, &circuit->snd_stream); - - fill_fixed_hdr(pdu_type, circuit->snd_stream); - - lenp = stream_get_endp(circuit->snd_stream); - stream_putw(circuit->snd_stream, 0); /* PDU length */ - stream_put(circuit->snd_stream, isis->sysid, ISIS_SYS_ID_LEN); - stream_putc(circuit->snd_stream, circuit->idx); - stream_putc(circuit->snd_stream, 9); /* code */ - stream_putc(circuit->snd_stream, 16); /* len */ - - stream_putw(circuit->snd_stream, ntohs(hdr->rem_lifetime)); - stream_put(circuit->snd_stream, hdr->lsp_id, ISIS_SYS_ID_LEN + 2); - stream_putl(circuit->snd_stream, ntohl(hdr->seq_num)); - stream_putw(circuit->snd_stream, ntohs(hdr->checksum)); - - length = (u_int16_t)stream_get_endp(circuit->snd_stream); - /* Update PDU length */ - stream_putw_at(circuit->snd_stream, lenp, length); - - retval = circuit->tx(circuit, level); - if (retval != ISIS_OK) - zlog_err("ISIS-Upd (%s): Send L%d LSP PSNP on %s failed", - circuit->area->area_tag, level, - circuit->interface->name); - - return retval; -} diff --git a/isisd/isis_pdu.h b/isisd/isis_pdu.h index 985fc56ad..709676187 100644 --- a/isisd/isis_pdu.h +++ b/isisd/isis_pdu.h @@ -125,30 +125,14 @@ struct isis_p2p_hello_hdr { #define L1_LINK_STATE 18 #define L2_LINK_STATE 20 -/* - * L1 and L2 IS to IS link state PDU header - * +-------+-------+-------+-------+-------+-------+-------+-------+ - * + PDU Length + 2 - * +-------+-------+-------+-------+-------+-------+-------+-------+ - * + Remaining Lifetime + 2 - * +-------+-------+-------+-------+-------+-------+-------+-------+ - * | LSP ID | id_len + 2 - * +-------+-------+-------+-------+-------+-------+-------+-------+ - * + Sequence Number + 4 - * +-------+-------+-------+-------+-------+-------+-------+-------+ - * + Checksum + 2 - * +-------+-------+-------+-------+-------+-------+-------+-------+ - * | P | ATT |LSPDBOL| ISTYPE | - * +-------+-------+-------+-------+-------+-------+-------+-------+ - */ -struct isis_link_state_hdr { - u_int16_t pdu_len; - u_int16_t rem_lifetime; - u_char lsp_id[ISIS_SYS_ID_LEN + 2]; - u_int32_t seq_num; - u_int16_t checksum; - u_int8_t lsp_bits; -} __attribute__((packed)); +struct isis_lsp_hdr { + uint16_t pdu_len; + uint16_t rem_lifetime; + uint8_t lsp_id[ISIS_SYS_ID_LEN + 2]; + uint32_t seqno; + uint16_t checksum; + uint8_t lsp_bits; +}; #define ISIS_LSP_HDR_LEN 19 /* @@ -229,8 +213,6 @@ int send_l2_csnp(struct thread *thread); int send_l1_psnp(struct thread *thread); int send_l2_psnp(struct thread *thread); int send_lsp(struct thread *thread); -int ack_lsp(struct isis_link_state_hdr *hdr, struct isis_circuit *circuit, - int level); void fill_fixed_hdr(uint8_t pdu_type, struct stream *stream); int send_hello(struct isis_circuit *circuit, int level); diff --git a/isisd/isis_redist.c b/isisd/isis_redist.c index 8e329494d..ea94b6580 100644 --- a/isisd/isis_redist.c +++ b/isisd/isis_redist.c @@ -37,7 +37,6 @@ #include "isisd/isis_flags.h" #include "isisd/isis_misc.h" #include "isisd/isis_circuit.h" -#include "isisd/isis_tlv.h" #include "isisd/isisd.h" #include "isisd/isis_lsp.h" #include "isisd/isis_route.h" diff --git a/isisd/isis_route.c b/isisd/isis_route.c index 8cb5aa9ed..267e72002 100644 --- a/isisd/isis_route.c +++ b/isisd/isis_route.c @@ -42,7 +42,6 @@ #include "isis_misc.h" #include "isis_adjacency.h" #include "isis_circuit.h" -#include "isis_tlv.h" #include "isis_pdu.h" #include "isis_lsp.h" #include "isis_spf.h" diff --git a/isisd/isis_routemap.c b/isisd/isis_routemap.c index 44d7fa040..d92207d57 100644 --- a/isisd/isis_routemap.c +++ b/isisd/isis_routemap.c @@ -42,7 +42,6 @@ #include "isis_misc.h" #include "isis_adjacency.h" #include "isis_circuit.h" -#include "isis_tlv.h" #include "isis_pdu.h" #include "isis_lsp.h" #include "isis_spf.h" diff --git a/isisd/isis_spf.c b/isisd/isis_spf.c index 615c2eeaa..ffe6bf2fb 100644 --- a/isisd/isis_spf.c +++ b/isisd/isis_spf.c @@ -44,7 +44,6 @@ #include "isis_misc.h" #include "isis_adjacency.h" #include "isis_circuit.h" -#include "isis_tlv.h" #include "isis_pdu.h" #include "isis_lsp.h" #include "isis_dynhn.h" @@ -52,9 +51,24 @@ #include "isis_route.h" #include "isis_csm.h" #include "isis_mt.h" +#include "isis_tlvs2.h" DEFINE_MTYPE_STATIC(ISISD, ISIS_SPF_RUN, "ISIS SPF Run Info"); +/* + * supports the given af ? + */ +static bool speaks(uint8_t *protocols, uint8_t count, int family) +{ + for (uint8_t i = 0; i < count; i++) { + if (family == AF_INET && protocols[i] == NLPID_IP) + return true; + if (family == AF_INET6 && protocols[i] == NLPID_IPV6) + return true; + } + return false; +} + struct isis_spf_run { struct isis_area *area; int level; @@ -340,7 +354,7 @@ static struct isis_lsp *isis_root_system_lsp(struct isis_area *area, int level, LSP_PSEUDO_ID(lspid) = 0; LSP_FRAGMENT(lspid) = 0; lsp = lsp_search(lspid, area->lspdb[level - 1]); - if (lsp && lsp->lsp_header->rem_lifetime != 0) + if (lsp && lsp->hdr.rem_lifetime != 0) return lsp; return NULL; } @@ -546,6 +560,13 @@ static void process_N(struct isis_spftree *spftree, enum vertextype vtype, assert(spftree && parent); + struct prefix p; + if (vtype >= VTYPE_IPREACH_INTERNAL) { + prefix_copy(&p, id); + apply_mask(&p); + id = &p; + } + /* RFC3787 section 5.1 */ if (spftree->area->newmetric == 1) { if (dist > MAX_WIDE_PATH_METRIC) @@ -632,30 +653,29 @@ static int isis_spf_process_lsp(struct isis_spftree *spftree, uint16_t depth, u_char *root_sysid, struct isis_vertex *parent) { - bool pseudo_lsp = LSP_PSEUDO_ID(lsp->lsp_header->lsp_id); - struct listnode *node, *fragnode = NULL; + bool pseudo_lsp = LSP_PSEUDO_ID(lsp->hdr.lsp_id); + struct listnode *fragnode = NULL; uint32_t dist; - struct is_neigh *is_neigh; - struct te_is_neigh *te_is_neigh; - struct ipv4_reachability *ipreach; - struct te_ipv4_reachability *te_ipv4_reach; enum vertextype vtype; - struct prefix prefix; - struct ipv6_reachability *ip6reach; static const u_char null_sysid[ISIS_SYS_ID_LEN]; - struct mt_router_info *mt_router_info = NULL; + struct isis_mt_router_info *mt_router_info = NULL; + + if (!lsp->tlvs) + return ISIS_OK; if (spftree->mtid != ISIS_MT_IPV4_UNICAST) - mt_router_info = tlvs_lookup_mt_router_info(&lsp->tlv_data, - spftree->mtid); + mt_router_info = isis_tlvs_lookup_mt_router_info(lsp->tlvs, + spftree->mtid); if (!pseudo_lsp && (spftree->mtid == ISIS_MT_IPV4_UNICAST - && !speaks(lsp->tlv_data.nlpids, spftree->family)) + && !speaks(lsp->tlvs->protocols_supported.protocols, + lsp->tlvs->protocols_supported.count, + spftree->family)) && !mt_router_info) return ISIS_OK; lspfragloop: - if (lsp->lsp_header->seq_num == 0) { + if (lsp->hdr.seqno == 0) { zlog_warn( "isis_spf_process_lsp(): lsp with 0 seq_num - ignore"); return ISIS_WARNING; @@ -663,142 +683,122 @@ lspfragloop: #ifdef EXTREME_DEBUG zlog_debug("ISIS-Spf: process_lsp %s", - print_sys_hostname(lsp->lsp_header->lsp_id)); + print_sys_hostname(lsp->hdr.lsp_id)); #endif /* EXTREME_DEBUG */ /* RFC3787 section 4 SHOULD ignore overload bit in pseudo LSPs */ if (pseudo_lsp || (spftree->mtid == ISIS_MT_IPV4_UNICAST - && !ISIS_MASK_LSP_OL_BIT(lsp->lsp_header->lsp_bits)) + && !ISIS_MASK_LSP_OL_BIT(lsp->hdr.lsp_bits)) || (mt_router_info && !mt_router_info->overload)) { if (pseudo_lsp || spftree->mtid == ISIS_MT_IPV4_UNICAST) { - for (ALL_LIST_ELEMENTS_RO(lsp->tlv_data.is_neighs, node, - is_neigh)) { + struct isis_oldstyle_reach *r; + for (r = (struct isis_oldstyle_reach *) + lsp->tlvs->oldstyle_reach.head; + r; r = r->next) { /* C.2.6 a) */ /* Two way connectivity */ - if (!memcmp(is_neigh->neigh_id, root_sysid, - ISIS_SYS_ID_LEN)) + if (!memcmp(r->id, root_sysid, ISIS_SYS_ID_LEN)) continue; if (!pseudo_lsp - && !memcmp(is_neigh->neigh_id, null_sysid, + && !memcmp(r->id, null_sysid, ISIS_SYS_ID_LEN)) continue; - dist = cost + is_neigh->metrics.metric_default; + dist = cost + r->metric; process_N(spftree, - LSP_PSEUDO_ID(is_neigh->neigh_id) + LSP_PSEUDO_ID(r->id) ? VTYPE_PSEUDO_IS : VTYPE_NONPSEUDO_IS, - (void *)is_neigh->neigh_id, dist, - depth + 1, parent); + (void *)r->id, dist, depth + 1, + parent); } } - struct list *te_is_neighs = NULL; - if (pseudo_lsp || spftree->mtid == ISIS_MT_IPV4_UNICAST) { - te_is_neighs = lsp->tlv_data.te_is_neighs; - } else { - struct tlv_mt_neighbors *mt_neighbors; - mt_neighbors = tlvs_lookup_mt_neighbors(&lsp->tlv_data, - spftree->mtid); - if (mt_neighbors) - te_is_neighs = mt_neighbors->list; - } - for (ALL_LIST_ELEMENTS_RO(te_is_neighs, node, te_is_neigh)) { - if (!memcmp(te_is_neigh->neigh_id, root_sysid, - ISIS_SYS_ID_LEN)) + struct isis_item_list *te_neighs = NULL; + if (pseudo_lsp || spftree->mtid == ISIS_MT_IPV4_UNICAST) + te_neighs = &lsp->tlvs->extended_reach; + else + te_neighs = isis_lookup_mt_items(&lsp->tlvs->mt_reach, + spftree->mtid); + + struct isis_extended_reach *er; + for (er = te_neighs + ? (struct isis_extended_reach *) + te_neighs->head + : NULL; + er; er = er->next) { + if (!memcmp(er->id, root_sysid, ISIS_SYS_ID_LEN)) continue; if (!pseudo_lsp - && !memcmp(te_is_neigh->neigh_id, null_sysid, - ISIS_SYS_ID_LEN)) + && !memcmp(er->id, null_sysid, ISIS_SYS_ID_LEN)) continue; - dist = cost + GET_TE_METRIC(te_is_neigh); + dist = cost + er->metric; process_N(spftree, - LSP_PSEUDO_ID(te_is_neigh->neigh_id) - ? VTYPE_PSEUDO_TE_IS - : VTYPE_NONPSEUDO_TE_IS, - (void *)te_is_neigh->neigh_id, dist, - depth + 1, parent); + LSP_PSEUDO_ID(er->id) ? VTYPE_PSEUDO_TE_IS + : VTYPE_NONPSEUDO_TE_IS, + (void *)er->id, dist, depth + 1, parent); } } if (!pseudo_lsp && spftree->family == AF_INET && spftree->mtid == ISIS_MT_IPV4_UNICAST) { - struct list *reachs[] = {lsp->tlv_data.ipv4_int_reachs, - lsp->tlv_data.ipv4_ext_reachs}; + struct isis_item_list *reachs[] = { + &lsp->tlvs->oldstyle_ip_reach, + &lsp->tlvs->oldstyle_ip_reach_ext}; - prefix.family = AF_INET; for (unsigned int i = 0; i < array_size(reachs); i++) { - vtype = (reachs[i] == lsp->tlv_data.ipv4_int_reachs) - ? VTYPE_IPREACH_INTERNAL - : VTYPE_IPREACH_EXTERNAL; - for (ALL_LIST_ELEMENTS_RO(reachs[i], node, ipreach)) { - dist = cost + ipreach->metrics.metric_default; - prefix.u.prefix4 = ipreach->prefix; - prefix.prefixlen = ip_masklen(ipreach->mask); - apply_mask(&prefix); - process_N(spftree, vtype, (void *)&prefix, dist, - depth + 1, parent); + vtype = i ? VTYPE_IPREACH_EXTERNAL + : VTYPE_IPREACH_INTERNAL; + + struct isis_oldstyle_ip_reach *r; + for (r = (struct isis_oldstyle_ip_reach *)reachs[i] + ->head; + r; r = r->next) { + dist = cost + r->metric; + process_N(spftree, vtype, (void *)&r->prefix, + dist, depth + 1, parent); } } } if (!pseudo_lsp && spftree->family == AF_INET) { - struct list *ipv4reachs = NULL; - - if (spftree->mtid == ISIS_MT_IPV4_UNICAST) { - ipv4reachs = lsp->tlv_data.te_ipv4_reachs; - } else { - struct tlv_mt_ipv4_reachs *mt_reachs; - mt_reachs = tlvs_lookup_mt_ipv4_reachs(&lsp->tlv_data, - spftree->mtid); - if (mt_reachs) - ipv4reachs = mt_reachs->list; - } - - prefix.family = AF_INET; - for (ALL_LIST_ELEMENTS_RO(ipv4reachs, node, te_ipv4_reach)) { - assert((te_ipv4_reach->control & 0x3F) - <= IPV4_MAX_BITLEN); - - dist = cost + ntohl(te_ipv4_reach->te_metric); - prefix.u.prefix4 = - newprefix2inaddr(&te_ipv4_reach->prefix_start, - te_ipv4_reach->control); - prefix.prefixlen = (te_ipv4_reach->control & 0x3F); - apply_mask(&prefix); - process_N(spftree, VTYPE_IPREACH_TE, (void *)&prefix, + struct isis_item_list *ipv4_reachs; + if (spftree->mtid == ISIS_MT_IPV4_UNICAST) + ipv4_reachs = &lsp->tlvs->extended_ip_reach; + else + ipv4_reachs = isis_lookup_mt_items( + &lsp->tlvs->mt_ip_reach, spftree->mtid); + + struct isis_extended_ip_reach *r; + for (r = ipv4_reachs + ? (struct isis_extended_ip_reach *) + ipv4_reachs->head + : NULL; + r; r = r->next) { + dist = cost + r->metric; + process_N(spftree, VTYPE_IPREACH_TE, (void *)&r->prefix, dist, depth + 1, parent); } } if (!pseudo_lsp && spftree->family == AF_INET6) { - struct list *ipv6reachs = NULL; - - if (spftree->mtid == ISIS_MT_IPV4_UNICAST) { - ipv6reachs = lsp->tlv_data.ipv6_reachs; - } else { - struct tlv_mt_ipv6_reachs *mt_reachs; - mt_reachs = tlvs_lookup_mt_ipv6_reachs(&lsp->tlv_data, - spftree->mtid); - if (mt_reachs) - ipv6reachs = mt_reachs->list; - } - - prefix.family = AF_INET6; - for (ALL_LIST_ELEMENTS_RO(ipv6reachs, node, ip6reach)) { - assert(ip6reach->prefix_len <= IPV6_MAX_BITLEN); - - dist = cost + ntohl(ip6reach->metric); - vtype = (ip6reach->control_info - & CTRL_INFO_DISTRIBUTION) - ? VTYPE_IP6REACH_EXTERNAL - : VTYPE_IP6REACH_INTERNAL; - prefix.prefixlen = ip6reach->prefix_len; - memcpy(&prefix.u.prefix6.s6_addr, ip6reach->prefix, - PSIZE(ip6reach->prefix_len)); - apply_mask(&prefix); - process_N(spftree, vtype, (void *)&prefix, dist, + struct isis_item_list *ipv6_reachs; + if (spftree->mtid == ISIS_MT_IPV4_UNICAST) + ipv6_reachs = &lsp->tlvs->ipv6_reach; + else + ipv6_reachs = isis_lookup_mt_items( + &lsp->tlvs->mt_ipv6_reach, spftree->mtid); + + struct isis_ipv6_reach *r; + for (r = ipv6_reachs + ? (struct isis_ipv6_reach *)ipv6_reachs->head + : NULL; + r; r = r->next) { + dist = cost + r->metric; + vtype = r->external ? VTYPE_IP6REACH_EXTERNAL + : VTYPE_IP6REACH_INTERNAL; + process_N(spftree, vtype, (void *)&r->prefix, dist, depth + 1, parent); } } @@ -893,7 +893,9 @@ static int isis_spf_preload_tent(struct isis_spftree *spftree, if (!adj_has_mt(adj, spftree->mtid)) continue; if (spftree->mtid == ISIS_MT_IPV4_UNICAST - && !speaks(&adj->nlpids, spftree->family)) + && !speaks(adj->nlpids.nlpids, + adj->nlpids.count, + spftree->family)) continue; switch (adj->sys_type) { case ISIS_SYSTYPE_ES: @@ -928,8 +930,7 @@ static int isis_spf_preload_tent(struct isis_spftree *spftree, ->lspdb[spftree->level - 1]); if (lsp == NULL - || lsp->lsp_header->rem_lifetime - == 0) + || lsp->hdr.rem_lifetime == 0) zlog_warn( "ISIS-Spf: No LSP %s found for IS adjacency " "L%d on %s (ID %u)", @@ -979,7 +980,7 @@ static int isis_spf_preload_tent(struct isis_spftree *spftree, lsp = lsp_search( lsp_id, spftree->area->lspdb[spftree->level - 1]); - if (lsp == NULL || lsp->lsp_header->rem_lifetime == 0) { + if (lsp == NULL || lsp->hdr.rem_lifetime == 0) { zlog_warn( "ISIS-Spf: No lsp (%p) found from root " "to L%d DR %s on %s (ID %d)", @@ -1015,7 +1016,9 @@ static int isis_spf_preload_tent(struct isis_spftree *spftree, LSP_PSEUDO_ID(lsp_id) = 0; LSP_FRAGMENT(lsp_id) = 0; if (spftree->mtid != ISIS_MT_IPV4_UNICAST - || speaks(&adj->nlpids, spftree->family)) + || speaks(adj->nlpids.nlpids, + adj->nlpids.count, + spftree->family)) isis_spf_add_local( spftree, spftree->area->oldmetric @@ -1178,7 +1181,7 @@ static int isis_run_spf(struct isis_area *area, int level, int family, 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]); - if (lsp && lsp->lsp_header->rem_lifetime != 0) { + if (lsp && lsp->hdr.rem_lifetime != 0) { isis_spf_process_lsp(spftree, lsp, vertex->d_N, vertex->depth, sysid, vertex); diff --git a/isisd/isis_te.c b/isisd/isis_te.c index 6b8f1fe16..70afef1a8 100644 --- a/isisd/isis_te.c +++ b/isisd/isis_te.c @@ -41,6 +41,7 @@ #include "md5.h" #include "sockunion.h" #include "network.h" +#include "sbuf.h" #include "isisd/dict.h" #include "isisd/isis_constants.h" @@ -48,7 +49,6 @@ #include "isisd/isis_flags.h" #include "isisd/isis_circuit.h" #include "isisd/isisd.h" -#include "isisd/isis_tlv.h" #include "isisd/isis_lsp.h" #include "isisd/isis_pdu.h" #include "isisd/isis_dynhn.h" @@ -100,9 +100,9 @@ struct mpls_te_circuit *mpls_te_circuit_new() /* Copy SUB TLVs parameters into a buffer - No space verification are performed */ /* Caller must verify before that there is enough free space in the buffer */ -u_char add_te_subtlvs(u_char *buf, struct mpls_te_circuit *mtc) +uint8_t add_te_subtlvs(uint8_t *buf, struct mpls_te_circuit *mtc) { - u_char size, *tlvs = buf; + uint8_t size, *tlvs = buf; zlog_debug("ISIS MPLS-TE: Add TE Sub TLVs to buffer"); @@ -232,7 +232,7 @@ u_char add_te_subtlvs(u_char *buf, struct mpls_te_circuit *mtc) } /* Compute total Sub-TLVs size */ -u_char subtlvs_len(struct mpls_te_circuit *mtc) +uint8_t subtlvs_len(struct mpls_te_circuit *mtc) { int length = 0; @@ -306,7 +306,7 @@ u_char subtlvs_len(struct mpls_te_circuit *mtc) return 0; } - mtc->length = (u_char)length; + mtc->length = (uint8_t)length; return mtc->length; } @@ -666,163 +666,116 @@ void isis_mpls_te_update(struct interface *ifp) * Followings are vty session control functions. *------------------------------------------------------------------------*/ -static u_char show_vty_subtlv_admin_grp(struct vty *vty, - struct te_subtlv_admin_grp *tlv) +static u_char print_subtlv_admin_grp(struct sbuf *buf, int indent, + struct te_subtlv_admin_grp *tlv) { - - if (vty != NULL) - vty_out(vty, " Administrative Group: 0x%x\n", - (u_int32_t)ntohl(tlv->value)); - else - zlog_debug(" Administrative Group: 0x%x", - (u_int32_t)ntohl(tlv->value)); - + sbuf_push(buf, indent, "Administrative Group: 0x%" PRIx32 "\n", + ntohl(tlv->value)); return (SUBTLV_HDR_SIZE + SUBTLV_DEF_SIZE); } -static u_char show_vty_subtlv_llri(struct vty *vty, struct te_subtlv_llri *tlv) +static u_char print_subtlv_llri(struct sbuf *buf, int indent, + struct te_subtlv_llri *tlv) { - if (vty != NULL) { - vty_out(vty, " Link Local ID: %d\n", - (u_int32_t)ntohl(tlv->local)); - vty_out(vty, " Link Remote ID: %d\n", - (u_int32_t)ntohl(tlv->remote)); - } else { - zlog_debug(" Link Local ID: %d", - (u_int32_t)ntohl(tlv->local)); - zlog_debug(" Link Remote ID: %d", - (u_int32_t)ntohl(tlv->remote)); - } + sbuf_push(buf, indent, "Link Local ID: %" PRIu32 "\n", + ntohl(tlv->local)); + sbuf_push(buf, indent, "Link Remote ID: %" PRIu32 "\n", + ntohl(tlv->remote)); return (SUBTLV_HDR_SIZE + TE_SUBTLV_LLRI_SIZE); } -static u_char show_vty_subtlv_local_ipaddr(struct vty *vty, - struct te_subtlv_local_ipaddr *tlv) +static u_char print_subtlv_local_ipaddr(struct sbuf *buf, int indent, + struct te_subtlv_local_ipaddr *tlv) { - if (vty != NULL) - vty_out(vty, " Local Interface IP Address(es): %s\n", - inet_ntoa(tlv->value)); - else - zlog_debug(" Local Interface IP Address(es): %s", - inet_ntoa(tlv->value)); + sbuf_push(buf, indent, "Local Interface IP Address(es): %s\n", + inet_ntoa(tlv->value)); return (SUBTLV_HDR_SIZE + SUBTLV_DEF_SIZE); } -static u_char show_vty_subtlv_rmt_ipaddr(struct vty *vty, - struct te_subtlv_rmt_ipaddr *tlv) +static u_char print_subtlv_rmt_ipaddr(struct sbuf *buf, int indent, + struct te_subtlv_rmt_ipaddr *tlv) { - if (vty != NULL) - vty_out(vty, " Remote Interface IP Address(es): %s\n", - inet_ntoa(tlv->value)); - else - zlog_debug(" Remote Interface IP Address(es): %s", - inet_ntoa(tlv->value)); + sbuf_push(buf, indent, "Remote Interface IP Address(es): %s\n", + inet_ntoa(tlv->value)); return (SUBTLV_HDR_SIZE + SUBTLV_DEF_SIZE); } -static u_char show_vty_subtlv_max_bw(struct vty *vty, - struct te_subtlv_max_bw *tlv) +static u_char print_subtlv_max_bw(struct sbuf *buf, int indent, + struct te_subtlv_max_bw *tlv) { float fval; fval = ntohf(tlv->value); - if (vty != NULL) - vty_out(vty, " Maximum Bandwidth: %g (Bytes/sec)\n", fval); - else - zlog_debug(" Maximum Bandwidth: %g (Bytes/sec)", fval); + sbuf_push(buf, indent, "Maximum Bandwidth: %g (Bytes/sec)\n", fval); return (SUBTLV_HDR_SIZE + SUBTLV_DEF_SIZE); } -static u_char show_vty_subtlv_max_rsv_bw(struct vty *vty, - struct te_subtlv_max_rsv_bw *tlv) +static u_char print_subtlv_max_rsv_bw(struct sbuf *buf, int indent, + struct te_subtlv_max_rsv_bw *tlv) { float fval; fval = ntohf(tlv->value); - if (vty != NULL) - vty_out(vty, - " Maximum Reservable Bandwidth: %g (Bytes/sec)\n", - fval); - else - zlog_debug(" Maximum Reservable Bandwidth: %g (Bytes/sec)", - fval); + sbuf_push(buf, indent, "Maximum Reservable Bandwidth: %g (Bytes/sec)\n", fval); return (SUBTLV_HDR_SIZE + SUBTLV_DEF_SIZE); } -static u_char show_vty_subtlv_unrsv_bw(struct vty *vty, - struct te_subtlv_unrsv_bw *tlv) +static u_char print_subtlv_unrsv_bw(struct sbuf *buf, int indent, + struct te_subtlv_unrsv_bw *tlv) { float fval1, fval2; int i; - if (vty != NULL) - vty_out(vty, " Unreserved Bandwidth:\n"); - else - zlog_debug(" Unreserved Bandwidth:"); + sbuf_push(buf, indent, "Unreserved Bandwidth:\n"); for (i = 0; i < MAX_CLASS_TYPE; i += 2) { fval1 = ntohf(tlv->value[i]); fval2 = ntohf(tlv->value[i + 1]); - if (vty != NULL) - vty_out(vty, - " [%d]: %g (Bytes/sec),\t[%d]: %g (Bytes/sec)\n", - i, fval1, i + 1, fval2); - else - zlog_debug( - " [%d]: %g (Bytes/sec),\t[%d]: %g (Bytes/sec)", - i, fval1, i + 1, fval2); + sbuf_push(buf, indent + 2, "[%d]: %g (Bytes/sec),\t[%d]: %g (Bytes/sec)\n", + i, fval1, i + 1, fval2); } return (SUBTLV_HDR_SIZE + TE_SUBTLV_UNRSV_SIZE); } -static u_char show_vty_subtlv_te_metric(struct vty *vty, - struct te_subtlv_te_metric *tlv) +static u_char print_subtlv_te_metric(struct sbuf *buf, int indent, + struct te_subtlv_te_metric *tlv) { u_int32_t te_metric; te_metric = tlv->value[2] | tlv->value[1] << 8 | tlv->value[0] << 16; - if (vty != NULL) - vty_out(vty, " Traffic Engineering Metric: %u\n", te_metric); - else - zlog_debug(" Traffic Engineering Metric: %u", te_metric); + sbuf_push(buf, indent, "Traffic Engineering Metric: %u\n", te_metric); return (SUBTLV_HDR_SIZE + SUBTLV_DEF_SIZE); } -static u_char show_vty_subtlv_ras(struct vty *vty, struct te_subtlv_ras *tlv) +static u_char print_subtlv_ras(struct sbuf *buf, int indent, + struct te_subtlv_ras *tlv) { - if (vty != NULL) - vty_out(vty, " Inter-AS TE Remote AS number: %u\n", - ntohl(tlv->value)); - else - zlog_debug(" Inter-AS TE Remote AS number: %u", - ntohl(tlv->value)); + sbuf_push(buf, indent, "Inter-AS TE Remote AS number: %" PRIu32 "\n", + ntohl(tlv->value)); return (SUBTLV_HDR_SIZE + SUBTLV_DEF_SIZE); } -static u_char show_vty_subtlv_rip(struct vty *vty, struct te_subtlv_rip *tlv) +static u_char print_subtlv_rip(struct sbuf *buf, int indent, + struct te_subtlv_rip *tlv) { - if (vty != NULL) - vty_out(vty, " Inter-AS TE Remote ASBR IP address: %s\n", - inet_ntoa(tlv->value)); - else - zlog_debug(" Inter-AS TE Remote ASBR IP address: %s", - inet_ntoa(tlv->value)); + sbuf_push(buf, indent, "Inter-AS TE Remote ASBR IP address: %s\n", + inet_ntoa(tlv->value)); return (SUBTLV_HDR_SIZE + SUBTLV_DEF_SIZE); } -static u_char show_vty_subtlv_av_delay(struct vty *vty, - struct te_subtlv_av_delay *tlv) +static u_char print_subtlv_av_delay(struct sbuf *buf, int indent, + struct te_subtlv_av_delay *tlv) { u_int32_t delay; u_int32_t A; @@ -830,18 +783,14 @@ static u_char show_vty_subtlv_av_delay(struct vty *vty, delay = (u_int32_t)ntohl(tlv->value) & TE_EXT_MASK; A = (u_int32_t)ntohl(tlv->value) & TE_EXT_ANORMAL; - if (vty != NULL) - vty_out(vty, " %s Average Link Delay: %d (micro-sec)\n", - A ? "Anomalous" : "Normal", delay); - else - zlog_debug(" %s Average Link Delay: %d (micro-sec)", - A ? "Anomalous" : "Normal", delay); + sbuf_push(buf, indent, "%s Average Link Delay: %" PRIu32 " (micro-sec)\n", + A ? "Anomalous" : "Normal", delay); return (SUBTLV_HDR_SIZE + SUBTLV_DEF_SIZE); } -static u_char show_vty_subtlv_mm_delay(struct vty *vty, - struct te_subtlv_mm_delay *tlv) +static u_char print_subtlv_mm_delay(struct sbuf *buf, int indent, + struct te_subtlv_mm_delay *tlv) { u_int32_t low, high; u_int32_t A; @@ -850,33 +799,26 @@ static u_char show_vty_subtlv_mm_delay(struct vty *vty, A = (u_int32_t)ntohl(tlv->low) & TE_EXT_ANORMAL; high = (u_int32_t)ntohl(tlv->high) & TE_EXT_MASK; - if (vty != NULL) - vty_out(vty, " %s Min/Max Link Delay: %d / %d (micro-sec)\n", - A ? "Anomalous" : "Normal", low, high); - else - zlog_debug(" %s Min/Max Link Delay: %d / %d (micro-sec)", - A ? "Anomalous" : "Normal", low, high); + sbuf_push(buf, indent, "%s Min/Max Link Delay: %" PRIu32 " / %" PRIu32 " (micro-sec)\n", + A ? "Anomalous" : "Normal", low, high); return (SUBTLV_HDR_SIZE + SUBTLV_DEF_SIZE); } -static u_char show_vty_subtlv_delay_var(struct vty *vty, - struct te_subtlv_delay_var *tlv) +static u_char print_subtlv_delay_var(struct sbuf *buf, int indent, + struct te_subtlv_delay_var *tlv) { u_int32_t jitter; jitter = (u_int32_t)ntohl(tlv->value) & TE_EXT_MASK; - if (vty != NULL) - vty_out(vty, " Delay Variation: %d (micro-sec)\n", jitter); - else - zlog_debug(" Delay Variation: %d (micro-sec)", jitter); + sbuf_push(buf, indent, "Delay Variation: %" PRIu32 " (micro-sec)\n", jitter); return (SUBTLV_HDR_SIZE + SUBTLV_DEF_SIZE); } -static u_char show_vty_subtlv_pkt_loss(struct vty *vty, - struct te_subtlv_pkt_loss *tlv) +static u_char print_subtlv_pkt_loss(struct sbuf *buf, int indent, + struct te_subtlv_pkt_loss *tlv) { u_int32_t loss; u_int32_t A; @@ -886,189 +828,162 @@ static u_char show_vty_subtlv_pkt_loss(struct vty *vty, fval = (float)(loss * LOSS_PRECISION); A = (u_int32_t)ntohl(tlv->value) & TE_EXT_ANORMAL; - if (vty != NULL) - vty_out(vty, " %s Link Packet Loss: %g (%%)\n", - A ? "Anomalous" : "Normal", fval); - else - zlog_debug(" %s Link Packet Loss: %g (%%)", - A ? "Anomalous" : "Normal", fval); + sbuf_push(buf, indent, "%s Link Packet Loss: %g (%%)\n", + A ? "Anomalous" : "Normal", fval); return (SUBTLV_HDR_SIZE + SUBTLV_DEF_SIZE); } -static u_char show_vty_subtlv_res_bw(struct vty *vty, - struct te_subtlv_res_bw *tlv) +static u_char print_subtlv_res_bw(struct sbuf *buf, int indent, + struct te_subtlv_res_bw *tlv) { float fval; fval = ntohf(tlv->value); - if (vty != NULL) - vty_out(vty, - " Unidirectional Residual Bandwidth: %g (Bytes/sec)\n", - fval); - else - zlog_debug( - " Unidirectional Residual Bandwidth: %g (Bytes/sec)", - fval); + sbuf_push(buf, indent, "Unidirectional Residual Bandwidth: %g (Bytes/sec)\n", + fval); return (SUBTLV_HDR_SIZE + SUBTLV_DEF_SIZE); } -static u_char show_vty_subtlv_ava_bw(struct vty *vty, - struct te_subtlv_ava_bw *tlv) +static u_char print_subtlv_ava_bw(struct sbuf *buf, int indent, + struct te_subtlv_ava_bw *tlv) { float fval; fval = ntohf(tlv->value); - if (vty != NULL) - vty_out(vty, - " Unidirectional Available Bandwidth: %g (Bytes/sec)\n", - fval); - else - zlog_debug( - " Unidirectional Available Bandwidth: %g (Bytes/sec)", - fval); + sbuf_push(buf, indent, "Unidirectional Available Bandwidth: %g (Bytes/sec)\n", + fval); return (SUBTLV_HDR_SIZE + SUBTLV_DEF_SIZE); } -static u_char show_vty_subtlv_use_bw(struct vty *vty, - struct te_subtlv_use_bw *tlv) +static u_char print_subtlv_use_bw(struct sbuf *buf, int indent, + struct te_subtlv_use_bw *tlv) { float fval; fval = ntohf(tlv->value); - if (vty != NULL) - vty_out(vty, - " Unidirectional Utilized Bandwidth: %g (Bytes/sec)\n", - fval); - else - zlog_debug( - " Unidirectional Utilized Bandwidth: %g (Bytes/sec)", - fval); + sbuf_push(buf, indent, "Unidirectional Utilized Bandwidth: %g (Bytes/sec)\n", + fval); return (SUBTLV_HDR_SIZE + SUBTLV_DEF_SIZE); } -static u_char show_vty_unknown_tlv(struct vty *vty, struct subtlv_header *tlvh) +static u_char print_unknown_tlv(struct sbuf *buf, int indent, + struct subtlv_header *tlvh) { int i, rtn = 1; u_char *v = (u_char *)tlvh; - if (vty != NULL) { - if (tlvh->length != 0) { - vty_out(vty, - " Unknown TLV: [type(%#.2x), length(%#.2x)]\n", - tlvh->type, tlvh->length); - vty_out(vty, " Dump: [00]"); - rtn = 1; /* initialize end of line counter */ - for (i = 0; i < tlvh->length; i++) { - vty_out(vty, " %#.2x", v[i]); - if (rtn == 8) { - vty_out(vty, "\n [%.2x]", - i + 1); - rtn = 1; - } else - rtn++; - } - vty_out(vty, "\n"); - } else - vty_out(vty, - " Unknown TLV: [type(%#.2x), length(%#.2x)]\n", - tlvh->type, tlvh->length); + if (tlvh->length != 0) { + sbuf_push(buf, indent, + "Unknown TLV: [type(%#.2x), length(%#.2x)]\n", + tlvh->type, tlvh->length); + sbuf_push(buf, indent + 2, "Dump: [00]"); + rtn = 1; /* initialize end of line counter */ + for (i = 0; i < tlvh->length; i++) { + sbuf_push(buf, 0, " %#.2x", v[i]); + if (rtn == 8) { + sbuf_push(buf, 0, "\n"); + sbuf_push(buf, indent + 8, + "[%.2x]", i + 1); + rtn = 1; + } else + rtn++; + } + sbuf_push(buf, 0, "\n"); } else { - zlog_debug(" Unknown TLV: [type(%#.2x), length(%#.2x)]", - tlvh->type, tlvh->length); + sbuf_push(buf, indent, + "Unknown TLV: [type(%#.2x), length(%#.2x)]\n", + tlvh->type, tlvh->length); } return SUBTLV_SIZE(tlvh); } /* Main Show function */ -void mpls_te_print_detail(struct vty *vty, struct te_is_neigh *te) +void mpls_te_print_detail(struct sbuf *buf, int indent, + uint8_t *subtlvs, uint8_t subtlv_len) { - struct subtlv_header *tlvh; - u_int16_t sum = 0; - - zlog_debug("ISIS MPLS-TE: Show database TE detail"); + struct subtlv_header *tlvh = (struct subtlv_header *)subtlvs; + uint16_t sum = 0; - tlvh = (struct subtlv_header *)te->sub_tlvs; - - for (; sum < te->sub_tlvs_length; tlvh = SUBTLV_HDR_NEXT(tlvh)) { + for (; sum < subtlv_len; tlvh = SUBTLV_HDR_NEXT(tlvh)) { switch (tlvh->type) { case TE_SUBTLV_ADMIN_GRP: - sum += show_vty_subtlv_admin_grp( - vty, (struct te_subtlv_admin_grp *)tlvh); + sum += print_subtlv_admin_grp(buf, indent, + (struct te_subtlv_admin_grp *)tlvh); break; case TE_SUBTLV_LLRI: - sum += show_vty_subtlv_llri( - vty, (struct te_subtlv_llri *)tlvh); + sum += print_subtlv_llri(buf, indent, + (struct te_subtlv_llri *)tlvh); break; case TE_SUBTLV_LOCAL_IPADDR: - sum += show_vty_subtlv_local_ipaddr( - vty, (struct te_subtlv_local_ipaddr *)tlvh); + sum += print_subtlv_local_ipaddr(buf, indent, + (struct te_subtlv_local_ipaddr *)tlvh); break; case TE_SUBTLV_RMT_IPADDR: - sum += show_vty_subtlv_rmt_ipaddr( - vty, (struct te_subtlv_rmt_ipaddr *)tlvh); + sum += print_subtlv_rmt_ipaddr(buf, indent, + (struct te_subtlv_rmt_ipaddr *)tlvh); break; case TE_SUBTLV_MAX_BW: - sum += show_vty_subtlv_max_bw( - vty, (struct te_subtlv_max_bw *)tlvh); + sum += print_subtlv_max_bw(buf, indent, + (struct te_subtlv_max_bw *)tlvh); break; case TE_SUBTLV_MAX_RSV_BW: - sum += show_vty_subtlv_max_rsv_bw( - vty, (struct te_subtlv_max_rsv_bw *)tlvh); + sum += print_subtlv_max_rsv_bw(buf, indent, + (struct te_subtlv_max_rsv_bw *)tlvh); break; case TE_SUBTLV_UNRSV_BW: - sum += show_vty_subtlv_unrsv_bw( - vty, (struct te_subtlv_unrsv_bw *)tlvh); + sum += print_subtlv_unrsv_bw(buf, indent, + (struct te_subtlv_unrsv_bw *)tlvh); break; case TE_SUBTLV_TE_METRIC: - sum += show_vty_subtlv_te_metric( - vty, (struct te_subtlv_te_metric *)tlvh); + sum += print_subtlv_te_metric(buf, indent, + (struct te_subtlv_te_metric *)tlvh); break; case TE_SUBTLV_RAS: - sum += show_vty_subtlv_ras( - vty, (struct te_subtlv_ras *)tlvh); + sum += print_subtlv_ras(buf, indent, + (struct te_subtlv_ras *)tlvh); break; case TE_SUBTLV_RIP: - sum += show_vty_subtlv_rip( - vty, (struct te_subtlv_rip *)tlvh); + sum += print_subtlv_rip(buf, indent, + (struct te_subtlv_rip *)tlvh); break; case TE_SUBTLV_AV_DELAY: - sum += show_vty_subtlv_av_delay( - vty, (struct te_subtlv_av_delay *)tlvh); + sum += print_subtlv_av_delay(buf, indent, + (struct te_subtlv_av_delay *)tlvh); break; case TE_SUBTLV_MM_DELAY: - sum += show_vty_subtlv_mm_delay( - vty, (struct te_subtlv_mm_delay *)tlvh); + sum += print_subtlv_mm_delay(buf, indent, + (struct te_subtlv_mm_delay *)tlvh); break; case TE_SUBTLV_DELAY_VAR: - sum += show_vty_subtlv_delay_var( - vty, (struct te_subtlv_delay_var *)tlvh); + sum += print_subtlv_delay_var(buf, indent, + (struct te_subtlv_delay_var *)tlvh); break; case TE_SUBTLV_PKT_LOSS: - sum += show_vty_subtlv_pkt_loss( - vty, (struct te_subtlv_pkt_loss *)tlvh); + sum += print_subtlv_pkt_loss(buf, indent, + (struct te_subtlv_pkt_loss *)tlvh); break; case TE_SUBTLV_RES_BW: - sum += show_vty_subtlv_res_bw( - vty, (struct te_subtlv_res_bw *)tlvh); + sum += print_subtlv_res_bw(buf, indent, + (struct te_subtlv_res_bw *)tlvh); break; case TE_SUBTLV_AVA_BW: - sum += show_vty_subtlv_ava_bw( - vty, (struct te_subtlv_ava_bw *)tlvh); + sum += print_subtlv_ava_bw(buf, indent, + (struct te_subtlv_ava_bw *)tlvh); break; case TE_SUBTLV_USE_BW: - sum += show_vty_subtlv_use_bw( - vty, (struct te_subtlv_use_bw *)tlvh); + sum += print_subtlv_use_bw(buf, indent, + (struct te_subtlv_use_bw *)tlvh); break; default: - sum += show_vty_unknown_tlv(vty, tlvh); + sum += print_unknown_tlv(buf, indent, tlvh); break; } } @@ -1252,6 +1167,9 @@ DEFUN (show_isis_mpls_te_router, static void show_mpls_te_sub(struct vty *vty, struct interface *ifp) { struct mpls_te_circuit *mtc; + struct sbuf buf; + + sbuf_init(&buf, NULL, 0); if ((IS_MPLS_TE(isisMplsTE)) && ((mtc = lookup_mpls_params_by_ifp(ifp)) != NULL)) { @@ -1276,38 +1194,42 @@ static void show_mpls_te_sub(struct vty *vty, struct interface *ifp) ifp->name); } - show_vty_subtlv_admin_grp(vty, &mtc->admin_grp); + sbuf_reset(&buf); + print_subtlv_admin_grp(&buf, 4, &mtc->admin_grp); if (SUBTLV_TYPE(mtc->local_ipaddr) != 0) - show_vty_subtlv_local_ipaddr(vty, &mtc->local_ipaddr); + print_subtlv_local_ipaddr(&buf, 4, &mtc->local_ipaddr); if (SUBTLV_TYPE(mtc->rmt_ipaddr) != 0) - show_vty_subtlv_rmt_ipaddr(vty, &mtc->rmt_ipaddr); + print_subtlv_rmt_ipaddr(&buf, 4, &mtc->rmt_ipaddr); - show_vty_subtlv_max_bw(vty, &mtc->max_bw); - show_vty_subtlv_max_rsv_bw(vty, &mtc->max_rsv_bw); - show_vty_subtlv_unrsv_bw(vty, &mtc->unrsv_bw); - show_vty_subtlv_te_metric(vty, &mtc->te_metric); + print_subtlv_max_bw(&buf, 4, &mtc->max_bw); + print_subtlv_max_rsv_bw(&buf, 4, &mtc->max_rsv_bw); + print_subtlv_unrsv_bw(&buf, 4, &mtc->unrsv_bw); + print_subtlv_te_metric(&buf, 4, &mtc->te_metric); if (IS_INTER_AS(mtc->type)) { if (SUBTLV_TYPE(mtc->ras) != 0) - show_vty_subtlv_ras(vty, &mtc->ras); + print_subtlv_ras(&buf, 4, &mtc->ras); if (SUBTLV_TYPE(mtc->rip) != 0) - show_vty_subtlv_rip(vty, &mtc->rip); + print_subtlv_rip(&buf, 4, &mtc->rip); } - show_vty_subtlv_av_delay(vty, &mtc->av_delay); - show_vty_subtlv_mm_delay(vty, &mtc->mm_delay); - show_vty_subtlv_delay_var(vty, &mtc->delay_var); - show_vty_subtlv_pkt_loss(vty, &mtc->pkt_loss); - show_vty_subtlv_res_bw(vty, &mtc->res_bw); - show_vty_subtlv_ava_bw(vty, &mtc->ava_bw); - show_vty_subtlv_use_bw(vty, &mtc->use_bw); + print_subtlv_av_delay(&buf, 4, &mtc->av_delay); + print_subtlv_mm_delay(&buf, 4, &mtc->mm_delay); + print_subtlv_delay_var(&buf, 4, &mtc->delay_var); + print_subtlv_pkt_loss(&buf, 4, &mtc->pkt_loss); + print_subtlv_res_bw(&buf, 4, &mtc->res_bw); + print_subtlv_ava_bw(&buf, 4, &mtc->ava_bw); + print_subtlv_use_bw(&buf, 4, &mtc->use_bw); + + vty_multiline(vty, "", "%s", sbuf_buf(&buf)); vty_out(vty, "---------------\n\n"); } else { vty_out(vty, " %s: MPLS-TE is disabled on this interface\n", ifp->name); } + sbuf_free(&buf); return; } diff --git a/isisd/isis_te.h b/isisd/isis_te.h index 0bd076af1..9b29792e2 100644 --- a/isisd/isis_te.h +++ b/isisd/isis_te.h @@ -81,6 +81,8 @@ struct subtlv_header { u_char length; /* Value portion only, in byte */ }; +#define MAX_SUBTLV_SIZE 256 + #define SUBTLV_HDR_SIZE 2 /* (sizeof (struct sub_tlv_header)) */ #define SUBTLV_SIZE(stlvh) (SUBTLV_HDR_SIZE + (stlvh)->length) @@ -306,12 +308,13 @@ struct mpls_te_circuit { /* Prototypes. */ void isis_mpls_te_init(void); struct mpls_te_circuit *mpls_te_circuit_new(void); -void mpls_te_print_detail(struct vty *, struct te_is_neigh *); +struct sbuf; +void mpls_te_print_detail(struct sbuf *buf, int indent, uint8_t *subtlvs, uint8_t subtlv_len); void set_circuitparams_local_ipaddr(struct mpls_te_circuit *, struct in_addr); void set_circuitparams_rmt_ipaddr(struct mpls_te_circuit *, struct in_addr); -u_char subtlvs_len(struct mpls_te_circuit *); -u_char add_te_subtlvs(u_char *, struct mpls_te_circuit *); -u_char build_te_subtlvs(u_char *, struct isis_circuit *); +uint8_t subtlvs_len(struct mpls_te_circuit *); +uint8_t add_te_subtlvs(uint8_t *, struct mpls_te_circuit *); +uint8_t build_te_subtlvs(uint8_t *, struct isis_circuit *); void isis_link_params_update(struct isis_circuit *, struct interface *); void isis_mpls_te_update(struct interface *); void isis_mpls_te_config_write_router(struct vty *); diff --git a/isisd/isis_tlv.c b/isisd/isis_tlv.c deleted file mode 100644 index a295f4dd3..000000000 --- a/isisd/isis_tlv.c +++ /dev/null @@ -1,1453 +0,0 @@ -/* - * IS-IS Rout(e)ing protocol - isis_tlv.c - * IS-IS TLV related routines - * - * Copyright (C) 2001,2002 Sampo Saaristo - * Tampere University of Technology - * Institute of Communications Engineering - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public Licenseas 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 "log.h" -#include "linklist.h" -#include "stream.h" -#include "memory.h" -#include "prefix.h" -#include "vty.h" -#include "if.h" - -#include "isisd/dict.h" -#include "isisd/isis_constants.h" -#include "isisd/isis_common.h" -#include "isisd/isis_flags.h" -#include "isisd/isis_circuit.h" -#include "isisd/isis_tlv.h" -#include "isisd/isisd.h" -#include "isisd/isis_dynhn.h" -#include "isisd/isis_misc.h" -#include "isisd/isis_pdu.h" -#include "isisd/isis_lsp.h" -#include "isisd/isis_te.h" -#include "isisd/isis_mt.h" - -void free_tlv(void *val) -{ - XFREE(MTYPE_ISIS_TLV, val); - - return; -} - -/* - * Called after parsing of a PDU. There shouldn't be any tlv's left, so this - * is only a caution to avoid memory leaks - */ -void free_tlvs(struct tlvs *tlvs) -{ - if (tlvs->area_addrs) - list_delete(tlvs->area_addrs); - if (tlvs->mt_router_info) - list_delete(tlvs->mt_router_info); - if (tlvs->is_neighs) - list_delete(tlvs->is_neighs); - if (tlvs->te_is_neighs) - list_delete(tlvs->te_is_neighs); - if (tlvs->mt_is_neighs) - list_delete(tlvs->mt_is_neighs); - if (tlvs->es_neighs) - list_delete(tlvs->es_neighs); - if (tlvs->lsp_entries) - list_delete(tlvs->lsp_entries); - if (tlvs->prefix_neighs) - list_delete(tlvs->prefix_neighs); - if (tlvs->lan_neighs) - list_delete(tlvs->lan_neighs); - if (tlvs->ipv4_addrs) - list_delete(tlvs->ipv4_addrs); - if (tlvs->ipv4_int_reachs) - list_delete(tlvs->ipv4_int_reachs); - if (tlvs->ipv4_ext_reachs) - list_delete(tlvs->ipv4_ext_reachs); - if (tlvs->te_ipv4_reachs) - list_delete(tlvs->te_ipv4_reachs); - if (tlvs->mt_ipv4_reachs) - list_delete(tlvs->mt_ipv4_reachs); - if (tlvs->ipv6_addrs) - list_delete(tlvs->ipv6_addrs); - if (tlvs->ipv6_reachs) - list_delete(tlvs->ipv6_reachs); - if (tlvs->mt_ipv6_reachs) - list_delete(tlvs->mt_ipv6_reachs); - - memset(tlvs, 0, sizeof(struct tlvs)); - - return; -} - -static int parse_mtid(uint16_t *mtid, bool read_mtid, unsigned int *length, - u_char **pnt) -{ - if (!read_mtid) { - *mtid = ISIS_MT_IPV4_UNICAST; - return ISIS_OK; - } - - uint16_t mtid_buf; - - if (*length < sizeof(mtid_buf)) { - zlog_warn("ISIS-TLV: mt tlv too short to contain MT id"); - return ISIS_WARNING; - } - - memcpy(&mtid_buf, *pnt, sizeof(mtid_buf)); - *pnt += sizeof(mtid_buf); - *length -= sizeof(mtid_buf); - - *mtid = ntohs(mtid_buf) & ISIS_MT_MASK; - return ISIS_OK; -} - -static int parse_mt_is_neighs(struct tlvs *tlvs, bool read_mtid, - unsigned int length, u_char *pnt) -{ - struct list *neigh_list; - uint16_t mtid; - int rv; - - rv = parse_mtid(&mtid, read_mtid, &length, &pnt); - if (rv != ISIS_OK) - return rv; - - if (mtid == ISIS_MT_IPV4_UNICAST) { - if (!tlvs->te_is_neighs) { - tlvs->te_is_neighs = list_new(); - tlvs->te_is_neighs->del = free_tlv; - } - neigh_list = tlvs->te_is_neighs; - } else { - struct tlv_mt_neighbors *neighbors; - - neighbors = tlvs_get_mt_neighbors(tlvs, mtid); - neighbors->list->del = free_tlv; - neigh_list = neighbors->list; - } - - while (length >= IS_NEIGHBOURS_LEN) { - struct te_is_neigh *neigh = - XCALLOC(MTYPE_ISIS_TLV, sizeof(*neigh)); - - memcpy(neigh, pnt, IS_NEIGHBOURS_LEN); - pnt += IS_NEIGHBOURS_LEN; - length -= IS_NEIGHBOURS_LEN; - - if (neigh->sub_tlvs_length > length) { - zlog_warn( - "ISIS-TLV: neighbor subtlv length exceeds TLV size"); - XFREE(MTYPE_ISIS_TLV, neigh); - return ISIS_WARNING; - } - - memcpy(neigh->sub_tlvs, pnt, neigh->sub_tlvs_length); - pnt += neigh->sub_tlvs_length; - length -= neigh->sub_tlvs_length; - - listnode_add(neigh_list, neigh); - } - - if (length) { - zlog_warn("ISIS-TLV: TE/MT neighor TLV has trailing data"); - return ISIS_WARNING; - } - - return ISIS_OK; -} - -static int parse_mt_ipv4_reachs(struct tlvs *tlvs, bool read_mtid, - unsigned int length, u_char *pnt) -{ - struct list *reach_list; - uint16_t mtid; - int rv; - - rv = parse_mtid(&mtid, read_mtid, &length, &pnt); - if (rv != ISIS_OK) - return rv; - - if (mtid == ISIS_MT_IPV4_UNICAST) { - if (!tlvs->te_ipv4_reachs) { - tlvs->te_ipv4_reachs = list_new(); - tlvs->te_ipv4_reachs->del = free_tlv; - } - reach_list = tlvs->te_ipv4_reachs; - } else { - struct tlv_mt_ipv4_reachs *reachs; - - reachs = tlvs_get_mt_ipv4_reachs(tlvs, mtid); - reachs->list->del = free_tlv; - reach_list = reachs->list; - } - - while (length >= 5) /* Metric + Control */ - { - struct te_ipv4_reachability *reach = - XCALLOC(MTYPE_ISIS_TLV, TE_IPV4_REACH_LEN); - - memcpy(reach, pnt, 5); /* Metric + Control */ - pnt += 5; - length -= 5; - - unsigned char prefixlen = reach->control & 0x3F; - - if (prefixlen > IPV4_MAX_BITLEN) { - zlog_warn( - "ISIS-TLV: invalid IPv4 extended reachability prefix length %d", - prefixlen); - XFREE(MTYPE_ISIS_TLV, reach); - return ISIS_WARNING; - } - - if (length < (unsigned int)PSIZE(prefixlen)) { - zlog_warn( - "ISIS-TLV: invalid IPv4 extended reachability prefix too long for tlv"); - XFREE(MTYPE_ISIS_TLV, reach); - return ISIS_WARNING; - } - - memcpy(&reach->prefix_start, pnt, PSIZE(prefixlen)); - pnt += PSIZE(prefixlen); - length -= PSIZE(prefixlen); - - if (reach->control & TE_IPV4_HAS_SUBTLV) { - if (length < 1) { - zlog_warn( - "ISIS-TLV: invalid IPv4 extended reachability SubTLV missing"); - XFREE(MTYPE_ISIS_TLV, reach); - return ISIS_WARNING; - } - - u_char subtlv_len = *pnt; - pnt++; - length--; - - if (length < subtlv_len) { - zlog_warn( - "ISIS-TLV: invalid IPv4 extended reachability SubTLVs have oversize"); - XFREE(MTYPE_ISIS_TLV, reach); - return ISIS_WARNING; - } - - /* Skip Sub-TLVs for now */ - pnt += subtlv_len; - length -= subtlv_len; - } - listnode_add(reach_list, reach); - } - - if (length) { - zlog_warn( - "ISIS-TLV: TE/MT ipv4 reachability TLV has trailing data"); - return ISIS_WARNING; - } - - return ISIS_OK; -} - -static int parse_mt_ipv6_reachs(struct tlvs *tlvs, bool read_mtid, - unsigned int length, u_char *pnt) -{ - struct list *reach_list; - uint16_t mtid; - int rv; - - rv = parse_mtid(&mtid, read_mtid, &length, &pnt); - if (rv != ISIS_OK) - return rv; - - if (mtid == ISIS_MT_IPV4_UNICAST) { - if (!tlvs->ipv6_reachs) { - tlvs->ipv6_reachs = list_new(); - tlvs->ipv6_reachs->del = free_tlv; - } - reach_list = tlvs->ipv6_reachs; - } else { - struct tlv_mt_ipv6_reachs *reachs; - - reachs = tlvs_get_mt_ipv6_reachs(tlvs, mtid); - reachs->list->del = free_tlv; - reach_list = reachs->list; - } - - while (length >= 6) /* Metric + Control + Prefixlen */ - { - struct ipv6_reachability *reach = - XCALLOC(MTYPE_ISIS_TLV, sizeof(*reach)); - - memcpy(reach, pnt, 6); /* Metric + Control + Prefixlen */ - pnt += 6; - length -= 6; - - if (reach->prefix_len > IPV6_MAX_BITLEN) { - zlog_warn( - "ISIS-TLV: invalid IPv6 reachability prefix length %d", - reach->prefix_len); - XFREE(MTYPE_ISIS_TLV, reach); - return ISIS_WARNING; - } - - if (length < (unsigned int)PSIZE(reach->prefix_len)) { - zlog_warn( - "ISIS-TLV: invalid IPv6 reachability prefix too long for tlv"); - XFREE(MTYPE_ISIS_TLV, reach); - return ISIS_WARNING; - } - - memcpy(&reach->prefix, pnt, PSIZE(reach->prefix_len)); - pnt += PSIZE(reach->prefix_len); - length -= PSIZE(reach->prefix_len); - - if (reach->control_info & CTRL_INFO_SUBTLVS) { - if (length < 1) { - zlog_warn( - "ISIS-TLV: invalid IPv6 reachability SubTLV missing"); - XFREE(MTYPE_ISIS_TLV, reach); - return ISIS_WARNING; - } - - u_char subtlv_len = *pnt; - pnt++; - length--; - - if (length < subtlv_len) { - zlog_warn( - "ISIS-TLV: invalid IPv6 reachability SubTLVs have oversize"); - XFREE(MTYPE_ISIS_TLV, reach); - return ISIS_WARNING; - } - - /* Skip Sub-TLVs for now */ - pnt += subtlv_len; - length -= subtlv_len; - } - listnode_add(reach_list, reach); - } - - if (length) { - zlog_warn( - "ISIS-TLV: (MT) IPv6 reachability TLV has trailing data"); - return ISIS_WARNING; - } - - return ISIS_OK; -} - -/* - * Parses the tlvs found in the variant length part of the PDU. - * Caller tells with flags in "expected" which TLV's it is interested in. - */ -int parse_tlvs(char *areatag, u_char *stream, int size, u_int32_t *expected, - u_int32_t *found, struct tlvs *tlvs, u_int32_t *auth_tlv_offset) -{ - u_char type, length; - struct lan_neigh *lan_nei; - struct area_addr *area_addr; - struct is_neigh *is_nei; - struct es_neigh *es_nei; - struct lsp_entry *lsp_entry; - struct in_addr *ipv4_addr; - struct ipv4_reachability *ipv4_reach; - struct in6_addr *ipv6_addr; - int value_len, retval = ISIS_OK; - u_char *start = stream, *pnt = stream; - - *found = 0; - memset(tlvs, 0, sizeof(struct tlvs)); - - while (pnt < stream + size - 2) { - type = *pnt; - length = *(pnt + 1); - pnt += 2; - value_len = 0; - if (pnt + length > stream + size) { - zlog_warn( - "ISIS-TLV (%s): TLV (type %d, length %d) exceeds packet " - "boundaries", - areatag, type, length); - retval = ISIS_WARNING; - break; - } - switch (type) { - case AREA_ADDRESSES: - /* +-------+-------+-------+-------+-------+-------+-------+-------+ - * | Address Length | - * +-------+-------+-------+-------+-------+-------+-------+-------+ - * | Area Address | - * +-------+-------+-------+-------+-------+-------+-------+-------+ - * : : - */ - *found |= TLVFLAG_AREA_ADDRS; -#ifdef EXTREME_TLV_DEBUG - zlog_debug("TLV Area Adresses len %d", length); -#endif /* EXTREME_TLV_DEBUG */ - if (*expected & TLVFLAG_AREA_ADDRS) { - while (length > value_len) { - area_addr = (struct area_addr *)pnt; - value_len += area_addr->addr_len + 1; - pnt += area_addr->addr_len + 1; - if (!tlvs->area_addrs) - tlvs->area_addrs = list_new(); - listnode_add(tlvs->area_addrs, - area_addr); - } - } else { - pnt += length; - } - break; - - case IS_NEIGHBOURS: - *found |= TLVFLAG_IS_NEIGHS; -#ifdef EXTREME_TLV_DEBUG - zlog_debug("ISIS-TLV (%s): IS Neighbours length %d", - areatag, length); -#endif /* EXTREME_TLV_DEBUG */ - if (TLVFLAG_IS_NEIGHS & *expected) { - /* +-------+-------+-------+-------+-------+-------+-------+-------+ - * | Virtual Flag | - * +-------+-------+-------+-------+-------+-------+-------+-------+ - */ - pnt++; - value_len++; - /* +-------+-------+-------+-------+-------+-------+-------+-------+ - * | 0 | I/E | Default - * Metric | - * +-------+-------+-------+-------+-------+-------+-------+-------+ - * | S | I/E | Delay Metric - * | - * +-------+-------+-------+-------+-------+-------+-------+-------+ - * | S | I/E | Expense - * Metric | - * +-------+-------+-------+-------+-------+-------+-------+-------+ - * | S | I/E | Error Metric - * | - * +-------+-------+-------+-------+-------+-------+-------+-------+ - * | Neighbour ID | - * +---------------------------------------------------------------+ - * : : - */ - while (length > value_len) { - is_nei = (struct is_neigh *)pnt; - value_len += 4 + ISIS_SYS_ID_LEN + 1; - pnt += 4 + ISIS_SYS_ID_LEN + 1; - if (!tlvs->is_neighs) - tlvs->is_neighs = list_new(); - listnode_add(tlvs->is_neighs, is_nei); - } - } else { - pnt += length; - } - break; - - case TE_IS_NEIGHBOURS: - *found |= TLVFLAG_TE_IS_NEIGHS; -#ifdef EXTREME_TLV_DEBUG - zlog_debug( - "ISIS-TLV (%s): Extended IS Neighbours length %d", - areatag, length); -#endif /* EXTREME_TLV_DEBUG */ - if (TLVFLAG_TE_IS_NEIGHS & *expected) - retval = parse_mt_is_neighs(tlvs, false, length, - pnt); - pnt += length; - break; - - case MT_IS_NEIGHBOURS: - *found |= TLVFLAG_TE_IS_NEIGHS; -#ifdef EXTREME_TLV_DEBUG - zlog_debug("ISIS-TLV (%s): MT IS Neighbours length %d", - areatag, length); -#endif - if (TLVFLAG_TE_IS_NEIGHS & *expected) - retval = parse_mt_is_neighs(tlvs, true, length, - pnt); - pnt += length; - break; - - case ES_NEIGHBOURS: -/* +-------+-------+-------+-------+-------+-------+-------+-------+ - * | 0 | I/E | Default Metric | - * +-------+-------+-------+-------+-------+-------+-------+-------+ - * | S | I/E | Delay Metric | - * +-------+-------+-------+-------+-------+-------+-------+-------+ - * | S | I/E | Expense Metric | - * +-------+-------+-------+-------+-------+-------+-------+-------+ - * | S | I/E | Error Metric | - * +-------+-------+-------+-------+-------+-------+-------+-------+ - * | Neighbour ID | - * +---------------------------------------------------------------+ - * | Neighbour ID | - * +---------------------------------------------------------------+ - * : : - */ -#ifdef EXTREME_TLV_DEBUG - zlog_debug("ISIS-TLV (%s): ES Neighbours length %d", - areatag, length); -#endif /* EXTREME_TLV_DEBUG */ - *found |= TLVFLAG_ES_NEIGHS; - if (*expected & TLVFLAG_ES_NEIGHS) { - es_nei = (struct es_neigh *)pnt; - value_len += 4; - pnt += 4; - while (length > value_len) { - /* FIXME FIXME FIXME - add to the list - */ - /* sys_id->id = pnt; */ - value_len += ISIS_SYS_ID_LEN; - pnt += ISIS_SYS_ID_LEN; - /* if (!es_nei->neigh_ids) - * es_nei->neigh_ids = sysid; */ - } - if (!tlvs->es_neighs) - tlvs->es_neighs = list_new(); - listnode_add(tlvs->es_neighs, es_nei); - } else { - pnt += length; - } - break; - - case LAN_NEIGHBOURS: - /* +-------+-------+-------+-------+-------+-------+-------+-------+ - * | LAN Address | - * +-------+-------+-------+-------+-------+-------+-------+-------+ - * : : - */ - *found |= TLVFLAG_LAN_NEIGHS; -#ifdef EXTREME_TLV_DEBUG - zlog_debug("ISIS-TLV (%s): LAN Neigbours length %d", - areatag, length); -#endif /* EXTREME_TLV_DEBUG */ - if (TLVFLAG_LAN_NEIGHS & *expected) { - while (length > value_len) { - lan_nei = (struct lan_neigh *)pnt; - if (!tlvs->lan_neighs) - tlvs->lan_neighs = list_new(); - listnode_add(tlvs->lan_neighs, lan_nei); - value_len += ETH_ALEN; - pnt += ETH_ALEN; - } - } else { - pnt += length; - } - break; - - case PADDING: -#ifdef EXTREME_TLV_DEBUG - zlog_debug("TLV padding %d", length); -#endif /* EXTREME_TLV_DEBUG */ - pnt += length; - break; - - case LSP_ENTRIES: -/* +-------+-------+-------+-------+-------+-------+-------+-------+ - * | Remaining Lifetime | 2 - * +-------+-------+-------+-------+-------+-------+-------+-------+ - * | LSP ID | id+2 - * +-------+-------+-------+-------+-------+-------+-------+-------+ - * | LSP Sequence Number | 4 - * +-------+-------+-------+-------+-------+-------+-------+-------+ - * | Checksum | 2 - * +-------+-------+-------+-------+-------+-------+-------+-------+ - */ -#ifdef EXTREME_TLV_DEBUG - zlog_debug("ISIS-TLV (%s): LSP Entries length %d", - areatag, length); -#endif /* EXTREME_TLV_DEBUG */ - *found |= TLVFLAG_LSP_ENTRIES; - if (TLVFLAG_LSP_ENTRIES & *expected) { - while (length > value_len) { - lsp_entry = (struct lsp_entry *)pnt; - value_len += 10 + ISIS_SYS_ID_LEN; - pnt += 10 + ISIS_SYS_ID_LEN; - if (!tlvs->lsp_entries) - tlvs->lsp_entries = list_new(); - listnode_add(tlvs->lsp_entries, - lsp_entry); - } - } else { - pnt += length; - } - break; - - case CHECKSUM: - /* +-------+-------+-------+-------+-------+-------+-------+-------+ - * | 16 bit fletcher CHECKSUM | - * +-------+-------+-------+-------+-------+-------+-------+-------+ - * : : - */ - *found |= TLVFLAG_CHECKSUM; -#ifdef EXTREME_TLV_DEBUG - zlog_debug("ISIS-TLV (%s): Checksum length %d", areatag, - length); -#endif /* EXTREME_TLV_DEBUG */ - if (*expected & TLVFLAG_CHECKSUM) { - tlvs->checksum = (struct checksum *)pnt; - } - pnt += length; - break; - - case PROTOCOLS_SUPPORTED: - /* +-------+-------+-------+-------+-------+-------+-------+-------+ - * | NLPID | - * +-------+-------+-------+-------+-------+-------+-------+-------+ - * : : - */ - *found |= TLVFLAG_NLPID; -#ifdef EXTREME_TLV_DEBUG - zlog_debug( - "ISIS-TLV (%s): Protocols Supported length %d", - areatag, length); -#endif /* EXTREME_TLV_DEBUG */ - if (*expected & TLVFLAG_NLPID) { - tlvs->nlpids = (struct nlpids *)(pnt - 1); - } - pnt += length; - break; - - case IPV4_ADDR: - /* +-------+-------+-------+-------+-------+-------+-------+-------+ - * + IP version 4 address + 4 - * +-------+-------+-------+-------+-------+-------+-------+-------+ - * : : - */ - *found |= TLVFLAG_IPV4_ADDR; -#ifdef EXTREME_TLV_DEBUG - zlog_debug("ISIS-TLV (%s): IPv4 Address length %d", - areatag, length); -#endif /* EXTREME_TLV_DEBUG */ - if (*expected & TLVFLAG_IPV4_ADDR) { - while (length > value_len) { - ipv4_addr = (struct in_addr *)pnt; -#ifdef EXTREME_TLV_DEBUG - zlog_debug( - "ISIS-TLV (%s) : IP ADDR %s, pnt %p", - areatag, inet_ntoa(*ipv4_addr), - pnt); -#endif /* EXTREME_TLV_DEBUG */ - if (!tlvs->ipv4_addrs) - tlvs->ipv4_addrs = list_new(); - listnode_add(tlvs->ipv4_addrs, - ipv4_addr); - value_len += 4; - pnt += 4; - } - } else { - pnt += length; - } - break; - - case AUTH_INFO: - *found |= TLVFLAG_AUTH_INFO; -#ifdef EXTREME_TLV_DEBUG - zlog_debug( - "ISIS-TLV (%s): IS-IS Authentication Information", - areatag); -#endif - if (*expected & TLVFLAG_AUTH_INFO) { - tlvs->auth_info.type = *pnt; - if (length == 0) { - zlog_warn( - "ISIS-TLV (%s): TLV (type %d, length %d) " - "incorrect.", - areatag, type, length); - return ISIS_WARNING; - } - --length; - tlvs->auth_info.len = length; - pnt++; - memcpy(tlvs->auth_info.passwd, pnt, length); - /* Return the authentication tlv pos for later - * computation - * of MD5 (RFC 5304, 2) - */ - if (auth_tlv_offset) - *auth_tlv_offset += (pnt - start - 3); - pnt += length; - } else { - pnt += length; - } - break; - - case DYNAMIC_HOSTNAME: - *found |= TLVFLAG_DYN_HOSTNAME; -#ifdef EXTREME_TLV_DEBUG - zlog_debug("ISIS-TLV (%s): Dynamic Hostname length %d", - areatag, length); -#endif /* EXTREME_TLV_DEBUG */ - if (*expected & TLVFLAG_DYN_HOSTNAME) { - /* the length is also included in the pointed - * struct */ - tlvs->hostname = (struct hostname *)(pnt - 1); - } - pnt += length; - break; - - case TE_ROUTER_ID: - /* +---------------------------------------------------------------+ - * + Router ID + 4 - * +---------------------------------------------------------------+ - */ - *found |= TLVFLAG_TE_ROUTER_ID; -#ifdef EXTREME_TLV_DEBUG - zlog_debug("ISIS-TLV (%s): TE Router ID %d", areatag, - length); -#endif /* EXTREME_TLV_DEBUG */ - if (*expected & TLVFLAG_TE_ROUTER_ID) - tlvs->router_id = (struct te_router_id *)(pnt); - pnt += length; - break; - - case IPV4_INT_REACHABILITY: - /* +-------+-------+-------+-------+-------+-------+-------+-------+ - * | 0 | I/E | Default Metric | 1 - * +-------+-------+-------+-------+-------+-------+-------+-------+ - * | S | I/E | Delay Metric | 1 - * +-------+-------+-------+-------+-------+-------+-------+-------+ - * | S | I/E | Expense Metric | 1 - * +-------+-------+-------+-------+-------+-------+-------+-------+ - * | S | I/E | Error Metric | 1 - * +-------+-------+-------+-------+-------+-------+-------+-------+ - * | ip address | 4 - * +---------------------------------------------------------------+ - * | address mask | 4 - * +---------------------------------------------------------------+ - * : : - */ - *found |= TLVFLAG_IPV4_INT_REACHABILITY; -#ifdef EXTREME_TLV_DEBUG - zlog_debug( - "ISIS-TLV (%s): IPv4 internal Reachability length %d", - areatag, length); -#endif /* EXTREME_TLV_DEBUG */ - if (*expected & TLVFLAG_IPV4_INT_REACHABILITY) { - while (length > value_len) { - ipv4_reach = - (struct ipv4_reachability *)pnt; - if (!tlvs->ipv4_int_reachs) - tlvs->ipv4_int_reachs = - list_new(); - listnode_add(tlvs->ipv4_int_reachs, - ipv4_reach); - value_len += 12; - pnt += 12; - } - } else { - pnt += length; - } - break; - - case IPV4_EXT_REACHABILITY: - /* +-------+-------+-------+-------+-------+-------+-------+-------+ - * | 0 | I/E | Default Metric | 1 - * +-------+-------+-------+-------+-------+-------+-------+-------+ - * | S | I/E | Delay Metric | 1 - * +-------+-------+-------+-------+-------+-------+-------+-------+ - * | S | I/E | Expense Metric | 1 - * +-------+-------+-------+-------+-------+-------+-------+-------+ - * | S | I/E | Error Metric | 1 - * +-------+-------+-------+-------+-------+-------+-------+-------+ - * | ip address | 4 - * +---------------------------------------------------------------+ - * | address mask | 4 - * +---------------------------------------------------------------+ - * : : - */ - *found |= TLVFLAG_IPV4_EXT_REACHABILITY; -#ifdef EXTREME_TLV_DEBUG - zlog_debug( - "ISIS-TLV (%s): IPv4 external Reachability length %d", - areatag, length); -#endif /* EXTREME_TLV_DEBUG */ - if (*expected & TLVFLAG_IPV4_EXT_REACHABILITY) { - while (length > value_len) { - ipv4_reach = - (struct ipv4_reachability *)pnt; - if (!tlvs->ipv4_ext_reachs) - tlvs->ipv4_ext_reachs = - list_new(); - listnode_add(tlvs->ipv4_ext_reachs, - ipv4_reach); - value_len += 12; - pnt += 12; - } - } else { - pnt += length; - } - break; - - case TE_IPV4_REACHABILITY: - *found |= TLVFLAG_TE_IPV4_REACHABILITY; -#ifdef EXTREME_TLV_DEBUG - zlog_debug( - "ISIS-TLV (%s): IPv4 extended Reachability length %d", - areatag, length); -#endif /* EXTREME_TLV_DEBUG */ - if (*expected & TLVFLAG_TE_IPV4_REACHABILITY) - retval = parse_mt_ipv4_reachs(tlvs, false, - length, pnt); - pnt += length; - break; - case MT_IPV4_REACHABILITY: - *found |= TLVFLAG_TE_IPV4_REACHABILITY; -#ifdef EXTREME_TLV_DEBUG - zlog_debug( - "ISIS-TLV (%s): IPv4 MT Reachability length %d", - areatag, length); -#endif /* EXTREME_TLV_DEBUG */ - if (*expected & TLVFLAG_TE_IPV4_REACHABILITY) - retval = parse_mt_ipv4_reachs(tlvs, true, - length, pnt); - pnt += length; - break; - case IPV6_ADDR: - /* +-------+-------+-------+-------+-------+-------+-------+-------+ - * + IP version 6 address + 16 - * +-------+-------+-------+-------+-------+-------+-------+-------+ - * : : - */ - *found |= TLVFLAG_IPV6_ADDR; -#ifdef EXTREME_TLV_DEBUG - zlog_debug("ISIS-TLV (%s): IPv6 Address length %d", - areatag, length); -#endif /* EXTREME_TLV_DEBUG */ - if (*expected & TLVFLAG_IPV6_ADDR) { - while (length > value_len) { - ipv6_addr = (struct in6_addr *)pnt; - if (!tlvs->ipv6_addrs) - tlvs->ipv6_addrs = list_new(); - listnode_add(tlvs->ipv6_addrs, - ipv6_addr); - value_len += 16; - pnt += 16; - } - } else { - pnt += length; - } - break; - - case IPV6_REACHABILITY: - *found |= TLVFLAG_IPV6_REACHABILITY; -#ifdef EXTREME_TLV_DEBUG - zlog_debug("ISIS-TLV (%s): IPv6 Reachability length %d", - areatag, length); -#endif /* EXTREME_TLV_DEBUG */ - if (*expected & TLVFLAG_IPV6_REACHABILITY) - retval = parse_mt_ipv6_reachs(tlvs, false, - length, pnt); - pnt += length; - break; - case MT_IPV6_REACHABILITY: - *found |= TLVFLAG_IPV6_REACHABILITY; -#ifdef EXTREME_TLV_DEBUG - zlog_debug("ISIS-TLV (%s): IPv6 Reachability length %d", - areatag, length); -#endif /* EXTREME_TLV_DEBUG */ - if (*expected & TLVFLAG_IPV6_REACHABILITY) - retval = parse_mt_ipv6_reachs(tlvs, true, - length, pnt); - pnt += length; - break; - case WAY3_HELLO: - /* +---------------------------------------------------------------+ - * | Adjacency state | 1 - * +---------------------------------------------------------------+ - * | Extended Local Circuit ID | 4 - * +---------------------------------------------------------------+ - * | Neighbor System ID (If known) - * | 0-8 - * (probably 6) - * +---------------------------------------------------------------+ - * | Neighbor Local Circuit ID (If - * known) | 4 - * +---------------------------------------------------------------+ - */ - *found |= TLVFLAG_3WAY_HELLO; - if (*expected & TLVFLAG_3WAY_HELLO) { - while (length > value_len) { - /* FIXME: make this work */ - /* Adjacency State (one - octet): - 0 = Up - 1 = Initializing - 2 = Down - Extended Local Circuit ID - (four octets) - Neighbor System ID if known - (zero to eight octets) - Neighbor Extended Local - Circuit ID (four octets, if Neighbor - System ID is present) */ - pnt += length; - value_len += length; - } - } else { - pnt += length; - } - - break; - case GRACEFUL_RESTART: - /* +-------+-------+-------+-------+-------+-------+-------+-------+ - * | Reserved | SA | RA - * | RR | 1 - * +-------+-------+-------+-------+-------+-------+-------+-------+ - * | Remaining Time | 2 - * +---------------------------------------------------------------+ - * | Restarting Neighbor ID (If known) - * | 0-8 - * +---------------------------------------------------------------+ - */ - *found |= TLVFLAG_GRACEFUL_RESTART; - if (*expected & TLVFLAG_GRACEFUL_RESTART) { - /* FIXME: make this work */ - } - pnt += length; - break; - - case MT_ROUTER_INFORMATION: - *found |= TLVFLAG_MT_ROUTER_INFORMATION; - if (*expected & TLVFLAG_MT_ROUTER_INFORMATION) { - if (!tlvs->mt_router_info) { - tlvs->mt_router_info = list_new(); - tlvs->mt_router_info->del = free_tlv; - } - while (length > value_len) { - uint16_t mt_info; - struct mt_router_info *info; - - if (value_len + sizeof(mt_info) - > length) { - zlog_warn( - "ISIS-TLV (%s): TLV 229 is truncated.", - areatag); - pnt += length - value_len; - break; - } - - memcpy(&mt_info, pnt, sizeof(mt_info)); - pnt += sizeof(mt_info); - value_len += sizeof(mt_info); - - mt_info = ntohs(mt_info); - info = XCALLOC(MTYPE_ISIS_TLV, - sizeof(*info)); - info->mtid = mt_info & ISIS_MT_MASK; - info->overload = - mt_info & ISIS_MT_OL_MASK; - listnode_add(tlvs->mt_router_info, - info); - } - } else { - pnt += length; - } - break; - default: - zlog_warn( - "ISIS-TLV (%s): unsupported TLV type %d, length %d", - areatag, type, length); - - pnt += length; - break; - } - /* Abort Parsing if error occured */ - if (retval != ISIS_OK) - return retval; - } - - return retval; -} - -int add_tlv(u_char tag, u_char len, u_char *value, struct stream *stream) -{ - if ((stream_get_size(stream) - stream_get_endp(stream)) - < (((unsigned)len) + 2)) { - zlog_warn( - "No room for TLV of type %d " - "(total size %d available %d required %d)", - tag, (int)stream_get_size(stream), - (int)(stream_get_size(stream) - - stream_get_endp(stream)), - len + 2); - return ISIS_WARNING; - } - - stream_putc(stream, tag); /* TAG */ - stream_putc(stream, len); /* LENGTH */ - stream_put(stream, value, (int)len); /* VALUE */ - -#ifdef EXTREME_DEBUG - zlog_debug("Added TLV %d len %d", tag, len); -#endif /* EXTREME DEBUG */ - return ISIS_OK; -} - -int tlv_add_mt_router_info(struct list *mt_router_info, struct stream *stream) -{ - struct listnode *node; - struct mt_router_info *info; - - uint16_t value[127]; - uint16_t *pos = value; - - for (ALL_LIST_ELEMENTS_RO(mt_router_info, node, info)) { - uint16_t mt_info; - - mt_info = info->mtid; - if (info->overload) - mt_info |= ISIS_MT_OL_MASK; - - *pos = htons(mt_info); - pos++; - } - - return add_tlv(MT_ROUTER_INFORMATION, (pos - value) * sizeof(*pos), - (u_char *)value, stream); -} - -int tlv_add_area_addrs(struct list *area_addrs, struct stream *stream) -{ - struct listnode *node; - struct area_addr *area_addr; - - u_char value[255]; - u_char *pos = value; - - for (ALL_LIST_ELEMENTS_RO(area_addrs, node, area_addr)) { - if (pos - value + area_addr->addr_len > 255) - goto err; - *pos = area_addr->addr_len; - pos++; - memcpy(pos, area_addr->area_addr, (int)area_addr->addr_len); - pos += area_addr->addr_len; - } - - return add_tlv(AREA_ADDRESSES, pos - value, value, stream); - -err: - zlog_warn("tlv_add_area_addrs(): TLV longer than 255"); - return ISIS_WARNING; -} - -int tlv_add_is_neighs(struct list *is_neighs, struct stream *stream) -{ - struct listnode *node; - struct is_neigh *is_neigh; - u_char value[255]; - u_char *pos = value; - int retval; - - *pos = 0; /*is_neigh->virtual; */ - pos++; - - for (ALL_LIST_ELEMENTS_RO(is_neighs, node, is_neigh)) { - if (pos - value + IS_NEIGHBOURS_LEN > 255) { - retval = add_tlv(IS_NEIGHBOURS, pos - value, value, - stream); - if (retval != ISIS_OK) - return retval; - pos = value; - } - *pos = is_neigh->metrics.metric_default; - pos++; - *pos = is_neigh->metrics.metric_delay; - pos++; - *pos = is_neigh->metrics.metric_expense; - pos++; - *pos = is_neigh->metrics.metric_error; - pos++; - memcpy(pos, is_neigh->neigh_id, ISIS_SYS_ID_LEN + 1); - pos += ISIS_SYS_ID_LEN + 1; - } - - return add_tlv(IS_NEIGHBOURS, pos - value, value, stream); -} - -static size_t max_tlv_size(struct stream *stream) -{ - size_t avail = stream_get_size(stream) - stream_get_endp(stream); - - if (avail < 2) - return 0; - - if (avail < 257) - return avail - 2; - - return 255; -} - -unsigned int tlv_add_te_is_neighs(struct list *te_is_neighs, - struct stream *stream, void *arg) -{ - struct listnode *node; - struct te_is_neigh *te_is_neigh; - u_char value[255]; - u_char *pos = value; - uint16_t mtid = arg ? *(uint16_t *)arg : ISIS_MT_IPV4_UNICAST; - unsigned int consumed = 0; - size_t max_size = max_tlv_size(stream); - - if (mtid != ISIS_MT_IPV4_UNICAST) { - uint16_t mtid_conversion = ntohs(mtid); - memcpy(pos, &mtid_conversion, sizeof(mtid_conversion)); - pos += sizeof(mtid_conversion); - } - - for (ALL_LIST_ELEMENTS_RO(te_is_neighs, node, te_is_neigh)) { - /* FIXME: Check if Total SubTLVs size doesn't exceed 255 */ - if ((size_t)(pos - value) + IS_NEIGHBOURS_LEN - + te_is_neigh->sub_tlvs_length - > max_size) - break; - - memcpy(pos, te_is_neigh->neigh_id, ISIS_SYS_ID_LEN + 1); - pos += ISIS_SYS_ID_LEN + 1; - memcpy(pos, te_is_neigh->te_metric, 3); - pos += 3; - /* Set the total size of Sub TLVs */ - *pos = te_is_neigh->sub_tlvs_length; - pos++; - /* Copy Sub TLVs if any */ - if (te_is_neigh->sub_tlvs_length > 0) { - memcpy(pos, te_is_neigh->sub_tlvs, - te_is_neigh->sub_tlvs_length); - pos += te_is_neigh->sub_tlvs_length; - } - consumed++; - } - - if (consumed) { - int rv = add_tlv((mtid != ISIS_MT_IPV4_UNICAST) - ? MT_IS_NEIGHBOURS - : TE_IS_NEIGHBOURS, - pos - value, value, stream); - assert(rv == ISIS_OK); - } - return consumed; -} - -int tlv_add_lan_neighs(struct list *lan_neighs, struct stream *stream) -{ - struct listnode *node; - u_char *snpa; - u_char value[255]; - u_char *pos = value; - int retval; - - for (ALL_LIST_ELEMENTS_RO(lan_neighs, node, snpa)) { - if (pos - value + ETH_ALEN > 255) { - retval = add_tlv(LAN_NEIGHBOURS, pos - value, value, - stream); - if (retval != ISIS_OK) - return retval; - pos = value; - } - memcpy(pos, snpa, ETH_ALEN); - pos += ETH_ALEN; - } - - return add_tlv(LAN_NEIGHBOURS, pos - value, value, stream); -} - -int tlv_add_nlpid(struct nlpids *nlpids, struct stream *stream) -{ - return add_tlv(PROTOCOLS_SUPPORTED, nlpids->count, nlpids->nlpids, - stream); -} - -int tlv_add_authinfo(u_char auth_type, u_char auth_len, u_char *auth_value, - struct stream *stream) -{ - u_char value[255]; - u_char *pos = value; - *pos++ = auth_type; - memcpy(pos, auth_value, auth_len); - - return add_tlv(AUTH_INFO, auth_len + 1, value, stream); -} - -int tlv_add_checksum(struct checksum *checksum, struct stream *stream) -{ - u_char value[255]; - u_char *pos = value; - return add_tlv(CHECKSUM, pos - value, value, stream); -} - -int tlv_add_ip_addrs(struct list *ip_addrs, struct stream *stream) -{ - struct listnode *node; - struct prefix_ipv4 *ipv4; - u_char value[255]; - u_char *pos = value; - - for (ALL_LIST_ELEMENTS_RO(ip_addrs, node, ipv4)) { - if (pos - value + IPV4_MAX_BYTELEN > 255) { - /* RFC 1195 s4.2: only one tuple of 63 allowed. */ - zlog_warn( - "tlv_add_ip_addrs(): cutting off at 63 IP addresses"); - break; - } - *(u_int32_t *)pos = ipv4->prefix.s_addr; - pos += IPV4_MAX_BYTELEN; - } - - return add_tlv(IPV4_ADDR, pos - value, value, stream); -} - -/* Used to add TLV containing just one IPv4 address - either IPv4 address TLV - * (in case of LSP) or TE router ID TLV. */ -int tlv_add_in_addr(struct in_addr *addr, struct stream *stream, u_char tag) -{ - u_char value[255]; - u_char *pos = value; - - memcpy(pos, addr, IPV4_MAX_BYTELEN); - pos += IPV4_MAX_BYTELEN; - - return add_tlv(tag, pos - value, value, stream); -} - -int tlv_add_dynamic_hostname(struct hostname *hostname, struct stream *stream) -{ - return add_tlv(DYNAMIC_HOSTNAME, hostname->namelen, hostname->name, - stream); -} - -int tlv_add_lsp_entries(struct list *lsps, struct stream *stream) -{ - struct listnode *node; - struct isis_lsp *lsp; - u_char value[255]; - u_char *pos = value; - int retval; - - for (ALL_LIST_ELEMENTS_RO(lsps, node, lsp)) { - if (pos - value + LSP_ENTRIES_LEN > 255) { - retval = add_tlv(LSP_ENTRIES, pos - value, value, - stream); - if (retval != ISIS_OK) - return retval; - pos = value; - } - *((u_int16_t *)pos) = lsp->lsp_header->rem_lifetime; - pos += 2; - memcpy(pos, lsp->lsp_header->lsp_id, ISIS_SYS_ID_LEN + 2); - pos += ISIS_SYS_ID_LEN + 2; - *((u_int32_t *)pos) = lsp->lsp_header->seq_num; - pos += 4; - *((u_int16_t *)pos) = lsp->lsp_header->checksum; - pos += 2; - } - - return add_tlv(LSP_ENTRIES, pos - value, value, stream); -} - -static int tlv_add_ipv4_reachs(u_char tag, struct list *ipv4_reachs, - struct stream *stream) -{ - struct listnode *node; - struct ipv4_reachability *reach; - u_char value[255]; - u_char *pos = value; - int retval; - - for (ALL_LIST_ELEMENTS_RO(ipv4_reachs, node, reach)) { - if (pos - value + IPV4_REACH_LEN > 255) { - retval = add_tlv(tag, pos - value, value, stream); - if (retval != ISIS_OK) - return retval; - pos = value; - } - *pos = reach->metrics.metric_default; - pos++; - *pos = reach->metrics.metric_delay; - pos++; - *pos = reach->metrics.metric_expense; - pos++; - *pos = reach->metrics.metric_error; - pos++; - *(u_int32_t *)pos = reach->prefix.s_addr; - pos += IPV4_MAX_BYTELEN; - *(u_int32_t *)pos = reach->mask.s_addr; - pos += IPV4_MAX_BYTELEN; - } - - return add_tlv(tag, pos - value, value, stream); -} - -int tlv_add_ipv4_int_reachs(struct list *ipv4_reachs, struct stream *stream) -{ - return tlv_add_ipv4_reachs(IPV4_INT_REACHABILITY, ipv4_reachs, stream); -} - -int tlv_add_ipv4_ext_reachs(struct list *ipv4_reachs, struct stream *stream) -{ - return tlv_add_ipv4_reachs(IPV4_EXT_REACHABILITY, ipv4_reachs, stream); -} - - -unsigned int tlv_add_te_ipv4_reachs(struct list *te_ipv4_reachs, - struct stream *stream, void *arg) -{ - struct listnode *node; - struct te_ipv4_reachability *te_reach; - u_char value[255]; - u_char *pos = value; - uint16_t mtid = arg ? *(uint16_t *)arg : ISIS_MT_IPV4_UNICAST; - unsigned int consumed = 0; - size_t max_size = max_tlv_size(stream); - - if (mtid != ISIS_MT_IPV4_UNICAST) { - uint16_t mtid_conversion = ntohs(mtid); - memcpy(pos, &mtid_conversion, sizeof(mtid_conversion)); - pos += sizeof(mtid_conversion); - } - - for (ALL_LIST_ELEMENTS_RO(te_ipv4_reachs, node, te_reach)) { - unsigned char prefixlen = te_reach->control & 0x3F; - - if ((size_t)(pos - value) + 5 + PSIZE(prefixlen) > max_size) - break; - - *(u_int32_t *)pos = te_reach->te_metric; - pos += 4; - *pos = te_reach->control; - pos++; - memcpy(pos, &te_reach->prefix_start, PSIZE(prefixlen)); - pos += PSIZE(prefixlen); - consumed++; - } - - if (consumed) { - int rv = add_tlv((mtid != ISIS_MT_IPV4_UNICAST) - ? MT_IPV4_REACHABILITY - : TE_IPV4_REACHABILITY, - pos - value, value, stream); - assert(rv == ISIS_OK); - } - - return consumed; -} - -int tlv_add_ipv6_addrs(struct list *ipv6_addrs, struct stream *stream) -{ - struct listnode *node; - struct prefix_ipv6 *ipv6; - u_char value[255]; - u_char *pos = value; - int retval; - - for (ALL_LIST_ELEMENTS_RO(ipv6_addrs, node, ipv6)) { - if (pos - value + IPV6_MAX_BYTELEN > 255) { - retval = add_tlv(IPV6_ADDR, pos - value, value, stream); - if (retval != ISIS_OK) - return retval; - pos = value; - } - memcpy(pos, ipv6->prefix.s6_addr, IPV6_MAX_BYTELEN); - pos += IPV6_MAX_BYTELEN; - } - - return add_tlv(IPV6_ADDR, pos - value, value, stream); -} - -unsigned int tlv_add_ipv6_reachs(struct list *ipv6_reachs, - struct stream *stream, void *arg) -{ - struct listnode *node; - struct ipv6_reachability *ip6reach; - u_char value[255]; - u_char *pos = value; - uint16_t mtid = arg ? *(uint16_t *)arg : ISIS_MT_IPV4_UNICAST; - unsigned int consumed = 0; - size_t max_size = max_tlv_size(stream); - - if (mtid != ISIS_MT_IPV4_UNICAST) { - uint16_t mtid_conversion = ntohs(mtid); - memcpy(pos, &mtid_conversion, sizeof(mtid_conversion)); - pos += sizeof(mtid_conversion); - } - - for (ALL_LIST_ELEMENTS_RO(ipv6_reachs, node, ip6reach)) { - if ((size_t)(pos - value) + 6 + PSIZE(ip6reach->prefix_len) - > max_size) - break; - - *(uint32_t *)pos = ip6reach->metric; - pos += 4; - *pos = ip6reach->control_info; - pos++; - *pos = ip6reach->prefix_len; - pos++; - memcpy(pos, ip6reach->prefix, PSIZE(ip6reach->prefix_len)); - pos += PSIZE(ip6reach->prefix_len); - consumed++; - } - - if (consumed) { - int rv = add_tlv((mtid != ISIS_MT_IPV4_UNICAST) - ? MT_IPV6_REACHABILITY - : IPV6_REACHABILITY, - pos - value, value, stream); - assert(rv == ISIS_OK); - } - - return consumed; -} - -int tlv_add_padding(struct stream *stream) -{ - int fullpads, i, left; - - /* - * How many times can we add full padding ? - */ - fullpads = (stream_get_size(stream) - stream_get_endp(stream)) / 257; - for (i = 0; i < fullpads; i++) { - if (!stream_putc(stream, (u_char)PADDING)) /* TAG */ - goto err; - if (!stream_putc(stream, (u_char)255)) /* LENGHT */ - goto err; - stream_put(stream, NULL, 255); /* zero padding */ - } - - left = stream_get_size(stream) - stream_get_endp(stream); - - if (left < 2) - return ISIS_OK; - - if (left == 2) { - stream_putc(stream, PADDING); - stream_putc(stream, 0); - return ISIS_OK; - } - - stream_putc(stream, PADDING); - stream_putc(stream, left - 2); - stream_put(stream, NULL, left - 2); - - return ISIS_OK; - -err: - zlog_warn("tlv_add_padding(): no room for tlv"); - return ISIS_WARNING; -} diff --git a/isisd/isis_tlv.h b/isisd/isis_tlv.h deleted file mode 100644 index d06548519..000000000 --- a/isisd/isis_tlv.h +++ /dev/null @@ -1,340 +0,0 @@ -/* - * IS-IS Rout(e)ing protocol - isis_tlv.h - * IS-IS TLV related routines - * - * Copyright (C) 2001,2002 Sampo Saaristo - * Tampere University of Technology - * Institute of Communications Engineering - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public Licenseas 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 - */ - -#ifndef _ZEBRA_ISIS_TLV_H -#define _ZEBRA_ISIS_TLV_H - -#include "isisd/isis_mt.h" - -/* - * The list of TLVs we (should) support. - * ____________________________________________________________________________ - * Name Value IIH LSP SNP Status - * LAN - * ____________________________________________________________________________ - * - * Area Addresses 1 y y n ISO10589 - * IIS Neighbors 2 n y n ISO10589 - * ES Neighbors 3 n y n ISO10589 - * IIS Neighbors 6 y n n ISO10589 - * Padding 8 y n n ISO10589 - * LSP Entries 9 n n y ISO10589 - * Authentication 10 y y y ISO10589, RFC3567 - * Checksum 12 y n y RFC3358 - * Extended IS Reachability 22 n y n RFC5305 - * IS Alias 24 n y n RFC3786 - * IP Int. Reachability 128 n y n RFC1195 - * Protocols Supported 129 y y n RFC1195 - * IP Ext. Reachability 130 n y n RFC1195 - * IDRPI 131 n y y RFC1195 - * IP Interface Address 132 y y n RFC1195 - * TE Router ID 134 n y n RFC5305 - * Extended IP Reachability 135 n y n RFC5305 - * Dynamic Hostname 137 n y n RFC2763 - * Shared Risk Link Group 138 n y y RFC5307 - * Inter-AS Reachability 141 n y n RFC5316 - * Restart TLV 211 y n n RFC3847 - * MT IS Reachability 222 n y n RFC5120 - * MT Supported 229 y y n RFC5120 - * IPv6 Interface Address 232 y y n RFC5308 - * MT IP Reachability 235 n y n RFC5120 - * IPv6 IP Reachability 236 n y n RFC5308 - * MT IPv6 IP Reachability 237 n y n RFC5120 - * P2P Adjacency State 240 y n n RFC3373 - * IIH Sequence Number 241 y n n draft-shen-isis-iih-sequence - * Router Capability 242 n y n RFC4971 - * - * - * IS Reachability sub-TLVs we support (See isis_te.[c,h]) - * ____________________________________________________________________________ - * Name Value Status - * ____________________________________________________________________________ - * Administartive group (color) 3 RFC5305 - * Link Local/Remote Identifiers 4 RFC5307 - * IPv4 interface address 6 RFC5305 - * IPv4 neighbor address 8 RFC5305 - * Maximum link bandwidth 9 RFC5305 - * Reservable link bandwidth 10 RFC5305 - * Unreserved bandwidth 11 RFC5305 - * TE Default metric 18 RFC5305 - * Link Protection Type 20 RFC5307 - * Interface Switching Capability 21 RFC5307 - * Remote AS number 24 RFC5316 - * IPv4 Remote ASBR identifier 25 RFC5316 - * - * - * IP Reachability sub-TLVs we (should) support. - * ____________________________________________________________________________ - * Name Value Status - * ____________________________________________________________________________ - * 32bit administrative tag 1 RFC5130 - * 64bit administrative tag 2 RFC5130 - * Management prefix color 117 RFC5120 - */ - -#define AREA_ADDRESSES 1 -#define IS_NEIGHBOURS 2 -#define ES_NEIGHBOURS 3 -#define LAN_NEIGHBOURS 6 -#define PADDING 8 -#define LSP_ENTRIES 9 -#define AUTH_INFO 10 -#define CHECKSUM 12 -#define TE_IS_NEIGHBOURS 22 -#define IS_ALIAS 24 -#define IPV4_INT_REACHABILITY 128 -#define PROTOCOLS_SUPPORTED 129 -#define IPV4_EXT_REACHABILITY 130 -#define IDRP_INFO 131 -#define IPV4_ADDR 132 -#define TE_ROUTER_ID 134 -#define TE_IPV4_REACHABILITY 135 -#define DYNAMIC_HOSTNAME 137 -#define GRACEFUL_RESTART 211 -#define MT_IS_NEIGHBOURS 222 -#define MT_ROUTER_INFORMATION 229 -#define IPV6_ADDR 232 -#define MT_IPV4_REACHABILITY 235 -#define IPV6_REACHABILITY 236 -#define MT_IPV6_REACHABILITY 237 -#define WAY3_HELLO 240 -#define ROUTER_INFORMATION 242 - -#define AUTH_INFO_HDRLEN 3 - -#define MAX_TLV_LEN 255 - -#define IS_NEIGHBOURS_LEN (ISIS_SYS_ID_LEN + 5) -#define LAN_NEIGHBOURS_LEN 6 -#define LSP_ENTRIES_LEN (10 + ISIS_SYS_ID_LEN) /* FIXME: should be entry */ -#define IPV4_REACH_LEN 12 -#define IPV6_REACH_LEN 22 -#define TE_IPV4_REACH_LEN 9 - -#define MAX_SUBTLV_SIZE 256 - -/* struct for neighbor */ -struct is_neigh { - struct metric metrics; - u_char neigh_id[ISIS_SYS_ID_LEN + 1]; -}; - -/* struct for te metric */ -struct te_is_neigh { - u_char neigh_id[ISIS_SYS_ID_LEN + 1]; - u_char te_metric[3]; - u_char sub_tlvs_length; - /* Theorical Maximum SubTLVs is 256 because the sub_tlvs_length is 8 - * bits */ - /* Practically, 118 bytes are necessary to store all supported TE - * parameters */ - /* FIXME: A pointer will use less memory, but need to be free */ - /* which is hard to fix, especially within free_tlvs() function */ - /* and malloc() / free() as a CPU cost compared to the memory usage */ - u_char sub_tlvs[MAX_SUBTLV_SIZE]; /* SUB TLVs storage */ -}; - -/* Decode and encode three-octet metric into host byte order integer */ -#define GET_TE_METRIC(t) \ - (((unsigned)(t)->te_metric[0] << 16) | ((t)->te_metric[1] << 8) \ - | (t)->te_metric[2]) -#define SET_TE_METRIC(t, m) \ - (((t)->te_metric[0] = (m) >> 16), ((t)->te_metric[1] = (m) >> 8), \ - ((t)->te_metric[2] = (m))) - -/* struct for es neighbors */ -struct es_neigh { - struct metric metrics; - /* approximate position of first, we use the - * length ((uchar*)metric-1) to know all */ - u_char first_es_neigh[ISIS_SYS_ID_LEN]; -}; - -struct partition_desig_level2_is { - struct list *isis_system_ids; -}; - -/* struct for lan neighbors */ -struct lan_neigh { - u_char LAN_addr[6]; -}; - -#ifdef __SUNPRO_C -#pragma pack(1) -#endif - -/* struct for LSP entry */ -struct lsp_entry { - u_int16_t rem_lifetime; - u_char lsp_id[ISIS_SYS_ID_LEN + 2]; - u_int32_t seq_num; - u_int16_t checksum; -} __attribute__((packed)); - -#ifdef __SUNPRO_C -#pragma pack() -#endif - -/* struct for checksum */ -struct checksum { - u_int16_t checksum; -}; - -/* ipv4 reachability */ -struct ipv4_reachability { - struct metric metrics; - struct in_addr prefix; - struct in_addr mask; -}; - -/* te router id */ -struct te_router_id { - struct in_addr id; -}; - -/* te ipv4 reachability */ -struct te_ipv4_reachability { - u_int32_t te_metric; - u_char control; - u_char prefix_start; /* since this is variable length by nature it only - */ -}; /* points to an approximate location */ - -#define TE_IPV4_HAS_SUBTLV (0x40) - -struct idrp_info { - u_char len; - u_char *value; -}; - -struct ipv6_reachability { - u_int32_t metric; - u_char control_info; - u_char prefix_len; - u_char prefix[16]; -}; - -/* bits in control_info */ -#define CTRL_INFO_DIRECTION 0x80 -#define DIRECTION_UP 0x00 -#define DIRECTION_DOWN 0x80 - -#define CTRL_INFO_DISTRIBUTION 0x40 -#define DISTRIBUTION_INTERNAL 0x00 -#define DISTRIBUTION_EXTERNAL 0x40 - -#define CTRL_INFO_SUBTLVS 0x20 - -struct mt_router_info { - ISIS_MT_INFO_FIELDS - bool overload; -}; - -/* - * Pointer to each tlv type, filled by parse_tlvs() - */ -struct tlvs { - struct checksum *checksum; - struct hostname *hostname; - struct nlpids *nlpids; - struct te_router_id *router_id; - struct list *area_addrs; - struct list *mt_router_info; - struct list *is_neighs; - struct list *te_is_neighs; - struct list *mt_is_neighs; - struct list *es_neighs; - struct list *lsp_entries; - struct list *prefix_neighs; - struct list *lan_neighs; - struct list *ipv4_addrs; - struct list *ipv4_int_reachs; - struct list *ipv4_ext_reachs; - struct list *te_ipv4_reachs; - struct list *mt_ipv4_reachs; - struct list *ipv6_addrs; - struct list *ipv6_reachs; - struct list *mt_ipv6_reachs; - struct isis_passwd auth_info; -}; - -/* - * Own definitions - used to bitmask found and expected - */ - -#define TLVFLAG_AREA_ADDRS (1<<0) -#define TLVFLAG_IS_NEIGHS (1<<1) -#define TLVFLAG_ES_NEIGHS (1<<2) -#define TLVFLAG_PARTITION_DESIG_LEVEL2_IS (1<<3) -#define TLVFLAG_PREFIX_NEIGHS (1<<4) -#define TLVFLAG_LAN_NEIGHS (1<<5) -#define TLVFLAG_LSP_ENTRIES (1<<6) -#define TLVFLAG_PADDING (1<<7) -#define TLVFLAG_AUTH_INFO (1<<8) -#define TLVFLAG_IPV4_INT_REACHABILITY (1<<9) -#define TLVFLAG_NLPID (1<<10) -#define TLVFLAG_IPV4_EXT_REACHABILITY (1<<11) -#define TLVFLAG_IPV4_ADDR (1<<12) -#define TLVFLAG_DYN_HOSTNAME (1<<13) -#define TLVFLAG_IPV6_ADDR (1<<14) -#define TLVFLAG_IPV6_REACHABILITY (1<<15) -#define TLVFLAG_TE_IS_NEIGHS (1<<16) -#define TLVFLAG_TE_IPV4_REACHABILITY (1<<17) -#define TLVFLAG_3WAY_HELLO (1<<18) -#define TLVFLAG_TE_ROUTER_ID (1<<19) -#define TLVFLAG_CHECKSUM (1<<20) -#define TLVFLAG_GRACEFUL_RESTART (1<<21) -#define TLVFLAG_MT_ROUTER_INFORMATION (1<<22) - -void init_tlvs(struct tlvs *tlvs, uint32_t expected); -void free_tlvs(struct tlvs *tlvs); -int parse_tlvs(char *areatag, u_char *stream, int size, u_int32_t *expected, - u_int32_t *found, struct tlvs *tlvs, u_int32_t *auth_tlv_offset); -int add_tlv(u_char, u_char, u_char *, struct stream *); -void free_tlv(void *val); - -int tlv_add_mt_router_info(struct list *mt_router_info, struct stream *stream); -int tlv_add_area_addrs(struct list *area_addrs, struct stream *stream); -int tlv_add_is_neighs(struct list *is_neighs, struct stream *stream); -unsigned int tlv_add_te_is_neighs(struct list *te_is_neighs, - struct stream *stream, void *arg); -int tlv_add_lan_neighs(struct list *lan_neighs, struct stream *stream); -int tlv_add_nlpid(struct nlpids *nlpids, struct stream *stream); -int tlv_add_checksum(struct checksum *checksum, struct stream *stream); -int tlv_add_authinfo(u_char auth_type, u_char authlen, u_char *auth_value, - struct stream *stream); -int tlv_add_ip_addrs(struct list *ip_addrs, struct stream *stream); -int tlv_add_in_addr(struct in_addr *, struct stream *stream, u_char tag); -int tlv_add_dynamic_hostname(struct hostname *hostname, struct stream *stream); -int tlv_add_lsp_entries(struct list *lsps, struct stream *stream); -int tlv_add_ipv4_int_reachs(struct list *ipv4_reachs, struct stream *stream); -int tlv_add_ipv4_ext_reachs(struct list *ipv4_reachs, struct stream *stream); -unsigned int tlv_add_te_ipv4_reachs(struct list *te_ipv4_reachs, - struct stream *stream, void *arg); -int tlv_add_ipv6_addrs(struct list *ipv6_addrs, struct stream *stream); -unsigned int tlv_add_ipv6_reachs(struct list *ipv6_reachs, - struct stream *stream, void *arg); - -int tlv_add_padding(struct stream *stream); - -#endif /* _ZEBRA_ISIS_TLV_H */ diff --git a/isisd/isis_zebra.c b/isisd/isis_zebra.c index 18a59d1fc..8c6968f8e 100644 --- a/isisd/isis_zebra.c +++ b/isisd/isis_zebra.c @@ -42,7 +42,6 @@ #include "isisd/isis_flags.h" #include "isisd/isis_misc.h" #include "isisd/isis_circuit.h" -#include "isisd/isis_tlv.h" #include "isisd/isisd.h" #include "isisd/isis_circuit.h" #include "isisd/isis_csm.h" diff --git a/isisd/isisd.c b/isisd/isisd.c index 8bbb5cf94..05797fb73 100644 --- a/isisd/isisd.c +++ b/isisd/isisd.c @@ -49,7 +49,6 @@ #include "isisd/isis_pdu.h" #include "isisd/isis_misc.h" #include "isisd/isis_constants.h" -#include "isisd/isis_tlv.h" #include "isisd/isis_lsp.h" #include "isisd/isis_spf.h" #include "isisd/isis_route.h" diff --git a/isisd/iso_checksum.c b/isisd/iso_checksum.c index e0a4ba370..25a870991 100644 --- a/isisd/iso_checksum.c +++ b/isisd/iso_checksum.c @@ -67,7 +67,7 @@ int iso_csum_verify(u_char *buffer, int len, uint16_t csum, int offset) return 1; checksum = fletcher_checksum(buffer, len, offset); - if (checksum == csum) + if (checksum == htons(csum)) return 0; return 1; } |