]> git.proxmox.com Git - mirror_frr.git/blob - eigrpd/eigrp_update.c
eigrp: Initial Commit
[mirror_frr.git] / eigrpd / eigrp_update.c
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 */
79 static void
80 remove_received_prefix_gr (struct list *nbr_prefixes, struct eigrp_prefix_entry *recv_prefix)
81 {
82 struct listnode *node1, *node11;
83 struct eigrp_prefix_entry *prefix;
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 }
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 */
110 static void
111 eigrp_update_receive_GR_ask (struct eigrp *eigrp, struct eigrp_neighbor *nbr, struct list *nbr_prefixes)
112 {
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 }
158 }
159
160 /*
161 * EIGRP UPDATE read function
162 */
163 void
164 eigrp_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;
179 struct list *nbr_prefixes;
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)))
201 same = 1;
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]",
206 size, ifindex2ifname(nbr->ei->ifp->ifindex),
207 inet_ntoa(nbr->src),
208 nbr->recv_sequence_number, flags);
209
210
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));
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))
224 {
225 /* Graceful restart Update received, routes also in next packet */
226
227 zlog_info("Neighbor %s (%s) is resync: peer graceful-restart",
228 inet_ntoa(nbr->src), ifindex2ifname(nbr->ei->ifp->ifindex));
229
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;
236 }
237 else if((flags == (EIGRP_EOT_FLAG)) && (!same))
238 {
239 /* If there was INIT+RS Update packet before,
240 * consider this as GR EOT */
241
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 }
251
252 }
253 else if((flags == (0)) && (!same))
254 {
255 /* If there was INIT+RS Update packet before,
256 * consider this as GR not final packet */
257
258 if(nbr->nbr_gr_prefixes != NULL)
259 {
260 /* this is GR not final route packet */
261 nbr_prefixes = nbr->nbr_gr_prefixes;
262
263 graceful_restart = 1;
264 graceful_restart_final = 0;
265 }
266
267 }
268 else if((flags & EIGRP_INIT_FLAG) && (!same))
269 { /* When in pending state, send INIT update only if it wasn't
270 already sent before (only if init_sequence is 0) */
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",
280 inet_ntoa(nbr->src), ifindex2ifname(nbr->ei->ifp->ifindex));
281 eigrp_nbr_state_set(nbr, EIGRP_NEIGHBOR_PENDING);
282 zlog_info("Neighbor %s (%s) is pending: new adjacency",
283 inet_ntoa(nbr->src), ifindex2ifname(nbr->ei->ifp->ifindex));
284 eigrp_update_send_init(nbr);
285 }
286 }
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;
303 struct eigrp_prefix_entry *dest = eigrp_topology_table_lookup_ipv4(
304 eigrp->topology_table, dest_addr);
305
306 /*if exists it comes to DUAL*/
307 if (dest != NULL)
308 {
309 /* remove received prefix from neighbor prefix list if in GR */
310 if(graceful_restart)
311 remove_received_prefix_gr(nbr_prefixes, dest);
312
313 struct eigrp_fsm_action_message *msg;
314 msg = XCALLOC(MTYPE_EIGRP_FSM_MSG,
315 sizeof(struct eigrp_fsm_action_message));
316 struct eigrp_neighbor_entry *entry =
317 eigrp_prefix_entry_lookup(dest->entries, nbr);
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 =
344 eigrp_calculate_metrics(eigrp,
345 &tlv->metric);
346 /*
347 * Filtering
348 */
349 e = eigrp_lookup();
350 /*
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];
355
356 if (alist) {
357 zlog_info ("ALIST PROC IN: %s", alist->name);
358 } else {
359 zlog_info("ALIST je prazdny");
360 }
361
362 /* Check if access-list fits */
363 if (alist && access_list_apply (alist,
364 (struct prefix *) dest_addr) == FILTER_DENY)
365 {
366 /* If yes, set reported metric to Max */
367 zlog_info("PROC IN: Nastavujem metriku na MAX");
368 ne->reported_metric.delay = EIGRP_MAX_METRIC;
369 zlog_info("PROC IN Prefix: %s", inet_ntoa(dest_addr->prefix));
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) == FILTER_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) == FILTER_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);
442
443 pe->fdistance = pe->distance = pe->rdistance =
444 ne->distance;
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
462 /* ask about prefixes not present in GR update,
463 * if this is final GR packet */
464 if(graceful_restart_final)
465 {
466 eigrp_update_receive_GR_ask(eigrp, nbr, nbr_prefixes);
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*/
482 void
483 eigrp_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
501 if((IF_DEF_PARAMS (nbr->ei->ifp)->auth_type == EIGRP_AUTH_TYPE_MD5) && (IF_DEF_PARAMS (nbr->ei->ifp)->auth_keychain != NULL))
502 {
503 length += eigrp_add_authTLV_MD5_to_stream(ep->s,nbr->ei);
504 eigrp_make_md5_digest(nbr->ei,ep->s, EIGRP_AUTH_UPDATE_INIT_FLAG);
505 }
506
507 /* EIGRP Checksum */
508 eigrp_packet_checksum(nbr->ei, ep->s, length);
509
510 ep->length = length;
511 ep->dst.s_addr = nbr->src.s_addr;
512
513 /*This ack number we await from neighbor*/
514 nbr->init_sequence_number = nbr->ei->eigrp->sequence_number;
515 ep->sequence_number = nbr->ei->eigrp->sequence_number;
516 if (IS_DEBUG_EIGRP_PACKET(0, RECV))
517 zlog_debug("Enqueuing Update Init Len [%u] Seq [%u] Dest [%s]",
518 ep->length, ep->sequence_number, inet_ntoa(ep->dst));
519
520 /*Put packet to retransmission queue*/
521 eigrp_fifo_push_head(nbr->retrans_queue, ep);
522
523 if (nbr->retrans_queue->count == 1)
524 {
525 eigrp_send_packet_reliably(nbr);
526 }
527 }
528
529 void
530 eigrp_update_send_EOT (struct eigrp_neighbor *nbr)
531 {
532 struct eigrp_packet *ep;
533 // struct eigrp_packet *ep_multicast;
534 u_int16_t length = EIGRP_HEADER_LEN;
535 struct eigrp_neighbor_entry *te;
536 struct eigrp_prefix_entry *pe;
537 struct listnode *node, *node2, *nnode, *nnode2;
538 struct access_list *alist;
539 struct prefix_list *plist;
540 struct access_list *alist_i;
541 struct prefix_list *plist_i;
542 struct eigrp *e;
543 struct prefix_ipv4 *dest_addr;
544
545 ep = eigrp_packet_new(nbr->ei->ifp->mtu);
546
547 /* Prepare EIGRP EOT UPDATE header */
548 eigrp_packet_header_init(EIGRP_OPC_UPDATE, nbr->ei, ep->s, EIGRP_EOT_FLAG,
549 nbr->ei->eigrp->sequence_number,
550 nbr->recv_sequence_number);
551
552 // encode Authentication TLV, if needed
553 if((IF_DEF_PARAMS (nbr->ei->ifp)->auth_type == EIGRP_AUTH_TYPE_MD5) && (IF_DEF_PARAMS (nbr->ei->ifp)->auth_keychain != NULL))
554 {
555 length += eigrp_add_authTLV_MD5_to_stream(ep->s,nbr->ei);
556 }
557
558 for (ALL_LIST_ELEMENTS(nbr->ei->eigrp->topology_table, node, nnode, pe))
559 {
560 for (ALL_LIST_ELEMENTS(pe->entries, node2, nnode2, te))
561 {
562 if ((te->ei == nbr->ei)
563 && (te->prefix->nt == EIGRP_TOPOLOGY_TYPE_REMOTE))
564 continue;
565
566 /* Get destination address from prefix */
567 dest_addr = pe->destination_ipv4;
568
569 /*
570 * Filtering
571 */
572 //TODO: Work in progress
573 /* get list from eigrp process */
574 e = eigrp_lookup();
575 /* Get access-lists and prefix-lists from process and interface */
576 alist = e->list[EIGRP_FILTER_OUT];
577 plist = e->prefix[EIGRP_FILTER_OUT];
578 alist_i = nbr->ei->list[EIGRP_FILTER_OUT];
579 plist_i = nbr->ei->prefix[EIGRP_FILTER_OUT];
580
581 /* Check if any list fits */
582 if ((alist && access_list_apply (alist,
583 (struct prefix *) dest_addr) == FILTER_DENY)||
584 (plist && prefix_list_apply (plist,
585 (struct prefix *) dest_addr) == FILTER_DENY)||
586 (alist_i && access_list_apply (alist_i,
587 (struct prefix *) dest_addr) == FILTER_DENY)||
588 (plist_i && prefix_list_apply (plist_i,
589 (struct prefix *) dest_addr) == FILTER_DENY))
590 {
591 zlog_info("PROC OUT EOT: Skipping");
592 //pe->reported_metric.delay = EIGRP_MAX_METRIC;
593 zlog_info("PROC OUT EOT Prefix: %s", inet_ntoa(dest_addr->prefix));
594 continue;
595 } else {
596 zlog_info("PROC OUT EOT: NENastavujem metriku ");
597 length += eigrp_add_internalTLV_to_stream(ep->s, pe);
598 }
599 /*
600 * End of filtering
601 */
602
603 /* NULL the pointer */
604 dest_addr = NULL;
605
606 }
607 }
608
609 if((IF_DEF_PARAMS (nbr->ei->ifp)->auth_type == EIGRP_AUTH_TYPE_MD5) && (IF_DEF_PARAMS (nbr->ei->ifp)->auth_keychain != NULL))
610 {
611 eigrp_make_md5_digest(nbr->ei,ep->s, EIGRP_AUTH_UPDATE_FLAG);
612 }
613
614 /* EIGRP Checksum */
615 eigrp_packet_checksum(nbr->ei, ep->s, length);
616
617 ep->length = length;
618 ep->dst.s_addr = nbr->src.s_addr;
619
620 /*This ack number we await from neighbor*/
621 ep->sequence_number = nbr->ei->eigrp->sequence_number;
622
623 if (IS_DEBUG_EIGRP_PACKET(0, RECV))
624 zlog_debug("Enqueuing Update Init Len [%u] Seq [%u] Dest [%s]",
625 ep->length, ep->sequence_number, inet_ntoa(ep->dst));
626
627 /*Put packet to retransmission queue*/
628 eigrp_fifo_push_head(nbr->retrans_queue, ep);
629
630 if (nbr->retrans_queue->count == 1)
631 {
632 eigrp_send_packet_reliably(nbr);
633 }
634
635 }
636
637 void
638 eigrp_update_send (struct eigrp_interface *ei)
639 {
640 struct eigrp_packet *ep;
641 struct listnode *node, *nnode;
642 struct eigrp_neighbor *nbr;
643 struct eigrp_prefix_entry *pe;
644 u_char has_tlv;
645 struct access_list *alist;
646 struct prefix_list *plist;
647 struct access_list *alist_i;
648 struct prefix_list *plist_i;
649 struct eigrp *e;
650 struct prefix_ipv4 *dest_addr;
651
652 u_int16_t length = EIGRP_HEADER_LEN;
653
654 ep = eigrp_packet_new(ei->ifp->mtu);
655
656 /* Prepare EIGRP INIT UPDATE header */
657 eigrp_packet_header_init(EIGRP_OPC_UPDATE, ei, ep->s, 0,
658 ei->eigrp->sequence_number, 0);
659
660 // encode Authentication TLV, if needed
661 if((IF_DEF_PARAMS (ei->ifp)->auth_type == EIGRP_AUTH_TYPE_MD5) && (IF_DEF_PARAMS (ei->ifp)->auth_keychain != NULL))
662 {
663 length += eigrp_add_authTLV_MD5_to_stream(ep->s,ei);
664 }
665
666 has_tlv = 0;
667 for (ALL_LIST_ELEMENTS(ei->eigrp->topology_changes_internalIPV4, node, nnode, pe))
668 {
669 if(pe->req_action & EIGRP_FSM_NEED_UPDATE)
670 {
671 /* Get destination address from prefix */
672 dest_addr = pe->destination_ipv4;
673
674 /*
675 * Filtering
676 */
677 //TODO: Work in progress
678 /* get list from eigrp process */
679 e = eigrp_lookup();
680 /* Get access-lists and prefix-lists from process and interface */
681 alist = e->list[EIGRP_FILTER_OUT];
682 plist = e->prefix[EIGRP_FILTER_OUT];
683 alist_i = ei->list[EIGRP_FILTER_OUT];
684 plist_i = ei->prefix[EIGRP_FILTER_OUT];
685
686 /* Check if any list fits */
687 if ((alist && access_list_apply (alist,
688 (struct prefix *) dest_addr) == FILTER_DENY)||
689 (plist && prefix_list_apply (plist,
690 (struct prefix *) dest_addr) == FILTER_DENY)||
691 (alist_i && access_list_apply (alist_i,
692 (struct prefix *) dest_addr) == FILTER_DENY)||
693 (plist_i && prefix_list_apply (plist_i,
694 (struct prefix *) dest_addr) == FILTER_DENY))
695 {
696 zlog_info("PROC OUT: Skipping");
697 //pe->reported_metric.delay = EIGRP_MAX_METRIC;
698 zlog_info("PROC OUT Prefix: %s", inet_ntoa(dest_addr->prefix));
699 continue;
700 } else {
701 zlog_info("PROC OUT: NENastavujem metriku ");
702 length += eigrp_add_internalTLV_to_stream(ep->s, pe);
703 has_tlv = 1;
704 }
705 /*
706 * End of filtering
707 */
708
709 /* NULL the pointer */
710 dest_addr = NULL;
711
712 }
713 }
714
715 if(!has_tlv)
716 {
717 eigrp_packet_free(ep);
718 return;
719 }
720
721 if((IF_DEF_PARAMS (ei->ifp)->auth_type == EIGRP_AUTH_TYPE_MD5) && (IF_DEF_PARAMS (ei->ifp)->auth_keychain != NULL))
722 {
723 eigrp_make_md5_digest(ei,ep->s, EIGRP_AUTH_UPDATE_FLAG);
724 }
725
726 /* EIGRP Checksum */
727 eigrp_packet_checksum(ei, ep->s, length);
728 ep->length = length;
729
730 ep->dst.s_addr = htonl(EIGRP_MULTICAST_ADDRESS);
731
732 /*This ack number we await from neighbor*/
733 ep->sequence_number = ei->eigrp->sequence_number;
734
735 if (IS_DEBUG_EIGRP_PACKET(0, RECV))
736 zlog_debug("Enqueuing Update length[%u] Seq [%u]",
737 length, ep->sequence_number);
738
739 for (ALL_LIST_ELEMENTS(ei->nbrs, node, nnode, nbr))
740 {
741 if (nbr->state == EIGRP_NEIGHBOR_UP)
742 {
743 /*Put packet to retransmission queue*/
744 eigrp_fifo_push_head(nbr->retrans_queue, ep);
745
746 if (nbr->retrans_queue->count == 1)
747 {
748 eigrp_send_packet_reliably(nbr);
749 }
750 }
751 }
752 }
753
754 void
755 eigrp_update_send_all (struct eigrp *eigrp, struct eigrp_interface *exception)
756 {
757
758 struct eigrp_interface *iface;
759 struct listnode *node, *node2, *nnode2;
760 struct eigrp_prefix_entry *pe;
761
762 for (ALL_LIST_ELEMENTS_RO(eigrp->eiflist, node, iface))
763 {
764 if (iface != exception)
765 {
766 eigrp_update_send(iface);
767 }
768 }
769
770 for (ALL_LIST_ELEMENTS(eigrp->topology_changes_internalIPV4, node2, nnode2, pe))
771 {
772 if(pe->req_action & EIGRP_FSM_NEED_UPDATE)
773 {
774 pe->req_action &= ~EIGRP_FSM_NEED_UPDATE;
775 listnode_delete(eigrp->topology_changes_internalIPV4, pe);
776 zlog_debug("UPDATE COUNT: %d", eigrp->topology_changes_internalIPV4->count);
777 }
778 }
779 }
780
781 /**
782 * @fn eigrp_update_send_GR_part
783 *
784 * @param[in] nbr contains neighbor who would receive Graceful restart
785 *
786 * @return void
787 *
788 * @par
789 * Function used for sending Graceful restart Update packet
790 * and if there are multiple chunks, send only one of them.
791 * It is called from thread. Do not call it directly.
792 *
793 * Uses nbr_gr_packet_type from neighbor.
794 */
795 static void
796 eigrp_update_send_GR_part(struct eigrp_neighbor *nbr)
797 {
798 struct eigrp_packet *ep;
799 u_int16_t length = EIGRP_HEADER_LEN;
800 struct listnode *node, *nnode;
801 struct eigrp_prefix_entry *pe;
802 struct prefix_ipv4 *dest_addr;
803 struct eigrp *e;
804 struct access_list *alist, *alist_i;
805 struct prefix_list *plist, *plist_i;
806 struct list *prefixes;
807 u_int32_t flags;
808 unsigned int send_prefixes;
809 struct TLV_IPv4_Internal_type *tlv_max;
810
811 /* get prefixes to send to neighbor */
812 prefixes = nbr->nbr_gr_prefixes_send;
813
814 send_prefixes = 0;
815 length = EIGRP_HEADER_LEN;
816
817 /* if there already were last packet chunk, we won't continue */
818 if(nbr->nbr_gr_packet_type == EIGRP_PACKET_PART_LAST)
819 return;
820
821 /* if this is first packet chunk, we need to decide,
822 * if there will be one or more chunks */
823 if(nbr->nbr_gr_packet_type == EIGRP_PACKET_PART_FIRST)
824 {
825 if(prefixes->count <= EIGRP_TLV_MAX_IPv4)
826 {
827 /* there will be only one chunk */
828 flags = EIGRP_INIT_FLAG + EIGRP_RS_FLAG + EIGRP_EOT_FLAG;
829 nbr->nbr_gr_packet_type = EIGRP_PACKET_PART_LAST;
830 }
831 else
832 {
833 /* there will be more chunks */
834 flags = EIGRP_INIT_FLAG + EIGRP_RS_FLAG;
835 nbr->nbr_gr_packet_type = EIGRP_PACKET_PART_NA;
836 }
837 }
838 else
839 {
840 /* this is not first chunk, and we need to decide,
841 * if there will be more chunks */
842 if(prefixes->count <= EIGRP_TLV_MAX_IPv4)
843 {
844 /* this is last chunk */
845 flags = EIGRP_EOT_FLAG;
846 nbr->nbr_gr_packet_type = EIGRP_PACKET_PART_LAST;
847 }
848 else
849 {
850 /* there will be more chunks */
851 flags = 0;
852 nbr->nbr_gr_packet_type = EIGRP_PACKET_PART_NA;
853 }
854 }
855
856 ep = eigrp_packet_new(nbr->ei->ifp->mtu);
857
858 /* Prepare EIGRP Graceful restart UPDATE header */
859 eigrp_packet_header_init(EIGRP_OPC_UPDATE, nbr->ei, ep->s,
860 flags,
861 nbr->ei->eigrp->sequence_number,
862 nbr->recv_sequence_number);
863
864 // encode Authentication TLV, if needed
865 if((IF_DEF_PARAMS (nbr->ei->ifp)->auth_type == EIGRP_AUTH_TYPE_MD5) && (IF_DEF_PARAMS (nbr->ei->ifp)->auth_keychain != NULL))
866 {
867 length += eigrp_add_authTLV_MD5_to_stream(ep->s,nbr->ei);
868 }
869
870 for (ALL_LIST_ELEMENTS(nbr->ei->eigrp->topology_table, node, nnode, pe))
871 {
872
873 /*
874 * Filtering
875 */
876 dest_addr = pe->destination_ipv4;
877 /* get list from eigrp process */
878 e = eigrp_lookup();
879 /* Get access-lists and prefix-lists from process and interface */
880 alist = e->list[EIGRP_FILTER_OUT];
881 plist = e->prefix[EIGRP_FILTER_OUT];
882 alist_i = nbr->ei->list[EIGRP_FILTER_OUT];
883 plist_i = nbr->ei->prefix[EIGRP_FILTER_OUT];
884
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) == FILTER_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) == FILTER_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
908
909 alist = e->list[EIGRP_FILTER_IN];
910 plist = e->prefix[EIGRP_FILTER_IN];
911 alist_i = nbr->ei->list[EIGRP_FILTER_IN];
912 plist_i = nbr->ei->prefix[EIGRP_FILTER_IN];
913
914
915 /* Check if any list fits */
916 if ((alist && access_list_apply (alist,
917 (struct prefix *) dest_addr) == FILTER_DENY)||
918 (plist && prefix_list_apply (plist,
919 (struct prefix *) dest_addr) == FILTER_DENY)||
920 (alist_i && access_list_apply (alist_i,
921 (struct prefix *) dest_addr) == FILTER_DENY)||
922 (plist_i && prefix_list_apply (plist_i,
923 (struct prefix *) dest_addr) == FILTER_DENY))
924 {
925 /* do not send filtered route */
926 zlog_info("Filtered prefix %s will be removed.",
927 inet_ntoa(dest_addr->prefix));
928
929 tlv_max = eigrp_IPv4_InternalTLV_new();
930 tlv_max->type = EIGRP_TLV_IPv4_INT;
931 tlv_max->length = 28U;
932 tlv_max->metric = pe->reported_metric;
933 /* set delay to MAX */
934 tlv_max->metric.delay = EIGRP_MAX_METRIC;
935 tlv_max->destination = pe->destination_ipv4->prefix;
936 tlv_max->prefix_length = pe->destination_ipv4->prefixlen;
937
938
939 /* prepare message for FSM */
940 struct eigrp_fsm_action_message *fsm_msg;
941 fsm_msg = XCALLOC(MTYPE_EIGRP_FSM_MSG,
942 sizeof(struct eigrp_fsm_action_message));
943
944 struct eigrp_neighbor_entry *entry =
945 eigrp_prefix_entry_lookup(pe->entries, nbr);
946
947 fsm_msg->packet_type = EIGRP_OPC_UPDATE;
948 fsm_msg->eigrp = e;
949 fsm_msg->data_type = EIGRP_TLV_IPv4_INT;
950 fsm_msg->adv_router = nbr;
951 fsm_msg->data.ipv4_int_type = tlv_max;
952 fsm_msg->entry = entry;
953 fsm_msg->prefix = pe;
954
955 /* send message to FSM */
956 int event = eigrp_get_fsm_event(fsm_msg);
957 eigrp_fsm_event(fsm_msg, event);
958
959 /* free memory used by TLV */
960 eigrp_IPv4_InternalTLV_free (tlv_max);
961 }
962 /*
963 * End of filtering
964 */
965
966 /* NULL the pointer */
967 dest_addr = NULL;
968
969 /* delete processed prefix from list */
970 listnode_delete(prefixes, pe);
971
972 /* if there are enough prefixes, send packet */
973 if(send_prefixes >= EIGRP_TLV_MAX_IPv4)
974 break;
975 }
976
977 /* compute Auth digest */
978 if((IF_DEF_PARAMS (nbr->ei->ifp)->auth_type == EIGRP_AUTH_TYPE_MD5) && (IF_DEF_PARAMS (nbr->ei->ifp)->auth_keychain != NULL))
979 {
980 eigrp_make_md5_digest(nbr->ei,ep->s, EIGRP_AUTH_UPDATE_FLAG);
981 }
982
983 /* EIGRP Checksum */
984 eigrp_packet_checksum(nbr->ei, ep->s, length);
985
986 ep->length = length;
987 ep->dst.s_addr = nbr->src.s_addr;
988
989 /*This ack number we await from neighbor*/
990 ep->sequence_number = nbr->ei->eigrp->sequence_number;
991
992 if (IS_DEBUG_EIGRP_PACKET(0, RECV))
993 zlog_debug("Enqueuing Update Init Len [%u] Seq [%u] Dest [%s]",
994 ep->length, ep->sequence_number, inet_ntoa(ep->dst));
995
996
997 /*Put packet to retransmission queue*/
998 eigrp_fifo_push_head(nbr->retrans_queue, ep);
999
1000 if (nbr->retrans_queue->count == 1)
1001 {
1002 eigrp_send_packet_reliably(nbr);
1003 }
1004 }
1005
1006 /**
1007 * @fn eigrp_update_send_GR_thread
1008 *
1009 * @param[in] thread contains neighbor who would receive Graceful restart
1010 *
1011 * @return int always 0
1012 *
1013 * @par
1014 * Function used for sending Graceful restart Update packet
1015 * in thread, it is prepared for multiple chunks of packet.
1016 *
1017 * Uses nbr_gr_packet_type and t_nbr_send_gr from neighbor.
1018 */
1019 int
1020 eigrp_update_send_GR_thread(struct thread *thread)
1021 {
1022 struct eigrp_neighbor *nbr;
1023
1024 /* get argument from thread */
1025 nbr = THREAD_ARG(thread);
1026 /* remove this thread pointer */
1027 nbr->t_nbr_send_gr = NULL;
1028
1029 /* if there is packet waiting in queue,
1030 * schedule this thread again with small delay */
1031 if(nbr->retrans_queue->count > 0)
1032 {
1033 nbr->t_nbr_send_gr = thread_add_timer_msec(master, eigrp_update_send_GR_thread, nbr, 10);
1034 return 0;
1035 }
1036
1037 /* send GR EIGRP packet chunk */
1038 eigrp_update_send_GR_part(nbr);
1039
1040 /* if it wasn't last chunk, schedule this thread again */
1041 if(nbr->nbr_gr_packet_type != EIGRP_PACKET_PART_LAST)
1042 nbr->t_nbr_send_gr = thread_execute(master, eigrp_update_send_GR_thread, nbr, 0);
1043
1044 return 0;
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 */
1061 void
1062 eigrp_update_send_GR (struct eigrp_neighbor *nbr, enum GR_type gr_type, struct vty *vty)
1063 {
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));
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));
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),
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 */
1102 nbr->t_nbr_send_gr = thread_execute(master, eigrp_update_send_GR_thread, nbr, 0);
1103 }
1104
1105 /**
1106 * @fn eigrp_update_send_interface_GR
1107 *
1108 * @param[in] ei Interface to neighbors of which the GR is sent
1109 * @param[in] gr_type Who executed Graceful restart
1110 * @param[in] vty Virtual terminal for log output
1111 *
1112 * @return void
1113 *
1114 * @par
1115 * Function used for sending Graceful restart Update packet
1116 * to all neighbors on specified interface.
1117 */
1118 void
1119 eigrp_update_send_interface_GR (struct eigrp_interface *ei, enum GR_type gr_type, struct vty *vty)
1120 {
1121 struct listnode *node;
1122 struct eigrp_neighbor *nbr;
1123
1124 /* iterate over all neighbors on eigrp interface */
1125 for (ALL_LIST_ELEMENTS_RO(ei->nbrs, node, nbr))
1126 {
1127 /* send GR to neighbor */
1128 eigrp_update_send_GR(nbr, gr_type, vty);
1129 }
1130 }
1131
1132 /**
1133 * @fn eigrp_update_send_process_GR
1134 *
1135 * @param[in] eigrp EIGRP process
1136 * @param[in] gr_type Who executed Graceful restart
1137 * @param[in] vty Virtual terminal for log output
1138 *
1139 * @return void
1140 *
1141 * @par
1142 * Function used for sending Graceful restart Update packet
1143 * to all neighbors in eigrp process.
1144 */
1145 void
1146 eigrp_update_send_process_GR (struct eigrp *eigrp, enum GR_type gr_type, struct vty *vty)
1147 {
1148 struct listnode *node;
1149 struct eigrp_interface *ei;
1150
1151 /* iterate over all eigrp interfaces */
1152 for (ALL_LIST_ELEMENTS_RO (eigrp->eiflist, node, ei))
1153 {
1154 /* send GR to all neighbors on interface */
1155 eigrp_update_send_interface_GR(ei, gr_type, vty);
1156 }
1157 }
1158
1159