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