blob: 0a988e0fafa225f989263bc69041b5f37f0bb06b [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;
hasso52dc7ee2004-09-23 19:18:23 +000078 struct listnode *node;
paul718e3742002-12-13 20:15:29 +000079
80 if (IS_DEBUG_OSPF_EVENT)
paul68980082003-03-25 05:07:42 +000081 zlog_info ("Router-ID[OLD:%s]: Update", inet_ntoa (ospf->router_id));
paul718e3742002-12-13 20:15:29 +000082
paul68980082003-03-25 05:07:42 +000083 router_id_old = ospf->router_id;
paul718e3742002-12-13 20:15:29 +000084
paul68980082003-03-25 05:07:42 +000085 if (ospf->router_id_static.s_addr != 0)
86 router_id = ospf->router_id_static;
paul718e3742002-12-13 20:15:29 +000087 else
hasso18a6dce2004-10-03 18:18:34 +000088 router_id = router_id_zebra;
paul718e3742002-12-13 20:15:29 +000089
paul68980082003-03-25 05:07:42 +000090 ospf->router_id = router_id;
paul718e3742002-12-13 20:15:29 +000091
92 if (IS_DEBUG_OSPF_EVENT)
paul68980082003-03-25 05:07:42 +000093 zlog_info ("Router-ID[NEW:%s]: Update", inet_ntoa (ospf->router_id));
paul718e3742002-12-13 20:15:29 +000094
95 if (!IPV4_ADDR_SAME (&router_id_old, &router_id))
96 {
paul68980082003-03-25 05:07:42 +000097 for (node = listhead (ospf->oiflist); node; nextnode (node))
paul718e3742002-12-13 20:15:29 +000098 {
99 struct ospf_interface *oi = getdata (node);
100
101 /* Update self-neighbor's router_id. */
102 oi->nbr_self->router_id = router_id;
103 }
104
105 /* If AS-external-LSA is queued, then flush those LSAs. */
paul68980082003-03-25 05:07:42 +0000106 if (router_id_old.s_addr == 0 && ospf->external_origin)
paul718e3742002-12-13 20:15:29 +0000107 {
108 int type;
109 /* Originate each redistributed external route. */
110 for (type = 0; type < ZEBRA_ROUTE_MAX; type++)
paul68980082003-03-25 05:07:42 +0000111 if (ospf->external_origin & (1 << type))
paul718e3742002-12-13 20:15:29 +0000112 thread_add_event (master, ospf_external_lsa_originate_timer,
paul68980082003-03-25 05:07:42 +0000113 ospf, type);
paul718e3742002-12-13 20:15:29 +0000114 /* Originate Deafult. */
paul68980082003-03-25 05:07:42 +0000115 if (ospf->external_origin & (1 << ZEBRA_ROUTE_MAX))
paul718e3742002-12-13 20:15:29 +0000116 thread_add_event (master, ospf_default_originate_timer,
paul68980082003-03-25 05:07:42 +0000117 &ospf->default_originate, 0);
paul718e3742002-12-13 20:15:29 +0000118
paul68980082003-03-25 05:07:42 +0000119 ospf->external_origin = 0;
paul718e3742002-12-13 20:15:29 +0000120 }
121
paul68980082003-03-25 05:07:42 +0000122 OSPF_TIMER_ON (ospf->t_router_lsa_update,
paul718e3742002-12-13 20:15:29 +0000123 ospf_router_lsa_update_timer, OSPF_LSA_UPDATE_DELAY);
124 }
125}
126
127int
128ospf_router_id_update_timer (struct thread *thread)
129{
paul020709f2003-04-04 02:44:16 +0000130 struct ospf *ospf = THREAD_ARG (thread);
paul68980082003-03-25 05:07:42 +0000131
paul718e3742002-12-13 20:15:29 +0000132 if (IS_DEBUG_OSPF_EVENT)
133 zlog_info ("Router-ID: Update timer fired!");
134
paul68980082003-03-25 05:07:42 +0000135 ospf->t_router_id_update = NULL;
136 ospf_router_id_update (ospf);
paul718e3742002-12-13 20:15:29 +0000137
138 return 0;
139}
140
141/* For OSPF area sort by area id. */
142int
143ospf_area_id_cmp (struct ospf_area *a1, struct ospf_area *a2)
144{
145 if (ntohl (a1->area_id.s_addr) > ntohl (a2->area_id.s_addr))
146 return 1;
147 if (ntohl (a1->area_id.s_addr) < ntohl (a2->area_id.s_addr))
148 return -1;
149 return 0;
150}
151
152/* Allocate new ospf structure. */
153struct ospf *
154ospf_new ()
155{
156 int i;
157
158 struct ospf *new = XCALLOC (MTYPE_OSPF_TOP, sizeof (struct ospf));
159
160 new->router_id.s_addr = htonl (0);
161 new->router_id_static.s_addr = htonl (0);
162
163 new->abr_type = OSPF_ABR_STAND;
paul718e3742002-12-13 20:15:29 +0000164 new->oiflist = list_new ();
165 new->vlinks = list_new ();
166 new->areas = list_new ();
167 new->areas->cmp = (int (*)(void *, void *)) ospf_area_id_cmp;
168 new->networks = route_table_init ();
169 new->nbr_nbma = route_table_init ();
170
171 new->lsdb = ospf_lsdb_new ();
172
173 new->default_originate = DEFAULT_ORIGINATE_NONE;
174
175 new->new_external_route = route_table_init ();
176 new->old_external_route = route_table_init ();
177 new->external_lsas = route_table_init ();
178
179 /* Distribute parameter init. */
180 for (i = 0; i <= ZEBRA_ROUTE_MAX; i++)
181 {
182 new->dmetric[i].type = -1;
183 new->dmetric[i].value = -1;
184 }
185 new->default_metric = -1;
186 new->ref_bandwidth = OSPF_DEFAULT_REF_BANDWIDTH;
187
188 /* SPF timer value init. */
189 new->spf_delay = OSPF_SPF_DELAY_DEFAULT;
190 new->spf_holdtime = OSPF_SPF_HOLDTIME_DEFAULT;
191
192 /* MaxAge init. */
193 new->maxage_lsa = list_new ();
194 new->t_maxage_walker =
195 thread_add_timer (master, ospf_lsa_maxage_walker,
paul68980082003-03-25 05:07:42 +0000196 new, OSPF_LSA_MAXAGE_CHECK_INTERVAL);
paul718e3742002-12-13 20:15:29 +0000197
198 /* Distance table init. */
199 new->distance_table = route_table_init ();
200
201 new->lsa_refresh_queue.index = 0;
202 new->lsa_refresh_interval = OSPF_LSA_REFRESH_INTERVAL_DEFAULT;
203 new->t_lsa_refresher = thread_add_timer (master, ospf_lsa_refresh_walker,
204 new, new->lsa_refresh_interval);
205 new->lsa_refresher_started = time (NULL);
206
207 new->fd = ospf_sock_init ();
208 if (new->fd >= 0)
209 new->t_read = thread_add_read (master, ospf_read, new, new->fd);
210 new->oi_write_q = list_new ();
211
212 return new;
213}
214
215struct ospf *
paul020709f2003-04-04 02:44:16 +0000216ospf_lookup ()
217{
218 if (listcount (om->ospf) == 0)
219 return NULL;
220
221 return getdata (listhead (om->ospf));
222}
223
224void
225ospf_add (struct ospf *ospf)
226{
227 listnode_add (om->ospf, ospf);
228}
229
230void
231ospf_delete (struct ospf *ospf)
232{
233 listnode_delete (om->ospf, ospf);
234}
235
236struct ospf *
paul718e3742002-12-13 20:15:29 +0000237ospf_get ()
238{
paul020709f2003-04-04 02:44:16 +0000239 struct ospf *ospf;
paul718e3742002-12-13 20:15:29 +0000240
paul020709f2003-04-04 02:44:16 +0000241 ospf = ospf_lookup ();
242 if (ospf == NULL)
243 {
244 ospf = ospf_new ();
245 ospf_add (ospf);
paul718e3742002-12-13 20:15:29 +0000246
paul020709f2003-04-04 02:44:16 +0000247 if (ospf->router_id_static.s_addr == 0)
248 ospf_router_id_update (ospf);
paul718e3742002-12-13 20:15:29 +0000249
250#ifdef HAVE_OPAQUE_LSA
paul020709f2003-04-04 02:44:16 +0000251 ospf_opaque_type11_lsa_init (ospf);
paul718e3742002-12-13 20:15:29 +0000252#endif /* HAVE_OPAQUE_LSA */
paul020709f2003-04-04 02:44:16 +0000253 }
paul68980082003-03-25 05:07:42 +0000254
255 return ospf;
paul718e3742002-12-13 20:15:29 +0000256}
257
258void
259ospf_finish (struct ospf *ospf)
260{
261 struct route_node *rn;
262 struct ospf_nbr_nbma *nbr_nbma;
paul68980082003-03-25 05:07:42 +0000263 struct ospf_lsa *lsa;
hasso52dc7ee2004-09-23 19:18:23 +0000264 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000265 int i;
266
267#ifdef HAVE_OPAQUE_LSA
268 ospf_opaque_type11_lsa_term (ospf);
269#endif /* HAVE_OPAQUE_LSA */
270
271 /* Unredister redistribution */
272 for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
paul020709f2003-04-04 02:44:16 +0000273 ospf_redistribute_unset (ospf, i);
paul718e3742002-12-13 20:15:29 +0000274
275 for (node = listhead (ospf->areas); node;)
276 {
277 struct ospf_area *area = getdata (node);
278 nextnode (node);
279
paul68980082003-03-25 05:07:42 +0000280 ospf_remove_vls_through_area (ospf, area);
paul718e3742002-12-13 20:15:29 +0000281 }
282
283 for (node = listhead (ospf->vlinks); node; )
284 {
285 struct ospf_vl_data *vl_data = node->data;
286 nextnode (node);
287
paul68980082003-03-25 05:07:42 +0000288 ospf_vl_delete (ospf, vl_data);
paul718e3742002-12-13 20:15:29 +0000289 }
290
291 list_delete (ospf->vlinks);
292
293 /* Reset interface. */
294 for (node = listhead (ospf->oiflist); node;)
295 {
296 struct ospf_interface *oi = getdata (node);
297 nextnode (node);
298
299 if (oi)
300 ospf_if_free (oi);
301 }
302
303 /* Clear static neighbors */
304 for (rn = route_top (ospf->nbr_nbma); rn; rn = route_next (rn))
305 if ((nbr_nbma = rn->info))
306 {
307 OSPF_POLL_TIMER_OFF (nbr_nbma->t_poll);
308
309 if (nbr_nbma->nbr)
310 {
311 nbr_nbma->nbr->nbr_nbma = NULL;
312 nbr_nbma->nbr = NULL;
313 }
314
315 if (nbr_nbma->oi)
316 {
317 listnode_delete (nbr_nbma->oi->nbr_nbma, nbr_nbma);
318 nbr_nbma->oi = NULL;
319 }
320
321 XFREE (MTYPE_OSPF_NEIGHBOR_STATIC, nbr_nbma);
322 }
323
324 route_table_finish (ospf->nbr_nbma);
325
326 /* Clear networks and Areas. */
327 for (rn = route_top (ospf->networks); rn; rn = route_next (rn))
328 {
329 struct ospf_network *network;
330
331 if ((network = rn->info) != NULL)
332 {
paul68980082003-03-25 05:07:42 +0000333 ospf_network_free (ospf, network);
paul718e3742002-12-13 20:15:29 +0000334 rn->info = NULL;
335 route_unlock_node (rn);
336 }
337 }
338
339 for (node = listhead (ospf->areas); node;)
340 {
341 struct ospf_area *area = getdata (node);
342 nextnode (node);
343
344 listnode_delete (ospf->areas, area);
345 ospf_area_free (area);
346 }
347
348 /* Cancel all timers. */
349 OSPF_TIMER_OFF (ospf->t_external_lsa);
350 OSPF_TIMER_OFF (ospf->t_router_id_update);
351 OSPF_TIMER_OFF (ospf->t_router_lsa_update);
352 OSPF_TIMER_OFF (ospf->t_spf_calc);
353 OSPF_TIMER_OFF (ospf->t_ase_calc);
354 OSPF_TIMER_OFF (ospf->t_maxage);
355 OSPF_TIMER_OFF (ospf->t_maxage_walker);
356 OSPF_TIMER_OFF (ospf->t_abr_task);
357 OSPF_TIMER_OFF (ospf->t_distribute_update);
358 OSPF_TIMER_OFF (ospf->t_lsa_refresher);
359 OSPF_TIMER_OFF (ospf->t_read);
360 OSPF_TIMER_OFF (ospf->t_write);
361
362 close (ospf->fd);
363
364#ifdef HAVE_OPAQUE_LSA
paul68980082003-03-25 05:07:42 +0000365 LSDB_LOOP (OPAQUE_AS_LSDB (ospf), rn, lsa)
366 ospf_discard_from_db (ospf, ospf->lsdb, lsa);
paul718e3742002-12-13 20:15:29 +0000367#endif /* HAVE_OPAQUE_LSA */
paul68980082003-03-25 05:07:42 +0000368 LSDB_LOOP (EXTERNAL_LSDB (ospf), rn, lsa)
369 ospf_discard_from_db (ospf, ospf->lsdb, lsa);
370
paul718e3742002-12-13 20:15:29 +0000371 ospf_lsdb_delete_all (ospf->lsdb);
372 ospf_lsdb_free (ospf->lsdb);
373
374 for (node = listhead (ospf->maxage_lsa); node; nextnode (node))
375 ospf_lsa_unlock (getdata (node));
376
377 list_delete (ospf->maxage_lsa);
378
379 if (ospf->old_table)
380 ospf_route_table_free (ospf->old_table);
381 if (ospf->new_table)
382 {
383 ospf_route_delete (ospf->new_table);
384 ospf_route_table_free (ospf->new_table);
385 }
386 if (ospf->old_rtrs)
387 ospf_rtrs_free (ospf->old_rtrs);
388 if (ospf->new_rtrs)
389 ospf_rtrs_free (ospf->new_rtrs);
390 if (ospf->new_external_route)
391 {
392 ospf_route_delete (ospf->new_external_route);
393 ospf_route_table_free (ospf->new_external_route);
394 }
395 if (ospf->old_external_route)
396 {
397 ospf_route_delete (ospf->old_external_route);
398 ospf_route_table_free (ospf->old_external_route);
399 }
400 if (ospf->external_lsas)
401 {
402 ospf_ase_external_lsas_finish (ospf->external_lsas);
403 }
404
405 list_delete (ospf->areas);
406
407 for (i = ZEBRA_ROUTE_SYSTEM; i <= ZEBRA_ROUTE_MAX; i++)
408 if (EXTERNAL_INFO (i) != NULL)
409 for (rn = route_top (EXTERNAL_INFO (i)); rn; rn = route_next (rn))
410 {
411 if (rn->info == NULL)
412 continue;
413
414 XFREE (MTYPE_OSPF_EXTERNAL_INFO, rn->info);
415 rn->info = NULL;
416 route_unlock_node (rn);
417 }
418
paul68980082003-03-25 05:07:42 +0000419 ospf_distance_reset (ospf);
paul718e3742002-12-13 20:15:29 +0000420 route_table_finish (ospf->distance_table);
421
paul020709f2003-04-04 02:44:16 +0000422 ospf_delete (ospf);
paul718e3742002-12-13 20:15:29 +0000423
paul020709f2003-04-04 02:44:16 +0000424 XFREE (MTYPE_OSPF_TOP, ospf);
paul718e3742002-12-13 20:15:29 +0000425}
426
427
428/* allocate new OSPF Area object */
429struct ospf_area *
paul68980082003-03-25 05:07:42 +0000430ospf_area_new (struct ospf *ospf, struct in_addr area_id)
paul718e3742002-12-13 20:15:29 +0000431{
432 struct ospf_area *new;
433
434 /* Allocate new config_network. */
435 new = XCALLOC (MTYPE_OSPF_AREA, sizeof (struct ospf_area));
436
paul68980082003-03-25 05:07:42 +0000437 new->ospf = ospf;
paul718e3742002-12-13 20:15:29 +0000438
439 new->area_id = area_id;
440
441 new->external_routing = OSPF_AREA_DEFAULT;
442 new->default_cost = 1;
443 new->auth_type = OSPF_AUTH_NULL;
444
445 /* New LSDB init. */
446 new->lsdb = ospf_lsdb_new ();
447
448 /* Self-originated LSAs initialize. */
449 new->router_lsa_self = NULL;
450
451#ifdef HAVE_OPAQUE_LSA
452 ospf_opaque_type10_lsa_init (new);
453#endif /* HAVE_OPAQUE_LSA */
454
455 new->oiflist = list_new ();
456 new->ranges = route_table_init ();
457
458 if (area_id.s_addr == OSPF_AREA_BACKBONE)
paul68980082003-03-25 05:07:42 +0000459 ospf->backbone = new;
paul718e3742002-12-13 20:15:29 +0000460
461 return new;
462}
463
464void
465ospf_area_free (struct ospf_area *area)
466{
paul68980082003-03-25 05:07:42 +0000467 struct route_node *rn;
468 struct ospf_lsa *lsa;
469
paul718e3742002-12-13 20:15:29 +0000470 /* Free LSDBs. */
paul68980082003-03-25 05:07:42 +0000471 LSDB_LOOP (ROUTER_LSDB (area), rn, lsa)
472 ospf_discard_from_db (area->ospf, area->lsdb, lsa);
473 LSDB_LOOP (NETWORK_LSDB (area), rn, lsa)
474 ospf_discard_from_db (area->ospf, area->lsdb, lsa);
475 LSDB_LOOP (SUMMARY_LSDB (area), rn, lsa)
476 ospf_discard_from_db (area->ospf, area->lsdb, lsa);
477 LSDB_LOOP (ASBR_SUMMARY_LSDB (area), rn, lsa)
478 ospf_discard_from_db (area->ospf, area->lsdb, lsa);
paul718e3742002-12-13 20:15:29 +0000479
paul68980082003-03-25 05:07:42 +0000480 LSDB_LOOP (NSSA_LSDB (area), rn, lsa)
481 ospf_discard_from_db (area->ospf, area->lsdb, lsa);
paul718e3742002-12-13 20:15:29 +0000482#ifdef HAVE_OPAQUE_LSA
paul68980082003-03-25 05:07:42 +0000483 LSDB_LOOP (OPAQUE_AREA_LSDB (area), rn, lsa)
484 ospf_discard_from_db (area->ospf, area->lsdb, lsa);
485 LSDB_LOOP (OPAQUE_LINK_LSDB (area), rn, lsa)
486 ospf_discard_from_db (area->ospf, area->lsdb, lsa);
paul718e3742002-12-13 20:15:29 +0000487#endif /* HAVE_OPAQUE_LSA */
488
489 ospf_lsdb_delete_all (area->lsdb);
490 ospf_lsdb_free (area->lsdb);
491
paul718e3742002-12-13 20:15:29 +0000492 ospf_lsa_unlock (area->router_lsa_self);
493
494 route_table_finish (area->ranges);
495 list_delete (area->oiflist);
496
497 if (EXPORT_NAME (area))
498 free (EXPORT_NAME (area));
499
500 if (IMPORT_NAME (area))
501 free (IMPORT_NAME (area));
502
503 /* Cancel timer. */
504 OSPF_TIMER_OFF (area->t_router_lsa_self);
505
506 if (OSPF_IS_AREA_BACKBONE (area))
paul68980082003-03-25 05:07:42 +0000507 area->ospf->backbone = NULL;
paul718e3742002-12-13 20:15:29 +0000508
509 XFREE (MTYPE_OSPF_AREA, area);
510}
511
512void
paul68980082003-03-25 05:07:42 +0000513ospf_area_check_free (struct ospf *ospf, struct in_addr area_id)
paul718e3742002-12-13 20:15:29 +0000514{
515 struct ospf_area *area;
516
paul68980082003-03-25 05:07:42 +0000517 area = ospf_area_lookup_by_area_id (ospf, area_id);
paul718e3742002-12-13 20:15:29 +0000518 if (area &&
519 listcount (area->oiflist) == 0 &&
520 area->ranges->top == NULL &&
521 area->shortcut_configured == OSPF_SHORTCUT_DEFAULT &&
522 area->external_routing == OSPF_AREA_DEFAULT &&
523 area->no_summary == 0 &&
524 area->default_cost == 1 &&
525 EXPORT_NAME (area) == NULL &&
526 IMPORT_NAME (area) == NULL &&
527 area->auth_type == OSPF_AUTH_NULL)
528 {
paul68980082003-03-25 05:07:42 +0000529 listnode_delete (ospf->areas, area);
paul718e3742002-12-13 20:15:29 +0000530 ospf_area_free (area);
531 }
532}
533
534struct ospf_area *
paul68980082003-03-25 05:07:42 +0000535ospf_area_get (struct ospf *ospf, struct in_addr area_id, int format)
paul718e3742002-12-13 20:15:29 +0000536{
537 struct ospf_area *area;
538
paul68980082003-03-25 05:07:42 +0000539 area = ospf_area_lookup_by_area_id (ospf, area_id);
paul718e3742002-12-13 20:15:29 +0000540 if (!area)
541 {
paul68980082003-03-25 05:07:42 +0000542 area = ospf_area_new (ospf, area_id);
paul718e3742002-12-13 20:15:29 +0000543 area->format = format;
paul68980082003-03-25 05:07:42 +0000544 listnode_add_sort (ospf->areas, area);
545 ospf_check_abr_status (ospf);
paul718e3742002-12-13 20:15:29 +0000546 }
547
548 return area;
549}
550
551struct ospf_area *
paul68980082003-03-25 05:07:42 +0000552ospf_area_lookup_by_area_id (struct ospf *ospf, struct in_addr area_id)
paul718e3742002-12-13 20:15:29 +0000553{
554 struct ospf_area *area;
hasso52dc7ee2004-09-23 19:18:23 +0000555 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000556
paul68980082003-03-25 05:07:42 +0000557 for (node = listhead (ospf->areas); node; nextnode (node))
paul718e3742002-12-13 20:15:29 +0000558 {
559 area = getdata (node);
560
561 if (IPV4_ADDR_SAME (&area->area_id, &area_id))
562 return area;
563 }
564
565 return NULL;
566}
567
568void
569ospf_area_add_if (struct ospf_area *area, struct ospf_interface *oi)
570{
571 listnode_add (area->oiflist, oi);
572}
573
574void
575ospf_area_del_if (struct ospf_area *area, struct ospf_interface *oi)
576{
577 listnode_delete (area->oiflist, oi);
578}
579
580
581/* Config network statement related functions. */
582struct ospf_network *
583ospf_network_new (struct in_addr area_id, int format)
584{
585 struct ospf_network *new;
586 new = XCALLOC (MTYPE_OSPF_NETWORK, sizeof (struct ospf_network));
587
588 new->area_id = area_id;
589 new->format = format;
590
591 return new;
592}
593
594void
paul68980082003-03-25 05:07:42 +0000595ospf_network_free (struct ospf *ospf, struct ospf_network *network)
paul718e3742002-12-13 20:15:29 +0000596{
paul68980082003-03-25 05:07:42 +0000597 ospf_area_check_free (ospf, network->area_id);
598 ospf_schedule_abr_task (ospf);
paul718e3742002-12-13 20:15:29 +0000599 XFREE (MTYPE_OSPF_NETWORK, network);
600}
601
602int
603ospf_network_set (struct ospf *ospf, struct prefix_ipv4 *p,
604 struct in_addr area_id)
605{
606 struct ospf_network *network;
607 struct ospf_area *area;
608 struct route_node *rn;
609 struct external_info *ei;
paul147193a2003-04-19 00:31:59 +0000610 int ret = OSPF_AREA_ID_FORMAT_ADDRESS;
paul718e3742002-12-13 20:15:29 +0000611
612 rn = route_node_get (ospf->networks, (struct prefix *)p);
613 if (rn->info)
614 {
615 /* There is already same network statement. */
616 route_unlock_node (rn);
617 return 0;
618 }
619
620 rn->info = network = ospf_network_new (area_id, ret);
paul68980082003-03-25 05:07:42 +0000621 area = ospf_area_get (ospf, area_id, ret);
paul718e3742002-12-13 20:15:29 +0000622
623 /* Run network config now. */
624 ospf_network_run (ospf, (struct prefix *)p, area);
625
626 /* Update connected redistribute. */
627 if (ospf_is_type_redistributed (ZEBRA_ROUTE_CONNECT))
628 if (EXTERNAL_INFO (ZEBRA_ROUTE_CONNECT))
629 for (rn = route_top (EXTERNAL_INFO (ZEBRA_ROUTE_CONNECT));
630 rn; rn = route_next (rn))
631 if ((ei = rn->info) != NULL)
paul68980082003-03-25 05:07:42 +0000632 if (ospf_external_info_find_lsa (ospf, &ei->p))
633 if (!ospf_distribute_check_connected (ospf, ei))
634 ospf_external_lsa_flush (ospf, ei->type, &ei->p,
paul718e3742002-12-13 20:15:29 +0000635 ei->ifindex, ei->nexthop);
636
paul68980082003-03-25 05:07:42 +0000637 ospf_area_check_free (ospf, area_id);
paul718e3742002-12-13 20:15:29 +0000638
639 return 1;
640}
641
642int
643ospf_network_unset (struct ospf *ospf, struct prefix_ipv4 *p,
644 struct in_addr area_id)
645{
646 struct route_node *rn;
647 struct ospf_network *network;
648 struct external_info *ei;
649
650 rn = route_node_lookup (ospf->networks, (struct prefix *)p);
651 if (rn == NULL)
652 return 0;
653
654 network = rn->info;
655 if (!IPV4_ADDR_SAME (&area_id, &network->area_id))
656 return 0;
657
paul68980082003-03-25 05:07:42 +0000658 ospf_network_free (ospf, rn->info);
paul718e3742002-12-13 20:15:29 +0000659 rn->info = NULL;
660 route_unlock_node (rn);
661
paul68980082003-03-25 05:07:42 +0000662 ospf_if_update (ospf);
paul718e3742002-12-13 20:15:29 +0000663
664 /* Update connected redistribute. */
665 if (ospf_is_type_redistributed (ZEBRA_ROUTE_CONNECT))
666 if (EXTERNAL_INFO (ZEBRA_ROUTE_CONNECT))
667 for (rn = route_top (EXTERNAL_INFO (ZEBRA_ROUTE_CONNECT));
668 rn; rn = route_next (rn))
669 if ((ei = rn->info) != NULL)
paul68980082003-03-25 05:07:42 +0000670 if (!ospf_external_info_find_lsa (ospf, &ei->p))
671 if (ospf_distribute_check_connected (ospf, ei))
672 ospf_external_lsa_originate (ospf, ei);
paul718e3742002-12-13 20:15:29 +0000673
674 return 1;
675}
676
paul570f7592003-01-25 06:47:41 +0000677/* Check whether interface matches given network
678 * returns: 1, true. 0, false
679 */
680int
681ospf_network_match_iface(struct connected *co, struct prefix *net)
682{
683 /* Behaviour to match both Cisco where:
684 * iface address lies within network specified -> ospf
685 * and zebra 0.9[2ish-3]:
686 * PtP special case: network specified == iface peer addr -> ospf
687 */
gdt8f40e892003-12-05 14:01:43 +0000688
689 /* For PtP, match if peer address matches network address exactly.
690 * This can be addr/32 or addr/p for p < 32, but the addr must match
691 * exactly; this is not a test for falling within the prefix. This
692 * test is solely for compatibility with zebra.
693 */
694 if (if_is_pointopoint (co->ifp) &&
695 IPV4_ADDR_SAME ( &(co->destination->u.prefix4), &(net->u.prefix4)))
696 return 1;
697
698#if 0
699 /* Decline to accept PtP if dst address does not match the
700 * prefix. (ifdefed out because this is a workaround, not the
701 * desired behavior.) */
702 if (if_is_pointopoint (co->ifp) &&
703 ! prefix_match (net, co->destination))
704 return 0;
705#endif
706
707 /* If the address is within the prefix, accept. Note that this
708 * applies to PtP as well as other types.
709 */
710 if (prefix_match (net, co->address))
711 return 1;
712
713 return 0; /* no match */
paul570f7592003-01-25 06:47:41 +0000714}
715
paul718e3742002-12-13 20:15:29 +0000716void
717ospf_network_run (struct ospf *ospf, struct prefix *p, struct ospf_area *area)
718{
719 struct interface *ifp;
hasso52dc7ee2004-09-23 19:18:23 +0000720 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000721
722 /* Schedule Router ID Update. */
723 if (ospf->router_id_static.s_addr == 0)
724 if (ospf->t_router_id_update == NULL)
725 {
paul020709f2003-04-04 02:44:16 +0000726 OSPF_TIMER_ON (ospf->t_router_id_update, ospf_router_id_update_timer,
727 OSPF_ROUTER_ID_UPDATE_DELAY);
paul718e3742002-12-13 20:15:29 +0000728 }
729
730 /* Get target interface. */
paul020709f2003-04-04 02:44:16 +0000731 for (node = listhead (om->iflist); node; nextnode (node))
paul718e3742002-12-13 20:15:29 +0000732 {
hasso52dc7ee2004-09-23 19:18:23 +0000733 struct listnode *cn;
paul718e3742002-12-13 20:15:29 +0000734
735 if ((ifp = getdata (node)) == NULL)
736 continue;
737
738 if (memcmp (ifp->name, "VLINK", 5) == 0)
739 continue;
740
741 /* if interface prefix is match specified prefix,
742 then create socket and join multicast group. */
743 for (cn = listhead (ifp->connected); cn; nextnode (cn))
744 {
745 struct connected *co = getdata (cn);
746 struct prefix *addr;
paul800dc102003-03-28 01:51:40 +0000747
paule7b050c2003-04-07 06:38:02 +0000748 if (CHECK_FLAG(co->flags,ZEBRA_IFA_SECONDARY))
749 continue;
paul718e3742002-12-13 20:15:29 +0000750
paul3738d8c2003-10-27 22:02:00 +0000751 if (if_is_pointopoint (co->ifp))
paul718e3742002-12-13 20:15:29 +0000752 addr = co->destination;
753 else
754 addr = co->address;
755
paulcb3f37d2003-02-18 23:26:37 +0000756 if (p->family == co->address->family
paul68980082003-03-25 05:07:42 +0000757 && ! ospf_if_is_configured (ospf, &(addr->u.prefix4))
paulcb3f37d2003-02-18 23:26:37 +0000758 && ospf_network_match_iface(co,p))
paul570f7592003-01-25 06:47:41 +0000759 {
paul537d8ea2003-08-27 06:45:32 +0000760 struct ospf_interface *oi;
paul718e3742002-12-13 20:15:29 +0000761
paul68980082003-03-25 05:07:42 +0000762 oi = ospf_if_new (ospf, ifp, co->address);
paul718e3742002-12-13 20:15:29 +0000763 oi->connected = co;
764
765 oi->nbr_self->address = *oi->address;
766
paul718e3742002-12-13 20:15:29 +0000767 oi->area = area;
768
769 oi->params = ospf_lookup_if_params (ifp, oi->address->u.prefix4);
770 oi->output_cost = ospf_if_get_output_cost (oi);
771
772 if (area->external_routing != OSPF_AREA_DEFAULT)
773 UNSET_FLAG (oi->nbr_self->options, OSPF_OPTION_E);
774 oi->nbr_self->priority = OSPF_IF_PARAM (oi, priority);
775
776 /* Add pseudo neighbor. */
777 ospf_nbr_add_self (oi);
778
779 /* Make sure pseudo neighbor's router_id. */
paul68980082003-03-25 05:07:42 +0000780 oi->nbr_self->router_id = ospf->router_id;
paul718e3742002-12-13 20:15:29 +0000781 oi->nbr_self->src = oi->address->u.prefix4;
782
783 /* Relate ospf interface to ospf instance. */
paul68980082003-03-25 05:07:42 +0000784 oi->ospf = ospf;
paul718e3742002-12-13 20:15:29 +0000785
786 /* update network type as interface flag */
787 /* If network type is specified previously,
788 skip network type setting. */
789 oi->type = IF_DEF_PARAMS (ifp)->type;
790
791 /* Set area flag. */
792 switch (area->external_routing)
793 {
794 case OSPF_AREA_DEFAULT:
795 SET_FLAG (oi->nbr_self->options, OSPF_OPTION_E);
796 break;
797 case OSPF_AREA_STUB:
798 UNSET_FLAG (oi->nbr_self->options, OSPF_OPTION_E);
799 break;
paul718e3742002-12-13 20:15:29 +0000800 case OSPF_AREA_NSSA:
801 UNSET_FLAG (oi->nbr_self->options, OSPF_OPTION_E);
802 SET_FLAG (oi->nbr_self->options, OSPF_OPTION_NP);
803 break;
paul718e3742002-12-13 20:15:29 +0000804 }
805
806 ospf_area_add_if (oi->area, oi);
807
paul2e3b2e42002-12-13 21:03:13 +0000808 if (if_is_operative (ifp))
paul718e3742002-12-13 20:15:29 +0000809 ospf_if_up (oi);
810
811 break;
812 }
813 }
814 }
815}
816
817void
818ospf_ls_upd_queue_empty (struct ospf_interface *oi)
819{
820 struct route_node *rn;
hasso52dc7ee2004-09-23 19:18:23 +0000821 struct listnode *node;
822 struct list *lst;
paul718e3742002-12-13 20:15:29 +0000823 struct ospf_lsa *lsa;
824
825 /* empty ls update queue */
826 for (rn = route_top (oi->ls_upd_queue); rn;
827 rn = route_next (rn))
hasso52dc7ee2004-09-23 19:18:23 +0000828 if ((lst = (struct list *) rn->info))
paul718e3742002-12-13 20:15:29 +0000829 {
830 for (node = listhead (lst); node; nextnode (node))
831 if ((lsa = getdata (node)))
832 ospf_lsa_unlock (lsa);
833 list_free (lst);
834 rn->info = NULL;
835 }
836
837 /* remove update event */
838 if (oi->t_ls_upd_event)
839 {
840 thread_cancel (oi->t_ls_upd_event);
841 oi->t_ls_upd_event = NULL;
842 }
843}
844
845void
paul68980082003-03-25 05:07:42 +0000846ospf_if_update (struct ospf *ospf)
paul718e3742002-12-13 20:15:29 +0000847{
848 struct route_node *rn;
hasso52dc7ee2004-09-23 19:18:23 +0000849 struct listnode *node;
850 struct listnode *next;
paul718e3742002-12-13 20:15:29 +0000851 struct ospf_network *network;
852 struct ospf_area *area;
853
paul68980082003-03-25 05:07:42 +0000854 if (ospf != NULL)
paul718e3742002-12-13 20:15:29 +0000855 {
856 /* Update Router ID scheduled. */
paul68980082003-03-25 05:07:42 +0000857 if (ospf->router_id_static.s_addr == 0)
858 if (ospf->t_router_id_update == NULL)
paul718e3742002-12-13 20:15:29 +0000859 {
paul020709f2003-04-04 02:44:16 +0000860 OSPF_TIMER_ON (ospf->t_router_id_update,
861 ospf_router_id_update_timer,
862 OSPF_ROUTER_ID_UPDATE_DELAY);
paul718e3742002-12-13 20:15:29 +0000863 }
864
865 /* Find interfaces that not configured already. */
paul68980082003-03-25 05:07:42 +0000866 for (node = listhead (ospf->oiflist); node; node = next)
paul718e3742002-12-13 20:15:29 +0000867 {
868 int found = 0;
869 struct ospf_interface *oi = getdata (node);
870 struct connected *co = oi->connected;
871
872 next = nextnode (node);
873
874 if (oi->type == OSPF_IFTYPE_VIRTUALLINK)
875 continue;
876
paul68980082003-03-25 05:07:42 +0000877 for (rn = route_top (ospf->networks); rn; rn = route_next (rn))
paul718e3742002-12-13 20:15:29 +0000878 {
879 if (rn->info == NULL)
880 continue;
881
paul570f7592003-01-25 06:47:41 +0000882 if (ospf_network_match_iface(co,&rn->p))
paul718e3742002-12-13 20:15:29 +0000883 {
884 found = 1;
885 route_unlock_node (rn);
886 break;
887 }
888 }
889
890 if (found == 0)
891 ospf_if_free (oi);
892 }
893
894 /* Run each interface. */
paul68980082003-03-25 05:07:42 +0000895 for (rn = route_top (ospf->networks); rn; rn = route_next (rn))
paul718e3742002-12-13 20:15:29 +0000896 if (rn->info != NULL)
897 {
898 network = (struct ospf_network *) rn->info;
paul68980082003-03-25 05:07:42 +0000899 area = ospf_area_get (ospf, network->area_id, network->format);
900 ospf_network_run (ospf, &rn->p, area);
paul718e3742002-12-13 20:15:29 +0000901 }
902 }
903}
904
905void
paul68980082003-03-25 05:07:42 +0000906ospf_remove_vls_through_area (struct ospf *ospf, struct ospf_area *area)
paul718e3742002-12-13 20:15:29 +0000907{
hasso52dc7ee2004-09-23 19:18:23 +0000908 struct listnode *node, *next;
paul718e3742002-12-13 20:15:29 +0000909 struct ospf_vl_data *vl_data;
910
paul68980082003-03-25 05:07:42 +0000911 for (node = listhead (ospf->vlinks); node; node = next)
paul718e3742002-12-13 20:15:29 +0000912 {
913 next = node->next;
914 if ((vl_data = getdata (node)) != NULL)
915 if (IPV4_ADDR_SAME (&vl_data->vl_area_id, &area->area_id))
paul68980082003-03-25 05:07:42 +0000916 ospf_vl_delete (ospf, vl_data);
paul718e3742002-12-13 20:15:29 +0000917 }
918}
919
920
921struct message ospf_area_type_msg[] =
922{
923 { OSPF_AREA_DEFAULT, "Default" },
924 { OSPF_AREA_STUB, "Stub" },
925 { OSPF_AREA_NSSA, "NSSA" },
926};
927int ospf_area_type_msg_max = OSPF_AREA_TYPE_MAX;
928
929void
930ospf_area_type_set (struct ospf_area *area, int type)
931{
hasso52dc7ee2004-09-23 19:18:23 +0000932 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000933 struct ospf_interface *oi;
934
935 if (area->external_routing == type)
936 {
937 if (IS_DEBUG_OSPF_EVENT)
938 zlog_info ("Area[%s]: Types are the same, ignored.",
939 inet_ntoa (area->area_id));
940 return;
941 }
942
943 area->external_routing = type;
944
945 if (IS_DEBUG_OSPF_EVENT)
946 zlog_info ("Area[%s]: Configured as %s", inet_ntoa (area->area_id),
947 LOOKUP (ospf_area_type_msg, type));
948
949 switch (area->external_routing)
950 {
951 case OSPF_AREA_DEFAULT:
952 for (node = listhead (area->oiflist); node; nextnode (node))
953 if ((oi = getdata (node)) != NULL)
954 if (oi->nbr_self != NULL)
hasso8585d4e2004-04-20 17:25:12 +0000955 {
hasso8585d4e2004-04-20 17:25:12 +0000956 UNSET_FLAG (oi->nbr_self->options, OSPF_OPTION_NP);
hasso8585d4e2004-04-20 17:25:12 +0000957 SET_FLAG (oi->nbr_self->options, OSPF_OPTION_E);
958 }
paul718e3742002-12-13 20:15:29 +0000959 break;
960 case OSPF_AREA_STUB:
961 for (node = listhead (area->oiflist); node; nextnode (node))
962 if ((oi = getdata (node)) != NULL)
963 if (oi->nbr_self != NULL)
964 {
965 if (IS_DEBUG_OSPF_EVENT)
966 zlog_info ("setting options on %s accordingly", IF_NAME (oi));
hasso8585d4e2004-04-20 17:25:12 +0000967 UNSET_FLAG (oi->nbr_self->options, OSPF_OPTION_NP);
paul718e3742002-12-13 20:15:29 +0000968 UNSET_FLAG (oi->nbr_self->options, OSPF_OPTION_E);
969 if (IS_DEBUG_OSPF_EVENT)
970 zlog_info ("options set on %s: %x",
971 IF_NAME (oi), OPTIONS (oi));
972 }
973 break;
974 case OSPF_AREA_NSSA:
paul718e3742002-12-13 20:15:29 +0000975 for (node = listhead (area->oiflist); node; nextnode (node))
976 if ((oi = getdata (node)) != NULL)
977 if (oi->nbr_self != NULL)
978 {
979 zlog_info ("setting nssa options on %s accordingly", IF_NAME (oi));
980 UNSET_FLAG (oi->nbr_self->options, OSPF_OPTION_E);
981 SET_FLAG (oi->nbr_self->options, OSPF_OPTION_NP);
982 zlog_info ("options set on %s: %x", IF_NAME (oi), OPTIONS (oi));
983 }
paul718e3742002-12-13 20:15:29 +0000984 break;
985 default:
986 break;
987 }
988
989 ospf_router_lsa_timer_add (area);
paul68980082003-03-25 05:07:42 +0000990 ospf_schedule_abr_task (area->ospf);
paul718e3742002-12-13 20:15:29 +0000991}
992
993int
paul68980082003-03-25 05:07:42 +0000994ospf_area_shortcut_set (struct ospf *ospf, struct ospf_area *area, int mode)
paul718e3742002-12-13 20:15:29 +0000995{
996 if (area->shortcut_configured == mode)
997 return 0;
998
999 area->shortcut_configured = mode;
1000 ospf_router_lsa_timer_add (area);
paul68980082003-03-25 05:07:42 +00001001 ospf_schedule_abr_task (ospf);
paul718e3742002-12-13 20:15:29 +00001002
paul68980082003-03-25 05:07:42 +00001003 ospf_area_check_free (ospf, area->area_id);
paul718e3742002-12-13 20:15:29 +00001004
1005 return 1;
1006}
1007
1008int
paul68980082003-03-25 05:07:42 +00001009ospf_area_shortcut_unset (struct ospf *ospf, struct ospf_area *area)
paul718e3742002-12-13 20:15:29 +00001010{
1011 area->shortcut_configured = OSPF_SHORTCUT_DEFAULT;
1012 ospf_router_lsa_timer_add (area);
paul68980082003-03-25 05:07:42 +00001013 ospf_area_check_free (ospf, area->area_id);
1014 ospf_schedule_abr_task (ospf);
paul718e3742002-12-13 20:15:29 +00001015
1016 return 1;
1017}
1018
1019int
1020ospf_area_vlink_count (struct ospf *ospf, struct ospf_area *area)
1021{
1022 struct ospf_vl_data *vl;
hasso52dc7ee2004-09-23 19:18:23 +00001023 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00001024 int count = 0;
1025
1026 for (node = listhead (ospf->vlinks); node; nextnode (node))
1027 {
1028 vl = getdata (node);
1029 if (IPV4_ADDR_SAME (&vl->vl_area_id, &area->area_id))
1030 count++;
1031 }
1032
1033 return count;
1034}
1035
1036int
1037ospf_area_stub_set (struct ospf *ospf, struct in_addr area_id)
1038{
1039 struct ospf_area *area;
paul147193a2003-04-19 00:31:59 +00001040 int format = OSPF_AREA_ID_FORMAT_ADDRESS;
paul718e3742002-12-13 20:15:29 +00001041
paul68980082003-03-25 05:07:42 +00001042 area = ospf_area_get (ospf, area_id, format);
paul718e3742002-12-13 20:15:29 +00001043 if (ospf_area_vlink_count (ospf, area))
1044 return 0;
1045
1046 if (area->external_routing != OSPF_AREA_STUB)
1047 ospf_area_type_set (area, OSPF_AREA_STUB);
1048
1049 return 1;
1050}
1051
1052int
1053ospf_area_stub_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 1;
1060
1061 if (area->external_routing == OSPF_AREA_STUB)
1062 ospf_area_type_set (area, OSPF_AREA_DEFAULT);
1063
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_no_summary_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 area->no_summary = 1;
1077
1078 return 1;
1079}
1080
1081int
1082ospf_area_no_summary_unset (struct ospf *ospf, struct in_addr area_id)
1083{
1084 struct ospf_area *area;
1085
paul68980082003-03-25 05:07:42 +00001086 area = ospf_area_lookup_by_area_id (ospf, area_id);
paul718e3742002-12-13 20:15:29 +00001087 if (area == NULL)
1088 return 0;
1089
1090 area->no_summary = 0;
paul68980082003-03-25 05:07:42 +00001091 ospf_area_check_free (ospf, area_id);
paul718e3742002-12-13 20:15:29 +00001092
1093 return 1;
1094}
1095
1096int
1097ospf_area_nssa_set (struct ospf *ospf, struct in_addr area_id)
1098{
1099 struct ospf_area *area;
paul147193a2003-04-19 00:31:59 +00001100 int format = OSPF_AREA_ID_FORMAT_ADDRESS;
paul718e3742002-12-13 20:15:29 +00001101
paul68980082003-03-25 05:07:42 +00001102 area = ospf_area_get (ospf, area_id, format);
paul718e3742002-12-13 20:15:29 +00001103 if (ospf_area_vlink_count (ospf, area))
1104 return 0;
1105
1106 if (area->external_routing != OSPF_AREA_NSSA)
1107 {
1108 ospf_area_type_set (area, OSPF_AREA_NSSA);
1109 ospf->anyNSSA++;
1110 }
1111
paul084c7842003-06-22 08:35:18 +00001112 /* set NSSA area defaults */
1113 area->no_summary = 0;
1114 area->NSSATranslatorRole = OSPF_NSSA_ROLE_CANDIDATE;
pauld4a53d52003-07-12 21:30:57 +00001115 area->NSSATranslatorState = OSPF_NSSA_TRANSLATE_DISABLED;
paul084c7842003-06-22 08:35:18 +00001116 area->NSSATranslatorStabilityInterval = OSPF_NSSA_TRANS_STABLE_DEFAULT;
1117
paul718e3742002-12-13 20:15:29 +00001118 return 1;
1119}
1120
1121int
1122ospf_area_nssa_unset (struct ospf *ospf, struct in_addr area_id)
1123{
1124 struct ospf_area *area;
1125
paul68980082003-03-25 05:07:42 +00001126 area = ospf_area_lookup_by_area_id (ospf, area_id);
paul718e3742002-12-13 20:15:29 +00001127 if (area == NULL)
1128 return 0;
1129
1130 if (area->external_routing == OSPF_AREA_NSSA)
1131 {
1132 ospf->anyNSSA--;
1133 ospf_area_type_set (area, OSPF_AREA_DEFAULT);
1134 }
1135
paul68980082003-03-25 05:07:42 +00001136 ospf_area_check_free (ospf, area_id);
paul718e3742002-12-13 20:15:29 +00001137
1138 return 1;
1139}
1140
1141int
1142ospf_area_nssa_translator_role_set (struct ospf *ospf, struct in_addr area_id,
1143 int role)
1144{
1145 struct ospf_area *area;
1146
paul68980082003-03-25 05:07:42 +00001147 area = ospf_area_lookup_by_area_id (ospf, area_id);
paul718e3742002-12-13 20:15:29 +00001148 if (area == NULL)
1149 return 0;
1150
paul084c7842003-06-22 08:35:18 +00001151 area->NSSATranslatorRole = role;
paul718e3742002-12-13 20:15:29 +00001152
1153 return 1;
1154}
1155
1156int
1157ospf_area_nssa_translator_role_unset (struct ospf *ospf,
1158 struct in_addr area_id)
1159{
1160 struct ospf_area *area;
1161
paul68980082003-03-25 05:07:42 +00001162 area = ospf_area_lookup_by_area_id (ospf, area_id);
paul718e3742002-12-13 20:15:29 +00001163 if (area == NULL)
1164 return 0;
1165
paul084c7842003-06-22 08:35:18 +00001166 area->NSSATranslatorRole = OSPF_NSSA_ROLE_CANDIDATE;
paul718e3742002-12-13 20:15:29 +00001167
paul68980082003-03-25 05:07:42 +00001168 ospf_area_check_free (ospf, area_id);
paul718e3742002-12-13 20:15:29 +00001169
1170 return 1;
1171}
1172
1173int
paul68980082003-03-25 05:07:42 +00001174ospf_area_export_list_set (struct ospf *ospf,
paul6c835672004-10-11 11:00:30 +00001175 struct ospf_area *area, const char *list_name)
paul718e3742002-12-13 20:15:29 +00001176{
1177 struct access_list *list;
1178 list = access_list_lookup (AFI_IP, list_name);
1179
1180 EXPORT_LIST (area) = list;
1181
1182 if (EXPORT_NAME (area))
1183 free (EXPORT_NAME (area));
1184
1185 EXPORT_NAME (area) = strdup (list_name);
paul68980082003-03-25 05:07:42 +00001186 ospf_schedule_abr_task (ospf);
paul718e3742002-12-13 20:15:29 +00001187
1188 return 1;
1189}
1190
1191int
paul68980082003-03-25 05:07:42 +00001192ospf_area_export_list_unset (struct ospf *ospf, struct ospf_area * area)
paul718e3742002-12-13 20:15:29 +00001193{
1194
1195 EXPORT_LIST (area) = 0;
1196
1197 if (EXPORT_NAME (area))
1198 free (EXPORT_NAME (area));
1199
1200 EXPORT_NAME (area) = NULL;
1201
paul68980082003-03-25 05:07:42 +00001202 ospf_area_check_free (ospf, area->area_id);
paul718e3742002-12-13 20:15:29 +00001203
paul68980082003-03-25 05:07:42 +00001204 ospf_schedule_abr_task (ospf);
paul718e3742002-12-13 20:15:29 +00001205
1206 return 1;
1207}
1208
1209int
paul6c835672004-10-11 11:00:30 +00001210ospf_area_import_list_set (struct ospf *ospf, struct ospf_area *area,
1211 const char *name)
paul718e3742002-12-13 20:15:29 +00001212{
1213 struct access_list *list;
1214 list = access_list_lookup (AFI_IP, name);
1215
1216 IMPORT_LIST (area) = list;
1217
1218 if (IMPORT_NAME (area))
1219 free (IMPORT_NAME (area));
1220
1221 IMPORT_NAME (area) = strdup (name);
paul68980082003-03-25 05:07:42 +00001222 ospf_schedule_abr_task (ospf);
paul718e3742002-12-13 20:15:29 +00001223
1224 return 1;
1225}
1226
1227int
paul68980082003-03-25 05:07:42 +00001228ospf_area_import_list_unset (struct ospf *ospf, struct ospf_area * area)
paul718e3742002-12-13 20:15:29 +00001229{
1230 IMPORT_LIST (area) = 0;
1231
1232 if (IMPORT_NAME (area))
1233 free (IMPORT_NAME (area));
1234
1235 IMPORT_NAME (area) = NULL;
paul68980082003-03-25 05:07:42 +00001236 ospf_area_check_free (ospf, area->area_id);
paul718e3742002-12-13 20:15:29 +00001237
paul68980082003-03-25 05:07:42 +00001238 ospf_schedule_abr_task (ospf);
paul718e3742002-12-13 20:15:29 +00001239
1240 return 1;
1241}
1242
1243int
1244ospf_timers_spf_set (struct ospf *ospf, u_int32_t delay, u_int32_t hold)
1245{
1246 ospf->spf_delay = delay;
1247 ospf->spf_holdtime = hold;
1248
1249 return 1;
1250}
1251
1252int
1253ospf_timers_spf_unset (struct ospf *ospf)
1254{
1255 ospf->spf_delay = OSPF_SPF_DELAY_DEFAULT;
1256 ospf->spf_holdtime = OSPF_SPF_HOLDTIME_DEFAULT;
1257
1258 return 1;
1259}
1260
1261int
1262ospf_timers_refresh_set (struct ospf *ospf, int interval)
1263{
1264 int time_left;
1265
1266 if (ospf->lsa_refresh_interval == interval)
1267 return 1;
1268
1269 time_left = ospf->lsa_refresh_interval -
1270 (time (NULL) - ospf->lsa_refresher_started);
1271
1272 if (time_left > interval)
1273 {
1274 OSPF_TIMER_OFF (ospf->t_lsa_refresher);
1275 ospf->t_lsa_refresher =
1276 thread_add_timer (master, ospf_lsa_refresh_walker, ospf, interval);
1277 }
1278 ospf->lsa_refresh_interval = interval;
1279
1280 return 1;
1281}
1282
1283int
1284ospf_timers_refresh_unset (struct ospf *ospf)
1285{
1286 int time_left;
1287
1288 time_left = ospf->lsa_refresh_interval -
1289 (time (NULL) - ospf->lsa_refresher_started);
1290
1291 if (time_left > OSPF_LSA_REFRESH_INTERVAL_DEFAULT)
1292 {
1293 OSPF_TIMER_OFF (ospf->t_lsa_refresher);
1294 ospf->t_lsa_refresher =
1295 thread_add_timer (master, ospf_lsa_refresh_walker, ospf,
1296 OSPF_LSA_REFRESH_INTERVAL_DEFAULT);
1297 }
1298
1299 ospf->lsa_refresh_interval = OSPF_LSA_REFRESH_INTERVAL_DEFAULT;
1300
1301 return 1;
1302}
1303
1304
1305struct ospf_nbr_nbma *
1306ospf_nbr_nbma_new ()
1307{
1308 struct ospf_nbr_nbma *nbr_nbma;
1309
1310 nbr_nbma = XMALLOC (MTYPE_OSPF_NEIGHBOR_STATIC,
1311 sizeof (struct ospf_nbr_nbma));
1312 memset (nbr_nbma, 0, sizeof (struct ospf_nbr_nbma));
1313
1314 nbr_nbma->priority = OSPF_NEIGHBOR_PRIORITY_DEFAULT;
1315 nbr_nbma->v_poll = OSPF_POLL_INTERVAL_DEFAULT;
1316
1317 return nbr_nbma;
1318}
1319
1320void
1321ospf_nbr_nbma_free (struct ospf_nbr_nbma *nbr_nbma)
1322{
1323 XFREE (MTYPE_OSPF_NEIGHBOR_STATIC, nbr_nbma);
1324}
1325
1326void
1327ospf_nbr_nbma_delete (struct ospf *ospf, struct ospf_nbr_nbma *nbr_nbma)
1328{
1329 struct route_node *rn;
1330 struct prefix_ipv4 p;
1331
1332 p.family = AF_INET;
1333 p.prefix = nbr_nbma->addr;
1334 p.prefixlen = IPV4_MAX_BITLEN;
1335
1336 rn = route_node_lookup (ospf->nbr_nbma, (struct prefix *)&p);
1337 if (rn)
1338 {
1339 ospf_nbr_nbma_free (rn->info);
1340 rn->info = NULL;
1341 route_unlock_node (rn);
1342 route_unlock_node (rn);
1343 }
1344}
1345
1346void
1347ospf_nbr_nbma_down (struct ospf_nbr_nbma *nbr_nbma)
1348{
1349 OSPF_TIMER_OFF (nbr_nbma->t_poll);
1350
1351 if (nbr_nbma->nbr)
1352 {
1353 nbr_nbma->nbr->nbr_nbma = NULL;
1354 OSPF_NSM_EVENT_EXECUTE (nbr_nbma->nbr, NSM_KillNbr);
1355 }
1356
1357 if (nbr_nbma->oi)
1358 listnode_delete (nbr_nbma->oi->nbr_nbma, nbr_nbma);
1359}
1360
1361void
1362ospf_nbr_nbma_add (struct ospf_nbr_nbma *nbr_nbma,
1363 struct ospf_interface *oi)
1364{
1365 struct ospf_neighbor *nbr;
1366 struct route_node *rn;
1367 struct prefix p;
1368
1369 if (oi->type != OSPF_IFTYPE_NBMA)
1370 return;
1371
1372 if (nbr_nbma->nbr != NULL)
1373 return;
1374
1375 if (IPV4_ADDR_SAME (&oi->nbr_self->address.u.prefix4, &nbr_nbma->addr))
1376 return;
1377
1378 nbr_nbma->oi = oi;
1379 listnode_add (oi->nbr_nbma, nbr_nbma);
1380
1381 /* Get neighbor information from table. */
1382 p.family = AF_INET;
1383 p.prefixlen = IPV4_MAX_BITLEN;
1384 p.u.prefix4 = nbr_nbma->addr;
1385
1386 rn = route_node_get (oi->nbrs, (struct prefix *)&p);
1387 if (rn->info)
1388 {
1389 nbr = rn->info;
1390 nbr->nbr_nbma = nbr_nbma;
1391 nbr_nbma->nbr = nbr;
1392
1393 route_unlock_node (rn);
1394 }
1395 else
1396 {
1397 nbr = rn->info = ospf_nbr_new (oi);
1398 nbr->state = NSM_Down;
1399 nbr->src = nbr_nbma->addr;
1400 nbr->nbr_nbma = nbr_nbma;
1401 nbr->priority = nbr_nbma->priority;
1402 nbr->address = p;
1403
1404 nbr_nbma->nbr = nbr;
1405
1406 OSPF_NSM_EVENT_EXECUTE (nbr, NSM_Start);
1407 }
1408}
1409
1410void
paul68980082003-03-25 05:07:42 +00001411ospf_nbr_nbma_if_update (struct ospf *ospf, struct ospf_interface *oi)
paul718e3742002-12-13 20:15:29 +00001412{
1413 struct ospf_nbr_nbma *nbr_nbma;
1414 struct route_node *rn;
1415 struct prefix_ipv4 p;
1416
1417 if (oi->type != OSPF_IFTYPE_NBMA)
1418 return;
1419
paul68980082003-03-25 05:07:42 +00001420 for (rn = route_top (ospf->nbr_nbma); rn; rn = route_next (rn))
paul718e3742002-12-13 20:15:29 +00001421 if ((nbr_nbma = rn->info))
1422 if (nbr_nbma->oi == NULL && nbr_nbma->nbr == NULL)
1423 {
1424 p.family = AF_INET;
1425 p.prefix = nbr_nbma->addr;
1426 p.prefixlen = IPV4_MAX_BITLEN;
1427
1428 if (prefix_match (oi->address, (struct prefix *)&p))
1429 ospf_nbr_nbma_add (nbr_nbma, oi);
1430 }
1431}
1432
1433struct ospf_nbr_nbma *
1434ospf_nbr_nbma_lookup (struct ospf *ospf, struct in_addr nbr_addr)
1435{
1436 struct route_node *rn;
1437 struct prefix_ipv4 p;
1438
1439 p.family = AF_INET;
1440 p.prefix = nbr_addr;
1441 p.prefixlen = IPV4_MAX_BITLEN;
1442
1443 rn = route_node_lookup (ospf->nbr_nbma, (struct prefix *)&p);
1444 if (rn)
1445 {
1446 route_unlock_node (rn);
1447 return rn->info;
1448 }
1449 return NULL;
1450}
1451
1452struct ospf_nbr_nbma *
paul68980082003-03-25 05:07:42 +00001453ospf_nbr_nbma_lookup_next (struct ospf *ospf, struct in_addr *addr, int first)
paul718e3742002-12-13 20:15:29 +00001454{
1455#if 0
1456 struct ospf_nbr_nbma *nbr_nbma;
hasso52dc7ee2004-09-23 19:18:23 +00001457 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00001458#endif
1459
paul68980082003-03-25 05:07:42 +00001460 if (ospf == NULL)
paul718e3742002-12-13 20:15:29 +00001461 return NULL;
1462
1463#if 0
paul68980082003-03-25 05:07:42 +00001464 for (node = listhead (ospf->nbr_nbma); node; nextnode (node))
paul718e3742002-12-13 20:15:29 +00001465 {
1466 nbr_nbma = getdata (node);
1467
1468 if (first)
1469 {
1470 *addr = nbr_nbma->addr;
1471 return nbr_nbma;
1472 }
1473 else if (ntohl (nbr_nbma->addr.s_addr) > ntohl (addr->s_addr))
1474 {
1475 *addr = nbr_nbma->addr;
1476 return nbr_nbma;
1477 }
1478 }
1479#endif
1480 return NULL;
1481}
1482
1483int
1484ospf_nbr_nbma_set (struct ospf *ospf, struct in_addr nbr_addr)
1485{
1486 struct ospf_nbr_nbma *nbr_nbma;
1487 struct ospf_interface *oi;
1488 struct prefix_ipv4 p;
1489 struct route_node *rn;
hasso52dc7ee2004-09-23 19:18:23 +00001490 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00001491
1492 nbr_nbma = ospf_nbr_nbma_lookup (ospf, nbr_addr);
1493 if (nbr_nbma)
1494 return 0;
1495
1496 nbr_nbma = ospf_nbr_nbma_new ();
1497 nbr_nbma->addr = nbr_addr;
1498
1499 p.family = AF_INET;
1500 p.prefix = nbr_addr;
1501 p.prefixlen = IPV4_MAX_BITLEN;
1502
1503 rn = route_node_get (ospf->nbr_nbma, (struct prefix *)&p);
1504 rn->info = nbr_nbma;
1505
1506 for (node = listhead (ospf->oiflist); node; nextnode (node))
1507 {
1508 oi = getdata (node);
1509 if (oi->type == OSPF_IFTYPE_NBMA)
1510 if (prefix_match (oi->address, (struct prefix *)&p))
1511 {
1512 ospf_nbr_nbma_add (nbr_nbma, oi);
1513 break;
1514 }
1515 }
1516
1517 return 1;
1518}
1519
1520int
1521ospf_nbr_nbma_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 ospf_nbr_nbma_down (nbr_nbma);
1530 ospf_nbr_nbma_delete (ospf, nbr_nbma);
1531
1532 return 1;
1533}
1534
1535int
1536ospf_nbr_nbma_priority_set (struct ospf *ospf, struct in_addr nbr_addr,
1537 u_char priority)
1538{
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->priority != priority)
1546 nbr_nbma->priority = priority;
1547
1548 return 1;
1549}
1550
1551int
1552ospf_nbr_nbma_priority_unset (struct ospf *ospf, struct in_addr nbr_addr)
1553{
1554 struct ospf_nbr_nbma *nbr_nbma;
1555
1556 nbr_nbma = ospf_nbr_nbma_lookup (ospf, nbr_addr);
1557 if (nbr_nbma == NULL)
1558 return 0;
1559
1560 if (nbr_nbma != OSPF_NEIGHBOR_PRIORITY_DEFAULT)
1561 nbr_nbma->priority = OSPF_NEIGHBOR_PRIORITY_DEFAULT;
1562
1563 return 1;
1564}
1565
1566int
1567ospf_nbr_nbma_poll_interval_set (struct ospf *ospf, struct in_addr nbr_addr,
paul6c835672004-10-11 11:00:30 +00001568 unsigned int interval)
paul718e3742002-12-13 20:15:29 +00001569{
1570 struct ospf_nbr_nbma *nbr_nbma;
1571
1572 nbr_nbma = ospf_nbr_nbma_lookup (ospf, nbr_addr);
1573 if (nbr_nbma == NULL)
1574 return 0;
1575
1576 if (nbr_nbma->v_poll != interval)
1577 {
1578 nbr_nbma->v_poll = interval;
1579 if (nbr_nbma->oi && ospf_if_is_up (nbr_nbma->oi))
1580 {
1581 OSPF_TIMER_OFF (nbr_nbma->t_poll);
1582 OSPF_POLL_TIMER_ON (nbr_nbma->t_poll, ospf_poll_timer,
1583 nbr_nbma->v_poll);
1584 }
1585 }
1586
1587 return 1;
1588}
1589
1590int
1591ospf_nbr_nbma_poll_interval_unset (struct ospf *ospf, struct in_addr addr)
1592{
1593 struct ospf_nbr_nbma *nbr_nbma;
1594
1595 nbr_nbma = ospf_nbr_nbma_lookup (ospf, addr);
1596 if (nbr_nbma == NULL)
1597 return 0;
1598
1599 if (nbr_nbma->v_poll != OSPF_POLL_INTERVAL_DEFAULT)
1600 nbr_nbma->v_poll = OSPF_POLL_INTERVAL_DEFAULT;
1601
1602 return 1;
1603}
1604
paul718e3742002-12-13 20:15:29 +00001605void
paul020709f2003-04-04 02:44:16 +00001606ospf_master_init ()
1607{
1608 memset (&ospf_master, 0, sizeof (struct ospf_master));
1609
1610 om = &ospf_master;
1611 om->ospf = list_new ();
1612 om->master = thread_master_create ();
1613 om->start_time = time (NULL);
1614}