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