]> git.proxmox.com Git - mirror_frr.git/blame - ospf6d/ospf6_message.c
ospf6d: add dbdesc 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
1877static uint32_t ospf6_packet_max(struct ospf6_interface *oi)
1878{
1879 assert(oi->ifmtu > sizeof(struct ip6_hdr));
1880 return oi->ifmtu - (sizeof(struct ip6_hdr));
1881}
1882
1883static uint16_t ospf6_make_hello(struct ospf6_interface *oi, struct stream *s)
1884{
1885 struct listnode *node, *nnode;
1886 struct ospf6_neighbor *on;
1887 uint16_t length = OSPF6_HELLO_MIN_SIZE;
1888
1889 stream_putl(s, oi->interface->ifindex);
1890 stream_putc(s, oi->priority);
1891 stream_putc(s, oi->area->options[0]);
1892 stream_putc(s, oi->area->options[1]);
1893 stream_putc(s, oi->area->options[2]);
1894 stream_putw(s, oi->hello_interval);
1895 stream_putw(s, oi->dead_interval);
1896 stream_put_ipv4(s, oi->drouter);
1897 stream_put_ipv4(s, oi->bdrouter);
1898
1899 for (ALL_LIST_ELEMENTS(oi->neighbor_list, node, nnode, on)) {
1900 if (on->state < OSPF6_NEIGHBOR_INIT)
1901 continue;
1902
1903 if ((length + sizeof(uint32_t) + OSPF6_HEADER_SIZE)
1904 > ospf6_packet_max(oi)) {
1905 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_HELLO,
1906 SEND))
1907 zlog_debug(
1908 "sending Hello message: exceeds I/F MTU");
1909 break;
1910 }
1911
1912 stream_put_ipv4(s, on->router_id);
1913 length += sizeof(uint32_t);
1914 }
1915
1916 return length;
1917}
1918
1919static int ospf6_write(struct thread *thread)
1920{
1921 struct ospf6 *ospf6 = THREAD_ARG(thread);
1922 struct ospf6_interface *oi;
1923 struct ospf6_interface *last_serviced_oi = NULL;
1924 struct ospf6_header *oh;
1925 struct ospf6_packet *op;
1926 struct listnode *node;
1927 char srcname[64], dstname[64];
1928 struct iovec iovector[2];
1929 int pkt_count = 0;
1930 int len;
1931
1932 if (ospf6->fd < 0) {
1933 zlog_warn("ospf6_write failed to send, fd %d", ospf6->fd);
1934 return -1;
1935 }
1936
1937 node = listhead(ospf6->oi_write_q);
1938 assert(node);
1939 oi = listgetdata(node);
1940
1941 while ((pkt_count < OSPF6_WRITE_INTERFACE_COUNT_DEFAULT) && oi
1942 && (last_serviced_oi != oi)) {
1943
1944 op = ospf6_fifo_head(oi->obuf);
1945 assert(op);
1946 assert(op->length >= OSPF6_HEADER_SIZE);
1947
1948 iovector[0].iov_base = (caddr_t)stream_pnt(op->s);
1949 iovector[0].iov_len = op->length;
1950 iovector[1].iov_base = NULL;
1951 iovector[1].iov_len = 0;
1952
1953 oh = (struct ospf6_header *)STREAM_DATA(op->s);
1954
1955 len = ospf6_sendmsg(oi->linklocal_addr, &op->dst,
1956 oi->interface->ifindex, iovector,
1957 ospf6->fd);
1958 if (len != op->length)
1959 flog_err(EC_LIB_DEVELOPMENT,
1960 "Could not send entire message");
1961
1962 if (IS_OSPF6_DEBUG_MESSAGE(oh->type, SEND)) {
1963 inet_ntop(AF_INET6, &op->dst, dstname, sizeof(dstname));
1964 inet_ntop(AF_INET6, oi->linklocal_addr, srcname,
1965 sizeof(srcname));
1966 zlog_debug("%s send on %s",
1967 lookup_msg(ospf6_message_type_str, oh->type,
1968 NULL),
1969 oi->interface->name);
1970 zlog_debug(" src: %s", srcname);
1971 zlog_debug(" dst: %s", dstname);
1972 }
1973 switch (oh->type) {
1974 case OSPF6_MESSAGE_TYPE_HELLO:
1975 oi->hello_out++;
1976 ospf6_hello_print(oh, OSPF6_ACTION_SEND);
1977 break;
1978 case OSPF6_MESSAGE_TYPE_DBDESC:
1979 oi->db_desc_out++;
1980 ospf6_dbdesc_print(oh, OSPF6_ACTION_SEND);
1981 break;
1982 case OSPF6_MESSAGE_TYPE_LSREQ:
1983 oi->ls_req_out++;
1984 ospf6_lsreq_print(oh, OSPF6_ACTION_SEND);
1985 break;
1986 case OSPF6_MESSAGE_TYPE_LSUPDATE:
1987 oi->ls_upd_out++;
1988 ospf6_lsupdate_print(oh, OSPF6_ACTION_SEND);
1989 break;
1990 case OSPF6_MESSAGE_TYPE_LSACK:
1991 oi->ls_ack_out++;
1992 ospf6_lsack_print(oh, OSPF6_ACTION_SEND);
1993 break;
1994 default:
1995 zlog_debug("Unknown message");
1996 assert(0);
1997 break;
1998 }
1999 /* Now delete packet from queue. */
2000 ospf6_packet_delete(oi);
2001
2002 /* Move this interface to the tail of write_q to
2003 serve everyone in a round robin fashion */
2004 list_delete_node(ospf6->oi_write_q, node);
2005 if (ospf6_fifo_head(oi->obuf) == NULL) {
2006 oi->on_write_q = 0;
2007 last_serviced_oi = NULL;
2008 oi = NULL;
2009 } else {
2010 listnode_add(ospf6->oi_write_q, oi);
2011 }
2012
2013 /* Setup to service from the head of the queue again */
2014 if (!list_isempty(ospf6->oi_write_q)) {
2015 node = listhead(ospf6->oi_write_q);
2016 oi = listgetdata(node);
2017 }
2018 }
2019
2020 /* If packets still remain in queue, call write thread. */
2021 if (!list_isempty(ospf6->oi_write_q))
2022 thread_add_write(master, ospf6_write, ospf6, ospf6->fd,
2023 &ospf6->t_write);
2024
2025 return 0;
2026}
2027
d62a17ae 2028static void ospf6_send(struct in6_addr *src, struct in6_addr *dst,
2029 struct ospf6_interface *oi, struct ospf6_header *oh)
718e3744 2030{
d62a17ae 2031 unsigned int len;
d47b448d 2032 char srcname[64];
d62a17ae 2033 struct iovec iovector[2];
2034
2035 /* initialize */
2036 iovector[0].iov_base = (caddr_t)oh;
2037 iovector[0].iov_len = ntohs(oh->length);
2038 iovector[1].iov_base = NULL;
2039 iovector[1].iov_len = 0;
2040
2041 /* fill OSPF header */
2042 oh->version = OSPFV3_VERSION;
2043 /* message type must be set before */
2044 /* message length must be set before */
2045 oh->router_id = oi->area->ospf6->router_id;
2046 oh->area_id = oi->area->area_id;
2047 /* checksum is calculated by kernel */
2048 oh->instance_id = oi->instance_id;
2049 oh->reserved = 0;
2050
2051 /* Log */
f44d0f5e 2052 if (IS_OSPF6_DEBUG_MESSAGE(oh->type, SEND_HDR)) {
d62a17ae 2053 if (src)
2054 inet_ntop(AF_INET6, src, srcname, sizeof(srcname));
2055 else
2056 memset(srcname, 0, sizeof(srcname));
2057 zlog_debug("%s send on %s",
2058 lookup_msg(ospf6_message_type_str, oh->type, NULL),
2059 oi->interface->name);
2060 zlog_debug(" src: %s", srcname);
5145a172 2061 zlog_debug(" dst: %pI6", dst);
d62a17ae 2062
2063 switch (oh->type) {
2064 case OSPF6_MESSAGE_TYPE_HELLO:
f44d0f5e 2065 ospf6_hello_print(oh, OSPF6_ACTION_RECV);
d62a17ae 2066 break;
2067 case OSPF6_MESSAGE_TYPE_DBDESC:
f44d0f5e 2068 ospf6_dbdesc_print(oh, OSPF6_ACTION_RECV);
d62a17ae 2069 break;
2070 case OSPF6_MESSAGE_TYPE_LSREQ:
f44d0f5e 2071 ospf6_lsreq_print(oh, OSPF6_ACTION_RECV);
d62a17ae 2072 break;
2073 case OSPF6_MESSAGE_TYPE_LSUPDATE:
f44d0f5e 2074 ospf6_lsupdate_print(oh, OSPF6_ACTION_RECV);
d62a17ae 2075 break;
2076 case OSPF6_MESSAGE_TYPE_LSACK:
f44d0f5e 2077 ospf6_lsack_print(oh, OSPF6_ACTION_RECV);
d62a17ae 2078 break;
2079 default:
2080 zlog_debug("Unknown message");
2081 assert(0);
2082 break;
2083 }
2084 }
2085
2086 /* send message */
7df1f362 2087 if (oi->area->ospf6->fd != -1) {
b66ec22c 2088 len = ospf6_sendmsg(src, dst, oi->interface->ifindex, iovector,
7df1f362
K
2089 oi->area->ospf6->fd);
2090 if (len != ntohs(oh->length))
2091 flog_err(EC_LIB_DEVELOPMENT,
2092 "Could not send entire message");
2093 }
718e3744 2094}
2095
d62a17ae 2096int ospf6_hello_send(struct thread *thread)
718e3744 2097{
d62a17ae 2098 struct ospf6_interface *oi;
3d968031
PR
2099 struct ospf6_packet *op;
2100 uint16_t length = OSPF6_HEADER_SIZE;
d62a17ae 2101
2102 oi = (struct ospf6_interface *)THREAD_ARG(thread);
2103 oi->thread_send_hello = (struct thread *)NULL;
2104
2105 if (oi->state <= OSPF6_INTERFACE_DOWN) {
f44d0f5e 2106 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_HELLO, SEND_HDR))
d62a17ae 2107 zlog_debug("Unable to send Hello on down interface %s",
2108 oi->interface->name);
2109 return 0;
2110 }
2111
3d968031 2112 op = ospf6_packet_new(oi->ifmtu);
d62a17ae 2113
3d968031 2114 ospf6_make_header(OSPF6_MESSAGE_TYPE_HELLO, oi, op->s);
d62a17ae 2115
3d968031
PR
2116 /* Prepare OSPF Hello body */
2117 length += ospf6_make_hello(oi, op->s);
2118 if (length == OSPF6_HEADER_SIZE) {
2119 /* Hello overshooting MTU */
2120 ospf6_packet_free(op);
2121 return 0;
2122 }
d62a17ae 2123
3d968031
PR
2124 /* Fill OSPF header. */
2125 ospf6_fill_header(oi, op->s, length);
d62a17ae 2126
3d968031
PR
2127 /* Set packet length. */
2128 op->length = length;
d62a17ae 2129
3d968031 2130 op->dst = allspfrouters6;
d62a17ae 2131
3d968031
PR
2132 /* Add packet to the top of the interface output queue, so that they
2133 * can't get delayed by things like long queues of LS Update packets
2134 */
2135 ospf6_packet_add_top(oi, op);
d62a17ae 2136
3d968031
PR
2137 /* set next thread */
2138 thread_add_timer(master, ospf6_hello_send, oi, oi->hello_interval,
2139 &oi->thread_send_hello);
d62a17ae 2140
d6a39b53 2141 OSPF6_MESSAGE_WRITE_ON(oi);
43855e3d 2142
d62a17ae 2143 return 0;
718e3744 2144}
2145
d6a39b53 2146static uint16_t ospf6_make_dbdesc(struct ospf6_neighbor *on, struct stream *s)
718e3744 2147{
d6a39b53 2148 uint16_t length = OSPF6_DB_DESC_MIN_SIZE;
2e37407f 2149 struct ospf6_lsa *lsa, *lsanext;
d62a17ae 2150
2151 /* if this is initial one, initialize sequence number for DbDesc */
2152 if (CHECK_FLAG(on->dbdesc_bits, OSPF6_DBDESC_IBIT)
2153 && (on->dbdesc_seqnum == 0)) {
2154 on->dbdesc_seqnum = monotime(NULL);
2155 }
2156
d6a39b53
PR
2157 /* reserved */
2158 stream_putc(s, 0); /* reserved 1 */
2159 stream_putc(s, on->ospf6_if->area->options[0]);
2160 stream_putc(s, on->ospf6_if->area->options[1]);
2161 stream_putc(s, on->ospf6_if->area->options[2]);
2162 stream_putw(s, on->ospf6_if->ifmtu);
2163 stream_putc(s, 0); /* reserved 2 */
2164 stream_putc(s, on->dbdesc_bits);
2165 stream_putl(s, on->dbdesc_seqnum);
d62a17ae 2166
2167 /* if this is not initial one, set LSA headers in dbdesc */
d62a17ae 2168 if (!CHECK_FLAG(on->dbdesc_bits, OSPF6_DBDESC_IBIT)) {
2e37407f 2169 for (ALL_LSDB(on->dbdesc_list, lsa, lsanext)) {
d62a17ae 2170 ospf6_lsa_age_update_to_send(lsa,
2171 on->ospf6_if->transdelay);
2172
2173 /* MTU check */
d6a39b53
PR
2174 if ((length + sizeof(struct ospf6_lsa_header)
2175 + OSPF6_HEADER_SIZE)
d62a17ae 2176 > ospf6_packet_max(on->ospf6_if)) {
ccf260c4 2177 ospf6_lsa_unlock(lsa);
2178 if (lsanext)
2179 ospf6_lsa_unlock(lsanext);
d62a17ae 2180 break;
2181 }
d6a39b53
PR
2182 stream_put(s, lsa->header,
2183 sizeof(struct ospf6_lsa_header));
2184 length += sizeof(struct ospf6_lsa_header);
d62a17ae 2185 }
2186 }
d6a39b53
PR
2187 return length;
2188}
2189
2190int ospf6_dbdesc_send(struct thread *thread)
2191{
2192 struct ospf6_neighbor *on;
2193 uint16_t length = OSPF6_HEADER_SIZE;
2194 struct ospf6_packet *op;
2195
2196 on = (struct ospf6_neighbor *)THREAD_ARG(thread);
2197 on->thread_send_dbdesc = (struct thread *)NULL;
2198
2199 if (on->state < OSPF6_NEIGHBOR_EXSTART) {
2200 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_DBDESC, SEND))
2201 zlog_debug(
2202 "Quit to send DbDesc to neighbor %s state %s",
2203 on->name, ospf6_neighbor_state_str[on->state]);
2204 return 0;
2205 }
2206
2207 /* set next thread if master */
2208 if (CHECK_FLAG(on->dbdesc_bits, OSPF6_DBDESC_MSBIT))
2209 thread_add_timer(master, ospf6_dbdesc_send, on,
2210 on->ospf6_if->rxmt_interval,
2211 &on->thread_send_dbdesc);
d62a17ae 2212
d6a39b53
PR
2213 op = ospf6_packet_new(on->ospf6_if->ifmtu);
2214 ospf6_make_header(OSPF6_MESSAGE_TYPE_DBDESC, on->ospf6_if, op->s);
d62a17ae 2215
d6a39b53
PR
2216 length += ospf6_make_dbdesc(on, op->s);
2217 ospf6_fill_header(on->ospf6_if, op->s, length);
2218
2219 /* Set packet length. */
2220 op->length = length;
d62a17ae 2221
2222 if (on->ospf6_if->state == OSPF6_INTERFACE_POINTTOPOINT)
d6a39b53 2223 op->dst = allspfrouters6;
d62a17ae 2224 else
d6a39b53 2225 op->dst = on->linklocal_addr;
d62a17ae 2226
d6a39b53 2227 ospf6_packet_add(on->ospf6_if, op);
43855e3d 2228
d6a39b53 2229 OSPF6_MESSAGE_WRITE_ON(on->ospf6_if);
d62a17ae 2230
2231 return 0;
718e3744 2232}
2233
d62a17ae 2234int ospf6_dbdesc_send_newone(struct thread *thread)
718e3744 2235{
d62a17ae 2236 struct ospf6_neighbor *on;
2e37407f 2237 struct ospf6_lsa *lsa, *lsanext;
d62a17ae 2238 unsigned int size = 0;
2239
2240 on = (struct ospf6_neighbor *)THREAD_ARG(thread);
2241 ospf6_lsdb_remove_all(on->dbdesc_list);
2242
2243 /* move LSAs from summary_list to dbdesc_list (within neighbor
2244 structure)
2245 so that ospf6_send_dbdesc () can send those LSAs */
2246 size = sizeof(struct ospf6_lsa_header) + sizeof(struct ospf6_dbdesc);
2e37407f 2247 for (ALL_LSDB(on->summary_list, lsa, lsanext)) {
bac66c5c 2248 /* if stub area then don't advertise AS-External LSAs */
4f785c07
RZ
2249 if ((IS_AREA_STUB(on->ospf6_if->area)
2250 || IS_AREA_NSSA(on->ospf6_if->area))
bac66c5c 2251 && ntohs(lsa->header->type) == OSPF6_LSTYPE_AS_EXTERNAL) {
2252 ospf6_lsdb_remove(lsa, on->summary_list);
2253 continue;
2254 }
2255
d62a17ae 2256 if (size + sizeof(struct ospf6_lsa_header)
2257 > ospf6_packet_max(on->ospf6_if)) {
ccf260c4 2258 ospf6_lsa_unlock(lsa);
2259 if (lsanext)
2260 ospf6_lsa_unlock(lsanext);
d62a17ae 2261 break;
2262 }
2263
2264 ospf6_lsdb_add(ospf6_lsa_copy(lsa), on->dbdesc_list);
2265 ospf6_lsdb_remove(lsa, on->summary_list);
2266 size += sizeof(struct ospf6_lsa_header);
2267 }
2268
2269 if (on->summary_list->count == 0)
2270 UNSET_FLAG(on->dbdesc_bits, OSPF6_DBDESC_MBIT);
2271
2272 /* If slave, More bit check must be done here */
2273 if (!CHECK_FLAG(on->dbdesc_bits, OSPF6_DBDESC_MSBIT) && /* Slave */
2274 !CHECK_FLAG(on->dbdesc_last.bits, OSPF6_DBDESC_MBIT)
2275 && !CHECK_FLAG(on->dbdesc_bits, OSPF6_DBDESC_MBIT))
2276 thread_add_event(master, exchange_done, on, 0, NULL);
2277
2278 thread_execute(master, ospf6_dbdesc_send, on, 0);
2279 return 0;
508e53e2 2280}
718e3744 2281
d62a17ae 2282int ospf6_lsreq_send(struct thread *thread)
508e53e2 2283{
d62a17ae 2284 struct ospf6_neighbor *on;
2285 struct ospf6_header *oh;
2286 struct ospf6_lsreq_entry *e;
d7c0a89a 2287 uint8_t *p;
2e37407f 2288 struct ospf6_lsa *lsa, *lsanext, *last_req;
d62a17ae 2289
2290 on = (struct ospf6_neighbor *)THREAD_ARG(thread);
2291 on->thread_send_lsreq = (struct thread *)NULL;
2292
2293 /* LSReq will be sent only in ExStart or Loading */
2294 if (on->state != OSPF6_NEIGHBOR_EXCHANGE
2295 && on->state != OSPF6_NEIGHBOR_LOADING) {
f44d0f5e 2296 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_LSREQ, SEND_HDR))
d62a17ae 2297 zlog_debug("Quit to send LSReq to neighbor %s state %s",
2298 on->name,
2299 ospf6_neighbor_state_str[on->state]);
2300 return 0;
2301 }
2302
2303 /* schedule loading_done if request list is empty */
2304 if (on->request_list->count == 0) {
2305 thread_add_event(master, loading_done, on, 0, NULL);
2306 return 0;
2307 }
2308
2309 memset(sendbuf, 0, iobuflen);
2310 oh = (struct ospf6_header *)sendbuf;
2311 last_req = NULL;
2312
2313 /* set Request entries in lsreq */
d7c0a89a 2314 p = (uint8_t *)((caddr_t)oh + sizeof(struct ospf6_header));
2e37407f 2315 for (ALL_LSDB(on->request_list, lsa, lsanext)) {
d62a17ae 2316 /* MTU check */
2317 if (p - sendbuf + sizeof(struct ospf6_lsreq_entry)
2318 > ospf6_packet_max(on->ospf6_if)) {
ccf260c4 2319 ospf6_lsa_unlock(lsa);
2320 if (lsanext)
2321 ospf6_lsa_unlock(lsanext);
d62a17ae 2322 break;
2323 }
2324
2325 e = (struct ospf6_lsreq_entry *)p;
2326 e->type = lsa->header->type;
2327 e->id = lsa->header->id;
2328 e->adv_router = lsa->header->adv_router;
2329 p += sizeof(struct ospf6_lsreq_entry);
2330 last_req = lsa;
2331 }
2332
2333 if (last_req != NULL) {
744ba569
DS
2334 if (on->last_ls_req != NULL)
2335 on->last_ls_req = ospf6_lsa_unlock(on->last_ls_req);
2336
d62a17ae 2337 ospf6_lsa_lock(last_req);
2338 on->last_ls_req = last_req;
2339 }
2340
2341 oh->type = OSPF6_MESSAGE_TYPE_LSREQ;
2342 oh->length = htons(p - sendbuf);
2343
43855e3d
CS
2344 on->ospf6_if->ls_req_out++;
2345
d62a17ae 2346 if (on->ospf6_if->state == OSPF6_INTERFACE_POINTTOPOINT)
2347 ospf6_send(on->ospf6_if->linklocal_addr, &allspfrouters6,
2348 on->ospf6_if, oh);
2349 else
2350 ospf6_send(on->ospf6_if->linklocal_addr, &on->linklocal_addr,
2351 on->ospf6_if, oh);
2352
2353 /* set next thread */
2354 if (on->request_list->count != 0) {
2355 on->thread_send_lsreq = NULL;
2356 thread_add_timer(master, ospf6_lsreq_send, on,
2357 on->ospf6_if->rxmt_interval,
2358 &on->thread_send_lsreq);
2359 }
2360
2361 return 0;
718e3744 2362}
2363
1ba43456
CS
2364static void ospf6_send_lsupdate(struct ospf6_neighbor *on,
2365 struct ospf6_interface *oi,
2366 struct ospf6_header *oh)
2367{
2368
2369 if (on) {
43855e3d
CS
2370 on->ospf6_if->ls_upd_out++;
2371
996c9314
LB
2372 if ((on->ospf6_if->state == OSPF6_INTERFACE_POINTTOPOINT)
2373 || (on->ospf6_if->state == OSPF6_INTERFACE_DR)
2374 || (on->ospf6_if->state == OSPF6_INTERFACE_BDR)) {
1ba43456
CS
2375 ospf6_send(on->ospf6_if->linklocal_addr,
2376 &allspfrouters6, on->ospf6_if, oh);
2377 } else {
2378 ospf6_send(on->ospf6_if->linklocal_addr,
2379 &on->linklocal_addr, on->ospf6_if, oh);
2380 }
2381 } else if (oi) {
43855e3d
CS
2382
2383 oi->ls_upd_out++;
2384
996c9314
LB
2385 if ((oi->state == OSPF6_INTERFACE_POINTTOPOINT)
2386 || (oi->state == OSPF6_INTERFACE_DR)
2387 || (oi->state == OSPF6_INTERFACE_BDR)) {
1ba43456
CS
2388 ospf6_send(oi->linklocal_addr, &allspfrouters6, oi, oh);
2389 } else {
2390 ospf6_send(oi->linklocal_addr, &alldrouters6, oi, oh);
2391 }
2392 }
2393}
2394
d62a17ae 2395int ospf6_lsupdate_send_neighbor(struct thread *thread)
718e3744 2396{
d62a17ae 2397 struct ospf6_neighbor *on;
2398 struct ospf6_header *oh;
2399 struct ospf6_lsupdate *lsupdate;
d7c0a89a 2400 uint8_t *p;
d62a17ae 2401 int lsa_cnt;
2e37407f 2402 struct ospf6_lsa *lsa, *lsanext;
d62a17ae 2403
2404 on = (struct ospf6_neighbor *)THREAD_ARG(thread);
2405 on->thread_send_lsupdate = (struct thread *)NULL;
2406
f44d0f5e 2407 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_LSUPDATE, SEND_HDR))
d62a17ae 2408 zlog_debug("LSUpdate to neighbor %s", on->name);
2409
2410 if (on->state < OSPF6_NEIGHBOR_EXCHANGE) {
f44d0f5e 2411 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_LSUPDATE,
2412 SEND_HDR))
d62a17ae 2413 zlog_debug("Quit to send (neighbor state %s)",
2414 ospf6_neighbor_state_str[on->state]);
2415 return 0;
2416 }
2417
2418 memset(sendbuf, 0, iobuflen);
2419 oh = (struct ospf6_header *)sendbuf;
2420 lsupdate = (struct ospf6_lsupdate *)((caddr_t)oh
2421 + sizeof(struct ospf6_header));
2422
d7c0a89a 2423 p = (uint8_t *)((caddr_t)lsupdate + sizeof(struct ospf6_lsupdate));
d62a17ae 2424 lsa_cnt = 0;
2425
2426 /* lsupdate_list lists those LSA which doesn't need to be
2427 retransmitted. remove those from the list */
2e37407f 2428 for (ALL_LSDB(on->lsupdate_list, lsa, lsanext)) {
d62a17ae 2429 /* MTU check */
2430 if ((p - sendbuf + (unsigned int)OSPF6_LSA_SIZE(lsa->header))
2431 > ospf6_packet_max(on->ospf6_if)) {
1ba43456
CS
2432 if (lsa_cnt) {
2433 oh->type = OSPF6_MESSAGE_TYPE_LSUPDATE;
2434 oh->length = htons(p - sendbuf);
2435 lsupdate->lsa_number = htonl(lsa_cnt);
2436
2437 ospf6_send_lsupdate(on, NULL, oh);
2438
2439 memset(sendbuf, 0, iobuflen);
2440 oh = (struct ospf6_header *)sendbuf;
996c9314
LB
2441 lsupdate = (struct ospf6_lsupdate
2442 *)((caddr_t)oh
2443 + sizeof(struct
2444 ospf6_header));
1ba43456 2445
d7c0a89a
QY
2446 p = (uint8_t *)((caddr_t)lsupdate
2447 + sizeof(struct
2448 ospf6_lsupdate));
1ba43456
CS
2449 lsa_cnt = 0;
2450 }
d62a17ae 2451 }
2452
2453 ospf6_lsa_age_update_to_send(lsa, on->ospf6_if->transdelay);
2454 memcpy(p, lsa->header, OSPF6_LSA_SIZE(lsa->header));
2455 p += OSPF6_LSA_SIZE(lsa->header);
2456 lsa_cnt++;
2457
e2e60c48 2458 assert(lsa->lock == 2);
d62a17ae 2459 ospf6_lsdb_remove(lsa, on->lsupdate_list);
2460 }
2461
2462 if (lsa_cnt) {
2463 oh->type = OSPF6_MESSAGE_TYPE_LSUPDATE;
2464 oh->length = htons(p - sendbuf);
2465 lsupdate->lsa_number = htonl(lsa_cnt);
1ba43456 2466 ospf6_send_lsupdate(on, NULL, oh);
d62a17ae 2467 }
2468
2469 /* The addresses used for retransmissions are different from those sent
2470 the
2471 first time and so we need to separate them here.
2472 */
2473 memset(sendbuf, 0, iobuflen);
2474 oh = (struct ospf6_header *)sendbuf;
2475 lsupdate = (struct ospf6_lsupdate *)((caddr_t)oh
2476 + sizeof(struct ospf6_header));
d7c0a89a 2477 p = (uint8_t *)((caddr_t)lsupdate + sizeof(struct ospf6_lsupdate));
d62a17ae 2478 lsa_cnt = 0;
2479
2e37407f 2480 for (ALL_LSDB(on->retrans_list, lsa, lsanext)) {
d62a17ae 2481 /* MTU check */
2482 if ((p - sendbuf + (unsigned int)OSPF6_LSA_SIZE(lsa->header))
2483 > ospf6_packet_max(on->ospf6_if)) {
1ba43456
CS
2484 if (lsa_cnt) {
2485 oh->type = OSPF6_MESSAGE_TYPE_LSUPDATE;
2486 oh->length = htons(p - sendbuf);
2487 lsupdate->lsa_number = htonl(lsa_cnt);
2488
996c9314
LB
2489 if (on->ospf6_if->state
2490 == OSPF6_INTERFACE_POINTTOPOINT) {
1ba43456
CS
2491 ospf6_send(on->ospf6_if->linklocal_addr,
2492 &allspfrouters6,
2493 on->ospf6_if, oh);
2494 } else {
2495 ospf6_send(on->ospf6_if->linklocal_addr,
2496 &on->linklocal_addr,
2497 on->ospf6_if, oh);
2498 }
2499
2500 memset(sendbuf, 0, iobuflen);
2501 oh = (struct ospf6_header *)sendbuf;
996c9314
LB
2502 lsupdate = (struct ospf6_lsupdate
2503 *)((caddr_t)oh
2504 + sizeof(struct
2505 ospf6_header));
d7c0a89a
QY
2506 p = (uint8_t *)((caddr_t)lsupdate
2507 + sizeof(struct
2508 ospf6_lsupdate));
1ba43456
CS
2509 lsa_cnt = 0;
2510 }
d62a17ae 2511 }
2512
2513 ospf6_lsa_age_update_to_send(lsa, on->ospf6_if->transdelay);
2514 memcpy(p, lsa->header, OSPF6_LSA_SIZE(lsa->header));
2515 p += OSPF6_LSA_SIZE(lsa->header);
2516 lsa_cnt++;
2517 }
2518
2519 if (lsa_cnt) {
2520 oh->type = OSPF6_MESSAGE_TYPE_LSUPDATE;
2521 oh->length = htons(p - sendbuf);
2522 lsupdate->lsa_number = htonl(lsa_cnt);
2523
2524 if (on->ospf6_if->state == OSPF6_INTERFACE_POINTTOPOINT)
2525 ospf6_send(on->ospf6_if->linklocal_addr,
2526 &allspfrouters6, on->ospf6_if, oh);
2527 else
2528 ospf6_send(on->ospf6_if->linklocal_addr,
2529 &on->linklocal_addr, on->ospf6_if, oh);
2530 }
2531
2532 if (on->lsupdate_list->count != 0) {
2533 on->thread_send_lsupdate = NULL;
2534 thread_add_event(master, ospf6_lsupdate_send_neighbor, on, 0,
2535 &on->thread_send_lsupdate);
2536 } else if (on->retrans_list->count != 0) {
2537 on->thread_send_lsupdate = NULL;
2538 thread_add_timer(master, ospf6_lsupdate_send_neighbor, on,
2539 on->ospf6_if->rxmt_interval,
2540 &on->thread_send_lsupdate);
2541 }
2542 return 0;
718e3744 2543}
2544
76249532
CS
2545int ospf6_lsupdate_send_neighbor_now(struct ospf6_neighbor *on,
2546 struct ospf6_lsa *lsa)
2547{
2548 struct ospf6_header *oh;
2549 struct ospf6_lsupdate *lsupdate;
d7c0a89a 2550 uint8_t *p;
76249532
CS
2551 int lsa_cnt = 0;
2552
2553 memset(sendbuf, 0, iobuflen);
2554 oh = (struct ospf6_header *)sendbuf;
2555 lsupdate = (struct ospf6_lsupdate *)((caddr_t)oh
2556 + sizeof(struct ospf6_header));
2557
d7c0a89a 2558 p = (uint8_t *)((caddr_t)lsupdate + sizeof(struct ospf6_lsupdate));
76249532
CS
2559 ospf6_lsa_age_update_to_send(lsa, on->ospf6_if->transdelay);
2560 memcpy(p, lsa->header, OSPF6_LSA_SIZE(lsa->header));
2561 p += OSPF6_LSA_SIZE(lsa->header);
2562 lsa_cnt++;
2563
2564 oh->type = OSPF6_MESSAGE_TYPE_LSUPDATE;
2565 oh->length = htons(p - sendbuf);
2566 lsupdate->lsa_number = htonl(lsa_cnt);
2567
996c9314 2568 if (IS_OSPF6_DEBUG_FLOODING
f44d0f5e 2569 || IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_LSUPDATE, SEND_HDR))
15569c58
DA
2570 zlog_debug("%s: Send lsupdate with lsa %s (age %u)", __func__,
2571 lsa->name, ntohs(lsa->header->age));
76249532
CS
2572
2573 ospf6_send_lsupdate(on, NULL, oh);
2574
2575 return 0;
2576}
2577
d62a17ae 2578int ospf6_lsupdate_send_interface(struct thread *thread)
718e3744 2579{
d62a17ae 2580 struct ospf6_interface *oi;
2581 struct ospf6_header *oh;
2582 struct ospf6_lsupdate *lsupdate;
d7c0a89a 2583 uint8_t *p;
d62a17ae 2584 int lsa_cnt;
2e37407f 2585 struct ospf6_lsa *lsa, *lsanext;
d62a17ae 2586
2587 oi = (struct ospf6_interface *)THREAD_ARG(thread);
2588 oi->thread_send_lsupdate = (struct thread *)NULL;
2589
2590 if (oi->state <= OSPF6_INTERFACE_WAITING) {
f44d0f5e 2591 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_LSUPDATE,
2592 SEND_HDR))
d62a17ae 2593 zlog_debug(
2594 "Quit to send LSUpdate to interface %s state %s",
2595 oi->interface->name,
2596 ospf6_interface_state_str[oi->state]);
2597 return 0;
2598 }
2599
2600 /* if we have nothing to send, return */
2601 if (oi->lsupdate_list->count == 0)
2602 return 0;
2603
2604 memset(sendbuf, 0, iobuflen);
2605 oh = (struct ospf6_header *)sendbuf;
2606 lsupdate = (struct ospf6_lsupdate *)((caddr_t)oh
2607 + sizeof(struct ospf6_header));
2608
d7c0a89a 2609 p = (uint8_t *)((caddr_t)lsupdate + sizeof(struct ospf6_lsupdate));
d62a17ae 2610 lsa_cnt = 0;
2611
2e37407f 2612 for (ALL_LSDB(oi->lsupdate_list, lsa, lsanext)) {
d62a17ae 2613 /* MTU check */
2614 if ((p - sendbuf + ((unsigned int)OSPF6_LSA_SIZE(lsa->header)))
2615 > ospf6_packet_max(oi)) {
1ba43456
CS
2616 if (lsa_cnt) {
2617 oh->type = OSPF6_MESSAGE_TYPE_LSUPDATE;
2618 oh->length = htons(p - sendbuf);
2619 lsupdate->lsa_number = htonl(lsa_cnt);
2620
2621 ospf6_send_lsupdate(NULL, oi, oh);
43855e3d 2622 if (IS_OSPF6_DEBUG_MESSAGE(
996c9314 2623 OSPF6_MESSAGE_TYPE_LSUPDATE, SEND))
43855e3d 2624 zlog_debug("%s: LSUpdate length %d",
15569c58 2625 __func__, ntohs(oh->length));
1ba43456
CS
2626
2627 memset(sendbuf, 0, iobuflen);
2628 oh = (struct ospf6_header *)sendbuf;
996c9314
LB
2629 lsupdate = (struct ospf6_lsupdate
2630 *)((caddr_t)oh
2631 + sizeof(struct
2632 ospf6_header));
1ba43456 2633
d7c0a89a
QY
2634 p = (uint8_t *)((caddr_t)lsupdate
2635 + sizeof(struct
2636 ospf6_lsupdate));
1ba43456
CS
2637 lsa_cnt = 0;
2638 }
d62a17ae 2639 }
2640
2641 ospf6_lsa_age_update_to_send(lsa, oi->transdelay);
2642 memcpy(p, lsa->header, OSPF6_LSA_SIZE(lsa->header));
2643 p += OSPF6_LSA_SIZE(lsa->header);
2644 lsa_cnt++;
2645
e2e60c48 2646 assert(lsa->lock == 2);
d62a17ae 2647 ospf6_lsdb_remove(lsa, oi->lsupdate_list);
2648 }
2649
2650 if (lsa_cnt) {
d62a17ae 2651 oh->type = OSPF6_MESSAGE_TYPE_LSUPDATE;
2652 oh->length = htons(p - sendbuf);
1ba43456 2653 lsupdate->lsa_number = htonl(lsa_cnt);
d62a17ae 2654
1ba43456 2655 ospf6_send_lsupdate(NULL, oi, oh);
d62a17ae 2656 }
2657
2658 if (oi->lsupdate_list->count > 0) {
2659 oi->thread_send_lsupdate = NULL;
2660 thread_add_event(master, ospf6_lsupdate_send_interface, oi, 0,
2661 &oi->thread_send_lsupdate);
2662 }
2663
2664 return 0;
718e3744 2665}
2666
d62a17ae 2667int ospf6_lsack_send_neighbor(struct thread *thread)
718e3744 2668{
d62a17ae 2669 struct ospf6_neighbor *on;
2670 struct ospf6_header *oh;
d7c0a89a 2671 uint8_t *p;
2e37407f 2672 struct ospf6_lsa *lsa, *lsanext;
d62a17ae 2673 int lsa_cnt = 0;
2674
2675 on = (struct ospf6_neighbor *)THREAD_ARG(thread);
2676 on->thread_send_lsack = (struct thread *)NULL;
2677
2678 if (on->state < OSPF6_NEIGHBOR_EXCHANGE) {
f44d0f5e 2679 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_LSACK, SEND_HDR))
d62a17ae 2680 zlog_debug("Quit to send LSAck to neighbor %s state %s",
2681 on->name,
2682 ospf6_neighbor_state_str[on->state]);
2683 return 0;
2684 }
2685
2686 /* if we have nothing to send, return */
2687 if (on->lsack_list->count == 0)
2688 return 0;
2689
2690 memset(sendbuf, 0, iobuflen);
2691 oh = (struct ospf6_header *)sendbuf;
2692
d7c0a89a 2693 p = (uint8_t *)((caddr_t)oh + sizeof(struct ospf6_header));
d62a17ae 2694
2e37407f 2695 for (ALL_LSDB(on->lsack_list, lsa, lsanext)) {
d62a17ae 2696 /* MTU check */
2697 if (p - sendbuf + sizeof(struct ospf6_lsa_header)
2698 > ospf6_packet_max(on->ospf6_if)) {
2699 /* if we run out of packet size/space here,
2700 better to try again soon. */
1ba43456
CS
2701 if (lsa_cnt) {
2702 oh->type = OSPF6_MESSAGE_TYPE_LSACK;
2703 oh->length = htons(p - sendbuf);
2704
43855e3d
CS
2705 on->ospf6_if->ls_ack_out++;
2706
1ba43456 2707 ospf6_send(on->ospf6_if->linklocal_addr,
996c9314
LB
2708 &on->linklocal_addr, on->ospf6_if,
2709 oh);
1ba43456
CS
2710
2711 memset(sendbuf, 0, iobuflen);
2712 oh = (struct ospf6_header *)sendbuf;
d7c0a89a
QY
2713 p = (uint8_t *)((caddr_t)oh
2714 + sizeof(struct ospf6_header));
1ba43456
CS
2715 lsa_cnt = 0;
2716 }
d62a17ae 2717 }
2718
2719 ospf6_lsa_age_update_to_send(lsa, on->ospf6_if->transdelay);
2720 memcpy(p, lsa->header, sizeof(struct ospf6_lsa_header));
2721 p += sizeof(struct ospf6_lsa_header);
2722
e2e60c48 2723 assert(lsa->lock == 2);
d62a17ae 2724 ospf6_lsdb_remove(lsa, on->lsack_list);
2725 lsa_cnt++;
2726 }
2727
2728 if (lsa_cnt) {
2729 oh->type = OSPF6_MESSAGE_TYPE_LSACK;
2730 oh->length = htons(p - sendbuf);
2731
43855e3d
CS
2732 on->ospf6_if->ls_ack_out++;
2733
d62a17ae 2734 ospf6_send(on->ospf6_if->linklocal_addr, &on->linklocal_addr,
2735 on->ospf6_if, oh);
2736 }
2737
2738 if (on->lsack_list->count > 0)
2739 thread_add_event(master, ospf6_lsack_send_neighbor, on, 0,
2740 &on->thread_send_lsack);
2741
2742 return 0;
718e3744 2743}
2744
d62a17ae 2745int ospf6_lsack_send_interface(struct thread *thread)
718e3744 2746{
d62a17ae 2747 struct ospf6_interface *oi;
2748 struct ospf6_header *oh;
d7c0a89a 2749 uint8_t *p;
2e37407f 2750 struct ospf6_lsa *lsa, *lsanext;
d62a17ae 2751 int lsa_cnt = 0;
2752
2753 oi = (struct ospf6_interface *)THREAD_ARG(thread);
2754 oi->thread_send_lsack = (struct thread *)NULL;
2755
2756 if (oi->state <= OSPF6_INTERFACE_WAITING) {
f44d0f5e 2757 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_LSACK, SEND_HDR))
d62a17ae 2758 zlog_debug(
2759 "Quit to send LSAck to interface %s state %s",
2760 oi->interface->name,
2761 ospf6_interface_state_str[oi->state]);
2762 return 0;
2763 }
2764
2765 /* if we have nothing to send, return */
2766 if (oi->lsack_list->count == 0)
2767 return 0;
2768
2769 memset(sendbuf, 0, iobuflen);
2770 oh = (struct ospf6_header *)sendbuf;
2771
d7c0a89a 2772 p = (uint8_t *)((caddr_t)oh + sizeof(struct ospf6_header));
d62a17ae 2773
2e37407f 2774 for (ALL_LSDB(oi->lsack_list, lsa, lsanext)) {
d62a17ae 2775 /* MTU check */
2776 if (p - sendbuf + sizeof(struct ospf6_lsa_header)
2777 > ospf6_packet_max(oi)) {
2778 /* if we run out of packet size/space here,
2779 better to try again soon. */
2780 THREAD_OFF(oi->thread_send_lsack);
2781 thread_add_event(master, ospf6_lsack_send_interface, oi,
2782 0, &oi->thread_send_lsack);
2783
ccf260c4 2784 ospf6_lsa_unlock(lsa);
2785 if (lsanext)
2786 ospf6_lsa_unlock(lsanext);
d62a17ae 2787 break;
2788 }
2789
2790 ospf6_lsa_age_update_to_send(lsa, oi->transdelay);
2791 memcpy(p, lsa->header, sizeof(struct ospf6_lsa_header));
2792 p += sizeof(struct ospf6_lsa_header);
2793
e2e60c48 2794 assert(lsa->lock == 2);
d62a17ae 2795 ospf6_lsdb_remove(lsa, oi->lsack_list);
2796 lsa_cnt++;
2797 }
2798
2799 if (lsa_cnt) {
2800 oh->type = OSPF6_MESSAGE_TYPE_LSACK;
2801 oh->length = htons(p - sendbuf);
2802
2803 if ((oi->state == OSPF6_INTERFACE_POINTTOPOINT)
2804 || (oi->state == OSPF6_INTERFACE_DR)
2805 || (oi->state == OSPF6_INTERFACE_BDR))
2806 ospf6_send(oi->linklocal_addr, &allspfrouters6, oi, oh);
2807 else
2808 ospf6_send(oi->linklocal_addr, &alldrouters6, oi, oh);
2809 }
2810
2811 if (oi->lsack_list->count > 0)
2812 thread_add_event(master, ospf6_lsack_send_interface, oi, 0,
2813 &oi->thread_send_lsack);
2814
2815 return 0;
718e3744 2816}
2817
508e53e2 2818/* Commands */
f44d0f5e 2819DEFUN(debug_ospf6_message, debug_ospf6_message_cmd,
2820 "debug ospf6 message <unknown|hello|dbdesc|lsreq|lsupdate|lsack|all> [<send|recv|send-hdr|recv-hdr>]",
2821 DEBUG_STR OSPF6_STR
2822 "Debug OSPFv3 message\n"
2823 "Debug Unknown message\n"
2824 "Debug Hello message\n"
2825 "Debug Database Description message\n"
2826 "Debug Link State Request message\n"
2827 "Debug Link State Update message\n"
2828 "Debug Link State Acknowledgement message\n"
2829 "Debug All message\n"
2830 "Debug only sending message, entire packet\n"
2831 "Debug only receiving message, entire packet\n"
2832 "Debug only sending message, header only\n"
2833 "Debug only receiving message, header only\n")
718e3744 2834{
d62a17ae 2835 int idx_packet = 3;
2836 int idx_send_recv = 4;
2837 unsigned char level = 0;
2838 int type = 0;
2839 int i;
2840
2841 /* check type */
2842 if (!strncmp(argv[idx_packet]->arg, "u", 1))
2843 type = OSPF6_MESSAGE_TYPE_UNKNOWN;
2844 else if (!strncmp(argv[idx_packet]->arg, "h", 1))
2845 type = OSPF6_MESSAGE_TYPE_HELLO;
2846 else if (!strncmp(argv[idx_packet]->arg, "d", 1))
2847 type = OSPF6_MESSAGE_TYPE_DBDESC;
2848 else if (!strncmp(argv[idx_packet]->arg, "lsr", 3))
2849 type = OSPF6_MESSAGE_TYPE_LSREQ;
2850 else if (!strncmp(argv[idx_packet]->arg, "lsu", 3))
2851 type = OSPF6_MESSAGE_TYPE_LSUPDATE;
2852 else if (!strncmp(argv[idx_packet]->arg, "lsa", 3))
2853 type = OSPF6_MESSAGE_TYPE_LSACK;
2854 else if (!strncmp(argv[idx_packet]->arg, "a", 1))
2855 type = OSPF6_MESSAGE_TYPE_ALL;
2856
2857 if (argc == 4)
2858 level = OSPF6_DEBUG_MESSAGE_SEND | OSPF6_DEBUG_MESSAGE_RECV;
f44d0f5e 2859 else if (!strncmp(argv[idx_send_recv]->arg, "send-h", 6))
2860 level = OSPF6_DEBUG_MESSAGE_SEND_HDR;
d62a17ae 2861 else if (!strncmp(argv[idx_send_recv]->arg, "s", 1))
2862 level = OSPF6_DEBUG_MESSAGE_SEND;
f44d0f5e 2863 else if (!strncmp(argv[idx_send_recv]->arg, "recv-h", 6))
2864 level = OSPF6_DEBUG_MESSAGE_RECV_HDR;
d62a17ae 2865 else if (!strncmp(argv[idx_send_recv]->arg, "r", 1))
2866 level = OSPF6_DEBUG_MESSAGE_RECV;
2867
2868 if (type == OSPF6_MESSAGE_TYPE_ALL) {
2869 for (i = 0; i < 6; i++)
2870 OSPF6_DEBUG_MESSAGE_ON(i, level);
2871 } else
2872 OSPF6_DEBUG_MESSAGE_ON(type, level);
2873
2874 return CMD_SUCCESS;
718e3744 2875}
2876
f44d0f5e 2877DEFUN(no_debug_ospf6_message, no_debug_ospf6_message_cmd,
2878 "no debug ospf6 message <unknown|hello|dbdesc|lsreq|lsupdate|lsack|all> [<send|recv|send-hdr|recv-hdr>]",
2879 NO_STR DEBUG_STR OSPF6_STR
2880 "Debug OSPFv3 message\n"
2881 "Debug Unknown message\n"
2882 "Debug Hello message\n"
2883 "Debug Database Description message\n"
2884 "Debug Link State Request message\n"
2885 "Debug Link State Update message\n"
2886 "Debug Link State Acknowledgement message\n"
2887 "Debug All message\n"
2888 "Debug only sending message, entire pkt\n"
2889 "Debug only receiving message, entire pkt\n"
2890 "Debug only sending message, header only\n"
2891 "Debug only receiving message, header only\n")
508e53e2 2892{
d62a17ae 2893 int idx_packet = 4;
2894 int idx_send_recv = 5;
2895 unsigned char level = 0;
2896 int type = 0;
2897 int i;
2898
2899 /* check type */
2900 if (!strncmp(argv[idx_packet]->arg, "u", 1))
2901 type = OSPF6_MESSAGE_TYPE_UNKNOWN;
2902 else if (!strncmp(argv[idx_packet]->arg, "h", 1))
2903 type = OSPF6_MESSAGE_TYPE_HELLO;
2904 else if (!strncmp(argv[idx_packet]->arg, "d", 1))
2905 type = OSPF6_MESSAGE_TYPE_DBDESC;
2906 else if (!strncmp(argv[idx_packet]->arg, "lsr", 3))
2907 type = OSPF6_MESSAGE_TYPE_LSREQ;
2908 else if (!strncmp(argv[idx_packet]->arg, "lsu", 3))
2909 type = OSPF6_MESSAGE_TYPE_LSUPDATE;
2910 else if (!strncmp(argv[idx_packet]->arg, "lsa", 3))
2911 type = OSPF6_MESSAGE_TYPE_LSACK;
2912 else if (!strncmp(argv[idx_packet]->arg, "a", 1))
2913 type = OSPF6_MESSAGE_TYPE_ALL;
2914
2915 if (argc == 5)
f44d0f5e 2916 level = OSPF6_DEBUG_MESSAGE_SEND | OSPF6_DEBUG_MESSAGE_RECV
2917 | OSPF6_DEBUG_MESSAGE_SEND_HDR
2918 | OSPF6_DEBUG_MESSAGE_RECV_HDR;
2919 else if (!strncmp(argv[idx_send_recv]->arg, "send-h", 6))
2920 level = OSPF6_DEBUG_MESSAGE_SEND_HDR;
d62a17ae 2921 else if (!strncmp(argv[idx_send_recv]->arg, "s", 1))
2922 level = OSPF6_DEBUG_MESSAGE_SEND;
f44d0f5e 2923 else if (!strncmp(argv[idx_send_recv]->arg, "recv-h", 6))
2924 level = OSPF6_DEBUG_MESSAGE_RECV_HDR;
d62a17ae 2925 else if (!strncmp(argv[idx_send_recv]->arg, "r", 1))
2926 level = OSPF6_DEBUG_MESSAGE_RECV;
2927
2928 if (type == OSPF6_MESSAGE_TYPE_ALL) {
2929 for (i = 0; i < 6; i++)
2930 OSPF6_DEBUG_MESSAGE_OFF(i, level);
2931 } else
2932 OSPF6_DEBUG_MESSAGE_OFF(type, level);
2933
2934 return CMD_SUCCESS;
718e3744 2935}
2936
508e53e2 2937
d62a17ae 2938int config_write_ospf6_debug_message(struct vty *vty)
718e3744 2939{
d62a17ae 2940 const char *type_str[] = {"unknown", "hello", "dbdesc",
2941 "lsreq", "lsupdate", "lsack"};
f44d0f5e 2942 unsigned char s = 0, r = 0, sh = 0, rh = 0;
d62a17ae 2943 int i;
2944
2945 for (i = 0; i < 6; i++) {
f44d0f5e 2946 if (IS_OSPF6_DEBUG_MESSAGE_ENABLED(i, SEND))
d62a17ae 2947 s |= 1 << i;
f44d0f5e 2948 if (IS_OSPF6_DEBUG_MESSAGE_ENABLED(i, RECV))
d62a17ae 2949 r |= 1 << i;
2950 }
2951
f44d0f5e 2952 for (i = 0; i < 6; i++) {
2953 if (IS_OSPF6_DEBUG_MESSAGE_ENABLED(i, SEND_HDR))
2954 sh |= 1 << i;
2955 if (IS_OSPF6_DEBUG_MESSAGE_ENABLED(i, RECV_HDR))
2956 rh |= 1 << i;
2957 }
2958
d62a17ae 2959 if (s == 0x3f && r == 0x3f) {
2960 vty_out(vty, "debug ospf6 message all\n");
2961 return 0;
2962 }
2963
2964 if (s == 0x3f && r == 0) {
2965 vty_out(vty, "debug ospf6 message all send\n");
2966 return 0;
2967 } else if (s == 0 && r == 0x3f) {
2968 vty_out(vty, "debug ospf6 message all recv\n");
2969 return 0;
2970 }
2971
f44d0f5e 2972 if (sh == 0x3f && rh == 0) {
2973 vty_out(vty, "debug ospf6 message all send-hdr\n");
2974 return 0;
2975 } else if (sh == 0 && rh == 0x3f) {
2976 vty_out(vty, "debug ospf6 message all recv-hdr\n");
2977 return 0;
2978 }
2979
d62a17ae 2980 /* Unknown message is logged by default */
2981 if (!IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN, SEND)
2982 && !IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
2983 vty_out(vty, "no debug ospf6 message unknown\n");
2984 else if (!IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN, SEND))
2985 vty_out(vty, "no debug ospf6 message unknown send\n");
2986 else if (!IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
2987 vty_out(vty, "no debug ospf6 message unknown recv\n");
2988
2989 for (i = 1; i < 6; i++) {
f44d0f5e 2990 if (IS_OSPF6_DEBUG_MESSAGE_ENABLED(i, SEND)
c9ac777a 2991 && IS_OSPF6_DEBUG_MESSAGE_ENABLED(i, RECV)) {
d62a17ae 2992 vty_out(vty, "debug ospf6 message %s\n", type_str[i]);
c9ac777a
IR
2993 continue;
2994 }
2995
2996 if (IS_OSPF6_DEBUG_MESSAGE_ENABLED(i, SEND))
d62a17ae 2997 vty_out(vty, "debug ospf6 message %s send\n",
2998 type_str[i]);
c9ac777a
IR
2999 else if (IS_OSPF6_DEBUG_MESSAGE_ENABLED(i, SEND_HDR))
3000 vty_out(vty, "debug ospf6 message %s send-hdr\n",
d62a17ae 3001 type_str[i]);
c9ac777a
IR
3002
3003 if (IS_OSPF6_DEBUG_MESSAGE_ENABLED(i, RECV))
3004 vty_out(vty, "debug ospf6 message %s recv\n",
f44d0f5e 3005 type_str[i]);
3006 else if (IS_OSPF6_DEBUG_MESSAGE_ENABLED(i, RECV_HDR))
3007 vty_out(vty, "debug ospf6 message %s recv-hdr\n",
3008 type_str[i]);
d62a17ae 3009 }
3010
3011 return 0;
718e3744 3012}
3013
d62a17ae 3014void install_element_ospf6_debug_message(void)
508e53e2 3015{
d62a17ae 3016 install_element(ENABLE_NODE, &debug_ospf6_message_cmd);
3017 install_element(ENABLE_NODE, &no_debug_ospf6_message_cmd);
3018 install_element(CONFIG_NODE, &debug_ospf6_message_cmd);
3019 install_element(CONFIG_NODE, &no_debug_ospf6_message_cmd);
508e53e2 3020}