Merge pull request #1379 from donaldsharp/eigrp_crashes

Eigrp crashes
This commit is contained in:
Renato Westphal 2017-11-02 13:09:46 -02:00 committed by GitHub
commit e919cf55bd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 134 additions and 52 deletions

View File

@ -297,6 +297,12 @@ enum eigrp_fsm_events {
#define EIGRP_TLV_IPv4_EXT (EIGRP_TLV_IPv4 | EIGRP_TLV_EXTERNAL)
#define EIGRP_TLV_IPv4_COM (EIGRP_TLV_IPv4 | EIGRP_TLV_COMMUNITY)
#define EIGRP_TLV_IPV4_SIZE_GRT_24_BIT 0x001D
#define EIGRP_TLV_IPV4_SIZE_GRT_16_BIT 0x001C
#define EIGRP_TLV_IPV4_SIZE_GRT_8_BIT 0x001B
#define EIGRP_TLV_IPV4_SIZE_GRT_0_BIT 0x001A
#define EIGRP_TLV_MAX_IPV4_BYTE EIGRP_TLV_IPV4_SIZE_GRT_24_BIT
/* max number of TLV IPv4 prefixes in packet */
#define EIGRP_TLV_MAX_IPv4 25

View File

@ -1165,25 +1165,57 @@ u_int16_t eigrp_add_internalTLV_to_stream(struct stream *s,
u_int16_t length;
stream_putw(s, EIGRP_TLV_IPv4_INT);
if (pe->destination->prefixlen <= 8) {
stream_putw(s, 0x001A);
length = 0x001A;
switch (pe->destination->prefixlen) {
case 0:
case 1:
case 2:
case 3:
case 4:
case 5:
case 6:
case 7:
case 8:
length = EIGRP_TLV_IPV4_SIZE_GRT_0_BIT;
stream_putw(s, length);
break;
case 9:
case 10:
case 11:
case 12:
case 13:
case 14:
case 15:
case 16:
length = EIGRP_TLV_IPV4_SIZE_GRT_8_BIT;
stream_putw(s, length);
break;
case 17:
case 18:
case 19:
case 20:
case 21:
case 22:
case 23:
case 24:
length = EIGRP_TLV_IPV4_SIZE_GRT_16_BIT;
stream_putw(s, length);
break;
case 25:
case 26:
case 27:
case 28:
case 29:
case 30:
case 31:
case 32:
length = EIGRP_TLV_IPV4_SIZE_GRT_24_BIT;
stream_putw(s, length);
break;
default:
zlog_err("%s: Unexpected prefix length: %d",
__PRETTY_FUNCTION__, pe->destination->prefixlen);
return 0;
}
if ((pe->destination->prefixlen > 8)
&& (pe->destination->prefixlen <= 16)) {
stream_putw(s, 0x001B);
length = 0x001B;
}
if ((pe->destination->prefixlen > 16)
&& (pe->destination->prefixlen <= 24)) {
stream_putw(s, 0x001C);
length = 0x001C;
}
if (pe->destination->prefixlen > 24) {
stream_putw(s, 0x001D);
length = 0x001D;
}
stream_putl(s, 0x00000000);
/*Metric*/

View File

@ -160,49 +160,91 @@ void eigrp_query_receive(struct eigrp *eigrp, struct ip *iph,
void eigrp_send_query(struct eigrp_interface *ei)
{
struct eigrp_packet *ep;
struct eigrp_packet *ep = NULL;
u_int16_t length = EIGRP_HEADER_LEN;
struct listnode *node, *nnode, *node2, *nnode2;
struct eigrp_neighbor *nbr;
struct eigrp_prefix_entry *pe;
bool has_tlv = false;
bool ep_saved = false;
ep = eigrp_packet_new(ei->ifp->mtu, NULL);
/* Prepare EIGRP INIT UPDATE header */
eigrp_packet_header_init(EIGRP_OPC_QUERY, ei->eigrp, ep->s, 0,
ei->eigrp->sequence_number, 0);
// encode Authentication TLV, if needed
if ((ei->params.auth_type == EIGRP_AUTH_TYPE_MD5)
&& (ei->params.auth_keychain != NULL)) {
length += eigrp_add_authTLV_MD5_to_stream(ep->s, ei);
}
bool new_packet = true;
for (ALL_LIST_ELEMENTS(ei->eigrp->topology_changes_internalIPV4, node,
nnode, pe)) {
if (!(pe->req_action & EIGRP_FSM_NEED_QUERY))
continue;
length += eigrp_add_internalTLV_to_stream(ep->s, pe);
for (ALL_LIST_ELEMENTS(ei->nbrs, node2, nnode2, nbr)) {
if (nbr->state == EIGRP_NEIGHBOR_UP) {
listnode_add(pe->rij, nbr);
has_tlv = true;;
if (new_packet) {
ep = eigrp_packet_new(ei->ifp->mtu, NULL);
/* Prepare EIGRP INIT UPDATE header */
eigrp_packet_header_init(EIGRP_OPC_QUERY,
ei->eigrp, ep->s, 0,
ei->eigrp->sequence_number, 0);
// encode Authentication TLV, if needed
if ((ei->params.auth_type == EIGRP_AUTH_TYPE_MD5)
&& (ei->params.auth_keychain != NULL)) {
length +=
eigrp_add_authTLV_MD5_to_stream(ep->s,
ei);
}
new_packet = false;
}
length += eigrp_add_internalTLV_to_stream(ep->s, pe);
has_tlv = true;
for (ALL_LIST_ELEMENTS(ei->nbrs, node2, nnode2, nbr)) {
if (nbr->state == EIGRP_NEIGHBOR_UP)
listnode_add(pe->rij, nbr);
}
if (length + EIGRP_TLV_MAX_IPV4_BYTE > (uint16_t)ei->ifp->mtu) {
if ((ei->params.auth_type == EIGRP_AUTH_TYPE_MD5)
&& ei->params.auth_keychain != NULL) {
eigrp_make_md5_digest(ei, ep->s,
EIGRP_AUTH_UPDATE_FLAG);
}
eigrp_packet_checksum(ei, ep->s, length);
ep->length = length;
ep->dst.s_addr = htonl(EIGRP_MULTICAST_ADDRESS);
ep->sequence_number = ei->eigrp->sequence_number;
ei->eigrp->sequence_number++;
for (ALL_LIST_ELEMENTS(ei->nbrs, node2, nnode2, nbr)) {
struct eigrp_packet *dup;
if (nbr->state != EIGRP_NEIGHBOR_UP)
continue;
dup = eigrp_packet_duplicate(ep, nbr);
/*Put packet to retransmission queue*/
eigrp_fifo_push(nbr->retrans_queue, dup);
if (nbr->retrans_queue->count == 1)
eigrp_send_packet_reliably(nbr);
}
has_tlv = false;
length = 0;
eigrp_packet_free(ep);
ep = NULL;
new_packet = true;
}
}
if (!has_tlv) {
if (ep)
eigrp_packet_free(ep);
return;
}
if ((ei->params.auth_type == EIGRP_AUTH_TYPE_MD5)
&& ei->params.auth_keychain != NULL) {
&& ei->params.auth_keychain != NULL)
eigrp_make_md5_digest(ei, ep->s, EIGRP_AUTH_UPDATE_FLAG);
}
/* EIGRP Checksum */
eigrp_packet_checksum(ei, ep->s, length);
@ -215,17 +257,18 @@ void eigrp_send_query(struct eigrp_interface *ei)
ei->eigrp->sequence_number++;
for (ALL_LIST_ELEMENTS(ei->nbrs, node2, nnode2, nbr)) {
if (nbr->state == EIGRP_NEIGHBOR_UP) {
/*Put packet to retransmission queue*/
eigrp_fifo_push(nbr->retrans_queue, ep);
ep_saved = true;
struct eigrp_packet *dup;
if (nbr->retrans_queue->count == 1) {
if (nbr->state != EIGRP_NEIGHBOR_UP)
continue;
dup = eigrp_packet_duplicate(ep, nbr);
/*Put packet to retransmission queue*/
eigrp_fifo_push(nbr->retrans_queue, dup);
if (nbr->retrans_queue->count == 1)
eigrp_send_packet_reliably(nbr);
}
}
}
if (!ep_saved)
eigrp_packet_free(ep);
}

View File

@ -560,7 +560,7 @@ void eigrp_update_send_EOT(struct eigrp_neighbor *nbr)
if (eigrp_nbr_split_horizon_check(te, ei))
continue;
if ((length + 0x001D) > mtu) {
if ((length + EIGRP_TLV_MAX_IPV4_BYTE) > mtu) {
eigrp_update_place_on_nbr_queue (nbr, ep, seq_no, length);
seq_no++;
@ -635,7 +635,8 @@ void eigrp_update_send(struct eigrp_interface *ei)
if (eigrp_nbr_split_horizon_check(ne, ei))
continue;
if ((length + 0x001D) > (u_int16_t)ei->ifp->mtu) {
if ((length + EIGRP_TLV_MAX_IPV4_BYTE) >
(u_int16_t)ei->ifp->mtu) {
if ((ei->params.auth_type == EIGRP_AUTH_TYPE_MD5)
&& (ei->params.auth_keychain != NULL)) {
eigrp_make_md5_digest(ei, ep->s, EIGRP_AUTH_UPDATE_FLAG);