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 from %pI6 (%pI4): (my %d, rcvd %d)",
414 oi
->interface
->vrf
->name
, oi
->interface
->name
, src
,
415 &oh
->router_id
, oi
->hello_interval
,
416 ntohs(hello
->hello_interval
));
420 /* RouterDeadInterval check */
421 if (ntohs(hello
->dead_interval
) != oi
->dead_interval
) {
423 "VRF %s: I/F %s DeadInterval mismatch from %pI6 (%pI4): (my %d, rcvd %d)",
424 oi
->interface
->vrf
->name
, oi
->interface
->name
, src
,
425 &oh
->router_id
, oi
->dead_interval
,
426 ntohs(hello
->dead_interval
));
431 if (OSPF6_OPT_ISSET(hello
->options
, OSPF6_OPT_E
) !=
432 OSPF6_OPT_ISSET(oi
->area
->options
, OSPF6_OPT_E
)) {
433 zlog_warn("VRF %s: IF %s E-bit mismatch from %pI6 (%pI4)",
434 oi
->interface
->vrf
->name
, oi
->interface
->name
, src
,
440 if (OSPF6_OPT_ISSET(hello
->options
, OSPF6_OPT_N
)
441 != OSPF6_OPT_ISSET(oi
->area
->options
, OSPF6_OPT_N
)) {
442 zlog_warn("VRF %s: IF %s N-bit mismatch",
443 oi
->interface
->vrf
->name
, oi
->interface
->name
);
447 if (((OSPF6_OPT_ISSET_EXT(hello
->options
, OSPF6_OPT_AT
) ==
449 (oi
->at_data
.flags
== 0)) ||
450 ((OSPF6_OPT_ISSET_EXT(hello
->options
, OSPF6_OPT_AT
) !=
452 (oi
->at_data
.flags
!= 0))) {
453 if (IS_OSPF6_DEBUG_AUTH_RX
)
455 "VRF %s: IF %s AT-bit mismatch in hello packet",
456 oi
->interface
->vrf
->name
, oi
->interface
->name
);
457 oi
->at_data
.rx_drop
++;
461 /* Find neighbor, create if not exist */
462 on
= ospf6_neighbor_lookup(oh
->router_id
, oi
);
464 on
= ospf6_neighbor_create(oh
->router_id
, oi
);
465 on
->prev_drouter
= on
->drouter
= hello
->drouter
;
466 on
->prev_bdrouter
= on
->bdrouter
= hello
->bdrouter
;
467 on
->priority
= hello
->priority
;
470 /* check latency against hello period */
472 latency
= monotime_since(&on
->last_hello
, NULL
)
473 - ((int64_t)oi
->hello_interval
* 1000000);
474 /* log if latency exceeds the hello period */
475 if (latency
> ((int64_t)oi
->hello_interval
* 1000000))
476 zlog_warn("%s RX %pI4 high latency %" PRId64
"us.", __func__
,
477 &on
->router_id
, latency
);
478 on
->last_hello
= timestamp
;
481 /* Always override neighbor's source address */
482 memcpy(&on
->linklocal_addr
, src
, sizeof(struct in6_addr
));
484 /* Neighbor ifindex check */
485 if (on
->ifindex
!= (ifindex_t
)ntohl(hello
->interface_id
)) {
486 on
->ifindex
= ntohl(hello
->interface_id
);
487 neighbor_ifindex_change
++;
491 for (p
= (char *)((caddr_t
)hello
+ sizeof(struct ospf6_hello
));
492 p
+ sizeof(uint32_t) <= OSPF6_MESSAGE_END(oh
);
493 p
+= sizeof(uint32_t)) {
494 uint32_t *router_id
= (uint32_t *)p
;
496 if (*router_id
== oi
->area
->ospf6
->router_id
)
500 assert(p
== OSPF6_MESSAGE_END(oh
));
502 /* RouterPriority check */
503 if (on
->priority
!= hello
->priority
) {
504 on
->priority
= hello
->priority
;
509 if (on
->drouter
!= hello
->drouter
) {
510 on
->prev_drouter
= on
->drouter
;
511 on
->drouter
= hello
->drouter
;
512 if (on
->prev_drouter
== on
->router_id
513 || on
->drouter
== on
->router_id
)
518 if (on
->bdrouter
!= hello
->bdrouter
) {
519 on
->prev_bdrouter
= on
->bdrouter
;
520 on
->bdrouter
= hello
->bdrouter
;
521 if (on
->prev_bdrouter
== on
->router_id
522 || on
->bdrouter
== on
->router_id
)
526 /* BackupSeen check */
527 if (oi
->state
== OSPF6_INTERFACE_WAITING
) {
528 if (hello
->bdrouter
== on
->router_id
)
530 else if (hello
->drouter
== on
->router_id
531 && hello
->bdrouter
== htonl(0))
537 /* Execute neighbor events */
538 event_execute(master
, hello_received
, on
, 0);
540 event_execute(master
, twoway_received
, on
, 0);
542 if (OSPF6_GR_IS_ACTIVE_HELPER(on
)) {
543 if (IS_DEBUG_OSPF6_GR
)
545 "%s, Received oneway hello from RESTARTER so ignore here.",
546 __PRETTY_FUNCTION__
);
548 /* If the router is DR_OTHER, RESTARTER will not wait
549 * until it receives the hello from it if it receives
551 * So, helper might receives ONE_WAY hello from
552 * RESTARTER. So not allowing to change the state if it
553 * receives one_way hellow when it acts as HELPER for
554 * that specific neighbor.
556 event_execute(master
, oneway_received
, on
, 0);
560 if (OSPF6_GR_IS_ACTIVE_HELPER(on
)) {
561 /* As per the GR Conformance Test Case 7.2. Section 3
562 * "Also, if X was the Designated Router on network segment S
563 * when the helping relationship began, Y maintains X as the
564 * Designated Router until the helping relationship is
566 * When it is a helper for this neighbor, It should not trigger
567 * the ISM Events. Also Intentionally not setting the priority
568 * and other fields so that when the neighbor exits the Grace
569 * period, it can handle if there is any change before GR and
572 if (IS_DEBUG_OSPF6_GR
)
574 "%s, Neighbor is under GR Restart, hence ignoring the ISM Events",
575 __PRETTY_FUNCTION__
);
581 * RFC 3623 - Section 2:
582 * "If the restarting router determines that it was the Designated
583 * Router on a given segment prior to the restart, it elects
584 * itself as the Designated Router again. The restarting router
585 * knows that it was the Designated Router if, while the
586 * associated interface is in Waiting state, a Hello packet is
587 * received from a neighbor listing the router as the Designated
590 if (oi
->area
->ospf6
->gr_info
.restart_in_progress
591 && oi
->state
== OSPF6_INTERFACE_WAITING
592 && hello
->drouter
== oi
->area
->ospf6
->router_id
)
593 oi
->drouter
= hello
->drouter
;
595 /* Schedule interface events */
597 event_add_event(master
, backup_seen
, oi
, 0, NULL
);
599 event_add_event(master
, neighbor_change
, oi
, 0, NULL
);
601 if (neighbor_ifindex_change
&& on
->state
== OSPF6_NEIGHBOR_FULL
)
602 OSPF6_ROUTER_LSA_SCHEDULE(oi
->area
);
605 static void ospf6_dbdesc_recv_master(struct ospf6_header
*oh
,
606 struct ospf6_neighbor
*on
)
608 struct ospf6_dbdesc
*dbdesc
;
611 dbdesc
= (struct ospf6_dbdesc
*)((caddr_t
)oh
612 + sizeof(struct ospf6_header
));
614 if (on
->state
< OSPF6_NEIGHBOR_INIT
) {
615 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV_HDR
))
616 zlog_debug("Neighbor state less than Init, ignore");
621 case OSPF6_NEIGHBOR_TWOWAY
:
622 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV_HDR
))
623 zlog_debug("Neighbor state is 2-Way, ignore");
626 case OSPF6_NEIGHBOR_INIT
:
627 event_execute(master
, twoway_received
, on
, 0);
628 if (on
->state
!= OSPF6_NEIGHBOR_EXSTART
) {
629 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV_HDR
))
631 "Neighbor state is not ExStart, ignore");
634 /* else fall through to ExStart */
636 case OSPF6_NEIGHBOR_EXSTART
:
637 /* if neighbor obeys us as our slave, schedule negotiation_done
638 and process LSA Headers. Otherwise, ignore this message */
639 if (!CHECK_FLAG(dbdesc
->bits
, OSPF6_DBDESC_MSBIT
)
640 && !CHECK_FLAG(dbdesc
->bits
, OSPF6_DBDESC_IBIT
)
641 && ntohl(dbdesc
->seqnum
) == on
->dbdesc_seqnum
) {
642 /* execute NegotiationDone */
643 event_execute(master
, negotiation_done
, on
, 0);
645 /* Record neighbor options */
646 memcpy(on
->options
, dbdesc
->options
,
647 sizeof(on
->options
));
649 zlog_warn("VRF %s: Nbr %s: Negotiation failed",
650 on
->ospf6_if
->interface
->vrf
->name
, on
->name
);
653 /* fall through to exchange */
655 case OSPF6_NEIGHBOR_EXCHANGE
:
656 if (!memcmp(dbdesc
, &on
->dbdesc_last
,
657 sizeof(struct ospf6_dbdesc
))) {
658 /* Duplicated DatabaseDescription is dropped by master
660 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV_HDR
))
662 "Duplicated dbdesc discarded by Master, ignore");
666 if (CHECK_FLAG(dbdesc
->bits
, OSPF6_DBDESC_MSBIT
)) {
668 "DbDesc recv: Master/Slave bit mismatch Nbr %s",
670 event_add_event(master
, seqnumber_mismatch
, on
, 0,
675 if (CHECK_FLAG(dbdesc
->bits
, OSPF6_DBDESC_IBIT
)) {
676 zlog_warn("DbDesc recv: Initialize bit mismatch Nbr %s",
678 event_add_event(master
, seqnumber_mismatch
, on
, 0,
683 if (memcmp(on
->options
, dbdesc
->options
, sizeof(on
->options
))) {
684 zlog_warn("DbDesc recv: Option field mismatch Nbr %s",
686 event_add_event(master
, seqnumber_mismatch
, on
, 0,
691 if (ntohl(dbdesc
->seqnum
) != on
->dbdesc_seqnum
) {
693 "DbDesc recv: Sequence number mismatch Nbr %s (received %#lx, %#lx expected)",
694 on
->name
, (unsigned long)ntohl(dbdesc
->seqnum
),
695 (unsigned long)on
->dbdesc_seqnum
);
696 event_add_event(master
, seqnumber_mismatch
, on
, 0,
702 case OSPF6_NEIGHBOR_LOADING
:
703 case OSPF6_NEIGHBOR_FULL
:
704 if (!memcmp(dbdesc
, &on
->dbdesc_last
,
705 sizeof(struct ospf6_dbdesc
))) {
706 /* Duplicated DatabaseDescription is dropped by master
708 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV_HDR
))
710 "Duplicated dbdesc discarded by Master, ignore");
715 "DbDesc recv: Not duplicate dbdesc in state %s Nbr %s",
716 ospf6_neighbor_state_str
[on
->state
], on
->name
);
717 event_add_event(master
, seqnumber_mismatch
, on
, 0, NULL
);
725 /* Process LSA headers */
726 for (p
= (char *)((caddr_t
)dbdesc
+ sizeof(struct ospf6_dbdesc
));
727 p
+ sizeof(struct ospf6_lsa_header
) <= OSPF6_MESSAGE_END(oh
);
728 p
+= sizeof(struct ospf6_lsa_header
)) {
729 struct ospf6_lsa
*his
, *mine
;
730 struct ospf6_lsdb
*lsdb
= NULL
;
732 his
= ospf6_lsa_create_headeronly((struct ospf6_lsa_header
*)p
);
734 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
735 zlog_debug("%s", his
->name
);
737 switch (OSPF6_LSA_SCOPE(his
->header
->type
)) {
738 case OSPF6_SCOPE_LINKLOCAL
:
739 lsdb
= on
->ospf6_if
->lsdb
;
741 case OSPF6_SCOPE_AREA
:
742 lsdb
= on
->ospf6_if
->area
->lsdb
;
745 lsdb
= on
->ospf6_if
->area
->ospf6
->lsdb
;
747 case OSPF6_SCOPE_RESERVED
:
748 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
749 zlog_debug("Ignoring LSA of reserved scope");
750 ospf6_lsa_delete(his
);
754 if (ntohs(his
->header
->type
) == OSPF6_LSTYPE_AS_EXTERNAL
755 && (IS_AREA_STUB(on
->ospf6_if
->area
)
756 || IS_AREA_NSSA(on
->ospf6_if
->area
))) {
757 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
759 "SeqNumMismatch (E-bit mismatch), discard");
760 ospf6_lsa_delete(his
);
761 event_add_event(master
, seqnumber_mismatch
, on
, 0,
766 mine
= ospf6_lsdb_lookup(his
->header
->type
, his
->header
->id
,
767 his
->header
->adv_router
, lsdb
);
769 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
770 zlog_debug("Add request (No database copy)");
771 ospf6_lsdb_add(ospf6_lsa_copy(his
), on
->request_list
);
772 } else if (ospf6_lsa_compare(his
, mine
) < 0) {
773 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
774 zlog_debug("Add request (Received MoreRecent)");
775 ospf6_lsdb_add(ospf6_lsa_copy(his
), on
->request_list
);
777 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
778 zlog_debug("Discard (Existing MoreRecent)");
780 ospf6_lsa_delete(his
);
783 assert(p
== OSPF6_MESSAGE_END(oh
));
785 /* Increment sequence number */
788 /* schedule send lsreq */
789 if (on
->request_list
->count
)
790 event_add_event(master
, ospf6_lsreq_send
, on
, 0,
791 &on
->thread_send_lsreq
);
793 EVENT_OFF(on
->thread_send_dbdesc
);
796 if (!CHECK_FLAG(dbdesc
->bits
, OSPF6_DBDESC_MBIT
)
797 && !CHECK_FLAG(on
->dbdesc_bits
, OSPF6_DBDESC_MBIT
))
798 event_add_event(master
, exchange_done
, on
, 0,
799 &on
->thread_exchange_done
);
801 event_add_event(master
, ospf6_dbdesc_send_newone
, on
, 0,
802 &on
->thread_send_dbdesc
);
805 /* save last received dbdesc */
806 memcpy(&on
->dbdesc_last
, dbdesc
, sizeof(struct ospf6_dbdesc
));
809 static void ospf6_dbdesc_recv_slave(struct ospf6_header
*oh
,
810 struct ospf6_neighbor
*on
)
812 struct ospf6_dbdesc
*dbdesc
;
815 dbdesc
= (struct ospf6_dbdesc
*)((caddr_t
)oh
816 + sizeof(struct ospf6_header
));
818 if (on
->state
< OSPF6_NEIGHBOR_INIT
) {
819 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV_HDR
))
820 zlog_debug("Neighbor state less than Init, ignore");
825 case OSPF6_NEIGHBOR_TWOWAY
:
826 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV_HDR
))
827 zlog_debug("Neighbor state is 2-Way, ignore");
830 case OSPF6_NEIGHBOR_INIT
:
831 event_execute(master
, twoway_received
, on
, 0);
832 if (on
->state
!= OSPF6_NEIGHBOR_EXSTART
) {
833 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV_HDR
))
835 "Neighbor state is not ExStart, ignore");
838 /* else fall through to ExStart */
840 case OSPF6_NEIGHBOR_EXSTART
:
841 /* If the neighbor is Master, act as Slave. Schedule
843 and process LSA Headers. Otherwise, ignore this message */
844 if (CHECK_FLAG(dbdesc
->bits
, OSPF6_DBDESC_IBIT
)
845 && CHECK_FLAG(dbdesc
->bits
, OSPF6_DBDESC_MBIT
)
846 && CHECK_FLAG(dbdesc
->bits
, OSPF6_DBDESC_MSBIT
)
848 == sizeof(struct ospf6_header
)
849 + sizeof(struct ospf6_dbdesc
)) {
850 /* set the master/slave bit to slave */
851 UNSET_FLAG(on
->dbdesc_bits
, OSPF6_DBDESC_MSBIT
);
853 /* set the DD sequence number to one specified by master
855 on
->dbdesc_seqnum
= ntohl(dbdesc
->seqnum
);
857 /* schedule NegotiationDone */
858 event_execute(master
, negotiation_done
, on
, 0);
860 /* Record neighbor options */
861 memcpy(on
->options
, dbdesc
->options
,
862 sizeof(on
->options
));
864 zlog_warn("VRF %s: Nbr %s Negotiation failed",
865 on
->ospf6_if
->interface
->vrf
->name
, on
->name
);
870 case OSPF6_NEIGHBOR_EXCHANGE
:
871 if (!memcmp(dbdesc
, &on
->dbdesc_last
,
872 sizeof(struct ospf6_dbdesc
))) {
873 /* Duplicated DatabaseDescription causes slave to
875 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV_HDR
))
877 "Duplicated dbdesc causes retransmit");
878 EVENT_OFF(on
->thread_send_dbdesc
);
879 event_add_event(master
, ospf6_dbdesc_send
, on
, 0,
880 &on
->thread_send_dbdesc
);
884 if (!CHECK_FLAG(dbdesc
->bits
, OSPF6_DBDESC_MSBIT
)) {
886 "DbDesc slave recv: Master/Slave bit mismatch Nbr %s",
888 event_add_event(master
, seqnumber_mismatch
, on
, 0,
893 if (CHECK_FLAG(dbdesc
->bits
, OSPF6_DBDESC_IBIT
)) {
895 "DbDesc slave recv: Initialize bit mismatch Nbr %s",
897 event_add_event(master
, seqnumber_mismatch
, on
, 0,
902 if (memcmp(on
->options
, dbdesc
->options
, sizeof(on
->options
))) {
904 "DbDesc slave recv: Option field mismatch Nbr %s",
906 event_add_event(master
, seqnumber_mismatch
, on
, 0,
911 if (ntohl(dbdesc
->seqnum
) != on
->dbdesc_seqnum
+ 1) {
913 "DbDesc slave recv: Sequence number mismatch Nbr %s (received %#lx, %#lx expected)",
914 on
->name
, (unsigned long)ntohl(dbdesc
->seqnum
),
915 (unsigned long)on
->dbdesc_seqnum
+ 1);
916 event_add_event(master
, seqnumber_mismatch
, on
, 0,
922 case OSPF6_NEIGHBOR_LOADING
:
923 case OSPF6_NEIGHBOR_FULL
:
924 if (!memcmp(dbdesc
, &on
->dbdesc_last
,
925 sizeof(struct ospf6_dbdesc
))) {
926 /* Duplicated DatabaseDescription causes slave to
928 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV_HDR
))
930 "Duplicated dbdesc causes retransmit");
931 EVENT_OFF(on
->thread_send_dbdesc
);
932 event_add_event(master
, ospf6_dbdesc_send
, on
, 0,
933 &on
->thread_send_dbdesc
);
938 "DbDesc slave recv: Not duplicate dbdesc in state %s Nbr %s",
939 ospf6_neighbor_state_str
[on
->state
], on
->name
);
940 event_add_event(master
, seqnumber_mismatch
, on
, 0, NULL
);
948 /* Process LSA headers */
949 for (p
= (char *)((caddr_t
)dbdesc
+ sizeof(struct ospf6_dbdesc
));
950 p
+ sizeof(struct ospf6_lsa_header
) <= OSPF6_MESSAGE_END(oh
);
951 p
+= sizeof(struct ospf6_lsa_header
)) {
952 struct ospf6_lsa
*his
, *mine
;
953 struct ospf6_lsdb
*lsdb
= NULL
;
955 his
= ospf6_lsa_create_headeronly((struct ospf6_lsa_header
*)p
);
957 switch (OSPF6_LSA_SCOPE(his
->header
->type
)) {
958 case OSPF6_SCOPE_LINKLOCAL
:
959 lsdb
= on
->ospf6_if
->lsdb
;
961 case OSPF6_SCOPE_AREA
:
962 lsdb
= on
->ospf6_if
->area
->lsdb
;
965 lsdb
= on
->ospf6_if
->area
->ospf6
->lsdb
;
967 case OSPF6_SCOPE_RESERVED
:
968 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
969 zlog_debug("Ignoring LSA of reserved scope");
970 ospf6_lsa_delete(his
);
974 if (OSPF6_LSA_SCOPE(his
->header
->type
) == OSPF6_SCOPE_AS
975 && (IS_AREA_STUB(on
->ospf6_if
->area
)
976 || IS_AREA_NSSA(on
->ospf6_if
->area
))) {
977 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
978 zlog_debug("E-bit mismatch with LSA Headers");
979 ospf6_lsa_delete(his
);
980 event_add_event(master
, seqnumber_mismatch
, on
, 0,
985 mine
= ospf6_lsdb_lookup(his
->header
->type
, his
->header
->id
,
986 his
->header
->adv_router
, lsdb
);
987 if (mine
== NULL
|| ospf6_lsa_compare(his
, mine
) < 0) {
988 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
989 zlog_debug("Add request-list: %s", his
->name
);
990 ospf6_lsdb_add(ospf6_lsa_copy(his
), on
->request_list
);
992 ospf6_lsa_delete(his
);
995 assert(p
== OSPF6_MESSAGE_END(oh
));
997 /* Set sequence number to Master's */
998 on
->dbdesc_seqnum
= ntohl(dbdesc
->seqnum
);
1000 /* schedule send lsreq */
1001 if (on
->request_list
->count
)
1002 event_add_event(master
, ospf6_lsreq_send
, on
, 0,
1003 &on
->thread_send_lsreq
);
1005 EVENT_OFF(on
->thread_send_dbdesc
);
1006 event_add_event(master
, ospf6_dbdesc_send_newone
, on
, 0,
1007 &on
->thread_send_dbdesc
);
1009 /* save last received dbdesc */
1010 memcpy(&on
->dbdesc_last
, dbdesc
, sizeof(struct ospf6_dbdesc
));
1013 static void ospf6_dbdesc_recv(struct in6_addr
*src
, struct in6_addr
*dst
,
1014 struct ospf6_interface
*oi
,
1015 struct ospf6_header
*oh
)
1017 struct ospf6_neighbor
*on
;
1018 struct ospf6_dbdesc
*dbdesc
;
1020 on
= ospf6_neighbor_lookup(oh
->router_id
, oi
);
1022 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV_HDR
))
1023 zlog_debug("Neighbor not found, ignore");
1027 dbdesc
= (struct ospf6_dbdesc
*)((caddr_t
)oh
1028 + sizeof(struct ospf6_header
));
1030 if (((OSPF6_OPT_ISSET_EXT(dbdesc
->options
, OSPF6_OPT_AT
) ==
1032 (oi
->at_data
.flags
== 0)) ||
1033 ((OSPF6_OPT_ISSET_EXT(dbdesc
->options
, OSPF6_OPT_AT
) !=
1035 (oi
->at_data
.flags
!= 0))) {
1036 if (IS_OSPF6_DEBUG_AUTH_RX
)
1038 "VRF %s: IF %s AT-bit mismatch in dbdesc packet",
1039 oi
->interface
->vrf
->name
, oi
->interface
->name
);
1040 oi
->at_data
.rx_drop
++;
1044 /* Interface MTU check */
1045 if (!oi
->mtu_ignore
&& ntohs(dbdesc
->ifmtu
) != oi
->ifmtu
) {
1046 zlog_warn("VRF %s: I/F %s MTU mismatch (my %d rcvd %d)",
1047 oi
->interface
->vrf
->name
, oi
->interface
->name
,
1048 oi
->ifmtu
, ntohs(dbdesc
->ifmtu
));
1052 if (dbdesc
->reserved1
|| dbdesc
->reserved2
) {
1053 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV_HDR
))
1055 "Non-0 reserved field in %s's DbDesc, correct",
1057 dbdesc
->reserved1
= 0;
1058 dbdesc
->reserved2
= 0;
1063 if (ntohl(oh
->router_id
) < ntohl(oi
->area
->ospf6
->router_id
))
1064 ospf6_dbdesc_recv_master(oh
, on
);
1065 else if (ntohl(oi
->area
->ospf6
->router_id
) < ntohl(oh
->router_id
))
1066 ospf6_dbdesc_recv_slave(oh
, on
);
1068 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV_HDR
))
1069 zlog_debug("Can't decide which is master, ignore");
1073 static void ospf6_lsreq_recv(struct in6_addr
*src
, struct in6_addr
*dst
,
1074 struct ospf6_interface
*oi
,
1075 struct ospf6_header
*oh
)
1077 struct ospf6_neighbor
*on
;
1079 struct ospf6_lsreq_entry
*e
;
1080 struct ospf6_lsdb
*lsdb
= NULL
;
1081 struct ospf6_lsa
*lsa
;
1083 on
= ospf6_neighbor_lookup(oh
->router_id
, oi
);
1085 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV_HDR
))
1086 zlog_debug("Neighbor not found, ignore");
1090 if (on
->state
!= OSPF6_NEIGHBOR_EXCHANGE
1091 && on
->state
!= OSPF6_NEIGHBOR_LOADING
1092 && on
->state
!= OSPF6_NEIGHBOR_FULL
) {
1093 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV_HDR
))
1094 zlog_debug("Neighbor state less than Exchange, ignore");
1100 /* Process each request */
1101 for (p
= (char *)((caddr_t
)oh
+ sizeof(struct ospf6_header
));
1102 p
+ sizeof(struct ospf6_lsreq_entry
) <= OSPF6_MESSAGE_END(oh
);
1103 p
+= sizeof(struct ospf6_lsreq_entry
)) {
1104 e
= (struct ospf6_lsreq_entry
*)p
;
1106 switch (OSPF6_LSA_SCOPE(e
->type
)) {
1107 case OSPF6_SCOPE_LINKLOCAL
:
1108 lsdb
= on
->ospf6_if
->lsdb
;
1110 case OSPF6_SCOPE_AREA
:
1111 lsdb
= on
->ospf6_if
->area
->lsdb
;
1113 case OSPF6_SCOPE_AS
:
1114 lsdb
= on
->ospf6_if
->area
->ospf6
->lsdb
;
1117 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
1118 zlog_debug("Ignoring LSA of reserved scope");
1122 /* Find database copy */
1123 lsa
= ospf6_lsdb_lookup(e
->type
, e
->id
, e
->adv_router
, lsdb
);
1126 "Can't find requested lsa [%s Id:%pI4 Adv:%pI4] send badLSReq",
1127 ospf6_lstype_name(e
->type
), &e
->id
,
1129 event_add_event(master
, bad_lsreq
, on
, 0, NULL
);
1133 ospf6_lsdb_add(ospf6_lsa_copy(lsa
), on
->lsupdate_list
);
1136 assert(p
== OSPF6_MESSAGE_END(oh
));
1138 /* schedule send lsupdate */
1139 EVENT_OFF(on
->thread_send_lsupdate
);
1140 event_add_event(master
, ospf6_lsupdate_send_neighbor
, on
, 0,
1141 &on
->thread_send_lsupdate
);
1144 /* Verify, that the specified memory area contains exactly N valid IPv6
1145 prefixes as specified by RFC5340, A.4.1. */
1146 static unsigned ospf6_prefixes_examin(
1147 struct ospf6_prefix
*current
, /* start of buffer */
1149 const uint32_t req_num_pfxs
/* always compared with the actual number
1153 uint8_t requested_pfx_bytes
;
1154 uint32_t real_num_pfxs
= 0;
1157 if (length
< OSPF6_PREFIX_MIN_SIZE
) {
1158 zlog_warn("%s: undersized IPv6 prefix header",
1162 /* safe to look deeper */
1163 if (current
->prefix_length
> IPV6_MAX_BITLEN
) {
1164 zlog_warn("%s: invalid PrefixLength (%u bits)",
1165 __func__
, current
->prefix_length
);
1168 /* covers both fixed- and variable-sized fields */
1169 requested_pfx_bytes
=
1170 OSPF6_PREFIX_MIN_SIZE
1171 + OSPF6_PREFIX_SPACE(current
->prefix_length
);
1172 if (requested_pfx_bytes
> length
) {
1173 zlog_warn("%s: undersized IPv6 prefix", __func__
);
1177 length
-= requested_pfx_bytes
;
1178 current
= (struct ospf6_prefix
*)((caddr_t
)current
1179 + requested_pfx_bytes
);
1182 if (real_num_pfxs
!= req_num_pfxs
) {
1184 "%s: IPv6 prefix number mismatch (%u required, %u real)",
1185 __func__
, req_num_pfxs
, real_num_pfxs
);
1191 /* Verify an LSA to have a valid length and dispatch further (where
1192 appropriate) to check if the contents, including nested IPv6 prefixes,
1193 is properly sized/aligned within the LSA. Note that this function gets
1194 LSA type in network byte order, uses in host byte order and passes to
1195 ospf6_lstype_name() in network byte order again. */
1196 static unsigned ospf6_lsa_examin(struct ospf6_lsa_header
*lsah
,
1197 const uint16_t lsalen
,
1198 const uint8_t headeronly
)
1200 struct ospf6_intra_prefix_lsa
*intra_prefix_lsa
;
1201 struct ospf6_as_external_lsa
*as_external_lsa
;
1202 struct ospf6_link_lsa
*link_lsa
;
1203 unsigned exp_length
;
1207 /* In case an additional minimum length constraint is defined for
1209 LSA type, make sure that this constraint is met. */
1210 lsatype
= ntohs(lsah
->type
);
1211 ltindex
= lsatype
& OSPF6_LSTYPE_FCODE_MASK
;
1212 if (ltindex
< OSPF6_LSTYPE_SIZE
&& ospf6_lsa_minlen
[ltindex
]
1213 && lsalen
< ospf6_lsa_minlen
[ltindex
] + OSPF6_LSA_HEADER_SIZE
) {
1214 zlog_warn("%s: undersized (%u B) LSA", __func__
, lsalen
);
1218 case OSPF6_LSTYPE_ROUTER
:
1219 /* RFC5340 A.4.3, LSA header + OSPF6_ROUTER_LSA_MIN_SIZE bytes
1221 by N>=0 interface descriptions. */
1222 if ((lsalen
- OSPF6_LSA_HEADER_SIZE
- OSPF6_ROUTER_LSA_MIN_SIZE
)
1223 % OSPF6_ROUTER_LSDESC_FIX_SIZE
) {
1225 "%s: Router LSA interface description alignment error",
1230 case OSPF6_LSTYPE_NETWORK
:
1231 /* RFC5340 A.4.4, LSA header + OSPF6_NETWORK_LSA_MIN_SIZE bytes
1232 followed by N>=0 attached router descriptions. */
1233 if ((lsalen
- OSPF6_LSA_HEADER_SIZE
1234 - OSPF6_NETWORK_LSA_MIN_SIZE
)
1235 % OSPF6_NETWORK_LSDESC_FIX_SIZE
) {
1237 "%s: Network LSA router description alignment error",
1242 case OSPF6_LSTYPE_INTER_PREFIX
:
1243 /* RFC5340 A.4.5, LSA header + OSPF6_INTER_PREFIX_LSA_MIN_SIZE
1245 followed by 3-4 fields of a single IPv6 prefix. */
1248 return ospf6_prefixes_examin(
1249 (struct ospf6_prefix
1250 *)((caddr_t
)lsah
+ OSPF6_LSA_HEADER_SIZE
1251 + OSPF6_INTER_PREFIX_LSA_MIN_SIZE
),
1252 lsalen
- OSPF6_LSA_HEADER_SIZE
1253 - OSPF6_INTER_PREFIX_LSA_MIN_SIZE
,
1255 case OSPF6_LSTYPE_INTER_ROUTER
:
1256 /* RFC5340 A.4.6, fixed-size LSA. */
1258 > OSPF6_LSA_HEADER_SIZE
+ OSPF6_INTER_ROUTER_LSA_FIX_SIZE
) {
1259 zlog_warn("%s: Inter Router LSA oversized (%u B) LSA",
1264 case OSPF6_LSTYPE_AS_EXTERNAL
: /* RFC5340 A.4.7, same as A.4.8. */
1265 case OSPF6_LSTYPE_TYPE_7
:
1266 /* RFC5340 A.4.8, LSA header + OSPF6_AS_EXTERNAL_LSA_MIN_SIZE
1268 followed by 3-4 fields of IPv6 prefix and 3 conditional LSA
1270 16 bytes of forwarding address, 4 bytes of external route
1272 4 bytes of referenced link state ID. */
1276 (struct ospf6_as_external_lsa
1277 *)((caddr_t
)lsah
+ OSPF6_LSA_HEADER_SIZE
);
1279 OSPF6_LSA_HEADER_SIZE
+ OSPF6_AS_EXTERNAL_LSA_MIN_SIZE
;
1280 /* To find out if the last optional field (Referenced Link State
1282 assumed in this LSA, we need to access fixed fields of the
1284 prefix before ospf6_prefix_examin() confirms its sizing. */
1285 if (exp_length
+ OSPF6_PREFIX_MIN_SIZE
> lsalen
) {
1287 "%s: AS External undersized (%u B) LSA header",
1291 /* forwarding address */
1292 if (CHECK_FLAG(as_external_lsa
->bits_metric
, OSPF6_ASBR_BIT_F
))
1294 /* external route tag */
1295 if (CHECK_FLAG(as_external_lsa
->bits_metric
, OSPF6_ASBR_BIT_T
))
1297 /* referenced link state ID */
1298 if (as_external_lsa
->prefix
.u
._prefix_referenced_lstype
)
1300 /* All the fixed-size fields (mandatory and optional) must fit.
1302 this check does not include any IPv6 prefix fields. */
1303 if (exp_length
> lsalen
) {
1305 "%s: AS External undersized (%u B) LSA header",
1309 /* The last call completely covers the remainder (IPv6 prefix).
1311 return ospf6_prefixes_examin(
1312 (struct ospf6_prefix
1313 *)((caddr_t
)as_external_lsa
1314 + OSPF6_AS_EXTERNAL_LSA_MIN_SIZE
),
1315 lsalen
- exp_length
, 1);
1316 case OSPF6_LSTYPE_LINK
:
1317 /* RFC5340 A.4.9, LSA header + OSPF6_LINK_LSA_MIN_SIZE bytes
1319 by N>=0 IPv6 prefix blocks (with N declared beforehand). */
1322 link_lsa
= (struct ospf6_link_lsa
*)((caddr_t
)lsah
1323 + OSPF6_LSA_HEADER_SIZE
);
1324 return ospf6_prefixes_examin(
1325 (struct ospf6_prefix
*)((caddr_t
)link_lsa
1326 + OSPF6_LINK_LSA_MIN_SIZE
),
1327 lsalen
- OSPF6_LSA_HEADER_SIZE
1328 - OSPF6_LINK_LSA_MIN_SIZE
,
1329 ntohl(link_lsa
->prefix_num
) /* 32 bits */
1331 case OSPF6_LSTYPE_INTRA_PREFIX
:
1332 /* RFC5340 A.4.10, LSA header + OSPF6_INTRA_PREFIX_LSA_MIN_SIZE
1334 followed by N>=0 IPv6 prefixes (with N declared beforehand).
1339 (struct ospf6_intra_prefix_lsa
1340 *)((caddr_t
)lsah
+ OSPF6_LSA_HEADER_SIZE
);
1341 return ospf6_prefixes_examin(
1342 (struct ospf6_prefix
1343 *)((caddr_t
)intra_prefix_lsa
1344 + OSPF6_INTRA_PREFIX_LSA_MIN_SIZE
),
1345 lsalen
- OSPF6_LSA_HEADER_SIZE
1346 - OSPF6_INTRA_PREFIX_LSA_MIN_SIZE
,
1347 ntohs(intra_prefix_lsa
->prefix_num
) /* 16 bits */
1349 case OSPF6_LSTYPE_GRACE_LSA
:
1350 if (lsalen
< OSPF6_LSA_HEADER_SIZE
+ GRACE_PERIOD_TLV_SIZE
1351 + GRACE_RESTART_REASON_TLV_SIZE
) {
1352 if (IS_DEBUG_OSPF6_GR
)
1353 zlog_debug("%s: Undersized GraceLSA.",
1358 /* No additional validation is possible for unknown LSA types, which are
1359 themselves valid in OPSFv3, hence the default decision is to accept.
1364 /* Verify if the provided input buffer is a valid sequence of LSAs. This
1365 includes verification of LSA blocks length/alignment and dispatching
1366 of deeper-level checks. */
1368 ospf6_lsaseq_examin(struct ospf6_lsa_header
*lsah
, /* start of buffered data */
1369 size_t length
, const uint8_t headeronly
,
1370 /* When declared_num_lsas is not 0, compare it to the real
1372 and treat the difference as an error. */
1373 const uint32_t declared_num_lsas
)
1375 uint32_t counted_lsas
= 0;
1379 if (length
< OSPF6_LSA_HEADER_SIZE
) {
1381 "%s: undersized (%zu B) trailing (#%u) LSA header",
1382 __func__
, length
, counted_lsas
);
1385 /* save on ntohs() calls here and in the LSA validator */
1386 lsalen
= OSPF6_LSA_SIZE(lsah
);
1387 if (lsalen
< OSPF6_LSA_HEADER_SIZE
) {
1389 "%s: malformed LSA header #%u, declared length is %u B",
1390 __func__
, counted_lsas
, lsalen
);
1394 /* less checks here and in ospf6_lsa_examin() */
1395 if (MSG_OK
!= ospf6_lsa_examin(lsah
, lsalen
, 1)) {
1397 "%s: anomaly in header-only %s LSA #%u",
1398 __func__
, ospf6_lstype_name(lsah
->type
),
1402 lsah
= (struct ospf6_lsa_header
1404 + OSPF6_LSA_HEADER_SIZE
);
1405 length
-= OSPF6_LSA_HEADER_SIZE
;
1407 /* make sure the input buffer is deep enough before
1409 if (lsalen
> length
) {
1411 "%s: anomaly in %s LSA #%u: declared length is %u B, buffered length is %zu B",
1412 __func__
, ospf6_lstype_name(lsah
->type
),
1413 counted_lsas
, lsalen
, length
);
1416 if (MSG_OK
!= ospf6_lsa_examin(lsah
, lsalen
, 0)) {
1417 zlog_warn("%s: anomaly in %s LSA #%u", __func__
,
1418 ospf6_lstype_name(lsah
->type
),
1422 lsah
= (struct ospf6_lsa_header
*)((caddr_t
)lsah
1429 if (declared_num_lsas
&& counted_lsas
!= declared_num_lsas
) {
1430 zlog_warn("%s: #LSAs declared (%u) does not match actual (%u)",
1431 __func__
, declared_num_lsas
, counted_lsas
);
1437 /* Verify a complete OSPF packet for proper sizing/alignment. */
1438 static unsigned ospf6_packet_examin(struct ospf6_header
*oh
,
1439 const unsigned bytesonwire
)
1441 struct ospf6_lsupdate
*lsupd
;
1444 /* length, 1st approximation */
1445 if (bytesonwire
< OSPF6_HEADER_SIZE
) {
1446 zlog_warn("%s: undersized (%u B) packet", __func__
,
1451 /* Now it is safe to access header fields. */
1452 if (bytesonwire
!= ntohs(oh
->length
)) {
1453 zlog_warn("%s: %s packet length error (%u real, %u declared)",
1454 __func__
, ospf6_message_type(oh
->type
), bytesonwire
,
1460 if (oh
->version
!= OSPFV3_VERSION
) {
1461 zlog_warn("%s: invalid (%u) protocol version", __func__
,
1465 /* length, 2nd approximation */
1466 if (oh
->type
< OSPF6_MESSAGE_TYPE_ALL
&& ospf6_packet_minlen
[oh
->type
]
1468 < OSPF6_HEADER_SIZE
+ ospf6_packet_minlen
[oh
->type
]) {
1469 zlog_warn("%s: undersized (%u B) %s packet", __func__
,
1470 bytesonwire
, ospf6_message_type(oh
->type
));
1473 /* type-specific deeper validation */
1475 case OSPF6_MESSAGE_TYPE_HELLO
:
1476 /* RFC5340 A.3.2, packet header + OSPF6_HELLO_MIN_SIZE bytes
1478 by N>=0 router-IDs. */
1480 == (bytesonwire
- OSPF6_HEADER_SIZE
- OSPF6_HELLO_MIN_SIZE
)
1483 zlog_warn("%s: alignment error in %s packet", __func__
,
1484 ospf6_message_type(oh
->type
));
1486 case OSPF6_MESSAGE_TYPE_DBDESC
:
1487 /* RFC5340 A.3.3, packet header + OSPF6_DB_DESC_MIN_SIZE bytes
1489 by N>=0 header-only LSAs. */
1490 test
= ospf6_lsaseq_examin(
1491 (struct ospf6_lsa_header
*)((caddr_t
)oh
1493 + OSPF6_DB_DESC_MIN_SIZE
),
1494 bytesonwire
- OSPF6_HEADER_SIZE
1495 - OSPF6_DB_DESC_MIN_SIZE
,
1498 case OSPF6_MESSAGE_TYPE_LSREQ
:
1499 /* RFC5340 A.3.4, packet header + N>=0 LS description blocks. */
1501 == (bytesonwire
- OSPF6_HEADER_SIZE
- OSPF6_LS_REQ_MIN_SIZE
)
1502 % OSPF6_LSREQ_LSDESC_FIX_SIZE
)
1504 zlog_warn("%s: alignment error in %s packet", __func__
,
1505 ospf6_message_type(oh
->type
));
1507 case OSPF6_MESSAGE_TYPE_LSUPDATE
:
1508 /* RFC5340 A.3.5, packet header + OSPF6_LS_UPD_MIN_SIZE bytes
1510 by N>=0 full LSAs (with N declared beforehand). */
1511 lsupd
= (struct ospf6_lsupdate
*)((caddr_t
)oh
1512 + OSPF6_HEADER_SIZE
);
1513 test
= ospf6_lsaseq_examin(
1514 (struct ospf6_lsa_header
*)((caddr_t
)lsupd
1515 + OSPF6_LS_UPD_MIN_SIZE
),
1516 bytesonwire
- OSPF6_HEADER_SIZE
- OSPF6_LS_UPD_MIN_SIZE
,
1517 0, ntohl(lsupd
->lsa_number
) /* 32 bits */
1520 case OSPF6_MESSAGE_TYPE_LSACK
:
1521 /* RFC5340 A.3.6, packet header + N>=0 header-only LSAs. */
1522 test
= ospf6_lsaseq_examin(
1523 (struct ospf6_lsa_header
*)((caddr_t
)oh
1525 + OSPF6_LS_ACK_MIN_SIZE
),
1526 bytesonwire
- OSPF6_HEADER_SIZE
- OSPF6_LS_ACK_MIN_SIZE
,
1530 zlog_warn("%s: invalid (%u) message type", __func__
, oh
->type
);
1534 zlog_warn("%s: anomaly in %s packet", __func__
,
1535 ospf6_message_type(oh
->type
));
1539 /* Verify particular fields of otherwise correct received OSPF packet to
1540 meet the requirements of RFC. */
1541 static int ospf6_rxpacket_examin(struct ospf6_interface
*oi
,
1542 struct ospf6_header
*oh
,
1543 const unsigned bytesonwire
)
1545 struct ospf6_neighbor
*on
;
1547 if (MSG_OK
!= ospf6_packet_examin(oh
, bytesonwire
))
1550 on
= ospf6_neighbor_lookup(oh
->router_id
, oi
);
1553 if (oh
->area_id
!= oi
->area
->area_id
) {
1554 if (oh
->area_id
== OSPF_AREA_BACKBONE
)
1556 "VRF %s: I/F %s (%s, Router-ID: %pI4) Message may be via Virtual Link: not supported",
1557 oi
->interface
->vrf
->name
, oi
->interface
->name
,
1558 on
? on
->name
: "null", &oh
->router_id
);
1561 "VRF %s: I/F %s (%s, Router-ID: %pI4) Area-ID mismatch (my %pI4, rcvd %pI4)",
1562 oi
->interface
->vrf
->name
, oi
->interface
->name
,
1563 on
? on
->name
: "null", &oh
->router_id
,
1564 &oi
->area
->area_id
, &oh
->area_id
);
1568 /* Instance-ID check */
1569 if (oh
->instance_id
!= oi
->instance_id
) {
1571 "VRF %s: I/F %s (%s, Router-ID: %pI4) Instance-ID mismatch (my %u, rcvd %u)",
1572 oi
->interface
->vrf
->name
, oi
->interface
->name
,
1573 on
? on
->name
: "null", &oh
->router_id
, oi
->instance_id
,
1578 /* Router-ID check */
1579 if (oh
->router_id
== oi
->area
->ospf6
->router_id
) {
1580 zlog_warn("VRF %s: I/F %s Duplicate Router-ID (%pI4)",
1581 oi
->interface
->vrf
->name
, oi
->interface
->name
,
1588 static void ospf6_lsupdate_recv(struct in6_addr
*src
, struct in6_addr
*dst
,
1589 struct ospf6_interface
*oi
,
1590 struct ospf6_header
*oh
)
1592 struct ospf6_neighbor
*on
;
1593 struct ospf6_lsupdate
*lsupdate
;
1596 on
= ospf6_neighbor_lookup(oh
->router_id
, oi
);
1598 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV_HDR
))
1599 zlog_debug("Neighbor not found, ignore");
1603 if (on
->state
!= OSPF6_NEIGHBOR_EXCHANGE
1604 && on
->state
!= OSPF6_NEIGHBOR_LOADING
1605 && on
->state
!= OSPF6_NEIGHBOR_FULL
) {
1606 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV_HDR
))
1607 zlog_debug("Neighbor state less than Exchange, ignore");
1611 lsupdate
= (struct ospf6_lsupdate
*)((caddr_t
)oh
1612 + sizeof(struct ospf6_header
));
1617 for (p
= (char *)((caddr_t
)lsupdate
+ sizeof(struct ospf6_lsupdate
));
1618 p
< OSPF6_MESSAGE_END(oh
)
1619 && p
+ OSPF6_LSA_SIZE(p
) <= OSPF6_MESSAGE_END(oh
);
1620 p
+= OSPF6_LSA_SIZE(p
)) {
1621 ospf6_receive_lsa(on
, (struct ospf6_lsa_header
*)p
);
1624 assert(p
== OSPF6_MESSAGE_END(oh
));
1627 static void ospf6_lsack_recv(struct in6_addr
*src
, struct in6_addr
*dst
,
1628 struct ospf6_interface
*oi
,
1629 struct ospf6_header
*oh
)
1631 struct ospf6_neighbor
*on
;
1633 struct ospf6_lsa
*his
, *mine
;
1634 struct ospf6_lsdb
*lsdb
= NULL
;
1636 assert(oh
->type
== OSPF6_MESSAGE_TYPE_LSACK
);
1638 on
= ospf6_neighbor_lookup(oh
->router_id
, oi
);
1640 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV_HDR
))
1641 zlog_debug("Neighbor not found, ignore");
1645 if (on
->state
!= OSPF6_NEIGHBOR_EXCHANGE
1646 && on
->state
!= OSPF6_NEIGHBOR_LOADING
1647 && on
->state
!= OSPF6_NEIGHBOR_FULL
) {
1648 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV_HDR
))
1649 zlog_debug("Neighbor state less than Exchange, ignore");
1655 for (p
= (char *)((caddr_t
)oh
+ sizeof(struct ospf6_header
));
1656 p
+ sizeof(struct ospf6_lsa_header
) <= OSPF6_MESSAGE_END(oh
);
1657 p
+= sizeof(struct ospf6_lsa_header
)) {
1658 his
= ospf6_lsa_create_headeronly((struct ospf6_lsa_header
*)p
);
1660 switch (OSPF6_LSA_SCOPE(his
->header
->type
)) {
1661 case OSPF6_SCOPE_LINKLOCAL
:
1662 lsdb
= on
->ospf6_if
->lsdb
;
1664 case OSPF6_SCOPE_AREA
:
1665 lsdb
= on
->ospf6_if
->area
->lsdb
;
1667 case OSPF6_SCOPE_AS
:
1668 lsdb
= on
->ospf6_if
->area
->ospf6
->lsdb
;
1670 case OSPF6_SCOPE_RESERVED
:
1671 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
1672 zlog_debug("Ignoring LSA of reserved scope");
1673 ospf6_lsa_delete(his
);
1677 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
1678 zlog_debug("%s acknowledged by %s", his
->name
,
1681 /* Find database copy */
1682 mine
= ospf6_lsdb_lookup(his
->header
->type
, his
->header
->id
,
1683 his
->header
->adv_router
, lsdb
);
1685 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
1686 zlog_debug("No database copy");
1687 ospf6_lsa_delete(his
);
1691 /* Check if the LSA is on his retrans-list */
1692 mine
= ospf6_lsdb_lookup(his
->header
->type
, his
->header
->id
,
1693 his
->header
->adv_router
,
1696 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
1697 zlog_debug("Not on %s's retrans-list",
1699 ospf6_lsa_delete(his
);
1703 if (ospf6_lsa_compare(his
, mine
) != 0) {
1704 /* Log this questionable acknowledgement,
1705 and examine the next one. */
1706 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
1707 zlog_debug("Questionable acknowledgement");
1708 ospf6_lsa_delete(his
);
1712 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
1714 "Acknowledged, remove from %s's retrans-list",
1717 ospf6_decrement_retrans_count(mine
);
1718 if (OSPF6_LSA_IS_MAXAGE(mine
))
1719 ospf6_maxage_remove(on
->ospf6_if
->area
->ospf6
);
1720 ospf6_lsdb_remove(mine
, on
->retrans_list
);
1721 ospf6_lsa_delete(his
);
1724 assert(p
== OSPF6_MESSAGE_END(oh
));
1727 static uint8_t *recvbuf
= NULL
;
1728 static uint8_t *sendbuf
= NULL
;
1729 static unsigned int iobuflen
= 0;
1731 int ospf6_iobuf_size(unsigned int size
)
1733 /* NB: there was previously code here that tried to dynamically size
1734 * the buffer for whatever we see in MTU on interfaces. Which is
1735 * _unconditionally wrong_ - we can always receive fragmented IPv6
1736 * up to the regular 64k length limit. (No jumbograms, thankfully.)
1740 /* the + 128 is to have some runway at the end */
1741 size_t alloc_size
= 65536 + 128;
1743 assert(!recvbuf
&& !sendbuf
);
1745 recvbuf
= XMALLOC(MTYPE_OSPF6_MESSAGE
, alloc_size
);
1746 sendbuf
= XMALLOC(MTYPE_OSPF6_MESSAGE
, alloc_size
);
1747 iobuflen
= alloc_size
;
1753 void ospf6_message_terminate(void)
1755 XFREE(MTYPE_OSPF6_MESSAGE
, recvbuf
);
1756 XFREE(MTYPE_OSPF6_MESSAGE
, sendbuf
);
1761 enum ospf6_read_return_enum
{
1763 OSPF6_READ_CONTINUE
,
1766 static int ospf6_read_helper(int sockfd
, struct ospf6
*ospf6
)
1769 struct in6_addr src
, dst
;
1771 struct iovec iovector
[2];
1772 struct ospf6_interface
*oi
;
1773 struct ospf6_header
*oh
;
1774 enum ospf6_auth_err ret
= OSPF6_AUTH_PROCESS_NORMAL
;
1775 uint32_t at_len
= 0;
1776 uint32_t lls_len
= 0;
1779 memset(&src
, 0, sizeof(src
));
1780 memset(&dst
, 0, sizeof(dst
));
1782 iovector
[0].iov_base
= recvbuf
;
1783 iovector
[0].iov_len
= iobuflen
;
1784 iovector
[1].iov_base
= NULL
;
1785 iovector
[1].iov_len
= 0;
1787 /* receive message */
1788 len
= ospf6_recvmsg(&src
, &dst
, &ifindex
, iovector
, sockfd
);
1790 return OSPF6_READ_ERROR
;
1792 if ((uint
)len
> iobuflen
) {
1793 flog_err(EC_LIB_DEVELOPMENT
, "Excess message read");
1794 return OSPF6_READ_ERROR
;
1797 /* ensure some zeroes past the end, just as a security precaution */
1798 memset(recvbuf
+ len
, 0, MIN(128, iobuflen
- len
));
1800 oi
= ospf6_interface_lookup_by_ifindex(ifindex
, ospf6
->vrf_id
);
1801 if (oi
== NULL
|| oi
->area
== NULL
1802 || CHECK_FLAG(oi
->flag
, OSPF6_INTERFACE_DISABLE
)) {
1803 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN
,
1805 zlog_debug("Message received on disabled interface");
1806 return OSPF6_READ_CONTINUE
;
1808 if (CHECK_FLAG(oi
->flag
, OSPF6_INTERFACE_PASSIVE
)) {
1809 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN
,
1811 zlog_debug("%s: Ignore message on passive interface %s",
1812 __func__
, oi
->interface
->name
);
1813 return OSPF6_READ_CONTINUE
;
1817 * Drop packet destined to another VRF.
1818 * This happens when raw_l3mdev_accept is set to 1.
1820 if (ospf6
->vrf_id
!= oi
->interface
->vrf
->vrf_id
)
1821 return OSPF6_READ_CONTINUE
;
1823 oh
= (struct ospf6_header
*)recvbuf
;
1824 ret
= ospf6_auth_validate_pkt(oi
, (uint32_t *)&len
, oh
, &at_len
,
1826 if (ret
== OSPF6_AUTH_VALIDATE_SUCCESS
) {
1827 ret
= ospf6_auth_check_digest(oh
, oi
, &src
, lls_len
);
1828 if (ret
== OSPF6_AUTH_VALIDATE_FAILURE
) {
1829 if (IS_OSPF6_DEBUG_AUTH_RX
)
1831 "RECV[%s]: OSPF packet auth digest miss-match on %s",
1832 oi
->interface
->name
,
1833 ospf6_message_type(oh
->type
));
1834 oi
->at_data
.rx_drop
++;
1835 return OSPF6_READ_CONTINUE
;
1837 } else if (ret
== OSPF6_AUTH_VALIDATE_FAILURE
) {
1838 oi
->at_data
.rx_drop
++;
1839 return OSPF6_READ_CONTINUE
;
1842 if (ospf6_rxpacket_examin(oi
, oh
, len
) != MSG_OK
)
1843 return OSPF6_READ_CONTINUE
;
1845 /* Being here means, that no sizing/alignment issues were detected in
1846 the input packet. This renders the additional checks performed below
1847 and also in the type-specific dispatching functions a dead code,
1848 which can be dismissed in a cleanup-focused review round later. */
1851 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV_HDR
)) {
1852 zlog_debug("%s received on %s", ospf6_message_type(oh
->type
),
1853 oi
->interface
->name
);
1854 zlog_debug(" src: %pI6", &src
);
1855 zlog_debug(" dst: %pI6", &dst
);
1858 case OSPF6_MESSAGE_TYPE_HELLO
:
1859 ospf6_hello_print(oh
, OSPF6_ACTION_RECV
);
1861 case OSPF6_MESSAGE_TYPE_DBDESC
:
1862 ospf6_dbdesc_print(oh
, OSPF6_ACTION_RECV
);
1864 case OSPF6_MESSAGE_TYPE_LSREQ
:
1865 ospf6_lsreq_print(oh
, OSPF6_ACTION_RECV
);
1867 case OSPF6_MESSAGE_TYPE_LSUPDATE
:
1868 ospf6_lsupdate_print(oh
, OSPF6_ACTION_RECV
);
1870 case OSPF6_MESSAGE_TYPE_LSACK
:
1871 ospf6_lsack_print(oh
, OSPF6_ACTION_RECV
);
1877 if ((at_len
!= 0) && IS_OSPF6_DEBUG_AUTH_RX
)
1878 ospf6_auth_hdr_dump_recv(oh
, (len
+ at_len
+ lls_len
),
1883 case OSPF6_MESSAGE_TYPE_HELLO
:
1884 ospf6_hello_recv(&src
, &dst
, oi
, oh
);
1887 case OSPF6_MESSAGE_TYPE_DBDESC
:
1888 ospf6_dbdesc_recv(&src
, &dst
, oi
, oh
);
1891 case OSPF6_MESSAGE_TYPE_LSREQ
:
1892 ospf6_lsreq_recv(&src
, &dst
, oi
, oh
);
1895 case OSPF6_MESSAGE_TYPE_LSUPDATE
:
1896 ospf6_lsupdate_recv(&src
, &dst
, oi
, oh
);
1899 case OSPF6_MESSAGE_TYPE_LSACK
:
1900 ospf6_lsack_recv(&src
, &dst
, oi
, oh
);
1907 return OSPF6_READ_CONTINUE
;
1910 void ospf6_receive(struct event
*thread
)
1913 struct ospf6
*ospf6
;
1916 /* add next read thread */
1917 ospf6
= EVENT_ARG(thread
);
1918 sockfd
= EVENT_FD(thread
);
1920 event_add_read(master
, ospf6_receive
, ospf6
, ospf6
->fd
,
1921 &ospf6
->t_ospf6_receive
);
1923 while (count
< ospf6
->write_oi_count
) {
1925 switch (ospf6_read_helper(sockfd
, ospf6
)) {
1926 case OSPF6_READ_ERROR
:
1928 case OSPF6_READ_CONTINUE
:
1934 static void ospf6_fill_hdr_checksum(struct ospf6_interface
*oi
,
1935 struct ospf6_packet
*op
)
1937 struct ipv6_ph ph
= {};
1938 struct ospf6_header
*oh
;
1939 void *offset
= NULL
;
1941 if (oi
->at_data
.flags
!= 0)
1944 memcpy(&ph
.src
, oi
->linklocal_addr
, sizeof(struct in6_addr
));
1945 memcpy(&ph
.dst
, &op
->dst
, sizeof(struct in6_addr
));
1946 ph
.ulpl
= htonl(op
->length
);
1947 ph
.next_hdr
= IPPROTO_OSPFIGP
;
1949 /* Suppress static analysis warnings about accessing icmp6 oob */
1950 oh
= (struct ospf6_header
*)STREAM_DATA(op
->s
);
1952 oh
->checksum
= in_cksum_with_ph6(&ph
, offset
, op
->length
);
1955 static void ospf6_make_header(uint8_t type
, struct ospf6_interface
*oi
,
1958 struct ospf6_header
*oh
;
1960 oh
= (struct ospf6_header
*)STREAM_DATA(s
);
1962 oh
->version
= (uint8_t)OSPFV3_VERSION
;
1966 oh
->router_id
= oi
->area
->ospf6
->router_id
;
1967 oh
->area_id
= oi
->area
->area_id
;
1969 oh
->instance_id
= oi
->instance_id
;
1972 stream_forward_endp(s
, OSPF6_HEADER_SIZE
);
1975 static void ospf6_fill_header(struct ospf6_interface
*oi
, struct stream
*s
,
1978 struct ospf6_header
*oh
;
1980 oh
= (struct ospf6_header
*)STREAM_DATA(s
);
1982 oh
->length
= htons(length
);
1985 static void ospf6_fill_lsupdate_header(struct stream
*s
, uint32_t lsa_num
)
1987 struct ospf6_header
*oh
;
1988 struct ospf6_lsupdate
*lsu
;
1990 oh
= (struct ospf6_header
*)STREAM_DATA(s
);
1992 lsu
= (struct ospf6_lsupdate
*)((caddr_t
)oh
1993 + sizeof(struct ospf6_header
));
1994 lsu
->lsa_number
= htonl(lsa_num
);
1997 static void ospf6_auth_trailer_copy_keychain_key(struct ospf6_interface
*oi
)
1999 char *keychain_name
= NULL
;
2000 struct keychain
*keychain
= NULL
;
2001 struct key
*key
= NULL
;
2003 keychain_name
= oi
->at_data
.keychain
;
2004 keychain
= keychain_lookup(keychain_name
);
2006 key
= key_lookup_for_send(keychain
);
2007 if (key
&& key
->string
&&
2008 key
->hash_algo
!= KEYCHAIN_ALGO_NULL
) {
2009 /* storing the values so that further
2010 * lookup can be avoided. after
2011 * processing the digest need to reset
2014 oi
->at_data
.hash_algo
= key
->hash_algo
;
2015 if (oi
->at_data
.auth_key
)
2016 XFREE(MTYPE_OSPF6_AUTH_MANUAL_KEY
,
2017 oi
->at_data
.auth_key
);
2018 oi
->at_data
.auth_key
= XSTRDUP(
2019 MTYPE_OSPF6_AUTH_MANUAL_KEY
, key
->string
);
2020 oi
->at_data
.key_id
= key
->index
;
2021 SET_FLAG(oi
->at_data
.flags
,
2022 OSPF6_AUTH_TRAILER_KEYCHAIN_VALID
);
2027 static uint16_t ospf6_packet_max(struct ospf6_interface
*oi
)
2029 uint16_t at_len
= 0;
2031 assert(oi
->ifmtu
> sizeof(struct ip6_hdr
));
2033 if (oi
->at_data
.flags
!= 0) {
2034 if (CHECK_FLAG(oi
->at_data
.flags
, OSPF6_AUTH_TRAILER_KEYCHAIN
))
2035 ospf6_auth_trailer_copy_keychain_key(oi
);
2037 at_len
+= OSPF6_AUTH_HDR_MIN_SIZE
;
2038 at_len
+= keychain_get_hash_len(oi
->at_data
.hash_algo
);
2039 return oi
->ifmtu
- (sizeof(struct ip6_hdr
)) - at_len
;
2042 return oi
->ifmtu
- (sizeof(struct ip6_hdr
));
2045 static uint16_t ospf6_make_hello(struct ospf6_interface
*oi
, struct stream
*s
)
2047 struct listnode
*node
, *nnode
;
2048 struct ospf6_neighbor
*on
;
2049 uint16_t length
= OSPF6_HELLO_MIN_SIZE
;
2050 uint8_t options1
= oi
->area
->options
[1];
2052 if (oi
->at_data
.flags
!= 0)
2053 options1
|= OSPF6_OPT_AT
;
2055 stream_putl(s
, oi
->interface
->ifindex
);
2056 stream_putc(s
, oi
->priority
);
2057 stream_putc(s
, oi
->area
->options
[0]);
2058 stream_putc(s
, options1
);
2059 stream_putc(s
, oi
->area
->options
[2]);
2060 stream_putw(s
, oi
->hello_interval
);
2061 stream_putw(s
, oi
->dead_interval
);
2062 stream_put_ipv4(s
, oi
->drouter
);
2063 stream_put_ipv4(s
, oi
->bdrouter
);
2065 for (ALL_LIST_ELEMENTS(oi
->neighbor_list
, node
, nnode
, on
)) {
2066 if (on
->state
< OSPF6_NEIGHBOR_INIT
)
2069 if ((length
+ sizeof(uint32_t) + OSPF6_HEADER_SIZE
)
2070 > ospf6_packet_max(oi
)) {
2071 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_HELLO
,
2074 "sending Hello message: exceeds I/F MTU");
2078 stream_put_ipv4(s
, on
->router_id
);
2079 length
+= sizeof(uint32_t);
2085 static void ospf6_write(struct event
*thread
)
2087 struct ospf6
*ospf6
= EVENT_ARG(thread
);
2088 struct ospf6_interface
*oi
;
2089 struct ospf6_header
*oh
;
2090 struct ospf6_packet
*op
;
2091 struct listnode
*node
;
2092 struct iovec iovector
[2];
2095 int64_t latency
= 0;
2096 struct timeval timestamp
;
2097 uint16_t at_len
= 0;
2099 if (ospf6
->fd
< 0) {
2100 zlog_warn("ospf6_write failed to send, fd %d", ospf6
->fd
);
2104 node
= listhead(ospf6
->oi_write_q
);
2106 oi
= listgetdata(node
);
2108 while ((pkt_count
< ospf6
->write_oi_count
) && oi
) {
2109 op
= ospf6_fifo_head(oi
->obuf
);
2111 assert(op
->length
>= OSPF6_HEADER_SIZE
);
2113 iovector
[0].iov_base
= (caddr_t
)stream_pnt(op
->s
);
2114 iovector
[0].iov_len
= op
->length
;
2115 iovector
[1].iov_base
= NULL
;
2116 iovector
[1].iov_len
= 0;
2118 oh
= (struct ospf6_header
*)STREAM_DATA(op
->s
);
2120 if (oi
->at_data
.flags
!= 0) {
2121 at_len
= ospf6_auth_len_get(oi
);
2123 iovector
[0].iov_len
=
2124 ntohs(oh
->length
) + at_len
;
2125 ospf6_auth_digest_send(oi
->linklocal_addr
, oi
,
2127 iovector
[0].iov_len
);
2129 iovector
[0].iov_len
= ntohs(oh
->length
);
2132 iovector
[0].iov_len
= ntohs(oh
->length
);
2135 len
= ospf6_sendmsg(oi
->linklocal_addr
, &op
->dst
,
2136 oi
->interface
->ifindex
, iovector
,
2139 if (len
!= (op
->length
+ (int)at_len
))
2140 flog_err(EC_LIB_DEVELOPMENT
,
2141 "Could not send entire message");
2143 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, SEND_HDR
)) {
2144 zlog_debug("%s send on %s",
2145 ospf6_message_type(oh
->type
),
2146 oi
->interface
->name
);
2147 zlog_debug(" src: %pI6", oi
->linklocal_addr
);
2148 zlog_debug(" dst: %pI6", &op
->dst
);
2150 case OSPF6_MESSAGE_TYPE_HELLO
:
2151 ospf6_hello_print(oh
, OSPF6_ACTION_SEND
);
2153 case OSPF6_MESSAGE_TYPE_DBDESC
:
2154 ospf6_dbdesc_print(oh
, OSPF6_ACTION_SEND
);
2156 case OSPF6_MESSAGE_TYPE_LSREQ
:
2157 ospf6_lsreq_print(oh
, OSPF6_ACTION_SEND
);
2159 case OSPF6_MESSAGE_TYPE_LSUPDATE
:
2160 ospf6_lsupdate_print(oh
, OSPF6_ACTION_SEND
);
2162 case OSPF6_MESSAGE_TYPE_LSACK
:
2163 ospf6_lsack_print(oh
, OSPF6_ACTION_SEND
);
2166 zlog_debug("Unknown message");
2172 case OSPF6_MESSAGE_TYPE_HELLO
:
2173 monotime(×tamp
);
2175 latency
= monotime_since(&oi
->last_hello
, NULL
)
2176 - ((int64_t)oi
->hello_interval
2179 /* log if latency exceeds the hello period */
2180 if (latency
> ((int64_t)oi
->hello_interval
* 1000000))
2181 zlog_warn("%s hello TX high latency %" PRId64
2184 oi
->last_hello
= timestamp
;
2187 case OSPF6_MESSAGE_TYPE_DBDESC
:
2190 case OSPF6_MESSAGE_TYPE_LSREQ
:
2193 case OSPF6_MESSAGE_TYPE_LSUPDATE
:
2196 case OSPF6_MESSAGE_TYPE_LSACK
:
2200 zlog_debug("Unknown message");
2205 if ((oi
->at_data
.flags
!= 0) &&
2206 (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, SEND_HDR
)) &&
2207 (IS_OSPF6_DEBUG_AUTH_TX
))
2208 ospf6_auth_hdr_dump_send(oh
, iovector
[0].iov_len
);
2210 /* initialize at_len to 0 for next packet */
2213 /* Now delete packet from queue. */
2214 ospf6_packet_delete(oi
);
2216 /* Move this interface to the tail of write_q to
2217 serve everyone in a round robin fashion */
2218 list_delete_node(ospf6
->oi_write_q
, node
);
2219 if (ospf6_fifo_head(oi
->obuf
) == NULL
) {
2223 listnode_add(ospf6
->oi_write_q
, oi
);
2226 /* Setup to service from the head of the queue again */
2227 if (!list_isempty(ospf6
->oi_write_q
)) {
2228 node
= listhead(ospf6
->oi_write_q
);
2229 oi
= listgetdata(node
);
2233 /* If packets still remain in queue, call write thread. */
2234 if (!list_isempty(ospf6
->oi_write_q
))
2235 event_add_write(master
, ospf6_write
, ospf6
, ospf6
->fd
,
2239 void ospf6_hello_send(struct event
*thread
)
2241 struct ospf6_interface
*oi
;
2242 struct ospf6_packet
*op
;
2243 uint16_t length
= OSPF6_HEADER_SIZE
;
2245 oi
= (struct ospf6_interface
*)EVENT_ARG(thread
);
2247 if (oi
->state
<= OSPF6_INTERFACE_DOWN
) {
2248 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_HELLO
, SEND_HDR
))
2249 zlog_debug("Unable to send Hello on down interface %s",
2250 oi
->interface
->name
);
2254 op
= ospf6_packet_new(oi
->ifmtu
);
2256 ospf6_make_header(OSPF6_MESSAGE_TYPE_HELLO
, oi
, op
->s
);
2258 /* Prepare OSPF Hello body */
2259 length
+= ospf6_make_hello(oi
, op
->s
);
2260 if (length
== OSPF6_HEADER_SIZE
) {
2261 /* Hello overshooting MTU */
2262 ospf6_packet_free(op
);
2266 /* Fill OSPF header. */
2267 ospf6_fill_header(oi
, op
->s
, length
);
2269 /* Set packet length. */
2270 op
->length
= length
;
2272 op
->dst
= allspfrouters6
;
2274 ospf6_fill_hdr_checksum(oi
, op
);
2276 /* Add packet to the top of the interface output queue, so that they
2277 * can't get delayed by things like long queues of LS Update packets
2279 ospf6_packet_add_top(oi
, op
);
2281 /* set next thread */
2282 event_add_timer(master
, ospf6_hello_send
, oi
, oi
->hello_interval
,
2283 &oi
->thread_send_hello
);
2285 OSPF6_MESSAGE_WRITE_ON(oi
);
2288 static uint16_t ospf6_make_dbdesc(struct ospf6_neighbor
*on
, struct stream
*s
)
2290 uint16_t length
= OSPF6_DB_DESC_MIN_SIZE
;
2291 struct ospf6_lsa
*lsa
, *lsanext
;
2292 uint8_t options1
= on
->ospf6_if
->area
->options
[1];
2294 if (on
->ospf6_if
->at_data
.flags
!= 0)
2295 options1
|= OSPF6_OPT_AT
;
2297 /* if this is initial one, initialize sequence number for DbDesc */
2298 if (CHECK_FLAG(on
->dbdesc_bits
, OSPF6_DBDESC_IBIT
)
2299 && (on
->dbdesc_seqnum
== 0)) {
2300 on
->dbdesc_seqnum
= frr_sequence32_next();
2304 stream_putc(s
, 0); /* reserved 1 */
2305 stream_putc(s
, on
->ospf6_if
->area
->options
[0]);
2306 stream_putc(s
, options1
);
2307 stream_putc(s
, on
->ospf6_if
->area
->options
[2]);
2308 stream_putw(s
, on
->ospf6_if
->ifmtu
);
2309 stream_putc(s
, 0); /* reserved 2 */
2310 stream_putc(s
, on
->dbdesc_bits
);
2311 stream_putl(s
, on
->dbdesc_seqnum
);
2313 /* if this is not initial one, set LSA headers in dbdesc */
2314 if (!CHECK_FLAG(on
->dbdesc_bits
, OSPF6_DBDESC_IBIT
)) {
2315 for (ALL_LSDB(on
->dbdesc_list
, lsa
, lsanext
)) {
2316 ospf6_lsa_age_update_to_send(lsa
,
2317 on
->ospf6_if
->transdelay
);
2320 if ((length
+ sizeof(struct ospf6_lsa_header
)
2321 + OSPF6_HEADER_SIZE
)
2322 > ospf6_packet_max(on
->ospf6_if
)) {
2323 ospf6_lsa_unlock(lsa
);
2325 ospf6_lsa_unlock(lsanext
);
2328 stream_put(s
, lsa
->header
,
2329 sizeof(struct ospf6_lsa_header
));
2330 length
+= sizeof(struct ospf6_lsa_header
);
2336 void ospf6_dbdesc_send(struct event
*thread
)
2338 struct ospf6_neighbor
*on
;
2339 uint16_t length
= OSPF6_HEADER_SIZE
;
2340 struct ospf6_packet
*op
;
2342 on
= (struct ospf6_neighbor
*)EVENT_ARG(thread
);
2344 if (on
->state
< OSPF6_NEIGHBOR_EXSTART
) {
2345 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_DBDESC
, SEND
))
2347 "Quit to send DbDesc to neighbor %s state %s",
2348 on
->name
, ospf6_neighbor_state_str
[on
->state
]);
2352 /* set next thread if master */
2353 if (CHECK_FLAG(on
->dbdesc_bits
, OSPF6_DBDESC_MSBIT
))
2354 event_add_timer(master
, ospf6_dbdesc_send
, on
,
2355 on
->ospf6_if
->rxmt_interval
,
2356 &on
->thread_send_dbdesc
);
2358 op
= ospf6_packet_new(on
->ospf6_if
->ifmtu
);
2359 ospf6_make_header(OSPF6_MESSAGE_TYPE_DBDESC
, on
->ospf6_if
, op
->s
);
2361 length
+= ospf6_make_dbdesc(on
, op
->s
);
2362 ospf6_fill_header(on
->ospf6_if
, op
->s
, length
);
2364 /* Set packet length. */
2365 op
->length
= length
;
2367 if (on
->ospf6_if
->state
== OSPF6_INTERFACE_POINTTOPOINT
)
2368 op
->dst
= allspfrouters6
;
2370 op
->dst
= on
->linklocal_addr
;
2372 ospf6_fill_hdr_checksum(on
->ospf6_if
, op
);
2374 ospf6_packet_add(on
->ospf6_if
, op
);
2376 OSPF6_MESSAGE_WRITE_ON(on
->ospf6_if
);
2379 void ospf6_dbdesc_send_newone(struct event
*thread
)
2381 struct ospf6_neighbor
*on
;
2382 struct ospf6_lsa
*lsa
, *lsanext
;
2383 unsigned int size
= 0;
2385 on
= (struct ospf6_neighbor
*)EVENT_ARG(thread
);
2386 ospf6_lsdb_remove_all(on
->dbdesc_list
);
2388 /* move LSAs from summary_list to dbdesc_list (within neighbor
2390 so that ospf6_send_dbdesc () can send those LSAs */
2391 size
= sizeof(struct ospf6_lsa_header
) + sizeof(struct ospf6_dbdesc
);
2392 for (ALL_LSDB(on
->summary_list
, lsa
, lsanext
)) {
2393 /* if stub area then don't advertise AS-External LSAs */
2394 if ((IS_AREA_STUB(on
->ospf6_if
->area
)
2395 || IS_AREA_NSSA(on
->ospf6_if
->area
))
2396 && ntohs(lsa
->header
->type
) == OSPF6_LSTYPE_AS_EXTERNAL
) {
2397 ospf6_lsdb_remove(lsa
, on
->summary_list
);
2401 if (size
+ sizeof(struct ospf6_lsa_header
)
2402 > ospf6_packet_max(on
->ospf6_if
)) {
2403 ospf6_lsa_unlock(lsa
);
2405 ospf6_lsa_unlock(lsanext
);
2409 ospf6_lsdb_add(ospf6_lsa_copy(lsa
), on
->dbdesc_list
);
2410 ospf6_lsdb_remove(lsa
, on
->summary_list
);
2411 size
+= sizeof(struct ospf6_lsa_header
);
2414 if (on
->summary_list
->count
== 0)
2415 UNSET_FLAG(on
->dbdesc_bits
, OSPF6_DBDESC_MBIT
);
2417 /* If slave, More bit check must be done here */
2418 if (!CHECK_FLAG(on
->dbdesc_bits
, OSPF6_DBDESC_MSBIT
) && /* Slave */
2419 !CHECK_FLAG(on
->dbdesc_last
.bits
, OSPF6_DBDESC_MBIT
)
2420 && !CHECK_FLAG(on
->dbdesc_bits
, OSPF6_DBDESC_MBIT
))
2421 event_add_event(master
, exchange_done
, on
, 0,
2422 &on
->thread_exchange_done
);
2424 event_execute(master
, ospf6_dbdesc_send
, on
, 0);
2427 static uint16_t ospf6_make_lsreq(struct ospf6_neighbor
*on
, struct stream
*s
)
2429 uint16_t length
= 0;
2430 struct ospf6_lsa
*lsa
, *lsanext
, *last_req
= NULL
;
2432 for (ALL_LSDB(on
->request_list
, lsa
, lsanext
)) {
2433 if ((length
+ OSPF6_HEADER_SIZE
)
2434 > ospf6_packet_max(on
->ospf6_if
)) {
2435 ospf6_lsa_unlock(lsa
);
2437 ospf6_lsa_unlock(lsanext
);
2440 stream_putw(s
, 0); /* reserved */
2441 stream_putw(s
, ntohs(lsa
->header
->type
));
2442 stream_putl(s
, ntohl(lsa
->header
->id
));
2443 stream_putl(s
, ntohl(lsa
->header
->adv_router
));
2444 length
+= sizeof(struct ospf6_lsreq_entry
);
2448 if (last_req
!= NULL
) {
2449 if (on
->last_ls_req
!= NULL
)
2450 on
->last_ls_req
= ospf6_lsa_unlock(on
->last_ls_req
);
2452 ospf6_lsa_lock(last_req
);
2453 on
->last_ls_req
= last_req
;
2459 static uint16_t ospf6_make_lsack_neighbor(struct ospf6_neighbor
*on
,
2460 struct ospf6_packet
**op
)
2462 uint16_t length
= 0;
2463 struct ospf6_lsa
*lsa
, *lsanext
;
2466 for (ALL_LSDB(on
->lsack_list
, lsa
, lsanext
)) {
2467 if ((length
+ sizeof(struct ospf6_lsa_header
)
2468 + OSPF6_HEADER_SIZE
)
2469 > ospf6_packet_max(on
->ospf6_if
)) {
2470 /* if we run out of packet size/space here,
2471 better to try again soon. */
2473 ospf6_fill_header(on
->ospf6_if
, (*op
)->s
,
2474 length
+ OSPF6_HEADER_SIZE
);
2476 (*op
)->length
= length
+ OSPF6_HEADER_SIZE
;
2477 (*op
)->dst
= on
->linklocal_addr
;
2478 ospf6_fill_hdr_checksum(on
->ospf6_if
, *op
);
2479 ospf6_packet_add(on
->ospf6_if
, *op
);
2480 OSPF6_MESSAGE_WRITE_ON(on
->ospf6_if
);
2482 *op
= ospf6_packet_new(on
->ospf6_if
->ifmtu
);
2483 ospf6_make_header(OSPF6_MESSAGE_TYPE_LSACK
,
2484 on
->ospf6_if
, (*op
)->s
);
2489 ospf6_lsa_age_update_to_send(lsa
, on
->ospf6_if
->transdelay
);
2490 stream_put((*op
)->s
, lsa
->header
,
2491 sizeof(struct ospf6_lsa_header
));
2492 length
+= sizeof(struct ospf6_lsa_header
);
2494 assert(lsa
->lock
== 2);
2495 ospf6_lsdb_remove(lsa
, on
->lsack_list
);
2501 void ospf6_lsreq_send(struct event
*thread
)
2503 struct ospf6_neighbor
*on
;
2504 struct ospf6_packet
*op
;
2505 uint16_t length
= OSPF6_HEADER_SIZE
;
2507 on
= (struct ospf6_neighbor
*)EVENT_ARG(thread
);
2509 /* LSReq will be sent only in ExStart or Loading */
2510 if (on
->state
!= OSPF6_NEIGHBOR_EXCHANGE
2511 && on
->state
!= OSPF6_NEIGHBOR_LOADING
) {
2512 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_LSREQ
, SEND_HDR
))
2513 zlog_debug("Quit to send LSReq to neighbor %s state %s",
2515 ospf6_neighbor_state_str
[on
->state
]);
2519 /* schedule loading_done if request list is empty */
2520 if (on
->request_list
->count
== 0) {
2521 event_add_event(master
, loading_done
, on
, 0, NULL
);
2525 op
= ospf6_packet_new(on
->ospf6_if
->ifmtu
);
2526 ospf6_make_header(OSPF6_MESSAGE_TYPE_LSREQ
, on
->ospf6_if
, op
->s
);
2528 length
+= ospf6_make_lsreq(on
, op
->s
);
2530 if (length
== OSPF6_HEADER_SIZE
) {
2531 /* Hello overshooting MTU */
2532 ospf6_packet_free(op
);
2536 /* Fill OSPF header. */
2537 ospf6_fill_header(on
->ospf6_if
, op
->s
, length
);
2539 /* Set packet length */
2540 op
->length
= length
;
2542 if (on
->ospf6_if
->state
== OSPF6_INTERFACE_POINTTOPOINT
)
2543 op
->dst
= allspfrouters6
;
2545 op
->dst
= on
->linklocal_addr
;
2547 ospf6_fill_hdr_checksum(on
->ospf6_if
, op
);
2548 ospf6_packet_add(on
->ospf6_if
, op
);
2550 OSPF6_MESSAGE_WRITE_ON(on
->ospf6_if
);
2552 /* set next thread */
2553 if (on
->request_list
->count
!= 0) {
2554 event_add_timer(master
, ospf6_lsreq_send
, on
,
2555 on
->ospf6_if
->rxmt_interval
,
2556 &on
->thread_send_lsreq
);
2560 static void ospf6_send_lsupdate(struct ospf6_neighbor
*on
,
2561 struct ospf6_interface
*oi
,
2562 struct ospf6_packet
*op
)
2567 if ((on
->ospf6_if
->state
== OSPF6_INTERFACE_POINTTOPOINT
)
2568 || (on
->ospf6_if
->state
== OSPF6_INTERFACE_DR
)
2569 || (on
->ospf6_if
->state
== OSPF6_INTERFACE_BDR
))
2570 op
->dst
= allspfrouters6
;
2572 op
->dst
= on
->linklocal_addr
;
2575 if ((oi
->state
== OSPF6_INTERFACE_POINTTOPOINT
)
2576 || (oi
->state
== OSPF6_INTERFACE_DR
)
2577 || (oi
->state
== OSPF6_INTERFACE_BDR
))
2578 op
->dst
= allspfrouters6
;
2580 op
->dst
= alldrouters6
;
2583 ospf6_fill_hdr_checksum(oi
, op
);
2584 ospf6_packet_add(oi
, op
);
2585 /* If ospf instance is being deleted, send the packet
2588 if ((oi
->area
== NULL
) || (oi
->area
->ospf6
== NULL
))
2590 if (oi
->area
->ospf6
->inst_shutdown
) {
2591 if (oi
->on_write_q
== 0) {
2592 listnode_add(oi
->area
->ospf6
->oi_write_q
, oi
);
2595 event_execute(master
, ospf6_write
, oi
->area
->ospf6
, 0);
2597 OSPF6_MESSAGE_WRITE_ON(oi
);
2601 static uint16_t ospf6_make_lsupdate_list(struct ospf6_neighbor
*on
,
2602 struct ospf6_packet
**op
, int *lsa_cnt
)
2604 uint16_t length
= OSPF6_LS_UPD_MIN_SIZE
;
2605 struct ospf6_lsa
*lsa
, *lsanext
;
2607 /* skip over fixed header */
2608 stream_forward_endp((*op
)->s
, OSPF6_LS_UPD_MIN_SIZE
);
2610 for (ALL_LSDB(on
->lsupdate_list
, lsa
, lsanext
)) {
2611 if ((length
+ OSPF6_LSA_SIZE(lsa
->header
) + OSPF6_HEADER_SIZE
) >
2612 ospf6_packet_max(on
->ospf6_if
)) {
2613 ospf6_fill_header(on
->ospf6_if
, (*op
)->s
,
2614 length
+ OSPF6_HEADER_SIZE
);
2615 (*op
)->length
= length
+ OSPF6_HEADER_SIZE
;
2616 ospf6_fill_lsupdate_header((*op
)->s
, *lsa_cnt
);
2617 ospf6_send_lsupdate(on
, NULL
, *op
);
2619 /* refresh packet */
2620 *op
= ospf6_packet_new(on
->ospf6_if
->ifmtu
);
2621 length
= OSPF6_LS_UPD_MIN_SIZE
;
2623 ospf6_make_header(OSPF6_MESSAGE_TYPE_LSUPDATE
,
2624 on
->ospf6_if
, (*op
)->s
);
2625 stream_forward_endp((*op
)->s
, OSPF6_LS_UPD_MIN_SIZE
);
2627 ospf6_lsa_age_update_to_send(lsa
, on
->ospf6_if
->transdelay
);
2628 stream_put((*op
)->s
, lsa
->header
, OSPF6_LSA_SIZE(lsa
->header
));
2630 length
+= OSPF6_LSA_SIZE(lsa
->header
);
2631 assert(lsa
->lock
== 2);
2632 ospf6_lsdb_remove(lsa
, on
->lsupdate_list
);
2637 static uint16_t ospf6_make_ls_retrans_list(struct ospf6_neighbor
*on
,
2638 struct ospf6_packet
**op
,
2641 uint16_t length
= OSPF6_LS_UPD_MIN_SIZE
;
2642 struct ospf6_lsa
*lsa
, *lsanext
;
2644 /* skip over fixed header */
2645 stream_forward_endp((*op
)->s
, OSPF6_LS_UPD_MIN_SIZE
);
2647 for (ALL_LSDB(on
->retrans_list
, lsa
, lsanext
)) {
2648 if ((length
+ OSPF6_LSA_SIZE(lsa
->header
) + OSPF6_HEADER_SIZE
) >
2649 ospf6_packet_max(on
->ospf6_if
)) {
2650 ospf6_fill_header(on
->ospf6_if
, (*op
)->s
,
2651 length
+ OSPF6_HEADER_SIZE
);
2652 (*op
)->length
= length
+ OSPF6_HEADER_SIZE
;
2653 ospf6_fill_lsupdate_header((*op
)->s
, *lsa_cnt
);
2654 if (on
->ospf6_if
->state
== OSPF6_INTERFACE_POINTTOPOINT
)
2655 (*op
)->dst
= allspfrouters6
;
2657 (*op
)->dst
= on
->linklocal_addr
;
2659 ospf6_fill_hdr_checksum(on
->ospf6_if
, *op
);
2660 ospf6_packet_add(on
->ospf6_if
, *op
);
2661 OSPF6_MESSAGE_WRITE_ON(on
->ospf6_if
);
2663 /* refresh packet */
2664 *op
= ospf6_packet_new(on
->ospf6_if
->ifmtu
);
2665 length
= OSPF6_LS_UPD_MIN_SIZE
;
2667 ospf6_make_header(OSPF6_MESSAGE_TYPE_LSUPDATE
,
2668 on
->ospf6_if
, (*op
)->s
);
2669 stream_forward_endp((*op
)->s
, OSPF6_LS_UPD_MIN_SIZE
);
2671 ospf6_lsa_age_update_to_send(lsa
, on
->ospf6_if
->transdelay
);
2672 stream_put((*op
)->s
, lsa
->header
, OSPF6_LSA_SIZE(lsa
->header
));
2674 length
+= OSPF6_LSA_SIZE(lsa
->header
);
2679 void ospf6_lsupdate_send_neighbor(struct event
*thread
)
2681 struct ospf6_neighbor
*on
;
2682 struct ospf6_packet
*op
;
2683 uint16_t length
= OSPF6_HEADER_SIZE
;
2686 on
= (struct ospf6_neighbor
*)EVENT_ARG(thread
);
2688 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_LSUPDATE
, SEND_HDR
))
2689 zlog_debug("LSUpdate to neighbor %s", on
->name
);
2691 if (on
->state
< OSPF6_NEIGHBOR_EXCHANGE
) {
2692 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_LSUPDATE
,
2694 zlog_debug("Quit to send (neighbor state %s)",
2695 ospf6_neighbor_state_str
[on
->state
]);
2699 /* first do lsupdate_list */
2700 op
= ospf6_packet_new(on
->ospf6_if
->ifmtu
);
2701 ospf6_make_header(OSPF6_MESSAGE_TYPE_LSUPDATE
, on
->ospf6_if
, op
->s
);
2702 length
+= ospf6_make_lsupdate_list(on
, &op
, &lsa_cnt
);
2704 /* Fill OSPF header. */
2705 ospf6_fill_header(on
->ospf6_if
, op
->s
, length
);
2706 ospf6_fill_lsupdate_header(op
->s
, lsa_cnt
);
2707 op
->length
= length
;
2708 ospf6_send_lsupdate(on
, NULL
, op
);
2710 /* prepare new packet */
2711 op
= ospf6_packet_new(on
->ospf6_if
->ifmtu
);
2712 length
= OSPF6_HEADER_SIZE
;
2715 stream_reset(op
->s
);
2716 length
= OSPF6_HEADER_SIZE
;
2719 ospf6_make_header(OSPF6_MESSAGE_TYPE_LSUPDATE
, on
->ospf6_if
, op
->s
);
2720 /* now do retransmit list */
2721 length
+= ospf6_make_ls_retrans_list(on
, &op
, &lsa_cnt
);
2723 ospf6_fill_header(on
->ospf6_if
, op
->s
, length
);
2724 ospf6_fill_lsupdate_header(op
->s
, lsa_cnt
);
2725 op
->length
= length
;
2726 if (on
->ospf6_if
->state
== OSPF6_INTERFACE_POINTTOPOINT
)
2727 op
->dst
= allspfrouters6
;
2729 op
->dst
= on
->linklocal_addr
;
2730 ospf6_fill_hdr_checksum(on
->ospf6_if
, op
);
2731 ospf6_packet_add(on
->ospf6_if
, op
);
2732 OSPF6_MESSAGE_WRITE_ON(on
->ospf6_if
);
2734 ospf6_packet_free(op
);
2736 if (on
->lsupdate_list
->count
!= 0) {
2737 event_add_event(master
, ospf6_lsupdate_send_neighbor
, on
, 0,
2738 &on
->thread_send_lsupdate
);
2739 } else if (on
->retrans_list
->count
!= 0) {
2740 event_add_timer(master
, ospf6_lsupdate_send_neighbor
, on
,
2741 on
->ospf6_if
->rxmt_interval
,
2742 &on
->thread_send_lsupdate
);
2746 int ospf6_lsupdate_send_neighbor_now(struct ospf6_neighbor
*on
,
2747 struct ospf6_lsa
*lsa
)
2749 struct ospf6_packet
*op
;
2750 uint16_t length
= OSPF6_HEADER_SIZE
;
2752 op
= ospf6_packet_new(on
->ospf6_if
->ifmtu
);
2753 ospf6_make_header(OSPF6_MESSAGE_TYPE_LSUPDATE
, on
->ospf6_if
, op
->s
);
2755 /* skip over fixed header */
2756 stream_forward_endp(op
->s
, OSPF6_LS_UPD_MIN_SIZE
);
2757 ospf6_lsa_age_update_to_send(lsa
, on
->ospf6_if
->transdelay
);
2758 stream_put(op
->s
, lsa
->header
, OSPF6_LSA_SIZE(lsa
->header
));
2759 length
= OSPF6_HEADER_SIZE
+ OSPF6_LS_UPD_MIN_SIZE
2760 + OSPF6_LSA_SIZE(lsa
->header
);
2761 ospf6_fill_header(on
->ospf6_if
, op
->s
, length
);
2762 ospf6_fill_lsupdate_header(op
->s
, 1);
2763 op
->length
= length
;
2765 if (IS_OSPF6_DEBUG_FLOODING
2766 || IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_LSUPDATE
, SEND_HDR
))
2767 zlog_debug("%s: Send lsupdate with lsa %s (age %u)", __func__
,
2768 lsa
->name
, ntohs(lsa
->header
->age
));
2770 ospf6_send_lsupdate(on
, NULL
, op
);
2775 static uint16_t ospf6_make_lsupdate_interface(struct ospf6_interface
*oi
,
2776 struct ospf6_packet
**op
,
2779 uint16_t length
= OSPF6_LS_UPD_MIN_SIZE
;
2780 struct ospf6_lsa
*lsa
, *lsanext
;
2782 /* skip over fixed header */
2783 stream_forward_endp((*op
)->s
, OSPF6_LS_UPD_MIN_SIZE
);
2785 for (ALL_LSDB(oi
->lsupdate_list
, lsa
, lsanext
)) {
2786 if (length
+ OSPF6_LSA_SIZE(lsa
->header
) + OSPF6_HEADER_SIZE
>
2787 ospf6_packet_max(oi
)) {
2788 ospf6_fill_header(oi
, (*op
)->s
,
2789 length
+ OSPF6_HEADER_SIZE
);
2790 (*op
)->length
= length
+ OSPF6_HEADER_SIZE
;
2791 ospf6_fill_lsupdate_header((*op
)->s
, *lsa_cnt
);
2792 ospf6_send_lsupdate(NULL
, oi
, *op
);
2794 /* refresh packet */
2795 *op
= ospf6_packet_new(oi
->ifmtu
);
2796 length
= OSPF6_LS_UPD_MIN_SIZE
;
2798 ospf6_make_header(OSPF6_MESSAGE_TYPE_LSUPDATE
, oi
,
2800 stream_forward_endp((*op
)->s
, OSPF6_LS_UPD_MIN_SIZE
);
2803 ospf6_lsa_age_update_to_send(lsa
, oi
->transdelay
);
2804 stream_put((*op
)->s
, lsa
->header
, OSPF6_LSA_SIZE(lsa
->header
));
2806 length
+= OSPF6_LSA_SIZE(lsa
->header
);
2808 assert(lsa
->lock
== 2);
2809 ospf6_lsdb_remove(lsa
, oi
->lsupdate_list
);
2814 void ospf6_lsupdate_send_interface(struct event
*thread
)
2816 struct ospf6_interface
*oi
;
2817 struct ospf6_packet
*op
;
2818 uint16_t length
= OSPF6_HEADER_SIZE
;
2821 oi
= (struct ospf6_interface
*)EVENT_ARG(thread
);
2823 if (oi
->state
<= OSPF6_INTERFACE_WAITING
) {
2824 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_LSUPDATE
,
2827 "Quit to send LSUpdate to interface %s state %s",
2828 oi
->interface
->name
,
2829 ospf6_interface_state_str
[oi
->state
]);
2833 /* if we have nothing to send, return */
2834 if (oi
->lsupdate_list
->count
== 0)
2837 op
= ospf6_packet_new(oi
->ifmtu
);
2838 ospf6_make_header(OSPF6_MESSAGE_TYPE_LSUPDATE
, oi
, op
->s
);
2839 length
+= ospf6_make_lsupdate_interface(oi
, &op
, &lsa_cnt
);
2841 /* Fill OSPF header. */
2842 ospf6_fill_header(oi
, op
->s
, length
);
2843 ospf6_fill_lsupdate_header(op
->s
, lsa_cnt
);
2844 op
->length
= length
;
2845 ospf6_send_lsupdate(NULL
, oi
, op
);
2847 ospf6_packet_free(op
);
2849 if (oi
->lsupdate_list
->count
> 0) {
2850 event_add_event(master
, ospf6_lsupdate_send_interface
, oi
, 0,
2851 &oi
->thread_send_lsupdate
);
2855 void ospf6_lsack_send_neighbor(struct event
*thread
)
2857 struct ospf6_neighbor
*on
;
2858 struct ospf6_packet
*op
;
2859 uint16_t length
= OSPF6_HEADER_SIZE
;
2861 on
= (struct ospf6_neighbor
*)EVENT_ARG(thread
);
2863 if (on
->state
< OSPF6_NEIGHBOR_EXCHANGE
) {
2864 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_LSACK
, SEND_HDR
))
2865 zlog_debug("Quit to send LSAck to neighbor %s state %s",
2867 ospf6_neighbor_state_str
[on
->state
]);
2871 /* if we have nothing to send, return */
2872 if (on
->lsack_list
->count
== 0)
2875 op
= ospf6_packet_new(on
->ospf6_if
->ifmtu
);
2876 ospf6_make_header(OSPF6_MESSAGE_TYPE_LSACK
, on
->ospf6_if
, op
->s
);
2878 length
+= ospf6_make_lsack_neighbor(on
, &op
);
2880 if (length
== OSPF6_HEADER_SIZE
) {
2881 ospf6_packet_free(op
);
2885 /* Fill OSPF header. */
2886 ospf6_fill_header(on
->ospf6_if
, op
->s
, length
);
2888 /* Set packet length, dst and queue to FIFO. */
2889 op
->length
= length
;
2890 op
->dst
= on
->linklocal_addr
;
2891 ospf6_fill_hdr_checksum(on
->ospf6_if
, op
);
2892 ospf6_packet_add(on
->ospf6_if
, op
);
2893 OSPF6_MESSAGE_WRITE_ON(on
->ospf6_if
);
2895 if (on
->lsack_list
->count
> 0)
2896 event_add_event(master
, ospf6_lsack_send_neighbor
, on
, 0,
2897 &on
->thread_send_lsack
);
2900 static uint16_t ospf6_make_lsack_interface(struct ospf6_interface
*oi
,
2901 struct ospf6_packet
*op
)
2903 uint16_t length
= 0;
2904 struct ospf6_lsa
*lsa
, *lsanext
;
2906 for (ALL_LSDB(oi
->lsack_list
, lsa
, lsanext
)) {
2907 if ((length
+ sizeof(struct ospf6_lsa_header
)
2908 + OSPF6_HEADER_SIZE
)
2909 > ospf6_packet_max(oi
)) {
2910 /* if we run out of packet size/space here,
2911 better to try again soon. */
2912 EVENT_OFF(oi
->thread_send_lsack
);
2913 event_add_event(master
, ospf6_lsack_send_interface
, oi
,
2914 0, &oi
->thread_send_lsack
);
2916 ospf6_lsa_unlock(lsa
);
2918 ospf6_lsa_unlock(lsanext
);
2921 ospf6_lsa_age_update_to_send(lsa
, oi
->transdelay
);
2922 stream_put(op
->s
, lsa
->header
, sizeof(struct ospf6_lsa_header
));
2923 length
+= sizeof(struct ospf6_lsa_header
);
2925 assert(lsa
->lock
== 2);
2926 ospf6_lsdb_remove(lsa
, oi
->lsack_list
);
2931 void ospf6_lsack_send_interface(struct event
*thread
)
2933 struct ospf6_interface
*oi
;
2934 struct ospf6_packet
*op
;
2935 uint16_t length
= OSPF6_HEADER_SIZE
;
2937 oi
= (struct ospf6_interface
*)EVENT_ARG(thread
);
2939 if (oi
->state
<= OSPF6_INTERFACE_WAITING
) {
2940 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_LSACK
, SEND_HDR
))
2942 "Quit to send LSAck to interface %s state %s",
2943 oi
->interface
->name
,
2944 ospf6_interface_state_str
[oi
->state
]);
2948 /* if we have nothing to send, return */
2949 if (oi
->lsack_list
->count
== 0)
2952 op
= ospf6_packet_new(oi
->ifmtu
);
2953 ospf6_make_header(OSPF6_MESSAGE_TYPE_LSACK
, oi
, op
->s
);
2955 length
+= ospf6_make_lsack_interface(oi
, op
);
2957 if (length
== OSPF6_HEADER_SIZE
) {
2958 ospf6_packet_free(op
);
2961 /* Fill OSPF header. */
2962 ospf6_fill_header(oi
, op
->s
, length
);
2964 /* Set packet length, dst and queue to FIFO. */
2965 op
->length
= length
;
2966 if ((oi
->state
== OSPF6_INTERFACE_POINTTOPOINT
)
2967 || (oi
->state
== OSPF6_INTERFACE_DR
)
2968 || (oi
->state
== OSPF6_INTERFACE_BDR
))
2969 op
->dst
= allspfrouters6
;
2971 op
->dst
= alldrouters6
;
2973 ospf6_fill_hdr_checksum(oi
, op
);
2974 ospf6_packet_add(oi
, op
);
2975 OSPF6_MESSAGE_WRITE_ON(oi
);
2977 if (oi
->lsack_list
->count
> 0)
2978 event_add_event(master
, ospf6_lsack_send_interface
, oi
, 0,
2979 &oi
->thread_send_lsack
);
2983 DEFUN(debug_ospf6_message
, debug_ospf6_message_cmd
,
2984 "debug ospf6 message <unknown|hello|dbdesc|lsreq|lsupdate|lsack|all> [<send|recv|send-hdr|recv-hdr>]",
2986 "Debug OSPFv3 message\n"
2987 "Debug Unknown message\n"
2988 "Debug Hello message\n"
2989 "Debug Database Description message\n"
2990 "Debug Link State Request message\n"
2991 "Debug Link State Update message\n"
2992 "Debug Link State Acknowledgement message\n"
2993 "Debug All message\n"
2994 "Debug only sending message, entire packet\n"
2995 "Debug only receiving message, entire packet\n"
2996 "Debug only sending message, header only\n"
2997 "Debug only receiving message, header only\n")
3000 int idx_send_recv
= 4;
3001 unsigned char level
= 0;
3006 if (!strncmp(argv
[idx_packet
]->arg
, "u", 1))
3007 type
= OSPF6_MESSAGE_TYPE_UNKNOWN
;
3008 else if (!strncmp(argv
[idx_packet
]->arg
, "h", 1))
3009 type
= OSPF6_MESSAGE_TYPE_HELLO
;
3010 else if (!strncmp(argv
[idx_packet
]->arg
, "d", 1))
3011 type
= OSPF6_MESSAGE_TYPE_DBDESC
;
3012 else if (!strncmp(argv
[idx_packet
]->arg
, "lsr", 3))
3013 type
= OSPF6_MESSAGE_TYPE_LSREQ
;
3014 else if (!strncmp(argv
[idx_packet
]->arg
, "lsu", 3))
3015 type
= OSPF6_MESSAGE_TYPE_LSUPDATE
;
3016 else if (!strncmp(argv
[idx_packet
]->arg
, "lsa", 3))
3017 type
= OSPF6_MESSAGE_TYPE_LSACK
;
3018 else if (!strncmp(argv
[idx_packet
]->arg
, "a", 1))
3019 type
= OSPF6_MESSAGE_TYPE_ALL
;
3022 level
= OSPF6_DEBUG_MESSAGE_SEND
| OSPF6_DEBUG_MESSAGE_RECV
;
3023 else if (!strncmp(argv
[idx_send_recv
]->arg
, "send-h", 6))
3024 level
= OSPF6_DEBUG_MESSAGE_SEND_HDR
;
3025 else if (!strncmp(argv
[idx_send_recv
]->arg
, "s", 1))
3026 level
= OSPF6_DEBUG_MESSAGE_SEND
;
3027 else if (!strncmp(argv
[idx_send_recv
]->arg
, "recv-h", 6))
3028 level
= OSPF6_DEBUG_MESSAGE_RECV_HDR
;
3029 else if (!strncmp(argv
[idx_send_recv
]->arg
, "r", 1))
3030 level
= OSPF6_DEBUG_MESSAGE_RECV
;
3032 if (type
== OSPF6_MESSAGE_TYPE_ALL
) {
3033 for (i
= 0; i
< 6; i
++)
3034 OSPF6_DEBUG_MESSAGE_ON(i
, level
);
3036 OSPF6_DEBUG_MESSAGE_ON(type
, level
);
3041 DEFUN(no_debug_ospf6_message
, no_debug_ospf6_message_cmd
,
3042 "no debug ospf6 message <unknown|hello|dbdesc|lsreq|lsupdate|lsack|all> [<send|recv|send-hdr|recv-hdr>]",
3043 NO_STR DEBUG_STR OSPF6_STR
3044 "Debug OSPFv3 message\n"
3045 "Debug Unknown message\n"
3046 "Debug Hello message\n"
3047 "Debug Database Description message\n"
3048 "Debug Link State Request message\n"
3049 "Debug Link State Update message\n"
3050 "Debug Link State Acknowledgement message\n"
3051 "Debug All message\n"
3052 "Debug only sending message, entire pkt\n"
3053 "Debug only receiving message, entire pkt\n"
3054 "Debug only sending message, header only\n"
3055 "Debug only receiving message, header only\n")
3058 int idx_send_recv
= 5;
3059 unsigned char level
= 0;
3064 if (!strncmp(argv
[idx_packet
]->arg
, "u", 1))
3065 type
= OSPF6_MESSAGE_TYPE_UNKNOWN
;
3066 else if (!strncmp(argv
[idx_packet
]->arg
, "h", 1))
3067 type
= OSPF6_MESSAGE_TYPE_HELLO
;
3068 else if (!strncmp(argv
[idx_packet
]->arg
, "d", 1))
3069 type
= OSPF6_MESSAGE_TYPE_DBDESC
;
3070 else if (!strncmp(argv
[idx_packet
]->arg
, "lsr", 3))
3071 type
= OSPF6_MESSAGE_TYPE_LSREQ
;
3072 else if (!strncmp(argv
[idx_packet
]->arg
, "lsu", 3))
3073 type
= OSPF6_MESSAGE_TYPE_LSUPDATE
;
3074 else if (!strncmp(argv
[idx_packet
]->arg
, "lsa", 3))
3075 type
= OSPF6_MESSAGE_TYPE_LSACK
;
3076 else if (!strncmp(argv
[idx_packet
]->arg
, "a", 1))
3077 type
= OSPF6_MESSAGE_TYPE_ALL
;
3080 level
= OSPF6_DEBUG_MESSAGE_SEND
| OSPF6_DEBUG_MESSAGE_RECV
3081 | OSPF6_DEBUG_MESSAGE_SEND_HDR
3082 | OSPF6_DEBUG_MESSAGE_RECV_HDR
;
3083 else if (!strncmp(argv
[idx_send_recv
]->arg
, "send-h", 6))
3084 level
= OSPF6_DEBUG_MESSAGE_SEND_HDR
;
3085 else if (!strncmp(argv
[idx_send_recv
]->arg
, "s", 1))
3086 level
= OSPF6_DEBUG_MESSAGE_SEND
;
3087 else if (!strncmp(argv
[idx_send_recv
]->arg
, "recv-h", 6))
3088 level
= OSPF6_DEBUG_MESSAGE_RECV_HDR
;
3089 else if (!strncmp(argv
[idx_send_recv
]->arg
, "r", 1))
3090 level
= OSPF6_DEBUG_MESSAGE_RECV
;
3092 if (type
== OSPF6_MESSAGE_TYPE_ALL
) {
3093 for (i
= 0; i
< 6; i
++)
3094 OSPF6_DEBUG_MESSAGE_OFF(i
, level
);
3096 OSPF6_DEBUG_MESSAGE_OFF(type
, level
);
3102 int config_write_ospf6_debug_message(struct vty
*vty
)
3104 const char *type_str
[] = {"unknown", "hello", "dbdesc",
3105 "lsreq", "lsupdate", "lsack"};
3106 unsigned char s
= 0, r
= 0, sh
= 0, rh
= 0;
3109 for (i
= 0; i
< 6; i
++) {
3110 if (IS_OSPF6_DEBUG_MESSAGE_ENABLED(i
, SEND
))
3112 if (IS_OSPF6_DEBUG_MESSAGE_ENABLED(i
, RECV
))
3116 for (i
= 0; i
< 6; i
++) {
3117 if (IS_OSPF6_DEBUG_MESSAGE_ENABLED(i
, SEND_HDR
))
3119 if (IS_OSPF6_DEBUG_MESSAGE_ENABLED(i
, RECV_HDR
))
3123 if (s
== 0x3f && r
== 0x3f) {
3124 vty_out(vty
, "debug ospf6 message all\n");
3128 if (s
== 0x3f && r
== 0) {
3129 vty_out(vty
, "debug ospf6 message all send\n");
3131 } else if (s
== 0 && r
== 0x3f) {
3132 vty_out(vty
, "debug ospf6 message all recv\n");
3136 if (sh
== 0x3f && rh
== 0) {
3137 vty_out(vty
, "debug ospf6 message all send-hdr\n");
3139 } else if (sh
== 0 && rh
== 0x3f) {
3140 vty_out(vty
, "debug ospf6 message all recv-hdr\n");
3144 /* Unknown message is logged by default */
3145 if (!IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN
, SEND
)
3146 && !IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN
, RECV
))
3147 vty_out(vty
, "no debug ospf6 message unknown\n");
3148 else if (!IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN
, SEND
))
3149 vty_out(vty
, "no debug ospf6 message unknown send\n");
3150 else if (!IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN
, RECV
))
3151 vty_out(vty
, "no debug ospf6 message unknown recv\n");
3153 for (i
= 1; i
< 6; i
++) {
3154 if (IS_OSPF6_DEBUG_MESSAGE_ENABLED(i
, SEND
)
3155 && IS_OSPF6_DEBUG_MESSAGE_ENABLED(i
, RECV
)) {
3156 vty_out(vty
, "debug ospf6 message %s\n", type_str
[i
]);
3160 if (IS_OSPF6_DEBUG_MESSAGE_ENABLED(i
, SEND
))
3161 vty_out(vty
, "debug ospf6 message %s send\n",
3163 else if (IS_OSPF6_DEBUG_MESSAGE_ENABLED(i
, SEND_HDR
))
3164 vty_out(vty
, "debug ospf6 message %s send-hdr\n",
3167 if (IS_OSPF6_DEBUG_MESSAGE_ENABLED(i
, RECV
))
3168 vty_out(vty
, "debug ospf6 message %s recv\n",
3170 else if (IS_OSPF6_DEBUG_MESSAGE_ENABLED(i
, RECV_HDR
))
3171 vty_out(vty
, "debug ospf6 message %s recv-hdr\n",
3178 void install_element_ospf6_debug_message(void)
3180 install_element(ENABLE_NODE
, &debug_ospf6_message_cmd
);
3181 install_element(ENABLE_NODE
, &no_debug_ospf6_message_cmd
);
3182 install_element(CONFIG_NODE
, &debug_ospf6_message_cmd
);
3183 install_element(CONFIG_NODE
, &no_debug_ospf6_message_cmd
);