blob: 054c3316c3dc323e7032a92bf10829ec44e6b577 [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
hasso3fb9cd62004-10-19 19:44:43 +0000689 /* For PtP, match if peer address matches network address exactly
690 * in situations where the peer address is available and the prefix
691 * length is 32 (i.e. a dedicated subnet has not been assigned).
692 * This is not a test for falling within the prefix. This
gdt8f40e892003-12-05 14:01:43 +0000693 * test is solely for compatibility with zebra.
hasso3fb9cd62004-10-19 19:44:43 +0000694 *
695 * If not PtP, accept if the address is within the prefix.
gdt8f40e892003-12-05 14:01:43 +0000696 */
hasso3fb9cd62004-10-19 19:44:43 +0000697 return CONNECTED_POINTOPOINT_HOST(co) ?
698 IPV4_ADDR_SAME ( &(co->destination->u.prefix4), &(net->u.prefix4)) :
699 prefix_match (net, co->address);
paul570f7592003-01-25 06:47:41 +0000700}
701
paul718e3742002-12-13 20:15:29 +0000702void
703ospf_network_run (struct ospf *ospf, struct prefix *p, struct ospf_area *area)
704{
705 struct interface *ifp;
hasso52dc7ee2004-09-23 19:18:23 +0000706 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000707
708 /* Schedule Router ID Update. */
709 if (ospf->router_id_static.s_addr == 0)
710 if (ospf->t_router_id_update == NULL)
711 {
paul020709f2003-04-04 02:44:16 +0000712 OSPF_TIMER_ON (ospf->t_router_id_update, ospf_router_id_update_timer,
713 OSPF_ROUTER_ID_UPDATE_DELAY);
paul718e3742002-12-13 20:15:29 +0000714 }
715
716 /* Get target interface. */
paul020709f2003-04-04 02:44:16 +0000717 for (node = listhead (om->iflist); node; nextnode (node))
paul718e3742002-12-13 20:15:29 +0000718 {
hasso52dc7ee2004-09-23 19:18:23 +0000719 struct listnode *cn;
paul718e3742002-12-13 20:15:29 +0000720
721 if ((ifp = getdata (node)) == NULL)
722 continue;
723
724 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. */
729 for (cn = listhead (ifp->connected); cn; nextnode (cn))
730 {
731 struct connected *co = getdata (cn);
732 struct prefix *addr;
paul800dc102003-03-28 01:51:40 +0000733
paule7b050c2003-04-07 06:38:02 +0000734 if (CHECK_FLAG(co->flags,ZEBRA_IFA_SECONDARY))
735 continue;
paul718e3742002-12-13 20:15:29 +0000736
hasso3fb9cd62004-10-19 19:44:43 +0000737 if (CONNECTED_POINTOPOINT_HOST(co))
paul718e3742002-12-13 20:15:29 +0000738 addr = co->destination;
739 else
740 addr = co->address;
741
paulcb3f37d2003-02-18 23:26:37 +0000742 if (p->family == co->address->family
paul68980082003-03-25 05:07:42 +0000743 && ! ospf_if_is_configured (ospf, &(addr->u.prefix4))
paulcb3f37d2003-02-18 23:26:37 +0000744 && ospf_network_match_iface(co,p))
paul570f7592003-01-25 06:47:41 +0000745 {
paul537d8ea2003-08-27 06:45:32 +0000746 struct ospf_interface *oi;
paul718e3742002-12-13 20:15:29 +0000747
paul68980082003-03-25 05:07:42 +0000748 oi = ospf_if_new (ospf, ifp, co->address);
paul718e3742002-12-13 20:15:29 +0000749 oi->connected = co;
750
751 oi->nbr_self->address = *oi->address;
752
paul718e3742002-12-13 20:15:29 +0000753 oi->area = area;
754
755 oi->params = ospf_lookup_if_params (ifp, oi->address->u.prefix4);
756 oi->output_cost = ospf_if_get_output_cost (oi);
757
758 if (area->external_routing != OSPF_AREA_DEFAULT)
759 UNSET_FLAG (oi->nbr_self->options, OSPF_OPTION_E);
760 oi->nbr_self->priority = OSPF_IF_PARAM (oi, priority);
761
762 /* Add pseudo neighbor. */
763 ospf_nbr_add_self (oi);
764
765 /* Make sure pseudo neighbor's router_id. */
paul68980082003-03-25 05:07:42 +0000766 oi->nbr_self->router_id = ospf->router_id;
paul718e3742002-12-13 20:15:29 +0000767 oi->nbr_self->src = oi->address->u.prefix4;
768
769 /* Relate ospf interface to ospf instance. */
paul68980082003-03-25 05:07:42 +0000770 oi->ospf = ospf;
paul718e3742002-12-13 20:15:29 +0000771
772 /* update network type as interface flag */
773 /* If network type is specified previously,
774 skip network type setting. */
775 oi->type = IF_DEF_PARAMS (ifp)->type;
776
777 /* Set area flag. */
778 switch (area->external_routing)
779 {
780 case OSPF_AREA_DEFAULT:
781 SET_FLAG (oi->nbr_self->options, OSPF_OPTION_E);
782 break;
783 case OSPF_AREA_STUB:
784 UNSET_FLAG (oi->nbr_self->options, OSPF_OPTION_E);
785 break;
paul718e3742002-12-13 20:15:29 +0000786 case OSPF_AREA_NSSA:
787 UNSET_FLAG (oi->nbr_self->options, OSPF_OPTION_E);
788 SET_FLAG (oi->nbr_self->options, OSPF_OPTION_NP);
789 break;
paul718e3742002-12-13 20:15:29 +0000790 }
791
792 ospf_area_add_if (oi->area, oi);
793
paul2e3b2e42002-12-13 21:03:13 +0000794 if (if_is_operative (ifp))
paul718e3742002-12-13 20:15:29 +0000795 ospf_if_up (oi);
796
797 break;
798 }
799 }
800 }
801}
802
803void
804ospf_ls_upd_queue_empty (struct ospf_interface *oi)
805{
806 struct route_node *rn;
hasso52dc7ee2004-09-23 19:18:23 +0000807 struct listnode *node;
808 struct list *lst;
paul718e3742002-12-13 20:15:29 +0000809 struct ospf_lsa *lsa;
810
811 /* empty ls update queue */
812 for (rn = route_top (oi->ls_upd_queue); rn;
813 rn = route_next (rn))
hasso52dc7ee2004-09-23 19:18:23 +0000814 if ((lst = (struct list *) rn->info))
paul718e3742002-12-13 20:15:29 +0000815 {
816 for (node = listhead (lst); node; nextnode (node))
817 if ((lsa = getdata (node)))
818 ospf_lsa_unlock (lsa);
819 list_free (lst);
820 rn->info = NULL;
821 }
822
823 /* remove update event */
824 if (oi->t_ls_upd_event)
825 {
826 thread_cancel (oi->t_ls_upd_event);
827 oi->t_ls_upd_event = NULL;
828 }
829}
830
831void
paul68980082003-03-25 05:07:42 +0000832ospf_if_update (struct ospf *ospf)
paul718e3742002-12-13 20:15:29 +0000833{
834 struct route_node *rn;
hasso52dc7ee2004-09-23 19:18:23 +0000835 struct listnode *node;
836 struct listnode *next;
paul718e3742002-12-13 20:15:29 +0000837 struct ospf_network *network;
838 struct ospf_area *area;
839
paul68980082003-03-25 05:07:42 +0000840 if (ospf != NULL)
paul718e3742002-12-13 20:15:29 +0000841 {
842 /* Update Router ID scheduled. */
paul68980082003-03-25 05:07:42 +0000843 if (ospf->router_id_static.s_addr == 0)
844 if (ospf->t_router_id_update == NULL)
paul718e3742002-12-13 20:15:29 +0000845 {
paul020709f2003-04-04 02:44:16 +0000846 OSPF_TIMER_ON (ospf->t_router_id_update,
847 ospf_router_id_update_timer,
848 OSPF_ROUTER_ID_UPDATE_DELAY);
paul718e3742002-12-13 20:15:29 +0000849 }
850
851 /* Find interfaces that not configured already. */
paul68980082003-03-25 05:07:42 +0000852 for (node = listhead (ospf->oiflist); node; node = next)
paul718e3742002-12-13 20:15:29 +0000853 {
854 int found = 0;
855 struct ospf_interface *oi = getdata (node);
856 struct connected *co = oi->connected;
857
858 next = nextnode (node);
859
860 if (oi->type == OSPF_IFTYPE_VIRTUALLINK)
861 continue;
862
paul68980082003-03-25 05:07:42 +0000863 for (rn = route_top (ospf->networks); rn; rn = route_next (rn))
paul718e3742002-12-13 20:15:29 +0000864 {
865 if (rn->info == NULL)
866 continue;
867
paul570f7592003-01-25 06:47:41 +0000868 if (ospf_network_match_iface(co,&rn->p))
paul718e3742002-12-13 20:15:29 +0000869 {
870 found = 1;
871 route_unlock_node (rn);
872 break;
873 }
874 }
875
876 if (found == 0)
877 ospf_if_free (oi);
878 }
879
880 /* Run each interface. */
paul68980082003-03-25 05:07:42 +0000881 for (rn = route_top (ospf->networks); rn; rn = route_next (rn))
paul718e3742002-12-13 20:15:29 +0000882 if (rn->info != NULL)
883 {
884 network = (struct ospf_network *) rn->info;
paul68980082003-03-25 05:07:42 +0000885 area = ospf_area_get (ospf, network->area_id, network->format);
886 ospf_network_run (ospf, &rn->p, area);
paul718e3742002-12-13 20:15:29 +0000887 }
888 }
889}
890
891void
paul68980082003-03-25 05:07:42 +0000892ospf_remove_vls_through_area (struct ospf *ospf, struct ospf_area *area)
paul718e3742002-12-13 20:15:29 +0000893{
hasso52dc7ee2004-09-23 19:18:23 +0000894 struct listnode *node, *next;
paul718e3742002-12-13 20:15:29 +0000895 struct ospf_vl_data *vl_data;
896
paul68980082003-03-25 05:07:42 +0000897 for (node = listhead (ospf->vlinks); node; node = next)
paul718e3742002-12-13 20:15:29 +0000898 {
899 next = node->next;
900 if ((vl_data = getdata (node)) != NULL)
901 if (IPV4_ADDR_SAME (&vl_data->vl_area_id, &area->area_id))
paul68980082003-03-25 05:07:42 +0000902 ospf_vl_delete (ospf, vl_data);
paul718e3742002-12-13 20:15:29 +0000903 }
904}
905
906
907struct message ospf_area_type_msg[] =
908{
909 { OSPF_AREA_DEFAULT, "Default" },
910 { OSPF_AREA_STUB, "Stub" },
911 { OSPF_AREA_NSSA, "NSSA" },
912};
913int ospf_area_type_msg_max = OSPF_AREA_TYPE_MAX;
914
915void
916ospf_area_type_set (struct ospf_area *area, int type)
917{
hasso52dc7ee2004-09-23 19:18:23 +0000918 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000919 struct ospf_interface *oi;
920
921 if (area->external_routing == type)
922 {
923 if (IS_DEBUG_OSPF_EVENT)
924 zlog_info ("Area[%s]: Types are the same, ignored.",
925 inet_ntoa (area->area_id));
926 return;
927 }
928
929 area->external_routing = type;
930
931 if (IS_DEBUG_OSPF_EVENT)
932 zlog_info ("Area[%s]: Configured as %s", inet_ntoa (area->area_id),
933 LOOKUP (ospf_area_type_msg, type));
934
935 switch (area->external_routing)
936 {
937 case OSPF_AREA_DEFAULT:
938 for (node = listhead (area->oiflist); node; nextnode (node))
939 if ((oi = getdata (node)) != NULL)
940 if (oi->nbr_self != NULL)
hasso8585d4e2004-04-20 17:25:12 +0000941 {
hasso8585d4e2004-04-20 17:25:12 +0000942 UNSET_FLAG (oi->nbr_self->options, OSPF_OPTION_NP);
hasso8585d4e2004-04-20 17:25:12 +0000943 SET_FLAG (oi->nbr_self->options, OSPF_OPTION_E);
944 }
paul718e3742002-12-13 20:15:29 +0000945 break;
946 case OSPF_AREA_STUB:
947 for (node = listhead (area->oiflist); node; nextnode (node))
948 if ((oi = getdata (node)) != NULL)
949 if (oi->nbr_self != NULL)
950 {
951 if (IS_DEBUG_OSPF_EVENT)
952 zlog_info ("setting options on %s accordingly", IF_NAME (oi));
hasso8585d4e2004-04-20 17:25:12 +0000953 UNSET_FLAG (oi->nbr_self->options, OSPF_OPTION_NP);
paul718e3742002-12-13 20:15:29 +0000954 UNSET_FLAG (oi->nbr_self->options, OSPF_OPTION_E);
955 if (IS_DEBUG_OSPF_EVENT)
956 zlog_info ("options set on %s: %x",
957 IF_NAME (oi), OPTIONS (oi));
958 }
959 break;
960 case OSPF_AREA_NSSA:
paul718e3742002-12-13 20:15:29 +0000961 for (node = listhead (area->oiflist); node; nextnode (node))
962 if ((oi = getdata (node)) != NULL)
963 if (oi->nbr_self != NULL)
964 {
965 zlog_info ("setting nssa options on %s accordingly", IF_NAME (oi));
966 UNSET_FLAG (oi->nbr_self->options, OSPF_OPTION_E);
967 SET_FLAG (oi->nbr_self->options, OSPF_OPTION_NP);
968 zlog_info ("options set on %s: %x", IF_NAME (oi), OPTIONS (oi));
969 }
paul718e3742002-12-13 20:15:29 +0000970 break;
971 default:
972 break;
973 }
974
975 ospf_router_lsa_timer_add (area);
paul68980082003-03-25 05:07:42 +0000976 ospf_schedule_abr_task (area->ospf);
paul718e3742002-12-13 20:15:29 +0000977}
978
979int
paul68980082003-03-25 05:07:42 +0000980ospf_area_shortcut_set (struct ospf *ospf, struct ospf_area *area, int mode)
paul718e3742002-12-13 20:15:29 +0000981{
982 if (area->shortcut_configured == mode)
983 return 0;
984
985 area->shortcut_configured = mode;
986 ospf_router_lsa_timer_add (area);
paul68980082003-03-25 05:07:42 +0000987 ospf_schedule_abr_task (ospf);
paul718e3742002-12-13 20:15:29 +0000988
paul68980082003-03-25 05:07:42 +0000989 ospf_area_check_free (ospf, area->area_id);
paul718e3742002-12-13 20:15:29 +0000990
991 return 1;
992}
993
994int
paul68980082003-03-25 05:07:42 +0000995ospf_area_shortcut_unset (struct ospf *ospf, struct ospf_area *area)
paul718e3742002-12-13 20:15:29 +0000996{
997 area->shortcut_configured = OSPF_SHORTCUT_DEFAULT;
998 ospf_router_lsa_timer_add (area);
paul68980082003-03-25 05:07:42 +0000999 ospf_area_check_free (ospf, area->area_id);
1000 ospf_schedule_abr_task (ospf);
paul718e3742002-12-13 20:15:29 +00001001
1002 return 1;
1003}
1004
1005int
1006ospf_area_vlink_count (struct ospf *ospf, struct ospf_area *area)
1007{
1008 struct ospf_vl_data *vl;
hasso52dc7ee2004-09-23 19:18:23 +00001009 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00001010 int count = 0;
1011
1012 for (node = listhead (ospf->vlinks); node; nextnode (node))
1013 {
1014 vl = getdata (node);
1015 if (IPV4_ADDR_SAME (&vl->vl_area_id, &area->area_id))
1016 count++;
1017 }
1018
1019 return count;
1020}
1021
1022int
1023ospf_area_stub_set (struct ospf *ospf, struct in_addr area_id)
1024{
1025 struct ospf_area *area;
paul147193a2003-04-19 00:31:59 +00001026 int format = OSPF_AREA_ID_FORMAT_ADDRESS;
paul718e3742002-12-13 20:15:29 +00001027
paul68980082003-03-25 05:07:42 +00001028 area = ospf_area_get (ospf, area_id, format);
paul718e3742002-12-13 20:15:29 +00001029 if (ospf_area_vlink_count (ospf, area))
1030 return 0;
1031
1032 if (area->external_routing != OSPF_AREA_STUB)
1033 ospf_area_type_set (area, OSPF_AREA_STUB);
1034
1035 return 1;
1036}
1037
1038int
1039ospf_area_stub_unset (struct ospf *ospf, struct in_addr area_id)
1040{
1041 struct ospf_area *area;
1042
paul68980082003-03-25 05:07:42 +00001043 area = ospf_area_lookup_by_area_id (ospf, area_id);
paul718e3742002-12-13 20:15:29 +00001044 if (area == NULL)
1045 return 1;
1046
1047 if (area->external_routing == OSPF_AREA_STUB)
1048 ospf_area_type_set (area, OSPF_AREA_DEFAULT);
1049
paul68980082003-03-25 05:07:42 +00001050 ospf_area_check_free (ospf, area_id);
paul718e3742002-12-13 20:15:29 +00001051
1052 return 1;
1053}
1054
1055int
1056ospf_area_no_summary_set (struct ospf *ospf, struct in_addr area_id)
1057{
1058 struct ospf_area *area;
paul147193a2003-04-19 00:31:59 +00001059 int format = OSPF_AREA_ID_FORMAT_ADDRESS;
paul718e3742002-12-13 20:15:29 +00001060
paul68980082003-03-25 05:07:42 +00001061 area = ospf_area_get (ospf, area_id, format);
paul718e3742002-12-13 20:15:29 +00001062 area->no_summary = 1;
1063
1064 return 1;
1065}
1066
1067int
1068ospf_area_no_summary_unset (struct ospf *ospf, struct in_addr area_id)
1069{
1070 struct ospf_area *area;
1071
paul68980082003-03-25 05:07:42 +00001072 area = ospf_area_lookup_by_area_id (ospf, area_id);
paul718e3742002-12-13 20:15:29 +00001073 if (area == NULL)
1074 return 0;
1075
1076 area->no_summary = 0;
paul68980082003-03-25 05:07:42 +00001077 ospf_area_check_free (ospf, area_id);
paul718e3742002-12-13 20:15:29 +00001078
1079 return 1;
1080}
1081
1082int
1083ospf_area_nssa_set (struct ospf *ospf, struct in_addr area_id)
1084{
1085 struct ospf_area *area;
paul147193a2003-04-19 00:31:59 +00001086 int format = OSPF_AREA_ID_FORMAT_ADDRESS;
paul718e3742002-12-13 20:15:29 +00001087
paul68980082003-03-25 05:07:42 +00001088 area = ospf_area_get (ospf, area_id, format);
paul718e3742002-12-13 20:15:29 +00001089 if (ospf_area_vlink_count (ospf, area))
1090 return 0;
1091
1092 if (area->external_routing != OSPF_AREA_NSSA)
1093 {
1094 ospf_area_type_set (area, OSPF_AREA_NSSA);
1095 ospf->anyNSSA++;
1096 }
1097
paul084c7842003-06-22 08:35:18 +00001098 /* set NSSA area defaults */
1099 area->no_summary = 0;
1100 area->NSSATranslatorRole = OSPF_NSSA_ROLE_CANDIDATE;
pauld4a53d52003-07-12 21:30:57 +00001101 area->NSSATranslatorState = OSPF_NSSA_TRANSLATE_DISABLED;
paul084c7842003-06-22 08:35:18 +00001102 area->NSSATranslatorStabilityInterval = OSPF_NSSA_TRANS_STABLE_DEFAULT;
1103
paul718e3742002-12-13 20:15:29 +00001104 return 1;
1105}
1106
1107int
1108ospf_area_nssa_unset (struct ospf *ospf, struct in_addr area_id)
1109{
1110 struct ospf_area *area;
1111
paul68980082003-03-25 05:07:42 +00001112 area = ospf_area_lookup_by_area_id (ospf, area_id);
paul718e3742002-12-13 20:15:29 +00001113 if (area == NULL)
1114 return 0;
1115
1116 if (area->external_routing == OSPF_AREA_NSSA)
1117 {
1118 ospf->anyNSSA--;
1119 ospf_area_type_set (area, OSPF_AREA_DEFAULT);
1120 }
1121
paul68980082003-03-25 05:07:42 +00001122 ospf_area_check_free (ospf, area_id);
paul718e3742002-12-13 20:15:29 +00001123
1124 return 1;
1125}
1126
1127int
1128ospf_area_nssa_translator_role_set (struct ospf *ospf, struct in_addr area_id,
1129 int role)
1130{
1131 struct ospf_area *area;
1132
paul68980082003-03-25 05:07:42 +00001133 area = ospf_area_lookup_by_area_id (ospf, area_id);
paul718e3742002-12-13 20:15:29 +00001134 if (area == NULL)
1135 return 0;
1136
paul084c7842003-06-22 08:35:18 +00001137 area->NSSATranslatorRole = role;
paul718e3742002-12-13 20:15:29 +00001138
1139 return 1;
1140}
1141
1142int
1143ospf_area_nssa_translator_role_unset (struct ospf *ospf,
1144 struct in_addr area_id)
1145{
1146 struct ospf_area *area;
1147
paul68980082003-03-25 05:07:42 +00001148 area = ospf_area_lookup_by_area_id (ospf, area_id);
paul718e3742002-12-13 20:15:29 +00001149 if (area == NULL)
1150 return 0;
1151
paul084c7842003-06-22 08:35:18 +00001152 area->NSSATranslatorRole = OSPF_NSSA_ROLE_CANDIDATE;
paul718e3742002-12-13 20:15:29 +00001153
paul68980082003-03-25 05:07:42 +00001154 ospf_area_check_free (ospf, area_id);
paul718e3742002-12-13 20:15:29 +00001155
1156 return 1;
1157}
1158
1159int
paul68980082003-03-25 05:07:42 +00001160ospf_area_export_list_set (struct ospf *ospf,
paul6c835672004-10-11 11:00:30 +00001161 struct ospf_area *area, const char *list_name)
paul718e3742002-12-13 20:15:29 +00001162{
1163 struct access_list *list;
1164 list = access_list_lookup (AFI_IP, list_name);
1165
1166 EXPORT_LIST (area) = list;
1167
1168 if (EXPORT_NAME (area))
1169 free (EXPORT_NAME (area));
1170
1171 EXPORT_NAME (area) = strdup (list_name);
paul68980082003-03-25 05:07:42 +00001172 ospf_schedule_abr_task (ospf);
paul718e3742002-12-13 20:15:29 +00001173
1174 return 1;
1175}
1176
1177int
paul68980082003-03-25 05:07:42 +00001178ospf_area_export_list_unset (struct ospf *ospf, struct ospf_area * area)
paul718e3742002-12-13 20:15:29 +00001179{
1180
1181 EXPORT_LIST (area) = 0;
1182
1183 if (EXPORT_NAME (area))
1184 free (EXPORT_NAME (area));
1185
1186 EXPORT_NAME (area) = NULL;
1187
paul68980082003-03-25 05:07:42 +00001188 ospf_area_check_free (ospf, area->area_id);
paul718e3742002-12-13 20:15:29 +00001189
paul68980082003-03-25 05:07:42 +00001190 ospf_schedule_abr_task (ospf);
paul718e3742002-12-13 20:15:29 +00001191
1192 return 1;
1193}
1194
1195int
paul6c835672004-10-11 11:00:30 +00001196ospf_area_import_list_set (struct ospf *ospf, struct ospf_area *area,
1197 const char *name)
paul718e3742002-12-13 20:15:29 +00001198{
1199 struct access_list *list;
1200 list = access_list_lookup (AFI_IP, name);
1201
1202 IMPORT_LIST (area) = list;
1203
1204 if (IMPORT_NAME (area))
1205 free (IMPORT_NAME (area));
1206
1207 IMPORT_NAME (area) = strdup (name);
paul68980082003-03-25 05:07:42 +00001208 ospf_schedule_abr_task (ospf);
paul718e3742002-12-13 20:15:29 +00001209
1210 return 1;
1211}
1212
1213int
paul68980082003-03-25 05:07:42 +00001214ospf_area_import_list_unset (struct ospf *ospf, struct ospf_area * area)
paul718e3742002-12-13 20:15:29 +00001215{
1216 IMPORT_LIST (area) = 0;
1217
1218 if (IMPORT_NAME (area))
1219 free (IMPORT_NAME (area));
1220
1221 IMPORT_NAME (area) = NULL;
paul68980082003-03-25 05:07:42 +00001222 ospf_area_check_free (ospf, area->area_id);
paul718e3742002-12-13 20:15:29 +00001223
paul68980082003-03-25 05:07:42 +00001224 ospf_schedule_abr_task (ospf);
paul718e3742002-12-13 20:15:29 +00001225
1226 return 1;
1227}
1228
1229int
1230ospf_timers_spf_set (struct ospf *ospf, u_int32_t delay, u_int32_t hold)
1231{
1232 ospf->spf_delay = delay;
1233 ospf->spf_holdtime = hold;
1234
1235 return 1;
1236}
1237
1238int
1239ospf_timers_spf_unset (struct ospf *ospf)
1240{
1241 ospf->spf_delay = OSPF_SPF_DELAY_DEFAULT;
1242 ospf->spf_holdtime = OSPF_SPF_HOLDTIME_DEFAULT;
1243
1244 return 1;
1245}
1246
1247int
1248ospf_timers_refresh_set (struct ospf *ospf, int interval)
1249{
1250 int time_left;
1251
1252 if (ospf->lsa_refresh_interval == interval)
1253 return 1;
1254
1255 time_left = ospf->lsa_refresh_interval -
1256 (time (NULL) - ospf->lsa_refresher_started);
1257
1258 if (time_left > interval)
1259 {
1260 OSPF_TIMER_OFF (ospf->t_lsa_refresher);
1261 ospf->t_lsa_refresher =
1262 thread_add_timer (master, ospf_lsa_refresh_walker, ospf, interval);
1263 }
1264 ospf->lsa_refresh_interval = interval;
1265
1266 return 1;
1267}
1268
1269int
1270ospf_timers_refresh_unset (struct ospf *ospf)
1271{
1272 int time_left;
1273
1274 time_left = ospf->lsa_refresh_interval -
1275 (time (NULL) - ospf->lsa_refresher_started);
1276
1277 if (time_left > OSPF_LSA_REFRESH_INTERVAL_DEFAULT)
1278 {
1279 OSPF_TIMER_OFF (ospf->t_lsa_refresher);
1280 ospf->t_lsa_refresher =
1281 thread_add_timer (master, ospf_lsa_refresh_walker, ospf,
1282 OSPF_LSA_REFRESH_INTERVAL_DEFAULT);
1283 }
1284
1285 ospf->lsa_refresh_interval = OSPF_LSA_REFRESH_INTERVAL_DEFAULT;
1286
1287 return 1;
1288}
1289
1290
1291struct ospf_nbr_nbma *
1292ospf_nbr_nbma_new ()
1293{
1294 struct ospf_nbr_nbma *nbr_nbma;
1295
1296 nbr_nbma = XMALLOC (MTYPE_OSPF_NEIGHBOR_STATIC,
1297 sizeof (struct ospf_nbr_nbma));
1298 memset (nbr_nbma, 0, sizeof (struct ospf_nbr_nbma));
1299
1300 nbr_nbma->priority = OSPF_NEIGHBOR_PRIORITY_DEFAULT;
1301 nbr_nbma->v_poll = OSPF_POLL_INTERVAL_DEFAULT;
1302
1303 return nbr_nbma;
1304}
1305
1306void
1307ospf_nbr_nbma_free (struct ospf_nbr_nbma *nbr_nbma)
1308{
1309 XFREE (MTYPE_OSPF_NEIGHBOR_STATIC, nbr_nbma);
1310}
1311
1312void
1313ospf_nbr_nbma_delete (struct ospf *ospf, struct ospf_nbr_nbma *nbr_nbma)
1314{
1315 struct route_node *rn;
1316 struct prefix_ipv4 p;
1317
1318 p.family = AF_INET;
1319 p.prefix = nbr_nbma->addr;
1320 p.prefixlen = IPV4_MAX_BITLEN;
1321
1322 rn = route_node_lookup (ospf->nbr_nbma, (struct prefix *)&p);
1323 if (rn)
1324 {
1325 ospf_nbr_nbma_free (rn->info);
1326 rn->info = NULL;
1327 route_unlock_node (rn);
1328 route_unlock_node (rn);
1329 }
1330}
1331
1332void
1333ospf_nbr_nbma_down (struct ospf_nbr_nbma *nbr_nbma)
1334{
1335 OSPF_TIMER_OFF (nbr_nbma->t_poll);
1336
1337 if (nbr_nbma->nbr)
1338 {
1339 nbr_nbma->nbr->nbr_nbma = NULL;
1340 OSPF_NSM_EVENT_EXECUTE (nbr_nbma->nbr, NSM_KillNbr);
1341 }
1342
1343 if (nbr_nbma->oi)
1344 listnode_delete (nbr_nbma->oi->nbr_nbma, nbr_nbma);
1345}
1346
1347void
1348ospf_nbr_nbma_add (struct ospf_nbr_nbma *nbr_nbma,
1349 struct ospf_interface *oi)
1350{
1351 struct ospf_neighbor *nbr;
1352 struct route_node *rn;
1353 struct prefix p;
1354
1355 if (oi->type != OSPF_IFTYPE_NBMA)
1356 return;
1357
1358 if (nbr_nbma->nbr != NULL)
1359 return;
1360
1361 if (IPV4_ADDR_SAME (&oi->nbr_self->address.u.prefix4, &nbr_nbma->addr))
1362 return;
1363
1364 nbr_nbma->oi = oi;
1365 listnode_add (oi->nbr_nbma, nbr_nbma);
1366
1367 /* Get neighbor information from table. */
1368 p.family = AF_INET;
1369 p.prefixlen = IPV4_MAX_BITLEN;
1370 p.u.prefix4 = nbr_nbma->addr;
1371
1372 rn = route_node_get (oi->nbrs, (struct prefix *)&p);
1373 if (rn->info)
1374 {
1375 nbr = rn->info;
1376 nbr->nbr_nbma = nbr_nbma;
1377 nbr_nbma->nbr = nbr;
1378
1379 route_unlock_node (rn);
1380 }
1381 else
1382 {
1383 nbr = rn->info = ospf_nbr_new (oi);
1384 nbr->state = NSM_Down;
1385 nbr->src = nbr_nbma->addr;
1386 nbr->nbr_nbma = nbr_nbma;
1387 nbr->priority = nbr_nbma->priority;
1388 nbr->address = p;
1389
1390 nbr_nbma->nbr = nbr;
1391
1392 OSPF_NSM_EVENT_EXECUTE (nbr, NSM_Start);
1393 }
1394}
1395
1396void
paul68980082003-03-25 05:07:42 +00001397ospf_nbr_nbma_if_update (struct ospf *ospf, struct ospf_interface *oi)
paul718e3742002-12-13 20:15:29 +00001398{
1399 struct ospf_nbr_nbma *nbr_nbma;
1400 struct route_node *rn;
1401 struct prefix_ipv4 p;
1402
1403 if (oi->type != OSPF_IFTYPE_NBMA)
1404 return;
1405
paul68980082003-03-25 05:07:42 +00001406 for (rn = route_top (ospf->nbr_nbma); rn; rn = route_next (rn))
paul718e3742002-12-13 20:15:29 +00001407 if ((nbr_nbma = rn->info))
1408 if (nbr_nbma->oi == NULL && nbr_nbma->nbr == NULL)
1409 {
1410 p.family = AF_INET;
1411 p.prefix = nbr_nbma->addr;
1412 p.prefixlen = IPV4_MAX_BITLEN;
1413
1414 if (prefix_match (oi->address, (struct prefix *)&p))
1415 ospf_nbr_nbma_add (nbr_nbma, oi);
1416 }
1417}
1418
1419struct ospf_nbr_nbma *
1420ospf_nbr_nbma_lookup (struct ospf *ospf, struct in_addr nbr_addr)
1421{
1422 struct route_node *rn;
1423 struct prefix_ipv4 p;
1424
1425 p.family = AF_INET;
1426 p.prefix = nbr_addr;
1427 p.prefixlen = IPV4_MAX_BITLEN;
1428
1429 rn = route_node_lookup (ospf->nbr_nbma, (struct prefix *)&p);
1430 if (rn)
1431 {
1432 route_unlock_node (rn);
1433 return rn->info;
1434 }
1435 return NULL;
1436}
1437
1438struct ospf_nbr_nbma *
paul68980082003-03-25 05:07:42 +00001439ospf_nbr_nbma_lookup_next (struct ospf *ospf, struct in_addr *addr, int first)
paul718e3742002-12-13 20:15:29 +00001440{
1441#if 0
1442 struct ospf_nbr_nbma *nbr_nbma;
hasso52dc7ee2004-09-23 19:18:23 +00001443 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00001444#endif
1445
paul68980082003-03-25 05:07:42 +00001446 if (ospf == NULL)
paul718e3742002-12-13 20:15:29 +00001447 return NULL;
1448
1449#if 0
paul68980082003-03-25 05:07:42 +00001450 for (node = listhead (ospf->nbr_nbma); node; nextnode (node))
paul718e3742002-12-13 20:15:29 +00001451 {
1452 nbr_nbma = getdata (node);
1453
1454 if (first)
1455 {
1456 *addr = nbr_nbma->addr;
1457 return nbr_nbma;
1458 }
1459 else if (ntohl (nbr_nbma->addr.s_addr) > ntohl (addr->s_addr))
1460 {
1461 *addr = nbr_nbma->addr;
1462 return nbr_nbma;
1463 }
1464 }
1465#endif
1466 return NULL;
1467}
1468
1469int
1470ospf_nbr_nbma_set (struct ospf *ospf, struct in_addr nbr_addr)
1471{
1472 struct ospf_nbr_nbma *nbr_nbma;
1473 struct ospf_interface *oi;
1474 struct prefix_ipv4 p;
1475 struct route_node *rn;
hasso52dc7ee2004-09-23 19:18:23 +00001476 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00001477
1478 nbr_nbma = ospf_nbr_nbma_lookup (ospf, nbr_addr);
1479 if (nbr_nbma)
1480 return 0;
1481
1482 nbr_nbma = ospf_nbr_nbma_new ();
1483 nbr_nbma->addr = nbr_addr;
1484
1485 p.family = AF_INET;
1486 p.prefix = nbr_addr;
1487 p.prefixlen = IPV4_MAX_BITLEN;
1488
1489 rn = route_node_get (ospf->nbr_nbma, (struct prefix *)&p);
1490 rn->info = nbr_nbma;
1491
1492 for (node = listhead (ospf->oiflist); node; nextnode (node))
1493 {
1494 oi = getdata (node);
1495 if (oi->type == OSPF_IFTYPE_NBMA)
1496 if (prefix_match (oi->address, (struct prefix *)&p))
1497 {
1498 ospf_nbr_nbma_add (nbr_nbma, oi);
1499 break;
1500 }
1501 }
1502
1503 return 1;
1504}
1505
1506int
1507ospf_nbr_nbma_unset (struct ospf *ospf, struct in_addr nbr_addr)
1508{
1509 struct ospf_nbr_nbma *nbr_nbma;
1510
1511 nbr_nbma = ospf_nbr_nbma_lookup (ospf, nbr_addr);
1512 if (nbr_nbma == NULL)
1513 return 0;
1514
1515 ospf_nbr_nbma_down (nbr_nbma);
1516 ospf_nbr_nbma_delete (ospf, nbr_nbma);
1517
1518 return 1;
1519}
1520
1521int
1522ospf_nbr_nbma_priority_set (struct ospf *ospf, struct in_addr nbr_addr,
1523 u_char priority)
1524{
1525 struct ospf_nbr_nbma *nbr_nbma;
1526
1527 nbr_nbma = ospf_nbr_nbma_lookup (ospf, nbr_addr);
1528 if (nbr_nbma == NULL)
1529 return 0;
1530
1531 if (nbr_nbma->priority != priority)
1532 nbr_nbma->priority = priority;
1533
1534 return 1;
1535}
1536
1537int
1538ospf_nbr_nbma_priority_unset (struct ospf *ospf, struct in_addr nbr_addr)
1539{
1540 struct ospf_nbr_nbma *nbr_nbma;
1541
1542 nbr_nbma = ospf_nbr_nbma_lookup (ospf, nbr_addr);
1543 if (nbr_nbma == NULL)
1544 return 0;
1545
1546 if (nbr_nbma != OSPF_NEIGHBOR_PRIORITY_DEFAULT)
1547 nbr_nbma->priority = OSPF_NEIGHBOR_PRIORITY_DEFAULT;
1548
1549 return 1;
1550}
1551
1552int
1553ospf_nbr_nbma_poll_interval_set (struct ospf *ospf, struct in_addr nbr_addr,
paul6c835672004-10-11 11:00:30 +00001554 unsigned int interval)
paul718e3742002-12-13 20:15:29 +00001555{
1556 struct ospf_nbr_nbma *nbr_nbma;
1557
1558 nbr_nbma = ospf_nbr_nbma_lookup (ospf, nbr_addr);
1559 if (nbr_nbma == NULL)
1560 return 0;
1561
1562 if (nbr_nbma->v_poll != interval)
1563 {
1564 nbr_nbma->v_poll = interval;
1565 if (nbr_nbma->oi && ospf_if_is_up (nbr_nbma->oi))
1566 {
1567 OSPF_TIMER_OFF (nbr_nbma->t_poll);
1568 OSPF_POLL_TIMER_ON (nbr_nbma->t_poll, ospf_poll_timer,
1569 nbr_nbma->v_poll);
1570 }
1571 }
1572
1573 return 1;
1574}
1575
1576int
1577ospf_nbr_nbma_poll_interval_unset (struct ospf *ospf, struct in_addr addr)
1578{
1579 struct ospf_nbr_nbma *nbr_nbma;
1580
1581 nbr_nbma = ospf_nbr_nbma_lookup (ospf, addr);
1582 if (nbr_nbma == NULL)
1583 return 0;
1584
1585 if (nbr_nbma->v_poll != OSPF_POLL_INTERVAL_DEFAULT)
1586 nbr_nbma->v_poll = OSPF_POLL_INTERVAL_DEFAULT;
1587
1588 return 1;
1589}
1590
paul718e3742002-12-13 20:15:29 +00001591void
paul020709f2003-04-04 02:44:16 +00001592ospf_master_init ()
1593{
1594 memset (&ospf_master, 0, sizeof (struct ospf_master));
1595
1596 om = &ospf_master;
1597 om->ospf = list_new ();
1598 om->master = thread_master_create ();
1599 om->start_time = time (NULL);
1600}