]> git.proxmox.com Git - mirror_frr.git/blob - eigrpd/eigrp_query.c
Merge pull request #12798 from donaldsharp/rib_match_multicast
[mirror_frr.git] / eigrpd / eigrp_query.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3 * EIGRP Sending and Receiving EIGRP Query Packets.
4 * Copyright (C) 2013-2014
5 * Authors:
6 * Donnie Savage
7 * Jan Janovic
8 * Matej Perina
9 * Peter Orsag
10 * Peter Paluch
11 */
12
13 #include <zebra.h>
14
15 #include "thread.h"
16 #include "memory.h"
17 #include "linklist.h"
18 #include "prefix.h"
19 #include "if.h"
20 #include "table.h"
21 #include "sockunion.h"
22 #include "stream.h"
23 #include "log.h"
24 #include "sockopt.h"
25 #include "checksum.h"
26 #include "md5.h"
27 #include "vty.h"
28
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"
40
41 uint32_t eigrp_query_send_all(struct eigrp *eigrp)
42 {
43 struct eigrp_interface *iface;
44 struct listnode *node, *node2, *nnode2;
45 struct eigrp_prefix_descriptor *pe;
46 uint32_t counter;
47
48 if (eigrp == NULL) {
49 zlog_debug("EIGRP Routing Process not enabled");
50 return 0;
51 }
52
53 counter = 0;
54 for (ALL_LIST_ELEMENTS_RO(eigrp->eiflist, node, iface)) {
55 eigrp_send_query(iface);
56 counter++;
57 }
58
59 for (ALL_LIST_ELEMENTS(eigrp->topology_changes_internalIPV4, node2,
60 nnode2, pe)) {
61 if (pe->req_action & EIGRP_FSM_NEED_QUERY) {
62 pe->req_action &= ~EIGRP_FSM_NEED_QUERY;
63 listnode_delete(eigrp->topology_changes_internalIPV4,
64 pe);
65 }
66 }
67
68 return counter;
69 }
70
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)
75 {
76 struct eigrp_neighbor *nbr;
77 struct TLV_IPv4_Internal_type *tlv;
78 struct prefix dest_addr;
79
80 uint16_t type;
81 uint16_t length;
82
83 /* increment statistics. */
84 ei->query_in++;
85
86 /* get neighbor struct */
87 nbr = eigrp_nbr_get(ei, eigrph, iph);
88
89 /* neighbor must be valid, eigrp_nbr_get creates if none existed */
90 assert(nbr);
91
92 nbr->recv_sequence_number = ntohl(eigrph->sequence);
93
94 while (s->endp > s->getp) {
95 type = stream_getw(s);
96 switch (type) {
97 case EIGRP_TLV_IPv4_INT:
98 stream_set_getp(s, s->getp - sizeof(uint16_t));
99
100 tlv = eigrp_read_ipv4_tlv(s);
101
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);
108
109 /* If the destination exists (it should, but one never
110 * know)*/
111 if (dest != NULL) {
112 struct eigrp_fsm_action_message msg;
113 struct eigrp_route_descriptor *entry =
114 eigrp_route_descriptor_lookup(
115 dest->entries, nbr);
116 msg.packet_type = EIGRP_OPC_QUERY;
117 msg.eigrp = eigrp;
118 msg.data_type = EIGRP_INT;
119 msg.adv_router = nbr;
120 msg.metrics = tlv->metric;
121 msg.entry = entry;
122 msg.prefix = dest;
123 eigrp_fsm_event(&msg);
124 }
125 eigrp_IPv4_InternalTLV_free(tlv);
126 break;
127
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
131 */
132 default:
133 length = stream_getw(s);
134 // -2 for type, -2 for len
135 for (length -= 4; length; length--) {
136 (void)stream_getc(s);
137 }
138 }
139 }
140 eigrp_hello_send_ack(nbr);
141 eigrp_query_send_all(eigrp);
142 eigrp_update_send_all(eigrp, nbr->ei);
143 }
144
145 void eigrp_send_query(struct eigrp_interface *ei)
146 {
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);
155
156 for (ALL_LIST_ELEMENTS(ei->eigrp->topology_changes_internalIPV4, node,
157 nnode, pe)) {
158 if (!(pe->req_action & EIGRP_FSM_NEED_QUERY))
159 continue;
160
161 if (new_packet) {
162 ep = eigrp_packet_new(eigrp_mtu, NULL);
163
164 /* Prepare EIGRP INIT UPDATE header */
165 eigrp_packet_header_init(EIGRP_OPC_QUERY, ei->eigrp,
166 ep->s, 0,
167 ei->eigrp->sequence_number, 0);
168
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,
173 ei);
174 }
175 new_packet = false;
176 }
177
178 length += eigrp_add_internalTLV_to_stream(ep->s, pe);
179 has_tlv = true;
180 for (ALL_LIST_ELEMENTS(ei->nbrs, node2, nnode2, nbr)) {
181 if (nbr->state == EIGRP_NEIGHBOR_UP)
182 listnode_add(pe->rij, nbr);
183 }
184
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);
190 }
191
192 eigrp_packet_checksum(ei, ep->s, length);
193 ep->length = length;
194
195 ep->dst.s_addr = htonl(EIGRP_MULTICAST_ADDRESS);
196
197 ep->sequence_number = ei->eigrp->sequence_number;
198 ei->eigrp->sequence_number++;
199
200 for (ALL_LIST_ELEMENTS(ei->nbrs, node2, nnode2, nbr)) {
201 struct eigrp_packet *dup;
202
203 if (nbr->state != EIGRP_NEIGHBOR_UP)
204 continue;
205
206 dup = eigrp_packet_duplicate(ep, nbr);
207 /*Put packet to retransmission queue*/
208 eigrp_fifo_push(nbr->retrans_queue, dup);
209
210 if (nbr->retrans_queue->count == 1)
211 eigrp_send_packet_reliably(nbr);
212 }
213
214 has_tlv = false;
215 length = 0;
216 eigrp_packet_free(ep);
217 ep = NULL;
218 new_packet = true;
219 }
220 }
221
222 if (!has_tlv)
223 return;
224
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);
228
229
230 /* EIGRP Checksum */
231 eigrp_packet_checksum(ei, ep->s, length);
232
233 ep->length = length;
234 ep->dst.s_addr = htonl(EIGRP_MULTICAST_ADDRESS);
235
236 /*This ack number we await from neighbor*/
237 ep->sequence_number = ei->eigrp->sequence_number;
238 ei->eigrp->sequence_number++;
239
240 for (ALL_LIST_ELEMENTS(ei->nbrs, node2, nnode2, nbr)) {
241 struct eigrp_packet *dup;
242
243 if (nbr->state != EIGRP_NEIGHBOR_UP)
244 continue;
245
246 dup = eigrp_packet_duplicate(ep, nbr);
247 /*Put packet to retransmission queue*/
248 eigrp_fifo_push(nbr->retrans_queue, dup);
249
250 if (nbr->retrans_queue->count == 1)
251 eigrp_send_packet_reliably(nbr);
252 }
253
254 eigrp_packet_free(ep);
255 }