blob: a1f0f0111f794ebefabf07df4ac0d0a6612fd398 [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
170 new->new_external_route = route_table_init ();
171 new->old_external_route = route_table_init ();
172 new->external_lsas = route_table_init ();
paul88d6cf32005-10-29 12:50:09 +0000173
174 new->stub_router_startup_time = OSPF_STUB_ROUTER_UNCONFIGURED;
paul31a59762005-11-14 11:11:11 +0000175 new->stub_router_shutdown_time = OSPF_STUB_ROUTER_UNCONFIGURED;
paul88d6cf32005-10-29 12:50:09 +0000176
paul718e3742002-12-13 20:15:29 +0000177 /* Distribute parameter init. */
178 for (i = 0; i <= ZEBRA_ROUTE_MAX; i++)
179 {
180 new->dmetric[i].type = -1;
181 new->dmetric[i].value = -1;
182 }
183 new->default_metric = -1;
184 new->ref_bandwidth = OSPF_DEFAULT_REF_BANDWIDTH;
185
186 /* SPF timer value init. */
187 new->spf_delay = OSPF_SPF_DELAY_DEFAULT;
188 new->spf_holdtime = OSPF_SPF_HOLDTIME_DEFAULT;
pauld24f6e22005-10-21 09:23:12 +0000189 new->spf_max_holdtime = OSPF_SPF_MAX_HOLDTIME_DEFAULT;
190 new->spf_hold_multiplier = 1;
paul718e3742002-12-13 20:15:29 +0000191
192 /* MaxAge init. */
193 new->maxage_lsa = list_new ();
194 new->t_maxage_walker =
195 thread_add_timer (master, ospf_lsa_maxage_walker,
paul68980082003-03-25 05:07:42 +0000196 new, OSPF_LSA_MAXAGE_CHECK_INTERVAL);
paul718e3742002-12-13 20:15:29 +0000197
198 /* Distance table init. */
199 new->distance_table = route_table_init ();
200
201 new->lsa_refresh_queue.index = 0;
202 new->lsa_refresh_interval = OSPF_LSA_REFRESH_INTERVAL_DEFAULT;
203 new->t_lsa_refresher = thread_add_timer (master, ospf_lsa_refresh_walker,
204 new, new->lsa_refresh_interval);
Paul Jakma2518efd2006-08-27 06:49:29 +0000205 new->lsa_refresher_started = quagga_time (NULL);
paul718e3742002-12-13 20:15:29 +0000206
ajs5c333492005-02-23 15:43:01 +0000207 if ((new->fd = ospf_sock_init()) < 0)
208 {
209 zlog_err("ospf_new: fatal error: ospf_sock_init was unable to open "
210 "a socket");
211 exit(1);
212 }
213 if ((new->ibuf = stream_new(OSPF_MAX_PACKET_SIZE+1)) == NULL)
214 {
215 zlog_err("ospf_new: fatal error: stream_new(%u) failed allocating ibuf",
216 OSPF_MAX_PACKET_SIZE+1);
217 exit(1);
218 }
219 new->t_read = thread_add_read (master, ospf_read, new, new->fd);
paul718e3742002-12-13 20:15:29 +0000220 new->oi_write_q = list_new ();
221
222 return new;
223}
224
225struct ospf *
paul020709f2003-04-04 02:44:16 +0000226ospf_lookup ()
227{
228 if (listcount (om->ospf) == 0)
229 return NULL;
230
paul1eb8ef22005-04-07 07:30:20 +0000231 return listgetdata (listhead (om->ospf));
paul020709f2003-04-04 02:44:16 +0000232}
233
paul4dadc292005-05-06 21:37:42 +0000234static void
paul020709f2003-04-04 02:44:16 +0000235ospf_add (struct ospf *ospf)
236{
237 listnode_add (om->ospf, ospf);
238}
239
paul4dadc292005-05-06 21:37:42 +0000240static void
paul020709f2003-04-04 02:44:16 +0000241ospf_delete (struct ospf *ospf)
242{
243 listnode_delete (om->ospf, ospf);
244}
245
246struct ospf *
paul718e3742002-12-13 20:15:29 +0000247ospf_get ()
248{
paul020709f2003-04-04 02:44:16 +0000249 struct ospf *ospf;
paul718e3742002-12-13 20:15:29 +0000250
paul020709f2003-04-04 02:44:16 +0000251 ospf = ospf_lookup ();
252 if (ospf == NULL)
253 {
254 ospf = ospf_new ();
255 ospf_add (ospf);
paul718e3742002-12-13 20:15:29 +0000256
paul020709f2003-04-04 02:44:16 +0000257 if (ospf->router_id_static.s_addr == 0)
258 ospf_router_id_update (ospf);
paul718e3742002-12-13 20:15:29 +0000259
260#ifdef HAVE_OPAQUE_LSA
paul020709f2003-04-04 02:44:16 +0000261 ospf_opaque_type11_lsa_init (ospf);
paul718e3742002-12-13 20:15:29 +0000262#endif /* HAVE_OPAQUE_LSA */
paul020709f2003-04-04 02:44:16 +0000263 }
paul68980082003-03-25 05:07:42 +0000264
265 return ospf;
paul718e3742002-12-13 20:15:29 +0000266}
paul88d6cf32005-10-29 12:50:09 +0000267
paulc9c93d52005-11-26 13:31:11 +0000268/* Handle the second half of deferred shutdown. This is called either
269 * from the deferred-shutdown timer thread, or directly through
270 * ospf_deferred_shutdown_check.
paul88d6cf32005-10-29 12:50:09 +0000271 *
272 * Function is to cleanup G-R state, if required then call ospf_finish_final
273 * to complete shutdown of this ospf instance. Possibly exit if the
274 * whole process is being shutdown and this was the last OSPF instance.
275 */
276static void
paulc9c93d52005-11-26 13:31:11 +0000277ospf_deferred_shutdown_finish (struct ospf *ospf)
paul88d6cf32005-10-29 12:50:09 +0000278{
279 ospf->stub_router_shutdown_time = OSPF_STUB_ROUTER_UNCONFIGURED;
paulc9c93d52005-11-26 13:31:11 +0000280 OSPF_TIMER_OFF (ospf->t_deferred_shutdown);
paul88d6cf32005-10-29 12:50:09 +0000281
282 ospf_finish_final (ospf);
283
284 /* *ospf is now invalid */
285
286 /* ospfd being shut-down? If so, was this the last ospf instance? */
287 if (CHECK_FLAG (om->options, OSPF_MASTER_SHUTDOWN)
288 && (listcount (om->ospf) == 0))
289 exit (0);
290
291 return;
292}
293
294/* Timer thread for G-R */
295static int
paulc9c93d52005-11-26 13:31:11 +0000296ospf_deferred_shutdown_timer (struct thread *t)
paul88d6cf32005-10-29 12:50:09 +0000297{
298 struct ospf *ospf = THREAD_ARG(t);
299
paulc9c93d52005-11-26 13:31:11 +0000300 ospf_deferred_shutdown_finish (ospf);
paul88d6cf32005-10-29 12:50:09 +0000301
302 return 0;
303}
304
paulc9c93d52005-11-26 13:31:11 +0000305/* Check whether deferred-shutdown must be scheduled, otherwise call
paul88d6cf32005-10-29 12:50:09 +0000306 * down directly into second-half of instance shutdown.
307 */
308static void
paulc9c93d52005-11-26 13:31:11 +0000309ospf_deferred_shutdown_check (struct ospf *ospf)
paul88d6cf32005-10-29 12:50:09 +0000310{
311 unsigned long timeout;
312 struct listnode *ln;
313 struct ospf_area *area;
314
paulc9c93d52005-11-26 13:31:11 +0000315 /* deferred shutdown already running? */
316 if (ospf->t_deferred_shutdown)
paul88d6cf32005-10-29 12:50:09 +0000317 return;
318
319 /* Should we try push out max-metric LSAs? */
320 if (ospf->stub_router_shutdown_time != OSPF_STUB_ROUTER_UNCONFIGURED)
321 {
322 for (ALL_LIST_ELEMENTS_RO (ospf->areas, ln, area))
323 {
324 SET_FLAG (area->stub_router_state, OSPF_AREA_ADMIN_STUB_ROUTED);
325
326 if (!CHECK_FLAG (area->stub_router_state, OSPF_AREA_IS_STUB_ROUTED))
327 ospf_router_lsa_timer_add (area);
328 }
329 timeout = ospf->stub_router_shutdown_time;
330 }
331 else
paulc9c93d52005-11-26 13:31:11 +0000332 {
333 /* No timer needed */
334 ospf_deferred_shutdown_finish (ospf);
335 return;
336 }
paul88d6cf32005-10-29 12:50:09 +0000337
paulc9c93d52005-11-26 13:31:11 +0000338 OSPF_TIMER_ON (ospf->t_deferred_shutdown, ospf_deferred_shutdown_timer,
paul88d6cf32005-10-29 12:50:09 +0000339 timeout);
340 return;
341}
342
343/* Shut down the entire process */
344void
345ospf_terminate (void)
346{
347 struct ospf *ospf;
348 struct listnode *node, *nnode;
349
350 /* shutdown already in progress */
351 if (CHECK_FLAG (om->options, OSPF_MASTER_SHUTDOWN))
352 return;
353
354 SET_FLAG (om->options, OSPF_MASTER_SHUTDOWN);
355
356 for (ALL_LIST_ELEMENTS (om->ospf, node, nnode, ospf))
357 ospf_finish (ospf);
358
359 /* Deliberately go back up, hopefully to thread scheduler, as
360 * One or more ospf_finish()'s may have deferred shutdown to a timer
361 * thread
362 */
363}
paul718e3742002-12-13 20:15:29 +0000364
365void
366ospf_finish (struct ospf *ospf)
367{
paulc9c93d52005-11-26 13:31:11 +0000368 /* let deferred shutdown decide */
369 ospf_deferred_shutdown_check (ospf);
paul88d6cf32005-10-29 12:50:09 +0000370
paulc9c93d52005-11-26 13:31:11 +0000371 /* if ospf_deferred_shutdown returns, then ospf_finish_final is
paul88d6cf32005-10-29 12:50:09 +0000372 * deferred to expiry of G-S timer thread. Return back up, hopefully
373 * to thread scheduler.
374 */
paulc9c93d52005-11-26 13:31:11 +0000375 return;
paul88d6cf32005-10-29 12:50:09 +0000376}
377
378/* Final cleanup of ospf instance */
379static void
380ospf_finish_final (struct ospf *ospf)
381{
paul718e3742002-12-13 20:15:29 +0000382 struct route_node *rn;
383 struct ospf_nbr_nbma *nbr_nbma;
paul68980082003-03-25 05:07:42 +0000384 struct ospf_lsa *lsa;
paul1eb8ef22005-04-07 07:30:20 +0000385 struct ospf_interface *oi;
386 struct ospf_area *area;
387 struct ospf_vl_data *vl_data;
388 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000389 int i;
390
391#ifdef HAVE_OPAQUE_LSA
392 ospf_opaque_type11_lsa_term (ospf);
393#endif /* HAVE_OPAQUE_LSA */
paul88d6cf32005-10-29 12:50:09 +0000394
395 /* be nice if this worked, but it doesn't */
396 /*ospf_flush_self_originated_lsas_now (ospf);*/
397
398 /* Unregister redistribution */
paul718e3742002-12-13 20:15:29 +0000399 for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
paul020709f2003-04-04 02:44:16 +0000400 ospf_redistribute_unset (ospf, i);
paul718e3742002-12-13 20:15:29 +0000401
paul1eb8ef22005-04-07 07:30:20 +0000402 for (ALL_LIST_ELEMENTS (ospf->areas, node, nnode, area))
403 ospf_remove_vls_through_area (ospf, area);
paul718e3742002-12-13 20:15:29 +0000404
paul1eb8ef22005-04-07 07:30:20 +0000405 for (ALL_LIST_ELEMENTS (ospf->vlinks, node, nnode, vl_data))
406 ospf_vl_delete (ospf, vl_data);
paul718e3742002-12-13 20:15:29 +0000407
408 list_delete (ospf->vlinks);
409
410 /* Reset interface. */
paul1eb8ef22005-04-07 07:30:20 +0000411 for (ALL_LIST_ELEMENTS (ospf->oiflist, node, nnode, oi))
412 ospf_if_free (oi);
paul718e3742002-12-13 20:15:29 +0000413
414 /* Clear static neighbors */
415 for (rn = route_top (ospf->nbr_nbma); rn; rn = route_next (rn))
416 if ((nbr_nbma = rn->info))
417 {
418 OSPF_POLL_TIMER_OFF (nbr_nbma->t_poll);
419
420 if (nbr_nbma->nbr)
421 {
422 nbr_nbma->nbr->nbr_nbma = NULL;
423 nbr_nbma->nbr = NULL;
424 }
425
426 if (nbr_nbma->oi)
427 {
428 listnode_delete (nbr_nbma->oi->nbr_nbma, nbr_nbma);
429 nbr_nbma->oi = NULL;
430 }
431
432 XFREE (MTYPE_OSPF_NEIGHBOR_STATIC, nbr_nbma);
433 }
434
435 route_table_finish (ospf->nbr_nbma);
436
437 /* Clear networks and Areas. */
438 for (rn = route_top (ospf->networks); rn; rn = route_next (rn))
439 {
440 struct ospf_network *network;
441
442 if ((network = rn->info) != NULL)
443 {
paul68980082003-03-25 05:07:42 +0000444 ospf_network_free (ospf, network);
paul718e3742002-12-13 20:15:29 +0000445 rn->info = NULL;
446 route_unlock_node (rn);
447 }
448 }
449
paul1eb8ef22005-04-07 07:30:20 +0000450 for (ALL_LIST_ELEMENTS (ospf->areas, node, nnode, area))
paul718e3742002-12-13 20:15:29 +0000451 {
paul718e3742002-12-13 20:15:29 +0000452 listnode_delete (ospf->areas, area);
453 ospf_area_free (area);
454 }
455
456 /* Cancel all timers. */
457 OSPF_TIMER_OFF (ospf->t_external_lsa);
paul718e3742002-12-13 20:15:29 +0000458 OSPF_TIMER_OFF (ospf->t_router_lsa_update);
459 OSPF_TIMER_OFF (ospf->t_spf_calc);
460 OSPF_TIMER_OFF (ospf->t_ase_calc);
461 OSPF_TIMER_OFF (ospf->t_maxage);
462 OSPF_TIMER_OFF (ospf->t_maxage_walker);
463 OSPF_TIMER_OFF (ospf->t_abr_task);
paul88d6cf32005-10-29 12:50:09 +0000464 OSPF_TIMER_OFF (ospf->t_asbr_check);
paul718e3742002-12-13 20:15:29 +0000465 OSPF_TIMER_OFF (ospf->t_distribute_update);
466 OSPF_TIMER_OFF (ospf->t_lsa_refresher);
467 OSPF_TIMER_OFF (ospf->t_read);
468 OSPF_TIMER_OFF (ospf->t_write);
paul31a59762005-11-14 11:11:11 +0000469#ifdef HAVE_OPAQUE_LSA
paul88d6cf32005-10-29 12:50:09 +0000470 OSPF_TIMER_OFF (ospf->t_opaque_lsa_self);
paul31a59762005-11-14 11:11:11 +0000471#endif
paul718e3742002-12-13 20:15:29 +0000472
473 close (ospf->fd);
ajs5c333492005-02-23 15:43:01 +0000474 stream_free(ospf->ibuf);
paul718e3742002-12-13 20:15:29 +0000475
476#ifdef HAVE_OPAQUE_LSA
paul68980082003-03-25 05:07:42 +0000477 LSDB_LOOP (OPAQUE_AS_LSDB (ospf), rn, lsa)
478 ospf_discard_from_db (ospf, ospf->lsdb, lsa);
paul718e3742002-12-13 20:15:29 +0000479#endif /* HAVE_OPAQUE_LSA */
paul68980082003-03-25 05:07:42 +0000480 LSDB_LOOP (EXTERNAL_LSDB (ospf), rn, lsa)
481 ospf_discard_from_db (ospf, ospf->lsdb, lsa);
482
paul718e3742002-12-13 20:15:29 +0000483 ospf_lsdb_delete_all (ospf->lsdb);
484 ospf_lsdb_free (ospf->lsdb);
485
paul1eb8ef22005-04-07 07:30:20 +0000486 for (ALL_LIST_ELEMENTS (ospf->maxage_lsa, node, nnode, lsa))
Paul Jakma1fe6ed32006-07-26 09:37:26 +0000487 ospf_lsa_unlock (&lsa); /* maxage_lsa */
paul718e3742002-12-13 20:15:29 +0000488
489 list_delete (ospf->maxage_lsa);
490
491 if (ospf->old_table)
492 ospf_route_table_free (ospf->old_table);
493 if (ospf->new_table)
494 {
495 ospf_route_delete (ospf->new_table);
496 ospf_route_table_free (ospf->new_table);
497 }
498 if (ospf->old_rtrs)
499 ospf_rtrs_free (ospf->old_rtrs);
500 if (ospf->new_rtrs)
501 ospf_rtrs_free (ospf->new_rtrs);
502 if (ospf->new_external_route)
503 {
504 ospf_route_delete (ospf->new_external_route);
505 ospf_route_table_free (ospf->new_external_route);
506 }
507 if (ospf->old_external_route)
508 {
509 ospf_route_delete (ospf->old_external_route);
510 ospf_route_table_free (ospf->old_external_route);
511 }
512 if (ospf->external_lsas)
513 {
514 ospf_ase_external_lsas_finish (ospf->external_lsas);
515 }
516
517 list_delete (ospf->areas);
518
519 for (i = ZEBRA_ROUTE_SYSTEM; i <= ZEBRA_ROUTE_MAX; i++)
520 if (EXTERNAL_INFO (i) != NULL)
521 for (rn = route_top (EXTERNAL_INFO (i)); rn; rn = route_next (rn))
522 {
523 if (rn->info == NULL)
524 continue;
525
526 XFREE (MTYPE_OSPF_EXTERNAL_INFO, rn->info);
527 rn->info = NULL;
528 route_unlock_node (rn);
529 }
530
paul68980082003-03-25 05:07:42 +0000531 ospf_distance_reset (ospf);
paul718e3742002-12-13 20:15:29 +0000532 route_table_finish (ospf->distance_table);
533
paul020709f2003-04-04 02:44:16 +0000534 ospf_delete (ospf);
paul718e3742002-12-13 20:15:29 +0000535
paul020709f2003-04-04 02:44:16 +0000536 XFREE (MTYPE_OSPF_TOP, ospf);
paul718e3742002-12-13 20:15:29 +0000537}
538
539
540/* allocate new OSPF Area object */
paul4dadc292005-05-06 21:37:42 +0000541static struct ospf_area *
paul68980082003-03-25 05:07:42 +0000542ospf_area_new (struct ospf *ospf, struct in_addr area_id)
paul718e3742002-12-13 20:15:29 +0000543{
544 struct ospf_area *new;
545
546 /* Allocate new config_network. */
547 new = XCALLOC (MTYPE_OSPF_AREA, sizeof (struct ospf_area));
548
paul68980082003-03-25 05:07:42 +0000549 new->ospf = ospf;
paul718e3742002-12-13 20:15:29 +0000550
551 new->area_id = area_id;
552
553 new->external_routing = OSPF_AREA_DEFAULT;
554 new->default_cost = 1;
555 new->auth_type = OSPF_AUTH_NULL;
paul88d6cf32005-10-29 12:50:09 +0000556
paul718e3742002-12-13 20:15:29 +0000557 /* New LSDB init. */
558 new->lsdb = ospf_lsdb_new ();
559
560 /* Self-originated LSAs initialize. */
561 new->router_lsa_self = NULL;
562
563#ifdef HAVE_OPAQUE_LSA
564 ospf_opaque_type10_lsa_init (new);
565#endif /* HAVE_OPAQUE_LSA */
566
567 new->oiflist = list_new ();
568 new->ranges = route_table_init ();
569
570 if (area_id.s_addr == OSPF_AREA_BACKBONE)
paul68980082003-03-25 05:07:42 +0000571 ospf->backbone = new;
paul718e3742002-12-13 20:15:29 +0000572
573 return new;
574}
575
576void
577ospf_area_free (struct ospf_area *area)
578{
paul68980082003-03-25 05:07:42 +0000579 struct route_node *rn;
580 struct ospf_lsa *lsa;
581
paul718e3742002-12-13 20:15:29 +0000582 /* Free LSDBs. */
paul68980082003-03-25 05:07:42 +0000583 LSDB_LOOP (ROUTER_LSDB (area), rn, lsa)
584 ospf_discard_from_db (area->ospf, area->lsdb, lsa);
585 LSDB_LOOP (NETWORK_LSDB (area), rn, lsa)
586 ospf_discard_from_db (area->ospf, area->lsdb, lsa);
587 LSDB_LOOP (SUMMARY_LSDB (area), rn, lsa)
588 ospf_discard_from_db (area->ospf, area->lsdb, lsa);
589 LSDB_LOOP (ASBR_SUMMARY_LSDB (area), rn, lsa)
590 ospf_discard_from_db (area->ospf, area->lsdb, lsa);
paul718e3742002-12-13 20:15:29 +0000591
paul68980082003-03-25 05:07:42 +0000592 LSDB_LOOP (NSSA_LSDB (area), rn, lsa)
593 ospf_discard_from_db (area->ospf, area->lsdb, lsa);
paul718e3742002-12-13 20:15:29 +0000594#ifdef HAVE_OPAQUE_LSA
paul68980082003-03-25 05:07:42 +0000595 LSDB_LOOP (OPAQUE_AREA_LSDB (area), rn, lsa)
596 ospf_discard_from_db (area->ospf, area->lsdb, lsa);
597 LSDB_LOOP (OPAQUE_LINK_LSDB (area), rn, lsa)
598 ospf_discard_from_db (area->ospf, area->lsdb, lsa);
paul718e3742002-12-13 20:15:29 +0000599#endif /* HAVE_OPAQUE_LSA */
600
601 ospf_lsdb_delete_all (area->lsdb);
602 ospf_lsdb_free (area->lsdb);
603
Paul Jakma1fe6ed32006-07-26 09:37:26 +0000604 ospf_lsa_unlock (&area->router_lsa_self);
paul718e3742002-12-13 20:15:29 +0000605
606 route_table_finish (area->ranges);
607 list_delete (area->oiflist);
608
609 if (EXPORT_NAME (area))
610 free (EXPORT_NAME (area));
611
612 if (IMPORT_NAME (area))
613 free (IMPORT_NAME (area));
614
615 /* Cancel timer. */
616 OSPF_TIMER_OFF (area->t_router_lsa_self);
paul88d6cf32005-10-29 12:50:09 +0000617 OSPF_TIMER_OFF (area->t_stub_router);
618#ifdef HAVE_OPAQUE_LSA
619 OSPF_TIMER_OFF (area->t_opaque_lsa_self);
620#endif /* HAVE_OPAQUE_LSA */
621
paul718e3742002-12-13 20:15:29 +0000622 if (OSPF_IS_AREA_BACKBONE (area))
paul68980082003-03-25 05:07:42 +0000623 area->ospf->backbone = NULL;
paul718e3742002-12-13 20:15:29 +0000624
625 XFREE (MTYPE_OSPF_AREA, area);
626}
627
628void
paul68980082003-03-25 05:07:42 +0000629ospf_area_check_free (struct ospf *ospf, struct in_addr area_id)
paul718e3742002-12-13 20:15:29 +0000630{
631 struct ospf_area *area;
632
paul68980082003-03-25 05:07:42 +0000633 area = ospf_area_lookup_by_area_id (ospf, area_id);
paul718e3742002-12-13 20:15:29 +0000634 if (area &&
635 listcount (area->oiflist) == 0 &&
636 area->ranges->top == NULL &&
637 area->shortcut_configured == OSPF_SHORTCUT_DEFAULT &&
638 area->external_routing == OSPF_AREA_DEFAULT &&
639 area->no_summary == 0 &&
640 area->default_cost == 1 &&
641 EXPORT_NAME (area) == NULL &&
642 IMPORT_NAME (area) == NULL &&
643 area->auth_type == OSPF_AUTH_NULL)
644 {
paul68980082003-03-25 05:07:42 +0000645 listnode_delete (ospf->areas, area);
paul718e3742002-12-13 20:15:29 +0000646 ospf_area_free (area);
647 }
648}
649
650struct ospf_area *
paul68980082003-03-25 05:07:42 +0000651ospf_area_get (struct ospf *ospf, struct in_addr area_id, int format)
paul718e3742002-12-13 20:15:29 +0000652{
653 struct ospf_area *area;
654
paul68980082003-03-25 05:07:42 +0000655 area = ospf_area_lookup_by_area_id (ospf, area_id);
paul718e3742002-12-13 20:15:29 +0000656 if (!area)
657 {
paul68980082003-03-25 05:07:42 +0000658 area = ospf_area_new (ospf, area_id);
paul718e3742002-12-13 20:15:29 +0000659 area->format = format;
paul68980082003-03-25 05:07:42 +0000660 listnode_add_sort (ospf->areas, area);
661 ospf_check_abr_status (ospf);
paul718e3742002-12-13 20:15:29 +0000662 }
663
664 return area;
665}
666
667struct ospf_area *
paul68980082003-03-25 05:07:42 +0000668ospf_area_lookup_by_area_id (struct ospf *ospf, struct in_addr area_id)
paul718e3742002-12-13 20:15:29 +0000669{
670 struct ospf_area *area;
hasso52dc7ee2004-09-23 19:18:23 +0000671 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000672
paul1eb8ef22005-04-07 07:30:20 +0000673 for (ALL_LIST_ELEMENTS_RO (ospf->areas, node, area))
674 if (IPV4_ADDR_SAME (&area->area_id, &area_id))
675 return area;
paul718e3742002-12-13 20:15:29 +0000676
677 return NULL;
678}
679
680void
681ospf_area_add_if (struct ospf_area *area, struct ospf_interface *oi)
682{
683 listnode_add (area->oiflist, oi);
684}
685
686void
687ospf_area_del_if (struct ospf_area *area, struct ospf_interface *oi)
688{
689 listnode_delete (area->oiflist, oi);
690}
691
692
693/* Config network statement related functions. */
paul4dadc292005-05-06 21:37:42 +0000694static struct ospf_network *
paul718e3742002-12-13 20:15:29 +0000695ospf_network_new (struct in_addr area_id, int format)
696{
697 struct ospf_network *new;
698 new = XCALLOC (MTYPE_OSPF_NETWORK, sizeof (struct ospf_network));
699
700 new->area_id = area_id;
701 new->format = format;
702
703 return new;
704}
705
706void
paul68980082003-03-25 05:07:42 +0000707ospf_network_free (struct ospf *ospf, struct ospf_network *network)
paul718e3742002-12-13 20:15:29 +0000708{
paul68980082003-03-25 05:07:42 +0000709 ospf_area_check_free (ospf, network->area_id);
710 ospf_schedule_abr_task (ospf);
paul718e3742002-12-13 20:15:29 +0000711 XFREE (MTYPE_OSPF_NETWORK, network);
712}
713
714int
715ospf_network_set (struct ospf *ospf, struct prefix_ipv4 *p,
716 struct in_addr area_id)
717{
718 struct ospf_network *network;
719 struct ospf_area *area;
720 struct route_node *rn;
721 struct external_info *ei;
paul147193a2003-04-19 00:31:59 +0000722 int ret = OSPF_AREA_ID_FORMAT_ADDRESS;
paul718e3742002-12-13 20:15:29 +0000723
724 rn = route_node_get (ospf->networks, (struct prefix *)p);
725 if (rn->info)
726 {
727 /* There is already same network statement. */
728 route_unlock_node (rn);
729 return 0;
730 }
731
732 rn->info = network = ospf_network_new (area_id, ret);
paul68980082003-03-25 05:07:42 +0000733 area = ospf_area_get (ospf, area_id, ret);
paul718e3742002-12-13 20:15:29 +0000734
735 /* Run network config now. */
736 ospf_network_run (ospf, (struct prefix *)p, area);
737
738 /* Update connected redistribute. */
739 if (ospf_is_type_redistributed (ZEBRA_ROUTE_CONNECT))
740 if (EXTERNAL_INFO (ZEBRA_ROUTE_CONNECT))
741 for (rn = route_top (EXTERNAL_INFO (ZEBRA_ROUTE_CONNECT));
742 rn; rn = route_next (rn))
743 if ((ei = rn->info) != NULL)
paul68980082003-03-25 05:07:42 +0000744 if (ospf_external_info_find_lsa (ospf, &ei->p))
745 if (!ospf_distribute_check_connected (ospf, ei))
746 ospf_external_lsa_flush (ospf, ei->type, &ei->p,
ajs5339cfd2005-09-19 13:28:05 +0000747 ei->ifindex /*, ei->nexthop */);
paul718e3742002-12-13 20:15:29 +0000748
paul68980082003-03-25 05:07:42 +0000749 ospf_area_check_free (ospf, area_id);
paul718e3742002-12-13 20:15:29 +0000750
751 return 1;
752}
753
754int
755ospf_network_unset (struct ospf *ospf, struct prefix_ipv4 *p,
756 struct in_addr area_id)
757{
758 struct route_node *rn;
759 struct ospf_network *network;
760 struct external_info *ei;
761
762 rn = route_node_lookup (ospf->networks, (struct prefix *)p);
763 if (rn == NULL)
764 return 0;
765
766 network = rn->info;
767 if (!IPV4_ADDR_SAME (&area_id, &network->area_id))
768 return 0;
769
paul68980082003-03-25 05:07:42 +0000770 ospf_network_free (ospf, rn->info);
paul718e3742002-12-13 20:15:29 +0000771 rn->info = NULL;
772 route_unlock_node (rn);
773
paul68980082003-03-25 05:07:42 +0000774 ospf_if_update (ospf);
paul718e3742002-12-13 20:15:29 +0000775
776 /* Update connected redistribute. */
777 if (ospf_is_type_redistributed (ZEBRA_ROUTE_CONNECT))
778 if (EXTERNAL_INFO (ZEBRA_ROUTE_CONNECT))
779 for (rn = route_top (EXTERNAL_INFO (ZEBRA_ROUTE_CONNECT));
780 rn; rn = route_next (rn))
781 if ((ei = rn->info) != NULL)
paul68980082003-03-25 05:07:42 +0000782 if (!ospf_external_info_find_lsa (ospf, &ei->p))
783 if (ospf_distribute_check_connected (ospf, ei))
784 ospf_external_lsa_originate (ospf, ei);
paul718e3742002-12-13 20:15:29 +0000785
786 return 1;
787}
788
paul570f7592003-01-25 06:47:41 +0000789/* Check whether interface matches given network
790 * returns: 1, true. 0, false
791 */
792int
793ospf_network_match_iface(struct connected *co, struct prefix *net)
794{
795 /* Behaviour to match both Cisco where:
796 * iface address lies within network specified -> ospf
797 * and zebra 0.9[2ish-3]:
798 * PtP special case: network specified == iface peer addr -> ospf
799 */
gdt8f40e892003-12-05 14:01:43 +0000800
paulf3ae74c2004-11-04 20:35:31 +0000801 /* For PtP, match if peer address matches network address exactly.
802 * This can be addr/32 or addr/p for p < 32, but the addr must match
803 * exactly; this is not a test for falling within the prefix. This
gdt8f40e892003-12-05 14:01:43 +0000804 * test is solely for compatibility with zebra.
gdt8f40e892003-12-05 14:01:43 +0000805 */
paulf3ae74c2004-11-04 20:35:31 +0000806 if (if_is_pointopoint (co->ifp) && co->destination &&
807 IPV4_ADDR_SAME ( &(co->destination->u.prefix4), &(net->u.prefix4)))
808 return 1;
809
810#if 0
811 /* Decline to accept PtP if dst address does not match the
812 * prefix. (ifdefed out because this is a workaround, not the
813 * desired behavior.) */
814 if (if_is_pointopoint (co->ifp) &&
815 ! prefix_match (net, co->destination))
816 return 0;
817#endif
818
819 /* If the address is within the prefix, accept. Note that this
820 * applies to PtP as well as other types.
821 */
822 if (prefix_match (net, co->address))
823 return 1;
824
825 return 0; /* no match */
paul570f7592003-01-25 06:47:41 +0000826}
827
paul718e3742002-12-13 20:15:29 +0000828void
829ospf_network_run (struct ospf *ospf, struct prefix *p, struct ospf_area *area)
830{
831 struct interface *ifp;
paul1eb8ef22005-04-07 07:30:20 +0000832 struct connected *co;
hasso52dc7ee2004-09-23 19:18:23 +0000833 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000834
835 /* Schedule Router ID Update. */
paul86752842006-01-10 20:34:46 +0000836 if (ospf->router_id.s_addr == 0)
paulb29800a2005-11-20 14:50:45 +0000837 ospf_router_id_update (ospf);
838
paul718e3742002-12-13 20:15:29 +0000839 /* Get target interface. */
paul1eb8ef22005-04-07 07:30:20 +0000840 for (ALL_LIST_ELEMENTS_RO (om->iflist, node, ifp))
paul718e3742002-12-13 20:15:29 +0000841 {
paul1eb8ef22005-04-07 07:30:20 +0000842 struct listnode *cnode;
paul718e3742002-12-13 20:15:29 +0000843
paul718e3742002-12-13 20:15:29 +0000844 if (memcmp (ifp->name, "VLINK", 5) == 0)
845 continue;
846
847 /* if interface prefix is match specified prefix,
848 then create socket and join multicast group. */
paul1eb8ef22005-04-07 07:30:20 +0000849 for (ALL_LIST_ELEMENTS_RO (ifp->connected, cnode, co))
paul718e3742002-12-13 20:15:29 +0000850 {
paul718e3742002-12-13 20:15:29 +0000851 struct prefix *addr;
paul800dc102003-03-28 01:51:40 +0000852
paule7b050c2003-04-07 06:38:02 +0000853 if (CHECK_FLAG(co->flags,ZEBRA_IFA_SECONDARY))
854 continue;
paul718e3742002-12-13 20:15:29 +0000855
hasso3fb9cd62004-10-19 19:44:43 +0000856 if (CONNECTED_POINTOPOINT_HOST(co))
paul718e3742002-12-13 20:15:29 +0000857 addr = co->destination;
858 else
859 addr = co->address;
860
paulcb3f37d2003-02-18 23:26:37 +0000861 if (p->family == co->address->family
paul68980082003-03-25 05:07:42 +0000862 && ! ospf_if_is_configured (ospf, &(addr->u.prefix4))
paulcb3f37d2003-02-18 23:26:37 +0000863 && ospf_network_match_iface(co,p))
paul570f7592003-01-25 06:47:41 +0000864 {
paul1eb8ef22005-04-07 07:30:20 +0000865 struct ospf_interface *oi;
paul718e3742002-12-13 20:15:29 +0000866
paul68980082003-03-25 05:07:42 +0000867 oi = ospf_if_new (ospf, ifp, co->address);
paul718e3742002-12-13 20:15:29 +0000868 oi->connected = co;
869
paul718e3742002-12-13 20:15:29 +0000870 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
paul718e3742002-12-13 20:15:29 +0000875 /* Add pseudo neighbor. */
876 ospf_nbr_add_self (oi);
877
paul718e3742002-12-13 20:15:29 +0000878 /* Relate ospf interface to ospf instance. */
paul68980082003-03-25 05:07:42 +0000879 oi->ospf = ospf;
paul718e3742002-12-13 20:15:29 +0000880
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
paul718e3742002-12-13 20:15:29 +0000886 ospf_area_add_if (oi->area, oi);
paulb29800a2005-11-20 14:50:45 +0000887
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 */
paul86752842006-01-10 20:34:46 +0000893 if ((ospf->router_id.s_addr != 0)
paulb29800a2005-11-20 14:50:45 +0000894 && if_is_operative (ifp))
paul718e3742002-12-13 20:15:29 +0000895 ospf_if_up (oi);
896
897 break;
898 }
899 }
900 }
901}
902
903void
904ospf_ls_upd_queue_empty (struct ospf_interface *oi)
905{
906 struct route_node *rn;
paul1eb8ef22005-04-07 07:30:20 +0000907 struct listnode *node, *nnode;
hasso52dc7ee2004-09-23 19:18:23 +0000908 struct list *lst;
paul718e3742002-12-13 20:15:29 +0000909 struct ospf_lsa *lsa;
910
911 /* empty ls update queue */
912 for (rn = route_top (oi->ls_upd_queue); rn;
913 rn = route_next (rn))
hasso52dc7ee2004-09-23 19:18:23 +0000914 if ((lst = (struct list *) rn->info))
paul718e3742002-12-13 20:15:29 +0000915 {
paul1eb8ef22005-04-07 07:30:20 +0000916 for (ALL_LIST_ELEMENTS (lst, node, nnode, lsa))
Paul Jakma1fe6ed32006-07-26 09:37:26 +0000917 ospf_lsa_unlock (&lsa); /* oi->ls_upd_queue */
paul718e3742002-12-13 20:15:29 +0000918 list_free (lst);
919 rn->info = NULL;
920 }
921
922 /* remove update event */
923 if (oi->t_ls_upd_event)
924 {
925 thread_cancel (oi->t_ls_upd_event);
926 oi->t_ls_upd_event = NULL;
927 }
928}
929
930void
paul68980082003-03-25 05:07:42 +0000931ospf_if_update (struct ospf *ospf)
paul718e3742002-12-13 20:15:29 +0000932{
933 struct route_node *rn;
paul1eb8ef22005-04-07 07:30:20 +0000934 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000935 struct ospf_network *network;
936 struct ospf_area *area;
paul1eb8ef22005-04-07 07:30:20 +0000937 struct ospf_interface *oi;
paul718e3742002-12-13 20:15:29 +0000938
paul68980082003-03-25 05:07:42 +0000939 if (ospf != NULL)
paul718e3742002-12-13 20:15:29 +0000940 {
paulb29800a2005-11-20 14:50:45 +0000941 /* Router-ID must be configured. */
paul86752842006-01-10 20:34:46 +0000942 if (ospf->router_id.s_addr == 0)
paulb29800a2005-11-20 14:50:45 +0000943 return;
944
paul718e3742002-12-13 20:15:29 +0000945 /* Find interfaces that not configured already. */
paul1eb8ef22005-04-07 07:30:20 +0000946 for (ALL_LIST_ELEMENTS (ospf->oiflist, node, nnode, oi))
paul718e3742002-12-13 20:15:29 +0000947 {
948 int found = 0;
paul718e3742002-12-13 20:15:29 +0000949 struct connected *co = oi->connected;
950
paul718e3742002-12-13 20:15:29 +0000951 if (oi->type == OSPF_IFTYPE_VIRTUALLINK)
952 continue;
953
paul68980082003-03-25 05:07:42 +0000954 for (rn = route_top (ospf->networks); rn; rn = route_next (rn))
paul718e3742002-12-13 20:15:29 +0000955 {
956 if (rn->info == NULL)
957 continue;
958
paul570f7592003-01-25 06:47:41 +0000959 if (ospf_network_match_iface(co,&rn->p))
paul718e3742002-12-13 20:15:29 +0000960 {
961 found = 1;
962 route_unlock_node (rn);
963 break;
964 }
965 }
966
967 if (found == 0)
968 ospf_if_free (oi);
969 }
970
971 /* Run each interface. */
paul68980082003-03-25 05:07:42 +0000972 for (rn = route_top (ospf->networks); rn; rn = route_next (rn))
paul718e3742002-12-13 20:15:29 +0000973 if (rn->info != NULL)
974 {
975 network = (struct ospf_network *) rn->info;
paul68980082003-03-25 05:07:42 +0000976 area = ospf_area_get (ospf, network->area_id, network->format);
977 ospf_network_run (ospf, &rn->p, area);
paul718e3742002-12-13 20:15:29 +0000978 }
979 }
980}
981
982void
paul68980082003-03-25 05:07:42 +0000983ospf_remove_vls_through_area (struct ospf *ospf, struct ospf_area *area)
paul718e3742002-12-13 20:15:29 +0000984{
paul1eb8ef22005-04-07 07:30:20 +0000985 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000986 struct ospf_vl_data *vl_data;
987
paul1eb8ef22005-04-07 07:30:20 +0000988 for (ALL_LIST_ELEMENTS (ospf->vlinks, node, nnode, vl_data))
989 if (IPV4_ADDR_SAME (&vl_data->vl_area_id, &area->area_id))
990 ospf_vl_delete (ospf, vl_data);
paul718e3742002-12-13 20:15:29 +0000991}
992
993
994struct message ospf_area_type_msg[] =
995{
996 { OSPF_AREA_DEFAULT, "Default" },
997 { OSPF_AREA_STUB, "Stub" },
998 { OSPF_AREA_NSSA, "NSSA" },
999};
1000int ospf_area_type_msg_max = OSPF_AREA_TYPE_MAX;
1001
paul4dadc292005-05-06 21:37:42 +00001002static void
paul718e3742002-12-13 20:15:29 +00001003ospf_area_type_set (struct ospf_area *area, int type)
1004{
hasso52dc7ee2004-09-23 19:18:23 +00001005 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00001006 struct ospf_interface *oi;
1007
1008 if (area->external_routing == type)
1009 {
1010 if (IS_DEBUG_OSPF_EVENT)
ajs9b0e25c2004-12-08 19:06:51 +00001011 zlog_debug ("Area[%s]: Types are the same, ignored.",
paul718e3742002-12-13 20:15:29 +00001012 inet_ntoa (area->area_id));
1013 return;
1014 }
1015
1016 area->external_routing = type;
1017
1018 if (IS_DEBUG_OSPF_EVENT)
ajs9b0e25c2004-12-08 19:06:51 +00001019 zlog_debug ("Area[%s]: Configured as %s", inet_ntoa (area->area_id),
paul718e3742002-12-13 20:15:29 +00001020 LOOKUP (ospf_area_type_msg, type));
1021
1022 switch (area->external_routing)
1023 {
1024 case OSPF_AREA_DEFAULT:
paul1eb8ef22005-04-07 07:30:20 +00001025 for (ALL_LIST_ELEMENTS_RO (area->oiflist, node, oi))
1026 if (oi->nbr_self != NULL)
1027 {
1028 UNSET_FLAG (oi->nbr_self->options, OSPF_OPTION_NP);
1029 SET_FLAG (oi->nbr_self->options, OSPF_OPTION_E);
1030 }
paul718e3742002-12-13 20:15:29 +00001031 break;
1032 case OSPF_AREA_STUB:
paul1eb8ef22005-04-07 07:30:20 +00001033 for (ALL_LIST_ELEMENTS_RO (area->oiflist, node, oi))
1034 if (oi->nbr_self != NULL)
1035 {
1036 if (IS_DEBUG_OSPF_EVENT)
1037 zlog_debug ("setting options on %s accordingly", IF_NAME (oi));
1038 UNSET_FLAG (oi->nbr_self->options, OSPF_OPTION_NP);
1039 UNSET_FLAG (oi->nbr_self->options, OSPF_OPTION_E);
1040 if (IS_DEBUG_OSPF_EVENT)
1041 zlog_debug ("options set on %s: %x",
1042 IF_NAME (oi), OPTIONS (oi));
1043 }
paul718e3742002-12-13 20:15:29 +00001044 break;
1045 case OSPF_AREA_NSSA:
paul1eb8ef22005-04-07 07:30:20 +00001046 for (ALL_LIST_ELEMENTS_RO (area->oiflist, node, oi))
1047 if (oi->nbr_self != NULL)
1048 {
1049 zlog_debug ("setting nssa options on %s accordingly", IF_NAME (oi));
1050 UNSET_FLAG (oi->nbr_self->options, OSPF_OPTION_E);
1051 SET_FLAG (oi->nbr_self->options, OSPF_OPTION_NP);
1052 zlog_debug ("options set on %s: %x", IF_NAME (oi), OPTIONS (oi));
1053 }
paul718e3742002-12-13 20:15:29 +00001054 break;
1055 default:
1056 break;
1057 }
1058
1059 ospf_router_lsa_timer_add (area);
paul68980082003-03-25 05:07:42 +00001060 ospf_schedule_abr_task (area->ospf);
paul718e3742002-12-13 20:15:29 +00001061}
1062
1063int
paul68980082003-03-25 05:07:42 +00001064ospf_area_shortcut_set (struct ospf *ospf, struct ospf_area *area, int mode)
paul718e3742002-12-13 20:15:29 +00001065{
1066 if (area->shortcut_configured == mode)
1067 return 0;
1068
1069 area->shortcut_configured = mode;
1070 ospf_router_lsa_timer_add (area);
paul68980082003-03-25 05:07:42 +00001071 ospf_schedule_abr_task (ospf);
paul718e3742002-12-13 20:15:29 +00001072
paul68980082003-03-25 05:07:42 +00001073 ospf_area_check_free (ospf, area->area_id);
paul718e3742002-12-13 20:15:29 +00001074
1075 return 1;
1076}
1077
1078int
paul68980082003-03-25 05:07:42 +00001079ospf_area_shortcut_unset (struct ospf *ospf, struct ospf_area *area)
paul718e3742002-12-13 20:15:29 +00001080{
1081 area->shortcut_configured = OSPF_SHORTCUT_DEFAULT;
1082 ospf_router_lsa_timer_add (area);
paul68980082003-03-25 05:07:42 +00001083 ospf_area_check_free (ospf, area->area_id);
1084 ospf_schedule_abr_task (ospf);
paul718e3742002-12-13 20:15:29 +00001085
1086 return 1;
1087}
1088
paul4dadc292005-05-06 21:37:42 +00001089static int
paul718e3742002-12-13 20:15:29 +00001090ospf_area_vlink_count (struct ospf *ospf, struct ospf_area *area)
1091{
1092 struct ospf_vl_data *vl;
hasso52dc7ee2004-09-23 19:18:23 +00001093 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00001094 int count = 0;
1095
paul1eb8ef22005-04-07 07:30:20 +00001096 for (ALL_LIST_ELEMENTS_RO (ospf->vlinks, node, vl))
1097 if (IPV4_ADDR_SAME (&vl->vl_area_id, &area->area_id))
1098 count++;
paul718e3742002-12-13 20:15:29 +00001099
1100 return count;
1101}
1102
1103int
1104ospf_area_stub_set (struct ospf *ospf, struct in_addr area_id)
1105{
1106 struct ospf_area *area;
paul147193a2003-04-19 00:31:59 +00001107 int format = OSPF_AREA_ID_FORMAT_ADDRESS;
paul718e3742002-12-13 20:15:29 +00001108
paul68980082003-03-25 05:07:42 +00001109 area = ospf_area_get (ospf, area_id, format);
paul718e3742002-12-13 20:15:29 +00001110 if (ospf_area_vlink_count (ospf, area))
1111 return 0;
1112
1113 if (area->external_routing != OSPF_AREA_STUB)
1114 ospf_area_type_set (area, OSPF_AREA_STUB);
1115
1116 return 1;
1117}
1118
1119int
1120ospf_area_stub_unset (struct ospf *ospf, struct in_addr area_id)
1121{
1122 struct ospf_area *area;
1123
paul68980082003-03-25 05:07:42 +00001124 area = ospf_area_lookup_by_area_id (ospf, area_id);
paul718e3742002-12-13 20:15:29 +00001125 if (area == NULL)
1126 return 1;
1127
1128 if (area->external_routing == OSPF_AREA_STUB)
1129 ospf_area_type_set (area, OSPF_AREA_DEFAULT);
1130
paul68980082003-03-25 05:07:42 +00001131 ospf_area_check_free (ospf, area_id);
paul718e3742002-12-13 20:15:29 +00001132
1133 return 1;
1134}
1135
1136int
1137ospf_area_no_summary_set (struct ospf *ospf, struct in_addr area_id)
1138{
1139 struct ospf_area *area;
paul147193a2003-04-19 00:31:59 +00001140 int format = OSPF_AREA_ID_FORMAT_ADDRESS;
paul718e3742002-12-13 20:15:29 +00001141
paul68980082003-03-25 05:07:42 +00001142 area = ospf_area_get (ospf, area_id, format);
paul718e3742002-12-13 20:15:29 +00001143 area->no_summary = 1;
1144
1145 return 1;
1146}
1147
1148int
1149ospf_area_no_summary_unset (struct ospf *ospf, struct in_addr area_id)
1150{
1151 struct ospf_area *area;
1152
paul68980082003-03-25 05:07:42 +00001153 area = ospf_area_lookup_by_area_id (ospf, area_id);
paul718e3742002-12-13 20:15:29 +00001154 if (area == NULL)
1155 return 0;
1156
1157 area->no_summary = 0;
paul68980082003-03-25 05:07:42 +00001158 ospf_area_check_free (ospf, area_id);
paul718e3742002-12-13 20:15:29 +00001159
1160 return 1;
1161}
1162
1163int
1164ospf_area_nssa_set (struct ospf *ospf, struct in_addr area_id)
1165{
1166 struct ospf_area *area;
paul147193a2003-04-19 00:31:59 +00001167 int format = OSPF_AREA_ID_FORMAT_ADDRESS;
paul718e3742002-12-13 20:15:29 +00001168
paul68980082003-03-25 05:07:42 +00001169 area = ospf_area_get (ospf, area_id, format);
paul718e3742002-12-13 20:15:29 +00001170 if (ospf_area_vlink_count (ospf, area))
1171 return 0;
1172
1173 if (area->external_routing != OSPF_AREA_NSSA)
1174 {
1175 ospf_area_type_set (area, OSPF_AREA_NSSA);
1176 ospf->anyNSSA++;
1177 }
1178
paul084c7842003-06-22 08:35:18 +00001179 /* set NSSA area defaults */
1180 area->no_summary = 0;
1181 area->NSSATranslatorRole = OSPF_NSSA_ROLE_CANDIDATE;
pauld4a53d52003-07-12 21:30:57 +00001182 area->NSSATranslatorState = OSPF_NSSA_TRANSLATE_DISABLED;
paul084c7842003-06-22 08:35:18 +00001183 area->NSSATranslatorStabilityInterval = OSPF_NSSA_TRANS_STABLE_DEFAULT;
1184
paul718e3742002-12-13 20:15:29 +00001185 return 1;
1186}
1187
1188int
1189ospf_area_nssa_unset (struct ospf *ospf, struct in_addr area_id)
1190{
1191 struct ospf_area *area;
1192
paul68980082003-03-25 05:07:42 +00001193 area = ospf_area_lookup_by_area_id (ospf, area_id);
paul718e3742002-12-13 20:15:29 +00001194 if (area == NULL)
1195 return 0;
1196
1197 if (area->external_routing == OSPF_AREA_NSSA)
1198 {
1199 ospf->anyNSSA--;
1200 ospf_area_type_set (area, OSPF_AREA_DEFAULT);
1201 }
1202
paul68980082003-03-25 05:07:42 +00001203 ospf_area_check_free (ospf, area_id);
paul718e3742002-12-13 20:15:29 +00001204
1205 return 1;
1206}
1207
1208int
1209ospf_area_nssa_translator_role_set (struct ospf *ospf, struct in_addr area_id,
1210 int role)
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 = role;
paul718e3742002-12-13 20:15:29 +00001219
1220 return 1;
1221}
1222
paul4dadc292005-05-06 21:37:42 +00001223/* XXX: unused? Leave for symmetry? */
1224static int
paul718e3742002-12-13 20:15:29 +00001225ospf_area_nssa_translator_role_unset (struct ospf *ospf,
1226 struct in_addr area_id)
1227{
1228 struct ospf_area *area;
1229
paul68980082003-03-25 05:07:42 +00001230 area = ospf_area_lookup_by_area_id (ospf, area_id);
paul718e3742002-12-13 20:15:29 +00001231 if (area == NULL)
1232 return 0;
1233
paul084c7842003-06-22 08:35:18 +00001234 area->NSSATranslatorRole = OSPF_NSSA_ROLE_CANDIDATE;
paul718e3742002-12-13 20:15:29 +00001235
paul68980082003-03-25 05:07:42 +00001236 ospf_area_check_free (ospf, area_id);
paul718e3742002-12-13 20:15:29 +00001237
1238 return 1;
1239}
1240
1241int
paul68980082003-03-25 05:07:42 +00001242ospf_area_export_list_set (struct ospf *ospf,
paul6c835672004-10-11 11:00:30 +00001243 struct ospf_area *area, const char *list_name)
paul718e3742002-12-13 20:15:29 +00001244{
1245 struct access_list *list;
1246 list = access_list_lookup (AFI_IP, list_name);
1247
1248 EXPORT_LIST (area) = list;
1249
1250 if (EXPORT_NAME (area))
1251 free (EXPORT_NAME (area));
1252
1253 EXPORT_NAME (area) = strdup (list_name);
paul68980082003-03-25 05:07:42 +00001254 ospf_schedule_abr_task (ospf);
paul718e3742002-12-13 20:15:29 +00001255
1256 return 1;
1257}
1258
1259int
paul68980082003-03-25 05:07:42 +00001260ospf_area_export_list_unset (struct ospf *ospf, struct ospf_area * area)
paul718e3742002-12-13 20:15:29 +00001261{
1262
1263 EXPORT_LIST (area) = 0;
1264
1265 if (EXPORT_NAME (area))
1266 free (EXPORT_NAME (area));
1267
1268 EXPORT_NAME (area) = NULL;
1269
paul68980082003-03-25 05:07:42 +00001270 ospf_area_check_free (ospf, area->area_id);
paul718e3742002-12-13 20:15:29 +00001271
paul68980082003-03-25 05:07:42 +00001272 ospf_schedule_abr_task (ospf);
paul718e3742002-12-13 20:15:29 +00001273
1274 return 1;
1275}
1276
1277int
paul6c835672004-10-11 11:00:30 +00001278ospf_area_import_list_set (struct ospf *ospf, struct ospf_area *area,
1279 const char *name)
paul718e3742002-12-13 20:15:29 +00001280{
1281 struct access_list *list;
1282 list = access_list_lookup (AFI_IP, name);
1283
1284 IMPORT_LIST (area) = list;
1285
1286 if (IMPORT_NAME (area))
1287 free (IMPORT_NAME (area));
1288
1289 IMPORT_NAME (area) = strdup (name);
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
paul68980082003-03-25 05:07:42 +00001296ospf_area_import_list_unset (struct ospf *ospf, struct ospf_area * area)
paul718e3742002-12-13 20:15:29 +00001297{
1298 IMPORT_LIST (area) = 0;
1299
1300 if (IMPORT_NAME (area))
1301 free (IMPORT_NAME (area));
1302
1303 IMPORT_NAME (area) = NULL;
paul68980082003-03-25 05:07:42 +00001304 ospf_area_check_free (ospf, area->area_id);
paul718e3742002-12-13 20:15:29 +00001305
paul68980082003-03-25 05:07:42 +00001306 ospf_schedule_abr_task (ospf);
paul718e3742002-12-13 20:15:29 +00001307
1308 return 1;
1309}
1310
1311int
paul718e3742002-12-13 20:15:29 +00001312ospf_timers_refresh_set (struct ospf *ospf, int interval)
1313{
1314 int time_left;
1315
1316 if (ospf->lsa_refresh_interval == interval)
1317 return 1;
1318
1319 time_left = ospf->lsa_refresh_interval -
Paul Jakma2518efd2006-08-27 06:49:29 +00001320 (quagga_time (NULL) - ospf->lsa_refresher_started);
paul718e3742002-12-13 20:15:29 +00001321
1322 if (time_left > interval)
1323 {
1324 OSPF_TIMER_OFF (ospf->t_lsa_refresher);
1325 ospf->t_lsa_refresher =
1326 thread_add_timer (master, ospf_lsa_refresh_walker, ospf, interval);
1327 }
1328 ospf->lsa_refresh_interval = interval;
1329
1330 return 1;
1331}
1332
1333int
1334ospf_timers_refresh_unset (struct ospf *ospf)
1335{
1336 int time_left;
1337
1338 time_left = ospf->lsa_refresh_interval -
Paul Jakma2518efd2006-08-27 06:49:29 +00001339 (quagga_time (NULL) - ospf->lsa_refresher_started);
paul718e3742002-12-13 20:15:29 +00001340
1341 if (time_left > OSPF_LSA_REFRESH_INTERVAL_DEFAULT)
1342 {
1343 OSPF_TIMER_OFF (ospf->t_lsa_refresher);
1344 ospf->t_lsa_refresher =
1345 thread_add_timer (master, ospf_lsa_refresh_walker, ospf,
1346 OSPF_LSA_REFRESH_INTERVAL_DEFAULT);
1347 }
1348
1349 ospf->lsa_refresh_interval = OSPF_LSA_REFRESH_INTERVAL_DEFAULT;
1350
1351 return 1;
1352}
1353
1354
paul4dadc292005-05-06 21:37:42 +00001355static struct ospf_nbr_nbma *
1356ospf_nbr_nbma_new (void)
paul718e3742002-12-13 20:15:29 +00001357{
1358 struct ospf_nbr_nbma *nbr_nbma;
1359
1360 nbr_nbma = XMALLOC (MTYPE_OSPF_NEIGHBOR_STATIC,
1361 sizeof (struct ospf_nbr_nbma));
1362 memset (nbr_nbma, 0, sizeof (struct ospf_nbr_nbma));
1363
1364 nbr_nbma->priority = OSPF_NEIGHBOR_PRIORITY_DEFAULT;
1365 nbr_nbma->v_poll = OSPF_POLL_INTERVAL_DEFAULT;
1366
1367 return nbr_nbma;
1368}
1369
paul4dadc292005-05-06 21:37:42 +00001370static void
paul718e3742002-12-13 20:15:29 +00001371ospf_nbr_nbma_free (struct ospf_nbr_nbma *nbr_nbma)
1372{
1373 XFREE (MTYPE_OSPF_NEIGHBOR_STATIC, nbr_nbma);
1374}
1375
paul4dadc292005-05-06 21:37:42 +00001376static void
paul718e3742002-12-13 20:15:29 +00001377ospf_nbr_nbma_delete (struct ospf *ospf, struct ospf_nbr_nbma *nbr_nbma)
1378{
1379 struct route_node *rn;
1380 struct prefix_ipv4 p;
1381
1382 p.family = AF_INET;
1383 p.prefix = nbr_nbma->addr;
1384 p.prefixlen = IPV4_MAX_BITLEN;
1385
1386 rn = route_node_lookup (ospf->nbr_nbma, (struct prefix *)&p);
1387 if (rn)
1388 {
1389 ospf_nbr_nbma_free (rn->info);
1390 rn->info = NULL;
1391 route_unlock_node (rn);
1392 route_unlock_node (rn);
1393 }
1394}
1395
paul4dadc292005-05-06 21:37:42 +00001396static void
paul718e3742002-12-13 20:15:29 +00001397ospf_nbr_nbma_down (struct ospf_nbr_nbma *nbr_nbma)
1398{
1399 OSPF_TIMER_OFF (nbr_nbma->t_poll);
1400
1401 if (nbr_nbma->nbr)
1402 {
1403 nbr_nbma->nbr->nbr_nbma = NULL;
1404 OSPF_NSM_EVENT_EXECUTE (nbr_nbma->nbr, NSM_KillNbr);
1405 }
1406
1407 if (nbr_nbma->oi)
1408 listnode_delete (nbr_nbma->oi->nbr_nbma, nbr_nbma);
1409}
1410
paul4dadc292005-05-06 21:37:42 +00001411static void
paul718e3742002-12-13 20:15:29 +00001412ospf_nbr_nbma_add (struct ospf_nbr_nbma *nbr_nbma,
1413 struct ospf_interface *oi)
1414{
1415 struct ospf_neighbor *nbr;
1416 struct route_node *rn;
1417 struct prefix p;
1418
1419 if (oi->type != OSPF_IFTYPE_NBMA)
1420 return;
1421
1422 if (nbr_nbma->nbr != NULL)
1423 return;
1424
1425 if (IPV4_ADDR_SAME (&oi->nbr_self->address.u.prefix4, &nbr_nbma->addr))
1426 return;
1427
1428 nbr_nbma->oi = oi;
1429 listnode_add (oi->nbr_nbma, nbr_nbma);
1430
1431 /* Get neighbor information from table. */
1432 p.family = AF_INET;
1433 p.prefixlen = IPV4_MAX_BITLEN;
1434 p.u.prefix4 = nbr_nbma->addr;
1435
1436 rn = route_node_get (oi->nbrs, (struct prefix *)&p);
1437 if (rn->info)
1438 {
1439 nbr = rn->info;
1440 nbr->nbr_nbma = nbr_nbma;
1441 nbr_nbma->nbr = nbr;
1442
1443 route_unlock_node (rn);
1444 }
1445 else
1446 {
1447 nbr = rn->info = ospf_nbr_new (oi);
1448 nbr->state = NSM_Down;
1449 nbr->src = nbr_nbma->addr;
1450 nbr->nbr_nbma = nbr_nbma;
1451 nbr->priority = nbr_nbma->priority;
1452 nbr->address = p;
1453
1454 nbr_nbma->nbr = nbr;
1455
1456 OSPF_NSM_EVENT_EXECUTE (nbr, NSM_Start);
1457 }
1458}
1459
1460void
paul68980082003-03-25 05:07:42 +00001461ospf_nbr_nbma_if_update (struct ospf *ospf, struct ospf_interface *oi)
paul718e3742002-12-13 20:15:29 +00001462{
1463 struct ospf_nbr_nbma *nbr_nbma;
1464 struct route_node *rn;
1465 struct prefix_ipv4 p;
1466
1467 if (oi->type != OSPF_IFTYPE_NBMA)
1468 return;
1469
paul68980082003-03-25 05:07:42 +00001470 for (rn = route_top (ospf->nbr_nbma); rn; rn = route_next (rn))
paul718e3742002-12-13 20:15:29 +00001471 if ((nbr_nbma = rn->info))
1472 if (nbr_nbma->oi == NULL && nbr_nbma->nbr == NULL)
1473 {
1474 p.family = AF_INET;
1475 p.prefix = nbr_nbma->addr;
1476 p.prefixlen = IPV4_MAX_BITLEN;
1477
1478 if (prefix_match (oi->address, (struct prefix *)&p))
1479 ospf_nbr_nbma_add (nbr_nbma, oi);
1480 }
1481}
1482
1483struct ospf_nbr_nbma *
1484ospf_nbr_nbma_lookup (struct ospf *ospf, struct in_addr nbr_addr)
1485{
1486 struct route_node *rn;
1487 struct prefix_ipv4 p;
1488
1489 p.family = AF_INET;
1490 p.prefix = nbr_addr;
1491 p.prefixlen = IPV4_MAX_BITLEN;
1492
1493 rn = route_node_lookup (ospf->nbr_nbma, (struct prefix *)&p);
1494 if (rn)
1495 {
1496 route_unlock_node (rn);
1497 return rn->info;
1498 }
1499 return NULL;
1500}
1501
1502struct ospf_nbr_nbma *
paul68980082003-03-25 05:07:42 +00001503ospf_nbr_nbma_lookup_next (struct ospf *ospf, struct in_addr *addr, int first)
paul718e3742002-12-13 20:15:29 +00001504{
1505#if 0
1506 struct ospf_nbr_nbma *nbr_nbma;
hasso52dc7ee2004-09-23 19:18:23 +00001507 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00001508#endif
1509
paul68980082003-03-25 05:07:42 +00001510 if (ospf == NULL)
paul718e3742002-12-13 20:15:29 +00001511 return NULL;
1512
1513#if 0
paul1eb8ef22005-04-07 07:30:20 +00001514 for (ALL_LIST_ELEMENTS_RO (ospf->nbr_nbma, node, nbr_nbma))
paul718e3742002-12-13 20:15:29 +00001515 {
paul718e3742002-12-13 20:15:29 +00001516 if (first)
1517 {
1518 *addr = nbr_nbma->addr;
1519 return nbr_nbma;
1520 }
1521 else if (ntohl (nbr_nbma->addr.s_addr) > ntohl (addr->s_addr))
1522 {
1523 *addr = nbr_nbma->addr;
1524 return nbr_nbma;
1525 }
1526 }
1527#endif
1528 return NULL;
1529}
1530
1531int
1532ospf_nbr_nbma_set (struct ospf *ospf, struct in_addr nbr_addr)
1533{
1534 struct ospf_nbr_nbma *nbr_nbma;
1535 struct ospf_interface *oi;
1536 struct prefix_ipv4 p;
1537 struct route_node *rn;
hasso52dc7ee2004-09-23 19:18:23 +00001538 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00001539
1540 nbr_nbma = ospf_nbr_nbma_lookup (ospf, nbr_addr);
1541 if (nbr_nbma)
1542 return 0;
1543
1544 nbr_nbma = ospf_nbr_nbma_new ();
1545 nbr_nbma->addr = nbr_addr;
1546
1547 p.family = AF_INET;
1548 p.prefix = nbr_addr;
1549 p.prefixlen = IPV4_MAX_BITLEN;
1550
1551 rn = route_node_get (ospf->nbr_nbma, (struct prefix *)&p);
1552 rn->info = nbr_nbma;
1553
paul1eb8ef22005-04-07 07:30:20 +00001554 for (ALL_LIST_ELEMENTS_RO (ospf->oiflist, node, oi))
paul718e3742002-12-13 20:15:29 +00001555 {
paul718e3742002-12-13 20:15:29 +00001556 if (oi->type == OSPF_IFTYPE_NBMA)
1557 if (prefix_match (oi->address, (struct prefix *)&p))
1558 {
1559 ospf_nbr_nbma_add (nbr_nbma, oi);
1560 break;
1561 }
1562 }
1563
1564 return 1;
1565}
1566
1567int
1568ospf_nbr_nbma_unset (struct ospf *ospf, struct in_addr nbr_addr)
1569{
1570 struct ospf_nbr_nbma *nbr_nbma;
1571
1572 nbr_nbma = ospf_nbr_nbma_lookup (ospf, nbr_addr);
1573 if (nbr_nbma == NULL)
1574 return 0;
1575
1576 ospf_nbr_nbma_down (nbr_nbma);
1577 ospf_nbr_nbma_delete (ospf, nbr_nbma);
1578
1579 return 1;
1580}
1581
1582int
1583ospf_nbr_nbma_priority_set (struct ospf *ospf, struct in_addr nbr_addr,
1584 u_char priority)
1585{
1586 struct ospf_nbr_nbma *nbr_nbma;
1587
1588 nbr_nbma = ospf_nbr_nbma_lookup (ospf, nbr_addr);
1589 if (nbr_nbma == NULL)
1590 return 0;
1591
1592 if (nbr_nbma->priority != priority)
1593 nbr_nbma->priority = priority;
1594
1595 return 1;
1596}
1597
1598int
1599ospf_nbr_nbma_priority_unset (struct ospf *ospf, struct in_addr nbr_addr)
1600{
1601 struct ospf_nbr_nbma *nbr_nbma;
1602
1603 nbr_nbma = ospf_nbr_nbma_lookup (ospf, nbr_addr);
1604 if (nbr_nbma == NULL)
1605 return 0;
1606
1607 if (nbr_nbma != OSPF_NEIGHBOR_PRIORITY_DEFAULT)
1608 nbr_nbma->priority = OSPF_NEIGHBOR_PRIORITY_DEFAULT;
1609
1610 return 1;
1611}
1612
1613int
1614ospf_nbr_nbma_poll_interval_set (struct ospf *ospf, struct in_addr nbr_addr,
paul6c835672004-10-11 11:00:30 +00001615 unsigned int interval)
paul718e3742002-12-13 20:15:29 +00001616{
1617 struct ospf_nbr_nbma *nbr_nbma;
1618
1619 nbr_nbma = ospf_nbr_nbma_lookup (ospf, nbr_addr);
1620 if (nbr_nbma == NULL)
1621 return 0;
1622
1623 if (nbr_nbma->v_poll != interval)
1624 {
1625 nbr_nbma->v_poll = interval;
1626 if (nbr_nbma->oi && ospf_if_is_up (nbr_nbma->oi))
1627 {
1628 OSPF_TIMER_OFF (nbr_nbma->t_poll);
1629 OSPF_POLL_TIMER_ON (nbr_nbma->t_poll, ospf_poll_timer,
1630 nbr_nbma->v_poll);
1631 }
1632 }
1633
1634 return 1;
1635}
1636
1637int
1638ospf_nbr_nbma_poll_interval_unset (struct ospf *ospf, struct in_addr addr)
1639{
1640 struct ospf_nbr_nbma *nbr_nbma;
1641
1642 nbr_nbma = ospf_nbr_nbma_lookup (ospf, addr);
1643 if (nbr_nbma == NULL)
1644 return 0;
1645
1646 if (nbr_nbma->v_poll != OSPF_POLL_INTERVAL_DEFAULT)
1647 nbr_nbma->v_poll = OSPF_POLL_INTERVAL_DEFAULT;
1648
1649 return 1;
1650}
1651
paul718e3742002-12-13 20:15:29 +00001652void
paul020709f2003-04-04 02:44:16 +00001653ospf_master_init ()
1654{
1655 memset (&ospf_master, 0, sizeof (struct ospf_master));
1656
1657 om = &ospf_master;
1658 om->ospf = list_new ();
1659 om->master = thread_master_create ();
Paul Jakma2518efd2006-08-27 06:49:29 +00001660 om->start_time = quagga_time (NULL);
paul020709f2003-04-04 02:44:16 +00001661}