]>
Commit | Line | Data |
---|---|---|
718e3744 | 1 | /* OSPF version 2 daemon program. |
2 | Copyright (C) 1999, 2000 Toshiaki Takada | |
3 | ||
4 | This file is part of GNU Zebra. | |
5 | ||
6 | GNU Zebra is free software; you can redistribute it and/or modify it | |
7 | under the terms of the GNU General Public License as published by the | |
8 | Free Software Foundation; either version 2, or (at your option) any | |
9 | later version. | |
10 | ||
11 | GNU Zebra is distributed in the hope that it will be useful, but | |
12 | WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
14 | General Public License for more details. | |
15 | ||
16 | You should have received a copy of the GNU General Public License | |
17 | along with GNU Zebra; see the file COPYING. If not, write to the Free | |
18 | Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA | |
19 | 02111-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 | ||
020709f9 | 55 | \f |
edd7c245 | 56 | |
020709f9 | 57 | /* OSPF process wide configuration. */ |
58 | static struct ospf_master ospf_master; | |
59 | ||
60 | /* OSPF process wide configuration pointer to export. */ | |
61 | struct ospf_master *om; | |
718e3744 | 62 | |
63 | extern struct zclient *zclient; | |
18a6dce6 | 64 | extern struct in_addr router_id_zebra; |
718e3744 | 65 | |
66 | \f | |
68980084 | 67 | void ospf_remove_vls_through_area (struct ospf *, struct ospf_area *); |
68 | void ospf_network_free (struct ospf *, struct ospf_network *); | |
718e3744 | 69 | void ospf_area_free (struct ospf_area *); |
70 | void ospf_network_run (struct ospf *, struct prefix *, struct ospf_area *); | |
71 | ||
718e3744 | 72 | #define OSPF_EXTERNAL_LSA_ORIGINATE_DELAY 1 |
73 | ||
74 | void | |
68980084 | 75 | ospf_router_id_update (struct ospf *ospf) |
718e3744 | 76 | { |
718e3744 | 77 | struct in_addr router_id, router_id_old; |
1eb8ef25 | 78 | struct ospf_interface *oi; |
52dc7ee6 | 79 | struct listnode *node; |
718e3744 | 80 | |
81 | if (IS_DEBUG_OSPF_EVENT) | |
9b0e25c0 | 82 | zlog_debug ("Router-ID[OLD:%s]: Update", inet_ntoa (ospf->router_id)); |
718e3744 | 83 | |
68980084 | 84 | router_id_old = ospf->router_id; |
718e3744 | 85 | |
68980084 | 86 | if (ospf->router_id_static.s_addr != 0) |
87 | router_id = ospf->router_id_static; | |
718e3744 | 88 | else |
18a6dce6 | 89 | router_id = router_id_zebra; |
718e3744 | 90 | |
68980084 | 91 | ospf->router_id = router_id; |
718e3744 | 92 | |
93 | if (IS_DEBUG_OSPF_EVENT) | |
9b0e25c0 | 94 | zlog_debug ("Router-ID[NEW:%s]: Update", inet_ntoa (ospf->router_id)); |
718e3744 | 95 | |
96 | if (!IPV4_ADDR_SAME (&router_id_old, &router_id)) | |
97 | { | |
1eb8ef25 | 98 | for (ALL_LIST_ELEMENTS_RO (ospf->oiflist, node, oi)) |
99 | /* Update self-neighbor's router_id. */ | |
100 | oi->nbr_self->router_id = router_id; | |
718e3744 | 101 | |
102 | /* If AS-external-LSA is queued, then flush those LSAs. */ | |
68980084 | 103 | if (router_id_old.s_addr == 0 && ospf->external_origin) |
718e3744 | 104 | { |
105 | int type; | |
106 | /* Originate each redistributed external route. */ | |
107 | for (type = 0; type < ZEBRA_ROUTE_MAX; type++) | |
68980084 | 108 | if (ospf->external_origin & (1 << type)) |
718e3744 | 109 | thread_add_event (master, ospf_external_lsa_originate_timer, |
68980084 | 110 | ospf, type); |
718e3744 | 111 | /* Originate Deafult. */ |
68980084 | 112 | if (ospf->external_origin & (1 << ZEBRA_ROUTE_MAX)) |
718e3744 | 113 | thread_add_event (master, ospf_default_originate_timer, |
68980084 | 114 | &ospf->default_originate, 0); |
718e3744 | 115 | |
68980084 | 116 | ospf->external_origin = 0; |
718e3744 | 117 | } |
118 | ||
68980084 | 119 | OSPF_TIMER_ON (ospf->t_router_lsa_update, |
718e3744 | 120 | ospf_router_lsa_update_timer, OSPF_LSA_UPDATE_DELAY); |
121 | } | |
122 | } | |
123 | ||
124 | int | |
125 | ospf_router_id_update_timer (struct thread *thread) | |
126 | { | |
020709f9 | 127 | struct ospf *ospf = THREAD_ARG (thread); |
68980084 | 128 | |
718e3744 | 129 | if (IS_DEBUG_OSPF_EVENT) |
9b0e25c0 | 130 | zlog_debug ("Router-ID: Update timer fired!"); |
718e3744 | 131 | |
68980084 | 132 | ospf->t_router_id_update = NULL; |
133 | ospf_router_id_update (ospf); | |
718e3744 | 134 | |
135 | return 0; | |
136 | } | |
137 | \f | |
138 | /* For OSPF area sort by area id. */ | |
4dadc291 | 139 | static int |
718e3744 | 140 | ospf_area_id_cmp (struct ospf_area *a1, struct ospf_area *a2) |
141 | { | |
142 | if (ntohl (a1->area_id.s_addr) > ntohl (a2->area_id.s_addr)) | |
143 | return 1; | |
144 | if (ntohl (a1->area_id.s_addr) < ntohl (a2->area_id.s_addr)) | |
145 | return -1; | |
146 | return 0; | |
147 | } | |
148 | ||
149 | /* Allocate new ospf structure. */ | |
4dadc291 | 150 | static struct ospf * |
151 | ospf_new (void) | |
718e3744 | 152 | { |
153 | int i; | |
154 | ||
155 | struct ospf *new = XCALLOC (MTYPE_OSPF_TOP, sizeof (struct ospf)); | |
156 | ||
157 | new->router_id.s_addr = htonl (0); | |
158 | new->router_id_static.s_addr = htonl (0); | |
159 | ||
d57834f6 | 160 | new->abr_type = OSPF_ABR_DEFAULT; |
718e3744 | 161 | new->oiflist = list_new (); |
162 | new->vlinks = list_new (); | |
163 | new->areas = list_new (); | |
164 | new->areas->cmp = (int (*)(void *, void *)) ospf_area_id_cmp; | |
165 | new->networks = route_table_init (); | |
166 | new->nbr_nbma = route_table_init (); | |
167 | ||
168 | new->lsdb = ospf_lsdb_new (); | |
169 | ||
170 | new->default_originate = DEFAULT_ORIGINATE_NONE; | |
171 | ||
172 | new->new_external_route = route_table_init (); | |
173 | new->old_external_route = route_table_init (); | |
174 | new->external_lsas = route_table_init (); | |
175 | ||
176 | /* Distribute parameter init. */ | |
177 | for (i = 0; i <= ZEBRA_ROUTE_MAX; i++) | |
178 | { | |
179 | new->dmetric[i].type = -1; | |
180 | new->dmetric[i].value = -1; | |
181 | } | |
182 | new->default_metric = -1; | |
183 | new->ref_bandwidth = OSPF_DEFAULT_REF_BANDWIDTH; | |
184 | ||
185 | /* SPF timer value init. */ | |
186 | new->spf_delay = OSPF_SPF_DELAY_DEFAULT; | |
187 | new->spf_holdtime = OSPF_SPF_HOLDTIME_DEFAULT; | |
d24f6e2a | 188 | new->spf_max_holdtime = OSPF_SPF_MAX_HOLDTIME_DEFAULT; |
189 | new->spf_hold_multiplier = 1; | |
718e3744 | 190 | |
191 | /* MaxAge init. */ | |
192 | new->maxage_lsa = list_new (); | |
193 | new->t_maxage_walker = | |
194 | thread_add_timer (master, ospf_lsa_maxage_walker, | |
68980084 | 195 | new, OSPF_LSA_MAXAGE_CHECK_INTERVAL); |
718e3744 | 196 | |
197 | /* Distance table init. */ | |
198 | new->distance_table = route_table_init (); | |
199 | ||
200 | new->lsa_refresh_queue.index = 0; | |
201 | new->lsa_refresh_interval = OSPF_LSA_REFRESH_INTERVAL_DEFAULT; | |
202 | new->t_lsa_refresher = thread_add_timer (master, ospf_lsa_refresh_walker, | |
203 | new, new->lsa_refresh_interval); | |
204 | new->lsa_refresher_started = time (NULL); | |
205 | ||
5c33349b | 206 | if ((new->fd = ospf_sock_init()) < 0) |
207 | { | |
208 | zlog_err("ospf_new: fatal error: ospf_sock_init was unable to open " | |
209 | "a socket"); | |
210 | exit(1); | |
211 | } | |
212 | if ((new->ibuf = stream_new(OSPF_MAX_PACKET_SIZE+1)) == NULL) | |
213 | { | |
214 | zlog_err("ospf_new: fatal error: stream_new(%u) failed allocating ibuf", | |
215 | OSPF_MAX_PACKET_SIZE+1); | |
216 | exit(1); | |
217 | } | |
218 | new->t_read = thread_add_read (master, ospf_read, new, new->fd); | |
718e3744 | 219 | new->oi_write_q = list_new (); |
220 | ||
221 | return new; | |
222 | } | |
223 | ||
224 | struct ospf * | |
020709f9 | 225 | ospf_lookup () |
718e3744 | 226 | { |
020709f9 | 227 | if (listcount (om->ospf) == 0) |
228 | return NULL; | |
718e3744 | 229 | |
1eb8ef25 | 230 | return listgetdata (listhead (om->ospf)); |
020709f9 | 231 | } |
232 | ||
4dadc291 | 233 | static void |
020709f9 | 234 | ospf_add (struct ospf *ospf) |
235 | { | |
236 | listnode_add (om->ospf, ospf); | |
237 | } | |
718e3744 | 238 | |
4dadc291 | 239 | static void |
020709f9 | 240 | ospf_delete (struct ospf *ospf) |
241 | { | |
242 | listnode_delete (om->ospf, ospf); | |
243 | } | |
68980084 | 244 | |
020709f9 | 245 | struct ospf * |
246 | ospf_get () | |
247 | { | |
248 | struct ospf *ospf; | |
249 | ||
250 | ospf = ospf_lookup (); | |
251 | if (ospf == NULL) | |
252 | { | |
253 | ospf = ospf_new (); | |
254 | ospf_add (ospf); | |
255 | ||
256 | if (ospf->router_id_static.s_addr == 0) | |
257 | ospf_router_id_update (ospf); | |
718e3744 | 258 | |
259 | #ifdef HAVE_OPAQUE_LSA | |
020709f9 | 260 | ospf_opaque_type11_lsa_init (ospf); |
718e3744 | 261 | #endif /* HAVE_OPAQUE_LSA */ |
020709f9 | 262 | } |
68980084 | 263 | |
264 | return ospf; | |
718e3744 | 265 | } |
266 | ||
267 | void | |
268 | ospf_finish (struct ospf *ospf) | |
269 | { | |
270 | struct route_node *rn; | |
271 | struct ospf_nbr_nbma *nbr_nbma; | |
68980084 | 272 | struct ospf_lsa *lsa; |
1eb8ef25 | 273 | struct ospf_interface *oi; |
274 | struct ospf_area *area; | |
275 | struct ospf_vl_data *vl_data; | |
276 | struct listnode *node, *nnode; | |
718e3744 | 277 | int i; |
278 | ||
279 | #ifdef HAVE_OPAQUE_LSA | |
280 | ospf_opaque_type11_lsa_term (ospf); | |
281 | #endif /* HAVE_OPAQUE_LSA */ | |
282 | ||
283 | /* Unredister redistribution */ | |
284 | for (i = 0; i < ZEBRA_ROUTE_MAX; i++) | |
020709f9 | 285 | ospf_redistribute_unset (ospf, i); |
718e3744 | 286 | |
1eb8ef25 | 287 | for (ALL_LIST_ELEMENTS (ospf->areas, node, nnode, area)) |
288 | ospf_remove_vls_through_area (ospf, area); | |
718e3744 | 289 | |
1eb8ef25 | 290 | for (ALL_LIST_ELEMENTS (ospf->vlinks, node, nnode, vl_data)) |
291 | ospf_vl_delete (ospf, vl_data); | |
718e3744 | 292 | |
293 | list_delete (ospf->vlinks); | |
294 | ||
295 | /* Reset interface. */ | |
1eb8ef25 | 296 | for (ALL_LIST_ELEMENTS (ospf->oiflist, node, nnode, oi)) |
297 | ospf_if_free (oi); | |
718e3744 | 298 | |
299 | /* Clear static neighbors */ | |
300 | for (rn = route_top (ospf->nbr_nbma); rn; rn = route_next (rn)) | |
301 | if ((nbr_nbma = rn->info)) | |
302 | { | |
303 | OSPF_POLL_TIMER_OFF (nbr_nbma->t_poll); | |
304 | ||
305 | if (nbr_nbma->nbr) | |
306 | { | |
307 | nbr_nbma->nbr->nbr_nbma = NULL; | |
308 | nbr_nbma->nbr = NULL; | |
309 | } | |
310 | ||
311 | if (nbr_nbma->oi) | |
312 | { | |
313 | listnode_delete (nbr_nbma->oi->nbr_nbma, nbr_nbma); | |
314 | nbr_nbma->oi = NULL; | |
315 | } | |
316 | ||
317 | XFREE (MTYPE_OSPF_NEIGHBOR_STATIC, nbr_nbma); | |
318 | } | |
319 | ||
320 | route_table_finish (ospf->nbr_nbma); | |
321 | ||
322 | /* Clear networks and Areas. */ | |
323 | for (rn = route_top (ospf->networks); rn; rn = route_next (rn)) | |
324 | { | |
325 | struct ospf_network *network; | |
326 | ||
327 | if ((network = rn->info) != NULL) | |
328 | { | |
68980084 | 329 | ospf_network_free (ospf, network); |
718e3744 | 330 | rn->info = NULL; |
331 | route_unlock_node (rn); | |
332 | } | |
333 | } | |
334 | ||
1eb8ef25 | 335 | for (ALL_LIST_ELEMENTS (ospf->areas, node, nnode, area)) |
718e3744 | 336 | { |
718e3744 | 337 | listnode_delete (ospf->areas, area); |
338 | ospf_area_free (area); | |
339 | } | |
340 | ||
341 | /* Cancel all timers. */ | |
342 | OSPF_TIMER_OFF (ospf->t_external_lsa); | |
343 | OSPF_TIMER_OFF (ospf->t_router_id_update); | |
344 | OSPF_TIMER_OFF (ospf->t_router_lsa_update); | |
345 | OSPF_TIMER_OFF (ospf->t_spf_calc); | |
346 | OSPF_TIMER_OFF (ospf->t_ase_calc); | |
347 | OSPF_TIMER_OFF (ospf->t_maxage); | |
348 | OSPF_TIMER_OFF (ospf->t_maxage_walker); | |
349 | OSPF_TIMER_OFF (ospf->t_abr_task); | |
350 | OSPF_TIMER_OFF (ospf->t_distribute_update); | |
351 | OSPF_TIMER_OFF (ospf->t_lsa_refresher); | |
352 | OSPF_TIMER_OFF (ospf->t_read); | |
353 | OSPF_TIMER_OFF (ospf->t_write); | |
354 | ||
355 | close (ospf->fd); | |
5c33349b | 356 | stream_free(ospf->ibuf); |
718e3744 | 357 | |
358 | #ifdef HAVE_OPAQUE_LSA | |
68980084 | 359 | LSDB_LOOP (OPAQUE_AS_LSDB (ospf), rn, lsa) |
360 | ospf_discard_from_db (ospf, ospf->lsdb, lsa); | |
718e3744 | 361 | #endif /* HAVE_OPAQUE_LSA */ |
68980084 | 362 | LSDB_LOOP (EXTERNAL_LSDB (ospf), rn, lsa) |
363 | ospf_discard_from_db (ospf, ospf->lsdb, lsa); | |
364 | ||
718e3744 | 365 | ospf_lsdb_delete_all (ospf->lsdb); |
366 | ospf_lsdb_free (ospf->lsdb); | |
367 | ||
1eb8ef25 | 368 | for (ALL_LIST_ELEMENTS (ospf->maxage_lsa, node, nnode, lsa)) |
369 | ospf_lsa_unlock (lsa); | |
718e3744 | 370 | |
371 | list_delete (ospf->maxage_lsa); | |
372 | ||
373 | if (ospf->old_table) | |
374 | ospf_route_table_free (ospf->old_table); | |
375 | if (ospf->new_table) | |
376 | { | |
377 | ospf_route_delete (ospf->new_table); | |
378 | ospf_route_table_free (ospf->new_table); | |
379 | } | |
380 | if (ospf->old_rtrs) | |
381 | ospf_rtrs_free (ospf->old_rtrs); | |
382 | if (ospf->new_rtrs) | |
383 | ospf_rtrs_free (ospf->new_rtrs); | |
384 | if (ospf->new_external_route) | |
385 | { | |
386 | ospf_route_delete (ospf->new_external_route); | |
387 | ospf_route_table_free (ospf->new_external_route); | |
388 | } | |
389 | if (ospf->old_external_route) | |
390 | { | |
391 | ospf_route_delete (ospf->old_external_route); | |
392 | ospf_route_table_free (ospf->old_external_route); | |
393 | } | |
394 | if (ospf->external_lsas) | |
395 | { | |
396 | ospf_ase_external_lsas_finish (ospf->external_lsas); | |
397 | } | |
398 | ||
399 | list_delete (ospf->areas); | |
400 | ||
401 | for (i = ZEBRA_ROUTE_SYSTEM; i <= ZEBRA_ROUTE_MAX; i++) | |
402 | if (EXTERNAL_INFO (i) != NULL) | |
403 | for (rn = route_top (EXTERNAL_INFO (i)); rn; rn = route_next (rn)) | |
404 | { | |
405 | if (rn->info == NULL) | |
406 | continue; | |
407 | ||
408 | XFREE (MTYPE_OSPF_EXTERNAL_INFO, rn->info); | |
409 | rn->info = NULL; | |
410 | route_unlock_node (rn); | |
411 | } | |
412 | ||
68980084 | 413 | ospf_distance_reset (ospf); |
718e3744 | 414 | route_table_finish (ospf->distance_table); |
415 | ||
020709f9 | 416 | ospf_delete (ospf); |
718e3744 | 417 | |
020709f9 | 418 | XFREE (MTYPE_OSPF_TOP, ospf); |
718e3744 | 419 | } |
420 | ||
421 | \f | |
422 | /* allocate new OSPF Area object */ | |
4dadc291 | 423 | static struct ospf_area * |
68980084 | 424 | ospf_area_new (struct ospf *ospf, struct in_addr area_id) |
718e3744 | 425 | { |
426 | struct ospf_area *new; | |
427 | ||
428 | /* Allocate new config_network. */ | |
429 | new = XCALLOC (MTYPE_OSPF_AREA, sizeof (struct ospf_area)); | |
430 | ||
68980084 | 431 | new->ospf = ospf; |
718e3744 | 432 | |
433 | new->area_id = area_id; | |
434 | ||
435 | new->external_routing = OSPF_AREA_DEFAULT; | |
436 | new->default_cost = 1; | |
437 | new->auth_type = OSPF_AUTH_NULL; | |
438 | ||
439 | /* New LSDB init. */ | |
440 | new->lsdb = ospf_lsdb_new (); | |
441 | ||
442 | /* Self-originated LSAs initialize. */ | |
443 | new->router_lsa_self = NULL; | |
444 | ||
445 | #ifdef HAVE_OPAQUE_LSA | |
446 | ospf_opaque_type10_lsa_init (new); | |
447 | #endif /* HAVE_OPAQUE_LSA */ | |
448 | ||
449 | new->oiflist = list_new (); | |
450 | new->ranges = route_table_init (); | |
451 | ||
452 | if (area_id.s_addr == OSPF_AREA_BACKBONE) | |
68980084 | 453 | ospf->backbone = new; |
718e3744 | 454 | |
455 | return new; | |
456 | } | |
457 | ||
458 | void | |
459 | ospf_area_free (struct ospf_area *area) | |
460 | { | |
68980084 | 461 | struct route_node *rn; |
462 | struct ospf_lsa *lsa; | |
463 | ||
718e3744 | 464 | /* Free LSDBs. */ |
68980084 | 465 | LSDB_LOOP (ROUTER_LSDB (area), rn, lsa) |
466 | ospf_discard_from_db (area->ospf, area->lsdb, lsa); | |
467 | LSDB_LOOP (NETWORK_LSDB (area), rn, lsa) | |
468 | ospf_discard_from_db (area->ospf, area->lsdb, lsa); | |
469 | LSDB_LOOP (SUMMARY_LSDB (area), rn, lsa) | |
470 | ospf_discard_from_db (area->ospf, area->lsdb, lsa); | |
471 | LSDB_LOOP (ASBR_SUMMARY_LSDB (area), rn, lsa) | |
472 | ospf_discard_from_db (area->ospf, area->lsdb, lsa); | |
718e3744 | 473 | |
68980084 | 474 | LSDB_LOOP (NSSA_LSDB (area), rn, lsa) |
475 | ospf_discard_from_db (area->ospf, area->lsdb, lsa); | |
718e3744 | 476 | #ifdef HAVE_OPAQUE_LSA |
68980084 | 477 | LSDB_LOOP (OPAQUE_AREA_LSDB (area), rn, lsa) |
478 | ospf_discard_from_db (area->ospf, area->lsdb, lsa); | |
479 | LSDB_LOOP (OPAQUE_LINK_LSDB (area), rn, lsa) | |
480 | ospf_discard_from_db (area->ospf, area->lsdb, lsa); | |
718e3744 | 481 | #endif /* HAVE_OPAQUE_LSA */ |
482 | ||
483 | ospf_lsdb_delete_all (area->lsdb); | |
484 | ospf_lsdb_free (area->lsdb); | |
485 | ||
718e3744 | 486 | ospf_lsa_unlock (area->router_lsa_self); |
487 | ||
488 | route_table_finish (area->ranges); | |
489 | list_delete (area->oiflist); | |
490 | ||
491 | if (EXPORT_NAME (area)) | |
492 | free (EXPORT_NAME (area)); | |
493 | ||
494 | if (IMPORT_NAME (area)) | |
495 | free (IMPORT_NAME (area)); | |
496 | ||
497 | /* Cancel timer. */ | |
498 | OSPF_TIMER_OFF (area->t_router_lsa_self); | |
499 | ||
500 | if (OSPF_IS_AREA_BACKBONE (area)) | |
68980084 | 501 | area->ospf->backbone = NULL; |
718e3744 | 502 | |
503 | XFREE (MTYPE_OSPF_AREA, area); | |
504 | } | |
505 | ||
506 | void | |
68980084 | 507 | ospf_area_check_free (struct ospf *ospf, struct in_addr area_id) |
718e3744 | 508 | { |
509 | struct ospf_area *area; | |
510 | ||
68980084 | 511 | area = ospf_area_lookup_by_area_id (ospf, area_id); |
718e3744 | 512 | if (area && |
513 | listcount (area->oiflist) == 0 && | |
514 | area->ranges->top == NULL && | |
515 | area->shortcut_configured == OSPF_SHORTCUT_DEFAULT && | |
516 | area->external_routing == OSPF_AREA_DEFAULT && | |
517 | area->no_summary == 0 && | |
518 | area->default_cost == 1 && | |
519 | EXPORT_NAME (area) == NULL && | |
520 | IMPORT_NAME (area) == NULL && | |
521 | area->auth_type == OSPF_AUTH_NULL) | |
522 | { | |
68980084 | 523 | listnode_delete (ospf->areas, area); |
718e3744 | 524 | ospf_area_free (area); |
525 | } | |
526 | } | |
527 | ||
528 | struct ospf_area * | |
68980084 | 529 | ospf_area_get (struct ospf *ospf, struct in_addr area_id, int format) |
718e3744 | 530 | { |
531 | struct ospf_area *area; | |
532 | ||
68980084 | 533 | area = ospf_area_lookup_by_area_id (ospf, area_id); |
718e3744 | 534 | if (!area) |
535 | { | |
68980084 | 536 | area = ospf_area_new (ospf, area_id); |
718e3744 | 537 | area->format = format; |
68980084 | 538 | listnode_add_sort (ospf->areas, area); |
539 | ospf_check_abr_status (ospf); | |
718e3744 | 540 | } |
541 | ||
542 | return area; | |
543 | } | |
544 | ||
545 | struct ospf_area * | |
68980084 | 546 | ospf_area_lookup_by_area_id (struct ospf *ospf, struct in_addr area_id) |
718e3744 | 547 | { |
548 | struct ospf_area *area; | |
52dc7ee6 | 549 | struct listnode *node; |
718e3744 | 550 | |
1eb8ef25 | 551 | for (ALL_LIST_ELEMENTS_RO (ospf->areas, node, area)) |
552 | if (IPV4_ADDR_SAME (&area->area_id, &area_id)) | |
553 | return area; | |
718e3744 | 554 | |
555 | return NULL; | |
556 | } | |
557 | ||
558 | void | |
559 | ospf_area_add_if (struct ospf_area *area, struct ospf_interface *oi) | |
560 | { | |
561 | listnode_add (area->oiflist, oi); | |
562 | } | |
563 | ||
564 | void | |
565 | ospf_area_del_if (struct ospf_area *area, struct ospf_interface *oi) | |
566 | { | |
567 | listnode_delete (area->oiflist, oi); | |
568 | } | |
569 | ||
570 | \f | |
571 | /* Config network statement related functions. */ | |
4dadc291 | 572 | static struct ospf_network * |
718e3744 | 573 | ospf_network_new (struct in_addr area_id, int format) |
574 | { | |
575 | struct ospf_network *new; | |
576 | new = XCALLOC (MTYPE_OSPF_NETWORK, sizeof (struct ospf_network)); | |
577 | ||
578 | new->area_id = area_id; | |
579 | new->format = format; | |
580 | ||
581 | return new; | |
582 | } | |
583 | ||
584 | void | |
68980084 | 585 | ospf_network_free (struct ospf *ospf, struct ospf_network *network) |
718e3744 | 586 | { |
68980084 | 587 | ospf_area_check_free (ospf, network->area_id); |
588 | ospf_schedule_abr_task (ospf); | |
718e3744 | 589 | XFREE (MTYPE_OSPF_NETWORK, network); |
590 | } | |
591 | ||
592 | int | |
593 | ospf_network_set (struct ospf *ospf, struct prefix_ipv4 *p, | |
594 | struct in_addr area_id) | |
595 | { | |
596 | struct ospf_network *network; | |
597 | struct ospf_area *area; | |
598 | struct route_node *rn; | |
599 | struct external_info *ei; | |
147193a2 | 600 | int ret = OSPF_AREA_ID_FORMAT_ADDRESS; |
718e3744 | 601 | |
602 | rn = route_node_get (ospf->networks, (struct prefix *)p); | |
603 | if (rn->info) | |
604 | { | |
605 | /* There is already same network statement. */ | |
606 | route_unlock_node (rn); | |
607 | return 0; | |
608 | } | |
609 | ||
610 | rn->info = network = ospf_network_new (area_id, ret); | |
68980084 | 611 | area = ospf_area_get (ospf, area_id, ret); |
718e3744 | 612 | |
613 | /* Run network config now. */ | |
614 | ospf_network_run (ospf, (struct prefix *)p, area); | |
615 | ||
616 | /* Update connected redistribute. */ | |
617 | if (ospf_is_type_redistributed (ZEBRA_ROUTE_CONNECT)) | |
618 | if (EXTERNAL_INFO (ZEBRA_ROUTE_CONNECT)) | |
619 | for (rn = route_top (EXTERNAL_INFO (ZEBRA_ROUTE_CONNECT)); | |
620 | rn; rn = route_next (rn)) | |
621 | if ((ei = rn->info) != NULL) | |
68980084 | 622 | if (ospf_external_info_find_lsa (ospf, &ei->p)) |
623 | if (!ospf_distribute_check_connected (ospf, ei)) | |
624 | ospf_external_lsa_flush (ospf, ei->type, &ei->p, | |
5339cfdb | 625 | ei->ifindex /*, ei->nexthop */); |
718e3744 | 626 | |
68980084 | 627 | ospf_area_check_free (ospf, area_id); |
718e3744 | 628 | |
629 | return 1; | |
630 | } | |
631 | ||
632 | int | |
633 | ospf_network_unset (struct ospf *ospf, struct prefix_ipv4 *p, | |
634 | struct in_addr area_id) | |
635 | { | |
636 | struct route_node *rn; | |
637 | struct ospf_network *network; | |
638 | struct external_info *ei; | |
639 | ||
640 | rn = route_node_lookup (ospf->networks, (struct prefix *)p); | |
641 | if (rn == NULL) | |
642 | return 0; | |
643 | ||
644 | network = rn->info; | |
645 | if (!IPV4_ADDR_SAME (&area_id, &network->area_id)) | |
646 | return 0; | |
647 | ||
68980084 | 648 | ospf_network_free (ospf, rn->info); |
718e3744 | 649 | rn->info = NULL; |
650 | route_unlock_node (rn); | |
651 | ||
68980084 | 652 | ospf_if_update (ospf); |
718e3744 | 653 | |
654 | /* Update connected redistribute. */ | |
655 | if (ospf_is_type_redistributed (ZEBRA_ROUTE_CONNECT)) | |
656 | if (EXTERNAL_INFO (ZEBRA_ROUTE_CONNECT)) | |
657 | for (rn = route_top (EXTERNAL_INFO (ZEBRA_ROUTE_CONNECT)); | |
658 | rn; rn = route_next (rn)) | |
659 | if ((ei = rn->info) != NULL) | |
68980084 | 660 | if (!ospf_external_info_find_lsa (ospf, &ei->p)) |
661 | if (ospf_distribute_check_connected (ospf, ei)) | |
662 | ospf_external_lsa_originate (ospf, ei); | |
718e3744 | 663 | |
664 | return 1; | |
665 | } | |
666 | ||
570f7598 | 667 | /* Check whether interface matches given network |
668 | * returns: 1, true. 0, false | |
669 | */ | |
670 | int | |
671 | ospf_network_match_iface(struct connected *co, struct prefix *net) | |
672 | { | |
673 | /* Behaviour to match both Cisco where: | |
674 | * iface address lies within network specified -> ospf | |
675 | * and zebra 0.9[2ish-3]: | |
676 | * PtP special case: network specified == iface peer addr -> ospf | |
677 | */ | |
8f40e891 | 678 | |
f3ae74cd | 679 | /* For PtP, match if peer address matches network address exactly. |
680 | * This can be addr/32 or addr/p for p < 32, but the addr must match | |
681 | * exactly; this is not a test for falling within the prefix. This | |
8f40e891 | 682 | * test is solely for compatibility with zebra. |
8f40e891 | 683 | */ |
f3ae74cd | 684 | if (if_is_pointopoint (co->ifp) && co->destination && |
685 | IPV4_ADDR_SAME ( &(co->destination->u.prefix4), &(net->u.prefix4))) | |
686 | return 1; | |
687 | ||
688 | #if 0 | |
689 | /* Decline to accept PtP if dst address does not match the | |
690 | * prefix. (ifdefed out because this is a workaround, not the | |
691 | * desired behavior.) */ | |
692 | if (if_is_pointopoint (co->ifp) && | |
693 | ! prefix_match (net, co->destination)) | |
694 | return 0; | |
695 | #endif | |
696 | ||
697 | /* If the address is within the prefix, accept. Note that this | |
698 | * applies to PtP as well as other types. | |
699 | */ | |
700 | if (prefix_match (net, co->address)) | |
701 | return 1; | |
702 | ||
703 | return 0; /* no match */ | |
570f7598 | 704 | } |
705 | ||
718e3744 | 706 | void |
707 | ospf_network_run (struct ospf *ospf, struct prefix *p, struct ospf_area *area) | |
708 | { | |
709 | struct interface *ifp; | |
1eb8ef25 | 710 | struct connected *co; |
52dc7ee6 | 711 | struct listnode *node; |
718e3744 | 712 | |
713 | /* Schedule Router ID Update. */ | |
714 | if (ospf->router_id_static.s_addr == 0) | |
715 | if (ospf->t_router_id_update == NULL) | |
716 | { | |
020709f9 | 717 | OSPF_TIMER_ON (ospf->t_router_id_update, ospf_router_id_update_timer, |
718 | OSPF_ROUTER_ID_UPDATE_DELAY); | |
718e3744 | 719 | } |
720 | ||
721 | /* Get target interface. */ | |
1eb8ef25 | 722 | for (ALL_LIST_ELEMENTS_RO (om->iflist, node, ifp)) |
718e3744 | 723 | { |
1eb8ef25 | 724 | struct listnode *cnode; |
718e3744 | 725 | |
718e3744 | 726 | if (memcmp (ifp->name, "VLINK", 5) == 0) |
727 | continue; | |
728 | ||
729 | /* if interface prefix is match specified prefix, | |
730 | then create socket and join multicast group. */ | |
1eb8ef25 | 731 | for (ALL_LIST_ELEMENTS_RO (ifp->connected, cnode, co)) |
718e3744 | 732 | { |
718e3744 | 733 | struct prefix *addr; |
800dc105 | 734 | |
e7b050cb | 735 | if (CHECK_FLAG(co->flags,ZEBRA_IFA_SECONDARY)) |
736 | continue; | |
718e3744 | 737 | |
3fb9cd6e | 738 | if (CONNECTED_POINTOPOINT_HOST(co)) |
718e3744 | 739 | addr = co->destination; |
740 | else | |
741 | addr = co->address; | |
742 | ||
cb3f37d2 | 743 | if (p->family == co->address->family |
68980084 | 744 | && ! ospf_if_is_configured (ospf, &(addr->u.prefix4)) |
cb3f37d2 | 745 | && ospf_network_match_iface(co,p)) |
570f7598 | 746 | { |
1eb8ef25 | 747 | struct ospf_interface *oi; |
718e3744 | 748 | |
68980084 | 749 | oi = ospf_if_new (ospf, ifp, co->address); |
718e3744 | 750 | oi->connected = co; |
751 | ||
752 | oi->nbr_self->address = *oi->address; | |
753 | ||
718e3744 | 754 | oi->area = area; |
755 | ||
756 | oi->params = ospf_lookup_if_params (ifp, oi->address->u.prefix4); | |
757 | oi->output_cost = ospf_if_get_output_cost (oi); | |
758 | ||
759 | if (area->external_routing != OSPF_AREA_DEFAULT) | |
760 | UNSET_FLAG (oi->nbr_self->options, OSPF_OPTION_E); | |
761 | oi->nbr_self->priority = OSPF_IF_PARAM (oi, priority); | |
762 | ||
763 | /* Add pseudo neighbor. */ | |
764 | ospf_nbr_add_self (oi); | |
765 | ||
766 | /* Make sure pseudo neighbor's router_id. */ | |
68980084 | 767 | oi->nbr_self->router_id = ospf->router_id; |
718e3744 | 768 | oi->nbr_self->src = oi->address->u.prefix4; |
769 | ||
770 | /* Relate ospf interface to ospf instance. */ | |
68980084 | 771 | oi->ospf = ospf; |
718e3744 | 772 | |
773 | /* update network type as interface flag */ | |
774 | /* If network type is specified previously, | |
775 | skip network type setting. */ | |
776 | oi->type = IF_DEF_PARAMS (ifp)->type; | |
777 | ||
778 | /* Set area flag. */ | |
779 | switch (area->external_routing) | |
780 | { | |
781 | case OSPF_AREA_DEFAULT: | |
782 | SET_FLAG (oi->nbr_self->options, OSPF_OPTION_E); | |
783 | break; | |
784 | case OSPF_AREA_STUB: | |
785 | UNSET_FLAG (oi->nbr_self->options, OSPF_OPTION_E); | |
786 | break; | |
718e3744 | 787 | case OSPF_AREA_NSSA: |
788 | UNSET_FLAG (oi->nbr_self->options, OSPF_OPTION_E); | |
789 | SET_FLAG (oi->nbr_self->options, OSPF_OPTION_NP); | |
790 | break; | |
718e3744 | 791 | } |
792 | ||
793 | ospf_area_add_if (oi->area, oi); | |
794 | ||
2e3b2e47 | 795 | if (if_is_operative (ifp)) |
718e3744 | 796 | ospf_if_up (oi); |
797 | ||
798 | break; | |
799 | } | |
800 | } | |
801 | } | |
802 | } | |
803 | ||
804 | void | |
805 | ospf_ls_upd_queue_empty (struct ospf_interface *oi) | |
806 | { | |
807 | struct route_node *rn; | |
1eb8ef25 | 808 | struct listnode *node, *nnode; |
52dc7ee6 | 809 | struct list *lst; |
718e3744 | 810 | struct ospf_lsa *lsa; |
811 | ||
812 | /* empty ls update queue */ | |
813 | for (rn = route_top (oi->ls_upd_queue); rn; | |
814 | rn = route_next (rn)) | |
52dc7ee6 | 815 | if ((lst = (struct list *) rn->info)) |
718e3744 | 816 | { |
1eb8ef25 | 817 | for (ALL_LIST_ELEMENTS (lst, node, nnode, lsa)) |
818 | ospf_lsa_unlock (lsa); | |
718e3744 | 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 | ||
831 | void | |
68980084 | 832 | ospf_if_update (struct ospf *ospf) |
718e3744 | 833 | { |
834 | struct route_node *rn; | |
1eb8ef25 | 835 | struct listnode *node, *nnode; |
718e3744 | 836 | struct ospf_network *network; |
837 | struct ospf_area *area; | |
1eb8ef25 | 838 | struct ospf_interface *oi; |
718e3744 | 839 | |
68980084 | 840 | if (ospf != NULL) |
718e3744 | 841 | { |
842 | /* Update Router ID scheduled. */ | |
68980084 | 843 | if (ospf->router_id_static.s_addr == 0) |
844 | if (ospf->t_router_id_update == NULL) | |
718e3744 | 845 | { |
020709f9 | 846 | OSPF_TIMER_ON (ospf->t_router_id_update, |
847 | ospf_router_id_update_timer, | |
848 | OSPF_ROUTER_ID_UPDATE_DELAY); | |
718e3744 | 849 | } |
850 | ||
851 | /* Find interfaces that not configured already. */ | |
1eb8ef25 | 852 | for (ALL_LIST_ELEMENTS (ospf->oiflist, node, nnode, oi)) |
718e3744 | 853 | { |
854 | int found = 0; | |
718e3744 | 855 | struct connected *co = oi->connected; |
856 | ||
718e3744 | 857 | if (oi->type == OSPF_IFTYPE_VIRTUALLINK) |
858 | continue; | |
859 | ||
68980084 | 860 | for (rn = route_top (ospf->networks); rn; rn = route_next (rn)) |
718e3744 | 861 | { |
862 | if (rn->info == NULL) | |
863 | continue; | |
864 | ||
570f7598 | 865 | if (ospf_network_match_iface(co,&rn->p)) |
718e3744 | 866 | { |
867 | found = 1; | |
868 | route_unlock_node (rn); | |
869 | break; | |
870 | } | |
871 | } | |
872 | ||
873 | if (found == 0) | |
874 | ospf_if_free (oi); | |
875 | } | |
876 | ||
877 | /* Run each interface. */ | |
68980084 | 878 | for (rn = route_top (ospf->networks); rn; rn = route_next (rn)) |
718e3744 | 879 | if (rn->info != NULL) |
880 | { | |
881 | network = (struct ospf_network *) rn->info; | |
68980084 | 882 | area = ospf_area_get (ospf, network->area_id, network->format); |
883 | ospf_network_run (ospf, &rn->p, area); | |
718e3744 | 884 | } |
885 | } | |
886 | } | |
887 | ||
888 | void | |
68980084 | 889 | ospf_remove_vls_through_area (struct ospf *ospf, struct ospf_area *area) |
718e3744 | 890 | { |
1eb8ef25 | 891 | struct listnode *node, *nnode; |
718e3744 | 892 | struct ospf_vl_data *vl_data; |
893 | ||
1eb8ef25 | 894 | for (ALL_LIST_ELEMENTS (ospf->vlinks, node, nnode, vl_data)) |
895 | if (IPV4_ADDR_SAME (&vl_data->vl_area_id, &area->area_id)) | |
896 | ospf_vl_delete (ospf, vl_data); | |
718e3744 | 897 | } |
898 | ||
899 | \f | |
900 | struct message ospf_area_type_msg[] = | |
901 | { | |
902 | { OSPF_AREA_DEFAULT, "Default" }, | |
903 | { OSPF_AREA_STUB, "Stub" }, | |
904 | { OSPF_AREA_NSSA, "NSSA" }, | |
905 | }; | |
906 | int ospf_area_type_msg_max = OSPF_AREA_TYPE_MAX; | |
907 | ||
4dadc291 | 908 | static void |
718e3744 | 909 | ospf_area_type_set (struct ospf_area *area, int type) |
910 | { | |
52dc7ee6 | 911 | struct listnode *node; |
718e3744 | 912 | struct ospf_interface *oi; |
913 | ||
914 | if (area->external_routing == type) | |
915 | { | |
916 | if (IS_DEBUG_OSPF_EVENT) | |
9b0e25c0 | 917 | zlog_debug ("Area[%s]: Types are the same, ignored.", |
718e3744 | 918 | inet_ntoa (area->area_id)); |
919 | return; | |
920 | } | |
921 | ||
922 | area->external_routing = type; | |
923 | ||
924 | if (IS_DEBUG_OSPF_EVENT) | |
9b0e25c0 | 925 | zlog_debug ("Area[%s]: Configured as %s", inet_ntoa (area->area_id), |
718e3744 | 926 | LOOKUP (ospf_area_type_msg, type)); |
927 | ||
928 | switch (area->external_routing) | |
929 | { | |
930 | case OSPF_AREA_DEFAULT: | |
1eb8ef25 | 931 | for (ALL_LIST_ELEMENTS_RO (area->oiflist, node, oi)) |
932 | if (oi->nbr_self != NULL) | |
933 | { | |
934 | UNSET_FLAG (oi->nbr_self->options, OSPF_OPTION_NP); | |
935 | SET_FLAG (oi->nbr_self->options, OSPF_OPTION_E); | |
936 | } | |
718e3744 | 937 | break; |
938 | case OSPF_AREA_STUB: | |
1eb8ef25 | 939 | for (ALL_LIST_ELEMENTS_RO (area->oiflist, node, oi)) |
940 | if (oi->nbr_self != NULL) | |
941 | { | |
942 | if (IS_DEBUG_OSPF_EVENT) | |
943 | zlog_debug ("setting options on %s accordingly", IF_NAME (oi)); | |
944 | UNSET_FLAG (oi->nbr_self->options, OSPF_OPTION_NP); | |
945 | UNSET_FLAG (oi->nbr_self->options, OSPF_OPTION_E); | |
946 | if (IS_DEBUG_OSPF_EVENT) | |
947 | zlog_debug ("options set on %s: %x", | |
948 | IF_NAME (oi), OPTIONS (oi)); | |
949 | } | |
718e3744 | 950 | break; |
951 | case OSPF_AREA_NSSA: | |
1eb8ef25 | 952 | for (ALL_LIST_ELEMENTS_RO (area->oiflist, node, oi)) |
953 | if (oi->nbr_self != NULL) | |
954 | { | |
955 | zlog_debug ("setting nssa options on %s accordingly", IF_NAME (oi)); | |
956 | UNSET_FLAG (oi->nbr_self->options, OSPF_OPTION_E); | |
957 | SET_FLAG (oi->nbr_self->options, OSPF_OPTION_NP); | |
958 | zlog_debug ("options set on %s: %x", IF_NAME (oi), OPTIONS (oi)); | |
959 | } | |
718e3744 | 960 | break; |
961 | default: | |
962 | break; | |
963 | } | |
964 | ||
965 | ospf_router_lsa_timer_add (area); | |
68980084 | 966 | ospf_schedule_abr_task (area->ospf); |
718e3744 | 967 | } |
968 | ||
969 | int | |
68980084 | 970 | ospf_area_shortcut_set (struct ospf *ospf, struct ospf_area *area, int mode) |
718e3744 | 971 | { |
972 | if (area->shortcut_configured == mode) | |
973 | return 0; | |
974 | ||
975 | area->shortcut_configured = mode; | |
976 | ospf_router_lsa_timer_add (area); | |
68980084 | 977 | ospf_schedule_abr_task (ospf); |
718e3744 | 978 | |
68980084 | 979 | ospf_area_check_free (ospf, area->area_id); |
718e3744 | 980 | |
981 | return 1; | |
982 | } | |
983 | ||
984 | int | |
68980084 | 985 | ospf_area_shortcut_unset (struct ospf *ospf, struct ospf_area *area) |
718e3744 | 986 | { |
987 | area->shortcut_configured = OSPF_SHORTCUT_DEFAULT; | |
988 | ospf_router_lsa_timer_add (area); | |
68980084 | 989 | ospf_area_check_free (ospf, area->area_id); |
990 | ospf_schedule_abr_task (ospf); | |
718e3744 | 991 | |
992 | return 1; | |
993 | } | |
994 | ||
4dadc291 | 995 | static int |
718e3744 | 996 | ospf_area_vlink_count (struct ospf *ospf, struct ospf_area *area) |
997 | { | |
998 | struct ospf_vl_data *vl; | |
52dc7ee6 | 999 | struct listnode *node; |
718e3744 | 1000 | int count = 0; |
1001 | ||
1eb8ef25 | 1002 | for (ALL_LIST_ELEMENTS_RO (ospf->vlinks, node, vl)) |
1003 | if (IPV4_ADDR_SAME (&vl->vl_area_id, &area->area_id)) | |
1004 | count++; | |
718e3744 | 1005 | |
1006 | return count; | |
1007 | } | |
1008 | ||
1009 | int | |
1010 | ospf_area_stub_set (struct ospf *ospf, struct in_addr area_id) | |
1011 | { | |
1012 | struct ospf_area *area; | |
147193a2 | 1013 | int format = OSPF_AREA_ID_FORMAT_ADDRESS; |
718e3744 | 1014 | |
68980084 | 1015 | area = ospf_area_get (ospf, area_id, format); |
718e3744 | 1016 | if (ospf_area_vlink_count (ospf, area)) |
1017 | return 0; | |
1018 | ||
1019 | if (area->external_routing != OSPF_AREA_STUB) | |
1020 | ospf_area_type_set (area, OSPF_AREA_STUB); | |
1021 | ||
1022 | return 1; | |
1023 | } | |
1024 | ||
1025 | int | |
1026 | ospf_area_stub_unset (struct ospf *ospf, struct in_addr area_id) | |
1027 | { | |
1028 | struct ospf_area *area; | |
1029 | ||
68980084 | 1030 | area = ospf_area_lookup_by_area_id (ospf, area_id); |
718e3744 | 1031 | if (area == NULL) |
1032 | return 1; | |
1033 | ||
1034 | if (area->external_routing == OSPF_AREA_STUB) | |
1035 | ospf_area_type_set (area, OSPF_AREA_DEFAULT); | |
1036 | ||
68980084 | 1037 | ospf_area_check_free (ospf, area_id); |
718e3744 | 1038 | |
1039 | return 1; | |
1040 | } | |
1041 | ||
1042 | int | |
1043 | ospf_area_no_summary_set (struct ospf *ospf, struct in_addr area_id) | |
1044 | { | |
1045 | struct ospf_area *area; | |
147193a2 | 1046 | int format = OSPF_AREA_ID_FORMAT_ADDRESS; |
718e3744 | 1047 | |
68980084 | 1048 | area = ospf_area_get (ospf, area_id, format); |
718e3744 | 1049 | area->no_summary = 1; |
1050 | ||
1051 | return 1; | |
1052 | } | |
1053 | ||
1054 | int | |
1055 | ospf_area_no_summary_unset (struct ospf *ospf, struct in_addr area_id) | |
1056 | { | |
1057 | struct ospf_area *area; | |
1058 | ||
68980084 | 1059 | area = ospf_area_lookup_by_area_id (ospf, area_id); |
718e3744 | 1060 | if (area == NULL) |
1061 | return 0; | |
1062 | ||
1063 | area->no_summary = 0; | |
68980084 | 1064 | ospf_area_check_free (ospf, area_id); |
718e3744 | 1065 | |
1066 | return 1; | |
1067 | } | |
1068 | ||
1069 | int | |
1070 | ospf_area_nssa_set (struct ospf *ospf, struct in_addr area_id) | |
1071 | { | |
1072 | struct ospf_area *area; | |
147193a2 | 1073 | int format = OSPF_AREA_ID_FORMAT_ADDRESS; |
718e3744 | 1074 | |
68980084 | 1075 | area = ospf_area_get (ospf, area_id, format); |
718e3744 | 1076 | if (ospf_area_vlink_count (ospf, area)) |
1077 | return 0; | |
1078 | ||
1079 | if (area->external_routing != OSPF_AREA_NSSA) | |
1080 | { | |
1081 | ospf_area_type_set (area, OSPF_AREA_NSSA); | |
1082 | ospf->anyNSSA++; | |
1083 | } | |
1084 | ||
084c7844 | 1085 | /* set NSSA area defaults */ |
1086 | area->no_summary = 0; | |
1087 | area->NSSATranslatorRole = OSPF_NSSA_ROLE_CANDIDATE; | |
d4a53d58 | 1088 | area->NSSATranslatorState = OSPF_NSSA_TRANSLATE_DISABLED; |
084c7844 | 1089 | area->NSSATranslatorStabilityInterval = OSPF_NSSA_TRANS_STABLE_DEFAULT; |
1090 | ||
718e3744 | 1091 | return 1; |
1092 | } | |
1093 | ||
1094 | int | |
1095 | ospf_area_nssa_unset (struct ospf *ospf, struct in_addr area_id) | |
1096 | { | |
1097 | struct ospf_area *area; | |
1098 | ||
68980084 | 1099 | area = ospf_area_lookup_by_area_id (ospf, area_id); |
718e3744 | 1100 | if (area == NULL) |
1101 | return 0; | |
1102 | ||
1103 | if (area->external_routing == OSPF_AREA_NSSA) | |
1104 | { | |
1105 | ospf->anyNSSA--; | |
1106 | ospf_area_type_set (area, OSPF_AREA_DEFAULT); | |
1107 | } | |
1108 | ||
68980084 | 1109 | ospf_area_check_free (ospf, area_id); |
718e3744 | 1110 | |
1111 | return 1; | |
1112 | } | |
1113 | ||
1114 | int | |
1115 | ospf_area_nssa_translator_role_set (struct ospf *ospf, struct in_addr area_id, | |
1116 | int role) | |
1117 | { | |
1118 | struct ospf_area *area; | |
1119 | ||
68980084 | 1120 | area = ospf_area_lookup_by_area_id (ospf, area_id); |
718e3744 | 1121 | if (area == NULL) |
1122 | return 0; | |
1123 | ||
084c7844 | 1124 | area->NSSATranslatorRole = role; |
718e3744 | 1125 | |
1126 | return 1; | |
1127 | } | |
1128 | ||
4dadc291 | 1129 | /* XXX: unused? Leave for symmetry? */ |
1130 | static int | |
718e3744 | 1131 | ospf_area_nssa_translator_role_unset (struct ospf *ospf, |
1132 | struct in_addr area_id) | |
1133 | { | |
1134 | struct ospf_area *area; | |
1135 | ||
68980084 | 1136 | area = ospf_area_lookup_by_area_id (ospf, area_id); |
718e3744 | 1137 | if (area == NULL) |
1138 | return 0; | |
1139 | ||
084c7844 | 1140 | area->NSSATranslatorRole = OSPF_NSSA_ROLE_CANDIDATE; |
718e3744 | 1141 | |
68980084 | 1142 | ospf_area_check_free (ospf, area_id); |
718e3744 | 1143 | |
1144 | return 1; | |
1145 | } | |
1146 | ||
1147 | int | |
68980084 | 1148 | ospf_area_export_list_set (struct ospf *ospf, |
6c835671 | 1149 | struct ospf_area *area, const char *list_name) |
718e3744 | 1150 | { |
1151 | struct access_list *list; | |
1152 | list = access_list_lookup (AFI_IP, list_name); | |
1153 | ||
1154 | EXPORT_LIST (area) = list; | |
1155 | ||
1156 | if (EXPORT_NAME (area)) | |
1157 | free (EXPORT_NAME (area)); | |
1158 | ||
1159 | EXPORT_NAME (area) = strdup (list_name); | |
68980084 | 1160 | ospf_schedule_abr_task (ospf); |
718e3744 | 1161 | |
1162 | return 1; | |
1163 | } | |
1164 | ||
1165 | int | |
68980084 | 1166 | ospf_area_export_list_unset (struct ospf *ospf, struct ospf_area * area) |
718e3744 | 1167 | { |
1168 | ||
1169 | EXPORT_LIST (area) = 0; | |
1170 | ||
1171 | if (EXPORT_NAME (area)) | |
1172 | free (EXPORT_NAME (area)); | |
1173 | ||
1174 | EXPORT_NAME (area) = NULL; | |
1175 | ||
68980084 | 1176 | ospf_area_check_free (ospf, area->area_id); |
718e3744 | 1177 | |
68980084 | 1178 | ospf_schedule_abr_task (ospf); |
718e3744 | 1179 | |
1180 | return 1; | |
1181 | } | |
1182 | ||
1183 | int | |
6c835671 | 1184 | ospf_area_import_list_set (struct ospf *ospf, struct ospf_area *area, |
1185 | const char *name) | |
718e3744 | 1186 | { |
1187 | struct access_list *list; | |
1188 | list = access_list_lookup (AFI_IP, name); | |
1189 | ||
1190 | IMPORT_LIST (area) = list; | |
1191 | ||
1192 | if (IMPORT_NAME (area)) | |
1193 | free (IMPORT_NAME (area)); | |
1194 | ||
1195 | IMPORT_NAME (area) = strdup (name); | |
68980084 | 1196 | ospf_schedule_abr_task (ospf); |
718e3744 | 1197 | |
1198 | return 1; | |
1199 | } | |
1200 | ||
1201 | int | |
68980084 | 1202 | ospf_area_import_list_unset (struct ospf *ospf, struct ospf_area * area) |
718e3744 | 1203 | { |
1204 | IMPORT_LIST (area) = 0; | |
1205 | ||
1206 | if (IMPORT_NAME (area)) | |
1207 | free (IMPORT_NAME (area)); | |
1208 | ||
1209 | IMPORT_NAME (area) = NULL; | |
68980084 | 1210 | ospf_area_check_free (ospf, area->area_id); |
718e3744 | 1211 | |
68980084 | 1212 | ospf_schedule_abr_task (ospf); |
718e3744 | 1213 | |
1214 | return 1; | |
1215 | } | |
1216 | ||
718e3744 | 1217 | int |
1218 | ospf_timers_refresh_set (struct ospf *ospf, int interval) | |
1219 | { | |
1220 | int time_left; | |
1221 | ||
1222 | if (ospf->lsa_refresh_interval == interval) | |
1223 | return 1; | |
1224 | ||
1225 | time_left = ospf->lsa_refresh_interval - | |
1226 | (time (NULL) - ospf->lsa_refresher_started); | |
1227 | ||
1228 | if (time_left > interval) | |
1229 | { | |
1230 | OSPF_TIMER_OFF (ospf->t_lsa_refresher); | |
1231 | ospf->t_lsa_refresher = | |
1232 | thread_add_timer (master, ospf_lsa_refresh_walker, ospf, interval); | |
1233 | } | |
1234 | ospf->lsa_refresh_interval = interval; | |
1235 | ||
1236 | return 1; | |
1237 | } | |
1238 | ||
1239 | int | |
1240 | ospf_timers_refresh_unset (struct ospf *ospf) | |
1241 | { | |
1242 | int time_left; | |
1243 | ||
1244 | time_left = ospf->lsa_refresh_interval - | |
1245 | (time (NULL) - ospf->lsa_refresher_started); | |
1246 | ||
1247 | if (time_left > OSPF_LSA_REFRESH_INTERVAL_DEFAULT) | |
1248 | { | |
1249 | OSPF_TIMER_OFF (ospf->t_lsa_refresher); | |
1250 | ospf->t_lsa_refresher = | |
1251 | thread_add_timer (master, ospf_lsa_refresh_walker, ospf, | |
1252 | OSPF_LSA_REFRESH_INTERVAL_DEFAULT); | |
1253 | } | |
1254 | ||
1255 | ospf->lsa_refresh_interval = OSPF_LSA_REFRESH_INTERVAL_DEFAULT; | |
1256 | ||
1257 | return 1; | |
1258 | } | |
1259 | ||
1260 | \f | |
4dadc291 | 1261 | static struct ospf_nbr_nbma * |
1262 | ospf_nbr_nbma_new (void) | |
718e3744 | 1263 | { |
1264 | struct ospf_nbr_nbma *nbr_nbma; | |
1265 | ||
1266 | nbr_nbma = XMALLOC (MTYPE_OSPF_NEIGHBOR_STATIC, | |
1267 | sizeof (struct ospf_nbr_nbma)); | |
1268 | memset (nbr_nbma, 0, sizeof (struct ospf_nbr_nbma)); | |
1269 | ||
1270 | nbr_nbma->priority = OSPF_NEIGHBOR_PRIORITY_DEFAULT; | |
1271 | nbr_nbma->v_poll = OSPF_POLL_INTERVAL_DEFAULT; | |
1272 | ||
1273 | return nbr_nbma; | |
1274 | } | |
1275 | ||
4dadc291 | 1276 | static void |
718e3744 | 1277 | ospf_nbr_nbma_free (struct ospf_nbr_nbma *nbr_nbma) |
1278 | { | |
1279 | XFREE (MTYPE_OSPF_NEIGHBOR_STATIC, nbr_nbma); | |
1280 | } | |
1281 | ||
4dadc291 | 1282 | static void |
718e3744 | 1283 | ospf_nbr_nbma_delete (struct ospf *ospf, struct ospf_nbr_nbma *nbr_nbma) |
1284 | { | |
1285 | struct route_node *rn; | |
1286 | struct prefix_ipv4 p; | |
1287 | ||
1288 | p.family = AF_INET; | |
1289 | p.prefix = nbr_nbma->addr; | |
1290 | p.prefixlen = IPV4_MAX_BITLEN; | |
1291 | ||
1292 | rn = route_node_lookup (ospf->nbr_nbma, (struct prefix *)&p); | |
1293 | if (rn) | |
1294 | { | |
1295 | ospf_nbr_nbma_free (rn->info); | |
1296 | rn->info = NULL; | |
1297 | route_unlock_node (rn); | |
1298 | route_unlock_node (rn); | |
1299 | } | |
1300 | } | |
1301 | ||
4dadc291 | 1302 | static void |
718e3744 | 1303 | ospf_nbr_nbma_down (struct ospf_nbr_nbma *nbr_nbma) |
1304 | { | |
1305 | OSPF_TIMER_OFF (nbr_nbma->t_poll); | |
1306 | ||
1307 | if (nbr_nbma->nbr) | |
1308 | { | |
1309 | nbr_nbma->nbr->nbr_nbma = NULL; | |
1310 | OSPF_NSM_EVENT_EXECUTE (nbr_nbma->nbr, NSM_KillNbr); | |
1311 | } | |
1312 | ||
1313 | if (nbr_nbma->oi) | |
1314 | listnode_delete (nbr_nbma->oi->nbr_nbma, nbr_nbma); | |
1315 | } | |
1316 | ||
4dadc291 | 1317 | static void |
718e3744 | 1318 | ospf_nbr_nbma_add (struct ospf_nbr_nbma *nbr_nbma, |
1319 | struct ospf_interface *oi) | |
1320 | { | |
1321 | struct ospf_neighbor *nbr; | |
1322 | struct route_node *rn; | |
1323 | struct prefix p; | |
1324 | ||
1325 | if (oi->type != OSPF_IFTYPE_NBMA) | |
1326 | return; | |
1327 | ||
1328 | if (nbr_nbma->nbr != NULL) | |
1329 | return; | |
1330 | ||
1331 | if (IPV4_ADDR_SAME (&oi->nbr_self->address.u.prefix4, &nbr_nbma->addr)) | |
1332 | return; | |
1333 | ||
1334 | nbr_nbma->oi = oi; | |
1335 | listnode_add (oi->nbr_nbma, nbr_nbma); | |
1336 | ||
1337 | /* Get neighbor information from table. */ | |
1338 | p.family = AF_INET; | |
1339 | p.prefixlen = IPV4_MAX_BITLEN; | |
1340 | p.u.prefix4 = nbr_nbma->addr; | |
1341 | ||
1342 | rn = route_node_get (oi->nbrs, (struct prefix *)&p); | |
1343 | if (rn->info) | |
1344 | { | |
1345 | nbr = rn->info; | |
1346 | nbr->nbr_nbma = nbr_nbma; | |
1347 | nbr_nbma->nbr = nbr; | |
1348 | ||
1349 | route_unlock_node (rn); | |
1350 | } | |
1351 | else | |
1352 | { | |
1353 | nbr = rn->info = ospf_nbr_new (oi); | |
1354 | nbr->state = NSM_Down; | |
1355 | nbr->src = nbr_nbma->addr; | |
1356 | nbr->nbr_nbma = nbr_nbma; | |
1357 | nbr->priority = nbr_nbma->priority; | |
1358 | nbr->address = p; | |
1359 | ||
1360 | nbr_nbma->nbr = nbr; | |
1361 | ||
1362 | OSPF_NSM_EVENT_EXECUTE (nbr, NSM_Start); | |
1363 | } | |
1364 | } | |
1365 | ||
1366 | void | |
68980084 | 1367 | ospf_nbr_nbma_if_update (struct ospf *ospf, struct ospf_interface *oi) |
718e3744 | 1368 | { |
1369 | struct ospf_nbr_nbma *nbr_nbma; | |
1370 | struct route_node *rn; | |
1371 | struct prefix_ipv4 p; | |
1372 | ||
1373 | if (oi->type != OSPF_IFTYPE_NBMA) | |
1374 | return; | |
1375 | ||
68980084 | 1376 | for (rn = route_top (ospf->nbr_nbma); rn; rn = route_next (rn)) |
718e3744 | 1377 | if ((nbr_nbma = rn->info)) |
1378 | if (nbr_nbma->oi == NULL && nbr_nbma->nbr == NULL) | |
1379 | { | |
1380 | p.family = AF_INET; | |
1381 | p.prefix = nbr_nbma->addr; | |
1382 | p.prefixlen = IPV4_MAX_BITLEN; | |
1383 | ||
1384 | if (prefix_match (oi->address, (struct prefix *)&p)) | |
1385 | ospf_nbr_nbma_add (nbr_nbma, oi); | |
1386 | } | |
1387 | } | |
1388 | ||
1389 | struct ospf_nbr_nbma * | |
1390 | ospf_nbr_nbma_lookup (struct ospf *ospf, struct in_addr nbr_addr) | |
1391 | { | |
1392 | struct route_node *rn; | |
1393 | struct prefix_ipv4 p; | |
1394 | ||
1395 | p.family = AF_INET; | |
1396 | p.prefix = nbr_addr; | |
1397 | p.prefixlen = IPV4_MAX_BITLEN; | |
1398 | ||
1399 | rn = route_node_lookup (ospf->nbr_nbma, (struct prefix *)&p); | |
1400 | if (rn) | |
1401 | { | |
1402 | route_unlock_node (rn); | |
1403 | return rn->info; | |
1404 | } | |
1405 | return NULL; | |
1406 | } | |
1407 | ||
1408 | struct ospf_nbr_nbma * | |
68980084 | 1409 | ospf_nbr_nbma_lookup_next (struct ospf *ospf, struct in_addr *addr, int first) |
718e3744 | 1410 | { |
1411 | #if 0 | |
1412 | struct ospf_nbr_nbma *nbr_nbma; | |
52dc7ee6 | 1413 | struct listnode *node; |
718e3744 | 1414 | #endif |
1415 | ||
68980084 | 1416 | if (ospf == NULL) |
718e3744 | 1417 | return NULL; |
1418 | ||
1419 | #if 0 | |
1eb8ef25 | 1420 | for (ALL_LIST_ELEMENTS_RO (ospf->nbr_nbma, node, nbr_nbma)) |
718e3744 | 1421 | { |
718e3744 | 1422 | if (first) |
1423 | { | |
1424 | *addr = nbr_nbma->addr; | |
1425 | return nbr_nbma; | |
1426 | } | |
1427 | else if (ntohl (nbr_nbma->addr.s_addr) > ntohl (addr->s_addr)) | |
1428 | { | |
1429 | *addr = nbr_nbma->addr; | |
1430 | return nbr_nbma; | |
1431 | } | |
1432 | } | |
1433 | #endif | |
1434 | return NULL; | |
1435 | } | |
1436 | ||
1437 | int | |
1438 | ospf_nbr_nbma_set (struct ospf *ospf, struct in_addr nbr_addr) | |
1439 | { | |
1440 | struct ospf_nbr_nbma *nbr_nbma; | |
1441 | struct ospf_interface *oi; | |
1442 | struct prefix_ipv4 p; | |
1443 | struct route_node *rn; | |
52dc7ee6 | 1444 | struct listnode *node; |
718e3744 | 1445 | |
1446 | nbr_nbma = ospf_nbr_nbma_lookup (ospf, nbr_addr); | |
1447 | if (nbr_nbma) | |
1448 | return 0; | |
1449 | ||
1450 | nbr_nbma = ospf_nbr_nbma_new (); | |
1451 | nbr_nbma->addr = nbr_addr; | |
1452 | ||
1453 | p.family = AF_INET; | |
1454 | p.prefix = nbr_addr; | |
1455 | p.prefixlen = IPV4_MAX_BITLEN; | |
1456 | ||
1457 | rn = route_node_get (ospf->nbr_nbma, (struct prefix *)&p); | |
1458 | rn->info = nbr_nbma; | |
1459 | ||
1eb8ef25 | 1460 | for (ALL_LIST_ELEMENTS_RO (ospf->oiflist, node, oi)) |
718e3744 | 1461 | { |
718e3744 | 1462 | if (oi->type == OSPF_IFTYPE_NBMA) |
1463 | if (prefix_match (oi->address, (struct prefix *)&p)) | |
1464 | { | |
1465 | ospf_nbr_nbma_add (nbr_nbma, oi); | |
1466 | break; | |
1467 | } | |
1468 | } | |
1469 | ||
1470 | return 1; | |
1471 | } | |
1472 | ||
1473 | int | |
1474 | ospf_nbr_nbma_unset (struct ospf *ospf, struct in_addr nbr_addr) | |
1475 | { | |
1476 | struct ospf_nbr_nbma *nbr_nbma; | |
1477 | ||
1478 | nbr_nbma = ospf_nbr_nbma_lookup (ospf, nbr_addr); | |
1479 | if (nbr_nbma == NULL) | |
1480 | return 0; | |
1481 | ||
1482 | ospf_nbr_nbma_down (nbr_nbma); | |
1483 | ospf_nbr_nbma_delete (ospf, nbr_nbma); | |
1484 | ||
1485 | return 1; | |
1486 | } | |
1487 | ||
1488 | int | |
1489 | ospf_nbr_nbma_priority_set (struct ospf *ospf, struct in_addr nbr_addr, | |
1490 | u_char priority) | |
1491 | { | |
1492 | struct ospf_nbr_nbma *nbr_nbma; | |
1493 | ||
1494 | nbr_nbma = ospf_nbr_nbma_lookup (ospf, nbr_addr); | |
1495 | if (nbr_nbma == NULL) | |
1496 | return 0; | |
1497 | ||
1498 | if (nbr_nbma->priority != priority) | |
1499 | nbr_nbma->priority = priority; | |
1500 | ||
1501 | return 1; | |
1502 | } | |
1503 | ||
1504 | int | |
1505 | ospf_nbr_nbma_priority_unset (struct ospf *ospf, struct in_addr nbr_addr) | |
1506 | { | |
1507 | struct ospf_nbr_nbma *nbr_nbma; | |
1508 | ||
1509 | nbr_nbma = ospf_nbr_nbma_lookup (ospf, nbr_addr); | |
1510 | if (nbr_nbma == NULL) | |
1511 | return 0; | |
1512 | ||
1513 | if (nbr_nbma != OSPF_NEIGHBOR_PRIORITY_DEFAULT) | |
1514 | nbr_nbma->priority = OSPF_NEIGHBOR_PRIORITY_DEFAULT; | |
1515 | ||
1516 | return 1; | |
1517 | } | |
1518 | ||
1519 | int | |
1520 | ospf_nbr_nbma_poll_interval_set (struct ospf *ospf, struct in_addr nbr_addr, | |
6c835671 | 1521 | unsigned int interval) |
718e3744 | 1522 | { |
1523 | struct ospf_nbr_nbma *nbr_nbma; | |
1524 | ||
1525 | nbr_nbma = ospf_nbr_nbma_lookup (ospf, nbr_addr); | |
1526 | if (nbr_nbma == NULL) | |
1527 | return 0; | |
1528 | ||
1529 | if (nbr_nbma->v_poll != interval) | |
1530 | { | |
1531 | nbr_nbma->v_poll = interval; | |
1532 | if (nbr_nbma->oi && ospf_if_is_up (nbr_nbma->oi)) | |
1533 | { | |
1534 | OSPF_TIMER_OFF (nbr_nbma->t_poll); | |
1535 | OSPF_POLL_TIMER_ON (nbr_nbma->t_poll, ospf_poll_timer, | |
1536 | nbr_nbma->v_poll); | |
1537 | } | |
1538 | } | |
1539 | ||
1540 | return 1; | |
1541 | } | |
1542 | ||
1543 | int | |
1544 | ospf_nbr_nbma_poll_interval_unset (struct ospf *ospf, struct in_addr addr) | |
1545 | { | |
1546 | struct ospf_nbr_nbma *nbr_nbma; | |
1547 | ||
1548 | nbr_nbma = ospf_nbr_nbma_lookup (ospf, addr); | |
1549 | if (nbr_nbma == NULL) | |
1550 | return 0; | |
1551 | ||
1552 | if (nbr_nbma->v_poll != OSPF_POLL_INTERVAL_DEFAULT) | |
1553 | nbr_nbma->v_poll = OSPF_POLL_INTERVAL_DEFAULT; | |
1554 | ||
1555 | return 1; | |
1556 | } | |
1557 | ||
718e3744 | 1558 | void |
020709f9 | 1559 | ospf_master_init () |
718e3744 | 1560 | { |
020709f9 | 1561 | memset (&ospf_master, 0, sizeof (struct ospf_master)); |
1562 | ||
1563 | om = &ospf_master; | |
1564 | om->ospf = list_new (); | |
1565 | om->master = thread_master_create (); | |
1566 | om->start_time = time (NULL); | |
1567 | } |