]> git.proxmox.com Git - mirror_frr.git/blob - eigrpd/eigrp_update.c
*: make consistent & update GPLv2 file headers
[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 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
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 */
78 static void
79 remove_received_prefix_gr (struct list *nbr_prefixes, struct eigrp_prefix_entry *recv_prefix)
80 {
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 }
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 */
109 static void
110 eigrp_update_receive_GR_ask (struct eigrp *eigrp, struct eigrp_neighbor *nbr, struct list *nbr_prefixes)
111 {
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 }
157 }
158
159 /*
160 * EIGRP UPDATE read function
161 */
162 void
163 eigrp_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;
178 struct list *nbr_prefixes = NULL;
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)))
200 same = 1;
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]",
205 size, ifindex2ifname(nbr->ei->ifp->ifindex, VRF_DEFAULT),
206 inet_ntoa(nbr->src),
207 nbr->recv_sequence_number, flags);
208
209
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))
223 {
224 /* Graceful restart Update received, routes also in next packet */
225
226 zlog_info("Neighbor %s (%s) is resync: peer graceful-restart",
227 inet_ntoa(nbr->src), ifindex2ifname(nbr->ei->ifp->ifindex, VRF_DEFAULT));
228
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;
235 }
236 else if((flags == (EIGRP_EOT_FLAG)) && (!same))
237 {
238 /* If there was INIT+RS Update packet before,
239 * consider this as GR EOT */
240
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 }
250
251 }
252 else if((flags == (0)) && (!same))
253 {
254 /* If there was INIT+RS Update packet before,
255 * consider this as GR not final packet */
256
257 if(nbr->nbr_gr_prefixes != NULL)
258 {
259 /* this is GR not final route packet */
260 nbr_prefixes = nbr->nbr_gr_prefixes;
261
262 graceful_restart = 1;
263 graceful_restart_final = 0;
264 }
265
266 }
267 else if((flags & EIGRP_INIT_FLAG) && (!same))
268 { /* When in pending state, send INIT update only if it wasn't
269 already sent before (only if init_sequence is 0) */
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",
279 inet_ntoa(nbr->src), ifindex2ifname(nbr->ei->ifp->ifindex, VRF_DEFAULT));
280 eigrp_nbr_state_set(nbr, EIGRP_NEIGHBOR_PENDING);
281 zlog_info("Neighbor %s (%s) is pending: new adjacency",
282 inet_ntoa(nbr->src), ifindex2ifname(nbr->ei->ifp->ifindex, VRF_DEFAULT));
283 eigrp_update_send_init(nbr);
284 }
285 }
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 {
293 stream_set_getp(s, s->getp - sizeof(u_int16_t));
294
295 tlv = eigrp_read_ipv4_tlv(s);
296
297 /*searching if destination exists */
298 struct prefix_ipv4 *dest_addr;
299 dest_addr = prefix_ipv4_new();
300 dest_addr->prefix = tlv->destination;
301 dest_addr->prefixlen = tlv->prefix_length;
302 struct eigrp_prefix_entry *dest =
303 eigrp_topology_table_lookup_ipv4(eigrp->topology_table, dest_addr);
304
305 /*if exists it comes to DUAL*/
306 if (dest != NULL)
307 {
308 /* remove received prefix from neighbor prefix list if in GR */
309 if(graceful_restart)
310 remove_received_prefix_gr(nbr_prefixes, dest);
311
312 struct eigrp_fsm_action_message *msg;
313 msg = XCALLOC(MTYPE_EIGRP_FSM_MSG,
314 sizeof(struct eigrp_fsm_action_message));
315 struct eigrp_neighbor_entry *entry =
316 eigrp_prefix_entry_lookup(dest->entries, nbr);
317
318 msg->packet_type = EIGRP_OPC_UPDATE;
319 msg->eigrp = eigrp;
320 msg->data_type = EIGRP_TLV_IPv4_INT;
321 msg->adv_router = nbr;
322 msg->data.ipv4_int_type = tlv;
323 msg->entry = entry;
324 msg->prefix = dest;
325 int event = eigrp_get_fsm_event(msg);
326 eigrp_fsm_event(msg, event);
327 }
328 else
329 {
330 /*Here comes topology information save*/
331 pe = eigrp_prefix_entry_new();
332 pe->serno = eigrp->serno;
333 pe->destination_ipv4 = dest_addr;
334 pe->af = AF_INET;
335 pe->state = EIGRP_FSM_STATE_PASSIVE;
336 pe->nt = EIGRP_TOPOLOGY_TYPE_REMOTE;
337
338 ne = eigrp_neighbor_entry_new();
339 ne->ei = ei;
340 ne->adv_router = nbr;
341 ne->reported_metric = tlv->metric;
342 ne->reported_distance =
343 eigrp_calculate_metrics(eigrp,
344 &tlv->metric);
345 /*
346 * Filtering
347 */
348 e = eigrp_lookup();
349 /*
350 * Check if there is any access-list on interface (IN direction)
351 * and set distance to max
352 */
353 alist = ei->list[EIGRP_FILTER_IN];
354
355 if (alist) {
356 zlog_info ("ALIST PROC IN: %s", alist->name);
357 } else {
358 zlog_info("ALIST je prazdny");
359 }
360
361 /* Check if access-list fits */
362 if (alist && access_list_apply (alist,
363 (struct prefix *) dest_addr) == FILTER_DENY)
364 {
365 /* If yes, set reported metric to Max */
366 zlog_info("PROC IN: Nastavujem metriku na MAX");
367 ne->reported_metric.delay = EIGRP_MAX_METRIC;
368 zlog_info("PROC IN Prefix: %s", inet_ntoa(dest_addr->prefix));
369 } else {
370 zlog_info("PROC IN: NENastavujem metriku ");
371 ne->distance = eigrp_calculate_total_metrics(eigrp, ne);
372 }
373
374 plist = e->prefix[EIGRP_FILTER_IN];
375
376 if (plist) {
377 zlog_info ("PLIST PROC IN: %s", plist->name);
378 } else {
379 zlog_info("PLIST PROC IN je prazdny");
380 }
381
382 /* Check if prefix-list fits */
383 if (plist && prefix_list_apply (plist,
384 (struct prefix *) dest_addr) == PREFIX_DENY)
385 {
386 /* If yes, set reported metric to Max */
387 zlog_info("PLIST PROC IN: Nastavujem metriku na MAX");
388 ne->reported_metric.delay = EIGRP_MAX_METRIC;
389 zlog_info("PLIST PROC IN Prefix: %s", inet_ntoa(dest_addr->prefix));
390 } else {
391 zlog_info("PLIST PROC IN: NENastavujem metriku ");
392 }
393
394 /*Get access-list from current interface */
395 zlog_info("Checking access_list on interface: %s",ei->ifp->name);
396 alist = ei->list[EIGRP_FILTER_IN];
397 if (alist) {
398 zlog_info ("ALIST INT IN: %s", alist->name);
399 } else {
400 zlog_info("ALIST INT IN je prazdny");
401 }
402
403 /* Check if access-list fits */
404 if (alist && access_list_apply (alist, (struct prefix *) dest_addr) == FILTER_DENY)
405 {
406 /* If yes, set reported metric to Max */
407 zlog_info("INT IN: Nastavujem metriku na MAX");
408 ne->reported_metric.delay = EIGRP_MAX_METRIC;
409 zlog_info("INT IN Prefix: %s", inet_ntoa(dest_addr->prefix));
410 } else {
411 zlog_info("INT IN: NENastavujem metriku ");
412 }
413
414 plist = ei->prefix[EIGRP_FILTER_IN];
415
416 if (plist) {
417 zlog_info ("PLIST INT IN: %s", plist->name);
418 } else {
419 zlog_info("PLIST INT IN je prazdny");
420 }
421
422 /* Check if prefix-list fits */
423 if (plist && prefix_list_apply (plist,
424 (struct prefix *) dest_addr) == PREFIX_DENY)
425 {
426 /* If yes, set reported metric to Max */
427 zlog_info("PLIST INT IN: Nastavujem metriku na MAX");
428 ne->reported_metric.delay = EIGRP_MAX_METRIC;
429 zlog_info("PLIST INT IN Prefix: %s", inet_ntoa(dest_addr->prefix));
430 } else {
431 zlog_info("PLIST INT IN: NENastavujem metriku ");
432 }
433 /*
434 * End of filtering
435 */
436
437 ne->distance = eigrp_calculate_total_metrics(eigrp, ne);
438
439 zlog_info("<DEBUG PROC IN Distance: %x", ne->distance);
440 zlog_info("<DEBUG PROC IN Delay: %x", ne->total_metric.delay);
441
442 pe->fdistance = pe->distance = pe->rdistance =
443 ne->distance;
444 ne->prefix = pe;
445 ne->flags = EIGRP_NEIGHBOR_ENTRY_SUCCESSOR_FLAG;
446
447 eigrp_prefix_entry_add(eigrp->topology_table, pe);
448 eigrp_neighbor_entry_add(pe, ne);
449 pe->distance = pe->fdistance = pe->rdistance =
450 ne->distance;
451 pe->reported_metric = ne->total_metric;
452 eigrp_topology_update_node_flags(pe);
453
454 pe->req_action |= EIGRP_FSM_NEED_UPDATE;
455 listnode_add(eigrp->topology_changes_internalIPV4, pe);
456 }
457 eigrp_IPv4_InternalTLV_free (tlv);
458 }
459 }
460
461 /* ask about prefixes not present in GR update,
462 * if this is final GR packet */
463 if(graceful_restart_final)
464 {
465 eigrp_update_receive_GR_ask(eigrp, nbr, nbr_prefixes);
466 }
467
468 /*
469 * We don't need to send separate Ack for INIT Update. INIT will be acked in EOT Update.
470 */
471 if ((nbr->state == EIGRP_NEIGHBOR_UP) && !(flags == EIGRP_INIT_FLAG))
472 {
473 eigrp_hello_send_ack(nbr);
474 }
475
476 eigrp_query_send_all(eigrp);
477 eigrp_update_send_all(eigrp, ei);
478 }
479
480 /*send EIGRP Update packet*/
481 void
482 eigrp_update_send_init (struct eigrp_neighbor *nbr)
483 {
484 struct eigrp_packet *ep;
485 u_int16_t length = EIGRP_HEADER_LEN;
486
487 ep = eigrp_packet_new(nbr->ei->ifp->mtu);
488
489 /* Prepare EIGRP INIT UPDATE header */
490 if (IS_DEBUG_EIGRP_PACKET(0, RECV))
491 zlog_debug("Enqueuing Update Init Seq [%u] Ack [%u]",
492 nbr->ei->eigrp->sequence_number,
493 nbr->recv_sequence_number);
494
495 eigrp_packet_header_init(EIGRP_OPC_UPDATE, nbr->ei, ep->s, EIGRP_INIT_FLAG,
496 nbr->ei->eigrp->sequence_number,
497 nbr->recv_sequence_number);
498
499 // encode Authentication TLV, if needed
500 if((IF_DEF_PARAMS (nbr->ei->ifp)->auth_type == EIGRP_AUTH_TYPE_MD5) &&
501 (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) == PREFIX_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) == PREFIX_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) &&
610 (IF_DEF_PARAMS (nbr->ei->ifp)->auth_keychain != NULL))
611 {
612 eigrp_make_md5_digest(nbr->ei,ep->s, EIGRP_AUTH_UPDATE_FLAG);
613 }
614
615 /* EIGRP Checksum */
616 eigrp_packet_checksum(nbr->ei, ep->s, length);
617
618 ep->length = length;
619 ep->dst.s_addr = nbr->src.s_addr;
620
621 /*This ack number we await from neighbor*/
622 ep->sequence_number = nbr->ei->eigrp->sequence_number;
623
624 if (IS_DEBUG_EIGRP_PACKET(0, RECV))
625 zlog_debug("Enqueuing Update Init Len [%u] Seq [%u] Dest [%s]",
626 ep->length, ep->sequence_number, inet_ntoa(ep->dst));
627
628 /*Put packet to retransmission queue*/
629 eigrp_fifo_push_head(nbr->retrans_queue, ep);
630
631 if (nbr->retrans_queue->count == 1)
632 {
633 eigrp_send_packet_reliably(nbr);
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) &&
662 (IF_DEF_PARAMS (ei->ifp)->auth_keychain != NULL))
663 {
664 length += eigrp_add_authTLV_MD5_to_stream(ep->s,ei);
665 }
666
667 has_tlv = 0;
668 for (ALL_LIST_ELEMENTS(ei->eigrp->topology_changes_internalIPV4, node, nnode, pe))
669 {
670 if(pe->req_action & EIGRP_FSM_NEED_UPDATE)
671 {
672 /* Get destination address from prefix */
673 dest_addr = pe->destination_ipv4;
674
675 /*
676 * Filtering
677 */
678 //TODO: Work in progress
679 /* get list from eigrp process */
680 e = eigrp_lookup();
681 /* Get access-lists and prefix-lists from process and interface */
682 alist = e->list[EIGRP_FILTER_OUT];
683 plist = e->prefix[EIGRP_FILTER_OUT];
684 alist_i = ei->list[EIGRP_FILTER_OUT];
685 plist_i = ei->prefix[EIGRP_FILTER_OUT];
686
687 /* Check if any list fits */
688 if ((alist && access_list_apply (alist,
689 (struct prefix *) dest_addr) == FILTER_DENY)||
690 (plist && prefix_list_apply (plist,
691 (struct prefix *) dest_addr) == PREFIX_DENY)||
692 (alist_i && access_list_apply (alist_i,
693 (struct prefix *) dest_addr) == FILTER_DENY)||
694 (plist_i && prefix_list_apply (plist_i,
695 (struct prefix *) dest_addr) == PREFIX_DENY))
696 {
697 zlog_info("PROC OUT: Skipping");
698 //pe->reported_metric.delay = EIGRP_MAX_METRIC;
699 zlog_info("PROC OUT Prefix: %s", inet_ntoa(dest_addr->prefix));
700 continue;
701 } else {
702 zlog_info("PROC OUT: NENastavujem metriku ");
703 length += eigrp_add_internalTLV_to_stream(ep->s, pe);
704 has_tlv = 1;
705 }
706 /*
707 * End of filtering
708 */
709
710 /* NULL the pointer */
711 dest_addr = NULL;
712
713 }
714 }
715
716 if(!has_tlv)
717 {
718 eigrp_packet_free(ep);
719 return;
720 }
721
722 if((IF_DEF_PARAMS (ei->ifp)->auth_type == EIGRP_AUTH_TYPE_MD5) && (IF_DEF_PARAMS (ei->ifp)->auth_keychain != NULL))
723 {
724 eigrp_make_md5_digest(ei,ep->s, EIGRP_AUTH_UPDATE_FLAG);
725 }
726
727 /* EIGRP Checksum */
728 eigrp_packet_checksum(ei, ep->s, length);
729 ep->length = length;
730
731 ep->dst.s_addr = htonl(EIGRP_MULTICAST_ADDRESS);
732
733 /*This ack number we await from neighbor*/
734 ep->sequence_number = ei->eigrp->sequence_number;
735
736 if (IS_DEBUG_EIGRP_PACKET(0, RECV))
737 zlog_debug("Enqueuing Update length[%u] Seq [%u]",
738 length, ep->sequence_number);
739
740 for (ALL_LIST_ELEMENTS(ei->nbrs, node, nnode, nbr))
741 {
742 if (nbr->state == EIGRP_NEIGHBOR_UP)
743 {
744 /*Put packet to retransmission queue*/
745 eigrp_fifo_push_head(nbr->retrans_queue, ep);
746
747 if (nbr->retrans_queue->count == 1)
748 {
749 eigrp_send_packet_reliably(nbr);
750 }
751 }
752 }
753 }
754
755 void
756 eigrp_update_send_all (struct eigrp *eigrp, struct eigrp_interface *exception)
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) &&
866 (IF_DEF_PARAMS (nbr->ei->ifp)->auth_keychain != NULL))
867 {
868 length += eigrp_add_authTLV_MD5_to_stream(ep->s,nbr->ei);
869 }
870
871 for (ALL_LIST_ELEMENTS(nbr->ei->eigrp->topology_table, node, nnode, pe))
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 /* Check if any list fits */
886 if ((alist && access_list_apply (alist,
887 (struct prefix *) dest_addr) == FILTER_DENY)||
888 (plist && prefix_list_apply (plist,
889 (struct prefix *) dest_addr) == PREFIX_DENY)||
890 (alist_i && access_list_apply (alist_i,
891 (struct prefix *) dest_addr) == FILTER_DENY)||
892 (plist_i && prefix_list_apply (plist_i,
893 (struct prefix *) dest_addr) == PREFIX_DENY))
894 {
895 /* do not send filtered route */
896 zlog_info("Filtered prefix %s won't be sent out.",
897 inet_ntoa(dest_addr->prefix));
898 }
899 else
900 {
901 /* sending route which wasn't filtered */
902 length += eigrp_add_internalTLV_to_stream(ep->s, pe);
903 send_prefixes++;
904 }
905
906 alist = e->list[EIGRP_FILTER_IN];
907 plist = e->prefix[EIGRP_FILTER_IN];
908 alist_i = nbr->ei->list[EIGRP_FILTER_IN];
909 plist_i = nbr->ei->prefix[EIGRP_FILTER_IN];
910
911 /* Check if any list fits */
912 if ((alist && access_list_apply (alist,
913 (struct prefix *) dest_addr) == FILTER_DENY)||
914 (plist && prefix_list_apply (plist,
915 (struct prefix *) dest_addr) == PREFIX_DENY)||
916 (alist_i && access_list_apply (alist_i,
917 (struct prefix *) dest_addr) == FILTER_DENY)||
918 (plist_i && prefix_list_apply (plist_i,
919 (struct prefix *) dest_addr) == PREFIX_DENY))
920 {
921 /* do not send filtered route */
922 zlog_info("Filtered prefix %s will be removed.",
923 inet_ntoa(dest_addr->prefix));
924
925 tlv_max = eigrp_IPv4_InternalTLV_new();
926 tlv_max->type = EIGRP_TLV_IPv4_INT;
927 tlv_max->length = 28U;
928 tlv_max->metric = pe->reported_metric;
929 /* set delay to MAX */
930 tlv_max->metric.delay = EIGRP_MAX_METRIC;
931 tlv_max->destination = pe->destination_ipv4->prefix;
932 tlv_max->prefix_length = pe->destination_ipv4->prefixlen;
933
934 /* prepare message for FSM */
935 struct eigrp_fsm_action_message *fsm_msg;
936 fsm_msg = XCALLOC(MTYPE_EIGRP_FSM_MSG,
937 sizeof(struct eigrp_fsm_action_message));
938
939 struct eigrp_neighbor_entry *entry =
940 eigrp_prefix_entry_lookup(pe->entries, nbr);
941
942 fsm_msg->packet_type = EIGRP_OPC_UPDATE;
943 fsm_msg->eigrp = e;
944 fsm_msg->data_type = EIGRP_TLV_IPv4_INT;
945 fsm_msg->adv_router = nbr;
946 fsm_msg->data.ipv4_int_type = tlv_max;
947 fsm_msg->entry = entry;
948 fsm_msg->prefix = pe;
949
950 /* send message to FSM */
951 int event = eigrp_get_fsm_event(fsm_msg);
952 eigrp_fsm_event(fsm_msg, event);
953
954 /* free memory used by TLV */
955 eigrp_IPv4_InternalTLV_free (tlv_max);
956 }
957 /*
958 * End of filtering
959 */
960
961 /* NULL the pointer */
962 dest_addr = NULL;
963
964 /* delete processed prefix from list */
965 listnode_delete(prefixes, pe);
966
967 /* if there are enough prefixes, send packet */
968 if(send_prefixes >= EIGRP_TLV_MAX_IPv4)
969 break;
970 }
971
972 /* compute Auth digest */
973 if((IF_DEF_PARAMS (nbr->ei->ifp)->auth_type == EIGRP_AUTH_TYPE_MD5) &&
974 (IF_DEF_PARAMS (nbr->ei->ifp)->auth_keychain != NULL))
975 {
976 eigrp_make_md5_digest(nbr->ei,ep->s, EIGRP_AUTH_UPDATE_FLAG);
977 }
978
979 /* EIGRP Checksum */
980 eigrp_packet_checksum(nbr->ei, ep->s, length);
981
982 ep->length = length;
983 ep->dst.s_addr = nbr->src.s_addr;
984
985 /*This ack number we await from neighbor*/
986 ep->sequence_number = nbr->ei->eigrp->sequence_number;
987
988 if (IS_DEBUG_EIGRP_PACKET(0, RECV))
989 zlog_debug("Enqueuing Update Init Len [%u] Seq [%u] Dest [%s]",
990 ep->length, ep->sequence_number, inet_ntoa(ep->dst));
991
992 /*Put packet to retransmission queue*/
993 eigrp_fifo_push_head(nbr->retrans_queue, ep);
994
995 if (nbr->retrans_queue->count == 1)
996 {
997 eigrp_send_packet_reliably(nbr);
998 }
999 }
1000
1001 /**
1002 * @fn eigrp_update_send_GR_thread
1003 *
1004 * @param[in] thread contains neighbor who would receive Graceful restart
1005 *
1006 * @return int always 0
1007 *
1008 * @par
1009 * Function used for sending Graceful restart Update packet
1010 * in thread, it is prepared for multiple chunks of packet.
1011 *
1012 * Uses nbr_gr_packet_type and t_nbr_send_gr from neighbor.
1013 */
1014 int
1015 eigrp_update_send_GR_thread(struct thread *thread)
1016 {
1017 struct eigrp_neighbor *nbr;
1018
1019 /* get argument from thread */
1020 nbr = THREAD_ARG(thread);
1021 /* remove this thread pointer */
1022 nbr->t_nbr_send_gr = NULL;
1023
1024 /* if there is packet waiting in queue,
1025 * schedule this thread again with small delay */
1026 if(nbr->retrans_queue->count > 0)
1027 {
1028 nbr->t_nbr_send_gr = NULL;
1029 thread_add_timer_msec(master, eigrp_update_send_GR_thread, nbr, 10,
1030 &nbr->t_nbr_send_gr);
1031 return 0;
1032 }
1033
1034 /* send GR EIGRP packet chunk */
1035 eigrp_update_send_GR_part(nbr);
1036
1037 /* if it wasn't last chunk, schedule this thread again */
1038 if(nbr->nbr_gr_packet_type != EIGRP_PACKET_PART_LAST) {
1039 thread_execute(master, eigrp_update_send_GR_thread, nbr, 0);
1040 nbr->t_nbr_send_gr = NULL;
1041 }
1042
1043 return 0;
1044 }
1045
1046 /**
1047 * @fn eigrp_update_send_GR
1048 *
1049 * @param[in] nbr Neighbor who would receive Graceful restart
1050 * @param[in] gr_type Who executed Graceful restart
1051 * @param[in] vty Virtual terminal for log output
1052 *
1053 * @return void
1054 *
1055 * @par
1056 * Function used for sending Graceful restart Update packet:
1057 * Creates Update packet with INIT, RS, EOT flags and include
1058 * all route except those filtered
1059 */
1060 void
1061 eigrp_update_send_GR (struct eigrp_neighbor *nbr, enum GR_type gr_type, struct vty *vty)
1062 {
1063 struct eigrp_prefix_entry *pe2;
1064 struct listnode *node2, *nnode2;
1065 struct list *prefixes;
1066
1067 if(gr_type == EIGRP_GR_FILTER)
1068 {
1069 /* function was called after applying filtration */
1070 zlog_info("Neighbor %s (%s) is resync: route configuration changed",
1071 inet_ntoa(nbr->src), ifindex2ifname(nbr->ei->ifp->ifindex, VRF_DEFAULT));
1072 }
1073 else if(gr_type == EIGRP_GR_MANUAL)
1074 {
1075 /* Graceful restart was called manually */
1076 zlog_info("Neighbor %s (%s) is resync: manually cleared",
1077 inet_ntoa(nbr->src), ifindex2ifname(nbr->ei->ifp->ifindex, VRF_DEFAULT));
1078
1079 if(vty != NULL)
1080 {
1081 vty_time_print (vty, 0);
1082 vty_out (vty, "Neighbor %s (%s) is resync: manually cleared%s",
1083 inet_ntoa (nbr->src),
1084 ifindex2ifname (nbr->ei->ifp->ifindex, VRF_DEFAULT),
1085 VTY_NEWLINE);
1086 }
1087 }
1088
1089 prefixes = list_new();
1090 /* add all prefixes from topology table to list */
1091 for (ALL_LIST_ELEMENTS(nbr->ei->eigrp->topology_table, node2, nnode2, pe2))
1092 {
1093 listnode_add(prefixes, pe2);
1094 }
1095
1096 /* save prefixes to neighbor */
1097 nbr->nbr_gr_prefixes_send = prefixes;
1098 /* indicate, that this is first GR Update packet chunk */
1099 nbr->nbr_gr_packet_type = EIGRP_PACKET_PART_FIRST;
1100 /* execute packet sending in thread */
1101 thread_execute(master, eigrp_update_send_GR_thread, nbr, 0);
1102 nbr->t_nbr_send_gr = NULL;
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 }