Annotation of embedaddon/quagga/ospfd/ospfd.c, revision 1.1

1.1     ! misho       1: /* OSPF version 2 daemon program.
        !             2:    Copyright (C) 1999, 2000 Toshiaki Takada
        !             3: 
        !             4: This file is part of GNU Zebra.
        !             5: 
        !             6: GNU Zebra is free software; you can redistribute it and/or modify it
        !             7: under the terms of the GNU General Public License as published by the
        !             8: Free Software Foundation; either version 2, or (at your option) any
        !             9: later version.
        !            10: 
        !            11: GNU Zebra is distributed in the hope that it will be useful, but
        !            12: WITHOUT ANY WARRANTY; without even the implied warranty of
        !            13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
        !            14: General Public License for more details.
        !            15: 
        !            16: You should have received a copy of the GNU General Public License
        !            17: along with GNU Zebra; see the file COPYING.  If not, write to the Free
        !            18: Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
        !            19: 02111-1307, USA.  */
        !            20: 
        !            21: #include <zebra.h>
        !            22: 
        !            23: #include "thread.h"
        !            24: #include "vty.h"
        !            25: #include "command.h"
        !            26: #include "linklist.h"
        !            27: #include "prefix.h"
        !            28: #include "table.h"
        !            29: #include "if.h"
        !            30: #include "memory.h"
        !            31: #include "stream.h"
        !            32: #include "log.h"
        !            33: #include "sockunion.h"          /* for inet_aton () */
        !            34: #include "zclient.h"
        !            35: #include "plist.h"
        !            36: #include "sockopt.h"
        !            37: 
        !            38: #include "ospfd/ospfd.h"
        !            39: #include "ospfd/ospf_network.h"
        !            40: #include "ospfd/ospf_interface.h"
        !            41: #include "ospfd/ospf_ism.h"
        !            42: #include "ospfd/ospf_asbr.h"
        !            43: #include "ospfd/ospf_lsa.h"
        !            44: #include "ospfd/ospf_lsdb.h"
        !            45: #include "ospfd/ospf_neighbor.h"
        !            46: #include "ospfd/ospf_nsm.h"
        !            47: #include "ospfd/ospf_spf.h"
        !            48: #include "ospfd/ospf_packet.h"
        !            49: #include "ospfd/ospf_dump.h"
        !            50: #include "ospfd/ospf_zebra.h"
        !            51: #include "ospfd/ospf_abr.h"
        !            52: #include "ospfd/ospf_flood.h"
        !            53: #include "ospfd/ospf_route.h"
        !            54: #include "ospfd/ospf_ase.h"
        !            55: 
        !            56: 
        !            57: 
        !            58: /* OSPF process wide configuration. */
        !            59: static struct ospf_master ospf_master;
        !            60: 
        !            61: /* OSPF process wide configuration pointer to export. */
        !            62: struct ospf_master *om;
        !            63: 
        !            64: extern struct zclient *zclient;
        !            65: extern struct in_addr router_id_zebra;
        !            66: 
        !            67: 
        !            68: static void ospf_remove_vls_through_area (struct ospf *, struct ospf_area *);
        !            69: static void ospf_network_free (struct ospf *, struct ospf_network *);
        !            70: static void ospf_area_free (struct ospf_area *);
        !            71: static void ospf_network_run (struct prefix *, struct ospf_area *);
        !            72: static void ospf_network_run_interface (struct prefix *, struct ospf_area *,
        !            73:                                         struct interface *);
        !            74: static int ospf_network_match_iface (const struct connected *,
        !            75:                                     const struct prefix *);
        !            76: static void ospf_finish_final (struct ospf *);
        !            77: 
        !            78: #define OSPF_EXTERNAL_LSA_ORIGINATE_DELAY 1
        !            79: 
        !            80: void
        !            81: ospf_router_id_update (struct ospf *ospf)
        !            82: {
        !            83:   struct in_addr router_id, router_id_old;
        !            84:   struct ospf_interface *oi;
        !            85:   struct interface *ifp;
        !            86:   struct listnode *node;
        !            87: 
        !            88:   if (IS_DEBUG_OSPF_EVENT)
        !            89:     zlog_debug ("Router-ID[OLD:%s]: Update", inet_ntoa (ospf->router_id));
        !            90: 
        !            91:   router_id_old = ospf->router_id;
        !            92: 
        !            93:   /* Select the router ID based on these priorities:
        !            94:        1. Statically assigned router ID is always the first choice.
        !            95:        2. If there is no statically assigned router ID, then try to stick
        !            96:           with the most recent value, since changing router ID's is very
        !            97:          disruptive.
        !            98:        3. Last choice: just go with whatever the zebra daemon recommends.
        !            99:   */
        !           100:   if (ospf->router_id_static.s_addr != 0)
        !           101:     router_id = ospf->router_id_static;
        !           102:   else if (ospf->router_id.s_addr != 0)
        !           103:     router_id = ospf->router_id;
        !           104:   else
        !           105:     router_id = router_id_zebra;
        !           106: 
        !           107:   ospf->router_id = router_id;
        !           108:   
        !           109:   if (IS_DEBUG_OSPF_EVENT)
        !           110:     zlog_debug ("Router-ID[NEW:%s]: Update", inet_ntoa (ospf->router_id));
        !           111: 
        !           112:   if (!IPV4_ADDR_SAME (&router_id_old, &router_id))
        !           113:     {
        !           114:       for (ALL_LIST_ELEMENTS_RO (ospf->oiflist, node, oi))
        !           115:         /* Update self-neighbor's router_id. */
        !           116:         oi->nbr_self->router_id = router_id;
        !           117: 
        !           118:       /* If AS-external-LSA is queued, then flush those LSAs. */
        !           119:       if (router_id_old.s_addr == 0 && ospf->external_origin)
        !           120:        {
        !           121:          int type;
        !           122:          /* Originate each redistributed external route. */
        !           123:          for (type = 0; type < ZEBRA_ROUTE_MAX; type++)
        !           124:            if (ospf->external_origin & (1 << type))
        !           125:              thread_add_event (master, ospf_external_lsa_originate_timer,
        !           126:                                ospf, type);
        !           127:          /* Originate Deafult. */
        !           128:          if (ospf->external_origin & (1 << ZEBRA_ROUTE_MAX))
        !           129:            thread_add_event (master, ospf_default_originate_timer, ospf, 0);
        !           130: 
        !           131:          ospf->external_origin = 0;
        !           132:        }
        !           133: 
        !           134:       /* update router-lsa's for each area */
        !           135:       ospf_router_lsa_update (ospf);
        !           136:       
        !           137:       /* update ospf_interface's */
        !           138:       for (ALL_LIST_ELEMENTS_RO (om->iflist, node, ifp))
        !           139:         ospf_if_update (ospf, ifp);
        !           140:     }
        !           141: }
        !           142: 
        !           143: /* For OSPF area sort by area id. */
        !           144: static int
        !           145: ospf_area_id_cmp (struct ospf_area *a1, struct ospf_area *a2)
        !           146: {
        !           147:   if (ntohl (a1->area_id.s_addr) > ntohl (a2->area_id.s_addr))
        !           148:     return 1;
        !           149:   if (ntohl (a1->area_id.s_addr) < ntohl (a2->area_id.s_addr))
        !           150:     return -1;
        !           151:   return 0;
        !           152: }
        !           153: 
        !           154: /* Allocate new ospf structure. */
        !           155: static struct ospf *
        !           156: ospf_new (void)
        !           157: {
        !           158:   int i;
        !           159: 
        !           160:   struct ospf *new = XCALLOC (MTYPE_OSPF_TOP, sizeof (struct ospf));
        !           161: 
        !           162:   new->router_id.s_addr = htonl (0);
        !           163:   new->router_id_static.s_addr = htonl (0);
        !           164: 
        !           165:   new->abr_type = OSPF_ABR_DEFAULT;
        !           166:   new->oiflist = list_new ();
        !           167:   new->vlinks = list_new ();
        !           168:   new->areas = list_new ();
        !           169:   new->areas->cmp = (int (*)(void *, void *)) ospf_area_id_cmp;
        !           170:   new->networks = route_table_init ();
        !           171:   new->nbr_nbma = route_table_init ();
        !           172: 
        !           173:   new->lsdb = ospf_lsdb_new ();
        !           174: 
        !           175:   new->default_originate = DEFAULT_ORIGINATE_NONE;
        !           176: 
        !           177:   new->passive_interface_default = OSPF_IF_ACTIVE;
        !           178:   
        !           179:   new->new_external_route = route_table_init ();
        !           180:   new->old_external_route = route_table_init ();
        !           181:   new->external_lsas = route_table_init ();
        !           182:   
        !           183:   new->stub_router_startup_time = OSPF_STUB_ROUTER_UNCONFIGURED;
        !           184:   new->stub_router_shutdown_time = OSPF_STUB_ROUTER_UNCONFIGURED;
        !           185:   
        !           186:   /* Distribute parameter init. */
        !           187:   for (i = 0; i <= ZEBRA_ROUTE_MAX; i++)
        !           188:     {
        !           189:       new->dmetric[i].type = -1;
        !           190:       new->dmetric[i].value = -1;
        !           191:     }
        !           192:   new->default_metric = -1;
        !           193:   new->ref_bandwidth = OSPF_DEFAULT_REF_BANDWIDTH;
        !           194: 
        !           195:   /* SPF timer value init. */
        !           196:   new->spf_delay = OSPF_SPF_DELAY_DEFAULT;
        !           197:   new->spf_holdtime = OSPF_SPF_HOLDTIME_DEFAULT;
        !           198:   new->spf_max_holdtime = OSPF_SPF_MAX_HOLDTIME_DEFAULT;
        !           199:   new->spf_hold_multiplier = 1;
        !           200: 
        !           201:   /* MaxAge init. */
        !           202:   new->maxage_delay = OSFP_LSA_MAXAGE_REMOVE_DELAY_DEFAULT;
        !           203:   new->maxage_lsa = list_new ();
        !           204:   new->t_maxage_walker =
        !           205:     thread_add_timer (master, ospf_lsa_maxage_walker,
        !           206:                       new, OSPF_LSA_MAXAGE_CHECK_INTERVAL);
        !           207: 
        !           208:   /* Distance table init. */
        !           209:   new->distance_table = route_table_init ();
        !           210: 
        !           211:   new->lsa_refresh_queue.index = 0;
        !           212:   new->lsa_refresh_interval = OSPF_LSA_REFRESH_INTERVAL_DEFAULT;
        !           213:   new->t_lsa_refresher = thread_add_timer (master, ospf_lsa_refresh_walker,
        !           214:                                           new, new->lsa_refresh_interval);
        !           215:   new->lsa_refresher_started = quagga_time (NULL);
        !           216: 
        !           217:   if ((new->fd = ospf_sock_init()) < 0)
        !           218:     {
        !           219:       zlog_err("ospf_new: fatal error: ospf_sock_init was unable to open "
        !           220:               "a socket");
        !           221:       exit(1);
        !           222:     }
        !           223:   new->maxsndbuflen = getsockopt_so_sendbuf (new->fd);
        !           224:   if (IS_DEBUG_OSPF (zebra, ZEBRA_INTERFACE))
        !           225:     zlog_debug ("%s: starting with OSPF send buffer size %d",
        !           226:       __func__, new->maxsndbuflen);
        !           227:   if ((new->ibuf = stream_new(OSPF_MAX_PACKET_SIZE+1)) == NULL)
        !           228:     {
        !           229:       zlog_err("ospf_new: fatal error: stream_new(%u) failed allocating ibuf",
        !           230:               OSPF_MAX_PACKET_SIZE+1);
        !           231:       exit(1);
        !           232:     }
        !           233:   new->t_read = thread_add_read (master, ospf_read, new, new->fd);
        !           234:   new->oi_write_q = list_new ();
        !           235:   
        !           236:   return new;
        !           237: }
        !           238: 
        !           239: struct ospf *
        !           240: ospf_lookup ()
        !           241: {
        !           242:   if (listcount (om->ospf) == 0)
        !           243:     return NULL;
        !           244: 
        !           245:   return listgetdata (listhead (om->ospf));
        !           246: }
        !           247: 
        !           248: static void
        !           249: ospf_add (struct ospf *ospf)
        !           250: {
        !           251:   listnode_add (om->ospf, ospf);
        !           252: }
        !           253: 
        !           254: static void
        !           255: ospf_delete (struct ospf *ospf)
        !           256: {
        !           257:   listnode_delete (om->ospf, ospf);
        !           258: }
        !           259: 
        !           260: struct ospf *
        !           261: ospf_get ()
        !           262: {
        !           263:   struct ospf *ospf;
        !           264: 
        !           265:   ospf = ospf_lookup ();
        !           266:   if (ospf == NULL)
        !           267:     {
        !           268:       ospf = ospf_new ();
        !           269:       ospf_add (ospf);
        !           270: 
        !           271:       if (ospf->router_id_static.s_addr == 0)
        !           272:        ospf_router_id_update (ospf);
        !           273: 
        !           274: #ifdef HAVE_OPAQUE_LSA
        !           275:       ospf_opaque_type11_lsa_init (ospf);
        !           276: #endif /* HAVE_OPAQUE_LSA */
        !           277:     }
        !           278: 
        !           279:   return ospf;
        !           280: }
        !           281: 
        !           282: /* Handle the second half of deferred shutdown. This is called either
        !           283:  * from the deferred-shutdown timer thread, or directly through
        !           284:  * ospf_deferred_shutdown_check.
        !           285:  *
        !           286:  * Function is to cleanup G-R state, if required then call ospf_finish_final
        !           287:  * to complete shutdown of this ospf instance. Possibly exit if the
        !           288:  * whole process is being shutdown and this was the last OSPF instance.
        !           289:  */
        !           290: static void
        !           291: ospf_deferred_shutdown_finish (struct ospf *ospf)
        !           292: {
        !           293:   ospf->stub_router_shutdown_time = OSPF_STUB_ROUTER_UNCONFIGURED;  
        !           294:   OSPF_TIMER_OFF (ospf->t_deferred_shutdown);
        !           295:   
        !           296:   ospf_finish_final (ospf);
        !           297:   
        !           298:   /* *ospf is now invalid */
        !           299:   
        !           300:   /* ospfd being shut-down? If so, was this the last ospf instance? */
        !           301:   if (CHECK_FLAG (om->options, OSPF_MASTER_SHUTDOWN)
        !           302:       && (listcount (om->ospf) == 0))
        !           303:     exit (0);
        !           304: 
        !           305:   return;
        !           306: }
        !           307: 
        !           308: /* Timer thread for G-R */
        !           309: static int
        !           310: ospf_deferred_shutdown_timer (struct thread *t)
        !           311: {
        !           312:   struct ospf *ospf = THREAD_ARG(t);
        !           313:   
        !           314:   ospf_deferred_shutdown_finish (ospf);
        !           315:   
        !           316:   return 0;
        !           317: }
        !           318: 
        !           319: /* Check whether deferred-shutdown must be scheduled, otherwise call
        !           320:  * down directly into second-half of instance shutdown.
        !           321:  */
        !           322: static void
        !           323: ospf_deferred_shutdown_check (struct ospf *ospf)
        !           324: {
        !           325:   unsigned long timeout;
        !           326:   struct listnode *ln;
        !           327:   struct ospf_area *area;
        !           328:   
        !           329:   /* deferred shutdown already running? */
        !           330:   if (ospf->t_deferred_shutdown)
        !           331:     return;
        !           332:   
        !           333:   /* Should we try push out max-metric LSAs? */
        !           334:   if (ospf->stub_router_shutdown_time != OSPF_STUB_ROUTER_UNCONFIGURED)
        !           335:     {
        !           336:       for (ALL_LIST_ELEMENTS_RO (ospf->areas, ln, area))
        !           337:         {
        !           338:           SET_FLAG (area->stub_router_state, OSPF_AREA_ADMIN_STUB_ROUTED);
        !           339:           
        !           340:           if (!CHECK_FLAG (area->stub_router_state, OSPF_AREA_IS_STUB_ROUTED))
        !           341:             ospf_router_lsa_update_area (area);
        !           342:         }
        !           343:       timeout = ospf->stub_router_shutdown_time;
        !           344:     }
        !           345:   else
        !           346:     {
        !           347:       /* No timer needed */
        !           348:       ospf_deferred_shutdown_finish (ospf);
        !           349:       return;
        !           350:     }
        !           351:   
        !           352:   OSPF_TIMER_ON (ospf->t_deferred_shutdown, ospf_deferred_shutdown_timer,
        !           353:                  timeout);
        !           354:   return;
        !           355: }
        !           356: 
        !           357: /* Shut down the entire process */
        !           358: void
        !           359: ospf_terminate (void)
        !           360: {
        !           361:   struct ospf *ospf;
        !           362:   struct listnode *node, *nnode;
        !           363:   
        !           364:   /* shutdown already in progress */
        !           365:   if (CHECK_FLAG (om->options, OSPF_MASTER_SHUTDOWN))
        !           366:     return;
        !           367:   
        !           368:   SET_FLAG (om->options, OSPF_MASTER_SHUTDOWN);
        !           369: 
        !           370:   /* exit immediately if OSPF not actually running */
        !           371:   if (listcount(om->ospf) == 0)
        !           372:     exit(0);
        !           373: 
        !           374:   for (ALL_LIST_ELEMENTS (om->ospf, node, nnode, ospf))
        !           375:     ospf_finish (ospf);
        !           376: 
        !           377:   /* Deliberately go back up, hopefully to thread scheduler, as
        !           378:    * One or more ospf_finish()'s may have deferred shutdown to a timer
        !           379:    * thread
        !           380:    */
        !           381: }
        !           382: 
        !           383: void
        !           384: ospf_finish (struct ospf *ospf)
        !           385: {
        !           386:   /* let deferred shutdown decide */
        !           387:   ospf_deferred_shutdown_check (ospf);
        !           388:       
        !           389:   /* if ospf_deferred_shutdown returns, then ospf_finish_final is
        !           390:    * deferred to expiry of G-S timer thread. Return back up, hopefully
        !           391:    * to thread scheduler.
        !           392:    */
        !           393:   return;
        !           394: }
        !           395: 
        !           396: /* Final cleanup of ospf instance */
        !           397: static void
        !           398: ospf_finish_final (struct ospf *ospf)
        !           399: {
        !           400:   struct route_node *rn;
        !           401:   struct ospf_nbr_nbma *nbr_nbma;
        !           402:   struct ospf_lsa *lsa;
        !           403:   struct ospf_interface *oi;
        !           404:   struct ospf_area *area;
        !           405:   struct ospf_vl_data *vl_data;
        !           406:   struct listnode *node, *nnode;
        !           407:   int i;
        !           408: 
        !           409: #ifdef HAVE_OPAQUE_LSA
        !           410:   ospf_opaque_type11_lsa_term (ospf);
        !           411: #endif /* HAVE_OPAQUE_LSA */
        !           412:   
        !           413:   /* be nice if this worked, but it doesn't */
        !           414:   /*ospf_flush_self_originated_lsas_now (ospf);*/
        !           415:   
        !           416:   /* Unregister redistribution */
        !           417:   for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
        !           418:     ospf_redistribute_unset (ospf, i);
        !           419:   ospf_redistribute_default_unset (ospf);
        !           420: 
        !           421:   for (ALL_LIST_ELEMENTS (ospf->areas, node, nnode, area))
        !           422:     ospf_remove_vls_through_area (ospf, area);
        !           423:   
        !           424:   for (ALL_LIST_ELEMENTS (ospf->vlinks, node, nnode, vl_data))
        !           425:     ospf_vl_delete (ospf, vl_data);
        !           426:   
        !           427:   list_delete (ospf->vlinks);
        !           428: 
        !           429:   /* Reset interface. */
        !           430:   for (ALL_LIST_ELEMENTS (ospf->oiflist, node, nnode, oi))
        !           431:     ospf_if_free (oi);
        !           432: 
        !           433:   /* Clear static neighbors */
        !           434:   for (rn = route_top (ospf->nbr_nbma); rn; rn = route_next (rn))
        !           435:     if ((nbr_nbma = rn->info))
        !           436:       {
        !           437:        OSPF_POLL_TIMER_OFF (nbr_nbma->t_poll);
        !           438: 
        !           439:        if (nbr_nbma->nbr)
        !           440:          {
        !           441:            nbr_nbma->nbr->nbr_nbma = NULL;
        !           442:            nbr_nbma->nbr = NULL;
        !           443:          }
        !           444: 
        !           445:        if (nbr_nbma->oi)
        !           446:          {
        !           447:            listnode_delete (nbr_nbma->oi->nbr_nbma, nbr_nbma);
        !           448:            nbr_nbma->oi = NULL;
        !           449:          }
        !           450: 
        !           451:        XFREE (MTYPE_OSPF_NEIGHBOR_STATIC, nbr_nbma);
        !           452:       }
        !           453: 
        !           454:   route_table_finish (ospf->nbr_nbma);
        !           455: 
        !           456:   /* Clear networks and Areas. */
        !           457:   for (rn = route_top (ospf->networks); rn; rn = route_next (rn))
        !           458:     {
        !           459:       struct ospf_network *network;
        !           460: 
        !           461:       if ((network = rn->info) != NULL)
        !           462:        {
        !           463:          ospf_network_free (ospf, network);
        !           464:          rn->info = NULL;
        !           465:          route_unlock_node (rn);
        !           466:        }
        !           467:     }
        !           468: 
        !           469:   for (ALL_LIST_ELEMENTS (ospf->areas, node, nnode, area))
        !           470:     {
        !           471:       listnode_delete (ospf->areas, area);
        !           472:       ospf_area_free (area);
        !           473:     }
        !           474: 
        !           475:   /* Cancel all timers. */
        !           476:   OSPF_TIMER_OFF (ospf->t_external_lsa);
        !           477:   OSPF_TIMER_OFF (ospf->t_spf_calc);
        !           478:   OSPF_TIMER_OFF (ospf->t_ase_calc);
        !           479:   OSPF_TIMER_OFF (ospf->t_maxage);
        !           480:   OSPF_TIMER_OFF (ospf->t_maxage_walker);
        !           481:   OSPF_TIMER_OFF (ospf->t_abr_task);
        !           482:   OSPF_TIMER_OFF (ospf->t_asbr_check);
        !           483:   OSPF_TIMER_OFF (ospf->t_distribute_update);
        !           484:   OSPF_TIMER_OFF (ospf->t_lsa_refresher);
        !           485:   OSPF_TIMER_OFF (ospf->t_read);
        !           486:   OSPF_TIMER_OFF (ospf->t_write);
        !           487: #ifdef HAVE_OPAQUE_LSA
        !           488:   OSPF_TIMER_OFF (ospf->t_opaque_lsa_self);
        !           489: #endif
        !           490: 
        !           491:   close (ospf->fd);
        !           492:   stream_free(ospf->ibuf);
        !           493:    
        !           494: #ifdef HAVE_OPAQUE_LSA
        !           495:   LSDB_LOOP (OPAQUE_AS_LSDB (ospf), rn, lsa)
        !           496:     ospf_discard_from_db (ospf, ospf->lsdb, lsa);
        !           497: #endif /* HAVE_OPAQUE_LSA */
        !           498:   LSDB_LOOP (EXTERNAL_LSDB (ospf), rn, lsa)
        !           499:     ospf_discard_from_db (ospf, ospf->lsdb, lsa);
        !           500: 
        !           501:   ospf_lsdb_delete_all (ospf->lsdb);
        !           502:   ospf_lsdb_free (ospf->lsdb);
        !           503: 
        !           504:   for (ALL_LIST_ELEMENTS (ospf->maxage_lsa, node, nnode, lsa))
        !           505:     ospf_lsa_unlock (&lsa); /* maxage_lsa */
        !           506: 
        !           507:   list_delete (ospf->maxage_lsa);
        !           508: 
        !           509:   if (ospf->old_table)
        !           510:     ospf_route_table_free (ospf->old_table);
        !           511:   if (ospf->new_table)
        !           512:     {
        !           513:       ospf_route_delete (ospf->new_table);
        !           514:       ospf_route_table_free (ospf->new_table);
        !           515:     }
        !           516:   if (ospf->old_rtrs)
        !           517:     ospf_rtrs_free (ospf->old_rtrs);
        !           518:   if (ospf->new_rtrs)
        !           519:     ospf_rtrs_free (ospf->new_rtrs);
        !           520:   if (ospf->new_external_route)
        !           521:     {
        !           522:       ospf_route_delete (ospf->new_external_route);
        !           523:       ospf_route_table_free (ospf->new_external_route);
        !           524:     }
        !           525:   if (ospf->old_external_route)
        !           526:     {
        !           527:       ospf_route_delete (ospf->old_external_route);
        !           528:       ospf_route_table_free (ospf->old_external_route);
        !           529:     }
        !           530:   if (ospf->external_lsas)
        !           531:     {
        !           532:       ospf_ase_external_lsas_finish (ospf->external_lsas);
        !           533:     }
        !           534: 
        !           535:   list_delete (ospf->areas);
        !           536:   
        !           537:   for (i = ZEBRA_ROUTE_SYSTEM; i <= ZEBRA_ROUTE_MAX; i++)
        !           538:     if (EXTERNAL_INFO (i) != NULL)
        !           539:       for (rn = route_top (EXTERNAL_INFO (i)); rn; rn = route_next (rn))
        !           540:        {
        !           541:          if (rn->info == NULL)
        !           542:            continue;
        !           543:          
        !           544:          XFREE (MTYPE_OSPF_EXTERNAL_INFO, rn->info);
        !           545:          rn->info = NULL;
        !           546:          route_unlock_node (rn);
        !           547:        }
        !           548: 
        !           549:   ospf_distance_reset (ospf);
        !           550:   route_table_finish (ospf->distance_table);
        !           551: 
        !           552:   ospf_delete (ospf);
        !           553: 
        !           554:   XFREE (MTYPE_OSPF_TOP, ospf);
        !           555: }
        !           556: 
        !           557: 
        !           558: /* allocate new OSPF Area object */
        !           559: static struct ospf_area *
        !           560: ospf_area_new (struct ospf *ospf, struct in_addr area_id)
        !           561: {
        !           562:   struct ospf_area *new;
        !           563: 
        !           564:   /* Allocate new config_network. */
        !           565:   new = XCALLOC (MTYPE_OSPF_AREA, sizeof (struct ospf_area));
        !           566: 
        !           567:   new->ospf = ospf;
        !           568: 
        !           569:   new->area_id = area_id;
        !           570: 
        !           571:   new->external_routing = OSPF_AREA_DEFAULT;
        !           572:   new->default_cost = 1;
        !           573:   new->auth_type = OSPF_AUTH_NULL;
        !           574:   
        !           575:   /* New LSDB init. */
        !           576:   new->lsdb = ospf_lsdb_new ();
        !           577: 
        !           578:   /* Self-originated LSAs initialize. */
        !           579:   new->router_lsa_self = NULL;
        !           580: 
        !           581: #ifdef HAVE_OPAQUE_LSA
        !           582:   ospf_opaque_type10_lsa_init (new);
        !           583: #endif /* HAVE_OPAQUE_LSA */
        !           584: 
        !           585:   new->oiflist = list_new ();
        !           586:   new->ranges = route_table_init ();
        !           587: 
        !           588:   if (area_id.s_addr == OSPF_AREA_BACKBONE)
        !           589:     ospf->backbone = new;
        !           590: 
        !           591:   return new;
        !           592: }
        !           593: 
        !           594: static void
        !           595: ospf_area_free (struct ospf_area *area)
        !           596: {
        !           597:   struct route_node *rn;
        !           598:   struct ospf_lsa *lsa;
        !           599: 
        !           600:   /* Free LSDBs. */
        !           601:   LSDB_LOOP (ROUTER_LSDB (area), rn, lsa)
        !           602:     ospf_discard_from_db (area->ospf, area->lsdb, lsa);
        !           603:   LSDB_LOOP (NETWORK_LSDB (area), rn, lsa)
        !           604:     ospf_discard_from_db (area->ospf, area->lsdb, lsa);
        !           605:   LSDB_LOOP (SUMMARY_LSDB (area), rn, lsa)
        !           606:     ospf_discard_from_db (area->ospf, area->lsdb, lsa);
        !           607:   LSDB_LOOP (ASBR_SUMMARY_LSDB (area), rn, lsa)
        !           608:     ospf_discard_from_db (area->ospf, area->lsdb, lsa);
        !           609: 
        !           610:   LSDB_LOOP (NSSA_LSDB (area), rn, lsa)
        !           611:     ospf_discard_from_db (area->ospf, area->lsdb, lsa);
        !           612: #ifdef HAVE_OPAQUE_LSA
        !           613:   LSDB_LOOP (OPAQUE_AREA_LSDB (area), rn, lsa)
        !           614:     ospf_discard_from_db (area->ospf, area->lsdb, lsa);
        !           615:   LSDB_LOOP (OPAQUE_LINK_LSDB (area), rn, lsa)
        !           616:     ospf_discard_from_db (area->ospf, area->lsdb, lsa);
        !           617: #endif /* HAVE_OPAQUE_LSA */
        !           618: 
        !           619:   ospf_lsdb_delete_all (area->lsdb);
        !           620:   ospf_lsdb_free (area->lsdb);
        !           621: 
        !           622:   ospf_lsa_unlock (&area->router_lsa_self);
        !           623:   
        !           624:   route_table_finish (area->ranges);
        !           625:   list_delete (area->oiflist);
        !           626: 
        !           627:   if (EXPORT_NAME (area))
        !           628:     free (EXPORT_NAME (area));
        !           629: 
        !           630:   if (IMPORT_NAME (area))
        !           631:     free (IMPORT_NAME (area));
        !           632: 
        !           633:   /* Cancel timer. */
        !           634:   OSPF_TIMER_OFF (area->t_stub_router);
        !           635: #ifdef HAVE_OPAQUE_LSA
        !           636:   OSPF_TIMER_OFF (area->t_opaque_lsa_self);
        !           637: #endif /* HAVE_OPAQUE_LSA */
        !           638:   
        !           639:   if (OSPF_IS_AREA_BACKBONE (area))
        !           640:     area->ospf->backbone = NULL;
        !           641: 
        !           642:   XFREE (MTYPE_OSPF_AREA, area);
        !           643: }
        !           644: 
        !           645: void
        !           646: ospf_area_check_free (struct ospf *ospf, struct in_addr area_id)
        !           647: {
        !           648:   struct ospf_area *area;
        !           649: 
        !           650:   area = ospf_area_lookup_by_area_id (ospf, area_id);
        !           651:   if (area &&
        !           652:       listcount (area->oiflist) == 0 &&
        !           653:       area->ranges->top == NULL &&
        !           654:       area->shortcut_configured == OSPF_SHORTCUT_DEFAULT &&
        !           655:       area->external_routing == OSPF_AREA_DEFAULT &&
        !           656:       area->no_summary == 0 &&
        !           657:       area->default_cost == 1 &&
        !           658:       EXPORT_NAME (area) == NULL &&
        !           659:       IMPORT_NAME (area) == NULL &&
        !           660:       area->auth_type == OSPF_AUTH_NULL)
        !           661:     {
        !           662:       listnode_delete (ospf->areas, area);
        !           663:       ospf_area_free (area);
        !           664:     }
        !           665: }
        !           666: 
        !           667: struct ospf_area *
        !           668: ospf_area_get (struct ospf *ospf, struct in_addr area_id, int format)
        !           669: {
        !           670:   struct ospf_area *area;
        !           671:   
        !           672:   area = ospf_area_lookup_by_area_id (ospf, area_id);
        !           673:   if (!area)
        !           674:     {
        !           675:       area = ospf_area_new (ospf, area_id);
        !           676:       area->format = format;
        !           677:       listnode_add_sort (ospf->areas, area);
        !           678:       ospf_check_abr_status (ospf);  
        !           679:     }
        !           680: 
        !           681:   return area;
        !           682: }
        !           683: 
        !           684: struct ospf_area *
        !           685: ospf_area_lookup_by_area_id (struct ospf *ospf, struct in_addr area_id)
        !           686: {
        !           687:   struct ospf_area *area;
        !           688:   struct listnode *node;
        !           689: 
        !           690:   for (ALL_LIST_ELEMENTS_RO (ospf->areas, node, area))
        !           691:     if (IPV4_ADDR_SAME (&area->area_id, &area_id))
        !           692:       return area;
        !           693: 
        !           694:   return NULL;
        !           695: }
        !           696: 
        !           697: void
        !           698: ospf_area_add_if (struct ospf_area *area, struct ospf_interface *oi)
        !           699: {
        !           700:   listnode_add (area->oiflist, oi);
        !           701: }
        !           702: 
        !           703: void
        !           704: ospf_area_del_if (struct ospf_area *area, struct ospf_interface *oi)
        !           705: {
        !           706:   listnode_delete (area->oiflist, oi);
        !           707: }
        !           708: 
        !           709: 
        !           710: /* Config network statement related functions. */
        !           711: static struct ospf_network *
        !           712: ospf_network_new (struct in_addr area_id, int format)
        !           713: {
        !           714:   struct ospf_network *new;
        !           715:   new = XCALLOC (MTYPE_OSPF_NETWORK, sizeof (struct ospf_network));
        !           716: 
        !           717:   new->area_id = area_id;
        !           718:   new->format = format;
        !           719:   
        !           720:   return new;
        !           721: }
        !           722: 
        !           723: static void
        !           724: ospf_network_free (struct ospf *ospf, struct ospf_network *network)
        !           725: {
        !           726:   ospf_area_check_free (ospf, network->area_id);
        !           727:   ospf_schedule_abr_task (ospf);
        !           728:   XFREE (MTYPE_OSPF_NETWORK, network);
        !           729: }
        !           730: 
        !           731: int
        !           732: ospf_network_set (struct ospf *ospf, struct prefix_ipv4 *p,
        !           733:                  struct in_addr area_id)
        !           734: {
        !           735:   struct ospf_network *network;
        !           736:   struct ospf_area *area;
        !           737:   struct route_node *rn;
        !           738:   struct external_info *ei;
        !           739:   int ret = OSPF_AREA_ID_FORMAT_ADDRESS;
        !           740: 
        !           741:   rn = route_node_get (ospf->networks, (struct prefix *)p);
        !           742:   if (rn->info)
        !           743:     {
        !           744:       /* There is already same network statement. */
        !           745:       route_unlock_node (rn);
        !           746:       return 0;
        !           747:     }
        !           748: 
        !           749:   rn->info = network = ospf_network_new (area_id, ret);
        !           750:   area = ospf_area_get (ospf, area_id, ret);
        !           751: 
        !           752:   /* Run network config now. */
        !           753:   ospf_network_run ((struct prefix *)p, area);
        !           754: 
        !           755:   /* Update connected redistribute. */
        !           756:   if (ospf_is_type_redistributed (ZEBRA_ROUTE_CONNECT))
        !           757:     if (EXTERNAL_INFO (ZEBRA_ROUTE_CONNECT))
        !           758:       for (rn = route_top (EXTERNAL_INFO (ZEBRA_ROUTE_CONNECT));
        !           759:           rn; rn = route_next (rn))
        !           760:        if ((ei = rn->info) != NULL)
        !           761:          if (ospf_external_info_find_lsa (ospf, &ei->p))
        !           762:            if (!ospf_distribute_check_connected (ospf, ei))
        !           763:              ospf_external_lsa_flush (ospf, ei->type, &ei->p,
        !           764:                                       ei->ifindex /*, ei->nexthop */);
        !           765: 
        !           766:   ospf_area_check_free (ospf, area_id);
        !           767: 
        !           768:   return 1;
        !           769: }
        !           770: 
        !           771: int
        !           772: ospf_network_unset (struct ospf *ospf, struct prefix_ipv4 *p,
        !           773:                    struct in_addr area_id)
        !           774: {
        !           775:   struct route_node *rn;
        !           776:   struct ospf_network *network;
        !           777:   struct external_info *ei;
        !           778:   struct listnode *node, *nnode;
        !           779:   struct ospf_interface *oi;
        !           780: 
        !           781:   rn = route_node_lookup (ospf->networks, (struct prefix *)p);
        !           782:   if (rn == NULL)
        !           783:     return 0;
        !           784: 
        !           785:   network = rn->info;
        !           786:   route_unlock_node (rn);
        !           787:   if (!IPV4_ADDR_SAME (&area_id, &network->area_id))
        !           788:     return 0;
        !           789: 
        !           790:   ospf_network_free (ospf, rn->info);
        !           791:   rn->info = NULL;
        !           792:   route_unlock_node (rn);      /* initial reference */
        !           793: 
        !           794:   /* Find interfaces that not configured already.  */
        !           795:   for (ALL_LIST_ELEMENTS (ospf->oiflist, node, nnode, oi))
        !           796:     {
        !           797:       int found = 0;
        !           798:       struct connected *co = oi->connected;
        !           799:       
        !           800:       if (oi->type == OSPF_IFTYPE_VIRTUALLINK)
        !           801:         continue;
        !           802:       
        !           803:       for (rn = route_top (ospf->networks); rn; rn = route_next (rn))
        !           804:         {
        !           805:           if (rn->info == NULL)
        !           806:             continue;
        !           807:           
        !           808:           if (ospf_network_match_iface(co,&rn->p))
        !           809:             {
        !           810:               found = 1;
        !           811:               route_unlock_node (rn);
        !           812:               break;
        !           813:             }
        !           814:         }
        !           815: 
        !           816:       if (found == 0)
        !           817:         ospf_if_free (oi);
        !           818:     }
        !           819:   
        !           820:   /* Update connected redistribute. */
        !           821:   if (ospf_is_type_redistributed (ZEBRA_ROUTE_CONNECT))
        !           822:     if (EXTERNAL_INFO (ZEBRA_ROUTE_CONNECT))
        !           823:       for (rn = route_top (EXTERNAL_INFO (ZEBRA_ROUTE_CONNECT));
        !           824:           rn; rn = route_next (rn))
        !           825:        if ((ei = rn->info) != NULL)
        !           826:          if (!ospf_external_info_find_lsa (ospf, &ei->p))
        !           827:            if (ospf_distribute_check_connected (ospf, ei))
        !           828:              ospf_external_lsa_originate (ospf, ei);
        !           829: 
        !           830:   return 1;
        !           831: }
        !           832: 
        !           833: /* Check whether interface matches given network
        !           834:  * returns: 1, true. 0, false
        !           835:  */
        !           836: static int
        !           837: ospf_network_match_iface(const struct connected *co, const struct prefix *net)
        !           838: {
        !           839:   /* new approach: more elegant and conceptually clean */
        !           840:   return prefix_match(net, CONNECTED_PREFIX(co));
        !           841: }
        !           842: 
        !           843: static void
        !           844: ospf_network_run_interface (struct prefix *p, struct ospf_area *area,
        !           845:                             struct interface *ifp)
        !           846: {
        !           847:   struct listnode *cnode;
        !           848:   struct connected *co;
        !           849:   
        !           850:   if (memcmp (ifp->name, "VLINK", 5) == 0)
        !           851:     return;
        !           852:   
        !           853:   /* if interface prefix is match specified prefix,
        !           854:      then create socket and join multicast group. */
        !           855:   for (ALL_LIST_ELEMENTS_RO (ifp->connected, cnode, co))
        !           856:     {
        !           857: 
        !           858:       if (CHECK_FLAG(co->flags,ZEBRA_IFA_SECONDARY))
        !           859:         continue;
        !           860: 
        !           861:       if (p->family == co->address->family 
        !           862:          && ! ospf_if_table_lookup(ifp, co->address)
        !           863:           && ospf_network_match_iface(co,p))
        !           864:         {
        !           865:            struct ospf_interface *oi;
        !           866:             
        !           867:             oi = ospf_if_new (area->ospf, ifp, co->address);
        !           868:             oi->connected = co;
        !           869:             
        !           870:             oi->area = area;
        !           871: 
        !           872:             oi->params = ospf_lookup_if_params (ifp, oi->address->u.prefix4);
        !           873:             oi->output_cost = ospf_if_get_output_cost (oi);
        !           874:             
        !           875:             /* Add pseudo neighbor. */
        !           876:             ospf_nbr_add_self (oi);
        !           877: 
        !           878:             /* Relate ospf interface to ospf instance. */
        !           879:             oi->ospf = area->ospf;
        !           880: 
        !           881:             /* update network type as interface flag */
        !           882:             /* If network type is specified previously,
        !           883:                skip network type setting. */
        !           884:             oi->type = IF_DEF_PARAMS (ifp)->type;
        !           885:             
        !           886:             ospf_area_add_if (oi->area, oi);
        !           887:             
        !           888:             /* if router_id is not configured, dont bring up
        !           889:              * interfaces.
        !           890:              * ospf_router_id_update() will call ospf_if_update
        !           891:              * whenever r-id is configured instead.
        !           892:              */
        !           893:             if ((area->ospf->router_id.s_addr != 0)
        !           894:                 && if_is_operative (ifp)) 
        !           895:               ospf_if_up (oi);
        !           896:           }
        !           897:     }
        !           898: }
        !           899: 
        !           900: static void
        !           901: ospf_network_run (struct prefix *p, struct ospf_area *area)
        !           902: {
        !           903:   struct interface *ifp;
        !           904:   struct listnode *node;
        !           905: 
        !           906:   /* Schedule Router ID Update. */
        !           907:   if (area->ospf->router_id.s_addr == 0)
        !           908:     ospf_router_id_update (area->ospf);
        !           909:   
        !           910:   /* Get target interface. */
        !           911:   for (ALL_LIST_ELEMENTS_RO (om->iflist, node, ifp))
        !           912:     ospf_network_run_interface (p, area, ifp);
        !           913: }
        !           914: 
        !           915: void
        !           916: ospf_ls_upd_queue_empty (struct ospf_interface *oi)
        !           917: {
        !           918:   struct route_node *rn;
        !           919:   struct listnode *node, *nnode;
        !           920:   struct list *lst;
        !           921:   struct ospf_lsa *lsa;
        !           922: 
        !           923:   /* empty ls update queue */
        !           924:   for (rn = route_top (oi->ls_upd_queue); rn;
        !           925:        rn = route_next (rn))
        !           926:     if ((lst = (struct list *) rn->info))
        !           927:       {
        !           928:        for (ALL_LIST_ELEMENTS (lst, node, nnode, lsa))
        !           929:           ospf_lsa_unlock (&lsa); /* oi->ls_upd_queue */
        !           930:        list_free (lst);
        !           931:        rn->info = NULL;
        !           932:       }
        !           933:   
        !           934:   /* remove update event */
        !           935:   if (oi->t_ls_upd_event)
        !           936:     {
        !           937:       thread_cancel (oi->t_ls_upd_event);
        !           938:       oi->t_ls_upd_event = NULL;
        !           939:     }
        !           940: }
        !           941: 
        !           942: void
        !           943: ospf_if_update (struct ospf *ospf, struct interface *ifp)
        !           944: {
        !           945:   struct route_node *rn;
        !           946:   struct ospf_network *network;
        !           947:   struct ospf_area *area;
        !           948:   
        !           949:   if (!ospf)
        !           950:     ospf = ospf_lookup ();
        !           951: 
        !           952:   /* OSPF must be on and Router-ID must be configured. */
        !           953:   if (!ospf || ospf->router_id.s_addr == 0)
        !           954:     return;
        !           955:   
        !           956:   /* Run each netowrk for this interface. */
        !           957:   for (rn = route_top (ospf->networks); rn; rn = route_next (rn))
        !           958:     if (rn->info != NULL)
        !           959:       {
        !           960:         network = (struct ospf_network *) rn->info;
        !           961:         area = ospf_area_get (ospf, network->area_id, network->format);
        !           962:         ospf_network_run_interface (&rn->p, area, ifp);
        !           963:       }
        !           964: }
        !           965: 
        !           966: void
        !           967: ospf_remove_vls_through_area (struct ospf *ospf, struct ospf_area *area)
        !           968: {
        !           969:   struct listnode *node, *nnode;
        !           970:   struct ospf_vl_data *vl_data;
        !           971: 
        !           972:   for (ALL_LIST_ELEMENTS (ospf->vlinks, node, nnode, vl_data))
        !           973:     if (IPV4_ADDR_SAME (&vl_data->vl_area_id, &area->area_id))
        !           974:       ospf_vl_delete (ospf, vl_data);
        !           975: }
        !           976: 
        !           977: 
        !           978: static const struct message ospf_area_type_msg[] =
        !           979: {
        !           980:   { OSPF_AREA_DEFAULT, "Default" },
        !           981:   { OSPF_AREA_STUB,     "Stub" },
        !           982:   { OSPF_AREA_NSSA,     "NSSA" },
        !           983: };
        !           984: static const int ospf_area_type_msg_max = OSPF_AREA_TYPE_MAX;
        !           985: 
        !           986: static void
        !           987: ospf_area_type_set (struct ospf_area *area, int type)
        !           988: {
        !           989:   struct listnode *node;
        !           990:   struct ospf_interface *oi;
        !           991: 
        !           992:   if (area->external_routing == type)
        !           993:     {
        !           994:       if (IS_DEBUG_OSPF_EVENT)
        !           995:        zlog_debug ("Area[%s]: Types are the same, ignored.",
        !           996:                   inet_ntoa (area->area_id));
        !           997:       return;
        !           998:     }
        !           999: 
        !          1000:   area->external_routing = type;
        !          1001: 
        !          1002:   if (IS_DEBUG_OSPF_EVENT)
        !          1003:     zlog_debug ("Area[%s]: Configured as %s", inet_ntoa (area->area_id),
        !          1004:               LOOKUP (ospf_area_type_msg, type));
        !          1005: 
        !          1006:   switch (area->external_routing)
        !          1007:     {
        !          1008:     case OSPF_AREA_DEFAULT:
        !          1009:       for (ALL_LIST_ELEMENTS_RO (area->oiflist, node, oi))
        !          1010:         if (oi->nbr_self != NULL)
        !          1011:           {
        !          1012:            UNSET_FLAG (oi->nbr_self->options, OSPF_OPTION_NP);
        !          1013:            SET_FLAG (oi->nbr_self->options, OSPF_OPTION_E);
        !          1014:           }
        !          1015:       break;
        !          1016:     case OSPF_AREA_STUB:
        !          1017:       for (ALL_LIST_ELEMENTS_RO (area->oiflist, node, oi))
        !          1018:         if (oi->nbr_self != NULL)
        !          1019:           {
        !          1020:             if (IS_DEBUG_OSPF_EVENT)
        !          1021:               zlog_debug ("setting options on %s accordingly", IF_NAME (oi));
        !          1022:             UNSET_FLAG (oi->nbr_self->options, OSPF_OPTION_NP);
        !          1023:             UNSET_FLAG (oi->nbr_self->options, OSPF_OPTION_E);
        !          1024:             if (IS_DEBUG_OSPF_EVENT)
        !          1025:               zlog_debug ("options set on %s: %x",
        !          1026:                          IF_NAME (oi), OPTIONS (oi));
        !          1027:           }
        !          1028:       break;
        !          1029:     case OSPF_AREA_NSSA:
        !          1030:       for (ALL_LIST_ELEMENTS_RO (area->oiflist, node, oi))
        !          1031:         if (oi->nbr_self != NULL)
        !          1032:           {
        !          1033:             zlog_debug ("setting nssa options on %s accordingly", IF_NAME (oi));
        !          1034:             UNSET_FLAG (oi->nbr_self->options, OSPF_OPTION_E);
        !          1035:             SET_FLAG (oi->nbr_self->options, OSPF_OPTION_NP);
        !          1036:             zlog_debug ("options set on %s: %x", IF_NAME (oi), OPTIONS (oi));
        !          1037:           }
        !          1038:       break;
        !          1039:     default:
        !          1040:       break;
        !          1041:     }
        !          1042: 
        !          1043:   ospf_router_lsa_update_area (area);
        !          1044:   ospf_schedule_abr_task (area->ospf);
        !          1045: }
        !          1046: 
        !          1047: int
        !          1048: ospf_area_shortcut_set (struct ospf *ospf, struct ospf_area *area, int mode)
        !          1049: {
        !          1050:   if (area->shortcut_configured == mode)
        !          1051:     return 0;
        !          1052: 
        !          1053:   area->shortcut_configured = mode;
        !          1054:   ospf_router_lsa_update_area (area);
        !          1055:   ospf_schedule_abr_task (ospf);
        !          1056: 
        !          1057:   ospf_area_check_free (ospf, area->area_id);
        !          1058: 
        !          1059:   return 1;
        !          1060: }
        !          1061: 
        !          1062: int
        !          1063: ospf_area_shortcut_unset (struct ospf *ospf, struct ospf_area *area)
        !          1064: {
        !          1065:   area->shortcut_configured = OSPF_SHORTCUT_DEFAULT;
        !          1066:   ospf_router_lsa_update_area (area);
        !          1067:   ospf_area_check_free (ospf, area->area_id);
        !          1068:   ospf_schedule_abr_task (ospf);
        !          1069: 
        !          1070:   return 1;
        !          1071: }
        !          1072: 
        !          1073: static int
        !          1074: ospf_area_vlink_count (struct ospf *ospf, struct ospf_area *area)
        !          1075: {
        !          1076:   struct ospf_vl_data *vl;
        !          1077:   struct listnode *node;
        !          1078:   int count = 0;
        !          1079: 
        !          1080:   for (ALL_LIST_ELEMENTS_RO (ospf->vlinks, node, vl))
        !          1081:     if (IPV4_ADDR_SAME (&vl->vl_area_id, &area->area_id))
        !          1082:       count++;
        !          1083: 
        !          1084:   return count;
        !          1085: }
        !          1086: 
        !          1087: int
        !          1088: ospf_area_stub_set (struct ospf *ospf, struct in_addr area_id)
        !          1089: {
        !          1090:   struct ospf_area *area;
        !          1091:   int format = OSPF_AREA_ID_FORMAT_ADDRESS;
        !          1092: 
        !          1093:   area = ospf_area_get (ospf, area_id, format);
        !          1094:   if (ospf_area_vlink_count (ospf, area))
        !          1095:     return 0;
        !          1096: 
        !          1097:   if (area->external_routing != OSPF_AREA_STUB)
        !          1098:     ospf_area_type_set (area, OSPF_AREA_STUB);
        !          1099: 
        !          1100:   return 1;
        !          1101: }
        !          1102: 
        !          1103: int
        !          1104: ospf_area_stub_unset (struct ospf *ospf, struct in_addr area_id)
        !          1105: {
        !          1106:   struct ospf_area *area;
        !          1107: 
        !          1108:   area = ospf_area_lookup_by_area_id (ospf, area_id);
        !          1109:   if (area == NULL)
        !          1110:     return 1;
        !          1111: 
        !          1112:   if (area->external_routing == OSPF_AREA_STUB)
        !          1113:     ospf_area_type_set (area, OSPF_AREA_DEFAULT);
        !          1114: 
        !          1115:   ospf_area_check_free (ospf, area_id);
        !          1116: 
        !          1117:   return 1;
        !          1118: }
        !          1119: 
        !          1120: int
        !          1121: ospf_area_no_summary_set (struct ospf *ospf, struct in_addr area_id)
        !          1122: {
        !          1123:   struct ospf_area *area;
        !          1124:   int format = OSPF_AREA_ID_FORMAT_ADDRESS;
        !          1125: 
        !          1126:   area = ospf_area_get (ospf, area_id, format);
        !          1127:   area->no_summary = 1;
        !          1128: 
        !          1129:   return 1;
        !          1130: }
        !          1131: 
        !          1132: int
        !          1133: ospf_area_no_summary_unset (struct ospf *ospf, struct in_addr area_id)
        !          1134: {
        !          1135:   struct ospf_area *area;
        !          1136: 
        !          1137:   area = ospf_area_lookup_by_area_id (ospf, area_id);
        !          1138:   if (area == NULL)
        !          1139:     return 0;
        !          1140: 
        !          1141:   area->no_summary = 0;
        !          1142:   ospf_area_check_free (ospf, area_id);
        !          1143: 
        !          1144:   return 1;
        !          1145: }
        !          1146: 
        !          1147: int
        !          1148: ospf_area_nssa_set (struct ospf *ospf, struct in_addr area_id)
        !          1149: {
        !          1150:   struct ospf_area *area;
        !          1151:   int format = OSPF_AREA_ID_FORMAT_ADDRESS;
        !          1152: 
        !          1153:   area = ospf_area_get (ospf, area_id, format);
        !          1154:   if (ospf_area_vlink_count (ospf, area))
        !          1155:     return 0;
        !          1156: 
        !          1157:   if (area->external_routing != OSPF_AREA_NSSA)
        !          1158:     {
        !          1159:       ospf_area_type_set (area, OSPF_AREA_NSSA);
        !          1160:       ospf->anyNSSA++;
        !          1161:     }
        !          1162: 
        !          1163:   /* set NSSA area defaults */
        !          1164:   area->no_summary = 0;
        !          1165:   area->NSSATranslatorRole = OSPF_NSSA_ROLE_CANDIDATE;
        !          1166:   area->NSSATranslatorState = OSPF_NSSA_TRANSLATE_DISABLED;
        !          1167:   area->NSSATranslatorStabilityInterval = OSPF_NSSA_TRANS_STABLE_DEFAULT;
        !          1168: 
        !          1169:   return 1;
        !          1170: }
        !          1171: 
        !          1172: int
        !          1173: ospf_area_nssa_unset (struct ospf *ospf, struct in_addr area_id)
        !          1174: {
        !          1175:   struct ospf_area *area;
        !          1176: 
        !          1177:   area = ospf_area_lookup_by_area_id (ospf, area_id);
        !          1178:   if (area == NULL)
        !          1179:     return 0;
        !          1180: 
        !          1181:   if (area->external_routing == OSPF_AREA_NSSA)
        !          1182:     {
        !          1183:       ospf->anyNSSA--;
        !          1184:       ospf_area_type_set (area, OSPF_AREA_DEFAULT);
        !          1185:     }
        !          1186: 
        !          1187:   ospf_area_check_free (ospf, area_id);
        !          1188: 
        !          1189:   return 1;
        !          1190: }
        !          1191: 
        !          1192: int
        !          1193: ospf_area_nssa_translator_role_set (struct ospf *ospf, struct in_addr area_id,
        !          1194:                                    int role)
        !          1195: {
        !          1196:   struct ospf_area *area;
        !          1197: 
        !          1198:   area = ospf_area_lookup_by_area_id (ospf, area_id);
        !          1199:   if (area == NULL)
        !          1200:     return 0;
        !          1201: 
        !          1202:   area->NSSATranslatorRole = role;
        !          1203: 
        !          1204:   return 1;
        !          1205: }
        !          1206: 
        !          1207: /* XXX: unused? Leave for symmetry? */
        !          1208: static int
        !          1209: ospf_area_nssa_translator_role_unset (struct ospf *ospf,
        !          1210:                                      struct in_addr area_id)
        !          1211: {
        !          1212:   struct ospf_area *area;
        !          1213: 
        !          1214:   area = ospf_area_lookup_by_area_id (ospf, area_id);
        !          1215:   if (area == NULL)
        !          1216:     return 0;
        !          1217: 
        !          1218:   area->NSSATranslatorRole = OSPF_NSSA_ROLE_CANDIDATE;
        !          1219: 
        !          1220:   ospf_area_check_free (ospf, area_id);
        !          1221: 
        !          1222:   return 1;
        !          1223: }
        !          1224: 
        !          1225: int
        !          1226: ospf_area_export_list_set (struct ospf *ospf,
        !          1227:                           struct ospf_area *area, const char *list_name)
        !          1228: {
        !          1229:   struct access_list *list;
        !          1230:   list = access_list_lookup (AFI_IP, list_name);
        !          1231: 
        !          1232:   EXPORT_LIST (area) = list;
        !          1233: 
        !          1234:   if (EXPORT_NAME (area))
        !          1235:     free (EXPORT_NAME (area));
        !          1236: 
        !          1237:   EXPORT_NAME (area) = strdup (list_name);
        !          1238:   ospf_schedule_abr_task (ospf);
        !          1239: 
        !          1240:   return 1;
        !          1241: }
        !          1242: 
        !          1243: int
        !          1244: ospf_area_export_list_unset (struct ospf *ospf, struct ospf_area * area)
        !          1245: {
        !          1246: 
        !          1247:   EXPORT_LIST (area) = 0;
        !          1248: 
        !          1249:   if (EXPORT_NAME (area))
        !          1250:     free (EXPORT_NAME (area));
        !          1251: 
        !          1252:   EXPORT_NAME (area) = NULL;
        !          1253: 
        !          1254:   ospf_area_check_free (ospf, area->area_id);
        !          1255:   
        !          1256:   ospf_schedule_abr_task (ospf);
        !          1257: 
        !          1258:   return 1;
        !          1259: }
        !          1260: 
        !          1261: int
        !          1262: ospf_area_import_list_set (struct ospf *ospf, struct ospf_area *area, 
        !          1263:                            const char *name)
        !          1264: {
        !          1265:   struct access_list *list;
        !          1266:   list = access_list_lookup (AFI_IP, name);
        !          1267: 
        !          1268:   IMPORT_LIST (area) = list;
        !          1269: 
        !          1270:   if (IMPORT_NAME (area))
        !          1271:     free (IMPORT_NAME (area));
        !          1272: 
        !          1273:   IMPORT_NAME (area) = strdup (name);
        !          1274:   ospf_schedule_abr_task (ospf);
        !          1275: 
        !          1276:   return 1;
        !          1277: }
        !          1278: 
        !          1279: int
        !          1280: ospf_area_import_list_unset (struct ospf *ospf, struct ospf_area * area)
        !          1281: {
        !          1282:   IMPORT_LIST (area) = 0;
        !          1283: 
        !          1284:   if (IMPORT_NAME (area))
        !          1285:     free (IMPORT_NAME (area));
        !          1286: 
        !          1287:   IMPORT_NAME (area) = NULL;
        !          1288:   ospf_area_check_free (ospf, area->area_id);
        !          1289: 
        !          1290:   ospf_schedule_abr_task (ospf);
        !          1291: 
        !          1292:   return 1;
        !          1293: }
        !          1294: 
        !          1295: int
        !          1296: ospf_timers_refresh_set (struct ospf *ospf, int interval)
        !          1297: {
        !          1298:   int time_left;
        !          1299: 
        !          1300:   if (ospf->lsa_refresh_interval == interval)
        !          1301:     return 1;
        !          1302: 
        !          1303:   time_left = ospf->lsa_refresh_interval -
        !          1304:     (quagga_time (NULL) - ospf->lsa_refresher_started);
        !          1305:   
        !          1306:   if (time_left > interval)
        !          1307:     {
        !          1308:       OSPF_TIMER_OFF (ospf->t_lsa_refresher);
        !          1309:       ospf->t_lsa_refresher =
        !          1310:        thread_add_timer (master, ospf_lsa_refresh_walker, ospf, interval);
        !          1311:     }
        !          1312:   ospf->lsa_refresh_interval = interval;
        !          1313: 
        !          1314:   return 1;
        !          1315: }
        !          1316: 
        !          1317: int
        !          1318: ospf_timers_refresh_unset (struct ospf *ospf)
        !          1319: {
        !          1320:   int time_left;
        !          1321: 
        !          1322:   time_left = ospf->lsa_refresh_interval -
        !          1323:     (quagga_time (NULL) - ospf->lsa_refresher_started);
        !          1324: 
        !          1325:   if (time_left > OSPF_LSA_REFRESH_INTERVAL_DEFAULT)
        !          1326:     {
        !          1327:       OSPF_TIMER_OFF (ospf->t_lsa_refresher);
        !          1328:       ospf->t_lsa_refresher =
        !          1329:        thread_add_timer (master, ospf_lsa_refresh_walker, ospf,
        !          1330:                          OSPF_LSA_REFRESH_INTERVAL_DEFAULT);
        !          1331:     }
        !          1332: 
        !          1333:   ospf->lsa_refresh_interval = OSPF_LSA_REFRESH_INTERVAL_DEFAULT;
        !          1334: 
        !          1335:   return 1;
        !          1336: }
        !          1337: 
        !          1338: 
        !          1339: static struct ospf_nbr_nbma *
        !          1340: ospf_nbr_nbma_new (void)
        !          1341: {
        !          1342:   struct ospf_nbr_nbma *nbr_nbma;
        !          1343: 
        !          1344:   nbr_nbma = XCALLOC (MTYPE_OSPF_NEIGHBOR_STATIC,
        !          1345:                      sizeof (struct ospf_nbr_nbma));
        !          1346: 
        !          1347:   nbr_nbma->priority = OSPF_NEIGHBOR_PRIORITY_DEFAULT;
        !          1348:   nbr_nbma->v_poll = OSPF_POLL_INTERVAL_DEFAULT;
        !          1349: 
        !          1350:   return nbr_nbma;
        !          1351: }
        !          1352: 
        !          1353: static void
        !          1354: ospf_nbr_nbma_free (struct ospf_nbr_nbma *nbr_nbma)
        !          1355: {
        !          1356:   XFREE (MTYPE_OSPF_NEIGHBOR_STATIC, nbr_nbma);
        !          1357: }
        !          1358: 
        !          1359: static void
        !          1360: ospf_nbr_nbma_delete (struct ospf *ospf, struct ospf_nbr_nbma *nbr_nbma)
        !          1361: {
        !          1362:   struct route_node *rn;
        !          1363:   struct prefix_ipv4 p;
        !          1364: 
        !          1365:   p.family = AF_INET;
        !          1366:   p.prefix = nbr_nbma->addr;
        !          1367:   p.prefixlen = IPV4_MAX_BITLEN;
        !          1368: 
        !          1369:   rn = route_node_lookup (ospf->nbr_nbma, (struct prefix *)&p);
        !          1370:   if (rn)
        !          1371:     {
        !          1372:       ospf_nbr_nbma_free (rn->info);
        !          1373:       rn->info = NULL;
        !          1374:       route_unlock_node (rn);
        !          1375:       route_unlock_node (rn);
        !          1376:     }
        !          1377: }
        !          1378: 
        !          1379: static void
        !          1380: ospf_nbr_nbma_down (struct ospf_nbr_nbma *nbr_nbma)
        !          1381: {
        !          1382:   OSPF_TIMER_OFF (nbr_nbma->t_poll);
        !          1383: 
        !          1384:   if (nbr_nbma->nbr)
        !          1385:     {
        !          1386:       nbr_nbma->nbr->nbr_nbma = NULL;
        !          1387:       OSPF_NSM_EVENT_EXECUTE (nbr_nbma->nbr, NSM_KillNbr);
        !          1388:     }
        !          1389: 
        !          1390:   if (nbr_nbma->oi)
        !          1391:     listnode_delete (nbr_nbma->oi->nbr_nbma, nbr_nbma);
        !          1392: }
        !          1393: 
        !          1394: static void
        !          1395: ospf_nbr_nbma_add (struct ospf_nbr_nbma *nbr_nbma,
        !          1396:                   struct ospf_interface *oi)
        !          1397: {
        !          1398:   struct ospf_neighbor *nbr;
        !          1399:   struct route_node *rn;
        !          1400:   struct prefix p;
        !          1401: 
        !          1402:   if (oi->type != OSPF_IFTYPE_NBMA)
        !          1403:     return;
        !          1404: 
        !          1405:   if (nbr_nbma->nbr != NULL)
        !          1406:     return;
        !          1407: 
        !          1408:   if (IPV4_ADDR_SAME (&oi->nbr_self->address.u.prefix4, &nbr_nbma->addr))
        !          1409:     return;
        !          1410:       
        !          1411:   nbr_nbma->oi = oi;
        !          1412:   listnode_add (oi->nbr_nbma, nbr_nbma);
        !          1413: 
        !          1414:   /* Get neighbor information from table. */
        !          1415:   p.family = AF_INET;
        !          1416:   p.prefixlen = IPV4_MAX_BITLEN;
        !          1417:   p.u.prefix4 = nbr_nbma->addr;
        !          1418: 
        !          1419:   rn = route_node_get (oi->nbrs, (struct prefix *)&p);
        !          1420:   if (rn->info)
        !          1421:     {
        !          1422:       nbr = rn->info;
        !          1423:       nbr->nbr_nbma = nbr_nbma;
        !          1424:       nbr_nbma->nbr = nbr;
        !          1425: 
        !          1426:       route_unlock_node (rn);
        !          1427:     }
        !          1428:   else
        !          1429:     {
        !          1430:       nbr = rn->info = ospf_nbr_new (oi);
        !          1431:       nbr->state = NSM_Down;
        !          1432:       nbr->src = nbr_nbma->addr;
        !          1433:       nbr->nbr_nbma = nbr_nbma;
        !          1434:       nbr->priority = nbr_nbma->priority;
        !          1435:       nbr->address = p;
        !          1436: 
        !          1437:       nbr_nbma->nbr = nbr;
        !          1438: 
        !          1439:       OSPF_NSM_EVENT_EXECUTE (nbr, NSM_Start);
        !          1440:     }
        !          1441: }
        !          1442: 
        !          1443: void
        !          1444: ospf_nbr_nbma_if_update (struct ospf *ospf, struct ospf_interface *oi)
        !          1445: {
        !          1446:   struct ospf_nbr_nbma *nbr_nbma;
        !          1447:   struct route_node *rn;
        !          1448:   struct prefix_ipv4 p;
        !          1449: 
        !          1450:   if (oi->type != OSPF_IFTYPE_NBMA)
        !          1451:     return;
        !          1452: 
        !          1453:   for (rn = route_top (ospf->nbr_nbma); rn; rn = route_next (rn))
        !          1454:     if ((nbr_nbma = rn->info))
        !          1455:       if (nbr_nbma->oi == NULL && nbr_nbma->nbr == NULL)
        !          1456:        {
        !          1457:          p.family = AF_INET;
        !          1458:          p.prefix = nbr_nbma->addr;
        !          1459:          p.prefixlen = IPV4_MAX_BITLEN;
        !          1460: 
        !          1461:          if (prefix_match (oi->address, (struct prefix *)&p))
        !          1462:            ospf_nbr_nbma_add (nbr_nbma, oi);
        !          1463:        }
        !          1464: }
        !          1465: 
        !          1466: struct ospf_nbr_nbma *
        !          1467: ospf_nbr_nbma_lookup (struct ospf *ospf, struct in_addr nbr_addr)
        !          1468: {
        !          1469:   struct route_node *rn;
        !          1470:   struct prefix_ipv4 p;
        !          1471: 
        !          1472:   p.family = AF_INET;
        !          1473:   p.prefix = nbr_addr;
        !          1474:   p.prefixlen = IPV4_MAX_BITLEN;
        !          1475: 
        !          1476:   rn = route_node_lookup (ospf->nbr_nbma, (struct prefix *)&p);
        !          1477:   if (rn)
        !          1478:     {
        !          1479:       route_unlock_node (rn);
        !          1480:       return rn->info;
        !          1481:     }
        !          1482:   return NULL;
        !          1483: }
        !          1484: 
        !          1485: struct ospf_nbr_nbma *
        !          1486: ospf_nbr_nbma_lookup_next (struct ospf *ospf, struct in_addr *addr, int first)
        !          1487: {
        !          1488: #if 0
        !          1489:   struct ospf_nbr_nbma *nbr_nbma;
        !          1490:   struct listnode *node;
        !          1491: #endif
        !          1492: 
        !          1493:   if (ospf == NULL)
        !          1494:     return NULL;
        !          1495: 
        !          1496: #if 0
        !          1497:   for (ALL_LIST_ELEMENTS_RO (ospf->nbr_nbma, node, nbr_nbma))
        !          1498:     {
        !          1499:       if (first)
        !          1500:        {
        !          1501:          *addr = nbr_nbma->addr;
        !          1502:          return nbr_nbma;
        !          1503:        }
        !          1504:       else if (ntohl (nbr_nbma->addr.s_addr) > ntohl (addr->s_addr))
        !          1505:        {
        !          1506:          *addr = nbr_nbma->addr;
        !          1507:          return nbr_nbma;
        !          1508:        }
        !          1509:     }
        !          1510: #endif
        !          1511:   return NULL;
        !          1512: }
        !          1513: 
        !          1514: int
        !          1515: ospf_nbr_nbma_set (struct ospf *ospf, struct in_addr nbr_addr)
        !          1516: {
        !          1517:   struct ospf_nbr_nbma *nbr_nbma;
        !          1518:   struct ospf_interface *oi;
        !          1519:   struct prefix_ipv4 p;
        !          1520:   struct route_node *rn;
        !          1521:   struct listnode *node;
        !          1522: 
        !          1523:   nbr_nbma = ospf_nbr_nbma_lookup (ospf, nbr_addr);
        !          1524:   if (nbr_nbma)
        !          1525:     return 0;
        !          1526: 
        !          1527:   nbr_nbma = ospf_nbr_nbma_new ();
        !          1528:   nbr_nbma->addr = nbr_addr;
        !          1529: 
        !          1530:   p.family = AF_INET;
        !          1531:   p.prefix = nbr_addr;
        !          1532:   p.prefixlen = IPV4_MAX_BITLEN;
        !          1533: 
        !          1534:   rn = route_node_get (ospf->nbr_nbma, (struct prefix *)&p);
        !          1535:   rn->info = nbr_nbma;
        !          1536: 
        !          1537:   for (ALL_LIST_ELEMENTS_RO (ospf->oiflist, node, oi))
        !          1538:     {
        !          1539:       if (oi->type == OSPF_IFTYPE_NBMA)
        !          1540:        if (prefix_match (oi->address, (struct prefix *)&p))
        !          1541:          {
        !          1542:            ospf_nbr_nbma_add (nbr_nbma, oi);
        !          1543:            break;
        !          1544:          }
        !          1545:     }
        !          1546: 
        !          1547:   return 1;
        !          1548: }
        !          1549: 
        !          1550: int
        !          1551: ospf_nbr_nbma_unset (struct ospf *ospf, struct in_addr nbr_addr)
        !          1552: {
        !          1553:   struct ospf_nbr_nbma *nbr_nbma;
        !          1554: 
        !          1555:   nbr_nbma = ospf_nbr_nbma_lookup (ospf, nbr_addr);
        !          1556:   if (nbr_nbma == NULL)
        !          1557:     return 0;
        !          1558: 
        !          1559:   ospf_nbr_nbma_down (nbr_nbma);
        !          1560:   ospf_nbr_nbma_delete (ospf, nbr_nbma);
        !          1561: 
        !          1562:   return 1;
        !          1563: }
        !          1564: 
        !          1565: int
        !          1566: ospf_nbr_nbma_priority_set (struct ospf *ospf, struct in_addr nbr_addr,
        !          1567:                            u_char priority)
        !          1568: {
        !          1569:   struct ospf_nbr_nbma *nbr_nbma;
        !          1570: 
        !          1571:   nbr_nbma = ospf_nbr_nbma_lookup (ospf, nbr_addr);
        !          1572:   if (nbr_nbma == NULL)
        !          1573:     return 0;
        !          1574: 
        !          1575:   if (nbr_nbma->priority != priority)
        !          1576:     nbr_nbma->priority = priority;
        !          1577: 
        !          1578:   return 1;
        !          1579: }
        !          1580: 
        !          1581: int
        !          1582: ospf_nbr_nbma_priority_unset (struct ospf *ospf, struct in_addr nbr_addr)
        !          1583: {
        !          1584:   struct ospf_nbr_nbma *nbr_nbma;
        !          1585: 
        !          1586:   nbr_nbma = ospf_nbr_nbma_lookup (ospf, nbr_addr);
        !          1587:   if (nbr_nbma == NULL)
        !          1588:     return 0;
        !          1589: 
        !          1590:   if (nbr_nbma != OSPF_NEIGHBOR_PRIORITY_DEFAULT)
        !          1591:     nbr_nbma->priority = OSPF_NEIGHBOR_PRIORITY_DEFAULT;
        !          1592: 
        !          1593:   return 1;
        !          1594: }
        !          1595: 
        !          1596: int
        !          1597: ospf_nbr_nbma_poll_interval_set (struct ospf *ospf, struct in_addr nbr_addr,
        !          1598:                                 unsigned int interval)
        !          1599: {
        !          1600:   struct ospf_nbr_nbma *nbr_nbma;
        !          1601: 
        !          1602:   nbr_nbma = ospf_nbr_nbma_lookup (ospf, nbr_addr);
        !          1603:   if (nbr_nbma == NULL)
        !          1604:     return 0;
        !          1605: 
        !          1606:   if (nbr_nbma->v_poll != interval)
        !          1607:     {
        !          1608:       nbr_nbma->v_poll = interval;
        !          1609:       if (nbr_nbma->oi && ospf_if_is_up (nbr_nbma->oi))
        !          1610:        {
        !          1611:          OSPF_TIMER_OFF (nbr_nbma->t_poll);
        !          1612:          OSPF_POLL_TIMER_ON (nbr_nbma->t_poll, ospf_poll_timer,
        !          1613:                              nbr_nbma->v_poll);
        !          1614:        }
        !          1615:     }
        !          1616: 
        !          1617:   return 1;
        !          1618: }
        !          1619: 
        !          1620: int
        !          1621: ospf_nbr_nbma_poll_interval_unset (struct ospf *ospf, struct in_addr addr)
        !          1622: {
        !          1623:   struct ospf_nbr_nbma *nbr_nbma;
        !          1624: 
        !          1625:   nbr_nbma = ospf_nbr_nbma_lookup (ospf, addr);
        !          1626:   if (nbr_nbma == NULL)
        !          1627:     return 0;
        !          1628: 
        !          1629:   if (nbr_nbma->v_poll != OSPF_POLL_INTERVAL_DEFAULT)
        !          1630:     nbr_nbma->v_poll = OSPF_POLL_INTERVAL_DEFAULT;
        !          1631: 
        !          1632:   return 1;
        !          1633: }
        !          1634: 
        !          1635: void
        !          1636: ospf_master_init ()
        !          1637: {
        !          1638:   memset (&ospf_master, 0, sizeof (struct ospf_master));
        !          1639: 
        !          1640:   om = &ospf_master;
        !          1641:   om->ospf = list_new ();
        !          1642:   om->master = thread_master_create ();
        !          1643:   om->start_time = quagga_time (NULL);
        !          1644: }

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