]> git.proxmox.com Git - mirror_frr.git/blame - ospf6d/ospf6_message.c
Merge pull request #12310 from kuldeepkash/pim_v6
[mirror_frr.git] / ospf6d / ospf6_message.c
CommitLineData
acddc0ed 1// SPDX-License-Identifier: GPL-2.0-or-later
718e3744 2/*
508e53e2 3 * Copyright (C) 2003 Yasuhiro Ohara
718e3744 4 */
5
508e53e2 6#include <zebra.h>
7
3b4cd3a9 8#include "memory.h"
508e53e2 9#include "log.h"
10#include "vty.h"
11#include "command.h"
12#include "thread.h"
13#include "linklist.h"
4ba03be5 14#include "lib_errors.h"
6cb85350 15#include "checksum.h"
fce7f209 16#include "network.h"
508e53e2 17
508e53e2 18#include "ospf6_proto.h"
19#include "ospf6_lsa.h"
20#include "ospf6_lsdb.h"
c527acf1 21#include "ospf6_top.h"
508e53e2 22#include "ospf6_network.h"
23#include "ospf6_message.h"
718e3744 24
508e53e2 25#include "ospf6_area.h"
26#include "ospf6_neighbor.h"
27#include "ospf6_interface.h"
718e3744 28
abc7ef44
DO
29/* for structures and macros ospf6_lsa_examin() needs */
30#include "ospf6_abr.h"
31#include "ospf6_asbr.h"
32#include "ospf6_intra.h"
33
508e53e2 34#include "ospf6_flood.h"
049207c3 35#include "ospf6d.h"
0d1753a7 36#include "ospf6_gr.h"
681b84e8 37#include <netinet/ip6.h>
6cb85350
AR
38#include "lib/libospf.h"
39#include "lib/keychain.h"
40#include "ospf6_auth_trailer.h"
681b84e8 41
30043e4c 42DEFINE_MTYPE_STATIC(OSPF6D, OSPF6_MESSAGE, "OSPF6 message");
4f7bf1ab
PR
43DEFINE_MTYPE_STATIC(OSPF6D, OSPF6_PACKET, "OSPF6 packet");
44DEFINE_MTYPE_STATIC(OSPF6D, OSPF6_FIFO, "OSPF6 FIFO queue");
30043e4c 45
508e53e2 46unsigned char conf_debug_ospf6_message[6] = {0x03, 0, 0, 0, 0, 0};
6cb85350
AR
47
48const char *ospf6_message_type(int type)
49{
50 switch (type) {
51 case OSPF6_MESSAGE_TYPE_HELLO:
52 return "Hello";
53 case OSPF6_MESSAGE_TYPE_DBDESC:
54 return "DbDesc";
55 case OSPF6_MESSAGE_TYPE_LSREQ:
56 return "LSReq";
57 case OSPF6_MESSAGE_TYPE_LSUPDATE:
58 return "LSUpdate";
59 case OSPF6_MESSAGE_TYPE_LSACK:
60 return "LSAck";
61 case OSPF6_MESSAGE_TYPE_UNKNOWN:
62 default:
63 return "unknown";
64 }
65}
718e3744 66
abc7ef44
DO
67/* Minimum (besides the standard OSPF packet header) lengths for OSPF
68 packets of particular types, offset is the "type" field. */
d7c0a89a 69const uint16_t ospf6_packet_minlen[OSPF6_MESSAGE_TYPE_ALL] = {
d62a17ae 70 0,
71 OSPF6_HELLO_MIN_SIZE,
72 OSPF6_DB_DESC_MIN_SIZE,
73 OSPF6_LS_REQ_MIN_SIZE,
74 OSPF6_LS_UPD_MIN_SIZE,
75 OSPF6_LS_ACK_MIN_SIZE};
abc7ef44
DO
76
77/* Minimum (besides the standard LSA header) lengths for LSAs of particular
78 types, offset is the "LSA function code" portion of "LSA type" field. */
d7c0a89a 79const uint16_t ospf6_lsa_minlen[OSPF6_LSTYPE_SIZE] = {
d62a17ae 80 0,
81 /* 0x2001 */ OSPF6_ROUTER_LSA_MIN_SIZE,
82 /* 0x2002 */ OSPF6_NETWORK_LSA_MIN_SIZE,
83 /* 0x2003 */ OSPF6_INTER_PREFIX_LSA_MIN_SIZE,
84 /* 0x2004 */ OSPF6_INTER_ROUTER_LSA_FIX_SIZE,
85 /* 0x4005 */ OSPF6_AS_EXTERNAL_LSA_MIN_SIZE,
86 /* 0x2006 */ 0,
87 /* 0x2007 */ OSPF6_AS_EXTERNAL_LSA_MIN_SIZE,
88 /* 0x0008 */ OSPF6_LINK_LSA_MIN_SIZE,
0d1753a7 89 /* 0x2009 */ OSPF6_INTRA_PREFIX_LSA_MIN_SIZE,
90 /* 0x200a */ 0,
91 /* 0x000b */ OSPF6_GRACE_LSA_MIN_SIZE};
abc7ef44 92
508e53e2 93/* print functions */
718e3744 94
d62a17ae 95static void ospf6_header_print(struct ospf6_header *oh)
718e3744 96{
d47b448d
DS
97 zlog_debug(" OSPFv%d Type:%d Len:%hu Router-ID:%pI4", oh->version,
98 oh->type, ntohs(oh->length), &oh->router_id);
99 zlog_debug(" Area-ID:%pI4 Cksum:%hx Instance-ID:%d", &oh->area_id,
d62a17ae 100 ntohs(oh->checksum), oh->instance_id);
718e3744 101}
102
f44d0f5e 103void ospf6_hello_print(struct ospf6_header *oh, int action)
718e3744 104{
d62a17ae 105 struct ospf6_hello *hello;
6cb85350 106 char options[32];
d62a17ae 107 char *p;
108
109 ospf6_header_print(oh);
110 assert(oh->type == OSPF6_MESSAGE_TYPE_HELLO);
111
112 hello = (struct ospf6_hello *)((caddr_t)oh
113 + sizeof(struct ospf6_header));
114
d62a17ae 115 ospf6_options_printbuf(hello->options, options, sizeof(options));
116
117 zlog_debug(" I/F-Id:%ld Priority:%d Option:%s",
d7c0a89a 118 (unsigned long)ntohl(hello->interface_id), hello->priority,
d62a17ae 119 options);
120 zlog_debug(" HelloInterval:%hu DeadInterval:%hu",
121 ntohs(hello->hello_interval), ntohs(hello->dead_interval));
d47b448d 122 zlog_debug(" DR:%pI4 BDR:%pI4", &hello->drouter, &hello->bdrouter);
d62a17ae 123
f44d0f5e 124 if ((IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV)
125 && action == OSPF6_ACTION_RECV)
126 || (IS_OSPF6_DEBUG_MESSAGE(oh->type, SEND)
127 && action == OSPF6_ACTION_SEND)) {
d62a17ae 128
f44d0f5e 129 for (p = (char *)((caddr_t)hello + sizeof(struct ospf6_hello));
130 p + sizeof(uint32_t) <= OSPF6_MESSAGE_END(oh);
131 p += sizeof(uint32_t))
132 zlog_debug(" Neighbor: %pI4", (in_addr_t *)p);
133
134 assert(p == OSPF6_MESSAGE_END(oh));
135 }
718e3744 136}
137
f44d0f5e 138void ospf6_dbdesc_print(struct ospf6_header *oh, int action)
718e3744 139{
d62a17ae 140 struct ospf6_dbdesc *dbdesc;
6cb85350 141 char options[32];
d62a17ae 142 char *p;
508e53e2 143
d62a17ae 144 ospf6_header_print(oh);
145 assert(oh->type == OSPF6_MESSAGE_TYPE_DBDESC);
508e53e2 146
d62a17ae 147 dbdesc = (struct ospf6_dbdesc *)((caddr_t)oh
148 + sizeof(struct ospf6_header));
508e53e2 149
d62a17ae 150 ospf6_options_printbuf(dbdesc->options, options, sizeof(options));
508e53e2 151
d62a17ae 152 zlog_debug(" MBZ: %#x Option: %s IfMTU: %hu", dbdesc->reserved1,
153 options, ntohs(dbdesc->ifmtu));
154 zlog_debug(" MBZ: %#x Bits: %s%s%s SeqNum: %#lx", dbdesc->reserved2,
155 (CHECK_FLAG(dbdesc->bits, OSPF6_DBDESC_IBIT) ? "I" : "-"),
156 (CHECK_FLAG(dbdesc->bits, OSPF6_DBDESC_MBIT) ? "M" : "-"),
157 (CHECK_FLAG(dbdesc->bits, OSPF6_DBDESC_MSBIT) ? "m" : "s"),
d7c0a89a 158 (unsigned long)ntohl(dbdesc->seqnum));
508e53e2 159
f44d0f5e 160 if ((IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV)
161 && action == OSPF6_ACTION_RECV)
162 || (IS_OSPF6_DEBUG_MESSAGE(oh->type, SEND)
163 && action == OSPF6_ACTION_SEND)) {
508e53e2 164
f44d0f5e 165 for (p = (char *)((caddr_t)dbdesc
166 + sizeof(struct ospf6_dbdesc));
167 p + sizeof(struct ospf6_lsa_header)
168 <= OSPF6_MESSAGE_END(oh);
169 p += sizeof(struct ospf6_lsa_header))
170 ospf6_lsa_header_print_raw(
171 (struct ospf6_lsa_header *)p);
172
173 assert(p == OSPF6_MESSAGE_END(oh));
174 }
718e3744 175}
176
f44d0f5e 177void ospf6_lsreq_print(struct ospf6_header *oh, int action)
718e3744 178{
d62a17ae 179 char *p;
180
181 ospf6_header_print(oh);
182 assert(oh->type == OSPF6_MESSAGE_TYPE_LSREQ);
183
f44d0f5e 184 if ((IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV)
185 && action == OSPF6_ACTION_RECV)
186 || (IS_OSPF6_DEBUG_MESSAGE(oh->type, SEND)
187 && action == OSPF6_ACTION_SEND)) {
188
189 for (p = (char *)((caddr_t)oh + sizeof(struct ospf6_header));
190 p + sizeof(struct ospf6_lsreq_entry)
191 <= OSPF6_MESSAGE_END(oh);
192 p += sizeof(struct ospf6_lsreq_entry)) {
193 struct ospf6_lsreq_entry *e =
194 (struct ospf6_lsreq_entry *)p;
195
196 zlog_debug(" [%s Id:%pI4 Adv:%pI4]",
197 ospf6_lstype_name(e->type), &e->id,
198 &e->adv_router);
199 }
d47b448d 200
f44d0f5e 201 assert(p == OSPF6_MESSAGE_END(oh));
d62a17ae 202 }
718e3744 203}
204
f44d0f5e 205void ospf6_lsupdate_print(struct ospf6_header *oh, int action)
718e3744 206{
d62a17ae 207 struct ospf6_lsupdate *lsupdate;
d7c0a89a 208 unsigned long num;
d62a17ae 209 char *p;
718e3744 210
d62a17ae 211 ospf6_header_print(oh);
212 assert(oh->type == OSPF6_MESSAGE_TYPE_LSUPDATE);
718e3744 213
d62a17ae 214 lsupdate = (struct ospf6_lsupdate *)((caddr_t)oh
215 + sizeof(struct ospf6_header));
718e3744 216
d62a17ae 217 num = ntohl(lsupdate->lsa_number);
218 zlog_debug(" Number of LSA: %ld", num);
718e3744 219
f44d0f5e 220 if ((IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV)
221 && action == OSPF6_ACTION_RECV)
222 || (IS_OSPF6_DEBUG_MESSAGE(oh->type, SEND)
223 && action == OSPF6_ACTION_SEND)) {
224
225 for (p = (char *)((caddr_t)lsupdate
226 + sizeof(struct ospf6_lsupdate));
227 p < OSPF6_MESSAGE_END(oh)
228 && p + OSPF6_LSA_SIZE(p) <= OSPF6_MESSAGE_END(oh);
229 p += OSPF6_LSA_SIZE(p)) {
230 ospf6_lsa_header_print_raw(
231 (struct ospf6_lsa_header *)p);
232 }
718e3744 233
f44d0f5e 234 assert(p == OSPF6_MESSAGE_END(oh));
235 }
718e3744 236}
237
f44d0f5e 238void ospf6_lsack_print(struct ospf6_header *oh, int action)
718e3744 239{
d62a17ae 240 char *p;
718e3744 241
d62a17ae 242 ospf6_header_print(oh);
243 assert(oh->type == OSPF6_MESSAGE_TYPE_LSACK);
718e3744 244
f44d0f5e 245 if ((IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV)
246 && action == OSPF6_ACTION_RECV)
247 || (IS_OSPF6_DEBUG_MESSAGE(oh->type, SEND)
248 && action == OSPF6_ACTION_SEND)) {
508e53e2 249
f44d0f5e 250 for (p = (char *)((caddr_t)oh + sizeof(struct ospf6_header));
251 p + sizeof(struct ospf6_lsa_header)
252 <= OSPF6_MESSAGE_END(oh);
253 p += sizeof(struct ospf6_lsa_header))
254 ospf6_lsa_header_print_raw(
255 (struct ospf6_lsa_header *)p);
256
257 assert(p == OSPF6_MESSAGE_END(oh));
258 }
718e3744 259}
260
3d968031
PR
261static struct ospf6_packet *ospf6_packet_new(size_t size)
262{
263 struct ospf6_packet *new;
264
265 new = XCALLOC(MTYPE_OSPF6_PACKET, sizeof(struct ospf6_packet));
266 new->s = stream_new(size);
267
268 return new;
269}
270
d6a39b53 271static void ospf6_packet_free(struct ospf6_packet *op)
4f7bf1ab
PR
272{
273 if (op->s)
274 stream_free(op->s);
275
276 XFREE(MTYPE_OSPF6_PACKET, op);
277}
278
279struct ospf6_fifo *ospf6_fifo_new(void)
280{
281 struct ospf6_fifo *new;
282
283 new = XCALLOC(MTYPE_OSPF6_FIFO, sizeof(struct ospf6_fifo));
284 return new;
285}
286
287/* Add new packet to fifo. */
531f925b 288static void ospf6_fifo_push(struct ospf6_fifo *fifo, struct ospf6_packet *op)
4f7bf1ab
PR
289{
290 if (fifo->tail)
291 fifo->tail->next = op;
292 else
293 fifo->head = op;
294
295 fifo->tail = op;
296
297 fifo->count++;
298}
299
300/* Add new packet to head of fifo. */
531f925b
PR
301static void ospf6_fifo_push_head(struct ospf6_fifo *fifo,
302 struct ospf6_packet *op)
4f7bf1ab
PR
303{
304 op->next = fifo->head;
305
306 if (fifo->tail == NULL)
307 fifo->tail = op;
308
309 fifo->head = op;
310
311 fifo->count++;
312}
313
314/* Delete first packet from fifo. */
531f925b 315static struct ospf6_packet *ospf6_fifo_pop(struct ospf6_fifo *fifo)
4f7bf1ab
PR
316{
317 struct ospf6_packet *op;
318
319 op = fifo->head;
320
321 if (op) {
322 fifo->head = op->next;
323
324 if (fifo->head == NULL)
325 fifo->tail = NULL;
326
327 fifo->count--;
328 }
329
330 return op;
331}
332
333/* Return first fifo entry. */
d6a39b53 334static struct ospf6_packet *ospf6_fifo_head(struct ospf6_fifo *fifo)
4f7bf1ab
PR
335{
336 return fifo->head;
337}
338
339/* Flush ospf packet fifo. */
340void ospf6_fifo_flush(struct ospf6_fifo *fifo)
341{
342 struct ospf6_packet *op;
343 struct ospf6_packet *next;
344
345 for (op = fifo->head; op; op = next) {
346 next = op->next;
347 ospf6_packet_free(op);
348 }
349 fifo->head = fifo->tail = NULL;
350 fifo->count = 0;
351}
352
353/* Free ospf packet fifo. */
354void ospf6_fifo_free(struct ospf6_fifo *fifo)
355{
356 ospf6_fifo_flush(fifo);
357
358 XFREE(MTYPE_OSPF6_FIFO, fifo);
359}
360
d6a39b53
PR
361static void ospf6_packet_add(struct ospf6_interface *oi,
362 struct ospf6_packet *op)
531f925b
PR
363{
364 /* Add packet to end of queue. */
365 ospf6_fifo_push(oi->obuf, op);
366
367 /* Debug of packet fifo*/
368 /* ospf_fifo_debug (oi->obuf); */
369}
370
3d968031
PR
371static void ospf6_packet_add_top(struct ospf6_interface *oi,
372 struct ospf6_packet *op)
531f925b
PR
373{
374 /* Add packet to head of queue. */
375 ospf6_fifo_push_head(oi->obuf, op);
376
377 /* Debug of packet fifo*/
378 /* ospf_fifo_debug (oi->obuf); */
379}
380
3d968031 381static void ospf6_packet_delete(struct ospf6_interface *oi)
531f925b
PR
382{
383 struct ospf6_packet *op;
384
385 op = ospf6_fifo_pop(oi->obuf);
386
387 if (op)
388 ospf6_packet_free(op);
389}
390
391
d62a17ae 392static void ospf6_hello_recv(struct in6_addr *src, struct in6_addr *dst,
393 struct ospf6_interface *oi,
394 struct ospf6_header *oh)
718e3744 395{
d62a17ae 396 struct ospf6_hello *hello;
397 struct ospf6_neighbor *on;
398 char *p;
399 int twoway = 0;
400 int neighborchange = 0;
401 int neighbor_ifindex_change = 0;
402 int backupseen = 0;
bb382e24
PR
403 int64_t latency = 0;
404 struct timeval timestamp;
d62a17ae 405
bb382e24 406 monotime(&timestamp);
d62a17ae 407 hello = (struct ospf6_hello *)((caddr_t)oh
408 + sizeof(struct ospf6_header));
409
410 /* HelloInterval check */
411 if (ntohs(hello->hello_interval) != oi->hello_interval) {
ff99e5b6 412 zlog_warn(
413 "VRF %s: I/F %s HelloInterval mismatch: (my %d, rcvd %d)",
096f7609
IR
414 oi->interface->vrf->name, oi->interface->name,
415 oi->hello_interval, ntohs(hello->hello_interval));
d62a17ae 416 return;
417 }
418
419 /* RouterDeadInterval check */
420 if (ntohs(hello->dead_interval) != oi->dead_interval) {
ff99e5b6 421 zlog_warn(
422 "VRF %s: I/F %s DeadInterval mismatch: (my %d, rcvd %d)",
096f7609
IR
423 oi->interface->vrf->name, oi->interface->name,
424 oi->dead_interval, ntohs(hello->dead_interval));
d62a17ae 425 return;
426 }
427
428 /* E-bit check */
429 if (OSPF6_OPT_ISSET(hello->options, OSPF6_OPT_E)
430 != OSPF6_OPT_ISSET(oi->area->options, OSPF6_OPT_E)) {
ff99e5b6 431 zlog_warn("VRF %s: IF %s E-bit mismatch",
096f7609 432 oi->interface->vrf->name, oi->interface->name);
d62a17ae 433 return;
434 }
435
a581473f 436 /* N-bit check */
437 if (OSPF6_OPT_ISSET(hello->options, OSPF6_OPT_N)
438 != OSPF6_OPT_ISSET(oi->area->options, OSPF6_OPT_N)) {
439 zlog_warn("VRF %s: IF %s N-bit mismatch",
440 oi->interface->vrf->name, oi->interface->name);
441 return;
442 }
443
6cb85350
AR
444 if (((OSPF6_OPT_ISSET_EXT(hello->options, OSPF6_OPT_AT) ==
445 OSPF6_OPT_AT) &&
446 (oi->at_data.flags == 0)) ||
447 ((OSPF6_OPT_ISSET_EXT(hello->options, OSPF6_OPT_AT) !=
448 OSPF6_OPT_AT) &&
449 (oi->at_data.flags != 0))) {
450 if (IS_OSPF6_DEBUG_AUTH_RX)
451 zlog_warn(
452 "VRF %s: IF %s AT-bit mismatch in hello packet",
453 oi->interface->vrf->name, oi->interface->name);
454 oi->at_data.rx_drop++;
455 return;
456 }
457
d62a17ae 458 /* Find neighbor, create if not exist */
459 on = ospf6_neighbor_lookup(oh->router_id, oi);
460 if (on == NULL) {
461 on = ospf6_neighbor_create(oh->router_id, oi);
462 on->prev_drouter = on->drouter = hello->drouter;
463 on->prev_bdrouter = on->bdrouter = hello->bdrouter;
464 on->priority = hello->priority;
465 }
466
bb382e24
PR
467 /* check latency against hello period */
468 if (on->hello_in)
469 latency = monotime_since(&on->last_hello, NULL)
0dd5ec12 470 - ((int64_t)oi->hello_interval * 1000000);
bb382e24 471 /* log if latency exceeds the hello period */
0dd5ec12 472 if (latency > ((int64_t)oi->hello_interval * 1000000))
bb382e24
PR
473 zlog_warn("%s RX %pI4 high latency %" PRId64 "us.", __func__,
474 &on->router_id, latency);
475 on->last_hello = timestamp;
476 on->hello_in++;
477
d62a17ae 478 /* Always override neighbor's source address */
479 memcpy(&on->linklocal_addr, src, sizeof(struct in6_addr));
480
481 /* Neighbor ifindex check */
482 if (on->ifindex != (ifindex_t)ntohl(hello->interface_id)) {
483 on->ifindex = ntohl(hello->interface_id);
484 neighbor_ifindex_change++;
485 }
486
487 /* TwoWay check */
488 for (p = (char *)((caddr_t)hello + sizeof(struct ospf6_hello));
d7c0a89a
QY
489 p + sizeof(uint32_t) <= OSPF6_MESSAGE_END(oh);
490 p += sizeof(uint32_t)) {
491 uint32_t *router_id = (uint32_t *)p;
d62a17ae 492
493 if (*router_id == oi->area->ospf6->router_id)
494 twoway++;
495 }
496
497 assert(p == OSPF6_MESSAGE_END(oh));
498
499 /* RouterPriority check */
500 if (on->priority != hello->priority) {
501 on->priority = hello->priority;
502 neighborchange++;
503 }
504
505 /* DR check */
506 if (on->drouter != hello->drouter) {
507 on->prev_drouter = on->drouter;
508 on->drouter = hello->drouter;
509 if (on->prev_drouter == on->router_id
510 || on->drouter == on->router_id)
511 neighborchange++;
512 }
513
514 /* BDR check */
515 if (on->bdrouter != hello->bdrouter) {
516 on->prev_bdrouter = on->bdrouter;
517 on->bdrouter = hello->bdrouter;
518 if (on->prev_bdrouter == on->router_id
519 || on->bdrouter == on->router_id)
520 neighborchange++;
521 }
522
523 /* BackupSeen check */
524 if (oi->state == OSPF6_INTERFACE_WAITING) {
525 if (hello->bdrouter == on->router_id)
526 backupseen++;
527 else if (hello->drouter == on->router_id
528 && hello->bdrouter == htonl(0))
529 backupseen++;
530 }
531
43855e3d
CS
532 oi->hello_in++;
533
d62a17ae 534 /* Execute neighbor events */
535 thread_execute(master, hello_received, on, 0);
536 if (twoway)
537 thread_execute(master, twoway_received, on, 0);
0d1753a7 538 else {
950b49f8
RW
539 if (OSPF6_GR_IS_ACTIVE_HELPER(on)) {
540 if (IS_DEBUG_OSPF6_GR)
541 zlog_debug(
542 "%s, Received oneway hello from RESTARTER so ignore here.",
543 __PRETTY_FUNCTION__);
544 } else {
0d1753a7 545 /* If the router is DR_OTHER, RESTARTER will not wait
546 * until it receives the hello from it if it receives
547 * from DR and BDR.
548 * So, helper might receives ONE_WAY hello from
549 * RESTARTER. So not allowing to change the state if it
550 * receives one_way hellow when it acts as HELPER for
551 * that specific neighbor.
552 */
553 thread_execute(master, oneway_received, on, 0);
554 }
555 }
556
557 if (OSPF6_GR_IS_ACTIVE_HELPER(on)) {
558 /* As per the GR Conformance Test Case 7.2. Section 3
559 * "Also, if X was the Designated Router on network segment S
560 * when the helping relationship began, Y maintains X as the
561 * Designated Router until the helping relationship is
562 * terminated."
563 * When it is a helper for this neighbor, It should not trigger
564 * the ISM Events. Also Intentionally not setting the priority
565 * and other fields so that when the neighbor exits the Grace
566 * period, it can handle if there is any change before GR and
567 * after GR.
568 */
0fc3e113 569 if (IS_DEBUG_OSPF6_GR)
0d1753a7 570 zlog_debug(
571 "%s, Neighbor is under GR Restart, hence ignoring the ISM Events",
572 __PRETTY_FUNCTION__);
573
574 return;
575 }
d62a17ae 576
71165098
RW
577 /*
578 * RFC 3623 - Section 2:
579 * "If the restarting router determines that it was the Designated
580 * Router on a given segment prior to the restart, it elects
581 * itself as the Designated Router again. The restarting router
582 * knows that it was the Designated Router if, while the
583 * associated interface is in Waiting state, a Hello packet is
584 * received from a neighbor listing the router as the Designated
585 * Router".
586 */
587 if (oi->area->ospf6->gr_info.restart_in_progress
588 && oi->state == OSPF6_INTERFACE_WAITING
589 && hello->drouter == oi->area->ospf6->router_id)
590 oi->drouter = hello->drouter;
591
d62a17ae 592 /* Schedule interface events */
593 if (backupseen)
594 thread_add_event(master, backup_seen, oi, 0, NULL);
595 if (neighborchange)
596 thread_add_event(master, neighbor_change, oi, 0, NULL);
597
598 if (neighbor_ifindex_change && on->state == OSPF6_NEIGHBOR_FULL)
599 OSPF6_ROUTER_LSA_SCHEDULE(oi->area);
718e3744 600}
601
d62a17ae 602static void ospf6_dbdesc_recv_master(struct ospf6_header *oh,
603 struct ospf6_neighbor *on)
718e3744 604{
d62a17ae 605 struct ospf6_dbdesc *dbdesc;
606 char *p;
607
608 dbdesc = (struct ospf6_dbdesc *)((caddr_t)oh
609 + sizeof(struct ospf6_header));
610
611 if (on->state < OSPF6_NEIGHBOR_INIT) {
f44d0f5e 612 if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV_HDR))
d62a17ae 613 zlog_debug("Neighbor state less than Init, ignore");
614 return;
615 }
616
617 switch (on->state) {
618 case OSPF6_NEIGHBOR_TWOWAY:
f44d0f5e 619 if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV_HDR))
d62a17ae 620 zlog_debug("Neighbor state is 2-Way, ignore");
621 return;
622
623 case OSPF6_NEIGHBOR_INIT:
624 thread_execute(master, twoway_received, on, 0);
625 if (on->state != OSPF6_NEIGHBOR_EXSTART) {
f44d0f5e 626 if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV_HDR))
d62a17ae 627 zlog_debug(
628 "Neighbor state is not ExStart, ignore");
629 return;
630 }
631 /* else fall through to ExStart */
632 /* fallthru */
633 case OSPF6_NEIGHBOR_EXSTART:
634 /* if neighbor obeys us as our slave, schedule negotiation_done
635 and process LSA Headers. Otherwise, ignore this message */
636 if (!CHECK_FLAG(dbdesc->bits, OSPF6_DBDESC_MSBIT)
637 && !CHECK_FLAG(dbdesc->bits, OSPF6_DBDESC_IBIT)
638 && ntohl(dbdesc->seqnum) == on->dbdesc_seqnum) {
639 /* execute NegotiationDone */
640 thread_execute(master, negotiation_done, on, 0);
641
642 /* Record neighbor options */
643 memcpy(on->options, dbdesc->options,
644 sizeof(on->options));
645 } else {
096f7609
IR
646 zlog_warn("VRF %s: Nbr %s: Negotiation failed",
647 on->ospf6_if->interface->vrf->name, on->name);
d62a17ae 648 return;
649 }
650 /* fall through to exchange */
651
652 case OSPF6_NEIGHBOR_EXCHANGE:
653 if (!memcmp(dbdesc, &on->dbdesc_last,
654 sizeof(struct ospf6_dbdesc))) {
655 /* Duplicated DatabaseDescription is dropped by master
656 */
f44d0f5e 657 if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV_HDR))
d62a17ae 658 zlog_debug(
659 "Duplicated dbdesc discarded by Master, ignore");
660 return;
661 }
662
663 if (CHECK_FLAG(dbdesc->bits, OSPF6_DBDESC_MSBIT)) {
1b1f7b4f 664 zlog_warn(
665 "DbDesc recv: Master/Slave bit mismatch Nbr %s",
666 on->name);
d62a17ae 667 thread_add_event(master, seqnumber_mismatch, on, 0,
668 NULL);
669 return;
670 }
671
672 if (CHECK_FLAG(dbdesc->bits, OSPF6_DBDESC_IBIT)) {
1b1f7b4f 673 zlog_warn("DbDesc recv: Initialize bit mismatch Nbr %s",
674 on->name);
d62a17ae 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))) {
1b1f7b4f 681 zlog_warn("DbDesc recv: Option field mismatch Nbr %s",
682 on->name);
d62a17ae 683 thread_add_event(master, seqnumber_mismatch, on, 0,
684 NULL);
685 return;
686 }
687
688 if (ntohl(dbdesc->seqnum) != on->dbdesc_seqnum) {
1b1f7b4f 689 zlog_warn(
690 "DbDesc recv: Sequence number mismatch Nbr %s (%#lx expected)",
691 on->name, (unsigned long)on->dbdesc_seqnum);
d62a17ae 692 thread_add_event(master, seqnumber_mismatch, on, 0,
693 NULL);
694 return;
695 }
696 break;
697
698 case OSPF6_NEIGHBOR_LOADING:
699 case OSPF6_NEIGHBOR_FULL:
700 if (!memcmp(dbdesc, &on->dbdesc_last,
701 sizeof(struct ospf6_dbdesc))) {
702 /* Duplicated DatabaseDescription is dropped by master
703 */
f44d0f5e 704 if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV_HDR))
d62a17ae 705 zlog_debug(
706 "Duplicated dbdesc discarded by Master, ignore");
707 return;
708 }
709
1b1f7b4f 710 zlog_warn(
711 "DbDesc recv: Not duplicate dbdesc in state %s Nbr %s",
712 ospf6_neighbor_state_str[on->state], on->name);
d62a17ae 713 thread_add_event(master, seqnumber_mismatch, on, 0, NULL);
714 return;
715
716 default:
717 assert(0);
718 break;
719 }
720
721 /* Process LSA headers */
722 for (p = (char *)((caddr_t)dbdesc + sizeof(struct ospf6_dbdesc));
723 p + sizeof(struct ospf6_lsa_header) <= OSPF6_MESSAGE_END(oh);
724 p += sizeof(struct ospf6_lsa_header)) {
725 struct ospf6_lsa *his, *mine;
726 struct ospf6_lsdb *lsdb = NULL;
727
728 his = ospf6_lsa_create_headeronly((struct ospf6_lsa_header *)p);
729
730 if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV))
731 zlog_debug("%s", his->name);
732
733 switch (OSPF6_LSA_SCOPE(his->header->type)) {
734 case OSPF6_SCOPE_LINKLOCAL:
735 lsdb = on->ospf6_if->lsdb;
736 break;
737 case OSPF6_SCOPE_AREA:
738 lsdb = on->ospf6_if->area->lsdb;
739 break;
740 case OSPF6_SCOPE_AS:
741 lsdb = on->ospf6_if->area->ospf6->lsdb;
742 break;
743 case OSPF6_SCOPE_RESERVED:
744 if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV))
745 zlog_debug("Ignoring LSA of reserved scope");
746 ospf6_lsa_delete(his);
747 continue;
d62a17ae 748 }
749
750 if (ntohs(his->header->type) == OSPF6_LSTYPE_AS_EXTERNAL
4f785c07
RZ
751 && (IS_AREA_STUB(on->ospf6_if->area)
752 || IS_AREA_NSSA(on->ospf6_if->area))) {
d62a17ae 753 if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV))
754 zlog_debug(
755 "SeqNumMismatch (E-bit mismatch), discard");
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) {
765 if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV))
766 zlog_debug("Add request (No database copy)");
767 ospf6_lsdb_add(ospf6_lsa_copy(his), on->request_list);
768 } else if (ospf6_lsa_compare(his, mine) < 0) {
769 if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV))
770 zlog_debug("Add request (Received MoreRecent)");
771 ospf6_lsdb_add(ospf6_lsa_copy(his), on->request_list);
772 } else {
773 if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV))
774 zlog_debug("Discard (Existing MoreRecent)");
775 }
776 ospf6_lsa_delete(his);
777 }
778
779 assert(p == OSPF6_MESSAGE_END(oh));
780
781 /* Increment sequence number */
782 on->dbdesc_seqnum++;
783
784 /* schedule send lsreq */
785 if (on->request_list->count)
786 thread_add_event(master, ospf6_lsreq_send, on, 0,
787 &on->thread_send_lsreq);
788
789 THREAD_OFF(on->thread_send_dbdesc);
790
791 /* More bit check */
792 if (!CHECK_FLAG(dbdesc->bits, OSPF6_DBDESC_MBIT)
793 && !CHECK_FLAG(on->dbdesc_bits, OSPF6_DBDESC_MBIT))
9318fc6a
DS
794 thread_add_event(master, exchange_done, on, 0,
795 &on->thread_exchange_done);
d62a17ae 796 else {
d62a17ae 797 thread_add_event(master, ospf6_dbdesc_send_newone, on, 0,
798 &on->thread_send_dbdesc);
799 }
800
801 /* save last received dbdesc */
802 memcpy(&on->dbdesc_last, dbdesc, sizeof(struct ospf6_dbdesc));
718e3744 803}
804
d62a17ae 805static void ospf6_dbdesc_recv_slave(struct ospf6_header *oh,
806 struct ospf6_neighbor *on)
718e3744 807{
d62a17ae 808 struct ospf6_dbdesc *dbdesc;
809 char *p;
810
811 dbdesc = (struct ospf6_dbdesc *)((caddr_t)oh
812 + sizeof(struct ospf6_header));
813
814 if (on->state < OSPF6_NEIGHBOR_INIT) {
f44d0f5e 815 if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV_HDR))
d62a17ae 816 zlog_debug("Neighbor state less than Init, ignore");
817 return;
818 }
819
820 switch (on->state) {
821 case OSPF6_NEIGHBOR_TWOWAY:
f44d0f5e 822 if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV_HDR))
d62a17ae 823 zlog_debug("Neighbor state is 2-Way, ignore");
824 return;
825
826 case OSPF6_NEIGHBOR_INIT:
827 thread_execute(master, twoway_received, on, 0);
828 if (on->state != OSPF6_NEIGHBOR_EXSTART) {
f44d0f5e 829 if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV_HDR))
d62a17ae 830 zlog_debug(
831 "Neighbor state is not ExStart, ignore");
832 return;
833 }
834 /* else fall through to ExStart */
835 /* fallthru */
836 case OSPF6_NEIGHBOR_EXSTART:
837 /* If the neighbor is Master, act as Slave. Schedule
838 negotiation_done
839 and process LSA Headers. Otherwise, ignore this message */
840 if (CHECK_FLAG(dbdesc->bits, OSPF6_DBDESC_IBIT)
841 && CHECK_FLAG(dbdesc->bits, OSPF6_DBDESC_MBIT)
842 && CHECK_FLAG(dbdesc->bits, OSPF6_DBDESC_MSBIT)
843 && ntohs(oh->length)
844 == sizeof(struct ospf6_header)
845 + sizeof(struct ospf6_dbdesc)) {
846 /* set the master/slave bit to slave */
847 UNSET_FLAG(on->dbdesc_bits, OSPF6_DBDESC_MSBIT);
848
849 /* set the DD sequence number to one specified by master
850 */
851 on->dbdesc_seqnum = ntohl(dbdesc->seqnum);
852
853 /* schedule NegotiationDone */
854 thread_execute(master, negotiation_done, on, 0);
855
856 /* Record neighbor options */
857 memcpy(on->options, dbdesc->options,
858 sizeof(on->options));
859 } else {
096f7609
IR
860 zlog_warn("VRF %s: Nbr %s Negotiation failed",
861 on->ospf6_if->interface->vrf->name, on->name);
d62a17ae 862 return;
863 }
864 break;
865
866 case OSPF6_NEIGHBOR_EXCHANGE:
867 if (!memcmp(dbdesc, &on->dbdesc_last,
868 sizeof(struct ospf6_dbdesc))) {
869 /* Duplicated DatabaseDescription causes slave to
870 * retransmit */
f44d0f5e 871 if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV_HDR))
d62a17ae 872 zlog_debug(
873 "Duplicated dbdesc causes retransmit");
874 THREAD_OFF(on->thread_send_dbdesc);
d62a17ae 875 thread_add_event(master, ospf6_dbdesc_send, on, 0,
876 &on->thread_send_dbdesc);
877 return;
878 }
879
880 if (!CHECK_FLAG(dbdesc->bits, OSPF6_DBDESC_MSBIT)) {
1b1f7b4f 881 zlog_warn(
882 "DbDesc slave recv: Master/Slave bit mismatch Nbr %s",
883 on->name);
d62a17ae 884 thread_add_event(master, seqnumber_mismatch, on, 0,
885 NULL);
886 return;
887 }
888
889 if (CHECK_FLAG(dbdesc->bits, OSPF6_DBDESC_IBIT)) {
1b1f7b4f 890 zlog_warn(
891 "DbDesc slave recv: Initialize bit mismatch Nbr %s",
892 on->name);
d62a17ae 893 thread_add_event(master, seqnumber_mismatch, on, 0,
894 NULL);
895 return;
896 }
897
898 if (memcmp(on->options, dbdesc->options, sizeof(on->options))) {
1b1f7b4f 899 zlog_warn(
900 "DbDesc slave recv: Option field mismatch Nbr %s",
901 on->name);
d62a17ae 902 thread_add_event(master, seqnumber_mismatch, on, 0,
903 NULL);
904 return;
905 }
906
907 if (ntohl(dbdesc->seqnum) != on->dbdesc_seqnum + 1) {
1b1f7b4f 908 zlog_warn(
909 "DbDesc slave recv: Sequence number mismatch Nbr %s (%#lx expected)",
910 on->name, (unsigned long)on->dbdesc_seqnum + 1);
d62a17ae 911 thread_add_event(master, seqnumber_mismatch, on, 0,
912 NULL);
913 return;
914 }
915 break;
916
917 case OSPF6_NEIGHBOR_LOADING:
918 case OSPF6_NEIGHBOR_FULL:
919 if (!memcmp(dbdesc, &on->dbdesc_last,
920 sizeof(struct ospf6_dbdesc))) {
921 /* Duplicated DatabaseDescription causes slave to
922 * retransmit */
f44d0f5e 923 if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV_HDR))
d62a17ae 924 zlog_debug(
925 "Duplicated dbdesc causes retransmit");
926 THREAD_OFF(on->thread_send_dbdesc);
927 thread_add_event(master, ospf6_dbdesc_send, on, 0,
928 &on->thread_send_dbdesc);
929 return;
930 }
931
1b1f7b4f 932 zlog_warn(
933 "DbDesc slave recv: Not duplicate dbdesc in state %s Nbr %s",
934 ospf6_neighbor_state_str[on->state], on->name);
d62a17ae 935 thread_add_event(master, seqnumber_mismatch, on, 0, NULL);
936 return;
937
938 default:
939 assert(0);
940 break;
941 }
942
943 /* Process LSA headers */
944 for (p = (char *)((caddr_t)dbdesc + sizeof(struct ospf6_dbdesc));
945 p + sizeof(struct ospf6_lsa_header) <= OSPF6_MESSAGE_END(oh);
946 p += sizeof(struct ospf6_lsa_header)) {
947 struct ospf6_lsa *his, *mine;
948 struct ospf6_lsdb *lsdb = NULL;
949
950 his = ospf6_lsa_create_headeronly((struct ospf6_lsa_header *)p);
951
952 switch (OSPF6_LSA_SCOPE(his->header->type)) {
953 case OSPF6_SCOPE_LINKLOCAL:
954 lsdb = on->ospf6_if->lsdb;
955 break;
956 case OSPF6_SCOPE_AREA:
957 lsdb = on->ospf6_if->area->lsdb;
958 break;
959 case OSPF6_SCOPE_AS:
960 lsdb = on->ospf6_if->area->ospf6->lsdb;
961 break;
962 case OSPF6_SCOPE_RESERVED:
963 if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV))
964 zlog_debug("Ignoring LSA of reserved scope");
965 ospf6_lsa_delete(his);
966 continue;
d62a17ae 967 }
968
969 if (OSPF6_LSA_SCOPE(his->header->type) == OSPF6_SCOPE_AS
4f785c07
RZ
970 && (IS_AREA_STUB(on->ospf6_if->area)
971 || IS_AREA_NSSA(on->ospf6_if->area))) {
d62a17ae 972 if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV))
973 zlog_debug("E-bit mismatch with LSA Headers");
974 ospf6_lsa_delete(his);
975 thread_add_event(master, seqnumber_mismatch, on, 0,
976 NULL);
977 return;
978 }
979
980 mine = ospf6_lsdb_lookup(his->header->type, his->header->id,
981 his->header->adv_router, lsdb);
982 if (mine == NULL || ospf6_lsa_compare(his, mine) < 0) {
983 if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV))
984 zlog_debug("Add request-list: %s", his->name);
985 ospf6_lsdb_add(ospf6_lsa_copy(his), on->request_list);
986 }
987 ospf6_lsa_delete(his);
988 }
989
990 assert(p == OSPF6_MESSAGE_END(oh));
991
992 /* Set sequence number to Master's */
993 on->dbdesc_seqnum = ntohl(dbdesc->seqnum);
994
995 /* schedule send lsreq */
996 if (on->request_list->count)
997 thread_add_event(master, ospf6_lsreq_send, on, 0,
998 &on->thread_send_lsreq);
999
1000 THREAD_OFF(on->thread_send_dbdesc);
1001 thread_add_event(master, ospf6_dbdesc_send_newone, on, 0,
1002 &on->thread_send_dbdesc);
1003
1004 /* save last received dbdesc */
1005 memcpy(&on->dbdesc_last, dbdesc, sizeof(struct ospf6_dbdesc));
718e3744 1006}
1007
d62a17ae 1008static void ospf6_dbdesc_recv(struct in6_addr *src, struct in6_addr *dst,
1009 struct ospf6_interface *oi,
1010 struct ospf6_header *oh)
718e3744 1011{
d62a17ae 1012 struct ospf6_neighbor *on;
1013 struct ospf6_dbdesc *dbdesc;
1014
1015 on = ospf6_neighbor_lookup(oh->router_id, oi);
1016 if (on == NULL) {
f44d0f5e 1017 if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV_HDR))
d62a17ae 1018 zlog_debug("Neighbor not found, ignore");
1019 return;
1020 }
1021
1022 dbdesc = (struct ospf6_dbdesc *)((caddr_t)oh
1023 + sizeof(struct ospf6_header));
1024
6cb85350
AR
1025 if (((OSPF6_OPT_ISSET_EXT(dbdesc->options, OSPF6_OPT_AT) ==
1026 OSPF6_OPT_AT) &&
1027 (oi->at_data.flags == 0)) ||
1028 ((OSPF6_OPT_ISSET_EXT(dbdesc->options, OSPF6_OPT_AT) !=
1029 OSPF6_OPT_AT) &&
1030 (oi->at_data.flags != 0))) {
1031 if (IS_OSPF6_DEBUG_AUTH_RX)
1032 zlog_warn(
1033 "VRF %s: IF %s AT-bit mismatch in dbdesc packet",
1034 oi->interface->vrf->name, oi->interface->name);
1035 oi->at_data.rx_drop++;
1036 return;
1037 }
1038
d62a17ae 1039 /* Interface MTU check */
1040 if (!oi->mtu_ignore && ntohs(dbdesc->ifmtu) != oi->ifmtu) {
ff99e5b6 1041 zlog_warn("VRF %s: I/F %s MTU mismatch (my %d rcvd %d)",
096f7609
IR
1042 oi->interface->vrf->name, oi->interface->name,
1043 oi->ifmtu, ntohs(dbdesc->ifmtu));
d62a17ae 1044 return;
1045 }
1046
1047 if (dbdesc->reserved1 || dbdesc->reserved2) {
f44d0f5e 1048 if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV_HDR))
d62a17ae 1049 zlog_debug(
1050 "Non-0 reserved field in %s's DbDesc, correct",
1051 on->name);
1052 dbdesc->reserved1 = 0;
1053 dbdesc->reserved2 = 0;
1054 }
1055
43855e3d
CS
1056 oi->db_desc_in++;
1057
beadc736 1058 if (ntohl(oh->router_id) < ntohl(oi->area->ospf6->router_id))
d62a17ae 1059 ospf6_dbdesc_recv_master(oh, on);
beadc736 1060 else if (ntohl(oi->area->ospf6->router_id) < ntohl(oh->router_id))
d62a17ae 1061 ospf6_dbdesc_recv_slave(oh, on);
1062 else {
f44d0f5e 1063 if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV_HDR))
d62a17ae 1064 zlog_debug("Can't decide which is master, ignore");
1065 }
718e3744 1066}
1067
d62a17ae 1068static void ospf6_lsreq_recv(struct in6_addr *src, struct in6_addr *dst,
1069 struct ospf6_interface *oi,
1070 struct ospf6_header *oh)
718e3744 1071{
d62a17ae 1072 struct ospf6_neighbor *on;
1073 char *p;
1074 struct ospf6_lsreq_entry *e;
1075 struct ospf6_lsdb *lsdb = NULL;
1076 struct ospf6_lsa *lsa;
1077
1078 on = ospf6_neighbor_lookup(oh->router_id, oi);
1079 if (on == NULL) {
f44d0f5e 1080 if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV_HDR))
d62a17ae 1081 zlog_debug("Neighbor not found, ignore");
1082 return;
1083 }
1084
1085 if (on->state != OSPF6_NEIGHBOR_EXCHANGE
1086 && on->state != OSPF6_NEIGHBOR_LOADING
1087 && on->state != OSPF6_NEIGHBOR_FULL) {
f44d0f5e 1088 if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV_HDR))
d62a17ae 1089 zlog_debug("Neighbor state less than Exchange, ignore");
1090 return;
1091 }
1092
43855e3d
CS
1093 oi->ls_req_in++;
1094
d62a17ae 1095 /* Process each request */
1096 for (p = (char *)((caddr_t)oh + sizeof(struct ospf6_header));
1097 p + sizeof(struct ospf6_lsreq_entry) <= OSPF6_MESSAGE_END(oh);
1098 p += sizeof(struct ospf6_lsreq_entry)) {
1099 e = (struct ospf6_lsreq_entry *)p;
1100
1101 switch (OSPF6_LSA_SCOPE(e->type)) {
1102 case OSPF6_SCOPE_LINKLOCAL:
1103 lsdb = on->ospf6_if->lsdb;
1104 break;
1105 case OSPF6_SCOPE_AREA:
1106 lsdb = on->ospf6_if->area->lsdb;
1107 break;
1108 case OSPF6_SCOPE_AS:
1109 lsdb = on->ospf6_if->area->ospf6->lsdb;
1110 break;
1111 default:
1112 if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV))
1113 zlog_debug("Ignoring LSA of reserved scope");
1114 continue;
d62a17ae 1115 }
1116
1117 /* Find database copy */
1118 lsa = ospf6_lsdb_lookup(e->type, e->id, e->adv_router, lsdb);
1119 if (lsa == NULL) {
1b1f7b4f 1120 zlog_warn(
1121 "Can't find requested lsa [%s Id:%pI4 Adv:%pI4] send badLSReq",
1122 ospf6_lstype_name(e->type), &e->id,
1123 &e->adv_router);
d62a17ae 1124 thread_add_event(master, bad_lsreq, on, 0, NULL);
1125 return;
1126 }
1127
1128 ospf6_lsdb_add(ospf6_lsa_copy(lsa), on->lsupdate_list);
1129 }
1130
1131 assert(p == OSPF6_MESSAGE_END(oh));
1132
1133 /* schedule send lsupdate */
1134 THREAD_OFF(on->thread_send_lsupdate);
1135 thread_add_event(master, ospf6_lsupdate_send_neighbor, on, 0,
1136 &on->thread_send_lsupdate);
718e3744 1137}
1138
abc7ef44
DO
1139/* Verify, that the specified memory area contains exactly N valid IPv6
1140 prefixes as specified by RFC5340, A.4.1. */
d62a17ae 1141static unsigned ospf6_prefixes_examin(
1142 struct ospf6_prefix *current, /* start of buffer */
1143 unsigned length,
d7c0a89a 1144 const uint32_t req_num_pfxs /* always compared with the actual number
d62a17ae 1145 of prefixes */
d7c0a89a 1146)
abc7ef44 1147{
d7c0a89a
QY
1148 uint8_t requested_pfx_bytes;
1149 uint32_t real_num_pfxs = 0;
d62a17ae 1150
1151 while (length) {
1152 if (length < OSPF6_PREFIX_MIN_SIZE) {
1b1f7b4f 1153 zlog_warn("%s: undersized IPv6 prefix header",
1154 __func__);
d62a17ae 1155 return MSG_NG;
1156 }
1157 /* safe to look deeper */
1158 if (current->prefix_length > IPV6_MAX_BITLEN) {
1b1f7b4f 1159 zlog_warn("%s: invalid PrefixLength (%u bits)",
1160 __func__, current->prefix_length);
d62a17ae 1161 return MSG_NG;
1162 }
1163 /* covers both fixed- and variable-sized fields */
1164 requested_pfx_bytes =
1165 OSPF6_PREFIX_MIN_SIZE
1166 + OSPF6_PREFIX_SPACE(current->prefix_length);
1167 if (requested_pfx_bytes > length) {
1b1f7b4f 1168 zlog_warn("%s: undersized IPv6 prefix", __func__);
d62a17ae 1169 return MSG_NG;
1170 }
1171 /* next prefix */
1172 length -= requested_pfx_bytes;
1173 current = (struct ospf6_prefix *)((caddr_t)current
1174 + requested_pfx_bytes);
1175 real_num_pfxs++;
1176 }
1177 if (real_num_pfxs != req_num_pfxs) {
1b1f7b4f 1178 zlog_warn(
1179 "%s: IPv6 prefix number mismatch (%u required, %u real)",
1180 __func__, req_num_pfxs, real_num_pfxs);
d62a17ae 1181 return MSG_NG;
1182 }
1183 return MSG_OK;
abc7ef44
DO
1184}
1185
1186/* Verify an LSA to have a valid length and dispatch further (where
1187 appropriate) to check if the contents, including nested IPv6 prefixes,
1188 is properly sized/aligned within the LSA. Note that this function gets
1189 LSA type in network byte order, uses in host byte order and passes to
1190 ospf6_lstype_name() in network byte order again. */
d62a17ae 1191static unsigned ospf6_lsa_examin(struct ospf6_lsa_header *lsah,
d7c0a89a
QY
1192 const uint16_t lsalen,
1193 const uint8_t headeronly)
abc7ef44 1194{
d62a17ae 1195 struct ospf6_intra_prefix_lsa *intra_prefix_lsa;
1196 struct ospf6_as_external_lsa *as_external_lsa;
1197 struct ospf6_link_lsa *link_lsa;
1198 unsigned exp_length;
d7c0a89a
QY
1199 uint8_t ltindex;
1200 uint16_t lsatype;
d62a17ae 1201
1202 /* In case an additional minimum length constraint is defined for
1203 current
1204 LSA type, make sure that this constraint is met. */
1205 lsatype = ntohs(lsah->type);
1206 ltindex = lsatype & OSPF6_LSTYPE_FCODE_MASK;
1207 if (ltindex < OSPF6_LSTYPE_SIZE && ospf6_lsa_minlen[ltindex]
1208 && lsalen < ospf6_lsa_minlen[ltindex] + OSPF6_LSA_HEADER_SIZE) {
1b1f7b4f 1209 zlog_warn("%s: undersized (%u B) LSA", __func__, lsalen);
d62a17ae 1210 return MSG_NG;
1211 }
1212 switch (lsatype) {
1213 case OSPF6_LSTYPE_ROUTER:
1214 /* RFC5340 A.4.3, LSA header + OSPF6_ROUTER_LSA_MIN_SIZE bytes
1215 followed
1216 by N>=0 interface descriptions. */
1217 if ((lsalen - OSPF6_LSA_HEADER_SIZE - OSPF6_ROUTER_LSA_MIN_SIZE)
1218 % OSPF6_ROUTER_LSDESC_FIX_SIZE) {
1b1f7b4f 1219 zlog_warn(
1220 "%s: Router LSA interface description alignment error",
1221 __func__);
d62a17ae 1222 return MSG_NG;
1223 }
1224 break;
1225 case OSPF6_LSTYPE_NETWORK:
1226 /* RFC5340 A.4.4, LSA header + OSPF6_NETWORK_LSA_MIN_SIZE bytes
1227 followed by N>=0 attached router descriptions. */
1228 if ((lsalen - OSPF6_LSA_HEADER_SIZE
1229 - OSPF6_NETWORK_LSA_MIN_SIZE)
1230 % OSPF6_NETWORK_LSDESC_FIX_SIZE) {
1b1f7b4f 1231 zlog_warn(
1232 "%s: Network LSA router description alignment error",
1233 __func__);
d62a17ae 1234 return MSG_NG;
1235 }
1236 break;
1237 case OSPF6_LSTYPE_INTER_PREFIX:
1238 /* RFC5340 A.4.5, LSA header + OSPF6_INTER_PREFIX_LSA_MIN_SIZE
1239 bytes
1240 followed by 3-4 fields of a single IPv6 prefix. */
1241 if (headeronly)
1242 break;
1243 return ospf6_prefixes_examin(
1244 (struct ospf6_prefix
1245 *)((caddr_t)lsah + OSPF6_LSA_HEADER_SIZE
1246 + OSPF6_INTER_PREFIX_LSA_MIN_SIZE),
1247 lsalen - OSPF6_LSA_HEADER_SIZE
1248 - OSPF6_INTER_PREFIX_LSA_MIN_SIZE,
1249 1);
1250 case OSPF6_LSTYPE_INTER_ROUTER:
1251 /* RFC5340 A.4.6, fixed-size LSA. */
1252 if (lsalen
1253 > OSPF6_LSA_HEADER_SIZE + OSPF6_INTER_ROUTER_LSA_FIX_SIZE) {
1b1f7b4f 1254 zlog_warn("%s: Inter Router LSA oversized (%u B) LSA",
1255 __func__, lsalen);
d62a17ae 1256 return MSG_NG;
1257 }
1258 break;
1259 case OSPF6_LSTYPE_AS_EXTERNAL: /* RFC5340 A.4.7, same as A.4.8. */
1260 case OSPF6_LSTYPE_TYPE_7:
1261 /* RFC5340 A.4.8, LSA header + OSPF6_AS_EXTERNAL_LSA_MIN_SIZE
1262 bytes
1263 followed by 3-4 fields of IPv6 prefix and 3 conditional LSA
1264 fields:
1265 16 bytes of forwarding address, 4 bytes of external route
1266 tag,
1267 4 bytes of referenced link state ID. */
1268 if (headeronly)
1269 break;
1270 as_external_lsa =
1271 (struct ospf6_as_external_lsa
1272 *)((caddr_t)lsah + OSPF6_LSA_HEADER_SIZE);
1273 exp_length =
1274 OSPF6_LSA_HEADER_SIZE + OSPF6_AS_EXTERNAL_LSA_MIN_SIZE;
1275 /* To find out if the last optional field (Referenced Link State
1276 ID) is
1277 assumed in this LSA, we need to access fixed fields of the
1278 IPv6
1279 prefix before ospf6_prefix_examin() confirms its sizing. */
1280 if (exp_length + OSPF6_PREFIX_MIN_SIZE > lsalen) {
1b1f7b4f 1281 zlog_warn(
1282 "%s: AS External undersized (%u B) LSA header",
1283 __func__, lsalen);
d62a17ae 1284 return MSG_NG;
1285 }
1286 /* forwarding address */
1287 if (CHECK_FLAG(as_external_lsa->bits_metric, OSPF6_ASBR_BIT_F))
1288 exp_length += 16;
1289 /* external route tag */
1290 if (CHECK_FLAG(as_external_lsa->bits_metric, OSPF6_ASBR_BIT_T))
1291 exp_length += 4;
1292 /* referenced link state ID */
1293 if (as_external_lsa->prefix.u._prefix_referenced_lstype)
1294 exp_length += 4;
1295 /* All the fixed-size fields (mandatory and optional) must fit.
1296 I.e.,
1297 this check does not include any IPv6 prefix fields. */
1298 if (exp_length > lsalen) {
1b1f7b4f 1299 zlog_warn(
1300 "%s: AS External undersized (%u B) LSA header",
1301 __func__, lsalen);
d62a17ae 1302 return MSG_NG;
1303 }
1304 /* The last call completely covers the remainder (IPv6 prefix).
1305 */
1306 return ospf6_prefixes_examin(
1307 (struct ospf6_prefix
1308 *)((caddr_t)as_external_lsa
1309 + OSPF6_AS_EXTERNAL_LSA_MIN_SIZE),
1310 lsalen - exp_length, 1);
1311 case OSPF6_LSTYPE_LINK:
1312 /* RFC5340 A.4.9, LSA header + OSPF6_LINK_LSA_MIN_SIZE bytes
1313 followed
1314 by N>=0 IPv6 prefix blocks (with N declared beforehand). */
1315 if (headeronly)
1316 break;
1317 link_lsa = (struct ospf6_link_lsa *)((caddr_t)lsah
1318 + OSPF6_LSA_HEADER_SIZE);
1319 return ospf6_prefixes_examin(
1320 (struct ospf6_prefix *)((caddr_t)link_lsa
1321 + OSPF6_LINK_LSA_MIN_SIZE),
1322 lsalen - OSPF6_LSA_HEADER_SIZE
1323 - OSPF6_LINK_LSA_MIN_SIZE,
1324 ntohl(link_lsa->prefix_num) /* 32 bits */
9d303b37 1325 );
d62a17ae 1326 case OSPF6_LSTYPE_INTRA_PREFIX:
1327 /* RFC5340 A.4.10, LSA header + OSPF6_INTRA_PREFIX_LSA_MIN_SIZE
1328 bytes
1329 followed by N>=0 IPv6 prefixes (with N declared beforehand).
1330 */
1331 if (headeronly)
1332 break;
1333 intra_prefix_lsa =
1334 (struct ospf6_intra_prefix_lsa
1335 *)((caddr_t)lsah + OSPF6_LSA_HEADER_SIZE);
1336 return ospf6_prefixes_examin(
1337 (struct ospf6_prefix
1338 *)((caddr_t)intra_prefix_lsa
1339 + OSPF6_INTRA_PREFIX_LSA_MIN_SIZE),
1340 lsalen - OSPF6_LSA_HEADER_SIZE
1341 - OSPF6_INTRA_PREFIX_LSA_MIN_SIZE,
1342 ntohs(intra_prefix_lsa->prefix_num) /* 16 bits */
0d1753a7 1343 );
1344 case OSPF6_LSTYPE_GRACE_LSA:
1345 if (lsalen < OSPF6_LSA_HEADER_SIZE + GRACE_PERIOD_TLV_SIZE
1346 + GRACE_RESTART_REASON_TLV_SIZE) {
0fc3e113 1347 if (IS_DEBUG_OSPF6_GR)
0d1753a7 1348 zlog_debug("%s: Undersized GraceLSA.",
1349 __func__);
1350 return MSG_NG;
1351 }
d62a17ae 1352 }
1353 /* No additional validation is possible for unknown LSA types, which are
1354 themselves valid in OPSFv3, hence the default decision is to accept.
1355 */
1356 return MSG_OK;
abc7ef44
DO
1357}
1358
1359/* Verify if the provided input buffer is a valid sequence of LSAs. This
1360 includes verification of LSA blocks length/alignment and dispatching
1361 of deeper-level checks. */
1362static unsigned
d62a17ae 1363ospf6_lsaseq_examin(struct ospf6_lsa_header *lsah, /* start of buffered data */
d7c0a89a 1364 size_t length, const uint8_t headeronly,
d62a17ae 1365 /* When declared_num_lsas is not 0, compare it to the real
1366 number of LSAs
1367 and treat the difference as an error. */
d7c0a89a 1368 const uint32_t declared_num_lsas)
abc7ef44 1369{
d7c0a89a 1370 uint32_t counted_lsas = 0;
d62a17ae 1371
1372 while (length) {
d7c0a89a 1373 uint16_t lsalen;
d62a17ae 1374 if (length < OSPF6_LSA_HEADER_SIZE) {
1b1f7b4f 1375 zlog_warn(
1376 "%s: undersized (%zu B) trailing (#%u) LSA header",
1377 __func__, length, counted_lsas);
d62a17ae 1378 return MSG_NG;
1379 }
1380 /* save on ntohs() calls here and in the LSA validator */
1381 lsalen = OSPF6_LSA_SIZE(lsah);
1382 if (lsalen < OSPF6_LSA_HEADER_SIZE) {
1b1f7b4f 1383 zlog_warn(
1384 "%s: malformed LSA header #%u, declared length is %u B",
1385 __func__, counted_lsas, lsalen);
d62a17ae 1386 return MSG_NG;
1387 }
1388 if (headeronly) {
1389 /* less checks here and in ospf6_lsa_examin() */
1390 if (MSG_OK != ospf6_lsa_examin(lsah, lsalen, 1)) {
1b1f7b4f 1391 zlog_warn(
1392 "%s: anomaly in header-only %s LSA #%u",
1393 __func__, ospf6_lstype_name(lsah->type),
1394 counted_lsas);
d62a17ae 1395 return MSG_NG;
1396 }
1397 lsah = (struct ospf6_lsa_header
1398 *)((caddr_t)lsah
1399 + OSPF6_LSA_HEADER_SIZE);
1400 length -= OSPF6_LSA_HEADER_SIZE;
1401 } else {
1402 /* make sure the input buffer is deep enough before
1403 * further checks */
1404 if (lsalen > length) {
1b1f7b4f 1405 zlog_warn(
1406 "%s: anomaly in %s LSA #%u: declared length is %u B, buffered length is %zu B",
1407 __func__, ospf6_lstype_name(lsah->type),
1408 counted_lsas, lsalen, length);
d62a17ae 1409 return MSG_NG;
1410 }
1411 if (MSG_OK != ospf6_lsa_examin(lsah, lsalen, 0)) {
1b1f7b4f 1412 zlog_warn("%s: anomaly in %s LSA #%u", __func__,
1413 ospf6_lstype_name(lsah->type),
1414 counted_lsas);
d62a17ae 1415 return MSG_NG;
1416 }
1417 lsah = (struct ospf6_lsa_header *)((caddr_t)lsah
1418 + lsalen);
1419 length -= lsalen;
1420 }
1421 counted_lsas++;
1422 }
1423
1424 if (declared_num_lsas && counted_lsas != declared_num_lsas) {
1b1f7b4f 1425 zlog_warn("%s: #LSAs declared (%u) does not match actual (%u)",
1426 __func__, declared_num_lsas, counted_lsas);
d62a17ae 1427 return MSG_NG;
1428 }
1429 return MSG_OK;
abc7ef44
DO
1430}
1431
1432/* Verify a complete OSPF packet for proper sizing/alignment. */
d62a17ae 1433static unsigned ospf6_packet_examin(struct ospf6_header *oh,
1434 const unsigned bytesonwire)
abc7ef44 1435{
d62a17ae 1436 struct ospf6_lsupdate *lsupd;
1437 unsigned test;
1438
1439 /* length, 1st approximation */
1440 if (bytesonwire < OSPF6_HEADER_SIZE) {
1b1f7b4f 1441 zlog_warn("%s: undersized (%u B) packet", __func__,
1442 bytesonwire);
d62a17ae 1443 return MSG_NG;
1444 }
6cb85350 1445
d62a17ae 1446 /* Now it is safe to access header fields. */
1447 if (bytesonwire != ntohs(oh->length)) {
1b1f7b4f 1448 zlog_warn("%s: %s packet length error (%u real, %u declared)",
6cb85350
AR
1449 __func__, ospf6_message_type(oh->type), bytesonwire,
1450 ntohs(oh->length));
d62a17ae 1451 return MSG_NG;
1452 }
6cb85350 1453
d62a17ae 1454 /* version check */
1455 if (oh->version != OSPFV3_VERSION) {
1b1f7b4f 1456 zlog_warn("%s: invalid (%u) protocol version", __func__,
1457 oh->version);
d62a17ae 1458 return MSG_NG;
1459 }
1460 /* length, 2nd approximation */
1461 if (oh->type < OSPF6_MESSAGE_TYPE_ALL && ospf6_packet_minlen[oh->type]
1462 && bytesonwire
1463 < OSPF6_HEADER_SIZE + ospf6_packet_minlen[oh->type]) {
1b1f7b4f 1464 zlog_warn("%s: undersized (%u B) %s packet", __func__,
6cb85350 1465 bytesonwire, ospf6_message_type(oh->type));
d62a17ae 1466 return MSG_NG;
1467 }
1468 /* type-specific deeper validation */
1469 switch (oh->type) {
1470 case OSPF6_MESSAGE_TYPE_HELLO:
1471 /* RFC5340 A.3.2, packet header + OSPF6_HELLO_MIN_SIZE bytes
1472 followed
1473 by N>=0 router-IDs. */
1474 if (0
1475 == (bytesonwire - OSPF6_HEADER_SIZE - OSPF6_HELLO_MIN_SIZE)
1476 % 4)
1477 return MSG_OK;
1b1f7b4f 1478 zlog_warn("%s: alignment error in %s packet", __func__,
6cb85350 1479 ospf6_message_type(oh->type));
d62a17ae 1480 return MSG_NG;
1481 case OSPF6_MESSAGE_TYPE_DBDESC:
1482 /* RFC5340 A.3.3, packet header + OSPF6_DB_DESC_MIN_SIZE bytes
1483 followed
1484 by N>=0 header-only LSAs. */
1485 test = ospf6_lsaseq_examin(
1486 (struct ospf6_lsa_header *)((caddr_t)oh
1487 + OSPF6_HEADER_SIZE
1488 + OSPF6_DB_DESC_MIN_SIZE),
1489 bytesonwire - OSPF6_HEADER_SIZE
1490 - OSPF6_DB_DESC_MIN_SIZE,
1491 1, 0);
1492 break;
1493 case OSPF6_MESSAGE_TYPE_LSREQ:
1494 /* RFC5340 A.3.4, packet header + N>=0 LS description blocks. */
1495 if (0
1496 == (bytesonwire - OSPF6_HEADER_SIZE - OSPF6_LS_REQ_MIN_SIZE)
1497 % OSPF6_LSREQ_LSDESC_FIX_SIZE)
1498 return MSG_OK;
1b1f7b4f 1499 zlog_warn("%s: alignment error in %s packet", __func__,
6cb85350 1500 ospf6_message_type(oh->type));
d62a17ae 1501 return MSG_NG;
1502 case OSPF6_MESSAGE_TYPE_LSUPDATE:
1503 /* RFC5340 A.3.5, packet header + OSPF6_LS_UPD_MIN_SIZE bytes
1504 followed
1505 by N>=0 full LSAs (with N declared beforehand). */
1506 lsupd = (struct ospf6_lsupdate *)((caddr_t)oh
1507 + OSPF6_HEADER_SIZE);
1508 test = ospf6_lsaseq_examin(
1509 (struct ospf6_lsa_header *)((caddr_t)lsupd
1510 + OSPF6_LS_UPD_MIN_SIZE),
1511 bytesonwire - OSPF6_HEADER_SIZE - OSPF6_LS_UPD_MIN_SIZE,
1512 0, ntohl(lsupd->lsa_number) /* 32 bits */
9d303b37 1513 );
d62a17ae 1514 break;
1515 case OSPF6_MESSAGE_TYPE_LSACK:
1516 /* RFC5340 A.3.6, packet header + N>=0 header-only LSAs. */
1517 test = ospf6_lsaseq_examin(
1518 (struct ospf6_lsa_header *)((caddr_t)oh
1519 + OSPF6_HEADER_SIZE
1520 + OSPF6_LS_ACK_MIN_SIZE),
1521 bytesonwire - OSPF6_HEADER_SIZE - OSPF6_LS_ACK_MIN_SIZE,
1522 1, 0);
1523 break;
1524 default:
1b1f7b4f 1525 zlog_warn("%s: invalid (%u) message type", __func__, oh->type);
d62a17ae 1526 return MSG_NG;
1527 }
1b1f7b4f 1528 if (test != MSG_OK)
1529 zlog_warn("%s: anomaly in %s packet", __func__,
6cb85350 1530 ospf6_message_type(oh->type));
d62a17ae 1531 return test;
abc7ef44
DO
1532}
1533
1534/* Verify particular fields of otherwise correct received OSPF packet to
1535 meet the requirements of RFC. */
d62a17ae 1536static int ospf6_rxpacket_examin(struct ospf6_interface *oi,
1537 struct ospf6_header *oh,
1538 const unsigned bytesonwire)
abc7ef44 1539{
d62a17ae 1540
1541 if (MSG_OK != ospf6_packet_examin(oh, bytesonwire))
1542 return MSG_NG;
1543
1544 /* Area-ID check */
1545 if (oh->area_id != oi->area->area_id) {
ff99e5b6 1546 if (oh->area_id == OSPF_AREA_BACKBONE)
1547 zlog_warn(
1548 "VRF %s: I/F %s Message may be via Virtual Link: not supported",
096f7609 1549 oi->interface->vrf->name, oi->interface->name);
ff99e5b6 1550 else
1551 zlog_warn(
d47b448d 1552 "VRF %s: I/F %s Area-ID mismatch (my %pI4, rcvd %pI4)",
096f7609
IR
1553 oi->interface->vrf->name, oi->interface->name,
1554 &oi->area->area_id, &oh->area_id);
d62a17ae 1555 return MSG_NG;
1556 }
1557
1558 /* Instance-ID check */
1559 if (oh->instance_id != oi->instance_id) {
ff99e5b6 1560 zlog_warn(
1561 "VRF %s: I/F %s Instance-ID mismatch (my %u, rcvd %u)",
096f7609
IR
1562 oi->interface->vrf->name, oi->interface->name,
1563 oi->instance_id, oh->instance_id);
d62a17ae 1564 return MSG_NG;
1565 }
1566
1567 /* Router-ID check */
1568 if (oh->router_id == oi->area->ospf6->router_id) {
d47b448d 1569 zlog_warn("VRF %s: I/F %s Duplicate Router-ID (%pI4)",
096f7609
IR
1570 oi->interface->vrf->name, oi->interface->name,
1571 &oh->router_id);
d62a17ae 1572 return MSG_NG;
1573 }
1574 return MSG_OK;
abc7ef44
DO
1575}
1576
d62a17ae 1577static void ospf6_lsupdate_recv(struct in6_addr *src, struct in6_addr *dst,
1578 struct ospf6_interface *oi,
1579 struct ospf6_header *oh)
718e3744 1580{
d62a17ae 1581 struct ospf6_neighbor *on;
1582 struct ospf6_lsupdate *lsupdate;
1583 char *p;
1584
1585 on = ospf6_neighbor_lookup(oh->router_id, oi);
1586 if (on == NULL) {
f44d0f5e 1587 if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV_HDR))
d62a17ae 1588 zlog_debug("Neighbor not found, ignore");
1589 return;
1590 }
1591
1592 if (on->state != OSPF6_NEIGHBOR_EXCHANGE
1593 && on->state != OSPF6_NEIGHBOR_LOADING
1594 && on->state != OSPF6_NEIGHBOR_FULL) {
f44d0f5e 1595 if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV_HDR))
d62a17ae 1596 zlog_debug("Neighbor state less than Exchange, ignore");
1597 return;
1598 }
1599
1600 lsupdate = (struct ospf6_lsupdate *)((caddr_t)oh
1601 + sizeof(struct ospf6_header));
718e3744 1602
43855e3d
CS
1603 oi->ls_upd_in++;
1604
d62a17ae 1605 /* Process LSAs */
1606 for (p = (char *)((caddr_t)lsupdate + sizeof(struct ospf6_lsupdate));
1607 p < OSPF6_MESSAGE_END(oh)
1608 && p + OSPF6_LSA_SIZE(p) <= OSPF6_MESSAGE_END(oh);
1609 p += OSPF6_LSA_SIZE(p)) {
1610 ospf6_receive_lsa(on, (struct ospf6_lsa_header *)p);
1611 }
1612
1613 assert(p == OSPF6_MESSAGE_END(oh));
508e53e2 1614}
1615
d62a17ae 1616static void ospf6_lsack_recv(struct in6_addr *src, struct in6_addr *dst,
1617 struct ospf6_interface *oi,
1618 struct ospf6_header *oh)
508e53e2 1619{
d62a17ae 1620 struct ospf6_neighbor *on;
1621 char *p;
1622 struct ospf6_lsa *his, *mine;
1623 struct ospf6_lsdb *lsdb = NULL;
1624
1625 assert(oh->type == OSPF6_MESSAGE_TYPE_LSACK);
1626
1627 on = ospf6_neighbor_lookup(oh->router_id, oi);
1628 if (on == NULL) {
f44d0f5e 1629 if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV_HDR))
d62a17ae 1630 zlog_debug("Neighbor not found, ignore");
1631 return;
1632 }
1633
1634 if (on->state != OSPF6_NEIGHBOR_EXCHANGE
1635 && on->state != OSPF6_NEIGHBOR_LOADING
1636 && on->state != OSPF6_NEIGHBOR_FULL) {
f44d0f5e 1637 if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV_HDR))
d62a17ae 1638 zlog_debug("Neighbor state less than Exchange, ignore");
1639 return;
1640 }
1641
43855e3d
CS
1642 oi->ls_ack_in++;
1643
d62a17ae 1644 for (p = (char *)((caddr_t)oh + sizeof(struct ospf6_header));
1645 p + sizeof(struct ospf6_lsa_header) <= OSPF6_MESSAGE_END(oh);
1646 p += sizeof(struct ospf6_lsa_header)) {
1647 his = ospf6_lsa_create_headeronly((struct ospf6_lsa_header *)p);
1648
1649 switch (OSPF6_LSA_SCOPE(his->header->type)) {
1650 case OSPF6_SCOPE_LINKLOCAL:
1651 lsdb = on->ospf6_if->lsdb;
1652 break;
1653 case OSPF6_SCOPE_AREA:
1654 lsdb = on->ospf6_if->area->lsdb;
1655 break;
1656 case OSPF6_SCOPE_AS:
1657 lsdb = on->ospf6_if->area->ospf6->lsdb;
1658 break;
1659 case OSPF6_SCOPE_RESERVED:
1660 if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV))
1661 zlog_debug("Ignoring LSA of reserved scope");
1662 ospf6_lsa_delete(his);
1663 continue;
d62a17ae 1664 }
1665
1666 if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV))
1667 zlog_debug("%s acknowledged by %s", his->name,
1668 on->name);
1669
1670 /* Find database copy */
1671 mine = ospf6_lsdb_lookup(his->header->type, his->header->id,
1672 his->header->adv_router, lsdb);
1673 if (mine == NULL) {
1674 if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV))
1675 zlog_debug("No database copy");
1676 ospf6_lsa_delete(his);
1677 continue;
1678 }
1679
1680 /* Check if the LSA is on his retrans-list */
1681 mine = ospf6_lsdb_lookup(his->header->type, his->header->id,
1682 his->header->adv_router,
1683 on->retrans_list);
1684 if (mine == NULL) {
1685 if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV))
1686 zlog_debug("Not on %s's retrans-list",
1687 on->name);
1688 ospf6_lsa_delete(his);
1689 continue;
1690 }
1691
1692 if (ospf6_lsa_compare(his, mine) != 0) {
1693 /* Log this questionable acknowledgement,
1694 and examine the next one. */
1695 if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV))
1696 zlog_debug("Questionable acknowledgement");
1697 ospf6_lsa_delete(his);
1698 continue;
1699 }
1700
1701 if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV))
1702 zlog_debug(
1703 "Acknowledged, remove from %s's retrans-list",
1704 on->name);
1705
1706 ospf6_decrement_retrans_count(mine);
1707 if (OSPF6_LSA_IS_MAXAGE(mine))
1708 ospf6_maxage_remove(on->ospf6_if->area->ospf6);
1709 ospf6_lsdb_remove(mine, on->retrans_list);
1710 ospf6_lsa_delete(his);
1711 }
1712
1713 assert(p == OSPF6_MESSAGE_END(oh));
508e53e2 1714}
1715
d7c0a89a
QY
1716static uint8_t *recvbuf = NULL;
1717static uint8_t *sendbuf = NULL;
6ac29a51 1718static unsigned int iobuflen = 0;
3b4cd3a9 1719
d62a17ae 1720int ospf6_iobuf_size(unsigned int size)
3b4cd3a9 1721{
c047b506
DL
1722 /* NB: there was previously code here that tried to dynamically size
1723 * the buffer for whatever we see in MTU on interfaces. Which is
1724 * _unconditionally wrong_ - we can always receive fragmented IPv6
1725 * up to the regular 64k length limit. (No jumbograms, thankfully.)
1726 */
d62a17ae 1727
c047b506
DL
1728 if (!iobuflen) {
1729 /* the + 128 is to have some runway at the end */
1730 size_t alloc_size = 65536 + 128;
d62a17ae 1731
c047b506 1732 assert(!recvbuf && !sendbuf);
d62a17ae 1733
c047b506
DL
1734 recvbuf = XMALLOC(MTYPE_OSPF6_MESSAGE, alloc_size);
1735 sendbuf = XMALLOC(MTYPE_OSPF6_MESSAGE, alloc_size);
1736 iobuflen = alloc_size;
1737 }
d62a17ae 1738
1739 return iobuflen;
3b4cd3a9 1740}
508e53e2 1741
d62a17ae 1742void ospf6_message_terminate(void)
ae2254aa 1743{
e1b36e13
QY
1744 XFREE(MTYPE_OSPF6_MESSAGE, recvbuf);
1745 XFREE(MTYPE_OSPF6_MESSAGE, sendbuf);
d62a17ae 1746
1747 iobuflen = 0;
ae2254aa
TG
1748}
1749
aa6a96ba
PR
1750enum ospf6_read_return_enum {
1751 OSPF6_READ_ERROR,
1752 OSPF6_READ_CONTINUE,
1753};
1754
ec44732e 1755static int ospf6_read_helper(int sockfd, struct ospf6 *ospf6)
508e53e2 1756{
aa6a96ba 1757 int len;
d62a17ae 1758 struct in6_addr src, dst;
1759 ifindex_t ifindex;
1760 struct iovec iovector[2];
1761 struct ospf6_interface *oi;
1762 struct ospf6_header *oh;
6cb85350
AR
1763 enum ospf6_auth_err ret = OSPF6_AUTH_PROCESS_NORMAL;
1764 uint32_t at_len = 0;
1765 uint32_t lls_len = 0;
d62a17ae 1766
1767 /* initialize */
1768 memset(&src, 0, sizeof(src));
1769 memset(&dst, 0, sizeof(dst));
1770 ifindex = 0;
d62a17ae 1771 iovector[0].iov_base = recvbuf;
1772 iovector[0].iov_len = iobuflen;
1773 iovector[1].iov_base = NULL;
1774 iovector[1].iov_len = 0;
1775
1776 /* receive message */
7df1f362 1777 len = ospf6_recvmsg(&src, &dst, &ifindex, iovector, sockfd);
aa6a96ba
PR
1778 if (len < 0)
1779 return OSPF6_READ_ERROR;
1780
1781 if ((uint)len > iobuflen) {
1c50c1c0 1782 flog_err(EC_LIB_DEVELOPMENT, "Excess message read");
aa6a96ba 1783 return OSPF6_READ_ERROR;
d62a17ae 1784 }
1785
c047b506
DL
1786 /* ensure some zeroes past the end, just as a security precaution */
1787 memset(recvbuf + len, 0, MIN(128, iobuflen - len));
1788
c5d28568 1789 oi = ospf6_interface_lookup_by_ifindex(ifindex, ospf6->vrf_id);
d62a17ae 1790 if (oi == NULL || oi->area == NULL
1791 || CHECK_FLAG(oi->flag, OSPF6_INTERFACE_DISABLE)) {
f44d0f5e 1792 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN,
1793 RECV_HDR))
e4c42d65 1794 zlog_debug("Message received on disabled interface");
aa6a96ba 1795 return OSPF6_READ_CONTINUE;
d62a17ae 1796 }
1797 if (CHECK_FLAG(oi->flag, OSPF6_INTERFACE_PASSIVE)) {
f44d0f5e 1798 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN,
1799 RECV_HDR))
d62a17ae 1800 zlog_debug("%s: Ignore message on passive interface %s",
1801 __func__, oi->interface->name);
aa6a96ba 1802 return OSPF6_READ_CONTINUE;
d62a17ae 1803 }
1804
709bd204
IR
1805 /*
1806 * Drop packet destined to another VRF.
1807 * This happens when raw_l3mdev_accept is set to 1.
1808 */
096f7609 1809 if (ospf6->vrf_id != oi->interface->vrf->vrf_id)
709bd204
IR
1810 return OSPF6_READ_CONTINUE;
1811
d62a17ae 1812 oh = (struct ospf6_header *)recvbuf;
6cb85350
AR
1813 ret = ospf6_auth_validate_pkt(oi, (uint32_t *)&len, oh, &at_len,
1814 &lls_len);
1815 if (ret == OSPF6_AUTH_VALIDATE_SUCCESS) {
1816 ret = ospf6_auth_check_digest(oh, oi, &src, lls_len);
1817 if (ret == OSPF6_AUTH_VALIDATE_FAILURE) {
1818 if (IS_OSPF6_DEBUG_AUTH_RX)
1819 zlog_err(
1820 "RECV[%s]: OSPF packet auth digest miss-match on %s",
1821 oi->interface->name,
1822 ospf6_message_type(oh->type));
1823 oi->at_data.rx_drop++;
1824 return OSPF6_READ_CONTINUE;
1825 }
1826 } else if (ret == OSPF6_AUTH_VALIDATE_FAILURE) {
1827 oi->at_data.rx_drop++;
1828 return OSPF6_READ_CONTINUE;
1829 }
1830
d62a17ae 1831 if (ospf6_rxpacket_examin(oi, oh, len) != MSG_OK)
aa6a96ba 1832 return OSPF6_READ_CONTINUE;
d62a17ae 1833
1834 /* Being here means, that no sizing/alignment issues were detected in
1835 the input packet. This renders the additional checks performed below
1836 and also in the type-specific dispatching functions a dead code,
1837 which can be dismissed in a cleanup-focused review round later. */
1838
1839 /* Log */
f44d0f5e 1840 if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV_HDR)) {
6cb85350 1841 zlog_debug("%s received on %s", ospf6_message_type(oh->type),
d62a17ae 1842 oi->interface->name);
5145a172
DL
1843 zlog_debug(" src: %pI6", &src);
1844 zlog_debug(" dst: %pI6", &dst);
d62a17ae 1845
1846 switch (oh->type) {
1847 case OSPF6_MESSAGE_TYPE_HELLO:
f44d0f5e 1848 ospf6_hello_print(oh, OSPF6_ACTION_RECV);
d62a17ae 1849 break;
1850 case OSPF6_MESSAGE_TYPE_DBDESC:
f44d0f5e 1851 ospf6_dbdesc_print(oh, OSPF6_ACTION_RECV);
d62a17ae 1852 break;
1853 case OSPF6_MESSAGE_TYPE_LSREQ:
f44d0f5e 1854 ospf6_lsreq_print(oh, OSPF6_ACTION_RECV);
d62a17ae 1855 break;
1856 case OSPF6_MESSAGE_TYPE_LSUPDATE:
f44d0f5e 1857 ospf6_lsupdate_print(oh, OSPF6_ACTION_RECV);
d62a17ae 1858 break;
1859 case OSPF6_MESSAGE_TYPE_LSACK:
f44d0f5e 1860 ospf6_lsack_print(oh, OSPF6_ACTION_RECV);
d62a17ae 1861 break;
1862 default:
1863 assert(0);
1864 }
6cb85350
AR
1865
1866 if ((at_len != 0) && IS_OSPF6_DEBUG_AUTH_RX)
1867 ospf6_auth_hdr_dump_recv(oh, (len + at_len + lls_len),
1868 lls_len);
d62a17ae 1869 }
1870
1871 switch (oh->type) {
1872 case OSPF6_MESSAGE_TYPE_HELLO:
1873 ospf6_hello_recv(&src, &dst, oi, oh);
1874 break;
1875
1876 case OSPF6_MESSAGE_TYPE_DBDESC:
1877 ospf6_dbdesc_recv(&src, &dst, oi, oh);
1878 break;
1879
1880 case OSPF6_MESSAGE_TYPE_LSREQ:
1881 ospf6_lsreq_recv(&src, &dst, oi, oh);
1882 break;
1883
1884 case OSPF6_MESSAGE_TYPE_LSUPDATE:
1885 ospf6_lsupdate_recv(&src, &dst, oi, oh);
1886 break;
1887
1888 case OSPF6_MESSAGE_TYPE_LSACK:
1889 ospf6_lsack_recv(&src, &dst, oi, oh);
1890 break;
1891
1892 default:
1893 assert(0);
1894 }
1895
aa6a96ba 1896 return OSPF6_READ_CONTINUE;
718e3744 1897}
1898
cc9f21da 1899void ospf6_receive(struct thread *thread)
ec44732e
PR
1900{
1901 int sockfd;
1902 struct ospf6 *ospf6;
aa6a96ba 1903 int count = 0;
ec44732e
PR
1904
1905 /* add next read thread */
1906 ospf6 = THREAD_ARG(thread);
1907 sockfd = THREAD_FD(thread);
1908
1909 thread_add_read(master, ospf6_receive, ospf6, ospf6->fd,
1910 &ospf6->t_ospf6_receive);
1911
78156066 1912 while (count < ospf6->write_oi_count) {
aa6a96ba
PR
1913 count++;
1914 switch (ospf6_read_helper(sockfd, ospf6)) {
1915 case OSPF6_READ_ERROR:
cc9f21da 1916 return;
aa6a96ba
PR
1917 case OSPF6_READ_CONTINUE:
1918 break;
1919 }
1920 }
718e3744 1921}
1922
6cb85350
AR
1923static void ospf6_fill_hdr_checksum(struct ospf6_interface *oi,
1924 struct ospf6_packet *op)
1925{
1926 struct ipv6_ph ph = {};
1927 struct ospf6_header *oh;
1928 void *offset = NULL;
1929
1930 if (oi->at_data.flags != 0)
1931 return;
1932
1933 memcpy(&ph.src, oi->linklocal_addr, sizeof(struct in6_addr));
1934 memcpy(&ph.dst, &op->dst, sizeof(struct in6_addr));
1935 ph.ulpl = htonl(op->length);
1936 ph.next_hdr = IPPROTO_OSPFIGP;
1937
1938 /* Suppress static analysis warnings about accessing icmp6 oob */
1939 oh = (struct ospf6_header *)STREAM_DATA(op->s);
1940 offset = oh;
1941 oh->checksum = in_cksum_with_ph6(&ph, offset, op->length);
1942}
1943
3d968031
PR
1944static void ospf6_make_header(uint8_t type, struct ospf6_interface *oi,
1945 struct stream *s)
718e3744 1946{
3d968031 1947 struct ospf6_header *oh;
d62a17ae 1948
3d968031
PR
1949 oh = (struct ospf6_header *)STREAM_DATA(s);
1950
1951 oh->version = (uint8_t)OSPFV3_VERSION;
1952 oh->type = type;
9ffafdd7 1953 oh->length = 0;
6cb85350 1954
d62a17ae 1955 oh->router_id = oi->area->ospf6->router_id;
1956 oh->area_id = oi->area->area_id;
9ffafdd7 1957 oh->checksum = 0;
d62a17ae 1958 oh->instance_id = oi->instance_id;
1959 oh->reserved = 0;
9ffafdd7 1960
3d968031
PR
1961 stream_forward_endp(s, OSPF6_HEADER_SIZE);
1962}
d62a17ae 1963
3d968031
PR
1964static void ospf6_fill_header(struct ospf6_interface *oi, struct stream *s,
1965 uint16_t length)
1966{
1967 struct ospf6_header *oh;
1968
1969 oh = (struct ospf6_header *)STREAM_DATA(s);
1970
1971 oh->length = htons(length);
1972}
1973
432b7daf
PR
1974static void ospf6_fill_lsupdate_header(struct stream *s, uint32_t lsa_num)
1975{
1976 struct ospf6_header *oh;
1977 struct ospf6_lsupdate *lsu;
1978
1979 oh = (struct ospf6_header *)STREAM_DATA(s);
1980
1981 lsu = (struct ospf6_lsupdate *)((caddr_t)oh
1982 + sizeof(struct ospf6_header));
1983 lsu->lsa_number = htonl(lsa_num);
1984}
1985
6cb85350
AR
1986static void ospf6_auth_trailer_copy_keychain_key(struct ospf6_interface *oi)
1987{
1988 char *keychain_name = NULL;
1989 struct keychain *keychain = NULL;
1990 struct key *key = NULL;
1991
1992 keychain_name = oi->at_data.keychain;
1993 keychain = keychain_lookup(keychain_name);
1994 if (keychain) {
1995 key = key_lookup_for_send(keychain);
1996 if (key && key->string &&
1997 key->hash_algo != KEYCHAIN_ALGO_NULL) {
1998 /* storing the values so that further
1999 * lookup can be avoided. after
2000 * processing the digest need to reset
2001 * these values
2002 */
2003 oi->at_data.hash_algo = key->hash_algo;
6354d635
DS
2004 if (oi->at_data.auth_key)
2005 XFREE(MTYPE_OSPF6_AUTH_MANUAL_KEY,
2006 oi->at_data.auth_key);
6cb85350
AR
2007 oi->at_data.auth_key = XSTRDUP(
2008 MTYPE_OSPF6_AUTH_MANUAL_KEY, key->string);
2009 oi->at_data.key_id = key->index;
2010 SET_FLAG(oi->at_data.flags,
2011 OSPF6_AUTH_TRAILER_KEYCHAIN_VALID);
2012 }
2013 }
2014}
2015
42bfee18 2016static uint16_t ospf6_packet_max(struct ospf6_interface *oi)
3d968031 2017{
42bfee18 2018 uint16_t at_len = 0;
6cb85350 2019
3d968031 2020 assert(oi->ifmtu > sizeof(struct ip6_hdr));
6cb85350
AR
2021
2022 if (oi->at_data.flags != 0) {
2023 if (CHECK_FLAG(oi->at_data.flags, OSPF6_AUTH_TRAILER_KEYCHAIN))
2024 ospf6_auth_trailer_copy_keychain_key(oi);
2025
2026 at_len += OSPF6_AUTH_HDR_MIN_SIZE;
2027 at_len += keychain_get_hash_len(oi->at_data.hash_algo);
2028 return oi->ifmtu - (sizeof(struct ip6_hdr)) - at_len;
2029 }
2030
3d968031
PR
2031 return oi->ifmtu - (sizeof(struct ip6_hdr));
2032}
2033
2034static uint16_t ospf6_make_hello(struct ospf6_interface *oi, struct stream *s)
2035{
2036 struct listnode *node, *nnode;
2037 struct ospf6_neighbor *on;
2038 uint16_t length = OSPF6_HELLO_MIN_SIZE;
6cb85350
AR
2039 uint8_t options1 = oi->area->options[1];
2040
2041 if (oi->at_data.flags != 0)
2042 options1 |= OSPF6_OPT_AT;
3d968031
PR
2043
2044 stream_putl(s, oi->interface->ifindex);
2045 stream_putc(s, oi->priority);
2046 stream_putc(s, oi->area->options[0]);
6cb85350 2047 stream_putc(s, options1);
3d968031
PR
2048 stream_putc(s, oi->area->options[2]);
2049 stream_putw(s, oi->hello_interval);
2050 stream_putw(s, oi->dead_interval);
2051 stream_put_ipv4(s, oi->drouter);
2052 stream_put_ipv4(s, oi->bdrouter);
d62a17ae 2053
3d968031
PR
2054 for (ALL_LIST_ELEMENTS(oi->neighbor_list, node, nnode, on)) {
2055 if (on->state < OSPF6_NEIGHBOR_INIT)
2056 continue;
2057
2058 if ((length + sizeof(uint32_t) + OSPF6_HEADER_SIZE)
2059 > ospf6_packet_max(oi)) {
2060 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_HELLO,
2061 SEND))
2062 zlog_debug(
2063 "sending Hello message: exceeds I/F MTU");
2064 break;
2065 }
2066
2067 stream_put_ipv4(s, on->router_id);
2068 length += sizeof(uint32_t);
2069 }
2070
2071 return length;
2072}
2073
cc9f21da 2074static void ospf6_write(struct thread *thread)
3d968031
PR
2075{
2076 struct ospf6 *ospf6 = THREAD_ARG(thread);
2077 struct ospf6_interface *oi;
3d968031
PR
2078 struct ospf6_header *oh;
2079 struct ospf6_packet *op;
2080 struct listnode *node;
3d968031
PR
2081 struct iovec iovector[2];
2082 int pkt_count = 0;
2083 int len;
bb382e24
PR
2084 int64_t latency = 0;
2085 struct timeval timestamp;
42bfee18 2086 uint16_t at_len = 0;
3d968031
PR
2087
2088 if (ospf6->fd < 0) {
2089 zlog_warn("ospf6_write failed to send, fd %d", ospf6->fd);
cc9f21da 2090 return;
3d968031
PR
2091 }
2092
2093 node = listhead(ospf6->oi_write_q);
2094 assert(node);
2095 oi = listgetdata(node);
2096
4e5c95be 2097 while ((pkt_count < ospf6->write_oi_count) && oi) {
3d968031
PR
2098 op = ospf6_fifo_head(oi->obuf);
2099 assert(op);
2100 assert(op->length >= OSPF6_HEADER_SIZE);
2101
2102 iovector[0].iov_base = (caddr_t)stream_pnt(op->s);
2103 iovector[0].iov_len = op->length;
2104 iovector[1].iov_base = NULL;
2105 iovector[1].iov_len = 0;
2106
2107 oh = (struct ospf6_header *)STREAM_DATA(op->s);
2108
6cb85350
AR
2109 if (oi->at_data.flags != 0) {
2110 at_len = ospf6_auth_len_get(oi);
2111 if (at_len) {
2112 iovector[0].iov_len =
2113 ntohs(oh->length) + at_len;
2114 ospf6_auth_digest_send(oi->linklocal_addr, oi,
2115 oh, at_len,
2116 iovector[0].iov_len);
2117 } else {
2118 iovector[0].iov_len = ntohs(oh->length);
2119 }
2120 } else {
2121 iovector[0].iov_len = ntohs(oh->length);
2122 }
2123
3d968031
PR
2124 len = ospf6_sendmsg(oi->linklocal_addr, &op->dst,
2125 oi->interface->ifindex, iovector,
2126 ospf6->fd);
6cb85350
AR
2127
2128 if (len != (op->length + (int)at_len))
3d968031
PR
2129 flog_err(EC_LIB_DEVELOPMENT,
2130 "Could not send entire message");
2131
a91f9d69 2132 if (IS_OSPF6_DEBUG_MESSAGE(oh->type, SEND_HDR)) {
3d968031 2133 zlog_debug("%s send on %s",
6cb85350 2134 ospf6_message_type(oh->type),
3d968031 2135 oi->interface->name);
779d9722
PR
2136 zlog_debug(" src: %pI6", oi->linklocal_addr);
2137 zlog_debug(" dst: %pI6", &op->dst);
a91f9d69
PR
2138 switch (oh->type) {
2139 case OSPF6_MESSAGE_TYPE_HELLO:
2140 ospf6_hello_print(oh, OSPF6_ACTION_SEND);
2141 break;
2142 case OSPF6_MESSAGE_TYPE_DBDESC:
2143 ospf6_dbdesc_print(oh, OSPF6_ACTION_SEND);
2144 break;
2145 case OSPF6_MESSAGE_TYPE_LSREQ:
2146 ospf6_lsreq_print(oh, OSPF6_ACTION_SEND);
2147 break;
2148 case OSPF6_MESSAGE_TYPE_LSUPDATE:
2149 ospf6_lsupdate_print(oh, OSPF6_ACTION_SEND);
2150 break;
2151 case OSPF6_MESSAGE_TYPE_LSACK:
2152 ospf6_lsack_print(oh, OSPF6_ACTION_SEND);
2153 break;
2154 default:
2155 zlog_debug("Unknown message");
2156 assert(0);
2157 break;
2158 }
3d968031 2159 }
d62a17ae 2160 switch (oh->type) {
2161 case OSPF6_MESSAGE_TYPE_HELLO:
bb382e24
PR
2162 monotime(&timestamp);
2163 if (oi->hello_out)
2164 latency = monotime_since(&oi->last_hello, NULL)
0dd5ec12
PR
2165 - ((int64_t)oi->hello_interval
2166 * 1000000);
bb382e24
PR
2167
2168 /* log if latency exceeds the hello period */
0dd5ec12 2169 if (latency > ((int64_t)oi->hello_interval * 1000000))
bb382e24
PR
2170 zlog_warn("%s hello TX high latency %" PRId64
2171 "us.",
2172 __func__, latency);
2173 oi->last_hello = timestamp;
3d968031 2174 oi->hello_out++;
d62a17ae 2175 break;
2176 case OSPF6_MESSAGE_TYPE_DBDESC:
3d968031 2177 oi->db_desc_out++;
d62a17ae 2178 break;
2179 case OSPF6_MESSAGE_TYPE_LSREQ:
3d968031 2180 oi->ls_req_out++;
d62a17ae 2181 break;
2182 case OSPF6_MESSAGE_TYPE_LSUPDATE:
3d968031 2183 oi->ls_upd_out++;
d62a17ae 2184 break;
2185 case OSPF6_MESSAGE_TYPE_LSACK:
3d968031 2186 oi->ls_ack_out++;
d62a17ae 2187 break;
2188 default:
2189 zlog_debug("Unknown message");
2190 assert(0);
2191 break;
2192 }
6cb85350
AR
2193
2194 if ((oi->at_data.flags != 0) &&
2195 (IS_OSPF6_DEBUG_MESSAGE(oh->type, SEND_HDR)) &&
2196 (IS_OSPF6_DEBUG_AUTH_TX))
2197 ospf6_auth_hdr_dump_send(oh, iovector[0].iov_len);
2198
2199 /* initialize at_len to 0 for next packet */
2200 at_len = 0;
2201
3d968031
PR
2202 /* Now delete packet from queue. */
2203 ospf6_packet_delete(oi);
2204
2205 /* Move this interface to the tail of write_q to
2206 serve everyone in a round robin fashion */
2207 list_delete_node(ospf6->oi_write_q, node);
2208 if (ospf6_fifo_head(oi->obuf) == NULL) {
2209 oi->on_write_q = 0;
3d968031
PR
2210 oi = NULL;
2211 } else {
2212 listnode_add(ospf6->oi_write_q, oi);
2213 }
d62a17ae 2214
3d968031
PR
2215 /* Setup to service from the head of the queue again */
2216 if (!list_isempty(ospf6->oi_write_q)) {
2217 node = listhead(ospf6->oi_write_q);
2218 oi = listgetdata(node);
2219 }
7df1f362 2220 }
718e3744 2221
3d968031
PR
2222 /* If packets still remain in queue, call write thread. */
2223 if (!list_isempty(ospf6->oi_write_q))
2224 thread_add_write(master, ospf6_write, ospf6, ospf6->fd,
2225 &ospf6->t_write);
681b84e8
DT
2226}
2227
cc9f21da 2228void ospf6_hello_send(struct thread *thread)
718e3744 2229{
d62a17ae 2230 struct ospf6_interface *oi;
3d968031
PR
2231 struct ospf6_packet *op;
2232 uint16_t length = OSPF6_HEADER_SIZE;
d62a17ae 2233
2234 oi = (struct ospf6_interface *)THREAD_ARG(thread);
d62a17ae 2235
2236 if (oi->state <= OSPF6_INTERFACE_DOWN) {
f44d0f5e 2237 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_HELLO, SEND_HDR))
d62a17ae 2238 zlog_debug("Unable to send Hello on down interface %s",
2239 oi->interface->name);
cc9f21da 2240 return;
d62a17ae 2241 }
2242
3d968031 2243 op = ospf6_packet_new(oi->ifmtu);
d62a17ae 2244
3d968031 2245 ospf6_make_header(OSPF6_MESSAGE_TYPE_HELLO, oi, op->s);
d62a17ae 2246
3d968031
PR
2247 /* Prepare OSPF Hello body */
2248 length += ospf6_make_hello(oi, op->s);
2249 if (length == OSPF6_HEADER_SIZE) {
2250 /* Hello overshooting MTU */
2251 ospf6_packet_free(op);
cc9f21da 2252 return;
3d968031 2253 }
d62a17ae 2254
3d968031
PR
2255 /* Fill OSPF header. */
2256 ospf6_fill_header(oi, op->s, length);
d62a17ae 2257
3d968031
PR
2258 /* Set packet length. */
2259 op->length = length;
d62a17ae 2260
3d968031 2261 op->dst = allspfrouters6;
d62a17ae 2262
6cb85350
AR
2263 ospf6_fill_hdr_checksum(oi, op);
2264
3d968031
PR
2265 /* Add packet to the top of the interface output queue, so that they
2266 * can't get delayed by things like long queues of LS Update packets
2267 */
2268 ospf6_packet_add_top(oi, op);
d62a17ae 2269
3d968031
PR
2270 /* set next thread */
2271 thread_add_timer(master, ospf6_hello_send, oi, oi->hello_interval,
2272 &oi->thread_send_hello);
d62a17ae 2273
d6a39b53 2274 OSPF6_MESSAGE_WRITE_ON(oi);
718e3744 2275}
2276
d6a39b53 2277static uint16_t ospf6_make_dbdesc(struct ospf6_neighbor *on, struct stream *s)
718e3744 2278{
d6a39b53 2279 uint16_t length = OSPF6_DB_DESC_MIN_SIZE;
2e37407f 2280 struct ospf6_lsa *lsa, *lsanext;
6cb85350
AR
2281 uint8_t options1 = on->ospf6_if->area->options[1];
2282
2283 if (on->ospf6_if->at_data.flags != 0)
2284 options1 |= OSPF6_OPT_AT;
d62a17ae 2285
2286 /* if this is initial one, initialize sequence number for DbDesc */
2287 if (CHECK_FLAG(on->dbdesc_bits, OSPF6_DBDESC_IBIT)
2288 && (on->dbdesc_seqnum == 0)) {
fce7f209 2289 on->dbdesc_seqnum = frr_sequence32_next();
d62a17ae 2290 }
2291
d6a39b53
PR
2292 /* reserved */
2293 stream_putc(s, 0); /* reserved 1 */
2294 stream_putc(s, on->ospf6_if->area->options[0]);
6cb85350 2295 stream_putc(s, options1);
d6a39b53
PR
2296 stream_putc(s, on->ospf6_if->area->options[2]);
2297 stream_putw(s, on->ospf6_if->ifmtu);
2298 stream_putc(s, 0); /* reserved 2 */
2299 stream_putc(s, on->dbdesc_bits);
2300 stream_putl(s, on->dbdesc_seqnum);
d62a17ae 2301
2302 /* if this is not initial one, set LSA headers in dbdesc */
d62a17ae 2303 if (!CHECK_FLAG(on->dbdesc_bits, OSPF6_DBDESC_IBIT)) {
2e37407f 2304 for (ALL_LSDB(on->dbdesc_list, lsa, lsanext)) {
d62a17ae 2305 ospf6_lsa_age_update_to_send(lsa,
2306 on->ospf6_if->transdelay);
2307
2308 /* MTU check */
d6a39b53
PR
2309 if ((length + sizeof(struct ospf6_lsa_header)
2310 + OSPF6_HEADER_SIZE)
d62a17ae 2311 > ospf6_packet_max(on->ospf6_if)) {
ccf260c4 2312 ospf6_lsa_unlock(lsa);
2313 if (lsanext)
2314 ospf6_lsa_unlock(lsanext);
d62a17ae 2315 break;
2316 }
d6a39b53
PR
2317 stream_put(s, lsa->header,
2318 sizeof(struct ospf6_lsa_header));
2319 length += sizeof(struct ospf6_lsa_header);
d62a17ae 2320 }
2321 }
d6a39b53
PR
2322 return length;
2323}
d62a17ae 2324
cc9f21da 2325void ospf6_dbdesc_send(struct thread *thread)
d6a39b53
PR
2326{
2327 struct ospf6_neighbor *on;
2328 uint16_t length = OSPF6_HEADER_SIZE;
2329 struct ospf6_packet *op;
d62a17ae 2330
d6a39b53 2331 on = (struct ospf6_neighbor *)THREAD_ARG(thread);
d6a39b53
PR
2332
2333 if (on->state < OSPF6_NEIGHBOR_EXSTART) {
2334 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_DBDESC, SEND))
2335 zlog_debug(
2336 "Quit to send DbDesc to neighbor %s state %s",
2337 on->name, ospf6_neighbor_state_str[on->state]);
cc9f21da 2338 return;
d6a39b53
PR
2339 }
2340
2341 /* set next thread if master */
2342 if (CHECK_FLAG(on->dbdesc_bits, OSPF6_DBDESC_MSBIT))
2343 thread_add_timer(master, ospf6_dbdesc_send, on,
2344 on->ospf6_if->rxmt_interval,
2345 &on->thread_send_dbdesc);
d62a17ae 2346
d6a39b53
PR
2347 op = ospf6_packet_new(on->ospf6_if->ifmtu);
2348 ospf6_make_header(OSPF6_MESSAGE_TYPE_DBDESC, on->ospf6_if, op->s);
d62a17ae 2349
d6a39b53
PR
2350 length += ospf6_make_dbdesc(on, op->s);
2351 ospf6_fill_header(on->ospf6_if, op->s, length);
2352
2353 /* Set packet length. */
2354 op->length = length;
d62a17ae 2355
2356 if (on->ospf6_if->state == OSPF6_INTERFACE_POINTTOPOINT)
d6a39b53 2357 op->dst = allspfrouters6;
d62a17ae 2358 else
d6a39b53 2359 op->dst = on->linklocal_addr;
d62a17ae 2360
6cb85350
AR
2361 ospf6_fill_hdr_checksum(on->ospf6_if, op);
2362
d6a39b53 2363 ospf6_packet_add(on->ospf6_if, op);
43855e3d 2364
d6a39b53 2365 OSPF6_MESSAGE_WRITE_ON(on->ospf6_if);
718e3744 2366}
2367
cc9f21da 2368void ospf6_dbdesc_send_newone(struct thread *thread)
718e3744 2369{
d62a17ae 2370 struct ospf6_neighbor *on;
2e37407f 2371 struct ospf6_lsa *lsa, *lsanext;
d62a17ae 2372 unsigned int size = 0;
2373
2374 on = (struct ospf6_neighbor *)THREAD_ARG(thread);
2375 ospf6_lsdb_remove_all(on->dbdesc_list);
2376
2377 /* move LSAs from summary_list to dbdesc_list (within neighbor
2378 structure)
2379 so that ospf6_send_dbdesc () can send those LSAs */
2380 size = sizeof(struct ospf6_lsa_header) + sizeof(struct ospf6_dbdesc);
2e37407f 2381 for (ALL_LSDB(on->summary_list, lsa, lsanext)) {
bac66c5c 2382 /* if stub area then don't advertise AS-External LSAs */
4f785c07
RZ
2383 if ((IS_AREA_STUB(on->ospf6_if->area)
2384 || IS_AREA_NSSA(on->ospf6_if->area))
bac66c5c 2385 && ntohs(lsa->header->type) == OSPF6_LSTYPE_AS_EXTERNAL) {
2386 ospf6_lsdb_remove(lsa, on->summary_list);
2387 continue;
2388 }
2389
d62a17ae 2390 if (size + sizeof(struct ospf6_lsa_header)
2391 > ospf6_packet_max(on->ospf6_if)) {
ccf260c4 2392 ospf6_lsa_unlock(lsa);
2393 if (lsanext)
2394 ospf6_lsa_unlock(lsanext);
d62a17ae 2395 break;
2396 }
2397
2398 ospf6_lsdb_add(ospf6_lsa_copy(lsa), on->dbdesc_list);
2399 ospf6_lsdb_remove(lsa, on->summary_list);
2400 size += sizeof(struct ospf6_lsa_header);
2401 }
2402
2403 if (on->summary_list->count == 0)
2404 UNSET_FLAG(on->dbdesc_bits, OSPF6_DBDESC_MBIT);
2405
2406 /* If slave, More bit check must be done here */
2407 if (!CHECK_FLAG(on->dbdesc_bits, OSPF6_DBDESC_MSBIT) && /* Slave */
2408 !CHECK_FLAG(on->dbdesc_last.bits, OSPF6_DBDESC_MBIT)
2409 && !CHECK_FLAG(on->dbdesc_bits, OSPF6_DBDESC_MBIT))
9318fc6a
DS
2410 thread_add_event(master, exchange_done, on, 0,
2411 &on->thread_exchange_done);
d62a17ae 2412
2413 thread_execute(master, ospf6_dbdesc_send, on, 0);
508e53e2 2414}
718e3744 2415
571eed23
PR
2416static uint16_t ospf6_make_lsreq(struct ospf6_neighbor *on, struct stream *s)
2417{
2418 uint16_t length = 0;
2419 struct ospf6_lsa *lsa, *lsanext, *last_req = NULL;
2420
2421 for (ALL_LSDB(on->request_list, lsa, lsanext)) {
2422 if ((length + OSPF6_HEADER_SIZE)
2423 > ospf6_packet_max(on->ospf6_if)) {
2424 ospf6_lsa_unlock(lsa);
2425 if (lsanext)
2426 ospf6_lsa_unlock(lsanext);
2427 break;
2428 }
2429 stream_putw(s, 0); /* reserved */
2430 stream_putw(s, ntohs(lsa->header->type));
2431 stream_putl(s, ntohl(lsa->header->id));
2432 stream_putl(s, ntohl(lsa->header->adv_router));
2433 length += sizeof(struct ospf6_lsreq_entry);
2434 last_req = lsa;
2435 }
2436
2437 if (last_req != NULL) {
2438 if (on->last_ls_req != NULL)
2439 on->last_ls_req = ospf6_lsa_unlock(on->last_ls_req);
2440
2441 ospf6_lsa_lock(last_req);
2442 on->last_ls_req = last_req;
2443 }
2444
2445 return length;
2446}
2447
dd784cf9
PR
2448static uint16_t ospf6_make_lsack_neighbor(struct ospf6_neighbor *on,
2449 struct ospf6_packet **op)
2450{
2451 uint16_t length = 0;
2452 struct ospf6_lsa *lsa, *lsanext;
2453 int lsa_cnt = 0;
2454
2455 for (ALL_LSDB(on->lsack_list, lsa, lsanext)) {
2456 if ((length + sizeof(struct ospf6_lsa_header)
2457 + OSPF6_HEADER_SIZE)
2458 > ospf6_packet_max(on->ospf6_if)) {
2459 /* if we run out of packet size/space here,
2460 better to try again soon. */
2461 if (lsa_cnt) {
2462 ospf6_fill_header(on->ospf6_if, (*op)->s,
2463 length + OSPF6_HEADER_SIZE);
2464
2465 (*op)->length = length + OSPF6_HEADER_SIZE;
2466 (*op)->dst = on->linklocal_addr;
6cb85350 2467 ospf6_fill_hdr_checksum(on->ospf6_if, *op);
dd784cf9
PR
2468 ospf6_packet_add(on->ospf6_if, *op);
2469 OSPF6_MESSAGE_WRITE_ON(on->ospf6_if);
2470 /* new packet */
2471 *op = ospf6_packet_new(on->ospf6_if->ifmtu);
2472 ospf6_make_header(OSPF6_MESSAGE_TYPE_LSACK,
2473 on->ospf6_if, (*op)->s);
2474 length = 0;
2475 lsa_cnt = 0;
2476 }
2477 }
2478 ospf6_lsa_age_update_to_send(lsa, on->ospf6_if->transdelay);
2479 stream_put((*op)->s, lsa->header,
2480 sizeof(struct ospf6_lsa_header));
2481 length += sizeof(struct ospf6_lsa_header);
2482
2483 assert(lsa->lock == 2);
2484 ospf6_lsdb_remove(lsa, on->lsack_list);
2485 lsa_cnt++;
2486 }
2487 return length;
2488}
2489
cc9f21da 2490void ospf6_lsreq_send(struct thread *thread)
508e53e2 2491{
d62a17ae 2492 struct ospf6_neighbor *on;
571eed23
PR
2493 struct ospf6_packet *op;
2494 uint16_t length = OSPF6_HEADER_SIZE;
d62a17ae 2495
2496 on = (struct ospf6_neighbor *)THREAD_ARG(thread);
d62a17ae 2497
2498 /* LSReq will be sent only in ExStart or Loading */
2499 if (on->state != OSPF6_NEIGHBOR_EXCHANGE
2500 && on->state != OSPF6_NEIGHBOR_LOADING) {
f44d0f5e 2501 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_LSREQ, SEND_HDR))
d62a17ae 2502 zlog_debug("Quit to send LSReq to neighbor %s state %s",
2503 on->name,
2504 ospf6_neighbor_state_str[on->state]);
cc9f21da 2505 return;
d62a17ae 2506 }
2507
2508 /* schedule loading_done if request list is empty */
2509 if (on->request_list->count == 0) {
2510 thread_add_event(master, loading_done, on, 0, NULL);
cc9f21da 2511 return;
d62a17ae 2512 }
2513
571eed23
PR
2514 op = ospf6_packet_new(on->ospf6_if->ifmtu);
2515 ospf6_make_header(OSPF6_MESSAGE_TYPE_LSREQ, on->ospf6_if, op->s);
d62a17ae 2516
571eed23 2517 length += ospf6_make_lsreq(on, op->s);
744ba569 2518
571eed23
PR
2519 if (length == OSPF6_HEADER_SIZE) {
2520 /* Hello overshooting MTU */
2521 ospf6_packet_free(op);
cc9f21da 2522 return;
d62a17ae 2523 }
2524
571eed23
PR
2525 /* Fill OSPF header. */
2526 ospf6_fill_header(on->ospf6_if, op->s, length);
d62a17ae 2527
dd784cf9 2528 /* Set packet length */
571eed23 2529 op->length = length;
43855e3d 2530
d62a17ae 2531 if (on->ospf6_if->state == OSPF6_INTERFACE_POINTTOPOINT)
571eed23 2532 op->dst = allspfrouters6;
d62a17ae 2533 else
571eed23
PR
2534 op->dst = on->linklocal_addr;
2535
6cb85350 2536 ospf6_fill_hdr_checksum(on->ospf6_if, op);
571eed23
PR
2537 ospf6_packet_add(on->ospf6_if, op);
2538
2539 OSPF6_MESSAGE_WRITE_ON(on->ospf6_if);
d62a17ae 2540
2541 /* set next thread */
2542 if (on->request_list->count != 0) {
d62a17ae 2543 thread_add_timer(master, ospf6_lsreq_send, on,
2544 on->ospf6_if->rxmt_interval,
2545 &on->thread_send_lsreq);
2546 }
718e3744 2547}
2548
1ba43456
CS
2549static void ospf6_send_lsupdate(struct ospf6_neighbor *on,
2550 struct ospf6_interface *oi,
432b7daf 2551 struct ospf6_packet *op)
1ba43456
CS
2552{
2553
2554 if (on) {
43855e3d 2555
996c9314
LB
2556 if ((on->ospf6_if->state == OSPF6_INTERFACE_POINTTOPOINT)
2557 || (on->ospf6_if->state == OSPF6_INTERFACE_DR)
432b7daf
PR
2558 || (on->ospf6_if->state == OSPF6_INTERFACE_BDR))
2559 op->dst = allspfrouters6;
2560 else
2561 op->dst = on->linklocal_addr;
2562 oi = on->ospf6_if;
1ba43456 2563 } else if (oi) {
996c9314
LB
2564 if ((oi->state == OSPF6_INTERFACE_POINTTOPOINT)
2565 || (oi->state == OSPF6_INTERFACE_DR)
432b7daf
PR
2566 || (oi->state == OSPF6_INTERFACE_BDR))
2567 op->dst = allspfrouters6;
2568 else
2569 op->dst = alldrouters6;
2570 }
2571 if (oi) {
6cb85350 2572 ospf6_fill_hdr_checksum(oi, op);
432b7daf 2573 ospf6_packet_add(oi, op);
7359e9ba
S
2574 /* If ospf instance is being deleted, send the packet
2575 * immediately
2576 */
2577 if ((oi->area == NULL) || (oi->area->ospf6 == NULL))
2578 return;
2579 if (oi->area->ospf6->inst_shutdown) {
2580 if (oi->on_write_q == 0) {
2581 listnode_add(oi->area->ospf6->oi_write_q, oi);
2582 oi->on_write_q = 1;
2583 }
2584 thread_execute(master, ospf6_write, oi->area->ospf6, 0);
2585 } else
2586 OSPF6_MESSAGE_WRITE_ON(oi);
432b7daf
PR
2587 }
2588}
2589
2590static uint16_t ospf6_make_lsupdate_list(struct ospf6_neighbor *on,
2591 struct ospf6_packet **op, int *lsa_cnt)
2592{
2593 uint16_t length = OSPF6_LS_UPD_MIN_SIZE;
2594 struct ospf6_lsa *lsa, *lsanext;
2595
2596 /* skip over fixed header */
2597 stream_forward_endp((*op)->s, OSPF6_LS_UPD_MIN_SIZE);
2598
2599 for (ALL_LSDB(on->lsupdate_list, lsa, lsanext)) {
42bfee18
AR
2600 if ((length + OSPF6_LSA_SIZE(lsa->header) + OSPF6_HEADER_SIZE) >
2601 ospf6_packet_max(on->ospf6_if)) {
432b7daf
PR
2602 ospf6_fill_header(on->ospf6_if, (*op)->s,
2603 length + OSPF6_HEADER_SIZE);
2604 (*op)->length = length + OSPF6_HEADER_SIZE;
2605 ospf6_fill_lsupdate_header((*op)->s, *lsa_cnt);
2606 ospf6_send_lsupdate(on, NULL, *op);
2607
2608 /* refresh packet */
2609 *op = ospf6_packet_new(on->ospf6_if->ifmtu);
2610 length = OSPF6_LS_UPD_MIN_SIZE;
2611 *lsa_cnt = 0;
2612 ospf6_make_header(OSPF6_MESSAGE_TYPE_LSUPDATE,
2613 on->ospf6_if, (*op)->s);
2614 stream_forward_endp((*op)->s, OSPF6_LS_UPD_MIN_SIZE);
1ba43456 2615 }
432b7daf
PR
2616 ospf6_lsa_age_update_to_send(lsa, on->ospf6_if->transdelay);
2617 stream_put((*op)->s, lsa->header, OSPF6_LSA_SIZE(lsa->header));
2618 (*lsa_cnt)++;
2619 length += OSPF6_LSA_SIZE(lsa->header);
2620 assert(lsa->lock == 2);
2621 ospf6_lsdb_remove(lsa, on->lsupdate_list);
1ba43456 2622 }
432b7daf
PR
2623 return length;
2624}
2625
2626static uint16_t ospf6_make_ls_retrans_list(struct ospf6_neighbor *on,
2627 struct ospf6_packet **op,
2628 int *lsa_cnt)
2629{
2630 uint16_t length = OSPF6_LS_UPD_MIN_SIZE;
2631 struct ospf6_lsa *lsa, *lsanext;
2632
2633 /* skip over fixed header */
2634 stream_forward_endp((*op)->s, OSPF6_LS_UPD_MIN_SIZE);
2635
2636 for (ALL_LSDB(on->retrans_list, lsa, lsanext)) {
42bfee18
AR
2637 if ((length + OSPF6_LSA_SIZE(lsa->header) + OSPF6_HEADER_SIZE) >
2638 ospf6_packet_max(on->ospf6_if)) {
432b7daf
PR
2639 ospf6_fill_header(on->ospf6_if, (*op)->s,
2640 length + OSPF6_HEADER_SIZE);
2641 (*op)->length = length + OSPF6_HEADER_SIZE;
2642 ospf6_fill_lsupdate_header((*op)->s, *lsa_cnt);
2643 if (on->ospf6_if->state == OSPF6_INTERFACE_POINTTOPOINT)
2644 (*op)->dst = allspfrouters6;
2645 else
2646 (*op)->dst = on->linklocal_addr;
2647
6cb85350 2648 ospf6_fill_hdr_checksum(on->ospf6_if, *op);
432b7daf
PR
2649 ospf6_packet_add(on->ospf6_if, *op);
2650 OSPF6_MESSAGE_WRITE_ON(on->ospf6_if);
2651
2652 /* refresh packet */
2653 *op = ospf6_packet_new(on->ospf6_if->ifmtu);
2654 length = OSPF6_LS_UPD_MIN_SIZE;
2655 *lsa_cnt = 0;
2656 ospf6_make_header(OSPF6_MESSAGE_TYPE_LSUPDATE,
2657 on->ospf6_if, (*op)->s);
2658 stream_forward_endp((*op)->s, OSPF6_LS_UPD_MIN_SIZE);
1ba43456 2659 }
432b7daf
PR
2660 ospf6_lsa_age_update_to_send(lsa, on->ospf6_if->transdelay);
2661 stream_put((*op)->s, lsa->header, OSPF6_LSA_SIZE(lsa->header));
2662 (*lsa_cnt)++;
2663 length += OSPF6_LSA_SIZE(lsa->header);
1ba43456 2664 }
432b7daf 2665 return length;
1ba43456
CS
2666}
2667
cc9f21da 2668void ospf6_lsupdate_send_neighbor(struct thread *thread)
718e3744 2669{
d62a17ae 2670 struct ospf6_neighbor *on;
432b7daf
PR
2671 struct ospf6_packet *op;
2672 uint16_t length = OSPF6_HEADER_SIZE;
2673 int lsa_cnt = 0;
d62a17ae 2674
2675 on = (struct ospf6_neighbor *)THREAD_ARG(thread);
d62a17ae 2676
f44d0f5e 2677 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_LSUPDATE, SEND_HDR))
d62a17ae 2678 zlog_debug("LSUpdate to neighbor %s", on->name);
2679
2680 if (on->state < OSPF6_NEIGHBOR_EXCHANGE) {
f44d0f5e 2681 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_LSUPDATE,
2682 SEND_HDR))
d62a17ae 2683 zlog_debug("Quit to send (neighbor state %s)",
2684 ospf6_neighbor_state_str[on->state]);
cc9f21da 2685 return;
d62a17ae 2686 }
2687
432b7daf
PR
2688 /* first do lsupdate_list */
2689 op = ospf6_packet_new(on->ospf6_if->ifmtu);
2690 ospf6_make_header(OSPF6_MESSAGE_TYPE_LSUPDATE, on->ospf6_if, op->s);
2691 length += ospf6_make_lsupdate_list(on, &op, &lsa_cnt);
d62a17ae 2692 if (lsa_cnt) {
432b7daf
PR
2693 /* Fill OSPF header. */
2694 ospf6_fill_header(on->ospf6_if, op->s, length);
2695 ospf6_fill_lsupdate_header(op->s, lsa_cnt);
2696 op->length = length;
2697 ospf6_send_lsupdate(on, NULL, op);
2698
2699 /* prepare new packet */
2700 op = ospf6_packet_new(on->ospf6_if->ifmtu);
2701 length = OSPF6_HEADER_SIZE;
2702 lsa_cnt = 0;
2703 } else {
2704 stream_reset(op->s);
2705 length = OSPF6_HEADER_SIZE;
2706 }
2707
2708 ospf6_make_header(OSPF6_MESSAGE_TYPE_LSUPDATE, on->ospf6_if, op->s);
2709 /* now do retransmit list */
2710 length += ospf6_make_ls_retrans_list(on, &op, &lsa_cnt);
d62a17ae 2711 if (lsa_cnt) {
432b7daf
PR
2712 ospf6_fill_header(on->ospf6_if, op->s, length);
2713 ospf6_fill_lsupdate_header(op->s, lsa_cnt);
2714 op->length = length;
d62a17ae 2715 if (on->ospf6_if->state == OSPF6_INTERFACE_POINTTOPOINT)
432b7daf 2716 op->dst = allspfrouters6;
d62a17ae 2717 else
432b7daf 2718 op->dst = on->linklocal_addr;
6cb85350 2719 ospf6_fill_hdr_checksum(on->ospf6_if, op);
432b7daf
PR
2720 ospf6_packet_add(on->ospf6_if, op);
2721 OSPF6_MESSAGE_WRITE_ON(on->ospf6_if);
2722 } else
2723 ospf6_packet_free(op);
d62a17ae 2724
2725 if (on->lsupdate_list->count != 0) {
d62a17ae 2726 thread_add_event(master, ospf6_lsupdate_send_neighbor, on, 0,
2727 &on->thread_send_lsupdate);
2728 } else if (on->retrans_list->count != 0) {
d62a17ae 2729 thread_add_timer(master, ospf6_lsupdate_send_neighbor, on,
2730 on->ospf6_if->rxmt_interval,
2731 &on->thread_send_lsupdate);
2732 }
718e3744 2733}
2734
76249532
CS
2735int ospf6_lsupdate_send_neighbor_now(struct ospf6_neighbor *on,
2736 struct ospf6_lsa *lsa)
2737{
432b7daf
PR
2738 struct ospf6_packet *op;
2739 uint16_t length = OSPF6_HEADER_SIZE;
76249532 2740
432b7daf
PR
2741 op = ospf6_packet_new(on->ospf6_if->ifmtu);
2742 ospf6_make_header(OSPF6_MESSAGE_TYPE_LSUPDATE, on->ospf6_if, op->s);
76249532 2743
432b7daf
PR
2744 /* skip over fixed header */
2745 stream_forward_endp(op->s, OSPF6_LS_UPD_MIN_SIZE);
76249532 2746 ospf6_lsa_age_update_to_send(lsa, on->ospf6_if->transdelay);
432b7daf
PR
2747 stream_put(op->s, lsa->header, OSPF6_LSA_SIZE(lsa->header));
2748 length = OSPF6_HEADER_SIZE + OSPF6_LS_UPD_MIN_SIZE
2749 + OSPF6_LSA_SIZE(lsa->header);
2750 ospf6_fill_header(on->ospf6_if, op->s, length);
2751 ospf6_fill_lsupdate_header(op->s, 1);
2752 op->length = length;
76249532 2753
996c9314 2754 if (IS_OSPF6_DEBUG_FLOODING
f44d0f5e 2755 || IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_LSUPDATE, SEND_HDR))
15569c58
DA
2756 zlog_debug("%s: Send lsupdate with lsa %s (age %u)", __func__,
2757 lsa->name, ntohs(lsa->header->age));
76249532 2758
432b7daf 2759 ospf6_send_lsupdate(on, NULL, op);
76249532
CS
2760
2761 return 0;
2762}
2763
432b7daf
PR
2764static uint16_t ospf6_make_lsupdate_interface(struct ospf6_interface *oi,
2765 struct ospf6_packet **op,
2766 int *lsa_cnt)
2767{
2768 uint16_t length = OSPF6_LS_UPD_MIN_SIZE;
2769 struct ospf6_lsa *lsa, *lsanext;
2770
2771 /* skip over fixed header */
2772 stream_forward_endp((*op)->s, OSPF6_LS_UPD_MIN_SIZE);
2773
2774 for (ALL_LSDB(oi->lsupdate_list, lsa, lsanext)) {
42bfee18
AR
2775 if (length + OSPF6_LSA_SIZE(lsa->header) + OSPF6_HEADER_SIZE >
2776 ospf6_packet_max(oi)) {
432b7daf
PR
2777 ospf6_fill_header(oi, (*op)->s,
2778 length + OSPF6_HEADER_SIZE);
2779 (*op)->length = length + OSPF6_HEADER_SIZE;
2780 ospf6_fill_lsupdate_header((*op)->s, *lsa_cnt);
2781 ospf6_send_lsupdate(NULL, oi, *op);
2782
2783 /* refresh packet */
2784 *op = ospf6_packet_new(oi->ifmtu);
2785 length = OSPF6_LS_UPD_MIN_SIZE;
2786 *lsa_cnt = 0;
2787 ospf6_make_header(OSPF6_MESSAGE_TYPE_LSUPDATE, oi,
2788 (*op)->s);
2789 stream_forward_endp((*op)->s, OSPF6_LS_UPD_MIN_SIZE);
2790 }
2791
2792 ospf6_lsa_age_update_to_send(lsa, oi->transdelay);
2793 stream_put((*op)->s, lsa->header, OSPF6_LSA_SIZE(lsa->header));
2794 (*lsa_cnt)++;
2795 length += OSPF6_LSA_SIZE(lsa->header);
2796
2797 assert(lsa->lock == 2);
2798 ospf6_lsdb_remove(lsa, oi->lsupdate_list);
2799 }
2800 return length;
2801}
2802
cc9f21da 2803void ospf6_lsupdate_send_interface(struct thread *thread)
718e3744 2804{
d62a17ae 2805 struct ospf6_interface *oi;
432b7daf
PR
2806 struct ospf6_packet *op;
2807 uint16_t length = OSPF6_HEADER_SIZE;
2808 int lsa_cnt = 0;
d62a17ae 2809
2810 oi = (struct ospf6_interface *)THREAD_ARG(thread);
d62a17ae 2811
2812 if (oi->state <= OSPF6_INTERFACE_WAITING) {
f44d0f5e 2813 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_LSUPDATE,
2814 SEND_HDR))
d62a17ae 2815 zlog_debug(
2816 "Quit to send LSUpdate to interface %s state %s",
2817 oi->interface->name,
2818 ospf6_interface_state_str[oi->state]);
cc9f21da 2819 return;
d62a17ae 2820 }
2821
2822 /* if we have nothing to send, return */
2823 if (oi->lsupdate_list->count == 0)
cc9f21da 2824 return;
d62a17ae 2825
432b7daf
PR
2826 op = ospf6_packet_new(oi->ifmtu);
2827 ospf6_make_header(OSPF6_MESSAGE_TYPE_LSUPDATE, oi, op->s);
2828 length += ospf6_make_lsupdate_interface(oi, &op, &lsa_cnt);
d62a17ae 2829 if (lsa_cnt) {
432b7daf
PR
2830 /* Fill OSPF header. */
2831 ospf6_fill_header(oi, op->s, length);
2832 ospf6_fill_lsupdate_header(op->s, lsa_cnt);
2833 op->length = length;
2834 ospf6_send_lsupdate(NULL, oi, op);
2835 } else
2836 ospf6_packet_free(op);
d62a17ae 2837
2838 if (oi->lsupdate_list->count > 0) {
d62a17ae 2839 thread_add_event(master, ospf6_lsupdate_send_interface, oi, 0,
2840 &oi->thread_send_lsupdate);
2841 }
718e3744 2842}
2843
cc9f21da 2844void ospf6_lsack_send_neighbor(struct thread *thread)
718e3744 2845{
d62a17ae 2846 struct ospf6_neighbor *on;
dd784cf9
PR
2847 struct ospf6_packet *op;
2848 uint16_t length = OSPF6_HEADER_SIZE;
d62a17ae 2849
2850 on = (struct ospf6_neighbor *)THREAD_ARG(thread);
d62a17ae 2851
2852 if (on->state < OSPF6_NEIGHBOR_EXCHANGE) {
f44d0f5e 2853 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_LSACK, SEND_HDR))
d62a17ae 2854 zlog_debug("Quit to send LSAck to neighbor %s state %s",
2855 on->name,
2856 ospf6_neighbor_state_str[on->state]);
cc9f21da 2857 return;
d62a17ae 2858 }
2859
2860 /* if we have nothing to send, return */
2861 if (on->lsack_list->count == 0)
cc9f21da 2862 return;
d62a17ae 2863
dd784cf9
PR
2864 op = ospf6_packet_new(on->ospf6_if->ifmtu);
2865 ospf6_make_header(OSPF6_MESSAGE_TYPE_LSACK, on->ospf6_if, op->s);
d62a17ae 2866
dd784cf9 2867 length += ospf6_make_lsack_neighbor(on, &op);
d62a17ae 2868
dd784cf9
PR
2869 if (length == OSPF6_HEADER_SIZE) {
2870 ospf6_packet_free(op);
cc9f21da 2871 return;
d62a17ae 2872 }
2873
dd784cf9
PR
2874 /* Fill OSPF header. */
2875 ospf6_fill_header(on->ospf6_if, op->s, length);
43855e3d 2876
dd784cf9
PR
2877 /* Set packet length, dst and queue to FIFO. */
2878 op->length = length;
2879 op->dst = on->linklocal_addr;
6cb85350 2880 ospf6_fill_hdr_checksum(on->ospf6_if, op);
dd784cf9
PR
2881 ospf6_packet_add(on->ospf6_if, op);
2882 OSPF6_MESSAGE_WRITE_ON(on->ospf6_if);
d62a17ae 2883
2884 if (on->lsack_list->count > 0)
2885 thread_add_event(master, ospf6_lsack_send_neighbor, on, 0,
2886 &on->thread_send_lsack);
718e3744 2887}
2888
dd784cf9
PR
2889static uint16_t ospf6_make_lsack_interface(struct ospf6_interface *oi,
2890 struct ospf6_packet *op)
2891{
2892 uint16_t length = 0;
2893 struct ospf6_lsa *lsa, *lsanext;
2894
2895 for (ALL_LSDB(oi->lsack_list, lsa, lsanext)) {
2896 if ((length + sizeof(struct ospf6_lsa_header)
2897 + OSPF6_HEADER_SIZE)
2898 > ospf6_packet_max(oi)) {
2899 /* if we run out of packet size/space here,
2900 better to try again soon. */
2901 THREAD_OFF(oi->thread_send_lsack);
2902 thread_add_event(master, ospf6_lsack_send_interface, oi,
2903 0, &oi->thread_send_lsack);
2904
2905 ospf6_lsa_unlock(lsa);
2906 if (lsanext)
2907 ospf6_lsa_unlock(lsanext);
2908 break;
2909 }
2910 ospf6_lsa_age_update_to_send(lsa, oi->transdelay);
2911 stream_put(op->s, lsa->header, sizeof(struct ospf6_lsa_header));
2912 length += sizeof(struct ospf6_lsa_header);
2913
2914 assert(lsa->lock == 2);
2915 ospf6_lsdb_remove(lsa, oi->lsack_list);
2916 }
2917 return length;
2918}
2919
cc9f21da 2920void ospf6_lsack_send_interface(struct thread *thread)
718e3744 2921{
d62a17ae 2922 struct ospf6_interface *oi;
dd784cf9
PR
2923 struct ospf6_packet *op;
2924 uint16_t length = OSPF6_HEADER_SIZE;
d62a17ae 2925
2926 oi = (struct ospf6_interface *)THREAD_ARG(thread);
d62a17ae 2927
2928 if (oi->state <= OSPF6_INTERFACE_WAITING) {
f44d0f5e 2929 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_LSACK, SEND_HDR))
d62a17ae 2930 zlog_debug(
2931 "Quit to send LSAck to interface %s state %s",
2932 oi->interface->name,
2933 ospf6_interface_state_str[oi->state]);
cc9f21da 2934 return;
d62a17ae 2935 }
2936
2937 /* if we have nothing to send, return */
2938 if (oi->lsack_list->count == 0)
cc9f21da 2939 return;
d62a17ae 2940
dd784cf9
PR
2941 op = ospf6_packet_new(oi->ifmtu);
2942 ospf6_make_header(OSPF6_MESSAGE_TYPE_LSACK, oi, op->s);
d62a17ae 2943
dd784cf9 2944 length += ospf6_make_lsack_interface(oi, op);
d62a17ae 2945
dd784cf9
PR
2946 if (length == OSPF6_HEADER_SIZE) {
2947 ospf6_packet_free(op);
cc9f21da 2948 return;
d62a17ae 2949 }
dd784cf9
PR
2950 /* Fill OSPF header. */
2951 ospf6_fill_header(oi, op->s, length);
d62a17ae 2952
dd784cf9
PR
2953 /* Set packet length, dst and queue to FIFO. */
2954 op->length = length;
2955 if ((oi->state == OSPF6_INTERFACE_POINTTOPOINT)
2956 || (oi->state == OSPF6_INTERFACE_DR)
2957 || (oi->state == OSPF6_INTERFACE_BDR))
2958 op->dst = allspfrouters6;
2959 else
2960 op->dst = alldrouters6;
d62a17ae 2961
6cb85350 2962 ospf6_fill_hdr_checksum(oi, op);
dd784cf9
PR
2963 ospf6_packet_add(oi, op);
2964 OSPF6_MESSAGE_WRITE_ON(oi);
d62a17ae 2965
2966 if (oi->lsack_list->count > 0)
2967 thread_add_event(master, ospf6_lsack_send_interface, oi, 0,
2968 &oi->thread_send_lsack);
718e3744 2969}
2970
508e53e2 2971/* Commands */
f44d0f5e 2972DEFUN(debug_ospf6_message, debug_ospf6_message_cmd,
2973 "debug ospf6 message <unknown|hello|dbdesc|lsreq|lsupdate|lsack|all> [<send|recv|send-hdr|recv-hdr>]",
2974 DEBUG_STR OSPF6_STR
2975 "Debug OSPFv3 message\n"
2976 "Debug Unknown message\n"
2977 "Debug Hello message\n"
2978 "Debug Database Description message\n"
2979 "Debug Link State Request message\n"
2980 "Debug Link State Update message\n"
2981 "Debug Link State Acknowledgement message\n"
2982 "Debug All message\n"
2983 "Debug only sending message, entire packet\n"
2984 "Debug only receiving message, entire packet\n"
2985 "Debug only sending message, header only\n"
2986 "Debug only receiving message, header only\n")
718e3744 2987{
d62a17ae 2988 int idx_packet = 3;
2989 int idx_send_recv = 4;
2990 unsigned char level = 0;
2991 int type = 0;
2992 int i;
2993
2994 /* check type */
2995 if (!strncmp(argv[idx_packet]->arg, "u", 1))
2996 type = OSPF6_MESSAGE_TYPE_UNKNOWN;
2997 else if (!strncmp(argv[idx_packet]->arg, "h", 1))
2998 type = OSPF6_MESSAGE_TYPE_HELLO;
2999 else if (!strncmp(argv[idx_packet]->arg, "d", 1))
3000 type = OSPF6_MESSAGE_TYPE_DBDESC;
3001 else if (!strncmp(argv[idx_packet]->arg, "lsr", 3))
3002 type = OSPF6_MESSAGE_TYPE_LSREQ;
3003 else if (!strncmp(argv[idx_packet]->arg, "lsu", 3))
3004 type = OSPF6_MESSAGE_TYPE_LSUPDATE;
3005 else if (!strncmp(argv[idx_packet]->arg, "lsa", 3))
3006 type = OSPF6_MESSAGE_TYPE_LSACK;
3007 else if (!strncmp(argv[idx_packet]->arg, "a", 1))
3008 type = OSPF6_MESSAGE_TYPE_ALL;
3009
3010 if (argc == 4)
3011 level = OSPF6_DEBUG_MESSAGE_SEND | OSPF6_DEBUG_MESSAGE_RECV;
f44d0f5e 3012 else if (!strncmp(argv[idx_send_recv]->arg, "send-h", 6))
3013 level = OSPF6_DEBUG_MESSAGE_SEND_HDR;
d62a17ae 3014 else if (!strncmp(argv[idx_send_recv]->arg, "s", 1))
3015 level = OSPF6_DEBUG_MESSAGE_SEND;
f44d0f5e 3016 else if (!strncmp(argv[idx_send_recv]->arg, "recv-h", 6))
3017 level = OSPF6_DEBUG_MESSAGE_RECV_HDR;
d62a17ae 3018 else if (!strncmp(argv[idx_send_recv]->arg, "r", 1))
3019 level = OSPF6_DEBUG_MESSAGE_RECV;
3020
3021 if (type == OSPF6_MESSAGE_TYPE_ALL) {
3022 for (i = 0; i < 6; i++)
3023 OSPF6_DEBUG_MESSAGE_ON(i, level);
3024 } else
3025 OSPF6_DEBUG_MESSAGE_ON(type, level);
3026
3027 return CMD_SUCCESS;
718e3744 3028}
3029
f44d0f5e 3030DEFUN(no_debug_ospf6_message, no_debug_ospf6_message_cmd,
3031 "no debug ospf6 message <unknown|hello|dbdesc|lsreq|lsupdate|lsack|all> [<send|recv|send-hdr|recv-hdr>]",
3032 NO_STR DEBUG_STR OSPF6_STR
3033 "Debug OSPFv3 message\n"
3034 "Debug Unknown message\n"
3035 "Debug Hello message\n"
3036 "Debug Database Description message\n"
3037 "Debug Link State Request message\n"
3038 "Debug Link State Update message\n"
3039 "Debug Link State Acknowledgement message\n"
3040 "Debug All message\n"
3041 "Debug only sending message, entire pkt\n"
3042 "Debug only receiving message, entire pkt\n"
3043 "Debug only sending message, header only\n"
3044 "Debug only receiving message, header only\n")
508e53e2 3045{
d62a17ae 3046 int idx_packet = 4;
3047 int idx_send_recv = 5;
3048 unsigned char level = 0;
3049 int type = 0;
3050 int i;
3051
3052 /* check type */
3053 if (!strncmp(argv[idx_packet]->arg, "u", 1))
3054 type = OSPF6_MESSAGE_TYPE_UNKNOWN;
3055 else if (!strncmp(argv[idx_packet]->arg, "h", 1))
3056 type = OSPF6_MESSAGE_TYPE_HELLO;
3057 else if (!strncmp(argv[idx_packet]->arg, "d", 1))
3058 type = OSPF6_MESSAGE_TYPE_DBDESC;
3059 else if (!strncmp(argv[idx_packet]->arg, "lsr", 3))
3060 type = OSPF6_MESSAGE_TYPE_LSREQ;
3061 else if (!strncmp(argv[idx_packet]->arg, "lsu", 3))
3062 type = OSPF6_MESSAGE_TYPE_LSUPDATE;
3063 else if (!strncmp(argv[idx_packet]->arg, "lsa", 3))
3064 type = OSPF6_MESSAGE_TYPE_LSACK;
3065 else if (!strncmp(argv[idx_packet]->arg, "a", 1))
3066 type = OSPF6_MESSAGE_TYPE_ALL;
3067
3068 if (argc == 5)
f44d0f5e 3069 level = OSPF6_DEBUG_MESSAGE_SEND | OSPF6_DEBUG_MESSAGE_RECV
3070 | OSPF6_DEBUG_MESSAGE_SEND_HDR
3071 | OSPF6_DEBUG_MESSAGE_RECV_HDR;
3072 else if (!strncmp(argv[idx_send_recv]->arg, "send-h", 6))
3073 level = OSPF6_DEBUG_MESSAGE_SEND_HDR;
d62a17ae 3074 else if (!strncmp(argv[idx_send_recv]->arg, "s", 1))
3075 level = OSPF6_DEBUG_MESSAGE_SEND;
f44d0f5e 3076 else if (!strncmp(argv[idx_send_recv]->arg, "recv-h", 6))
3077 level = OSPF6_DEBUG_MESSAGE_RECV_HDR;
d62a17ae 3078 else if (!strncmp(argv[idx_send_recv]->arg, "r", 1))
3079 level = OSPF6_DEBUG_MESSAGE_RECV;
3080
3081 if (type == OSPF6_MESSAGE_TYPE_ALL) {
3082 for (i = 0; i < 6; i++)
3083 OSPF6_DEBUG_MESSAGE_OFF(i, level);
3084 } else
3085 OSPF6_DEBUG_MESSAGE_OFF(type, level);
3086
3087 return CMD_SUCCESS;
718e3744 3088}
3089
508e53e2 3090
d62a17ae 3091int config_write_ospf6_debug_message(struct vty *vty)
718e3744 3092{
d62a17ae 3093 const char *type_str[] = {"unknown", "hello", "dbdesc",
3094 "lsreq", "lsupdate", "lsack"};
f44d0f5e 3095 unsigned char s = 0, r = 0, sh = 0, rh = 0;
d62a17ae 3096 int i;
3097
3098 for (i = 0; i < 6; i++) {
f44d0f5e 3099 if (IS_OSPF6_DEBUG_MESSAGE_ENABLED(i, SEND))
d62a17ae 3100 s |= 1 << i;
f44d0f5e 3101 if (IS_OSPF6_DEBUG_MESSAGE_ENABLED(i, RECV))
d62a17ae 3102 r |= 1 << i;
3103 }
3104
f44d0f5e 3105 for (i = 0; i < 6; i++) {
3106 if (IS_OSPF6_DEBUG_MESSAGE_ENABLED(i, SEND_HDR))
3107 sh |= 1 << i;
3108 if (IS_OSPF6_DEBUG_MESSAGE_ENABLED(i, RECV_HDR))
3109 rh |= 1 << i;
3110 }
3111
d62a17ae 3112 if (s == 0x3f && r == 0x3f) {
3113 vty_out(vty, "debug ospf6 message all\n");
3114 return 0;
3115 }
3116
3117 if (s == 0x3f && r == 0) {
3118 vty_out(vty, "debug ospf6 message all send\n");
3119 return 0;
3120 } else if (s == 0 && r == 0x3f) {
3121 vty_out(vty, "debug ospf6 message all recv\n");
3122 return 0;
3123 }
3124
f44d0f5e 3125 if (sh == 0x3f && rh == 0) {
3126 vty_out(vty, "debug ospf6 message all send-hdr\n");
3127 return 0;
3128 } else if (sh == 0 && rh == 0x3f) {
3129 vty_out(vty, "debug ospf6 message all recv-hdr\n");
3130 return 0;
3131 }
3132
d62a17ae 3133 /* Unknown message is logged by default */
3134 if (!IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN, SEND)
3135 && !IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
3136 vty_out(vty, "no debug ospf6 message unknown\n");
3137 else if (!IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN, SEND))
3138 vty_out(vty, "no debug ospf6 message unknown send\n");
3139 else if (!IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
3140 vty_out(vty, "no debug ospf6 message unknown recv\n");
3141
3142 for (i = 1; i < 6; i++) {
f44d0f5e 3143 if (IS_OSPF6_DEBUG_MESSAGE_ENABLED(i, SEND)
c9ac777a 3144 && IS_OSPF6_DEBUG_MESSAGE_ENABLED(i, RECV)) {
d62a17ae 3145 vty_out(vty, "debug ospf6 message %s\n", type_str[i]);
c9ac777a
IR
3146 continue;
3147 }
3148
3149 if (IS_OSPF6_DEBUG_MESSAGE_ENABLED(i, SEND))
d62a17ae 3150 vty_out(vty, "debug ospf6 message %s send\n",
3151 type_str[i]);
c9ac777a
IR
3152 else if (IS_OSPF6_DEBUG_MESSAGE_ENABLED(i, SEND_HDR))
3153 vty_out(vty, "debug ospf6 message %s send-hdr\n",
d62a17ae 3154 type_str[i]);
c9ac777a
IR
3155
3156 if (IS_OSPF6_DEBUG_MESSAGE_ENABLED(i, RECV))
3157 vty_out(vty, "debug ospf6 message %s recv\n",
f44d0f5e 3158 type_str[i]);
3159 else if (IS_OSPF6_DEBUG_MESSAGE_ENABLED(i, RECV_HDR))
3160 vty_out(vty, "debug ospf6 message %s recv-hdr\n",
3161 type_str[i]);
d62a17ae 3162 }
3163
3164 return 0;
718e3744 3165}
3166
d62a17ae 3167void install_element_ospf6_debug_message(void)
508e53e2 3168{
d62a17ae 3169 install_element(ENABLE_NODE, &debug_ospf6_message_cmd);
3170 install_element(ENABLE_NODE, &no_debug_ospf6_message_cmd);
3171 install_element(CONFIG_NODE, &debug_ospf6_message_cmd);
3172 install_element(CONFIG_NODE, &no_debug_ospf6_message_cmd);
508e53e2 3173}