Annotation of embedaddon/quagga/bgpd/bgp_nexthop.c, revision 1.1

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

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