blob: a4c4fac31d55e4c0a118925a6b0803cc068c6075 [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"
Denis Ovsienkof102e752007-09-18 09:01:13 +000036#include "sockopt.h"
paul718e3742002-12-13 20:15:29 +000037
38#include "ospfd/ospfd.h"
39#include "ospfd/ospf_network.h"
40#include "ospfd/ospf_interface.h"
41#include "ospfd/ospf_ism.h"
42#include "ospfd/ospf_asbr.h"
43#include "ospfd/ospf_lsa.h"
44#include "ospfd/ospf_lsdb.h"
45#include "ospfd/ospf_neighbor.h"
46#include "ospfd/ospf_nsm.h"
47#include "ospfd/ospf_spf.h"
48#include "ospfd/ospf_packet.h"
49#include "ospfd/ospf_dump.h"
50#include "ospfd/ospf_zebra.h"
51#include "ospfd/ospf_abr.h"
52#include "ospfd/ospf_flood.h"
53#include "ospfd/ospf_route.h"
54#include "ospfd/ospf_ase.h"
55
paul020709f2003-04-04 02:44:16 +000056
pauledd7c242003-06-04 13:59:38 +000057
paul020709f2003-04-04 02:44:16 +000058/* OSPF process wide configuration. */
59static struct ospf_master ospf_master;
60
61/* OSPF process wide configuration pointer to export. */
62struct ospf_master *om;
paul718e3742002-12-13 20:15:29 +000063
64extern struct zclient *zclient;
hasso18a6dce2004-10-03 18:18:34 +000065extern struct in_addr router_id_zebra;
paul718e3742002-12-13 20:15:29 +000066
67
paul88d6cf32005-10-29 12:50:09 +000068static void ospf_remove_vls_through_area (struct ospf *, struct ospf_area *);
69static void ospf_network_free (struct ospf *, struct ospf_network *);
70static void ospf_area_free (struct ospf_area *);
71static void ospf_network_run (struct ospf *, struct prefix *, struct ospf_area *);
72static void ospf_finish_final (struct ospf *);
paul718e3742002-12-13 20:15:29 +000073
paul718e3742002-12-13 20:15:29 +000074#define OSPF_EXTERNAL_LSA_ORIGINATE_DELAY 1
paul88d6cf32005-10-29 12:50:09 +000075
paul718e3742002-12-13 20:15:29 +000076void
paul68980082003-03-25 05:07:42 +000077ospf_router_id_update (struct ospf *ospf)
paul718e3742002-12-13 20:15:29 +000078{
paul718e3742002-12-13 20:15:29 +000079 struct in_addr router_id, router_id_old;
paul1eb8ef22005-04-07 07:30:20 +000080 struct ospf_interface *oi;
hasso52dc7ee2004-09-23 19:18:23 +000081 struct listnode *node;
paul718e3742002-12-13 20:15:29 +000082
83 if (IS_DEBUG_OSPF_EVENT)
ajs9b0e25c2004-12-08 19:06:51 +000084 zlog_debug ("Router-ID[OLD:%s]: Update", inet_ntoa (ospf->router_id));
paul718e3742002-12-13 20:15:29 +000085
paul68980082003-03-25 05:07:42 +000086 router_id_old = ospf->router_id;
paul718e3742002-12-13 20:15:29 +000087
Andrew J. Schorr16700082006-07-27 22:29:06 +000088 /* Select the router ID based on these priorities:
89 1. Statically assigned router ID is always the first choice.
90 2. If there is no statically assigned router ID, then try to stick
91 with the most recent value, since changing router ID's is very
92 disruptive.
93 3. Last choice: just go with whatever the zebra daemon recommends.
94 */
paul68980082003-03-25 05:07:42 +000095 if (ospf->router_id_static.s_addr != 0)
96 router_id = ospf->router_id_static;
Andrew J. Schorr16700082006-07-27 22:29:06 +000097 else if (ospf->router_id.s_addr != 0)
98 router_id = ospf->router_id;
paul718e3742002-12-13 20:15:29 +000099 else
hasso18a6dce2004-10-03 18:18:34 +0000100 router_id = router_id_zebra;
paul718e3742002-12-13 20:15:29 +0000101
paul68980082003-03-25 05:07:42 +0000102 ospf->router_id = router_id;
paul718e3742002-12-13 20:15:29 +0000103
104 if (IS_DEBUG_OSPF_EVENT)
ajs9b0e25c2004-12-08 19:06:51 +0000105 zlog_debug ("Router-ID[NEW:%s]: Update", inet_ntoa (ospf->router_id));
paul718e3742002-12-13 20:15:29 +0000106
107 if (!IPV4_ADDR_SAME (&router_id_old, &router_id))
108 {
paul1eb8ef22005-04-07 07:30:20 +0000109 for (ALL_LIST_ELEMENTS_RO (ospf->oiflist, node, oi))
110 /* Update self-neighbor's router_id. */
111 oi->nbr_self->router_id = router_id;
paul718e3742002-12-13 20:15:29 +0000112
113 /* If AS-external-LSA is queued, then flush those LSAs. */
paul68980082003-03-25 05:07:42 +0000114 if (router_id_old.s_addr == 0 && ospf->external_origin)
paul718e3742002-12-13 20:15:29 +0000115 {
116 int type;
117 /* Originate each redistributed external route. */
118 for (type = 0; type < ZEBRA_ROUTE_MAX; type++)
paul68980082003-03-25 05:07:42 +0000119 if (ospf->external_origin & (1 << type))
paul718e3742002-12-13 20:15:29 +0000120 thread_add_event (master, ospf_external_lsa_originate_timer,
paul68980082003-03-25 05:07:42 +0000121 ospf, type);
paul718e3742002-12-13 20:15:29 +0000122 /* Originate Deafult. */
paul68980082003-03-25 05:07:42 +0000123 if (ospf->external_origin & (1 << ZEBRA_ROUTE_MAX))
Paul Jakma4021b602006-05-12 22:55:41 +0000124 thread_add_event (master, ospf_default_originate_timer, ospf, 0);
paul718e3742002-12-13 20:15:29 +0000125
paul68980082003-03-25 05:07:42 +0000126 ospf->external_origin = 0;
paul718e3742002-12-13 20:15:29 +0000127 }
128
paul68980082003-03-25 05:07:42 +0000129 OSPF_TIMER_ON (ospf->t_router_lsa_update,
paul718e3742002-12-13 20:15:29 +0000130 ospf_router_lsa_update_timer, OSPF_LSA_UPDATE_DELAY);
paulb29800a2005-11-20 14:50:45 +0000131
132 /* update ospf_interface's */
133 ospf_if_update (ospf);
paul718e3742002-12-13 20:15:29 +0000134 }
135}
paul718e3742002-12-13 20:15:29 +0000136
137/* For OSPF area sort by area id. */
paul4dadc292005-05-06 21:37:42 +0000138static int
paul718e3742002-12-13 20:15:29 +0000139ospf_area_id_cmp (struct ospf_area *a1, struct ospf_area *a2)
140{
141 if (ntohl (a1->area_id.s_addr) > ntohl (a2->area_id.s_addr))
142 return 1;
143 if (ntohl (a1->area_id.s_addr) < ntohl (a2->area_id.s_addr))
144 return -1;
145 return 0;
146}
147
148/* Allocate new ospf structure. */
paul4dadc292005-05-06 21:37:42 +0000149static struct ospf *
150ospf_new (void)
paul718e3742002-12-13 20:15:29 +0000151{
152 int i;
153
154 struct ospf *new = XCALLOC (MTYPE_OSPF_TOP, sizeof (struct ospf));
155
156 new->router_id.s_addr = htonl (0);
157 new->router_id_static.s_addr = htonl (0);
158
pauld57834f2005-07-12 20:04:22 +0000159 new->abr_type = OSPF_ABR_DEFAULT;
paul718e3742002-12-13 20:15:29 +0000160 new->oiflist = list_new ();
161 new->vlinks = list_new ();
162 new->areas = list_new ();
163 new->areas->cmp = (int (*)(void *, void *)) ospf_area_id_cmp;
164 new->networks = route_table_init ();
165 new->nbr_nbma = route_table_init ();
166
167 new->lsdb = ospf_lsdb_new ();
168
169 new->default_originate = DEFAULT_ORIGINATE_NONE;
170
Paul Jakma7ffa8fa2006-10-22 20:07:53 +0000171 new->passive_interface_default = OSPF_IF_ACTIVE;
172
paul718e3742002-12-13 20:15:29 +0000173 new->new_external_route = route_table_init ();
174 new->old_external_route = route_table_init ();
175 new->external_lsas = route_table_init ();
paul88d6cf32005-10-29 12:50:09 +0000176
177 new->stub_router_startup_time = OSPF_STUB_ROUTER_UNCONFIGURED;
paul31a59762005-11-14 11:11:11 +0000178 new->stub_router_shutdown_time = OSPF_STUB_ROUTER_UNCONFIGURED;
paul88d6cf32005-10-29 12:50:09 +0000179
paul718e3742002-12-13 20:15:29 +0000180 /* Distribute parameter init. */
181 for (i = 0; i <= ZEBRA_ROUTE_MAX; i++)
182 {
183 new->dmetric[i].type = -1;
184 new->dmetric[i].value = -1;
185 }
186 new->default_metric = -1;
187 new->ref_bandwidth = OSPF_DEFAULT_REF_BANDWIDTH;
188
189 /* SPF timer value init. */
190 new->spf_delay = OSPF_SPF_DELAY_DEFAULT;
191 new->spf_holdtime = OSPF_SPF_HOLDTIME_DEFAULT;
pauld24f6e22005-10-21 09:23:12 +0000192 new->spf_max_holdtime = OSPF_SPF_MAX_HOLDTIME_DEFAULT;
193 new->spf_hold_multiplier = 1;
paul718e3742002-12-13 20:15:29 +0000194
195 /* MaxAge init. */
196 new->maxage_lsa = list_new ();
197 new->t_maxage_walker =
198 thread_add_timer (master, ospf_lsa_maxage_walker,
paul68980082003-03-25 05:07:42 +0000199 new, OSPF_LSA_MAXAGE_CHECK_INTERVAL);
paul718e3742002-12-13 20:15:29 +0000200
201 /* Distance table init. */
202 new->distance_table = route_table_init ();
203
204 new->lsa_refresh_queue.index = 0;
205 new->lsa_refresh_interval = OSPF_LSA_REFRESH_INTERVAL_DEFAULT;
206 new->t_lsa_refresher = thread_add_timer (master, ospf_lsa_refresh_walker,
207 new, new->lsa_refresh_interval);
Paul Jakma2518efd2006-08-27 06:49:29 +0000208 new->lsa_refresher_started = quagga_time (NULL);
paul718e3742002-12-13 20:15:29 +0000209
ajs5c333492005-02-23 15:43:01 +0000210 if ((new->fd = ospf_sock_init()) < 0)
211 {
212 zlog_err("ospf_new: fatal error: ospf_sock_init was unable to open "
213 "a socket");
214 exit(1);
215 }
Denis Ovsienkof102e752007-09-18 09:01:13 +0000216 new->maxsndbuflen = getsockopt_so_sendbuf (new->fd);
217 if (IS_DEBUG_OSPF (zebra, ZEBRA_INTERFACE))
218 zlog_debug ("%s: starting with OSPF send buffer size %d",
219 __func__, new->maxsndbuflen);
ajs5c333492005-02-23 15:43:01 +0000220 if ((new->ibuf = stream_new(OSPF_MAX_PACKET_SIZE+1)) == NULL)
221 {
222 zlog_err("ospf_new: fatal error: stream_new(%u) failed allocating ibuf",
223 OSPF_MAX_PACKET_SIZE+1);
224 exit(1);
225 }
226 new->t_read = thread_add_read (master, ospf_read, new, new->fd);
paul718e3742002-12-13 20:15:29 +0000227 new->oi_write_q = list_new ();
228
229 return new;
230}
231
232struct ospf *
paul020709f2003-04-04 02:44:16 +0000233ospf_lookup ()
234{
235 if (listcount (om->ospf) == 0)
236 return NULL;
237
paul1eb8ef22005-04-07 07:30:20 +0000238 return listgetdata (listhead (om->ospf));
paul020709f2003-04-04 02:44:16 +0000239}
240
paul4dadc292005-05-06 21:37:42 +0000241static void
paul020709f2003-04-04 02:44:16 +0000242ospf_add (struct ospf *ospf)
243{
244 listnode_add (om->ospf, ospf);
245}
246
paul4dadc292005-05-06 21:37:42 +0000247static void
paul020709f2003-04-04 02:44:16 +0000248ospf_delete (struct ospf *ospf)
249{
250 listnode_delete (om->ospf, ospf);
251}
252
253struct ospf *
paul718e3742002-12-13 20:15:29 +0000254ospf_get ()
255{
paul020709f2003-04-04 02:44:16 +0000256 struct ospf *ospf;
paul718e3742002-12-13 20:15:29 +0000257
paul020709f2003-04-04 02:44:16 +0000258 ospf = ospf_lookup ();
259 if (ospf == NULL)
260 {
261 ospf = ospf_new ();
262 ospf_add (ospf);
paul718e3742002-12-13 20:15:29 +0000263
paul020709f2003-04-04 02:44:16 +0000264 if (ospf->router_id_static.s_addr == 0)
265 ospf_router_id_update (ospf);
paul718e3742002-12-13 20:15:29 +0000266
267#ifdef HAVE_OPAQUE_LSA
paul020709f2003-04-04 02:44:16 +0000268 ospf_opaque_type11_lsa_init (ospf);
paul718e3742002-12-13 20:15:29 +0000269#endif /* HAVE_OPAQUE_LSA */
paul020709f2003-04-04 02:44:16 +0000270 }
paul68980082003-03-25 05:07:42 +0000271
272 return ospf;
paul718e3742002-12-13 20:15:29 +0000273}
paul88d6cf32005-10-29 12:50:09 +0000274
paulc9c93d52005-11-26 13:31:11 +0000275/* Handle the second half of deferred shutdown. This is called either
276 * from the deferred-shutdown timer thread, or directly through
277 * ospf_deferred_shutdown_check.
paul88d6cf32005-10-29 12:50:09 +0000278 *
279 * Function is to cleanup G-R state, if required then call ospf_finish_final
280 * to complete shutdown of this ospf instance. Possibly exit if the
281 * whole process is being shutdown and this was the last OSPF instance.
282 */
283static void
paulc9c93d52005-11-26 13:31:11 +0000284ospf_deferred_shutdown_finish (struct ospf *ospf)
paul88d6cf32005-10-29 12:50:09 +0000285{
286 ospf->stub_router_shutdown_time = OSPF_STUB_ROUTER_UNCONFIGURED;
paulc9c93d52005-11-26 13:31:11 +0000287 OSPF_TIMER_OFF (ospf->t_deferred_shutdown);
paul88d6cf32005-10-29 12:50:09 +0000288
289 ospf_finish_final (ospf);
290
291 /* *ospf is now invalid */
292
293 /* ospfd being shut-down? If so, was this the last ospf instance? */
294 if (CHECK_FLAG (om->options, OSPF_MASTER_SHUTDOWN)
295 && (listcount (om->ospf) == 0))
296 exit (0);
297
298 return;
299}
300
301/* Timer thread for G-R */
302static int
paulc9c93d52005-11-26 13:31:11 +0000303ospf_deferred_shutdown_timer (struct thread *t)
paul88d6cf32005-10-29 12:50:09 +0000304{
305 struct ospf *ospf = THREAD_ARG(t);
306
paulc9c93d52005-11-26 13:31:11 +0000307 ospf_deferred_shutdown_finish (ospf);
paul88d6cf32005-10-29 12:50:09 +0000308
309 return 0;
310}
311
paulc9c93d52005-11-26 13:31:11 +0000312/* Check whether deferred-shutdown must be scheduled, otherwise call
paul88d6cf32005-10-29 12:50:09 +0000313 * down directly into second-half of instance shutdown.
314 */
315static void
paulc9c93d52005-11-26 13:31:11 +0000316ospf_deferred_shutdown_check (struct ospf *ospf)
paul88d6cf32005-10-29 12:50:09 +0000317{
318 unsigned long timeout;
319 struct listnode *ln;
320 struct ospf_area *area;
321
paulc9c93d52005-11-26 13:31:11 +0000322 /* deferred shutdown already running? */
323 if (ospf->t_deferred_shutdown)
paul88d6cf32005-10-29 12:50:09 +0000324 return;
325
326 /* Should we try push out max-metric LSAs? */
327 if (ospf->stub_router_shutdown_time != OSPF_STUB_ROUTER_UNCONFIGURED)
328 {
329 for (ALL_LIST_ELEMENTS_RO (ospf->areas, ln, area))
330 {
331 SET_FLAG (area->stub_router_state, OSPF_AREA_ADMIN_STUB_ROUTED);
332
333 if (!CHECK_FLAG (area->stub_router_state, OSPF_AREA_IS_STUB_ROUTED))
334 ospf_router_lsa_timer_add (area);
335 }
336 timeout = ospf->stub_router_shutdown_time;
337 }
338 else
paulc9c93d52005-11-26 13:31:11 +0000339 {
340 /* No timer needed */
341 ospf_deferred_shutdown_finish (ospf);
342 return;
343 }
paul88d6cf32005-10-29 12:50:09 +0000344
paulc9c93d52005-11-26 13:31:11 +0000345 OSPF_TIMER_ON (ospf->t_deferred_shutdown, ospf_deferred_shutdown_timer,
paul88d6cf32005-10-29 12:50:09 +0000346 timeout);
347 return;
348}
349
350/* Shut down the entire process */
351void
352ospf_terminate (void)
353{
354 struct ospf *ospf;
355 struct listnode *node, *nnode;
356
357 /* shutdown already in progress */
358 if (CHECK_FLAG (om->options, OSPF_MASTER_SHUTDOWN))
359 return;
360
361 SET_FLAG (om->options, OSPF_MASTER_SHUTDOWN);
362
Andrew J. Schorr4056a542007-02-27 13:55:46 +0000363 /* exit immediately if OSPF not actually running */
364 if (listcount(om->ospf) == 0)
365 exit(0);
366
paul88d6cf32005-10-29 12:50:09 +0000367 for (ALL_LIST_ELEMENTS (om->ospf, node, nnode, ospf))
368 ospf_finish (ospf);
369
370 /* Deliberately go back up, hopefully to thread scheduler, as
371 * One or more ospf_finish()'s may have deferred shutdown to a timer
372 * thread
373 */
374}
paul718e3742002-12-13 20:15:29 +0000375
376void
377ospf_finish (struct ospf *ospf)
378{
paulc9c93d52005-11-26 13:31:11 +0000379 /* let deferred shutdown decide */
380 ospf_deferred_shutdown_check (ospf);
paul88d6cf32005-10-29 12:50:09 +0000381
paulc9c93d52005-11-26 13:31:11 +0000382 /* if ospf_deferred_shutdown returns, then ospf_finish_final is
paul88d6cf32005-10-29 12:50:09 +0000383 * deferred to expiry of G-S timer thread. Return back up, hopefully
384 * to thread scheduler.
385 */
paulc9c93d52005-11-26 13:31:11 +0000386 return;
paul88d6cf32005-10-29 12:50:09 +0000387}
388
389/* Final cleanup of ospf instance */
390static void
391ospf_finish_final (struct ospf *ospf)
392{
paul718e3742002-12-13 20:15:29 +0000393 struct route_node *rn;
394 struct ospf_nbr_nbma *nbr_nbma;
paul68980082003-03-25 05:07:42 +0000395 struct ospf_lsa *lsa;
paul1eb8ef22005-04-07 07:30:20 +0000396 struct ospf_interface *oi;
397 struct ospf_area *area;
398 struct ospf_vl_data *vl_data;
399 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000400 int i;
401
402#ifdef HAVE_OPAQUE_LSA
403 ospf_opaque_type11_lsa_term (ospf);
404#endif /* HAVE_OPAQUE_LSA */
paul88d6cf32005-10-29 12:50:09 +0000405
406 /* be nice if this worked, but it doesn't */
407 /*ospf_flush_self_originated_lsas_now (ospf);*/
408
409 /* Unregister redistribution */
paul718e3742002-12-13 20:15:29 +0000410 for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
paul020709f2003-04-04 02:44:16 +0000411 ospf_redistribute_unset (ospf, i);
Paul Jakma29b5a042006-08-27 08:01:20 +0000412 ospf_redistribute_default_unset (ospf);
paul718e3742002-12-13 20:15:29 +0000413
paul1eb8ef22005-04-07 07:30:20 +0000414 for (ALL_LIST_ELEMENTS (ospf->areas, node, nnode, area))
415 ospf_remove_vls_through_area (ospf, area);
paul718e3742002-12-13 20:15:29 +0000416
paul1eb8ef22005-04-07 07:30:20 +0000417 for (ALL_LIST_ELEMENTS (ospf->vlinks, node, nnode, vl_data))
418 ospf_vl_delete (ospf, vl_data);
paul718e3742002-12-13 20:15:29 +0000419
420 list_delete (ospf->vlinks);
421
422 /* Reset interface. */
paul1eb8ef22005-04-07 07:30:20 +0000423 for (ALL_LIST_ELEMENTS (ospf->oiflist, node, nnode, oi))
424 ospf_if_free (oi);
paul718e3742002-12-13 20:15:29 +0000425
426 /* Clear static neighbors */
427 for (rn = route_top (ospf->nbr_nbma); rn; rn = route_next (rn))
428 if ((nbr_nbma = rn->info))
429 {
430 OSPF_POLL_TIMER_OFF (nbr_nbma->t_poll);
431
432 if (nbr_nbma->nbr)
433 {
434 nbr_nbma->nbr->nbr_nbma = NULL;
435 nbr_nbma->nbr = NULL;
436 }
437
438 if (nbr_nbma->oi)
439 {
440 listnode_delete (nbr_nbma->oi->nbr_nbma, nbr_nbma);
441 nbr_nbma->oi = NULL;
442 }
443
444 XFREE (MTYPE_OSPF_NEIGHBOR_STATIC, nbr_nbma);
445 }
446
447 route_table_finish (ospf->nbr_nbma);
448
449 /* Clear networks and Areas. */
450 for (rn = route_top (ospf->networks); rn; rn = route_next (rn))
451 {
452 struct ospf_network *network;
453
454 if ((network = rn->info) != NULL)
455 {
paul68980082003-03-25 05:07:42 +0000456 ospf_network_free (ospf, network);
paul718e3742002-12-13 20:15:29 +0000457 rn->info = NULL;
458 route_unlock_node (rn);
459 }
460 }
461
paul1eb8ef22005-04-07 07:30:20 +0000462 for (ALL_LIST_ELEMENTS (ospf->areas, node, nnode, area))
paul718e3742002-12-13 20:15:29 +0000463 {
paul718e3742002-12-13 20:15:29 +0000464 listnode_delete (ospf->areas, area);
465 ospf_area_free (area);
466 }
467
468 /* Cancel all timers. */
469 OSPF_TIMER_OFF (ospf->t_external_lsa);
paul718e3742002-12-13 20:15:29 +0000470 OSPF_TIMER_OFF (ospf->t_router_lsa_update);
471 OSPF_TIMER_OFF (ospf->t_spf_calc);
472 OSPF_TIMER_OFF (ospf->t_ase_calc);
473 OSPF_TIMER_OFF (ospf->t_maxage);
474 OSPF_TIMER_OFF (ospf->t_maxage_walker);
475 OSPF_TIMER_OFF (ospf->t_abr_task);
paul88d6cf32005-10-29 12:50:09 +0000476 OSPF_TIMER_OFF (ospf->t_asbr_check);
paul718e3742002-12-13 20:15:29 +0000477 OSPF_TIMER_OFF (ospf->t_distribute_update);
478 OSPF_TIMER_OFF (ospf->t_lsa_refresher);
479 OSPF_TIMER_OFF (ospf->t_read);
480 OSPF_TIMER_OFF (ospf->t_write);
paul31a59762005-11-14 11:11:11 +0000481#ifdef HAVE_OPAQUE_LSA
paul88d6cf32005-10-29 12:50:09 +0000482 OSPF_TIMER_OFF (ospf->t_opaque_lsa_self);
paul31a59762005-11-14 11:11:11 +0000483#endif
paul718e3742002-12-13 20:15:29 +0000484
485 close (ospf->fd);
ajs5c333492005-02-23 15:43:01 +0000486 stream_free(ospf->ibuf);
paul718e3742002-12-13 20:15:29 +0000487
488#ifdef HAVE_OPAQUE_LSA
paul68980082003-03-25 05:07:42 +0000489 LSDB_LOOP (OPAQUE_AS_LSDB (ospf), rn, lsa)
490 ospf_discard_from_db (ospf, ospf->lsdb, lsa);
paul718e3742002-12-13 20:15:29 +0000491#endif /* HAVE_OPAQUE_LSA */
paul68980082003-03-25 05:07:42 +0000492 LSDB_LOOP (EXTERNAL_LSDB (ospf), rn, lsa)
493 ospf_discard_from_db (ospf, ospf->lsdb, lsa);
494
paul718e3742002-12-13 20:15:29 +0000495 ospf_lsdb_delete_all (ospf->lsdb);
496 ospf_lsdb_free (ospf->lsdb);
497
paul1eb8ef22005-04-07 07:30:20 +0000498 for (ALL_LIST_ELEMENTS (ospf->maxage_lsa, node, nnode, lsa))
Paul Jakma1fe6ed32006-07-26 09:37:26 +0000499 ospf_lsa_unlock (&lsa); /* maxage_lsa */
paul718e3742002-12-13 20:15:29 +0000500
501 list_delete (ospf->maxage_lsa);
502
503 if (ospf->old_table)
504 ospf_route_table_free (ospf->old_table);
505 if (ospf->new_table)
506 {
507 ospf_route_delete (ospf->new_table);
508 ospf_route_table_free (ospf->new_table);
509 }
510 if (ospf->old_rtrs)
511 ospf_rtrs_free (ospf->old_rtrs);
512 if (ospf->new_rtrs)
513 ospf_rtrs_free (ospf->new_rtrs);
514 if (ospf->new_external_route)
515 {
516 ospf_route_delete (ospf->new_external_route);
517 ospf_route_table_free (ospf->new_external_route);
518 }
519 if (ospf->old_external_route)
520 {
521 ospf_route_delete (ospf->old_external_route);
522 ospf_route_table_free (ospf->old_external_route);
523 }
524 if (ospf->external_lsas)
525 {
526 ospf_ase_external_lsas_finish (ospf->external_lsas);
527 }
528
529 list_delete (ospf->areas);
530
531 for (i = ZEBRA_ROUTE_SYSTEM; i <= ZEBRA_ROUTE_MAX; i++)
532 if (EXTERNAL_INFO (i) != NULL)
533 for (rn = route_top (EXTERNAL_INFO (i)); rn; rn = route_next (rn))
534 {
535 if (rn->info == NULL)
536 continue;
537
538 XFREE (MTYPE_OSPF_EXTERNAL_INFO, rn->info);
539 rn->info = NULL;
540 route_unlock_node (rn);
541 }
542
paul68980082003-03-25 05:07:42 +0000543 ospf_distance_reset (ospf);
paul718e3742002-12-13 20:15:29 +0000544 route_table_finish (ospf->distance_table);
545
paul020709f2003-04-04 02:44:16 +0000546 ospf_delete (ospf);
paul718e3742002-12-13 20:15:29 +0000547
paul020709f2003-04-04 02:44:16 +0000548 XFREE (MTYPE_OSPF_TOP, ospf);
paul718e3742002-12-13 20:15:29 +0000549}
550
551
552/* allocate new OSPF Area object */
paul4dadc292005-05-06 21:37:42 +0000553static struct ospf_area *
paul68980082003-03-25 05:07:42 +0000554ospf_area_new (struct ospf *ospf, struct in_addr area_id)
paul718e3742002-12-13 20:15:29 +0000555{
556 struct ospf_area *new;
557
558 /* Allocate new config_network. */
559 new = XCALLOC (MTYPE_OSPF_AREA, sizeof (struct ospf_area));
560
paul68980082003-03-25 05:07:42 +0000561 new->ospf = ospf;
paul718e3742002-12-13 20:15:29 +0000562
563 new->area_id = area_id;
564
565 new->external_routing = OSPF_AREA_DEFAULT;
566 new->default_cost = 1;
567 new->auth_type = OSPF_AUTH_NULL;
paul88d6cf32005-10-29 12:50:09 +0000568
paul718e3742002-12-13 20:15:29 +0000569 /* New LSDB init. */
570 new->lsdb = ospf_lsdb_new ();
571
572 /* Self-originated LSAs initialize. */
573 new->router_lsa_self = NULL;
574
575#ifdef HAVE_OPAQUE_LSA
576 ospf_opaque_type10_lsa_init (new);
577#endif /* HAVE_OPAQUE_LSA */
578
579 new->oiflist = list_new ();
580 new->ranges = route_table_init ();
581
582 if (area_id.s_addr == OSPF_AREA_BACKBONE)
paul68980082003-03-25 05:07:42 +0000583 ospf->backbone = new;
paul718e3742002-12-13 20:15:29 +0000584
585 return new;
586}
587
588void
589ospf_area_free (struct ospf_area *area)
590{
paul68980082003-03-25 05:07:42 +0000591 struct route_node *rn;
592 struct ospf_lsa *lsa;
593
paul718e3742002-12-13 20:15:29 +0000594 /* Free LSDBs. */
paul68980082003-03-25 05:07:42 +0000595 LSDB_LOOP (ROUTER_LSDB (area), rn, lsa)
596 ospf_discard_from_db (area->ospf, area->lsdb, lsa);
597 LSDB_LOOP (NETWORK_LSDB (area), rn, lsa)
598 ospf_discard_from_db (area->ospf, area->lsdb, lsa);
599 LSDB_LOOP (SUMMARY_LSDB (area), rn, lsa)
600 ospf_discard_from_db (area->ospf, area->lsdb, lsa);
601 LSDB_LOOP (ASBR_SUMMARY_LSDB (area), rn, lsa)
602 ospf_discard_from_db (area->ospf, area->lsdb, lsa);
paul718e3742002-12-13 20:15:29 +0000603
paul68980082003-03-25 05:07:42 +0000604 LSDB_LOOP (NSSA_LSDB (area), rn, lsa)
605 ospf_discard_from_db (area->ospf, area->lsdb, lsa);
paul718e3742002-12-13 20:15:29 +0000606#ifdef HAVE_OPAQUE_LSA
paul68980082003-03-25 05:07:42 +0000607 LSDB_LOOP (OPAQUE_AREA_LSDB (area), rn, lsa)
608 ospf_discard_from_db (area->ospf, area->lsdb, lsa);
609 LSDB_LOOP (OPAQUE_LINK_LSDB (area), rn, lsa)
610 ospf_discard_from_db (area->ospf, area->lsdb, lsa);
paul718e3742002-12-13 20:15:29 +0000611#endif /* HAVE_OPAQUE_LSA */
612
613 ospf_lsdb_delete_all (area->lsdb);
614 ospf_lsdb_free (area->lsdb);
615
Paul Jakma1fe6ed32006-07-26 09:37:26 +0000616 ospf_lsa_unlock (&area->router_lsa_self);
paul718e3742002-12-13 20:15:29 +0000617
618 route_table_finish (area->ranges);
619 list_delete (area->oiflist);
620
621 if (EXPORT_NAME (area))
622 free (EXPORT_NAME (area));
623
624 if (IMPORT_NAME (area))
625 free (IMPORT_NAME (area));
626
627 /* Cancel timer. */
628 OSPF_TIMER_OFF (area->t_router_lsa_self);
paul88d6cf32005-10-29 12:50:09 +0000629 OSPF_TIMER_OFF (area->t_stub_router);
630#ifdef HAVE_OPAQUE_LSA
631 OSPF_TIMER_OFF (area->t_opaque_lsa_self);
632#endif /* HAVE_OPAQUE_LSA */
633
paul718e3742002-12-13 20:15:29 +0000634 if (OSPF_IS_AREA_BACKBONE (area))
paul68980082003-03-25 05:07:42 +0000635 area->ospf->backbone = NULL;
paul718e3742002-12-13 20:15:29 +0000636
637 XFREE (MTYPE_OSPF_AREA, area);
638}
639
640void
paul68980082003-03-25 05:07:42 +0000641ospf_area_check_free (struct ospf *ospf, struct in_addr area_id)
paul718e3742002-12-13 20:15:29 +0000642{
643 struct ospf_area *area;
644
paul68980082003-03-25 05:07:42 +0000645 area = ospf_area_lookup_by_area_id (ospf, area_id);
paul718e3742002-12-13 20:15:29 +0000646 if (area &&
647 listcount (area->oiflist) == 0 &&
648 area->ranges->top == NULL &&
649 area->shortcut_configured == OSPF_SHORTCUT_DEFAULT &&
650 area->external_routing == OSPF_AREA_DEFAULT &&
651 area->no_summary == 0 &&
652 area->default_cost == 1 &&
653 EXPORT_NAME (area) == NULL &&
654 IMPORT_NAME (area) == NULL &&
655 area->auth_type == OSPF_AUTH_NULL)
656 {
paul68980082003-03-25 05:07:42 +0000657 listnode_delete (ospf->areas, area);
paul718e3742002-12-13 20:15:29 +0000658 ospf_area_free (area);
659 }
660}
661
662struct ospf_area *
paul68980082003-03-25 05:07:42 +0000663ospf_area_get (struct ospf *ospf, struct in_addr area_id, int format)
paul718e3742002-12-13 20:15:29 +0000664{
665 struct ospf_area *area;
666
paul68980082003-03-25 05:07:42 +0000667 area = ospf_area_lookup_by_area_id (ospf, area_id);
paul718e3742002-12-13 20:15:29 +0000668 if (!area)
669 {
paul68980082003-03-25 05:07:42 +0000670 area = ospf_area_new (ospf, area_id);
paul718e3742002-12-13 20:15:29 +0000671 area->format = format;
paul68980082003-03-25 05:07:42 +0000672 listnode_add_sort (ospf->areas, area);
673 ospf_check_abr_status (ospf);
paul718e3742002-12-13 20:15:29 +0000674 }
675
676 return area;
677}
678
679struct ospf_area *
paul68980082003-03-25 05:07:42 +0000680ospf_area_lookup_by_area_id (struct ospf *ospf, struct in_addr area_id)
paul718e3742002-12-13 20:15:29 +0000681{
682 struct ospf_area *area;
hasso52dc7ee2004-09-23 19:18:23 +0000683 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000684
paul1eb8ef22005-04-07 07:30:20 +0000685 for (ALL_LIST_ELEMENTS_RO (ospf->areas, node, area))
686 if (IPV4_ADDR_SAME (&area->area_id, &area_id))
687 return area;
paul718e3742002-12-13 20:15:29 +0000688
689 return NULL;
690}
691
692void
693ospf_area_add_if (struct ospf_area *area, struct ospf_interface *oi)
694{
695 listnode_add (area->oiflist, oi);
696}
697
698void
699ospf_area_del_if (struct ospf_area *area, struct ospf_interface *oi)
700{
701 listnode_delete (area->oiflist, oi);
702}
703
704
705/* Config network statement related functions. */
paul4dadc292005-05-06 21:37:42 +0000706static struct ospf_network *
paul718e3742002-12-13 20:15:29 +0000707ospf_network_new (struct in_addr area_id, int format)
708{
709 struct ospf_network *new;
710 new = XCALLOC (MTYPE_OSPF_NETWORK, sizeof (struct ospf_network));
711
712 new->area_id = area_id;
713 new->format = format;
714
715 return new;
716}
717
718void
paul68980082003-03-25 05:07:42 +0000719ospf_network_free (struct ospf *ospf, struct ospf_network *network)
paul718e3742002-12-13 20:15:29 +0000720{
paul68980082003-03-25 05:07:42 +0000721 ospf_area_check_free (ospf, network->area_id);
722 ospf_schedule_abr_task (ospf);
paul718e3742002-12-13 20:15:29 +0000723 XFREE (MTYPE_OSPF_NETWORK, network);
724}
725
726int
727ospf_network_set (struct ospf *ospf, struct prefix_ipv4 *p,
728 struct in_addr area_id)
729{
730 struct ospf_network *network;
731 struct ospf_area *area;
732 struct route_node *rn;
733 struct external_info *ei;
paul147193a2003-04-19 00:31:59 +0000734 int ret = OSPF_AREA_ID_FORMAT_ADDRESS;
paul718e3742002-12-13 20:15:29 +0000735
736 rn = route_node_get (ospf->networks, (struct prefix *)p);
737 if (rn->info)
738 {
739 /* There is already same network statement. */
740 route_unlock_node (rn);
741 return 0;
742 }
743
744 rn->info = network = ospf_network_new (area_id, ret);
paul68980082003-03-25 05:07:42 +0000745 area = ospf_area_get (ospf, area_id, ret);
paul718e3742002-12-13 20:15:29 +0000746
747 /* Run network config now. */
748 ospf_network_run (ospf, (struct prefix *)p, area);
749
750 /* Update connected redistribute. */
751 if (ospf_is_type_redistributed (ZEBRA_ROUTE_CONNECT))
752 if (EXTERNAL_INFO (ZEBRA_ROUTE_CONNECT))
753 for (rn = route_top (EXTERNAL_INFO (ZEBRA_ROUTE_CONNECT));
754 rn; rn = route_next (rn))
755 if ((ei = rn->info) != NULL)
paul68980082003-03-25 05:07:42 +0000756 if (ospf_external_info_find_lsa (ospf, &ei->p))
757 if (!ospf_distribute_check_connected (ospf, ei))
758 ospf_external_lsa_flush (ospf, ei->type, &ei->p,
ajs5339cfd2005-09-19 13:28:05 +0000759 ei->ifindex /*, ei->nexthop */);
paul718e3742002-12-13 20:15:29 +0000760
paul68980082003-03-25 05:07:42 +0000761 ospf_area_check_free (ospf, area_id);
paul718e3742002-12-13 20:15:29 +0000762
763 return 1;
764}
765
766int
767ospf_network_unset (struct ospf *ospf, struct prefix_ipv4 *p,
768 struct in_addr area_id)
769{
770 struct route_node *rn;
771 struct ospf_network *network;
772 struct external_info *ei;
773
774 rn = route_node_lookup (ospf->networks, (struct prefix *)p);
775 if (rn == NULL)
776 return 0;
777
778 network = rn->info;
779 if (!IPV4_ADDR_SAME (&area_id, &network->area_id))
780 return 0;
781
paul68980082003-03-25 05:07:42 +0000782 ospf_network_free (ospf, rn->info);
paul718e3742002-12-13 20:15:29 +0000783 rn->info = NULL;
784 route_unlock_node (rn);
785
paul68980082003-03-25 05:07:42 +0000786 ospf_if_update (ospf);
paul718e3742002-12-13 20:15:29 +0000787
788 /* Update connected redistribute. */
789 if (ospf_is_type_redistributed (ZEBRA_ROUTE_CONNECT))
790 if (EXTERNAL_INFO (ZEBRA_ROUTE_CONNECT))
791 for (rn = route_top (EXTERNAL_INFO (ZEBRA_ROUTE_CONNECT));
792 rn; rn = route_next (rn))
793 if ((ei = rn->info) != NULL)
paul68980082003-03-25 05:07:42 +0000794 if (!ospf_external_info_find_lsa (ospf, &ei->p))
795 if (ospf_distribute_check_connected (ospf, ei))
796 ospf_external_lsa_originate (ospf, ei);
paul718e3742002-12-13 20:15:29 +0000797
798 return 1;
799}
800
paul570f7592003-01-25 06:47:41 +0000801/* Check whether interface matches given network
802 * returns: 1, true. 0, false
803 */
804int
805ospf_network_match_iface(struct connected *co, struct prefix *net)
806{
Andrew J. Schorrf0ec8322007-04-30 16:52:05 +0000807/* #define COMPATIBILITY_MODE */
Andrew J. Schorre4529632006-12-12 19:18:21 +0000808 /* The old code used to have a special case for PtP interfaces:
809
810 if (if_is_pointopoint (co->ifp) && co->destination &&
811 IPV4_ADDR_SAME ( &(co->destination->u.prefix4), &(net->u.prefix4)))
812 return 1;
813
814 The new approach is much more general. If a peer address is supplied,
815 then we are routing to that prefix, so that's the address to compare
816 against (not the local address, which may not be unique).
817 */
818#ifndef COMPATIBILITY_MODE
819 /* new approach: more elegant and conceptually clean */
820 return prefix_match(net, CONNECTED_PREFIX(co));
821#else /* COMPATIBILITY_MODE */
822 /* match old (strange?) behavior */
823
paul570f7592003-01-25 06:47:41 +0000824 /* Behaviour to match both Cisco where:
825 * iface address lies within network specified -> ospf
826 * and zebra 0.9[2ish-3]:
827 * PtP special case: network specified == iface peer addr -> ospf
828 */
gdt8f40e892003-12-05 14:01:43 +0000829
paulf3ae74c2004-11-04 20:35:31 +0000830 /* For PtP, match if peer address matches network address exactly.
831 * This can be addr/32 or addr/p for p < 32, but the addr must match
832 * exactly; this is not a test for falling within the prefix. This
gdt8f40e892003-12-05 14:01:43 +0000833 * test is solely for compatibility with zebra.
gdt8f40e892003-12-05 14:01:43 +0000834 */
Andrew J. Schorre4529632006-12-12 19:18:21 +0000835 if (CONNECTED_PEER(co) &&
paulf3ae74c2004-11-04 20:35:31 +0000836 IPV4_ADDR_SAME ( &(co->destination->u.prefix4), &(net->u.prefix4)))
837 return 1;
838
839#if 0
840 /* Decline to accept PtP if dst address does not match the
841 * prefix. (ifdefed out because this is a workaround, not the
842 * desired behavior.) */
843 if (if_is_pointopoint (co->ifp) &&
844 ! prefix_match (net, co->destination))
845 return 0;
846#endif
847
848 /* If the address is within the prefix, accept. Note that this
849 * applies to PtP as well as other types.
850 */
851 if (prefix_match (net, co->address))
852 return 1;
853
854 return 0; /* no match */
Andrew J. Schorre4529632006-12-12 19:18:21 +0000855
856#endif /* COMPATIBILITY_MODE */
paul570f7592003-01-25 06:47:41 +0000857}
858
paul718e3742002-12-13 20:15:29 +0000859void
860ospf_network_run (struct ospf *ospf, struct prefix *p, struct ospf_area *area)
861{
862 struct interface *ifp;
paul1eb8ef22005-04-07 07:30:20 +0000863 struct connected *co;
hasso52dc7ee2004-09-23 19:18:23 +0000864 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000865
866 /* Schedule Router ID Update. */
paul86752842006-01-10 20:34:46 +0000867 if (ospf->router_id.s_addr == 0)
paulb29800a2005-11-20 14:50:45 +0000868 ospf_router_id_update (ospf);
869
paul718e3742002-12-13 20:15:29 +0000870 /* Get target interface. */
paul1eb8ef22005-04-07 07:30:20 +0000871 for (ALL_LIST_ELEMENTS_RO (om->iflist, node, ifp))
paul718e3742002-12-13 20:15:29 +0000872 {
paul1eb8ef22005-04-07 07:30:20 +0000873 struct listnode *cnode;
paul718e3742002-12-13 20:15:29 +0000874
paul718e3742002-12-13 20:15:29 +0000875 if (memcmp (ifp->name, "VLINK", 5) == 0)
876 continue;
877
878 /* if interface prefix is match specified prefix,
879 then create socket and join multicast group. */
paul1eb8ef22005-04-07 07:30:20 +0000880 for (ALL_LIST_ELEMENTS_RO (ifp->connected, cnode, co))
paul718e3742002-12-13 20:15:29 +0000881 {
paul718e3742002-12-13 20:15:29 +0000882 struct prefix *addr;
paul800dc102003-03-28 01:51:40 +0000883
paule7b050c2003-04-07 06:38:02 +0000884 if (CHECK_FLAG(co->flags,ZEBRA_IFA_SECONDARY))
885 continue;
paul718e3742002-12-13 20:15:29 +0000886
Andrew J. Schorre4529632006-12-12 19:18:21 +0000887 addr = CONNECTED_ID(co);
paul718e3742002-12-13 20:15:29 +0000888
paulcb3f37d2003-02-18 23:26:37 +0000889 if (p->family == co->address->family
paul68980082003-03-25 05:07:42 +0000890 && ! ospf_if_is_configured (ospf, &(addr->u.prefix4))
paulcb3f37d2003-02-18 23:26:37 +0000891 && ospf_network_match_iface(co,p))
paul570f7592003-01-25 06:47:41 +0000892 {
paul1eb8ef22005-04-07 07:30:20 +0000893 struct ospf_interface *oi;
paul718e3742002-12-13 20:15:29 +0000894
paul68980082003-03-25 05:07:42 +0000895 oi = ospf_if_new (ospf, ifp, co->address);
paul718e3742002-12-13 20:15:29 +0000896 oi->connected = co;
897
paul718e3742002-12-13 20:15:29 +0000898 oi->area = area;
899
900 oi->params = ospf_lookup_if_params (ifp, oi->address->u.prefix4);
901 oi->output_cost = ospf_if_get_output_cost (oi);
902
paul718e3742002-12-13 20:15:29 +0000903 /* Add pseudo neighbor. */
904 ospf_nbr_add_self (oi);
905
paul718e3742002-12-13 20:15:29 +0000906 /* Relate ospf interface to ospf instance. */
paul68980082003-03-25 05:07:42 +0000907 oi->ospf = ospf;
paul718e3742002-12-13 20:15:29 +0000908
909 /* update network type as interface flag */
910 /* If network type is specified previously,
911 skip network type setting. */
912 oi->type = IF_DEF_PARAMS (ifp)->type;
913
paul718e3742002-12-13 20:15:29 +0000914 ospf_area_add_if (oi->area, oi);
paulb29800a2005-11-20 14:50:45 +0000915
916 /* if router_id is not configured, dont bring up
917 * interfaces.
918 * ospf_router_id_update() will call ospf_if_update
919 * whenever r-id is configured instead.
920 */
paul86752842006-01-10 20:34:46 +0000921 if ((ospf->router_id.s_addr != 0)
paulb29800a2005-11-20 14:50:45 +0000922 && if_is_operative (ifp))
paul718e3742002-12-13 20:15:29 +0000923 ospf_if_up (oi);
paul718e3742002-12-13 20:15:29 +0000924 }
925 }
926 }
927}
928
929void
930ospf_ls_upd_queue_empty (struct ospf_interface *oi)
931{
932 struct route_node *rn;
paul1eb8ef22005-04-07 07:30:20 +0000933 struct listnode *node, *nnode;
hasso52dc7ee2004-09-23 19:18:23 +0000934 struct list *lst;
paul718e3742002-12-13 20:15:29 +0000935 struct ospf_lsa *lsa;
936
937 /* empty ls update queue */
938 for (rn = route_top (oi->ls_upd_queue); rn;
939 rn = route_next (rn))
hasso52dc7ee2004-09-23 19:18:23 +0000940 if ((lst = (struct list *) rn->info))
paul718e3742002-12-13 20:15:29 +0000941 {
paul1eb8ef22005-04-07 07:30:20 +0000942 for (ALL_LIST_ELEMENTS (lst, node, nnode, lsa))
Paul Jakma1fe6ed32006-07-26 09:37:26 +0000943 ospf_lsa_unlock (&lsa); /* oi->ls_upd_queue */
paul718e3742002-12-13 20:15:29 +0000944 list_free (lst);
945 rn->info = NULL;
946 }
947
948 /* remove update event */
949 if (oi->t_ls_upd_event)
950 {
951 thread_cancel (oi->t_ls_upd_event);
952 oi->t_ls_upd_event = NULL;
953 }
954}
955
956void
paul68980082003-03-25 05:07:42 +0000957ospf_if_update (struct ospf *ospf)
paul718e3742002-12-13 20:15:29 +0000958{
959 struct route_node *rn;
paul1eb8ef22005-04-07 07:30:20 +0000960 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000961 struct ospf_network *network;
962 struct ospf_area *area;
paul1eb8ef22005-04-07 07:30:20 +0000963 struct ospf_interface *oi;
paul718e3742002-12-13 20:15:29 +0000964
paul68980082003-03-25 05:07:42 +0000965 if (ospf != NULL)
paul718e3742002-12-13 20:15:29 +0000966 {
paulb29800a2005-11-20 14:50:45 +0000967 /* Router-ID must be configured. */
paul86752842006-01-10 20:34:46 +0000968 if (ospf->router_id.s_addr == 0)
paulb29800a2005-11-20 14:50:45 +0000969 return;
970
paul718e3742002-12-13 20:15:29 +0000971 /* Find interfaces that not configured already. */
paul1eb8ef22005-04-07 07:30:20 +0000972 for (ALL_LIST_ELEMENTS (ospf->oiflist, node, nnode, oi))
paul718e3742002-12-13 20:15:29 +0000973 {
974 int found = 0;
paul718e3742002-12-13 20:15:29 +0000975 struct connected *co = oi->connected;
976
paul718e3742002-12-13 20:15:29 +0000977 if (oi->type == OSPF_IFTYPE_VIRTUALLINK)
978 continue;
979
paul68980082003-03-25 05:07:42 +0000980 for (rn = route_top (ospf->networks); rn; rn = route_next (rn))
paul718e3742002-12-13 20:15:29 +0000981 {
982 if (rn->info == NULL)
983 continue;
984
paul570f7592003-01-25 06:47:41 +0000985 if (ospf_network_match_iface(co,&rn->p))
paul718e3742002-12-13 20:15:29 +0000986 {
987 found = 1;
988 route_unlock_node (rn);
989 break;
990 }
991 }
992
993 if (found == 0)
994 ospf_if_free (oi);
995 }
996
997 /* Run each interface. */
paul68980082003-03-25 05:07:42 +0000998 for (rn = route_top (ospf->networks); rn; rn = route_next (rn))
paul718e3742002-12-13 20:15:29 +0000999 if (rn->info != NULL)
1000 {
1001 network = (struct ospf_network *) rn->info;
paul68980082003-03-25 05:07:42 +00001002 area = ospf_area_get (ospf, network->area_id, network->format);
1003 ospf_network_run (ospf, &rn->p, area);
paul718e3742002-12-13 20:15:29 +00001004 }
1005 }
1006}
1007
1008void
paul68980082003-03-25 05:07:42 +00001009ospf_remove_vls_through_area (struct ospf *ospf, struct ospf_area *area)
paul718e3742002-12-13 20:15:29 +00001010{
paul1eb8ef22005-04-07 07:30:20 +00001011 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001012 struct ospf_vl_data *vl_data;
1013
paul1eb8ef22005-04-07 07:30:20 +00001014 for (ALL_LIST_ELEMENTS (ospf->vlinks, node, nnode, vl_data))
1015 if (IPV4_ADDR_SAME (&vl_data->vl_area_id, &area->area_id))
1016 ospf_vl_delete (ospf, vl_data);
paul718e3742002-12-13 20:15:29 +00001017}
1018
1019
1020struct message ospf_area_type_msg[] =
1021{
1022 { OSPF_AREA_DEFAULT, "Default" },
1023 { OSPF_AREA_STUB, "Stub" },
1024 { OSPF_AREA_NSSA, "NSSA" },
1025};
1026int ospf_area_type_msg_max = OSPF_AREA_TYPE_MAX;
1027
paul4dadc292005-05-06 21:37:42 +00001028static void
paul718e3742002-12-13 20:15:29 +00001029ospf_area_type_set (struct ospf_area *area, int type)
1030{
hasso52dc7ee2004-09-23 19:18:23 +00001031 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00001032 struct ospf_interface *oi;
1033
1034 if (area->external_routing == type)
1035 {
1036 if (IS_DEBUG_OSPF_EVENT)
ajs9b0e25c2004-12-08 19:06:51 +00001037 zlog_debug ("Area[%s]: Types are the same, ignored.",
paul718e3742002-12-13 20:15:29 +00001038 inet_ntoa (area->area_id));
1039 return;
1040 }
1041
1042 area->external_routing = type;
1043
1044 if (IS_DEBUG_OSPF_EVENT)
ajs9b0e25c2004-12-08 19:06:51 +00001045 zlog_debug ("Area[%s]: Configured as %s", inet_ntoa (area->area_id),
paul718e3742002-12-13 20:15:29 +00001046 LOOKUP (ospf_area_type_msg, type));
1047
1048 switch (area->external_routing)
1049 {
1050 case OSPF_AREA_DEFAULT:
paul1eb8ef22005-04-07 07:30:20 +00001051 for (ALL_LIST_ELEMENTS_RO (area->oiflist, node, oi))
1052 if (oi->nbr_self != NULL)
1053 {
1054 UNSET_FLAG (oi->nbr_self->options, OSPF_OPTION_NP);
1055 SET_FLAG (oi->nbr_self->options, OSPF_OPTION_E);
1056 }
paul718e3742002-12-13 20:15:29 +00001057 break;
1058 case OSPF_AREA_STUB:
paul1eb8ef22005-04-07 07:30:20 +00001059 for (ALL_LIST_ELEMENTS_RO (area->oiflist, node, oi))
1060 if (oi->nbr_self != NULL)
1061 {
1062 if (IS_DEBUG_OSPF_EVENT)
1063 zlog_debug ("setting options on %s accordingly", IF_NAME (oi));
1064 UNSET_FLAG (oi->nbr_self->options, OSPF_OPTION_NP);
1065 UNSET_FLAG (oi->nbr_self->options, OSPF_OPTION_E);
1066 if (IS_DEBUG_OSPF_EVENT)
1067 zlog_debug ("options set on %s: %x",
1068 IF_NAME (oi), OPTIONS (oi));
1069 }
paul718e3742002-12-13 20:15:29 +00001070 break;
1071 case OSPF_AREA_NSSA:
paul1eb8ef22005-04-07 07:30:20 +00001072 for (ALL_LIST_ELEMENTS_RO (area->oiflist, node, oi))
1073 if (oi->nbr_self != NULL)
1074 {
1075 zlog_debug ("setting nssa options on %s accordingly", IF_NAME (oi));
1076 UNSET_FLAG (oi->nbr_self->options, OSPF_OPTION_E);
1077 SET_FLAG (oi->nbr_self->options, OSPF_OPTION_NP);
1078 zlog_debug ("options set on %s: %x", IF_NAME (oi), OPTIONS (oi));
1079 }
paul718e3742002-12-13 20:15:29 +00001080 break;
1081 default:
1082 break;
1083 }
1084
1085 ospf_router_lsa_timer_add (area);
paul68980082003-03-25 05:07:42 +00001086 ospf_schedule_abr_task (area->ospf);
paul718e3742002-12-13 20:15:29 +00001087}
1088
1089int
paul68980082003-03-25 05:07:42 +00001090ospf_area_shortcut_set (struct ospf *ospf, struct ospf_area *area, int mode)
paul718e3742002-12-13 20:15:29 +00001091{
1092 if (area->shortcut_configured == mode)
1093 return 0;
1094
1095 area->shortcut_configured = mode;
1096 ospf_router_lsa_timer_add (area);
paul68980082003-03-25 05:07:42 +00001097 ospf_schedule_abr_task (ospf);
paul718e3742002-12-13 20:15:29 +00001098
paul68980082003-03-25 05:07:42 +00001099 ospf_area_check_free (ospf, area->area_id);
paul718e3742002-12-13 20:15:29 +00001100
1101 return 1;
1102}
1103
1104int
paul68980082003-03-25 05:07:42 +00001105ospf_area_shortcut_unset (struct ospf *ospf, struct ospf_area *area)
paul718e3742002-12-13 20:15:29 +00001106{
1107 area->shortcut_configured = OSPF_SHORTCUT_DEFAULT;
1108 ospf_router_lsa_timer_add (area);
paul68980082003-03-25 05:07:42 +00001109 ospf_area_check_free (ospf, area->area_id);
1110 ospf_schedule_abr_task (ospf);
paul718e3742002-12-13 20:15:29 +00001111
1112 return 1;
1113}
1114
paul4dadc292005-05-06 21:37:42 +00001115static int
paul718e3742002-12-13 20:15:29 +00001116ospf_area_vlink_count (struct ospf *ospf, struct ospf_area *area)
1117{
1118 struct ospf_vl_data *vl;
hasso52dc7ee2004-09-23 19:18:23 +00001119 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00001120 int count = 0;
1121
paul1eb8ef22005-04-07 07:30:20 +00001122 for (ALL_LIST_ELEMENTS_RO (ospf->vlinks, node, vl))
1123 if (IPV4_ADDR_SAME (&vl->vl_area_id, &area->area_id))
1124 count++;
paul718e3742002-12-13 20:15:29 +00001125
1126 return count;
1127}
1128
1129int
1130ospf_area_stub_set (struct ospf *ospf, struct in_addr area_id)
1131{
1132 struct ospf_area *area;
paul147193a2003-04-19 00:31:59 +00001133 int format = OSPF_AREA_ID_FORMAT_ADDRESS;
paul718e3742002-12-13 20:15:29 +00001134
paul68980082003-03-25 05:07:42 +00001135 area = ospf_area_get (ospf, area_id, format);
paul718e3742002-12-13 20:15:29 +00001136 if (ospf_area_vlink_count (ospf, area))
1137 return 0;
1138
1139 if (area->external_routing != OSPF_AREA_STUB)
1140 ospf_area_type_set (area, OSPF_AREA_STUB);
1141
1142 return 1;
1143}
1144
1145int
1146ospf_area_stub_unset (struct ospf *ospf, struct in_addr area_id)
1147{
1148 struct ospf_area *area;
1149
paul68980082003-03-25 05:07:42 +00001150 area = ospf_area_lookup_by_area_id (ospf, area_id);
paul718e3742002-12-13 20:15:29 +00001151 if (area == NULL)
1152 return 1;
1153
1154 if (area->external_routing == OSPF_AREA_STUB)
1155 ospf_area_type_set (area, OSPF_AREA_DEFAULT);
1156
paul68980082003-03-25 05:07:42 +00001157 ospf_area_check_free (ospf, area_id);
paul718e3742002-12-13 20:15:29 +00001158
1159 return 1;
1160}
1161
1162int
1163ospf_area_no_summary_set (struct ospf *ospf, struct in_addr area_id)
1164{
1165 struct ospf_area *area;
paul147193a2003-04-19 00:31:59 +00001166 int format = OSPF_AREA_ID_FORMAT_ADDRESS;
paul718e3742002-12-13 20:15:29 +00001167
paul68980082003-03-25 05:07:42 +00001168 area = ospf_area_get (ospf, area_id, format);
paul718e3742002-12-13 20:15:29 +00001169 area->no_summary = 1;
1170
1171 return 1;
1172}
1173
1174int
1175ospf_area_no_summary_unset (struct ospf *ospf, struct in_addr area_id)
1176{
1177 struct ospf_area *area;
1178
paul68980082003-03-25 05:07:42 +00001179 area = ospf_area_lookup_by_area_id (ospf, area_id);
paul718e3742002-12-13 20:15:29 +00001180 if (area == NULL)
1181 return 0;
1182
1183 area->no_summary = 0;
paul68980082003-03-25 05:07:42 +00001184 ospf_area_check_free (ospf, area_id);
paul718e3742002-12-13 20:15:29 +00001185
1186 return 1;
1187}
1188
1189int
1190ospf_area_nssa_set (struct ospf *ospf, struct in_addr area_id)
1191{
1192 struct ospf_area *area;
paul147193a2003-04-19 00:31:59 +00001193 int format = OSPF_AREA_ID_FORMAT_ADDRESS;
paul718e3742002-12-13 20:15:29 +00001194
paul68980082003-03-25 05:07:42 +00001195 area = ospf_area_get (ospf, area_id, format);
paul718e3742002-12-13 20:15:29 +00001196 if (ospf_area_vlink_count (ospf, area))
1197 return 0;
1198
1199 if (area->external_routing != OSPF_AREA_NSSA)
1200 {
1201 ospf_area_type_set (area, OSPF_AREA_NSSA);
1202 ospf->anyNSSA++;
1203 }
1204
paul084c7842003-06-22 08:35:18 +00001205 /* set NSSA area defaults */
1206 area->no_summary = 0;
1207 area->NSSATranslatorRole = OSPF_NSSA_ROLE_CANDIDATE;
pauld4a53d52003-07-12 21:30:57 +00001208 area->NSSATranslatorState = OSPF_NSSA_TRANSLATE_DISABLED;
paul084c7842003-06-22 08:35:18 +00001209 area->NSSATranslatorStabilityInterval = OSPF_NSSA_TRANS_STABLE_DEFAULT;
1210
paul718e3742002-12-13 20:15:29 +00001211 return 1;
1212}
1213
1214int
1215ospf_area_nssa_unset (struct ospf *ospf, struct in_addr area_id)
1216{
1217 struct ospf_area *area;
1218
paul68980082003-03-25 05:07:42 +00001219 area = ospf_area_lookup_by_area_id (ospf, area_id);
paul718e3742002-12-13 20:15:29 +00001220 if (area == NULL)
1221 return 0;
1222
1223 if (area->external_routing == OSPF_AREA_NSSA)
1224 {
1225 ospf->anyNSSA--;
1226 ospf_area_type_set (area, OSPF_AREA_DEFAULT);
1227 }
1228
paul68980082003-03-25 05:07:42 +00001229 ospf_area_check_free (ospf, area_id);
paul718e3742002-12-13 20:15:29 +00001230
1231 return 1;
1232}
1233
1234int
1235ospf_area_nssa_translator_role_set (struct ospf *ospf, struct in_addr area_id,
1236 int role)
1237{
1238 struct ospf_area *area;
1239
paul68980082003-03-25 05:07:42 +00001240 area = ospf_area_lookup_by_area_id (ospf, area_id);
paul718e3742002-12-13 20:15:29 +00001241 if (area == NULL)
1242 return 0;
1243
paul084c7842003-06-22 08:35:18 +00001244 area->NSSATranslatorRole = role;
paul718e3742002-12-13 20:15:29 +00001245
1246 return 1;
1247}
1248
paul4dadc292005-05-06 21:37:42 +00001249/* XXX: unused? Leave for symmetry? */
1250static int
paul718e3742002-12-13 20:15:29 +00001251ospf_area_nssa_translator_role_unset (struct ospf *ospf,
1252 struct in_addr area_id)
1253{
1254 struct ospf_area *area;
1255
paul68980082003-03-25 05:07:42 +00001256 area = ospf_area_lookup_by_area_id (ospf, area_id);
paul718e3742002-12-13 20:15:29 +00001257 if (area == NULL)
1258 return 0;
1259
paul084c7842003-06-22 08:35:18 +00001260 area->NSSATranslatorRole = OSPF_NSSA_ROLE_CANDIDATE;
paul718e3742002-12-13 20:15:29 +00001261
paul68980082003-03-25 05:07:42 +00001262 ospf_area_check_free (ospf, area_id);
paul718e3742002-12-13 20:15:29 +00001263
1264 return 1;
1265}
1266
1267int
paul68980082003-03-25 05:07:42 +00001268ospf_area_export_list_set (struct ospf *ospf,
paul6c835672004-10-11 11:00:30 +00001269 struct ospf_area *area, const char *list_name)
paul718e3742002-12-13 20:15:29 +00001270{
1271 struct access_list *list;
1272 list = access_list_lookup (AFI_IP, list_name);
1273
1274 EXPORT_LIST (area) = list;
1275
1276 if (EXPORT_NAME (area))
1277 free (EXPORT_NAME (area));
1278
1279 EXPORT_NAME (area) = strdup (list_name);
paul68980082003-03-25 05:07:42 +00001280 ospf_schedule_abr_task (ospf);
paul718e3742002-12-13 20:15:29 +00001281
1282 return 1;
1283}
1284
1285int
paul68980082003-03-25 05:07:42 +00001286ospf_area_export_list_unset (struct ospf *ospf, struct ospf_area * area)
paul718e3742002-12-13 20:15:29 +00001287{
1288
1289 EXPORT_LIST (area) = 0;
1290
1291 if (EXPORT_NAME (area))
1292 free (EXPORT_NAME (area));
1293
1294 EXPORT_NAME (area) = NULL;
1295
paul68980082003-03-25 05:07:42 +00001296 ospf_area_check_free (ospf, area->area_id);
paul718e3742002-12-13 20:15:29 +00001297
paul68980082003-03-25 05:07:42 +00001298 ospf_schedule_abr_task (ospf);
paul718e3742002-12-13 20:15:29 +00001299
1300 return 1;
1301}
1302
1303int
paul6c835672004-10-11 11:00:30 +00001304ospf_area_import_list_set (struct ospf *ospf, struct ospf_area *area,
1305 const char *name)
paul718e3742002-12-13 20:15:29 +00001306{
1307 struct access_list *list;
1308 list = access_list_lookup (AFI_IP, name);
1309
1310 IMPORT_LIST (area) = list;
1311
1312 if (IMPORT_NAME (area))
1313 free (IMPORT_NAME (area));
1314
1315 IMPORT_NAME (area) = strdup (name);
paul68980082003-03-25 05:07:42 +00001316 ospf_schedule_abr_task (ospf);
paul718e3742002-12-13 20:15:29 +00001317
1318 return 1;
1319}
1320
1321int
paul68980082003-03-25 05:07:42 +00001322ospf_area_import_list_unset (struct ospf *ospf, struct ospf_area * area)
paul718e3742002-12-13 20:15:29 +00001323{
1324 IMPORT_LIST (area) = 0;
1325
1326 if (IMPORT_NAME (area))
1327 free (IMPORT_NAME (area));
1328
1329 IMPORT_NAME (area) = NULL;
paul68980082003-03-25 05:07:42 +00001330 ospf_area_check_free (ospf, area->area_id);
paul718e3742002-12-13 20:15:29 +00001331
paul68980082003-03-25 05:07:42 +00001332 ospf_schedule_abr_task (ospf);
paul718e3742002-12-13 20:15:29 +00001333
1334 return 1;
1335}
1336
1337int
paul718e3742002-12-13 20:15:29 +00001338ospf_timers_refresh_set (struct ospf *ospf, int interval)
1339{
1340 int time_left;
1341
1342 if (ospf->lsa_refresh_interval == interval)
1343 return 1;
1344
1345 time_left = ospf->lsa_refresh_interval -
Paul Jakma2518efd2006-08-27 06:49:29 +00001346 (quagga_time (NULL) - ospf->lsa_refresher_started);
paul718e3742002-12-13 20:15:29 +00001347
1348 if (time_left > interval)
1349 {
1350 OSPF_TIMER_OFF (ospf->t_lsa_refresher);
1351 ospf->t_lsa_refresher =
1352 thread_add_timer (master, ospf_lsa_refresh_walker, ospf, interval);
1353 }
1354 ospf->lsa_refresh_interval = interval;
1355
1356 return 1;
1357}
1358
1359int
1360ospf_timers_refresh_unset (struct ospf *ospf)
1361{
1362 int time_left;
1363
1364 time_left = ospf->lsa_refresh_interval -
Paul Jakma2518efd2006-08-27 06:49:29 +00001365 (quagga_time (NULL) - ospf->lsa_refresher_started);
paul718e3742002-12-13 20:15:29 +00001366
1367 if (time_left > OSPF_LSA_REFRESH_INTERVAL_DEFAULT)
1368 {
1369 OSPF_TIMER_OFF (ospf->t_lsa_refresher);
1370 ospf->t_lsa_refresher =
1371 thread_add_timer (master, ospf_lsa_refresh_walker, ospf,
1372 OSPF_LSA_REFRESH_INTERVAL_DEFAULT);
1373 }
1374
1375 ospf->lsa_refresh_interval = OSPF_LSA_REFRESH_INTERVAL_DEFAULT;
1376
1377 return 1;
1378}
1379
1380
paul4dadc292005-05-06 21:37:42 +00001381static struct ospf_nbr_nbma *
1382ospf_nbr_nbma_new (void)
paul718e3742002-12-13 20:15:29 +00001383{
1384 struct ospf_nbr_nbma *nbr_nbma;
1385
1386 nbr_nbma = XMALLOC (MTYPE_OSPF_NEIGHBOR_STATIC,
1387 sizeof (struct ospf_nbr_nbma));
1388 memset (nbr_nbma, 0, sizeof (struct ospf_nbr_nbma));
1389
1390 nbr_nbma->priority = OSPF_NEIGHBOR_PRIORITY_DEFAULT;
1391 nbr_nbma->v_poll = OSPF_POLL_INTERVAL_DEFAULT;
1392
1393 return nbr_nbma;
1394}
1395
paul4dadc292005-05-06 21:37:42 +00001396static void
paul718e3742002-12-13 20:15:29 +00001397ospf_nbr_nbma_free (struct ospf_nbr_nbma *nbr_nbma)
1398{
1399 XFREE (MTYPE_OSPF_NEIGHBOR_STATIC, nbr_nbma);
1400}
1401
paul4dadc292005-05-06 21:37:42 +00001402static void
paul718e3742002-12-13 20:15:29 +00001403ospf_nbr_nbma_delete (struct ospf *ospf, struct ospf_nbr_nbma *nbr_nbma)
1404{
1405 struct route_node *rn;
1406 struct prefix_ipv4 p;
1407
1408 p.family = AF_INET;
1409 p.prefix = nbr_nbma->addr;
1410 p.prefixlen = IPV4_MAX_BITLEN;
1411
1412 rn = route_node_lookup (ospf->nbr_nbma, (struct prefix *)&p);
1413 if (rn)
1414 {
1415 ospf_nbr_nbma_free (rn->info);
1416 rn->info = NULL;
1417 route_unlock_node (rn);
1418 route_unlock_node (rn);
1419 }
1420}
1421
paul4dadc292005-05-06 21:37:42 +00001422static void
paul718e3742002-12-13 20:15:29 +00001423ospf_nbr_nbma_down (struct ospf_nbr_nbma *nbr_nbma)
1424{
1425 OSPF_TIMER_OFF (nbr_nbma->t_poll);
1426
1427 if (nbr_nbma->nbr)
1428 {
1429 nbr_nbma->nbr->nbr_nbma = NULL;
1430 OSPF_NSM_EVENT_EXECUTE (nbr_nbma->nbr, NSM_KillNbr);
1431 }
1432
1433 if (nbr_nbma->oi)
1434 listnode_delete (nbr_nbma->oi->nbr_nbma, nbr_nbma);
1435}
1436
paul4dadc292005-05-06 21:37:42 +00001437static void
paul718e3742002-12-13 20:15:29 +00001438ospf_nbr_nbma_add (struct ospf_nbr_nbma *nbr_nbma,
1439 struct ospf_interface *oi)
1440{
1441 struct ospf_neighbor *nbr;
1442 struct route_node *rn;
1443 struct prefix p;
1444
1445 if (oi->type != OSPF_IFTYPE_NBMA)
1446 return;
1447
1448 if (nbr_nbma->nbr != NULL)
1449 return;
1450
1451 if (IPV4_ADDR_SAME (&oi->nbr_self->address.u.prefix4, &nbr_nbma->addr))
1452 return;
1453
1454 nbr_nbma->oi = oi;
1455 listnode_add (oi->nbr_nbma, nbr_nbma);
1456
1457 /* Get neighbor information from table. */
1458 p.family = AF_INET;
1459 p.prefixlen = IPV4_MAX_BITLEN;
1460 p.u.prefix4 = nbr_nbma->addr;
1461
1462 rn = route_node_get (oi->nbrs, (struct prefix *)&p);
1463 if (rn->info)
1464 {
1465 nbr = rn->info;
1466 nbr->nbr_nbma = nbr_nbma;
1467 nbr_nbma->nbr = nbr;
1468
1469 route_unlock_node (rn);
1470 }
1471 else
1472 {
1473 nbr = rn->info = ospf_nbr_new (oi);
1474 nbr->state = NSM_Down;
1475 nbr->src = nbr_nbma->addr;
1476 nbr->nbr_nbma = nbr_nbma;
1477 nbr->priority = nbr_nbma->priority;
1478 nbr->address = p;
1479
1480 nbr_nbma->nbr = nbr;
1481
1482 OSPF_NSM_EVENT_EXECUTE (nbr, NSM_Start);
1483 }
1484}
1485
1486void
paul68980082003-03-25 05:07:42 +00001487ospf_nbr_nbma_if_update (struct ospf *ospf, struct ospf_interface *oi)
paul718e3742002-12-13 20:15:29 +00001488{
1489 struct ospf_nbr_nbma *nbr_nbma;
1490 struct route_node *rn;
1491 struct prefix_ipv4 p;
1492
1493 if (oi->type != OSPF_IFTYPE_NBMA)
1494 return;
1495
paul68980082003-03-25 05:07:42 +00001496 for (rn = route_top (ospf->nbr_nbma); rn; rn = route_next (rn))
paul718e3742002-12-13 20:15:29 +00001497 if ((nbr_nbma = rn->info))
1498 if (nbr_nbma->oi == NULL && nbr_nbma->nbr == NULL)
1499 {
1500 p.family = AF_INET;
1501 p.prefix = nbr_nbma->addr;
1502 p.prefixlen = IPV4_MAX_BITLEN;
1503
1504 if (prefix_match (oi->address, (struct prefix *)&p))
1505 ospf_nbr_nbma_add (nbr_nbma, oi);
1506 }
1507}
1508
1509struct ospf_nbr_nbma *
1510ospf_nbr_nbma_lookup (struct ospf *ospf, struct in_addr nbr_addr)
1511{
1512 struct route_node *rn;
1513 struct prefix_ipv4 p;
1514
1515 p.family = AF_INET;
1516 p.prefix = nbr_addr;
1517 p.prefixlen = IPV4_MAX_BITLEN;
1518
1519 rn = route_node_lookup (ospf->nbr_nbma, (struct prefix *)&p);
1520 if (rn)
1521 {
1522 route_unlock_node (rn);
1523 return rn->info;
1524 }
1525 return NULL;
1526}
1527
1528struct ospf_nbr_nbma *
paul68980082003-03-25 05:07:42 +00001529ospf_nbr_nbma_lookup_next (struct ospf *ospf, struct in_addr *addr, int first)
paul718e3742002-12-13 20:15:29 +00001530{
1531#if 0
1532 struct ospf_nbr_nbma *nbr_nbma;
hasso52dc7ee2004-09-23 19:18:23 +00001533 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00001534#endif
1535
paul68980082003-03-25 05:07:42 +00001536 if (ospf == NULL)
paul718e3742002-12-13 20:15:29 +00001537 return NULL;
1538
1539#if 0
paul1eb8ef22005-04-07 07:30:20 +00001540 for (ALL_LIST_ELEMENTS_RO (ospf->nbr_nbma, node, nbr_nbma))
paul718e3742002-12-13 20:15:29 +00001541 {
paul718e3742002-12-13 20:15:29 +00001542 if (first)
1543 {
1544 *addr = nbr_nbma->addr;
1545 return nbr_nbma;
1546 }
1547 else if (ntohl (nbr_nbma->addr.s_addr) > ntohl (addr->s_addr))
1548 {
1549 *addr = nbr_nbma->addr;
1550 return nbr_nbma;
1551 }
1552 }
1553#endif
1554 return NULL;
1555}
1556
1557int
1558ospf_nbr_nbma_set (struct ospf *ospf, struct in_addr nbr_addr)
1559{
1560 struct ospf_nbr_nbma *nbr_nbma;
1561 struct ospf_interface *oi;
1562 struct prefix_ipv4 p;
1563 struct route_node *rn;
hasso52dc7ee2004-09-23 19:18:23 +00001564 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00001565
1566 nbr_nbma = ospf_nbr_nbma_lookup (ospf, nbr_addr);
1567 if (nbr_nbma)
1568 return 0;
1569
1570 nbr_nbma = ospf_nbr_nbma_new ();
1571 nbr_nbma->addr = nbr_addr;
1572
1573 p.family = AF_INET;
1574 p.prefix = nbr_addr;
1575 p.prefixlen = IPV4_MAX_BITLEN;
1576
1577 rn = route_node_get (ospf->nbr_nbma, (struct prefix *)&p);
1578 rn->info = nbr_nbma;
1579
paul1eb8ef22005-04-07 07:30:20 +00001580 for (ALL_LIST_ELEMENTS_RO (ospf->oiflist, node, oi))
paul718e3742002-12-13 20:15:29 +00001581 {
paul718e3742002-12-13 20:15:29 +00001582 if (oi->type == OSPF_IFTYPE_NBMA)
1583 if (prefix_match (oi->address, (struct prefix *)&p))
1584 {
1585 ospf_nbr_nbma_add (nbr_nbma, oi);
1586 break;
1587 }
1588 }
1589
1590 return 1;
1591}
1592
1593int
1594ospf_nbr_nbma_unset (struct ospf *ospf, struct in_addr nbr_addr)
1595{
1596 struct ospf_nbr_nbma *nbr_nbma;
1597
1598 nbr_nbma = ospf_nbr_nbma_lookup (ospf, nbr_addr);
1599 if (nbr_nbma == NULL)
1600 return 0;
1601
1602 ospf_nbr_nbma_down (nbr_nbma);
1603 ospf_nbr_nbma_delete (ospf, nbr_nbma);
1604
1605 return 1;
1606}
1607
1608int
1609ospf_nbr_nbma_priority_set (struct ospf *ospf, struct in_addr nbr_addr,
1610 u_char priority)
1611{
1612 struct ospf_nbr_nbma *nbr_nbma;
1613
1614 nbr_nbma = ospf_nbr_nbma_lookup (ospf, nbr_addr);
1615 if (nbr_nbma == NULL)
1616 return 0;
1617
1618 if (nbr_nbma->priority != priority)
1619 nbr_nbma->priority = priority;
1620
1621 return 1;
1622}
1623
1624int
1625ospf_nbr_nbma_priority_unset (struct ospf *ospf, struct in_addr nbr_addr)
1626{
1627 struct ospf_nbr_nbma *nbr_nbma;
1628
1629 nbr_nbma = ospf_nbr_nbma_lookup (ospf, nbr_addr);
1630 if (nbr_nbma == NULL)
1631 return 0;
1632
1633 if (nbr_nbma != OSPF_NEIGHBOR_PRIORITY_DEFAULT)
1634 nbr_nbma->priority = OSPF_NEIGHBOR_PRIORITY_DEFAULT;
1635
1636 return 1;
1637}
1638
1639int
1640ospf_nbr_nbma_poll_interval_set (struct ospf *ospf, struct in_addr nbr_addr,
paul6c835672004-10-11 11:00:30 +00001641 unsigned int interval)
paul718e3742002-12-13 20:15:29 +00001642{
1643 struct ospf_nbr_nbma *nbr_nbma;
1644
1645 nbr_nbma = ospf_nbr_nbma_lookup (ospf, nbr_addr);
1646 if (nbr_nbma == NULL)
1647 return 0;
1648
1649 if (nbr_nbma->v_poll != interval)
1650 {
1651 nbr_nbma->v_poll = interval;
1652 if (nbr_nbma->oi && ospf_if_is_up (nbr_nbma->oi))
1653 {
1654 OSPF_TIMER_OFF (nbr_nbma->t_poll);
1655 OSPF_POLL_TIMER_ON (nbr_nbma->t_poll, ospf_poll_timer,
1656 nbr_nbma->v_poll);
1657 }
1658 }
1659
1660 return 1;
1661}
1662
1663int
1664ospf_nbr_nbma_poll_interval_unset (struct ospf *ospf, struct in_addr addr)
1665{
1666 struct ospf_nbr_nbma *nbr_nbma;
1667
1668 nbr_nbma = ospf_nbr_nbma_lookup (ospf, addr);
1669 if (nbr_nbma == NULL)
1670 return 0;
1671
1672 if (nbr_nbma->v_poll != OSPF_POLL_INTERVAL_DEFAULT)
1673 nbr_nbma->v_poll = OSPF_POLL_INTERVAL_DEFAULT;
1674
1675 return 1;
1676}
1677
paul718e3742002-12-13 20:15:29 +00001678void
paul020709f2003-04-04 02:44:16 +00001679ospf_master_init ()
1680{
1681 memset (&ospf_master, 0, sizeof (struct ospf_master));
1682
1683 om = &ospf_master;
1684 om->ospf = list_new ();
1685 om->master = thread_master_create ();
Paul Jakma2518efd2006-08-27 06:49:29 +00001686 om->start_time = quagga_time (NULL);
paul020709f2003-04-04 02:44:16 +00001687}