1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * EIGRP Sending and Receiving EIGRP Query Packets.
4 * Copyright (C) 2013-2014
21 #include "sockunion.h"
29 #include "eigrpd/eigrp_structs.h"
30 #include "eigrpd/eigrpd.h"
31 #include "eigrpd/eigrp_interface.h"
32 #include "eigrpd/eigrp_neighbor.h"
33 #include "eigrpd/eigrp_packet.h"
34 #include "eigrpd/eigrp_zebra.h"
35 #include "eigrpd/eigrp_vty.h"
36 #include "eigrpd/eigrp_dump.h"
37 #include "eigrpd/eigrp_macros.h"
38 #include "eigrpd/eigrp_topology.h"
39 #include "eigrpd/eigrp_fsm.h"
41 uint32_t eigrp_query_send_all(struct eigrp
*eigrp
)
43 struct eigrp_interface
*iface
;
44 struct listnode
*node
, *node2
, *nnode2
;
45 struct eigrp_prefix_descriptor
*pe
;
49 zlog_debug("EIGRP Routing Process not enabled");
54 for (ALL_LIST_ELEMENTS_RO(eigrp
->eiflist
, node
, iface
)) {
55 eigrp_send_query(iface
);
59 for (ALL_LIST_ELEMENTS(eigrp
->topology_changes_internalIPV4
, node2
,
61 if (pe
->req_action
& EIGRP_FSM_NEED_QUERY
) {
62 pe
->req_action
&= ~EIGRP_FSM_NEED_QUERY
;
63 listnode_delete(eigrp
->topology_changes_internalIPV4
,
71 /*EIGRP QUERY read function*/
72 void eigrp_query_receive(struct eigrp
*eigrp
, struct ip
*iph
,
73 struct eigrp_header
*eigrph
, struct stream
*s
,
74 struct eigrp_interface
*ei
, int size
)
76 struct eigrp_neighbor
*nbr
;
77 struct TLV_IPv4_Internal_type
*tlv
;
78 struct prefix dest_addr
;
83 /* increment statistics. */
86 /* get neighbor struct */
87 nbr
= eigrp_nbr_get(ei
, eigrph
, iph
);
89 /* neighbor must be valid, eigrp_nbr_get creates if none existed */
92 nbr
->recv_sequence_number
= ntohl(eigrph
->sequence
);
94 while (s
->endp
> s
->getp
) {
95 type
= stream_getw(s
);
97 case EIGRP_TLV_IPv4_INT
:
98 stream_set_getp(s
, s
->getp
- sizeof(uint16_t));
100 tlv
= eigrp_read_ipv4_tlv(s
);
102 dest_addr
.family
= AF_INET
;
103 dest_addr
.u
.prefix4
= tlv
->destination
;
104 dest_addr
.prefixlen
= tlv
->prefix_length
;
105 struct eigrp_prefix_descriptor
*dest
=
106 eigrp_topology_table_lookup_ipv4(
107 eigrp
->topology_table
, &dest_addr
);
109 /* If the destination exists (it should, but one never
112 struct eigrp_fsm_action_message msg
;
113 struct eigrp_route_descriptor
*entry
=
114 eigrp_route_descriptor_lookup(
116 msg
.packet_type
= EIGRP_OPC_QUERY
;
118 msg
.data_type
= EIGRP_INT
;
119 msg
.adv_router
= nbr
;
120 msg
.metrics
= tlv
->metric
;
123 eigrp_fsm_event(&msg
);
125 eigrp_IPv4_InternalTLV_free(tlv
);
128 case EIGRP_TLV_IPv4_EXT
:
129 /* DVS: processing of external routes needs packet and fsm work.
130 * for now, lets just not creash the box
133 length
= stream_getw(s
);
134 // -2 for type, -2 for len
135 for (length
-= 4; length
; length
--) {
136 (void)stream_getc(s
);
140 eigrp_hello_send_ack(nbr
);
141 eigrp_query_send_all(eigrp
);
142 eigrp_update_send_all(eigrp
, nbr
->ei
);
145 void eigrp_send_query(struct eigrp_interface
*ei
)
147 struct eigrp_packet
*ep
= NULL
;
148 uint16_t length
= EIGRP_HEADER_LEN
;
149 struct listnode
*node
, *nnode
, *node2
, *nnode2
;
150 struct eigrp_neighbor
*nbr
;
151 struct eigrp_prefix_descriptor
*pe
;
152 bool has_tlv
= false;
153 bool new_packet
= true;
154 uint16_t eigrp_mtu
= EIGRP_PACKET_MTU(ei
->ifp
->mtu
);
156 for (ALL_LIST_ELEMENTS(ei
->eigrp
->topology_changes_internalIPV4
, node
,
158 if (!(pe
->req_action
& EIGRP_FSM_NEED_QUERY
))
162 ep
= eigrp_packet_new(eigrp_mtu
, NULL
);
164 /* Prepare EIGRP INIT UPDATE header */
165 eigrp_packet_header_init(EIGRP_OPC_QUERY
, ei
->eigrp
,
167 ei
->eigrp
->sequence_number
, 0);
169 // encode Authentication TLV, if needed
170 if ((ei
->params
.auth_type
== EIGRP_AUTH_TYPE_MD5
)
171 && (ei
->params
.auth_keychain
!= NULL
)) {
172 length
+= eigrp_add_authTLV_MD5_to_stream(ep
->s
,
178 length
+= eigrp_add_internalTLV_to_stream(ep
->s
, pe
);
180 for (ALL_LIST_ELEMENTS(ei
->nbrs
, node2
, nnode2
, nbr
)) {
181 if (nbr
->state
== EIGRP_NEIGHBOR_UP
)
182 listnode_add(pe
->rij
, nbr
);
185 if (length
+ EIGRP_TLV_MAX_IPV4_BYTE
> eigrp_mtu
) {
186 if ((ei
->params
.auth_type
== EIGRP_AUTH_TYPE_MD5
)
187 && ei
->params
.auth_keychain
!= NULL
) {
188 eigrp_make_md5_digest(ei
, ep
->s
,
189 EIGRP_AUTH_UPDATE_FLAG
);
192 eigrp_packet_checksum(ei
, ep
->s
, length
);
195 ep
->dst
.s_addr
= htonl(EIGRP_MULTICAST_ADDRESS
);
197 ep
->sequence_number
= ei
->eigrp
->sequence_number
;
198 ei
->eigrp
->sequence_number
++;
200 for (ALL_LIST_ELEMENTS(ei
->nbrs
, node2
, nnode2
, nbr
)) {
201 struct eigrp_packet
*dup
;
203 if (nbr
->state
!= EIGRP_NEIGHBOR_UP
)
206 dup
= eigrp_packet_duplicate(ep
, nbr
);
207 /*Put packet to retransmission queue*/
208 eigrp_fifo_push(nbr
->retrans_queue
, dup
);
210 if (nbr
->retrans_queue
->count
== 1)
211 eigrp_send_packet_reliably(nbr
);
216 eigrp_packet_free(ep
);
225 if ((ei
->params
.auth_type
== EIGRP_AUTH_TYPE_MD5
)
226 && ei
->params
.auth_keychain
!= NULL
)
227 eigrp_make_md5_digest(ei
, ep
->s
, EIGRP_AUTH_UPDATE_FLAG
);
231 eigrp_packet_checksum(ei
, ep
->s
, length
);
234 ep
->dst
.s_addr
= htonl(EIGRP_MULTICAST_ADDRESS
);
236 /*This ack number we await from neighbor*/
237 ep
->sequence_number
= ei
->eigrp
->sequence_number
;
238 ei
->eigrp
->sequence_number
++;
240 for (ALL_LIST_ELEMENTS(ei
->nbrs
, node2
, nnode2
, nbr
)) {
241 struct eigrp_packet
*dup
;
243 if (nbr
->state
!= EIGRP_NEIGHBOR_UP
)
246 dup
= eigrp_packet_duplicate(ep
, nbr
);
247 /*Put packet to retransmission queue*/
248 eigrp_fifo_push(nbr
->retrans_queue
, dup
);
250 if (nbr
->retrans_queue
->count
== 1)
251 eigrp_send_packet_reliably(nbr
);
254 eigrp_packet_free(ep
);