ospf6_intra.c
上传用户:xiaozhuqw
上传日期:2009-11-15
资源大小:1338k
文件大小:43k
源码类别:

网络

开发平台:

Unix_Linux

  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. #include <zebra.h>
  22. #include "log.h"
  23. #include "linklist.h"
  24. #include "thread.h"
  25. #include "memory.h"
  26. #include "if.h"
  27. #include "prefix.h"
  28. #include "table.h"
  29. #include "vty.h"
  30. #include "command.h"
  31. #include "ospf6_proto.h"
  32. #include "ospf6_message.h"
  33. #include "ospf6_route.h"
  34. #include "ospf6_lsa.h"
  35. #include "ospf6_lsdb.h"
  36. #include "ospf6_top.h"
  37. #include "ospf6_area.h"
  38. #include "ospf6_interface.h"
  39. #include "ospf6_neighbor.h"
  40. #include "ospf6_intra.h"
  41. #include "ospf6_asbr.h"
  42. #include "ospf6_abr.h"
  43. #include "ospf6_flood.h"
  44. #include "ospf6d.h"
  45. /******************************/
  46. /* RFC2740 3.4.3.1 Router-LSA */
  47. /******************************/
  48. int
  49. ospf6_router_lsa_show (struct vty *vty, struct ospf6_lsa *lsa)
  50. {
  51.   char *start, *end, *current;
  52.   char buf[32], name[32], bits[16], options[32];
  53.   struct ospf6_router_lsa *router_lsa;
  54.   struct ospf6_router_lsdesc *lsdesc;
  55.   router_lsa = (struct ospf6_router_lsa *)
  56.     ((char *) lsa->header + sizeof (struct ospf6_lsa_header));
  57.   ospf6_capability_printbuf (router_lsa->bits, bits, sizeof (bits));
  58.   ospf6_options_printbuf (router_lsa->options, options, sizeof (options));
  59.   vty_out (vty, "    Bits: %s Options: %s%s", bits, options, VNL);
  60.   start = (char *) router_lsa + sizeof (struct ospf6_router_lsa);
  61.   end = (char *) lsa->header + ntohs (lsa->header->length);
  62.   for (current = start; current + sizeof (struct ospf6_router_lsdesc) <= end;
  63.        current += sizeof (struct ospf6_router_lsdesc))
  64.     {
  65.       lsdesc = (struct ospf6_router_lsdesc *) current;
  66.       if (lsdesc->type == OSPF6_ROUTER_LSDESC_POINTTOPOINT)
  67.         snprintf (name, sizeof (name), "Point-To-Point");
  68.       else if (lsdesc->type == OSPF6_ROUTER_LSDESC_TRANSIT_NETWORK)
  69.         snprintf (name, sizeof (name), "Transit-Network");
  70.       else if (lsdesc->type == OSPF6_ROUTER_LSDESC_STUB_NETWORK)
  71.         snprintf (name, sizeof (name), "Stub-Network");
  72.       else if (lsdesc->type == OSPF6_ROUTER_LSDESC_VIRTUAL_LINK)
  73.         snprintf (name, sizeof (name), "Virtual-Link");
  74.       else
  75.         snprintf (name, sizeof (name), "Unknown (%#x)", lsdesc->type);
  76.       vty_out (vty, "    Type: %s Metric: %d%s",
  77.                name, ntohs (lsdesc->metric), VNL);
  78.       vty_out (vty, "    Interface ID: %s%s",
  79.                inet_ntop (AF_INET, &lsdesc->interface_id,
  80.                           buf, sizeof (buf)), VNL);
  81.       vty_out (vty, "    Neighbor Interface ID: %s%s",
  82.                inet_ntop (AF_INET, &lsdesc->neighbor_interface_id,
  83.                           buf, sizeof (buf)), VNL);
  84.       vty_out (vty, "    Neighbor Router ID: %s%s",
  85.                inet_ntop (AF_INET, &lsdesc->neighbor_router_id,
  86.                           buf, sizeof (buf)), VNL);
  87.     }
  88.   return 0;
  89. }
  90. int
  91. ospf6_router_lsa_originate (struct thread *thread)
  92. {
  93.   struct ospf6_area *oa;
  94.   char buffer [OSPF6_MAX_LSASIZE];
  95.   struct ospf6_lsa_header *lsa_header;
  96.   struct ospf6_lsa *lsa;
  97.   u_int32_t link_state_id = 0;
  98.   listnode i, j;
  99.   struct ospf6_interface *oi;
  100.   struct ospf6_neighbor *on, *drouter = NULL;
  101.   struct ospf6_router_lsa *router_lsa;
  102.   struct ospf6_router_lsdesc *lsdesc;
  103.   u_int16_t type;
  104.   u_int32_t router;
  105.   int count;
  106.   oa = (struct ospf6_area *) THREAD_ARG (thread);
  107.   oa->thread_router_lsa = NULL;
  108.   if (IS_OSPF6_DEBUG_ORIGINATE (ROUTER))
  109.     zlog_info ("Originate Router-LSA for Area %s", oa->name);
  110.   memset (buffer, 0, sizeof (buffer));
  111.   lsa_header = (struct ospf6_lsa_header *) buffer;
  112.   router_lsa = (struct ospf6_router_lsa *)
  113.     ((caddr_t) lsa_header + sizeof (struct ospf6_lsa_header));
  114.   OSPF6_OPT_SET (router_lsa->options, OSPF6_OPT_V6);
  115.   OSPF6_OPT_SET (router_lsa->options, OSPF6_OPT_E);
  116.   OSPF6_OPT_CLEAR (router_lsa->options, OSPF6_OPT_MC);
  117.   OSPF6_OPT_CLEAR (router_lsa->options, OSPF6_OPT_N);
  118.   OSPF6_OPT_SET (router_lsa->options, OSPF6_OPT_R);
  119.   OSPF6_OPT_CLEAR (router_lsa->options, OSPF6_OPT_DC);
  120.   if (ospf6_is_router_abr (ospf6))
  121.     SET_FLAG (router_lsa->bits, OSPF6_ROUTER_BIT_B);
  122.   else
  123.     UNSET_FLAG (router_lsa->bits, OSPF6_ROUTER_BIT_B);
  124.   if (ospf6_asbr_is_asbr (ospf6))
  125.     SET_FLAG (router_lsa->bits, OSPF6_ROUTER_BIT_E);
  126.   else
  127.     UNSET_FLAG (router_lsa->bits, OSPF6_ROUTER_BIT_E);
  128.   UNSET_FLAG (router_lsa->bits, OSPF6_ROUTER_BIT_V);
  129.   UNSET_FLAG (router_lsa->bits, OSPF6_ROUTER_BIT_W);
  130.   /* describe links for each interfaces */
  131.   lsdesc = (struct ospf6_router_lsdesc *)
  132.     ((caddr_t) router_lsa + sizeof (struct ospf6_router_lsa));
  133.   for (i = listhead (oa->if_list); i; nextnode (i))
  134.     {
  135.       oi = (struct ospf6_interface *) getdata (i);
  136.       /* Interfaces in state Down or Loopback are not described */
  137.       if (oi->state == OSPF6_INTERFACE_DOWN ||
  138.           oi->state == OSPF6_INTERFACE_LOOPBACK)
  139.         continue;
  140.       /* Nor are interfaces without any full adjacencies described */
  141.       count = 0;
  142.       for (j = listhead (oi->neighbor_list); j; nextnode (j))
  143.         {
  144.           on = (struct ospf6_neighbor *) getdata (j);
  145.           if (on->state == OSPF6_NEIGHBOR_FULL)
  146.             count++;
  147.         }
  148.       if (count == 0)
  149.         continue;
  150.       /* Multiple Router-LSA instance according to size limit setting */
  151.       if (oa->router_lsa_size_limit != 0 &&
  152.           (caddr_t) lsdesc + sizeof (struct ospf6_router_lsdesc) -
  153.           (caddr_t) buffer > oa->router_lsa_size_limit)
  154.         {
  155.           if ((caddr_t) lsdesc == (caddr_t) router_lsa +
  156.                                   sizeof (struct ospf6_router_lsa))
  157.             {
  158.               if (IS_OSPF6_DEBUG_ORIGINATE (ROUTER))
  159.                 zlog_info ("Size limit setting for Router-LSA too short");
  160.               return 0;
  161.             }
  162.           /* Fill LSA Header */
  163.           lsa_header->age = 0;
  164.           lsa_header->type = htons (OSPF6_LSTYPE_ROUTER);
  165.           lsa_header->id = htonl (link_state_id);
  166.           lsa_header->adv_router = oa->ospf6->router_id;
  167.           lsa_header->seqnum =
  168.             ospf6_new_ls_seqnum (lsa_header->type, lsa_header->id,
  169.                                  lsa_header->adv_router, oa->lsdb);
  170.           lsa_header->length = htons ((caddr_t) lsdesc - (caddr_t) buffer);
  171.           /* LSA checksum */
  172.           ospf6_lsa_checksum (lsa_header);
  173.           /* create LSA */
  174.           lsa = ospf6_lsa_create (lsa_header);
  175.           /* Originate */
  176.           ospf6_lsa_originate_area (lsa, oa);
  177.           /* Reset setting for consecutive origination */
  178.           memset ((caddr_t) router_lsa + sizeof (struct ospf6_router_lsa),
  179.                   0, (caddr_t) lsdesc - (caddr_t) router_lsa);
  180.           lsdesc = (struct ospf6_router_lsdesc *)
  181.             ((caddr_t) router_lsa + sizeof (struct ospf6_router_lsa));
  182.           link_state_id ++;
  183.         }
  184.       /* Point-to-Point interfaces */
  185.       if (if_is_pointopoint (oi->interface))
  186.         {
  187.           for (j = listhead (oi->neighbor_list); j; nextnode (j))
  188.             {
  189.               on = (struct ospf6_neighbor *) getdata (j);
  190.               if (on->state != OSPF6_NEIGHBOR_FULL)
  191.                 continue;
  192.               lsdesc->type = OSPF6_ROUTER_LSDESC_POINTTOPOINT;
  193.               lsdesc->metric = htons (oi->cost);
  194.               lsdesc->interface_id = htonl (oi->interface->ifindex);
  195.               lsdesc->neighbor_interface_id = htonl (on->ifindex);
  196.               lsdesc->neighbor_router_id = on->router_id;
  197.               lsdesc++;
  198.             }
  199.         }
  200.       /* Broadcast and NBMA interfaces */
  201.       if (if_is_broadcast (oi->interface))
  202.         {
  203.           /* If this router is not DR,
  204.              and If this router not fully adjacent with DR,
  205.              this interface is not transit yet: ignore. */
  206.           if (oi->state != OSPF6_INTERFACE_DR)
  207.             {
  208.               drouter = ospf6_neighbor_lookup (oi->drouter, oi);
  209.               if (drouter == NULL || drouter->state != OSPF6_NEIGHBOR_FULL)
  210.                 continue;
  211.             }
  212.           lsdesc->type = OSPF6_ROUTER_LSDESC_TRANSIT_NETWORK;
  213.           lsdesc->metric = htons (oi->cost);
  214.           lsdesc->interface_id = htonl (oi->interface->ifindex);
  215.           if (oi->state != OSPF6_INTERFACE_DR)
  216.             {
  217.               lsdesc->neighbor_interface_id = htonl (drouter->ifindex);
  218.               lsdesc->neighbor_router_id = drouter->router_id;
  219.             }
  220.           else
  221.             {
  222.               lsdesc->neighbor_interface_id = htonl (oi->interface->ifindex);
  223.               lsdesc->neighbor_router_id = oi->area->ospf6->router_id;
  224.             }
  225.           lsdesc++;
  226.         }
  227.       /* Virtual links */
  228.         /* xxx */
  229.       /* Point-to-Multipoint interfaces */
  230.         /* xxx */
  231.     }
  232.   if ((caddr_t) lsdesc != (caddr_t) router_lsa +
  233.                           sizeof (struct ospf6_router_lsa))
  234.     {
  235.       /* Fill LSA Header */
  236.       lsa_header->age = 0;
  237.       lsa_header->type = htons (OSPF6_LSTYPE_ROUTER);
  238.       lsa_header->id = htonl (link_state_id);
  239.       lsa_header->adv_router = oa->ospf6->router_id;
  240.       lsa_header->seqnum =
  241.         ospf6_new_ls_seqnum (lsa_header->type, lsa_header->id,
  242.                              lsa_header->adv_router, oa->lsdb);
  243.       lsa_header->length = htons ((caddr_t) lsdesc - (caddr_t) buffer);
  244.       /* LSA checksum */
  245.       ospf6_lsa_checksum (lsa_header);
  246.       /* create LSA */
  247.       lsa = ospf6_lsa_create (lsa_header);
  248.       /* Originate */
  249.       ospf6_lsa_originate_area (lsa, oa);
  250.       link_state_id ++;
  251.     }
  252.   else
  253.     {
  254.       if (IS_OSPF6_DEBUG_ORIGINATE (ROUTER))
  255.         zlog_info ("Nothing to describe in Router-LSA, suppress");
  256.     }
  257.   /* Do premature-aging of rest, undesired Router-LSAs */
  258.   type = ntohs (OSPF6_LSTYPE_ROUTER);
  259.   router = oa->ospf6->router_id;
  260.   for (lsa = ospf6_lsdb_type_router_head (type, router, oa->lsdb); lsa;
  261.        lsa = ospf6_lsdb_type_router_next (type, router, lsa))
  262.     {
  263.       if (ntohl (lsa->header->id) < link_state_id)
  264.         continue;
  265.       ospf6_lsa_purge (lsa);
  266.     }
  267.   return 0;
  268. }
  269. /*******************************/
  270. /* RFC2740 3.4.3.2 Network-LSA */
  271. /*******************************/
  272. int
  273. ospf6_network_lsa_show (struct vty *vty, struct ospf6_lsa *lsa)
  274. {
  275.   char *start, *end, *current;
  276.   struct ospf6_network_lsa *network_lsa;
  277.   struct ospf6_network_lsdesc *lsdesc;
  278.   char buf[128], options[32];
  279.   network_lsa = (struct ospf6_network_lsa *)
  280.     ((caddr_t) lsa->header + sizeof (struct ospf6_lsa_header));
  281.   ospf6_options_printbuf (network_lsa->options, options, sizeof (options));
  282.   vty_out (vty, "     Options: %s%s", options, VNL);
  283.   start = (char *) network_lsa + sizeof (struct ospf6_network_lsa);
  284.   end = (char *) lsa->header + ntohs (lsa->header->length);
  285.   for (current = start; current + sizeof (struct ospf6_network_lsdesc) <= end;
  286.        current += sizeof (struct ospf6_network_lsdesc))
  287.     {
  288.       lsdesc = (struct ospf6_network_lsdesc *) current;
  289.       inet_ntop (AF_INET, &lsdesc->router_id, buf, sizeof (buf));
  290.       vty_out (vty, "     Attached Router: %s%s", buf, VNL);
  291.     }
  292.   return 0;
  293. }
  294. int
  295. ospf6_network_lsa_originate (struct thread *thread)
  296. {
  297.   struct ospf6_interface *oi;
  298.   char buffer [OSPF6_MAX_LSASIZE];
  299.   struct ospf6_lsa_header *lsa_header;
  300.   int count;
  301.   struct ospf6_lsa *old, *lsa;
  302.   struct ospf6_network_lsa *network_lsa;
  303.   struct ospf6_network_lsdesc *lsdesc;
  304.   struct ospf6_neighbor *on;
  305.   struct ospf6_link_lsa *link_lsa;
  306.   listnode i;
  307.   u_int16_t type;
  308.   oi = (struct ospf6_interface *) THREAD_ARG (thread);
  309.   oi->thread_network_lsa = NULL;
  310.   /* The interface must be enabled until here. A Network-LSA of a
  311.      disabled interface (but was once enabled) should be flushed
  312.      by ospf6_lsa_refresh (), and does not come here. */
  313.   assert (oi->area);
  314.   old = ospf6_lsdb_lookup (htons (OSPF6_LSTYPE_NETWORK),
  315.                            htonl (oi->interface->ifindex),
  316.                            oi->area->ospf6->router_id, oi->area->lsdb);
  317.   /* Do not originate Network-LSA if not DR */
  318.   if (oi->state != OSPF6_INTERFACE_DR)
  319.     {
  320.       if (old)
  321.         ospf6_lsa_purge (old);
  322.       return 0;
  323.     }
  324.   if (IS_OSPF6_DEBUG_ORIGINATE (NETWORK))
  325.     zlog_info ("Originate Network-LSA for Interface %s", oi->interface->name);
  326.   /* If none of neighbor is adjacent to us */
  327.   count = 0;
  328.   for (i = listhead (oi->neighbor_list); i; nextnode (i))
  329.     {
  330.       on = (struct ospf6_neighbor *) getdata (i);
  331.       if (on->state == OSPF6_NEIGHBOR_FULL)
  332.         count++;
  333.     }
  334.   if (count == 0)
  335.     {
  336.       if (IS_OSPF6_DEBUG_ORIGINATE (NETWORK))
  337.         zlog_info ("Interface stub, ignore");
  338.       if (old)
  339.         ospf6_lsa_purge (old);
  340.       return 0;
  341.     }
  342.   /* prepare buffer */
  343.   memset (buffer, 0, sizeof (buffer));
  344.   lsa_header = (struct ospf6_lsa_header *) buffer;
  345.   network_lsa = (struct ospf6_network_lsa *)
  346.     ((caddr_t) lsa_header + sizeof (struct ospf6_lsa_header));
  347.   /* Collect the interface's Link-LSAs to describe
  348.      network's optional capabilities */
  349.   type = htons (OSPF6_LSTYPE_LINK);
  350.   for (lsa = ospf6_lsdb_type_head (type, oi->lsdb); lsa;
  351.        lsa = ospf6_lsdb_type_next (type, lsa))
  352.     {
  353.       link_lsa = (struct ospf6_link_lsa *)
  354.         ((caddr_t) lsa->header + sizeof (struct ospf6_lsa_header));
  355.       network_lsa->options[0] |= link_lsa->options[0];
  356.       network_lsa->options[1] |= link_lsa->options[1];
  357.       network_lsa->options[2] |= link_lsa->options[2];
  358.     }
  359.   lsdesc = (struct ospf6_network_lsdesc *)
  360.     ((caddr_t) network_lsa + sizeof (struct ospf6_network_lsa));
  361.   /* set Link Description to the router itself */
  362.   lsdesc->router_id = oi->area->ospf6->router_id;
  363.   lsdesc++;
  364.   /* Walk through the neighbors */
  365.   for (i = listhead (oi->neighbor_list); i; nextnode (i))
  366.     {
  367.       on = (struct ospf6_neighbor *) getdata (i);
  368.       if (on->state != OSPF6_NEIGHBOR_FULL)
  369.         continue;
  370.       /* set this neighbor's Router-ID to LSA */
  371.       lsdesc->router_id = on->router_id;
  372.       lsdesc++;
  373.     }
  374.   /* Fill LSA Header */
  375.   lsa_header->age = 0;
  376.   lsa_header->type = htons (OSPF6_LSTYPE_NETWORK);
  377.   lsa_header->id = htonl (oi->interface->ifindex);
  378.   lsa_header->adv_router = oi->area->ospf6->router_id;
  379.   lsa_header->seqnum =
  380.     ospf6_new_ls_seqnum (lsa_header->type, lsa_header->id,
  381.                          lsa_header->adv_router, oi->area->lsdb);
  382.   lsa_header->length = htons ((caddr_t) lsdesc - (caddr_t) buffer);
  383.   /* LSA checksum */
  384.   ospf6_lsa_checksum (lsa_header);
  385.   /* create LSA */
  386.   lsa = ospf6_lsa_create (lsa_header);
  387.   /* Originate */
  388.   ospf6_lsa_originate_area (lsa, oi->area);
  389.   return 0;
  390. }
  391. /****************************/
  392. /* RFC2740 3.4.3.6 Link-LSA */
  393. /****************************/
  394. int
  395. ospf6_link_lsa_show (struct vty *vty, struct ospf6_lsa *lsa)
  396. {
  397.   char *start, *end, *current;
  398.   struct ospf6_link_lsa *link_lsa;
  399.   int prefixnum;
  400.   char buf[128], options[32];
  401.   struct ospf6_prefix *prefix;
  402.   char *p, *mc, *la, *nu;
  403.   struct in6_addr in6;
  404.   link_lsa = (struct ospf6_link_lsa *)
  405.     ((caddr_t) lsa->header + sizeof (struct ospf6_lsa_header));
  406.   ospf6_options_printbuf (link_lsa->options, options, sizeof (options));
  407.   inet_ntop (AF_INET6, &link_lsa->linklocal_addr, buf, sizeof (buf));
  408.   prefixnum = ntohl (link_lsa->prefix_num);
  409.   vty_out (vty, "     Priority: %d Options: %s%s",
  410.            link_lsa->priority, options, VNL);
  411.   vty_out (vty, "     LinkLocal Address: %s%s", buf, VNL);
  412.   vty_out (vty, "     Number of Prefix: %d%s", prefixnum, VNL);
  413.   start = (char *) link_lsa + sizeof (struct ospf6_link_lsa);
  414.   end = (char *) lsa->header + ntohs (lsa->header->length); 
  415.   for (current = start; current < end; current += OSPF6_PREFIX_SIZE (prefix))
  416.     {
  417.       prefix = (struct ospf6_prefix *) current;
  418.       if (prefix->prefix_length == 0 ||
  419.           current + OSPF6_PREFIX_SIZE (prefix) > end)
  420.         break;
  421.       p = (CHECK_FLAG (prefix->prefix_options, OSPF6_PREFIX_OPTION_P) ?
  422.            "P" : "--");
  423.       mc = (CHECK_FLAG (prefix->prefix_options, OSPF6_PREFIX_OPTION_MC) ?
  424.            "MC" : "--");
  425.       la = (CHECK_FLAG (prefix->prefix_options, OSPF6_PREFIX_OPTION_LA) ?
  426.            "LA" : "--");
  427.       nu = (CHECK_FLAG (prefix->prefix_options, OSPF6_PREFIX_OPTION_NU) ?
  428.            "NU" : "--");
  429.       vty_out (vty, "     Prefix Options: %s|%s|%s|%s%s",
  430.                p, mc, la, nu, VNL);
  431.       memset (&in6, 0, sizeof (in6));
  432.       memcpy (&in6, OSPF6_PREFIX_BODY (prefix),
  433.               OSPF6_PREFIX_SPACE (prefix->prefix_length));
  434.       inet_ntop (AF_INET6, &in6, buf, sizeof (buf));
  435.       vty_out (vty, "     Prefix: %s/%d%s",
  436.                buf, prefix->prefix_length, VNL);
  437.     }
  438.   return 0;
  439. }
  440. int
  441. ospf6_link_lsa_originate (struct thread *thread)
  442. {
  443.   struct ospf6_interface *oi;
  444.   char buffer[OSPF6_MAX_LSASIZE];
  445.   struct ospf6_lsa_header *lsa_header;
  446.   struct ospf6_lsa *old, *lsa;
  447.   struct ospf6_link_lsa *link_lsa;
  448.   struct ospf6_route *route;
  449.   struct ospf6_prefix *op;
  450.   oi = (struct ospf6_interface *) THREAD_ARG (thread);
  451.   oi->thread_link_lsa = NULL;
  452.   assert (oi->area);
  453.   /* find previous LSA */
  454.   old = ospf6_lsdb_lookup (htons (OSPF6_LSTYPE_LINK),
  455.                            htonl (oi->interface->ifindex),
  456.                            oi->area->ospf6->router_id, oi->lsdb);
  457.   if (CHECK_FLAG (oi->flag, OSPF6_INTERFACE_DISABLE))
  458.     {
  459.       if (old)
  460.         ospf6_lsa_purge (old);
  461.       return 0;
  462.     }
  463.   if (IS_OSPF6_DEBUG_ORIGINATE (LINK))
  464.     zlog_info ("Originate Link-LSA for Interface %s", oi->interface->name);
  465.   /* can't make Link-LSA if linklocal address not set */
  466.   if (oi->linklocal_addr == NULL)
  467.     {
  468.       if (IS_OSPF6_DEBUG_ORIGINATE (LINK))
  469.         zlog_info ("No Linklocal address on %s, defer originating",
  470.                    oi->interface->name);
  471.       if (old)
  472.         ospf6_lsa_purge (old);
  473.       return 0;
  474.     }
  475.   /* prepare buffer */
  476.   memset (buffer, 0, sizeof (buffer));
  477.   lsa_header = (struct ospf6_lsa_header *) buffer;
  478.   link_lsa = (struct ospf6_link_lsa *)
  479.     ((caddr_t) lsa_header + sizeof (struct ospf6_lsa_header));
  480.   /* Fill Link-LSA */
  481.   link_lsa->priority = oi->priority;
  482.   memcpy (link_lsa->options, oi->area->options, 3);
  483.   memcpy (&link_lsa->linklocal_addr, oi->linklocal_addr,
  484.           sizeof (struct in6_addr));
  485.   link_lsa->prefix_num = htonl (oi->route_connected->count);
  486.   op = (struct ospf6_prefix *)
  487.     ((caddr_t) link_lsa + sizeof (struct ospf6_link_lsa));
  488.   /* connected prefix to advertise */
  489.   for (route = ospf6_route_head (oi->route_connected); route;
  490.        route = ospf6_route_next (route))
  491.     {
  492.       op->prefix_length = route->prefix.prefixlen;
  493.       op->prefix_options = route->path.prefix_options;
  494.       op->prefix_metric = htons (0);
  495.       memcpy (OSPF6_PREFIX_BODY (op), &route->prefix.u.prefix6,
  496.               OSPF6_PREFIX_SPACE (op->prefix_length));
  497.       op = OSPF6_PREFIX_NEXT (op);
  498.     }
  499.   /* Fill LSA Header */
  500.   lsa_header->age = 0;
  501.   lsa_header->type = htons (OSPF6_LSTYPE_LINK);
  502.   lsa_header->id = htonl (oi->interface->ifindex);
  503.   lsa_header->adv_router = oi->area->ospf6->router_id;
  504.   lsa_header->seqnum =
  505.     ospf6_new_ls_seqnum (lsa_header->type, lsa_header->id,
  506.                          lsa_header->adv_router, oi->lsdb);
  507.   lsa_header->length = htons ((caddr_t) op - (caddr_t) buffer);
  508.   /* LSA checksum */
  509.   ospf6_lsa_checksum (lsa_header);
  510.   /* create LSA */
  511.   lsa = ospf6_lsa_create (lsa_header);
  512.   /* Originate */
  513.   ospf6_lsa_originate_interface (lsa, oi);
  514.   return 0;
  515. }
  516. /*****************************************/
  517. /* RFC2740 3.4.3.7 Intra-Area-Prefix-LSA */
  518. /*****************************************/
  519. int
  520. ospf6_intra_prefix_lsa_show (struct vty *vty, struct ospf6_lsa *lsa)
  521. {
  522.   char *start, *end, *current;
  523.   struct ospf6_intra_prefix_lsa *intra_prefix_lsa;
  524.   int prefixnum;
  525.   char buf[128];
  526.   struct ospf6_prefix *prefix;
  527.   char id[16], adv_router[16];
  528.   char *p, *mc, *la, *nu;
  529.   struct in6_addr in6;
  530.   intra_prefix_lsa = (struct ospf6_intra_prefix_lsa *)
  531.     ((caddr_t) lsa->header + sizeof (struct ospf6_lsa_header));
  532.   prefixnum = ntohs (intra_prefix_lsa->prefix_num);
  533.   vty_out (vty, "     Number of Prefix: %d%s", prefixnum, VNL);
  534.   inet_ntop (AF_INET, &intra_prefix_lsa->ref_id, id, sizeof (id));
  535.   inet_ntop (AF_INET, &intra_prefix_lsa->ref_adv_router,
  536.              adv_router, sizeof (adv_router));
  537.   vty_out (vty, "     Reference: %s Id: %s Adv: %s%s",
  538.            ospf6_lstype_name (intra_prefix_lsa->ref_type), id, adv_router,
  539.            VNL);
  540.   start = (char *) intra_prefix_lsa + sizeof (struct ospf6_intra_prefix_lsa);
  541.   end = (char *) lsa->header + ntohs (lsa->header->length); 
  542.   for (current = start; current < end; current += OSPF6_PREFIX_SIZE (prefix))
  543.     {
  544.       prefix = (struct ospf6_prefix *) current;
  545.       if (prefix->prefix_length == 0 ||
  546.           current + OSPF6_PREFIX_SIZE (prefix) > end)
  547.         break;
  548.       p = (CHECK_FLAG (prefix->prefix_options, OSPF6_PREFIX_OPTION_P) ?
  549.            "P" : "--");
  550.       mc = (CHECK_FLAG (prefix->prefix_options, OSPF6_PREFIX_OPTION_MC) ?
  551.            "MC" : "--");
  552.       la = (CHECK_FLAG (prefix->prefix_options, OSPF6_PREFIX_OPTION_LA) ?
  553.            "LA" : "--");
  554.       nu = (CHECK_FLAG (prefix->prefix_options, OSPF6_PREFIX_OPTION_NU) ?
  555.            "NU" : "--");
  556.       vty_out (vty, "     Prefix Options: %s|%s|%s|%s%s",
  557.                p, mc, la, nu, VNL);
  558.       memset (&in6, 0, sizeof (in6));
  559.       memcpy (&in6, OSPF6_PREFIX_BODY (prefix),
  560.               OSPF6_PREFIX_SPACE (prefix->prefix_length));
  561.       inet_ntop (AF_INET6, &in6, buf, sizeof (buf));
  562.       vty_out (vty, "     Prefix: %s/%d%s",
  563.                buf, prefix->prefix_length, VNL);
  564.     }
  565.   return 0;
  566. }
  567. int
  568. ospf6_intra_prefix_lsa_originate_stub (struct thread *thread)
  569. {
  570.   struct ospf6_area *oa;
  571.   char buffer[OSPF6_MAX_LSASIZE];
  572.   struct ospf6_lsa_header *lsa_header;
  573.   struct ospf6_lsa *old, *lsa;
  574.   struct ospf6_intra_prefix_lsa *intra_prefix_lsa;
  575.   struct ospf6_interface *oi;
  576.   struct ospf6_neighbor *on;
  577.   struct ospf6_route *route;
  578.   struct ospf6_prefix *op;
  579.   listnode i, j;
  580.   int full_count = 0;
  581.   unsigned short prefix_num = 0;
  582.   char buf[BUFSIZ];
  583.   struct ospf6_route_table *route_advertise;
  584.   oa = (struct ospf6_area *) THREAD_ARG (thread);
  585.   oa->thread_intra_prefix_lsa = NULL;
  586.   /* find previous LSA */
  587.   old = ospf6_lsdb_lookup (htons (OSPF6_LSTYPE_INTRA_PREFIX),
  588.                            htonl (0), oa->ospf6->router_id, oa->lsdb);
  589.   if (! IS_AREA_ENABLED (oa))
  590.     {
  591.       if (old)
  592.         ospf6_lsa_purge (old);
  593.       return 0;
  594.     }
  595.   if (IS_OSPF6_DEBUG_ORIGINATE (INTRA_PREFIX))
  596.     zlog_info ("Originate Intra-Area-Prefix-LSA for area %s's stub prefix",
  597.                oa->name);
  598.   /* prepare buffer */
  599.   memset (buffer, 0, sizeof (buffer));
  600.   lsa_header = (struct ospf6_lsa_header *) buffer;
  601.   intra_prefix_lsa = (struct ospf6_intra_prefix_lsa *)
  602.     ((caddr_t) lsa_header + sizeof (struct ospf6_lsa_header));
  603.   /* Fill Intra-Area-Prefix-LSA */
  604.   intra_prefix_lsa->ref_type = htons (OSPF6_LSTYPE_ROUTER);
  605.   intra_prefix_lsa->ref_id = htonl (0);
  606.   intra_prefix_lsa->ref_adv_router = oa->ospf6->router_id;
  607.   route_advertise = ospf6_route_table_create ();
  608.   for (i = listhead (oa->if_list); i; nextnode (i))
  609.     {
  610.       oi = (struct ospf6_interface *) getdata (i);
  611.       if (oi->state == OSPF6_INTERFACE_DOWN)
  612.         {
  613.           if (IS_OSPF6_DEBUG_ORIGINATE (INTRA_PREFIX))
  614.             zlog_info ("  Interface %s is down, ignore", oi->interface->name);
  615.           continue;
  616.         }
  617.       full_count = 0;
  618.       for (j = listhead (oi->neighbor_list); j; nextnode (j))
  619.         {
  620.           on = (struct ospf6_neighbor *) getdata (j);
  621.           if (on->state == OSPF6_NEIGHBOR_FULL)
  622.             full_count++;
  623.         }
  624.       if (oi->state != OSPF6_INTERFACE_LOOPBACK &&
  625.           oi->state != OSPF6_INTERFACE_POINTTOPOINT &&
  626.           full_count != 0)
  627.         {
  628.           if (IS_OSPF6_DEBUG_ORIGINATE (INTRA_PREFIX))
  629.             zlog_info ("  Interface %s is not stub, ignore",
  630.                        oi->interface->name);
  631.           continue;
  632.         }
  633.       if (IS_OSPF6_DEBUG_ORIGINATE (INTRA_PREFIX))
  634.         zlog_info ("  Interface %s:", oi->interface->name);
  635.       /* connected prefix to advertise */
  636.       for (route = ospf6_route_head (oi->route_connected); route;
  637.            route = ospf6_route_best_next (route))
  638.         {
  639.           if (IS_OSPF6_DEBUG_ORIGINATE (INTRA_PREFIX))
  640.             {
  641.               prefix2str (&route->prefix, buf, sizeof (buf));
  642.               zlog_info ("    include %s", buf);
  643.             }
  644.           ospf6_route_add (ospf6_route_copy (route), route_advertise);
  645.         }
  646.     }
  647.   if (route_advertise->count == 0)
  648.     {
  649.       if (old)
  650.         ospf6_lsa_purge (old);
  651.       ospf6_route_table_delete (route_advertise);
  652.       return 0;
  653.     }
  654.   /* put prefixes to advertise */
  655.   prefix_num = 0;
  656.   op = (struct ospf6_prefix *)
  657.     ((caddr_t) intra_prefix_lsa + sizeof (struct ospf6_intra_prefix_lsa));
  658.   for (route = ospf6_route_head (route_advertise); route;
  659.        route = ospf6_route_best_next (route))
  660.     {
  661.       op->prefix_length = route->prefix.prefixlen;
  662.       op->prefix_options = route->path.prefix_options;
  663.       op->prefix_metric = htons (route->path.cost);
  664.       memcpy (OSPF6_PREFIX_BODY (op), &route->prefix.u.prefix6,
  665.               OSPF6_PREFIX_SPACE (op->prefix_length));
  666.       op = OSPF6_PREFIX_NEXT (op);
  667.       prefix_num++;
  668.     }
  669.   ospf6_route_table_delete (route_advertise);
  670.   if (prefix_num == 0)
  671.     {
  672.       if (IS_OSPF6_DEBUG_ORIGINATE (INTRA_PREFIX))
  673.         zlog_info ("Quit to Advertise Intra-Prefix: no route to advertise");
  674.       return 0;
  675.     }
  676.   intra_prefix_lsa->prefix_num = htons (prefix_num);
  677.   /* Fill LSA Header */
  678.   lsa_header->age = 0;
  679.   lsa_header->type = htons (OSPF6_LSTYPE_INTRA_PREFIX);
  680.   lsa_header->id = htonl (0);
  681.   lsa_header->adv_router = oa->ospf6->router_id;
  682.   lsa_header->seqnum =
  683.     ospf6_new_ls_seqnum (lsa_header->type, lsa_header->id,
  684.                          lsa_header->adv_router, oa->lsdb);
  685.   lsa_header->length = htons ((caddr_t) op - (caddr_t) lsa_header);
  686.   /* LSA checksum */
  687.   ospf6_lsa_checksum (lsa_header);
  688.   /* create LSA */
  689.   lsa = ospf6_lsa_create (lsa_header);
  690.   /* Originate */
  691.   ospf6_lsa_originate_area (lsa, oa);
  692.   return 0;
  693. }
  694. int
  695. ospf6_intra_prefix_lsa_originate_transit (struct thread *thread)
  696. {
  697.   struct ospf6_interface *oi;
  698.   char buffer[OSPF6_MAX_LSASIZE];
  699.   struct ospf6_lsa_header *lsa_header;
  700.   struct ospf6_lsa *old, *lsa;
  701.   struct ospf6_intra_prefix_lsa *intra_prefix_lsa;
  702.   struct ospf6_neighbor *on;
  703.   struct ospf6_route *route;
  704.   struct ospf6_prefix *op;
  705.   listnode i;
  706.   int full_count = 0;
  707.   unsigned short prefix_num = 0;
  708.   struct ospf6_route_table *route_advertise;
  709.   struct ospf6_link_lsa *link_lsa;
  710.   char *start, *end, *current;
  711.   u_int16_t type;
  712.   char buf[BUFSIZ];
  713.   oi = (struct ospf6_interface *) THREAD_ARG (thread);
  714.   oi->thread_intra_prefix_lsa = NULL;
  715.   assert (oi->area);
  716.   /* find previous LSA */
  717.   old = ospf6_lsdb_lookup (htons (OSPF6_LSTYPE_INTRA_PREFIX),
  718.                            htonl (oi->interface->ifindex),
  719.                            oi->area->ospf6->router_id, oi->area->lsdb);
  720.   if (CHECK_FLAG (oi->flag, OSPF6_INTERFACE_DISABLE))
  721.     {
  722.       if (old)
  723.         ospf6_lsa_purge (old);
  724.       return 0;
  725.     }
  726.   if (IS_OSPF6_DEBUG_ORIGINATE (INTRA_PREFIX))
  727.     zlog_info ("Originate Intra-Area-Prefix-LSA for interface %s's prefix",
  728.                oi->interface->name);
  729.   /* prepare buffer */
  730.   memset (buffer, 0, sizeof (buffer));
  731.   lsa_header = (struct ospf6_lsa_header *) buffer;
  732.   intra_prefix_lsa = (struct ospf6_intra_prefix_lsa *)
  733.     ((caddr_t) lsa_header + sizeof (struct ospf6_lsa_header));
  734.   /* Fill Intra-Area-Prefix-LSA */
  735.   intra_prefix_lsa->ref_type = htons (OSPF6_LSTYPE_NETWORK);
  736.   intra_prefix_lsa->ref_id = htonl (oi->interface->ifindex);
  737.   intra_prefix_lsa->ref_adv_router = oi->area->ospf6->router_id;
  738.   if (oi->state != OSPF6_INTERFACE_DR)
  739.     {
  740.       if (IS_OSPF6_DEBUG_ORIGINATE (INTRA_PREFIX))
  741.         zlog_info ("  Interface is not DR");
  742.       if (old)
  743.         ospf6_lsa_purge (old);
  744.       return 0;
  745.     }
  746.   full_count = 0;
  747.   for (i = listhead (oi->neighbor_list); i; nextnode (i))
  748.     {
  749.       on = (struct ospf6_neighbor *) getdata (i);
  750.       if (on->state == OSPF6_NEIGHBOR_FULL)
  751.         full_count++;
  752.     }
  753.   if (full_count == 0)
  754.     {
  755.       if (IS_OSPF6_DEBUG_ORIGINATE (INTRA_PREFIX))
  756.         zlog_info ("  Interface is stub");
  757.       if (old)
  758.         ospf6_lsa_purge (old);
  759.       return 0;
  760.     }
  761.   /* connected prefix to advertise */
  762.   route_advertise = ospf6_route_table_create ();
  763.   type = ntohs (OSPF6_LSTYPE_LINK);
  764.   for (lsa = ospf6_lsdb_type_head (type, oi->lsdb); lsa;
  765.        lsa = ospf6_lsdb_type_next (type, lsa))
  766.     {
  767.       if (OSPF6_LSA_IS_MAXAGE (lsa))
  768.         continue;
  769.       if (IS_OSPF6_DEBUG_ORIGINATE (INTRA_PREFIX))
  770.         zlog_info ("  include prefix from %s", lsa->name);
  771.       if (lsa->header->adv_router != oi->area->ospf6->router_id)
  772.         {
  773.           on = ospf6_neighbor_lookup (lsa->header->adv_router, oi);
  774.           if (on == NULL || on->state != OSPF6_NEIGHBOR_FULL)
  775.             {
  776.               if (IS_OSPF6_DEBUG_ORIGINATE (INTRA_PREFIX))
  777.                 zlog_info ("    Neighbor not found or not Full, ignore");
  778.               continue;
  779.             }
  780.         }
  781.       link_lsa = (struct ospf6_link_lsa *)
  782.         ((caddr_t) lsa->header + sizeof (struct ospf6_lsa_header));
  783.       prefix_num = (unsigned short) ntohl (link_lsa->prefix_num);
  784.       start = (char *) link_lsa + sizeof (struct ospf6_link_lsa);
  785.       end = (char *) lsa->header + ntohs (lsa->header->length); 
  786.       for (current = start; current < end && prefix_num;
  787.            current += OSPF6_PREFIX_SIZE (op))
  788.         {
  789.           op = (struct ospf6_prefix *) current;
  790.           if (op->prefix_length == 0 ||
  791.               current + OSPF6_PREFIX_SIZE (op) > end)
  792.             break;
  793.           route = ospf6_route_create ();
  794.           route->type = OSPF6_DEST_TYPE_NETWORK;
  795.           route->prefix.family = AF_INET6;
  796.           route->prefix.prefixlen = op->prefix_length;
  797.           memset (&route->prefix.u.prefix6, 0, sizeof (struct in6_addr));
  798.           memcpy (&route->prefix.u.prefix6, OSPF6_PREFIX_BODY (op),
  799.                   OSPF6_PREFIX_SPACE (op->prefix_length));
  800.           route->path.origin.type = lsa->header->type;
  801.           route->path.origin.id = lsa->header->id;
  802.           route->path.origin.adv_router = lsa->header->adv_router;
  803.           route->path.options[0] = link_lsa->options[0];
  804.           route->path.options[1] = link_lsa->options[1];
  805.           route->path.options[2] = link_lsa->options[2];
  806.           route->path.prefix_options = op->prefix_options;
  807.           route->path.area_id = oi->area->area_id;
  808.           route->path.type = OSPF6_PATH_TYPE_INTRA;
  809.           if (IS_OSPF6_DEBUG_ORIGINATE (INTRA_PREFIX))
  810.             {
  811.               prefix2str (&route->prefix, buf, sizeof (buf));
  812.               zlog_info ("    include %s", buf);
  813.             }
  814.           ospf6_route_add (route, route_advertise);
  815.           prefix_num--;
  816.         }
  817.       if (current != end && IS_OSPF6_DEBUG_ORIGINATE (INTRA_PREFIX))
  818.         zlog_info ("Trailing garbage in %s", lsa->name);
  819.     }
  820.   op = (struct ospf6_prefix *)
  821.     ((caddr_t) intra_prefix_lsa + sizeof (struct ospf6_intra_prefix_lsa));
  822.   prefix_num = 0;
  823.   for (route = ospf6_route_head (route_advertise); route;
  824.        route = ospf6_route_best_next (route))
  825.     {
  826.       op->prefix_length = route->prefix.prefixlen;
  827.       op->prefix_options = route->path.prefix_options;
  828.       op->prefix_metric = htons (0);
  829.       memcpy (OSPF6_PREFIX_BODY (op), &route->prefix.u.prefix6,
  830.               OSPF6_PREFIX_SPACE (op->prefix_length));
  831.       op = OSPF6_PREFIX_NEXT (op);
  832.       prefix_num++;
  833.     }
  834.   ospf6_route_table_delete (route_advertise);
  835.   if (prefix_num == 0)
  836.     {
  837.       if (IS_OSPF6_DEBUG_ORIGINATE (INTRA_PREFIX))
  838.         zlog_info ("Quit to Advertise Intra-Prefix: no route to advertise");
  839.       return 0;
  840.     }
  841.   intra_prefix_lsa->prefix_num = htons (prefix_num);
  842.   /* Fill LSA Header */
  843.   lsa_header->age = 0;
  844.   lsa_header->type = htons (OSPF6_LSTYPE_INTRA_PREFIX);
  845.   lsa_header->id = htonl (oi->interface->ifindex);
  846.   lsa_header->adv_router = oi->area->ospf6->router_id;
  847.   lsa_header->seqnum =
  848.     ospf6_new_ls_seqnum (lsa_header->type, lsa_header->id,
  849.                          lsa_header->adv_router, oi->area->lsdb);
  850.   lsa_header->length = htons ((caddr_t) op - (caddr_t) lsa_header);
  851.   /* LSA checksum */
  852.   ospf6_lsa_checksum (lsa_header);
  853.   /* create LSA */
  854.   lsa = ospf6_lsa_create (lsa_header);
  855.   /* Originate */
  856.   ospf6_lsa_originate_area (lsa, oi->area);
  857.   return 0;
  858. }
  859. void
  860. ospf6_intra_prefix_lsa_add (struct ospf6_lsa *lsa)
  861. {
  862.   struct ospf6_area *oa;
  863.   struct ospf6_intra_prefix_lsa *intra_prefix_lsa;
  864.   struct prefix ls_prefix;
  865.   struct ospf6_route *route, *ls_entry;
  866.   int i, prefix_num;
  867.   struct ospf6_prefix *op;
  868.   char *start, *current, *end;
  869.   char buf[64];
  870.   if (OSPF6_LSA_IS_MAXAGE (lsa))
  871.     return;
  872.   if (IS_OSPF6_DEBUG_EXAMIN (INTRA_PREFIX))
  873.     zlog_info ("%s found", lsa->name);
  874.   oa = OSPF6_AREA (lsa->lsdb->data);
  875.   intra_prefix_lsa = (struct ospf6_intra_prefix_lsa *)
  876.     OSPF6_LSA_HEADER_END (lsa->header);
  877.   if (intra_prefix_lsa->ref_type == htons (OSPF6_LSTYPE_ROUTER))
  878.     ospf6_linkstate_prefix (intra_prefix_lsa->ref_adv_router,
  879.                             htonl (0), &ls_prefix);
  880.   else if (intra_prefix_lsa->ref_type == htons (OSPF6_LSTYPE_NETWORK))
  881.     ospf6_linkstate_prefix (intra_prefix_lsa->ref_adv_router,
  882.                             intra_prefix_lsa->ref_id, &ls_prefix);
  883.   else
  884.     {
  885.       if (IS_OSPF6_DEBUG_EXAMIN (INTRA_PREFIX))
  886.         zlog_info ("Unknown reference LS-type: %#hx",
  887.                    ntohs (intra_prefix_lsa->ref_type));
  888.       return;
  889.     }
  890.   ls_entry = ospf6_route_lookup (&ls_prefix, oa->spf_table);
  891.   if (ls_entry == NULL)
  892.     {
  893.       if (IS_OSPF6_DEBUG_EXAMIN (INTRA_PREFIX))
  894.         {
  895.           ospf6_linkstate_prefix2str (&ls_prefix, buf, sizeof (buf));
  896.           zlog_info ("LS entry does not exist: %s", buf);
  897.         }
  898.       return;
  899.     }
  900.   prefix_num = ntohs (intra_prefix_lsa->prefix_num);
  901.   start = (caddr_t) intra_prefix_lsa +
  902.           sizeof (struct ospf6_intra_prefix_lsa);
  903.   end = OSPF6_LSA_END (lsa->header);
  904.   for (current = start; current < end; current += OSPF6_PREFIX_SIZE (op))
  905.     {
  906.       op = (struct ospf6_prefix *) current;
  907.       if (prefix_num == 0)
  908.         break;
  909.       if (end < current + OSPF6_PREFIX_SIZE (op))
  910.         break;
  911.       route = ospf6_route_create ();
  912.       memset (&route->prefix, 0, sizeof (struct prefix));
  913.       route->prefix.family = AF_INET6;
  914.       route->prefix.prefixlen = op->prefix_length;
  915.       ospf6_prefix_in6_addr (&route->prefix.u.prefix6, op);
  916.       route->type = OSPF6_DEST_TYPE_NETWORK;
  917.       route->path.origin.type = lsa->header->type;
  918.       route->path.origin.id = lsa->header->id;
  919.       route->path.origin.adv_router = lsa->header->adv_router;
  920.       route->path.prefix_options = op->prefix_options;
  921.       route->path.area_id = oa->area_id;
  922.       route->path.type = OSPF6_PATH_TYPE_INTRA;
  923.       route->path.metric_type = 1;
  924.       route->path.cost = ls_entry->path.cost +
  925.                          ntohs (op->prefix_metric);
  926.       for (i = 0; ospf6_nexthop_is_set (&ls_entry->nexthop[i]) &&
  927.            i < OSPF6_MULTI_PATH_LIMIT; i++)
  928.         ospf6_nexthop_copy (&route->nexthop[i], &ls_entry->nexthop[i]);
  929.       if (IS_OSPF6_DEBUG_EXAMIN (INTRA_PREFIX))
  930.         {
  931.           prefix2str (&route->prefix, buf, sizeof (buf));
  932.           zlog_info ("  add %s", buf);
  933.         }
  934.       ospf6_route_add (route, oa->route_table);
  935.       prefix_num--;
  936.     }
  937.   if (current != end && IS_OSPF6_DEBUG_EXAMIN (INTRA_PREFIX))
  938.     zlog_info ("Trailing garbage ignored");
  939. }
  940. void
  941. ospf6_intra_prefix_lsa_remove (struct ospf6_lsa *lsa)
  942. {
  943.   struct ospf6_area *oa;
  944.   struct ospf6_intra_prefix_lsa *intra_prefix_lsa;
  945.   struct prefix prefix;
  946.   struct ospf6_route *route;
  947.   int prefix_num;
  948.   struct ospf6_prefix *op;
  949.   char *start, *current, *end;
  950.   char buf[64];
  951.   if (IS_OSPF6_DEBUG_EXAMIN (INTRA_PREFIX))
  952.     zlog_info ("%s disappearing", lsa->name);
  953.   oa = OSPF6_AREA (lsa->lsdb->data);
  954.   intra_prefix_lsa = (struct ospf6_intra_prefix_lsa *)
  955.     OSPF6_LSA_HEADER_END (lsa->header);
  956.   prefix_num = ntohs (intra_prefix_lsa->prefix_num);
  957.   start = (caddr_t) intra_prefix_lsa +
  958.           sizeof (struct ospf6_intra_prefix_lsa);
  959.   end = OSPF6_LSA_END (lsa->header);
  960.   for (current = start; current < end; current += OSPF6_PREFIX_SIZE (op))
  961.     {
  962.       op = (struct ospf6_prefix *) current;
  963.       if (prefix_num == 0)
  964.         break;
  965.       if (end < current + OSPF6_PREFIX_SIZE (op))
  966.         break;
  967.       prefix_num--;
  968.       memset (&prefix, 0, sizeof (struct prefix));
  969.       prefix.family = AF_INET6;
  970.       prefix.prefixlen = op->prefix_length;
  971.       ospf6_prefix_in6_addr (&prefix.u.prefix6, op);
  972.       route = ospf6_route_lookup (&prefix, oa->route_table);
  973.       if (route == NULL)
  974.         continue;
  975.       for (ospf6_route_lock (route);
  976.            route && ospf6_route_is_prefix (&prefix, route);
  977.            route = ospf6_route_next (route))
  978.         {
  979.           if (route->type != OSPF6_DEST_TYPE_NETWORK)
  980.             continue;
  981.           if (route->path.area_id != oa->area_id)
  982.             continue;
  983.           if (route->path.type != OSPF6_PATH_TYPE_INTRA)
  984.             continue;
  985.           if (route->path.origin.type != lsa->header->type ||
  986.               route->path.origin.id != lsa->header->id ||
  987.               route->path.origin.adv_router != lsa->header->adv_router)
  988.             continue;
  989.           if (IS_OSPF6_DEBUG_EXAMIN (INTRA_PREFIX))
  990.             {
  991.               prefix2str (&route->prefix, buf, sizeof (buf));
  992.               zlog_info ("remove %s", buf);
  993.             }
  994.           ospf6_route_remove (route, oa->route_table);
  995.         }
  996.     }
  997.   if (current != end && IS_OSPF6_DEBUG_EXAMIN (INTRA_PREFIX))
  998.     zlog_info ("Trailing garbage ignored");
  999. }
  1000. void
  1001. ospf6_intra_route_calculation (struct ospf6_area *oa)
  1002. {
  1003.   struct ospf6_route *route;
  1004.   u_int16_t type;
  1005.   struct ospf6_lsa *lsa;
  1006.   void (*hook_add) (struct ospf6_route *) = NULL;
  1007.   void (*hook_remove) (struct ospf6_route *) = NULL;
  1008.   if (IS_OSPF6_DEBUG_EXAMIN (INTRA_PREFIX))
  1009.     zlog_info ("Re-examin intra-routes for area %s", oa->name);
  1010.   hook_add = oa->route_table->hook_add;
  1011.   hook_remove = oa->route_table->hook_remove;
  1012.   oa->route_table->hook_add = NULL;
  1013.   oa->route_table->hook_remove = NULL;
  1014.   for (route = ospf6_route_head (oa->route_table); route;
  1015.        route = ospf6_route_next (route))
  1016.     route->flag = OSPF6_ROUTE_REMOVE;
  1017.   type = htons (OSPF6_LSTYPE_INTRA_PREFIX);
  1018.   for (lsa = ospf6_lsdb_type_head (type, oa->lsdb); lsa;
  1019.        lsa = ospf6_lsdb_type_next (type, lsa))
  1020.     ospf6_intra_prefix_lsa_add (lsa);
  1021.   oa->route_table->hook_add = hook_add;
  1022.   oa->route_table->hook_remove = hook_remove;
  1023.   for (route = ospf6_route_head (oa->route_table); route;
  1024.        route = ospf6_route_next (route))
  1025.     {
  1026.       if (CHECK_FLAG (route->flag, OSPF6_ROUTE_REMOVE) &&
  1027.           CHECK_FLAG (route->flag, OSPF6_ROUTE_ADD))
  1028.         {
  1029.           UNSET_FLAG (route->flag, OSPF6_ROUTE_REMOVE);
  1030.           UNSET_FLAG (route->flag, OSPF6_ROUTE_ADD);
  1031.         }
  1032.       if (CHECK_FLAG (route->flag, OSPF6_ROUTE_REMOVE))
  1033.         ospf6_route_remove (route, oa->route_table);
  1034.       else if (CHECK_FLAG (route->flag, OSPF6_ROUTE_ADD) ||
  1035.                CHECK_FLAG (route->flag, OSPF6_ROUTE_CHANGE))
  1036.         {
  1037.           if (hook_add)
  1038.             (*hook_add) (route);
  1039.         }
  1040.       route->flag = 0;
  1041.     }
  1042.   if (IS_OSPF6_DEBUG_EXAMIN (INTRA_PREFIX))
  1043.     zlog_info ("Re-examin intra-routes for area %s: Done", oa->name);
  1044. }
  1045. void
  1046. ospf6_intra_brouter_calculation (struct ospf6_area *oa)
  1047. {
  1048.   struct ospf6_route *lsentry, *copy;
  1049.   void (*hook_add) (struct ospf6_route *) = NULL;
  1050.   void (*hook_remove) (struct ospf6_route *) = NULL;
  1051.   char buf[16];
  1052.   if (IS_OSPF6_DEBUG_ROUTE (INTRA))
  1053.     zlog_info ("Border-router calculation for area %s", oa->name);
  1054.   hook_add = oa->ospf6->brouter_table->hook_add;
  1055.   hook_remove = oa->ospf6->brouter_table->hook_remove;
  1056.   oa->ospf6->brouter_table->hook_add = NULL;
  1057.   oa->ospf6->brouter_table->hook_remove = NULL;
  1058.   /* withdraw the previous router entries for the area */
  1059.   for (lsentry = ospf6_route_head (oa->ospf6->brouter_table); lsentry;
  1060.        lsentry = ospf6_route_next (lsentry))
  1061.     {
  1062.       if (lsentry->path.area_id != oa->area_id)
  1063.         continue;
  1064.       lsentry->flag = OSPF6_ROUTE_REMOVE;
  1065.     }
  1066.   for (lsentry = ospf6_route_head (oa->spf_table); lsentry;
  1067.        lsentry = ospf6_route_next (lsentry))
  1068.     {
  1069.       if (lsentry->type != OSPF6_DEST_TYPE_LINKSTATE)
  1070.         continue;
  1071.       if (ospf6_linkstate_prefix_id (&lsentry->prefix) != htonl (0))
  1072.         continue;
  1073.       if (! CHECK_FLAG (lsentry->path.router_bits, OSPF6_ROUTER_BIT_E) &&
  1074.           ! CHECK_FLAG (lsentry->path.router_bits, OSPF6_ROUTER_BIT_B))
  1075.         continue;
  1076.       copy = ospf6_route_copy (lsentry);
  1077.       copy->type = OSPF6_DEST_TYPE_ROUTER;
  1078.       copy->path.area_id = oa->area_id;
  1079.       ospf6_route_add (copy, oa->ospf6->brouter_table);
  1080.       if (IS_OSPF6_DEBUG_ROUTE (INTRA))
  1081.         {
  1082.           inet_ntop (AF_INET, &ADV_ROUTER_IN_PREFIX (&copy->prefix),
  1083.                      buf, sizeof (buf));
  1084.           zlog_info ("Re-install router entry %s", buf);
  1085.         }
  1086.     }
  1087.   oa->ospf6->brouter_table->hook_add = hook_add;
  1088.   oa->ospf6->brouter_table->hook_remove = hook_remove;
  1089.   for (lsentry = ospf6_route_head (oa->ospf6->brouter_table); lsentry;
  1090.        lsentry = ospf6_route_next (lsentry))
  1091.     {
  1092.       if (lsentry->path.area_id != oa->area_id)
  1093.         continue;
  1094.       if (CHECK_FLAG (lsentry->flag, OSPF6_ROUTE_WAS_REMOVED))
  1095.         continue;
  1096.       if (CHECK_FLAG (lsentry->flag, OSPF6_ROUTE_REMOVE) &&
  1097.           CHECK_FLAG (lsentry->flag, OSPF6_ROUTE_ADD))
  1098.         {
  1099.           UNSET_FLAG (lsentry->flag, OSPF6_ROUTE_REMOVE);
  1100.           UNSET_FLAG (lsentry->flag, OSPF6_ROUTE_ADD);
  1101.         }
  1102.       if (CHECK_FLAG (lsentry->flag, OSPF6_ROUTE_REMOVE))
  1103.         ospf6_route_remove (lsentry, oa->ospf6->brouter_table);
  1104.       else if (CHECK_FLAG (lsentry->flag, OSPF6_ROUTE_ADD) ||
  1105.                CHECK_FLAG (lsentry->flag, OSPF6_ROUTE_CHANGE))
  1106.         {
  1107.           if (IS_OSPF6_DEBUG_ROUTE (INTRA))
  1108.             {
  1109.               inet_ntop (AF_INET, &ADV_ROUTER_IN_PREFIX (&lsentry->prefix),
  1110.                          buf, sizeof (buf));
  1111.               zlog_info ("Call hook for router entry %s", buf);
  1112.             }
  1113.           if (hook_add)
  1114.             (*hook_add) (lsentry);
  1115.         }
  1116.       lsentry->flag = 0;
  1117.     }
  1118.   if (IS_OSPF6_DEBUG_ROUTE (INTRA))
  1119.     zlog_info ("Border-router calculation for area %s: Done", oa->name);
  1120. }
  1121. struct ospf6_lsa_handler router_handler =
  1122. {
  1123.   OSPF6_LSTYPE_ROUTER,
  1124.   "Router",
  1125.   ospf6_router_lsa_show
  1126. };
  1127. struct ospf6_lsa_handler network_handler =
  1128. {
  1129.   OSPF6_LSTYPE_NETWORK,
  1130.   "Network",
  1131.   ospf6_network_lsa_show
  1132. };
  1133. struct ospf6_lsa_handler link_handler =
  1134. {
  1135.   OSPF6_LSTYPE_LINK,
  1136.   "Link",
  1137.   ospf6_link_lsa_show
  1138. };
  1139. struct ospf6_lsa_handler intra_prefix_handler =
  1140. {
  1141.   OSPF6_LSTYPE_INTRA_PREFIX,
  1142.   "Intra-Prefix",
  1143.   ospf6_intra_prefix_lsa_show
  1144. };
  1145. void
  1146. ospf6_intra_init ()
  1147. {
  1148.   ospf6_install_lsa_handler (&router_handler);
  1149.   ospf6_install_lsa_handler (&network_handler);
  1150.   ospf6_install_lsa_handler (&link_handler);
  1151.   ospf6_install_lsa_handler (&intra_prefix_handler);
  1152. }