blob: a7553e738ffb94127dfef44607520ee72c3a0c6c [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
paul68980082003-03-25 05:07:42 +0000134 OSPF_TIMER_ON (ospf->t_router_lsa_update,
paul718e3742002-12-13 20:15:29 +0000135 ospf_router_lsa_update_timer, OSPF_LSA_UPDATE_DELAY);
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))
340 ospf_router_lsa_timer_add (area);
341 }
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_router_lsa_update);
477 OSPF_TIMER_OFF (ospf->t_spf_calc);
478 OSPF_TIMER_OFF (ospf->t_ase_calc);
479 OSPF_TIMER_OFF (ospf->t_maxage);
480 OSPF_TIMER_OFF (ospf->t_maxage_walker);
481 OSPF_TIMER_OFF (ospf->t_abr_task);
paul88d6cf32005-10-29 12:50:09 +0000482 OSPF_TIMER_OFF (ospf->t_asbr_check);
paul718e3742002-12-13 20:15:29 +0000483 OSPF_TIMER_OFF (ospf->t_distribute_update);
484 OSPF_TIMER_OFF (ospf->t_lsa_refresher);
485 OSPF_TIMER_OFF (ospf->t_read);
486 OSPF_TIMER_OFF (ospf->t_write);
paul31a59762005-11-14 11:11:11 +0000487#ifdef HAVE_OPAQUE_LSA
paul88d6cf32005-10-29 12:50:09 +0000488 OSPF_TIMER_OFF (ospf->t_opaque_lsa_self);
paul31a59762005-11-14 11:11:11 +0000489#endif
paul718e3742002-12-13 20:15:29 +0000490
491 close (ospf->fd);
ajs5c333492005-02-23 15:43:01 +0000492 stream_free(ospf->ibuf);
paul718e3742002-12-13 20:15:29 +0000493
494#ifdef HAVE_OPAQUE_LSA
paul68980082003-03-25 05:07:42 +0000495 LSDB_LOOP (OPAQUE_AS_LSDB (ospf), rn, lsa)
496 ospf_discard_from_db (ospf, ospf->lsdb, lsa);
paul718e3742002-12-13 20:15:29 +0000497#endif /* HAVE_OPAQUE_LSA */
paul68980082003-03-25 05:07:42 +0000498 LSDB_LOOP (EXTERNAL_LSDB (ospf), rn, lsa)
499 ospf_discard_from_db (ospf, ospf->lsdb, lsa);
500
paul718e3742002-12-13 20:15:29 +0000501 ospf_lsdb_delete_all (ospf->lsdb);
502 ospf_lsdb_free (ospf->lsdb);
503
paul1eb8ef22005-04-07 07:30:20 +0000504 for (ALL_LIST_ELEMENTS (ospf->maxage_lsa, node, nnode, lsa))
Paul Jakma1fe6ed32006-07-26 09:37:26 +0000505 ospf_lsa_unlock (&lsa); /* maxage_lsa */
paul718e3742002-12-13 20:15:29 +0000506
507 list_delete (ospf->maxage_lsa);
508
509 if (ospf->old_table)
510 ospf_route_table_free (ospf->old_table);
511 if (ospf->new_table)
512 {
513 ospf_route_delete (ospf->new_table);
514 ospf_route_table_free (ospf->new_table);
515 }
516 if (ospf->old_rtrs)
517 ospf_rtrs_free (ospf->old_rtrs);
518 if (ospf->new_rtrs)
519 ospf_rtrs_free (ospf->new_rtrs);
520 if (ospf->new_external_route)
521 {
522 ospf_route_delete (ospf->new_external_route);
523 ospf_route_table_free (ospf->new_external_route);
524 }
525 if (ospf->old_external_route)
526 {
527 ospf_route_delete (ospf->old_external_route);
528 ospf_route_table_free (ospf->old_external_route);
529 }
530 if (ospf->external_lsas)
531 {
532 ospf_ase_external_lsas_finish (ospf->external_lsas);
533 }
534
535 list_delete (ospf->areas);
536
537 for (i = ZEBRA_ROUTE_SYSTEM; i <= ZEBRA_ROUTE_MAX; i++)
538 if (EXTERNAL_INFO (i) != NULL)
539 for (rn = route_top (EXTERNAL_INFO (i)); rn; rn = route_next (rn))
540 {
541 if (rn->info == NULL)
542 continue;
543
544 XFREE (MTYPE_OSPF_EXTERNAL_INFO, rn->info);
545 rn->info = NULL;
546 route_unlock_node (rn);
547 }
548
paul68980082003-03-25 05:07:42 +0000549 ospf_distance_reset (ospf);
paul718e3742002-12-13 20:15:29 +0000550 route_table_finish (ospf->distance_table);
551
paul020709f2003-04-04 02:44:16 +0000552 ospf_delete (ospf);
paul718e3742002-12-13 20:15:29 +0000553
paul020709f2003-04-04 02:44:16 +0000554 XFREE (MTYPE_OSPF_TOP, ospf);
paul718e3742002-12-13 20:15:29 +0000555}
556
557
558/* allocate new OSPF Area object */
paul4dadc292005-05-06 21:37:42 +0000559static struct ospf_area *
paul68980082003-03-25 05:07:42 +0000560ospf_area_new (struct ospf *ospf, struct in_addr area_id)
paul718e3742002-12-13 20:15:29 +0000561{
562 struct ospf_area *new;
563
564 /* Allocate new config_network. */
565 new = XCALLOC (MTYPE_OSPF_AREA, sizeof (struct ospf_area));
566
paul68980082003-03-25 05:07:42 +0000567 new->ospf = ospf;
paul718e3742002-12-13 20:15:29 +0000568
569 new->area_id = area_id;
570
571 new->external_routing = OSPF_AREA_DEFAULT;
572 new->default_cost = 1;
573 new->auth_type = OSPF_AUTH_NULL;
paul88d6cf32005-10-29 12:50:09 +0000574
paul718e3742002-12-13 20:15:29 +0000575 /* New LSDB init. */
576 new->lsdb = ospf_lsdb_new ();
577
578 /* Self-originated LSAs initialize. */
579 new->router_lsa_self = NULL;
580
581#ifdef HAVE_OPAQUE_LSA
582 ospf_opaque_type10_lsa_init (new);
583#endif /* HAVE_OPAQUE_LSA */
584
585 new->oiflist = list_new ();
586 new->ranges = route_table_init ();
587
588 if (area_id.s_addr == OSPF_AREA_BACKBONE)
paul68980082003-03-25 05:07:42 +0000589 ospf->backbone = new;
paul718e3742002-12-13 20:15:29 +0000590
591 return new;
592}
593
Stephen Hemminger917e2992009-12-03 19:07:00 +0300594static void
paul718e3742002-12-13 20:15:29 +0000595ospf_area_free (struct ospf_area *area)
596{
paul68980082003-03-25 05:07:42 +0000597 struct route_node *rn;
598 struct ospf_lsa *lsa;
599
paul718e3742002-12-13 20:15:29 +0000600 /* Free LSDBs. */
paul68980082003-03-25 05:07:42 +0000601 LSDB_LOOP (ROUTER_LSDB (area), rn, lsa)
602 ospf_discard_from_db (area->ospf, area->lsdb, lsa);
603 LSDB_LOOP (NETWORK_LSDB (area), rn, lsa)
604 ospf_discard_from_db (area->ospf, area->lsdb, lsa);
605 LSDB_LOOP (SUMMARY_LSDB (area), rn, lsa)
606 ospf_discard_from_db (area->ospf, area->lsdb, lsa);
607 LSDB_LOOP (ASBR_SUMMARY_LSDB (area), rn, lsa)
608 ospf_discard_from_db (area->ospf, area->lsdb, lsa);
paul718e3742002-12-13 20:15:29 +0000609
paul68980082003-03-25 05:07:42 +0000610 LSDB_LOOP (NSSA_LSDB (area), rn, lsa)
611 ospf_discard_from_db (area->ospf, area->lsdb, lsa);
paul718e3742002-12-13 20:15:29 +0000612#ifdef HAVE_OPAQUE_LSA
paul68980082003-03-25 05:07:42 +0000613 LSDB_LOOP (OPAQUE_AREA_LSDB (area), rn, lsa)
614 ospf_discard_from_db (area->ospf, area->lsdb, lsa);
615 LSDB_LOOP (OPAQUE_LINK_LSDB (area), rn, lsa)
616 ospf_discard_from_db (area->ospf, area->lsdb, lsa);
paul718e3742002-12-13 20:15:29 +0000617#endif /* HAVE_OPAQUE_LSA */
618
619 ospf_lsdb_delete_all (area->lsdb);
620 ospf_lsdb_free (area->lsdb);
621
Paul Jakma1fe6ed32006-07-26 09:37:26 +0000622 ospf_lsa_unlock (&area->router_lsa_self);
paul718e3742002-12-13 20:15:29 +0000623
624 route_table_finish (area->ranges);
625 list_delete (area->oiflist);
626
627 if (EXPORT_NAME (area))
628 free (EXPORT_NAME (area));
629
630 if (IMPORT_NAME (area))
631 free (IMPORT_NAME (area));
632
633 /* Cancel timer. */
634 OSPF_TIMER_OFF (area->t_router_lsa_self);
paul88d6cf32005-10-29 12:50:09 +0000635 OSPF_TIMER_OFF (area->t_stub_router);
636#ifdef HAVE_OPAQUE_LSA
637 OSPF_TIMER_OFF (area->t_opaque_lsa_self);
638#endif /* HAVE_OPAQUE_LSA */
639
paul718e3742002-12-13 20:15:29 +0000640 if (OSPF_IS_AREA_BACKBONE (area))
paul68980082003-03-25 05:07:42 +0000641 area->ospf->backbone = NULL;
paul718e3742002-12-13 20:15:29 +0000642
643 XFREE (MTYPE_OSPF_AREA, area);
644}
645
646void
paul68980082003-03-25 05:07:42 +0000647ospf_area_check_free (struct ospf *ospf, struct in_addr area_id)
paul718e3742002-12-13 20:15:29 +0000648{
649 struct ospf_area *area;
650
paul68980082003-03-25 05:07:42 +0000651 area = ospf_area_lookup_by_area_id (ospf, area_id);
paul718e3742002-12-13 20:15:29 +0000652 if (area &&
653 listcount (area->oiflist) == 0 &&
654 area->ranges->top == NULL &&
655 area->shortcut_configured == OSPF_SHORTCUT_DEFAULT &&
656 area->external_routing == OSPF_AREA_DEFAULT &&
657 area->no_summary == 0 &&
658 area->default_cost == 1 &&
659 EXPORT_NAME (area) == NULL &&
660 IMPORT_NAME (area) == NULL &&
661 area->auth_type == OSPF_AUTH_NULL)
662 {
paul68980082003-03-25 05:07:42 +0000663 listnode_delete (ospf->areas, area);
paul718e3742002-12-13 20:15:29 +0000664 ospf_area_free (area);
665 }
666}
667
668struct ospf_area *
paul68980082003-03-25 05:07:42 +0000669ospf_area_get (struct ospf *ospf, struct in_addr area_id, int format)
paul718e3742002-12-13 20:15:29 +0000670{
671 struct ospf_area *area;
672
paul68980082003-03-25 05:07:42 +0000673 area = ospf_area_lookup_by_area_id (ospf, area_id);
paul718e3742002-12-13 20:15:29 +0000674 if (!area)
675 {
paul68980082003-03-25 05:07:42 +0000676 area = ospf_area_new (ospf, area_id);
paul718e3742002-12-13 20:15:29 +0000677 area->format = format;
paul68980082003-03-25 05:07:42 +0000678 listnode_add_sort (ospf->areas, area);
679 ospf_check_abr_status (ospf);
paul718e3742002-12-13 20:15:29 +0000680 }
681
682 return area;
683}
684
685struct ospf_area *
paul68980082003-03-25 05:07:42 +0000686ospf_area_lookup_by_area_id (struct ospf *ospf, struct in_addr area_id)
paul718e3742002-12-13 20:15:29 +0000687{
688 struct ospf_area *area;
hasso52dc7ee2004-09-23 19:18:23 +0000689 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000690
paul1eb8ef22005-04-07 07:30:20 +0000691 for (ALL_LIST_ELEMENTS_RO (ospf->areas, node, area))
692 if (IPV4_ADDR_SAME (&area->area_id, &area_id))
693 return area;
paul718e3742002-12-13 20:15:29 +0000694
695 return NULL;
696}
697
698void
699ospf_area_add_if (struct ospf_area *area, struct ospf_interface *oi)
700{
701 listnode_add (area->oiflist, oi);
702}
703
704void
705ospf_area_del_if (struct ospf_area *area, struct ospf_interface *oi)
706{
707 listnode_delete (area->oiflist, oi);
708}
709
710
711/* Config network statement related functions. */
paul4dadc292005-05-06 21:37:42 +0000712static struct ospf_network *
paul718e3742002-12-13 20:15:29 +0000713ospf_network_new (struct in_addr area_id, int format)
714{
715 struct ospf_network *new;
716 new = XCALLOC (MTYPE_OSPF_NETWORK, sizeof (struct ospf_network));
717
718 new->area_id = area_id;
719 new->format = format;
720
721 return new;
722}
723
Stephen Hemminger917e2992009-12-03 19:07:00 +0300724static void
paul68980082003-03-25 05:07:42 +0000725ospf_network_free (struct ospf *ospf, struct ospf_network *network)
paul718e3742002-12-13 20:15:29 +0000726{
paul68980082003-03-25 05:07:42 +0000727 ospf_area_check_free (ospf, network->area_id);
728 ospf_schedule_abr_task (ospf);
paul718e3742002-12-13 20:15:29 +0000729 XFREE (MTYPE_OSPF_NETWORK, network);
730}
731
732int
733ospf_network_set (struct ospf *ospf, struct prefix_ipv4 *p,
734 struct in_addr area_id)
735{
736 struct ospf_network *network;
737 struct ospf_area *area;
738 struct route_node *rn;
739 struct external_info *ei;
paul147193a2003-04-19 00:31:59 +0000740 int ret = OSPF_AREA_ID_FORMAT_ADDRESS;
paul718e3742002-12-13 20:15:29 +0000741
742 rn = route_node_get (ospf->networks, (struct prefix *)p);
743 if (rn->info)
744 {
745 /* There is already same network statement. */
746 route_unlock_node (rn);
747 return 0;
748 }
749
750 rn->info = network = ospf_network_new (area_id, ret);
paul68980082003-03-25 05:07:42 +0000751 area = ospf_area_get (ospf, area_id, ret);
paul718e3742002-12-13 20:15:29 +0000752
753 /* Run network config now. */
Joakim Tjernlunda49eb302008-09-02 19:06:31 +0100754 ospf_network_run ((struct prefix *)p, area);
paul718e3742002-12-13 20:15:29 +0000755
756 /* Update connected redistribute. */
757 if (ospf_is_type_redistributed (ZEBRA_ROUTE_CONNECT))
758 if (EXTERNAL_INFO (ZEBRA_ROUTE_CONNECT))
759 for (rn = route_top (EXTERNAL_INFO (ZEBRA_ROUTE_CONNECT));
760 rn; rn = route_next (rn))
761 if ((ei = rn->info) != NULL)
paul68980082003-03-25 05:07:42 +0000762 if (ospf_external_info_find_lsa (ospf, &ei->p))
763 if (!ospf_distribute_check_connected (ospf, ei))
764 ospf_external_lsa_flush (ospf, ei->type, &ei->p,
ajs5339cfd2005-09-19 13:28:05 +0000765 ei->ifindex /*, ei->nexthop */);
paul718e3742002-12-13 20:15:29 +0000766
paul68980082003-03-25 05:07:42 +0000767 ospf_area_check_free (ospf, area_id);
paul718e3742002-12-13 20:15:29 +0000768
769 return 1;
770}
771
772int
773ospf_network_unset (struct ospf *ospf, struct prefix_ipv4 *p,
774 struct in_addr area_id)
775{
776 struct route_node *rn;
777 struct ospf_network *network;
778 struct external_info *ei;
Joakim Tjernlunda49eb302008-09-02 19:06:31 +0100779 struct listnode *node, *nnode;
780 struct ospf_interface *oi;
paul718e3742002-12-13 20:15:29 +0000781
782 rn = route_node_lookup (ospf->networks, (struct prefix *)p);
783 if (rn == NULL)
784 return 0;
785
786 network = rn->info;
Stephen Hemminger965f54f2009-06-03 16:44:21 -0700787 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +0000788 if (!IPV4_ADDR_SAME (&area_id, &network->area_id))
789 return 0;
790
paul68980082003-03-25 05:07:42 +0000791 ospf_network_free (ospf, rn->info);
paul718e3742002-12-13 20:15:29 +0000792 rn->info = NULL;
Stephen Hemminger965f54f2009-06-03 16:44:21 -0700793 route_unlock_node (rn); /* initial reference */
paul718e3742002-12-13 20:15:29 +0000794
Joakim Tjernlunda49eb302008-09-02 19:06:31 +0100795 /* Find interfaces that not configured already. */
796 for (ALL_LIST_ELEMENTS (ospf->oiflist, node, nnode, oi))
797 {
798 int found = 0;
799 struct connected *co = oi->connected;
800
801 if (oi->type == OSPF_IFTYPE_VIRTUALLINK)
802 continue;
803
804 for (rn = route_top (ospf->networks); rn; rn = route_next (rn))
805 {
806 if (rn->info == NULL)
807 continue;
808
809 if (ospf_network_match_iface(co,&rn->p))
810 {
811 found = 1;
812 route_unlock_node (rn);
813 break;
814 }
815 }
816
817 if (found == 0)
818 ospf_if_free (oi);
819 }
paul718e3742002-12-13 20:15:29 +0000820
821 /* Update connected redistribute. */
822 if (ospf_is_type_redistributed (ZEBRA_ROUTE_CONNECT))
823 if (EXTERNAL_INFO (ZEBRA_ROUTE_CONNECT))
824 for (rn = route_top (EXTERNAL_INFO (ZEBRA_ROUTE_CONNECT));
825 rn; rn = route_next (rn))
826 if ((ei = rn->info) != NULL)
paul68980082003-03-25 05:07:42 +0000827 if (!ospf_external_info_find_lsa (ospf, &ei->p))
828 if (ospf_distribute_check_connected (ospf, ei))
829 ospf_external_lsa_originate (ospf, ei);
paul718e3742002-12-13 20:15:29 +0000830
831 return 1;
832}
833
paul570f7592003-01-25 06:47:41 +0000834/* Check whether interface matches given network
835 * returns: 1, true. 0, false
836 */
Stephen Hemminger917e2992009-12-03 19:07:00 +0300837static int
838ospf_network_match_iface(const struct connected *co, const struct prefix *net)
paul570f7592003-01-25 06:47:41 +0000839{
Andrew J. Schorre4529632006-12-12 19:18:21 +0000840 /* new approach: more elegant and conceptually clean */
841 return prefix_match(net, CONNECTED_PREFIX(co));
paul570f7592003-01-25 06:47:41 +0000842}
843
Stephen Hemminger917e2992009-12-03 19:07:00 +0300844static void
Joakim Tjernlunda49eb302008-09-02 19:06:31 +0100845ospf_network_run_interface (struct prefix *p, struct ospf_area *area,
846 struct interface *ifp)
847{
848 struct listnode *cnode;
849 struct connected *co;
850
851 if (memcmp (ifp->name, "VLINK", 5) == 0)
852 return;
853
854 /* if interface prefix is match specified prefix,
855 then create socket and join multicast group. */
856 for (ALL_LIST_ELEMENTS_RO (ifp->connected, cnode, co))
857 {
Joakim Tjernlundf0f63842009-07-27 12:42:29 +0200858
Joakim Tjernlunda49eb302008-09-02 19:06:31 +0100859 if (CHECK_FLAG(co->flags,ZEBRA_IFA_SECONDARY))
860 continue;
861
Joakim Tjernlunda49eb302008-09-02 19:06:31 +0100862 if (p->family == co->address->family
Joakim Tjernlundf0f63842009-07-27 12:42:29 +0200863 && ! ospf_if_table_lookup(ifp, co->address)
Joakim Tjernlunda49eb302008-09-02 19:06:31 +0100864 && ospf_network_match_iface(co,p))
865 {
866 struct ospf_interface *oi;
867
868 oi = ospf_if_new (area->ospf, ifp, co->address);
869 oi->connected = co;
870
871 oi->area = area;
872
873 oi->params = ospf_lookup_if_params (ifp, oi->address->u.prefix4);
874 oi->output_cost = ospf_if_get_output_cost (oi);
875
876 /* Add pseudo neighbor. */
877 ospf_nbr_add_self (oi);
878
879 /* Relate ospf interface to ospf instance. */
880 oi->ospf = area->ospf;
881
882 /* update network type as interface flag */
883 /* If network type is specified previously,
884 skip network type setting. */
885 oi->type = IF_DEF_PARAMS (ifp)->type;
886
887 ospf_area_add_if (oi->area, oi);
888
889 /* if router_id is not configured, dont bring up
890 * interfaces.
891 * ospf_router_id_update() will call ospf_if_update
892 * whenever r-id is configured instead.
893 */
894 if ((area->ospf->router_id.s_addr != 0)
895 && if_is_operative (ifp))
896 ospf_if_up (oi);
897 }
898 }
899}
900
Stephen Hemminger917e2992009-12-03 19:07:00 +0300901static void
Joakim Tjernlunda49eb302008-09-02 19:06:31 +0100902ospf_network_run (struct prefix *p, struct ospf_area *area)
paul718e3742002-12-13 20:15:29 +0000903{
904 struct interface *ifp;
hasso52dc7ee2004-09-23 19:18:23 +0000905 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000906
907 /* Schedule Router ID Update. */
Joakim Tjernlunda49eb302008-09-02 19:06:31 +0100908 if (area->ospf->router_id.s_addr == 0)
909 ospf_router_id_update (area->ospf);
paulb29800a2005-11-20 14:50:45 +0000910
paul718e3742002-12-13 20:15:29 +0000911 /* Get target interface. */
paul1eb8ef22005-04-07 07:30:20 +0000912 for (ALL_LIST_ELEMENTS_RO (om->iflist, node, ifp))
Joakim Tjernlunda49eb302008-09-02 19:06:31 +0100913 ospf_network_run_interface (p, area, ifp);
paul718e3742002-12-13 20:15:29 +0000914}
915
916void
917ospf_ls_upd_queue_empty (struct ospf_interface *oi)
918{
919 struct route_node *rn;
paul1eb8ef22005-04-07 07:30:20 +0000920 struct listnode *node, *nnode;
hasso52dc7ee2004-09-23 19:18:23 +0000921 struct list *lst;
paul718e3742002-12-13 20:15:29 +0000922 struct ospf_lsa *lsa;
923
924 /* empty ls update queue */
925 for (rn = route_top (oi->ls_upd_queue); rn;
926 rn = route_next (rn))
hasso52dc7ee2004-09-23 19:18:23 +0000927 if ((lst = (struct list *) rn->info))
paul718e3742002-12-13 20:15:29 +0000928 {
paul1eb8ef22005-04-07 07:30:20 +0000929 for (ALL_LIST_ELEMENTS (lst, node, nnode, lsa))
Paul Jakma1fe6ed32006-07-26 09:37:26 +0000930 ospf_lsa_unlock (&lsa); /* oi->ls_upd_queue */
paul718e3742002-12-13 20:15:29 +0000931 list_free (lst);
932 rn->info = NULL;
933 }
934
935 /* remove update event */
936 if (oi->t_ls_upd_event)
937 {
938 thread_cancel (oi->t_ls_upd_event);
939 oi->t_ls_upd_event = NULL;
940 }
941}
942
943void
Joakim Tjernlunda49eb302008-09-02 19:06:31 +0100944ospf_if_update (struct ospf *ospf, struct interface *ifp)
paul718e3742002-12-13 20:15:29 +0000945{
946 struct route_node *rn;
paul718e3742002-12-13 20:15:29 +0000947 struct ospf_network *network;
948 struct ospf_area *area;
Joakim Tjernlunda49eb302008-09-02 19:06:31 +0100949
950 if (!ospf)
951 ospf = ospf_lookup ();
paul718e3742002-12-13 20:15:29 +0000952
Joakim Tjernlund6e687d72008-09-24 17:15:48 +0100953 /* OSPF must be on and Router-ID must be configured. */
954 if (!ospf || ospf->router_id.s_addr == 0)
Joakim Tjernlunda49eb302008-09-02 19:06:31 +0100955 return;
956
957 /* Run each netowrk for this interface. */
958 for (rn = route_top (ospf->networks); rn; rn = route_next (rn))
959 if (rn->info != NULL)
960 {
961 network = (struct ospf_network *) rn->info;
962 area = ospf_area_get (ospf, network->area_id, network->format);
963 ospf_network_run_interface (&rn->p, area, ifp);
964 }
paul718e3742002-12-13 20:15:29 +0000965}
966
967void
paul68980082003-03-25 05:07:42 +0000968ospf_remove_vls_through_area (struct ospf *ospf, struct ospf_area *area)
paul718e3742002-12-13 20:15:29 +0000969{
paul1eb8ef22005-04-07 07:30:20 +0000970 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000971 struct ospf_vl_data *vl_data;
972
paul1eb8ef22005-04-07 07:30:20 +0000973 for (ALL_LIST_ELEMENTS (ospf->vlinks, node, nnode, vl_data))
974 if (IPV4_ADDR_SAME (&vl_data->vl_area_id, &area->area_id))
975 ospf_vl_delete (ospf, vl_data);
paul718e3742002-12-13 20:15:29 +0000976}
977
978
Stephen Hemminger7ba82f72009-05-15 10:47:45 -0700979static const struct message ospf_area_type_msg[] =
paul718e3742002-12-13 20:15:29 +0000980{
981 { OSPF_AREA_DEFAULT, "Default" },
982 { OSPF_AREA_STUB, "Stub" },
983 { OSPF_AREA_NSSA, "NSSA" },
984};
Stephen Hemminger7ba82f72009-05-15 10:47:45 -0700985static const int ospf_area_type_msg_max = OSPF_AREA_TYPE_MAX;
paul718e3742002-12-13 20:15:29 +0000986
paul4dadc292005-05-06 21:37:42 +0000987static void
paul718e3742002-12-13 20:15:29 +0000988ospf_area_type_set (struct ospf_area *area, int type)
989{
hasso52dc7ee2004-09-23 19:18:23 +0000990 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000991 struct ospf_interface *oi;
992
993 if (area->external_routing == type)
994 {
995 if (IS_DEBUG_OSPF_EVENT)
ajs9b0e25c2004-12-08 19:06:51 +0000996 zlog_debug ("Area[%s]: Types are the same, ignored.",
paul718e3742002-12-13 20:15:29 +0000997 inet_ntoa (area->area_id));
998 return;
999 }
1000
1001 area->external_routing = type;
1002
1003 if (IS_DEBUG_OSPF_EVENT)
ajs9b0e25c2004-12-08 19:06:51 +00001004 zlog_debug ("Area[%s]: Configured as %s", inet_ntoa (area->area_id),
paul718e3742002-12-13 20:15:29 +00001005 LOOKUP (ospf_area_type_msg, type));
1006
1007 switch (area->external_routing)
1008 {
1009 case OSPF_AREA_DEFAULT:
paul1eb8ef22005-04-07 07:30:20 +00001010 for (ALL_LIST_ELEMENTS_RO (area->oiflist, node, oi))
1011 if (oi->nbr_self != NULL)
1012 {
1013 UNSET_FLAG (oi->nbr_self->options, OSPF_OPTION_NP);
1014 SET_FLAG (oi->nbr_self->options, OSPF_OPTION_E);
1015 }
paul718e3742002-12-13 20:15:29 +00001016 break;
1017 case OSPF_AREA_STUB:
paul1eb8ef22005-04-07 07:30:20 +00001018 for (ALL_LIST_ELEMENTS_RO (area->oiflist, node, oi))
1019 if (oi->nbr_self != NULL)
1020 {
1021 if (IS_DEBUG_OSPF_EVENT)
1022 zlog_debug ("setting options on %s accordingly", IF_NAME (oi));
1023 UNSET_FLAG (oi->nbr_self->options, OSPF_OPTION_NP);
1024 UNSET_FLAG (oi->nbr_self->options, OSPF_OPTION_E);
1025 if (IS_DEBUG_OSPF_EVENT)
1026 zlog_debug ("options set on %s: %x",
1027 IF_NAME (oi), OPTIONS (oi));
1028 }
paul718e3742002-12-13 20:15:29 +00001029 break;
1030 case OSPF_AREA_NSSA:
paul1eb8ef22005-04-07 07:30:20 +00001031 for (ALL_LIST_ELEMENTS_RO (area->oiflist, node, oi))
1032 if (oi->nbr_self != NULL)
1033 {
1034 zlog_debug ("setting nssa options on %s accordingly", IF_NAME (oi));
1035 UNSET_FLAG (oi->nbr_self->options, OSPF_OPTION_E);
1036 SET_FLAG (oi->nbr_self->options, OSPF_OPTION_NP);
1037 zlog_debug ("options set on %s: %x", IF_NAME (oi), OPTIONS (oi));
1038 }
paul718e3742002-12-13 20:15:29 +00001039 break;
1040 default:
1041 break;
1042 }
1043
1044 ospf_router_lsa_timer_add (area);
paul68980082003-03-25 05:07:42 +00001045 ospf_schedule_abr_task (area->ospf);
paul718e3742002-12-13 20:15:29 +00001046}
1047
1048int
paul68980082003-03-25 05:07:42 +00001049ospf_area_shortcut_set (struct ospf *ospf, struct ospf_area *area, int mode)
paul718e3742002-12-13 20:15:29 +00001050{
1051 if (area->shortcut_configured == mode)
1052 return 0;
1053
1054 area->shortcut_configured = mode;
1055 ospf_router_lsa_timer_add (area);
paul68980082003-03-25 05:07:42 +00001056 ospf_schedule_abr_task (ospf);
paul718e3742002-12-13 20:15:29 +00001057
paul68980082003-03-25 05:07:42 +00001058 ospf_area_check_free (ospf, area->area_id);
paul718e3742002-12-13 20:15:29 +00001059
1060 return 1;
1061}
1062
1063int
paul68980082003-03-25 05:07:42 +00001064ospf_area_shortcut_unset (struct ospf *ospf, struct ospf_area *area)
paul718e3742002-12-13 20:15:29 +00001065{
1066 area->shortcut_configured = OSPF_SHORTCUT_DEFAULT;
1067 ospf_router_lsa_timer_add (area);
paul68980082003-03-25 05:07:42 +00001068 ospf_area_check_free (ospf, area->area_id);
1069 ospf_schedule_abr_task (ospf);
paul718e3742002-12-13 20:15:29 +00001070
1071 return 1;
1072}
1073
paul4dadc292005-05-06 21:37:42 +00001074static int
paul718e3742002-12-13 20:15:29 +00001075ospf_area_vlink_count (struct ospf *ospf, struct ospf_area *area)
1076{
1077 struct ospf_vl_data *vl;
hasso52dc7ee2004-09-23 19:18:23 +00001078 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00001079 int count = 0;
1080
paul1eb8ef22005-04-07 07:30:20 +00001081 for (ALL_LIST_ELEMENTS_RO (ospf->vlinks, node, vl))
1082 if (IPV4_ADDR_SAME (&vl->vl_area_id, &area->area_id))
1083 count++;
paul718e3742002-12-13 20:15:29 +00001084
1085 return count;
1086}
1087
1088int
1089ospf_area_stub_set (struct ospf *ospf, struct in_addr area_id)
1090{
1091 struct ospf_area *area;
paul147193a2003-04-19 00:31:59 +00001092 int format = OSPF_AREA_ID_FORMAT_ADDRESS;
paul718e3742002-12-13 20:15:29 +00001093
paul68980082003-03-25 05:07:42 +00001094 area = ospf_area_get (ospf, area_id, format);
paul718e3742002-12-13 20:15:29 +00001095 if (ospf_area_vlink_count (ospf, area))
1096 return 0;
1097
1098 if (area->external_routing != OSPF_AREA_STUB)
1099 ospf_area_type_set (area, OSPF_AREA_STUB);
1100
1101 return 1;
1102}
1103
1104int
1105ospf_area_stub_unset (struct ospf *ospf, struct in_addr area_id)
1106{
1107 struct ospf_area *area;
1108
paul68980082003-03-25 05:07:42 +00001109 area = ospf_area_lookup_by_area_id (ospf, area_id);
paul718e3742002-12-13 20:15:29 +00001110 if (area == NULL)
1111 return 1;
1112
1113 if (area->external_routing == OSPF_AREA_STUB)
1114 ospf_area_type_set (area, OSPF_AREA_DEFAULT);
1115
paul68980082003-03-25 05:07:42 +00001116 ospf_area_check_free (ospf, area_id);
paul718e3742002-12-13 20:15:29 +00001117
1118 return 1;
1119}
1120
1121int
1122ospf_area_no_summary_set (struct ospf *ospf, struct in_addr area_id)
1123{
1124 struct ospf_area *area;
paul147193a2003-04-19 00:31:59 +00001125 int format = OSPF_AREA_ID_FORMAT_ADDRESS;
paul718e3742002-12-13 20:15:29 +00001126
paul68980082003-03-25 05:07:42 +00001127 area = ospf_area_get (ospf, area_id, format);
paul718e3742002-12-13 20:15:29 +00001128 area->no_summary = 1;
1129
1130 return 1;
1131}
1132
1133int
1134ospf_area_no_summary_unset (struct ospf *ospf, struct in_addr area_id)
1135{
1136 struct ospf_area *area;
1137
paul68980082003-03-25 05:07:42 +00001138 area = ospf_area_lookup_by_area_id (ospf, area_id);
paul718e3742002-12-13 20:15:29 +00001139 if (area == NULL)
1140 return 0;
1141
1142 area->no_summary = 0;
paul68980082003-03-25 05:07:42 +00001143 ospf_area_check_free (ospf, area_id);
paul718e3742002-12-13 20:15:29 +00001144
1145 return 1;
1146}
1147
1148int
1149ospf_area_nssa_set (struct ospf *ospf, struct in_addr area_id)
1150{
1151 struct ospf_area *area;
paul147193a2003-04-19 00:31:59 +00001152 int format = OSPF_AREA_ID_FORMAT_ADDRESS;
paul718e3742002-12-13 20:15:29 +00001153
paul68980082003-03-25 05:07:42 +00001154 area = ospf_area_get (ospf, area_id, format);
paul718e3742002-12-13 20:15:29 +00001155 if (ospf_area_vlink_count (ospf, area))
1156 return 0;
1157
1158 if (area->external_routing != OSPF_AREA_NSSA)
1159 {
1160 ospf_area_type_set (area, OSPF_AREA_NSSA);
1161 ospf->anyNSSA++;
1162 }
1163
paul084c7842003-06-22 08:35:18 +00001164 /* set NSSA area defaults */
1165 area->no_summary = 0;
1166 area->NSSATranslatorRole = OSPF_NSSA_ROLE_CANDIDATE;
pauld4a53d52003-07-12 21:30:57 +00001167 area->NSSATranslatorState = OSPF_NSSA_TRANSLATE_DISABLED;
paul084c7842003-06-22 08:35:18 +00001168 area->NSSATranslatorStabilityInterval = OSPF_NSSA_TRANS_STABLE_DEFAULT;
1169
paul718e3742002-12-13 20:15:29 +00001170 return 1;
1171}
1172
1173int
1174ospf_area_nssa_unset (struct ospf *ospf, struct in_addr area_id)
1175{
1176 struct ospf_area *area;
1177
paul68980082003-03-25 05:07:42 +00001178 area = ospf_area_lookup_by_area_id (ospf, area_id);
paul718e3742002-12-13 20:15:29 +00001179 if (area == NULL)
1180 return 0;
1181
1182 if (area->external_routing == OSPF_AREA_NSSA)
1183 {
1184 ospf->anyNSSA--;
1185 ospf_area_type_set (area, OSPF_AREA_DEFAULT);
1186 }
1187
paul68980082003-03-25 05:07:42 +00001188 ospf_area_check_free (ospf, area_id);
paul718e3742002-12-13 20:15:29 +00001189
1190 return 1;
1191}
1192
1193int
1194ospf_area_nssa_translator_role_set (struct ospf *ospf, struct in_addr area_id,
1195 int role)
1196{
1197 struct ospf_area *area;
1198
paul68980082003-03-25 05:07:42 +00001199 area = ospf_area_lookup_by_area_id (ospf, area_id);
paul718e3742002-12-13 20:15:29 +00001200 if (area == NULL)
1201 return 0;
1202
paul084c7842003-06-22 08:35:18 +00001203 area->NSSATranslatorRole = role;
paul718e3742002-12-13 20:15:29 +00001204
1205 return 1;
1206}
1207
paul4dadc292005-05-06 21:37:42 +00001208/* XXX: unused? Leave for symmetry? */
1209static int
paul718e3742002-12-13 20:15:29 +00001210ospf_area_nssa_translator_role_unset (struct ospf *ospf,
1211 struct in_addr area_id)
1212{
1213 struct ospf_area *area;
1214
paul68980082003-03-25 05:07:42 +00001215 area = ospf_area_lookup_by_area_id (ospf, area_id);
paul718e3742002-12-13 20:15:29 +00001216 if (area == NULL)
1217 return 0;
1218
paul084c7842003-06-22 08:35:18 +00001219 area->NSSATranslatorRole = OSPF_NSSA_ROLE_CANDIDATE;
paul718e3742002-12-13 20:15:29 +00001220
paul68980082003-03-25 05:07:42 +00001221 ospf_area_check_free (ospf, area_id);
paul718e3742002-12-13 20:15:29 +00001222
1223 return 1;
1224}
1225
1226int
paul68980082003-03-25 05:07:42 +00001227ospf_area_export_list_set (struct ospf *ospf,
paul6c835672004-10-11 11:00:30 +00001228 struct ospf_area *area, const char *list_name)
paul718e3742002-12-13 20:15:29 +00001229{
1230 struct access_list *list;
1231 list = access_list_lookup (AFI_IP, list_name);
1232
1233 EXPORT_LIST (area) = list;
1234
1235 if (EXPORT_NAME (area))
1236 free (EXPORT_NAME (area));
1237
1238 EXPORT_NAME (area) = strdup (list_name);
paul68980082003-03-25 05:07:42 +00001239 ospf_schedule_abr_task (ospf);
paul718e3742002-12-13 20:15:29 +00001240
1241 return 1;
1242}
1243
1244int
paul68980082003-03-25 05:07:42 +00001245ospf_area_export_list_unset (struct ospf *ospf, struct ospf_area * area)
paul718e3742002-12-13 20:15:29 +00001246{
1247
1248 EXPORT_LIST (area) = 0;
1249
1250 if (EXPORT_NAME (area))
1251 free (EXPORT_NAME (area));
1252
1253 EXPORT_NAME (area) = NULL;
1254
paul68980082003-03-25 05:07:42 +00001255 ospf_area_check_free (ospf, area->area_id);
paul718e3742002-12-13 20:15:29 +00001256
paul68980082003-03-25 05:07:42 +00001257 ospf_schedule_abr_task (ospf);
paul718e3742002-12-13 20:15:29 +00001258
1259 return 1;
1260}
1261
1262int
paul6c835672004-10-11 11:00:30 +00001263ospf_area_import_list_set (struct ospf *ospf, struct ospf_area *area,
1264 const char *name)
paul718e3742002-12-13 20:15:29 +00001265{
1266 struct access_list *list;
1267 list = access_list_lookup (AFI_IP, name);
1268
1269 IMPORT_LIST (area) = list;
1270
1271 if (IMPORT_NAME (area))
1272 free (IMPORT_NAME (area));
1273
1274 IMPORT_NAME (area) = strdup (name);
paul68980082003-03-25 05:07:42 +00001275 ospf_schedule_abr_task (ospf);
paul718e3742002-12-13 20:15:29 +00001276
1277 return 1;
1278}
1279
1280int
paul68980082003-03-25 05:07:42 +00001281ospf_area_import_list_unset (struct ospf *ospf, struct ospf_area * area)
paul718e3742002-12-13 20:15:29 +00001282{
1283 IMPORT_LIST (area) = 0;
1284
1285 if (IMPORT_NAME (area))
1286 free (IMPORT_NAME (area));
1287
1288 IMPORT_NAME (area) = NULL;
paul68980082003-03-25 05:07:42 +00001289 ospf_area_check_free (ospf, area->area_id);
paul718e3742002-12-13 20:15:29 +00001290
paul68980082003-03-25 05:07:42 +00001291 ospf_schedule_abr_task (ospf);
paul718e3742002-12-13 20:15:29 +00001292
1293 return 1;
1294}
1295
1296int
paul718e3742002-12-13 20:15:29 +00001297ospf_timers_refresh_set (struct ospf *ospf, int interval)
1298{
1299 int time_left;
1300
1301 if (ospf->lsa_refresh_interval == interval)
1302 return 1;
1303
1304 time_left = ospf->lsa_refresh_interval -
Paul Jakma2518efd2006-08-27 06:49:29 +00001305 (quagga_time (NULL) - ospf->lsa_refresher_started);
paul718e3742002-12-13 20:15:29 +00001306
1307 if (time_left > interval)
1308 {
1309 OSPF_TIMER_OFF (ospf->t_lsa_refresher);
1310 ospf->t_lsa_refresher =
1311 thread_add_timer (master, ospf_lsa_refresh_walker, ospf, interval);
1312 }
1313 ospf->lsa_refresh_interval = interval;
1314
1315 return 1;
1316}
1317
1318int
1319ospf_timers_refresh_unset (struct ospf *ospf)
1320{
1321 int time_left;
1322
1323 time_left = ospf->lsa_refresh_interval -
Paul Jakma2518efd2006-08-27 06:49:29 +00001324 (quagga_time (NULL) - ospf->lsa_refresher_started);
paul718e3742002-12-13 20:15:29 +00001325
1326 if (time_left > OSPF_LSA_REFRESH_INTERVAL_DEFAULT)
1327 {
1328 OSPF_TIMER_OFF (ospf->t_lsa_refresher);
1329 ospf->t_lsa_refresher =
1330 thread_add_timer (master, ospf_lsa_refresh_walker, ospf,
1331 OSPF_LSA_REFRESH_INTERVAL_DEFAULT);
1332 }
1333
1334 ospf->lsa_refresh_interval = OSPF_LSA_REFRESH_INTERVAL_DEFAULT;
1335
1336 return 1;
1337}
1338
1339
paul4dadc292005-05-06 21:37:42 +00001340static struct ospf_nbr_nbma *
1341ospf_nbr_nbma_new (void)
paul718e3742002-12-13 20:15:29 +00001342{
1343 struct ospf_nbr_nbma *nbr_nbma;
1344
Stephen Hemminger393deb92008-08-18 14:13:29 -07001345 nbr_nbma = XCALLOC (MTYPE_OSPF_NEIGHBOR_STATIC,
paul718e3742002-12-13 20:15:29 +00001346 sizeof (struct ospf_nbr_nbma));
paul718e3742002-12-13 20:15:29 +00001347
1348 nbr_nbma->priority = OSPF_NEIGHBOR_PRIORITY_DEFAULT;
1349 nbr_nbma->v_poll = OSPF_POLL_INTERVAL_DEFAULT;
1350
1351 return nbr_nbma;
1352}
1353
paul4dadc292005-05-06 21:37:42 +00001354static void
paul718e3742002-12-13 20:15:29 +00001355ospf_nbr_nbma_free (struct ospf_nbr_nbma *nbr_nbma)
1356{
1357 XFREE (MTYPE_OSPF_NEIGHBOR_STATIC, nbr_nbma);
1358}
1359
paul4dadc292005-05-06 21:37:42 +00001360static void
paul718e3742002-12-13 20:15:29 +00001361ospf_nbr_nbma_delete (struct ospf *ospf, struct ospf_nbr_nbma *nbr_nbma)
1362{
1363 struct route_node *rn;
1364 struct prefix_ipv4 p;
1365
1366 p.family = AF_INET;
1367 p.prefix = nbr_nbma->addr;
1368 p.prefixlen = IPV4_MAX_BITLEN;
1369
1370 rn = route_node_lookup (ospf->nbr_nbma, (struct prefix *)&p);
1371 if (rn)
1372 {
1373 ospf_nbr_nbma_free (rn->info);
1374 rn->info = NULL;
1375 route_unlock_node (rn);
1376 route_unlock_node (rn);
1377 }
1378}
1379
paul4dadc292005-05-06 21:37:42 +00001380static void
paul718e3742002-12-13 20:15:29 +00001381ospf_nbr_nbma_down (struct ospf_nbr_nbma *nbr_nbma)
1382{
1383 OSPF_TIMER_OFF (nbr_nbma->t_poll);
1384
1385 if (nbr_nbma->nbr)
1386 {
1387 nbr_nbma->nbr->nbr_nbma = NULL;
1388 OSPF_NSM_EVENT_EXECUTE (nbr_nbma->nbr, NSM_KillNbr);
1389 }
1390
1391 if (nbr_nbma->oi)
1392 listnode_delete (nbr_nbma->oi->nbr_nbma, nbr_nbma);
1393}
1394
paul4dadc292005-05-06 21:37:42 +00001395static void
paul718e3742002-12-13 20:15:29 +00001396ospf_nbr_nbma_add (struct ospf_nbr_nbma *nbr_nbma,
1397 struct ospf_interface *oi)
1398{
1399 struct ospf_neighbor *nbr;
1400 struct route_node *rn;
1401 struct prefix p;
1402
1403 if (oi->type != OSPF_IFTYPE_NBMA)
1404 return;
1405
1406 if (nbr_nbma->nbr != NULL)
1407 return;
1408
1409 if (IPV4_ADDR_SAME (&oi->nbr_self->address.u.prefix4, &nbr_nbma->addr))
1410 return;
1411
1412 nbr_nbma->oi = oi;
1413 listnode_add (oi->nbr_nbma, nbr_nbma);
1414
1415 /* Get neighbor information from table. */
1416 p.family = AF_INET;
1417 p.prefixlen = IPV4_MAX_BITLEN;
1418 p.u.prefix4 = nbr_nbma->addr;
1419
1420 rn = route_node_get (oi->nbrs, (struct prefix *)&p);
1421 if (rn->info)
1422 {
1423 nbr = rn->info;
1424 nbr->nbr_nbma = nbr_nbma;
1425 nbr_nbma->nbr = nbr;
1426
1427 route_unlock_node (rn);
1428 }
1429 else
1430 {
1431 nbr = rn->info = ospf_nbr_new (oi);
1432 nbr->state = NSM_Down;
1433 nbr->src = nbr_nbma->addr;
1434 nbr->nbr_nbma = nbr_nbma;
1435 nbr->priority = nbr_nbma->priority;
1436 nbr->address = p;
1437
1438 nbr_nbma->nbr = nbr;
1439
1440 OSPF_NSM_EVENT_EXECUTE (nbr, NSM_Start);
1441 }
1442}
1443
1444void
paul68980082003-03-25 05:07:42 +00001445ospf_nbr_nbma_if_update (struct ospf *ospf, struct ospf_interface *oi)
paul718e3742002-12-13 20:15:29 +00001446{
1447 struct ospf_nbr_nbma *nbr_nbma;
1448 struct route_node *rn;
1449 struct prefix_ipv4 p;
1450
1451 if (oi->type != OSPF_IFTYPE_NBMA)
1452 return;
1453
paul68980082003-03-25 05:07:42 +00001454 for (rn = route_top (ospf->nbr_nbma); rn; rn = route_next (rn))
paul718e3742002-12-13 20:15:29 +00001455 if ((nbr_nbma = rn->info))
1456 if (nbr_nbma->oi == NULL && nbr_nbma->nbr == NULL)
1457 {
1458 p.family = AF_INET;
1459 p.prefix = nbr_nbma->addr;
1460 p.prefixlen = IPV4_MAX_BITLEN;
1461
1462 if (prefix_match (oi->address, (struct prefix *)&p))
1463 ospf_nbr_nbma_add (nbr_nbma, oi);
1464 }
1465}
1466
1467struct ospf_nbr_nbma *
1468ospf_nbr_nbma_lookup (struct ospf *ospf, struct in_addr nbr_addr)
1469{
1470 struct route_node *rn;
1471 struct prefix_ipv4 p;
1472
1473 p.family = AF_INET;
1474 p.prefix = nbr_addr;
1475 p.prefixlen = IPV4_MAX_BITLEN;
1476
1477 rn = route_node_lookup (ospf->nbr_nbma, (struct prefix *)&p);
1478 if (rn)
1479 {
1480 route_unlock_node (rn);
1481 return rn->info;
1482 }
1483 return NULL;
1484}
1485
1486struct ospf_nbr_nbma *
paul68980082003-03-25 05:07:42 +00001487ospf_nbr_nbma_lookup_next (struct ospf *ospf, struct in_addr *addr, int first)
paul718e3742002-12-13 20:15:29 +00001488{
1489#if 0
1490 struct ospf_nbr_nbma *nbr_nbma;
hasso52dc7ee2004-09-23 19:18:23 +00001491 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00001492#endif
1493
paul68980082003-03-25 05:07:42 +00001494 if (ospf == NULL)
paul718e3742002-12-13 20:15:29 +00001495 return NULL;
1496
1497#if 0
paul1eb8ef22005-04-07 07:30:20 +00001498 for (ALL_LIST_ELEMENTS_RO (ospf->nbr_nbma, node, nbr_nbma))
paul718e3742002-12-13 20:15:29 +00001499 {
paul718e3742002-12-13 20:15:29 +00001500 if (first)
1501 {
1502 *addr = nbr_nbma->addr;
1503 return nbr_nbma;
1504 }
1505 else if (ntohl (nbr_nbma->addr.s_addr) > ntohl (addr->s_addr))
1506 {
1507 *addr = nbr_nbma->addr;
1508 return nbr_nbma;
1509 }
1510 }
1511#endif
1512 return NULL;
1513}
1514
1515int
1516ospf_nbr_nbma_set (struct ospf *ospf, struct in_addr nbr_addr)
1517{
1518 struct ospf_nbr_nbma *nbr_nbma;
1519 struct ospf_interface *oi;
1520 struct prefix_ipv4 p;
1521 struct route_node *rn;
hasso52dc7ee2004-09-23 19:18:23 +00001522 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00001523
1524 nbr_nbma = ospf_nbr_nbma_lookup (ospf, nbr_addr);
1525 if (nbr_nbma)
1526 return 0;
1527
1528 nbr_nbma = ospf_nbr_nbma_new ();
1529 nbr_nbma->addr = nbr_addr;
1530
1531 p.family = AF_INET;
1532 p.prefix = nbr_addr;
1533 p.prefixlen = IPV4_MAX_BITLEN;
1534
1535 rn = route_node_get (ospf->nbr_nbma, (struct prefix *)&p);
1536 rn->info = nbr_nbma;
1537
paul1eb8ef22005-04-07 07:30:20 +00001538 for (ALL_LIST_ELEMENTS_RO (ospf->oiflist, node, oi))
paul718e3742002-12-13 20:15:29 +00001539 {
paul718e3742002-12-13 20:15:29 +00001540 if (oi->type == OSPF_IFTYPE_NBMA)
1541 if (prefix_match (oi->address, (struct prefix *)&p))
1542 {
1543 ospf_nbr_nbma_add (nbr_nbma, oi);
1544 break;
1545 }
1546 }
1547
1548 return 1;
1549}
1550
1551int
1552ospf_nbr_nbma_unset (struct ospf *ospf, struct in_addr nbr_addr)
1553{
1554 struct ospf_nbr_nbma *nbr_nbma;
1555
1556 nbr_nbma = ospf_nbr_nbma_lookup (ospf, nbr_addr);
1557 if (nbr_nbma == NULL)
1558 return 0;
1559
1560 ospf_nbr_nbma_down (nbr_nbma);
1561 ospf_nbr_nbma_delete (ospf, nbr_nbma);
1562
1563 return 1;
1564}
1565
1566int
1567ospf_nbr_nbma_priority_set (struct ospf *ospf, struct in_addr nbr_addr,
1568 u_char priority)
1569{
1570 struct ospf_nbr_nbma *nbr_nbma;
1571
1572 nbr_nbma = ospf_nbr_nbma_lookup (ospf, nbr_addr);
1573 if (nbr_nbma == NULL)
1574 return 0;
1575
1576 if (nbr_nbma->priority != priority)
1577 nbr_nbma->priority = priority;
1578
1579 return 1;
1580}
1581
1582int
1583ospf_nbr_nbma_priority_unset (struct ospf *ospf, struct in_addr nbr_addr)
1584{
1585 struct ospf_nbr_nbma *nbr_nbma;
1586
1587 nbr_nbma = ospf_nbr_nbma_lookup (ospf, nbr_addr);
1588 if (nbr_nbma == NULL)
1589 return 0;
1590
1591 if (nbr_nbma != OSPF_NEIGHBOR_PRIORITY_DEFAULT)
1592 nbr_nbma->priority = OSPF_NEIGHBOR_PRIORITY_DEFAULT;
1593
1594 return 1;
1595}
1596
1597int
1598ospf_nbr_nbma_poll_interval_set (struct ospf *ospf, struct in_addr nbr_addr,
paul6c835672004-10-11 11:00:30 +00001599 unsigned int interval)
paul718e3742002-12-13 20:15:29 +00001600{
1601 struct ospf_nbr_nbma *nbr_nbma;
1602
1603 nbr_nbma = ospf_nbr_nbma_lookup (ospf, nbr_addr);
1604 if (nbr_nbma == NULL)
1605 return 0;
1606
1607 if (nbr_nbma->v_poll != interval)
1608 {
1609 nbr_nbma->v_poll = interval;
1610 if (nbr_nbma->oi && ospf_if_is_up (nbr_nbma->oi))
1611 {
1612 OSPF_TIMER_OFF (nbr_nbma->t_poll);
1613 OSPF_POLL_TIMER_ON (nbr_nbma->t_poll, ospf_poll_timer,
1614 nbr_nbma->v_poll);
1615 }
1616 }
1617
1618 return 1;
1619}
1620
1621int
1622ospf_nbr_nbma_poll_interval_unset (struct ospf *ospf, struct in_addr addr)
1623{
1624 struct ospf_nbr_nbma *nbr_nbma;
1625
1626 nbr_nbma = ospf_nbr_nbma_lookup (ospf, addr);
1627 if (nbr_nbma == NULL)
1628 return 0;
1629
1630 if (nbr_nbma->v_poll != OSPF_POLL_INTERVAL_DEFAULT)
1631 nbr_nbma->v_poll = OSPF_POLL_INTERVAL_DEFAULT;
1632
1633 return 1;
1634}
1635
paul718e3742002-12-13 20:15:29 +00001636void
paul020709f2003-04-04 02:44:16 +00001637ospf_master_init ()
1638{
1639 memset (&ospf_master, 0, sizeof (struct ospf_master));
1640
1641 om = &ospf_master;
1642 om->ospf = list_new ();
1643 om->master = thread_master_create ();
Paul Jakma2518efd2006-08-27 06:49:29 +00001644 om->start_time = quagga_time (NULL);
paul020709f2003-04-04 02:44:16 +00001645}