LCOV - code coverage report
Current view: top level - bgpd - bgp_nexthop.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 679 0.0 %
Date: 2015-11-19 Functions: 0 37 0.0 %

          Line data    Source code
       1             : /* BGP nexthop scan
       2             :    Copyright (C) 2000 Kunihiro Ishiguro
       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 Free
      18             : Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
      19             : 02111-1307, USA.  */
      20             : 
      21             : #include <zebra.h>
      22             : 
      23             : #include "command.h"
      24             : #include "thread.h"
      25             : #include "prefix.h"
      26             : #include "zclient.h"
      27             : #include "stream.h"
      28             : #include "network.h"
      29             : #include "log.h"
      30             : #include "memory.h"
      31             : #include "hash.h"
      32             : #include "jhash.h"
      33             : 
      34             : #include "bgpd/bgpd.h"
      35             : #include "bgpd/bgp_table.h"
      36             : #include "bgpd/bgp_route.h"
      37             : #include "bgpd/bgp_attr.h"
      38             : #include "bgpd/bgp_nexthop.h"
      39             : #include "bgpd/bgp_debug.h"
      40             : #include "bgpd/bgp_damp.h"
      41             : #include "zebra/rib.h"
      42             : #include "zebra/zserv.h"      /* For ZEBRA_SERV_PATH. */
      43             : 
      44             : struct bgp_nexthop_cache *zlookup_query (struct in_addr);
      45             : #ifdef HAVE_IPV6
      46             : struct bgp_nexthop_cache *zlookup_query_ipv6 (struct in6_addr *);
      47             : #endif /* HAVE_IPV6 */
      48             : 
      49             : /* Only one BGP scan thread are activated at the same time. */
      50             : static struct thread *bgp_scan_thread = NULL;
      51             : 
      52             : /* BGP import thread */
      53             : static struct thread *bgp_import_thread = NULL;
      54             : 
      55             : /* BGP scan interval. */
      56             : static int bgp_scan_interval;
      57             : 
      58             : /* BGP import interval. */
      59             : static int bgp_import_interval;
      60             : 
      61             : /* Route table for next-hop lookup cache. */
      62             : static struct bgp_table *bgp_nexthop_cache_table[AFI_MAX];
      63             : static struct bgp_table *cache1_table[AFI_MAX];
      64             : static struct bgp_table *cache2_table[AFI_MAX];
      65             : 
      66             : /* Route table for connected route. */
      67             : static struct bgp_table *bgp_connected_table[AFI_MAX];
      68             : 
      69             : /* BGP nexthop lookup query client. */
      70             : struct zclient *zlookup = NULL;
      71             : 
      72             : /* Add nexthop to the end of the list.  */
      73             : static void
      74           0 : bnc_nexthop_add (struct bgp_nexthop_cache *bnc, struct nexthop *nexthop)
      75             : {
      76             :   struct nexthop *last;
      77             : 
      78           0 :   for (last = bnc->nexthop; last && last->next; last = last->next)
      79             :     ;
      80           0 :   if (last)
      81           0 :     last->next = nexthop;
      82             :   else
      83           0 :     bnc->nexthop = nexthop;
      84           0 :   nexthop->prev = last;
      85           0 : }
      86             : 
      87             : static void
      88           0 : bnc_nexthop_free (struct bgp_nexthop_cache *bnc)
      89             : {
      90             :   struct nexthop *nexthop;
      91           0 :   struct nexthop *next = NULL;
      92             : 
      93           0 :   for (nexthop = bnc->nexthop; nexthop; nexthop = next)
      94             :     {
      95           0 :       next = nexthop->next;
      96           0 :       XFREE (MTYPE_NEXTHOP, nexthop);
      97             :     }
      98           0 : }
      99             : 
     100             : static struct bgp_nexthop_cache *
     101           0 : bnc_new (void)
     102             : {
     103           0 :   return XCALLOC (MTYPE_BGP_NEXTHOP_CACHE, sizeof (struct bgp_nexthop_cache));
     104             : }
     105             : 
     106             : static void
     107           0 : bnc_free (struct bgp_nexthop_cache *bnc)
     108             : {
     109           0 :   bnc_nexthop_free (bnc);
     110           0 :   XFREE (MTYPE_BGP_NEXTHOP_CACHE, bnc);
     111           0 : }
     112             : 
     113             : static int
     114           0 : bgp_nexthop_same (struct nexthop *next1, struct nexthop *next2)
     115             : {
     116           0 :   if (next1->type != next2->type)
     117           0 :     return 0;
     118             : 
     119           0 :   switch (next1->type)
     120             :     {
     121             :     case ZEBRA_NEXTHOP_IPV4:
     122           0 :       if (! IPV4_ADDR_SAME (&next1->gate.ipv4, &next2->gate.ipv4))
     123           0 :         return 0;
     124           0 :       break;
     125             :     case ZEBRA_NEXTHOP_IPV4_IFINDEX:
     126           0 :       if (! IPV4_ADDR_SAME (&next1->gate.ipv4, &next2->gate.ipv4)
     127           0 :           || next1->ifindex != next2->ifindex)
     128           0 :         return 0;
     129           0 :       break;
     130             :     case ZEBRA_NEXTHOP_IFINDEX:
     131             :     case ZEBRA_NEXTHOP_IFNAME:
     132           0 :       if (next1->ifindex != next2->ifindex)
     133           0 :         return 0;
     134           0 :       break;
     135             : #ifdef HAVE_IPV6
     136             :     case ZEBRA_NEXTHOP_IPV6:
     137           0 :       if (! IPV6_ADDR_SAME (&next1->gate.ipv6, &next2->gate.ipv6))
     138           0 :         return 0;
     139           0 :       break;
     140             :     case ZEBRA_NEXTHOP_IPV6_IFINDEX:
     141             :     case ZEBRA_NEXTHOP_IPV6_IFNAME:
     142           0 :       if (! IPV6_ADDR_SAME (&next1->gate.ipv6, &next2->gate.ipv6))
     143           0 :         return 0;
     144           0 :       if (next1->ifindex != next2->ifindex)
     145           0 :         return 0;
     146           0 :       break;
     147             : #endif /* HAVE_IPV6 */
     148             :     default:
     149             :       /* do nothing */
     150           0 :       break;
     151             :     }
     152           0 :   return 1;
     153             : }
     154             : 
     155             : static int
     156           0 : bgp_nexthop_cache_different (struct bgp_nexthop_cache *bnc1,
     157             :                            struct bgp_nexthop_cache *bnc2)
     158             : {
     159             :   int i;
     160             :   struct nexthop *next1, *next2;
     161             : 
     162           0 :   if (bnc1->nexthop_num != bnc2->nexthop_num)
     163           0 :     return 1;
     164             : 
     165           0 :   next1 = bnc1->nexthop;
     166           0 :   next2 = bnc2->nexthop;
     167             : 
     168           0 :   for (i = 0; i < bnc1->nexthop_num; i++)
     169             :     {
     170           0 :       if (! bgp_nexthop_same (next1, next2))
     171           0 :         return 1;
     172             : 
     173           0 :       next1 = next1->next;
     174           0 :       next2 = next2->next;
     175             :     }
     176           0 :   return 0;
     177             : }
     178             : 
     179             : /* If nexthop exists on connected network return 1. */
     180             : int
     181           0 : bgp_nexthop_onlink (afi_t afi, struct attr *attr)
     182             : {
     183             :   struct bgp_node *rn;
     184             :   
     185             :   /* If zebra is not enabled return */
     186           0 :   if (zlookup->sock < 0)
     187           0 :     return 1;
     188             :   
     189             :   /* Lookup the address is onlink or not. */
     190           0 :   if (afi == AFI_IP)
     191             :     {
     192           0 :       rn = bgp_node_match_ipv4 (bgp_connected_table[AFI_IP], &attr->nexthop);
     193           0 :       if (rn)
     194             :         {
     195           0 :           bgp_unlock_node (rn);
     196           0 :           return 1;
     197             :         }
     198             :     }
     199             : #ifdef HAVE_IPV6
     200           0 :   else if (afi == AFI_IP6)
     201             :     {
     202           0 :       if (attr->extra->mp_nexthop_len == 32)
     203           0 :         return 1;
     204           0 :       else if (attr->extra->mp_nexthop_len == 16)
     205             :         {
     206           0 :           if (IN6_IS_ADDR_LINKLOCAL (&attr->extra->mp_nexthop_global))
     207           0 :             return 1;
     208             : 
     209           0 :           rn = bgp_node_match_ipv6 (bgp_connected_table[AFI_IP6],
     210           0 :                                       &attr->extra->mp_nexthop_global);
     211           0 :           if (rn)
     212             :             {
     213           0 :               bgp_unlock_node (rn);
     214           0 :               return 1;
     215             :             }
     216             :         }
     217             :     }
     218             : #endif /* HAVE_IPV6 */
     219           0 :   return 0;
     220             : }
     221             : 
     222             : #ifdef HAVE_IPV6
     223             : /* Check specified next-hop is reachable or not. */
     224             : static int
     225           0 : bgp_nexthop_lookup_ipv6 (struct peer *peer, struct bgp_info *ri, int *changed,
     226             :                          int *metricchanged)
     227             : {
     228             :   struct bgp_node *rn;
     229             :   struct prefix p;
     230             :   struct bgp_nexthop_cache *bnc;
     231             :   struct attr *attr;
     232             :   
     233             :   /* If lookup is not enabled, return valid. */
     234           0 :   if (zlookup->sock < 0)
     235             :     {
     236           0 :       if (ri->extra)
     237           0 :         ri->extra->igpmetric = 0;
     238           0 :       return 1;
     239             :     }
     240             :   
     241             :   /* Only check IPv6 global address only nexthop. */
     242           0 :   attr = ri->attr;
     243             : 
     244           0 :   if (attr->extra->mp_nexthop_len != 16 
     245           0 :       || IN6_IS_ADDR_LINKLOCAL (&attr->extra->mp_nexthop_global))
     246           0 :     return 1;
     247             : 
     248           0 :   memset (&p, 0, sizeof (struct prefix));
     249           0 :   p.family = AF_INET6;
     250           0 :   p.prefixlen = IPV6_MAX_BITLEN;
     251           0 :   p.u.prefix6 = attr->extra->mp_nexthop_global;
     252             : 
     253             :   /* IBGP or ebgp-multihop */
     254           0 :   rn = bgp_node_get (bgp_nexthop_cache_table[AFI_IP6], &p);
     255             : 
     256           0 :   if (rn->info)
     257             :     {
     258           0 :       bnc = rn->info;
     259           0 :       bgp_unlock_node (rn);
     260             :     }
     261             :   else
     262             :     {
     263           0 :       if (NULL == (bnc = zlookup_query_ipv6 (&attr->extra->mp_nexthop_global)))
     264           0 :         bnc = bnc_new ();
     265             :       else
     266             :         {
     267           0 :           if (changed)
     268             :             {
     269             :               struct bgp_table *old;
     270             :               struct bgp_node *oldrn;
     271             : 
     272           0 :               if (bgp_nexthop_cache_table[AFI_IP6] == cache1_table[AFI_IP6])
     273           0 :                 old = cache2_table[AFI_IP6];
     274             :               else
     275           0 :                 old = cache1_table[AFI_IP6];
     276             : 
     277           0 :               oldrn = bgp_node_lookup (old, &p);
     278           0 :               if (oldrn)
     279             :                 {
     280           0 :                   struct bgp_nexthop_cache *oldbnc = oldrn->info;
     281             : 
     282           0 :                   bnc->changed = bgp_nexthop_cache_different (bnc, oldbnc);
     283             : 
     284           0 :                   if (bnc->metric != oldbnc->metric)
     285           0 :                     bnc->metricchanged = 1;
     286             : 
     287           0 :                   bgp_unlock_node (oldrn);
     288             :                 }
     289             :             }
     290             :         }
     291           0 :       rn->info = bnc;
     292             :     }
     293             : 
     294           0 :   if (changed)
     295           0 :     *changed = bnc->changed;
     296             : 
     297           0 :   if (metricchanged)
     298           0 :     *metricchanged = bnc->metricchanged;
     299             : 
     300           0 :   if (bnc->valid && bnc->metric)
     301           0 :     (bgp_info_extra_get (ri))->igpmetric = bnc->metric;
     302           0 :   else if (ri->extra)
     303           0 :     ri->extra->igpmetric = 0;
     304             : 
     305           0 :   return bnc->valid;
     306             : }
     307             : #endif /* HAVE_IPV6 */
     308             : 
     309             : /* Check specified next-hop is reachable or not. */
     310             : int
     311           0 : bgp_nexthop_lookup (afi_t afi, struct peer *peer, struct bgp_info *ri,
     312             :                     int *changed, int *metricchanged)
     313             : {
     314             :   struct bgp_node *rn;
     315             :   struct prefix p;
     316             :   struct bgp_nexthop_cache *bnc;
     317             :   struct in_addr addr;
     318             :   
     319             :   /* If lookup is not enabled, return valid. */
     320           0 :   if (zlookup->sock < 0)
     321             :     {
     322           0 :       if (ri->extra)
     323           0 :         ri->extra->igpmetric = 0;
     324           0 :       return 1;
     325             :     }
     326             :   
     327             : #ifdef HAVE_IPV6
     328           0 :   if (afi == AFI_IP6)
     329           0 :     return bgp_nexthop_lookup_ipv6 (peer, ri, changed, metricchanged);
     330             : #endif /* HAVE_IPV6 */
     331             : 
     332           0 :   addr = ri->attr->nexthop;
     333             : 
     334           0 :   memset (&p, 0, sizeof (struct prefix));
     335           0 :   p.family = AF_INET;
     336           0 :   p.prefixlen = IPV4_MAX_BITLEN;
     337           0 :   p.u.prefix4 = addr;
     338             : 
     339             :   /* IBGP or ebgp-multihop */
     340           0 :   rn = bgp_node_get (bgp_nexthop_cache_table[AFI_IP], &p);
     341             : 
     342           0 :   if (rn->info)
     343             :     {
     344           0 :       bnc = rn->info;
     345           0 :       bgp_unlock_node (rn);
     346             :     }
     347             :   else
     348             :     {
     349           0 :       if (NULL == (bnc = zlookup_query (addr)))
     350           0 :         bnc = bnc_new ();
     351             :       else
     352             :         {
     353           0 :           if (changed)
     354             :             {
     355             :               struct bgp_table *old;
     356             :               struct bgp_node *oldrn;
     357             : 
     358           0 :               if (bgp_nexthop_cache_table[AFI_IP] == cache1_table[AFI_IP])
     359           0 :                 old = cache2_table[AFI_IP];
     360             :               else
     361           0 :                 old = cache1_table[AFI_IP];
     362             : 
     363           0 :               oldrn = bgp_node_lookup (old, &p);
     364           0 :               if (oldrn)
     365             :                 {
     366           0 :                   struct bgp_nexthop_cache *oldbnc = oldrn->info;
     367             : 
     368           0 :                   bnc->changed = bgp_nexthop_cache_different (bnc, oldbnc);
     369             : 
     370           0 :                   if (bnc->metric != oldbnc->metric)
     371           0 :                     bnc->metricchanged = 1;
     372             : 
     373           0 :                   bgp_unlock_node (oldrn);
     374             :                 }
     375             :             }
     376             :         }
     377           0 :       rn->info = bnc;
     378             :     }
     379             : 
     380           0 :   if (changed)
     381           0 :     *changed = bnc->changed;
     382             : 
     383           0 :   if (metricchanged)
     384           0 :     *metricchanged = bnc->metricchanged;
     385             : 
     386           0 :   if (bnc->valid && bnc->metric)
     387           0 :     (bgp_info_extra_get(ri))->igpmetric = bnc->metric;
     388           0 :   else if (ri->extra)
     389           0 :     ri->extra->igpmetric = 0;
     390             : 
     391           0 :   return bnc->valid;
     392             : }
     393             : 
     394             : /* Reset and free all BGP nexthop cache. */
     395             : static void
     396           0 : bgp_nexthop_cache_reset (struct bgp_table *table)
     397             : {
     398             :   struct bgp_node *rn;
     399             :   struct bgp_nexthop_cache *bnc;
     400             : 
     401           0 :   for (rn = bgp_table_top (table); rn; rn = bgp_route_next (rn))
     402           0 :     if ((bnc = rn->info) != NULL)
     403             :       {
     404           0 :         bnc_free (bnc);
     405           0 :         rn->info = NULL;
     406           0 :         bgp_unlock_node (rn);
     407             :       }
     408           0 : }
     409             : 
     410             : static void
     411           0 : bgp_scan (afi_t afi, safi_t safi)
     412             : {
     413             :   struct bgp_node *rn;
     414             :   struct bgp *bgp;
     415             :   struct bgp_info *bi;
     416             :   struct bgp_info *next;
     417             :   struct peer *peer;
     418             :   struct listnode *node, *nnode;
     419             :   int valid;
     420             :   int current;
     421             :   int changed;
     422             :   int metricchanged;
     423             : 
     424             :   /* Change cache. */
     425           0 :   if (bgp_nexthop_cache_table[afi] == cache1_table[afi])
     426           0 :     bgp_nexthop_cache_table[afi] = cache2_table[afi];
     427             :   else
     428           0 :     bgp_nexthop_cache_table[afi] = cache1_table[afi];
     429             : 
     430             :   /* Get default bgp. */
     431           0 :   bgp = bgp_get_default ();
     432           0 :   if (bgp == NULL)
     433           0 :     return;
     434             : 
     435             :   /* Maximum prefix check */
     436           0 :   for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
     437             :     {
     438           0 :       if (peer->status != Established)
     439           0 :         continue;
     440             : 
     441           0 :       if (peer->afc[afi][SAFI_UNICAST])
     442           0 :         bgp_maximum_prefix_overflow (peer, afi, SAFI_UNICAST, 1);
     443           0 :       if (peer->afc[afi][SAFI_MULTICAST])
     444           0 :         bgp_maximum_prefix_overflow (peer, afi, SAFI_MULTICAST, 1);
     445           0 :       if (peer->afc[afi][SAFI_MPLS_VPN])
     446           0 :         bgp_maximum_prefix_overflow (peer, afi, SAFI_MPLS_VPN, 1);
     447             :     }
     448             : 
     449           0 :   for (rn = bgp_table_top (bgp->rib[afi][SAFI_UNICAST]); rn;
     450           0 :        rn = bgp_route_next (rn))
     451             :     {
     452           0 :       for (bi = rn->info; bi; bi = next)
     453             :         {
     454           0 :           next = bi->next;
     455             : 
     456           0 :           if (bi->type == ZEBRA_ROUTE_BGP && bi->sub_type == BGP_ROUTE_NORMAL)
     457             :             {
     458           0 :               changed = 0;
     459           0 :               metricchanged = 0;
     460             : 
     461           0 :               if (bi->peer->sort == BGP_PEER_EBGP && bi->peer->ttl == 1
     462           0 :                   && !CHECK_FLAG(bi->peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK))
     463           0 :                 valid = bgp_nexthop_onlink (afi, bi->attr);
     464             :               else
     465           0 :                 valid = bgp_nexthop_lookup (afi, bi->peer, bi,
     466             :                                             &changed, &metricchanged);
     467             : 
     468           0 :               current = CHECK_FLAG (bi->flags, BGP_INFO_VALID) ? 1 : 0;
     469             : 
     470           0 :               if (changed)
     471           0 :                 SET_FLAG (bi->flags, BGP_INFO_IGP_CHANGED);
     472             :               else
     473           0 :                 UNSET_FLAG (bi->flags, BGP_INFO_IGP_CHANGED);
     474             : 
     475           0 :               if (valid != current)
     476             :                 {
     477           0 :                   if (CHECK_FLAG (bi->flags, BGP_INFO_VALID))
     478             :                     {
     479           0 :                       bgp_aggregate_decrement (bgp, &rn->p, bi,
     480             :                                                afi, SAFI_UNICAST);
     481           0 :                       bgp_info_unset_flag (rn, bi, BGP_INFO_VALID);
     482             :                     }
     483             :                   else
     484             :                     {
     485           0 :                       bgp_info_set_flag (rn, bi, BGP_INFO_VALID);
     486           0 :                       bgp_aggregate_increment (bgp, &rn->p, bi,
     487             :                                                afi, SAFI_UNICAST);
     488             :                     }
     489             :                 }
     490             : 
     491           0 :               if (CHECK_FLAG (bgp->af_flags[afi][SAFI_UNICAST],
     492             :                   BGP_CONFIG_DAMPENING)
     493           0 :                   &&  bi->extra && bi->extra->damp_info )
     494           0 :                 if (bgp_damp_scan (bi, afi, SAFI_UNICAST))
     495           0 :                   bgp_aggregate_increment (bgp, &rn->p, bi,
     496             :                                            afi, SAFI_UNICAST);
     497             :             }
     498             :         }
     499           0 :       bgp_process (bgp, rn, afi, SAFI_UNICAST);
     500             :     }
     501             : 
     502             :   /* Flash old cache. */
     503           0 :   if (bgp_nexthop_cache_table[afi] == cache1_table[afi])
     504           0 :     bgp_nexthop_cache_reset (cache2_table[afi]);
     505             :   else
     506           0 :     bgp_nexthop_cache_reset (cache1_table[afi]);
     507             : 
     508           0 :   if (BGP_DEBUG (events, EVENTS))
     509             :     {
     510           0 :       if (afi == AFI_IP)
     511           0 :         zlog_debug ("scanning IPv4 Unicast routing tables");
     512           0 :       else if (afi == AFI_IP6)
     513           0 :         zlog_debug ("scanning IPv6 Unicast routing tables");
     514             :     }
     515             : 
     516             :   /* Reevaluate default-originate route-maps and announce/withdraw
     517             :    * default route if neccesary. */
     518           0 :   for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
     519             :     {
     520           0 :       if (peer->status == Established
     521           0 :           && CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE)
     522           0 :           && peer->default_rmap[afi][safi].name)
     523           0 :         bgp_default_originate (peer, afi, safi, 0);
     524             :     }
     525             : }
     526             : 
     527             : /* BGP scan thread.  This thread check nexthop reachability. */
     528             : static int
     529           0 : bgp_scan_timer (struct thread *t)
     530             : {
     531           0 :   bgp_scan_thread =
     532           0 :     thread_add_timer (master, bgp_scan_timer, NULL, bgp_scan_interval);
     533             : 
     534           0 :   if (BGP_DEBUG (events, EVENTS))
     535           0 :     zlog_debug ("Performing BGP general scanning");
     536             : 
     537           0 :   bgp_scan (AFI_IP, SAFI_UNICAST);
     538             : 
     539             : #ifdef HAVE_IPV6
     540           0 :   bgp_scan (AFI_IP6, SAFI_UNICAST);
     541             : #endif /* HAVE_IPV6 */
     542             : 
     543           0 :   return 0;
     544             : }
     545             : 
     546             : /* BGP own address structure */
     547             : struct bgp_addr
     548             : {
     549             :   struct in_addr addr;
     550             :   int refcnt;
     551             : };
     552             : 
     553             : static struct hash *bgp_address_hash;
     554             : 
     555             : static void *
     556           0 : bgp_address_hash_alloc (void *p)
     557             : {
     558           0 :   struct in_addr *val = p;
     559             :   struct bgp_addr *addr;
     560             : 
     561           0 :   addr = XMALLOC (MTYPE_BGP_ADDR, sizeof (struct bgp_addr));
     562           0 :   addr->refcnt = 0;
     563           0 :   addr->addr.s_addr = val->s_addr;
     564             : 
     565           0 :   return addr;
     566             : }
     567             : 
     568             : static unsigned int
     569           0 : bgp_address_hash_key_make (void *p)
     570             : {
     571           0 :   const struct bgp_addr *addr = p;
     572             : 
     573           0 :   return jhash_1word(addr->addr.s_addr, 0);
     574             : }
     575             : 
     576             : static int
     577           0 : bgp_address_hash_cmp (const void *p1, const void *p2)
     578             : {
     579           0 :   const struct bgp_addr *addr1 = p1;
     580           0 :   const struct bgp_addr *addr2 = p2;
     581             : 
     582           0 :   return addr1->addr.s_addr == addr2->addr.s_addr;
     583             : }
     584             : 
     585             : void
     586           0 : bgp_address_init (void)
     587             : {
     588           0 :   bgp_address_hash = hash_create (bgp_address_hash_key_make,
     589             :                                   bgp_address_hash_cmp);
     590           0 : }
     591             : 
     592             : static void
     593           0 : bgp_address_add (struct prefix *p)
     594             : {
     595             :   struct bgp_addr tmp;
     596             :   struct bgp_addr *addr;
     597             : 
     598           0 :   tmp.addr = p->u.prefix4;
     599             : 
     600           0 :   addr = hash_get (bgp_address_hash, &tmp, bgp_address_hash_alloc);
     601           0 :   addr->refcnt++;
     602           0 : }
     603             : 
     604             : static void
     605           0 : bgp_address_del (struct prefix *p)
     606             : {
     607             :   struct bgp_addr tmp;
     608             :   struct bgp_addr *addr;
     609             : 
     610           0 :   tmp.addr = p->u.prefix4;
     611             : 
     612           0 :   addr = hash_lookup (bgp_address_hash, &tmp);
     613             :   /* may have been deleted earlier by bgp_interface_down() */
     614           0 :   if (addr == NULL)
     615           0 :     return;
     616             : 
     617           0 :   addr->refcnt--;
     618             : 
     619           0 :   if (addr->refcnt == 0)
     620             :     {
     621           0 :       hash_release (bgp_address_hash, addr);
     622           0 :       XFREE (MTYPE_BGP_ADDR, addr);
     623             :     }
     624             : }
     625             : 
     626             : 
     627             : struct bgp_connected_ref
     628             : {
     629             :   unsigned int refcnt;
     630             : };
     631             : 
     632             : void
     633           0 : bgp_connected_add (struct connected *ifc)
     634             : {
     635             :   struct prefix p;
     636             :   struct prefix *addr;
     637             :   struct interface *ifp;
     638             :   struct bgp_node *rn;
     639             :   struct bgp_connected_ref *bc;
     640             : 
     641           0 :   ifp = ifc->ifp;
     642             : 
     643           0 :   if (! ifp)
     644           0 :     return;
     645             : 
     646           0 :   if (if_is_loopback (ifp))
     647           0 :     return;
     648             : 
     649           0 :   addr = ifc->address;
     650             : 
     651           0 :   if (addr->family == AF_INET)
     652             :     {
     653           0 :       PREFIX_COPY_IPV4(&p, CONNECTED_PREFIX(ifc));
     654           0 :       apply_mask_ipv4 ((struct prefix_ipv4 *) &p);
     655             : 
     656           0 :       if (prefix_ipv4_any ((struct prefix_ipv4 *) &p))
     657           0 :         return;
     658             : 
     659           0 :       bgp_address_add (addr);
     660             : 
     661           0 :       rn = bgp_node_get (bgp_connected_table[AFI_IP], (struct prefix *) &p);
     662           0 :       if (rn->info)
     663             :         {
     664           0 :           bc = rn->info;
     665           0 :           bc->refcnt++;
     666             :         }
     667             :       else
     668             :         {
     669           0 :           bc = XCALLOC (MTYPE_BGP_CONN, sizeof (struct bgp_connected_ref));
     670           0 :           bc->refcnt = 1;
     671           0 :           rn->info = bc;
     672             :         }
     673             :     }
     674             : #ifdef HAVE_IPV6
     675           0 :   else if (addr->family == AF_INET6)
     676             :     {
     677           0 :       PREFIX_COPY_IPV6(&p, CONNECTED_PREFIX(ifc));
     678           0 :       apply_mask_ipv6 ((struct prefix_ipv6 *) &p);
     679             : 
     680           0 :       if (IN6_IS_ADDR_UNSPECIFIED (&p.u.prefix6))
     681           0 :         return;
     682             : 
     683           0 :       if (IN6_IS_ADDR_LINKLOCAL (&p.u.prefix6))
     684           0 :         return;
     685             : 
     686           0 :       rn = bgp_node_get (bgp_connected_table[AFI_IP6], (struct prefix *) &p);
     687           0 :       if (rn->info)
     688             :         {
     689           0 :           bc = rn->info;
     690           0 :           bc->refcnt++;
     691             :         }
     692             :       else
     693             :         {
     694           0 :           bc = XCALLOC (MTYPE_BGP_CONN, sizeof (struct bgp_connected_ref));
     695           0 :           bc->refcnt = 1;
     696           0 :           rn->info = bc;
     697             :         }
     698             :     }
     699             : #endif /* HAVE_IPV6 */
     700             : }
     701             : 
     702             : void
     703           0 : bgp_connected_delete (struct connected *ifc)
     704             : {
     705             :   struct prefix p;
     706             :   struct prefix *addr;
     707             :   struct interface *ifp;
     708             :   struct bgp_node *rn;
     709             :   struct bgp_connected_ref *bc;
     710             : 
     711           0 :   ifp = ifc->ifp;
     712             : 
     713           0 :   if (if_is_loopback (ifp))
     714           0 :     return;
     715             : 
     716           0 :   addr = ifc->address;
     717             : 
     718           0 :   if (addr->family == AF_INET)
     719             :     {
     720           0 :       PREFIX_COPY_IPV4(&p, CONNECTED_PREFIX(ifc));
     721           0 :       apply_mask_ipv4 ((struct prefix_ipv4 *) &p);
     722             : 
     723           0 :       if (prefix_ipv4_any ((struct prefix_ipv4 *) &p))
     724           0 :         return;
     725             : 
     726           0 :       bgp_address_del (addr);
     727             : 
     728           0 :       rn = bgp_node_lookup (bgp_connected_table[AFI_IP], &p);
     729           0 :       if (! rn)
     730           0 :         return;
     731             : 
     732           0 :       bc = rn->info;
     733           0 :       bc->refcnt--;
     734           0 :       if (bc->refcnt == 0)
     735             :         {
     736           0 :           XFREE (MTYPE_BGP_CONN, bc);
     737           0 :           rn->info = NULL;
     738             :         }
     739           0 :       bgp_unlock_node (rn);
     740           0 :       bgp_unlock_node (rn);
     741             :     }
     742             : #ifdef HAVE_IPV6
     743           0 :   else if (addr->family == AF_INET6)
     744             :     {
     745           0 :       PREFIX_COPY_IPV6(&p, CONNECTED_PREFIX(ifc));
     746           0 :       apply_mask_ipv6 ((struct prefix_ipv6 *) &p);
     747             : 
     748           0 :       if (IN6_IS_ADDR_UNSPECIFIED (&p.u.prefix6))
     749           0 :         return;
     750             : 
     751           0 :       if (IN6_IS_ADDR_LINKLOCAL (&p.u.prefix6))
     752           0 :         return;
     753             : 
     754           0 :       rn = bgp_node_lookup (bgp_connected_table[AFI_IP6], (struct prefix *) &p);
     755           0 :       if (! rn)
     756           0 :         return;
     757             : 
     758           0 :       bc = rn->info;
     759           0 :       bc->refcnt--;
     760           0 :       if (bc->refcnt == 0)
     761             :         {
     762           0 :           XFREE (MTYPE_BGP_CONN, bc);
     763           0 :           rn->info = NULL;
     764             :         }
     765           0 :       bgp_unlock_node (rn);
     766           0 :       bgp_unlock_node (rn);
     767             :     }
     768             : #endif /* HAVE_IPV6 */
     769             : }
     770             : 
     771             : int
     772           0 : bgp_nexthop_self (struct attr *attr)
     773             : {
     774             :   struct bgp_addr tmp, *addr;
     775             : 
     776           0 :   tmp.addr = attr->nexthop;
     777             : 
     778           0 :   addr = hash_lookup (bgp_address_hash, &tmp);
     779           0 :   if (addr)
     780           0 :     return 1;
     781             : 
     782           0 :   return 0;
     783             : }
     784             : 
     785             : static struct bgp_nexthop_cache *
     786           0 : zlookup_read (void)
     787             : {
     788             :   struct stream *s;
     789             :   uint16_t length;
     790             :   u_char marker;
     791             :   u_char version;
     792             :   uint16_t command;
     793             :   int nbytes;
     794             :   struct in_addr raddr;
     795             :   uint32_t metric;
     796             :   int i;
     797             :   u_char nexthop_num;
     798             :   struct nexthop *nexthop;
     799             :   struct bgp_nexthop_cache *bnc;
     800             : 
     801           0 :   s = zlookup->ibuf;
     802           0 :   stream_reset (s);
     803             : 
     804           0 :   nbytes = stream_read (s, zlookup->sock, 2);
     805           0 :   length = stream_getw (s);
     806             : 
     807           0 :   nbytes = stream_read (s, zlookup->sock, length - 2);
     808           0 :   marker = stream_getc (s);
     809           0 :   version = stream_getc (s);
     810             :   
     811           0 :   if (version != ZSERV_VERSION || marker != ZEBRA_HEADER_MARKER)
     812             :     {
     813           0 :       zlog_err("%s: socket %d version mismatch, marker %d, version %d",
     814           0 :                __func__, zlookup->sock, marker, version);
     815           0 :       return NULL;
     816             :     }
     817             :     
     818           0 :   command = stream_getw (s);
     819             :   
     820           0 :   raddr.s_addr = stream_get_ipv4 (s);
     821           0 :   metric = stream_getl (s);
     822           0 :   nexthop_num = stream_getc (s);
     823             : 
     824           0 :   if (nexthop_num)
     825             :     {
     826           0 :       bnc = bnc_new ();
     827           0 :       bnc->valid = 1;
     828           0 :       bnc->metric = metric;
     829           0 :       bnc->nexthop_num = nexthop_num;
     830             : 
     831           0 :       for (i = 0; i < nexthop_num; i++)
     832             :         {
     833           0 :           nexthop = XCALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop));
     834           0 :           nexthop->type = stream_getc (s);
     835           0 :           switch (nexthop->type)
     836             :             {
     837             :             case ZEBRA_NEXTHOP_IPV4:
     838           0 :               nexthop->gate.ipv4.s_addr = stream_get_ipv4 (s);
     839           0 :               break;
     840             :             case ZEBRA_NEXTHOP_IPV4_IFINDEX:
     841           0 :               nexthop->gate.ipv4.s_addr = stream_get_ipv4 (s);
     842           0 :               nexthop->ifindex = stream_getl (s);
     843           0 :               break;
     844             :             case ZEBRA_NEXTHOP_IFINDEX:
     845             :             case ZEBRA_NEXTHOP_IFNAME:
     846           0 :               nexthop->ifindex = stream_getl (s);
     847           0 :               break;
     848             :             default:
     849             :               /* do nothing */
     850           0 :               break;
     851             :             }
     852           0 :           bnc_nexthop_add (bnc, nexthop);
     853             :         }
     854             :     }
     855             :   else
     856           0 :     return NULL;
     857             : 
     858           0 :   return bnc;
     859             : }
     860             : 
     861             : struct bgp_nexthop_cache *
     862           0 : zlookup_query (struct in_addr addr)
     863             : {
     864             :   int ret;
     865             :   struct stream *s;
     866             : 
     867             :   /* Check socket. */
     868           0 :   if (zlookup->sock < 0)
     869           0 :     return NULL;
     870             : 
     871           0 :   s = zlookup->obuf;
     872           0 :   stream_reset (s);
     873           0 :   zclient_create_header (s, ZEBRA_IPV4_NEXTHOP_LOOKUP);
     874           0 :   stream_put_in_addr (s, &addr);
     875             :   
     876           0 :   stream_putw_at (s, 0, stream_get_endp (s));
     877             :   
     878           0 :   ret = writen (zlookup->sock, s->data, stream_get_endp (s));
     879           0 :   if (ret < 0)
     880             :     {
     881           0 :       zlog_err ("can't write to zlookup->sock");
     882           0 :       close (zlookup->sock);
     883           0 :       zlookup->sock = -1;
     884           0 :       return NULL;
     885             :     }
     886           0 :   if (ret == 0)
     887             :     {
     888           0 :       zlog_err ("zlookup->sock connection closed");
     889           0 :       close (zlookup->sock);
     890           0 :       zlookup->sock = -1;
     891           0 :       return NULL;
     892             :     }
     893             : 
     894           0 :   return zlookup_read ();
     895             : }
     896             : 
     897             : #ifdef HAVE_IPV6
     898             : static struct bgp_nexthop_cache *
     899           0 : zlookup_read_ipv6 (void)
     900             : {
     901             :   struct stream *s;
     902             :   uint16_t length;
     903             :   u_char version, marker;
     904             :   uint16_t  command;
     905             :   int nbytes;
     906             :   struct in6_addr raddr;
     907             :   uint32_t metric;
     908             :   int i;
     909             :   u_char nexthop_num;
     910             :   struct nexthop *nexthop;
     911             :   struct bgp_nexthop_cache *bnc;
     912             : 
     913           0 :   s = zlookup->ibuf;
     914           0 :   stream_reset (s);
     915             : 
     916           0 :   nbytes = stream_read (s, zlookup->sock, 2);
     917           0 :   length = stream_getw (s);
     918             : 
     919           0 :   nbytes = stream_read (s, zlookup->sock, length - 2);
     920           0 :   marker = stream_getc (s);
     921           0 :   version = stream_getc (s);
     922             :   
     923           0 :   if (version != ZSERV_VERSION || marker != ZEBRA_HEADER_MARKER)
     924             :     {
     925           0 :       zlog_err("%s: socket %d version mismatch, marker %d, version %d",
     926           0 :                __func__, zlookup->sock, marker, version);
     927           0 :       return NULL;
     928             :     }
     929             :     
     930           0 :   command = stream_getw (s);
     931             :   
     932           0 :   stream_get (&raddr, s, 16);
     933             : 
     934           0 :   metric = stream_getl (s);
     935           0 :   nexthop_num = stream_getc (s);
     936             : 
     937           0 :   if (nexthop_num)
     938             :     {
     939           0 :       bnc = bnc_new ();
     940           0 :       bnc->valid = 1;
     941           0 :       bnc->metric = metric;
     942           0 :       bnc->nexthop_num = nexthop_num;
     943             : 
     944           0 :       for (i = 0; i < nexthop_num; i++)
     945             :         {
     946           0 :           nexthop = XCALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop));
     947           0 :           nexthop->type = stream_getc (s);
     948           0 :           switch (nexthop->type)
     949             :             {
     950             :             case ZEBRA_NEXTHOP_IPV6:
     951           0 :               stream_get (&nexthop->gate.ipv6, s, 16);
     952           0 :               break;
     953             :             case ZEBRA_NEXTHOP_IPV6_IFINDEX:
     954             :             case ZEBRA_NEXTHOP_IPV6_IFNAME:
     955           0 :               stream_get (&nexthop->gate.ipv6, s, 16);
     956           0 :               nexthop->ifindex = stream_getl (s);
     957           0 :               break;
     958             :             case ZEBRA_NEXTHOP_IFINDEX:
     959             :             case ZEBRA_NEXTHOP_IFNAME:
     960           0 :               nexthop->ifindex = stream_getl (s);
     961           0 :               break;
     962             :             default:
     963             :               /* do nothing */
     964           0 :               break;
     965             :             }
     966           0 :           bnc_nexthop_add (bnc, nexthop);
     967             :         }
     968             :     }
     969             :   else
     970           0 :     return NULL;
     971             : 
     972           0 :   return bnc;
     973             : }
     974             : 
     975             : struct bgp_nexthop_cache *
     976           0 : zlookup_query_ipv6 (struct in6_addr *addr)
     977             : {
     978             :   int ret;
     979             :   struct stream *s;
     980             : 
     981             :   /* Check socket. */
     982           0 :   if (zlookup->sock < 0)
     983           0 :     return NULL;
     984             : 
     985           0 :   s = zlookup->obuf;
     986           0 :   stream_reset (s);
     987           0 :   zclient_create_header (s, ZEBRA_IPV6_NEXTHOP_LOOKUP);
     988           0 :   stream_put (s, addr, 16);
     989           0 :   stream_putw_at (s, 0, stream_get_endp (s));
     990             :   
     991           0 :   ret = writen (zlookup->sock, s->data, stream_get_endp (s));
     992           0 :   if (ret < 0)
     993             :     {
     994           0 :       zlog_err ("can't write to zlookup->sock");
     995           0 :       close (zlookup->sock);
     996           0 :       zlookup->sock = -1;
     997           0 :       return NULL;
     998             :     }
     999           0 :   if (ret == 0)
    1000             :     {
    1001           0 :       zlog_err ("zlookup->sock connection closed");
    1002           0 :       close (zlookup->sock);
    1003           0 :       zlookup->sock = -1;
    1004           0 :       return NULL;
    1005             :     }
    1006             : 
    1007           0 :   return zlookup_read_ipv6 ();
    1008             : }
    1009             : #endif /* HAVE_IPV6 */
    1010             : 
    1011             : static int
    1012           0 : bgp_import_check (struct prefix *p, u_int32_t *igpmetric,
    1013             :                   struct in_addr *igpnexthop)
    1014             : {
    1015             :   struct stream *s;
    1016             :   int ret;
    1017             :   u_int16_t length, command;
    1018             :   u_char version, marker;
    1019             :   int nbytes;
    1020             :   struct in_addr addr;
    1021             :   struct in_addr nexthop;
    1022           0 :   u_int32_t metric = 0;
    1023             :   u_char nexthop_num;
    1024             :   u_char nexthop_type;
    1025             : 
    1026             :   /* If lookup connection is not available return valid. */
    1027           0 :   if (zlookup->sock < 0)
    1028             :     {
    1029           0 :       if (igpmetric)
    1030           0 :         *igpmetric = 0;
    1031           0 :       return 1;
    1032             :     }
    1033             : 
    1034             :   /* Send query to the lookup connection */
    1035           0 :   s = zlookup->obuf;
    1036           0 :   stream_reset (s);
    1037           0 :   zclient_create_header (s, ZEBRA_IPV4_IMPORT_LOOKUP);
    1038             :   
    1039           0 :   stream_putc (s, p->prefixlen);
    1040           0 :   stream_put_in_addr (s, &p->u.prefix4);
    1041             :   
    1042           0 :   stream_putw_at (s, 0, stream_get_endp (s));
    1043             :   
    1044             :   /* Write the packet. */
    1045           0 :   ret = writen (zlookup->sock, s->data, stream_get_endp (s));
    1046             : 
    1047           0 :   if (ret < 0)
    1048             :     {
    1049           0 :       zlog_err ("can't write to zlookup->sock");
    1050           0 :       close (zlookup->sock);
    1051           0 :       zlookup->sock = -1;
    1052           0 :       return 1;
    1053             :     }
    1054           0 :   if (ret == 0)
    1055             :     {
    1056           0 :       zlog_err ("zlookup->sock connection closed");
    1057           0 :       close (zlookup->sock);
    1058           0 :       zlookup->sock = -1;
    1059           0 :       return 1;
    1060             :     }
    1061             : 
    1062             :   /* Get result. */
    1063           0 :   stream_reset (s);
    1064             : 
    1065             :   /* Fetch length. */
    1066           0 :   nbytes = stream_read (s, zlookup->sock, 2);
    1067           0 :   length = stream_getw (s);
    1068             : 
    1069             :   /* Fetch whole data. */
    1070           0 :   nbytes = stream_read (s, zlookup->sock, length - 2);
    1071           0 :   marker = stream_getc (s);
    1072           0 :   version = stream_getc (s);
    1073             : 
    1074           0 :   if (version != ZSERV_VERSION || marker != ZEBRA_HEADER_MARKER)
    1075             :     {
    1076           0 :       zlog_err("%s: socket %d version mismatch, marker %d, version %d",
    1077           0 :                __func__, zlookup->sock, marker, version);
    1078           0 :       return 0;
    1079             :     }
    1080             :     
    1081           0 :   command = stream_getw (s);
    1082             :   
    1083           0 :   addr.s_addr = stream_get_ipv4 (s);
    1084           0 :   metric = stream_getl (s);
    1085           0 :   nexthop_num = stream_getc (s);
    1086             : 
    1087             :   /* Set IGP metric value. */
    1088           0 :   if (igpmetric)
    1089           0 :     *igpmetric = metric;
    1090             : 
    1091             :   /* If there is nexthop then this is active route. */
    1092           0 :   if (nexthop_num)
    1093             :     {
    1094           0 :       nexthop.s_addr = 0;
    1095           0 :       nexthop_type = stream_getc (s);
    1096           0 :       switch (nexthop_type)
    1097             :         {
    1098             :         case ZEBRA_NEXTHOP_IPV4:
    1099           0 :           nexthop.s_addr = stream_get_ipv4 (s);
    1100           0 :           break;
    1101             :         case ZEBRA_NEXTHOP_IPV4_IFINDEX:
    1102           0 :           nexthop.s_addr = stream_get_ipv4 (s);
    1103           0 :           /* ifindex */ (void)stream_getl (s);
    1104           0 :           break;
    1105             :         default:
    1106             :           /* do nothing */
    1107           0 :           break;
    1108             :         }
    1109           0 :       *igpnexthop = nexthop;
    1110             : 
    1111           0 :       return 1;
    1112             :     }
    1113             :   else
    1114           0 :     return 0;
    1115             : }
    1116             : 
    1117             : /* Scan all configured BGP route then check the route exists in IGP or
    1118             :    not. */
    1119             : static int
    1120           0 : bgp_import (struct thread *t)
    1121             : {
    1122             :   struct bgp *bgp;
    1123             :   struct bgp_node *rn;
    1124             :   struct bgp_static *bgp_static;
    1125             :   struct listnode *node, *nnode;
    1126             :   int valid;
    1127             :   u_int32_t metric;
    1128             :   struct in_addr nexthop;
    1129             :   afi_t afi;
    1130             :   safi_t safi;
    1131             : 
    1132           0 :   bgp_import_thread = 
    1133           0 :     thread_add_timer (master, bgp_import, NULL, bgp_import_interval);
    1134             : 
    1135           0 :   if (BGP_DEBUG (events, EVENTS))
    1136           0 :     zlog_debug ("Import timer expired.");
    1137             : 
    1138           0 :   for (ALL_LIST_ELEMENTS (bm->bgp, node, nnode, bgp))
    1139             :     {
    1140           0 :       for (afi = AFI_IP; afi < AFI_MAX; afi++)
    1141           0 :         for (safi = SAFI_UNICAST; safi < SAFI_MPLS_VPN; safi++)
    1142           0 :           for (rn = bgp_table_top (bgp->route[afi][safi]); rn;
    1143           0 :                rn = bgp_route_next (rn))
    1144           0 :             if ((bgp_static = rn->info) != NULL)
    1145             :               {
    1146           0 :                 if (bgp_static->backdoor)
    1147           0 :                   continue;
    1148             : 
    1149           0 :                 valid = bgp_static->valid;
    1150           0 :                 metric = bgp_static->igpmetric;
    1151           0 :                 nexthop = bgp_static->igpnexthop;
    1152             : 
    1153           0 :                 if (bgp_flag_check (bgp, BGP_FLAG_IMPORT_CHECK)
    1154           0 :                     && afi == AFI_IP && safi == SAFI_UNICAST)
    1155           0 :                   bgp_static->valid = bgp_import_check (&rn->p, &bgp_static->igpmetric,
    1156             :                                                         &bgp_static->igpnexthop);
    1157             :                 else
    1158             :                   {
    1159           0 :                     bgp_static->valid = 1;
    1160           0 :                     bgp_static->igpmetric = 0;
    1161           0 :                     bgp_static->igpnexthop.s_addr = 0;
    1162             :                   }
    1163             : 
    1164           0 :                 if (bgp_static->valid != valid)
    1165             :                   {
    1166           0 :                     if (bgp_static->valid)
    1167           0 :                       bgp_static_update (bgp, &rn->p, bgp_static, afi, safi);
    1168             :                     else
    1169           0 :                       bgp_static_withdraw (bgp, &rn->p, afi, safi);
    1170             :                   }
    1171           0 :                 else if (bgp_static->valid)
    1172             :                   {
    1173           0 :                     if (bgp_static->igpmetric != metric
    1174           0 :                         || bgp_static->igpnexthop.s_addr != nexthop.s_addr
    1175           0 :                         || bgp_static->rmap.name)
    1176           0 :                       bgp_static_update (bgp, &rn->p, bgp_static, afi, safi);
    1177             :                   }
    1178             :               }
    1179             :     }
    1180           0 :   return 0;
    1181             : }
    1182             : 
    1183             : /* Connect to zebra for nexthop lookup. */
    1184             : static int
    1185           0 : zlookup_connect (struct thread *t)
    1186             : {
    1187             :   struct zclient *zlookup;
    1188             : 
    1189           0 :   zlookup = THREAD_ARG (t);
    1190           0 :   zlookup->t_connect = NULL;
    1191             : 
    1192           0 :   if (zlookup->sock != -1)
    1193           0 :     return 0;
    1194             : 
    1195           0 :   if (zclient_socket_connect (zlookup) < 0)
    1196           0 :     return -1;
    1197             : 
    1198           0 :   return 0;
    1199             : }
    1200             : 
    1201             : /* Check specified multiaccess next-hop. */
    1202             : int
    1203           0 : bgp_multiaccess_check_v4 (struct in_addr nexthop, char *peer)
    1204             : {
    1205             :   struct bgp_node *rn1;
    1206             :   struct bgp_node *rn2;
    1207             :   struct prefix p1;
    1208             :   struct prefix p2;
    1209             :   struct in_addr addr;
    1210             :   int ret;
    1211             : 
    1212           0 :   ret = inet_aton (peer, &addr);
    1213           0 :   if (! ret)
    1214           0 :     return 0;
    1215             : 
    1216           0 :   memset (&p1, 0, sizeof (struct prefix));
    1217           0 :   p1.family = AF_INET;
    1218           0 :   p1.prefixlen = IPV4_MAX_BITLEN;
    1219           0 :   p1.u.prefix4 = nexthop;
    1220           0 :   memset (&p2, 0, sizeof (struct prefix));
    1221           0 :   p2.family = AF_INET;
    1222           0 :   p2.prefixlen = IPV4_MAX_BITLEN;
    1223           0 :   p2.u.prefix4 = addr;
    1224             : 
    1225             :   /* If bgp scan is not enabled, return invalid. */
    1226           0 :   if (zlookup->sock < 0)
    1227           0 :     return 0;
    1228             : 
    1229           0 :   rn1 = bgp_node_match (bgp_connected_table[AFI_IP], &p1);
    1230           0 :   if (! rn1)
    1231           0 :     return 0;
    1232           0 :   bgp_unlock_node (rn1);
    1233             :   
    1234           0 :   rn2 = bgp_node_match (bgp_connected_table[AFI_IP], &p2);
    1235           0 :   if (! rn2)
    1236           0 :     return 0;
    1237           0 :   bgp_unlock_node (rn2);
    1238             : 
    1239             :   /* This is safe, even with above unlocks, since we are just
    1240             :      comparing pointers to the objects, not the objects themselves. */
    1241           0 :   if (rn1 == rn2)
    1242           0 :     return 1;
    1243             : 
    1244           0 :   return 0;
    1245             : }
    1246             : 
    1247           0 : DEFUN (bgp_scan_time,
    1248             :        bgp_scan_time_cmd,
    1249             :        "bgp scan-time <5-60>",
    1250             :        "BGP specific commands\n"
    1251             :        "Configure background scanner interval\n"
    1252             :        "Scanner interval (seconds)\n")
    1253             : {
    1254           0 :   bgp_scan_interval = atoi (argv[0]);
    1255             : 
    1256           0 :   if (bgp_scan_thread)
    1257             :     {
    1258           0 :       thread_cancel (bgp_scan_thread);
    1259           0 :       bgp_scan_thread = 
    1260           0 :         thread_add_timer (master, bgp_scan_timer, NULL, bgp_scan_interval);
    1261             :     }
    1262             : 
    1263           0 :   return CMD_SUCCESS;
    1264             : }
    1265             : 
    1266           0 : DEFUN (no_bgp_scan_time,
    1267             :        no_bgp_scan_time_cmd,
    1268             :        "no bgp scan-time",
    1269             :        NO_STR
    1270             :        "BGP specific commands\n"
    1271             :        "Configure background scanner interval\n")
    1272             : {
    1273           0 :   bgp_scan_interval = BGP_SCAN_INTERVAL_DEFAULT;
    1274             : 
    1275           0 :   if (bgp_scan_thread)
    1276             :     {
    1277           0 :       thread_cancel (bgp_scan_thread);
    1278           0 :       bgp_scan_thread = 
    1279           0 :         thread_add_timer (master, bgp_scan_timer, NULL, bgp_scan_interval);
    1280             :     }
    1281             : 
    1282           0 :   return CMD_SUCCESS;
    1283             : }
    1284             : 
    1285             : ALIAS (no_bgp_scan_time,
    1286             :        no_bgp_scan_time_val_cmd,
    1287             :        "no bgp scan-time <5-60>",
    1288             :        NO_STR
    1289             :        "BGP specific commands\n"
    1290             :        "Configure background scanner interval\n"
    1291             :        "Scanner interval (seconds)\n")
    1292             : 
    1293             : static int
    1294           0 : show_ip_bgp_scan_tables (struct vty *vty, const char detail)
    1295             : {
    1296             :   struct bgp_node *rn;
    1297             :   struct bgp_nexthop_cache *bnc;
    1298             :   char buf[INET6_ADDRSTRLEN];
    1299             :   u_char i;
    1300             : 
    1301           0 :   if (bgp_scan_thread)
    1302           0 :     vty_out (vty, "BGP scan is running%s", VTY_NEWLINE);
    1303             :   else
    1304           0 :     vty_out (vty, "BGP scan is not running%s", VTY_NEWLINE);
    1305           0 :   vty_out (vty, "BGP scan interval is %d%s", bgp_scan_interval, VTY_NEWLINE);
    1306             : 
    1307           0 :   vty_out (vty, "Current BGP nexthop cache:%s", VTY_NEWLINE);
    1308           0 :   for (rn = bgp_table_top (bgp_nexthop_cache_table[AFI_IP]); rn; rn = bgp_route_next (rn))
    1309           0 :     if ((bnc = rn->info) != NULL)
    1310             :       {
    1311           0 :         if (bnc->valid)
    1312             :         {
    1313           0 :           vty_out (vty, " %s valid [IGP metric %d]%s",
    1314           0 :                    inet_ntop (AF_INET, &rn->p.u.prefix4, buf, INET6_ADDRSTRLEN), bnc->metric, VTY_NEWLINE);
    1315           0 :           if (detail)
    1316           0 :             for (i = 0; i < bnc->nexthop_num; i++)
    1317           0 :               switch (bnc->nexthop[i].type)
    1318             :               {
    1319             :               case NEXTHOP_TYPE_IPV4:
    1320           0 :                 vty_out (vty, "  gate %s%s", inet_ntop (AF_INET, &bnc->nexthop[i].gate.ipv4, buf, INET6_ADDRSTRLEN), VTY_NEWLINE);
    1321           0 :                 break;
    1322             :               case NEXTHOP_TYPE_IPV4_IFINDEX:
    1323           0 :                 vty_out (vty, "  gate %s", inet_ntop (AF_INET, &bnc->nexthop[i].gate.ipv4, buf, INET6_ADDRSTRLEN));
    1324           0 :                 vty_out (vty, " ifidx %u%s", bnc->nexthop[i].ifindex, VTY_NEWLINE);
    1325           0 :                 break;
    1326             :               case NEXTHOP_TYPE_IFINDEX:
    1327           0 :                 vty_out (vty, "  ifidx %u%s", bnc->nexthop[i].ifindex, VTY_NEWLINE);
    1328           0 :                 break;
    1329             :               default:
    1330           0 :                 vty_out (vty, "  invalid nexthop type %u%s", bnc->nexthop[i].type, VTY_NEWLINE);
    1331             :               }
    1332             :         }
    1333             :         else
    1334           0 :           vty_out (vty, " %s invalid%s",
    1335           0 :                    inet_ntop (AF_INET, &rn->p.u.prefix4, buf, INET6_ADDRSTRLEN), VTY_NEWLINE);
    1336             :       }
    1337             : 
    1338             : #ifdef HAVE_IPV6
    1339             :   {
    1340           0 :     for (rn = bgp_table_top (bgp_nexthop_cache_table[AFI_IP6]); 
    1341             :          rn; 
    1342           0 :          rn = bgp_route_next (rn))
    1343           0 :       if ((bnc = rn->info) != NULL)
    1344             :         {
    1345           0 :           if (bnc->valid)
    1346             :           {
    1347           0 :             vty_out (vty, " %s valid [IGP metric %d]%s",
    1348           0 :                      inet_ntop (AF_INET6, &rn->p.u.prefix6, buf, INET6_ADDRSTRLEN),
    1349           0 :                      bnc->metric, VTY_NEWLINE);
    1350           0 :             if (detail)
    1351           0 :               for (i = 0; i < bnc->nexthop_num; i++)
    1352           0 :                 switch (bnc->nexthop[i].type)
    1353             :                 {
    1354             :                 case NEXTHOP_TYPE_IPV6:
    1355           0 :                   vty_out (vty, "  gate %s%s", inet_ntop (AF_INET6, &bnc->nexthop[i].gate.ipv6, buf, INET6_ADDRSTRLEN), VTY_NEWLINE);
    1356           0 :                   break;
    1357             :                 case NEXTHOP_TYPE_IFINDEX:
    1358           0 :                   vty_out (vty, "  ifidx %u%s", bnc->nexthop[i].ifindex, VTY_NEWLINE);
    1359           0 :                   break;
    1360             :                 default:
    1361           0 :                   vty_out (vty, "  invalid nexthop type %u%s", bnc->nexthop[i].type, VTY_NEWLINE);
    1362             :                 }
    1363             :           }
    1364             :           else
    1365           0 :             vty_out (vty, " %s invalid%s",
    1366           0 :                      inet_ntop (AF_INET6, &rn->p.u.prefix6, buf, INET6_ADDRSTRLEN),
    1367           0 :                      VTY_NEWLINE);
    1368             :         }
    1369             :   }
    1370             : #endif /* HAVE_IPV6 */
    1371             : 
    1372           0 :   vty_out (vty, "BGP connected route:%s", VTY_NEWLINE);
    1373           0 :   for (rn = bgp_table_top (bgp_connected_table[AFI_IP]); 
    1374             :        rn; 
    1375           0 :        rn = bgp_route_next (rn))
    1376           0 :     if (rn->info != NULL)
    1377           0 :       vty_out (vty, " %s/%d%s", inet_ntoa (rn->p.u.prefix4), rn->p.prefixlen,
    1378           0 :                VTY_NEWLINE);
    1379             : 
    1380             : #ifdef HAVE_IPV6
    1381             :   {
    1382           0 :     for (rn = bgp_table_top (bgp_connected_table[AFI_IP6]); 
    1383             :          rn; 
    1384           0 :          rn = bgp_route_next (rn))
    1385           0 :       if (rn->info != NULL)
    1386           0 :         vty_out (vty, " %s/%d%s",
    1387           0 :                  inet_ntop (AF_INET6, &rn->p.u.prefix6, buf, INET6_ADDRSTRLEN),
    1388           0 :                  rn->p.prefixlen,
    1389           0 :                  VTY_NEWLINE);
    1390             :   }
    1391             : #endif /* HAVE_IPV6 */
    1392             : 
    1393           0 :   return CMD_SUCCESS;
    1394             : }
    1395             : 
    1396           0 : DEFUN (show_ip_bgp_scan,
    1397             :        show_ip_bgp_scan_cmd,
    1398             :        "show ip bgp scan",
    1399             :        SHOW_STR
    1400             :        IP_STR
    1401             :        BGP_STR
    1402             :        "BGP scan status\n")
    1403             : {
    1404           0 :   return show_ip_bgp_scan_tables (vty, 0);
    1405             : }
    1406             : 
    1407           0 : DEFUN (show_ip_bgp_scan_detail,
    1408             :        show_ip_bgp_scan_detail_cmd,
    1409             :        "show ip bgp scan detail",
    1410             :        SHOW_STR
    1411             :        IP_STR
    1412             :        BGP_STR
    1413             :        "BGP scan status\n"
    1414             :        "More detailed output\n")
    1415             : {
    1416           0 :   return show_ip_bgp_scan_tables (vty, 1);
    1417             : }
    1418             : 
    1419             : int
    1420           0 : bgp_config_write_scan_time (struct vty *vty)
    1421             : {
    1422           0 :   if (bgp_scan_interval != BGP_SCAN_INTERVAL_DEFAULT)
    1423           0 :     vty_out (vty, " bgp scan-time %d%s", bgp_scan_interval, VTY_NEWLINE);
    1424           0 :   return CMD_SUCCESS;
    1425             : }
    1426             : 
    1427             : void
    1428           0 : bgp_scan_init (void)
    1429             : {
    1430           0 :   zlookup = zclient_new ();
    1431           0 :   zlookup->sock = -1;
    1432           0 :   zlookup->t_connect = thread_add_event (master, zlookup_connect, zlookup, 0);
    1433             : 
    1434           0 :   bgp_scan_interval = BGP_SCAN_INTERVAL_DEFAULT;
    1435           0 :   bgp_import_interval = BGP_IMPORT_INTERVAL_DEFAULT;
    1436             : 
    1437           0 :   cache1_table[AFI_IP] = bgp_table_init (AFI_IP, SAFI_UNICAST);
    1438           0 :   cache2_table[AFI_IP] = bgp_table_init (AFI_IP, SAFI_UNICAST);
    1439           0 :   bgp_nexthop_cache_table[AFI_IP] = cache1_table[AFI_IP];
    1440             : 
    1441           0 :   bgp_connected_table[AFI_IP] = bgp_table_init (AFI_IP, SAFI_UNICAST);
    1442             : 
    1443             : #ifdef HAVE_IPV6
    1444           0 :   cache1_table[AFI_IP6] = bgp_table_init (AFI_IP6, SAFI_UNICAST);
    1445           0 :   cache2_table[AFI_IP6] = bgp_table_init (AFI_IP6, SAFI_UNICAST);
    1446           0 :   bgp_nexthop_cache_table[AFI_IP6] = cache1_table[AFI_IP6];
    1447           0 :   bgp_connected_table[AFI_IP6] = bgp_table_init (AFI_IP6, SAFI_UNICAST);
    1448             : #endif /* HAVE_IPV6 */
    1449             : 
    1450             :   /* Make BGP scan thread. */
    1451           0 :   bgp_scan_thread = thread_add_timer (master, bgp_scan_timer, 
    1452             :                                       NULL, bgp_scan_interval);
    1453             :   /* Make BGP import there. */
    1454           0 :   bgp_import_thread = thread_add_timer (master, bgp_import, NULL, 0);
    1455             : 
    1456           0 :   install_element (BGP_NODE, &bgp_scan_time_cmd);
    1457           0 :   install_element (BGP_NODE, &no_bgp_scan_time_cmd);
    1458           0 :   install_element (BGP_NODE, &no_bgp_scan_time_val_cmd);
    1459           0 :   install_element (VIEW_NODE, &show_ip_bgp_scan_cmd);
    1460           0 :   install_element (VIEW_NODE, &show_ip_bgp_scan_detail_cmd);
    1461           0 :   install_element (RESTRICTED_NODE, &show_ip_bgp_scan_cmd);
    1462           0 :   install_element (ENABLE_NODE, &show_ip_bgp_scan_cmd);
    1463           0 :   install_element (ENABLE_NODE, &show_ip_bgp_scan_detail_cmd);
    1464           0 : }
    1465             : 
    1466             : void
    1467           0 : bgp_scan_finish (void)
    1468             : {
    1469             :   /* Only the current one needs to be reset. */
    1470           0 :   bgp_nexthop_cache_reset (bgp_nexthop_cache_table[AFI_IP]);
    1471             : 
    1472           0 :   bgp_table_unlock (cache1_table[AFI_IP]);
    1473           0 :   cache1_table[AFI_IP] = NULL;
    1474             : 
    1475           0 :   bgp_table_unlock (cache2_table[AFI_IP]);
    1476           0 :   cache2_table[AFI_IP] = NULL;
    1477             : 
    1478           0 :   bgp_table_unlock (bgp_connected_table[AFI_IP]);
    1479           0 :   bgp_connected_table[AFI_IP] = NULL;
    1480             : 
    1481             : #ifdef HAVE_IPV6
    1482             :   /* Only the current one needs to be reset. */
    1483           0 :   bgp_nexthop_cache_reset (bgp_nexthop_cache_table[AFI_IP6]);
    1484             : 
    1485           0 :   bgp_table_unlock (cache1_table[AFI_IP6]);
    1486           0 :   cache1_table[AFI_IP6] = NULL;
    1487             : 
    1488           0 :   bgp_table_unlock (cache2_table[AFI_IP6]);
    1489           0 :   cache2_table[AFI_IP6] = NULL;
    1490             : 
    1491           0 :   bgp_table_unlock (bgp_connected_table[AFI_IP6]);
    1492           0 :   bgp_connected_table[AFI_IP6] = NULL;
    1493             : #endif /* HAVE_IPV6 */
    1494           0 : }

Generated by: LCOV version 1.10