]> git.proxmox.com Git - mirror_frr.git/blame - eigrpd/eigrp_reply.c
eigrp: Initial Commit
[mirror_frr.git] / eigrpd / eigrp_reply.c
CommitLineData
7f57883e
DS
1/*
2 * EIGRP Sending and Receiving EIGRP Reply Packets.
3 * Copyright (C) 2013-2016
4 * Authors:
5 * Donnie Savage
6 * Jan Janovic
7 * Matej Perina
8 * Peter Orsag
9 * Peter Paluch
10 * Frantisek Gazo
11 * Tomas Hvorkovy
12 * Martin Kontsek
13 * Lukas Koribsky
14 *
15 * This file is part of GNU Zebra.
16 *
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
20 * later version.
21 *
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.
26 *
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
30 * 02111-1307, USA.
31 */
32
33#include <zebra.h>
34
35#include "thread.h"
36#include "memory.h"
37#include "linklist.h"
38#include "prefix.h"
39#include "if.h"
40#include "table.h"
41#include "sockunion.h"
42#include "stream.h"
43#include "log.h"
44#include "sockopt.h"
45#include "checksum.h"
46#include "md5.h"
47#include "vty.h"
48#include "keychain.h"
49#include "plist.h"
50
51#include "eigrpd/eigrp_structs.h"
52#include "eigrpd/eigrpd.h"
53#include "eigrpd/eigrp_interface.h"
54#include "eigrpd/eigrp_neighbor.h"
55#include "eigrpd/eigrp_packet.h"
56#include "eigrpd/eigrp_zebra.h"
57#include "eigrpd/eigrp_vty.h"
58#include "eigrpd/eigrp_dump.h"
59#include "eigrpd/eigrp_macros.h"
60#include "eigrpd/eigrp_topology.h"
61#include "eigrpd/eigrp_fsm.h"
62#include "eigrpd/eigrp_memory.h"
63
64void
65eigrp_send_reply (struct eigrp_neighbor *nbr, struct eigrp_prefix_entry *pe)
66{
67 struct eigrp_packet *ep;
68 u_int16_t length = EIGRP_HEADER_LEN;
69
70 struct access_list *alist;
71 struct prefix_list *plist;
72 struct access_list *alist_i;
73 struct prefix_list *plist_i;
74 struct eigrp *e;
75 struct eigrp_prefix_entry *pe2;
76
77 //TODO: Work in progress
78 /* Filtering */
79 /* get list from eigrp process */
80 e = eigrp_lookup();
81 pe2 = XCALLOC(MTYPE_EIGRP_PREFIX_ENTRY, sizeof(struct eigrp_prefix_entry));
82 memcpy(pe2,pe,sizeof(struct eigrp_prefix_entry));
83 /* Get access-lists and prefix-lists from process and interface */
84 alist = e->list[EIGRP_FILTER_OUT];
85 plist = e->prefix[EIGRP_FILTER_OUT];
86 alist_i = nbr->ei->list[EIGRP_FILTER_OUT];
87 plist_i = nbr->ei->prefix[EIGRP_FILTER_OUT];
88 zlog_info("REPLY Send: Filtering");
89
90 zlog_info("REPLY SEND Prefix: %s", inet_ntoa(nbr->src));
91 /* Check if any list fits */
92 if ((alist && access_list_apply (alist, (struct prefix *) pe2->destination_ipv4) == FILTER_DENY)||
93 (plist && prefix_list_apply (plist, (struct prefix *) pe2->destination_ipv4) == FILTER_DENY)||
94 (alist_i && access_list_apply (alist_i, (struct prefix *) pe2->destination_ipv4) == FILTER_DENY)||
95 (plist_i && prefix_list_apply (plist_i, (struct prefix *) pe2->destination_ipv4) == FILTER_DENY))
96 {
97 zlog_info("REPLY SEND: Setting Metric to max");
98 pe2->reported_metric.delay = EIGRP_MAX_METRIC;
99
100 } else {
101 zlog_info("REPLY SEND: Not setting metric");
102 }
103
104
105 /*
106 * End of filtering
107 */
108
109 ep = eigrp_packet_new(nbr->ei->ifp->mtu);
110
111 /* Prepare EIGRP INIT UPDATE header */
112 eigrp_packet_header_init(EIGRP_OPC_REPLY, nbr->ei, ep->s, 0,
113 nbr->ei->eigrp->sequence_number, 0);
114
115 // encode Authentication TLV, if needed
116 if((IF_DEF_PARAMS (nbr->ei->ifp)->auth_type == EIGRP_AUTH_TYPE_MD5) && (IF_DEF_PARAMS (nbr->ei->ifp)->auth_keychain != NULL))
117 {
118 length += eigrp_add_authTLV_MD5_to_stream(ep->s,nbr->ei);
119 }
120
121
122 length += eigrp_add_internalTLV_to_stream(ep->s, pe2);
123
124 if((IF_DEF_PARAMS (nbr->ei->ifp)->auth_type == EIGRP_AUTH_TYPE_MD5) && (IF_DEF_PARAMS (nbr->ei->ifp)->auth_keychain != NULL))
125 {
126 eigrp_make_md5_digest(nbr->ei,ep->s, EIGRP_AUTH_UPDATE_FLAG);
127 }
128
129 /* EIGRP Checksum */
130 eigrp_packet_checksum(nbr->ei, ep->s, length);
131
132 ep->length = length;
133 ep->dst.s_addr = nbr->src.s_addr;
134
135 /*This ack number we await from neighbor*/
136 ep->sequence_number = nbr->ei->eigrp->sequence_number;
137
138 /*Put packet to retransmission queue*/
139 eigrp_fifo_push_head(nbr->retrans_queue, ep);
140
141 if (nbr->retrans_queue->count == 1)
142 {
143 eigrp_send_packet_reliably(nbr);
144 }
145}
146
147/*EIGRP REPLY read function*/
148void
149eigrp_reply_receive (struct eigrp *eigrp, struct ip *iph, struct eigrp_header *eigrph,
150 struct stream * s, struct eigrp_interface *ei, int size)
151{
152 struct eigrp_neighbor *nbr;
153 struct TLV_IPv4_Internal_type *tlv;
154
155 struct access_list *alist;
156 struct prefix_list *plist;
157 struct access_list *alist_i;
158 struct prefix_list *plist_i;
159 struct eigrp *e;
160
161 u_int16_t type;
162
163 /* increment statistics. */
164 ei->reply_in++;
165
166 /* get neighbor struct */
167 nbr = eigrp_nbr_get(ei, eigrph, iph);
168
169 /* neighbor must be valid, eigrp_nbr_get creates if none existed */
170 assert(nbr);
171
172 nbr->recv_sequence_number = ntohl(eigrph->sequence);
173
174 while (s->endp > s->getp)
175 {
176 type = stream_getw(s);
177 if (type == EIGRP_TLV_IPv4_INT)
178 {
179 stream_set_getp(s, s->getp - sizeof(u_int16_t));
180
181 tlv = eigrp_read_ipv4_tlv(s);
182
183 struct prefix_ipv4 *dest_addr;
184 dest_addr = prefix_ipv4_new();
185 dest_addr->prefix = tlv->destination;
186 dest_addr->prefixlen = tlv->prefix_length;
187 struct eigrp_prefix_entry *dest = eigrp_topology_table_lookup_ipv4(
188 eigrp->topology_table, dest_addr);
189 /*
190 * Destination must exists
191 */
192 assert(dest);
193
194 struct eigrp_fsm_action_message *msg;
195 msg = XCALLOC(MTYPE_EIGRP_FSM_MSG,
196 sizeof(struct eigrp_fsm_action_message));
197 struct eigrp_neighbor_entry *entry = eigrp_prefix_entry_lookup(
198 dest->entries, nbr);
199
200 /*
201 * Filtering
202 */
203 //TODO: Work in progress
204 /* get list from eigrp process */
205 e = eigrp_lookup();
206 /* Get access-lists and prefix-lists from process and interface */
207 alist = e->list[EIGRP_FILTER_IN];
208 plist = e->prefix[EIGRP_FILTER_IN];
209 alist_i = ei->list[EIGRP_FILTER_IN];
210 plist_i = ei->prefix[EIGRP_FILTER_IN];
211 zlog_info("REPLY Receive: Filtering");
212 zlog_info("REPLY RECEIVE Prefix: %s", inet_ntoa(dest_addr->prefix));
213 /* Check if any list fits */
214 if ((alist && access_list_apply (alist,
215 (struct prefix *) dest_addr) == FILTER_DENY)||
216 (plist && prefix_list_apply (plist,
217 (struct prefix *) dest_addr) == FILTER_DENY)||
218 (alist_i && access_list_apply (alist_i,
219 (struct prefix *) dest_addr) == FILTER_DENY)||
220 (plist_i && prefix_list_apply (plist_i,
221 (struct prefix *) dest_addr) == FILTER_DENY))
222 {
223 zlog_info("REPLY RECEIVE: Setting metric to max");
224 tlv->metric.delay = EIGRP_MAX_METRIC;
225 zlog_info("REPLY RECEIVE Prefix: %s", inet_ntoa(dest_addr->prefix));
226 } else {
227 zlog_info("REPLY RECEIVE: Not setting metric");
228 }
229 /*
230 * End of filtering
231 */
232
233 msg->packet_type = EIGRP_OPC_REPLY;
234 msg->eigrp = eigrp;
235 msg->data_type = EIGRP_TLV_IPv4_INT;
236 msg->adv_router = nbr;
237 msg->data.ipv4_int_type = tlv;
238 msg->entry = entry;
239 msg->prefix = dest;
240 int event = eigrp_get_fsm_event(msg);
241 eigrp_fsm_event(msg, event);
242
243
244 eigrp_IPv4_InternalTLV_free (tlv);
245 }
246 }
247 eigrp_hello_send_ack(nbr);
248}
249