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

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

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