2 * Copyright (C) 2003 Yasuhiro Ohara
4 * This file is part of GNU Zebra.
6 * GNU Zebra is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2, or (at your option) any
11 * GNU Zebra is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
16 * You should have received a copy of the GNU General Public License along
17 * with this program; see the file COPYING; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
29 #include "lib_errors.h"
33 #include "ospf6_proto.h"
34 #include "ospf6_lsa.h"
35 #include "ospf6_lsdb.h"
36 #include "ospf6_top.h"
37 #include "ospf6_network.h"
38 #include "ospf6_message.h"
40 #include "ospf6_area.h"
41 #include "ospf6_neighbor.h"
42 #include "ospf6_interface.h"
44 /* for structures and macros ospf6_lsa_examin() needs */
45 #include "ospf6_abr.h"
46 #include "ospf6_asbr.h"
47 #include "ospf6_intra.h"
49 #include "ospf6_flood.h"
52 #include <netinet/ip6.h>
53 #include "lib/libospf.h"
54 #include "lib/keychain.h"
55 #include "ospf6_auth_trailer.h"
57 DEFINE_MTYPE_STATIC(OSPF6D
, OSPF6_MESSAGE
, "OSPF6 message");
58 DEFINE_MTYPE_STATIC(OSPF6D
, OSPF6_PACKET
, "OSPF6 packet");
59 DEFINE_MTYPE_STATIC(OSPF6D
, OSPF6_FIFO
, "OSPF6 FIFO queue");
61 unsigned char conf_debug_ospf6_message
[6] = {0x03, 0, 0, 0, 0, 0};
63 const char *ospf6_message_type(int type
)
66 case OSPF6_MESSAGE_TYPE_HELLO
:
68 case OSPF6_MESSAGE_TYPE_DBDESC
:
70 case OSPF6_MESSAGE_TYPE_LSREQ
:
72 case OSPF6_MESSAGE_TYPE_LSUPDATE
:
74 case OSPF6_MESSAGE_TYPE_LSACK
:
76 case OSPF6_MESSAGE_TYPE_UNKNOWN
:
82 /* Minimum (besides the standard OSPF packet header) lengths for OSPF
83 packets of particular types, offset is the "type" field. */
84 const uint16_t ospf6_packet_minlen
[OSPF6_MESSAGE_TYPE_ALL
] = {
87 OSPF6_DB_DESC_MIN_SIZE
,
88 OSPF6_LS_REQ_MIN_SIZE
,
89 OSPF6_LS_UPD_MIN_SIZE
,
90 OSPF6_LS_ACK_MIN_SIZE
};
92 /* Minimum (besides the standard LSA header) lengths for LSAs of particular
93 types, offset is the "LSA function code" portion of "LSA type" field. */
94 const uint16_t ospf6_lsa_minlen
[OSPF6_LSTYPE_SIZE
] = {
96 /* 0x2001 */ OSPF6_ROUTER_LSA_MIN_SIZE
,
97 /* 0x2002 */ OSPF6_NETWORK_LSA_MIN_SIZE
,
98 /* 0x2003 */ OSPF6_INTER_PREFIX_LSA_MIN_SIZE
,
99 /* 0x2004 */ OSPF6_INTER_ROUTER_LSA_FIX_SIZE
,
100 /* 0x4005 */ OSPF6_AS_EXTERNAL_LSA_MIN_SIZE
,
102 /* 0x2007 */ OSPF6_AS_EXTERNAL_LSA_MIN_SIZE
,
103 /* 0x0008 */ OSPF6_LINK_LSA_MIN_SIZE
,
104 /* 0x2009 */ OSPF6_INTRA_PREFIX_LSA_MIN_SIZE
,
106 /* 0x000b */ OSPF6_GRACE_LSA_MIN_SIZE
};
108 /* print functions */
110 static void ospf6_header_print(struct ospf6_header
*oh
)
112 zlog_debug(" OSPFv%d Type:%d Len:%hu Router-ID:%pI4", oh
->version
,
113 oh
->type
, ntohs(oh
->length
), &oh
->router_id
);
114 zlog_debug(" Area-ID:%pI4 Cksum:%hx Instance-ID:%d", &oh
->area_id
,
115 ntohs(oh
->checksum
), oh
->instance_id
);
118 void ospf6_hello_print(struct ospf6_header
*oh
, int action
)
120 struct ospf6_hello
*hello
;
124 ospf6_header_print(oh
);
125 assert(oh
->type
== OSPF6_MESSAGE_TYPE_HELLO
);
127 hello
= (struct ospf6_hello
*)((caddr_t
)oh
128 + sizeof(struct ospf6_header
));
130 ospf6_options_printbuf(hello
->options
, options
, sizeof(options
));
132 zlog_debug(" I/F-Id:%ld Priority:%d Option:%s",
133 (unsigned long)ntohl(hello
->interface_id
), hello
->priority
,
135 zlog_debug(" HelloInterval:%hu DeadInterval:%hu",
136 ntohs(hello
->hello_interval
), ntohs(hello
->dead_interval
));
137 zlog_debug(" DR:%pI4 BDR:%pI4", &hello
->drouter
, &hello
->bdrouter
);
139 if ((IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
)
140 && action
== OSPF6_ACTION_RECV
)
141 || (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, SEND
)
142 && action
== OSPF6_ACTION_SEND
)) {
144 for (p
= (char *)((caddr_t
)hello
+ sizeof(struct ospf6_hello
));
145 p
+ sizeof(uint32_t) <= OSPF6_MESSAGE_END(oh
);
146 p
+= sizeof(uint32_t))
147 zlog_debug(" Neighbor: %pI4", (in_addr_t
*)p
);
149 assert(p
== OSPF6_MESSAGE_END(oh
));
153 void ospf6_dbdesc_print(struct ospf6_header
*oh
, int action
)
155 struct ospf6_dbdesc
*dbdesc
;
159 ospf6_header_print(oh
);
160 assert(oh
->type
== OSPF6_MESSAGE_TYPE_DBDESC
);
162 dbdesc
= (struct ospf6_dbdesc
*)((caddr_t
)oh
163 + sizeof(struct ospf6_header
));
165 ospf6_options_printbuf(dbdesc
->options
, options
, sizeof(options
));
167 zlog_debug(" MBZ: %#x Option: %s IfMTU: %hu", dbdesc
->reserved1
,
168 options
, ntohs(dbdesc
->ifmtu
));
169 zlog_debug(" MBZ: %#x Bits: %s%s%s SeqNum: %#lx", dbdesc
->reserved2
,
170 (CHECK_FLAG(dbdesc
->bits
, OSPF6_DBDESC_IBIT
) ? "I" : "-"),
171 (CHECK_FLAG(dbdesc
->bits
, OSPF6_DBDESC_MBIT
) ? "M" : "-"),
172 (CHECK_FLAG(dbdesc
->bits
, OSPF6_DBDESC_MSBIT
) ? "m" : "s"),
173 (unsigned long)ntohl(dbdesc
->seqnum
));
175 if ((IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
)
176 && action
== OSPF6_ACTION_RECV
)
177 || (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, SEND
)
178 && action
== OSPF6_ACTION_SEND
)) {
180 for (p
= (char *)((caddr_t
)dbdesc
181 + sizeof(struct ospf6_dbdesc
));
182 p
+ sizeof(struct ospf6_lsa_header
)
183 <= OSPF6_MESSAGE_END(oh
);
184 p
+= sizeof(struct ospf6_lsa_header
))
185 ospf6_lsa_header_print_raw(
186 (struct ospf6_lsa_header
*)p
);
188 assert(p
== OSPF6_MESSAGE_END(oh
));
192 void ospf6_lsreq_print(struct ospf6_header
*oh
, int action
)
196 ospf6_header_print(oh
);
197 assert(oh
->type
== OSPF6_MESSAGE_TYPE_LSREQ
);
199 if ((IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
)
200 && action
== OSPF6_ACTION_RECV
)
201 || (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, SEND
)
202 && action
== OSPF6_ACTION_SEND
)) {
204 for (p
= (char *)((caddr_t
)oh
+ sizeof(struct ospf6_header
));
205 p
+ sizeof(struct ospf6_lsreq_entry
)
206 <= OSPF6_MESSAGE_END(oh
);
207 p
+= sizeof(struct ospf6_lsreq_entry
)) {
208 struct ospf6_lsreq_entry
*e
=
209 (struct ospf6_lsreq_entry
*)p
;
211 zlog_debug(" [%s Id:%pI4 Adv:%pI4]",
212 ospf6_lstype_name(e
->type
), &e
->id
,
216 assert(p
== OSPF6_MESSAGE_END(oh
));
220 void ospf6_lsupdate_print(struct ospf6_header
*oh
, int action
)
222 struct ospf6_lsupdate
*lsupdate
;
226 ospf6_header_print(oh
);
227 assert(oh
->type
== OSPF6_MESSAGE_TYPE_LSUPDATE
);
229 lsupdate
= (struct ospf6_lsupdate
*)((caddr_t
)oh
230 + sizeof(struct ospf6_header
));
232 num
= ntohl(lsupdate
->lsa_number
);
233 zlog_debug(" Number of LSA: %ld", num
);
235 if ((IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
)
236 && action
== OSPF6_ACTION_RECV
)
237 || (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, SEND
)
238 && action
== OSPF6_ACTION_SEND
)) {
240 for (p
= (char *)((caddr_t
)lsupdate
241 + sizeof(struct ospf6_lsupdate
));
242 p
< OSPF6_MESSAGE_END(oh
)
243 && p
+ OSPF6_LSA_SIZE(p
) <= OSPF6_MESSAGE_END(oh
);
244 p
+= OSPF6_LSA_SIZE(p
)) {
245 ospf6_lsa_header_print_raw(
246 (struct ospf6_lsa_header
*)p
);
249 assert(p
== OSPF6_MESSAGE_END(oh
));
253 void ospf6_lsack_print(struct ospf6_header
*oh
, int action
)
257 ospf6_header_print(oh
);
258 assert(oh
->type
== OSPF6_MESSAGE_TYPE_LSACK
);
260 if ((IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
)
261 && action
== OSPF6_ACTION_RECV
)
262 || (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, SEND
)
263 && action
== OSPF6_ACTION_SEND
)) {
265 for (p
= (char *)((caddr_t
)oh
+ sizeof(struct ospf6_header
));
266 p
+ sizeof(struct ospf6_lsa_header
)
267 <= OSPF6_MESSAGE_END(oh
);
268 p
+= sizeof(struct ospf6_lsa_header
))
269 ospf6_lsa_header_print_raw(
270 (struct ospf6_lsa_header
*)p
);
272 assert(p
== OSPF6_MESSAGE_END(oh
));
276 static struct ospf6_packet
*ospf6_packet_new(size_t size
)
278 struct ospf6_packet
*new;
280 new = XCALLOC(MTYPE_OSPF6_PACKET
, sizeof(struct ospf6_packet
));
281 new->s
= stream_new(size
);
286 static void ospf6_packet_free(struct ospf6_packet
*op
)
291 XFREE(MTYPE_OSPF6_PACKET
, op
);
294 struct ospf6_fifo
*ospf6_fifo_new(void)
296 struct ospf6_fifo
*new;
298 new = XCALLOC(MTYPE_OSPF6_FIFO
, sizeof(struct ospf6_fifo
));
302 /* Add new packet to fifo. */
303 static void ospf6_fifo_push(struct ospf6_fifo
*fifo
, struct ospf6_packet
*op
)
306 fifo
->tail
->next
= op
;
315 /* Add new packet to head of fifo. */
316 static void ospf6_fifo_push_head(struct ospf6_fifo
*fifo
,
317 struct ospf6_packet
*op
)
319 op
->next
= fifo
->head
;
321 if (fifo
->tail
== NULL
)
329 /* Delete first packet from fifo. */
330 static struct ospf6_packet
*ospf6_fifo_pop(struct ospf6_fifo
*fifo
)
332 struct ospf6_packet
*op
;
337 fifo
->head
= op
->next
;
339 if (fifo
->head
== NULL
)
348 /* Return first fifo entry. */
349 static struct ospf6_packet
*ospf6_fifo_head(struct ospf6_fifo
*fifo
)
354 /* Flush ospf packet fifo. */
355 void ospf6_fifo_flush(struct ospf6_fifo
*fifo
)
357 struct ospf6_packet
*op
;
358 struct ospf6_packet
*next
;
360 for (op
= fifo
->head
; op
; op
= next
) {
362 ospf6_packet_free(op
);
364 fifo
->head
= fifo
->tail
= NULL
;
368 /* Free ospf packet fifo. */
369 void ospf6_fifo_free(struct ospf6_fifo
*fifo
)
371 ospf6_fifo_flush(fifo
);
373 XFREE(MTYPE_OSPF6_FIFO
, fifo
);
376 static void ospf6_packet_add(struct ospf6_interface
*oi
,
377 struct ospf6_packet
*op
)
379 /* Add packet to end of queue. */
380 ospf6_fifo_push(oi
->obuf
, op
);
382 /* Debug of packet fifo*/
383 /* ospf_fifo_debug (oi->obuf); */
386 static void ospf6_packet_add_top(struct ospf6_interface
*oi
,
387 struct ospf6_packet
*op
)
389 /* Add packet to head of queue. */
390 ospf6_fifo_push_head(oi
->obuf
, op
);
392 /* Debug of packet fifo*/
393 /* ospf_fifo_debug (oi->obuf); */
396 static void ospf6_packet_delete(struct ospf6_interface
*oi
)
398 struct ospf6_packet
*op
;
400 op
= ospf6_fifo_pop(oi
->obuf
);
403 ospf6_packet_free(op
);
407 static void ospf6_hello_recv(struct in6_addr
*src
, struct in6_addr
*dst
,
408 struct ospf6_interface
*oi
,
409 struct ospf6_header
*oh
)
411 struct ospf6_hello
*hello
;
412 struct ospf6_neighbor
*on
;
415 int neighborchange
= 0;
416 int neighbor_ifindex_change
= 0;
419 struct timeval timestamp
;
421 monotime(×tamp
);
422 hello
= (struct ospf6_hello
*)((caddr_t
)oh
423 + sizeof(struct ospf6_header
));
425 /* HelloInterval check */
426 if (ntohs(hello
->hello_interval
) != oi
->hello_interval
) {
428 "VRF %s: I/F %s HelloInterval mismatch: (my %d, rcvd %d)",
429 oi
->interface
->vrf
->name
, oi
->interface
->name
,
430 oi
->hello_interval
, ntohs(hello
->hello_interval
));
434 /* RouterDeadInterval check */
435 if (ntohs(hello
->dead_interval
) != oi
->dead_interval
) {
437 "VRF %s: I/F %s DeadInterval mismatch: (my %d, rcvd %d)",
438 oi
->interface
->vrf
->name
, oi
->interface
->name
,
439 oi
->dead_interval
, ntohs(hello
->dead_interval
));
444 if (OSPF6_OPT_ISSET(hello
->options
, OSPF6_OPT_E
)
445 != OSPF6_OPT_ISSET(oi
->area
->options
, OSPF6_OPT_E
)) {
446 zlog_warn("VRF %s: IF %s E-bit mismatch",
447 oi
->interface
->vrf
->name
, oi
->interface
->name
);
452 if (OSPF6_OPT_ISSET(hello
->options
, OSPF6_OPT_N
)
453 != OSPF6_OPT_ISSET(oi
->area
->options
, OSPF6_OPT_N
)) {
454 zlog_warn("VRF %s: IF %s N-bit mismatch",
455 oi
->interface
->vrf
->name
, oi
->interface
->name
);
459 if (((OSPF6_OPT_ISSET_EXT(hello
->options
, OSPF6_OPT_AT
) ==
461 (oi
->at_data
.flags
== 0)) ||
462 ((OSPF6_OPT_ISSET_EXT(hello
->options
, OSPF6_OPT_AT
) !=
464 (oi
->at_data
.flags
!= 0))) {
465 if (IS_OSPF6_DEBUG_AUTH_RX
)
467 "VRF %s: IF %s AT-bit mismatch in hello packet",
468 oi
->interface
->vrf
->name
, oi
->interface
->name
);
469 oi
->at_data
.rx_drop
++;
473 /* Find neighbor, create if not exist */
474 on
= ospf6_neighbor_lookup(oh
->router_id
, oi
);
476 on
= ospf6_neighbor_create(oh
->router_id
, oi
);
477 on
->prev_drouter
= on
->drouter
= hello
->drouter
;
478 on
->prev_bdrouter
= on
->bdrouter
= hello
->bdrouter
;
479 on
->priority
= hello
->priority
;
482 /* check latency against hello period */
484 latency
= monotime_since(&on
->last_hello
, NULL
)
485 - ((int64_t)oi
->hello_interval
* 1000000);
486 /* log if latency exceeds the hello period */
487 if (latency
> ((int64_t)oi
->hello_interval
* 1000000))
488 zlog_warn("%s RX %pI4 high latency %" PRId64
"us.", __func__
,
489 &on
->router_id
, latency
);
490 on
->last_hello
= timestamp
;
493 /* Always override neighbor's source address */
494 memcpy(&on
->linklocal_addr
, src
, sizeof(struct in6_addr
));
496 /* Neighbor ifindex check */
497 if (on
->ifindex
!= (ifindex_t
)ntohl(hello
->interface_id
)) {
498 on
->ifindex
= ntohl(hello
->interface_id
);
499 neighbor_ifindex_change
++;
503 for (p
= (char *)((caddr_t
)hello
+ sizeof(struct ospf6_hello
));
504 p
+ sizeof(uint32_t) <= OSPF6_MESSAGE_END(oh
);
505 p
+= sizeof(uint32_t)) {
506 uint32_t *router_id
= (uint32_t *)p
;
508 if (*router_id
== oi
->area
->ospf6
->router_id
)
512 assert(p
== OSPF6_MESSAGE_END(oh
));
514 /* RouterPriority check */
515 if (on
->priority
!= hello
->priority
) {
516 on
->priority
= hello
->priority
;
521 if (on
->drouter
!= hello
->drouter
) {
522 on
->prev_drouter
= on
->drouter
;
523 on
->drouter
= hello
->drouter
;
524 if (on
->prev_drouter
== on
->router_id
525 || on
->drouter
== on
->router_id
)
530 if (on
->bdrouter
!= hello
->bdrouter
) {
531 on
->prev_bdrouter
= on
->bdrouter
;
532 on
->bdrouter
= hello
->bdrouter
;
533 if (on
->prev_bdrouter
== on
->router_id
534 || on
->bdrouter
== on
->router_id
)
538 /* BackupSeen check */
539 if (oi
->state
== OSPF6_INTERFACE_WAITING
) {
540 if (hello
->bdrouter
== on
->router_id
)
542 else if (hello
->drouter
== on
->router_id
543 && hello
->bdrouter
== htonl(0))
549 /* Execute neighbor events */
550 thread_execute(master
, hello_received
, on
, 0);
552 thread_execute(master
, twoway_received
, on
, 0);
554 if (OSPF6_GR_IS_ACTIVE_HELPER(on
)) {
555 if (IS_DEBUG_OSPF6_GR
)
557 "%s, Received oneway hello from RESTARTER so ignore here.",
558 __PRETTY_FUNCTION__
);
560 /* If the router is DR_OTHER, RESTARTER will not wait
561 * until it receives the hello from it if it receives
563 * So, helper might receives ONE_WAY hello from
564 * RESTARTER. So not allowing to change the state if it
565 * receives one_way hellow when it acts as HELPER for
566 * that specific neighbor.
568 thread_execute(master
, oneway_received
, on
, 0);
572 if (OSPF6_GR_IS_ACTIVE_HELPER(on
)) {
573 /* As per the GR Conformance Test Case 7.2. Section 3
574 * "Also, if X was the Designated Router on network segment S
575 * when the helping relationship began, Y maintains X as the
576 * Designated Router until the helping relationship is
578 * When it is a helper for this neighbor, It should not trigger
579 * the ISM Events. Also Intentionally not setting the priority
580 * and other fields so that when the neighbor exits the Grace
581 * period, it can handle if there is any change before GR and
584 if (IS_DEBUG_OSPF6_GR
)
586 "%s, Neighbor is under GR Restart, hence ignoring the ISM Events",
587 __PRETTY_FUNCTION__
);
593 * RFC 3623 - Section 2:
594 * "If the restarting router determines that it was the Designated
595 * Router on a given segment prior to the restart, it elects
596 * itself as the Designated Router again. The restarting router
597 * knows that it was the Designated Router if, while the
598 * associated interface is in Waiting state, a Hello packet is
599 * received from a neighbor listing the router as the Designated
602 if (oi
->area
->ospf6
->gr_info
.restart_in_progress
603 && oi
->state
== OSPF6_INTERFACE_WAITING
604 && hello
->drouter
== oi
->area
->ospf6
->router_id
)
605 oi
->drouter
= hello
->drouter
;
607 /* Schedule interface events */
609 thread_add_event(master
, backup_seen
, oi
, 0, NULL
);
611 thread_add_event(master
, neighbor_change
, oi
, 0, NULL
);
613 if (neighbor_ifindex_change
&& on
->state
== OSPF6_NEIGHBOR_FULL
)
614 OSPF6_ROUTER_LSA_SCHEDULE(oi
->area
);
617 static void ospf6_dbdesc_recv_master(struct ospf6_header
*oh
,
618 struct ospf6_neighbor
*on
)
620 struct ospf6_dbdesc
*dbdesc
;
623 dbdesc
= (struct ospf6_dbdesc
*)((caddr_t
)oh
624 + sizeof(struct ospf6_header
));
626 if (on
->state
< OSPF6_NEIGHBOR_INIT
) {
627 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV_HDR
))
628 zlog_debug("Neighbor state less than Init, ignore");
633 case OSPF6_NEIGHBOR_TWOWAY
:
634 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV_HDR
))
635 zlog_debug("Neighbor state is 2-Way, ignore");
638 case OSPF6_NEIGHBOR_INIT
:
639 thread_execute(master
, twoway_received
, on
, 0);
640 if (on
->state
!= OSPF6_NEIGHBOR_EXSTART
) {
641 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV_HDR
))
643 "Neighbor state is not ExStart, ignore");
646 /* else fall through to ExStart */
648 case OSPF6_NEIGHBOR_EXSTART
:
649 /* if neighbor obeys us as our slave, schedule negotiation_done
650 and process LSA Headers. Otherwise, ignore this message */
651 if (!CHECK_FLAG(dbdesc
->bits
, OSPF6_DBDESC_MSBIT
)
652 && !CHECK_FLAG(dbdesc
->bits
, OSPF6_DBDESC_IBIT
)
653 && ntohl(dbdesc
->seqnum
) == on
->dbdesc_seqnum
) {
654 /* execute NegotiationDone */
655 thread_execute(master
, negotiation_done
, on
, 0);
657 /* Record neighbor options */
658 memcpy(on
->options
, dbdesc
->options
,
659 sizeof(on
->options
));
661 zlog_warn("VRF %s: Nbr %s: Negotiation failed",
662 on
->ospf6_if
->interface
->vrf
->name
, on
->name
);
665 /* fall through to exchange */
667 case OSPF6_NEIGHBOR_EXCHANGE
:
668 if (!memcmp(dbdesc
, &on
->dbdesc_last
,
669 sizeof(struct ospf6_dbdesc
))) {
670 /* Duplicated DatabaseDescription is dropped by master
672 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV_HDR
))
674 "Duplicated dbdesc discarded by Master, ignore");
678 if (CHECK_FLAG(dbdesc
->bits
, OSPF6_DBDESC_MSBIT
)) {
680 "DbDesc recv: Master/Slave bit mismatch Nbr %s",
682 thread_add_event(master
, seqnumber_mismatch
, on
, 0,
687 if (CHECK_FLAG(dbdesc
->bits
, OSPF6_DBDESC_IBIT
)) {
688 zlog_warn("DbDesc recv: Initialize bit mismatch Nbr %s",
690 thread_add_event(master
, seqnumber_mismatch
, on
, 0,
695 if (memcmp(on
->options
, dbdesc
->options
, sizeof(on
->options
))) {
696 zlog_warn("DbDesc recv: Option field mismatch Nbr %s",
698 thread_add_event(master
, seqnumber_mismatch
, on
, 0,
703 if (ntohl(dbdesc
->seqnum
) != on
->dbdesc_seqnum
) {
705 "DbDesc recv: Sequence number mismatch Nbr %s (%#lx expected)",
706 on
->name
, (unsigned long)on
->dbdesc_seqnum
);
707 thread_add_event(master
, seqnumber_mismatch
, on
, 0,
713 case OSPF6_NEIGHBOR_LOADING
:
714 case OSPF6_NEIGHBOR_FULL
:
715 if (!memcmp(dbdesc
, &on
->dbdesc_last
,
716 sizeof(struct ospf6_dbdesc
))) {
717 /* Duplicated DatabaseDescription is dropped by master
719 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV_HDR
))
721 "Duplicated dbdesc discarded by Master, ignore");
726 "DbDesc recv: Not duplicate dbdesc in state %s Nbr %s",
727 ospf6_neighbor_state_str
[on
->state
], on
->name
);
728 thread_add_event(master
, seqnumber_mismatch
, on
, 0, NULL
);
736 /* Process LSA headers */
737 for (p
= (char *)((caddr_t
)dbdesc
+ sizeof(struct ospf6_dbdesc
));
738 p
+ sizeof(struct ospf6_lsa_header
) <= OSPF6_MESSAGE_END(oh
);
739 p
+= sizeof(struct ospf6_lsa_header
)) {
740 struct ospf6_lsa
*his
, *mine
;
741 struct ospf6_lsdb
*lsdb
= NULL
;
743 his
= ospf6_lsa_create_headeronly((struct ospf6_lsa_header
*)p
);
745 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
746 zlog_debug("%s", his
->name
);
748 switch (OSPF6_LSA_SCOPE(his
->header
->type
)) {
749 case OSPF6_SCOPE_LINKLOCAL
:
750 lsdb
= on
->ospf6_if
->lsdb
;
752 case OSPF6_SCOPE_AREA
:
753 lsdb
= on
->ospf6_if
->area
->lsdb
;
756 lsdb
= on
->ospf6_if
->area
->ospf6
->lsdb
;
758 case OSPF6_SCOPE_RESERVED
:
759 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
760 zlog_debug("Ignoring LSA of reserved scope");
761 ospf6_lsa_delete(his
);
765 if (ntohs(his
->header
->type
) == OSPF6_LSTYPE_AS_EXTERNAL
766 && (IS_AREA_STUB(on
->ospf6_if
->area
)
767 || IS_AREA_NSSA(on
->ospf6_if
->area
))) {
768 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
770 "SeqNumMismatch (E-bit mismatch), discard");
771 ospf6_lsa_delete(his
);
772 thread_add_event(master
, seqnumber_mismatch
, on
, 0,
777 mine
= ospf6_lsdb_lookup(his
->header
->type
, his
->header
->id
,
778 his
->header
->adv_router
, lsdb
);
780 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
781 zlog_debug("Add request (No database copy)");
782 ospf6_lsdb_add(ospf6_lsa_copy(his
), on
->request_list
);
783 } else if (ospf6_lsa_compare(his
, mine
) < 0) {
784 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
785 zlog_debug("Add request (Received MoreRecent)");
786 ospf6_lsdb_add(ospf6_lsa_copy(his
), on
->request_list
);
788 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
789 zlog_debug("Discard (Existing MoreRecent)");
791 ospf6_lsa_delete(his
);
794 assert(p
== OSPF6_MESSAGE_END(oh
));
796 /* Increment sequence number */
799 /* schedule send lsreq */
800 if (on
->request_list
->count
)
801 thread_add_event(master
, ospf6_lsreq_send
, on
, 0,
802 &on
->thread_send_lsreq
);
804 THREAD_OFF(on
->thread_send_dbdesc
);
807 if (!CHECK_FLAG(dbdesc
->bits
, OSPF6_DBDESC_MBIT
)
808 && !CHECK_FLAG(on
->dbdesc_bits
, OSPF6_DBDESC_MBIT
))
809 thread_add_event(master
, exchange_done
, on
, 0,
810 &on
->thread_exchange_done
);
812 thread_add_event(master
, ospf6_dbdesc_send_newone
, on
, 0,
813 &on
->thread_send_dbdesc
);
816 /* save last received dbdesc */
817 memcpy(&on
->dbdesc_last
, dbdesc
, sizeof(struct ospf6_dbdesc
));
820 static void ospf6_dbdesc_recv_slave(struct ospf6_header
*oh
,
821 struct ospf6_neighbor
*on
)
823 struct ospf6_dbdesc
*dbdesc
;
826 dbdesc
= (struct ospf6_dbdesc
*)((caddr_t
)oh
827 + sizeof(struct ospf6_header
));
829 if (on
->state
< OSPF6_NEIGHBOR_INIT
) {
830 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV_HDR
))
831 zlog_debug("Neighbor state less than Init, ignore");
836 case OSPF6_NEIGHBOR_TWOWAY
:
837 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV_HDR
))
838 zlog_debug("Neighbor state is 2-Way, ignore");
841 case OSPF6_NEIGHBOR_INIT
:
842 thread_execute(master
, twoway_received
, on
, 0);
843 if (on
->state
!= OSPF6_NEIGHBOR_EXSTART
) {
844 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV_HDR
))
846 "Neighbor state is not ExStart, ignore");
849 /* else fall through to ExStart */
851 case OSPF6_NEIGHBOR_EXSTART
:
852 /* If the neighbor is Master, act as Slave. Schedule
854 and process LSA Headers. Otherwise, ignore this message */
855 if (CHECK_FLAG(dbdesc
->bits
, OSPF6_DBDESC_IBIT
)
856 && CHECK_FLAG(dbdesc
->bits
, OSPF6_DBDESC_MBIT
)
857 && CHECK_FLAG(dbdesc
->bits
, OSPF6_DBDESC_MSBIT
)
859 == sizeof(struct ospf6_header
)
860 + sizeof(struct ospf6_dbdesc
)) {
861 /* set the master/slave bit to slave */
862 UNSET_FLAG(on
->dbdesc_bits
, OSPF6_DBDESC_MSBIT
);
864 /* set the DD sequence number to one specified by master
866 on
->dbdesc_seqnum
= ntohl(dbdesc
->seqnum
);
868 /* schedule NegotiationDone */
869 thread_execute(master
, negotiation_done
, on
, 0);
871 /* Record neighbor options */
872 memcpy(on
->options
, dbdesc
->options
,
873 sizeof(on
->options
));
875 zlog_warn("VRF %s: Nbr %s Negotiation failed",
876 on
->ospf6_if
->interface
->vrf
->name
, on
->name
);
881 case OSPF6_NEIGHBOR_EXCHANGE
:
882 if (!memcmp(dbdesc
, &on
->dbdesc_last
,
883 sizeof(struct ospf6_dbdesc
))) {
884 /* Duplicated DatabaseDescription causes slave to
886 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV_HDR
))
888 "Duplicated dbdesc causes retransmit");
889 THREAD_OFF(on
->thread_send_dbdesc
);
890 thread_add_event(master
, ospf6_dbdesc_send
, on
, 0,
891 &on
->thread_send_dbdesc
);
895 if (!CHECK_FLAG(dbdesc
->bits
, OSPF6_DBDESC_MSBIT
)) {
897 "DbDesc slave recv: Master/Slave bit mismatch Nbr %s",
899 thread_add_event(master
, seqnumber_mismatch
, on
, 0,
904 if (CHECK_FLAG(dbdesc
->bits
, OSPF6_DBDESC_IBIT
)) {
906 "DbDesc slave recv: Initialize bit mismatch Nbr %s",
908 thread_add_event(master
, seqnumber_mismatch
, on
, 0,
913 if (memcmp(on
->options
, dbdesc
->options
, sizeof(on
->options
))) {
915 "DbDesc slave recv: Option field mismatch Nbr %s",
917 thread_add_event(master
, seqnumber_mismatch
, on
, 0,
922 if (ntohl(dbdesc
->seqnum
) != on
->dbdesc_seqnum
+ 1) {
924 "DbDesc slave recv: Sequence number mismatch Nbr %s (%#lx expected)",
925 on
->name
, (unsigned long)on
->dbdesc_seqnum
+ 1);
926 thread_add_event(master
, seqnumber_mismatch
, on
, 0,
932 case OSPF6_NEIGHBOR_LOADING
:
933 case OSPF6_NEIGHBOR_FULL
:
934 if (!memcmp(dbdesc
, &on
->dbdesc_last
,
935 sizeof(struct ospf6_dbdesc
))) {
936 /* Duplicated DatabaseDescription causes slave to
938 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV_HDR
))
940 "Duplicated dbdesc causes retransmit");
941 THREAD_OFF(on
->thread_send_dbdesc
);
942 thread_add_event(master
, ospf6_dbdesc_send
, on
, 0,
943 &on
->thread_send_dbdesc
);
948 "DbDesc slave recv: Not duplicate dbdesc in state %s Nbr %s",
949 ospf6_neighbor_state_str
[on
->state
], on
->name
);
950 thread_add_event(master
, seqnumber_mismatch
, on
, 0, NULL
);
958 /* Process LSA headers */
959 for (p
= (char *)((caddr_t
)dbdesc
+ sizeof(struct ospf6_dbdesc
));
960 p
+ sizeof(struct ospf6_lsa_header
) <= OSPF6_MESSAGE_END(oh
);
961 p
+= sizeof(struct ospf6_lsa_header
)) {
962 struct ospf6_lsa
*his
, *mine
;
963 struct ospf6_lsdb
*lsdb
= NULL
;
965 his
= ospf6_lsa_create_headeronly((struct ospf6_lsa_header
*)p
);
967 switch (OSPF6_LSA_SCOPE(his
->header
->type
)) {
968 case OSPF6_SCOPE_LINKLOCAL
:
969 lsdb
= on
->ospf6_if
->lsdb
;
971 case OSPF6_SCOPE_AREA
:
972 lsdb
= on
->ospf6_if
->area
->lsdb
;
975 lsdb
= on
->ospf6_if
->area
->ospf6
->lsdb
;
977 case OSPF6_SCOPE_RESERVED
:
978 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
979 zlog_debug("Ignoring LSA of reserved scope");
980 ospf6_lsa_delete(his
);
984 if (OSPF6_LSA_SCOPE(his
->header
->type
) == OSPF6_SCOPE_AS
985 && (IS_AREA_STUB(on
->ospf6_if
->area
)
986 || IS_AREA_NSSA(on
->ospf6_if
->area
))) {
987 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
988 zlog_debug("E-bit mismatch with LSA Headers");
989 ospf6_lsa_delete(his
);
990 thread_add_event(master
, seqnumber_mismatch
, on
, 0,
995 mine
= ospf6_lsdb_lookup(his
->header
->type
, his
->header
->id
,
996 his
->header
->adv_router
, lsdb
);
997 if (mine
== NULL
|| ospf6_lsa_compare(his
, mine
) < 0) {
998 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
999 zlog_debug("Add request-list: %s", his
->name
);
1000 ospf6_lsdb_add(ospf6_lsa_copy(his
), on
->request_list
);
1002 ospf6_lsa_delete(his
);
1005 assert(p
== OSPF6_MESSAGE_END(oh
));
1007 /* Set sequence number to Master's */
1008 on
->dbdesc_seqnum
= ntohl(dbdesc
->seqnum
);
1010 /* schedule send lsreq */
1011 if (on
->request_list
->count
)
1012 thread_add_event(master
, ospf6_lsreq_send
, on
, 0,
1013 &on
->thread_send_lsreq
);
1015 THREAD_OFF(on
->thread_send_dbdesc
);
1016 thread_add_event(master
, ospf6_dbdesc_send_newone
, on
, 0,
1017 &on
->thread_send_dbdesc
);
1019 /* save last received dbdesc */
1020 memcpy(&on
->dbdesc_last
, dbdesc
, sizeof(struct ospf6_dbdesc
));
1023 static void ospf6_dbdesc_recv(struct in6_addr
*src
, struct in6_addr
*dst
,
1024 struct ospf6_interface
*oi
,
1025 struct ospf6_header
*oh
)
1027 struct ospf6_neighbor
*on
;
1028 struct ospf6_dbdesc
*dbdesc
;
1030 on
= ospf6_neighbor_lookup(oh
->router_id
, oi
);
1032 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV_HDR
))
1033 zlog_debug("Neighbor not found, ignore");
1037 dbdesc
= (struct ospf6_dbdesc
*)((caddr_t
)oh
1038 + sizeof(struct ospf6_header
));
1040 if (((OSPF6_OPT_ISSET_EXT(dbdesc
->options
, OSPF6_OPT_AT
) ==
1042 (oi
->at_data
.flags
== 0)) ||
1043 ((OSPF6_OPT_ISSET_EXT(dbdesc
->options
, OSPF6_OPT_AT
) !=
1045 (oi
->at_data
.flags
!= 0))) {
1046 if (IS_OSPF6_DEBUG_AUTH_RX
)
1048 "VRF %s: IF %s AT-bit mismatch in dbdesc packet",
1049 oi
->interface
->vrf
->name
, oi
->interface
->name
);
1050 oi
->at_data
.rx_drop
++;
1054 /* Interface MTU check */
1055 if (!oi
->mtu_ignore
&& ntohs(dbdesc
->ifmtu
) != oi
->ifmtu
) {
1056 zlog_warn("VRF %s: I/F %s MTU mismatch (my %d rcvd %d)",
1057 oi
->interface
->vrf
->name
, oi
->interface
->name
,
1058 oi
->ifmtu
, ntohs(dbdesc
->ifmtu
));
1062 if (dbdesc
->reserved1
|| dbdesc
->reserved2
) {
1063 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV_HDR
))
1065 "Non-0 reserved field in %s's DbDesc, correct",
1067 dbdesc
->reserved1
= 0;
1068 dbdesc
->reserved2
= 0;
1073 if (ntohl(oh
->router_id
) < ntohl(oi
->area
->ospf6
->router_id
))
1074 ospf6_dbdesc_recv_master(oh
, on
);
1075 else if (ntohl(oi
->area
->ospf6
->router_id
) < ntohl(oh
->router_id
))
1076 ospf6_dbdesc_recv_slave(oh
, on
);
1078 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV_HDR
))
1079 zlog_debug("Can't decide which is master, ignore");
1083 static void ospf6_lsreq_recv(struct in6_addr
*src
, struct in6_addr
*dst
,
1084 struct ospf6_interface
*oi
,
1085 struct ospf6_header
*oh
)
1087 struct ospf6_neighbor
*on
;
1089 struct ospf6_lsreq_entry
*e
;
1090 struct ospf6_lsdb
*lsdb
= NULL
;
1091 struct ospf6_lsa
*lsa
;
1093 on
= ospf6_neighbor_lookup(oh
->router_id
, oi
);
1095 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV_HDR
))
1096 zlog_debug("Neighbor not found, ignore");
1100 if (on
->state
!= OSPF6_NEIGHBOR_EXCHANGE
1101 && on
->state
!= OSPF6_NEIGHBOR_LOADING
1102 && on
->state
!= OSPF6_NEIGHBOR_FULL
) {
1103 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV_HDR
))
1104 zlog_debug("Neighbor state less than Exchange, ignore");
1110 /* Process each request */
1111 for (p
= (char *)((caddr_t
)oh
+ sizeof(struct ospf6_header
));
1112 p
+ sizeof(struct ospf6_lsreq_entry
) <= OSPF6_MESSAGE_END(oh
);
1113 p
+= sizeof(struct ospf6_lsreq_entry
)) {
1114 e
= (struct ospf6_lsreq_entry
*)p
;
1116 switch (OSPF6_LSA_SCOPE(e
->type
)) {
1117 case OSPF6_SCOPE_LINKLOCAL
:
1118 lsdb
= on
->ospf6_if
->lsdb
;
1120 case OSPF6_SCOPE_AREA
:
1121 lsdb
= on
->ospf6_if
->area
->lsdb
;
1123 case OSPF6_SCOPE_AS
:
1124 lsdb
= on
->ospf6_if
->area
->ospf6
->lsdb
;
1127 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
1128 zlog_debug("Ignoring LSA of reserved scope");
1132 /* Find database copy */
1133 lsa
= ospf6_lsdb_lookup(e
->type
, e
->id
, e
->adv_router
, lsdb
);
1136 "Can't find requested lsa [%s Id:%pI4 Adv:%pI4] send badLSReq",
1137 ospf6_lstype_name(e
->type
), &e
->id
,
1139 thread_add_event(master
, bad_lsreq
, on
, 0, NULL
);
1143 ospf6_lsdb_add(ospf6_lsa_copy(lsa
), on
->lsupdate_list
);
1146 assert(p
== OSPF6_MESSAGE_END(oh
));
1148 /* schedule send lsupdate */
1149 THREAD_OFF(on
->thread_send_lsupdate
);
1150 thread_add_event(master
, ospf6_lsupdate_send_neighbor
, on
, 0,
1151 &on
->thread_send_lsupdate
);
1154 /* Verify, that the specified memory area contains exactly N valid IPv6
1155 prefixes as specified by RFC5340, A.4.1. */
1156 static unsigned ospf6_prefixes_examin(
1157 struct ospf6_prefix
*current
, /* start of buffer */
1159 const uint32_t req_num_pfxs
/* always compared with the actual number
1163 uint8_t requested_pfx_bytes
;
1164 uint32_t real_num_pfxs
= 0;
1167 if (length
< OSPF6_PREFIX_MIN_SIZE
) {
1168 zlog_warn("%s: undersized IPv6 prefix header",
1172 /* safe to look deeper */
1173 if (current
->prefix_length
> IPV6_MAX_BITLEN
) {
1174 zlog_warn("%s: invalid PrefixLength (%u bits)",
1175 __func__
, current
->prefix_length
);
1178 /* covers both fixed- and variable-sized fields */
1179 requested_pfx_bytes
=
1180 OSPF6_PREFIX_MIN_SIZE
1181 + OSPF6_PREFIX_SPACE(current
->prefix_length
);
1182 if (requested_pfx_bytes
> length
) {
1183 zlog_warn("%s: undersized IPv6 prefix", __func__
);
1187 length
-= requested_pfx_bytes
;
1188 current
= (struct ospf6_prefix
*)((caddr_t
)current
1189 + requested_pfx_bytes
);
1192 if (real_num_pfxs
!= req_num_pfxs
) {
1194 "%s: IPv6 prefix number mismatch (%u required, %u real)",
1195 __func__
, req_num_pfxs
, real_num_pfxs
);
1201 /* Verify an LSA to have a valid length and dispatch further (where
1202 appropriate) to check if the contents, including nested IPv6 prefixes,
1203 is properly sized/aligned within the LSA. Note that this function gets
1204 LSA type in network byte order, uses in host byte order and passes to
1205 ospf6_lstype_name() in network byte order again. */
1206 static unsigned ospf6_lsa_examin(struct ospf6_lsa_header
*lsah
,
1207 const uint16_t lsalen
,
1208 const uint8_t headeronly
)
1210 struct ospf6_intra_prefix_lsa
*intra_prefix_lsa
;
1211 struct ospf6_as_external_lsa
*as_external_lsa
;
1212 struct ospf6_link_lsa
*link_lsa
;
1213 unsigned exp_length
;
1217 /* In case an additional minimum length constraint is defined for
1219 LSA type, make sure that this constraint is met. */
1220 lsatype
= ntohs(lsah
->type
);
1221 ltindex
= lsatype
& OSPF6_LSTYPE_FCODE_MASK
;
1222 if (ltindex
< OSPF6_LSTYPE_SIZE
&& ospf6_lsa_minlen
[ltindex
]
1223 && lsalen
< ospf6_lsa_minlen
[ltindex
] + OSPF6_LSA_HEADER_SIZE
) {
1224 zlog_warn("%s: undersized (%u B) LSA", __func__
, lsalen
);
1228 case OSPF6_LSTYPE_ROUTER
:
1229 /* RFC5340 A.4.3, LSA header + OSPF6_ROUTER_LSA_MIN_SIZE bytes
1231 by N>=0 interface descriptions. */
1232 if ((lsalen
- OSPF6_LSA_HEADER_SIZE
- OSPF6_ROUTER_LSA_MIN_SIZE
)
1233 % OSPF6_ROUTER_LSDESC_FIX_SIZE
) {
1235 "%s: Router LSA interface description alignment error",
1240 case OSPF6_LSTYPE_NETWORK
:
1241 /* RFC5340 A.4.4, LSA header + OSPF6_NETWORK_LSA_MIN_SIZE bytes
1242 followed by N>=0 attached router descriptions. */
1243 if ((lsalen
- OSPF6_LSA_HEADER_SIZE
1244 - OSPF6_NETWORK_LSA_MIN_SIZE
)
1245 % OSPF6_NETWORK_LSDESC_FIX_SIZE
) {
1247 "%s: Network LSA router description alignment error",
1252 case OSPF6_LSTYPE_INTER_PREFIX
:
1253 /* RFC5340 A.4.5, LSA header + OSPF6_INTER_PREFIX_LSA_MIN_SIZE
1255 followed by 3-4 fields of a single IPv6 prefix. */
1258 return ospf6_prefixes_examin(
1259 (struct ospf6_prefix
1260 *)((caddr_t
)lsah
+ OSPF6_LSA_HEADER_SIZE
1261 + OSPF6_INTER_PREFIX_LSA_MIN_SIZE
),
1262 lsalen
- OSPF6_LSA_HEADER_SIZE
1263 - OSPF6_INTER_PREFIX_LSA_MIN_SIZE
,
1265 case OSPF6_LSTYPE_INTER_ROUTER
:
1266 /* RFC5340 A.4.6, fixed-size LSA. */
1268 > OSPF6_LSA_HEADER_SIZE
+ OSPF6_INTER_ROUTER_LSA_FIX_SIZE
) {
1269 zlog_warn("%s: Inter Router LSA oversized (%u B) LSA",
1274 case OSPF6_LSTYPE_AS_EXTERNAL
: /* RFC5340 A.4.7, same as A.4.8. */
1275 case OSPF6_LSTYPE_TYPE_7
:
1276 /* RFC5340 A.4.8, LSA header + OSPF6_AS_EXTERNAL_LSA_MIN_SIZE
1278 followed by 3-4 fields of IPv6 prefix and 3 conditional LSA
1280 16 bytes of forwarding address, 4 bytes of external route
1282 4 bytes of referenced link state ID. */
1286 (struct ospf6_as_external_lsa
1287 *)((caddr_t
)lsah
+ OSPF6_LSA_HEADER_SIZE
);
1289 OSPF6_LSA_HEADER_SIZE
+ OSPF6_AS_EXTERNAL_LSA_MIN_SIZE
;
1290 /* To find out if the last optional field (Referenced Link State
1292 assumed in this LSA, we need to access fixed fields of the
1294 prefix before ospf6_prefix_examin() confirms its sizing. */
1295 if (exp_length
+ OSPF6_PREFIX_MIN_SIZE
> lsalen
) {
1297 "%s: AS External undersized (%u B) LSA header",
1301 /* forwarding address */
1302 if (CHECK_FLAG(as_external_lsa
->bits_metric
, OSPF6_ASBR_BIT_F
))
1304 /* external route tag */
1305 if (CHECK_FLAG(as_external_lsa
->bits_metric
, OSPF6_ASBR_BIT_T
))
1307 /* referenced link state ID */
1308 if (as_external_lsa
->prefix
.u
._prefix_referenced_lstype
)
1310 /* All the fixed-size fields (mandatory and optional) must fit.
1312 this check does not include any IPv6 prefix fields. */
1313 if (exp_length
> lsalen
) {
1315 "%s: AS External undersized (%u B) LSA header",
1319 /* The last call completely covers the remainder (IPv6 prefix).
1321 return ospf6_prefixes_examin(
1322 (struct ospf6_prefix
1323 *)((caddr_t
)as_external_lsa
1324 + OSPF6_AS_EXTERNAL_LSA_MIN_SIZE
),
1325 lsalen
- exp_length
, 1);
1326 case OSPF6_LSTYPE_LINK
:
1327 /* RFC5340 A.4.9, LSA header + OSPF6_LINK_LSA_MIN_SIZE bytes
1329 by N>=0 IPv6 prefix blocks (with N declared beforehand). */
1332 link_lsa
= (struct ospf6_link_lsa
*)((caddr_t
)lsah
1333 + OSPF6_LSA_HEADER_SIZE
);
1334 return ospf6_prefixes_examin(
1335 (struct ospf6_prefix
*)((caddr_t
)link_lsa
1336 + OSPF6_LINK_LSA_MIN_SIZE
),
1337 lsalen
- OSPF6_LSA_HEADER_SIZE
1338 - OSPF6_LINK_LSA_MIN_SIZE
,
1339 ntohl(link_lsa
->prefix_num
) /* 32 bits */
1341 case OSPF6_LSTYPE_INTRA_PREFIX
:
1342 /* RFC5340 A.4.10, LSA header + OSPF6_INTRA_PREFIX_LSA_MIN_SIZE
1344 followed by N>=0 IPv6 prefixes (with N declared beforehand).
1349 (struct ospf6_intra_prefix_lsa
1350 *)((caddr_t
)lsah
+ OSPF6_LSA_HEADER_SIZE
);
1351 return ospf6_prefixes_examin(
1352 (struct ospf6_prefix
1353 *)((caddr_t
)intra_prefix_lsa
1354 + OSPF6_INTRA_PREFIX_LSA_MIN_SIZE
),
1355 lsalen
- OSPF6_LSA_HEADER_SIZE
1356 - OSPF6_INTRA_PREFIX_LSA_MIN_SIZE
,
1357 ntohs(intra_prefix_lsa
->prefix_num
) /* 16 bits */
1359 case OSPF6_LSTYPE_GRACE_LSA
:
1360 if (lsalen
< OSPF6_LSA_HEADER_SIZE
+ GRACE_PERIOD_TLV_SIZE
1361 + GRACE_RESTART_REASON_TLV_SIZE
) {
1362 if (IS_DEBUG_OSPF6_GR
)
1363 zlog_debug("%s: Undersized GraceLSA.",
1368 /* No additional validation is possible for unknown LSA types, which are
1369 themselves valid in OPSFv3, hence the default decision is to accept.
1374 /* Verify if the provided input buffer is a valid sequence of LSAs. This
1375 includes verification of LSA blocks length/alignment and dispatching
1376 of deeper-level checks. */
1378 ospf6_lsaseq_examin(struct ospf6_lsa_header
*lsah
, /* start of buffered data */
1379 size_t length
, const uint8_t headeronly
,
1380 /* When declared_num_lsas is not 0, compare it to the real
1382 and treat the difference as an error. */
1383 const uint32_t declared_num_lsas
)
1385 uint32_t counted_lsas
= 0;
1389 if (length
< OSPF6_LSA_HEADER_SIZE
) {
1391 "%s: undersized (%zu B) trailing (#%u) LSA header",
1392 __func__
, length
, counted_lsas
);
1395 /* save on ntohs() calls here and in the LSA validator */
1396 lsalen
= OSPF6_LSA_SIZE(lsah
);
1397 if (lsalen
< OSPF6_LSA_HEADER_SIZE
) {
1399 "%s: malformed LSA header #%u, declared length is %u B",
1400 __func__
, counted_lsas
, lsalen
);
1404 /* less checks here and in ospf6_lsa_examin() */
1405 if (MSG_OK
!= ospf6_lsa_examin(lsah
, lsalen
, 1)) {
1407 "%s: anomaly in header-only %s LSA #%u",
1408 __func__
, ospf6_lstype_name(lsah
->type
),
1412 lsah
= (struct ospf6_lsa_header
1414 + OSPF6_LSA_HEADER_SIZE
);
1415 length
-= OSPF6_LSA_HEADER_SIZE
;
1417 /* make sure the input buffer is deep enough before
1419 if (lsalen
> length
) {
1421 "%s: anomaly in %s LSA #%u: declared length is %u B, buffered length is %zu B",
1422 __func__
, ospf6_lstype_name(lsah
->type
),
1423 counted_lsas
, lsalen
, length
);
1426 if (MSG_OK
!= ospf6_lsa_examin(lsah
, lsalen
, 0)) {
1427 zlog_warn("%s: anomaly in %s LSA #%u", __func__
,
1428 ospf6_lstype_name(lsah
->type
),
1432 lsah
= (struct ospf6_lsa_header
*)((caddr_t
)lsah
1439 if (declared_num_lsas
&& counted_lsas
!= declared_num_lsas
) {
1440 zlog_warn("%s: #LSAs declared (%u) does not match actual (%u)",
1441 __func__
, declared_num_lsas
, counted_lsas
);
1447 /* Verify a complete OSPF packet for proper sizing/alignment. */
1448 static unsigned ospf6_packet_examin(struct ospf6_header
*oh
,
1449 const unsigned bytesonwire
)
1451 struct ospf6_lsupdate
*lsupd
;
1454 /* length, 1st approximation */
1455 if (bytesonwire
< OSPF6_HEADER_SIZE
) {
1456 zlog_warn("%s: undersized (%u B) packet", __func__
,
1461 /* Now it is safe to access header fields. */
1462 if (bytesonwire
!= ntohs(oh
->length
)) {
1463 zlog_warn("%s: %s packet length error (%u real, %u declared)",
1464 __func__
, ospf6_message_type(oh
->type
), bytesonwire
,
1470 if (oh
->version
!= OSPFV3_VERSION
) {
1471 zlog_warn("%s: invalid (%u) protocol version", __func__
,
1475 /* length, 2nd approximation */
1476 if (oh
->type
< OSPF6_MESSAGE_TYPE_ALL
&& ospf6_packet_minlen
[oh
->type
]
1478 < OSPF6_HEADER_SIZE
+ ospf6_packet_minlen
[oh
->type
]) {
1479 zlog_warn("%s: undersized (%u B) %s packet", __func__
,
1480 bytesonwire
, ospf6_message_type(oh
->type
));
1483 /* type-specific deeper validation */
1485 case OSPF6_MESSAGE_TYPE_HELLO
:
1486 /* RFC5340 A.3.2, packet header + OSPF6_HELLO_MIN_SIZE bytes
1488 by N>=0 router-IDs. */
1490 == (bytesonwire
- OSPF6_HEADER_SIZE
- OSPF6_HELLO_MIN_SIZE
)
1493 zlog_warn("%s: alignment error in %s packet", __func__
,
1494 ospf6_message_type(oh
->type
));
1496 case OSPF6_MESSAGE_TYPE_DBDESC
:
1497 /* RFC5340 A.3.3, packet header + OSPF6_DB_DESC_MIN_SIZE bytes
1499 by N>=0 header-only LSAs. */
1500 test
= ospf6_lsaseq_examin(
1501 (struct ospf6_lsa_header
*)((caddr_t
)oh
1503 + OSPF6_DB_DESC_MIN_SIZE
),
1504 bytesonwire
- OSPF6_HEADER_SIZE
1505 - OSPF6_DB_DESC_MIN_SIZE
,
1508 case OSPF6_MESSAGE_TYPE_LSREQ
:
1509 /* RFC5340 A.3.4, packet header + N>=0 LS description blocks. */
1511 == (bytesonwire
- OSPF6_HEADER_SIZE
- OSPF6_LS_REQ_MIN_SIZE
)
1512 % OSPF6_LSREQ_LSDESC_FIX_SIZE
)
1514 zlog_warn("%s: alignment error in %s packet", __func__
,
1515 ospf6_message_type(oh
->type
));
1517 case OSPF6_MESSAGE_TYPE_LSUPDATE
:
1518 /* RFC5340 A.3.5, packet header + OSPF6_LS_UPD_MIN_SIZE bytes
1520 by N>=0 full LSAs (with N declared beforehand). */
1521 lsupd
= (struct ospf6_lsupdate
*)((caddr_t
)oh
1522 + OSPF6_HEADER_SIZE
);
1523 test
= ospf6_lsaseq_examin(
1524 (struct ospf6_lsa_header
*)((caddr_t
)lsupd
1525 + OSPF6_LS_UPD_MIN_SIZE
),
1526 bytesonwire
- OSPF6_HEADER_SIZE
- OSPF6_LS_UPD_MIN_SIZE
,
1527 0, ntohl(lsupd
->lsa_number
) /* 32 bits */
1530 case OSPF6_MESSAGE_TYPE_LSACK
:
1531 /* RFC5340 A.3.6, packet header + N>=0 header-only LSAs. */
1532 test
= ospf6_lsaseq_examin(
1533 (struct ospf6_lsa_header
*)((caddr_t
)oh
1535 + OSPF6_LS_ACK_MIN_SIZE
),
1536 bytesonwire
- OSPF6_HEADER_SIZE
- OSPF6_LS_ACK_MIN_SIZE
,
1540 zlog_warn("%s: invalid (%u) message type", __func__
, oh
->type
);
1544 zlog_warn("%s: anomaly in %s packet", __func__
,
1545 ospf6_message_type(oh
->type
));
1549 /* Verify particular fields of otherwise correct received OSPF packet to
1550 meet the requirements of RFC. */
1551 static int ospf6_rxpacket_examin(struct ospf6_interface
*oi
,
1552 struct ospf6_header
*oh
,
1553 const unsigned bytesonwire
)
1556 if (MSG_OK
!= ospf6_packet_examin(oh
, bytesonwire
))
1560 if (oh
->area_id
!= oi
->area
->area_id
) {
1561 if (oh
->area_id
== OSPF_AREA_BACKBONE
)
1563 "VRF %s: I/F %s Message may be via Virtual Link: not supported",
1564 oi
->interface
->vrf
->name
, oi
->interface
->name
);
1567 "VRF %s: I/F %s Area-ID mismatch (my %pI4, rcvd %pI4)",
1568 oi
->interface
->vrf
->name
, oi
->interface
->name
,
1569 &oi
->area
->area_id
, &oh
->area_id
);
1573 /* Instance-ID check */
1574 if (oh
->instance_id
!= oi
->instance_id
) {
1576 "VRF %s: I/F %s Instance-ID mismatch (my %u, rcvd %u)",
1577 oi
->interface
->vrf
->name
, oi
->interface
->name
,
1578 oi
->instance_id
, oh
->instance_id
);
1582 /* Router-ID check */
1583 if (oh
->router_id
== oi
->area
->ospf6
->router_id
) {
1584 zlog_warn("VRF %s: I/F %s Duplicate Router-ID (%pI4)",
1585 oi
->interface
->vrf
->name
, oi
->interface
->name
,
1592 static void ospf6_lsupdate_recv(struct in6_addr
*src
, struct in6_addr
*dst
,
1593 struct ospf6_interface
*oi
,
1594 struct ospf6_header
*oh
)
1596 struct ospf6_neighbor
*on
;
1597 struct ospf6_lsupdate
*lsupdate
;
1600 on
= ospf6_neighbor_lookup(oh
->router_id
, oi
);
1602 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV_HDR
))
1603 zlog_debug("Neighbor not found, ignore");
1607 if (on
->state
!= OSPF6_NEIGHBOR_EXCHANGE
1608 && on
->state
!= OSPF6_NEIGHBOR_LOADING
1609 && on
->state
!= OSPF6_NEIGHBOR_FULL
) {
1610 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV_HDR
))
1611 zlog_debug("Neighbor state less than Exchange, ignore");
1615 lsupdate
= (struct ospf6_lsupdate
*)((caddr_t
)oh
1616 + sizeof(struct ospf6_header
));
1621 for (p
= (char *)((caddr_t
)lsupdate
+ sizeof(struct ospf6_lsupdate
));
1622 p
< OSPF6_MESSAGE_END(oh
)
1623 && p
+ OSPF6_LSA_SIZE(p
) <= OSPF6_MESSAGE_END(oh
);
1624 p
+= OSPF6_LSA_SIZE(p
)) {
1625 ospf6_receive_lsa(on
, (struct ospf6_lsa_header
*)p
);
1628 assert(p
== OSPF6_MESSAGE_END(oh
));
1631 static void ospf6_lsack_recv(struct in6_addr
*src
, struct in6_addr
*dst
,
1632 struct ospf6_interface
*oi
,
1633 struct ospf6_header
*oh
)
1635 struct ospf6_neighbor
*on
;
1637 struct ospf6_lsa
*his
, *mine
;
1638 struct ospf6_lsdb
*lsdb
= NULL
;
1640 assert(oh
->type
== OSPF6_MESSAGE_TYPE_LSACK
);
1642 on
= ospf6_neighbor_lookup(oh
->router_id
, oi
);
1644 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV_HDR
))
1645 zlog_debug("Neighbor not found, ignore");
1649 if (on
->state
!= OSPF6_NEIGHBOR_EXCHANGE
1650 && on
->state
!= OSPF6_NEIGHBOR_LOADING
1651 && on
->state
!= OSPF6_NEIGHBOR_FULL
) {
1652 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV_HDR
))
1653 zlog_debug("Neighbor state less than Exchange, ignore");
1659 for (p
= (char *)((caddr_t
)oh
+ sizeof(struct ospf6_header
));
1660 p
+ sizeof(struct ospf6_lsa_header
) <= OSPF6_MESSAGE_END(oh
);
1661 p
+= sizeof(struct ospf6_lsa_header
)) {
1662 his
= ospf6_lsa_create_headeronly((struct ospf6_lsa_header
*)p
);
1664 switch (OSPF6_LSA_SCOPE(his
->header
->type
)) {
1665 case OSPF6_SCOPE_LINKLOCAL
:
1666 lsdb
= on
->ospf6_if
->lsdb
;
1668 case OSPF6_SCOPE_AREA
:
1669 lsdb
= on
->ospf6_if
->area
->lsdb
;
1671 case OSPF6_SCOPE_AS
:
1672 lsdb
= on
->ospf6_if
->area
->ospf6
->lsdb
;
1674 case OSPF6_SCOPE_RESERVED
:
1675 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
1676 zlog_debug("Ignoring LSA of reserved scope");
1677 ospf6_lsa_delete(his
);
1681 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
1682 zlog_debug("%s acknowledged by %s", his
->name
,
1685 /* Find database copy */
1686 mine
= ospf6_lsdb_lookup(his
->header
->type
, his
->header
->id
,
1687 his
->header
->adv_router
, lsdb
);
1689 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
1690 zlog_debug("No database copy");
1691 ospf6_lsa_delete(his
);
1695 /* Check if the LSA is on his retrans-list */
1696 mine
= ospf6_lsdb_lookup(his
->header
->type
, his
->header
->id
,
1697 his
->header
->adv_router
,
1700 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
1701 zlog_debug("Not on %s's retrans-list",
1703 ospf6_lsa_delete(his
);
1707 if (ospf6_lsa_compare(his
, mine
) != 0) {
1708 /* Log this questionable acknowledgement,
1709 and examine the next one. */
1710 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
1711 zlog_debug("Questionable acknowledgement");
1712 ospf6_lsa_delete(his
);
1716 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
1718 "Acknowledged, remove from %s's retrans-list",
1721 ospf6_decrement_retrans_count(mine
);
1722 if (OSPF6_LSA_IS_MAXAGE(mine
))
1723 ospf6_maxage_remove(on
->ospf6_if
->area
->ospf6
);
1724 ospf6_lsdb_remove(mine
, on
->retrans_list
);
1725 ospf6_lsa_delete(his
);
1728 assert(p
== OSPF6_MESSAGE_END(oh
));
1731 static uint8_t *recvbuf
= NULL
;
1732 static uint8_t *sendbuf
= NULL
;
1733 static unsigned int iobuflen
= 0;
1735 int ospf6_iobuf_size(unsigned int size
)
1737 /* NB: there was previously code here that tried to dynamically size
1738 * the buffer for whatever we see in MTU on interfaces. Which is
1739 * _unconditionally wrong_ - we can always receive fragmented IPv6
1740 * up to the regular 64k length limit. (No jumbograms, thankfully.)
1744 /* the + 128 is to have some runway at the end */
1745 size_t alloc_size
= 65536 + 128;
1747 assert(!recvbuf
&& !sendbuf
);
1749 recvbuf
= XMALLOC(MTYPE_OSPF6_MESSAGE
, alloc_size
);
1750 sendbuf
= XMALLOC(MTYPE_OSPF6_MESSAGE
, alloc_size
);
1751 iobuflen
= alloc_size
;
1757 void ospf6_message_terminate(void)
1759 XFREE(MTYPE_OSPF6_MESSAGE
, recvbuf
);
1760 XFREE(MTYPE_OSPF6_MESSAGE
, sendbuf
);
1765 enum ospf6_read_return_enum
{
1767 OSPF6_READ_CONTINUE
,
1770 static int ospf6_read_helper(int sockfd
, struct ospf6
*ospf6
)
1773 struct in6_addr src
, dst
;
1775 struct iovec iovector
[2];
1776 struct ospf6_interface
*oi
;
1777 struct ospf6_header
*oh
;
1778 enum ospf6_auth_err ret
= OSPF6_AUTH_PROCESS_NORMAL
;
1779 uint32_t at_len
= 0;
1780 uint32_t lls_len
= 0;
1783 memset(&src
, 0, sizeof(src
));
1784 memset(&dst
, 0, sizeof(dst
));
1786 iovector
[0].iov_base
= recvbuf
;
1787 iovector
[0].iov_len
= iobuflen
;
1788 iovector
[1].iov_base
= NULL
;
1789 iovector
[1].iov_len
= 0;
1791 /* receive message */
1792 len
= ospf6_recvmsg(&src
, &dst
, &ifindex
, iovector
, sockfd
);
1794 return OSPF6_READ_ERROR
;
1796 if ((uint
)len
> iobuflen
) {
1797 flog_err(EC_LIB_DEVELOPMENT
, "Excess message read");
1798 return OSPF6_READ_ERROR
;
1801 /* ensure some zeroes past the end, just as a security precaution */
1802 memset(recvbuf
+ len
, 0, MIN(128, iobuflen
- len
));
1804 oi
= ospf6_interface_lookup_by_ifindex(ifindex
, ospf6
->vrf_id
);
1805 if (oi
== NULL
|| oi
->area
== NULL
1806 || CHECK_FLAG(oi
->flag
, OSPF6_INTERFACE_DISABLE
)) {
1807 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN
,
1809 zlog_debug("Message received on disabled interface");
1810 return OSPF6_READ_CONTINUE
;
1812 if (CHECK_FLAG(oi
->flag
, OSPF6_INTERFACE_PASSIVE
)) {
1813 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN
,
1815 zlog_debug("%s: Ignore message on passive interface %s",
1816 __func__
, oi
->interface
->name
);
1817 return OSPF6_READ_CONTINUE
;
1821 * Drop packet destined to another VRF.
1822 * This happens when raw_l3mdev_accept is set to 1.
1824 if (ospf6
->vrf_id
!= oi
->interface
->vrf
->vrf_id
)
1825 return OSPF6_READ_CONTINUE
;
1827 oh
= (struct ospf6_header
*)recvbuf
;
1828 ret
= ospf6_auth_validate_pkt(oi
, (uint32_t *)&len
, oh
, &at_len
,
1830 if (ret
== OSPF6_AUTH_VALIDATE_SUCCESS
) {
1831 ret
= ospf6_auth_check_digest(oh
, oi
, &src
, lls_len
);
1832 if (ret
== OSPF6_AUTH_VALIDATE_FAILURE
) {
1833 if (IS_OSPF6_DEBUG_AUTH_RX
)
1835 "RECV[%s]: OSPF packet auth digest miss-match on %s",
1836 oi
->interface
->name
,
1837 ospf6_message_type(oh
->type
));
1838 oi
->at_data
.rx_drop
++;
1839 return OSPF6_READ_CONTINUE
;
1841 } else if (ret
== OSPF6_AUTH_VALIDATE_FAILURE
) {
1842 oi
->at_data
.rx_drop
++;
1843 return OSPF6_READ_CONTINUE
;
1846 if (ospf6_rxpacket_examin(oi
, oh
, len
) != MSG_OK
)
1847 return OSPF6_READ_CONTINUE
;
1849 /* Being here means, that no sizing/alignment issues were detected in
1850 the input packet. This renders the additional checks performed below
1851 and also in the type-specific dispatching functions a dead code,
1852 which can be dismissed in a cleanup-focused review round later. */
1855 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV_HDR
)) {
1856 zlog_debug("%s received on %s", ospf6_message_type(oh
->type
),
1857 oi
->interface
->name
);
1858 zlog_debug(" src: %pI6", &src
);
1859 zlog_debug(" dst: %pI6", &dst
);
1862 case OSPF6_MESSAGE_TYPE_HELLO
:
1863 ospf6_hello_print(oh
, OSPF6_ACTION_RECV
);
1865 case OSPF6_MESSAGE_TYPE_DBDESC
:
1866 ospf6_dbdesc_print(oh
, OSPF6_ACTION_RECV
);
1868 case OSPF6_MESSAGE_TYPE_LSREQ
:
1869 ospf6_lsreq_print(oh
, OSPF6_ACTION_RECV
);
1871 case OSPF6_MESSAGE_TYPE_LSUPDATE
:
1872 ospf6_lsupdate_print(oh
, OSPF6_ACTION_RECV
);
1874 case OSPF6_MESSAGE_TYPE_LSACK
:
1875 ospf6_lsack_print(oh
, OSPF6_ACTION_RECV
);
1881 if ((at_len
!= 0) && IS_OSPF6_DEBUG_AUTH_RX
)
1882 ospf6_auth_hdr_dump_recv(oh
, (len
+ at_len
+ lls_len
),
1887 case OSPF6_MESSAGE_TYPE_HELLO
:
1888 ospf6_hello_recv(&src
, &dst
, oi
, oh
);
1891 case OSPF6_MESSAGE_TYPE_DBDESC
:
1892 ospf6_dbdesc_recv(&src
, &dst
, oi
, oh
);
1895 case OSPF6_MESSAGE_TYPE_LSREQ
:
1896 ospf6_lsreq_recv(&src
, &dst
, oi
, oh
);
1899 case OSPF6_MESSAGE_TYPE_LSUPDATE
:
1900 ospf6_lsupdate_recv(&src
, &dst
, oi
, oh
);
1903 case OSPF6_MESSAGE_TYPE_LSACK
:
1904 ospf6_lsack_recv(&src
, &dst
, oi
, oh
);
1911 return OSPF6_READ_CONTINUE
;
1914 void ospf6_receive(struct thread
*thread
)
1917 struct ospf6
*ospf6
;
1920 /* add next read thread */
1921 ospf6
= THREAD_ARG(thread
);
1922 sockfd
= THREAD_FD(thread
);
1924 thread_add_read(master
, ospf6_receive
, ospf6
, ospf6
->fd
,
1925 &ospf6
->t_ospf6_receive
);
1927 while (count
< ospf6
->write_oi_count
) {
1929 switch (ospf6_read_helper(sockfd
, ospf6
)) {
1930 case OSPF6_READ_ERROR
:
1932 case OSPF6_READ_CONTINUE
:
1938 static void ospf6_fill_hdr_checksum(struct ospf6_interface
*oi
,
1939 struct ospf6_packet
*op
)
1941 struct ipv6_ph ph
= {};
1942 struct ospf6_header
*oh
;
1943 void *offset
= NULL
;
1945 if (oi
->at_data
.flags
!= 0)
1948 memcpy(&ph
.src
, oi
->linklocal_addr
, sizeof(struct in6_addr
));
1949 memcpy(&ph
.dst
, &op
->dst
, sizeof(struct in6_addr
));
1950 ph
.ulpl
= htonl(op
->length
);
1951 ph
.next_hdr
= IPPROTO_OSPFIGP
;
1953 /* Suppress static analysis warnings about accessing icmp6 oob */
1954 oh
= (struct ospf6_header
*)STREAM_DATA(op
->s
);
1956 oh
->checksum
= in_cksum_with_ph6(&ph
, offset
, op
->length
);
1959 static void ospf6_make_header(uint8_t type
, struct ospf6_interface
*oi
,
1962 struct ospf6_header
*oh
;
1964 oh
= (struct ospf6_header
*)STREAM_DATA(s
);
1966 oh
->version
= (uint8_t)OSPFV3_VERSION
;
1970 oh
->router_id
= oi
->area
->ospf6
->router_id
;
1971 oh
->area_id
= oi
->area
->area_id
;
1973 oh
->instance_id
= oi
->instance_id
;
1976 stream_forward_endp(s
, OSPF6_HEADER_SIZE
);
1979 static void ospf6_fill_header(struct ospf6_interface
*oi
, struct stream
*s
,
1982 struct ospf6_header
*oh
;
1984 oh
= (struct ospf6_header
*)STREAM_DATA(s
);
1986 oh
->length
= htons(length
);
1989 static void ospf6_fill_lsupdate_header(struct stream
*s
, uint32_t lsa_num
)
1991 struct ospf6_header
*oh
;
1992 struct ospf6_lsupdate
*lsu
;
1994 oh
= (struct ospf6_header
*)STREAM_DATA(s
);
1996 lsu
= (struct ospf6_lsupdate
*)((caddr_t
)oh
1997 + sizeof(struct ospf6_header
));
1998 lsu
->lsa_number
= htonl(lsa_num
);
2001 static void ospf6_auth_trailer_copy_keychain_key(struct ospf6_interface
*oi
)
2003 char *keychain_name
= NULL
;
2004 struct keychain
*keychain
= NULL
;
2005 struct key
*key
= NULL
;
2007 keychain_name
= oi
->at_data
.keychain
;
2008 keychain
= keychain_lookup(keychain_name
);
2010 key
= key_lookup_for_send(keychain
);
2011 if (key
&& key
->string
&&
2012 key
->hash_algo
!= KEYCHAIN_ALGO_NULL
) {
2013 /* storing the values so that further
2014 * lookup can be avoided. after
2015 * processing the digest need to reset
2018 oi
->at_data
.hash_algo
= key
->hash_algo
;
2019 if (oi
->at_data
.auth_key
)
2020 XFREE(MTYPE_OSPF6_AUTH_MANUAL_KEY
,
2021 oi
->at_data
.auth_key
);
2022 oi
->at_data
.auth_key
= XSTRDUP(
2023 MTYPE_OSPF6_AUTH_MANUAL_KEY
, key
->string
);
2024 oi
->at_data
.key_id
= key
->index
;
2025 SET_FLAG(oi
->at_data
.flags
,
2026 OSPF6_AUTH_TRAILER_KEYCHAIN_VALID
);
2031 static uint16_t ospf6_packet_max(struct ospf6_interface
*oi
)
2033 uint16_t at_len
= 0;
2035 assert(oi
->ifmtu
> sizeof(struct ip6_hdr
));
2037 if (oi
->at_data
.flags
!= 0) {
2038 if (CHECK_FLAG(oi
->at_data
.flags
, OSPF6_AUTH_TRAILER_KEYCHAIN
))
2039 ospf6_auth_trailer_copy_keychain_key(oi
);
2041 at_len
+= OSPF6_AUTH_HDR_MIN_SIZE
;
2042 at_len
+= keychain_get_hash_len(oi
->at_data
.hash_algo
);
2043 return oi
->ifmtu
- (sizeof(struct ip6_hdr
)) - at_len
;
2046 return oi
->ifmtu
- (sizeof(struct ip6_hdr
));
2049 static uint16_t ospf6_make_hello(struct ospf6_interface
*oi
, struct stream
*s
)
2051 struct listnode
*node
, *nnode
;
2052 struct ospf6_neighbor
*on
;
2053 uint16_t length
= OSPF6_HELLO_MIN_SIZE
;
2054 uint8_t options1
= oi
->area
->options
[1];
2056 if (oi
->at_data
.flags
!= 0)
2057 options1
|= OSPF6_OPT_AT
;
2059 stream_putl(s
, oi
->interface
->ifindex
);
2060 stream_putc(s
, oi
->priority
);
2061 stream_putc(s
, oi
->area
->options
[0]);
2062 stream_putc(s
, options1
);
2063 stream_putc(s
, oi
->area
->options
[2]);
2064 stream_putw(s
, oi
->hello_interval
);
2065 stream_putw(s
, oi
->dead_interval
);
2066 stream_put_ipv4(s
, oi
->drouter
);
2067 stream_put_ipv4(s
, oi
->bdrouter
);
2069 for (ALL_LIST_ELEMENTS(oi
->neighbor_list
, node
, nnode
, on
)) {
2070 if (on
->state
< OSPF6_NEIGHBOR_INIT
)
2073 if ((length
+ sizeof(uint32_t) + OSPF6_HEADER_SIZE
)
2074 > ospf6_packet_max(oi
)) {
2075 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_HELLO
,
2078 "sending Hello message: exceeds I/F MTU");
2082 stream_put_ipv4(s
, on
->router_id
);
2083 length
+= sizeof(uint32_t);
2089 static void ospf6_write(struct thread
*thread
)
2091 struct ospf6
*ospf6
= THREAD_ARG(thread
);
2092 struct ospf6_interface
*oi
;
2093 struct ospf6_header
*oh
;
2094 struct ospf6_packet
*op
;
2095 struct listnode
*node
;
2096 struct iovec iovector
[2];
2099 int64_t latency
= 0;
2100 struct timeval timestamp
;
2101 uint16_t at_len
= 0;
2103 if (ospf6
->fd
< 0) {
2104 zlog_warn("ospf6_write failed to send, fd %d", ospf6
->fd
);
2108 node
= listhead(ospf6
->oi_write_q
);
2110 oi
= listgetdata(node
);
2112 while ((pkt_count
< ospf6
->write_oi_count
) && oi
) {
2113 op
= ospf6_fifo_head(oi
->obuf
);
2115 assert(op
->length
>= OSPF6_HEADER_SIZE
);
2117 iovector
[0].iov_base
= (caddr_t
)stream_pnt(op
->s
);
2118 iovector
[0].iov_len
= op
->length
;
2119 iovector
[1].iov_base
= NULL
;
2120 iovector
[1].iov_len
= 0;
2122 oh
= (struct ospf6_header
*)STREAM_DATA(op
->s
);
2124 if (oi
->at_data
.flags
!= 0) {
2125 at_len
= ospf6_auth_len_get(oi
);
2127 iovector
[0].iov_len
=
2128 ntohs(oh
->length
) + at_len
;
2129 ospf6_auth_digest_send(oi
->linklocal_addr
, oi
,
2131 iovector
[0].iov_len
);
2133 iovector
[0].iov_len
= ntohs(oh
->length
);
2136 iovector
[0].iov_len
= ntohs(oh
->length
);
2139 len
= ospf6_sendmsg(oi
->linklocal_addr
, &op
->dst
,
2140 oi
->interface
->ifindex
, iovector
,
2143 if (len
!= (op
->length
+ (int)at_len
))
2144 flog_err(EC_LIB_DEVELOPMENT
,
2145 "Could not send entire message");
2147 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, SEND_HDR
)) {
2148 zlog_debug("%s send on %s",
2149 ospf6_message_type(oh
->type
),
2150 oi
->interface
->name
);
2151 zlog_debug(" src: %pI6", oi
->linklocal_addr
);
2152 zlog_debug(" dst: %pI6", &op
->dst
);
2154 case OSPF6_MESSAGE_TYPE_HELLO
:
2155 ospf6_hello_print(oh
, OSPF6_ACTION_SEND
);
2157 case OSPF6_MESSAGE_TYPE_DBDESC
:
2158 ospf6_dbdesc_print(oh
, OSPF6_ACTION_SEND
);
2160 case OSPF6_MESSAGE_TYPE_LSREQ
:
2161 ospf6_lsreq_print(oh
, OSPF6_ACTION_SEND
);
2163 case OSPF6_MESSAGE_TYPE_LSUPDATE
:
2164 ospf6_lsupdate_print(oh
, OSPF6_ACTION_SEND
);
2166 case OSPF6_MESSAGE_TYPE_LSACK
:
2167 ospf6_lsack_print(oh
, OSPF6_ACTION_SEND
);
2170 zlog_debug("Unknown message");
2176 case OSPF6_MESSAGE_TYPE_HELLO
:
2177 monotime(×tamp
);
2179 latency
= monotime_since(&oi
->last_hello
, NULL
)
2180 - ((int64_t)oi
->hello_interval
2183 /* log if latency exceeds the hello period */
2184 if (latency
> ((int64_t)oi
->hello_interval
* 1000000))
2185 zlog_warn("%s hello TX high latency %" PRId64
2188 oi
->last_hello
= timestamp
;
2191 case OSPF6_MESSAGE_TYPE_DBDESC
:
2194 case OSPF6_MESSAGE_TYPE_LSREQ
:
2197 case OSPF6_MESSAGE_TYPE_LSUPDATE
:
2200 case OSPF6_MESSAGE_TYPE_LSACK
:
2204 zlog_debug("Unknown message");
2209 if ((oi
->at_data
.flags
!= 0) &&
2210 (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, SEND_HDR
)) &&
2211 (IS_OSPF6_DEBUG_AUTH_TX
))
2212 ospf6_auth_hdr_dump_send(oh
, iovector
[0].iov_len
);
2214 /* initialize at_len to 0 for next packet */
2217 /* Now delete packet from queue. */
2218 ospf6_packet_delete(oi
);
2220 /* Move this interface to the tail of write_q to
2221 serve everyone in a round robin fashion */
2222 list_delete_node(ospf6
->oi_write_q
, node
);
2223 if (ospf6_fifo_head(oi
->obuf
) == NULL
) {
2227 listnode_add(ospf6
->oi_write_q
, oi
);
2230 /* Setup to service from the head of the queue again */
2231 if (!list_isempty(ospf6
->oi_write_q
)) {
2232 node
= listhead(ospf6
->oi_write_q
);
2233 oi
= listgetdata(node
);
2237 /* If packets still remain in queue, call write thread. */
2238 if (!list_isempty(ospf6
->oi_write_q
))
2239 thread_add_write(master
, ospf6_write
, ospf6
, ospf6
->fd
,
2243 void ospf6_hello_send(struct thread
*thread
)
2245 struct ospf6_interface
*oi
;
2246 struct ospf6_packet
*op
;
2247 uint16_t length
= OSPF6_HEADER_SIZE
;
2249 oi
= (struct ospf6_interface
*)THREAD_ARG(thread
);
2251 if (oi
->state
<= OSPF6_INTERFACE_DOWN
) {
2252 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_HELLO
, SEND_HDR
))
2253 zlog_debug("Unable to send Hello on down interface %s",
2254 oi
->interface
->name
);
2258 op
= ospf6_packet_new(oi
->ifmtu
);
2260 ospf6_make_header(OSPF6_MESSAGE_TYPE_HELLO
, oi
, op
->s
);
2262 /* Prepare OSPF Hello body */
2263 length
+= ospf6_make_hello(oi
, op
->s
);
2264 if (length
== OSPF6_HEADER_SIZE
) {
2265 /* Hello overshooting MTU */
2266 ospf6_packet_free(op
);
2270 /* Fill OSPF header. */
2271 ospf6_fill_header(oi
, op
->s
, length
);
2273 /* Set packet length. */
2274 op
->length
= length
;
2276 op
->dst
= allspfrouters6
;
2278 ospf6_fill_hdr_checksum(oi
, op
);
2280 /* Add packet to the top of the interface output queue, so that they
2281 * can't get delayed by things like long queues of LS Update packets
2283 ospf6_packet_add_top(oi
, op
);
2285 /* set next thread */
2286 thread_add_timer(master
, ospf6_hello_send
, oi
, oi
->hello_interval
,
2287 &oi
->thread_send_hello
);
2289 OSPF6_MESSAGE_WRITE_ON(oi
);
2292 static uint16_t ospf6_make_dbdesc(struct ospf6_neighbor
*on
, struct stream
*s
)
2294 uint16_t length
= OSPF6_DB_DESC_MIN_SIZE
;
2295 struct ospf6_lsa
*lsa
, *lsanext
;
2296 uint8_t options1
= on
->ospf6_if
->area
->options
[1];
2298 if (on
->ospf6_if
->at_data
.flags
!= 0)
2299 options1
|= OSPF6_OPT_AT
;
2301 /* if this is initial one, initialize sequence number for DbDesc */
2302 if (CHECK_FLAG(on
->dbdesc_bits
, OSPF6_DBDESC_IBIT
)
2303 && (on
->dbdesc_seqnum
== 0)) {
2304 on
->dbdesc_seqnum
= frr_sequence32_next();
2308 stream_putc(s
, 0); /* reserved 1 */
2309 stream_putc(s
, on
->ospf6_if
->area
->options
[0]);
2310 stream_putc(s
, options1
);
2311 stream_putc(s
, on
->ospf6_if
->area
->options
[2]);
2312 stream_putw(s
, on
->ospf6_if
->ifmtu
);
2313 stream_putc(s
, 0); /* reserved 2 */
2314 stream_putc(s
, on
->dbdesc_bits
);
2315 stream_putl(s
, on
->dbdesc_seqnum
);
2317 /* if this is not initial one, set LSA headers in dbdesc */
2318 if (!CHECK_FLAG(on
->dbdesc_bits
, OSPF6_DBDESC_IBIT
)) {
2319 for (ALL_LSDB(on
->dbdesc_list
, lsa
, lsanext
)) {
2320 ospf6_lsa_age_update_to_send(lsa
,
2321 on
->ospf6_if
->transdelay
);
2324 if ((length
+ sizeof(struct ospf6_lsa_header
)
2325 + OSPF6_HEADER_SIZE
)
2326 > ospf6_packet_max(on
->ospf6_if
)) {
2327 ospf6_lsa_unlock(lsa
);
2329 ospf6_lsa_unlock(lsanext
);
2332 stream_put(s
, lsa
->header
,
2333 sizeof(struct ospf6_lsa_header
));
2334 length
+= sizeof(struct ospf6_lsa_header
);
2340 void ospf6_dbdesc_send(struct thread
*thread
)
2342 struct ospf6_neighbor
*on
;
2343 uint16_t length
= OSPF6_HEADER_SIZE
;
2344 struct ospf6_packet
*op
;
2346 on
= (struct ospf6_neighbor
*)THREAD_ARG(thread
);
2348 if (on
->state
< OSPF6_NEIGHBOR_EXSTART
) {
2349 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_DBDESC
, SEND
))
2351 "Quit to send DbDesc to neighbor %s state %s",
2352 on
->name
, ospf6_neighbor_state_str
[on
->state
]);
2356 /* set next thread if master */
2357 if (CHECK_FLAG(on
->dbdesc_bits
, OSPF6_DBDESC_MSBIT
))
2358 thread_add_timer(master
, ospf6_dbdesc_send
, on
,
2359 on
->ospf6_if
->rxmt_interval
,
2360 &on
->thread_send_dbdesc
);
2362 op
= ospf6_packet_new(on
->ospf6_if
->ifmtu
);
2363 ospf6_make_header(OSPF6_MESSAGE_TYPE_DBDESC
, on
->ospf6_if
, op
->s
);
2365 length
+= ospf6_make_dbdesc(on
, op
->s
);
2366 ospf6_fill_header(on
->ospf6_if
, op
->s
, length
);
2368 /* Set packet length. */
2369 op
->length
= length
;
2371 if (on
->ospf6_if
->state
== OSPF6_INTERFACE_POINTTOPOINT
)
2372 op
->dst
= allspfrouters6
;
2374 op
->dst
= on
->linklocal_addr
;
2376 ospf6_fill_hdr_checksum(on
->ospf6_if
, op
);
2378 ospf6_packet_add(on
->ospf6_if
, op
);
2380 OSPF6_MESSAGE_WRITE_ON(on
->ospf6_if
);
2383 void ospf6_dbdesc_send_newone(struct thread
*thread
)
2385 struct ospf6_neighbor
*on
;
2386 struct ospf6_lsa
*lsa
, *lsanext
;
2387 unsigned int size
= 0;
2389 on
= (struct ospf6_neighbor
*)THREAD_ARG(thread
);
2390 ospf6_lsdb_remove_all(on
->dbdesc_list
);
2392 /* move LSAs from summary_list to dbdesc_list (within neighbor
2394 so that ospf6_send_dbdesc () can send those LSAs */
2395 size
= sizeof(struct ospf6_lsa_header
) + sizeof(struct ospf6_dbdesc
);
2396 for (ALL_LSDB(on
->summary_list
, lsa
, lsanext
)) {
2397 /* if stub area then don't advertise AS-External LSAs */
2398 if ((IS_AREA_STUB(on
->ospf6_if
->area
)
2399 || IS_AREA_NSSA(on
->ospf6_if
->area
))
2400 && ntohs(lsa
->header
->type
) == OSPF6_LSTYPE_AS_EXTERNAL
) {
2401 ospf6_lsdb_remove(lsa
, on
->summary_list
);
2405 if (size
+ sizeof(struct ospf6_lsa_header
)
2406 > ospf6_packet_max(on
->ospf6_if
)) {
2407 ospf6_lsa_unlock(lsa
);
2409 ospf6_lsa_unlock(lsanext
);
2413 ospf6_lsdb_add(ospf6_lsa_copy(lsa
), on
->dbdesc_list
);
2414 ospf6_lsdb_remove(lsa
, on
->summary_list
);
2415 size
+= sizeof(struct ospf6_lsa_header
);
2418 if (on
->summary_list
->count
== 0)
2419 UNSET_FLAG(on
->dbdesc_bits
, OSPF6_DBDESC_MBIT
);
2421 /* If slave, More bit check must be done here */
2422 if (!CHECK_FLAG(on
->dbdesc_bits
, OSPF6_DBDESC_MSBIT
) && /* Slave */
2423 !CHECK_FLAG(on
->dbdesc_last
.bits
, OSPF6_DBDESC_MBIT
)
2424 && !CHECK_FLAG(on
->dbdesc_bits
, OSPF6_DBDESC_MBIT
))
2425 thread_add_event(master
, exchange_done
, on
, 0,
2426 &on
->thread_exchange_done
);
2428 thread_execute(master
, ospf6_dbdesc_send
, on
, 0);
2431 static uint16_t ospf6_make_lsreq(struct ospf6_neighbor
*on
, struct stream
*s
)
2433 uint16_t length
= 0;
2434 struct ospf6_lsa
*lsa
, *lsanext
, *last_req
= NULL
;
2436 for (ALL_LSDB(on
->request_list
, lsa
, lsanext
)) {
2437 if ((length
+ OSPF6_HEADER_SIZE
)
2438 > ospf6_packet_max(on
->ospf6_if
)) {
2439 ospf6_lsa_unlock(lsa
);
2441 ospf6_lsa_unlock(lsanext
);
2444 stream_putw(s
, 0); /* reserved */
2445 stream_putw(s
, ntohs(lsa
->header
->type
));
2446 stream_putl(s
, ntohl(lsa
->header
->id
));
2447 stream_putl(s
, ntohl(lsa
->header
->adv_router
));
2448 length
+= sizeof(struct ospf6_lsreq_entry
);
2452 if (last_req
!= NULL
) {
2453 if (on
->last_ls_req
!= NULL
)
2454 on
->last_ls_req
= ospf6_lsa_unlock(on
->last_ls_req
);
2456 ospf6_lsa_lock(last_req
);
2457 on
->last_ls_req
= last_req
;
2463 static uint16_t ospf6_make_lsack_neighbor(struct ospf6_neighbor
*on
,
2464 struct ospf6_packet
**op
)
2466 uint16_t length
= 0;
2467 struct ospf6_lsa
*lsa
, *lsanext
;
2470 for (ALL_LSDB(on
->lsack_list
, lsa
, lsanext
)) {
2471 if ((length
+ sizeof(struct ospf6_lsa_header
)
2472 + OSPF6_HEADER_SIZE
)
2473 > ospf6_packet_max(on
->ospf6_if
)) {
2474 /* if we run out of packet size/space here,
2475 better to try again soon. */
2477 ospf6_fill_header(on
->ospf6_if
, (*op
)->s
,
2478 length
+ OSPF6_HEADER_SIZE
);
2480 (*op
)->length
= length
+ OSPF6_HEADER_SIZE
;
2481 (*op
)->dst
= on
->linklocal_addr
;
2482 ospf6_fill_hdr_checksum(on
->ospf6_if
, *op
);
2483 ospf6_packet_add(on
->ospf6_if
, *op
);
2484 OSPF6_MESSAGE_WRITE_ON(on
->ospf6_if
);
2486 *op
= ospf6_packet_new(on
->ospf6_if
->ifmtu
);
2487 ospf6_make_header(OSPF6_MESSAGE_TYPE_LSACK
,
2488 on
->ospf6_if
, (*op
)->s
);
2493 ospf6_lsa_age_update_to_send(lsa
, on
->ospf6_if
->transdelay
);
2494 stream_put((*op
)->s
, lsa
->header
,
2495 sizeof(struct ospf6_lsa_header
));
2496 length
+= sizeof(struct ospf6_lsa_header
);
2498 assert(lsa
->lock
== 2);
2499 ospf6_lsdb_remove(lsa
, on
->lsack_list
);
2505 void ospf6_lsreq_send(struct thread
*thread
)
2507 struct ospf6_neighbor
*on
;
2508 struct ospf6_packet
*op
;
2509 uint16_t length
= OSPF6_HEADER_SIZE
;
2511 on
= (struct ospf6_neighbor
*)THREAD_ARG(thread
);
2513 /* LSReq will be sent only in ExStart or Loading */
2514 if (on
->state
!= OSPF6_NEIGHBOR_EXCHANGE
2515 && on
->state
!= OSPF6_NEIGHBOR_LOADING
) {
2516 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_LSREQ
, SEND_HDR
))
2517 zlog_debug("Quit to send LSReq to neighbor %s state %s",
2519 ospf6_neighbor_state_str
[on
->state
]);
2523 /* schedule loading_done if request list is empty */
2524 if (on
->request_list
->count
== 0) {
2525 thread_add_event(master
, loading_done
, on
, 0, NULL
);
2529 op
= ospf6_packet_new(on
->ospf6_if
->ifmtu
);
2530 ospf6_make_header(OSPF6_MESSAGE_TYPE_LSREQ
, on
->ospf6_if
, op
->s
);
2532 length
+= ospf6_make_lsreq(on
, op
->s
);
2534 if (length
== OSPF6_HEADER_SIZE
) {
2535 /* Hello overshooting MTU */
2536 ospf6_packet_free(op
);
2540 /* Fill OSPF header. */
2541 ospf6_fill_header(on
->ospf6_if
, op
->s
, length
);
2543 /* Set packet length */
2544 op
->length
= length
;
2546 if (on
->ospf6_if
->state
== OSPF6_INTERFACE_POINTTOPOINT
)
2547 op
->dst
= allspfrouters6
;
2549 op
->dst
= on
->linklocal_addr
;
2551 ospf6_fill_hdr_checksum(on
->ospf6_if
, op
);
2552 ospf6_packet_add(on
->ospf6_if
, op
);
2554 OSPF6_MESSAGE_WRITE_ON(on
->ospf6_if
);
2556 /* set next thread */
2557 if (on
->request_list
->count
!= 0) {
2558 thread_add_timer(master
, ospf6_lsreq_send
, on
,
2559 on
->ospf6_if
->rxmt_interval
,
2560 &on
->thread_send_lsreq
);
2564 static void ospf6_send_lsupdate(struct ospf6_neighbor
*on
,
2565 struct ospf6_interface
*oi
,
2566 struct ospf6_packet
*op
)
2571 if ((on
->ospf6_if
->state
== OSPF6_INTERFACE_POINTTOPOINT
)
2572 || (on
->ospf6_if
->state
== OSPF6_INTERFACE_DR
)
2573 || (on
->ospf6_if
->state
== OSPF6_INTERFACE_BDR
))
2574 op
->dst
= allspfrouters6
;
2576 op
->dst
= on
->linklocal_addr
;
2579 if ((oi
->state
== OSPF6_INTERFACE_POINTTOPOINT
)
2580 || (oi
->state
== OSPF6_INTERFACE_DR
)
2581 || (oi
->state
== OSPF6_INTERFACE_BDR
))
2582 op
->dst
= allspfrouters6
;
2584 op
->dst
= alldrouters6
;
2587 ospf6_fill_hdr_checksum(oi
, op
);
2588 ospf6_packet_add(oi
, op
);
2589 /* If ospf instance is being deleted, send the packet
2592 if ((oi
->area
== NULL
) || (oi
->area
->ospf6
== NULL
))
2594 if (oi
->area
->ospf6
->inst_shutdown
) {
2595 if (oi
->on_write_q
== 0) {
2596 listnode_add(oi
->area
->ospf6
->oi_write_q
, oi
);
2599 thread_execute(master
, ospf6_write
, oi
->area
->ospf6
, 0);
2601 OSPF6_MESSAGE_WRITE_ON(oi
);
2605 static uint16_t ospf6_make_lsupdate_list(struct ospf6_neighbor
*on
,
2606 struct ospf6_packet
**op
, int *lsa_cnt
)
2608 uint16_t length
= OSPF6_LS_UPD_MIN_SIZE
;
2609 struct ospf6_lsa
*lsa
, *lsanext
;
2611 /* skip over fixed header */
2612 stream_forward_endp((*op
)->s
, OSPF6_LS_UPD_MIN_SIZE
);
2614 for (ALL_LSDB(on
->lsupdate_list
, lsa
, lsanext
)) {
2615 if ((length
+ OSPF6_LSA_SIZE(lsa
->header
) + OSPF6_HEADER_SIZE
) >
2616 ospf6_packet_max(on
->ospf6_if
)) {
2617 ospf6_fill_header(on
->ospf6_if
, (*op
)->s
,
2618 length
+ OSPF6_HEADER_SIZE
);
2619 (*op
)->length
= length
+ OSPF6_HEADER_SIZE
;
2620 ospf6_fill_lsupdate_header((*op
)->s
, *lsa_cnt
);
2621 ospf6_send_lsupdate(on
, NULL
, *op
);
2623 /* refresh packet */
2624 *op
= ospf6_packet_new(on
->ospf6_if
->ifmtu
);
2625 length
= OSPF6_LS_UPD_MIN_SIZE
;
2627 ospf6_make_header(OSPF6_MESSAGE_TYPE_LSUPDATE
,
2628 on
->ospf6_if
, (*op
)->s
);
2629 stream_forward_endp((*op
)->s
, OSPF6_LS_UPD_MIN_SIZE
);
2631 ospf6_lsa_age_update_to_send(lsa
, on
->ospf6_if
->transdelay
);
2632 stream_put((*op
)->s
, lsa
->header
, OSPF6_LSA_SIZE(lsa
->header
));
2634 length
+= OSPF6_LSA_SIZE(lsa
->header
);
2635 assert(lsa
->lock
== 2);
2636 ospf6_lsdb_remove(lsa
, on
->lsupdate_list
);
2641 static uint16_t ospf6_make_ls_retrans_list(struct ospf6_neighbor
*on
,
2642 struct ospf6_packet
**op
,
2645 uint16_t length
= OSPF6_LS_UPD_MIN_SIZE
;
2646 struct ospf6_lsa
*lsa
, *lsanext
;
2648 /* skip over fixed header */
2649 stream_forward_endp((*op
)->s
, OSPF6_LS_UPD_MIN_SIZE
);
2651 for (ALL_LSDB(on
->retrans_list
, lsa
, lsanext
)) {
2652 if ((length
+ OSPF6_LSA_SIZE(lsa
->header
) + OSPF6_HEADER_SIZE
) >
2653 ospf6_packet_max(on
->ospf6_if
)) {
2654 ospf6_fill_header(on
->ospf6_if
, (*op
)->s
,
2655 length
+ OSPF6_HEADER_SIZE
);
2656 (*op
)->length
= length
+ OSPF6_HEADER_SIZE
;
2657 ospf6_fill_lsupdate_header((*op
)->s
, *lsa_cnt
);
2658 if (on
->ospf6_if
->state
== OSPF6_INTERFACE_POINTTOPOINT
)
2659 (*op
)->dst
= allspfrouters6
;
2661 (*op
)->dst
= on
->linklocal_addr
;
2663 ospf6_fill_hdr_checksum(on
->ospf6_if
, *op
);
2664 ospf6_packet_add(on
->ospf6_if
, *op
);
2665 OSPF6_MESSAGE_WRITE_ON(on
->ospf6_if
);
2667 /* refresh packet */
2668 *op
= ospf6_packet_new(on
->ospf6_if
->ifmtu
);
2669 length
= OSPF6_LS_UPD_MIN_SIZE
;
2671 ospf6_make_header(OSPF6_MESSAGE_TYPE_LSUPDATE
,
2672 on
->ospf6_if
, (*op
)->s
);
2673 stream_forward_endp((*op
)->s
, OSPF6_LS_UPD_MIN_SIZE
);
2675 ospf6_lsa_age_update_to_send(lsa
, on
->ospf6_if
->transdelay
);
2676 stream_put((*op
)->s
, lsa
->header
, OSPF6_LSA_SIZE(lsa
->header
));
2678 length
+= OSPF6_LSA_SIZE(lsa
->header
);
2683 void ospf6_lsupdate_send_neighbor(struct thread
*thread
)
2685 struct ospf6_neighbor
*on
;
2686 struct ospf6_packet
*op
;
2687 uint16_t length
= OSPF6_HEADER_SIZE
;
2690 on
= (struct ospf6_neighbor
*)THREAD_ARG(thread
);
2692 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_LSUPDATE
, SEND_HDR
))
2693 zlog_debug("LSUpdate to neighbor %s", on
->name
);
2695 if (on
->state
< OSPF6_NEIGHBOR_EXCHANGE
) {
2696 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_LSUPDATE
,
2698 zlog_debug("Quit to send (neighbor state %s)",
2699 ospf6_neighbor_state_str
[on
->state
]);
2703 /* first do lsupdate_list */
2704 op
= ospf6_packet_new(on
->ospf6_if
->ifmtu
);
2705 ospf6_make_header(OSPF6_MESSAGE_TYPE_LSUPDATE
, on
->ospf6_if
, op
->s
);
2706 length
+= ospf6_make_lsupdate_list(on
, &op
, &lsa_cnt
);
2708 /* Fill OSPF header. */
2709 ospf6_fill_header(on
->ospf6_if
, op
->s
, length
);
2710 ospf6_fill_lsupdate_header(op
->s
, lsa_cnt
);
2711 op
->length
= length
;
2712 ospf6_send_lsupdate(on
, NULL
, op
);
2714 /* prepare new packet */
2715 op
= ospf6_packet_new(on
->ospf6_if
->ifmtu
);
2716 length
= OSPF6_HEADER_SIZE
;
2719 stream_reset(op
->s
);
2720 length
= OSPF6_HEADER_SIZE
;
2723 ospf6_make_header(OSPF6_MESSAGE_TYPE_LSUPDATE
, on
->ospf6_if
, op
->s
);
2724 /* now do retransmit list */
2725 length
+= ospf6_make_ls_retrans_list(on
, &op
, &lsa_cnt
);
2727 ospf6_fill_header(on
->ospf6_if
, op
->s
, length
);
2728 ospf6_fill_lsupdate_header(op
->s
, lsa_cnt
);
2729 op
->length
= length
;
2730 if (on
->ospf6_if
->state
== OSPF6_INTERFACE_POINTTOPOINT
)
2731 op
->dst
= allspfrouters6
;
2733 op
->dst
= on
->linklocal_addr
;
2734 ospf6_fill_hdr_checksum(on
->ospf6_if
, op
);
2735 ospf6_packet_add(on
->ospf6_if
, op
);
2736 OSPF6_MESSAGE_WRITE_ON(on
->ospf6_if
);
2738 ospf6_packet_free(op
);
2740 if (on
->lsupdate_list
->count
!= 0) {
2741 thread_add_event(master
, ospf6_lsupdate_send_neighbor
, on
, 0,
2742 &on
->thread_send_lsupdate
);
2743 } else if (on
->retrans_list
->count
!= 0) {
2744 thread_add_timer(master
, ospf6_lsupdate_send_neighbor
, on
,
2745 on
->ospf6_if
->rxmt_interval
,
2746 &on
->thread_send_lsupdate
);
2750 int ospf6_lsupdate_send_neighbor_now(struct ospf6_neighbor
*on
,
2751 struct ospf6_lsa
*lsa
)
2753 struct ospf6_packet
*op
;
2754 uint16_t length
= OSPF6_HEADER_SIZE
;
2756 op
= ospf6_packet_new(on
->ospf6_if
->ifmtu
);
2757 ospf6_make_header(OSPF6_MESSAGE_TYPE_LSUPDATE
, on
->ospf6_if
, op
->s
);
2759 /* skip over fixed header */
2760 stream_forward_endp(op
->s
, OSPF6_LS_UPD_MIN_SIZE
);
2761 ospf6_lsa_age_update_to_send(lsa
, on
->ospf6_if
->transdelay
);
2762 stream_put(op
->s
, lsa
->header
, OSPF6_LSA_SIZE(lsa
->header
));
2763 length
= OSPF6_HEADER_SIZE
+ OSPF6_LS_UPD_MIN_SIZE
2764 + OSPF6_LSA_SIZE(lsa
->header
);
2765 ospf6_fill_header(on
->ospf6_if
, op
->s
, length
);
2766 ospf6_fill_lsupdate_header(op
->s
, 1);
2767 op
->length
= length
;
2769 if (IS_OSPF6_DEBUG_FLOODING
2770 || IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_LSUPDATE
, SEND_HDR
))
2771 zlog_debug("%s: Send lsupdate with lsa %s (age %u)", __func__
,
2772 lsa
->name
, ntohs(lsa
->header
->age
));
2774 ospf6_send_lsupdate(on
, NULL
, op
);
2779 static uint16_t ospf6_make_lsupdate_interface(struct ospf6_interface
*oi
,
2780 struct ospf6_packet
**op
,
2783 uint16_t length
= OSPF6_LS_UPD_MIN_SIZE
;
2784 struct ospf6_lsa
*lsa
, *lsanext
;
2786 /* skip over fixed header */
2787 stream_forward_endp((*op
)->s
, OSPF6_LS_UPD_MIN_SIZE
);
2789 for (ALL_LSDB(oi
->lsupdate_list
, lsa
, lsanext
)) {
2790 if (length
+ OSPF6_LSA_SIZE(lsa
->header
) + OSPF6_HEADER_SIZE
>
2791 ospf6_packet_max(oi
)) {
2792 ospf6_fill_header(oi
, (*op
)->s
,
2793 length
+ OSPF6_HEADER_SIZE
);
2794 (*op
)->length
= length
+ OSPF6_HEADER_SIZE
;
2795 ospf6_fill_lsupdate_header((*op
)->s
, *lsa_cnt
);
2796 ospf6_send_lsupdate(NULL
, oi
, *op
);
2798 /* refresh packet */
2799 *op
= ospf6_packet_new(oi
->ifmtu
);
2800 length
= OSPF6_LS_UPD_MIN_SIZE
;
2802 ospf6_make_header(OSPF6_MESSAGE_TYPE_LSUPDATE
, oi
,
2804 stream_forward_endp((*op
)->s
, OSPF6_LS_UPD_MIN_SIZE
);
2807 ospf6_lsa_age_update_to_send(lsa
, oi
->transdelay
);
2808 stream_put((*op
)->s
, lsa
->header
, OSPF6_LSA_SIZE(lsa
->header
));
2810 length
+= OSPF6_LSA_SIZE(lsa
->header
);
2812 assert(lsa
->lock
== 2);
2813 ospf6_lsdb_remove(lsa
, oi
->lsupdate_list
);
2818 void ospf6_lsupdate_send_interface(struct thread
*thread
)
2820 struct ospf6_interface
*oi
;
2821 struct ospf6_packet
*op
;
2822 uint16_t length
= OSPF6_HEADER_SIZE
;
2825 oi
= (struct ospf6_interface
*)THREAD_ARG(thread
);
2827 if (oi
->state
<= OSPF6_INTERFACE_WAITING
) {
2828 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_LSUPDATE
,
2831 "Quit to send LSUpdate to interface %s state %s",
2832 oi
->interface
->name
,
2833 ospf6_interface_state_str
[oi
->state
]);
2837 /* if we have nothing to send, return */
2838 if (oi
->lsupdate_list
->count
== 0)
2841 op
= ospf6_packet_new(oi
->ifmtu
);
2842 ospf6_make_header(OSPF6_MESSAGE_TYPE_LSUPDATE
, oi
, op
->s
);
2843 length
+= ospf6_make_lsupdate_interface(oi
, &op
, &lsa_cnt
);
2845 /* Fill OSPF header. */
2846 ospf6_fill_header(oi
, op
->s
, length
);
2847 ospf6_fill_lsupdate_header(op
->s
, lsa_cnt
);
2848 op
->length
= length
;
2849 ospf6_send_lsupdate(NULL
, oi
, op
);
2851 ospf6_packet_free(op
);
2853 if (oi
->lsupdate_list
->count
> 0) {
2854 thread_add_event(master
, ospf6_lsupdate_send_interface
, oi
, 0,
2855 &oi
->thread_send_lsupdate
);
2859 void ospf6_lsack_send_neighbor(struct thread
*thread
)
2861 struct ospf6_neighbor
*on
;
2862 struct ospf6_packet
*op
;
2863 uint16_t length
= OSPF6_HEADER_SIZE
;
2865 on
= (struct ospf6_neighbor
*)THREAD_ARG(thread
);
2867 if (on
->state
< OSPF6_NEIGHBOR_EXCHANGE
) {
2868 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_LSACK
, SEND_HDR
))
2869 zlog_debug("Quit to send LSAck to neighbor %s state %s",
2871 ospf6_neighbor_state_str
[on
->state
]);
2875 /* if we have nothing to send, return */
2876 if (on
->lsack_list
->count
== 0)
2879 op
= ospf6_packet_new(on
->ospf6_if
->ifmtu
);
2880 ospf6_make_header(OSPF6_MESSAGE_TYPE_LSACK
, on
->ospf6_if
, op
->s
);
2882 length
+= ospf6_make_lsack_neighbor(on
, &op
);
2884 if (length
== OSPF6_HEADER_SIZE
) {
2885 ospf6_packet_free(op
);
2889 /* Fill OSPF header. */
2890 ospf6_fill_header(on
->ospf6_if
, op
->s
, length
);
2892 /* Set packet length, dst and queue to FIFO. */
2893 op
->length
= length
;
2894 op
->dst
= on
->linklocal_addr
;
2895 ospf6_fill_hdr_checksum(on
->ospf6_if
, op
);
2896 ospf6_packet_add(on
->ospf6_if
, op
);
2897 OSPF6_MESSAGE_WRITE_ON(on
->ospf6_if
);
2899 if (on
->lsack_list
->count
> 0)
2900 thread_add_event(master
, ospf6_lsack_send_neighbor
, on
, 0,
2901 &on
->thread_send_lsack
);
2904 static uint16_t ospf6_make_lsack_interface(struct ospf6_interface
*oi
,
2905 struct ospf6_packet
*op
)
2907 uint16_t length
= 0;
2908 struct ospf6_lsa
*lsa
, *lsanext
;
2910 for (ALL_LSDB(oi
->lsack_list
, lsa
, lsanext
)) {
2911 if ((length
+ sizeof(struct ospf6_lsa_header
)
2912 + OSPF6_HEADER_SIZE
)
2913 > ospf6_packet_max(oi
)) {
2914 /* if we run out of packet size/space here,
2915 better to try again soon. */
2916 THREAD_OFF(oi
->thread_send_lsack
);
2917 thread_add_event(master
, ospf6_lsack_send_interface
, oi
,
2918 0, &oi
->thread_send_lsack
);
2920 ospf6_lsa_unlock(lsa
);
2922 ospf6_lsa_unlock(lsanext
);
2925 ospf6_lsa_age_update_to_send(lsa
, oi
->transdelay
);
2926 stream_put(op
->s
, lsa
->header
, sizeof(struct ospf6_lsa_header
));
2927 length
+= sizeof(struct ospf6_lsa_header
);
2929 assert(lsa
->lock
== 2);
2930 ospf6_lsdb_remove(lsa
, oi
->lsack_list
);
2935 void ospf6_lsack_send_interface(struct thread
*thread
)
2937 struct ospf6_interface
*oi
;
2938 struct ospf6_packet
*op
;
2939 uint16_t length
= OSPF6_HEADER_SIZE
;
2941 oi
= (struct ospf6_interface
*)THREAD_ARG(thread
);
2943 if (oi
->state
<= OSPF6_INTERFACE_WAITING
) {
2944 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_LSACK
, SEND_HDR
))
2946 "Quit to send LSAck to interface %s state %s",
2947 oi
->interface
->name
,
2948 ospf6_interface_state_str
[oi
->state
]);
2952 /* if we have nothing to send, return */
2953 if (oi
->lsack_list
->count
== 0)
2956 op
= ospf6_packet_new(oi
->ifmtu
);
2957 ospf6_make_header(OSPF6_MESSAGE_TYPE_LSACK
, oi
, op
->s
);
2959 length
+= ospf6_make_lsack_interface(oi
, op
);
2961 if (length
== OSPF6_HEADER_SIZE
) {
2962 ospf6_packet_free(op
);
2965 /* Fill OSPF header. */
2966 ospf6_fill_header(oi
, op
->s
, length
);
2968 /* Set packet length, dst and queue to FIFO. */
2969 op
->length
= length
;
2970 if ((oi
->state
== OSPF6_INTERFACE_POINTTOPOINT
)
2971 || (oi
->state
== OSPF6_INTERFACE_DR
)
2972 || (oi
->state
== OSPF6_INTERFACE_BDR
))
2973 op
->dst
= allspfrouters6
;
2975 op
->dst
= alldrouters6
;
2977 ospf6_fill_hdr_checksum(oi
, op
);
2978 ospf6_packet_add(oi
, op
);
2979 OSPF6_MESSAGE_WRITE_ON(oi
);
2981 if (oi
->lsack_list
->count
> 0)
2982 thread_add_event(master
, ospf6_lsack_send_interface
, oi
, 0,
2983 &oi
->thread_send_lsack
);
2987 DEFUN(debug_ospf6_message
, debug_ospf6_message_cmd
,
2988 "debug ospf6 message <unknown|hello|dbdesc|lsreq|lsupdate|lsack|all> [<send|recv|send-hdr|recv-hdr>]",
2990 "Debug OSPFv3 message\n"
2991 "Debug Unknown message\n"
2992 "Debug Hello message\n"
2993 "Debug Database Description message\n"
2994 "Debug Link State Request message\n"
2995 "Debug Link State Update message\n"
2996 "Debug Link State Acknowledgement message\n"
2997 "Debug All message\n"
2998 "Debug only sending message, entire packet\n"
2999 "Debug only receiving message, entire packet\n"
3000 "Debug only sending message, header only\n"
3001 "Debug only receiving message, header only\n")
3004 int idx_send_recv
= 4;
3005 unsigned char level
= 0;
3010 if (!strncmp(argv
[idx_packet
]->arg
, "u", 1))
3011 type
= OSPF6_MESSAGE_TYPE_UNKNOWN
;
3012 else if (!strncmp(argv
[idx_packet
]->arg
, "h", 1))
3013 type
= OSPF6_MESSAGE_TYPE_HELLO
;
3014 else if (!strncmp(argv
[idx_packet
]->arg
, "d", 1))
3015 type
= OSPF6_MESSAGE_TYPE_DBDESC
;
3016 else if (!strncmp(argv
[idx_packet
]->arg
, "lsr", 3))
3017 type
= OSPF6_MESSAGE_TYPE_LSREQ
;
3018 else if (!strncmp(argv
[idx_packet
]->arg
, "lsu", 3))
3019 type
= OSPF6_MESSAGE_TYPE_LSUPDATE
;
3020 else if (!strncmp(argv
[idx_packet
]->arg
, "lsa", 3))
3021 type
= OSPF6_MESSAGE_TYPE_LSACK
;
3022 else if (!strncmp(argv
[idx_packet
]->arg
, "a", 1))
3023 type
= OSPF6_MESSAGE_TYPE_ALL
;
3026 level
= OSPF6_DEBUG_MESSAGE_SEND
| OSPF6_DEBUG_MESSAGE_RECV
;
3027 else if (!strncmp(argv
[idx_send_recv
]->arg
, "send-h", 6))
3028 level
= OSPF6_DEBUG_MESSAGE_SEND_HDR
;
3029 else if (!strncmp(argv
[idx_send_recv
]->arg
, "s", 1))
3030 level
= OSPF6_DEBUG_MESSAGE_SEND
;
3031 else if (!strncmp(argv
[idx_send_recv
]->arg
, "recv-h", 6))
3032 level
= OSPF6_DEBUG_MESSAGE_RECV_HDR
;
3033 else if (!strncmp(argv
[idx_send_recv
]->arg
, "r", 1))
3034 level
= OSPF6_DEBUG_MESSAGE_RECV
;
3036 if (type
== OSPF6_MESSAGE_TYPE_ALL
) {
3037 for (i
= 0; i
< 6; i
++)
3038 OSPF6_DEBUG_MESSAGE_ON(i
, level
);
3040 OSPF6_DEBUG_MESSAGE_ON(type
, level
);
3045 DEFUN(no_debug_ospf6_message
, no_debug_ospf6_message_cmd
,
3046 "no debug ospf6 message <unknown|hello|dbdesc|lsreq|lsupdate|lsack|all> [<send|recv|send-hdr|recv-hdr>]",
3047 NO_STR DEBUG_STR OSPF6_STR
3048 "Debug OSPFv3 message\n"
3049 "Debug Unknown message\n"
3050 "Debug Hello message\n"
3051 "Debug Database Description message\n"
3052 "Debug Link State Request message\n"
3053 "Debug Link State Update message\n"
3054 "Debug Link State Acknowledgement message\n"
3055 "Debug All message\n"
3056 "Debug only sending message, entire pkt\n"
3057 "Debug only receiving message, entire pkt\n"
3058 "Debug only sending message, header only\n"
3059 "Debug only receiving message, header only\n")
3062 int idx_send_recv
= 5;
3063 unsigned char level
= 0;
3068 if (!strncmp(argv
[idx_packet
]->arg
, "u", 1))
3069 type
= OSPF6_MESSAGE_TYPE_UNKNOWN
;
3070 else if (!strncmp(argv
[idx_packet
]->arg
, "h", 1))
3071 type
= OSPF6_MESSAGE_TYPE_HELLO
;
3072 else if (!strncmp(argv
[idx_packet
]->arg
, "d", 1))
3073 type
= OSPF6_MESSAGE_TYPE_DBDESC
;
3074 else if (!strncmp(argv
[idx_packet
]->arg
, "lsr", 3))
3075 type
= OSPF6_MESSAGE_TYPE_LSREQ
;
3076 else if (!strncmp(argv
[idx_packet
]->arg
, "lsu", 3))
3077 type
= OSPF6_MESSAGE_TYPE_LSUPDATE
;
3078 else if (!strncmp(argv
[idx_packet
]->arg
, "lsa", 3))
3079 type
= OSPF6_MESSAGE_TYPE_LSACK
;
3080 else if (!strncmp(argv
[idx_packet
]->arg
, "a", 1))
3081 type
= OSPF6_MESSAGE_TYPE_ALL
;
3084 level
= OSPF6_DEBUG_MESSAGE_SEND
| OSPF6_DEBUG_MESSAGE_RECV
3085 | OSPF6_DEBUG_MESSAGE_SEND_HDR
3086 | OSPF6_DEBUG_MESSAGE_RECV_HDR
;
3087 else if (!strncmp(argv
[idx_send_recv
]->arg
, "send-h", 6))
3088 level
= OSPF6_DEBUG_MESSAGE_SEND_HDR
;
3089 else if (!strncmp(argv
[idx_send_recv
]->arg
, "s", 1))
3090 level
= OSPF6_DEBUG_MESSAGE_SEND
;
3091 else if (!strncmp(argv
[idx_send_recv
]->arg
, "recv-h", 6))
3092 level
= OSPF6_DEBUG_MESSAGE_RECV_HDR
;
3093 else if (!strncmp(argv
[idx_send_recv
]->arg
, "r", 1))
3094 level
= OSPF6_DEBUG_MESSAGE_RECV
;
3096 if (type
== OSPF6_MESSAGE_TYPE_ALL
) {
3097 for (i
= 0; i
< 6; i
++)
3098 OSPF6_DEBUG_MESSAGE_OFF(i
, level
);
3100 OSPF6_DEBUG_MESSAGE_OFF(type
, level
);
3106 int config_write_ospf6_debug_message(struct vty
*vty
)
3108 const char *type_str
[] = {"unknown", "hello", "dbdesc",
3109 "lsreq", "lsupdate", "lsack"};
3110 unsigned char s
= 0, r
= 0, sh
= 0, rh
= 0;
3113 for (i
= 0; i
< 6; i
++) {
3114 if (IS_OSPF6_DEBUG_MESSAGE_ENABLED(i
, SEND
))
3116 if (IS_OSPF6_DEBUG_MESSAGE_ENABLED(i
, RECV
))
3120 for (i
= 0; i
< 6; i
++) {
3121 if (IS_OSPF6_DEBUG_MESSAGE_ENABLED(i
, SEND_HDR
))
3123 if (IS_OSPF6_DEBUG_MESSAGE_ENABLED(i
, RECV_HDR
))
3127 if (s
== 0x3f && r
== 0x3f) {
3128 vty_out(vty
, "debug ospf6 message all\n");
3132 if (s
== 0x3f && r
== 0) {
3133 vty_out(vty
, "debug ospf6 message all send\n");
3135 } else if (s
== 0 && r
== 0x3f) {
3136 vty_out(vty
, "debug ospf6 message all recv\n");
3140 if (sh
== 0x3f && rh
== 0) {
3141 vty_out(vty
, "debug ospf6 message all send-hdr\n");
3143 } else if (sh
== 0 && rh
== 0x3f) {
3144 vty_out(vty
, "debug ospf6 message all recv-hdr\n");
3148 /* Unknown message is logged by default */
3149 if (!IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN
, SEND
)
3150 && !IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN
, RECV
))
3151 vty_out(vty
, "no debug ospf6 message unknown\n");
3152 else if (!IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN
, SEND
))
3153 vty_out(vty
, "no debug ospf6 message unknown send\n");
3154 else if (!IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN
, RECV
))
3155 vty_out(vty
, "no debug ospf6 message unknown recv\n");
3157 for (i
= 1; i
< 6; i
++) {
3158 if (IS_OSPF6_DEBUG_MESSAGE_ENABLED(i
, SEND
)
3159 && IS_OSPF6_DEBUG_MESSAGE_ENABLED(i
, RECV
)) {
3160 vty_out(vty
, "debug ospf6 message %s\n", type_str
[i
]);
3164 if (IS_OSPF6_DEBUG_MESSAGE_ENABLED(i
, SEND
))
3165 vty_out(vty
, "debug ospf6 message %s send\n",
3167 else if (IS_OSPF6_DEBUG_MESSAGE_ENABLED(i
, SEND_HDR
))
3168 vty_out(vty
, "debug ospf6 message %s send-hdr\n",
3171 if (IS_OSPF6_DEBUG_MESSAGE_ENABLED(i
, RECV
))
3172 vty_out(vty
, "debug ospf6 message %s recv\n",
3174 else if (IS_OSPF6_DEBUG_MESSAGE_ENABLED(i
, RECV_HDR
))
3175 vty_out(vty
, "debug ospf6 message %s recv-hdr\n",
3182 void install_element_ospf6_debug_message(void)
3184 install_element(ENABLE_NODE
, &debug_ospf6_message_cmd
);
3185 install_element(ENABLE_NODE
, &no_debug_ospf6_message_cmd
);
3186 install_element(CONFIG_NODE
, &debug_ospf6_message_cmd
);
3187 install_element(CONFIG_NODE
, &no_debug_ospf6_message_cmd
);