]> git.proxmox.com Git - mirror_frr.git/blame - eigrpd/eigrp_hello.c
eigrpd: Only install up to eigrp->max_paths into rib.
[mirror_frr.git] / eigrpd / eigrp_hello.c
CommitLineData
7f57883e
DS
1/*
2 * EIGRP Sending and Receiving EIGRP Hello 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 "vty.h"
47#include "md5.h"
48
49#include "eigrpd/eigrp_structs.h"
50#include "eigrpd/eigrpd.h"
51#include "eigrpd/eigrp_interface.h"
52#include "eigrpd/eigrp_neighbor.h"
53#include "eigrpd/eigrp_packet.h"
54#include "eigrpd/eigrp_zebra.h"
55#include "eigrpd/eigrp_vty.h"
56#include "eigrpd/eigrp_dump.h"
57#include "eigrpd/eigrp_macros.h"
58
59/* Packet Type String. */
60static const struct message eigrp_general_tlv_type_str[] =
61{
62 { EIGRP_TLV_PARAMETER, "PARAMETER" },
63 { EIGRP_TLV_AUTH, "AUTH" },
64 { EIGRP_TLV_SEQ, "SEQ" },
65 { EIGRP_TLV_SW_VERSION, "SW_VERSION" },
66 { EIGRP_TLV_NEXT_MCAST_SEQ, "NEXT_MCAST_SEQ" },
67 { EIGRP_TLV_PEER_TERMINATION, "PEER_TERMINATION" },
68 { EIGRP_TLV_PEER_MTRLIST, "PEER_MTRLIST" },
69 { EIGRP_TLV_PEER_TIDLIST, "PEER_TIDLIST" },
70};
71
72static const size_t eigrp_general_tlv_type_str_max = sizeof(eigrp_general_tlv_type_str) /
73 sizeof(eigrp_general_tlv_type_str[0]);
74
75
76/*
77 * @fn eigrp_hello_timer
78 *
79 * @param[in] thread current execution thread timer is associated with
80 *
81 * @return int always returns 0
82 *
83 * @par
84 * Called once per "hello" time interval, default 5 seconds
85 * Sends hello packet via multicast for all interfaces eigrp
86 * is configured for
87 */
88int
89eigrp_hello_timer (struct thread *thread)
90{
91 struct eigrp_interface *ei;
92
93 ei = THREAD_ARG(thread);
94 ei->t_hello = NULL;
95
96 if (IS_DEBUG_EIGRP(0, TIMERS))
a7248930
DS
97 zlog_debug ("Start Hello Timer (%s) Expire [%u]",
98 IF_NAME(ei), EIGRP_IF_PARAM(ei, v_hello));
7f57883e
DS
99
100 /* Sending hello packet. */
101 eigrp_hello_send(ei, EIGRP_HELLO_NORMAL, NULL);
102
103 /* Hello timer set. */
104 ei->t_hello = thread_add_timer(master, eigrp_hello_timer, ei,
105 EIGRP_IF_PARAM(ei, v_hello));
106
107 return 0;
108}
109
110/**
111 * @fn eigrp_hello_parameter_decode
112 *
113 * @param[in] nbr neighbor the ACK should be sent to
114 * @param[in] param pointer packet TLV is stored to
115 *
116 * @return u_int16_t number of bytes added to packet stream
117 *
118 * @par
119 * Encode Parameter TLV, used to convey metric weights and the hold time.
120 *
121 * @usage
122 * Note the addition of K6 for the new extended metrics, and does not apply to
123 * older TLV packet formats.
124 */
125static void
126eigrp_hello_parameter_decode (struct eigrp_neighbor *nbr,
127 struct eigrp_tlv_hdr_type *tlv)
128{
129 struct eigrp *eigrp = nbr->ei->eigrp;
130 struct TLV_Parameter_Type *param = (struct TLV_Parameter_Type *)tlv;
131
132 /* copy over the values passed in by the neighbor */
133 nbr->K1 = param->K1;
134 nbr->K2 = param->K2;
135 nbr->K3 = param->K3;
136 nbr->K4 = param->K4;
137 nbr->K5 = param->K5;
138 nbr->K6 = param->K6;
139 nbr->v_holddown = ntohs(param->hold_time);
140
141 /*
142 * Check K1-K5 have the correct values to be able to become neighbors
143 * K6 does not have to match
144 */
145 if ((eigrp->k_values[0] == nbr->K1) &&
146 (eigrp->k_values[1] == nbr->K2) &&
147 (eigrp->k_values[2] == nbr->K3) &&
148 (eigrp->k_values[3] == nbr->K4) &&
149 (eigrp->k_values[4] == nbr->K5))
150 {
151
152 if (eigrp_nbr_state_get(nbr) == EIGRP_NEIGHBOR_DOWN)
153 {
154 zlog_info("Neighbor %s (%s) is pending: new adjacency",
ca975a87 155 inet_ntoa(nbr->src), ifindex2ifname(nbr->ei->ifp->ifindex, VRF_DEFAULT));
7f57883e
DS
156
157 /* Expedited hello sent */
158 eigrp_hello_send(nbr->ei, EIGRP_HELLO_NORMAL, NULL);
159
160// if(ntohl(nbr->ei->address->u.prefix4.s_addr) > ntohl(nbr->src.s_addr))
161 eigrp_update_send_init(nbr);
162
163 eigrp_nbr_state_set(nbr, EIGRP_NEIGHBOR_PENDING);
164 }
165 }
166 else
167 {
168 if (eigrp_nbr_state_get(nbr) != EIGRP_NEIGHBOR_DOWN)
169 {
170 if ((param->K1 & param->K2 & param->K3 & param->K4 & param->K5) == 255)
171 {
172 zlog_info ("Neighbor %s (%s) is down: Interface PEER-TERMINATION received",
ca975a87 173 inet_ntoa (nbr->src),ifindex2ifname (nbr->ei->ifp->ifindex, VRF_DEFAULT));
7f57883e
DS
174 eigrp_nbr_delete (nbr);
175 }
176 else
177 {
178 zlog_info ("Neighbor %s (%s) going down: Kvalue mismatch",
ca975a87 179 inet_ntoa (nbr->src),ifindex2ifname (nbr->ei->ifp->ifindex, VRF_DEFAULT));
7f57883e
DS
180 eigrp_nbr_state_set(nbr, EIGRP_NEIGHBOR_DOWN);
181 }
182 }
183 }
184}
185
186static u_char
187eigrp_hello_authentication_decode(struct stream *s, struct eigrp_tlv_hdr_type *tlv_header, struct eigrp_neighbor *nbr)
188{
189
190 struct TLV_MD5_Authentication_Type *md5;
191
192 md5 = (struct TLV_MD5_Authentication_Type *) tlv_header;
193
194 if(md5->auth_type == EIGRP_AUTH_TYPE_MD5)
195 return eigrp_check_md5_digest(s, md5, nbr, EIGRP_AUTH_BASIC_HELLO_FLAG);
196 else if (md5->auth_type == EIGRP_AUTH_TYPE_SHA256)
197 return eigrp_check_sha256_digest(s, (struct TLV_SHA256_Authentication_Type *) tlv_header, nbr, EIGRP_AUTH_BASIC_HELLO_FLAG);
198
199 return 0;
200}
201
202/**
203 * @fn eigrp_sw_version_decode
204 *
205 * @param[in] nbr neighbor the ACK shoudl be sent to
206 * @param[in] param pointer to TLV software version information
207 *
208 * @return void
209 *
210 * @par
211 * Read the software version in the specified location.
212 * This consists of two bytes of OS version, and two bytes of EIGRP
213 * revision number.
214 */
215static void
216eigrp_sw_version_decode (struct eigrp_neighbor *nbr,
217 struct eigrp_tlv_hdr_type *tlv)
218{
219 struct TLV_Software_Type *version = (struct TLV_Software_Type *)tlv;
220
221 nbr->os_rel_major = version->vender_major;
222 nbr->os_rel_minor = version->vender_minor;
223 nbr->tlv_rel_major = version->eigrp_major;
224 nbr->tlv_rel_minor = version->eigrp_minor;
225 return;
226}
227
228/**
229 * @fn eigrp_peer_termination_decode
230 *
231 * @param[in] nbr neighbor the ACK shoudl be sent to
232 * @param[in] tlv pointer to TLV software version information
233 *
234 * @return void
235 *
236 * @par
237 * Read the address in the TLV and match to out address. If
238 * a match is found, move the sending neighbor to the down state. If
239 * out address is not in the TLV, then ignore the peer termination
240 */
241static void
242eigrp_peer_termination_decode (struct eigrp_neighbor *nbr,
243 struct eigrp_tlv_hdr_type *tlv)
244{
245 struct TLV_Peer_Termination_type *param = (struct TLV_Peer_Termination_type *)tlv;
246
247 uint32_t my_ip = nbr->ei->address->u.prefix4.s_addr;
248 uint32_t received_ip = param->neighbor_ip;
249
250 if(my_ip == received_ip)
251 {
252 zlog_info ("Neighbor %s (%s) is down: Peer Termination received",
ca975a87 253 inet_ntoa (nbr->src),ifindex2ifname (nbr->ei->ifp->ifindex, VRF_DEFAULT));
7f57883e
DS
254 /* set neighbor to DOWN */
255 nbr->state = EIGRP_NEIGHBOR_DOWN;
256 /* delete neighbor */
257 eigrp_nbr_delete (nbr);
258 }
259}
260
261/**
262 * @fn eigrp_peer_termination_encode
263 *
264 * @param[in,out] s packet stream TLV is stored to
265 * @param[in] nbr_addr pointer to neighbor address for Peer Termination TLV
266 *
267 * @return u_int16_t number of bytes added to packet stream
268 *
269 * @par
270 * Function used to encode Peer Termination TLV to Hello packet.
271 */
272static u_int16_t
273eigrp_peer_termination_encode (struct stream *s, struct in_addr *nbr_addr)
274{
275 u_int16_t length = EIGRP_TLV_PEER_TERMINATION_LEN;
276
277 /* fill in type and length */
278 stream_putw(s, EIGRP_TLV_PEER_TERMINATION);
279 stream_putw(s, length);
280
281 /* fill in unknown field 0x04 */
282 stream_putc(s, 0x04);
283
284 /* finally neighbor IP address */
285 stream_put_ipv4(s, nbr_addr->s_addr);
286
287 return(length);
288}
289
290/*
291 * @fn eigrp_hello_receive
292 *
293 * @param[in] eigrp eigrp routing process
294 * @param[in] iph pointer to ip header
295 * @param[in] eigrph pointer to eigrp header
296 * @param[in] s input ip stream
297 * @param[in] ei eigrp interface packet arrived on
298 * @param[in] size size of eigrp packet
299 *
300 * @return void
301 *
302 * @par
303 * This is the main worker function for processing hello packets. It
304 * will validate the peer associated with the src ip address of the ip
305 * header, and then decode each of the general TLVs which the packet
306 * may contain.
307 *
308 * @usage
309 * Not all TLVs are current decoder. This is a work in progress..
310 */
311void
312eigrp_hello_receive (struct eigrp *eigrp, struct ip *iph, struct eigrp_header *eigrph,
313 struct stream *s, struct eigrp_interface *ei, int size)
314{
315 struct eigrp_tlv_hdr_type *tlv_header;
316 struct eigrp_neighbor *nbr;
317 uint16_t type;
318 uint16_t length;
319
320 /* get neighbor struct */
321 nbr = eigrp_nbr_get(ei, eigrph, iph);
322
323 /* neighbor must be valid, eigrp_nbr_get creates if none existed */
324 assert(nbr);
325
326 if (IS_DEBUG_EIGRP_PACKET(eigrph->opcode - 1, RECV))
327 zlog_debug("Processing Hello size[%u] int(%s) nbr(%s)",
ca975a87 328 size, ifindex2ifname(nbr->ei->ifp->ifindex, VRF_DEFAULT),
7f57883e
DS
329 inet_ntoa(nbr->src));
330
331 size -= EIGRP_HEADER_LEN;
332 if (size < 0)
333 return;
334
335 tlv_header = (struct eigrp_tlv_hdr_type *)eigrph->tlv;
336
337 do {
338 type = ntohs(tlv_header->type);
339 length = ntohs(tlv_header->length);
340
341 if ((length > 0) && (length <= size))
342 {
343 if (IS_DEBUG_EIGRP_PACKET(0, RECV))
344 zlog_debug(" General TLV(%s)", LOOKUP(eigrp_general_tlv_type_str, type));
345
346 // determine what General TLV is being processed
347 switch (type)
348 {
349 case EIGRP_TLV_PARAMETER:
350 eigrp_hello_parameter_decode(nbr, tlv_header);
351 break;
352 case EIGRP_TLV_AUTH:
353 {
354 if(eigrp_hello_authentication_decode(s,tlv_header,nbr) == 0)
355 return;
356 else
357 break;
358 break;
359 }
360 case EIGRP_TLV_SEQ:
361 break;
362 case EIGRP_TLV_SW_VERSION:
363 eigrp_sw_version_decode(nbr, tlv_header);
364 break;
365 case EIGRP_TLV_NEXT_MCAST_SEQ:
366 break;
367 case EIGRP_TLV_PEER_TERMINATION:
368 eigrp_peer_termination_decode(nbr, tlv_header);
369 break;
370 case EIGRP_TLV_PEER_MTRLIST:
371 case EIGRP_TLV_PEER_TIDLIST:
372 break;
373 default:
374 break;
375 }
376 }
377
378 tlv_header = (struct eigrp_tlv_hdr_type *)(((char *)tlv_header) + length);
379 size -= length;
380
381 } while (size > 0);
382
383
384 /*If received packet is hello with Parameter TLV*/
385 if (ntohl(eigrph->ack) == 0)
386 {
387 /* increment statistics. */
388 ei->hello_in++;
389 eigrp_nbr_state_update(nbr);
390
391 }
392
393 if (IS_DEBUG_EIGRP_PACKET(0, RECV))
394 zlog_debug("Hello Packet received from %s", inet_ntoa(nbr->src));
395
396}
397
398/**
399 * @fn eigrp_sw_version_encode
400 *
401 * @param[in,out] s packet stream TLV is stored to
402 *
403 * @return u_int16_t number of bytes added to packet stream
404 *
405 * @par
406 * Store the software version in the specified location.
407 * This consists of two bytes of OS version, and two bytes of EIGRP
408 * revision number.
409 */
410static u_int16_t
411eigrp_sw_version_encode (struct stream *s)
412{
413 u_int16_t length = EIGRP_TLV_SW_VERSION_LEN;
414
415 // setup the tlv fields
416 stream_putw(s, EIGRP_TLV_SW_VERSION);
417 stream_putw(s, length);
418
419 // encode the version of quagga we're running
420 // DVS: need to figure out a cleaner way to do this
421 stream_putc(s, 0); //!< major os version
422 stream_putc(s, 99); //!< minor os version
423
424 /* and the core eigrp version */
425 stream_putc(s, EIGRP_MAJOR_VERSION);
426 stream_putc(s, EIGRP_MINOR_VERSION);
427
428 return(length);
429}
430
431/**
432 * @fn eigrp_tidlist_encode
433 *
434 * @param[in,out] s packet stream TLV is stored to
435 *
436 * @return void
437 *
438 * @par
439 * If doing mutli-topology, then store the supported TID list.
440 * This is currently a place holder function
441 */
442static u_int16_t
443eigrp_tidlist_encode (struct stream *s)
444{
445 //u_int16_t length = EIGRP_TLV_SW_VERSION_LEN;
446 return 0;
447}
448
449/**
450 * @fn eigrp_sequence_encode
451 *
452 * @param[in,out] s packet stream TLV is stored to
453 *
454 * @return u_int16_t number of bytes added to packet stream
455 *
456 * @par
457 * Part of conditional receive process
458 *
459 */
460static u_int16_t
461eigrp_sequence_encode (struct stream *s)
462{
463 u_int16_t length = EIGRP_TLV_SEQ_BASE_LEN;
464 struct eigrp *eigrp;
465 struct eigrp_interface *ei;
466 struct listnode *node, *node2, *nnode2;
467 struct eigrp_neighbor *nbr;
468 size_t backup_end, size_end;
469 int found;
470
471 eigrp = eigrp_lookup ();
472 if (eigrp == NULL)
473 {
474 return 0;
475 }
476
477 // add in the parameters TLV
478 backup_end = stream_get_endp(s);
479 stream_putw(s, EIGRP_TLV_SEQ);
480 size_end = s->endp;
481 stream_putw(s, 0x0000);
482 stream_putc(s, IPV4_MAX_BYTELEN);
483
484 found = 0;
485 for (ALL_LIST_ELEMENTS_RO (eigrp->eiflist, node, ei))
486 {
487 for (ALL_LIST_ELEMENTS (ei->nbrs, node2, nnode2, nbr))
488 {
489 if(nbr->multicast_queue->count > 0)
490 {
491 length += (u_int16_t) stream_put_ipv4(s,nbr->src.s_addr);
492 found = 1;
493 }
494 }
495 }
496
497 if(found == 0)
498 {
499 stream_set_endp(s,backup_end);
500 return 0;
501 }
502
503 backup_end = stream_get_endp (s);
504 stream_set_endp (s,size_end);
505 stream_putw (s, length);
506 stream_set_endp (s, backup_end);
507
508 return length;
509}
510
511/**
512 * @fn eigrp_sequence_encode
513 *
514 * @param[in,out] s packet stream TLV is stored to
515 *
516 * @return u_int16_t number of bytes added to packet stream
517 *
518 * @par
519 * Part of conditional receive process
520 *
521 */
522static u_int16_t
523eigrp_next_sequence_encode (struct stream *s)
524{
525 u_int16_t length = EIGRP_NEXT_SEQUENCE_TLV_SIZE;
526 struct eigrp *eigrp;
527
528 eigrp = eigrp_lookup ();
529 if (eigrp == NULL)
530 {
531 return 0;
532 }
533
534 // add in the parameters TLV
535 stream_putw(s, EIGRP_TLV_NEXT_MCAST_SEQ);
536 stream_putw(s, EIGRP_NEXT_SEQUENCE_TLV_SIZE);
537 stream_putl(s,eigrp->sequence_number+1);
538
539 return length;
540}
541
542/**
543 * @fn eigrp_hello_parameter_encode
544 *
545 * @param[in] ei pointer to interface hello packet came in on
546 * @param[in,out] s packet stream TLV is stored to
547 *
548 * @return u_int16_t number of bytes added to packet stream
549 *
550 * @par
551 * Encode Parameter TLV, used to convey metric weights and the hold time.
552 *
553 * @usage
554 * Note the addition of K6 for the new extended metrics, and does not apply to
555 * older TLV packet formats.
556 */
557static u_int16_t
558eigrp_hello_parameter_encode (struct eigrp_interface *ei, struct stream *s, u_char flags)
559{
560 u_int16_t length = EIGRP_TLV_PARAMETER_LEN;
561
562 // add in the parameters TLV
563 stream_putw(s, EIGRP_TLV_PARAMETER);
564 stream_putw(s, EIGRP_TLV_PARAMETER_LEN);
565
566 //if graceful shutdown is needed to be announced, send all 255 in K values
567 if(flags & EIGRP_HELLO_GRACEFUL_SHUTDOWN)
568 {
569 stream_putc(s, 0xff); /* K1 */
570 stream_putc(s, 0xff); /* K2 */
571 stream_putc(s, 0xff); /* K3 */
572 stream_putc(s, 0xff); /* K4 */
573 stream_putc(s, 0xff); /* K5 */
574 stream_putc(s, 0xff); /* K6 */
575 }
576 else // set k values
577 {
578 stream_putc(s, ei->eigrp->k_values[0]); /* K1 */
579 stream_putc(s, ei->eigrp->k_values[1]); /* K2 */
580 stream_putc(s, ei->eigrp->k_values[2]); /* K3 */
581 stream_putc(s, ei->eigrp->k_values[3]); /* K4 */
582 stream_putc(s, ei->eigrp->k_values[4]); /* K5 */
583 stream_putc(s, ei->eigrp->k_values[5]); /* K6 */
584 }
585
586 // and set hold time value..
587 stream_putw(s, IF_DEF_PARAMS(ei->ifp)->v_wait);
588
589 return length;
590}
591
592/**
593 * @fn eigrp_hello_encode
594 *
595 * @param[in] ei pointer to interface hello packet came in on
596 * @param[in] s packet stream TLV is stored to
597 * @param[in] ack if non-zero, neigbors sequence packet to ack
598 * @param[in] flags type of hello packet
599 * @param[in] nbr_addr pointer to neighbor address for Peer Termination TLV
600 *
601 * @return eigrp_packet pointer initialize hello packet
602 *
603 * @par
604 * Allocate an EIGRP hello packet, and add in the the approperate TLVs
605 *
606 */
607static struct eigrp_packet *
608eigrp_hello_encode (struct eigrp_interface *ei, in_addr_t addr, u_int32_t ack, u_char flags, struct in_addr *nbr_addr)
609{
610 struct eigrp_packet *ep;
611 u_int16_t length = EIGRP_HEADER_LEN;
612
613 // allocate a new packet to be sent
614 ep = eigrp_packet_new(ei->ifp->mtu);
615
616 if (ep)
617 {
618 // encode common header feilds
619 eigrp_packet_header_init(EIGRP_OPC_HELLO, ei, ep->s, 0, 0, ack);
620
621 // encode Authentication TLV
622 if((IF_DEF_PARAMS (ei->ifp)->auth_type == EIGRP_AUTH_TYPE_MD5) && (IF_DEF_PARAMS (ei->ifp)->auth_keychain != NULL))
623 {
624 length += eigrp_add_authTLV_MD5_to_stream(ep->s,ei);
625 }
626 else if((IF_DEF_PARAMS (ei->ifp)->auth_type == EIGRP_AUTH_TYPE_SHA256) && (IF_DEF_PARAMS (ei->ifp)->auth_keychain != NULL))
627 {
628 length += eigrp_add_authTLV_SHA256_to_stream(ep->s,ei);
629 }
630
631 /* encode appropriate parameters to Hello packet */
632 if(flags & EIGRP_HELLO_GRACEFUL_SHUTDOWN)
633 length += eigrp_hello_parameter_encode(ei, ep->s, EIGRP_HELLO_GRACEFUL_SHUTDOWN);
634 else
635 length += eigrp_hello_parameter_encode(ei, ep->s, EIGRP_HELLO_NORMAL);
636
637 // figure out the version of code we're running
638 length += eigrp_sw_version_encode(ep->s);
639
640 if(flags & EIGRP_HELLO_ADD_SEQUENCE)
641 {
642 length += eigrp_sequence_encode(ep->s);
643 length += eigrp_next_sequence_encode(ep->s);
644 }
645
646 // add in the TID list if doing multi-topology
647 length += eigrp_tidlist_encode(ep->s);
648
649 /* encode Peer Termination TLV if needed */
650 if(flags & EIGRP_HELLO_GRACEFUL_SHUTDOWN_NBR)
651 length += eigrp_peer_termination_encode(ep->s, nbr_addr);
652
653 // Set packet length
654 ep->length = length;
655
656 // set soruce address for the hello packet
657 ep->dst.s_addr = addr;
658
659 if((IF_DEF_PARAMS (ei->ifp)->auth_type == EIGRP_AUTH_TYPE_MD5) && (IF_DEF_PARAMS (ei->ifp)->auth_keychain != NULL))
660 {
661 eigrp_make_md5_digest(ei,ep->s, EIGRP_AUTH_BASIC_HELLO_FLAG);
662 }
663 else if((IF_DEF_PARAMS (ei->ifp)->auth_type == EIGRP_AUTH_TYPE_SHA256) && (IF_DEF_PARAMS (ei->ifp)->auth_keychain != NULL))
664 {
665 eigrp_make_sha256_digest(ei,ep->s, EIGRP_AUTH_BASIC_HELLO_FLAG);
666 }
667
668 // EIGRP Checksum
669 eigrp_packet_checksum(ei, ep->s, length);
670 }
671
672 return(ep);
673}
674
675/**
676 * @fn eigrp_hello_send
677 *
678 * @param[in] nbr neighbor the ACK should be sent to
679 *
680 * @return void
681 *
682 * @par
683 * Send (unicast) a hello packet with the destination address
684 * associated with the neighbor. The eigrp header ACK feild will be
685 * updated to the neighbor's sequence number to acknolodge any
686 * outstanding packets
687 */
688void
689eigrp_hello_send_ack (struct eigrp_neighbor *nbr)
690{
691 struct eigrp_packet *ep;
692
693 /* if packet succesfully created, add it to the interface queue */
694 ep = eigrp_hello_encode(nbr->ei, nbr->src.s_addr, nbr->recv_sequence_number, EIGRP_HELLO_NORMAL, NULL);
695
696 if (ep)
697 {
698 if (IS_DEBUG_EIGRP_PACKET(0, SEND))
699 zlog_debug("Queueing [Hello] Ack Seq [%u] nbr [%s]",
700 nbr->recv_sequence_number, inet_ntoa(nbr->src));
701
702 /* Add packet to the top of the interface output queue*/
703 eigrp_fifo_push_head(nbr->ei->obuf, ep);
704
705 /* Hook thread to write packet. */
706 if (nbr->ei->on_write_q == 0)
707 {
708 listnode_add(nbr->ei->eigrp->oi_write_q, nbr->ei);
709 nbr->ei->on_write_q = 1;
710 }
711 if (nbr->ei->eigrp->t_write == NULL)
712 nbr->ei->eigrp->t_write =
713 thread_add_write(master, eigrp_write, nbr->ei->eigrp, nbr->ei->eigrp->fd);
714 }
715}
716
717/**
718 * @fn eigrp_hello_send
719 *
720 * @param[in] ei pointer to interface hello should be sent
721 * @param[in] flags type of hello packet
722 * @param[in] nbr_addr pointer to neighbor address for Peer Termination TLV
723 *
724 * @return void
725 *
726 * @par
727 * Build and enqueue a generic (multicast) periodic hello packet for
728 * sending. If no packets are currently queues, the packet will be
729 * sent immadiatly
730 */
731void
732eigrp_hello_send (struct eigrp_interface *ei, u_char flags, struct in_addr *nbr_addr)
733{
734 struct eigrp_packet *ep = NULL;
735
736 /* If this is passive interface, do not send EIGRP Hello.
737 if ((EIGRP_IF_PASSIVE_STATUS (ei) == EIGRP_IF_PASSIVE) ||
738 (ei->type != EIGRP_IFTYPE_NBMA))
739 return;
740 */
741
742 if (IS_DEBUG_EIGRP_PACKET(0, SEND))
743 zlog_debug("Queueing [Hello] Interface(%s)", IF_NAME(ei));
744
745 /* if packet was succesfully created, then add it to the interface queue */
746 ep = eigrp_hello_encode(ei, htonl(EIGRP_MULTICAST_ADDRESS), 0, flags, nbr_addr);
747
748 if (ep)
749 {
750 // Add packet to the top of the interface output queue
751 eigrp_fifo_push_head(ei->obuf, ep);
752
753 /* Hook thread to write packet. */
754 if (ei->on_write_q == 0)
755 {
756 listnode_add(ei->eigrp->oi_write_q, ei);
757 ei->on_write_q = 1;
758 }
759
760 if (ei->eigrp->t_write == NULL)
761 {
762 if(flags & EIGRP_HELLO_GRACEFUL_SHUTDOWN)
763 {
764 ei->eigrp->t_write =
765 thread_execute(master, eigrp_write, ei->eigrp, ei->eigrp->fd);
766 }
767 else
768 {
769 ei->eigrp->t_write =
770 thread_add_write(master, eigrp_write, ei->eigrp, ei->eigrp->fd);
771 }
772 }
773 }
774}