blob: 0188ffda8922b4ee96fa05d79c09827334e563f2 [file] [log] [blame]
paul718e3742002-12-13 20:15:29 +00001/* OSPF version 2 daemon program.
2 Copyright (C) 1999, 2000 Toshiaki Takada
3
4This file is part of GNU Zebra.
5
6GNU Zebra is free software; you can redistribute it and/or modify it
7under the terms of the GNU General Public License as published by the
8Free Software Foundation; either version 2, or (at your option) any
9later version.
10
11GNU Zebra is distributed in the hope that it will be useful, but
12WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with GNU Zebra; see the file COPYING. If not, write to the Free
18Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
1902111-1307, USA. */
20
21#include <zebra.h>
22
23#include "thread.h"
24#include "vty.h"
25#include "command.h"
26#include "linklist.h"
27#include "prefix.h"
28#include "table.h"
29#include "if.h"
30#include "memory.h"
31#include "stream.h"
32#include "log.h"
33#include "sockunion.h" /* for inet_aton () */
34#include "zclient.h"
35#include "plist.h"
Denis Ovsienkof102e752007-09-18 09:01:13 +000036#include "sockopt.h"
paul718e3742002-12-13 20:15:29 +000037
38#include "ospfd/ospfd.h"
39#include "ospfd/ospf_network.h"
40#include "ospfd/ospf_interface.h"
41#include "ospfd/ospf_ism.h"
42#include "ospfd/ospf_asbr.h"
43#include "ospfd/ospf_lsa.h"
44#include "ospfd/ospf_lsdb.h"
45#include "ospfd/ospf_neighbor.h"
46#include "ospfd/ospf_nsm.h"
47#include "ospfd/ospf_spf.h"
48#include "ospfd/ospf_packet.h"
49#include "ospfd/ospf_dump.h"
50#include "ospfd/ospf_zebra.h"
51#include "ospfd/ospf_abr.h"
52#include "ospfd/ospf_flood.h"
53#include "ospfd/ospf_route.h"
54#include "ospfd/ospf_ase.h"
55
paul020709f2003-04-04 02:44:16 +000056
pauledd7c242003-06-04 13:59:38 +000057
paul020709f2003-04-04 02:44:16 +000058/* OSPF process wide configuration. */
59static struct ospf_master ospf_master;
60
61/* OSPF process wide configuration pointer to export. */
62struct ospf_master *om;
paul718e3742002-12-13 20:15:29 +000063
64extern struct zclient *zclient;
hasso18a6dce2004-10-03 18:18:34 +000065extern struct in_addr router_id_zebra;
paul718e3742002-12-13 20:15:29 +000066
67
paul88d6cf32005-10-29 12:50:09 +000068static void ospf_remove_vls_through_area (struct ospf *, struct ospf_area *);
69static void ospf_network_free (struct ospf *, struct ospf_network *);
70static void ospf_area_free (struct ospf_area *);
Joakim Tjernlunda49eb302008-09-02 19:06:31 +010071static void ospf_network_run (struct prefix *, struct ospf_area *);
72static void ospf_network_run_interface (struct prefix *, struct ospf_area *,
73 struct interface *);
Stephen Hemminger917e2992009-12-03 19:07:00 +030074static int ospf_network_match_iface (const struct connected *,
75 const struct prefix *);
paul88d6cf32005-10-29 12:50:09 +000076static void ospf_finish_final (struct ospf *);
paul718e3742002-12-13 20:15:29 +000077
paul718e3742002-12-13 20:15:29 +000078#define OSPF_EXTERNAL_LSA_ORIGINATE_DELAY 1
paul88d6cf32005-10-29 12:50:09 +000079
paul718e3742002-12-13 20:15:29 +000080void
paul68980082003-03-25 05:07:42 +000081ospf_router_id_update (struct ospf *ospf)
paul718e3742002-12-13 20:15:29 +000082{
paul718e3742002-12-13 20:15:29 +000083 struct in_addr router_id, router_id_old;
paul1eb8ef22005-04-07 07:30:20 +000084 struct ospf_interface *oi;
Joakim Tjernlunda49eb302008-09-02 19:06:31 +010085 struct interface *ifp;
hasso52dc7ee2004-09-23 19:18:23 +000086 struct listnode *node;
paul718e3742002-12-13 20:15:29 +000087
88 if (IS_DEBUG_OSPF_EVENT)
ajs9b0e25c2004-12-08 19:06:51 +000089 zlog_debug ("Router-ID[OLD:%s]: Update", inet_ntoa (ospf->router_id));
paul718e3742002-12-13 20:15:29 +000090
paul68980082003-03-25 05:07:42 +000091 router_id_old = ospf->router_id;
paul718e3742002-12-13 20:15:29 +000092
Andrew J. Schorr16700082006-07-27 22:29:06 +000093 /* Select the router ID based on these priorities:
94 1. Statically assigned router ID is always the first choice.
95 2. If there is no statically assigned router ID, then try to stick
96 with the most recent value, since changing router ID's is very
97 disruptive.
98 3. Last choice: just go with whatever the zebra daemon recommends.
99 */
paul68980082003-03-25 05:07:42 +0000100 if (ospf->router_id_static.s_addr != 0)
101 router_id = ospf->router_id_static;
Andrew J. Schorr16700082006-07-27 22:29:06 +0000102 else if (ospf->router_id.s_addr != 0)
103 router_id = ospf->router_id;
paul718e3742002-12-13 20:15:29 +0000104 else
hasso18a6dce2004-10-03 18:18:34 +0000105 router_id = router_id_zebra;
paul718e3742002-12-13 20:15:29 +0000106
paul68980082003-03-25 05:07:42 +0000107 ospf->router_id = router_id;
paul718e3742002-12-13 20:15:29 +0000108
109 if (IS_DEBUG_OSPF_EVENT)
ajs9b0e25c2004-12-08 19:06:51 +0000110 zlog_debug ("Router-ID[NEW:%s]: Update", inet_ntoa (ospf->router_id));
paul718e3742002-12-13 20:15:29 +0000111
112 if (!IPV4_ADDR_SAME (&router_id_old, &router_id))
113 {
paul1eb8ef22005-04-07 07:30:20 +0000114 for (ALL_LIST_ELEMENTS_RO (ospf->oiflist, node, oi))
115 /* Update self-neighbor's router_id. */
116 oi->nbr_self->router_id = router_id;
paul718e3742002-12-13 20:15:29 +0000117
118 /* If AS-external-LSA is queued, then flush those LSAs. */
paul68980082003-03-25 05:07:42 +0000119 if (router_id_old.s_addr == 0 && ospf->external_origin)
paul718e3742002-12-13 20:15:29 +0000120 {
121 int type;
122 /* Originate each redistributed external route. */
123 for (type = 0; type < ZEBRA_ROUTE_MAX; type++)
paul68980082003-03-25 05:07:42 +0000124 if (ospf->external_origin & (1 << type))
paul718e3742002-12-13 20:15:29 +0000125 thread_add_event (master, ospf_external_lsa_originate_timer,
paul68980082003-03-25 05:07:42 +0000126 ospf, type);
paul718e3742002-12-13 20:15:29 +0000127 /* Originate Deafult. */
paul68980082003-03-25 05:07:42 +0000128 if (ospf->external_origin & (1 << ZEBRA_ROUTE_MAX))
Paul Jakma4021b602006-05-12 22:55:41 +0000129 thread_add_event (master, ospf_default_originate_timer, ospf, 0);
paul718e3742002-12-13 20:15:29 +0000130
paul68980082003-03-25 05:07:42 +0000131 ospf->external_origin = 0;
paul718e3742002-12-13 20:15:29 +0000132 }
133
Paul Jakmac363d382010-01-24 22:42:13 +0000134 /* update router-lsa's for each area */
135 ospf_router_lsa_update (ospf);
paulb29800a2005-11-20 14:50:45 +0000136
137 /* update ospf_interface's */
Joakim Tjernlunda49eb302008-09-02 19:06:31 +0100138 for (ALL_LIST_ELEMENTS_RO (om->iflist, node, ifp))
139 ospf_if_update (ospf, ifp);
paul718e3742002-12-13 20:15:29 +0000140 }
141}
paul718e3742002-12-13 20:15:29 +0000142
143/* For OSPF area sort by area id. */
paul4dadc292005-05-06 21:37:42 +0000144static int
paul718e3742002-12-13 20:15:29 +0000145ospf_area_id_cmp (struct ospf_area *a1, struct ospf_area *a2)
146{
147 if (ntohl (a1->area_id.s_addr) > ntohl (a2->area_id.s_addr))
148 return 1;
149 if (ntohl (a1->area_id.s_addr) < ntohl (a2->area_id.s_addr))
150 return -1;
151 return 0;
152}
153
154/* Allocate new ospf structure. */
paul4dadc292005-05-06 21:37:42 +0000155static struct ospf *
156ospf_new (void)
paul718e3742002-12-13 20:15:29 +0000157{
158 int i;
159
160 struct ospf *new = XCALLOC (MTYPE_OSPF_TOP, sizeof (struct ospf));
161
162 new->router_id.s_addr = htonl (0);
163 new->router_id_static.s_addr = htonl (0);
164
pauld57834f2005-07-12 20:04:22 +0000165 new->abr_type = OSPF_ABR_DEFAULT;
paul718e3742002-12-13 20:15:29 +0000166 new->oiflist = list_new ();
167 new->vlinks = list_new ();
168 new->areas = list_new ();
169 new->areas->cmp = (int (*)(void *, void *)) ospf_area_id_cmp;
170 new->networks = route_table_init ();
171 new->nbr_nbma = route_table_init ();
172
173 new->lsdb = ospf_lsdb_new ();
174
175 new->default_originate = DEFAULT_ORIGINATE_NONE;
176
Paul Jakma7ffa8fa2006-10-22 20:07:53 +0000177 new->passive_interface_default = OSPF_IF_ACTIVE;
178
paul718e3742002-12-13 20:15:29 +0000179 new->new_external_route = route_table_init ();
180 new->old_external_route = route_table_init ();
181 new->external_lsas = route_table_init ();
paul88d6cf32005-10-29 12:50:09 +0000182
183 new->stub_router_startup_time = OSPF_STUB_ROUTER_UNCONFIGURED;
paul31a59762005-11-14 11:11:11 +0000184 new->stub_router_shutdown_time = OSPF_STUB_ROUTER_UNCONFIGURED;
paul88d6cf32005-10-29 12:50:09 +0000185
paul718e3742002-12-13 20:15:29 +0000186 /* Distribute parameter init. */
187 for (i = 0; i <= ZEBRA_ROUTE_MAX; i++)
188 {
189 new->dmetric[i].type = -1;
190 new->dmetric[i].value = -1;
191 }
192 new->default_metric = -1;
193 new->ref_bandwidth = OSPF_DEFAULT_REF_BANDWIDTH;
194
195 /* SPF timer value init. */
196 new->spf_delay = OSPF_SPF_DELAY_DEFAULT;
197 new->spf_holdtime = OSPF_SPF_HOLDTIME_DEFAULT;
pauld24f6e22005-10-21 09:23:12 +0000198 new->spf_max_holdtime = OSPF_SPF_MAX_HOLDTIME_DEFAULT;
199 new->spf_hold_multiplier = 1;
paul718e3742002-12-13 20:15:29 +0000200
201 /* MaxAge init. */
Paul Jakma02d942c2010-01-24 23:36:20 +0000202 new->maxage_delay = OSFP_LSA_MAXAGE_REMOVE_DELAY_DEFAULT;
paul718e3742002-12-13 20:15:29 +0000203 new->maxage_lsa = list_new ();
204 new->t_maxage_walker =
205 thread_add_timer (master, ospf_lsa_maxage_walker,
paul68980082003-03-25 05:07:42 +0000206 new, OSPF_LSA_MAXAGE_CHECK_INTERVAL);
paul718e3742002-12-13 20:15:29 +0000207
208 /* Distance table init. */
209 new->distance_table = route_table_init ();
210
211 new->lsa_refresh_queue.index = 0;
212 new->lsa_refresh_interval = OSPF_LSA_REFRESH_INTERVAL_DEFAULT;
213 new->t_lsa_refresher = thread_add_timer (master, ospf_lsa_refresh_walker,
214 new, new->lsa_refresh_interval);
Paul Jakma2518efd2006-08-27 06:49:29 +0000215 new->lsa_refresher_started = quagga_time (NULL);
paul718e3742002-12-13 20:15:29 +0000216
ajs5c333492005-02-23 15:43:01 +0000217 if ((new->fd = ospf_sock_init()) < 0)
218 {
219 zlog_err("ospf_new: fatal error: ospf_sock_init was unable to open "
220 "a socket");
221 exit(1);
222 }
Denis Ovsienkof102e752007-09-18 09:01:13 +0000223 new->maxsndbuflen = getsockopt_so_sendbuf (new->fd);
224 if (IS_DEBUG_OSPF (zebra, ZEBRA_INTERFACE))
225 zlog_debug ("%s: starting with OSPF send buffer size %d",
226 __func__, new->maxsndbuflen);
ajs5c333492005-02-23 15:43:01 +0000227 if ((new->ibuf = stream_new(OSPF_MAX_PACKET_SIZE+1)) == NULL)
228 {
229 zlog_err("ospf_new: fatal error: stream_new(%u) failed allocating ibuf",
230 OSPF_MAX_PACKET_SIZE+1);
231 exit(1);
232 }
233 new->t_read = thread_add_read (master, ospf_read, new, new->fd);
paul718e3742002-12-13 20:15:29 +0000234 new->oi_write_q = list_new ();
235
236 return new;
237}
238
239struct ospf *
paul020709f2003-04-04 02:44:16 +0000240ospf_lookup ()
241{
242 if (listcount (om->ospf) == 0)
243 return NULL;
244
paul1eb8ef22005-04-07 07:30:20 +0000245 return listgetdata (listhead (om->ospf));
paul020709f2003-04-04 02:44:16 +0000246}
247
paul4dadc292005-05-06 21:37:42 +0000248static void
paul020709f2003-04-04 02:44:16 +0000249ospf_add (struct ospf *ospf)
250{
251 listnode_add (om->ospf, ospf);
252}
253
paul4dadc292005-05-06 21:37:42 +0000254static void
paul020709f2003-04-04 02:44:16 +0000255ospf_delete (struct ospf *ospf)
256{
257 listnode_delete (om->ospf, ospf);
258}
259
260struct ospf *
paul718e3742002-12-13 20:15:29 +0000261ospf_get ()
262{
paul020709f2003-04-04 02:44:16 +0000263 struct ospf *ospf;
paul718e3742002-12-13 20:15:29 +0000264
paul020709f2003-04-04 02:44:16 +0000265 ospf = ospf_lookup ();
266 if (ospf == NULL)
267 {
268 ospf = ospf_new ();
269 ospf_add (ospf);
paul718e3742002-12-13 20:15:29 +0000270
paul020709f2003-04-04 02:44:16 +0000271 if (ospf->router_id_static.s_addr == 0)
272 ospf_router_id_update (ospf);
paul718e3742002-12-13 20:15:29 +0000273
274#ifdef HAVE_OPAQUE_LSA
paul020709f2003-04-04 02:44:16 +0000275 ospf_opaque_type11_lsa_init (ospf);
paul718e3742002-12-13 20:15:29 +0000276#endif /* HAVE_OPAQUE_LSA */
paul020709f2003-04-04 02:44:16 +0000277 }
paul68980082003-03-25 05:07:42 +0000278
279 return ospf;
paul718e3742002-12-13 20:15:29 +0000280}
paul88d6cf32005-10-29 12:50:09 +0000281
paulc9c93d52005-11-26 13:31:11 +0000282/* Handle the second half of deferred shutdown. This is called either
283 * from the deferred-shutdown timer thread, or directly through
284 * ospf_deferred_shutdown_check.
paul88d6cf32005-10-29 12:50:09 +0000285 *
286 * Function is to cleanup G-R state, if required then call ospf_finish_final
287 * to complete shutdown of this ospf instance. Possibly exit if the
288 * whole process is being shutdown and this was the last OSPF instance.
289 */
290static void
paulc9c93d52005-11-26 13:31:11 +0000291ospf_deferred_shutdown_finish (struct ospf *ospf)
paul88d6cf32005-10-29 12:50:09 +0000292{
293 ospf->stub_router_shutdown_time = OSPF_STUB_ROUTER_UNCONFIGURED;
paulc9c93d52005-11-26 13:31:11 +0000294 OSPF_TIMER_OFF (ospf->t_deferred_shutdown);
paul88d6cf32005-10-29 12:50:09 +0000295
296 ospf_finish_final (ospf);
297
298 /* *ospf is now invalid */
299
300 /* ospfd being shut-down? If so, was this the last ospf instance? */
301 if (CHECK_FLAG (om->options, OSPF_MASTER_SHUTDOWN)
302 && (listcount (om->ospf) == 0))
303 exit (0);
304
305 return;
306}
307
308/* Timer thread for G-R */
309static int
paulc9c93d52005-11-26 13:31:11 +0000310ospf_deferred_shutdown_timer (struct thread *t)
paul88d6cf32005-10-29 12:50:09 +0000311{
312 struct ospf *ospf = THREAD_ARG(t);
313
paulc9c93d52005-11-26 13:31:11 +0000314 ospf_deferred_shutdown_finish (ospf);
paul88d6cf32005-10-29 12:50:09 +0000315
316 return 0;
317}
318
paulc9c93d52005-11-26 13:31:11 +0000319/* Check whether deferred-shutdown must be scheduled, otherwise call
paul88d6cf32005-10-29 12:50:09 +0000320 * down directly into second-half of instance shutdown.
321 */
322static void
paulc9c93d52005-11-26 13:31:11 +0000323ospf_deferred_shutdown_check (struct ospf *ospf)
paul88d6cf32005-10-29 12:50:09 +0000324{
325 unsigned long timeout;
326 struct listnode *ln;
327 struct ospf_area *area;
328
paulc9c93d52005-11-26 13:31:11 +0000329 /* deferred shutdown already running? */
330 if (ospf->t_deferred_shutdown)
paul88d6cf32005-10-29 12:50:09 +0000331 return;
332
333 /* Should we try push out max-metric LSAs? */
334 if (ospf->stub_router_shutdown_time != OSPF_STUB_ROUTER_UNCONFIGURED)
335 {
336 for (ALL_LIST_ELEMENTS_RO (ospf->areas, ln, area))
337 {
338 SET_FLAG (area->stub_router_state, OSPF_AREA_ADMIN_STUB_ROUTED);
339
340 if (!CHECK_FLAG (area->stub_router_state, OSPF_AREA_IS_STUB_ROUTED))
Paul Jakmac363d382010-01-24 22:42:13 +0000341 ospf_router_lsa_update_area (area);
paul88d6cf32005-10-29 12:50:09 +0000342 }
343 timeout = ospf->stub_router_shutdown_time;
344 }
345 else
paulc9c93d52005-11-26 13:31:11 +0000346 {
347 /* No timer needed */
348 ospf_deferred_shutdown_finish (ospf);
349 return;
350 }
paul88d6cf32005-10-29 12:50:09 +0000351
paulc9c93d52005-11-26 13:31:11 +0000352 OSPF_TIMER_ON (ospf->t_deferred_shutdown, ospf_deferred_shutdown_timer,
paul88d6cf32005-10-29 12:50:09 +0000353 timeout);
354 return;
355}
356
357/* Shut down the entire process */
358void
359ospf_terminate (void)
360{
361 struct ospf *ospf;
362 struct listnode *node, *nnode;
363
364 /* shutdown already in progress */
365 if (CHECK_FLAG (om->options, OSPF_MASTER_SHUTDOWN))
366 return;
367
368 SET_FLAG (om->options, OSPF_MASTER_SHUTDOWN);
369
Andrew J. Schorr4056a542007-02-27 13:55:46 +0000370 /* exit immediately if OSPF not actually running */
371 if (listcount(om->ospf) == 0)
372 exit(0);
373
paul88d6cf32005-10-29 12:50:09 +0000374 for (ALL_LIST_ELEMENTS (om->ospf, node, nnode, ospf))
375 ospf_finish (ospf);
376
377 /* Deliberately go back up, hopefully to thread scheduler, as
378 * One or more ospf_finish()'s may have deferred shutdown to a timer
379 * thread
380 */
381}
paul718e3742002-12-13 20:15:29 +0000382
383void
384ospf_finish (struct ospf *ospf)
385{
paulc9c93d52005-11-26 13:31:11 +0000386 /* let deferred shutdown decide */
387 ospf_deferred_shutdown_check (ospf);
paul88d6cf32005-10-29 12:50:09 +0000388
paulc9c93d52005-11-26 13:31:11 +0000389 /* if ospf_deferred_shutdown returns, then ospf_finish_final is
paul88d6cf32005-10-29 12:50:09 +0000390 * deferred to expiry of G-S timer thread. Return back up, hopefully
391 * to thread scheduler.
392 */
paulc9c93d52005-11-26 13:31:11 +0000393 return;
paul88d6cf32005-10-29 12:50:09 +0000394}
395
396/* Final cleanup of ospf instance */
397static void
398ospf_finish_final (struct ospf *ospf)
399{
paul718e3742002-12-13 20:15:29 +0000400 struct route_node *rn;
401 struct ospf_nbr_nbma *nbr_nbma;
paul68980082003-03-25 05:07:42 +0000402 struct ospf_lsa *lsa;
paul1eb8ef22005-04-07 07:30:20 +0000403 struct ospf_interface *oi;
404 struct ospf_area *area;
405 struct ospf_vl_data *vl_data;
406 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000407 int i;
408
409#ifdef HAVE_OPAQUE_LSA
410 ospf_opaque_type11_lsa_term (ospf);
411#endif /* HAVE_OPAQUE_LSA */
paul88d6cf32005-10-29 12:50:09 +0000412
413 /* be nice if this worked, but it doesn't */
414 /*ospf_flush_self_originated_lsas_now (ospf);*/
415
416 /* Unregister redistribution */
paul718e3742002-12-13 20:15:29 +0000417 for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
paul020709f2003-04-04 02:44:16 +0000418 ospf_redistribute_unset (ospf, i);
Paul Jakma29b5a042006-08-27 08:01:20 +0000419 ospf_redistribute_default_unset (ospf);
paul718e3742002-12-13 20:15:29 +0000420
paul1eb8ef22005-04-07 07:30:20 +0000421 for (ALL_LIST_ELEMENTS (ospf->areas, node, nnode, area))
422 ospf_remove_vls_through_area (ospf, area);
paul718e3742002-12-13 20:15:29 +0000423
paul1eb8ef22005-04-07 07:30:20 +0000424 for (ALL_LIST_ELEMENTS (ospf->vlinks, node, nnode, vl_data))
425 ospf_vl_delete (ospf, vl_data);
paul718e3742002-12-13 20:15:29 +0000426
427 list_delete (ospf->vlinks);
428
429 /* Reset interface. */
paul1eb8ef22005-04-07 07:30:20 +0000430 for (ALL_LIST_ELEMENTS (ospf->oiflist, node, nnode, oi))
431 ospf_if_free (oi);
paul718e3742002-12-13 20:15:29 +0000432
433 /* Clear static neighbors */
434 for (rn = route_top (ospf->nbr_nbma); rn; rn = route_next (rn))
435 if ((nbr_nbma = rn->info))
436 {
437 OSPF_POLL_TIMER_OFF (nbr_nbma->t_poll);
438
439 if (nbr_nbma->nbr)
440 {
441 nbr_nbma->nbr->nbr_nbma = NULL;
442 nbr_nbma->nbr = NULL;
443 }
444
445 if (nbr_nbma->oi)
446 {
447 listnode_delete (nbr_nbma->oi->nbr_nbma, nbr_nbma);
448 nbr_nbma->oi = NULL;
449 }
450
451 XFREE (MTYPE_OSPF_NEIGHBOR_STATIC, nbr_nbma);
452 }
453
454 route_table_finish (ospf->nbr_nbma);
455
456 /* Clear networks and Areas. */
457 for (rn = route_top (ospf->networks); rn; rn = route_next (rn))
458 {
459 struct ospf_network *network;
460
461 if ((network = rn->info) != NULL)
462 {
paul68980082003-03-25 05:07:42 +0000463 ospf_network_free (ospf, network);
paul718e3742002-12-13 20:15:29 +0000464 rn->info = NULL;
465 route_unlock_node (rn);
466 }
467 }
468
paul1eb8ef22005-04-07 07:30:20 +0000469 for (ALL_LIST_ELEMENTS (ospf->areas, node, nnode, area))
paul718e3742002-12-13 20:15:29 +0000470 {
paul718e3742002-12-13 20:15:29 +0000471 listnode_delete (ospf->areas, area);
472 ospf_area_free (area);
473 }
474
475 /* Cancel all timers. */
476 OSPF_TIMER_OFF (ospf->t_external_lsa);
paul718e3742002-12-13 20:15:29 +0000477 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. */
paul88d6cf32005-10-29 12:50:09 +0000634 OSPF_TIMER_OFF (area->t_stub_router);
635#ifdef HAVE_OPAQUE_LSA
636 OSPF_TIMER_OFF (area->t_opaque_lsa_self);
637#endif /* HAVE_OPAQUE_LSA */
638
paul718e3742002-12-13 20:15:29 +0000639 if (OSPF_IS_AREA_BACKBONE (area))
paul68980082003-03-25 05:07:42 +0000640 area->ospf->backbone = NULL;
paul718e3742002-12-13 20:15:29 +0000641
642 XFREE (MTYPE_OSPF_AREA, area);
643}
644
645void
paul68980082003-03-25 05:07:42 +0000646ospf_area_check_free (struct ospf *ospf, struct in_addr area_id)
paul718e3742002-12-13 20:15:29 +0000647{
648 struct ospf_area *area;
649
paul68980082003-03-25 05:07:42 +0000650 area = ospf_area_lookup_by_area_id (ospf, area_id);
paul718e3742002-12-13 20:15:29 +0000651 if (area &&
652 listcount (area->oiflist) == 0 &&
653 area->ranges->top == NULL &&
654 area->shortcut_configured == OSPF_SHORTCUT_DEFAULT &&
655 area->external_routing == OSPF_AREA_DEFAULT &&
656 area->no_summary == 0 &&
657 area->default_cost == 1 &&
658 EXPORT_NAME (area) == NULL &&
659 IMPORT_NAME (area) == NULL &&
660 area->auth_type == OSPF_AUTH_NULL)
661 {
paul68980082003-03-25 05:07:42 +0000662 listnode_delete (ospf->areas, area);
paul718e3742002-12-13 20:15:29 +0000663 ospf_area_free (area);
664 }
665}
666
667struct ospf_area *
paul68980082003-03-25 05:07:42 +0000668ospf_area_get (struct ospf *ospf, struct in_addr area_id, int format)
paul718e3742002-12-13 20:15:29 +0000669{
670 struct ospf_area *area;
671
paul68980082003-03-25 05:07:42 +0000672 area = ospf_area_lookup_by_area_id (ospf, area_id);
paul718e3742002-12-13 20:15:29 +0000673 if (!area)
674 {
paul68980082003-03-25 05:07:42 +0000675 area = ospf_area_new (ospf, area_id);
paul718e3742002-12-13 20:15:29 +0000676 area->format = format;
paul68980082003-03-25 05:07:42 +0000677 listnode_add_sort (ospf->areas, area);
678 ospf_check_abr_status (ospf);
paul718e3742002-12-13 20:15:29 +0000679 }
680
681 return area;
682}
683
684struct ospf_area *
paul68980082003-03-25 05:07:42 +0000685ospf_area_lookup_by_area_id (struct ospf *ospf, struct in_addr area_id)
paul718e3742002-12-13 20:15:29 +0000686{
687 struct ospf_area *area;
hasso52dc7ee2004-09-23 19:18:23 +0000688 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000689
paul1eb8ef22005-04-07 07:30:20 +0000690 for (ALL_LIST_ELEMENTS_RO (ospf->areas, node, area))
691 if (IPV4_ADDR_SAME (&area->area_id, &area_id))
692 return area;
paul718e3742002-12-13 20:15:29 +0000693
694 return NULL;
695}
696
697void
698ospf_area_add_if (struct ospf_area *area, struct ospf_interface *oi)
699{
700 listnode_add (area->oiflist, oi);
701}
702
703void
704ospf_area_del_if (struct ospf_area *area, struct ospf_interface *oi)
705{
706 listnode_delete (area->oiflist, oi);
707}
708
709
710/* Config network statement related functions. */
paul4dadc292005-05-06 21:37:42 +0000711static struct ospf_network *
paul718e3742002-12-13 20:15:29 +0000712ospf_network_new (struct in_addr area_id, int format)
713{
714 struct ospf_network *new;
715 new = XCALLOC (MTYPE_OSPF_NETWORK, sizeof (struct ospf_network));
716
717 new->area_id = area_id;
718 new->format = format;
719
720 return new;
721}
722
Stephen Hemminger917e2992009-12-03 19:07:00 +0300723static void
paul68980082003-03-25 05:07:42 +0000724ospf_network_free (struct ospf *ospf, struct ospf_network *network)
paul718e3742002-12-13 20:15:29 +0000725{
paul68980082003-03-25 05:07:42 +0000726 ospf_area_check_free (ospf, network->area_id);
727 ospf_schedule_abr_task (ospf);
paul718e3742002-12-13 20:15:29 +0000728 XFREE (MTYPE_OSPF_NETWORK, network);
729}
730
731int
732ospf_network_set (struct ospf *ospf, struct prefix_ipv4 *p,
733 struct in_addr area_id)
734{
735 struct ospf_network *network;
736 struct ospf_area *area;
737 struct route_node *rn;
738 struct external_info *ei;
paul147193a2003-04-19 00:31:59 +0000739 int ret = OSPF_AREA_ID_FORMAT_ADDRESS;
paul718e3742002-12-13 20:15:29 +0000740
741 rn = route_node_get (ospf->networks, (struct prefix *)p);
742 if (rn->info)
743 {
744 /* There is already same network statement. */
745 route_unlock_node (rn);
746 return 0;
747 }
748
749 rn->info = network = ospf_network_new (area_id, ret);
paul68980082003-03-25 05:07:42 +0000750 area = ospf_area_get (ospf, area_id, ret);
paul718e3742002-12-13 20:15:29 +0000751
752 /* Run network config now. */
Joakim Tjernlunda49eb302008-09-02 19:06:31 +0100753 ospf_network_run ((struct prefix *)p, area);
paul718e3742002-12-13 20:15:29 +0000754
755 /* Update connected redistribute. */
756 if (ospf_is_type_redistributed (ZEBRA_ROUTE_CONNECT))
757 if (EXTERNAL_INFO (ZEBRA_ROUTE_CONNECT))
758 for (rn = route_top (EXTERNAL_INFO (ZEBRA_ROUTE_CONNECT));
759 rn; rn = route_next (rn))
760 if ((ei = rn->info) != NULL)
paul68980082003-03-25 05:07:42 +0000761 if (ospf_external_info_find_lsa (ospf, &ei->p))
762 if (!ospf_distribute_check_connected (ospf, ei))
763 ospf_external_lsa_flush (ospf, ei->type, &ei->p,
ajs5339cfd2005-09-19 13:28:05 +0000764 ei->ifindex /*, ei->nexthop */);
paul718e3742002-12-13 20:15:29 +0000765
paul68980082003-03-25 05:07:42 +0000766 ospf_area_check_free (ospf, area_id);
paul718e3742002-12-13 20:15:29 +0000767
768 return 1;
769}
770
771int
772ospf_network_unset (struct ospf *ospf, struct prefix_ipv4 *p,
773 struct in_addr area_id)
774{
775 struct route_node *rn;
776 struct ospf_network *network;
777 struct external_info *ei;
Joakim Tjernlunda49eb302008-09-02 19:06:31 +0100778 struct listnode *node, *nnode;
779 struct ospf_interface *oi;
paul718e3742002-12-13 20:15:29 +0000780
781 rn = route_node_lookup (ospf->networks, (struct prefix *)p);
782 if (rn == NULL)
783 return 0;
784
785 network = rn->info;
Stephen Hemminger965f54f2009-06-03 16:44:21 -0700786 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +0000787 if (!IPV4_ADDR_SAME (&area_id, &network->area_id))
788 return 0;
789
paul68980082003-03-25 05:07:42 +0000790 ospf_network_free (ospf, rn->info);
paul718e3742002-12-13 20:15:29 +0000791 rn->info = NULL;
Stephen Hemminger965f54f2009-06-03 16:44:21 -0700792 route_unlock_node (rn); /* initial reference */
paul718e3742002-12-13 20:15:29 +0000793
Joakim Tjernlunda49eb302008-09-02 19:06:31 +0100794 /* Find interfaces that not configured already. */
795 for (ALL_LIST_ELEMENTS (ospf->oiflist, node, nnode, oi))
796 {
797 int found = 0;
798 struct connected *co = oi->connected;
799
800 if (oi->type == OSPF_IFTYPE_VIRTUALLINK)
801 continue;
802
803 for (rn = route_top (ospf->networks); rn; rn = route_next (rn))
804 {
805 if (rn->info == NULL)
806 continue;
807
808 if (ospf_network_match_iface(co,&rn->p))
809 {
810 found = 1;
811 route_unlock_node (rn);
812 break;
813 }
814 }
815
816 if (found == 0)
817 ospf_if_free (oi);
818 }
paul718e3742002-12-13 20:15:29 +0000819
820 /* Update connected redistribute. */
821 if (ospf_is_type_redistributed (ZEBRA_ROUTE_CONNECT))
822 if (EXTERNAL_INFO (ZEBRA_ROUTE_CONNECT))
823 for (rn = route_top (EXTERNAL_INFO (ZEBRA_ROUTE_CONNECT));
824 rn; rn = route_next (rn))
825 if ((ei = rn->info) != NULL)
paul68980082003-03-25 05:07:42 +0000826 if (!ospf_external_info_find_lsa (ospf, &ei->p))
827 if (ospf_distribute_check_connected (ospf, ei))
828 ospf_external_lsa_originate (ospf, ei);
paul718e3742002-12-13 20:15:29 +0000829
830 return 1;
831}
832
paul570f7592003-01-25 06:47:41 +0000833/* Check whether interface matches given network
834 * returns: 1, true. 0, false
835 */
Stephen Hemminger917e2992009-12-03 19:07:00 +0300836static int
837ospf_network_match_iface(const struct connected *co, const struct prefix *net)
paul570f7592003-01-25 06:47:41 +0000838{
Andrew J. Schorre4529632006-12-12 19:18:21 +0000839 /* new approach: more elegant and conceptually clean */
840 return prefix_match(net, CONNECTED_PREFIX(co));
paul570f7592003-01-25 06:47:41 +0000841}
842
Stephen Hemminger917e2992009-12-03 19:07:00 +0300843static void
Joakim Tjernlunda49eb302008-09-02 19:06:31 +0100844ospf_network_run_interface (struct prefix *p, struct ospf_area *area,
845 struct interface *ifp)
846{
847 struct listnode *cnode;
848 struct connected *co;
849
850 if (memcmp (ifp->name, "VLINK", 5) == 0)
851 return;
852
853 /* if interface prefix is match specified prefix,
854 then create socket and join multicast group. */
855 for (ALL_LIST_ELEMENTS_RO (ifp->connected, cnode, co))
856 {
Joakim Tjernlundf0f63842009-07-27 12:42:29 +0200857
Joakim Tjernlunda49eb302008-09-02 19:06:31 +0100858 if (CHECK_FLAG(co->flags,ZEBRA_IFA_SECONDARY))
859 continue;
860
Joakim Tjernlunda49eb302008-09-02 19:06:31 +0100861 if (p->family == co->address->family
Joakim Tjernlundf0f63842009-07-27 12:42:29 +0200862 && ! ospf_if_table_lookup(ifp, co->address)
Joakim Tjernlunda49eb302008-09-02 19:06:31 +0100863 && ospf_network_match_iface(co,p))
864 {
865 struct ospf_interface *oi;
866
867 oi = ospf_if_new (area->ospf, ifp, co->address);
868 oi->connected = co;
869
870 oi->area = area;
871
872 oi->params = ospf_lookup_if_params (ifp, oi->address->u.prefix4);
873 oi->output_cost = ospf_if_get_output_cost (oi);
874
875 /* Add pseudo neighbor. */
876 ospf_nbr_add_self (oi);
877
878 /* Relate ospf interface to ospf instance. */
879 oi->ospf = area->ospf;
880
881 /* update network type as interface flag */
882 /* If network type is specified previously,
883 skip network type setting. */
884 oi->type = IF_DEF_PARAMS (ifp)->type;
885
886 ospf_area_add_if (oi->area, oi);
887
888 /* if router_id is not configured, dont bring up
889 * interfaces.
890 * ospf_router_id_update() will call ospf_if_update
891 * whenever r-id is configured instead.
892 */
893 if ((area->ospf->router_id.s_addr != 0)
894 && if_is_operative (ifp))
895 ospf_if_up (oi);
896 }
897 }
898}
899
Stephen Hemminger917e2992009-12-03 19:07:00 +0300900static void
Joakim Tjernlunda49eb302008-09-02 19:06:31 +0100901ospf_network_run (struct prefix *p, struct ospf_area *area)
paul718e3742002-12-13 20:15:29 +0000902{
903 struct interface *ifp;
hasso52dc7ee2004-09-23 19:18:23 +0000904 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000905
906 /* Schedule Router ID Update. */
Joakim Tjernlunda49eb302008-09-02 19:06:31 +0100907 if (area->ospf->router_id.s_addr == 0)
908 ospf_router_id_update (area->ospf);
paulb29800a2005-11-20 14:50:45 +0000909
paul718e3742002-12-13 20:15:29 +0000910 /* Get target interface. */
paul1eb8ef22005-04-07 07:30:20 +0000911 for (ALL_LIST_ELEMENTS_RO (om->iflist, node, ifp))
Joakim Tjernlunda49eb302008-09-02 19:06:31 +0100912 ospf_network_run_interface (p, area, ifp);
paul718e3742002-12-13 20:15:29 +0000913}
914
915void
916ospf_ls_upd_queue_empty (struct ospf_interface *oi)
917{
918 struct route_node *rn;
paul1eb8ef22005-04-07 07:30:20 +0000919 struct listnode *node, *nnode;
hasso52dc7ee2004-09-23 19:18:23 +0000920 struct list *lst;
paul718e3742002-12-13 20:15:29 +0000921 struct ospf_lsa *lsa;
922
923 /* empty ls update queue */
924 for (rn = route_top (oi->ls_upd_queue); rn;
925 rn = route_next (rn))
hasso52dc7ee2004-09-23 19:18:23 +0000926 if ((lst = (struct list *) rn->info))
paul718e3742002-12-13 20:15:29 +0000927 {
paul1eb8ef22005-04-07 07:30:20 +0000928 for (ALL_LIST_ELEMENTS (lst, node, nnode, lsa))
Paul Jakma1fe6ed32006-07-26 09:37:26 +0000929 ospf_lsa_unlock (&lsa); /* oi->ls_upd_queue */
paul718e3742002-12-13 20:15:29 +0000930 list_free (lst);
931 rn->info = NULL;
932 }
933
934 /* remove update event */
935 if (oi->t_ls_upd_event)
936 {
937 thread_cancel (oi->t_ls_upd_event);
938 oi->t_ls_upd_event = NULL;
939 }
940}
941
942void
Joakim Tjernlunda49eb302008-09-02 19:06:31 +0100943ospf_if_update (struct ospf *ospf, struct interface *ifp)
paul718e3742002-12-13 20:15:29 +0000944{
945 struct route_node *rn;
paul718e3742002-12-13 20:15:29 +0000946 struct ospf_network *network;
947 struct ospf_area *area;
Joakim Tjernlunda49eb302008-09-02 19:06:31 +0100948
949 if (!ospf)
950 ospf = ospf_lookup ();
paul718e3742002-12-13 20:15:29 +0000951
Joakim Tjernlund6e687d72008-09-24 17:15:48 +0100952 /* OSPF must be on and Router-ID must be configured. */
953 if (!ospf || ospf->router_id.s_addr == 0)
Joakim Tjernlunda49eb302008-09-02 19:06:31 +0100954 return;
955
956 /* Run each netowrk for this interface. */
957 for (rn = route_top (ospf->networks); rn; rn = route_next (rn))
958 if (rn->info != NULL)
959 {
960 network = (struct ospf_network *) rn->info;
961 area = ospf_area_get (ospf, network->area_id, network->format);
962 ospf_network_run_interface (&rn->p, area, ifp);
963 }
paul718e3742002-12-13 20:15:29 +0000964}
965
966void
paul68980082003-03-25 05:07:42 +0000967ospf_remove_vls_through_area (struct ospf *ospf, struct ospf_area *area)
paul718e3742002-12-13 20:15:29 +0000968{
paul1eb8ef22005-04-07 07:30:20 +0000969 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000970 struct ospf_vl_data *vl_data;
971
paul1eb8ef22005-04-07 07:30:20 +0000972 for (ALL_LIST_ELEMENTS (ospf->vlinks, node, nnode, vl_data))
973 if (IPV4_ADDR_SAME (&vl_data->vl_area_id, &area->area_id))
974 ospf_vl_delete (ospf, vl_data);
paul718e3742002-12-13 20:15:29 +0000975}
976
977
Stephen Hemminger7ba82f72009-05-15 10:47:45 -0700978static const struct message ospf_area_type_msg[] =
paul718e3742002-12-13 20:15:29 +0000979{
980 { OSPF_AREA_DEFAULT, "Default" },
981 { OSPF_AREA_STUB, "Stub" },
982 { OSPF_AREA_NSSA, "NSSA" },
983};
Stephen Hemminger7ba82f72009-05-15 10:47:45 -0700984static const int ospf_area_type_msg_max = OSPF_AREA_TYPE_MAX;
paul718e3742002-12-13 20:15:29 +0000985
paul4dadc292005-05-06 21:37:42 +0000986static void
paul718e3742002-12-13 20:15:29 +0000987ospf_area_type_set (struct ospf_area *area, int type)
988{
hasso52dc7ee2004-09-23 19:18:23 +0000989 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000990 struct ospf_interface *oi;
991
992 if (area->external_routing == type)
993 {
994 if (IS_DEBUG_OSPF_EVENT)
ajs9b0e25c2004-12-08 19:06:51 +0000995 zlog_debug ("Area[%s]: Types are the same, ignored.",
paul718e3742002-12-13 20:15:29 +0000996 inet_ntoa (area->area_id));
997 return;
998 }
999
1000 area->external_routing = type;
1001
1002 if (IS_DEBUG_OSPF_EVENT)
ajs9b0e25c2004-12-08 19:06:51 +00001003 zlog_debug ("Area[%s]: Configured as %s", inet_ntoa (area->area_id),
paul718e3742002-12-13 20:15:29 +00001004 LOOKUP (ospf_area_type_msg, type));
1005
1006 switch (area->external_routing)
1007 {
1008 case OSPF_AREA_DEFAULT:
paul1eb8ef22005-04-07 07:30:20 +00001009 for (ALL_LIST_ELEMENTS_RO (area->oiflist, node, oi))
1010 if (oi->nbr_self != NULL)
1011 {
1012 UNSET_FLAG (oi->nbr_self->options, OSPF_OPTION_NP);
1013 SET_FLAG (oi->nbr_self->options, OSPF_OPTION_E);
1014 }
paul718e3742002-12-13 20:15:29 +00001015 break;
1016 case OSPF_AREA_STUB:
paul1eb8ef22005-04-07 07:30:20 +00001017 for (ALL_LIST_ELEMENTS_RO (area->oiflist, node, oi))
1018 if (oi->nbr_self != NULL)
1019 {
1020 if (IS_DEBUG_OSPF_EVENT)
1021 zlog_debug ("setting options on %s accordingly", IF_NAME (oi));
1022 UNSET_FLAG (oi->nbr_self->options, OSPF_OPTION_NP);
1023 UNSET_FLAG (oi->nbr_self->options, OSPF_OPTION_E);
1024 if (IS_DEBUG_OSPF_EVENT)
1025 zlog_debug ("options set on %s: %x",
1026 IF_NAME (oi), OPTIONS (oi));
1027 }
paul718e3742002-12-13 20:15:29 +00001028 break;
1029 case OSPF_AREA_NSSA:
paul1eb8ef22005-04-07 07:30:20 +00001030 for (ALL_LIST_ELEMENTS_RO (area->oiflist, node, oi))
1031 if (oi->nbr_self != NULL)
1032 {
1033 zlog_debug ("setting nssa options on %s accordingly", IF_NAME (oi));
1034 UNSET_FLAG (oi->nbr_self->options, OSPF_OPTION_E);
1035 SET_FLAG (oi->nbr_self->options, OSPF_OPTION_NP);
1036 zlog_debug ("options set on %s: %x", IF_NAME (oi), OPTIONS (oi));
1037 }
paul718e3742002-12-13 20:15:29 +00001038 break;
1039 default:
1040 break;
1041 }
1042
Paul Jakmac363d382010-01-24 22:42:13 +00001043 ospf_router_lsa_update_area (area);
paul68980082003-03-25 05:07:42 +00001044 ospf_schedule_abr_task (area->ospf);
paul718e3742002-12-13 20:15:29 +00001045}
1046
1047int
paul68980082003-03-25 05:07:42 +00001048ospf_area_shortcut_set (struct ospf *ospf, struct ospf_area *area, int mode)
paul718e3742002-12-13 20:15:29 +00001049{
1050 if (area->shortcut_configured == mode)
1051 return 0;
1052
1053 area->shortcut_configured = mode;
Paul Jakmac363d382010-01-24 22:42:13 +00001054 ospf_router_lsa_update_area (area);
paul68980082003-03-25 05:07:42 +00001055 ospf_schedule_abr_task (ospf);
paul718e3742002-12-13 20:15:29 +00001056
paul68980082003-03-25 05:07:42 +00001057 ospf_area_check_free (ospf, area->area_id);
paul718e3742002-12-13 20:15:29 +00001058
1059 return 1;
1060}
1061
1062int
paul68980082003-03-25 05:07:42 +00001063ospf_area_shortcut_unset (struct ospf *ospf, struct ospf_area *area)
paul718e3742002-12-13 20:15:29 +00001064{
1065 area->shortcut_configured = OSPF_SHORTCUT_DEFAULT;
Paul Jakmac363d382010-01-24 22:42:13 +00001066 ospf_router_lsa_update_area (area);
paul68980082003-03-25 05:07:42 +00001067 ospf_area_check_free (ospf, area->area_id);
1068 ospf_schedule_abr_task (ospf);
paul718e3742002-12-13 20:15:29 +00001069
1070 return 1;
1071}
1072
paul4dadc292005-05-06 21:37:42 +00001073static int
paul718e3742002-12-13 20:15:29 +00001074ospf_area_vlink_count (struct ospf *ospf, struct ospf_area *area)
1075{
1076 struct ospf_vl_data *vl;
hasso52dc7ee2004-09-23 19:18:23 +00001077 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00001078 int count = 0;
1079
paul1eb8ef22005-04-07 07:30:20 +00001080 for (ALL_LIST_ELEMENTS_RO (ospf->vlinks, node, vl))
1081 if (IPV4_ADDR_SAME (&vl->vl_area_id, &area->area_id))
1082 count++;
paul718e3742002-12-13 20:15:29 +00001083
1084 return count;
1085}
1086
1087int
1088ospf_area_stub_set (struct ospf *ospf, struct in_addr area_id)
1089{
1090 struct ospf_area *area;
paul147193a2003-04-19 00:31:59 +00001091 int format = OSPF_AREA_ID_FORMAT_ADDRESS;
paul718e3742002-12-13 20:15:29 +00001092
paul68980082003-03-25 05:07:42 +00001093 area = ospf_area_get (ospf, area_id, format);
paul718e3742002-12-13 20:15:29 +00001094 if (ospf_area_vlink_count (ospf, area))
1095 return 0;
1096
1097 if (area->external_routing != OSPF_AREA_STUB)
1098 ospf_area_type_set (area, OSPF_AREA_STUB);
1099
1100 return 1;
1101}
1102
1103int
1104ospf_area_stub_unset (struct ospf *ospf, struct in_addr area_id)
1105{
1106 struct ospf_area *area;
1107
paul68980082003-03-25 05:07:42 +00001108 area = ospf_area_lookup_by_area_id (ospf, area_id);
paul718e3742002-12-13 20:15:29 +00001109 if (area == NULL)
1110 return 1;
1111
1112 if (area->external_routing == OSPF_AREA_STUB)
1113 ospf_area_type_set (area, OSPF_AREA_DEFAULT);
1114
paul68980082003-03-25 05:07:42 +00001115 ospf_area_check_free (ospf, area_id);
paul718e3742002-12-13 20:15:29 +00001116
1117 return 1;
1118}
1119
1120int
1121ospf_area_no_summary_set (struct ospf *ospf, struct in_addr area_id)
1122{
1123 struct ospf_area *area;
paul147193a2003-04-19 00:31:59 +00001124 int format = OSPF_AREA_ID_FORMAT_ADDRESS;
paul718e3742002-12-13 20:15:29 +00001125
paul68980082003-03-25 05:07:42 +00001126 area = ospf_area_get (ospf, area_id, format);
paul718e3742002-12-13 20:15:29 +00001127 area->no_summary = 1;
1128
1129 return 1;
1130}
1131
1132int
1133ospf_area_no_summary_unset (struct ospf *ospf, struct in_addr area_id)
1134{
1135 struct ospf_area *area;
1136
paul68980082003-03-25 05:07:42 +00001137 area = ospf_area_lookup_by_area_id (ospf, area_id);
paul718e3742002-12-13 20:15:29 +00001138 if (area == NULL)
1139 return 0;
1140
1141 area->no_summary = 0;
paul68980082003-03-25 05:07:42 +00001142 ospf_area_check_free (ospf, area_id);
paul718e3742002-12-13 20:15:29 +00001143
1144 return 1;
1145}
1146
1147int
1148ospf_area_nssa_set (struct ospf *ospf, struct in_addr area_id)
1149{
1150 struct ospf_area *area;
paul147193a2003-04-19 00:31:59 +00001151 int format = OSPF_AREA_ID_FORMAT_ADDRESS;
paul718e3742002-12-13 20:15:29 +00001152
paul68980082003-03-25 05:07:42 +00001153 area = ospf_area_get (ospf, area_id, format);
paul718e3742002-12-13 20:15:29 +00001154 if (ospf_area_vlink_count (ospf, area))
1155 return 0;
1156
1157 if (area->external_routing != OSPF_AREA_NSSA)
1158 {
1159 ospf_area_type_set (area, OSPF_AREA_NSSA);
1160 ospf->anyNSSA++;
1161 }
1162
paul084c7842003-06-22 08:35:18 +00001163 /* set NSSA area defaults */
1164 area->no_summary = 0;
1165 area->NSSATranslatorRole = OSPF_NSSA_ROLE_CANDIDATE;
pauld4a53d52003-07-12 21:30:57 +00001166 area->NSSATranslatorState = OSPF_NSSA_TRANSLATE_DISABLED;
paul084c7842003-06-22 08:35:18 +00001167 area->NSSATranslatorStabilityInterval = OSPF_NSSA_TRANS_STABLE_DEFAULT;
1168
paul718e3742002-12-13 20:15:29 +00001169 return 1;
1170}
1171
1172int
1173ospf_area_nssa_unset (struct ospf *ospf, struct in_addr area_id)
1174{
1175 struct ospf_area *area;
1176
paul68980082003-03-25 05:07:42 +00001177 area = ospf_area_lookup_by_area_id (ospf, area_id);
paul718e3742002-12-13 20:15:29 +00001178 if (area == NULL)
1179 return 0;
1180
1181 if (area->external_routing == OSPF_AREA_NSSA)
1182 {
1183 ospf->anyNSSA--;
1184 ospf_area_type_set (area, OSPF_AREA_DEFAULT);
1185 }
1186
paul68980082003-03-25 05:07:42 +00001187 ospf_area_check_free (ospf, area_id);
paul718e3742002-12-13 20:15:29 +00001188
1189 return 1;
1190}
1191
1192int
1193ospf_area_nssa_translator_role_set (struct ospf *ospf, struct in_addr area_id,
1194 int role)
1195{
1196 struct ospf_area *area;
1197
paul68980082003-03-25 05:07:42 +00001198 area = ospf_area_lookup_by_area_id (ospf, area_id);
paul718e3742002-12-13 20:15:29 +00001199 if (area == NULL)
1200 return 0;
1201
paul084c7842003-06-22 08:35:18 +00001202 area->NSSATranslatorRole = role;
paul718e3742002-12-13 20:15:29 +00001203
1204 return 1;
1205}
1206
paul4dadc292005-05-06 21:37:42 +00001207/* XXX: unused? Leave for symmetry? */
1208static int
paul718e3742002-12-13 20:15:29 +00001209ospf_area_nssa_translator_role_unset (struct ospf *ospf,
1210 struct in_addr area_id)
1211{
1212 struct ospf_area *area;
1213
paul68980082003-03-25 05:07:42 +00001214 area = ospf_area_lookup_by_area_id (ospf, area_id);
paul718e3742002-12-13 20:15:29 +00001215 if (area == NULL)
1216 return 0;
1217
paul084c7842003-06-22 08:35:18 +00001218 area->NSSATranslatorRole = OSPF_NSSA_ROLE_CANDIDATE;
paul718e3742002-12-13 20:15:29 +00001219
paul68980082003-03-25 05:07:42 +00001220 ospf_area_check_free (ospf, area_id);
paul718e3742002-12-13 20:15:29 +00001221
1222 return 1;
1223}
1224
1225int
paul68980082003-03-25 05:07:42 +00001226ospf_area_export_list_set (struct ospf *ospf,
paul6c835672004-10-11 11:00:30 +00001227 struct ospf_area *area, const char *list_name)
paul718e3742002-12-13 20:15:29 +00001228{
1229 struct access_list *list;
1230 list = access_list_lookup (AFI_IP, list_name);
1231
1232 EXPORT_LIST (area) = list;
1233
1234 if (EXPORT_NAME (area))
1235 free (EXPORT_NAME (area));
1236
1237 EXPORT_NAME (area) = strdup (list_name);
paul68980082003-03-25 05:07:42 +00001238 ospf_schedule_abr_task (ospf);
paul718e3742002-12-13 20:15:29 +00001239
1240 return 1;
1241}
1242
1243int
paul68980082003-03-25 05:07:42 +00001244ospf_area_export_list_unset (struct ospf *ospf, struct ospf_area * area)
paul718e3742002-12-13 20:15:29 +00001245{
1246
1247 EXPORT_LIST (area) = 0;
1248
1249 if (EXPORT_NAME (area))
1250 free (EXPORT_NAME (area));
1251
1252 EXPORT_NAME (area) = NULL;
1253
paul68980082003-03-25 05:07:42 +00001254 ospf_area_check_free (ospf, area->area_id);
paul718e3742002-12-13 20:15:29 +00001255
paul68980082003-03-25 05:07:42 +00001256 ospf_schedule_abr_task (ospf);
paul718e3742002-12-13 20:15:29 +00001257
1258 return 1;
1259}
1260
1261int
paul6c835672004-10-11 11:00:30 +00001262ospf_area_import_list_set (struct ospf *ospf, struct ospf_area *area,
1263 const char *name)
paul718e3742002-12-13 20:15:29 +00001264{
1265 struct access_list *list;
1266 list = access_list_lookup (AFI_IP, name);
1267
1268 IMPORT_LIST (area) = list;
1269
1270 if (IMPORT_NAME (area))
1271 free (IMPORT_NAME (area));
1272
1273 IMPORT_NAME (area) = strdup (name);
paul68980082003-03-25 05:07:42 +00001274 ospf_schedule_abr_task (ospf);
paul718e3742002-12-13 20:15:29 +00001275
1276 return 1;
1277}
1278
1279int
paul68980082003-03-25 05:07:42 +00001280ospf_area_import_list_unset (struct ospf *ospf, struct ospf_area * area)
paul718e3742002-12-13 20:15:29 +00001281{
1282 IMPORT_LIST (area) = 0;
1283
1284 if (IMPORT_NAME (area))
1285 free (IMPORT_NAME (area));
1286
1287 IMPORT_NAME (area) = NULL;
paul68980082003-03-25 05:07:42 +00001288 ospf_area_check_free (ospf, area->area_id);
paul718e3742002-12-13 20:15:29 +00001289
paul68980082003-03-25 05:07:42 +00001290 ospf_schedule_abr_task (ospf);
paul718e3742002-12-13 20:15:29 +00001291
1292 return 1;
1293}
1294
1295int
paul718e3742002-12-13 20:15:29 +00001296ospf_timers_refresh_set (struct ospf *ospf, int interval)
1297{
1298 int time_left;
1299
1300 if (ospf->lsa_refresh_interval == interval)
1301 return 1;
1302
1303 time_left = ospf->lsa_refresh_interval -
Paul Jakma2518efd2006-08-27 06:49:29 +00001304 (quagga_time (NULL) - ospf->lsa_refresher_started);
paul718e3742002-12-13 20:15:29 +00001305
1306 if (time_left > interval)
1307 {
1308 OSPF_TIMER_OFF (ospf->t_lsa_refresher);
1309 ospf->t_lsa_refresher =
1310 thread_add_timer (master, ospf_lsa_refresh_walker, ospf, interval);
1311 }
1312 ospf->lsa_refresh_interval = interval;
1313
1314 return 1;
1315}
1316
1317int
1318ospf_timers_refresh_unset (struct ospf *ospf)
1319{
1320 int time_left;
1321
1322 time_left = ospf->lsa_refresh_interval -
Paul Jakma2518efd2006-08-27 06:49:29 +00001323 (quagga_time (NULL) - ospf->lsa_refresher_started);
paul718e3742002-12-13 20:15:29 +00001324
1325 if (time_left > OSPF_LSA_REFRESH_INTERVAL_DEFAULT)
1326 {
1327 OSPF_TIMER_OFF (ospf->t_lsa_refresher);
1328 ospf->t_lsa_refresher =
1329 thread_add_timer (master, ospf_lsa_refresh_walker, ospf,
1330 OSPF_LSA_REFRESH_INTERVAL_DEFAULT);
1331 }
1332
1333 ospf->lsa_refresh_interval = OSPF_LSA_REFRESH_INTERVAL_DEFAULT;
1334
1335 return 1;
1336}
1337
1338
paul4dadc292005-05-06 21:37:42 +00001339static struct ospf_nbr_nbma *
1340ospf_nbr_nbma_new (void)
paul718e3742002-12-13 20:15:29 +00001341{
1342 struct ospf_nbr_nbma *nbr_nbma;
1343
Stephen Hemminger393deb92008-08-18 14:13:29 -07001344 nbr_nbma = XCALLOC (MTYPE_OSPF_NEIGHBOR_STATIC,
paul718e3742002-12-13 20:15:29 +00001345 sizeof (struct ospf_nbr_nbma));
paul718e3742002-12-13 20:15:29 +00001346
1347 nbr_nbma->priority = OSPF_NEIGHBOR_PRIORITY_DEFAULT;
1348 nbr_nbma->v_poll = OSPF_POLL_INTERVAL_DEFAULT;
1349
1350 return nbr_nbma;
1351}
1352
paul4dadc292005-05-06 21:37:42 +00001353static void
paul718e3742002-12-13 20:15:29 +00001354ospf_nbr_nbma_free (struct ospf_nbr_nbma *nbr_nbma)
1355{
1356 XFREE (MTYPE_OSPF_NEIGHBOR_STATIC, nbr_nbma);
1357}
1358
paul4dadc292005-05-06 21:37:42 +00001359static void
paul718e3742002-12-13 20:15:29 +00001360ospf_nbr_nbma_delete (struct ospf *ospf, struct ospf_nbr_nbma *nbr_nbma)
1361{
1362 struct route_node *rn;
1363 struct prefix_ipv4 p;
1364
1365 p.family = AF_INET;
1366 p.prefix = nbr_nbma->addr;
1367 p.prefixlen = IPV4_MAX_BITLEN;
1368
1369 rn = route_node_lookup (ospf->nbr_nbma, (struct prefix *)&p);
1370 if (rn)
1371 {
1372 ospf_nbr_nbma_free (rn->info);
1373 rn->info = NULL;
1374 route_unlock_node (rn);
1375 route_unlock_node (rn);
1376 }
1377}
1378
paul4dadc292005-05-06 21:37:42 +00001379static void
paul718e3742002-12-13 20:15:29 +00001380ospf_nbr_nbma_down (struct ospf_nbr_nbma *nbr_nbma)
1381{
1382 OSPF_TIMER_OFF (nbr_nbma->t_poll);
1383
1384 if (nbr_nbma->nbr)
1385 {
1386 nbr_nbma->nbr->nbr_nbma = NULL;
1387 OSPF_NSM_EVENT_EXECUTE (nbr_nbma->nbr, NSM_KillNbr);
1388 }
1389
1390 if (nbr_nbma->oi)
1391 listnode_delete (nbr_nbma->oi->nbr_nbma, nbr_nbma);
1392}
1393
paul4dadc292005-05-06 21:37:42 +00001394static void
paul718e3742002-12-13 20:15:29 +00001395ospf_nbr_nbma_add (struct ospf_nbr_nbma *nbr_nbma,
1396 struct ospf_interface *oi)
1397{
1398 struct ospf_neighbor *nbr;
1399 struct route_node *rn;
1400 struct prefix p;
1401
1402 if (oi->type != OSPF_IFTYPE_NBMA)
1403 return;
1404
1405 if (nbr_nbma->nbr != NULL)
1406 return;
1407
1408 if (IPV4_ADDR_SAME (&oi->nbr_self->address.u.prefix4, &nbr_nbma->addr))
1409 return;
1410
1411 nbr_nbma->oi = oi;
1412 listnode_add (oi->nbr_nbma, nbr_nbma);
1413
1414 /* Get neighbor information from table. */
1415 p.family = AF_INET;
1416 p.prefixlen = IPV4_MAX_BITLEN;
1417 p.u.prefix4 = nbr_nbma->addr;
1418
1419 rn = route_node_get (oi->nbrs, (struct prefix *)&p);
1420 if (rn->info)
1421 {
1422 nbr = rn->info;
1423 nbr->nbr_nbma = nbr_nbma;
1424 nbr_nbma->nbr = nbr;
1425
1426 route_unlock_node (rn);
1427 }
1428 else
1429 {
1430 nbr = rn->info = ospf_nbr_new (oi);
1431 nbr->state = NSM_Down;
1432 nbr->src = nbr_nbma->addr;
1433 nbr->nbr_nbma = nbr_nbma;
1434 nbr->priority = nbr_nbma->priority;
1435 nbr->address = p;
1436
1437 nbr_nbma->nbr = nbr;
1438
1439 OSPF_NSM_EVENT_EXECUTE (nbr, NSM_Start);
1440 }
1441}
1442
1443void
paul68980082003-03-25 05:07:42 +00001444ospf_nbr_nbma_if_update (struct ospf *ospf, struct ospf_interface *oi)
paul718e3742002-12-13 20:15:29 +00001445{
1446 struct ospf_nbr_nbma *nbr_nbma;
1447 struct route_node *rn;
1448 struct prefix_ipv4 p;
1449
1450 if (oi->type != OSPF_IFTYPE_NBMA)
1451 return;
1452
paul68980082003-03-25 05:07:42 +00001453 for (rn = route_top (ospf->nbr_nbma); rn; rn = route_next (rn))
paul718e3742002-12-13 20:15:29 +00001454 if ((nbr_nbma = rn->info))
1455 if (nbr_nbma->oi == NULL && nbr_nbma->nbr == NULL)
1456 {
1457 p.family = AF_INET;
1458 p.prefix = nbr_nbma->addr;
1459 p.prefixlen = IPV4_MAX_BITLEN;
1460
1461 if (prefix_match (oi->address, (struct prefix *)&p))
1462 ospf_nbr_nbma_add (nbr_nbma, oi);
1463 }
1464}
1465
1466struct ospf_nbr_nbma *
1467ospf_nbr_nbma_lookup (struct ospf *ospf, struct in_addr nbr_addr)
1468{
1469 struct route_node *rn;
1470 struct prefix_ipv4 p;
1471
1472 p.family = AF_INET;
1473 p.prefix = nbr_addr;
1474 p.prefixlen = IPV4_MAX_BITLEN;
1475
1476 rn = route_node_lookup (ospf->nbr_nbma, (struct prefix *)&p);
1477 if (rn)
1478 {
1479 route_unlock_node (rn);
1480 return rn->info;
1481 }
1482 return NULL;
1483}
1484
1485struct ospf_nbr_nbma *
paul68980082003-03-25 05:07:42 +00001486ospf_nbr_nbma_lookup_next (struct ospf *ospf, struct in_addr *addr, int first)
paul718e3742002-12-13 20:15:29 +00001487{
1488#if 0
1489 struct ospf_nbr_nbma *nbr_nbma;
hasso52dc7ee2004-09-23 19:18:23 +00001490 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00001491#endif
1492
paul68980082003-03-25 05:07:42 +00001493 if (ospf == NULL)
paul718e3742002-12-13 20:15:29 +00001494 return NULL;
1495
1496#if 0
paul1eb8ef22005-04-07 07:30:20 +00001497 for (ALL_LIST_ELEMENTS_RO (ospf->nbr_nbma, node, nbr_nbma))
paul718e3742002-12-13 20:15:29 +00001498 {
paul718e3742002-12-13 20:15:29 +00001499 if (first)
1500 {
1501 *addr = nbr_nbma->addr;
1502 return nbr_nbma;
1503 }
1504 else if (ntohl (nbr_nbma->addr.s_addr) > ntohl (addr->s_addr))
1505 {
1506 *addr = nbr_nbma->addr;
1507 return nbr_nbma;
1508 }
1509 }
1510#endif
1511 return NULL;
1512}
1513
1514int
1515ospf_nbr_nbma_set (struct ospf *ospf, struct in_addr nbr_addr)
1516{
1517 struct ospf_nbr_nbma *nbr_nbma;
1518 struct ospf_interface *oi;
1519 struct prefix_ipv4 p;
1520 struct route_node *rn;
hasso52dc7ee2004-09-23 19:18:23 +00001521 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00001522
1523 nbr_nbma = ospf_nbr_nbma_lookup (ospf, nbr_addr);
1524 if (nbr_nbma)
1525 return 0;
1526
1527 nbr_nbma = ospf_nbr_nbma_new ();
1528 nbr_nbma->addr = nbr_addr;
1529
1530 p.family = AF_INET;
1531 p.prefix = nbr_addr;
1532 p.prefixlen = IPV4_MAX_BITLEN;
1533
1534 rn = route_node_get (ospf->nbr_nbma, (struct prefix *)&p);
1535 rn->info = nbr_nbma;
1536
paul1eb8ef22005-04-07 07:30:20 +00001537 for (ALL_LIST_ELEMENTS_RO (ospf->oiflist, node, oi))
paul718e3742002-12-13 20:15:29 +00001538 {
paul718e3742002-12-13 20:15:29 +00001539 if (oi->type == OSPF_IFTYPE_NBMA)
1540 if (prefix_match (oi->address, (struct prefix *)&p))
1541 {
1542 ospf_nbr_nbma_add (nbr_nbma, oi);
1543 break;
1544 }
1545 }
1546
1547 return 1;
1548}
1549
1550int
1551ospf_nbr_nbma_unset (struct ospf *ospf, struct in_addr nbr_addr)
1552{
1553 struct ospf_nbr_nbma *nbr_nbma;
1554
1555 nbr_nbma = ospf_nbr_nbma_lookup (ospf, nbr_addr);
1556 if (nbr_nbma == NULL)
1557 return 0;
1558
1559 ospf_nbr_nbma_down (nbr_nbma);
1560 ospf_nbr_nbma_delete (ospf, nbr_nbma);
1561
1562 return 1;
1563}
1564
1565int
1566ospf_nbr_nbma_priority_set (struct ospf *ospf, struct in_addr nbr_addr,
1567 u_char priority)
1568{
1569 struct ospf_nbr_nbma *nbr_nbma;
1570
1571 nbr_nbma = ospf_nbr_nbma_lookup (ospf, nbr_addr);
1572 if (nbr_nbma == NULL)
1573 return 0;
1574
1575 if (nbr_nbma->priority != priority)
1576 nbr_nbma->priority = priority;
1577
1578 return 1;
1579}
1580
1581int
1582ospf_nbr_nbma_priority_unset (struct ospf *ospf, struct in_addr nbr_addr)
1583{
1584 struct ospf_nbr_nbma *nbr_nbma;
1585
1586 nbr_nbma = ospf_nbr_nbma_lookup (ospf, nbr_addr);
1587 if (nbr_nbma == NULL)
1588 return 0;
1589
1590 if (nbr_nbma != OSPF_NEIGHBOR_PRIORITY_DEFAULT)
1591 nbr_nbma->priority = OSPF_NEIGHBOR_PRIORITY_DEFAULT;
1592
1593 return 1;
1594}
1595
1596int
1597ospf_nbr_nbma_poll_interval_set (struct ospf *ospf, struct in_addr nbr_addr,
paul6c835672004-10-11 11:00:30 +00001598 unsigned int interval)
paul718e3742002-12-13 20:15:29 +00001599{
1600 struct ospf_nbr_nbma *nbr_nbma;
1601
1602 nbr_nbma = ospf_nbr_nbma_lookup (ospf, nbr_addr);
1603 if (nbr_nbma == NULL)
1604 return 0;
1605
1606 if (nbr_nbma->v_poll != interval)
1607 {
1608 nbr_nbma->v_poll = interval;
1609 if (nbr_nbma->oi && ospf_if_is_up (nbr_nbma->oi))
1610 {
1611 OSPF_TIMER_OFF (nbr_nbma->t_poll);
1612 OSPF_POLL_TIMER_ON (nbr_nbma->t_poll, ospf_poll_timer,
1613 nbr_nbma->v_poll);
1614 }
1615 }
1616
1617 return 1;
1618}
1619
1620int
1621ospf_nbr_nbma_poll_interval_unset (struct ospf *ospf, struct in_addr addr)
1622{
1623 struct ospf_nbr_nbma *nbr_nbma;
1624
1625 nbr_nbma = ospf_nbr_nbma_lookup (ospf, addr);
1626 if (nbr_nbma == NULL)
1627 return 0;
1628
1629 if (nbr_nbma->v_poll != OSPF_POLL_INTERVAL_DEFAULT)
1630 nbr_nbma->v_poll = OSPF_POLL_INTERVAL_DEFAULT;
1631
1632 return 1;
1633}
1634
paul718e3742002-12-13 20:15:29 +00001635void
paul020709f2003-04-04 02:44:16 +00001636ospf_master_init ()
1637{
1638 memset (&ospf_master, 0, sizeof (struct ospf_master));
1639
1640 om = &ospf_master;
1641 om->ospf = list_new ();
1642 om->master = thread_master_create ();
Paul Jakma2518efd2006-08-27 06:49:29 +00001643 om->start_time = quagga_time (NULL);
paul020709f2003-04-04 02:44:16 +00001644}