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