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