1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Copyright (C) 2003 Yasuhiro Ohara
14 #include "lib_errors.h"
18 #include "ospf6_proto.h"
19 #include "ospf6_lsa.h"
20 #include "ospf6_lsdb.h"
21 #include "ospf6_top.h"
22 #include "ospf6_network.h"
23 #include "ospf6_message.h"
25 #include "ospf6_area.h"
26 #include "ospf6_neighbor.h"
27 #include "ospf6_interface.h"
29 /* for structures and macros ospf6_lsa_examin() needs */
30 #include "ospf6_abr.h"
31 #include "ospf6_asbr.h"
32 #include "ospf6_intra.h"
34 #include "ospf6_flood.h"
37 #include <netinet/ip6.h>
38 #include "lib/libospf.h"
39 #include "lib/keychain.h"
40 #include "ospf6_auth_trailer.h"
42 DEFINE_MTYPE_STATIC(OSPF6D
, OSPF6_MESSAGE
, "OSPF6 message");
43 DEFINE_MTYPE_STATIC(OSPF6D
, OSPF6_PACKET
, "OSPF6 packet");
44 DEFINE_MTYPE_STATIC(OSPF6D
, OSPF6_FIFO
, "OSPF6 FIFO queue");
46 unsigned char conf_debug_ospf6_message
[6] = {0x03, 0, 0, 0, 0, 0};
48 const char *ospf6_message_type(int type
)
51 case OSPF6_MESSAGE_TYPE_HELLO
:
53 case OSPF6_MESSAGE_TYPE_DBDESC
:
55 case OSPF6_MESSAGE_TYPE_LSREQ
:
57 case OSPF6_MESSAGE_TYPE_LSUPDATE
:
59 case OSPF6_MESSAGE_TYPE_LSACK
:
61 case OSPF6_MESSAGE_TYPE_UNKNOWN
:
67 /* Minimum (besides the standard OSPF packet header) lengths for OSPF
68 packets of particular types, offset is the "type" field. */
69 const uint16_t ospf6_packet_minlen
[OSPF6_MESSAGE_TYPE_ALL
] = {
72 OSPF6_DB_DESC_MIN_SIZE
,
73 OSPF6_LS_REQ_MIN_SIZE
,
74 OSPF6_LS_UPD_MIN_SIZE
,
75 OSPF6_LS_ACK_MIN_SIZE
};
77 /* Minimum (besides the standard LSA header) lengths for LSAs of particular
78 types, offset is the "LSA function code" portion of "LSA type" field. */
79 const uint16_t ospf6_lsa_minlen
[OSPF6_LSTYPE_SIZE
] = {
81 /* 0x2001 */ OSPF6_ROUTER_LSA_MIN_SIZE
,
82 /* 0x2002 */ OSPF6_NETWORK_LSA_MIN_SIZE
,
83 /* 0x2003 */ OSPF6_INTER_PREFIX_LSA_MIN_SIZE
,
84 /* 0x2004 */ OSPF6_INTER_ROUTER_LSA_FIX_SIZE
,
85 /* 0x4005 */ OSPF6_AS_EXTERNAL_LSA_MIN_SIZE
,
87 /* 0x2007 */ OSPF6_AS_EXTERNAL_LSA_MIN_SIZE
,
88 /* 0x0008 */ OSPF6_LINK_LSA_MIN_SIZE
,
89 /* 0x2009 */ OSPF6_INTRA_PREFIX_LSA_MIN_SIZE
,
91 /* 0x000b */ OSPF6_GRACE_LSA_MIN_SIZE
};
95 static void ospf6_header_print(struct ospf6_header
*oh
)
97 zlog_debug(" OSPFv%d Type:%d Len:%hu Router-ID:%pI4", oh
->version
,
98 oh
->type
, ntohs(oh
->length
), &oh
->router_id
);
99 zlog_debug(" Area-ID:%pI4 Cksum:%hx Instance-ID:%d", &oh
->area_id
,
100 ntohs(oh
->checksum
), oh
->instance_id
);
103 void ospf6_hello_print(struct ospf6_header
*oh
, int action
)
105 struct ospf6_hello
*hello
;
109 ospf6_header_print(oh
);
110 assert(oh
->type
== OSPF6_MESSAGE_TYPE_HELLO
);
112 hello
= (struct ospf6_hello
*)((caddr_t
)oh
113 + sizeof(struct ospf6_header
));
115 ospf6_options_printbuf(hello
->options
, options
, sizeof(options
));
117 zlog_debug(" I/F-Id:%ld Priority:%d Option:%s",
118 (unsigned long)ntohl(hello
->interface_id
), hello
->priority
,
120 zlog_debug(" HelloInterval:%hu DeadInterval:%hu",
121 ntohs(hello
->hello_interval
), ntohs(hello
->dead_interval
));
122 zlog_debug(" DR:%pI4 BDR:%pI4", &hello
->drouter
, &hello
->bdrouter
);
124 if ((IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
)
125 && action
== OSPF6_ACTION_RECV
)
126 || (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, SEND
)
127 && action
== OSPF6_ACTION_SEND
)) {
129 for (p
= (char *)((caddr_t
)hello
+ sizeof(struct ospf6_hello
));
130 p
+ sizeof(uint32_t) <= OSPF6_MESSAGE_END(oh
);
131 p
+= sizeof(uint32_t))
132 zlog_debug(" Neighbor: %pI4", (in_addr_t
*)p
);
134 assert(p
== OSPF6_MESSAGE_END(oh
));
138 void ospf6_dbdesc_print(struct ospf6_header
*oh
, int action
)
140 struct ospf6_dbdesc
*dbdesc
;
144 ospf6_header_print(oh
);
145 assert(oh
->type
== OSPF6_MESSAGE_TYPE_DBDESC
);
147 dbdesc
= (struct ospf6_dbdesc
*)((caddr_t
)oh
148 + sizeof(struct ospf6_header
));
150 ospf6_options_printbuf(dbdesc
->options
, options
, sizeof(options
));
152 zlog_debug(" MBZ: %#x Option: %s IfMTU: %hu", dbdesc
->reserved1
,
153 options
, ntohs(dbdesc
->ifmtu
));
154 zlog_debug(" MBZ: %#x Bits: %s%s%s SeqNum: %#lx", dbdesc
->reserved2
,
155 (CHECK_FLAG(dbdesc
->bits
, OSPF6_DBDESC_IBIT
) ? "I" : "-"),
156 (CHECK_FLAG(dbdesc
->bits
, OSPF6_DBDESC_MBIT
) ? "M" : "-"),
157 (CHECK_FLAG(dbdesc
->bits
, OSPF6_DBDESC_MSBIT
) ? "m" : "s"),
158 (unsigned long)ntohl(dbdesc
->seqnum
));
160 if ((IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
)
161 && action
== OSPF6_ACTION_RECV
)
162 || (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, SEND
)
163 && action
== OSPF6_ACTION_SEND
)) {
165 for (p
= (char *)((caddr_t
)dbdesc
166 + sizeof(struct ospf6_dbdesc
));
167 p
+ sizeof(struct ospf6_lsa_header
)
168 <= OSPF6_MESSAGE_END(oh
);
169 p
+= sizeof(struct ospf6_lsa_header
))
170 ospf6_lsa_header_print_raw(
171 (struct ospf6_lsa_header
*)p
);
173 assert(p
== OSPF6_MESSAGE_END(oh
));
177 void ospf6_lsreq_print(struct ospf6_header
*oh
, int action
)
181 ospf6_header_print(oh
);
182 assert(oh
->type
== OSPF6_MESSAGE_TYPE_LSREQ
);
184 if ((IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
)
185 && action
== OSPF6_ACTION_RECV
)
186 || (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, SEND
)
187 && action
== OSPF6_ACTION_SEND
)) {
189 for (p
= (char *)((caddr_t
)oh
+ sizeof(struct ospf6_header
));
190 p
+ sizeof(struct ospf6_lsreq_entry
)
191 <= OSPF6_MESSAGE_END(oh
);
192 p
+= sizeof(struct ospf6_lsreq_entry
)) {
193 struct ospf6_lsreq_entry
*e
=
194 (struct ospf6_lsreq_entry
*)p
;
196 zlog_debug(" [%s Id:%pI4 Adv:%pI4]",
197 ospf6_lstype_name(e
->type
), &e
->id
,
201 assert(p
== OSPF6_MESSAGE_END(oh
));
205 void ospf6_lsupdate_print(struct ospf6_header
*oh
, int action
)
207 struct ospf6_lsupdate
*lsupdate
;
211 ospf6_header_print(oh
);
212 assert(oh
->type
== OSPF6_MESSAGE_TYPE_LSUPDATE
);
214 lsupdate
= (struct ospf6_lsupdate
*)((caddr_t
)oh
215 + sizeof(struct ospf6_header
));
217 num
= ntohl(lsupdate
->lsa_number
);
218 zlog_debug(" Number of LSA: %ld", num
);
220 if ((IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
)
221 && action
== OSPF6_ACTION_RECV
)
222 || (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, SEND
)
223 && action
== OSPF6_ACTION_SEND
)) {
225 for (p
= (char *)((caddr_t
)lsupdate
226 + sizeof(struct ospf6_lsupdate
));
227 p
< OSPF6_MESSAGE_END(oh
)
228 && p
+ OSPF6_LSA_SIZE(p
) <= OSPF6_MESSAGE_END(oh
);
229 p
+= OSPF6_LSA_SIZE(p
)) {
230 ospf6_lsa_header_print_raw(
231 (struct ospf6_lsa_header
*)p
);
234 assert(p
== OSPF6_MESSAGE_END(oh
));
238 void ospf6_lsack_print(struct ospf6_header
*oh
, int action
)
242 ospf6_header_print(oh
);
243 assert(oh
->type
== OSPF6_MESSAGE_TYPE_LSACK
);
245 if ((IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
)
246 && action
== OSPF6_ACTION_RECV
)
247 || (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, SEND
)
248 && action
== OSPF6_ACTION_SEND
)) {
250 for (p
= (char *)((caddr_t
)oh
+ sizeof(struct ospf6_header
));
251 p
+ sizeof(struct ospf6_lsa_header
)
252 <= OSPF6_MESSAGE_END(oh
);
253 p
+= sizeof(struct ospf6_lsa_header
))
254 ospf6_lsa_header_print_raw(
255 (struct ospf6_lsa_header
*)p
);
257 assert(p
== OSPF6_MESSAGE_END(oh
));
261 static struct ospf6_packet
*ospf6_packet_new(size_t size
)
263 struct ospf6_packet
*new;
265 new = XCALLOC(MTYPE_OSPF6_PACKET
, sizeof(struct ospf6_packet
));
266 new->s
= stream_new(size
);
271 static void ospf6_packet_free(struct ospf6_packet
*op
)
276 XFREE(MTYPE_OSPF6_PACKET
, op
);
279 struct ospf6_fifo
*ospf6_fifo_new(void)
281 struct ospf6_fifo
*new;
283 new = XCALLOC(MTYPE_OSPF6_FIFO
, sizeof(struct ospf6_fifo
));
287 /* Add new packet to fifo. */
288 static void ospf6_fifo_push(struct ospf6_fifo
*fifo
, struct ospf6_packet
*op
)
291 fifo
->tail
->next
= op
;
300 /* Add new packet to head of fifo. */
301 static void ospf6_fifo_push_head(struct ospf6_fifo
*fifo
,
302 struct ospf6_packet
*op
)
304 op
->next
= fifo
->head
;
306 if (fifo
->tail
== NULL
)
314 /* Delete first packet from fifo. */
315 static struct ospf6_packet
*ospf6_fifo_pop(struct ospf6_fifo
*fifo
)
317 struct ospf6_packet
*op
;
322 fifo
->head
= op
->next
;
324 if (fifo
->head
== NULL
)
333 /* Return first fifo entry. */
334 static struct ospf6_packet
*ospf6_fifo_head(struct ospf6_fifo
*fifo
)
339 /* Flush ospf packet fifo. */
340 void ospf6_fifo_flush(struct ospf6_fifo
*fifo
)
342 struct ospf6_packet
*op
;
343 struct ospf6_packet
*next
;
345 for (op
= fifo
->head
; op
; op
= next
) {
347 ospf6_packet_free(op
);
349 fifo
->head
= fifo
->tail
= NULL
;
353 /* Free ospf packet fifo. */
354 void ospf6_fifo_free(struct ospf6_fifo
*fifo
)
356 ospf6_fifo_flush(fifo
);
358 XFREE(MTYPE_OSPF6_FIFO
, fifo
);
361 static void ospf6_packet_add(struct ospf6_interface
*oi
,
362 struct ospf6_packet
*op
)
364 /* Add packet to end of queue. */
365 ospf6_fifo_push(oi
->obuf
, op
);
367 /* Debug of packet fifo*/
368 /* ospf_fifo_debug (oi->obuf); */
371 static void ospf6_packet_add_top(struct ospf6_interface
*oi
,
372 struct ospf6_packet
*op
)
374 /* Add packet to head of queue. */
375 ospf6_fifo_push_head(oi
->obuf
, op
);
377 /* Debug of packet fifo*/
378 /* ospf_fifo_debug (oi->obuf); */
381 static void ospf6_packet_delete(struct ospf6_interface
*oi
)
383 struct ospf6_packet
*op
;
385 op
= ospf6_fifo_pop(oi
->obuf
);
388 ospf6_packet_free(op
);
392 static void ospf6_hello_recv(struct in6_addr
*src
, struct in6_addr
*dst
,
393 struct ospf6_interface
*oi
,
394 struct ospf6_header
*oh
)
396 struct ospf6_hello
*hello
;
397 struct ospf6_neighbor
*on
;
400 int neighborchange
= 0;
401 int neighbor_ifindex_change
= 0;
404 struct timeval timestamp
;
406 monotime(×tamp
);
407 hello
= (struct ospf6_hello
*)((caddr_t
)oh
408 + sizeof(struct ospf6_header
));
410 /* HelloInterval check */
411 if (ntohs(hello
->hello_interval
) != oi
->hello_interval
) {
413 "VRF %s: I/F %s HelloInterval mismatch: (my %d, rcvd %d)",
414 oi
->interface
->vrf
->name
, oi
->interface
->name
,
415 oi
->hello_interval
, ntohs(hello
->hello_interval
));
419 /* RouterDeadInterval check */
420 if (ntohs(hello
->dead_interval
) != oi
->dead_interval
) {
422 "VRF %s: I/F %s DeadInterval mismatch: (my %d, rcvd %d)",
423 oi
->interface
->vrf
->name
, oi
->interface
->name
,
424 oi
->dead_interval
, ntohs(hello
->dead_interval
));
429 if (OSPF6_OPT_ISSET(hello
->options
, OSPF6_OPT_E
)
430 != OSPF6_OPT_ISSET(oi
->area
->options
, OSPF6_OPT_E
)) {
431 zlog_warn("VRF %s: IF %s E-bit mismatch",
432 oi
->interface
->vrf
->name
, oi
->interface
->name
);
437 if (OSPF6_OPT_ISSET(hello
->options
, OSPF6_OPT_N
)
438 != OSPF6_OPT_ISSET(oi
->area
->options
, OSPF6_OPT_N
)) {
439 zlog_warn("VRF %s: IF %s N-bit mismatch",
440 oi
->interface
->vrf
->name
, oi
->interface
->name
);
444 if (((OSPF6_OPT_ISSET_EXT(hello
->options
, OSPF6_OPT_AT
) ==
446 (oi
->at_data
.flags
== 0)) ||
447 ((OSPF6_OPT_ISSET_EXT(hello
->options
, OSPF6_OPT_AT
) !=
449 (oi
->at_data
.flags
!= 0))) {
450 if (IS_OSPF6_DEBUG_AUTH_RX
)
452 "VRF %s: IF %s AT-bit mismatch in hello packet",
453 oi
->interface
->vrf
->name
, oi
->interface
->name
);
454 oi
->at_data
.rx_drop
++;
458 /* Find neighbor, create if not exist */
459 on
= ospf6_neighbor_lookup(oh
->router_id
, oi
);
461 on
= ospf6_neighbor_create(oh
->router_id
, oi
);
462 on
->prev_drouter
= on
->drouter
= hello
->drouter
;
463 on
->prev_bdrouter
= on
->bdrouter
= hello
->bdrouter
;
464 on
->priority
= hello
->priority
;
467 /* check latency against hello period */
469 latency
= monotime_since(&on
->last_hello
, NULL
)
470 - ((int64_t)oi
->hello_interval
* 1000000);
471 /* log if latency exceeds the hello period */
472 if (latency
> ((int64_t)oi
->hello_interval
* 1000000))
473 zlog_warn("%s RX %pI4 high latency %" PRId64
"us.", __func__
,
474 &on
->router_id
, latency
);
475 on
->last_hello
= timestamp
;
478 /* Always override neighbor's source address */
479 memcpy(&on
->linklocal_addr
, src
, sizeof(struct in6_addr
));
481 /* Neighbor ifindex check */
482 if (on
->ifindex
!= (ifindex_t
)ntohl(hello
->interface_id
)) {
483 on
->ifindex
= ntohl(hello
->interface_id
);
484 neighbor_ifindex_change
++;
488 for (p
= (char *)((caddr_t
)hello
+ sizeof(struct ospf6_hello
));
489 p
+ sizeof(uint32_t) <= OSPF6_MESSAGE_END(oh
);
490 p
+= sizeof(uint32_t)) {
491 uint32_t *router_id
= (uint32_t *)p
;
493 if (*router_id
== oi
->area
->ospf6
->router_id
)
497 assert(p
== OSPF6_MESSAGE_END(oh
));
499 /* RouterPriority check */
500 if (on
->priority
!= hello
->priority
) {
501 on
->priority
= hello
->priority
;
506 if (on
->drouter
!= hello
->drouter
) {
507 on
->prev_drouter
= on
->drouter
;
508 on
->drouter
= hello
->drouter
;
509 if (on
->prev_drouter
== on
->router_id
510 || on
->drouter
== on
->router_id
)
515 if (on
->bdrouter
!= hello
->bdrouter
) {
516 on
->prev_bdrouter
= on
->bdrouter
;
517 on
->bdrouter
= hello
->bdrouter
;
518 if (on
->prev_bdrouter
== on
->router_id
519 || on
->bdrouter
== on
->router_id
)
523 /* BackupSeen check */
524 if (oi
->state
== OSPF6_INTERFACE_WAITING
) {
525 if (hello
->bdrouter
== on
->router_id
)
527 else if (hello
->drouter
== on
->router_id
528 && hello
->bdrouter
== htonl(0))
534 /* Execute neighbor events */
535 thread_execute(master
, hello_received
, on
, 0);
537 thread_execute(master
, twoway_received
, on
, 0);
539 if (OSPF6_GR_IS_ACTIVE_HELPER(on
)) {
540 if (IS_DEBUG_OSPF6_GR
)
542 "%s, Received oneway hello from RESTARTER so ignore here.",
543 __PRETTY_FUNCTION__
);
545 /* If the router is DR_OTHER, RESTARTER will not wait
546 * until it receives the hello from it if it receives
548 * So, helper might receives ONE_WAY hello from
549 * RESTARTER. So not allowing to change the state if it
550 * receives one_way hellow when it acts as HELPER for
551 * that specific neighbor.
553 thread_execute(master
, oneway_received
, on
, 0);
557 if (OSPF6_GR_IS_ACTIVE_HELPER(on
)) {
558 /* As per the GR Conformance Test Case 7.2. Section 3
559 * "Also, if X was the Designated Router on network segment S
560 * when the helping relationship began, Y maintains X as the
561 * Designated Router until the helping relationship is
563 * When it is a helper for this neighbor, It should not trigger
564 * the ISM Events. Also Intentionally not setting the priority
565 * and other fields so that when the neighbor exits the Grace
566 * period, it can handle if there is any change before GR and
569 if (IS_DEBUG_OSPF6_GR
)
571 "%s, Neighbor is under GR Restart, hence ignoring the ISM Events",
572 __PRETTY_FUNCTION__
);
578 * RFC 3623 - Section 2:
579 * "If the restarting router determines that it was the Designated
580 * Router on a given segment prior to the restart, it elects
581 * itself as the Designated Router again. The restarting router
582 * knows that it was the Designated Router if, while the
583 * associated interface is in Waiting state, a Hello packet is
584 * received from a neighbor listing the router as the Designated
587 if (oi
->area
->ospf6
->gr_info
.restart_in_progress
588 && oi
->state
== OSPF6_INTERFACE_WAITING
589 && hello
->drouter
== oi
->area
->ospf6
->router_id
)
590 oi
->drouter
= hello
->drouter
;
592 /* Schedule interface events */
594 thread_add_event(master
, backup_seen
, oi
, 0, NULL
);
596 thread_add_event(master
, neighbor_change
, oi
, 0, NULL
);
598 if (neighbor_ifindex_change
&& on
->state
== OSPF6_NEIGHBOR_FULL
)
599 OSPF6_ROUTER_LSA_SCHEDULE(oi
->area
);
602 static void ospf6_dbdesc_recv_master(struct ospf6_header
*oh
,
603 struct ospf6_neighbor
*on
)
605 struct ospf6_dbdesc
*dbdesc
;
608 dbdesc
= (struct ospf6_dbdesc
*)((caddr_t
)oh
609 + sizeof(struct ospf6_header
));
611 if (on
->state
< OSPF6_NEIGHBOR_INIT
) {
612 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV_HDR
))
613 zlog_debug("Neighbor state less than Init, ignore");
618 case OSPF6_NEIGHBOR_TWOWAY
:
619 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV_HDR
))
620 zlog_debug("Neighbor state is 2-Way, ignore");
623 case OSPF6_NEIGHBOR_INIT
:
624 thread_execute(master
, twoway_received
, on
, 0);
625 if (on
->state
!= OSPF6_NEIGHBOR_EXSTART
) {
626 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV_HDR
))
628 "Neighbor state is not ExStart, ignore");
631 /* else fall through to ExStart */
633 case OSPF6_NEIGHBOR_EXSTART
:
634 /* if neighbor obeys us as our slave, schedule negotiation_done
635 and process LSA Headers. Otherwise, ignore this message */
636 if (!CHECK_FLAG(dbdesc
->bits
, OSPF6_DBDESC_MSBIT
)
637 && !CHECK_FLAG(dbdesc
->bits
, OSPF6_DBDESC_IBIT
)
638 && ntohl(dbdesc
->seqnum
) == on
->dbdesc_seqnum
) {
639 /* execute NegotiationDone */
640 thread_execute(master
, negotiation_done
, on
, 0);
642 /* Record neighbor options */
643 memcpy(on
->options
, dbdesc
->options
,
644 sizeof(on
->options
));
646 zlog_warn("VRF %s: Nbr %s: Negotiation failed",
647 on
->ospf6_if
->interface
->vrf
->name
, on
->name
);
650 /* fall through to exchange */
652 case OSPF6_NEIGHBOR_EXCHANGE
:
653 if (!memcmp(dbdesc
, &on
->dbdesc_last
,
654 sizeof(struct ospf6_dbdesc
))) {
655 /* Duplicated DatabaseDescription is dropped by master
657 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV_HDR
))
659 "Duplicated dbdesc discarded by Master, ignore");
663 if (CHECK_FLAG(dbdesc
->bits
, OSPF6_DBDESC_MSBIT
)) {
665 "DbDesc recv: Master/Slave bit mismatch Nbr %s",
667 thread_add_event(master
, seqnumber_mismatch
, on
, 0,
672 if (CHECK_FLAG(dbdesc
->bits
, OSPF6_DBDESC_IBIT
)) {
673 zlog_warn("DbDesc recv: Initialize bit mismatch Nbr %s",
675 thread_add_event(master
, seqnumber_mismatch
, on
, 0,
680 if (memcmp(on
->options
, dbdesc
->options
, sizeof(on
->options
))) {
681 zlog_warn("DbDesc recv: Option field mismatch Nbr %s",
683 thread_add_event(master
, seqnumber_mismatch
, on
, 0,
688 if (ntohl(dbdesc
->seqnum
) != on
->dbdesc_seqnum
) {
690 "DbDesc recv: Sequence number mismatch Nbr %s (%#lx expected)",
691 on
->name
, (unsigned long)on
->dbdesc_seqnum
);
692 thread_add_event(master
, seqnumber_mismatch
, on
, 0,
698 case OSPF6_NEIGHBOR_LOADING
:
699 case OSPF6_NEIGHBOR_FULL
:
700 if (!memcmp(dbdesc
, &on
->dbdesc_last
,
701 sizeof(struct ospf6_dbdesc
))) {
702 /* Duplicated DatabaseDescription is dropped by master
704 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV_HDR
))
706 "Duplicated dbdesc discarded by Master, ignore");
711 "DbDesc recv: Not duplicate dbdesc in state %s Nbr %s",
712 ospf6_neighbor_state_str
[on
->state
], on
->name
);
713 thread_add_event(master
, seqnumber_mismatch
, on
, 0, NULL
);
721 /* Process LSA headers */
722 for (p
= (char *)((caddr_t
)dbdesc
+ sizeof(struct ospf6_dbdesc
));
723 p
+ sizeof(struct ospf6_lsa_header
) <= OSPF6_MESSAGE_END(oh
);
724 p
+= sizeof(struct ospf6_lsa_header
)) {
725 struct ospf6_lsa
*his
, *mine
;
726 struct ospf6_lsdb
*lsdb
= NULL
;
728 his
= ospf6_lsa_create_headeronly((struct ospf6_lsa_header
*)p
);
730 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
731 zlog_debug("%s", his
->name
);
733 switch (OSPF6_LSA_SCOPE(his
->header
->type
)) {
734 case OSPF6_SCOPE_LINKLOCAL
:
735 lsdb
= on
->ospf6_if
->lsdb
;
737 case OSPF6_SCOPE_AREA
:
738 lsdb
= on
->ospf6_if
->area
->lsdb
;
741 lsdb
= on
->ospf6_if
->area
->ospf6
->lsdb
;
743 case OSPF6_SCOPE_RESERVED
:
744 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
745 zlog_debug("Ignoring LSA of reserved scope");
746 ospf6_lsa_delete(his
);
750 if (ntohs(his
->header
->type
) == OSPF6_LSTYPE_AS_EXTERNAL
751 && (IS_AREA_STUB(on
->ospf6_if
->area
)
752 || IS_AREA_NSSA(on
->ospf6_if
->area
))) {
753 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
755 "SeqNumMismatch (E-bit mismatch), discard");
756 ospf6_lsa_delete(his
);
757 thread_add_event(master
, seqnumber_mismatch
, on
, 0,
762 mine
= ospf6_lsdb_lookup(his
->header
->type
, his
->header
->id
,
763 his
->header
->adv_router
, lsdb
);
765 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
766 zlog_debug("Add request (No database copy)");
767 ospf6_lsdb_add(ospf6_lsa_copy(his
), on
->request_list
);
768 } else if (ospf6_lsa_compare(his
, mine
) < 0) {
769 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
770 zlog_debug("Add request (Received MoreRecent)");
771 ospf6_lsdb_add(ospf6_lsa_copy(his
), on
->request_list
);
773 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
774 zlog_debug("Discard (Existing MoreRecent)");
776 ospf6_lsa_delete(his
);
779 assert(p
== OSPF6_MESSAGE_END(oh
));
781 /* Increment sequence number */
784 /* schedule send lsreq */
785 if (on
->request_list
->count
)
786 thread_add_event(master
, ospf6_lsreq_send
, on
, 0,
787 &on
->thread_send_lsreq
);
789 THREAD_OFF(on
->thread_send_dbdesc
);
792 if (!CHECK_FLAG(dbdesc
->bits
, OSPF6_DBDESC_MBIT
)
793 && !CHECK_FLAG(on
->dbdesc_bits
, OSPF6_DBDESC_MBIT
))
794 thread_add_event(master
, exchange_done
, on
, 0,
795 &on
->thread_exchange_done
);
797 thread_add_event(master
, ospf6_dbdesc_send_newone
, on
, 0,
798 &on
->thread_send_dbdesc
);
801 /* save last received dbdesc */
802 memcpy(&on
->dbdesc_last
, dbdesc
, sizeof(struct ospf6_dbdesc
));
805 static void ospf6_dbdesc_recv_slave(struct ospf6_header
*oh
,
806 struct ospf6_neighbor
*on
)
808 struct ospf6_dbdesc
*dbdesc
;
811 dbdesc
= (struct ospf6_dbdesc
*)((caddr_t
)oh
812 + sizeof(struct ospf6_header
));
814 if (on
->state
< OSPF6_NEIGHBOR_INIT
) {
815 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV_HDR
))
816 zlog_debug("Neighbor state less than Init, ignore");
821 case OSPF6_NEIGHBOR_TWOWAY
:
822 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV_HDR
))
823 zlog_debug("Neighbor state is 2-Way, ignore");
826 case OSPF6_NEIGHBOR_INIT
:
827 thread_execute(master
, twoway_received
, on
, 0);
828 if (on
->state
!= OSPF6_NEIGHBOR_EXSTART
) {
829 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV_HDR
))
831 "Neighbor state is not ExStart, ignore");
834 /* else fall through to ExStart */
836 case OSPF6_NEIGHBOR_EXSTART
:
837 /* If the neighbor is Master, act as Slave. Schedule
839 and process LSA Headers. Otherwise, ignore this message */
840 if (CHECK_FLAG(dbdesc
->bits
, OSPF6_DBDESC_IBIT
)
841 && CHECK_FLAG(dbdesc
->bits
, OSPF6_DBDESC_MBIT
)
842 && CHECK_FLAG(dbdesc
->bits
, OSPF6_DBDESC_MSBIT
)
844 == sizeof(struct ospf6_header
)
845 + sizeof(struct ospf6_dbdesc
)) {
846 /* set the master/slave bit to slave */
847 UNSET_FLAG(on
->dbdesc_bits
, OSPF6_DBDESC_MSBIT
);
849 /* set the DD sequence number to one specified by master
851 on
->dbdesc_seqnum
= ntohl(dbdesc
->seqnum
);
853 /* schedule NegotiationDone */
854 thread_execute(master
, negotiation_done
, on
, 0);
856 /* Record neighbor options */
857 memcpy(on
->options
, dbdesc
->options
,
858 sizeof(on
->options
));
860 zlog_warn("VRF %s: Nbr %s Negotiation failed",
861 on
->ospf6_if
->interface
->vrf
->name
, on
->name
);
866 case OSPF6_NEIGHBOR_EXCHANGE
:
867 if (!memcmp(dbdesc
, &on
->dbdesc_last
,
868 sizeof(struct ospf6_dbdesc
))) {
869 /* Duplicated DatabaseDescription causes slave to
871 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV_HDR
))
873 "Duplicated dbdesc causes retransmit");
874 THREAD_OFF(on
->thread_send_dbdesc
);
875 thread_add_event(master
, ospf6_dbdesc_send
, on
, 0,
876 &on
->thread_send_dbdesc
);
880 if (!CHECK_FLAG(dbdesc
->bits
, OSPF6_DBDESC_MSBIT
)) {
882 "DbDesc slave recv: Master/Slave bit mismatch Nbr %s",
884 thread_add_event(master
, seqnumber_mismatch
, on
, 0,
889 if (CHECK_FLAG(dbdesc
->bits
, OSPF6_DBDESC_IBIT
)) {
891 "DbDesc slave recv: Initialize bit mismatch Nbr %s",
893 thread_add_event(master
, seqnumber_mismatch
, on
, 0,
898 if (memcmp(on
->options
, dbdesc
->options
, sizeof(on
->options
))) {
900 "DbDesc slave recv: Option field mismatch Nbr %s",
902 thread_add_event(master
, seqnumber_mismatch
, on
, 0,
907 if (ntohl(dbdesc
->seqnum
) != on
->dbdesc_seqnum
+ 1) {
909 "DbDesc slave recv: Sequence number mismatch Nbr %s (%#lx expected)",
910 on
->name
, (unsigned long)on
->dbdesc_seqnum
+ 1);
911 thread_add_event(master
, seqnumber_mismatch
, on
, 0,
917 case OSPF6_NEIGHBOR_LOADING
:
918 case OSPF6_NEIGHBOR_FULL
:
919 if (!memcmp(dbdesc
, &on
->dbdesc_last
,
920 sizeof(struct ospf6_dbdesc
))) {
921 /* Duplicated DatabaseDescription causes slave to
923 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV_HDR
))
925 "Duplicated dbdesc causes retransmit");
926 THREAD_OFF(on
->thread_send_dbdesc
);
927 thread_add_event(master
, ospf6_dbdesc_send
, on
, 0,
928 &on
->thread_send_dbdesc
);
933 "DbDesc slave recv: Not duplicate dbdesc in state %s Nbr %s",
934 ospf6_neighbor_state_str
[on
->state
], on
->name
);
935 thread_add_event(master
, seqnumber_mismatch
, on
, 0, NULL
);
943 /* Process LSA headers */
944 for (p
= (char *)((caddr_t
)dbdesc
+ sizeof(struct ospf6_dbdesc
));
945 p
+ sizeof(struct ospf6_lsa_header
) <= OSPF6_MESSAGE_END(oh
);
946 p
+= sizeof(struct ospf6_lsa_header
)) {
947 struct ospf6_lsa
*his
, *mine
;
948 struct ospf6_lsdb
*lsdb
= NULL
;
950 his
= ospf6_lsa_create_headeronly((struct ospf6_lsa_header
*)p
);
952 switch (OSPF6_LSA_SCOPE(his
->header
->type
)) {
953 case OSPF6_SCOPE_LINKLOCAL
:
954 lsdb
= on
->ospf6_if
->lsdb
;
956 case OSPF6_SCOPE_AREA
:
957 lsdb
= on
->ospf6_if
->area
->lsdb
;
960 lsdb
= on
->ospf6_if
->area
->ospf6
->lsdb
;
962 case OSPF6_SCOPE_RESERVED
:
963 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
964 zlog_debug("Ignoring LSA of reserved scope");
965 ospf6_lsa_delete(his
);
969 if (OSPF6_LSA_SCOPE(his
->header
->type
) == OSPF6_SCOPE_AS
970 && (IS_AREA_STUB(on
->ospf6_if
->area
)
971 || IS_AREA_NSSA(on
->ospf6_if
->area
))) {
972 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
973 zlog_debug("E-bit mismatch with LSA Headers");
974 ospf6_lsa_delete(his
);
975 thread_add_event(master
, seqnumber_mismatch
, on
, 0,
980 mine
= ospf6_lsdb_lookup(his
->header
->type
, his
->header
->id
,
981 his
->header
->adv_router
, lsdb
);
982 if (mine
== NULL
|| ospf6_lsa_compare(his
, mine
) < 0) {
983 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
984 zlog_debug("Add request-list: %s", his
->name
);
985 ospf6_lsdb_add(ospf6_lsa_copy(his
), on
->request_list
);
987 ospf6_lsa_delete(his
);
990 assert(p
== OSPF6_MESSAGE_END(oh
));
992 /* Set sequence number to Master's */
993 on
->dbdesc_seqnum
= ntohl(dbdesc
->seqnum
);
995 /* schedule send lsreq */
996 if (on
->request_list
->count
)
997 thread_add_event(master
, ospf6_lsreq_send
, on
, 0,
998 &on
->thread_send_lsreq
);
1000 THREAD_OFF(on
->thread_send_dbdesc
);
1001 thread_add_event(master
, ospf6_dbdesc_send_newone
, on
, 0,
1002 &on
->thread_send_dbdesc
);
1004 /* save last received dbdesc */
1005 memcpy(&on
->dbdesc_last
, dbdesc
, sizeof(struct ospf6_dbdesc
));
1008 static void ospf6_dbdesc_recv(struct in6_addr
*src
, struct in6_addr
*dst
,
1009 struct ospf6_interface
*oi
,
1010 struct ospf6_header
*oh
)
1012 struct ospf6_neighbor
*on
;
1013 struct ospf6_dbdesc
*dbdesc
;
1015 on
= ospf6_neighbor_lookup(oh
->router_id
, oi
);
1017 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV_HDR
))
1018 zlog_debug("Neighbor not found, ignore");
1022 dbdesc
= (struct ospf6_dbdesc
*)((caddr_t
)oh
1023 + sizeof(struct ospf6_header
));
1025 if (((OSPF6_OPT_ISSET_EXT(dbdesc
->options
, OSPF6_OPT_AT
) ==
1027 (oi
->at_data
.flags
== 0)) ||
1028 ((OSPF6_OPT_ISSET_EXT(dbdesc
->options
, OSPF6_OPT_AT
) !=
1030 (oi
->at_data
.flags
!= 0))) {
1031 if (IS_OSPF6_DEBUG_AUTH_RX
)
1033 "VRF %s: IF %s AT-bit mismatch in dbdesc packet",
1034 oi
->interface
->vrf
->name
, oi
->interface
->name
);
1035 oi
->at_data
.rx_drop
++;
1039 /* Interface MTU check */
1040 if (!oi
->mtu_ignore
&& ntohs(dbdesc
->ifmtu
) != oi
->ifmtu
) {
1041 zlog_warn("VRF %s: I/F %s MTU mismatch (my %d rcvd %d)",
1042 oi
->interface
->vrf
->name
, oi
->interface
->name
,
1043 oi
->ifmtu
, ntohs(dbdesc
->ifmtu
));
1047 if (dbdesc
->reserved1
|| dbdesc
->reserved2
) {
1048 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV_HDR
))
1050 "Non-0 reserved field in %s's DbDesc, correct",
1052 dbdesc
->reserved1
= 0;
1053 dbdesc
->reserved2
= 0;
1058 if (ntohl(oh
->router_id
) < ntohl(oi
->area
->ospf6
->router_id
))
1059 ospf6_dbdesc_recv_master(oh
, on
);
1060 else if (ntohl(oi
->area
->ospf6
->router_id
) < ntohl(oh
->router_id
))
1061 ospf6_dbdesc_recv_slave(oh
, on
);
1063 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV_HDR
))
1064 zlog_debug("Can't decide which is master, ignore");
1068 static void ospf6_lsreq_recv(struct in6_addr
*src
, struct in6_addr
*dst
,
1069 struct ospf6_interface
*oi
,
1070 struct ospf6_header
*oh
)
1072 struct ospf6_neighbor
*on
;
1074 struct ospf6_lsreq_entry
*e
;
1075 struct ospf6_lsdb
*lsdb
= NULL
;
1076 struct ospf6_lsa
*lsa
;
1078 on
= ospf6_neighbor_lookup(oh
->router_id
, oi
);
1080 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV_HDR
))
1081 zlog_debug("Neighbor not found, ignore");
1085 if (on
->state
!= OSPF6_NEIGHBOR_EXCHANGE
1086 && on
->state
!= OSPF6_NEIGHBOR_LOADING
1087 && on
->state
!= OSPF6_NEIGHBOR_FULL
) {
1088 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV_HDR
))
1089 zlog_debug("Neighbor state less than Exchange, ignore");
1095 /* Process each request */
1096 for (p
= (char *)((caddr_t
)oh
+ sizeof(struct ospf6_header
));
1097 p
+ sizeof(struct ospf6_lsreq_entry
) <= OSPF6_MESSAGE_END(oh
);
1098 p
+= sizeof(struct ospf6_lsreq_entry
)) {
1099 e
= (struct ospf6_lsreq_entry
*)p
;
1101 switch (OSPF6_LSA_SCOPE(e
->type
)) {
1102 case OSPF6_SCOPE_LINKLOCAL
:
1103 lsdb
= on
->ospf6_if
->lsdb
;
1105 case OSPF6_SCOPE_AREA
:
1106 lsdb
= on
->ospf6_if
->area
->lsdb
;
1108 case OSPF6_SCOPE_AS
:
1109 lsdb
= on
->ospf6_if
->area
->ospf6
->lsdb
;
1112 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
1113 zlog_debug("Ignoring LSA of reserved scope");
1117 /* Find database copy */
1118 lsa
= ospf6_lsdb_lookup(e
->type
, e
->id
, e
->adv_router
, lsdb
);
1121 "Can't find requested lsa [%s Id:%pI4 Adv:%pI4] send badLSReq",
1122 ospf6_lstype_name(e
->type
), &e
->id
,
1124 thread_add_event(master
, bad_lsreq
, on
, 0, NULL
);
1128 ospf6_lsdb_add(ospf6_lsa_copy(lsa
), on
->lsupdate_list
);
1131 assert(p
== OSPF6_MESSAGE_END(oh
));
1133 /* schedule send lsupdate */
1134 THREAD_OFF(on
->thread_send_lsupdate
);
1135 thread_add_event(master
, ospf6_lsupdate_send_neighbor
, on
, 0,
1136 &on
->thread_send_lsupdate
);
1139 /* Verify, that the specified memory area contains exactly N valid IPv6
1140 prefixes as specified by RFC5340, A.4.1. */
1141 static unsigned ospf6_prefixes_examin(
1142 struct ospf6_prefix
*current
, /* start of buffer */
1144 const uint32_t req_num_pfxs
/* always compared with the actual number
1148 uint8_t requested_pfx_bytes
;
1149 uint32_t real_num_pfxs
= 0;
1152 if (length
< OSPF6_PREFIX_MIN_SIZE
) {
1153 zlog_warn("%s: undersized IPv6 prefix header",
1157 /* safe to look deeper */
1158 if (current
->prefix_length
> IPV6_MAX_BITLEN
) {
1159 zlog_warn("%s: invalid PrefixLength (%u bits)",
1160 __func__
, current
->prefix_length
);
1163 /* covers both fixed- and variable-sized fields */
1164 requested_pfx_bytes
=
1165 OSPF6_PREFIX_MIN_SIZE
1166 + OSPF6_PREFIX_SPACE(current
->prefix_length
);
1167 if (requested_pfx_bytes
> length
) {
1168 zlog_warn("%s: undersized IPv6 prefix", __func__
);
1172 length
-= requested_pfx_bytes
;
1173 current
= (struct ospf6_prefix
*)((caddr_t
)current
1174 + requested_pfx_bytes
);
1177 if (real_num_pfxs
!= req_num_pfxs
) {
1179 "%s: IPv6 prefix number mismatch (%u required, %u real)",
1180 __func__
, req_num_pfxs
, real_num_pfxs
);
1186 /* Verify an LSA to have a valid length and dispatch further (where
1187 appropriate) to check if the contents, including nested IPv6 prefixes,
1188 is properly sized/aligned within the LSA. Note that this function gets
1189 LSA type in network byte order, uses in host byte order and passes to
1190 ospf6_lstype_name() in network byte order again. */
1191 static unsigned ospf6_lsa_examin(struct ospf6_lsa_header
*lsah
,
1192 const uint16_t lsalen
,
1193 const uint8_t headeronly
)
1195 struct ospf6_intra_prefix_lsa
*intra_prefix_lsa
;
1196 struct ospf6_as_external_lsa
*as_external_lsa
;
1197 struct ospf6_link_lsa
*link_lsa
;
1198 unsigned exp_length
;
1202 /* In case an additional minimum length constraint is defined for
1204 LSA type, make sure that this constraint is met. */
1205 lsatype
= ntohs(lsah
->type
);
1206 ltindex
= lsatype
& OSPF6_LSTYPE_FCODE_MASK
;
1207 if (ltindex
< OSPF6_LSTYPE_SIZE
&& ospf6_lsa_minlen
[ltindex
]
1208 && lsalen
< ospf6_lsa_minlen
[ltindex
] + OSPF6_LSA_HEADER_SIZE
) {
1209 zlog_warn("%s: undersized (%u B) LSA", __func__
, lsalen
);
1213 case OSPF6_LSTYPE_ROUTER
:
1214 /* RFC5340 A.4.3, LSA header + OSPF6_ROUTER_LSA_MIN_SIZE bytes
1216 by N>=0 interface descriptions. */
1217 if ((lsalen
- OSPF6_LSA_HEADER_SIZE
- OSPF6_ROUTER_LSA_MIN_SIZE
)
1218 % OSPF6_ROUTER_LSDESC_FIX_SIZE
) {
1220 "%s: Router LSA interface description alignment error",
1225 case OSPF6_LSTYPE_NETWORK
:
1226 /* RFC5340 A.4.4, LSA header + OSPF6_NETWORK_LSA_MIN_SIZE bytes
1227 followed by N>=0 attached router descriptions. */
1228 if ((lsalen
- OSPF6_LSA_HEADER_SIZE
1229 - OSPF6_NETWORK_LSA_MIN_SIZE
)
1230 % OSPF6_NETWORK_LSDESC_FIX_SIZE
) {
1232 "%s: Network LSA router description alignment error",
1237 case OSPF6_LSTYPE_INTER_PREFIX
:
1238 /* RFC5340 A.4.5, LSA header + OSPF6_INTER_PREFIX_LSA_MIN_SIZE
1240 followed by 3-4 fields of a single IPv6 prefix. */
1243 return ospf6_prefixes_examin(
1244 (struct ospf6_prefix
1245 *)((caddr_t
)lsah
+ OSPF6_LSA_HEADER_SIZE
1246 + OSPF6_INTER_PREFIX_LSA_MIN_SIZE
),
1247 lsalen
- OSPF6_LSA_HEADER_SIZE
1248 - OSPF6_INTER_PREFIX_LSA_MIN_SIZE
,
1250 case OSPF6_LSTYPE_INTER_ROUTER
:
1251 /* RFC5340 A.4.6, fixed-size LSA. */
1253 > OSPF6_LSA_HEADER_SIZE
+ OSPF6_INTER_ROUTER_LSA_FIX_SIZE
) {
1254 zlog_warn("%s: Inter Router LSA oversized (%u B) LSA",
1259 case OSPF6_LSTYPE_AS_EXTERNAL
: /* RFC5340 A.4.7, same as A.4.8. */
1260 case OSPF6_LSTYPE_TYPE_7
:
1261 /* RFC5340 A.4.8, LSA header + OSPF6_AS_EXTERNAL_LSA_MIN_SIZE
1263 followed by 3-4 fields of IPv6 prefix and 3 conditional LSA
1265 16 bytes of forwarding address, 4 bytes of external route
1267 4 bytes of referenced link state ID. */
1271 (struct ospf6_as_external_lsa
1272 *)((caddr_t
)lsah
+ OSPF6_LSA_HEADER_SIZE
);
1274 OSPF6_LSA_HEADER_SIZE
+ OSPF6_AS_EXTERNAL_LSA_MIN_SIZE
;
1275 /* To find out if the last optional field (Referenced Link State
1277 assumed in this LSA, we need to access fixed fields of the
1279 prefix before ospf6_prefix_examin() confirms its sizing. */
1280 if (exp_length
+ OSPF6_PREFIX_MIN_SIZE
> lsalen
) {
1282 "%s: AS External undersized (%u B) LSA header",
1286 /* forwarding address */
1287 if (CHECK_FLAG(as_external_lsa
->bits_metric
, OSPF6_ASBR_BIT_F
))
1289 /* external route tag */
1290 if (CHECK_FLAG(as_external_lsa
->bits_metric
, OSPF6_ASBR_BIT_T
))
1292 /* referenced link state ID */
1293 if (as_external_lsa
->prefix
.u
._prefix_referenced_lstype
)
1295 /* All the fixed-size fields (mandatory and optional) must fit.
1297 this check does not include any IPv6 prefix fields. */
1298 if (exp_length
> lsalen
) {
1300 "%s: AS External undersized (%u B) LSA header",
1304 /* The last call completely covers the remainder (IPv6 prefix).
1306 return ospf6_prefixes_examin(
1307 (struct ospf6_prefix
1308 *)((caddr_t
)as_external_lsa
1309 + OSPF6_AS_EXTERNAL_LSA_MIN_SIZE
),
1310 lsalen
- exp_length
, 1);
1311 case OSPF6_LSTYPE_LINK
:
1312 /* RFC5340 A.4.9, LSA header + OSPF6_LINK_LSA_MIN_SIZE bytes
1314 by N>=0 IPv6 prefix blocks (with N declared beforehand). */
1317 link_lsa
= (struct ospf6_link_lsa
*)((caddr_t
)lsah
1318 + OSPF6_LSA_HEADER_SIZE
);
1319 return ospf6_prefixes_examin(
1320 (struct ospf6_prefix
*)((caddr_t
)link_lsa
1321 + OSPF6_LINK_LSA_MIN_SIZE
),
1322 lsalen
- OSPF6_LSA_HEADER_SIZE
1323 - OSPF6_LINK_LSA_MIN_SIZE
,
1324 ntohl(link_lsa
->prefix_num
) /* 32 bits */
1326 case OSPF6_LSTYPE_INTRA_PREFIX
:
1327 /* RFC5340 A.4.10, LSA header + OSPF6_INTRA_PREFIX_LSA_MIN_SIZE
1329 followed by N>=0 IPv6 prefixes (with N declared beforehand).
1334 (struct ospf6_intra_prefix_lsa
1335 *)((caddr_t
)lsah
+ OSPF6_LSA_HEADER_SIZE
);
1336 return ospf6_prefixes_examin(
1337 (struct ospf6_prefix
1338 *)((caddr_t
)intra_prefix_lsa
1339 + OSPF6_INTRA_PREFIX_LSA_MIN_SIZE
),
1340 lsalen
- OSPF6_LSA_HEADER_SIZE
1341 - OSPF6_INTRA_PREFIX_LSA_MIN_SIZE
,
1342 ntohs(intra_prefix_lsa
->prefix_num
) /* 16 bits */
1344 case OSPF6_LSTYPE_GRACE_LSA
:
1345 if (lsalen
< OSPF6_LSA_HEADER_SIZE
+ GRACE_PERIOD_TLV_SIZE
1346 + GRACE_RESTART_REASON_TLV_SIZE
) {
1347 if (IS_DEBUG_OSPF6_GR
)
1348 zlog_debug("%s: Undersized GraceLSA.",
1353 /* No additional validation is possible for unknown LSA types, which are
1354 themselves valid in OPSFv3, hence the default decision is to accept.
1359 /* Verify if the provided input buffer is a valid sequence of LSAs. This
1360 includes verification of LSA blocks length/alignment and dispatching
1361 of deeper-level checks. */
1363 ospf6_lsaseq_examin(struct ospf6_lsa_header
*lsah
, /* start of buffered data */
1364 size_t length
, const uint8_t headeronly
,
1365 /* When declared_num_lsas is not 0, compare it to the real
1367 and treat the difference as an error. */
1368 const uint32_t declared_num_lsas
)
1370 uint32_t counted_lsas
= 0;
1374 if (length
< OSPF6_LSA_HEADER_SIZE
) {
1376 "%s: undersized (%zu B) trailing (#%u) LSA header",
1377 __func__
, length
, counted_lsas
);
1380 /* save on ntohs() calls here and in the LSA validator */
1381 lsalen
= OSPF6_LSA_SIZE(lsah
);
1382 if (lsalen
< OSPF6_LSA_HEADER_SIZE
) {
1384 "%s: malformed LSA header #%u, declared length is %u B",
1385 __func__
, counted_lsas
, lsalen
);
1389 /* less checks here and in ospf6_lsa_examin() */
1390 if (MSG_OK
!= ospf6_lsa_examin(lsah
, lsalen
, 1)) {
1392 "%s: anomaly in header-only %s LSA #%u",
1393 __func__
, ospf6_lstype_name(lsah
->type
),
1397 lsah
= (struct ospf6_lsa_header
1399 + OSPF6_LSA_HEADER_SIZE
);
1400 length
-= OSPF6_LSA_HEADER_SIZE
;
1402 /* make sure the input buffer is deep enough before
1404 if (lsalen
> length
) {
1406 "%s: anomaly in %s LSA #%u: declared length is %u B, buffered length is %zu B",
1407 __func__
, ospf6_lstype_name(lsah
->type
),
1408 counted_lsas
, lsalen
, length
);
1411 if (MSG_OK
!= ospf6_lsa_examin(lsah
, lsalen
, 0)) {
1412 zlog_warn("%s: anomaly in %s LSA #%u", __func__
,
1413 ospf6_lstype_name(lsah
->type
),
1417 lsah
= (struct ospf6_lsa_header
*)((caddr_t
)lsah
1424 if (declared_num_lsas
&& counted_lsas
!= declared_num_lsas
) {
1425 zlog_warn("%s: #LSAs declared (%u) does not match actual (%u)",
1426 __func__
, declared_num_lsas
, counted_lsas
);
1432 /* Verify a complete OSPF packet for proper sizing/alignment. */
1433 static unsigned ospf6_packet_examin(struct ospf6_header
*oh
,
1434 const unsigned bytesonwire
)
1436 struct ospf6_lsupdate
*lsupd
;
1439 /* length, 1st approximation */
1440 if (bytesonwire
< OSPF6_HEADER_SIZE
) {
1441 zlog_warn("%s: undersized (%u B) packet", __func__
,
1446 /* Now it is safe to access header fields. */
1447 if (bytesonwire
!= ntohs(oh
->length
)) {
1448 zlog_warn("%s: %s packet length error (%u real, %u declared)",
1449 __func__
, ospf6_message_type(oh
->type
), bytesonwire
,
1455 if (oh
->version
!= OSPFV3_VERSION
) {
1456 zlog_warn("%s: invalid (%u) protocol version", __func__
,
1460 /* length, 2nd approximation */
1461 if (oh
->type
< OSPF6_MESSAGE_TYPE_ALL
&& ospf6_packet_minlen
[oh
->type
]
1463 < OSPF6_HEADER_SIZE
+ ospf6_packet_minlen
[oh
->type
]) {
1464 zlog_warn("%s: undersized (%u B) %s packet", __func__
,
1465 bytesonwire
, ospf6_message_type(oh
->type
));
1468 /* type-specific deeper validation */
1470 case OSPF6_MESSAGE_TYPE_HELLO
:
1471 /* RFC5340 A.3.2, packet header + OSPF6_HELLO_MIN_SIZE bytes
1473 by N>=0 router-IDs. */
1475 == (bytesonwire
- OSPF6_HEADER_SIZE
- OSPF6_HELLO_MIN_SIZE
)
1478 zlog_warn("%s: alignment error in %s packet", __func__
,
1479 ospf6_message_type(oh
->type
));
1481 case OSPF6_MESSAGE_TYPE_DBDESC
:
1482 /* RFC5340 A.3.3, packet header + OSPF6_DB_DESC_MIN_SIZE bytes
1484 by N>=0 header-only LSAs. */
1485 test
= ospf6_lsaseq_examin(
1486 (struct ospf6_lsa_header
*)((caddr_t
)oh
1488 + OSPF6_DB_DESC_MIN_SIZE
),
1489 bytesonwire
- OSPF6_HEADER_SIZE
1490 - OSPF6_DB_DESC_MIN_SIZE
,
1493 case OSPF6_MESSAGE_TYPE_LSREQ
:
1494 /* RFC5340 A.3.4, packet header + N>=0 LS description blocks. */
1496 == (bytesonwire
- OSPF6_HEADER_SIZE
- OSPF6_LS_REQ_MIN_SIZE
)
1497 % OSPF6_LSREQ_LSDESC_FIX_SIZE
)
1499 zlog_warn("%s: alignment error in %s packet", __func__
,
1500 ospf6_message_type(oh
->type
));
1502 case OSPF6_MESSAGE_TYPE_LSUPDATE
:
1503 /* RFC5340 A.3.5, packet header + OSPF6_LS_UPD_MIN_SIZE bytes
1505 by N>=0 full LSAs (with N declared beforehand). */
1506 lsupd
= (struct ospf6_lsupdate
*)((caddr_t
)oh
1507 + OSPF6_HEADER_SIZE
);
1508 test
= ospf6_lsaseq_examin(
1509 (struct ospf6_lsa_header
*)((caddr_t
)lsupd
1510 + OSPF6_LS_UPD_MIN_SIZE
),
1511 bytesonwire
- OSPF6_HEADER_SIZE
- OSPF6_LS_UPD_MIN_SIZE
,
1512 0, ntohl(lsupd
->lsa_number
) /* 32 bits */
1515 case OSPF6_MESSAGE_TYPE_LSACK
:
1516 /* RFC5340 A.3.6, packet header + N>=0 header-only LSAs. */
1517 test
= ospf6_lsaseq_examin(
1518 (struct ospf6_lsa_header
*)((caddr_t
)oh
1520 + OSPF6_LS_ACK_MIN_SIZE
),
1521 bytesonwire
- OSPF6_HEADER_SIZE
- OSPF6_LS_ACK_MIN_SIZE
,
1525 zlog_warn("%s: invalid (%u) message type", __func__
, oh
->type
);
1529 zlog_warn("%s: anomaly in %s packet", __func__
,
1530 ospf6_message_type(oh
->type
));
1534 /* Verify particular fields of otherwise correct received OSPF packet to
1535 meet the requirements of RFC. */
1536 static int ospf6_rxpacket_examin(struct ospf6_interface
*oi
,
1537 struct ospf6_header
*oh
,
1538 const unsigned bytesonwire
)
1541 if (MSG_OK
!= ospf6_packet_examin(oh
, bytesonwire
))
1545 if (oh
->area_id
!= oi
->area
->area_id
) {
1546 if (oh
->area_id
== OSPF_AREA_BACKBONE
)
1548 "VRF %s: I/F %s Message may be via Virtual Link: not supported",
1549 oi
->interface
->vrf
->name
, oi
->interface
->name
);
1552 "VRF %s: I/F %s Area-ID mismatch (my %pI4, rcvd %pI4)",
1553 oi
->interface
->vrf
->name
, oi
->interface
->name
,
1554 &oi
->area
->area_id
, &oh
->area_id
);
1558 /* Instance-ID check */
1559 if (oh
->instance_id
!= oi
->instance_id
) {
1561 "VRF %s: I/F %s Instance-ID mismatch (my %u, rcvd %u)",
1562 oi
->interface
->vrf
->name
, oi
->interface
->name
,
1563 oi
->instance_id
, oh
->instance_id
);
1567 /* Router-ID check */
1568 if (oh
->router_id
== oi
->area
->ospf6
->router_id
) {
1569 zlog_warn("VRF %s: I/F %s Duplicate Router-ID (%pI4)",
1570 oi
->interface
->vrf
->name
, oi
->interface
->name
,
1577 static void ospf6_lsupdate_recv(struct in6_addr
*src
, struct in6_addr
*dst
,
1578 struct ospf6_interface
*oi
,
1579 struct ospf6_header
*oh
)
1581 struct ospf6_neighbor
*on
;
1582 struct ospf6_lsupdate
*lsupdate
;
1585 on
= ospf6_neighbor_lookup(oh
->router_id
, oi
);
1587 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV_HDR
))
1588 zlog_debug("Neighbor not found, ignore");
1592 if (on
->state
!= OSPF6_NEIGHBOR_EXCHANGE
1593 && on
->state
!= OSPF6_NEIGHBOR_LOADING
1594 && on
->state
!= OSPF6_NEIGHBOR_FULL
) {
1595 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV_HDR
))
1596 zlog_debug("Neighbor state less than Exchange, ignore");
1600 lsupdate
= (struct ospf6_lsupdate
*)((caddr_t
)oh
1601 + sizeof(struct ospf6_header
));
1606 for (p
= (char *)((caddr_t
)lsupdate
+ sizeof(struct ospf6_lsupdate
));
1607 p
< OSPF6_MESSAGE_END(oh
)
1608 && p
+ OSPF6_LSA_SIZE(p
) <= OSPF6_MESSAGE_END(oh
);
1609 p
+= OSPF6_LSA_SIZE(p
)) {
1610 ospf6_receive_lsa(on
, (struct ospf6_lsa_header
*)p
);
1613 assert(p
== OSPF6_MESSAGE_END(oh
));
1616 static void ospf6_lsack_recv(struct in6_addr
*src
, struct in6_addr
*dst
,
1617 struct ospf6_interface
*oi
,
1618 struct ospf6_header
*oh
)
1620 struct ospf6_neighbor
*on
;
1622 struct ospf6_lsa
*his
, *mine
;
1623 struct ospf6_lsdb
*lsdb
= NULL
;
1625 assert(oh
->type
== OSPF6_MESSAGE_TYPE_LSACK
);
1627 on
= ospf6_neighbor_lookup(oh
->router_id
, oi
);
1629 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV_HDR
))
1630 zlog_debug("Neighbor not found, ignore");
1634 if (on
->state
!= OSPF6_NEIGHBOR_EXCHANGE
1635 && on
->state
!= OSPF6_NEIGHBOR_LOADING
1636 && on
->state
!= OSPF6_NEIGHBOR_FULL
) {
1637 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV_HDR
))
1638 zlog_debug("Neighbor state less than Exchange, ignore");
1644 for (p
= (char *)((caddr_t
)oh
+ sizeof(struct ospf6_header
));
1645 p
+ sizeof(struct ospf6_lsa_header
) <= OSPF6_MESSAGE_END(oh
);
1646 p
+= sizeof(struct ospf6_lsa_header
)) {
1647 his
= ospf6_lsa_create_headeronly((struct ospf6_lsa_header
*)p
);
1649 switch (OSPF6_LSA_SCOPE(his
->header
->type
)) {
1650 case OSPF6_SCOPE_LINKLOCAL
:
1651 lsdb
= on
->ospf6_if
->lsdb
;
1653 case OSPF6_SCOPE_AREA
:
1654 lsdb
= on
->ospf6_if
->area
->lsdb
;
1656 case OSPF6_SCOPE_AS
:
1657 lsdb
= on
->ospf6_if
->area
->ospf6
->lsdb
;
1659 case OSPF6_SCOPE_RESERVED
:
1660 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
1661 zlog_debug("Ignoring LSA of reserved scope");
1662 ospf6_lsa_delete(his
);
1666 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
1667 zlog_debug("%s acknowledged by %s", his
->name
,
1670 /* Find database copy */
1671 mine
= ospf6_lsdb_lookup(his
->header
->type
, his
->header
->id
,
1672 his
->header
->adv_router
, lsdb
);
1674 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
1675 zlog_debug("No database copy");
1676 ospf6_lsa_delete(his
);
1680 /* Check if the LSA is on his retrans-list */
1681 mine
= ospf6_lsdb_lookup(his
->header
->type
, his
->header
->id
,
1682 his
->header
->adv_router
,
1685 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
1686 zlog_debug("Not on %s's retrans-list",
1688 ospf6_lsa_delete(his
);
1692 if (ospf6_lsa_compare(his
, mine
) != 0) {
1693 /* Log this questionable acknowledgement,
1694 and examine the next one. */
1695 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
1696 zlog_debug("Questionable acknowledgement");
1697 ospf6_lsa_delete(his
);
1701 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
1703 "Acknowledged, remove from %s's retrans-list",
1706 ospf6_decrement_retrans_count(mine
);
1707 if (OSPF6_LSA_IS_MAXAGE(mine
))
1708 ospf6_maxage_remove(on
->ospf6_if
->area
->ospf6
);
1709 ospf6_lsdb_remove(mine
, on
->retrans_list
);
1710 ospf6_lsa_delete(his
);
1713 assert(p
== OSPF6_MESSAGE_END(oh
));
1716 static uint8_t *recvbuf
= NULL
;
1717 static uint8_t *sendbuf
= NULL
;
1718 static unsigned int iobuflen
= 0;
1720 int ospf6_iobuf_size(unsigned int size
)
1722 /* NB: there was previously code here that tried to dynamically size
1723 * the buffer for whatever we see in MTU on interfaces. Which is
1724 * _unconditionally wrong_ - we can always receive fragmented IPv6
1725 * up to the regular 64k length limit. (No jumbograms, thankfully.)
1729 /* the + 128 is to have some runway at the end */
1730 size_t alloc_size
= 65536 + 128;
1732 assert(!recvbuf
&& !sendbuf
);
1734 recvbuf
= XMALLOC(MTYPE_OSPF6_MESSAGE
, alloc_size
);
1735 sendbuf
= XMALLOC(MTYPE_OSPF6_MESSAGE
, alloc_size
);
1736 iobuflen
= alloc_size
;
1742 void ospf6_message_terminate(void)
1744 XFREE(MTYPE_OSPF6_MESSAGE
, recvbuf
);
1745 XFREE(MTYPE_OSPF6_MESSAGE
, sendbuf
);
1750 enum ospf6_read_return_enum
{
1752 OSPF6_READ_CONTINUE
,
1755 static int ospf6_read_helper(int sockfd
, struct ospf6
*ospf6
)
1758 struct in6_addr src
, dst
;
1760 struct iovec iovector
[2];
1761 struct ospf6_interface
*oi
;
1762 struct ospf6_header
*oh
;
1763 enum ospf6_auth_err ret
= OSPF6_AUTH_PROCESS_NORMAL
;
1764 uint32_t at_len
= 0;
1765 uint32_t lls_len
= 0;
1768 memset(&src
, 0, sizeof(src
));
1769 memset(&dst
, 0, sizeof(dst
));
1771 iovector
[0].iov_base
= recvbuf
;
1772 iovector
[0].iov_len
= iobuflen
;
1773 iovector
[1].iov_base
= NULL
;
1774 iovector
[1].iov_len
= 0;
1776 /* receive message */
1777 len
= ospf6_recvmsg(&src
, &dst
, &ifindex
, iovector
, sockfd
);
1779 return OSPF6_READ_ERROR
;
1781 if ((uint
)len
> iobuflen
) {
1782 flog_err(EC_LIB_DEVELOPMENT
, "Excess message read");
1783 return OSPF6_READ_ERROR
;
1786 /* ensure some zeroes past the end, just as a security precaution */
1787 memset(recvbuf
+ len
, 0, MIN(128, iobuflen
- len
));
1789 oi
= ospf6_interface_lookup_by_ifindex(ifindex
, ospf6
->vrf_id
);
1790 if (oi
== NULL
|| oi
->area
== NULL
1791 || CHECK_FLAG(oi
->flag
, OSPF6_INTERFACE_DISABLE
)) {
1792 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN
,
1794 zlog_debug("Message received on disabled interface");
1795 return OSPF6_READ_CONTINUE
;
1797 if (CHECK_FLAG(oi
->flag
, OSPF6_INTERFACE_PASSIVE
)) {
1798 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN
,
1800 zlog_debug("%s: Ignore message on passive interface %s",
1801 __func__
, oi
->interface
->name
);
1802 return OSPF6_READ_CONTINUE
;
1806 * Drop packet destined to another VRF.
1807 * This happens when raw_l3mdev_accept is set to 1.
1809 if (ospf6
->vrf_id
!= oi
->interface
->vrf
->vrf_id
)
1810 return OSPF6_READ_CONTINUE
;
1812 oh
= (struct ospf6_header
*)recvbuf
;
1813 ret
= ospf6_auth_validate_pkt(oi
, (uint32_t *)&len
, oh
, &at_len
,
1815 if (ret
== OSPF6_AUTH_VALIDATE_SUCCESS
) {
1816 ret
= ospf6_auth_check_digest(oh
, oi
, &src
, lls_len
);
1817 if (ret
== OSPF6_AUTH_VALIDATE_FAILURE
) {
1818 if (IS_OSPF6_DEBUG_AUTH_RX
)
1820 "RECV[%s]: OSPF packet auth digest miss-match on %s",
1821 oi
->interface
->name
,
1822 ospf6_message_type(oh
->type
));
1823 oi
->at_data
.rx_drop
++;
1824 return OSPF6_READ_CONTINUE
;
1826 } else if (ret
== OSPF6_AUTH_VALIDATE_FAILURE
) {
1827 oi
->at_data
.rx_drop
++;
1828 return OSPF6_READ_CONTINUE
;
1831 if (ospf6_rxpacket_examin(oi
, oh
, len
) != MSG_OK
)
1832 return OSPF6_READ_CONTINUE
;
1834 /* Being here means, that no sizing/alignment issues were detected in
1835 the input packet. This renders the additional checks performed below
1836 and also in the type-specific dispatching functions a dead code,
1837 which can be dismissed in a cleanup-focused review round later. */
1840 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV_HDR
)) {
1841 zlog_debug("%s received on %s", ospf6_message_type(oh
->type
),
1842 oi
->interface
->name
);
1843 zlog_debug(" src: %pI6", &src
);
1844 zlog_debug(" dst: %pI6", &dst
);
1847 case OSPF6_MESSAGE_TYPE_HELLO
:
1848 ospf6_hello_print(oh
, OSPF6_ACTION_RECV
);
1850 case OSPF6_MESSAGE_TYPE_DBDESC
:
1851 ospf6_dbdesc_print(oh
, OSPF6_ACTION_RECV
);
1853 case OSPF6_MESSAGE_TYPE_LSREQ
:
1854 ospf6_lsreq_print(oh
, OSPF6_ACTION_RECV
);
1856 case OSPF6_MESSAGE_TYPE_LSUPDATE
:
1857 ospf6_lsupdate_print(oh
, OSPF6_ACTION_RECV
);
1859 case OSPF6_MESSAGE_TYPE_LSACK
:
1860 ospf6_lsack_print(oh
, OSPF6_ACTION_RECV
);
1866 if ((at_len
!= 0) && IS_OSPF6_DEBUG_AUTH_RX
)
1867 ospf6_auth_hdr_dump_recv(oh
, (len
+ at_len
+ lls_len
),
1872 case OSPF6_MESSAGE_TYPE_HELLO
:
1873 ospf6_hello_recv(&src
, &dst
, oi
, oh
);
1876 case OSPF6_MESSAGE_TYPE_DBDESC
:
1877 ospf6_dbdesc_recv(&src
, &dst
, oi
, oh
);
1880 case OSPF6_MESSAGE_TYPE_LSREQ
:
1881 ospf6_lsreq_recv(&src
, &dst
, oi
, oh
);
1884 case OSPF6_MESSAGE_TYPE_LSUPDATE
:
1885 ospf6_lsupdate_recv(&src
, &dst
, oi
, oh
);
1888 case OSPF6_MESSAGE_TYPE_LSACK
:
1889 ospf6_lsack_recv(&src
, &dst
, oi
, oh
);
1896 return OSPF6_READ_CONTINUE
;
1899 void ospf6_receive(struct thread
*thread
)
1902 struct ospf6
*ospf6
;
1905 /* add next read thread */
1906 ospf6
= THREAD_ARG(thread
);
1907 sockfd
= THREAD_FD(thread
);
1909 thread_add_read(master
, ospf6_receive
, ospf6
, ospf6
->fd
,
1910 &ospf6
->t_ospf6_receive
);
1912 while (count
< ospf6
->write_oi_count
) {
1914 switch (ospf6_read_helper(sockfd
, ospf6
)) {
1915 case OSPF6_READ_ERROR
:
1917 case OSPF6_READ_CONTINUE
:
1923 static void ospf6_fill_hdr_checksum(struct ospf6_interface
*oi
,
1924 struct ospf6_packet
*op
)
1926 struct ipv6_ph ph
= {};
1927 struct ospf6_header
*oh
;
1928 void *offset
= NULL
;
1930 if (oi
->at_data
.flags
!= 0)
1933 memcpy(&ph
.src
, oi
->linklocal_addr
, sizeof(struct in6_addr
));
1934 memcpy(&ph
.dst
, &op
->dst
, sizeof(struct in6_addr
));
1935 ph
.ulpl
= htonl(op
->length
);
1936 ph
.next_hdr
= IPPROTO_OSPFIGP
;
1938 /* Suppress static analysis warnings about accessing icmp6 oob */
1939 oh
= (struct ospf6_header
*)STREAM_DATA(op
->s
);
1941 oh
->checksum
= in_cksum_with_ph6(&ph
, offset
, op
->length
);
1944 static void ospf6_make_header(uint8_t type
, struct ospf6_interface
*oi
,
1947 struct ospf6_header
*oh
;
1949 oh
= (struct ospf6_header
*)STREAM_DATA(s
);
1951 oh
->version
= (uint8_t)OSPFV3_VERSION
;
1955 oh
->router_id
= oi
->area
->ospf6
->router_id
;
1956 oh
->area_id
= oi
->area
->area_id
;
1958 oh
->instance_id
= oi
->instance_id
;
1961 stream_forward_endp(s
, OSPF6_HEADER_SIZE
);
1964 static void ospf6_fill_header(struct ospf6_interface
*oi
, struct stream
*s
,
1967 struct ospf6_header
*oh
;
1969 oh
= (struct ospf6_header
*)STREAM_DATA(s
);
1971 oh
->length
= htons(length
);
1974 static void ospf6_fill_lsupdate_header(struct stream
*s
, uint32_t lsa_num
)
1976 struct ospf6_header
*oh
;
1977 struct ospf6_lsupdate
*lsu
;
1979 oh
= (struct ospf6_header
*)STREAM_DATA(s
);
1981 lsu
= (struct ospf6_lsupdate
*)((caddr_t
)oh
1982 + sizeof(struct ospf6_header
));
1983 lsu
->lsa_number
= htonl(lsa_num
);
1986 static void ospf6_auth_trailer_copy_keychain_key(struct ospf6_interface
*oi
)
1988 char *keychain_name
= NULL
;
1989 struct keychain
*keychain
= NULL
;
1990 struct key
*key
= NULL
;
1992 keychain_name
= oi
->at_data
.keychain
;
1993 keychain
= keychain_lookup(keychain_name
);
1995 key
= key_lookup_for_send(keychain
);
1996 if (key
&& key
->string
&&
1997 key
->hash_algo
!= KEYCHAIN_ALGO_NULL
) {
1998 /* storing the values so that further
1999 * lookup can be avoided. after
2000 * processing the digest need to reset
2003 oi
->at_data
.hash_algo
= key
->hash_algo
;
2004 if (oi
->at_data
.auth_key
)
2005 XFREE(MTYPE_OSPF6_AUTH_MANUAL_KEY
,
2006 oi
->at_data
.auth_key
);
2007 oi
->at_data
.auth_key
= XSTRDUP(
2008 MTYPE_OSPF6_AUTH_MANUAL_KEY
, key
->string
);
2009 oi
->at_data
.key_id
= key
->index
;
2010 SET_FLAG(oi
->at_data
.flags
,
2011 OSPF6_AUTH_TRAILER_KEYCHAIN_VALID
);
2016 static uint16_t ospf6_packet_max(struct ospf6_interface
*oi
)
2018 uint16_t at_len
= 0;
2020 assert(oi
->ifmtu
> sizeof(struct ip6_hdr
));
2022 if (oi
->at_data
.flags
!= 0) {
2023 if (CHECK_FLAG(oi
->at_data
.flags
, OSPF6_AUTH_TRAILER_KEYCHAIN
))
2024 ospf6_auth_trailer_copy_keychain_key(oi
);
2026 at_len
+= OSPF6_AUTH_HDR_MIN_SIZE
;
2027 at_len
+= keychain_get_hash_len(oi
->at_data
.hash_algo
);
2028 return oi
->ifmtu
- (sizeof(struct ip6_hdr
)) - at_len
;
2031 return oi
->ifmtu
- (sizeof(struct ip6_hdr
));
2034 static uint16_t ospf6_make_hello(struct ospf6_interface
*oi
, struct stream
*s
)
2036 struct listnode
*node
, *nnode
;
2037 struct ospf6_neighbor
*on
;
2038 uint16_t length
= OSPF6_HELLO_MIN_SIZE
;
2039 uint8_t options1
= oi
->area
->options
[1];
2041 if (oi
->at_data
.flags
!= 0)
2042 options1
|= OSPF6_OPT_AT
;
2044 stream_putl(s
, oi
->interface
->ifindex
);
2045 stream_putc(s
, oi
->priority
);
2046 stream_putc(s
, oi
->area
->options
[0]);
2047 stream_putc(s
, options1
);
2048 stream_putc(s
, oi
->area
->options
[2]);
2049 stream_putw(s
, oi
->hello_interval
);
2050 stream_putw(s
, oi
->dead_interval
);
2051 stream_put_ipv4(s
, oi
->drouter
);
2052 stream_put_ipv4(s
, oi
->bdrouter
);
2054 for (ALL_LIST_ELEMENTS(oi
->neighbor_list
, node
, nnode
, on
)) {
2055 if (on
->state
< OSPF6_NEIGHBOR_INIT
)
2058 if ((length
+ sizeof(uint32_t) + OSPF6_HEADER_SIZE
)
2059 > ospf6_packet_max(oi
)) {
2060 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_HELLO
,
2063 "sending Hello message: exceeds I/F MTU");
2067 stream_put_ipv4(s
, on
->router_id
);
2068 length
+= sizeof(uint32_t);
2074 static void ospf6_write(struct thread
*thread
)
2076 struct ospf6
*ospf6
= THREAD_ARG(thread
);
2077 struct ospf6_interface
*oi
;
2078 struct ospf6_header
*oh
;
2079 struct ospf6_packet
*op
;
2080 struct listnode
*node
;
2081 struct iovec iovector
[2];
2084 int64_t latency
= 0;
2085 struct timeval timestamp
;
2086 uint16_t at_len
= 0;
2088 if (ospf6
->fd
< 0) {
2089 zlog_warn("ospf6_write failed to send, fd %d", ospf6
->fd
);
2093 node
= listhead(ospf6
->oi_write_q
);
2095 oi
= listgetdata(node
);
2097 while ((pkt_count
< ospf6
->write_oi_count
) && oi
) {
2098 op
= ospf6_fifo_head(oi
->obuf
);
2100 assert(op
->length
>= OSPF6_HEADER_SIZE
);
2102 iovector
[0].iov_base
= (caddr_t
)stream_pnt(op
->s
);
2103 iovector
[0].iov_len
= op
->length
;
2104 iovector
[1].iov_base
= NULL
;
2105 iovector
[1].iov_len
= 0;
2107 oh
= (struct ospf6_header
*)STREAM_DATA(op
->s
);
2109 if (oi
->at_data
.flags
!= 0) {
2110 at_len
= ospf6_auth_len_get(oi
);
2112 iovector
[0].iov_len
=
2113 ntohs(oh
->length
) + at_len
;
2114 ospf6_auth_digest_send(oi
->linklocal_addr
, oi
,
2116 iovector
[0].iov_len
);
2118 iovector
[0].iov_len
= ntohs(oh
->length
);
2121 iovector
[0].iov_len
= ntohs(oh
->length
);
2124 len
= ospf6_sendmsg(oi
->linklocal_addr
, &op
->dst
,
2125 oi
->interface
->ifindex
, iovector
,
2128 if (len
!= (op
->length
+ (int)at_len
))
2129 flog_err(EC_LIB_DEVELOPMENT
,
2130 "Could not send entire message");
2132 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, SEND_HDR
)) {
2133 zlog_debug("%s send on %s",
2134 ospf6_message_type(oh
->type
),
2135 oi
->interface
->name
);
2136 zlog_debug(" src: %pI6", oi
->linklocal_addr
);
2137 zlog_debug(" dst: %pI6", &op
->dst
);
2139 case OSPF6_MESSAGE_TYPE_HELLO
:
2140 ospf6_hello_print(oh
, OSPF6_ACTION_SEND
);
2142 case OSPF6_MESSAGE_TYPE_DBDESC
:
2143 ospf6_dbdesc_print(oh
, OSPF6_ACTION_SEND
);
2145 case OSPF6_MESSAGE_TYPE_LSREQ
:
2146 ospf6_lsreq_print(oh
, OSPF6_ACTION_SEND
);
2148 case OSPF6_MESSAGE_TYPE_LSUPDATE
:
2149 ospf6_lsupdate_print(oh
, OSPF6_ACTION_SEND
);
2151 case OSPF6_MESSAGE_TYPE_LSACK
:
2152 ospf6_lsack_print(oh
, OSPF6_ACTION_SEND
);
2155 zlog_debug("Unknown message");
2161 case OSPF6_MESSAGE_TYPE_HELLO
:
2162 monotime(×tamp
);
2164 latency
= monotime_since(&oi
->last_hello
, NULL
)
2165 - ((int64_t)oi
->hello_interval
2168 /* log if latency exceeds the hello period */
2169 if (latency
> ((int64_t)oi
->hello_interval
* 1000000))
2170 zlog_warn("%s hello TX high latency %" PRId64
2173 oi
->last_hello
= timestamp
;
2176 case OSPF6_MESSAGE_TYPE_DBDESC
:
2179 case OSPF6_MESSAGE_TYPE_LSREQ
:
2182 case OSPF6_MESSAGE_TYPE_LSUPDATE
:
2185 case OSPF6_MESSAGE_TYPE_LSACK
:
2189 zlog_debug("Unknown message");
2194 if ((oi
->at_data
.flags
!= 0) &&
2195 (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, SEND_HDR
)) &&
2196 (IS_OSPF6_DEBUG_AUTH_TX
))
2197 ospf6_auth_hdr_dump_send(oh
, iovector
[0].iov_len
);
2199 /* initialize at_len to 0 for next packet */
2202 /* Now delete packet from queue. */
2203 ospf6_packet_delete(oi
);
2205 /* Move this interface to the tail of write_q to
2206 serve everyone in a round robin fashion */
2207 list_delete_node(ospf6
->oi_write_q
, node
);
2208 if (ospf6_fifo_head(oi
->obuf
) == NULL
) {
2212 listnode_add(ospf6
->oi_write_q
, oi
);
2215 /* Setup to service from the head of the queue again */
2216 if (!list_isempty(ospf6
->oi_write_q
)) {
2217 node
= listhead(ospf6
->oi_write_q
);
2218 oi
= listgetdata(node
);
2222 /* If packets still remain in queue, call write thread. */
2223 if (!list_isempty(ospf6
->oi_write_q
))
2224 thread_add_write(master
, ospf6_write
, ospf6
, ospf6
->fd
,
2228 void ospf6_hello_send(struct thread
*thread
)
2230 struct ospf6_interface
*oi
;
2231 struct ospf6_packet
*op
;
2232 uint16_t length
= OSPF6_HEADER_SIZE
;
2234 oi
= (struct ospf6_interface
*)THREAD_ARG(thread
);
2236 if (oi
->state
<= OSPF6_INTERFACE_DOWN
) {
2237 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_HELLO
, SEND_HDR
))
2238 zlog_debug("Unable to send Hello on down interface %s",
2239 oi
->interface
->name
);
2243 op
= ospf6_packet_new(oi
->ifmtu
);
2245 ospf6_make_header(OSPF6_MESSAGE_TYPE_HELLO
, oi
, op
->s
);
2247 /* Prepare OSPF Hello body */
2248 length
+= ospf6_make_hello(oi
, op
->s
);
2249 if (length
== OSPF6_HEADER_SIZE
) {
2250 /* Hello overshooting MTU */
2251 ospf6_packet_free(op
);
2255 /* Fill OSPF header. */
2256 ospf6_fill_header(oi
, op
->s
, length
);
2258 /* Set packet length. */
2259 op
->length
= length
;
2261 op
->dst
= allspfrouters6
;
2263 ospf6_fill_hdr_checksum(oi
, op
);
2265 /* Add packet to the top of the interface output queue, so that they
2266 * can't get delayed by things like long queues of LS Update packets
2268 ospf6_packet_add_top(oi
, op
);
2270 /* set next thread */
2271 thread_add_timer(master
, ospf6_hello_send
, oi
, oi
->hello_interval
,
2272 &oi
->thread_send_hello
);
2274 OSPF6_MESSAGE_WRITE_ON(oi
);
2277 static uint16_t ospf6_make_dbdesc(struct ospf6_neighbor
*on
, struct stream
*s
)
2279 uint16_t length
= OSPF6_DB_DESC_MIN_SIZE
;
2280 struct ospf6_lsa
*lsa
, *lsanext
;
2281 uint8_t options1
= on
->ospf6_if
->area
->options
[1];
2283 if (on
->ospf6_if
->at_data
.flags
!= 0)
2284 options1
|= OSPF6_OPT_AT
;
2286 /* if this is initial one, initialize sequence number for DbDesc */
2287 if (CHECK_FLAG(on
->dbdesc_bits
, OSPF6_DBDESC_IBIT
)
2288 && (on
->dbdesc_seqnum
== 0)) {
2289 on
->dbdesc_seqnum
= frr_sequence32_next();
2293 stream_putc(s
, 0); /* reserved 1 */
2294 stream_putc(s
, on
->ospf6_if
->area
->options
[0]);
2295 stream_putc(s
, options1
);
2296 stream_putc(s
, on
->ospf6_if
->area
->options
[2]);
2297 stream_putw(s
, on
->ospf6_if
->ifmtu
);
2298 stream_putc(s
, 0); /* reserved 2 */
2299 stream_putc(s
, on
->dbdesc_bits
);
2300 stream_putl(s
, on
->dbdesc_seqnum
);
2302 /* if this is not initial one, set LSA headers in dbdesc */
2303 if (!CHECK_FLAG(on
->dbdesc_bits
, OSPF6_DBDESC_IBIT
)) {
2304 for (ALL_LSDB(on
->dbdesc_list
, lsa
, lsanext
)) {
2305 ospf6_lsa_age_update_to_send(lsa
,
2306 on
->ospf6_if
->transdelay
);
2309 if ((length
+ sizeof(struct ospf6_lsa_header
)
2310 + OSPF6_HEADER_SIZE
)
2311 > ospf6_packet_max(on
->ospf6_if
)) {
2312 ospf6_lsa_unlock(lsa
);
2314 ospf6_lsa_unlock(lsanext
);
2317 stream_put(s
, lsa
->header
,
2318 sizeof(struct ospf6_lsa_header
));
2319 length
+= sizeof(struct ospf6_lsa_header
);
2325 void ospf6_dbdesc_send(struct thread
*thread
)
2327 struct ospf6_neighbor
*on
;
2328 uint16_t length
= OSPF6_HEADER_SIZE
;
2329 struct ospf6_packet
*op
;
2331 on
= (struct ospf6_neighbor
*)THREAD_ARG(thread
);
2333 if (on
->state
< OSPF6_NEIGHBOR_EXSTART
) {
2334 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_DBDESC
, SEND
))
2336 "Quit to send DbDesc to neighbor %s state %s",
2337 on
->name
, ospf6_neighbor_state_str
[on
->state
]);
2341 /* set next thread if master */
2342 if (CHECK_FLAG(on
->dbdesc_bits
, OSPF6_DBDESC_MSBIT
))
2343 thread_add_timer(master
, ospf6_dbdesc_send
, on
,
2344 on
->ospf6_if
->rxmt_interval
,
2345 &on
->thread_send_dbdesc
);
2347 op
= ospf6_packet_new(on
->ospf6_if
->ifmtu
);
2348 ospf6_make_header(OSPF6_MESSAGE_TYPE_DBDESC
, on
->ospf6_if
, op
->s
);
2350 length
+= ospf6_make_dbdesc(on
, op
->s
);
2351 ospf6_fill_header(on
->ospf6_if
, op
->s
, length
);
2353 /* Set packet length. */
2354 op
->length
= length
;
2356 if (on
->ospf6_if
->state
== OSPF6_INTERFACE_POINTTOPOINT
)
2357 op
->dst
= allspfrouters6
;
2359 op
->dst
= on
->linklocal_addr
;
2361 ospf6_fill_hdr_checksum(on
->ospf6_if
, op
);
2363 ospf6_packet_add(on
->ospf6_if
, op
);
2365 OSPF6_MESSAGE_WRITE_ON(on
->ospf6_if
);
2368 void ospf6_dbdesc_send_newone(struct thread
*thread
)
2370 struct ospf6_neighbor
*on
;
2371 struct ospf6_lsa
*lsa
, *lsanext
;
2372 unsigned int size
= 0;
2374 on
= (struct ospf6_neighbor
*)THREAD_ARG(thread
);
2375 ospf6_lsdb_remove_all(on
->dbdesc_list
);
2377 /* move LSAs from summary_list to dbdesc_list (within neighbor
2379 so that ospf6_send_dbdesc () can send those LSAs */
2380 size
= sizeof(struct ospf6_lsa_header
) + sizeof(struct ospf6_dbdesc
);
2381 for (ALL_LSDB(on
->summary_list
, lsa
, lsanext
)) {
2382 /* if stub area then don't advertise AS-External LSAs */
2383 if ((IS_AREA_STUB(on
->ospf6_if
->area
)
2384 || IS_AREA_NSSA(on
->ospf6_if
->area
))
2385 && ntohs(lsa
->header
->type
) == OSPF6_LSTYPE_AS_EXTERNAL
) {
2386 ospf6_lsdb_remove(lsa
, on
->summary_list
);
2390 if (size
+ sizeof(struct ospf6_lsa_header
)
2391 > ospf6_packet_max(on
->ospf6_if
)) {
2392 ospf6_lsa_unlock(lsa
);
2394 ospf6_lsa_unlock(lsanext
);
2398 ospf6_lsdb_add(ospf6_lsa_copy(lsa
), on
->dbdesc_list
);
2399 ospf6_lsdb_remove(lsa
, on
->summary_list
);
2400 size
+= sizeof(struct ospf6_lsa_header
);
2403 if (on
->summary_list
->count
== 0)
2404 UNSET_FLAG(on
->dbdesc_bits
, OSPF6_DBDESC_MBIT
);
2406 /* If slave, More bit check must be done here */
2407 if (!CHECK_FLAG(on
->dbdesc_bits
, OSPF6_DBDESC_MSBIT
) && /* Slave */
2408 !CHECK_FLAG(on
->dbdesc_last
.bits
, OSPF6_DBDESC_MBIT
)
2409 && !CHECK_FLAG(on
->dbdesc_bits
, OSPF6_DBDESC_MBIT
))
2410 thread_add_event(master
, exchange_done
, on
, 0,
2411 &on
->thread_exchange_done
);
2413 thread_execute(master
, ospf6_dbdesc_send
, on
, 0);
2416 static uint16_t ospf6_make_lsreq(struct ospf6_neighbor
*on
, struct stream
*s
)
2418 uint16_t length
= 0;
2419 struct ospf6_lsa
*lsa
, *lsanext
, *last_req
= NULL
;
2421 for (ALL_LSDB(on
->request_list
, lsa
, lsanext
)) {
2422 if ((length
+ OSPF6_HEADER_SIZE
)
2423 > ospf6_packet_max(on
->ospf6_if
)) {
2424 ospf6_lsa_unlock(lsa
);
2426 ospf6_lsa_unlock(lsanext
);
2429 stream_putw(s
, 0); /* reserved */
2430 stream_putw(s
, ntohs(lsa
->header
->type
));
2431 stream_putl(s
, ntohl(lsa
->header
->id
));
2432 stream_putl(s
, ntohl(lsa
->header
->adv_router
));
2433 length
+= sizeof(struct ospf6_lsreq_entry
);
2437 if (last_req
!= NULL
) {
2438 if (on
->last_ls_req
!= NULL
)
2439 on
->last_ls_req
= ospf6_lsa_unlock(on
->last_ls_req
);
2441 ospf6_lsa_lock(last_req
);
2442 on
->last_ls_req
= last_req
;
2448 static uint16_t ospf6_make_lsack_neighbor(struct ospf6_neighbor
*on
,
2449 struct ospf6_packet
**op
)
2451 uint16_t length
= 0;
2452 struct ospf6_lsa
*lsa
, *lsanext
;
2455 for (ALL_LSDB(on
->lsack_list
, lsa
, lsanext
)) {
2456 if ((length
+ sizeof(struct ospf6_lsa_header
)
2457 + OSPF6_HEADER_SIZE
)
2458 > ospf6_packet_max(on
->ospf6_if
)) {
2459 /* if we run out of packet size/space here,
2460 better to try again soon. */
2462 ospf6_fill_header(on
->ospf6_if
, (*op
)->s
,
2463 length
+ OSPF6_HEADER_SIZE
);
2465 (*op
)->length
= length
+ OSPF6_HEADER_SIZE
;
2466 (*op
)->dst
= on
->linklocal_addr
;
2467 ospf6_fill_hdr_checksum(on
->ospf6_if
, *op
);
2468 ospf6_packet_add(on
->ospf6_if
, *op
);
2469 OSPF6_MESSAGE_WRITE_ON(on
->ospf6_if
);
2471 *op
= ospf6_packet_new(on
->ospf6_if
->ifmtu
);
2472 ospf6_make_header(OSPF6_MESSAGE_TYPE_LSACK
,
2473 on
->ospf6_if
, (*op
)->s
);
2478 ospf6_lsa_age_update_to_send(lsa
, on
->ospf6_if
->transdelay
);
2479 stream_put((*op
)->s
, lsa
->header
,
2480 sizeof(struct ospf6_lsa_header
));
2481 length
+= sizeof(struct ospf6_lsa_header
);
2483 assert(lsa
->lock
== 2);
2484 ospf6_lsdb_remove(lsa
, on
->lsack_list
);
2490 void ospf6_lsreq_send(struct thread
*thread
)
2492 struct ospf6_neighbor
*on
;
2493 struct ospf6_packet
*op
;
2494 uint16_t length
= OSPF6_HEADER_SIZE
;
2496 on
= (struct ospf6_neighbor
*)THREAD_ARG(thread
);
2498 /* LSReq will be sent only in ExStart or Loading */
2499 if (on
->state
!= OSPF6_NEIGHBOR_EXCHANGE
2500 && on
->state
!= OSPF6_NEIGHBOR_LOADING
) {
2501 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_LSREQ
, SEND_HDR
))
2502 zlog_debug("Quit to send LSReq to neighbor %s state %s",
2504 ospf6_neighbor_state_str
[on
->state
]);
2508 /* schedule loading_done if request list is empty */
2509 if (on
->request_list
->count
== 0) {
2510 thread_add_event(master
, loading_done
, on
, 0, NULL
);
2514 op
= ospf6_packet_new(on
->ospf6_if
->ifmtu
);
2515 ospf6_make_header(OSPF6_MESSAGE_TYPE_LSREQ
, on
->ospf6_if
, op
->s
);
2517 length
+= ospf6_make_lsreq(on
, op
->s
);
2519 if (length
== OSPF6_HEADER_SIZE
) {
2520 /* Hello overshooting MTU */
2521 ospf6_packet_free(op
);
2525 /* Fill OSPF header. */
2526 ospf6_fill_header(on
->ospf6_if
, op
->s
, length
);
2528 /* Set packet length */
2529 op
->length
= length
;
2531 if (on
->ospf6_if
->state
== OSPF6_INTERFACE_POINTTOPOINT
)
2532 op
->dst
= allspfrouters6
;
2534 op
->dst
= on
->linklocal_addr
;
2536 ospf6_fill_hdr_checksum(on
->ospf6_if
, op
);
2537 ospf6_packet_add(on
->ospf6_if
, op
);
2539 OSPF6_MESSAGE_WRITE_ON(on
->ospf6_if
);
2541 /* set next thread */
2542 if (on
->request_list
->count
!= 0) {
2543 thread_add_timer(master
, ospf6_lsreq_send
, on
,
2544 on
->ospf6_if
->rxmt_interval
,
2545 &on
->thread_send_lsreq
);
2549 static void ospf6_send_lsupdate(struct ospf6_neighbor
*on
,
2550 struct ospf6_interface
*oi
,
2551 struct ospf6_packet
*op
)
2556 if ((on
->ospf6_if
->state
== OSPF6_INTERFACE_POINTTOPOINT
)
2557 || (on
->ospf6_if
->state
== OSPF6_INTERFACE_DR
)
2558 || (on
->ospf6_if
->state
== OSPF6_INTERFACE_BDR
))
2559 op
->dst
= allspfrouters6
;
2561 op
->dst
= on
->linklocal_addr
;
2564 if ((oi
->state
== OSPF6_INTERFACE_POINTTOPOINT
)
2565 || (oi
->state
== OSPF6_INTERFACE_DR
)
2566 || (oi
->state
== OSPF6_INTERFACE_BDR
))
2567 op
->dst
= allspfrouters6
;
2569 op
->dst
= alldrouters6
;
2572 ospf6_fill_hdr_checksum(oi
, op
);
2573 ospf6_packet_add(oi
, op
);
2574 /* If ospf instance is being deleted, send the packet
2577 if ((oi
->area
== NULL
) || (oi
->area
->ospf6
== NULL
))
2579 if (oi
->area
->ospf6
->inst_shutdown
) {
2580 if (oi
->on_write_q
== 0) {
2581 listnode_add(oi
->area
->ospf6
->oi_write_q
, oi
);
2584 thread_execute(master
, ospf6_write
, oi
->area
->ospf6
, 0);
2586 OSPF6_MESSAGE_WRITE_ON(oi
);
2590 static uint16_t ospf6_make_lsupdate_list(struct ospf6_neighbor
*on
,
2591 struct ospf6_packet
**op
, int *lsa_cnt
)
2593 uint16_t length
= OSPF6_LS_UPD_MIN_SIZE
;
2594 struct ospf6_lsa
*lsa
, *lsanext
;
2596 /* skip over fixed header */
2597 stream_forward_endp((*op
)->s
, OSPF6_LS_UPD_MIN_SIZE
);
2599 for (ALL_LSDB(on
->lsupdate_list
, lsa
, lsanext
)) {
2600 if ((length
+ OSPF6_LSA_SIZE(lsa
->header
) + OSPF6_HEADER_SIZE
) >
2601 ospf6_packet_max(on
->ospf6_if
)) {
2602 ospf6_fill_header(on
->ospf6_if
, (*op
)->s
,
2603 length
+ OSPF6_HEADER_SIZE
);
2604 (*op
)->length
= length
+ OSPF6_HEADER_SIZE
;
2605 ospf6_fill_lsupdate_header((*op
)->s
, *lsa_cnt
);
2606 ospf6_send_lsupdate(on
, NULL
, *op
);
2608 /* refresh packet */
2609 *op
= ospf6_packet_new(on
->ospf6_if
->ifmtu
);
2610 length
= OSPF6_LS_UPD_MIN_SIZE
;
2612 ospf6_make_header(OSPF6_MESSAGE_TYPE_LSUPDATE
,
2613 on
->ospf6_if
, (*op
)->s
);
2614 stream_forward_endp((*op
)->s
, OSPF6_LS_UPD_MIN_SIZE
);
2616 ospf6_lsa_age_update_to_send(lsa
, on
->ospf6_if
->transdelay
);
2617 stream_put((*op
)->s
, lsa
->header
, OSPF6_LSA_SIZE(lsa
->header
));
2619 length
+= OSPF6_LSA_SIZE(lsa
->header
);
2620 assert(lsa
->lock
== 2);
2621 ospf6_lsdb_remove(lsa
, on
->lsupdate_list
);
2626 static uint16_t ospf6_make_ls_retrans_list(struct ospf6_neighbor
*on
,
2627 struct ospf6_packet
**op
,
2630 uint16_t length
= OSPF6_LS_UPD_MIN_SIZE
;
2631 struct ospf6_lsa
*lsa
, *lsanext
;
2633 /* skip over fixed header */
2634 stream_forward_endp((*op
)->s
, OSPF6_LS_UPD_MIN_SIZE
);
2636 for (ALL_LSDB(on
->retrans_list
, lsa
, lsanext
)) {
2637 if ((length
+ OSPF6_LSA_SIZE(lsa
->header
) + OSPF6_HEADER_SIZE
) >
2638 ospf6_packet_max(on
->ospf6_if
)) {
2639 ospf6_fill_header(on
->ospf6_if
, (*op
)->s
,
2640 length
+ OSPF6_HEADER_SIZE
);
2641 (*op
)->length
= length
+ OSPF6_HEADER_SIZE
;
2642 ospf6_fill_lsupdate_header((*op
)->s
, *lsa_cnt
);
2643 if (on
->ospf6_if
->state
== OSPF6_INTERFACE_POINTTOPOINT
)
2644 (*op
)->dst
= allspfrouters6
;
2646 (*op
)->dst
= on
->linklocal_addr
;
2648 ospf6_fill_hdr_checksum(on
->ospf6_if
, *op
);
2649 ospf6_packet_add(on
->ospf6_if
, *op
);
2650 OSPF6_MESSAGE_WRITE_ON(on
->ospf6_if
);
2652 /* refresh packet */
2653 *op
= ospf6_packet_new(on
->ospf6_if
->ifmtu
);
2654 length
= OSPF6_LS_UPD_MIN_SIZE
;
2656 ospf6_make_header(OSPF6_MESSAGE_TYPE_LSUPDATE
,
2657 on
->ospf6_if
, (*op
)->s
);
2658 stream_forward_endp((*op
)->s
, OSPF6_LS_UPD_MIN_SIZE
);
2660 ospf6_lsa_age_update_to_send(lsa
, on
->ospf6_if
->transdelay
);
2661 stream_put((*op
)->s
, lsa
->header
, OSPF6_LSA_SIZE(lsa
->header
));
2663 length
+= OSPF6_LSA_SIZE(lsa
->header
);
2668 void ospf6_lsupdate_send_neighbor(struct thread
*thread
)
2670 struct ospf6_neighbor
*on
;
2671 struct ospf6_packet
*op
;
2672 uint16_t length
= OSPF6_HEADER_SIZE
;
2675 on
= (struct ospf6_neighbor
*)THREAD_ARG(thread
);
2677 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_LSUPDATE
, SEND_HDR
))
2678 zlog_debug("LSUpdate to neighbor %s", on
->name
);
2680 if (on
->state
< OSPF6_NEIGHBOR_EXCHANGE
) {
2681 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_LSUPDATE
,
2683 zlog_debug("Quit to send (neighbor state %s)",
2684 ospf6_neighbor_state_str
[on
->state
]);
2688 /* first do lsupdate_list */
2689 op
= ospf6_packet_new(on
->ospf6_if
->ifmtu
);
2690 ospf6_make_header(OSPF6_MESSAGE_TYPE_LSUPDATE
, on
->ospf6_if
, op
->s
);
2691 length
+= ospf6_make_lsupdate_list(on
, &op
, &lsa_cnt
);
2693 /* Fill OSPF header. */
2694 ospf6_fill_header(on
->ospf6_if
, op
->s
, length
);
2695 ospf6_fill_lsupdate_header(op
->s
, lsa_cnt
);
2696 op
->length
= length
;
2697 ospf6_send_lsupdate(on
, NULL
, op
);
2699 /* prepare new packet */
2700 op
= ospf6_packet_new(on
->ospf6_if
->ifmtu
);
2701 length
= OSPF6_HEADER_SIZE
;
2704 stream_reset(op
->s
);
2705 length
= OSPF6_HEADER_SIZE
;
2708 ospf6_make_header(OSPF6_MESSAGE_TYPE_LSUPDATE
, on
->ospf6_if
, op
->s
);
2709 /* now do retransmit list */
2710 length
+= ospf6_make_ls_retrans_list(on
, &op
, &lsa_cnt
);
2712 ospf6_fill_header(on
->ospf6_if
, op
->s
, length
);
2713 ospf6_fill_lsupdate_header(op
->s
, lsa_cnt
);
2714 op
->length
= length
;
2715 if (on
->ospf6_if
->state
== OSPF6_INTERFACE_POINTTOPOINT
)
2716 op
->dst
= allspfrouters6
;
2718 op
->dst
= on
->linklocal_addr
;
2719 ospf6_fill_hdr_checksum(on
->ospf6_if
, op
);
2720 ospf6_packet_add(on
->ospf6_if
, op
);
2721 OSPF6_MESSAGE_WRITE_ON(on
->ospf6_if
);
2723 ospf6_packet_free(op
);
2725 if (on
->lsupdate_list
->count
!= 0) {
2726 thread_add_event(master
, ospf6_lsupdate_send_neighbor
, on
, 0,
2727 &on
->thread_send_lsupdate
);
2728 } else if (on
->retrans_list
->count
!= 0) {
2729 thread_add_timer(master
, ospf6_lsupdate_send_neighbor
, on
,
2730 on
->ospf6_if
->rxmt_interval
,
2731 &on
->thread_send_lsupdate
);
2735 int ospf6_lsupdate_send_neighbor_now(struct ospf6_neighbor
*on
,
2736 struct ospf6_lsa
*lsa
)
2738 struct ospf6_packet
*op
;
2739 uint16_t length
= OSPF6_HEADER_SIZE
;
2741 op
= ospf6_packet_new(on
->ospf6_if
->ifmtu
);
2742 ospf6_make_header(OSPF6_MESSAGE_TYPE_LSUPDATE
, on
->ospf6_if
, op
->s
);
2744 /* skip over fixed header */
2745 stream_forward_endp(op
->s
, OSPF6_LS_UPD_MIN_SIZE
);
2746 ospf6_lsa_age_update_to_send(lsa
, on
->ospf6_if
->transdelay
);
2747 stream_put(op
->s
, lsa
->header
, OSPF6_LSA_SIZE(lsa
->header
));
2748 length
= OSPF6_HEADER_SIZE
+ OSPF6_LS_UPD_MIN_SIZE
2749 + OSPF6_LSA_SIZE(lsa
->header
);
2750 ospf6_fill_header(on
->ospf6_if
, op
->s
, length
);
2751 ospf6_fill_lsupdate_header(op
->s
, 1);
2752 op
->length
= length
;
2754 if (IS_OSPF6_DEBUG_FLOODING
2755 || IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_LSUPDATE
, SEND_HDR
))
2756 zlog_debug("%s: Send lsupdate with lsa %s (age %u)", __func__
,
2757 lsa
->name
, ntohs(lsa
->header
->age
));
2759 ospf6_send_lsupdate(on
, NULL
, op
);
2764 static uint16_t ospf6_make_lsupdate_interface(struct ospf6_interface
*oi
,
2765 struct ospf6_packet
**op
,
2768 uint16_t length
= OSPF6_LS_UPD_MIN_SIZE
;
2769 struct ospf6_lsa
*lsa
, *lsanext
;
2771 /* skip over fixed header */
2772 stream_forward_endp((*op
)->s
, OSPF6_LS_UPD_MIN_SIZE
);
2774 for (ALL_LSDB(oi
->lsupdate_list
, lsa
, lsanext
)) {
2775 if (length
+ OSPF6_LSA_SIZE(lsa
->header
) + OSPF6_HEADER_SIZE
>
2776 ospf6_packet_max(oi
)) {
2777 ospf6_fill_header(oi
, (*op
)->s
,
2778 length
+ OSPF6_HEADER_SIZE
);
2779 (*op
)->length
= length
+ OSPF6_HEADER_SIZE
;
2780 ospf6_fill_lsupdate_header((*op
)->s
, *lsa_cnt
);
2781 ospf6_send_lsupdate(NULL
, oi
, *op
);
2783 /* refresh packet */
2784 *op
= ospf6_packet_new(oi
->ifmtu
);
2785 length
= OSPF6_LS_UPD_MIN_SIZE
;
2787 ospf6_make_header(OSPF6_MESSAGE_TYPE_LSUPDATE
, oi
,
2789 stream_forward_endp((*op
)->s
, OSPF6_LS_UPD_MIN_SIZE
);
2792 ospf6_lsa_age_update_to_send(lsa
, oi
->transdelay
);
2793 stream_put((*op
)->s
, lsa
->header
, OSPF6_LSA_SIZE(lsa
->header
));
2795 length
+= OSPF6_LSA_SIZE(lsa
->header
);
2797 assert(lsa
->lock
== 2);
2798 ospf6_lsdb_remove(lsa
, oi
->lsupdate_list
);
2803 void ospf6_lsupdate_send_interface(struct thread
*thread
)
2805 struct ospf6_interface
*oi
;
2806 struct ospf6_packet
*op
;
2807 uint16_t length
= OSPF6_HEADER_SIZE
;
2810 oi
= (struct ospf6_interface
*)THREAD_ARG(thread
);
2812 if (oi
->state
<= OSPF6_INTERFACE_WAITING
) {
2813 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_LSUPDATE
,
2816 "Quit to send LSUpdate to interface %s state %s",
2817 oi
->interface
->name
,
2818 ospf6_interface_state_str
[oi
->state
]);
2822 /* if we have nothing to send, return */
2823 if (oi
->lsupdate_list
->count
== 0)
2826 op
= ospf6_packet_new(oi
->ifmtu
);
2827 ospf6_make_header(OSPF6_MESSAGE_TYPE_LSUPDATE
, oi
, op
->s
);
2828 length
+= ospf6_make_lsupdate_interface(oi
, &op
, &lsa_cnt
);
2830 /* Fill OSPF header. */
2831 ospf6_fill_header(oi
, op
->s
, length
);
2832 ospf6_fill_lsupdate_header(op
->s
, lsa_cnt
);
2833 op
->length
= length
;
2834 ospf6_send_lsupdate(NULL
, oi
, op
);
2836 ospf6_packet_free(op
);
2838 if (oi
->lsupdate_list
->count
> 0) {
2839 thread_add_event(master
, ospf6_lsupdate_send_interface
, oi
, 0,
2840 &oi
->thread_send_lsupdate
);
2844 void ospf6_lsack_send_neighbor(struct thread
*thread
)
2846 struct ospf6_neighbor
*on
;
2847 struct ospf6_packet
*op
;
2848 uint16_t length
= OSPF6_HEADER_SIZE
;
2850 on
= (struct ospf6_neighbor
*)THREAD_ARG(thread
);
2852 if (on
->state
< OSPF6_NEIGHBOR_EXCHANGE
) {
2853 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_LSACK
, SEND_HDR
))
2854 zlog_debug("Quit to send LSAck to neighbor %s state %s",
2856 ospf6_neighbor_state_str
[on
->state
]);
2860 /* if we have nothing to send, return */
2861 if (on
->lsack_list
->count
== 0)
2864 op
= ospf6_packet_new(on
->ospf6_if
->ifmtu
);
2865 ospf6_make_header(OSPF6_MESSAGE_TYPE_LSACK
, on
->ospf6_if
, op
->s
);
2867 length
+= ospf6_make_lsack_neighbor(on
, &op
);
2869 if (length
== OSPF6_HEADER_SIZE
) {
2870 ospf6_packet_free(op
);
2874 /* Fill OSPF header. */
2875 ospf6_fill_header(on
->ospf6_if
, op
->s
, length
);
2877 /* Set packet length, dst and queue to FIFO. */
2878 op
->length
= length
;
2879 op
->dst
= on
->linklocal_addr
;
2880 ospf6_fill_hdr_checksum(on
->ospf6_if
, op
);
2881 ospf6_packet_add(on
->ospf6_if
, op
);
2882 OSPF6_MESSAGE_WRITE_ON(on
->ospf6_if
);
2884 if (on
->lsack_list
->count
> 0)
2885 thread_add_event(master
, ospf6_lsack_send_neighbor
, on
, 0,
2886 &on
->thread_send_lsack
);
2889 static uint16_t ospf6_make_lsack_interface(struct ospf6_interface
*oi
,
2890 struct ospf6_packet
*op
)
2892 uint16_t length
= 0;
2893 struct ospf6_lsa
*lsa
, *lsanext
;
2895 for (ALL_LSDB(oi
->lsack_list
, lsa
, lsanext
)) {
2896 if ((length
+ sizeof(struct ospf6_lsa_header
)
2897 + OSPF6_HEADER_SIZE
)
2898 > ospf6_packet_max(oi
)) {
2899 /* if we run out of packet size/space here,
2900 better to try again soon. */
2901 THREAD_OFF(oi
->thread_send_lsack
);
2902 thread_add_event(master
, ospf6_lsack_send_interface
, oi
,
2903 0, &oi
->thread_send_lsack
);
2905 ospf6_lsa_unlock(lsa
);
2907 ospf6_lsa_unlock(lsanext
);
2910 ospf6_lsa_age_update_to_send(lsa
, oi
->transdelay
);
2911 stream_put(op
->s
, lsa
->header
, sizeof(struct ospf6_lsa_header
));
2912 length
+= sizeof(struct ospf6_lsa_header
);
2914 assert(lsa
->lock
== 2);
2915 ospf6_lsdb_remove(lsa
, oi
->lsack_list
);
2920 void ospf6_lsack_send_interface(struct thread
*thread
)
2922 struct ospf6_interface
*oi
;
2923 struct ospf6_packet
*op
;
2924 uint16_t length
= OSPF6_HEADER_SIZE
;
2926 oi
= (struct ospf6_interface
*)THREAD_ARG(thread
);
2928 if (oi
->state
<= OSPF6_INTERFACE_WAITING
) {
2929 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_LSACK
, SEND_HDR
))
2931 "Quit to send LSAck to interface %s state %s",
2932 oi
->interface
->name
,
2933 ospf6_interface_state_str
[oi
->state
]);
2937 /* if we have nothing to send, return */
2938 if (oi
->lsack_list
->count
== 0)
2941 op
= ospf6_packet_new(oi
->ifmtu
);
2942 ospf6_make_header(OSPF6_MESSAGE_TYPE_LSACK
, oi
, op
->s
);
2944 length
+= ospf6_make_lsack_interface(oi
, op
);
2946 if (length
== OSPF6_HEADER_SIZE
) {
2947 ospf6_packet_free(op
);
2950 /* Fill OSPF header. */
2951 ospf6_fill_header(oi
, op
->s
, length
);
2953 /* Set packet length, dst and queue to FIFO. */
2954 op
->length
= length
;
2955 if ((oi
->state
== OSPF6_INTERFACE_POINTTOPOINT
)
2956 || (oi
->state
== OSPF6_INTERFACE_DR
)
2957 || (oi
->state
== OSPF6_INTERFACE_BDR
))
2958 op
->dst
= allspfrouters6
;
2960 op
->dst
= alldrouters6
;
2962 ospf6_fill_hdr_checksum(oi
, op
);
2963 ospf6_packet_add(oi
, op
);
2964 OSPF6_MESSAGE_WRITE_ON(oi
);
2966 if (oi
->lsack_list
->count
> 0)
2967 thread_add_event(master
, ospf6_lsack_send_interface
, oi
, 0,
2968 &oi
->thread_send_lsack
);
2972 DEFUN(debug_ospf6_message
, debug_ospf6_message_cmd
,
2973 "debug ospf6 message <unknown|hello|dbdesc|lsreq|lsupdate|lsack|all> [<send|recv|send-hdr|recv-hdr>]",
2975 "Debug OSPFv3 message\n"
2976 "Debug Unknown message\n"
2977 "Debug Hello message\n"
2978 "Debug Database Description message\n"
2979 "Debug Link State Request message\n"
2980 "Debug Link State Update message\n"
2981 "Debug Link State Acknowledgement message\n"
2982 "Debug All message\n"
2983 "Debug only sending message, entire packet\n"
2984 "Debug only receiving message, entire packet\n"
2985 "Debug only sending message, header only\n"
2986 "Debug only receiving message, header only\n")
2989 int idx_send_recv
= 4;
2990 unsigned char level
= 0;
2995 if (!strncmp(argv
[idx_packet
]->arg
, "u", 1))
2996 type
= OSPF6_MESSAGE_TYPE_UNKNOWN
;
2997 else if (!strncmp(argv
[idx_packet
]->arg
, "h", 1))
2998 type
= OSPF6_MESSAGE_TYPE_HELLO
;
2999 else if (!strncmp(argv
[idx_packet
]->arg
, "d", 1))
3000 type
= OSPF6_MESSAGE_TYPE_DBDESC
;
3001 else if (!strncmp(argv
[idx_packet
]->arg
, "lsr", 3))
3002 type
= OSPF6_MESSAGE_TYPE_LSREQ
;
3003 else if (!strncmp(argv
[idx_packet
]->arg
, "lsu", 3))
3004 type
= OSPF6_MESSAGE_TYPE_LSUPDATE
;
3005 else if (!strncmp(argv
[idx_packet
]->arg
, "lsa", 3))
3006 type
= OSPF6_MESSAGE_TYPE_LSACK
;
3007 else if (!strncmp(argv
[idx_packet
]->arg
, "a", 1))
3008 type
= OSPF6_MESSAGE_TYPE_ALL
;
3011 level
= OSPF6_DEBUG_MESSAGE_SEND
| OSPF6_DEBUG_MESSAGE_RECV
;
3012 else if (!strncmp(argv
[idx_send_recv
]->arg
, "send-h", 6))
3013 level
= OSPF6_DEBUG_MESSAGE_SEND_HDR
;
3014 else if (!strncmp(argv
[idx_send_recv
]->arg
, "s", 1))
3015 level
= OSPF6_DEBUG_MESSAGE_SEND
;
3016 else if (!strncmp(argv
[idx_send_recv
]->arg
, "recv-h", 6))
3017 level
= OSPF6_DEBUG_MESSAGE_RECV_HDR
;
3018 else if (!strncmp(argv
[idx_send_recv
]->arg
, "r", 1))
3019 level
= OSPF6_DEBUG_MESSAGE_RECV
;
3021 if (type
== OSPF6_MESSAGE_TYPE_ALL
) {
3022 for (i
= 0; i
< 6; i
++)
3023 OSPF6_DEBUG_MESSAGE_ON(i
, level
);
3025 OSPF6_DEBUG_MESSAGE_ON(type
, level
);
3030 DEFUN(no_debug_ospf6_message
, no_debug_ospf6_message_cmd
,
3031 "no debug ospf6 message <unknown|hello|dbdesc|lsreq|lsupdate|lsack|all> [<send|recv|send-hdr|recv-hdr>]",
3032 NO_STR DEBUG_STR OSPF6_STR
3033 "Debug OSPFv3 message\n"
3034 "Debug Unknown message\n"
3035 "Debug Hello message\n"
3036 "Debug Database Description message\n"
3037 "Debug Link State Request message\n"
3038 "Debug Link State Update message\n"
3039 "Debug Link State Acknowledgement message\n"
3040 "Debug All message\n"
3041 "Debug only sending message, entire pkt\n"
3042 "Debug only receiving message, entire pkt\n"
3043 "Debug only sending message, header only\n"
3044 "Debug only receiving message, header only\n")
3047 int idx_send_recv
= 5;
3048 unsigned char level
= 0;
3053 if (!strncmp(argv
[idx_packet
]->arg
, "u", 1))
3054 type
= OSPF6_MESSAGE_TYPE_UNKNOWN
;
3055 else if (!strncmp(argv
[idx_packet
]->arg
, "h", 1))
3056 type
= OSPF6_MESSAGE_TYPE_HELLO
;
3057 else if (!strncmp(argv
[idx_packet
]->arg
, "d", 1))
3058 type
= OSPF6_MESSAGE_TYPE_DBDESC
;
3059 else if (!strncmp(argv
[idx_packet
]->arg
, "lsr", 3))
3060 type
= OSPF6_MESSAGE_TYPE_LSREQ
;
3061 else if (!strncmp(argv
[idx_packet
]->arg
, "lsu", 3))
3062 type
= OSPF6_MESSAGE_TYPE_LSUPDATE
;
3063 else if (!strncmp(argv
[idx_packet
]->arg
, "lsa", 3))
3064 type
= OSPF6_MESSAGE_TYPE_LSACK
;
3065 else if (!strncmp(argv
[idx_packet
]->arg
, "a", 1))
3066 type
= OSPF6_MESSAGE_TYPE_ALL
;
3069 level
= OSPF6_DEBUG_MESSAGE_SEND
| OSPF6_DEBUG_MESSAGE_RECV
3070 | OSPF6_DEBUG_MESSAGE_SEND_HDR
3071 | OSPF6_DEBUG_MESSAGE_RECV_HDR
;
3072 else if (!strncmp(argv
[idx_send_recv
]->arg
, "send-h", 6))
3073 level
= OSPF6_DEBUG_MESSAGE_SEND_HDR
;
3074 else if (!strncmp(argv
[idx_send_recv
]->arg
, "s", 1))
3075 level
= OSPF6_DEBUG_MESSAGE_SEND
;
3076 else if (!strncmp(argv
[idx_send_recv
]->arg
, "recv-h", 6))
3077 level
= OSPF6_DEBUG_MESSAGE_RECV_HDR
;
3078 else if (!strncmp(argv
[idx_send_recv
]->arg
, "r", 1))
3079 level
= OSPF6_DEBUG_MESSAGE_RECV
;
3081 if (type
== OSPF6_MESSAGE_TYPE_ALL
) {
3082 for (i
= 0; i
< 6; i
++)
3083 OSPF6_DEBUG_MESSAGE_OFF(i
, level
);
3085 OSPF6_DEBUG_MESSAGE_OFF(type
, level
);
3091 int config_write_ospf6_debug_message(struct vty
*vty
)
3093 const char *type_str
[] = {"unknown", "hello", "dbdesc",
3094 "lsreq", "lsupdate", "lsack"};
3095 unsigned char s
= 0, r
= 0, sh
= 0, rh
= 0;
3098 for (i
= 0; i
< 6; i
++) {
3099 if (IS_OSPF6_DEBUG_MESSAGE_ENABLED(i
, SEND
))
3101 if (IS_OSPF6_DEBUG_MESSAGE_ENABLED(i
, RECV
))
3105 for (i
= 0; i
< 6; i
++) {
3106 if (IS_OSPF6_DEBUG_MESSAGE_ENABLED(i
, SEND_HDR
))
3108 if (IS_OSPF6_DEBUG_MESSAGE_ENABLED(i
, RECV_HDR
))
3112 if (s
== 0x3f && r
== 0x3f) {
3113 vty_out(vty
, "debug ospf6 message all\n");
3117 if (s
== 0x3f && r
== 0) {
3118 vty_out(vty
, "debug ospf6 message all send\n");
3120 } else if (s
== 0 && r
== 0x3f) {
3121 vty_out(vty
, "debug ospf6 message all recv\n");
3125 if (sh
== 0x3f && rh
== 0) {
3126 vty_out(vty
, "debug ospf6 message all send-hdr\n");
3128 } else if (sh
== 0 && rh
== 0x3f) {
3129 vty_out(vty
, "debug ospf6 message all recv-hdr\n");
3133 /* Unknown message is logged by default */
3134 if (!IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN
, SEND
)
3135 && !IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN
, RECV
))
3136 vty_out(vty
, "no debug ospf6 message unknown\n");
3137 else if (!IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN
, SEND
))
3138 vty_out(vty
, "no debug ospf6 message unknown send\n");
3139 else if (!IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN
, RECV
))
3140 vty_out(vty
, "no debug ospf6 message unknown recv\n");
3142 for (i
= 1; i
< 6; i
++) {
3143 if (IS_OSPF6_DEBUG_MESSAGE_ENABLED(i
, SEND
)
3144 && IS_OSPF6_DEBUG_MESSAGE_ENABLED(i
, RECV
)) {
3145 vty_out(vty
, "debug ospf6 message %s\n", type_str
[i
]);
3149 if (IS_OSPF6_DEBUG_MESSAGE_ENABLED(i
, SEND
))
3150 vty_out(vty
, "debug ospf6 message %s send\n",
3152 else if (IS_OSPF6_DEBUG_MESSAGE_ENABLED(i
, SEND_HDR
))
3153 vty_out(vty
, "debug ospf6 message %s send-hdr\n",
3156 if (IS_OSPF6_DEBUG_MESSAGE_ENABLED(i
, RECV
))
3157 vty_out(vty
, "debug ospf6 message %s recv\n",
3159 else if (IS_OSPF6_DEBUG_MESSAGE_ENABLED(i
, RECV_HDR
))
3160 vty_out(vty
, "debug ospf6 message %s recv-hdr\n",
3167 void install_element_ospf6_debug_message(void)
3169 install_element(ENABLE_NODE
, &debug_ospf6_message_cmd
);
3170 install_element(ENABLE_NODE
, &no_debug_ospf6_message_cmd
);
3171 install_element(CONFIG_NODE
, &debug_ospf6_message_cmd
);
3172 install_element(CONFIG_NODE
, &no_debug_ospf6_message_cmd
);