File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / quagga / ospfd / ospf_interface.c
Revision 1.1.1.2 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Sun Jul 21 23:54:40 2013 UTC (10 years, 11 months ago) by misho
Branches: quagga, MAIN
CVS tags: v0_99_22p0, v0_99_22, HEAD
0.99.22

    1: /*
    2:  * OSPF Interface functions.
    3:  * Copyright (C) 1999, 2000 Toshiaki Takada
    4:  *
    5:  * This file is part of GNU Zebra.
    6:  * 
    7:  * GNU Zebra is free software; you can redistribute it and/or modify
    8:  * it under the terms of the GNU General Public License as published
    9:  * by the Free Software Foundation; either version 2, or (at your
   10:  * option) any later version.
   11:  *
   12:  * GNU Zebra is distributed in the hope that it will be useful, but
   13:  * WITHOUT ANY WARRANTY; without even the implied warranty of
   14:  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   15:  * General Public License for more details.
   16:  *
   17:  * You should have received a copy of the GNU General Public License
   18:  * along with GNU Zebra; see the file COPYING.  If not, write to the
   19:  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
   20:  * Boston, MA 02111-1307, USA.
   21:  */
   22: 
   23: #include <zebra.h>
   24: 
   25: #include "thread.h"
   26: #include "linklist.h"
   27: #include "prefix.h"
   28: #include "if.h"
   29: #include "table.h"
   30: #include "memory.h"
   31: #include "command.h"
   32: #include "stream.h"
   33: #include "log.h"
   34: 
   35: #include "ospfd/ospfd.h"
   36: #include "ospfd/ospf_spf.h"
   37: #include "ospfd/ospf_interface.h"
   38: #include "ospfd/ospf_ism.h"
   39: #include "ospfd/ospf_asbr.h"
   40: #include "ospfd/ospf_lsa.h"
   41: #include "ospfd/ospf_lsdb.h"
   42: #include "ospfd/ospf_neighbor.h"
   43: #include "ospfd/ospf_nsm.h"
   44: #include "ospfd/ospf_packet.h"
   45: #include "ospfd/ospf_abr.h"
   46: #include "ospfd/ospf_network.h"
   47: #include "ospfd/ospf_dump.h"
   48: #ifdef HAVE_SNMP
   49: #include "ospfd/ospf_snmp.h"
   50: #endif /* HAVE_SNMP */
   51: 
   52: 
   53: int
   54: ospf_if_get_output_cost (struct ospf_interface *oi)
   55: {
   56:   /* If all else fails, use default OSPF cost */
   57:   u_int32_t cost;
   58:   u_int32_t bw, refbw;
   59: 
   60:   bw = oi->ifp->bandwidth ? oi->ifp->bandwidth : OSPF_DEFAULT_BANDWIDTH;
   61:   refbw = oi->ospf->ref_bandwidth;
   62: 
   63:   /* A specifed ip ospf cost overrides a calculated one. */
   64:   if (OSPF_IF_PARAM_CONFIGURED (IF_DEF_PARAMS (oi->ifp), output_cost_cmd) ||
   65:       OSPF_IF_PARAM_CONFIGURED (oi->params, output_cost_cmd))
   66:     cost = OSPF_IF_PARAM (oi, output_cost_cmd);
   67:   /* See if a cost can be calculated from the zebra processes
   68:      interface bandwidth field. */
   69:   else
   70:     {
   71:       cost = (u_int32_t) ((double)refbw / (double)bw + (double)0.5);
   72:       if (cost < 1)
   73: 	cost = 1;
   74:       else if (cost > 65535)
   75: 	cost = 65535;
   76:     }
   77: 
   78:   return cost;
   79: }
   80: 
   81: void
   82: ospf_if_recalculate_output_cost (struct interface *ifp)
   83: {
   84:   u_int32_t newcost;
   85:   struct route_node *rn;
   86:   
   87:   for (rn = route_top (IF_OIFS (ifp)); rn; rn = route_next (rn))
   88:     {
   89:       struct ospf_interface *oi;
   90:       
   91:       if ( (oi = rn->info) == NULL)
   92: 	continue;
   93: 
   94:       newcost = ospf_if_get_output_cost (oi);
   95: 
   96:       /* Is actual output cost changed? */
   97:       if (oi->output_cost != newcost)
   98: 	{
   99: 	  oi->output_cost = newcost;
  100: 	  ospf_router_lsa_update_area (oi->area);
  101: 	}
  102:     }
  103: }
  104: 
  105: /* Simulate down/up on the interface.  This is needed, for example, when 
  106:    the MTU changes. */
  107: void
  108: ospf_if_reset(struct interface *ifp)
  109: {
  110:   struct route_node *rn;
  111:   
  112:   for (rn = route_top (IF_OIFS (ifp)); rn; rn = route_next (rn))
  113:     {
  114:       struct ospf_interface *oi;
  115:       
  116:       if ( (oi = rn->info) == NULL)
  117: 	continue;
  118: 
  119:       ospf_if_down(oi);
  120:       ospf_if_up(oi);
  121:     }
  122: }
  123: 
  124: void
  125: ospf_if_reset_variables (struct ospf_interface *oi)
  126: {
  127:   /* Set default values. */
  128:   /* don't clear this flag.  oi->flag = OSPF_IF_DISABLE; */
  129: 
  130:   if (oi->vl_data)
  131:     oi->type = OSPF_IFTYPE_VIRTUALLINK;
  132:   else 
  133:   /* preserve network-type */
  134:   if (oi->type != OSPF_IFTYPE_NBMA)
  135:     oi->type = OSPF_IFTYPE_BROADCAST;
  136: 
  137:   oi->state = ISM_Down;
  138: 
  139:   oi->crypt_seqnum = 0;
  140: 
  141:   /* This must be short, (less than RxmtInterval) 
  142:      - RFC 2328 Section 13.5 para 3.  Set to 1 second to avoid Acks being
  143:        held back for too long - MAG */
  144:   oi->v_ls_ack = 1;  
  145: }
  146: 
  147: /* lookup oi for specified prefix/ifp */
  148: struct ospf_interface *
  149: ospf_if_table_lookup (struct interface *ifp, struct prefix *prefix)
  150: {
  151:   struct prefix p;
  152:   struct route_node *rn;
  153:   struct ospf_interface *rninfo = NULL;
  154:   
  155:   p = *prefix;
  156:   p.prefixlen = IPV4_MAX_PREFIXLEN;
  157:   
  158:   /* route_node_get implicitely locks */
  159:   if ((rn = route_node_lookup (IF_OIFS (ifp), &p)))
  160:     {
  161:       rninfo = (struct ospf_interface *) rn->info;
  162:       route_unlock_node (rn);
  163:     }
  164:   
  165:   return rninfo;
  166: }
  167: 
  168: static void
  169: ospf_add_to_if (struct interface *ifp, struct ospf_interface *oi)
  170: {
  171:   struct route_node *rn;
  172:   struct prefix p;
  173: 
  174:   p = *oi->address;
  175:   p.prefixlen = IPV4_MAX_PREFIXLEN;
  176: 
  177:   rn = route_node_get (IF_OIFS (ifp), &p);
  178:   /* rn->info should either be NULL or equal to this oi
  179:    * as route_node_get may return an existing node
  180:    */
  181:   assert (!rn->info || rn->info == oi);
  182:   rn->info = oi;
  183: }
  184: 
  185: static void
  186: ospf_delete_from_if (struct interface *ifp, struct ospf_interface *oi)
  187: {
  188:   struct route_node *rn;
  189:   struct prefix p;
  190: 
  191:   p = *oi->address;
  192:   p.prefixlen = IPV4_MAX_PREFIXLEN;
  193: 
  194:   rn = route_node_lookup (IF_OIFS (oi->ifp), &p);
  195:   assert (rn);
  196:   assert (rn->info);
  197:   rn->info = NULL;
  198:   route_unlock_node (rn);
  199:   route_unlock_node (rn);
  200: }
  201: 
  202: struct ospf_interface *
  203: ospf_if_new (struct ospf *ospf, struct interface *ifp, struct prefix *p)
  204: {
  205:   struct ospf_interface *oi;
  206: 
  207:   if ((oi = ospf_if_table_lookup (ifp, p)) == NULL)
  208:     {
  209:       oi = XCALLOC (MTYPE_OSPF_IF, sizeof (struct ospf_interface));
  210:       memset (oi, 0, sizeof (struct ospf_interface));
  211:     }
  212:   else
  213:     return oi;
  214:     
  215:   /* Set zebra interface pointer. */
  216:   oi->ifp = ifp;
  217:   oi->address = p;
  218:   
  219:   ospf_add_to_if (ifp, oi);
  220:   listnode_add (ospf->oiflist, oi);
  221:   
  222:   /* Initialize neighbor list. */
  223:   oi->nbrs = route_table_init ();
  224: 
  225:   /* Initialize static neighbor list. */
  226:   oi->nbr_nbma = list_new ();
  227: 
  228:   /* Initialize Link State Acknowledgment list. */
  229:   oi->ls_ack = list_new ();
  230:   oi->ls_ack_direct.ls_ack = list_new ();
  231: 
  232:   /* Set default values. */
  233:   ospf_if_reset_variables (oi);
  234: 
  235:   /* Add pseudo neighbor. */
  236:   oi->nbr_self = ospf_nbr_new (oi);
  237: 
  238:   oi->ls_upd_queue = route_table_init ();
  239:   oi->t_ls_upd_event = NULL;
  240:   oi->t_ls_ack_direct = NULL;
  241: 
  242:   oi->crypt_seqnum = time (NULL);
  243: 
  244: #ifdef HAVE_OPAQUE_LSA
  245:   ospf_opaque_type9_lsa_init (oi);
  246: #endif /* HAVE_OPAQUE_LSA */
  247: 
  248:   oi->ospf = ospf;
  249:   
  250:   return oi;
  251: }
  252: 
  253: /* Restore an interface to its pre UP state
  254:    Used from ism_interface_down only */
  255: void
  256: ospf_if_cleanup (struct ospf_interface *oi)
  257: {
  258:   struct route_node *rn;
  259:   struct listnode *node, *nnode;
  260:   struct ospf_neighbor *nbr;
  261:   struct ospf_nbr_nbma *nbr_nbma;
  262:   struct ospf_lsa *lsa;
  263: 
  264:   /* oi->nbrs and oi->nbr_nbma should be deleted on InterfaceDown event */
  265:   /* delete all static neighbors attached to this interface */
  266:   for (ALL_LIST_ELEMENTS (oi->nbr_nbma, node, nnode, nbr_nbma))
  267:     {
  268:       OSPF_POLL_TIMER_OFF (nbr_nbma->t_poll);
  269: 
  270:       if (nbr_nbma->nbr)
  271: 	{
  272: 	  nbr_nbma->nbr->nbr_nbma = NULL;
  273: 	  nbr_nbma->nbr = NULL;
  274: 	}
  275: 
  276:       nbr_nbma->oi = NULL;
  277:       
  278:       listnode_delete (oi->nbr_nbma, nbr_nbma);
  279:     }
  280: 
  281:   /* send Neighbor event KillNbr to all associated neighbors. */
  282:   for (rn = route_top (oi->nbrs); rn; rn = route_next (rn))
  283:     if ((nbr = rn->info) != NULL)
  284:       if (nbr != oi->nbr_self)
  285: 	OSPF_NSM_EVENT_EXECUTE (nbr, NSM_KillNbr);
  286: 
  287:   /* Cleanup Link State Acknowlegdment list. */
  288:   for (ALL_LIST_ELEMENTS (oi->ls_ack, node, nnode, lsa))
  289:     ospf_lsa_unlock (&lsa); /* oi->ls_ack */
  290:   list_delete_all_node (oi->ls_ack);
  291: 
  292:   oi->crypt_seqnum = 0;
  293:   
  294:   /* Empty link state update queue */
  295:   ospf_ls_upd_queue_empty (oi);
  296:   
  297:   /* Reset pseudo neighbor. */
  298:   ospf_nbr_delete (oi->nbr_self);
  299:   oi->nbr_self = ospf_nbr_new (oi);
  300:   ospf_nbr_add_self (oi);
  301: }
  302: 
  303: void
  304: ospf_if_free (struct ospf_interface *oi)
  305: {
  306:   ospf_if_down (oi);
  307: 
  308:   assert (oi->state == ISM_Down);
  309: 
  310: #ifdef HAVE_OPAQUE_LSA
  311:   ospf_opaque_type9_lsa_term (oi);
  312: #endif /* HAVE_OPAQUE_LSA */
  313: 
  314:   /* Free Pseudo Neighbour */
  315:   ospf_nbr_delete (oi->nbr_self);
  316:   
  317:   route_table_finish (oi->nbrs);
  318:   route_table_finish (oi->ls_upd_queue);
  319:   
  320:   /* Free any lists that should be freed */
  321:   list_free (oi->nbr_nbma);
  322:   
  323:   list_free (oi->ls_ack);
  324:   list_free (oi->ls_ack_direct.ls_ack);
  325:   
  326:   ospf_delete_from_if (oi->ifp, oi);
  327: 
  328:   listnode_delete (oi->ospf->oiflist, oi);
  329:   listnode_delete (oi->area->oiflist, oi);
  330: 
  331:   thread_cancel_event (master, oi);
  332: 
  333:   memset (oi, 0, sizeof (*oi));
  334:   XFREE (MTYPE_OSPF_IF, oi);
  335: }
  336: 
  337: 
  338: /*
  339: *  check if interface with given address is configured and
  340: *  return it if yes.  special treatment for PtP networks.
  341: */
  342: struct ospf_interface *
  343: ospf_if_is_configured (struct ospf *ospf, struct in_addr *address)
  344: {
  345:   struct listnode *node, *nnode;
  346:   struct ospf_interface *oi;
  347:   struct prefix_ipv4 addr;
  348: 
  349:   addr.family = AF_INET;
  350:   addr.prefix = *address;
  351:   addr.prefixlen = IPV4_MAX_PREFIXLEN;
  352: 
  353:   for (ALL_LIST_ELEMENTS (ospf->oiflist, node, nnode, oi))
  354:     if (oi->type != OSPF_IFTYPE_VIRTUALLINK)
  355:       {
  356:         if (oi->type == OSPF_IFTYPE_POINTOPOINT)
  357: 	  {
  358: 	    /* special leniency: match if addr is anywhere on peer subnet */
  359: 	    if (prefix_match(CONNECTED_PREFIX(oi->connected),
  360: 			     (struct prefix *)&addr))
  361: 	      return oi;
  362: 	  }
  363:         else
  364: 	  {
  365: 	    if (IPV4_ADDR_SAME (address, &oi->address->u.prefix4))
  366: 	      return oi;
  367: 	  }
  368:       }
  369:   return NULL;
  370: }
  371: 
  372: int
  373: ospf_if_is_up (struct ospf_interface *oi)
  374: {
  375:   return if_is_up (oi->ifp);
  376: }
  377: 
  378: struct ospf_interface *
  379: ospf_if_exists (struct ospf_interface *oic)
  380: { 
  381:   struct listnode *node;
  382:   struct ospf *ospf;
  383:   struct ospf_interface *oi;
  384: 
  385:   if ((ospf = ospf_lookup ()) == NULL)
  386:     return NULL;
  387: 
  388:   for (ALL_LIST_ELEMENTS_RO (ospf->oiflist, node, oi))
  389:     if (oi == oic)
  390:       return oi;
  391: 
  392:   return NULL;
  393: }
  394: 
  395: /* Lookup OSPF interface by router LSA posistion */
  396: struct ospf_interface *
  397: ospf_if_lookup_by_lsa_pos (struct ospf_area *area, int lsa_pos)
  398: {
  399:   struct listnode *node;
  400:   struct ospf_interface *oi;
  401: 
  402:   for (ALL_LIST_ELEMENTS_RO (area->oiflist, node, oi))
  403:     {
  404:       if (lsa_pos >= oi->lsa_pos_beg && lsa_pos < oi->lsa_pos_end)
  405: 	return oi;
  406:     }
  407:   return NULL;
  408: }
  409: 
  410: struct ospf_interface *
  411: ospf_if_lookup_by_local_addr (struct ospf *ospf,
  412: 			      struct interface *ifp, struct in_addr address)
  413: {
  414:   struct listnode *node;
  415:   struct ospf_interface *oi;
  416:   
  417:   for (ALL_LIST_ELEMENTS_RO (ospf->oiflist, node, oi))
  418:     if (oi->type != OSPF_IFTYPE_VIRTUALLINK)
  419:       {
  420: 	if (ifp && oi->ifp != ifp)
  421: 	  continue;
  422: 	
  423: 	if (IPV4_ADDR_SAME (&address, &oi->address->u.prefix4))
  424: 	  return oi;
  425:       }
  426: 
  427:   return NULL;
  428: }
  429: 
  430: struct ospf_interface *
  431: ospf_if_lookup_by_prefix (struct ospf *ospf, struct prefix_ipv4 *p)
  432: {
  433:   struct listnode *node;
  434:   struct ospf_interface *oi;
  435:   
  436:   /* Check each Interface. */
  437:   for (ALL_LIST_ELEMENTS_RO (ospf->oiflist, node, oi))
  438:     {
  439:       if (oi->type != OSPF_IFTYPE_VIRTUALLINK)
  440: 	{
  441: 	  struct prefix ptmp;
  442: 
  443: 	  prefix_copy (&ptmp, CONNECTED_PREFIX(oi->connected));
  444: 	  apply_mask (&ptmp);
  445: 	  if (prefix_same (&ptmp, (struct prefix *) p))
  446: 	    return oi;
  447: 	}
  448:     }
  449:   return NULL;
  450: }
  451: 
  452: /* determine receiving interface by ifp and source address */
  453: struct ospf_interface *
  454: ospf_if_lookup_recv_if (struct ospf *ospf, struct in_addr src,
  455: 			struct interface *ifp)
  456: {
  457:   struct route_node *rn;
  458:   struct prefix_ipv4 addr;
  459:   struct ospf_interface *oi, *match;
  460: 
  461:   addr.family = AF_INET;
  462:   addr.prefix = src;
  463:   addr.prefixlen = IPV4_MAX_BITLEN;
  464: 
  465:   match = NULL;
  466: 
  467:   for (rn = route_top (IF_OIFS (ifp)); rn; rn = route_next (rn))
  468:     {
  469:       oi = rn->info;
  470: 
  471:       if (!oi) /* oi can be NULL for PtP aliases */
  472: 	continue;
  473: 
  474:       if (oi->type == OSPF_IFTYPE_VIRTUALLINK)
  475: 	continue;
  476: 
  477:       if (if_is_loopback (oi->ifp))
  478:         continue;
  479: 
  480:       if (prefix_match (CONNECTED_PREFIX(oi->connected),
  481:       			(struct prefix *) &addr))
  482: 	{
  483: 	  if ( (match == NULL) || 
  484: 	       (match->address->prefixlen < oi->address->prefixlen)
  485: 	     )
  486: 	    match = oi;
  487: 	}
  488:     }
  489: 
  490:   return match;
  491: }
  492: 
  493: void
  494: ospf_if_stream_set (struct ospf_interface *oi)
  495: {
  496:   /* set output fifo queue. */
  497:   if (oi->obuf == NULL) 
  498:     oi->obuf = ospf_fifo_new ();
  499: }
  500: 
  501: void
  502: ospf_if_stream_unset (struct ospf_interface *oi)
  503: {
  504:   struct ospf *ospf = oi->ospf;
  505: 
  506:   if (oi->obuf)
  507:     {
  508:      ospf_fifo_free (oi->obuf);
  509:      oi->obuf = NULL;
  510: 
  511:      if (oi->on_write_q)
  512:        {
  513: 	 listnode_delete (ospf->oi_write_q, oi);
  514:          if (list_isempty(ospf->oi_write_q))
  515:            OSPF_TIMER_OFF (ospf->t_write);
  516: 	 oi->on_write_q = 0;
  517:        }
  518:     }
  519: }
  520: 
  521: 
  522: static struct ospf_if_params *
  523: ospf_new_if_params (void)
  524: {
  525:   struct ospf_if_params *oip;
  526: 
  527:   oip = XCALLOC (MTYPE_OSPF_IF_PARAMS, sizeof (struct ospf_if_params));
  528: 
  529:   if (!oip)
  530:     return NULL;
  531: 
  532:   UNSET_IF_PARAM (oip, output_cost_cmd);
  533:   UNSET_IF_PARAM (oip, transmit_delay);
  534:   UNSET_IF_PARAM (oip, retransmit_interval);
  535:   UNSET_IF_PARAM (oip, passive_interface);
  536:   UNSET_IF_PARAM (oip, v_hello);
  537:   UNSET_IF_PARAM (oip, fast_hello);
  538:   UNSET_IF_PARAM (oip, v_wait);
  539:   UNSET_IF_PARAM (oip, priority);
  540:   UNSET_IF_PARAM (oip, type);
  541:   UNSET_IF_PARAM (oip, auth_simple);
  542:   UNSET_IF_PARAM (oip, auth_crypt);
  543:   UNSET_IF_PARAM (oip, auth_type);
  544: 
  545:   oip->auth_crypt = list_new ();
  546:   
  547:   oip->network_lsa_seqnum = htonl(OSPF_INITIAL_SEQUENCE_NUMBER);
  548: 
  549:   return oip;
  550: }
  551: 
  552: void
  553: ospf_del_if_params (struct ospf_if_params *oip)
  554: {
  555:   list_delete (oip->auth_crypt);
  556:   XFREE (MTYPE_OSPF_IF_PARAMS, oip);
  557: }
  558: 
  559: void
  560: ospf_free_if_params (struct interface *ifp, struct in_addr addr)
  561: {
  562:   struct ospf_if_params *oip;
  563:   struct prefix_ipv4 p;
  564:   struct route_node *rn;
  565: 
  566:   p.family = AF_INET;
  567:   p.prefixlen = IPV4_MAX_PREFIXLEN;
  568:   p.prefix = addr;
  569:   rn = route_node_lookup (IF_OIFS_PARAMS (ifp), (struct prefix*)&p);
  570:   if (!rn || !rn->info)
  571:     return;
  572: 
  573:   oip = rn->info;
  574:   route_unlock_node (rn);
  575:   
  576:   if (!OSPF_IF_PARAM_CONFIGURED (oip, output_cost_cmd) &&
  577:       !OSPF_IF_PARAM_CONFIGURED (oip, transmit_delay) &&
  578:       !OSPF_IF_PARAM_CONFIGURED (oip, retransmit_interval) &&
  579:       !OSPF_IF_PARAM_CONFIGURED (oip, passive_interface) &&
  580:       !OSPF_IF_PARAM_CONFIGURED (oip, v_hello) &&
  581:       !OSPF_IF_PARAM_CONFIGURED (oip, fast_hello) &&
  582:       !OSPF_IF_PARAM_CONFIGURED (oip, v_wait) &&
  583:       !OSPF_IF_PARAM_CONFIGURED (oip, priority) &&
  584:       !OSPF_IF_PARAM_CONFIGURED (oip, type) &&
  585:       !OSPF_IF_PARAM_CONFIGURED (oip, auth_simple) &&
  586:       !OSPF_IF_PARAM_CONFIGURED (oip, auth_type) &&
  587:       listcount (oip->auth_crypt) == 0 &&
  588:       ntohl (oip->network_lsa_seqnum) != OSPF_INITIAL_SEQUENCE_NUMBER)
  589:     {
  590:       ospf_del_if_params (oip);
  591:       rn->info = NULL;
  592:       route_unlock_node (rn);
  593:     }
  594: }
  595: 
  596: struct ospf_if_params *
  597: ospf_lookup_if_params (struct interface *ifp, struct in_addr addr)
  598: {
  599:   struct prefix_ipv4 p;
  600:   struct route_node *rn;
  601: 
  602:   p.family = AF_INET;
  603:   p.prefixlen = IPV4_MAX_PREFIXLEN;
  604:   p.prefix = addr;
  605: 
  606:   rn = route_node_lookup (IF_OIFS_PARAMS (ifp), (struct prefix*)&p);
  607:   
  608:   if (rn)
  609:     {
  610:       route_unlock_node (rn);
  611:       return rn->info;
  612:     }
  613: 
  614:   return NULL;
  615: }
  616: 
  617: struct ospf_if_params *
  618: ospf_get_if_params (struct interface *ifp, struct in_addr addr)
  619: {
  620:   struct prefix_ipv4 p;
  621:   struct route_node *rn;
  622: 
  623:   p.family = AF_INET;
  624:   p.prefixlen = IPV4_MAX_PREFIXLEN;
  625:   p.prefix = addr;
  626: 
  627:   rn = route_node_get (IF_OIFS_PARAMS (ifp), (struct prefix*)&p);
  628:   
  629:   if (rn->info == NULL)
  630:     rn->info = ospf_new_if_params ();
  631:   else
  632:     route_unlock_node (rn);
  633:   
  634:   return rn->info;
  635: }
  636: 
  637: void
  638: ospf_if_update_params (struct interface *ifp, struct in_addr addr)
  639: {
  640:   struct route_node *rn;
  641:   struct ospf_interface *oi;
  642:   
  643:   for (rn = route_top (IF_OIFS (ifp)); rn; rn = route_next (rn))
  644:     {
  645:       if ((oi = rn->info) == NULL)
  646: 	continue;
  647: 
  648:       if (IPV4_ADDR_SAME (&oi->address->u.prefix4, &addr))
  649: 	oi->params = ospf_lookup_if_params (ifp, oi->address->u.prefix4);
  650:     }
  651: }
  652: 
  653: int
  654: ospf_if_new_hook (struct interface *ifp)
  655: {
  656:   int rc = 0;
  657: 
  658:   ifp->info = XCALLOC (MTYPE_OSPF_IF_INFO, sizeof (struct ospf_if_info));
  659:   
  660:   IF_OIFS (ifp) = route_table_init ();
  661:   IF_OIFS_PARAMS (ifp) = route_table_init ();
  662:   
  663:   IF_DEF_PARAMS (ifp) = ospf_new_if_params ();
  664:   
  665:   SET_IF_PARAM (IF_DEF_PARAMS (ifp), transmit_delay);
  666:   IF_DEF_PARAMS (ifp)->transmit_delay = OSPF_TRANSMIT_DELAY_DEFAULT;
  667:   
  668:   SET_IF_PARAM (IF_DEF_PARAMS (ifp), retransmit_interval);
  669:   IF_DEF_PARAMS (ifp)->retransmit_interval = OSPF_RETRANSMIT_INTERVAL_DEFAULT;
  670: 
  671:   SET_IF_PARAM (IF_DEF_PARAMS (ifp), priority);
  672:   IF_DEF_PARAMS (ifp)->priority = OSPF_ROUTER_PRIORITY_DEFAULT;
  673: 
  674:   IF_DEF_PARAMS (ifp)->mtu_ignore = OSPF_MTU_IGNORE_DEFAULT;
  675: 
  676:   SET_IF_PARAM (IF_DEF_PARAMS (ifp), v_hello);
  677:   IF_DEF_PARAMS (ifp)->v_hello = OSPF_HELLO_INTERVAL_DEFAULT;
  678: 
  679:   SET_IF_PARAM (IF_DEF_PARAMS (ifp), fast_hello);
  680:   IF_DEF_PARAMS (ifp)->fast_hello = OSPF_FAST_HELLO_DEFAULT;
  681: 
  682:   SET_IF_PARAM (IF_DEF_PARAMS (ifp), v_wait);
  683:   IF_DEF_PARAMS (ifp)->v_wait = OSPF_ROUTER_DEAD_INTERVAL_DEFAULT;
  684: 
  685:   SET_IF_PARAM (IF_DEF_PARAMS (ifp), auth_simple);
  686:   memset (IF_DEF_PARAMS (ifp)->auth_simple, 0, OSPF_AUTH_SIMPLE_SIZE);
  687:   
  688:   SET_IF_PARAM (IF_DEF_PARAMS (ifp), auth_type);
  689:   IF_DEF_PARAMS (ifp)->auth_type = OSPF_AUTH_NOTSET;
  690:   
  691: #ifdef HAVE_OPAQUE_LSA
  692:   rc = ospf_opaque_new_if (ifp);
  693: #endif /* HAVE_OPAQUE_LSA */
  694:   return rc;
  695: }
  696: 
  697: static int
  698: ospf_if_delete_hook (struct interface *ifp)
  699: {
  700:   int rc = 0;
  701:   struct route_node *rn;
  702: #ifdef HAVE_OPAQUE_LSA
  703:   rc = ospf_opaque_del_if (ifp);
  704: #endif /* HAVE_OPAQUE_LSA */
  705: 
  706:   route_table_finish (IF_OIFS (ifp));
  707: 
  708:   for (rn = route_top (IF_OIFS_PARAMS (ifp)); rn; rn = route_next (rn))
  709:     if (rn->info)
  710:       ospf_del_if_params (rn->info);
  711:   route_table_finish (IF_OIFS_PARAMS (ifp));
  712: 
  713:   ospf_del_if_params ((struct ospf_if_params *) IF_DEF_PARAMS (ifp));
  714:   XFREE (MTYPE_OSPF_IF_INFO, ifp->info);
  715:   ifp->info = NULL;
  716: 
  717:   return rc;
  718: }
  719: 
  720: int
  721: ospf_if_is_enable (struct ospf_interface *oi)
  722: {
  723:   if (!if_is_loopback (oi->ifp))
  724:     if (if_is_up (oi->ifp))
  725: 	return 1;
  726: 
  727:   return 0;
  728: }
  729: 
  730: void
  731: ospf_if_set_multicast(struct ospf_interface *oi)
  732: {
  733:   if ((oi->state > ISM_Loopback) &&
  734:       (oi->type != OSPF_IFTYPE_LOOPBACK) &&
  735:       (oi->type != OSPF_IFTYPE_VIRTUALLINK) &&
  736:       (OSPF_IF_PASSIVE_STATUS(oi) == OSPF_IF_ACTIVE))
  737:     {
  738:       /* The interface should belong to the OSPF-all-routers group. */
  739:       if (!OI_MEMBER_CHECK(oi, MEMBER_ALLROUTERS) &&
  740: 	  (ospf_if_add_allspfrouters(oi->ospf, oi->address,
  741: 				     oi->ifp->ifindex) >= 0))
  742: 	  /* Set the flag only if the system call to join succeeded. */
  743: 	  OI_MEMBER_JOINED(oi, MEMBER_ALLROUTERS);
  744:     }
  745:   else
  746:     {
  747:       /* The interface should NOT belong to the OSPF-all-routers group. */
  748:       if (OI_MEMBER_CHECK(oi, MEMBER_ALLROUTERS))
  749:         {
  750:           /* Only actually drop if this is the last reference */
  751:           if (OI_MEMBER_COUNT(oi, MEMBER_ALLROUTERS) == 1)
  752: 	    ospf_if_drop_allspfrouters (oi->ospf, oi->address,
  753: 	                                oi->ifp->ifindex);
  754: 	  /* Unset the flag regardless of whether the system call to leave
  755: 	     the group succeeded, since it's much safer to assume that
  756: 	     we are not a member. */
  757:           OI_MEMBER_LEFT(oi,MEMBER_ALLROUTERS);
  758:         }
  759:     }
  760: 
  761:   if (((oi->type == OSPF_IFTYPE_BROADCAST) ||
  762:        (oi->type == OSPF_IFTYPE_POINTOPOINT)) &&
  763:       ((oi->state == ISM_DR) || (oi->state == ISM_Backup)) &&
  764:       (OSPF_IF_PASSIVE_STATUS(oi) == OSPF_IF_ACTIVE))
  765:     {
  766:       /* The interface should belong to the OSPF-designated-routers group. */
  767:       if (!OI_MEMBER_CHECK(oi, MEMBER_DROUTERS) &&
  768: 	  (ospf_if_add_alldrouters(oi->ospf, oi->address,
  769: 	  			   oi->ifp->ifindex) >= 0))
  770: 	/* Set the flag only if the system call to join succeeded. */
  771: 	OI_MEMBER_JOINED(oi, MEMBER_DROUTERS);
  772:     }
  773:   else
  774:     {
  775:       /* The interface should NOT belong to the OSPF-designated-routers group */
  776:       if (OI_MEMBER_CHECK(oi, MEMBER_DROUTERS))
  777:         {
  778:           /* drop only if last reference */
  779:           if (OI_MEMBER_COUNT(oi, MEMBER_DROUTERS) == 1)
  780: 	    ospf_if_drop_alldrouters(oi->ospf, oi->address, oi->ifp->ifindex);
  781:           
  782: 	  /* Unset the flag regardless of whether the system call to leave
  783: 	     the group succeeded, since it's much safer to assume that
  784: 	     we are not a member. */
  785:           OI_MEMBER_LEFT(oi, MEMBER_DROUTERS);
  786:         }
  787:     }
  788: }
  789: 
  790: int
  791: ospf_if_up (struct ospf_interface *oi)
  792: {
  793:   if (oi == NULL)
  794:     return 0;
  795: 
  796:   if (oi->type == OSPF_IFTYPE_LOOPBACK)
  797:     OSPF_ISM_EVENT_SCHEDULE (oi, ISM_LoopInd);
  798:   else
  799:     {
  800:       struct ospf *ospf = ospf_lookup ();
  801:       if (ospf != NULL)
  802:         ospf_adjust_sndbuflen (ospf, oi->ifp->mtu);
  803:       else
  804:         zlog_warn ("%s: ospf_lookup() returned NULL", __func__);
  805:       ospf_if_stream_set (oi);
  806:       OSPF_ISM_EVENT_SCHEDULE (oi, ISM_InterfaceUp);
  807:     }
  808: 
  809:   return 1;
  810: }
  811: 
  812: int
  813: ospf_if_down (struct ospf_interface *oi)
  814: {
  815:   if (oi == NULL)
  816:     return 0;
  817: 
  818:   OSPF_ISM_EVENT_EXECUTE (oi, ISM_InterfaceDown);
  819:   /* delete position in router LSA */
  820:   oi->lsa_pos_beg = 0;
  821:   oi->lsa_pos_end = 0;
  822:   /* Shutdown packet reception and sending */
  823:   ospf_if_stream_unset (oi);
  824: 
  825:   return 1;
  826: }
  827: 
  828: 
  829: /* Virtual Link related functions. */
  830: 
  831: struct ospf_vl_data *
  832: ospf_vl_data_new (struct ospf_area *area, struct in_addr vl_peer)
  833: {
  834:   struct ospf_vl_data *vl_data;
  835: 
  836:   vl_data = XCALLOC (MTYPE_OSPF_VL_DATA, sizeof (struct ospf_vl_data));
  837: 
  838:   vl_data->vl_peer.s_addr = vl_peer.s_addr;
  839:   vl_data->vl_area_id = area->area_id;
  840:   vl_data->format = area->format;
  841: 
  842:   return vl_data;
  843: }
  844: 
  845: void
  846: ospf_vl_data_free (struct ospf_vl_data *vl_data)
  847: {
  848:   XFREE (MTYPE_OSPF_VL_DATA, vl_data);
  849: }
  850: 
  851: u_int vlink_count = 0;
  852: 
  853: struct ospf_interface * 
  854: ospf_vl_new (struct ospf *ospf, struct ospf_vl_data *vl_data)
  855: {
  856:   struct ospf_interface * voi;
  857:   struct interface * vi;
  858:   char   ifname[INTERFACE_NAMSIZ + 1];
  859:   struct ospf_area *area;
  860:   struct in_addr area_id;
  861:   struct connected *co;
  862:   struct prefix_ipv4 *p;
  863:   
  864:   if (IS_DEBUG_OSPF_EVENT)
  865:     zlog_debug ("ospf_vl_new(): Start");
  866:   if (vlink_count == OSPF_VL_MAX_COUNT)
  867:     {
  868:       if (IS_DEBUG_OSPF_EVENT)
  869: 	zlog_debug ("ospf_vl_new(): Alarm: "
  870: 		   "cannot create more than OSPF_MAX_VL_COUNT virtual links");
  871:       return NULL;
  872:     }
  873: 
  874:   if (IS_DEBUG_OSPF_EVENT)
  875:     zlog_debug ("ospf_vl_new(): creating pseudo zebra interface");
  876: 
  877:   snprintf (ifname, sizeof(ifname), "VLINK%d", vlink_count);
  878:   vi = if_create (ifname, strnlen(ifname, sizeof(ifname)));
  879:   co = connected_new ();
  880:   co->ifp = vi;
  881:   listnode_add (vi->connected, co);
  882: 
  883:   p = prefix_ipv4_new ();
  884:   p->family = AF_INET;
  885:   p->prefix.s_addr = 0;
  886:   p->prefixlen = 0;
  887:  
  888:   co->address = (struct prefix *)p;
  889:   
  890:   voi = ospf_if_new (ospf, vi, co->address);
  891:   if (voi == NULL)
  892:     {
  893:       if (IS_DEBUG_OSPF_EVENT)
  894: 	zlog_debug ("ospf_vl_new(): Alarm: OSPF int structure is not created");
  895:       return NULL;
  896:     }
  897:   voi->connected = co;
  898:   voi->vl_data = vl_data;
  899:   voi->ifp->mtu = OSPF_VL_MTU;
  900:   voi->type = OSPF_IFTYPE_VIRTUALLINK;
  901: 
  902:   vlink_count++;
  903:   if (IS_DEBUG_OSPF_EVENT)
  904:     zlog_debug ("ospf_vl_new(): Created name: %s", ifname);
  905:   if (IS_DEBUG_OSPF_EVENT)
  906:     zlog_debug ("ospf_vl_new(): set if->name to %s", vi->name);
  907: 
  908:   area_id.s_addr = 0;
  909:   area = ospf_area_get (ospf, area_id, OSPF_AREA_ID_FORMAT_ADDRESS);
  910:   voi->area = area;
  911: 
  912:   if (IS_DEBUG_OSPF_EVENT)
  913:     zlog_debug ("ospf_vl_new(): set associated area to the backbone");
  914: 
  915:   ospf_nbr_add_self (voi);
  916:   ospf_area_add_if (voi->area, voi);
  917: 
  918:   ospf_if_stream_set (voi);
  919: 
  920:   if (IS_DEBUG_OSPF_EVENT)
  921:     zlog_debug ("ospf_vl_new(): Stop");
  922:   return voi;
  923: }
  924: 
  925: static void
  926: ospf_vl_if_delete (struct ospf_vl_data *vl_data)
  927: {
  928:   struct interface *ifp = vl_data->vl_oi->ifp;
  929:   vl_data->vl_oi->address->u.prefix4.s_addr = 0;
  930:   vl_data->vl_oi->address->prefixlen = 0;
  931:   ospf_if_free (vl_data->vl_oi);
  932:   if_delete (ifp);
  933:   vlink_count--;
  934: }
  935: 
  936: /* Look up vl_data for given peer, optionally qualified to be in the
  937:  * specified area. NULL area returns first found..
  938:  */
  939: struct ospf_vl_data *
  940: ospf_vl_lookup (struct ospf *ospf, struct ospf_area *area,
  941:                 struct in_addr vl_peer)
  942: {
  943:   struct ospf_vl_data *vl_data;
  944:   struct listnode *node;
  945:   
  946:   if (IS_DEBUG_OSPF_EVENT)
  947:     {
  948:       zlog_debug ("%s: Looking for %s", __func__, inet_ntoa (vl_peer));
  949:       if (area)
  950:         zlog_debug ("%s: in area %s", __func__, inet_ntoa (area->area_id));
  951:     }
  952:   
  953:   for (ALL_LIST_ELEMENTS_RO (ospf->vlinks, node, vl_data))
  954:     {
  955:       if (IS_DEBUG_OSPF_EVENT)
  956:         zlog_debug ("%s: VL %s, peer %s", __func__,
  957:                     vl_data->vl_oi->ifp->name,
  958:                     inet_ntoa (vl_data->vl_peer));
  959:       
  960:       if (area && !IPV4_ADDR_SAME (&vl_data->vl_area_id, &area->area_id))
  961:         continue;
  962:       
  963:       if (IPV4_ADDR_SAME (&vl_data->vl_peer, &vl_peer))
  964:         return vl_data;
  965:     }
  966: 
  967:   return NULL;
  968: }
  969: 
  970: static void 
  971: ospf_vl_shutdown (struct ospf_vl_data *vl_data)
  972: {
  973:   struct ospf_interface *oi;
  974: 
  975:   if ((oi = vl_data->vl_oi) == NULL)
  976:     return;
  977: 
  978:   oi->address->u.prefix4.s_addr = 0;
  979:   oi->address->prefixlen = 0;
  980: 
  981:   UNSET_FLAG (oi->ifp->flags, IFF_UP);
  982:   /* OSPF_ISM_EVENT_SCHEDULE (oi, ISM_InterfaceDown); */
  983:   OSPF_ISM_EVENT_EXECUTE (oi, ISM_InterfaceDown);
  984: }
  985: 
  986: void
  987: ospf_vl_add (struct ospf *ospf, struct ospf_vl_data *vl_data)
  988: {
  989:   listnode_add (ospf->vlinks, vl_data);
  990: #ifdef HAVE_SNMP
  991:   ospf_snmp_vl_add (vl_data);
  992: #endif /* HAVE_SNMP */
  993: }
  994: 
  995: void
  996: ospf_vl_delete (struct ospf *ospf, struct ospf_vl_data *vl_data)
  997: {
  998:   ospf_vl_shutdown (vl_data);
  999:   ospf_vl_if_delete (vl_data);
 1000: 
 1001: #ifdef HAVE_SNMP
 1002:   ospf_snmp_vl_delete (vl_data);
 1003: #endif /* HAVE_SNMP */
 1004:   listnode_delete (ospf->vlinks, vl_data);
 1005: 
 1006:   ospf_vl_data_free (vl_data);
 1007: }
 1008: 
 1009: static int
 1010: ospf_vl_set_params (struct ospf_vl_data *vl_data, struct vertex *v)
 1011: {
 1012:   int changed = 0;
 1013:   struct ospf_interface *voi;
 1014:   struct listnode *node;
 1015:   struct vertex_parent *vp = NULL;
 1016:   int i;
 1017:   struct router_lsa *rl;
 1018: 
 1019:   voi = vl_data->vl_oi;
 1020: 
 1021:   if (voi->output_cost != v->distance)
 1022:     {
 1023:      
 1024:       voi->output_cost = v->distance;
 1025:       changed = 1;
 1026:     }
 1027: 
 1028:   for (ALL_LIST_ELEMENTS_RO (v->parents, node, vp))
 1029:     {
 1030:       vl_data->nexthop.oi = vp->nexthop->oi;
 1031:       vl_data->nexthop.router = vp->nexthop->router;
 1032:       
 1033:       if (!IPV4_ADDR_SAME(&voi->address->u.prefix4,
 1034:                           &vl_data->nexthop.oi->address->u.prefix4))
 1035:         changed = 1;
 1036:         
 1037:       voi->address->u.prefix4 = vl_data->nexthop.oi->address->u.prefix4;
 1038:       voi->address->prefixlen = vl_data->nexthop.oi->address->prefixlen;
 1039: 
 1040:       break; /* We take the first interface. */
 1041:     }
 1042: 
 1043:   rl = (struct router_lsa *)v->lsa;
 1044: 
 1045:   /* use SPF determined backlink index in struct vertex
 1046:    * for virtual link destination address
 1047:    */
 1048:   if (vp && vp->backlink >= 0)
 1049:     {
 1050:       if (!IPV4_ADDR_SAME (&vl_data->peer_addr,
 1051:                            &rl->link[vp->backlink].link_data))
 1052:         changed = 1;
 1053:       vl_data->peer_addr = rl->link[vp->backlink].link_data;
 1054:     }
 1055:   else
 1056:     {
 1057:       /* This is highly odd, there is no backlink index
 1058:        * there should be due to the ospf_spf_has_link() check
 1059:        * in SPF. Lets warn and try pick a link anyway.
 1060:        */
 1061:       zlog_warn ("ospf_vl_set_params: No backlink for %s!",
 1062:                  vl_data->vl_oi->ifp->name);
 1063:       for (i = 0; i < ntohs (rl->links); i++)
 1064:         {
 1065:           switch (rl->link[i].type)
 1066:             {
 1067:               case LSA_LINK_TYPE_VIRTUALLINK:
 1068:                 if (IS_DEBUG_OSPF_EVENT)
 1069:                   zlog_debug ("found back link through VL");
 1070:               case LSA_LINK_TYPE_TRANSIT:
 1071:               case LSA_LINK_TYPE_POINTOPOINT:
 1072:                 if (!IPV4_ADDR_SAME (&vl_data->peer_addr,
 1073:                                      &rl->link[i].link_data))
 1074:                   changed = 1;
 1075:                 vl_data->peer_addr = rl->link[i].link_data;
 1076:             }
 1077:         }
 1078:     }
 1079:     
 1080:   if (IS_DEBUG_OSPF_EVENT)
 1081:     zlog_debug ("%s: %s peer address: %s, cost: %d,%schanged", __func__,
 1082:                vl_data->vl_oi->ifp->name,
 1083:                inet_ntoa(vl_data->peer_addr),
 1084:                voi->output_cost,
 1085:                (changed ? " " : " un"));
 1086:                
 1087:   return changed;
 1088: }
 1089: 
 1090: 
 1091: void
 1092: ospf_vl_up_check (struct ospf_area *area, struct in_addr rid,
 1093:                   struct vertex *v)
 1094: {
 1095:   struct ospf *ospf = area->ospf;
 1096:   struct listnode *node;
 1097:   struct ospf_vl_data *vl_data;
 1098:   struct ospf_interface *oi;
 1099: 
 1100:   if (IS_DEBUG_OSPF_EVENT)
 1101:     {
 1102:       zlog_debug ("ospf_vl_up_check(): Start");
 1103:       zlog_debug ("ospf_vl_up_check(): Router ID is %s", inet_ntoa (rid));
 1104:       zlog_debug ("ospf_vl_up_check(): Area is %s", inet_ntoa (area->area_id));
 1105:     }
 1106: 
 1107:   for (ALL_LIST_ELEMENTS_RO (ospf->vlinks, node, vl_data))
 1108:     {
 1109:       if (IS_DEBUG_OSPF_EVENT)
 1110: 	{
 1111: 	  zlog_debug ("%s: considering VL, %s in area %s", __func__,
 1112: 		     vl_data->vl_oi->ifp->name,
 1113: 		     inet_ntoa (vl_data->vl_area_id));
 1114: 	  zlog_debug ("%s: peer ID: %s", __func__,
 1115: 		     inet_ntoa (vl_data->vl_peer));
 1116: 	}
 1117: 
 1118:       if (IPV4_ADDR_SAME (&vl_data->vl_peer, &rid) &&
 1119:           IPV4_ADDR_SAME (&vl_data->vl_area_id, &area->area_id))
 1120:         {
 1121:           oi = vl_data->vl_oi;
 1122:           SET_FLAG (vl_data->flags, OSPF_VL_FLAG_APPROVED);
 1123: 
 1124: 	  if (IS_DEBUG_OSPF_EVENT)
 1125: 	    zlog_debug ("ospf_vl_up_check(): this VL matched");
 1126: 
 1127:           if (oi->state == ISM_Down)
 1128:             {
 1129: 	      if (IS_DEBUG_OSPF_EVENT)
 1130: 		zlog_debug ("ospf_vl_up_check(): VL is down, waking it up");
 1131:               SET_FLAG (oi->ifp->flags, IFF_UP);
 1132:               OSPF_ISM_EVENT_EXECUTE(oi,ISM_InterfaceUp);
 1133:             }
 1134: 
 1135:          if (ospf_vl_set_params (vl_data, v))
 1136:            {
 1137:              if (IS_DEBUG_OSPF (ism, ISM_EVENTS))
 1138:                zlog_debug ("ospf_vl_up_check: VL cost change,"
 1139:                           " scheduling router lsa refresh");
 1140:              if (ospf->backbone)
 1141:                ospf_router_lsa_update_area (ospf->backbone);
 1142:              else if (IS_DEBUG_OSPF (ism, ISM_EVENTS))
 1143:                zlog_debug ("ospf_vl_up_check: VL cost change, no backbone!");
 1144:            }
 1145:         }
 1146:     }
 1147: }
 1148: 
 1149: void
 1150: ospf_vl_unapprove (struct ospf *ospf)
 1151: {
 1152:   struct listnode *node;
 1153:   struct ospf_vl_data *vl_data;
 1154: 
 1155:   for (ALL_LIST_ELEMENTS_RO (ospf->vlinks, node, vl_data))
 1156:     UNSET_FLAG (vl_data->flags, OSPF_VL_FLAG_APPROVED);
 1157: }
 1158: 
 1159: void
 1160: ospf_vl_shut_unapproved (struct ospf *ospf)
 1161: {
 1162:   struct listnode *node, *nnode;
 1163:   struct ospf_vl_data *vl_data;
 1164: 
 1165:   for (ALL_LIST_ELEMENTS (ospf->vlinks, node, nnode, vl_data))
 1166:     if (!CHECK_FLAG (vl_data->flags, OSPF_VL_FLAG_APPROVED))
 1167:       ospf_vl_shutdown (vl_data);
 1168: }
 1169: 
 1170: int
 1171: ospf_full_virtual_nbrs (struct ospf_area *area)
 1172: {
 1173:   if (IS_DEBUG_OSPF_EVENT)
 1174:     {
 1175:       zlog_debug ("counting fully adjacent virtual neighbors in area %s",
 1176: 		 inet_ntoa (area->area_id));
 1177:       zlog_debug ("there are %d of them", area->full_vls);
 1178:     }
 1179: 
 1180:   return area->full_vls;
 1181: }
 1182: 
 1183: int
 1184: ospf_vls_in_area (struct ospf_area *area)
 1185: {
 1186:   struct listnode *node;
 1187:   struct ospf_vl_data *vl_data;
 1188:   int c = 0;
 1189: 
 1190:   for (ALL_LIST_ELEMENTS_RO (area->ospf->vlinks, node, vl_data))
 1191:     if (IPV4_ADDR_SAME (&vl_data->vl_area_id, &area->area_id))
 1192:       c++;
 1193: 
 1194:   return c;
 1195: }
 1196: 
 1197: 
 1198: struct crypt_key *
 1199: ospf_crypt_key_new ()
 1200: {
 1201:   return XCALLOC (MTYPE_OSPF_CRYPT_KEY, sizeof (struct crypt_key));
 1202: }
 1203: 
 1204: void
 1205: ospf_crypt_key_add (struct list *crypt, struct crypt_key *ck)
 1206: {
 1207:   listnode_add (crypt, ck);
 1208: }
 1209: 
 1210: struct crypt_key *
 1211: ospf_crypt_key_lookup (struct list *auth_crypt, u_char key_id)
 1212: {
 1213:   struct listnode *node;
 1214:   struct crypt_key *ck;
 1215: 
 1216:   for (ALL_LIST_ELEMENTS_RO (auth_crypt, node, ck))
 1217:     if (ck->key_id == key_id)
 1218:       return ck;
 1219: 
 1220:   return NULL;
 1221: }
 1222: 
 1223: int
 1224: ospf_crypt_key_delete (struct list *auth_crypt, u_char key_id)
 1225: {
 1226:   struct listnode *node, *nnode;
 1227:   struct crypt_key *ck;
 1228: 
 1229:   for (ALL_LIST_ELEMENTS (auth_crypt, node, nnode, ck))
 1230:     {
 1231:       if (ck->key_id == key_id)
 1232:         {
 1233:           listnode_delete (auth_crypt, ck);
 1234:           XFREE (MTYPE_OSPF_CRYPT_KEY, ck);
 1235:           return 1;
 1236:         }
 1237:     }
 1238: 
 1239:   return 0;
 1240: }
 1241: 
 1242: u_char
 1243: ospf_default_iftype(struct interface *ifp)
 1244: {
 1245:   if (if_is_pointopoint (ifp))
 1246:     return OSPF_IFTYPE_POINTOPOINT;
 1247:   else if (if_is_loopback (ifp))
 1248:     return OSPF_IFTYPE_LOOPBACK;
 1249:   else
 1250:     return OSPF_IFTYPE_BROADCAST;
 1251: }
 1252: 
 1253: void
 1254: ospf_if_init ()
 1255: {
 1256:   /* Initialize Zebra interface data structure. */
 1257:   if_init ();
 1258:   om->iflist = iflist;
 1259:   if_add_hook (IF_NEW_HOOK, ospf_if_new_hook);
 1260:   if_add_hook (IF_DELETE_HOOK, ospf_if_delete_hook);
 1261: }

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