]>
Commit | Line | Data |
---|---|---|
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" |
718e3744 | 32 | |
33 | #include "ospf6_proto.h" | |
718e3744 | 34 | #include "ospf6_lsa.h" |
35 | #include "ospf6_lsdb.h" | |
36 | #include "ospf6_message.h" | |
718e3744 | 37 | |
38 | #include "ospf6_top.h" | |
39 | #include "ospf6_area.h" | |
40 | #include "ospf6_interface.h" | |
41 | #include "ospf6_neighbor.h" | |
718e3744 | 42 | |
508e53e2 | 43 | #include "ospf6_flood.h" |
049207c3 | 44 | #include "ospf6d.h" |
718e3744 | 45 | |
1e05838a | 46 | vector ospf6_lsa_handler_vector; |
718e3744 | 47 | |
6ac29a51 | 48 | static int |
1e05838a | 49 | ospf6_unknown_lsa_show (struct vty *vty, struct ospf6_lsa *lsa) |
50 | { | |
51 | u_char *start, *end, *current; | |
52 | char byte[4]; | |
53 | ||
03d52f8d | 54 | start = (u_char *) lsa->header + sizeof (struct ospf6_lsa_header); |
55 | end = (u_char *) lsa->header + ntohs (lsa->header->length); | |
1e05838a | 56 | |
57 | vty_out (vty, " Unknown contents:%s", VNL); | |
58 | for (current = start; current < end; current ++) | |
59 | { | |
60 | if ((current - start) % 16 == 0) | |
61 | vty_out (vty, "%s ", VNL); | |
62 | else if ((current - start) % 4 == 0) | |
63 | vty_out (vty, " "); | |
718e3744 | 64 | |
1e05838a | 65 | snprintf (byte, sizeof (byte), "%02x", *current); |
66 | vty_out (vty, "%s", byte); | |
67 | } | |
68 | ||
69 | vty_out (vty, "%s%s", VNL, VNL); | |
70 | return 0; | |
71 | } | |
72 | ||
73 | struct ospf6_lsa_handler unknown_handler = | |
74 | { | |
75 | OSPF6_LSTYPE_UNKNOWN, | |
76 | "Unknown", | |
77 | ospf6_unknown_lsa_show, | |
78 | OSPF6_LSA_DEBUG, | |
79 | }; | |
80 | ||
81 | void | |
82 | ospf6_install_lsa_handler (struct ospf6_lsa_handler *handler) | |
83 | { | |
84 | /* type in handler is host byte order */ | |
85 | int index = handler->type & OSPF6_LSTYPE_FCODE_MASK; | |
86 | vector_set_index (ospf6_lsa_handler_vector, index, handler); | |
87 | } | |
88 | ||
89 | struct ospf6_lsa_handler * | |
90 | ospf6_get_lsa_handler (u_int16_t type) | |
91 | { | |
92 | struct ospf6_lsa_handler *handler = NULL; | |
0c083ee9 | 93 | unsigned int index = ntohs (type) & OSPF6_LSTYPE_FCODE_MASK; |
1e05838a | 94 | |
55468c86 | 95 | if (index >= vector_active (ospf6_lsa_handler_vector)) |
1e05838a | 96 | handler = &unknown_handler; |
97 | else | |
98 | handler = vector_slot (ospf6_lsa_handler_vector, index); | |
99 | ||
2680aa2b | 100 | if (handler == NULL) |
101 | handler = &unknown_handler; | |
102 | ||
1e05838a | 103 | return handler; |
104 | } | |
718e3744 | 105 | |
0c083ee9 | 106 | const char * |
508e53e2 | 107 | ospf6_lstype_name (u_int16_t type) |
108 | { | |
109 | static char buf[8]; | |
1e05838a | 110 | struct ospf6_lsa_handler *handler; |
508e53e2 | 111 | |
1e05838a | 112 | handler = ospf6_get_lsa_handler (type); |
113 | if (handler && handler != &unknown_handler) | |
114 | return handler->name; | |
718e3744 | 115 | |
508e53e2 | 116 | snprintf (buf, sizeof (buf), "0x%04hx", ntohs (type)); |
117 | return buf; | |
718e3744 | 118 | } |
119 | ||
1e05838a | 120 | u_char |
121 | ospf6_lstype_debug (u_int16_t type) | |
122 | { | |
123 | struct ospf6_lsa_handler *handler; | |
124 | handler = ospf6_get_lsa_handler (type); | |
125 | return handler->debug; | |
126 | } | |
127 | ||
718e3744 | 128 | /* RFC2328: Section 13.2 */ |
129 | int | |
508e53e2 | 130 | ospf6_lsa_is_differ (struct ospf6_lsa *lsa1, |
131 | struct ospf6_lsa *lsa2) | |
718e3744 | 132 | { |
508e53e2 | 133 | int len; |
718e3744 | 134 | |
508e53e2 | 135 | assert (OSPF6_LSA_IS_SAME (lsa1, lsa2)); |
718e3744 | 136 | |
508e53e2 | 137 | /* XXX, Options ??? */ |
718e3744 | 138 | |
139 | ospf6_lsa_age_current (lsa1); | |
140 | ospf6_lsa_age_current (lsa2); | |
141 | if (ntohs (lsa1->header->age) == MAXAGE && | |
142 | ntohs (lsa2->header->age) != MAXAGE) | |
143 | return 1; | |
144 | if (ntohs (lsa1->header->age) != MAXAGE && | |
145 | ntohs (lsa2->header->age) == MAXAGE) | |
146 | return 1; | |
147 | ||
148 | /* compare body */ | |
149 | if (ntohs (lsa1->header->length) != ntohs (lsa2->header->length)) | |
150 | return 1; | |
151 | ||
508e53e2 | 152 | len = ntohs (lsa1->header->length) - sizeof (struct ospf6_lsa_header); |
153 | return memcmp (lsa1->header + 1, lsa2->header + 1, len); | |
718e3744 | 154 | } |
155 | ||
156 | int | |
508e53e2 | 157 | ospf6_lsa_is_changed (struct ospf6_lsa *lsa1, |
158 | struct ospf6_lsa *lsa2) | |
718e3744 | 159 | { |
508e53e2 | 160 | int length; |
718e3744 | 161 | |
508e53e2 | 162 | if (OSPF6_LSA_IS_MAXAGE (lsa1) ^ OSPF6_LSA_IS_MAXAGE (lsa2)) |
163 | return 1; | |
164 | if (ntohs (lsa1->header->length) != ntohs (lsa2->header->length)) | |
165 | return 1; | |
718e3744 | 166 | |
508e53e2 | 167 | length = OSPF6_LSA_SIZE (lsa1->header) - sizeof (struct ospf6_lsa_header); |
168 | assert (length > 0); | |
718e3744 | 169 | |
508e53e2 | 170 | return memcmp (OSPF6_LSA_HEADER_END (lsa1->header), |
171 | OSPF6_LSA_HEADER_END (lsa2->header), length); | |
718e3744 | 172 | } |
173 | ||
174 | /* ospf6 age functions */ | |
3b68735f | 175 | /* calculate birth */ |
718e3744 | 176 | static void |
177 | ospf6_lsa_age_set (struct ospf6_lsa *lsa) | |
178 | { | |
179 | struct timeval now; | |
180 | ||
181 | assert (lsa && lsa->header); | |
182 | ||
183 | if (gettimeofday (&now, (struct timezone *)NULL) < 0) | |
184 | zlog_warn ("LSA: gettimeofday failed, may fail LSA AGEs: %s", | |
6099b3b5 | 185 | safe_strerror (errno)); |
718e3744 | 186 | |
187 | lsa->birth.tv_sec = now.tv_sec - ntohs (lsa->header->age); | |
188 | lsa->birth.tv_usec = now.tv_usec; | |
3b68735f | 189 | |
718e3744 | 190 | return; |
191 | } | |
192 | ||
193 | /* this function calculates current age from its birth, | |
194 | then update age field of LSA header. return value is current age */ | |
195 | u_int16_t | |
196 | ospf6_lsa_age_current (struct ospf6_lsa *lsa) | |
197 | { | |
198 | struct timeval now; | |
199 | u_int32_t ulage; | |
200 | u_int16_t age; | |
201 | ||
202 | assert (lsa); | |
203 | assert (lsa->header); | |
204 | ||
205 | /* current time */ | |
206 | if (gettimeofday (&now, (struct timezone *)NULL) < 0) | |
508e53e2 | 207 | zlog_warn ("LSA: gettimeofday failed, may fail LSA AGEs: %s", |
6099b3b5 | 208 | safe_strerror (errno)); |
718e3744 | 209 | |
210 | /* calculate age */ | |
211 | ulage = now.tv_sec - lsa->birth.tv_sec; | |
212 | ||
213 | /* if over MAXAGE, set to it */ | |
508e53e2 | 214 | age = (ulage > MAXAGE ? MAXAGE : ulage); |
718e3744 | 215 | |
216 | lsa->header->age = htons (age); | |
217 | return age; | |
218 | } | |
219 | ||
220 | /* update age field of LSA header with adding InfTransDelay */ | |
221 | void | |
222 | ospf6_lsa_age_update_to_send (struct ospf6_lsa *lsa, u_int32_t transdelay) | |
223 | { | |
224 | unsigned short age; | |
225 | ||
226 | age = ospf6_lsa_age_current (lsa) + transdelay; | |
227 | if (age > MAXAGE) | |
228 | age = MAXAGE; | |
229 | lsa->header->age = htons (age); | |
718e3744 | 230 | } |
231 | ||
232 | void | |
233 | ospf6_lsa_premature_aging (struct ospf6_lsa *lsa) | |
234 | { | |
235 | /* log */ | |
1e05838a | 236 | if (IS_OSPF6_DEBUG_LSA_TYPE (lsa->header->type)) |
c6487d61 | 237 | zlog_debug ("LSA: Premature aging: %s", lsa->name); |
718e3744 | 238 | |
508e53e2 | 239 | THREAD_OFF (lsa->expire); |
240 | THREAD_OFF (lsa->refresh); | |
718e3744 | 241 | |
242 | memset (&lsa->birth, 0, sizeof (struct timeval)); | |
243 | thread_execute (master, ospf6_lsa_expire, lsa, 0); | |
244 | } | |
245 | ||
246 | /* check which is more recent. if a is more recent, return -1; | |
247 | if the same, return 0; otherwise(b is more recent), return 1 */ | |
248 | int | |
508e53e2 | 249 | ospf6_lsa_compare (struct ospf6_lsa *a, struct ospf6_lsa *b) |
718e3744 | 250 | { |
251 | signed long seqnuma, seqnumb; | |
252 | u_int16_t cksuma, cksumb; | |
253 | u_int16_t agea, ageb; | |
254 | ||
255 | assert (a && a->header); | |
256 | assert (b && b->header); | |
508e53e2 | 257 | assert (OSPF6_LSA_IS_SAME (a, b)); |
718e3744 | 258 | |
259 | seqnuma = ((signed long) ntohl (a->header->seqnum)) | |
260 | - (signed long) INITIAL_SEQUENCE_NUMBER; | |
261 | seqnumb = ((signed long) ntohl (b->header->seqnum)) | |
262 | - (signed long) INITIAL_SEQUENCE_NUMBER; | |
263 | ||
264 | /* compare by sequence number */ | |
508e53e2 | 265 | /* XXX, LS sequence number wrapping */ |
718e3744 | 266 | if (seqnuma > seqnumb) |
267 | return -1; | |
268 | else if (seqnuma < seqnumb) | |
269 | return 1; | |
270 | ||
271 | /* Checksum */ | |
272 | cksuma = ntohs (a->header->checksum); | |
273 | cksumb = ntohs (b->header->checksum); | |
274 | if (cksuma > cksumb) | |
275 | return -1; | |
276 | if (cksuma < cksumb) | |
277 | return 0; | |
278 | ||
508e53e2 | 279 | /* Update Age */ |
718e3744 | 280 | agea = ospf6_lsa_age_current (a); |
281 | ageb = ospf6_lsa_age_current (b); | |
282 | ||
508e53e2 | 283 | /* MaxAge check */ |
284 | if (agea == MAXAGE && ageb != MAXAGE) | |
718e3744 | 285 | return -1; |
508e53e2 | 286 | else if (agea != MAXAGE && ageb == MAXAGE) |
718e3744 | 287 | return 1; |
288 | ||
508e53e2 | 289 | /* Age check */ |
290 | if (agea > ageb && agea - ageb >= MAX_AGE_DIFF) | |
718e3744 | 291 | return 1; |
508e53e2 | 292 | else if (agea < ageb && ageb - agea >= MAX_AGE_DIFF) |
718e3744 | 293 | return -1; |
294 | ||
295 | /* neither recent */ | |
718e3744 | 296 | return 0; |
297 | } | |
298 | ||
508e53e2 | 299 | char * |
300 | ospf6_lsa_printbuf (struct ospf6_lsa *lsa, char *buf, int size) | |
718e3744 | 301 | { |
508e53e2 | 302 | char id[16], adv_router[16]; |
303 | inet_ntop (AF_INET, &lsa->header->id, id, sizeof (id)); | |
304 | inet_ntop (AF_INET, &lsa->header->adv_router, adv_router, | |
305 | sizeof (adv_router)); | |
306 | snprintf (buf, size, "[%s Id:%s Adv:%s]", | |
1e05838a | 307 | ospf6_lstype_name (lsa->header->type), id, adv_router); |
508e53e2 | 308 | return buf; |
718e3744 | 309 | } |
310 | ||
508e53e2 | 311 | void |
312 | ospf6_lsa_header_print_raw (struct ospf6_lsa_header *header) | |
718e3744 | 313 | { |
508e53e2 | 314 | char id[16], adv_router[16]; |
315 | inet_ntop (AF_INET, &header->id, id, sizeof (id)); | |
316 | inet_ntop (AF_INET, &header->adv_router, adv_router, | |
317 | sizeof (adv_router)); | |
c6487d61 | 318 | zlog_debug (" [%s Id:%s Adv:%s]", |
319 | ospf6_lstype_name (header->type), id, adv_router); | |
320 | zlog_debug (" Age: %4hu SeqNum: %#08lx Cksum: %04hx Len: %d", | |
321 | ntohs (header->age), (u_long) ntohl (header->seqnum), | |
322 | ntohs (header->checksum), ntohs (header->length)); | |
718e3744 | 323 | } |
324 | ||
508e53e2 | 325 | void |
326 | ospf6_lsa_header_print (struct ospf6_lsa *lsa) | |
718e3744 | 327 | { |
508e53e2 | 328 | ospf6_lsa_age_current (lsa); |
329 | ospf6_lsa_header_print_raw (lsa->header); | |
718e3744 | 330 | } |
331 | ||
718e3744 | 332 | void |
333 | ospf6_lsa_show_summary_header (struct vty *vty) | |
334 | { | |
335 | vty_out (vty, "%-12s %-15s %-15s %4s %8s %4s %4s %-8s%s", | |
336 | "Type", "LSId", "AdvRouter", "Age", "SeqNum", | |
049207c3 | 337 | "Cksm", "Len", "Duration", VNL); |
718e3744 | 338 | } |
339 | ||
340 | void | |
341 | ospf6_lsa_show_summary (struct vty *vty, struct ospf6_lsa *lsa) | |
342 | { | |
508e53e2 | 343 | char adv_router[16], id[16]; |
718e3744 | 344 | struct timeval now, res; |
345 | char duration[16]; | |
346 | ||
347 | assert (lsa); | |
348 | assert (lsa->header); | |
349 | ||
718e3744 | 350 | inet_ntop (AF_INET, &lsa->header->id, id, sizeof (id)); |
351 | inet_ntop (AF_INET, &lsa->header->adv_router, adv_router, | |
352 | sizeof (adv_router)); | |
353 | ||
354 | gettimeofday (&now, NULL); | |
508e53e2 | 355 | timersub (&now, &lsa->installed, &res); |
356 | timerstring (&res, duration, sizeof (duration)); | |
718e3744 | 357 | |
358 | vty_out (vty, "%-12s %-15s %-15s %4hu %8lx %04hx %4hu %8s%s", | |
1e05838a | 359 | ospf6_lstype_name (lsa->header->type), |
508e53e2 | 360 | id, adv_router, ospf6_lsa_age_current (lsa), |
718e3744 | 361 | (u_long) ntohl (lsa->header->seqnum), |
362 | ntohs (lsa->header->checksum), ntohs (lsa->header->length), | |
049207c3 | 363 | duration, VNL); |
718e3744 | 364 | } |
365 | ||
366 | void | |
367 | ospf6_lsa_show_dump (struct vty *vty, struct ospf6_lsa *lsa) | |
368 | { | |
369 | u_char *start, *end, *current; | |
370 | char byte[4]; | |
371 | ||
03d52f8d | 372 | start = (u_char *) lsa->header; |
373 | end = (u_char *) lsa->header + ntohs (lsa->header->length); | |
718e3744 | 374 | |
049207c3 | 375 | vty_out (vty, "%s", VNL); |
376 | vty_out (vty, "%s:%s", lsa->name, VNL); | |
718e3744 | 377 | |
378 | for (current = start; current < end; current ++) | |
379 | { | |
380 | if ((current - start) % 16 == 0) | |
049207c3 | 381 | vty_out (vty, "%s ", VNL); |
718e3744 | 382 | else if ((current - start) % 4 == 0) |
383 | vty_out (vty, " "); | |
384 | ||
385 | snprintf (byte, sizeof (byte), "%02x", *current); | |
386 | vty_out (vty, "%s", byte); | |
387 | } | |
388 | ||
049207c3 | 389 | vty_out (vty, "%s%s", VNL, VNL); |
6452df09 | 390 | return; |
718e3744 | 391 | } |
392 | ||
508e53e2 | 393 | void |
394 | ospf6_lsa_show_internal (struct vty *vty, struct ospf6_lsa *lsa) | |
395 | { | |
396 | char adv_router[64], id[64]; | |
397 | ||
398 | assert (lsa && lsa->header); | |
399 | ||
400 | inet_ntop (AF_INET, &lsa->header->id, id, sizeof (id)); | |
401 | inet_ntop (AF_INET, &lsa->header->adv_router, | |
402 | adv_router, sizeof (adv_router)); | |
403 | ||
049207c3 | 404 | vty_out (vty, "%s", VNL); |
508e53e2 | 405 | vty_out (vty, "Age: %4hu Type: %s%s", ospf6_lsa_age_current (lsa), |
1e05838a | 406 | ospf6_lstype_name (lsa->header->type), VNL); |
049207c3 | 407 | vty_out (vty, "Link State ID: %s%s", id, VNL); |
408 | vty_out (vty, "Advertising Router: %s%s", adv_router, VNL); | |
508e53e2 | 409 | vty_out (vty, "LS Sequence Number: %#010lx%s", |
049207c3 | 410 | (u_long) ntohl (lsa->header->seqnum), VNL); |
508e53e2 | 411 | vty_out (vty, "CheckSum: %#06hx Length: %hu%s", |
412 | ntohs (lsa->header->checksum), | |
049207c3 | 413 | ntohs (lsa->header->length), VNL); |
508e53e2 | 414 | vty_out (vty, " Prev: %p This: %p Next: %p%s", |
049207c3 | 415 | lsa->prev, lsa, lsa->next, VNL); |
416 | vty_out (vty, "%s", VNL); | |
6452df09 | 417 | return; |
508e53e2 | 418 | } |
419 | ||
6452df09 | 420 | void |
421 | ospf6_lsa_show (struct vty *vty, struct ospf6_lsa *lsa) | |
422 | { | |
423 | char adv_router[64], id[64]; | |
1e05838a | 424 | struct ospf6_lsa_handler *handler; |
6452df09 | 425 | |
426 | assert (lsa && lsa->header); | |
718e3744 | 427 | |
6452df09 | 428 | inet_ntop (AF_INET, &lsa->header->id, id, sizeof (id)); |
429 | inet_ntop (AF_INET, &lsa->header->adv_router, | |
430 | adv_router, sizeof (adv_router)); | |
431 | ||
432 | vty_out (vty, "Age: %4hu Type: %s%s", ospf6_lsa_age_current (lsa), | |
1e05838a | 433 | ospf6_lstype_name (lsa->header->type), VNL); |
6452df09 | 434 | vty_out (vty, "Link State ID: %s%s", id, VNL); |
435 | vty_out (vty, "Advertising Router: %s%s", adv_router, VNL); | |
436 | vty_out (vty, "LS Sequence Number: %#010lx%s", | |
437 | (u_long) ntohl (lsa->header->seqnum), VNL); | |
438 | vty_out (vty, "CheckSum: %#06hx Length: %hu%s", | |
439 | ntohs (lsa->header->checksum), | |
440 | ntohs (lsa->header->length), VNL); | |
441 | ||
1e05838a | 442 | handler = ospf6_get_lsa_handler (lsa->header->type); |
443 | if (handler->show == NULL) | |
444 | handler = &unknown_handler; | |
445 | (*handler->show) (vty, lsa); | |
6452df09 | 446 | |
447 | vty_out (vty, "%s", VNL); | |
448 | } | |
449 | ||
450 | /* OSPFv3 LSA creation/deletion function */ | |
718e3744 | 451 | struct ospf6_lsa * |
508e53e2 | 452 | ospf6_lsa_create (struct ospf6_lsa_header *header) |
718e3744 | 453 | { |
454 | struct ospf6_lsa *lsa = NULL; | |
508e53e2 | 455 | struct ospf6_lsa_header *new_header = NULL; |
718e3744 | 456 | u_int16_t lsa_size = 0; |
718e3744 | 457 | |
508e53e2 | 458 | /* size of the entire LSA */ |
459 | lsa_size = ntohs (header->length); /* XXX vulnerable */ | |
718e3744 | 460 | |
461 | /* allocate memory for this LSA */ | |
508e53e2 | 462 | new_header = (struct ospf6_lsa_header *) |
718e3744 | 463 | XMALLOC (MTYPE_OSPF6_LSA, lsa_size); |
718e3744 | 464 | |
508e53e2 | 465 | /* copy LSA from original header */ |
466 | memcpy (new_header, header, lsa_size); | |
718e3744 | 467 | |
468 | /* LSA information structure */ | |
469 | /* allocate memory */ | |
470 | lsa = (struct ospf6_lsa *) | |
508e53e2 | 471 | XMALLOC (MTYPE_OSPF6_LSA, sizeof (struct ospf6_lsa)); |
718e3744 | 472 | memset (lsa, 0, sizeof (struct ospf6_lsa)); |
473 | ||
508e53e2 | 474 | lsa->header = (struct ospf6_lsa_header *) new_header; |
718e3744 | 475 | |
476 | /* dump string */ | |
508e53e2 | 477 | ospf6_lsa_printbuf (lsa, lsa->name, sizeof (lsa->name)); |
718e3744 | 478 | |
3b68735f | 479 | /* calculate birth of this lsa */ |
718e3744 | 480 | ospf6_lsa_age_set (lsa); |
481 | ||
718e3744 | 482 | return lsa; |
483 | } | |
484 | ||
485 | struct ospf6_lsa * | |
508e53e2 | 486 | ospf6_lsa_create_headeronly (struct ospf6_lsa_header *header) |
718e3744 | 487 | { |
488 | struct ospf6_lsa *lsa = NULL; | |
508e53e2 | 489 | struct ospf6_lsa_header *new_header = NULL; |
718e3744 | 490 | |
491 | /* allocate memory for this LSA */ | |
508e53e2 | 492 | new_header = (struct ospf6_lsa_header *) |
493 | XMALLOC (MTYPE_OSPF6_LSA, sizeof (struct ospf6_lsa_header)); | |
718e3744 | 494 | |
508e53e2 | 495 | /* copy LSA from original header */ |
496 | memcpy (new_header, header, sizeof (struct ospf6_lsa_header)); | |
718e3744 | 497 | |
498 | /* LSA information structure */ | |
499 | /* allocate memory */ | |
500 | lsa = (struct ospf6_lsa *) | |
508e53e2 | 501 | XMALLOC (MTYPE_OSPF6_LSA, sizeof (struct ospf6_lsa)); |
718e3744 | 502 | memset (lsa, 0, sizeof (struct ospf6_lsa)); |
503 | ||
508e53e2 | 504 | lsa->header = (struct ospf6_lsa_header *) new_header; |
6452df09 | 505 | SET_FLAG (lsa->flag, OSPF6_LSA_HEADERONLY); |
718e3744 | 506 | |
507 | /* dump string */ | |
508e53e2 | 508 | ospf6_lsa_printbuf (lsa, lsa->name, sizeof (lsa->name)); |
718e3744 | 509 | |
3b68735f | 510 | /* calculate birth of this lsa */ |
718e3744 | 511 | ospf6_lsa_age_set (lsa); |
512 | ||
718e3744 | 513 | return lsa; |
514 | } | |
515 | ||
516 | void | |
517 | ospf6_lsa_delete (struct ospf6_lsa *lsa) | |
518 | { | |
508e53e2 | 519 | assert (lsa->lock == 0); |
718e3744 | 520 | |
521 | /* cancel threads */ | |
508e53e2 | 522 | THREAD_OFF (lsa->expire); |
523 | THREAD_OFF (lsa->refresh); | |
718e3744 | 524 | |
718e3744 | 525 | /* do free */ |
508e53e2 | 526 | XFREE (MTYPE_OSPF6_LSA, lsa->header); |
527 | XFREE (MTYPE_OSPF6_LSA, lsa); | |
528 | } | |
718e3744 | 529 | |
508e53e2 | 530 | struct ospf6_lsa * |
531 | ospf6_lsa_copy (struct ospf6_lsa *lsa) | |
532 | { | |
533 | struct ospf6_lsa *copy = NULL; | |
534 | ||
508e53e2 | 535 | ospf6_lsa_age_current (lsa); |
6452df09 | 536 | if (CHECK_FLAG (lsa->flag, OSPF6_LSA_HEADERONLY)) |
508e53e2 | 537 | copy = ospf6_lsa_create_headeronly (lsa->header); |
718e3744 | 538 | else |
508e53e2 | 539 | copy = ospf6_lsa_create (lsa->header); |
540 | assert (copy->lock == 0); | |
541 | ||
3b68735f | 542 | copy->birth = lsa->birth; |
508e53e2 | 543 | copy->originated = lsa->originated; |
ccb59b11 | 544 | copy->received = lsa->received; |
545 | copy->installed = lsa->installed; | |
6452df09 | 546 | copy->lsdb = lsa->lsdb; |
508e53e2 | 547 | |
508e53e2 | 548 | return copy; |
718e3744 | 549 | } |
550 | ||
508e53e2 | 551 | /* increment reference counter of struct ospf6_lsa */ |
718e3744 | 552 | void |
553 | ospf6_lsa_lock (struct ospf6_lsa *lsa) | |
554 | { | |
555 | lsa->lock++; | |
556 | return; | |
557 | } | |
558 | ||
508e53e2 | 559 | /* decrement reference counter of struct ospf6_lsa */ |
718e3744 | 560 | void |
561 | ospf6_lsa_unlock (struct ospf6_lsa *lsa) | |
562 | { | |
563 | /* decrement reference counter */ | |
508e53e2 | 564 | assert (lsa->lock > 0); |
565 | lsa->lock--; | |
718e3744 | 566 | |
508e53e2 | 567 | if (lsa->lock != 0) |
568 | return; | |
569 | ||
508e53e2 | 570 | ospf6_lsa_delete (lsa); |
718e3744 | 571 | } |
572 | ||
718e3744 | 573 | \f |
508e53e2 | 574 | /* ospf6 lsa expiry */ |
718e3744 | 575 | int |
576 | ospf6_lsa_expire (struct thread *thread) | |
577 | { | |
578 | struct ospf6_lsa *lsa; | |
718e3744 | 579 | |
580 | lsa = (struct ospf6_lsa *) THREAD_ARG (thread); | |
718e3744 | 581 | |
508e53e2 | 582 | assert (lsa && lsa->header); |
583 | assert (OSPF6_LSA_IS_MAXAGE (lsa)); | |
584 | assert (! lsa->refresh); | |
718e3744 | 585 | |
586 | lsa->expire = (struct thread *) NULL; | |
587 | ||
1e05838a | 588 | if (IS_OSPF6_DEBUG_LSA_TYPE (lsa->header->type)) |
718e3744 | 589 | { |
c6487d61 | 590 | zlog_debug ("LSA Expire:"); |
508e53e2 | 591 | ospf6_lsa_header_print (lsa); |
592 | } | |
718e3744 | 593 | |
6452df09 | 594 | if (CHECK_FLAG (lsa->flag, OSPF6_LSA_HEADERONLY)) |
508e53e2 | 595 | return 0; /* dbexchange will do something ... */ |
718e3744 | 596 | |
508e53e2 | 597 | /* reflood lsa */ |
6452df09 | 598 | ospf6_flood (NULL, lsa); |
508e53e2 | 599 | |
600 | /* reinstall lsa */ | |
3b68735f | 601 | ospf6_install_lsa (lsa); |
508e53e2 | 602 | |
603 | /* schedule maxage remover */ | |
604 | ospf6_maxage_remove (ospf6); | |
718e3744 | 605 | |
606 | return 0; | |
607 | } | |
608 | ||
609 | int | |
610 | ospf6_lsa_refresh (struct thread *thread) | |
611 | { | |
6452df09 | 612 | struct ospf6_lsa *old, *self, *new; |
613 | struct ospf6_lsdb *lsdb_self; | |
718e3744 | 614 | |
615 | assert (thread); | |
6452df09 | 616 | old = (struct ospf6_lsa *) THREAD_ARG (thread); |
617 | assert (old && old->header); | |
718e3744 | 618 | |
6452df09 | 619 | old->refresh = (struct thread *) NULL; |
620 | ||
621 | lsdb_self = ospf6_get_scoped_lsdb_self (old); | |
622 | self = ospf6_lsdb_lookup (old->header->type, old->header->id, | |
623 | old->header->adv_router, lsdb_self); | |
624 | if (self == NULL) | |
625 | { | |
1e05838a | 626 | if (IS_OSPF6_DEBUG_LSA_TYPE (old->header->type)) |
c6487d61 | 627 | zlog_debug ("Refresh: could not find self LSA, flush %s", old->name); |
6452df09 | 628 | ospf6_lsa_premature_aging (old); |
629 | return 0; | |
630 | } | |
631 | ||
632 | /* Reset age, increment LS sequence number. */ | |
633 | self->header->age = htons (0); | |
634 | self->header->seqnum = | |
635 | ospf6_new_ls_seqnum (self->header->type, self->header->id, | |
636 | self->header->adv_router, old->lsdb); | |
637 | ospf6_lsa_checksum (self->header); | |
638 | ||
639 | new = ospf6_lsa_create (self->header); | |
640 | new->lsdb = old->lsdb; | |
641 | new->refresh = thread_add_timer (master, ospf6_lsa_refresh, new, | |
642 | LS_REFRESH_TIME); | |
718e3744 | 643 | |
6452df09 | 644 | /* store it in the LSDB for self-originated LSAs */ |
645 | ospf6_lsdb_add (ospf6_lsa_copy (new), lsdb_self); | |
718e3744 | 646 | |
1e05838a | 647 | if (IS_OSPF6_DEBUG_LSA_TYPE (new->header->type)) |
718e3744 | 648 | { |
c6487d61 | 649 | zlog_debug ("LSA Refresh:"); |
6452df09 | 650 | ospf6_lsa_header_print (new); |
718e3744 | 651 | } |
652 | ||
6452df09 | 653 | ospf6_flood_clear (old); |
654 | ospf6_flood (NULL, new); | |
655 | ospf6_install_lsa (new); | |
656 | ||
508e53e2 | 657 | return 0; |
718e3744 | 658 | } |
659 | ||
660 | \f | |
661 | ||
662 | /* enhanced Fletcher checksum algorithm, RFC1008 7.2 */ | |
663 | #define MODX 4102 | |
664 | #define LSA_CHECKSUM_OFFSET 15 | |
665 | ||
666 | unsigned short | |
667 | ospf6_lsa_checksum (struct ospf6_lsa_header *lsa_header) | |
668 | { | |
669 | u_char *sp, *ep, *p, *q; | |
670 | int c0 = 0, c1 = 0; | |
671 | int x, y; | |
672 | u_int16_t length; | |
673 | ||
674 | lsa_header->checksum = 0; | |
675 | length = ntohs (lsa_header->length) - 2; | |
03d52f8d | 676 | sp = (u_char *) &lsa_header->type; |
718e3744 | 677 | |
678 | for (ep = sp + length; sp < ep; sp = q) | |
679 | { | |
680 | q = sp + MODX; | |
681 | if (q > ep) | |
682 | q = ep; | |
683 | for (p = sp; p < q; p++) | |
684 | { | |
685 | c0 += *p; | |
686 | c1 += c0; | |
687 | } | |
688 | c0 %= 255; | |
689 | c1 %= 255; | |
690 | } | |
691 | ||
692 | /* r = (c1 << 8) + c0; */ | |
693 | x = ((length - LSA_CHECKSUM_OFFSET) * c0 - c1) % 255; | |
694 | if (x <= 0) | |
695 | x += 255; | |
696 | y = 510 - c0 - x; | |
697 | if (y > 255) | |
698 | y -= 255; | |
699 | ||
700 | lsa_header->checksum = htons ((x << 8) + y); | |
701 | ||
702 | return (lsa_header->checksum); | |
703 | } | |
704 | ||
6452df09 | 705 | void |
6ac29a51 | 706 | ospf6_lsa_init (void) |
6452df09 | 707 | { |
1e05838a | 708 | ospf6_lsa_handler_vector = vector_init (0); |
6452df09 | 709 | ospf6_install_lsa_handler (&unknown_handler); |
718e3744 | 710 | } |
711 | ||
712 | \f | |
6ac29a51 | 713 | static char * |
1e05838a | 714 | ospf6_lsa_handler_name (struct ospf6_lsa_handler *h) |
715 | { | |
716 | static char buf[64]; | |
0c083ee9 | 717 | unsigned int i; |
718 | unsigned int size = strlen (h->name); | |
1e05838a | 719 | |
c32d28b7 | 720 | if (!strcmp(h->name, "Unknown") && |
1e05838a | 721 | h->type != OSPF6_LSTYPE_UNKNOWN) |
722 | { | |
723 | snprintf (buf, sizeof (buf), "%#04hx", h->type); | |
724 | return buf; | |
725 | } | |
726 | ||
727 | for (i = 0; i < MIN (size, sizeof (buf)); i++) | |
728 | { | |
729 | if (! islower (h->name[i])) | |
730 | buf[i] = tolower (h->name[i]); | |
731 | else | |
732 | buf[i] = h->name[i]; | |
733 | } | |
734 | buf[size] = '\0'; | |
735 | return buf; | |
736 | } | |
718e3744 | 737 | |
1e05838a | 738 | DEFUN (debug_ospf6_lsa_type, |
739 | debug_ospf6_lsa_hex_cmd, | |
740 | "debug ospf6 lsa XXXX/0xXXXX", | |
508e53e2 | 741 | DEBUG_STR |
742 | OSPF6_STR | |
743 | "Debug Link State Advertisements (LSAs)\n" | |
1e05838a | 744 | "Specify LS type as Hexadecimal\n" |
508e53e2 | 745 | ) |
746 | { | |
0c083ee9 | 747 | unsigned int i; |
1e05838a | 748 | struct ospf6_lsa_handler *handler = NULL; |
749 | unsigned long val; | |
750 | char *endptr = NULL; | |
751 | u_int16_t type = 0; | |
752 | ||
753 | assert (argc); | |
508e53e2 | 754 | |
1e05838a | 755 | if ((strlen (argv[0]) == 6 && ! strncmp (argv[0], "0x", 2)) || |
756 | (strlen (argv[0]) == 4)) | |
508e53e2 | 757 | { |
1e05838a | 758 | val = strtoul (argv[0], &endptr, 16); |
759 | if (*endptr == '\0') | |
760 | type = val; | |
718e3744 | 761 | } |
1e05838a | 762 | |
55468c86 | 763 | for (i = 0; i < vector_active (ospf6_lsa_handler_vector); i++) |
718e3744 | 764 | { |
1e05838a | 765 | handler = vector_slot (ospf6_lsa_handler_vector, i); |
766 | if (handler == NULL) | |
767 | continue; | |
768 | if (type && handler->type == type) | |
769 | break; | |
770 | if (! strcasecmp (argv[0], handler->name)) | |
771 | break; | |
772 | handler = NULL; | |
508e53e2 | 773 | } |
774 | ||
1e05838a | 775 | if (type && handler == NULL) |
776 | { | |
777 | handler = (struct ospf6_lsa_handler *) | |
778 | malloc (sizeof (struct ospf6_lsa_handler)); | |
779 | memset (handler, 0, sizeof (struct ospf6_lsa_handler)); | |
780 | handler->type = type; | |
781 | handler->name = "Unknown"; | |
782 | handler->show = ospf6_unknown_lsa_show; | |
783 | vector_set_index (ospf6_lsa_handler_vector, | |
784 | handler->type & OSPF6_LSTYPE_FCODE_MASK, handler); | |
785 | } | |
786 | ||
787 | if (handler == NULL) | |
788 | handler = &unknown_handler; | |
789 | ||
790 | if (argc >= 2) | |
791 | { | |
792 | if (! strcmp (argv[1], "originate")) | |
793 | SET_FLAG (handler->debug, OSPF6_LSA_DEBUG_ORIGINATE); | |
794 | if (! strcmp (argv[1], "examin")) | |
795 | SET_FLAG (handler->debug, OSPF6_LSA_DEBUG_EXAMIN); | |
796 | if (! strcmp (argv[1], "flooding")) | |
797 | SET_FLAG (handler->debug, OSPF6_LSA_DEBUG_FLOOD); | |
798 | } | |
799 | else | |
800 | SET_FLAG (handler->debug, OSPF6_LSA_DEBUG); | |
801 | ||
508e53e2 | 802 | return CMD_SUCCESS; |
803 | } | |
804 | ||
1e05838a | 805 | DEFUN (no_debug_ospf6_lsa_type, |
806 | no_debug_ospf6_lsa_hex_cmd, | |
807 | "no debug ospf6 lsa XXXX/0xXXXX", | |
508e53e2 | 808 | NO_STR |
809 | DEBUG_STR | |
810 | OSPF6_STR | |
811 | "Debug Link State Advertisements (LSAs)\n" | |
1e05838a | 812 | "Specify LS type as Hexadecimal\n" |
508e53e2 | 813 | ) |
814 | { | |
0c083ee9 | 815 | u_int i; |
1e05838a | 816 | struct ospf6_lsa_handler *handler = NULL; |
817 | unsigned long val; | |
818 | char *endptr = NULL; | |
819 | u_int16_t type = 0; | |
508e53e2 | 820 | |
1e05838a | 821 | assert (argc); |
822 | ||
823 | if ((strlen (argv[0]) == 6 && ! strncmp (argv[0], "0x", 2)) || | |
824 | (strlen (argv[0]) == 4)) | |
508e53e2 | 825 | { |
1e05838a | 826 | val = strtoul (argv[0], &endptr, 16); |
827 | if (*endptr == '\0') | |
828 | type = val; | |
829 | } | |
830 | ||
55468c86 | 831 | for (i = 0; i < vector_active (ospf6_lsa_handler_vector); i++) |
1e05838a | 832 | { |
833 | handler = vector_slot (ospf6_lsa_handler_vector, i); | |
834 | if (handler == NULL) | |
835 | continue; | |
836 | if (type && handler->type == type) | |
837 | break; | |
838 | if (! strcasecmp (argv[0], handler->name)) | |
839 | break; | |
840 | } | |
841 | ||
842 | if (handler == NULL) | |
843 | return CMD_SUCCESS; | |
844 | ||
845 | if (argc >= 2) | |
846 | { | |
847 | if (! strcmp (argv[1], "originate")) | |
848 | UNSET_FLAG (handler->debug, OSPF6_LSA_DEBUG_ORIGINATE); | |
849 | if (! strcmp (argv[1], "examin")) | |
850 | UNSET_FLAG (handler->debug, OSPF6_LSA_DEBUG_EXAMIN); | |
851 | if (! strcmp (argv[1], "flooding")) | |
852 | UNSET_FLAG (handler->debug, OSPF6_LSA_DEBUG_FLOOD); | |
718e3744 | 853 | } |
718e3744 | 854 | else |
1e05838a | 855 | UNSET_FLAG (handler->debug, OSPF6_LSA_DEBUG); |
856 | ||
857 | if (handler->debug == 0 && | |
e733f949 | 858 | !strcmp(handler->name, "Unknown") && type != OSPF6_LSTYPE_UNKNOWN) |
718e3744 | 859 | { |
1e05838a | 860 | free (handler); |
861 | vector_slot (ospf6_lsa_handler_vector, i) = NULL; | |
718e3744 | 862 | } |
718e3744 | 863 | |
508e53e2 | 864 | return CMD_SUCCESS; |
718e3744 | 865 | } |
866 | ||
1e05838a | 867 | struct cmd_element debug_ospf6_lsa_type_cmd; |
868 | struct cmd_element debug_ospf6_lsa_type_detail_cmd; | |
869 | struct cmd_element no_debug_ospf6_lsa_type_cmd; | |
870 | struct cmd_element no_debug_ospf6_lsa_type_detail_cmd; | |
718e3744 | 871 | |
1e05838a | 872 | void |
6ac29a51 | 873 | install_element_ospf6_debug_lsa (void) |
718e3744 | 874 | { |
0c083ee9 | 875 | u_int i; |
1e05838a | 876 | struct ospf6_lsa_handler *handler; |
877 | #define STRSIZE 256 | |
878 | #define DOCSIZE 1024 | |
879 | static char strbuf[STRSIZE]; | |
880 | static char docbuf[DOCSIZE]; | |
881 | static char detail_strbuf[STRSIZE]; | |
882 | static char detail_docbuf[DOCSIZE]; | |
883 | char *str, *no_str; | |
884 | char *doc, *no_doc; | |
885 | ||
886 | strbuf[0] = '\0'; | |
887 | no_str = &strbuf[strlen (strbuf)]; | |
888 | strncat (strbuf, "no ", STRSIZE - strlen (strbuf)); | |
889 | str = &strbuf[strlen (strbuf)]; | |
890 | ||
891 | strncat (strbuf, "debug ospf6 lsa (", STRSIZE - strlen (strbuf)); | |
55468c86 | 892 | for (i = 0; i < vector_active (ospf6_lsa_handler_vector); i++) |
718e3744 | 893 | { |
1e05838a | 894 | handler = vector_slot (ospf6_lsa_handler_vector, i); |
895 | if (handler == NULL) | |
896 | continue; | |
897 | strncat (strbuf, ospf6_lsa_handler_name (handler), | |
898 | STRSIZE - strlen (strbuf)); | |
899 | strncat (strbuf, "|", STRSIZE - strlen (strbuf)); | |
718e3744 | 900 | } |
1e05838a | 901 | strbuf[strlen (strbuf) - 1] = ')'; |
902 | strbuf[strlen (strbuf)] = '\0'; | |
718e3744 | 903 | |
1e05838a | 904 | docbuf[0] = '\0'; |
905 | no_doc = &docbuf[strlen (docbuf)]; | |
906 | strncat (docbuf, NO_STR, DOCSIZE - strlen (docbuf)); | |
907 | doc = &docbuf[strlen (docbuf)]; | |
908 | ||
909 | strncat (docbuf, DEBUG_STR, DOCSIZE - strlen (docbuf)); | |
910 | strncat (docbuf, OSPF6_STR, DOCSIZE - strlen (docbuf)); | |
911 | strncat (docbuf, "Debug Link State Advertisements (LSAs)\n", | |
912 | DOCSIZE - strlen (docbuf)); | |
913 | ||
55468c86 | 914 | for (i = 0; i < vector_active (ospf6_lsa_handler_vector); i++) |
1e05838a | 915 | { |
916 | handler = vector_slot (ospf6_lsa_handler_vector, i); | |
917 | if (handler == NULL) | |
918 | continue; | |
919 | strncat (docbuf, "Debug ", DOCSIZE - strlen (docbuf)); | |
920 | strncat (docbuf, handler->name, DOCSIZE - strlen (docbuf)); | |
921 | strncat (docbuf, "-LSA\n", DOCSIZE - strlen (docbuf)); | |
922 | } | |
923 | docbuf[strlen (docbuf)] = '\0'; | |
924 | ||
925 | debug_ospf6_lsa_type_cmd.string = str; | |
926 | debug_ospf6_lsa_type_cmd.func = debug_ospf6_lsa_type; | |
927 | debug_ospf6_lsa_type_cmd.doc = doc; | |
928 | ||
929 | no_debug_ospf6_lsa_type_cmd.string = no_str; | |
930 | no_debug_ospf6_lsa_type_cmd.func = no_debug_ospf6_lsa_type; | |
931 | no_debug_ospf6_lsa_type_cmd.doc = no_doc; | |
932 | ||
933 | strncpy (detail_strbuf, strbuf, STRSIZE); | |
934 | strncat (detail_strbuf, " (originate|examin|flooding)", | |
935 | STRSIZE - strlen (detail_strbuf)); | |
936 | detail_strbuf[strlen (detail_strbuf)] = '\0'; | |
937 | no_str = &detail_strbuf[0]; | |
938 | str = &detail_strbuf[strlen ("no ")]; | |
939 | ||
940 | strncpy (detail_docbuf, docbuf, DOCSIZE); | |
941 | strncat (detail_docbuf, "Debug Originating LSA\n", | |
942 | DOCSIZE - strlen (detail_docbuf)); | |
943 | strncat (detail_docbuf, "Debug Examining LSA\n", | |
944 | DOCSIZE - strlen (detail_docbuf)); | |
945 | strncat (detail_docbuf, "Debug Flooding LSA\n", | |
946 | DOCSIZE - strlen (detail_docbuf)); | |
947 | detail_docbuf[strlen (detail_docbuf)] = '\0'; | |
948 | no_doc = &detail_docbuf[0]; | |
949 | doc = &detail_docbuf[strlen (NO_STR)]; | |
950 | ||
951 | debug_ospf6_lsa_type_detail_cmd.string = str; | |
952 | debug_ospf6_lsa_type_detail_cmd.func = debug_ospf6_lsa_type; | |
953 | debug_ospf6_lsa_type_detail_cmd.doc = doc; | |
954 | ||
955 | no_debug_ospf6_lsa_type_detail_cmd.string = no_str; | |
956 | no_debug_ospf6_lsa_type_detail_cmd.func = no_debug_ospf6_lsa_type; | |
957 | no_debug_ospf6_lsa_type_detail_cmd.doc = no_doc; | |
958 | ||
959 | install_element (ENABLE_NODE, &debug_ospf6_lsa_hex_cmd); | |
960 | install_element (ENABLE_NODE, &debug_ospf6_lsa_type_cmd); | |
961 | install_element (ENABLE_NODE, &debug_ospf6_lsa_type_detail_cmd); | |
962 | install_element (ENABLE_NODE, &no_debug_ospf6_lsa_hex_cmd); | |
963 | install_element (ENABLE_NODE, &no_debug_ospf6_lsa_type_cmd); | |
964 | install_element (ENABLE_NODE, &no_debug_ospf6_lsa_type_detail_cmd); | |
965 | install_element (CONFIG_NODE, &debug_ospf6_lsa_hex_cmd); | |
966 | install_element (CONFIG_NODE, &debug_ospf6_lsa_type_cmd); | |
967 | install_element (CONFIG_NODE, &debug_ospf6_lsa_type_detail_cmd); | |
968 | install_element (CONFIG_NODE, &no_debug_ospf6_lsa_hex_cmd); | |
969 | install_element (CONFIG_NODE, &no_debug_ospf6_lsa_type_cmd); | |
970 | install_element (CONFIG_NODE, &no_debug_ospf6_lsa_type_detail_cmd); | |
718e3744 | 971 | } |
972 | ||
1e05838a | 973 | int |
974 | config_write_ospf6_debug_lsa (struct vty *vty) | |
718e3744 | 975 | { |
0c083ee9 | 976 | u_int i; |
1e05838a | 977 | struct ospf6_lsa_handler *handler; |
978 | ||
55468c86 | 979 | for (i = 0; i < vector_active (ospf6_lsa_handler_vector); i++) |
1e05838a | 980 | { |
981 | handler = vector_slot (ospf6_lsa_handler_vector, i); | |
982 | if (handler == NULL) | |
983 | continue; | |
984 | if (CHECK_FLAG (handler->debug, OSPF6_LSA_DEBUG)) | |
985 | vty_out (vty, "debug ospf6 lsa %s%s", | |
986 | ospf6_lsa_handler_name (handler), VNL); | |
987 | if (CHECK_FLAG (handler->debug, OSPF6_LSA_DEBUG_ORIGINATE)) | |
988 | vty_out (vty, "debug ospf6 lsa %s originate%s", | |
989 | ospf6_lsa_handler_name (handler), VNL); | |
990 | if (CHECK_FLAG (handler->debug, OSPF6_LSA_DEBUG_EXAMIN)) | |
991 | vty_out (vty, "debug ospf6 lsa %s examin%s", | |
992 | ospf6_lsa_handler_name (handler), VNL); | |
993 | if (CHECK_FLAG (handler->debug, OSPF6_LSA_DEBUG_FLOOD)) | |
994 | vty_out (vty, "debug ospf6 lsa %s flooding%s", | |
995 | ospf6_lsa_handler_name (handler), VNL); | |
996 | } | |
997 | ||
998 | return 0; | |
718e3744 | 999 | } |
1000 | ||
718e3744 | 1001 |