File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / quagga / bgpd / bgp_nexthop.c
Revision 1.1.1.3 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Sun Jul 21 23:54:37 2013 UTC (10 years, 11 months ago) by misho
Branches: quagga, MAIN
CVS tags: v0_99_22p0, v0_99_22, HEAD
0.99.22

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

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>