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