blob: 7db81cea7089d9a2d5b54a608a417a3e6e901d93 [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 *);
Joakim Tjernlunda49eb302008-09-02 19:06:31 +010071static void ospf_network_run (struct prefix *, struct ospf_area *);
72static void ospf_network_run_interface (struct prefix *, struct ospf_area *,
73 struct interface *);
Stephen Hemminger917e2992009-12-03 19:07:00 +030074static int ospf_network_match_iface (const struct connected *,
75 const struct prefix *);
paul88d6cf32005-10-29 12:50:09 +000076static void ospf_finish_final (struct ospf *);
paul718e3742002-12-13 20:15:29 +000077
paul718e3742002-12-13 20:15:29 +000078#define OSPF_EXTERNAL_LSA_ORIGINATE_DELAY 1
paul88d6cf32005-10-29 12:50:09 +000079
paul718e3742002-12-13 20:15:29 +000080void
paul68980082003-03-25 05:07:42 +000081ospf_router_id_update (struct ospf *ospf)
paul718e3742002-12-13 20:15:29 +000082{
paul718e3742002-12-13 20:15:29 +000083 struct in_addr router_id, router_id_old;
paul1eb8ef22005-04-07 07:30:20 +000084 struct ospf_interface *oi;
Joakim Tjernlunda49eb302008-09-02 19:06:31 +010085 struct interface *ifp;
hasso52dc7ee2004-09-23 19:18:23 +000086 struct listnode *node;
paul718e3742002-12-13 20:15:29 +000087
88 if (IS_DEBUG_OSPF_EVENT)
ajs9b0e25c2004-12-08 19:06:51 +000089 zlog_debug ("Router-ID[OLD:%s]: Update", inet_ntoa (ospf->router_id));
paul718e3742002-12-13 20:15:29 +000090
paul68980082003-03-25 05:07:42 +000091 router_id_old = ospf->router_id;
paul718e3742002-12-13 20:15:29 +000092
Andrew J. Schorr16700082006-07-27 22:29:06 +000093 /* Select the router ID based on these priorities:
94 1. Statically assigned router ID is always the first choice.
95 2. If there is no statically assigned router ID, then try to stick
96 with the most recent value, since changing router ID's is very
97 disruptive.
98 3. Last choice: just go with whatever the zebra daemon recommends.
99 */
paul68980082003-03-25 05:07:42 +0000100 if (ospf->router_id_static.s_addr != 0)
101 router_id = ospf->router_id_static;
Andrew J. Schorr16700082006-07-27 22:29:06 +0000102 else if (ospf->router_id.s_addr != 0)
103 router_id = ospf->router_id;
paul718e3742002-12-13 20:15:29 +0000104 else
hasso18a6dce2004-10-03 18:18:34 +0000105 router_id = router_id_zebra;
paul718e3742002-12-13 20:15:29 +0000106
paul68980082003-03-25 05:07:42 +0000107 ospf->router_id = router_id;
paul718e3742002-12-13 20:15:29 +0000108
109 if (IS_DEBUG_OSPF_EVENT)
ajs9b0e25c2004-12-08 19:06:51 +0000110 zlog_debug ("Router-ID[NEW:%s]: Update", inet_ntoa (ospf->router_id));
paul718e3742002-12-13 20:15:29 +0000111
112 if (!IPV4_ADDR_SAME (&router_id_old, &router_id))
113 {
paul1eb8ef22005-04-07 07:30:20 +0000114 for (ALL_LIST_ELEMENTS_RO (ospf->oiflist, node, oi))
115 /* Update self-neighbor's router_id. */
116 oi->nbr_self->router_id = router_id;
paul718e3742002-12-13 20:15:29 +0000117
118 /* If AS-external-LSA is queued, then flush those LSAs. */
paul68980082003-03-25 05:07:42 +0000119 if (router_id_old.s_addr == 0 && ospf->external_origin)
paul718e3742002-12-13 20:15:29 +0000120 {
121 int type;
122 /* Originate each redistributed external route. */
123 for (type = 0; type < ZEBRA_ROUTE_MAX; type++)
paul68980082003-03-25 05:07:42 +0000124 if (ospf->external_origin & (1 << type))
paul718e3742002-12-13 20:15:29 +0000125 thread_add_event (master, ospf_external_lsa_originate_timer,
paul68980082003-03-25 05:07:42 +0000126 ospf, type);
paul718e3742002-12-13 20:15:29 +0000127 /* Originate Deafult. */
paul68980082003-03-25 05:07:42 +0000128 if (ospf->external_origin & (1 << ZEBRA_ROUTE_MAX))
Paul Jakma4021b602006-05-12 22:55:41 +0000129 thread_add_event (master, ospf_default_originate_timer, ospf, 0);
paul718e3742002-12-13 20:15:29 +0000130
paul68980082003-03-25 05:07:42 +0000131 ospf->external_origin = 0;
paul718e3742002-12-13 20:15:29 +0000132 }
133
Paul Jakmac363d382010-01-24 22:42:13 +0000134 /* update router-lsa's for each area */
135 ospf_router_lsa_update (ospf);
paulb29800a2005-11-20 14:50:45 +0000136
137 /* update ospf_interface's */
Joakim Tjernlunda49eb302008-09-02 19:06:31 +0100138 for (ALL_LIST_ELEMENTS_RO (om->iflist, node, ifp))
139 ospf_if_update (ospf, ifp);
paul718e3742002-12-13 20:15:29 +0000140 }
141}
paul718e3742002-12-13 20:15:29 +0000142
143/* For OSPF area sort by area id. */
paul4dadc292005-05-06 21:37:42 +0000144static int
paul718e3742002-12-13 20:15:29 +0000145ospf_area_id_cmp (struct ospf_area *a1, struct ospf_area *a2)
146{
147 if (ntohl (a1->area_id.s_addr) > ntohl (a2->area_id.s_addr))
148 return 1;
149 if (ntohl (a1->area_id.s_addr) < ntohl (a2->area_id.s_addr))
150 return -1;
151 return 0;
152}
153
154/* Allocate new ospf structure. */
paul4dadc292005-05-06 21:37:42 +0000155static struct ospf *
156ospf_new (void)
paul718e3742002-12-13 20:15:29 +0000157{
158 int i;
159
160 struct ospf *new = XCALLOC (MTYPE_OSPF_TOP, sizeof (struct ospf));
161
162 new->router_id.s_addr = htonl (0);
163 new->router_id_static.s_addr = htonl (0);
164
pauld57834f2005-07-12 20:04:22 +0000165 new->abr_type = OSPF_ABR_DEFAULT;
paul718e3742002-12-13 20:15:29 +0000166 new->oiflist = list_new ();
167 new->vlinks = list_new ();
168 new->areas = list_new ();
169 new->areas->cmp = (int (*)(void *, void *)) ospf_area_id_cmp;
170 new->networks = route_table_init ();
171 new->nbr_nbma = route_table_init ();
172
173 new->lsdb = ospf_lsdb_new ();
174
175 new->default_originate = DEFAULT_ORIGINATE_NONE;
176
Paul Jakma7ffa8fa2006-10-22 20:07:53 +0000177 new->passive_interface_default = OSPF_IF_ACTIVE;
178
paul718e3742002-12-13 20:15:29 +0000179 new->new_external_route = route_table_init ();
180 new->old_external_route = route_table_init ();
181 new->external_lsas = route_table_init ();
paul88d6cf32005-10-29 12:50:09 +0000182
183 new->stub_router_startup_time = OSPF_STUB_ROUTER_UNCONFIGURED;
paul31a59762005-11-14 11:11:11 +0000184 new->stub_router_shutdown_time = OSPF_STUB_ROUTER_UNCONFIGURED;
paul88d6cf32005-10-29 12:50:09 +0000185
paul718e3742002-12-13 20:15:29 +0000186 /* Distribute parameter init. */
187 for (i = 0; i <= ZEBRA_ROUTE_MAX; i++)
188 {
189 new->dmetric[i].type = -1;
190 new->dmetric[i].value = -1;
191 }
192 new->default_metric = -1;
193 new->ref_bandwidth = OSPF_DEFAULT_REF_BANDWIDTH;
194
195 /* SPF timer value init. */
196 new->spf_delay = OSPF_SPF_DELAY_DEFAULT;
197 new->spf_holdtime = OSPF_SPF_HOLDTIME_DEFAULT;
pauld24f6e22005-10-21 09:23:12 +0000198 new->spf_max_holdtime = OSPF_SPF_MAX_HOLDTIME_DEFAULT;
199 new->spf_hold_multiplier = 1;
paul718e3742002-12-13 20:15:29 +0000200
201 /* MaxAge init. */
202 new->maxage_lsa = list_new ();
203 new->t_maxage_walker =
204 thread_add_timer (master, ospf_lsa_maxage_walker,
paul68980082003-03-25 05:07:42 +0000205 new, OSPF_LSA_MAXAGE_CHECK_INTERVAL);
paul718e3742002-12-13 20:15:29 +0000206
207 /* Distance table init. */
208 new->distance_table = route_table_init ();
209
210 new->lsa_refresh_queue.index = 0;
211 new->lsa_refresh_interval = OSPF_LSA_REFRESH_INTERVAL_DEFAULT;
212 new->t_lsa_refresher = thread_add_timer (master, ospf_lsa_refresh_walker,
213 new, new->lsa_refresh_interval);
Paul Jakma2518efd2006-08-27 06:49:29 +0000214 new->lsa_refresher_started = quagga_time (NULL);
paul718e3742002-12-13 20:15:29 +0000215
ajs5c333492005-02-23 15:43:01 +0000216 if ((new->fd = ospf_sock_init()) < 0)
217 {
218 zlog_err("ospf_new: fatal error: ospf_sock_init was unable to open "
219 "a socket");
220 exit(1);
221 }
Denis Ovsienkof102e752007-09-18 09:01:13 +0000222 new->maxsndbuflen = getsockopt_so_sendbuf (new->fd);
223 if (IS_DEBUG_OSPF (zebra, ZEBRA_INTERFACE))
224 zlog_debug ("%s: starting with OSPF send buffer size %d",
225 __func__, new->maxsndbuflen);
ajs5c333492005-02-23 15:43:01 +0000226 if ((new->ibuf = stream_new(OSPF_MAX_PACKET_SIZE+1)) == NULL)
227 {
228 zlog_err("ospf_new: fatal error: stream_new(%u) failed allocating ibuf",
229 OSPF_MAX_PACKET_SIZE+1);
230 exit(1);
231 }
232 new->t_read = thread_add_read (master, ospf_read, new, new->fd);
paul718e3742002-12-13 20:15:29 +0000233 new->oi_write_q = list_new ();
234
235 return new;
236}
237
238struct ospf *
paul020709f2003-04-04 02:44:16 +0000239ospf_lookup ()
240{
241 if (listcount (om->ospf) == 0)
242 return NULL;
243
paul1eb8ef22005-04-07 07:30:20 +0000244 return listgetdata (listhead (om->ospf));
paul020709f2003-04-04 02:44:16 +0000245}
246
paul4dadc292005-05-06 21:37:42 +0000247static void
paul020709f2003-04-04 02:44:16 +0000248ospf_add (struct ospf *ospf)
249{
250 listnode_add (om->ospf, ospf);
251}
252
paul4dadc292005-05-06 21:37:42 +0000253static void
paul020709f2003-04-04 02:44:16 +0000254ospf_delete (struct ospf *ospf)
255{
256 listnode_delete (om->ospf, ospf);
257}
258
259struct ospf *
paul718e3742002-12-13 20:15:29 +0000260ospf_get ()
261{
paul020709f2003-04-04 02:44:16 +0000262 struct ospf *ospf;
paul718e3742002-12-13 20:15:29 +0000263
paul020709f2003-04-04 02:44:16 +0000264 ospf = ospf_lookup ();
265 if (ospf == NULL)
266 {
267 ospf = ospf_new ();
268 ospf_add (ospf);
paul718e3742002-12-13 20:15:29 +0000269
paul020709f2003-04-04 02:44:16 +0000270 if (ospf->router_id_static.s_addr == 0)
271 ospf_router_id_update (ospf);
paul718e3742002-12-13 20:15:29 +0000272
273#ifdef HAVE_OPAQUE_LSA
paul020709f2003-04-04 02:44:16 +0000274 ospf_opaque_type11_lsa_init (ospf);
paul718e3742002-12-13 20:15:29 +0000275#endif /* HAVE_OPAQUE_LSA */
paul020709f2003-04-04 02:44:16 +0000276 }
paul68980082003-03-25 05:07:42 +0000277
278 return ospf;
paul718e3742002-12-13 20:15:29 +0000279}
paul88d6cf32005-10-29 12:50:09 +0000280
paulc9c93d52005-11-26 13:31:11 +0000281/* Handle the second half of deferred shutdown. This is called either
282 * from the deferred-shutdown timer thread, or directly through
283 * ospf_deferred_shutdown_check.
paul88d6cf32005-10-29 12:50:09 +0000284 *
285 * Function is to cleanup G-R state, if required then call ospf_finish_final
286 * to complete shutdown of this ospf instance. Possibly exit if the
287 * whole process is being shutdown and this was the last OSPF instance.
288 */
289static void
paulc9c93d52005-11-26 13:31:11 +0000290ospf_deferred_shutdown_finish (struct ospf *ospf)
paul88d6cf32005-10-29 12:50:09 +0000291{
292 ospf->stub_router_shutdown_time = OSPF_STUB_ROUTER_UNCONFIGURED;
paulc9c93d52005-11-26 13:31:11 +0000293 OSPF_TIMER_OFF (ospf->t_deferred_shutdown);
paul88d6cf32005-10-29 12:50:09 +0000294
295 ospf_finish_final (ospf);
296
297 /* *ospf is now invalid */
298
299 /* ospfd being shut-down? If so, was this the last ospf instance? */
300 if (CHECK_FLAG (om->options, OSPF_MASTER_SHUTDOWN)
301 && (listcount (om->ospf) == 0))
302 exit (0);
303
304 return;
305}
306
307/* Timer thread for G-R */
308static int
paulc9c93d52005-11-26 13:31:11 +0000309ospf_deferred_shutdown_timer (struct thread *t)
paul88d6cf32005-10-29 12:50:09 +0000310{
311 struct ospf *ospf = THREAD_ARG(t);
312
paulc9c93d52005-11-26 13:31:11 +0000313 ospf_deferred_shutdown_finish (ospf);
paul88d6cf32005-10-29 12:50:09 +0000314
315 return 0;
316}
317
paulc9c93d52005-11-26 13:31:11 +0000318/* Check whether deferred-shutdown must be scheduled, otherwise call
paul88d6cf32005-10-29 12:50:09 +0000319 * down directly into second-half of instance shutdown.
320 */
321static void
paulc9c93d52005-11-26 13:31:11 +0000322ospf_deferred_shutdown_check (struct ospf *ospf)
paul88d6cf32005-10-29 12:50:09 +0000323{
324 unsigned long timeout;
325 struct listnode *ln;
326 struct ospf_area *area;
327
paulc9c93d52005-11-26 13:31:11 +0000328 /* deferred shutdown already running? */
329 if (ospf->t_deferred_shutdown)
paul88d6cf32005-10-29 12:50:09 +0000330 return;
331
332 /* Should we try push out max-metric LSAs? */
333 if (ospf->stub_router_shutdown_time != OSPF_STUB_ROUTER_UNCONFIGURED)
334 {
335 for (ALL_LIST_ELEMENTS_RO (ospf->areas, ln, area))
336 {
337 SET_FLAG (area->stub_router_state, OSPF_AREA_ADMIN_STUB_ROUTED);
338
339 if (!CHECK_FLAG (area->stub_router_state, OSPF_AREA_IS_STUB_ROUTED))
Paul Jakmac363d382010-01-24 22:42:13 +0000340 ospf_router_lsa_update_area (area);
paul88d6cf32005-10-29 12:50:09 +0000341 }
342 timeout = ospf->stub_router_shutdown_time;
343 }
344 else
paulc9c93d52005-11-26 13:31:11 +0000345 {
346 /* No timer needed */
347 ospf_deferred_shutdown_finish (ospf);
348 return;
349 }
paul88d6cf32005-10-29 12:50:09 +0000350
paulc9c93d52005-11-26 13:31:11 +0000351 OSPF_TIMER_ON (ospf->t_deferred_shutdown, ospf_deferred_shutdown_timer,
paul88d6cf32005-10-29 12:50:09 +0000352 timeout);
353 return;
354}
355
356/* Shut down the entire process */
357void
358ospf_terminate (void)
359{
360 struct ospf *ospf;
361 struct listnode *node, *nnode;
362
363 /* shutdown already in progress */
364 if (CHECK_FLAG (om->options, OSPF_MASTER_SHUTDOWN))
365 return;
366
367 SET_FLAG (om->options, OSPF_MASTER_SHUTDOWN);
368
Andrew J. Schorr4056a542007-02-27 13:55:46 +0000369 /* exit immediately if OSPF not actually running */
370 if (listcount(om->ospf) == 0)
371 exit(0);
372
paul88d6cf32005-10-29 12:50:09 +0000373 for (ALL_LIST_ELEMENTS (om->ospf, node, nnode, ospf))
374 ospf_finish (ospf);
375
376 /* Deliberately go back up, hopefully to thread scheduler, as
377 * One or more ospf_finish()'s may have deferred shutdown to a timer
378 * thread
379 */
380}
paul718e3742002-12-13 20:15:29 +0000381
382void
383ospf_finish (struct ospf *ospf)
384{
paulc9c93d52005-11-26 13:31:11 +0000385 /* let deferred shutdown decide */
386 ospf_deferred_shutdown_check (ospf);
paul88d6cf32005-10-29 12:50:09 +0000387
paulc9c93d52005-11-26 13:31:11 +0000388 /* if ospf_deferred_shutdown returns, then ospf_finish_final is
paul88d6cf32005-10-29 12:50:09 +0000389 * deferred to expiry of G-S timer thread. Return back up, hopefully
390 * to thread scheduler.
391 */
paulc9c93d52005-11-26 13:31:11 +0000392 return;
paul88d6cf32005-10-29 12:50:09 +0000393}
394
395/* Final cleanup of ospf instance */
396static void
397ospf_finish_final (struct ospf *ospf)
398{
paul718e3742002-12-13 20:15:29 +0000399 struct route_node *rn;
400 struct ospf_nbr_nbma *nbr_nbma;
paul68980082003-03-25 05:07:42 +0000401 struct ospf_lsa *lsa;
paul1eb8ef22005-04-07 07:30:20 +0000402 struct ospf_interface *oi;
403 struct ospf_area *area;
404 struct ospf_vl_data *vl_data;
405 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000406 int i;
407
408#ifdef HAVE_OPAQUE_LSA
409 ospf_opaque_type11_lsa_term (ospf);
410#endif /* HAVE_OPAQUE_LSA */
paul88d6cf32005-10-29 12:50:09 +0000411
412 /* be nice if this worked, but it doesn't */
413 /*ospf_flush_self_originated_lsas_now (ospf);*/
414
415 /* Unregister redistribution */
paul718e3742002-12-13 20:15:29 +0000416 for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
paul020709f2003-04-04 02:44:16 +0000417 ospf_redistribute_unset (ospf, i);
Paul Jakma29b5a042006-08-27 08:01:20 +0000418 ospf_redistribute_default_unset (ospf);
paul718e3742002-12-13 20:15:29 +0000419
paul1eb8ef22005-04-07 07:30:20 +0000420 for (ALL_LIST_ELEMENTS (ospf->areas, node, nnode, area))
421 ospf_remove_vls_through_area (ospf, area);
paul718e3742002-12-13 20:15:29 +0000422
paul1eb8ef22005-04-07 07:30:20 +0000423 for (ALL_LIST_ELEMENTS (ospf->vlinks, node, nnode, vl_data))
424 ospf_vl_delete (ospf, vl_data);
paul718e3742002-12-13 20:15:29 +0000425
426 list_delete (ospf->vlinks);
427
428 /* Reset interface. */
paul1eb8ef22005-04-07 07:30:20 +0000429 for (ALL_LIST_ELEMENTS (ospf->oiflist, node, nnode, oi))
430 ospf_if_free (oi);
paul718e3742002-12-13 20:15:29 +0000431
432 /* Clear static neighbors */
433 for (rn = route_top (ospf->nbr_nbma); rn; rn = route_next (rn))
434 if ((nbr_nbma = rn->info))
435 {
436 OSPF_POLL_TIMER_OFF (nbr_nbma->t_poll);
437
438 if (nbr_nbma->nbr)
439 {
440 nbr_nbma->nbr->nbr_nbma = NULL;
441 nbr_nbma->nbr = NULL;
442 }
443
444 if (nbr_nbma->oi)
445 {
446 listnode_delete (nbr_nbma->oi->nbr_nbma, nbr_nbma);
447 nbr_nbma->oi = NULL;
448 }
449
450 XFREE (MTYPE_OSPF_NEIGHBOR_STATIC, nbr_nbma);
451 }
452
453 route_table_finish (ospf->nbr_nbma);
454
455 /* Clear networks and Areas. */
456 for (rn = route_top (ospf->networks); rn; rn = route_next (rn))
457 {
458 struct ospf_network *network;
459
460 if ((network = rn->info) != NULL)
461 {
paul68980082003-03-25 05:07:42 +0000462 ospf_network_free (ospf, network);
paul718e3742002-12-13 20:15:29 +0000463 rn->info = NULL;
464 route_unlock_node (rn);
465 }
466 }
467
paul1eb8ef22005-04-07 07:30:20 +0000468 for (ALL_LIST_ELEMENTS (ospf->areas, node, nnode, area))
paul718e3742002-12-13 20:15:29 +0000469 {
paul718e3742002-12-13 20:15:29 +0000470 listnode_delete (ospf->areas, area);
471 ospf_area_free (area);
472 }
473
474 /* Cancel all timers. */
475 OSPF_TIMER_OFF (ospf->t_external_lsa);
paul718e3742002-12-13 20:15:29 +0000476 OSPF_TIMER_OFF (ospf->t_spf_calc);
477 OSPF_TIMER_OFF (ospf->t_ase_calc);
478 OSPF_TIMER_OFF (ospf->t_maxage);
479 OSPF_TIMER_OFF (ospf->t_maxage_walker);
480 OSPF_TIMER_OFF (ospf->t_abr_task);
paul88d6cf32005-10-29 12:50:09 +0000481 OSPF_TIMER_OFF (ospf->t_asbr_check);
paul718e3742002-12-13 20:15:29 +0000482 OSPF_TIMER_OFF (ospf->t_distribute_update);
483 OSPF_TIMER_OFF (ospf->t_lsa_refresher);
484 OSPF_TIMER_OFF (ospf->t_read);
485 OSPF_TIMER_OFF (ospf->t_write);
paul31a59762005-11-14 11:11:11 +0000486#ifdef HAVE_OPAQUE_LSA
paul88d6cf32005-10-29 12:50:09 +0000487 OSPF_TIMER_OFF (ospf->t_opaque_lsa_self);
paul31a59762005-11-14 11:11:11 +0000488#endif
paul718e3742002-12-13 20:15:29 +0000489
490 close (ospf->fd);
ajs5c333492005-02-23 15:43:01 +0000491 stream_free(ospf->ibuf);
paul718e3742002-12-13 20:15:29 +0000492
493#ifdef HAVE_OPAQUE_LSA
paul68980082003-03-25 05:07:42 +0000494 LSDB_LOOP (OPAQUE_AS_LSDB (ospf), rn, lsa)
495 ospf_discard_from_db (ospf, ospf->lsdb, lsa);
paul718e3742002-12-13 20:15:29 +0000496#endif /* HAVE_OPAQUE_LSA */
paul68980082003-03-25 05:07:42 +0000497 LSDB_LOOP (EXTERNAL_LSDB (ospf), rn, lsa)
498 ospf_discard_from_db (ospf, ospf->lsdb, lsa);
499
paul718e3742002-12-13 20:15:29 +0000500 ospf_lsdb_delete_all (ospf->lsdb);
501 ospf_lsdb_free (ospf->lsdb);
502
paul1eb8ef22005-04-07 07:30:20 +0000503 for (ALL_LIST_ELEMENTS (ospf->maxage_lsa, node, nnode, lsa))
Paul Jakma1fe6ed32006-07-26 09:37:26 +0000504 ospf_lsa_unlock (&lsa); /* maxage_lsa */
paul718e3742002-12-13 20:15:29 +0000505
506 list_delete (ospf->maxage_lsa);
507
508 if (ospf->old_table)
509 ospf_route_table_free (ospf->old_table);
510 if (ospf->new_table)
511 {
512 ospf_route_delete (ospf->new_table);
513 ospf_route_table_free (ospf->new_table);
514 }
515 if (ospf->old_rtrs)
516 ospf_rtrs_free (ospf->old_rtrs);
517 if (ospf->new_rtrs)
518 ospf_rtrs_free (ospf->new_rtrs);
519 if (ospf->new_external_route)
520 {
521 ospf_route_delete (ospf->new_external_route);
522 ospf_route_table_free (ospf->new_external_route);
523 }
524 if (ospf->old_external_route)
525 {
526 ospf_route_delete (ospf->old_external_route);
527 ospf_route_table_free (ospf->old_external_route);
528 }
529 if (ospf->external_lsas)
530 {
531 ospf_ase_external_lsas_finish (ospf->external_lsas);
532 }
533
534 list_delete (ospf->areas);
535
536 for (i = ZEBRA_ROUTE_SYSTEM; i <= ZEBRA_ROUTE_MAX; i++)
537 if (EXTERNAL_INFO (i) != NULL)
538 for (rn = route_top (EXTERNAL_INFO (i)); rn; rn = route_next (rn))
539 {
540 if (rn->info == NULL)
541 continue;
542
543 XFREE (MTYPE_OSPF_EXTERNAL_INFO, rn->info);
544 rn->info = NULL;
545 route_unlock_node (rn);
546 }
547
paul68980082003-03-25 05:07:42 +0000548 ospf_distance_reset (ospf);
paul718e3742002-12-13 20:15:29 +0000549 route_table_finish (ospf->distance_table);
550
paul020709f2003-04-04 02:44:16 +0000551 ospf_delete (ospf);
paul718e3742002-12-13 20:15:29 +0000552
paul020709f2003-04-04 02:44:16 +0000553 XFREE (MTYPE_OSPF_TOP, ospf);
paul718e3742002-12-13 20:15:29 +0000554}
555
556
557/* allocate new OSPF Area object */
paul4dadc292005-05-06 21:37:42 +0000558static struct ospf_area *
paul68980082003-03-25 05:07:42 +0000559ospf_area_new (struct ospf *ospf, struct in_addr area_id)
paul718e3742002-12-13 20:15:29 +0000560{
561 struct ospf_area *new;
562
563 /* Allocate new config_network. */
564 new = XCALLOC (MTYPE_OSPF_AREA, sizeof (struct ospf_area));
565
paul68980082003-03-25 05:07:42 +0000566 new->ospf = ospf;
paul718e3742002-12-13 20:15:29 +0000567
568 new->area_id = area_id;
569
570 new->external_routing = OSPF_AREA_DEFAULT;
571 new->default_cost = 1;
572 new->auth_type = OSPF_AUTH_NULL;
paul88d6cf32005-10-29 12:50:09 +0000573
paul718e3742002-12-13 20:15:29 +0000574 /* New LSDB init. */
575 new->lsdb = ospf_lsdb_new ();
576
577 /* Self-originated LSAs initialize. */
578 new->router_lsa_self = NULL;
579
580#ifdef HAVE_OPAQUE_LSA
581 ospf_opaque_type10_lsa_init (new);
582#endif /* HAVE_OPAQUE_LSA */
583
584 new->oiflist = list_new ();
585 new->ranges = route_table_init ();
586
587 if (area_id.s_addr == OSPF_AREA_BACKBONE)
paul68980082003-03-25 05:07:42 +0000588 ospf->backbone = new;
paul718e3742002-12-13 20:15:29 +0000589
590 return new;
591}
592
Stephen Hemminger917e2992009-12-03 19:07:00 +0300593static void
paul718e3742002-12-13 20:15:29 +0000594ospf_area_free (struct ospf_area *area)
595{
paul68980082003-03-25 05:07:42 +0000596 struct route_node *rn;
597 struct ospf_lsa *lsa;
598
paul718e3742002-12-13 20:15:29 +0000599 /* Free LSDBs. */
paul68980082003-03-25 05:07:42 +0000600 LSDB_LOOP (ROUTER_LSDB (area), rn, lsa)
601 ospf_discard_from_db (area->ospf, area->lsdb, lsa);
602 LSDB_LOOP (NETWORK_LSDB (area), rn, lsa)
603 ospf_discard_from_db (area->ospf, area->lsdb, lsa);
604 LSDB_LOOP (SUMMARY_LSDB (area), rn, lsa)
605 ospf_discard_from_db (area->ospf, area->lsdb, lsa);
606 LSDB_LOOP (ASBR_SUMMARY_LSDB (area), rn, lsa)
607 ospf_discard_from_db (area->ospf, area->lsdb, lsa);
paul718e3742002-12-13 20:15:29 +0000608
paul68980082003-03-25 05:07:42 +0000609 LSDB_LOOP (NSSA_LSDB (area), rn, lsa)
610 ospf_discard_from_db (area->ospf, area->lsdb, lsa);
paul718e3742002-12-13 20:15:29 +0000611#ifdef HAVE_OPAQUE_LSA
paul68980082003-03-25 05:07:42 +0000612 LSDB_LOOP (OPAQUE_AREA_LSDB (area), rn, lsa)
613 ospf_discard_from_db (area->ospf, area->lsdb, lsa);
614 LSDB_LOOP (OPAQUE_LINK_LSDB (area), rn, lsa)
615 ospf_discard_from_db (area->ospf, area->lsdb, lsa);
paul718e3742002-12-13 20:15:29 +0000616#endif /* HAVE_OPAQUE_LSA */
617
618 ospf_lsdb_delete_all (area->lsdb);
619 ospf_lsdb_free (area->lsdb);
620
Paul Jakma1fe6ed32006-07-26 09:37:26 +0000621 ospf_lsa_unlock (&area->router_lsa_self);
paul718e3742002-12-13 20:15:29 +0000622
623 route_table_finish (area->ranges);
624 list_delete (area->oiflist);
625
626 if (EXPORT_NAME (area))
627 free (EXPORT_NAME (area));
628
629 if (IMPORT_NAME (area))
630 free (IMPORT_NAME (area));
631
632 /* Cancel timer. */
paul88d6cf32005-10-29 12:50:09 +0000633 OSPF_TIMER_OFF (area->t_stub_router);
634#ifdef HAVE_OPAQUE_LSA
635 OSPF_TIMER_OFF (area->t_opaque_lsa_self);
636#endif /* HAVE_OPAQUE_LSA */
637
paul718e3742002-12-13 20:15:29 +0000638 if (OSPF_IS_AREA_BACKBONE (area))
paul68980082003-03-25 05:07:42 +0000639 area->ospf->backbone = NULL;
paul718e3742002-12-13 20:15:29 +0000640
641 XFREE (MTYPE_OSPF_AREA, area);
642}
643
644void
paul68980082003-03-25 05:07:42 +0000645ospf_area_check_free (struct ospf *ospf, struct in_addr area_id)
paul718e3742002-12-13 20:15:29 +0000646{
647 struct ospf_area *area;
648
paul68980082003-03-25 05:07:42 +0000649 area = ospf_area_lookup_by_area_id (ospf, area_id);
paul718e3742002-12-13 20:15:29 +0000650 if (area &&
651 listcount (area->oiflist) == 0 &&
652 area->ranges->top == NULL &&
653 area->shortcut_configured == OSPF_SHORTCUT_DEFAULT &&
654 area->external_routing == OSPF_AREA_DEFAULT &&
655 area->no_summary == 0 &&
656 area->default_cost == 1 &&
657 EXPORT_NAME (area) == NULL &&
658 IMPORT_NAME (area) == NULL &&
659 area->auth_type == OSPF_AUTH_NULL)
660 {
paul68980082003-03-25 05:07:42 +0000661 listnode_delete (ospf->areas, area);
paul718e3742002-12-13 20:15:29 +0000662 ospf_area_free (area);
663 }
664}
665
666struct ospf_area *
paul68980082003-03-25 05:07:42 +0000667ospf_area_get (struct ospf *ospf, struct in_addr area_id, int format)
paul718e3742002-12-13 20:15:29 +0000668{
669 struct ospf_area *area;
670
paul68980082003-03-25 05:07:42 +0000671 area = ospf_area_lookup_by_area_id (ospf, area_id);
paul718e3742002-12-13 20:15:29 +0000672 if (!area)
673 {
paul68980082003-03-25 05:07:42 +0000674 area = ospf_area_new (ospf, area_id);
paul718e3742002-12-13 20:15:29 +0000675 area->format = format;
paul68980082003-03-25 05:07:42 +0000676 listnode_add_sort (ospf->areas, area);
677 ospf_check_abr_status (ospf);
paul718e3742002-12-13 20:15:29 +0000678 }
679
680 return area;
681}
682
683struct ospf_area *
paul68980082003-03-25 05:07:42 +0000684ospf_area_lookup_by_area_id (struct ospf *ospf, struct in_addr area_id)
paul718e3742002-12-13 20:15:29 +0000685{
686 struct ospf_area *area;
hasso52dc7ee2004-09-23 19:18:23 +0000687 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000688
paul1eb8ef22005-04-07 07:30:20 +0000689 for (ALL_LIST_ELEMENTS_RO (ospf->areas, node, area))
690 if (IPV4_ADDR_SAME (&area->area_id, &area_id))
691 return area;
paul718e3742002-12-13 20:15:29 +0000692
693 return NULL;
694}
695
696void
697ospf_area_add_if (struct ospf_area *area, struct ospf_interface *oi)
698{
699 listnode_add (area->oiflist, oi);
700}
701
702void
703ospf_area_del_if (struct ospf_area *area, struct ospf_interface *oi)
704{
705 listnode_delete (area->oiflist, oi);
706}
707
708
709/* Config network statement related functions. */
paul4dadc292005-05-06 21:37:42 +0000710static struct ospf_network *
paul718e3742002-12-13 20:15:29 +0000711ospf_network_new (struct in_addr area_id, int format)
712{
713 struct ospf_network *new;
714 new = XCALLOC (MTYPE_OSPF_NETWORK, sizeof (struct ospf_network));
715
716 new->area_id = area_id;
717 new->format = format;
718
719 return new;
720}
721
Stephen Hemminger917e2992009-12-03 19:07:00 +0300722static void
paul68980082003-03-25 05:07:42 +0000723ospf_network_free (struct ospf *ospf, struct ospf_network *network)
paul718e3742002-12-13 20:15:29 +0000724{
paul68980082003-03-25 05:07:42 +0000725 ospf_area_check_free (ospf, network->area_id);
726 ospf_schedule_abr_task (ospf);
paul718e3742002-12-13 20:15:29 +0000727 XFREE (MTYPE_OSPF_NETWORK, network);
728}
729
730int
731ospf_network_set (struct ospf *ospf, struct prefix_ipv4 *p,
732 struct in_addr area_id)
733{
734 struct ospf_network *network;
735 struct ospf_area *area;
736 struct route_node *rn;
737 struct external_info *ei;
paul147193a2003-04-19 00:31:59 +0000738 int ret = OSPF_AREA_ID_FORMAT_ADDRESS;
paul718e3742002-12-13 20:15:29 +0000739
740 rn = route_node_get (ospf->networks, (struct prefix *)p);
741 if (rn->info)
742 {
743 /* There is already same network statement. */
744 route_unlock_node (rn);
745 return 0;
746 }
747
748 rn->info = network = ospf_network_new (area_id, ret);
paul68980082003-03-25 05:07:42 +0000749 area = ospf_area_get (ospf, area_id, ret);
paul718e3742002-12-13 20:15:29 +0000750
751 /* Run network config now. */
Joakim Tjernlunda49eb302008-09-02 19:06:31 +0100752 ospf_network_run ((struct prefix *)p, area);
paul718e3742002-12-13 20:15:29 +0000753
754 /* Update connected redistribute. */
755 if (ospf_is_type_redistributed (ZEBRA_ROUTE_CONNECT))
756 if (EXTERNAL_INFO (ZEBRA_ROUTE_CONNECT))
757 for (rn = route_top (EXTERNAL_INFO (ZEBRA_ROUTE_CONNECT));
758 rn; rn = route_next (rn))
759 if ((ei = rn->info) != NULL)
paul68980082003-03-25 05:07:42 +0000760 if (ospf_external_info_find_lsa (ospf, &ei->p))
761 if (!ospf_distribute_check_connected (ospf, ei))
762 ospf_external_lsa_flush (ospf, ei->type, &ei->p,
ajs5339cfd2005-09-19 13:28:05 +0000763 ei->ifindex /*, ei->nexthop */);
paul718e3742002-12-13 20:15:29 +0000764
paul68980082003-03-25 05:07:42 +0000765 ospf_area_check_free (ospf, area_id);
paul718e3742002-12-13 20:15:29 +0000766
767 return 1;
768}
769
770int
771ospf_network_unset (struct ospf *ospf, struct prefix_ipv4 *p,
772 struct in_addr area_id)
773{
774 struct route_node *rn;
775 struct ospf_network *network;
776 struct external_info *ei;
Joakim Tjernlunda49eb302008-09-02 19:06:31 +0100777 struct listnode *node, *nnode;
778 struct ospf_interface *oi;
paul718e3742002-12-13 20:15:29 +0000779
780 rn = route_node_lookup (ospf->networks, (struct prefix *)p);
781 if (rn == NULL)
782 return 0;
783
784 network = rn->info;
Stephen Hemminger965f54f2009-06-03 16:44:21 -0700785 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +0000786 if (!IPV4_ADDR_SAME (&area_id, &network->area_id))
787 return 0;
788
paul68980082003-03-25 05:07:42 +0000789 ospf_network_free (ospf, rn->info);
paul718e3742002-12-13 20:15:29 +0000790 rn->info = NULL;
Stephen Hemminger965f54f2009-06-03 16:44:21 -0700791 route_unlock_node (rn); /* initial reference */
paul718e3742002-12-13 20:15:29 +0000792
Joakim Tjernlunda49eb302008-09-02 19:06:31 +0100793 /* Find interfaces that not configured already. */
794 for (ALL_LIST_ELEMENTS (ospf->oiflist, node, nnode, oi))
795 {
796 int found = 0;
797 struct connected *co = oi->connected;
798
799 if (oi->type == OSPF_IFTYPE_VIRTUALLINK)
800 continue;
801
802 for (rn = route_top (ospf->networks); rn; rn = route_next (rn))
803 {
804 if (rn->info == NULL)
805 continue;
806
807 if (ospf_network_match_iface(co,&rn->p))
808 {
809 found = 1;
810 route_unlock_node (rn);
811 break;
812 }
813 }
814
815 if (found == 0)
816 ospf_if_free (oi);
817 }
paul718e3742002-12-13 20:15:29 +0000818
819 /* Update connected redistribute. */
820 if (ospf_is_type_redistributed (ZEBRA_ROUTE_CONNECT))
821 if (EXTERNAL_INFO (ZEBRA_ROUTE_CONNECT))
822 for (rn = route_top (EXTERNAL_INFO (ZEBRA_ROUTE_CONNECT));
823 rn; rn = route_next (rn))
824 if ((ei = rn->info) != NULL)
paul68980082003-03-25 05:07:42 +0000825 if (!ospf_external_info_find_lsa (ospf, &ei->p))
826 if (ospf_distribute_check_connected (ospf, ei))
827 ospf_external_lsa_originate (ospf, ei);
paul718e3742002-12-13 20:15:29 +0000828
829 return 1;
830}
831
paul570f7592003-01-25 06:47:41 +0000832/* Check whether interface matches given network
833 * returns: 1, true. 0, false
834 */
Stephen Hemminger917e2992009-12-03 19:07:00 +0300835static int
836ospf_network_match_iface(const struct connected *co, const struct prefix *net)
paul570f7592003-01-25 06:47:41 +0000837{
Andrew J. Schorre4529632006-12-12 19:18:21 +0000838 /* new approach: more elegant and conceptually clean */
839 return prefix_match(net, CONNECTED_PREFIX(co));
paul570f7592003-01-25 06:47:41 +0000840}
841
Stephen Hemminger917e2992009-12-03 19:07:00 +0300842static void
Joakim Tjernlunda49eb302008-09-02 19:06:31 +0100843ospf_network_run_interface (struct prefix *p, struct ospf_area *area,
844 struct interface *ifp)
845{
846 struct listnode *cnode;
847 struct connected *co;
848
849 if (memcmp (ifp->name, "VLINK", 5) == 0)
850 return;
851
852 /* if interface prefix is match specified prefix,
853 then create socket and join multicast group. */
854 for (ALL_LIST_ELEMENTS_RO (ifp->connected, cnode, co))
855 {
Joakim Tjernlundf0f63842009-07-27 12:42:29 +0200856
Joakim Tjernlunda49eb302008-09-02 19:06:31 +0100857 if (CHECK_FLAG(co->flags,ZEBRA_IFA_SECONDARY))
858 continue;
859
Joakim Tjernlunda49eb302008-09-02 19:06:31 +0100860 if (p->family == co->address->family
Joakim Tjernlundf0f63842009-07-27 12:42:29 +0200861 && ! ospf_if_table_lookup(ifp, co->address)
Joakim Tjernlunda49eb302008-09-02 19:06:31 +0100862 && ospf_network_match_iface(co,p))
863 {
864 struct ospf_interface *oi;
865
866 oi = ospf_if_new (area->ospf, ifp, co->address);
867 oi->connected = co;
868
869 oi->area = area;
870
871 oi->params = ospf_lookup_if_params (ifp, oi->address->u.prefix4);
872 oi->output_cost = ospf_if_get_output_cost (oi);
873
874 /* Add pseudo neighbor. */
875 ospf_nbr_add_self (oi);
876
877 /* Relate ospf interface to ospf instance. */
878 oi->ospf = area->ospf;
879
880 /* update network type as interface flag */
881 /* If network type is specified previously,
882 skip network type setting. */
883 oi->type = IF_DEF_PARAMS (ifp)->type;
884
885 ospf_area_add_if (oi->area, oi);
886
887 /* if router_id is not configured, dont bring up
888 * interfaces.
889 * ospf_router_id_update() will call ospf_if_update
890 * whenever r-id is configured instead.
891 */
892 if ((area->ospf->router_id.s_addr != 0)
893 && if_is_operative (ifp))
894 ospf_if_up (oi);
895 }
896 }
897}
898
Stephen Hemminger917e2992009-12-03 19:07:00 +0300899static void
Joakim Tjernlunda49eb302008-09-02 19:06:31 +0100900ospf_network_run (struct prefix *p, struct ospf_area *area)
paul718e3742002-12-13 20:15:29 +0000901{
902 struct interface *ifp;
hasso52dc7ee2004-09-23 19:18:23 +0000903 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000904
905 /* Schedule Router ID Update. */
Joakim Tjernlunda49eb302008-09-02 19:06:31 +0100906 if (area->ospf->router_id.s_addr == 0)
907 ospf_router_id_update (area->ospf);
paulb29800a2005-11-20 14:50:45 +0000908
paul718e3742002-12-13 20:15:29 +0000909 /* Get target interface. */
paul1eb8ef22005-04-07 07:30:20 +0000910 for (ALL_LIST_ELEMENTS_RO (om->iflist, node, ifp))
Joakim Tjernlunda49eb302008-09-02 19:06:31 +0100911 ospf_network_run_interface (p, area, ifp);
paul718e3742002-12-13 20:15:29 +0000912}
913
914void
915ospf_ls_upd_queue_empty (struct ospf_interface *oi)
916{
917 struct route_node *rn;
paul1eb8ef22005-04-07 07:30:20 +0000918 struct listnode *node, *nnode;
hasso52dc7ee2004-09-23 19:18:23 +0000919 struct list *lst;
paul718e3742002-12-13 20:15:29 +0000920 struct ospf_lsa *lsa;
921
922 /* empty ls update queue */
923 for (rn = route_top (oi->ls_upd_queue); rn;
924 rn = route_next (rn))
hasso52dc7ee2004-09-23 19:18:23 +0000925 if ((lst = (struct list *) rn->info))
paul718e3742002-12-13 20:15:29 +0000926 {
paul1eb8ef22005-04-07 07:30:20 +0000927 for (ALL_LIST_ELEMENTS (lst, node, nnode, lsa))
Paul Jakma1fe6ed32006-07-26 09:37:26 +0000928 ospf_lsa_unlock (&lsa); /* oi->ls_upd_queue */
paul718e3742002-12-13 20:15:29 +0000929 list_free (lst);
930 rn->info = NULL;
931 }
932
933 /* remove update event */
934 if (oi->t_ls_upd_event)
935 {
936 thread_cancel (oi->t_ls_upd_event);
937 oi->t_ls_upd_event = NULL;
938 }
939}
940
941void
Joakim Tjernlunda49eb302008-09-02 19:06:31 +0100942ospf_if_update (struct ospf *ospf, struct interface *ifp)
paul718e3742002-12-13 20:15:29 +0000943{
944 struct route_node *rn;
paul718e3742002-12-13 20:15:29 +0000945 struct ospf_network *network;
946 struct ospf_area *area;
Joakim Tjernlunda49eb302008-09-02 19:06:31 +0100947
948 if (!ospf)
949 ospf = ospf_lookup ();
paul718e3742002-12-13 20:15:29 +0000950
Joakim Tjernlund6e687d72008-09-24 17:15:48 +0100951 /* OSPF must be on and Router-ID must be configured. */
952 if (!ospf || ospf->router_id.s_addr == 0)
Joakim Tjernlunda49eb302008-09-02 19:06:31 +0100953 return;
954
955 /* Run each netowrk for this interface. */
956 for (rn = route_top (ospf->networks); rn; rn = route_next (rn))
957 if (rn->info != NULL)
958 {
959 network = (struct ospf_network *) rn->info;
960 area = ospf_area_get (ospf, network->area_id, network->format);
961 ospf_network_run_interface (&rn->p, area, ifp);
962 }
paul718e3742002-12-13 20:15:29 +0000963}
964
965void
paul68980082003-03-25 05:07:42 +0000966ospf_remove_vls_through_area (struct ospf *ospf, struct ospf_area *area)
paul718e3742002-12-13 20:15:29 +0000967{
paul1eb8ef22005-04-07 07:30:20 +0000968 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000969 struct ospf_vl_data *vl_data;
970
paul1eb8ef22005-04-07 07:30:20 +0000971 for (ALL_LIST_ELEMENTS (ospf->vlinks, node, nnode, vl_data))
972 if (IPV4_ADDR_SAME (&vl_data->vl_area_id, &area->area_id))
973 ospf_vl_delete (ospf, vl_data);
paul718e3742002-12-13 20:15:29 +0000974}
975
976
Stephen Hemminger7ba82f72009-05-15 10:47:45 -0700977static const struct message ospf_area_type_msg[] =
paul718e3742002-12-13 20:15:29 +0000978{
979 { OSPF_AREA_DEFAULT, "Default" },
980 { OSPF_AREA_STUB, "Stub" },
981 { OSPF_AREA_NSSA, "NSSA" },
982};
Stephen Hemminger7ba82f72009-05-15 10:47:45 -0700983static const int ospf_area_type_msg_max = OSPF_AREA_TYPE_MAX;
paul718e3742002-12-13 20:15:29 +0000984
paul4dadc292005-05-06 21:37:42 +0000985static void
paul718e3742002-12-13 20:15:29 +0000986ospf_area_type_set (struct ospf_area *area, int type)
987{
hasso52dc7ee2004-09-23 19:18:23 +0000988 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000989 struct ospf_interface *oi;
990
991 if (area->external_routing == type)
992 {
993 if (IS_DEBUG_OSPF_EVENT)
ajs9b0e25c2004-12-08 19:06:51 +0000994 zlog_debug ("Area[%s]: Types are the same, ignored.",
paul718e3742002-12-13 20:15:29 +0000995 inet_ntoa (area->area_id));
996 return;
997 }
998
999 area->external_routing = type;
1000
1001 if (IS_DEBUG_OSPF_EVENT)
ajs9b0e25c2004-12-08 19:06:51 +00001002 zlog_debug ("Area[%s]: Configured as %s", inet_ntoa (area->area_id),
paul718e3742002-12-13 20:15:29 +00001003 LOOKUP (ospf_area_type_msg, type));
1004
1005 switch (area->external_routing)
1006 {
1007 case OSPF_AREA_DEFAULT:
paul1eb8ef22005-04-07 07:30:20 +00001008 for (ALL_LIST_ELEMENTS_RO (area->oiflist, node, oi))
1009 if (oi->nbr_self != NULL)
1010 {
1011 UNSET_FLAG (oi->nbr_self->options, OSPF_OPTION_NP);
1012 SET_FLAG (oi->nbr_self->options, OSPF_OPTION_E);
1013 }
paul718e3742002-12-13 20:15:29 +00001014 break;
1015 case OSPF_AREA_STUB:
paul1eb8ef22005-04-07 07:30:20 +00001016 for (ALL_LIST_ELEMENTS_RO (area->oiflist, node, oi))
1017 if (oi->nbr_self != NULL)
1018 {
1019 if (IS_DEBUG_OSPF_EVENT)
1020 zlog_debug ("setting options on %s accordingly", IF_NAME (oi));
1021 UNSET_FLAG (oi->nbr_self->options, OSPF_OPTION_NP);
1022 UNSET_FLAG (oi->nbr_self->options, OSPF_OPTION_E);
1023 if (IS_DEBUG_OSPF_EVENT)
1024 zlog_debug ("options set on %s: %x",
1025 IF_NAME (oi), OPTIONS (oi));
1026 }
paul718e3742002-12-13 20:15:29 +00001027 break;
1028 case OSPF_AREA_NSSA:
paul1eb8ef22005-04-07 07:30:20 +00001029 for (ALL_LIST_ELEMENTS_RO (area->oiflist, node, oi))
1030 if (oi->nbr_self != NULL)
1031 {
1032 zlog_debug ("setting nssa options on %s accordingly", IF_NAME (oi));
1033 UNSET_FLAG (oi->nbr_self->options, OSPF_OPTION_E);
1034 SET_FLAG (oi->nbr_self->options, OSPF_OPTION_NP);
1035 zlog_debug ("options set on %s: %x", IF_NAME (oi), OPTIONS (oi));
1036 }
paul718e3742002-12-13 20:15:29 +00001037 break;
1038 default:
1039 break;
1040 }
1041
Paul Jakmac363d382010-01-24 22:42:13 +00001042 ospf_router_lsa_update_area (area);
paul68980082003-03-25 05:07:42 +00001043 ospf_schedule_abr_task (area->ospf);
paul718e3742002-12-13 20:15:29 +00001044}
1045
1046int
paul68980082003-03-25 05:07:42 +00001047ospf_area_shortcut_set (struct ospf *ospf, struct ospf_area *area, int mode)
paul718e3742002-12-13 20:15:29 +00001048{
1049 if (area->shortcut_configured == mode)
1050 return 0;
1051
1052 area->shortcut_configured = mode;
Paul Jakmac363d382010-01-24 22:42:13 +00001053 ospf_router_lsa_update_area (area);
paul68980082003-03-25 05:07:42 +00001054 ospf_schedule_abr_task (ospf);
paul718e3742002-12-13 20:15:29 +00001055
paul68980082003-03-25 05:07:42 +00001056 ospf_area_check_free (ospf, area->area_id);
paul718e3742002-12-13 20:15:29 +00001057
1058 return 1;
1059}
1060
1061int
paul68980082003-03-25 05:07:42 +00001062ospf_area_shortcut_unset (struct ospf *ospf, struct ospf_area *area)
paul718e3742002-12-13 20:15:29 +00001063{
1064 area->shortcut_configured = OSPF_SHORTCUT_DEFAULT;
Paul Jakmac363d382010-01-24 22:42:13 +00001065 ospf_router_lsa_update_area (area);
paul68980082003-03-25 05:07:42 +00001066 ospf_area_check_free (ospf, area->area_id);
1067 ospf_schedule_abr_task (ospf);
paul718e3742002-12-13 20:15:29 +00001068
1069 return 1;
1070}
1071
paul4dadc292005-05-06 21:37:42 +00001072static int
paul718e3742002-12-13 20:15:29 +00001073ospf_area_vlink_count (struct ospf *ospf, struct ospf_area *area)
1074{
1075 struct ospf_vl_data *vl;
hasso52dc7ee2004-09-23 19:18:23 +00001076 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00001077 int count = 0;
1078
paul1eb8ef22005-04-07 07:30:20 +00001079 for (ALL_LIST_ELEMENTS_RO (ospf->vlinks, node, vl))
1080 if (IPV4_ADDR_SAME (&vl->vl_area_id, &area->area_id))
1081 count++;
paul718e3742002-12-13 20:15:29 +00001082
1083 return count;
1084}
1085
1086int
1087ospf_area_stub_set (struct ospf *ospf, struct in_addr area_id)
1088{
1089 struct ospf_area *area;
paul147193a2003-04-19 00:31:59 +00001090 int format = OSPF_AREA_ID_FORMAT_ADDRESS;
paul718e3742002-12-13 20:15:29 +00001091
paul68980082003-03-25 05:07:42 +00001092 area = ospf_area_get (ospf, area_id, format);
paul718e3742002-12-13 20:15:29 +00001093 if (ospf_area_vlink_count (ospf, area))
1094 return 0;
1095
1096 if (area->external_routing != OSPF_AREA_STUB)
1097 ospf_area_type_set (area, OSPF_AREA_STUB);
1098
1099 return 1;
1100}
1101
1102int
1103ospf_area_stub_unset (struct ospf *ospf, struct in_addr area_id)
1104{
1105 struct ospf_area *area;
1106
paul68980082003-03-25 05:07:42 +00001107 area = ospf_area_lookup_by_area_id (ospf, area_id);
paul718e3742002-12-13 20:15:29 +00001108 if (area == NULL)
1109 return 1;
1110
1111 if (area->external_routing == OSPF_AREA_STUB)
1112 ospf_area_type_set (area, OSPF_AREA_DEFAULT);
1113
paul68980082003-03-25 05:07:42 +00001114 ospf_area_check_free (ospf, area_id);
paul718e3742002-12-13 20:15:29 +00001115
1116 return 1;
1117}
1118
1119int
1120ospf_area_no_summary_set (struct ospf *ospf, struct in_addr area_id)
1121{
1122 struct ospf_area *area;
paul147193a2003-04-19 00:31:59 +00001123 int format = OSPF_AREA_ID_FORMAT_ADDRESS;
paul718e3742002-12-13 20:15:29 +00001124
paul68980082003-03-25 05:07:42 +00001125 area = ospf_area_get (ospf, area_id, format);
paul718e3742002-12-13 20:15:29 +00001126 area->no_summary = 1;
1127
1128 return 1;
1129}
1130
1131int
1132ospf_area_no_summary_unset (struct ospf *ospf, struct in_addr area_id)
1133{
1134 struct ospf_area *area;
1135
paul68980082003-03-25 05:07:42 +00001136 area = ospf_area_lookup_by_area_id (ospf, area_id);
paul718e3742002-12-13 20:15:29 +00001137 if (area == NULL)
1138 return 0;
1139
1140 area->no_summary = 0;
paul68980082003-03-25 05:07:42 +00001141 ospf_area_check_free (ospf, area_id);
paul718e3742002-12-13 20:15:29 +00001142
1143 return 1;
1144}
1145
1146int
1147ospf_area_nssa_set (struct ospf *ospf, struct in_addr area_id)
1148{
1149 struct ospf_area *area;
paul147193a2003-04-19 00:31:59 +00001150 int format = OSPF_AREA_ID_FORMAT_ADDRESS;
paul718e3742002-12-13 20:15:29 +00001151
paul68980082003-03-25 05:07:42 +00001152 area = ospf_area_get (ospf, area_id, format);
paul718e3742002-12-13 20:15:29 +00001153 if (ospf_area_vlink_count (ospf, area))
1154 return 0;
1155
1156 if (area->external_routing != OSPF_AREA_NSSA)
1157 {
1158 ospf_area_type_set (area, OSPF_AREA_NSSA);
1159 ospf->anyNSSA++;
1160 }
1161
paul084c7842003-06-22 08:35:18 +00001162 /* set NSSA area defaults */
1163 area->no_summary = 0;
1164 area->NSSATranslatorRole = OSPF_NSSA_ROLE_CANDIDATE;
pauld4a53d52003-07-12 21:30:57 +00001165 area->NSSATranslatorState = OSPF_NSSA_TRANSLATE_DISABLED;
paul084c7842003-06-22 08:35:18 +00001166 area->NSSATranslatorStabilityInterval = OSPF_NSSA_TRANS_STABLE_DEFAULT;
1167
paul718e3742002-12-13 20:15:29 +00001168 return 1;
1169}
1170
1171int
1172ospf_area_nssa_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 if (area->external_routing == OSPF_AREA_NSSA)
1181 {
1182 ospf->anyNSSA--;
1183 ospf_area_type_set (area, OSPF_AREA_DEFAULT);
1184 }
1185
paul68980082003-03-25 05:07:42 +00001186 ospf_area_check_free (ospf, area_id);
paul718e3742002-12-13 20:15:29 +00001187
1188 return 1;
1189}
1190
1191int
1192ospf_area_nssa_translator_role_set (struct ospf *ospf, struct in_addr area_id,
1193 int role)
1194{
1195 struct ospf_area *area;
1196
paul68980082003-03-25 05:07:42 +00001197 area = ospf_area_lookup_by_area_id (ospf, area_id);
paul718e3742002-12-13 20:15:29 +00001198 if (area == NULL)
1199 return 0;
1200
paul084c7842003-06-22 08:35:18 +00001201 area->NSSATranslatorRole = role;
paul718e3742002-12-13 20:15:29 +00001202
1203 return 1;
1204}
1205
paul4dadc292005-05-06 21:37:42 +00001206/* XXX: unused? Leave for symmetry? */
1207static int
paul718e3742002-12-13 20:15:29 +00001208ospf_area_nssa_translator_role_unset (struct ospf *ospf,
1209 struct in_addr area_id)
1210{
1211 struct ospf_area *area;
1212
paul68980082003-03-25 05:07:42 +00001213 area = ospf_area_lookup_by_area_id (ospf, area_id);
paul718e3742002-12-13 20:15:29 +00001214 if (area == NULL)
1215 return 0;
1216
paul084c7842003-06-22 08:35:18 +00001217 area->NSSATranslatorRole = OSPF_NSSA_ROLE_CANDIDATE;
paul718e3742002-12-13 20:15:29 +00001218
paul68980082003-03-25 05:07:42 +00001219 ospf_area_check_free (ospf, area_id);
paul718e3742002-12-13 20:15:29 +00001220
1221 return 1;
1222}
1223
1224int
paul68980082003-03-25 05:07:42 +00001225ospf_area_export_list_set (struct ospf *ospf,
paul6c835672004-10-11 11:00:30 +00001226 struct ospf_area *area, const char *list_name)
paul718e3742002-12-13 20:15:29 +00001227{
1228 struct access_list *list;
1229 list = access_list_lookup (AFI_IP, list_name);
1230
1231 EXPORT_LIST (area) = list;
1232
1233 if (EXPORT_NAME (area))
1234 free (EXPORT_NAME (area));
1235
1236 EXPORT_NAME (area) = strdup (list_name);
paul68980082003-03-25 05:07:42 +00001237 ospf_schedule_abr_task (ospf);
paul718e3742002-12-13 20:15:29 +00001238
1239 return 1;
1240}
1241
1242int
paul68980082003-03-25 05:07:42 +00001243ospf_area_export_list_unset (struct ospf *ospf, struct ospf_area * area)
paul718e3742002-12-13 20:15:29 +00001244{
1245
1246 EXPORT_LIST (area) = 0;
1247
1248 if (EXPORT_NAME (area))
1249 free (EXPORT_NAME (area));
1250
1251 EXPORT_NAME (area) = NULL;
1252
paul68980082003-03-25 05:07:42 +00001253 ospf_area_check_free (ospf, area->area_id);
paul718e3742002-12-13 20:15:29 +00001254
paul68980082003-03-25 05:07:42 +00001255 ospf_schedule_abr_task (ospf);
paul718e3742002-12-13 20:15:29 +00001256
1257 return 1;
1258}
1259
1260int
paul6c835672004-10-11 11:00:30 +00001261ospf_area_import_list_set (struct ospf *ospf, struct ospf_area *area,
1262 const char *name)
paul718e3742002-12-13 20:15:29 +00001263{
1264 struct access_list *list;
1265 list = access_list_lookup (AFI_IP, name);
1266
1267 IMPORT_LIST (area) = list;
1268
1269 if (IMPORT_NAME (area))
1270 free (IMPORT_NAME (area));
1271
1272 IMPORT_NAME (area) = strdup (name);
paul68980082003-03-25 05:07:42 +00001273 ospf_schedule_abr_task (ospf);
paul718e3742002-12-13 20:15:29 +00001274
1275 return 1;
1276}
1277
1278int
paul68980082003-03-25 05:07:42 +00001279ospf_area_import_list_unset (struct ospf *ospf, struct ospf_area * area)
paul718e3742002-12-13 20:15:29 +00001280{
1281 IMPORT_LIST (area) = 0;
1282
1283 if (IMPORT_NAME (area))
1284 free (IMPORT_NAME (area));
1285
1286 IMPORT_NAME (area) = NULL;
paul68980082003-03-25 05:07:42 +00001287 ospf_area_check_free (ospf, area->area_id);
paul718e3742002-12-13 20:15:29 +00001288
paul68980082003-03-25 05:07:42 +00001289 ospf_schedule_abr_task (ospf);
paul718e3742002-12-13 20:15:29 +00001290
1291 return 1;
1292}
1293
1294int
paul718e3742002-12-13 20:15:29 +00001295ospf_timers_refresh_set (struct ospf *ospf, int interval)
1296{
1297 int time_left;
1298
1299 if (ospf->lsa_refresh_interval == interval)
1300 return 1;
1301
1302 time_left = ospf->lsa_refresh_interval -
Paul Jakma2518efd2006-08-27 06:49:29 +00001303 (quagga_time (NULL) - ospf->lsa_refresher_started);
paul718e3742002-12-13 20:15:29 +00001304
1305 if (time_left > interval)
1306 {
1307 OSPF_TIMER_OFF (ospf->t_lsa_refresher);
1308 ospf->t_lsa_refresher =
1309 thread_add_timer (master, ospf_lsa_refresh_walker, ospf, interval);
1310 }
1311 ospf->lsa_refresh_interval = interval;
1312
1313 return 1;
1314}
1315
1316int
1317ospf_timers_refresh_unset (struct ospf *ospf)
1318{
1319 int time_left;
1320
1321 time_left = ospf->lsa_refresh_interval -
Paul Jakma2518efd2006-08-27 06:49:29 +00001322 (quagga_time (NULL) - ospf->lsa_refresher_started);
paul718e3742002-12-13 20:15:29 +00001323
1324 if (time_left > OSPF_LSA_REFRESH_INTERVAL_DEFAULT)
1325 {
1326 OSPF_TIMER_OFF (ospf->t_lsa_refresher);
1327 ospf->t_lsa_refresher =
1328 thread_add_timer (master, ospf_lsa_refresh_walker, ospf,
1329 OSPF_LSA_REFRESH_INTERVAL_DEFAULT);
1330 }
1331
1332 ospf->lsa_refresh_interval = OSPF_LSA_REFRESH_INTERVAL_DEFAULT;
1333
1334 return 1;
1335}
1336
1337
paul4dadc292005-05-06 21:37:42 +00001338static struct ospf_nbr_nbma *
1339ospf_nbr_nbma_new (void)
paul718e3742002-12-13 20:15:29 +00001340{
1341 struct ospf_nbr_nbma *nbr_nbma;
1342
Stephen Hemminger393deb92008-08-18 14:13:29 -07001343 nbr_nbma = XCALLOC (MTYPE_OSPF_NEIGHBOR_STATIC,
paul718e3742002-12-13 20:15:29 +00001344 sizeof (struct ospf_nbr_nbma));
paul718e3742002-12-13 20:15:29 +00001345
1346 nbr_nbma->priority = OSPF_NEIGHBOR_PRIORITY_DEFAULT;
1347 nbr_nbma->v_poll = OSPF_POLL_INTERVAL_DEFAULT;
1348
1349 return nbr_nbma;
1350}
1351
paul4dadc292005-05-06 21:37:42 +00001352static void
paul718e3742002-12-13 20:15:29 +00001353ospf_nbr_nbma_free (struct ospf_nbr_nbma *nbr_nbma)
1354{
1355 XFREE (MTYPE_OSPF_NEIGHBOR_STATIC, nbr_nbma);
1356}
1357
paul4dadc292005-05-06 21:37:42 +00001358static void
paul718e3742002-12-13 20:15:29 +00001359ospf_nbr_nbma_delete (struct ospf *ospf, struct ospf_nbr_nbma *nbr_nbma)
1360{
1361 struct route_node *rn;
1362 struct prefix_ipv4 p;
1363
1364 p.family = AF_INET;
1365 p.prefix = nbr_nbma->addr;
1366 p.prefixlen = IPV4_MAX_BITLEN;
1367
1368 rn = route_node_lookup (ospf->nbr_nbma, (struct prefix *)&p);
1369 if (rn)
1370 {
1371 ospf_nbr_nbma_free (rn->info);
1372 rn->info = NULL;
1373 route_unlock_node (rn);
1374 route_unlock_node (rn);
1375 }
1376}
1377
paul4dadc292005-05-06 21:37:42 +00001378static void
paul718e3742002-12-13 20:15:29 +00001379ospf_nbr_nbma_down (struct ospf_nbr_nbma *nbr_nbma)
1380{
1381 OSPF_TIMER_OFF (nbr_nbma->t_poll);
1382
1383 if (nbr_nbma->nbr)
1384 {
1385 nbr_nbma->nbr->nbr_nbma = NULL;
1386 OSPF_NSM_EVENT_EXECUTE (nbr_nbma->nbr, NSM_KillNbr);
1387 }
1388
1389 if (nbr_nbma->oi)
1390 listnode_delete (nbr_nbma->oi->nbr_nbma, nbr_nbma);
1391}
1392
paul4dadc292005-05-06 21:37:42 +00001393static void
paul718e3742002-12-13 20:15:29 +00001394ospf_nbr_nbma_add (struct ospf_nbr_nbma *nbr_nbma,
1395 struct ospf_interface *oi)
1396{
1397 struct ospf_neighbor *nbr;
1398 struct route_node *rn;
1399 struct prefix p;
1400
1401 if (oi->type != OSPF_IFTYPE_NBMA)
1402 return;
1403
1404 if (nbr_nbma->nbr != NULL)
1405 return;
1406
1407 if (IPV4_ADDR_SAME (&oi->nbr_self->address.u.prefix4, &nbr_nbma->addr))
1408 return;
1409
1410 nbr_nbma->oi = oi;
1411 listnode_add (oi->nbr_nbma, nbr_nbma);
1412
1413 /* Get neighbor information from table. */
1414 p.family = AF_INET;
1415 p.prefixlen = IPV4_MAX_BITLEN;
1416 p.u.prefix4 = nbr_nbma->addr;
1417
1418 rn = route_node_get (oi->nbrs, (struct prefix *)&p);
1419 if (rn->info)
1420 {
1421 nbr = rn->info;
1422 nbr->nbr_nbma = nbr_nbma;
1423 nbr_nbma->nbr = nbr;
1424
1425 route_unlock_node (rn);
1426 }
1427 else
1428 {
1429 nbr = rn->info = ospf_nbr_new (oi);
1430 nbr->state = NSM_Down;
1431 nbr->src = nbr_nbma->addr;
1432 nbr->nbr_nbma = nbr_nbma;
1433 nbr->priority = nbr_nbma->priority;
1434 nbr->address = p;
1435
1436 nbr_nbma->nbr = nbr;
1437
1438 OSPF_NSM_EVENT_EXECUTE (nbr, NSM_Start);
1439 }
1440}
1441
1442void
paul68980082003-03-25 05:07:42 +00001443ospf_nbr_nbma_if_update (struct ospf *ospf, struct ospf_interface *oi)
paul718e3742002-12-13 20:15:29 +00001444{
1445 struct ospf_nbr_nbma *nbr_nbma;
1446 struct route_node *rn;
1447 struct prefix_ipv4 p;
1448
1449 if (oi->type != OSPF_IFTYPE_NBMA)
1450 return;
1451
paul68980082003-03-25 05:07:42 +00001452 for (rn = route_top (ospf->nbr_nbma); rn; rn = route_next (rn))
paul718e3742002-12-13 20:15:29 +00001453 if ((nbr_nbma = rn->info))
1454 if (nbr_nbma->oi == NULL && nbr_nbma->nbr == NULL)
1455 {
1456 p.family = AF_INET;
1457 p.prefix = nbr_nbma->addr;
1458 p.prefixlen = IPV4_MAX_BITLEN;
1459
1460 if (prefix_match (oi->address, (struct prefix *)&p))
1461 ospf_nbr_nbma_add (nbr_nbma, oi);
1462 }
1463}
1464
1465struct ospf_nbr_nbma *
1466ospf_nbr_nbma_lookup (struct ospf *ospf, struct in_addr nbr_addr)
1467{
1468 struct route_node *rn;
1469 struct prefix_ipv4 p;
1470
1471 p.family = AF_INET;
1472 p.prefix = nbr_addr;
1473 p.prefixlen = IPV4_MAX_BITLEN;
1474
1475 rn = route_node_lookup (ospf->nbr_nbma, (struct prefix *)&p);
1476 if (rn)
1477 {
1478 route_unlock_node (rn);
1479 return rn->info;
1480 }
1481 return NULL;
1482}
1483
1484struct ospf_nbr_nbma *
paul68980082003-03-25 05:07:42 +00001485ospf_nbr_nbma_lookup_next (struct ospf *ospf, struct in_addr *addr, int first)
paul718e3742002-12-13 20:15:29 +00001486{
1487#if 0
1488 struct ospf_nbr_nbma *nbr_nbma;
hasso52dc7ee2004-09-23 19:18:23 +00001489 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00001490#endif
1491
paul68980082003-03-25 05:07:42 +00001492 if (ospf == NULL)
paul718e3742002-12-13 20:15:29 +00001493 return NULL;
1494
1495#if 0
paul1eb8ef22005-04-07 07:30:20 +00001496 for (ALL_LIST_ELEMENTS_RO (ospf->nbr_nbma, node, nbr_nbma))
paul718e3742002-12-13 20:15:29 +00001497 {
paul718e3742002-12-13 20:15:29 +00001498 if (first)
1499 {
1500 *addr = nbr_nbma->addr;
1501 return nbr_nbma;
1502 }
1503 else if (ntohl (nbr_nbma->addr.s_addr) > ntohl (addr->s_addr))
1504 {
1505 *addr = nbr_nbma->addr;
1506 return nbr_nbma;
1507 }
1508 }
1509#endif
1510 return NULL;
1511}
1512
1513int
1514ospf_nbr_nbma_set (struct ospf *ospf, struct in_addr nbr_addr)
1515{
1516 struct ospf_nbr_nbma *nbr_nbma;
1517 struct ospf_interface *oi;
1518 struct prefix_ipv4 p;
1519 struct route_node *rn;
hasso52dc7ee2004-09-23 19:18:23 +00001520 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00001521
1522 nbr_nbma = ospf_nbr_nbma_lookup (ospf, nbr_addr);
1523 if (nbr_nbma)
1524 return 0;
1525
1526 nbr_nbma = ospf_nbr_nbma_new ();
1527 nbr_nbma->addr = nbr_addr;
1528
1529 p.family = AF_INET;
1530 p.prefix = nbr_addr;
1531 p.prefixlen = IPV4_MAX_BITLEN;
1532
1533 rn = route_node_get (ospf->nbr_nbma, (struct prefix *)&p);
1534 rn->info = nbr_nbma;
1535
paul1eb8ef22005-04-07 07:30:20 +00001536 for (ALL_LIST_ELEMENTS_RO (ospf->oiflist, node, oi))
paul718e3742002-12-13 20:15:29 +00001537 {
paul718e3742002-12-13 20:15:29 +00001538 if (oi->type == OSPF_IFTYPE_NBMA)
1539 if (prefix_match (oi->address, (struct prefix *)&p))
1540 {
1541 ospf_nbr_nbma_add (nbr_nbma, oi);
1542 break;
1543 }
1544 }
1545
1546 return 1;
1547}
1548
1549int
1550ospf_nbr_nbma_unset (struct ospf *ospf, struct in_addr nbr_addr)
1551{
1552 struct ospf_nbr_nbma *nbr_nbma;
1553
1554 nbr_nbma = ospf_nbr_nbma_lookup (ospf, nbr_addr);
1555 if (nbr_nbma == NULL)
1556 return 0;
1557
1558 ospf_nbr_nbma_down (nbr_nbma);
1559 ospf_nbr_nbma_delete (ospf, nbr_nbma);
1560
1561 return 1;
1562}
1563
1564int
1565ospf_nbr_nbma_priority_set (struct ospf *ospf, struct in_addr nbr_addr,
1566 u_char priority)
1567{
1568 struct ospf_nbr_nbma *nbr_nbma;
1569
1570 nbr_nbma = ospf_nbr_nbma_lookup (ospf, nbr_addr);
1571 if (nbr_nbma == NULL)
1572 return 0;
1573
1574 if (nbr_nbma->priority != priority)
1575 nbr_nbma->priority = priority;
1576
1577 return 1;
1578}
1579
1580int
1581ospf_nbr_nbma_priority_unset (struct ospf *ospf, struct in_addr nbr_addr)
1582{
1583 struct ospf_nbr_nbma *nbr_nbma;
1584
1585 nbr_nbma = ospf_nbr_nbma_lookup (ospf, nbr_addr);
1586 if (nbr_nbma == NULL)
1587 return 0;
1588
1589 if (nbr_nbma != OSPF_NEIGHBOR_PRIORITY_DEFAULT)
1590 nbr_nbma->priority = OSPF_NEIGHBOR_PRIORITY_DEFAULT;
1591
1592 return 1;
1593}
1594
1595int
1596ospf_nbr_nbma_poll_interval_set (struct ospf *ospf, struct in_addr nbr_addr,
paul6c835672004-10-11 11:00:30 +00001597 unsigned int interval)
paul718e3742002-12-13 20:15:29 +00001598{
1599 struct ospf_nbr_nbma *nbr_nbma;
1600
1601 nbr_nbma = ospf_nbr_nbma_lookup (ospf, nbr_addr);
1602 if (nbr_nbma == NULL)
1603 return 0;
1604
1605 if (nbr_nbma->v_poll != interval)
1606 {
1607 nbr_nbma->v_poll = interval;
1608 if (nbr_nbma->oi && ospf_if_is_up (nbr_nbma->oi))
1609 {
1610 OSPF_TIMER_OFF (nbr_nbma->t_poll);
1611 OSPF_POLL_TIMER_ON (nbr_nbma->t_poll, ospf_poll_timer,
1612 nbr_nbma->v_poll);
1613 }
1614 }
1615
1616 return 1;
1617}
1618
1619int
1620ospf_nbr_nbma_poll_interval_unset (struct ospf *ospf, struct in_addr addr)
1621{
1622 struct ospf_nbr_nbma *nbr_nbma;
1623
1624 nbr_nbma = ospf_nbr_nbma_lookup (ospf, addr);
1625 if (nbr_nbma == NULL)
1626 return 0;
1627
1628 if (nbr_nbma->v_poll != OSPF_POLL_INTERVAL_DEFAULT)
1629 nbr_nbma->v_poll = OSPF_POLL_INTERVAL_DEFAULT;
1630
1631 return 1;
1632}
1633
paul718e3742002-12-13 20:15:29 +00001634void
paul020709f2003-04-04 02:44:16 +00001635ospf_master_init ()
1636{
1637 memset (&ospf_master, 0, sizeof (struct ospf_master));
1638
1639 om = &ospf_master;
1640 om->ospf = list_new ();
1641 om->master = thread_master_create ();
Paul Jakma2518efd2006-08-27 06:49:29 +00001642 om->start_time = quagga_time (NULL);
paul020709f2003-04-04 02:44:16 +00001643}