Annotation of embedaddon/bird2/proto/ospf/ospf.c, revision 1.1.1.1

1.1       misho       1: /*
                      2:  *     BIRD -- OSPF
                      3:  *
                      4:  *     (c) 1999--2004 Ondrej Filip <feela@network.cz>
                      5:  *     (c) 2009--2014 Ondrej Zajicek <santiago@crfreenet.org>
                      6:  *     (c) 2009--2014 CZ.NIC z.s.p.o.
                      7:  *
                      8:  *     Can be freely distributed and used under the terms of the GNU GPL.
                      9:  */
                     10: 
                     11: /**
                     12:  * DOC: Open Shortest Path First (OSPF)
                     13:  *
                     14:  * The OSPF protocol is quite complicated and its complex implemenation is split
                     15:  * to many files. In |ospf.c|, you will find mainly the interface for
                     16:  * communication with the core (e.g., reconfiguration hooks, shutdown and
                     17:  * initialisation and so on). File |iface.c| contains the interface state
                     18:  * machine and functions for allocation and deallocation of OSPF's interface
                     19:  * data structures. Source |neighbor.c| includes the neighbor state machine and
                     20:  * functions for election of Designated Router and Backup Designated router. In
                     21:  * |packet.c|, you will find various functions for sending and receiving generic
                     22:  * OSPF packets. There are also routines for authentication and checksumming.
                     23:  * In |hello.c|, there are routines for sending and receiving of hello packets
                     24:  * as well as functions for maintaining wait times and the inactivity timer.
                     25:  * Files |lsreq.c|, |lsack.c|, |dbdes.c| contain functions for sending and
                     26:  * receiving of link-state requests, link-state acknowledgements and database
                     27:  * descriptions respectively.  In |lsupd.c|, there are functions for sending and
                     28:  * receiving of link-state updates and also the flooding algorithm. Source
                     29:  * |topology.c| is a place where routines for searching LSAs in the link-state
                     30:  * database, adding and deleting them reside, there also are functions for
                     31:  * originating of various types of LSAs (router LSA, net LSA, external LSA).
                     32:  * File |rt.c| contains routines for calculating the routing table. |lsalib.c|
                     33:  * is a set of various functions for working with the LSAs (endianity
                     34:  * conversions, calculation of checksum etc.).
                     35:  *
                     36:  * One instance of the protocol is able to hold LSA databases for multiple OSPF
                     37:  * areas, to exchange routing information between multiple neighbors and to
                     38:  * calculate the routing tables. The core structure is &ospf_proto to which
                     39:  * multiple &ospf_area and &ospf_iface structures are connected. &ospf_proto is
                     40:  * also connected to &top_hash_graph which is a dynamic hashing structure that
                     41:  * describes the link-state database. It allows fast search, addition and
                     42:  * deletion. Each LSA is kept in two pieces: header and body. Both of them are
                     43:  * kept in the endianity of the CPU.
                     44:  *
                     45:  * In OSPFv2 specification, it is implied that there is one IP prefix for each
                     46:  * physical network/interface (unless it is an ptp link). But in modern systems,
                     47:  * there might be more independent IP prefixes associated with an interface.  To
                     48:  * handle this situation, we have one &ospf_iface for each active IP prefix
                     49:  * (instead for each active iface); This behaves like virtual interface for the
                     50:  * purpose of OSPF.  If we receive packet, we associate it with a proper virtual
                     51:  * interface mainly according to its source address.
                     52:  *
                     53:  * OSPF keeps one socket per &ospf_iface. This allows us (compared to one socket
                     54:  * approach) to evade problems with a limit of multicast groups per socket and
                     55:  * with sending multicast packets to appropriate interface in a portable way.
                     56:  * The socket is associated with underlying physical iface and should not
                     57:  * receive packets received on other ifaces (unfortunately, this is not true on
                     58:  * BSD). Generally, one packet can be received by more sockets (for example, if
                     59:  * there are more &ospf_iface on one physical iface), therefore we explicitly
                     60:  * filter received packets according to src/dst IP address and received iface.
                     61:  *
                     62:  * Vlinks are implemented using particularly degenerate form of &ospf_iface,
                     63:  * which has several exceptions: it does not have its iface or socket (it copies
                     64:  * these from 'parent' &ospf_iface) and it is present in iface list even when
                     65:  * down (it is not freed in ospf_iface_down()).
                     66:  *
                     67:  * The heart beat of ospf is ospf_disp(). It is called at regular intervals
                     68:  * (&ospf_proto->tick). It is responsible for aging and flushing of LSAs in the
                     69:  * database, updating topology information in LSAs and for routing table
                     70:  * calculation.
                     71:  *
                     72:  * To every &ospf_iface, we connect one or more &ospf_neighbor's -- a structure
                     73:  * containing many timers and queues for building adjacency and for exchange of
                     74:  * routing messages.
                     75:  *
                     76:  * BIRD's OSPF implementation respects RFC2328 in every detail, but some of
                     77:  * internal algorithms do differ. The RFC recommends making a snapshot of the
                     78:  * link-state database when a new adjacency is forming and sending the database
                     79:  * description packets based on the information in this snapshot. The database
                     80:  * can be quite large in some networks, so rather we walk through a &slist
                     81:  * structure which allows us to continue even if the actual LSA we were working
                     82:  * with is deleted. New LSAs are added at the tail of this &slist.
                     83:  *
                     84:  * We also do not keep a separate OSPF routing table, because the core helps us
                     85:  * by being able to recognize when a route is updated to an identical one and it
                     86:  * suppresses the update automatically. Due to this, we can flush all the routes
                     87:  * we have recalculated and also those we have deleted to the core's routing
                     88:  * table and the core will take care of the rest. This simplifies the process
                     89:  * and conserves memory.
                     90:  *
                     91:  * Supported standards:
                     92:  * - RFC 2328 - main OSPFv2 standard
                     93:  * - RFC 5340 - main OSPFv3 standard
                     94:  * - RFC 3101 - OSPFv2 NSSA areas
                     95:  * - RFC 3623 - OSPFv2 Graceful Restart
                     96:  * - RFC 4576 - OSPFv2 VPN loop prevention
                     97:  * - RFC 5187 - OSPFv3 Graceful Restart
                     98:  * - RFC 5250 - OSPFv2 Opaque LSAs
                     99:  * - RFC 5709 - OSPFv2 HMAC-SHA Cryptographic Authentication
                    100:  * - RFC 5838 - OSPFv3 Support of Address Families
                    101:  * - RFC 6549 - OSPFv2 Multi-Instance Extensions
                    102:  * - RFC 6987 - OSPF Stub Router Advertisement
                    103:  * - RFC 7166 - OSPFv3 Authentication Trailer
                    104:  * - RFC 7770 - OSPF Router Information LSA
                    105:  */
                    106: 
                    107: #include <stdlib.h>
                    108: #include "ospf.h"
                    109: 
                    110: static int ospf_preexport(struct proto *P, rte **new, struct linpool *pool);
                    111: static void ospf_make_tmp_attrs(struct rte *rt, struct linpool *pool);
                    112: static void ospf_store_tmp_attrs(struct rte *rt, struct linpool *pool);
                    113: static void ospf_reload_routes(struct channel *C);
                    114: static int ospf_rte_better(struct rte *new, struct rte *old);
                    115: static int ospf_rte_same(struct rte *new, struct rte *old);
                    116: static void ospf_disp(timer *timer);
                    117: 
                    118: 
                    119: static void
                    120: add_area_nets(struct ospf_area *oa, struct ospf_area_config *ac)
                    121: {
                    122:   struct ospf_proto *p = oa->po;
                    123:   struct area_net_config *anc;
                    124:   struct area_net *an;
                    125: 
                    126:   fib_init(&oa->net_fib,  p->p.pool, ospf_get_af(p),
                    127:           sizeof(struct area_net), OFFSETOF(struct area_net, fn), 0, NULL);
                    128:   fib_init(&oa->enet_fib, p->p.pool, ospf_get_af(p),
                    129:           sizeof(struct area_net), OFFSETOF(struct area_net, fn), 0, NULL);
                    130: 
                    131:   WALK_LIST(anc, ac->net_list)
                    132:   {
                    133:     an = fib_get(&oa->net_fib, &anc->prefix);
                    134:     an->hidden = anc->hidden;
                    135:   }
                    136: 
                    137:   WALK_LIST(anc, ac->enet_list)
                    138:   {
                    139:     an = fib_get(&oa->enet_fib, &anc->prefix);
                    140:     an->hidden = anc->hidden;
                    141:     an->tag = anc->tag;
                    142:   }
                    143: }
                    144: 
                    145: static inline uint
                    146: ospf_opts(struct ospf_proto *p)
                    147: {
                    148:   if (ospf_is_v2(p))
                    149:     return OPT_O;
                    150: 
                    151:   return ((ospf_is_ip6(p) && !p->af_mc) ? OPT_V6 : 0) |
                    152:     (!p->stub_router ? OPT_R : 0) | (p->af_ext ? OPT_AF : 0);
                    153: }
                    154: 
                    155: static void
                    156: ospf_area_add(struct ospf_proto *p, struct ospf_area_config *ac)
                    157: {
                    158:   struct ospf_area *oa;
                    159: 
                    160:   OSPF_TRACE(D_EVENTS, "Adding area %R", ac->areaid);
                    161: 
                    162:   oa = mb_allocz(p->p.pool, sizeof(struct ospf_area));
                    163:   add_tail(&p->area_list, NODE oa);
                    164:   p->areano++;
                    165: 
                    166:   oa->ac = ac;
                    167:   oa->areaid = ac->areaid;
                    168:   oa->rt = NULL;
                    169:   oa->po = p;
                    170:   fib_init(&oa->rtr, p->p.pool, NET_IP4, sizeof(ort), OFFSETOF(ort, fn), 0, NULL);
                    171:   add_area_nets(oa, ac);
                    172: 
                    173:   if (oa->areaid == 0)
                    174:     p->backbone = oa;
                    175: 
                    176:   oa->options = ac->type | ospf_opts(p);
                    177: 
                    178:   ospf_notify_rt_lsa(oa);
                    179: }
                    180: 
                    181: static void
                    182: ospf_flush_area(struct ospf_proto *p, u32 areaid)
                    183: {
                    184:   struct top_hash_entry *en;
                    185: 
                    186:   WALK_SLIST(en, p->lsal)
                    187:     if ((LSA_SCOPE(en->lsa_type) == LSA_SCOPE_AREA) && (en->domain == areaid))
                    188:       ospf_flush_lsa(p, en);
                    189: }
                    190: 
                    191: static void
                    192: ospf_area_remove(struct ospf_area *oa)
                    193: {
                    194:   struct ospf_proto *p = oa->po;
                    195:   OSPF_TRACE(D_EVENTS, "Removing area %R", oa->areaid);
                    196: 
                    197:   /* We suppose that interfaces are already removed */
                    198:   ospf_flush_area(p, oa->areaid);
                    199: 
                    200:   fib_free(&oa->rtr);
                    201:   fib_free(&oa->net_fib);
                    202:   fib_free(&oa->enet_fib);
                    203: 
                    204:   if (oa->translator_timer)
                    205:     rfree(oa->translator_timer);
                    206: 
                    207:   p->areano--;
                    208:   rem_node(NODE oa);
                    209:   mb_free(oa);
                    210: }
                    211: 
                    212: struct ospf_area *
                    213: ospf_find_area(struct ospf_proto *p, u32 aid)
                    214: {
                    215:   struct ospf_area *oa;
                    216:   WALK_LIST(oa, p->area_list)
                    217:     if (((struct ospf_area *) oa)->areaid == aid)
                    218:       return oa;
                    219:   return NULL;
                    220: }
                    221: 
                    222: static struct ospf_iface *
                    223: ospf_find_vlink(struct ospf_proto *p, u32 voa, u32 vid)
                    224: {
                    225:   struct ospf_iface *ifa;
                    226:   WALK_LIST(ifa, p->iface_list)
                    227:     if ((ifa->type == OSPF_IT_VLINK) && (ifa->voa->areaid == voa) && (ifa->vid == vid))
                    228:       return ifa;
                    229:   return NULL;
                    230: }
                    231: 
                    232: static void
                    233: ospf_start_gr_recovery(struct ospf_proto *p)
                    234: {
                    235:   OSPF_TRACE(D_EVENTS, "Graceful restart started");
                    236: 
                    237:   p->gr_recovery = 1;
                    238:   p->gr_timeout = current_time() + (p->gr_time S);
                    239:   channel_graceful_restart_lock(p->p.main_channel);
                    240:   p->p.main_channel->gr_wait = 1;
                    241: 
                    242:   /* NOTE: We should get end of grace period from non-volatile storage */
                    243: }
                    244: 
                    245: void
                    246: ospf_stop_gr_recovery(struct ospf_proto *p)
                    247: {
                    248:   p->gr_recovery = 0;
                    249:   p->gr_cleanup = 1;
                    250:   p->gr_timeout = 0;
                    251: 
                    252:   /* Reorigination of router/network LSAs is already scheduled */
                    253: 
                    254:   /* Rest is done in ospf_cleanup_gr_recovery() */
                    255: }
                    256: 
                    257: static void
                    258: ospf_cleanup_gr_recovery(struct ospf_proto *p)
                    259: {
                    260:   struct top_hash_entry *en;
                    261: 
                    262:   /* Flush dirty LSAa except external ones, these will be handled by feed */
                    263:   WALK_SLIST(en, p->lsal)
                    264:     if (en->gr_dirty)
                    265:     {
                    266:       if ((en->lsa_type == LSA_T_EXT) || (en->lsa_type == LSA_T_NSSA))
                    267:        en->mode = LSA_M_EXPORT;
                    268:       else
                    269:        ospf_flush_lsa(p, en);
                    270:     }
                    271: 
                    272:   /* End graceful restart on channel, will also schedule feed */
                    273:   channel_graceful_restart_unlock(p->p.main_channel);
                    274: 
                    275:   p->gr_cleanup = 0;
                    276: }
                    277: 
                    278: static int
                    279: ospf_start(struct proto *P)
                    280: {
                    281:   struct ospf_proto *p = (struct ospf_proto *) P;
                    282:   struct ospf_config *c = (struct ospf_config *) (P->cf);
                    283:   struct ospf_area_config *ac;
                    284: 
                    285:   p->router_id = proto_get_router_id(P->cf);
                    286:   p->ospf2 = c->ospf2;
                    287:   p->af_ext = c->af_ext;
                    288:   p->af_mc = c->af_mc;
                    289:   p->rfc1583 = c->rfc1583;
                    290:   p->stub_router = c->stub_router;
                    291:   p->merge_external = c->merge_external;
                    292:   p->instance_id = c->instance_id;
                    293:   p->asbr = c->asbr;
                    294:   p->vpn_pe = c->vpn_pe;
                    295:   p->ecmp = c->ecmp;
                    296:   p->gr_mode = c->gr_mode;
                    297:   p->gr_time = c->gr_time;
                    298:   p->tick = c->tick;
                    299:   p->disp_timer = tm_new_init(P->pool, ospf_disp, p, p->tick S, 0);
                    300:   tm_start(p->disp_timer, 100 MS);
                    301:   p->lsab_size = 256;
                    302:   p->lsab_used = 0;
                    303:   p->lsab = mb_alloc(P->pool, p->lsab_size);
                    304:   p->nhpool = lp_new(P->pool, 12*sizeof(struct nexthop));
                    305:   init_list(&(p->iface_list));
                    306:   init_list(&(p->area_list));
                    307:   fib_init(&p->rtf, P->pool, ospf_get_af(p), sizeof(ort), OFFSETOF(ort, fn), 0, NULL);
                    308:   if (ospf_is_v3(p))
                    309:     idm_init(&p->idm, P->pool, 16);
                    310:   p->areano = 0;
                    311:   p->gr = ospf_top_new(p, P->pool);
                    312:   s_init_list(&(p->lsal));
                    313: 
                    314:   p->flood_event = ev_new_init(P->pool, ospf_flood_event, p);
                    315: 
                    316:   p->log_pkt_tbf = (struct tbf){ .rate = 1, .burst = 5 };
                    317:   p->log_lsa_tbf = (struct tbf){ .rate = 4, .burst = 20 };
                    318: 
                    319:   /* Lock the channel when in GR recovery mode */
                    320:   if (p->p.gr_recovery && (p->gr_mode == OSPF_GR_ABLE))
                    321:     ospf_start_gr_recovery(p);
                    322: 
                    323:   WALK_LIST(ac, c->area_list)
                    324:     ospf_area_add(p, ac);
                    325: 
                    326:   if (c->abr)
                    327:     ospf_open_vlink_sk(p);
                    328: 
                    329:   /* Add all virtual links */
                    330:   struct ospf_iface_patt *ic;
                    331:   WALK_LIST(ic, c->vlink_list)
                    332:     ospf_iface_new_vlink(p, ic);
                    333: 
                    334:   return PS_UP;
                    335: }
                    336: 
                    337: static void
                    338: ospf_dump(struct proto *P)
                    339: {
                    340:   struct ospf_proto *p = (struct ospf_proto *) P;
                    341:   struct ospf_iface *ifa;
                    342:   struct ospf_neighbor *n;
                    343: 
                    344:   OSPF_TRACE(D_EVENTS, "Area number: %d", p->areano);
                    345: 
                    346:   WALK_LIST(ifa, p->iface_list)
                    347:   {
                    348:     OSPF_TRACE(D_EVENTS, "Interface: %s", ifa->ifname);
                    349:     OSPF_TRACE(D_EVENTS, "state: %u", ifa->state);
                    350:     OSPF_TRACE(D_EVENTS, "DR:  %R", ifa->drid);
                    351:     OSPF_TRACE(D_EVENTS, "BDR: %R", ifa->bdrid);
                    352:     WALK_LIST(n, ifa->neigh_list)
                    353:     {
                    354:       OSPF_TRACE(D_EVENTS, "  neighbor %R in state %u", n->rid, n->state);
                    355:     }
                    356:   }
                    357: 
                    358:   /*
                    359:   OSPF_TRACE(D_EVENTS, "LSA graph dump start:");
                    360:   ospf_top_dump(p->gr, p);
                    361:   OSPF_TRACE(D_EVENTS, "LSA graph dump finished");
                    362:   */
                    363:   neigh_dump_all();
                    364: }
                    365: 
                    366: static struct proto *
                    367: ospf_init(struct proto_config *CF)
                    368: {
                    369:   struct ospf_config *cf = (struct ospf_config *) CF;
                    370:   struct proto *P = proto_new(CF);
                    371: 
                    372:   P->main_channel = proto_add_channel(P, proto_cf_main_channel(CF));
                    373: 
                    374:   P->rt_notify = ospf_rt_notify;
                    375:   P->if_notify = ospf_if_notify;
                    376:   P->ifa_notify = cf->ospf2 ? ospf_ifa_notify2 : ospf_ifa_notify3;
                    377:   P->preexport = ospf_preexport;
                    378:   P->reload_routes = ospf_reload_routes;
                    379:   P->feed_begin = ospf_feed_begin;
                    380:   P->feed_end = ospf_feed_end;
                    381:   P->make_tmp_attrs = ospf_make_tmp_attrs;
                    382:   P->store_tmp_attrs = ospf_store_tmp_attrs;
                    383:   P->rte_better = ospf_rte_better;
                    384:   P->rte_same = ospf_rte_same;
                    385: 
                    386:   return P;
                    387: }
                    388: 
                    389: /* If new is better return 1 */
                    390: static int
                    391: ospf_rte_better(struct rte *new, struct rte *old)
                    392: {
                    393:   if (new->u.ospf.metric1 == LSINFINITY)
                    394:     return 0;
                    395: 
                    396:   if(new->attrs->source < old->attrs->source) return 1;
                    397:   if(new->attrs->source > old->attrs->source) return 0;
                    398: 
                    399:   if(new->attrs->source == RTS_OSPF_EXT2)
                    400:   {
                    401:     if(new->u.ospf.metric2 < old->u.ospf.metric2) return 1;
                    402:     if(new->u.ospf.metric2 > old->u.ospf.metric2) return 0;
                    403:   }
                    404: 
                    405:   if (new->u.ospf.metric1 < old->u.ospf.metric1)
                    406:     return 1;
                    407: 
                    408:   return 0;                    /* Old is shorter or same */
                    409: }
                    410: 
                    411: static int
                    412: ospf_rte_same(struct rte *new, struct rte *old)
                    413: {
                    414:   /* new->attrs == old->attrs always */
                    415:   return
                    416:     new->u.ospf.metric1 == old->u.ospf.metric1 &&
                    417:     new->u.ospf.metric2 == old->u.ospf.metric2 &&
                    418:     new->u.ospf.tag == old->u.ospf.tag &&
                    419:     new->u.ospf.router_id == old->u.ospf.router_id;
                    420: }
                    421: 
                    422: 
                    423: void
                    424: ospf_schedule_rtcalc(struct ospf_proto *p)
                    425: {
                    426:   if (p->calcrt)
                    427:     return;
                    428: 
                    429:   OSPF_TRACE(D_EVENTS, "Scheduling routing table calculation");
                    430:   p->calcrt = 1;
                    431: }
                    432: 
                    433: static void
                    434: ospf_reload_routes(struct channel *C)
                    435: {
                    436:   struct ospf_proto *p = (struct ospf_proto *) C->proto;
                    437: 
                    438:   if (p->calcrt == 2)
                    439:     return;
                    440: 
                    441:   OSPF_TRACE(D_EVENTS, "Scheduling routing table calculation with route reload");
                    442:   p->calcrt = 2;
                    443: }
                    444: 
                    445: 
                    446: /**
                    447:  * ospf_disp - invokes routing table calculation, aging and also area_disp()
                    448:  * @timer: timer usually called every @ospf_proto->tick second, @timer->data
                    449:  * point to @ospf_proto
                    450:  */
                    451: static void
                    452: ospf_disp(timer * timer)
                    453: {
                    454:   struct ospf_proto *p = timer->data;
                    455: 
                    456:   /* Check for end of graceful restart */
                    457:   if (p->gr_recovery)
                    458:     ospf_update_gr_recovery(p);
                    459: 
                    460:   /* Originate or flush local topology LSAs */
                    461:   ospf_update_topology(p);
                    462: 
                    463:   /* Process LSA DB */
                    464:   ospf_update_lsadb(p);
                    465: 
                    466:   /* Calculate routing table */
                    467:   if (p->calcrt)
                    468:     ospf_rt_spf(p);
                    469: 
                    470:   /* Cleanup after graceful restart */
                    471:   if (p->gr_cleanup)
                    472:     ospf_cleanup_gr_recovery(p);
                    473: }
                    474: 
                    475: 
                    476: /**
                    477:  * ospf_preexport - accept or reject new route from nest's routing table
                    478:  * @P: OSPF protocol instance
                    479:  * @new: the new route
                    480:  * @attrs: list of attributes
                    481:  * @pool: pool for allocation of attributes
                    482:  *
                    483:  * Its quite simple. It does not accept our own routes and leaves the decision on
                    484:  * import to the filters.
                    485:  */
                    486: static int
                    487: ospf_preexport(struct proto *P, rte **new, struct linpool *pool UNUSED)
                    488: {
                    489:   struct ospf_proto *p = (struct ospf_proto *) P;
                    490:   struct ospf_area *oa = ospf_main_area(p);
                    491:   rte *e = *new;
                    492: 
                    493:   /* Reject our own routes */
                    494:   if (e->attrs->src->proto == P)
                    495:     return -1;
                    496: 
                    497:   /* Do not export routes to stub areas */
                    498:   if (oa_is_stub(oa))
                    499:     return -1;
                    500: 
                    501:   return 0;
                    502: }
                    503: 
                    504: static void
                    505: ospf_make_tmp_attrs(struct rte *rt, struct linpool *pool)
                    506: {
                    507:   rte_init_tmp_attrs(rt, pool, 4);
                    508:   rte_make_tmp_attr(rt, EA_OSPF_METRIC1, EAF_TYPE_INT, rt->u.ospf.metric1);
                    509:   rte_make_tmp_attr(rt, EA_OSPF_METRIC2, EAF_TYPE_INT, rt->u.ospf.metric2);
                    510:   rte_make_tmp_attr(rt, EA_OSPF_TAG, EAF_TYPE_INT, rt->u.ospf.tag);
                    511:   rte_make_tmp_attr(rt, EA_OSPF_ROUTER_ID, EAF_TYPE_ROUTER_ID, rt->u.ospf.router_id);
                    512: }
                    513: 
                    514: static void
                    515: ospf_store_tmp_attrs(struct rte *rt, struct linpool *pool)
                    516: {
                    517:   rte_init_tmp_attrs(rt, pool, 4);
                    518:   rt->u.ospf.metric1 = rte_store_tmp_attr(rt, EA_OSPF_METRIC1);
                    519:   rt->u.ospf.metric2 = rte_store_tmp_attr(rt, EA_OSPF_METRIC2);
                    520:   rt->u.ospf.tag = rte_store_tmp_attr(rt, EA_OSPF_TAG);
                    521:   rt->u.ospf.router_id = rte_store_tmp_attr(rt, EA_OSPF_ROUTER_ID);
                    522: }
                    523: 
                    524: /**
                    525:  * ospf_shutdown - Finish of OSPF instance
                    526:  * @P: OSPF protocol instance
                    527:  *
                    528:  * RFC does not define any action that should be taken before router
                    529:  * shutdown. To make my neighbors react as fast as possible, I send
                    530:  * them hello packet with empty neighbor list. They should start
                    531:  * their neighbor state machine with event %NEIGHBOR_1WAY.
                    532:  */
                    533: static int
                    534: ospf_shutdown(struct proto *P)
                    535: {
                    536:   struct ospf_proto *p = (struct ospf_proto *) P;
                    537:   struct ospf_iface *ifa;
                    538: 
                    539:   OSPF_TRACE(D_EVENTS, "Shutdown requested");
                    540: 
                    541:   if ((P->down_code == PDC_CMD_GR_DOWN) && (p->gr_mode == OSPF_GR_ABLE))
                    542:   {
                    543:     /* Originate Grace LSAs */
                    544:     WALK_LIST(ifa, p->iface_list)
                    545:       ospf_originate_gr_lsa(p, ifa);
                    546:   }
                    547:   else
                    548:   {
                    549:     /* Send to all my neighbors 1WAY */
                    550:     WALK_LIST(ifa, p->iface_list)
                    551:       ospf_iface_shutdown(ifa);
                    552:   }
                    553: 
                    554:   /* Cleanup locked rta entries */
                    555:   FIB_WALK(&p->rtf, ort, nf)
                    556:   {
                    557:     rta_free(nf->old_rta);
                    558:   }
                    559:   FIB_WALK_END;
                    560: 
                    561:   return PS_DOWN;
                    562: }
                    563: 
                    564: static void
                    565: ospf_get_status(struct proto *P, byte * buf)
                    566: {
                    567:   struct ospf_proto *p = (struct ospf_proto *) P;
                    568: 
                    569:   if (p->p.proto_state == PS_DOWN)
                    570:     buf[0] = 0;
                    571:   else
                    572:   {
                    573:     struct ospf_iface *ifa;
                    574:     struct ospf_neighbor *n;
                    575:     int adj = 0;
                    576: 
                    577:     WALK_LIST(ifa, p->iface_list)
                    578:       WALK_LIST(n, ifa->neigh_list) if (n->state == NEIGHBOR_FULL)
                    579:       adj = 1;
                    580: 
                    581:     if (adj == 0)
                    582:       strcpy(buf, "Alone");
                    583:     else
                    584:       strcpy(buf, "Running");
                    585:   }
                    586: }
                    587: 
                    588: static void
                    589: ospf_get_route_info(rte * rte, byte * buf)
                    590: {
                    591:   char *type = "<bug>";
                    592: 
                    593:   switch (rte->attrs->source)
                    594:   {
                    595:   case RTS_OSPF:
                    596:     type = "I";
                    597:     break;
                    598:   case RTS_OSPF_IA:
                    599:     type = "IA";
                    600:     break;
                    601:   case RTS_OSPF_EXT1:
                    602:     type = "E1";
                    603:     break;
                    604:   case RTS_OSPF_EXT2:
                    605:     type = "E2";
                    606:     break;
                    607:   }
                    608: 
                    609:   buf += bsprintf(buf, " %s", type);
                    610:   buf += bsprintf(buf, " (%d/%d", rte->pref, rte->u.ospf.metric1);
                    611:   if (rte->attrs->source == RTS_OSPF_EXT2)
                    612:     buf += bsprintf(buf, "/%d", rte->u.ospf.metric2);
                    613:   buf += bsprintf(buf, ")");
                    614:   if ((rte->attrs->source == RTS_OSPF_EXT1 || rte->attrs->source == RTS_OSPF_EXT2) && rte->u.ospf.tag)
                    615:   {
                    616:     buf += bsprintf(buf, " [%x]", rte->u.ospf.tag);
                    617:   }
                    618:   if (rte->u.ospf.router_id)
                    619:     buf += bsprintf(buf, " [%R]", rte->u.ospf.router_id);
                    620: }
                    621: 
                    622: static int
                    623: ospf_get_attr(eattr * a, byte * buf, int buflen UNUSED)
                    624: {
                    625:   switch (a->id)
                    626:   {
                    627:   case EA_OSPF_METRIC1:
                    628:     bsprintf(buf, "metric1");
                    629:     return GA_NAME;
                    630:   case EA_OSPF_METRIC2:
                    631:     bsprintf(buf, "metric2");
                    632:     return GA_NAME;
                    633:   case EA_OSPF_TAG:
                    634:     bsprintf(buf, "tag: 0x%08x", a->u.data);
                    635:     return GA_FULL;
                    636:   case EA_OSPF_ROUTER_ID:
                    637:     bsprintf(buf, "router_id");
                    638:     return GA_NAME;
                    639:   default:
                    640:     return GA_UNKNOWN;
                    641:   }
                    642: }
                    643: 
                    644: static void
                    645: ospf_area_reconfigure(struct ospf_area *oa, struct ospf_area_config *nac)
                    646: {
                    647:   struct ospf_proto *p = oa->po;
                    648:   struct ospf_area_config *oac = oa->ac;
                    649:   struct ospf_iface *ifa, *ifx;
                    650: 
                    651:   oa->ac = nac;
                    652:   oa->options = nac->type | ospf_opts(p);
                    653: 
                    654:   if (nac->type != oac->type)
                    655:   {
                    656:     log(L_INFO "%s: Restarting area %R", p->p.name, oa->areaid);
                    657: 
                    658:     /* Remove area interfaces, will be re-added later */
                    659:     WALK_LIST_DELSAFE(ifa, ifx, p->iface_list)
                    660:       if (ifa->oa == oa)
                    661:       {
                    662:        ospf_iface_shutdown(ifa);
                    663:        ospf_iface_remove(ifa);
                    664:       }
                    665: 
                    666:     /* Flush area LSAs */
                    667:     ospf_flush_area(p, oa->areaid);
                    668:   }
                    669: 
                    670:   /* Handle net_list */
                    671:   fib_free(&oa->net_fib);
                    672:   fib_free(&oa->enet_fib);
                    673:   add_area_nets(oa, nac);
                    674: 
                    675:   /* No need to handle stubnet_list */
                    676: 
                    677:   oa->marked = 0;
                    678:   ospf_notify_rt_lsa(oa);
                    679: }
                    680: 
                    681: /**
                    682:  * ospf_reconfigure - reconfiguration hook
                    683:  * @P: current instance of protocol (with old configuration)
                    684:  * @c: new configuration requested by user
                    685:  *
                    686:  * This hook tries to be a little bit intelligent. Instance of OSPF
                    687:  * will survive change of many constants like hello interval,
                    688:  * password change, addition or deletion of some neighbor on
                    689:  * nonbroadcast network, cost of interface, etc.
                    690:  */
                    691: static int
                    692: ospf_reconfigure(struct proto *P, struct proto_config *CF)
                    693: {
                    694:   struct ospf_proto *p = (struct ospf_proto *) P;
                    695:   struct ospf_config *old = (struct ospf_config *) (P->cf);
                    696:   struct ospf_config *new = (struct ospf_config *) CF;
                    697:   struct ospf_area_config *oac, *nac;
                    698:   struct ospf_area *oa, *oax;
                    699:   struct ospf_iface *ifa, *ifx;
                    700:   struct ospf_iface_patt *ip;
                    701: 
                    702:   if (proto_get_router_id(CF) != p->router_id)
                    703:     return 0;
                    704: 
                    705:   if (p->ospf2 != new->ospf2)
                    706:     return 0;
                    707: 
                    708:   if (p->rfc1583 != new->rfc1583)
                    709:     return 0;
                    710: 
                    711:   if (p->instance_id != new->instance_id)
                    712:     return 0;
                    713: 
                    714:   if (old->abr != new->abr)
                    715:     return 0;
                    716: 
                    717:   if (p->areano == 1)
                    718:   {
                    719:     oac = HEAD(old->area_list);
                    720:     nac = HEAD(new->area_list);
                    721: 
                    722:     if (oac->type != nac->type)
                    723:       return 0;
                    724:   }
                    725: 
                    726:   if (old->vpn_pe != new->vpn_pe)
                    727:     return 0;
                    728: 
                    729:   if ((p->af_ext != new->af_ext) || (p->af_mc != new->af_mc))
                    730:     return 0;
                    731: 
                    732:   if (!proto_configure_channel(P, &P->main_channel, proto_cf_main_channel(CF)))
                    733:     return 0;
                    734: 
                    735:   p->stub_router = new->stub_router;
                    736:   p->merge_external = new->merge_external;
                    737:   p->asbr = new->asbr;
                    738:   p->ecmp = new->ecmp;
                    739:   p->gr_mode = new->gr_mode;
                    740:   p->gr_time = new->gr_time;
                    741:   p->tick = new->tick;
                    742:   p->disp_timer->recurrent = p->tick S;
                    743:   tm_start(p->disp_timer, 10 MS);
                    744: 
                    745:   /* Mark all areas and ifaces */
                    746:   WALK_LIST(oa, p->area_list)
                    747:     oa->marked = 1;
                    748: 
                    749:   WALK_LIST(ifa, p->iface_list)
                    750:     ifa->marked = 1;
                    751: 
                    752:   /* Add and update areas */
                    753:   WALK_LIST(nac, new->area_list)
                    754:   {
                    755:     oa = ospf_find_area(p, nac->areaid);
                    756:     if (oa)
                    757:       ospf_area_reconfigure(oa, nac);
                    758:     else
                    759:       ospf_area_add(p, nac);
                    760:   }
                    761: 
                    762:   /* Add and update interfaces */
                    763:   ospf_reconfigure_ifaces(p);
                    764: 
                    765:   /* Add and update vlinks */
                    766:   WALK_LIST(ip, new->vlink_list)
                    767:   {
                    768:     ifa = ospf_find_vlink(p, ip->voa, ip->vid);
                    769:     if (ifa)
                    770:       ospf_iface_reconfigure(ifa, ip);
                    771:     else
                    772:       ospf_iface_new_vlink(p, ip);
                    773:   }
                    774: 
                    775:   /* Delete remaining ifaces and areas */
                    776:   WALK_LIST_DELSAFE(ifa, ifx, p->iface_list)
                    777:     if (ifa->marked)
                    778:     {
                    779:       ospf_iface_shutdown(ifa);
                    780:       ospf_iface_remove(ifa);
                    781:     }
                    782: 
                    783:   WALK_LIST_DELSAFE(oa, oax, p->area_list)
                    784:     if (oa->marked)
                    785:       ospf_area_remove(oa);
                    786: 
                    787:   ospf_schedule_rtcalc(p);
                    788: 
                    789:   return 1;
                    790: }
                    791: 
                    792: 
                    793: void
                    794: ospf_sh_neigh(struct proto *P, char *iff)
                    795: {
                    796:   struct ospf_proto *p = (struct ospf_proto *) P;
                    797:   struct ospf_iface *ifa = NULL;
                    798:   struct ospf_neighbor *n;
                    799: 
                    800:   if (p->p.proto_state != PS_UP)
                    801:   {
                    802:     cli_msg(-1013, "%s: is not up", p->p.name);
                    803:     cli_msg(0, "");
                    804:     return;
                    805:   }
                    806: 
                    807:   cli_msg(-1013, "%s:", p->p.name);
                    808:   cli_msg(-1013, "%-12s\t%3s\t%-15s\t%-5s\t%-10s %s", "Router ID", "Pri",
                    809:          "     State", "DTime", "Interface", "Router IP");
                    810:   WALK_LIST(ifa, p->iface_list)
                    811:     if ((iff == NULL) || patmatch(iff, ifa->ifname))
                    812:       WALK_LIST(n, ifa->neigh_list)
                    813:        ospf_sh_neigh_info(n);
                    814:   cli_msg(0, "");
                    815: }
                    816: 
                    817: void
                    818: ospf_sh(struct proto *P)
                    819: {
                    820:   struct ospf_proto *p = (struct ospf_proto *) P;
                    821:   struct ospf_area *oa;
                    822:   struct ospf_iface *ifa;
                    823:   struct ospf_neighbor *n;
                    824:   int ifano, nno, adjno, firstfib;
                    825: 
                    826:   if (p->p.proto_state != PS_UP)
                    827:   {
                    828:     cli_msg(-1014, "%s: is not up", p->p.name);
                    829:     cli_msg(0, "");
                    830:     return;
                    831:   }
                    832: 
                    833:   cli_msg(-1014, "%s:", p->p.name);
                    834:   cli_msg(-1014, "RFC1583 compatibility: %s", (p->rfc1583 ? "enabled" : "disabled"));
                    835:   cli_msg(-1014, "Stub router: %s", (p->stub_router ? "Yes" : "No"));
                    836:   cli_msg(-1014, "RT scheduler tick: %d", p->tick);
                    837:   cli_msg(-1014, "Number of areas: %u", p->areano);
                    838:   cli_msg(-1014, "Number of LSAs in DB:\t%u", p->gr->hash_entries);
                    839: 
                    840:   WALK_LIST(oa, p->area_list)
                    841:   {
                    842:     cli_msg(-1014, "\tArea: %R (%u) %s", oa->areaid, oa->areaid,
                    843:            oa->areaid == 0 ? "[BACKBONE]" : "");
                    844:     ifano = 0;
                    845:     nno = 0;
                    846:     adjno = 0;
                    847:     WALK_LIST(ifa, p->iface_list)
                    848:     {
                    849:       if (oa == ifa->oa)
                    850:       {
                    851:        ifano++;
                    852:        WALK_LIST(n, ifa->neigh_list)
                    853:        {
                    854:          nno++;
                    855:          if (n->state == NEIGHBOR_FULL)
                    856:            adjno++;
                    857:        }
                    858:       }
                    859:     }
                    860: 
                    861:     cli_msg(-1014, "\t\tStub:\t%s", oa_is_stub(oa) ? "Yes" : "No");
                    862:     cli_msg(-1014, "\t\tNSSA:\t%s", oa_is_nssa(oa) ? "Yes" : "No");
                    863:     cli_msg(-1014, "\t\tTransit:\t%s", oa->trcap ? "Yes" : "No");
                    864: 
                    865:     if (oa_is_nssa(oa))
                    866:       cli_msg(-1014, "\t\tNSSA translation:\t%s%s", oa->translate ? "Yes" : "No",
                    867:              oa->translate == TRANS_WAIT ? " (run down)" : "");
                    868:     cli_msg(-1014, "\t\tNumber of interfaces:\t%u", ifano);
                    869:     cli_msg(-1014, "\t\tNumber of neighbors:\t%u", nno);
                    870:     cli_msg(-1014, "\t\tNumber of adjacent neighbors:\t%u", adjno);
                    871: 
                    872:     firstfib = 1;
                    873:     FIB_WALK(&oa->net_fib, struct area_net, anet)
                    874:     {
                    875:       if(firstfib)
                    876:       {
                    877:        cli_msg(-1014, "\t\tArea networks:");
                    878:        firstfib = 0;
                    879:       }
                    880:       cli_msg(-1014, "\t\t\t%1N\t%s\t%s", anet->fn.addr,
                    881:                anet->hidden ? "Hidden" : "Advertise", anet->active ? "Active" : "");
                    882:     }
                    883:     FIB_WALK_END;
                    884: 
                    885:     firstfib = 1;
                    886:     FIB_WALK(&oa->enet_fib, struct area_net, anet)
                    887:     {
                    888:       if(firstfib)
                    889:       {
                    890:        cli_msg(-1014, "\t\tArea external networks:");
                    891:        firstfib = 0;
                    892:       }
                    893:       cli_msg(-1014, "\t\t\t%1N\t%s\t%s", anet->fn.addr,
                    894:                anet->hidden ? "Hidden" : "Advertise", anet->active ? "Active" : "");
                    895:     }
                    896:     FIB_WALK_END;
                    897: 
                    898:   }
                    899:   cli_msg(0, "");
                    900: }
                    901: 
                    902: void
                    903: ospf_sh_iface(struct proto *P, char *iff)
                    904: {
                    905:   struct ospf_proto *p = (struct ospf_proto *) P;
                    906:   struct ospf_iface *ifa = NULL;
                    907: 
                    908:   if (p->p.proto_state != PS_UP)
                    909:   {
                    910:     cli_msg(-1015, "%s: is not up", p->p.name);
                    911:     cli_msg(0, "");
                    912:     return;
                    913:   }
                    914: 
                    915:   cli_msg(-1015, "%s:", p->p.name);
                    916:   WALK_LIST(ifa, p->iface_list)
                    917:     if ((iff == NULL) || patmatch(iff, ifa->ifname))
                    918:       ospf_iface_info(ifa);
                    919:   cli_msg(0, "");
                    920: }
                    921: 
                    922: /* lsa_compare_for_state() - Compare function for 'show ospf state'
                    923:  *
                    924:  * First we want to separate network-LSAs and other LSAs (because network-LSAs
                    925:  * will be presented as network nodes and other LSAs together as router nodes)
                    926:  * Network-LSAs are sorted according to network prefix, other LSAs are sorted
                    927:  * according to originating router id (to get all LSA needed to represent one
                    928:  * router node together). Then, according to LSA type, ID and age.
                    929:  *
                    930:  * For OSPFv3, we have to handle also Prefix-LSAs. We would like to put each
                    931:  * immediately after the referenced LSA. We will make faked LSA based on ref_
                    932:  * values
                    933:  */
                    934: 
                    935: static struct ospf_lsa_header *
                    936: fake_lsa_from_prefix_lsa(struct ospf_lsa_header *dst, struct ospf_lsa_header *src,
                    937:                         struct ospf_lsa_prefix *px)
                    938: {
                    939:   dst->age = src->age;
                    940:   dst->type_raw = px->ref_type;
                    941:   dst->id = px->ref_id;
                    942:   dst->rt = px->ref_rt;
                    943:   dst->sn = src->sn;
                    944: 
                    945:   return dst;
                    946: }
                    947: 
                    948: 
                    949: static int lsa_compare_ospf3;
                    950: 
                    951: static int
                    952: lsa_compare_for_state(const void *p1, const void *p2)
                    953: {
                    954:   struct top_hash_entry *he1 = * (struct top_hash_entry **) p1;
                    955:   struct top_hash_entry *he2 = * (struct top_hash_entry **) p2;
                    956:   struct ospf_lsa_header *lsa1 = &(he1->lsa);
                    957:   struct ospf_lsa_header *lsa2 = &(he2->lsa);
                    958:   struct ospf_lsa_header lsatmp1, lsatmp2;
                    959:   u16 lsa1_type = he1->lsa_type;
                    960:   u16 lsa2_type = he2->lsa_type;
                    961: 
                    962:   if (he1->domain < he2->domain)
                    963:     return -1;
                    964:   if (he1->domain > he2->domain)
                    965:     return 1;
                    966: 
                    967: 
                    968:   /* px1 or px2 assumes OSPFv3 */
                    969:   int px1 = (lsa1_type == LSA_T_PREFIX);
                    970:   int px2 = (lsa2_type == LSA_T_PREFIX);
                    971: 
                    972:   if (px1)
                    973:   {
                    974:     lsa1 = fake_lsa_from_prefix_lsa(&lsatmp1, lsa1, he1->lsa_body);
                    975:     lsa1_type = lsa1->type_raw;        /* FIXME: handle unknown ref_type */
                    976:   }
                    977: 
                    978:   if (px2)
                    979:   {
                    980:     lsa2 = fake_lsa_from_prefix_lsa(&lsatmp2, lsa2, he2->lsa_body);
                    981:     lsa2_type = lsa2->type_raw;
                    982:   }
                    983: 
                    984: 
                    985:   int nt1 = (lsa1_type == LSA_T_NET);
                    986:   int nt2 = (lsa2_type == LSA_T_NET);
                    987: 
                    988:   if (nt1 != nt2)
                    989:     return nt1 - nt2;
                    990: 
                    991:   if (nt1)
                    992:   {
                    993:     /* In OSPFv3, networks are named based on ID of DR */
                    994:     if (lsa_compare_ospf3)
                    995:     {
                    996:       if (lsa1->rt < lsa2->rt)
                    997:        return -1;
                    998:       if (lsa1->rt > lsa2->rt)
                    999:        return 1;
                   1000:     }
                   1001: 
                   1002:     /* For OSPFv2, this is IP of the network,
                   1003:        for OSPFv3, this is interface ID */
                   1004:     if (lsa1->id < lsa2->id)
                   1005:       return -1;
                   1006:     if (lsa1->id > lsa2->id)
                   1007:       return 1;
                   1008: 
                   1009:     if (px1 != px2)
                   1010:       return px1 - px2;
                   1011: 
                   1012:     return lsa1->sn - lsa2->sn;
                   1013:   }
                   1014:   else
                   1015:   {
                   1016:     if (lsa1->rt < lsa2->rt)
                   1017:       return -1;
                   1018:     if (lsa1->rt > lsa2->rt)
                   1019:       return 1;
                   1020: 
                   1021:     if (lsa1_type < lsa2_type)
                   1022:       return -1;
                   1023:     if (lsa1_type > lsa2_type)
                   1024:       return 1;
                   1025: 
                   1026:     if (lsa1->id < lsa2->id)
                   1027:       return -1;
                   1028:     if (lsa1->id > lsa2->id)
                   1029:       return 1;
                   1030: 
                   1031:     if (px1 != px2)
                   1032:       return px1 - px2;
                   1033: 
                   1034:     return lsa1->sn - lsa2->sn;
                   1035:   }
                   1036: }
                   1037: 
                   1038: static int
                   1039: ext_compare_for_state(const void *p1, const void *p2)
                   1040: {
                   1041:   struct top_hash_entry * he1 = * (struct top_hash_entry **) p1;
                   1042:   struct top_hash_entry * he2 = * (struct top_hash_entry **) p2;
                   1043:   struct ospf_lsa_header *lsa1 = &(he1->lsa);
                   1044:   struct ospf_lsa_header *lsa2 = &(he2->lsa);
                   1045: 
                   1046:   if (lsa1->rt < lsa2->rt)
                   1047:     return -1;
                   1048:   if (lsa1->rt > lsa2->rt)
                   1049:     return 1;
                   1050: 
                   1051:   if (lsa1->id < lsa2->id)
                   1052:     return -1;
                   1053:   if (lsa1->id > lsa2->id)
                   1054:     return 1;
                   1055: 
                   1056:   return lsa1->sn - lsa2->sn;
                   1057: }
                   1058: 
                   1059: static inline void
                   1060: show_lsa_distance(struct top_hash_entry *he)
                   1061: {
                   1062:   if (he->color == INSPF)
                   1063:     cli_msg(-1016, "\t\tdistance %u", he->dist);
                   1064:   else
                   1065:     cli_msg(-1016, "\t\tunreachable");
                   1066: }
                   1067: 
                   1068: static inline void
                   1069: show_lsa_router(struct ospf_proto *p, struct top_hash_entry *he, int verbose)
                   1070: {
                   1071:   struct ospf_lsa_rt_walk rtl;
                   1072: 
                   1073:   cli_msg(-1016, "");
                   1074:   cli_msg(-1016, "\trouter %R", he->lsa.rt);
                   1075:   show_lsa_distance(he);
                   1076: 
                   1077:   lsa_walk_rt_init(p, he, &rtl);
                   1078:   while (lsa_walk_rt(&rtl))
                   1079:     if (rtl.type == LSART_VLNK)
                   1080:       cli_msg(-1016, "\t\tvlink %R metric %u", rtl.id, rtl.metric);
                   1081: 
                   1082:   lsa_walk_rt_init(p, he, &rtl);
                   1083:   while (lsa_walk_rt(&rtl))
                   1084:     if (rtl.type == LSART_PTP)
                   1085:       cli_msg(-1016, "\t\trouter %R metric %u", rtl.id, rtl.metric);
                   1086: 
                   1087:   lsa_walk_rt_init(p, he, &rtl);
                   1088:   while (lsa_walk_rt(&rtl))
                   1089:     if (rtl.type == LSART_NET)
                   1090:     {
                   1091:       if (ospf_is_v2(p))
                   1092:       {
                   1093:        /* In OSPFv2, we try to find network-LSA to get prefix/pxlen */
                   1094:        struct top_hash_entry *net_he = ospf_hash_find_net2(p->gr, he->domain, rtl.id);
                   1095: 
                   1096:        if (net_he && (net_he->lsa.age < LSA_MAXAGE))
                   1097:        {
                   1098:          struct ospf_lsa_header *net_lsa = &(net_he->lsa);
                   1099:          struct ospf_lsa_net *net_ln = net_he->lsa_body;
                   1100: 
                   1101:          cli_msg(-1016, "\t\tnetwork %I/%d metric %u",
                   1102:                  ipa_from_u32(net_lsa->id & net_ln->optx),
                   1103:                  u32_masklen(net_ln->optx), rtl.metric);
                   1104:        }
                   1105:        else
                   1106:          cli_msg(-1016, "\t\tnetwork [%R] metric %u", rtl.id, rtl.metric);
                   1107:       }
                   1108:       else
                   1109:        cli_msg(-1016, "\t\tnetwork [%R-%u] metric %u", rtl.id, rtl.nif, rtl.metric);
                   1110:     }
                   1111: 
                   1112:   if (ospf_is_v2(p) && verbose)
                   1113:   {
                   1114:     lsa_walk_rt_init(p, he, &rtl);
                   1115:     while (lsa_walk_rt(&rtl))
                   1116:       if (rtl.type == LSART_STUB)
                   1117:        cli_msg(-1016, "\t\tstubnet %I/%d metric %u",
                   1118:                ipa_from_u32(rtl.id), u32_masklen(rtl.data), rtl.metric);
                   1119:   }
                   1120: }
                   1121: 
                   1122: static inline void
                   1123: show_lsa_network(struct top_hash_entry *he, int ospf2)
                   1124: {
                   1125:   struct ospf_lsa_header *lsa = &(he->lsa);
                   1126:   struct ospf_lsa_net *ln = he->lsa_body;
                   1127:   u32 i;
                   1128: 
                   1129:   if (ospf2)
                   1130:   {
                   1131:     cli_msg(-1016, "");
                   1132:     cli_msg(-1016, "\tnetwork %I/%d", ipa_from_u32(lsa->id & ln->optx), u32_masklen(ln->optx));
                   1133:     cli_msg(-1016, "\t\tdr %R", lsa->rt);
                   1134:   }
                   1135:   else
                   1136:   {
                   1137:     cli_msg(-1016, "");
                   1138:     cli_msg(-1016, "\tnetwork [%R-%u]", lsa->rt, lsa->id);
                   1139:   }
                   1140: 
                   1141:   show_lsa_distance(he);
                   1142: 
                   1143:   for (i = 0; i < lsa_net_count(lsa); i++)
                   1144:     cli_msg(-1016, "\t\trouter %R", ln->routers[i]);
                   1145: }
                   1146: 
                   1147: static inline void
                   1148: show_lsa_sum_net(struct top_hash_entry *he, int ospf2, int af)
                   1149: {
                   1150:   net_addr net;
                   1151:   u8 pxopts;
                   1152:   u32 metric;
                   1153: 
                   1154:   lsa_parse_sum_net(he, ospf2, af, &net, &pxopts, &metric);
                   1155:   cli_msg(-1016, "\t\txnetwork %N metric %u", &net, metric);
                   1156: }
                   1157: 
                   1158: static inline void
                   1159: show_lsa_sum_rt(struct top_hash_entry *he, int ospf2)
                   1160: {
                   1161:   u32 metric;
                   1162:   u32 dst_rid;
                   1163:   u32 options;
                   1164: 
                   1165:   lsa_parse_sum_rt(he, ospf2, &dst_rid, &metric, &options);
                   1166:   cli_msg(-1016, "\t\txrouter %R metric %u", dst_rid, metric);
                   1167: }
                   1168: 
                   1169: 
                   1170: static inline void
                   1171: show_lsa_external(struct top_hash_entry *he, int ospf2, int af)
                   1172: {
                   1173:   struct ospf_lsa_ext_local rt;
                   1174:   char str_via[IPA_MAX_TEXT_LENGTH + 8] = "";
                   1175:   char str_tag[16] = "";
                   1176: 
                   1177:   if (he->lsa_type == LSA_T_EXT)
                   1178:     he->domain = 0; /* Unmark the LSA */
                   1179: 
                   1180:   lsa_parse_ext(he, ospf2, af, &rt);
                   1181: 
                   1182:   if (rt.fbit)
                   1183:     bsprintf(str_via, " via %I", rt.fwaddr);
                   1184: 
                   1185:   if (rt.tag)
                   1186:     bsprintf(str_tag, " tag %08x", rt.tag);
                   1187: 
                   1188:   cli_msg(-1016, "\t\t%s %N metric%s %u%s%s",
                   1189:          (he->lsa_type == LSA_T_NSSA) ? "nssa-ext" : "external",
                   1190:          &rt.net, rt.ebit ? "2" : "", rt.metric, str_via, str_tag);
                   1191: }
                   1192: 
                   1193: static inline void
                   1194: show_lsa_prefix(struct top_hash_entry *he, struct top_hash_entry *cnode, int af)
                   1195: {
                   1196:   struct ospf_lsa_prefix *px = he->lsa_body;
                   1197:   u32 *buf;
                   1198:   int i;
                   1199: 
                   1200:   /* We check whether given prefix-LSA is related to the current node */
                   1201:   if ((px->ref_type != cnode->lsa.type_raw) || (px->ref_rt != cnode->lsa.rt))
                   1202:     return;
                   1203: 
                   1204:   if ((px->ref_type == LSA_T_RT) && (px->ref_id != 0))
                   1205:     return;
                   1206: 
                   1207:   if ((px->ref_type == LSA_T_NET) && (px->ref_id != cnode->lsa.id))
                   1208:     return;
                   1209: 
                   1210:   buf = px->rest;
                   1211:   for (i = 0; i < px->pxcount; i++)
                   1212:   {
                   1213:     net_addr net;
                   1214:     u8 pxopts;
                   1215:     u16 metric;
                   1216: 
                   1217:     buf = ospf3_get_prefix(buf, af, &net, &pxopts, &metric);
                   1218: 
                   1219:     if (px->ref_type == LSA_T_RT)
                   1220:       cli_msg(-1016, "\t\tstubnet %N metric %u", &net, metric);
                   1221:     else
                   1222:       cli_msg(-1016, "\t\taddress %N", &net);
                   1223:   }
                   1224: }
                   1225: 
                   1226: void
                   1227: ospf_sh_state(struct proto *P, int verbose, int reachable)
                   1228: {
                   1229:   struct ospf_proto *p = (struct ospf_proto *) P;
                   1230:   int ospf2 = ospf_is_v2(p);
                   1231:   int af = ospf_get_af(p);
                   1232:   uint i, ix, j1, jx;
                   1233:   u32 last_area = 0xFFFFFFFF;
                   1234: 
                   1235:   if (p->p.proto_state != PS_UP)
                   1236:   {
                   1237:     cli_msg(-1016, "%s: is not up", p->p.name);
                   1238:     cli_msg(0, "");
                   1239:     return;
                   1240:   }
                   1241: 
                   1242:   /* We store interesting area-scoped LSAs in array hea and
                   1243:      global-scoped (LSA_T_EXT) LSAs in array hex */
                   1244: 
                   1245:   uint num = p->gr->hash_entries;
                   1246:   struct top_hash_entry *hea[num];
                   1247:   struct top_hash_entry *hex[verbose ? num : 0];
                   1248:   struct top_hash_entry *he;
                   1249:   struct top_hash_entry *cnode = NULL;
                   1250: 
                   1251:   j1 = jx = 0;
                   1252:   WALK_SLIST(he, p->lsal)
                   1253:   {
                   1254:     int accept;
                   1255: 
                   1256:     if (he->lsa.age == LSA_MAXAGE)
                   1257:       continue;
                   1258: 
                   1259:     switch (he->lsa_type)
                   1260:     {
                   1261:     case LSA_T_RT:
                   1262:     case LSA_T_NET:
                   1263:       accept = 1;
                   1264:       break;
                   1265: 
                   1266:     case LSA_T_SUM_NET:
                   1267:     case LSA_T_SUM_RT:
                   1268:     case LSA_T_NSSA:
                   1269:     case LSA_T_PREFIX:
                   1270:       accept = verbose;
                   1271:       break;
                   1272: 
                   1273:     case LSA_T_EXT:
                   1274:       if (verbose)
                   1275:       {
                   1276:        he->domain = 1; /* Abuse domain field to mark the LSA */
                   1277:        hex[jx++] = he;
                   1278:       }
                   1279:       /* fallthrough */
                   1280:     default:
                   1281:       accept = 0;
                   1282:     }
                   1283: 
                   1284:     if (accept)
                   1285:       hea[j1++] = he;
                   1286:   }
                   1287: 
                   1288:   ASSERT(j1 <= num && jx <= num);
                   1289: 
                   1290:   lsa_compare_ospf3 = !ospf2;
                   1291:   qsort(hea, j1, sizeof(struct top_hash_entry *), lsa_compare_for_state);
                   1292:   qsort(hex, jx, sizeof(struct top_hash_entry *), ext_compare_for_state);
                   1293: 
                   1294:   /*
                   1295:    * This code is a bit tricky, we have a primary LSAs (router and
                   1296:    * network) that are presented as a node, and secondary LSAs that
                   1297:    * are presented as a part of a primary node. cnode represents an
                   1298:    * currently opened node (whose header was presented). The LSAs are
                   1299:    * sorted to get secondary LSAs just after related primary LSA (if
                   1300:    * available). We present secondary LSAs only when related primary
                   1301:    * LSA is opened.
                   1302:    *
                   1303:    * AS-external LSAs are stored separately as they might be presented
                   1304:    * several times (for each area when related ASBR is opened). When
                   1305:    * the node is closed, related external routes are presented. We
                   1306:    * also have to take into account that in OSPFv3, there might be
                   1307:    * more router-LSAs and only the first should be considered as a
                   1308:    * primary. This is handled by not closing old router-LSA when next
                   1309:    * one is processed (which is not opened because there is already
                   1310:    * one opened).
                   1311:    */
                   1312: 
                   1313:   ix = 0;
                   1314:   for (i = 0; i < j1; i++)
                   1315:   {
                   1316:     he = hea[i];
                   1317: 
                   1318:     /* If there is no opened node, we open the LSA (if appropriate) or skip to the next one */
                   1319:     if (!cnode)
                   1320:     {
                   1321:       if (((he->lsa_type == LSA_T_RT) || (he->lsa_type == LSA_T_NET))
                   1322:          && ((he->color == INSPF) || !reachable))
                   1323:       {
                   1324:        cnode = he;
                   1325: 
                   1326:        if (he->domain != last_area)
                   1327:        {
                   1328:          cli_msg(-1016, "");
                   1329:          cli_msg(-1016, "area %R", he->domain);
                   1330:          last_area = he->domain;
                   1331:          ix = 0;
                   1332:        }
                   1333:       }
                   1334:       else
                   1335:        continue;
                   1336:     }
                   1337: 
                   1338:     ASSERT(cnode && (he->domain == last_area) && (he->lsa.rt == cnode->lsa.rt));
                   1339: 
                   1340:     switch (he->lsa_type)
                   1341:     {
                   1342:     case LSA_T_RT:
                   1343:       if (he->lsa.id == cnode->lsa.id)
                   1344:        show_lsa_router(p, he, verbose);
                   1345:       break;
                   1346: 
                   1347:     case LSA_T_NET:
                   1348:       show_lsa_network(he, ospf2);
                   1349:       break;
                   1350: 
                   1351:     case LSA_T_SUM_NET:
                   1352:       if (cnode->lsa_type == LSA_T_RT)
                   1353:        show_lsa_sum_net(he, ospf2, af);
                   1354:       break;
                   1355: 
                   1356:     case LSA_T_SUM_RT:
                   1357:       if (cnode->lsa_type == LSA_T_RT)
                   1358:        show_lsa_sum_rt(he, ospf2);
                   1359:       break;
                   1360: 
                   1361:     case LSA_T_EXT:
                   1362:     case LSA_T_NSSA:
                   1363:       show_lsa_external(he, ospf2, af);
                   1364:       break;
                   1365: 
                   1366:     case LSA_T_PREFIX:
                   1367:       show_lsa_prefix(he, cnode, af);
                   1368:       break;
                   1369:     }
                   1370: 
                   1371:     /* In these cases, we close the current node */
                   1372:     if ((i+1 == j1)
                   1373:        || (hea[i+1]->domain != last_area)
                   1374:        || (hea[i+1]->lsa.rt != cnode->lsa.rt)
                   1375:        || (hea[i+1]->lsa_type == LSA_T_NET))
                   1376:     {
                   1377:       while ((ix < jx) && (hex[ix]->lsa.rt < cnode->lsa.rt))
                   1378:        ix++;
                   1379: 
                   1380:       while ((ix < jx) && (hex[ix]->lsa.rt == cnode->lsa.rt))
                   1381:        show_lsa_external(hex[ix++], ospf2, af);
                   1382: 
                   1383:       cnode = NULL;
                   1384:     }
                   1385:   }
                   1386: 
                   1387:   int hdr = 0;
                   1388:   u32 last_rt = 0xFFFFFFFF;
                   1389:   for (ix = 0; ix < jx; ix++)
                   1390:   {
                   1391:     he = hex[ix];
                   1392: 
                   1393:     /* If it is still marked, we show it now. */
                   1394:     if (he->domain)
                   1395:     {
                   1396:       he->domain = 0;
                   1397: 
                   1398:       if ((he->color != INSPF) && reachable)
                   1399:        continue;
                   1400: 
                   1401:       if (!hdr)
                   1402:       {
                   1403:        cli_msg(-1016, "");
                   1404:        cli_msg(-1016, "other ASBRs");
                   1405:        hdr = 1;
                   1406:       }
                   1407: 
                   1408:       if (he->lsa.rt != last_rt)
                   1409:       {
                   1410:        cli_msg(-1016, "");
                   1411:        cli_msg(-1016, "\trouter %R", he->lsa.rt);
                   1412:        last_rt = he->lsa.rt;
                   1413:       }
                   1414: 
                   1415:       show_lsa_external(he, ospf2, af);
                   1416:     }
                   1417:   }
                   1418: 
                   1419:   cli_msg(0, "");
                   1420: }
                   1421: 
                   1422: 
                   1423: static int
                   1424: lsa_compare_for_lsadb(const void *p1, const void *p2)
                   1425: {
                   1426:   struct top_hash_entry * he1 = * (struct top_hash_entry **) p1;
                   1427:   struct top_hash_entry * he2 = * (struct top_hash_entry **) p2;
                   1428:   struct ospf_lsa_header *lsa1 = &(he1->lsa);
                   1429:   struct ospf_lsa_header *lsa2 = &(he2->lsa);
                   1430:   int sc1 = LSA_SCOPE(he1->lsa_type);
                   1431:   int sc2 = LSA_SCOPE(he2->lsa_type);
                   1432: 
                   1433:   if (sc1 != sc2)
                   1434:     return sc2 - sc1;
                   1435: 
                   1436:   if (he1->domain != he2->domain)
                   1437:     return he1->domain - he2->domain;
                   1438: 
                   1439:   if (lsa1->rt != lsa2->rt)
                   1440:     return lsa1->rt - lsa2->rt;
                   1441: 
                   1442:   if (lsa1->id != lsa2->id)
                   1443:     return lsa1->id - lsa2->id;
                   1444: 
                   1445:   if (he1->lsa_type != he2->lsa_type)
                   1446:     return he1->lsa_type - he2->lsa_type;
                   1447: 
                   1448:   return lsa1->sn - lsa2->sn;
                   1449: }
                   1450: 
                   1451: void
                   1452: ospf_sh_lsadb(struct lsadb_show_data *ld)
                   1453: {
                   1454:   struct ospf_proto *p = ld->proto;
                   1455:   uint num = p->gr->hash_entries;
                   1456:   uint i, j;
                   1457:   int last_dscope = -1;
                   1458:   u32 last_domain = 0;
                   1459:   u16 type_mask = ospf_is_v2(p) ?  0x00ff : 0xffff;    /* see lsa_etype() */
                   1460: 
                   1461:   if (p->p.proto_state != PS_UP)
                   1462:   {
                   1463:     cli_msg(-1017, "%s: is not up", p->p.name);
                   1464:     cli_msg(0, "");
                   1465:     return;
                   1466:   }
                   1467: 
                   1468:   if (ld->router == SH_ROUTER_SELF)
                   1469:     ld->router = p->router_id;
                   1470: 
                   1471:   struct top_hash_entry *hea[num];
                   1472:   struct top_hash_entry *he;
                   1473: 
                   1474:   j = 0;
                   1475:   WALK_SLIST(he, p->lsal)
                   1476:     if (he->lsa_body)
                   1477:       hea[j++] = he;
                   1478: 
                   1479:   ASSERT(j <= num);
                   1480: 
                   1481:   qsort(hea, j, sizeof(struct top_hash_entry *), lsa_compare_for_lsadb);
                   1482: 
                   1483:   for (i = 0; i < j; i++)
                   1484:   {
                   1485:     struct ospf_lsa_header *lsa = &(hea[i]->lsa);
                   1486:     u16 lsa_type = lsa->type_raw & type_mask;
                   1487:     u16 dscope = LSA_SCOPE(hea[i]->lsa_type);
                   1488: 
                   1489:     /* Hack: 1 is used for LSA_SCOPE_LINK, fixed by & 0xf000 */
                   1490:     if (ld->scope && (dscope != (ld->scope & 0xf000)))
                   1491:       continue;
                   1492: 
                   1493:     if ((ld->scope == LSA_SCOPE_AREA) && (hea[i]->domain != ld->area))
                   1494:       continue;
                   1495: 
                   1496:     /* For user convenience ignore high nibble */
                   1497:     if (ld->type && ((lsa_type & 0x0fff) != (ld->type & 0x0fff)))
                   1498:       continue;
                   1499: 
                   1500:     if (ld->lsid && (lsa->id != ld->lsid))
                   1501:       continue;
                   1502: 
                   1503:     if (ld->router && (lsa->rt != ld->router))
                   1504:       continue;
                   1505: 
                   1506:     if ((dscope != last_dscope) || (hea[i]->domain != last_domain))
                   1507:     {
                   1508:       cli_msg(-1017, "");
                   1509:       switch (dscope)
                   1510:       {
                   1511:       case LSA_SCOPE_AS:
                   1512:        cli_msg(-1017, "Global");
                   1513:        break;
                   1514: 
                   1515:       case LSA_SCOPE_AREA:
                   1516:        cli_msg(-1017, "Area %R", hea[i]->domain);
                   1517:        break;
                   1518: 
                   1519:       case LSA_SCOPE_LINK:
                   1520:        {
                   1521:          struct iface *ifa = if_find_by_index(hea[i]->domain);
                   1522:          cli_msg(-1017, "Link %s", (ifa != NULL) ? ifa->name : "?");
                   1523:        }
                   1524:        break;
                   1525:       }
                   1526:       cli_msg(-1017, "");
                   1527:       cli_msg(-1017," Type   LS ID           Router          Sequence   Age  Checksum");
                   1528: 
                   1529:       last_dscope = dscope;
                   1530:       last_domain = hea[i]->domain;
                   1531:     }
                   1532: 
                   1533:     cli_msg(-1017," %04x  %-15R %-15R  %08x %5u    %04x",
                   1534:            lsa_type, lsa->id, lsa->rt, lsa->sn, lsa->age, lsa->checksum);
                   1535:   }
                   1536:   cli_msg(0, "");
                   1537: }
                   1538: 
                   1539: 
                   1540: struct protocol proto_ospf = {
                   1541:   .name =              "OSPF",
                   1542:   .template =          "ospf%d",
                   1543:   .class =             PROTOCOL_OSPF,
                   1544:   .preference =                DEF_PREF_OSPF,
                   1545:   .channel_mask =      NB_IP,
                   1546:   .proto_size =                sizeof(struct ospf_proto),
                   1547:   .config_size =       sizeof(struct ospf_config),
                   1548:   .init =              ospf_init,
                   1549:   .dump =              ospf_dump,
                   1550:   .start =             ospf_start,
                   1551:   .shutdown =          ospf_shutdown,
                   1552:   .reconfigure =       ospf_reconfigure,
                   1553:   .get_status =                ospf_get_status,
                   1554:   .get_attr =          ospf_get_attr,
                   1555:   .get_route_info =    ospf_get_route_info
                   1556: };

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