blob: c951a29a843fc4c9e75e8563e97e15915877377d [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;
785 if (!IPV4_ADDR_SAME (&area_id, &network->area_id))
786 return 0;
787
paul68980082003-03-25 05:07:42 +0000788 ospf_network_free (ospf, rn->info);
paul718e3742002-12-13 20:15:29 +0000789 rn->info = NULL;
790 route_unlock_node (rn);
791
Joakim Tjernlunda49eb302008-09-02 19:06:31 +0100792 /* Find interfaces that not configured already. */
793 for (ALL_LIST_ELEMENTS (ospf->oiflist, node, nnode, oi))
794 {
795 int found = 0;
796 struct connected *co = oi->connected;
797
798 if (oi->type == OSPF_IFTYPE_VIRTUALLINK)
799 continue;
800
801 for (rn = route_top (ospf->networks); rn; rn = route_next (rn))
802 {
803 if (rn->info == NULL)
804 continue;
805
806 if (ospf_network_match_iface(co,&rn->p))
807 {
808 found = 1;
809 route_unlock_node (rn);
810 break;
811 }
812 }
813
814 if (found == 0)
815 ospf_if_free (oi);
816 }
paul718e3742002-12-13 20:15:29 +0000817
818 /* Update connected redistribute. */
819 if (ospf_is_type_redistributed (ZEBRA_ROUTE_CONNECT))
820 if (EXTERNAL_INFO (ZEBRA_ROUTE_CONNECT))
821 for (rn = route_top (EXTERNAL_INFO (ZEBRA_ROUTE_CONNECT));
822 rn; rn = route_next (rn))
823 if ((ei = rn->info) != NULL)
paul68980082003-03-25 05:07:42 +0000824 if (!ospf_external_info_find_lsa (ospf, &ei->p))
825 if (ospf_distribute_check_connected (ospf, ei))
826 ospf_external_lsa_originate (ospf, ei);
paul718e3742002-12-13 20:15:29 +0000827
828 return 1;
829}
830
paul570f7592003-01-25 06:47:41 +0000831/* Check whether interface matches given network
832 * returns: 1, true. 0, false
833 */
834int
835ospf_network_match_iface(struct connected *co, struct prefix *net)
836{
Andrew J. Schorrf0ec8322007-04-30 16:52:05 +0000837/* #define COMPATIBILITY_MODE */
Andrew J. Schorre4529632006-12-12 19:18:21 +0000838 /* The old code used to have a special case for PtP interfaces:
839
840 if (if_is_pointopoint (co->ifp) && co->destination &&
841 IPV4_ADDR_SAME ( &(co->destination->u.prefix4), &(net->u.prefix4)))
842 return 1;
843
844 The new approach is much more general. If a peer address is supplied,
845 then we are routing to that prefix, so that's the address to compare
846 against (not the local address, which may not be unique).
847 */
848#ifndef COMPATIBILITY_MODE
849 /* new approach: more elegant and conceptually clean */
850 return prefix_match(net, CONNECTED_PREFIX(co));
851#else /* COMPATIBILITY_MODE */
852 /* match old (strange?) behavior */
853
paul570f7592003-01-25 06:47:41 +0000854 /* Behaviour to match both Cisco where:
855 * iface address lies within network specified -> ospf
856 * and zebra 0.9[2ish-3]:
857 * PtP special case: network specified == iface peer addr -> ospf
858 */
gdt8f40e892003-12-05 14:01:43 +0000859
paulf3ae74c2004-11-04 20:35:31 +0000860 /* For PtP, match if peer address matches network address exactly.
861 * This can be addr/32 or addr/p for p < 32, but the addr must match
862 * exactly; this is not a test for falling within the prefix. This
gdt8f40e892003-12-05 14:01:43 +0000863 * test is solely for compatibility with zebra.
gdt8f40e892003-12-05 14:01:43 +0000864 */
Andrew J. Schorre4529632006-12-12 19:18:21 +0000865 if (CONNECTED_PEER(co) &&
paulf3ae74c2004-11-04 20:35:31 +0000866 IPV4_ADDR_SAME ( &(co->destination->u.prefix4), &(net->u.prefix4)))
867 return 1;
868
869#if 0
870 /* Decline to accept PtP if dst address does not match the
871 * prefix. (ifdefed out because this is a workaround, not the
872 * desired behavior.) */
873 if (if_is_pointopoint (co->ifp) &&
874 ! prefix_match (net, co->destination))
875 return 0;
876#endif
877
878 /* If the address is within the prefix, accept. Note that this
879 * applies to PtP as well as other types.
880 */
881 if (prefix_match (net, co->address))
882 return 1;
883
884 return 0; /* no match */
Andrew J. Schorre4529632006-12-12 19:18:21 +0000885
886#endif /* COMPATIBILITY_MODE */
paul570f7592003-01-25 06:47:41 +0000887}
888
paul718e3742002-12-13 20:15:29 +0000889void
Joakim Tjernlunda49eb302008-09-02 19:06:31 +0100890ospf_network_run_interface (struct prefix *p, struct ospf_area *area,
891 struct interface *ifp)
892{
893 struct listnode *cnode;
894 struct connected *co;
895
896 if (memcmp (ifp->name, "VLINK", 5) == 0)
897 return;
898
899 /* if interface prefix is match specified prefix,
900 then create socket and join multicast group. */
901 for (ALL_LIST_ELEMENTS_RO (ifp->connected, cnode, co))
902 {
903 struct prefix *addr;
904
905 if (CHECK_FLAG(co->flags,ZEBRA_IFA_SECONDARY))
906 continue;
907
908 addr = CONNECTED_ID(co);
909
910 if (p->family == co->address->family
911 && ! ospf_if_is_configured (area->ospf, &(addr->u.prefix4))
912 && ospf_network_match_iface(co,p))
913 {
914 struct ospf_interface *oi;
915
916 oi = ospf_if_new (area->ospf, ifp, co->address);
917 oi->connected = co;
918
919 oi->area = area;
920
921 oi->params = ospf_lookup_if_params (ifp, oi->address->u.prefix4);
922 oi->output_cost = ospf_if_get_output_cost (oi);
923
924 /* Add pseudo neighbor. */
925 ospf_nbr_add_self (oi);
926
927 /* Relate ospf interface to ospf instance. */
928 oi->ospf = area->ospf;
929
930 /* update network type as interface flag */
931 /* If network type is specified previously,
932 skip network type setting. */
933 oi->type = IF_DEF_PARAMS (ifp)->type;
934
935 ospf_area_add_if (oi->area, oi);
936
937 /* if router_id is not configured, dont bring up
938 * interfaces.
939 * ospf_router_id_update() will call ospf_if_update
940 * whenever r-id is configured instead.
941 */
942 if ((area->ospf->router_id.s_addr != 0)
943 && if_is_operative (ifp))
944 ospf_if_up (oi);
945 }
946 }
947}
948
949void
950ospf_network_run (struct prefix *p, struct ospf_area *area)
paul718e3742002-12-13 20:15:29 +0000951{
952 struct interface *ifp;
hasso52dc7ee2004-09-23 19:18:23 +0000953 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000954
955 /* Schedule Router ID Update. */
Joakim Tjernlunda49eb302008-09-02 19:06:31 +0100956 if (area->ospf->router_id.s_addr == 0)
957 ospf_router_id_update (area->ospf);
paulb29800a2005-11-20 14:50:45 +0000958
paul718e3742002-12-13 20:15:29 +0000959 /* Get target interface. */
paul1eb8ef22005-04-07 07:30:20 +0000960 for (ALL_LIST_ELEMENTS_RO (om->iflist, node, ifp))
Joakim Tjernlunda49eb302008-09-02 19:06:31 +0100961 ospf_network_run_interface (p, area, ifp);
paul718e3742002-12-13 20:15:29 +0000962}
963
964void
965ospf_ls_upd_queue_empty (struct ospf_interface *oi)
966{
967 struct route_node *rn;
paul1eb8ef22005-04-07 07:30:20 +0000968 struct listnode *node, *nnode;
hasso52dc7ee2004-09-23 19:18:23 +0000969 struct list *lst;
paul718e3742002-12-13 20:15:29 +0000970 struct ospf_lsa *lsa;
971
972 /* empty ls update queue */
973 for (rn = route_top (oi->ls_upd_queue); rn;
974 rn = route_next (rn))
hasso52dc7ee2004-09-23 19:18:23 +0000975 if ((lst = (struct list *) rn->info))
paul718e3742002-12-13 20:15:29 +0000976 {
paul1eb8ef22005-04-07 07:30:20 +0000977 for (ALL_LIST_ELEMENTS (lst, node, nnode, lsa))
Paul Jakma1fe6ed32006-07-26 09:37:26 +0000978 ospf_lsa_unlock (&lsa); /* oi->ls_upd_queue */
paul718e3742002-12-13 20:15:29 +0000979 list_free (lst);
980 rn->info = NULL;
981 }
982
983 /* remove update event */
984 if (oi->t_ls_upd_event)
985 {
986 thread_cancel (oi->t_ls_upd_event);
987 oi->t_ls_upd_event = NULL;
988 }
989}
990
991void
Joakim Tjernlunda49eb302008-09-02 19:06:31 +0100992ospf_if_update (struct ospf *ospf, struct interface *ifp)
paul718e3742002-12-13 20:15:29 +0000993{
994 struct route_node *rn;
paul718e3742002-12-13 20:15:29 +0000995 struct ospf_network *network;
996 struct ospf_area *area;
Joakim Tjernlunda49eb302008-09-02 19:06:31 +0100997
998 if (!ospf)
999 ospf = ospf_lookup ();
paul718e3742002-12-13 20:15:29 +00001000
Joakim Tjernlund6e687d72008-09-24 17:15:48 +01001001 /* OSPF must be on and Router-ID must be configured. */
1002 if (!ospf || ospf->router_id.s_addr == 0)
Joakim Tjernlunda49eb302008-09-02 19:06:31 +01001003 return;
1004
1005 /* Run each netowrk for this interface. */
1006 for (rn = route_top (ospf->networks); rn; rn = route_next (rn))
1007 if (rn->info != NULL)
1008 {
1009 network = (struct ospf_network *) rn->info;
1010 area = ospf_area_get (ospf, network->area_id, network->format);
1011 ospf_network_run_interface (&rn->p, area, ifp);
1012 }
paul718e3742002-12-13 20:15:29 +00001013}
1014
1015void
paul68980082003-03-25 05:07:42 +00001016ospf_remove_vls_through_area (struct ospf *ospf, struct ospf_area *area)
paul718e3742002-12-13 20:15:29 +00001017{
paul1eb8ef22005-04-07 07:30:20 +00001018 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001019 struct ospf_vl_data *vl_data;
1020
paul1eb8ef22005-04-07 07:30:20 +00001021 for (ALL_LIST_ELEMENTS (ospf->vlinks, node, nnode, vl_data))
1022 if (IPV4_ADDR_SAME (&vl_data->vl_area_id, &area->area_id))
1023 ospf_vl_delete (ospf, vl_data);
paul718e3742002-12-13 20:15:29 +00001024}
1025
1026
1027struct message ospf_area_type_msg[] =
1028{
1029 { OSPF_AREA_DEFAULT, "Default" },
1030 { OSPF_AREA_STUB, "Stub" },
1031 { OSPF_AREA_NSSA, "NSSA" },
1032};
1033int ospf_area_type_msg_max = OSPF_AREA_TYPE_MAX;
1034
paul4dadc292005-05-06 21:37:42 +00001035static void
paul718e3742002-12-13 20:15:29 +00001036ospf_area_type_set (struct ospf_area *area, int type)
1037{
hasso52dc7ee2004-09-23 19:18:23 +00001038 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00001039 struct ospf_interface *oi;
1040
1041 if (area->external_routing == type)
1042 {
1043 if (IS_DEBUG_OSPF_EVENT)
ajs9b0e25c2004-12-08 19:06:51 +00001044 zlog_debug ("Area[%s]: Types are the same, ignored.",
paul718e3742002-12-13 20:15:29 +00001045 inet_ntoa (area->area_id));
1046 return;
1047 }
1048
1049 area->external_routing = type;
1050
1051 if (IS_DEBUG_OSPF_EVENT)
ajs9b0e25c2004-12-08 19:06:51 +00001052 zlog_debug ("Area[%s]: Configured as %s", inet_ntoa (area->area_id),
paul718e3742002-12-13 20:15:29 +00001053 LOOKUP (ospf_area_type_msg, type));
1054
1055 switch (area->external_routing)
1056 {
1057 case OSPF_AREA_DEFAULT:
paul1eb8ef22005-04-07 07:30:20 +00001058 for (ALL_LIST_ELEMENTS_RO (area->oiflist, node, oi))
1059 if (oi->nbr_self != NULL)
1060 {
1061 UNSET_FLAG (oi->nbr_self->options, OSPF_OPTION_NP);
1062 SET_FLAG (oi->nbr_self->options, OSPF_OPTION_E);
1063 }
paul718e3742002-12-13 20:15:29 +00001064 break;
1065 case OSPF_AREA_STUB:
paul1eb8ef22005-04-07 07:30:20 +00001066 for (ALL_LIST_ELEMENTS_RO (area->oiflist, node, oi))
1067 if (oi->nbr_self != NULL)
1068 {
1069 if (IS_DEBUG_OSPF_EVENT)
1070 zlog_debug ("setting options on %s accordingly", IF_NAME (oi));
1071 UNSET_FLAG (oi->nbr_self->options, OSPF_OPTION_NP);
1072 UNSET_FLAG (oi->nbr_self->options, OSPF_OPTION_E);
1073 if (IS_DEBUG_OSPF_EVENT)
1074 zlog_debug ("options set on %s: %x",
1075 IF_NAME (oi), OPTIONS (oi));
1076 }
paul718e3742002-12-13 20:15:29 +00001077 break;
1078 case OSPF_AREA_NSSA:
paul1eb8ef22005-04-07 07:30:20 +00001079 for (ALL_LIST_ELEMENTS_RO (area->oiflist, node, oi))
1080 if (oi->nbr_self != NULL)
1081 {
1082 zlog_debug ("setting nssa options on %s accordingly", IF_NAME (oi));
1083 UNSET_FLAG (oi->nbr_self->options, OSPF_OPTION_E);
1084 SET_FLAG (oi->nbr_self->options, OSPF_OPTION_NP);
1085 zlog_debug ("options set on %s: %x", IF_NAME (oi), OPTIONS (oi));
1086 }
paul718e3742002-12-13 20:15:29 +00001087 break;
1088 default:
1089 break;
1090 }
1091
1092 ospf_router_lsa_timer_add (area);
paul68980082003-03-25 05:07:42 +00001093 ospf_schedule_abr_task (area->ospf);
paul718e3742002-12-13 20:15:29 +00001094}
1095
1096int
paul68980082003-03-25 05:07:42 +00001097ospf_area_shortcut_set (struct ospf *ospf, struct ospf_area *area, int mode)
paul718e3742002-12-13 20:15:29 +00001098{
1099 if (area->shortcut_configured == mode)
1100 return 0;
1101
1102 area->shortcut_configured = mode;
1103 ospf_router_lsa_timer_add (area);
paul68980082003-03-25 05:07:42 +00001104 ospf_schedule_abr_task (ospf);
paul718e3742002-12-13 20:15:29 +00001105
paul68980082003-03-25 05:07:42 +00001106 ospf_area_check_free (ospf, area->area_id);
paul718e3742002-12-13 20:15:29 +00001107
1108 return 1;
1109}
1110
1111int
paul68980082003-03-25 05:07:42 +00001112ospf_area_shortcut_unset (struct ospf *ospf, struct ospf_area *area)
paul718e3742002-12-13 20:15:29 +00001113{
1114 area->shortcut_configured = OSPF_SHORTCUT_DEFAULT;
1115 ospf_router_lsa_timer_add (area);
paul68980082003-03-25 05:07:42 +00001116 ospf_area_check_free (ospf, area->area_id);
1117 ospf_schedule_abr_task (ospf);
paul718e3742002-12-13 20:15:29 +00001118
1119 return 1;
1120}
1121
paul4dadc292005-05-06 21:37:42 +00001122static int
paul718e3742002-12-13 20:15:29 +00001123ospf_area_vlink_count (struct ospf *ospf, struct ospf_area *area)
1124{
1125 struct ospf_vl_data *vl;
hasso52dc7ee2004-09-23 19:18:23 +00001126 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00001127 int count = 0;
1128
paul1eb8ef22005-04-07 07:30:20 +00001129 for (ALL_LIST_ELEMENTS_RO (ospf->vlinks, node, vl))
1130 if (IPV4_ADDR_SAME (&vl->vl_area_id, &area->area_id))
1131 count++;
paul718e3742002-12-13 20:15:29 +00001132
1133 return count;
1134}
1135
1136int
1137ospf_area_stub_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 if (ospf_area_vlink_count (ospf, area))
1144 return 0;
1145
1146 if (area->external_routing != OSPF_AREA_STUB)
1147 ospf_area_type_set (area, OSPF_AREA_STUB);
1148
1149 return 1;
1150}
1151
1152int
1153ospf_area_stub_unset (struct ospf *ospf, struct in_addr area_id)
1154{
1155 struct ospf_area *area;
1156
paul68980082003-03-25 05:07:42 +00001157 area = ospf_area_lookup_by_area_id (ospf, area_id);
paul718e3742002-12-13 20:15:29 +00001158 if (area == NULL)
1159 return 1;
1160
1161 if (area->external_routing == OSPF_AREA_STUB)
1162 ospf_area_type_set (area, OSPF_AREA_DEFAULT);
1163
paul68980082003-03-25 05:07:42 +00001164 ospf_area_check_free (ospf, area_id);
paul718e3742002-12-13 20:15:29 +00001165
1166 return 1;
1167}
1168
1169int
1170ospf_area_no_summary_set (struct ospf *ospf, struct in_addr area_id)
1171{
1172 struct ospf_area *area;
paul147193a2003-04-19 00:31:59 +00001173 int format = OSPF_AREA_ID_FORMAT_ADDRESS;
paul718e3742002-12-13 20:15:29 +00001174
paul68980082003-03-25 05:07:42 +00001175 area = ospf_area_get (ospf, area_id, format);
paul718e3742002-12-13 20:15:29 +00001176 area->no_summary = 1;
1177
1178 return 1;
1179}
1180
1181int
1182ospf_area_no_summary_unset (struct ospf *ospf, struct in_addr area_id)
1183{
1184 struct ospf_area *area;
1185
paul68980082003-03-25 05:07:42 +00001186 area = ospf_area_lookup_by_area_id (ospf, area_id);
paul718e3742002-12-13 20:15:29 +00001187 if (area == NULL)
1188 return 0;
1189
1190 area->no_summary = 0;
paul68980082003-03-25 05:07:42 +00001191 ospf_area_check_free (ospf, area_id);
paul718e3742002-12-13 20:15:29 +00001192
1193 return 1;
1194}
1195
1196int
1197ospf_area_nssa_set (struct ospf *ospf, struct in_addr area_id)
1198{
1199 struct ospf_area *area;
paul147193a2003-04-19 00:31:59 +00001200 int format = OSPF_AREA_ID_FORMAT_ADDRESS;
paul718e3742002-12-13 20:15:29 +00001201
paul68980082003-03-25 05:07:42 +00001202 area = ospf_area_get (ospf, area_id, format);
paul718e3742002-12-13 20:15:29 +00001203 if (ospf_area_vlink_count (ospf, area))
1204 return 0;
1205
1206 if (area->external_routing != OSPF_AREA_NSSA)
1207 {
1208 ospf_area_type_set (area, OSPF_AREA_NSSA);
1209 ospf->anyNSSA++;
1210 }
1211
paul084c7842003-06-22 08:35:18 +00001212 /* set NSSA area defaults */
1213 area->no_summary = 0;
1214 area->NSSATranslatorRole = OSPF_NSSA_ROLE_CANDIDATE;
pauld4a53d52003-07-12 21:30:57 +00001215 area->NSSATranslatorState = OSPF_NSSA_TRANSLATE_DISABLED;
paul084c7842003-06-22 08:35:18 +00001216 area->NSSATranslatorStabilityInterval = OSPF_NSSA_TRANS_STABLE_DEFAULT;
1217
paul718e3742002-12-13 20:15:29 +00001218 return 1;
1219}
1220
1221int
1222ospf_area_nssa_unset (struct ospf *ospf, struct in_addr area_id)
1223{
1224 struct ospf_area *area;
1225
paul68980082003-03-25 05:07:42 +00001226 area = ospf_area_lookup_by_area_id (ospf, area_id);
paul718e3742002-12-13 20:15:29 +00001227 if (area == NULL)
1228 return 0;
1229
1230 if (area->external_routing == OSPF_AREA_NSSA)
1231 {
1232 ospf->anyNSSA--;
1233 ospf_area_type_set (area, OSPF_AREA_DEFAULT);
1234 }
1235
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
1242ospf_area_nssa_translator_role_set (struct ospf *ospf, struct in_addr area_id,
1243 int role)
1244{
1245 struct ospf_area *area;
1246
paul68980082003-03-25 05:07:42 +00001247 area = ospf_area_lookup_by_area_id (ospf, area_id);
paul718e3742002-12-13 20:15:29 +00001248 if (area == NULL)
1249 return 0;
1250
paul084c7842003-06-22 08:35:18 +00001251 area->NSSATranslatorRole = role;
paul718e3742002-12-13 20:15:29 +00001252
1253 return 1;
1254}
1255
paul4dadc292005-05-06 21:37:42 +00001256/* XXX: unused? Leave for symmetry? */
1257static int
paul718e3742002-12-13 20:15:29 +00001258ospf_area_nssa_translator_role_unset (struct ospf *ospf,
1259 struct in_addr area_id)
1260{
1261 struct ospf_area *area;
1262
paul68980082003-03-25 05:07:42 +00001263 area = ospf_area_lookup_by_area_id (ospf, area_id);
paul718e3742002-12-13 20:15:29 +00001264 if (area == NULL)
1265 return 0;
1266
paul084c7842003-06-22 08:35:18 +00001267 area->NSSATranslatorRole = OSPF_NSSA_ROLE_CANDIDATE;
paul718e3742002-12-13 20:15:29 +00001268
paul68980082003-03-25 05:07:42 +00001269 ospf_area_check_free (ospf, area_id);
paul718e3742002-12-13 20:15:29 +00001270
1271 return 1;
1272}
1273
1274int
paul68980082003-03-25 05:07:42 +00001275ospf_area_export_list_set (struct ospf *ospf,
paul6c835672004-10-11 11:00:30 +00001276 struct ospf_area *area, const char *list_name)
paul718e3742002-12-13 20:15:29 +00001277{
1278 struct access_list *list;
1279 list = access_list_lookup (AFI_IP, list_name);
1280
1281 EXPORT_LIST (area) = list;
1282
1283 if (EXPORT_NAME (area))
1284 free (EXPORT_NAME (area));
1285
1286 EXPORT_NAME (area) = strdup (list_name);
paul68980082003-03-25 05:07:42 +00001287 ospf_schedule_abr_task (ospf);
paul718e3742002-12-13 20:15:29 +00001288
1289 return 1;
1290}
1291
1292int
paul68980082003-03-25 05:07:42 +00001293ospf_area_export_list_unset (struct ospf *ospf, struct ospf_area * area)
paul718e3742002-12-13 20:15:29 +00001294{
1295
1296 EXPORT_LIST (area) = 0;
1297
1298 if (EXPORT_NAME (area))
1299 free (EXPORT_NAME (area));
1300
1301 EXPORT_NAME (area) = NULL;
1302
paul68980082003-03-25 05:07:42 +00001303 ospf_area_check_free (ospf, area->area_id);
paul718e3742002-12-13 20:15:29 +00001304
paul68980082003-03-25 05:07:42 +00001305 ospf_schedule_abr_task (ospf);
paul718e3742002-12-13 20:15:29 +00001306
1307 return 1;
1308}
1309
1310int
paul6c835672004-10-11 11:00:30 +00001311ospf_area_import_list_set (struct ospf *ospf, struct ospf_area *area,
1312 const char *name)
paul718e3742002-12-13 20:15:29 +00001313{
1314 struct access_list *list;
1315 list = access_list_lookup (AFI_IP, name);
1316
1317 IMPORT_LIST (area) = list;
1318
1319 if (IMPORT_NAME (area))
1320 free (IMPORT_NAME (area));
1321
1322 IMPORT_NAME (area) = strdup (name);
paul68980082003-03-25 05:07:42 +00001323 ospf_schedule_abr_task (ospf);
paul718e3742002-12-13 20:15:29 +00001324
1325 return 1;
1326}
1327
1328int
paul68980082003-03-25 05:07:42 +00001329ospf_area_import_list_unset (struct ospf *ospf, struct ospf_area * area)
paul718e3742002-12-13 20:15:29 +00001330{
1331 IMPORT_LIST (area) = 0;
1332
1333 if (IMPORT_NAME (area))
1334 free (IMPORT_NAME (area));
1335
1336 IMPORT_NAME (area) = NULL;
paul68980082003-03-25 05:07:42 +00001337 ospf_area_check_free (ospf, area->area_id);
paul718e3742002-12-13 20:15:29 +00001338
paul68980082003-03-25 05:07:42 +00001339 ospf_schedule_abr_task (ospf);
paul718e3742002-12-13 20:15:29 +00001340
1341 return 1;
1342}
1343
1344int
paul718e3742002-12-13 20:15:29 +00001345ospf_timers_refresh_set (struct ospf *ospf, int interval)
1346{
1347 int time_left;
1348
1349 if (ospf->lsa_refresh_interval == interval)
1350 return 1;
1351
1352 time_left = ospf->lsa_refresh_interval -
Paul Jakma2518efd2006-08-27 06:49:29 +00001353 (quagga_time (NULL) - ospf->lsa_refresher_started);
paul718e3742002-12-13 20:15:29 +00001354
1355 if (time_left > interval)
1356 {
1357 OSPF_TIMER_OFF (ospf->t_lsa_refresher);
1358 ospf->t_lsa_refresher =
1359 thread_add_timer (master, ospf_lsa_refresh_walker, ospf, interval);
1360 }
1361 ospf->lsa_refresh_interval = interval;
1362
1363 return 1;
1364}
1365
1366int
1367ospf_timers_refresh_unset (struct ospf *ospf)
1368{
1369 int time_left;
1370
1371 time_left = ospf->lsa_refresh_interval -
Paul Jakma2518efd2006-08-27 06:49:29 +00001372 (quagga_time (NULL) - ospf->lsa_refresher_started);
paul718e3742002-12-13 20:15:29 +00001373
1374 if (time_left > OSPF_LSA_REFRESH_INTERVAL_DEFAULT)
1375 {
1376 OSPF_TIMER_OFF (ospf->t_lsa_refresher);
1377 ospf->t_lsa_refresher =
1378 thread_add_timer (master, ospf_lsa_refresh_walker, ospf,
1379 OSPF_LSA_REFRESH_INTERVAL_DEFAULT);
1380 }
1381
1382 ospf->lsa_refresh_interval = OSPF_LSA_REFRESH_INTERVAL_DEFAULT;
1383
1384 return 1;
1385}
1386
1387
paul4dadc292005-05-06 21:37:42 +00001388static struct ospf_nbr_nbma *
1389ospf_nbr_nbma_new (void)
paul718e3742002-12-13 20:15:29 +00001390{
1391 struct ospf_nbr_nbma *nbr_nbma;
1392
1393 nbr_nbma = XMALLOC (MTYPE_OSPF_NEIGHBOR_STATIC,
1394 sizeof (struct ospf_nbr_nbma));
1395 memset (nbr_nbma, 0, sizeof (struct ospf_nbr_nbma));
1396
1397 nbr_nbma->priority = OSPF_NEIGHBOR_PRIORITY_DEFAULT;
1398 nbr_nbma->v_poll = OSPF_POLL_INTERVAL_DEFAULT;
1399
1400 return nbr_nbma;
1401}
1402
paul4dadc292005-05-06 21:37:42 +00001403static void
paul718e3742002-12-13 20:15:29 +00001404ospf_nbr_nbma_free (struct ospf_nbr_nbma *nbr_nbma)
1405{
1406 XFREE (MTYPE_OSPF_NEIGHBOR_STATIC, nbr_nbma);
1407}
1408
paul4dadc292005-05-06 21:37:42 +00001409static void
paul718e3742002-12-13 20:15:29 +00001410ospf_nbr_nbma_delete (struct ospf *ospf, struct ospf_nbr_nbma *nbr_nbma)
1411{
1412 struct route_node *rn;
1413 struct prefix_ipv4 p;
1414
1415 p.family = AF_INET;
1416 p.prefix = nbr_nbma->addr;
1417 p.prefixlen = IPV4_MAX_BITLEN;
1418
1419 rn = route_node_lookup (ospf->nbr_nbma, (struct prefix *)&p);
1420 if (rn)
1421 {
1422 ospf_nbr_nbma_free (rn->info);
1423 rn->info = NULL;
1424 route_unlock_node (rn);
1425 route_unlock_node (rn);
1426 }
1427}
1428
paul4dadc292005-05-06 21:37:42 +00001429static void
paul718e3742002-12-13 20:15:29 +00001430ospf_nbr_nbma_down (struct ospf_nbr_nbma *nbr_nbma)
1431{
1432 OSPF_TIMER_OFF (nbr_nbma->t_poll);
1433
1434 if (nbr_nbma->nbr)
1435 {
1436 nbr_nbma->nbr->nbr_nbma = NULL;
1437 OSPF_NSM_EVENT_EXECUTE (nbr_nbma->nbr, NSM_KillNbr);
1438 }
1439
1440 if (nbr_nbma->oi)
1441 listnode_delete (nbr_nbma->oi->nbr_nbma, nbr_nbma);
1442}
1443
paul4dadc292005-05-06 21:37:42 +00001444static void
paul718e3742002-12-13 20:15:29 +00001445ospf_nbr_nbma_add (struct ospf_nbr_nbma *nbr_nbma,
1446 struct ospf_interface *oi)
1447{
1448 struct ospf_neighbor *nbr;
1449 struct route_node *rn;
1450 struct prefix p;
1451
1452 if (oi->type != OSPF_IFTYPE_NBMA)
1453 return;
1454
1455 if (nbr_nbma->nbr != NULL)
1456 return;
1457
1458 if (IPV4_ADDR_SAME (&oi->nbr_self->address.u.prefix4, &nbr_nbma->addr))
1459 return;
1460
1461 nbr_nbma->oi = oi;
1462 listnode_add (oi->nbr_nbma, nbr_nbma);
1463
1464 /* Get neighbor information from table. */
1465 p.family = AF_INET;
1466 p.prefixlen = IPV4_MAX_BITLEN;
1467 p.u.prefix4 = nbr_nbma->addr;
1468
1469 rn = route_node_get (oi->nbrs, (struct prefix *)&p);
1470 if (rn->info)
1471 {
1472 nbr = rn->info;
1473 nbr->nbr_nbma = nbr_nbma;
1474 nbr_nbma->nbr = nbr;
1475
1476 route_unlock_node (rn);
1477 }
1478 else
1479 {
1480 nbr = rn->info = ospf_nbr_new (oi);
1481 nbr->state = NSM_Down;
1482 nbr->src = nbr_nbma->addr;
1483 nbr->nbr_nbma = nbr_nbma;
1484 nbr->priority = nbr_nbma->priority;
1485 nbr->address = p;
1486
1487 nbr_nbma->nbr = nbr;
1488
1489 OSPF_NSM_EVENT_EXECUTE (nbr, NSM_Start);
1490 }
1491}
1492
1493void
paul68980082003-03-25 05:07:42 +00001494ospf_nbr_nbma_if_update (struct ospf *ospf, struct ospf_interface *oi)
paul718e3742002-12-13 20:15:29 +00001495{
1496 struct ospf_nbr_nbma *nbr_nbma;
1497 struct route_node *rn;
1498 struct prefix_ipv4 p;
1499
1500 if (oi->type != OSPF_IFTYPE_NBMA)
1501 return;
1502
paul68980082003-03-25 05:07:42 +00001503 for (rn = route_top (ospf->nbr_nbma); rn; rn = route_next (rn))
paul718e3742002-12-13 20:15:29 +00001504 if ((nbr_nbma = rn->info))
1505 if (nbr_nbma->oi == NULL && nbr_nbma->nbr == NULL)
1506 {
1507 p.family = AF_INET;
1508 p.prefix = nbr_nbma->addr;
1509 p.prefixlen = IPV4_MAX_BITLEN;
1510
1511 if (prefix_match (oi->address, (struct prefix *)&p))
1512 ospf_nbr_nbma_add (nbr_nbma, oi);
1513 }
1514}
1515
1516struct ospf_nbr_nbma *
1517ospf_nbr_nbma_lookup (struct ospf *ospf, struct in_addr nbr_addr)
1518{
1519 struct route_node *rn;
1520 struct prefix_ipv4 p;
1521
1522 p.family = AF_INET;
1523 p.prefix = nbr_addr;
1524 p.prefixlen = IPV4_MAX_BITLEN;
1525
1526 rn = route_node_lookup (ospf->nbr_nbma, (struct prefix *)&p);
1527 if (rn)
1528 {
1529 route_unlock_node (rn);
1530 return rn->info;
1531 }
1532 return NULL;
1533}
1534
1535struct ospf_nbr_nbma *
paul68980082003-03-25 05:07:42 +00001536ospf_nbr_nbma_lookup_next (struct ospf *ospf, struct in_addr *addr, int first)
paul718e3742002-12-13 20:15:29 +00001537{
1538#if 0
1539 struct ospf_nbr_nbma *nbr_nbma;
hasso52dc7ee2004-09-23 19:18:23 +00001540 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00001541#endif
1542
paul68980082003-03-25 05:07:42 +00001543 if (ospf == NULL)
paul718e3742002-12-13 20:15:29 +00001544 return NULL;
1545
1546#if 0
paul1eb8ef22005-04-07 07:30:20 +00001547 for (ALL_LIST_ELEMENTS_RO (ospf->nbr_nbma, node, nbr_nbma))
paul718e3742002-12-13 20:15:29 +00001548 {
paul718e3742002-12-13 20:15:29 +00001549 if (first)
1550 {
1551 *addr = nbr_nbma->addr;
1552 return nbr_nbma;
1553 }
1554 else if (ntohl (nbr_nbma->addr.s_addr) > ntohl (addr->s_addr))
1555 {
1556 *addr = nbr_nbma->addr;
1557 return nbr_nbma;
1558 }
1559 }
1560#endif
1561 return NULL;
1562}
1563
1564int
1565ospf_nbr_nbma_set (struct ospf *ospf, struct in_addr nbr_addr)
1566{
1567 struct ospf_nbr_nbma *nbr_nbma;
1568 struct ospf_interface *oi;
1569 struct prefix_ipv4 p;
1570 struct route_node *rn;
hasso52dc7ee2004-09-23 19:18:23 +00001571 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00001572
1573 nbr_nbma = ospf_nbr_nbma_lookup (ospf, nbr_addr);
1574 if (nbr_nbma)
1575 return 0;
1576
1577 nbr_nbma = ospf_nbr_nbma_new ();
1578 nbr_nbma->addr = nbr_addr;
1579
1580 p.family = AF_INET;
1581 p.prefix = nbr_addr;
1582 p.prefixlen = IPV4_MAX_BITLEN;
1583
1584 rn = route_node_get (ospf->nbr_nbma, (struct prefix *)&p);
1585 rn->info = nbr_nbma;
1586
paul1eb8ef22005-04-07 07:30:20 +00001587 for (ALL_LIST_ELEMENTS_RO (ospf->oiflist, node, oi))
paul718e3742002-12-13 20:15:29 +00001588 {
paul718e3742002-12-13 20:15:29 +00001589 if (oi->type == OSPF_IFTYPE_NBMA)
1590 if (prefix_match (oi->address, (struct prefix *)&p))
1591 {
1592 ospf_nbr_nbma_add (nbr_nbma, oi);
1593 break;
1594 }
1595 }
1596
1597 return 1;
1598}
1599
1600int
1601ospf_nbr_nbma_unset (struct ospf *ospf, struct in_addr nbr_addr)
1602{
1603 struct ospf_nbr_nbma *nbr_nbma;
1604
1605 nbr_nbma = ospf_nbr_nbma_lookup (ospf, nbr_addr);
1606 if (nbr_nbma == NULL)
1607 return 0;
1608
1609 ospf_nbr_nbma_down (nbr_nbma);
1610 ospf_nbr_nbma_delete (ospf, nbr_nbma);
1611
1612 return 1;
1613}
1614
1615int
1616ospf_nbr_nbma_priority_set (struct ospf *ospf, struct in_addr nbr_addr,
1617 u_char priority)
1618{
1619 struct ospf_nbr_nbma *nbr_nbma;
1620
1621 nbr_nbma = ospf_nbr_nbma_lookup (ospf, nbr_addr);
1622 if (nbr_nbma == NULL)
1623 return 0;
1624
1625 if (nbr_nbma->priority != priority)
1626 nbr_nbma->priority = priority;
1627
1628 return 1;
1629}
1630
1631int
1632ospf_nbr_nbma_priority_unset (struct ospf *ospf, struct in_addr nbr_addr)
1633{
1634 struct ospf_nbr_nbma *nbr_nbma;
1635
1636 nbr_nbma = ospf_nbr_nbma_lookup (ospf, nbr_addr);
1637 if (nbr_nbma == NULL)
1638 return 0;
1639
1640 if (nbr_nbma != OSPF_NEIGHBOR_PRIORITY_DEFAULT)
1641 nbr_nbma->priority = OSPF_NEIGHBOR_PRIORITY_DEFAULT;
1642
1643 return 1;
1644}
1645
1646int
1647ospf_nbr_nbma_poll_interval_set (struct ospf *ospf, struct in_addr nbr_addr,
paul6c835672004-10-11 11:00:30 +00001648 unsigned int interval)
paul718e3742002-12-13 20:15:29 +00001649{
1650 struct ospf_nbr_nbma *nbr_nbma;
1651
1652 nbr_nbma = ospf_nbr_nbma_lookup (ospf, nbr_addr);
1653 if (nbr_nbma == NULL)
1654 return 0;
1655
1656 if (nbr_nbma->v_poll != interval)
1657 {
1658 nbr_nbma->v_poll = interval;
1659 if (nbr_nbma->oi && ospf_if_is_up (nbr_nbma->oi))
1660 {
1661 OSPF_TIMER_OFF (nbr_nbma->t_poll);
1662 OSPF_POLL_TIMER_ON (nbr_nbma->t_poll, ospf_poll_timer,
1663 nbr_nbma->v_poll);
1664 }
1665 }
1666
1667 return 1;
1668}
1669
1670int
1671ospf_nbr_nbma_poll_interval_unset (struct ospf *ospf, struct in_addr addr)
1672{
1673 struct ospf_nbr_nbma *nbr_nbma;
1674
1675 nbr_nbma = ospf_nbr_nbma_lookup (ospf, addr);
1676 if (nbr_nbma == NULL)
1677 return 0;
1678
1679 if (nbr_nbma->v_poll != OSPF_POLL_INTERVAL_DEFAULT)
1680 nbr_nbma->v_poll = OSPF_POLL_INTERVAL_DEFAULT;
1681
1682 return 1;
1683}
1684
paul718e3742002-12-13 20:15:29 +00001685void
paul020709f2003-04-04 02:44:16 +00001686ospf_master_init ()
1687{
1688 memset (&ospf_master, 0, sizeof (struct ospf_master));
1689
1690 om = &ospf_master;
1691 om->ospf = list_new ();
1692 om->master = thread_master_create ();
Paul Jakma2518efd2006-08-27 06:49:29 +00001693 om->start_time = quagga_time (NULL);
paul020709f2003-04-04 02:44:16 +00001694}