Annotation of embedaddon/bird/proto/static/static.c, revision 1.1

1.1     ! misho       1: /*
        !             2:  *     BIRD -- Static Route Generator
        !             3:  *
        !             4:  *     (c) 1998--2000 Martin Mares <mj@ucw.cz>
        !             5:  *
        !             6:  *     Can be freely distributed and used under the terms of the GNU GPL.
        !             7:  */
        !             8: 
        !             9: /**
        !            10:  * DOC: Static
        !            11:  *
        !            12:  * The Static protocol is implemented in a straightforward way. It keeps
        !            13:  * two lists of static routes: one containing interface routes and one
        !            14:  * holding the remaining ones. Interface routes are inserted and removed according
        !            15:  * to interface events received from the core via the if_notify() hook. Routes
        !            16:  * pointing to a neighboring router use a sticky node in the neighbor cache
        !            17:  * to be notified about gaining or losing the neighbor. Special
        !            18:  * routes like black holes or rejects are inserted all the time.
        !            19:  *
        !            20:  * Multipath routes are tricky. Because these routes depends on
        !            21:  * several neighbors we need to integrate that to the neighbor
        !            22:  * notification handling, we use dummy static_route nodes, one for
        !            23:  * each nexthop. Therefore, a multipath route consists of a master
        !            24:  * static_route node (of dest RTD_MULTIPATH), which specifies prefix
        !            25:  * and is used in most circumstances, and a list of dummy static_route
        !            26:  * nodes (of dest RTD_NONE), which stores info about nexthops and are
        !            27:  * connected to neighbor entries and neighbor notifications. Dummy
        !            28:  * nodes are chained using mp_next, they aren't in other_routes list,
        !            29:  * and abuse some fields (masklen, if_name) for other purposes.
        !            30:  *
        !            31:  * The only other thing worth mentioning is that when asked for reconfiguration,
        !            32:  * Static not only compares the two configurations, but it also calculates
        !            33:  * difference between the lists of static routes and it just inserts the
        !            34:  * newly added routes and removes the obsolete ones.
        !            35:  */
        !            36: 
        !            37: #undef LOCAL_DEBUG
        !            38: 
        !            39: #include "nest/bird.h"
        !            40: #include "nest/iface.h"
        !            41: #include "nest/protocol.h"
        !            42: #include "nest/route.h"
        !            43: #include "nest/cli.h"
        !            44: #include "conf/conf.h"
        !            45: #include "filter/filter.h"
        !            46: #include "lib/string.h"
        !            47: #include "lib/alloca.h"
        !            48: 
        !            49: #include "static.h"
        !            50: 
        !            51: static linpool *static_lp;
        !            52: 
        !            53: static inline rtable *
        !            54: p_igp_table(struct proto *p)
        !            55: {
        !            56:   struct static_config *cf = (void *) p->cf;
        !            57:   return cf->igp_table ? cf->igp_table->table : p->table;
        !            58: }
        !            59: 
        !            60: static void
        !            61: static_install(struct proto *p, struct static_route *r, struct iface *ifa)
        !            62: {
        !            63:   net *n;
        !            64:   rta a;
        !            65:   rte *e;
        !            66: 
        !            67:   if (r->installed > 0)
        !            68:     return;
        !            69: 
        !            70:   DBG("Installing static route %I/%d, rtd=%d\n", r->net, r->masklen, r->dest);
        !            71:   bzero(&a, sizeof(a));
        !            72:   a.src = p->main_source;
        !            73:   a.source = (r->dest == RTD_DEVICE) ? RTS_STATIC_DEVICE : RTS_STATIC;
        !            74:   a.scope = SCOPE_UNIVERSE;
        !            75:   a.cast = RTC_UNICAST;
        !            76:   a.dest = r->dest;
        !            77:   a.gw = r->via;
        !            78:   a.iface = ifa;
        !            79: 
        !            80:   if (r->dest == RTD_MULTIPATH)
        !            81:     {
        !            82:       struct static_route *r2;
        !            83:       struct mpnh *nhs = NULL;
        !            84: 
        !            85:       for (r2 = r->mp_next; r2; r2 = r2->mp_next)
        !            86:        if (r2->installed)
        !            87:          {
        !            88:            struct mpnh *nh = alloca(sizeof(struct mpnh));
        !            89:            nh->gw = r2->via;
        !            90:            nh->iface = r2->neigh->iface;
        !            91:            nh->weight = r2->masklen; /* really */
        !            92:            mpnh_insert(&nhs, nh);
        !            93:          }
        !            94: 
        !            95:       /* There is at least one nexthop */
        !            96:       if (!nhs->next)
        !            97:        {
        !            98:          /* Fallback to unipath route for exactly one nexthop */
        !            99:          a.dest = RTD_ROUTER;
        !           100:          a.gw = nhs->gw;
        !           101:          a.iface = nhs->iface;
        !           102:        }
        !           103:       else
        !           104:        a.nexthops = nhs;
        !           105:     }
        !           106: 
        !           107:   if (r->dest == RTDX_RECURSIVE)
        !           108:     rta_set_recursive_next_hop(p->table, &a, p_igp_table(p), &r->via, &r->via);
        !           109: 
        !           110:   /* We skip rta_lookup() here */
        !           111: 
        !           112:   n = net_get(p->table, r->net, r->masklen);
        !           113:   e = rte_get_temp(&a);
        !           114:   e->net = n;
        !           115:   e->pflags = 0;
        !           116: 
        !           117:   if (r->cmds)
        !           118:     f_eval_rte(r->cmds, &e, static_lp);
        !           119: 
        !           120:   rte_update(p, n, e);
        !           121:   r->installed = 1;
        !           122: 
        !           123:   if (r->cmds)
        !           124:     lp_flush(static_lp);
        !           125: }
        !           126: 
        !           127: static void
        !           128: static_remove(struct proto *p, struct static_route *r)
        !           129: {
        !           130:   net *n;
        !           131: 
        !           132:   if (!r->installed)
        !           133:     return;
        !           134: 
        !           135:   DBG("Removing static route %I/%d via %I\n", r->net, r->masklen, r->via);
        !           136:   n = net_find(p->table, r->net, r->masklen);
        !           137:   rte_update(p, n, NULL);
        !           138:   r->installed = 0;
        !           139: }
        !           140: 
        !           141: static void
        !           142: static_bfd_notify(struct bfd_request *req);
        !           143: 
        !           144: static void
        !           145: static_update_bfd(struct proto *p, struct static_route *r)
        !           146: {
        !           147:   struct neighbor *nb = r->neigh;
        !           148:   int bfd_up = (nb->scope > 0) && r->use_bfd;
        !           149: 
        !           150:   if (bfd_up && !r->bfd_req)
        !           151:   {
        !           152:     // ip_addr local = ipa_nonzero(r->local) ? r->local : nb->ifa->ip;
        !           153:     r->bfd_req = bfd_request_session(p->pool, r->via, nb->ifa->ip, nb->iface,
        !           154:                                     static_bfd_notify, r);
        !           155:   }
        !           156: 
        !           157:   if (!bfd_up && r->bfd_req)
        !           158:   {
        !           159:     rfree(r->bfd_req);
        !           160:     r->bfd_req = NULL;
        !           161:   }
        !           162: }
        !           163: 
        !           164: static int
        !           165: static_decide(struct static_config *cf, struct static_route *r)
        !           166: {
        !           167:   /* r->dest != RTD_MULTIPATH, but may be RTD_NONE (part of multipath route)
        !           168:      the route also have to be valid (r->neigh != NULL) */
        !           169: 
        !           170:   if (r->neigh->scope < 0)
        !           171:     return 0;
        !           172: 
        !           173:   if (cf->check_link && !(r->neigh->iface->flags & IF_LINK_UP))
        !           174:     return 0;
        !           175: 
        !           176:   if (r->bfd_req && r->bfd_req->state != BFD_STATE_UP)
        !           177:     return 0;
        !           178: 
        !           179:   return 1;
        !           180: }
        !           181: 
        !           182: 
        !           183: static void
        !           184: static_add(struct proto *p, struct static_config *cf, struct static_route *r)
        !           185: {
        !           186:   DBG("static_add(%I/%d,%d)\n", r->net, r->masklen, r->dest);
        !           187:   switch (r->dest)
        !           188:     {
        !           189:     case RTD_ROUTER:
        !           190:       {
        !           191:        struct neighbor *n = neigh_find2(p, &r->via, r->via_if, NEF_STICKY);
        !           192:        if (n)
        !           193:          {
        !           194:            r->chain = n->data;
        !           195:            n->data = r;
        !           196:            r->neigh = n;
        !           197: 
        !           198:            static_update_bfd(p, r);
        !           199:            if (static_decide(cf, r))
        !           200:              static_install(p, r, n->iface);
        !           201:            else
        !           202:              static_remove(p, r);
        !           203:          }
        !           204:        else
        !           205:          {
        !           206:            log(L_ERR "Static route destination %I is invalid. Ignoring.", r->via);
        !           207:            static_remove(p, r);
        !           208:          }
        !           209:        break;
        !           210:       }
        !           211: 
        !           212:     case RTD_DEVICE:
        !           213:       break;
        !           214: 
        !           215:     case RTD_MULTIPATH:
        !           216:       {
        !           217:        int count = 0;
        !           218:        struct static_route *r2;
        !           219: 
        !           220:        for (r2 = r->mp_next; r2; r2 = r2->mp_next)
        !           221:          {
        !           222:            struct neighbor *n = neigh_find2(p, &r2->via, r2->via_if, NEF_STICKY);
        !           223:            if (n)
        !           224:              {
        !           225:                r2->chain = n->data;
        !           226:                n->data = r2;
        !           227:                r2->neigh = n;
        !           228: 
        !           229:                static_update_bfd(p, r2);
        !           230:                r2->installed = static_decide(cf, r2);
        !           231:                count += r2->installed;
        !           232:              }
        !           233:            else
        !           234:              {
        !           235:                log(L_ERR "Static route destination %I is invalid. Ignoring.", r2->via);
        !           236:                r2->installed = 0;
        !           237:              }
        !           238:          }
        !           239: 
        !           240:        if (count)
        !           241:          static_install(p, r, NULL);
        !           242:        else
        !           243:          static_remove(p, r);
        !           244:        break;
        !           245:       }
        !           246: 
        !           247:     default:
        !           248:       static_install(p, r, NULL);
        !           249:     }
        !           250: }
        !           251: 
        !           252: static void
        !           253: static_rte_cleanup(struct proto *p UNUSED, struct static_route *r)
        !           254: {
        !           255:   struct static_route *r2;
        !           256: 
        !           257:   if (r->bfd_req)
        !           258:   {
        !           259:     rfree(r->bfd_req);
        !           260:     r->bfd_req = NULL;
        !           261:   }
        !           262: 
        !           263:   if (r->dest == RTD_MULTIPATH)
        !           264:     for (r2 = r->mp_next; r2; r2 = r2->mp_next)
        !           265:       if (r2->bfd_req)
        !           266:       {
        !           267:        rfree(r2->bfd_req);
        !           268:        r2->bfd_req = NULL;
        !           269:       }
        !           270: }
        !           271: 
        !           272: static int
        !           273: static_start(struct proto *p)
        !           274: {
        !           275:   struct static_config *cf = (void *) p->cf;
        !           276:   struct static_route *r;
        !           277: 
        !           278:   DBG("Static: take off!\n");
        !           279: 
        !           280:   if (!static_lp)
        !           281:     static_lp = lp_new(&root_pool, 1008);
        !           282: 
        !           283:   if (cf->igp_table)
        !           284:     rt_lock_table(cf->igp_table->table);
        !           285: 
        !           286:   /* We have to go UP before routes could be installed */
        !           287:   proto_notify_state(p, PS_UP);
        !           288: 
        !           289:   WALK_LIST(r, cf->other_routes)
        !           290:     static_add(p, cf, r);
        !           291:   return PS_UP;
        !           292: }
        !           293: 
        !           294: static int
        !           295: static_shutdown(struct proto *p)
        !           296: {
        !           297:   struct static_config *cf = (void *) p->cf;
        !           298:   struct static_route *r;
        !           299: 
        !           300:   /* Just reset the flag, the routes will be flushed by the nest */
        !           301:   WALK_LIST(r, cf->iface_routes)
        !           302:     r->installed = 0;
        !           303:   WALK_LIST(r, cf->other_routes)
        !           304:   {
        !           305:     static_rte_cleanup(p, r);
        !           306:     r->installed = 0;
        !           307:   }
        !           308: 
        !           309:   return PS_DOWN;
        !           310: }
        !           311: 
        !           312: static void
        !           313: static_cleanup(struct proto *p)
        !           314: {
        !           315:   struct static_config *cf = (void *) p->cf;
        !           316: 
        !           317:   if (cf->igp_table)
        !           318:     rt_unlock_table(cf->igp_table->table);
        !           319: }
        !           320: 
        !           321: static void
        !           322: static_update_rte(struct proto *p, struct static_route *r)
        !           323: {
        !           324:   switch (r->dest)
        !           325:   {
        !           326:   case RTD_ROUTER:
        !           327:     if (static_decide((struct static_config *) p->cf, r))
        !           328:       static_install(p, r, r->neigh->iface);
        !           329:     else
        !           330:       static_remove(p, r);
        !           331:     break;
        !           332: 
        !           333:   case RTD_NONE: /* a part of multipath route */
        !           334:   {
        !           335:     int decision = static_decide((struct static_config *) p->cf, r);
        !           336:     if (decision == r->installed)
        !           337:       break; /* no change */
        !           338:     r->installed = decision;
        !           339: 
        !           340:     struct static_route *r1, *r2;
        !           341:     int count = 0;
        !           342:     r1 = (void *) r->if_name; /* really */
        !           343:     for (r2 = r1->mp_next; r2; r2 = r2->mp_next)
        !           344:       count += r2->installed;
        !           345: 
        !           346:     if (count)
        !           347:     {
        !           348:       /* Set of nexthops changed - force reinstall */
        !           349:       r1->installed = 0;
        !           350:       static_install(p, r1, NULL);
        !           351:     }
        !           352:     else
        !           353:       static_remove(p, r1);
        !           354: 
        !           355:     break;
        !           356:   }
        !           357:   }
        !           358: }
        !           359: 
        !           360: static void
        !           361: static_neigh_notify(struct neighbor *n)
        !           362: {
        !           363:   struct proto *p = n->proto;
        !           364:   struct static_route *r;
        !           365: 
        !           366:   DBG("Static: neighbor notify for %I: iface %p\n", n->addr, n->iface);
        !           367:   for(r=n->data; r; r=r->chain)
        !           368:   {
        !           369:     static_update_bfd(p, r);
        !           370:     static_update_rte(p, r);
        !           371:   }
        !           372: }
        !           373: 
        !           374: static void
        !           375: static_bfd_notify(struct bfd_request *req)
        !           376: {
        !           377:   struct static_route *r = req->data;
        !           378:   struct proto *p = r->neigh->proto;
        !           379: 
        !           380:   // if (req->down) TRACE(D_EVENTS, "BFD session down for nbr %I on %s", XXXX);
        !           381: 
        !           382:   static_update_rte(p, r);
        !           383: }
        !           384: 
        !           385: static void
        !           386: static_dump_rt(struct static_route *r)
        !           387: {
        !           388:   debug("%-1I/%2d: ", r->net, r->masklen);
        !           389:   switch (r->dest)
        !           390:     {
        !           391:     case RTD_ROUTER:
        !           392:       debug("via %I\n", r->via);
        !           393:       break;
        !           394:     case RTD_DEVICE:
        !           395:       debug("dev %s\n", r->if_name);
        !           396:       break;
        !           397:     default:
        !           398:       debug("rtd %d\n", r->dest);
        !           399:       break;
        !           400:     }
        !           401: }
        !           402: 
        !           403: static void
        !           404: static_dump(struct proto *p)
        !           405: {
        !           406:   struct static_config *c = (void *) p->cf;
        !           407:   struct static_route *r;
        !           408: 
        !           409:   debug("Independent static routes:\n");
        !           410:   WALK_LIST(r, c->other_routes)
        !           411:     static_dump_rt(r);
        !           412:   debug("Device static routes:\n");
        !           413:   WALK_LIST(r, c->iface_routes)
        !           414:     static_dump_rt(r);
        !           415: }
        !           416: 
        !           417: static void
        !           418: static_if_notify(struct proto *p, unsigned flags, struct iface *i)
        !           419: {
        !           420:   struct static_route *r;
        !           421:   struct static_config *c = (void *) p->cf;
        !           422: 
        !           423:   if (flags & IF_CHANGE_UP)
        !           424:     {
        !           425:       WALK_LIST(r, c->iface_routes)
        !           426:        if (!strcmp(r->if_name, i->name))
        !           427:          static_install(p, r, i);
        !           428:     }
        !           429:   else if (flags & IF_CHANGE_DOWN)
        !           430:     {
        !           431:       WALK_LIST(r, c->iface_routes)
        !           432:        if (!strcmp(r->if_name, i->name))
        !           433:          static_remove(p, r);
        !           434:     }
        !           435: }
        !           436: 
        !           437: int
        !           438: static_rte_mergable(rte *pri UNUSED, rte *sec UNUSED)
        !           439: {
        !           440:   return 1;
        !           441: }
        !           442: 
        !           443: void
        !           444: static_init_config(struct static_config *c)
        !           445: {
        !           446:   init_list(&c->iface_routes);
        !           447:   init_list(&c->other_routes);
        !           448: }
        !           449: 
        !           450: static struct proto *
        !           451: static_init(struct proto_config *c)
        !           452: {
        !           453:   struct proto *p = proto_new(c, sizeof(struct proto));
        !           454: 
        !           455:   p->neigh_notify = static_neigh_notify;
        !           456:   p->if_notify = static_if_notify;
        !           457:   p->rte_mergable = static_rte_mergable;
        !           458: 
        !           459:   return p;
        !           460: }
        !           461: 
        !           462: static inline int
        !           463: static_same_net(struct static_route *x, struct static_route *y)
        !           464: {
        !           465:   return ipa_equal(x->net, y->net) && (x->masklen == y->masklen);
        !           466: }
        !           467: 
        !           468: static inline int
        !           469: static_same_dest(struct static_route *x, struct static_route *y)
        !           470: {
        !           471:   if (x->dest != y->dest)
        !           472:     return 0;
        !           473: 
        !           474:   switch (x->dest)
        !           475:     {
        !           476:     case RTD_ROUTER:
        !           477:       return ipa_equal(x->via, y->via) && (x->via_if == y->via_if);
        !           478: 
        !           479:     case RTD_DEVICE:
        !           480:       return !strcmp(x->if_name, y->if_name);
        !           481: 
        !           482:     case RTD_MULTIPATH:
        !           483:       for (x = x->mp_next, y = y->mp_next;
        !           484:           x && y;
        !           485:           x = x->mp_next, y = y->mp_next)
        !           486:        if (!ipa_equal(x->via, y->via) || (x->via_if != y->via_if) || (x->use_bfd != y->use_bfd))
        !           487:          return 0;
        !           488:       return !x && !y;
        !           489: 
        !           490:     case RTDX_RECURSIVE:
        !           491:       return ipa_equal(x->via, y->via);
        !           492: 
        !           493:     default:
        !           494:       return 1;
        !           495:     }
        !           496: }
        !           497: 
        !           498: static inline int
        !           499: static_same_rte(struct static_route *x, struct static_route *y)
        !           500: {
        !           501:   return static_same_dest(x, y) && i_same(x->cmds, y->cmds);
        !           502: }
        !           503: 
        !           504: 
        !           505: static void
        !           506: static_match(struct proto *p, struct static_route *r, struct static_config *n)
        !           507: {
        !           508:   struct static_route *t;
        !           509: 
        !           510:   /*
        !           511:    * For given old route *r we find whether a route to the same
        !           512:    * network is also in the new route list. In that case, we keep the
        !           513:    * route and possibly update the route later if destination changed.
        !           514:    * Otherwise, we remove the route.
        !           515:    */
        !           516: 
        !           517:   if (r->neigh)
        !           518:     r->neigh->data = NULL;
        !           519: 
        !           520:   WALK_LIST(t, n->iface_routes)
        !           521:     if (static_same_net(r, t))
        !           522:       goto found;
        !           523: 
        !           524:   WALK_LIST(t, n->other_routes)
        !           525:     if (static_same_net(r, t))
        !           526:       goto found;
        !           527: 
        !           528:   static_remove(p, r);
        !           529:   return;
        !           530: 
        !           531:  found:
        !           532:   /* If destination is different, force reinstall */
        !           533:   if ((r->installed > 0) && !static_same_rte(r, t))
        !           534:     t->installed = -1;
        !           535:   else
        !           536:     t->installed = r->installed;
        !           537: }
        !           538: 
        !           539: static inline rtable *
        !           540: cf_igp_table(struct static_config *cf)
        !           541: {
        !           542:   return cf->igp_table ? cf->igp_table->table : NULL;
        !           543: }
        !           544: 
        !           545: static int
        !           546: static_reconfigure(struct proto *p, struct proto_config *new)
        !           547: {
        !           548:   struct static_config *o = (void *) p->cf;
        !           549:   struct static_config *n = (void *) new;
        !           550:   struct static_route *r;
        !           551: 
        !           552:   if (cf_igp_table(o) != cf_igp_table(n))
        !           553:     return 0;
        !           554: 
        !           555:   /* Delete all obsolete routes and reset neighbor entries */
        !           556:   WALK_LIST(r, o->iface_routes)
        !           557:     static_match(p, r, n);
        !           558:   WALK_LIST(r, o->other_routes)
        !           559:     static_match(p, r, n);
        !           560: 
        !           561:   /* Now add all new routes, those not changed will be ignored by static_install() */
        !           562:   WALK_LIST(r, n->iface_routes)
        !           563:     {
        !           564:       struct iface *ifa;
        !           565:       if ((ifa = if_find_by_name(r->if_name)) && (ifa->flags & IF_UP))
        !           566:        static_install(p, r, ifa);
        !           567:     }
        !           568:   WALK_LIST(r, n->other_routes)
        !           569:     static_add(p, n, r);
        !           570: 
        !           571:   WALK_LIST(r, o->other_routes)
        !           572:     static_rte_cleanup(p, r);
        !           573: 
        !           574:   return 1;
        !           575: }
        !           576: 
        !           577: static void
        !           578: static_copy_routes(list *dlst, list *slst)
        !           579: {
        !           580:   struct static_route *dr, *sr;
        !           581: 
        !           582:   init_list(dlst);
        !           583:   WALK_LIST(sr, *slst)
        !           584:     {
        !           585:       /* copy one route */
        !           586:       dr = cfg_alloc(sizeof(struct static_route));
        !           587:       memcpy(dr, sr, sizeof(struct static_route));
        !           588: 
        !           589:       /* This fn is supposed to be called on fresh src routes, which have 'live'
        !           590:         fields (like .chain, .neigh or .installed) zero, so no need to zero them */
        !           591: 
        !           592:       /* We need to copy multipath chain, because there are backptrs in 'if_name' */
        !           593:       if (dr->dest == RTD_MULTIPATH)
        !           594:        {
        !           595:          struct static_route *md, *ms, **mp_last;
        !           596: 
        !           597:          mp_last = &(dr->mp_next);
        !           598:          for (ms = sr->mp_next; ms; ms = ms->mp_next)
        !           599:            {
        !           600:              md = cfg_alloc(sizeof(struct static_route));
        !           601:              memcpy(md, ms, sizeof(struct static_route));
        !           602:              md->if_name = (void *) dr; /* really */
        !           603: 
        !           604:              *mp_last = md;
        !           605:              mp_last = &(md->mp_next);
        !           606:            }
        !           607:          *mp_last = NULL;
        !           608:        }
        !           609: 
        !           610:       add_tail(dlst, (node *) dr);
        !           611:     }
        !           612: }
        !           613: 
        !           614: static void
        !           615: static_copy_config(struct proto_config *dest, struct proto_config *src)
        !           616: {
        !           617:   struct static_config *d = (struct static_config *) dest;
        !           618:   struct static_config *s = (struct static_config *) src;
        !           619: 
        !           620:   /* Shallow copy of everything */
        !           621:   proto_copy_rest(dest, src, sizeof(struct static_config));
        !           622: 
        !           623:   /* Copy route lists */
        !           624:   static_copy_routes(&d->iface_routes, &s->iface_routes);
        !           625:   static_copy_routes(&d->other_routes, &s->other_routes);
        !           626: }
        !           627: 
        !           628: 
        !           629: struct protocol proto_static = {
        !           630:   .name =              "Static",
        !           631:   .template =          "static%d",
        !           632:   .preference =                DEF_PREF_STATIC,
        !           633:   .config_size =       sizeof(struct static_config),
        !           634:   .init =              static_init,
        !           635:   .dump =              static_dump,
        !           636:   .start =             static_start,
        !           637:   .shutdown =          static_shutdown,
        !           638:   .cleanup =           static_cleanup,
        !           639:   .reconfigure =       static_reconfigure,
        !           640:   .copy_config =       static_copy_config
        !           641: };
        !           642: 
        !           643: static void
        !           644: static_show_rt(struct static_route *r)
        !           645: {
        !           646:   byte via[STD_ADDRESS_P_LENGTH + 16];
        !           647: 
        !           648:   switch (r->dest)
        !           649:     {
        !           650:     case RTD_ROUTER:   bsprintf(via, "via %I%J", r->via, r->via_if); break;
        !           651:     case RTD_DEVICE:   bsprintf(via, "dev %s", r->if_name); break;
        !           652:     case RTD_BLACKHOLE:        bsprintf(via, "blackhole"); break;
        !           653:     case RTD_UNREACHABLE: bsprintf(via, "unreachable"); break;
        !           654:     case RTD_PROHIBIT: bsprintf(via, "prohibited"); break;
        !           655:     case RTD_MULTIPATH:        bsprintf(via, "multipath"); break;
        !           656:     case RTDX_RECURSIVE: bsprintf(via, "recursive %I", r->via); break;
        !           657:     default:           bsprintf(via, "???");
        !           658:     }
        !           659:   cli_msg(-1009, "%I/%d %s%s%s", r->net, r->masklen, via,
        !           660:          r->bfd_req ? " (bfd)" : "", r->installed ? "" : " (dormant)");
        !           661: 
        !           662:   struct static_route *r2;
        !           663:   if (r->dest == RTD_MULTIPATH)
        !           664:     for (r2 = r->mp_next; r2; r2 = r2->mp_next)
        !           665:       cli_msg(-1009, "\tvia %I%J weight %d%s%s", r2->via, r2->via_if, r2->masklen + 1, /* really */
        !           666:              r2->bfd_req ? " (bfd)" : "", r2->installed ? "" : " (dormant)");
        !           667: }
        !           668: 
        !           669: void
        !           670: static_show(struct proto *P)
        !           671: {
        !           672:   struct static_config *c = (void *) P->cf;
        !           673:   struct static_route *r;
        !           674: 
        !           675:   WALK_LIST(r, c->other_routes)
        !           676:     static_show_rt(r);
        !           677:   WALK_LIST(r, c->iface_routes)
        !           678:     static_show_rt(r);
        !           679:   cli_msg(0, "");
        !           680: }

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