2 * EIGRP Sending and Receiving EIGRP Hello Packets.
3 * Copyright (C) 2013-2016
15 * This file is part of GNU Zebra.
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
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.
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
41 #include "sockunion.h"
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"
59 /* Packet Type String. */
60 static const struct message eigrp_general_tlv_type_str
[] =
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" },
72 static const size_t eigrp_general_tlv_type_str_max
= sizeof(eigrp_general_tlv_type_str
) /
73 sizeof(eigrp_general_tlv_type_str
[0]);
77 * @fn eigrp_hello_timer
79 * @param[in] thread current execution thread timer is associated with
81 * @return int always returns 0
84 * Called once per "hello" time interval, default 5 seconds
85 * Sends hello packet via multicast for all interfaces eigrp
89 eigrp_hello_timer (struct thread
*thread
)
91 struct eigrp_interface
*ei
;
93 ei
= THREAD_ARG(thread
);
96 if (IS_DEBUG_EIGRP(0, TIMERS
))
97 zlog (NULL
, LOG_DEBUG
, "Start Hello Timer (%s) Expire [%u]",
98 IF_NAME(ei
), EIGRP_IF_PARAM(ei
, v_hello
));
100 /* Sending hello packet. */
101 eigrp_hello_send(ei
, EIGRP_HELLO_NORMAL
, NULL
);
103 /* Hello timer set. */
104 ei
->t_hello
= thread_add_timer(master
, eigrp_hello_timer
, ei
,
105 EIGRP_IF_PARAM(ei
, v_hello
));
111 * @fn eigrp_hello_parameter_decode
113 * @param[in] nbr neighbor the ACK should be sent to
114 * @param[in] param pointer packet TLV is stored to
116 * @return u_int16_t number of bytes added to packet stream
119 * Encode Parameter TLV, used to convey metric weights and the hold time.
122 * Note the addition of K6 for the new extended metrics, and does not apply to
123 * older TLV packet formats.
126 eigrp_hello_parameter_decode (struct eigrp_neighbor
*nbr
,
127 struct eigrp_tlv_hdr_type
*tlv
)
129 struct eigrp
*eigrp
= nbr
->ei
->eigrp
;
130 struct TLV_Parameter_Type
*param
= (struct TLV_Parameter_Type
*)tlv
;
132 /* copy over the values passed in by the neighbor */
139 nbr
->v_holddown
= ntohs(param
->hold_time
);
142 * Check K1-K5 have the correct values to be able to become neighbors
143 * K6 does not have to match
145 if ((eigrp
->k_values
[0] == nbr
->K1
) &&
146 (eigrp
->k_values
[1] == nbr
->K2
) &&
147 (eigrp
->k_values
[2] == nbr
->K3
) &&
148 (eigrp
->k_values
[3] == nbr
->K4
) &&
149 (eigrp
->k_values
[4] == nbr
->K5
))
152 if (eigrp_nbr_state_get(nbr
) == EIGRP_NEIGHBOR_DOWN
)
154 zlog_info("Neighbor %s (%s) is pending: new adjacency",
155 inet_ntoa(nbr
->src
), ifindex2ifname(nbr
->ei
->ifp
->ifindex
));
157 /* Expedited hello sent */
158 eigrp_hello_send(nbr
->ei
, EIGRP_HELLO_NORMAL
, NULL
);
160 // if(ntohl(nbr->ei->address->u.prefix4.s_addr) > ntohl(nbr->src.s_addr))
161 eigrp_update_send_init(nbr
);
163 eigrp_nbr_state_set(nbr
, EIGRP_NEIGHBOR_PENDING
);
168 if (eigrp_nbr_state_get(nbr
) != EIGRP_NEIGHBOR_DOWN
)
170 if ((param
->K1
& param
->K2
& param
->K3
& param
->K4
& param
->K5
) == 255)
172 zlog_info ("Neighbor %s (%s) is down: Interface PEER-TERMINATION received",
173 inet_ntoa (nbr
->src
),ifindex2ifname (nbr
->ei
->ifp
->ifindex
));
174 eigrp_nbr_delete (nbr
);
178 zlog_info ("Neighbor %s (%s) going down: Kvalue mismatch",
179 inet_ntoa (nbr
->src
),ifindex2ifname (nbr
->ei
->ifp
->ifindex
));
180 eigrp_nbr_state_set(nbr
, EIGRP_NEIGHBOR_DOWN
);
187 eigrp_hello_authentication_decode(struct stream
*s
, struct eigrp_tlv_hdr_type
*tlv_header
, struct eigrp_neighbor
*nbr
)
190 struct TLV_MD5_Authentication_Type
*md5
;
192 md5
= (struct TLV_MD5_Authentication_Type
*) tlv_header
;
194 if(md5
->auth_type
== EIGRP_AUTH_TYPE_MD5
)
195 return eigrp_check_md5_digest(s
, md5
, nbr
, EIGRP_AUTH_BASIC_HELLO_FLAG
);
196 else if (md5
->auth_type
== EIGRP_AUTH_TYPE_SHA256
)
197 return eigrp_check_sha256_digest(s
, (struct TLV_SHA256_Authentication_Type
*) tlv_header
, nbr
, EIGRP_AUTH_BASIC_HELLO_FLAG
);
203 * @fn eigrp_sw_version_decode
205 * @param[in] nbr neighbor the ACK shoudl be sent to
206 * @param[in] param pointer to TLV software version information
211 * Read the software version in the specified location.
212 * This consists of two bytes of OS version, and two bytes of EIGRP
216 eigrp_sw_version_decode (struct eigrp_neighbor
*nbr
,
217 struct eigrp_tlv_hdr_type
*tlv
)
219 struct TLV_Software_Type
*version
= (struct TLV_Software_Type
*)tlv
;
221 nbr
->os_rel_major
= version
->vender_major
;
222 nbr
->os_rel_minor
= version
->vender_minor
;
223 nbr
->tlv_rel_major
= version
->eigrp_major
;
224 nbr
->tlv_rel_minor
= version
->eigrp_minor
;
229 * @fn eigrp_peer_termination_decode
231 * @param[in] nbr neighbor the ACK shoudl be sent to
232 * @param[in] tlv pointer to TLV software version information
237 * Read the address in the TLV and match to out address. If
238 * a match is found, move the sending neighbor to the down state. If
239 * out address is not in the TLV, then ignore the peer termination
242 eigrp_peer_termination_decode (struct eigrp_neighbor
*nbr
,
243 struct eigrp_tlv_hdr_type
*tlv
)
245 struct TLV_Peer_Termination_type
*param
= (struct TLV_Peer_Termination_type
*)tlv
;
247 uint32_t my_ip
= nbr
->ei
->address
->u
.prefix4
.s_addr
;
248 uint32_t received_ip
= param
->neighbor_ip
;
250 if(my_ip
== received_ip
)
252 zlog_info ("Neighbor %s (%s) is down: Peer Termination received",
253 inet_ntoa (nbr
->src
),ifindex2ifname (nbr
->ei
->ifp
->ifindex
));
254 /* set neighbor to DOWN */
255 nbr
->state
= EIGRP_NEIGHBOR_DOWN
;
256 /* delete neighbor */
257 eigrp_nbr_delete (nbr
);
262 * @fn eigrp_peer_termination_encode
264 * @param[in,out] s packet stream TLV is stored to
265 * @param[in] nbr_addr pointer to neighbor address for Peer Termination TLV
267 * @return u_int16_t number of bytes added to packet stream
270 * Function used to encode Peer Termination TLV to Hello packet.
273 eigrp_peer_termination_encode (struct stream
*s
, struct in_addr
*nbr_addr
)
275 u_int16_t length
= EIGRP_TLV_PEER_TERMINATION_LEN
;
277 /* fill in type and length */
278 stream_putw(s
, EIGRP_TLV_PEER_TERMINATION
);
279 stream_putw(s
, length
);
281 /* fill in unknown field 0x04 */
282 stream_putc(s
, 0x04);
284 /* finally neighbor IP address */
285 stream_put_ipv4(s
, nbr_addr
->s_addr
);
291 * @fn eigrp_hello_receive
293 * @param[in] eigrp eigrp routing process
294 * @param[in] iph pointer to ip header
295 * @param[in] eigrph pointer to eigrp header
296 * @param[in] s input ip stream
297 * @param[in] ei eigrp interface packet arrived on
298 * @param[in] size size of eigrp packet
303 * This is the main worker function for processing hello packets. It
304 * will validate the peer associated with the src ip address of the ip
305 * header, and then decode each of the general TLVs which the packet
309 * Not all TLVs are current decoder. This is a work in progress..
312 eigrp_hello_receive (struct eigrp
*eigrp
, struct ip
*iph
, struct eigrp_header
*eigrph
,
313 struct stream
*s
, struct eigrp_interface
*ei
, int size
)
315 struct eigrp_tlv_hdr_type
*tlv_header
;
316 struct eigrp_neighbor
*nbr
;
320 /* get neighbor struct */
321 nbr
= eigrp_nbr_get(ei
, eigrph
, iph
);
323 /* neighbor must be valid, eigrp_nbr_get creates if none existed */
326 if (IS_DEBUG_EIGRP_PACKET(eigrph
->opcode
- 1, RECV
))
327 zlog_debug("Processing Hello size[%u] int(%s) nbr(%s)",
328 size
, ifindex2ifname(nbr
->ei
->ifp
->ifindex
),
329 inet_ntoa(nbr
->src
));
331 size
-= EIGRP_HEADER_LEN
;
335 tlv_header
= (struct eigrp_tlv_hdr_type
*)eigrph
->tlv
;
338 type
= ntohs(tlv_header
->type
);
339 length
= ntohs(tlv_header
->length
);
341 if ((length
> 0) && (length
<= size
))
343 if (IS_DEBUG_EIGRP_PACKET(0, RECV
))
344 zlog_debug(" General TLV(%s)", LOOKUP(eigrp_general_tlv_type_str
, type
));
346 // determine what General TLV is being processed
349 case EIGRP_TLV_PARAMETER
:
350 eigrp_hello_parameter_decode(nbr
, tlv_header
);
354 if(eigrp_hello_authentication_decode(s
,tlv_header
,nbr
) == 0)
362 case EIGRP_TLV_SW_VERSION
:
363 eigrp_sw_version_decode(nbr
, tlv_header
);
365 case EIGRP_TLV_NEXT_MCAST_SEQ
:
367 case EIGRP_TLV_PEER_TERMINATION
:
368 eigrp_peer_termination_decode(nbr
, tlv_header
);
370 case EIGRP_TLV_PEER_MTRLIST
:
371 case EIGRP_TLV_PEER_TIDLIST
:
378 tlv_header
= (struct eigrp_tlv_hdr_type
*)(((char *)tlv_header
) + length
);
384 /*If received packet is hello with Parameter TLV*/
385 if (ntohl(eigrph
->ack
) == 0)
387 /* increment statistics. */
389 eigrp_nbr_state_update(nbr
);
393 if (IS_DEBUG_EIGRP_PACKET(0, RECV
))
394 zlog_debug("Hello Packet received from %s", inet_ntoa(nbr
->src
));
399 * @fn eigrp_sw_version_encode
401 * @param[in,out] s packet stream TLV is stored to
403 * @return u_int16_t number of bytes added to packet stream
406 * Store the software version in the specified location.
407 * This consists of two bytes of OS version, and two bytes of EIGRP
411 eigrp_sw_version_encode (struct stream
*s
)
413 u_int16_t length
= EIGRP_TLV_SW_VERSION_LEN
;
415 // setup the tlv fields
416 stream_putw(s
, EIGRP_TLV_SW_VERSION
);
417 stream_putw(s
, length
);
419 // encode the version of quagga we're running
420 // DVS: need to figure out a cleaner way to do this
421 stream_putc(s
, 0); //!< major os version
422 stream_putc(s
, 99); //!< minor os version
424 /* and the core eigrp version */
425 stream_putc(s
, EIGRP_MAJOR_VERSION
);
426 stream_putc(s
, EIGRP_MINOR_VERSION
);
432 * @fn eigrp_tidlist_encode
434 * @param[in,out] s packet stream TLV is stored to
439 * If doing mutli-topology, then store the supported TID list.
440 * This is currently a place holder function
443 eigrp_tidlist_encode (struct stream
*s
)
445 //u_int16_t length = EIGRP_TLV_SW_VERSION_LEN;
450 * @fn eigrp_sequence_encode
452 * @param[in,out] s packet stream TLV is stored to
454 * @return u_int16_t number of bytes added to packet stream
457 * Part of conditional receive process
461 eigrp_sequence_encode (struct stream
*s
)
463 u_int16_t length
= EIGRP_TLV_SEQ_BASE_LEN
;
465 struct eigrp_interface
*ei
;
466 struct listnode
*node
, *node2
, *nnode2
;
467 struct eigrp_neighbor
*nbr
;
468 size_t backup_end
, size_end
;
471 eigrp
= eigrp_lookup ();
477 // add in the parameters TLV
478 backup_end
= stream_get_endp(s
);
479 stream_putw(s
, EIGRP_TLV_SEQ
);
481 stream_putw(s
, 0x0000);
482 stream_putc(s
, IPV4_MAX_BYTELEN
);
485 for (ALL_LIST_ELEMENTS_RO (eigrp
->eiflist
, node
, ei
))
487 for (ALL_LIST_ELEMENTS (ei
->nbrs
, node2
, nnode2
, nbr
))
489 if(nbr
->multicast_queue
->count
> 0)
491 length
+= (u_int16_t
) stream_put_ipv4(s
,nbr
->src
.s_addr
);
499 stream_set_endp(s
,backup_end
);
503 backup_end
= stream_get_endp (s
);
504 stream_set_endp (s
,size_end
);
505 stream_putw (s
, length
);
506 stream_set_endp (s
, backup_end
);
512 * @fn eigrp_sequence_encode
514 * @param[in,out] s packet stream TLV is stored to
516 * @return u_int16_t number of bytes added to packet stream
519 * Part of conditional receive process
523 eigrp_next_sequence_encode (struct stream
*s
)
525 u_int16_t length
= EIGRP_NEXT_SEQUENCE_TLV_SIZE
;
528 eigrp
= eigrp_lookup ();
534 // add in the parameters TLV
535 stream_putw(s
, EIGRP_TLV_NEXT_MCAST_SEQ
);
536 stream_putw(s
, EIGRP_NEXT_SEQUENCE_TLV_SIZE
);
537 stream_putl(s
,eigrp
->sequence_number
+1);
543 * @fn eigrp_hello_parameter_encode
545 * @param[in] ei pointer to interface hello packet came in on
546 * @param[in,out] s packet stream TLV is stored to
548 * @return u_int16_t number of bytes added to packet stream
551 * Encode Parameter TLV, used to convey metric weights and the hold time.
554 * Note the addition of K6 for the new extended metrics, and does not apply to
555 * older TLV packet formats.
558 eigrp_hello_parameter_encode (struct eigrp_interface
*ei
, struct stream
*s
, u_char flags
)
560 u_int16_t length
= EIGRP_TLV_PARAMETER_LEN
;
562 // add in the parameters TLV
563 stream_putw(s
, EIGRP_TLV_PARAMETER
);
564 stream_putw(s
, EIGRP_TLV_PARAMETER_LEN
);
566 //if graceful shutdown is needed to be announced, send all 255 in K values
567 if(flags
& EIGRP_HELLO_GRACEFUL_SHUTDOWN
)
569 stream_putc(s
, 0xff); /* K1 */
570 stream_putc(s
, 0xff); /* K2 */
571 stream_putc(s
, 0xff); /* K3 */
572 stream_putc(s
, 0xff); /* K4 */
573 stream_putc(s
, 0xff); /* K5 */
574 stream_putc(s
, 0xff); /* K6 */
578 stream_putc(s
, ei
->eigrp
->k_values
[0]); /* K1 */
579 stream_putc(s
, ei
->eigrp
->k_values
[1]); /* K2 */
580 stream_putc(s
, ei
->eigrp
->k_values
[2]); /* K3 */
581 stream_putc(s
, ei
->eigrp
->k_values
[3]); /* K4 */
582 stream_putc(s
, ei
->eigrp
->k_values
[4]); /* K5 */
583 stream_putc(s
, ei
->eigrp
->k_values
[5]); /* K6 */
586 // and set hold time value..
587 stream_putw(s
, IF_DEF_PARAMS(ei
->ifp
)->v_wait
);
593 * @fn eigrp_hello_encode
595 * @param[in] ei pointer to interface hello packet came in on
596 * @param[in] s packet stream TLV is stored to
597 * @param[in] ack if non-zero, neigbors sequence packet to ack
598 * @param[in] flags type of hello packet
599 * @param[in] nbr_addr pointer to neighbor address for Peer Termination TLV
601 * @return eigrp_packet pointer initialize hello packet
604 * Allocate an EIGRP hello packet, and add in the the approperate TLVs
607 static struct eigrp_packet
*
608 eigrp_hello_encode (struct eigrp_interface
*ei
, in_addr_t addr
, u_int32_t ack
, u_char flags
, struct in_addr
*nbr_addr
)
610 struct eigrp_packet
*ep
;
611 u_int16_t length
= EIGRP_HEADER_LEN
;
613 // allocate a new packet to be sent
614 ep
= eigrp_packet_new(ei
->ifp
->mtu
);
618 // encode common header feilds
619 eigrp_packet_header_init(EIGRP_OPC_HELLO
, ei
, ep
->s
, 0, 0, ack
);
621 // encode Authentication TLV
622 if((IF_DEF_PARAMS (ei
->ifp
)->auth_type
== EIGRP_AUTH_TYPE_MD5
) && (IF_DEF_PARAMS (ei
->ifp
)->auth_keychain
!= NULL
))
624 length
+= eigrp_add_authTLV_MD5_to_stream(ep
->s
,ei
);
626 else if((IF_DEF_PARAMS (ei
->ifp
)->auth_type
== EIGRP_AUTH_TYPE_SHA256
) && (IF_DEF_PARAMS (ei
->ifp
)->auth_keychain
!= NULL
))
628 length
+= eigrp_add_authTLV_SHA256_to_stream(ep
->s
,ei
);
631 /* encode appropriate parameters to Hello packet */
632 if(flags
& EIGRP_HELLO_GRACEFUL_SHUTDOWN
)
633 length
+= eigrp_hello_parameter_encode(ei
, ep
->s
, EIGRP_HELLO_GRACEFUL_SHUTDOWN
);
635 length
+= eigrp_hello_parameter_encode(ei
, ep
->s
, EIGRP_HELLO_NORMAL
);
637 // figure out the version of code we're running
638 length
+= eigrp_sw_version_encode(ep
->s
);
640 if(flags
& EIGRP_HELLO_ADD_SEQUENCE
)
642 length
+= eigrp_sequence_encode(ep
->s
);
643 length
+= eigrp_next_sequence_encode(ep
->s
);
646 // add in the TID list if doing multi-topology
647 length
+= eigrp_tidlist_encode(ep
->s
);
649 /* encode Peer Termination TLV if needed */
650 if(flags
& EIGRP_HELLO_GRACEFUL_SHUTDOWN_NBR
)
651 length
+= eigrp_peer_termination_encode(ep
->s
, nbr_addr
);
656 // set soruce address for the hello packet
657 ep
->dst
.s_addr
= addr
;
659 if((IF_DEF_PARAMS (ei
->ifp
)->auth_type
== EIGRP_AUTH_TYPE_MD5
) && (IF_DEF_PARAMS (ei
->ifp
)->auth_keychain
!= NULL
))
661 eigrp_make_md5_digest(ei
,ep
->s
, EIGRP_AUTH_BASIC_HELLO_FLAG
);
663 else if((IF_DEF_PARAMS (ei
->ifp
)->auth_type
== EIGRP_AUTH_TYPE_SHA256
) && (IF_DEF_PARAMS (ei
->ifp
)->auth_keychain
!= NULL
))
665 eigrp_make_sha256_digest(ei
,ep
->s
, EIGRP_AUTH_BASIC_HELLO_FLAG
);
669 eigrp_packet_checksum(ei
, ep
->s
, length
);
676 * @fn eigrp_hello_send
678 * @param[in] nbr neighbor the ACK should be sent to
683 * Send (unicast) a hello packet with the destination address
684 * associated with the neighbor. The eigrp header ACK feild will be
685 * updated to the neighbor's sequence number to acknolodge any
686 * outstanding packets
689 eigrp_hello_send_ack (struct eigrp_neighbor
*nbr
)
691 struct eigrp_packet
*ep
;
693 /* if packet succesfully created, add it to the interface queue */
694 ep
= eigrp_hello_encode(nbr
->ei
, nbr
->src
.s_addr
, nbr
->recv_sequence_number
, EIGRP_HELLO_NORMAL
, NULL
);
698 if (IS_DEBUG_EIGRP_PACKET(0, SEND
))
699 zlog_debug("Queueing [Hello] Ack Seq [%u] nbr [%s]",
700 nbr
->recv_sequence_number
, inet_ntoa(nbr
->src
));
702 /* Add packet to the top of the interface output queue*/
703 eigrp_fifo_push_head(nbr
->ei
->obuf
, ep
);
705 /* Hook thread to write packet. */
706 if (nbr
->ei
->on_write_q
== 0)
708 listnode_add(nbr
->ei
->eigrp
->oi_write_q
, nbr
->ei
);
709 nbr
->ei
->on_write_q
= 1;
711 if (nbr
->ei
->eigrp
->t_write
== NULL
)
712 nbr
->ei
->eigrp
->t_write
=
713 thread_add_write(master
, eigrp_write
, nbr
->ei
->eigrp
, nbr
->ei
->eigrp
->fd
);
718 * @fn eigrp_hello_send
720 * @param[in] ei pointer to interface hello should be sent
721 * @param[in] flags type of hello packet
722 * @param[in] nbr_addr pointer to neighbor address for Peer Termination TLV
727 * Build and enqueue a generic (multicast) periodic hello packet for
728 * sending. If no packets are currently queues, the packet will be
732 eigrp_hello_send (struct eigrp_interface
*ei
, u_char flags
, struct in_addr
*nbr_addr
)
734 struct eigrp_packet
*ep
= NULL
;
736 /* If this is passive interface, do not send EIGRP Hello.
737 if ((EIGRP_IF_PASSIVE_STATUS (ei) == EIGRP_IF_PASSIVE) ||
738 (ei->type != EIGRP_IFTYPE_NBMA))
742 if (IS_DEBUG_EIGRP_PACKET(0, SEND
))
743 zlog_debug("Queueing [Hello] Interface(%s)", IF_NAME(ei
));
745 /* if packet was succesfully created, then add it to the interface queue */
746 ep
= eigrp_hello_encode(ei
, htonl(EIGRP_MULTICAST_ADDRESS
), 0, flags
, nbr_addr
);
750 // Add packet to the top of the interface output queue
751 eigrp_fifo_push_head(ei
->obuf
, ep
);
753 /* Hook thread to write packet. */
754 if (ei
->on_write_q
== 0)
756 listnode_add(ei
->eigrp
->oi_write_q
, ei
);
760 if (ei
->eigrp
->t_write
== NULL
)
762 if(flags
& EIGRP_HELLO_GRACEFUL_SHUTDOWN
)
765 thread_execute(master
, eigrp_write
, ei
->eigrp
, ei
->eigrp
->fd
);
770 thread_add_write(master
, eigrp_write
, ei
->eigrp
, ei
->eigrp
->fd
);