blob: 8ef80cb3c398cad33ea1adc19abf8f32a8782581 [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
358 for (ALL_LIST_ELEMENTS (om->ospf, node, nnode, ospf))
359 ospf_finish (ospf);
360
361 /* Deliberately go back up, hopefully to thread scheduler, as
362 * One or more ospf_finish()'s may have deferred shutdown to a timer
363 * thread
364 */
365}
paul718e3742002-12-13 20:15:29 +0000366
367void
368ospf_finish (struct ospf *ospf)
369{
paulc9c93d52005-11-26 13:31:11 +0000370 /* let deferred shutdown decide */
371 ospf_deferred_shutdown_check (ospf);
paul88d6cf32005-10-29 12:50:09 +0000372
paulc9c93d52005-11-26 13:31:11 +0000373 /* if ospf_deferred_shutdown returns, then ospf_finish_final is
paul88d6cf32005-10-29 12:50:09 +0000374 * deferred to expiry of G-S timer thread. Return back up, hopefully
375 * to thread scheduler.
376 */
paulc9c93d52005-11-26 13:31:11 +0000377 return;
paul88d6cf32005-10-29 12:50:09 +0000378}
379
380/* Final cleanup of ospf instance */
381static void
382ospf_finish_final (struct ospf *ospf)
383{
paul718e3742002-12-13 20:15:29 +0000384 struct route_node *rn;
385 struct ospf_nbr_nbma *nbr_nbma;
paul68980082003-03-25 05:07:42 +0000386 struct ospf_lsa *lsa;
paul1eb8ef22005-04-07 07:30:20 +0000387 struct ospf_interface *oi;
388 struct ospf_area *area;
389 struct ospf_vl_data *vl_data;
390 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000391 int i;
392
393#ifdef HAVE_OPAQUE_LSA
394 ospf_opaque_type11_lsa_term (ospf);
395#endif /* HAVE_OPAQUE_LSA */
paul88d6cf32005-10-29 12:50:09 +0000396
397 /* be nice if this worked, but it doesn't */
398 /*ospf_flush_self_originated_lsas_now (ospf);*/
399
400 /* Unregister redistribution */
paul718e3742002-12-13 20:15:29 +0000401 for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
paul020709f2003-04-04 02:44:16 +0000402 ospf_redistribute_unset (ospf, i);
Paul Jakma29b5a042006-08-27 08:01:20 +0000403 ospf_redistribute_default_unset (ospf);
paul718e3742002-12-13 20:15:29 +0000404
paul1eb8ef22005-04-07 07:30:20 +0000405 for (ALL_LIST_ELEMENTS (ospf->areas, node, nnode, area))
406 ospf_remove_vls_through_area (ospf, area);
paul718e3742002-12-13 20:15:29 +0000407
paul1eb8ef22005-04-07 07:30:20 +0000408 for (ALL_LIST_ELEMENTS (ospf->vlinks, node, nnode, vl_data))
409 ospf_vl_delete (ospf, vl_data);
paul718e3742002-12-13 20:15:29 +0000410
411 list_delete (ospf->vlinks);
412
413 /* Reset interface. */
paul1eb8ef22005-04-07 07:30:20 +0000414 for (ALL_LIST_ELEMENTS (ospf->oiflist, node, nnode, oi))
415 ospf_if_free (oi);
paul718e3742002-12-13 20:15:29 +0000416
417 /* Clear static neighbors */
418 for (rn = route_top (ospf->nbr_nbma); rn; rn = route_next (rn))
419 if ((nbr_nbma = rn->info))
420 {
421 OSPF_POLL_TIMER_OFF (nbr_nbma->t_poll);
422
423 if (nbr_nbma->nbr)
424 {
425 nbr_nbma->nbr->nbr_nbma = NULL;
426 nbr_nbma->nbr = NULL;
427 }
428
429 if (nbr_nbma->oi)
430 {
431 listnode_delete (nbr_nbma->oi->nbr_nbma, nbr_nbma);
432 nbr_nbma->oi = NULL;
433 }
434
435 XFREE (MTYPE_OSPF_NEIGHBOR_STATIC, nbr_nbma);
436 }
437
438 route_table_finish (ospf->nbr_nbma);
439
440 /* Clear networks and Areas. */
441 for (rn = route_top (ospf->networks); rn; rn = route_next (rn))
442 {
443 struct ospf_network *network;
444
445 if ((network = rn->info) != NULL)
446 {
paul68980082003-03-25 05:07:42 +0000447 ospf_network_free (ospf, network);
paul718e3742002-12-13 20:15:29 +0000448 rn->info = NULL;
449 route_unlock_node (rn);
450 }
451 }
452
paul1eb8ef22005-04-07 07:30:20 +0000453 for (ALL_LIST_ELEMENTS (ospf->areas, node, nnode, area))
paul718e3742002-12-13 20:15:29 +0000454 {
paul718e3742002-12-13 20:15:29 +0000455 listnode_delete (ospf->areas, area);
456 ospf_area_free (area);
457 }
458
459 /* Cancel all timers. */
460 OSPF_TIMER_OFF (ospf->t_external_lsa);
paul718e3742002-12-13 20:15:29 +0000461 OSPF_TIMER_OFF (ospf->t_router_lsa_update);
462 OSPF_TIMER_OFF (ospf->t_spf_calc);
463 OSPF_TIMER_OFF (ospf->t_ase_calc);
464 OSPF_TIMER_OFF (ospf->t_maxage);
465 OSPF_TIMER_OFF (ospf->t_maxage_walker);
466 OSPF_TIMER_OFF (ospf->t_abr_task);
paul88d6cf32005-10-29 12:50:09 +0000467 OSPF_TIMER_OFF (ospf->t_asbr_check);
paul718e3742002-12-13 20:15:29 +0000468 OSPF_TIMER_OFF (ospf->t_distribute_update);
469 OSPF_TIMER_OFF (ospf->t_lsa_refresher);
470 OSPF_TIMER_OFF (ospf->t_read);
471 OSPF_TIMER_OFF (ospf->t_write);
paul31a59762005-11-14 11:11:11 +0000472#ifdef HAVE_OPAQUE_LSA
paul88d6cf32005-10-29 12:50:09 +0000473 OSPF_TIMER_OFF (ospf->t_opaque_lsa_self);
paul31a59762005-11-14 11:11:11 +0000474#endif
paul718e3742002-12-13 20:15:29 +0000475
476 close (ospf->fd);
ajs5c333492005-02-23 15:43:01 +0000477 stream_free(ospf->ibuf);
paul718e3742002-12-13 20:15:29 +0000478
479#ifdef HAVE_OPAQUE_LSA
paul68980082003-03-25 05:07:42 +0000480 LSDB_LOOP (OPAQUE_AS_LSDB (ospf), rn, lsa)
481 ospf_discard_from_db (ospf, ospf->lsdb, lsa);
paul718e3742002-12-13 20:15:29 +0000482#endif /* HAVE_OPAQUE_LSA */
paul68980082003-03-25 05:07:42 +0000483 LSDB_LOOP (EXTERNAL_LSDB (ospf), rn, lsa)
484 ospf_discard_from_db (ospf, ospf->lsdb, lsa);
485
paul718e3742002-12-13 20:15:29 +0000486 ospf_lsdb_delete_all (ospf->lsdb);
487 ospf_lsdb_free (ospf->lsdb);
488
paul1eb8ef22005-04-07 07:30:20 +0000489 for (ALL_LIST_ELEMENTS (ospf->maxage_lsa, node, nnode, lsa))
Paul Jakma1fe6ed32006-07-26 09:37:26 +0000490 ospf_lsa_unlock (&lsa); /* maxage_lsa */
paul718e3742002-12-13 20:15:29 +0000491
492 list_delete (ospf->maxage_lsa);
493
494 if (ospf->old_table)
495 ospf_route_table_free (ospf->old_table);
496 if (ospf->new_table)
497 {
498 ospf_route_delete (ospf->new_table);
499 ospf_route_table_free (ospf->new_table);
500 }
501 if (ospf->old_rtrs)
502 ospf_rtrs_free (ospf->old_rtrs);
503 if (ospf->new_rtrs)
504 ospf_rtrs_free (ospf->new_rtrs);
505 if (ospf->new_external_route)
506 {
507 ospf_route_delete (ospf->new_external_route);
508 ospf_route_table_free (ospf->new_external_route);
509 }
510 if (ospf->old_external_route)
511 {
512 ospf_route_delete (ospf->old_external_route);
513 ospf_route_table_free (ospf->old_external_route);
514 }
515 if (ospf->external_lsas)
516 {
517 ospf_ase_external_lsas_finish (ospf->external_lsas);
518 }
519
520 list_delete (ospf->areas);
521
522 for (i = ZEBRA_ROUTE_SYSTEM; i <= ZEBRA_ROUTE_MAX; i++)
523 if (EXTERNAL_INFO (i) != NULL)
524 for (rn = route_top (EXTERNAL_INFO (i)); rn; rn = route_next (rn))
525 {
526 if (rn->info == NULL)
527 continue;
528
529 XFREE (MTYPE_OSPF_EXTERNAL_INFO, rn->info);
530 rn->info = NULL;
531 route_unlock_node (rn);
532 }
533
paul68980082003-03-25 05:07:42 +0000534 ospf_distance_reset (ospf);
paul718e3742002-12-13 20:15:29 +0000535 route_table_finish (ospf->distance_table);
536
paul020709f2003-04-04 02:44:16 +0000537 ospf_delete (ospf);
paul718e3742002-12-13 20:15:29 +0000538
paul020709f2003-04-04 02:44:16 +0000539 XFREE (MTYPE_OSPF_TOP, ospf);
paul718e3742002-12-13 20:15:29 +0000540}
541
542
543/* allocate new OSPF Area object */
paul4dadc292005-05-06 21:37:42 +0000544static struct ospf_area *
paul68980082003-03-25 05:07:42 +0000545ospf_area_new (struct ospf *ospf, struct in_addr area_id)
paul718e3742002-12-13 20:15:29 +0000546{
547 struct ospf_area *new;
548
549 /* Allocate new config_network. */
550 new = XCALLOC (MTYPE_OSPF_AREA, sizeof (struct ospf_area));
551
paul68980082003-03-25 05:07:42 +0000552 new->ospf = ospf;
paul718e3742002-12-13 20:15:29 +0000553
554 new->area_id = area_id;
555
556 new->external_routing = OSPF_AREA_DEFAULT;
557 new->default_cost = 1;
558 new->auth_type = OSPF_AUTH_NULL;
paul88d6cf32005-10-29 12:50:09 +0000559
paul718e3742002-12-13 20:15:29 +0000560 /* New LSDB init. */
561 new->lsdb = ospf_lsdb_new ();
562
563 /* Self-originated LSAs initialize. */
564 new->router_lsa_self = NULL;
565
566#ifdef HAVE_OPAQUE_LSA
567 ospf_opaque_type10_lsa_init (new);
568#endif /* HAVE_OPAQUE_LSA */
569
570 new->oiflist = list_new ();
571 new->ranges = route_table_init ();
572
573 if (area_id.s_addr == OSPF_AREA_BACKBONE)
paul68980082003-03-25 05:07:42 +0000574 ospf->backbone = new;
paul718e3742002-12-13 20:15:29 +0000575
576 return new;
577}
578
579void
580ospf_area_free (struct ospf_area *area)
581{
paul68980082003-03-25 05:07:42 +0000582 struct route_node *rn;
583 struct ospf_lsa *lsa;
584
paul718e3742002-12-13 20:15:29 +0000585 /* Free LSDBs. */
paul68980082003-03-25 05:07:42 +0000586 LSDB_LOOP (ROUTER_LSDB (area), rn, lsa)
587 ospf_discard_from_db (area->ospf, area->lsdb, lsa);
588 LSDB_LOOP (NETWORK_LSDB (area), rn, lsa)
589 ospf_discard_from_db (area->ospf, area->lsdb, lsa);
590 LSDB_LOOP (SUMMARY_LSDB (area), rn, lsa)
591 ospf_discard_from_db (area->ospf, area->lsdb, lsa);
592 LSDB_LOOP (ASBR_SUMMARY_LSDB (area), rn, lsa)
593 ospf_discard_from_db (area->ospf, area->lsdb, lsa);
paul718e3742002-12-13 20:15:29 +0000594
paul68980082003-03-25 05:07:42 +0000595 LSDB_LOOP (NSSA_LSDB (area), rn, lsa)
596 ospf_discard_from_db (area->ospf, area->lsdb, lsa);
paul718e3742002-12-13 20:15:29 +0000597#ifdef HAVE_OPAQUE_LSA
paul68980082003-03-25 05:07:42 +0000598 LSDB_LOOP (OPAQUE_AREA_LSDB (area), rn, lsa)
599 ospf_discard_from_db (area->ospf, area->lsdb, lsa);
600 LSDB_LOOP (OPAQUE_LINK_LSDB (area), rn, lsa)
601 ospf_discard_from_db (area->ospf, area->lsdb, lsa);
paul718e3742002-12-13 20:15:29 +0000602#endif /* HAVE_OPAQUE_LSA */
603
604 ospf_lsdb_delete_all (area->lsdb);
605 ospf_lsdb_free (area->lsdb);
606
Paul Jakma1fe6ed32006-07-26 09:37:26 +0000607 ospf_lsa_unlock (&area->router_lsa_self);
paul718e3742002-12-13 20:15:29 +0000608
609 route_table_finish (area->ranges);
610 list_delete (area->oiflist);
611
612 if (EXPORT_NAME (area))
613 free (EXPORT_NAME (area));
614
615 if (IMPORT_NAME (area))
616 free (IMPORT_NAME (area));
617
618 /* Cancel timer. */
619 OSPF_TIMER_OFF (area->t_router_lsa_self);
paul88d6cf32005-10-29 12:50:09 +0000620 OSPF_TIMER_OFF (area->t_stub_router);
621#ifdef HAVE_OPAQUE_LSA
622 OSPF_TIMER_OFF (area->t_opaque_lsa_self);
623#endif /* HAVE_OPAQUE_LSA */
624
paul718e3742002-12-13 20:15:29 +0000625 if (OSPF_IS_AREA_BACKBONE (area))
paul68980082003-03-25 05:07:42 +0000626 area->ospf->backbone = NULL;
paul718e3742002-12-13 20:15:29 +0000627
628 XFREE (MTYPE_OSPF_AREA, area);
629}
630
631void
paul68980082003-03-25 05:07:42 +0000632ospf_area_check_free (struct ospf *ospf, struct in_addr area_id)
paul718e3742002-12-13 20:15:29 +0000633{
634 struct ospf_area *area;
635
paul68980082003-03-25 05:07:42 +0000636 area = ospf_area_lookup_by_area_id (ospf, area_id);
paul718e3742002-12-13 20:15:29 +0000637 if (area &&
638 listcount (area->oiflist) == 0 &&
639 area->ranges->top == NULL &&
640 area->shortcut_configured == OSPF_SHORTCUT_DEFAULT &&
641 area->external_routing == OSPF_AREA_DEFAULT &&
642 area->no_summary == 0 &&
643 area->default_cost == 1 &&
644 EXPORT_NAME (area) == NULL &&
645 IMPORT_NAME (area) == NULL &&
646 area->auth_type == OSPF_AUTH_NULL)
647 {
paul68980082003-03-25 05:07:42 +0000648 listnode_delete (ospf->areas, area);
paul718e3742002-12-13 20:15:29 +0000649 ospf_area_free (area);
650 }
651}
652
653struct ospf_area *
paul68980082003-03-25 05:07:42 +0000654ospf_area_get (struct ospf *ospf, struct in_addr area_id, int format)
paul718e3742002-12-13 20:15:29 +0000655{
656 struct ospf_area *area;
657
paul68980082003-03-25 05:07:42 +0000658 area = ospf_area_lookup_by_area_id (ospf, area_id);
paul718e3742002-12-13 20:15:29 +0000659 if (!area)
660 {
paul68980082003-03-25 05:07:42 +0000661 area = ospf_area_new (ospf, area_id);
paul718e3742002-12-13 20:15:29 +0000662 area->format = format;
paul68980082003-03-25 05:07:42 +0000663 listnode_add_sort (ospf->areas, area);
664 ospf_check_abr_status (ospf);
paul718e3742002-12-13 20:15:29 +0000665 }
666
667 return area;
668}
669
670struct ospf_area *
paul68980082003-03-25 05:07:42 +0000671ospf_area_lookup_by_area_id (struct ospf *ospf, struct in_addr area_id)
paul718e3742002-12-13 20:15:29 +0000672{
673 struct ospf_area *area;
hasso52dc7ee2004-09-23 19:18:23 +0000674 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000675
paul1eb8ef22005-04-07 07:30:20 +0000676 for (ALL_LIST_ELEMENTS_RO (ospf->areas, node, area))
677 if (IPV4_ADDR_SAME (&area->area_id, &area_id))
678 return area;
paul718e3742002-12-13 20:15:29 +0000679
680 return NULL;
681}
682
683void
684ospf_area_add_if (struct ospf_area *area, struct ospf_interface *oi)
685{
686 listnode_add (area->oiflist, oi);
687}
688
689void
690ospf_area_del_if (struct ospf_area *area, struct ospf_interface *oi)
691{
692 listnode_delete (area->oiflist, oi);
693}
694
695
696/* Config network statement related functions. */
paul4dadc292005-05-06 21:37:42 +0000697static struct ospf_network *
paul718e3742002-12-13 20:15:29 +0000698ospf_network_new (struct in_addr area_id, int format)
699{
700 struct ospf_network *new;
701 new = XCALLOC (MTYPE_OSPF_NETWORK, sizeof (struct ospf_network));
702
703 new->area_id = area_id;
704 new->format = format;
705
706 return new;
707}
708
709void
paul68980082003-03-25 05:07:42 +0000710ospf_network_free (struct ospf *ospf, struct ospf_network *network)
paul718e3742002-12-13 20:15:29 +0000711{
paul68980082003-03-25 05:07:42 +0000712 ospf_area_check_free (ospf, network->area_id);
713 ospf_schedule_abr_task (ospf);
paul718e3742002-12-13 20:15:29 +0000714 XFREE (MTYPE_OSPF_NETWORK, network);
715}
716
717int
718ospf_network_set (struct ospf *ospf, struct prefix_ipv4 *p,
719 struct in_addr area_id)
720{
721 struct ospf_network *network;
722 struct ospf_area *area;
723 struct route_node *rn;
724 struct external_info *ei;
paul147193a2003-04-19 00:31:59 +0000725 int ret = OSPF_AREA_ID_FORMAT_ADDRESS;
paul718e3742002-12-13 20:15:29 +0000726
727 rn = route_node_get (ospf->networks, (struct prefix *)p);
728 if (rn->info)
729 {
730 /* There is already same network statement. */
731 route_unlock_node (rn);
732 return 0;
733 }
734
735 rn->info = network = ospf_network_new (area_id, ret);
paul68980082003-03-25 05:07:42 +0000736 area = ospf_area_get (ospf, area_id, ret);
paul718e3742002-12-13 20:15:29 +0000737
738 /* Run network config now. */
739 ospf_network_run (ospf, (struct prefix *)p, area);
740
741 /* Update connected redistribute. */
742 if (ospf_is_type_redistributed (ZEBRA_ROUTE_CONNECT))
743 if (EXTERNAL_INFO (ZEBRA_ROUTE_CONNECT))
744 for (rn = route_top (EXTERNAL_INFO (ZEBRA_ROUTE_CONNECT));
745 rn; rn = route_next (rn))
746 if ((ei = rn->info) != NULL)
paul68980082003-03-25 05:07:42 +0000747 if (ospf_external_info_find_lsa (ospf, &ei->p))
748 if (!ospf_distribute_check_connected (ospf, ei))
749 ospf_external_lsa_flush (ospf, ei->type, &ei->p,
ajs5339cfd2005-09-19 13:28:05 +0000750 ei->ifindex /*, ei->nexthop */);
paul718e3742002-12-13 20:15:29 +0000751
paul68980082003-03-25 05:07:42 +0000752 ospf_area_check_free (ospf, area_id);
paul718e3742002-12-13 20:15:29 +0000753
754 return 1;
755}
756
757int
758ospf_network_unset (struct ospf *ospf, struct prefix_ipv4 *p,
759 struct in_addr area_id)
760{
761 struct route_node *rn;
762 struct ospf_network *network;
763 struct external_info *ei;
764
765 rn = route_node_lookup (ospf->networks, (struct prefix *)p);
766 if (rn == NULL)
767 return 0;
768
769 network = rn->info;
770 if (!IPV4_ADDR_SAME (&area_id, &network->area_id))
771 return 0;
772
paul68980082003-03-25 05:07:42 +0000773 ospf_network_free (ospf, rn->info);
paul718e3742002-12-13 20:15:29 +0000774 rn->info = NULL;
775 route_unlock_node (rn);
776
paul68980082003-03-25 05:07:42 +0000777 ospf_if_update (ospf);
paul718e3742002-12-13 20:15:29 +0000778
779 /* Update connected redistribute. */
780 if (ospf_is_type_redistributed (ZEBRA_ROUTE_CONNECT))
781 if (EXTERNAL_INFO (ZEBRA_ROUTE_CONNECT))
782 for (rn = route_top (EXTERNAL_INFO (ZEBRA_ROUTE_CONNECT));
783 rn; rn = route_next (rn))
784 if ((ei = rn->info) != NULL)
paul68980082003-03-25 05:07:42 +0000785 if (!ospf_external_info_find_lsa (ospf, &ei->p))
786 if (ospf_distribute_check_connected (ospf, ei))
787 ospf_external_lsa_originate (ospf, ei);
paul718e3742002-12-13 20:15:29 +0000788
789 return 1;
790}
791
paul570f7592003-01-25 06:47:41 +0000792/* Check whether interface matches given network
793 * returns: 1, true. 0, false
794 */
795int
796ospf_network_match_iface(struct connected *co, struct prefix *net)
797{
798 /* Behaviour to match both Cisco where:
799 * iface address lies within network specified -> ospf
800 * and zebra 0.9[2ish-3]:
801 * PtP special case: network specified == iface peer addr -> ospf
802 */
gdt8f40e892003-12-05 14:01:43 +0000803
paulf3ae74c2004-11-04 20:35:31 +0000804 /* For PtP, match if peer address matches network address exactly.
805 * This can be addr/32 or addr/p for p < 32, but the addr must match
806 * exactly; this is not a test for falling within the prefix. This
gdt8f40e892003-12-05 14:01:43 +0000807 * test is solely for compatibility with zebra.
gdt8f40e892003-12-05 14:01:43 +0000808 */
paulf3ae74c2004-11-04 20:35:31 +0000809 if (if_is_pointopoint (co->ifp) && co->destination &&
810 IPV4_ADDR_SAME ( &(co->destination->u.prefix4), &(net->u.prefix4)))
811 return 1;
812
813#if 0
814 /* Decline to accept PtP if dst address does not match the
815 * prefix. (ifdefed out because this is a workaround, not the
816 * desired behavior.) */
817 if (if_is_pointopoint (co->ifp) &&
818 ! prefix_match (net, co->destination))
819 return 0;
820#endif
821
822 /* If the address is within the prefix, accept. Note that this
823 * applies to PtP as well as other types.
824 */
825 if (prefix_match (net, co->address))
826 return 1;
827
828 return 0; /* no match */
paul570f7592003-01-25 06:47:41 +0000829}
830
paul718e3742002-12-13 20:15:29 +0000831void
832ospf_network_run (struct ospf *ospf, struct prefix *p, struct ospf_area *area)
833{
834 struct interface *ifp;
paul1eb8ef22005-04-07 07:30:20 +0000835 struct connected *co;
hasso52dc7ee2004-09-23 19:18:23 +0000836 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000837
838 /* Schedule Router ID Update. */
paul86752842006-01-10 20:34:46 +0000839 if (ospf->router_id.s_addr == 0)
paulb29800a2005-11-20 14:50:45 +0000840 ospf_router_id_update (ospf);
841
paul718e3742002-12-13 20:15:29 +0000842 /* Get target interface. */
paul1eb8ef22005-04-07 07:30:20 +0000843 for (ALL_LIST_ELEMENTS_RO (om->iflist, node, ifp))
paul718e3742002-12-13 20:15:29 +0000844 {
paul1eb8ef22005-04-07 07:30:20 +0000845 struct listnode *cnode;
paul718e3742002-12-13 20:15:29 +0000846
paul718e3742002-12-13 20:15:29 +0000847 if (memcmp (ifp->name, "VLINK", 5) == 0)
848 continue;
849
850 /* if interface prefix is match specified prefix,
851 then create socket and join multicast group. */
paul1eb8ef22005-04-07 07:30:20 +0000852 for (ALL_LIST_ELEMENTS_RO (ifp->connected, cnode, co))
paul718e3742002-12-13 20:15:29 +0000853 {
paul718e3742002-12-13 20:15:29 +0000854 struct prefix *addr;
paul800dc102003-03-28 01:51:40 +0000855
paule7b050c2003-04-07 06:38:02 +0000856 if (CHECK_FLAG(co->flags,ZEBRA_IFA_SECONDARY))
857 continue;
paul718e3742002-12-13 20:15:29 +0000858
hasso3fb9cd62004-10-19 19:44:43 +0000859 if (CONNECTED_POINTOPOINT_HOST(co))
paul718e3742002-12-13 20:15:29 +0000860 addr = co->destination;
861 else
862 addr = co->address;
863
paulcb3f37d2003-02-18 23:26:37 +0000864 if (p->family == co->address->family
paul68980082003-03-25 05:07:42 +0000865 && ! ospf_if_is_configured (ospf, &(addr->u.prefix4))
paulcb3f37d2003-02-18 23:26:37 +0000866 && ospf_network_match_iface(co,p))
paul570f7592003-01-25 06:47:41 +0000867 {
paul1eb8ef22005-04-07 07:30:20 +0000868 struct ospf_interface *oi;
paul718e3742002-12-13 20:15:29 +0000869
paul68980082003-03-25 05:07:42 +0000870 oi = ospf_if_new (ospf, ifp, co->address);
paul718e3742002-12-13 20:15:29 +0000871 oi->connected = co;
872
paul718e3742002-12-13 20:15:29 +0000873 oi->area = area;
874
875 oi->params = ospf_lookup_if_params (ifp, oi->address->u.prefix4);
876 oi->output_cost = ospf_if_get_output_cost (oi);
877
paul718e3742002-12-13 20:15:29 +0000878 /* Add pseudo neighbor. */
879 ospf_nbr_add_self (oi);
880
paul718e3742002-12-13 20:15:29 +0000881 /* Relate ospf interface to ospf instance. */
paul68980082003-03-25 05:07:42 +0000882 oi->ospf = ospf;
paul718e3742002-12-13 20:15:29 +0000883
884 /* update network type as interface flag */
885 /* If network type is specified previously,
886 skip network type setting. */
887 oi->type = IF_DEF_PARAMS (ifp)->type;
888
paul718e3742002-12-13 20:15:29 +0000889 ospf_area_add_if (oi->area, oi);
paulb29800a2005-11-20 14:50:45 +0000890
891 /* if router_id is not configured, dont bring up
892 * interfaces.
893 * ospf_router_id_update() will call ospf_if_update
894 * whenever r-id is configured instead.
895 */
paul86752842006-01-10 20:34:46 +0000896 if ((ospf->router_id.s_addr != 0)
paulb29800a2005-11-20 14:50:45 +0000897 && if_is_operative (ifp))
paul718e3742002-12-13 20:15:29 +0000898 ospf_if_up (oi);
899
900 break;
901 }
902 }
903 }
904}
905
906void
907ospf_ls_upd_queue_empty (struct ospf_interface *oi)
908{
909 struct route_node *rn;
paul1eb8ef22005-04-07 07:30:20 +0000910 struct listnode *node, *nnode;
hasso52dc7ee2004-09-23 19:18:23 +0000911 struct list *lst;
paul718e3742002-12-13 20:15:29 +0000912 struct ospf_lsa *lsa;
913
914 /* empty ls update queue */
915 for (rn = route_top (oi->ls_upd_queue); rn;
916 rn = route_next (rn))
hasso52dc7ee2004-09-23 19:18:23 +0000917 if ((lst = (struct list *) rn->info))
paul718e3742002-12-13 20:15:29 +0000918 {
paul1eb8ef22005-04-07 07:30:20 +0000919 for (ALL_LIST_ELEMENTS (lst, node, nnode, lsa))
Paul Jakma1fe6ed32006-07-26 09:37:26 +0000920 ospf_lsa_unlock (&lsa); /* oi->ls_upd_queue */
paul718e3742002-12-13 20:15:29 +0000921 list_free (lst);
922 rn->info = NULL;
923 }
924
925 /* remove update event */
926 if (oi->t_ls_upd_event)
927 {
928 thread_cancel (oi->t_ls_upd_event);
929 oi->t_ls_upd_event = NULL;
930 }
931}
932
933void
paul68980082003-03-25 05:07:42 +0000934ospf_if_update (struct ospf *ospf)
paul718e3742002-12-13 20:15:29 +0000935{
936 struct route_node *rn;
paul1eb8ef22005-04-07 07:30:20 +0000937 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000938 struct ospf_network *network;
939 struct ospf_area *area;
paul1eb8ef22005-04-07 07:30:20 +0000940 struct ospf_interface *oi;
paul718e3742002-12-13 20:15:29 +0000941
paul68980082003-03-25 05:07:42 +0000942 if (ospf != NULL)
paul718e3742002-12-13 20:15:29 +0000943 {
paulb29800a2005-11-20 14:50:45 +0000944 /* Router-ID must be configured. */
paul86752842006-01-10 20:34:46 +0000945 if (ospf->router_id.s_addr == 0)
paulb29800a2005-11-20 14:50:45 +0000946 return;
947
paul718e3742002-12-13 20:15:29 +0000948 /* Find interfaces that not configured already. */
paul1eb8ef22005-04-07 07:30:20 +0000949 for (ALL_LIST_ELEMENTS (ospf->oiflist, node, nnode, oi))
paul718e3742002-12-13 20:15:29 +0000950 {
951 int found = 0;
paul718e3742002-12-13 20:15:29 +0000952 struct connected *co = oi->connected;
953
paul718e3742002-12-13 20:15:29 +0000954 if (oi->type == OSPF_IFTYPE_VIRTUALLINK)
955 continue;
956
paul68980082003-03-25 05:07:42 +0000957 for (rn = route_top (ospf->networks); rn; rn = route_next (rn))
paul718e3742002-12-13 20:15:29 +0000958 {
959 if (rn->info == NULL)
960 continue;
961
paul570f7592003-01-25 06:47:41 +0000962 if (ospf_network_match_iface(co,&rn->p))
paul718e3742002-12-13 20:15:29 +0000963 {
964 found = 1;
965 route_unlock_node (rn);
966 break;
967 }
968 }
969
970 if (found == 0)
971 ospf_if_free (oi);
972 }
973
974 /* Run each interface. */
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 if (rn->info != NULL)
977 {
978 network = (struct ospf_network *) rn->info;
paul68980082003-03-25 05:07:42 +0000979 area = ospf_area_get (ospf, network->area_id, network->format);
980 ospf_network_run (ospf, &rn->p, area);
paul718e3742002-12-13 20:15:29 +0000981 }
982 }
983}
984
985void
paul68980082003-03-25 05:07:42 +0000986ospf_remove_vls_through_area (struct ospf *ospf, struct ospf_area *area)
paul718e3742002-12-13 20:15:29 +0000987{
paul1eb8ef22005-04-07 07:30:20 +0000988 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000989 struct ospf_vl_data *vl_data;
990
paul1eb8ef22005-04-07 07:30:20 +0000991 for (ALL_LIST_ELEMENTS (ospf->vlinks, node, nnode, vl_data))
992 if (IPV4_ADDR_SAME (&vl_data->vl_area_id, &area->area_id))
993 ospf_vl_delete (ospf, vl_data);
paul718e3742002-12-13 20:15:29 +0000994}
995
996
997struct message ospf_area_type_msg[] =
998{
999 { OSPF_AREA_DEFAULT, "Default" },
1000 { OSPF_AREA_STUB, "Stub" },
1001 { OSPF_AREA_NSSA, "NSSA" },
1002};
1003int ospf_area_type_msg_max = OSPF_AREA_TYPE_MAX;
1004
paul4dadc292005-05-06 21:37:42 +00001005static void
paul718e3742002-12-13 20:15:29 +00001006ospf_area_type_set (struct ospf_area *area, int type)
1007{
hasso52dc7ee2004-09-23 19:18:23 +00001008 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00001009 struct ospf_interface *oi;
1010
1011 if (area->external_routing == type)
1012 {
1013 if (IS_DEBUG_OSPF_EVENT)
ajs9b0e25c2004-12-08 19:06:51 +00001014 zlog_debug ("Area[%s]: Types are the same, ignored.",
paul718e3742002-12-13 20:15:29 +00001015 inet_ntoa (area->area_id));
1016 return;
1017 }
1018
1019 area->external_routing = type;
1020
1021 if (IS_DEBUG_OSPF_EVENT)
ajs9b0e25c2004-12-08 19:06:51 +00001022 zlog_debug ("Area[%s]: Configured as %s", inet_ntoa (area->area_id),
paul718e3742002-12-13 20:15:29 +00001023 LOOKUP (ospf_area_type_msg, type));
1024
1025 switch (area->external_routing)
1026 {
1027 case OSPF_AREA_DEFAULT:
paul1eb8ef22005-04-07 07:30:20 +00001028 for (ALL_LIST_ELEMENTS_RO (area->oiflist, node, oi))
1029 if (oi->nbr_self != NULL)
1030 {
1031 UNSET_FLAG (oi->nbr_self->options, OSPF_OPTION_NP);
1032 SET_FLAG (oi->nbr_self->options, OSPF_OPTION_E);
1033 }
paul718e3742002-12-13 20:15:29 +00001034 break;
1035 case OSPF_AREA_STUB:
paul1eb8ef22005-04-07 07:30:20 +00001036 for (ALL_LIST_ELEMENTS_RO (area->oiflist, node, oi))
1037 if (oi->nbr_self != NULL)
1038 {
1039 if (IS_DEBUG_OSPF_EVENT)
1040 zlog_debug ("setting options on %s accordingly", IF_NAME (oi));
1041 UNSET_FLAG (oi->nbr_self->options, OSPF_OPTION_NP);
1042 UNSET_FLAG (oi->nbr_self->options, OSPF_OPTION_E);
1043 if (IS_DEBUG_OSPF_EVENT)
1044 zlog_debug ("options set on %s: %x",
1045 IF_NAME (oi), OPTIONS (oi));
1046 }
paul718e3742002-12-13 20:15:29 +00001047 break;
1048 case OSPF_AREA_NSSA:
paul1eb8ef22005-04-07 07:30:20 +00001049 for (ALL_LIST_ELEMENTS_RO (area->oiflist, node, oi))
1050 if (oi->nbr_self != NULL)
1051 {
1052 zlog_debug ("setting nssa options on %s accordingly", IF_NAME (oi));
1053 UNSET_FLAG (oi->nbr_self->options, OSPF_OPTION_E);
1054 SET_FLAG (oi->nbr_self->options, OSPF_OPTION_NP);
1055 zlog_debug ("options set on %s: %x", IF_NAME (oi), OPTIONS (oi));
1056 }
paul718e3742002-12-13 20:15:29 +00001057 break;
1058 default:
1059 break;
1060 }
1061
1062 ospf_router_lsa_timer_add (area);
paul68980082003-03-25 05:07:42 +00001063 ospf_schedule_abr_task (area->ospf);
paul718e3742002-12-13 20:15:29 +00001064}
1065
1066int
paul68980082003-03-25 05:07:42 +00001067ospf_area_shortcut_set (struct ospf *ospf, struct ospf_area *area, int mode)
paul718e3742002-12-13 20:15:29 +00001068{
1069 if (area->shortcut_configured == mode)
1070 return 0;
1071
1072 area->shortcut_configured = mode;
1073 ospf_router_lsa_timer_add (area);
paul68980082003-03-25 05:07:42 +00001074 ospf_schedule_abr_task (ospf);
paul718e3742002-12-13 20:15:29 +00001075
paul68980082003-03-25 05:07:42 +00001076 ospf_area_check_free (ospf, area->area_id);
paul718e3742002-12-13 20:15:29 +00001077
1078 return 1;
1079}
1080
1081int
paul68980082003-03-25 05:07:42 +00001082ospf_area_shortcut_unset (struct ospf *ospf, struct ospf_area *area)
paul718e3742002-12-13 20:15:29 +00001083{
1084 area->shortcut_configured = OSPF_SHORTCUT_DEFAULT;
1085 ospf_router_lsa_timer_add (area);
paul68980082003-03-25 05:07:42 +00001086 ospf_area_check_free (ospf, area->area_id);
1087 ospf_schedule_abr_task (ospf);
paul718e3742002-12-13 20:15:29 +00001088
1089 return 1;
1090}
1091
paul4dadc292005-05-06 21:37:42 +00001092static int
paul718e3742002-12-13 20:15:29 +00001093ospf_area_vlink_count (struct ospf *ospf, struct ospf_area *area)
1094{
1095 struct ospf_vl_data *vl;
hasso52dc7ee2004-09-23 19:18:23 +00001096 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00001097 int count = 0;
1098
paul1eb8ef22005-04-07 07:30:20 +00001099 for (ALL_LIST_ELEMENTS_RO (ospf->vlinks, node, vl))
1100 if (IPV4_ADDR_SAME (&vl->vl_area_id, &area->area_id))
1101 count++;
paul718e3742002-12-13 20:15:29 +00001102
1103 return count;
1104}
1105
1106int
1107ospf_area_stub_set (struct ospf *ospf, struct in_addr area_id)
1108{
1109 struct ospf_area *area;
paul147193a2003-04-19 00:31:59 +00001110 int format = OSPF_AREA_ID_FORMAT_ADDRESS;
paul718e3742002-12-13 20:15:29 +00001111
paul68980082003-03-25 05:07:42 +00001112 area = ospf_area_get (ospf, area_id, format);
paul718e3742002-12-13 20:15:29 +00001113 if (ospf_area_vlink_count (ospf, area))
1114 return 0;
1115
1116 if (area->external_routing != OSPF_AREA_STUB)
1117 ospf_area_type_set (area, OSPF_AREA_STUB);
1118
1119 return 1;
1120}
1121
1122int
1123ospf_area_stub_unset (struct ospf *ospf, struct in_addr area_id)
1124{
1125 struct ospf_area *area;
1126
paul68980082003-03-25 05:07:42 +00001127 area = ospf_area_lookup_by_area_id (ospf, area_id);
paul718e3742002-12-13 20:15:29 +00001128 if (area == NULL)
1129 return 1;
1130
1131 if (area->external_routing == OSPF_AREA_STUB)
1132 ospf_area_type_set (area, OSPF_AREA_DEFAULT);
1133
paul68980082003-03-25 05:07:42 +00001134 ospf_area_check_free (ospf, area_id);
paul718e3742002-12-13 20:15:29 +00001135
1136 return 1;
1137}
1138
1139int
1140ospf_area_no_summary_set (struct ospf *ospf, struct in_addr area_id)
1141{
1142 struct ospf_area *area;
paul147193a2003-04-19 00:31:59 +00001143 int format = OSPF_AREA_ID_FORMAT_ADDRESS;
paul718e3742002-12-13 20:15:29 +00001144
paul68980082003-03-25 05:07:42 +00001145 area = ospf_area_get (ospf, area_id, format);
paul718e3742002-12-13 20:15:29 +00001146 area->no_summary = 1;
1147
1148 return 1;
1149}
1150
1151int
1152ospf_area_no_summary_unset (struct ospf *ospf, struct in_addr area_id)
1153{
1154 struct ospf_area *area;
1155
paul68980082003-03-25 05:07:42 +00001156 area = ospf_area_lookup_by_area_id (ospf, area_id);
paul718e3742002-12-13 20:15:29 +00001157 if (area == NULL)
1158 return 0;
1159
1160 area->no_summary = 0;
paul68980082003-03-25 05:07:42 +00001161 ospf_area_check_free (ospf, area_id);
paul718e3742002-12-13 20:15:29 +00001162
1163 return 1;
1164}
1165
1166int
1167ospf_area_nssa_set (struct ospf *ospf, struct in_addr area_id)
1168{
1169 struct ospf_area *area;
paul147193a2003-04-19 00:31:59 +00001170 int format = OSPF_AREA_ID_FORMAT_ADDRESS;
paul718e3742002-12-13 20:15:29 +00001171
paul68980082003-03-25 05:07:42 +00001172 area = ospf_area_get (ospf, area_id, format);
paul718e3742002-12-13 20:15:29 +00001173 if (ospf_area_vlink_count (ospf, area))
1174 return 0;
1175
1176 if (area->external_routing != OSPF_AREA_NSSA)
1177 {
1178 ospf_area_type_set (area, OSPF_AREA_NSSA);
1179 ospf->anyNSSA++;
1180 }
1181
paul084c7842003-06-22 08:35:18 +00001182 /* set NSSA area defaults */
1183 area->no_summary = 0;
1184 area->NSSATranslatorRole = OSPF_NSSA_ROLE_CANDIDATE;
pauld4a53d52003-07-12 21:30:57 +00001185 area->NSSATranslatorState = OSPF_NSSA_TRANSLATE_DISABLED;
paul084c7842003-06-22 08:35:18 +00001186 area->NSSATranslatorStabilityInterval = OSPF_NSSA_TRANS_STABLE_DEFAULT;
1187
paul718e3742002-12-13 20:15:29 +00001188 return 1;
1189}
1190
1191int
1192ospf_area_nssa_unset (struct ospf *ospf, struct in_addr area_id)
1193{
1194 struct ospf_area *area;
1195
paul68980082003-03-25 05:07:42 +00001196 area = ospf_area_lookup_by_area_id (ospf, area_id);
paul718e3742002-12-13 20:15:29 +00001197 if (area == NULL)
1198 return 0;
1199
1200 if (area->external_routing == OSPF_AREA_NSSA)
1201 {
1202 ospf->anyNSSA--;
1203 ospf_area_type_set (area, OSPF_AREA_DEFAULT);
1204 }
1205
paul68980082003-03-25 05:07:42 +00001206 ospf_area_check_free (ospf, area_id);
paul718e3742002-12-13 20:15:29 +00001207
1208 return 1;
1209}
1210
1211int
1212ospf_area_nssa_translator_role_set (struct ospf *ospf, struct in_addr area_id,
1213 int role)
1214{
1215 struct ospf_area *area;
1216
paul68980082003-03-25 05:07:42 +00001217 area = ospf_area_lookup_by_area_id (ospf, area_id);
paul718e3742002-12-13 20:15:29 +00001218 if (area == NULL)
1219 return 0;
1220
paul084c7842003-06-22 08:35:18 +00001221 area->NSSATranslatorRole = role;
paul718e3742002-12-13 20:15:29 +00001222
1223 return 1;
1224}
1225
paul4dadc292005-05-06 21:37:42 +00001226/* XXX: unused? Leave for symmetry? */
1227static int
paul718e3742002-12-13 20:15:29 +00001228ospf_area_nssa_translator_role_unset (struct ospf *ospf,
1229 struct in_addr area_id)
1230{
1231 struct ospf_area *area;
1232
paul68980082003-03-25 05:07:42 +00001233 area = ospf_area_lookup_by_area_id (ospf, area_id);
paul718e3742002-12-13 20:15:29 +00001234 if (area == NULL)
1235 return 0;
1236
paul084c7842003-06-22 08:35:18 +00001237 area->NSSATranslatorRole = OSPF_NSSA_ROLE_CANDIDATE;
paul718e3742002-12-13 20:15:29 +00001238
paul68980082003-03-25 05:07:42 +00001239 ospf_area_check_free (ospf, area_id);
paul718e3742002-12-13 20:15:29 +00001240
1241 return 1;
1242}
1243
1244int
paul68980082003-03-25 05:07:42 +00001245ospf_area_export_list_set (struct ospf *ospf,
paul6c835672004-10-11 11:00:30 +00001246 struct ospf_area *area, const char *list_name)
paul718e3742002-12-13 20:15:29 +00001247{
1248 struct access_list *list;
1249 list = access_list_lookup (AFI_IP, list_name);
1250
1251 EXPORT_LIST (area) = list;
1252
1253 if (EXPORT_NAME (area))
1254 free (EXPORT_NAME (area));
1255
1256 EXPORT_NAME (area) = strdup (list_name);
paul68980082003-03-25 05:07:42 +00001257 ospf_schedule_abr_task (ospf);
paul718e3742002-12-13 20:15:29 +00001258
1259 return 1;
1260}
1261
1262int
paul68980082003-03-25 05:07:42 +00001263ospf_area_export_list_unset (struct ospf *ospf, struct ospf_area * area)
paul718e3742002-12-13 20:15:29 +00001264{
1265
1266 EXPORT_LIST (area) = 0;
1267
1268 if (EXPORT_NAME (area))
1269 free (EXPORT_NAME (area));
1270
1271 EXPORT_NAME (area) = NULL;
1272
paul68980082003-03-25 05:07:42 +00001273 ospf_area_check_free (ospf, area->area_id);
paul718e3742002-12-13 20:15:29 +00001274
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
paul6c835672004-10-11 11:00:30 +00001281ospf_area_import_list_set (struct ospf *ospf, struct ospf_area *area,
1282 const char *name)
paul718e3742002-12-13 20:15:29 +00001283{
1284 struct access_list *list;
1285 list = access_list_lookup (AFI_IP, name);
1286
1287 IMPORT_LIST (area) = list;
1288
1289 if (IMPORT_NAME (area))
1290 free (IMPORT_NAME (area));
1291
1292 IMPORT_NAME (area) = strdup (name);
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
paul68980082003-03-25 05:07:42 +00001299ospf_area_import_list_unset (struct ospf *ospf, struct ospf_area * area)
paul718e3742002-12-13 20:15:29 +00001300{
1301 IMPORT_LIST (area) = 0;
1302
1303 if (IMPORT_NAME (area))
1304 free (IMPORT_NAME (area));
1305
1306 IMPORT_NAME (area) = NULL;
paul68980082003-03-25 05:07:42 +00001307 ospf_area_check_free (ospf, area->area_id);
paul718e3742002-12-13 20:15:29 +00001308
paul68980082003-03-25 05:07:42 +00001309 ospf_schedule_abr_task (ospf);
paul718e3742002-12-13 20:15:29 +00001310
1311 return 1;
1312}
1313
1314int
paul718e3742002-12-13 20:15:29 +00001315ospf_timers_refresh_set (struct ospf *ospf, int interval)
1316{
1317 int time_left;
1318
1319 if (ospf->lsa_refresh_interval == interval)
1320 return 1;
1321
1322 time_left = ospf->lsa_refresh_interval -
Paul Jakma2518efd2006-08-27 06:49:29 +00001323 (quagga_time (NULL) - ospf->lsa_refresher_started);
paul718e3742002-12-13 20:15:29 +00001324
1325 if (time_left > interval)
1326 {
1327 OSPF_TIMER_OFF (ospf->t_lsa_refresher);
1328 ospf->t_lsa_refresher =
1329 thread_add_timer (master, ospf_lsa_refresh_walker, ospf, interval);
1330 }
1331 ospf->lsa_refresh_interval = interval;
1332
1333 return 1;
1334}
1335
1336int
1337ospf_timers_refresh_unset (struct ospf *ospf)
1338{
1339 int time_left;
1340
1341 time_left = ospf->lsa_refresh_interval -
Paul Jakma2518efd2006-08-27 06:49:29 +00001342 (quagga_time (NULL) - ospf->lsa_refresher_started);
paul718e3742002-12-13 20:15:29 +00001343
1344 if (time_left > OSPF_LSA_REFRESH_INTERVAL_DEFAULT)
1345 {
1346 OSPF_TIMER_OFF (ospf->t_lsa_refresher);
1347 ospf->t_lsa_refresher =
1348 thread_add_timer (master, ospf_lsa_refresh_walker, ospf,
1349 OSPF_LSA_REFRESH_INTERVAL_DEFAULT);
1350 }
1351
1352 ospf->lsa_refresh_interval = OSPF_LSA_REFRESH_INTERVAL_DEFAULT;
1353
1354 return 1;
1355}
1356
1357
paul4dadc292005-05-06 21:37:42 +00001358static struct ospf_nbr_nbma *
1359ospf_nbr_nbma_new (void)
paul718e3742002-12-13 20:15:29 +00001360{
1361 struct ospf_nbr_nbma *nbr_nbma;
1362
1363 nbr_nbma = XMALLOC (MTYPE_OSPF_NEIGHBOR_STATIC,
1364 sizeof (struct ospf_nbr_nbma));
1365 memset (nbr_nbma, 0, sizeof (struct ospf_nbr_nbma));
1366
1367 nbr_nbma->priority = OSPF_NEIGHBOR_PRIORITY_DEFAULT;
1368 nbr_nbma->v_poll = OSPF_POLL_INTERVAL_DEFAULT;
1369
1370 return nbr_nbma;
1371}
1372
paul4dadc292005-05-06 21:37:42 +00001373static void
paul718e3742002-12-13 20:15:29 +00001374ospf_nbr_nbma_free (struct ospf_nbr_nbma *nbr_nbma)
1375{
1376 XFREE (MTYPE_OSPF_NEIGHBOR_STATIC, nbr_nbma);
1377}
1378
paul4dadc292005-05-06 21:37:42 +00001379static void
paul718e3742002-12-13 20:15:29 +00001380ospf_nbr_nbma_delete (struct ospf *ospf, struct ospf_nbr_nbma *nbr_nbma)
1381{
1382 struct route_node *rn;
1383 struct prefix_ipv4 p;
1384
1385 p.family = AF_INET;
1386 p.prefix = nbr_nbma->addr;
1387 p.prefixlen = IPV4_MAX_BITLEN;
1388
1389 rn = route_node_lookup (ospf->nbr_nbma, (struct prefix *)&p);
1390 if (rn)
1391 {
1392 ospf_nbr_nbma_free (rn->info);
1393 rn->info = NULL;
1394 route_unlock_node (rn);
1395 route_unlock_node (rn);
1396 }
1397}
1398
paul4dadc292005-05-06 21:37:42 +00001399static void
paul718e3742002-12-13 20:15:29 +00001400ospf_nbr_nbma_down (struct ospf_nbr_nbma *nbr_nbma)
1401{
1402 OSPF_TIMER_OFF (nbr_nbma->t_poll);
1403
1404 if (nbr_nbma->nbr)
1405 {
1406 nbr_nbma->nbr->nbr_nbma = NULL;
1407 OSPF_NSM_EVENT_EXECUTE (nbr_nbma->nbr, NSM_KillNbr);
1408 }
1409
1410 if (nbr_nbma->oi)
1411 listnode_delete (nbr_nbma->oi->nbr_nbma, nbr_nbma);
1412}
1413
paul4dadc292005-05-06 21:37:42 +00001414static void
paul718e3742002-12-13 20:15:29 +00001415ospf_nbr_nbma_add (struct ospf_nbr_nbma *nbr_nbma,
1416 struct ospf_interface *oi)
1417{
1418 struct ospf_neighbor *nbr;
1419 struct route_node *rn;
1420 struct prefix p;
1421
1422 if (oi->type != OSPF_IFTYPE_NBMA)
1423 return;
1424
1425 if (nbr_nbma->nbr != NULL)
1426 return;
1427
1428 if (IPV4_ADDR_SAME (&oi->nbr_self->address.u.prefix4, &nbr_nbma->addr))
1429 return;
1430
1431 nbr_nbma->oi = oi;
1432 listnode_add (oi->nbr_nbma, nbr_nbma);
1433
1434 /* Get neighbor information from table. */
1435 p.family = AF_INET;
1436 p.prefixlen = IPV4_MAX_BITLEN;
1437 p.u.prefix4 = nbr_nbma->addr;
1438
1439 rn = route_node_get (oi->nbrs, (struct prefix *)&p);
1440 if (rn->info)
1441 {
1442 nbr = rn->info;
1443 nbr->nbr_nbma = nbr_nbma;
1444 nbr_nbma->nbr = nbr;
1445
1446 route_unlock_node (rn);
1447 }
1448 else
1449 {
1450 nbr = rn->info = ospf_nbr_new (oi);
1451 nbr->state = NSM_Down;
1452 nbr->src = nbr_nbma->addr;
1453 nbr->nbr_nbma = nbr_nbma;
1454 nbr->priority = nbr_nbma->priority;
1455 nbr->address = p;
1456
1457 nbr_nbma->nbr = nbr;
1458
1459 OSPF_NSM_EVENT_EXECUTE (nbr, NSM_Start);
1460 }
1461}
1462
1463void
paul68980082003-03-25 05:07:42 +00001464ospf_nbr_nbma_if_update (struct ospf *ospf, struct ospf_interface *oi)
paul718e3742002-12-13 20:15:29 +00001465{
1466 struct ospf_nbr_nbma *nbr_nbma;
1467 struct route_node *rn;
1468 struct prefix_ipv4 p;
1469
1470 if (oi->type != OSPF_IFTYPE_NBMA)
1471 return;
1472
paul68980082003-03-25 05:07:42 +00001473 for (rn = route_top (ospf->nbr_nbma); rn; rn = route_next (rn))
paul718e3742002-12-13 20:15:29 +00001474 if ((nbr_nbma = rn->info))
1475 if (nbr_nbma->oi == NULL && nbr_nbma->nbr == NULL)
1476 {
1477 p.family = AF_INET;
1478 p.prefix = nbr_nbma->addr;
1479 p.prefixlen = IPV4_MAX_BITLEN;
1480
1481 if (prefix_match (oi->address, (struct prefix *)&p))
1482 ospf_nbr_nbma_add (nbr_nbma, oi);
1483 }
1484}
1485
1486struct ospf_nbr_nbma *
1487ospf_nbr_nbma_lookup (struct ospf *ospf, struct in_addr nbr_addr)
1488{
1489 struct route_node *rn;
1490 struct prefix_ipv4 p;
1491
1492 p.family = AF_INET;
1493 p.prefix = nbr_addr;
1494 p.prefixlen = IPV4_MAX_BITLEN;
1495
1496 rn = route_node_lookup (ospf->nbr_nbma, (struct prefix *)&p);
1497 if (rn)
1498 {
1499 route_unlock_node (rn);
1500 return rn->info;
1501 }
1502 return NULL;
1503}
1504
1505struct ospf_nbr_nbma *
paul68980082003-03-25 05:07:42 +00001506ospf_nbr_nbma_lookup_next (struct ospf *ospf, struct in_addr *addr, int first)
paul718e3742002-12-13 20:15:29 +00001507{
1508#if 0
1509 struct ospf_nbr_nbma *nbr_nbma;
hasso52dc7ee2004-09-23 19:18:23 +00001510 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00001511#endif
1512
paul68980082003-03-25 05:07:42 +00001513 if (ospf == NULL)
paul718e3742002-12-13 20:15:29 +00001514 return NULL;
1515
1516#if 0
paul1eb8ef22005-04-07 07:30:20 +00001517 for (ALL_LIST_ELEMENTS_RO (ospf->nbr_nbma, node, nbr_nbma))
paul718e3742002-12-13 20:15:29 +00001518 {
paul718e3742002-12-13 20:15:29 +00001519 if (first)
1520 {
1521 *addr = nbr_nbma->addr;
1522 return nbr_nbma;
1523 }
1524 else if (ntohl (nbr_nbma->addr.s_addr) > ntohl (addr->s_addr))
1525 {
1526 *addr = nbr_nbma->addr;
1527 return nbr_nbma;
1528 }
1529 }
1530#endif
1531 return NULL;
1532}
1533
1534int
1535ospf_nbr_nbma_set (struct ospf *ospf, struct in_addr nbr_addr)
1536{
1537 struct ospf_nbr_nbma *nbr_nbma;
1538 struct ospf_interface *oi;
1539 struct prefix_ipv4 p;
1540 struct route_node *rn;
hasso52dc7ee2004-09-23 19:18:23 +00001541 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00001542
1543 nbr_nbma = ospf_nbr_nbma_lookup (ospf, nbr_addr);
1544 if (nbr_nbma)
1545 return 0;
1546
1547 nbr_nbma = ospf_nbr_nbma_new ();
1548 nbr_nbma->addr = nbr_addr;
1549
1550 p.family = AF_INET;
1551 p.prefix = nbr_addr;
1552 p.prefixlen = IPV4_MAX_BITLEN;
1553
1554 rn = route_node_get (ospf->nbr_nbma, (struct prefix *)&p);
1555 rn->info = nbr_nbma;
1556
paul1eb8ef22005-04-07 07:30:20 +00001557 for (ALL_LIST_ELEMENTS_RO (ospf->oiflist, node, oi))
paul718e3742002-12-13 20:15:29 +00001558 {
paul718e3742002-12-13 20:15:29 +00001559 if (oi->type == OSPF_IFTYPE_NBMA)
1560 if (prefix_match (oi->address, (struct prefix *)&p))
1561 {
1562 ospf_nbr_nbma_add (nbr_nbma, oi);
1563 break;
1564 }
1565 }
1566
1567 return 1;
1568}
1569
1570int
1571ospf_nbr_nbma_unset (struct ospf *ospf, struct in_addr nbr_addr)
1572{
1573 struct ospf_nbr_nbma *nbr_nbma;
1574
1575 nbr_nbma = ospf_nbr_nbma_lookup (ospf, nbr_addr);
1576 if (nbr_nbma == NULL)
1577 return 0;
1578
1579 ospf_nbr_nbma_down (nbr_nbma);
1580 ospf_nbr_nbma_delete (ospf, nbr_nbma);
1581
1582 return 1;
1583}
1584
1585int
1586ospf_nbr_nbma_priority_set (struct ospf *ospf, struct in_addr nbr_addr,
1587 u_char priority)
1588{
1589 struct ospf_nbr_nbma *nbr_nbma;
1590
1591 nbr_nbma = ospf_nbr_nbma_lookup (ospf, nbr_addr);
1592 if (nbr_nbma == NULL)
1593 return 0;
1594
1595 if (nbr_nbma->priority != priority)
1596 nbr_nbma->priority = priority;
1597
1598 return 1;
1599}
1600
1601int
1602ospf_nbr_nbma_priority_unset (struct ospf *ospf, struct in_addr nbr_addr)
1603{
1604 struct ospf_nbr_nbma *nbr_nbma;
1605
1606 nbr_nbma = ospf_nbr_nbma_lookup (ospf, nbr_addr);
1607 if (nbr_nbma == NULL)
1608 return 0;
1609
1610 if (nbr_nbma != OSPF_NEIGHBOR_PRIORITY_DEFAULT)
1611 nbr_nbma->priority = OSPF_NEIGHBOR_PRIORITY_DEFAULT;
1612
1613 return 1;
1614}
1615
1616int
1617ospf_nbr_nbma_poll_interval_set (struct ospf *ospf, struct in_addr nbr_addr,
paul6c835672004-10-11 11:00:30 +00001618 unsigned int interval)
paul718e3742002-12-13 20:15:29 +00001619{
1620 struct ospf_nbr_nbma *nbr_nbma;
1621
1622 nbr_nbma = ospf_nbr_nbma_lookup (ospf, nbr_addr);
1623 if (nbr_nbma == NULL)
1624 return 0;
1625
1626 if (nbr_nbma->v_poll != interval)
1627 {
1628 nbr_nbma->v_poll = interval;
1629 if (nbr_nbma->oi && ospf_if_is_up (nbr_nbma->oi))
1630 {
1631 OSPF_TIMER_OFF (nbr_nbma->t_poll);
1632 OSPF_POLL_TIMER_ON (nbr_nbma->t_poll, ospf_poll_timer,
1633 nbr_nbma->v_poll);
1634 }
1635 }
1636
1637 return 1;
1638}
1639
1640int
1641ospf_nbr_nbma_poll_interval_unset (struct ospf *ospf, struct in_addr addr)
1642{
1643 struct ospf_nbr_nbma *nbr_nbma;
1644
1645 nbr_nbma = ospf_nbr_nbma_lookup (ospf, addr);
1646 if (nbr_nbma == NULL)
1647 return 0;
1648
1649 if (nbr_nbma->v_poll != OSPF_POLL_INTERVAL_DEFAULT)
1650 nbr_nbma->v_poll = OSPF_POLL_INTERVAL_DEFAULT;
1651
1652 return 1;
1653}
1654
paul718e3742002-12-13 20:15:29 +00001655void
paul020709f2003-04-04 02:44:16 +00001656ospf_master_init ()
1657{
1658 memset (&ospf_master, 0, sizeof (struct ospf_master));
1659
1660 om = &ospf_master;
1661 om->ospf = list_new ();
1662 om->master = thread_master_create ();
Paul Jakma2518efd2006-08-27 06:49:29 +00001663 om->start_time = quagga_time (NULL);
paul020709f2003-04-04 02:44:16 +00001664}