]> git.sommitrealweird.co.uk Git - quagga-debian.git/blob - ospf6d/ospf6_lsa.c
New upstream version 1.2.4
[quagga-debian.git] / ospf6d / ospf6_lsa.c
1 /*
2  * Copyright (C) 2003 Yasuhiro Ohara
3  *
4  * This file is part of GNU Zebra.
5  *
6  * GNU Zebra is free software; you can redistribute it and/or modify it
7  * under the terms of the GNU General Public License as published by the
8  * Free Software Foundation; either version 2, or (at your option) any
9  * later version.
10  *
11  * GNU Zebra is distributed in the hope that it will be useful, but
12  * WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with GNU Zebra; see the file COPYING.  If not, write to the 
18  * Free Software Foundation, Inc., 59 Temple Place - Suite 330, 
19  * Boston, MA 02111-1307, USA.  
20  */
21
22 #include <zebra.h>
23
24 /* Include other stuffs */
25 #include "log.h"
26 #include "linklist.h"
27 #include "vector.h"
28 #include "vty.h"
29 #include "command.h"
30 #include "memory.h"
31 #include "thread.h"
32 #include "checksum.h"
33
34 #include "ospf6_proto.h"
35 #include "ospf6_lsa.h"
36 #include "ospf6_lsdb.h"
37 #include "ospf6_message.h"
38
39 #include "ospf6_top.h"
40 #include "ospf6_area.h"
41 #include "ospf6_interface.h"
42 #include "ospf6_neighbor.h"
43
44 #include "ospf6_flood.h"
45 #include "ospf6d.h"
46
47 vector ospf6_lsa_handler_vector;
48
49 static int
50 ospf6_unknown_lsa_show (struct vty *vty, struct ospf6_lsa *lsa)
51 {
52   u_char *start, *end, *current;
53   char byte[4];
54
55   start = (u_char *) lsa->header + sizeof (struct ospf6_lsa_header);
56   end = (u_char *) lsa->header + ntohs (lsa->header->length);
57
58   vty_out (vty, "        Unknown contents:%s", VNL);
59   for (current = start; current < end; current ++)
60     {
61       if ((current - start) % 16 == 0)
62         vty_out (vty, "%s        ", VNL);
63       else if ((current - start) % 4 == 0)
64         vty_out (vty, " ");
65
66       snprintf (byte, sizeof (byte), "%02x", *current);
67       vty_out (vty, "%s", byte);
68     }
69
70   vty_out (vty, "%s%s", VNL, VNL);
71   return 0;
72 }
73
74 struct ospf6_lsa_handler unknown_handler =
75 {
76   OSPF6_LSTYPE_UNKNOWN,
77   "Unknown",
78   "Unk",
79   ospf6_unknown_lsa_show,
80   NULL,
81   OSPF6_LSA_DEBUG,
82 };
83
84 void
85 ospf6_install_lsa_handler (struct ospf6_lsa_handler *handler)
86 {
87   /* type in handler is host byte order */
88   int index = handler->type & OSPF6_LSTYPE_FCODE_MASK;
89   vector_set_index (ospf6_lsa_handler_vector, index, handler);
90 }
91
92 struct ospf6_lsa_handler *
93 ospf6_get_lsa_handler (u_int16_t type)
94 {
95   struct ospf6_lsa_handler *handler = NULL;
96   unsigned int index = ntohs (type) & OSPF6_LSTYPE_FCODE_MASK;
97
98   if (index >= vector_active (ospf6_lsa_handler_vector))
99     handler = &unknown_handler;
100   else
101     handler = vector_slot (ospf6_lsa_handler_vector, index);
102
103   if (handler == NULL)
104     handler = &unknown_handler;
105
106   return handler;
107 }
108
109 const char *
110 ospf6_lstype_name (u_int16_t type)
111 {
112   static char buf[8];
113   struct ospf6_lsa_handler *handler;
114
115   handler = ospf6_get_lsa_handler (type);
116   if (handler && handler != &unknown_handler)
117     return handler->name;
118
119   snprintf (buf, sizeof (buf), "0x%04hx", ntohs (type));
120   return buf;
121 }
122
123 const char *
124 ospf6_lstype_short_name (u_int16_t type)
125 {
126   static char buf[8];
127   struct ospf6_lsa_handler *handler;
128
129   handler = ospf6_get_lsa_handler (type);
130   if (handler && handler != &unknown_handler)
131     return handler->short_name;
132
133   snprintf (buf, sizeof (buf), "0x%04hx", ntohs (type));
134   return buf;
135 }
136
137 u_char
138 ospf6_lstype_debug (u_int16_t type)
139 {
140   struct ospf6_lsa_handler *handler;
141   handler = ospf6_get_lsa_handler (type);
142   return handler->debug;
143 }
144
145 /* RFC2328: Section 13.2 */
146 int
147 ospf6_lsa_is_differ (struct ospf6_lsa *lsa1,
148                      struct ospf6_lsa *lsa2)
149 {
150   int len;
151
152   assert (OSPF6_LSA_IS_SAME (lsa1, lsa2));
153
154   /* XXX, Options ??? */
155
156   ospf6_lsa_age_current (lsa1);
157   ospf6_lsa_age_current (lsa2);
158   if (ntohs (lsa1->header->age) == OSPF_LSA_MAXAGE &&
159       ntohs (lsa2->header->age) != OSPF_LSA_MAXAGE)
160     return 1;
161   if (ntohs (lsa1->header->age) != OSPF_LSA_MAXAGE &&
162       ntohs (lsa2->header->age) == OSPF_LSA_MAXAGE)
163     return 1;
164
165   /* compare body */
166   if (ntohs (lsa1->header->length) != ntohs (lsa2->header->length))
167     return 1;
168
169   len = ntohs (lsa1->header->length) - sizeof (struct ospf6_lsa_header);
170   return memcmp (lsa1->header + 1, lsa2->header + 1, len);
171 }
172
173 int
174 ospf6_lsa_is_changed (struct ospf6_lsa *lsa1,
175                       struct ospf6_lsa *lsa2)
176 {
177   int length;
178
179   if (OSPF6_LSA_IS_MAXAGE (lsa1) ^ OSPF6_LSA_IS_MAXAGE (lsa2))
180     return 1;
181   if (ntohs (lsa1->header->length) != ntohs (lsa2->header->length))
182     return 1;
183   /* Going beyond LSA headers to compare the payload only makes sense, when both LSAs aren't header-only. */
184   if (CHECK_FLAG (lsa1->flag, OSPF6_LSA_HEADERONLY) != CHECK_FLAG (lsa2->flag, OSPF6_LSA_HEADERONLY))
185   {
186     zlog_warn ("%s: only one of two (%s, %s) LSAs compared is header-only", __func__, lsa1->name, lsa2->name);
187     return 1;
188   }
189   if (CHECK_FLAG (lsa1->flag, OSPF6_LSA_HEADERONLY))
190     return 0;
191
192   length = OSPF6_LSA_SIZE (lsa1->header) - sizeof (struct ospf6_lsa_header);
193   /* Once upper layer verifies LSAs received, length underrun should become a warning. */
194   if (length <= 0)
195     return 0;
196
197   return memcmp (OSPF6_LSA_HEADER_END (lsa1->header),
198                  OSPF6_LSA_HEADER_END (lsa2->header), length);
199 }
200
201 /* ospf6 age functions */
202 /* calculate birth */
203 static void
204 ospf6_lsa_age_set (struct ospf6_lsa *lsa)
205 {
206   struct timeval now;
207
208   assert (lsa && lsa->header);
209
210   if (quagga_gettime (QUAGGA_CLK_MONOTONIC, &now) < 0)
211     zlog_warn ("LSA: quagga_gettime failed, may fail LSA AGEs: %s",
212                safe_strerror (errno));
213
214   lsa->birth.tv_sec = now.tv_sec - ntohs (lsa->header->age);
215   lsa->birth.tv_usec = now.tv_usec;
216
217   return;
218 }
219
220 /* this function calculates current age from its birth,
221    then update age field of LSA header. return value is current age */
222 u_int16_t
223 ospf6_lsa_age_current (struct ospf6_lsa *lsa)
224 {
225   struct timeval now;
226   u_int32_t ulage;
227   u_int16_t age;
228
229   assert (lsa);
230   assert (lsa->header);
231
232   /* current time */
233   if (quagga_gettime (QUAGGA_CLK_MONOTONIC, &now) < 0)
234     zlog_warn ("LSA: quagga_gettime failed, may fail LSA AGEs: %s",
235                safe_strerror (errno));
236
237   if (ntohs (lsa->header->age) >= OSPF_LSA_MAXAGE)
238     {
239       /* ospf6_lsa_premature_aging () sets age to MAXAGE; when using
240          relative time, we cannot compare against lsa birth time, so
241          we catch this special case here. */
242       lsa->header->age = htons (OSPF_LSA_MAXAGE);
243       return OSPF_LSA_MAXAGE;
244     }
245   /* calculate age */
246   ulage = now.tv_sec - lsa->birth.tv_sec;
247
248   /* if over MAXAGE, set to it */
249   age = (ulage > OSPF_LSA_MAXAGE ? OSPF_LSA_MAXAGE : ulage);
250
251   lsa->header->age = htons (age);
252   return age;
253 }
254
255 /* update age field of LSA header with adding InfTransDelay */
256 void
257 ospf6_lsa_age_update_to_send (struct ospf6_lsa *lsa, u_int32_t transdelay)
258 {
259   unsigned short age;
260
261   age = ospf6_lsa_age_current (lsa) + transdelay;
262   if (age > OSPF_LSA_MAXAGE)
263     age = OSPF_LSA_MAXAGE;
264   lsa->header->age = htons (age);
265 }
266
267 void
268 ospf6_lsa_premature_aging (struct ospf6_lsa *lsa)
269 {
270   /* log */
271   if (IS_OSPF6_DEBUG_LSA_TYPE (lsa->header->type))
272     zlog_debug ("LSA: Premature aging: %s", lsa->name);
273
274   THREAD_OFF (lsa->expire);
275   THREAD_OFF (lsa->refresh);
276
277   /*
278    * We clear the LSA from the neighbor retx lists now because it
279    * will not get deleted later. Essentially, changing the age to
280    * MaxAge will prevent this LSA from being matched with its
281    * existing entries in the retx list thereby causing those entries
282    * to be silently replaced with its MaxAged version, but with ever
283    * increasing retx count causing this LSA to remain forever and
284    * for the MaxAge remover thread to be called forever too.
285    *
286    * The reason the previous entry silently disappears is that when
287    * entry is added to a neighbor's retx list, it replaces the existing
288    * entry. But since the ospf6_lsdb_add() routine is generic and not aware
289    * of the special semantics of retx count, the retx count is not
290    * decremented when its replaced. Attempting to add the incr and decr
291    * retx count routines as the hook_add and hook_remove for the retx lists
292    * have a problem because the hook_remove routine is called for MaxAge
293    * entries (as will be the case in a traditional LSDB, unlike in this case
294    * where an LSDB is used as an efficient tree structure to store all kinds
295    * of data) that are added instead of calling the hook_add routine.
296    */
297
298   ospf6_flood_clear (lsa);
299
300   lsa->header->age = htons (OSPF_LSA_MAXAGE);
301   thread_execute (master, ospf6_lsa_expire, lsa, 0);
302 }
303
304 /* check which is more recent. if a is more recent, return -1;
305    if the same, return 0; otherwise(b is more recent), return 1 */
306 int
307 ospf6_lsa_compare (struct ospf6_lsa *a, struct ospf6_lsa *b)
308 {
309   int32_t seqnuma, seqnumb;
310   u_int16_t cksuma, cksumb;
311   u_int16_t agea, ageb;
312
313   assert (a && a->header);
314   assert (b && b->header);
315   assert (OSPF6_LSA_IS_SAME (a, b));
316
317   seqnuma = (int32_t) ntohl (a->header->seqnum);
318   seqnumb = (int32_t) ntohl (b->header->seqnum);
319
320   /* compare by sequence number */
321   if (seqnuma > seqnumb)
322     return -1;
323   if (seqnuma < seqnumb)
324     return 1;
325
326   /* Checksum */
327   cksuma = ntohs (a->header->checksum);
328   cksumb = ntohs (b->header->checksum);
329   if (cksuma > cksumb)
330     return -1;
331   if (cksuma < cksumb)
332     return 0;
333
334   /* Update Age */
335   agea = ospf6_lsa_age_current (a);
336   ageb = ospf6_lsa_age_current (b);
337
338   /* MaxAge check */
339   if (agea == OSPF_LSA_MAXAGE && ageb != OSPF_LSA_MAXAGE)
340     return -1;
341   else if (agea != OSPF_LSA_MAXAGE && ageb == OSPF_LSA_MAXAGE)
342     return 1;
343
344   /* Age check */
345   if (agea > ageb && agea - ageb >= OSPF_LSA_MAXAGE_DIFF)
346     return 1;
347   else if (agea < ageb && ageb - agea >= OSPF_LSA_MAXAGE_DIFF)
348     return -1;
349
350   /* neither recent */
351   return 0;
352 }
353
354 char *
355 ospf6_lsa_printbuf (struct ospf6_lsa *lsa, char *buf, int size)
356 {
357   char id[16], adv_router[16];
358   inet_ntop (AF_INET, &lsa->header->id, id, sizeof (id));
359   inet_ntop (AF_INET, &lsa->header->adv_router, adv_router,
360              sizeof (adv_router));
361   snprintf (buf, size, "[%s Id:%s Adv:%s]",
362             ospf6_lstype_name (lsa->header->type), id, adv_router);
363   return buf;
364 }
365
366 void
367 ospf6_lsa_header_print_raw (struct ospf6_lsa_header *header)
368 {
369   char id[16], adv_router[16];
370   inet_ntop (AF_INET, &header->id, id, sizeof (id));
371   inet_ntop (AF_INET, &header->adv_router, adv_router,
372              sizeof (adv_router));
373   zlog_debug ("    [%s Id:%s Adv:%s]",
374               ospf6_lstype_name (header->type), id, adv_router);
375   zlog_debug ("    Age: %4hu SeqNum: %#08lx Cksum: %04hx Len: %d",
376               ntohs (header->age), (u_long) ntohl (header->seqnum),
377               ntohs (header->checksum), ntohs (header->length));
378 }
379
380 void
381 ospf6_lsa_header_print (struct ospf6_lsa *lsa)
382 {
383   ospf6_lsa_age_current (lsa);
384   ospf6_lsa_header_print_raw (lsa->header);
385 }
386
387 void
388 ospf6_lsa_show_summary_header (struct vty *vty)
389 {
390   vty_out (vty, "%-4s %-15s%-15s%4s %8s %30s%s",
391            "Type", "LSId", "AdvRouter", "Age", "SeqNum",
392            "Payload", VNL);
393 }
394
395 void
396 ospf6_lsa_show_summary (struct vty *vty, struct ospf6_lsa *lsa)
397 {
398   char adv_router[16], id[16];
399   int type;
400   struct ospf6_lsa_handler *handler;
401   char buf[64], tmpbuf[80];
402   int cnt = 0;
403
404   assert (lsa);
405   assert (lsa->header);
406
407   inet_ntop (AF_INET, &lsa->header->id, id, sizeof (id));
408   inet_ntop (AF_INET, &lsa->header->adv_router, adv_router,
409              sizeof (adv_router));
410
411   type = ntohs(lsa->header->type);
412   handler = ospf6_get_lsa_handler (lsa->header->type);
413   if ((type == OSPF6_LSTYPE_INTER_PREFIX) ||
414       (type == OSPF6_LSTYPE_INTER_ROUTER) ||
415       (type == OSPF6_LSTYPE_AS_EXTERNAL))
416     {
417       vty_out (vty, "%-4s %-15s%-15s%4hu %8lx %30s%s",
418                ospf6_lstype_short_name (lsa->header->type),
419                id, adv_router, ospf6_lsa_age_current (lsa),
420                (u_long) ntohl (lsa->header->seqnum),
421                handler->get_prefix_str(lsa, buf, sizeof(buf), 0), VNL);
422     }
423   else if (type != OSPF6_LSTYPE_UNKNOWN)
424     {
425       sprintf (tmpbuf, "%-4s %-15s%-15s%4hu %8lx",
426                ospf6_lstype_short_name (lsa->header->type),
427                id, adv_router, ospf6_lsa_age_current (lsa),
428                (u_long) ntohl (lsa->header->seqnum));
429
430       while (handler->get_prefix_str(lsa, buf, sizeof(buf), cnt) != NULL)
431         {
432           vty_out (vty, "%s %30s%s", tmpbuf, buf, VNL);
433           cnt++;
434         }
435     }
436   else
437     {
438       vty_out (vty, "%-4s %-15s%-15s%4hu %8lx%s",
439                ospf6_lstype_short_name (lsa->header->type),
440                id, adv_router, ospf6_lsa_age_current (lsa),
441                (u_long) ntohl (lsa->header->seqnum), VNL);
442     }
443 }
444
445 void
446 ospf6_lsa_show_dump (struct vty *vty, struct ospf6_lsa *lsa)
447 {
448   u_char *start, *end, *current;
449   char byte[4];
450
451   start = (u_char *) lsa->header;
452   end = (u_char *) lsa->header + ntohs (lsa->header->length);
453
454   vty_out (vty, "%s", VNL);
455   vty_out (vty, "%s:%s", lsa->name, VNL);
456
457   for (current = start; current < end; current ++)
458     {
459       if ((current - start) % 16 == 0)
460         vty_out (vty, "%s        ", VNL);
461       else if ((current - start) % 4 == 0)
462         vty_out (vty, " ");
463
464       snprintf (byte, sizeof (byte), "%02x", *current);
465       vty_out (vty, "%s", byte);
466     }
467
468   vty_out (vty, "%s%s", VNL, VNL);
469   return;
470 }
471
472 void
473 ospf6_lsa_show_internal (struct vty *vty, struct ospf6_lsa *lsa)
474 {
475   char adv_router[64], id[64];
476
477   assert (lsa && lsa->header);
478
479   inet_ntop (AF_INET, &lsa->header->id, id, sizeof (id));
480   inet_ntop (AF_INET, &lsa->header->adv_router,
481              adv_router, sizeof (adv_router));
482
483   vty_out (vty, "%s", VNL);
484   vty_out (vty, "Age: %4hu Type: %s%s", ospf6_lsa_age_current (lsa),
485            ospf6_lstype_name (lsa->header->type), VNL);
486   vty_out (vty, "Link State ID: %s%s", id, VNL);
487   vty_out (vty, "Advertising Router: %s%s", adv_router, VNL);
488   vty_out (vty, "LS Sequence Number: %#010lx%s",
489            (u_long) ntohl (lsa->header->seqnum), VNL);
490   vty_out (vty, "CheckSum: %#06hx Length: %hu%s",
491            ntohs (lsa->header->checksum),
492            ntohs (lsa->header->length), VNL);
493   vty_out (vty, "Flag: %x %s", lsa->flag, VNL);
494   vty_out (vty, "Lock: %d %s", lsa->lock, VNL);
495   vty_out (vty, "ReTx Count: %d%s", lsa->retrans_count, VNL);
496   vty_out (vty, "Threads: Expire: 0x%p, Refresh: 0x%p %s",
497            (void *)lsa->expire, (void *)lsa->refresh, VNL);
498   vty_out (vty, "%s", VNL);
499   return;
500 }
501
502 void
503 ospf6_lsa_show (struct vty *vty, struct ospf6_lsa *lsa)
504 {
505   char adv_router[64], id[64];
506   struct ospf6_lsa_handler *handler;
507   struct timeval now, res;
508   char duration[16];
509
510   assert (lsa && lsa->header);
511
512   inet_ntop (AF_INET, &lsa->header->id, id, sizeof (id));
513   inet_ntop (AF_INET, &lsa->header->adv_router,
514              adv_router, sizeof (adv_router));
515
516   quagga_gettime (QUAGGA_CLK_MONOTONIC, &now);
517   timersub (&now, &lsa->installed, &res);
518   timerstring (&res, duration, sizeof (duration));
519
520   vty_out (vty, "Age: %4hu Type: %s%s", ospf6_lsa_age_current (lsa),
521            ospf6_lstype_name (lsa->header->type), VNL);
522   vty_out (vty, "Link State ID: %s%s", id, VNL);
523   vty_out (vty, "Advertising Router: %s%s", adv_router, VNL);
524   vty_out (vty, "LS Sequence Number: %#010lx%s",
525            (u_long) ntohl (lsa->header->seqnum), VNL);
526   vty_out (vty, "CheckSum: %#06hx Length: %hu%s",
527            ntohs (lsa->header->checksum),
528            ntohs (lsa->header->length), VNL);
529   vty_out (vty, "Duration: %s%s", duration, VNL);
530
531   handler = ospf6_get_lsa_handler (lsa->header->type);
532   if (handler->show == NULL)
533     handler = &unknown_handler;
534   (*handler->show) (vty, lsa);
535
536   vty_out (vty, "%s", VNL);
537 }
538
539 /* OSPFv3 LSA creation/deletion function */
540 struct ospf6_lsa *
541 ospf6_lsa_create (struct ospf6_lsa_header *header)
542 {
543   struct ospf6_lsa *lsa = NULL;
544   struct ospf6_lsa_header *new_header = NULL;
545   u_int16_t lsa_size = 0;
546
547   /* size of the entire LSA */
548   lsa_size = ntohs (header->length);   /* XXX vulnerable */
549
550   /* allocate memory for this LSA */
551   new_header = (struct ospf6_lsa_header *)
552     XMALLOC (MTYPE_OSPF6_LSA, lsa_size);
553
554   /* copy LSA from original header */
555   memcpy (new_header, header, lsa_size);
556
557   /* LSA information structure */
558   /* allocate memory */
559   lsa = (struct ospf6_lsa *)
560     XCALLOC (MTYPE_OSPF6_LSA, sizeof (struct ospf6_lsa));
561
562   lsa->header = (struct ospf6_lsa_header *) new_header;
563
564   /* dump string */
565   ospf6_lsa_printbuf (lsa, lsa->name, sizeof (lsa->name));
566
567   /* calculate birth of this lsa */
568   ospf6_lsa_age_set (lsa);
569
570   return lsa;
571 }
572
573 struct ospf6_lsa *
574 ospf6_lsa_create_headeronly (struct ospf6_lsa_header *header)
575 {
576   struct ospf6_lsa *lsa = NULL;
577   struct ospf6_lsa_header *new_header = NULL;
578
579   /* allocate memory for this LSA */
580   new_header = (struct ospf6_lsa_header *)
581     XMALLOC (MTYPE_OSPF6_LSA, sizeof (struct ospf6_lsa_header));
582
583   /* copy LSA from original header */
584   memcpy (new_header, header, sizeof (struct ospf6_lsa_header));
585
586   /* LSA information structure */
587   /* allocate memory */
588   lsa = (struct ospf6_lsa *)
589     XCALLOC (MTYPE_OSPF6_LSA, sizeof (struct ospf6_lsa));
590
591   lsa->header = (struct ospf6_lsa_header *) new_header;
592   SET_FLAG (lsa->flag, OSPF6_LSA_HEADERONLY);
593
594   /* dump string */
595   ospf6_lsa_printbuf (lsa, lsa->name, sizeof (lsa->name));
596
597   /* calculate birth of this lsa */
598   ospf6_lsa_age_set (lsa);
599
600   return lsa;
601 }
602
603 void
604 ospf6_lsa_delete (struct ospf6_lsa *lsa)
605 {
606   assert (lsa->lock == 0);
607
608   /* cancel threads */
609   THREAD_OFF (lsa->expire);
610   THREAD_OFF (lsa->refresh);
611
612   /* do free */
613   XFREE (MTYPE_OSPF6_LSA, lsa->header);
614   XFREE (MTYPE_OSPF6_LSA, lsa);
615 }
616
617 struct ospf6_lsa *
618 ospf6_lsa_copy (struct ospf6_lsa *lsa)
619 {
620   struct ospf6_lsa *copy = NULL;
621
622   ospf6_lsa_age_current (lsa);
623   if (CHECK_FLAG (lsa->flag, OSPF6_LSA_HEADERONLY))
624     copy = ospf6_lsa_create_headeronly (lsa->header);
625   else
626     copy = ospf6_lsa_create (lsa->header);
627   assert (copy->lock == 0);
628
629   copy->birth = lsa->birth;
630   copy->originated = lsa->originated;
631   copy->received = lsa->received;
632   copy->installed = lsa->installed;
633   copy->lsdb = lsa->lsdb;
634   copy->rn = NULL;
635
636   return copy;
637 }
638
639 /* increment reference counter of struct ospf6_lsa */
640 void
641 ospf6_lsa_lock (struct ospf6_lsa *lsa)
642 {
643   lsa->lock++;
644   return;
645 }
646
647 /* decrement reference counter of struct ospf6_lsa */
648 void
649 ospf6_lsa_unlock (struct ospf6_lsa *lsa)
650 {
651   /* decrement reference counter */
652   assert (lsa->lock > 0);
653   lsa->lock--;
654
655   if (lsa->lock != 0)
656     return;
657
658   ospf6_lsa_delete (lsa);
659 }
660
661
662 /* ospf6 lsa expiry */
663 int
664 ospf6_lsa_expire (struct thread *thread)
665 {
666   struct ospf6_lsa *lsa;
667
668   lsa = (struct ospf6_lsa *) THREAD_ARG (thread);
669
670   assert (lsa && lsa->header);
671   assert (OSPF6_LSA_IS_MAXAGE (lsa));
672   assert (! lsa->refresh);
673
674   lsa->expire = (struct thread *) NULL;
675
676   if (IS_OSPF6_DEBUG_LSA_TYPE (lsa->header->type))
677     {
678       zlog_debug ("LSA Expire:");
679       ospf6_lsa_header_print (lsa);
680     }
681
682   if (CHECK_FLAG (lsa->flag, OSPF6_LSA_HEADERONLY))
683     return 0;    /* dbexchange will do something ... */
684
685   /* reinstall lsa */
686   ospf6_install_lsa (lsa);
687
688   /* reflood lsa */
689   ospf6_flood (NULL, lsa);
690
691   /* schedule maxage remover */
692   ospf6_maxage_remove (ospf6);
693
694   return 0;
695 }
696
697 int
698 ospf6_lsa_refresh (struct thread *thread)
699 {
700   struct ospf6_lsa *old, *self, *new;
701   struct ospf6_lsdb *lsdb_self;
702
703   assert (thread);
704   old = (struct ospf6_lsa *) THREAD_ARG (thread);
705   assert (old && old->header);
706
707   old->refresh = (struct thread *) NULL;
708
709   lsdb_self = ospf6_get_scoped_lsdb_self (old);
710   self = ospf6_lsdb_lookup (old->header->type, old->header->id,
711                             old->header->adv_router, lsdb_self);
712   if (self == NULL)
713     {
714       if (IS_OSPF6_DEBUG_LSA_TYPE (old->header->type))
715         zlog_debug ("Refresh: could not find self LSA, flush %s", old->name);
716       ospf6_lsa_premature_aging (old);
717       return 0;
718     }
719
720   /* Reset age, increment LS sequence number. */
721   self->header->age = htons (0);
722   self->header->seqnum =
723     ospf6_new_ls_seqnum (self->header->type, self->header->id,
724                          self->header->adv_router, old->lsdb);
725   ospf6_lsa_checksum (self->header);
726
727   new = ospf6_lsa_create (self->header);
728   new->lsdb = old->lsdb;
729   new->refresh = thread_add_timer (master, ospf6_lsa_refresh, new,
730                                    OSPF_LS_REFRESH_TIME);
731
732   /* store it in the LSDB for self-originated LSAs */
733   ospf6_lsdb_add (ospf6_lsa_copy (new), lsdb_self);
734
735   if (IS_OSPF6_DEBUG_LSA_TYPE (new->header->type))
736     {
737       zlog_debug ("LSA Refresh:");
738       ospf6_lsa_header_print (new);
739     }
740
741   ospf6_install_lsa (new);
742   ospf6_flood (NULL, new);
743
744   return 0;
745 }
746
747
748
749 /* Fletcher Checksum -- Refer to RFC1008. */
750
751 /* All the offsets are zero-based. The offsets in the RFC1008 are
752    one-based. */
753 unsigned short
754 ospf6_lsa_checksum (struct ospf6_lsa_header *lsa_header)
755 {
756   u_char *buffer = (u_char *) &lsa_header->type;
757   int type_offset = buffer - (u_char *) &lsa_header->age; /* should be 2 */
758
759   /* Skip the AGE field */
760   u_int16_t len = ntohs(lsa_header->length) - type_offset;
761
762   /* Checksum offset starts from "type" field, not the beginning of the
763      lsa_header struct. The offset is 14, rather than 16. */
764   int checksum_offset = (u_char *) &lsa_header->checksum - buffer;
765
766   return (unsigned short)fletcher_checksum(buffer, len, checksum_offset);
767 }
768
769 int
770 ospf6_lsa_checksum_valid (struct ospf6_lsa_header *lsa_header)
771 {
772   u_char *buffer = (u_char *) &lsa_header->type;
773   int type_offset = buffer - (u_char *) &lsa_header->age; /* should be 2 */
774
775   /* Skip the AGE field */
776   u_int16_t len = ntohs(lsa_header->length) - type_offset;
777
778   return (fletcher_checksum(buffer, len, FLETCHER_CHECKSUM_VALIDATE) == 0);
779 }
780
781 void
782 ospf6_lsa_init (void)
783 {
784   ospf6_lsa_handler_vector = vector_init (0);
785   ospf6_install_lsa_handler (&unknown_handler);
786 }
787
788 void
789 ospf6_lsa_terminate (void)
790 {
791   vector_free (ospf6_lsa_handler_vector);
792 }
793
794 static char *
795 ospf6_lsa_handler_name (struct ospf6_lsa_handler *h)
796 {
797   static char buf[64];
798   unsigned int i; 
799   unsigned int size = strlen (h->name);
800
801   if (!strcmp(h->name, "unknown") &&
802       h->type != OSPF6_LSTYPE_UNKNOWN)
803     {
804       snprintf (buf, sizeof (buf), "%#04hx", h->type);
805       return buf;
806     }
807
808   for (i = 0; i < MIN (size, sizeof (buf)); i++)
809     {
810       if (! islower ((unsigned char)h->name[i]))
811         buf[i] = tolower ((unsigned char)h->name[i]);
812       else
813         buf[i] = h->name[i];
814     }
815   buf[size] = '\0';
816   return buf;
817 }
818
819 DEFUN (debug_ospf6_lsa_type,
820        debug_ospf6_lsa_hex_cmd,
821        "debug ospf6 lsa (router|network|inter-prefix|inter-router|as-ext|grp-mbr|type7|link|intra-prefix|unknown)",
822        DEBUG_STR
823        OSPF6_STR
824        "Debug Link State Advertisements (LSAs)\n"
825        "Specify LS type as Hexadecimal\n"
826       )
827 {
828   unsigned int i;
829   struct ospf6_lsa_handler *handler = NULL;
830
831   assert (argc);
832
833   for (i = 0; i < vector_active (ospf6_lsa_handler_vector); i++)
834     {
835       handler = vector_slot (ospf6_lsa_handler_vector, i);
836       if (handler == NULL)
837         continue;
838       if (strncmp (argv[0], ospf6_lsa_handler_name(handler), strlen(argv[0])) == 0)
839         break;
840       if (! strcasecmp (argv[0], handler->name))
841         break;
842       handler = NULL;
843     }
844
845   if (handler == NULL)
846     handler = &unknown_handler;
847
848   if (argc >= 2)
849     {
850       if (! strcmp (argv[1], "originate"))
851         SET_FLAG (handler->debug, OSPF6_LSA_DEBUG_ORIGINATE);
852       if (! strcmp (argv[1], "examine"))
853         SET_FLAG (handler->debug, OSPF6_LSA_DEBUG_EXAMIN);
854       if (! strcmp (argv[1], "flooding"))
855         SET_FLAG (handler->debug, OSPF6_LSA_DEBUG_FLOOD);
856     }
857   else
858     SET_FLAG (handler->debug, OSPF6_LSA_DEBUG);
859
860   return CMD_SUCCESS;
861 }
862
863 ALIAS (debug_ospf6_lsa_type,
864        debug_ospf6_lsa_hex_detail_cmd,
865        "debug ospf6 lsa (router|network|inter-prefix|inter-router|as-ext|grp-mbr|type7|link|intra-prefix|unknown) (originate|examine|flooding)",
866        DEBUG_STR
867        OSPF6_STR
868        "Debug Link State Advertisements (LSAs)\n"
869        "Specify LS type as Hexadecimal\n"
870       )
871
872 DEFUN (no_debug_ospf6_lsa_type,
873        no_debug_ospf6_lsa_hex_cmd,
874        "no debug ospf6 lsa (router|network|inter-prefix|inter-router|as-ext|grp-mbr|type7|link|intra-prefix|unknown)",
875        NO_STR
876        DEBUG_STR
877        OSPF6_STR
878        "Debug Link State Advertisements (LSAs)\n"
879        "Specify LS type as Hexadecimal\n"
880       )
881 {
882   u_int i;
883   struct ospf6_lsa_handler *handler = NULL;
884
885   assert (argc);
886
887   for (i = 0; i < vector_active (ospf6_lsa_handler_vector); i++)
888     {
889       handler = vector_slot (ospf6_lsa_handler_vector, i);
890       if (handler == NULL)
891         continue;
892       if (strncmp (argv[0], ospf6_lsa_handler_name(handler), strlen(argv[0])) == 0)
893         break;
894       if (! strcasecmp (argv[0], handler->name))
895         break;
896     }
897
898   if (handler == NULL)
899     return CMD_SUCCESS;
900
901   if (argc >= 2)
902     {
903       if (! strcmp (argv[1], "originate"))
904         UNSET_FLAG (handler->debug, OSPF6_LSA_DEBUG_ORIGINATE);
905       if (! strcmp (argv[1], "examine"))
906         UNSET_FLAG (handler->debug, OSPF6_LSA_DEBUG_EXAMIN);
907       if (! strcmp (argv[1], "flooding"))
908         UNSET_FLAG (handler->debug, OSPF6_LSA_DEBUG_FLOOD);
909     }
910   else
911     UNSET_FLAG (handler->debug, OSPF6_LSA_DEBUG);
912
913   return CMD_SUCCESS;
914 }
915
916 ALIAS (no_debug_ospf6_lsa_type,
917        no_debug_ospf6_lsa_hex_detail_cmd,
918        "no debug ospf6 lsa (router|network|inter-prefix|inter-router|as-ext|grp-mbr|type7|link|intra-prefix) (originate|examine|flooding)",
919        NO_STR
920        DEBUG_STR
921        OSPF6_STR
922        "Debug Link State Advertisements (LSAs)\n"
923        "Specify LS type as Hexadecimal\n"
924       )
925
926 void
927 install_element_ospf6_debug_lsa (void)
928 {
929   install_element (ENABLE_NODE, &debug_ospf6_lsa_hex_cmd);
930   install_element (ENABLE_NODE, &debug_ospf6_lsa_hex_detail_cmd);
931   install_element (ENABLE_NODE, &no_debug_ospf6_lsa_hex_cmd);
932   install_element (ENABLE_NODE, &no_debug_ospf6_lsa_hex_detail_cmd);
933   install_element (CONFIG_NODE, &debug_ospf6_lsa_hex_cmd);
934   install_element (CONFIG_NODE, &debug_ospf6_lsa_hex_detail_cmd);
935   install_element (CONFIG_NODE, &no_debug_ospf6_lsa_hex_cmd);
936   install_element (CONFIG_NODE, &no_debug_ospf6_lsa_hex_detail_cmd);
937 }
938
939 int
940 config_write_ospf6_debug_lsa (struct vty *vty)
941 {
942   u_int i;
943   struct ospf6_lsa_handler *handler;
944
945   for (i = 0; i < vector_active (ospf6_lsa_handler_vector); i++)
946     {
947       handler = vector_slot (ospf6_lsa_handler_vector, i);
948       if (handler == NULL)
949         continue;
950       if (CHECK_FLAG (handler->debug, OSPF6_LSA_DEBUG))
951         vty_out (vty, "debug ospf6 lsa %s%s",
952                  ospf6_lsa_handler_name (handler), VNL);
953       if (CHECK_FLAG (handler->debug, OSPF6_LSA_DEBUG_ORIGINATE))
954         vty_out (vty, "debug ospf6 lsa %s originate%s",
955                  ospf6_lsa_handler_name (handler), VNL);
956       if (CHECK_FLAG (handler->debug, OSPF6_LSA_DEBUG_EXAMIN))
957         vty_out (vty, "debug ospf6 lsa %s examine%s",
958                  ospf6_lsa_handler_name (handler), VNL);
959       if (CHECK_FLAG (handler->debug, OSPF6_LSA_DEBUG_FLOOD))
960         vty_out (vty, "debug ospf6 lsa %s flooding%s",
961                  ospf6_lsa_handler_name (handler), VNL);
962     }
963
964   return 0;
965 }
966
967