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