Annotation of embedaddon/quagga/bgpd/bgp_nexthop.c, revision 1.1.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>