]> git.proxmox.com Git - mirror_frr.git/blame - ospf6d/ospf6_message.c
Merge pull request #8170 from mjstapp/fix_sa_pim
[mirror_frr.git] / ospf6d / ospf6_message.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 *
896014f4
DL
16 * You should have received a copy of the GNU General Public License along
17 * with this program; see the file COPYING; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
718e3744 19 */
20
508e53e2 21#include <zebra.h>
22
3b4cd3a9 23#include "memory.h"
508e53e2 24#include "log.h"
25#include "vty.h"
26#include "command.h"
27#include "thread.h"
28#include "linklist.h"
4ba03be5 29#include "lib_errors.h"
508e53e2 30
508e53e2 31#include "ospf6_proto.h"
32#include "ospf6_lsa.h"
33#include "ospf6_lsdb.h"
c527acf1 34#include "ospf6_top.h"
508e53e2 35#include "ospf6_network.h"
36#include "ospf6_message.h"
718e3744 37
508e53e2 38#include "ospf6_area.h"
39#include "ospf6_neighbor.h"
40#include "ospf6_interface.h"
718e3744 41
abc7ef44
DO
42/* for structures and macros ospf6_lsa_examin() needs */
43#include "ospf6_abr.h"
44#include "ospf6_asbr.h"
45#include "ospf6_intra.h"
46
508e53e2 47#include "ospf6_flood.h"
049207c3 48#include "ospf6d.h"
718e3744 49
681b84e8
DT
50#include <netinet/ip6.h>
51
508e53e2 52unsigned char conf_debug_ospf6_message[6] = {0x03, 0, 0, 0, 0, 0};
d62a17ae 53static const struct message ospf6_message_type_str[] = {
54 {OSPF6_MESSAGE_TYPE_HELLO, "Hello"},
55 {OSPF6_MESSAGE_TYPE_DBDESC, "DbDesc"},
56 {OSPF6_MESSAGE_TYPE_LSREQ, "LSReq"},
57 {OSPF6_MESSAGE_TYPE_LSUPDATE, "LSUpdate"},
58 {OSPF6_MESSAGE_TYPE_LSACK, "LSAck"},
59 {0}};
718e3744 60
abc7ef44
DO
61/* Minimum (besides the standard OSPF packet header) lengths for OSPF
62 packets of particular types, offset is the "type" field. */
d7c0a89a 63const uint16_t ospf6_packet_minlen[OSPF6_MESSAGE_TYPE_ALL] = {
d62a17ae 64 0,
65 OSPF6_HELLO_MIN_SIZE,
66 OSPF6_DB_DESC_MIN_SIZE,
67 OSPF6_LS_REQ_MIN_SIZE,
68 OSPF6_LS_UPD_MIN_SIZE,
69 OSPF6_LS_ACK_MIN_SIZE};
abc7ef44
DO
70
71/* Minimum (besides the standard LSA header) lengths for LSAs of particular
72 types, offset is the "LSA function code" portion of "LSA type" field. */
d7c0a89a 73const uint16_t ospf6_lsa_minlen[OSPF6_LSTYPE_SIZE] = {
d62a17ae 74 0,
75 /* 0x2001 */ OSPF6_ROUTER_LSA_MIN_SIZE,
76 /* 0x2002 */ OSPF6_NETWORK_LSA_MIN_SIZE,
77 /* 0x2003 */ OSPF6_INTER_PREFIX_LSA_MIN_SIZE,
78 /* 0x2004 */ OSPF6_INTER_ROUTER_LSA_FIX_SIZE,
79 /* 0x4005 */ OSPF6_AS_EXTERNAL_LSA_MIN_SIZE,
80 /* 0x2006 */ 0,
81 /* 0x2007 */ OSPF6_AS_EXTERNAL_LSA_MIN_SIZE,
82 /* 0x0008 */ OSPF6_LINK_LSA_MIN_SIZE,
83 /* 0x2009 */ OSPF6_INTRA_PREFIX_LSA_MIN_SIZE};
abc7ef44 84
508e53e2 85/* print functions */
718e3744 86
d62a17ae 87static void ospf6_header_print(struct ospf6_header *oh)
718e3744 88{
d62a17ae 89 char router_id[16], area_id[16];
90 inet_ntop(AF_INET, &oh->router_id, router_id, sizeof(router_id));
91 inet_ntop(AF_INET, &oh->area_id, area_id, sizeof(area_id));
92
93 zlog_debug(" OSPFv%d Type:%d Len:%hu Router-ID:%s", oh->version,
94 oh->type, ntohs(oh->length), router_id);
95 zlog_debug(" Area-ID:%s Cksum:%hx Instance-ID:%d", area_id,
96 ntohs(oh->checksum), oh->instance_id);
718e3744 97}
98
d62a17ae 99void ospf6_hello_print(struct ospf6_header *oh)
718e3744 100{
d62a17ae 101 struct ospf6_hello *hello;
102 char options[16];
103 char drouter[16], bdrouter[16], neighbor[16];
104 char *p;
105
106 ospf6_header_print(oh);
107 assert(oh->type == OSPF6_MESSAGE_TYPE_HELLO);
108
109 hello = (struct ospf6_hello *)((caddr_t)oh
110 + sizeof(struct ospf6_header));
111
112 inet_ntop(AF_INET, &hello->drouter, drouter, sizeof(drouter));
113 inet_ntop(AF_INET, &hello->bdrouter, bdrouter, sizeof(bdrouter));
114 ospf6_options_printbuf(hello->options, options, sizeof(options));
115
116 zlog_debug(" I/F-Id:%ld Priority:%d Option:%s",
d7c0a89a 117 (unsigned long)ntohl(hello->interface_id), hello->priority,
d62a17ae 118 options);
119 zlog_debug(" HelloInterval:%hu DeadInterval:%hu",
120 ntohs(hello->hello_interval), ntohs(hello->dead_interval));
121 zlog_debug(" DR:%s BDR:%s", drouter, bdrouter);
122
123 for (p = (char *)((caddr_t)hello + sizeof(struct ospf6_hello));
d7c0a89a
QY
124 p + sizeof(uint32_t) <= OSPF6_MESSAGE_END(oh);
125 p += sizeof(uint32_t)) {
d62a17ae 126 inet_ntop(AF_INET, (void *)p, neighbor, sizeof(neighbor));
127 zlog_debug(" Neighbor: %s", neighbor);
128 }
129
130 assert(p == OSPF6_MESSAGE_END(oh));
718e3744 131}
132
d62a17ae 133void ospf6_dbdesc_print(struct ospf6_header *oh)
718e3744 134{
d62a17ae 135 struct ospf6_dbdesc *dbdesc;
136 char options[16];
137 char *p;
508e53e2 138
d62a17ae 139 ospf6_header_print(oh);
140 assert(oh->type == OSPF6_MESSAGE_TYPE_DBDESC);
508e53e2 141
d62a17ae 142 dbdesc = (struct ospf6_dbdesc *)((caddr_t)oh
143 + sizeof(struct ospf6_header));
508e53e2 144
d62a17ae 145 ospf6_options_printbuf(dbdesc->options, options, sizeof(options));
508e53e2 146
d62a17ae 147 zlog_debug(" MBZ: %#x Option: %s IfMTU: %hu", dbdesc->reserved1,
148 options, ntohs(dbdesc->ifmtu));
149 zlog_debug(" MBZ: %#x Bits: %s%s%s SeqNum: %#lx", dbdesc->reserved2,
150 (CHECK_FLAG(dbdesc->bits, OSPF6_DBDESC_IBIT) ? "I" : "-"),
151 (CHECK_FLAG(dbdesc->bits, OSPF6_DBDESC_MBIT) ? "M" : "-"),
152 (CHECK_FLAG(dbdesc->bits, OSPF6_DBDESC_MSBIT) ? "m" : "s"),
d7c0a89a 153 (unsigned long)ntohl(dbdesc->seqnum));
508e53e2 154
d62a17ae 155 for (p = (char *)((caddr_t)dbdesc + sizeof(struct ospf6_dbdesc));
156 p + sizeof(struct ospf6_lsa_header) <= OSPF6_MESSAGE_END(oh);
157 p += sizeof(struct ospf6_lsa_header))
158 ospf6_lsa_header_print_raw((struct ospf6_lsa_header *)p);
508e53e2 159
d62a17ae 160 assert(p == OSPF6_MESSAGE_END(oh));
718e3744 161}
162
d62a17ae 163void ospf6_lsreq_print(struct ospf6_header *oh)
718e3744 164{
d62a17ae 165 char id[16], adv_router[16];
166 char *p;
167
168 ospf6_header_print(oh);
169 assert(oh->type == OSPF6_MESSAGE_TYPE_LSREQ);
170
171 for (p = (char *)((caddr_t)oh + sizeof(struct ospf6_header));
172 p + sizeof(struct ospf6_lsreq_entry) <= OSPF6_MESSAGE_END(oh);
173 p += sizeof(struct ospf6_lsreq_entry)) {
174 struct ospf6_lsreq_entry *e = (struct ospf6_lsreq_entry *)p;
175 inet_ntop(AF_INET, &e->adv_router, adv_router,
176 sizeof(adv_router));
177 inet_ntop(AF_INET, &e->id, id, sizeof(id));
178 zlog_debug(" [%s Id:%s Adv:%s]", ospf6_lstype_name(e->type),
179 id, adv_router);
180 }
181
182 assert(p == OSPF6_MESSAGE_END(oh));
718e3744 183}
184
d62a17ae 185void ospf6_lsupdate_print(struct ospf6_header *oh)
718e3744 186{
d62a17ae 187 struct ospf6_lsupdate *lsupdate;
d7c0a89a 188 unsigned long num;
d62a17ae 189 char *p;
718e3744 190
d62a17ae 191 ospf6_header_print(oh);
192 assert(oh->type == OSPF6_MESSAGE_TYPE_LSUPDATE);
718e3744 193
d62a17ae 194 lsupdate = (struct ospf6_lsupdate *)((caddr_t)oh
195 + sizeof(struct ospf6_header));
718e3744 196
d62a17ae 197 num = ntohl(lsupdate->lsa_number);
198 zlog_debug(" Number of LSA: %ld", num);
718e3744 199
d62a17ae 200 for (p = (char *)((caddr_t)lsupdate + sizeof(struct ospf6_lsupdate));
201 p < OSPF6_MESSAGE_END(oh)
202 && p + OSPF6_LSA_SIZE(p) <= OSPF6_MESSAGE_END(oh);
203 p += OSPF6_LSA_SIZE(p)) {
204 ospf6_lsa_header_print_raw((struct ospf6_lsa_header *)p);
205 }
718e3744 206
d62a17ae 207 assert(p == OSPF6_MESSAGE_END(oh));
718e3744 208}
209
d62a17ae 210void ospf6_lsack_print(struct ospf6_header *oh)
718e3744 211{
d62a17ae 212 char *p;
718e3744 213
d62a17ae 214 ospf6_header_print(oh);
215 assert(oh->type == OSPF6_MESSAGE_TYPE_LSACK);
718e3744 216
d62a17ae 217 for (p = (char *)((caddr_t)oh + sizeof(struct ospf6_header));
218 p + sizeof(struct ospf6_lsa_header) <= OSPF6_MESSAGE_END(oh);
219 p += sizeof(struct ospf6_lsa_header))
220 ospf6_lsa_header_print_raw((struct ospf6_lsa_header *)p);
508e53e2 221
d62a17ae 222 assert(p == OSPF6_MESSAGE_END(oh));
718e3744 223}
224
d62a17ae 225static void ospf6_hello_recv(struct in6_addr *src, struct in6_addr *dst,
226 struct ospf6_interface *oi,
227 struct ospf6_header *oh)
718e3744 228{
d62a17ae 229 struct ospf6_hello *hello;
230 struct ospf6_neighbor *on;
231 char *p;
232 int twoway = 0;
233 int neighborchange = 0;
234 int neighbor_ifindex_change = 0;
235 int backupseen = 0;
236
237 hello = (struct ospf6_hello *)((caddr_t)oh
238 + sizeof(struct ospf6_header));
239
240 /* HelloInterval check */
241 if (ntohs(hello->hello_interval) != oi->hello_interval) {
ff99e5b6 242 zlog_warn(
243 "VRF %s: I/F %s HelloInterval mismatch: (my %d, rcvd %d)",
244 vrf_id_to_name(oi->interface->vrf_id),
245 oi->interface->name, oi->hello_interval,
246 ntohs(hello->hello_interval));
d62a17ae 247 return;
248 }
249
250 /* RouterDeadInterval check */
251 if (ntohs(hello->dead_interval) != oi->dead_interval) {
ff99e5b6 252 zlog_warn(
253 "VRF %s: I/F %s DeadInterval mismatch: (my %d, rcvd %d)",
254 vrf_id_to_name(oi->interface->vrf_id),
255 oi->interface->name, oi->dead_interval,
256 ntohs(hello->dead_interval));
d62a17ae 257 return;
258 }
259
260 /* E-bit check */
261 if (OSPF6_OPT_ISSET(hello->options, OSPF6_OPT_E)
262 != OSPF6_OPT_ISSET(oi->area->options, OSPF6_OPT_E)) {
ff99e5b6 263 zlog_warn("VRF %s: IF %s E-bit mismatch",
264 vrf_id_to_name(oi->interface->vrf_id),
265 oi->interface->name);
d62a17ae 266 return;
267 }
268
269 /* Find neighbor, create if not exist */
270 on = ospf6_neighbor_lookup(oh->router_id, oi);
271 if (on == NULL) {
272 on = ospf6_neighbor_create(oh->router_id, oi);
273 on->prev_drouter = on->drouter = hello->drouter;
274 on->prev_bdrouter = on->bdrouter = hello->bdrouter;
275 on->priority = hello->priority;
276 }
277
278 /* Always override neighbor's source address */
279 memcpy(&on->linklocal_addr, src, sizeof(struct in6_addr));
280
281 /* Neighbor ifindex check */
282 if (on->ifindex != (ifindex_t)ntohl(hello->interface_id)) {
283 on->ifindex = ntohl(hello->interface_id);
284 neighbor_ifindex_change++;
285 }
286
287 /* TwoWay check */
288 for (p = (char *)((caddr_t)hello + sizeof(struct ospf6_hello));
d7c0a89a
QY
289 p + sizeof(uint32_t) <= OSPF6_MESSAGE_END(oh);
290 p += sizeof(uint32_t)) {
291 uint32_t *router_id = (uint32_t *)p;
d62a17ae 292
293 if (*router_id == oi->area->ospf6->router_id)
294 twoway++;
295 }
296
297 assert(p == OSPF6_MESSAGE_END(oh));
298
299 /* RouterPriority check */
300 if (on->priority != hello->priority) {
301 on->priority = hello->priority;
302 neighborchange++;
303 }
304
305 /* DR check */
306 if (on->drouter != hello->drouter) {
307 on->prev_drouter = on->drouter;
308 on->drouter = hello->drouter;
309 if (on->prev_drouter == on->router_id
310 || on->drouter == on->router_id)
311 neighborchange++;
312 }
313
314 /* BDR check */
315 if (on->bdrouter != hello->bdrouter) {
316 on->prev_bdrouter = on->bdrouter;
317 on->bdrouter = hello->bdrouter;
318 if (on->prev_bdrouter == on->router_id
319 || on->bdrouter == on->router_id)
320 neighborchange++;
321 }
322
323 /* BackupSeen check */
324 if (oi->state == OSPF6_INTERFACE_WAITING) {
325 if (hello->bdrouter == on->router_id)
326 backupseen++;
327 else if (hello->drouter == on->router_id
328 && hello->bdrouter == htonl(0))
329 backupseen++;
330 }
331
43855e3d
CS
332 oi->hello_in++;
333
d62a17ae 334 /* Execute neighbor events */
335 thread_execute(master, hello_received, on, 0);
336 if (twoway)
337 thread_execute(master, twoway_received, on, 0);
338 else
339 thread_execute(master, oneway_received, on, 0);
340
341 /* Schedule interface events */
342 if (backupseen)
343 thread_add_event(master, backup_seen, oi, 0, NULL);
344 if (neighborchange)
345 thread_add_event(master, neighbor_change, oi, 0, NULL);
346
347 if (neighbor_ifindex_change && on->state == OSPF6_NEIGHBOR_FULL)
348 OSPF6_ROUTER_LSA_SCHEDULE(oi->area);
718e3744 349}
350
d62a17ae 351static void ospf6_dbdesc_recv_master(struct ospf6_header *oh,
352 struct ospf6_neighbor *on)
718e3744 353{
d62a17ae 354 struct ospf6_dbdesc *dbdesc;
355 char *p;
356
357 dbdesc = (struct ospf6_dbdesc *)((caddr_t)oh
358 + sizeof(struct ospf6_header));
359
360 if (on->state < OSPF6_NEIGHBOR_INIT) {
361 if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV))
362 zlog_debug("Neighbor state less than Init, ignore");
363 return;
364 }
365
366 switch (on->state) {
367 case OSPF6_NEIGHBOR_TWOWAY:
368 if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV))
369 zlog_debug("Neighbor state is 2-Way, ignore");
370 return;
371
372 case OSPF6_NEIGHBOR_INIT:
373 thread_execute(master, twoway_received, on, 0);
374 if (on->state != OSPF6_NEIGHBOR_EXSTART) {
375 if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV))
376 zlog_debug(
377 "Neighbor state is not ExStart, ignore");
378 return;
379 }
380 /* else fall through to ExStart */
381 /* fallthru */
382 case OSPF6_NEIGHBOR_EXSTART:
383 /* if neighbor obeys us as our slave, schedule negotiation_done
384 and process LSA Headers. Otherwise, ignore this message */
385 if (!CHECK_FLAG(dbdesc->bits, OSPF6_DBDESC_MSBIT)
386 && !CHECK_FLAG(dbdesc->bits, OSPF6_DBDESC_IBIT)
387 && ntohl(dbdesc->seqnum) == on->dbdesc_seqnum) {
388 /* execute NegotiationDone */
389 thread_execute(master, negotiation_done, on, 0);
390
391 /* Record neighbor options */
392 memcpy(on->options, dbdesc->options,
393 sizeof(on->options));
394 } else {
ff99e5b6 395 zlog_warn(
396 "VRF %s: Nbr %s: Negotiation failed",
397 vrf_id_to_name(on->ospf6_if->interface->vrf_id),
398 on->name);
d62a17ae 399 return;
400 }
401 /* fall through to exchange */
402
403 case OSPF6_NEIGHBOR_EXCHANGE:
404 if (!memcmp(dbdesc, &on->dbdesc_last,
405 sizeof(struct ospf6_dbdesc))) {
406 /* Duplicated DatabaseDescription is dropped by master
407 */
408 if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV))
409 zlog_debug(
410 "Duplicated dbdesc discarded by Master, ignore");
411 return;
412 }
413
414 if (CHECK_FLAG(dbdesc->bits, OSPF6_DBDESC_MSBIT)) {
415 if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV))
416 zlog_debug("Master/Slave bit mismatch");
417 thread_add_event(master, seqnumber_mismatch, on, 0,
418 NULL);
419 return;
420 }
421
422 if (CHECK_FLAG(dbdesc->bits, OSPF6_DBDESC_IBIT)) {
423 if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV))
424 zlog_debug("Initialize bit mismatch");
425 thread_add_event(master, seqnumber_mismatch, on, 0,
426 NULL);
427 return;
428 }
429
430 if (memcmp(on->options, dbdesc->options, sizeof(on->options))) {
431 if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV))
432 zlog_debug("Option field mismatch");
433 thread_add_event(master, seqnumber_mismatch, on, 0,
434 NULL);
435 return;
436 }
437
438 if (ntohl(dbdesc->seqnum) != on->dbdesc_seqnum) {
439 if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV))
440 zlog_debug(
441 "Sequence number mismatch (%#lx expected)",
d7c0a89a 442 (unsigned long)on->dbdesc_seqnum);
d62a17ae 443 thread_add_event(master, seqnumber_mismatch, on, 0,
444 NULL);
445 return;
446 }
447 break;
448
449 case OSPF6_NEIGHBOR_LOADING:
450 case OSPF6_NEIGHBOR_FULL:
451 if (!memcmp(dbdesc, &on->dbdesc_last,
452 sizeof(struct ospf6_dbdesc))) {
453 /* Duplicated DatabaseDescription is dropped by master
454 */
455 if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV))
456 zlog_debug(
457 "Duplicated dbdesc discarded by Master, ignore");
458 return;
459 }
460
461 if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV))
462 zlog_debug("Not duplicate dbdesc in state %s",
463 ospf6_neighbor_state_str[on->state]);
464 thread_add_event(master, seqnumber_mismatch, on, 0, NULL);
465 return;
466
467 default:
468 assert(0);
469 break;
470 }
471
472 /* Process LSA headers */
473 for (p = (char *)((caddr_t)dbdesc + sizeof(struct ospf6_dbdesc));
474 p + sizeof(struct ospf6_lsa_header) <= OSPF6_MESSAGE_END(oh);
475 p += sizeof(struct ospf6_lsa_header)) {
476 struct ospf6_lsa *his, *mine;
477 struct ospf6_lsdb *lsdb = NULL;
478
479 his = ospf6_lsa_create_headeronly((struct ospf6_lsa_header *)p);
480
481 if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV))
482 zlog_debug("%s", his->name);
483
484 switch (OSPF6_LSA_SCOPE(his->header->type)) {
485 case OSPF6_SCOPE_LINKLOCAL:
486 lsdb = on->ospf6_if->lsdb;
487 break;
488 case OSPF6_SCOPE_AREA:
489 lsdb = on->ospf6_if->area->lsdb;
490 break;
491 case OSPF6_SCOPE_AS:
492 lsdb = on->ospf6_if->area->ospf6->lsdb;
493 break;
494 case OSPF6_SCOPE_RESERVED:
495 if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV))
496 zlog_debug("Ignoring LSA of reserved scope");
497 ospf6_lsa_delete(his);
498 continue;
499 break;
500 }
501
502 if (ntohs(his->header->type) == OSPF6_LSTYPE_AS_EXTERNAL
503 && IS_AREA_STUB(on->ospf6_if->area)) {
504 if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV))
505 zlog_debug(
506 "SeqNumMismatch (E-bit mismatch), discard");
507 ospf6_lsa_delete(his);
508 thread_add_event(master, seqnumber_mismatch, on, 0,
509 NULL);
510 return;
511 }
512
513 mine = ospf6_lsdb_lookup(his->header->type, his->header->id,
514 his->header->adv_router, lsdb);
515 if (mine == NULL) {
516 if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV))
517 zlog_debug("Add request (No database copy)");
518 ospf6_lsdb_add(ospf6_lsa_copy(his), on->request_list);
519 } else if (ospf6_lsa_compare(his, mine) < 0) {
520 if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV))
521 zlog_debug("Add request (Received MoreRecent)");
522 ospf6_lsdb_add(ospf6_lsa_copy(his), on->request_list);
523 } else {
524 if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV))
525 zlog_debug("Discard (Existing MoreRecent)");
526 }
527 ospf6_lsa_delete(his);
528 }
529
530 assert(p == OSPF6_MESSAGE_END(oh));
531
532 /* Increment sequence number */
533 on->dbdesc_seqnum++;
534
535 /* schedule send lsreq */
536 if (on->request_list->count)
537 thread_add_event(master, ospf6_lsreq_send, on, 0,
538 &on->thread_send_lsreq);
539
540 THREAD_OFF(on->thread_send_dbdesc);
541
542 /* More bit check */
543 if (!CHECK_FLAG(dbdesc->bits, OSPF6_DBDESC_MBIT)
544 && !CHECK_FLAG(on->dbdesc_bits, OSPF6_DBDESC_MBIT))
545 thread_add_event(master, exchange_done, on, 0, NULL);
546 else {
547 on->thread_send_dbdesc = NULL;
548 thread_add_event(master, ospf6_dbdesc_send_newone, on, 0,
549 &on->thread_send_dbdesc);
550 }
551
552 /* save last received dbdesc */
553 memcpy(&on->dbdesc_last, dbdesc, sizeof(struct ospf6_dbdesc));
718e3744 554}
555
d62a17ae 556static void ospf6_dbdesc_recv_slave(struct ospf6_header *oh,
557 struct ospf6_neighbor *on)
718e3744 558{
d62a17ae 559 struct ospf6_dbdesc *dbdesc;
560 char *p;
561
562 dbdesc = (struct ospf6_dbdesc *)((caddr_t)oh
563 + sizeof(struct ospf6_header));
564
565 if (on->state < OSPF6_NEIGHBOR_INIT) {
566 if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV))
567 zlog_debug("Neighbor state less than Init, ignore");
568 return;
569 }
570
571 switch (on->state) {
572 case OSPF6_NEIGHBOR_TWOWAY:
573 if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV))
574 zlog_debug("Neighbor state is 2-Way, ignore");
575 return;
576
577 case OSPF6_NEIGHBOR_INIT:
578 thread_execute(master, twoway_received, on, 0);
579 if (on->state != OSPF6_NEIGHBOR_EXSTART) {
580 if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV))
581 zlog_debug(
582 "Neighbor state is not ExStart, ignore");
583 return;
584 }
585 /* else fall through to ExStart */
586 /* fallthru */
587 case OSPF6_NEIGHBOR_EXSTART:
588 /* If the neighbor is Master, act as Slave. Schedule
589 negotiation_done
590 and process LSA Headers. Otherwise, ignore this message */
591 if (CHECK_FLAG(dbdesc->bits, OSPF6_DBDESC_IBIT)
592 && CHECK_FLAG(dbdesc->bits, OSPF6_DBDESC_MBIT)
593 && CHECK_FLAG(dbdesc->bits, OSPF6_DBDESC_MSBIT)
594 && ntohs(oh->length)
595 == sizeof(struct ospf6_header)
596 + sizeof(struct ospf6_dbdesc)) {
597 /* set the master/slave bit to slave */
598 UNSET_FLAG(on->dbdesc_bits, OSPF6_DBDESC_MSBIT);
599
600 /* set the DD sequence number to one specified by master
601 */
602 on->dbdesc_seqnum = ntohl(dbdesc->seqnum);
603
604 /* schedule NegotiationDone */
605 thread_execute(master, negotiation_done, on, 0);
606
607 /* Record neighbor options */
608 memcpy(on->options, dbdesc->options,
609 sizeof(on->options));
610 } else {
ff99e5b6 611 zlog_warn(
612 "VRF %s: Nbr %s Negotiation failed",
613 vrf_id_to_name(on->ospf6_if->interface->vrf_id),
614 on->name);
d62a17ae 615 return;
616 }
617 break;
618
619 case OSPF6_NEIGHBOR_EXCHANGE:
620 if (!memcmp(dbdesc, &on->dbdesc_last,
621 sizeof(struct ospf6_dbdesc))) {
622 /* Duplicated DatabaseDescription causes slave to
623 * retransmit */
624 if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV))
625 zlog_debug(
626 "Duplicated dbdesc causes retransmit");
627 THREAD_OFF(on->thread_send_dbdesc);
628 on->thread_send_dbdesc = NULL;
629 thread_add_event(master, ospf6_dbdesc_send, on, 0,
630 &on->thread_send_dbdesc);
631 return;
632 }
633
634 if (!CHECK_FLAG(dbdesc->bits, OSPF6_DBDESC_MSBIT)) {
635 if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV))
636 zlog_debug("Master/Slave bit mismatch");
637 thread_add_event(master, seqnumber_mismatch, on, 0,
638 NULL);
639 return;
640 }
641
642 if (CHECK_FLAG(dbdesc->bits, OSPF6_DBDESC_IBIT)) {
643 if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV))
644 zlog_debug("Initialize bit mismatch");
645 thread_add_event(master, seqnumber_mismatch, on, 0,
646 NULL);
647 return;
648 }
649
650 if (memcmp(on->options, dbdesc->options, sizeof(on->options))) {
651 if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV))
652 zlog_debug("Option field mismatch");
653 thread_add_event(master, seqnumber_mismatch, on, 0,
654 NULL);
655 return;
656 }
657
658 if (ntohl(dbdesc->seqnum) != on->dbdesc_seqnum + 1) {
659 if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV))
660 zlog_debug(
661 "Sequence number mismatch (%#lx expected)",
d7c0a89a 662 (unsigned long)on->dbdesc_seqnum + 1);
d62a17ae 663 thread_add_event(master, seqnumber_mismatch, on, 0,
664 NULL);
665 return;
666 }
667 break;
668
669 case OSPF6_NEIGHBOR_LOADING:
670 case OSPF6_NEIGHBOR_FULL:
671 if (!memcmp(dbdesc, &on->dbdesc_last,
672 sizeof(struct ospf6_dbdesc))) {
673 /* Duplicated DatabaseDescription causes slave to
674 * retransmit */
675 if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV))
676 zlog_debug(
677 "Duplicated dbdesc causes retransmit");
678 THREAD_OFF(on->thread_send_dbdesc);
679 thread_add_event(master, ospf6_dbdesc_send, on, 0,
680 &on->thread_send_dbdesc);
681 return;
682 }
683
684 if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV))
685 zlog_debug("Not duplicate dbdesc in state %s",
686 ospf6_neighbor_state_str[on->state]);
687 thread_add_event(master, seqnumber_mismatch, on, 0, NULL);
688 return;
689
690 default:
691 assert(0);
692 break;
693 }
694
695 /* Process LSA headers */
696 for (p = (char *)((caddr_t)dbdesc + sizeof(struct ospf6_dbdesc));
697 p + sizeof(struct ospf6_lsa_header) <= OSPF6_MESSAGE_END(oh);
698 p += sizeof(struct ospf6_lsa_header)) {
699 struct ospf6_lsa *his, *mine;
700 struct ospf6_lsdb *lsdb = NULL;
701
702 his = ospf6_lsa_create_headeronly((struct ospf6_lsa_header *)p);
703
704 switch (OSPF6_LSA_SCOPE(his->header->type)) {
705 case OSPF6_SCOPE_LINKLOCAL:
706 lsdb = on->ospf6_if->lsdb;
707 break;
708 case OSPF6_SCOPE_AREA:
709 lsdb = on->ospf6_if->area->lsdb;
710 break;
711 case OSPF6_SCOPE_AS:
712 lsdb = on->ospf6_if->area->ospf6->lsdb;
713 break;
714 case OSPF6_SCOPE_RESERVED:
715 if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV))
716 zlog_debug("Ignoring LSA of reserved scope");
717 ospf6_lsa_delete(his);
718 continue;
719 break;
720 }
721
722 if (OSPF6_LSA_SCOPE(his->header->type) == OSPF6_SCOPE_AS
723 && IS_AREA_STUB(on->ospf6_if->area)) {
724 if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV))
725 zlog_debug("E-bit mismatch with LSA Headers");
726 ospf6_lsa_delete(his);
727 thread_add_event(master, seqnumber_mismatch, on, 0,
728 NULL);
729 return;
730 }
731
732 mine = ospf6_lsdb_lookup(his->header->type, his->header->id,
733 his->header->adv_router, lsdb);
734 if (mine == NULL || ospf6_lsa_compare(his, mine) < 0) {
735 if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV))
736 zlog_debug("Add request-list: %s", his->name);
737 ospf6_lsdb_add(ospf6_lsa_copy(his), on->request_list);
738 }
739 ospf6_lsa_delete(his);
740 }
741
742 assert(p == OSPF6_MESSAGE_END(oh));
743
744 /* Set sequence number to Master's */
745 on->dbdesc_seqnum = ntohl(dbdesc->seqnum);
746
747 /* schedule send lsreq */
748 if (on->request_list->count)
749 thread_add_event(master, ospf6_lsreq_send, on, 0,
750 &on->thread_send_lsreq);
751
752 THREAD_OFF(on->thread_send_dbdesc);
753 thread_add_event(master, ospf6_dbdesc_send_newone, on, 0,
754 &on->thread_send_dbdesc);
755
756 /* save last received dbdesc */
757 memcpy(&on->dbdesc_last, dbdesc, sizeof(struct ospf6_dbdesc));
718e3744 758}
759
d62a17ae 760static void ospf6_dbdesc_recv(struct in6_addr *src, struct in6_addr *dst,
761 struct ospf6_interface *oi,
762 struct ospf6_header *oh)
718e3744 763{
d62a17ae 764 struct ospf6_neighbor *on;
765 struct ospf6_dbdesc *dbdesc;
766
767 on = ospf6_neighbor_lookup(oh->router_id, oi);
768 if (on == NULL) {
769 if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV))
770 zlog_debug("Neighbor not found, ignore");
771 return;
772 }
773
774 dbdesc = (struct ospf6_dbdesc *)((caddr_t)oh
775 + sizeof(struct ospf6_header));
776
777 /* Interface MTU check */
778 if (!oi->mtu_ignore && ntohs(dbdesc->ifmtu) != oi->ifmtu) {
ff99e5b6 779 zlog_warn("VRF %s: I/F %s MTU mismatch (my %d rcvd %d)",
780 vrf_id_to_name(oi->interface->vrf_id),
781 oi->interface->name, oi->ifmtu, ntohs(dbdesc->ifmtu));
d62a17ae 782 return;
783 }
784
785 if (dbdesc->reserved1 || dbdesc->reserved2) {
786 if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV))
787 zlog_debug(
788 "Non-0 reserved field in %s's DbDesc, correct",
789 on->name);
790 dbdesc->reserved1 = 0;
791 dbdesc->reserved2 = 0;
792 }
793
43855e3d
CS
794 oi->db_desc_in++;
795
beadc736 796 if (ntohl(oh->router_id) < ntohl(oi->area->ospf6->router_id))
d62a17ae 797 ospf6_dbdesc_recv_master(oh, on);
beadc736 798 else if (ntohl(oi->area->ospf6->router_id) < ntohl(oh->router_id))
d62a17ae 799 ospf6_dbdesc_recv_slave(oh, on);
800 else {
801 if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV))
802 zlog_debug("Can't decide which is master, ignore");
803 }
718e3744 804}
805
d62a17ae 806static void ospf6_lsreq_recv(struct in6_addr *src, struct in6_addr *dst,
807 struct ospf6_interface *oi,
808 struct ospf6_header *oh)
718e3744 809{
d62a17ae 810 struct ospf6_neighbor *on;
811 char *p;
812 struct ospf6_lsreq_entry *e;
813 struct ospf6_lsdb *lsdb = NULL;
814 struct ospf6_lsa *lsa;
815
816 on = ospf6_neighbor_lookup(oh->router_id, oi);
817 if (on == NULL) {
818 if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV))
819 zlog_debug("Neighbor not found, ignore");
820 return;
821 }
822
823 if (on->state != OSPF6_NEIGHBOR_EXCHANGE
824 && on->state != OSPF6_NEIGHBOR_LOADING
825 && on->state != OSPF6_NEIGHBOR_FULL) {
826 if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV))
827 zlog_debug("Neighbor state less than Exchange, ignore");
828 return;
829 }
830
43855e3d
CS
831 oi->ls_req_in++;
832
d62a17ae 833 /* Process each request */
834 for (p = (char *)((caddr_t)oh + sizeof(struct ospf6_header));
835 p + sizeof(struct ospf6_lsreq_entry) <= OSPF6_MESSAGE_END(oh);
836 p += sizeof(struct ospf6_lsreq_entry)) {
837 e = (struct ospf6_lsreq_entry *)p;
838
839 switch (OSPF6_LSA_SCOPE(e->type)) {
840 case OSPF6_SCOPE_LINKLOCAL:
841 lsdb = on->ospf6_if->lsdb;
842 break;
843 case OSPF6_SCOPE_AREA:
844 lsdb = on->ospf6_if->area->lsdb;
845 break;
846 case OSPF6_SCOPE_AS:
847 lsdb = on->ospf6_if->area->ospf6->lsdb;
848 break;
849 default:
850 if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV))
851 zlog_debug("Ignoring LSA of reserved scope");
852 continue;
853 break;
854 }
855
856 /* Find database copy */
857 lsa = ospf6_lsdb_lookup(e->type, e->id, e->adv_router, lsdb);
858 if (lsa == NULL) {
859 char id[16], adv_router[16];
860 if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV)) {
861 inet_ntop(AF_INET, &e->id, id, sizeof(id));
862 inet_ntop(AF_INET, &e->adv_router, adv_router,
863 sizeof(adv_router));
864 zlog_debug(
865 "Can't find requested [%s Id:%s Adv:%s]",
866 ospf6_lstype_name(e->type), id,
867 adv_router);
868 }
869 thread_add_event(master, bad_lsreq, on, 0, NULL);
870 return;
871 }
872
873 ospf6_lsdb_add(ospf6_lsa_copy(lsa), on->lsupdate_list);
874 }
875
876 assert(p == OSPF6_MESSAGE_END(oh));
877
878 /* schedule send lsupdate */
879 THREAD_OFF(on->thread_send_lsupdate);
880 thread_add_event(master, ospf6_lsupdate_send_neighbor, on, 0,
881 &on->thread_send_lsupdate);
718e3744 882}
883
abc7ef44
DO
884/* Verify, that the specified memory area contains exactly N valid IPv6
885 prefixes as specified by RFC5340, A.4.1. */
d62a17ae 886static unsigned ospf6_prefixes_examin(
887 struct ospf6_prefix *current, /* start of buffer */
888 unsigned length,
d7c0a89a 889 const uint32_t req_num_pfxs /* always compared with the actual number
d62a17ae 890 of prefixes */
d7c0a89a 891)
abc7ef44 892{
d7c0a89a
QY
893 uint8_t requested_pfx_bytes;
894 uint32_t real_num_pfxs = 0;
d62a17ae 895
896 while (length) {
897 if (length < OSPF6_PREFIX_MIN_SIZE) {
898 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN,
899 RECV))
900 zlog_debug("%s: undersized IPv6 prefix header",
901 __func__);
902 return MSG_NG;
903 }
904 /* safe to look deeper */
905 if (current->prefix_length > IPV6_MAX_BITLEN) {
906 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN,
907 RECV))
908 zlog_debug("%s: invalid PrefixLength (%u bits)",
909 __func__, current->prefix_length);
910 return MSG_NG;
911 }
912 /* covers both fixed- and variable-sized fields */
913 requested_pfx_bytes =
914 OSPF6_PREFIX_MIN_SIZE
915 + OSPF6_PREFIX_SPACE(current->prefix_length);
916 if (requested_pfx_bytes > length) {
917 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN,
918 RECV))
919 zlog_debug("%s: undersized IPv6 prefix",
920 __func__);
921 return MSG_NG;
922 }
923 /* next prefix */
924 length -= requested_pfx_bytes;
925 current = (struct ospf6_prefix *)((caddr_t)current
926 + requested_pfx_bytes);
927 real_num_pfxs++;
928 }
929 if (real_num_pfxs != req_num_pfxs) {
930 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
931 zlog_debug(
932 "%s: IPv6 prefix number mismatch (%u required, %u real)",
933 __func__, req_num_pfxs, real_num_pfxs);
934 return MSG_NG;
935 }
936 return MSG_OK;
abc7ef44
DO
937}
938
939/* Verify an LSA to have a valid length and dispatch further (where
940 appropriate) to check if the contents, including nested IPv6 prefixes,
941 is properly sized/aligned within the LSA. Note that this function gets
942 LSA type in network byte order, uses in host byte order and passes to
943 ospf6_lstype_name() in network byte order again. */
d62a17ae 944static unsigned ospf6_lsa_examin(struct ospf6_lsa_header *lsah,
d7c0a89a
QY
945 const uint16_t lsalen,
946 const uint8_t headeronly)
abc7ef44 947{
d62a17ae 948 struct ospf6_intra_prefix_lsa *intra_prefix_lsa;
949 struct ospf6_as_external_lsa *as_external_lsa;
950 struct ospf6_link_lsa *link_lsa;
951 unsigned exp_length;
d7c0a89a
QY
952 uint8_t ltindex;
953 uint16_t lsatype;
d62a17ae 954
955 /* In case an additional minimum length constraint is defined for
956 current
957 LSA type, make sure that this constraint is met. */
958 lsatype = ntohs(lsah->type);
959 ltindex = lsatype & OSPF6_LSTYPE_FCODE_MASK;
960 if (ltindex < OSPF6_LSTYPE_SIZE && ospf6_lsa_minlen[ltindex]
961 && lsalen < ospf6_lsa_minlen[ltindex] + OSPF6_LSA_HEADER_SIZE) {
962 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
963 zlog_debug("%s: undersized (%u B) LSA", __func__,
964 lsalen);
965 return MSG_NG;
966 }
967 switch (lsatype) {
968 case OSPF6_LSTYPE_ROUTER:
969 /* RFC5340 A.4.3, LSA header + OSPF6_ROUTER_LSA_MIN_SIZE bytes
970 followed
971 by N>=0 interface descriptions. */
972 if ((lsalen - OSPF6_LSA_HEADER_SIZE - OSPF6_ROUTER_LSA_MIN_SIZE)
973 % OSPF6_ROUTER_LSDESC_FIX_SIZE) {
974 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN,
975 RECV))
976 zlog_debug(
977 "%s: interface description alignment error",
978 __func__);
979 return MSG_NG;
980 }
981 break;
982 case OSPF6_LSTYPE_NETWORK:
983 /* RFC5340 A.4.4, LSA header + OSPF6_NETWORK_LSA_MIN_SIZE bytes
984 followed by N>=0 attached router descriptions. */
985 if ((lsalen - OSPF6_LSA_HEADER_SIZE
986 - OSPF6_NETWORK_LSA_MIN_SIZE)
987 % OSPF6_NETWORK_LSDESC_FIX_SIZE) {
988 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN,
989 RECV))
990 zlog_debug(
991 "%s: router description alignment error",
992 __func__);
993 return MSG_NG;
994 }
995 break;
996 case OSPF6_LSTYPE_INTER_PREFIX:
997 /* RFC5340 A.4.5, LSA header + OSPF6_INTER_PREFIX_LSA_MIN_SIZE
998 bytes
999 followed by 3-4 fields of a single IPv6 prefix. */
1000 if (headeronly)
1001 break;
1002 return ospf6_prefixes_examin(
1003 (struct ospf6_prefix
1004 *)((caddr_t)lsah + OSPF6_LSA_HEADER_SIZE
1005 + OSPF6_INTER_PREFIX_LSA_MIN_SIZE),
1006 lsalen - OSPF6_LSA_HEADER_SIZE
1007 - OSPF6_INTER_PREFIX_LSA_MIN_SIZE,
1008 1);
1009 case OSPF6_LSTYPE_INTER_ROUTER:
1010 /* RFC5340 A.4.6, fixed-size LSA. */
1011 if (lsalen
1012 > OSPF6_LSA_HEADER_SIZE + OSPF6_INTER_ROUTER_LSA_FIX_SIZE) {
1013 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN,
1014 RECV))
1015 zlog_debug("%s: oversized (%u B) LSA", __func__,
1016 lsalen);
1017 return MSG_NG;
1018 }
1019 break;
1020 case OSPF6_LSTYPE_AS_EXTERNAL: /* RFC5340 A.4.7, same as A.4.8. */
1021 case OSPF6_LSTYPE_TYPE_7:
1022 /* RFC5340 A.4.8, LSA header + OSPF6_AS_EXTERNAL_LSA_MIN_SIZE
1023 bytes
1024 followed by 3-4 fields of IPv6 prefix and 3 conditional LSA
1025 fields:
1026 16 bytes of forwarding address, 4 bytes of external route
1027 tag,
1028 4 bytes of referenced link state ID. */
1029 if (headeronly)
1030 break;
1031 as_external_lsa =
1032 (struct ospf6_as_external_lsa
1033 *)((caddr_t)lsah + OSPF6_LSA_HEADER_SIZE);
1034 exp_length =
1035 OSPF6_LSA_HEADER_SIZE + OSPF6_AS_EXTERNAL_LSA_MIN_SIZE;
1036 /* To find out if the last optional field (Referenced Link State
1037 ID) is
1038 assumed in this LSA, we need to access fixed fields of the
1039 IPv6
1040 prefix before ospf6_prefix_examin() confirms its sizing. */
1041 if (exp_length + OSPF6_PREFIX_MIN_SIZE > lsalen) {
1042 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN,
1043 RECV))
1044 zlog_debug("%s: undersized (%u B) LSA header",
1045 __func__, lsalen);
1046 return MSG_NG;
1047 }
1048 /* forwarding address */
1049 if (CHECK_FLAG(as_external_lsa->bits_metric, OSPF6_ASBR_BIT_F))
1050 exp_length += 16;
1051 /* external route tag */
1052 if (CHECK_FLAG(as_external_lsa->bits_metric, OSPF6_ASBR_BIT_T))
1053 exp_length += 4;
1054 /* referenced link state ID */
1055 if (as_external_lsa->prefix.u._prefix_referenced_lstype)
1056 exp_length += 4;
1057 /* All the fixed-size fields (mandatory and optional) must fit.
1058 I.e.,
1059 this check does not include any IPv6 prefix fields. */
1060 if (exp_length > lsalen) {
1061 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN,
1062 RECV))
1063 zlog_debug("%s: undersized (%u B) LSA header",
1064 __func__, lsalen);
1065 return MSG_NG;
1066 }
1067 /* The last call completely covers the remainder (IPv6 prefix).
1068 */
1069 return ospf6_prefixes_examin(
1070 (struct ospf6_prefix
1071 *)((caddr_t)as_external_lsa
1072 + OSPF6_AS_EXTERNAL_LSA_MIN_SIZE),
1073 lsalen - exp_length, 1);
1074 case OSPF6_LSTYPE_LINK:
1075 /* RFC5340 A.4.9, LSA header + OSPF6_LINK_LSA_MIN_SIZE bytes
1076 followed
1077 by N>=0 IPv6 prefix blocks (with N declared beforehand). */
1078 if (headeronly)
1079 break;
1080 link_lsa = (struct ospf6_link_lsa *)((caddr_t)lsah
1081 + OSPF6_LSA_HEADER_SIZE);
1082 return ospf6_prefixes_examin(
1083 (struct ospf6_prefix *)((caddr_t)link_lsa
1084 + OSPF6_LINK_LSA_MIN_SIZE),
1085 lsalen - OSPF6_LSA_HEADER_SIZE
1086 - OSPF6_LINK_LSA_MIN_SIZE,
1087 ntohl(link_lsa->prefix_num) /* 32 bits */
9d303b37 1088 );
d62a17ae 1089 case OSPF6_LSTYPE_INTRA_PREFIX:
1090 /* RFC5340 A.4.10, LSA header + OSPF6_INTRA_PREFIX_LSA_MIN_SIZE
1091 bytes
1092 followed by N>=0 IPv6 prefixes (with N declared beforehand).
1093 */
1094 if (headeronly)
1095 break;
1096 intra_prefix_lsa =
1097 (struct ospf6_intra_prefix_lsa
1098 *)((caddr_t)lsah + OSPF6_LSA_HEADER_SIZE);
1099 return ospf6_prefixes_examin(
1100 (struct ospf6_prefix
1101 *)((caddr_t)intra_prefix_lsa
1102 + OSPF6_INTRA_PREFIX_LSA_MIN_SIZE),
1103 lsalen - OSPF6_LSA_HEADER_SIZE
1104 - OSPF6_INTRA_PREFIX_LSA_MIN_SIZE,
1105 ntohs(intra_prefix_lsa->prefix_num) /* 16 bits */
9d303b37 1106 );
d62a17ae 1107 }
1108 /* No additional validation is possible for unknown LSA types, which are
1109 themselves valid in OPSFv3, hence the default decision is to accept.
1110 */
1111 return MSG_OK;
abc7ef44
DO
1112}
1113
1114/* Verify if the provided input buffer is a valid sequence of LSAs. This
1115 includes verification of LSA blocks length/alignment and dispatching
1116 of deeper-level checks. */
1117static unsigned
d62a17ae 1118ospf6_lsaseq_examin(struct ospf6_lsa_header *lsah, /* start of buffered data */
d7c0a89a 1119 size_t length, const uint8_t headeronly,
d62a17ae 1120 /* When declared_num_lsas is not 0, compare it to the real
1121 number of LSAs
1122 and treat the difference as an error. */
d7c0a89a 1123 const uint32_t declared_num_lsas)
abc7ef44 1124{
d7c0a89a 1125 uint32_t counted_lsas = 0;
d62a17ae 1126
1127 while (length) {
d7c0a89a 1128 uint16_t lsalen;
d62a17ae 1129 if (length < OSPF6_LSA_HEADER_SIZE) {
1130 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN,
1131 RECV))
1132 zlog_debug(
1133 "%s: undersized (%zu B) trailing (#%u) LSA header",
1134 __func__, length, counted_lsas);
1135 return MSG_NG;
1136 }
1137 /* save on ntohs() calls here and in the LSA validator */
1138 lsalen = OSPF6_LSA_SIZE(lsah);
1139 if (lsalen < OSPF6_LSA_HEADER_SIZE) {
1140 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN,
1141 RECV))
1142 zlog_debug(
1143 "%s: malformed LSA header #%u, declared length is %u B",
1144 __func__, counted_lsas, lsalen);
1145 return MSG_NG;
1146 }
1147 if (headeronly) {
1148 /* less checks here and in ospf6_lsa_examin() */
1149 if (MSG_OK != ospf6_lsa_examin(lsah, lsalen, 1)) {
1150 if (IS_OSPF6_DEBUG_MESSAGE(
1151 OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
1152 zlog_debug(
1153 "%s: anomaly in header-only %s LSA #%u",
1154 __func__,
1155 ospf6_lstype_name(lsah->type),
1156 counted_lsas);
1157 return MSG_NG;
1158 }
1159 lsah = (struct ospf6_lsa_header
1160 *)((caddr_t)lsah
1161 + OSPF6_LSA_HEADER_SIZE);
1162 length -= OSPF6_LSA_HEADER_SIZE;
1163 } else {
1164 /* make sure the input buffer is deep enough before
1165 * further checks */
1166 if (lsalen > length) {
1167 if (IS_OSPF6_DEBUG_MESSAGE(
1168 OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
1169 zlog_debug(
1170 "%s: anomaly in %s LSA #%u: declared length is %u B, buffered length is %zu B",
1171 __func__,
1172 ospf6_lstype_name(lsah->type),
1173 counted_lsas, lsalen, length);
1174 return MSG_NG;
1175 }
1176 if (MSG_OK != ospf6_lsa_examin(lsah, lsalen, 0)) {
1177 if (IS_OSPF6_DEBUG_MESSAGE(
1178 OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
1179 zlog_debug(
1180 "%s: anomaly in %s LSA #%u",
1181 __func__,
1182 ospf6_lstype_name(lsah->type),
1183 counted_lsas);
1184 return MSG_NG;
1185 }
1186 lsah = (struct ospf6_lsa_header *)((caddr_t)lsah
1187 + lsalen);
1188 length -= lsalen;
1189 }
1190 counted_lsas++;
1191 }
1192
1193 if (declared_num_lsas && counted_lsas != declared_num_lsas) {
1194 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
1195 zlog_debug(
1196 "%s: #LSAs declared (%u) does not match actual (%u)",
1197 __func__, declared_num_lsas, counted_lsas);
1198 return MSG_NG;
1199 }
1200 return MSG_OK;
abc7ef44
DO
1201}
1202
1203/* Verify a complete OSPF packet for proper sizing/alignment. */
d62a17ae 1204static unsigned ospf6_packet_examin(struct ospf6_header *oh,
1205 const unsigned bytesonwire)
abc7ef44 1206{
d62a17ae 1207 struct ospf6_lsupdate *lsupd;
1208 unsigned test;
1209
1210 /* length, 1st approximation */
1211 if (bytesonwire < OSPF6_HEADER_SIZE) {
1212 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
1213 zlog_debug("%s: undersized (%u B) packet", __func__,
1214 bytesonwire);
1215 return MSG_NG;
1216 }
1217 /* Now it is safe to access header fields. */
1218 if (bytesonwire != ntohs(oh->length)) {
1219 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
1220 zlog_debug(
1ba43456
CS
1221 "%s: %s packet length error (%u real, %u declared)",
1222 __func__, lookup_msg(ospf6_message_type_str,
1223 oh->type, NULL),
1224 bytesonwire, ntohs(oh->length));
d62a17ae 1225 return MSG_NG;
1226 }
1227 /* version check */
1228 if (oh->version != OSPFV3_VERSION) {
1229 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
1230 zlog_debug("%s: invalid (%u) protocol version",
1231 __func__, oh->version);
1232 return MSG_NG;
1233 }
1234 /* length, 2nd approximation */
1235 if (oh->type < OSPF6_MESSAGE_TYPE_ALL && ospf6_packet_minlen[oh->type]
1236 && bytesonwire
1237 < OSPF6_HEADER_SIZE + ospf6_packet_minlen[oh->type]) {
1238 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
1239 zlog_debug("%s: undersized (%u B) %s packet", __func__,
1240 bytesonwire,
1241 lookup_msg(ospf6_message_type_str, oh->type,
1242 NULL));
1243 return MSG_NG;
1244 }
1245 /* type-specific deeper validation */
1246 switch (oh->type) {
1247 case OSPF6_MESSAGE_TYPE_HELLO:
1248 /* RFC5340 A.3.2, packet header + OSPF6_HELLO_MIN_SIZE bytes
1249 followed
1250 by N>=0 router-IDs. */
1251 if (0
1252 == (bytesonwire - OSPF6_HEADER_SIZE - OSPF6_HELLO_MIN_SIZE)
1253 % 4)
1254 return MSG_OK;
1255 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
1256 zlog_debug("%s: alignment error in %s packet", __func__,
1257 lookup_msg(ospf6_message_type_str, oh->type,
1258 NULL));
1259 return MSG_NG;
1260 case OSPF6_MESSAGE_TYPE_DBDESC:
1261 /* RFC5340 A.3.3, packet header + OSPF6_DB_DESC_MIN_SIZE bytes
1262 followed
1263 by N>=0 header-only LSAs. */
1264 test = ospf6_lsaseq_examin(
1265 (struct ospf6_lsa_header *)((caddr_t)oh
1266 + OSPF6_HEADER_SIZE
1267 + OSPF6_DB_DESC_MIN_SIZE),
1268 bytesonwire - OSPF6_HEADER_SIZE
1269 - OSPF6_DB_DESC_MIN_SIZE,
1270 1, 0);
1271 break;
1272 case OSPF6_MESSAGE_TYPE_LSREQ:
1273 /* RFC5340 A.3.4, packet header + N>=0 LS description blocks. */
1274 if (0
1275 == (bytesonwire - OSPF6_HEADER_SIZE - OSPF6_LS_REQ_MIN_SIZE)
1276 % OSPF6_LSREQ_LSDESC_FIX_SIZE)
1277 return MSG_OK;
1278 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
1279 zlog_debug("%s: alignment error in %s packet", __func__,
1280 lookup_msg(ospf6_message_type_str, oh->type,
1281 NULL));
1282 return MSG_NG;
1283 case OSPF6_MESSAGE_TYPE_LSUPDATE:
1284 /* RFC5340 A.3.5, packet header + OSPF6_LS_UPD_MIN_SIZE bytes
1285 followed
1286 by N>=0 full LSAs (with N declared beforehand). */
1287 lsupd = (struct ospf6_lsupdate *)((caddr_t)oh
1288 + OSPF6_HEADER_SIZE);
1289 test = ospf6_lsaseq_examin(
1290 (struct ospf6_lsa_header *)((caddr_t)lsupd
1291 + OSPF6_LS_UPD_MIN_SIZE),
1292 bytesonwire - OSPF6_HEADER_SIZE - OSPF6_LS_UPD_MIN_SIZE,
1293 0, ntohl(lsupd->lsa_number) /* 32 bits */
9d303b37 1294 );
d62a17ae 1295 break;
1296 case OSPF6_MESSAGE_TYPE_LSACK:
1297 /* RFC5340 A.3.6, packet header + N>=0 header-only LSAs. */
1298 test = ospf6_lsaseq_examin(
1299 (struct ospf6_lsa_header *)((caddr_t)oh
1300 + OSPF6_HEADER_SIZE
1301 + OSPF6_LS_ACK_MIN_SIZE),
1302 bytesonwire - OSPF6_HEADER_SIZE - OSPF6_LS_ACK_MIN_SIZE,
1303 1, 0);
1304 break;
1305 default:
1306 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
1307 zlog_debug("%s: invalid (%u) message type", __func__,
1308 oh->type);
1309 return MSG_NG;
1310 }
1311 if (test != MSG_OK
1312 && IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
1313 zlog_debug("%s: anomaly in %s packet", __func__,
1314 lookup_msg(ospf6_message_type_str, oh->type, NULL));
1315 return test;
abc7ef44
DO
1316}
1317
1318/* Verify particular fields of otherwise correct received OSPF packet to
1319 meet the requirements of RFC. */
d62a17ae 1320static int ospf6_rxpacket_examin(struct ospf6_interface *oi,
1321 struct ospf6_header *oh,
1322 const unsigned bytesonwire)
abc7ef44 1323{
d62a17ae 1324 char buf[2][INET_ADDRSTRLEN];
1325
1326 if (MSG_OK != ospf6_packet_examin(oh, bytesonwire))
1327 return MSG_NG;
1328
1329 /* Area-ID check */
1330 if (oh->area_id != oi->area->area_id) {
ff99e5b6 1331 if (oh->area_id == OSPF_AREA_BACKBONE)
1332 zlog_warn(
1333 "VRF %s: I/F %s Message may be via Virtual Link: not supported",
1334 vrf_id_to_name(oi->interface->vrf_id),
1335 oi->interface->name);
1336 else
1337 zlog_warn(
1338 "VRF %s: I/F %s Area-ID mismatch (my %s, rcvd %s)",
1339 vrf_id_to_name(oi->interface->vrf_id),
1340 oi->interface->name,
1341 inet_ntop(AF_INET, &oi->area->area_id, buf[0],
1342 INET_ADDRSTRLEN),
1343 inet_ntop(AF_INET, &oh->area_id, buf[1],
1344 INET_ADDRSTRLEN));
d62a17ae 1345 return MSG_NG;
1346 }
1347
1348 /* Instance-ID check */
1349 if (oh->instance_id != oi->instance_id) {
ff99e5b6 1350 zlog_warn(
1351 "VRF %s: I/F %s Instance-ID mismatch (my %u, rcvd %u)",
1352 vrf_id_to_name(oi->interface->vrf_id),
1353 oi->interface->name, oi->instance_id, oh->instance_id);
d62a17ae 1354 return MSG_NG;
1355 }
1356
1357 /* Router-ID check */
1358 if (oh->router_id == oi->area->ospf6->router_id) {
ff99e5b6 1359 zlog_warn("VRF %s: I/F %s Duplicate Router-ID (%s)",
1360 vrf_id_to_name(oi->interface->vrf_id),
1361 oi->interface->name,
d62a17ae 1362 inet_ntop(AF_INET, &oh->router_id, buf[0],
1363 INET_ADDRSTRLEN));
1364 return MSG_NG;
1365 }
1366 return MSG_OK;
abc7ef44
DO
1367}
1368
d62a17ae 1369static void ospf6_lsupdate_recv(struct in6_addr *src, struct in6_addr *dst,
1370 struct ospf6_interface *oi,
1371 struct ospf6_header *oh)
718e3744 1372{
d62a17ae 1373 struct ospf6_neighbor *on;
1374 struct ospf6_lsupdate *lsupdate;
1375 char *p;
1376
1377 on = ospf6_neighbor_lookup(oh->router_id, oi);
1378 if (on == NULL) {
1379 if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV))
1380 zlog_debug("Neighbor not found, ignore");
1381 return;
1382 }
1383
1384 if (on->state != OSPF6_NEIGHBOR_EXCHANGE
1385 && on->state != OSPF6_NEIGHBOR_LOADING
1386 && on->state != OSPF6_NEIGHBOR_FULL) {
1387 if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV))
1388 zlog_debug("Neighbor state less than Exchange, ignore");
1389 return;
1390 }
1391
1392 lsupdate = (struct ospf6_lsupdate *)((caddr_t)oh
1393 + sizeof(struct ospf6_header));
718e3744 1394
43855e3d
CS
1395 oi->ls_upd_in++;
1396
d62a17ae 1397 /* Process LSAs */
1398 for (p = (char *)((caddr_t)lsupdate + sizeof(struct ospf6_lsupdate));
1399 p < OSPF6_MESSAGE_END(oh)
1400 && p + OSPF6_LSA_SIZE(p) <= OSPF6_MESSAGE_END(oh);
1401 p += OSPF6_LSA_SIZE(p)) {
1402 ospf6_receive_lsa(on, (struct ospf6_lsa_header *)p);
1403 }
1404
1405 assert(p == OSPF6_MESSAGE_END(oh));
508e53e2 1406}
1407
d62a17ae 1408static void ospf6_lsack_recv(struct in6_addr *src, struct in6_addr *dst,
1409 struct ospf6_interface *oi,
1410 struct ospf6_header *oh)
508e53e2 1411{
d62a17ae 1412 struct ospf6_neighbor *on;
1413 char *p;
1414 struct ospf6_lsa *his, *mine;
1415 struct ospf6_lsdb *lsdb = NULL;
1416
1417 assert(oh->type == OSPF6_MESSAGE_TYPE_LSACK);
1418
1419 on = ospf6_neighbor_lookup(oh->router_id, oi);
1420 if (on == NULL) {
1421 if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV))
1422 zlog_debug("Neighbor not found, ignore");
1423 return;
1424 }
1425
1426 if (on->state != OSPF6_NEIGHBOR_EXCHANGE
1427 && on->state != OSPF6_NEIGHBOR_LOADING
1428 && on->state != OSPF6_NEIGHBOR_FULL) {
1429 if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV))
1430 zlog_debug("Neighbor state less than Exchange, ignore");
1431 return;
1432 }
1433
43855e3d
CS
1434 oi->ls_ack_in++;
1435
d62a17ae 1436 for (p = (char *)((caddr_t)oh + sizeof(struct ospf6_header));
1437 p + sizeof(struct ospf6_lsa_header) <= OSPF6_MESSAGE_END(oh);
1438 p += sizeof(struct ospf6_lsa_header)) {
1439 his = ospf6_lsa_create_headeronly((struct ospf6_lsa_header *)p);
1440
1441 switch (OSPF6_LSA_SCOPE(his->header->type)) {
1442 case OSPF6_SCOPE_LINKLOCAL:
1443 lsdb = on->ospf6_if->lsdb;
1444 break;
1445 case OSPF6_SCOPE_AREA:
1446 lsdb = on->ospf6_if->area->lsdb;
1447 break;
1448 case OSPF6_SCOPE_AS:
1449 lsdb = on->ospf6_if->area->ospf6->lsdb;
1450 break;
1451 case OSPF6_SCOPE_RESERVED:
1452 if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV))
1453 zlog_debug("Ignoring LSA of reserved scope");
1454 ospf6_lsa_delete(his);
1455 continue;
1456 break;
1457 }
1458
1459 if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV))
1460 zlog_debug("%s acknowledged by %s", his->name,
1461 on->name);
1462
1463 /* Find database copy */
1464 mine = ospf6_lsdb_lookup(his->header->type, his->header->id,
1465 his->header->adv_router, lsdb);
1466 if (mine == NULL) {
1467 if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV))
1468 zlog_debug("No database copy");
1469 ospf6_lsa_delete(his);
1470 continue;
1471 }
1472
1473 /* Check if the LSA is on his retrans-list */
1474 mine = ospf6_lsdb_lookup(his->header->type, his->header->id,
1475 his->header->adv_router,
1476 on->retrans_list);
1477 if (mine == NULL) {
1478 if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV))
1479 zlog_debug("Not on %s's retrans-list",
1480 on->name);
1481 ospf6_lsa_delete(his);
1482 continue;
1483 }
1484
1485 if (ospf6_lsa_compare(his, mine) != 0) {
1486 /* Log this questionable acknowledgement,
1487 and examine the next one. */
1488 if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV))
1489 zlog_debug("Questionable acknowledgement");
1490 ospf6_lsa_delete(his);
1491 continue;
1492 }
1493
1494 if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV))
1495 zlog_debug(
1496 "Acknowledged, remove from %s's retrans-list",
1497 on->name);
1498
1499 ospf6_decrement_retrans_count(mine);
1500 if (OSPF6_LSA_IS_MAXAGE(mine))
1501 ospf6_maxage_remove(on->ospf6_if->area->ospf6);
1502 ospf6_lsdb_remove(mine, on->retrans_list);
1503 ospf6_lsa_delete(his);
1504 }
1505
1506 assert(p == OSPF6_MESSAGE_END(oh));
508e53e2 1507}
1508
d7c0a89a
QY
1509static uint8_t *recvbuf = NULL;
1510static uint8_t *sendbuf = NULL;
6ac29a51 1511static unsigned int iobuflen = 0;
3b4cd3a9 1512
d62a17ae 1513int ospf6_iobuf_size(unsigned int size)
3b4cd3a9 1514{
d7c0a89a 1515 uint8_t *recvnew, *sendnew;
d62a17ae 1516
1517 if (size <= iobuflen)
1518 return iobuflen;
1519
1520 recvnew = XMALLOC(MTYPE_OSPF6_MESSAGE, size);
1521 sendnew = XMALLOC(MTYPE_OSPF6_MESSAGE, size);
d62a17ae 1522
0a22ddfb
QY
1523 XFREE(MTYPE_OSPF6_MESSAGE, recvbuf);
1524 XFREE(MTYPE_OSPF6_MESSAGE, sendbuf);
d62a17ae 1525 recvbuf = recvnew;
1526 sendbuf = sendnew;
1527 iobuflen = size;
1528
1529 return iobuflen;
3b4cd3a9 1530}
508e53e2 1531
d62a17ae 1532void ospf6_message_terminate(void)
ae2254aa 1533{
e1b36e13
QY
1534 XFREE(MTYPE_OSPF6_MESSAGE, recvbuf);
1535 XFREE(MTYPE_OSPF6_MESSAGE, sendbuf);
d62a17ae 1536
1537 iobuflen = 0;
ae2254aa
TG
1538}
1539
d62a17ae 1540int ospf6_receive(struct thread *thread)
508e53e2 1541{
d62a17ae 1542 int sockfd;
1543 unsigned int len;
1544 char srcname[64], dstname[64];
1545 struct in6_addr src, dst;
1546 ifindex_t ifindex;
1547 struct iovec iovector[2];
1548 struct ospf6_interface *oi;
1549 struct ospf6_header *oh;
7df1f362 1550 struct ospf6 *ospf6;
d62a17ae 1551
1552 /* add next read thread */
7df1f362 1553 ospf6 = THREAD_ARG(thread);
d62a17ae 1554 sockfd = THREAD_FD(thread);
7df1f362
K
1555
1556 thread_add_read(master, ospf6_receive, ospf6, ospf6->fd,
1557 &ospf6->t_ospf6_receive);
d62a17ae 1558
1559 /* initialize */
1560 memset(&src, 0, sizeof(src));
1561 memset(&dst, 0, sizeof(dst));
1562 ifindex = 0;
1563 memset(recvbuf, 0, iobuflen);
1564 iovector[0].iov_base = recvbuf;
1565 iovector[0].iov_len = iobuflen;
1566 iovector[1].iov_base = NULL;
1567 iovector[1].iov_len = 0;
1568
1569 /* receive message */
7df1f362 1570 len = ospf6_recvmsg(&src, &dst, &ifindex, iovector, sockfd);
d62a17ae 1571 if (len > iobuflen) {
1c50c1c0 1572 flog_err(EC_LIB_DEVELOPMENT, "Excess message read");
d62a17ae 1573 return 0;
1574 }
1575
c5d28568 1576 oi = ospf6_interface_lookup_by_ifindex(ifindex, ospf6->vrf_id);
d62a17ae 1577 if (oi == NULL || oi->area == NULL
1578 || CHECK_FLAG(oi->flag, OSPF6_INTERFACE_DISABLE)) {
e4c42d65
DS
1579 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
1580 zlog_debug("Message received on disabled interface");
d62a17ae 1581 return 0;
1582 }
1583 if (CHECK_FLAG(oi->flag, OSPF6_INTERFACE_PASSIVE)) {
1584 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
1585 zlog_debug("%s: Ignore message on passive interface %s",
1586 __func__, oi->interface->name);
1587 return 0;
1588 }
1589
1590 oh = (struct ospf6_header *)recvbuf;
1591 if (ospf6_rxpacket_examin(oi, oh, len) != MSG_OK)
1592 return 0;
1593
1594 /* Being here means, that no sizing/alignment issues were detected in
1595 the input packet. This renders the additional checks performed below
1596 and also in the type-specific dispatching functions a dead code,
1597 which can be dismissed in a cleanup-focused review round later. */
1598
1599 /* Log */
1600 if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV)) {
1601 inet_ntop(AF_INET6, &src, srcname, sizeof(srcname));
1602 inet_ntop(AF_INET6, &dst, dstname, sizeof(dstname));
1603 zlog_debug("%s received on %s",
1604 lookup_msg(ospf6_message_type_str, oh->type, NULL),
1605 oi->interface->name);
1606 zlog_debug(" src: %s", srcname);
1607 zlog_debug(" dst: %s", dstname);
1608
1609 switch (oh->type) {
1610 case OSPF6_MESSAGE_TYPE_HELLO:
1611 ospf6_hello_print(oh);
1612 break;
1613 case OSPF6_MESSAGE_TYPE_DBDESC:
1614 ospf6_dbdesc_print(oh);
1615 break;
1616 case OSPF6_MESSAGE_TYPE_LSREQ:
1617 ospf6_lsreq_print(oh);
1618 break;
1619 case OSPF6_MESSAGE_TYPE_LSUPDATE:
1620 ospf6_lsupdate_print(oh);
1621 break;
1622 case OSPF6_MESSAGE_TYPE_LSACK:
1623 ospf6_lsack_print(oh);
1624 break;
1625 default:
1626 assert(0);
1627 }
1628 }
1629
1630 switch (oh->type) {
1631 case OSPF6_MESSAGE_TYPE_HELLO:
1632 ospf6_hello_recv(&src, &dst, oi, oh);
1633 break;
1634
1635 case OSPF6_MESSAGE_TYPE_DBDESC:
1636 ospf6_dbdesc_recv(&src, &dst, oi, oh);
1637 break;
1638
1639 case OSPF6_MESSAGE_TYPE_LSREQ:
1640 ospf6_lsreq_recv(&src, &dst, oi, oh);
1641 break;
1642
1643 case OSPF6_MESSAGE_TYPE_LSUPDATE:
1644 ospf6_lsupdate_recv(&src, &dst, oi, oh);
1645 break;
1646
1647 case OSPF6_MESSAGE_TYPE_LSACK:
1648 ospf6_lsack_recv(&src, &dst, oi, oh);
1649 break;
1650
1651 default:
1652 assert(0);
1653 }
1654
1655 return 0;
718e3744 1656}
1657
d62a17ae 1658static void ospf6_send(struct in6_addr *src, struct in6_addr *dst,
1659 struct ospf6_interface *oi, struct ospf6_header *oh)
718e3744 1660{
d62a17ae 1661 unsigned int len;
1662 char srcname[64], dstname[64];
1663 struct iovec iovector[2];
1664
1665 /* initialize */
1666 iovector[0].iov_base = (caddr_t)oh;
1667 iovector[0].iov_len = ntohs(oh->length);
1668 iovector[1].iov_base = NULL;
1669 iovector[1].iov_len = 0;
1670
1671 /* fill OSPF header */
1672 oh->version = OSPFV3_VERSION;
1673 /* message type must be set before */
1674 /* message length must be set before */
1675 oh->router_id = oi->area->ospf6->router_id;
1676 oh->area_id = oi->area->area_id;
1677 /* checksum is calculated by kernel */
1678 oh->instance_id = oi->instance_id;
1679 oh->reserved = 0;
1680
1681 /* Log */
1682 if (IS_OSPF6_DEBUG_MESSAGE(oh->type, SEND)) {
1683 inet_ntop(AF_INET6, dst, dstname, sizeof(dstname));
1684 if (src)
1685 inet_ntop(AF_INET6, src, srcname, sizeof(srcname));
1686 else
1687 memset(srcname, 0, sizeof(srcname));
1688 zlog_debug("%s send on %s",
1689 lookup_msg(ospf6_message_type_str, oh->type, NULL),
1690 oi->interface->name);
1691 zlog_debug(" src: %s", srcname);
1692 zlog_debug(" dst: %s", dstname);
1693
1694 switch (oh->type) {
1695 case OSPF6_MESSAGE_TYPE_HELLO:
1696 ospf6_hello_print(oh);
1697 break;
1698 case OSPF6_MESSAGE_TYPE_DBDESC:
1699 ospf6_dbdesc_print(oh);
1700 break;
1701 case OSPF6_MESSAGE_TYPE_LSREQ:
1702 ospf6_lsreq_print(oh);
1703 break;
1704 case OSPF6_MESSAGE_TYPE_LSUPDATE:
1705 ospf6_lsupdate_print(oh);
1706 break;
1707 case OSPF6_MESSAGE_TYPE_LSACK:
1708 ospf6_lsack_print(oh);
1709 break;
1710 default:
1711 zlog_debug("Unknown message");
1712 assert(0);
1713 break;
1714 }
1715 }
1716
1717 /* send message */
7df1f362 1718 if (oi->area->ospf6->fd != -1) {
b66ec22c 1719 len = ospf6_sendmsg(src, dst, oi->interface->ifindex, iovector,
7df1f362
K
1720 oi->area->ospf6->fd);
1721 if (len != ntohs(oh->length))
1722 flog_err(EC_LIB_DEVELOPMENT,
1723 "Could not send entire message");
1724 }
718e3744 1725}
1726
d62a17ae 1727static uint32_t ospf6_packet_max(struct ospf6_interface *oi)
681b84e8 1728{
d62a17ae 1729 assert(oi->ifmtu > sizeof(struct ip6_hdr));
1730 return oi->ifmtu - (sizeof(struct ip6_hdr));
681b84e8
DT
1731}
1732
d62a17ae 1733int ospf6_hello_send(struct thread *thread)
718e3744 1734{
d62a17ae 1735 struct ospf6_interface *oi;
1736 struct ospf6_header *oh;
1737 struct ospf6_hello *hello;
d7c0a89a 1738 uint8_t *p;
d62a17ae 1739 struct listnode *node, *nnode;
1740 struct ospf6_neighbor *on;
1741
1742 oi = (struct ospf6_interface *)THREAD_ARG(thread);
1743 oi->thread_send_hello = (struct thread *)NULL;
1744
1745 if (oi->state <= OSPF6_INTERFACE_DOWN) {
1746 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_HELLO, SEND))
1747 zlog_debug("Unable to send Hello on down interface %s",
1748 oi->interface->name);
1749 return 0;
1750 }
1751
1752 if (iobuflen == 0) {
1753 zlog_debug("Unable to send Hello on interface %s iobuflen is 0",
1754 oi->interface->name);
1755 return 0;
1756 }
1757
1758 /* set next thread */
1759 thread_add_timer(master, ospf6_hello_send, oi, oi->hello_interval,
1760 &oi->thread_send_hello);
1761
1762 memset(sendbuf, 0, iobuflen);
1763 oh = (struct ospf6_header *)sendbuf;
1764 hello = (struct ospf6_hello *)((caddr_t)oh
1765 + sizeof(struct ospf6_header));
1766
1767 hello->interface_id = htonl(oi->interface->ifindex);
1768 hello->priority = oi->priority;
1769 hello->options[0] = oi->area->options[0];
1770 hello->options[1] = oi->area->options[1];
1771 hello->options[2] = oi->area->options[2];
1772 hello->hello_interval = htons(oi->hello_interval);
1773 hello->dead_interval = htons(oi->dead_interval);
1774 hello->drouter = oi->drouter;
1775 hello->bdrouter = oi->bdrouter;
1776
d7c0a89a 1777 p = (uint8_t *)((caddr_t)hello + sizeof(struct ospf6_hello));
d62a17ae 1778
1779 for (ALL_LIST_ELEMENTS(oi->neighbor_list, node, nnode, on)) {
1780 if (on->state < OSPF6_NEIGHBOR_INIT)
1781 continue;
1782
d7c0a89a 1783 if (p - sendbuf + sizeof(uint32_t) > ospf6_packet_max(oi)) {
d62a17ae 1784 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_HELLO,
1785 SEND))
1786 zlog_debug(
1787 "sending Hello message: exceeds I/F MTU");
1788 break;
1789 }
1790
d7c0a89a
QY
1791 memcpy(p, &on->router_id, sizeof(uint32_t));
1792 p += sizeof(uint32_t);
d62a17ae 1793 }
1794
1795 oh->type = OSPF6_MESSAGE_TYPE_HELLO;
1796 oh->length = htons(p - sendbuf);
1797
43855e3d
CS
1798 oi->hello_out++;
1799
d62a17ae 1800 ospf6_send(oi->linklocal_addr, &allspfrouters6, oi, oh);
1801 return 0;
718e3744 1802}
1803
d62a17ae 1804int ospf6_dbdesc_send(struct thread *thread)
718e3744 1805{
d62a17ae 1806 struct ospf6_neighbor *on;
1807 struct ospf6_header *oh;
1808 struct ospf6_dbdesc *dbdesc;
d7c0a89a 1809 uint8_t *p;
2e37407f 1810 struct ospf6_lsa *lsa, *lsanext;
d62a17ae 1811 struct in6_addr *dst;
1812
1813 on = (struct ospf6_neighbor *)THREAD_ARG(thread);
1814 on->thread_send_dbdesc = (struct thread *)NULL;
1815
1816 if (on->state < OSPF6_NEIGHBOR_EXSTART) {
1817 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_DBDESC, SEND))
1818 zlog_debug(
1819 "Quit to send DbDesc to neighbor %s state %s",
1820 on->name, ospf6_neighbor_state_str[on->state]);
1821 return 0;
1822 }
1823
1824 /* set next thread if master */
1825 if (CHECK_FLAG(on->dbdesc_bits, OSPF6_DBDESC_MSBIT))
1826 thread_add_timer(master, ospf6_dbdesc_send, on,
1827 on->ospf6_if->rxmt_interval,
1828 &on->thread_send_dbdesc);
1829
1830 memset(sendbuf, 0, iobuflen);
1831 oh = (struct ospf6_header *)sendbuf;
1832 dbdesc = (struct ospf6_dbdesc *)((caddr_t)oh
1833 + sizeof(struct ospf6_header));
1834
1835 /* if this is initial one, initialize sequence number for DbDesc */
1836 if (CHECK_FLAG(on->dbdesc_bits, OSPF6_DBDESC_IBIT)
1837 && (on->dbdesc_seqnum == 0)) {
1838 on->dbdesc_seqnum = monotime(NULL);
1839 }
1840
1841 dbdesc->options[0] = on->ospf6_if->area->options[0];
1842 dbdesc->options[1] = on->ospf6_if->area->options[1];
1843 dbdesc->options[2] = on->ospf6_if->area->options[2];
1844 dbdesc->ifmtu = htons(on->ospf6_if->ifmtu);
1845 dbdesc->bits = on->dbdesc_bits;
1846 dbdesc->seqnum = htonl(on->dbdesc_seqnum);
1847
1848 /* if this is not initial one, set LSA headers in dbdesc */
d7c0a89a 1849 p = (uint8_t *)((caddr_t)dbdesc + sizeof(struct ospf6_dbdesc));
d62a17ae 1850 if (!CHECK_FLAG(on->dbdesc_bits, OSPF6_DBDESC_IBIT)) {
2e37407f 1851 for (ALL_LSDB(on->dbdesc_list, lsa, lsanext)) {
d62a17ae 1852 ospf6_lsa_age_update_to_send(lsa,
1853 on->ospf6_if->transdelay);
1854
1855 /* MTU check */
1856 if (p - sendbuf + sizeof(struct ospf6_lsa_header)
1857 > ospf6_packet_max(on->ospf6_if)) {
1858 ospf6_lsdb_lsa_unlock(lsa);
1859 break;
1860 }
1861 memcpy(p, lsa->header, sizeof(struct ospf6_lsa_header));
1862 p += sizeof(struct ospf6_lsa_header);
1863 }
1864 }
1865
1866 oh->type = OSPF6_MESSAGE_TYPE_DBDESC;
1867 oh->length = htons(p - sendbuf);
1868
1869
1870 if (on->ospf6_if->state == OSPF6_INTERFACE_POINTTOPOINT)
1871 dst = &allspfrouters6;
1872 else
1873 dst = &on->linklocal_addr;
1874
43855e3d
CS
1875 on->ospf6_if->db_desc_out++;
1876
d62a17ae 1877 ospf6_send(on->ospf6_if->linklocal_addr, dst, on->ospf6_if, oh);
1878
1879 return 0;
718e3744 1880}
1881
d62a17ae 1882int ospf6_dbdesc_send_newone(struct thread *thread)
718e3744 1883{
d62a17ae 1884 struct ospf6_neighbor *on;
2e37407f 1885 struct ospf6_lsa *lsa, *lsanext;
d62a17ae 1886 unsigned int size = 0;
1887
1888 on = (struct ospf6_neighbor *)THREAD_ARG(thread);
1889 ospf6_lsdb_remove_all(on->dbdesc_list);
1890
1891 /* move LSAs from summary_list to dbdesc_list (within neighbor
1892 structure)
1893 so that ospf6_send_dbdesc () can send those LSAs */
1894 size = sizeof(struct ospf6_lsa_header) + sizeof(struct ospf6_dbdesc);
2e37407f 1895 for (ALL_LSDB(on->summary_list, lsa, lsanext)) {
d62a17ae 1896 if (size + sizeof(struct ospf6_lsa_header)
1897 > ospf6_packet_max(on->ospf6_if)) {
1898 ospf6_lsdb_lsa_unlock(lsa);
1899 break;
1900 }
1901
1902 ospf6_lsdb_add(ospf6_lsa_copy(lsa), on->dbdesc_list);
1903 ospf6_lsdb_remove(lsa, on->summary_list);
1904 size += sizeof(struct ospf6_lsa_header);
1905 }
1906
1907 if (on->summary_list->count == 0)
1908 UNSET_FLAG(on->dbdesc_bits, OSPF6_DBDESC_MBIT);
1909
1910 /* If slave, More bit check must be done here */
1911 if (!CHECK_FLAG(on->dbdesc_bits, OSPF6_DBDESC_MSBIT) && /* Slave */
1912 !CHECK_FLAG(on->dbdesc_last.bits, OSPF6_DBDESC_MBIT)
1913 && !CHECK_FLAG(on->dbdesc_bits, OSPF6_DBDESC_MBIT))
1914 thread_add_event(master, exchange_done, on, 0, NULL);
1915
1916 thread_execute(master, ospf6_dbdesc_send, on, 0);
1917 return 0;
508e53e2 1918}
718e3744 1919
d62a17ae 1920int ospf6_lsreq_send(struct thread *thread)
508e53e2 1921{
d62a17ae 1922 struct ospf6_neighbor *on;
1923 struct ospf6_header *oh;
1924 struct ospf6_lsreq_entry *e;
d7c0a89a 1925 uint8_t *p;
2e37407f 1926 struct ospf6_lsa *lsa, *lsanext, *last_req;
d62a17ae 1927
1928 on = (struct ospf6_neighbor *)THREAD_ARG(thread);
1929 on->thread_send_lsreq = (struct thread *)NULL;
1930
1931 /* LSReq will be sent only in ExStart or Loading */
1932 if (on->state != OSPF6_NEIGHBOR_EXCHANGE
1933 && on->state != OSPF6_NEIGHBOR_LOADING) {
1934 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_LSREQ, SEND))
1935 zlog_debug("Quit to send LSReq to neighbor %s state %s",
1936 on->name,
1937 ospf6_neighbor_state_str[on->state]);
1938 return 0;
1939 }
1940
1941 /* schedule loading_done if request list is empty */
1942 if (on->request_list->count == 0) {
1943 thread_add_event(master, loading_done, on, 0, NULL);
1944 return 0;
1945 }
1946
1947 memset(sendbuf, 0, iobuflen);
1948 oh = (struct ospf6_header *)sendbuf;
1949 last_req = NULL;
1950
1951 /* set Request entries in lsreq */
d7c0a89a 1952 p = (uint8_t *)((caddr_t)oh + sizeof(struct ospf6_header));
2e37407f 1953 for (ALL_LSDB(on->request_list, lsa, lsanext)) {
d62a17ae 1954 /* MTU check */
1955 if (p - sendbuf + sizeof(struct ospf6_lsreq_entry)
1956 > ospf6_packet_max(on->ospf6_if)) {
1957 ospf6_lsdb_lsa_unlock(lsa);
1958 break;
1959 }
1960
1961 e = (struct ospf6_lsreq_entry *)p;
1962 e->type = lsa->header->type;
1963 e->id = lsa->header->id;
1964 e->adv_router = lsa->header->adv_router;
1965 p += sizeof(struct ospf6_lsreq_entry);
1966 last_req = lsa;
1967 }
1968
1969 if (last_req != NULL) {
744ba569
DS
1970 if (on->last_ls_req != NULL)
1971 on->last_ls_req = ospf6_lsa_unlock(on->last_ls_req);
1972
d62a17ae 1973 ospf6_lsa_lock(last_req);
1974 on->last_ls_req = last_req;
1975 }
1976
1977 oh->type = OSPF6_MESSAGE_TYPE_LSREQ;
1978 oh->length = htons(p - sendbuf);
1979
43855e3d
CS
1980 on->ospf6_if->ls_req_out++;
1981
d62a17ae 1982 if (on->ospf6_if->state == OSPF6_INTERFACE_POINTTOPOINT)
1983 ospf6_send(on->ospf6_if->linklocal_addr, &allspfrouters6,
1984 on->ospf6_if, oh);
1985 else
1986 ospf6_send(on->ospf6_if->linklocal_addr, &on->linklocal_addr,
1987 on->ospf6_if, oh);
1988
1989 /* set next thread */
1990 if (on->request_list->count != 0) {
1991 on->thread_send_lsreq = NULL;
1992 thread_add_timer(master, ospf6_lsreq_send, on,
1993 on->ospf6_if->rxmt_interval,
1994 &on->thread_send_lsreq);
1995 }
1996
1997 return 0;
718e3744 1998}
1999
1ba43456
CS
2000static void ospf6_send_lsupdate(struct ospf6_neighbor *on,
2001 struct ospf6_interface *oi,
2002 struct ospf6_header *oh)
2003{
2004
2005 if (on) {
43855e3d
CS
2006 on->ospf6_if->ls_upd_out++;
2007
996c9314
LB
2008 if ((on->ospf6_if->state == OSPF6_INTERFACE_POINTTOPOINT)
2009 || (on->ospf6_if->state == OSPF6_INTERFACE_DR)
2010 || (on->ospf6_if->state == OSPF6_INTERFACE_BDR)) {
1ba43456
CS
2011 ospf6_send(on->ospf6_if->linklocal_addr,
2012 &allspfrouters6, on->ospf6_if, oh);
2013 } else {
2014 ospf6_send(on->ospf6_if->linklocal_addr,
2015 &on->linklocal_addr, on->ospf6_if, oh);
2016 }
2017 } else if (oi) {
43855e3d
CS
2018
2019 oi->ls_upd_out++;
2020
996c9314
LB
2021 if ((oi->state == OSPF6_INTERFACE_POINTTOPOINT)
2022 || (oi->state == OSPF6_INTERFACE_DR)
2023 || (oi->state == OSPF6_INTERFACE_BDR)) {
1ba43456
CS
2024 ospf6_send(oi->linklocal_addr, &allspfrouters6, oi, oh);
2025 } else {
2026 ospf6_send(oi->linklocal_addr, &alldrouters6, oi, oh);
2027 }
2028 }
2029}
2030
d62a17ae 2031int ospf6_lsupdate_send_neighbor(struct thread *thread)
718e3744 2032{
d62a17ae 2033 struct ospf6_neighbor *on;
2034 struct ospf6_header *oh;
2035 struct ospf6_lsupdate *lsupdate;
d7c0a89a 2036 uint8_t *p;
d62a17ae 2037 int lsa_cnt;
2e37407f 2038 struct ospf6_lsa *lsa, *lsanext;
d62a17ae 2039
2040 on = (struct ospf6_neighbor *)THREAD_ARG(thread);
2041 on->thread_send_lsupdate = (struct thread *)NULL;
2042
2043 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_LSUPDATE, SEND))
2044 zlog_debug("LSUpdate to neighbor %s", on->name);
2045
2046 if (on->state < OSPF6_NEIGHBOR_EXCHANGE) {
2047 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_LSUPDATE, SEND))
2048 zlog_debug("Quit to send (neighbor state %s)",
2049 ospf6_neighbor_state_str[on->state]);
2050 return 0;
2051 }
2052
2053 memset(sendbuf, 0, iobuflen);
2054 oh = (struct ospf6_header *)sendbuf;
2055 lsupdate = (struct ospf6_lsupdate *)((caddr_t)oh
2056 + sizeof(struct ospf6_header));
2057
d7c0a89a 2058 p = (uint8_t *)((caddr_t)lsupdate + sizeof(struct ospf6_lsupdate));
d62a17ae 2059 lsa_cnt = 0;
2060
2061 /* lsupdate_list lists those LSA which doesn't need to be
2062 retransmitted. remove those from the list */
2e37407f 2063 for (ALL_LSDB(on->lsupdate_list, lsa, lsanext)) {
d62a17ae 2064 /* MTU check */
2065 if ((p - sendbuf + (unsigned int)OSPF6_LSA_SIZE(lsa->header))
2066 > ospf6_packet_max(on->ospf6_if)) {
1ba43456
CS
2067 if (lsa_cnt) {
2068 oh->type = OSPF6_MESSAGE_TYPE_LSUPDATE;
2069 oh->length = htons(p - sendbuf);
2070 lsupdate->lsa_number = htonl(lsa_cnt);
2071
2072 ospf6_send_lsupdate(on, NULL, oh);
2073
2074 memset(sendbuf, 0, iobuflen);
2075 oh = (struct ospf6_header *)sendbuf;
996c9314
LB
2076 lsupdate = (struct ospf6_lsupdate
2077 *)((caddr_t)oh
2078 + sizeof(struct
2079 ospf6_header));
1ba43456 2080
d7c0a89a
QY
2081 p = (uint8_t *)((caddr_t)lsupdate
2082 + sizeof(struct
2083 ospf6_lsupdate));
1ba43456
CS
2084 lsa_cnt = 0;
2085 }
d62a17ae 2086 }
2087
2088 ospf6_lsa_age_update_to_send(lsa, on->ospf6_if->transdelay);
2089 memcpy(p, lsa->header, OSPF6_LSA_SIZE(lsa->header));
2090 p += OSPF6_LSA_SIZE(lsa->header);
2091 lsa_cnt++;
2092
e2e60c48 2093 assert(lsa->lock == 2);
d62a17ae 2094 ospf6_lsdb_remove(lsa, on->lsupdate_list);
2095 }
2096
2097 if (lsa_cnt) {
2098 oh->type = OSPF6_MESSAGE_TYPE_LSUPDATE;
2099 oh->length = htons(p - sendbuf);
2100 lsupdate->lsa_number = htonl(lsa_cnt);
1ba43456 2101 ospf6_send_lsupdate(on, NULL, oh);
d62a17ae 2102 }
2103
2104 /* The addresses used for retransmissions are different from those sent
2105 the
2106 first time and so we need to separate them here.
2107 */
2108 memset(sendbuf, 0, iobuflen);
2109 oh = (struct ospf6_header *)sendbuf;
2110 lsupdate = (struct ospf6_lsupdate *)((caddr_t)oh
2111 + sizeof(struct ospf6_header));
d7c0a89a 2112 p = (uint8_t *)((caddr_t)lsupdate + sizeof(struct ospf6_lsupdate));
d62a17ae 2113 lsa_cnt = 0;
2114
2e37407f 2115 for (ALL_LSDB(on->retrans_list, lsa, lsanext)) {
d62a17ae 2116 /* MTU check */
2117 if ((p - sendbuf + (unsigned int)OSPF6_LSA_SIZE(lsa->header))
2118 > ospf6_packet_max(on->ospf6_if)) {
1ba43456
CS
2119 if (lsa_cnt) {
2120 oh->type = OSPF6_MESSAGE_TYPE_LSUPDATE;
2121 oh->length = htons(p - sendbuf);
2122 lsupdate->lsa_number = htonl(lsa_cnt);
2123
996c9314
LB
2124 if (on->ospf6_if->state
2125 == OSPF6_INTERFACE_POINTTOPOINT) {
1ba43456
CS
2126 ospf6_send(on->ospf6_if->linklocal_addr,
2127 &allspfrouters6,
2128 on->ospf6_if, oh);
2129 } else {
2130 ospf6_send(on->ospf6_if->linklocal_addr,
2131 &on->linklocal_addr,
2132 on->ospf6_if, oh);
2133 }
2134
2135 memset(sendbuf, 0, iobuflen);
2136 oh = (struct ospf6_header *)sendbuf;
996c9314
LB
2137 lsupdate = (struct ospf6_lsupdate
2138 *)((caddr_t)oh
2139 + sizeof(struct
2140 ospf6_header));
d7c0a89a
QY
2141 p = (uint8_t *)((caddr_t)lsupdate
2142 + sizeof(struct
2143 ospf6_lsupdate));
1ba43456
CS
2144 lsa_cnt = 0;
2145 }
d62a17ae 2146 }
2147
2148 ospf6_lsa_age_update_to_send(lsa, on->ospf6_if->transdelay);
2149 memcpy(p, lsa->header, OSPF6_LSA_SIZE(lsa->header));
2150 p += OSPF6_LSA_SIZE(lsa->header);
2151 lsa_cnt++;
2152 }
2153
2154 if (lsa_cnt) {
2155 oh->type = OSPF6_MESSAGE_TYPE_LSUPDATE;
2156 oh->length = htons(p - sendbuf);
2157 lsupdate->lsa_number = htonl(lsa_cnt);
2158
2159 if (on->ospf6_if->state == OSPF6_INTERFACE_POINTTOPOINT)
2160 ospf6_send(on->ospf6_if->linklocal_addr,
2161 &allspfrouters6, on->ospf6_if, oh);
2162 else
2163 ospf6_send(on->ospf6_if->linklocal_addr,
2164 &on->linklocal_addr, on->ospf6_if, oh);
2165 }
2166
2167 if (on->lsupdate_list->count != 0) {
2168 on->thread_send_lsupdate = NULL;
2169 thread_add_event(master, ospf6_lsupdate_send_neighbor, on, 0,
2170 &on->thread_send_lsupdate);
2171 } else if (on->retrans_list->count != 0) {
2172 on->thread_send_lsupdate = NULL;
2173 thread_add_timer(master, ospf6_lsupdate_send_neighbor, on,
2174 on->ospf6_if->rxmt_interval,
2175 &on->thread_send_lsupdate);
2176 }
2177 return 0;
718e3744 2178}
2179
76249532
CS
2180int ospf6_lsupdate_send_neighbor_now(struct ospf6_neighbor *on,
2181 struct ospf6_lsa *lsa)
2182{
2183 struct ospf6_header *oh;
2184 struct ospf6_lsupdate *lsupdate;
d7c0a89a 2185 uint8_t *p;
76249532
CS
2186 int lsa_cnt = 0;
2187
2188 memset(sendbuf, 0, iobuflen);
2189 oh = (struct ospf6_header *)sendbuf;
2190 lsupdate = (struct ospf6_lsupdate *)((caddr_t)oh
2191 + sizeof(struct ospf6_header));
2192
d7c0a89a 2193 p = (uint8_t *)((caddr_t)lsupdate + sizeof(struct ospf6_lsupdate));
76249532
CS
2194 ospf6_lsa_age_update_to_send(lsa, on->ospf6_if->transdelay);
2195 memcpy(p, lsa->header, OSPF6_LSA_SIZE(lsa->header));
2196 p += OSPF6_LSA_SIZE(lsa->header);
2197 lsa_cnt++;
2198
2199 oh->type = OSPF6_MESSAGE_TYPE_LSUPDATE;
2200 oh->length = htons(p - sendbuf);
2201 lsupdate->lsa_number = htonl(lsa_cnt);
2202
996c9314
LB
2203 if (IS_OSPF6_DEBUG_FLOODING
2204 || IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_LSUPDATE, SEND))
15569c58
DA
2205 zlog_debug("%s: Send lsupdate with lsa %s (age %u)", __func__,
2206 lsa->name, ntohs(lsa->header->age));
76249532
CS
2207
2208 ospf6_send_lsupdate(on, NULL, oh);
2209
2210 return 0;
2211}
2212
d62a17ae 2213int ospf6_lsupdate_send_interface(struct thread *thread)
718e3744 2214{
d62a17ae 2215 struct ospf6_interface *oi;
2216 struct ospf6_header *oh;
2217 struct ospf6_lsupdate *lsupdate;
d7c0a89a 2218 uint8_t *p;
d62a17ae 2219 int lsa_cnt;
2e37407f 2220 struct ospf6_lsa *lsa, *lsanext;
d62a17ae 2221
2222 oi = (struct ospf6_interface *)THREAD_ARG(thread);
2223 oi->thread_send_lsupdate = (struct thread *)NULL;
2224
2225 if (oi->state <= OSPF6_INTERFACE_WAITING) {
2226 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_LSUPDATE, SEND))
2227 zlog_debug(
2228 "Quit to send LSUpdate to interface %s state %s",
2229 oi->interface->name,
2230 ospf6_interface_state_str[oi->state]);
2231 return 0;
2232 }
2233
2234 /* if we have nothing to send, return */
2235 if (oi->lsupdate_list->count == 0)
2236 return 0;
2237
2238 memset(sendbuf, 0, iobuflen);
2239 oh = (struct ospf6_header *)sendbuf;
2240 lsupdate = (struct ospf6_lsupdate *)((caddr_t)oh
2241 + sizeof(struct ospf6_header));
2242
d7c0a89a 2243 p = (uint8_t *)((caddr_t)lsupdate + sizeof(struct ospf6_lsupdate));
d62a17ae 2244 lsa_cnt = 0;
2245
2e37407f 2246 for (ALL_LSDB(oi->lsupdate_list, lsa, lsanext)) {
d62a17ae 2247 /* MTU check */
2248 if ((p - sendbuf + ((unsigned int)OSPF6_LSA_SIZE(lsa->header)))
2249 > ospf6_packet_max(oi)) {
1ba43456
CS
2250 if (lsa_cnt) {
2251 oh->type = OSPF6_MESSAGE_TYPE_LSUPDATE;
2252 oh->length = htons(p - sendbuf);
2253 lsupdate->lsa_number = htonl(lsa_cnt);
2254
2255 ospf6_send_lsupdate(NULL, oi, oh);
43855e3d 2256 if (IS_OSPF6_DEBUG_MESSAGE(
996c9314 2257 OSPF6_MESSAGE_TYPE_LSUPDATE, SEND))
43855e3d 2258 zlog_debug("%s: LSUpdate length %d",
15569c58 2259 __func__, ntohs(oh->length));
1ba43456
CS
2260
2261 memset(sendbuf, 0, iobuflen);
2262 oh = (struct ospf6_header *)sendbuf;
996c9314
LB
2263 lsupdate = (struct ospf6_lsupdate
2264 *)((caddr_t)oh
2265 + sizeof(struct
2266 ospf6_header));
1ba43456 2267
d7c0a89a
QY
2268 p = (uint8_t *)((caddr_t)lsupdate
2269 + sizeof(struct
2270 ospf6_lsupdate));
1ba43456
CS
2271 lsa_cnt = 0;
2272 }
d62a17ae 2273 }
2274
2275 ospf6_lsa_age_update_to_send(lsa, oi->transdelay);
2276 memcpy(p, lsa->header, OSPF6_LSA_SIZE(lsa->header));
2277 p += OSPF6_LSA_SIZE(lsa->header);
2278 lsa_cnt++;
2279
e2e60c48 2280 assert(lsa->lock == 2);
d62a17ae 2281 ospf6_lsdb_remove(lsa, oi->lsupdate_list);
2282 }
2283
2284 if (lsa_cnt) {
d62a17ae 2285 oh->type = OSPF6_MESSAGE_TYPE_LSUPDATE;
2286 oh->length = htons(p - sendbuf);
1ba43456 2287 lsupdate->lsa_number = htonl(lsa_cnt);
d62a17ae 2288
1ba43456 2289 ospf6_send_lsupdate(NULL, oi, oh);
d62a17ae 2290 }
2291
2292 if (oi->lsupdate_list->count > 0) {
2293 oi->thread_send_lsupdate = NULL;
2294 thread_add_event(master, ospf6_lsupdate_send_interface, oi, 0,
2295 &oi->thread_send_lsupdate);
2296 }
2297
2298 return 0;
718e3744 2299}
2300
d62a17ae 2301int ospf6_lsack_send_neighbor(struct thread *thread)
718e3744 2302{
d62a17ae 2303 struct ospf6_neighbor *on;
2304 struct ospf6_header *oh;
d7c0a89a 2305 uint8_t *p;
2e37407f 2306 struct ospf6_lsa *lsa, *lsanext;
d62a17ae 2307 int lsa_cnt = 0;
2308
2309 on = (struct ospf6_neighbor *)THREAD_ARG(thread);
2310 on->thread_send_lsack = (struct thread *)NULL;
2311
2312 if (on->state < OSPF6_NEIGHBOR_EXCHANGE) {
2313 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_LSACK, SEND))
2314 zlog_debug("Quit to send LSAck to neighbor %s state %s",
2315 on->name,
2316 ospf6_neighbor_state_str[on->state]);
2317 return 0;
2318 }
2319
2320 /* if we have nothing to send, return */
2321 if (on->lsack_list->count == 0)
2322 return 0;
2323
2324 memset(sendbuf, 0, iobuflen);
2325 oh = (struct ospf6_header *)sendbuf;
2326
d7c0a89a 2327 p = (uint8_t *)((caddr_t)oh + sizeof(struct ospf6_header));
d62a17ae 2328
2e37407f 2329 for (ALL_LSDB(on->lsack_list, lsa, lsanext)) {
d62a17ae 2330 /* MTU check */
2331 if (p - sendbuf + sizeof(struct ospf6_lsa_header)
2332 > ospf6_packet_max(on->ospf6_if)) {
2333 /* if we run out of packet size/space here,
2334 better to try again soon. */
1ba43456
CS
2335 if (lsa_cnt) {
2336 oh->type = OSPF6_MESSAGE_TYPE_LSACK;
2337 oh->length = htons(p - sendbuf);
2338
43855e3d
CS
2339 on->ospf6_if->ls_ack_out++;
2340
1ba43456 2341 ospf6_send(on->ospf6_if->linklocal_addr,
996c9314
LB
2342 &on->linklocal_addr, on->ospf6_if,
2343 oh);
1ba43456
CS
2344
2345 memset(sendbuf, 0, iobuflen);
2346 oh = (struct ospf6_header *)sendbuf;
d7c0a89a
QY
2347 p = (uint8_t *)((caddr_t)oh
2348 + sizeof(struct ospf6_header));
1ba43456
CS
2349 lsa_cnt = 0;
2350 }
d62a17ae 2351 }
2352
2353 ospf6_lsa_age_update_to_send(lsa, on->ospf6_if->transdelay);
2354 memcpy(p, lsa->header, sizeof(struct ospf6_lsa_header));
2355 p += sizeof(struct ospf6_lsa_header);
2356
e2e60c48 2357 assert(lsa->lock == 2);
d62a17ae 2358 ospf6_lsdb_remove(lsa, on->lsack_list);
2359 lsa_cnt++;
2360 }
2361
2362 if (lsa_cnt) {
2363 oh->type = OSPF6_MESSAGE_TYPE_LSACK;
2364 oh->length = htons(p - sendbuf);
2365
43855e3d
CS
2366 on->ospf6_if->ls_ack_out++;
2367
d62a17ae 2368 ospf6_send(on->ospf6_if->linklocal_addr, &on->linklocal_addr,
2369 on->ospf6_if, oh);
2370 }
2371
2372 if (on->lsack_list->count > 0)
2373 thread_add_event(master, ospf6_lsack_send_neighbor, on, 0,
2374 &on->thread_send_lsack);
2375
2376 return 0;
718e3744 2377}
2378
d62a17ae 2379int ospf6_lsack_send_interface(struct thread *thread)
718e3744 2380{
d62a17ae 2381 struct ospf6_interface *oi;
2382 struct ospf6_header *oh;
d7c0a89a 2383 uint8_t *p;
2e37407f 2384 struct ospf6_lsa *lsa, *lsanext;
d62a17ae 2385 int lsa_cnt = 0;
2386
2387 oi = (struct ospf6_interface *)THREAD_ARG(thread);
2388 oi->thread_send_lsack = (struct thread *)NULL;
2389
2390 if (oi->state <= OSPF6_INTERFACE_WAITING) {
2391 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_LSACK, SEND))
2392 zlog_debug(
2393 "Quit to send LSAck to interface %s state %s",
2394 oi->interface->name,
2395 ospf6_interface_state_str[oi->state]);
2396 return 0;
2397 }
2398
2399 /* if we have nothing to send, return */
2400 if (oi->lsack_list->count == 0)
2401 return 0;
2402
2403 memset(sendbuf, 0, iobuflen);
2404 oh = (struct ospf6_header *)sendbuf;
2405
d7c0a89a 2406 p = (uint8_t *)((caddr_t)oh + sizeof(struct ospf6_header));
d62a17ae 2407
2e37407f 2408 for (ALL_LSDB(oi->lsack_list, lsa, lsanext)) {
d62a17ae 2409 /* MTU check */
2410 if (p - sendbuf + sizeof(struct ospf6_lsa_header)
2411 > ospf6_packet_max(oi)) {
2412 /* if we run out of packet size/space here,
2413 better to try again soon. */
2414 THREAD_OFF(oi->thread_send_lsack);
2415 thread_add_event(master, ospf6_lsack_send_interface, oi,
2416 0, &oi->thread_send_lsack);
2417
2418 ospf6_lsdb_lsa_unlock(lsa);
2419 break;
2420 }
2421
2422 ospf6_lsa_age_update_to_send(lsa, oi->transdelay);
2423 memcpy(p, lsa->header, sizeof(struct ospf6_lsa_header));
2424 p += sizeof(struct ospf6_lsa_header);
2425
e2e60c48 2426 assert(lsa->lock == 2);
d62a17ae 2427 ospf6_lsdb_remove(lsa, oi->lsack_list);
2428 lsa_cnt++;
2429 }
2430
2431 if (lsa_cnt) {
2432 oh->type = OSPF6_MESSAGE_TYPE_LSACK;
2433 oh->length = htons(p - sendbuf);
2434
2435 if ((oi->state == OSPF6_INTERFACE_POINTTOPOINT)
2436 || (oi->state == OSPF6_INTERFACE_DR)
2437 || (oi->state == OSPF6_INTERFACE_BDR))
2438 ospf6_send(oi->linklocal_addr, &allspfrouters6, oi, oh);
2439 else
2440 ospf6_send(oi->linklocal_addr, &alldrouters6, oi, oh);
2441 }
2442
2443 if (oi->lsack_list->count > 0)
2444 thread_add_event(master, ospf6_lsack_send_interface, oi, 0,
2445 &oi->thread_send_lsack);
2446
2447 return 0;
718e3744 2448}
2449
6b0655a2 2450
508e53e2 2451/* Commands */
2452DEFUN (debug_ospf6_message,
2453 debug_ospf6_message_cmd,
1d68dbfe 2454 "debug ospf6 message <unknown|hello|dbdesc|lsreq|lsupdate|lsack|all> [<send|recv>]",
508e53e2 2455 DEBUG_STR
2456 OSPF6_STR
2457 "Debug OSPFv3 message\n"
2458 "Debug Unknown message\n"
2459 "Debug Hello message\n"
2460 "Debug Database Description message\n"
2461 "Debug Link State Request message\n"
2462 "Debug Link State Update message\n"
2463 "Debug Link State Acknowledgement message\n"
2464 "Debug All message\n"
1d68dbfe
DW
2465 "Debug only sending message\n"
2466 "Debug only receiving message\n")
718e3744 2467{
d62a17ae 2468 int idx_packet = 3;
2469 int idx_send_recv = 4;
2470 unsigned char level = 0;
2471 int type = 0;
2472 int i;
2473
2474 /* check type */
2475 if (!strncmp(argv[idx_packet]->arg, "u", 1))
2476 type = OSPF6_MESSAGE_TYPE_UNKNOWN;
2477 else if (!strncmp(argv[idx_packet]->arg, "h", 1))
2478 type = OSPF6_MESSAGE_TYPE_HELLO;
2479 else if (!strncmp(argv[idx_packet]->arg, "d", 1))
2480 type = OSPF6_MESSAGE_TYPE_DBDESC;
2481 else if (!strncmp(argv[idx_packet]->arg, "lsr", 3))
2482 type = OSPF6_MESSAGE_TYPE_LSREQ;
2483 else if (!strncmp(argv[idx_packet]->arg, "lsu", 3))
2484 type = OSPF6_MESSAGE_TYPE_LSUPDATE;
2485 else if (!strncmp(argv[idx_packet]->arg, "lsa", 3))
2486 type = OSPF6_MESSAGE_TYPE_LSACK;
2487 else if (!strncmp(argv[idx_packet]->arg, "a", 1))
2488 type = OSPF6_MESSAGE_TYPE_ALL;
2489
2490 if (argc == 4)
2491 level = OSPF6_DEBUG_MESSAGE_SEND | OSPF6_DEBUG_MESSAGE_RECV;
2492 else if (!strncmp(argv[idx_send_recv]->arg, "s", 1))
2493 level = OSPF6_DEBUG_MESSAGE_SEND;
2494 else if (!strncmp(argv[idx_send_recv]->arg, "r", 1))
2495 level = OSPF6_DEBUG_MESSAGE_RECV;
2496
2497 if (type == OSPF6_MESSAGE_TYPE_ALL) {
2498 for (i = 0; i < 6; i++)
2499 OSPF6_DEBUG_MESSAGE_ON(i, level);
2500 } else
2501 OSPF6_DEBUG_MESSAGE_ON(type, level);
2502
2503 return CMD_SUCCESS;
718e3744 2504}
2505
508e53e2 2506DEFUN (no_debug_ospf6_message,
2507 no_debug_ospf6_message_cmd,
1d68dbfe 2508 "no debug ospf6 message <unknown|hello|dbdesc|lsreq|lsupdate|lsack|all> [<send|recv>]",
508e53e2 2509 NO_STR
2510 DEBUG_STR
2511 OSPF6_STR
2512 "Debug OSPFv3 message\n"
2513 "Debug Unknown message\n"
2514 "Debug Hello message\n"
2515 "Debug Database Description message\n"
2516 "Debug Link State Request message\n"
2517 "Debug Link State Update message\n"
2518 "Debug Link State Acknowledgement message\n"
2519 "Debug All message\n"
1d68dbfe
DW
2520 "Debug only sending message\n"
2521 "Debug only receiving message\n")
508e53e2 2522{
d62a17ae 2523 int idx_packet = 4;
2524 int idx_send_recv = 5;
2525 unsigned char level = 0;
2526 int type = 0;
2527 int i;
2528
2529 /* check type */
2530 if (!strncmp(argv[idx_packet]->arg, "u", 1))
2531 type = OSPF6_MESSAGE_TYPE_UNKNOWN;
2532 else if (!strncmp(argv[idx_packet]->arg, "h", 1))
2533 type = OSPF6_MESSAGE_TYPE_HELLO;
2534 else if (!strncmp(argv[idx_packet]->arg, "d", 1))
2535 type = OSPF6_MESSAGE_TYPE_DBDESC;
2536 else if (!strncmp(argv[idx_packet]->arg, "lsr", 3))
2537 type = OSPF6_MESSAGE_TYPE_LSREQ;
2538 else if (!strncmp(argv[idx_packet]->arg, "lsu", 3))
2539 type = OSPF6_MESSAGE_TYPE_LSUPDATE;
2540 else if (!strncmp(argv[idx_packet]->arg, "lsa", 3))
2541 type = OSPF6_MESSAGE_TYPE_LSACK;
2542 else if (!strncmp(argv[idx_packet]->arg, "a", 1))
2543 type = OSPF6_MESSAGE_TYPE_ALL;
2544
2545 if (argc == 5)
2546 level = OSPF6_DEBUG_MESSAGE_SEND | OSPF6_DEBUG_MESSAGE_RECV;
2547 else if (!strncmp(argv[idx_send_recv]->arg, "s", 1))
2548 level = OSPF6_DEBUG_MESSAGE_SEND;
2549 else if (!strncmp(argv[idx_send_recv]->arg, "r", 1))
2550 level = OSPF6_DEBUG_MESSAGE_RECV;
2551
2552 if (type == OSPF6_MESSAGE_TYPE_ALL) {
2553 for (i = 0; i < 6; i++)
2554 OSPF6_DEBUG_MESSAGE_OFF(i, level);
2555 } else
2556 OSPF6_DEBUG_MESSAGE_OFF(type, level);
2557
2558 return CMD_SUCCESS;
718e3744 2559}
2560
508e53e2 2561
d62a17ae 2562int config_write_ospf6_debug_message(struct vty *vty)
718e3744 2563{
d62a17ae 2564 const char *type_str[] = {"unknown", "hello", "dbdesc",
2565 "lsreq", "lsupdate", "lsack"};
2566 unsigned char s = 0, r = 0;
2567 int i;
2568
2569 for (i = 0; i < 6; i++) {
2570 if (IS_OSPF6_DEBUG_MESSAGE(i, SEND))
2571 s |= 1 << i;
2572 if (IS_OSPF6_DEBUG_MESSAGE(i, RECV))
2573 r |= 1 << i;
2574 }
2575
2576 if (s == 0x3f && r == 0x3f) {
2577 vty_out(vty, "debug ospf6 message all\n");
2578 return 0;
2579 }
2580
2581 if (s == 0x3f && r == 0) {
2582 vty_out(vty, "debug ospf6 message all send\n");
2583 return 0;
2584 } else if (s == 0 && r == 0x3f) {
2585 vty_out(vty, "debug ospf6 message all recv\n");
2586 return 0;
2587 }
2588
2589 /* Unknown message is logged by default */
2590 if (!IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN, SEND)
2591 && !IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
2592 vty_out(vty, "no debug ospf6 message unknown\n");
2593 else if (!IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN, SEND))
2594 vty_out(vty, "no debug ospf6 message unknown send\n");
2595 else if (!IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
2596 vty_out(vty, "no debug ospf6 message unknown recv\n");
2597
2598 for (i = 1; i < 6; i++) {
2599 if (IS_OSPF6_DEBUG_MESSAGE(i, SEND)
2600 && IS_OSPF6_DEBUG_MESSAGE(i, RECV))
2601 vty_out(vty, "debug ospf6 message %s\n", type_str[i]);
2602 else if (IS_OSPF6_DEBUG_MESSAGE(i, SEND))
2603 vty_out(vty, "debug ospf6 message %s send\n",
2604 type_str[i]);
2605 else if (IS_OSPF6_DEBUG_MESSAGE(i, RECV))
2606 vty_out(vty, "debug ospf6 message %s recv\n",
2607 type_str[i]);
2608 }
2609
2610 return 0;
718e3744 2611}
2612
d62a17ae 2613void install_element_ospf6_debug_message(void)
508e53e2 2614{
d62a17ae 2615 install_element(ENABLE_NODE, &debug_ospf6_message_cmd);
2616 install_element(ENABLE_NODE, &no_debug_ospf6_message_cmd);
2617 install_element(CONFIG_NODE, &debug_ospf6_message_cmd);
2618 install_element(CONFIG_NODE, &no_debug_ospf6_message_cmd);
508e53e2 2619}