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