]> git.proxmox.com Git - mirror_frr.git/blame - eigrpd/eigrp_update.c
Merge pull request #531 from qlyoung/fix-stack-ref
[mirror_frr.git] / eigrpd / eigrp_update.c
CommitLineData
7f57883e
DS
1/*
2 * EIGRP Sending and Receiving EIGRP Update Packets.
3 * Copyright (C) 2013-2016
4 * Authors:
5 * Donnie Savage
6 * Jan Janovic
7 * Matej Perina
8 * Peter Orsag
9 * Peter Paluch
10 * Frantisek Gazo
11 * Tomas Hvorkovy
12 * Martin Kontsek
13 * Lukas Koribsky
14 *
15 * This file is part of GNU Zebra.
16 *
17 * GNU Zebra is free software; you can redistribute it and/or modify it
18 * under the terms of the GNU General Public License as published by the
19 * Free Software Foundation; either version 2, or (at your option) any
20 * later version.
21 *
22 * GNU Zebra is distributed in the hope that it will be useful, but
23 * WITHOUT ANY WARRANTY; without even the implied warranty of
24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
25 * General Public License for more details.
26 *
27 * You should have received a copy of the GNU General Public License
28 * along with GNU Zebra; see the file COPYING. If not, write to the Free
29 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
30 * 02111-1307, USA.
31 */
32
33#include <zebra.h>
34
35#include "thread.h"
36#include "memory.h"
37#include "linklist.h"
38#include "prefix.h"
39#include "if.h"
40#include "table.h"
41#include "sockunion.h"
42#include "stream.h"
43#include "log.h"
44#include "sockopt.h"
45#include "checksum.h"
46#include "md5.h"
47#include "vty.h"
48#include "plist.h"
49#include "plist_int.h"
50#include "routemap.h"
51#include "vty.h"
52
53#include "eigrpd/eigrp_structs.h"
54#include "eigrpd/eigrpd.h"
55#include "eigrpd/eigrp_interface.h"
56#include "eigrpd/eigrp_neighbor.h"
57#include "eigrpd/eigrp_packet.h"
58#include "eigrpd/eigrp_zebra.h"
59#include "eigrpd/eigrp_vty.h"
60#include "eigrpd/eigrp_dump.h"
61#include "eigrpd/eigrp_macros.h"
62#include "eigrpd/eigrp_topology.h"
63#include "eigrpd/eigrp_fsm.h"
64#include "eigrpd/eigrp_network.h"
65#include "eigrpd/eigrp_memory.h"
66
67/**
68 * @fn remove_received_prefix_gr
69 *
70 * @param[in] nbr_prefixes List of neighbor prefixes
71 * @param[in] recv_prefix Prefix which needs to be removed from list
72 *
73 * @return void
74 *
75 * @par
76 * Function is used for removing received prefix
77 * from list of neighbor prefixes
78 */
79static void
80remove_received_prefix_gr (struct list *nbr_prefixes, struct eigrp_prefix_entry *recv_prefix)
81{
f9e5c9ca
DS
82 struct listnode *node1, *node11;
83 struct eigrp_prefix_entry *prefix = NULL;
84
85 /* iterate over all prefixes in list */
86 for (ALL_LIST_ELEMENTS(nbr_prefixes, node1, node11, prefix))
87 {
88 /* remove prefix from list if found */
89 if (prefix == recv_prefix)
90 {
91 listnode_delete(nbr_prefixes, prefix);
92 }
93 }
7f57883e
DS
94}
95
96/**
97 * @fn eigrp_update_receive_GR_ask
98 *
99 * @param[in] eigrp EIGRP process
100 * @param[in] nbr Neighbor update of who we received
101 * @param[in] nbr_prefixes Prefixes which weren't advertised
102 *
103 * @return void
104 *
105 * @par
106 * Function is used for notifying FSM about prefixes which
107 * weren't advertised by neighbor:
108 * We will send message to FSM with prefix delay set to infinity.
109 */
110static void
111eigrp_update_receive_GR_ask (struct eigrp *eigrp, struct eigrp_neighbor *nbr, struct list *nbr_prefixes)
112{
f9e5c9ca
DS
113 struct listnode *node1;
114 struct eigrp_prefix_entry *prefix;
115 struct TLV_IPv4_Internal_type *tlv_max;
116
117 /* iterate over all prefixes which weren't advertised by neighbor */
118 for (ALL_LIST_ELEMENTS_RO(nbr_prefixes, node1, prefix))
119 {
120 zlog_debug("GR receive: Neighbor not advertised %s/%d",
121 inet_ntoa(prefix->destination_ipv4->prefix),
122 prefix->destination_ipv4->prefixlen);
123
124 /* create internal IPv4 TLV with infinite delay */
125 tlv_max = eigrp_IPv4_InternalTLV_new();
126 tlv_max->type = EIGRP_TLV_IPv4_INT;
127 tlv_max->length = 28U;
128 tlv_max->metric = prefix->reported_metric;
129 /* set delay to MAX */
130 tlv_max->metric.delay = EIGRP_MAX_METRIC;
131 tlv_max->destination = prefix->destination_ipv4->prefix;
132 tlv_max->prefix_length = prefix->destination_ipv4->prefixlen;
133
134
135 /* prepare message for FSM */
136 struct eigrp_fsm_action_message *fsm_msg;
137 fsm_msg = XCALLOC(MTYPE_EIGRP_FSM_MSG,
138 sizeof(struct eigrp_fsm_action_message));
139
140 struct eigrp_neighbor_entry *entry =
141 eigrp_prefix_entry_lookup(prefix->entries, nbr);
142
143 fsm_msg->packet_type = EIGRP_OPC_UPDATE;
144 fsm_msg->eigrp = eigrp;
145 fsm_msg->data_type = EIGRP_TLV_IPv4_INT;
146 fsm_msg->adv_router = nbr;
147 fsm_msg->data.ipv4_int_type = tlv_max;
148 fsm_msg->entry = entry;
149 fsm_msg->prefix = prefix;
150
151 /* send message to FSM */
152 int event = eigrp_get_fsm_event(fsm_msg);
153 eigrp_fsm_event(fsm_msg, event);
154
155 /* free memory used by TLV */
156 eigrp_IPv4_InternalTLV_free (tlv_max);
157 }
7f57883e
DS
158}
159
160/*
161 * EIGRP UPDATE read function
162 */
163void
164eigrp_update_receive (struct eigrp *eigrp, struct ip *iph, struct eigrp_header *eigrph,
165 struct stream * s, struct eigrp_interface *ei, int size)
166{
167 struct eigrp_neighbor *nbr;
168 struct TLV_IPv4_Internal_type *tlv;
169 struct eigrp_prefix_entry *pe;
170 struct eigrp_neighbor_entry *ne;
171 u_int32_t flags;
172 u_int16_t type;
173 u_char same;
174 struct access_list *alist;
175 struct prefix_list *plist;
176 struct eigrp *e;
177 u_char graceful_restart;
178 u_char graceful_restart_final;
511ba2b8 179 struct list *nbr_prefixes = NULL;
7f57883e
DS
180
181 /* increment statistics. */
182 ei->update_in++;
183
184 /* get neighbor struct */
185 nbr = eigrp_nbr_get(ei, eigrph, iph);
186
187 /* neighbor must be valid, eigrp_nbr_get creates if none existed */
188 assert(nbr);
189
190 flags = ntohl(eigrph->flags);
191
192 if (flags & EIGRP_CR_FLAG)
193 {
194 return;
195 }
196
197 same = 0;
198 graceful_restart = 0;
199 graceful_restart_final = 0;
200 if((nbr->recv_sequence_number) == (ntohl(eigrph->sequence)))
f9e5c9ca 201 same = 1;
7f57883e
DS
202
203 nbr->recv_sequence_number = ntohl(eigrph->sequence);
204 if (IS_DEBUG_EIGRP_PACKET(0, RECV))
205 zlog_debug("Processing Update size[%u] int(%s) nbr(%s) seq [%u] flags [%0x]",
ca975a87 206 size, ifindex2ifname(nbr->ei->ifp->ifindex, VRF_DEFAULT),
7f57883e
DS
207 inet_ntoa(nbr->src),
208 nbr->recv_sequence_number, flags);
209
210
f9e5c9ca
DS
211 if((flags == (EIGRP_INIT_FLAG+EIGRP_RS_FLAG+EIGRP_EOT_FLAG)) && (!same))
212 {
213 /* Graceful restart Update received with all routes */
214
215 zlog_info("Neighbor %s (%s) is resync: peer graceful-restart",
216 inet_ntoa(nbr->src), ifindex2ifname(nbr->ei->ifp->ifindex, VRF_DEFAULT));
217
218 /* get all prefixes from neighbor from topology table */
219 nbr_prefixes = eigrp_neighbor_prefixes_lookup(eigrp, nbr);
220 graceful_restart = 1;
221 graceful_restart_final = 1;
222 }
223 else if((flags == (EIGRP_INIT_FLAG+EIGRP_RS_FLAG)) && (!same))
7f57883e 224 {
f9e5c9ca 225 /* Graceful restart Update received, routes also in next packet */
7f57883e 226
f9e5c9ca
DS
227 zlog_info("Neighbor %s (%s) is resync: peer graceful-restart",
228 inet_ntoa(nbr->src), ifindex2ifname(nbr->ei->ifp->ifindex, VRF_DEFAULT));
7f57883e 229
f9e5c9ca
DS
230 /* get all prefixes from neighbor from topology table */
231 nbr_prefixes = eigrp_neighbor_prefixes_lookup(eigrp, nbr);
232 /* save prefixes to neighbor for later use */
233 nbr->nbr_gr_prefixes = nbr_prefixes;
234 graceful_restart = 1;
235 graceful_restart_final = 0;
7f57883e 236 }
f9e5c9ca 237 else if((flags == (EIGRP_EOT_FLAG)) && (!same))
7f57883e 238 {
f9e5c9ca
DS
239 /* If there was INIT+RS Update packet before,
240 * consider this as GR EOT */
7f57883e 241
f9e5c9ca
DS
242 if(nbr->nbr_gr_prefixes != NULL)
243 {
244 /* this is final packet of GR */
245 nbr_prefixes = nbr->nbr_gr_prefixes;
246 nbr->nbr_gr_prefixes = NULL;
247
248 graceful_restart = 1;
249 graceful_restart_final = 1;
250 }
7f57883e 251
7f57883e 252 }
7f57883e 253 else if((flags == (0)) && (!same))
f9e5c9ca
DS
254 {
255 /* If there was INIT+RS Update packet before,
256 * consider this as GR not final packet */
7f57883e 257
f9e5c9ca
DS
258 if(nbr->nbr_gr_prefixes != NULL)
259 {
260 /* this is GR not final route packet */
261 nbr_prefixes = nbr->nbr_gr_prefixes;
7f57883e 262
f9e5c9ca
DS
263 graceful_restart = 1;
264 graceful_restart_final = 0;
265 }
7f57883e 266
f9e5c9ca 267 }
7f57883e 268 else if((flags & EIGRP_INIT_FLAG) && (!same))
f9e5c9ca
DS
269 { /* When in pending state, send INIT update only if it wasn't
270 already sent before (only if init_sequence is 0) */
7f57883e
DS
271 if((nbr->state == EIGRP_NEIGHBOR_PENDING) && (nbr->init_sequence_number == 0))
272 eigrp_update_send_init(nbr);
273
274 if (nbr->state == EIGRP_NEIGHBOR_UP)
275 {
276 eigrp_nbr_state_set(nbr, EIGRP_NEIGHBOR_DOWN);
277 eigrp_topology_neighbor_down(nbr->ei->eigrp,nbr);
278 nbr->recv_sequence_number = ntohl(eigrph->sequence);
279 zlog_info("Neighbor %s (%s) is down: peer restarted",
ca975a87 280 inet_ntoa(nbr->src), ifindex2ifname(nbr->ei->ifp->ifindex, VRF_DEFAULT));
7f57883e
DS
281 eigrp_nbr_state_set(nbr, EIGRP_NEIGHBOR_PENDING);
282 zlog_info("Neighbor %s (%s) is pending: new adjacency",
ca975a87 283 inet_ntoa(nbr->src), ifindex2ifname(nbr->ei->ifp->ifindex, VRF_DEFAULT));
7f57883e
DS
284 eigrp_update_send_init(nbr);
285 }
f9e5c9ca 286 }
7f57883e
DS
287
288 /*If there is topology information*/
289 while (s->endp > s->getp)
290 {
291 type = stream_getw(s);
292 if (type == EIGRP_TLV_IPv4_INT)
293 {
294 stream_set_getp(s, s->getp - sizeof(u_int16_t));
295
296 tlv = eigrp_read_ipv4_tlv(s);
297
298 /*searching if destination exists */
299 struct prefix_ipv4 *dest_addr;
300 dest_addr = prefix_ipv4_new();
301 dest_addr->prefix = tlv->destination;
302 dest_addr->prefixlen = tlv->prefix_length;
f9e5c9ca
DS
303 struct eigrp_prefix_entry *dest =
304 eigrp_topology_table_lookup_ipv4(eigrp->topology_table, dest_addr);
7f57883e
DS
305
306 /*if exists it comes to DUAL*/
307 if (dest != NULL)
308 {
f9e5c9ca
DS
309 /* remove received prefix from neighbor prefix list if in GR */
310 if(graceful_restart)
311 remove_received_prefix_gr(nbr_prefixes, dest);
7f57883e
DS
312
313 struct eigrp_fsm_action_message *msg;
314 msg = XCALLOC(MTYPE_EIGRP_FSM_MSG,
f9e5c9ca 315 sizeof(struct eigrp_fsm_action_message));
7f57883e 316 struct eigrp_neighbor_entry *entry =
f9e5c9ca 317 eigrp_prefix_entry_lookup(dest->entries, nbr);
7f57883e
DS
318
319 msg->packet_type = EIGRP_OPC_UPDATE;
320 msg->eigrp = eigrp;
321 msg->data_type = EIGRP_TLV_IPv4_INT;
322 msg->adv_router = nbr;
323 msg->data.ipv4_int_type = tlv;
324 msg->entry = entry;
325 msg->prefix = dest;
326 int event = eigrp_get_fsm_event(msg);
327 eigrp_fsm_event(msg, event);
328 }
329 else
330 {
331 /*Here comes topology information save*/
332 pe = eigrp_prefix_entry_new();
333 pe->serno = eigrp->serno;
334 pe->destination_ipv4 = dest_addr;
335 pe->af = AF_INET;
336 pe->state = EIGRP_FSM_STATE_PASSIVE;
337 pe->nt = EIGRP_TOPOLOGY_TYPE_REMOTE;
338
339 ne = eigrp_neighbor_entry_new();
340 ne->ei = ei;
341 ne->adv_router = nbr;
342 ne->reported_metric = tlv->metric;
343 ne->reported_distance =
f9e5c9ca
DS
344 eigrp_calculate_metrics(eigrp,
345 &tlv->metric);
7f57883e
DS
346 /*
347 * Filtering
348 */
349 e = eigrp_lookup();
350 /*
f9e5c9ca
DS
351 * Check if there is any access-list on interface (IN direction)
352 * and set distance to max
353 */
354 alist = ei->list[EIGRP_FILTER_IN];
7f57883e 355
f9e5c9ca 356 if (alist) {
7f57883e 357 zlog_info ("ALIST PROC IN: %s", alist->name);
f9e5c9ca
DS
358 } else {
359 zlog_info("ALIST je prazdny");
360 }
7f57883e
DS
361
362 /* Check if access-list fits */
f9e5c9ca
DS
363 if (alist && access_list_apply (alist,
364 (struct prefix *) dest_addr) == FILTER_DENY)
365 {
7f57883e 366 /* If yes, set reported metric to Max */
f9e5c9ca 367 zlog_info("PROC IN: Nastavujem metriku na MAX");
7f57883e
DS
368 ne->reported_metric.delay = EIGRP_MAX_METRIC;
369 zlog_info("PROC IN Prefix: %s", inet_ntoa(dest_addr->prefix));
f9e5c9ca
DS
370 } else {
371 zlog_info("PROC IN: NENastavujem metriku ");
372 ne->distance = eigrp_calculate_total_metrics(eigrp, ne);
373 }
374
375 plist = e->prefix[EIGRP_FILTER_IN];
376
377 if (plist) {
378 zlog_info ("PLIST PROC IN: %s", plist->name);
379 } else {
380 zlog_info("PLIST PROC IN je prazdny");
381 }
382
383 /* Check if prefix-list fits */
384 if (plist && prefix_list_apply (plist,
385 (struct prefix *) dest_addr) == PREFIX_DENY)
386 {
387 /* If yes, set reported metric to Max */
388 zlog_info("PLIST PROC IN: Nastavujem metriku na MAX");
389 ne->reported_metric.delay = EIGRP_MAX_METRIC;
390 zlog_info("PLIST PROC IN Prefix: %s", inet_ntoa(dest_addr->prefix));
391 } else {
392 zlog_info("PLIST PROC IN: NENastavujem metriku ");
393 }
394
395 /*Get access-list from current interface */
396 zlog_info("Checking access_list on interface: %s",ei->ifp->name);
397 alist = ei->list[EIGRP_FILTER_IN];
398 if (alist) {
399 zlog_info ("ALIST INT IN: %s", alist->name);
400 } else {
401 zlog_info("ALIST INT IN je prazdny");
402 }
403
404 /* Check if access-list fits */
405 if (alist && access_list_apply (alist, (struct prefix *) dest_addr) == FILTER_DENY)
406 {
407 /* If yes, set reported metric to Max */
408 zlog_info("INT IN: Nastavujem metriku na MAX");
409 ne->reported_metric.delay = EIGRP_MAX_METRIC;
410 zlog_info("INT IN Prefix: %s", inet_ntoa(dest_addr->prefix));
411 } else {
412 zlog_info("INT IN: NENastavujem metriku ");
413 }
414
415 plist = ei->prefix[EIGRP_FILTER_IN];
416
417 if (plist) {
418 zlog_info ("PLIST INT IN: %s", plist->name);
419 } else {
420 zlog_info("PLIST INT IN je prazdny");
421 }
422
423 /* Check if prefix-list fits */
424 if (plist && prefix_list_apply (plist,
425 (struct prefix *) dest_addr) == PREFIX_DENY)
426 {
427 /* If yes, set reported metric to Max */
428 zlog_info("PLIST INT IN: Nastavujem metriku na MAX");
429 ne->reported_metric.delay = EIGRP_MAX_METRIC;
430 zlog_info("PLIST INT IN Prefix: %s", inet_ntoa(dest_addr->prefix));
431 } else {
432 zlog_info("PLIST INT IN: NENastavujem metriku ");
433 }
434 /*
435 * End of filtering
436 */
437
438 ne->distance = eigrp_calculate_total_metrics(eigrp, ne);
439
440 zlog_info("<DEBUG PROC IN Distance: %x", ne->distance);
441 zlog_info("<DEBUG PROC IN Delay: %x", ne->total_metric.delay);
7f57883e
DS
442
443 pe->fdistance = pe->distance = pe->rdistance =
f9e5c9ca 444 ne->distance;
7f57883e
DS
445 ne->prefix = pe;
446 ne->flags = EIGRP_NEIGHBOR_ENTRY_SUCCESSOR_FLAG;
447
448 eigrp_prefix_entry_add(eigrp->topology_table, pe);
449 eigrp_neighbor_entry_add(pe, ne);
450 pe->distance = pe->fdistance = pe->rdistance =
451 ne->distance;
452 pe->reported_metric = ne->total_metric;
453 eigrp_topology_update_node_flags(pe);
454
455 pe->req_action |= EIGRP_FSM_NEED_UPDATE;
456 listnode_add(eigrp->topology_changes_internalIPV4, pe);
457 }
458 eigrp_IPv4_InternalTLV_free (tlv);
459 }
460 }
461
f9e5c9ca
DS
462 /* ask about prefixes not present in GR update,
463 * if this is final GR packet */
464 if(graceful_restart_final)
7f57883e 465 {
f9e5c9ca 466 eigrp_update_receive_GR_ask(eigrp, nbr, nbr_prefixes);
7f57883e
DS
467 }
468
469 /*
470 * We don't need to send separate Ack for INIT Update. INIT will be acked in EOT Update.
471 */
472 if ((nbr->state == EIGRP_NEIGHBOR_UP) && !(flags == EIGRP_INIT_FLAG))
473 {
474 eigrp_hello_send_ack(nbr);
475 }
476
477 eigrp_query_send_all(eigrp);
478 eigrp_update_send_all(eigrp, ei);
479}
480
481/*send EIGRP Update packet*/
482void
483eigrp_update_send_init (struct eigrp_neighbor *nbr)
484{
485 struct eigrp_packet *ep;
486 u_int16_t length = EIGRP_HEADER_LEN;
487
488 ep = eigrp_packet_new(nbr->ei->ifp->mtu);
489
490 /* Prepare EIGRP INIT UPDATE header */
491 if (IS_DEBUG_EIGRP_PACKET(0, RECV))
492 zlog_debug("Enqueuing Update Init Seq [%u] Ack [%u]",
493 nbr->ei->eigrp->sequence_number,
494 nbr->recv_sequence_number);
495
496 eigrp_packet_header_init(EIGRP_OPC_UPDATE, nbr->ei, ep->s, EIGRP_INIT_FLAG,
497 nbr->ei->eigrp->sequence_number,
498 nbr->recv_sequence_number);
499
500 // encode Authentication TLV, if needed
f9e5c9ca
DS
501 if((IF_DEF_PARAMS (nbr->ei->ifp)->auth_type == EIGRP_AUTH_TYPE_MD5) &&
502 (IF_DEF_PARAMS (nbr->ei->ifp)->auth_keychain != NULL))
7f57883e
DS
503 {
504 length += eigrp_add_authTLV_MD5_to_stream(ep->s,nbr->ei);
505 eigrp_make_md5_digest(nbr->ei,ep->s, EIGRP_AUTH_UPDATE_INIT_FLAG);
506 }
507
508 /* EIGRP Checksum */
509 eigrp_packet_checksum(nbr->ei, ep->s, length);
510
511 ep->length = length;
512 ep->dst.s_addr = nbr->src.s_addr;
513
514 /*This ack number we await from neighbor*/
515 nbr->init_sequence_number = nbr->ei->eigrp->sequence_number;
516 ep->sequence_number = nbr->ei->eigrp->sequence_number;
517 if (IS_DEBUG_EIGRP_PACKET(0, RECV))
518 zlog_debug("Enqueuing Update Init Len [%u] Seq [%u] Dest [%s]",
519 ep->length, ep->sequence_number, inet_ntoa(ep->dst));
520
521 /*Put packet to retransmission queue*/
522 eigrp_fifo_push_head(nbr->retrans_queue, ep);
523
524 if (nbr->retrans_queue->count == 1)
525 {
526 eigrp_send_packet_reliably(nbr);
527 }
528}
529
530void
531eigrp_update_send_EOT (struct eigrp_neighbor *nbr)
532{
533 struct eigrp_packet *ep;
f9e5c9ca 534 // struct eigrp_packet *ep_multicast;
7f57883e
DS
535 u_int16_t length = EIGRP_HEADER_LEN;
536 struct eigrp_neighbor_entry *te;
537 struct eigrp_prefix_entry *pe;
538 struct listnode *node, *node2, *nnode, *nnode2;
539 struct access_list *alist;
540 struct prefix_list *plist;
541 struct access_list *alist_i;
542 struct prefix_list *plist_i;
543 struct eigrp *e;
544 struct prefix_ipv4 *dest_addr;
545
546 ep = eigrp_packet_new(nbr->ei->ifp->mtu);
547
548 /* Prepare EIGRP EOT UPDATE header */
549 eigrp_packet_header_init(EIGRP_OPC_UPDATE, nbr->ei, ep->s, EIGRP_EOT_FLAG,
550 nbr->ei->eigrp->sequence_number,
551 nbr->recv_sequence_number);
552
553 // encode Authentication TLV, if needed
554 if((IF_DEF_PARAMS (nbr->ei->ifp)->auth_type == EIGRP_AUTH_TYPE_MD5) && (IF_DEF_PARAMS (nbr->ei->ifp)->auth_keychain != NULL))
555 {
556 length += eigrp_add_authTLV_MD5_to_stream(ep->s,nbr->ei);
557 }
558
559 for (ALL_LIST_ELEMENTS(nbr->ei->eigrp->topology_table, node, nnode, pe))
560 {
561 for (ALL_LIST_ELEMENTS(pe->entries, node2, nnode2, te))
562 {
563 if ((te->ei == nbr->ei)
564 && (te->prefix->nt == EIGRP_TOPOLOGY_TYPE_REMOTE))
565 continue;
566
567 /* Get destination address from prefix */
f9e5c9ca
DS
568 dest_addr = pe->destination_ipv4;
569
570 /*
571 * Filtering
572 */
573 //TODO: Work in progress
574 /* get list from eigrp process */
575 e = eigrp_lookup();
576 /* Get access-lists and prefix-lists from process and interface */
577 alist = e->list[EIGRP_FILTER_OUT];
578 plist = e->prefix[EIGRP_FILTER_OUT];
579 alist_i = nbr->ei->list[EIGRP_FILTER_OUT];
580 plist_i = nbr->ei->prefix[EIGRP_FILTER_OUT];
581
582 /* Check if any list fits */
583 if ((alist && access_list_apply (alist,
584 (struct prefix *) dest_addr) == FILTER_DENY)||
585 (plist && prefix_list_apply (plist,
586 (struct prefix *) dest_addr) == PREFIX_DENY)||
587 (alist_i && access_list_apply (alist_i,
588 (struct prefix *) dest_addr) == FILTER_DENY)||
589 (plist_i && prefix_list_apply (plist_i,
590 (struct prefix *) dest_addr) == PREFIX_DENY))
591 {
592 zlog_info("PROC OUT EOT: Skipping");
593 //pe->reported_metric.delay = EIGRP_MAX_METRIC;
594 zlog_info("PROC OUT EOT Prefix: %s", inet_ntoa(dest_addr->prefix));
595 continue;
596 } else {
597 zlog_info("PROC OUT EOT: NENastavujem metriku ");
598 length += eigrp_add_internalTLV_to_stream(ep->s, pe);
599 }
600 /*
601 * End of filtering
602 */
603
604 /* NULL the pointer */
605 dest_addr = NULL;
7f57883e
DS
606
607 }
608 }
609
f9e5c9ca
DS
610 if((IF_DEF_PARAMS (nbr->ei->ifp)->auth_type == EIGRP_AUTH_TYPE_MD5) &&
611 (IF_DEF_PARAMS (nbr->ei->ifp)->auth_keychain != NULL))
7f57883e
DS
612 {
613 eigrp_make_md5_digest(nbr->ei,ep->s, EIGRP_AUTH_UPDATE_FLAG);
614 }
615
616 /* EIGRP Checksum */
617 eigrp_packet_checksum(nbr->ei, ep->s, length);
618
619 ep->length = length;
620 ep->dst.s_addr = nbr->src.s_addr;
621
622 /*This ack number we await from neighbor*/
623 ep->sequence_number = nbr->ei->eigrp->sequence_number;
624
625 if (IS_DEBUG_EIGRP_PACKET(0, RECV))
626 zlog_debug("Enqueuing Update Init Len [%u] Seq [%u] Dest [%s]",
627 ep->length, ep->sequence_number, inet_ntoa(ep->dst));
628
629 /*Put packet to retransmission queue*/
630 eigrp_fifo_push_head(nbr->retrans_queue, ep);
631
632 if (nbr->retrans_queue->count == 1)
633 {
634 eigrp_send_packet_reliably(nbr);
635 }
7f57883e
DS
636}
637
638void
639eigrp_update_send (struct eigrp_interface *ei)
640{
641 struct eigrp_packet *ep;
642 struct listnode *node, *nnode;
643 struct eigrp_neighbor *nbr;
644 struct eigrp_prefix_entry *pe;
645 u_char has_tlv;
646 struct access_list *alist;
647 struct prefix_list *plist;
648 struct access_list *alist_i;
649 struct prefix_list *plist_i;
650 struct eigrp *e;
651 struct prefix_ipv4 *dest_addr;
f9e5c9ca 652
7f57883e
DS
653 u_int16_t length = EIGRP_HEADER_LEN;
654
655 ep = eigrp_packet_new(ei->ifp->mtu);
656
657 /* Prepare EIGRP INIT UPDATE header */
658 eigrp_packet_header_init(EIGRP_OPC_UPDATE, ei, ep->s, 0,
659 ei->eigrp->sequence_number, 0);
660
661 // encode Authentication TLV, if needed
f9e5c9ca
DS
662 if((IF_DEF_PARAMS (ei->ifp)->auth_type == EIGRP_AUTH_TYPE_MD5) &&
663 (IF_DEF_PARAMS (ei->ifp)->auth_keychain != NULL))
7f57883e
DS
664 {
665 length += eigrp_add_authTLV_MD5_to_stream(ep->s,ei);
666 }
667
668 has_tlv = 0;
669 for (ALL_LIST_ELEMENTS(ei->eigrp->topology_changes_internalIPV4, node, nnode, pe))
670 {
671 if(pe->req_action & EIGRP_FSM_NEED_UPDATE)
672 {
f9e5c9ca
DS
673 /* Get destination address from prefix */
674 dest_addr = pe->destination_ipv4;
675
676 /*
677 * Filtering
678 */
679 //TODO: Work in progress
680 /* get list from eigrp process */
681 e = eigrp_lookup();
682 /* Get access-lists and prefix-lists from process and interface */
683 alist = e->list[EIGRP_FILTER_OUT];
684 plist = e->prefix[EIGRP_FILTER_OUT];
685 alist_i = ei->list[EIGRP_FILTER_OUT];
686 plist_i = ei->prefix[EIGRP_FILTER_OUT];
687
688 /* Check if any list fits */
689 if ((alist && access_list_apply (alist,
690 (struct prefix *) dest_addr) == FILTER_DENY)||
691 (plist && prefix_list_apply (plist,
692 (struct prefix *) dest_addr) == PREFIX_DENY)||
693 (alist_i && access_list_apply (alist_i,
694 (struct prefix *) dest_addr) == FILTER_DENY)||
695 (plist_i && prefix_list_apply (plist_i,
696 (struct prefix *) dest_addr) == PREFIX_DENY))
697 {
698 zlog_info("PROC OUT: Skipping");
699 //pe->reported_metric.delay = EIGRP_MAX_METRIC;
700 zlog_info("PROC OUT Prefix: %s", inet_ntoa(dest_addr->prefix));
701 continue;
702 } else {
703 zlog_info("PROC OUT: NENastavujem metriku ");
704 length += eigrp_add_internalTLV_to_stream(ep->s, pe);
705 has_tlv = 1;
706 }
707 /*
708 * End of filtering
709 */
710
711 /* NULL the pointer */
712 dest_addr = NULL;
7f57883e
DS
713
714 }
715 }
716
717 if(!has_tlv)
718 {
719 eigrp_packet_free(ep);
720 return;
721 }
722
723 if((IF_DEF_PARAMS (ei->ifp)->auth_type == EIGRP_AUTH_TYPE_MD5) && (IF_DEF_PARAMS (ei->ifp)->auth_keychain != NULL))
724 {
725 eigrp_make_md5_digest(ei,ep->s, EIGRP_AUTH_UPDATE_FLAG);
726 }
727
728 /* EIGRP Checksum */
729 eigrp_packet_checksum(ei, ep->s, length);
730 ep->length = length;
731
732 ep->dst.s_addr = htonl(EIGRP_MULTICAST_ADDRESS);
733
734 /*This ack number we await from neighbor*/
735 ep->sequence_number = ei->eigrp->sequence_number;
736
737 if (IS_DEBUG_EIGRP_PACKET(0, RECV))
738 zlog_debug("Enqueuing Update length[%u] Seq [%u]",
739 length, ep->sequence_number);
740
741 for (ALL_LIST_ELEMENTS(ei->nbrs, node, nnode, nbr))
742 {
743 if (nbr->state == EIGRP_NEIGHBOR_UP)
744 {
745 /*Put packet to retransmission queue*/
746 eigrp_fifo_push_head(nbr->retrans_queue, ep);
747
748 if (nbr->retrans_queue->count == 1)
749 {
750 eigrp_send_packet_reliably(nbr);
751 }
752 }
753 }
754}
755
756void
757eigrp_update_send_all (struct eigrp *eigrp, struct eigrp_interface *exception)
758{
7f57883e
DS
759 struct eigrp_interface *iface;
760 struct listnode *node, *node2, *nnode2;
761 struct eigrp_prefix_entry *pe;
762
763 for (ALL_LIST_ELEMENTS_RO(eigrp->eiflist, node, iface))
764 {
765 if (iface != exception)
766 {
767 eigrp_update_send(iface);
768 }
769 }
770
771 for (ALL_LIST_ELEMENTS(eigrp->topology_changes_internalIPV4, node2, nnode2, pe))
772 {
773 if(pe->req_action & EIGRP_FSM_NEED_UPDATE)
774 {
775 pe->req_action &= ~EIGRP_FSM_NEED_UPDATE;
776 listnode_delete(eigrp->topology_changes_internalIPV4, pe);
777 zlog_debug("UPDATE COUNT: %d", eigrp->topology_changes_internalIPV4->count);
778 }
779 }
780}
781
782/**
783 * @fn eigrp_update_send_GR_part
784 *
785 * @param[in] nbr contains neighbor who would receive Graceful restart
786 *
787 * @return void
788 *
789 * @par
790 * Function used for sending Graceful restart Update packet
791 * and if there are multiple chunks, send only one of them.
792 * It is called from thread. Do not call it directly.
793 *
794 * Uses nbr_gr_packet_type from neighbor.
795 */
796static void
797eigrp_update_send_GR_part(struct eigrp_neighbor *nbr)
798{
f9e5c9ca
DS
799 struct eigrp_packet *ep;
800 u_int16_t length = EIGRP_HEADER_LEN;
801 struct listnode *node, *nnode;
802 struct eigrp_prefix_entry *pe;
803 struct prefix_ipv4 *dest_addr;
804 struct eigrp *e;
805 struct access_list *alist, *alist_i;
806 struct prefix_list *plist, *plist_i;
807 struct list *prefixes;
808 u_int32_t flags;
809 unsigned int send_prefixes;
810 struct TLV_IPv4_Internal_type *tlv_max;
811
812 /* get prefixes to send to neighbor */
813 prefixes = nbr->nbr_gr_prefixes_send;
814
815 send_prefixes = 0;
816 length = EIGRP_HEADER_LEN;
817
818 /* if there already were last packet chunk, we won't continue */
819 if(nbr->nbr_gr_packet_type == EIGRP_PACKET_PART_LAST)
820 return;
821
822 /* if this is first packet chunk, we need to decide,
823 * if there will be one or more chunks */
824 if(nbr->nbr_gr_packet_type == EIGRP_PACKET_PART_FIRST)
825 {
826 if(prefixes->count <= EIGRP_TLV_MAX_IPv4)
827 {
828 /* there will be only one chunk */
829 flags = EIGRP_INIT_FLAG + EIGRP_RS_FLAG + EIGRP_EOT_FLAG;
830 nbr->nbr_gr_packet_type = EIGRP_PACKET_PART_LAST;
831 }
832 else
833 {
834 /* there will be more chunks */
835 flags = EIGRP_INIT_FLAG + EIGRP_RS_FLAG;
836 nbr->nbr_gr_packet_type = EIGRP_PACKET_PART_NA;
837 }
838 }
839 else
840 {
841 /* this is not first chunk, and we need to decide,
842 * if there will be more chunks */
843 if(prefixes->count <= EIGRP_TLV_MAX_IPv4)
844 {
845 /* this is last chunk */
846 flags = EIGRP_EOT_FLAG;
847 nbr->nbr_gr_packet_type = EIGRP_PACKET_PART_LAST;
848 }
849 else
850 {
851 /* there will be more chunks */
852 flags = 0;
853 nbr->nbr_gr_packet_type = EIGRP_PACKET_PART_NA;
854 }
855 }
856
857 ep = eigrp_packet_new(nbr->ei->ifp->mtu);
858
859 /* Prepare EIGRP Graceful restart UPDATE header */
860 eigrp_packet_header_init(EIGRP_OPC_UPDATE, nbr->ei, ep->s,
861 flags,
862 nbr->ei->eigrp->sequence_number,
863 nbr->recv_sequence_number);
864
865 // encode Authentication TLV, if needed
866 if((IF_DEF_PARAMS (nbr->ei->ifp)->auth_type == EIGRP_AUTH_TYPE_MD5) &&
867 (IF_DEF_PARAMS (nbr->ei->ifp)->auth_keychain != NULL))
868 {
869 length += eigrp_add_authTLV_MD5_to_stream(ep->s,nbr->ei);
870 }
871
872 for (ALL_LIST_ELEMENTS(nbr->ei->eigrp->topology_table, node, nnode, pe))
873 {
874 /*
875 * Filtering
876 */
877 dest_addr = pe->destination_ipv4;
878 /* get list from eigrp process */
879 e = eigrp_lookup();
880 /* Get access-lists and prefix-lists from process and interface */
881 alist = e->list[EIGRP_FILTER_OUT];
882 plist = e->prefix[EIGRP_FILTER_OUT];
883 alist_i = nbr->ei->list[EIGRP_FILTER_OUT];
884 plist_i = nbr->ei->prefix[EIGRP_FILTER_OUT];
885
886 /* Check if any list fits */
887 if ((alist && access_list_apply (alist,
888 (struct prefix *) dest_addr) == FILTER_DENY)||
889 (plist && prefix_list_apply (plist,
890 (struct prefix *) dest_addr) == PREFIX_DENY)||
891 (alist_i && access_list_apply (alist_i,
892 (struct prefix *) dest_addr) == FILTER_DENY)||
893 (plist_i && prefix_list_apply (plist_i,
894 (struct prefix *) dest_addr) == PREFIX_DENY))
895 {
896 /* do not send filtered route */
897 zlog_info("Filtered prefix %s won't be sent out.",
898 inet_ntoa(dest_addr->prefix));
899 }
900 else
901 {
902 /* sending route which wasn't filtered */
903 length += eigrp_add_internalTLV_to_stream(ep->s, pe);
904 send_prefixes++;
905 }
906
907 alist = e->list[EIGRP_FILTER_IN];
908 plist = e->prefix[EIGRP_FILTER_IN];
909 alist_i = nbr->ei->list[EIGRP_FILTER_IN];
910 plist_i = nbr->ei->prefix[EIGRP_FILTER_IN];
911
912 /* Check if any list fits */
913 if ((alist && access_list_apply (alist,
914 (struct prefix *) dest_addr) == FILTER_DENY)||
915 (plist && prefix_list_apply (plist,
916 (struct prefix *) dest_addr) == PREFIX_DENY)||
917 (alist_i && access_list_apply (alist_i,
918 (struct prefix *) dest_addr) == FILTER_DENY)||
919 (plist_i && prefix_list_apply (plist_i,
920 (struct prefix *) dest_addr) == PREFIX_DENY))
921 {
922 /* do not send filtered route */
923 zlog_info("Filtered prefix %s will be removed.",
924 inet_ntoa(dest_addr->prefix));
925
926 tlv_max = eigrp_IPv4_InternalTLV_new();
927 tlv_max->type = EIGRP_TLV_IPv4_INT;
928 tlv_max->length = 28U;
929 tlv_max->metric = pe->reported_metric;
930 /* set delay to MAX */
931 tlv_max->metric.delay = EIGRP_MAX_METRIC;
932 tlv_max->destination = pe->destination_ipv4->prefix;
933 tlv_max->prefix_length = pe->destination_ipv4->prefixlen;
934
935 /* prepare message for FSM */
936 struct eigrp_fsm_action_message *fsm_msg;
937 fsm_msg = XCALLOC(MTYPE_EIGRP_FSM_MSG,
938 sizeof(struct eigrp_fsm_action_message));
939
940 struct eigrp_neighbor_entry *entry =
941 eigrp_prefix_entry_lookup(pe->entries, nbr);
942
943 fsm_msg->packet_type = EIGRP_OPC_UPDATE;
944 fsm_msg->eigrp = e;
945 fsm_msg->data_type = EIGRP_TLV_IPv4_INT;
946 fsm_msg->adv_router = nbr;
947 fsm_msg->data.ipv4_int_type = tlv_max;
948 fsm_msg->entry = entry;
949 fsm_msg->prefix = pe;
950
951 /* send message to FSM */
952 int event = eigrp_get_fsm_event(fsm_msg);
953 eigrp_fsm_event(fsm_msg, event);
954
955 /* free memory used by TLV */
956 eigrp_IPv4_InternalTLV_free (tlv_max);
957 }
958 /*
959 * End of filtering
960 */
961
962 /* NULL the pointer */
963 dest_addr = NULL;
964
965 /* delete processed prefix from list */
966 listnode_delete(prefixes, pe);
967
968 /* if there are enough prefixes, send packet */
969 if(send_prefixes >= EIGRP_TLV_MAX_IPv4)
970 break;
971 }
972
973 /* compute Auth digest */
974 if((IF_DEF_PARAMS (nbr->ei->ifp)->auth_type == EIGRP_AUTH_TYPE_MD5) &&
975 (IF_DEF_PARAMS (nbr->ei->ifp)->auth_keychain != NULL))
976 {
977 eigrp_make_md5_digest(nbr->ei,ep->s, EIGRP_AUTH_UPDATE_FLAG);
978 }
979
980 /* EIGRP Checksum */
981 eigrp_packet_checksum(nbr->ei, ep->s, length);
982
983 ep->length = length;
984 ep->dst.s_addr = nbr->src.s_addr;
985
986 /*This ack number we await from neighbor*/
987 ep->sequence_number = nbr->ei->eigrp->sequence_number;
988
989 if (IS_DEBUG_EIGRP_PACKET(0, RECV))
990 zlog_debug("Enqueuing Update Init Len [%u] Seq [%u] Dest [%s]",
991 ep->length, ep->sequence_number, inet_ntoa(ep->dst));
992
993 /*Put packet to retransmission queue*/
994 eigrp_fifo_push_head(nbr->retrans_queue, ep);
995
996 if (nbr->retrans_queue->count == 1)
997 {
998 eigrp_send_packet_reliably(nbr);
999 }
7f57883e
DS
1000}
1001
1002/**
1003 * @fn eigrp_update_send_GR_thread
1004 *
1005 * @param[in] thread contains neighbor who would receive Graceful restart
1006 *
1007 * @return int always 0
1008 *
1009 * @par
1010 * Function used for sending Graceful restart Update packet
1011 * in thread, it is prepared for multiple chunks of packet.
1012 *
1013 * Uses nbr_gr_packet_type and t_nbr_send_gr from neighbor.
1014 */
1015int
1016eigrp_update_send_GR_thread(struct thread *thread)
1017{
f9e5c9ca 1018 struct eigrp_neighbor *nbr;
7f57883e 1019
f9e5c9ca
DS
1020 /* get argument from thread */
1021 nbr = THREAD_ARG(thread);
1022 /* remove this thread pointer */
1023 nbr->t_nbr_send_gr = NULL;
7f57883e 1024
f9e5c9ca
DS
1025 /* if there is packet waiting in queue,
1026 * schedule this thread again with small delay */
1027 if(nbr->retrans_queue->count > 0)
1028 {
c94671b8
QY
1029 nbr->t_nbr_send_gr = NULL;
1030 thread_add_timer_msec(master, eigrp_update_send_GR_thread, nbr, 10,
1031 &nbr->t_nbr_send_gr);
f9e5c9ca
DS
1032 return 0;
1033 }
7f57883e 1034
f9e5c9ca
DS
1035 /* send GR EIGRP packet chunk */
1036 eigrp_update_send_GR_part(nbr);
7f57883e 1037
f9e5c9ca 1038 /* if it wasn't last chunk, schedule this thread again */
c94671b8
QY
1039 if(nbr->nbr_gr_packet_type != EIGRP_PACKET_PART_LAST) {
1040 thread_execute(master, eigrp_update_send_GR_thread, nbr, 0);
1041 nbr->t_nbr_send_gr = NULL;
1042 }
7f57883e 1043
f9e5c9ca 1044 return 0;
7f57883e
DS
1045}
1046
1047/**
1048 * @fn eigrp_update_send_GR
1049 *
1050 * @param[in] nbr Neighbor who would receive Graceful restart
1051 * @param[in] gr_type Who executed Graceful restart
1052 * @param[in] vty Virtual terminal for log output
1053 *
1054 * @return void
1055 *
1056 * @par
1057 * Function used for sending Graceful restart Update packet:
1058 * Creates Update packet with INIT, RS, EOT flags and include
1059 * all route except those filtered
1060 */
1061void
1062eigrp_update_send_GR (struct eigrp_neighbor *nbr, enum GR_type gr_type, struct vty *vty)
1063{
f9e5c9ca
DS
1064 struct eigrp_prefix_entry *pe2;
1065 struct listnode *node2, *nnode2;
1066 struct list *prefixes;
1067
1068 if(gr_type == EIGRP_GR_FILTER)
1069 {
1070 /* function was called after applying filtration */
1071 zlog_info("Neighbor %s (%s) is resync: route configuration changed",
1072 inet_ntoa(nbr->src), ifindex2ifname(nbr->ei->ifp->ifindex, VRF_DEFAULT));
1073 }
1074 else if(gr_type == EIGRP_GR_MANUAL)
1075 {
1076 /* Graceful restart was called manually */
1077 zlog_info("Neighbor %s (%s) is resync: manually cleared",
1078 inet_ntoa(nbr->src), ifindex2ifname(nbr->ei->ifp->ifindex, VRF_DEFAULT));
1079
1080 if(vty != NULL)
1081 {
1082 vty_time_print (vty, 0);
1083 vty_out (vty, "Neighbor %s (%s) is resync: manually cleared%s",
1084 inet_ntoa (nbr->src),
1085 ifindex2ifname (nbr->ei->ifp->ifindex, VRF_DEFAULT),
1086 VTY_NEWLINE);
1087 }
1088 }
1089
1090 prefixes = list_new();
1091 /* add all prefixes from topology table to list */
1092 for (ALL_LIST_ELEMENTS(nbr->ei->eigrp->topology_table, node2, nnode2, pe2))
1093 {
1094 listnode_add(prefixes, pe2);
1095 }
1096
1097 /* save prefixes to neighbor */
1098 nbr->nbr_gr_prefixes_send = prefixes;
1099 /* indicate, that this is first GR Update packet chunk */
1100 nbr->nbr_gr_packet_type = EIGRP_PACKET_PART_FIRST;
1101 /* execute packet sending in thread */
c94671b8
QY
1102 thread_execute(master, eigrp_update_send_GR_thread, nbr, 0);
1103 nbr->t_nbr_send_gr = NULL;
7f57883e
DS
1104}
1105
1106/**
1107 * @fn eigrp_update_send_interface_GR
1108 *
1109 * @param[in] ei Interface to neighbors of which the GR is sent
1110 * @param[in] gr_type Who executed Graceful restart
1111 * @param[in] vty Virtual terminal for log output
1112 *
1113 * @return void
1114 *
1115 * @par
1116 * Function used for sending Graceful restart Update packet
1117 * to all neighbors on specified interface.
1118 */
1119void
1120eigrp_update_send_interface_GR (struct eigrp_interface *ei, enum GR_type gr_type, struct vty *vty)
1121{
f9e5c9ca
DS
1122 struct listnode *node;
1123 struct eigrp_neighbor *nbr;
1124
1125 /* iterate over all neighbors on eigrp interface */
1126 for (ALL_LIST_ELEMENTS_RO(ei->nbrs, node, nbr))
1127 {
1128 /* send GR to neighbor */
1129 eigrp_update_send_GR(nbr, gr_type, vty);
1130 }
7f57883e
DS
1131}
1132
1133/**
1134 * @fn eigrp_update_send_process_GR
1135 *
1136 * @param[in] eigrp EIGRP process
1137 * @param[in] gr_type Who executed Graceful restart
1138 * @param[in] vty Virtual terminal for log output
1139 *
1140 * @return void
1141 *
1142 * @par
1143 * Function used for sending Graceful restart Update packet
1144 * to all neighbors in eigrp process.
1145 */
1146void
1147eigrp_update_send_process_GR (struct eigrp *eigrp, enum GR_type gr_type, struct vty *vty)
1148{
f9e5c9ca
DS
1149 struct listnode *node;
1150 struct eigrp_interface *ei;
7f57883e 1151
f9e5c9ca
DS
1152 /* iterate over all eigrp interfaces */
1153 for (ALL_LIST_ELEMENTS_RO (eigrp->eiflist, node, ei))
1154 {
1155 /* send GR to all neighbors on interface */
1156 eigrp_update_send_interface_GR(ei, gr_type, vty);
1157 }
1158}