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