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