1/*
2 * LSA function
3 * Copyright (C) 1999 Yasuhiro Ohara
4 *
5 * This file is part of GNU Zebra.
6 *
7 * GNU Zebra is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2, or (at your option) any
10 * later version.
11 *
12 * GNU Zebra is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with GNU Zebra; see the file COPYING.  If not, write to the
19 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 * Boston, MA 02111-1307, USA.
21 */
22
23#include <zebra.h>
24
25/* Include other stuffs */
26#include "version.h"
27#include "log.h"
28#include "getopt.h"
29#include "linklist.h"
30#include "thread.h"
31#include "command.h"
32#include "memory.h"
33#include "sockunion.h"
34#include "if.h"
35#include "prefix.h"
36#include "stream.h"
37#include "thread.h"
38#include "filter.h"
39#include "zclient.h"
40#include "table.h"
41#include "plist.h"
42
43#include "ospf6_proto.h"
44#include "ospf6_prefix.h"
45#include "ospf6_lsa.h"
46#include "ospf6_lsdb.h"
47#include "ospf6_message.h"
48#include "ospf6_dump.h"
49
50#include "ospf6_top.h"
51#include "ospf6_area.h"
52#include "ospf6_interface.h"
53#include "ospf6_neighbor.h"
54#include "ospf6_redistribute.h"
55#include "ospf6_ism.h"
56#include "ospf6_nsm.h"
57#include "ospf6_dbex.h"
58
59#define HEADER_DEPENDENCY
60#include "ospf6d.h"
61#undef HEADER_DEPENDENCY
62
63/* test LSAs identity */
64static int
65ospf6_lsa_issame (struct ospf6_lsa_header__ *lsh1,
66                  struct ospf6_lsa_header__ *lsh2)
67{
68  assert (lsh1 && lsh2);
69
70  if (lsh1->adv_router != lsh2->adv_router)
71    return 0;
72
73  if (lsh1->id != lsh2->id)
74    return 0;
75
76  if (lsh1->type != lsh2->type)
77    return 0;
78
79  return 1;
80}
81
82/* RFC2328: Section 13.2 */
83int
84ospf6_lsa_differ (struct ospf6_lsa *lsa1,
85                  struct ospf6_lsa *lsa2)
86{
87  int diff, cmplen;
88
89  if (! ospf6_lsa_issame (lsa1->header, lsa2->header))
90    return 1;
91
92  /* check Options field */
93  /* xxx */
94
95  ospf6_lsa_age_current (lsa1);
96  ospf6_lsa_age_current (lsa2);
97  if (ntohs (lsa1->header->age) == MAXAGE &&
98      ntohs (lsa2->header->age) != MAXAGE)
99    return 1;
100  if (ntohs (lsa1->header->age) != MAXAGE &&
101      ntohs (lsa2->header->age) == MAXAGE)
102    return 1;
103
104  /* compare body */
105  if (ntohs (lsa1->header->length) != ntohs (lsa2->header->length))
106    return 1;
107
108  cmplen = ntohs (lsa1->header->length) - sizeof (struct ospf6_lsa_header);
109  diff = memcmp (lsa1->header + 1, lsa2->header + 1, cmplen);
110
111  return diff;
112}
113
114int
115ospf6_lsa_match (u_int16_t type, u_int32_t id, u_int32_t adv_router,
116                 struct ospf6_lsa_header *lsh)
117{
118  if (lsh->advrtr != adv_router)
119    return 0;
120
121  if (lsh->ls_id != id)
122    return 0;
123
124  if (lsh->type != type)
125    return 0;
126
127  return 1;
128}
129
130/* ospf6 age functions */
131/* calculate birth and set expire timer */
132static void
133ospf6_lsa_age_set (struct ospf6_lsa *lsa)
134{
135  struct timeval now;
136
137  assert (lsa && lsa->header);
138
139  if (gettimeofday (&now, (struct timezone *)NULL) < 0)
140    zlog_warn ("LSA: gettimeofday failed, may fail LSA AGEs: %s",
141               strerror (errno));
142
143  lsa->birth.tv_sec = now.tv_sec - ntohs (lsa->header->age);
144  lsa->birth.tv_usec = now.tv_usec;
145  lsa->expire = thread_add_timer (master, ospf6_lsa_expire, lsa,
146                                  lsa->birth.tv_sec + MAXAGE - now.tv_sec);
147  return;
148}
149
150/* this function calculates current age from its birth,
151   then update age field of LSA header. return value is current age */
152u_int16_t
153ospf6_lsa_age_current (struct ospf6_lsa *lsa)
154{
155  struct timeval now;
156  u_int32_t ulage;
157  u_int16_t age;
158
159  assert (lsa);
160  assert (lsa->header);
161
162  /* current time */
163  if (gettimeofday (&now, (struct timezone *)NULL) < 0)
164    zlog_warn ("LSA: gettimeofday failed, may fail ages: %s",
165               strerror (errno));
166
167  /* calculate age */
168  ulage = now.tv_sec - lsa->birth.tv_sec;
169
170  /* if over MAXAGE, set to it */
171  if (ulage > MAXAGE)
172    age = MAXAGE;
173  else
174    age = ulage;
175
176  lsa->header->age = htons (age);
177  return age;
178}
179
180/* update age field of LSA header with adding InfTransDelay */
181void
182ospf6_lsa_age_update_to_send (struct ospf6_lsa *lsa, u_int32_t transdelay)
183{
184  unsigned short age;
185
186  age = ospf6_lsa_age_current (lsa) + transdelay;
187  if (age > MAXAGE)
188    age = MAXAGE;
189  lsa->header->age = htons (age);
190  return;
191}
192
193void
194ospf6_lsa_premature_aging (struct ospf6_lsa *lsa)
195{
196  /* log */
197  if (IS_OSPF6_DUMP_LSA)
198    zlog_info ("LSA: Premature aging: %s", lsa->str);
199
200  if (lsa->expire)
201    thread_cancel (lsa->expire);
202  lsa->expire = (struct thread *) NULL;
203  if (lsa->refresh)
204    thread_cancel (lsa->refresh);
205  lsa->refresh = (struct thread *) NULL;
206
207  memset (&lsa->birth, 0, sizeof (struct timeval));
208  thread_execute (master, ospf6_lsa_expire, lsa, 0);
209}
210
211/* check which is more recent. if a is more recent, return -1;
212   if the same, return 0; otherwise(b is more recent), return 1 */
213int
214ospf6_lsa_check_recent (struct ospf6_lsa *a, struct ospf6_lsa *b)
215{
216  signed long seqnuma, seqnumb;
217  u_int16_t cksuma, cksumb;
218  u_int16_t agea, ageb;
219
220  assert (a && a->header);
221  assert (b && b->header);
222  assert (ospf6_lsa_issame (a->header, b->header));
223
224  seqnuma = ((signed long) ntohl (a->header->seqnum))
225             - (signed long) INITIAL_SEQUENCE_NUMBER;
226  seqnumb = ((signed long) ntohl (b->header->seqnum))
227             - (signed long) INITIAL_SEQUENCE_NUMBER;
228
229  /* compare by sequence number */
230    /* xxx, care about LS sequence number wrapping */
231  recent_reason = "seqnum";
232  if (seqnuma > seqnumb)
233    return -1;
234  else if (seqnuma < seqnumb)
235    return 1;
236
237  /* Checksum */
238  cksuma = ntohs (a->header->checksum);
239  cksumb = ntohs (b->header->checksum);
240  if (cksuma > cksumb)
241    return -1;
242  if (cksuma < cksumb)
243    return 0;
244
245  /* Age check */
246  agea = ospf6_lsa_age_current (a);
247  ageb = ospf6_lsa_age_current (b);
248
249    /* MaxAge check */
250  recent_reason = "max age";
251  if (agea == OSPF6_LSA_MAXAGE && ageb != OSPF6_LSA_MAXAGE)
252    return -1;
253  else if (agea != OSPF6_LSA_MAXAGE && ageb == OSPF6_LSA_MAXAGE)
254    return 1;
255
256  recent_reason = "age differ";
257  if (agea > ageb && agea - ageb >= OSPF6_LSA_MAXAGEDIFF)
258    return 1;
259  else if (agea < ageb && ageb - agea >= OSPF6_LSA_MAXAGEDIFF)
260    return -1;
261
262  /* neither recent */
263  recent_reason = "the same instance";
264  return 0;
265}
266
267int
268ospf6_lsa_lsd_num (struct ospf6_lsa_header *lsa_header)
269{
270  int ldnum = 0;
271  u_int16_t len;
272
273  len = ntohs (lsa_header->length);
274  len -= sizeof (struct ospf6_lsa_header);
275  if (lsa_header->type == htons (OSPF6_LSA_TYPE_ROUTER))
276    {
277      len -= sizeof (struct ospf6_router_lsa);
278      ldnum = len / sizeof (struct ospf6_router_lsd);
279    }
280  else /* (lsa_header->type == htons (OSPF6_LSA_TYPE_NETWORK)) */
281    {
282      len -= sizeof (struct ospf6_network_lsa);
283      ldnum = len / sizeof (u_int32_t);
284    }
285
286  return ldnum;
287}
288
289void *
290ospf6_lsa_lsd_get (int index, struct ospf6_lsa_header *lsa_header)
291{
292  void *p;
293  struct ospf6_router_lsa *router_lsa;
294  struct ospf6_router_lsd *router_lsd;
295  struct ospf6_network_lsa *network_lsa;
296  struct ospf6_network_lsd *network_lsd;
297
298  if (lsa_header->type == htons (OSPF6_LSA_TYPE_ROUTER))
299    {
300      router_lsa = (struct ospf6_router_lsa *) (lsa_header + 1);
301      router_lsd = (struct ospf6_router_lsd *) (router_lsa + 1);
302      router_lsd += index;
303      p = (void *) router_lsd;
304    }
305  else if (lsa_header->type == htons (OSPF6_LSA_TYPE_NETWORK))
306    {
307      network_lsa = (struct ospf6_network_lsa *) (lsa_header + 1);
308      network_lsd = (struct ospf6_network_lsd *) (network_lsa + 1);
309      network_lsd += index;
310      p = (void *) network_lsd;
311    }
312  else
313    {
314      p = (void *) NULL;
315    }
316
317  return p;
318}
319
320/* network_lsd <-> router_lsd */
321static int
322ospf6_lsa_lsd_network_reference_match (struct ospf6_network_lsd *network_lsd1,
323                                       struct ospf6_lsa_header *lsa_header1,
324                                       struct ospf6_router_lsd *router_lsd2,
325                                       struct ospf6_lsa_header *lsa_header2)
326{
327  if (network_lsd1->adv_router != lsa_header2->advrtr)
328    return 0;
329  if (router_lsd2->type != OSPF6_ROUTER_LSD_TYPE_TRANSIT_NETWORK)
330    return 0;
331  if (router_lsd2->neighbor_router_id != lsa_header1->advrtr)
332    return 0;
333  if (router_lsd2->neighbor_interface_id != lsa_header1->ls_id)
334    return 0;
335  return 1;
336}
337
338/* router_lsd <-> router_lsd */
339static int
340ospf6_lsa_lsd_router_reference_match (struct ospf6_router_lsd *router_lsd1,
341                                      struct ospf6_lsa_header *lsa_header1,
342                                      struct ospf6_router_lsd *router_lsd2,
343                                      struct ospf6_lsa_header *lsa_header2)
344{
345  if (router_lsd1->type != OSPF6_ROUTER_LSD_TYPE_POINTTOPOINT)
346    return 0;
347  if (router_lsd2->type != OSPF6_ROUTER_LSD_TYPE_POINTTOPOINT)
348    return 0;
349  if (router_lsd1->neighbor_router_id != lsa_header2->advrtr)
350    return 0;
351  if (router_lsd2->neighbor_router_id != lsa_header1->advrtr)
352    return 0;
353  if (router_lsd1->neighbor_interface_id != router_lsd2->interface_id)
354    return 0;
355  if (router_lsd2->neighbor_interface_id != router_lsd1->interface_id)
356    return 0;
357  return 1;
358}
359
360int
361ospf6_lsa_lsd_is_refer_ok (int index1, struct ospf6_lsa_header *lsa_header1,
362                           int index2, struct ospf6_lsa_header *lsa_header2)
363{
364  struct ospf6_router_lsd *r1, *r2;
365  struct ospf6_network_lsd *n;
366
367  r1 = (struct ospf6_router_lsd *) NULL;
368  r2 = (struct ospf6_router_lsd *) NULL;
369  n = (struct ospf6_network_lsd *) NULL;
370  if (lsa_header1->type == htons (OSPF6_LSA_TYPE_ROUTER))
371    r1 = (struct ospf6_router_lsd *) ospf6_lsa_lsd_get (index1, lsa_header1);
372  else
373    n = (struct ospf6_network_lsd *) ospf6_lsa_lsd_get (index1, lsa_header1);
374
375  if (lsa_header2->type == htons (OSPF6_LSA_TYPE_ROUTER))
376    r2 = (struct ospf6_router_lsd *) ospf6_lsa_lsd_get (index2, lsa_header2);
377  else
378    n = (struct ospf6_network_lsd *) ospf6_lsa_lsd_get (index2, lsa_header2);
379
380  if (r1 && r2)
381    return ospf6_lsa_lsd_router_reference_match (r1, lsa_header1,
382                                                 r2, lsa_header2);
383  else if (r1 && n)
384    return ospf6_lsa_lsd_network_reference_match (n, lsa_header2,
385                                                  r1, lsa_header1);
386  else if (n && r2)
387    return ospf6_lsa_lsd_network_reference_match (n, lsa_header1,
388                                                 r2, lsa_header2);
389  return 0;
390}
391
392void
393ospf6_lsa_show (struct vty *vty, struct ospf6_lsa *lsa)
394{
395  char adv_router[64], id[64], type[32];
396
397  assert (lsa);
398  assert (lsa->header);
399
400  ospf6_lsa_type_string (lsa->header->type, type, sizeof (type));
401  inet_ntop (AF_INET, &lsa->header->id, id, sizeof (id));
402  inet_ntop (AF_INET, &lsa->header->adv_router,
403             adv_router, sizeof (adv_router));
404
405  vty_out (vty, "%s", VTY_NEWLINE);
406  vty_out (vty, "Age: %4hu Type: %s%s", ospf6_lsa_age_current (lsa),
407           type, VTY_NEWLINE);
408  vty_out (vty, "Link State ID: %s%s", id, VTY_NEWLINE);
409  vty_out (vty, "Advertising Router: %s%s", adv_router, VTY_NEWLINE);
410  vty_out (vty, "LS Sequence Number: %#lx%s", (u_long)ntohl (lsa->header->seqnum),
411           VTY_NEWLINE);
412  vty_out (vty, "CheckSum: %#hx Length: %hu%s", ntohs (lsa->header->checksum),
413           ntohs (lsa->header->length), VTY_NEWLINE);
414
415  {
416    struct ospf6_lsa_slot *slot;
417    slot = ospf6_lsa_slot_get (lsa->header->type);
418    if (slot)
419      {
420        (*slot->func_show) (vty, lsa);
421        vty_out (vty, "%s", VTY_NEWLINE);
422        return;
423      }
424  }
425
426  vty_out (vty, "%sUnknown LSA type ...%s", VTY_NEWLINE, VTY_NEWLINE);
427}
428
429void
430ospf6_lsa_show_summary_header (struct vty *vty)
431{
432  vty_out (vty, "%-12s %-15s %-15s %4s %8s %4s %4s %-8s%s",
433           "Type", "LSId", "AdvRouter", "Age", "SeqNum",
434           "Cksm", "Len", "Duration", VTY_NEWLINE);
435}
436
437void
438ospf6_lsa_show_summary (struct vty *vty, struct ospf6_lsa *lsa)
439{
440  char adv_router[16], id[16], type[16];
441  struct timeval now, res;
442  char duration[16];
443
444  assert (lsa);
445  assert (lsa->header);
446
447  memset (type, 0, sizeof (type));
448  ospf6_lsa_type_string (lsa->header->type, type, 13);
449  inet_ntop (AF_INET, &lsa->header->id, id, sizeof (id));
450  inet_ntop (AF_INET, &lsa->header->adv_router, adv_router,
451             sizeof (adv_router));
452
453  gettimeofday (&now, NULL);
454  ospf6_timeval_sub (&now, &lsa->installed, &res);
455  ospf6_timeval_string_summary (&res, duration, sizeof (duration));
456
457  vty_out (vty, "%-12s %-15s %-15s %4hu %8lx %04hx %4hu %8s%s",
458           type, id, adv_router, ospf6_lsa_age_current (lsa),
459           (u_long) ntohl (lsa->header->seqnum),
460           ntohs (lsa->header->checksum), ntohs (lsa->header->length),
461           duration, VTY_NEWLINE);
462}
463
464void
465ospf6_lsa_show_dump (struct vty *vty, struct ospf6_lsa *lsa)
466{
467  u_char *start, *end, *current;
468  char byte[4];
469
470  start = (char *) lsa->header;
471  end = (char *) lsa->header + ntohs (lsa->header->length);
472
473  vty_out (vty, "%s", VTY_NEWLINE);
474  vty_out (vty, "%s:%s", lsa->str, VTY_NEWLINE);
475
476  for (current = start; current < end; current ++)
477    {
478      if ((current - start) % 16 == 0)
479        vty_out (vty, "%s        ", VTY_NEWLINE);
480      else if ((current - start) % 4 == 0)
481        vty_out (vty, " ");
482
483      snprintf (byte, sizeof (byte), "%02x", *current);
484      vty_out (vty, "%s", byte);
485    }
486
487  vty_out (vty, "%s%s", VTY_NEWLINE, VTY_NEWLINE);
488}
489
490/* OSPFv3 LSA creation/deletion function */
491
492/* calculate LS sequence number for my new LSA.
493   return value is network byte order */
494static signed long
495ospf6_lsa_seqnum_new (u_int16_t type, u_int32_t id, u_int32_t adv_router,
496                      void *scope)
497{
498  struct ospf6_lsa *lsa;
499  signed long seqnum;
500
501  /* get current database copy */
502  lsa = ospf6_lsdb_lookup (type, id, adv_router, scope);
503
504  /* if current database copy not found, return InitialSequenceNumber */
505  if (!lsa)
506    seqnum = INITIAL_SEQUENCE_NUMBER;
507  else
508    seqnum = (signed long) ntohl (lsa->header->seqnum) + 1;
509
510  return (htonl (seqnum));
511}
512
513#if 0
514static void
515ospf6_lsa_header_set (u_int16_t type, u_int32_t ls_id, u_int32_t advrtr,
516                      struct ospf6_lsa_header *lsa_header, int bodysize)
517{
518  /* fill LSA header */
519  lsa_header->age = 0;
520  lsa_header->type = type;
521  lsa_header->ls_id = ls_id;
522  lsa_header->advrtr = advrtr;
523  lsa_header->seqnum =
524    ospf6_lsa_seqnum_new (lsa_header->type, lsa_header->ls_id,
525                          lsa_header->advrtr);
526  lsa_header->length = htons (sizeof (struct ospf6_lsa_header) + bodysize);
527
528  /* LSA checksum */
529  ospf6_lsa_checksum (lsa_header);
530}
531#endif /*0*/
532
533struct ospf6_lsa *
534ospf6_lsa_create (struct ospf6_lsa_header *source)
535{
536  struct ospf6_lsa *lsa = NULL;
537  struct ospf6_lsa_header *lsa_header = NULL;
538  u_int16_t lsa_size = 0;
539  char buf_router[16], buf_id[16], typebuf[32];
540
541  /* whole length of this LSA */
542  lsa_size = ntohs (source->length);
543
544  /* allocate memory for this LSA */
545  lsa_header = (struct ospf6_lsa_header *)
546    XMALLOC (MTYPE_OSPF6_LSA, lsa_size);
547  if (! lsa_header)
548    {
549      zlog_err ("Can't allocate memory for LSA Header");
550      return (struct ospf6_lsa *) NULL;
551    }
552  memset (lsa_header, 0, lsa_size);
553
554  /* copy LSA from source */
555  memcpy (lsa_header, source, lsa_size);
556
557  /* LSA information structure */
558  /* allocate memory */
559  lsa = (struct ospf6_lsa *)
560          XMALLOC (MTYPE_OSPF6_LSA, sizeof (struct ospf6_lsa));
561  memset (lsa, 0, sizeof (struct ospf6_lsa));
562
563  lsa->lsa_hdr = (struct ospf6_lsa_hdr *) lsa_header;
564  lsa->header = (struct ospf6_lsa_header__ *) lsa_header;
565
566  lsa->summary = 0; /* this is not LSA summary */
567
568  /* dump string */
569  inet_ntop (AF_INET, &lsa->header->id, buf_id, sizeof (buf_id));
570  inet_ntop (AF_INET, &lsa->header->adv_router, buf_router,
571             sizeof (buf_router));
572  snprintf (lsa->str, sizeof (lsa->str), "[%s ID=%s Adv=%s]",
573            ospf6_lsa_type_string (lsa_header->type, typebuf,
574                                   sizeof (typebuf)),
575            buf_id, buf_router);
576
577  /* calculate birth, expire and refresh of this lsa */
578  ospf6_lsa_age_set (lsa);
579
580#ifdef DEBUG
581  if (IS_OSPF6_DUMP_LSA)
582    zlog_info ("Create: %s (%p/%p)", lsa->str, lsa, lsa->header);
583#endif /*DEBUG*/
584
585  return lsa;
586}
587
588struct ospf6_lsa *
589ospf6_lsa_summary_create (struct ospf6_lsa_header__ *source)
590{
591  struct ospf6_lsa *lsa = NULL;
592  struct ospf6_lsa_header *lsa_header = NULL;
593  u_int16_t lsa_size = 0;
594  char buf_router[16], buf_id[16], typebuf[16];
595
596  /* LSA summary contains LSA Header only */
597  lsa_size = sizeof (struct ospf6_lsa_header);
598
599  /* allocate memory for this LSA */
600  lsa_header = (struct ospf6_lsa_header *)
601    XMALLOC (MTYPE_OSPF6_LSA_SUMMARY, lsa_size);
602  memset (lsa_header, 0, lsa_size);
603
604  /* copy LSA from source */
605  memcpy (lsa_header, source, lsa_size);
606
607  /* LSA information structure */
608  /* allocate memory */
609  lsa = (struct ospf6_lsa *)
610          XMALLOC (MTYPE_OSPF6_LSA_SUMMARY, sizeof (struct ospf6_lsa));
611  memset (lsa, 0, sizeof (struct ospf6_lsa));
612
613  lsa->lsa_hdr = (struct ospf6_lsa_hdr *) lsa_header;
614  lsa->header = (struct ospf6_lsa_header__ *) lsa_header;
615  lsa->summary = 1; /* this is LSA summary */
616
617  /* dump string */
618  inet_ntop (AF_INET, &lsa->header->id, buf_id, sizeof (buf_id));
619  inet_ntop (AF_INET, &lsa->header->adv_router, buf_router,
620             sizeof (buf_router));
621  snprintf (lsa->str, sizeof (lsa->str), "[%s Summary ID=%s Adv=%s]",
622            ospf6_lsa_type_string (lsa->header->type, typebuf,
623                                   sizeof (typebuf)),
624            buf_id, buf_router);
625
626  /* calculate birth, expire and refresh of this lsa */
627  ospf6_lsa_age_set (lsa);
628
629#ifdef DEBUG
630  if (IS_OSPF6_DUMP_LSA)
631    zlog_info ("Create: %s (%p/%p)", lsa->str, lsa, lsa->header);
632#endif /*DEBUG*/
633
634  return lsa;
635}
636
637void
638ospf6_lsa_delete (struct ospf6_lsa *lsa)
639{
640  /* just to make sure */
641  if (lsa->lock != 0)
642    {
643      zlog_err ("Can't delete %s: lock: %ld", lsa->str, lsa->lock);
644      return;
645    }
646
647  /* cancel threads */
648  if (lsa->expire)
649    thread_cancel (lsa->expire);
650  lsa->expire = (struct thread *) NULL;
651  if (lsa->refresh)
652    thread_cancel (lsa->refresh);
653  lsa->refresh = (struct thread *) NULL;
654
655#ifdef DEBUG
656  if (IS_OSPF6_DUMP_LSA)
657      zlog_info ("Delete %s (%p/%p)", lsa->str, lsa, lsa->header);
658#endif /*DEBUG*/
659
660  /* do free */
661  if (lsa->summary)
662    XFREE (MTYPE_OSPF6_LSA_SUMMARY, lsa->header);
663  else
664    XFREE (MTYPE_OSPF6_LSA, lsa->header);
665  lsa->header = NULL;
666
667  if (lsa->summary)
668    XFREE (MTYPE_OSPF6_LSA_SUMMARY, lsa);
669  else
670    XFREE (MTYPE_OSPF6_LSA, lsa);
671}
672
673/* increment reference counter of  struct ospf6_lsa */
674void
675ospf6_lsa_lock (struct ospf6_lsa *lsa)
676{
677  lsa->lock++;
678  return;
679}
680
681/* decrement reference counter of  struct ospf6_lsa */
682void
683ospf6_lsa_unlock (struct ospf6_lsa *lsa)
684{
685  /* decrement reference counter */
686  if (lsa->lock > 0)
687    lsa->lock--;
688  else
689    zlog_warn ("Can't unlock %s: already no lock", lsa->str);
690
691  if (lsa->lock == 0)
692    ospf6_lsa_delete (lsa);
693}
694
695/* check necessity to update LSA:
696   returns 1 if it's necessary to reoriginate */
697static int
698ospf6_lsa_is_really_reoriginate (struct ospf6_lsa *new)
699{
700  struct ospf6_lsa *old;
701  int diff;
702
703  /* find previous LSA */
704  old = ospf6_lsdb_lookup (new->header->type, new->header->id,
705                           new->header->adv_router, new->scope);
706  if (! old)
707    return 1;
708
709  /* Check if this is refresh */
710  if (CHECK_FLAG (old->flag, OSPF6_LSA_FLAG_REFRESH))
711    {
712      zlog_warn ("LSA: reoriginate: %s: Refresh", new->str);
713      return 1;
714    }
715
716  /* Are these contents different ? */
717  diff = ospf6_lsa_differ (new, old);
718
719  if (diff)
720    return 1;
721
722  if (IS_OSPF6_DUMP_LSA)
723    zlog_info ("LSA: Suppress updating %s", new->str);
724  return 0;
725}
726
727void
728ospf6_lsa_originate (u_int16_t type, u_int32_t id, u_int32_t adv_router,
729                     char *data, int data_len, void *scope)
730{
731  char buffer[MAXLSASIZE];
732  struct ospf6_lsa_header *lsa_header;
733  struct ospf6_lsa *lsa;
734
735  assert (data_len <= sizeof (buffer) - sizeof (struct ospf6_lsa_header));
736
737  lsa_header = (struct ospf6_lsa_header *) buffer;
738
739  /* Copy LSA Body */
740  memcpy (buffer + sizeof (struct ospf6_lsa_header), data, data_len);
741
742  /* Fill LSA Header */
743  lsa_header->age = 0;
744  lsa_header->type = type;
745  lsa_header->ls_id = id;
746  lsa_header->advrtr = adv_router;
747  lsa_header->seqnum =
748    ospf6_lsa_seqnum_new (lsa_header->type, lsa_header->ls_id,
749                          lsa_header->advrtr, scope);
750  lsa_header->length = htons (sizeof (struct ospf6_lsa_header) + data_len);
751
752  /* LSA checksum */
753  ospf6_lsa_checksum (lsa_header);
754
755  /* create LSA */
756  lsa = ospf6_lsa_create ((struct ospf6_lsa_header *) buffer);
757  lsa->refresh = thread_add_timer (master, ospf6_lsa_refresh, lsa,
758                                   OSPF6_LS_REFRESH_TIME);
759  lsa->scope = scope;
760
761  if (ospf6_lsa_is_really_reoriginate (lsa))
762    {
763      ospf6_dbex_remove_from_all_retrans_list (lsa);
764      ospf6_dbex_flood (lsa, NULL);
765      ospf6_lsdb_install (lsa);
766    }
767  else
768    ospf6_lsa_delete (lsa);
769}
770
771
772/* ospf6_lsa expired */
773int
774ospf6_lsa_expire (struct thread *thread)
775{
776  struct ospf6_lsa *lsa;
777  struct ospf6_lsdb *lsdb = NULL;
778
779  lsa = (struct ospf6_lsa *) THREAD_ARG (thread);
780  assert (lsa && lsa->lsa_hdr);
781
782  /* assertion */
783  assert (IS_LSA_MAXAGE (lsa));
784  assert (!lsa->refresh);
785
786  lsa->expire = (struct thread *) NULL;
787
788  /* log */
789  if (IS_OSPF6_DUMP_LSA)
790    zlog_info ("LSA: Expire: %s", lsa->str);
791
792  if (!lsa->summary)
793    {
794      /* reflood lsa */
795      ospf6_dbex_flood (lsa, NULL);
796
797      /* get scoped lsdb, call remove hook */
798      if (OSPF6_LSA_IS_SCOPE_LINKLOCAL (ntohs (lsa->header->type)))
799        lsdb = ((struct ospf6_interface *) lsa->scope)->lsdb;
800      else if (OSPF6_LSA_IS_SCOPE_AREA (ntohs (lsa->header->type)))
801        lsdb = ((struct ospf6_area *) lsa->scope)->lsdb;
802      else if (OSPF6_LSA_IS_SCOPE_AS (ntohs (lsa->header->type)))
803        lsdb = ((struct ospf6 *) lsa->scope)->lsdb;
804      else
805        assert (0);
806
807#if 0
808      if (lsdb->hook)
809        (*lsdb->hook) (lsa, NULL);
810#else /*0*/
811      CALL_REMOVE_HOOK (&database_hook, lsa);
812#endif /*0*/
813
814      /* do not free LSA, and do nothing about lslists.
815         wait event (ospf6_lsdb_check_maxage) */
816    }
817
818  return 0;
819}
820
821int
822ospf6_lsa_refresh (struct thread *thread)
823{
824  struct ospf6_lsa *lsa;
825  struct ospf6_lsa_slot *slot;
826
827  assert (thread);
828  lsa = (struct ospf6_lsa *) THREAD_ARG  (thread);
829  assert (lsa && lsa->lsa_hdr);
830
831  /* this will be used later as flag to decide really originate */
832  lsa->refresh = (struct thread *) NULL;
833  SET_FLAG (lsa->flag, OSPF6_LSA_FLAG_REFRESH);
834
835  /* log */
836  if (IS_OSPF6_DUMP_LSA)
837    zlog_info ("LSA Refresh: %s", lsa->str);
838
839  slot = ospf6_lsa_slot_get (lsa->header->type);
840  if (slot)
841    {
842      zlog_info ("LSA Refresh: %s", slot->name);
843      (*slot->func_refresh) (lsa);
844      return 0;
845    }
846
847  zlog_warn ("Can't Refresh LSA: Unknown type: %#x",
848             ntohs (lsa->header->type));
849  return 1;
850}
851
852
853
854/* enhanced Fletcher checksum algorithm, RFC1008 7.2 */
855#define MODX                4102
856#define LSA_CHECKSUM_OFFSET   15
857
858unsigned short
859ospf6_lsa_checksum (struct ospf6_lsa_header *lsa_header)
860{
861  u_char *sp, *ep, *p, *q;
862  int c0 = 0, c1 = 0;
863  int x, y;
864  u_int16_t length;
865
866  lsa_header->checksum = 0;
867  length = ntohs (lsa_header->length) - 2;
868  sp = (char *) &lsa_header->type;
869
870  for (ep = sp + length; sp < ep; sp = q)
871    {
872      q = sp + MODX;
873      if (q > ep)
874        q = ep;
875      for (p = sp; p < q; p++)
876        {
877          c0 += *p;
878          c1 += c0;
879        }
880      c0 %= 255;
881      c1 %= 255;
882    }
883
884  /* r = (c1 << 8) + c0; */
885  x = ((length - LSA_CHECKSUM_OFFSET) * c0 - c1) % 255;
886  if (x <= 0)
887    x += 255;
888  y = 510 - c0 - x;
889  if (y > 255)
890    y -= 255;
891
892  lsa_header->checksum = htons ((x << 8) + y);
893
894  return (lsa_header->checksum);
895}
896
897int
898ospf6_lsa_is_known_type (struct ospf6_lsa_header *lsa_header)
899{
900  struct ospf6_lsa_slot *slot;
901
902  slot = ospf6_lsa_slot_get (lsa_header->type);
903  if (slot)
904    return 1;
905  return 0;
906}
907
908struct ospf6_lsa_slot *slot_head = NULL;
909
910struct ospf6_lsa_slot *
911ospf6_lsa_slot_get (u_int16_t type)
912{
913  struct ospf6_lsa_slot *slot;
914
915  for (slot = slot_head; slot; slot = slot->next)
916    {
917      if (slot->type == type)
918        return slot;
919    }
920
921  return NULL;
922}
923
924int
925ospf6_lsa_slot_register (struct ospf6_lsa_slot *src)
926{
927  struct ospf6_lsa_slot *new, *slot;
928
929  slot = ospf6_lsa_slot_get (src->type);
930  if (slot)
931    {
932      if (IS_OSPF6_DUMP_LSA)
933        zlog_info ("LSA: Slot register: already exists: %#x %s",
934                   slot->type, slot->name);
935      return -1;
936    }
937
938  new = (struct ospf6_lsa_slot *)
939    XMALLOC (MTYPE_OSPF6_LSA, sizeof (struct ospf6_lsa_slot));
940  if (! new)
941    {
942      zlog_err ("Can't allocate memory for LSA slot: %s", strerror (errno));
943      return -1;
944    }
945  memset (new, 0, sizeof (struct ospf6_lsa_slot));
946  memcpy (new, src, sizeof (struct ospf6_lsa_slot));
947
948  if (IS_OSPF6_DUMP_LSA)
949    zlog_info ("LSA: Slot register: %#x %s", slot->type, slot->name);
950
951  if (slot_head == NULL)
952    {
953      new->prev = NULL;
954      new->next = NULL;
955      slot_head = new;
956      return 0;
957    }
958
959  slot = slot_head;
960  while (slot->next)
961    slot = slot->next;
962
963  slot->next = new;
964  new->prev = slot;
965
966  return 0;
967}
968
969int
970ospf6_lsa_slot_unregister (u_int16_t type)
971{
972  struct ospf6_lsa_slot *slot;
973
974  slot = ospf6_lsa_slot_get (type);
975  if (slot == NULL)
976    {
977      if (IS_OSPF6_DUMP_LSA)
978        zlog_info ("Registering LSA slot: no such slot: %#x", type);
979      return -1;
980    }
981
982  if (IS_OSPF6_DUMP_LSA)
983    zlog_info ("Unregistering LSA Slot: %#x %s", slot->type, slot->name);
984
985  if (slot->prev)
986    slot->prev->next = slot->next;
987  if (slot->next)
988    slot->next->prev = slot->prev;
989
990  if (slot_head == slot)
991    slot_head = slot->next;
992
993  XFREE (MTYPE_OSPF6_LSA, slot);
994  return 0;
995}
996
997char *
998ospf6_lsa_type_string (u_int16_t type, char *buf, int bufsize)
999{
1000  struct ospf6_lsa_slot *slot;
1001
1002  slot = ospf6_lsa_slot_get (type);
1003  if (slot)
1004    snprintf (buf, bufsize, "%s", slot->name);
1005  else
1006    snprintf (buf, bufsize, "Type=0x%04x", ntohs (type));
1007
1008  return buf;
1009}
1010
1011
1012/*******************/
1013/* LSA Origination */
1014/*******************/
1015
1016#define CONTINUE_IF_ADDRESS_LINKLOCAL(addr)\
1017  if (IN6_IS_ADDR_LINKLOCAL (&(addr)->u.prefix6))\
1018    {\
1019      char buf[64];\
1020      prefix2str (addr, buf, sizeof (buf));\
1021      if (IS_OSPF6_DUMP_LSA)\
1022        zlog_info ("  Filter out Linklocal: %s", buf);\
1023      continue;\
1024    }
1025
1026#define CONTINUE_IF_ADDRESS_UNSPECIFIED(addr)\
1027  if (IN6_IS_ADDR_UNSPECIFIED (&(addr)->u.prefix6))\
1028    {\
1029      char buf[64];\
1030      prefix2str (addr, buf, sizeof (buf));\
1031      if (IS_OSPF6_DUMP_LSA)\
1032        zlog_info ("  Filter out Unspecified: %s", buf);\
1033      continue;\
1034    }
1035
1036#define CONTINUE_IF_ADDRESS_LOOPBACK(addr)\
1037  if (IN6_IS_ADDR_LOOPBACK (&(addr)->u.prefix6))\
1038    {\
1039      char buf[64];\
1040      prefix2str (addr, buf, sizeof (buf));\
1041      if (IS_OSPF6_DUMP_LSA)\
1042        zlog_info ("  Filter out Loopback: %s", buf);\
1043      continue;\
1044    }
1045
1046#define CONTINUE_IF_ADDRESS_V4COMPAT(addr)\
1047  if (IN6_IS_ADDR_V4COMPAT (&(addr)->u.prefix6))\
1048    {\
1049      char buf[64];\
1050      prefix2str (addr, buf, sizeof (buf));\
1051      if (IS_OSPF6_DUMP_LSA)\
1052        zlog_info ("  Filter out V4Compat: %s", buf);\
1053      continue;\
1054    }
1055
1056#define CONTINUE_IF_ADDRESS_V4MAPPED(addr)\
1057  if (IN6_IS_ADDR_V4MAPPED (&(addr)->u.prefix6))\
1058    {\
1059      char buf[64];\
1060      prefix2str (addr, buf, sizeof (buf));\
1061      if (IS_OSPF6_DUMP_LSA)\
1062        zlog_info ("  Filter out V4Mapped: %s", buf);\
1063      continue;\
1064    }
1065
1066/******************************/
1067/* RFC2740 3.4.3.1 Router-LSA */
1068/******************************/
1069
1070char *
1071ospf6_lsa_router_bits_string (u_char router_bits, char *buf, int size)
1072{
1073  char w, v, e, b;
1074
1075  w = (router_bits & OSPF6_ROUTER_LSA_BIT_W ? 'W' : '-');
1076  v = (router_bits & OSPF6_ROUTER_LSA_BIT_V ? 'V' : '-');
1077  e = (router_bits & OSPF6_ROUTER_LSA_BIT_E ? 'E' : '-');
1078  b = (router_bits & OSPF6_ROUTER_LSA_BIT_B ? 'B' : '-');
1079  snprintf (buf, size, "----%c%c%c%c", w, v, e, b);
1080  return buf;
1081}
1082
1083int
1084ospf6_lsa_router_show (struct vty *vty, struct ospf6_lsa *lsa)
1085{
1086  char *start, *end, *current;
1087  char buf[32], name[32], bits[32], options[32];
1088  struct ospf6_router_lsa *router_lsa;
1089  struct ospf6_router_lsd *lsdesc;
1090
1091  assert (lsa->header);
1092
1093  router_lsa = (struct ospf6_router_lsa *)
1094    ((char *) lsa->header + sizeof (struct ospf6_lsa_header));
1095
1096  ospf6_lsa_router_bits_string (router_lsa->bits, bits, sizeof (bits));
1097  ospf6_options_string (router_lsa->options, options, sizeof (options));
1098  vty_out (vty, "    Bits: %s Options: %s%s", bits, options, VTY_NEWLINE);
1099
1100  start = (char *) router_lsa + sizeof (struct ospf6_router_lsa);
1101  end = (char *) lsa->header + ntohs (lsa->header->length);
1102  for (current = start; current + sizeof (struct ospf6_router_lsd) <= end;
1103       current += sizeof (struct ospf6_router_lsd))
1104    {
1105      lsdesc = (struct ospf6_router_lsd *) current;
1106
1107      if (lsdesc->type == OSPF6_ROUTER_LSD_TYPE_POINTTOPOINT)
1108        snprintf (name, sizeof (name), "Point-To-Point");
1109      else if (lsdesc->type == OSPF6_ROUTER_LSD_TYPE_TRANSIT_NETWORK)
1110        snprintf (name, sizeof (name), "Transit-Network");
1111      else if (lsdesc->type == OSPF6_ROUTER_LSD_TYPE_STUB_NETWORK)
1112        snprintf (name, sizeof (name), "Stub-Network");
1113      else if (lsdesc->type == OSPF6_ROUTER_LSD_TYPE_VIRTUAL_LINK)
1114        snprintf (name, sizeof (name), "Virtual-Link");
1115      else
1116        snprintf (name, sizeof (name), "Unknown (%#x)", lsdesc->type);
1117
1118      vty_out (vty, "    Type: %s Metric: %d%s",
1119               name, ntohs (lsdesc->metric), VTY_NEWLINE);
1120      vty_out (vty, "    Interface ID: %s%s",
1121               inet_ntop (AF_INET, &lsdesc->interface_id,
1122                          buf, sizeof (buf)), VTY_NEWLINE);
1123      vty_out (vty, "    Neighbor Interface ID: %s%s",
1124               inet_ntop (AF_INET, &lsdesc->neighbor_interface_id,
1125                          buf, sizeof (buf)), VTY_NEWLINE);
1126      vty_out (vty, "    Neighbor Router ID: %s%s",
1127               inet_ntop (AF_INET, &lsdesc->neighbor_router_id,
1128                          buf, sizeof (buf)), VTY_NEWLINE);
1129    }
1130  return 0;
1131}
1132
1133void
1134ospf6_lsa_router_update (u_int32_t area_id)
1135{
1136  char buffer [MAXLSASIZE];
1137  u_int16_t size;
1138  struct ospf6_lsa *old;
1139  struct ospf6_area *o6a;
1140  int count;
1141
1142  struct ospf6_router_lsa *router_lsa;
1143  struct ospf6_router_lsd *router_lsd;
1144  listnode i;
1145  struct ospf6_interface *o6i;
1146  struct ospf6_neighbor *o6n = NULL;
1147
1148  o6a = ospf6_area_lookup (area_id, ospf6);
1149  if (! o6a)
1150    {
1151      inet_ntop (AF_INET, &area_id, buffer, sizeof (buffer));
1152      if (IS_OSPF6_DUMP_LSA)
1153        zlog_warn ("Update Router-LSA: No such area: %s", buffer);
1154      return;
1155    }
1156
1157  if (IS_OSPF6_DUMP_LSA)
1158    zlog_info ("Update Router-LSA: for Area %s", o6a->str);
1159
1160  /* find previous LSA */
1161  /* xxx, there may be multiple Router-LSAs */
1162  old = ospf6_lsdb_lookup (htons (OSPF6_LSA_TYPE_ROUTER),
1163                           htonl (0), o6a->ospf6->router_id, o6a);
1164
1165  size = sizeof (struct ospf6_router_lsa);
1166  memset (buffer, 0, sizeof (buffer));
1167  router_lsa = (struct ospf6_router_lsa *) buffer;
1168
1169  OSPF6_OPT_CLEAR_ALL (router_lsa->options);
1170  OSPF6_OPT_SET (router_lsa->options, OSPF6_OPT_V6);
1171  OSPF6_OPT_SET (router_lsa->options, OSPF6_OPT_E);
1172  OSPF6_OPT_CLEAR (router_lsa->options, OSPF6_OPT_MC);
1173  OSPF6_OPT_CLEAR (router_lsa->options, OSPF6_OPT_N);
1174  OSPF6_OPT_SET (router_lsa->options, OSPF6_OPT_R);
1175  OSPF6_OPT_CLEAR (router_lsa->options, OSPF6_OPT_DC);
1176
1177  OSPF6_ROUTER_LSA_CLEAR_ALL_BITS (router_lsa);
1178  OSPF6_ROUTER_LSA_CLEAR (router_lsa, OSPF6_ROUTER_LSA_BIT_B);
1179
1180  if (ospf6_is_asbr (o6a->ospf6))
1181    OSPF6_ROUTER_LSA_SET (router_lsa, OSPF6_ROUTER_LSA_BIT_E);
1182  else
1183    OSPF6_ROUTER_LSA_CLEAR (router_lsa, OSPF6_ROUTER_LSA_BIT_E);
1184
1185  OSPF6_ROUTER_LSA_CLEAR (router_lsa, OSPF6_ROUTER_LSA_BIT_V);
1186  OSPF6_ROUTER_LSA_CLEAR (router_lsa, OSPF6_ROUTER_LSA_BIT_W);
1187
1188  /* describe links for each interfaces */
1189  router_lsd = (struct ospf6_router_lsd *) (router_lsa + 1);
1190  for (i = listhead (o6a->if_list); i; nextnode (i))
1191    {
1192      o6i = (struct ospf6_interface *) getdata (i);
1193      assert (o6i);
1194
1195      /* Interfaces in state Down or Loopback are not described */
1196      if (o6i->state == IFS_DOWN || o6i->state == IFS_LOOPBACK)
1197        continue;
1198
1199      /* Nor are interfaces without any full adjacencies described */
1200      count = 0;
1201      o6i->foreach_nei (o6i, &count, NBS_FULL, ospf6_count_state);
1202      if (count == 0)
1203        continue;
1204
1205      /* Point-to-Point interfaces */
1206      if (if_is_pointopoint (o6i->interface))
1207        {
1208          if (listcount (o6i->neighbor_list) == 0)
1209            continue;
1210
1211          if (listcount (o6i->neighbor_list) != 1)
1212            zlog_warn ("LSA: Multiple neighbors on PoinToPoint: %s",
1213                       o6i->interface->name);
1214
1215          o6n = (struct ospf6_neighbor *)
1216                   getdata (listhead (o6i->neighbor_list));
1217          assert (o6n);
1218
1219          router_lsd->type = OSPF6_ROUTER_LSD_TYPE_POINTTOPOINT;
1220          router_lsd->metric = htons (o6i->cost);
1221          router_lsd->interface_id = htonl (o6i->if_id);
1222          router_lsd->neighbor_interface_id = htonl (o6n->ifid);
1223          router_lsd->neighbor_router_id = o6n->router_id;
1224
1225          size += sizeof (struct ospf6_router_lsd);
1226          router_lsd ++;
1227
1228          continue;
1229        }
1230
1231      /* Broadcast and NBMA interfaces */
1232      if (if_is_broadcast (o6i->interface))
1233        {
1234          /* If this router is not DR,
1235             and If this router not fully adjacent with DR,
1236             this interface is not transit yet: ignore. */
1237          if (o6i->state != IFS_DR)
1238            {
1239              o6n = ospf6_neighbor_lookup (o6i->dr, o6i); /* find DR */
1240              if (o6n == NULL || o6n->state != NBS_FULL)
1241                continue;
1242            }
1243          else
1244            {
1245              count = 0;
1246              o6i->foreach_nei (o6i, &count, NBS_FULL, ospf6_count_state);
1247              if (count == 0)
1248                continue;
1249            }
1250
1251          router_lsd->type = OSPF6_ROUTER_LSD_TYPE_TRANSIT_NETWORK;
1252          router_lsd->metric = htons (o6i->cost);
1253          router_lsd->interface_id = htonl (o6i->if_id);
1254          if (o6i->state != IFS_DR)
1255            {
1256              router_lsd->neighbor_interface_id = htonl (o6n->ifid);
1257              router_lsd->neighbor_router_id = o6n->router_id;
1258            }
1259          else
1260            {
1261              router_lsd->neighbor_interface_id = htonl (o6i->if_id);
1262              router_lsd->neighbor_router_id = o6i->area->ospf6->router_id;
1263            }
1264
1265          size += sizeof (struct ospf6_router_lsd);
1266          router_lsd ++;
1267
1268          continue;
1269        }
1270
1271      /* Virtual links */
1272        /* xxx */
1273      /* Point-to-Multipoint interfaces */
1274        /* xxx */
1275    }
1276
1277  ospf6_lsa_originate (htons (OSPF6_LSA_TYPE_ROUTER),
1278                       htonl (0), o6a->ospf6->router_id,
1279                       (char *) router_lsa, size, o6a);
1280}
1281
1282int
1283ospf6_lsa_router_hook_neighbor (void *neighbor)
1284{
1285  struct ospf6_neighbor *o6n = neighbor;
1286  if (o6n->ospf6_interface->area)
1287    ospf6_lsa_router_update (o6n->ospf6_interface->area->area_id);
1288  return 0;
1289}
1290
1291int
1292ospf6_lsa_router_hook_interface (void *interface)
1293{
1294  struct ospf6_interface *o6i = interface;
1295  if (o6i->area)
1296    ospf6_lsa_router_update (o6i->area->area_id);
1297  return 0;
1298}
1299
1300int
1301ospf6_lsa_router_hook_area (void *area)
1302{
1303  struct ospf6_area *o6a = area;
1304  ospf6_lsa_router_update (o6a->area_id);
1305  return 0;
1306}
1307
1308int
1309ospf6_lsa_router_hook_top (void *ospf6)
1310{
1311  struct ospf6 *o6 = ospf6;
1312  struct ospf6_area *o6a;
1313  listnode node;
1314
1315  for (node = listhead (o6->area_list); node; nextnode (node))
1316    {
1317      o6a = getdata (node);
1318      ospf6_lsa_router_update (o6a->area_id);
1319    }
1320  return 0;
1321}
1322
1323int
1324ospf6_lsa_router_refresh (void *old)
1325{
1326  struct ospf6_lsa *lsa = old;
1327  struct ospf6_area *o6a;
1328
1329  o6a = lsa->scope;
1330  ospf6_lsa_router_update (o6a->area_id);
1331  return 0;
1332}
1333
1334void
1335ospf6_lsa_slot_register_router ()
1336{
1337  struct ospf6_lsa_slot slot;
1338  struct ospf6_hook hook;
1339
1340  memset (&slot, 0, sizeof (struct ospf6_lsa_slot));
1341  slot.type              = htons (OSPF6_LSA_TYPE_ROUTER);
1342  slot.name              = "Router";
1343  slot.func_show         = ospf6_lsa_router_show;
1344  slot.func_refresh      = ospf6_lsa_router_refresh;
1345  ospf6_lsa_slot_register (&slot);
1346
1347  ospf6_lsdb_hook[OSPF6_LSA_TYPE_ROUTER & OSPF6_LSTYPE_CODE_MASK].hook =
1348    ospf6_spf_database_hook;
1349
1350  memset (&hook, 0, sizeof (hook));
1351  hook.name = "OriginateRouter";
1352  hook.hook_change  = ospf6_lsa_router_hook_neighbor;
1353  ospf6_hook_register (&hook, &neighbor_hook);
1354
1355  memset (&hook, 0, sizeof (hook));
1356  hook.name = "OriginateRouter";
1357  hook.hook_change = ospf6_lsa_router_hook_interface;
1358  ospf6_hook_register (&hook, &interface_hook);
1359
1360  memset (&hook, 0, sizeof (hook));
1361  hook.name = "OriginateRouter";
1362  hook.hook_change      = ospf6_lsa_router_hook_area;
1363  ospf6_hook_register (&hook, &area_hook);
1364
1365  memset (&hook, 0, sizeof (hook));
1366  hook.name = "OriginateRouter";
1367  hook.hook_change       = ospf6_lsa_router_hook_top;
1368  ospf6_hook_register (&hook, &top_hook);
1369}
1370
1371/*******************************/
1372/* RFC2740 3.4.3.2 Network-LSA */
1373/*******************************/
1374
1375int
1376ospf6_lsa_network_show (struct vty *vty, struct ospf6_lsa *lsa)
1377{
1378  char *start, *end, *current;
1379  struct ospf6_network_lsa *network_lsa;
1380  u_int32_t *router_id;
1381  char buf[128], options[32];
1382
1383  assert (lsa->header);
1384  network_lsa = (struct ospf6_network_lsa *) (lsa->header + 1);
1385  router_id = (u_int32_t *)(network_lsa + 1);
1386
1387  ospf6_options_string (network_lsa->options, options, sizeof (options));
1388  vty_out (vty, "     Options: %s%s", options, VTY_NEWLINE);
1389
1390  start = (char *) network_lsa + sizeof (struct ospf6_network_lsa);
1391  end = (char *) lsa->header + ntohs (lsa->header->length);
1392  for (current = start; current + sizeof (u_int32_t) <= end;
1393       current += sizeof (u_int32_t))
1394    {
1395      router_id = (u_int32_t *) current;
1396      inet_ntop (AF_INET, router_id, buf, sizeof (buf));
1397      vty_out (vty, "     Attached Router: %s%s", buf, VTY_NEWLINE);
1398    }
1399  return 0;
1400}
1401
1402void
1403ospf6_lsa_network_update (char *ifname)
1404{
1405  char buffer [MAXLSASIZE];
1406  u_int16_t size;
1407  struct ospf6_lsa *old;
1408  struct interface *ifp;
1409  struct ospf6_interface *o6i;
1410  int count;
1411
1412  struct ospf6_network_lsa *network_lsa;
1413  struct ospf6_neighbor *o6n;
1414  u_int32_t *router_id;
1415  listnode node;
1416
1417  ifp = if_lookup_by_name (ifname);
1418  if (! ifp)
1419    {
1420      if (IS_OSPF6_DUMP_LSA)
1421        zlog_warn ("Update Network: No such Interface: %s", ifname);
1422      return;
1423    }
1424
1425  o6i = (struct ospf6_interface *) ifp->info;
1426  if (! o6i || ! o6i->area)
1427    {
1428      if (IS_OSPF6_DUMP_LSA)
1429        zlog_warn ("Update Network: Interface not enabled: %s", ifname);
1430      return;
1431    }
1432
1433  /* find previous LSA */
1434  old = ospf6_lsdb_lookup (htons (OSPF6_LSA_TYPE_NETWORK),
1435                           htonl (o6i->if_id),
1436                           o6i->area->ospf6->router_id, o6i->area);
1437
1438  /* Don't originate Network-LSA if not DR */
1439  if (o6i->state != IFS_DR)
1440    {
1441      if (IS_OSPF6_DUMP_LSA)
1442        zlog_info ("Update Network: Interface %s is not DR",
1443                   o6i->interface->name);
1444      if (old)
1445        ospf6_lsa_premature_aging (old);
1446      return;
1447    }
1448
1449  /* If none of neighbor is adjacent to us */
1450  count = 0;
1451  o6i->foreach_nei (o6i, &count, NBS_FULL, ospf6_count_state);
1452  if (count == 0)
1453    {
1454      if (IS_OSPF6_DUMP_LSA)
1455        zlog_info ("Update Network: Interface %s is Stub",
1456                   o6i->interface->name);
1457      if (old)
1458        ospf6_lsa_premature_aging (old);
1459      return;
1460    }
1461
1462  if (IS_OSPF6_DUMP_LSA)
1463    zlog_info ("Update Network: Interface %s", o6i->interface->name);
1464
1465  /* prepare buffer */
1466  memset (buffer, 0, sizeof (buffer));
1467  size = sizeof (struct ospf6_network_lsa);
1468  network_lsa = (struct ospf6_network_lsa *) buffer;
1469  router_id = (u_int32_t *)(network_lsa + 1);
1470
1471  /* set fields of myself */
1472  *router_id++ = o6i->area->ospf6->router_id;
1473  size += sizeof (u_int32_t);
1474  network_lsa->options[0] |= o6i->area->options[0];
1475  network_lsa->options[1] |= o6i->area->options[1];
1476  network_lsa->options[2] |= o6i->area->options[2];
1477
1478  /* Walk through neighbors */
1479  for (node = listhead (o6i->neighbor_list); node; nextnode (node))
1480    {
1481      o6n = (struct ospf6_neighbor *) getdata (node);
1482
1483      if (o6n->state != NBS_FULL)
1484        continue;
1485
1486      /* set this neighbor's Router-ID to LSA */
1487      *router_id++ = o6n->router_id;
1488      size += sizeof (u_int32_t);
1489
1490      /* options field is logical OR */
1491      network_lsa->options[0] |= o6n->options[0];
1492      network_lsa->options[1] |= o6n->options[1];
1493      network_lsa->options[2] |= o6n->options[2];
1494    }
1495
1496  ospf6_lsa_originate (htons (OSPF6_LSA_TYPE_NETWORK),
1497                       htonl (o6i->if_id), o6i->area->ospf6->router_id,
1498                       (char *) network_lsa, size, o6i->area);
1499}
1500
1501int
1502ospf6_lsa_network_hook_neighbor (void *neighbor)
1503{
1504  struct ospf6_neighbor *o6n = neighbor;
1505  ospf6_lsa_network_update (o6n->ospf6_interface->interface->name);
1506  return 0;
1507}
1508
1509int
1510ospf6_lsa_network_hook_interface (void *interface)
1511{
1512  struct ospf6_interface *o6i = interface;
1513  if (o6i->area)
1514    ospf6_lsa_network_update (o6i->interface->name);
1515  return 0;
1516}
1517
1518int
1519ospf6_lsa_network_refresh (void *old)
1520{
1521  struct ospf6_lsa *lsa = old;
1522  struct interface *ifp;
1523
1524  ifp = if_lookup_by_index (ntohl (lsa->header->id));
1525  if (! ifp)
1526    ospf6_lsa_premature_aging (old);
1527  else
1528    ospf6_lsa_network_update (ifp->name);
1529
1530  return 0;
1531}
1532
1533void
1534ospf6_lsa_slot_register_network ()
1535{
1536  struct ospf6_lsa_slot slot;
1537  struct ospf6_hook hook;
1538
1539  memset (&slot, 0, sizeof (struct ospf6_lsa_slot));
1540  slot.type              = htons (OSPF6_LSA_TYPE_NETWORK);
1541  slot.name              = "Network";
1542  slot.func_show         = ospf6_lsa_network_show;
1543  slot.func_refresh      = ospf6_lsa_network_refresh;
1544  ospf6_lsa_slot_register (&slot);
1545
1546  ospf6_lsdb_hook[OSPF6_LSA_TYPE_NETWORK & OSPF6_LSTYPE_CODE_MASK].hook =
1547    ospf6_spf_database_hook;
1548
1549  memset (&hook, 0, sizeof (hook));
1550  hook.name  = "OriginateNetwork";
1551  hook.hook_change  = ospf6_lsa_network_hook_neighbor;
1552  ospf6_hook_register (&hook, &neighbor_hook);
1553
1554  memset (&hook, 0, sizeof (hook));
1555  hook.name  = "OriginateNetwork";
1556  hook.hook_change = ospf6_lsa_network_hook_interface;
1557  ospf6_hook_register (&hook, &interface_hook);
1558}
1559
1560/****************************/
1561/* RFC2740 3.4.3.6 Link-LSA */
1562/****************************/
1563
1564int
1565ospf6_lsa_link_show (struct vty *vty, struct ospf6_lsa *lsa)
1566{
1567  char *start, *end, *current;
1568  struct ospf6_link_lsa *link_lsa;
1569  int prefixnum;
1570  struct ospf6_prefix *prefix;
1571  char buf[128];
1572  struct in6_addr in6;
1573
1574  assert (lsa->header);
1575
1576  link_lsa = (struct ospf6_link_lsa *) (lsa->header + 1);
1577  prefixnum = ntohl (link_lsa->llsa_prefix_num);
1578
1579  inet_ntop (AF_INET6, (void *)&link_lsa->llsa_linklocal, buf, sizeof (buf));
1580  vty_out (vty, "     LinkLocal Address: %s%s", buf, VTY_NEWLINE);
1581  vty_out (vty, "     Number of Prefix: %d%s", prefixnum, VTY_NEWLINE);
1582
1583  start = (char *) link_lsa + sizeof (struct ospf6_link_lsa);
1584  end = (char *) lsa->header + ntohs (lsa->header->length);
1585  for (current = start; current < end; current += OSPF6_PREFIX_SIZE (prefix))
1586    {
1587      prefix = (struct ospf6_prefix *) current;
1588      if (current + OSPF6_PREFIX_SIZE (prefix) > end)
1589        {
1590          vty_out (vty, "    Trailing %d byte garbage ... Malformed%s",
1591                   end - current, VTY_NEWLINE);
1592          return -1;
1593        }
1594
1595      ospf6_prefix_options_str (prefix->prefix_options, buf, sizeof (buf));
1596      vty_out (vty, "     Prefix Options: %s%s", buf, VTY_NEWLINE);
1597      ospf6_prefix_in6_addr (prefix, &in6);
1598      inet_ntop (AF_INET6, &in6, buf, sizeof (buf));
1599      vty_out (vty, "     Prefix: %s/%d%s",
1600               buf, prefix->prefix_length, VTY_NEWLINE);
1601    }
1602
1603  return 0;
1604}
1605
1606
1607void
1608ospf6_lsa_link_update (char *ifname)
1609{
1610  char *cp, buffer [MAXLSASIZE], buf[32];
1611  u_int16_t size;
1612  struct ospf6_lsa *old;
1613  struct interface *ifp;
1614  struct ospf6_interface *o6i;
1615
1616  struct ospf6_link_lsa *link_lsa;
1617  struct ospf6_prefix *p;
1618  list prefix_connected;
1619  listnode node;
1620  struct connected *c;
1621
1622  ifp = if_lookup_by_name (ifname);
1623  if (! ifp)
1624    {
1625      if (IS_OSPF6_DUMP_LSA)
1626        zlog_info ("Update Link: No such Interface: %s", ifname);
1627      return;
1628    }
1629
1630  o6i = (struct ospf6_interface *) ifp->info;
1631  if (! o6i || ! o6i->area)
1632    {
1633      if (IS_OSPF6_DUMP_LSA)
1634        zlog_info ("Update Link: Interface not enabled: %s", ifname);
1635      return;
1636    }
1637
1638#if 0
1639  /* Link-LSA is on Broadcast or NBMA */
1640  if (! if_is_broadcast (o6i->interface) /* && ! NBMA xxx */)
1641    {
1642      return;
1643    }
1644#endif /*0*/
1645
1646  /* find previous LSA */
1647  old = ospf6_lsdb_lookup (htons (OSPF6_LSA_TYPE_LINK), htonl (o6i->if_id),
1648                           ospf6->router_id, o6i->area);
1649
1650  /* can't make Link-LSA if linklocal address not set */
1651  if (! o6i->lladdr)
1652    {
1653      if (IS_OSPF6_DUMP_LSA)
1654        zlog_warn ("Update Link: No Linklocal Address: %s",
1655                   o6i->interface->name);
1656      if (old)
1657        ospf6_lsa_premature_aging (old);
1658      return;
1659    }
1660
1661  if (IS_OSPF6_DUMP_LSA)
1662    zlog_info ("Update Link: Interface %s", o6i->interface->name);
1663
1664  if (! ospf6_interface_is_enabled (o6i->interface->ifindex))
1665    {
1666      if (IS_OSPF6_DUMP_LSA)
1667        zlog_info ("  Interface %s not enabled", o6i->interface->name);
1668      if (old)
1669        ospf6_lsa_premature_aging (old);
1670      return;
1671    }
1672
1673  /* check connected prefix */
1674  prefix_connected = list_new ();
1675  for (node = listhead (o6i->interface->connected); node; nextnode (node))
1676    {
1677      c = (struct connected *) getdata (node);
1678
1679      /* filter prefix not IPv6 */
1680      if (c->address->family != AF_INET6)
1681        continue;
1682
1683      /* for log */
1684      prefix2str (c->address, buf, sizeof (buf));
1685
1686      CONTINUE_IF_ADDRESS_LINKLOCAL (c->address);
1687      CONTINUE_IF_ADDRESS_UNSPECIFIED (c->address);
1688      CONTINUE_IF_ADDRESS_LOOPBACK (c->address);
1689      CONTINUE_IF_ADDRESS_V4COMPAT (c->address);
1690      CONTINUE_IF_ADDRESS_V4MAPPED (c->address);
1691
1692      /* filter prefix specified by configuration */
1693      if (o6i->plist_name)
1694        {
1695          struct prefix_list *plist;
1696          enum prefix_list_type result = PREFIX_PERMIT;
1697
1698          plist = prefix_list_lookup (AFI_IP6, o6i->plist_name);
1699          if (plist)
1700            result = prefix_list_apply (plist, c->address);
1701          else if (IS_OSPF6_DUMP_LSA)
1702            zlog_warn ("Update Intra-Prefix (Stub): "
1703                       "Prefix list \"%s\" not found", o6i->plist_name);
1704
1705          if (result == PREFIX_DENY)
1706            {
1707              if (IS_OSPF6_DUMP_LSA)
1708                zlog_info ("  Filter out Prefix-list %s: %s",
1709                           o6i->plist_name, buf);
1710              continue;
1711            }
1712        }
1713
1714      if (IS_OSPF6_DUMP_LSA)
1715        zlog_info ("    Advertise %s", buf);
1716
1717      /* hold prefix in list. duplicate is filtered in ospf6_prefix_add() */
1718      p = ospf6_prefix_create (0, 0, (struct prefix_ipv6 *) c->address);
1719      ospf6_prefix_add (prefix_connected, p);
1720    }
1721
1722  /* Note: even if no prefix configured, still we have to create Link-LSA
1723     for next-hop resolution */
1724
1725  memset (buffer, 0, sizeof (buffer));
1726  size = sizeof (struct ospf6_link_lsa);
1727  link_lsa = (struct ospf6_link_lsa *) buffer;
1728
1729  /* fill Link LSA and calculate size */
1730  link_lsa->llsa_rtr_pri = o6i->priority;
1731  link_lsa->llsa_options[0] = o6i->area->options[0];
1732  link_lsa->llsa_options[1] = o6i->area->options[1];
1733  link_lsa->llsa_options[2] = o6i->area->options[2];
1734
1735  /* linklocal address */
1736  memcpy (&link_lsa->llsa_linklocal, o6i->lladdr, sizeof (struct in6_addr));
1737
1738#ifdef KAME /* clear ifindex */
1739  if (link_lsa->llsa_linklocal.s6_addr[3] & 0x0f)
1740    link_lsa->llsa_linklocal.s6_addr[3] &= ~((char)0x0f);
1741#endif /* KAME */
1742
1743  link_lsa->llsa_prefix_num = htonl (listcount (prefix_connected));
1744  cp = (char *)(link_lsa + 1);
1745  for (node = listhead (prefix_connected); node; nextnode (node))
1746    {
1747      p = (struct ospf6_prefix *) getdata (node);
1748      size += OSPF6_PREFIX_SIZE (p);
1749      memcpy (cp, p, OSPF6_PREFIX_SIZE (p));
1750      cp += OSPF6_PREFIX_SIZE (p);
1751    }
1752
1753  for (node = listhead (prefix_connected); node; nextnode (node))
1754    {
1755      p = (struct ospf6_prefix *) getdata (node);
1756      ospf6_prefix_delete (p);
1757    }
1758  list_delete (prefix_connected);
1759
1760  ospf6_lsa_originate (htons (OSPF6_LSA_TYPE_LINK),
1761                       htonl (o6i->if_id), o6i->area->ospf6->router_id,
1762                       (char *) link_lsa, size, o6i);
1763}
1764
1765int
1766ospf6_lsa_link_hook_interface (void *interface)
1767{
1768  struct ospf6_interface *o6i = interface;
1769  if (o6i->area)
1770    ospf6_lsa_link_update (o6i->interface->name);
1771  return 0;
1772}
1773
1774int
1775ospf6_lsa_link_refresh (void *old)
1776{
1777  struct ospf6_lsa *lsa = old;
1778  struct interface *ifp;
1779
1780  ifp = if_lookup_by_index (ntohl (lsa->header->id));
1781  if (! ifp)
1782    ospf6_lsa_premature_aging (old);
1783  else
1784    ospf6_lsa_link_update (ifp->name);
1785
1786  return 0;
1787}
1788
1789void
1790ospf6_lsa_slot_register_link ()
1791{
1792  struct ospf6_lsa_slot slot;
1793
1794  memset (&slot, 0, sizeof (struct ospf6_lsa_slot));
1795  slot.type              = htons (OSPF6_LSA_TYPE_LINK);
1796  slot.name              = "Link";
1797  slot.func_show         = ospf6_lsa_link_show;
1798  slot.func_refresh      = ospf6_lsa_link_refresh;
1799  slot.hook_interface.name = "OriginateLink";
1800  slot.hook_interface.hook_change = ospf6_lsa_link_hook_interface;
1801  ospf6_lsa_slot_register (&slot);
1802
1803  /*
1804   * Link LSA handling will be shift in ospf6_intra.c
1805   * Currently, only database hook only moved to ospf6_intra.c
1806   */
1807#if 0
1808  ospf6_lsdb_hook[OSPF6_LSA_TYPE_LINK & OSPF6_LSTYPE_CODE_MASK].hook =
1809    ospf6_spf_database_hook;
1810#endif /*0*/
1811}
1812
1813int
1814ospf6_lsa_add_hook (void *data)
1815{
1816  struct ospf6_lsa *lsa = data;
1817  struct ospf6_lsa_slot *sp;
1818
1819  sp = ospf6_lsa_slot_get (lsa->header->type);
1820  if (sp)
1821    {
1822      CALL_CHANGE_HOOK (&sp->database_hook, lsa);
1823    }
1824  else
1825    zlog_warn ("Unknown LSA added to database: %s", lsa->str);
1826  return 0;
1827}
1828
1829int
1830ospf6_lsa_change_hook (void *data)
1831{
1832  struct ospf6_lsa *lsa = data;
1833  struct ospf6_lsa_slot *sp;
1834
1835  sp = ospf6_lsa_slot_get (lsa->header->type);
1836  if (sp)
1837    {
1838      CALL_CHANGE_HOOK (&sp->database_hook, lsa);
1839    }
1840  else
1841    zlog_warn ("Unknown LSA changed in database: %s", lsa->str);
1842  return 0;
1843}
1844
1845int
1846ospf6_lsa_remove_hook (void *data)
1847{
1848  struct ospf6_lsa *lsa = data;
1849  struct ospf6_lsa_slot *sp;
1850
1851  sp = ospf6_lsa_slot_get (lsa->header->type);
1852  if (sp)
1853    {
1854      CALL_REMOVE_HOOK (&sp->database_hook, lsa);
1855    }
1856  else
1857    zlog_warn ("Unknown LSA removed from database: %s", lsa->str);
1858  return 0;
1859}
1860
1861/* Initialize LSA slots */
1862void
1863ospf6_lsa_init ()
1864{
1865  struct ospf6_hook hook;
1866
1867  slot_head = NULL;
1868  ospf6_lsa_slot_register_router ();
1869  ospf6_lsa_slot_register_network ();
1870  ospf6_lsa_slot_register_link ();
1871#if 0
1872  ospf6_lsa_slot_register_intra_prefix ();
1873  ospf6_lsa_slot_register_as_external ();
1874#endif /*0*/
1875
1876  hook.name = "LSADatabaseHook";
1877  hook.hook_add = ospf6_lsa_add_hook;
1878  hook.hook_change = ospf6_lsa_change_hook;
1879  hook.hook_remove = ospf6_lsa_remove_hook;
1880  ospf6_hook_register (&hook, &database_hook);
1881}
1882
1883