]> git.proxmox.com Git - mirror_frr.git/blame - ospf6d/ospf6_intra.c
Merge pull request #885 from bingen/fix_debug_directive
[mirror_frr.git] / ospf6d / ospf6_intra.c
CommitLineData
718e3744 1/*
508e53e2 2 * Copyright (C) 2003 Yasuhiro Ohara
718e3744 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
18 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 * Boston, MA 02111-1307, USA.
20 */
21
508e53e2 22#include <zebra.h>
718e3744 23
508e53e2 24#include "log.h"
25#include "linklist.h"
26#include "thread.h"
27#include "memory.h"
28#include "if.h"
29#include "prefix.h"
30#include "table.h"
31#include "vty.h"
32#include "command.h"
a90607a4 33#include "vrf.h"
718e3744 34
508e53e2 35#include "ospf6_proto.h"
36#include "ospf6_message.h"
37#include "ospf6_route.h"
38#include "ospf6_lsa.h"
39#include "ospf6_lsdb.h"
40
41#include "ospf6_top.h"
42#include "ospf6_area.h"
43#include "ospf6_interface.h"
44#include "ospf6_neighbor.h"
45#include "ospf6_intra.h"
46#include "ospf6_asbr.h"
6452df09 47#include "ospf6_abr.h"
48#include "ospf6_flood.h"
049207c3 49#include "ospf6d.h"
a0edf674 50#include "ospf6_spf.h"
cb4b8845
PJ
51
52unsigned char conf_debug_ospf6_brouter = 0;
53u_int32_t conf_debug_ospf6_brouter_specific_router_id;
54u_int32_t conf_debug_ospf6_brouter_specific_area_id;
55
508e53e2 56/******************************/
57/* RFC2740 3.4.3.1 Router-LSA */
58/******************************/
718e3744 59
e68a6767
DD
60static char *
61ospf6_router_lsa_get_nbr_id (struct ospf6_lsa *lsa, char *buf, int buflen,
62 int pos)
63{
64 struct ospf6_router_lsa *router_lsa;
65 struct ospf6_router_lsdesc *lsdesc;
66 char *start, *end;
67 char buf1[INET_ADDRSTRLEN], buf2[INET_ADDRSTRLEN];
68
69 if (lsa)
70 {
71 router_lsa = (struct ospf6_router_lsa *)
72 ((char *) lsa->header + sizeof (struct ospf6_lsa_header));
73 start = (char *) router_lsa + sizeof (struct ospf6_router_lsa);
74 end = (char *) lsa->header + ntohs (lsa->header->length);
75
76 lsdesc = (struct ospf6_router_lsdesc *)
77 (start + pos*(sizeof (struct ospf6_router_lsdesc)));
78 if ((char *)lsdesc < end)
79 {
80 if (buf && (buflen > INET_ADDRSTRLEN*2))
81 {
82 inet_ntop (AF_INET, &lsdesc->neighbor_interface_id,
83 buf1, sizeof(buf1));
84 inet_ntop (AF_INET, &lsdesc->neighbor_router_id,
85 buf2, sizeof(buf2));
86 sprintf (buf, "%s/%s", buf2, buf1);
87 }
88 }
89 else
90 return NULL;
91 }
92
93 return buf;
94}
95
6ac29a51 96static int
508e53e2 97ospf6_router_lsa_show (struct vty *vty, struct ospf6_lsa *lsa)
718e3744 98{
508e53e2 99 char *start, *end, *current;
100 char buf[32], name[32], bits[16], options[32];
101 struct ospf6_router_lsa *router_lsa;
102 struct ospf6_router_lsdesc *lsdesc;
718e3744 103
508e53e2 104 router_lsa = (struct ospf6_router_lsa *)
105 ((char *) lsa->header + sizeof (struct ospf6_lsa_header));
718e3744 106
508e53e2 107 ospf6_capability_printbuf (router_lsa->bits, bits, sizeof (bits));
108 ospf6_options_printbuf (router_lsa->options, options, sizeof (options));
049207c3 109 vty_out (vty, " Bits: %s Options: %s%s", bits, options, VNL);
718e3744 110
508e53e2 111 start = (char *) router_lsa + sizeof (struct ospf6_router_lsa);
718e3744 112 end = (char *) lsa->header + ntohs (lsa->header->length);
508e53e2 113 for (current = start; current + sizeof (struct ospf6_router_lsdesc) <= end;
114 current += sizeof (struct ospf6_router_lsdesc))
115 {
116 lsdesc = (struct ospf6_router_lsdesc *) current;
117
118 if (lsdesc->type == OSPF6_ROUTER_LSDESC_POINTTOPOINT)
119 snprintf (name, sizeof (name), "Point-To-Point");
120 else if (lsdesc->type == OSPF6_ROUTER_LSDESC_TRANSIT_NETWORK)
121 snprintf (name, sizeof (name), "Transit-Network");
122 else if (lsdesc->type == OSPF6_ROUTER_LSDESC_STUB_NETWORK)
123 snprintf (name, sizeof (name), "Stub-Network");
124 else if (lsdesc->type == OSPF6_ROUTER_LSDESC_VIRTUAL_LINK)
125 snprintf (name, sizeof (name), "Virtual-Link");
718e3744 126 else
508e53e2 127 snprintf (name, sizeof (name), "Unknown (%#x)", lsdesc->type);
128
129 vty_out (vty, " Type: %s Metric: %d%s",
049207c3 130 name, ntohs (lsdesc->metric), VNL);
508e53e2 131 vty_out (vty, " Interface ID: %s%s",
132 inet_ntop (AF_INET, &lsdesc->interface_id,
049207c3 133 buf, sizeof (buf)), VNL);
508e53e2 134 vty_out (vty, " Neighbor Interface ID: %s%s",
135 inet_ntop (AF_INET, &lsdesc->neighbor_interface_id,
049207c3 136 buf, sizeof (buf)), VNL);
508e53e2 137 vty_out (vty, " Neighbor Router ID: %s%s",
138 inet_ntop (AF_INET, &lsdesc->neighbor_router_id,
049207c3 139 buf, sizeof (buf)), VNL);
718e3744 140 }
508e53e2 141 return 0;
718e3744 142}
143
ca1f4309
DS
144static void
145ospf6_router_lsa_options_set (struct ospf6_area *oa,
146 struct ospf6_router_lsa *router_lsa)
147{
148 OSPF6_OPT_CLEAR_ALL (router_lsa->options);
149 memcpy (router_lsa->options, oa->options, 3);
150
151 if (ospf6_is_router_abr (ospf6))
152 SET_FLAG (router_lsa->bits, OSPF6_ROUTER_BIT_B);
153 else
154 UNSET_FLAG (router_lsa->bits, OSPF6_ROUTER_BIT_B);
155
156 if (!IS_AREA_STUB (oa) && ospf6_asbr_is_asbr (oa->ospf6))
157 {
158 SET_FLAG (router_lsa->bits, OSPF6_ROUTER_BIT_E);
159 }
160 else
161 {
162 UNSET_FLAG (router_lsa->bits, OSPF6_ROUTER_BIT_E);
163 }
164
165 UNSET_FLAG (router_lsa->bits, OSPF6_ROUTER_BIT_V);
166 UNSET_FLAG (router_lsa->bits, OSPF6_ROUTER_BIT_W);
167}
168
f41b4a02
DD
169int
170ospf6_router_is_stub_router (struct ospf6_lsa *lsa)
171{
172 struct ospf6_router_lsa *rtr_lsa;
173
174 if (lsa != NULL && OSPF6_LSA_IS_TYPE (ROUTER, lsa))
175 {
176 rtr_lsa = (struct ospf6_router_lsa *)
177 ((caddr_t) lsa->header + sizeof (struct ospf6_lsa_header));
178
179 if (!OSPF6_OPT_ISSET (rtr_lsa->options, OSPF6_OPT_R))
180 {
181 return (OSPF6_IS_STUB_ROUTER);
182 }
183 else if (!OSPF6_OPT_ISSET (rtr_lsa->options, OSPF6_OPT_V6))
184 {
185 return (OSPF6_IS_STUB_ROUTER_V6);
186 }
187 }
188
189 return (OSPF6_NOT_STUB_ROUTER);
190}
191
6452df09 192int
193ospf6_router_lsa_originate (struct thread *thread)
718e3744 194{
6452df09 195 struct ospf6_area *oa;
196
508e53e2 197 char buffer [OSPF6_MAX_LSASIZE];
198 struct ospf6_lsa_header *lsa_header;
199 struct ospf6_lsa *lsa;
200
201 u_int32_t link_state_id = 0;
1eb8ef25 202 struct listnode *node, *nnode;
203 struct listnode *j;
508e53e2 204 struct ospf6_interface *oi;
205 struct ospf6_neighbor *on, *drouter = NULL;
206 struct ospf6_router_lsa *router_lsa;
207 struct ospf6_router_lsdesc *lsdesc;
208 u_int16_t type;
209 u_int32_t router;
210 int count;
718e3744 211
6452df09 212 oa = (struct ospf6_area *) THREAD_ARG (thread);
213 oa->thread_router_lsa = NULL;
214
1e05838a 215 if (IS_OSPF6_DEBUG_ORIGINATE (ROUTER))
c6487d61 216 zlog_debug ("Originate Router-LSA for Area %s", oa->name);
718e3744 217
508e53e2 218 memset (buffer, 0, sizeof (buffer));
219 lsa_header = (struct ospf6_lsa_header *) buffer;
220 router_lsa = (struct ospf6_router_lsa *)
221 ((caddr_t) lsa_header + sizeof (struct ospf6_lsa_header));
222
ca1f4309 223 ospf6_router_lsa_options_set (oa, router_lsa);
718e3744 224
508e53e2 225 /* describe links for each interfaces */
226 lsdesc = (struct ospf6_router_lsdesc *)
227 ((caddr_t) router_lsa + sizeof (struct ospf6_router_lsa));
718e3744 228
1eb8ef25 229 for (ALL_LIST_ELEMENTS (oa->if_list, node, nnode, oi))
718e3744 230 {
508e53e2 231 /* Interfaces in state Down or Loopback are not described */
232 if (oi->state == OSPF6_INTERFACE_DOWN ||
233 oi->state == OSPF6_INTERFACE_LOOPBACK)
234 continue;
235
236 /* Nor are interfaces without any full adjacencies described */
237 count = 0;
1eb8ef25 238 for (ALL_LIST_ELEMENTS_RO (oi->neighbor_list, j, on))
239 if (on->state == OSPF6_NEIGHBOR_FULL)
240 count++;
c3c0ac83 241
508e53e2 242 if (count == 0)
243 continue;
244
245 /* Multiple Router-LSA instance according to size limit setting */
0c083ee9 246 if ( (oa->router_lsa_size_limit != 0)
ee046671
DS
247 && ((size_t)((char *)lsdesc - buffer)
248 + sizeof (struct ospf6_router_lsdesc)
249 > oa->router_lsa_size_limit))
508e53e2 250 {
251 if ((caddr_t) lsdesc == (caddr_t) router_lsa +
252 sizeof (struct ospf6_router_lsa))
253 {
1e05838a 254 if (IS_OSPF6_DEBUG_ORIGINATE (ROUTER))
c6487d61 255 zlog_debug ("Size limit setting for Router-LSA too short");
6452df09 256 return 0;
508e53e2 257 }
258
508e53e2 259 link_state_id ++;
260 }
261
262 /* Point-to-Point interfaces */
c5926a92 263 if (oi->type == OSPF_IFTYPE_POINTOPOINT)
508e53e2 264 {
1eb8ef25 265 for (ALL_LIST_ELEMENTS_RO (oi->neighbor_list, j, on))
508e53e2 266 {
508e53e2 267 if (on->state != OSPF6_NEIGHBOR_FULL)
268 continue;
269
270 lsdesc->type = OSPF6_ROUTER_LSDESC_POINTTOPOINT;
271 lsdesc->metric = htons (oi->cost);
272 lsdesc->interface_id = htonl (oi->interface->ifindex);
273 lsdesc->neighbor_interface_id = htonl (on->ifindex);
274 lsdesc->neighbor_router_id = on->router_id;
275
276 lsdesc++;
277 }
278 }
279
280 /* Broadcast and NBMA interfaces */
c5926a92 281 else if (oi->type == OSPF_IFTYPE_BROADCAST)
508e53e2 282 {
283 /* If this router is not DR,
284 and If this router not fully adjacent with DR,
285 this interface is not transit yet: ignore. */
286 if (oi->state != OSPF6_INTERFACE_DR)
287 {
288 drouter = ospf6_neighbor_lookup (oi->drouter, oi);
289 if (drouter == NULL || drouter->state != OSPF6_NEIGHBOR_FULL)
290 continue;
291 }
292
293 lsdesc->type = OSPF6_ROUTER_LSDESC_TRANSIT_NETWORK;
294 lsdesc->metric = htons (oi->cost);
295 lsdesc->interface_id = htonl (oi->interface->ifindex);
296 if (oi->state != OSPF6_INTERFACE_DR)
297 {
298 lsdesc->neighbor_interface_id = htonl (drouter->ifindex);
299 lsdesc->neighbor_router_id = drouter->router_id;
300 }
301 else
302 {
303 lsdesc->neighbor_interface_id = htonl (oi->interface->ifindex);
304 lsdesc->neighbor_router_id = oi->area->ospf6->router_id;
305 }
306
307 lsdesc++;
308 }
c5926a92
DD
309 else
310 {
311 assert (0); /* Unknown interface type */
312 }
508e53e2 313
314 /* Virtual links */
315 /* xxx */
316 /* Point-to-Multipoint interfaces */
317 /* xxx */
718e3744 318 }
319
17d003da
DD
320 /* Fill LSA Header */
321 lsa_header->age = 0;
322 lsa_header->type = htons (OSPF6_LSTYPE_ROUTER);
323 lsa_header->id = htonl (link_state_id);
324 lsa_header->adv_router = oa->ospf6->router_id;
325 lsa_header->seqnum =
326 ospf6_new_ls_seqnum (lsa_header->type, lsa_header->id,
327 lsa_header->adv_router, oa->lsdb);
328 lsa_header->length = htons ((caddr_t) lsdesc - (caddr_t) buffer);
329
330 /* LSA checksum */
331 ospf6_lsa_checksum (lsa_header);
332
333 /* create LSA */
334 lsa = ospf6_lsa_create (lsa_header);
335
336 /* Originate */
337 ospf6_lsa_originate_area (lsa, oa);
338
339 link_state_id ++;
718e3744 340
508e53e2 341 /* Do premature-aging of rest, undesired Router-LSAs */
342 type = ntohs (OSPF6_LSTYPE_ROUTER);
343 router = oa->ospf6->router_id;
c3c0ac83 344 count = 0;
508e53e2 345 for (lsa = ospf6_lsdb_type_router_head (type, router, oa->lsdb); lsa;
346 lsa = ospf6_lsdb_type_router_next (type, router, lsa))
718e3744 347 {
508e53e2 348 if (ntohl (lsa->header->id) < link_state_id)
349 continue;
6452df09 350 ospf6_lsa_purge (lsa);
c3c0ac83 351 count++;
718e3744 352 }
718e3744 353
c3c0ac83
DS
354 /*
355 * Waiting till the LSA is actually removed from the database to trigger
356 * SPF delays network convergence. Unlike IPv4, for an ABR, when all
357 * interfaces associated with an area are gone, triggering an SPF right away
358 * helps convergence with inter-area routes.
359 */
360 if (count && !link_state_id)
361 ospf6_spf_schedule (oa->ospf6, OSPF6_SPF_FLAGS_ROUTER_LSA_ORIGINATED);
362
508e53e2 363 return 0;
364}
718e3744 365
508e53e2 366/*******************************/
367/* RFC2740 3.4.3.2 Network-LSA */
368/*******************************/
718e3744 369
e68a6767
DD
370static char *
371ospf6_network_lsa_get_ar_id (struct ospf6_lsa *lsa, char *buf, int buflen,
372 int pos)
373{
374 char *start, *end, *current;
375 struct ospf6_network_lsa *network_lsa;
376 struct ospf6_network_lsdesc *lsdesc;
377
378 if (lsa)
379 {
380 network_lsa = (struct ospf6_network_lsa *)
381 ((caddr_t) lsa->header + sizeof (struct ospf6_lsa_header));
382
383 start = (char *) network_lsa + sizeof (struct ospf6_network_lsa);
384 end = (char *) lsa->header + ntohs (lsa->header->length);
385 current = start + pos*(sizeof (struct ospf6_network_lsdesc));
386
387 if ((current + sizeof(struct ospf6_network_lsdesc)) <= end)
388 {
389 lsdesc = (struct ospf6_network_lsdesc *)current;
390 if (buf)
391 inet_ntop (AF_INET, &lsdesc->router_id, buf, buflen);
392 }
393 else
394 return NULL;
395 }
396
397 return (buf);
398}
399
6ac29a51 400static int
508e53e2 401ospf6_network_lsa_show (struct vty *vty, struct ospf6_lsa *lsa)
402{
403 char *start, *end, *current;
404 struct ospf6_network_lsa *network_lsa;
405 struct ospf6_network_lsdesc *lsdesc;
406 char buf[128], options[32];
407
408 network_lsa = (struct ospf6_network_lsa *)
409 ((caddr_t) lsa->header + sizeof (struct ospf6_lsa_header));
410
411 ospf6_options_printbuf (network_lsa->options, options, sizeof (options));
049207c3 412 vty_out (vty, " Options: %s%s", options, VNL);
718e3744 413
508e53e2 414 start = (char *) network_lsa + sizeof (struct ospf6_network_lsa);
415 end = (char *) lsa->header + ntohs (lsa->header->length);
416 for (current = start; current + sizeof (struct ospf6_network_lsdesc) <= end;
417 current += sizeof (struct ospf6_network_lsdesc))
718e3744 418 {
508e53e2 419 lsdesc = (struct ospf6_network_lsdesc *) current;
420 inet_ntop (AF_INET, &lsdesc->router_id, buf, sizeof (buf));
049207c3 421 vty_out (vty, " Attached Router: %s%s", buf, VNL);
718e3744 422 }
423 return 0;
424}
425
6452df09 426int
427ospf6_network_lsa_originate (struct thread *thread)
718e3744 428{
6452df09 429 struct ospf6_interface *oi;
430
508e53e2 431 char buffer [OSPF6_MAX_LSASIZE];
432 struct ospf6_lsa_header *lsa_header;
718e3744 433
508e53e2 434 int count;
435 struct ospf6_lsa *old, *lsa;
436 struct ospf6_network_lsa *network_lsa;
437 struct ospf6_network_lsdesc *lsdesc;
438 struct ospf6_neighbor *on;
439 struct ospf6_link_lsa *link_lsa;
52dc7ee6 440 struct listnode *i;
508e53e2 441 u_int16_t type;
442
6452df09 443 oi = (struct ospf6_interface *) THREAD_ARG (thread);
444 oi->thread_network_lsa = NULL;
445
446 /* The interface must be enabled until here. A Network-LSA of a
447 disabled interface (but was once enabled) should be flushed
448 by ospf6_lsa_refresh (), and does not come here. */
449 assert (oi->area);
718e3744 450
508e53e2 451 old = ospf6_lsdb_lookup (htons (OSPF6_LSTYPE_NETWORK),
452 htonl (oi->interface->ifindex),
453 oi->area->ospf6->router_id, oi->area->lsdb);
718e3744 454
508e53e2 455 /* Do not originate Network-LSA if not DR */
456 if (oi->state != OSPF6_INTERFACE_DR)
718e3744 457 {
508e53e2 458 if (old)
c3c0ac83
DS
459 {
460 ospf6_lsa_purge (old);
461 /*
462 * Waiting till the LSA is actually removed from the database to
463 * trigger SPF delays network convergence.
464 */
465 ospf6_spf_schedule (oi->area->ospf6,
466 OSPF6_SPF_FLAGS_NETWORK_LSA_ORIGINATED);
467 }
6452df09 468 return 0;
508e53e2 469 }
718e3744 470
1e05838a 471 if (IS_OSPF6_DEBUG_ORIGINATE (NETWORK))
c6487d61 472 zlog_debug ("Originate Network-LSA for Interface %s", oi->interface->name);
718e3744 473
508e53e2 474 /* If none of neighbor is adjacent to us */
475 count = 0;
c3c0ac83 476
1eb8ef25 477 for (ALL_LIST_ELEMENTS_RO (oi->neighbor_list, i, on))
478 if (on->state == OSPF6_NEIGHBOR_FULL)
479 count++;
c3c0ac83 480
508e53e2 481 if (count == 0)
482 {
1e05838a 483 if (IS_OSPF6_DEBUG_ORIGINATE (NETWORK))
c6487d61 484 zlog_debug ("Interface stub, ignore");
508e53e2 485 if (old)
6452df09 486 ospf6_lsa_purge (old);
487 return 0;
718e3744 488 }
718e3744 489
508e53e2 490 /* prepare buffer */
491 memset (buffer, 0, sizeof (buffer));
492 lsa_header = (struct ospf6_lsa_header *) buffer;
493 network_lsa = (struct ospf6_network_lsa *)
494 ((caddr_t) lsa_header + sizeof (struct ospf6_lsa_header));
495
496 /* Collect the interface's Link-LSAs to describe
497 network's optional capabilities */
498 type = htons (OSPF6_LSTYPE_LINK);
499 for (lsa = ospf6_lsdb_type_head (type, oi->lsdb); lsa;
500 lsa = ospf6_lsdb_type_next (type, lsa))
501 {
502 link_lsa = (struct ospf6_link_lsa *)
503 ((caddr_t) lsa->header + sizeof (struct ospf6_lsa_header));
504 network_lsa->options[0] |= link_lsa->options[0];
505 network_lsa->options[1] |= link_lsa->options[1];
506 network_lsa->options[2] |= link_lsa->options[2];
507 }
718e3744 508
508e53e2 509 lsdesc = (struct ospf6_network_lsdesc *)
510 ((caddr_t) network_lsa + sizeof (struct ospf6_network_lsa));
718e3744 511
508e53e2 512 /* set Link Description to the router itself */
513 lsdesc->router_id = oi->area->ospf6->router_id;
514 lsdesc++;
718e3744 515
508e53e2 516 /* Walk through the neighbors */
1eb8ef25 517 for (ALL_LIST_ELEMENTS_RO (oi->neighbor_list, i, on))
718e3744 518 {
508e53e2 519 if (on->state != OSPF6_NEIGHBOR_FULL)
718e3744 520 continue;
521
508e53e2 522 /* set this neighbor's Router-ID to LSA */
523 lsdesc->router_id = on->router_id;
524 lsdesc++;
525 }
718e3744 526
508e53e2 527 /* Fill LSA Header */
528 lsa_header->age = 0;
529 lsa_header->type = htons (OSPF6_LSTYPE_NETWORK);
530 lsa_header->id = htonl (oi->interface->ifindex);
531 lsa_header->adv_router = oi->area->ospf6->router_id;
532 lsa_header->seqnum =
049207c3 533 ospf6_new_ls_seqnum (lsa_header->type, lsa_header->id,
534 lsa_header->adv_router, oi->area->lsdb);
508e53e2 535 lsa_header->length = htons ((caddr_t) lsdesc - (caddr_t) buffer);
536
537 /* LSA checksum */
538 ospf6_lsa_checksum (lsa_header);
539
540 /* create LSA */
541 lsa = ospf6_lsa_create (lsa_header);
508e53e2 542
543 /* Originate */
6452df09 544 ospf6_lsa_originate_area (lsa, oi->area);
508e53e2 545
546 return 0;
547}
718e3744 548
549
508e53e2 550/****************************/
551/* RFC2740 3.4.3.6 Link-LSA */
552/****************************/
553
e68a6767
DD
554static char *
555ospf6_link_lsa_get_prefix_str (struct ospf6_lsa *lsa, char *buf, int buflen,
556 int pos)
557{
558 char *start, *end, *current;
559 struct ospf6_link_lsa *link_lsa;
560 struct in6_addr in6;
561 struct ospf6_prefix *prefix;
562 int cnt = 0, prefixnum;
563
564 if (lsa)
565 {
566 link_lsa = (struct ospf6_link_lsa *)
567 ((caddr_t) lsa->header + sizeof (struct ospf6_lsa_header));
568
569 if (pos == 0) {
570 inet_ntop (AF_INET6, &link_lsa->linklocal_addr, buf, buflen);
571 return (buf);
572 }
573
574 prefixnum = ntohl (link_lsa->prefix_num);
575 if (pos > prefixnum)
576 return (NULL);
577
578 start = (char *) link_lsa + sizeof (struct ospf6_link_lsa);
579 end = (char *) lsa->header + ntohs (lsa->header->length);
580 current = start;
581
582 do
583 {
584 prefix = (struct ospf6_prefix *) current;
585 if (prefix->prefix_length == 0 ||
586 current + OSPF6_PREFIX_SIZE (prefix) > end)
587 {
588 return (NULL);
589 }
590
591 if (cnt < pos)
592 {
593 current = start + pos*OSPF6_PREFIX_SIZE(prefix);
594 cnt++;
595 }
596 else
597 {
598 memset (&in6, 0, sizeof (in6));
599 memcpy (&in6, OSPF6_PREFIX_BODY (prefix),
600 OSPF6_PREFIX_SPACE (prefix->prefix_length));
601 inet_ntop (AF_INET6, &in6, buf, buflen);
602 return (buf);
603 }
604 } while (current <= end);
605 }
606 return (NULL);
607}
608
6ac29a51 609static int
508e53e2 610ospf6_link_lsa_show (struct vty *vty, struct ospf6_lsa *lsa)
718e3744 611{
508e53e2 612 char *start, *end, *current;
613 struct ospf6_link_lsa *link_lsa;
614 int prefixnum;
615 char buf[128], options[32];
718e3744 616 struct ospf6_prefix *prefix;
0c083ee9 617 const char *p, *mc, *la, *nu;
718e3744 618 struct in6_addr in6;
718e3744 619
508e53e2 620 link_lsa = (struct ospf6_link_lsa *)
621 ((caddr_t) lsa->header + sizeof (struct ospf6_lsa_header));
718e3744 622
508e53e2 623 ospf6_options_printbuf (link_lsa->options, options, sizeof (options));
624 inet_ntop (AF_INET6, &link_lsa->linklocal_addr, buf, sizeof (buf));
625 prefixnum = ntohl (link_lsa->prefix_num);
718e3744 626
508e53e2 627 vty_out (vty, " Priority: %d Options: %s%s",
049207c3 628 link_lsa->priority, options, VNL);
629 vty_out (vty, " LinkLocal Address: %s%s", buf, VNL);
630 vty_out (vty, " Number of Prefix: %d%s", prefixnum, VNL);
718e3744 631
508e53e2 632 start = (char *) link_lsa + sizeof (struct ospf6_link_lsa);
633 end = (char *) lsa->header + ntohs (lsa->header->length);
718e3744 634 for (current = start; current < end; current += OSPF6_PREFIX_SIZE (prefix))
635 {
636 prefix = (struct ospf6_prefix *) current;
508e53e2 637 if (prefix->prefix_length == 0 ||
638 current + OSPF6_PREFIX_SIZE (prefix) > end)
639 break;
640
641 p = (CHECK_FLAG (prefix->prefix_options, OSPF6_PREFIX_OPTION_P) ?
642 "P" : "--");
643 mc = (CHECK_FLAG (prefix->prefix_options, OSPF6_PREFIX_OPTION_MC) ?
644 "MC" : "--");
645 la = (CHECK_FLAG (prefix->prefix_options, OSPF6_PREFIX_OPTION_LA) ?
646 "LA" : "--");
647 nu = (CHECK_FLAG (prefix->prefix_options, OSPF6_PREFIX_OPTION_NU) ?
648 "NU" : "--");
649 vty_out (vty, " Prefix Options: %s|%s|%s|%s%s",
049207c3 650 p, mc, la, nu, VNL);
508e53e2 651
652 memset (&in6, 0, sizeof (in6));
653 memcpy (&in6, OSPF6_PREFIX_BODY (prefix),
654 OSPF6_PREFIX_SPACE (prefix->prefix_length));
718e3744 655 inet_ntop (AF_INET6, &in6, buf, sizeof (buf));
656 vty_out (vty, " Prefix: %s/%d%s",
049207c3 657 buf, prefix->prefix_length, VNL);
718e3744 658 }
659
660 return 0;
661}
662
6452df09 663int
664ospf6_link_lsa_originate (struct thread *thread)
718e3744 665{
6452df09 666 struct ospf6_interface *oi;
667
508e53e2 668 char buffer[OSPF6_MAX_LSASIZE];
669 struct ospf6_lsa_header *lsa_header;
670 struct ospf6_lsa *old, *lsa;
718e3744 671
508e53e2 672 struct ospf6_link_lsa *link_lsa;
673 struct ospf6_route *route;
674 struct ospf6_prefix *op;
718e3744 675
6452df09 676 oi = (struct ospf6_interface *) THREAD_ARG (thread);
677 oi->thread_link_lsa = NULL;
678
679 assert (oi->area);
718e3744 680
681 /* find previous LSA */
508e53e2 682 old = ospf6_lsdb_lookup (htons (OSPF6_LSTYPE_LINK),
683 htonl (oi->interface->ifindex),
684 oi->area->ospf6->router_id, oi->lsdb);
718e3744 685
508e53e2 686 if (CHECK_FLAG (oi->flag, OSPF6_INTERFACE_DISABLE))
718e3744 687 {
688 if (old)
6452df09 689 ospf6_lsa_purge (old);
690 return 0;
718e3744 691 }
692
1e05838a 693 if (IS_OSPF6_DEBUG_ORIGINATE (LINK))
c6487d61 694 zlog_debug ("Originate Link-LSA for Interface %s", oi->interface->name);
508e53e2 695
696 /* can't make Link-LSA if linklocal address not set */
697 if (oi->linklocal_addr == NULL)
718e3744 698 {
1e05838a 699 if (IS_OSPF6_DEBUG_ORIGINATE (LINK))
c6487d61 700 zlog_debug ("No Linklocal address on %s, defer originating",
508e53e2 701 oi->interface->name);
718e3744 702 if (old)
6452df09 703 ospf6_lsa_purge (old);
704 return 0;
718e3744 705 }
706
508e53e2 707 /* prepare buffer */
708 memset (buffer, 0, sizeof (buffer));
709 lsa_header = (struct ospf6_lsa_header *) buffer;
710 link_lsa = (struct ospf6_link_lsa *)
711 ((caddr_t) lsa_header + sizeof (struct ospf6_lsa_header));
712
713 /* Fill Link-LSA */
714 link_lsa->priority = oi->priority;
715 memcpy (link_lsa->options, oi->area->options, 3);
716 memcpy (&link_lsa->linklocal_addr, oi->linklocal_addr,
717 sizeof (struct in6_addr));
718 link_lsa->prefix_num = htonl (oi->route_connected->count);
719
720 op = (struct ospf6_prefix *)
721 ((caddr_t) link_lsa + sizeof (struct ospf6_link_lsa));
722
723 /* connected prefix to advertise */
724 for (route = ospf6_route_head (oi->route_connected); route;
725 route = ospf6_route_next (route))
718e3744 726 {
508e53e2 727 op->prefix_length = route->prefix.prefixlen;
728 op->prefix_options = route->path.prefix_options;
729 op->prefix_metric = htons (0);
730 memcpy (OSPF6_PREFIX_BODY (op), &route->prefix.u.prefix6,
731 OSPF6_PREFIX_SPACE (op->prefix_length));
732 op = OSPF6_PREFIX_NEXT (op);
733 }
718e3744 734
508e53e2 735 /* Fill LSA Header */
736 lsa_header->age = 0;
737 lsa_header->type = htons (OSPF6_LSTYPE_LINK);
738 lsa_header->id = htonl (oi->interface->ifindex);
739 lsa_header->adv_router = oi->area->ospf6->router_id;
740 lsa_header->seqnum =
049207c3 741 ospf6_new_ls_seqnum (lsa_header->type, lsa_header->id,
742 lsa_header->adv_router, oi->lsdb);
508e53e2 743 lsa_header->length = htons ((caddr_t) op - (caddr_t) buffer);
744
745 /* LSA checksum */
746 ospf6_lsa_checksum (lsa_header);
747
748 /* create LSA */
749 lsa = ospf6_lsa_create (lsa_header);
508e53e2 750
751 /* Originate */
6452df09 752 ospf6_lsa_originate_interface (lsa, oi);
718e3744 753
508e53e2 754 return 0;
755}
718e3744 756
718e3744 757
508e53e2 758/*****************************************/
759/* RFC2740 3.4.3.7 Intra-Area-Prefix-LSA */
760/*****************************************/
e68a6767
DD
761static char *
762ospf6_intra_prefix_lsa_get_prefix_str (struct ospf6_lsa *lsa, char *buf,
763 int buflen, int pos)
764{
765 char *start, *end, *current;
766 struct ospf6_intra_prefix_lsa *intra_prefix_lsa;
767 struct in6_addr in6;
768 int prefixnum, cnt = 0;
769 struct ospf6_prefix *prefix;
770
771 if (lsa)
772 {
773 intra_prefix_lsa = (struct ospf6_intra_prefix_lsa *)
774 ((caddr_t) lsa->header + sizeof (struct ospf6_lsa_header));
775
776 prefixnum = ntohs (intra_prefix_lsa->prefix_num);
777 if (pos > prefixnum)
778 return (NULL);
779
780 start = (char *) intra_prefix_lsa + sizeof (struct ospf6_intra_prefix_lsa);
781 end = (char *) lsa->header + ntohs (lsa->header->length);
782 current = start;
783
784 do
785 {
786 prefix = (struct ospf6_prefix *) current;
787 if (prefix->prefix_length == 0 ||
788 current + OSPF6_PREFIX_SIZE (prefix) > end)
789 {
790 return NULL;
791 }
792
793 if (cnt < pos)
794 {
795 current = start + pos*OSPF6_PREFIX_SIZE(prefix);
796 cnt++;
797 }
798 else
799 {
800 memset (&in6, 0, sizeof (in6));
801 memcpy (&in6, OSPF6_PREFIX_BODY (prefix),
802 OSPF6_PREFIX_SPACE (prefix->prefix_length));
803 inet_ntop (AF_INET6, &in6, buf, buflen);
804 sprintf(&buf[strlen(buf)], "/%d", prefix->prefix_length);
805 return (buf);
806 }
807 } while (current <= end);
808 }
809 return (buf);
810}
718e3744 811
6ac29a51 812static int
508e53e2 813ospf6_intra_prefix_lsa_show (struct vty *vty, struct ospf6_lsa *lsa)
814{
815 char *start, *end, *current;
816 struct ospf6_intra_prefix_lsa *intra_prefix_lsa;
817 int prefixnum;
818 char buf[128];
819 struct ospf6_prefix *prefix;
820 char id[16], adv_router[16];
0c083ee9 821 const char *p, *mc, *la, *nu;
508e53e2 822 struct in6_addr in6;
718e3744 823
508e53e2 824 intra_prefix_lsa = (struct ospf6_intra_prefix_lsa *)
825 ((caddr_t) lsa->header + sizeof (struct ospf6_lsa_header));
718e3744 826
508e53e2 827 prefixnum = ntohs (intra_prefix_lsa->prefix_num);
718e3744 828
049207c3 829 vty_out (vty, " Number of Prefix: %d%s", prefixnum, VNL);
718e3744 830
508e53e2 831 inet_ntop (AF_INET, &intra_prefix_lsa->ref_id, id, sizeof (id));
832 inet_ntop (AF_INET, &intra_prefix_lsa->ref_adv_router,
833 adv_router, sizeof (adv_router));
834 vty_out (vty, " Reference: %s Id: %s Adv: %s%s",
1e05838a 835 ospf6_lstype_name (intra_prefix_lsa->ref_type), id, adv_router,
049207c3 836 VNL);
718e3744 837
508e53e2 838 start = (char *) intra_prefix_lsa + sizeof (struct ospf6_intra_prefix_lsa);
839 end = (char *) lsa->header + ntohs (lsa->header->length);
840 for (current = start; current < end; current += OSPF6_PREFIX_SIZE (prefix))
718e3744 841 {
508e53e2 842 prefix = (struct ospf6_prefix *) current;
843 if (prefix->prefix_length == 0 ||
844 current + OSPF6_PREFIX_SIZE (prefix) > end)
845 break;
846
847 p = (CHECK_FLAG (prefix->prefix_options, OSPF6_PREFIX_OPTION_P) ?
848 "P" : "--");
849 mc = (CHECK_FLAG (prefix->prefix_options, OSPF6_PREFIX_OPTION_MC) ?
850 "MC" : "--");
851 la = (CHECK_FLAG (prefix->prefix_options, OSPF6_PREFIX_OPTION_LA) ?
852 "LA" : "--");
853 nu = (CHECK_FLAG (prefix->prefix_options, OSPF6_PREFIX_OPTION_NU) ?
854 "NU" : "--");
855 vty_out (vty, " Prefix Options: %s|%s|%s|%s%s",
049207c3 856 p, mc, la, nu, VNL);
508e53e2 857
858 memset (&in6, 0, sizeof (in6));
859 memcpy (&in6, OSPF6_PREFIX_BODY (prefix),
860 OSPF6_PREFIX_SPACE (prefix->prefix_length));
861 inet_ntop (AF_INET6, &in6, buf, sizeof (buf));
862 vty_out (vty, " Prefix: %s/%d%s",
049207c3 863 buf, prefix->prefix_length, VNL);
718e3744 864 }
718e3744 865
508e53e2 866 return 0;
718e3744 867}
868
6452df09 869int
870ospf6_intra_prefix_lsa_originate_stub (struct thread *thread)
718e3744 871{
6452df09 872 struct ospf6_area *oa;
873
508e53e2 874 char buffer[OSPF6_MAX_LSASIZE];
875 struct ospf6_lsa_header *lsa_header;
876 struct ospf6_lsa *old, *lsa;
877
878 struct ospf6_intra_prefix_lsa *intra_prefix_lsa;
879 struct ospf6_interface *oi;
880 struct ospf6_neighbor *on;
881 struct ospf6_route *route;
882 struct ospf6_prefix *op;
52dc7ee6 883 struct listnode *i, *j;
508e53e2 884 int full_count = 0;
885 unsigned short prefix_num = 0;
4690c7d7 886 char buf[PREFIX2STR_BUFFER];
508e53e2 887 struct ospf6_route_table *route_advertise;
718e3744 888
6452df09 889 oa = (struct ospf6_area *) THREAD_ARG (thread);
890 oa->thread_intra_prefix_lsa = NULL;
891
508e53e2 892 /* find previous LSA */
893 old = ospf6_lsdb_lookup (htons (OSPF6_LSTYPE_INTRA_PREFIX),
894 htonl (0), oa->ospf6->router_id, oa->lsdb);
718e3744 895
6452df09 896 if (! IS_AREA_ENABLED (oa))
718e3744 897 {
508e53e2 898 if (old)
6452df09 899 ospf6_lsa_purge (old);
900 return 0;
718e3744 901 }
718e3744 902
1e05838a 903 if (IS_OSPF6_DEBUG_ORIGINATE (INTRA_PREFIX))
c6487d61 904 zlog_debug ("Originate Intra-Area-Prefix-LSA for area %s's stub prefix",
508e53e2 905 oa->name);
906
907 /* prepare buffer */
908 memset (buffer, 0, sizeof (buffer));
909 lsa_header = (struct ospf6_lsa_header *) buffer;
910 intra_prefix_lsa = (struct ospf6_intra_prefix_lsa *)
911 ((caddr_t) lsa_header + sizeof (struct ospf6_lsa_header));
912
913 /* Fill Intra-Area-Prefix-LSA */
914 intra_prefix_lsa->ref_type = htons (OSPF6_LSTYPE_ROUTER);
915 intra_prefix_lsa->ref_id = htonl (0);
916 intra_prefix_lsa->ref_adv_router = oa->ospf6->router_id;
718e3744 917
cf1ce250 918 route_advertise = ospf6_route_table_create (0, 0);
718e3744 919
1eb8ef25 920 for (ALL_LIST_ELEMENTS_RO (oa->if_list, i, oi))
718e3744 921 {
508e53e2 922 if (oi->state == OSPF6_INTERFACE_DOWN)
718e3744 923 {
1e05838a 924 if (IS_OSPF6_DEBUG_ORIGINATE (INTRA_PREFIX))
c6487d61 925 zlog_debug (" Interface %s is down, ignore", oi->interface->name);
718e3744 926 continue;
927 }
928
508e53e2 929 full_count = 0;
1eb8ef25 930
931 for (ALL_LIST_ELEMENTS_RO (oi->neighbor_list, j, on))
932 if (on->state == OSPF6_NEIGHBOR_FULL)
933 full_count++;
934
508e53e2 935 if (oi->state != OSPF6_INTERFACE_LOOPBACK &&
936 oi->state != OSPF6_INTERFACE_POINTTOPOINT &&
937 full_count != 0)
718e3744 938 {
1e05838a 939 if (IS_OSPF6_DEBUG_ORIGINATE (INTRA_PREFIX))
c6487d61 940 zlog_debug (" Interface %s is not stub, ignore",
508e53e2 941 oi->interface->name);
718e3744 942 continue;
943 }
944
1e05838a 945 if (IS_OSPF6_DEBUG_ORIGINATE (INTRA_PREFIX))
c6487d61 946 zlog_debug (" Interface %s:", oi->interface->name);
718e3744 947
508e53e2 948 /* connected prefix to advertise */
949 for (route = ospf6_route_head (oi->route_connected); route;
950 route = ospf6_route_best_next (route))
718e3744 951 {
1e05838a 952 if (IS_OSPF6_DEBUG_ORIGINATE (INTRA_PREFIX))
508e53e2 953 {
954 prefix2str (&route->prefix, buf, sizeof (buf));
c6487d61 955 zlog_debug (" include %s", buf);
508e53e2 956 }
957 ospf6_route_add (ospf6_route_copy (route), route_advertise);
958 }
959 }
718e3744 960
508e53e2 961 if (route_advertise->count == 0)
962 {
963 if (old)
6452df09 964 ospf6_lsa_purge (old);
508e53e2 965 ospf6_route_table_delete (route_advertise);
6452df09 966 return 0;
508e53e2 967 }
718e3744 968
508e53e2 969 /* put prefixes to advertise */
970 prefix_num = 0;
971 op = (struct ospf6_prefix *)
972 ((caddr_t) intra_prefix_lsa + sizeof (struct ospf6_intra_prefix_lsa));
973 for (route = ospf6_route_head (route_advertise); route;
974 route = ospf6_route_best_next (route))
975 {
976 op->prefix_length = route->prefix.prefixlen;
977 op->prefix_options = route->path.prefix_options;
978 op->prefix_metric = htons (route->path.cost);
979 memcpy (OSPF6_PREFIX_BODY (op), &route->prefix.u.prefix6,
980 OSPF6_PREFIX_SPACE (op->prefix_length));
981 op = OSPF6_PREFIX_NEXT (op);
982 prefix_num++;
983 }
718e3744 984
508e53e2 985 ospf6_route_table_delete (route_advertise);
718e3744 986
508e53e2 987 if (prefix_num == 0)
988 {
1e05838a 989 if (IS_OSPF6_DEBUG_ORIGINATE (INTRA_PREFIX))
c6487d61 990 zlog_debug ("Quit to Advertise Intra-Prefix: no route to advertise");
6452df09 991 return 0;
508e53e2 992 }
718e3744 993
508e53e2 994 intra_prefix_lsa->prefix_num = htons (prefix_num);
995
996 /* Fill LSA Header */
997 lsa_header->age = 0;
998 lsa_header->type = htons (OSPF6_LSTYPE_INTRA_PREFIX);
999 lsa_header->id = htonl (0);
1000 lsa_header->adv_router = oa->ospf6->router_id;
1001 lsa_header->seqnum =
049207c3 1002 ospf6_new_ls_seqnum (lsa_header->type, lsa_header->id,
1003 lsa_header->adv_router, oa->lsdb);
508e53e2 1004 lsa_header->length = htons ((caddr_t) op - (caddr_t) lsa_header);
1005
1006 /* LSA checksum */
1007 ospf6_lsa_checksum (lsa_header);
1008
1009 /* create LSA */
1010 lsa = ospf6_lsa_create (lsa_header);
508e53e2 1011
1012 /* Originate */
6452df09 1013 ospf6_lsa_originate_area (lsa, oa);
1014
1015 return 0;
508e53e2 1016}
718e3744 1017
6452df09 1018
1019int
1020ospf6_intra_prefix_lsa_originate_transit (struct thread *thread)
508e53e2 1021{
6452df09 1022 struct ospf6_interface *oi;
1023
508e53e2 1024 char buffer[OSPF6_MAX_LSASIZE];
1025 struct ospf6_lsa_header *lsa_header;
1026 struct ospf6_lsa *old, *lsa;
1027
1028 struct ospf6_intra_prefix_lsa *intra_prefix_lsa;
1029 struct ospf6_neighbor *on;
1030 struct ospf6_route *route;
1031 struct ospf6_prefix *op;
52dc7ee6 1032 struct listnode *i;
508e53e2 1033 int full_count = 0;
1034 unsigned short prefix_num = 0;
1035 struct ospf6_route_table *route_advertise;
1036 struct ospf6_link_lsa *link_lsa;
1037 char *start, *end, *current;
1038 u_int16_t type;
4690c7d7 1039 char buf[PREFIX2STR_BUFFER];
718e3744 1040
6452df09 1041 oi = (struct ospf6_interface *) THREAD_ARG (thread);
1042 oi->thread_intra_prefix_lsa = NULL;
1043
1044 assert (oi->area);
718e3744 1045
508e53e2 1046 /* find previous LSA */
1047 old = ospf6_lsdb_lookup (htons (OSPF6_LSTYPE_INTRA_PREFIX),
1048 htonl (oi->interface->ifindex),
1049 oi->area->ospf6->router_id, oi->area->lsdb);
718e3744 1050
508e53e2 1051 if (CHECK_FLAG (oi->flag, OSPF6_INTERFACE_DISABLE))
718e3744 1052 {
718e3744 1053 if (old)
6452df09 1054 ospf6_lsa_purge (old);
1055 return 0;
718e3744 1056 }
1057
1e05838a 1058 if (IS_OSPF6_DEBUG_ORIGINATE (INTRA_PREFIX))
c6487d61 1059 zlog_debug ("Originate Intra-Area-Prefix-LSA for interface %s's prefix",
508e53e2 1060 oi->interface->name);
1061
718e3744 1062 /* prepare buffer */
1063 memset (buffer, 0, sizeof (buffer));
508e53e2 1064 lsa_header = (struct ospf6_lsa_header *) buffer;
1065 intra_prefix_lsa = (struct ospf6_intra_prefix_lsa *)
1066 ((caddr_t) lsa_header + sizeof (struct ospf6_lsa_header));
718e3744 1067
508e53e2 1068 /* Fill Intra-Area-Prefix-LSA */
1069 intra_prefix_lsa->ref_type = htons (OSPF6_LSTYPE_NETWORK);
1070 intra_prefix_lsa->ref_id = htonl (oi->interface->ifindex);
1071 intra_prefix_lsa->ref_adv_router = oi->area->ospf6->router_id;
718e3744 1072
508e53e2 1073 if (oi->state != OSPF6_INTERFACE_DR)
718e3744 1074 {
1e05838a 1075 if (IS_OSPF6_DEBUG_ORIGINATE (INTRA_PREFIX))
c6487d61 1076 zlog_debug (" Interface is not DR");
508e53e2 1077 if (old)
6452df09 1078 ospf6_lsa_purge (old);
1079 return 0;
508e53e2 1080 }
1081
1082 full_count = 0;
1eb8ef25 1083 for (ALL_LIST_ELEMENTS_RO (oi->neighbor_list, i, on))
1084 if (on->state == OSPF6_NEIGHBOR_FULL)
1085 full_count++;
c3c0ac83 1086
508e53e2 1087 if (full_count == 0)
1088 {
1e05838a 1089 if (IS_OSPF6_DEBUG_ORIGINATE (INTRA_PREFIX))
c6487d61 1090 zlog_debug (" Interface is stub");
508e53e2 1091 if (old)
6452df09 1092 ospf6_lsa_purge (old);
1093 return 0;
508e53e2 1094 }
1095
1096 /* connected prefix to advertise */
cf1ce250 1097 route_advertise = ospf6_route_table_create (0, 0);
508e53e2 1098
1099 type = ntohs (OSPF6_LSTYPE_LINK);
1100 for (lsa = ospf6_lsdb_type_head (type, oi->lsdb); lsa;
1101 lsa = ospf6_lsdb_type_next (type, lsa))
1102 {
1103 if (OSPF6_LSA_IS_MAXAGE (lsa))
1104 continue;
718e3744 1105
1e05838a 1106 if (IS_OSPF6_DEBUG_ORIGINATE (INTRA_PREFIX))
c6487d61 1107 zlog_debug (" include prefix from %s", lsa->name);
718e3744 1108
508e53e2 1109 if (lsa->header->adv_router != oi->area->ospf6->router_id)
1110 {
1111 on = ospf6_neighbor_lookup (lsa->header->adv_router, oi);
1112 if (on == NULL || on->state != OSPF6_NEIGHBOR_FULL)
1113 {
1e05838a 1114 if (IS_OSPF6_DEBUG_ORIGINATE (INTRA_PREFIX))
c6487d61 1115 zlog_debug (" Neighbor not found or not Full, ignore");
508e53e2 1116 continue;
1117 }
1118 }
1119
1120 link_lsa = (struct ospf6_link_lsa *)
1121 ((caddr_t) lsa->header + sizeof (struct ospf6_lsa_header));
1122
1123 prefix_num = (unsigned short) ntohl (link_lsa->prefix_num);
1124 start = (char *) link_lsa + sizeof (struct ospf6_link_lsa);
1125 end = (char *) lsa->header + ntohs (lsa->header->length);
1126 for (current = start; current < end && prefix_num;
1127 current += OSPF6_PREFIX_SIZE (op))
1128 {
1129 op = (struct ospf6_prefix *) current;
1130 if (op->prefix_length == 0 ||
1131 current + OSPF6_PREFIX_SIZE (op) > end)
1132 break;
1133
1134 route = ospf6_route_create ();
1135
1136 route->type = OSPF6_DEST_TYPE_NETWORK;
1137 route->prefix.family = AF_INET6;
1138 route->prefix.prefixlen = op->prefix_length;
1139 memset (&route->prefix.u.prefix6, 0, sizeof (struct in6_addr));
1140 memcpy (&route->prefix.u.prefix6, OSPF6_PREFIX_BODY (op),
1141 OSPF6_PREFIX_SPACE (op->prefix_length));
1142
1143 route->path.origin.type = lsa->header->type;
1144 route->path.origin.id = lsa->header->id;
1145 route->path.origin.adv_router = lsa->header->adv_router;
1146 route->path.options[0] = link_lsa->options[0];
1147 route->path.options[1] = link_lsa->options[1];
1148 route->path.options[2] = link_lsa->options[2];
1149 route->path.prefix_options = op->prefix_options;
1150 route->path.area_id = oi->area->area_id;
1151 route->path.type = OSPF6_PATH_TYPE_INTRA;
1152
1e05838a 1153 if (IS_OSPF6_DEBUG_ORIGINATE (INTRA_PREFIX))
508e53e2 1154 {
1155 prefix2str (&route->prefix, buf, sizeof (buf));
c6487d61 1156 zlog_debug (" include %s", buf);
508e53e2 1157 }
1158
1159 ospf6_route_add (route, route_advertise);
1160 prefix_num--;
1161 }
1e05838a 1162 if (current != end && IS_OSPF6_DEBUG_ORIGINATE (INTRA_PREFIX))
c6487d61 1163 zlog_debug ("Trailing garbage in %s", lsa->name);
718e3744 1164 }
718e3744 1165
508e53e2 1166 op = (struct ospf6_prefix *)
1167 ((caddr_t) intra_prefix_lsa + sizeof (struct ospf6_intra_prefix_lsa));
1168
1169 prefix_num = 0;
1170 for (route = ospf6_route_head (route_advertise); route;
1171 route = ospf6_route_best_next (route))
718e3744 1172 {
508e53e2 1173 op->prefix_length = route->prefix.prefixlen;
1174 op->prefix_options = route->path.prefix_options;
1175 op->prefix_metric = htons (0);
1176 memcpy (OSPF6_PREFIX_BODY (op), &route->prefix.u.prefix6,
1177 OSPF6_PREFIX_SPACE (op->prefix_length));
1178 op = OSPF6_PREFIX_NEXT (op);
1179 prefix_num++;
718e3744 1180 }
718e3744 1181
508e53e2 1182 ospf6_route_table_delete (route_advertise);
718e3744 1183
508e53e2 1184 if (prefix_num == 0)
718e3744 1185 {
1e05838a 1186 if (IS_OSPF6_DEBUG_ORIGINATE (INTRA_PREFIX))
c6487d61 1187 zlog_debug ("Quit to Advertise Intra-Prefix: no route to advertise");
6452df09 1188 return 0;
718e3744 1189 }
508e53e2 1190
1191 intra_prefix_lsa->prefix_num = htons (prefix_num);
1192
1193 /* Fill LSA Header */
1194 lsa_header->age = 0;
1195 lsa_header->type = htons (OSPF6_LSTYPE_INTRA_PREFIX);
1196 lsa_header->id = htonl (oi->interface->ifindex);
1197 lsa_header->adv_router = oi->area->ospf6->router_id;
1198 lsa_header->seqnum =
049207c3 1199 ospf6_new_ls_seqnum (lsa_header->type, lsa_header->id,
1200 lsa_header->adv_router, oi->area->lsdb);
508e53e2 1201 lsa_header->length = htons ((caddr_t) op - (caddr_t) lsa_header);
1202
1203 /* LSA checksum */
1204 ospf6_lsa_checksum (lsa_header);
1205
1206 /* create LSA */
1207 lsa = ospf6_lsa_create (lsa_header);
508e53e2 1208
1209 /* Originate */
6452df09 1210 ospf6_lsa_originate_area (lsa, oi->area);
508e53e2 1211
1212 return 0;
1213}
1214
1215void
1216ospf6_intra_prefix_lsa_add (struct ospf6_lsa *lsa)
1217{
1218 struct ospf6_area *oa;
1219 struct ospf6_intra_prefix_lsa *intra_prefix_lsa;
1220 struct prefix ls_prefix;
1221 struct ospf6_route *route, *ls_entry;
c3c0ac83 1222 int prefix_num;
508e53e2 1223 struct ospf6_prefix *op;
1224 char *start, *current, *end;
4690c7d7 1225 char buf[PREFIX2STR_BUFFER];
b81e97a8
DD
1226 struct interface *ifp;
1227 int direct_connect = 0;
508e53e2 1228
ccb59b11 1229 if (OSPF6_LSA_IS_MAXAGE (lsa))
1230 return;
1231
1e05838a 1232 if (IS_OSPF6_DEBUG_EXAMIN (INTRA_PREFIX))
c6487d61 1233 zlog_debug ("%s found", lsa->name);
508e53e2 1234
6452df09 1235 oa = OSPF6_AREA (lsa->lsdb->data);
1236
508e53e2 1237 intra_prefix_lsa = (struct ospf6_intra_prefix_lsa *)
1238 OSPF6_LSA_HEADER_END (lsa->header);
1239 if (intra_prefix_lsa->ref_type == htons (OSPF6_LSTYPE_ROUTER))
1240 ospf6_linkstate_prefix (intra_prefix_lsa->ref_adv_router,
1241 htonl (0), &ls_prefix);
1242 else if (intra_prefix_lsa->ref_type == htons (OSPF6_LSTYPE_NETWORK))
1243 ospf6_linkstate_prefix (intra_prefix_lsa->ref_adv_router,
1244 intra_prefix_lsa->ref_id, &ls_prefix);
718e3744 1245 else
1246 {
1e05838a 1247 if (IS_OSPF6_DEBUG_EXAMIN (INTRA_PREFIX))
c6487d61 1248 zlog_debug ("Unknown reference LS-type: %#hx",
1249 ntohs (intra_prefix_lsa->ref_type));
508e53e2 1250 return;
718e3744 1251 }
1252
508e53e2 1253 ls_entry = ospf6_route_lookup (&ls_prefix, oa->spf_table);
1254 if (ls_entry == NULL)
1255 {
1e05838a 1256 if (IS_OSPF6_DEBUG_EXAMIN (INTRA_PREFIX))
508e53e2 1257 {
1258 ospf6_linkstate_prefix2str (&ls_prefix, buf, sizeof (buf));
c6487d61 1259 zlog_debug ("LS entry does not exist: %s", buf);
508e53e2 1260 }
1261 return;
1262 }
1263
b81e97a8
DD
1264 if (intra_prefix_lsa->ref_adv_router == oa->ospf6->router_id)
1265 {
1266 /* the intra-prefix are directly connected */
1267 direct_connect = 1;
1268 }
1269
508e53e2 1270 prefix_num = ntohs (intra_prefix_lsa->prefix_num);
1271 start = (caddr_t) intra_prefix_lsa +
1272 sizeof (struct ospf6_intra_prefix_lsa);
1273 end = OSPF6_LSA_END (lsa->header);
1274 for (current = start; current < end; current += OSPF6_PREFIX_SIZE (op))
1275 {
1276 op = (struct ospf6_prefix *) current;
1277 if (prefix_num == 0)
1278 break;
1279 if (end < current + OSPF6_PREFIX_SIZE (op))
1280 break;
1281
e68a6767 1282 /* Appendix A.4.1.1 */
a1c55bf1 1283 if (CHECK_FLAG(op->prefix_options, OSPF6_PREFIX_OPTION_NU))
e68a6767
DD
1284 {
1285 if (IS_OSPF6_DEBUG_EXAMIN (INTRA_PREFIX))
1286 {
1287 ospf6_linkstate_prefix2str ((struct prefix *)OSPF6_PREFIX_BODY(op),
1288 buf, sizeof (buf));
a1c55bf1 1289 zlog_debug ("%s: Skipping Prefix %s has NU option set",
e68a6767
DD
1290 __func__, buf);
1291 }
1292 continue;
1293 }
1294
508e53e2 1295 route = ospf6_route_create ();
ccb59b11 1296
1297 memset (&route->prefix, 0, sizeof (struct prefix));
508e53e2 1298 route->prefix.family = AF_INET6;
ccb59b11 1299 route->prefix.prefixlen = op->prefix_length;
1300 ospf6_prefix_in6_addr (&route->prefix.u.prefix6, op);
1301
508e53e2 1302 route->type = OSPF6_DEST_TYPE_NETWORK;
1303 route->path.origin.type = lsa->header->type;
1304 route->path.origin.id = lsa->header->id;
1305 route->path.origin.adv_router = lsa->header->adv_router;
1306 route->path.prefix_options = op->prefix_options;
1307 route->path.area_id = oa->area_id;
1308 route->path.type = OSPF6_PATH_TYPE_INTRA;
1309 route->path.metric_type = 1;
1310 route->path.cost = ls_entry->path.cost +
1311 ntohs (op->prefix_metric);
1312
b81e97a8
DD
1313 if (direct_connect)
1314 {
a90607a4 1315 ifp = if_lookup_prefix(&route->prefix, VRF_DEFAULT);
b81e97a8 1316 if (ifp)
c3c0ac83 1317 ospf6_route_add_nexthop (route, ifp->ifindex, NULL);
b81e97a8
DD
1318 }
1319 else
1320 {
c3c0ac83 1321 ospf6_route_copy_nexthops (route, ls_entry);
b81e97a8 1322 }
508e53e2 1323
1e05838a 1324 if (IS_OSPF6_DEBUG_EXAMIN (INTRA_PREFIX))
508e53e2 1325 {
1326 prefix2str (&route->prefix, buf, sizeof (buf));
c6487d61 1327 zlog_debug (" add %s", buf);
508e53e2 1328 }
1329
1330 ospf6_route_add (route, oa->route_table);
1331 prefix_num--;
1332 }
1333
1e05838a 1334 if (current != end && IS_OSPF6_DEBUG_EXAMIN (INTRA_PREFIX))
c6487d61 1335 zlog_debug ("Trailing garbage ignored");
718e3744 1336}
1337
1338void
508e53e2 1339ospf6_intra_prefix_lsa_remove (struct ospf6_lsa *lsa)
718e3744 1340{
508e53e2 1341 struct ospf6_area *oa;
1342 struct ospf6_intra_prefix_lsa *intra_prefix_lsa;
1343 struct prefix prefix;
0f23bb67 1344 struct ospf6_route *route, *nroute;
508e53e2 1345 int prefix_num;
1346 struct ospf6_prefix *op;
1347 char *start, *current, *end;
4690c7d7 1348 char buf[PREFIX2STR_BUFFER];
508e53e2 1349
1e05838a 1350 if (IS_OSPF6_DEBUG_EXAMIN (INTRA_PREFIX))
c6487d61 1351 zlog_debug ("%s disappearing", lsa->name);
508e53e2 1352
6452df09 1353 oa = OSPF6_AREA (lsa->lsdb->data);
1354
508e53e2 1355 intra_prefix_lsa = (struct ospf6_intra_prefix_lsa *)
1356 OSPF6_LSA_HEADER_END (lsa->header);
1357
1358 prefix_num = ntohs (intra_prefix_lsa->prefix_num);
1359 start = (caddr_t) intra_prefix_lsa +
1360 sizeof (struct ospf6_intra_prefix_lsa);
1361 end = OSPF6_LSA_END (lsa->header);
1362 for (current = start; current < end; current += OSPF6_PREFIX_SIZE (op))
1363 {
1364 op = (struct ospf6_prefix *) current;
1365 if (prefix_num == 0)
1366 break;
1367 if (end < current + OSPF6_PREFIX_SIZE (op))
1368 break;
1369 prefix_num--;
1370
ccb59b11 1371 memset (&prefix, 0, sizeof (struct prefix));
508e53e2 1372 prefix.family = AF_INET6;
1373 prefix.prefixlen = op->prefix_length;
1374 ospf6_prefix_in6_addr (&prefix.u.prefix6, op);
1375
1376 route = ospf6_route_lookup (&prefix, oa->route_table);
1377 if (route == NULL)
1378 continue;
1379
1380 for (ospf6_route_lock (route);
1381 route && ospf6_route_is_prefix (&prefix, route);
0f23bb67 1382 route = nroute)
508e53e2 1383 {
0f23bb67 1384 nroute = ospf6_route_next (route);
508e53e2 1385 if (route->type != OSPF6_DEST_TYPE_NETWORK)
1386 continue;
1387 if (route->path.area_id != oa->area_id)
1388 continue;
1389 if (route->path.type != OSPF6_PATH_TYPE_INTRA)
1390 continue;
1391 if (route->path.origin.type != lsa->header->type ||
1392 route->path.origin.id != lsa->header->id ||
1393 route->path.origin.adv_router != lsa->header->adv_router)
1394 continue;
1395
1e05838a 1396 if (IS_OSPF6_DEBUG_EXAMIN (INTRA_PREFIX))
508e53e2 1397 {
1398 prefix2str (&route->prefix, buf, sizeof (buf));
c6487d61 1399 zlog_debug ("remove %s", buf);
508e53e2 1400 }
1401 ospf6_route_remove (route, oa->route_table);
1402 }
e7a6d80d
TG
1403 if (route)
1404 ospf6_route_unlock (route);
508e53e2 1405 }
1406
1e05838a 1407 if (current != end && IS_OSPF6_DEBUG_EXAMIN (INTRA_PREFIX))
c6487d61 1408 zlog_debug ("Trailing garbage ignored");
718e3744 1409}
1410
1411void
508e53e2 1412ospf6_intra_route_calculation (struct ospf6_area *oa)
718e3744 1413{
0f23bb67 1414 struct ospf6_route *route, *nroute;
508e53e2 1415 u_int16_t type;
1416 struct ospf6_lsa *lsa;
1417 void (*hook_add) (struct ospf6_route *) = NULL;
1418 void (*hook_remove) (struct ospf6_route *) = NULL;
1419
1e05838a 1420 if (IS_OSPF6_DEBUG_EXAMIN (INTRA_PREFIX))
c6487d61 1421 zlog_debug ("Re-examin intra-routes for area %s", oa->name);
508e53e2 1422
1423 hook_add = oa->route_table->hook_add;
1424 hook_remove = oa->route_table->hook_remove;
1425 oa->route_table->hook_add = NULL;
1426 oa->route_table->hook_remove = NULL;
1427
1428 for (route = ospf6_route_head (oa->route_table); route;
1429 route = ospf6_route_next (route))
1430 route->flag = OSPF6_ROUTE_REMOVE;
1431
1432 type = htons (OSPF6_LSTYPE_INTRA_PREFIX);
1433 for (lsa = ospf6_lsdb_type_head (type, oa->lsdb); lsa;
1434 lsa = ospf6_lsdb_type_next (type, lsa))
1435 ospf6_intra_prefix_lsa_add (lsa);
1436
1437 oa->route_table->hook_add = hook_add;
1438 oa->route_table->hook_remove = hook_remove;
1439
1440 for (route = ospf6_route_head (oa->route_table); route;
0f23bb67 1441 route = nroute)
508e53e2 1442 {
0f23bb67 1443 nroute = ospf6_route_next (route);
508e53e2 1444 if (CHECK_FLAG (route->flag, OSPF6_ROUTE_REMOVE) &&
1445 CHECK_FLAG (route->flag, OSPF6_ROUTE_ADD))
1446 {
1447 UNSET_FLAG (route->flag, OSPF6_ROUTE_REMOVE);
1448 UNSET_FLAG (route->flag, OSPF6_ROUTE_ADD);
1449 }
1450
1451 if (CHECK_FLAG (route->flag, OSPF6_ROUTE_REMOVE))
1452 ospf6_route_remove (route, oa->route_table);
1453 else if (CHECK_FLAG (route->flag, OSPF6_ROUTE_ADD) ||
1454 CHECK_FLAG (route->flag, OSPF6_ROUTE_CHANGE))
1455 {
1456 if (hook_add)
1457 (*hook_add) (route);
8f599166 1458 route->flag = 0;
508e53e2 1459 }
ca1f4309
DS
1460 else
1461 {
1462 /* Redo the summaries as things might have changed */
1463 ospf6_abr_originate_summary (route);
8f599166 1464 route->flag = 0;
ca1f4309 1465 }
508e53e2 1466 }
1467
1e05838a 1468 if (IS_OSPF6_DEBUG_EXAMIN (INTRA_PREFIX))
c6487d61 1469 zlog_debug ("Re-examin intra-routes for area %s: Done", oa->name);
718e3744 1470}
1471
6ac29a51 1472static void
cf1ce250
PJ
1473ospf6_brouter_debug_print (struct ospf6_route *brouter)
1474{
1475 u_int32_t brouter_id;
1476 char brouter_name[16];
1477 char area_name[16];
1478 char destination[64];
1479 char installed[16], changed[16];
1480 struct timeval now, res;
1481 char id[16], adv_router[16];
1482 char capa[16], options[16];
1483
1484 brouter_id = ADV_ROUTER_IN_PREFIX (&brouter->prefix);
1485 inet_ntop (AF_INET, &brouter_id, brouter_name, sizeof (brouter_name));
1486 inet_ntop (AF_INET, &brouter->path.area_id, area_name, sizeof (area_name));
1487 ospf6_linkstate_prefix2str (&brouter->prefix, destination,
1488 sizeof (destination));
1489
cf672a86 1490 monotime(&now);
cf1ce250
PJ
1491 timersub (&now, &brouter->installed, &res);
1492 timerstring (&res, installed, sizeof (installed));
1493
cf672a86 1494 monotime(&now);
cf1ce250
PJ
1495 timersub (&now, &brouter->changed, &res);
1496 timerstring (&res, changed, sizeof (changed));
1497
1498 inet_ntop (AF_INET, &brouter->path.origin.id, id, sizeof (id));
1499 inet_ntop (AF_INET, &brouter->path.origin.adv_router, adv_router,
1500 sizeof (adv_router));
1501
1502 ospf6_options_printbuf (brouter->path.options, options, sizeof (options));
1503 ospf6_capability_printbuf (brouter->path.router_bits, capa, sizeof (capa));
1504
1505 zlog_info ("Brouter: %s via area %s", brouter_name, area_name);
1506 zlog_info (" memory: prev: %p this: %p next: %p parent rnode: %p",
6c4f4e6e
DL
1507 (void *)brouter->prev, (void *)brouter, (void *)brouter->next,
1508 (void *)brouter->rnode);
cf1ce250
PJ
1509 zlog_info (" type: %d prefix: %s installed: %s changed: %s",
1510 brouter->type, destination, installed, changed);
1511 zlog_info (" lock: %d flags: %s%s%s%s", brouter->lock,
1512 (CHECK_FLAG (brouter->flag, OSPF6_ROUTE_BEST) ? "B" : "-"),
1513 (CHECK_FLAG (brouter->flag, OSPF6_ROUTE_ADD) ? "A" : "-"),
1514 (CHECK_FLAG (brouter->flag, OSPF6_ROUTE_REMOVE) ? "R" : "-"),
1515 (CHECK_FLAG (brouter->flag, OSPF6_ROUTE_CHANGE) ? "C" : "-"));
1516 zlog_info (" path type: %s ls-origin %s id: %s adv-router %s",
1517 OSPF6_PATH_TYPE_NAME (brouter->path.type),
1518 ospf6_lstype_name (brouter->path.origin.type),
1519 id, adv_router);
1520 zlog_info (" options: %s router-bits: %s metric-type: %d metric: %d/%d",
1521 options, capa, brouter->path.metric_type,
c3c0ac83 1522 brouter->path.cost, brouter->path.u.cost_e2);
cf1ce250
PJ
1523}
1524
718e3744 1525void
6452df09 1526ospf6_intra_brouter_calculation (struct ospf6_area *oa)
718e3744 1527{
0f23bb67 1528 struct ospf6_route *brouter, *nbrouter, *copy;
508e53e2 1529 void (*hook_add) (struct ospf6_route *) = NULL;
1530 void (*hook_remove) (struct ospf6_route *) = NULL;
cb4b8845
PJ
1531 u_int32_t brouter_id;
1532 char brouter_name[16];
1533
1534 if (IS_OSPF6_DEBUG_BROUTER_SPECIFIC_AREA_ID (oa->area_id))
1535 zlog_info ("border-router calculation for area %s", oa->name);
1536
6452df09 1537 hook_add = oa->ospf6->brouter_table->hook_add;
1538 hook_remove = oa->ospf6->brouter_table->hook_remove;
1539 oa->ospf6->brouter_table->hook_add = NULL;
1540 oa->ospf6->brouter_table->hook_remove = NULL;
508e53e2 1541
6452df09 1542 /* withdraw the previous router entries for the area */
cb4b8845
PJ
1543 for (brouter = ospf6_route_head (oa->ospf6->brouter_table); brouter;
1544 brouter = ospf6_route_next (brouter))
508e53e2 1545 {
cf1ce250
PJ
1546 brouter_id = ADV_ROUTER_IN_PREFIX (&brouter->prefix);
1547 inet_ntop (AF_INET, &brouter_id, brouter_name, sizeof (brouter_name));
cb4b8845 1548 if (brouter->path.area_id != oa->area_id)
508e53e2 1549 continue;
ca1f4309 1550 SET_FLAG (brouter->flag, OSPF6_ROUTE_REMOVE);
cf1ce250
PJ
1551
1552 if (IS_OSPF6_DEBUG_BROUTER_SPECIFIC_ROUTER_ID (brouter_id) ||
1553 IS_OSPF6_DEBUG_ROUTE (MEMORY))
1554 {
1555 zlog_info ("%p: mark as removing: area %s brouter %s",
6c4f4e6e 1556 (void *)brouter, oa->name, brouter_name);
cf1ce250
PJ
1557 ospf6_brouter_debug_print (brouter);
1558 }
508e53e2 1559 }
1560
cb4b8845
PJ
1561 for (brouter = ospf6_route_head (oa->spf_table); brouter;
1562 brouter = ospf6_route_next (brouter))
508e53e2 1563 {
cf1ce250
PJ
1564 brouter_id = ADV_ROUTER_IN_PREFIX (&brouter->prefix);
1565 inet_ntop (AF_INET, &brouter_id, brouter_name, sizeof (brouter_name));
1566
cb4b8845 1567 if (brouter->type != OSPF6_DEST_TYPE_LINKSTATE)
508e53e2 1568 continue;
cb4b8845 1569 if (ospf6_linkstate_prefix_id (&brouter->prefix) != htonl (0))
508e53e2 1570 continue;
cb4b8845
PJ
1571 if (! CHECK_FLAG (brouter->path.router_bits, OSPF6_ROUTER_BIT_E) &&
1572 ! CHECK_FLAG (brouter->path.router_bits, OSPF6_ROUTER_BIT_B))
508e53e2 1573 continue;
1574
01879114
DD
1575 if (! OSPF6_OPT_ISSET (brouter->path.options, OSPF6_OPT_V6) ||
1576 ! OSPF6_OPT_ISSET (brouter->path.options, OSPF6_OPT_R))
1577 continue;
1578
cb4b8845 1579 copy = ospf6_route_copy (brouter);
508e53e2 1580 copy->type = OSPF6_DEST_TYPE_ROUTER;
ccb59b11 1581 copy->path.area_id = oa->area_id;
6452df09 1582 ospf6_route_add (copy, oa->ospf6->brouter_table);
cf1ce250
PJ
1583
1584 if (IS_OSPF6_DEBUG_BROUTER_SPECIFIC_ROUTER_ID (brouter_id) ||
1585 IS_OSPF6_DEBUG_ROUTE (MEMORY))
1586 {
1587 zlog_info ("%p: transfer: area %s brouter %s",
6c4f4e6e 1588 (void *)brouter, oa->name, brouter_name);
cf1ce250
PJ
1589 ospf6_brouter_debug_print (brouter);
1590 }
508e53e2 1591 }
1592
6452df09 1593 oa->ospf6->brouter_table->hook_add = hook_add;
1594 oa->ospf6->brouter_table->hook_remove = hook_remove;
508e53e2 1595
cb4b8845 1596 for (brouter = ospf6_route_head (oa->ospf6->brouter_table); brouter;
0f23bb67 1597 brouter = nbrouter)
508e53e2 1598 {
0f23bb67 1599 nbrouter = ospf6_route_next (brouter);
cb4b8845
PJ
1600 brouter_id = ADV_ROUTER_IN_PREFIX (&brouter->prefix);
1601 inet_ntop (AF_INET, &brouter_id, brouter_name, sizeof (brouter_name));
1602
1603 if (brouter->path.area_id != oa->area_id)
508e53e2 1604 continue;
1605
cb4b8845 1606 if (CHECK_FLAG (brouter->flag, OSPF6_ROUTE_WAS_REMOVED))
9428f2dc 1607 continue;
1608
cb4b8845
PJ
1609 if (CHECK_FLAG (brouter->flag, OSPF6_ROUTE_REMOVE) &&
1610 CHECK_FLAG (brouter->flag, OSPF6_ROUTE_ADD))
508e53e2 1611 {
cb4b8845
PJ
1612 UNSET_FLAG (brouter->flag, OSPF6_ROUTE_REMOVE);
1613 UNSET_FLAG (brouter->flag, OSPF6_ROUTE_ADD);
508e53e2 1614 }
1615
cb4b8845 1616 if (CHECK_FLAG (brouter->flag, OSPF6_ROUTE_REMOVE))
508e53e2 1617 {
cb4b8845
PJ
1618 if (IS_OSPF6_DEBUG_BROUTER ||
1619 IS_OSPF6_DEBUG_BROUTER_SPECIFIC_ROUTER_ID (brouter_id) ||
1620 IS_OSPF6_DEBUG_BROUTER_SPECIFIC_AREA_ID (oa->area_id))
1621 zlog_info ("brouter %s disappears via area %s",
1622 brouter_name, oa->name);
1623 ospf6_route_remove (brouter, oa->ospf6->brouter_table);
7de6a87b 1624 brouter = NULL;
cb4b8845
PJ
1625 }
1626 else if (CHECK_FLAG (brouter->flag, OSPF6_ROUTE_ADD) ||
1627 CHECK_FLAG (brouter->flag, OSPF6_ROUTE_CHANGE))
1628 {
1629 if (IS_OSPF6_DEBUG_BROUTER ||
1630 IS_OSPF6_DEBUG_BROUTER_SPECIFIC_ROUTER_ID (brouter_id) ||
1631 IS_OSPF6_DEBUG_BROUTER_SPECIFIC_AREA_ID (oa->area_id))
1632 zlog_info ("brouter %s appears via area %s",
1633 brouter_name, oa->name);
cf1ce250 1634
cb4b8845 1635 /* newly added */
508e53e2 1636 if (hook_add)
cb4b8845
PJ
1637 (*hook_add) (brouter);
1638 }
1639 else
1640 {
1641 if (IS_OSPF6_DEBUG_BROUTER_SPECIFIC_ROUTER_ID (brouter_id) ||
1642 IS_OSPF6_DEBUG_BROUTER_SPECIFIC_AREA_ID (oa->area_id))
1643 zlog_info ("brouter %s still exists via area %s",
1644 brouter_name, oa->name);
ca1f4309
DS
1645 /* But re-originate summaries */
1646 ospf6_abr_originate_summary (brouter);
508e53e2 1647 }
7de6a87b
QY
1648
1649 if (brouter)
1650 {
1651 UNSET_FLAG (brouter->flag, OSPF6_ROUTE_ADD);
1652 UNSET_FLAG (brouter->flag, OSPF6_ROUTE_CHANGE);
1653 }
508e53e2 1654 }
1655
cb4b8845
PJ
1656 if (IS_OSPF6_DEBUG_BROUTER_SPECIFIC_AREA_ID (oa->area_id))
1657 zlog_info ("border-router calculation for area %s: done", oa->name);
718e3744 1658}
1659
6452df09 1660struct ospf6_lsa_handler router_handler =
1661{
1662 OSPF6_LSTYPE_ROUTER,
1663 "Router",
e68a6767
DD
1664 "Rtr",
1665 ospf6_router_lsa_show,
1666 ospf6_router_lsa_get_nbr_id
6452df09 1667};
1668
1669struct ospf6_lsa_handler network_handler =
1670{
1671 OSPF6_LSTYPE_NETWORK,
1672 "Network",
e68a6767
DD
1673 "Net",
1674 ospf6_network_lsa_show,
1675 ospf6_network_lsa_get_ar_id
6452df09 1676};
1677
1678struct ospf6_lsa_handler link_handler =
1679{
1680 OSPF6_LSTYPE_LINK,
1681 "Link",
e68a6767
DD
1682 "Lnk",
1683 ospf6_link_lsa_show,
1684 ospf6_link_lsa_get_prefix_str
6452df09 1685};
1686
1687struct ospf6_lsa_handler intra_prefix_handler =
1688{
1689 OSPF6_LSTYPE_INTRA_PREFIX,
1690 "Intra-Prefix",
e68a6767
DD
1691 "INP",
1692 ospf6_intra_prefix_lsa_show,
1693 ospf6_intra_prefix_lsa_get_prefix_str
6452df09 1694};
1695
718e3744 1696void
cb4b8845 1697ospf6_intra_init (void)
718e3744 1698{
6452df09 1699 ospf6_install_lsa_handler (&router_handler);
1700 ospf6_install_lsa_handler (&network_handler);
1701 ospf6_install_lsa_handler (&link_handler);
1702 ospf6_install_lsa_handler (&intra_prefix_handler);
718e3744 1703}
1704
cb4b8845
PJ
1705DEFUN (debug_ospf6_brouter,
1706 debug_ospf6_brouter_cmd,
1707 "debug ospf6 border-routers",
1708 DEBUG_STR
1709 OSPF6_STR
1710 "Debug border router\n"
1711 )
1712{
1713 OSPF6_DEBUG_BROUTER_ON ();
1714 return CMD_SUCCESS;
1715}
1716
1717DEFUN (no_debug_ospf6_brouter,
1718 no_debug_ospf6_brouter_cmd,
1719 "no debug ospf6 border-routers",
1720 NO_STR
1721 DEBUG_STR
1722 OSPF6_STR
1723 "Debug border router\n"
1724 )
1725{
1726 OSPF6_DEBUG_BROUTER_OFF ();
1727 return CMD_SUCCESS;
1728}
1729
1730DEFUN (debug_ospf6_brouter_router,
1731 debug_ospf6_brouter_router_cmd,
1732 "debug ospf6 border-routers router-id A.B.C.D",
1733 DEBUG_STR
1734 OSPF6_STR
1735 "Debug border router\n"
1736 "Debug specific border router\n"
1737 "Specify border-router's router-id\n"
1738 )
1739{
51c26414 1740 int idx_ipv4 = 4;
cb4b8845 1741 u_int32_t router_id;
51c26414 1742 inet_pton (AF_INET, argv[idx_ipv4]->arg, &router_id);
cb4b8845
PJ
1743 OSPF6_DEBUG_BROUTER_SPECIFIC_ROUTER_ON (router_id);
1744 return CMD_SUCCESS;
1745}
1746
1747DEFUN (no_debug_ospf6_brouter_router,
1748 no_debug_ospf6_brouter_router_cmd,
1749 "no debug ospf6 border-routers router-id",
1750 NO_STR
1751 DEBUG_STR
1752 OSPF6_STR
1753 "Debug border router\n"
1754 "Debug specific border router\n"
1755 )
1756{
1757 OSPF6_DEBUG_BROUTER_SPECIFIC_ROUTER_OFF ();
1758 return CMD_SUCCESS;
1759}
1760
1761DEFUN (debug_ospf6_brouter_area,
1762 debug_ospf6_brouter_area_cmd,
1763 "debug ospf6 border-routers area-id A.B.C.D",
1764 DEBUG_STR
1765 OSPF6_STR
1766 "Debug border router\n"
1767 "Debug border routers in specific Area\n"
1768 "Specify Area-ID\n"
1769 )
1770{
51c26414 1771 int idx_ipv4 = 4;
cb4b8845 1772 u_int32_t area_id;
51c26414 1773 inet_pton (AF_INET, argv[idx_ipv4]->arg, &area_id);
cb4b8845
PJ
1774 OSPF6_DEBUG_BROUTER_SPECIFIC_AREA_ON (area_id);
1775 return CMD_SUCCESS;
1776}
1777
1778DEFUN (no_debug_ospf6_brouter_area,
1779 no_debug_ospf6_brouter_area_cmd,
1780 "no debug ospf6 border-routers area-id",
1781 NO_STR
1782 DEBUG_STR
1783 OSPF6_STR
1784 "Debug border router\n"
1785 "Debug border routers in specific Area\n"
1786 )
1787{
1788 OSPF6_DEBUG_BROUTER_SPECIFIC_AREA_OFF ();
1789 return CMD_SUCCESS;
1790}
1791
1792int
1793config_write_ospf6_debug_brouter (struct vty *vty)
1794{
1795 char buf[16];
1796 if (IS_OSPF6_DEBUG_BROUTER)
1797 vty_out (vty, "debug ospf6 border-routers%s", VNL);
1798 if (IS_OSPF6_DEBUG_BROUTER_SPECIFIC_ROUTER)
1799 {
1800 inet_ntop (AF_INET, &conf_debug_ospf6_brouter_specific_router_id,
1801 buf, sizeof (buf));
1802 vty_out (vty, "debug ospf6 border-routers router-id %s%s", buf, VNL);
1803 }
1804 if (IS_OSPF6_DEBUG_BROUTER_SPECIFIC_AREA)
1805 {
1806 inet_ntop (AF_INET, &conf_debug_ospf6_brouter_specific_area_id,
1807 buf, sizeof (buf));
1808 vty_out (vty, "debug ospf6 border-routers area-id %s%s", buf, VNL);
1809 }
1810 return 0;
1811}
1812
1813void
1814install_element_ospf6_debug_brouter (void)
1815{
1816 install_element (ENABLE_NODE, &debug_ospf6_brouter_cmd);
1817 install_element (ENABLE_NODE, &debug_ospf6_brouter_router_cmd);
1818 install_element (ENABLE_NODE, &debug_ospf6_brouter_area_cmd);
1819 install_element (ENABLE_NODE, &no_debug_ospf6_brouter_cmd);
1820 install_element (ENABLE_NODE, &no_debug_ospf6_brouter_router_cmd);
1821 install_element (ENABLE_NODE, &no_debug_ospf6_brouter_area_cmd);
1822 install_element (CONFIG_NODE, &debug_ospf6_brouter_cmd);
1823 install_element (CONFIG_NODE, &debug_ospf6_brouter_router_cmd);
1824 install_element (CONFIG_NODE, &debug_ospf6_brouter_area_cmd);
1825 install_element (CONFIG_NODE, &no_debug_ospf6_brouter_cmd);
1826 install_element (CONFIG_NODE, &no_debug_ospf6_brouter_router_cmd);
1827 install_element (CONFIG_NODE, &no_debug_ospf6_brouter_area_cmd);
1828}
1829
718e3744 1830