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