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