blob: 30164d02e6afa71b4ea27d9bea34c55d49c06a7c [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
160 new->abr_type = OSPF_ABR_STAND;
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;
188
189 /* MaxAge init. */
190 new->maxage_lsa = list_new ();
191 new->t_maxage_walker =
192 thread_add_timer (master, ospf_lsa_maxage_walker,
paul68980082003-03-25 05:07:42 +0000193 new, OSPF_LSA_MAXAGE_CHECK_INTERVAL);
paul718e3742002-12-13 20:15:29 +0000194
195 /* Distance table init. */
196 new->distance_table = route_table_init ();
197
198 new->lsa_refresh_queue.index = 0;
199 new->lsa_refresh_interval = OSPF_LSA_REFRESH_INTERVAL_DEFAULT;
200 new->t_lsa_refresher = thread_add_timer (master, ospf_lsa_refresh_walker,
201 new, new->lsa_refresh_interval);
202 new->lsa_refresher_started = time (NULL);
203
ajs5c333492005-02-23 15:43:01 +0000204 if ((new->fd = ospf_sock_init()) < 0)
205 {
206 zlog_err("ospf_new: fatal error: ospf_sock_init was unable to open "
207 "a socket");
208 exit(1);
209 }
210 if ((new->ibuf = stream_new(OSPF_MAX_PACKET_SIZE+1)) == NULL)
211 {
212 zlog_err("ospf_new: fatal error: stream_new(%u) failed allocating ibuf",
213 OSPF_MAX_PACKET_SIZE+1);
214 exit(1);
215 }
216 new->t_read = thread_add_read (master, ospf_read, new, new->fd);
paul718e3742002-12-13 20:15:29 +0000217 new->oi_write_q = list_new ();
218
219 return new;
220}
221
222struct ospf *
paul020709f2003-04-04 02:44:16 +0000223ospf_lookup ()
224{
225 if (listcount (om->ospf) == 0)
226 return NULL;
227
paul1eb8ef22005-04-07 07:30:20 +0000228 return listgetdata (listhead (om->ospf));
paul020709f2003-04-04 02:44:16 +0000229}
230
paul4dadc292005-05-06 21:37:42 +0000231static void
paul020709f2003-04-04 02:44:16 +0000232ospf_add (struct ospf *ospf)
233{
234 listnode_add (om->ospf, ospf);
235}
236
paul4dadc292005-05-06 21:37:42 +0000237static void
paul020709f2003-04-04 02:44:16 +0000238ospf_delete (struct ospf *ospf)
239{
240 listnode_delete (om->ospf, ospf);
241}
242
243struct ospf *
paul718e3742002-12-13 20:15:29 +0000244ospf_get ()
245{
paul020709f2003-04-04 02:44:16 +0000246 struct ospf *ospf;
paul718e3742002-12-13 20:15:29 +0000247
paul020709f2003-04-04 02:44:16 +0000248 ospf = ospf_lookup ();
249 if (ospf == NULL)
250 {
251 ospf = ospf_new ();
252 ospf_add (ospf);
paul718e3742002-12-13 20:15:29 +0000253
paul020709f2003-04-04 02:44:16 +0000254 if (ospf->router_id_static.s_addr == 0)
255 ospf_router_id_update (ospf);
paul718e3742002-12-13 20:15:29 +0000256
257#ifdef HAVE_OPAQUE_LSA
paul020709f2003-04-04 02:44:16 +0000258 ospf_opaque_type11_lsa_init (ospf);
paul718e3742002-12-13 20:15:29 +0000259#endif /* HAVE_OPAQUE_LSA */
paul020709f2003-04-04 02:44:16 +0000260 }
paul68980082003-03-25 05:07:42 +0000261
262 return ospf;
paul718e3742002-12-13 20:15:29 +0000263}
264
265void
266ospf_finish (struct ospf *ospf)
267{
268 struct route_node *rn;
269 struct ospf_nbr_nbma *nbr_nbma;
paul68980082003-03-25 05:07:42 +0000270 struct ospf_lsa *lsa;
paul1eb8ef22005-04-07 07:30:20 +0000271 struct ospf_interface *oi;
272 struct ospf_area *area;
273 struct ospf_vl_data *vl_data;
274 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000275 int i;
276
277#ifdef HAVE_OPAQUE_LSA
278 ospf_opaque_type11_lsa_term (ospf);
279#endif /* HAVE_OPAQUE_LSA */
280
281 /* Unredister redistribution */
282 for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
paul020709f2003-04-04 02:44:16 +0000283 ospf_redistribute_unset (ospf, i);
paul718e3742002-12-13 20:15:29 +0000284
paul1eb8ef22005-04-07 07:30:20 +0000285 for (ALL_LIST_ELEMENTS (ospf->areas, node, nnode, area))
286 ospf_remove_vls_through_area (ospf, area);
paul718e3742002-12-13 20:15:29 +0000287
paul1eb8ef22005-04-07 07:30:20 +0000288 for (ALL_LIST_ELEMENTS (ospf->vlinks, node, nnode, vl_data))
289 ospf_vl_delete (ospf, vl_data);
paul718e3742002-12-13 20:15:29 +0000290
291 list_delete (ospf->vlinks);
292
293 /* Reset interface. */
paul1eb8ef22005-04-07 07:30:20 +0000294 for (ALL_LIST_ELEMENTS (ospf->oiflist, node, nnode, oi))
295 ospf_if_free (oi);
paul718e3742002-12-13 20:15:29 +0000296
297 /* Clear static neighbors */
298 for (rn = route_top (ospf->nbr_nbma); rn; rn = route_next (rn))
299 if ((nbr_nbma = rn->info))
300 {
301 OSPF_POLL_TIMER_OFF (nbr_nbma->t_poll);
302
303 if (nbr_nbma->nbr)
304 {
305 nbr_nbma->nbr->nbr_nbma = NULL;
306 nbr_nbma->nbr = NULL;
307 }
308
309 if (nbr_nbma->oi)
310 {
311 listnode_delete (nbr_nbma->oi->nbr_nbma, nbr_nbma);
312 nbr_nbma->oi = NULL;
313 }
314
315 XFREE (MTYPE_OSPF_NEIGHBOR_STATIC, nbr_nbma);
316 }
317
318 route_table_finish (ospf->nbr_nbma);
319
320 /* Clear networks and Areas. */
321 for (rn = route_top (ospf->networks); rn; rn = route_next (rn))
322 {
323 struct ospf_network *network;
324
325 if ((network = rn->info) != NULL)
326 {
paul68980082003-03-25 05:07:42 +0000327 ospf_network_free (ospf, network);
paul718e3742002-12-13 20:15:29 +0000328 rn->info = NULL;
329 route_unlock_node (rn);
330 }
331 }
332
paul1eb8ef22005-04-07 07:30:20 +0000333 for (ALL_LIST_ELEMENTS (ospf->areas, node, nnode, area))
paul718e3742002-12-13 20:15:29 +0000334 {
paul718e3742002-12-13 20:15:29 +0000335 listnode_delete (ospf->areas, area);
336 ospf_area_free (area);
337 }
338
339 /* Cancel all timers. */
340 OSPF_TIMER_OFF (ospf->t_external_lsa);
341 OSPF_TIMER_OFF (ospf->t_router_id_update);
342 OSPF_TIMER_OFF (ospf->t_router_lsa_update);
343 OSPF_TIMER_OFF (ospf->t_spf_calc);
344 OSPF_TIMER_OFF (ospf->t_ase_calc);
345 OSPF_TIMER_OFF (ospf->t_maxage);
346 OSPF_TIMER_OFF (ospf->t_maxage_walker);
347 OSPF_TIMER_OFF (ospf->t_abr_task);
348 OSPF_TIMER_OFF (ospf->t_distribute_update);
349 OSPF_TIMER_OFF (ospf->t_lsa_refresher);
350 OSPF_TIMER_OFF (ospf->t_read);
351 OSPF_TIMER_OFF (ospf->t_write);
352
353 close (ospf->fd);
ajs5c333492005-02-23 15:43:01 +0000354 stream_free(ospf->ibuf);
paul718e3742002-12-13 20:15:29 +0000355
356#ifdef HAVE_OPAQUE_LSA
paul68980082003-03-25 05:07:42 +0000357 LSDB_LOOP (OPAQUE_AS_LSDB (ospf), rn, lsa)
358 ospf_discard_from_db (ospf, ospf->lsdb, lsa);
paul718e3742002-12-13 20:15:29 +0000359#endif /* HAVE_OPAQUE_LSA */
paul68980082003-03-25 05:07:42 +0000360 LSDB_LOOP (EXTERNAL_LSDB (ospf), rn, lsa)
361 ospf_discard_from_db (ospf, ospf->lsdb, lsa);
362
paul718e3742002-12-13 20:15:29 +0000363 ospf_lsdb_delete_all (ospf->lsdb);
364 ospf_lsdb_free (ospf->lsdb);
365
paul1eb8ef22005-04-07 07:30:20 +0000366 for (ALL_LIST_ELEMENTS (ospf->maxage_lsa, node, nnode, lsa))
367 ospf_lsa_unlock (lsa);
paul718e3742002-12-13 20:15:29 +0000368
369 list_delete (ospf->maxage_lsa);
370
371 if (ospf->old_table)
372 ospf_route_table_free (ospf->old_table);
373 if (ospf->new_table)
374 {
375 ospf_route_delete (ospf->new_table);
376 ospf_route_table_free (ospf->new_table);
377 }
378 if (ospf->old_rtrs)
379 ospf_rtrs_free (ospf->old_rtrs);
380 if (ospf->new_rtrs)
381 ospf_rtrs_free (ospf->new_rtrs);
382 if (ospf->new_external_route)
383 {
384 ospf_route_delete (ospf->new_external_route);
385 ospf_route_table_free (ospf->new_external_route);
386 }
387 if (ospf->old_external_route)
388 {
389 ospf_route_delete (ospf->old_external_route);
390 ospf_route_table_free (ospf->old_external_route);
391 }
392 if (ospf->external_lsas)
393 {
394 ospf_ase_external_lsas_finish (ospf->external_lsas);
395 }
396
397 list_delete (ospf->areas);
398
399 for (i = ZEBRA_ROUTE_SYSTEM; i <= ZEBRA_ROUTE_MAX; i++)
400 if (EXTERNAL_INFO (i) != NULL)
401 for (rn = route_top (EXTERNAL_INFO (i)); rn; rn = route_next (rn))
402 {
403 if (rn->info == NULL)
404 continue;
405
406 XFREE (MTYPE_OSPF_EXTERNAL_INFO, rn->info);
407 rn->info = NULL;
408 route_unlock_node (rn);
409 }
410
paul68980082003-03-25 05:07:42 +0000411 ospf_distance_reset (ospf);
paul718e3742002-12-13 20:15:29 +0000412 route_table_finish (ospf->distance_table);
413
paul020709f2003-04-04 02:44:16 +0000414 ospf_delete (ospf);
paul718e3742002-12-13 20:15:29 +0000415
paul020709f2003-04-04 02:44:16 +0000416 XFREE (MTYPE_OSPF_TOP, ospf);
paul718e3742002-12-13 20:15:29 +0000417}
418
419
420/* allocate new OSPF Area object */
paul4dadc292005-05-06 21:37:42 +0000421static struct ospf_area *
paul68980082003-03-25 05:07:42 +0000422ospf_area_new (struct ospf *ospf, struct in_addr area_id)
paul718e3742002-12-13 20:15:29 +0000423{
424 struct ospf_area *new;
425
426 /* Allocate new config_network. */
427 new = XCALLOC (MTYPE_OSPF_AREA, sizeof (struct ospf_area));
428
paul68980082003-03-25 05:07:42 +0000429 new->ospf = ospf;
paul718e3742002-12-13 20:15:29 +0000430
431 new->area_id = area_id;
432
433 new->external_routing = OSPF_AREA_DEFAULT;
434 new->default_cost = 1;
435 new->auth_type = OSPF_AUTH_NULL;
436
437 /* New LSDB init. */
438 new->lsdb = ospf_lsdb_new ();
439
440 /* Self-originated LSAs initialize. */
441 new->router_lsa_self = NULL;
442
443#ifdef HAVE_OPAQUE_LSA
444 ospf_opaque_type10_lsa_init (new);
445#endif /* HAVE_OPAQUE_LSA */
446
447 new->oiflist = list_new ();
448 new->ranges = route_table_init ();
449
450 if (area_id.s_addr == OSPF_AREA_BACKBONE)
paul68980082003-03-25 05:07:42 +0000451 ospf->backbone = new;
paul718e3742002-12-13 20:15:29 +0000452
453 return new;
454}
455
456void
457ospf_area_free (struct ospf_area *area)
458{
paul68980082003-03-25 05:07:42 +0000459 struct route_node *rn;
460 struct ospf_lsa *lsa;
461
paul718e3742002-12-13 20:15:29 +0000462 /* Free LSDBs. */
paul68980082003-03-25 05:07:42 +0000463 LSDB_LOOP (ROUTER_LSDB (area), rn, lsa)
464 ospf_discard_from_db (area->ospf, area->lsdb, lsa);
465 LSDB_LOOP (NETWORK_LSDB (area), rn, lsa)
466 ospf_discard_from_db (area->ospf, area->lsdb, lsa);
467 LSDB_LOOP (SUMMARY_LSDB (area), rn, lsa)
468 ospf_discard_from_db (area->ospf, area->lsdb, lsa);
469 LSDB_LOOP (ASBR_SUMMARY_LSDB (area), rn, lsa)
470 ospf_discard_from_db (area->ospf, area->lsdb, lsa);
paul718e3742002-12-13 20:15:29 +0000471
paul68980082003-03-25 05:07:42 +0000472 LSDB_LOOP (NSSA_LSDB (area), rn, lsa)
473 ospf_discard_from_db (area->ospf, area->lsdb, lsa);
paul718e3742002-12-13 20:15:29 +0000474#ifdef HAVE_OPAQUE_LSA
paul68980082003-03-25 05:07:42 +0000475 LSDB_LOOP (OPAQUE_AREA_LSDB (area), rn, lsa)
476 ospf_discard_from_db (area->ospf, area->lsdb, lsa);
477 LSDB_LOOP (OPAQUE_LINK_LSDB (area), rn, lsa)
478 ospf_discard_from_db (area->ospf, area->lsdb, lsa);
paul718e3742002-12-13 20:15:29 +0000479#endif /* HAVE_OPAQUE_LSA */
480
481 ospf_lsdb_delete_all (area->lsdb);
482 ospf_lsdb_free (area->lsdb);
483
paul718e3742002-12-13 20:15:29 +0000484 ospf_lsa_unlock (area->router_lsa_self);
485
486 route_table_finish (area->ranges);
487 list_delete (area->oiflist);
488
489 if (EXPORT_NAME (area))
490 free (EXPORT_NAME (area));
491
492 if (IMPORT_NAME (area))
493 free (IMPORT_NAME (area));
494
495 /* Cancel timer. */
496 OSPF_TIMER_OFF (area->t_router_lsa_self);
497
498 if (OSPF_IS_AREA_BACKBONE (area))
paul68980082003-03-25 05:07:42 +0000499 area->ospf->backbone = NULL;
paul718e3742002-12-13 20:15:29 +0000500
501 XFREE (MTYPE_OSPF_AREA, area);
502}
503
504void
paul68980082003-03-25 05:07:42 +0000505ospf_area_check_free (struct ospf *ospf, struct in_addr area_id)
paul718e3742002-12-13 20:15:29 +0000506{
507 struct ospf_area *area;
508
paul68980082003-03-25 05:07:42 +0000509 area = ospf_area_lookup_by_area_id (ospf, area_id);
paul718e3742002-12-13 20:15:29 +0000510 if (area &&
511 listcount (area->oiflist) == 0 &&
512 area->ranges->top == NULL &&
513 area->shortcut_configured == OSPF_SHORTCUT_DEFAULT &&
514 area->external_routing == OSPF_AREA_DEFAULT &&
515 area->no_summary == 0 &&
516 area->default_cost == 1 &&
517 EXPORT_NAME (area) == NULL &&
518 IMPORT_NAME (area) == NULL &&
519 area->auth_type == OSPF_AUTH_NULL)
520 {
paul68980082003-03-25 05:07:42 +0000521 listnode_delete (ospf->areas, area);
paul718e3742002-12-13 20:15:29 +0000522 ospf_area_free (area);
523 }
524}
525
526struct ospf_area *
paul68980082003-03-25 05:07:42 +0000527ospf_area_get (struct ospf *ospf, struct in_addr area_id, int format)
paul718e3742002-12-13 20:15:29 +0000528{
529 struct ospf_area *area;
530
paul68980082003-03-25 05:07:42 +0000531 area = ospf_area_lookup_by_area_id (ospf, area_id);
paul718e3742002-12-13 20:15:29 +0000532 if (!area)
533 {
paul68980082003-03-25 05:07:42 +0000534 area = ospf_area_new (ospf, area_id);
paul718e3742002-12-13 20:15:29 +0000535 area->format = format;
paul68980082003-03-25 05:07:42 +0000536 listnode_add_sort (ospf->areas, area);
537 ospf_check_abr_status (ospf);
paul718e3742002-12-13 20:15:29 +0000538 }
539
540 return area;
541}
542
543struct ospf_area *
paul68980082003-03-25 05:07:42 +0000544ospf_area_lookup_by_area_id (struct ospf *ospf, struct in_addr area_id)
paul718e3742002-12-13 20:15:29 +0000545{
546 struct ospf_area *area;
hasso52dc7ee2004-09-23 19:18:23 +0000547 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000548
paul1eb8ef22005-04-07 07:30:20 +0000549 for (ALL_LIST_ELEMENTS_RO (ospf->areas, node, area))
550 if (IPV4_ADDR_SAME (&area->area_id, &area_id))
551 return area;
paul718e3742002-12-13 20:15:29 +0000552
553 return NULL;
554}
555
556void
557ospf_area_add_if (struct ospf_area *area, struct ospf_interface *oi)
558{
559 listnode_add (area->oiflist, oi);
560}
561
562void
563ospf_area_del_if (struct ospf_area *area, struct ospf_interface *oi)
564{
565 listnode_delete (area->oiflist, oi);
566}
567
568
569/* Config network statement related functions. */
paul4dadc292005-05-06 21:37:42 +0000570static struct ospf_network *
paul718e3742002-12-13 20:15:29 +0000571ospf_network_new (struct in_addr area_id, int format)
572{
573 struct ospf_network *new;
574 new = XCALLOC (MTYPE_OSPF_NETWORK, sizeof (struct ospf_network));
575
576 new->area_id = area_id;
577 new->format = format;
578
579 return new;
580}
581
582void
paul68980082003-03-25 05:07:42 +0000583ospf_network_free (struct ospf *ospf, struct ospf_network *network)
paul718e3742002-12-13 20:15:29 +0000584{
paul68980082003-03-25 05:07:42 +0000585 ospf_area_check_free (ospf, network->area_id);
586 ospf_schedule_abr_task (ospf);
paul718e3742002-12-13 20:15:29 +0000587 XFREE (MTYPE_OSPF_NETWORK, network);
588}
589
590int
591ospf_network_set (struct ospf *ospf, struct prefix_ipv4 *p,
592 struct in_addr area_id)
593{
594 struct ospf_network *network;
595 struct ospf_area *area;
596 struct route_node *rn;
597 struct external_info *ei;
paul147193a2003-04-19 00:31:59 +0000598 int ret = OSPF_AREA_ID_FORMAT_ADDRESS;
paul718e3742002-12-13 20:15:29 +0000599
600 rn = route_node_get (ospf->networks, (struct prefix *)p);
601 if (rn->info)
602 {
603 /* There is already same network statement. */
604 route_unlock_node (rn);
605 return 0;
606 }
607
608 rn->info = network = ospf_network_new (area_id, ret);
paul68980082003-03-25 05:07:42 +0000609 area = ospf_area_get (ospf, area_id, ret);
paul718e3742002-12-13 20:15:29 +0000610
611 /* Run network config now. */
612 ospf_network_run (ospf, (struct prefix *)p, area);
613
614 /* Update connected redistribute. */
615 if (ospf_is_type_redistributed (ZEBRA_ROUTE_CONNECT))
616 if (EXTERNAL_INFO (ZEBRA_ROUTE_CONNECT))
617 for (rn = route_top (EXTERNAL_INFO (ZEBRA_ROUTE_CONNECT));
618 rn; rn = route_next (rn))
619 if ((ei = rn->info) != NULL)
paul68980082003-03-25 05:07:42 +0000620 if (ospf_external_info_find_lsa (ospf, &ei->p))
621 if (!ospf_distribute_check_connected (ospf, ei))
622 ospf_external_lsa_flush (ospf, ei->type, &ei->p,
paul718e3742002-12-13 20:15:29 +0000623 ei->ifindex, ei->nexthop);
624
paul68980082003-03-25 05:07:42 +0000625 ospf_area_check_free (ospf, area_id);
paul718e3742002-12-13 20:15:29 +0000626
627 return 1;
628}
629
630int
631ospf_network_unset (struct ospf *ospf, struct prefix_ipv4 *p,
632 struct in_addr area_id)
633{
634 struct route_node *rn;
635 struct ospf_network *network;
636 struct external_info *ei;
637
638 rn = route_node_lookup (ospf->networks, (struct prefix *)p);
639 if (rn == NULL)
640 return 0;
641
642 network = rn->info;
643 if (!IPV4_ADDR_SAME (&area_id, &network->area_id))
644 return 0;
645
paul68980082003-03-25 05:07:42 +0000646 ospf_network_free (ospf, rn->info);
paul718e3742002-12-13 20:15:29 +0000647 rn->info = NULL;
648 route_unlock_node (rn);
649
paul68980082003-03-25 05:07:42 +0000650 ospf_if_update (ospf);
paul718e3742002-12-13 20:15:29 +0000651
652 /* Update connected redistribute. */
653 if (ospf_is_type_redistributed (ZEBRA_ROUTE_CONNECT))
654 if (EXTERNAL_INFO (ZEBRA_ROUTE_CONNECT))
655 for (rn = route_top (EXTERNAL_INFO (ZEBRA_ROUTE_CONNECT));
656 rn; rn = route_next (rn))
657 if ((ei = rn->info) != NULL)
paul68980082003-03-25 05:07:42 +0000658 if (!ospf_external_info_find_lsa (ospf, &ei->p))
659 if (ospf_distribute_check_connected (ospf, ei))
660 ospf_external_lsa_originate (ospf, ei);
paul718e3742002-12-13 20:15:29 +0000661
662 return 1;
663}
664
paul570f7592003-01-25 06:47:41 +0000665/* Check whether interface matches given network
666 * returns: 1, true. 0, false
667 */
668int
669ospf_network_match_iface(struct connected *co, struct prefix *net)
670{
671 /* Behaviour to match both Cisco where:
672 * iface address lies within network specified -> ospf
673 * and zebra 0.9[2ish-3]:
674 * PtP special case: network specified == iface peer addr -> ospf
675 */
gdt8f40e892003-12-05 14:01:43 +0000676
paulf3ae74c2004-11-04 20:35:31 +0000677 /* For PtP, match if peer address matches network address exactly.
678 * This can be addr/32 or addr/p for p < 32, but the addr must match
679 * exactly; this is not a test for falling within the prefix. This
gdt8f40e892003-12-05 14:01:43 +0000680 * test is solely for compatibility with zebra.
gdt8f40e892003-12-05 14:01:43 +0000681 */
paulf3ae74c2004-11-04 20:35:31 +0000682 if (if_is_pointopoint (co->ifp) && co->destination &&
683 IPV4_ADDR_SAME ( &(co->destination->u.prefix4), &(net->u.prefix4)))
684 return 1;
685
686#if 0
687 /* Decline to accept PtP if dst address does not match the
688 * prefix. (ifdefed out because this is a workaround, not the
689 * desired behavior.) */
690 if (if_is_pointopoint (co->ifp) &&
691 ! prefix_match (net, co->destination))
692 return 0;
693#endif
694
695 /* If the address is within the prefix, accept. Note that this
696 * applies to PtP as well as other types.
697 */
698 if (prefix_match (net, co->address))
699 return 1;
700
701 return 0; /* no match */
paul570f7592003-01-25 06:47:41 +0000702}
703
paul718e3742002-12-13 20:15:29 +0000704void
705ospf_network_run (struct ospf *ospf, struct prefix *p, struct ospf_area *area)
706{
707 struct interface *ifp;
paul1eb8ef22005-04-07 07:30:20 +0000708 struct connected *co;
hasso52dc7ee2004-09-23 19:18:23 +0000709 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000710
711 /* Schedule Router ID Update. */
712 if (ospf->router_id_static.s_addr == 0)
713 if (ospf->t_router_id_update == NULL)
714 {
paul020709f2003-04-04 02:44:16 +0000715 OSPF_TIMER_ON (ospf->t_router_id_update, ospf_router_id_update_timer,
716 OSPF_ROUTER_ID_UPDATE_DELAY);
paul718e3742002-12-13 20:15:29 +0000717 }
718
719 /* Get target interface. */
paul1eb8ef22005-04-07 07:30:20 +0000720 for (ALL_LIST_ELEMENTS_RO (om->iflist, node, ifp))
paul718e3742002-12-13 20:15:29 +0000721 {
paul1eb8ef22005-04-07 07:30:20 +0000722 struct listnode *cnode;
paul718e3742002-12-13 20:15:29 +0000723
paul718e3742002-12-13 20:15:29 +0000724 if (memcmp (ifp->name, "VLINK", 5) == 0)
725 continue;
726
727 /* if interface prefix is match specified prefix,
728 then create socket and join multicast group. */
paul1eb8ef22005-04-07 07:30:20 +0000729 for (ALL_LIST_ELEMENTS_RO (ifp->connected, cnode, co))
paul718e3742002-12-13 20:15:29 +0000730 {
paul718e3742002-12-13 20:15:29 +0000731 struct prefix *addr;
paul800dc102003-03-28 01:51:40 +0000732
paule7b050c2003-04-07 06:38:02 +0000733 if (CHECK_FLAG(co->flags,ZEBRA_IFA_SECONDARY))
734 continue;
paul718e3742002-12-13 20:15:29 +0000735
hasso3fb9cd62004-10-19 19:44:43 +0000736 if (CONNECTED_POINTOPOINT_HOST(co))
paul718e3742002-12-13 20:15:29 +0000737 addr = co->destination;
738 else
739 addr = co->address;
740
paulcb3f37d2003-02-18 23:26:37 +0000741 if (p->family == co->address->family
paul68980082003-03-25 05:07:42 +0000742 && ! ospf_if_is_configured (ospf, &(addr->u.prefix4))
paulcb3f37d2003-02-18 23:26:37 +0000743 && ospf_network_match_iface(co,p))
paul570f7592003-01-25 06:47:41 +0000744 {
paul1eb8ef22005-04-07 07:30:20 +0000745 struct ospf_interface *oi;
paul718e3742002-12-13 20:15:29 +0000746
paul68980082003-03-25 05:07:42 +0000747 oi = ospf_if_new (ospf, ifp, co->address);
paul718e3742002-12-13 20:15:29 +0000748 oi->connected = co;
749
750 oi->nbr_self->address = *oi->address;
751
paul718e3742002-12-13 20:15:29 +0000752 oi->area = area;
753
754 oi->params = ospf_lookup_if_params (ifp, oi->address->u.prefix4);
755 oi->output_cost = ospf_if_get_output_cost (oi);
756
757 if (area->external_routing != OSPF_AREA_DEFAULT)
758 UNSET_FLAG (oi->nbr_self->options, OSPF_OPTION_E);
759 oi->nbr_self->priority = OSPF_IF_PARAM (oi, priority);
760
761 /* Add pseudo neighbor. */
762 ospf_nbr_add_self (oi);
763
764 /* Make sure pseudo neighbor's router_id. */
paul68980082003-03-25 05:07:42 +0000765 oi->nbr_self->router_id = ospf->router_id;
paul718e3742002-12-13 20:15:29 +0000766 oi->nbr_self->src = oi->address->u.prefix4;
767
768 /* Relate ospf interface to ospf instance. */
paul68980082003-03-25 05:07:42 +0000769 oi->ospf = ospf;
paul718e3742002-12-13 20:15:29 +0000770
771 /* update network type as interface flag */
772 /* If network type is specified previously,
773 skip network type setting. */
774 oi->type = IF_DEF_PARAMS (ifp)->type;
775
776 /* Set area flag. */
777 switch (area->external_routing)
778 {
779 case OSPF_AREA_DEFAULT:
780 SET_FLAG (oi->nbr_self->options, OSPF_OPTION_E);
781 break;
782 case OSPF_AREA_STUB:
783 UNSET_FLAG (oi->nbr_self->options, OSPF_OPTION_E);
784 break;
paul718e3742002-12-13 20:15:29 +0000785 case OSPF_AREA_NSSA:
786 UNSET_FLAG (oi->nbr_self->options, OSPF_OPTION_E);
787 SET_FLAG (oi->nbr_self->options, OSPF_OPTION_NP);
788 break;
paul718e3742002-12-13 20:15:29 +0000789 }
790
791 ospf_area_add_if (oi->area, oi);
792
paul2e3b2e42002-12-13 21:03:13 +0000793 if (if_is_operative (ifp))
paul718e3742002-12-13 20:15:29 +0000794 ospf_if_up (oi);
795
796 break;
797 }
798 }
799 }
800}
801
802void
803ospf_ls_upd_queue_empty (struct ospf_interface *oi)
804{
805 struct route_node *rn;
paul1eb8ef22005-04-07 07:30:20 +0000806 struct listnode *node, *nnode;
hasso52dc7ee2004-09-23 19:18:23 +0000807 struct list *lst;
paul718e3742002-12-13 20:15:29 +0000808 struct ospf_lsa *lsa;
809
810 /* empty ls update queue */
811 for (rn = route_top (oi->ls_upd_queue); rn;
812 rn = route_next (rn))
hasso52dc7ee2004-09-23 19:18:23 +0000813 if ((lst = (struct list *) rn->info))
paul718e3742002-12-13 20:15:29 +0000814 {
paul1eb8ef22005-04-07 07:30:20 +0000815 for (ALL_LIST_ELEMENTS (lst, node, nnode, lsa))
816 ospf_lsa_unlock (lsa);
paul718e3742002-12-13 20:15:29 +0000817 list_free (lst);
818 rn->info = NULL;
819 }
820
821 /* remove update event */
822 if (oi->t_ls_upd_event)
823 {
824 thread_cancel (oi->t_ls_upd_event);
825 oi->t_ls_upd_event = NULL;
826 }
827}
828
829void
paul68980082003-03-25 05:07:42 +0000830ospf_if_update (struct ospf *ospf)
paul718e3742002-12-13 20:15:29 +0000831{
832 struct route_node *rn;
paul1eb8ef22005-04-07 07:30:20 +0000833 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000834 struct ospf_network *network;
835 struct ospf_area *area;
paul1eb8ef22005-04-07 07:30:20 +0000836 struct ospf_interface *oi;
paul718e3742002-12-13 20:15:29 +0000837
paul68980082003-03-25 05:07:42 +0000838 if (ospf != NULL)
paul718e3742002-12-13 20:15:29 +0000839 {
840 /* Update Router ID scheduled. */
paul68980082003-03-25 05:07:42 +0000841 if (ospf->router_id_static.s_addr == 0)
842 if (ospf->t_router_id_update == NULL)
paul718e3742002-12-13 20:15:29 +0000843 {
paul020709f2003-04-04 02:44:16 +0000844 OSPF_TIMER_ON (ospf->t_router_id_update,
845 ospf_router_id_update_timer,
846 OSPF_ROUTER_ID_UPDATE_DELAY);
paul718e3742002-12-13 20:15:29 +0000847 }
848
849 /* Find interfaces that not configured already. */
paul1eb8ef22005-04-07 07:30:20 +0000850 for (ALL_LIST_ELEMENTS (ospf->oiflist, node, nnode, oi))
paul718e3742002-12-13 20:15:29 +0000851 {
852 int found = 0;
paul718e3742002-12-13 20:15:29 +0000853 struct connected *co = oi->connected;
854
paul718e3742002-12-13 20:15:29 +0000855 if (oi->type == OSPF_IFTYPE_VIRTUALLINK)
856 continue;
857
paul68980082003-03-25 05:07:42 +0000858 for (rn = route_top (ospf->networks); rn; rn = route_next (rn))
paul718e3742002-12-13 20:15:29 +0000859 {
860 if (rn->info == NULL)
861 continue;
862
paul570f7592003-01-25 06:47:41 +0000863 if (ospf_network_match_iface(co,&rn->p))
paul718e3742002-12-13 20:15:29 +0000864 {
865 found = 1;
866 route_unlock_node (rn);
867 break;
868 }
869 }
870
871 if (found == 0)
872 ospf_if_free (oi);
873 }
874
875 /* Run each interface. */
paul68980082003-03-25 05:07:42 +0000876 for (rn = route_top (ospf->networks); rn; rn = route_next (rn))
paul718e3742002-12-13 20:15:29 +0000877 if (rn->info != NULL)
878 {
879 network = (struct ospf_network *) rn->info;
paul68980082003-03-25 05:07:42 +0000880 area = ospf_area_get (ospf, network->area_id, network->format);
881 ospf_network_run (ospf, &rn->p, area);
paul718e3742002-12-13 20:15:29 +0000882 }
883 }
884}
885
886void
paul68980082003-03-25 05:07:42 +0000887ospf_remove_vls_through_area (struct ospf *ospf, struct ospf_area *area)
paul718e3742002-12-13 20:15:29 +0000888{
paul1eb8ef22005-04-07 07:30:20 +0000889 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000890 struct ospf_vl_data *vl_data;
891
paul1eb8ef22005-04-07 07:30:20 +0000892 for (ALL_LIST_ELEMENTS (ospf->vlinks, node, nnode, vl_data))
893 if (IPV4_ADDR_SAME (&vl_data->vl_area_id, &area->area_id))
894 ospf_vl_delete (ospf, vl_data);
paul718e3742002-12-13 20:15:29 +0000895}
896
897
898struct message ospf_area_type_msg[] =
899{
900 { OSPF_AREA_DEFAULT, "Default" },
901 { OSPF_AREA_STUB, "Stub" },
902 { OSPF_AREA_NSSA, "NSSA" },
903};
904int ospf_area_type_msg_max = OSPF_AREA_TYPE_MAX;
905
paul4dadc292005-05-06 21:37:42 +0000906static void
paul718e3742002-12-13 20:15:29 +0000907ospf_area_type_set (struct ospf_area *area, int type)
908{
hasso52dc7ee2004-09-23 19:18:23 +0000909 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000910 struct ospf_interface *oi;
911
912 if (area->external_routing == type)
913 {
914 if (IS_DEBUG_OSPF_EVENT)
ajs9b0e25c2004-12-08 19:06:51 +0000915 zlog_debug ("Area[%s]: Types are the same, ignored.",
paul718e3742002-12-13 20:15:29 +0000916 inet_ntoa (area->area_id));
917 return;
918 }
919
920 area->external_routing = type;
921
922 if (IS_DEBUG_OSPF_EVENT)
ajs9b0e25c2004-12-08 19:06:51 +0000923 zlog_debug ("Area[%s]: Configured as %s", inet_ntoa (area->area_id),
paul718e3742002-12-13 20:15:29 +0000924 LOOKUP (ospf_area_type_msg, type));
925
926 switch (area->external_routing)
927 {
928 case OSPF_AREA_DEFAULT:
paul1eb8ef22005-04-07 07:30:20 +0000929 for (ALL_LIST_ELEMENTS_RO (area->oiflist, node, oi))
930 if (oi->nbr_self != NULL)
931 {
932 UNSET_FLAG (oi->nbr_self->options, OSPF_OPTION_NP);
933 SET_FLAG (oi->nbr_self->options, OSPF_OPTION_E);
934 }
paul718e3742002-12-13 20:15:29 +0000935 break;
936 case OSPF_AREA_STUB:
paul1eb8ef22005-04-07 07:30:20 +0000937 for (ALL_LIST_ELEMENTS_RO (area->oiflist, node, oi))
938 if (oi->nbr_self != NULL)
939 {
940 if (IS_DEBUG_OSPF_EVENT)
941 zlog_debug ("setting options on %s accordingly", IF_NAME (oi));
942 UNSET_FLAG (oi->nbr_self->options, OSPF_OPTION_NP);
943 UNSET_FLAG (oi->nbr_self->options, OSPF_OPTION_E);
944 if (IS_DEBUG_OSPF_EVENT)
945 zlog_debug ("options set on %s: %x",
946 IF_NAME (oi), OPTIONS (oi));
947 }
paul718e3742002-12-13 20:15:29 +0000948 break;
949 case OSPF_AREA_NSSA:
paul1eb8ef22005-04-07 07:30:20 +0000950 for (ALL_LIST_ELEMENTS_RO (area->oiflist, node, oi))
951 if (oi->nbr_self != NULL)
952 {
953 zlog_debug ("setting nssa options on %s accordingly", IF_NAME (oi));
954 UNSET_FLAG (oi->nbr_self->options, OSPF_OPTION_E);
955 SET_FLAG (oi->nbr_self->options, OSPF_OPTION_NP);
956 zlog_debug ("options set on %s: %x", IF_NAME (oi), OPTIONS (oi));
957 }
paul718e3742002-12-13 20:15:29 +0000958 break;
959 default:
960 break;
961 }
962
963 ospf_router_lsa_timer_add (area);
paul68980082003-03-25 05:07:42 +0000964 ospf_schedule_abr_task (area->ospf);
paul718e3742002-12-13 20:15:29 +0000965}
966
967int
paul68980082003-03-25 05:07:42 +0000968ospf_area_shortcut_set (struct ospf *ospf, struct ospf_area *area, int mode)
paul718e3742002-12-13 20:15:29 +0000969{
970 if (area->shortcut_configured == mode)
971 return 0;
972
973 area->shortcut_configured = mode;
974 ospf_router_lsa_timer_add (area);
paul68980082003-03-25 05:07:42 +0000975 ospf_schedule_abr_task (ospf);
paul718e3742002-12-13 20:15:29 +0000976
paul68980082003-03-25 05:07:42 +0000977 ospf_area_check_free (ospf, area->area_id);
paul718e3742002-12-13 20:15:29 +0000978
979 return 1;
980}
981
982int
paul68980082003-03-25 05:07:42 +0000983ospf_area_shortcut_unset (struct ospf *ospf, struct ospf_area *area)
paul718e3742002-12-13 20:15:29 +0000984{
985 area->shortcut_configured = OSPF_SHORTCUT_DEFAULT;
986 ospf_router_lsa_timer_add (area);
paul68980082003-03-25 05:07:42 +0000987 ospf_area_check_free (ospf, area->area_id);
988 ospf_schedule_abr_task (ospf);
paul718e3742002-12-13 20:15:29 +0000989
990 return 1;
991}
992
paul4dadc292005-05-06 21:37:42 +0000993static int
paul718e3742002-12-13 20:15:29 +0000994ospf_area_vlink_count (struct ospf *ospf, struct ospf_area *area)
995{
996 struct ospf_vl_data *vl;
hasso52dc7ee2004-09-23 19:18:23 +0000997 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000998 int count = 0;
999
paul1eb8ef22005-04-07 07:30:20 +00001000 for (ALL_LIST_ELEMENTS_RO (ospf->vlinks, node, vl))
1001 if (IPV4_ADDR_SAME (&vl->vl_area_id, &area->area_id))
1002 count++;
paul718e3742002-12-13 20:15:29 +00001003
1004 return count;
1005}
1006
1007int
1008ospf_area_stub_set (struct ospf *ospf, struct in_addr area_id)
1009{
1010 struct ospf_area *area;
paul147193a2003-04-19 00:31:59 +00001011 int format = OSPF_AREA_ID_FORMAT_ADDRESS;
paul718e3742002-12-13 20:15:29 +00001012
paul68980082003-03-25 05:07:42 +00001013 area = ospf_area_get (ospf, area_id, format);
paul718e3742002-12-13 20:15:29 +00001014 if (ospf_area_vlink_count (ospf, area))
1015 return 0;
1016
1017 if (area->external_routing != OSPF_AREA_STUB)
1018 ospf_area_type_set (area, OSPF_AREA_STUB);
1019
1020 return 1;
1021}
1022
1023int
1024ospf_area_stub_unset (struct ospf *ospf, struct in_addr area_id)
1025{
1026 struct ospf_area *area;
1027
paul68980082003-03-25 05:07:42 +00001028 area = ospf_area_lookup_by_area_id (ospf, area_id);
paul718e3742002-12-13 20:15:29 +00001029 if (area == NULL)
1030 return 1;
1031
1032 if (area->external_routing == OSPF_AREA_STUB)
1033 ospf_area_type_set (area, OSPF_AREA_DEFAULT);
1034
paul68980082003-03-25 05:07:42 +00001035 ospf_area_check_free (ospf, area_id);
paul718e3742002-12-13 20:15:29 +00001036
1037 return 1;
1038}
1039
1040int
1041ospf_area_no_summary_set (struct ospf *ospf, struct in_addr area_id)
1042{
1043 struct ospf_area *area;
paul147193a2003-04-19 00:31:59 +00001044 int format = OSPF_AREA_ID_FORMAT_ADDRESS;
paul718e3742002-12-13 20:15:29 +00001045
paul68980082003-03-25 05:07:42 +00001046 area = ospf_area_get (ospf, area_id, format);
paul718e3742002-12-13 20:15:29 +00001047 area->no_summary = 1;
1048
1049 return 1;
1050}
1051
1052int
1053ospf_area_no_summary_unset (struct ospf *ospf, struct in_addr area_id)
1054{
1055 struct ospf_area *area;
1056
paul68980082003-03-25 05:07:42 +00001057 area = ospf_area_lookup_by_area_id (ospf, area_id);
paul718e3742002-12-13 20:15:29 +00001058 if (area == NULL)
1059 return 0;
1060
1061 area->no_summary = 0;
paul68980082003-03-25 05:07:42 +00001062 ospf_area_check_free (ospf, area_id);
paul718e3742002-12-13 20:15:29 +00001063
1064 return 1;
1065}
1066
1067int
1068ospf_area_nssa_set (struct ospf *ospf, struct in_addr area_id)
1069{
1070 struct ospf_area *area;
paul147193a2003-04-19 00:31:59 +00001071 int format = OSPF_AREA_ID_FORMAT_ADDRESS;
paul718e3742002-12-13 20:15:29 +00001072
paul68980082003-03-25 05:07:42 +00001073 area = ospf_area_get (ospf, area_id, format);
paul718e3742002-12-13 20:15:29 +00001074 if (ospf_area_vlink_count (ospf, area))
1075 return 0;
1076
1077 if (area->external_routing != OSPF_AREA_NSSA)
1078 {
1079 ospf_area_type_set (area, OSPF_AREA_NSSA);
1080 ospf->anyNSSA++;
1081 }
1082
paul084c7842003-06-22 08:35:18 +00001083 /* set NSSA area defaults */
1084 area->no_summary = 0;
1085 area->NSSATranslatorRole = OSPF_NSSA_ROLE_CANDIDATE;
pauld4a53d52003-07-12 21:30:57 +00001086 area->NSSATranslatorState = OSPF_NSSA_TRANSLATE_DISABLED;
paul084c7842003-06-22 08:35:18 +00001087 area->NSSATranslatorStabilityInterval = OSPF_NSSA_TRANS_STABLE_DEFAULT;
1088
paul718e3742002-12-13 20:15:29 +00001089 return 1;
1090}
1091
1092int
1093ospf_area_nssa_unset (struct ospf *ospf, struct in_addr area_id)
1094{
1095 struct ospf_area *area;
1096
paul68980082003-03-25 05:07:42 +00001097 area = ospf_area_lookup_by_area_id (ospf, area_id);
paul718e3742002-12-13 20:15:29 +00001098 if (area == NULL)
1099 return 0;
1100
1101 if (area->external_routing == OSPF_AREA_NSSA)
1102 {
1103 ospf->anyNSSA--;
1104 ospf_area_type_set (area, OSPF_AREA_DEFAULT);
1105 }
1106
paul68980082003-03-25 05:07:42 +00001107 ospf_area_check_free (ospf, area_id);
paul718e3742002-12-13 20:15:29 +00001108
1109 return 1;
1110}
1111
1112int
1113ospf_area_nssa_translator_role_set (struct ospf *ospf, struct in_addr area_id,
1114 int role)
1115{
1116 struct ospf_area *area;
1117
paul68980082003-03-25 05:07:42 +00001118 area = ospf_area_lookup_by_area_id (ospf, area_id);
paul718e3742002-12-13 20:15:29 +00001119 if (area == NULL)
1120 return 0;
1121
paul084c7842003-06-22 08:35:18 +00001122 area->NSSATranslatorRole = role;
paul718e3742002-12-13 20:15:29 +00001123
1124 return 1;
1125}
1126
paul4dadc292005-05-06 21:37:42 +00001127/* XXX: unused? Leave for symmetry? */
1128static int
paul718e3742002-12-13 20:15:29 +00001129ospf_area_nssa_translator_role_unset (struct ospf *ospf,
1130 struct in_addr area_id)
1131{
1132 struct ospf_area *area;
1133
paul68980082003-03-25 05:07:42 +00001134 area = ospf_area_lookup_by_area_id (ospf, area_id);
paul718e3742002-12-13 20:15:29 +00001135 if (area == NULL)
1136 return 0;
1137
paul084c7842003-06-22 08:35:18 +00001138 area->NSSATranslatorRole = OSPF_NSSA_ROLE_CANDIDATE;
paul718e3742002-12-13 20:15:29 +00001139
paul68980082003-03-25 05:07:42 +00001140 ospf_area_check_free (ospf, area_id);
paul718e3742002-12-13 20:15:29 +00001141
1142 return 1;
1143}
1144
1145int
paul68980082003-03-25 05:07:42 +00001146ospf_area_export_list_set (struct ospf *ospf,
paul6c835672004-10-11 11:00:30 +00001147 struct ospf_area *area, const char *list_name)
paul718e3742002-12-13 20:15:29 +00001148{
1149 struct access_list *list;
1150 list = access_list_lookup (AFI_IP, list_name);
1151
1152 EXPORT_LIST (area) = list;
1153
1154 if (EXPORT_NAME (area))
1155 free (EXPORT_NAME (area));
1156
1157 EXPORT_NAME (area) = strdup (list_name);
paul68980082003-03-25 05:07:42 +00001158 ospf_schedule_abr_task (ospf);
paul718e3742002-12-13 20:15:29 +00001159
1160 return 1;
1161}
1162
1163int
paul68980082003-03-25 05:07:42 +00001164ospf_area_export_list_unset (struct ospf *ospf, struct ospf_area * area)
paul718e3742002-12-13 20:15:29 +00001165{
1166
1167 EXPORT_LIST (area) = 0;
1168
1169 if (EXPORT_NAME (area))
1170 free (EXPORT_NAME (area));
1171
1172 EXPORT_NAME (area) = NULL;
1173
paul68980082003-03-25 05:07:42 +00001174 ospf_area_check_free (ospf, area->area_id);
paul718e3742002-12-13 20:15:29 +00001175
paul68980082003-03-25 05:07:42 +00001176 ospf_schedule_abr_task (ospf);
paul718e3742002-12-13 20:15:29 +00001177
1178 return 1;
1179}
1180
1181int
paul6c835672004-10-11 11:00:30 +00001182ospf_area_import_list_set (struct ospf *ospf, struct ospf_area *area,
1183 const char *name)
paul718e3742002-12-13 20:15:29 +00001184{
1185 struct access_list *list;
1186 list = access_list_lookup (AFI_IP, name);
1187
1188 IMPORT_LIST (area) = list;
1189
1190 if (IMPORT_NAME (area))
1191 free (IMPORT_NAME (area));
1192
1193 IMPORT_NAME (area) = strdup (name);
paul68980082003-03-25 05:07:42 +00001194 ospf_schedule_abr_task (ospf);
paul718e3742002-12-13 20:15:29 +00001195
1196 return 1;
1197}
1198
1199int
paul68980082003-03-25 05:07:42 +00001200ospf_area_import_list_unset (struct ospf *ospf, struct ospf_area * area)
paul718e3742002-12-13 20:15:29 +00001201{
1202 IMPORT_LIST (area) = 0;
1203
1204 if (IMPORT_NAME (area))
1205 free (IMPORT_NAME (area));
1206
1207 IMPORT_NAME (area) = NULL;
paul68980082003-03-25 05:07:42 +00001208 ospf_area_check_free (ospf, area->area_id);
paul718e3742002-12-13 20:15:29 +00001209
paul68980082003-03-25 05:07:42 +00001210 ospf_schedule_abr_task (ospf);
paul718e3742002-12-13 20:15:29 +00001211
1212 return 1;
1213}
1214
1215int
1216ospf_timers_spf_set (struct ospf *ospf, u_int32_t delay, u_int32_t hold)
1217{
1218 ospf->spf_delay = delay;
1219 ospf->spf_holdtime = hold;
1220
1221 return 1;
1222}
1223
1224int
1225ospf_timers_spf_unset (struct ospf *ospf)
1226{
1227 ospf->spf_delay = OSPF_SPF_DELAY_DEFAULT;
1228 ospf->spf_holdtime = OSPF_SPF_HOLDTIME_DEFAULT;
1229
1230 return 1;
1231}
1232
1233int
1234ospf_timers_refresh_set (struct ospf *ospf, int interval)
1235{
1236 int time_left;
1237
1238 if (ospf->lsa_refresh_interval == interval)
1239 return 1;
1240
1241 time_left = ospf->lsa_refresh_interval -
1242 (time (NULL) - ospf->lsa_refresher_started);
1243
1244 if (time_left > interval)
1245 {
1246 OSPF_TIMER_OFF (ospf->t_lsa_refresher);
1247 ospf->t_lsa_refresher =
1248 thread_add_timer (master, ospf_lsa_refresh_walker, ospf, interval);
1249 }
1250 ospf->lsa_refresh_interval = interval;
1251
1252 return 1;
1253}
1254
1255int
1256ospf_timers_refresh_unset (struct ospf *ospf)
1257{
1258 int time_left;
1259
1260 time_left = ospf->lsa_refresh_interval -
1261 (time (NULL) - ospf->lsa_refresher_started);
1262
1263 if (time_left > OSPF_LSA_REFRESH_INTERVAL_DEFAULT)
1264 {
1265 OSPF_TIMER_OFF (ospf->t_lsa_refresher);
1266 ospf->t_lsa_refresher =
1267 thread_add_timer (master, ospf_lsa_refresh_walker, ospf,
1268 OSPF_LSA_REFRESH_INTERVAL_DEFAULT);
1269 }
1270
1271 ospf->lsa_refresh_interval = OSPF_LSA_REFRESH_INTERVAL_DEFAULT;
1272
1273 return 1;
1274}
1275
1276
paul4dadc292005-05-06 21:37:42 +00001277static struct ospf_nbr_nbma *
1278ospf_nbr_nbma_new (void)
paul718e3742002-12-13 20:15:29 +00001279{
1280 struct ospf_nbr_nbma *nbr_nbma;
1281
1282 nbr_nbma = XMALLOC (MTYPE_OSPF_NEIGHBOR_STATIC,
1283 sizeof (struct ospf_nbr_nbma));
1284 memset (nbr_nbma, 0, sizeof (struct ospf_nbr_nbma));
1285
1286 nbr_nbma->priority = OSPF_NEIGHBOR_PRIORITY_DEFAULT;
1287 nbr_nbma->v_poll = OSPF_POLL_INTERVAL_DEFAULT;
1288
1289 return nbr_nbma;
1290}
1291
paul4dadc292005-05-06 21:37:42 +00001292static void
paul718e3742002-12-13 20:15:29 +00001293ospf_nbr_nbma_free (struct ospf_nbr_nbma *nbr_nbma)
1294{
1295 XFREE (MTYPE_OSPF_NEIGHBOR_STATIC, nbr_nbma);
1296}
1297
paul4dadc292005-05-06 21:37:42 +00001298static void
paul718e3742002-12-13 20:15:29 +00001299ospf_nbr_nbma_delete (struct ospf *ospf, struct ospf_nbr_nbma *nbr_nbma)
1300{
1301 struct route_node *rn;
1302 struct prefix_ipv4 p;
1303
1304 p.family = AF_INET;
1305 p.prefix = nbr_nbma->addr;
1306 p.prefixlen = IPV4_MAX_BITLEN;
1307
1308 rn = route_node_lookup (ospf->nbr_nbma, (struct prefix *)&p);
1309 if (rn)
1310 {
1311 ospf_nbr_nbma_free (rn->info);
1312 rn->info = NULL;
1313 route_unlock_node (rn);
1314 route_unlock_node (rn);
1315 }
1316}
1317
paul4dadc292005-05-06 21:37:42 +00001318static void
paul718e3742002-12-13 20:15:29 +00001319ospf_nbr_nbma_down (struct ospf_nbr_nbma *nbr_nbma)
1320{
1321 OSPF_TIMER_OFF (nbr_nbma->t_poll);
1322
1323 if (nbr_nbma->nbr)
1324 {
1325 nbr_nbma->nbr->nbr_nbma = NULL;
1326 OSPF_NSM_EVENT_EXECUTE (nbr_nbma->nbr, NSM_KillNbr);
1327 }
1328
1329 if (nbr_nbma->oi)
1330 listnode_delete (nbr_nbma->oi->nbr_nbma, nbr_nbma);
1331}
1332
paul4dadc292005-05-06 21:37:42 +00001333static void
paul718e3742002-12-13 20:15:29 +00001334ospf_nbr_nbma_add (struct ospf_nbr_nbma *nbr_nbma,
1335 struct ospf_interface *oi)
1336{
1337 struct ospf_neighbor *nbr;
1338 struct route_node *rn;
1339 struct prefix p;
1340
1341 if (oi->type != OSPF_IFTYPE_NBMA)
1342 return;
1343
1344 if (nbr_nbma->nbr != NULL)
1345 return;
1346
1347 if (IPV4_ADDR_SAME (&oi->nbr_self->address.u.prefix4, &nbr_nbma->addr))
1348 return;
1349
1350 nbr_nbma->oi = oi;
1351 listnode_add (oi->nbr_nbma, nbr_nbma);
1352
1353 /* Get neighbor information from table. */
1354 p.family = AF_INET;
1355 p.prefixlen = IPV4_MAX_BITLEN;
1356 p.u.prefix4 = nbr_nbma->addr;
1357
1358 rn = route_node_get (oi->nbrs, (struct prefix *)&p);
1359 if (rn->info)
1360 {
1361 nbr = rn->info;
1362 nbr->nbr_nbma = nbr_nbma;
1363 nbr_nbma->nbr = nbr;
1364
1365 route_unlock_node (rn);
1366 }
1367 else
1368 {
1369 nbr = rn->info = ospf_nbr_new (oi);
1370 nbr->state = NSM_Down;
1371 nbr->src = nbr_nbma->addr;
1372 nbr->nbr_nbma = nbr_nbma;
1373 nbr->priority = nbr_nbma->priority;
1374 nbr->address = p;
1375
1376 nbr_nbma->nbr = nbr;
1377
1378 OSPF_NSM_EVENT_EXECUTE (nbr, NSM_Start);
1379 }
1380}
1381
1382void
paul68980082003-03-25 05:07:42 +00001383ospf_nbr_nbma_if_update (struct ospf *ospf, struct ospf_interface *oi)
paul718e3742002-12-13 20:15:29 +00001384{
1385 struct ospf_nbr_nbma *nbr_nbma;
1386 struct route_node *rn;
1387 struct prefix_ipv4 p;
1388
1389 if (oi->type != OSPF_IFTYPE_NBMA)
1390 return;
1391
paul68980082003-03-25 05:07:42 +00001392 for (rn = route_top (ospf->nbr_nbma); rn; rn = route_next (rn))
paul718e3742002-12-13 20:15:29 +00001393 if ((nbr_nbma = rn->info))
1394 if (nbr_nbma->oi == NULL && nbr_nbma->nbr == NULL)
1395 {
1396 p.family = AF_INET;
1397 p.prefix = nbr_nbma->addr;
1398 p.prefixlen = IPV4_MAX_BITLEN;
1399
1400 if (prefix_match (oi->address, (struct prefix *)&p))
1401 ospf_nbr_nbma_add (nbr_nbma, oi);
1402 }
1403}
1404
1405struct ospf_nbr_nbma *
1406ospf_nbr_nbma_lookup (struct ospf *ospf, struct in_addr nbr_addr)
1407{
1408 struct route_node *rn;
1409 struct prefix_ipv4 p;
1410
1411 p.family = AF_INET;
1412 p.prefix = nbr_addr;
1413 p.prefixlen = IPV4_MAX_BITLEN;
1414
1415 rn = route_node_lookup (ospf->nbr_nbma, (struct prefix *)&p);
1416 if (rn)
1417 {
1418 route_unlock_node (rn);
1419 return rn->info;
1420 }
1421 return NULL;
1422}
1423
1424struct ospf_nbr_nbma *
paul68980082003-03-25 05:07:42 +00001425ospf_nbr_nbma_lookup_next (struct ospf *ospf, struct in_addr *addr, int first)
paul718e3742002-12-13 20:15:29 +00001426{
1427#if 0
1428 struct ospf_nbr_nbma *nbr_nbma;
hasso52dc7ee2004-09-23 19:18:23 +00001429 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00001430#endif
1431
paul68980082003-03-25 05:07:42 +00001432 if (ospf == NULL)
paul718e3742002-12-13 20:15:29 +00001433 return NULL;
1434
1435#if 0
paul1eb8ef22005-04-07 07:30:20 +00001436 for (ALL_LIST_ELEMENTS_RO (ospf->nbr_nbma, node, nbr_nbma))
paul718e3742002-12-13 20:15:29 +00001437 {
paul718e3742002-12-13 20:15:29 +00001438 if (first)
1439 {
1440 *addr = nbr_nbma->addr;
1441 return nbr_nbma;
1442 }
1443 else if (ntohl (nbr_nbma->addr.s_addr) > ntohl (addr->s_addr))
1444 {
1445 *addr = nbr_nbma->addr;
1446 return nbr_nbma;
1447 }
1448 }
1449#endif
1450 return NULL;
1451}
1452
1453int
1454ospf_nbr_nbma_set (struct ospf *ospf, struct in_addr nbr_addr)
1455{
1456 struct ospf_nbr_nbma *nbr_nbma;
1457 struct ospf_interface *oi;
1458 struct prefix_ipv4 p;
1459 struct route_node *rn;
hasso52dc7ee2004-09-23 19:18:23 +00001460 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00001461
1462 nbr_nbma = ospf_nbr_nbma_lookup (ospf, nbr_addr);
1463 if (nbr_nbma)
1464 return 0;
1465
1466 nbr_nbma = ospf_nbr_nbma_new ();
1467 nbr_nbma->addr = nbr_addr;
1468
1469 p.family = AF_INET;
1470 p.prefix = nbr_addr;
1471 p.prefixlen = IPV4_MAX_BITLEN;
1472
1473 rn = route_node_get (ospf->nbr_nbma, (struct prefix *)&p);
1474 rn->info = nbr_nbma;
1475
paul1eb8ef22005-04-07 07:30:20 +00001476 for (ALL_LIST_ELEMENTS_RO (ospf->oiflist, node, oi))
paul718e3742002-12-13 20:15:29 +00001477 {
paul718e3742002-12-13 20:15:29 +00001478 if (oi->type == OSPF_IFTYPE_NBMA)
1479 if (prefix_match (oi->address, (struct prefix *)&p))
1480 {
1481 ospf_nbr_nbma_add (nbr_nbma, oi);
1482 break;
1483 }
1484 }
1485
1486 return 1;
1487}
1488
1489int
1490ospf_nbr_nbma_unset (struct ospf *ospf, struct in_addr nbr_addr)
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 ospf_nbr_nbma_down (nbr_nbma);
1499 ospf_nbr_nbma_delete (ospf, nbr_nbma);
1500
1501 return 1;
1502}
1503
1504int
1505ospf_nbr_nbma_priority_set (struct ospf *ospf, struct in_addr nbr_addr,
1506 u_char priority)
1507{
1508 struct ospf_nbr_nbma *nbr_nbma;
1509
1510 nbr_nbma = ospf_nbr_nbma_lookup (ospf, nbr_addr);
1511 if (nbr_nbma == NULL)
1512 return 0;
1513
1514 if (nbr_nbma->priority != priority)
1515 nbr_nbma->priority = priority;
1516
1517 return 1;
1518}
1519
1520int
1521ospf_nbr_nbma_priority_unset (struct ospf *ospf, struct in_addr nbr_addr)
1522{
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 != OSPF_NEIGHBOR_PRIORITY_DEFAULT)
1530 nbr_nbma->priority = OSPF_NEIGHBOR_PRIORITY_DEFAULT;
1531
1532 return 1;
1533}
1534
1535int
1536ospf_nbr_nbma_poll_interval_set (struct ospf *ospf, struct in_addr nbr_addr,
paul6c835672004-10-11 11:00:30 +00001537 unsigned int interval)
paul718e3742002-12-13 20:15:29 +00001538{
1539 struct ospf_nbr_nbma *nbr_nbma;
1540
1541 nbr_nbma = ospf_nbr_nbma_lookup (ospf, nbr_addr);
1542 if (nbr_nbma == NULL)
1543 return 0;
1544
1545 if (nbr_nbma->v_poll != interval)
1546 {
1547 nbr_nbma->v_poll = interval;
1548 if (nbr_nbma->oi && ospf_if_is_up (nbr_nbma->oi))
1549 {
1550 OSPF_TIMER_OFF (nbr_nbma->t_poll);
1551 OSPF_POLL_TIMER_ON (nbr_nbma->t_poll, ospf_poll_timer,
1552 nbr_nbma->v_poll);
1553 }
1554 }
1555
1556 return 1;
1557}
1558
1559int
1560ospf_nbr_nbma_poll_interval_unset (struct ospf *ospf, struct in_addr addr)
1561{
1562 struct ospf_nbr_nbma *nbr_nbma;
1563
1564 nbr_nbma = ospf_nbr_nbma_lookup (ospf, addr);
1565 if (nbr_nbma == NULL)
1566 return 0;
1567
1568 if (nbr_nbma->v_poll != OSPF_POLL_INTERVAL_DEFAULT)
1569 nbr_nbma->v_poll = OSPF_POLL_INTERVAL_DEFAULT;
1570
1571 return 1;
1572}
1573
paul718e3742002-12-13 20:15:29 +00001574void
paul020709f2003-04-04 02:44:16 +00001575ospf_master_init ()
1576{
1577 memset (&ospf_master, 0, sizeof (struct ospf_master));
1578
1579 om = &ospf_master;
1580 om->ospf = list_new ();
1581 om->master = thread_master_create ();
1582 om->start_time = time (NULL);
1583}