summaryrefslogtreecommitdiffstats
path: root/eigrpd/eigrp_update.c
diff options
context:
space:
mode:
authorDonald Sharp <sharpd@cumulusnetworks.com>2017-08-19 20:15:34 +0200
committerDonald Sharp <sharpd@cumulusnetworks.com>2017-08-19 20:23:15 +0200
commita6e8810ee341b0c1fc959ca0c9ed044990b4bfc8 (patch)
tree675c11b6bbf5fa166e1a34ecdebf838f5cf3a57c /eigrpd/eigrp_update.c
parenteigrpd: Fix memory leak in eigrp_update (diff)
downloadfrr-a6e8810ee341b0c1fc959ca0c9ed044990b4bfc8.tar.xz
frr-a6e8810ee341b0c1fc959ca0c9ed044990b4bfc8.zip
eigrpd: Allow eigrp_update_send to recognize a full packet
Modify code to allow the eigrp_update_send function to recognize that we have a full packet and to do the right thing from there. Signed-off-by: Donald Sharp <sharpd@cumulusnetworks.com>
Diffstat (limited to '')
-rw-r--r--eigrpd/eigrp_update.c90
1 files changed, 65 insertions, 25 deletions
diff --git a/eigrpd/eigrp_update.c b/eigrpd/eigrp_update.c
index e42f84abc..8971635bf 100644
--- a/eigrpd/eigrp_update.c
+++ b/eigrpd/eigrp_update.c
@@ -534,6 +534,38 @@ static void eigrp_update_place_on_nbr_queue(struct eigrp_neighbor *nbr,
eigrp_send_packet_reliably(nbr);
}
+static void eigrp_update_send_to_all_nbrs(struct eigrp_interface *ei,
+ struct eigrp_packet *ep)
+{
+ struct listnode *node, *nnode;
+ struct eigrp_neighbor *nbr;
+ bool packet_sent = false;
+
+ for (ALL_LIST_ELEMENTS(ei->nbrs, node, nnode, nbr)) {
+ struct eigrp_packet *ep_dup;
+
+ if (nbr->state != EIGRP_NEIGHBOR_UP)
+ continue;
+
+ if (packet_sent)
+ ep_dup = eigrp_packet_duplicate(ep, NULL);
+ else
+ ep_dup = ep;
+
+ ep_dup->nbr = nbr;
+ packet_sent = true;
+ /*Put packet to retransmission queue*/
+ eigrp_fifo_push(nbr->retrans_queue, ep_dup);
+
+ if (nbr->retrans_queue->count == 1) {
+ eigrp_send_packet_reliably(nbr);
+ }
+ }
+
+ if (!packet_sent)
+ eigrp_packet_free(ep);
+}
+
void eigrp_update_send_EOT(struct eigrp_neighbor *nbr)
{
struct eigrp_packet *ep;
@@ -617,13 +649,13 @@ void eigrp_update_send_EOT(struct eigrp_neighbor *nbr)
}
eigrp_update_place_on_nbr_queue (nbr, ep, seq_no, length);
+ nbr->ei->eigrp->sequence_number = seq_no++;
}
void eigrp_update_send(struct eigrp_interface *ei)
{
struct eigrp_packet *ep;
struct listnode *node, *nnode;
- struct eigrp_neighbor *nbr;
struct eigrp_prefix_entry *pe;
u_char has_tlv;
struct access_list *alist;
@@ -632,7 +664,10 @@ void eigrp_update_send(struct eigrp_interface *ei)
struct prefix_list *plist_i;
struct eigrp *e;
struct prefix_ipv4 *dest_addr;
- bool packet_sent = false;
+ u_int32_t seq_no = ei->eigrp->sequence_number;
+
+ if (ei->nbrs->count == 0)
+ return;
u_int16_t length = EIGRP_HEADER_LEN;
@@ -640,7 +675,7 @@ void eigrp_update_send(struct eigrp_interface *ei)
/* Prepare EIGRP INIT UPDATE header */
eigrp_packet_header_init(EIGRP_OPC_UPDATE, ei, ep->s, 0,
- ei->eigrp->sequence_number, 0);
+ seq_no, 0);
// encode Authentication TLV, if needed
if ((IF_DEF_PARAMS(ei->ifp)->auth_type == EIGRP_AUTH_TYPE_MD5)
@@ -655,6 +690,31 @@ void eigrp_update_send(struct eigrp_interface *ei)
if (!(pe->req_action & EIGRP_FSM_NEED_UPDATE))
continue;
+ if ((length + 0x001D) > (u_int16_t)ei->ifp->mtu) {
+ if ((IF_DEF_PARAMS(ei->ifp)->auth_type == EIGRP_AUTH_TYPE_MD5)
+ && (IF_DEF_PARAMS(ei->ifp)->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 = seq_no;
+ seq_no++;
+ eigrp_update_send_to_all_nbrs(ei, ep);
+
+ length = EIGRP_HEADER_LEN;
+ ep = eigrp_packet_new(ei->ifp->mtu, NULL);
+ eigrp_packet_header_init(EIGRP_OPC_UPDATE, ei, ep->s, 0,
+ seq_no, 0);
+ if ((IF_DEF_PARAMS(ei->ifp)->auth_type == EIGRP_AUTH_TYPE_MD5)
+ && (IF_DEF_PARAMS(ei->ifp)->auth_keychain != NULL)) {
+ length += eigrp_add_authTLV_MD5_to_stream(ep->s, ei);
+ }
+ has_tlv = 0;
+ }
/* Get destination address from prefix */
dest_addr = pe->destination_ipv4;
@@ -718,28 +778,8 @@ void eigrp_update_send(struct eigrp_interface *ei)
zlog_debug("Enqueuing Update length[%u] Seq [%u]", length,
ep->sequence_number);
- for (ALL_LIST_ELEMENTS(ei->nbrs, node, nnode, nbr)) {
- struct eigrp_packet *ep_dup;
-
- if (nbr->state != EIGRP_NEIGHBOR_UP)
- continue;
-
- if (packet_sent)
- ep_dup = eigrp_packet_duplicate(ep);
- else
- ep_dup = ep;
-
- packet_sent = true;
- /*Put packet to retransmission queue*/
- eigrp_fifo_push(nbr->retrans_queue, ep_dup);
-
- if (nbr->retrans_queue->count == 1) {
- eigrp_send_packet_reliably(nbr);
- }
- }
-
- if (!packet_sent)
- eigrp_packet_free(ep);
+ eigrp_update_send_to_all_nbrs(ei, ep);
+ ei->eigrp->sequence_number = seq_no++;
}
void eigrp_update_send_all(struct eigrp *eigrp,