blob: b86986b5686bcb9ca0b51ff955c30d9a4363e5b9 [file] [log] [blame]
paul718e3742002-12-13 20:15:29 +00001/* OSPF version 2 daemon program.
2 Copyright (C) 1999, 2000 Toshiaki Takada
3
4This file is part of GNU Zebra.
5
6GNU Zebra is free software; you can redistribute it and/or modify it
7under the terms of the GNU General Public License as published by the
8Free Software Foundation; either version 2, or (at your option) any
9later version.
10
11GNU Zebra is distributed in the hope that it will be useful, but
12WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with GNU Zebra; see the file COPYING. If not, write to the Free
18Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
1902111-1307, USA. */
20
21#include <zebra.h>
22
23#include "thread.h"
24#include "vty.h"
25#include "command.h"
26#include "linklist.h"
27#include "prefix.h"
28#include "table.h"
29#include "if.h"
30#include "memory.h"
31#include "stream.h"
32#include "log.h"
33#include "sockunion.h" /* for inet_aton () */
34#include "zclient.h"
35#include "plist.h"
Denis Ovsienkof102e752007-09-18 09:01:13 +000036#include "sockopt.h"
paul718e3742002-12-13 20:15:29 +000037
38#include "ospfd/ospfd.h"
39#include "ospfd/ospf_network.h"
40#include "ospfd/ospf_interface.h"
41#include "ospfd/ospf_ism.h"
42#include "ospfd/ospf_asbr.h"
43#include "ospfd/ospf_lsa.h"
44#include "ospfd/ospf_lsdb.h"
45#include "ospfd/ospf_neighbor.h"
46#include "ospfd/ospf_nsm.h"
47#include "ospfd/ospf_spf.h"
48#include "ospfd/ospf_packet.h"
49#include "ospfd/ospf_dump.h"
50#include "ospfd/ospf_zebra.h"
51#include "ospfd/ospf_abr.h"
52#include "ospfd/ospf_flood.h"
53#include "ospfd/ospf_route.h"
54#include "ospfd/ospf_ase.h"
55
paul020709f2003-04-04 02:44:16 +000056
pauledd7c242003-06-04 13:59:38 +000057
paul020709f2003-04-04 02:44:16 +000058/* OSPF process wide configuration. */
59static struct ospf_master ospf_master;
60
61/* OSPF process wide configuration pointer to export. */
62struct ospf_master *om;
paul718e3742002-12-13 20:15:29 +000063
64extern struct zclient *zclient;
hasso18a6dce2004-10-03 18:18:34 +000065extern struct in_addr router_id_zebra;
paul718e3742002-12-13 20:15:29 +000066
67
paul88d6cf32005-10-29 12:50:09 +000068static void ospf_remove_vls_through_area (struct ospf *, struct ospf_area *);
69static void ospf_network_free (struct ospf *, struct ospf_network *);
70static void ospf_area_free (struct ospf_area *);
Joakim Tjernlunda49eb302008-09-02 19:06:31 +010071static void ospf_network_run (struct prefix *, struct ospf_area *);
72static void ospf_network_run_interface (struct prefix *, struct ospf_area *,
73 struct interface *);
paul88d6cf32005-10-29 12:50:09 +000074static void ospf_finish_final (struct ospf *);
paul718e3742002-12-13 20:15:29 +000075
paul718e3742002-12-13 20:15:29 +000076#define OSPF_EXTERNAL_LSA_ORIGINATE_DELAY 1
paul88d6cf32005-10-29 12:50:09 +000077
paul718e3742002-12-13 20:15:29 +000078void
paul68980082003-03-25 05:07:42 +000079ospf_router_id_update (struct ospf *ospf)
paul718e3742002-12-13 20:15:29 +000080{
paul718e3742002-12-13 20:15:29 +000081 struct in_addr router_id, router_id_old;
paul1eb8ef22005-04-07 07:30:20 +000082 struct ospf_interface *oi;
Joakim Tjernlunda49eb302008-09-02 19:06:31 +010083 struct interface *ifp;
hasso52dc7ee2004-09-23 19:18:23 +000084 struct listnode *node;
paul718e3742002-12-13 20:15:29 +000085
86 if (IS_DEBUG_OSPF_EVENT)
ajs9b0e25c2004-12-08 19:06:51 +000087 zlog_debug ("Router-ID[OLD:%s]: Update", inet_ntoa (ospf->router_id));
paul718e3742002-12-13 20:15:29 +000088
paul68980082003-03-25 05:07:42 +000089 router_id_old = ospf->router_id;
paul718e3742002-12-13 20:15:29 +000090
Andrew J. Schorr16700082006-07-27 22:29:06 +000091 /* Select the router ID based on these priorities:
92 1. Statically assigned router ID is always the first choice.
93 2. If there is no statically assigned router ID, then try to stick
94 with the most recent value, since changing router ID's is very
95 disruptive.
96 3. Last choice: just go with whatever the zebra daemon recommends.
97 */
paul68980082003-03-25 05:07:42 +000098 if (ospf->router_id_static.s_addr != 0)
99 router_id = ospf->router_id_static;
Andrew J. Schorr16700082006-07-27 22:29:06 +0000100 else if (ospf->router_id.s_addr != 0)
101 router_id = ospf->router_id;
paul718e3742002-12-13 20:15:29 +0000102 else
hasso18a6dce2004-10-03 18:18:34 +0000103 router_id = router_id_zebra;
paul718e3742002-12-13 20:15:29 +0000104
paul68980082003-03-25 05:07:42 +0000105 ospf->router_id = router_id;
paul718e3742002-12-13 20:15:29 +0000106
107 if (IS_DEBUG_OSPF_EVENT)
ajs9b0e25c2004-12-08 19:06:51 +0000108 zlog_debug ("Router-ID[NEW:%s]: Update", inet_ntoa (ospf->router_id));
paul718e3742002-12-13 20:15:29 +0000109
110 if (!IPV4_ADDR_SAME (&router_id_old, &router_id))
111 {
paul1eb8ef22005-04-07 07:30:20 +0000112 for (ALL_LIST_ELEMENTS_RO (ospf->oiflist, node, oi))
113 /* Update self-neighbor's router_id. */
114 oi->nbr_self->router_id = router_id;
paul718e3742002-12-13 20:15:29 +0000115
116 /* If AS-external-LSA is queued, then flush those LSAs. */
paul68980082003-03-25 05:07:42 +0000117 if (router_id_old.s_addr == 0 && ospf->external_origin)
paul718e3742002-12-13 20:15:29 +0000118 {
119 int type;
120 /* Originate each redistributed external route. */
121 for (type = 0; type < ZEBRA_ROUTE_MAX; type++)
paul68980082003-03-25 05:07:42 +0000122 if (ospf->external_origin & (1 << type))
paul718e3742002-12-13 20:15:29 +0000123 thread_add_event (master, ospf_external_lsa_originate_timer,
paul68980082003-03-25 05:07:42 +0000124 ospf, type);
paul718e3742002-12-13 20:15:29 +0000125 /* Originate Deafult. */
paul68980082003-03-25 05:07:42 +0000126 if (ospf->external_origin & (1 << ZEBRA_ROUTE_MAX))
Paul Jakma4021b602006-05-12 22:55:41 +0000127 thread_add_event (master, ospf_default_originate_timer, ospf, 0);
paul718e3742002-12-13 20:15:29 +0000128
paul68980082003-03-25 05:07:42 +0000129 ospf->external_origin = 0;
paul718e3742002-12-13 20:15:29 +0000130 }
131
paul68980082003-03-25 05:07:42 +0000132 OSPF_TIMER_ON (ospf->t_router_lsa_update,
paul718e3742002-12-13 20:15:29 +0000133 ospf_router_lsa_update_timer, OSPF_LSA_UPDATE_DELAY);
paulb29800a2005-11-20 14:50:45 +0000134
135 /* update ospf_interface's */
Joakim Tjernlunda49eb302008-09-02 19:06:31 +0100136 for (ALL_LIST_ELEMENTS_RO (om->iflist, node, ifp))
137 ospf_if_update (ospf, ifp);
paul718e3742002-12-13 20:15:29 +0000138 }
139}
paul718e3742002-12-13 20:15:29 +0000140
141/* For OSPF area sort by area id. */
paul4dadc292005-05-06 21:37:42 +0000142static int
paul718e3742002-12-13 20:15:29 +0000143ospf_area_id_cmp (struct ospf_area *a1, struct ospf_area *a2)
144{
145 if (ntohl (a1->area_id.s_addr) > ntohl (a2->area_id.s_addr))
146 return 1;
147 if (ntohl (a1->area_id.s_addr) < ntohl (a2->area_id.s_addr))
148 return -1;
149 return 0;
150}
151
152/* Allocate new ospf structure. */
paul4dadc292005-05-06 21:37:42 +0000153static struct ospf *
154ospf_new (void)
paul718e3742002-12-13 20:15:29 +0000155{
156 int i;
157
158 struct ospf *new = XCALLOC (MTYPE_OSPF_TOP, sizeof (struct ospf));
159
160 new->router_id.s_addr = htonl (0);
161 new->router_id_static.s_addr = htonl (0);
162
pauld57834f2005-07-12 20:04:22 +0000163 new->abr_type = OSPF_ABR_DEFAULT;
paul718e3742002-12-13 20:15:29 +0000164 new->oiflist = list_new ();
165 new->vlinks = list_new ();
166 new->areas = list_new ();
167 new->areas->cmp = (int (*)(void *, void *)) ospf_area_id_cmp;
168 new->networks = route_table_init ();
169 new->nbr_nbma = route_table_init ();
170
171 new->lsdb = ospf_lsdb_new ();
172
173 new->default_originate = DEFAULT_ORIGINATE_NONE;
174
Paul Jakma7ffa8fa2006-10-22 20:07:53 +0000175 new->passive_interface_default = OSPF_IF_ACTIVE;
176
paul718e3742002-12-13 20:15:29 +0000177 new->new_external_route = route_table_init ();
178 new->old_external_route = route_table_init ();
179 new->external_lsas = route_table_init ();
paul88d6cf32005-10-29 12:50:09 +0000180
181 new->stub_router_startup_time = OSPF_STUB_ROUTER_UNCONFIGURED;
paul31a59762005-11-14 11:11:11 +0000182 new->stub_router_shutdown_time = OSPF_STUB_ROUTER_UNCONFIGURED;
paul88d6cf32005-10-29 12:50:09 +0000183
paul718e3742002-12-13 20:15:29 +0000184 /* Distribute parameter init. */
185 for (i = 0; i <= ZEBRA_ROUTE_MAX; i++)
186 {
187 new->dmetric[i].type = -1;
188 new->dmetric[i].value = -1;
189 }
190 new->default_metric = -1;
191 new->ref_bandwidth = OSPF_DEFAULT_REF_BANDWIDTH;
192
193 /* SPF timer value init. */
194 new->spf_delay = OSPF_SPF_DELAY_DEFAULT;
195 new->spf_holdtime = OSPF_SPF_HOLDTIME_DEFAULT;
pauld24f6e22005-10-21 09:23:12 +0000196 new->spf_max_holdtime = OSPF_SPF_MAX_HOLDTIME_DEFAULT;
197 new->spf_hold_multiplier = 1;
paul718e3742002-12-13 20:15:29 +0000198
199 /* MaxAge init. */
200 new->maxage_lsa = list_new ();
201 new->t_maxage_walker =
202 thread_add_timer (master, ospf_lsa_maxage_walker,
paul68980082003-03-25 05:07:42 +0000203 new, OSPF_LSA_MAXAGE_CHECK_INTERVAL);
paul718e3742002-12-13 20:15:29 +0000204
205 /* Distance table init. */
206 new->distance_table = route_table_init ();
207
208 new->lsa_refresh_queue.index = 0;
209 new->lsa_refresh_interval = OSPF_LSA_REFRESH_INTERVAL_DEFAULT;
210 new->t_lsa_refresher = thread_add_timer (master, ospf_lsa_refresh_walker,
211 new, new->lsa_refresh_interval);
Paul Jakma2518efd2006-08-27 06:49:29 +0000212 new->lsa_refresher_started = quagga_time (NULL);
paul718e3742002-12-13 20:15:29 +0000213
ajs5c333492005-02-23 15:43:01 +0000214 if ((new->fd = ospf_sock_init()) < 0)
215 {
216 zlog_err("ospf_new: fatal error: ospf_sock_init was unable to open "
217 "a socket");
218 exit(1);
219 }
Denis Ovsienkof102e752007-09-18 09:01:13 +0000220 new->maxsndbuflen = getsockopt_so_sendbuf (new->fd);
221 if (IS_DEBUG_OSPF (zebra, ZEBRA_INTERFACE))
222 zlog_debug ("%s: starting with OSPF send buffer size %d",
223 __func__, new->maxsndbuflen);
ajs5c333492005-02-23 15:43:01 +0000224 if ((new->ibuf = stream_new(OSPF_MAX_PACKET_SIZE+1)) == NULL)
225 {
226 zlog_err("ospf_new: fatal error: stream_new(%u) failed allocating ibuf",
227 OSPF_MAX_PACKET_SIZE+1);
228 exit(1);
229 }
230 new->t_read = thread_add_read (master, ospf_read, new, new->fd);
paul718e3742002-12-13 20:15:29 +0000231 new->oi_write_q = list_new ();
232
233 return new;
234}
235
236struct ospf *
paul020709f2003-04-04 02:44:16 +0000237ospf_lookup ()
238{
239 if (listcount (om->ospf) == 0)
240 return NULL;
241
paul1eb8ef22005-04-07 07:30:20 +0000242 return listgetdata (listhead (om->ospf));
paul020709f2003-04-04 02:44:16 +0000243}
244
paul4dadc292005-05-06 21:37:42 +0000245static void
paul020709f2003-04-04 02:44:16 +0000246ospf_add (struct ospf *ospf)
247{
248 listnode_add (om->ospf, ospf);
249}
250
paul4dadc292005-05-06 21:37:42 +0000251static void
paul020709f2003-04-04 02:44:16 +0000252ospf_delete (struct ospf *ospf)
253{
254 listnode_delete (om->ospf, ospf);
255}
256
257struct ospf *
paul718e3742002-12-13 20:15:29 +0000258ospf_get ()
259{
paul020709f2003-04-04 02:44:16 +0000260 struct ospf *ospf;
paul718e3742002-12-13 20:15:29 +0000261
paul020709f2003-04-04 02:44:16 +0000262 ospf = ospf_lookup ();
263 if (ospf == NULL)
264 {
265 ospf = ospf_new ();
266 ospf_add (ospf);
paul718e3742002-12-13 20:15:29 +0000267
paul020709f2003-04-04 02:44:16 +0000268 if (ospf->router_id_static.s_addr == 0)
269 ospf_router_id_update (ospf);
paul718e3742002-12-13 20:15:29 +0000270
271#ifdef HAVE_OPAQUE_LSA
paul020709f2003-04-04 02:44:16 +0000272 ospf_opaque_type11_lsa_init (ospf);
paul718e3742002-12-13 20:15:29 +0000273#endif /* HAVE_OPAQUE_LSA */
paul020709f2003-04-04 02:44:16 +0000274 }
paul68980082003-03-25 05:07:42 +0000275
276 return ospf;
paul718e3742002-12-13 20:15:29 +0000277}
paul88d6cf32005-10-29 12:50:09 +0000278
paulc9c93d52005-11-26 13:31:11 +0000279/* Handle the second half of deferred shutdown. This is called either
280 * from the deferred-shutdown timer thread, or directly through
281 * ospf_deferred_shutdown_check.
paul88d6cf32005-10-29 12:50:09 +0000282 *
283 * Function is to cleanup G-R state, if required then call ospf_finish_final
284 * to complete shutdown of this ospf instance. Possibly exit if the
285 * whole process is being shutdown and this was the last OSPF instance.
286 */
287static void
paulc9c93d52005-11-26 13:31:11 +0000288ospf_deferred_shutdown_finish (struct ospf *ospf)
paul88d6cf32005-10-29 12:50:09 +0000289{
290 ospf->stub_router_shutdown_time = OSPF_STUB_ROUTER_UNCONFIGURED;
paulc9c93d52005-11-26 13:31:11 +0000291 OSPF_TIMER_OFF (ospf->t_deferred_shutdown);
paul88d6cf32005-10-29 12:50:09 +0000292
293 ospf_finish_final (ospf);
294
295 /* *ospf is now invalid */
296
297 /* ospfd being shut-down? If so, was this the last ospf instance? */
298 if (CHECK_FLAG (om->options, OSPF_MASTER_SHUTDOWN)
299 && (listcount (om->ospf) == 0))
300 exit (0);
301
302 return;
303}
304
305/* Timer thread for G-R */
306static int
paulc9c93d52005-11-26 13:31:11 +0000307ospf_deferred_shutdown_timer (struct thread *t)
paul88d6cf32005-10-29 12:50:09 +0000308{
309 struct ospf *ospf = THREAD_ARG(t);
310
paulc9c93d52005-11-26 13:31:11 +0000311 ospf_deferred_shutdown_finish (ospf);
paul88d6cf32005-10-29 12:50:09 +0000312
313 return 0;
314}
315
paulc9c93d52005-11-26 13:31:11 +0000316/* Check whether deferred-shutdown must be scheduled, otherwise call
paul88d6cf32005-10-29 12:50:09 +0000317 * down directly into second-half of instance shutdown.
318 */
319static void
paulc9c93d52005-11-26 13:31:11 +0000320ospf_deferred_shutdown_check (struct ospf *ospf)
paul88d6cf32005-10-29 12:50:09 +0000321{
322 unsigned long timeout;
323 struct listnode *ln;
324 struct ospf_area *area;
325
paulc9c93d52005-11-26 13:31:11 +0000326 /* deferred shutdown already running? */
327 if (ospf->t_deferred_shutdown)
paul88d6cf32005-10-29 12:50:09 +0000328 return;
329
330 /* Should we try push out max-metric LSAs? */
331 if (ospf->stub_router_shutdown_time != OSPF_STUB_ROUTER_UNCONFIGURED)
332 {
333 for (ALL_LIST_ELEMENTS_RO (ospf->areas, ln, area))
334 {
335 SET_FLAG (area->stub_router_state, OSPF_AREA_ADMIN_STUB_ROUTED);
336
337 if (!CHECK_FLAG (area->stub_router_state, OSPF_AREA_IS_STUB_ROUTED))
338 ospf_router_lsa_timer_add (area);
339 }
340 timeout = ospf->stub_router_shutdown_time;
341 }
342 else
paulc9c93d52005-11-26 13:31:11 +0000343 {
344 /* No timer needed */
345 ospf_deferred_shutdown_finish (ospf);
346 return;
347 }
paul88d6cf32005-10-29 12:50:09 +0000348
paulc9c93d52005-11-26 13:31:11 +0000349 OSPF_TIMER_ON (ospf->t_deferred_shutdown, ospf_deferred_shutdown_timer,
paul88d6cf32005-10-29 12:50:09 +0000350 timeout);
351 return;
352}
353
354/* Shut down the entire process */
355void
356ospf_terminate (void)
357{
358 struct ospf *ospf;
359 struct listnode *node, *nnode;
360
361 /* shutdown already in progress */
362 if (CHECK_FLAG (om->options, OSPF_MASTER_SHUTDOWN))
363 return;
364
365 SET_FLAG (om->options, OSPF_MASTER_SHUTDOWN);
366
Andrew J. Schorr4056a542007-02-27 13:55:46 +0000367 /* exit immediately if OSPF not actually running */
368 if (listcount(om->ospf) == 0)
369 exit(0);
370
paul88d6cf32005-10-29 12:50:09 +0000371 for (ALL_LIST_ELEMENTS (om->ospf, node, nnode, ospf))
372 ospf_finish (ospf);
373
374 /* Deliberately go back up, hopefully to thread scheduler, as
375 * One or more ospf_finish()'s may have deferred shutdown to a timer
376 * thread
377 */
378}
paul718e3742002-12-13 20:15:29 +0000379
380void
381ospf_finish (struct ospf *ospf)
382{
paulc9c93d52005-11-26 13:31:11 +0000383 /* let deferred shutdown decide */
384 ospf_deferred_shutdown_check (ospf);
paul88d6cf32005-10-29 12:50:09 +0000385
paulc9c93d52005-11-26 13:31:11 +0000386 /* if ospf_deferred_shutdown returns, then ospf_finish_final is
paul88d6cf32005-10-29 12:50:09 +0000387 * deferred to expiry of G-S timer thread. Return back up, hopefully
388 * to thread scheduler.
389 */
paulc9c93d52005-11-26 13:31:11 +0000390 return;
paul88d6cf32005-10-29 12:50:09 +0000391}
392
393/* Final cleanup of ospf instance */
394static void
395ospf_finish_final (struct ospf *ospf)
396{
paul718e3742002-12-13 20:15:29 +0000397 struct route_node *rn;
398 struct ospf_nbr_nbma *nbr_nbma;
paul68980082003-03-25 05:07:42 +0000399 struct ospf_lsa *lsa;
paul1eb8ef22005-04-07 07:30:20 +0000400 struct ospf_interface *oi;
401 struct ospf_area *area;
402 struct ospf_vl_data *vl_data;
403 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000404 int i;
405
406#ifdef HAVE_OPAQUE_LSA
407 ospf_opaque_type11_lsa_term (ospf);
408#endif /* HAVE_OPAQUE_LSA */
paul88d6cf32005-10-29 12:50:09 +0000409
410 /* be nice if this worked, but it doesn't */
411 /*ospf_flush_self_originated_lsas_now (ospf);*/
412
413 /* Unregister redistribution */
paul718e3742002-12-13 20:15:29 +0000414 for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
paul020709f2003-04-04 02:44:16 +0000415 ospf_redistribute_unset (ospf, i);
Paul Jakma29b5a042006-08-27 08:01:20 +0000416 ospf_redistribute_default_unset (ospf);
paul718e3742002-12-13 20:15:29 +0000417
paul1eb8ef22005-04-07 07:30:20 +0000418 for (ALL_LIST_ELEMENTS (ospf->areas, node, nnode, area))
419 ospf_remove_vls_through_area (ospf, area);
paul718e3742002-12-13 20:15:29 +0000420
paul1eb8ef22005-04-07 07:30:20 +0000421 for (ALL_LIST_ELEMENTS (ospf->vlinks, node, nnode, vl_data))
422 ospf_vl_delete (ospf, vl_data);
paul718e3742002-12-13 20:15:29 +0000423
424 list_delete (ospf->vlinks);
425
426 /* Reset interface. */
paul1eb8ef22005-04-07 07:30:20 +0000427 for (ALL_LIST_ELEMENTS (ospf->oiflist, node, nnode, oi))
428 ospf_if_free (oi);
paul718e3742002-12-13 20:15:29 +0000429
430 /* Clear static neighbors */
431 for (rn = route_top (ospf->nbr_nbma); rn; rn = route_next (rn))
432 if ((nbr_nbma = rn->info))
433 {
434 OSPF_POLL_TIMER_OFF (nbr_nbma->t_poll);
435
436 if (nbr_nbma->nbr)
437 {
438 nbr_nbma->nbr->nbr_nbma = NULL;
439 nbr_nbma->nbr = NULL;
440 }
441
442 if (nbr_nbma->oi)
443 {
444 listnode_delete (nbr_nbma->oi->nbr_nbma, nbr_nbma);
445 nbr_nbma->oi = NULL;
446 }
447
448 XFREE (MTYPE_OSPF_NEIGHBOR_STATIC, nbr_nbma);
449 }
450
451 route_table_finish (ospf->nbr_nbma);
452
453 /* Clear networks and Areas. */
454 for (rn = route_top (ospf->networks); rn; rn = route_next (rn))
455 {
456 struct ospf_network *network;
457
458 if ((network = rn->info) != NULL)
459 {
paul68980082003-03-25 05:07:42 +0000460 ospf_network_free (ospf, network);
paul718e3742002-12-13 20:15:29 +0000461 rn->info = NULL;
462 route_unlock_node (rn);
463 }
464 }
465
paul1eb8ef22005-04-07 07:30:20 +0000466 for (ALL_LIST_ELEMENTS (ospf->areas, node, nnode, area))
paul718e3742002-12-13 20:15:29 +0000467 {
paul718e3742002-12-13 20:15:29 +0000468 listnode_delete (ospf->areas, area);
469 ospf_area_free (area);
470 }
471
472 /* Cancel all timers. */
473 OSPF_TIMER_OFF (ospf->t_external_lsa);
paul718e3742002-12-13 20:15:29 +0000474 OSPF_TIMER_OFF (ospf->t_router_lsa_update);
475 OSPF_TIMER_OFF (ospf->t_spf_calc);
476 OSPF_TIMER_OFF (ospf->t_ase_calc);
477 OSPF_TIMER_OFF (ospf->t_maxage);
478 OSPF_TIMER_OFF (ospf->t_maxage_walker);
479 OSPF_TIMER_OFF (ospf->t_abr_task);
paul88d6cf32005-10-29 12:50:09 +0000480 OSPF_TIMER_OFF (ospf->t_asbr_check);
paul718e3742002-12-13 20:15:29 +0000481 OSPF_TIMER_OFF (ospf->t_distribute_update);
482 OSPF_TIMER_OFF (ospf->t_lsa_refresher);
483 OSPF_TIMER_OFF (ospf->t_read);
484 OSPF_TIMER_OFF (ospf->t_write);
paul31a59762005-11-14 11:11:11 +0000485#ifdef HAVE_OPAQUE_LSA
paul88d6cf32005-10-29 12:50:09 +0000486 OSPF_TIMER_OFF (ospf->t_opaque_lsa_self);
paul31a59762005-11-14 11:11:11 +0000487#endif
paul718e3742002-12-13 20:15:29 +0000488
489 close (ospf->fd);
ajs5c333492005-02-23 15:43:01 +0000490 stream_free(ospf->ibuf);
paul718e3742002-12-13 20:15:29 +0000491
492#ifdef HAVE_OPAQUE_LSA
paul68980082003-03-25 05:07:42 +0000493 LSDB_LOOP (OPAQUE_AS_LSDB (ospf), rn, lsa)
494 ospf_discard_from_db (ospf, ospf->lsdb, lsa);
paul718e3742002-12-13 20:15:29 +0000495#endif /* HAVE_OPAQUE_LSA */
paul68980082003-03-25 05:07:42 +0000496 LSDB_LOOP (EXTERNAL_LSDB (ospf), rn, lsa)
497 ospf_discard_from_db (ospf, ospf->lsdb, lsa);
498
paul718e3742002-12-13 20:15:29 +0000499 ospf_lsdb_delete_all (ospf->lsdb);
500 ospf_lsdb_free (ospf->lsdb);
501
paul1eb8ef22005-04-07 07:30:20 +0000502 for (ALL_LIST_ELEMENTS (ospf->maxage_lsa, node, nnode, lsa))
Paul Jakma1fe6ed32006-07-26 09:37:26 +0000503 ospf_lsa_unlock (&lsa); /* maxage_lsa */
paul718e3742002-12-13 20:15:29 +0000504
505 list_delete (ospf->maxage_lsa);
506
507 if (ospf->old_table)
508 ospf_route_table_free (ospf->old_table);
509 if (ospf->new_table)
510 {
511 ospf_route_delete (ospf->new_table);
512 ospf_route_table_free (ospf->new_table);
513 }
514 if (ospf->old_rtrs)
515 ospf_rtrs_free (ospf->old_rtrs);
516 if (ospf->new_rtrs)
517 ospf_rtrs_free (ospf->new_rtrs);
518 if (ospf->new_external_route)
519 {
520 ospf_route_delete (ospf->new_external_route);
521 ospf_route_table_free (ospf->new_external_route);
522 }
523 if (ospf->old_external_route)
524 {
525 ospf_route_delete (ospf->old_external_route);
526 ospf_route_table_free (ospf->old_external_route);
527 }
528 if (ospf->external_lsas)
529 {
530 ospf_ase_external_lsas_finish (ospf->external_lsas);
531 }
532
533 list_delete (ospf->areas);
534
535 for (i = ZEBRA_ROUTE_SYSTEM; i <= ZEBRA_ROUTE_MAX; i++)
536 if (EXTERNAL_INFO (i) != NULL)
537 for (rn = route_top (EXTERNAL_INFO (i)); rn; rn = route_next (rn))
538 {
539 if (rn->info == NULL)
540 continue;
541
542 XFREE (MTYPE_OSPF_EXTERNAL_INFO, rn->info);
543 rn->info = NULL;
544 route_unlock_node (rn);
545 }
546
paul68980082003-03-25 05:07:42 +0000547 ospf_distance_reset (ospf);
paul718e3742002-12-13 20:15:29 +0000548 route_table_finish (ospf->distance_table);
549
paul020709f2003-04-04 02:44:16 +0000550 ospf_delete (ospf);
paul718e3742002-12-13 20:15:29 +0000551
paul020709f2003-04-04 02:44:16 +0000552 XFREE (MTYPE_OSPF_TOP, ospf);
paul718e3742002-12-13 20:15:29 +0000553}
554
555
556/* allocate new OSPF Area object */
paul4dadc292005-05-06 21:37:42 +0000557static struct ospf_area *
paul68980082003-03-25 05:07:42 +0000558ospf_area_new (struct ospf *ospf, struct in_addr area_id)
paul718e3742002-12-13 20:15:29 +0000559{
560 struct ospf_area *new;
561
562 /* Allocate new config_network. */
563 new = XCALLOC (MTYPE_OSPF_AREA, sizeof (struct ospf_area));
564
paul68980082003-03-25 05:07:42 +0000565 new->ospf = ospf;
paul718e3742002-12-13 20:15:29 +0000566
567 new->area_id = area_id;
568
569 new->external_routing = OSPF_AREA_DEFAULT;
570 new->default_cost = 1;
571 new->auth_type = OSPF_AUTH_NULL;
paul88d6cf32005-10-29 12:50:09 +0000572
paul718e3742002-12-13 20:15:29 +0000573 /* New LSDB init. */
574 new->lsdb = ospf_lsdb_new ();
575
576 /* Self-originated LSAs initialize. */
577 new->router_lsa_self = NULL;
578
579#ifdef HAVE_OPAQUE_LSA
580 ospf_opaque_type10_lsa_init (new);
581#endif /* HAVE_OPAQUE_LSA */
582
583 new->oiflist = list_new ();
584 new->ranges = route_table_init ();
585
586 if (area_id.s_addr == OSPF_AREA_BACKBONE)
paul68980082003-03-25 05:07:42 +0000587 ospf->backbone = new;
paul718e3742002-12-13 20:15:29 +0000588
589 return new;
590}
591
592void
593ospf_area_free (struct ospf_area *area)
594{
paul68980082003-03-25 05:07:42 +0000595 struct route_node *rn;
596 struct ospf_lsa *lsa;
597
paul718e3742002-12-13 20:15:29 +0000598 /* Free LSDBs. */
paul68980082003-03-25 05:07:42 +0000599 LSDB_LOOP (ROUTER_LSDB (area), rn, lsa)
600 ospf_discard_from_db (area->ospf, area->lsdb, lsa);
601 LSDB_LOOP (NETWORK_LSDB (area), rn, lsa)
602 ospf_discard_from_db (area->ospf, area->lsdb, lsa);
603 LSDB_LOOP (SUMMARY_LSDB (area), rn, lsa)
604 ospf_discard_from_db (area->ospf, area->lsdb, lsa);
605 LSDB_LOOP (ASBR_SUMMARY_LSDB (area), rn, lsa)
606 ospf_discard_from_db (area->ospf, area->lsdb, lsa);
paul718e3742002-12-13 20:15:29 +0000607
paul68980082003-03-25 05:07:42 +0000608 LSDB_LOOP (NSSA_LSDB (area), rn, lsa)
609 ospf_discard_from_db (area->ospf, area->lsdb, lsa);
paul718e3742002-12-13 20:15:29 +0000610#ifdef HAVE_OPAQUE_LSA
paul68980082003-03-25 05:07:42 +0000611 LSDB_LOOP (OPAQUE_AREA_LSDB (area), rn, lsa)
612 ospf_discard_from_db (area->ospf, area->lsdb, lsa);
613 LSDB_LOOP (OPAQUE_LINK_LSDB (area), rn, lsa)
614 ospf_discard_from_db (area->ospf, area->lsdb, lsa);
paul718e3742002-12-13 20:15:29 +0000615#endif /* HAVE_OPAQUE_LSA */
616
617 ospf_lsdb_delete_all (area->lsdb);
618 ospf_lsdb_free (area->lsdb);
619
Paul Jakma1fe6ed32006-07-26 09:37:26 +0000620 ospf_lsa_unlock (&area->router_lsa_self);
paul718e3742002-12-13 20:15:29 +0000621
622 route_table_finish (area->ranges);
623 list_delete (area->oiflist);
624
625 if (EXPORT_NAME (area))
626 free (EXPORT_NAME (area));
627
628 if (IMPORT_NAME (area))
629 free (IMPORT_NAME (area));
630
631 /* Cancel timer. */
632 OSPF_TIMER_OFF (area->t_router_lsa_self);
paul88d6cf32005-10-29 12:50:09 +0000633 OSPF_TIMER_OFF (area->t_stub_router);
634#ifdef HAVE_OPAQUE_LSA
635 OSPF_TIMER_OFF (area->t_opaque_lsa_self);
636#endif /* HAVE_OPAQUE_LSA */
637
paul718e3742002-12-13 20:15:29 +0000638 if (OSPF_IS_AREA_BACKBONE (area))
paul68980082003-03-25 05:07:42 +0000639 area->ospf->backbone = NULL;
paul718e3742002-12-13 20:15:29 +0000640
641 XFREE (MTYPE_OSPF_AREA, area);
642}
643
644void
paul68980082003-03-25 05:07:42 +0000645ospf_area_check_free (struct ospf *ospf, struct in_addr area_id)
paul718e3742002-12-13 20:15:29 +0000646{
647 struct ospf_area *area;
648
paul68980082003-03-25 05:07:42 +0000649 area = ospf_area_lookup_by_area_id (ospf, area_id);
paul718e3742002-12-13 20:15:29 +0000650 if (area &&
651 listcount (area->oiflist) == 0 &&
652 area->ranges->top == NULL &&
653 area->shortcut_configured == OSPF_SHORTCUT_DEFAULT &&
654 area->external_routing == OSPF_AREA_DEFAULT &&
655 area->no_summary == 0 &&
656 area->default_cost == 1 &&
657 EXPORT_NAME (area) == NULL &&
658 IMPORT_NAME (area) == NULL &&
659 area->auth_type == OSPF_AUTH_NULL)
660 {
paul68980082003-03-25 05:07:42 +0000661 listnode_delete (ospf->areas, area);
paul718e3742002-12-13 20:15:29 +0000662 ospf_area_free (area);
663 }
664}
665
666struct ospf_area *
paul68980082003-03-25 05:07:42 +0000667ospf_area_get (struct ospf *ospf, struct in_addr area_id, int format)
paul718e3742002-12-13 20:15:29 +0000668{
669 struct ospf_area *area;
670
paul68980082003-03-25 05:07:42 +0000671 area = ospf_area_lookup_by_area_id (ospf, area_id);
paul718e3742002-12-13 20:15:29 +0000672 if (!area)
673 {
paul68980082003-03-25 05:07:42 +0000674 area = ospf_area_new (ospf, area_id);
paul718e3742002-12-13 20:15:29 +0000675 area->format = format;
paul68980082003-03-25 05:07:42 +0000676 listnode_add_sort (ospf->areas, area);
677 ospf_check_abr_status (ospf);
paul718e3742002-12-13 20:15:29 +0000678 }
679
680 return area;
681}
682
683struct ospf_area *
paul68980082003-03-25 05:07:42 +0000684ospf_area_lookup_by_area_id (struct ospf *ospf, struct in_addr area_id)
paul718e3742002-12-13 20:15:29 +0000685{
686 struct ospf_area *area;
hasso52dc7ee2004-09-23 19:18:23 +0000687 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000688
paul1eb8ef22005-04-07 07:30:20 +0000689 for (ALL_LIST_ELEMENTS_RO (ospf->areas, node, area))
690 if (IPV4_ADDR_SAME (&area->area_id, &area_id))
691 return area;
paul718e3742002-12-13 20:15:29 +0000692
693 return NULL;
694}
695
696void
697ospf_area_add_if (struct ospf_area *area, struct ospf_interface *oi)
698{
699 listnode_add (area->oiflist, oi);
700}
701
702void
703ospf_area_del_if (struct ospf_area *area, struct ospf_interface *oi)
704{
705 listnode_delete (area->oiflist, oi);
706}
707
708
709/* Config network statement related functions. */
paul4dadc292005-05-06 21:37:42 +0000710static struct ospf_network *
paul718e3742002-12-13 20:15:29 +0000711ospf_network_new (struct in_addr area_id, int format)
712{
713 struct ospf_network *new;
714 new = XCALLOC (MTYPE_OSPF_NETWORK, sizeof (struct ospf_network));
715
716 new->area_id = area_id;
717 new->format = format;
718
719 return new;
720}
721
722void
paul68980082003-03-25 05:07:42 +0000723ospf_network_free (struct ospf *ospf, struct ospf_network *network)
paul718e3742002-12-13 20:15:29 +0000724{
paul68980082003-03-25 05:07:42 +0000725 ospf_area_check_free (ospf, network->area_id);
726 ospf_schedule_abr_task (ospf);
paul718e3742002-12-13 20:15:29 +0000727 XFREE (MTYPE_OSPF_NETWORK, network);
728}
729
730int
731ospf_network_set (struct ospf *ospf, struct prefix_ipv4 *p,
732 struct in_addr area_id)
733{
734 struct ospf_network *network;
735 struct ospf_area *area;
736 struct route_node *rn;
737 struct external_info *ei;
paul147193a2003-04-19 00:31:59 +0000738 int ret = OSPF_AREA_ID_FORMAT_ADDRESS;
paul718e3742002-12-13 20:15:29 +0000739
740 rn = route_node_get (ospf->networks, (struct prefix *)p);
741 if (rn->info)
742 {
743 /* There is already same network statement. */
744 route_unlock_node (rn);
745 return 0;
746 }
747
748 rn->info = network = ospf_network_new (area_id, ret);
paul68980082003-03-25 05:07:42 +0000749 area = ospf_area_get (ospf, area_id, ret);
paul718e3742002-12-13 20:15:29 +0000750
751 /* Run network config now. */
Joakim Tjernlunda49eb302008-09-02 19:06:31 +0100752 ospf_network_run ((struct prefix *)p, area);
paul718e3742002-12-13 20:15:29 +0000753
754 /* Update connected redistribute. */
755 if (ospf_is_type_redistributed (ZEBRA_ROUTE_CONNECT))
756 if (EXTERNAL_INFO (ZEBRA_ROUTE_CONNECT))
757 for (rn = route_top (EXTERNAL_INFO (ZEBRA_ROUTE_CONNECT));
758 rn; rn = route_next (rn))
759 if ((ei = rn->info) != NULL)
paul68980082003-03-25 05:07:42 +0000760 if (ospf_external_info_find_lsa (ospf, &ei->p))
761 if (!ospf_distribute_check_connected (ospf, ei))
762 ospf_external_lsa_flush (ospf, ei->type, &ei->p,
ajs5339cfd2005-09-19 13:28:05 +0000763 ei->ifindex /*, ei->nexthop */);
paul718e3742002-12-13 20:15:29 +0000764
paul68980082003-03-25 05:07:42 +0000765 ospf_area_check_free (ospf, area_id);
paul718e3742002-12-13 20:15:29 +0000766
767 return 1;
768}
769
770int
771ospf_network_unset (struct ospf *ospf, struct prefix_ipv4 *p,
772 struct in_addr area_id)
773{
774 struct route_node *rn;
775 struct ospf_network *network;
776 struct external_info *ei;
Joakim Tjernlunda49eb302008-09-02 19:06:31 +0100777 struct listnode *node, *nnode;
778 struct ospf_interface *oi;
paul718e3742002-12-13 20:15:29 +0000779
780 rn = route_node_lookup (ospf->networks, (struct prefix *)p);
781 if (rn == NULL)
782 return 0;
783
784 network = rn->info;
Stephen Hemminger965f54f2009-06-03 16:44:21 -0700785 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +0000786 if (!IPV4_ADDR_SAME (&area_id, &network->area_id))
787 return 0;
788
paul68980082003-03-25 05:07:42 +0000789 ospf_network_free (ospf, rn->info);
paul718e3742002-12-13 20:15:29 +0000790 rn->info = NULL;
Stephen Hemminger965f54f2009-06-03 16:44:21 -0700791 route_unlock_node (rn); /* initial reference */
paul718e3742002-12-13 20:15:29 +0000792
Joakim Tjernlunda49eb302008-09-02 19:06:31 +0100793 /* Find interfaces that not configured already. */
794 for (ALL_LIST_ELEMENTS (ospf->oiflist, node, nnode, oi))
795 {
796 int found = 0;
797 struct connected *co = oi->connected;
798
799 if (oi->type == OSPF_IFTYPE_VIRTUALLINK)
800 continue;
801
802 for (rn = route_top (ospf->networks); rn; rn = route_next (rn))
803 {
804 if (rn->info == NULL)
805 continue;
806
807 if (ospf_network_match_iface(co,&rn->p))
808 {
809 found = 1;
810 route_unlock_node (rn);
811 break;
812 }
813 }
814
815 if (found == 0)
816 ospf_if_free (oi);
817 }
paul718e3742002-12-13 20:15:29 +0000818
819 /* Update connected redistribute. */
820 if (ospf_is_type_redistributed (ZEBRA_ROUTE_CONNECT))
821 if (EXTERNAL_INFO (ZEBRA_ROUTE_CONNECT))
822 for (rn = route_top (EXTERNAL_INFO (ZEBRA_ROUTE_CONNECT));
823 rn; rn = route_next (rn))
824 if ((ei = rn->info) != NULL)
paul68980082003-03-25 05:07:42 +0000825 if (!ospf_external_info_find_lsa (ospf, &ei->p))
826 if (ospf_distribute_check_connected (ospf, ei))
827 ospf_external_lsa_originate (ospf, ei);
paul718e3742002-12-13 20:15:29 +0000828
829 return 1;
830}
831
paul570f7592003-01-25 06:47:41 +0000832/* Check whether interface matches given network
833 * returns: 1, true. 0, false
834 */
835int
836ospf_network_match_iface(struct connected *co, struct prefix *net)
837{
Andrew J. Schorrf0ec8322007-04-30 16:52:05 +0000838/* #define COMPATIBILITY_MODE */
Andrew J. Schorre4529632006-12-12 19:18:21 +0000839 /* The old code used to have a special case for PtP interfaces:
840
841 if (if_is_pointopoint (co->ifp) && co->destination &&
842 IPV4_ADDR_SAME ( &(co->destination->u.prefix4), &(net->u.prefix4)))
843 return 1;
844
845 The new approach is much more general. If a peer address is supplied,
846 then we are routing to that prefix, so that's the address to compare
847 against (not the local address, which may not be unique).
848 */
849#ifndef COMPATIBILITY_MODE
850 /* new approach: more elegant and conceptually clean */
851 return prefix_match(net, CONNECTED_PREFIX(co));
852#else /* COMPATIBILITY_MODE */
853 /* match old (strange?) behavior */
854
paul570f7592003-01-25 06:47:41 +0000855 /* Behaviour to match both Cisco where:
856 * iface address lies within network specified -> ospf
857 * and zebra 0.9[2ish-3]:
858 * PtP special case: network specified == iface peer addr -> ospf
859 */
gdt8f40e892003-12-05 14:01:43 +0000860
paulf3ae74c2004-11-04 20:35:31 +0000861 /* For PtP, match if peer address matches network address exactly.
862 * This can be addr/32 or addr/p for p < 32, but the addr must match
863 * exactly; this is not a test for falling within the prefix. This
gdt8f40e892003-12-05 14:01:43 +0000864 * test is solely for compatibility with zebra.
gdt8f40e892003-12-05 14:01:43 +0000865 */
Andrew J. Schorre4529632006-12-12 19:18:21 +0000866 if (CONNECTED_PEER(co) &&
paulf3ae74c2004-11-04 20:35:31 +0000867 IPV4_ADDR_SAME ( &(co->destination->u.prefix4), &(net->u.prefix4)))
868 return 1;
869
870#if 0
871 /* Decline to accept PtP if dst address does not match the
872 * prefix. (ifdefed out because this is a workaround, not the
873 * desired behavior.) */
874 if (if_is_pointopoint (co->ifp) &&
875 ! prefix_match (net, co->destination))
876 return 0;
877#endif
878
879 /* If the address is within the prefix, accept. Note that this
880 * applies to PtP as well as other types.
881 */
882 if (prefix_match (net, co->address))
883 return 1;
884
885 return 0; /* no match */
Andrew J. Schorre4529632006-12-12 19:18:21 +0000886
887#endif /* COMPATIBILITY_MODE */
paul570f7592003-01-25 06:47:41 +0000888}
889
paul718e3742002-12-13 20:15:29 +0000890void
Joakim Tjernlunda49eb302008-09-02 19:06:31 +0100891ospf_network_run_interface (struct prefix *p, struct ospf_area *area,
892 struct interface *ifp)
893{
894 struct listnode *cnode;
895 struct connected *co;
896
897 if (memcmp (ifp->name, "VLINK", 5) == 0)
898 return;
899
900 /* if interface prefix is match specified prefix,
901 then create socket and join multicast group. */
902 for (ALL_LIST_ELEMENTS_RO (ifp->connected, cnode, co))
903 {
Joakim Tjernlundf0f63842009-07-27 12:42:29 +0200904
Joakim Tjernlunda49eb302008-09-02 19:06:31 +0100905 if (CHECK_FLAG(co->flags,ZEBRA_IFA_SECONDARY))
906 continue;
907
Joakim Tjernlunda49eb302008-09-02 19:06:31 +0100908 if (p->family == co->address->family
Joakim Tjernlundf0f63842009-07-27 12:42:29 +0200909 && ! ospf_if_table_lookup(ifp, co->address)
Joakim Tjernlunda49eb302008-09-02 19:06:31 +0100910 && ospf_network_match_iface(co,p))
911 {
912 struct ospf_interface *oi;
913
914 oi = ospf_if_new (area->ospf, ifp, co->address);
915 oi->connected = co;
916
917 oi->area = area;
918
919 oi->params = ospf_lookup_if_params (ifp, oi->address->u.prefix4);
920 oi->output_cost = ospf_if_get_output_cost (oi);
921
922 /* Add pseudo neighbor. */
923 ospf_nbr_add_self (oi);
924
925 /* Relate ospf interface to ospf instance. */
926 oi->ospf = area->ospf;
927
928 /* update network type as interface flag */
929 /* If network type is specified previously,
930 skip network type setting. */
931 oi->type = IF_DEF_PARAMS (ifp)->type;
932
933 ospf_area_add_if (oi->area, oi);
934
935 /* if router_id is not configured, dont bring up
936 * interfaces.
937 * ospf_router_id_update() will call ospf_if_update
938 * whenever r-id is configured instead.
939 */
940 if ((area->ospf->router_id.s_addr != 0)
941 && if_is_operative (ifp))
942 ospf_if_up (oi);
943 }
944 }
945}
946
947void
948ospf_network_run (struct prefix *p, struct ospf_area *area)
paul718e3742002-12-13 20:15:29 +0000949{
950 struct interface *ifp;
hasso52dc7ee2004-09-23 19:18:23 +0000951 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000952
953 /* Schedule Router ID Update. */
Joakim Tjernlunda49eb302008-09-02 19:06:31 +0100954 if (area->ospf->router_id.s_addr == 0)
955 ospf_router_id_update (area->ospf);
paulb29800a2005-11-20 14:50:45 +0000956
paul718e3742002-12-13 20:15:29 +0000957 /* Get target interface. */
paul1eb8ef22005-04-07 07:30:20 +0000958 for (ALL_LIST_ELEMENTS_RO (om->iflist, node, ifp))
Joakim Tjernlunda49eb302008-09-02 19:06:31 +0100959 ospf_network_run_interface (p, area, ifp);
paul718e3742002-12-13 20:15:29 +0000960}
961
962void
963ospf_ls_upd_queue_empty (struct ospf_interface *oi)
964{
965 struct route_node *rn;
paul1eb8ef22005-04-07 07:30:20 +0000966 struct listnode *node, *nnode;
hasso52dc7ee2004-09-23 19:18:23 +0000967 struct list *lst;
paul718e3742002-12-13 20:15:29 +0000968 struct ospf_lsa *lsa;
969
970 /* empty ls update queue */
971 for (rn = route_top (oi->ls_upd_queue); rn;
972 rn = route_next (rn))
hasso52dc7ee2004-09-23 19:18:23 +0000973 if ((lst = (struct list *) rn->info))
paul718e3742002-12-13 20:15:29 +0000974 {
paul1eb8ef22005-04-07 07:30:20 +0000975 for (ALL_LIST_ELEMENTS (lst, node, nnode, lsa))
Paul Jakma1fe6ed32006-07-26 09:37:26 +0000976 ospf_lsa_unlock (&lsa); /* oi->ls_upd_queue */
paul718e3742002-12-13 20:15:29 +0000977 list_free (lst);
978 rn->info = NULL;
979 }
980
981 /* remove update event */
982 if (oi->t_ls_upd_event)
983 {
984 thread_cancel (oi->t_ls_upd_event);
985 oi->t_ls_upd_event = NULL;
986 }
987}
988
989void
Joakim Tjernlunda49eb302008-09-02 19:06:31 +0100990ospf_if_update (struct ospf *ospf, struct interface *ifp)
paul718e3742002-12-13 20:15:29 +0000991{
992 struct route_node *rn;
paul718e3742002-12-13 20:15:29 +0000993 struct ospf_network *network;
994 struct ospf_area *area;
Joakim Tjernlunda49eb302008-09-02 19:06:31 +0100995
996 if (!ospf)
997 ospf = ospf_lookup ();
paul718e3742002-12-13 20:15:29 +0000998
Joakim Tjernlund6e687d72008-09-24 17:15:48 +0100999 /* OSPF must be on and Router-ID must be configured. */
1000 if (!ospf || ospf->router_id.s_addr == 0)
Joakim Tjernlunda49eb302008-09-02 19:06:31 +01001001 return;
1002
1003 /* Run each netowrk for this interface. */
1004 for (rn = route_top (ospf->networks); rn; rn = route_next (rn))
1005 if (rn->info != NULL)
1006 {
1007 network = (struct ospf_network *) rn->info;
1008 area = ospf_area_get (ospf, network->area_id, network->format);
1009 ospf_network_run_interface (&rn->p, area, ifp);
1010 }
paul718e3742002-12-13 20:15:29 +00001011}
1012
1013void
paul68980082003-03-25 05:07:42 +00001014ospf_remove_vls_through_area (struct ospf *ospf, struct ospf_area *area)
paul718e3742002-12-13 20:15:29 +00001015{
paul1eb8ef22005-04-07 07:30:20 +00001016 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001017 struct ospf_vl_data *vl_data;
1018
paul1eb8ef22005-04-07 07:30:20 +00001019 for (ALL_LIST_ELEMENTS (ospf->vlinks, node, nnode, vl_data))
1020 if (IPV4_ADDR_SAME (&vl_data->vl_area_id, &area->area_id))
1021 ospf_vl_delete (ospf, vl_data);
paul718e3742002-12-13 20:15:29 +00001022}
1023
1024
Stephen Hemminger7ba82f72009-05-15 10:47:45 -07001025static const struct message ospf_area_type_msg[] =
paul718e3742002-12-13 20:15:29 +00001026{
1027 { OSPF_AREA_DEFAULT, "Default" },
1028 { OSPF_AREA_STUB, "Stub" },
1029 { OSPF_AREA_NSSA, "NSSA" },
1030};
Stephen Hemminger7ba82f72009-05-15 10:47:45 -07001031static const int ospf_area_type_msg_max = OSPF_AREA_TYPE_MAX;
paul718e3742002-12-13 20:15:29 +00001032
paul4dadc292005-05-06 21:37:42 +00001033static void
paul718e3742002-12-13 20:15:29 +00001034ospf_area_type_set (struct ospf_area *area, int type)
1035{
hasso52dc7ee2004-09-23 19:18:23 +00001036 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00001037 struct ospf_interface *oi;
1038
1039 if (area->external_routing == type)
1040 {
1041 if (IS_DEBUG_OSPF_EVENT)
ajs9b0e25c2004-12-08 19:06:51 +00001042 zlog_debug ("Area[%s]: Types are the same, ignored.",
paul718e3742002-12-13 20:15:29 +00001043 inet_ntoa (area->area_id));
1044 return;
1045 }
1046
1047 area->external_routing = type;
1048
1049 if (IS_DEBUG_OSPF_EVENT)
ajs9b0e25c2004-12-08 19:06:51 +00001050 zlog_debug ("Area[%s]: Configured as %s", inet_ntoa (area->area_id),
paul718e3742002-12-13 20:15:29 +00001051 LOOKUP (ospf_area_type_msg, type));
1052
1053 switch (area->external_routing)
1054 {
1055 case OSPF_AREA_DEFAULT:
paul1eb8ef22005-04-07 07:30:20 +00001056 for (ALL_LIST_ELEMENTS_RO (area->oiflist, node, oi))
1057 if (oi->nbr_self != NULL)
1058 {
1059 UNSET_FLAG (oi->nbr_self->options, OSPF_OPTION_NP);
1060 SET_FLAG (oi->nbr_self->options, OSPF_OPTION_E);
1061 }
paul718e3742002-12-13 20:15:29 +00001062 break;
1063 case OSPF_AREA_STUB:
paul1eb8ef22005-04-07 07:30:20 +00001064 for (ALL_LIST_ELEMENTS_RO (area->oiflist, node, oi))
1065 if (oi->nbr_self != NULL)
1066 {
1067 if (IS_DEBUG_OSPF_EVENT)
1068 zlog_debug ("setting options on %s accordingly", IF_NAME (oi));
1069 UNSET_FLAG (oi->nbr_self->options, OSPF_OPTION_NP);
1070 UNSET_FLAG (oi->nbr_self->options, OSPF_OPTION_E);
1071 if (IS_DEBUG_OSPF_EVENT)
1072 zlog_debug ("options set on %s: %x",
1073 IF_NAME (oi), OPTIONS (oi));
1074 }
paul718e3742002-12-13 20:15:29 +00001075 break;
1076 case OSPF_AREA_NSSA:
paul1eb8ef22005-04-07 07:30:20 +00001077 for (ALL_LIST_ELEMENTS_RO (area->oiflist, node, oi))
1078 if (oi->nbr_self != NULL)
1079 {
1080 zlog_debug ("setting nssa options on %s accordingly", IF_NAME (oi));
1081 UNSET_FLAG (oi->nbr_self->options, OSPF_OPTION_E);
1082 SET_FLAG (oi->nbr_self->options, OSPF_OPTION_NP);
1083 zlog_debug ("options set on %s: %x", IF_NAME (oi), OPTIONS (oi));
1084 }
paul718e3742002-12-13 20:15:29 +00001085 break;
1086 default:
1087 break;
1088 }
1089
1090 ospf_router_lsa_timer_add (area);
paul68980082003-03-25 05:07:42 +00001091 ospf_schedule_abr_task (area->ospf);
paul718e3742002-12-13 20:15:29 +00001092}
1093
1094int
paul68980082003-03-25 05:07:42 +00001095ospf_area_shortcut_set (struct ospf *ospf, struct ospf_area *area, int mode)
paul718e3742002-12-13 20:15:29 +00001096{
1097 if (area->shortcut_configured == mode)
1098 return 0;
1099
1100 area->shortcut_configured = mode;
1101 ospf_router_lsa_timer_add (area);
paul68980082003-03-25 05:07:42 +00001102 ospf_schedule_abr_task (ospf);
paul718e3742002-12-13 20:15:29 +00001103
paul68980082003-03-25 05:07:42 +00001104 ospf_area_check_free (ospf, area->area_id);
paul718e3742002-12-13 20:15:29 +00001105
1106 return 1;
1107}
1108
1109int
paul68980082003-03-25 05:07:42 +00001110ospf_area_shortcut_unset (struct ospf *ospf, struct ospf_area *area)
paul718e3742002-12-13 20:15:29 +00001111{
1112 area->shortcut_configured = OSPF_SHORTCUT_DEFAULT;
1113 ospf_router_lsa_timer_add (area);
paul68980082003-03-25 05:07:42 +00001114 ospf_area_check_free (ospf, area->area_id);
1115 ospf_schedule_abr_task (ospf);
paul718e3742002-12-13 20:15:29 +00001116
1117 return 1;
1118}
1119
paul4dadc292005-05-06 21:37:42 +00001120static int
paul718e3742002-12-13 20:15:29 +00001121ospf_area_vlink_count (struct ospf *ospf, struct ospf_area *area)
1122{
1123 struct ospf_vl_data *vl;
hasso52dc7ee2004-09-23 19:18:23 +00001124 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00001125 int count = 0;
1126
paul1eb8ef22005-04-07 07:30:20 +00001127 for (ALL_LIST_ELEMENTS_RO (ospf->vlinks, node, vl))
1128 if (IPV4_ADDR_SAME (&vl->vl_area_id, &area->area_id))
1129 count++;
paul718e3742002-12-13 20:15:29 +00001130
1131 return count;
1132}
1133
1134int
1135ospf_area_stub_set (struct ospf *ospf, struct in_addr area_id)
1136{
1137 struct ospf_area *area;
paul147193a2003-04-19 00:31:59 +00001138 int format = OSPF_AREA_ID_FORMAT_ADDRESS;
paul718e3742002-12-13 20:15:29 +00001139
paul68980082003-03-25 05:07:42 +00001140 area = ospf_area_get (ospf, area_id, format);
paul718e3742002-12-13 20:15:29 +00001141 if (ospf_area_vlink_count (ospf, area))
1142 return 0;
1143
1144 if (area->external_routing != OSPF_AREA_STUB)
1145 ospf_area_type_set (area, OSPF_AREA_STUB);
1146
1147 return 1;
1148}
1149
1150int
1151ospf_area_stub_unset (struct ospf *ospf, struct in_addr area_id)
1152{
1153 struct ospf_area *area;
1154
paul68980082003-03-25 05:07:42 +00001155 area = ospf_area_lookup_by_area_id (ospf, area_id);
paul718e3742002-12-13 20:15:29 +00001156 if (area == NULL)
1157 return 1;
1158
1159 if (area->external_routing == OSPF_AREA_STUB)
1160 ospf_area_type_set (area, OSPF_AREA_DEFAULT);
1161
paul68980082003-03-25 05:07:42 +00001162 ospf_area_check_free (ospf, area_id);
paul718e3742002-12-13 20:15:29 +00001163
1164 return 1;
1165}
1166
1167int
1168ospf_area_no_summary_set (struct ospf *ospf, struct in_addr area_id)
1169{
1170 struct ospf_area *area;
paul147193a2003-04-19 00:31:59 +00001171 int format = OSPF_AREA_ID_FORMAT_ADDRESS;
paul718e3742002-12-13 20:15:29 +00001172
paul68980082003-03-25 05:07:42 +00001173 area = ospf_area_get (ospf, area_id, format);
paul718e3742002-12-13 20:15:29 +00001174 area->no_summary = 1;
1175
1176 return 1;
1177}
1178
1179int
1180ospf_area_no_summary_unset (struct ospf *ospf, struct in_addr area_id)
1181{
1182 struct ospf_area *area;
1183
paul68980082003-03-25 05:07:42 +00001184 area = ospf_area_lookup_by_area_id (ospf, area_id);
paul718e3742002-12-13 20:15:29 +00001185 if (area == NULL)
1186 return 0;
1187
1188 area->no_summary = 0;
paul68980082003-03-25 05:07:42 +00001189 ospf_area_check_free (ospf, area_id);
paul718e3742002-12-13 20:15:29 +00001190
1191 return 1;
1192}
1193
1194int
1195ospf_area_nssa_set (struct ospf *ospf, struct in_addr area_id)
1196{
1197 struct ospf_area *area;
paul147193a2003-04-19 00:31:59 +00001198 int format = OSPF_AREA_ID_FORMAT_ADDRESS;
paul718e3742002-12-13 20:15:29 +00001199
paul68980082003-03-25 05:07:42 +00001200 area = ospf_area_get (ospf, area_id, format);
paul718e3742002-12-13 20:15:29 +00001201 if (ospf_area_vlink_count (ospf, area))
1202 return 0;
1203
1204 if (area->external_routing != OSPF_AREA_NSSA)
1205 {
1206 ospf_area_type_set (area, OSPF_AREA_NSSA);
1207 ospf->anyNSSA++;
1208 }
1209
paul084c7842003-06-22 08:35:18 +00001210 /* set NSSA area defaults */
1211 area->no_summary = 0;
1212 area->NSSATranslatorRole = OSPF_NSSA_ROLE_CANDIDATE;
pauld4a53d52003-07-12 21:30:57 +00001213 area->NSSATranslatorState = OSPF_NSSA_TRANSLATE_DISABLED;
paul084c7842003-06-22 08:35:18 +00001214 area->NSSATranslatorStabilityInterval = OSPF_NSSA_TRANS_STABLE_DEFAULT;
1215
paul718e3742002-12-13 20:15:29 +00001216 return 1;
1217}
1218
1219int
1220ospf_area_nssa_unset (struct ospf *ospf, struct in_addr area_id)
1221{
1222 struct ospf_area *area;
1223
paul68980082003-03-25 05:07:42 +00001224 area = ospf_area_lookup_by_area_id (ospf, area_id);
paul718e3742002-12-13 20:15:29 +00001225 if (area == NULL)
1226 return 0;
1227
1228 if (area->external_routing == OSPF_AREA_NSSA)
1229 {
1230 ospf->anyNSSA--;
1231 ospf_area_type_set (area, OSPF_AREA_DEFAULT);
1232 }
1233
paul68980082003-03-25 05:07:42 +00001234 ospf_area_check_free (ospf, area_id);
paul718e3742002-12-13 20:15:29 +00001235
1236 return 1;
1237}
1238
1239int
1240ospf_area_nssa_translator_role_set (struct ospf *ospf, struct in_addr area_id,
1241 int role)
1242{
1243 struct ospf_area *area;
1244
paul68980082003-03-25 05:07:42 +00001245 area = ospf_area_lookup_by_area_id (ospf, area_id);
paul718e3742002-12-13 20:15:29 +00001246 if (area == NULL)
1247 return 0;
1248
paul084c7842003-06-22 08:35:18 +00001249 area->NSSATranslatorRole = role;
paul718e3742002-12-13 20:15:29 +00001250
1251 return 1;
1252}
1253
paul4dadc292005-05-06 21:37:42 +00001254/* XXX: unused? Leave for symmetry? */
1255static int
paul718e3742002-12-13 20:15:29 +00001256ospf_area_nssa_translator_role_unset (struct ospf *ospf,
1257 struct in_addr area_id)
1258{
1259 struct ospf_area *area;
1260
paul68980082003-03-25 05:07:42 +00001261 area = ospf_area_lookup_by_area_id (ospf, area_id);
paul718e3742002-12-13 20:15:29 +00001262 if (area == NULL)
1263 return 0;
1264
paul084c7842003-06-22 08:35:18 +00001265 area->NSSATranslatorRole = OSPF_NSSA_ROLE_CANDIDATE;
paul718e3742002-12-13 20:15:29 +00001266
paul68980082003-03-25 05:07:42 +00001267 ospf_area_check_free (ospf, area_id);
paul718e3742002-12-13 20:15:29 +00001268
1269 return 1;
1270}
1271
1272int
paul68980082003-03-25 05:07:42 +00001273ospf_area_export_list_set (struct ospf *ospf,
paul6c835672004-10-11 11:00:30 +00001274 struct ospf_area *area, const char *list_name)
paul718e3742002-12-13 20:15:29 +00001275{
1276 struct access_list *list;
1277 list = access_list_lookup (AFI_IP, list_name);
1278
1279 EXPORT_LIST (area) = list;
1280
1281 if (EXPORT_NAME (area))
1282 free (EXPORT_NAME (area));
1283
1284 EXPORT_NAME (area) = strdup (list_name);
paul68980082003-03-25 05:07:42 +00001285 ospf_schedule_abr_task (ospf);
paul718e3742002-12-13 20:15:29 +00001286
1287 return 1;
1288}
1289
1290int
paul68980082003-03-25 05:07:42 +00001291ospf_area_export_list_unset (struct ospf *ospf, struct ospf_area * area)
paul718e3742002-12-13 20:15:29 +00001292{
1293
1294 EXPORT_LIST (area) = 0;
1295
1296 if (EXPORT_NAME (area))
1297 free (EXPORT_NAME (area));
1298
1299 EXPORT_NAME (area) = NULL;
1300
paul68980082003-03-25 05:07:42 +00001301 ospf_area_check_free (ospf, area->area_id);
paul718e3742002-12-13 20:15:29 +00001302
paul68980082003-03-25 05:07:42 +00001303 ospf_schedule_abr_task (ospf);
paul718e3742002-12-13 20:15:29 +00001304
1305 return 1;
1306}
1307
1308int
paul6c835672004-10-11 11:00:30 +00001309ospf_area_import_list_set (struct ospf *ospf, struct ospf_area *area,
1310 const char *name)
paul718e3742002-12-13 20:15:29 +00001311{
1312 struct access_list *list;
1313 list = access_list_lookup (AFI_IP, name);
1314
1315 IMPORT_LIST (area) = list;
1316
1317 if (IMPORT_NAME (area))
1318 free (IMPORT_NAME (area));
1319
1320 IMPORT_NAME (area) = strdup (name);
paul68980082003-03-25 05:07:42 +00001321 ospf_schedule_abr_task (ospf);
paul718e3742002-12-13 20:15:29 +00001322
1323 return 1;
1324}
1325
1326int
paul68980082003-03-25 05:07:42 +00001327ospf_area_import_list_unset (struct ospf *ospf, struct ospf_area * area)
paul718e3742002-12-13 20:15:29 +00001328{
1329 IMPORT_LIST (area) = 0;
1330
1331 if (IMPORT_NAME (area))
1332 free (IMPORT_NAME (area));
1333
1334 IMPORT_NAME (area) = NULL;
paul68980082003-03-25 05:07:42 +00001335 ospf_area_check_free (ospf, area->area_id);
paul718e3742002-12-13 20:15:29 +00001336
paul68980082003-03-25 05:07:42 +00001337 ospf_schedule_abr_task (ospf);
paul718e3742002-12-13 20:15:29 +00001338
1339 return 1;
1340}
1341
1342int
paul718e3742002-12-13 20:15:29 +00001343ospf_timers_refresh_set (struct ospf *ospf, int interval)
1344{
1345 int time_left;
1346
1347 if (ospf->lsa_refresh_interval == interval)
1348 return 1;
1349
1350 time_left = ospf->lsa_refresh_interval -
Paul Jakma2518efd2006-08-27 06:49:29 +00001351 (quagga_time (NULL) - ospf->lsa_refresher_started);
paul718e3742002-12-13 20:15:29 +00001352
1353 if (time_left > interval)
1354 {
1355 OSPF_TIMER_OFF (ospf->t_lsa_refresher);
1356 ospf->t_lsa_refresher =
1357 thread_add_timer (master, ospf_lsa_refresh_walker, ospf, interval);
1358 }
1359 ospf->lsa_refresh_interval = interval;
1360
1361 return 1;
1362}
1363
1364int
1365ospf_timers_refresh_unset (struct ospf *ospf)
1366{
1367 int time_left;
1368
1369 time_left = ospf->lsa_refresh_interval -
Paul Jakma2518efd2006-08-27 06:49:29 +00001370 (quagga_time (NULL) - ospf->lsa_refresher_started);
paul718e3742002-12-13 20:15:29 +00001371
1372 if (time_left > OSPF_LSA_REFRESH_INTERVAL_DEFAULT)
1373 {
1374 OSPF_TIMER_OFF (ospf->t_lsa_refresher);
1375 ospf->t_lsa_refresher =
1376 thread_add_timer (master, ospf_lsa_refresh_walker, ospf,
1377 OSPF_LSA_REFRESH_INTERVAL_DEFAULT);
1378 }
1379
1380 ospf->lsa_refresh_interval = OSPF_LSA_REFRESH_INTERVAL_DEFAULT;
1381
1382 return 1;
1383}
1384
1385
paul4dadc292005-05-06 21:37:42 +00001386static struct ospf_nbr_nbma *
1387ospf_nbr_nbma_new (void)
paul718e3742002-12-13 20:15:29 +00001388{
1389 struct ospf_nbr_nbma *nbr_nbma;
1390
Stephen Hemminger393deb92008-08-18 14:13:29 -07001391 nbr_nbma = XCALLOC (MTYPE_OSPF_NEIGHBOR_STATIC,
paul718e3742002-12-13 20:15:29 +00001392 sizeof (struct ospf_nbr_nbma));
paul718e3742002-12-13 20:15:29 +00001393
1394 nbr_nbma->priority = OSPF_NEIGHBOR_PRIORITY_DEFAULT;
1395 nbr_nbma->v_poll = OSPF_POLL_INTERVAL_DEFAULT;
1396
1397 return nbr_nbma;
1398}
1399
paul4dadc292005-05-06 21:37:42 +00001400static void
paul718e3742002-12-13 20:15:29 +00001401ospf_nbr_nbma_free (struct ospf_nbr_nbma *nbr_nbma)
1402{
1403 XFREE (MTYPE_OSPF_NEIGHBOR_STATIC, nbr_nbma);
1404}
1405
paul4dadc292005-05-06 21:37:42 +00001406static void
paul718e3742002-12-13 20:15:29 +00001407ospf_nbr_nbma_delete (struct ospf *ospf, struct ospf_nbr_nbma *nbr_nbma)
1408{
1409 struct route_node *rn;
1410 struct prefix_ipv4 p;
1411
1412 p.family = AF_INET;
1413 p.prefix = nbr_nbma->addr;
1414 p.prefixlen = IPV4_MAX_BITLEN;
1415
1416 rn = route_node_lookup (ospf->nbr_nbma, (struct prefix *)&p);
1417 if (rn)
1418 {
1419 ospf_nbr_nbma_free (rn->info);
1420 rn->info = NULL;
1421 route_unlock_node (rn);
1422 route_unlock_node (rn);
1423 }
1424}
1425
paul4dadc292005-05-06 21:37:42 +00001426static void
paul718e3742002-12-13 20:15:29 +00001427ospf_nbr_nbma_down (struct ospf_nbr_nbma *nbr_nbma)
1428{
1429 OSPF_TIMER_OFF (nbr_nbma->t_poll);
1430
1431 if (nbr_nbma->nbr)
1432 {
1433 nbr_nbma->nbr->nbr_nbma = NULL;
1434 OSPF_NSM_EVENT_EXECUTE (nbr_nbma->nbr, NSM_KillNbr);
1435 }
1436
1437 if (nbr_nbma->oi)
1438 listnode_delete (nbr_nbma->oi->nbr_nbma, nbr_nbma);
1439}
1440
paul4dadc292005-05-06 21:37:42 +00001441static void
paul718e3742002-12-13 20:15:29 +00001442ospf_nbr_nbma_add (struct ospf_nbr_nbma *nbr_nbma,
1443 struct ospf_interface *oi)
1444{
1445 struct ospf_neighbor *nbr;
1446 struct route_node *rn;
1447 struct prefix p;
1448
1449 if (oi->type != OSPF_IFTYPE_NBMA)
1450 return;
1451
1452 if (nbr_nbma->nbr != NULL)
1453 return;
1454
1455 if (IPV4_ADDR_SAME (&oi->nbr_self->address.u.prefix4, &nbr_nbma->addr))
1456 return;
1457
1458 nbr_nbma->oi = oi;
1459 listnode_add (oi->nbr_nbma, nbr_nbma);
1460
1461 /* Get neighbor information from table. */
1462 p.family = AF_INET;
1463 p.prefixlen = IPV4_MAX_BITLEN;
1464 p.u.prefix4 = nbr_nbma->addr;
1465
1466 rn = route_node_get (oi->nbrs, (struct prefix *)&p);
1467 if (rn->info)
1468 {
1469 nbr = rn->info;
1470 nbr->nbr_nbma = nbr_nbma;
1471 nbr_nbma->nbr = nbr;
1472
1473 route_unlock_node (rn);
1474 }
1475 else
1476 {
1477 nbr = rn->info = ospf_nbr_new (oi);
1478 nbr->state = NSM_Down;
1479 nbr->src = nbr_nbma->addr;
1480 nbr->nbr_nbma = nbr_nbma;
1481 nbr->priority = nbr_nbma->priority;
1482 nbr->address = p;
1483
1484 nbr_nbma->nbr = nbr;
1485
1486 OSPF_NSM_EVENT_EXECUTE (nbr, NSM_Start);
1487 }
1488}
1489
1490void
paul68980082003-03-25 05:07:42 +00001491ospf_nbr_nbma_if_update (struct ospf *ospf, struct ospf_interface *oi)
paul718e3742002-12-13 20:15:29 +00001492{
1493 struct ospf_nbr_nbma *nbr_nbma;
1494 struct route_node *rn;
1495 struct prefix_ipv4 p;
1496
1497 if (oi->type != OSPF_IFTYPE_NBMA)
1498 return;
1499
paul68980082003-03-25 05:07:42 +00001500 for (rn = route_top (ospf->nbr_nbma); rn; rn = route_next (rn))
paul718e3742002-12-13 20:15:29 +00001501 if ((nbr_nbma = rn->info))
1502 if (nbr_nbma->oi == NULL && nbr_nbma->nbr == NULL)
1503 {
1504 p.family = AF_INET;
1505 p.prefix = nbr_nbma->addr;
1506 p.prefixlen = IPV4_MAX_BITLEN;
1507
1508 if (prefix_match (oi->address, (struct prefix *)&p))
1509 ospf_nbr_nbma_add (nbr_nbma, oi);
1510 }
1511}
1512
1513struct ospf_nbr_nbma *
1514ospf_nbr_nbma_lookup (struct ospf *ospf, struct in_addr nbr_addr)
1515{
1516 struct route_node *rn;
1517 struct prefix_ipv4 p;
1518
1519 p.family = AF_INET;
1520 p.prefix = nbr_addr;
1521 p.prefixlen = IPV4_MAX_BITLEN;
1522
1523 rn = route_node_lookup (ospf->nbr_nbma, (struct prefix *)&p);
1524 if (rn)
1525 {
1526 route_unlock_node (rn);
1527 return rn->info;
1528 }
1529 return NULL;
1530}
1531
1532struct ospf_nbr_nbma *
paul68980082003-03-25 05:07:42 +00001533ospf_nbr_nbma_lookup_next (struct ospf *ospf, struct in_addr *addr, int first)
paul718e3742002-12-13 20:15:29 +00001534{
1535#if 0
1536 struct ospf_nbr_nbma *nbr_nbma;
hasso52dc7ee2004-09-23 19:18:23 +00001537 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00001538#endif
1539
paul68980082003-03-25 05:07:42 +00001540 if (ospf == NULL)
paul718e3742002-12-13 20:15:29 +00001541 return NULL;
1542
1543#if 0
paul1eb8ef22005-04-07 07:30:20 +00001544 for (ALL_LIST_ELEMENTS_RO (ospf->nbr_nbma, node, nbr_nbma))
paul718e3742002-12-13 20:15:29 +00001545 {
paul718e3742002-12-13 20:15:29 +00001546 if (first)
1547 {
1548 *addr = nbr_nbma->addr;
1549 return nbr_nbma;
1550 }
1551 else if (ntohl (nbr_nbma->addr.s_addr) > ntohl (addr->s_addr))
1552 {
1553 *addr = nbr_nbma->addr;
1554 return nbr_nbma;
1555 }
1556 }
1557#endif
1558 return NULL;
1559}
1560
1561int
1562ospf_nbr_nbma_set (struct ospf *ospf, struct in_addr nbr_addr)
1563{
1564 struct ospf_nbr_nbma *nbr_nbma;
1565 struct ospf_interface *oi;
1566 struct prefix_ipv4 p;
1567 struct route_node *rn;
hasso52dc7ee2004-09-23 19:18:23 +00001568 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00001569
1570 nbr_nbma = ospf_nbr_nbma_lookup (ospf, nbr_addr);
1571 if (nbr_nbma)
1572 return 0;
1573
1574 nbr_nbma = ospf_nbr_nbma_new ();
1575 nbr_nbma->addr = nbr_addr;
1576
1577 p.family = AF_INET;
1578 p.prefix = nbr_addr;
1579 p.prefixlen = IPV4_MAX_BITLEN;
1580
1581 rn = route_node_get (ospf->nbr_nbma, (struct prefix *)&p);
1582 rn->info = nbr_nbma;
1583
paul1eb8ef22005-04-07 07:30:20 +00001584 for (ALL_LIST_ELEMENTS_RO (ospf->oiflist, node, oi))
paul718e3742002-12-13 20:15:29 +00001585 {
paul718e3742002-12-13 20:15:29 +00001586 if (oi->type == OSPF_IFTYPE_NBMA)
1587 if (prefix_match (oi->address, (struct prefix *)&p))
1588 {
1589 ospf_nbr_nbma_add (nbr_nbma, oi);
1590 break;
1591 }
1592 }
1593
1594 return 1;
1595}
1596
1597int
1598ospf_nbr_nbma_unset (struct ospf *ospf, struct in_addr nbr_addr)
1599{
1600 struct ospf_nbr_nbma *nbr_nbma;
1601
1602 nbr_nbma = ospf_nbr_nbma_lookup (ospf, nbr_addr);
1603 if (nbr_nbma == NULL)
1604 return 0;
1605
1606 ospf_nbr_nbma_down (nbr_nbma);
1607 ospf_nbr_nbma_delete (ospf, nbr_nbma);
1608
1609 return 1;
1610}
1611
1612int
1613ospf_nbr_nbma_priority_set (struct ospf *ospf, struct in_addr nbr_addr,
1614 u_char priority)
1615{
1616 struct ospf_nbr_nbma *nbr_nbma;
1617
1618 nbr_nbma = ospf_nbr_nbma_lookup (ospf, nbr_addr);
1619 if (nbr_nbma == NULL)
1620 return 0;
1621
1622 if (nbr_nbma->priority != priority)
1623 nbr_nbma->priority = priority;
1624
1625 return 1;
1626}
1627
1628int
1629ospf_nbr_nbma_priority_unset (struct ospf *ospf, struct in_addr nbr_addr)
1630{
1631 struct ospf_nbr_nbma *nbr_nbma;
1632
1633 nbr_nbma = ospf_nbr_nbma_lookup (ospf, nbr_addr);
1634 if (nbr_nbma == NULL)
1635 return 0;
1636
1637 if (nbr_nbma != OSPF_NEIGHBOR_PRIORITY_DEFAULT)
1638 nbr_nbma->priority = OSPF_NEIGHBOR_PRIORITY_DEFAULT;
1639
1640 return 1;
1641}
1642
1643int
1644ospf_nbr_nbma_poll_interval_set (struct ospf *ospf, struct in_addr nbr_addr,
paul6c835672004-10-11 11:00:30 +00001645 unsigned int interval)
paul718e3742002-12-13 20:15:29 +00001646{
1647 struct ospf_nbr_nbma *nbr_nbma;
1648
1649 nbr_nbma = ospf_nbr_nbma_lookup (ospf, nbr_addr);
1650 if (nbr_nbma == NULL)
1651 return 0;
1652
1653 if (nbr_nbma->v_poll != interval)
1654 {
1655 nbr_nbma->v_poll = interval;
1656 if (nbr_nbma->oi && ospf_if_is_up (nbr_nbma->oi))
1657 {
1658 OSPF_TIMER_OFF (nbr_nbma->t_poll);
1659 OSPF_POLL_TIMER_ON (nbr_nbma->t_poll, ospf_poll_timer,
1660 nbr_nbma->v_poll);
1661 }
1662 }
1663
1664 return 1;
1665}
1666
1667int
1668ospf_nbr_nbma_poll_interval_unset (struct ospf *ospf, struct in_addr addr)
1669{
1670 struct ospf_nbr_nbma *nbr_nbma;
1671
1672 nbr_nbma = ospf_nbr_nbma_lookup (ospf, addr);
1673 if (nbr_nbma == NULL)
1674 return 0;
1675
1676 if (nbr_nbma->v_poll != OSPF_POLL_INTERVAL_DEFAULT)
1677 nbr_nbma->v_poll = OSPF_POLL_INTERVAL_DEFAULT;
1678
1679 return 1;
1680}
1681
paul718e3742002-12-13 20:15:29 +00001682void
paul020709f2003-04-04 02:44:16 +00001683ospf_master_init ()
1684{
1685 memset (&ospf_master, 0, sizeof (struct ospf_master));
1686
1687 om = &ospf_master;
1688 om->ospf = list_new ();
1689 om->master = thread_master_create ();
Paul Jakma2518efd2006-08-27 06:49:29 +00001690 om->start_time = quagga_time (NULL);
paul020709f2003-04-04 02:44:16 +00001691}