blob: f72295d1cf294e79f4ac0649625d048432e0be05 [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"
36
37#include "ospfd/ospfd.h"
38#include "ospfd/ospf_network.h"
39#include "ospfd/ospf_interface.h"
40#include "ospfd/ospf_ism.h"
41#include "ospfd/ospf_asbr.h"
42#include "ospfd/ospf_lsa.h"
43#include "ospfd/ospf_lsdb.h"
44#include "ospfd/ospf_neighbor.h"
45#include "ospfd/ospf_nsm.h"
46#include "ospfd/ospf_spf.h"
47#include "ospfd/ospf_packet.h"
48#include "ospfd/ospf_dump.h"
49#include "ospfd/ospf_zebra.h"
50#include "ospfd/ospf_abr.h"
51#include "ospfd/ospf_flood.h"
52#include "ospfd/ospf_route.h"
53#include "ospfd/ospf_ase.h"
54
paul020709f2003-04-04 02:44:16 +000055
pauledd7c242003-06-04 13:59:38 +000056
paul020709f2003-04-04 02:44:16 +000057/* OSPF process wide configuration. */
58static struct ospf_master ospf_master;
59
60/* OSPF process wide configuration pointer to export. */
61struct ospf_master *om;
paul718e3742002-12-13 20:15:29 +000062
63extern struct zclient *zclient;
hasso18a6dce2004-10-03 18:18:34 +000064extern struct in_addr router_id_zebra;
paul718e3742002-12-13 20:15:29 +000065
66
paul88d6cf32005-10-29 12:50:09 +000067static void ospf_remove_vls_through_area (struct ospf *, struct ospf_area *);
68static void ospf_network_free (struct ospf *, struct ospf_network *);
69static void ospf_area_free (struct ospf_area *);
70static void ospf_network_run (struct ospf *, struct prefix *, struct ospf_area *);
71static void ospf_finish_final (struct ospf *);
paul718e3742002-12-13 20:15:29 +000072
paul718e3742002-12-13 20:15:29 +000073#define OSPF_EXTERNAL_LSA_ORIGINATE_DELAY 1
paul88d6cf32005-10-29 12:50:09 +000074
paul718e3742002-12-13 20:15:29 +000075void
paul68980082003-03-25 05:07:42 +000076ospf_router_id_update (struct ospf *ospf)
paul718e3742002-12-13 20:15:29 +000077{
paul718e3742002-12-13 20:15:29 +000078 struct in_addr router_id, router_id_old;
paul1eb8ef22005-04-07 07:30:20 +000079 struct ospf_interface *oi;
hasso52dc7ee2004-09-23 19:18:23 +000080 struct listnode *node;
paul718e3742002-12-13 20:15:29 +000081
82 if (IS_DEBUG_OSPF_EVENT)
ajs9b0e25c2004-12-08 19:06:51 +000083 zlog_debug ("Router-ID[OLD:%s]: Update", inet_ntoa (ospf->router_id));
paul718e3742002-12-13 20:15:29 +000084
paul68980082003-03-25 05:07:42 +000085 router_id_old = ospf->router_id;
paul718e3742002-12-13 20:15:29 +000086
Andrew J. Schorr16700082006-07-27 22:29:06 +000087 /* Select the router ID based on these priorities:
88 1. Statically assigned router ID is always the first choice.
89 2. If there is no statically assigned router ID, then try to stick
90 with the most recent value, since changing router ID's is very
91 disruptive.
92 3. Last choice: just go with whatever the zebra daemon recommends.
93 */
paul68980082003-03-25 05:07:42 +000094 if (ospf->router_id_static.s_addr != 0)
95 router_id = ospf->router_id_static;
Andrew J. Schorr16700082006-07-27 22:29:06 +000096 else if (ospf->router_id.s_addr != 0)
97 router_id = ospf->router_id;
paul718e3742002-12-13 20:15:29 +000098 else
hasso18a6dce2004-10-03 18:18:34 +000099 router_id = router_id_zebra;
paul718e3742002-12-13 20:15:29 +0000100
paul68980082003-03-25 05:07:42 +0000101 ospf->router_id = router_id;
paul718e3742002-12-13 20:15:29 +0000102
103 if (IS_DEBUG_OSPF_EVENT)
ajs9b0e25c2004-12-08 19:06:51 +0000104 zlog_debug ("Router-ID[NEW:%s]: Update", inet_ntoa (ospf->router_id));
paul718e3742002-12-13 20:15:29 +0000105
106 if (!IPV4_ADDR_SAME (&router_id_old, &router_id))
107 {
paul1eb8ef22005-04-07 07:30:20 +0000108 for (ALL_LIST_ELEMENTS_RO (ospf->oiflist, node, oi))
109 /* Update self-neighbor's router_id. */
110 oi->nbr_self->router_id = router_id;
paul718e3742002-12-13 20:15:29 +0000111
112 /* If AS-external-LSA is queued, then flush those LSAs. */
paul68980082003-03-25 05:07:42 +0000113 if (router_id_old.s_addr == 0 && ospf->external_origin)
paul718e3742002-12-13 20:15:29 +0000114 {
115 int type;
116 /* Originate each redistributed external route. */
117 for (type = 0; type < ZEBRA_ROUTE_MAX; type++)
paul68980082003-03-25 05:07:42 +0000118 if (ospf->external_origin & (1 << type))
paul718e3742002-12-13 20:15:29 +0000119 thread_add_event (master, ospf_external_lsa_originate_timer,
paul68980082003-03-25 05:07:42 +0000120 ospf, type);
paul718e3742002-12-13 20:15:29 +0000121 /* Originate Deafult. */
paul68980082003-03-25 05:07:42 +0000122 if (ospf->external_origin & (1 << ZEBRA_ROUTE_MAX))
Paul Jakma4021b602006-05-12 22:55:41 +0000123 thread_add_event (master, ospf_default_originate_timer, ospf, 0);
paul718e3742002-12-13 20:15:29 +0000124
paul68980082003-03-25 05:07:42 +0000125 ospf->external_origin = 0;
paul718e3742002-12-13 20:15:29 +0000126 }
127
paul68980082003-03-25 05:07:42 +0000128 OSPF_TIMER_ON (ospf->t_router_lsa_update,
paul718e3742002-12-13 20:15:29 +0000129 ospf_router_lsa_update_timer, OSPF_LSA_UPDATE_DELAY);
paulb29800a2005-11-20 14:50:45 +0000130
131 /* update ospf_interface's */
132 ospf_if_update (ospf);
paul718e3742002-12-13 20:15:29 +0000133 }
134}
paul718e3742002-12-13 20:15:29 +0000135
136/* For OSPF area sort by area id. */
paul4dadc292005-05-06 21:37:42 +0000137static int
paul718e3742002-12-13 20:15:29 +0000138ospf_area_id_cmp (struct ospf_area *a1, struct ospf_area *a2)
139{
140 if (ntohl (a1->area_id.s_addr) > ntohl (a2->area_id.s_addr))
141 return 1;
142 if (ntohl (a1->area_id.s_addr) < ntohl (a2->area_id.s_addr))
143 return -1;
144 return 0;
145}
146
147/* Allocate new ospf structure. */
paul4dadc292005-05-06 21:37:42 +0000148static struct ospf *
149ospf_new (void)
paul718e3742002-12-13 20:15:29 +0000150{
151 int i;
152
153 struct ospf *new = XCALLOC (MTYPE_OSPF_TOP, sizeof (struct ospf));
154
155 new->router_id.s_addr = htonl (0);
156 new->router_id_static.s_addr = htonl (0);
157
pauld57834f2005-07-12 20:04:22 +0000158 new->abr_type = OSPF_ABR_DEFAULT;
paul718e3742002-12-13 20:15:29 +0000159 new->oiflist = list_new ();
160 new->vlinks = list_new ();
161 new->areas = list_new ();
162 new->areas->cmp = (int (*)(void *, void *)) ospf_area_id_cmp;
163 new->networks = route_table_init ();
164 new->nbr_nbma = route_table_init ();
165
166 new->lsdb = ospf_lsdb_new ();
167
168 new->default_originate = DEFAULT_ORIGINATE_NONE;
169
Paul Jakma7ffa8fa2006-10-22 20:07:53 +0000170 new->passive_interface_default = OSPF_IF_ACTIVE;
171
paul718e3742002-12-13 20:15:29 +0000172 new->new_external_route = route_table_init ();
173 new->old_external_route = route_table_init ();
174 new->external_lsas = route_table_init ();
paul88d6cf32005-10-29 12:50:09 +0000175
176 new->stub_router_startup_time = OSPF_STUB_ROUTER_UNCONFIGURED;
paul31a59762005-11-14 11:11:11 +0000177 new->stub_router_shutdown_time = OSPF_STUB_ROUTER_UNCONFIGURED;
paul88d6cf32005-10-29 12:50:09 +0000178
paul718e3742002-12-13 20:15:29 +0000179 /* Distribute parameter init. */
180 for (i = 0; i <= ZEBRA_ROUTE_MAX; i++)
181 {
182 new->dmetric[i].type = -1;
183 new->dmetric[i].value = -1;
184 }
185 new->default_metric = -1;
186 new->ref_bandwidth = OSPF_DEFAULT_REF_BANDWIDTH;
187
188 /* SPF timer value init. */
189 new->spf_delay = OSPF_SPF_DELAY_DEFAULT;
190 new->spf_holdtime = OSPF_SPF_HOLDTIME_DEFAULT;
pauld24f6e22005-10-21 09:23:12 +0000191 new->spf_max_holdtime = OSPF_SPF_MAX_HOLDTIME_DEFAULT;
192 new->spf_hold_multiplier = 1;
paul718e3742002-12-13 20:15:29 +0000193
194 /* MaxAge init. */
195 new->maxage_lsa = list_new ();
196 new->t_maxage_walker =
197 thread_add_timer (master, ospf_lsa_maxage_walker,
paul68980082003-03-25 05:07:42 +0000198 new, OSPF_LSA_MAXAGE_CHECK_INTERVAL);
paul718e3742002-12-13 20:15:29 +0000199
200 /* Distance table init. */
201 new->distance_table = route_table_init ();
202
203 new->lsa_refresh_queue.index = 0;
204 new->lsa_refresh_interval = OSPF_LSA_REFRESH_INTERVAL_DEFAULT;
205 new->t_lsa_refresher = thread_add_timer (master, ospf_lsa_refresh_walker,
206 new, new->lsa_refresh_interval);
Paul Jakma2518efd2006-08-27 06:49:29 +0000207 new->lsa_refresher_started = quagga_time (NULL);
paul718e3742002-12-13 20:15:29 +0000208
ajs5c333492005-02-23 15:43:01 +0000209 if ((new->fd = ospf_sock_init()) < 0)
210 {
211 zlog_err("ospf_new: fatal error: ospf_sock_init was unable to open "
212 "a socket");
213 exit(1);
214 }
215 if ((new->ibuf = stream_new(OSPF_MAX_PACKET_SIZE+1)) == NULL)
216 {
217 zlog_err("ospf_new: fatal error: stream_new(%u) failed allocating ibuf",
218 OSPF_MAX_PACKET_SIZE+1);
219 exit(1);
220 }
221 new->t_read = thread_add_read (master, ospf_read, new, new->fd);
paul718e3742002-12-13 20:15:29 +0000222 new->oi_write_q = list_new ();
223
224 return new;
225}
226
227struct ospf *
paul020709f2003-04-04 02:44:16 +0000228ospf_lookup ()
229{
230 if (listcount (om->ospf) == 0)
231 return NULL;
232
paul1eb8ef22005-04-07 07:30:20 +0000233 return listgetdata (listhead (om->ospf));
paul020709f2003-04-04 02:44:16 +0000234}
235
paul4dadc292005-05-06 21:37:42 +0000236static void
paul020709f2003-04-04 02:44:16 +0000237ospf_add (struct ospf *ospf)
238{
239 listnode_add (om->ospf, ospf);
240}
241
paul4dadc292005-05-06 21:37:42 +0000242static void
paul020709f2003-04-04 02:44:16 +0000243ospf_delete (struct ospf *ospf)
244{
245 listnode_delete (om->ospf, ospf);
246}
247
248struct ospf *
paul718e3742002-12-13 20:15:29 +0000249ospf_get ()
250{
paul020709f2003-04-04 02:44:16 +0000251 struct ospf *ospf;
paul718e3742002-12-13 20:15:29 +0000252
paul020709f2003-04-04 02:44:16 +0000253 ospf = ospf_lookup ();
254 if (ospf == NULL)
255 {
256 ospf = ospf_new ();
257 ospf_add (ospf);
paul718e3742002-12-13 20:15:29 +0000258
paul020709f2003-04-04 02:44:16 +0000259 if (ospf->router_id_static.s_addr == 0)
260 ospf_router_id_update (ospf);
paul718e3742002-12-13 20:15:29 +0000261
262#ifdef HAVE_OPAQUE_LSA
paul020709f2003-04-04 02:44:16 +0000263 ospf_opaque_type11_lsa_init (ospf);
paul718e3742002-12-13 20:15:29 +0000264#endif /* HAVE_OPAQUE_LSA */
paul020709f2003-04-04 02:44:16 +0000265 }
paul68980082003-03-25 05:07:42 +0000266
267 return ospf;
paul718e3742002-12-13 20:15:29 +0000268}
paul88d6cf32005-10-29 12:50:09 +0000269
paulc9c93d52005-11-26 13:31:11 +0000270/* Handle the second half of deferred shutdown. This is called either
271 * from the deferred-shutdown timer thread, or directly through
272 * ospf_deferred_shutdown_check.
paul88d6cf32005-10-29 12:50:09 +0000273 *
274 * Function is to cleanup G-R state, if required then call ospf_finish_final
275 * to complete shutdown of this ospf instance. Possibly exit if the
276 * whole process is being shutdown and this was the last OSPF instance.
277 */
278static void
paulc9c93d52005-11-26 13:31:11 +0000279ospf_deferred_shutdown_finish (struct ospf *ospf)
paul88d6cf32005-10-29 12:50:09 +0000280{
281 ospf->stub_router_shutdown_time = OSPF_STUB_ROUTER_UNCONFIGURED;
paulc9c93d52005-11-26 13:31:11 +0000282 OSPF_TIMER_OFF (ospf->t_deferred_shutdown);
paul88d6cf32005-10-29 12:50:09 +0000283
284 ospf_finish_final (ospf);
285
286 /* *ospf is now invalid */
287
288 /* ospfd being shut-down? If so, was this the last ospf instance? */
289 if (CHECK_FLAG (om->options, OSPF_MASTER_SHUTDOWN)
290 && (listcount (om->ospf) == 0))
291 exit (0);
292
293 return;
294}
295
296/* Timer thread for G-R */
297static int
paulc9c93d52005-11-26 13:31:11 +0000298ospf_deferred_shutdown_timer (struct thread *t)
paul88d6cf32005-10-29 12:50:09 +0000299{
300 struct ospf *ospf = THREAD_ARG(t);
301
paulc9c93d52005-11-26 13:31:11 +0000302 ospf_deferred_shutdown_finish (ospf);
paul88d6cf32005-10-29 12:50:09 +0000303
304 return 0;
305}
306
paulc9c93d52005-11-26 13:31:11 +0000307/* Check whether deferred-shutdown must be scheduled, otherwise call
paul88d6cf32005-10-29 12:50:09 +0000308 * down directly into second-half of instance shutdown.
309 */
310static void
paulc9c93d52005-11-26 13:31:11 +0000311ospf_deferred_shutdown_check (struct ospf *ospf)
paul88d6cf32005-10-29 12:50:09 +0000312{
313 unsigned long timeout;
314 struct listnode *ln;
315 struct ospf_area *area;
316
paulc9c93d52005-11-26 13:31:11 +0000317 /* deferred shutdown already running? */
318 if (ospf->t_deferred_shutdown)
paul88d6cf32005-10-29 12:50:09 +0000319 return;
320
321 /* Should we try push out max-metric LSAs? */
322 if (ospf->stub_router_shutdown_time != OSPF_STUB_ROUTER_UNCONFIGURED)
323 {
324 for (ALL_LIST_ELEMENTS_RO (ospf->areas, ln, area))
325 {
326 SET_FLAG (area->stub_router_state, OSPF_AREA_ADMIN_STUB_ROUTED);
327
328 if (!CHECK_FLAG (area->stub_router_state, OSPF_AREA_IS_STUB_ROUTED))
329 ospf_router_lsa_timer_add (area);
330 }
331 timeout = ospf->stub_router_shutdown_time;
332 }
333 else
paulc9c93d52005-11-26 13:31:11 +0000334 {
335 /* No timer needed */
336 ospf_deferred_shutdown_finish (ospf);
337 return;
338 }
paul88d6cf32005-10-29 12:50:09 +0000339
paulc9c93d52005-11-26 13:31:11 +0000340 OSPF_TIMER_ON (ospf->t_deferred_shutdown, ospf_deferred_shutdown_timer,
paul88d6cf32005-10-29 12:50:09 +0000341 timeout);
342 return;
343}
344
345/* Shut down the entire process */
346void
347ospf_terminate (void)
348{
349 struct ospf *ospf;
350 struct listnode *node, *nnode;
351
352 /* shutdown already in progress */
353 if (CHECK_FLAG (om->options, OSPF_MASTER_SHUTDOWN))
354 return;
355
356 SET_FLAG (om->options, OSPF_MASTER_SHUTDOWN);
357
358 for (ALL_LIST_ELEMENTS (om->ospf, node, nnode, ospf))
359 ospf_finish (ospf);
360
361 /* Deliberately go back up, hopefully to thread scheduler, as
362 * One or more ospf_finish()'s may have deferred shutdown to a timer
363 * thread
364 */
365}
paul718e3742002-12-13 20:15:29 +0000366
367void
368ospf_finish (struct ospf *ospf)
369{
paulc9c93d52005-11-26 13:31:11 +0000370 /* let deferred shutdown decide */
371 ospf_deferred_shutdown_check (ospf);
paul88d6cf32005-10-29 12:50:09 +0000372
paulc9c93d52005-11-26 13:31:11 +0000373 /* if ospf_deferred_shutdown returns, then ospf_finish_final is
paul88d6cf32005-10-29 12:50:09 +0000374 * deferred to expiry of G-S timer thread. Return back up, hopefully
375 * to thread scheduler.
376 */
paulc9c93d52005-11-26 13:31:11 +0000377 return;
paul88d6cf32005-10-29 12:50:09 +0000378}
379
380/* Final cleanup of ospf instance */
381static void
382ospf_finish_final (struct ospf *ospf)
383{
paul718e3742002-12-13 20:15:29 +0000384 struct route_node *rn;
385 struct ospf_nbr_nbma *nbr_nbma;
paul68980082003-03-25 05:07:42 +0000386 struct ospf_lsa *lsa;
paul1eb8ef22005-04-07 07:30:20 +0000387 struct ospf_interface *oi;
388 struct ospf_area *area;
389 struct ospf_vl_data *vl_data;
390 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000391 int i;
392
393#ifdef HAVE_OPAQUE_LSA
394 ospf_opaque_type11_lsa_term (ospf);
395#endif /* HAVE_OPAQUE_LSA */
paul88d6cf32005-10-29 12:50:09 +0000396
397 /* be nice if this worked, but it doesn't */
398 /*ospf_flush_self_originated_lsas_now (ospf);*/
399
400 /* Unregister redistribution */
paul718e3742002-12-13 20:15:29 +0000401 for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
paul020709f2003-04-04 02:44:16 +0000402 ospf_redistribute_unset (ospf, i);
Paul Jakma29b5a042006-08-27 08:01:20 +0000403 ospf_redistribute_default_unset (ospf);
paul718e3742002-12-13 20:15:29 +0000404
paul1eb8ef22005-04-07 07:30:20 +0000405 for (ALL_LIST_ELEMENTS (ospf->areas, node, nnode, area))
406 ospf_remove_vls_through_area (ospf, area);
paul718e3742002-12-13 20:15:29 +0000407
paul1eb8ef22005-04-07 07:30:20 +0000408 for (ALL_LIST_ELEMENTS (ospf->vlinks, node, nnode, vl_data))
409 ospf_vl_delete (ospf, vl_data);
paul718e3742002-12-13 20:15:29 +0000410
411 list_delete (ospf->vlinks);
412
413 /* Reset interface. */
paul1eb8ef22005-04-07 07:30:20 +0000414 for (ALL_LIST_ELEMENTS (ospf->oiflist, node, nnode, oi))
415 ospf_if_free (oi);
paul718e3742002-12-13 20:15:29 +0000416
417 /* Clear static neighbors */
418 for (rn = route_top (ospf->nbr_nbma); rn; rn = route_next (rn))
419 if ((nbr_nbma = rn->info))
420 {
421 OSPF_POLL_TIMER_OFF (nbr_nbma->t_poll);
422
423 if (nbr_nbma->nbr)
424 {
425 nbr_nbma->nbr->nbr_nbma = NULL;
426 nbr_nbma->nbr = NULL;
427 }
428
429 if (nbr_nbma->oi)
430 {
431 listnode_delete (nbr_nbma->oi->nbr_nbma, nbr_nbma);
432 nbr_nbma->oi = NULL;
433 }
434
435 XFREE (MTYPE_OSPF_NEIGHBOR_STATIC, nbr_nbma);
436 }
437
438 route_table_finish (ospf->nbr_nbma);
439
440 /* Clear networks and Areas. */
441 for (rn = route_top (ospf->networks); rn; rn = route_next (rn))
442 {
443 struct ospf_network *network;
444
445 if ((network = rn->info) != NULL)
446 {
paul68980082003-03-25 05:07:42 +0000447 ospf_network_free (ospf, network);
paul718e3742002-12-13 20:15:29 +0000448 rn->info = NULL;
449 route_unlock_node (rn);
450 }
451 }
452
paul1eb8ef22005-04-07 07:30:20 +0000453 for (ALL_LIST_ELEMENTS (ospf->areas, node, nnode, area))
paul718e3742002-12-13 20:15:29 +0000454 {
paul718e3742002-12-13 20:15:29 +0000455 listnode_delete (ospf->areas, area);
456 ospf_area_free (area);
457 }
458
459 /* Cancel all timers. */
460 OSPF_TIMER_OFF (ospf->t_external_lsa);
paul718e3742002-12-13 20:15:29 +0000461 OSPF_TIMER_OFF (ospf->t_router_lsa_update);
462 OSPF_TIMER_OFF (ospf->t_spf_calc);
463 OSPF_TIMER_OFF (ospf->t_ase_calc);
464 OSPF_TIMER_OFF (ospf->t_maxage);
465 OSPF_TIMER_OFF (ospf->t_maxage_walker);
466 OSPF_TIMER_OFF (ospf->t_abr_task);
paul88d6cf32005-10-29 12:50:09 +0000467 OSPF_TIMER_OFF (ospf->t_asbr_check);
paul718e3742002-12-13 20:15:29 +0000468 OSPF_TIMER_OFF (ospf->t_distribute_update);
469 OSPF_TIMER_OFF (ospf->t_lsa_refresher);
470 OSPF_TIMER_OFF (ospf->t_read);
471 OSPF_TIMER_OFF (ospf->t_write);
paul31a59762005-11-14 11:11:11 +0000472#ifdef HAVE_OPAQUE_LSA
paul88d6cf32005-10-29 12:50:09 +0000473 OSPF_TIMER_OFF (ospf->t_opaque_lsa_self);
paul31a59762005-11-14 11:11:11 +0000474#endif
paul718e3742002-12-13 20:15:29 +0000475
476 close (ospf->fd);
ajs5c333492005-02-23 15:43:01 +0000477 stream_free(ospf->ibuf);
paul718e3742002-12-13 20:15:29 +0000478
479#ifdef HAVE_OPAQUE_LSA
paul68980082003-03-25 05:07:42 +0000480 LSDB_LOOP (OPAQUE_AS_LSDB (ospf), rn, lsa)
481 ospf_discard_from_db (ospf, ospf->lsdb, lsa);
paul718e3742002-12-13 20:15:29 +0000482#endif /* HAVE_OPAQUE_LSA */
paul68980082003-03-25 05:07:42 +0000483 LSDB_LOOP (EXTERNAL_LSDB (ospf), rn, lsa)
484 ospf_discard_from_db (ospf, ospf->lsdb, lsa);
485
paul718e3742002-12-13 20:15:29 +0000486 ospf_lsdb_delete_all (ospf->lsdb);
487 ospf_lsdb_free (ospf->lsdb);
488
paul1eb8ef22005-04-07 07:30:20 +0000489 for (ALL_LIST_ELEMENTS (ospf->maxage_lsa, node, nnode, lsa))
Paul Jakma1fe6ed32006-07-26 09:37:26 +0000490 ospf_lsa_unlock (&lsa); /* maxage_lsa */
paul718e3742002-12-13 20:15:29 +0000491
492 list_delete (ospf->maxage_lsa);
493
494 if (ospf->old_table)
495 ospf_route_table_free (ospf->old_table);
496 if (ospf->new_table)
497 {
498 ospf_route_delete (ospf->new_table);
499 ospf_route_table_free (ospf->new_table);
500 }
501 if (ospf->old_rtrs)
502 ospf_rtrs_free (ospf->old_rtrs);
503 if (ospf->new_rtrs)
504 ospf_rtrs_free (ospf->new_rtrs);
505 if (ospf->new_external_route)
506 {
507 ospf_route_delete (ospf->new_external_route);
508 ospf_route_table_free (ospf->new_external_route);
509 }
510 if (ospf->old_external_route)
511 {
512 ospf_route_delete (ospf->old_external_route);
513 ospf_route_table_free (ospf->old_external_route);
514 }
515 if (ospf->external_lsas)
516 {
517 ospf_ase_external_lsas_finish (ospf->external_lsas);
518 }
519
520 list_delete (ospf->areas);
521
522 for (i = ZEBRA_ROUTE_SYSTEM; i <= ZEBRA_ROUTE_MAX; i++)
523 if (EXTERNAL_INFO (i) != NULL)
524 for (rn = route_top (EXTERNAL_INFO (i)); rn; rn = route_next (rn))
525 {
526 if (rn->info == NULL)
527 continue;
528
529 XFREE (MTYPE_OSPF_EXTERNAL_INFO, rn->info);
530 rn->info = NULL;
531 route_unlock_node (rn);
532 }
533
paul68980082003-03-25 05:07:42 +0000534 ospf_distance_reset (ospf);
paul718e3742002-12-13 20:15:29 +0000535 route_table_finish (ospf->distance_table);
536
paul020709f2003-04-04 02:44:16 +0000537 ospf_delete (ospf);
paul718e3742002-12-13 20:15:29 +0000538
paul020709f2003-04-04 02:44:16 +0000539 XFREE (MTYPE_OSPF_TOP, ospf);
paul718e3742002-12-13 20:15:29 +0000540}
541
542
543/* allocate new OSPF Area object */
paul4dadc292005-05-06 21:37:42 +0000544static struct ospf_area *
paul68980082003-03-25 05:07:42 +0000545ospf_area_new (struct ospf *ospf, struct in_addr area_id)
paul718e3742002-12-13 20:15:29 +0000546{
547 struct ospf_area *new;
548
549 /* Allocate new config_network. */
550 new = XCALLOC (MTYPE_OSPF_AREA, sizeof (struct ospf_area));
551
paul68980082003-03-25 05:07:42 +0000552 new->ospf = ospf;
paul718e3742002-12-13 20:15:29 +0000553
554 new->area_id = area_id;
555
556 new->external_routing = OSPF_AREA_DEFAULT;
557 new->default_cost = 1;
558 new->auth_type = OSPF_AUTH_NULL;
paul88d6cf32005-10-29 12:50:09 +0000559
paul718e3742002-12-13 20:15:29 +0000560 /* New LSDB init. */
561 new->lsdb = ospf_lsdb_new ();
562
563 /* Self-originated LSAs initialize. */
564 new->router_lsa_self = NULL;
565
566#ifdef HAVE_OPAQUE_LSA
567 ospf_opaque_type10_lsa_init (new);
568#endif /* HAVE_OPAQUE_LSA */
569
570 new->oiflist = list_new ();
571 new->ranges = route_table_init ();
572
573 if (area_id.s_addr == OSPF_AREA_BACKBONE)
paul68980082003-03-25 05:07:42 +0000574 ospf->backbone = new;
paul718e3742002-12-13 20:15:29 +0000575
576 return new;
577}
578
579void
580ospf_area_free (struct ospf_area *area)
581{
paul68980082003-03-25 05:07:42 +0000582 struct route_node *rn;
583 struct ospf_lsa *lsa;
584
paul718e3742002-12-13 20:15:29 +0000585 /* Free LSDBs. */
paul68980082003-03-25 05:07:42 +0000586 LSDB_LOOP (ROUTER_LSDB (area), rn, lsa)
587 ospf_discard_from_db (area->ospf, area->lsdb, lsa);
588 LSDB_LOOP (NETWORK_LSDB (area), rn, lsa)
589 ospf_discard_from_db (area->ospf, area->lsdb, lsa);
590 LSDB_LOOP (SUMMARY_LSDB (area), rn, lsa)
591 ospf_discard_from_db (area->ospf, area->lsdb, lsa);
592 LSDB_LOOP (ASBR_SUMMARY_LSDB (area), rn, lsa)
593 ospf_discard_from_db (area->ospf, area->lsdb, lsa);
paul718e3742002-12-13 20:15:29 +0000594
paul68980082003-03-25 05:07:42 +0000595 LSDB_LOOP (NSSA_LSDB (area), rn, lsa)
596 ospf_discard_from_db (area->ospf, area->lsdb, lsa);
paul718e3742002-12-13 20:15:29 +0000597#ifdef HAVE_OPAQUE_LSA
paul68980082003-03-25 05:07:42 +0000598 LSDB_LOOP (OPAQUE_AREA_LSDB (area), rn, lsa)
599 ospf_discard_from_db (area->ospf, area->lsdb, lsa);
600 LSDB_LOOP (OPAQUE_LINK_LSDB (area), rn, lsa)
601 ospf_discard_from_db (area->ospf, area->lsdb, lsa);
paul718e3742002-12-13 20:15:29 +0000602#endif /* HAVE_OPAQUE_LSA */
603
604 ospf_lsdb_delete_all (area->lsdb);
605 ospf_lsdb_free (area->lsdb);
606
Paul Jakma1fe6ed32006-07-26 09:37:26 +0000607 ospf_lsa_unlock (&area->router_lsa_self);
paul718e3742002-12-13 20:15:29 +0000608
609 route_table_finish (area->ranges);
610 list_delete (area->oiflist);
611
612 if (EXPORT_NAME (area))
613 free (EXPORT_NAME (area));
614
615 if (IMPORT_NAME (area))
616 free (IMPORT_NAME (area));
617
618 /* Cancel timer. */
619 OSPF_TIMER_OFF (area->t_router_lsa_self);
paul88d6cf32005-10-29 12:50:09 +0000620 OSPF_TIMER_OFF (area->t_stub_router);
621#ifdef HAVE_OPAQUE_LSA
622 OSPF_TIMER_OFF (area->t_opaque_lsa_self);
623#endif /* HAVE_OPAQUE_LSA */
624
paul718e3742002-12-13 20:15:29 +0000625 if (OSPF_IS_AREA_BACKBONE (area))
paul68980082003-03-25 05:07:42 +0000626 area->ospf->backbone = NULL;
paul718e3742002-12-13 20:15:29 +0000627
628 XFREE (MTYPE_OSPF_AREA, area);
629}
630
631void
paul68980082003-03-25 05:07:42 +0000632ospf_area_check_free (struct ospf *ospf, struct in_addr area_id)
paul718e3742002-12-13 20:15:29 +0000633{
634 struct ospf_area *area;
635
paul68980082003-03-25 05:07:42 +0000636 area = ospf_area_lookup_by_area_id (ospf, area_id);
paul718e3742002-12-13 20:15:29 +0000637 if (area &&
638 listcount (area->oiflist) == 0 &&
639 area->ranges->top == NULL &&
640 area->shortcut_configured == OSPF_SHORTCUT_DEFAULT &&
641 area->external_routing == OSPF_AREA_DEFAULT &&
642 area->no_summary == 0 &&
643 area->default_cost == 1 &&
644 EXPORT_NAME (area) == NULL &&
645 IMPORT_NAME (area) == NULL &&
646 area->auth_type == OSPF_AUTH_NULL)
647 {
paul68980082003-03-25 05:07:42 +0000648 listnode_delete (ospf->areas, area);
paul718e3742002-12-13 20:15:29 +0000649 ospf_area_free (area);
650 }
651}
652
653struct ospf_area *
paul68980082003-03-25 05:07:42 +0000654ospf_area_get (struct ospf *ospf, struct in_addr area_id, int format)
paul718e3742002-12-13 20:15:29 +0000655{
656 struct ospf_area *area;
657
paul68980082003-03-25 05:07:42 +0000658 area = ospf_area_lookup_by_area_id (ospf, area_id);
paul718e3742002-12-13 20:15:29 +0000659 if (!area)
660 {
paul68980082003-03-25 05:07:42 +0000661 area = ospf_area_new (ospf, area_id);
paul718e3742002-12-13 20:15:29 +0000662 area->format = format;
paul68980082003-03-25 05:07:42 +0000663 listnode_add_sort (ospf->areas, area);
664 ospf_check_abr_status (ospf);
paul718e3742002-12-13 20:15:29 +0000665 }
666
667 return area;
668}
669
670struct ospf_area *
paul68980082003-03-25 05:07:42 +0000671ospf_area_lookup_by_area_id (struct ospf *ospf, struct in_addr area_id)
paul718e3742002-12-13 20:15:29 +0000672{
673 struct ospf_area *area;
hasso52dc7ee2004-09-23 19:18:23 +0000674 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000675
paul1eb8ef22005-04-07 07:30:20 +0000676 for (ALL_LIST_ELEMENTS_RO (ospf->areas, node, area))
677 if (IPV4_ADDR_SAME (&area->area_id, &area_id))
678 return area;
paul718e3742002-12-13 20:15:29 +0000679
680 return NULL;
681}
682
683void
684ospf_area_add_if (struct ospf_area *area, struct ospf_interface *oi)
685{
686 listnode_add (area->oiflist, oi);
687}
688
689void
690ospf_area_del_if (struct ospf_area *area, struct ospf_interface *oi)
691{
692 listnode_delete (area->oiflist, oi);
693}
694
695
696/* Config network statement related functions. */
paul4dadc292005-05-06 21:37:42 +0000697static struct ospf_network *
paul718e3742002-12-13 20:15:29 +0000698ospf_network_new (struct in_addr area_id, int format)
699{
700 struct ospf_network *new;
701 new = XCALLOC (MTYPE_OSPF_NETWORK, sizeof (struct ospf_network));
702
703 new->area_id = area_id;
704 new->format = format;
705
706 return new;
707}
708
709void
paul68980082003-03-25 05:07:42 +0000710ospf_network_free (struct ospf *ospf, struct ospf_network *network)
paul718e3742002-12-13 20:15:29 +0000711{
paul68980082003-03-25 05:07:42 +0000712 ospf_area_check_free (ospf, network->area_id);
713 ospf_schedule_abr_task (ospf);
paul718e3742002-12-13 20:15:29 +0000714 XFREE (MTYPE_OSPF_NETWORK, network);
715}
716
717int
718ospf_network_set (struct ospf *ospf, struct prefix_ipv4 *p,
719 struct in_addr area_id)
720{
721 struct ospf_network *network;
722 struct ospf_area *area;
723 struct route_node *rn;
724 struct external_info *ei;
paul147193a2003-04-19 00:31:59 +0000725 int ret = OSPF_AREA_ID_FORMAT_ADDRESS;
paul718e3742002-12-13 20:15:29 +0000726
727 rn = route_node_get (ospf->networks, (struct prefix *)p);
728 if (rn->info)
729 {
730 /* There is already same network statement. */
731 route_unlock_node (rn);
732 return 0;
733 }
734
735 rn->info = network = ospf_network_new (area_id, ret);
paul68980082003-03-25 05:07:42 +0000736 area = ospf_area_get (ospf, area_id, ret);
paul718e3742002-12-13 20:15:29 +0000737
738 /* Run network config now. */
739 ospf_network_run (ospf, (struct prefix *)p, area);
740
741 /* Update connected redistribute. */
742 if (ospf_is_type_redistributed (ZEBRA_ROUTE_CONNECT))
743 if (EXTERNAL_INFO (ZEBRA_ROUTE_CONNECT))
744 for (rn = route_top (EXTERNAL_INFO (ZEBRA_ROUTE_CONNECT));
745 rn; rn = route_next (rn))
746 if ((ei = rn->info) != NULL)
paul68980082003-03-25 05:07:42 +0000747 if (ospf_external_info_find_lsa (ospf, &ei->p))
748 if (!ospf_distribute_check_connected (ospf, ei))
749 ospf_external_lsa_flush (ospf, ei->type, &ei->p,
ajs5339cfd2005-09-19 13:28:05 +0000750 ei->ifindex /*, ei->nexthop */);
paul718e3742002-12-13 20:15:29 +0000751
paul68980082003-03-25 05:07:42 +0000752 ospf_area_check_free (ospf, area_id);
paul718e3742002-12-13 20:15:29 +0000753
754 return 1;
755}
756
757int
758ospf_network_unset (struct ospf *ospf, struct prefix_ipv4 *p,
759 struct in_addr area_id)
760{
761 struct route_node *rn;
762 struct ospf_network *network;
763 struct external_info *ei;
764
765 rn = route_node_lookup (ospf->networks, (struct prefix *)p);
766 if (rn == NULL)
767 return 0;
768
769 network = rn->info;
770 if (!IPV4_ADDR_SAME (&area_id, &network->area_id))
771 return 0;
772
paul68980082003-03-25 05:07:42 +0000773 ospf_network_free (ospf, rn->info);
paul718e3742002-12-13 20:15:29 +0000774 rn->info = NULL;
775 route_unlock_node (rn);
776
paul68980082003-03-25 05:07:42 +0000777 ospf_if_update (ospf);
paul718e3742002-12-13 20:15:29 +0000778
779 /* Update connected redistribute. */
780 if (ospf_is_type_redistributed (ZEBRA_ROUTE_CONNECT))
781 if (EXTERNAL_INFO (ZEBRA_ROUTE_CONNECT))
782 for (rn = route_top (EXTERNAL_INFO (ZEBRA_ROUTE_CONNECT));
783 rn; rn = route_next (rn))
784 if ((ei = rn->info) != NULL)
paul68980082003-03-25 05:07:42 +0000785 if (!ospf_external_info_find_lsa (ospf, &ei->p))
786 if (ospf_distribute_check_connected (ospf, ei))
787 ospf_external_lsa_originate (ospf, ei);
paul718e3742002-12-13 20:15:29 +0000788
789 return 1;
790}
791
paul570f7592003-01-25 06:47:41 +0000792/* Check whether interface matches given network
793 * returns: 1, true. 0, false
794 */
795int
796ospf_network_match_iface(struct connected *co, struct prefix *net)
797{
Andrew J. Schorre4529632006-12-12 19:18:21 +0000798#define COMPATIBILITY_MODE
799 /* The old code used to have a special case for PtP interfaces:
800
801 if (if_is_pointopoint (co->ifp) && co->destination &&
802 IPV4_ADDR_SAME ( &(co->destination->u.prefix4), &(net->u.prefix4)))
803 return 1;
804
805 The new approach is much more general. If a peer address is supplied,
806 then we are routing to that prefix, so that's the address to compare
807 against (not the local address, which may not be unique).
808 */
809#ifndef COMPATIBILITY_MODE
810 /* new approach: more elegant and conceptually clean */
811 return prefix_match(net, CONNECTED_PREFIX(co));
812#else /* COMPATIBILITY_MODE */
813 /* match old (strange?) behavior */
814
paul570f7592003-01-25 06:47:41 +0000815 /* Behaviour to match both Cisco where:
816 * iface address lies within network specified -> ospf
817 * and zebra 0.9[2ish-3]:
818 * PtP special case: network specified == iface peer addr -> ospf
819 */
gdt8f40e892003-12-05 14:01:43 +0000820
paulf3ae74c2004-11-04 20:35:31 +0000821 /* For PtP, match if peer address matches network address exactly.
822 * This can be addr/32 or addr/p for p < 32, but the addr must match
823 * exactly; this is not a test for falling within the prefix. This
gdt8f40e892003-12-05 14:01:43 +0000824 * test is solely for compatibility with zebra.
gdt8f40e892003-12-05 14:01:43 +0000825 */
Andrew J. Schorre4529632006-12-12 19:18:21 +0000826 if (CONNECTED_PEER(co) &&
paulf3ae74c2004-11-04 20:35:31 +0000827 IPV4_ADDR_SAME ( &(co->destination->u.prefix4), &(net->u.prefix4)))
828 return 1;
829
830#if 0
831 /* Decline to accept PtP if dst address does not match the
832 * prefix. (ifdefed out because this is a workaround, not the
833 * desired behavior.) */
834 if (if_is_pointopoint (co->ifp) &&
835 ! prefix_match (net, co->destination))
836 return 0;
837#endif
838
839 /* If the address is within the prefix, accept. Note that this
840 * applies to PtP as well as other types.
841 */
842 if (prefix_match (net, co->address))
843 return 1;
844
845 return 0; /* no match */
Andrew J. Schorre4529632006-12-12 19:18:21 +0000846
847#endif /* COMPATIBILITY_MODE */
paul570f7592003-01-25 06:47:41 +0000848}
849
paul718e3742002-12-13 20:15:29 +0000850void
851ospf_network_run (struct ospf *ospf, struct prefix *p, struct ospf_area *area)
852{
853 struct interface *ifp;
paul1eb8ef22005-04-07 07:30:20 +0000854 struct connected *co;
hasso52dc7ee2004-09-23 19:18:23 +0000855 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000856
857 /* Schedule Router ID Update. */
paul86752842006-01-10 20:34:46 +0000858 if (ospf->router_id.s_addr == 0)
paulb29800a2005-11-20 14:50:45 +0000859 ospf_router_id_update (ospf);
860
paul718e3742002-12-13 20:15:29 +0000861 /* Get target interface. */
paul1eb8ef22005-04-07 07:30:20 +0000862 for (ALL_LIST_ELEMENTS_RO (om->iflist, node, ifp))
paul718e3742002-12-13 20:15:29 +0000863 {
paul1eb8ef22005-04-07 07:30:20 +0000864 struct listnode *cnode;
paul718e3742002-12-13 20:15:29 +0000865
paul718e3742002-12-13 20:15:29 +0000866 if (memcmp (ifp->name, "VLINK", 5) == 0)
867 continue;
868
869 /* if interface prefix is match specified prefix,
870 then create socket and join multicast group. */
paul1eb8ef22005-04-07 07:30:20 +0000871 for (ALL_LIST_ELEMENTS_RO (ifp->connected, cnode, co))
paul718e3742002-12-13 20:15:29 +0000872 {
paul718e3742002-12-13 20:15:29 +0000873 struct prefix *addr;
paul800dc102003-03-28 01:51:40 +0000874
paule7b050c2003-04-07 06:38:02 +0000875 if (CHECK_FLAG(co->flags,ZEBRA_IFA_SECONDARY))
876 continue;
paul718e3742002-12-13 20:15:29 +0000877
Andrew J. Schorre4529632006-12-12 19:18:21 +0000878 addr = CONNECTED_ID(co);
paul718e3742002-12-13 20:15:29 +0000879
paulcb3f37d2003-02-18 23:26:37 +0000880 if (p->family == co->address->family
paul68980082003-03-25 05:07:42 +0000881 && ! ospf_if_is_configured (ospf, &(addr->u.prefix4))
paulcb3f37d2003-02-18 23:26:37 +0000882 && ospf_network_match_iface(co,p))
paul570f7592003-01-25 06:47:41 +0000883 {
paul1eb8ef22005-04-07 07:30:20 +0000884 struct ospf_interface *oi;
paul718e3742002-12-13 20:15:29 +0000885
paul68980082003-03-25 05:07:42 +0000886 oi = ospf_if_new (ospf, ifp, co->address);
paul718e3742002-12-13 20:15:29 +0000887 oi->connected = co;
888
paul718e3742002-12-13 20:15:29 +0000889 oi->area = area;
890
891 oi->params = ospf_lookup_if_params (ifp, oi->address->u.prefix4);
892 oi->output_cost = ospf_if_get_output_cost (oi);
893
paul718e3742002-12-13 20:15:29 +0000894 /* Add pseudo neighbor. */
895 ospf_nbr_add_self (oi);
896
paul718e3742002-12-13 20:15:29 +0000897 /* Relate ospf interface to ospf instance. */
paul68980082003-03-25 05:07:42 +0000898 oi->ospf = ospf;
paul718e3742002-12-13 20:15:29 +0000899
900 /* update network type as interface flag */
901 /* If network type is specified previously,
902 skip network type setting. */
903 oi->type = IF_DEF_PARAMS (ifp)->type;
904
paul718e3742002-12-13 20:15:29 +0000905 ospf_area_add_if (oi->area, oi);
paulb29800a2005-11-20 14:50:45 +0000906
907 /* if router_id is not configured, dont bring up
908 * interfaces.
909 * ospf_router_id_update() will call ospf_if_update
910 * whenever r-id is configured instead.
911 */
paul86752842006-01-10 20:34:46 +0000912 if ((ospf->router_id.s_addr != 0)
paulb29800a2005-11-20 14:50:45 +0000913 && if_is_operative (ifp))
paul718e3742002-12-13 20:15:29 +0000914 ospf_if_up (oi);
paul718e3742002-12-13 20:15:29 +0000915 }
916 }
917 }
918}
919
920void
921ospf_ls_upd_queue_empty (struct ospf_interface *oi)
922{
923 struct route_node *rn;
paul1eb8ef22005-04-07 07:30:20 +0000924 struct listnode *node, *nnode;
hasso52dc7ee2004-09-23 19:18:23 +0000925 struct list *lst;
paul718e3742002-12-13 20:15:29 +0000926 struct ospf_lsa *lsa;
927
928 /* empty ls update queue */
929 for (rn = route_top (oi->ls_upd_queue); rn;
930 rn = route_next (rn))
hasso52dc7ee2004-09-23 19:18:23 +0000931 if ((lst = (struct list *) rn->info))
paul718e3742002-12-13 20:15:29 +0000932 {
paul1eb8ef22005-04-07 07:30:20 +0000933 for (ALL_LIST_ELEMENTS (lst, node, nnode, lsa))
Paul Jakma1fe6ed32006-07-26 09:37:26 +0000934 ospf_lsa_unlock (&lsa); /* oi->ls_upd_queue */
paul718e3742002-12-13 20:15:29 +0000935 list_free (lst);
936 rn->info = NULL;
937 }
938
939 /* remove update event */
940 if (oi->t_ls_upd_event)
941 {
942 thread_cancel (oi->t_ls_upd_event);
943 oi->t_ls_upd_event = NULL;
944 }
945}
946
947void
paul68980082003-03-25 05:07:42 +0000948ospf_if_update (struct ospf *ospf)
paul718e3742002-12-13 20:15:29 +0000949{
950 struct route_node *rn;
paul1eb8ef22005-04-07 07:30:20 +0000951 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000952 struct ospf_network *network;
953 struct ospf_area *area;
paul1eb8ef22005-04-07 07:30:20 +0000954 struct ospf_interface *oi;
paul718e3742002-12-13 20:15:29 +0000955
paul68980082003-03-25 05:07:42 +0000956 if (ospf != NULL)
paul718e3742002-12-13 20:15:29 +0000957 {
paulb29800a2005-11-20 14:50:45 +0000958 /* Router-ID must be configured. */
paul86752842006-01-10 20:34:46 +0000959 if (ospf->router_id.s_addr == 0)
paulb29800a2005-11-20 14:50:45 +0000960 return;
961
paul718e3742002-12-13 20:15:29 +0000962 /* Find interfaces that not configured already. */
paul1eb8ef22005-04-07 07:30:20 +0000963 for (ALL_LIST_ELEMENTS (ospf->oiflist, node, nnode, oi))
paul718e3742002-12-13 20:15:29 +0000964 {
965 int found = 0;
paul718e3742002-12-13 20:15:29 +0000966 struct connected *co = oi->connected;
967
paul718e3742002-12-13 20:15:29 +0000968 if (oi->type == OSPF_IFTYPE_VIRTUALLINK)
969 continue;
970
paul68980082003-03-25 05:07:42 +0000971 for (rn = route_top (ospf->networks); rn; rn = route_next (rn))
paul718e3742002-12-13 20:15:29 +0000972 {
973 if (rn->info == NULL)
974 continue;
975
paul570f7592003-01-25 06:47:41 +0000976 if (ospf_network_match_iface(co,&rn->p))
paul718e3742002-12-13 20:15:29 +0000977 {
978 found = 1;
979 route_unlock_node (rn);
980 break;
981 }
982 }
983
984 if (found == 0)
985 ospf_if_free (oi);
986 }
987
988 /* Run each interface. */
paul68980082003-03-25 05:07:42 +0000989 for (rn = route_top (ospf->networks); rn; rn = route_next (rn))
paul718e3742002-12-13 20:15:29 +0000990 if (rn->info != NULL)
991 {
992 network = (struct ospf_network *) rn->info;
paul68980082003-03-25 05:07:42 +0000993 area = ospf_area_get (ospf, network->area_id, network->format);
994 ospf_network_run (ospf, &rn->p, area);
paul718e3742002-12-13 20:15:29 +0000995 }
996 }
997}
998
999void
paul68980082003-03-25 05:07:42 +00001000ospf_remove_vls_through_area (struct ospf *ospf, struct ospf_area *area)
paul718e3742002-12-13 20:15:29 +00001001{
paul1eb8ef22005-04-07 07:30:20 +00001002 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001003 struct ospf_vl_data *vl_data;
1004
paul1eb8ef22005-04-07 07:30:20 +00001005 for (ALL_LIST_ELEMENTS (ospf->vlinks, node, nnode, vl_data))
1006 if (IPV4_ADDR_SAME (&vl_data->vl_area_id, &area->area_id))
1007 ospf_vl_delete (ospf, vl_data);
paul718e3742002-12-13 20:15:29 +00001008}
1009
1010
1011struct message ospf_area_type_msg[] =
1012{
1013 { OSPF_AREA_DEFAULT, "Default" },
1014 { OSPF_AREA_STUB, "Stub" },
1015 { OSPF_AREA_NSSA, "NSSA" },
1016};
1017int ospf_area_type_msg_max = OSPF_AREA_TYPE_MAX;
1018
paul4dadc292005-05-06 21:37:42 +00001019static void
paul718e3742002-12-13 20:15:29 +00001020ospf_area_type_set (struct ospf_area *area, int type)
1021{
hasso52dc7ee2004-09-23 19:18:23 +00001022 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00001023 struct ospf_interface *oi;
1024
1025 if (area->external_routing == type)
1026 {
1027 if (IS_DEBUG_OSPF_EVENT)
ajs9b0e25c2004-12-08 19:06:51 +00001028 zlog_debug ("Area[%s]: Types are the same, ignored.",
paul718e3742002-12-13 20:15:29 +00001029 inet_ntoa (area->area_id));
1030 return;
1031 }
1032
1033 area->external_routing = type;
1034
1035 if (IS_DEBUG_OSPF_EVENT)
ajs9b0e25c2004-12-08 19:06:51 +00001036 zlog_debug ("Area[%s]: Configured as %s", inet_ntoa (area->area_id),
paul718e3742002-12-13 20:15:29 +00001037 LOOKUP (ospf_area_type_msg, type));
1038
1039 switch (area->external_routing)
1040 {
1041 case OSPF_AREA_DEFAULT:
paul1eb8ef22005-04-07 07:30:20 +00001042 for (ALL_LIST_ELEMENTS_RO (area->oiflist, node, oi))
1043 if (oi->nbr_self != NULL)
1044 {
1045 UNSET_FLAG (oi->nbr_self->options, OSPF_OPTION_NP);
1046 SET_FLAG (oi->nbr_self->options, OSPF_OPTION_E);
1047 }
paul718e3742002-12-13 20:15:29 +00001048 break;
1049 case OSPF_AREA_STUB:
paul1eb8ef22005-04-07 07:30:20 +00001050 for (ALL_LIST_ELEMENTS_RO (area->oiflist, node, oi))
1051 if (oi->nbr_self != NULL)
1052 {
1053 if (IS_DEBUG_OSPF_EVENT)
1054 zlog_debug ("setting options on %s accordingly", IF_NAME (oi));
1055 UNSET_FLAG (oi->nbr_self->options, OSPF_OPTION_NP);
1056 UNSET_FLAG (oi->nbr_self->options, OSPF_OPTION_E);
1057 if (IS_DEBUG_OSPF_EVENT)
1058 zlog_debug ("options set on %s: %x",
1059 IF_NAME (oi), OPTIONS (oi));
1060 }
paul718e3742002-12-13 20:15:29 +00001061 break;
1062 case OSPF_AREA_NSSA:
paul1eb8ef22005-04-07 07:30:20 +00001063 for (ALL_LIST_ELEMENTS_RO (area->oiflist, node, oi))
1064 if (oi->nbr_self != NULL)
1065 {
1066 zlog_debug ("setting nssa options on %s accordingly", IF_NAME (oi));
1067 UNSET_FLAG (oi->nbr_self->options, OSPF_OPTION_E);
1068 SET_FLAG (oi->nbr_self->options, OSPF_OPTION_NP);
1069 zlog_debug ("options set on %s: %x", IF_NAME (oi), OPTIONS (oi));
1070 }
paul718e3742002-12-13 20:15:29 +00001071 break;
1072 default:
1073 break;
1074 }
1075
1076 ospf_router_lsa_timer_add (area);
paul68980082003-03-25 05:07:42 +00001077 ospf_schedule_abr_task (area->ospf);
paul718e3742002-12-13 20:15:29 +00001078}
1079
1080int
paul68980082003-03-25 05:07:42 +00001081ospf_area_shortcut_set (struct ospf *ospf, struct ospf_area *area, int mode)
paul718e3742002-12-13 20:15:29 +00001082{
1083 if (area->shortcut_configured == mode)
1084 return 0;
1085
1086 area->shortcut_configured = mode;
1087 ospf_router_lsa_timer_add (area);
paul68980082003-03-25 05:07:42 +00001088 ospf_schedule_abr_task (ospf);
paul718e3742002-12-13 20:15:29 +00001089
paul68980082003-03-25 05:07:42 +00001090 ospf_area_check_free (ospf, area->area_id);
paul718e3742002-12-13 20:15:29 +00001091
1092 return 1;
1093}
1094
1095int
paul68980082003-03-25 05:07:42 +00001096ospf_area_shortcut_unset (struct ospf *ospf, struct ospf_area *area)
paul718e3742002-12-13 20:15:29 +00001097{
1098 area->shortcut_configured = OSPF_SHORTCUT_DEFAULT;
1099 ospf_router_lsa_timer_add (area);
paul68980082003-03-25 05:07:42 +00001100 ospf_area_check_free (ospf, area->area_id);
1101 ospf_schedule_abr_task (ospf);
paul718e3742002-12-13 20:15:29 +00001102
1103 return 1;
1104}
1105
paul4dadc292005-05-06 21:37:42 +00001106static int
paul718e3742002-12-13 20:15:29 +00001107ospf_area_vlink_count (struct ospf *ospf, struct ospf_area *area)
1108{
1109 struct ospf_vl_data *vl;
hasso52dc7ee2004-09-23 19:18:23 +00001110 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00001111 int count = 0;
1112
paul1eb8ef22005-04-07 07:30:20 +00001113 for (ALL_LIST_ELEMENTS_RO (ospf->vlinks, node, vl))
1114 if (IPV4_ADDR_SAME (&vl->vl_area_id, &area->area_id))
1115 count++;
paul718e3742002-12-13 20:15:29 +00001116
1117 return count;
1118}
1119
1120int
1121ospf_area_stub_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 if (ospf_area_vlink_count (ospf, area))
1128 return 0;
1129
1130 if (area->external_routing != OSPF_AREA_STUB)
1131 ospf_area_type_set (area, OSPF_AREA_STUB);
1132
1133 return 1;
1134}
1135
1136int
1137ospf_area_stub_unset (struct ospf *ospf, struct in_addr area_id)
1138{
1139 struct ospf_area *area;
1140
paul68980082003-03-25 05:07:42 +00001141 area = ospf_area_lookup_by_area_id (ospf, area_id);
paul718e3742002-12-13 20:15:29 +00001142 if (area == NULL)
1143 return 1;
1144
1145 if (area->external_routing == OSPF_AREA_STUB)
1146 ospf_area_type_set (area, OSPF_AREA_DEFAULT);
1147
paul68980082003-03-25 05:07:42 +00001148 ospf_area_check_free (ospf, area_id);
paul718e3742002-12-13 20:15:29 +00001149
1150 return 1;
1151}
1152
1153int
1154ospf_area_no_summary_set (struct ospf *ospf, struct in_addr area_id)
1155{
1156 struct ospf_area *area;
paul147193a2003-04-19 00:31:59 +00001157 int format = OSPF_AREA_ID_FORMAT_ADDRESS;
paul718e3742002-12-13 20:15:29 +00001158
paul68980082003-03-25 05:07:42 +00001159 area = ospf_area_get (ospf, area_id, format);
paul718e3742002-12-13 20:15:29 +00001160 area->no_summary = 1;
1161
1162 return 1;
1163}
1164
1165int
1166ospf_area_no_summary_unset (struct ospf *ospf, struct in_addr area_id)
1167{
1168 struct ospf_area *area;
1169
paul68980082003-03-25 05:07:42 +00001170 area = ospf_area_lookup_by_area_id (ospf, area_id);
paul718e3742002-12-13 20:15:29 +00001171 if (area == NULL)
1172 return 0;
1173
1174 area->no_summary = 0;
paul68980082003-03-25 05:07:42 +00001175 ospf_area_check_free (ospf, area_id);
paul718e3742002-12-13 20:15:29 +00001176
1177 return 1;
1178}
1179
1180int
1181ospf_area_nssa_set (struct ospf *ospf, struct in_addr area_id)
1182{
1183 struct ospf_area *area;
paul147193a2003-04-19 00:31:59 +00001184 int format = OSPF_AREA_ID_FORMAT_ADDRESS;
paul718e3742002-12-13 20:15:29 +00001185
paul68980082003-03-25 05:07:42 +00001186 area = ospf_area_get (ospf, area_id, format);
paul718e3742002-12-13 20:15:29 +00001187 if (ospf_area_vlink_count (ospf, area))
1188 return 0;
1189
1190 if (area->external_routing != OSPF_AREA_NSSA)
1191 {
1192 ospf_area_type_set (area, OSPF_AREA_NSSA);
1193 ospf->anyNSSA++;
1194 }
1195
paul084c7842003-06-22 08:35:18 +00001196 /* set NSSA area defaults */
1197 area->no_summary = 0;
1198 area->NSSATranslatorRole = OSPF_NSSA_ROLE_CANDIDATE;
pauld4a53d52003-07-12 21:30:57 +00001199 area->NSSATranslatorState = OSPF_NSSA_TRANSLATE_DISABLED;
paul084c7842003-06-22 08:35:18 +00001200 area->NSSATranslatorStabilityInterval = OSPF_NSSA_TRANS_STABLE_DEFAULT;
1201
paul718e3742002-12-13 20:15:29 +00001202 return 1;
1203}
1204
1205int
1206ospf_area_nssa_unset (struct ospf *ospf, struct in_addr area_id)
1207{
1208 struct ospf_area *area;
1209
paul68980082003-03-25 05:07:42 +00001210 area = ospf_area_lookup_by_area_id (ospf, area_id);
paul718e3742002-12-13 20:15:29 +00001211 if (area == NULL)
1212 return 0;
1213
1214 if (area->external_routing == OSPF_AREA_NSSA)
1215 {
1216 ospf->anyNSSA--;
1217 ospf_area_type_set (area, OSPF_AREA_DEFAULT);
1218 }
1219
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
1226ospf_area_nssa_translator_role_set (struct ospf *ospf, struct in_addr area_id,
1227 int role)
1228{
1229 struct ospf_area *area;
1230
paul68980082003-03-25 05:07:42 +00001231 area = ospf_area_lookup_by_area_id (ospf, area_id);
paul718e3742002-12-13 20:15:29 +00001232 if (area == NULL)
1233 return 0;
1234
paul084c7842003-06-22 08:35:18 +00001235 area->NSSATranslatorRole = role;
paul718e3742002-12-13 20:15:29 +00001236
1237 return 1;
1238}
1239
paul4dadc292005-05-06 21:37:42 +00001240/* XXX: unused? Leave for symmetry? */
1241static int
paul718e3742002-12-13 20:15:29 +00001242ospf_area_nssa_translator_role_unset (struct ospf *ospf,
1243 struct in_addr area_id)
1244{
1245 struct ospf_area *area;
1246
paul68980082003-03-25 05:07:42 +00001247 area = ospf_area_lookup_by_area_id (ospf, area_id);
paul718e3742002-12-13 20:15:29 +00001248 if (area == NULL)
1249 return 0;
1250
paul084c7842003-06-22 08:35:18 +00001251 area->NSSATranslatorRole = OSPF_NSSA_ROLE_CANDIDATE;
paul718e3742002-12-13 20:15:29 +00001252
paul68980082003-03-25 05:07:42 +00001253 ospf_area_check_free (ospf, area_id);
paul718e3742002-12-13 20:15:29 +00001254
1255 return 1;
1256}
1257
1258int
paul68980082003-03-25 05:07:42 +00001259ospf_area_export_list_set (struct ospf *ospf,
paul6c835672004-10-11 11:00:30 +00001260 struct ospf_area *area, const char *list_name)
paul718e3742002-12-13 20:15:29 +00001261{
1262 struct access_list *list;
1263 list = access_list_lookup (AFI_IP, list_name);
1264
1265 EXPORT_LIST (area) = list;
1266
1267 if (EXPORT_NAME (area))
1268 free (EXPORT_NAME (area));
1269
1270 EXPORT_NAME (area) = strdup (list_name);
paul68980082003-03-25 05:07:42 +00001271 ospf_schedule_abr_task (ospf);
paul718e3742002-12-13 20:15:29 +00001272
1273 return 1;
1274}
1275
1276int
paul68980082003-03-25 05:07:42 +00001277ospf_area_export_list_unset (struct ospf *ospf, struct ospf_area * area)
paul718e3742002-12-13 20:15:29 +00001278{
1279
1280 EXPORT_LIST (area) = 0;
1281
1282 if (EXPORT_NAME (area))
1283 free (EXPORT_NAME (area));
1284
1285 EXPORT_NAME (area) = NULL;
1286
paul68980082003-03-25 05:07:42 +00001287 ospf_area_check_free (ospf, area->area_id);
paul718e3742002-12-13 20:15:29 +00001288
paul68980082003-03-25 05:07:42 +00001289 ospf_schedule_abr_task (ospf);
paul718e3742002-12-13 20:15:29 +00001290
1291 return 1;
1292}
1293
1294int
paul6c835672004-10-11 11:00:30 +00001295ospf_area_import_list_set (struct ospf *ospf, struct ospf_area *area,
1296 const char *name)
paul718e3742002-12-13 20:15:29 +00001297{
1298 struct access_list *list;
1299 list = access_list_lookup (AFI_IP, name);
1300
1301 IMPORT_LIST (area) = list;
1302
1303 if (IMPORT_NAME (area))
1304 free (IMPORT_NAME (area));
1305
1306 IMPORT_NAME (area) = strdup (name);
paul68980082003-03-25 05:07:42 +00001307 ospf_schedule_abr_task (ospf);
paul718e3742002-12-13 20:15:29 +00001308
1309 return 1;
1310}
1311
1312int
paul68980082003-03-25 05:07:42 +00001313ospf_area_import_list_unset (struct ospf *ospf, struct ospf_area * area)
paul718e3742002-12-13 20:15:29 +00001314{
1315 IMPORT_LIST (area) = 0;
1316
1317 if (IMPORT_NAME (area))
1318 free (IMPORT_NAME (area));
1319
1320 IMPORT_NAME (area) = NULL;
paul68980082003-03-25 05:07:42 +00001321 ospf_area_check_free (ospf, area->area_id);
paul718e3742002-12-13 20:15:29 +00001322
paul68980082003-03-25 05:07:42 +00001323 ospf_schedule_abr_task (ospf);
paul718e3742002-12-13 20:15:29 +00001324
1325 return 1;
1326}
1327
1328int
paul718e3742002-12-13 20:15:29 +00001329ospf_timers_refresh_set (struct ospf *ospf, int interval)
1330{
1331 int time_left;
1332
1333 if (ospf->lsa_refresh_interval == interval)
1334 return 1;
1335
1336 time_left = ospf->lsa_refresh_interval -
Paul Jakma2518efd2006-08-27 06:49:29 +00001337 (quagga_time (NULL) - ospf->lsa_refresher_started);
paul718e3742002-12-13 20:15:29 +00001338
1339 if (time_left > interval)
1340 {
1341 OSPF_TIMER_OFF (ospf->t_lsa_refresher);
1342 ospf->t_lsa_refresher =
1343 thread_add_timer (master, ospf_lsa_refresh_walker, ospf, interval);
1344 }
1345 ospf->lsa_refresh_interval = interval;
1346
1347 return 1;
1348}
1349
1350int
1351ospf_timers_refresh_unset (struct ospf *ospf)
1352{
1353 int time_left;
1354
1355 time_left = ospf->lsa_refresh_interval -
Paul Jakma2518efd2006-08-27 06:49:29 +00001356 (quagga_time (NULL) - ospf->lsa_refresher_started);
paul718e3742002-12-13 20:15:29 +00001357
1358 if (time_left > OSPF_LSA_REFRESH_INTERVAL_DEFAULT)
1359 {
1360 OSPF_TIMER_OFF (ospf->t_lsa_refresher);
1361 ospf->t_lsa_refresher =
1362 thread_add_timer (master, ospf_lsa_refresh_walker, ospf,
1363 OSPF_LSA_REFRESH_INTERVAL_DEFAULT);
1364 }
1365
1366 ospf->lsa_refresh_interval = OSPF_LSA_REFRESH_INTERVAL_DEFAULT;
1367
1368 return 1;
1369}
1370
1371
paul4dadc292005-05-06 21:37:42 +00001372static struct ospf_nbr_nbma *
1373ospf_nbr_nbma_new (void)
paul718e3742002-12-13 20:15:29 +00001374{
1375 struct ospf_nbr_nbma *nbr_nbma;
1376
1377 nbr_nbma = XMALLOC (MTYPE_OSPF_NEIGHBOR_STATIC,
1378 sizeof (struct ospf_nbr_nbma));
1379 memset (nbr_nbma, 0, sizeof (struct ospf_nbr_nbma));
1380
1381 nbr_nbma->priority = OSPF_NEIGHBOR_PRIORITY_DEFAULT;
1382 nbr_nbma->v_poll = OSPF_POLL_INTERVAL_DEFAULT;
1383
1384 return nbr_nbma;
1385}
1386
paul4dadc292005-05-06 21:37:42 +00001387static void
paul718e3742002-12-13 20:15:29 +00001388ospf_nbr_nbma_free (struct ospf_nbr_nbma *nbr_nbma)
1389{
1390 XFREE (MTYPE_OSPF_NEIGHBOR_STATIC, nbr_nbma);
1391}
1392
paul4dadc292005-05-06 21:37:42 +00001393static void
paul718e3742002-12-13 20:15:29 +00001394ospf_nbr_nbma_delete (struct ospf *ospf, struct ospf_nbr_nbma *nbr_nbma)
1395{
1396 struct route_node *rn;
1397 struct prefix_ipv4 p;
1398
1399 p.family = AF_INET;
1400 p.prefix = nbr_nbma->addr;
1401 p.prefixlen = IPV4_MAX_BITLEN;
1402
1403 rn = route_node_lookup (ospf->nbr_nbma, (struct prefix *)&p);
1404 if (rn)
1405 {
1406 ospf_nbr_nbma_free (rn->info);
1407 rn->info = NULL;
1408 route_unlock_node (rn);
1409 route_unlock_node (rn);
1410 }
1411}
1412
paul4dadc292005-05-06 21:37:42 +00001413static void
paul718e3742002-12-13 20:15:29 +00001414ospf_nbr_nbma_down (struct ospf_nbr_nbma *nbr_nbma)
1415{
1416 OSPF_TIMER_OFF (nbr_nbma->t_poll);
1417
1418 if (nbr_nbma->nbr)
1419 {
1420 nbr_nbma->nbr->nbr_nbma = NULL;
1421 OSPF_NSM_EVENT_EXECUTE (nbr_nbma->nbr, NSM_KillNbr);
1422 }
1423
1424 if (nbr_nbma->oi)
1425 listnode_delete (nbr_nbma->oi->nbr_nbma, nbr_nbma);
1426}
1427
paul4dadc292005-05-06 21:37:42 +00001428static void
paul718e3742002-12-13 20:15:29 +00001429ospf_nbr_nbma_add (struct ospf_nbr_nbma *nbr_nbma,
1430 struct ospf_interface *oi)
1431{
1432 struct ospf_neighbor *nbr;
1433 struct route_node *rn;
1434 struct prefix p;
1435
1436 if (oi->type != OSPF_IFTYPE_NBMA)
1437 return;
1438
1439 if (nbr_nbma->nbr != NULL)
1440 return;
1441
1442 if (IPV4_ADDR_SAME (&oi->nbr_self->address.u.prefix4, &nbr_nbma->addr))
1443 return;
1444
1445 nbr_nbma->oi = oi;
1446 listnode_add (oi->nbr_nbma, nbr_nbma);
1447
1448 /* Get neighbor information from table. */
1449 p.family = AF_INET;
1450 p.prefixlen = IPV4_MAX_BITLEN;
1451 p.u.prefix4 = nbr_nbma->addr;
1452
1453 rn = route_node_get (oi->nbrs, (struct prefix *)&p);
1454 if (rn->info)
1455 {
1456 nbr = rn->info;
1457 nbr->nbr_nbma = nbr_nbma;
1458 nbr_nbma->nbr = nbr;
1459
1460 route_unlock_node (rn);
1461 }
1462 else
1463 {
1464 nbr = rn->info = ospf_nbr_new (oi);
1465 nbr->state = NSM_Down;
1466 nbr->src = nbr_nbma->addr;
1467 nbr->nbr_nbma = nbr_nbma;
1468 nbr->priority = nbr_nbma->priority;
1469 nbr->address = p;
1470
1471 nbr_nbma->nbr = nbr;
1472
1473 OSPF_NSM_EVENT_EXECUTE (nbr, NSM_Start);
1474 }
1475}
1476
1477void
paul68980082003-03-25 05:07:42 +00001478ospf_nbr_nbma_if_update (struct ospf *ospf, struct ospf_interface *oi)
paul718e3742002-12-13 20:15:29 +00001479{
1480 struct ospf_nbr_nbma *nbr_nbma;
1481 struct route_node *rn;
1482 struct prefix_ipv4 p;
1483
1484 if (oi->type != OSPF_IFTYPE_NBMA)
1485 return;
1486
paul68980082003-03-25 05:07:42 +00001487 for (rn = route_top (ospf->nbr_nbma); rn; rn = route_next (rn))
paul718e3742002-12-13 20:15:29 +00001488 if ((nbr_nbma = rn->info))
1489 if (nbr_nbma->oi == NULL && nbr_nbma->nbr == NULL)
1490 {
1491 p.family = AF_INET;
1492 p.prefix = nbr_nbma->addr;
1493 p.prefixlen = IPV4_MAX_BITLEN;
1494
1495 if (prefix_match (oi->address, (struct prefix *)&p))
1496 ospf_nbr_nbma_add (nbr_nbma, oi);
1497 }
1498}
1499
1500struct ospf_nbr_nbma *
1501ospf_nbr_nbma_lookup (struct ospf *ospf, struct in_addr nbr_addr)
1502{
1503 struct route_node *rn;
1504 struct prefix_ipv4 p;
1505
1506 p.family = AF_INET;
1507 p.prefix = nbr_addr;
1508 p.prefixlen = IPV4_MAX_BITLEN;
1509
1510 rn = route_node_lookup (ospf->nbr_nbma, (struct prefix *)&p);
1511 if (rn)
1512 {
1513 route_unlock_node (rn);
1514 return rn->info;
1515 }
1516 return NULL;
1517}
1518
1519struct ospf_nbr_nbma *
paul68980082003-03-25 05:07:42 +00001520ospf_nbr_nbma_lookup_next (struct ospf *ospf, struct in_addr *addr, int first)
paul718e3742002-12-13 20:15:29 +00001521{
1522#if 0
1523 struct ospf_nbr_nbma *nbr_nbma;
hasso52dc7ee2004-09-23 19:18:23 +00001524 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00001525#endif
1526
paul68980082003-03-25 05:07:42 +00001527 if (ospf == NULL)
paul718e3742002-12-13 20:15:29 +00001528 return NULL;
1529
1530#if 0
paul1eb8ef22005-04-07 07:30:20 +00001531 for (ALL_LIST_ELEMENTS_RO (ospf->nbr_nbma, node, nbr_nbma))
paul718e3742002-12-13 20:15:29 +00001532 {
paul718e3742002-12-13 20:15:29 +00001533 if (first)
1534 {
1535 *addr = nbr_nbma->addr;
1536 return nbr_nbma;
1537 }
1538 else if (ntohl (nbr_nbma->addr.s_addr) > ntohl (addr->s_addr))
1539 {
1540 *addr = nbr_nbma->addr;
1541 return nbr_nbma;
1542 }
1543 }
1544#endif
1545 return NULL;
1546}
1547
1548int
1549ospf_nbr_nbma_set (struct ospf *ospf, struct in_addr nbr_addr)
1550{
1551 struct ospf_nbr_nbma *nbr_nbma;
1552 struct ospf_interface *oi;
1553 struct prefix_ipv4 p;
1554 struct route_node *rn;
hasso52dc7ee2004-09-23 19:18:23 +00001555 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00001556
1557 nbr_nbma = ospf_nbr_nbma_lookup (ospf, nbr_addr);
1558 if (nbr_nbma)
1559 return 0;
1560
1561 nbr_nbma = ospf_nbr_nbma_new ();
1562 nbr_nbma->addr = nbr_addr;
1563
1564 p.family = AF_INET;
1565 p.prefix = nbr_addr;
1566 p.prefixlen = IPV4_MAX_BITLEN;
1567
1568 rn = route_node_get (ospf->nbr_nbma, (struct prefix *)&p);
1569 rn->info = nbr_nbma;
1570
paul1eb8ef22005-04-07 07:30:20 +00001571 for (ALL_LIST_ELEMENTS_RO (ospf->oiflist, node, oi))
paul718e3742002-12-13 20:15:29 +00001572 {
paul718e3742002-12-13 20:15:29 +00001573 if (oi->type == OSPF_IFTYPE_NBMA)
1574 if (prefix_match (oi->address, (struct prefix *)&p))
1575 {
1576 ospf_nbr_nbma_add (nbr_nbma, oi);
1577 break;
1578 }
1579 }
1580
1581 return 1;
1582}
1583
1584int
1585ospf_nbr_nbma_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 ospf_nbr_nbma_down (nbr_nbma);
1594 ospf_nbr_nbma_delete (ospf, nbr_nbma);
1595
1596 return 1;
1597}
1598
1599int
1600ospf_nbr_nbma_priority_set (struct ospf *ospf, struct in_addr nbr_addr,
1601 u_char priority)
1602{
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->priority != priority)
1610 nbr_nbma->priority = priority;
1611
1612 return 1;
1613}
1614
1615int
1616ospf_nbr_nbma_priority_unset (struct ospf *ospf, struct in_addr nbr_addr)
1617{
1618 struct ospf_nbr_nbma *nbr_nbma;
1619
1620 nbr_nbma = ospf_nbr_nbma_lookup (ospf, nbr_addr);
1621 if (nbr_nbma == NULL)
1622 return 0;
1623
1624 if (nbr_nbma != OSPF_NEIGHBOR_PRIORITY_DEFAULT)
1625 nbr_nbma->priority = OSPF_NEIGHBOR_PRIORITY_DEFAULT;
1626
1627 return 1;
1628}
1629
1630int
1631ospf_nbr_nbma_poll_interval_set (struct ospf *ospf, struct in_addr nbr_addr,
paul6c835672004-10-11 11:00:30 +00001632 unsigned int interval)
paul718e3742002-12-13 20:15:29 +00001633{
1634 struct ospf_nbr_nbma *nbr_nbma;
1635
1636 nbr_nbma = ospf_nbr_nbma_lookup (ospf, nbr_addr);
1637 if (nbr_nbma == NULL)
1638 return 0;
1639
1640 if (nbr_nbma->v_poll != interval)
1641 {
1642 nbr_nbma->v_poll = interval;
1643 if (nbr_nbma->oi && ospf_if_is_up (nbr_nbma->oi))
1644 {
1645 OSPF_TIMER_OFF (nbr_nbma->t_poll);
1646 OSPF_POLL_TIMER_ON (nbr_nbma->t_poll, ospf_poll_timer,
1647 nbr_nbma->v_poll);
1648 }
1649 }
1650
1651 return 1;
1652}
1653
1654int
1655ospf_nbr_nbma_poll_interval_unset (struct ospf *ospf, struct in_addr addr)
1656{
1657 struct ospf_nbr_nbma *nbr_nbma;
1658
1659 nbr_nbma = ospf_nbr_nbma_lookup (ospf, addr);
1660 if (nbr_nbma == NULL)
1661 return 0;
1662
1663 if (nbr_nbma->v_poll != OSPF_POLL_INTERVAL_DEFAULT)
1664 nbr_nbma->v_poll = OSPF_POLL_INTERVAL_DEFAULT;
1665
1666 return 1;
1667}
1668
paul718e3742002-12-13 20:15:29 +00001669void
paul020709f2003-04-04 02:44:16 +00001670ospf_master_init ()
1671{
1672 memset (&ospf_master, 0, sizeof (struct ospf_master));
1673
1674 om = &ospf_master;
1675 om->ospf = list_new ();
1676 om->master = thread_master_create ();
Paul Jakma2518efd2006-08-27 06:49:29 +00001677 om->start_time = quagga_time (NULL);
paul020709f2003-04-04 02:44:16 +00001678}