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