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