blob: 159422b47c6a1758c596470a000452df7ff47185 [file] [log] [blame]
paul718e3742002-12-13 20:15:29 +00001/* OSPF version 2 daemon program.
2 Copyright (C) 1999, 2000 Toshiaki Takada
3
4This file is part of GNU Zebra.
5
6GNU Zebra is free software; you can redistribute it and/or modify it
7under the terms of the GNU General Public License as published by the
8Free Software Foundation; either version 2, or (at your option) any
9later version.
10
11GNU Zebra is distributed in the hope that it will be useful, but
12WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with GNU Zebra; see the file COPYING. If not, write to the Free
18Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
1902111-1307, USA. */
20
21#include <zebra.h>
22
23#include "thread.h"
24#include "vty.h"
25#include "command.h"
26#include "linklist.h"
27#include "prefix.h"
28#include "table.h"
29#include "if.h"
30#include "memory.h"
31#include "stream.h"
32#include "log.h"
33#include "sockunion.h" /* for inet_aton () */
34#include "zclient.h"
35#include "plist.h"
36
37#include "ospfd/ospfd.h"
38#include "ospfd/ospf_network.h"
39#include "ospfd/ospf_interface.h"
40#include "ospfd/ospf_ism.h"
41#include "ospfd/ospf_asbr.h"
42#include "ospfd/ospf_lsa.h"
43#include "ospfd/ospf_lsdb.h"
44#include "ospfd/ospf_neighbor.h"
45#include "ospfd/ospf_nsm.h"
46#include "ospfd/ospf_spf.h"
47#include "ospfd/ospf_packet.h"
48#include "ospfd/ospf_dump.h"
49#include "ospfd/ospf_zebra.h"
50#include "ospfd/ospf_abr.h"
51#include "ospfd/ospf_flood.h"
52#include "ospfd/ospf_route.h"
53#include "ospfd/ospf_ase.h"
54
paul020709f2003-04-04 02:44:16 +000055
pauledd7c242003-06-04 13:59:38 +000056
paul020709f2003-04-04 02:44:16 +000057/* OSPF process wide configuration. */
58static struct ospf_master ospf_master;
59
60/* OSPF process wide configuration pointer to export. */
61struct ospf_master *om;
paul718e3742002-12-13 20:15:29 +000062
63extern struct zclient *zclient;
hasso18a6dce2004-10-03 18:18:34 +000064extern struct in_addr router_id_zebra;
paul718e3742002-12-13 20:15:29 +000065
66
paul88d6cf32005-10-29 12:50:09 +000067static void ospf_remove_vls_through_area (struct ospf *, struct ospf_area *);
68static void ospf_network_free (struct ospf *, struct ospf_network *);
69static void ospf_area_free (struct ospf_area *);
70static void ospf_network_run (struct ospf *, struct prefix *, struct ospf_area *);
71static void ospf_finish_final (struct ospf *);
paul718e3742002-12-13 20:15:29 +000072
paul718e3742002-12-13 20:15:29 +000073#define OSPF_EXTERNAL_LSA_ORIGINATE_DELAY 1
paul88d6cf32005-10-29 12:50:09 +000074
paul718e3742002-12-13 20:15:29 +000075void
paul68980082003-03-25 05:07:42 +000076ospf_router_id_update (struct ospf *ospf)
paul718e3742002-12-13 20:15:29 +000077{
paul718e3742002-12-13 20:15:29 +000078 struct in_addr router_id, router_id_old;
paul1eb8ef22005-04-07 07:30:20 +000079 struct ospf_interface *oi;
hasso52dc7ee2004-09-23 19:18:23 +000080 struct listnode *node;
paul718e3742002-12-13 20:15:29 +000081
82 if (IS_DEBUG_OSPF_EVENT)
ajs9b0e25c2004-12-08 19:06:51 +000083 zlog_debug ("Router-ID[OLD:%s]: Update", inet_ntoa (ospf->router_id));
paul718e3742002-12-13 20:15:29 +000084
paul68980082003-03-25 05:07:42 +000085 router_id_old = ospf->router_id;
paul718e3742002-12-13 20:15:29 +000086
Andrew J. Schorr16700082006-07-27 22:29:06 +000087 /* Select the router ID based on these priorities:
88 1. Statically assigned router ID is always the first choice.
89 2. If there is no statically assigned router ID, then try to stick
90 with the most recent value, since changing router ID's is very
91 disruptive.
92 3. Last choice: just go with whatever the zebra daemon recommends.
93 */
paul68980082003-03-25 05:07:42 +000094 if (ospf->router_id_static.s_addr != 0)
95 router_id = ospf->router_id_static;
Andrew J. Schorr16700082006-07-27 22:29:06 +000096 else if (ospf->router_id.s_addr != 0)
97 router_id = ospf->router_id;
paul718e3742002-12-13 20:15:29 +000098 else
hasso18a6dce2004-10-03 18:18:34 +000099 router_id = router_id_zebra;
paul718e3742002-12-13 20:15:29 +0000100
paul68980082003-03-25 05:07:42 +0000101 ospf->router_id = router_id;
paul718e3742002-12-13 20:15:29 +0000102
103 if (IS_DEBUG_OSPF_EVENT)
ajs9b0e25c2004-12-08 19:06:51 +0000104 zlog_debug ("Router-ID[NEW:%s]: Update", inet_ntoa (ospf->router_id));
paul718e3742002-12-13 20:15:29 +0000105
106 if (!IPV4_ADDR_SAME (&router_id_old, &router_id))
107 {
paul1eb8ef22005-04-07 07:30:20 +0000108 for (ALL_LIST_ELEMENTS_RO (ospf->oiflist, node, oi))
109 /* Update self-neighbor's router_id. */
110 oi->nbr_self->router_id = router_id;
paul718e3742002-12-13 20:15:29 +0000111
112 /* If AS-external-LSA is queued, then flush those LSAs. */
paul68980082003-03-25 05:07:42 +0000113 if (router_id_old.s_addr == 0 && ospf->external_origin)
paul718e3742002-12-13 20:15:29 +0000114 {
115 int type;
116 /* Originate each redistributed external route. */
117 for (type = 0; type < ZEBRA_ROUTE_MAX; type++)
paul68980082003-03-25 05:07:42 +0000118 if (ospf->external_origin & (1 << type))
paul718e3742002-12-13 20:15:29 +0000119 thread_add_event (master, ospf_external_lsa_originate_timer,
paul68980082003-03-25 05:07:42 +0000120 ospf, type);
paul718e3742002-12-13 20:15:29 +0000121 /* Originate Deafult. */
paul68980082003-03-25 05:07:42 +0000122 if (ospf->external_origin & (1 << ZEBRA_ROUTE_MAX))
Paul Jakma4021b602006-05-12 22:55:41 +0000123 thread_add_event (master, ospf_default_originate_timer, ospf, 0);
paul718e3742002-12-13 20:15:29 +0000124
paul68980082003-03-25 05:07:42 +0000125 ospf->external_origin = 0;
paul718e3742002-12-13 20:15:29 +0000126 }
127
paul68980082003-03-25 05:07:42 +0000128 OSPF_TIMER_ON (ospf->t_router_lsa_update,
paul718e3742002-12-13 20:15:29 +0000129 ospf_router_lsa_update_timer, OSPF_LSA_UPDATE_DELAY);
paulb29800a2005-11-20 14:50:45 +0000130
131 /* update ospf_interface's */
132 ospf_if_update (ospf);
paul718e3742002-12-13 20:15:29 +0000133 }
134}
paul718e3742002-12-13 20:15:29 +0000135
136/* For OSPF area sort by area id. */
paul4dadc292005-05-06 21:37:42 +0000137static int
paul718e3742002-12-13 20:15:29 +0000138ospf_area_id_cmp (struct ospf_area *a1, struct ospf_area *a2)
139{
140 if (ntohl (a1->area_id.s_addr) > ntohl (a2->area_id.s_addr))
141 return 1;
142 if (ntohl (a1->area_id.s_addr) < ntohl (a2->area_id.s_addr))
143 return -1;
144 return 0;
145}
146
147/* Allocate new ospf structure. */
paul4dadc292005-05-06 21:37:42 +0000148static struct ospf *
149ospf_new (void)
paul718e3742002-12-13 20:15:29 +0000150{
151 int i;
152
153 struct ospf *new = XCALLOC (MTYPE_OSPF_TOP, sizeof (struct ospf));
154
155 new->router_id.s_addr = htonl (0);
156 new->router_id_static.s_addr = htonl (0);
157
pauld57834f2005-07-12 20:04:22 +0000158 new->abr_type = OSPF_ABR_DEFAULT;
paul718e3742002-12-13 20:15:29 +0000159 new->oiflist = list_new ();
160 new->vlinks = list_new ();
161 new->areas = list_new ();
162 new->areas->cmp = (int (*)(void *, void *)) ospf_area_id_cmp;
163 new->networks = route_table_init ();
164 new->nbr_nbma = route_table_init ();
165
166 new->lsdb = ospf_lsdb_new ();
167
168 new->default_originate = DEFAULT_ORIGINATE_NONE;
169
Paul Jakma7ffa8fa2006-10-22 20:07:53 +0000170 new->passive_interface_default = OSPF_IF_ACTIVE;
171
paul718e3742002-12-13 20:15:29 +0000172 new->new_external_route = route_table_init ();
173 new->old_external_route = route_table_init ();
174 new->external_lsas = route_table_init ();
paul88d6cf32005-10-29 12:50:09 +0000175
176 new->stub_router_startup_time = OSPF_STUB_ROUTER_UNCONFIGURED;
paul31a59762005-11-14 11:11:11 +0000177 new->stub_router_shutdown_time = OSPF_STUB_ROUTER_UNCONFIGURED;
paul88d6cf32005-10-29 12:50:09 +0000178
paul718e3742002-12-13 20:15:29 +0000179 /* Distribute parameter init. */
180 for (i = 0; i <= ZEBRA_ROUTE_MAX; i++)
181 {
182 new->dmetric[i].type = -1;
183 new->dmetric[i].value = -1;
184 }
185 new->default_metric = -1;
186 new->ref_bandwidth = OSPF_DEFAULT_REF_BANDWIDTH;
187
188 /* SPF timer value init. */
189 new->spf_delay = OSPF_SPF_DELAY_DEFAULT;
190 new->spf_holdtime = OSPF_SPF_HOLDTIME_DEFAULT;
pauld24f6e22005-10-21 09:23:12 +0000191 new->spf_max_holdtime = OSPF_SPF_MAX_HOLDTIME_DEFAULT;
192 new->spf_hold_multiplier = 1;
paul718e3742002-12-13 20:15:29 +0000193
194 /* MaxAge init. */
195 new->maxage_lsa = list_new ();
196 new->t_maxage_walker =
197 thread_add_timer (master, ospf_lsa_maxage_walker,
paul68980082003-03-25 05:07:42 +0000198 new, OSPF_LSA_MAXAGE_CHECK_INTERVAL);
paul718e3742002-12-13 20:15:29 +0000199
200 /* Distance table init. */
201 new->distance_table = route_table_init ();
202
203 new->lsa_refresh_queue.index = 0;
204 new->lsa_refresh_interval = OSPF_LSA_REFRESH_INTERVAL_DEFAULT;
205 new->t_lsa_refresher = thread_add_timer (master, ospf_lsa_refresh_walker,
206 new, new->lsa_refresh_interval);
Paul Jakma2518efd2006-08-27 06:49:29 +0000207 new->lsa_refresher_started = quagga_time (NULL);
paul718e3742002-12-13 20:15:29 +0000208
ajs5c333492005-02-23 15:43:01 +0000209 if ((new->fd = ospf_sock_init()) < 0)
210 {
211 zlog_err("ospf_new: fatal error: ospf_sock_init was unable to open "
212 "a socket");
213 exit(1);
214 }
215 if ((new->ibuf = stream_new(OSPF_MAX_PACKET_SIZE+1)) == NULL)
216 {
217 zlog_err("ospf_new: fatal error: stream_new(%u) failed allocating ibuf",
218 OSPF_MAX_PACKET_SIZE+1);
219 exit(1);
220 }
221 new->t_read = thread_add_read (master, ospf_read, new, new->fd);
paul718e3742002-12-13 20:15:29 +0000222 new->oi_write_q = list_new ();
223
224 return new;
225}
226
227struct ospf *
paul020709f2003-04-04 02:44:16 +0000228ospf_lookup ()
229{
230 if (listcount (om->ospf) == 0)
231 return NULL;
232
paul1eb8ef22005-04-07 07:30:20 +0000233 return listgetdata (listhead (om->ospf));
paul020709f2003-04-04 02:44:16 +0000234}
235
paul4dadc292005-05-06 21:37:42 +0000236static void
paul020709f2003-04-04 02:44:16 +0000237ospf_add (struct ospf *ospf)
238{
239 listnode_add (om->ospf, ospf);
240}
241
paul4dadc292005-05-06 21:37:42 +0000242static void
paul020709f2003-04-04 02:44:16 +0000243ospf_delete (struct ospf *ospf)
244{
245 listnode_delete (om->ospf, ospf);
246}
247
248struct ospf *
paul718e3742002-12-13 20:15:29 +0000249ospf_get ()
250{
paul020709f2003-04-04 02:44:16 +0000251 struct ospf *ospf;
paul718e3742002-12-13 20:15:29 +0000252
paul020709f2003-04-04 02:44:16 +0000253 ospf = ospf_lookup ();
254 if (ospf == NULL)
255 {
256 ospf = ospf_new ();
257 ospf_add (ospf);
paul718e3742002-12-13 20:15:29 +0000258
paul020709f2003-04-04 02:44:16 +0000259 if (ospf->router_id_static.s_addr == 0)
260 ospf_router_id_update (ospf);
paul718e3742002-12-13 20:15:29 +0000261
262#ifdef HAVE_OPAQUE_LSA
paul020709f2003-04-04 02:44:16 +0000263 ospf_opaque_type11_lsa_init (ospf);
paul718e3742002-12-13 20:15:29 +0000264#endif /* HAVE_OPAQUE_LSA */
paul020709f2003-04-04 02:44:16 +0000265 }
paul68980082003-03-25 05:07:42 +0000266
267 return ospf;
paul718e3742002-12-13 20:15:29 +0000268}
paul88d6cf32005-10-29 12:50:09 +0000269
paulc9c93d52005-11-26 13:31:11 +0000270/* Handle the second half of deferred shutdown. This is called either
271 * from the deferred-shutdown timer thread, or directly through
272 * ospf_deferred_shutdown_check.
paul88d6cf32005-10-29 12:50:09 +0000273 *
274 * Function is to cleanup G-R state, if required then call ospf_finish_final
275 * to complete shutdown of this ospf instance. Possibly exit if the
276 * whole process is being shutdown and this was the last OSPF instance.
277 */
278static void
paulc9c93d52005-11-26 13:31:11 +0000279ospf_deferred_shutdown_finish (struct ospf *ospf)
paul88d6cf32005-10-29 12:50:09 +0000280{
281 ospf->stub_router_shutdown_time = OSPF_STUB_ROUTER_UNCONFIGURED;
paulc9c93d52005-11-26 13:31:11 +0000282 OSPF_TIMER_OFF (ospf->t_deferred_shutdown);
paul88d6cf32005-10-29 12:50:09 +0000283
284 ospf_finish_final (ospf);
285
286 /* *ospf is now invalid */
287
288 /* ospfd being shut-down? If so, was this the last ospf instance? */
289 if (CHECK_FLAG (om->options, OSPF_MASTER_SHUTDOWN)
290 && (listcount (om->ospf) == 0))
291 exit (0);
292
293 return;
294}
295
296/* Timer thread for G-R */
297static int
paulc9c93d52005-11-26 13:31:11 +0000298ospf_deferred_shutdown_timer (struct thread *t)
paul88d6cf32005-10-29 12:50:09 +0000299{
300 struct ospf *ospf = THREAD_ARG(t);
301
paulc9c93d52005-11-26 13:31:11 +0000302 ospf_deferred_shutdown_finish (ospf);
paul88d6cf32005-10-29 12:50:09 +0000303
304 return 0;
305}
306
paulc9c93d52005-11-26 13:31:11 +0000307/* Check whether deferred-shutdown must be scheduled, otherwise call
paul88d6cf32005-10-29 12:50:09 +0000308 * down directly into second-half of instance shutdown.
309 */
310static void
paulc9c93d52005-11-26 13:31:11 +0000311ospf_deferred_shutdown_check (struct ospf *ospf)
paul88d6cf32005-10-29 12:50:09 +0000312{
313 unsigned long timeout;
314 struct listnode *ln;
315 struct ospf_area *area;
316
paulc9c93d52005-11-26 13:31:11 +0000317 /* deferred shutdown already running? */
318 if (ospf->t_deferred_shutdown)
paul88d6cf32005-10-29 12:50:09 +0000319 return;
320
321 /* Should we try push out max-metric LSAs? */
322 if (ospf->stub_router_shutdown_time != OSPF_STUB_ROUTER_UNCONFIGURED)
323 {
324 for (ALL_LIST_ELEMENTS_RO (ospf->areas, ln, area))
325 {
326 SET_FLAG (area->stub_router_state, OSPF_AREA_ADMIN_STUB_ROUTED);
327
328 if (!CHECK_FLAG (area->stub_router_state, OSPF_AREA_IS_STUB_ROUTED))
329 ospf_router_lsa_timer_add (area);
330 }
331 timeout = ospf->stub_router_shutdown_time;
332 }
333 else
paulc9c93d52005-11-26 13:31:11 +0000334 {
335 /* No timer needed */
336 ospf_deferred_shutdown_finish (ospf);
337 return;
338 }
paul88d6cf32005-10-29 12:50:09 +0000339
paulc9c93d52005-11-26 13:31:11 +0000340 OSPF_TIMER_ON (ospf->t_deferred_shutdown, ospf_deferred_shutdown_timer,
paul88d6cf32005-10-29 12:50:09 +0000341 timeout);
342 return;
343}
344
345/* Shut down the entire process */
346void
347ospf_terminate (void)
348{
349 struct ospf *ospf;
350 struct listnode *node, *nnode;
351
352 /* shutdown already in progress */
353 if (CHECK_FLAG (om->options, OSPF_MASTER_SHUTDOWN))
354 return;
355
356 SET_FLAG (om->options, OSPF_MASTER_SHUTDOWN);
357
Andrew J. Schorr4056a542007-02-27 13:55:46 +0000358 /* exit immediately if OSPF not actually running */
359 if (listcount(om->ospf) == 0)
360 exit(0);
361
paul88d6cf32005-10-29 12:50:09 +0000362 for (ALL_LIST_ELEMENTS (om->ospf, node, nnode, ospf))
363 ospf_finish (ospf);
364
365 /* Deliberately go back up, hopefully to thread scheduler, as
366 * One or more ospf_finish()'s may have deferred shutdown to a timer
367 * thread
368 */
369}
paul718e3742002-12-13 20:15:29 +0000370
371void
372ospf_finish (struct ospf *ospf)
373{
paulc9c93d52005-11-26 13:31:11 +0000374 /* let deferred shutdown decide */
375 ospf_deferred_shutdown_check (ospf);
paul88d6cf32005-10-29 12:50:09 +0000376
paulc9c93d52005-11-26 13:31:11 +0000377 /* if ospf_deferred_shutdown returns, then ospf_finish_final is
paul88d6cf32005-10-29 12:50:09 +0000378 * deferred to expiry of G-S timer thread. Return back up, hopefully
379 * to thread scheduler.
380 */
paulc9c93d52005-11-26 13:31:11 +0000381 return;
paul88d6cf32005-10-29 12:50:09 +0000382}
383
384/* Final cleanup of ospf instance */
385static void
386ospf_finish_final (struct ospf *ospf)
387{
paul718e3742002-12-13 20:15:29 +0000388 struct route_node *rn;
389 struct ospf_nbr_nbma *nbr_nbma;
paul68980082003-03-25 05:07:42 +0000390 struct ospf_lsa *lsa;
paul1eb8ef22005-04-07 07:30:20 +0000391 struct ospf_interface *oi;
392 struct ospf_area *area;
393 struct ospf_vl_data *vl_data;
394 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000395 int i;
396
397#ifdef HAVE_OPAQUE_LSA
398 ospf_opaque_type11_lsa_term (ospf);
399#endif /* HAVE_OPAQUE_LSA */
paul88d6cf32005-10-29 12:50:09 +0000400
401 /* be nice if this worked, but it doesn't */
402 /*ospf_flush_self_originated_lsas_now (ospf);*/
403
404 /* Unregister redistribution */
paul718e3742002-12-13 20:15:29 +0000405 for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
paul020709f2003-04-04 02:44:16 +0000406 ospf_redistribute_unset (ospf, i);
Paul Jakma29b5a042006-08-27 08:01:20 +0000407 ospf_redistribute_default_unset (ospf);
paul718e3742002-12-13 20:15:29 +0000408
paul1eb8ef22005-04-07 07:30:20 +0000409 for (ALL_LIST_ELEMENTS (ospf->areas, node, nnode, area))
410 ospf_remove_vls_through_area (ospf, area);
paul718e3742002-12-13 20:15:29 +0000411
paul1eb8ef22005-04-07 07:30:20 +0000412 for (ALL_LIST_ELEMENTS (ospf->vlinks, node, nnode, vl_data))
413 ospf_vl_delete (ospf, vl_data);
paul718e3742002-12-13 20:15:29 +0000414
415 list_delete (ospf->vlinks);
416
417 /* Reset interface. */
paul1eb8ef22005-04-07 07:30:20 +0000418 for (ALL_LIST_ELEMENTS (ospf->oiflist, node, nnode, oi))
419 ospf_if_free (oi);
paul718e3742002-12-13 20:15:29 +0000420
421 /* Clear static neighbors */
422 for (rn = route_top (ospf->nbr_nbma); rn; rn = route_next (rn))
423 if ((nbr_nbma = rn->info))
424 {
425 OSPF_POLL_TIMER_OFF (nbr_nbma->t_poll);
426
427 if (nbr_nbma->nbr)
428 {
429 nbr_nbma->nbr->nbr_nbma = NULL;
430 nbr_nbma->nbr = NULL;
431 }
432
433 if (nbr_nbma->oi)
434 {
435 listnode_delete (nbr_nbma->oi->nbr_nbma, nbr_nbma);
436 nbr_nbma->oi = NULL;
437 }
438
439 XFREE (MTYPE_OSPF_NEIGHBOR_STATIC, nbr_nbma);
440 }
441
442 route_table_finish (ospf->nbr_nbma);
443
444 /* Clear networks and Areas. */
445 for (rn = route_top (ospf->networks); rn; rn = route_next (rn))
446 {
447 struct ospf_network *network;
448
449 if ((network = rn->info) != NULL)
450 {
paul68980082003-03-25 05:07:42 +0000451 ospf_network_free (ospf, network);
paul718e3742002-12-13 20:15:29 +0000452 rn->info = NULL;
453 route_unlock_node (rn);
454 }
455 }
456
paul1eb8ef22005-04-07 07:30:20 +0000457 for (ALL_LIST_ELEMENTS (ospf->areas, node, nnode, area))
paul718e3742002-12-13 20:15:29 +0000458 {
paul718e3742002-12-13 20:15:29 +0000459 listnode_delete (ospf->areas, area);
460 ospf_area_free (area);
461 }
462
463 /* Cancel all timers. */
464 OSPF_TIMER_OFF (ospf->t_external_lsa);
paul718e3742002-12-13 20:15:29 +0000465 OSPF_TIMER_OFF (ospf->t_router_lsa_update);
466 OSPF_TIMER_OFF (ospf->t_spf_calc);
467 OSPF_TIMER_OFF (ospf->t_ase_calc);
468 OSPF_TIMER_OFF (ospf->t_maxage);
469 OSPF_TIMER_OFF (ospf->t_maxage_walker);
470 OSPF_TIMER_OFF (ospf->t_abr_task);
paul88d6cf32005-10-29 12:50:09 +0000471 OSPF_TIMER_OFF (ospf->t_asbr_check);
paul718e3742002-12-13 20:15:29 +0000472 OSPF_TIMER_OFF (ospf->t_distribute_update);
473 OSPF_TIMER_OFF (ospf->t_lsa_refresher);
474 OSPF_TIMER_OFF (ospf->t_read);
475 OSPF_TIMER_OFF (ospf->t_write);
paul31a59762005-11-14 11:11:11 +0000476#ifdef HAVE_OPAQUE_LSA
paul88d6cf32005-10-29 12:50:09 +0000477 OSPF_TIMER_OFF (ospf->t_opaque_lsa_self);
paul31a59762005-11-14 11:11:11 +0000478#endif
paul718e3742002-12-13 20:15:29 +0000479
480 close (ospf->fd);
ajs5c333492005-02-23 15:43:01 +0000481 stream_free(ospf->ibuf);
paul718e3742002-12-13 20:15:29 +0000482
483#ifdef HAVE_OPAQUE_LSA
paul68980082003-03-25 05:07:42 +0000484 LSDB_LOOP (OPAQUE_AS_LSDB (ospf), rn, lsa)
485 ospf_discard_from_db (ospf, ospf->lsdb, lsa);
paul718e3742002-12-13 20:15:29 +0000486#endif /* HAVE_OPAQUE_LSA */
paul68980082003-03-25 05:07:42 +0000487 LSDB_LOOP (EXTERNAL_LSDB (ospf), rn, lsa)
488 ospf_discard_from_db (ospf, ospf->lsdb, lsa);
489
paul718e3742002-12-13 20:15:29 +0000490 ospf_lsdb_delete_all (ospf->lsdb);
491 ospf_lsdb_free (ospf->lsdb);
492
paul1eb8ef22005-04-07 07:30:20 +0000493 for (ALL_LIST_ELEMENTS (ospf->maxage_lsa, node, nnode, lsa))
Paul Jakma1fe6ed32006-07-26 09:37:26 +0000494 ospf_lsa_unlock (&lsa); /* maxage_lsa */
paul718e3742002-12-13 20:15:29 +0000495
496 list_delete (ospf->maxage_lsa);
497
498 if (ospf->old_table)
499 ospf_route_table_free (ospf->old_table);
500 if (ospf->new_table)
501 {
502 ospf_route_delete (ospf->new_table);
503 ospf_route_table_free (ospf->new_table);
504 }
505 if (ospf->old_rtrs)
506 ospf_rtrs_free (ospf->old_rtrs);
507 if (ospf->new_rtrs)
508 ospf_rtrs_free (ospf->new_rtrs);
509 if (ospf->new_external_route)
510 {
511 ospf_route_delete (ospf->new_external_route);
512 ospf_route_table_free (ospf->new_external_route);
513 }
514 if (ospf->old_external_route)
515 {
516 ospf_route_delete (ospf->old_external_route);
517 ospf_route_table_free (ospf->old_external_route);
518 }
519 if (ospf->external_lsas)
520 {
521 ospf_ase_external_lsas_finish (ospf->external_lsas);
522 }
523
524 list_delete (ospf->areas);
525
526 for (i = ZEBRA_ROUTE_SYSTEM; i <= ZEBRA_ROUTE_MAX; i++)
527 if (EXTERNAL_INFO (i) != NULL)
528 for (rn = route_top (EXTERNAL_INFO (i)); rn; rn = route_next (rn))
529 {
530 if (rn->info == NULL)
531 continue;
532
533 XFREE (MTYPE_OSPF_EXTERNAL_INFO, rn->info);
534 rn->info = NULL;
535 route_unlock_node (rn);
536 }
537
paul68980082003-03-25 05:07:42 +0000538 ospf_distance_reset (ospf);
paul718e3742002-12-13 20:15:29 +0000539 route_table_finish (ospf->distance_table);
540
paul020709f2003-04-04 02:44:16 +0000541 ospf_delete (ospf);
paul718e3742002-12-13 20:15:29 +0000542
paul020709f2003-04-04 02:44:16 +0000543 XFREE (MTYPE_OSPF_TOP, ospf);
paul718e3742002-12-13 20:15:29 +0000544}
545
546
547/* allocate new OSPF Area object */
paul4dadc292005-05-06 21:37:42 +0000548static struct ospf_area *
paul68980082003-03-25 05:07:42 +0000549ospf_area_new (struct ospf *ospf, struct in_addr area_id)
paul718e3742002-12-13 20:15:29 +0000550{
551 struct ospf_area *new;
552
553 /* Allocate new config_network. */
554 new = XCALLOC (MTYPE_OSPF_AREA, sizeof (struct ospf_area));
555
paul68980082003-03-25 05:07:42 +0000556 new->ospf = ospf;
paul718e3742002-12-13 20:15:29 +0000557
558 new->area_id = area_id;
559
560 new->external_routing = OSPF_AREA_DEFAULT;
561 new->default_cost = 1;
562 new->auth_type = OSPF_AUTH_NULL;
paul88d6cf32005-10-29 12:50:09 +0000563
paul718e3742002-12-13 20:15:29 +0000564 /* New LSDB init. */
565 new->lsdb = ospf_lsdb_new ();
566
567 /* Self-originated LSAs initialize. */
568 new->router_lsa_self = NULL;
569
570#ifdef HAVE_OPAQUE_LSA
571 ospf_opaque_type10_lsa_init (new);
572#endif /* HAVE_OPAQUE_LSA */
573
574 new->oiflist = list_new ();
575 new->ranges = route_table_init ();
576
577 if (area_id.s_addr == OSPF_AREA_BACKBONE)
paul68980082003-03-25 05:07:42 +0000578 ospf->backbone = new;
paul718e3742002-12-13 20:15:29 +0000579
580 return new;
581}
582
583void
584ospf_area_free (struct ospf_area *area)
585{
paul68980082003-03-25 05:07:42 +0000586 struct route_node *rn;
587 struct ospf_lsa *lsa;
588
paul718e3742002-12-13 20:15:29 +0000589 /* Free LSDBs. */
paul68980082003-03-25 05:07:42 +0000590 LSDB_LOOP (ROUTER_LSDB (area), rn, lsa)
591 ospf_discard_from_db (area->ospf, area->lsdb, lsa);
592 LSDB_LOOP (NETWORK_LSDB (area), rn, lsa)
593 ospf_discard_from_db (area->ospf, area->lsdb, lsa);
594 LSDB_LOOP (SUMMARY_LSDB (area), rn, lsa)
595 ospf_discard_from_db (area->ospf, area->lsdb, lsa);
596 LSDB_LOOP (ASBR_SUMMARY_LSDB (area), rn, lsa)
597 ospf_discard_from_db (area->ospf, area->lsdb, lsa);
paul718e3742002-12-13 20:15:29 +0000598
paul68980082003-03-25 05:07:42 +0000599 LSDB_LOOP (NSSA_LSDB (area), rn, lsa)
600 ospf_discard_from_db (area->ospf, area->lsdb, lsa);
paul718e3742002-12-13 20:15:29 +0000601#ifdef HAVE_OPAQUE_LSA
paul68980082003-03-25 05:07:42 +0000602 LSDB_LOOP (OPAQUE_AREA_LSDB (area), rn, lsa)
603 ospf_discard_from_db (area->ospf, area->lsdb, lsa);
604 LSDB_LOOP (OPAQUE_LINK_LSDB (area), rn, lsa)
605 ospf_discard_from_db (area->ospf, area->lsdb, lsa);
paul718e3742002-12-13 20:15:29 +0000606#endif /* HAVE_OPAQUE_LSA */
607
608 ospf_lsdb_delete_all (area->lsdb);
609 ospf_lsdb_free (area->lsdb);
610
Paul Jakma1fe6ed32006-07-26 09:37:26 +0000611 ospf_lsa_unlock (&area->router_lsa_self);
paul718e3742002-12-13 20:15:29 +0000612
613 route_table_finish (area->ranges);
614 list_delete (area->oiflist);
615
616 if (EXPORT_NAME (area))
617 free (EXPORT_NAME (area));
618
619 if (IMPORT_NAME (area))
620 free (IMPORT_NAME (area));
621
622 /* Cancel timer. */
623 OSPF_TIMER_OFF (area->t_router_lsa_self);
paul88d6cf32005-10-29 12:50:09 +0000624 OSPF_TIMER_OFF (area->t_stub_router);
625#ifdef HAVE_OPAQUE_LSA
626 OSPF_TIMER_OFF (area->t_opaque_lsa_self);
627#endif /* HAVE_OPAQUE_LSA */
628
paul718e3742002-12-13 20:15:29 +0000629 if (OSPF_IS_AREA_BACKBONE (area))
paul68980082003-03-25 05:07:42 +0000630 area->ospf->backbone = NULL;
paul718e3742002-12-13 20:15:29 +0000631
632 XFREE (MTYPE_OSPF_AREA, area);
633}
634
635void
paul68980082003-03-25 05:07:42 +0000636ospf_area_check_free (struct ospf *ospf, struct in_addr area_id)
paul718e3742002-12-13 20:15:29 +0000637{
638 struct ospf_area *area;
639
paul68980082003-03-25 05:07:42 +0000640 area = ospf_area_lookup_by_area_id (ospf, area_id);
paul718e3742002-12-13 20:15:29 +0000641 if (area &&
642 listcount (area->oiflist) == 0 &&
643 area->ranges->top == NULL &&
644 area->shortcut_configured == OSPF_SHORTCUT_DEFAULT &&
645 area->external_routing == OSPF_AREA_DEFAULT &&
646 area->no_summary == 0 &&
647 area->default_cost == 1 &&
648 EXPORT_NAME (area) == NULL &&
649 IMPORT_NAME (area) == NULL &&
650 area->auth_type == OSPF_AUTH_NULL)
651 {
paul68980082003-03-25 05:07:42 +0000652 listnode_delete (ospf->areas, area);
paul718e3742002-12-13 20:15:29 +0000653 ospf_area_free (area);
654 }
655}
656
657struct ospf_area *
paul68980082003-03-25 05:07:42 +0000658ospf_area_get (struct ospf *ospf, struct in_addr area_id, int format)
paul718e3742002-12-13 20:15:29 +0000659{
660 struct ospf_area *area;
661
paul68980082003-03-25 05:07:42 +0000662 area = ospf_area_lookup_by_area_id (ospf, area_id);
paul718e3742002-12-13 20:15:29 +0000663 if (!area)
664 {
paul68980082003-03-25 05:07:42 +0000665 area = ospf_area_new (ospf, area_id);
paul718e3742002-12-13 20:15:29 +0000666 area->format = format;
paul68980082003-03-25 05:07:42 +0000667 listnode_add_sort (ospf->areas, area);
668 ospf_check_abr_status (ospf);
paul718e3742002-12-13 20:15:29 +0000669 }
670
671 return area;
672}
673
674struct ospf_area *
paul68980082003-03-25 05:07:42 +0000675ospf_area_lookup_by_area_id (struct ospf *ospf, struct in_addr area_id)
paul718e3742002-12-13 20:15:29 +0000676{
677 struct ospf_area *area;
hasso52dc7ee2004-09-23 19:18:23 +0000678 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000679
paul1eb8ef22005-04-07 07:30:20 +0000680 for (ALL_LIST_ELEMENTS_RO (ospf->areas, node, area))
681 if (IPV4_ADDR_SAME (&area->area_id, &area_id))
682 return area;
paul718e3742002-12-13 20:15:29 +0000683
684 return NULL;
685}
686
687void
688ospf_area_add_if (struct ospf_area *area, struct ospf_interface *oi)
689{
690 listnode_add (area->oiflist, oi);
691}
692
693void
694ospf_area_del_if (struct ospf_area *area, struct ospf_interface *oi)
695{
696 listnode_delete (area->oiflist, oi);
697}
698
699
700/* Config network statement related functions. */
paul4dadc292005-05-06 21:37:42 +0000701static struct ospf_network *
paul718e3742002-12-13 20:15:29 +0000702ospf_network_new (struct in_addr area_id, int format)
703{
704 struct ospf_network *new;
705 new = XCALLOC (MTYPE_OSPF_NETWORK, sizeof (struct ospf_network));
706
707 new->area_id = area_id;
708 new->format = format;
709
710 return new;
711}
712
713void
paul68980082003-03-25 05:07:42 +0000714ospf_network_free (struct ospf *ospf, struct ospf_network *network)
paul718e3742002-12-13 20:15:29 +0000715{
paul68980082003-03-25 05:07:42 +0000716 ospf_area_check_free (ospf, network->area_id);
717 ospf_schedule_abr_task (ospf);
paul718e3742002-12-13 20:15:29 +0000718 XFREE (MTYPE_OSPF_NETWORK, network);
719}
720
721int
722ospf_network_set (struct ospf *ospf, struct prefix_ipv4 *p,
723 struct in_addr area_id)
724{
725 struct ospf_network *network;
726 struct ospf_area *area;
727 struct route_node *rn;
728 struct external_info *ei;
paul147193a2003-04-19 00:31:59 +0000729 int ret = OSPF_AREA_ID_FORMAT_ADDRESS;
paul718e3742002-12-13 20:15:29 +0000730
731 rn = route_node_get (ospf->networks, (struct prefix *)p);
732 if (rn->info)
733 {
734 /* There is already same network statement. */
735 route_unlock_node (rn);
736 return 0;
737 }
738
739 rn->info = network = ospf_network_new (area_id, ret);
paul68980082003-03-25 05:07:42 +0000740 area = ospf_area_get (ospf, area_id, ret);
paul718e3742002-12-13 20:15:29 +0000741
742 /* Run network config now. */
743 ospf_network_run (ospf, (struct prefix *)p, area);
744
745 /* Update connected redistribute. */
746 if (ospf_is_type_redistributed (ZEBRA_ROUTE_CONNECT))
747 if (EXTERNAL_INFO (ZEBRA_ROUTE_CONNECT))
748 for (rn = route_top (EXTERNAL_INFO (ZEBRA_ROUTE_CONNECT));
749 rn; rn = route_next (rn))
750 if ((ei = rn->info) != NULL)
paul68980082003-03-25 05:07:42 +0000751 if (ospf_external_info_find_lsa (ospf, &ei->p))
752 if (!ospf_distribute_check_connected (ospf, ei))
753 ospf_external_lsa_flush (ospf, ei->type, &ei->p,
ajs5339cfd2005-09-19 13:28:05 +0000754 ei->ifindex /*, ei->nexthop */);
paul718e3742002-12-13 20:15:29 +0000755
paul68980082003-03-25 05:07:42 +0000756 ospf_area_check_free (ospf, area_id);
paul718e3742002-12-13 20:15:29 +0000757
758 return 1;
759}
760
761int
762ospf_network_unset (struct ospf *ospf, struct prefix_ipv4 *p,
763 struct in_addr area_id)
764{
765 struct route_node *rn;
766 struct ospf_network *network;
767 struct external_info *ei;
768
769 rn = route_node_lookup (ospf->networks, (struct prefix *)p);
770 if (rn == NULL)
771 return 0;
772
773 network = rn->info;
774 if (!IPV4_ADDR_SAME (&area_id, &network->area_id))
775 return 0;
776
paul68980082003-03-25 05:07:42 +0000777 ospf_network_free (ospf, rn->info);
paul718e3742002-12-13 20:15:29 +0000778 rn->info = NULL;
779 route_unlock_node (rn);
780
paul68980082003-03-25 05:07:42 +0000781 ospf_if_update (ospf);
paul718e3742002-12-13 20:15:29 +0000782
783 /* Update connected redistribute. */
784 if (ospf_is_type_redistributed (ZEBRA_ROUTE_CONNECT))
785 if (EXTERNAL_INFO (ZEBRA_ROUTE_CONNECT))
786 for (rn = route_top (EXTERNAL_INFO (ZEBRA_ROUTE_CONNECT));
787 rn; rn = route_next (rn))
788 if ((ei = rn->info) != NULL)
paul68980082003-03-25 05:07:42 +0000789 if (!ospf_external_info_find_lsa (ospf, &ei->p))
790 if (ospf_distribute_check_connected (ospf, ei))
791 ospf_external_lsa_originate (ospf, ei);
paul718e3742002-12-13 20:15:29 +0000792
793 return 1;
794}
795
paul570f7592003-01-25 06:47:41 +0000796/* Check whether interface matches given network
797 * returns: 1, true. 0, false
798 */
799int
800ospf_network_match_iface(struct connected *co, struct prefix *net)
801{
Andrew J. Schorre4529632006-12-12 19:18:21 +0000802#define COMPATIBILITY_MODE
803 /* The old code used to have a special case for PtP interfaces:
804
805 if (if_is_pointopoint (co->ifp) && co->destination &&
806 IPV4_ADDR_SAME ( &(co->destination->u.prefix4), &(net->u.prefix4)))
807 return 1;
808
809 The new approach is much more general. If a peer address is supplied,
810 then we are routing to that prefix, so that's the address to compare
811 against (not the local address, which may not be unique).
812 */
813#ifndef COMPATIBILITY_MODE
814 /* new approach: more elegant and conceptually clean */
815 return prefix_match(net, CONNECTED_PREFIX(co));
816#else /* COMPATIBILITY_MODE */
817 /* match old (strange?) behavior */
818
paul570f7592003-01-25 06:47:41 +0000819 /* Behaviour to match both Cisco where:
820 * iface address lies within network specified -> ospf
821 * and zebra 0.9[2ish-3]:
822 * PtP special case: network specified == iface peer addr -> ospf
823 */
gdt8f40e892003-12-05 14:01:43 +0000824
paulf3ae74c2004-11-04 20:35:31 +0000825 /* For PtP, match if peer address matches network address exactly.
826 * This can be addr/32 or addr/p for p < 32, but the addr must match
827 * exactly; this is not a test for falling within the prefix. This
gdt8f40e892003-12-05 14:01:43 +0000828 * test is solely for compatibility with zebra.
gdt8f40e892003-12-05 14:01:43 +0000829 */
Andrew J. Schorre4529632006-12-12 19:18:21 +0000830 if (CONNECTED_PEER(co) &&
paulf3ae74c2004-11-04 20:35:31 +0000831 IPV4_ADDR_SAME ( &(co->destination->u.prefix4), &(net->u.prefix4)))
832 return 1;
833
834#if 0
835 /* Decline to accept PtP if dst address does not match the
836 * prefix. (ifdefed out because this is a workaround, not the
837 * desired behavior.) */
838 if (if_is_pointopoint (co->ifp) &&
839 ! prefix_match (net, co->destination))
840 return 0;
841#endif
842
843 /* If the address is within the prefix, accept. Note that this
844 * applies to PtP as well as other types.
845 */
846 if (prefix_match (net, co->address))
847 return 1;
848
849 return 0; /* no match */
Andrew J. Schorre4529632006-12-12 19:18:21 +0000850
851#endif /* COMPATIBILITY_MODE */
paul570f7592003-01-25 06:47:41 +0000852}
853
paul718e3742002-12-13 20:15:29 +0000854void
855ospf_network_run (struct ospf *ospf, struct prefix *p, struct ospf_area *area)
856{
857 struct interface *ifp;
paul1eb8ef22005-04-07 07:30:20 +0000858 struct connected *co;
hasso52dc7ee2004-09-23 19:18:23 +0000859 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000860
861 /* Schedule Router ID Update. */
paul86752842006-01-10 20:34:46 +0000862 if (ospf->router_id.s_addr == 0)
paulb29800a2005-11-20 14:50:45 +0000863 ospf_router_id_update (ospf);
864
paul718e3742002-12-13 20:15:29 +0000865 /* Get target interface. */
paul1eb8ef22005-04-07 07:30:20 +0000866 for (ALL_LIST_ELEMENTS_RO (om->iflist, node, ifp))
paul718e3742002-12-13 20:15:29 +0000867 {
paul1eb8ef22005-04-07 07:30:20 +0000868 struct listnode *cnode;
paul718e3742002-12-13 20:15:29 +0000869
paul718e3742002-12-13 20:15:29 +0000870 if (memcmp (ifp->name, "VLINK", 5) == 0)
871 continue;
872
873 /* if interface prefix is match specified prefix,
874 then create socket and join multicast group. */
paul1eb8ef22005-04-07 07:30:20 +0000875 for (ALL_LIST_ELEMENTS_RO (ifp->connected, cnode, co))
paul718e3742002-12-13 20:15:29 +0000876 {
paul718e3742002-12-13 20:15:29 +0000877 struct prefix *addr;
paul800dc102003-03-28 01:51:40 +0000878
paule7b050c2003-04-07 06:38:02 +0000879 if (CHECK_FLAG(co->flags,ZEBRA_IFA_SECONDARY))
880 continue;
paul718e3742002-12-13 20:15:29 +0000881
Andrew J. Schorre4529632006-12-12 19:18:21 +0000882 addr = CONNECTED_ID(co);
paul718e3742002-12-13 20:15:29 +0000883
paulcb3f37d2003-02-18 23:26:37 +0000884 if (p->family == co->address->family
paul68980082003-03-25 05:07:42 +0000885 && ! ospf_if_is_configured (ospf, &(addr->u.prefix4))
paulcb3f37d2003-02-18 23:26:37 +0000886 && ospf_network_match_iface(co,p))
paul570f7592003-01-25 06:47:41 +0000887 {
paul1eb8ef22005-04-07 07:30:20 +0000888 struct ospf_interface *oi;
paul718e3742002-12-13 20:15:29 +0000889
paul68980082003-03-25 05:07:42 +0000890 oi = ospf_if_new (ospf, ifp, co->address);
paul718e3742002-12-13 20:15:29 +0000891 oi->connected = co;
892
paul718e3742002-12-13 20:15:29 +0000893 oi->area = area;
894
895 oi->params = ospf_lookup_if_params (ifp, oi->address->u.prefix4);
896 oi->output_cost = ospf_if_get_output_cost (oi);
897
paul718e3742002-12-13 20:15:29 +0000898 /* Add pseudo neighbor. */
899 ospf_nbr_add_self (oi);
900
paul718e3742002-12-13 20:15:29 +0000901 /* Relate ospf interface to ospf instance. */
paul68980082003-03-25 05:07:42 +0000902 oi->ospf = ospf;
paul718e3742002-12-13 20:15:29 +0000903
904 /* update network type as interface flag */
905 /* If network type is specified previously,
906 skip network type setting. */
907 oi->type = IF_DEF_PARAMS (ifp)->type;
908
paul718e3742002-12-13 20:15:29 +0000909 ospf_area_add_if (oi->area, oi);
paulb29800a2005-11-20 14:50:45 +0000910
911 /* if router_id is not configured, dont bring up
912 * interfaces.
913 * ospf_router_id_update() will call ospf_if_update
914 * whenever r-id is configured instead.
915 */
paul86752842006-01-10 20:34:46 +0000916 if ((ospf->router_id.s_addr != 0)
paulb29800a2005-11-20 14:50:45 +0000917 && if_is_operative (ifp))
paul718e3742002-12-13 20:15:29 +0000918 ospf_if_up (oi);
paul718e3742002-12-13 20:15:29 +0000919 }
920 }
921 }
922}
923
924void
925ospf_ls_upd_queue_empty (struct ospf_interface *oi)
926{
927 struct route_node *rn;
paul1eb8ef22005-04-07 07:30:20 +0000928 struct listnode *node, *nnode;
hasso52dc7ee2004-09-23 19:18:23 +0000929 struct list *lst;
paul718e3742002-12-13 20:15:29 +0000930 struct ospf_lsa *lsa;
931
932 /* empty ls update queue */
933 for (rn = route_top (oi->ls_upd_queue); rn;
934 rn = route_next (rn))
hasso52dc7ee2004-09-23 19:18:23 +0000935 if ((lst = (struct list *) rn->info))
paul718e3742002-12-13 20:15:29 +0000936 {
paul1eb8ef22005-04-07 07:30:20 +0000937 for (ALL_LIST_ELEMENTS (lst, node, nnode, lsa))
Paul Jakma1fe6ed32006-07-26 09:37:26 +0000938 ospf_lsa_unlock (&lsa); /* oi->ls_upd_queue */
paul718e3742002-12-13 20:15:29 +0000939 list_free (lst);
940 rn->info = NULL;
941 }
942
943 /* remove update event */
944 if (oi->t_ls_upd_event)
945 {
946 thread_cancel (oi->t_ls_upd_event);
947 oi->t_ls_upd_event = NULL;
948 }
949}
950
951void
paul68980082003-03-25 05:07:42 +0000952ospf_if_update (struct ospf *ospf)
paul718e3742002-12-13 20:15:29 +0000953{
954 struct route_node *rn;
paul1eb8ef22005-04-07 07:30:20 +0000955 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000956 struct ospf_network *network;
957 struct ospf_area *area;
paul1eb8ef22005-04-07 07:30:20 +0000958 struct ospf_interface *oi;
paul718e3742002-12-13 20:15:29 +0000959
paul68980082003-03-25 05:07:42 +0000960 if (ospf != NULL)
paul718e3742002-12-13 20:15:29 +0000961 {
paulb29800a2005-11-20 14:50:45 +0000962 /* Router-ID must be configured. */
paul86752842006-01-10 20:34:46 +0000963 if (ospf->router_id.s_addr == 0)
paulb29800a2005-11-20 14:50:45 +0000964 return;
965
paul718e3742002-12-13 20:15:29 +0000966 /* Find interfaces that not configured already. */
paul1eb8ef22005-04-07 07:30:20 +0000967 for (ALL_LIST_ELEMENTS (ospf->oiflist, node, nnode, oi))
paul718e3742002-12-13 20:15:29 +0000968 {
969 int found = 0;
paul718e3742002-12-13 20:15:29 +0000970 struct connected *co = oi->connected;
971
paul718e3742002-12-13 20:15:29 +0000972 if (oi->type == OSPF_IFTYPE_VIRTUALLINK)
973 continue;
974
paul68980082003-03-25 05:07:42 +0000975 for (rn = route_top (ospf->networks); rn; rn = route_next (rn))
paul718e3742002-12-13 20:15:29 +0000976 {
977 if (rn->info == NULL)
978 continue;
979
paul570f7592003-01-25 06:47:41 +0000980 if (ospf_network_match_iface(co,&rn->p))
paul718e3742002-12-13 20:15:29 +0000981 {
982 found = 1;
983 route_unlock_node (rn);
984 break;
985 }
986 }
987
988 if (found == 0)
989 ospf_if_free (oi);
990 }
991
992 /* Run each interface. */
paul68980082003-03-25 05:07:42 +0000993 for (rn = route_top (ospf->networks); rn; rn = route_next (rn))
paul718e3742002-12-13 20:15:29 +0000994 if (rn->info != NULL)
995 {
996 network = (struct ospf_network *) rn->info;
paul68980082003-03-25 05:07:42 +0000997 area = ospf_area_get (ospf, network->area_id, network->format);
998 ospf_network_run (ospf, &rn->p, area);
paul718e3742002-12-13 20:15:29 +0000999 }
1000 }
1001}
1002
1003void
paul68980082003-03-25 05:07:42 +00001004ospf_remove_vls_through_area (struct ospf *ospf, struct ospf_area *area)
paul718e3742002-12-13 20:15:29 +00001005{
paul1eb8ef22005-04-07 07:30:20 +00001006 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001007 struct ospf_vl_data *vl_data;
1008
paul1eb8ef22005-04-07 07:30:20 +00001009 for (ALL_LIST_ELEMENTS (ospf->vlinks, node, nnode, vl_data))
1010 if (IPV4_ADDR_SAME (&vl_data->vl_area_id, &area->area_id))
1011 ospf_vl_delete (ospf, vl_data);
paul718e3742002-12-13 20:15:29 +00001012}
1013
1014
1015struct message ospf_area_type_msg[] =
1016{
1017 { OSPF_AREA_DEFAULT, "Default" },
1018 { OSPF_AREA_STUB, "Stub" },
1019 { OSPF_AREA_NSSA, "NSSA" },
1020};
1021int ospf_area_type_msg_max = OSPF_AREA_TYPE_MAX;
1022
paul4dadc292005-05-06 21:37:42 +00001023static void
paul718e3742002-12-13 20:15:29 +00001024ospf_area_type_set (struct ospf_area *area, int type)
1025{
hasso52dc7ee2004-09-23 19:18:23 +00001026 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00001027 struct ospf_interface *oi;
1028
1029 if (area->external_routing == type)
1030 {
1031 if (IS_DEBUG_OSPF_EVENT)
ajs9b0e25c2004-12-08 19:06:51 +00001032 zlog_debug ("Area[%s]: Types are the same, ignored.",
paul718e3742002-12-13 20:15:29 +00001033 inet_ntoa (area->area_id));
1034 return;
1035 }
1036
1037 area->external_routing = type;
1038
1039 if (IS_DEBUG_OSPF_EVENT)
ajs9b0e25c2004-12-08 19:06:51 +00001040 zlog_debug ("Area[%s]: Configured as %s", inet_ntoa (area->area_id),
paul718e3742002-12-13 20:15:29 +00001041 LOOKUP (ospf_area_type_msg, type));
1042
1043 switch (area->external_routing)
1044 {
1045 case OSPF_AREA_DEFAULT:
paul1eb8ef22005-04-07 07:30:20 +00001046 for (ALL_LIST_ELEMENTS_RO (area->oiflist, node, oi))
1047 if (oi->nbr_self != NULL)
1048 {
1049 UNSET_FLAG (oi->nbr_self->options, OSPF_OPTION_NP);
1050 SET_FLAG (oi->nbr_self->options, OSPF_OPTION_E);
1051 }
paul718e3742002-12-13 20:15:29 +00001052 break;
1053 case OSPF_AREA_STUB:
paul1eb8ef22005-04-07 07:30:20 +00001054 for (ALL_LIST_ELEMENTS_RO (area->oiflist, node, oi))
1055 if (oi->nbr_self != NULL)
1056 {
1057 if (IS_DEBUG_OSPF_EVENT)
1058 zlog_debug ("setting options on %s accordingly", IF_NAME (oi));
1059 UNSET_FLAG (oi->nbr_self->options, OSPF_OPTION_NP);
1060 UNSET_FLAG (oi->nbr_self->options, OSPF_OPTION_E);
1061 if (IS_DEBUG_OSPF_EVENT)
1062 zlog_debug ("options set on %s: %x",
1063 IF_NAME (oi), OPTIONS (oi));
1064 }
paul718e3742002-12-13 20:15:29 +00001065 break;
1066 case OSPF_AREA_NSSA:
paul1eb8ef22005-04-07 07:30:20 +00001067 for (ALL_LIST_ELEMENTS_RO (area->oiflist, node, oi))
1068 if (oi->nbr_self != NULL)
1069 {
1070 zlog_debug ("setting nssa options on %s accordingly", IF_NAME (oi));
1071 UNSET_FLAG (oi->nbr_self->options, OSPF_OPTION_E);
1072 SET_FLAG (oi->nbr_self->options, OSPF_OPTION_NP);
1073 zlog_debug ("options set on %s: %x", IF_NAME (oi), OPTIONS (oi));
1074 }
paul718e3742002-12-13 20:15:29 +00001075 break;
1076 default:
1077 break;
1078 }
1079
1080 ospf_router_lsa_timer_add (area);
paul68980082003-03-25 05:07:42 +00001081 ospf_schedule_abr_task (area->ospf);
paul718e3742002-12-13 20:15:29 +00001082}
1083
1084int
paul68980082003-03-25 05:07:42 +00001085ospf_area_shortcut_set (struct ospf *ospf, struct ospf_area *area, int mode)
paul718e3742002-12-13 20:15:29 +00001086{
1087 if (area->shortcut_configured == mode)
1088 return 0;
1089
1090 area->shortcut_configured = mode;
1091 ospf_router_lsa_timer_add (area);
paul68980082003-03-25 05:07:42 +00001092 ospf_schedule_abr_task (ospf);
paul718e3742002-12-13 20:15:29 +00001093
paul68980082003-03-25 05:07:42 +00001094 ospf_area_check_free (ospf, area->area_id);
paul718e3742002-12-13 20:15:29 +00001095
1096 return 1;
1097}
1098
1099int
paul68980082003-03-25 05:07:42 +00001100ospf_area_shortcut_unset (struct ospf *ospf, struct ospf_area *area)
paul718e3742002-12-13 20:15:29 +00001101{
1102 area->shortcut_configured = OSPF_SHORTCUT_DEFAULT;
1103 ospf_router_lsa_timer_add (area);
paul68980082003-03-25 05:07:42 +00001104 ospf_area_check_free (ospf, area->area_id);
1105 ospf_schedule_abr_task (ospf);
paul718e3742002-12-13 20:15:29 +00001106
1107 return 1;
1108}
1109
paul4dadc292005-05-06 21:37:42 +00001110static int
paul718e3742002-12-13 20:15:29 +00001111ospf_area_vlink_count (struct ospf *ospf, struct ospf_area *area)
1112{
1113 struct ospf_vl_data *vl;
hasso52dc7ee2004-09-23 19:18:23 +00001114 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00001115 int count = 0;
1116
paul1eb8ef22005-04-07 07:30:20 +00001117 for (ALL_LIST_ELEMENTS_RO (ospf->vlinks, node, vl))
1118 if (IPV4_ADDR_SAME (&vl->vl_area_id, &area->area_id))
1119 count++;
paul718e3742002-12-13 20:15:29 +00001120
1121 return count;
1122}
1123
1124int
1125ospf_area_stub_set (struct ospf *ospf, struct in_addr area_id)
1126{
1127 struct ospf_area *area;
paul147193a2003-04-19 00:31:59 +00001128 int format = OSPF_AREA_ID_FORMAT_ADDRESS;
paul718e3742002-12-13 20:15:29 +00001129
paul68980082003-03-25 05:07:42 +00001130 area = ospf_area_get (ospf, area_id, format);
paul718e3742002-12-13 20:15:29 +00001131 if (ospf_area_vlink_count (ospf, area))
1132 return 0;
1133
1134 if (area->external_routing != OSPF_AREA_STUB)
1135 ospf_area_type_set (area, OSPF_AREA_STUB);
1136
1137 return 1;
1138}
1139
1140int
1141ospf_area_stub_unset (struct ospf *ospf, struct in_addr area_id)
1142{
1143 struct ospf_area *area;
1144
paul68980082003-03-25 05:07:42 +00001145 area = ospf_area_lookup_by_area_id (ospf, area_id);
paul718e3742002-12-13 20:15:29 +00001146 if (area == NULL)
1147 return 1;
1148
1149 if (area->external_routing == OSPF_AREA_STUB)
1150 ospf_area_type_set (area, OSPF_AREA_DEFAULT);
1151
paul68980082003-03-25 05:07:42 +00001152 ospf_area_check_free (ospf, area_id);
paul718e3742002-12-13 20:15:29 +00001153
1154 return 1;
1155}
1156
1157int
1158ospf_area_no_summary_set (struct ospf *ospf, struct in_addr area_id)
1159{
1160 struct ospf_area *area;
paul147193a2003-04-19 00:31:59 +00001161 int format = OSPF_AREA_ID_FORMAT_ADDRESS;
paul718e3742002-12-13 20:15:29 +00001162
paul68980082003-03-25 05:07:42 +00001163 area = ospf_area_get (ospf, area_id, format);
paul718e3742002-12-13 20:15:29 +00001164 area->no_summary = 1;
1165
1166 return 1;
1167}
1168
1169int
1170ospf_area_no_summary_unset (struct ospf *ospf, struct in_addr area_id)
1171{
1172 struct ospf_area *area;
1173
paul68980082003-03-25 05:07:42 +00001174 area = ospf_area_lookup_by_area_id (ospf, area_id);
paul718e3742002-12-13 20:15:29 +00001175 if (area == NULL)
1176 return 0;
1177
1178 area->no_summary = 0;
paul68980082003-03-25 05:07:42 +00001179 ospf_area_check_free (ospf, area_id);
paul718e3742002-12-13 20:15:29 +00001180
1181 return 1;
1182}
1183
1184int
1185ospf_area_nssa_set (struct ospf *ospf, struct in_addr area_id)
1186{
1187 struct ospf_area *area;
paul147193a2003-04-19 00:31:59 +00001188 int format = OSPF_AREA_ID_FORMAT_ADDRESS;
paul718e3742002-12-13 20:15:29 +00001189
paul68980082003-03-25 05:07:42 +00001190 area = ospf_area_get (ospf, area_id, format);
paul718e3742002-12-13 20:15:29 +00001191 if (ospf_area_vlink_count (ospf, area))
1192 return 0;
1193
1194 if (area->external_routing != OSPF_AREA_NSSA)
1195 {
1196 ospf_area_type_set (area, OSPF_AREA_NSSA);
1197 ospf->anyNSSA++;
1198 }
1199
paul084c7842003-06-22 08:35:18 +00001200 /* set NSSA area defaults */
1201 area->no_summary = 0;
1202 area->NSSATranslatorRole = OSPF_NSSA_ROLE_CANDIDATE;
pauld4a53d52003-07-12 21:30:57 +00001203 area->NSSATranslatorState = OSPF_NSSA_TRANSLATE_DISABLED;
paul084c7842003-06-22 08:35:18 +00001204 area->NSSATranslatorStabilityInterval = OSPF_NSSA_TRANS_STABLE_DEFAULT;
1205
paul718e3742002-12-13 20:15:29 +00001206 return 1;
1207}
1208
1209int
1210ospf_area_nssa_unset (struct ospf *ospf, struct in_addr area_id)
1211{
1212 struct ospf_area *area;
1213
paul68980082003-03-25 05:07:42 +00001214 area = ospf_area_lookup_by_area_id (ospf, area_id);
paul718e3742002-12-13 20:15:29 +00001215 if (area == NULL)
1216 return 0;
1217
1218 if (area->external_routing == OSPF_AREA_NSSA)
1219 {
1220 ospf->anyNSSA--;
1221 ospf_area_type_set (area, OSPF_AREA_DEFAULT);
1222 }
1223
paul68980082003-03-25 05:07:42 +00001224 ospf_area_check_free (ospf, area_id);
paul718e3742002-12-13 20:15:29 +00001225
1226 return 1;
1227}
1228
1229int
1230ospf_area_nssa_translator_role_set (struct ospf *ospf, struct in_addr area_id,
1231 int role)
1232{
1233 struct ospf_area *area;
1234
paul68980082003-03-25 05:07:42 +00001235 area = ospf_area_lookup_by_area_id (ospf, area_id);
paul718e3742002-12-13 20:15:29 +00001236 if (area == NULL)
1237 return 0;
1238
paul084c7842003-06-22 08:35:18 +00001239 area->NSSATranslatorRole = role;
paul718e3742002-12-13 20:15:29 +00001240
1241 return 1;
1242}
1243
paul4dadc292005-05-06 21:37:42 +00001244/* XXX: unused? Leave for symmetry? */
1245static int
paul718e3742002-12-13 20:15:29 +00001246ospf_area_nssa_translator_role_unset (struct ospf *ospf,
1247 struct in_addr area_id)
1248{
1249 struct ospf_area *area;
1250
paul68980082003-03-25 05:07:42 +00001251 area = ospf_area_lookup_by_area_id (ospf, area_id);
paul718e3742002-12-13 20:15:29 +00001252 if (area == NULL)
1253 return 0;
1254
paul084c7842003-06-22 08:35:18 +00001255 area->NSSATranslatorRole = OSPF_NSSA_ROLE_CANDIDATE;
paul718e3742002-12-13 20:15:29 +00001256
paul68980082003-03-25 05:07:42 +00001257 ospf_area_check_free (ospf, area_id);
paul718e3742002-12-13 20:15:29 +00001258
1259 return 1;
1260}
1261
1262int
paul68980082003-03-25 05:07:42 +00001263ospf_area_export_list_set (struct ospf *ospf,
paul6c835672004-10-11 11:00:30 +00001264 struct ospf_area *area, const char *list_name)
paul718e3742002-12-13 20:15:29 +00001265{
1266 struct access_list *list;
1267 list = access_list_lookup (AFI_IP, list_name);
1268
1269 EXPORT_LIST (area) = list;
1270
1271 if (EXPORT_NAME (area))
1272 free (EXPORT_NAME (area));
1273
1274 EXPORT_NAME (area) = strdup (list_name);
paul68980082003-03-25 05:07:42 +00001275 ospf_schedule_abr_task (ospf);
paul718e3742002-12-13 20:15:29 +00001276
1277 return 1;
1278}
1279
1280int
paul68980082003-03-25 05:07:42 +00001281ospf_area_export_list_unset (struct ospf *ospf, struct ospf_area * area)
paul718e3742002-12-13 20:15:29 +00001282{
1283
1284 EXPORT_LIST (area) = 0;
1285
1286 if (EXPORT_NAME (area))
1287 free (EXPORT_NAME (area));
1288
1289 EXPORT_NAME (area) = NULL;
1290
paul68980082003-03-25 05:07:42 +00001291 ospf_area_check_free (ospf, area->area_id);
paul718e3742002-12-13 20:15:29 +00001292
paul68980082003-03-25 05:07:42 +00001293 ospf_schedule_abr_task (ospf);
paul718e3742002-12-13 20:15:29 +00001294
1295 return 1;
1296}
1297
1298int
paul6c835672004-10-11 11:00:30 +00001299ospf_area_import_list_set (struct ospf *ospf, struct ospf_area *area,
1300 const char *name)
paul718e3742002-12-13 20:15:29 +00001301{
1302 struct access_list *list;
1303 list = access_list_lookup (AFI_IP, name);
1304
1305 IMPORT_LIST (area) = list;
1306
1307 if (IMPORT_NAME (area))
1308 free (IMPORT_NAME (area));
1309
1310 IMPORT_NAME (area) = strdup (name);
paul68980082003-03-25 05:07:42 +00001311 ospf_schedule_abr_task (ospf);
paul718e3742002-12-13 20:15:29 +00001312
1313 return 1;
1314}
1315
1316int
paul68980082003-03-25 05:07:42 +00001317ospf_area_import_list_unset (struct ospf *ospf, struct ospf_area * area)
paul718e3742002-12-13 20:15:29 +00001318{
1319 IMPORT_LIST (area) = 0;
1320
1321 if (IMPORT_NAME (area))
1322 free (IMPORT_NAME (area));
1323
1324 IMPORT_NAME (area) = NULL;
paul68980082003-03-25 05:07:42 +00001325 ospf_area_check_free (ospf, area->area_id);
paul718e3742002-12-13 20:15:29 +00001326
paul68980082003-03-25 05:07:42 +00001327 ospf_schedule_abr_task (ospf);
paul718e3742002-12-13 20:15:29 +00001328
1329 return 1;
1330}
1331
1332int
paul718e3742002-12-13 20:15:29 +00001333ospf_timers_refresh_set (struct ospf *ospf, int interval)
1334{
1335 int time_left;
1336
1337 if (ospf->lsa_refresh_interval == interval)
1338 return 1;
1339
1340 time_left = ospf->lsa_refresh_interval -
Paul Jakma2518efd2006-08-27 06:49:29 +00001341 (quagga_time (NULL) - ospf->lsa_refresher_started);
paul718e3742002-12-13 20:15:29 +00001342
1343 if (time_left > interval)
1344 {
1345 OSPF_TIMER_OFF (ospf->t_lsa_refresher);
1346 ospf->t_lsa_refresher =
1347 thread_add_timer (master, ospf_lsa_refresh_walker, ospf, interval);
1348 }
1349 ospf->lsa_refresh_interval = interval;
1350
1351 return 1;
1352}
1353
1354int
1355ospf_timers_refresh_unset (struct ospf *ospf)
1356{
1357 int time_left;
1358
1359 time_left = ospf->lsa_refresh_interval -
Paul Jakma2518efd2006-08-27 06:49:29 +00001360 (quagga_time (NULL) - ospf->lsa_refresher_started);
paul718e3742002-12-13 20:15:29 +00001361
1362 if (time_left > OSPF_LSA_REFRESH_INTERVAL_DEFAULT)
1363 {
1364 OSPF_TIMER_OFF (ospf->t_lsa_refresher);
1365 ospf->t_lsa_refresher =
1366 thread_add_timer (master, ospf_lsa_refresh_walker, ospf,
1367 OSPF_LSA_REFRESH_INTERVAL_DEFAULT);
1368 }
1369
1370 ospf->lsa_refresh_interval = OSPF_LSA_REFRESH_INTERVAL_DEFAULT;
1371
1372 return 1;
1373}
1374
1375
paul4dadc292005-05-06 21:37:42 +00001376static struct ospf_nbr_nbma *
1377ospf_nbr_nbma_new (void)
paul718e3742002-12-13 20:15:29 +00001378{
1379 struct ospf_nbr_nbma *nbr_nbma;
1380
1381 nbr_nbma = XMALLOC (MTYPE_OSPF_NEIGHBOR_STATIC,
1382 sizeof (struct ospf_nbr_nbma));
1383 memset (nbr_nbma, 0, sizeof (struct ospf_nbr_nbma));
1384
1385 nbr_nbma->priority = OSPF_NEIGHBOR_PRIORITY_DEFAULT;
1386 nbr_nbma->v_poll = OSPF_POLL_INTERVAL_DEFAULT;
1387
1388 return nbr_nbma;
1389}
1390
paul4dadc292005-05-06 21:37:42 +00001391static void
paul718e3742002-12-13 20:15:29 +00001392ospf_nbr_nbma_free (struct ospf_nbr_nbma *nbr_nbma)
1393{
1394 XFREE (MTYPE_OSPF_NEIGHBOR_STATIC, nbr_nbma);
1395}
1396
paul4dadc292005-05-06 21:37:42 +00001397static void
paul718e3742002-12-13 20:15:29 +00001398ospf_nbr_nbma_delete (struct ospf *ospf, struct ospf_nbr_nbma *nbr_nbma)
1399{
1400 struct route_node *rn;
1401 struct prefix_ipv4 p;
1402
1403 p.family = AF_INET;
1404 p.prefix = nbr_nbma->addr;
1405 p.prefixlen = IPV4_MAX_BITLEN;
1406
1407 rn = route_node_lookup (ospf->nbr_nbma, (struct prefix *)&p);
1408 if (rn)
1409 {
1410 ospf_nbr_nbma_free (rn->info);
1411 rn->info = NULL;
1412 route_unlock_node (rn);
1413 route_unlock_node (rn);
1414 }
1415}
1416
paul4dadc292005-05-06 21:37:42 +00001417static void
paul718e3742002-12-13 20:15:29 +00001418ospf_nbr_nbma_down (struct ospf_nbr_nbma *nbr_nbma)
1419{
1420 OSPF_TIMER_OFF (nbr_nbma->t_poll);
1421
1422 if (nbr_nbma->nbr)
1423 {
1424 nbr_nbma->nbr->nbr_nbma = NULL;
1425 OSPF_NSM_EVENT_EXECUTE (nbr_nbma->nbr, NSM_KillNbr);
1426 }
1427
1428 if (nbr_nbma->oi)
1429 listnode_delete (nbr_nbma->oi->nbr_nbma, nbr_nbma);
1430}
1431
paul4dadc292005-05-06 21:37:42 +00001432static void
paul718e3742002-12-13 20:15:29 +00001433ospf_nbr_nbma_add (struct ospf_nbr_nbma *nbr_nbma,
1434 struct ospf_interface *oi)
1435{
1436 struct ospf_neighbor *nbr;
1437 struct route_node *rn;
1438 struct prefix p;
1439
1440 if (oi->type != OSPF_IFTYPE_NBMA)
1441 return;
1442
1443 if (nbr_nbma->nbr != NULL)
1444 return;
1445
1446 if (IPV4_ADDR_SAME (&oi->nbr_self->address.u.prefix4, &nbr_nbma->addr))
1447 return;
1448
1449 nbr_nbma->oi = oi;
1450 listnode_add (oi->nbr_nbma, nbr_nbma);
1451
1452 /* Get neighbor information from table. */
1453 p.family = AF_INET;
1454 p.prefixlen = IPV4_MAX_BITLEN;
1455 p.u.prefix4 = nbr_nbma->addr;
1456
1457 rn = route_node_get (oi->nbrs, (struct prefix *)&p);
1458 if (rn->info)
1459 {
1460 nbr = rn->info;
1461 nbr->nbr_nbma = nbr_nbma;
1462 nbr_nbma->nbr = nbr;
1463
1464 route_unlock_node (rn);
1465 }
1466 else
1467 {
1468 nbr = rn->info = ospf_nbr_new (oi);
1469 nbr->state = NSM_Down;
1470 nbr->src = nbr_nbma->addr;
1471 nbr->nbr_nbma = nbr_nbma;
1472 nbr->priority = nbr_nbma->priority;
1473 nbr->address = p;
1474
1475 nbr_nbma->nbr = nbr;
1476
1477 OSPF_NSM_EVENT_EXECUTE (nbr, NSM_Start);
1478 }
1479}
1480
1481void
paul68980082003-03-25 05:07:42 +00001482ospf_nbr_nbma_if_update (struct ospf *ospf, struct ospf_interface *oi)
paul718e3742002-12-13 20:15:29 +00001483{
1484 struct ospf_nbr_nbma *nbr_nbma;
1485 struct route_node *rn;
1486 struct prefix_ipv4 p;
1487
1488 if (oi->type != OSPF_IFTYPE_NBMA)
1489 return;
1490
paul68980082003-03-25 05:07:42 +00001491 for (rn = route_top (ospf->nbr_nbma); rn; rn = route_next (rn))
paul718e3742002-12-13 20:15:29 +00001492 if ((nbr_nbma = rn->info))
1493 if (nbr_nbma->oi == NULL && nbr_nbma->nbr == NULL)
1494 {
1495 p.family = AF_INET;
1496 p.prefix = nbr_nbma->addr;
1497 p.prefixlen = IPV4_MAX_BITLEN;
1498
1499 if (prefix_match (oi->address, (struct prefix *)&p))
1500 ospf_nbr_nbma_add (nbr_nbma, oi);
1501 }
1502}
1503
1504struct ospf_nbr_nbma *
1505ospf_nbr_nbma_lookup (struct ospf *ospf, struct in_addr nbr_addr)
1506{
1507 struct route_node *rn;
1508 struct prefix_ipv4 p;
1509
1510 p.family = AF_INET;
1511 p.prefix = nbr_addr;
1512 p.prefixlen = IPV4_MAX_BITLEN;
1513
1514 rn = route_node_lookup (ospf->nbr_nbma, (struct prefix *)&p);
1515 if (rn)
1516 {
1517 route_unlock_node (rn);
1518 return rn->info;
1519 }
1520 return NULL;
1521}
1522
1523struct ospf_nbr_nbma *
paul68980082003-03-25 05:07:42 +00001524ospf_nbr_nbma_lookup_next (struct ospf *ospf, struct in_addr *addr, int first)
paul718e3742002-12-13 20:15:29 +00001525{
1526#if 0
1527 struct ospf_nbr_nbma *nbr_nbma;
hasso52dc7ee2004-09-23 19:18:23 +00001528 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00001529#endif
1530
paul68980082003-03-25 05:07:42 +00001531 if (ospf == NULL)
paul718e3742002-12-13 20:15:29 +00001532 return NULL;
1533
1534#if 0
paul1eb8ef22005-04-07 07:30:20 +00001535 for (ALL_LIST_ELEMENTS_RO (ospf->nbr_nbma, node, nbr_nbma))
paul718e3742002-12-13 20:15:29 +00001536 {
paul718e3742002-12-13 20:15:29 +00001537 if (first)
1538 {
1539 *addr = nbr_nbma->addr;
1540 return nbr_nbma;
1541 }
1542 else if (ntohl (nbr_nbma->addr.s_addr) > ntohl (addr->s_addr))
1543 {
1544 *addr = nbr_nbma->addr;
1545 return nbr_nbma;
1546 }
1547 }
1548#endif
1549 return NULL;
1550}
1551
1552int
1553ospf_nbr_nbma_set (struct ospf *ospf, struct in_addr nbr_addr)
1554{
1555 struct ospf_nbr_nbma *nbr_nbma;
1556 struct ospf_interface *oi;
1557 struct prefix_ipv4 p;
1558 struct route_node *rn;
hasso52dc7ee2004-09-23 19:18:23 +00001559 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00001560
1561 nbr_nbma = ospf_nbr_nbma_lookup (ospf, nbr_addr);
1562 if (nbr_nbma)
1563 return 0;
1564
1565 nbr_nbma = ospf_nbr_nbma_new ();
1566 nbr_nbma->addr = nbr_addr;
1567
1568 p.family = AF_INET;
1569 p.prefix = nbr_addr;
1570 p.prefixlen = IPV4_MAX_BITLEN;
1571
1572 rn = route_node_get (ospf->nbr_nbma, (struct prefix *)&p);
1573 rn->info = nbr_nbma;
1574
paul1eb8ef22005-04-07 07:30:20 +00001575 for (ALL_LIST_ELEMENTS_RO (ospf->oiflist, node, oi))
paul718e3742002-12-13 20:15:29 +00001576 {
paul718e3742002-12-13 20:15:29 +00001577 if (oi->type == OSPF_IFTYPE_NBMA)
1578 if (prefix_match (oi->address, (struct prefix *)&p))
1579 {
1580 ospf_nbr_nbma_add (nbr_nbma, oi);
1581 break;
1582 }
1583 }
1584
1585 return 1;
1586}
1587
1588int
1589ospf_nbr_nbma_unset (struct ospf *ospf, struct in_addr nbr_addr)
1590{
1591 struct ospf_nbr_nbma *nbr_nbma;
1592
1593 nbr_nbma = ospf_nbr_nbma_lookup (ospf, nbr_addr);
1594 if (nbr_nbma == NULL)
1595 return 0;
1596
1597 ospf_nbr_nbma_down (nbr_nbma);
1598 ospf_nbr_nbma_delete (ospf, nbr_nbma);
1599
1600 return 1;
1601}
1602
1603int
1604ospf_nbr_nbma_priority_set (struct ospf *ospf, struct in_addr nbr_addr,
1605 u_char priority)
1606{
1607 struct ospf_nbr_nbma *nbr_nbma;
1608
1609 nbr_nbma = ospf_nbr_nbma_lookup (ospf, nbr_addr);
1610 if (nbr_nbma == NULL)
1611 return 0;
1612
1613 if (nbr_nbma->priority != priority)
1614 nbr_nbma->priority = priority;
1615
1616 return 1;
1617}
1618
1619int
1620ospf_nbr_nbma_priority_unset (struct ospf *ospf, struct in_addr nbr_addr)
1621{
1622 struct ospf_nbr_nbma *nbr_nbma;
1623
1624 nbr_nbma = ospf_nbr_nbma_lookup (ospf, nbr_addr);
1625 if (nbr_nbma == NULL)
1626 return 0;
1627
1628 if (nbr_nbma != OSPF_NEIGHBOR_PRIORITY_DEFAULT)
1629 nbr_nbma->priority = OSPF_NEIGHBOR_PRIORITY_DEFAULT;
1630
1631 return 1;
1632}
1633
1634int
1635ospf_nbr_nbma_poll_interval_set (struct ospf *ospf, struct in_addr nbr_addr,
paul6c835672004-10-11 11:00:30 +00001636 unsigned int interval)
paul718e3742002-12-13 20:15:29 +00001637{
1638 struct ospf_nbr_nbma *nbr_nbma;
1639
1640 nbr_nbma = ospf_nbr_nbma_lookup (ospf, nbr_addr);
1641 if (nbr_nbma == NULL)
1642 return 0;
1643
1644 if (nbr_nbma->v_poll != interval)
1645 {
1646 nbr_nbma->v_poll = interval;
1647 if (nbr_nbma->oi && ospf_if_is_up (nbr_nbma->oi))
1648 {
1649 OSPF_TIMER_OFF (nbr_nbma->t_poll);
1650 OSPF_POLL_TIMER_ON (nbr_nbma->t_poll, ospf_poll_timer,
1651 nbr_nbma->v_poll);
1652 }
1653 }
1654
1655 return 1;
1656}
1657
1658int
1659ospf_nbr_nbma_poll_interval_unset (struct ospf *ospf, struct in_addr addr)
1660{
1661 struct ospf_nbr_nbma *nbr_nbma;
1662
1663 nbr_nbma = ospf_nbr_nbma_lookup (ospf, addr);
1664 if (nbr_nbma == NULL)
1665 return 0;
1666
1667 if (nbr_nbma->v_poll != OSPF_POLL_INTERVAL_DEFAULT)
1668 nbr_nbma->v_poll = OSPF_POLL_INTERVAL_DEFAULT;
1669
1670 return 1;
1671}
1672
paul718e3742002-12-13 20:15:29 +00001673void
paul020709f2003-04-04 02:44:16 +00001674ospf_master_init ()
1675{
1676 memset (&ospf_master, 0, sizeof (struct ospf_master));
1677
1678 om = &ospf_master;
1679 om->ospf = list_new ();
1680 om->master = thread_master_create ();
Paul Jakma2518efd2006-08-27 06:49:29 +00001681 om->start_time = quagga_time (NULL);
paul020709f2003-04-04 02:44:16 +00001682}