]> git.proxmox.com Git - mirror_frr.git/blame - eigrpd/eigrp_query.c
Merge pull request #12798 from donaldsharp/rib_match_multicast
[mirror_frr.git] / eigrpd / eigrp_query.c
CommitLineData
acddc0ed 1// SPDX-License-Identifier: GPL-2.0-or-later
7f57883e
DS
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
7f57883e
DS
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"
7f57883e 40
d7c0a89a 41uint32_t eigrp_query_send_all(struct eigrp *eigrp)
7f57883e 42{
d62a17ae 43 struct eigrp_interface *iface;
44 struct listnode *node, *node2, *nnode2;
dc4accdd 45 struct eigrp_prefix_descriptor *pe;
d7c0a89a 46 uint32_t counter;
d62a17ae 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;
7f57883e
DS
69}
70
71/*EIGRP QUERY read function*/
d62a17ae 72void eigrp_query_receive(struct eigrp *eigrp, struct ip *iph,
73 struct eigrp_header *eigrph, struct stream *s,
74 struct eigrp_interface *ei, int size)
7f57883e 75{
d62a17ae 76 struct eigrp_neighbor *nbr;
77 struct TLV_IPv4_Internal_type *tlv;
476a1469 78 struct prefix dest_addr;
d62a17ae 79
d7c0a89a
QY
80 uint16_t type;
81 uint16_t length;
d62a17ae 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);
c283f389
DS
96 switch (type) {
97 case EIGRP_TLV_IPv4_INT:
d7c0a89a 98 stream_set_getp(s, s->getp - sizeof(uint16_t));
d62a17ae 99
100 tlv = eigrp_read_ipv4_tlv(s);
101
102 dest_addr.family = AF_INET;
476a1469 103 dest_addr.u.prefix4 = tlv->destination;
d62a17ae 104 dest_addr.prefixlen = tlv->prefix_length;
dc4accdd 105 struct eigrp_prefix_descriptor *dest =
d62a17ae 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) {
92035b1d 112 struct eigrp_fsm_action_message msg;
dc4accdd
DS
113 struct eigrp_route_descriptor *entry =
114 eigrp_route_descriptor_lookup(
115 dest->entries, nbr);
92035b1d
DS
116 msg.packet_type = EIGRP_OPC_QUERY;
117 msg.eigrp = eigrp;
7cfa4322 118 msg.data_type = EIGRP_INT;
92035b1d 119 msg.adv_router = nbr;
db6ec9ff 120 msg.metrics = tlv->metric;
92035b1d
DS
121 msg.entry = entry;
122 msg.prefix = dest;
6118272f 123 eigrp_fsm_event(&msg);
d62a17ae 124 }
125 eigrp_IPv4_InternalTLV_free(tlv);
c283f389
DS
126 break;
127
128 case EIGRP_TLV_IPv4_EXT:
996c9314
LB
129 /* DVS: processing of external routes needs packet and fsm work.
130 * for now, lets just not creash the box
131 */
c283f389
DS
132 default:
133 length = stream_getw(s);
134 // -2 for type, -2 for len
996c9314 135 for (length -= 4; length; length--) {
c283f389
DS
136 (void)stream_getc(s);
137 }
d62a17ae 138 }
139 }
140 eigrp_hello_send_ack(nbr);
141 eigrp_query_send_all(eigrp);
142 eigrp_update_send_all(eigrp, nbr->ei);
7f57883e
DS
143}
144
d62a17ae 145void eigrp_send_query(struct eigrp_interface *ei)
7f57883e 146{
c3d4dea2 147 struct eigrp_packet *ep = NULL;
d7c0a89a 148 uint16_t length = EIGRP_HEADER_LEN;
d62a17ae 149 struct listnode *node, *nnode, *node2, *nnode2;
150 struct eigrp_neighbor *nbr;
dc4accdd 151 struct eigrp_prefix_descriptor *pe;
d4395853 152 bool has_tlv = false;
c3d4dea2 153 bool new_packet = true;
9378632f 154 uint16_t eigrp_mtu = EIGRP_PACKET_MTU(ei->ifp->mtu);
d62a17ae 155
d62a17ae 156 for (ALL_LIST_ELEMENTS(ei->eigrp->topology_changes_internalIPV4, node,
157 nnode, pe)) {
68b7dd07
DS
158 if (!(pe->req_action & EIGRP_FSM_NEED_QUERY))
159 continue;
160
c3d4dea2 161 if (new_packet) {
ca83a1ab 162 ep = eigrp_packet_new(eigrp_mtu, NULL);
c3d4dea2
DS
163
164 /* Prepare EIGRP INIT UPDATE header */
996c9314
LB
165 eigrp_packet_header_init(EIGRP_OPC_QUERY, ei->eigrp,
166 ep->s, 0,
c3d4dea2
DS
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)) {
996c9314
LB
172 length += eigrp_add_authTLV_MD5_to_stream(ep->s,
173 ei);
c3d4dea2
DS
174 }
175 new_packet = false;
176 }
177
68b7dd07 178 length += eigrp_add_internalTLV_to_stream(ep->s, pe);
c3d4dea2 179 has_tlv = true;
68b7dd07 180 for (ALL_LIST_ELEMENTS(ei->nbrs, node2, nnode2, nbr)) {
c3d4dea2 181 if (nbr->state == EIGRP_NEIGHBOR_UP)
68b7dd07 182 listnode_add(pe->rij, nbr);
c3d4dea2
DS
183 }
184
ca83a1ab 185 if (length + EIGRP_TLV_MAX_IPV4_BYTE > eigrp_mtu) {
c3d4dea2
DS
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);
d62a17ae 212 }
c3d4dea2
DS
213
214 has_tlv = false;
215 length = 0;
216 eigrp_packet_free(ep);
217 ep = NULL;
218 new_packet = true;
d62a17ae 219 }
220 }
221
11b88ecf 222 if (!has_tlv)
d62a17ae 223 return;
d62a17ae 224
b748db67 225 if ((ei->params.auth_type == EIGRP_AUTH_TYPE_MD5)
c3d4dea2 226 && ei->params.auth_keychain != NULL)
d62a17ae 227 eigrp_make_md5_digest(ei, ep->s, EIGRP_AUTH_UPDATE_FLAG);
c3d4dea2 228
d62a17ae 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;
68b7dd07 238 ei->eigrp->sequence_number++;
d62a17ae 239
240 for (ALL_LIST_ELEMENTS(ei->nbrs, node2, nnode2, nbr)) {
c3d4dea2 241 struct eigrp_packet *dup;
d62a17ae 242
c3d4dea2
DS
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);
d62a17ae 252 }
253
c3d4dea2 254 eigrp_packet_free(ep);
7f57883e 255}