Annotation of embedaddon/quagga/ospfd/ospf_opaque.c, revision 1.1.1.3

1.1       misho       1: /*
                      2:  * This is an implementation of rfc2370.
                      3:  * Copyright (C) 2001 KDD R&D Laboratories, Inc.
                      4:  * http://www.kddlabs.co.jp/
                      5:  *
                      6:  * This file is part of GNU Zebra.
                      7:  *
                      8:  * GNU Zebra is free software; you can redistribute it and/or modify it
                      9:  * under the terms of the GNU General Public License as published by the
                     10:  * Free Software Foundation; either version 2, or (at your option) any
                     11:  * later version.
                     12:  * 
                     13:  * GNU Zebra is distributed in the hope that it will be useful, but
                     14:  * WITHOUT ANY WARRANTY; without even the implied warranty of
                     15:  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
                     16:  * General Public License for more details.
                     17:  *
                     18:  * You should have received a copy of the GNU General Public License
                     19:  * along with GNU Zebra; see the file COPYING.  If not, write to the Free
                     20:  * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
                     21:  * 02111-1307, USA.
                     22:  */
                     23: 
                     24: /***** MTYPE definitions are not reflected to "memory.h" yet. *****/
                     25: #define MTYPE_OSPF_OPAQUE_FUNCTAB      0
                     26: #define MTYPE_OPAQUE_INFO_PER_TYPE     0
                     27: #define MTYPE_OPAQUE_INFO_PER_ID       0
                     28: 
                     29: #include <zebra.h>
                     30: 
                     31: #include "linklist.h"
                     32: #include "prefix.h"
                     33: #include "if.h"
                     34: #include "table.h"
                     35: #include "memory.h"
                     36: #include "command.h"
                     37: #include "vty.h"
                     38: #include "stream.h"
                     39: #include "log.h"
                     40: #include "thread.h"
                     41: #include "hash.h"
                     42: #include "sockunion.h"         /* for inet_aton() */
                     43: 
                     44: #include "ospfd/ospfd.h"
                     45: #include "ospfd/ospf_interface.h"
                     46: #include "ospfd/ospf_ism.h"
                     47: #include "ospfd/ospf_asbr.h"
                     48: #include "ospfd/ospf_lsa.h"
                     49: #include "ospfd/ospf_lsdb.h"
                     50: #include "ospfd/ospf_neighbor.h"
                     51: #include "ospfd/ospf_nsm.h"
                     52: #include "ospfd/ospf_flood.h"
                     53: #include "ospfd/ospf_packet.h"
                     54: #include "ospfd/ospf_spf.h"
                     55: #include "ospfd/ospf_dump.h"
                     56: #include "ospfd/ospf_route.h"
                     57: #include "ospfd/ospf_ase.h"
                     58: #include "ospfd/ospf_zebra.h"
                     59: 
                     60: /*------------------------------------------------------------------------*
                     61:  * Followings are initialize/terminate functions for Opaque-LSAs handling.
                     62:  *------------------------------------------------------------------------*/
                     63: 
                     64: #include "ospfd/ospf_te.h"
                     65: 
                     66: #ifdef SUPPORT_OSPF_API
                     67: int ospf_apiserver_init (void);
                     68: void ospf_apiserver_term (void); 
                     69: /* Init apiserver? It's disabled by default. */
                     70: int ospf_apiserver_enable;
                     71: #endif /* SUPPORT_OSPF_API */
                     72: 
                     73: static void ospf_opaque_register_vty (void);
                     74: static void ospf_opaque_funclist_init (void);
                     75: static void ospf_opaque_funclist_term (void);
                     76: static void free_opaque_info_per_type (void *val);
                     77: static void free_opaque_info_per_id (void *val);
                     78: static int ospf_opaque_lsa_install_hook (struct ospf_lsa *lsa);
                     79: static int ospf_opaque_lsa_delete_hook (struct ospf_lsa *lsa);
                     80: 
                     81: void
                     82: ospf_opaque_init (void)
                     83: {
                     84:   ospf_opaque_register_vty ();
                     85:   ospf_opaque_funclist_init ();
                     86: 
                     87:   if (ospf_mpls_te_init () != 0)
                     88:     exit (1);
                     89: 
                     90: #ifdef SUPPORT_OSPF_API
                     91:   if ((ospf_apiserver_enable) && (ospf_apiserver_init () != 0))
                     92:     exit (1);
                     93: #endif /* SUPPORT_OSPF_API */
                     94: 
                     95:   return;
                     96: }
                     97: 
                     98: void
                     99: ospf_opaque_term (void)
                    100: {
                    101:   ospf_mpls_te_term ();
                    102: 
                    103: #ifdef SUPPORT_OSPF_API
                    104:   ospf_apiserver_term ();
                    105: #endif /* SUPPORT_OSPF_API */
                    106: 
                    107:   ospf_opaque_funclist_term ();
                    108:   return;
                    109: }
                    110: 
                    111: int
                    112: ospf_opaque_type9_lsa_init (struct ospf_interface *oi)
                    113: {
                    114:   if (oi->opaque_lsa_self != NULL)
                    115:     list_delete (oi->opaque_lsa_self);
                    116: 
                    117:   oi->opaque_lsa_self = list_new ();
                    118:   oi->opaque_lsa_self->del = free_opaque_info_per_type;
                    119:   oi->t_opaque_lsa_self = NULL;
                    120:   return 0;
                    121: }
                    122: 
                    123: void
                    124: ospf_opaque_type9_lsa_term (struct ospf_interface *oi)
                    125: {
                    126:   OSPF_TIMER_OFF (oi->t_opaque_lsa_self);
                    127:   if (oi->opaque_lsa_self != NULL)
                    128:     list_delete (oi->opaque_lsa_self);
                    129:   oi->opaque_lsa_self = NULL;
                    130:   return;
                    131: }
                    132: 
                    133: int
                    134: ospf_opaque_type10_lsa_init (struct ospf_area *area)
                    135: {
                    136:   if (area->opaque_lsa_self != NULL)
                    137:     list_delete (area->opaque_lsa_self);
                    138: 
                    139:   area->opaque_lsa_self = list_new ();
                    140:   area->opaque_lsa_self->del = free_opaque_info_per_type;
                    141:   area->t_opaque_lsa_self = NULL;
                    142: 
                    143: #ifdef MONITOR_LSDB_CHANGE
                    144:   area->lsdb->new_lsa_hook = ospf_opaque_lsa_install_hook;
                    145:   area->lsdb->del_lsa_hook = ospf_opaque_lsa_delete_hook;
                    146: #endif /* MONITOR_LSDB_CHANGE */
                    147:   return 0;
                    148: }
                    149: 
                    150: void
                    151: ospf_opaque_type10_lsa_term (struct ospf_area *area)
                    152: {
                    153: #ifdef MONITOR_LSDB_CHANGE
                    154:   area->lsdb->new_lsa_hook = 
                    155:   area->lsdb->del_lsa_hook = NULL;
                    156: #endif /* MONITOR_LSDB_CHANGE */
                    157: 
                    158:   OSPF_TIMER_OFF (area->t_opaque_lsa_self);
                    159:   if (area->opaque_lsa_self != NULL)
                    160:     list_delete (area->opaque_lsa_self);
                    161:   area->opaque_lsa_self = NULL;
                    162:   return;
                    163: }
                    164: 
                    165: int
                    166: ospf_opaque_type11_lsa_init (struct ospf *top)
                    167: {
                    168:   if (top->opaque_lsa_self != NULL)
                    169:     list_delete (top->opaque_lsa_self);
                    170: 
                    171:   top->opaque_lsa_self = list_new ();
                    172:   top->opaque_lsa_self->del = free_opaque_info_per_type;
                    173:   top->t_opaque_lsa_self = NULL;
                    174: 
                    175: #ifdef MONITOR_LSDB_CHANGE
                    176:   top->lsdb->new_lsa_hook = ospf_opaque_lsa_install_hook;
                    177:   top->lsdb->del_lsa_hook = ospf_opaque_lsa_delete_hook;
                    178: #endif /* MONITOR_LSDB_CHANGE */
                    179:   return 0;
                    180: }
                    181: 
                    182: void
                    183: ospf_opaque_type11_lsa_term (struct ospf *top)
                    184: {
                    185: #ifdef MONITOR_LSDB_CHANGE
                    186:   top->lsdb->new_lsa_hook = 
                    187:   top->lsdb->del_lsa_hook = NULL;
                    188: #endif /* MONITOR_LSDB_CHANGE */
                    189: 
                    190:   OSPF_TIMER_OFF (top->t_opaque_lsa_self);
                    191:   if (top->opaque_lsa_self != NULL)
                    192:     list_delete (top->opaque_lsa_self);
                    193:   top->opaque_lsa_self = NULL;
                    194:   return;
                    195: }
                    196: 
                    197: static const char *
                    198: ospf_opaque_type_name (u_char opaque_type)
                    199: {
                    200:   const char *name = "Unknown";
                    201: 
                    202:   switch (opaque_type)
                    203:     {
                    204:     case OPAQUE_TYPE_WILDCARD: /* This is a special assignment! */
                    205:       name = "Wildcard";
                    206:       break;
                    207:     case OPAQUE_TYPE_TRAFFIC_ENGINEERING_LSA:
                    208:       name = "Traffic Engineering LSA";
                    209:       break;
                    210:     case OPAQUE_TYPE_SYCAMORE_OPTICAL_TOPOLOGY_DESC:
                    211:       name = "Sycamore optical topology description";
                    212:       break;
                    213:     case OPAQUE_TYPE_GRACE_LSA:
                    214:       name = "Grace-LSA";
                    215:       break;
                    216:     default:
                    217:       if (OPAQUE_TYPE_RANGE_UNASSIGNED (opaque_type))
                    218:         name = "Unassigned";
1.1.1.2   misho     219:       else
                    220:         {
                    221:           u_int32_t bigger_range = opaque_type;
                    222:           /*
                    223:            * Get around type-limits warning: comparison is always true due to limited range of data type
                    224:            */
                    225:           if (OPAQUE_TYPE_RANGE_RESERVED (bigger_range))
                    226:             name = "Private/Experimental";
                    227:         }
1.1       misho     228:       break;
                    229:     }
                    230:   return name;
                    231: }
                    232: 
                    233: /*------------------------------------------------------------------------*
                    234:  * Followings are management functions to store user specified callbacks.
                    235:  *------------------------------------------------------------------------*/
                    236: 
                    237: struct opaque_info_per_type; /* Forward declaration. */
                    238: 
                    239: struct ospf_opaque_functab
                    240: {
                    241:   u_char opaque_type;
                    242:   struct opaque_info_per_type *oipt;
                    243: 
                    244:   int (* new_if_hook)(struct interface *ifp);
                    245:   int (* del_if_hook)(struct interface *ifp);
                    246:   void (* ism_change_hook)(struct ospf_interface *oi, int old_status);
                    247:   void (* nsm_change_hook)(struct ospf_neighbor *nbr, int old_status);
                    248:   void (* config_write_router)(struct vty *vty);
                    249:   void (* config_write_if    )(struct vty *vty, struct interface *ifp);
                    250:   void (* config_write_debug )(struct vty *vty);
                    251:   void (* show_opaque_info   )(struct vty *vty, struct ospf_lsa *lsa);
                    252:   int  (* lsa_originator)(void *arg);
                    253:   struct ospf_lsa *(* lsa_refresher )(struct ospf_lsa *lsa);
                    254:   int (* new_lsa_hook)(struct ospf_lsa *lsa);
                    255:   int (* del_lsa_hook)(struct ospf_lsa *lsa);
                    256: };
                    257: 
                    258: /* Handle LSA-9/10/11 altogether. */
                    259: static struct list *ospf_opaque_wildcard_funclist;
                    260: static struct list *ospf_opaque_type9_funclist;
                    261: static struct list *ospf_opaque_type10_funclist;
                    262: static struct list *ospf_opaque_type11_funclist;
                    263: 
                    264: static void
                    265: ospf_opaque_del_functab (void *val)
                    266: {
                    267:   XFREE (MTYPE_OSPF_OPAQUE_FUNCTAB, val);
                    268:   return;
                    269: }
                    270: 
                    271: static void
                    272: ospf_opaque_funclist_init (void)
                    273: {
                    274:   struct list *funclist;
                    275: 
                    276:   funclist = ospf_opaque_wildcard_funclist = list_new ();
                    277:   funclist->del = ospf_opaque_del_functab;
                    278: 
                    279:   funclist = ospf_opaque_type9_funclist  = list_new ();
                    280:   funclist->del = ospf_opaque_del_functab;
                    281: 
                    282:   funclist = ospf_opaque_type10_funclist = list_new ();
                    283:   funclist->del = ospf_opaque_del_functab;
                    284: 
                    285:   funclist = ospf_opaque_type11_funclist = list_new ();
                    286:   funclist->del = ospf_opaque_del_functab;
                    287:   return;
                    288: }
                    289: 
                    290: static void
                    291: ospf_opaque_funclist_term (void)
                    292: {
                    293:   struct list *funclist;
                    294: 
                    295:   funclist = ospf_opaque_wildcard_funclist;
                    296:   list_delete (funclist);
                    297: 
                    298:   funclist = ospf_opaque_type9_funclist;
                    299:   list_delete (funclist);
                    300: 
                    301:   funclist = ospf_opaque_type10_funclist;
                    302:   list_delete (funclist);
                    303: 
                    304:   funclist = ospf_opaque_type11_funclist;
                    305:   list_delete (funclist);
                    306:   return;
                    307: }
                    308: 
                    309: static struct list *
                    310: ospf_get_opaque_funclist (u_char lsa_type)
                    311: {
                    312:   struct list *funclist = NULL;
                    313: 
                    314:   switch (lsa_type)
                    315:     {
                    316:     case OPAQUE_TYPE_WILDCARD:
                    317:       /* XXX
                    318:        * This is an ugly trick to handle type-9/10/11 LSA altogether.
                    319:        * Yes, "OPAQUE_TYPE_WILDCARD (value 0)" is not an LSA-type, nor
                    320:        * an officially assigned opaque-type.
                    321:        * Though it is possible that the value might be officially used
                    322:        * in the future, we use it internally as a special label, for now.
                    323:        */
                    324:       funclist = ospf_opaque_wildcard_funclist;
                    325:       break;
                    326:     case OSPF_OPAQUE_LINK_LSA:
                    327:       funclist = ospf_opaque_type9_funclist;
                    328:       break;
                    329:     case OSPF_OPAQUE_AREA_LSA:
                    330:       funclist = ospf_opaque_type10_funclist;
                    331:       break;
                    332:     case OSPF_OPAQUE_AS_LSA:
                    333:       funclist = ospf_opaque_type11_funclist;
                    334:       break;
                    335:     default:
                    336:       zlog_warn ("ospf_get_opaque_funclist: Unexpected LSA-type(%u)", lsa_type);
                    337:       break;
                    338:     }
                    339:   return funclist;
                    340: }
                    341: 
                    342: /* XXX: such a huge argument list can /not/ be healthy... */
                    343: int
                    344: ospf_register_opaque_functab (
                    345:   u_char lsa_type,
                    346:   u_char opaque_type,
                    347:   int (* new_if_hook)(struct interface *ifp),
                    348:   int (* del_if_hook)(struct interface *ifp),
                    349:   void (* ism_change_hook)(struct ospf_interface *oi, int old_status),
                    350:   void (* nsm_change_hook)(struct ospf_neighbor *nbr, int old_status),
                    351:   void (* config_write_router)(struct vty *vty),
                    352:   void (* config_write_if    )(struct vty *vty, struct interface *ifp),
                    353:   void (* config_write_debug )(struct vty *vty),
                    354:   void (* show_opaque_info   )(struct vty *vty, struct ospf_lsa *lsa),
                    355:   int  (* lsa_originator)(void *arg),
                    356:   struct ospf_lsa *(* lsa_refresher )(struct ospf_lsa *lsa),
                    357:   int (* new_lsa_hook)(struct ospf_lsa *lsa),
                    358:   int (* del_lsa_hook)(struct ospf_lsa *lsa))
                    359: {
                    360:   struct list *funclist;
                    361:   struct ospf_opaque_functab *new;
                    362:   int rc = -1;
                    363: 
                    364:   if ((funclist = ospf_get_opaque_funclist (lsa_type)) == NULL)
                    365:     {
                    366:       zlog_warn ("ospf_register_opaque_functab: Cannot get funclist"
                    367:                  " for Type-%u LSAs?",
                    368:                  lsa_type);
                    369:       goto out;
                    370:     }
                    371:   else
                    372:     {
                    373:       struct listnode *node, *nnode;
                    374:       struct ospf_opaque_functab *functab;
                    375:       
                    376:       for (ALL_LIST_ELEMENTS (funclist, node, nnode, functab))
                    377:         if (functab->opaque_type == opaque_type)
                    378:           {
                    379:             zlog_warn ("ospf_register_opaque_functab: Duplicated entry?:"
                    380:                        " lsa_type(%u), opaque_type(%u)", 
                    381:                        lsa_type, opaque_type);
                    382:             goto out;
                    383:           }
                    384:     }
                    385: 
                    386:   if ((new = XCALLOC (MTYPE_OSPF_OPAQUE_FUNCTAB,
                    387:                      sizeof (struct ospf_opaque_functab))) == NULL)
                    388:     {
                    389:       zlog_warn ("ospf_register_opaque_functab: XMALLOC: %s",
                    390:                  safe_strerror (errno));
                    391:       goto out;
                    392:     }
                    393: 
                    394:   new->opaque_type    = opaque_type;
                    395:   new->oipt           = NULL;
                    396:   new->new_if_hook    = new_if_hook;
                    397:   new->del_if_hook    = del_if_hook;
                    398:   new->ism_change_hook     = ism_change_hook;
                    399:   new->nsm_change_hook     = nsm_change_hook;
                    400:   new->config_write_router = config_write_router;
                    401:   new->config_write_if     = config_write_if;
                    402:   new->config_write_debug  = config_write_debug;
                    403:   new->show_opaque_info    = show_opaque_info;
                    404:   new->lsa_originator = lsa_originator;
                    405:   new->lsa_refresher  = lsa_refresher;
                    406:   new->new_lsa_hook   = new_lsa_hook;
                    407:   new->del_lsa_hook   = del_lsa_hook;
                    408: 
                    409:   listnode_add (funclist, new);
                    410:   rc = 0;
                    411: 
                    412: out:
                    413:   return rc;
                    414: }
                    415: 
                    416: void
                    417: ospf_delete_opaque_functab (u_char lsa_type, u_char opaque_type)
                    418: {
                    419:   struct list *funclist;
                    420:   struct listnode *node, *nnode;
                    421:   struct ospf_opaque_functab *functab;
                    422: 
                    423:   if ((funclist = ospf_get_opaque_funclist (lsa_type)) != NULL)
                    424:     for (ALL_LIST_ELEMENTS (funclist, node, nnode, functab))
                    425:       {
                    426:         if (functab->opaque_type == opaque_type)
                    427:           {
                    428:             /* Cleanup internal control information, if it still remains. */
                    429:             if (functab->oipt != NULL)
                    430:               free_opaque_info_per_type (functab->oipt);
                    431: 
                    432:             /* Dequeue listnode entry from the list. */
                    433:             listnode_delete (funclist, functab);
                    434: 
                    435:             /* Avoid misjudgement in the next lookup. */
                    436:             if (listcount (funclist) == 0)
                    437:               funclist->head = funclist->tail = NULL;
                    438: 
                    439:             XFREE (MTYPE_OSPF_OPAQUE_FUNCTAB, functab);
                    440:             break;
                    441:          }
                    442:       }
                    443: 
                    444:   return;
                    445: }
                    446: 
                    447: static struct ospf_opaque_functab *
                    448: ospf_opaque_functab_lookup (struct ospf_lsa *lsa)
                    449: {
                    450:   struct list *funclist;
                    451:   struct listnode *node;
                    452:   struct ospf_opaque_functab *functab;
                    453:   u_char key = GET_OPAQUE_TYPE (ntohl (lsa->data->id.s_addr));
                    454: 
                    455:   if ((funclist = ospf_get_opaque_funclist (lsa->data->type)) != NULL)
                    456:     for (ALL_LIST_ELEMENTS_RO (funclist, node, functab))
                    457:       if (functab->opaque_type == key)
                    458:         return functab;
                    459: 
                    460:   return NULL;
                    461: }
                    462: 
                    463: /*------------------------------------------------------------------------*
                    464:  * Followings are management functions for self-originated LSA entries.
                    465:  *------------------------------------------------------------------------*/
                    466: 
                    467: /*
                    468:  * Opaque-LSA control information per opaque-type.
                    469:  * Single Opaque-Type may have multiple instances; each of them will be
                    470:  * identified by their opaque-id.
                    471:  */
                    472: struct opaque_info_per_type
                    473: {
                    474:   u_char lsa_type;
                    475:   u_char opaque_type;
                    476: 
                    477:   enum { PROC_NORMAL, PROC_SUSPEND } status;
                    478: 
                    479:   /*
                    480:    * Thread for (re-)origination scheduling for this opaque-type.
                    481:    *
                    482:    * Initial origination of Opaque-LSAs is controlled by generic
                    483:    * Opaque-LSA handling module so that same opaque-type entries are
                    484:    * called all at once when certain conditions are met.
                    485:    * However, there might be cases that some Opaque-LSA clients need
                    486:    * to (re-)originate their own Opaque-LSAs out-of-sync with others.
                    487:    * This thread is prepared for that specific purpose.
                    488:    */
                    489:   struct thread *t_opaque_lsa_self;
                    490: 
                    491:   /*
                    492:    * Backpointer to an "owner" which is LSA-type dependent.
                    493:    *   type-9:  struct ospf_interface
                    494:    *   type-10: struct ospf_area
                    495:    *   type-11: struct ospf
                    496:    */
                    497:   void *owner;
                    498: 
                    499:   /* Collection of callback functions for this opaque-type. */
                    500:   struct ospf_opaque_functab *functab;
                    501: 
                    502:   /* List of Opaque-LSA control informations per opaque-id. */
                    503:   struct list *id_list;
                    504: };
                    505: 
                    506: /* Opaque-LSA control information per opaque-id. */
                    507: struct opaque_info_per_id
                    508: {
                    509:   u_int32_t opaque_id;
                    510: 
                    511:   /* Thread for refresh/flush scheduling for this opaque-type/id. */
                    512:   struct thread *t_opaque_lsa_self;
                    513: 
                    514:   /* Backpointer to Opaque-LSA control information per opaque-type. */
                    515:   struct opaque_info_per_type *opqctl_type;
                    516: 
                    517:   /* Here comes an actual Opaque-LSA entry for this opaque-type/id. */
                    518:   struct ospf_lsa *lsa;
                    519: };
                    520: 
                    521: static struct opaque_info_per_type *register_opaque_info_per_type (struct ospf_opaque_functab *functab, struct ospf_lsa *new);
                    522: static struct opaque_info_per_type *lookup_opaque_info_by_type (struct ospf_lsa *lsa);
                    523: static struct opaque_info_per_id *register_opaque_info_per_id (struct opaque_info_per_type *oipt, struct ospf_lsa *new);
                    524: static struct opaque_info_per_id *lookup_opaque_info_by_id (struct opaque_info_per_type *oipt, struct ospf_lsa *lsa);
                    525: static struct opaque_info_per_id *register_opaque_lsa (struct ospf_lsa *new);
                    526: 
                    527: 
                    528: static struct opaque_info_per_type *
                    529: register_opaque_info_per_type (struct ospf_opaque_functab *functab,
                    530:                                struct ospf_lsa *new)
                    531: {
                    532:   struct ospf *top;
                    533:   struct opaque_info_per_type *oipt;
                    534: 
                    535:   if ((oipt = XCALLOC (MTYPE_OPAQUE_INFO_PER_TYPE,
                    536:                       sizeof (struct opaque_info_per_type))) == NULL)
                    537:     {
                    538:       zlog_warn ("register_opaque_info_per_type: XMALLOC: %s", safe_strerror (errno));
                    539:       goto out;
                    540:     }
                    541: 
                    542:   switch (new->data->type)
                    543:     {
                    544:     case OSPF_OPAQUE_LINK_LSA:
                    545:       oipt->owner = new->oi;
                    546:       listnode_add (new->oi->opaque_lsa_self, oipt);
                    547:       break;
                    548:     case OSPF_OPAQUE_AREA_LSA:
                    549:       oipt->owner = new->area;
                    550:       listnode_add (new->area->opaque_lsa_self, oipt);
                    551:       break;
                    552:     case OSPF_OPAQUE_AS_LSA:
                    553:       top = ospf_lookup ();
                    554:       if (new->area != NULL && (top = new->area->ospf) == NULL)
                    555:         {
                    556:           free_opaque_info_per_type ((void *) oipt);
                    557:           oipt = NULL;
                    558:           goto out; /* This case may not exist. */
                    559:         }
                    560:       oipt->owner = top;
                    561:       listnode_add (top->opaque_lsa_self, oipt);
                    562:       break;
                    563:     default:
                    564:       zlog_warn ("register_opaque_info_per_type: Unexpected LSA-type(%u)", new->data->type);
                    565:       free_opaque_info_per_type ((void *) oipt);
                    566:       oipt = NULL;
                    567:       goto out; /* This case may not exist. */
                    568:     }
                    569: 
                    570:   oipt->lsa_type = new->data->type;
                    571:   oipt->opaque_type = GET_OPAQUE_TYPE (ntohl (new->data->id.s_addr));
                    572:   oipt->status = PROC_NORMAL;
                    573:   oipt->t_opaque_lsa_self = NULL;
                    574:   oipt->functab = functab;
                    575:   functab->oipt = oipt;
                    576:   oipt->id_list = list_new ();
                    577:   oipt->id_list->del = free_opaque_info_per_id;
                    578: 
                    579: out:
                    580:   return oipt;
                    581: }
                    582: 
                    583: static void
                    584: free_opaque_info_per_type (void *val)
                    585: {
                    586:   struct opaque_info_per_type *oipt = (struct opaque_info_per_type *) val;
                    587:   struct opaque_info_per_id *oipi;
                    588:   struct ospf_lsa *lsa;
                    589:   struct listnode *node, *nnode;
                    590: 
                    591:   /* Control information per opaque-id may still exist. */
                    592:   for (ALL_LIST_ELEMENTS (oipt->id_list, node, nnode, oipi))
                    593:     {
                    594:       if ((lsa = oipi->lsa) == NULL)
                    595:         continue;
                    596:       if (IS_LSA_MAXAGE (lsa))
                    597:         continue;
                    598:       ospf_opaque_lsa_flush_schedule (lsa);
                    599:     }
                    600: 
                    601:   /* Remove "oipt" from its owner's self-originated LSA list. */
                    602:   switch (oipt->lsa_type)
                    603:     {
                    604:     case OSPF_OPAQUE_LINK_LSA:
                    605:       {
                    606:         struct ospf_interface *oi = (struct ospf_interface *)(oipt->owner);
                    607:         listnode_delete (oi->opaque_lsa_self, oipt);
                    608:         break;
                    609:       }
                    610:     case OSPF_OPAQUE_AREA_LSA:
                    611:       {
                    612:         struct ospf_area *area = (struct ospf_area *)(oipt->owner);
                    613:         listnode_delete (area->opaque_lsa_self, oipt);
                    614:         break;
                    615:       }
                    616:     case OSPF_OPAQUE_AS_LSA:
                    617:       {
                    618:         struct ospf *top = (struct ospf *)(oipt->owner);
                    619:         listnode_delete (top->opaque_lsa_self, oipt);
                    620:         break;
                    621:       }
                    622:     default:
                    623:       zlog_warn ("free_opaque_info_per_type: Unexpected LSA-type(%u)", oipt->lsa_type);
                    624:       break; /* This case may not exist. */
                    625:     }
                    626: 
                    627:   OSPF_TIMER_OFF (oipt->t_opaque_lsa_self);
                    628:   list_delete (oipt->id_list);
                    629:   XFREE (MTYPE_OPAQUE_INFO_PER_TYPE, oipt);
                    630:   return;
                    631: }
                    632: 
                    633: static struct opaque_info_per_type *
                    634: lookup_opaque_info_by_type (struct ospf_lsa *lsa)
                    635: {
                    636:   struct ospf *top;
                    637:   struct ospf_area *area;
                    638:   struct ospf_interface *oi;
                    639:   struct list *listtop = NULL;
                    640:   struct listnode *node, *nnode;
                    641:   struct opaque_info_per_type *oipt = NULL;
                    642:   u_char key = GET_OPAQUE_TYPE (ntohl (lsa->data->id.s_addr));
                    643: 
                    644:   switch (lsa->data->type)
                    645:     {
                    646:     case OSPF_OPAQUE_LINK_LSA:
                    647:       if ((oi = lsa->oi) != NULL)
                    648:         listtop = oi->opaque_lsa_self;
                    649:       else
                    650:         zlog_warn ("Type-9 Opaque-LSA: Reference to OI is missing?");
                    651:       break;
                    652:     case OSPF_OPAQUE_AREA_LSA:
                    653:       if ((area = lsa->area) != NULL)
                    654:         listtop = area->opaque_lsa_self;
                    655:       else
                    656:         zlog_warn ("Type-10 Opaque-LSA: Reference to AREA is missing?");
                    657:       break;
                    658:     case OSPF_OPAQUE_AS_LSA:
                    659:       top = ospf_lookup ();
                    660:       if ((area = lsa->area) != NULL && (top = area->ospf) == NULL)
                    661:         {
                    662:           zlog_warn ("Type-11 Opaque-LSA: Reference to OSPF is missing?");
                    663:           break; /* Unlikely to happen. */
                    664:         }
                    665:       listtop = top->opaque_lsa_self;
                    666:       break;
                    667:     default:
                    668:       zlog_warn ("lookup_opaque_info_by_type: Unexpected LSA-type(%u)", lsa->data->type);
                    669:       break;
                    670:     }
                    671: 
                    672:   if (listtop != NULL)
                    673:     for (ALL_LIST_ELEMENTS (listtop, node, nnode, oipt))
                    674:       if (oipt->opaque_type == key)
                    675:         return oipt;
                    676: 
                    677:   return NULL;
                    678: }
                    679: 
                    680: static struct opaque_info_per_id *
                    681: register_opaque_info_per_id (struct opaque_info_per_type *oipt,
                    682:                              struct ospf_lsa *new)
                    683: {
                    684:   struct opaque_info_per_id *oipi;
                    685: 
                    686:   if ((oipi = XCALLOC (MTYPE_OPAQUE_INFO_PER_ID,
                    687:                       sizeof (struct opaque_info_per_id))) == NULL)
                    688:     {
                    689:       zlog_warn ("register_opaque_info_per_id: XMALLOC: %s", safe_strerror (errno));
                    690:       goto out;
                    691:     }
                    692:   oipi->opaque_id = GET_OPAQUE_ID (ntohl (new->data->id.s_addr));
                    693:   oipi->t_opaque_lsa_self = NULL;
                    694:   oipi->opqctl_type = oipt;
                    695:   oipi->lsa = ospf_lsa_lock (new);
                    696: 
                    697:   listnode_add (oipt->id_list, oipi);
                    698: 
                    699: out:
                    700:   return oipi;
                    701: }
                    702: 
                    703: static void
                    704: free_opaque_info_per_id (void *val)
                    705: {
                    706:   struct opaque_info_per_id *oipi = (struct opaque_info_per_id *) val;
                    707: 
                    708:   OSPF_TIMER_OFF (oipi->t_opaque_lsa_self);
                    709:   if (oipi->lsa != NULL)
                    710:     ospf_lsa_unlock (&oipi->lsa);
                    711:   XFREE (MTYPE_OPAQUE_INFO_PER_ID, oipi);
                    712:   return;
                    713: }
                    714: 
                    715: static struct opaque_info_per_id *
                    716: lookup_opaque_info_by_id (struct opaque_info_per_type *oipt,
                    717:                           struct ospf_lsa *lsa)
                    718: {
                    719:   struct listnode *node, *nnode;
                    720:   struct opaque_info_per_id   *oipi;
                    721:   u_int32_t key = GET_OPAQUE_ID (ntohl (lsa->data->id.s_addr));
                    722: 
                    723:   for (ALL_LIST_ELEMENTS (oipt->id_list, node, nnode, oipi))
                    724:     if (oipi->opaque_id == key)
                    725:       return oipi;
                    726: 
                    727:   return NULL;
                    728: }
                    729: 
                    730: static struct opaque_info_per_id *
                    731: register_opaque_lsa (struct ospf_lsa *new)
                    732: {
                    733:   struct ospf_opaque_functab *functab;
                    734:   struct opaque_info_per_type *oipt;
                    735:   struct opaque_info_per_id *oipi = NULL;
                    736: 
                    737:   if ((functab = ospf_opaque_functab_lookup (new)) == NULL)
                    738:     goto out;
                    739: 
                    740:   if ((oipt = lookup_opaque_info_by_type (new)) == NULL
                    741:   &&  (oipt = register_opaque_info_per_type (functab, new)) == NULL)
                    742:     goto out;
                    743: 
                    744:   if ((oipi = register_opaque_info_per_id (oipt, new)) == NULL)
                    745:     goto out;
                    746: 
                    747: out:
                    748:   return oipi;
                    749: }
                    750: 
                    751: /*------------------------------------------------------------------------*
                    752:  * Followings are (vty) configuration functions for Opaque-LSAs handling.
                    753:  *------------------------------------------------------------------------*/
                    754: 
                    755: DEFUN (capability_opaque,
                    756:        capability_opaque_cmd,
                    757:        "capability opaque",
                    758:        "Enable specific OSPF feature\n"
                    759:        "Opaque LSA\n")
                    760: {
                    761:   struct ospf *ospf = (struct ospf *) vty->index;
                    762: 
                    763:   /* Turn on the "master switch" of opaque-lsa capability. */
                    764:   if (!CHECK_FLAG (ospf->config, OSPF_OPAQUE_CAPABLE))
                    765:     {
                    766:       if (IS_DEBUG_OSPF_EVENT)
                    767:         zlog_debug ("Opaque capability: OFF -> ON");
                    768: 
                    769:       SET_FLAG (ospf->config, OSPF_OPAQUE_CAPABLE);
                    770:       ospf_renegotiate_optional_capabilities (ospf);
                    771:     }
                    772:   return CMD_SUCCESS;
                    773: }
                    774: 
                    775: ALIAS (capability_opaque,
                    776:        ospf_opaque_capable_cmd,
                    777:        "ospf opaque-lsa",
                    778:        "OSPF specific commands\n"
                    779:        "Enable the Opaque-LSA capability (rfc2370)\n")
                    780: 
                    781: DEFUN (no_capability_opaque,
                    782:        no_capability_opaque_cmd,
                    783:        "no capability opaque",
                    784:        NO_STR
                    785:        "Enable specific OSPF feature\n"
                    786:        "Opaque LSA\n")
                    787: {
                    788:   struct ospf *ospf = (struct ospf *) vty->index;
                    789: 
                    790:   /* Turn off the "master switch" of opaque-lsa capability. */
                    791:   if (CHECK_FLAG (ospf->config, OSPF_OPAQUE_CAPABLE))
                    792:     {
                    793:       if (IS_DEBUG_OSPF_EVENT)
                    794:         zlog_debug ("Opaque capability: ON -> OFF");
                    795: 
                    796:       UNSET_FLAG (ospf->config, OSPF_OPAQUE_CAPABLE);
                    797:       ospf_renegotiate_optional_capabilities (ospf);
                    798:     }
                    799:   return CMD_SUCCESS;
                    800: }
                    801: 
                    802: ALIAS (no_capability_opaque,
                    803:        no_ospf_opaque_capable_cmd,
                    804:        "no ospf opaque-lsa",
                    805:        NO_STR
                    806:        "OSPF specific commands\n"
                    807:        "Disable the Opaque-LSA capability (rfc2370)\n")
                    808: 
                    809: static void
                    810: ospf_opaque_register_vty (void)
                    811: {
                    812:   install_element (OSPF_NODE, &capability_opaque_cmd);
                    813:   install_element (OSPF_NODE, &no_capability_opaque_cmd);
                    814:   install_element (OSPF_NODE, &ospf_opaque_capable_cmd);
                    815:   install_element (OSPF_NODE, &no_ospf_opaque_capable_cmd);
                    816:   return;
                    817: }
                    818: 
                    819: /*------------------------------------------------------------------------*
                    820:  * Followings are collection of user-registered function callers.
                    821:  *------------------------------------------------------------------------*/
                    822: 
                    823: static int
                    824: opaque_lsa_new_if_callback (struct list *funclist, struct interface *ifp)
                    825: {
                    826:   struct listnode *node, *nnode;
                    827:   struct ospf_opaque_functab *functab;
                    828:   int rc = -1;
                    829: 
                    830:   for (ALL_LIST_ELEMENTS (funclist, node, nnode, functab))
                    831:     if (functab->new_if_hook != NULL)
                    832:       if ((* functab->new_if_hook)(ifp) != 0)
                    833:         goto out;
                    834:   rc = 0;
                    835: out:
                    836:   return rc;
                    837: }
                    838: 
                    839: static int
                    840: opaque_lsa_del_if_callback (struct list *funclist, struct interface *ifp)
                    841: {
                    842:   struct listnode *node, *nnode;
                    843:   struct ospf_opaque_functab *functab;
                    844:   int rc = -1;
                    845: 
                    846:   for (ALL_LIST_ELEMENTS (funclist, node, nnode, functab))
                    847:     if (functab->del_if_hook != NULL)
                    848:       if ((* functab->del_if_hook)(ifp) != 0)
                    849:         goto out;
                    850:   rc = 0;
                    851: out:
                    852:   return rc;
                    853: }
                    854: 
                    855: static void
                    856: opaque_lsa_ism_change_callback (struct list *funclist,
                    857:                                 struct ospf_interface *oi, int old_status)
                    858: {
                    859:   struct listnode *node, *nnode;
                    860:   struct ospf_opaque_functab *functab;
                    861: 
                    862:   for (ALL_LIST_ELEMENTS (funclist, node, nnode, functab))
                    863:     if (functab->ism_change_hook != NULL)
                    864:       (* functab->ism_change_hook)(oi, old_status);
                    865: 
                    866:   return;
                    867: }
                    868: 
                    869: static void
                    870: opaque_lsa_nsm_change_callback (struct list *funclist,
                    871:                                 struct ospf_neighbor *nbr, int old_status)
                    872: {
                    873:   struct listnode *node, *nnode;
                    874:   struct ospf_opaque_functab *functab;
                    875: 
                    876:   for (ALL_LIST_ELEMENTS (funclist, node, nnode, functab))
                    877:     if (functab->nsm_change_hook != NULL)
                    878:       (* functab->nsm_change_hook)(nbr, old_status);
                    879:   return;
                    880: }
                    881: 
                    882: static void
                    883: opaque_lsa_config_write_router_callback (struct list *funclist, 
                    884:                                          struct vty *vty)
                    885: {
                    886:   struct listnode *node, *nnode;
                    887:   struct ospf_opaque_functab *functab;
                    888: 
                    889:   for (ALL_LIST_ELEMENTS (funclist, node, nnode, functab))
                    890:     if (functab->config_write_router != NULL)
                    891:       (* functab->config_write_router)(vty);
                    892:   return;
                    893: }
                    894: 
                    895: static void
                    896: opaque_lsa_config_write_if_callback (struct list *funclist,
                    897:                                      struct vty *vty, struct interface *ifp)
                    898: {
                    899:   struct listnode *node, *nnode;
                    900:   struct ospf_opaque_functab *functab;
                    901: 
                    902:   for (ALL_LIST_ELEMENTS (funclist, node, nnode, functab))
                    903:     if (functab->config_write_if != NULL)
                    904:       (* functab->config_write_if)(vty, ifp);
                    905:   return;
                    906: }
                    907: 
                    908: static void
                    909: opaque_lsa_config_write_debug_callback (struct list *funclist, struct vty *vty)
                    910: {
                    911:   struct listnode *node, *nnode;
                    912:   struct ospf_opaque_functab *functab;
                    913: 
                    914:   for (ALL_LIST_ELEMENTS (funclist, node, nnode, functab))
                    915:     if (functab->config_write_debug != NULL)
                    916:       (* functab->config_write_debug)(vty);
                    917:   return;
                    918: }
                    919: 
                    920: static int
                    921: opaque_lsa_originate_callback (struct list *funclist, void *lsa_type_dependent)
                    922: {
                    923:   struct listnode *node, *nnode;
                    924:   struct ospf_opaque_functab *functab;
                    925:   int rc = -1;
                    926: 
                    927:   for (ALL_LIST_ELEMENTS (funclist, node, nnode, functab))
                    928:     if (functab->lsa_originator != NULL)
                    929:       if ((* functab->lsa_originator)(lsa_type_dependent) != 0)
                    930:          goto out;
                    931:   rc = 0;
                    932: out:
                    933:   return rc;
                    934: }
                    935: 
                    936: static int
                    937: new_lsa_callback (struct list *funclist, struct ospf_lsa *lsa)
                    938: {
                    939:   struct listnode *node, *nnode;
                    940:   struct ospf_opaque_functab *functab;
                    941:   int rc = -1;
                    942: 
                    943:   /* This function handles ALL types of LSAs, not only opaque ones. */
                    944:   for (ALL_LIST_ELEMENTS (funclist, node, nnode, functab))
                    945:     if (functab->new_lsa_hook != NULL)
                    946:       if ((* functab->new_lsa_hook)(lsa) != 0)
                    947:         goto out;
                    948:   rc = 0;
                    949: out:
                    950:   return rc;
                    951: }
                    952: 
                    953: static int
                    954: del_lsa_callback (struct list *funclist, struct ospf_lsa *lsa)
                    955: {
                    956:   struct listnode *node, *nnode;
                    957:   struct ospf_opaque_functab *functab;
                    958:   int rc = -1;
                    959: 
                    960:   /* This function handles ALL types of LSAs, not only opaque ones. */
                    961:   for (ALL_LIST_ELEMENTS (funclist, node, nnode, functab))
                    962:     if (functab->del_lsa_hook != NULL)
                    963:       if ((* functab->del_lsa_hook)(lsa) != 0)
                    964:         goto out;
                    965:   rc = 0;
                    966: out:
                    967:   return rc;
                    968: }
                    969: 
                    970: /*------------------------------------------------------------------------*
                    971:  * Followings are glue functions to call Opaque-LSA specific processing.
                    972:  *------------------------------------------------------------------------*/
                    973: 
                    974: int
                    975: ospf_opaque_new_if (struct interface *ifp)
                    976: {
                    977:   struct list *funclist;
                    978:   int rc = -1;
                    979: 
                    980:   funclist = ospf_opaque_wildcard_funclist;
                    981:   if (opaque_lsa_new_if_callback (funclist, ifp) != 0)
                    982:     goto out;
                    983: 
                    984:   funclist = ospf_opaque_type9_funclist;
                    985:   if (opaque_lsa_new_if_callback (funclist, ifp) != 0)
                    986:     goto out;
                    987: 
                    988:   funclist = ospf_opaque_type10_funclist;
                    989:   if (opaque_lsa_new_if_callback (funclist, ifp) != 0)
                    990:     goto out;
                    991: 
                    992:   funclist = ospf_opaque_type11_funclist;
                    993:   if (opaque_lsa_new_if_callback (funclist, ifp) != 0)
                    994:     goto out;
                    995: 
                    996:   rc = 0;
                    997: out:
                    998:   return rc;
                    999: }
                   1000: 
                   1001: int
                   1002: ospf_opaque_del_if (struct interface *ifp)
                   1003: {
                   1004:   struct list *funclist;
                   1005:   int rc = -1;
                   1006: 
                   1007:   funclist = ospf_opaque_wildcard_funclist;
                   1008:   if (opaque_lsa_del_if_callback (funclist, ifp) != 0)
                   1009:     goto out;
                   1010: 
                   1011:   funclist = ospf_opaque_type9_funclist;
                   1012:   if (opaque_lsa_del_if_callback (funclist, ifp) != 0)
                   1013:     goto out;
                   1014: 
                   1015:   funclist = ospf_opaque_type10_funclist;
                   1016:   if (opaque_lsa_del_if_callback (funclist, ifp) != 0)
                   1017:     goto out;
                   1018: 
                   1019:   funclist = ospf_opaque_type11_funclist;
                   1020:   if (opaque_lsa_del_if_callback (funclist, ifp) != 0)
                   1021:     goto out;
                   1022: 
                   1023:   rc = 0;
                   1024: out:
                   1025:   return rc;
                   1026: }
                   1027: 
                   1028: void
                   1029: ospf_opaque_ism_change (struct ospf_interface *oi, int old_status)
                   1030: {
                   1031:   struct list *funclist;
                   1032: 
                   1033:   funclist = ospf_opaque_wildcard_funclist;
                   1034:   opaque_lsa_ism_change_callback (funclist, oi, old_status);
                   1035: 
                   1036:   funclist = ospf_opaque_type9_funclist;
                   1037:   opaque_lsa_ism_change_callback (funclist, oi, old_status);
                   1038: 
                   1039:   funclist = ospf_opaque_type10_funclist;
                   1040:   opaque_lsa_ism_change_callback (funclist, oi, old_status);
                   1041: 
                   1042:   funclist = ospf_opaque_type11_funclist;
                   1043:   opaque_lsa_ism_change_callback (funclist, oi, old_status);
                   1044: 
                   1045:   return;
                   1046: }
                   1047: 
                   1048: void
                   1049: ospf_opaque_nsm_change (struct ospf_neighbor *nbr, int old_state)
                   1050: {
                   1051:   struct ospf *top;
                   1052:   struct list *funclist;
                   1053: 
                   1054:   if ((top = oi_to_top (nbr->oi)) == NULL)
                   1055:     goto out;
                   1056: 
                   1057:   if (old_state != NSM_Full && nbr->state == NSM_Full)
                   1058:     {
                   1059:       if (CHECK_FLAG (nbr->options, OSPF_OPTION_O))
                   1060:         {
                   1061:           if (! CHECK_FLAG (top->opaque, OPAQUE_OPERATION_READY_BIT))
                   1062:             {
                   1063:               if (IS_DEBUG_OSPF_EVENT)
                   1064:                 zlog_debug ("Opaque-LSA: Now get operational!");
                   1065: 
                   1066:               SET_FLAG (top->opaque, OPAQUE_OPERATION_READY_BIT);
                   1067:             }
                   1068: 
                   1069:           ospf_opaque_lsa_originate_schedule (nbr->oi, NULL);
                   1070:         }
                   1071:     }
                   1072:   else
                   1073:   if (old_state == NSM_Full && nbr->state != NSM_Full)
                   1074:     {
                   1075: #ifdef NOTYET
                   1076:       /*
                   1077:        * If no more opaque-capable full-state neighbor remains in the
                   1078:        * flooding scope which corresponds to Opaque-LSA type, periodic
                   1079:        * LS flooding should be stopped.
                   1080:        */
                   1081: #endif /* NOTYET */
                   1082:       ;
                   1083:     }
                   1084: 
                   1085:   funclist = ospf_opaque_wildcard_funclist;
                   1086:   opaque_lsa_nsm_change_callback (funclist, nbr, old_state);
                   1087: 
                   1088:   funclist = ospf_opaque_type9_funclist;
                   1089:   opaque_lsa_nsm_change_callback (funclist, nbr, old_state);
                   1090: 
                   1091:   funclist = ospf_opaque_type10_funclist;
                   1092:   opaque_lsa_nsm_change_callback (funclist, nbr, old_state);
                   1093: 
                   1094:   funclist = ospf_opaque_type11_funclist;
                   1095:   opaque_lsa_nsm_change_callback (funclist, nbr, old_state);
                   1096: 
                   1097: out:
                   1098:   return;
                   1099: }
                   1100: 
                   1101: void
                   1102: ospf_opaque_config_write_router (struct vty *vty, struct ospf *ospf)
                   1103: {
                   1104:   struct list *funclist;
                   1105: 
                   1106:   if (CHECK_FLAG (ospf->config, OSPF_OPAQUE_CAPABLE))
                   1107:     vty_out (vty, " capability opaque%s", VTY_NEWLINE);
                   1108: 
                   1109:   funclist = ospf_opaque_wildcard_funclist;
                   1110:   opaque_lsa_config_write_router_callback (funclist, vty);
                   1111: 
                   1112:   funclist = ospf_opaque_type9_funclist;
                   1113:   opaque_lsa_config_write_router_callback (funclist, vty);
                   1114: 
                   1115:   funclist = ospf_opaque_type10_funclist;
                   1116:   opaque_lsa_config_write_router_callback (funclist, vty);
                   1117: 
                   1118:   funclist = ospf_opaque_type11_funclist;
                   1119:   opaque_lsa_config_write_router_callback (funclist, vty);
                   1120: 
                   1121:   return;
                   1122: }
                   1123: 
                   1124: void
                   1125: ospf_opaque_config_write_if (struct vty *vty, struct interface *ifp)
                   1126: {
                   1127:   struct list *funclist;
                   1128: 
                   1129:   funclist = ospf_opaque_wildcard_funclist;
                   1130:   opaque_lsa_config_write_if_callback (funclist, vty, ifp);
                   1131: 
                   1132:   funclist = ospf_opaque_type9_funclist;
                   1133:   opaque_lsa_config_write_if_callback (funclist, vty, ifp);
                   1134: 
                   1135:   funclist = ospf_opaque_type10_funclist;
                   1136:   opaque_lsa_config_write_if_callback (funclist, vty, ifp);
                   1137: 
                   1138:   funclist = ospf_opaque_type11_funclist;
                   1139:   opaque_lsa_config_write_if_callback (funclist, vty, ifp);
                   1140: 
                   1141:   return;
                   1142: }
                   1143: 
                   1144: void
                   1145: ospf_opaque_config_write_debug (struct vty *vty)
                   1146: {
                   1147:   struct list *funclist;
                   1148: 
                   1149:   funclist = ospf_opaque_wildcard_funclist;
                   1150:   opaque_lsa_config_write_debug_callback (funclist, vty);
                   1151: 
                   1152:   funclist = ospf_opaque_type9_funclist;
                   1153:   opaque_lsa_config_write_debug_callback (funclist, vty);
                   1154: 
                   1155:   funclist = ospf_opaque_type10_funclist;
                   1156:   opaque_lsa_config_write_debug_callback (funclist, vty);
                   1157: 
                   1158:   funclist = ospf_opaque_type11_funclist;
                   1159:   opaque_lsa_config_write_debug_callback (funclist, vty);
                   1160: 
                   1161:   return;
                   1162: }
                   1163: 
                   1164: void
                   1165: show_opaque_info_detail (struct vty *vty, struct ospf_lsa *lsa)
                   1166: {
                   1167:   struct lsa_header *lsah = (struct lsa_header *) lsa->data;
                   1168:   u_int32_t lsid = ntohl (lsah->id.s_addr);
                   1169:   u_char    opaque_type = GET_OPAQUE_TYPE (lsid);
                   1170:   u_int32_t opaque_id = GET_OPAQUE_ID (lsid);
                   1171:   struct ospf_opaque_functab *functab;
                   1172: 
                   1173:   /* Switch output functionality by vty address. */
                   1174:   if (vty != NULL)
                   1175:     {
                   1176:       vty_out (vty, "  Opaque-Type %u (%s)%s", opaque_type,
                   1177:               ospf_opaque_type_name (opaque_type), VTY_NEWLINE);
                   1178:       vty_out (vty, "  Opaque-ID   0x%x%s", opaque_id, VTY_NEWLINE);
                   1179: 
                   1180:       vty_out (vty, "  Opaque-Info: %u octets of data%s%s",
                   1181:                ntohs (lsah->length) - OSPF_LSA_HEADER_SIZE,
                   1182:                VALID_OPAQUE_INFO_LEN(lsah) ? "" : "(Invalid length?)",
                   1183:                VTY_NEWLINE);
                   1184:     }
                   1185:   else
                   1186:     {
                   1187:       zlog_debug ("    Opaque-Type %u (%s)", opaque_type,
                   1188:                 ospf_opaque_type_name (opaque_type));
                   1189:       zlog_debug ("    Opaque-ID   0x%x", opaque_id);
                   1190: 
                   1191:       zlog_debug ("    Opaque-Info: %u octets of data%s",
                   1192:                ntohs (lsah->length) - OSPF_LSA_HEADER_SIZE,
                   1193:                VALID_OPAQUE_INFO_LEN(lsah) ? "" : "(Invalid length?)");
                   1194:     }
                   1195: 
                   1196:   /* Call individual output functions. */
                   1197:   if ((functab = ospf_opaque_functab_lookup (lsa)) != NULL)
                   1198:     if (functab->show_opaque_info != NULL)
                   1199:       (* functab->show_opaque_info)(vty, lsa);
                   1200: 
                   1201:   return;
                   1202: }
                   1203: 
                   1204: void
                   1205: ospf_opaque_lsa_dump (struct stream *s, u_int16_t length)
                   1206: {
                   1207:   struct ospf_lsa lsa;
                   1208: 
                   1209:   lsa.data = (struct lsa_header *) STREAM_PNT (s);
                   1210:   show_opaque_info_detail (NULL, &lsa);
                   1211:   return;
                   1212: }
                   1213: 
                   1214: static int
                   1215: ospf_opaque_lsa_install_hook (struct ospf_lsa *lsa)
                   1216: {
                   1217:   struct list *funclist;
                   1218:   int rc = -1;
                   1219: 
                   1220:   /*
                   1221:    * Some Opaque-LSA user may want to monitor every LSA installation
                   1222:    * into the LSDB, regardless with target LSA type.
                   1223:    */
                   1224:   funclist = ospf_opaque_wildcard_funclist;
                   1225:   if (new_lsa_callback (funclist, lsa) != 0)
                   1226:     goto out;
                   1227: 
                   1228:   funclist = ospf_opaque_type9_funclist;
                   1229:   if (new_lsa_callback (funclist, lsa) != 0)
                   1230:     goto out;
                   1231: 
                   1232:   funclist = ospf_opaque_type10_funclist;
                   1233:   if (new_lsa_callback (funclist, lsa) != 0)
                   1234:     goto out;
                   1235: 
                   1236:   funclist = ospf_opaque_type11_funclist;
                   1237:   if (new_lsa_callback (funclist, lsa) != 0)
                   1238:     goto out;
                   1239: 
                   1240:   rc = 0;
                   1241: out:
                   1242:   return rc;
                   1243: }
                   1244: 
                   1245: static int
                   1246: ospf_opaque_lsa_delete_hook (struct ospf_lsa *lsa)
                   1247: {
                   1248:   struct list *funclist;
                   1249:   int rc = -1;
                   1250: 
                   1251:   /*
                   1252:    * Some Opaque-LSA user may want to monitor every LSA deletion
                   1253:    * from the LSDB, regardless with target LSA type.
                   1254:    */
                   1255:   funclist = ospf_opaque_wildcard_funclist;
                   1256:   if (del_lsa_callback (funclist, lsa) != 0)
                   1257:     goto out;
                   1258: 
                   1259:   funclist = ospf_opaque_type9_funclist;
                   1260:   if (del_lsa_callback (funclist, lsa) != 0)
                   1261:     goto out;
                   1262: 
                   1263:   funclist = ospf_opaque_type10_funclist;
                   1264:   if (del_lsa_callback (funclist, lsa) != 0)
                   1265:     goto out;
                   1266: 
                   1267:   funclist = ospf_opaque_type11_funclist;
                   1268:   if (del_lsa_callback (funclist, lsa) != 0)
                   1269:     goto out;
                   1270: 
                   1271:   rc = 0;
                   1272: out:
                   1273:   return rc;
                   1274: }
                   1275: 
                   1276: /*------------------------------------------------------------------------*
                   1277:  * Followings are Opaque-LSA origination/refresh management functions.
                   1278:  *------------------------------------------------------------------------*/
                   1279: 
                   1280: static int ospf_opaque_type9_lsa_originate (struct thread *t);
                   1281: static int ospf_opaque_type10_lsa_originate (struct thread *t);
                   1282: static int ospf_opaque_type11_lsa_originate (struct thread *t);
                   1283: static void ospf_opaque_lsa_reoriginate_resume (struct list *listtop, void *arg);
                   1284: 
                   1285: void
                   1286: ospf_opaque_lsa_originate_schedule (struct ospf_interface *oi, int *delay0)
                   1287: {
                   1288:   struct ospf *top;
                   1289:   struct ospf_area *area;
                   1290:   struct listnode *node, *nnode;
                   1291:   struct opaque_info_per_type *oipt;
                   1292:   int delay = 0;
                   1293: 
                   1294:   if ((top = oi_to_top (oi)) == NULL || (area = oi->area) == NULL)
                   1295:     {
                   1296:       zlog_warn ("ospf_opaque_lsa_originate_schedule: Invalid argument?");
                   1297:       goto out;
                   1298:     }
                   1299: 
                   1300:   /* It may not a right time to schedule origination now. */
                   1301:   if (! CHECK_FLAG (top->opaque, OPAQUE_OPERATION_READY_BIT))
                   1302:     {
                   1303:       if (IS_DEBUG_OSPF_EVENT)
                   1304:         zlog_debug ("ospf_opaque_lsa_originate_schedule: Not operational.");
                   1305:       goto out; /* This is not an error. */
                   1306:     }
1.1.1.3 ! misho    1307:   
1.1       misho    1308:   if (delay0 != NULL)
                   1309:     delay = *delay0;
                   1310: 
                   1311:   /*
                   1312:    * There might be some entries that have been waiting for triggering
                   1313:    * of per opaque-type re-origination get resumed.
                   1314:    */
                   1315:   ospf_opaque_lsa_reoriginate_resume (  oi->opaque_lsa_self, (void *)   oi);
                   1316:   ospf_opaque_lsa_reoriginate_resume (area->opaque_lsa_self, (void *) area);
                   1317:   ospf_opaque_lsa_reoriginate_resume ( top->opaque_lsa_self, (void *)  top);
                   1318: 
                   1319:   /*
                   1320:    * Now, schedule origination of all Opaque-LSAs per opaque-type.
                   1321:    */
                   1322:   if (! list_isempty (ospf_opaque_type9_funclist)
                   1323:   &&    list_isempty (oi->opaque_lsa_self)
                   1324:   &&    oi->t_opaque_lsa_self == NULL)
                   1325:     {
                   1326:       if (IS_DEBUG_OSPF_EVENT)
1.1.1.3 ! misho    1327:         zlog_debug ("Schedule Type-9 Opaque-LSA origination in %d ms later.", delay);
1.1       misho    1328:       oi->t_opaque_lsa_self =
1.1.1.3 ! misho    1329:        thread_add_timer_msec (master, ospf_opaque_type9_lsa_originate, oi, delay);
        !          1330:       delay += top->min_ls_interval;
1.1       misho    1331:     }
                   1332: 
                   1333:   if (! list_isempty (ospf_opaque_type10_funclist)
                   1334:   &&    list_isempty (area->opaque_lsa_self)
                   1335:   &&    area->t_opaque_lsa_self == NULL)
                   1336:     {
                   1337:       /*
                   1338:        * One AREA may contain multiple OIs, but above 2nd and 3rd
                   1339:        * conditions prevent from scheduling the originate function
                   1340:        * again and again.
                   1341:        */
                   1342:       if (IS_DEBUG_OSPF_EVENT)
1.1.1.3 ! misho    1343:         zlog_debug ("Schedule Type-10 Opaque-LSA origination in %d ms later.", delay);
1.1       misho    1344:       area->t_opaque_lsa_self =
1.1.1.3 ! misho    1345:         thread_add_timer_msec (master, ospf_opaque_type10_lsa_originate,
1.1       misho    1346:                           area, delay);
1.1.1.3 ! misho    1347:       delay += top->min_ls_interval;
1.1       misho    1348:     }
                   1349: 
                   1350:   if (! list_isempty (ospf_opaque_type11_funclist)
                   1351:   &&    list_isempty (top->opaque_lsa_self)
                   1352:   &&    top->t_opaque_lsa_self == NULL)
                   1353:     {
                   1354:       /*
                   1355:        * One OSPF may contain multiple AREAs, but above 2nd and 3rd
                   1356:        * conditions prevent from scheduling the originate function
                   1357:        * again and again.
                   1358:        */
                   1359:       if (IS_DEBUG_OSPF_EVENT)
1.1.1.3 ! misho    1360:         zlog_debug ("Schedule Type-11 Opaque-LSA origination in %d ms later.", delay);
1.1       misho    1361:       top->t_opaque_lsa_self =
1.1.1.3 ! misho    1362:         thread_add_timer_msec (master, ospf_opaque_type11_lsa_originate,
1.1       misho    1363:                           top, delay);
1.1.1.3 ! misho    1364:       delay += top->min_ls_interval;
1.1       misho    1365:     }
                   1366: 
                   1367:   /*
                   1368:    * Following section treats a special situation that this node's
                   1369:    * opaque capability has changed as "ON -> OFF -> ON".
                   1370:    */
                   1371:   if (! list_isempty (ospf_opaque_type9_funclist)
                   1372:   &&  ! list_isempty (oi->opaque_lsa_self))
                   1373:     {
                   1374:       for (ALL_LIST_ELEMENTS (oi->opaque_lsa_self, node, nnode, oipt))
                   1375:         {
                   1376:          /* 
                   1377:           * removed the test for
                   1378:           *   (! list_isempty (oipt->id_list))   * Handler is already active. *
                   1379:            * because opaque cababilities ON -> OFF -> ON result in list_isempty (oipt->id_list)
                   1380:           * not being empty.
                   1381:           */
                   1382:           if (oipt->t_opaque_lsa_self != NULL /* Waiting for a thread call. */
                   1383:               || oipt->status == PROC_SUSPEND)   /* Cannot originate now. */
                   1384:               continue;
                   1385: 
                   1386:           ospf_opaque_lsa_reoriginate_schedule ((void *) oi,
                   1387:             OSPF_OPAQUE_LINK_LSA, oipt->opaque_type);
                   1388:         }
                   1389:     }
                   1390: 
                   1391:   if (! list_isempty (ospf_opaque_type10_funclist)
                   1392:   &&  ! list_isempty (area->opaque_lsa_self))
                   1393:     {
                   1394:       for (ALL_LIST_ELEMENTS (area->opaque_lsa_self, node, nnode, oipt))
                   1395:         {
                   1396:          /* 
                   1397:           * removed the test for
                   1398:           *   (! list_isempty (oipt->id_list))   * Handler is already active. *
                   1399:            * because opaque cababilities ON -> OFF -> ON result in list_isempty (oipt->id_list)
                   1400:           * not being empty.
                   1401:           */
                   1402:           if (oipt->t_opaque_lsa_self != NULL /* Waiting for a thread call. */
                   1403:               || oipt->status == PROC_SUSPEND)   /* Cannot originate now. */
                   1404:             continue;
                   1405: 
                   1406:           ospf_opaque_lsa_reoriginate_schedule ((void *) area,
                   1407:             OSPF_OPAQUE_AREA_LSA, oipt->opaque_type);
                   1408:         }
                   1409:     }
                   1410: 
                   1411:   if (! list_isempty (ospf_opaque_type11_funclist)
                   1412:   &&  ! list_isempty (top->opaque_lsa_self))
                   1413:     {
                   1414:       for (ALL_LIST_ELEMENTS (top->opaque_lsa_self, node, nnode, oipt))
                   1415:         {
                   1416:          /* 
                   1417:           * removed the test for
                   1418:           *   (! list_isempty (oipt->id_list))   * Handler is already active. *
                   1419:            * because opaque cababilities ON -> OFF -> ON result in list_isempty (oipt->id_list)
                   1420:           * not being empty.
                   1421:           */
                   1422:           if (oipt->t_opaque_lsa_self != NULL /* Waiting for a thread call. */
                   1423:               || oipt->status == PROC_SUSPEND)   /* Cannot originate now. */
                   1424:             continue;
                   1425: 
                   1426:           ospf_opaque_lsa_reoriginate_schedule ((void *) top,
                   1427:             OSPF_OPAQUE_AS_LSA, oipt->opaque_type);
                   1428:         }
                   1429:     }
                   1430: 
                   1431:   if (delay0 != NULL)
                   1432:     *delay0 = delay;
                   1433: 
                   1434: out:
                   1435:   return;
                   1436: }
                   1437: 
                   1438: static int
                   1439: ospf_opaque_type9_lsa_originate (struct thread *t)
                   1440: {
                   1441:   struct ospf_interface *oi;
                   1442:   int rc;
                   1443: 
                   1444:   oi = THREAD_ARG (t);
                   1445:   oi->t_opaque_lsa_self = NULL;
                   1446: 
                   1447:   if (IS_DEBUG_OSPF_EVENT)
                   1448:     zlog_debug ("Timer[Type9-LSA]: Originate Opaque-LSAs for OI %s",
                   1449:                 IF_NAME (oi));
                   1450: 
                   1451:   rc = opaque_lsa_originate_callback (ospf_opaque_type9_funclist, oi);
                   1452: 
                   1453:   return rc;
                   1454: }
                   1455: 
                   1456: static int
                   1457: ospf_opaque_type10_lsa_originate (struct thread *t)
                   1458: {
                   1459:   struct ospf_area *area;
                   1460:   int rc;
                   1461: 
                   1462:   area = THREAD_ARG (t);
                   1463:   area->t_opaque_lsa_self = NULL;
                   1464: 
                   1465:   if (IS_DEBUG_OSPF_EVENT)
                   1466:     zlog_debug ("Timer[Type10-LSA]: Originate Opaque-LSAs for Area %s",
                   1467:                 inet_ntoa (area->area_id));
                   1468: 
                   1469:   rc = opaque_lsa_originate_callback (ospf_opaque_type10_funclist, area);
                   1470: 
                   1471:   return rc;
                   1472: }
                   1473: 
                   1474: static int
                   1475: ospf_opaque_type11_lsa_originate (struct thread *t)
                   1476: {
                   1477:   struct ospf *top;
                   1478:   int rc;
                   1479: 
                   1480:   top = THREAD_ARG (t);
                   1481:   top->t_opaque_lsa_self = NULL;
                   1482: 
                   1483:   if (IS_DEBUG_OSPF_EVENT)
                   1484:     zlog_debug ("Timer[Type11-LSA]: Originate AS-External Opaque-LSAs");
                   1485: 
                   1486:   rc = opaque_lsa_originate_callback (ospf_opaque_type11_funclist, top);
                   1487: 
                   1488:   return rc;
                   1489: }
                   1490: 
                   1491: static void
                   1492: ospf_opaque_lsa_reoriginate_resume (struct list *listtop, void *arg)
                   1493: {
                   1494:   struct listnode *node, *nnode;
                   1495:   struct opaque_info_per_type *oipt;
                   1496:   struct ospf_opaque_functab *functab;
                   1497: 
                   1498:   if (listtop == NULL)
                   1499:     goto out;
                   1500: 
                   1501:   /*
                   1502:    * Pickup oipt entries those which in SUSPEND status, and give
                   1503:    * them a chance to start re-origination now.
                   1504:    */
                   1505:   for (ALL_LIST_ELEMENTS (listtop, node, nnode, oipt))
                   1506:     {
                   1507:       if (oipt->status != PROC_SUSPEND)
                   1508:           continue;
                   1509: 
                   1510:       oipt->status = PROC_NORMAL;
                   1511: 
                   1512:       if ((functab = oipt->functab) == NULL
                   1513:           || functab->lsa_originator  == NULL)
                   1514:         continue;
                   1515: 
                   1516:       if ((* functab->lsa_originator)(arg) != 0)
                   1517:         {
                   1518:           zlog_warn ("ospf_opaque_lsa_reoriginate_resume: Failed (opaque-type=%u)", oipt->opaque_type);
                   1519:           continue;
                   1520:         }
                   1521:     }
                   1522: 
                   1523: out:
                   1524:   return;
                   1525: }
                   1526: 
                   1527: struct ospf_lsa *
                   1528: ospf_opaque_lsa_install (struct ospf_lsa *lsa, int rt_recalc)
                   1529: {
                   1530:   struct ospf_lsa *new = NULL;
                   1531:   struct opaque_info_per_type *oipt;
                   1532:   struct opaque_info_per_id *oipi;
                   1533:   struct ospf *top;
                   1534: 
                   1535:   /* Don't take "rt_recalc" into consideration for now. *//* XXX */
                   1536: 
                   1537:   if (! IS_LSA_SELF (lsa))
                   1538:     {
                   1539:       new = lsa; /* Don't touch this LSA. */
                   1540:       goto out;
                   1541:     }
                   1542: 
                   1543:   if (IS_DEBUG_OSPF (lsa, LSA_INSTALL))
                   1544:     zlog_debug ("Install Type-%u Opaque-LSA: [opaque-type=%u, opaque-id=%x]", lsa->data->type, GET_OPAQUE_TYPE (ntohl (lsa->data->id.s_addr)), GET_OPAQUE_ID (ntohl (lsa->data->id.s_addr)));
                   1545: 
                   1546:   /* Replace the existing lsa with the new one. */
                   1547:   if ((oipt = lookup_opaque_info_by_type (lsa)) != NULL
                   1548:       && (oipi = lookup_opaque_info_by_id (oipt, lsa)) != NULL)
                   1549:     {
                   1550:       ospf_lsa_unlock (&oipi->lsa);
                   1551:       oipi->lsa = ospf_lsa_lock (lsa);
                   1552:     }
                   1553:   /* Register the new lsa entry and get its control info. */
                   1554:   else
                   1555:   if ((oipi = register_opaque_lsa (lsa)) == NULL)
                   1556:     {
                   1557:       zlog_warn ("ospf_opaque_lsa_install: register_opaque_lsa() ?");
                   1558:       goto out;
                   1559:     }
                   1560: 
                   1561:   /*
                   1562:    * Make use of a common mechanism (ospf_lsa_refresh_walker)
                   1563:    * for periodic refresh of self-originated Opaque-LSAs.
                   1564:    */
                   1565:   switch (lsa->data->type)
                   1566:     {
                   1567:     case OSPF_OPAQUE_LINK_LSA:
                   1568:       if ((top = oi_to_top (lsa->oi)) == NULL)
                   1569:         {
                   1570:           /* Above conditions must have passed. */
                   1571:           zlog_warn ("ospf_opaque_lsa_install: Sonmething wrong?");
                   1572:           goto out;
                   1573:         }
                   1574:       break;
                   1575:     case OSPF_OPAQUE_AREA_LSA:
                   1576:       if (lsa->area == NULL || (top = lsa->area->ospf) == NULL)
                   1577:         {
                   1578:           /* Above conditions must have passed. */
                   1579:           zlog_warn ("ospf_opaque_lsa_install: Sonmething wrong?");
                   1580:           goto out;
                   1581:         }
                   1582:       break;
                   1583:     case OSPF_OPAQUE_AS_LSA:
                   1584:       top = ospf_lookup ();
                   1585:       if (lsa->area != NULL && (top = lsa->area->ospf) == NULL)
                   1586:         {
                   1587:           /* Above conditions must have passed. */
                   1588:           zlog_warn ("ospf_opaque_lsa_install: Sonmething wrong?");
                   1589:           goto out;
                   1590:         }
                   1591:       break;
                   1592:     default:
                   1593:       zlog_warn ("ospf_opaque_lsa_install: Unexpected LSA-type(%u)", lsa->data->type);
                   1594:       goto out;
                   1595:     }
                   1596: 
                   1597:   ospf_refresher_register_lsa (top, lsa);
                   1598:   new = lsa;
                   1599: 
                   1600: out:
                   1601:   return new;
                   1602: }
                   1603: 
                   1604: struct ospf_lsa *
                   1605: ospf_opaque_lsa_refresh (struct ospf_lsa *lsa)
                   1606: {
                   1607:   struct ospf *ospf;
                   1608:   struct ospf_opaque_functab *functab;
                   1609:   struct ospf_lsa *new = NULL;
                   1610:   
                   1611:   ospf = ospf_lookup ();
                   1612: 
                   1613:   if ((functab = ospf_opaque_functab_lookup (lsa)) == NULL
                   1614:       || functab->lsa_refresher == NULL)
                   1615:     {
                   1616:       /*
                   1617:        * Though this LSA seems to have originated on this node, the
                   1618:        * handling module for this "lsa-type and opaque-type" was
                   1619:        * already deleted sometime ago.
                   1620:        * Anyway, this node still has a responsibility to flush this
                   1621:        * LSA from the routing domain.
                   1622:        */
                   1623:       if (IS_DEBUG_OSPF_EVENT)
                   1624:         zlog_debug ("LSA[Type%d:%s]: Flush stray Opaque-LSA", lsa->data->type, inet_ntoa (lsa->data->id));
                   1625: 
                   1626:       lsa->data->ls_age = htons (OSPF_LSA_MAXAGE);
                   1627:       ospf_lsa_flush (ospf, lsa);
                   1628:     }
                   1629:   else
                   1630:     new = (* functab->lsa_refresher)(lsa);
                   1631: 
                   1632:   return new;
                   1633: }
                   1634: 
                   1635: /*------------------------------------------------------------------------*
                   1636:  * Followings are re-origination/refresh/flush operations of Opaque-LSAs,
                   1637:  * triggered by external interventions (vty session, signaling, etc).
                   1638:  *------------------------------------------------------------------------*/
                   1639: 
                   1640: #define OSPF_OPAQUE_TIMER_ON(T,F,L,V) \
                   1641:       if (!(T)) \
1.1.1.3 ! misho    1642:         (T) = thread_add_timer_msec (master, (F), (L), (V))
1.1       misho    1643: 
                   1644: static struct ospf_lsa *pseudo_lsa (struct ospf_interface *oi, struct ospf_area *area, u_char lsa_type, u_char opaque_type);
                   1645: static int ospf_opaque_type9_lsa_reoriginate_timer (struct thread *t);
                   1646: static int ospf_opaque_type10_lsa_reoriginate_timer (struct thread *t);
                   1647: static int ospf_opaque_type11_lsa_reoriginate_timer (struct thread *t);
                   1648: static int ospf_opaque_lsa_refresh_timer (struct thread *t);
                   1649: 
                   1650: void
                   1651: ospf_opaque_lsa_reoriginate_schedule (void *lsa_type_dependent,
                   1652:                                       u_char lsa_type, u_char opaque_type)
                   1653: {
                   1654:   struct ospf *top;
                   1655:   struct ospf_area dummy, *area = NULL;
                   1656:   struct ospf_interface *oi = NULL;
                   1657: 
                   1658:   struct ospf_lsa *lsa;
                   1659:   struct opaque_info_per_type *oipt;
                   1660:   int (*func) (struct thread * t) = NULL;
                   1661:   int delay;
                   1662: 
                   1663:   switch (lsa_type)
                   1664:     {
                   1665:     case OSPF_OPAQUE_LINK_LSA:
                   1666:       if ((oi = (struct ospf_interface *) lsa_type_dependent) == NULL)
                   1667:         {
                   1668:           zlog_warn ("ospf_opaque_lsa_reoriginate_schedule:"
                   1669:                      " Type-9 Opaque-LSA: Invalid parameter?");
                   1670:           goto out;
                   1671:         }
                   1672:       if ((top = oi_to_top (oi)) == NULL)
                   1673:         {
                   1674:           zlog_warn ("ospf_opaque_lsa_reoriginate_schedule: OI(%s) -> TOP?",
                   1675:                      IF_NAME (oi));
                   1676:           goto out;
                   1677:         }
                   1678:       if (!list_isempty (ospf_opaque_type9_funclist)
                   1679:           && list_isempty (oi->opaque_lsa_self)
                   1680:           && oi->t_opaque_lsa_self != NULL)
                   1681:         {
                   1682:           zlog_warn ("Type-9 Opaque-LSA (opaque_type=%u):"
                   1683:                      " Common origination for OI(%s) has already started",
                   1684:                      opaque_type, IF_NAME (oi));
                   1685:           goto out;
                   1686:         }
                   1687:       func = ospf_opaque_type9_lsa_reoriginate_timer;
                   1688:       break;
                   1689:     case OSPF_OPAQUE_AREA_LSA:
                   1690:       if ((area = (struct ospf_area *) lsa_type_dependent) == NULL)
                   1691:         {
                   1692:           zlog_warn ("ospf_opaque_lsa_reoriginate_schedule:"
                   1693:                      " Type-10 Opaque-LSA: Invalid parameter?");
                   1694:           goto out;
                   1695:         }
                   1696:       if ((top = area->ospf) == NULL)
                   1697:         {
                   1698:           zlog_warn ("ospf_opaque_lsa_reoriginate_schedule:"
                   1699:                      " AREA(%s) -> TOP?", inet_ntoa (area->area_id));
                   1700:           goto out;
                   1701:         }
                   1702:       if (!list_isempty (ospf_opaque_type10_funclist)
                   1703:           && list_isempty (area->opaque_lsa_self)
                   1704:           && area->t_opaque_lsa_self != NULL)
                   1705:         {
                   1706:           zlog_warn ("Type-10 Opaque-LSA (opaque_type=%u):"
                   1707:                      " Common origination for AREA(%s) has already started",
                   1708:                      opaque_type, inet_ntoa (area->area_id));
                   1709:           goto out;
                   1710:         }
                   1711:       func = ospf_opaque_type10_lsa_reoriginate_timer;
                   1712:       break;
                   1713:     case OSPF_OPAQUE_AS_LSA:
                   1714:       if ((top = (struct ospf *) lsa_type_dependent) == NULL)
                   1715:         {
                   1716:           zlog_warn ("ospf_opaque_lsa_reoriginate_schedule:"
                   1717:                      " Type-11 Opaque-LSA: Invalid parameter?");
                   1718:           goto out;
                   1719:         }
                   1720:       if (!list_isempty (ospf_opaque_type11_funclist)
                   1721:           && list_isempty (top->opaque_lsa_self)
                   1722:           && top->t_opaque_lsa_self != NULL)
                   1723:         {
                   1724:           zlog_warn ("Type-11 Opaque-LSA (opaque_type=%u):"
                   1725:                      " Common origination has already started", opaque_type);
                   1726:           goto out;
                   1727:         }
                   1728: 
                   1729:       /* Fake "area" to pass "ospf" to a lookup function later. */
                   1730:       dummy.ospf = top;
                   1731:       area = &dummy;
                   1732: 
                   1733:       func = ospf_opaque_type11_lsa_reoriginate_timer;
                   1734:       break;
                   1735:     default:
                   1736:       zlog_warn ("ospf_opaque_lsa_reoriginate_schedule:"
                   1737:                  " Unexpected LSA-type(%u)",
                   1738:                  lsa_type);
                   1739:       goto out;
                   1740:     }
                   1741: 
                   1742:   /* It may not a right time to schedule reorigination now. */
                   1743:   if (!CHECK_FLAG (top->opaque, OPAQUE_OPERATION_READY_BIT))
                   1744:     {
                   1745:       if (IS_DEBUG_OSPF_EVENT)
                   1746:         zlog_debug ("ospf_opaque_lsa_reoriginate_schedule: Not operational.");
                   1747:       goto out;                 /* This is not an error. */
                   1748:     }
1.1.1.3 ! misho    1749:   
1.1       misho    1750:   /* Generate a dummy lsa to be passed for a lookup function. */
                   1751:   lsa = pseudo_lsa (oi, area, lsa_type, opaque_type);
                   1752: 
                   1753:   if ((oipt = lookup_opaque_info_by_type (lsa)) == NULL)
                   1754:     {
                   1755:       struct ospf_opaque_functab *functab;
                   1756:       if ((functab = ospf_opaque_functab_lookup (lsa)) == NULL)
                   1757:         {
                   1758:           zlog_warn ("ospf_opaque_lsa_reoriginate_schedule:"
                   1759:                      " No associated function?: lsa_type(%u),"
                   1760:                      " opaque_type(%u)",
                   1761:                      lsa_type, opaque_type);
                   1762:           goto out;
                   1763:         }
                   1764:       if ((oipt = register_opaque_info_per_type (functab, lsa)) == NULL)
                   1765:         {
                   1766:           zlog_warn ("ospf_opaque_lsa_reoriginate_schedule:"
                   1767:                      " Cannot get a control info?: lsa_type(%u),"
                   1768:                      " opaque_type(%u)",
                   1769:                      lsa_type, opaque_type);
                   1770:           goto out;
                   1771:         }
                   1772:     }
                   1773: 
                   1774:   if (oipt->t_opaque_lsa_self != NULL)
                   1775:     {
                   1776:       if (IS_DEBUG_OSPF_EVENT)
                   1777:         zlog_debug ("Type-%u Opaque-LSA has already scheduled to"
                   1778:                    " RE-ORIGINATE: [opaque-type=%u]",
                   1779:                    lsa_type, GET_OPAQUE_TYPE (ntohl (lsa->data->id.s_addr)));
                   1780:       goto out;
                   1781:     }
                   1782: 
                   1783:   /*
                   1784:    * Different from initial origination time, in which various conditions
                   1785:    * (opaque capability, neighbor status etc) are assured by caller of
                   1786:    * the originating function "ospf_opaque_lsa_originate_schedule ()",
                   1787:    * it is highly possible that these conditions might not be satisfied
                   1788:    * at the time of re-origination function is to be called.
                   1789:    */
1.1.1.3 ! misho    1790:   delay = top->min_ls_interval; /* XXX */
1.1       misho    1791: 
                   1792:   if (IS_DEBUG_OSPF_EVENT)
                   1793:     zlog_debug ("Schedule Type-%u Opaque-LSA to RE-ORIGINATE in %d"
1.1.1.3 ! misho    1794:                " ms later: [opaque-type=%u]",
1.1       misho    1795:                lsa_type, delay, 
                   1796:                GET_OPAQUE_TYPE (ntohl (lsa->data->id.s_addr)));
                   1797: 
                   1798:   OSPF_OPAQUE_TIMER_ON (oipt->t_opaque_lsa_self, func, oipt, delay);
                   1799: 
                   1800: out:
                   1801:   return;
                   1802: }
                   1803: 
                   1804: static struct ospf_lsa *
                   1805: pseudo_lsa (struct ospf_interface *oi, struct ospf_area *area,
                   1806:             u_char lsa_type, u_char opaque_type)
                   1807: {
                   1808:   static struct ospf_lsa lsa = { 0 };
                   1809:   static struct lsa_header lsah = { 0 };
                   1810:   u_int32_t tmp;
                   1811: 
                   1812:   lsa.oi   = oi;
                   1813:   lsa.area = area;
                   1814:   lsa.data = &lsah;
                   1815: 
                   1816:   lsah.type = lsa_type;
                   1817:   tmp = SET_OPAQUE_LSID (opaque_type, 0); /* Opaque-ID is unused here. */
                   1818:   lsah.id.s_addr = htonl (tmp);
                   1819: 
                   1820:   return &lsa;
                   1821: }
                   1822: 
                   1823: static int
                   1824: ospf_opaque_type9_lsa_reoriginate_timer (struct thread *t)
                   1825: {
                   1826:   struct opaque_info_per_type *oipt;
                   1827:   struct ospf_opaque_functab *functab;
                   1828:   struct ospf *top;
                   1829:   struct ospf_interface *oi;
                   1830:   int rc = -1;
                   1831: 
                   1832:   oipt = THREAD_ARG (t);
                   1833:   oipt->t_opaque_lsa_self = NULL;
                   1834: 
                   1835:   if ((functab = oipt->functab) == NULL
                   1836:   ||   functab->lsa_originator == NULL)
                   1837:     {
                   1838:       zlog_warn ("ospf_opaque_type9_lsa_reoriginate_timer: No associated function?");
                   1839:       goto out;
                   1840:     }
                   1841: 
                   1842:   oi = (struct ospf_interface *) oipt->owner;
                   1843:   if ((top = oi_to_top (oi)) == NULL)
                   1844:     {
                   1845:       zlog_warn ("ospf_opaque_type9_lsa_reoriginate_timer: Something wrong?");
                   1846:       goto out;
                   1847:     }
                   1848: 
                   1849:   if (! CHECK_FLAG (top->config, OSPF_OPAQUE_CAPABLE)
                   1850:   ||  ! ospf_if_is_enable (oi)
                   1851:   ||    ospf_nbr_count_opaque_capable (oi) == 0)
                   1852:     {
                   1853:       if (IS_DEBUG_OSPF_EVENT)
                   1854:         zlog_debug ("Suspend re-origination of Type-9 Opaque-LSAs (opaque-type=%u) for a while...", oipt->opaque_type);
                   1855:     
                   1856:       oipt->status = PROC_SUSPEND;
                   1857:       rc = 0;
                   1858:       goto out;
                   1859:     }
                   1860: 
                   1861:   if (IS_DEBUG_OSPF_EVENT)
                   1862:     zlog_debug ("Timer[Type9-LSA]: Re-originate Opaque-LSAs (opaque-type=%u) for OI (%s)", oipt->opaque_type, IF_NAME (oi));
                   1863: 
                   1864:   rc = (* functab->lsa_originator)(oi);
                   1865: out:
                   1866:   return rc;
                   1867: }
                   1868: 
                   1869: static int
                   1870: ospf_opaque_type10_lsa_reoriginate_timer (struct thread *t)
                   1871: {
                   1872:   struct opaque_info_per_type *oipt;
                   1873:   struct ospf_opaque_functab *functab;
                   1874:   struct listnode *node, *nnode;
                   1875:   struct ospf *top;
                   1876:   struct ospf_area *area;
                   1877:   struct ospf_interface *oi;
                   1878:   int n, rc = -1;
                   1879: 
                   1880:   oipt = THREAD_ARG (t);
                   1881:   oipt->t_opaque_lsa_self = NULL;
                   1882: 
                   1883:   if ((functab = oipt->functab) == NULL
                   1884:   ||   functab->lsa_originator == NULL)
                   1885:     {
                   1886:       zlog_warn ("ospf_opaque_type10_lsa_reoriginate_timer: No associated function?");
                   1887:       goto out;
                   1888:     }
                   1889: 
                   1890:   area = (struct ospf_area *) oipt->owner;
                   1891:   if (area == NULL || (top = area->ospf) == NULL)
                   1892:     {
                   1893:       zlog_warn ("ospf_opaque_type10_lsa_reoriginate_timer: Something wrong?");
                   1894:       goto out;
                   1895:     }
                   1896: 
                   1897:   /* There must be at least one "opaque-capable, full-state" neighbor. */
                   1898:   n = 0;
                   1899:   for (ALL_LIST_ELEMENTS (area->oiflist, node, nnode, oi))
                   1900:     {
                   1901:       if ((n = ospf_nbr_count_opaque_capable (oi)) > 0)
                   1902:         break;
                   1903:     }
                   1904: 
                   1905:   if (n == 0 || ! CHECK_FLAG (top->config, OSPF_OPAQUE_CAPABLE))
                   1906:     {
                   1907:       if (IS_DEBUG_OSPF_EVENT)
                   1908:         zlog_debug ("Suspend re-origination of Type-10 Opaque-LSAs"
                   1909:                    " (opaque-type=%u) for a while...", 
                   1910:                    oipt->opaque_type);
                   1911: 
                   1912:       oipt->status = PROC_SUSPEND;
                   1913:       rc = 0;
                   1914:       goto out;
                   1915:     }
                   1916: 
                   1917:   if (IS_DEBUG_OSPF_EVENT)
                   1918:     zlog_debug ("Timer[Type10-LSA]: Re-originate Opaque-LSAs"
                   1919:                " (opaque-type=%u) for Area %s", 
                   1920:                oipt->opaque_type, inet_ntoa (area->area_id));
                   1921: 
                   1922:   rc = (* functab->lsa_originator)(area);
                   1923: out:
                   1924:   return rc;
                   1925: }
                   1926: 
                   1927: static int
                   1928: ospf_opaque_type11_lsa_reoriginate_timer (struct thread *t)
                   1929: {
                   1930:   struct opaque_info_per_type *oipt;
                   1931:   struct ospf_opaque_functab *functab;
                   1932:   struct ospf *top;
                   1933:   int rc = -1;
                   1934: 
                   1935:   oipt = THREAD_ARG (t);
                   1936:   oipt->t_opaque_lsa_self = NULL;
                   1937: 
                   1938:   if ((functab = oipt->functab) == NULL
                   1939:       || functab->lsa_originator == NULL)
                   1940:     {
                   1941:       zlog_warn ("ospf_opaque_type11_lsa_reoriginate_timer:"
                   1942:                  " No associated function?");
                   1943:       goto out;
                   1944:     }
                   1945: 
                   1946:   if ((top = (struct ospf *) oipt->owner) == NULL)
                   1947:     {
                   1948:       zlog_warn ("ospf_opaque_type11_lsa_reoriginate_timer: Something wrong?");
                   1949:       goto out;
                   1950:     }
                   1951: 
                   1952:   if (! CHECK_FLAG (top->config, OSPF_OPAQUE_CAPABLE))
                   1953:     {
                   1954:       if (IS_DEBUG_OSPF_EVENT)
                   1955:         zlog_debug ("Suspend re-origination of Type-11 Opaque-LSAs (opaque-type=%u) for a while...", oipt->opaque_type);
                   1956:     
                   1957:       oipt->status = PROC_SUSPEND;
                   1958:       rc = 0;
                   1959:       goto out;
                   1960:     }
                   1961: 
                   1962:   if (IS_DEBUG_OSPF_EVENT)
                   1963:     zlog_debug ("Timer[Type11-LSA]: Re-originate Opaque-LSAs (opaque-type=%u).", oipt->opaque_type);
                   1964: 
                   1965:   rc = (* functab->lsa_originator)(top);
                   1966: out:
                   1967:   return rc;
                   1968: }
                   1969: 
                   1970: void
                   1971: ospf_opaque_lsa_refresh_schedule (struct ospf_lsa *lsa0)
                   1972: {
                   1973:   struct opaque_info_per_type *oipt;
                   1974:   struct opaque_info_per_id *oipi;
                   1975:   struct ospf_lsa *lsa;
                   1976:   int delay;
                   1977: 
                   1978:   if ((oipt = lookup_opaque_info_by_type (lsa0)) == NULL
                   1979:   ||  (oipi = lookup_opaque_info_by_id (oipt, lsa0)) == NULL)
                   1980:     {
                   1981:       zlog_warn ("ospf_opaque_lsa_refresh_schedule: Invalid parameter?");
                   1982:       goto out;
                   1983:     }
                   1984: 
                   1985:   /* Given "lsa0" and current "oipi->lsa" may different, but harmless. */
                   1986:   if ((lsa = oipi->lsa) == NULL)
                   1987:     {
                   1988:       zlog_warn ("ospf_opaque_lsa_refresh_schedule: Something wrong?");
                   1989:       goto out;
                   1990:     }
                   1991: 
                   1992:   if (oipi->t_opaque_lsa_self != NULL)
                   1993:     {
                   1994:       if (IS_DEBUG_OSPF_EVENT)
                   1995:         zlog_debug ("Type-%u Opaque-LSA has already scheduled to REFRESH: [opaque-type=%u, opaque-id=%x]", lsa->data->type, GET_OPAQUE_TYPE (ntohl (lsa->data->id.s_addr)), GET_OPAQUE_ID (ntohl (lsa->data->id.s_addr)));
                   1996:       goto out;
                   1997:     }
                   1998: 
                   1999:   /* Delete this lsa from neighbor retransmit-list. */
                   2000:   switch (lsa->data->type)
                   2001:     {
                   2002:     case OSPF_OPAQUE_LINK_LSA:
                   2003:     case OSPF_OPAQUE_AREA_LSA:
                   2004:       ospf_ls_retransmit_delete_nbr_area (lsa->area, lsa);
                   2005:       break;
                   2006:     case OSPF_OPAQUE_AS_LSA:
                   2007:       ospf_ls_retransmit_delete_nbr_as (lsa0->area->ospf, lsa);
                   2008:       break;
                   2009:     default:
                   2010:       zlog_warn ("ospf_opaque_lsa_refresh_schedule: Unexpected LSA-type(%u)", lsa->data->type);
                   2011:       goto out;
                   2012:     }
                   2013: 
                   2014:   delay = ospf_lsa_refresh_delay (lsa);
                   2015: 
                   2016:   if (IS_DEBUG_OSPF_EVENT)
                   2017:     zlog_debug ("Schedule Type-%u Opaque-LSA to REFRESH in %d sec later: [opaque-type=%u, opaque-id=%x]", lsa->data->type, delay, GET_OPAQUE_TYPE (ntohl (lsa->data->id.s_addr)), GET_OPAQUE_ID (ntohl (lsa->data->id.s_addr)));
                   2018: 
                   2019:   OSPF_OPAQUE_TIMER_ON (oipi->t_opaque_lsa_self,
1.1.1.3 ! misho    2020:                         ospf_opaque_lsa_refresh_timer, oipi, delay * 1000);
1.1       misho    2021: out:
                   2022:   return;
                   2023: }
                   2024: 
                   2025: static int
                   2026: ospf_opaque_lsa_refresh_timer (struct thread *t)
                   2027: {
                   2028:   struct opaque_info_per_id *oipi;
                   2029:   struct ospf_opaque_functab *functab;
                   2030:   struct ospf_lsa *lsa;
                   2031: 
                   2032:   if (IS_DEBUG_OSPF_EVENT)
                   2033:     zlog_debug ("Timer[Opaque-LSA]: (Opaque-LSA Refresh expire)");
                   2034: 
                   2035:   oipi = THREAD_ARG (t);
                   2036:   oipi->t_opaque_lsa_self = NULL;
                   2037: 
                   2038:   if ((lsa = oipi->lsa) != NULL)
                   2039:     if ((functab = oipi->opqctl_type->functab) != NULL)
                   2040:       if (functab->lsa_refresher != NULL)
                   2041:         (* functab->lsa_refresher)(lsa);
                   2042: 
                   2043:   return 0;
                   2044: }
                   2045: 
                   2046: void
                   2047: ospf_opaque_lsa_flush_schedule (struct ospf_lsa *lsa0)
                   2048: {
                   2049:   struct opaque_info_per_type *oipt;
                   2050:   struct opaque_info_per_id *oipi;
                   2051:   struct ospf_lsa *lsa;
                   2052: 
                   2053:   if ((oipt = lookup_opaque_info_by_type (lsa0)) == NULL
                   2054:   ||  (oipi = lookup_opaque_info_by_id (oipt, lsa0)) == NULL)
                   2055:     {
                   2056:       zlog_warn ("ospf_opaque_lsa_flush_schedule: Invalid parameter?");
                   2057:       goto out;
                   2058:     }
                   2059: 
                   2060:   /* Given "lsa0" and current "oipi->lsa" may different, but harmless. */
                   2061:   if ((lsa = oipi->lsa) == NULL)
                   2062:     {
                   2063:       zlog_warn ("ospf_opaque_lsa_flush_schedule: Something wrong?");
                   2064:       goto out;
                   2065:     }
                   2066: 
                   2067:   /* Delete this lsa from neighbor retransmit-list. */
                   2068:   switch (lsa->data->type)
                   2069:     {
                   2070:     case OSPF_OPAQUE_LINK_LSA:
                   2071:     case OSPF_OPAQUE_AREA_LSA:
                   2072:       ospf_ls_retransmit_delete_nbr_area (lsa->area, lsa);
                   2073:       break;
                   2074:     case OSPF_OPAQUE_AS_LSA:
                   2075:       ospf_ls_retransmit_delete_nbr_as (lsa0->area->ospf, lsa);
                   2076:       break;
                   2077:     default:
                   2078:       zlog_warn ("ospf_opaque_lsa_flush_schedule: Unexpected LSA-type(%u)", lsa->data->type);
                   2079:       goto out;
                   2080:     }
                   2081: 
                   2082:   /* Dequeue listnode entry from the list. */
                   2083:   listnode_delete (oipt->id_list, oipi);
                   2084: 
                   2085:   /* Avoid misjudgement in the next lookup. */
                   2086:   if (listcount (oipt->id_list) == 0)
                   2087:     oipt->id_list->head = oipt->id_list->tail = NULL;
                   2088: 
                   2089:   /* Disassociate internal control information with the given lsa. */
                   2090:   free_opaque_info_per_id ((void *) oipi);
                   2091: 
                   2092:   /* Force given lsa's age to MaxAge. */
                   2093:   lsa->data->ls_age = htons (OSPF_LSA_MAXAGE);
                   2094: 
                   2095:   if (IS_DEBUG_OSPF_EVENT)
                   2096:     zlog_debug ("Schedule Type-%u Opaque-LSA to FLUSH: [opaque-type=%u, opaque-id=%x]", lsa->data->type, GET_OPAQUE_TYPE (ntohl (lsa->data->id.s_addr)), GET_OPAQUE_ID (ntohl (lsa->data->id.s_addr)));
                   2097: 
                   2098:   /* This lsa will be flushed and removed eventually. */
                   2099:   ospf_lsa_flush (lsa0->area->ospf, lsa);
                   2100: 
                   2101: out:
                   2102:   return;
                   2103: }
                   2104: 
                   2105: void
                   2106: ospf_opaque_self_originated_lsa_received (struct ospf_neighbor *nbr, 
                   2107:                                           struct ospf_lsa *lsa)
                   2108: {
                   2109:   struct ospf *top;
1.1.1.3 ! misho    2110:   
1.1       misho    2111:   if ((top = oi_to_top (nbr->oi)) == NULL)
                   2112:     return;
                   2113: 
                   2114:   /*
                   2115:    * Since these LSA entries are not yet installed into corresponding
                   2116:    * LSDB, just flush them without calling ospf_ls_maxage() afterward.
                   2117:    */
                   2118:   lsa->data->ls_age = htons (OSPF_LSA_MAXAGE);
                   2119:   switch (lsa->data->type)
                   2120:     {
                   2121:     case OSPF_OPAQUE_LINK_LSA:
                   2122:       ospf_flood_through_area (nbr->oi->area, NULL/*inbr*/, lsa);
                   2123:       break;
                   2124:     case OSPF_OPAQUE_AREA_LSA:
                   2125:       ospf_flood_through_area (nbr->oi->area, NULL/*inbr*/, lsa);
                   2126:       break;
                   2127:     case OSPF_OPAQUE_AS_LSA:
                   2128:       ospf_flood_through_as (top, NULL/*inbr*/, lsa);
                   2129:       break;
                   2130:     default:
                   2131:       zlog_warn ("ospf_opaque_self_originated_lsa_received: Unexpected LSA-type(%u)", lsa->data->type);
                   2132:       return;
                   2133:     }
1.1.1.3 ! misho    2134:   ospf_lsa_discard (lsa); /* List "lsas" will be deleted by caller. */  
1.1       misho    2135: }
                   2136: 
                   2137: /*------------------------------------------------------------------------*
                   2138:  * Followings are util functions; probably be used by Opaque-LSAs only...
                   2139:  *------------------------------------------------------------------------*/
                   2140: 
                   2141: void
                   2142: htonf (float *src, float *dst)
                   2143: {
                   2144:   u_int32_t lu1, lu2;
                   2145: 
                   2146:   memcpy (&lu1, src, sizeof (u_int32_t));
                   2147:   lu2 = htonl (lu1);
                   2148:   memcpy (dst, &lu2, sizeof (u_int32_t));
                   2149:   return;
                   2150: }
                   2151: 
                   2152: void
                   2153: ntohf (float *src, float *dst)
                   2154: {
                   2155:   u_int32_t lu1, lu2;
                   2156: 
                   2157:   memcpy (&lu1, src, sizeof (u_int32_t));
                   2158:   lu2 = ntohl (lu1);
                   2159:   memcpy (dst, &lu2, sizeof (u_int32_t));
                   2160:   return;
                   2161: }
                   2162: 
                   2163: struct ospf *
                   2164: oi_to_top (struct ospf_interface *oi)
                   2165: {
                   2166:   struct ospf *top = NULL;
                   2167:   struct ospf_area *area;
                   2168: 
                   2169:   if (oi == NULL || (area = oi->area) == NULL || (top = area->ospf) == NULL)
                   2170:     zlog_warn ("Broken relationship for \"OI -> AREA -> OSPF\"?");
                   2171: 
                   2172:   return top;
                   2173: }
                   2174: 

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