blob: bf8ca4dcb046125f94379b03b6676b26122b1a6a [file] [log] [blame]
paul718e3742002-12-13 20:15:29 +00001/* OSPF version 2 daemon program.
2 Copyright (C) 1999, 2000 Toshiaki Takada
3
4This file is part of GNU Zebra.
5
6GNU Zebra is free software; you can redistribute it and/or modify it
7under the terms of the GNU General Public License as published by the
8Free Software Foundation; either version 2, or (at your option) any
9later version.
10
11GNU Zebra is distributed in the hope that it will be useful, but
12WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with GNU Zebra; see the file COPYING. If not, write to the Free
18Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
1902111-1307, USA. */
20
21#include <zebra.h>
22
23#include "thread.h"
24#include "vty.h"
25#include "command.h"
26#include "linklist.h"
27#include "prefix.h"
28#include "table.h"
29#include "if.h"
30#include "memory.h"
31#include "stream.h"
32#include "log.h"
33#include "sockunion.h" /* for inet_aton () */
34#include "zclient.h"
35#include "plist.h"
36
37#include "ospfd/ospfd.h"
38#include "ospfd/ospf_network.h"
39#include "ospfd/ospf_interface.h"
40#include "ospfd/ospf_ism.h"
41#include "ospfd/ospf_asbr.h"
42#include "ospfd/ospf_lsa.h"
43#include "ospfd/ospf_lsdb.h"
44#include "ospfd/ospf_neighbor.h"
45#include "ospfd/ospf_nsm.h"
46#include "ospfd/ospf_spf.h"
47#include "ospfd/ospf_packet.h"
48#include "ospfd/ospf_dump.h"
49#include "ospfd/ospf_zebra.h"
50#include "ospfd/ospf_abr.h"
51#include "ospfd/ospf_flood.h"
52#include "ospfd/ospf_route.h"
53#include "ospfd/ospf_ase.h"
54
paul020709f2003-04-04 02:44:16 +000055
pauledd7c242003-06-04 13:59:38 +000056
paul020709f2003-04-04 02:44:16 +000057/* OSPF process wide configuration. */
58static struct ospf_master ospf_master;
59
60/* OSPF process wide configuration pointer to export. */
61struct ospf_master *om;
paul718e3742002-12-13 20:15:29 +000062
63extern struct zclient *zclient;
hasso18a6dce2004-10-03 18:18:34 +000064extern struct in_addr router_id_zebra;
paul718e3742002-12-13 20:15:29 +000065
66
paul68980082003-03-25 05:07:42 +000067void ospf_remove_vls_through_area (struct ospf *, struct ospf_area *);
68void ospf_network_free (struct ospf *, struct ospf_network *);
paul718e3742002-12-13 20:15:29 +000069void ospf_area_free (struct ospf_area *);
70void ospf_network_run (struct ospf *, struct prefix *, struct ospf_area *);
71
paul718e3742002-12-13 20:15:29 +000072#define OSPF_EXTERNAL_LSA_ORIGINATE_DELAY 1
73
74void
paul68980082003-03-25 05:07:42 +000075ospf_router_id_update (struct ospf *ospf)
paul718e3742002-12-13 20:15:29 +000076{
paul718e3742002-12-13 20:15:29 +000077 struct in_addr router_id, router_id_old;
paul1eb8ef22005-04-07 07:30:20 +000078 struct ospf_interface *oi;
hasso52dc7ee2004-09-23 19:18:23 +000079 struct listnode *node;
paul718e3742002-12-13 20:15:29 +000080
81 if (IS_DEBUG_OSPF_EVENT)
ajs9b0e25c2004-12-08 19:06:51 +000082 zlog_debug ("Router-ID[OLD:%s]: Update", inet_ntoa (ospf->router_id));
paul718e3742002-12-13 20:15:29 +000083
paul68980082003-03-25 05:07:42 +000084 router_id_old = ospf->router_id;
paul718e3742002-12-13 20:15:29 +000085
paul68980082003-03-25 05:07:42 +000086 if (ospf->router_id_static.s_addr != 0)
87 router_id = ospf->router_id_static;
paul718e3742002-12-13 20:15:29 +000088 else
hasso18a6dce2004-10-03 18:18:34 +000089 router_id = router_id_zebra;
paul718e3742002-12-13 20:15:29 +000090
paul68980082003-03-25 05:07:42 +000091 ospf->router_id = router_id;
paul718e3742002-12-13 20:15:29 +000092
93 if (IS_DEBUG_OSPF_EVENT)
ajs9b0e25c2004-12-08 19:06:51 +000094 zlog_debug ("Router-ID[NEW:%s]: Update", inet_ntoa (ospf->router_id));
paul718e3742002-12-13 20:15:29 +000095
96 if (!IPV4_ADDR_SAME (&router_id_old, &router_id))
97 {
paul1eb8ef22005-04-07 07:30:20 +000098 for (ALL_LIST_ELEMENTS_RO (ospf->oiflist, node, oi))
99 /* Update self-neighbor's router_id. */
100 oi->nbr_self->router_id = router_id;
paul718e3742002-12-13 20:15:29 +0000101
102 /* If AS-external-LSA is queued, then flush those LSAs. */
paul68980082003-03-25 05:07:42 +0000103 if (router_id_old.s_addr == 0 && ospf->external_origin)
paul718e3742002-12-13 20:15:29 +0000104 {
105 int type;
106 /* Originate each redistributed external route. */
107 for (type = 0; type < ZEBRA_ROUTE_MAX; type++)
paul68980082003-03-25 05:07:42 +0000108 if (ospf->external_origin & (1 << type))
paul718e3742002-12-13 20:15:29 +0000109 thread_add_event (master, ospf_external_lsa_originate_timer,
paul68980082003-03-25 05:07:42 +0000110 ospf, type);
paul718e3742002-12-13 20:15:29 +0000111 /* Originate Deafult. */
paul68980082003-03-25 05:07:42 +0000112 if (ospf->external_origin & (1 << ZEBRA_ROUTE_MAX))
paul718e3742002-12-13 20:15:29 +0000113 thread_add_event (master, ospf_default_originate_timer,
paul68980082003-03-25 05:07:42 +0000114 &ospf->default_originate, 0);
paul718e3742002-12-13 20:15:29 +0000115
paul68980082003-03-25 05:07:42 +0000116 ospf->external_origin = 0;
paul718e3742002-12-13 20:15:29 +0000117 }
118
paul68980082003-03-25 05:07:42 +0000119 OSPF_TIMER_ON (ospf->t_router_lsa_update,
paul718e3742002-12-13 20:15:29 +0000120 ospf_router_lsa_update_timer, OSPF_LSA_UPDATE_DELAY);
121 }
122}
123
124int
125ospf_router_id_update_timer (struct thread *thread)
126{
paul020709f2003-04-04 02:44:16 +0000127 struct ospf *ospf = THREAD_ARG (thread);
paul68980082003-03-25 05:07:42 +0000128
paul718e3742002-12-13 20:15:29 +0000129 if (IS_DEBUG_OSPF_EVENT)
ajs9b0e25c2004-12-08 19:06:51 +0000130 zlog_debug ("Router-ID: Update timer fired!");
paul718e3742002-12-13 20:15:29 +0000131
paul68980082003-03-25 05:07:42 +0000132 ospf->t_router_id_update = NULL;
133 ospf_router_id_update (ospf);
paul718e3742002-12-13 20:15:29 +0000134
135 return 0;
136}
137
138/* For OSPF area sort by area id. */
paul4dadc292005-05-06 21:37:42 +0000139static int
paul718e3742002-12-13 20:15:29 +0000140ospf_area_id_cmp (struct ospf_area *a1, struct ospf_area *a2)
141{
142 if (ntohl (a1->area_id.s_addr) > ntohl (a2->area_id.s_addr))
143 return 1;
144 if (ntohl (a1->area_id.s_addr) < ntohl (a2->area_id.s_addr))
145 return -1;
146 return 0;
147}
148
149/* Allocate new ospf structure. */
paul4dadc292005-05-06 21:37:42 +0000150static struct ospf *
151ospf_new (void)
paul718e3742002-12-13 20:15:29 +0000152{
153 int i;
154
155 struct ospf *new = XCALLOC (MTYPE_OSPF_TOP, sizeof (struct ospf));
156
157 new->router_id.s_addr = htonl (0);
158 new->router_id_static.s_addr = htonl (0);
159
pauld57834f2005-07-12 20:04:22 +0000160 new->abr_type = OSPF_ABR_DEFAULT;
paul718e3742002-12-13 20:15:29 +0000161 new->oiflist = list_new ();
162 new->vlinks = list_new ();
163 new->areas = list_new ();
164 new->areas->cmp = (int (*)(void *, void *)) ospf_area_id_cmp;
165 new->networks = route_table_init ();
166 new->nbr_nbma = route_table_init ();
167
168 new->lsdb = ospf_lsdb_new ();
169
170 new->default_originate = DEFAULT_ORIGINATE_NONE;
171
172 new->new_external_route = route_table_init ();
173 new->old_external_route = route_table_init ();
174 new->external_lsas = route_table_init ();
175
176 /* Distribute parameter init. */
177 for (i = 0; i <= ZEBRA_ROUTE_MAX; i++)
178 {
179 new->dmetric[i].type = -1;
180 new->dmetric[i].value = -1;
181 }
182 new->default_metric = -1;
183 new->ref_bandwidth = OSPF_DEFAULT_REF_BANDWIDTH;
184
185 /* SPF timer value init. */
186 new->spf_delay = OSPF_SPF_DELAY_DEFAULT;
187 new->spf_holdtime = OSPF_SPF_HOLDTIME_DEFAULT;
pauld24f6e22005-10-21 09:23:12 +0000188 new->spf_max_holdtime = OSPF_SPF_MAX_HOLDTIME_DEFAULT;
189 new->spf_hold_multiplier = 1;
paul718e3742002-12-13 20:15:29 +0000190
191 /* MaxAge init. */
192 new->maxage_lsa = list_new ();
193 new->t_maxage_walker =
194 thread_add_timer (master, ospf_lsa_maxage_walker,
paul68980082003-03-25 05:07:42 +0000195 new, OSPF_LSA_MAXAGE_CHECK_INTERVAL);
paul718e3742002-12-13 20:15:29 +0000196
197 /* Distance table init. */
198 new->distance_table = route_table_init ();
199
200 new->lsa_refresh_queue.index = 0;
201 new->lsa_refresh_interval = OSPF_LSA_REFRESH_INTERVAL_DEFAULT;
202 new->t_lsa_refresher = thread_add_timer (master, ospf_lsa_refresh_walker,
203 new, new->lsa_refresh_interval);
204 new->lsa_refresher_started = time (NULL);
205
ajs5c333492005-02-23 15:43:01 +0000206 if ((new->fd = ospf_sock_init()) < 0)
207 {
208 zlog_err("ospf_new: fatal error: ospf_sock_init was unable to open "
209 "a socket");
210 exit(1);
211 }
212 if ((new->ibuf = stream_new(OSPF_MAX_PACKET_SIZE+1)) == NULL)
213 {
214 zlog_err("ospf_new: fatal error: stream_new(%u) failed allocating ibuf",
215 OSPF_MAX_PACKET_SIZE+1);
216 exit(1);
217 }
218 new->t_read = thread_add_read (master, ospf_read, new, new->fd);
paul718e3742002-12-13 20:15:29 +0000219 new->oi_write_q = list_new ();
220
221 return new;
222}
223
224struct ospf *
paul020709f2003-04-04 02:44:16 +0000225ospf_lookup ()
226{
227 if (listcount (om->ospf) == 0)
228 return NULL;
229
paul1eb8ef22005-04-07 07:30:20 +0000230 return listgetdata (listhead (om->ospf));
paul020709f2003-04-04 02:44:16 +0000231}
232
paul4dadc292005-05-06 21:37:42 +0000233static void
paul020709f2003-04-04 02:44:16 +0000234ospf_add (struct ospf *ospf)
235{
236 listnode_add (om->ospf, ospf);
237}
238
paul4dadc292005-05-06 21:37:42 +0000239static void
paul020709f2003-04-04 02:44:16 +0000240ospf_delete (struct ospf *ospf)
241{
242 listnode_delete (om->ospf, ospf);
243}
244
245struct ospf *
paul718e3742002-12-13 20:15:29 +0000246ospf_get ()
247{
paul020709f2003-04-04 02:44:16 +0000248 struct ospf *ospf;
paul718e3742002-12-13 20:15:29 +0000249
paul020709f2003-04-04 02:44:16 +0000250 ospf = ospf_lookup ();
251 if (ospf == NULL)
252 {
253 ospf = ospf_new ();
254 ospf_add (ospf);
paul718e3742002-12-13 20:15:29 +0000255
paul020709f2003-04-04 02:44:16 +0000256 if (ospf->router_id_static.s_addr == 0)
257 ospf_router_id_update (ospf);
paul718e3742002-12-13 20:15:29 +0000258
259#ifdef HAVE_OPAQUE_LSA
paul020709f2003-04-04 02:44:16 +0000260 ospf_opaque_type11_lsa_init (ospf);
paul718e3742002-12-13 20:15:29 +0000261#endif /* HAVE_OPAQUE_LSA */
paul020709f2003-04-04 02:44:16 +0000262 }
paul68980082003-03-25 05:07:42 +0000263
264 return ospf;
paul718e3742002-12-13 20:15:29 +0000265}
266
267void
268ospf_finish (struct ospf *ospf)
269{
270 struct route_node *rn;
271 struct ospf_nbr_nbma *nbr_nbma;
paul68980082003-03-25 05:07:42 +0000272 struct ospf_lsa *lsa;
paul1eb8ef22005-04-07 07:30:20 +0000273 struct ospf_interface *oi;
274 struct ospf_area *area;
275 struct ospf_vl_data *vl_data;
276 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000277 int i;
278
279#ifdef HAVE_OPAQUE_LSA
280 ospf_opaque_type11_lsa_term (ospf);
281#endif /* HAVE_OPAQUE_LSA */
282
283 /* Unredister redistribution */
284 for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
paul020709f2003-04-04 02:44:16 +0000285 ospf_redistribute_unset (ospf, i);
paul718e3742002-12-13 20:15:29 +0000286
paul1eb8ef22005-04-07 07:30:20 +0000287 for (ALL_LIST_ELEMENTS (ospf->areas, node, nnode, area))
288 ospf_remove_vls_through_area (ospf, area);
paul718e3742002-12-13 20:15:29 +0000289
paul1eb8ef22005-04-07 07:30:20 +0000290 for (ALL_LIST_ELEMENTS (ospf->vlinks, node, nnode, vl_data))
291 ospf_vl_delete (ospf, vl_data);
paul718e3742002-12-13 20:15:29 +0000292
293 list_delete (ospf->vlinks);
294
295 /* Reset interface. */
paul1eb8ef22005-04-07 07:30:20 +0000296 for (ALL_LIST_ELEMENTS (ospf->oiflist, node, nnode, oi))
297 ospf_if_free (oi);
paul718e3742002-12-13 20:15:29 +0000298
299 /* Clear static neighbors */
300 for (rn = route_top (ospf->nbr_nbma); rn; rn = route_next (rn))
301 if ((nbr_nbma = rn->info))
302 {
303 OSPF_POLL_TIMER_OFF (nbr_nbma->t_poll);
304
305 if (nbr_nbma->nbr)
306 {
307 nbr_nbma->nbr->nbr_nbma = NULL;
308 nbr_nbma->nbr = NULL;
309 }
310
311 if (nbr_nbma->oi)
312 {
313 listnode_delete (nbr_nbma->oi->nbr_nbma, nbr_nbma);
314 nbr_nbma->oi = NULL;
315 }
316
317 XFREE (MTYPE_OSPF_NEIGHBOR_STATIC, nbr_nbma);
318 }
319
320 route_table_finish (ospf->nbr_nbma);
321
322 /* Clear networks and Areas. */
323 for (rn = route_top (ospf->networks); rn; rn = route_next (rn))
324 {
325 struct ospf_network *network;
326
327 if ((network = rn->info) != NULL)
328 {
paul68980082003-03-25 05:07:42 +0000329 ospf_network_free (ospf, network);
paul718e3742002-12-13 20:15:29 +0000330 rn->info = NULL;
331 route_unlock_node (rn);
332 }
333 }
334
paul1eb8ef22005-04-07 07:30:20 +0000335 for (ALL_LIST_ELEMENTS (ospf->areas, node, nnode, area))
paul718e3742002-12-13 20:15:29 +0000336 {
paul718e3742002-12-13 20:15:29 +0000337 listnode_delete (ospf->areas, area);
338 ospf_area_free (area);
339 }
340
341 /* Cancel all timers. */
342 OSPF_TIMER_OFF (ospf->t_external_lsa);
343 OSPF_TIMER_OFF (ospf->t_router_id_update);
344 OSPF_TIMER_OFF (ospf->t_router_lsa_update);
345 OSPF_TIMER_OFF (ospf->t_spf_calc);
346 OSPF_TIMER_OFF (ospf->t_ase_calc);
347 OSPF_TIMER_OFF (ospf->t_maxage);
348 OSPF_TIMER_OFF (ospf->t_maxage_walker);
349 OSPF_TIMER_OFF (ospf->t_abr_task);
350 OSPF_TIMER_OFF (ospf->t_distribute_update);
351 OSPF_TIMER_OFF (ospf->t_lsa_refresher);
352 OSPF_TIMER_OFF (ospf->t_read);
353 OSPF_TIMER_OFF (ospf->t_write);
354
355 close (ospf->fd);
ajs5c333492005-02-23 15:43:01 +0000356 stream_free(ospf->ibuf);
paul718e3742002-12-13 20:15:29 +0000357
358#ifdef HAVE_OPAQUE_LSA
paul68980082003-03-25 05:07:42 +0000359 LSDB_LOOP (OPAQUE_AS_LSDB (ospf), rn, lsa)
360 ospf_discard_from_db (ospf, ospf->lsdb, lsa);
paul718e3742002-12-13 20:15:29 +0000361#endif /* HAVE_OPAQUE_LSA */
paul68980082003-03-25 05:07:42 +0000362 LSDB_LOOP (EXTERNAL_LSDB (ospf), rn, lsa)
363 ospf_discard_from_db (ospf, ospf->lsdb, lsa);
364
paul718e3742002-12-13 20:15:29 +0000365 ospf_lsdb_delete_all (ospf->lsdb);
366 ospf_lsdb_free (ospf->lsdb);
367
paul1eb8ef22005-04-07 07:30:20 +0000368 for (ALL_LIST_ELEMENTS (ospf->maxage_lsa, node, nnode, lsa))
369 ospf_lsa_unlock (lsa);
paul718e3742002-12-13 20:15:29 +0000370
371 list_delete (ospf->maxage_lsa);
372
373 if (ospf->old_table)
374 ospf_route_table_free (ospf->old_table);
375 if (ospf->new_table)
376 {
377 ospf_route_delete (ospf->new_table);
378 ospf_route_table_free (ospf->new_table);
379 }
380 if (ospf->old_rtrs)
381 ospf_rtrs_free (ospf->old_rtrs);
382 if (ospf->new_rtrs)
383 ospf_rtrs_free (ospf->new_rtrs);
384 if (ospf->new_external_route)
385 {
386 ospf_route_delete (ospf->new_external_route);
387 ospf_route_table_free (ospf->new_external_route);
388 }
389 if (ospf->old_external_route)
390 {
391 ospf_route_delete (ospf->old_external_route);
392 ospf_route_table_free (ospf->old_external_route);
393 }
394 if (ospf->external_lsas)
395 {
396 ospf_ase_external_lsas_finish (ospf->external_lsas);
397 }
398
399 list_delete (ospf->areas);
400
401 for (i = ZEBRA_ROUTE_SYSTEM; i <= ZEBRA_ROUTE_MAX; i++)
402 if (EXTERNAL_INFO (i) != NULL)
403 for (rn = route_top (EXTERNAL_INFO (i)); rn; rn = route_next (rn))
404 {
405 if (rn->info == NULL)
406 continue;
407
408 XFREE (MTYPE_OSPF_EXTERNAL_INFO, rn->info);
409 rn->info = NULL;
410 route_unlock_node (rn);
411 }
412
paul68980082003-03-25 05:07:42 +0000413 ospf_distance_reset (ospf);
paul718e3742002-12-13 20:15:29 +0000414 route_table_finish (ospf->distance_table);
415
paul020709f2003-04-04 02:44:16 +0000416 ospf_delete (ospf);
paul718e3742002-12-13 20:15:29 +0000417
paul020709f2003-04-04 02:44:16 +0000418 XFREE (MTYPE_OSPF_TOP, ospf);
paul718e3742002-12-13 20:15:29 +0000419}
420
421
422/* allocate new OSPF Area object */
paul4dadc292005-05-06 21:37:42 +0000423static struct ospf_area *
paul68980082003-03-25 05:07:42 +0000424ospf_area_new (struct ospf *ospf, struct in_addr area_id)
paul718e3742002-12-13 20:15:29 +0000425{
426 struct ospf_area *new;
427
428 /* Allocate new config_network. */
429 new = XCALLOC (MTYPE_OSPF_AREA, sizeof (struct ospf_area));
430
paul68980082003-03-25 05:07:42 +0000431 new->ospf = ospf;
paul718e3742002-12-13 20:15:29 +0000432
433 new->area_id = area_id;
434
435 new->external_routing = OSPF_AREA_DEFAULT;
436 new->default_cost = 1;
437 new->auth_type = OSPF_AUTH_NULL;
438
439 /* New LSDB init. */
440 new->lsdb = ospf_lsdb_new ();
441
442 /* Self-originated LSAs initialize. */
443 new->router_lsa_self = NULL;
444
445#ifdef HAVE_OPAQUE_LSA
446 ospf_opaque_type10_lsa_init (new);
447#endif /* HAVE_OPAQUE_LSA */
448
449 new->oiflist = list_new ();
450 new->ranges = route_table_init ();
451
452 if (area_id.s_addr == OSPF_AREA_BACKBONE)
paul68980082003-03-25 05:07:42 +0000453 ospf->backbone = new;
paul718e3742002-12-13 20:15:29 +0000454
455 return new;
456}
457
458void
459ospf_area_free (struct ospf_area *area)
460{
paul68980082003-03-25 05:07:42 +0000461 struct route_node *rn;
462 struct ospf_lsa *lsa;
463
paul718e3742002-12-13 20:15:29 +0000464 /* Free LSDBs. */
paul68980082003-03-25 05:07:42 +0000465 LSDB_LOOP (ROUTER_LSDB (area), rn, lsa)
466 ospf_discard_from_db (area->ospf, area->lsdb, lsa);
467 LSDB_LOOP (NETWORK_LSDB (area), rn, lsa)
468 ospf_discard_from_db (area->ospf, area->lsdb, lsa);
469 LSDB_LOOP (SUMMARY_LSDB (area), rn, lsa)
470 ospf_discard_from_db (area->ospf, area->lsdb, lsa);
471 LSDB_LOOP (ASBR_SUMMARY_LSDB (area), rn, lsa)
472 ospf_discard_from_db (area->ospf, area->lsdb, lsa);
paul718e3742002-12-13 20:15:29 +0000473
paul68980082003-03-25 05:07:42 +0000474 LSDB_LOOP (NSSA_LSDB (area), rn, lsa)
475 ospf_discard_from_db (area->ospf, area->lsdb, lsa);
paul718e3742002-12-13 20:15:29 +0000476#ifdef HAVE_OPAQUE_LSA
paul68980082003-03-25 05:07:42 +0000477 LSDB_LOOP (OPAQUE_AREA_LSDB (area), rn, lsa)
478 ospf_discard_from_db (area->ospf, area->lsdb, lsa);
479 LSDB_LOOP (OPAQUE_LINK_LSDB (area), rn, lsa)
480 ospf_discard_from_db (area->ospf, area->lsdb, lsa);
paul718e3742002-12-13 20:15:29 +0000481#endif /* HAVE_OPAQUE_LSA */
482
483 ospf_lsdb_delete_all (area->lsdb);
484 ospf_lsdb_free (area->lsdb);
485
paul718e3742002-12-13 20:15:29 +0000486 ospf_lsa_unlock (area->router_lsa_self);
487
488 route_table_finish (area->ranges);
489 list_delete (area->oiflist);
490
491 if (EXPORT_NAME (area))
492 free (EXPORT_NAME (area));
493
494 if (IMPORT_NAME (area))
495 free (IMPORT_NAME (area));
496
497 /* Cancel timer. */
498 OSPF_TIMER_OFF (area->t_router_lsa_self);
499
500 if (OSPF_IS_AREA_BACKBONE (area))
paul68980082003-03-25 05:07:42 +0000501 area->ospf->backbone = NULL;
paul718e3742002-12-13 20:15:29 +0000502
503 XFREE (MTYPE_OSPF_AREA, area);
504}
505
506void
paul68980082003-03-25 05:07:42 +0000507ospf_area_check_free (struct ospf *ospf, struct in_addr area_id)
paul718e3742002-12-13 20:15:29 +0000508{
509 struct ospf_area *area;
510
paul68980082003-03-25 05:07:42 +0000511 area = ospf_area_lookup_by_area_id (ospf, area_id);
paul718e3742002-12-13 20:15:29 +0000512 if (area &&
513 listcount (area->oiflist) == 0 &&
514 area->ranges->top == NULL &&
515 area->shortcut_configured == OSPF_SHORTCUT_DEFAULT &&
516 area->external_routing == OSPF_AREA_DEFAULT &&
517 area->no_summary == 0 &&
518 area->default_cost == 1 &&
519 EXPORT_NAME (area) == NULL &&
520 IMPORT_NAME (area) == NULL &&
521 area->auth_type == OSPF_AUTH_NULL)
522 {
paul68980082003-03-25 05:07:42 +0000523 listnode_delete (ospf->areas, area);
paul718e3742002-12-13 20:15:29 +0000524 ospf_area_free (area);
525 }
526}
527
528struct ospf_area *
paul68980082003-03-25 05:07:42 +0000529ospf_area_get (struct ospf *ospf, struct in_addr area_id, int format)
paul718e3742002-12-13 20:15:29 +0000530{
531 struct ospf_area *area;
532
paul68980082003-03-25 05:07:42 +0000533 area = ospf_area_lookup_by_area_id (ospf, area_id);
paul718e3742002-12-13 20:15:29 +0000534 if (!area)
535 {
paul68980082003-03-25 05:07:42 +0000536 area = ospf_area_new (ospf, area_id);
paul718e3742002-12-13 20:15:29 +0000537 area->format = format;
paul68980082003-03-25 05:07:42 +0000538 listnode_add_sort (ospf->areas, area);
539 ospf_check_abr_status (ospf);
paul718e3742002-12-13 20:15:29 +0000540 }
541
542 return area;
543}
544
545struct ospf_area *
paul68980082003-03-25 05:07:42 +0000546ospf_area_lookup_by_area_id (struct ospf *ospf, struct in_addr area_id)
paul718e3742002-12-13 20:15:29 +0000547{
548 struct ospf_area *area;
hasso52dc7ee2004-09-23 19:18:23 +0000549 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000550
paul1eb8ef22005-04-07 07:30:20 +0000551 for (ALL_LIST_ELEMENTS_RO (ospf->areas, node, area))
552 if (IPV4_ADDR_SAME (&area->area_id, &area_id))
553 return area;
paul718e3742002-12-13 20:15:29 +0000554
555 return NULL;
556}
557
558void
559ospf_area_add_if (struct ospf_area *area, struct ospf_interface *oi)
560{
561 listnode_add (area->oiflist, oi);
562}
563
564void
565ospf_area_del_if (struct ospf_area *area, struct ospf_interface *oi)
566{
567 listnode_delete (area->oiflist, oi);
568}
569
570
571/* Config network statement related functions. */
paul4dadc292005-05-06 21:37:42 +0000572static struct ospf_network *
paul718e3742002-12-13 20:15:29 +0000573ospf_network_new (struct in_addr area_id, int format)
574{
575 struct ospf_network *new;
576 new = XCALLOC (MTYPE_OSPF_NETWORK, sizeof (struct ospf_network));
577
578 new->area_id = area_id;
579 new->format = format;
580
581 return new;
582}
583
584void
paul68980082003-03-25 05:07:42 +0000585ospf_network_free (struct ospf *ospf, struct ospf_network *network)
paul718e3742002-12-13 20:15:29 +0000586{
paul68980082003-03-25 05:07:42 +0000587 ospf_area_check_free (ospf, network->area_id);
588 ospf_schedule_abr_task (ospf);
paul718e3742002-12-13 20:15:29 +0000589 XFREE (MTYPE_OSPF_NETWORK, network);
590}
591
592int
593ospf_network_set (struct ospf *ospf, struct prefix_ipv4 *p,
594 struct in_addr area_id)
595{
596 struct ospf_network *network;
597 struct ospf_area *area;
598 struct route_node *rn;
599 struct external_info *ei;
paul147193a2003-04-19 00:31:59 +0000600 int ret = OSPF_AREA_ID_FORMAT_ADDRESS;
paul718e3742002-12-13 20:15:29 +0000601
602 rn = route_node_get (ospf->networks, (struct prefix *)p);
603 if (rn->info)
604 {
605 /* There is already same network statement. */
606 route_unlock_node (rn);
607 return 0;
608 }
609
610 rn->info = network = ospf_network_new (area_id, ret);
paul68980082003-03-25 05:07:42 +0000611 area = ospf_area_get (ospf, area_id, ret);
paul718e3742002-12-13 20:15:29 +0000612
613 /* Run network config now. */
614 ospf_network_run (ospf, (struct prefix *)p, area);
615
616 /* Update connected redistribute. */
617 if (ospf_is_type_redistributed (ZEBRA_ROUTE_CONNECT))
618 if (EXTERNAL_INFO (ZEBRA_ROUTE_CONNECT))
619 for (rn = route_top (EXTERNAL_INFO (ZEBRA_ROUTE_CONNECT));
620 rn; rn = route_next (rn))
621 if ((ei = rn->info) != NULL)
paul68980082003-03-25 05:07:42 +0000622 if (ospf_external_info_find_lsa (ospf, &ei->p))
623 if (!ospf_distribute_check_connected (ospf, ei))
624 ospf_external_lsa_flush (ospf, ei->type, &ei->p,
ajs5339cfd2005-09-19 13:28:05 +0000625 ei->ifindex /*, ei->nexthop */);
paul718e3742002-12-13 20:15:29 +0000626
paul68980082003-03-25 05:07:42 +0000627 ospf_area_check_free (ospf, area_id);
paul718e3742002-12-13 20:15:29 +0000628
629 return 1;
630}
631
632int
633ospf_network_unset (struct ospf *ospf, struct prefix_ipv4 *p,
634 struct in_addr area_id)
635{
636 struct route_node *rn;
637 struct ospf_network *network;
638 struct external_info *ei;
639
640 rn = route_node_lookup (ospf->networks, (struct prefix *)p);
641 if (rn == NULL)
642 return 0;
643
644 network = rn->info;
645 if (!IPV4_ADDR_SAME (&area_id, &network->area_id))
646 return 0;
647
paul68980082003-03-25 05:07:42 +0000648 ospf_network_free (ospf, rn->info);
paul718e3742002-12-13 20:15:29 +0000649 rn->info = NULL;
650 route_unlock_node (rn);
651
paul68980082003-03-25 05:07:42 +0000652 ospf_if_update (ospf);
paul718e3742002-12-13 20:15:29 +0000653
654 /* Update connected redistribute. */
655 if (ospf_is_type_redistributed (ZEBRA_ROUTE_CONNECT))
656 if (EXTERNAL_INFO (ZEBRA_ROUTE_CONNECT))
657 for (rn = route_top (EXTERNAL_INFO (ZEBRA_ROUTE_CONNECT));
658 rn; rn = route_next (rn))
659 if ((ei = rn->info) != NULL)
paul68980082003-03-25 05:07:42 +0000660 if (!ospf_external_info_find_lsa (ospf, &ei->p))
661 if (ospf_distribute_check_connected (ospf, ei))
662 ospf_external_lsa_originate (ospf, ei);
paul718e3742002-12-13 20:15:29 +0000663
664 return 1;
665}
666
paul570f7592003-01-25 06:47:41 +0000667/* Check whether interface matches given network
668 * returns: 1, true. 0, false
669 */
670int
671ospf_network_match_iface(struct connected *co, struct prefix *net)
672{
673 /* Behaviour to match both Cisco where:
674 * iface address lies within network specified -> ospf
675 * and zebra 0.9[2ish-3]:
676 * PtP special case: network specified == iface peer addr -> ospf
677 */
gdt8f40e892003-12-05 14:01:43 +0000678
paulf3ae74c2004-11-04 20:35:31 +0000679 /* For PtP, match if peer address matches network address exactly.
680 * This can be addr/32 or addr/p for p < 32, but the addr must match
681 * exactly; this is not a test for falling within the prefix. This
gdt8f40e892003-12-05 14:01:43 +0000682 * test is solely for compatibility with zebra.
gdt8f40e892003-12-05 14:01:43 +0000683 */
paulf3ae74c2004-11-04 20:35:31 +0000684 if (if_is_pointopoint (co->ifp) && co->destination &&
685 IPV4_ADDR_SAME ( &(co->destination->u.prefix4), &(net->u.prefix4)))
686 return 1;
687
688#if 0
689 /* Decline to accept PtP if dst address does not match the
690 * prefix. (ifdefed out because this is a workaround, not the
691 * desired behavior.) */
692 if (if_is_pointopoint (co->ifp) &&
693 ! prefix_match (net, co->destination))
694 return 0;
695#endif
696
697 /* If the address is within the prefix, accept. Note that this
698 * applies to PtP as well as other types.
699 */
700 if (prefix_match (net, co->address))
701 return 1;
702
703 return 0; /* no match */
paul570f7592003-01-25 06:47:41 +0000704}
705
paul718e3742002-12-13 20:15:29 +0000706void
707ospf_network_run (struct ospf *ospf, struct prefix *p, struct ospf_area *area)
708{
709 struct interface *ifp;
paul1eb8ef22005-04-07 07:30:20 +0000710 struct connected *co;
hasso52dc7ee2004-09-23 19:18:23 +0000711 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000712
713 /* Schedule Router ID Update. */
714 if (ospf->router_id_static.s_addr == 0)
715 if (ospf->t_router_id_update == NULL)
716 {
paul020709f2003-04-04 02:44:16 +0000717 OSPF_TIMER_ON (ospf->t_router_id_update, ospf_router_id_update_timer,
718 OSPF_ROUTER_ID_UPDATE_DELAY);
paul718e3742002-12-13 20:15:29 +0000719 }
720
721 /* Get target interface. */
paul1eb8ef22005-04-07 07:30:20 +0000722 for (ALL_LIST_ELEMENTS_RO (om->iflist, node, ifp))
paul718e3742002-12-13 20:15:29 +0000723 {
paul1eb8ef22005-04-07 07:30:20 +0000724 struct listnode *cnode;
paul718e3742002-12-13 20:15:29 +0000725
paul718e3742002-12-13 20:15:29 +0000726 if (memcmp (ifp->name, "VLINK", 5) == 0)
727 continue;
728
729 /* if interface prefix is match specified prefix,
730 then create socket and join multicast group. */
paul1eb8ef22005-04-07 07:30:20 +0000731 for (ALL_LIST_ELEMENTS_RO (ifp->connected, cnode, co))
paul718e3742002-12-13 20:15:29 +0000732 {
paul718e3742002-12-13 20:15:29 +0000733 struct prefix *addr;
paul800dc102003-03-28 01:51:40 +0000734
paule7b050c2003-04-07 06:38:02 +0000735 if (CHECK_FLAG(co->flags,ZEBRA_IFA_SECONDARY))
736 continue;
paul718e3742002-12-13 20:15:29 +0000737
hasso3fb9cd62004-10-19 19:44:43 +0000738 if (CONNECTED_POINTOPOINT_HOST(co))
paul718e3742002-12-13 20:15:29 +0000739 addr = co->destination;
740 else
741 addr = co->address;
742
paulcb3f37d2003-02-18 23:26:37 +0000743 if (p->family == co->address->family
paul68980082003-03-25 05:07:42 +0000744 && ! ospf_if_is_configured (ospf, &(addr->u.prefix4))
paulcb3f37d2003-02-18 23:26:37 +0000745 && ospf_network_match_iface(co,p))
paul570f7592003-01-25 06:47:41 +0000746 {
paul1eb8ef22005-04-07 07:30:20 +0000747 struct ospf_interface *oi;
paul718e3742002-12-13 20:15:29 +0000748
paul68980082003-03-25 05:07:42 +0000749 oi = ospf_if_new (ospf, ifp, co->address);
paul718e3742002-12-13 20:15:29 +0000750 oi->connected = co;
751
752 oi->nbr_self->address = *oi->address;
753
paul718e3742002-12-13 20:15:29 +0000754 oi->area = area;
755
756 oi->params = ospf_lookup_if_params (ifp, oi->address->u.prefix4);
757 oi->output_cost = ospf_if_get_output_cost (oi);
758
759 if (area->external_routing != OSPF_AREA_DEFAULT)
760 UNSET_FLAG (oi->nbr_self->options, OSPF_OPTION_E);
761 oi->nbr_self->priority = OSPF_IF_PARAM (oi, priority);
762
763 /* Add pseudo neighbor. */
764 ospf_nbr_add_self (oi);
765
766 /* Make sure pseudo neighbor's router_id. */
paul68980082003-03-25 05:07:42 +0000767 oi->nbr_self->router_id = ospf->router_id;
paul718e3742002-12-13 20:15:29 +0000768 oi->nbr_self->src = oi->address->u.prefix4;
769
770 /* Relate ospf interface to ospf instance. */
paul68980082003-03-25 05:07:42 +0000771 oi->ospf = ospf;
paul718e3742002-12-13 20:15:29 +0000772
773 /* update network type as interface flag */
774 /* If network type is specified previously,
775 skip network type setting. */
776 oi->type = IF_DEF_PARAMS (ifp)->type;
777
778 /* Set area flag. */
779 switch (area->external_routing)
780 {
781 case OSPF_AREA_DEFAULT:
782 SET_FLAG (oi->nbr_self->options, OSPF_OPTION_E);
783 break;
784 case OSPF_AREA_STUB:
785 UNSET_FLAG (oi->nbr_self->options, OSPF_OPTION_E);
786 break;
paul718e3742002-12-13 20:15:29 +0000787 case OSPF_AREA_NSSA:
788 UNSET_FLAG (oi->nbr_self->options, OSPF_OPTION_E);
789 SET_FLAG (oi->nbr_self->options, OSPF_OPTION_NP);
790 break;
paul718e3742002-12-13 20:15:29 +0000791 }
792
793 ospf_area_add_if (oi->area, oi);
794
paul2e3b2e42002-12-13 21:03:13 +0000795 if (if_is_operative (ifp))
paul718e3742002-12-13 20:15:29 +0000796 ospf_if_up (oi);
797
798 break;
799 }
800 }
801 }
802}
803
804void
805ospf_ls_upd_queue_empty (struct ospf_interface *oi)
806{
807 struct route_node *rn;
paul1eb8ef22005-04-07 07:30:20 +0000808 struct listnode *node, *nnode;
hasso52dc7ee2004-09-23 19:18:23 +0000809 struct list *lst;
paul718e3742002-12-13 20:15:29 +0000810 struct ospf_lsa *lsa;
811
812 /* empty ls update queue */
813 for (rn = route_top (oi->ls_upd_queue); rn;
814 rn = route_next (rn))
hasso52dc7ee2004-09-23 19:18:23 +0000815 if ((lst = (struct list *) rn->info))
paul718e3742002-12-13 20:15:29 +0000816 {
paul1eb8ef22005-04-07 07:30:20 +0000817 for (ALL_LIST_ELEMENTS (lst, node, nnode, lsa))
818 ospf_lsa_unlock (lsa);
paul718e3742002-12-13 20:15:29 +0000819 list_free (lst);
820 rn->info = NULL;
821 }
822
823 /* remove update event */
824 if (oi->t_ls_upd_event)
825 {
826 thread_cancel (oi->t_ls_upd_event);
827 oi->t_ls_upd_event = NULL;
828 }
829}
830
831void
paul68980082003-03-25 05:07:42 +0000832ospf_if_update (struct ospf *ospf)
paul718e3742002-12-13 20:15:29 +0000833{
834 struct route_node *rn;
paul1eb8ef22005-04-07 07:30:20 +0000835 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000836 struct ospf_network *network;
837 struct ospf_area *area;
paul1eb8ef22005-04-07 07:30:20 +0000838 struct ospf_interface *oi;
paul718e3742002-12-13 20:15:29 +0000839
paul68980082003-03-25 05:07:42 +0000840 if (ospf != NULL)
paul718e3742002-12-13 20:15:29 +0000841 {
842 /* Update Router ID scheduled. */
paul68980082003-03-25 05:07:42 +0000843 if (ospf->router_id_static.s_addr == 0)
844 if (ospf->t_router_id_update == NULL)
paul718e3742002-12-13 20:15:29 +0000845 {
paul020709f2003-04-04 02:44:16 +0000846 OSPF_TIMER_ON (ospf->t_router_id_update,
847 ospf_router_id_update_timer,
848 OSPF_ROUTER_ID_UPDATE_DELAY);
paul718e3742002-12-13 20:15:29 +0000849 }
850
851 /* Find interfaces that not configured already. */
paul1eb8ef22005-04-07 07:30:20 +0000852 for (ALL_LIST_ELEMENTS (ospf->oiflist, node, nnode, oi))
paul718e3742002-12-13 20:15:29 +0000853 {
854 int found = 0;
paul718e3742002-12-13 20:15:29 +0000855 struct connected *co = oi->connected;
856
paul718e3742002-12-13 20:15:29 +0000857 if (oi->type == OSPF_IFTYPE_VIRTUALLINK)
858 continue;
859
paul68980082003-03-25 05:07:42 +0000860 for (rn = route_top (ospf->networks); rn; rn = route_next (rn))
paul718e3742002-12-13 20:15:29 +0000861 {
862 if (rn->info == NULL)
863 continue;
864
paul570f7592003-01-25 06:47:41 +0000865 if (ospf_network_match_iface(co,&rn->p))
paul718e3742002-12-13 20:15:29 +0000866 {
867 found = 1;
868 route_unlock_node (rn);
869 break;
870 }
871 }
872
873 if (found == 0)
874 ospf_if_free (oi);
875 }
876
877 /* Run each interface. */
paul68980082003-03-25 05:07:42 +0000878 for (rn = route_top (ospf->networks); rn; rn = route_next (rn))
paul718e3742002-12-13 20:15:29 +0000879 if (rn->info != NULL)
880 {
881 network = (struct ospf_network *) rn->info;
paul68980082003-03-25 05:07:42 +0000882 area = ospf_area_get (ospf, network->area_id, network->format);
883 ospf_network_run (ospf, &rn->p, area);
paul718e3742002-12-13 20:15:29 +0000884 }
885 }
886}
887
888void
paul68980082003-03-25 05:07:42 +0000889ospf_remove_vls_through_area (struct ospf *ospf, struct ospf_area *area)
paul718e3742002-12-13 20:15:29 +0000890{
paul1eb8ef22005-04-07 07:30:20 +0000891 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000892 struct ospf_vl_data *vl_data;
893
paul1eb8ef22005-04-07 07:30:20 +0000894 for (ALL_LIST_ELEMENTS (ospf->vlinks, node, nnode, vl_data))
895 if (IPV4_ADDR_SAME (&vl_data->vl_area_id, &area->area_id))
896 ospf_vl_delete (ospf, vl_data);
paul718e3742002-12-13 20:15:29 +0000897}
898
899
900struct message ospf_area_type_msg[] =
901{
902 { OSPF_AREA_DEFAULT, "Default" },
903 { OSPF_AREA_STUB, "Stub" },
904 { OSPF_AREA_NSSA, "NSSA" },
905};
906int ospf_area_type_msg_max = OSPF_AREA_TYPE_MAX;
907
paul4dadc292005-05-06 21:37:42 +0000908static void
paul718e3742002-12-13 20:15:29 +0000909ospf_area_type_set (struct ospf_area *area, int type)
910{
hasso52dc7ee2004-09-23 19:18:23 +0000911 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000912 struct ospf_interface *oi;
913
914 if (area->external_routing == type)
915 {
916 if (IS_DEBUG_OSPF_EVENT)
ajs9b0e25c2004-12-08 19:06:51 +0000917 zlog_debug ("Area[%s]: Types are the same, ignored.",
paul718e3742002-12-13 20:15:29 +0000918 inet_ntoa (area->area_id));
919 return;
920 }
921
922 area->external_routing = type;
923
924 if (IS_DEBUG_OSPF_EVENT)
ajs9b0e25c2004-12-08 19:06:51 +0000925 zlog_debug ("Area[%s]: Configured as %s", inet_ntoa (area->area_id),
paul718e3742002-12-13 20:15:29 +0000926 LOOKUP (ospf_area_type_msg, type));
927
928 switch (area->external_routing)
929 {
930 case OSPF_AREA_DEFAULT:
paul1eb8ef22005-04-07 07:30:20 +0000931 for (ALL_LIST_ELEMENTS_RO (area->oiflist, node, oi))
932 if (oi->nbr_self != NULL)
933 {
934 UNSET_FLAG (oi->nbr_self->options, OSPF_OPTION_NP);
935 SET_FLAG (oi->nbr_self->options, OSPF_OPTION_E);
936 }
paul718e3742002-12-13 20:15:29 +0000937 break;
938 case OSPF_AREA_STUB:
paul1eb8ef22005-04-07 07:30:20 +0000939 for (ALL_LIST_ELEMENTS_RO (area->oiflist, node, oi))
940 if (oi->nbr_self != NULL)
941 {
942 if (IS_DEBUG_OSPF_EVENT)
943 zlog_debug ("setting options on %s accordingly", IF_NAME (oi));
944 UNSET_FLAG (oi->nbr_self->options, OSPF_OPTION_NP);
945 UNSET_FLAG (oi->nbr_self->options, OSPF_OPTION_E);
946 if (IS_DEBUG_OSPF_EVENT)
947 zlog_debug ("options set on %s: %x",
948 IF_NAME (oi), OPTIONS (oi));
949 }
paul718e3742002-12-13 20:15:29 +0000950 break;
951 case OSPF_AREA_NSSA:
paul1eb8ef22005-04-07 07:30:20 +0000952 for (ALL_LIST_ELEMENTS_RO (area->oiflist, node, oi))
953 if (oi->nbr_self != NULL)
954 {
955 zlog_debug ("setting nssa options on %s accordingly", IF_NAME (oi));
956 UNSET_FLAG (oi->nbr_self->options, OSPF_OPTION_E);
957 SET_FLAG (oi->nbr_self->options, OSPF_OPTION_NP);
958 zlog_debug ("options set on %s: %x", IF_NAME (oi), OPTIONS (oi));
959 }
paul718e3742002-12-13 20:15:29 +0000960 break;
961 default:
962 break;
963 }
964
965 ospf_router_lsa_timer_add (area);
paul68980082003-03-25 05:07:42 +0000966 ospf_schedule_abr_task (area->ospf);
paul718e3742002-12-13 20:15:29 +0000967}
968
969int
paul68980082003-03-25 05:07:42 +0000970ospf_area_shortcut_set (struct ospf *ospf, struct ospf_area *area, int mode)
paul718e3742002-12-13 20:15:29 +0000971{
972 if (area->shortcut_configured == mode)
973 return 0;
974
975 area->shortcut_configured = mode;
976 ospf_router_lsa_timer_add (area);
paul68980082003-03-25 05:07:42 +0000977 ospf_schedule_abr_task (ospf);
paul718e3742002-12-13 20:15:29 +0000978
paul68980082003-03-25 05:07:42 +0000979 ospf_area_check_free (ospf, area->area_id);
paul718e3742002-12-13 20:15:29 +0000980
981 return 1;
982}
983
984int
paul68980082003-03-25 05:07:42 +0000985ospf_area_shortcut_unset (struct ospf *ospf, struct ospf_area *area)
paul718e3742002-12-13 20:15:29 +0000986{
987 area->shortcut_configured = OSPF_SHORTCUT_DEFAULT;
988 ospf_router_lsa_timer_add (area);
paul68980082003-03-25 05:07:42 +0000989 ospf_area_check_free (ospf, area->area_id);
990 ospf_schedule_abr_task (ospf);
paul718e3742002-12-13 20:15:29 +0000991
992 return 1;
993}
994
paul4dadc292005-05-06 21:37:42 +0000995static int
paul718e3742002-12-13 20:15:29 +0000996ospf_area_vlink_count (struct ospf *ospf, struct ospf_area *area)
997{
998 struct ospf_vl_data *vl;
hasso52dc7ee2004-09-23 19:18:23 +0000999 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00001000 int count = 0;
1001
paul1eb8ef22005-04-07 07:30:20 +00001002 for (ALL_LIST_ELEMENTS_RO (ospf->vlinks, node, vl))
1003 if (IPV4_ADDR_SAME (&vl->vl_area_id, &area->area_id))
1004 count++;
paul718e3742002-12-13 20:15:29 +00001005
1006 return count;
1007}
1008
1009int
1010ospf_area_stub_set (struct ospf *ospf, struct in_addr area_id)
1011{
1012 struct ospf_area *area;
paul147193a2003-04-19 00:31:59 +00001013 int format = OSPF_AREA_ID_FORMAT_ADDRESS;
paul718e3742002-12-13 20:15:29 +00001014
paul68980082003-03-25 05:07:42 +00001015 area = ospf_area_get (ospf, area_id, format);
paul718e3742002-12-13 20:15:29 +00001016 if (ospf_area_vlink_count (ospf, area))
1017 return 0;
1018
1019 if (area->external_routing != OSPF_AREA_STUB)
1020 ospf_area_type_set (area, OSPF_AREA_STUB);
1021
1022 return 1;
1023}
1024
1025int
1026ospf_area_stub_unset (struct ospf *ospf, struct in_addr area_id)
1027{
1028 struct ospf_area *area;
1029
paul68980082003-03-25 05:07:42 +00001030 area = ospf_area_lookup_by_area_id (ospf, area_id);
paul718e3742002-12-13 20:15:29 +00001031 if (area == NULL)
1032 return 1;
1033
1034 if (area->external_routing == OSPF_AREA_STUB)
1035 ospf_area_type_set (area, OSPF_AREA_DEFAULT);
1036
paul68980082003-03-25 05:07:42 +00001037 ospf_area_check_free (ospf, area_id);
paul718e3742002-12-13 20:15:29 +00001038
1039 return 1;
1040}
1041
1042int
1043ospf_area_no_summary_set (struct ospf *ospf, struct in_addr area_id)
1044{
1045 struct ospf_area *area;
paul147193a2003-04-19 00:31:59 +00001046 int format = OSPF_AREA_ID_FORMAT_ADDRESS;
paul718e3742002-12-13 20:15:29 +00001047
paul68980082003-03-25 05:07:42 +00001048 area = ospf_area_get (ospf, area_id, format);
paul718e3742002-12-13 20:15:29 +00001049 area->no_summary = 1;
1050
1051 return 1;
1052}
1053
1054int
1055ospf_area_no_summary_unset (struct ospf *ospf, struct in_addr area_id)
1056{
1057 struct ospf_area *area;
1058
paul68980082003-03-25 05:07:42 +00001059 area = ospf_area_lookup_by_area_id (ospf, area_id);
paul718e3742002-12-13 20:15:29 +00001060 if (area == NULL)
1061 return 0;
1062
1063 area->no_summary = 0;
paul68980082003-03-25 05:07:42 +00001064 ospf_area_check_free (ospf, area_id);
paul718e3742002-12-13 20:15:29 +00001065
1066 return 1;
1067}
1068
1069int
1070ospf_area_nssa_set (struct ospf *ospf, struct in_addr area_id)
1071{
1072 struct ospf_area *area;
paul147193a2003-04-19 00:31:59 +00001073 int format = OSPF_AREA_ID_FORMAT_ADDRESS;
paul718e3742002-12-13 20:15:29 +00001074
paul68980082003-03-25 05:07:42 +00001075 area = ospf_area_get (ospf, area_id, format);
paul718e3742002-12-13 20:15:29 +00001076 if (ospf_area_vlink_count (ospf, area))
1077 return 0;
1078
1079 if (area->external_routing != OSPF_AREA_NSSA)
1080 {
1081 ospf_area_type_set (area, OSPF_AREA_NSSA);
1082 ospf->anyNSSA++;
1083 }
1084
paul084c7842003-06-22 08:35:18 +00001085 /* set NSSA area defaults */
1086 area->no_summary = 0;
1087 area->NSSATranslatorRole = OSPF_NSSA_ROLE_CANDIDATE;
pauld4a53d52003-07-12 21:30:57 +00001088 area->NSSATranslatorState = OSPF_NSSA_TRANSLATE_DISABLED;
paul084c7842003-06-22 08:35:18 +00001089 area->NSSATranslatorStabilityInterval = OSPF_NSSA_TRANS_STABLE_DEFAULT;
1090
paul718e3742002-12-13 20:15:29 +00001091 return 1;
1092}
1093
1094int
1095ospf_area_nssa_unset (struct ospf *ospf, struct in_addr area_id)
1096{
1097 struct ospf_area *area;
1098
paul68980082003-03-25 05:07:42 +00001099 area = ospf_area_lookup_by_area_id (ospf, area_id);
paul718e3742002-12-13 20:15:29 +00001100 if (area == NULL)
1101 return 0;
1102
1103 if (area->external_routing == OSPF_AREA_NSSA)
1104 {
1105 ospf->anyNSSA--;
1106 ospf_area_type_set (area, OSPF_AREA_DEFAULT);
1107 }
1108
paul68980082003-03-25 05:07:42 +00001109 ospf_area_check_free (ospf, area_id);
paul718e3742002-12-13 20:15:29 +00001110
1111 return 1;
1112}
1113
1114int
1115ospf_area_nssa_translator_role_set (struct ospf *ospf, struct in_addr area_id,
1116 int role)
1117{
1118 struct ospf_area *area;
1119
paul68980082003-03-25 05:07:42 +00001120 area = ospf_area_lookup_by_area_id (ospf, area_id);
paul718e3742002-12-13 20:15:29 +00001121 if (area == NULL)
1122 return 0;
1123
paul084c7842003-06-22 08:35:18 +00001124 area->NSSATranslatorRole = role;
paul718e3742002-12-13 20:15:29 +00001125
1126 return 1;
1127}
1128
paul4dadc292005-05-06 21:37:42 +00001129/* XXX: unused? Leave for symmetry? */
1130static int
paul718e3742002-12-13 20:15:29 +00001131ospf_area_nssa_translator_role_unset (struct ospf *ospf,
1132 struct in_addr area_id)
1133{
1134 struct ospf_area *area;
1135
paul68980082003-03-25 05:07:42 +00001136 area = ospf_area_lookup_by_area_id (ospf, area_id);
paul718e3742002-12-13 20:15:29 +00001137 if (area == NULL)
1138 return 0;
1139
paul084c7842003-06-22 08:35:18 +00001140 area->NSSATranslatorRole = OSPF_NSSA_ROLE_CANDIDATE;
paul718e3742002-12-13 20:15:29 +00001141
paul68980082003-03-25 05:07:42 +00001142 ospf_area_check_free (ospf, area_id);
paul718e3742002-12-13 20:15:29 +00001143
1144 return 1;
1145}
1146
1147int
paul68980082003-03-25 05:07:42 +00001148ospf_area_export_list_set (struct ospf *ospf,
paul6c835672004-10-11 11:00:30 +00001149 struct ospf_area *area, const char *list_name)
paul718e3742002-12-13 20:15:29 +00001150{
1151 struct access_list *list;
1152 list = access_list_lookup (AFI_IP, list_name);
1153
1154 EXPORT_LIST (area) = list;
1155
1156 if (EXPORT_NAME (area))
1157 free (EXPORT_NAME (area));
1158
1159 EXPORT_NAME (area) = strdup (list_name);
paul68980082003-03-25 05:07:42 +00001160 ospf_schedule_abr_task (ospf);
paul718e3742002-12-13 20:15:29 +00001161
1162 return 1;
1163}
1164
1165int
paul68980082003-03-25 05:07:42 +00001166ospf_area_export_list_unset (struct ospf *ospf, struct ospf_area * area)
paul718e3742002-12-13 20:15:29 +00001167{
1168
1169 EXPORT_LIST (area) = 0;
1170
1171 if (EXPORT_NAME (area))
1172 free (EXPORT_NAME (area));
1173
1174 EXPORT_NAME (area) = NULL;
1175
paul68980082003-03-25 05:07:42 +00001176 ospf_area_check_free (ospf, area->area_id);
paul718e3742002-12-13 20:15:29 +00001177
paul68980082003-03-25 05:07:42 +00001178 ospf_schedule_abr_task (ospf);
paul718e3742002-12-13 20:15:29 +00001179
1180 return 1;
1181}
1182
1183int
paul6c835672004-10-11 11:00:30 +00001184ospf_area_import_list_set (struct ospf *ospf, struct ospf_area *area,
1185 const char *name)
paul718e3742002-12-13 20:15:29 +00001186{
1187 struct access_list *list;
1188 list = access_list_lookup (AFI_IP, name);
1189
1190 IMPORT_LIST (area) = list;
1191
1192 if (IMPORT_NAME (area))
1193 free (IMPORT_NAME (area));
1194
1195 IMPORT_NAME (area) = strdup (name);
paul68980082003-03-25 05:07:42 +00001196 ospf_schedule_abr_task (ospf);
paul718e3742002-12-13 20:15:29 +00001197
1198 return 1;
1199}
1200
1201int
paul68980082003-03-25 05:07:42 +00001202ospf_area_import_list_unset (struct ospf *ospf, struct ospf_area * area)
paul718e3742002-12-13 20:15:29 +00001203{
1204 IMPORT_LIST (area) = 0;
1205
1206 if (IMPORT_NAME (area))
1207 free (IMPORT_NAME (area));
1208
1209 IMPORT_NAME (area) = NULL;
paul68980082003-03-25 05:07:42 +00001210 ospf_area_check_free (ospf, area->area_id);
paul718e3742002-12-13 20:15:29 +00001211
paul68980082003-03-25 05:07:42 +00001212 ospf_schedule_abr_task (ospf);
paul718e3742002-12-13 20:15:29 +00001213
1214 return 1;
1215}
1216
1217int
paul718e3742002-12-13 20:15:29 +00001218ospf_timers_refresh_set (struct ospf *ospf, int interval)
1219{
1220 int time_left;
1221
1222 if (ospf->lsa_refresh_interval == interval)
1223 return 1;
1224
1225 time_left = ospf->lsa_refresh_interval -
1226 (time (NULL) - ospf->lsa_refresher_started);
1227
1228 if (time_left > interval)
1229 {
1230 OSPF_TIMER_OFF (ospf->t_lsa_refresher);
1231 ospf->t_lsa_refresher =
1232 thread_add_timer (master, ospf_lsa_refresh_walker, ospf, interval);
1233 }
1234 ospf->lsa_refresh_interval = interval;
1235
1236 return 1;
1237}
1238
1239int
1240ospf_timers_refresh_unset (struct ospf *ospf)
1241{
1242 int time_left;
1243
1244 time_left = ospf->lsa_refresh_interval -
1245 (time (NULL) - ospf->lsa_refresher_started);
1246
1247 if (time_left > OSPF_LSA_REFRESH_INTERVAL_DEFAULT)
1248 {
1249 OSPF_TIMER_OFF (ospf->t_lsa_refresher);
1250 ospf->t_lsa_refresher =
1251 thread_add_timer (master, ospf_lsa_refresh_walker, ospf,
1252 OSPF_LSA_REFRESH_INTERVAL_DEFAULT);
1253 }
1254
1255 ospf->lsa_refresh_interval = OSPF_LSA_REFRESH_INTERVAL_DEFAULT;
1256
1257 return 1;
1258}
1259
1260
paul4dadc292005-05-06 21:37:42 +00001261static struct ospf_nbr_nbma *
1262ospf_nbr_nbma_new (void)
paul718e3742002-12-13 20:15:29 +00001263{
1264 struct ospf_nbr_nbma *nbr_nbma;
1265
1266 nbr_nbma = XMALLOC (MTYPE_OSPF_NEIGHBOR_STATIC,
1267 sizeof (struct ospf_nbr_nbma));
1268 memset (nbr_nbma, 0, sizeof (struct ospf_nbr_nbma));
1269
1270 nbr_nbma->priority = OSPF_NEIGHBOR_PRIORITY_DEFAULT;
1271 nbr_nbma->v_poll = OSPF_POLL_INTERVAL_DEFAULT;
1272
1273 return nbr_nbma;
1274}
1275
paul4dadc292005-05-06 21:37:42 +00001276static void
paul718e3742002-12-13 20:15:29 +00001277ospf_nbr_nbma_free (struct ospf_nbr_nbma *nbr_nbma)
1278{
1279 XFREE (MTYPE_OSPF_NEIGHBOR_STATIC, nbr_nbma);
1280}
1281
paul4dadc292005-05-06 21:37:42 +00001282static void
paul718e3742002-12-13 20:15:29 +00001283ospf_nbr_nbma_delete (struct ospf *ospf, struct ospf_nbr_nbma *nbr_nbma)
1284{
1285 struct route_node *rn;
1286 struct prefix_ipv4 p;
1287
1288 p.family = AF_INET;
1289 p.prefix = nbr_nbma->addr;
1290 p.prefixlen = IPV4_MAX_BITLEN;
1291
1292 rn = route_node_lookup (ospf->nbr_nbma, (struct prefix *)&p);
1293 if (rn)
1294 {
1295 ospf_nbr_nbma_free (rn->info);
1296 rn->info = NULL;
1297 route_unlock_node (rn);
1298 route_unlock_node (rn);
1299 }
1300}
1301
paul4dadc292005-05-06 21:37:42 +00001302static void
paul718e3742002-12-13 20:15:29 +00001303ospf_nbr_nbma_down (struct ospf_nbr_nbma *nbr_nbma)
1304{
1305 OSPF_TIMER_OFF (nbr_nbma->t_poll);
1306
1307 if (nbr_nbma->nbr)
1308 {
1309 nbr_nbma->nbr->nbr_nbma = NULL;
1310 OSPF_NSM_EVENT_EXECUTE (nbr_nbma->nbr, NSM_KillNbr);
1311 }
1312
1313 if (nbr_nbma->oi)
1314 listnode_delete (nbr_nbma->oi->nbr_nbma, nbr_nbma);
1315}
1316
paul4dadc292005-05-06 21:37:42 +00001317static void
paul718e3742002-12-13 20:15:29 +00001318ospf_nbr_nbma_add (struct ospf_nbr_nbma *nbr_nbma,
1319 struct ospf_interface *oi)
1320{
1321 struct ospf_neighbor *nbr;
1322 struct route_node *rn;
1323 struct prefix p;
1324
1325 if (oi->type != OSPF_IFTYPE_NBMA)
1326 return;
1327
1328 if (nbr_nbma->nbr != NULL)
1329 return;
1330
1331 if (IPV4_ADDR_SAME (&oi->nbr_self->address.u.prefix4, &nbr_nbma->addr))
1332 return;
1333
1334 nbr_nbma->oi = oi;
1335 listnode_add (oi->nbr_nbma, nbr_nbma);
1336
1337 /* Get neighbor information from table. */
1338 p.family = AF_INET;
1339 p.prefixlen = IPV4_MAX_BITLEN;
1340 p.u.prefix4 = nbr_nbma->addr;
1341
1342 rn = route_node_get (oi->nbrs, (struct prefix *)&p);
1343 if (rn->info)
1344 {
1345 nbr = rn->info;
1346 nbr->nbr_nbma = nbr_nbma;
1347 nbr_nbma->nbr = nbr;
1348
1349 route_unlock_node (rn);
1350 }
1351 else
1352 {
1353 nbr = rn->info = ospf_nbr_new (oi);
1354 nbr->state = NSM_Down;
1355 nbr->src = nbr_nbma->addr;
1356 nbr->nbr_nbma = nbr_nbma;
1357 nbr->priority = nbr_nbma->priority;
1358 nbr->address = p;
1359
1360 nbr_nbma->nbr = nbr;
1361
1362 OSPF_NSM_EVENT_EXECUTE (nbr, NSM_Start);
1363 }
1364}
1365
1366void
paul68980082003-03-25 05:07:42 +00001367ospf_nbr_nbma_if_update (struct ospf *ospf, struct ospf_interface *oi)
paul718e3742002-12-13 20:15:29 +00001368{
1369 struct ospf_nbr_nbma *nbr_nbma;
1370 struct route_node *rn;
1371 struct prefix_ipv4 p;
1372
1373 if (oi->type != OSPF_IFTYPE_NBMA)
1374 return;
1375
paul68980082003-03-25 05:07:42 +00001376 for (rn = route_top (ospf->nbr_nbma); rn; rn = route_next (rn))
paul718e3742002-12-13 20:15:29 +00001377 if ((nbr_nbma = rn->info))
1378 if (nbr_nbma->oi == NULL && nbr_nbma->nbr == NULL)
1379 {
1380 p.family = AF_INET;
1381 p.prefix = nbr_nbma->addr;
1382 p.prefixlen = IPV4_MAX_BITLEN;
1383
1384 if (prefix_match (oi->address, (struct prefix *)&p))
1385 ospf_nbr_nbma_add (nbr_nbma, oi);
1386 }
1387}
1388
1389struct ospf_nbr_nbma *
1390ospf_nbr_nbma_lookup (struct ospf *ospf, struct in_addr nbr_addr)
1391{
1392 struct route_node *rn;
1393 struct prefix_ipv4 p;
1394
1395 p.family = AF_INET;
1396 p.prefix = nbr_addr;
1397 p.prefixlen = IPV4_MAX_BITLEN;
1398
1399 rn = route_node_lookup (ospf->nbr_nbma, (struct prefix *)&p);
1400 if (rn)
1401 {
1402 route_unlock_node (rn);
1403 return rn->info;
1404 }
1405 return NULL;
1406}
1407
1408struct ospf_nbr_nbma *
paul68980082003-03-25 05:07:42 +00001409ospf_nbr_nbma_lookup_next (struct ospf *ospf, struct in_addr *addr, int first)
paul718e3742002-12-13 20:15:29 +00001410{
1411#if 0
1412 struct ospf_nbr_nbma *nbr_nbma;
hasso52dc7ee2004-09-23 19:18:23 +00001413 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00001414#endif
1415
paul68980082003-03-25 05:07:42 +00001416 if (ospf == NULL)
paul718e3742002-12-13 20:15:29 +00001417 return NULL;
1418
1419#if 0
paul1eb8ef22005-04-07 07:30:20 +00001420 for (ALL_LIST_ELEMENTS_RO (ospf->nbr_nbma, node, nbr_nbma))
paul718e3742002-12-13 20:15:29 +00001421 {
paul718e3742002-12-13 20:15:29 +00001422 if (first)
1423 {
1424 *addr = nbr_nbma->addr;
1425 return nbr_nbma;
1426 }
1427 else if (ntohl (nbr_nbma->addr.s_addr) > ntohl (addr->s_addr))
1428 {
1429 *addr = nbr_nbma->addr;
1430 return nbr_nbma;
1431 }
1432 }
1433#endif
1434 return NULL;
1435}
1436
1437int
1438ospf_nbr_nbma_set (struct ospf *ospf, struct in_addr nbr_addr)
1439{
1440 struct ospf_nbr_nbma *nbr_nbma;
1441 struct ospf_interface *oi;
1442 struct prefix_ipv4 p;
1443 struct route_node *rn;
hasso52dc7ee2004-09-23 19:18:23 +00001444 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00001445
1446 nbr_nbma = ospf_nbr_nbma_lookup (ospf, nbr_addr);
1447 if (nbr_nbma)
1448 return 0;
1449
1450 nbr_nbma = ospf_nbr_nbma_new ();
1451 nbr_nbma->addr = nbr_addr;
1452
1453 p.family = AF_INET;
1454 p.prefix = nbr_addr;
1455 p.prefixlen = IPV4_MAX_BITLEN;
1456
1457 rn = route_node_get (ospf->nbr_nbma, (struct prefix *)&p);
1458 rn->info = nbr_nbma;
1459
paul1eb8ef22005-04-07 07:30:20 +00001460 for (ALL_LIST_ELEMENTS_RO (ospf->oiflist, node, oi))
paul718e3742002-12-13 20:15:29 +00001461 {
paul718e3742002-12-13 20:15:29 +00001462 if (oi->type == OSPF_IFTYPE_NBMA)
1463 if (prefix_match (oi->address, (struct prefix *)&p))
1464 {
1465 ospf_nbr_nbma_add (nbr_nbma, oi);
1466 break;
1467 }
1468 }
1469
1470 return 1;
1471}
1472
1473int
1474ospf_nbr_nbma_unset (struct ospf *ospf, struct in_addr nbr_addr)
1475{
1476 struct ospf_nbr_nbma *nbr_nbma;
1477
1478 nbr_nbma = ospf_nbr_nbma_lookup (ospf, nbr_addr);
1479 if (nbr_nbma == NULL)
1480 return 0;
1481
1482 ospf_nbr_nbma_down (nbr_nbma);
1483 ospf_nbr_nbma_delete (ospf, nbr_nbma);
1484
1485 return 1;
1486}
1487
1488int
1489ospf_nbr_nbma_priority_set (struct ospf *ospf, struct in_addr nbr_addr,
1490 u_char priority)
1491{
1492 struct ospf_nbr_nbma *nbr_nbma;
1493
1494 nbr_nbma = ospf_nbr_nbma_lookup (ospf, nbr_addr);
1495 if (nbr_nbma == NULL)
1496 return 0;
1497
1498 if (nbr_nbma->priority != priority)
1499 nbr_nbma->priority = priority;
1500
1501 return 1;
1502}
1503
1504int
1505ospf_nbr_nbma_priority_unset (struct ospf *ospf, struct in_addr nbr_addr)
1506{
1507 struct ospf_nbr_nbma *nbr_nbma;
1508
1509 nbr_nbma = ospf_nbr_nbma_lookup (ospf, nbr_addr);
1510 if (nbr_nbma == NULL)
1511 return 0;
1512
1513 if (nbr_nbma != OSPF_NEIGHBOR_PRIORITY_DEFAULT)
1514 nbr_nbma->priority = OSPF_NEIGHBOR_PRIORITY_DEFAULT;
1515
1516 return 1;
1517}
1518
1519int
1520ospf_nbr_nbma_poll_interval_set (struct ospf *ospf, struct in_addr nbr_addr,
paul6c835672004-10-11 11:00:30 +00001521 unsigned int interval)
paul718e3742002-12-13 20:15:29 +00001522{
1523 struct ospf_nbr_nbma *nbr_nbma;
1524
1525 nbr_nbma = ospf_nbr_nbma_lookup (ospf, nbr_addr);
1526 if (nbr_nbma == NULL)
1527 return 0;
1528
1529 if (nbr_nbma->v_poll != interval)
1530 {
1531 nbr_nbma->v_poll = interval;
1532 if (nbr_nbma->oi && ospf_if_is_up (nbr_nbma->oi))
1533 {
1534 OSPF_TIMER_OFF (nbr_nbma->t_poll);
1535 OSPF_POLL_TIMER_ON (nbr_nbma->t_poll, ospf_poll_timer,
1536 nbr_nbma->v_poll);
1537 }
1538 }
1539
1540 return 1;
1541}
1542
1543int
1544ospf_nbr_nbma_poll_interval_unset (struct ospf *ospf, struct in_addr addr)
1545{
1546 struct ospf_nbr_nbma *nbr_nbma;
1547
1548 nbr_nbma = ospf_nbr_nbma_lookup (ospf, addr);
1549 if (nbr_nbma == NULL)
1550 return 0;
1551
1552 if (nbr_nbma->v_poll != OSPF_POLL_INTERVAL_DEFAULT)
1553 nbr_nbma->v_poll = OSPF_POLL_INTERVAL_DEFAULT;
1554
1555 return 1;
1556}
1557
paul718e3742002-12-13 20:15:29 +00001558void
paul020709f2003-04-04 02:44:16 +00001559ospf_master_init ()
1560{
1561 memset (&ospf_master, 0, sizeof (struct ospf_master));
1562
1563 om = &ospf_master;
1564 om->ospf = list_new ();
1565 om->master = thread_master_create ();
1566 om->start_time = time (NULL);
1567}