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