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