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