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