blob: a77fb4b16d71a6169f5a6bb652b9afa73c639bd5 [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)
ajs9b0e25c2004-12-08 19:06:51 +000081 zlog_debug ("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)
ajs9b0e25c2004-12-08 19:06:51 +000093 zlog_debug ("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)
ajs9b0e25c2004-12-08 19:06:51 +0000133 zlog_debug ("Router-ID: Update timer fired!");
paul718e3742002-12-13 20:15:29 +0000134
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
ajs5c333492005-02-23 15:43:01 +0000207 if ((new->fd = ospf_sock_init()) < 0)
208 {
209 zlog_err("ospf_new: fatal error: ospf_sock_init was unable to open "
210 "a socket");
211 exit(1);
212 }
213 if ((new->ibuf = stream_new(OSPF_MAX_PACKET_SIZE+1)) == NULL)
214 {
215 zlog_err("ospf_new: fatal error: stream_new(%u) failed allocating ibuf",
216 OSPF_MAX_PACKET_SIZE+1);
217 exit(1);
218 }
219 new->t_read = thread_add_read (master, ospf_read, new, new->fd);
paul718e3742002-12-13 20:15:29 +0000220 new->oi_write_q = list_new ();
221
222 return new;
223}
224
225struct ospf *
paul020709f2003-04-04 02:44:16 +0000226ospf_lookup ()
227{
228 if (listcount (om->ospf) == 0)
229 return NULL;
230
231 return getdata (listhead (om->ospf));
232}
233
234void
235ospf_add (struct ospf *ospf)
236{
237 listnode_add (om->ospf, ospf);
238}
239
240void
241ospf_delete (struct ospf *ospf)
242{
243 listnode_delete (om->ospf, ospf);
244}
245
246struct ospf *
paul718e3742002-12-13 20:15:29 +0000247ospf_get ()
248{
paul020709f2003-04-04 02:44:16 +0000249 struct ospf *ospf;
paul718e3742002-12-13 20:15:29 +0000250
paul020709f2003-04-04 02:44:16 +0000251 ospf = ospf_lookup ();
252 if (ospf == NULL)
253 {
254 ospf = ospf_new ();
255 ospf_add (ospf);
paul718e3742002-12-13 20:15:29 +0000256
paul020709f2003-04-04 02:44:16 +0000257 if (ospf->router_id_static.s_addr == 0)
258 ospf_router_id_update (ospf);
paul718e3742002-12-13 20:15:29 +0000259
260#ifdef HAVE_OPAQUE_LSA
paul020709f2003-04-04 02:44:16 +0000261 ospf_opaque_type11_lsa_init (ospf);
paul718e3742002-12-13 20:15:29 +0000262#endif /* HAVE_OPAQUE_LSA */
paul020709f2003-04-04 02:44:16 +0000263 }
paul68980082003-03-25 05:07:42 +0000264
265 return ospf;
paul718e3742002-12-13 20:15:29 +0000266}
267
268void
269ospf_finish (struct ospf *ospf)
270{
271 struct route_node *rn;
272 struct ospf_nbr_nbma *nbr_nbma;
paul68980082003-03-25 05:07:42 +0000273 struct ospf_lsa *lsa;
hasso52dc7ee2004-09-23 19:18:23 +0000274 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000275 int i;
276
277#ifdef HAVE_OPAQUE_LSA
278 ospf_opaque_type11_lsa_term (ospf);
279#endif /* HAVE_OPAQUE_LSA */
280
281 /* Unredister redistribution */
282 for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
paul020709f2003-04-04 02:44:16 +0000283 ospf_redistribute_unset (ospf, i);
paul718e3742002-12-13 20:15:29 +0000284
285 for (node = listhead (ospf->areas); node;)
286 {
287 struct ospf_area *area = getdata (node);
288 nextnode (node);
289
paul68980082003-03-25 05:07:42 +0000290 ospf_remove_vls_through_area (ospf, area);
paul718e3742002-12-13 20:15:29 +0000291 }
292
293 for (node = listhead (ospf->vlinks); node; )
294 {
295 struct ospf_vl_data *vl_data = node->data;
296 nextnode (node);
297
paul68980082003-03-25 05:07:42 +0000298 ospf_vl_delete (ospf, vl_data);
paul718e3742002-12-13 20:15:29 +0000299 }
300
301 list_delete (ospf->vlinks);
302
303 /* Reset interface. */
304 for (node = listhead (ospf->oiflist); node;)
305 {
306 struct ospf_interface *oi = getdata (node);
307 nextnode (node);
308
309 if (oi)
310 ospf_if_free (oi);
311 }
312
313 /* Clear static neighbors */
314 for (rn = route_top (ospf->nbr_nbma); rn; rn = route_next (rn))
315 if ((nbr_nbma = rn->info))
316 {
317 OSPF_POLL_TIMER_OFF (nbr_nbma->t_poll);
318
319 if (nbr_nbma->nbr)
320 {
321 nbr_nbma->nbr->nbr_nbma = NULL;
322 nbr_nbma->nbr = NULL;
323 }
324
325 if (nbr_nbma->oi)
326 {
327 listnode_delete (nbr_nbma->oi->nbr_nbma, nbr_nbma);
328 nbr_nbma->oi = NULL;
329 }
330
331 XFREE (MTYPE_OSPF_NEIGHBOR_STATIC, nbr_nbma);
332 }
333
334 route_table_finish (ospf->nbr_nbma);
335
336 /* Clear networks and Areas. */
337 for (rn = route_top (ospf->networks); rn; rn = route_next (rn))
338 {
339 struct ospf_network *network;
340
341 if ((network = rn->info) != NULL)
342 {
paul68980082003-03-25 05:07:42 +0000343 ospf_network_free (ospf, network);
paul718e3742002-12-13 20:15:29 +0000344 rn->info = NULL;
345 route_unlock_node (rn);
346 }
347 }
348
349 for (node = listhead (ospf->areas); node;)
350 {
351 struct ospf_area *area = getdata (node);
352 nextnode (node);
353
354 listnode_delete (ospf->areas, area);
355 ospf_area_free (area);
356 }
357
358 /* Cancel all timers. */
359 OSPF_TIMER_OFF (ospf->t_external_lsa);
360 OSPF_TIMER_OFF (ospf->t_router_id_update);
361 OSPF_TIMER_OFF (ospf->t_router_lsa_update);
362 OSPF_TIMER_OFF (ospf->t_spf_calc);
363 OSPF_TIMER_OFF (ospf->t_ase_calc);
364 OSPF_TIMER_OFF (ospf->t_maxage);
365 OSPF_TIMER_OFF (ospf->t_maxage_walker);
366 OSPF_TIMER_OFF (ospf->t_abr_task);
367 OSPF_TIMER_OFF (ospf->t_distribute_update);
368 OSPF_TIMER_OFF (ospf->t_lsa_refresher);
369 OSPF_TIMER_OFF (ospf->t_read);
370 OSPF_TIMER_OFF (ospf->t_write);
371
372 close (ospf->fd);
ajs5c333492005-02-23 15:43:01 +0000373 stream_free(ospf->ibuf);
paul718e3742002-12-13 20:15:29 +0000374
375#ifdef HAVE_OPAQUE_LSA
paul68980082003-03-25 05:07:42 +0000376 LSDB_LOOP (OPAQUE_AS_LSDB (ospf), rn, lsa)
377 ospf_discard_from_db (ospf, ospf->lsdb, lsa);
paul718e3742002-12-13 20:15:29 +0000378#endif /* HAVE_OPAQUE_LSA */
paul68980082003-03-25 05:07:42 +0000379 LSDB_LOOP (EXTERNAL_LSDB (ospf), rn, lsa)
380 ospf_discard_from_db (ospf, ospf->lsdb, lsa);
381
paul718e3742002-12-13 20:15:29 +0000382 ospf_lsdb_delete_all (ospf->lsdb);
383 ospf_lsdb_free (ospf->lsdb);
384
385 for (node = listhead (ospf->maxage_lsa); node; nextnode (node))
386 ospf_lsa_unlock (getdata (node));
387
388 list_delete (ospf->maxage_lsa);
389
390 if (ospf->old_table)
391 ospf_route_table_free (ospf->old_table);
392 if (ospf->new_table)
393 {
394 ospf_route_delete (ospf->new_table);
395 ospf_route_table_free (ospf->new_table);
396 }
397 if (ospf->old_rtrs)
398 ospf_rtrs_free (ospf->old_rtrs);
399 if (ospf->new_rtrs)
400 ospf_rtrs_free (ospf->new_rtrs);
401 if (ospf->new_external_route)
402 {
403 ospf_route_delete (ospf->new_external_route);
404 ospf_route_table_free (ospf->new_external_route);
405 }
406 if (ospf->old_external_route)
407 {
408 ospf_route_delete (ospf->old_external_route);
409 ospf_route_table_free (ospf->old_external_route);
410 }
411 if (ospf->external_lsas)
412 {
413 ospf_ase_external_lsas_finish (ospf->external_lsas);
414 }
415
416 list_delete (ospf->areas);
417
418 for (i = ZEBRA_ROUTE_SYSTEM; i <= ZEBRA_ROUTE_MAX; i++)
419 if (EXTERNAL_INFO (i) != NULL)
420 for (rn = route_top (EXTERNAL_INFO (i)); rn; rn = route_next (rn))
421 {
422 if (rn->info == NULL)
423 continue;
424
425 XFREE (MTYPE_OSPF_EXTERNAL_INFO, rn->info);
426 rn->info = NULL;
427 route_unlock_node (rn);
428 }
429
paul68980082003-03-25 05:07:42 +0000430 ospf_distance_reset (ospf);
paul718e3742002-12-13 20:15:29 +0000431 route_table_finish (ospf->distance_table);
432
paul020709f2003-04-04 02:44:16 +0000433 ospf_delete (ospf);
paul718e3742002-12-13 20:15:29 +0000434
paul020709f2003-04-04 02:44:16 +0000435 XFREE (MTYPE_OSPF_TOP, ospf);
paul718e3742002-12-13 20:15:29 +0000436}
437
438
439/* allocate new OSPF Area object */
440struct ospf_area *
paul68980082003-03-25 05:07:42 +0000441ospf_area_new (struct ospf *ospf, struct in_addr area_id)
paul718e3742002-12-13 20:15:29 +0000442{
443 struct ospf_area *new;
444
445 /* Allocate new config_network. */
446 new = XCALLOC (MTYPE_OSPF_AREA, sizeof (struct ospf_area));
447
paul68980082003-03-25 05:07:42 +0000448 new->ospf = ospf;
paul718e3742002-12-13 20:15:29 +0000449
450 new->area_id = area_id;
451
452 new->external_routing = OSPF_AREA_DEFAULT;
453 new->default_cost = 1;
454 new->auth_type = OSPF_AUTH_NULL;
455
456 /* New LSDB init. */
457 new->lsdb = ospf_lsdb_new ();
458
459 /* Self-originated LSAs initialize. */
460 new->router_lsa_self = NULL;
461
462#ifdef HAVE_OPAQUE_LSA
463 ospf_opaque_type10_lsa_init (new);
464#endif /* HAVE_OPAQUE_LSA */
465
466 new->oiflist = list_new ();
467 new->ranges = route_table_init ();
468
469 if (area_id.s_addr == OSPF_AREA_BACKBONE)
paul68980082003-03-25 05:07:42 +0000470 ospf->backbone = new;
paul718e3742002-12-13 20:15:29 +0000471
472 return new;
473}
474
475void
476ospf_area_free (struct ospf_area *area)
477{
paul68980082003-03-25 05:07:42 +0000478 struct route_node *rn;
479 struct ospf_lsa *lsa;
480
paul718e3742002-12-13 20:15:29 +0000481 /* Free LSDBs. */
paul68980082003-03-25 05:07:42 +0000482 LSDB_LOOP (ROUTER_LSDB (area), rn, lsa)
483 ospf_discard_from_db (area->ospf, area->lsdb, lsa);
484 LSDB_LOOP (NETWORK_LSDB (area), rn, lsa)
485 ospf_discard_from_db (area->ospf, area->lsdb, lsa);
486 LSDB_LOOP (SUMMARY_LSDB (area), rn, lsa)
487 ospf_discard_from_db (area->ospf, area->lsdb, lsa);
488 LSDB_LOOP (ASBR_SUMMARY_LSDB (area), rn, lsa)
489 ospf_discard_from_db (area->ospf, area->lsdb, lsa);
paul718e3742002-12-13 20:15:29 +0000490
paul68980082003-03-25 05:07:42 +0000491 LSDB_LOOP (NSSA_LSDB (area), rn, lsa)
492 ospf_discard_from_db (area->ospf, area->lsdb, lsa);
paul718e3742002-12-13 20:15:29 +0000493#ifdef HAVE_OPAQUE_LSA
paul68980082003-03-25 05:07:42 +0000494 LSDB_LOOP (OPAQUE_AREA_LSDB (area), rn, lsa)
495 ospf_discard_from_db (area->ospf, area->lsdb, lsa);
496 LSDB_LOOP (OPAQUE_LINK_LSDB (area), rn, lsa)
497 ospf_discard_from_db (area->ospf, area->lsdb, lsa);
paul718e3742002-12-13 20:15:29 +0000498#endif /* HAVE_OPAQUE_LSA */
499
500 ospf_lsdb_delete_all (area->lsdb);
501 ospf_lsdb_free (area->lsdb);
502
paul718e3742002-12-13 20:15:29 +0000503 ospf_lsa_unlock (area->router_lsa_self);
504
505 route_table_finish (area->ranges);
506 list_delete (area->oiflist);
507
508 if (EXPORT_NAME (area))
509 free (EXPORT_NAME (area));
510
511 if (IMPORT_NAME (area))
512 free (IMPORT_NAME (area));
513
514 /* Cancel timer. */
515 OSPF_TIMER_OFF (area->t_router_lsa_self);
516
517 if (OSPF_IS_AREA_BACKBONE (area))
paul68980082003-03-25 05:07:42 +0000518 area->ospf->backbone = NULL;
paul718e3742002-12-13 20:15:29 +0000519
520 XFREE (MTYPE_OSPF_AREA, area);
521}
522
523void
paul68980082003-03-25 05:07:42 +0000524ospf_area_check_free (struct ospf *ospf, struct in_addr area_id)
paul718e3742002-12-13 20:15:29 +0000525{
526 struct ospf_area *area;
527
paul68980082003-03-25 05:07:42 +0000528 area = ospf_area_lookup_by_area_id (ospf, area_id);
paul718e3742002-12-13 20:15:29 +0000529 if (area &&
530 listcount (area->oiflist) == 0 &&
531 area->ranges->top == NULL &&
532 area->shortcut_configured == OSPF_SHORTCUT_DEFAULT &&
533 area->external_routing == OSPF_AREA_DEFAULT &&
534 area->no_summary == 0 &&
535 area->default_cost == 1 &&
536 EXPORT_NAME (area) == NULL &&
537 IMPORT_NAME (area) == NULL &&
538 area->auth_type == OSPF_AUTH_NULL)
539 {
paul68980082003-03-25 05:07:42 +0000540 listnode_delete (ospf->areas, area);
paul718e3742002-12-13 20:15:29 +0000541 ospf_area_free (area);
542 }
543}
544
545struct ospf_area *
paul68980082003-03-25 05:07:42 +0000546ospf_area_get (struct ospf *ospf, struct in_addr area_id, int format)
paul718e3742002-12-13 20:15:29 +0000547{
548 struct ospf_area *area;
549
paul68980082003-03-25 05:07:42 +0000550 area = ospf_area_lookup_by_area_id (ospf, area_id);
paul718e3742002-12-13 20:15:29 +0000551 if (!area)
552 {
paul68980082003-03-25 05:07:42 +0000553 area = ospf_area_new (ospf, area_id);
paul718e3742002-12-13 20:15:29 +0000554 area->format = format;
paul68980082003-03-25 05:07:42 +0000555 listnode_add_sort (ospf->areas, area);
556 ospf_check_abr_status (ospf);
paul718e3742002-12-13 20:15:29 +0000557 }
558
559 return area;
560}
561
562struct ospf_area *
paul68980082003-03-25 05:07:42 +0000563ospf_area_lookup_by_area_id (struct ospf *ospf, struct in_addr area_id)
paul718e3742002-12-13 20:15:29 +0000564{
565 struct ospf_area *area;
hasso52dc7ee2004-09-23 19:18:23 +0000566 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000567
paul68980082003-03-25 05:07:42 +0000568 for (node = listhead (ospf->areas); node; nextnode (node))
paul718e3742002-12-13 20:15:29 +0000569 {
570 area = getdata (node);
571
572 if (IPV4_ADDR_SAME (&area->area_id, &area_id))
573 return area;
574 }
575
576 return NULL;
577}
578
579void
580ospf_area_add_if (struct ospf_area *area, struct ospf_interface *oi)
581{
582 listnode_add (area->oiflist, oi);
583}
584
585void
586ospf_area_del_if (struct ospf_area *area, struct ospf_interface *oi)
587{
588 listnode_delete (area->oiflist, oi);
589}
590
591
592/* Config network statement related functions. */
593struct ospf_network *
594ospf_network_new (struct in_addr area_id, int format)
595{
596 struct ospf_network *new;
597 new = XCALLOC (MTYPE_OSPF_NETWORK, sizeof (struct ospf_network));
598
599 new->area_id = area_id;
600 new->format = format;
601
602 return new;
603}
604
605void
paul68980082003-03-25 05:07:42 +0000606ospf_network_free (struct ospf *ospf, struct ospf_network *network)
paul718e3742002-12-13 20:15:29 +0000607{
paul68980082003-03-25 05:07:42 +0000608 ospf_area_check_free (ospf, network->area_id);
609 ospf_schedule_abr_task (ospf);
paul718e3742002-12-13 20:15:29 +0000610 XFREE (MTYPE_OSPF_NETWORK, network);
611}
612
613int
614ospf_network_set (struct ospf *ospf, struct prefix_ipv4 *p,
615 struct in_addr area_id)
616{
617 struct ospf_network *network;
618 struct ospf_area *area;
619 struct route_node *rn;
620 struct external_info *ei;
paul147193a2003-04-19 00:31:59 +0000621 int ret = OSPF_AREA_ID_FORMAT_ADDRESS;
paul718e3742002-12-13 20:15:29 +0000622
623 rn = route_node_get (ospf->networks, (struct prefix *)p);
624 if (rn->info)
625 {
626 /* There is already same network statement. */
627 route_unlock_node (rn);
628 return 0;
629 }
630
631 rn->info = network = ospf_network_new (area_id, ret);
paul68980082003-03-25 05:07:42 +0000632 area = ospf_area_get (ospf, area_id, ret);
paul718e3742002-12-13 20:15:29 +0000633
634 /* Run network config now. */
635 ospf_network_run (ospf, (struct prefix *)p, area);
636
637 /* Update connected redistribute. */
638 if (ospf_is_type_redistributed (ZEBRA_ROUTE_CONNECT))
639 if (EXTERNAL_INFO (ZEBRA_ROUTE_CONNECT))
640 for (rn = route_top (EXTERNAL_INFO (ZEBRA_ROUTE_CONNECT));
641 rn; rn = route_next (rn))
642 if ((ei = rn->info) != NULL)
paul68980082003-03-25 05:07:42 +0000643 if (ospf_external_info_find_lsa (ospf, &ei->p))
644 if (!ospf_distribute_check_connected (ospf, ei))
645 ospf_external_lsa_flush (ospf, ei->type, &ei->p,
paul718e3742002-12-13 20:15:29 +0000646 ei->ifindex, ei->nexthop);
647
paul68980082003-03-25 05:07:42 +0000648 ospf_area_check_free (ospf, area_id);
paul718e3742002-12-13 20:15:29 +0000649
650 return 1;
651}
652
653int
654ospf_network_unset (struct ospf *ospf, struct prefix_ipv4 *p,
655 struct in_addr area_id)
656{
657 struct route_node *rn;
658 struct ospf_network *network;
659 struct external_info *ei;
660
661 rn = route_node_lookup (ospf->networks, (struct prefix *)p);
662 if (rn == NULL)
663 return 0;
664
665 network = rn->info;
666 if (!IPV4_ADDR_SAME (&area_id, &network->area_id))
667 return 0;
668
paul68980082003-03-25 05:07:42 +0000669 ospf_network_free (ospf, rn->info);
paul718e3742002-12-13 20:15:29 +0000670 rn->info = NULL;
671 route_unlock_node (rn);
672
paul68980082003-03-25 05:07:42 +0000673 ospf_if_update (ospf);
paul718e3742002-12-13 20:15:29 +0000674
675 /* Update connected redistribute. */
676 if (ospf_is_type_redistributed (ZEBRA_ROUTE_CONNECT))
677 if (EXTERNAL_INFO (ZEBRA_ROUTE_CONNECT))
678 for (rn = route_top (EXTERNAL_INFO (ZEBRA_ROUTE_CONNECT));
679 rn; rn = route_next (rn))
680 if ((ei = rn->info) != NULL)
paul68980082003-03-25 05:07:42 +0000681 if (!ospf_external_info_find_lsa (ospf, &ei->p))
682 if (ospf_distribute_check_connected (ospf, ei))
683 ospf_external_lsa_originate (ospf, ei);
paul718e3742002-12-13 20:15:29 +0000684
685 return 1;
686}
687
paul570f7592003-01-25 06:47:41 +0000688/* Check whether interface matches given network
689 * returns: 1, true. 0, false
690 */
691int
692ospf_network_match_iface(struct connected *co, struct prefix *net)
693{
694 /* Behaviour to match both Cisco where:
695 * iface address lies within network specified -> ospf
696 * and zebra 0.9[2ish-3]:
697 * PtP special case: network specified == iface peer addr -> ospf
698 */
gdt8f40e892003-12-05 14:01:43 +0000699
paulf3ae74c2004-11-04 20:35:31 +0000700 /* For PtP, match if peer address matches network address exactly.
701 * This can be addr/32 or addr/p for p < 32, but the addr must match
702 * exactly; this is not a test for falling within the prefix. This
gdt8f40e892003-12-05 14:01:43 +0000703 * test is solely for compatibility with zebra.
gdt8f40e892003-12-05 14:01:43 +0000704 */
paulf3ae74c2004-11-04 20:35:31 +0000705 if (if_is_pointopoint (co->ifp) && co->destination &&
706 IPV4_ADDR_SAME ( &(co->destination->u.prefix4), &(net->u.prefix4)))
707 return 1;
708
709#if 0
710 /* Decline to accept PtP if dst address does not match the
711 * prefix. (ifdefed out because this is a workaround, not the
712 * desired behavior.) */
713 if (if_is_pointopoint (co->ifp) &&
714 ! prefix_match (net, co->destination))
715 return 0;
716#endif
717
718 /* If the address is within the prefix, accept. Note that this
719 * applies to PtP as well as other types.
720 */
721 if (prefix_match (net, co->address))
722 return 1;
723
724 return 0; /* no match */
paul570f7592003-01-25 06:47:41 +0000725}
726
paul718e3742002-12-13 20:15:29 +0000727void
728ospf_network_run (struct ospf *ospf, struct prefix *p, struct ospf_area *area)
729{
730 struct interface *ifp;
hasso52dc7ee2004-09-23 19:18:23 +0000731 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000732
733 /* Schedule Router ID Update. */
734 if (ospf->router_id_static.s_addr == 0)
735 if (ospf->t_router_id_update == NULL)
736 {
paul020709f2003-04-04 02:44:16 +0000737 OSPF_TIMER_ON (ospf->t_router_id_update, ospf_router_id_update_timer,
738 OSPF_ROUTER_ID_UPDATE_DELAY);
paul718e3742002-12-13 20:15:29 +0000739 }
740
741 /* Get target interface. */
paul020709f2003-04-04 02:44:16 +0000742 for (node = listhead (om->iflist); node; nextnode (node))
paul718e3742002-12-13 20:15:29 +0000743 {
hasso52dc7ee2004-09-23 19:18:23 +0000744 struct listnode *cn;
paul718e3742002-12-13 20:15:29 +0000745
746 if ((ifp = getdata (node)) == NULL)
747 continue;
748
749 if (memcmp (ifp->name, "VLINK", 5) == 0)
750 continue;
751
752 /* if interface prefix is match specified prefix,
753 then create socket and join multicast group. */
754 for (cn = listhead (ifp->connected); cn; nextnode (cn))
755 {
756 struct connected *co = getdata (cn);
757 struct prefix *addr;
paul800dc102003-03-28 01:51:40 +0000758
paule7b050c2003-04-07 06:38:02 +0000759 if (CHECK_FLAG(co->flags,ZEBRA_IFA_SECONDARY))
760 continue;
paul718e3742002-12-13 20:15:29 +0000761
hasso3fb9cd62004-10-19 19:44:43 +0000762 if (CONNECTED_POINTOPOINT_HOST(co))
paul718e3742002-12-13 20:15:29 +0000763 addr = co->destination;
764 else
765 addr = co->address;
766
paulcb3f37d2003-02-18 23:26:37 +0000767 if (p->family == co->address->family
paul68980082003-03-25 05:07:42 +0000768 && ! ospf_if_is_configured (ospf, &(addr->u.prefix4))
paulcb3f37d2003-02-18 23:26:37 +0000769 && ospf_network_match_iface(co,p))
paul570f7592003-01-25 06:47:41 +0000770 {
paul537d8ea2003-08-27 06:45:32 +0000771 struct ospf_interface *oi;
paul718e3742002-12-13 20:15:29 +0000772
paul68980082003-03-25 05:07:42 +0000773 oi = ospf_if_new (ospf, ifp, co->address);
paul718e3742002-12-13 20:15:29 +0000774 oi->connected = co;
775
776 oi->nbr_self->address = *oi->address;
777
paul718e3742002-12-13 20:15:29 +0000778 oi->area = area;
779
780 oi->params = ospf_lookup_if_params (ifp, oi->address->u.prefix4);
781 oi->output_cost = ospf_if_get_output_cost (oi);
782
783 if (area->external_routing != OSPF_AREA_DEFAULT)
784 UNSET_FLAG (oi->nbr_self->options, OSPF_OPTION_E);
785 oi->nbr_self->priority = OSPF_IF_PARAM (oi, priority);
786
787 /* Add pseudo neighbor. */
788 ospf_nbr_add_self (oi);
789
790 /* Make sure pseudo neighbor's router_id. */
paul68980082003-03-25 05:07:42 +0000791 oi->nbr_self->router_id = ospf->router_id;
paul718e3742002-12-13 20:15:29 +0000792 oi->nbr_self->src = oi->address->u.prefix4;
793
794 /* Relate ospf interface to ospf instance. */
paul68980082003-03-25 05:07:42 +0000795 oi->ospf = ospf;
paul718e3742002-12-13 20:15:29 +0000796
797 /* update network type as interface flag */
798 /* If network type is specified previously,
799 skip network type setting. */
800 oi->type = IF_DEF_PARAMS (ifp)->type;
801
802 /* Set area flag. */
803 switch (area->external_routing)
804 {
805 case OSPF_AREA_DEFAULT:
806 SET_FLAG (oi->nbr_self->options, OSPF_OPTION_E);
807 break;
808 case OSPF_AREA_STUB:
809 UNSET_FLAG (oi->nbr_self->options, OSPF_OPTION_E);
810 break;
paul718e3742002-12-13 20:15:29 +0000811 case OSPF_AREA_NSSA:
812 UNSET_FLAG (oi->nbr_self->options, OSPF_OPTION_E);
813 SET_FLAG (oi->nbr_self->options, OSPF_OPTION_NP);
814 break;
paul718e3742002-12-13 20:15:29 +0000815 }
816
817 ospf_area_add_if (oi->area, oi);
818
paul2e3b2e42002-12-13 21:03:13 +0000819 if (if_is_operative (ifp))
paul718e3742002-12-13 20:15:29 +0000820 ospf_if_up (oi);
821
822 break;
823 }
824 }
825 }
826}
827
828void
829ospf_ls_upd_queue_empty (struct ospf_interface *oi)
830{
831 struct route_node *rn;
hasso52dc7ee2004-09-23 19:18:23 +0000832 struct listnode *node;
833 struct list *lst;
paul718e3742002-12-13 20:15:29 +0000834 struct ospf_lsa *lsa;
835
836 /* empty ls update queue */
837 for (rn = route_top (oi->ls_upd_queue); rn;
838 rn = route_next (rn))
hasso52dc7ee2004-09-23 19:18:23 +0000839 if ((lst = (struct list *) rn->info))
paul718e3742002-12-13 20:15:29 +0000840 {
841 for (node = listhead (lst); node; nextnode (node))
842 if ((lsa = getdata (node)))
843 ospf_lsa_unlock (lsa);
844 list_free (lst);
845 rn->info = NULL;
846 }
847
848 /* remove update event */
849 if (oi->t_ls_upd_event)
850 {
851 thread_cancel (oi->t_ls_upd_event);
852 oi->t_ls_upd_event = NULL;
853 }
854}
855
856void
paul68980082003-03-25 05:07:42 +0000857ospf_if_update (struct ospf *ospf)
paul718e3742002-12-13 20:15:29 +0000858{
859 struct route_node *rn;
hasso52dc7ee2004-09-23 19:18:23 +0000860 struct listnode *node;
861 struct listnode *next;
paul718e3742002-12-13 20:15:29 +0000862 struct ospf_network *network;
863 struct ospf_area *area;
864
paul68980082003-03-25 05:07:42 +0000865 if (ospf != NULL)
paul718e3742002-12-13 20:15:29 +0000866 {
867 /* Update Router ID scheduled. */
paul68980082003-03-25 05:07:42 +0000868 if (ospf->router_id_static.s_addr == 0)
869 if (ospf->t_router_id_update == NULL)
paul718e3742002-12-13 20:15:29 +0000870 {
paul020709f2003-04-04 02:44:16 +0000871 OSPF_TIMER_ON (ospf->t_router_id_update,
872 ospf_router_id_update_timer,
873 OSPF_ROUTER_ID_UPDATE_DELAY);
paul718e3742002-12-13 20:15:29 +0000874 }
875
876 /* Find interfaces that not configured already. */
paul68980082003-03-25 05:07:42 +0000877 for (node = listhead (ospf->oiflist); node; node = next)
paul718e3742002-12-13 20:15:29 +0000878 {
879 int found = 0;
880 struct ospf_interface *oi = getdata (node);
881 struct connected *co = oi->connected;
882
883 next = nextnode (node);
884
885 if (oi->type == OSPF_IFTYPE_VIRTUALLINK)
886 continue;
887
paul68980082003-03-25 05:07:42 +0000888 for (rn = route_top (ospf->networks); rn; rn = route_next (rn))
paul718e3742002-12-13 20:15:29 +0000889 {
890 if (rn->info == NULL)
891 continue;
892
paul570f7592003-01-25 06:47:41 +0000893 if (ospf_network_match_iface(co,&rn->p))
paul718e3742002-12-13 20:15:29 +0000894 {
895 found = 1;
896 route_unlock_node (rn);
897 break;
898 }
899 }
900
901 if (found == 0)
902 ospf_if_free (oi);
903 }
904
905 /* Run each interface. */
paul68980082003-03-25 05:07:42 +0000906 for (rn = route_top (ospf->networks); rn; rn = route_next (rn))
paul718e3742002-12-13 20:15:29 +0000907 if (rn->info != NULL)
908 {
909 network = (struct ospf_network *) rn->info;
paul68980082003-03-25 05:07:42 +0000910 area = ospf_area_get (ospf, network->area_id, network->format);
911 ospf_network_run (ospf, &rn->p, area);
paul718e3742002-12-13 20:15:29 +0000912 }
913 }
914}
915
916void
paul68980082003-03-25 05:07:42 +0000917ospf_remove_vls_through_area (struct ospf *ospf, struct ospf_area *area)
paul718e3742002-12-13 20:15:29 +0000918{
hasso52dc7ee2004-09-23 19:18:23 +0000919 struct listnode *node, *next;
paul718e3742002-12-13 20:15:29 +0000920 struct ospf_vl_data *vl_data;
921
paul68980082003-03-25 05:07:42 +0000922 for (node = listhead (ospf->vlinks); node; node = next)
paul718e3742002-12-13 20:15:29 +0000923 {
924 next = node->next;
925 if ((vl_data = getdata (node)) != NULL)
926 if (IPV4_ADDR_SAME (&vl_data->vl_area_id, &area->area_id))
paul68980082003-03-25 05:07:42 +0000927 ospf_vl_delete (ospf, vl_data);
paul718e3742002-12-13 20:15:29 +0000928 }
929}
930
931
932struct message ospf_area_type_msg[] =
933{
934 { OSPF_AREA_DEFAULT, "Default" },
935 { OSPF_AREA_STUB, "Stub" },
936 { OSPF_AREA_NSSA, "NSSA" },
937};
938int ospf_area_type_msg_max = OSPF_AREA_TYPE_MAX;
939
940void
941ospf_area_type_set (struct ospf_area *area, int type)
942{
hasso52dc7ee2004-09-23 19:18:23 +0000943 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000944 struct ospf_interface *oi;
945
946 if (area->external_routing == type)
947 {
948 if (IS_DEBUG_OSPF_EVENT)
ajs9b0e25c2004-12-08 19:06:51 +0000949 zlog_debug ("Area[%s]: Types are the same, ignored.",
paul718e3742002-12-13 20:15:29 +0000950 inet_ntoa (area->area_id));
951 return;
952 }
953
954 area->external_routing = type;
955
956 if (IS_DEBUG_OSPF_EVENT)
ajs9b0e25c2004-12-08 19:06:51 +0000957 zlog_debug ("Area[%s]: Configured as %s", inet_ntoa (area->area_id),
paul718e3742002-12-13 20:15:29 +0000958 LOOKUP (ospf_area_type_msg, type));
959
960 switch (area->external_routing)
961 {
962 case OSPF_AREA_DEFAULT:
963 for (node = listhead (area->oiflist); node; nextnode (node))
964 if ((oi = getdata (node)) != NULL)
965 if (oi->nbr_self != NULL)
hasso8585d4e2004-04-20 17:25:12 +0000966 {
hasso8585d4e2004-04-20 17:25:12 +0000967 UNSET_FLAG (oi->nbr_self->options, OSPF_OPTION_NP);
hasso8585d4e2004-04-20 17:25:12 +0000968 SET_FLAG (oi->nbr_self->options, OSPF_OPTION_E);
969 }
paul718e3742002-12-13 20:15:29 +0000970 break;
971 case OSPF_AREA_STUB:
972 for (node = listhead (area->oiflist); node; nextnode (node))
973 if ((oi = getdata (node)) != NULL)
974 if (oi->nbr_self != NULL)
975 {
976 if (IS_DEBUG_OSPF_EVENT)
ajs9b0e25c2004-12-08 19:06:51 +0000977 zlog_debug ("setting options on %s accordingly", IF_NAME (oi));
hasso8585d4e2004-04-20 17:25:12 +0000978 UNSET_FLAG (oi->nbr_self->options, OSPF_OPTION_NP);
paul718e3742002-12-13 20:15:29 +0000979 UNSET_FLAG (oi->nbr_self->options, OSPF_OPTION_E);
980 if (IS_DEBUG_OSPF_EVENT)
ajs9b0e25c2004-12-08 19:06:51 +0000981 zlog_debug ("options set on %s: %x",
paul718e3742002-12-13 20:15:29 +0000982 IF_NAME (oi), OPTIONS (oi));
983 }
984 break;
985 case OSPF_AREA_NSSA:
paul718e3742002-12-13 20:15:29 +0000986 for (node = listhead (area->oiflist); node; nextnode (node))
987 if ((oi = getdata (node)) != NULL)
988 if (oi->nbr_self != NULL)
989 {
ajs9b0e25c2004-12-08 19:06:51 +0000990 if (IS_DEBUG_OSPF_EVENT)
991 zlog_debug ("setting nssa options on %s accordingly", IF_NAME (oi));
paul718e3742002-12-13 20:15:29 +0000992 UNSET_FLAG (oi->nbr_self->options, OSPF_OPTION_E);
993 SET_FLAG (oi->nbr_self->options, OSPF_OPTION_NP);
ajs9b0e25c2004-12-08 19:06:51 +0000994 if (IS_DEBUG_OSPF_EVENT)
995 zlog_debug ("options set on %s: %x", IF_NAME (oi), OPTIONS (oi));
paul718e3742002-12-13 20:15:29 +0000996 }
paul718e3742002-12-13 20:15:29 +0000997 break;
998 default:
999 break;
1000 }
1001
1002 ospf_router_lsa_timer_add (area);
paul68980082003-03-25 05:07:42 +00001003 ospf_schedule_abr_task (area->ospf);
paul718e3742002-12-13 20:15:29 +00001004}
1005
1006int
paul68980082003-03-25 05:07:42 +00001007ospf_area_shortcut_set (struct ospf *ospf, struct ospf_area *area, int mode)
paul718e3742002-12-13 20:15:29 +00001008{
1009 if (area->shortcut_configured == mode)
1010 return 0;
1011
1012 area->shortcut_configured = mode;
1013 ospf_router_lsa_timer_add (area);
paul68980082003-03-25 05:07:42 +00001014 ospf_schedule_abr_task (ospf);
paul718e3742002-12-13 20:15:29 +00001015
paul68980082003-03-25 05:07:42 +00001016 ospf_area_check_free (ospf, area->area_id);
paul718e3742002-12-13 20:15:29 +00001017
1018 return 1;
1019}
1020
1021int
paul68980082003-03-25 05:07:42 +00001022ospf_area_shortcut_unset (struct ospf *ospf, struct ospf_area *area)
paul718e3742002-12-13 20:15:29 +00001023{
1024 area->shortcut_configured = OSPF_SHORTCUT_DEFAULT;
1025 ospf_router_lsa_timer_add (area);
paul68980082003-03-25 05:07:42 +00001026 ospf_area_check_free (ospf, area->area_id);
1027 ospf_schedule_abr_task (ospf);
paul718e3742002-12-13 20:15:29 +00001028
1029 return 1;
1030}
1031
1032int
1033ospf_area_vlink_count (struct ospf *ospf, struct ospf_area *area)
1034{
1035 struct ospf_vl_data *vl;
hasso52dc7ee2004-09-23 19:18:23 +00001036 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00001037 int count = 0;
1038
1039 for (node = listhead (ospf->vlinks); node; nextnode (node))
1040 {
1041 vl = getdata (node);
1042 if (IPV4_ADDR_SAME (&vl->vl_area_id, &area->area_id))
1043 count++;
1044 }
1045
1046 return count;
1047}
1048
1049int
1050ospf_area_stub_set (struct ospf *ospf, struct in_addr area_id)
1051{
1052 struct ospf_area *area;
paul147193a2003-04-19 00:31:59 +00001053 int format = OSPF_AREA_ID_FORMAT_ADDRESS;
paul718e3742002-12-13 20:15:29 +00001054
paul68980082003-03-25 05:07:42 +00001055 area = ospf_area_get (ospf, area_id, format);
paul718e3742002-12-13 20:15:29 +00001056 if (ospf_area_vlink_count (ospf, area))
1057 return 0;
1058
1059 if (area->external_routing != OSPF_AREA_STUB)
1060 ospf_area_type_set (area, OSPF_AREA_STUB);
1061
1062 return 1;
1063}
1064
1065int
1066ospf_area_stub_unset (struct ospf *ospf, struct in_addr area_id)
1067{
1068 struct ospf_area *area;
1069
paul68980082003-03-25 05:07:42 +00001070 area = ospf_area_lookup_by_area_id (ospf, area_id);
paul718e3742002-12-13 20:15:29 +00001071 if (area == NULL)
1072 return 1;
1073
1074 if (area->external_routing == OSPF_AREA_STUB)
1075 ospf_area_type_set (area, OSPF_AREA_DEFAULT);
1076
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_no_summary_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 area->no_summary = 1;
1090
1091 return 1;
1092}
1093
1094int
1095ospf_area_no_summary_unset (struct ospf *ospf, struct in_addr area_id)
1096{
1097 struct ospf_area *area;
1098
paul68980082003-03-25 05:07:42 +00001099 area = ospf_area_lookup_by_area_id (ospf, area_id);
paul718e3742002-12-13 20:15:29 +00001100 if (area == NULL)
1101 return 0;
1102
1103 area->no_summary = 0;
paul68980082003-03-25 05:07:42 +00001104 ospf_area_check_free (ospf, area_id);
paul718e3742002-12-13 20:15:29 +00001105
1106 return 1;
1107}
1108
1109int
1110ospf_area_nssa_set (struct ospf *ospf, struct in_addr area_id)
1111{
1112 struct ospf_area *area;
paul147193a2003-04-19 00:31:59 +00001113 int format = OSPF_AREA_ID_FORMAT_ADDRESS;
paul718e3742002-12-13 20:15:29 +00001114
paul68980082003-03-25 05:07:42 +00001115 area = ospf_area_get (ospf, area_id, format);
paul718e3742002-12-13 20:15:29 +00001116 if (ospf_area_vlink_count (ospf, area))
1117 return 0;
1118
1119 if (area->external_routing != OSPF_AREA_NSSA)
1120 {
1121 ospf_area_type_set (area, OSPF_AREA_NSSA);
1122 ospf->anyNSSA++;
1123 }
1124
paul084c7842003-06-22 08:35:18 +00001125 /* set NSSA area defaults */
1126 area->no_summary = 0;
1127 area->NSSATranslatorRole = OSPF_NSSA_ROLE_CANDIDATE;
pauld4a53d52003-07-12 21:30:57 +00001128 area->NSSATranslatorState = OSPF_NSSA_TRANSLATE_DISABLED;
paul084c7842003-06-22 08:35:18 +00001129 area->NSSATranslatorStabilityInterval = OSPF_NSSA_TRANS_STABLE_DEFAULT;
1130
paul718e3742002-12-13 20:15:29 +00001131 return 1;
1132}
1133
1134int
1135ospf_area_nssa_unset (struct ospf *ospf, struct in_addr area_id)
1136{
1137 struct ospf_area *area;
1138
paul68980082003-03-25 05:07:42 +00001139 area = ospf_area_lookup_by_area_id (ospf, area_id);
paul718e3742002-12-13 20:15:29 +00001140 if (area == NULL)
1141 return 0;
1142
1143 if (area->external_routing == OSPF_AREA_NSSA)
1144 {
1145 ospf->anyNSSA--;
1146 ospf_area_type_set (area, OSPF_AREA_DEFAULT);
1147 }
1148
paul68980082003-03-25 05:07:42 +00001149 ospf_area_check_free (ospf, area_id);
paul718e3742002-12-13 20:15:29 +00001150
1151 return 1;
1152}
1153
1154int
1155ospf_area_nssa_translator_role_set (struct ospf *ospf, struct in_addr area_id,
1156 int role)
1157{
1158 struct ospf_area *area;
1159
paul68980082003-03-25 05:07:42 +00001160 area = ospf_area_lookup_by_area_id (ospf, area_id);
paul718e3742002-12-13 20:15:29 +00001161 if (area == NULL)
1162 return 0;
1163
paul084c7842003-06-22 08:35:18 +00001164 area->NSSATranslatorRole = role;
paul718e3742002-12-13 20:15:29 +00001165
1166 return 1;
1167}
1168
1169int
1170ospf_area_nssa_translator_role_unset (struct ospf *ospf,
1171 struct in_addr area_id)
1172{
1173 struct ospf_area *area;
1174
paul68980082003-03-25 05:07:42 +00001175 area = ospf_area_lookup_by_area_id (ospf, area_id);
paul718e3742002-12-13 20:15:29 +00001176 if (area == NULL)
1177 return 0;
1178
paul084c7842003-06-22 08:35:18 +00001179 area->NSSATranslatorRole = OSPF_NSSA_ROLE_CANDIDATE;
paul718e3742002-12-13 20:15:29 +00001180
paul68980082003-03-25 05:07:42 +00001181 ospf_area_check_free (ospf, area_id);
paul718e3742002-12-13 20:15:29 +00001182
1183 return 1;
1184}
1185
1186int
paul68980082003-03-25 05:07:42 +00001187ospf_area_export_list_set (struct ospf *ospf,
paul6c835672004-10-11 11:00:30 +00001188 struct ospf_area *area, const char *list_name)
paul718e3742002-12-13 20:15:29 +00001189{
1190 struct access_list *list;
1191 list = access_list_lookup (AFI_IP, list_name);
1192
1193 EXPORT_LIST (area) = list;
1194
1195 if (EXPORT_NAME (area))
1196 free (EXPORT_NAME (area));
1197
1198 EXPORT_NAME (area) = strdup (list_name);
paul68980082003-03-25 05:07:42 +00001199 ospf_schedule_abr_task (ospf);
paul718e3742002-12-13 20:15:29 +00001200
1201 return 1;
1202}
1203
1204int
paul68980082003-03-25 05:07:42 +00001205ospf_area_export_list_unset (struct ospf *ospf, struct ospf_area * area)
paul718e3742002-12-13 20:15:29 +00001206{
1207
1208 EXPORT_LIST (area) = 0;
1209
1210 if (EXPORT_NAME (area))
1211 free (EXPORT_NAME (area));
1212
1213 EXPORT_NAME (area) = NULL;
1214
paul68980082003-03-25 05:07:42 +00001215 ospf_area_check_free (ospf, area->area_id);
paul718e3742002-12-13 20:15:29 +00001216
paul68980082003-03-25 05:07:42 +00001217 ospf_schedule_abr_task (ospf);
paul718e3742002-12-13 20:15:29 +00001218
1219 return 1;
1220}
1221
1222int
paul6c835672004-10-11 11:00:30 +00001223ospf_area_import_list_set (struct ospf *ospf, struct ospf_area *area,
1224 const char *name)
paul718e3742002-12-13 20:15:29 +00001225{
1226 struct access_list *list;
1227 list = access_list_lookup (AFI_IP, name);
1228
1229 IMPORT_LIST (area) = list;
1230
1231 if (IMPORT_NAME (area))
1232 free (IMPORT_NAME (area));
1233
1234 IMPORT_NAME (area) = strdup (name);
paul68980082003-03-25 05:07:42 +00001235 ospf_schedule_abr_task (ospf);
paul718e3742002-12-13 20:15:29 +00001236
1237 return 1;
1238}
1239
1240int
paul68980082003-03-25 05:07:42 +00001241ospf_area_import_list_unset (struct ospf *ospf, struct ospf_area * area)
paul718e3742002-12-13 20:15:29 +00001242{
1243 IMPORT_LIST (area) = 0;
1244
1245 if (IMPORT_NAME (area))
1246 free (IMPORT_NAME (area));
1247
1248 IMPORT_NAME (area) = NULL;
paul68980082003-03-25 05:07:42 +00001249 ospf_area_check_free (ospf, area->area_id);
paul718e3742002-12-13 20:15:29 +00001250
paul68980082003-03-25 05:07:42 +00001251 ospf_schedule_abr_task (ospf);
paul718e3742002-12-13 20:15:29 +00001252
1253 return 1;
1254}
1255
1256int
1257ospf_timers_spf_set (struct ospf *ospf, u_int32_t delay, u_int32_t hold)
1258{
1259 ospf->spf_delay = delay;
1260 ospf->spf_holdtime = hold;
1261
1262 return 1;
1263}
1264
1265int
1266ospf_timers_spf_unset (struct ospf *ospf)
1267{
1268 ospf->spf_delay = OSPF_SPF_DELAY_DEFAULT;
1269 ospf->spf_holdtime = OSPF_SPF_HOLDTIME_DEFAULT;
1270
1271 return 1;
1272}
1273
1274int
1275ospf_timers_refresh_set (struct ospf *ospf, int interval)
1276{
1277 int time_left;
1278
1279 if (ospf->lsa_refresh_interval == interval)
1280 return 1;
1281
1282 time_left = ospf->lsa_refresh_interval -
1283 (time (NULL) - ospf->lsa_refresher_started);
1284
1285 if (time_left > interval)
1286 {
1287 OSPF_TIMER_OFF (ospf->t_lsa_refresher);
1288 ospf->t_lsa_refresher =
1289 thread_add_timer (master, ospf_lsa_refresh_walker, ospf, interval);
1290 }
1291 ospf->lsa_refresh_interval = interval;
1292
1293 return 1;
1294}
1295
1296int
1297ospf_timers_refresh_unset (struct ospf *ospf)
1298{
1299 int time_left;
1300
1301 time_left = ospf->lsa_refresh_interval -
1302 (time (NULL) - ospf->lsa_refresher_started);
1303
1304 if (time_left > OSPF_LSA_REFRESH_INTERVAL_DEFAULT)
1305 {
1306 OSPF_TIMER_OFF (ospf->t_lsa_refresher);
1307 ospf->t_lsa_refresher =
1308 thread_add_timer (master, ospf_lsa_refresh_walker, ospf,
1309 OSPF_LSA_REFRESH_INTERVAL_DEFAULT);
1310 }
1311
1312 ospf->lsa_refresh_interval = OSPF_LSA_REFRESH_INTERVAL_DEFAULT;
1313
1314 return 1;
1315}
1316
1317
1318struct ospf_nbr_nbma *
1319ospf_nbr_nbma_new ()
1320{
1321 struct ospf_nbr_nbma *nbr_nbma;
1322
1323 nbr_nbma = XMALLOC (MTYPE_OSPF_NEIGHBOR_STATIC,
1324 sizeof (struct ospf_nbr_nbma));
1325 memset (nbr_nbma, 0, sizeof (struct ospf_nbr_nbma));
1326
1327 nbr_nbma->priority = OSPF_NEIGHBOR_PRIORITY_DEFAULT;
1328 nbr_nbma->v_poll = OSPF_POLL_INTERVAL_DEFAULT;
1329
1330 return nbr_nbma;
1331}
1332
1333void
1334ospf_nbr_nbma_free (struct ospf_nbr_nbma *nbr_nbma)
1335{
1336 XFREE (MTYPE_OSPF_NEIGHBOR_STATIC, nbr_nbma);
1337}
1338
1339void
1340ospf_nbr_nbma_delete (struct ospf *ospf, struct ospf_nbr_nbma *nbr_nbma)
1341{
1342 struct route_node *rn;
1343 struct prefix_ipv4 p;
1344
1345 p.family = AF_INET;
1346 p.prefix = nbr_nbma->addr;
1347 p.prefixlen = IPV4_MAX_BITLEN;
1348
1349 rn = route_node_lookup (ospf->nbr_nbma, (struct prefix *)&p);
1350 if (rn)
1351 {
1352 ospf_nbr_nbma_free (rn->info);
1353 rn->info = NULL;
1354 route_unlock_node (rn);
1355 route_unlock_node (rn);
1356 }
1357}
1358
1359void
1360ospf_nbr_nbma_down (struct ospf_nbr_nbma *nbr_nbma)
1361{
1362 OSPF_TIMER_OFF (nbr_nbma->t_poll);
1363
1364 if (nbr_nbma->nbr)
1365 {
1366 nbr_nbma->nbr->nbr_nbma = NULL;
1367 OSPF_NSM_EVENT_EXECUTE (nbr_nbma->nbr, NSM_KillNbr);
1368 }
1369
1370 if (nbr_nbma->oi)
1371 listnode_delete (nbr_nbma->oi->nbr_nbma, nbr_nbma);
1372}
1373
1374void
1375ospf_nbr_nbma_add (struct ospf_nbr_nbma *nbr_nbma,
1376 struct ospf_interface *oi)
1377{
1378 struct ospf_neighbor *nbr;
1379 struct route_node *rn;
1380 struct prefix p;
1381
1382 if (oi->type != OSPF_IFTYPE_NBMA)
1383 return;
1384
1385 if (nbr_nbma->nbr != NULL)
1386 return;
1387
1388 if (IPV4_ADDR_SAME (&oi->nbr_self->address.u.prefix4, &nbr_nbma->addr))
1389 return;
1390
1391 nbr_nbma->oi = oi;
1392 listnode_add (oi->nbr_nbma, nbr_nbma);
1393
1394 /* Get neighbor information from table. */
1395 p.family = AF_INET;
1396 p.prefixlen = IPV4_MAX_BITLEN;
1397 p.u.prefix4 = nbr_nbma->addr;
1398
1399 rn = route_node_get (oi->nbrs, (struct prefix *)&p);
1400 if (rn->info)
1401 {
1402 nbr = rn->info;
1403 nbr->nbr_nbma = nbr_nbma;
1404 nbr_nbma->nbr = nbr;
1405
1406 route_unlock_node (rn);
1407 }
1408 else
1409 {
1410 nbr = rn->info = ospf_nbr_new (oi);
1411 nbr->state = NSM_Down;
1412 nbr->src = nbr_nbma->addr;
1413 nbr->nbr_nbma = nbr_nbma;
1414 nbr->priority = nbr_nbma->priority;
1415 nbr->address = p;
1416
1417 nbr_nbma->nbr = nbr;
1418
1419 OSPF_NSM_EVENT_EXECUTE (nbr, NSM_Start);
1420 }
1421}
1422
1423void
paul68980082003-03-25 05:07:42 +00001424ospf_nbr_nbma_if_update (struct ospf *ospf, struct ospf_interface *oi)
paul718e3742002-12-13 20:15:29 +00001425{
1426 struct ospf_nbr_nbma *nbr_nbma;
1427 struct route_node *rn;
1428 struct prefix_ipv4 p;
1429
1430 if (oi->type != OSPF_IFTYPE_NBMA)
1431 return;
1432
paul68980082003-03-25 05:07:42 +00001433 for (rn = route_top (ospf->nbr_nbma); rn; rn = route_next (rn))
paul718e3742002-12-13 20:15:29 +00001434 if ((nbr_nbma = rn->info))
1435 if (nbr_nbma->oi == NULL && nbr_nbma->nbr == NULL)
1436 {
1437 p.family = AF_INET;
1438 p.prefix = nbr_nbma->addr;
1439 p.prefixlen = IPV4_MAX_BITLEN;
1440
1441 if (prefix_match (oi->address, (struct prefix *)&p))
1442 ospf_nbr_nbma_add (nbr_nbma, oi);
1443 }
1444}
1445
1446struct ospf_nbr_nbma *
1447ospf_nbr_nbma_lookup (struct ospf *ospf, struct in_addr nbr_addr)
1448{
1449 struct route_node *rn;
1450 struct prefix_ipv4 p;
1451
1452 p.family = AF_INET;
1453 p.prefix = nbr_addr;
1454 p.prefixlen = IPV4_MAX_BITLEN;
1455
1456 rn = route_node_lookup (ospf->nbr_nbma, (struct prefix *)&p);
1457 if (rn)
1458 {
1459 route_unlock_node (rn);
1460 return rn->info;
1461 }
1462 return NULL;
1463}
1464
1465struct ospf_nbr_nbma *
paul68980082003-03-25 05:07:42 +00001466ospf_nbr_nbma_lookup_next (struct ospf *ospf, struct in_addr *addr, int first)
paul718e3742002-12-13 20:15:29 +00001467{
1468#if 0
1469 struct ospf_nbr_nbma *nbr_nbma;
hasso52dc7ee2004-09-23 19:18:23 +00001470 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00001471#endif
1472
paul68980082003-03-25 05:07:42 +00001473 if (ospf == NULL)
paul718e3742002-12-13 20:15:29 +00001474 return NULL;
1475
1476#if 0
paul68980082003-03-25 05:07:42 +00001477 for (node = listhead (ospf->nbr_nbma); node; nextnode (node))
paul718e3742002-12-13 20:15:29 +00001478 {
1479 nbr_nbma = getdata (node);
1480
1481 if (first)
1482 {
1483 *addr = nbr_nbma->addr;
1484 return nbr_nbma;
1485 }
1486 else if (ntohl (nbr_nbma->addr.s_addr) > ntohl (addr->s_addr))
1487 {
1488 *addr = nbr_nbma->addr;
1489 return nbr_nbma;
1490 }
1491 }
1492#endif
1493 return NULL;
1494}
1495
1496int
1497ospf_nbr_nbma_set (struct ospf *ospf, struct in_addr nbr_addr)
1498{
1499 struct ospf_nbr_nbma *nbr_nbma;
1500 struct ospf_interface *oi;
1501 struct prefix_ipv4 p;
1502 struct route_node *rn;
hasso52dc7ee2004-09-23 19:18:23 +00001503 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00001504
1505 nbr_nbma = ospf_nbr_nbma_lookup (ospf, nbr_addr);
1506 if (nbr_nbma)
1507 return 0;
1508
1509 nbr_nbma = ospf_nbr_nbma_new ();
1510 nbr_nbma->addr = nbr_addr;
1511
1512 p.family = AF_INET;
1513 p.prefix = nbr_addr;
1514 p.prefixlen = IPV4_MAX_BITLEN;
1515
1516 rn = route_node_get (ospf->nbr_nbma, (struct prefix *)&p);
1517 rn->info = nbr_nbma;
1518
1519 for (node = listhead (ospf->oiflist); node; nextnode (node))
1520 {
1521 oi = getdata (node);
1522 if (oi->type == OSPF_IFTYPE_NBMA)
1523 if (prefix_match (oi->address, (struct prefix *)&p))
1524 {
1525 ospf_nbr_nbma_add (nbr_nbma, oi);
1526 break;
1527 }
1528 }
1529
1530 return 1;
1531}
1532
1533int
1534ospf_nbr_nbma_unset (struct ospf *ospf, struct in_addr nbr_addr)
1535{
1536 struct ospf_nbr_nbma *nbr_nbma;
1537
1538 nbr_nbma = ospf_nbr_nbma_lookup (ospf, nbr_addr);
1539 if (nbr_nbma == NULL)
1540 return 0;
1541
1542 ospf_nbr_nbma_down (nbr_nbma);
1543 ospf_nbr_nbma_delete (ospf, nbr_nbma);
1544
1545 return 1;
1546}
1547
1548int
1549ospf_nbr_nbma_priority_set (struct ospf *ospf, struct in_addr nbr_addr,
1550 u_char priority)
1551{
1552 struct ospf_nbr_nbma *nbr_nbma;
1553
1554 nbr_nbma = ospf_nbr_nbma_lookup (ospf, nbr_addr);
1555 if (nbr_nbma == NULL)
1556 return 0;
1557
1558 if (nbr_nbma->priority != priority)
1559 nbr_nbma->priority = priority;
1560
1561 return 1;
1562}
1563
1564int
1565ospf_nbr_nbma_priority_unset (struct ospf *ospf, struct in_addr nbr_addr)
1566{
1567 struct ospf_nbr_nbma *nbr_nbma;
1568
1569 nbr_nbma = ospf_nbr_nbma_lookup (ospf, nbr_addr);
1570 if (nbr_nbma == NULL)
1571 return 0;
1572
1573 if (nbr_nbma != OSPF_NEIGHBOR_PRIORITY_DEFAULT)
1574 nbr_nbma->priority = OSPF_NEIGHBOR_PRIORITY_DEFAULT;
1575
1576 return 1;
1577}
1578
1579int
1580ospf_nbr_nbma_poll_interval_set (struct ospf *ospf, struct in_addr nbr_addr,
paul6c835672004-10-11 11:00:30 +00001581 unsigned int interval)
paul718e3742002-12-13 20:15:29 +00001582{
1583 struct ospf_nbr_nbma *nbr_nbma;
1584
1585 nbr_nbma = ospf_nbr_nbma_lookup (ospf, nbr_addr);
1586 if (nbr_nbma == NULL)
1587 return 0;
1588
1589 if (nbr_nbma->v_poll != interval)
1590 {
1591 nbr_nbma->v_poll = interval;
1592 if (nbr_nbma->oi && ospf_if_is_up (nbr_nbma->oi))
1593 {
1594 OSPF_TIMER_OFF (nbr_nbma->t_poll);
1595 OSPF_POLL_TIMER_ON (nbr_nbma->t_poll, ospf_poll_timer,
1596 nbr_nbma->v_poll);
1597 }
1598 }
1599
1600 return 1;
1601}
1602
1603int
1604ospf_nbr_nbma_poll_interval_unset (struct ospf *ospf, struct in_addr addr)
1605{
1606 struct ospf_nbr_nbma *nbr_nbma;
1607
1608 nbr_nbma = ospf_nbr_nbma_lookup (ospf, addr);
1609 if (nbr_nbma == NULL)
1610 return 0;
1611
1612 if (nbr_nbma->v_poll != OSPF_POLL_INTERVAL_DEFAULT)
1613 nbr_nbma->v_poll = OSPF_POLL_INTERVAL_DEFAULT;
1614
1615 return 1;
1616}
1617
paul718e3742002-12-13 20:15:29 +00001618void
paul020709f2003-04-04 02:44:16 +00001619ospf_master_init ()
1620{
1621 memset (&ospf_master, 0, sizeof (struct ospf_master));
1622
1623 om = &ospf_master;
1624 om->ospf = list_new ();
1625 om->master = thread_master_create ();
1626 om->start_time = time (NULL);
1627}