-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy patheigrp_siaquery.c
107 lines (90 loc) · 3.03 KB
/
eigrp_siaquery.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* EIGRP Sending and Receiving EIGRP SIA-Query Packets.
* Copyright (C) 2013-2014
* Authors:
* Donnie Savage
* Jan Janovic
* Matej Perina
* Peter Orsag
* Peter Paluch
*/
#include "eigrpd/eigrpd.h"
#include "eigrpd/eigrp_structs.h"
#include "eigrpd/eigrp_neighbor.h"
#include "eigrpd/eigrp_packet.h"
#include "eigrpd/eigrp_auth.h"
#include "eigrpd/eigrp_topology.h"
#include "eigrpd/eigrp_fsm.h"
/* EIGRP SIA-QUERY read function */
void eigrp_siaquery_receive(eigrp_instance_t *eigrp, eigrp_neighbor_t *nbr,
struct eigrp_header *eigrph, struct stream *pkt,
eigrp_interface_t *ei, int length)
{
eigrp_fsm_action_message_t msg;
eigrp_route_descriptor_t *route;
/* increment statistics. */
ei->stats.rcvd.siaQuery++;
/* get neighbor struct */
nbr->recv_sequence_number = ntohl(eigrph->sequence);
// process all TLVs in the packet
while (pkt->endp > pkt->getp) {
route = (nbr->tlv_decoder)(eigrp, nbr, pkt, length);
// should have got route off the packet, but one never know
if (route) {
msg.packet_type = EIGRP_OPC_SIAQUERY;
msg.eigrp = eigrp;
msg.data_type = EIGRP_INT;
msg.adv_router = nbr;
msg.route = route;
msg.metrics = route->metric;
msg.prefix = route->prefix;
eigrp_fsm_event(&msg);
} else {
// neighbor sent corrupted packet - flush remaining
// packet
break;
}
}
eigrp_hello_send_ack(nbr);
}
void eigrp_siaquery_send(eigrp_instance_t *eigrp, eigrp_neighbor_t *nbr,
eigrp_prefix_descriptor_t *prefix)
{
eigrp_packet_t *packet;
eigrp_route_descriptor_t *route;
uint16_t length = EIGRP_HEADER_LEN;
struct list *successors;
packet = eigrp_packet_new(EIGRP_PACKET_MTU(nbr->ei->ifp->mtu), nbr);
/* Prepare EIGRP INIT UPDATE header */
eigrp_packet_header_init(EIGRP_OPC_SIAQUERY, nbr->ei->eigrp, packet->s, 0,
nbr->ei->eigrp->sequence_number, 0);
// encode Authentication TLV, if needed
if ((nbr->ei->params.auth_type == EIGRP_AUTH_TYPE_MD5)
&& (nbr->ei->params.auth_keychain != NULL)) {
length += eigrp_add_authTLV_MD5_encode(packet->s, nbr->ei);
}
// grab the route from the prefix so we can get the metrics we need
successors = eigrp_topology_get_successor(prefix);
assert(successors); // If this is NULL somebody poked us in the eye.
route = listnode_head(successors);
length += (nbr->tlv_encoder)(eigrp, nbr, packet->s, route);
if ((nbr->ei->params.auth_type == EIGRP_AUTH_TYPE_MD5)
&& (nbr->ei->params.auth_keychain != NULL)) {
eigrp_make_md5_digest(nbr->ei, packet->s, EIGRP_AUTH_UPDATE_FLAG);
}
/* EIGRP Checksum */
eigrp_packet_checksum(nbr->ei, packet->s, length);
packet->length = length;
eigrp_addr_copy(&packet->dst, &nbr->src);
/*This ack number we await from neighbor*/
packet->sequence_number = nbr->ei->eigrp->sequence_number;
if (nbr->state == EIGRP_NEIGHBOR_UP) {
/*Put packet to retransmission queue*/
eigrp_packet_enqueue(nbr->retrans_queue, packet);
if (nbr->retrans_queue->count == 1) {
eigrp_packet_send_reliably(eigrp, nbr);
}
} else
eigrp_packet_free(packet);
}