version 1.1.1.3, 2013/07/21 23:54:38
|
version 1.1.1.4, 2016/11/02 10:09:10
|
Line 62
|
Line 62
|
#endif /* PNBBY */ |
#endif /* PNBBY */ |
|
|
/* Utility mask array. */ |
/* Utility mask array. */ |
static u_char maskbit[] = { | static const u_char maskbit[] = { |
0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff |
0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff |
}; |
}; |
|
|
Line 204 authentication_check (struct isis_passwd *remote, stru
|
Line 204 authentication_check (struct isis_passwd *remote, stru
|
/* Compute the digest */ |
/* Compute the digest */ |
hmac_md5 (STREAM_DATA (stream), stream_get_endp (stream), |
hmac_md5 (STREAM_DATA (stream), stream_get_endp (stream), |
(unsigned char *) &(local->passwd), local->len, |
(unsigned char *) &(local->passwd), local->len, |
(caddr_t) &digest); | (unsigned char *) &digest); |
/* Copy back the authentication value after the check */ |
/* Copy back the authentication value after the check */ |
memcpy (STREAM_DATA (stream) + auth_tlv_offset + 3, |
memcpy (STREAM_DATA (stream) + auth_tlv_offset + 3, |
remote->passwd, ISIS_AUTH_MD5_SIZE); |
remote->passwd, ISIS_AUTH_MD5_SIZE); |
Line 402 process_p2p_hello (struct isis_circuit *circuit)
|
Line 402 process_p2p_hello (struct isis_circuit *circuit)
|
u_int32_t expected = 0, found = 0, auth_tlv_offset = 0; |
u_int32_t expected = 0, found = 0, auth_tlv_offset = 0; |
uint16_t pdu_len; |
uint16_t pdu_len; |
struct tlvs tlvs; |
struct tlvs tlvs; |
|
int v4_usable = 0, v6_usable = 0; |
|
|
if (isis->debugs & DEBUG_ADJ_PACKETS) |
if (isis->debugs & DEBUG_ADJ_PACKETS) |
{ |
{ |
Line 518 process_p2p_hello (struct isis_circuit *circuit)
|
Line 519 process_p2p_hello (struct isis_circuit *circuit)
|
/* |
/* |
* check if it's own interface ip match iih ip addrs |
* check if it's own interface ip match iih ip addrs |
*/ |
*/ |
if ((found & TLVFLAG_IPV4_ADDR) == 0 || | if (found & TLVFLAG_IPV4_ADDR) |
ip_match (circuit->ip_addrs, tlvs.ipv4_addrs) == 0) | |
{ |
{ |
zlog_warn ("ISIS-Adj: No usable IP interface addresses " | if (ip_match (circuit->ip_addrs, tlvs.ipv4_addrs)) |
"in LAN IIH from %s\n", circuit->interface->name); | v4_usable = 1; |
| else |
| zlog_warn ("ISIS-Adj: IPv4 addresses present but no overlap " |
| "in P2P IIH from %s\n", circuit->interface->name); |
| } |
| #ifndef HAVE_IPV6 |
| else /* !(found & TLVFLAG_IPV4_ADDR) */ |
| zlog_warn ("ISIS-Adj: no IPv4 in P2P IIH from %s " |
| "(this isisd has no IPv6)\n", circuit->interface->name); |
| |
| #else |
| if (found & TLVFLAG_IPV6_ADDR) |
| { |
| /* TBA: check that we have a linklocal ourselves? */ |
| struct listnode *node; |
| struct in6_addr *ip; |
| for (ALL_LIST_ELEMENTS_RO (tlvs.ipv6_addrs, node, ip)) |
| if (IN6_IS_ADDR_LINKLOCAL (ip)) |
| { |
| v6_usable = 1; |
| break; |
| } |
| |
| if (!v6_usable) |
| zlog_warn ("ISIS-Adj: IPv6 addresses present but no link-local " |
| "in P2P IIH from %s\n", circuit->interface->name); |
| } |
| |
| if (!(found & (TLVFLAG_IPV4_ADDR | TLVFLAG_IPV6_ADDR))) |
| zlog_warn ("ISIS-Adj: neither IPv4 nor IPv6 addr in P2P IIH from %s\n", |
| circuit->interface->name); |
| #endif |
| |
| if (!v6_usable && !v4_usable) |
| { |
free_tlvs (&tlvs); |
free_tlvs (&tlvs); |
return ISIS_WARNING; |
return ISIS_WARNING; |
} |
} |
|
|
/* |
/* |
|
* it's own p2p IIH PDU - discard |
|
*/ |
|
if (!memcmp (hdr->source_id, isis->sysid, ISIS_SYS_ID_LEN)) |
|
{ |
|
zlog_warn ("ISIS-Adj (%s): it's own IIH PDU - discarded", |
|
circuit->area->area_tag); |
|
free_tlvs (&tlvs); |
|
return ISIS_WARNING; |
|
} |
|
|
|
/* |
* My interpertation of the ISO, if no adj exists we will create one for |
* My interpertation of the ISO, if no adj exists we will create one for |
* the circuit |
* the circuit |
*/ |
*/ |
adj = circuit->u.p2p.neighbor; |
adj = circuit->u.p2p.neighbor; |
|
/* If an adjacency exists, check it is with the source of the hello |
|
* packets */ |
|
if (adj) |
|
{ |
|
if (memcmp(hdr->source_id, adj->sysid, ISIS_SYS_ID_LEN)) |
|
{ |
|
zlog_debug("hello source and adjacency do not match, set adj down\n"); |
|
isis_adj_state_change (adj, ISIS_ADJ_DOWN, "adj do not exist"); |
|
return 0; |
|
} |
|
} |
if (!adj || adj->level != hdr->circuit_t) |
if (!adj || adj->level != hdr->circuit_t) |
{ |
{ |
if (!adj) |
if (!adj) |
Line 545 process_p2p_hello (struct isis_circuit *circuit)
|
Line 601 process_p2p_hello (struct isis_circuit *circuit)
|
adj->level = hdr->circuit_t; |
adj->level = hdr->circuit_t; |
} |
} |
circuit->u.p2p.neighbor = adj; |
circuit->u.p2p.neighbor = adj; |
|
/* Build lsp with the new neighbor entry when a new |
|
* adjacency is formed. Set adjacency circuit type to |
|
* IIH PDU header circuit type before lsp is regenerated |
|
* when an adjacency is up. This will result in the new |
|
* adjacency entry getting added to the lsp tlv neighbor list. |
|
*/ |
|
adj->circuit_t = hdr->circuit_t; |
isis_adj_state_change (adj, ISIS_ADJ_INITIALIZING, NULL); |
isis_adj_state_change (adj, ISIS_ADJ_INITIALIZING, NULL); |
adj->sys_type = ISIS_SYSTYPE_UNKNOWN; |
adj->sys_type = ISIS_SYSTYPE_UNKNOWN; |
} |
} |
Line 830 process_p2p_hello (struct isis_circuit *circuit)
|
Line 893 process_p2p_hello (struct isis_circuit *circuit)
|
break; |
break; |
} |
} |
|
|
adj->circuit_t = hdr->circuit_t; |
|
|
|
if (isis->debugs & DEBUG_ADJ_PACKETS) |
if (isis->debugs & DEBUG_ADJ_PACKETS) |
{ |
{ |
Line 850 process_p2p_hello (struct isis_circuit *circuit)
|
Line 912 process_p2p_hello (struct isis_circuit *circuit)
|
* Process IS-IS LAN Level 1/2 Hello PDU |
* Process IS-IS LAN Level 1/2 Hello PDU |
*/ |
*/ |
static int |
static int |
process_lan_hello (int level, struct isis_circuit *circuit, u_char * ssnpa) | process_lan_hello (int level, struct isis_circuit *circuit, const u_char *ssnpa) |
{ |
{ |
int retval = ISIS_OK; |
int retval = ISIS_OK; |
struct isis_lan_hello_hdr hdr; |
struct isis_lan_hello_hdr hdr; |
Line 859 process_lan_hello (int level, struct isis_circuit *cir
|
Line 921 process_lan_hello (int level, struct isis_circuit *cir
|
struct tlvs tlvs; |
struct tlvs tlvs; |
u_char *snpa; |
u_char *snpa; |
struct listnode *node; |
struct listnode *node; |
|
int v4_usable = 0, v6_usable = 0; |
|
|
if (isis->debugs & DEBUG_ADJ_PACKETS) |
if (isis->debugs & DEBUG_ADJ_PACKETS) |
{ |
{ |
Line 1045 process_lan_hello (int level, struct isis_circuit *cir
|
Line 1108 process_lan_hello (int level, struct isis_circuit *cir
|
/* |
/* |
* check if it's own interface ip match iih ip addrs |
* check if it's own interface ip match iih ip addrs |
*/ |
*/ |
if ((found & TLVFLAG_IPV4_ADDR) == 0 || | if (found & TLVFLAG_IPV4_ADDR) |
ip_match (circuit->ip_addrs, tlvs.ipv4_addrs) == 0) | |
{ |
{ |
zlog_debug ("ISIS-Adj: No usable IP interface addresses " | if (ip_match (circuit->ip_addrs, tlvs.ipv4_addrs)) |
"in LAN IIH from %s\n", circuit->interface->name); | v4_usable = 1; |
retval = ISIS_WARNING; | else |
goto out; | zlog_warn ("ISIS-Adj: IPv4 addresses present but no overlap " |
| "in LAN IIH from %s\n", circuit->interface->name); |
} |
} |
|
#ifndef HAVE_IPV6 |
|
else /* !(found & TLVFLAG_IPV4_ADDR) */ |
|
zlog_warn ("ISIS-Adj: no IPv4 in LAN IIH from %s " |
|
"(this isisd has no IPv6)\n", circuit->interface->name); |
|
|
|
#else |
|
if (found & TLVFLAG_IPV6_ADDR) |
|
{ |
|
/* TBA: check that we have a linklocal ourselves? */ |
|
struct listnode *node; |
|
struct in6_addr *ip; |
|
for (ALL_LIST_ELEMENTS_RO (tlvs.ipv6_addrs, node, ip)) |
|
if (IN6_IS_ADDR_LINKLOCAL (ip)) |
|
{ |
|
v6_usable = 1; |
|
break; |
|
} |
|
|
|
if (!v6_usable) |
|
zlog_warn ("ISIS-Adj: IPv6 addresses present but no link-local " |
|
"in LAN IIH from %s\n", circuit->interface->name); |
|
} |
|
|
|
if (!(found & (TLVFLAG_IPV4_ADDR | TLVFLAG_IPV6_ADDR))) |
|
zlog_warn ("ISIS-Adj: neither IPv4 nor IPv6 addr in LAN IIH from %s\n", |
|
circuit->interface->name); |
|
#endif |
|
|
|
if (!v6_usable && !v4_usable) |
|
{ |
|
free_tlvs (&tlvs); |
|
return ISIS_WARNING; |
|
} |
|
|
|
|
adj = isis_adj_lookup (hdr.source_id, circuit->u.bc.adjdb[level - 1]); |
adj = isis_adj_lookup (hdr.source_id, circuit->u.bc.adjdb[level - 1]); |
if ((adj == NULL) || (memcmp(adj->snpa, ssnpa, ETH_ALEN)) || |
if ((adj == NULL) || (memcmp(adj->snpa, ssnpa, ETH_ALEN)) || |
(adj->level != level)) |
(adj->level != level)) |
Line 1184 out:
|
Line 1281 out:
|
if (isis->debugs & DEBUG_ADJ_PACKETS) |
if (isis->debugs & DEBUG_ADJ_PACKETS) |
{ |
{ |
zlog_debug ("ISIS-Adj (%s): Rcvd L%d LAN IIH from %s on %s, cirType %s, " |
zlog_debug ("ISIS-Adj (%s): Rcvd L%d LAN IIH from %s on %s, cirType %s, " |
"cirID %u, length %ld", | "cirID %u, length %zd", |
circuit->area->area_tag, |
circuit->area->area_tag, |
level, snpa_print (ssnpa), circuit->interface->name, |
level, snpa_print (ssnpa), circuit->interface->name, |
circuit_t2string (circuit->is_type), |
circuit_t2string (circuit->is_type), |
Line 1203 out:
|
Line 1300 out:
|
* Section 7.3.15.1 - Action on receipt of a link state PDU |
* Section 7.3.15.1 - Action on receipt of a link state PDU |
*/ |
*/ |
static int |
static int |
process_lsp (int level, struct isis_circuit *circuit, u_char * ssnpa) | process_lsp (int level, struct isis_circuit *circuit, const u_char *ssnpa) |
{ |
{ |
struct isis_link_state_hdr *hdr; |
struct isis_link_state_hdr *hdr; |
struct isis_adjacency *adj = NULL; |
struct isis_adjacency *adj = NULL; |
Line 1212 process_lsp (int level, struct isis_circuit *circuit,
|
Line 1309 process_lsp (int level, struct isis_circuit *circuit,
|
u_char lspid[ISIS_SYS_ID_LEN + 2]; |
u_char lspid[ISIS_SYS_ID_LEN + 2]; |
struct isis_passwd *passwd; |
struct isis_passwd *passwd; |
uint16_t pdu_len; |
uint16_t pdu_len; |
|
int lsp_confusion; |
|
|
if (isis->debugs & DEBUG_UPDATE_PACKETS) |
if (isis->debugs & DEBUG_UPDATE_PACKETS) |
{ |
{ |
Line 1386 dontcheckadj:
|
Line 1484 dontcheckadj:
|
|
|
/* 7.3.15.1 a) 9 - OriginatingLSPBufferSize - not implemented FIXME: do it */ |
/* 7.3.15.1 a) 9 - OriginatingLSPBufferSize - not implemented FIXME: do it */ |
|
|
|
/* 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; |
|
} |
|
else |
|
lsp_confusion = 0; |
|
|
/* 7.3.15.1 b) - If the remaining life time is 0, we perform 7.3.16.4 */ |
/* 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) |
{ |
{ |
Line 1408 dontcheckadj:
|
Line 1521 dontcheckadj:
|
lsp_update (lsp, circuit->rcv_stream, circuit->area, level); |
lsp_update (lsp, circuit->rcv_stream, circuit->area, level); |
/* ii */ |
/* ii */ |
lsp_set_all_srmflags (lsp); |
lsp_set_all_srmflags (lsp); |
/* iii */ |
|
ISIS_CLEAR_FLAG (lsp->SRMflags, circuit); |
|
/* v */ |
/* v */ |
ISIS_FLAGS_CLEAR_ALL (lsp->SSNflags); /* FIXME: OTHER than c */ |
ISIS_FLAGS_CLEAR_ALL (lsp->SSNflags); /* FIXME: OTHER than c */ |
/* iv */ |
|
if (circuit->circ_type != CIRCUIT_T_BROADCAST) |
|
ISIS_SET_FLAG (lsp->SSNflags, circuit); |
|
|
|
|
/* For the case of lsp confusion, flood the purge back to its |
|
* originator so that it can react. Otherwise, don't reflood |
|
* through incoming circuit as usual */ |
|
if (!lsp_confusion) |
|
{ |
|
/* iii */ |
|
ISIS_CLEAR_FLAG (lsp->SRMflags, circuit); |
|
/* iv */ |
|
if (circuit->circ_type != CIRCUIT_T_BROADCAST) |
|
ISIS_SET_FLAG (lsp->SSNflags, circuit); |
|
} |
} /* 7.3.16.4 b) 2) */ |
} /* 7.3.16.4 b) 2) */ |
else if (comp == LSP_EQUAL) |
else if (comp == LSP_EQUAL) |
{ |
{ |
Line 1460 dontcheckadj:
|
Line 1579 dontcheckadj:
|
if (!lsp) |
if (!lsp) |
{ |
{ |
/* 7.3.16.4: initiate a purge */ |
/* 7.3.16.4: initiate a purge */ |
lsp_purge_non_exist (hdr, circuit->area); | lsp_purge_non_exist(level, hdr, circuit->area); |
return ISIS_OK; |
return ISIS_OK; |
} |
} |
/* 7.3.15.1 d) - If this is our own lsp and we have it */ |
/* 7.3.15.1 d) - If this is our own lsp and we have it */ |
Line 1552 dontcheckadj:
|
Line 1671 dontcheckadj:
|
|
|
static int |
static int |
process_snp (int snp_type, int level, struct isis_circuit *circuit, |
process_snp (int snp_type, int level, struct isis_circuit *circuit, |
u_char * ssnpa) | const u_char *ssnpa) |
{ |
{ |
int retval = ISIS_OK; |
int retval = ISIS_OK; |
int cmp, own_lsp; |
int cmp, own_lsp; |
Line 1597 process_snp (int snp_type, int level, struct isis_circ
|
Line 1716 process_snp (int snp_type, int level, struct isis_circ
|
pdu_len > ISO_MTU(circuit) || |
pdu_len > ISO_MTU(circuit) || |
pdu_len > stream_get_endp (circuit->rcv_stream)) |
pdu_len > stream_get_endp (circuit->rcv_stream)) |
{ |
{ |
zlog_warn ("Received a CSNP with bogus length %d", pdu_len); | zlog_warn ("Received a PSNP with bogus length %d", pdu_len); |
return ISIS_WARNING; |
return ISIS_WARNING; |
} |
} |
} |
} |
Line 1798 process_snp (int snp_type, int level, struct isis_circ
|
Line 1917 process_snp (int snp_type, int level, struct isis_circ
|
if (entry->rem_lifetime && entry->checksum && entry->seq_num && |
if (entry->rem_lifetime && entry->checksum && entry->seq_num && |
memcmp (entry->lsp_id, isis->sysid, ISIS_SYS_ID_LEN)) |
memcmp (entry->lsp_id, isis->sysid, ISIS_SYS_ID_LEN)) |
{ |
{ |
lsp = lsp_new (entry->lsp_id, ntohs (entry->rem_lifetime), | lsp = lsp_new(circuit->area, entry->lsp_id, |
0, 0, entry->checksum, level); | ntohs(entry->rem_lifetime), |
lsp->area = circuit->area; | 0, 0, entry->checksum, level); |
lsp_insert (lsp, circuit->area->lspdb[level - 1]); |
lsp_insert (lsp, circuit->area->lspdb[level - 1]); |
ISIS_FLAGS_CLEAR_ALL (lsp->SRMflags); |
ISIS_FLAGS_CLEAR_ALL (lsp->SRMflags); |
ISIS_SET_FLAG (lsp->SSNflags, circuit); |
ISIS_SET_FLAG (lsp->SSNflags, circuit); |
Line 1848 process_snp (int snp_type, int level, struct isis_circ
|
Line 1967 process_snp (int snp_type, int level, struct isis_circ
|
} |
} |
|
|
static int |
static int |
process_csnp (int level, struct isis_circuit *circuit, u_char * ssnpa) | process_csnp (int level, struct isis_circuit *circuit, const u_char *ssnpa) |
{ |
{ |
if (isis->debugs & DEBUG_SNP_PACKETS) |
if (isis->debugs & DEBUG_SNP_PACKETS) |
{ |
{ |
Line 1872 process_csnp (int level, struct isis_circuit *circuit,
|
Line 1991 process_csnp (int level, struct isis_circuit *circuit,
|
} |
} |
|
|
static int |
static int |
process_psnp (int level, struct isis_circuit *circuit, u_char * ssnpa) | process_psnp (int level, struct isis_circuit *circuit, const u_char *ssnpa) |
{ |
{ |
if (isis->debugs & DEBUG_SNP_PACKETS) |
if (isis->debugs & DEBUG_SNP_PACKETS) |
{ |
{ |
Line 1895 process_psnp (int level, struct isis_circuit *circuit,
|
Line 2014 process_psnp (int level, struct isis_circuit *circuit,
|
} |
} |
|
|
/* |
/* |
* Process ISH |
|
* ISO - 10589 |
|
* Section 8.2.2 - Receiving ISH PDUs by an intermediate system |
|
* FIXME: sample packet dump, need to figure 0x81 - looks like NLPid |
|
* 0x82 0x15 0x01 0x00 0x04 0x01 0x2c 0x59 |
|
* 0x38 0x08 0x47 0x00 0x01 0x00 0x02 0x00 |
|
* 0x03 0x00 0x81 0x01 0xcc |
|
*/ |
|
static int |
|
process_is_hello (struct isis_circuit *circuit) |
|
{ |
|
struct isis_adjacency *adj; |
|
int retval = ISIS_OK; |
|
u_char neigh_len; |
|
u_char *sysid; |
|
|
|
if (isis->debugs & DEBUG_ADJ_PACKETS) |
|
{ |
|
zlog_debug ("ISIS-Adj (%s): Rcvd ISH on %s, cirType %s, cirID %u", |
|
circuit->area->area_tag, circuit->interface->name, |
|
circuit_t2string (circuit->is_type), circuit->circuit_id); |
|
if (isis->debugs & DEBUG_PACKET_DUMP) |
|
zlog_dump_data (STREAM_DATA (circuit->rcv_stream), |
|
stream_get_endp (circuit->rcv_stream)); |
|
} |
|
|
|
/* In this point in time we are not yet able to handle is_hellos |
|
* on lan - Sorry juniper... |
|
*/ |
|
if (circuit->circ_type == CIRCUIT_T_BROADCAST) |
|
return retval; |
|
|
|
neigh_len = stream_getc (circuit->rcv_stream); |
|
sysid = STREAM_PNT (circuit->rcv_stream) + neigh_len - 1 - ISIS_SYS_ID_LEN; |
|
adj = circuit->u.p2p.neighbor; |
|
if (!adj) |
|
{ |
|
/* 8.2.2 */ |
|
adj = isis_new_adj (sysid, NULL, 0, circuit); |
|
if (adj == NULL) |
|
return ISIS_ERROR; |
|
|
|
isis_adj_state_change (adj, ISIS_ADJ_INITIALIZING, NULL); |
|
adj->sys_type = ISIS_SYSTYPE_UNKNOWN; |
|
circuit->u.p2p.neighbor = adj; |
|
} |
|
/* 8.2.2 a) */ |
|
if ((adj->adj_state == ISIS_ADJ_UP) && memcmp (adj->sysid, sysid, |
|
ISIS_SYS_ID_LEN)) |
|
{ |
|
/* 8.2.2 a) 1) FIXME: adjStateChange(down) event */ |
|
/* 8.2.2 a) 2) delete the adj */ |
|
XFREE (MTYPE_ISIS_ADJACENCY, adj); |
|
/* 8.2.2 a) 3) create a new adj */ |
|
adj = isis_new_adj (sysid, NULL, 0, circuit); |
|
if (adj == NULL) |
|
return ISIS_ERROR; |
|
|
|
/* 8.2.2 a) 3) i */ |
|
isis_adj_state_change (adj, ISIS_ADJ_INITIALIZING, NULL); |
|
/* 8.2.2 a) 3) ii */ |
|
adj->sys_type = ISIS_SYSTYPE_UNKNOWN; |
|
/* 8.2.2 a) 4) quite meaningless */ |
|
} |
|
/* 8.2.2 b) ignore on condition */ |
|
if ((adj->adj_state == ISIS_ADJ_INITIALIZING) && |
|
(adj->sys_type == ISIS_SYSTYPE_IS)) |
|
{ |
|
/* do nothing */ |
|
} |
|
else |
|
{ |
|
/* 8.2.2 c) respond with a p2p IIH */ |
|
send_hello (circuit, 1); |
|
} |
|
/* 8.2.2 d) type is IS */ |
|
adj->sys_type = ISIS_SYSTYPE_IS; |
|
/* 8.2.2 e) FIXME: Circuit type of? */ |
|
|
|
return retval; |
|
} |
|
|
|
/* |
|
* PDU Dispatcher |
* PDU Dispatcher |
*/ |
*/ |
|
|
Line 2107 isis_receive (struct thread *thread)
|
Line 2143 isis_receive (struct thread *thread)
|
circuit = THREAD_ARG (thread); |
circuit = THREAD_ARG (thread); |
assert (circuit); |
assert (circuit); |
|
|
if (circuit->rcv_stream == NULL) | isis_circuit_stream(circuit, &circuit->rcv_stream); |
circuit->rcv_stream = stream_new (ISO_MTU (circuit)); | |
else | |
stream_reset (circuit->rcv_stream); | |
|
|
retval = circuit->rx (circuit, ssnpa); |
retval = circuit->rx (circuit, ssnpa); |
circuit->t_read = NULL; |
circuit->t_read = NULL; |
Line 2146 isis_receive (struct thread *thread)
|
Line 2179 isis_receive (struct thread *thread)
|
|
|
circuit->t_read = NULL; |
circuit->t_read = NULL; |
|
|
if (circuit->rcv_stream == NULL) | isis_circuit_stream(circuit, &circuit->rcv_stream); |
circuit->rcv_stream = stream_new (ISO_MTU (circuit)); | |
else | |
stream_reset (circuit->rcv_stream); | |
|
|
retval = circuit->rx (circuit, ssnpa); |
retval = circuit->rx (circuit, ssnpa); |
|
|
Line 2241 send_hello (struct isis_circuit *circuit, int level)
|
Line 2271 send_hello (struct isis_circuit *circuit, int level)
|
struct isis_lan_hello_hdr hello_hdr; |
struct isis_lan_hello_hdr hello_hdr; |
struct isis_p2p_hello_hdr p2p_hello_hdr; |
struct isis_p2p_hello_hdr p2p_hello_hdr; |
unsigned char hmac_md5_hash[ISIS_AUTH_MD5_SIZE]; |
unsigned char hmac_md5_hash[ISIS_AUTH_MD5_SIZE]; |
unsigned long len_pointer, length, auth_tlv_offset = 0; | size_t len_pointer, length, auth_tlv_offset = 0; |
u_int32_t interval; |
u_int32_t interval; |
int retval; |
int retval; |
|
|
Line 2254 send_hello (struct isis_circuit *circuit, int level)
|
Line 2284 send_hello (struct isis_circuit *circuit, int level)
|
return ISIS_WARNING; |
return ISIS_WARNING; |
} |
} |
|
|
if (!circuit->snd_stream) | isis_circuit_stream(circuit, &circuit->snd_stream); |
circuit->snd_stream = stream_new (ISO_MTU (circuit)); | |
else | |
stream_reset (circuit->snd_stream); | |
|
|
if (circuit->circ_type == CIRCUIT_T_BROADCAST) |
if (circuit->circ_type == CIRCUIT_T_BROADCAST) |
if (level == IS_LEVEL_1) |
if (level == IS_LEVEL_1) |
Line 2389 send_hello (struct isis_circuit *circuit, int level)
|
Line 2416 send_hello (struct isis_circuit *circuit, int level)
|
hmac_md5 (STREAM_DATA (circuit->snd_stream), |
hmac_md5 (STREAM_DATA (circuit->snd_stream), |
stream_get_endp (circuit->snd_stream), |
stream_get_endp (circuit->snd_stream), |
(unsigned char *) &circuit->passwd.passwd, circuit->passwd.len, |
(unsigned char *) &circuit->passwd.passwd, circuit->passwd.len, |
(caddr_t) &hmac_md5_hash); | (unsigned char *) &hmac_md5_hash); |
/* Copy the hash into the stream */ |
/* Copy the hash into the stream */ |
memcpy (STREAM_DATA (circuit->snd_stream) + auth_tlv_offset + 3, |
memcpy (STREAM_DATA (circuit->snd_stream) + auth_tlv_offset + 3, |
hmac_md5_hash, ISIS_AUTH_MD5_SIZE); |
hmac_md5_hash, ISIS_AUTH_MD5_SIZE); |
Line 2399 send_hello (struct isis_circuit *circuit, int level)
|
Line 2426 send_hello (struct isis_circuit *circuit, int level)
|
{ |
{ |
if (circuit->circ_type == CIRCUIT_T_BROADCAST) |
if (circuit->circ_type == CIRCUIT_T_BROADCAST) |
{ |
{ |
zlog_debug ("ISIS-Adj (%s): Sent L%d LAN IIH on %s, length %ld", | zlog_debug ("ISIS-Adj (%s): Sending L%d LAN IIH on %s, length %zd", |
circuit->area->area_tag, level, circuit->interface->name, |
circuit->area->area_tag, level, circuit->interface->name, |
/* FIXME: use %z when we stop supporting old compilers. */ |
|
length); |
length); |
} |
} |
else |
else |
{ |
{ |
zlog_debug ("ISIS-Adj (%s): Sent P2P IIH on %s, length %ld", | zlog_debug ("ISIS-Adj (%s): Sending P2P IIH on %s, length %zd", |
circuit->area->area_tag, circuit->interface->name, |
circuit->area->area_tag, circuit->interface->name, |
/* FIXME: use %z when we stop supporting old compilers. */ |
|
length); |
length); |
} |
} |
if (isis->debugs & DEBUG_PACKET_DUMP) |
if (isis->debugs & DEBUG_PACKET_DUMP) |
Line 2434 send_lan_l1_hello (struct thread *thread)
|
Line 2459 send_lan_l1_hello (struct thread *thread)
|
assert (circuit); |
assert (circuit); |
circuit->u.bc.t_send_lan_hello[0] = NULL; |
circuit->u.bc.t_send_lan_hello[0] = NULL; |
|
|
|
if (!(circuit->area->is_type & IS_LEVEL_1)) |
|
{ |
|
zlog_warn ("ISIS-Hello (%s): Trying to send L1 IIH in L2-only area", |
|
circuit->area->area_tag); |
|
return 1; |
|
} |
|
|
if (circuit->u.bc.run_dr_elect[0]) |
if (circuit->u.bc.run_dr_elect[0]) |
retval = isis_dr_elect (circuit, 1); |
retval = isis_dr_elect (circuit, 1); |
|
|
Line 2457 send_lan_l2_hello (struct thread *thread)
|
Line 2489 send_lan_l2_hello (struct thread *thread)
|
assert (circuit); |
assert (circuit); |
circuit->u.bc.t_send_lan_hello[1] = NULL; |
circuit->u.bc.t_send_lan_hello[1] = NULL; |
|
|
|
if (!(circuit->area->is_type & IS_LEVEL_2)) |
|
{ |
|
zlog_warn ("ISIS-Hello (%s): Trying to send L2 IIH in L1 area", |
|
circuit->area->area_tag); |
|
return 1; |
|
} |
|
|
if (circuit->u.bc.run_dr_elect[1]) |
if (circuit->u.bc.run_dr_elect[1]) |
retval = isis_dr_elect (circuit, 2); |
retval = isis_dr_elect (circuit, 2); |
|
|
Line 2501 build_csnp (int level, u_char * start, u_char * stop,
|
Line 2540 build_csnp (int level, u_char * start, u_char * stop,
|
unsigned long auth_tlv_offset = 0; |
unsigned long auth_tlv_offset = 0; |
int retval = ISIS_OK; |
int retval = ISIS_OK; |
|
|
if (circuit->snd_stream == NULL) | isis_circuit_stream(circuit, &circuit->snd_stream); |
circuit->snd_stream = stream_new (ISO_MTU (circuit)); | |
else | |
stream_reset (circuit->snd_stream); | |
|
|
if (level == IS_LEVEL_1) |
if (level == IS_LEVEL_1) |
fill_fixed_hdr_andstream (&fixed_hdr, L1_COMPLETE_SEQ_NUM, |
fill_fixed_hdr_andstream (&fixed_hdr, L1_COMPLETE_SEQ_NUM, |
Line 2576 build_csnp (int level, u_char * start, u_char * stop,
|
Line 2612 build_csnp (int level, u_char * start, u_char * stop,
|
hmac_md5 (STREAM_DATA (circuit->snd_stream), |
hmac_md5 (STREAM_DATA (circuit->snd_stream), |
stream_get_endp(circuit->snd_stream), |
stream_get_endp(circuit->snd_stream), |
(unsigned char *) &passwd->passwd, passwd->len, |
(unsigned char *) &passwd->passwd, passwd->len, |
(caddr_t) &hmac_md5_hash); | (unsigned char *) &hmac_md5_hash); |
/* Copy the hash into the stream */ |
/* Copy the hash into the stream */ |
memcpy (STREAM_DATA (circuit->snd_stream) + auth_tlv_offset + 3, |
memcpy (STREAM_DATA (circuit->snd_stream) + auth_tlv_offset + 3, |
hmac_md5_hash, ISIS_AUTH_MD5_SIZE); |
hmac_md5_hash, ISIS_AUTH_MD5_SIZE); |
Line 2721 send_csnp (struct isis_circuit *circuit, int level)
|
Line 2757 send_csnp (struct isis_circuit *circuit, int level)
|
|
|
if (isis->debugs & DEBUG_SNP_PACKETS) |
if (isis->debugs & DEBUG_SNP_PACKETS) |
{ |
{ |
zlog_debug ("ISIS-Snp (%s): Sent L%d CSNP on %s, length %ld", | zlog_debug ("ISIS-Snp (%s): Sending L%d CSNP on %s, length %zd", |
circuit->area->area_tag, level, circuit->interface->name, |
circuit->area->area_tag, level, circuit->interface->name, |
stream_get_endp (circuit->snd_stream)); |
stream_get_endp (circuit->snd_stream)); |
for (ALL_LIST_ELEMENTS_RO (list, node, lsp)) |
for (ALL_LIST_ELEMENTS_RO (list, node, lsp)) |
Line 2828 build_psnp (int level, struct isis_circuit *circuit, s
|
Line 2864 build_psnp (int level, struct isis_circuit *circuit, s
|
unsigned long auth_tlv_offset = 0; |
unsigned long auth_tlv_offset = 0; |
int retval = ISIS_OK; |
int retval = ISIS_OK; |
|
|
if (circuit->snd_stream == NULL) | isis_circuit_stream(circuit, &circuit->snd_stream); |
circuit->snd_stream = stream_new (ISO_MTU (circuit)); | |
else | |
stream_reset (circuit->snd_stream); | |
|
|
if (level == IS_LEVEL_1) |
if (level == IS_LEVEL_1) |
fill_fixed_hdr_andstream (&fixed_hdr, L1_PARTIAL_SEQ_NUM, |
fill_fixed_hdr_andstream (&fixed_hdr, L1_PARTIAL_SEQ_NUM, |
Line 2912 build_psnp (int level, struct isis_circuit *circuit, s
|
Line 2945 build_psnp (int level, struct isis_circuit *circuit, s
|
hmac_md5 (STREAM_DATA (circuit->snd_stream), |
hmac_md5 (STREAM_DATA (circuit->snd_stream), |
stream_get_endp(circuit->snd_stream), |
stream_get_endp(circuit->snd_stream), |
(unsigned char *) &passwd->passwd, passwd->len, |
(unsigned char *) &passwd->passwd, passwd->len, |
(caddr_t) &hmac_md5_hash); | (unsigned char *) &hmac_md5_hash); |
/* Copy the hash into the stream */ |
/* Copy the hash into the stream */ |
memcpy (STREAM_DATA (circuit->snd_stream) + auth_tlv_offset + 3, |
memcpy (STREAM_DATA (circuit->snd_stream) + auth_tlv_offset + 3, |
hmac_md5_hash, ISIS_AUTH_MD5_SIZE); |
hmac_md5_hash, ISIS_AUTH_MD5_SIZE); |
Line 2970 send_psnp (int level, struct isis_circuit *circuit)
|
Line 3003 send_psnp (int level, struct isis_circuit *circuit)
|
|
|
if (isis->debugs & DEBUG_SNP_PACKETS) |
if (isis->debugs & DEBUG_SNP_PACKETS) |
{ |
{ |
zlog_debug ("ISIS-Snp (%s): Sent L%d PSNP on %s, length %ld", | zlog_debug ("ISIS-Snp (%s): Sending L%d PSNP on %s, length %zd", |
circuit->area->area_tag, level, |
circuit->area->area_tag, level, |
circuit->interface->name, |
circuit->interface->name, |
stream_get_endp (circuit->snd_stream)); |
stream_get_endp (circuit->snd_stream)); |
Line 3054 send_lsp (struct thread *thread)
|
Line 3087 send_lsp (struct thread *thread)
|
struct isis_circuit *circuit; |
struct isis_circuit *circuit; |
struct isis_lsp *lsp; |
struct isis_lsp *lsp; |
struct listnode *node; |
struct listnode *node; |
|
int clear_srm = 1; |
int retval = ISIS_OK; |
int retval = ISIS_OK; |
|
|
circuit = THREAD_ARG (thread); |
circuit = THREAD_ARG (thread); |
assert (circuit); |
assert (circuit); |
|
|
if (circuit->state != C_STATE_UP || circuit->is_passive == 1) | if (!circuit->lsp_queue) |
{ | return ISIS_OK; |
return retval; | |
} | |
|
|
node = listhead (circuit->lsp_queue); |
node = listhead (circuit->lsp_queue); |
|
|
Line 3072 send_lsp (struct thread *thread)
|
Line 3104 send_lsp (struct thread *thread)
|
* thread gets a chance to run. |
* thread gets a chance to run. |
*/ |
*/ |
if (!node) |
if (!node) |
{ | return ISIS_OK; |
return retval; | |
} | |
|
|
|
/* |
|
* Delete LSP from lsp_queue. If it's still in queue, it is assumed |
|
* as 'transmit pending', but send_lsp may never be called again. |
|
* Retry will happen because SRM flag will not be cleared. |
|
*/ |
lsp = listgetdata(node); |
lsp = listgetdata(node); |
|
list_delete_node (circuit->lsp_queue, node); |
|
|
|
/* Set the last-cleared time if the queue is empty. */ |
|
/* TODO: Is is possible that new lsps keep being added to the queue |
|
* that the queue is never empty? */ |
|
if (list_isempty (circuit->lsp_queue)) |
|
circuit->lsp_queue_last_cleared = time (NULL); |
|
|
|
if (circuit->state != C_STATE_UP || circuit->is_passive == 1) |
|
goto out; |
|
|
/* |
/* |
* Do not send if levels do not match |
* Do not send if levels do not match |
*/ |
*/ |
if (!(lsp->level & circuit->is_type)) |
if (!(lsp->level & circuit->is_type)) |
{ | goto out; |
list_delete_node (circuit->lsp_queue, node); | |
return retval; | |
} | |
|
|
/* |
/* |
* Do not send if we do not have adjacencies in state up on the circuit |
* Do not send if we do not have adjacencies in state up on the circuit |
*/ |
*/ |
if (circuit->upadjcount[lsp->level - 1] == 0) |
if (circuit->upadjcount[lsp->level - 1] == 0) |
|
goto out; |
|
|
|
/* stream_copy will assert and stop program execution if LSP is larger than |
|
* the circuit's MTU. So handle and log this case here. */ |
|
if (stream_get_endp(lsp->pdu) > stream_get_size(circuit->snd_stream)) |
{ |
{ |
list_delete_node (circuit->lsp_queue, node); | zlog_err("ISIS-Upd (%s): Can't send L%d LSP %s, seq 0x%08x," |
return retval; | " cksum 0x%04x, lifetime %us 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), |
| circuit->interface->name, |
| stream_get_endp(lsp->pdu), |
| stream_get_size(circuit->snd_stream)); |
| if (isis->debugs & DEBUG_PACKET_DUMP) |
| zlog_dump_data(STREAM_DATA(lsp->pdu), stream_get_endp(lsp->pdu)); |
| retval = ISIS_ERROR; |
| goto out; |
} |
} |
|
|
/* copy our lsp to the send buffer */ |
/* copy our lsp to the send buffer */ |
Line 3102 send_lsp (struct thread *thread)
|
Line 3162 send_lsp (struct thread *thread)
|
if (isis->debugs & DEBUG_UPDATE_PACKETS) |
if (isis->debugs & DEBUG_UPDATE_PACKETS) |
{ |
{ |
zlog_debug |
zlog_debug |
("ISIS-Upd (%s): Sent L%d LSP %s, seq 0x%08x, cksum 0x%04x," | ("ISIS-Upd (%s): Sending L%d LSP %s, seq 0x%08x, cksum 0x%04x," |
" lifetime %us on %s", circuit->area->area_tag, lsp->level, |
" lifetime %us on %s", circuit->area->area_tag, lsp->level, |
rawlspid_print (lsp->lsp_header->lsp_id), |
rawlspid_print (lsp->lsp_header->lsp_id), |
ntohl (lsp->lsp_header->seq_num), |
ntohl (lsp->lsp_header->seq_num), |
Line 3114 send_lsp (struct thread *thread)
|
Line 3174 send_lsp (struct thread *thread)
|
stream_get_endp (circuit->snd_stream)); |
stream_get_endp (circuit->snd_stream)); |
} |
} |
|
|
|
clear_srm = 0; |
retval = circuit->tx (circuit, lsp->level); |
retval = circuit->tx (circuit, lsp->level); |
if (retval != ISIS_OK) |
if (retval != ISIS_OK) |
{ |
{ |
zlog_err ("ISIS-Upd (%s): Send L%d LSP on %s failed", | zlog_err ("ISIS-Upd (%s): Send L%d LSP on %s failed %s", |
circuit->area->area_tag, lsp->level, |
circuit->area->area_tag, lsp->level, |
circuit->interface->name); | circuit->interface->name, |
return retval; | (retval == ISIS_WARNING) ? "temporarily" : "permanently"); |
} |
} |
|
|
/* | out: |
* If the sending succeeded, we can del the lsp from circuits | if (clear_srm |
* lsp_queue | || (retval == ISIS_OK && circuit->circ_type == CIRCUIT_T_BROADCAST) |
*/ | || (retval != ISIS_OK && retval != ISIS_WARNING)) |
list_delete_node (circuit->lsp_queue, node); | { |
| /* SRM flag will trigger retransmission. We will not retransmit if we |
| * encountered a fatal error. |
| * On success, they should only be cleared if it's a broadcast circuit. |
| * On a P2P circuit, we will wait for the ack from the neighbor to clear |
| * the fag. |
| */ |
| ISIS_CLEAR_FLAG (lsp->SRMflags, circuit); |
| } |
|
|
/* Set the last-cleared time if the queue is empty. */ |
|
/* TODO: Is is possible that new lsps keep being added to the queue |
|
* that the queue is never empty? */ |
|
if (list_isempty (circuit->lsp_queue)) |
|
circuit->lsp_queue_last_cleared = time (NULL); |
|
|
|
/* |
|
* On broadcast circuits also the SRMflag can be cleared |
|
*/ |
|
if (circuit->circ_type == CIRCUIT_T_BROADCAST) |
|
ISIS_CLEAR_FLAG (lsp->SRMflags, circuit); |
|
|
|
return retval; |
return retval; |
} |
} |
|
|
Line 3153 ack_lsp (struct isis_link_state_hdr *hdr, struct isis_
|
Line 3210 ack_lsp (struct isis_link_state_hdr *hdr, struct isis_
|
u_int16_t length; |
u_int16_t length; |
struct isis_fixed_hdr fixed_hdr; |
struct isis_fixed_hdr fixed_hdr; |
|
|
if (!circuit->snd_stream) | isis_circuit_stream(circuit, &circuit->snd_stream); |
circuit->snd_stream = stream_new (ISO_MTU (circuit)); | |
else | |
stream_reset (circuit->snd_stream); | |
|
|
// fill_llc_hdr (stream); |
// fill_llc_hdr (stream); |
if (level == IS_LEVEL_1) |
if (level == IS_LEVEL_1) |