]> git.proxmox.com Git - mirror_frr.git/blob - eigrpd/eigrp_interface.c
Merge pull request #449 from dwalton76/valgrind-enable
[mirror_frr.git] / eigrpd / eigrp_interface.c
1 /*
2 * EIGRP Interface Functions.
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 "linklist.h"
37 #include "prefix.h"
38 #include "if.h"
39 #include "table.h"
40 #include "memory.h"
41 #include "command.h"
42 #include "stream.h"
43 #include "log.h"
44 #include "keychain.h"
45 #include "vrf.h"
46
47 #include "eigrpd/eigrp_structs.h"
48 #include "eigrpd/eigrpd.h"
49 #include "eigrpd/eigrp_interface.h"
50 #include "eigrpd/eigrp_neighbor.h"
51 #include "eigrpd/eigrp_packet.h"
52 #include "eigrpd/eigrp_zebra.h"
53 #include "eigrpd/eigrp_vty.h"
54 #include "eigrpd/eigrp_network.h"
55 #include "eigrpd/eigrp_topology.h"
56 #include "eigrpd/eigrp_memory.h"
57
58 static void
59 eigrp_delete_from_if (struct interface *, struct eigrp_interface *);
60
61 static void
62 eigrp_add_to_if (struct interface *ifp, struct eigrp_interface *ei)
63 {
64 struct route_node *rn;
65 struct prefix p;
66
67 p = *ei->address;
68 p.prefixlen = IPV4_MAX_PREFIXLEN;
69
70 rn = route_node_get (IF_OIFS (ifp), &p);
71 /* rn->info should either be NULL or equal to this ei
72 * as route_node_get may return an existing node
73 */
74 assert (!rn->info || rn->info == ei);
75 rn->info = ei;
76 }
77
78 struct eigrp_interface *
79 eigrp_if_new (struct eigrp *eigrp, struct interface *ifp, struct prefix *p)
80 {
81 struct eigrp_interface *ei;
82 int i;
83
84 if ((ei = eigrp_if_table_lookup (ifp, p)) == NULL)
85 {
86 ei = XCALLOC (MTYPE_EIGRP_IF, sizeof (struct eigrp_interface));
87 memset (ei, 0, sizeof (struct eigrp_interface));
88 }
89 else
90 return ei;
91
92 /* Set zebra interface pointer. */
93 ei->ifp = ifp;
94 ei->address = p;
95
96 eigrp_add_to_if (ifp, ei);
97 listnode_add (eigrp->eiflist, ei);
98
99 ei->type = EIGRP_IFTYPE_BROADCAST;
100
101 /* Initialize neighbor list. */
102 ei->nbrs = list_new ();
103
104 ei->crypt_seqnum = time (NULL);
105
106 /* Initialize lists */
107 for (i = 0; i < EIGRP_FILTER_MAX; i++)
108 {
109 ei->list[i] = NULL;
110 ei->prefix[i] = NULL;
111 ei->routemap[i] = NULL;
112 }
113
114 return ei;
115 }
116
117 /* lookup ei for specified prefix/ifp */
118 struct eigrp_interface *
119 eigrp_if_table_lookup (struct interface *ifp, struct prefix *prefix)
120 {
121 struct prefix p;
122 struct route_node *rn;
123 struct eigrp_interface *rninfo = NULL;
124
125 p = *prefix;
126 p.prefixlen = IPV4_MAX_PREFIXLEN;
127
128 /* route_node_get implicitly locks */
129 if ((rn = route_node_lookup (IF_OIFS (ifp), &p)))
130 {
131 rninfo = (struct eigrp_interface *) rn->info;
132 route_unlock_node (rn);
133 }
134
135 return rninfo;
136 }
137
138 int
139 eigrp_if_delete_hook (struct interface *ifp)
140 {
141 struct route_node *rn;
142
143 route_table_finish (IF_OIFS (ifp));
144
145 for (rn = route_top (IF_OIFS_PARAMS (ifp)); rn; rn = route_next (rn))
146 if (rn->info)
147 eigrp_del_if_params (rn->info);
148 route_table_finish (IF_OIFS_PARAMS (ifp));
149
150 XFREE (MTYPE_EIGRP_IF_INFO, ifp->info);
151 ifp->info = NULL;
152
153 return 0;
154 }
155
156 struct list *eigrp_iflist;
157
158 void
159 eigrp_if_init ()
160 {
161 /* Initialize Zebra interface data structure. */
162 if_add_hook (IF_NEW_HOOK, eigrp_if_new_hook);
163 if_add_hook (IF_DELETE_HOOK, eigrp_if_delete_hook);
164 }
165
166 int
167 eigrp_if_new_hook (struct interface *ifp)
168 {
169 int rc = 0;
170
171 ifp->info = XCALLOC (MTYPE_EIGRP_IF_INFO, sizeof (struct eigrp_if_info));
172
173 IF_OIFS (ifp) = route_table_init ();
174 IF_OIFS_PARAMS (ifp) = route_table_init ();
175
176 IF_DEF_PARAMS (ifp) = eigrp_new_if_params ();
177
178 SET_IF_PARAM (IF_DEF_PARAMS (ifp), v_hello);
179 IF_DEF_PARAMS (ifp)->v_hello = (u_int32_t) EIGRP_HELLO_INTERVAL_DEFAULT;
180
181 SET_IF_PARAM (IF_DEF_PARAMS (ifp), v_wait);
182 IF_DEF_PARAMS (ifp)->v_wait = (u_int16_t) EIGRP_HOLD_INTERVAL_DEFAULT;
183
184 SET_IF_PARAM (IF_DEF_PARAMS (ifp), bandwidth);
185 IF_DEF_PARAMS (ifp)->bandwidth = (u_int32_t) EIGRP_BANDWIDTH_DEFAULT;
186
187 SET_IF_PARAM (IF_DEF_PARAMS (ifp), delay);
188 IF_DEF_PARAMS (ifp)->delay = (u_int32_t) EIGRP_DELAY_DEFAULT;
189
190 SET_IF_PARAM (IF_DEF_PARAMS (ifp), reliability);
191 IF_DEF_PARAMS (ifp)->reliability = (u_char) EIGRP_RELIABILITY_DEFAULT;
192
193 SET_IF_PARAM (IF_DEF_PARAMS (ifp), load);
194 IF_DEF_PARAMS (ifp)->load = (u_char) EIGRP_LOAD_DEFAULT;
195
196 SET_IF_PARAM (IF_DEF_PARAMS (ifp), auth_type);
197 IF_DEF_PARAMS (ifp)->auth_type = EIGRP_AUTH_TYPE_NONE;
198
199 SET_IF_PARAM (IF_DEF_PARAMS (ifp), auth_keychain);
200 IF_DEF_PARAMS (ifp)->auth_keychain= NULL;
201
202 return rc;
203 }
204
205 struct eigrp_if_params *
206 eigrp_new_if_params (void)
207 {
208 struct eigrp_if_params *eip;
209
210 eip = XCALLOC (MTYPE_EIGRP_IF_PARAMS, sizeof (struct eigrp_if_params));
211 if (!eip)
212 return NULL;
213
214 UNSET_IF_PARAM (eip, passive_interface);
215 UNSET_IF_PARAM (eip, v_hello);
216 UNSET_IF_PARAM (eip, v_wait);
217 UNSET_IF_PARAM (eip, bandwidth);
218 UNSET_IF_PARAM (eip, delay);
219 UNSET_IF_PARAM (eip, reliability);
220 UNSET_IF_PARAM (eip, load);
221 UNSET_IF_PARAM (eip, auth_keychain);
222 UNSET_IF_PARAM (eip, auth_type);
223
224 return eip;
225 }
226
227 void
228 eigrp_del_if_params (struct eigrp_if_params *eip)
229 {
230 if(eip->auth_keychain)
231 free(eip->auth_keychain);
232
233 XFREE (MTYPE_EIGRP_IF_PARAMS, eip);
234 }
235
236 struct eigrp_if_params *
237 eigrp_lookup_if_params (struct interface *ifp, struct in_addr addr)
238 {
239 struct prefix_ipv4 p;
240 struct route_node *rn;
241
242 p.family = AF_INET;
243 p.prefixlen = IPV4_MAX_PREFIXLEN;
244 p.prefix = addr;
245
246 rn = route_node_lookup (IF_OIFS_PARAMS (ifp), (struct prefix*) &p);
247
248 if (rn)
249 {
250 route_unlock_node (rn);
251 return rn->info;
252 }
253
254 return NULL;
255 }
256
257 int
258 eigrp_if_up (struct eigrp_interface *ei)
259 {
260 struct eigrp_prefix_entry *pe;
261 struct eigrp_neighbor_entry *ne;
262 struct eigrp_metrics metric;
263 struct eigrp_interface *ei2;
264 struct listnode *node, *nnode;
265 struct eigrp *eigrp = eigrp_lookup ();
266
267 if (ei == NULL)
268 return 0;
269
270 if (eigrp != NULL)
271 eigrp_adjust_sndbuflen (eigrp, ei->ifp->mtu);
272 else
273 zlog_warn ("%s: eigrp_lookup () returned NULL", __func__);
274 eigrp_if_stream_set (ei);
275
276 /* Set multicast memberships appropriately for new state. */
277 eigrp_if_set_multicast (ei);
278
279 thread_add_event (master, eigrp_hello_timer, ei, (1));
280
281 /*Prepare metrics*/
282 metric.bandwith = eigrp_bandwidth_to_scaled (EIGRP_IF_PARAM (ei,bandwidth));
283 metric.delay = eigrp_delay_to_scaled (EIGRP_IF_PARAM (ei,delay));
284 metric.load = EIGRP_IF_PARAM (ei,load);
285 metric.reliability = EIGRP_IF_PARAM (ei,reliability);
286 metric.mtu[0] = 0xDC;
287 metric.mtu[1] = 0x05;
288 metric.mtu[2] = 0x00;
289 metric.hop_count = 0;
290 metric.flags = 0;
291 metric.tag = 0;
292
293 /*Add connected entry to topology table*/
294
295 struct prefix_ipv4 *dest_addr = prefix_ipv4_new ();
296
297 dest_addr->family = AF_INET;
298 dest_addr->prefix = ei->connected->address->u.prefix4;
299 dest_addr->prefixlen = ei->connected->address->prefixlen;
300 apply_mask_ipv4 (dest_addr);
301 pe = eigrp_topology_table_lookup_ipv4 (eigrp->topology_table, dest_addr);
302
303 if (pe == NULL)
304 {
305 pe = eigrp_prefix_entry_new ();
306 pe->serno = eigrp->serno;
307 pe->destination_ipv4 = dest_addr;
308 pe->af = AF_INET;
309 pe->nt = EIGRP_TOPOLOGY_TYPE_CONNECTED;
310
311 pe->state = EIGRP_FSM_STATE_PASSIVE;
312 pe->fdistance = eigrp_calculate_metrics (eigrp, &metric);
313 pe->req_action |= EIGRP_FSM_NEED_UPDATE;
314 eigrp_prefix_entry_add (eigrp->topology_table, pe);
315 listnode_add(eigrp->topology_changes_internalIPV4, pe);
316 }
317 ne = eigrp_neighbor_entry_new ();
318 ne->ei = ei;
319 ne->reported_metric = metric;
320 ne->total_metric = metric;
321 ne->distance = eigrp_calculate_metrics (eigrp, &metric);
322 ne->reported_distance = 0;
323 ne->prefix = pe;
324 ne->adv_router = eigrp->neighbor_self;
325 ne->flags = EIGRP_NEIGHBOR_ENTRY_SUCCESSOR_FLAG;
326 eigrp_neighbor_entry_add (pe, ne);
327
328 for (ALL_LIST_ELEMENTS (eigrp->eiflist, node, nnode, ei2))
329 {
330 if (ei2->nbrs->count != 0)
331 {
332 eigrp_update_send (ei2);
333 }
334 }
335
336 pe->req_action &= ~EIGRP_FSM_NEED_UPDATE;
337 listnode_delete(eigrp->topology_changes_internalIPV4, pe);
338
339 return 1;
340 }
341
342 int
343 eigrp_if_down (struct eigrp_interface *ei)
344 {
345 struct listnode *node, *nnode;
346 struct eigrp_neighbor *nbr;
347
348 if (ei == NULL)
349 return 0;
350
351 /* Shutdown packet reception and sending */
352 if(ei->t_hello)
353 THREAD_OFF (ei->t_hello);
354
355 eigrp_if_stream_unset (ei);
356
357 /*Set infinite metrics to routes learned by this interface and start query process*/
358 for (ALL_LIST_ELEMENTS (ei->nbrs, node, nnode, nbr))
359 {
360 eigrp_nbr_delete(nbr);
361 }
362
363 return 1;
364 }
365
366 void
367 eigrp_if_stream_set (struct eigrp_interface *ei)
368 {
369 /* set output fifo queue. */
370 if (ei->obuf == NULL)
371 ei->obuf = eigrp_fifo_new ();
372 }
373
374 void
375 eigrp_if_stream_unset (struct eigrp_interface *ei)
376 {
377 struct eigrp *eigrp = ei->eigrp;
378
379 if (ei->obuf)
380 {
381 eigrp_fifo_free (ei->obuf);
382 ei->obuf = NULL;
383
384 if (ei->on_write_q)
385 {
386 listnode_delete (eigrp->oi_write_q, ei);
387 if (list_isempty (eigrp->oi_write_q))
388 thread_cancel (eigrp->t_write);
389 ei->on_write_q = 0;
390 }
391 }
392 }
393
394 void
395 eigrp_if_set_multicast (struct eigrp_interface *ei)
396 {
397 if ((EIGRP_IF_PASSIVE_STATUS (ei) == EIGRP_IF_ACTIVE))
398 {
399 /* The interface should belong to the EIGRP-all-routers group. */
400 if (!EI_MEMBER_CHECK (ei, MEMBER_ALLROUTERS)
401 && (eigrp_if_add_allspfrouters (ei->eigrp, ei->address,
402 ei->ifp->ifindex) >= 0))
403 /* Set the flag only if the system call to join succeeded. */
404 EI_MEMBER_JOINED (ei, MEMBER_ALLROUTERS);
405 }
406 else
407 {
408 /* The interface should NOT belong to the EIGRP-all-routers group. */
409 if (EI_MEMBER_CHECK (ei, MEMBER_ALLROUTERS))
410 {
411 /* Only actually drop if this is the last reference */
412 if (EI_MEMBER_COUNT (ei, MEMBER_ALLROUTERS) == 1)
413 eigrp_if_drop_allspfrouters (ei->eigrp, ei->address,
414 ei->ifp->ifindex);
415 /* Unset the flag regardless of whether the system call to leave
416 the group succeeded, since it's much safer to assume that
417 we are not a member. */
418 EI_MEMBER_LEFT (ei, MEMBER_ALLROUTERS);
419 }
420 }
421 }
422
423 u_char
424 eigrp_default_iftype (struct interface *ifp)
425 {
426 if (if_is_pointopoint (ifp))
427 return EIGRP_IFTYPE_POINTOPOINT;
428 else if (if_is_loopback (ifp))
429 return EIGRP_IFTYPE_LOOPBACK;
430 else
431 return EIGRP_IFTYPE_BROADCAST;
432 }
433
434 void
435 eigrp_if_free (struct eigrp_interface *ei, int source)
436 {
437 struct prefix_ipv4 dest_addr;
438 struct eigrp_prefix_entry *pe;
439 struct eigrp *eigrp = eigrp_lookup ();
440
441 if (source == INTERFACE_DOWN_BY_VTY)
442 {
443 THREAD_OFF (ei->t_hello);
444 eigrp_hello_send(ei,EIGRP_HELLO_GRACEFUL_SHUTDOWN, NULL);
445 }
446
447 dest_addr.family = AF_INET;
448 dest_addr.prefix = ei->connected->address->u.prefix4;
449 dest_addr.prefixlen = ei->connected->address->prefixlen;
450 apply_mask_ipv4(&dest_addr);
451 pe = eigrp_topology_table_lookup_ipv4 (eigrp->topology_table, &dest_addr);
452 if (pe)
453 eigrp_prefix_entry_delete (eigrp->topology_table, pe);
454
455 eigrp_if_down (ei);
456
457 list_delete (ei->nbrs);
458 eigrp_delete_from_if (ei->ifp, ei);
459 listnode_delete (ei->eigrp->eiflist, ei);
460
461 thread_cancel_event (master, ei);
462
463 memset (ei, 0, sizeof (*ei));
464 XFREE (MTYPE_EIGRP_IF, ei);
465 }
466
467 static void
468 eigrp_delete_from_if (struct interface *ifp, struct eigrp_interface *ei)
469 {
470 struct route_node *rn;
471 struct prefix p;
472
473 p = *ei->address;
474 p.prefixlen = IPV4_MAX_PREFIXLEN;
475
476 rn = route_node_lookup (IF_OIFS (ei->ifp), &p);
477 assert (rn);
478 assert (rn->info);
479 rn->info = NULL;
480 route_unlock_node (rn);
481 route_unlock_node (rn);
482 }
483
484 /* Simulate down/up on the interface. This is needed, for example, when
485 the MTU changes. */
486 void
487 eigrp_if_reset (struct interface *ifp)
488 {
489 struct route_node *rn;
490
491 for (rn = route_top (IF_OIFS (ifp)); rn; rn = route_next (rn))
492 {
493 struct eigrp_interface *ei;
494
495 if ((ei = rn->info) == NULL)
496 continue;
497
498 eigrp_if_down (ei);
499 eigrp_if_up (ei);
500 }
501 }
502
503 struct eigrp_interface *
504 eigrp_if_lookup_by_local_addr (struct eigrp *eigrp, struct interface *ifp,
505 struct in_addr address)
506 {
507 struct listnode *node;
508 struct eigrp_interface *ei;
509
510 for (ALL_LIST_ELEMENTS_RO (eigrp->eiflist, node, ei))
511 {
512 if (ifp && ei->ifp != ifp)
513 continue;
514
515 if (IPV4_ADDR_SAME (&address, &ei->address->u.prefix4))
516 return ei;
517 }
518
519 return NULL;
520 }
521
522 /**
523 * @fn eigrp_if_lookup_by_name
524 *
525 * @param[in] eigrp EIGRP process
526 * @param[in] if_name Name of the interface
527 *
528 * @return struct eigrp_interface *
529 *
530 * @par
531 * Function is used for lookup interface by name.
532 */
533 struct eigrp_interface *
534 eigrp_if_lookup_by_name (struct eigrp *eigrp, const char *if_name)
535 {
536 struct eigrp_interface *ei;
537 struct listnode *node;
538
539 /* iterate over all eigrp interfaces */
540 for (ALL_LIST_ELEMENTS_RO (eigrp->eiflist, node, ei))
541 {
542 /* compare int name with eigrp interface's name */
543 if(strcmp(ei->ifp->name, if_name) == 0)
544 {
545 return ei;
546 }
547 }
548
549 return NULL;
550 }
551
552 /* determine receiving interface by ifp and source address */
553 struct eigrp_interface *
554 eigrp_if_lookup_recv_if (struct eigrp *eigrp, struct in_addr src,
555 struct interface *ifp)
556 {
557 struct route_node *rn;
558 struct prefix_ipv4 addr;
559 struct eigrp_interface *ei, *match;
560
561 addr.family = AF_INET;
562 addr.prefix = src;
563 addr.prefixlen = IPV4_MAX_BITLEN;
564
565 match = NULL;
566
567 for (rn = route_top (IF_OIFS (ifp)); rn; rn = route_next (rn))
568 {
569 ei = rn->info;
570
571 if (!ei) /* oi can be NULL for PtP aliases */
572 continue;
573
574 if (if_is_loopback (ei->ifp))
575 continue;
576
577 if (prefix_match (CONNECTED_PREFIX (ei->connected),
578 (struct prefix *) &addr))
579 {
580 if ((match == NULL)
581 || (match->address->prefixlen < ei->address->prefixlen))
582 match = ei;
583 }
584 }
585
586 return match;
587 }
588
589 u_int32_t
590 eigrp_bandwidth_to_scaled (u_int32_t bandwidth)
591 {
592 uint64_t temp_bandwidth = (256ull * 10000000) / bandwidth;
593
594 temp_bandwidth =
595 temp_bandwidth < EIGRP_MAX_METRIC ? temp_bandwidth : EIGRP_MAX_METRIC;
596
597 return (u_int32_t) temp_bandwidth;
598 }
599
600 u_int32_t
601 eigrp_scaled_to_bandwidth (u_int32_t scaled)
602 {
603 uint64_t temp_scaled = scaled * (256ull * 10000000);
604
605 temp_scaled =
606 temp_scaled < EIGRP_MAX_METRIC ? temp_scaled : EIGRP_MAX_METRIC;
607
608 return (u_int32_t) temp_scaled;
609 }
610
611 u_int32_t
612 eigrp_delay_to_scaled (u_int32_t delay)
613 {
614 return delay * 256;
615 }
616
617 u_int32_t
618 eigrp_scaled_to_delay (u_int32_t scaled)
619 {
620 return scaled / 256;
621 }