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