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