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