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

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

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