blob: 8133050d7b501646eaed543500407d9297a0054c [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 }
Denis Ovsienkob7fe4142007-08-21 16:32:56 +0000215 new->maxsndbuflen = 0;
216 ospf_adjust_sndbuflen (new, OSPF_SNDBUFLEN_DEFAULT);
ajs5c333492005-02-23 15:43:01 +0000217 if ((new->ibuf = stream_new(OSPF_MAX_PACKET_SIZE+1)) == NULL)
218 {
219 zlog_err("ospf_new: fatal error: stream_new(%u) failed allocating ibuf",
220 OSPF_MAX_PACKET_SIZE+1);
221 exit(1);
222 }
223 new->t_read = thread_add_read (master, ospf_read, new, new->fd);
paul718e3742002-12-13 20:15:29 +0000224 new->oi_write_q = list_new ();
225
226 return new;
227}
228
229struct ospf *
paul020709f2003-04-04 02:44:16 +0000230ospf_lookup ()
231{
232 if (listcount (om->ospf) == 0)
233 return NULL;
234
paul1eb8ef22005-04-07 07:30:20 +0000235 return listgetdata (listhead (om->ospf));
paul020709f2003-04-04 02:44:16 +0000236}
237
paul4dadc292005-05-06 21:37:42 +0000238static void
paul020709f2003-04-04 02:44:16 +0000239ospf_add (struct ospf *ospf)
240{
241 listnode_add (om->ospf, ospf);
242}
243
paul4dadc292005-05-06 21:37:42 +0000244static void
paul020709f2003-04-04 02:44:16 +0000245ospf_delete (struct ospf *ospf)
246{
247 listnode_delete (om->ospf, ospf);
248}
249
250struct ospf *
paul718e3742002-12-13 20:15:29 +0000251ospf_get ()
252{
paul020709f2003-04-04 02:44:16 +0000253 struct ospf *ospf;
paul718e3742002-12-13 20:15:29 +0000254
paul020709f2003-04-04 02:44:16 +0000255 ospf = ospf_lookup ();
256 if (ospf == NULL)
257 {
258 ospf = ospf_new ();
259 ospf_add (ospf);
paul718e3742002-12-13 20:15:29 +0000260
paul020709f2003-04-04 02:44:16 +0000261 if (ospf->router_id_static.s_addr == 0)
262 ospf_router_id_update (ospf);
paul718e3742002-12-13 20:15:29 +0000263
264#ifdef HAVE_OPAQUE_LSA
paul020709f2003-04-04 02:44:16 +0000265 ospf_opaque_type11_lsa_init (ospf);
paul718e3742002-12-13 20:15:29 +0000266#endif /* HAVE_OPAQUE_LSA */
paul020709f2003-04-04 02:44:16 +0000267 }
paul68980082003-03-25 05:07:42 +0000268
269 return ospf;
paul718e3742002-12-13 20:15:29 +0000270}
paul88d6cf32005-10-29 12:50:09 +0000271
paulc9c93d52005-11-26 13:31:11 +0000272/* Handle the second half of deferred shutdown. This is called either
273 * from the deferred-shutdown timer thread, or directly through
274 * ospf_deferred_shutdown_check.
paul88d6cf32005-10-29 12:50:09 +0000275 *
276 * Function is to cleanup G-R state, if required then call ospf_finish_final
277 * to complete shutdown of this ospf instance. Possibly exit if the
278 * whole process is being shutdown and this was the last OSPF instance.
279 */
280static void
paulc9c93d52005-11-26 13:31:11 +0000281ospf_deferred_shutdown_finish (struct ospf *ospf)
paul88d6cf32005-10-29 12:50:09 +0000282{
283 ospf->stub_router_shutdown_time = OSPF_STUB_ROUTER_UNCONFIGURED;
paulc9c93d52005-11-26 13:31:11 +0000284 OSPF_TIMER_OFF (ospf->t_deferred_shutdown);
paul88d6cf32005-10-29 12:50:09 +0000285
286 ospf_finish_final (ospf);
287
288 /* *ospf is now invalid */
289
290 /* ospfd being shut-down? If so, was this the last ospf instance? */
291 if (CHECK_FLAG (om->options, OSPF_MASTER_SHUTDOWN)
292 && (listcount (om->ospf) == 0))
293 exit (0);
294
295 return;
296}
297
298/* Timer thread for G-R */
299static int
paulc9c93d52005-11-26 13:31:11 +0000300ospf_deferred_shutdown_timer (struct thread *t)
paul88d6cf32005-10-29 12:50:09 +0000301{
302 struct ospf *ospf = THREAD_ARG(t);
303
paulc9c93d52005-11-26 13:31:11 +0000304 ospf_deferred_shutdown_finish (ospf);
paul88d6cf32005-10-29 12:50:09 +0000305
306 return 0;
307}
308
paulc9c93d52005-11-26 13:31:11 +0000309/* Check whether deferred-shutdown must be scheduled, otherwise call
paul88d6cf32005-10-29 12:50:09 +0000310 * down directly into second-half of instance shutdown.
311 */
312static void
paulc9c93d52005-11-26 13:31:11 +0000313ospf_deferred_shutdown_check (struct ospf *ospf)
paul88d6cf32005-10-29 12:50:09 +0000314{
315 unsigned long timeout;
316 struct listnode *ln;
317 struct ospf_area *area;
318
paulc9c93d52005-11-26 13:31:11 +0000319 /* deferred shutdown already running? */
320 if (ospf->t_deferred_shutdown)
paul88d6cf32005-10-29 12:50:09 +0000321 return;
322
323 /* Should we try push out max-metric LSAs? */
324 if (ospf->stub_router_shutdown_time != OSPF_STUB_ROUTER_UNCONFIGURED)
325 {
326 for (ALL_LIST_ELEMENTS_RO (ospf->areas, ln, area))
327 {
328 SET_FLAG (area->stub_router_state, OSPF_AREA_ADMIN_STUB_ROUTED);
329
330 if (!CHECK_FLAG (area->stub_router_state, OSPF_AREA_IS_STUB_ROUTED))
331 ospf_router_lsa_timer_add (area);
332 }
333 timeout = ospf->stub_router_shutdown_time;
334 }
335 else
paulc9c93d52005-11-26 13:31:11 +0000336 {
337 /* No timer needed */
338 ospf_deferred_shutdown_finish (ospf);
339 return;
340 }
paul88d6cf32005-10-29 12:50:09 +0000341
paulc9c93d52005-11-26 13:31:11 +0000342 OSPF_TIMER_ON (ospf->t_deferred_shutdown, ospf_deferred_shutdown_timer,
paul88d6cf32005-10-29 12:50:09 +0000343 timeout);
344 return;
345}
346
347/* Shut down the entire process */
348void
349ospf_terminate (void)
350{
351 struct ospf *ospf;
352 struct listnode *node, *nnode;
353
354 /* shutdown already in progress */
355 if (CHECK_FLAG (om->options, OSPF_MASTER_SHUTDOWN))
356 return;
357
358 SET_FLAG (om->options, OSPF_MASTER_SHUTDOWN);
359
Andrew J. Schorr4056a542007-02-27 13:55:46 +0000360 /* exit immediately if OSPF not actually running */
361 if (listcount(om->ospf) == 0)
362 exit(0);
363
paul88d6cf32005-10-29 12:50:09 +0000364 for (ALL_LIST_ELEMENTS (om->ospf, node, nnode, ospf))
365 ospf_finish (ospf);
366
367 /* Deliberately go back up, hopefully to thread scheduler, as
368 * One or more ospf_finish()'s may have deferred shutdown to a timer
369 * thread
370 */
371}
paul718e3742002-12-13 20:15:29 +0000372
373void
374ospf_finish (struct ospf *ospf)
375{
paulc9c93d52005-11-26 13:31:11 +0000376 /* let deferred shutdown decide */
377 ospf_deferred_shutdown_check (ospf);
paul88d6cf32005-10-29 12:50:09 +0000378
paulc9c93d52005-11-26 13:31:11 +0000379 /* if ospf_deferred_shutdown returns, then ospf_finish_final is
paul88d6cf32005-10-29 12:50:09 +0000380 * deferred to expiry of G-S timer thread. Return back up, hopefully
381 * to thread scheduler.
382 */
paulc9c93d52005-11-26 13:31:11 +0000383 return;
paul88d6cf32005-10-29 12:50:09 +0000384}
385
386/* Final cleanup of ospf instance */
387static void
388ospf_finish_final (struct ospf *ospf)
389{
paul718e3742002-12-13 20:15:29 +0000390 struct route_node *rn;
391 struct ospf_nbr_nbma *nbr_nbma;
paul68980082003-03-25 05:07:42 +0000392 struct ospf_lsa *lsa;
paul1eb8ef22005-04-07 07:30:20 +0000393 struct ospf_interface *oi;
394 struct ospf_area *area;
395 struct ospf_vl_data *vl_data;
396 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000397 int i;
398
399#ifdef HAVE_OPAQUE_LSA
400 ospf_opaque_type11_lsa_term (ospf);
401#endif /* HAVE_OPAQUE_LSA */
paul88d6cf32005-10-29 12:50:09 +0000402
403 /* be nice if this worked, but it doesn't */
404 /*ospf_flush_self_originated_lsas_now (ospf);*/
405
406 /* Unregister redistribution */
paul718e3742002-12-13 20:15:29 +0000407 for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
paul020709f2003-04-04 02:44:16 +0000408 ospf_redistribute_unset (ospf, i);
Paul Jakma29b5a042006-08-27 08:01:20 +0000409 ospf_redistribute_default_unset (ospf);
paul718e3742002-12-13 20:15:29 +0000410
paul1eb8ef22005-04-07 07:30:20 +0000411 for (ALL_LIST_ELEMENTS (ospf->areas, node, nnode, area))
412 ospf_remove_vls_through_area (ospf, area);
paul718e3742002-12-13 20:15:29 +0000413
paul1eb8ef22005-04-07 07:30:20 +0000414 for (ALL_LIST_ELEMENTS (ospf->vlinks, node, nnode, vl_data))
415 ospf_vl_delete (ospf, vl_data);
paul718e3742002-12-13 20:15:29 +0000416
417 list_delete (ospf->vlinks);
418
419 /* Reset interface. */
paul1eb8ef22005-04-07 07:30:20 +0000420 for (ALL_LIST_ELEMENTS (ospf->oiflist, node, nnode, oi))
421 ospf_if_free (oi);
paul718e3742002-12-13 20:15:29 +0000422
423 /* Clear static neighbors */
424 for (rn = route_top (ospf->nbr_nbma); rn; rn = route_next (rn))
425 if ((nbr_nbma = rn->info))
426 {
427 OSPF_POLL_TIMER_OFF (nbr_nbma->t_poll);
428
429 if (nbr_nbma->nbr)
430 {
431 nbr_nbma->nbr->nbr_nbma = NULL;
432 nbr_nbma->nbr = NULL;
433 }
434
435 if (nbr_nbma->oi)
436 {
437 listnode_delete (nbr_nbma->oi->nbr_nbma, nbr_nbma);
438 nbr_nbma->oi = NULL;
439 }
440
441 XFREE (MTYPE_OSPF_NEIGHBOR_STATIC, nbr_nbma);
442 }
443
444 route_table_finish (ospf->nbr_nbma);
445
446 /* Clear networks and Areas. */
447 for (rn = route_top (ospf->networks); rn; rn = route_next (rn))
448 {
449 struct ospf_network *network;
450
451 if ((network = rn->info) != NULL)
452 {
paul68980082003-03-25 05:07:42 +0000453 ospf_network_free (ospf, network);
paul718e3742002-12-13 20:15:29 +0000454 rn->info = NULL;
455 route_unlock_node (rn);
456 }
457 }
458
paul1eb8ef22005-04-07 07:30:20 +0000459 for (ALL_LIST_ELEMENTS (ospf->areas, node, nnode, area))
paul718e3742002-12-13 20:15:29 +0000460 {
paul718e3742002-12-13 20:15:29 +0000461 listnode_delete (ospf->areas, area);
462 ospf_area_free (area);
463 }
464
465 /* Cancel all timers. */
466 OSPF_TIMER_OFF (ospf->t_external_lsa);
paul718e3742002-12-13 20:15:29 +0000467 OSPF_TIMER_OFF (ospf->t_router_lsa_update);
468 OSPF_TIMER_OFF (ospf->t_spf_calc);
469 OSPF_TIMER_OFF (ospf->t_ase_calc);
470 OSPF_TIMER_OFF (ospf->t_maxage);
471 OSPF_TIMER_OFF (ospf->t_maxage_walker);
472 OSPF_TIMER_OFF (ospf->t_abr_task);
paul88d6cf32005-10-29 12:50:09 +0000473 OSPF_TIMER_OFF (ospf->t_asbr_check);
paul718e3742002-12-13 20:15:29 +0000474 OSPF_TIMER_OFF (ospf->t_distribute_update);
475 OSPF_TIMER_OFF (ospf->t_lsa_refresher);
476 OSPF_TIMER_OFF (ospf->t_read);
477 OSPF_TIMER_OFF (ospf->t_write);
paul31a59762005-11-14 11:11:11 +0000478#ifdef HAVE_OPAQUE_LSA
paul88d6cf32005-10-29 12:50:09 +0000479 OSPF_TIMER_OFF (ospf->t_opaque_lsa_self);
paul31a59762005-11-14 11:11:11 +0000480#endif
paul718e3742002-12-13 20:15:29 +0000481
482 close (ospf->fd);
ajs5c333492005-02-23 15:43:01 +0000483 stream_free(ospf->ibuf);
paul718e3742002-12-13 20:15:29 +0000484
485#ifdef HAVE_OPAQUE_LSA
paul68980082003-03-25 05:07:42 +0000486 LSDB_LOOP (OPAQUE_AS_LSDB (ospf), rn, lsa)
487 ospf_discard_from_db (ospf, ospf->lsdb, lsa);
paul718e3742002-12-13 20:15:29 +0000488#endif /* HAVE_OPAQUE_LSA */
paul68980082003-03-25 05:07:42 +0000489 LSDB_LOOP (EXTERNAL_LSDB (ospf), rn, lsa)
490 ospf_discard_from_db (ospf, ospf->lsdb, lsa);
491
paul718e3742002-12-13 20:15:29 +0000492 ospf_lsdb_delete_all (ospf->lsdb);
493 ospf_lsdb_free (ospf->lsdb);
494
paul1eb8ef22005-04-07 07:30:20 +0000495 for (ALL_LIST_ELEMENTS (ospf->maxage_lsa, node, nnode, lsa))
Paul Jakma1fe6ed32006-07-26 09:37:26 +0000496 ospf_lsa_unlock (&lsa); /* maxage_lsa */
paul718e3742002-12-13 20:15:29 +0000497
498 list_delete (ospf->maxage_lsa);
499
500 if (ospf->old_table)
501 ospf_route_table_free (ospf->old_table);
502 if (ospf->new_table)
503 {
504 ospf_route_delete (ospf->new_table);
505 ospf_route_table_free (ospf->new_table);
506 }
507 if (ospf->old_rtrs)
508 ospf_rtrs_free (ospf->old_rtrs);
509 if (ospf->new_rtrs)
510 ospf_rtrs_free (ospf->new_rtrs);
511 if (ospf->new_external_route)
512 {
513 ospf_route_delete (ospf->new_external_route);
514 ospf_route_table_free (ospf->new_external_route);
515 }
516 if (ospf->old_external_route)
517 {
518 ospf_route_delete (ospf->old_external_route);
519 ospf_route_table_free (ospf->old_external_route);
520 }
521 if (ospf->external_lsas)
522 {
523 ospf_ase_external_lsas_finish (ospf->external_lsas);
524 }
525
526 list_delete (ospf->areas);
527
528 for (i = ZEBRA_ROUTE_SYSTEM; i <= ZEBRA_ROUTE_MAX; i++)
529 if (EXTERNAL_INFO (i) != NULL)
530 for (rn = route_top (EXTERNAL_INFO (i)); rn; rn = route_next (rn))
531 {
532 if (rn->info == NULL)
533 continue;
534
535 XFREE (MTYPE_OSPF_EXTERNAL_INFO, rn->info);
536 rn->info = NULL;
537 route_unlock_node (rn);
538 }
539
paul68980082003-03-25 05:07:42 +0000540 ospf_distance_reset (ospf);
paul718e3742002-12-13 20:15:29 +0000541 route_table_finish (ospf->distance_table);
542
paul020709f2003-04-04 02:44:16 +0000543 ospf_delete (ospf);
paul718e3742002-12-13 20:15:29 +0000544
paul020709f2003-04-04 02:44:16 +0000545 XFREE (MTYPE_OSPF_TOP, ospf);
paul718e3742002-12-13 20:15:29 +0000546}
547
548
549/* allocate new OSPF Area object */
paul4dadc292005-05-06 21:37:42 +0000550static struct ospf_area *
paul68980082003-03-25 05:07:42 +0000551ospf_area_new (struct ospf *ospf, struct in_addr area_id)
paul718e3742002-12-13 20:15:29 +0000552{
553 struct ospf_area *new;
554
555 /* Allocate new config_network. */
556 new = XCALLOC (MTYPE_OSPF_AREA, sizeof (struct ospf_area));
557
paul68980082003-03-25 05:07:42 +0000558 new->ospf = ospf;
paul718e3742002-12-13 20:15:29 +0000559
560 new->area_id = area_id;
561
562 new->external_routing = OSPF_AREA_DEFAULT;
563 new->default_cost = 1;
564 new->auth_type = OSPF_AUTH_NULL;
paul88d6cf32005-10-29 12:50:09 +0000565
paul718e3742002-12-13 20:15:29 +0000566 /* New LSDB init. */
567 new->lsdb = ospf_lsdb_new ();
568
569 /* Self-originated LSAs initialize. */
570 new->router_lsa_self = NULL;
571
572#ifdef HAVE_OPAQUE_LSA
573 ospf_opaque_type10_lsa_init (new);
574#endif /* HAVE_OPAQUE_LSA */
575
576 new->oiflist = list_new ();
577 new->ranges = route_table_init ();
578
579 if (area_id.s_addr == OSPF_AREA_BACKBONE)
paul68980082003-03-25 05:07:42 +0000580 ospf->backbone = new;
paul718e3742002-12-13 20:15:29 +0000581
582 return new;
583}
584
585void
586ospf_area_free (struct ospf_area *area)
587{
paul68980082003-03-25 05:07:42 +0000588 struct route_node *rn;
589 struct ospf_lsa *lsa;
590
paul718e3742002-12-13 20:15:29 +0000591 /* Free LSDBs. */
paul68980082003-03-25 05:07:42 +0000592 LSDB_LOOP (ROUTER_LSDB (area), rn, lsa)
593 ospf_discard_from_db (area->ospf, area->lsdb, lsa);
594 LSDB_LOOP (NETWORK_LSDB (area), rn, lsa)
595 ospf_discard_from_db (area->ospf, area->lsdb, lsa);
596 LSDB_LOOP (SUMMARY_LSDB (area), rn, lsa)
597 ospf_discard_from_db (area->ospf, area->lsdb, lsa);
598 LSDB_LOOP (ASBR_SUMMARY_LSDB (area), rn, lsa)
599 ospf_discard_from_db (area->ospf, area->lsdb, lsa);
paul718e3742002-12-13 20:15:29 +0000600
paul68980082003-03-25 05:07:42 +0000601 LSDB_LOOP (NSSA_LSDB (area), rn, lsa)
602 ospf_discard_from_db (area->ospf, area->lsdb, lsa);
paul718e3742002-12-13 20:15:29 +0000603#ifdef HAVE_OPAQUE_LSA
paul68980082003-03-25 05:07:42 +0000604 LSDB_LOOP (OPAQUE_AREA_LSDB (area), rn, lsa)
605 ospf_discard_from_db (area->ospf, area->lsdb, lsa);
606 LSDB_LOOP (OPAQUE_LINK_LSDB (area), rn, lsa)
607 ospf_discard_from_db (area->ospf, area->lsdb, lsa);
paul718e3742002-12-13 20:15:29 +0000608#endif /* HAVE_OPAQUE_LSA */
609
610 ospf_lsdb_delete_all (area->lsdb);
611 ospf_lsdb_free (area->lsdb);
612
Paul Jakma1fe6ed32006-07-26 09:37:26 +0000613 ospf_lsa_unlock (&area->router_lsa_self);
paul718e3742002-12-13 20:15:29 +0000614
615 route_table_finish (area->ranges);
616 list_delete (area->oiflist);
617
618 if (EXPORT_NAME (area))
619 free (EXPORT_NAME (area));
620
621 if (IMPORT_NAME (area))
622 free (IMPORT_NAME (area));
623
624 /* Cancel timer. */
625 OSPF_TIMER_OFF (area->t_router_lsa_self);
paul88d6cf32005-10-29 12:50:09 +0000626 OSPF_TIMER_OFF (area->t_stub_router);
627#ifdef HAVE_OPAQUE_LSA
628 OSPF_TIMER_OFF (area->t_opaque_lsa_self);
629#endif /* HAVE_OPAQUE_LSA */
630
paul718e3742002-12-13 20:15:29 +0000631 if (OSPF_IS_AREA_BACKBONE (area))
paul68980082003-03-25 05:07:42 +0000632 area->ospf->backbone = NULL;
paul718e3742002-12-13 20:15:29 +0000633
634 XFREE (MTYPE_OSPF_AREA, area);
635}
636
637void
paul68980082003-03-25 05:07:42 +0000638ospf_area_check_free (struct ospf *ospf, struct in_addr area_id)
paul718e3742002-12-13 20:15:29 +0000639{
640 struct ospf_area *area;
641
paul68980082003-03-25 05:07:42 +0000642 area = ospf_area_lookup_by_area_id (ospf, area_id);
paul718e3742002-12-13 20:15:29 +0000643 if (area &&
644 listcount (area->oiflist) == 0 &&
645 area->ranges->top == NULL &&
646 area->shortcut_configured == OSPF_SHORTCUT_DEFAULT &&
647 area->external_routing == OSPF_AREA_DEFAULT &&
648 area->no_summary == 0 &&
649 area->default_cost == 1 &&
650 EXPORT_NAME (area) == NULL &&
651 IMPORT_NAME (area) == NULL &&
652 area->auth_type == OSPF_AUTH_NULL)
653 {
paul68980082003-03-25 05:07:42 +0000654 listnode_delete (ospf->areas, area);
paul718e3742002-12-13 20:15:29 +0000655 ospf_area_free (area);
656 }
657}
658
659struct ospf_area *
paul68980082003-03-25 05:07:42 +0000660ospf_area_get (struct ospf *ospf, struct in_addr area_id, int format)
paul718e3742002-12-13 20:15:29 +0000661{
662 struct ospf_area *area;
663
paul68980082003-03-25 05:07:42 +0000664 area = ospf_area_lookup_by_area_id (ospf, area_id);
paul718e3742002-12-13 20:15:29 +0000665 if (!area)
666 {
paul68980082003-03-25 05:07:42 +0000667 area = ospf_area_new (ospf, area_id);
paul718e3742002-12-13 20:15:29 +0000668 area->format = format;
paul68980082003-03-25 05:07:42 +0000669 listnode_add_sort (ospf->areas, area);
670 ospf_check_abr_status (ospf);
paul718e3742002-12-13 20:15:29 +0000671 }
672
673 return area;
674}
675
676struct ospf_area *
paul68980082003-03-25 05:07:42 +0000677ospf_area_lookup_by_area_id (struct ospf *ospf, struct in_addr area_id)
paul718e3742002-12-13 20:15:29 +0000678{
679 struct ospf_area *area;
hasso52dc7ee2004-09-23 19:18:23 +0000680 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000681
paul1eb8ef22005-04-07 07:30:20 +0000682 for (ALL_LIST_ELEMENTS_RO (ospf->areas, node, area))
683 if (IPV4_ADDR_SAME (&area->area_id, &area_id))
684 return area;
paul718e3742002-12-13 20:15:29 +0000685
686 return NULL;
687}
688
689void
690ospf_area_add_if (struct ospf_area *area, struct ospf_interface *oi)
691{
692 listnode_add (area->oiflist, oi);
693}
694
695void
696ospf_area_del_if (struct ospf_area *area, struct ospf_interface *oi)
697{
698 listnode_delete (area->oiflist, oi);
699}
700
701
702/* Config network statement related functions. */
paul4dadc292005-05-06 21:37:42 +0000703static struct ospf_network *
paul718e3742002-12-13 20:15:29 +0000704ospf_network_new (struct in_addr area_id, int format)
705{
706 struct ospf_network *new;
707 new = XCALLOC (MTYPE_OSPF_NETWORK, sizeof (struct ospf_network));
708
709 new->area_id = area_id;
710 new->format = format;
711
712 return new;
713}
714
715void
paul68980082003-03-25 05:07:42 +0000716ospf_network_free (struct ospf *ospf, struct ospf_network *network)
paul718e3742002-12-13 20:15:29 +0000717{
paul68980082003-03-25 05:07:42 +0000718 ospf_area_check_free (ospf, network->area_id);
719 ospf_schedule_abr_task (ospf);
paul718e3742002-12-13 20:15:29 +0000720 XFREE (MTYPE_OSPF_NETWORK, network);
721}
722
723int
724ospf_network_set (struct ospf *ospf, struct prefix_ipv4 *p,
725 struct in_addr area_id)
726{
727 struct ospf_network *network;
728 struct ospf_area *area;
729 struct route_node *rn;
730 struct external_info *ei;
paul147193a2003-04-19 00:31:59 +0000731 int ret = OSPF_AREA_ID_FORMAT_ADDRESS;
paul718e3742002-12-13 20:15:29 +0000732
733 rn = route_node_get (ospf->networks, (struct prefix *)p);
734 if (rn->info)
735 {
736 /* There is already same network statement. */
737 route_unlock_node (rn);
738 return 0;
739 }
740
741 rn->info = network = ospf_network_new (area_id, ret);
paul68980082003-03-25 05:07:42 +0000742 area = ospf_area_get (ospf, area_id, ret);
paul718e3742002-12-13 20:15:29 +0000743
744 /* Run network config now. */
745 ospf_network_run (ospf, (struct prefix *)p, area);
746
747 /* Update connected redistribute. */
748 if (ospf_is_type_redistributed (ZEBRA_ROUTE_CONNECT))
749 if (EXTERNAL_INFO (ZEBRA_ROUTE_CONNECT))
750 for (rn = route_top (EXTERNAL_INFO (ZEBRA_ROUTE_CONNECT));
751 rn; rn = route_next (rn))
752 if ((ei = rn->info) != NULL)
paul68980082003-03-25 05:07:42 +0000753 if (ospf_external_info_find_lsa (ospf, &ei->p))
754 if (!ospf_distribute_check_connected (ospf, ei))
755 ospf_external_lsa_flush (ospf, ei->type, &ei->p,
ajs5339cfd2005-09-19 13:28:05 +0000756 ei->ifindex /*, ei->nexthop */);
paul718e3742002-12-13 20:15:29 +0000757
paul68980082003-03-25 05:07:42 +0000758 ospf_area_check_free (ospf, area_id);
paul718e3742002-12-13 20:15:29 +0000759
760 return 1;
761}
762
763int
764ospf_network_unset (struct ospf *ospf, struct prefix_ipv4 *p,
765 struct in_addr area_id)
766{
767 struct route_node *rn;
768 struct ospf_network *network;
769 struct external_info *ei;
770
771 rn = route_node_lookup (ospf->networks, (struct prefix *)p);
772 if (rn == NULL)
773 return 0;
774
775 network = rn->info;
776 if (!IPV4_ADDR_SAME (&area_id, &network->area_id))
777 return 0;
778
paul68980082003-03-25 05:07:42 +0000779 ospf_network_free (ospf, rn->info);
paul718e3742002-12-13 20:15:29 +0000780 rn->info = NULL;
781 route_unlock_node (rn);
782
paul68980082003-03-25 05:07:42 +0000783 ospf_if_update (ospf);
paul718e3742002-12-13 20:15:29 +0000784
785 /* Update connected redistribute. */
786 if (ospf_is_type_redistributed (ZEBRA_ROUTE_CONNECT))
787 if (EXTERNAL_INFO (ZEBRA_ROUTE_CONNECT))
788 for (rn = route_top (EXTERNAL_INFO (ZEBRA_ROUTE_CONNECT));
789 rn; rn = route_next (rn))
790 if ((ei = rn->info) != NULL)
paul68980082003-03-25 05:07:42 +0000791 if (!ospf_external_info_find_lsa (ospf, &ei->p))
792 if (ospf_distribute_check_connected (ospf, ei))
793 ospf_external_lsa_originate (ospf, ei);
paul718e3742002-12-13 20:15:29 +0000794
795 return 1;
796}
797
paul570f7592003-01-25 06:47:41 +0000798/* Check whether interface matches given network
799 * returns: 1, true. 0, false
800 */
801int
802ospf_network_match_iface(struct connected *co, struct prefix *net)
803{
Andrew J. Schorrf0ec8322007-04-30 16:52:05 +0000804/* #define COMPATIBILITY_MODE */
Andrew J. Schorre4529632006-12-12 19:18:21 +0000805 /* The old code used to have a special case for PtP interfaces:
806
807 if (if_is_pointopoint (co->ifp) && co->destination &&
808 IPV4_ADDR_SAME ( &(co->destination->u.prefix4), &(net->u.prefix4)))
809 return 1;
810
811 The new approach is much more general. If a peer address is supplied,
812 then we are routing to that prefix, so that's the address to compare
813 against (not the local address, which may not be unique).
814 */
815#ifndef COMPATIBILITY_MODE
816 /* new approach: more elegant and conceptually clean */
817 return prefix_match(net, CONNECTED_PREFIX(co));
818#else /* COMPATIBILITY_MODE */
819 /* match old (strange?) behavior */
820
paul570f7592003-01-25 06:47:41 +0000821 /* Behaviour to match both Cisco where:
822 * iface address lies within network specified -> ospf
823 * and zebra 0.9[2ish-3]:
824 * PtP special case: network specified == iface peer addr -> ospf
825 */
gdt8f40e892003-12-05 14:01:43 +0000826
paulf3ae74c2004-11-04 20:35:31 +0000827 /* For PtP, match if peer address matches network address exactly.
828 * This can be addr/32 or addr/p for p < 32, but the addr must match
829 * exactly; this is not a test for falling within the prefix. This
gdt8f40e892003-12-05 14:01:43 +0000830 * test is solely for compatibility with zebra.
gdt8f40e892003-12-05 14:01:43 +0000831 */
Andrew J. Schorre4529632006-12-12 19:18:21 +0000832 if (CONNECTED_PEER(co) &&
paulf3ae74c2004-11-04 20:35:31 +0000833 IPV4_ADDR_SAME ( &(co->destination->u.prefix4), &(net->u.prefix4)))
834 return 1;
835
836#if 0
837 /* Decline to accept PtP if dst address does not match the
838 * prefix. (ifdefed out because this is a workaround, not the
839 * desired behavior.) */
840 if (if_is_pointopoint (co->ifp) &&
841 ! prefix_match (net, co->destination))
842 return 0;
843#endif
844
845 /* If the address is within the prefix, accept. Note that this
846 * applies to PtP as well as other types.
847 */
848 if (prefix_match (net, co->address))
849 return 1;
850
851 return 0; /* no match */
Andrew J. Schorre4529632006-12-12 19:18:21 +0000852
853#endif /* COMPATIBILITY_MODE */
paul570f7592003-01-25 06:47:41 +0000854}
855
paul718e3742002-12-13 20:15:29 +0000856void
857ospf_network_run (struct ospf *ospf, struct prefix *p, struct ospf_area *area)
858{
859 struct interface *ifp;
paul1eb8ef22005-04-07 07:30:20 +0000860 struct connected *co;
hasso52dc7ee2004-09-23 19:18:23 +0000861 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000862
863 /* Schedule Router ID Update. */
paul86752842006-01-10 20:34:46 +0000864 if (ospf->router_id.s_addr == 0)
paulb29800a2005-11-20 14:50:45 +0000865 ospf_router_id_update (ospf);
866
paul718e3742002-12-13 20:15:29 +0000867 /* Get target interface. */
paul1eb8ef22005-04-07 07:30:20 +0000868 for (ALL_LIST_ELEMENTS_RO (om->iflist, node, ifp))
paul718e3742002-12-13 20:15:29 +0000869 {
paul1eb8ef22005-04-07 07:30:20 +0000870 struct listnode *cnode;
paul718e3742002-12-13 20:15:29 +0000871
paul718e3742002-12-13 20:15:29 +0000872 if (memcmp (ifp->name, "VLINK", 5) == 0)
873 continue;
874
875 /* if interface prefix is match specified prefix,
876 then create socket and join multicast group. */
paul1eb8ef22005-04-07 07:30:20 +0000877 for (ALL_LIST_ELEMENTS_RO (ifp->connected, cnode, co))
paul718e3742002-12-13 20:15:29 +0000878 {
paul718e3742002-12-13 20:15:29 +0000879 struct prefix *addr;
paul800dc102003-03-28 01:51:40 +0000880
paule7b050c2003-04-07 06:38:02 +0000881 if (CHECK_FLAG(co->flags,ZEBRA_IFA_SECONDARY))
882 continue;
paul718e3742002-12-13 20:15:29 +0000883
Andrew J. Schorre4529632006-12-12 19:18:21 +0000884 addr = CONNECTED_ID(co);
paul718e3742002-12-13 20:15:29 +0000885
paulcb3f37d2003-02-18 23:26:37 +0000886 if (p->family == co->address->family
paul68980082003-03-25 05:07:42 +0000887 && ! ospf_if_is_configured (ospf, &(addr->u.prefix4))
paulcb3f37d2003-02-18 23:26:37 +0000888 && ospf_network_match_iface(co,p))
paul570f7592003-01-25 06:47:41 +0000889 {
paul1eb8ef22005-04-07 07:30:20 +0000890 struct ospf_interface *oi;
paul718e3742002-12-13 20:15:29 +0000891
paul68980082003-03-25 05:07:42 +0000892 oi = ospf_if_new (ospf, ifp, co->address);
paul718e3742002-12-13 20:15:29 +0000893 oi->connected = co;
894
paul718e3742002-12-13 20:15:29 +0000895 oi->area = area;
896
897 oi->params = ospf_lookup_if_params (ifp, oi->address->u.prefix4);
898 oi->output_cost = ospf_if_get_output_cost (oi);
899
paul718e3742002-12-13 20:15:29 +0000900 /* Add pseudo neighbor. */
901 ospf_nbr_add_self (oi);
902
paul718e3742002-12-13 20:15:29 +0000903 /* Relate ospf interface to ospf instance. */
paul68980082003-03-25 05:07:42 +0000904 oi->ospf = ospf;
paul718e3742002-12-13 20:15:29 +0000905
906 /* update network type as interface flag */
907 /* If network type is specified previously,
908 skip network type setting. */
909 oi->type = IF_DEF_PARAMS (ifp)->type;
910
paul718e3742002-12-13 20:15:29 +0000911 ospf_area_add_if (oi->area, oi);
paulb29800a2005-11-20 14:50:45 +0000912
913 /* if router_id is not configured, dont bring up
914 * interfaces.
915 * ospf_router_id_update() will call ospf_if_update
916 * whenever r-id is configured instead.
917 */
paul86752842006-01-10 20:34:46 +0000918 if ((ospf->router_id.s_addr != 0)
paulb29800a2005-11-20 14:50:45 +0000919 && if_is_operative (ifp))
paul718e3742002-12-13 20:15:29 +0000920 ospf_if_up (oi);
paul718e3742002-12-13 20:15:29 +0000921 }
922 }
923 }
924}
925
926void
927ospf_ls_upd_queue_empty (struct ospf_interface *oi)
928{
929 struct route_node *rn;
paul1eb8ef22005-04-07 07:30:20 +0000930 struct listnode *node, *nnode;
hasso52dc7ee2004-09-23 19:18:23 +0000931 struct list *lst;
paul718e3742002-12-13 20:15:29 +0000932 struct ospf_lsa *lsa;
933
934 /* empty ls update queue */
935 for (rn = route_top (oi->ls_upd_queue); rn;
936 rn = route_next (rn))
hasso52dc7ee2004-09-23 19:18:23 +0000937 if ((lst = (struct list *) rn->info))
paul718e3742002-12-13 20:15:29 +0000938 {
paul1eb8ef22005-04-07 07:30:20 +0000939 for (ALL_LIST_ELEMENTS (lst, node, nnode, lsa))
Paul Jakma1fe6ed32006-07-26 09:37:26 +0000940 ospf_lsa_unlock (&lsa); /* oi->ls_upd_queue */
paul718e3742002-12-13 20:15:29 +0000941 list_free (lst);
942 rn->info = NULL;
943 }
944
945 /* remove update event */
946 if (oi->t_ls_upd_event)
947 {
948 thread_cancel (oi->t_ls_upd_event);
949 oi->t_ls_upd_event = NULL;
950 }
951}
952
953void
paul68980082003-03-25 05:07:42 +0000954ospf_if_update (struct ospf *ospf)
paul718e3742002-12-13 20:15:29 +0000955{
956 struct route_node *rn;
paul1eb8ef22005-04-07 07:30:20 +0000957 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000958 struct ospf_network *network;
959 struct ospf_area *area;
paul1eb8ef22005-04-07 07:30:20 +0000960 struct ospf_interface *oi;
paul718e3742002-12-13 20:15:29 +0000961
paul68980082003-03-25 05:07:42 +0000962 if (ospf != NULL)
paul718e3742002-12-13 20:15:29 +0000963 {
paulb29800a2005-11-20 14:50:45 +0000964 /* Router-ID must be configured. */
paul86752842006-01-10 20:34:46 +0000965 if (ospf->router_id.s_addr == 0)
paulb29800a2005-11-20 14:50:45 +0000966 return;
967
paul718e3742002-12-13 20:15:29 +0000968 /* Find interfaces that not configured already. */
paul1eb8ef22005-04-07 07:30:20 +0000969 for (ALL_LIST_ELEMENTS (ospf->oiflist, node, nnode, oi))
paul718e3742002-12-13 20:15:29 +0000970 {
971 int found = 0;
paul718e3742002-12-13 20:15:29 +0000972 struct connected *co = oi->connected;
973
paul718e3742002-12-13 20:15:29 +0000974 if (oi->type == OSPF_IFTYPE_VIRTUALLINK)
975 continue;
976
paul68980082003-03-25 05:07:42 +0000977 for (rn = route_top (ospf->networks); rn; rn = route_next (rn))
paul718e3742002-12-13 20:15:29 +0000978 {
979 if (rn->info == NULL)
980 continue;
981
paul570f7592003-01-25 06:47:41 +0000982 if (ospf_network_match_iface(co,&rn->p))
paul718e3742002-12-13 20:15:29 +0000983 {
984 found = 1;
985 route_unlock_node (rn);
986 break;
987 }
988 }
989
990 if (found == 0)
991 ospf_if_free (oi);
992 }
993
994 /* Run each interface. */
paul68980082003-03-25 05:07:42 +0000995 for (rn = route_top (ospf->networks); rn; rn = route_next (rn))
paul718e3742002-12-13 20:15:29 +0000996 if (rn->info != NULL)
997 {
998 network = (struct ospf_network *) rn->info;
paul68980082003-03-25 05:07:42 +0000999 area = ospf_area_get (ospf, network->area_id, network->format);
1000 ospf_network_run (ospf, &rn->p, area);
paul718e3742002-12-13 20:15:29 +00001001 }
1002 }
1003}
1004
1005void
paul68980082003-03-25 05:07:42 +00001006ospf_remove_vls_through_area (struct ospf *ospf, struct ospf_area *area)
paul718e3742002-12-13 20:15:29 +00001007{
paul1eb8ef22005-04-07 07:30:20 +00001008 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001009 struct ospf_vl_data *vl_data;
1010
paul1eb8ef22005-04-07 07:30:20 +00001011 for (ALL_LIST_ELEMENTS (ospf->vlinks, node, nnode, vl_data))
1012 if (IPV4_ADDR_SAME (&vl_data->vl_area_id, &area->area_id))
1013 ospf_vl_delete (ospf, vl_data);
paul718e3742002-12-13 20:15:29 +00001014}
1015
1016
1017struct message ospf_area_type_msg[] =
1018{
1019 { OSPF_AREA_DEFAULT, "Default" },
1020 { OSPF_AREA_STUB, "Stub" },
1021 { OSPF_AREA_NSSA, "NSSA" },
1022};
1023int ospf_area_type_msg_max = OSPF_AREA_TYPE_MAX;
1024
paul4dadc292005-05-06 21:37:42 +00001025static void
paul718e3742002-12-13 20:15:29 +00001026ospf_area_type_set (struct ospf_area *area, int type)
1027{
hasso52dc7ee2004-09-23 19:18:23 +00001028 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00001029 struct ospf_interface *oi;
1030
1031 if (area->external_routing == type)
1032 {
1033 if (IS_DEBUG_OSPF_EVENT)
ajs9b0e25c2004-12-08 19:06:51 +00001034 zlog_debug ("Area[%s]: Types are the same, ignored.",
paul718e3742002-12-13 20:15:29 +00001035 inet_ntoa (area->area_id));
1036 return;
1037 }
1038
1039 area->external_routing = type;
1040
1041 if (IS_DEBUG_OSPF_EVENT)
ajs9b0e25c2004-12-08 19:06:51 +00001042 zlog_debug ("Area[%s]: Configured as %s", inet_ntoa (area->area_id),
paul718e3742002-12-13 20:15:29 +00001043 LOOKUP (ospf_area_type_msg, type));
1044
1045 switch (area->external_routing)
1046 {
1047 case OSPF_AREA_DEFAULT:
paul1eb8ef22005-04-07 07:30:20 +00001048 for (ALL_LIST_ELEMENTS_RO (area->oiflist, node, oi))
1049 if (oi->nbr_self != NULL)
1050 {
1051 UNSET_FLAG (oi->nbr_self->options, OSPF_OPTION_NP);
1052 SET_FLAG (oi->nbr_self->options, OSPF_OPTION_E);
1053 }
paul718e3742002-12-13 20:15:29 +00001054 break;
1055 case OSPF_AREA_STUB:
paul1eb8ef22005-04-07 07:30:20 +00001056 for (ALL_LIST_ELEMENTS_RO (area->oiflist, node, oi))
1057 if (oi->nbr_self != NULL)
1058 {
1059 if (IS_DEBUG_OSPF_EVENT)
1060 zlog_debug ("setting options on %s accordingly", IF_NAME (oi));
1061 UNSET_FLAG (oi->nbr_self->options, OSPF_OPTION_NP);
1062 UNSET_FLAG (oi->nbr_self->options, OSPF_OPTION_E);
1063 if (IS_DEBUG_OSPF_EVENT)
1064 zlog_debug ("options set on %s: %x",
1065 IF_NAME (oi), OPTIONS (oi));
1066 }
paul718e3742002-12-13 20:15:29 +00001067 break;
1068 case OSPF_AREA_NSSA:
paul1eb8ef22005-04-07 07:30:20 +00001069 for (ALL_LIST_ELEMENTS_RO (area->oiflist, node, oi))
1070 if (oi->nbr_self != NULL)
1071 {
1072 zlog_debug ("setting nssa options on %s accordingly", IF_NAME (oi));
1073 UNSET_FLAG (oi->nbr_self->options, OSPF_OPTION_E);
1074 SET_FLAG (oi->nbr_self->options, OSPF_OPTION_NP);
1075 zlog_debug ("options set on %s: %x", IF_NAME (oi), OPTIONS (oi));
1076 }
paul718e3742002-12-13 20:15:29 +00001077 break;
1078 default:
1079 break;
1080 }
1081
1082 ospf_router_lsa_timer_add (area);
paul68980082003-03-25 05:07:42 +00001083 ospf_schedule_abr_task (area->ospf);
paul718e3742002-12-13 20:15:29 +00001084}
1085
1086int
paul68980082003-03-25 05:07:42 +00001087ospf_area_shortcut_set (struct ospf *ospf, struct ospf_area *area, int mode)
paul718e3742002-12-13 20:15:29 +00001088{
1089 if (area->shortcut_configured == mode)
1090 return 0;
1091
1092 area->shortcut_configured = mode;
1093 ospf_router_lsa_timer_add (area);
paul68980082003-03-25 05:07:42 +00001094 ospf_schedule_abr_task (ospf);
paul718e3742002-12-13 20:15:29 +00001095
paul68980082003-03-25 05:07:42 +00001096 ospf_area_check_free (ospf, area->area_id);
paul718e3742002-12-13 20:15:29 +00001097
1098 return 1;
1099}
1100
1101int
paul68980082003-03-25 05:07:42 +00001102ospf_area_shortcut_unset (struct ospf *ospf, struct ospf_area *area)
paul718e3742002-12-13 20:15:29 +00001103{
1104 area->shortcut_configured = OSPF_SHORTCUT_DEFAULT;
1105 ospf_router_lsa_timer_add (area);
paul68980082003-03-25 05:07:42 +00001106 ospf_area_check_free (ospf, area->area_id);
1107 ospf_schedule_abr_task (ospf);
paul718e3742002-12-13 20:15:29 +00001108
1109 return 1;
1110}
1111
paul4dadc292005-05-06 21:37:42 +00001112static int
paul718e3742002-12-13 20:15:29 +00001113ospf_area_vlink_count (struct ospf *ospf, struct ospf_area *area)
1114{
1115 struct ospf_vl_data *vl;
hasso52dc7ee2004-09-23 19:18:23 +00001116 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00001117 int count = 0;
1118
paul1eb8ef22005-04-07 07:30:20 +00001119 for (ALL_LIST_ELEMENTS_RO (ospf->vlinks, node, vl))
1120 if (IPV4_ADDR_SAME (&vl->vl_area_id, &area->area_id))
1121 count++;
paul718e3742002-12-13 20:15:29 +00001122
1123 return count;
1124}
1125
1126int
1127ospf_area_stub_set (struct ospf *ospf, struct in_addr area_id)
1128{
1129 struct ospf_area *area;
paul147193a2003-04-19 00:31:59 +00001130 int format = OSPF_AREA_ID_FORMAT_ADDRESS;
paul718e3742002-12-13 20:15:29 +00001131
paul68980082003-03-25 05:07:42 +00001132 area = ospf_area_get (ospf, area_id, format);
paul718e3742002-12-13 20:15:29 +00001133 if (ospf_area_vlink_count (ospf, area))
1134 return 0;
1135
1136 if (area->external_routing != OSPF_AREA_STUB)
1137 ospf_area_type_set (area, OSPF_AREA_STUB);
1138
1139 return 1;
1140}
1141
1142int
1143ospf_area_stub_unset (struct ospf *ospf, struct in_addr area_id)
1144{
1145 struct ospf_area *area;
1146
paul68980082003-03-25 05:07:42 +00001147 area = ospf_area_lookup_by_area_id (ospf, area_id);
paul718e3742002-12-13 20:15:29 +00001148 if (area == NULL)
1149 return 1;
1150
1151 if (area->external_routing == OSPF_AREA_STUB)
1152 ospf_area_type_set (area, OSPF_AREA_DEFAULT);
1153
paul68980082003-03-25 05:07:42 +00001154 ospf_area_check_free (ospf, area_id);
paul718e3742002-12-13 20:15:29 +00001155
1156 return 1;
1157}
1158
1159int
1160ospf_area_no_summary_set (struct ospf *ospf, struct in_addr area_id)
1161{
1162 struct ospf_area *area;
paul147193a2003-04-19 00:31:59 +00001163 int format = OSPF_AREA_ID_FORMAT_ADDRESS;
paul718e3742002-12-13 20:15:29 +00001164
paul68980082003-03-25 05:07:42 +00001165 area = ospf_area_get (ospf, area_id, format);
paul718e3742002-12-13 20:15:29 +00001166 area->no_summary = 1;
1167
1168 return 1;
1169}
1170
1171int
1172ospf_area_no_summary_unset (struct ospf *ospf, struct in_addr area_id)
1173{
1174 struct ospf_area *area;
1175
paul68980082003-03-25 05:07:42 +00001176 area = ospf_area_lookup_by_area_id (ospf, area_id);
paul718e3742002-12-13 20:15:29 +00001177 if (area == NULL)
1178 return 0;
1179
1180 area->no_summary = 0;
paul68980082003-03-25 05:07:42 +00001181 ospf_area_check_free (ospf, area_id);
paul718e3742002-12-13 20:15:29 +00001182
1183 return 1;
1184}
1185
1186int
1187ospf_area_nssa_set (struct ospf *ospf, struct in_addr area_id)
1188{
1189 struct ospf_area *area;
paul147193a2003-04-19 00:31:59 +00001190 int format = OSPF_AREA_ID_FORMAT_ADDRESS;
paul718e3742002-12-13 20:15:29 +00001191
paul68980082003-03-25 05:07:42 +00001192 area = ospf_area_get (ospf, area_id, format);
paul718e3742002-12-13 20:15:29 +00001193 if (ospf_area_vlink_count (ospf, area))
1194 return 0;
1195
1196 if (area->external_routing != OSPF_AREA_NSSA)
1197 {
1198 ospf_area_type_set (area, OSPF_AREA_NSSA);
1199 ospf->anyNSSA++;
1200 }
1201
paul084c7842003-06-22 08:35:18 +00001202 /* set NSSA area defaults */
1203 area->no_summary = 0;
1204 area->NSSATranslatorRole = OSPF_NSSA_ROLE_CANDIDATE;
pauld4a53d52003-07-12 21:30:57 +00001205 area->NSSATranslatorState = OSPF_NSSA_TRANSLATE_DISABLED;
paul084c7842003-06-22 08:35:18 +00001206 area->NSSATranslatorStabilityInterval = OSPF_NSSA_TRANS_STABLE_DEFAULT;
1207
paul718e3742002-12-13 20:15:29 +00001208 return 1;
1209}
1210
1211int
1212ospf_area_nssa_unset (struct ospf *ospf, struct in_addr area_id)
1213{
1214 struct ospf_area *area;
1215
paul68980082003-03-25 05:07:42 +00001216 area = ospf_area_lookup_by_area_id (ospf, area_id);
paul718e3742002-12-13 20:15:29 +00001217 if (area == NULL)
1218 return 0;
1219
1220 if (area->external_routing == OSPF_AREA_NSSA)
1221 {
1222 ospf->anyNSSA--;
1223 ospf_area_type_set (area, OSPF_AREA_DEFAULT);
1224 }
1225
paul68980082003-03-25 05:07:42 +00001226 ospf_area_check_free (ospf, area_id);
paul718e3742002-12-13 20:15:29 +00001227
1228 return 1;
1229}
1230
1231int
1232ospf_area_nssa_translator_role_set (struct ospf *ospf, struct in_addr area_id,
1233 int role)
1234{
1235 struct ospf_area *area;
1236
paul68980082003-03-25 05:07:42 +00001237 area = ospf_area_lookup_by_area_id (ospf, area_id);
paul718e3742002-12-13 20:15:29 +00001238 if (area == NULL)
1239 return 0;
1240
paul084c7842003-06-22 08:35:18 +00001241 area->NSSATranslatorRole = role;
paul718e3742002-12-13 20:15:29 +00001242
1243 return 1;
1244}
1245
paul4dadc292005-05-06 21:37:42 +00001246/* XXX: unused? Leave for symmetry? */
1247static int
paul718e3742002-12-13 20:15:29 +00001248ospf_area_nssa_translator_role_unset (struct ospf *ospf,
1249 struct in_addr area_id)
1250{
1251 struct ospf_area *area;
1252
paul68980082003-03-25 05:07:42 +00001253 area = ospf_area_lookup_by_area_id (ospf, area_id);
paul718e3742002-12-13 20:15:29 +00001254 if (area == NULL)
1255 return 0;
1256
paul084c7842003-06-22 08:35:18 +00001257 area->NSSATranslatorRole = OSPF_NSSA_ROLE_CANDIDATE;
paul718e3742002-12-13 20:15:29 +00001258
paul68980082003-03-25 05:07:42 +00001259 ospf_area_check_free (ospf, area_id);
paul718e3742002-12-13 20:15:29 +00001260
1261 return 1;
1262}
1263
1264int
paul68980082003-03-25 05:07:42 +00001265ospf_area_export_list_set (struct ospf *ospf,
paul6c835672004-10-11 11:00:30 +00001266 struct ospf_area *area, const char *list_name)
paul718e3742002-12-13 20:15:29 +00001267{
1268 struct access_list *list;
1269 list = access_list_lookup (AFI_IP, list_name);
1270
1271 EXPORT_LIST (area) = list;
1272
1273 if (EXPORT_NAME (area))
1274 free (EXPORT_NAME (area));
1275
1276 EXPORT_NAME (area) = strdup (list_name);
paul68980082003-03-25 05:07:42 +00001277 ospf_schedule_abr_task (ospf);
paul718e3742002-12-13 20:15:29 +00001278
1279 return 1;
1280}
1281
1282int
paul68980082003-03-25 05:07:42 +00001283ospf_area_export_list_unset (struct ospf *ospf, struct ospf_area * area)
paul718e3742002-12-13 20:15:29 +00001284{
1285
1286 EXPORT_LIST (area) = 0;
1287
1288 if (EXPORT_NAME (area))
1289 free (EXPORT_NAME (area));
1290
1291 EXPORT_NAME (area) = NULL;
1292
paul68980082003-03-25 05:07:42 +00001293 ospf_area_check_free (ospf, area->area_id);
paul718e3742002-12-13 20:15:29 +00001294
paul68980082003-03-25 05:07:42 +00001295 ospf_schedule_abr_task (ospf);
paul718e3742002-12-13 20:15:29 +00001296
1297 return 1;
1298}
1299
1300int
paul6c835672004-10-11 11:00:30 +00001301ospf_area_import_list_set (struct ospf *ospf, struct ospf_area *area,
1302 const char *name)
paul718e3742002-12-13 20:15:29 +00001303{
1304 struct access_list *list;
1305 list = access_list_lookup (AFI_IP, name);
1306
1307 IMPORT_LIST (area) = list;
1308
1309 if (IMPORT_NAME (area))
1310 free (IMPORT_NAME (area));
1311
1312 IMPORT_NAME (area) = strdup (name);
paul68980082003-03-25 05:07:42 +00001313 ospf_schedule_abr_task (ospf);
paul718e3742002-12-13 20:15:29 +00001314
1315 return 1;
1316}
1317
1318int
paul68980082003-03-25 05:07:42 +00001319ospf_area_import_list_unset (struct ospf *ospf, struct ospf_area * area)
paul718e3742002-12-13 20:15:29 +00001320{
1321 IMPORT_LIST (area) = 0;
1322
1323 if (IMPORT_NAME (area))
1324 free (IMPORT_NAME (area));
1325
1326 IMPORT_NAME (area) = NULL;
paul68980082003-03-25 05:07:42 +00001327 ospf_area_check_free (ospf, area->area_id);
paul718e3742002-12-13 20:15:29 +00001328
paul68980082003-03-25 05:07:42 +00001329 ospf_schedule_abr_task (ospf);
paul718e3742002-12-13 20:15:29 +00001330
1331 return 1;
1332}
1333
1334int
paul718e3742002-12-13 20:15:29 +00001335ospf_timers_refresh_set (struct ospf *ospf, int interval)
1336{
1337 int time_left;
1338
1339 if (ospf->lsa_refresh_interval == interval)
1340 return 1;
1341
1342 time_left = ospf->lsa_refresh_interval -
Paul Jakma2518efd2006-08-27 06:49:29 +00001343 (quagga_time (NULL) - ospf->lsa_refresher_started);
paul718e3742002-12-13 20:15:29 +00001344
1345 if (time_left > interval)
1346 {
1347 OSPF_TIMER_OFF (ospf->t_lsa_refresher);
1348 ospf->t_lsa_refresher =
1349 thread_add_timer (master, ospf_lsa_refresh_walker, ospf, interval);
1350 }
1351 ospf->lsa_refresh_interval = interval;
1352
1353 return 1;
1354}
1355
1356int
1357ospf_timers_refresh_unset (struct ospf *ospf)
1358{
1359 int time_left;
1360
1361 time_left = ospf->lsa_refresh_interval -
Paul Jakma2518efd2006-08-27 06:49:29 +00001362 (quagga_time (NULL) - ospf->lsa_refresher_started);
paul718e3742002-12-13 20:15:29 +00001363
1364 if (time_left > OSPF_LSA_REFRESH_INTERVAL_DEFAULT)
1365 {
1366 OSPF_TIMER_OFF (ospf->t_lsa_refresher);
1367 ospf->t_lsa_refresher =
1368 thread_add_timer (master, ospf_lsa_refresh_walker, ospf,
1369 OSPF_LSA_REFRESH_INTERVAL_DEFAULT);
1370 }
1371
1372 ospf->lsa_refresh_interval = OSPF_LSA_REFRESH_INTERVAL_DEFAULT;
1373
1374 return 1;
1375}
1376
1377
paul4dadc292005-05-06 21:37:42 +00001378static struct ospf_nbr_nbma *
1379ospf_nbr_nbma_new (void)
paul718e3742002-12-13 20:15:29 +00001380{
1381 struct ospf_nbr_nbma *nbr_nbma;
1382
1383 nbr_nbma = XMALLOC (MTYPE_OSPF_NEIGHBOR_STATIC,
1384 sizeof (struct ospf_nbr_nbma));
1385 memset (nbr_nbma, 0, sizeof (struct ospf_nbr_nbma));
1386
1387 nbr_nbma->priority = OSPF_NEIGHBOR_PRIORITY_DEFAULT;
1388 nbr_nbma->v_poll = OSPF_POLL_INTERVAL_DEFAULT;
1389
1390 return nbr_nbma;
1391}
1392
paul4dadc292005-05-06 21:37:42 +00001393static void
paul718e3742002-12-13 20:15:29 +00001394ospf_nbr_nbma_free (struct ospf_nbr_nbma *nbr_nbma)
1395{
1396 XFREE (MTYPE_OSPF_NEIGHBOR_STATIC, nbr_nbma);
1397}
1398
paul4dadc292005-05-06 21:37:42 +00001399static void
paul718e3742002-12-13 20:15:29 +00001400ospf_nbr_nbma_delete (struct ospf *ospf, struct ospf_nbr_nbma *nbr_nbma)
1401{
1402 struct route_node *rn;
1403 struct prefix_ipv4 p;
1404
1405 p.family = AF_INET;
1406 p.prefix = nbr_nbma->addr;
1407 p.prefixlen = IPV4_MAX_BITLEN;
1408
1409 rn = route_node_lookup (ospf->nbr_nbma, (struct prefix *)&p);
1410 if (rn)
1411 {
1412 ospf_nbr_nbma_free (rn->info);
1413 rn->info = NULL;
1414 route_unlock_node (rn);
1415 route_unlock_node (rn);
1416 }
1417}
1418
paul4dadc292005-05-06 21:37:42 +00001419static void
paul718e3742002-12-13 20:15:29 +00001420ospf_nbr_nbma_down (struct ospf_nbr_nbma *nbr_nbma)
1421{
1422 OSPF_TIMER_OFF (nbr_nbma->t_poll);
1423
1424 if (nbr_nbma->nbr)
1425 {
1426 nbr_nbma->nbr->nbr_nbma = NULL;
1427 OSPF_NSM_EVENT_EXECUTE (nbr_nbma->nbr, NSM_KillNbr);
1428 }
1429
1430 if (nbr_nbma->oi)
1431 listnode_delete (nbr_nbma->oi->nbr_nbma, nbr_nbma);
1432}
1433
paul4dadc292005-05-06 21:37:42 +00001434static void
paul718e3742002-12-13 20:15:29 +00001435ospf_nbr_nbma_add (struct ospf_nbr_nbma *nbr_nbma,
1436 struct ospf_interface *oi)
1437{
1438 struct ospf_neighbor *nbr;
1439 struct route_node *rn;
1440 struct prefix p;
1441
1442 if (oi->type != OSPF_IFTYPE_NBMA)
1443 return;
1444
1445 if (nbr_nbma->nbr != NULL)
1446 return;
1447
1448 if (IPV4_ADDR_SAME (&oi->nbr_self->address.u.prefix4, &nbr_nbma->addr))
1449 return;
1450
1451 nbr_nbma->oi = oi;
1452 listnode_add (oi->nbr_nbma, nbr_nbma);
1453
1454 /* Get neighbor information from table. */
1455 p.family = AF_INET;
1456 p.prefixlen = IPV4_MAX_BITLEN;
1457 p.u.prefix4 = nbr_nbma->addr;
1458
1459 rn = route_node_get (oi->nbrs, (struct prefix *)&p);
1460 if (rn->info)
1461 {
1462 nbr = rn->info;
1463 nbr->nbr_nbma = nbr_nbma;
1464 nbr_nbma->nbr = nbr;
1465
1466 route_unlock_node (rn);
1467 }
1468 else
1469 {
1470 nbr = rn->info = ospf_nbr_new (oi);
1471 nbr->state = NSM_Down;
1472 nbr->src = nbr_nbma->addr;
1473 nbr->nbr_nbma = nbr_nbma;
1474 nbr->priority = nbr_nbma->priority;
1475 nbr->address = p;
1476
1477 nbr_nbma->nbr = nbr;
1478
1479 OSPF_NSM_EVENT_EXECUTE (nbr, NSM_Start);
1480 }
1481}
1482
1483void
paul68980082003-03-25 05:07:42 +00001484ospf_nbr_nbma_if_update (struct ospf *ospf, struct ospf_interface *oi)
paul718e3742002-12-13 20:15:29 +00001485{
1486 struct ospf_nbr_nbma *nbr_nbma;
1487 struct route_node *rn;
1488 struct prefix_ipv4 p;
1489
1490 if (oi->type != OSPF_IFTYPE_NBMA)
1491 return;
1492
paul68980082003-03-25 05:07:42 +00001493 for (rn = route_top (ospf->nbr_nbma); rn; rn = route_next (rn))
paul718e3742002-12-13 20:15:29 +00001494 if ((nbr_nbma = rn->info))
1495 if (nbr_nbma->oi == NULL && nbr_nbma->nbr == NULL)
1496 {
1497 p.family = AF_INET;
1498 p.prefix = nbr_nbma->addr;
1499 p.prefixlen = IPV4_MAX_BITLEN;
1500
1501 if (prefix_match (oi->address, (struct prefix *)&p))
1502 ospf_nbr_nbma_add (nbr_nbma, oi);
1503 }
1504}
1505
1506struct ospf_nbr_nbma *
1507ospf_nbr_nbma_lookup (struct ospf *ospf, struct in_addr nbr_addr)
1508{
1509 struct route_node *rn;
1510 struct prefix_ipv4 p;
1511
1512 p.family = AF_INET;
1513 p.prefix = nbr_addr;
1514 p.prefixlen = IPV4_MAX_BITLEN;
1515
1516 rn = route_node_lookup (ospf->nbr_nbma, (struct prefix *)&p);
1517 if (rn)
1518 {
1519 route_unlock_node (rn);
1520 return rn->info;
1521 }
1522 return NULL;
1523}
1524
1525struct ospf_nbr_nbma *
paul68980082003-03-25 05:07:42 +00001526ospf_nbr_nbma_lookup_next (struct ospf *ospf, struct in_addr *addr, int first)
paul718e3742002-12-13 20:15:29 +00001527{
1528#if 0
1529 struct ospf_nbr_nbma *nbr_nbma;
hasso52dc7ee2004-09-23 19:18:23 +00001530 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00001531#endif
1532
paul68980082003-03-25 05:07:42 +00001533 if (ospf == NULL)
paul718e3742002-12-13 20:15:29 +00001534 return NULL;
1535
1536#if 0
paul1eb8ef22005-04-07 07:30:20 +00001537 for (ALL_LIST_ELEMENTS_RO (ospf->nbr_nbma, node, nbr_nbma))
paul718e3742002-12-13 20:15:29 +00001538 {
paul718e3742002-12-13 20:15:29 +00001539 if (first)
1540 {
1541 *addr = nbr_nbma->addr;
1542 return nbr_nbma;
1543 }
1544 else if (ntohl (nbr_nbma->addr.s_addr) > ntohl (addr->s_addr))
1545 {
1546 *addr = nbr_nbma->addr;
1547 return nbr_nbma;
1548 }
1549 }
1550#endif
1551 return NULL;
1552}
1553
1554int
1555ospf_nbr_nbma_set (struct ospf *ospf, struct in_addr nbr_addr)
1556{
1557 struct ospf_nbr_nbma *nbr_nbma;
1558 struct ospf_interface *oi;
1559 struct prefix_ipv4 p;
1560 struct route_node *rn;
hasso52dc7ee2004-09-23 19:18:23 +00001561 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00001562
1563 nbr_nbma = ospf_nbr_nbma_lookup (ospf, nbr_addr);
1564 if (nbr_nbma)
1565 return 0;
1566
1567 nbr_nbma = ospf_nbr_nbma_new ();
1568 nbr_nbma->addr = nbr_addr;
1569
1570 p.family = AF_INET;
1571 p.prefix = nbr_addr;
1572 p.prefixlen = IPV4_MAX_BITLEN;
1573
1574 rn = route_node_get (ospf->nbr_nbma, (struct prefix *)&p);
1575 rn->info = nbr_nbma;
1576
paul1eb8ef22005-04-07 07:30:20 +00001577 for (ALL_LIST_ELEMENTS_RO (ospf->oiflist, node, oi))
paul718e3742002-12-13 20:15:29 +00001578 {
paul718e3742002-12-13 20:15:29 +00001579 if (oi->type == OSPF_IFTYPE_NBMA)
1580 if (prefix_match (oi->address, (struct prefix *)&p))
1581 {
1582 ospf_nbr_nbma_add (nbr_nbma, oi);
1583 break;
1584 }
1585 }
1586
1587 return 1;
1588}
1589
1590int
1591ospf_nbr_nbma_unset (struct ospf *ospf, struct in_addr nbr_addr)
1592{
1593 struct ospf_nbr_nbma *nbr_nbma;
1594
1595 nbr_nbma = ospf_nbr_nbma_lookup (ospf, nbr_addr);
1596 if (nbr_nbma == NULL)
1597 return 0;
1598
1599 ospf_nbr_nbma_down (nbr_nbma);
1600 ospf_nbr_nbma_delete (ospf, nbr_nbma);
1601
1602 return 1;
1603}
1604
1605int
1606ospf_nbr_nbma_priority_set (struct ospf *ospf, struct in_addr nbr_addr,
1607 u_char priority)
1608{
1609 struct ospf_nbr_nbma *nbr_nbma;
1610
1611 nbr_nbma = ospf_nbr_nbma_lookup (ospf, nbr_addr);
1612 if (nbr_nbma == NULL)
1613 return 0;
1614
1615 if (nbr_nbma->priority != priority)
1616 nbr_nbma->priority = priority;
1617
1618 return 1;
1619}
1620
1621int
1622ospf_nbr_nbma_priority_unset (struct ospf *ospf, struct in_addr nbr_addr)
1623{
1624 struct ospf_nbr_nbma *nbr_nbma;
1625
1626 nbr_nbma = ospf_nbr_nbma_lookup (ospf, nbr_addr);
1627 if (nbr_nbma == NULL)
1628 return 0;
1629
1630 if (nbr_nbma != OSPF_NEIGHBOR_PRIORITY_DEFAULT)
1631 nbr_nbma->priority = OSPF_NEIGHBOR_PRIORITY_DEFAULT;
1632
1633 return 1;
1634}
1635
1636int
1637ospf_nbr_nbma_poll_interval_set (struct ospf *ospf, struct in_addr nbr_addr,
paul6c835672004-10-11 11:00:30 +00001638 unsigned int interval)
paul718e3742002-12-13 20:15:29 +00001639{
1640 struct ospf_nbr_nbma *nbr_nbma;
1641
1642 nbr_nbma = ospf_nbr_nbma_lookup (ospf, nbr_addr);
1643 if (nbr_nbma == NULL)
1644 return 0;
1645
1646 if (nbr_nbma->v_poll != interval)
1647 {
1648 nbr_nbma->v_poll = interval;
1649 if (nbr_nbma->oi && ospf_if_is_up (nbr_nbma->oi))
1650 {
1651 OSPF_TIMER_OFF (nbr_nbma->t_poll);
1652 OSPF_POLL_TIMER_ON (nbr_nbma->t_poll, ospf_poll_timer,
1653 nbr_nbma->v_poll);
1654 }
1655 }
1656
1657 return 1;
1658}
1659
1660int
1661ospf_nbr_nbma_poll_interval_unset (struct ospf *ospf, struct in_addr addr)
1662{
1663 struct ospf_nbr_nbma *nbr_nbma;
1664
1665 nbr_nbma = ospf_nbr_nbma_lookup (ospf, addr);
1666 if (nbr_nbma == NULL)
1667 return 0;
1668
1669 if (nbr_nbma->v_poll != OSPF_POLL_INTERVAL_DEFAULT)
1670 nbr_nbma->v_poll = OSPF_POLL_INTERVAL_DEFAULT;
1671
1672 return 1;
1673}
1674
paul718e3742002-12-13 20:15:29 +00001675void
paul020709f2003-04-04 02:44:16 +00001676ospf_master_init ()
1677{
1678 memset (&ospf_master, 0, sizeof (struct ospf_master));
1679
1680 om = &ospf_master;
1681 om->ospf = list_new ();
1682 om->master = thread_master_create ();
Paul Jakma2518efd2006-08-27 06:49:29 +00001683 om->start_time = quagga_time (NULL);
paul020709f2003-04-04 02:44:16 +00001684}