blob: c250fe9e731e9acc747733ee09f5000fdd6feadc [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
Stephen Hemmingera80e20d2011-12-06 23:54:17 +04001208#if 0
paul4dadc292005-05-06 21:37:42 +00001209/* XXX: unused? Leave for symmetry? */
1210static int
paul718e3742002-12-13 20:15:29 +00001211ospf_area_nssa_translator_role_unset (struct ospf *ospf,
1212 struct in_addr area_id)
1213{
1214 struct ospf_area *area;
1215
paul68980082003-03-25 05:07:42 +00001216 area = ospf_area_lookup_by_area_id (ospf, area_id);
paul718e3742002-12-13 20:15:29 +00001217 if (area == NULL)
1218 return 0;
1219
paul084c7842003-06-22 08:35:18 +00001220 area->NSSATranslatorRole = OSPF_NSSA_ROLE_CANDIDATE;
paul718e3742002-12-13 20:15:29 +00001221
paul68980082003-03-25 05:07:42 +00001222 ospf_area_check_free (ospf, area_id);
paul718e3742002-12-13 20:15:29 +00001223
1224 return 1;
1225}
Stephen Hemmingera80e20d2011-12-06 23:54:17 +04001226#endif
paul718e3742002-12-13 20:15:29 +00001227
1228int
paul68980082003-03-25 05:07:42 +00001229ospf_area_export_list_set (struct ospf *ospf,
paul6c835672004-10-11 11:00:30 +00001230 struct ospf_area *area, const char *list_name)
paul718e3742002-12-13 20:15:29 +00001231{
1232 struct access_list *list;
1233 list = access_list_lookup (AFI_IP, list_name);
1234
1235 EXPORT_LIST (area) = list;
1236
1237 if (EXPORT_NAME (area))
1238 free (EXPORT_NAME (area));
1239
1240 EXPORT_NAME (area) = strdup (list_name);
paul68980082003-03-25 05:07:42 +00001241 ospf_schedule_abr_task (ospf);
paul718e3742002-12-13 20:15:29 +00001242
1243 return 1;
1244}
1245
1246int
paul68980082003-03-25 05:07:42 +00001247ospf_area_export_list_unset (struct ospf *ospf, struct ospf_area * area)
paul718e3742002-12-13 20:15:29 +00001248{
1249
1250 EXPORT_LIST (area) = 0;
1251
1252 if (EXPORT_NAME (area))
1253 free (EXPORT_NAME (area));
1254
1255 EXPORT_NAME (area) = NULL;
1256
paul68980082003-03-25 05:07:42 +00001257 ospf_area_check_free (ospf, area->area_id);
paul718e3742002-12-13 20:15:29 +00001258
paul68980082003-03-25 05:07:42 +00001259 ospf_schedule_abr_task (ospf);
paul718e3742002-12-13 20:15:29 +00001260
1261 return 1;
1262}
1263
1264int
paul6c835672004-10-11 11:00:30 +00001265ospf_area_import_list_set (struct ospf *ospf, struct ospf_area *area,
1266 const char *name)
paul718e3742002-12-13 20:15:29 +00001267{
1268 struct access_list *list;
1269 list = access_list_lookup (AFI_IP, name);
1270
1271 IMPORT_LIST (area) = list;
1272
1273 if (IMPORT_NAME (area))
1274 free (IMPORT_NAME (area));
1275
1276 IMPORT_NAME (area) = strdup (name);
paul68980082003-03-25 05:07:42 +00001277 ospf_schedule_abr_task (ospf);
paul718e3742002-12-13 20:15:29 +00001278
1279 return 1;
1280}
1281
1282int
paul68980082003-03-25 05:07:42 +00001283ospf_area_import_list_unset (struct ospf *ospf, struct ospf_area * area)
paul718e3742002-12-13 20:15:29 +00001284{
1285 IMPORT_LIST (area) = 0;
1286
1287 if (IMPORT_NAME (area))
1288 free (IMPORT_NAME (area));
1289
1290 IMPORT_NAME (area) = NULL;
paul68980082003-03-25 05:07:42 +00001291 ospf_area_check_free (ospf, area->area_id);
paul718e3742002-12-13 20:15:29 +00001292
paul68980082003-03-25 05:07:42 +00001293 ospf_schedule_abr_task (ospf);
paul718e3742002-12-13 20:15:29 +00001294
1295 return 1;
1296}
1297
1298int
paul718e3742002-12-13 20:15:29 +00001299ospf_timers_refresh_set (struct ospf *ospf, int interval)
1300{
1301 int time_left;
1302
1303 if (ospf->lsa_refresh_interval == interval)
1304 return 1;
1305
1306 time_left = ospf->lsa_refresh_interval -
Paul Jakma2518efd2006-08-27 06:49:29 +00001307 (quagga_time (NULL) - ospf->lsa_refresher_started);
paul718e3742002-12-13 20:15:29 +00001308
1309 if (time_left > interval)
1310 {
1311 OSPF_TIMER_OFF (ospf->t_lsa_refresher);
1312 ospf->t_lsa_refresher =
1313 thread_add_timer (master, ospf_lsa_refresh_walker, ospf, interval);
1314 }
1315 ospf->lsa_refresh_interval = interval;
1316
1317 return 1;
1318}
1319
1320int
1321ospf_timers_refresh_unset (struct ospf *ospf)
1322{
1323 int time_left;
1324
1325 time_left = ospf->lsa_refresh_interval -
Paul Jakma2518efd2006-08-27 06:49:29 +00001326 (quagga_time (NULL) - ospf->lsa_refresher_started);
paul718e3742002-12-13 20:15:29 +00001327
1328 if (time_left > OSPF_LSA_REFRESH_INTERVAL_DEFAULT)
1329 {
1330 OSPF_TIMER_OFF (ospf->t_lsa_refresher);
1331 ospf->t_lsa_refresher =
1332 thread_add_timer (master, ospf_lsa_refresh_walker, ospf,
1333 OSPF_LSA_REFRESH_INTERVAL_DEFAULT);
1334 }
1335
1336 ospf->lsa_refresh_interval = OSPF_LSA_REFRESH_INTERVAL_DEFAULT;
1337
1338 return 1;
1339}
1340
1341
paul4dadc292005-05-06 21:37:42 +00001342static struct ospf_nbr_nbma *
1343ospf_nbr_nbma_new (void)
paul718e3742002-12-13 20:15:29 +00001344{
1345 struct ospf_nbr_nbma *nbr_nbma;
1346
Stephen Hemminger393deb92008-08-18 14:13:29 -07001347 nbr_nbma = XCALLOC (MTYPE_OSPF_NEIGHBOR_STATIC,
paul718e3742002-12-13 20:15:29 +00001348 sizeof (struct ospf_nbr_nbma));
paul718e3742002-12-13 20:15:29 +00001349
1350 nbr_nbma->priority = OSPF_NEIGHBOR_PRIORITY_DEFAULT;
1351 nbr_nbma->v_poll = OSPF_POLL_INTERVAL_DEFAULT;
1352
1353 return nbr_nbma;
1354}
1355
paul4dadc292005-05-06 21:37:42 +00001356static void
paul718e3742002-12-13 20:15:29 +00001357ospf_nbr_nbma_free (struct ospf_nbr_nbma *nbr_nbma)
1358{
1359 XFREE (MTYPE_OSPF_NEIGHBOR_STATIC, nbr_nbma);
1360}
1361
paul4dadc292005-05-06 21:37:42 +00001362static void
paul718e3742002-12-13 20:15:29 +00001363ospf_nbr_nbma_delete (struct ospf *ospf, struct ospf_nbr_nbma *nbr_nbma)
1364{
1365 struct route_node *rn;
1366 struct prefix_ipv4 p;
1367
1368 p.family = AF_INET;
1369 p.prefix = nbr_nbma->addr;
1370 p.prefixlen = IPV4_MAX_BITLEN;
1371
1372 rn = route_node_lookup (ospf->nbr_nbma, (struct prefix *)&p);
1373 if (rn)
1374 {
1375 ospf_nbr_nbma_free (rn->info);
1376 rn->info = NULL;
1377 route_unlock_node (rn);
1378 route_unlock_node (rn);
1379 }
1380}
1381
paul4dadc292005-05-06 21:37:42 +00001382static void
paul718e3742002-12-13 20:15:29 +00001383ospf_nbr_nbma_down (struct ospf_nbr_nbma *nbr_nbma)
1384{
1385 OSPF_TIMER_OFF (nbr_nbma->t_poll);
1386
1387 if (nbr_nbma->nbr)
1388 {
1389 nbr_nbma->nbr->nbr_nbma = NULL;
1390 OSPF_NSM_EVENT_EXECUTE (nbr_nbma->nbr, NSM_KillNbr);
1391 }
1392
1393 if (nbr_nbma->oi)
1394 listnode_delete (nbr_nbma->oi->nbr_nbma, nbr_nbma);
1395}
1396
paul4dadc292005-05-06 21:37:42 +00001397static void
paul718e3742002-12-13 20:15:29 +00001398ospf_nbr_nbma_add (struct ospf_nbr_nbma *nbr_nbma,
1399 struct ospf_interface *oi)
1400{
1401 struct ospf_neighbor *nbr;
1402 struct route_node *rn;
1403 struct prefix p;
1404
1405 if (oi->type != OSPF_IFTYPE_NBMA)
1406 return;
1407
1408 if (nbr_nbma->nbr != NULL)
1409 return;
1410
1411 if (IPV4_ADDR_SAME (&oi->nbr_self->address.u.prefix4, &nbr_nbma->addr))
1412 return;
1413
1414 nbr_nbma->oi = oi;
1415 listnode_add (oi->nbr_nbma, nbr_nbma);
1416
1417 /* Get neighbor information from table. */
1418 p.family = AF_INET;
1419 p.prefixlen = IPV4_MAX_BITLEN;
1420 p.u.prefix4 = nbr_nbma->addr;
1421
1422 rn = route_node_get (oi->nbrs, (struct prefix *)&p);
1423 if (rn->info)
1424 {
1425 nbr = rn->info;
1426 nbr->nbr_nbma = nbr_nbma;
1427 nbr_nbma->nbr = nbr;
1428
1429 route_unlock_node (rn);
1430 }
1431 else
1432 {
1433 nbr = rn->info = ospf_nbr_new (oi);
1434 nbr->state = NSM_Down;
1435 nbr->src = nbr_nbma->addr;
1436 nbr->nbr_nbma = nbr_nbma;
1437 nbr->priority = nbr_nbma->priority;
1438 nbr->address = p;
1439
1440 nbr_nbma->nbr = nbr;
1441
1442 OSPF_NSM_EVENT_EXECUTE (nbr, NSM_Start);
1443 }
1444}
1445
1446void
paul68980082003-03-25 05:07:42 +00001447ospf_nbr_nbma_if_update (struct ospf *ospf, struct ospf_interface *oi)
paul718e3742002-12-13 20:15:29 +00001448{
1449 struct ospf_nbr_nbma *nbr_nbma;
1450 struct route_node *rn;
1451 struct prefix_ipv4 p;
1452
1453 if (oi->type != OSPF_IFTYPE_NBMA)
1454 return;
1455
paul68980082003-03-25 05:07:42 +00001456 for (rn = route_top (ospf->nbr_nbma); rn; rn = route_next (rn))
paul718e3742002-12-13 20:15:29 +00001457 if ((nbr_nbma = rn->info))
1458 if (nbr_nbma->oi == NULL && nbr_nbma->nbr == NULL)
1459 {
1460 p.family = AF_INET;
1461 p.prefix = nbr_nbma->addr;
1462 p.prefixlen = IPV4_MAX_BITLEN;
1463
1464 if (prefix_match (oi->address, (struct prefix *)&p))
1465 ospf_nbr_nbma_add (nbr_nbma, oi);
1466 }
1467}
1468
1469struct ospf_nbr_nbma *
1470ospf_nbr_nbma_lookup (struct ospf *ospf, struct in_addr nbr_addr)
1471{
1472 struct route_node *rn;
1473 struct prefix_ipv4 p;
1474
1475 p.family = AF_INET;
1476 p.prefix = nbr_addr;
1477 p.prefixlen = IPV4_MAX_BITLEN;
1478
1479 rn = route_node_lookup (ospf->nbr_nbma, (struct prefix *)&p);
1480 if (rn)
1481 {
1482 route_unlock_node (rn);
1483 return rn->info;
1484 }
1485 return NULL;
1486}
1487
1488struct ospf_nbr_nbma *
paul68980082003-03-25 05:07:42 +00001489ospf_nbr_nbma_lookup_next (struct ospf *ospf, struct in_addr *addr, int first)
paul718e3742002-12-13 20:15:29 +00001490{
1491#if 0
1492 struct ospf_nbr_nbma *nbr_nbma;
hasso52dc7ee2004-09-23 19:18:23 +00001493 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00001494#endif
1495
paul68980082003-03-25 05:07:42 +00001496 if (ospf == NULL)
paul718e3742002-12-13 20:15:29 +00001497 return NULL;
1498
1499#if 0
paul1eb8ef22005-04-07 07:30:20 +00001500 for (ALL_LIST_ELEMENTS_RO (ospf->nbr_nbma, node, nbr_nbma))
paul718e3742002-12-13 20:15:29 +00001501 {
paul718e3742002-12-13 20:15:29 +00001502 if (first)
1503 {
1504 *addr = nbr_nbma->addr;
1505 return nbr_nbma;
1506 }
1507 else if (ntohl (nbr_nbma->addr.s_addr) > ntohl (addr->s_addr))
1508 {
1509 *addr = nbr_nbma->addr;
1510 return nbr_nbma;
1511 }
1512 }
1513#endif
1514 return NULL;
1515}
1516
1517int
1518ospf_nbr_nbma_set (struct ospf *ospf, struct in_addr nbr_addr)
1519{
1520 struct ospf_nbr_nbma *nbr_nbma;
1521 struct ospf_interface *oi;
1522 struct prefix_ipv4 p;
1523 struct route_node *rn;
hasso52dc7ee2004-09-23 19:18:23 +00001524 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00001525
1526 nbr_nbma = ospf_nbr_nbma_lookup (ospf, nbr_addr);
1527 if (nbr_nbma)
1528 return 0;
1529
1530 nbr_nbma = ospf_nbr_nbma_new ();
1531 nbr_nbma->addr = nbr_addr;
1532
1533 p.family = AF_INET;
1534 p.prefix = nbr_addr;
1535 p.prefixlen = IPV4_MAX_BITLEN;
1536
1537 rn = route_node_get (ospf->nbr_nbma, (struct prefix *)&p);
1538 rn->info = nbr_nbma;
1539
paul1eb8ef22005-04-07 07:30:20 +00001540 for (ALL_LIST_ELEMENTS_RO (ospf->oiflist, node, oi))
paul718e3742002-12-13 20:15:29 +00001541 {
paul718e3742002-12-13 20:15:29 +00001542 if (oi->type == OSPF_IFTYPE_NBMA)
1543 if (prefix_match (oi->address, (struct prefix *)&p))
1544 {
1545 ospf_nbr_nbma_add (nbr_nbma, oi);
1546 break;
1547 }
1548 }
1549
1550 return 1;
1551}
1552
1553int
1554ospf_nbr_nbma_unset (struct ospf *ospf, struct in_addr nbr_addr)
1555{
1556 struct ospf_nbr_nbma *nbr_nbma;
1557
1558 nbr_nbma = ospf_nbr_nbma_lookup (ospf, nbr_addr);
1559 if (nbr_nbma == NULL)
1560 return 0;
1561
1562 ospf_nbr_nbma_down (nbr_nbma);
1563 ospf_nbr_nbma_delete (ospf, nbr_nbma);
1564
1565 return 1;
1566}
1567
1568int
1569ospf_nbr_nbma_priority_set (struct ospf *ospf, struct in_addr nbr_addr,
1570 u_char priority)
1571{
1572 struct ospf_nbr_nbma *nbr_nbma;
1573
1574 nbr_nbma = ospf_nbr_nbma_lookup (ospf, nbr_addr);
1575 if (nbr_nbma == NULL)
1576 return 0;
1577
1578 if (nbr_nbma->priority != priority)
1579 nbr_nbma->priority = priority;
1580
1581 return 1;
1582}
1583
1584int
1585ospf_nbr_nbma_priority_unset (struct ospf *ospf, struct in_addr nbr_addr)
1586{
1587 struct ospf_nbr_nbma *nbr_nbma;
1588
1589 nbr_nbma = ospf_nbr_nbma_lookup (ospf, nbr_addr);
1590 if (nbr_nbma == NULL)
1591 return 0;
1592
1593 if (nbr_nbma != OSPF_NEIGHBOR_PRIORITY_DEFAULT)
1594 nbr_nbma->priority = OSPF_NEIGHBOR_PRIORITY_DEFAULT;
1595
1596 return 1;
1597}
1598
1599int
1600ospf_nbr_nbma_poll_interval_set (struct ospf *ospf, struct in_addr nbr_addr,
paul6c835672004-10-11 11:00:30 +00001601 unsigned int interval)
paul718e3742002-12-13 20:15:29 +00001602{
1603 struct ospf_nbr_nbma *nbr_nbma;
1604
1605 nbr_nbma = ospf_nbr_nbma_lookup (ospf, nbr_addr);
1606 if (nbr_nbma == NULL)
1607 return 0;
1608
1609 if (nbr_nbma->v_poll != interval)
1610 {
1611 nbr_nbma->v_poll = interval;
1612 if (nbr_nbma->oi && ospf_if_is_up (nbr_nbma->oi))
1613 {
1614 OSPF_TIMER_OFF (nbr_nbma->t_poll);
1615 OSPF_POLL_TIMER_ON (nbr_nbma->t_poll, ospf_poll_timer,
1616 nbr_nbma->v_poll);
1617 }
1618 }
1619
1620 return 1;
1621}
1622
1623int
1624ospf_nbr_nbma_poll_interval_unset (struct ospf *ospf, struct in_addr addr)
1625{
1626 struct ospf_nbr_nbma *nbr_nbma;
1627
1628 nbr_nbma = ospf_nbr_nbma_lookup (ospf, addr);
1629 if (nbr_nbma == NULL)
1630 return 0;
1631
1632 if (nbr_nbma->v_poll != OSPF_POLL_INTERVAL_DEFAULT)
1633 nbr_nbma->v_poll = OSPF_POLL_INTERVAL_DEFAULT;
1634
1635 return 1;
1636}
1637
paul718e3742002-12-13 20:15:29 +00001638void
paul020709f2003-04-04 02:44:16 +00001639ospf_master_init ()
1640{
1641 memset (&ospf_master, 0, sizeof (struct ospf_master));
1642
1643 om = &ospf_master;
1644 om->ospf = list_new ();
1645 om->master = thread_master_create ();
Paul Jakma2518efd2006-08-27 06:49:29 +00001646 om->start_time = quagga_time (NULL);
paul020709f2003-04-04 02:44:16 +00001647}