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