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"
32 #include "ospf6_proto.h"
33 #include "ospf6_lsa.h"
34 #include "ospf6_lsdb.h"
35 #include "ospf6_top.h"
36 #include "ospf6_network.h"
37 #include "ospf6_message.h"
39 #include "ospf6_area.h"
40 #include "ospf6_neighbor.h"
41 #include "ospf6_interface.h"
43 /* for structures and macros ospf6_lsa_examin() needs */
44 #include "ospf6_abr.h"
45 #include "ospf6_asbr.h"
46 #include "ospf6_intra.h"
48 #include "ospf6_flood.h"
51 #include <netinet/ip6.h>
52 #include "lib/libospf.h"
53 #include "lib/keychain.h"
54 #include "ospf6_auth_trailer.h"
56 DEFINE_MTYPE_STATIC(OSPF6D
, OSPF6_MESSAGE
, "OSPF6 message");
57 DEFINE_MTYPE_STATIC(OSPF6D
, OSPF6_PACKET
, "OSPF6 packet");
58 DEFINE_MTYPE_STATIC(OSPF6D
, OSPF6_FIFO
, "OSPF6 FIFO queue");
60 unsigned char conf_debug_ospf6_message
[6] = {0x03, 0, 0, 0, 0, 0};
62 const char *ospf6_message_type(int type
)
65 case OSPF6_MESSAGE_TYPE_HELLO
:
67 case OSPF6_MESSAGE_TYPE_DBDESC
:
69 case OSPF6_MESSAGE_TYPE_LSREQ
:
71 case OSPF6_MESSAGE_TYPE_LSUPDATE
:
73 case OSPF6_MESSAGE_TYPE_LSACK
:
75 case OSPF6_MESSAGE_TYPE_UNKNOWN
:
81 /* Minimum (besides the standard OSPF packet header) lengths for OSPF
82 packets of particular types, offset is the "type" field. */
83 const uint16_t ospf6_packet_minlen
[OSPF6_MESSAGE_TYPE_ALL
] = {
86 OSPF6_DB_DESC_MIN_SIZE
,
87 OSPF6_LS_REQ_MIN_SIZE
,
88 OSPF6_LS_UPD_MIN_SIZE
,
89 OSPF6_LS_ACK_MIN_SIZE
};
91 /* Minimum (besides the standard LSA header) lengths for LSAs of particular
92 types, offset is the "LSA function code" portion of "LSA type" field. */
93 const uint16_t ospf6_lsa_minlen
[OSPF6_LSTYPE_SIZE
] = {
95 /* 0x2001 */ OSPF6_ROUTER_LSA_MIN_SIZE
,
96 /* 0x2002 */ OSPF6_NETWORK_LSA_MIN_SIZE
,
97 /* 0x2003 */ OSPF6_INTER_PREFIX_LSA_MIN_SIZE
,
98 /* 0x2004 */ OSPF6_INTER_ROUTER_LSA_FIX_SIZE
,
99 /* 0x4005 */ OSPF6_AS_EXTERNAL_LSA_MIN_SIZE
,
101 /* 0x2007 */ OSPF6_AS_EXTERNAL_LSA_MIN_SIZE
,
102 /* 0x0008 */ OSPF6_LINK_LSA_MIN_SIZE
,
103 /* 0x2009 */ OSPF6_INTRA_PREFIX_LSA_MIN_SIZE
,
105 /* 0x000b */ OSPF6_GRACE_LSA_MIN_SIZE
};
107 /* print functions */
109 static void ospf6_header_print(struct ospf6_header
*oh
)
111 zlog_debug(" OSPFv%d Type:%d Len:%hu Router-ID:%pI4", oh
->version
,
112 oh
->type
, ntohs(oh
->length
), &oh
->router_id
);
113 zlog_debug(" Area-ID:%pI4 Cksum:%hx Instance-ID:%d", &oh
->area_id
,
114 ntohs(oh
->checksum
), oh
->instance_id
);
117 void ospf6_hello_print(struct ospf6_header
*oh
, int action
)
119 struct ospf6_hello
*hello
;
123 ospf6_header_print(oh
);
124 assert(oh
->type
== OSPF6_MESSAGE_TYPE_HELLO
);
126 hello
= (struct ospf6_hello
*)((caddr_t
)oh
127 + sizeof(struct ospf6_header
));
129 ospf6_options_printbuf(hello
->options
, options
, sizeof(options
));
131 zlog_debug(" I/F-Id:%ld Priority:%d Option:%s",
132 (unsigned long)ntohl(hello
->interface_id
), hello
->priority
,
134 zlog_debug(" HelloInterval:%hu DeadInterval:%hu",
135 ntohs(hello
->hello_interval
), ntohs(hello
->dead_interval
));
136 zlog_debug(" DR:%pI4 BDR:%pI4", &hello
->drouter
, &hello
->bdrouter
);
138 if ((IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
)
139 && action
== OSPF6_ACTION_RECV
)
140 || (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, SEND
)
141 && action
== OSPF6_ACTION_SEND
)) {
143 for (p
= (char *)((caddr_t
)hello
+ sizeof(struct ospf6_hello
));
144 p
+ sizeof(uint32_t) <= OSPF6_MESSAGE_END(oh
);
145 p
+= sizeof(uint32_t))
146 zlog_debug(" Neighbor: %pI4", (in_addr_t
*)p
);
148 assert(p
== OSPF6_MESSAGE_END(oh
));
152 void ospf6_dbdesc_print(struct ospf6_header
*oh
, int action
)
154 struct ospf6_dbdesc
*dbdesc
;
158 ospf6_header_print(oh
);
159 assert(oh
->type
== OSPF6_MESSAGE_TYPE_DBDESC
);
161 dbdesc
= (struct ospf6_dbdesc
*)((caddr_t
)oh
162 + sizeof(struct ospf6_header
));
164 ospf6_options_printbuf(dbdesc
->options
, options
, sizeof(options
));
166 zlog_debug(" MBZ: %#x Option: %s IfMTU: %hu", dbdesc
->reserved1
,
167 options
, ntohs(dbdesc
->ifmtu
));
168 zlog_debug(" MBZ: %#x Bits: %s%s%s SeqNum: %#lx", dbdesc
->reserved2
,
169 (CHECK_FLAG(dbdesc
->bits
, OSPF6_DBDESC_IBIT
) ? "I" : "-"),
170 (CHECK_FLAG(dbdesc
->bits
, OSPF6_DBDESC_MBIT
) ? "M" : "-"),
171 (CHECK_FLAG(dbdesc
->bits
, OSPF6_DBDESC_MSBIT
) ? "m" : "s"),
172 (unsigned long)ntohl(dbdesc
->seqnum
));
174 if ((IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
)
175 && action
== OSPF6_ACTION_RECV
)
176 || (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, SEND
)
177 && action
== OSPF6_ACTION_SEND
)) {
179 for (p
= (char *)((caddr_t
)dbdesc
180 + sizeof(struct ospf6_dbdesc
));
181 p
+ sizeof(struct ospf6_lsa_header
)
182 <= OSPF6_MESSAGE_END(oh
);
183 p
+= sizeof(struct ospf6_lsa_header
))
184 ospf6_lsa_header_print_raw(
185 (struct ospf6_lsa_header
*)p
);
187 assert(p
== OSPF6_MESSAGE_END(oh
));
191 void ospf6_lsreq_print(struct ospf6_header
*oh
, int action
)
195 ospf6_header_print(oh
);
196 assert(oh
->type
== OSPF6_MESSAGE_TYPE_LSREQ
);
198 if ((IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
)
199 && action
== OSPF6_ACTION_RECV
)
200 || (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, SEND
)
201 && action
== OSPF6_ACTION_SEND
)) {
203 for (p
= (char *)((caddr_t
)oh
+ sizeof(struct ospf6_header
));
204 p
+ sizeof(struct ospf6_lsreq_entry
)
205 <= OSPF6_MESSAGE_END(oh
);
206 p
+= sizeof(struct ospf6_lsreq_entry
)) {
207 struct ospf6_lsreq_entry
*e
=
208 (struct ospf6_lsreq_entry
*)p
;
210 zlog_debug(" [%s Id:%pI4 Adv:%pI4]",
211 ospf6_lstype_name(e
->type
), &e
->id
,
215 assert(p
== OSPF6_MESSAGE_END(oh
));
219 void ospf6_lsupdate_print(struct ospf6_header
*oh
, int action
)
221 struct ospf6_lsupdate
*lsupdate
;
225 ospf6_header_print(oh
);
226 assert(oh
->type
== OSPF6_MESSAGE_TYPE_LSUPDATE
);
228 lsupdate
= (struct ospf6_lsupdate
*)((caddr_t
)oh
229 + sizeof(struct ospf6_header
));
231 num
= ntohl(lsupdate
->lsa_number
);
232 zlog_debug(" Number of LSA: %ld", num
);
234 if ((IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
)
235 && action
== OSPF6_ACTION_RECV
)
236 || (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, SEND
)
237 && action
== OSPF6_ACTION_SEND
)) {
239 for (p
= (char *)((caddr_t
)lsupdate
240 + sizeof(struct ospf6_lsupdate
));
241 p
< OSPF6_MESSAGE_END(oh
)
242 && p
+ OSPF6_LSA_SIZE(p
) <= OSPF6_MESSAGE_END(oh
);
243 p
+= OSPF6_LSA_SIZE(p
)) {
244 ospf6_lsa_header_print_raw(
245 (struct ospf6_lsa_header
*)p
);
248 assert(p
== OSPF6_MESSAGE_END(oh
));
252 void ospf6_lsack_print(struct ospf6_header
*oh
, int action
)
256 ospf6_header_print(oh
);
257 assert(oh
->type
== OSPF6_MESSAGE_TYPE_LSACK
);
259 if ((IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
)
260 && action
== OSPF6_ACTION_RECV
)
261 || (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, SEND
)
262 && action
== OSPF6_ACTION_SEND
)) {
264 for (p
= (char *)((caddr_t
)oh
+ sizeof(struct ospf6_header
));
265 p
+ sizeof(struct ospf6_lsa_header
)
266 <= OSPF6_MESSAGE_END(oh
);
267 p
+= sizeof(struct ospf6_lsa_header
))
268 ospf6_lsa_header_print_raw(
269 (struct ospf6_lsa_header
*)p
);
271 assert(p
== OSPF6_MESSAGE_END(oh
));
275 static struct ospf6_packet
*ospf6_packet_new(size_t size
)
277 struct ospf6_packet
*new;
279 new = XCALLOC(MTYPE_OSPF6_PACKET
, sizeof(struct ospf6_packet
));
280 new->s
= stream_new(size
);
285 static void ospf6_packet_free(struct ospf6_packet
*op
)
290 XFREE(MTYPE_OSPF6_PACKET
, op
);
293 struct ospf6_fifo
*ospf6_fifo_new(void)
295 struct ospf6_fifo
*new;
297 new = XCALLOC(MTYPE_OSPF6_FIFO
, sizeof(struct ospf6_fifo
));
301 /* Add new packet to fifo. */
302 static void ospf6_fifo_push(struct ospf6_fifo
*fifo
, struct ospf6_packet
*op
)
305 fifo
->tail
->next
= op
;
314 /* Add new packet to head of fifo. */
315 static void ospf6_fifo_push_head(struct ospf6_fifo
*fifo
,
316 struct ospf6_packet
*op
)
318 op
->next
= fifo
->head
;
320 if (fifo
->tail
== NULL
)
328 /* Delete first packet from fifo. */
329 static struct ospf6_packet
*ospf6_fifo_pop(struct ospf6_fifo
*fifo
)
331 struct ospf6_packet
*op
;
336 fifo
->head
= op
->next
;
338 if (fifo
->head
== NULL
)
347 /* Return first fifo entry. */
348 static struct ospf6_packet
*ospf6_fifo_head(struct ospf6_fifo
*fifo
)
353 /* Flush ospf packet fifo. */
354 void ospf6_fifo_flush(struct ospf6_fifo
*fifo
)
356 struct ospf6_packet
*op
;
357 struct ospf6_packet
*next
;
359 for (op
= fifo
->head
; op
; op
= next
) {
361 ospf6_packet_free(op
);
363 fifo
->head
= fifo
->tail
= NULL
;
367 /* Free ospf packet fifo. */
368 void ospf6_fifo_free(struct ospf6_fifo
*fifo
)
370 ospf6_fifo_flush(fifo
);
372 XFREE(MTYPE_OSPF6_FIFO
, fifo
);
375 static void ospf6_packet_add(struct ospf6_interface
*oi
,
376 struct ospf6_packet
*op
)
378 /* Add packet to end of queue. */
379 ospf6_fifo_push(oi
->obuf
, op
);
381 /* Debug of packet fifo*/
382 /* ospf_fifo_debug (oi->obuf); */
385 static void ospf6_packet_add_top(struct ospf6_interface
*oi
,
386 struct ospf6_packet
*op
)
388 /* Add packet to head of queue. */
389 ospf6_fifo_push_head(oi
->obuf
, op
);
391 /* Debug of packet fifo*/
392 /* ospf_fifo_debug (oi->obuf); */
395 static void ospf6_packet_delete(struct ospf6_interface
*oi
)
397 struct ospf6_packet
*op
;
399 op
= ospf6_fifo_pop(oi
->obuf
);
402 ospf6_packet_free(op
);
406 static void ospf6_hello_recv(struct in6_addr
*src
, struct in6_addr
*dst
,
407 struct ospf6_interface
*oi
,
408 struct ospf6_header
*oh
)
410 struct ospf6_hello
*hello
;
411 struct ospf6_neighbor
*on
;
414 int neighborchange
= 0;
415 int neighbor_ifindex_change
= 0;
418 struct timeval timestamp
;
420 monotime(×tamp
);
421 hello
= (struct ospf6_hello
*)((caddr_t
)oh
422 + sizeof(struct ospf6_header
));
424 /* HelloInterval check */
425 if (ntohs(hello
->hello_interval
) != oi
->hello_interval
) {
427 "VRF %s: I/F %s HelloInterval mismatch: (my %d, rcvd %d)",
428 oi
->interface
->vrf
->name
, oi
->interface
->name
,
429 oi
->hello_interval
, ntohs(hello
->hello_interval
));
433 /* RouterDeadInterval check */
434 if (ntohs(hello
->dead_interval
) != oi
->dead_interval
) {
436 "VRF %s: I/F %s DeadInterval mismatch: (my %d, rcvd %d)",
437 oi
->interface
->vrf
->name
, oi
->interface
->name
,
438 oi
->dead_interval
, ntohs(hello
->dead_interval
));
443 if (OSPF6_OPT_ISSET(hello
->options
, OSPF6_OPT_E
)
444 != OSPF6_OPT_ISSET(oi
->area
->options
, OSPF6_OPT_E
)) {
445 zlog_warn("VRF %s: IF %s E-bit mismatch",
446 oi
->interface
->vrf
->name
, oi
->interface
->name
);
451 if (OSPF6_OPT_ISSET(hello
->options
, OSPF6_OPT_N
)
452 != OSPF6_OPT_ISSET(oi
->area
->options
, OSPF6_OPT_N
)) {
453 zlog_warn("VRF %s: IF %s N-bit mismatch",
454 oi
->interface
->vrf
->name
, oi
->interface
->name
);
458 if (((OSPF6_OPT_ISSET_EXT(hello
->options
, OSPF6_OPT_AT
) ==
460 (oi
->at_data
.flags
== 0)) ||
461 ((OSPF6_OPT_ISSET_EXT(hello
->options
, OSPF6_OPT_AT
) !=
463 (oi
->at_data
.flags
!= 0))) {
464 if (IS_OSPF6_DEBUG_AUTH_RX
)
466 "VRF %s: IF %s AT-bit mismatch in hello packet",
467 oi
->interface
->vrf
->name
, oi
->interface
->name
);
468 oi
->at_data
.rx_drop
++;
472 /* Find neighbor, create if not exist */
473 on
= ospf6_neighbor_lookup(oh
->router_id
, oi
);
475 on
= ospf6_neighbor_create(oh
->router_id
, oi
);
476 on
->prev_drouter
= on
->drouter
= hello
->drouter
;
477 on
->prev_bdrouter
= on
->bdrouter
= hello
->bdrouter
;
478 on
->priority
= hello
->priority
;
481 /* check latency against hello period */
483 latency
= monotime_since(&on
->last_hello
, NULL
)
484 - ((int64_t)oi
->hello_interval
* 1000000);
485 /* log if latency exceeds the hello period */
486 if (latency
> ((int64_t)oi
->hello_interval
* 1000000))
487 zlog_warn("%s RX %pI4 high latency %" PRId64
"us.", __func__
,
488 &on
->router_id
, latency
);
489 on
->last_hello
= timestamp
;
492 /* Always override neighbor's source address */
493 memcpy(&on
->linklocal_addr
, src
, sizeof(struct in6_addr
));
495 /* Neighbor ifindex check */
496 if (on
->ifindex
!= (ifindex_t
)ntohl(hello
->interface_id
)) {
497 on
->ifindex
= ntohl(hello
->interface_id
);
498 neighbor_ifindex_change
++;
502 for (p
= (char *)((caddr_t
)hello
+ sizeof(struct ospf6_hello
));
503 p
+ sizeof(uint32_t) <= OSPF6_MESSAGE_END(oh
);
504 p
+= sizeof(uint32_t)) {
505 uint32_t *router_id
= (uint32_t *)p
;
507 if (*router_id
== oi
->area
->ospf6
->router_id
)
511 assert(p
== OSPF6_MESSAGE_END(oh
));
513 /* RouterPriority check */
514 if (on
->priority
!= hello
->priority
) {
515 on
->priority
= hello
->priority
;
520 if (on
->drouter
!= hello
->drouter
) {
521 on
->prev_drouter
= on
->drouter
;
522 on
->drouter
= hello
->drouter
;
523 if (on
->prev_drouter
== on
->router_id
524 || on
->drouter
== on
->router_id
)
529 if (on
->bdrouter
!= hello
->bdrouter
) {
530 on
->prev_bdrouter
= on
->bdrouter
;
531 on
->bdrouter
= hello
->bdrouter
;
532 if (on
->prev_bdrouter
== on
->router_id
533 || on
->bdrouter
== on
->router_id
)
537 /* BackupSeen check */
538 if (oi
->state
== OSPF6_INTERFACE_WAITING
) {
539 if (hello
->bdrouter
== on
->router_id
)
541 else if (hello
->drouter
== on
->router_id
542 && hello
->bdrouter
== htonl(0))
548 /* Execute neighbor events */
549 thread_execute(master
, hello_received
, on
, 0);
551 thread_execute(master
, twoway_received
, on
, 0);
553 if (OSPF6_GR_IS_ACTIVE_HELPER(on
)) {
554 if (IS_DEBUG_OSPF6_GR
)
556 "%s, Received oneway hello from RESTARTER so ignore here.",
557 __PRETTY_FUNCTION__
);
559 /* If the router is DR_OTHER, RESTARTER will not wait
560 * until it receives the hello from it if it receives
562 * So, helper might receives ONE_WAY hello from
563 * RESTARTER. So not allowing to change the state if it
564 * receives one_way hellow when it acts as HELPER for
565 * that specific neighbor.
567 thread_execute(master
, oneway_received
, on
, 0);
571 if (OSPF6_GR_IS_ACTIVE_HELPER(on
)) {
572 /* As per the GR Conformance Test Case 7.2. Section 3
573 * "Also, if X was the Designated Router on network segment S
574 * when the helping relationship began, Y maintains X as the
575 * Designated Router until the helping relationship is
577 * When it is a helper for this neighbor, It should not trigger
578 * the ISM Events. Also Intentionally not setting the priority
579 * and other fields so that when the neighbor exits the Grace
580 * period, it can handle if there is any change before GR and
583 if (IS_DEBUG_OSPF6_GR
)
585 "%s, Neighbor is under GR Restart, hence ignoring the ISM Events",
586 __PRETTY_FUNCTION__
);
592 * RFC 3623 - Section 2:
593 * "If the restarting router determines that it was the Designated
594 * Router on a given segment prior to the restart, it elects
595 * itself as the Designated Router again. The restarting router
596 * knows that it was the Designated Router if, while the
597 * associated interface is in Waiting state, a Hello packet is
598 * received from a neighbor listing the router as the Designated
601 if (oi
->area
->ospf6
->gr_info
.restart_in_progress
602 && oi
->state
== OSPF6_INTERFACE_WAITING
603 && hello
->drouter
== oi
->area
->ospf6
->router_id
)
604 oi
->drouter
= hello
->drouter
;
606 /* Schedule interface events */
608 thread_add_event(master
, backup_seen
, oi
, 0, NULL
);
610 thread_add_event(master
, neighbor_change
, oi
, 0, NULL
);
612 if (neighbor_ifindex_change
&& on
->state
== OSPF6_NEIGHBOR_FULL
)
613 OSPF6_ROUTER_LSA_SCHEDULE(oi
->area
);
616 static void ospf6_dbdesc_recv_master(struct ospf6_header
*oh
,
617 struct ospf6_neighbor
*on
)
619 struct ospf6_dbdesc
*dbdesc
;
622 dbdesc
= (struct ospf6_dbdesc
*)((caddr_t
)oh
623 + sizeof(struct ospf6_header
));
625 if (on
->state
< OSPF6_NEIGHBOR_INIT
) {
626 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV_HDR
))
627 zlog_debug("Neighbor state less than Init, ignore");
632 case OSPF6_NEIGHBOR_TWOWAY
:
633 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV_HDR
))
634 zlog_debug("Neighbor state is 2-Way, ignore");
637 case OSPF6_NEIGHBOR_INIT
:
638 thread_execute(master
, twoway_received
, on
, 0);
639 if (on
->state
!= OSPF6_NEIGHBOR_EXSTART
) {
640 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV_HDR
))
642 "Neighbor state is not ExStart, ignore");
645 /* else fall through to ExStart */
647 case OSPF6_NEIGHBOR_EXSTART
:
648 /* if neighbor obeys us as our slave, schedule negotiation_done
649 and process LSA Headers. Otherwise, ignore this message */
650 if (!CHECK_FLAG(dbdesc
->bits
, OSPF6_DBDESC_MSBIT
)
651 && !CHECK_FLAG(dbdesc
->bits
, OSPF6_DBDESC_IBIT
)
652 && ntohl(dbdesc
->seqnum
) == on
->dbdesc_seqnum
) {
653 /* execute NegotiationDone */
654 thread_execute(master
, negotiation_done
, on
, 0);
656 /* Record neighbor options */
657 memcpy(on
->options
, dbdesc
->options
,
658 sizeof(on
->options
));
660 zlog_warn("VRF %s: Nbr %s: Negotiation failed",
661 on
->ospf6_if
->interface
->vrf
->name
, on
->name
);
664 /* fall through to exchange */
666 case OSPF6_NEIGHBOR_EXCHANGE
:
667 if (!memcmp(dbdesc
, &on
->dbdesc_last
,
668 sizeof(struct ospf6_dbdesc
))) {
669 /* Duplicated DatabaseDescription is dropped by master
671 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV_HDR
))
673 "Duplicated dbdesc discarded by Master, ignore");
677 if (CHECK_FLAG(dbdesc
->bits
, OSPF6_DBDESC_MSBIT
)) {
679 "DbDesc recv: Master/Slave bit mismatch Nbr %s",
681 thread_add_event(master
, seqnumber_mismatch
, on
, 0,
686 if (CHECK_FLAG(dbdesc
->bits
, OSPF6_DBDESC_IBIT
)) {
687 zlog_warn("DbDesc recv: Initialize bit mismatch Nbr %s",
689 thread_add_event(master
, seqnumber_mismatch
, on
, 0,
694 if (memcmp(on
->options
, dbdesc
->options
, sizeof(on
->options
))) {
695 zlog_warn("DbDesc recv: Option field mismatch Nbr %s",
697 thread_add_event(master
, seqnumber_mismatch
, on
, 0,
702 if (ntohl(dbdesc
->seqnum
) != on
->dbdesc_seqnum
) {
704 "DbDesc recv: Sequence number mismatch Nbr %s (%#lx expected)",
705 on
->name
, (unsigned long)on
->dbdesc_seqnum
);
706 thread_add_event(master
, seqnumber_mismatch
, on
, 0,
712 case OSPF6_NEIGHBOR_LOADING
:
713 case OSPF6_NEIGHBOR_FULL
:
714 if (!memcmp(dbdesc
, &on
->dbdesc_last
,
715 sizeof(struct ospf6_dbdesc
))) {
716 /* Duplicated DatabaseDescription is dropped by master
718 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV_HDR
))
720 "Duplicated dbdesc discarded by Master, ignore");
725 "DbDesc recv: Not duplicate dbdesc in state %s Nbr %s",
726 ospf6_neighbor_state_str
[on
->state
], on
->name
);
727 thread_add_event(master
, seqnumber_mismatch
, on
, 0, NULL
);
735 /* Process LSA headers */
736 for (p
= (char *)((caddr_t
)dbdesc
+ sizeof(struct ospf6_dbdesc
));
737 p
+ sizeof(struct ospf6_lsa_header
) <= OSPF6_MESSAGE_END(oh
);
738 p
+= sizeof(struct ospf6_lsa_header
)) {
739 struct ospf6_lsa
*his
, *mine
;
740 struct ospf6_lsdb
*lsdb
= NULL
;
742 his
= ospf6_lsa_create_headeronly((struct ospf6_lsa_header
*)p
);
744 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
745 zlog_debug("%s", his
->name
);
747 switch (OSPF6_LSA_SCOPE(his
->header
->type
)) {
748 case OSPF6_SCOPE_LINKLOCAL
:
749 lsdb
= on
->ospf6_if
->lsdb
;
751 case OSPF6_SCOPE_AREA
:
752 lsdb
= on
->ospf6_if
->area
->lsdb
;
755 lsdb
= on
->ospf6_if
->area
->ospf6
->lsdb
;
757 case OSPF6_SCOPE_RESERVED
:
758 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
759 zlog_debug("Ignoring LSA of reserved scope");
760 ospf6_lsa_delete(his
);
764 if (ntohs(his
->header
->type
) == OSPF6_LSTYPE_AS_EXTERNAL
765 && (IS_AREA_STUB(on
->ospf6_if
->area
)
766 || IS_AREA_NSSA(on
->ospf6_if
->area
))) {
767 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
769 "SeqNumMismatch (E-bit mismatch), discard");
770 ospf6_lsa_delete(his
);
771 thread_add_event(master
, seqnumber_mismatch
, on
, 0,
776 mine
= ospf6_lsdb_lookup(his
->header
->type
, his
->header
->id
,
777 his
->header
->adv_router
, lsdb
);
779 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
780 zlog_debug("Add request (No database copy)");
781 ospf6_lsdb_add(ospf6_lsa_copy(his
), on
->request_list
);
782 } else if (ospf6_lsa_compare(his
, mine
) < 0) {
783 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
784 zlog_debug("Add request (Received MoreRecent)");
785 ospf6_lsdb_add(ospf6_lsa_copy(his
), on
->request_list
);
787 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
788 zlog_debug("Discard (Existing MoreRecent)");
790 ospf6_lsa_delete(his
);
793 assert(p
== OSPF6_MESSAGE_END(oh
));
795 /* Increment sequence number */
798 /* schedule send lsreq */
799 if (on
->request_list
->count
)
800 thread_add_event(master
, ospf6_lsreq_send
, on
, 0,
801 &on
->thread_send_lsreq
);
803 THREAD_OFF(on
->thread_send_dbdesc
);
806 if (!CHECK_FLAG(dbdesc
->bits
, OSPF6_DBDESC_MBIT
)
807 && !CHECK_FLAG(on
->dbdesc_bits
, OSPF6_DBDESC_MBIT
))
808 thread_add_event(master
, exchange_done
, on
, 0,
809 &on
->thread_exchange_done
);
811 thread_add_event(master
, ospf6_dbdesc_send_newone
, on
, 0,
812 &on
->thread_send_dbdesc
);
815 /* save last received dbdesc */
816 memcpy(&on
->dbdesc_last
, dbdesc
, sizeof(struct ospf6_dbdesc
));
819 static void ospf6_dbdesc_recv_slave(struct ospf6_header
*oh
,
820 struct ospf6_neighbor
*on
)
822 struct ospf6_dbdesc
*dbdesc
;
825 dbdesc
= (struct ospf6_dbdesc
*)((caddr_t
)oh
826 + sizeof(struct ospf6_header
));
828 if (on
->state
< OSPF6_NEIGHBOR_INIT
) {
829 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV_HDR
))
830 zlog_debug("Neighbor state less than Init, ignore");
835 case OSPF6_NEIGHBOR_TWOWAY
:
836 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV_HDR
))
837 zlog_debug("Neighbor state is 2-Way, ignore");
840 case OSPF6_NEIGHBOR_INIT
:
841 thread_execute(master
, twoway_received
, on
, 0);
842 if (on
->state
!= OSPF6_NEIGHBOR_EXSTART
) {
843 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV_HDR
))
845 "Neighbor state is not ExStart, ignore");
848 /* else fall through to ExStart */
850 case OSPF6_NEIGHBOR_EXSTART
:
851 /* If the neighbor is Master, act as Slave. Schedule
853 and process LSA Headers. Otherwise, ignore this message */
854 if (CHECK_FLAG(dbdesc
->bits
, OSPF6_DBDESC_IBIT
)
855 && CHECK_FLAG(dbdesc
->bits
, OSPF6_DBDESC_MBIT
)
856 && CHECK_FLAG(dbdesc
->bits
, OSPF6_DBDESC_MSBIT
)
858 == sizeof(struct ospf6_header
)
859 + sizeof(struct ospf6_dbdesc
)) {
860 /* set the master/slave bit to slave */
861 UNSET_FLAG(on
->dbdesc_bits
, OSPF6_DBDESC_MSBIT
);
863 /* set the DD sequence number to one specified by master
865 on
->dbdesc_seqnum
= ntohl(dbdesc
->seqnum
);
867 /* schedule NegotiationDone */
868 thread_execute(master
, negotiation_done
, on
, 0);
870 /* Record neighbor options */
871 memcpy(on
->options
, dbdesc
->options
,
872 sizeof(on
->options
));
874 zlog_warn("VRF %s: Nbr %s Negotiation failed",
875 on
->ospf6_if
->interface
->vrf
->name
, on
->name
);
880 case OSPF6_NEIGHBOR_EXCHANGE
:
881 if (!memcmp(dbdesc
, &on
->dbdesc_last
,
882 sizeof(struct ospf6_dbdesc
))) {
883 /* Duplicated DatabaseDescription causes slave to
885 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV_HDR
))
887 "Duplicated dbdesc causes retransmit");
888 THREAD_OFF(on
->thread_send_dbdesc
);
889 thread_add_event(master
, ospf6_dbdesc_send
, on
, 0,
890 &on
->thread_send_dbdesc
);
894 if (!CHECK_FLAG(dbdesc
->bits
, OSPF6_DBDESC_MSBIT
)) {
896 "DbDesc slave recv: Master/Slave bit mismatch Nbr %s",
898 thread_add_event(master
, seqnumber_mismatch
, on
, 0,
903 if (CHECK_FLAG(dbdesc
->bits
, OSPF6_DBDESC_IBIT
)) {
905 "DbDesc slave recv: Initialize bit mismatch Nbr %s",
907 thread_add_event(master
, seqnumber_mismatch
, on
, 0,
912 if (memcmp(on
->options
, dbdesc
->options
, sizeof(on
->options
))) {
914 "DbDesc slave recv: Option field mismatch Nbr %s",
916 thread_add_event(master
, seqnumber_mismatch
, on
, 0,
921 if (ntohl(dbdesc
->seqnum
) != on
->dbdesc_seqnum
+ 1) {
923 "DbDesc slave recv: Sequence number mismatch Nbr %s (%#lx expected)",
924 on
->name
, (unsigned long)on
->dbdesc_seqnum
+ 1);
925 thread_add_event(master
, seqnumber_mismatch
, on
, 0,
931 case OSPF6_NEIGHBOR_LOADING
:
932 case OSPF6_NEIGHBOR_FULL
:
933 if (!memcmp(dbdesc
, &on
->dbdesc_last
,
934 sizeof(struct ospf6_dbdesc
))) {
935 /* Duplicated DatabaseDescription causes slave to
937 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV_HDR
))
939 "Duplicated dbdesc causes retransmit");
940 THREAD_OFF(on
->thread_send_dbdesc
);
941 thread_add_event(master
, ospf6_dbdesc_send
, on
, 0,
942 &on
->thread_send_dbdesc
);
947 "DbDesc slave recv: Not duplicate dbdesc in state %s Nbr %s",
948 ospf6_neighbor_state_str
[on
->state
], on
->name
);
949 thread_add_event(master
, seqnumber_mismatch
, on
, 0, NULL
);
957 /* Process LSA headers */
958 for (p
= (char *)((caddr_t
)dbdesc
+ sizeof(struct ospf6_dbdesc
));
959 p
+ sizeof(struct ospf6_lsa_header
) <= OSPF6_MESSAGE_END(oh
);
960 p
+= sizeof(struct ospf6_lsa_header
)) {
961 struct ospf6_lsa
*his
, *mine
;
962 struct ospf6_lsdb
*lsdb
= NULL
;
964 his
= ospf6_lsa_create_headeronly((struct ospf6_lsa_header
*)p
);
966 switch (OSPF6_LSA_SCOPE(his
->header
->type
)) {
967 case OSPF6_SCOPE_LINKLOCAL
:
968 lsdb
= on
->ospf6_if
->lsdb
;
970 case OSPF6_SCOPE_AREA
:
971 lsdb
= on
->ospf6_if
->area
->lsdb
;
974 lsdb
= on
->ospf6_if
->area
->ospf6
->lsdb
;
976 case OSPF6_SCOPE_RESERVED
:
977 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
978 zlog_debug("Ignoring LSA of reserved scope");
979 ospf6_lsa_delete(his
);
983 if (OSPF6_LSA_SCOPE(his
->header
->type
) == OSPF6_SCOPE_AS
984 && (IS_AREA_STUB(on
->ospf6_if
->area
)
985 || IS_AREA_NSSA(on
->ospf6_if
->area
))) {
986 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
987 zlog_debug("E-bit mismatch with LSA Headers");
988 ospf6_lsa_delete(his
);
989 thread_add_event(master
, seqnumber_mismatch
, on
, 0,
994 mine
= ospf6_lsdb_lookup(his
->header
->type
, his
->header
->id
,
995 his
->header
->adv_router
, lsdb
);
996 if (mine
== NULL
|| ospf6_lsa_compare(his
, mine
) < 0) {
997 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
998 zlog_debug("Add request-list: %s", his
->name
);
999 ospf6_lsdb_add(ospf6_lsa_copy(his
), on
->request_list
);
1001 ospf6_lsa_delete(his
);
1004 assert(p
== OSPF6_MESSAGE_END(oh
));
1006 /* Set sequence number to Master's */
1007 on
->dbdesc_seqnum
= ntohl(dbdesc
->seqnum
);
1009 /* schedule send lsreq */
1010 if (on
->request_list
->count
)
1011 thread_add_event(master
, ospf6_lsreq_send
, on
, 0,
1012 &on
->thread_send_lsreq
);
1014 THREAD_OFF(on
->thread_send_dbdesc
);
1015 thread_add_event(master
, ospf6_dbdesc_send_newone
, on
, 0,
1016 &on
->thread_send_dbdesc
);
1018 /* save last received dbdesc */
1019 memcpy(&on
->dbdesc_last
, dbdesc
, sizeof(struct ospf6_dbdesc
));
1022 static void ospf6_dbdesc_recv(struct in6_addr
*src
, struct in6_addr
*dst
,
1023 struct ospf6_interface
*oi
,
1024 struct ospf6_header
*oh
)
1026 struct ospf6_neighbor
*on
;
1027 struct ospf6_dbdesc
*dbdesc
;
1029 on
= ospf6_neighbor_lookup(oh
->router_id
, oi
);
1031 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV_HDR
))
1032 zlog_debug("Neighbor not found, ignore");
1036 dbdesc
= (struct ospf6_dbdesc
*)((caddr_t
)oh
1037 + sizeof(struct ospf6_header
));
1039 if (((OSPF6_OPT_ISSET_EXT(dbdesc
->options
, OSPF6_OPT_AT
) ==
1041 (oi
->at_data
.flags
== 0)) ||
1042 ((OSPF6_OPT_ISSET_EXT(dbdesc
->options
, OSPF6_OPT_AT
) !=
1044 (oi
->at_data
.flags
!= 0))) {
1045 if (IS_OSPF6_DEBUG_AUTH_RX
)
1047 "VRF %s: IF %s AT-bit mismatch in dbdesc packet",
1048 oi
->interface
->vrf
->name
, oi
->interface
->name
);
1049 oi
->at_data
.rx_drop
++;
1053 /* Interface MTU check */
1054 if (!oi
->mtu_ignore
&& ntohs(dbdesc
->ifmtu
) != oi
->ifmtu
) {
1055 zlog_warn("VRF %s: I/F %s MTU mismatch (my %d rcvd %d)",
1056 oi
->interface
->vrf
->name
, oi
->interface
->name
,
1057 oi
->ifmtu
, ntohs(dbdesc
->ifmtu
));
1061 if (dbdesc
->reserved1
|| dbdesc
->reserved2
) {
1062 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV_HDR
))
1064 "Non-0 reserved field in %s's DbDesc, correct",
1066 dbdesc
->reserved1
= 0;
1067 dbdesc
->reserved2
= 0;
1072 if (ntohl(oh
->router_id
) < ntohl(oi
->area
->ospf6
->router_id
))
1073 ospf6_dbdesc_recv_master(oh
, on
);
1074 else if (ntohl(oi
->area
->ospf6
->router_id
) < ntohl(oh
->router_id
))
1075 ospf6_dbdesc_recv_slave(oh
, on
);
1077 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV_HDR
))
1078 zlog_debug("Can't decide which is master, ignore");
1082 static void ospf6_lsreq_recv(struct in6_addr
*src
, struct in6_addr
*dst
,
1083 struct ospf6_interface
*oi
,
1084 struct ospf6_header
*oh
)
1086 struct ospf6_neighbor
*on
;
1088 struct ospf6_lsreq_entry
*e
;
1089 struct ospf6_lsdb
*lsdb
= NULL
;
1090 struct ospf6_lsa
*lsa
;
1092 on
= ospf6_neighbor_lookup(oh
->router_id
, oi
);
1094 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV_HDR
))
1095 zlog_debug("Neighbor not found, ignore");
1099 if (on
->state
!= OSPF6_NEIGHBOR_EXCHANGE
1100 && on
->state
!= OSPF6_NEIGHBOR_LOADING
1101 && on
->state
!= OSPF6_NEIGHBOR_FULL
) {
1102 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV_HDR
))
1103 zlog_debug("Neighbor state less than Exchange, ignore");
1109 /* Process each request */
1110 for (p
= (char *)((caddr_t
)oh
+ sizeof(struct ospf6_header
));
1111 p
+ sizeof(struct ospf6_lsreq_entry
) <= OSPF6_MESSAGE_END(oh
);
1112 p
+= sizeof(struct ospf6_lsreq_entry
)) {
1113 e
= (struct ospf6_lsreq_entry
*)p
;
1115 switch (OSPF6_LSA_SCOPE(e
->type
)) {
1116 case OSPF6_SCOPE_LINKLOCAL
:
1117 lsdb
= on
->ospf6_if
->lsdb
;
1119 case OSPF6_SCOPE_AREA
:
1120 lsdb
= on
->ospf6_if
->area
->lsdb
;
1122 case OSPF6_SCOPE_AS
:
1123 lsdb
= on
->ospf6_if
->area
->ospf6
->lsdb
;
1126 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
1127 zlog_debug("Ignoring LSA of reserved scope");
1131 /* Find database copy */
1132 lsa
= ospf6_lsdb_lookup(e
->type
, e
->id
, e
->adv_router
, lsdb
);
1135 "Can't find requested lsa [%s Id:%pI4 Adv:%pI4] send badLSReq",
1136 ospf6_lstype_name(e
->type
), &e
->id
,
1138 thread_add_event(master
, bad_lsreq
, on
, 0, NULL
);
1142 ospf6_lsdb_add(ospf6_lsa_copy(lsa
), on
->lsupdate_list
);
1145 assert(p
== OSPF6_MESSAGE_END(oh
));
1147 /* schedule send lsupdate */
1148 THREAD_OFF(on
->thread_send_lsupdate
);
1149 thread_add_event(master
, ospf6_lsupdate_send_neighbor
, on
, 0,
1150 &on
->thread_send_lsupdate
);
1153 /* Verify, that the specified memory area contains exactly N valid IPv6
1154 prefixes as specified by RFC5340, A.4.1. */
1155 static unsigned ospf6_prefixes_examin(
1156 struct ospf6_prefix
*current
, /* start of buffer */
1158 const uint32_t req_num_pfxs
/* always compared with the actual number
1162 uint8_t requested_pfx_bytes
;
1163 uint32_t real_num_pfxs
= 0;
1166 if (length
< OSPF6_PREFIX_MIN_SIZE
) {
1167 zlog_warn("%s: undersized IPv6 prefix header",
1171 /* safe to look deeper */
1172 if (current
->prefix_length
> IPV6_MAX_BITLEN
) {
1173 zlog_warn("%s: invalid PrefixLength (%u bits)",
1174 __func__
, current
->prefix_length
);
1177 /* covers both fixed- and variable-sized fields */
1178 requested_pfx_bytes
=
1179 OSPF6_PREFIX_MIN_SIZE
1180 + OSPF6_PREFIX_SPACE(current
->prefix_length
);
1181 if (requested_pfx_bytes
> length
) {
1182 zlog_warn("%s: undersized IPv6 prefix", __func__
);
1186 length
-= requested_pfx_bytes
;
1187 current
= (struct ospf6_prefix
*)((caddr_t
)current
1188 + requested_pfx_bytes
);
1191 if (real_num_pfxs
!= req_num_pfxs
) {
1193 "%s: IPv6 prefix number mismatch (%u required, %u real)",
1194 __func__
, req_num_pfxs
, real_num_pfxs
);
1200 /* Verify an LSA to have a valid length and dispatch further (where
1201 appropriate) to check if the contents, including nested IPv6 prefixes,
1202 is properly sized/aligned within the LSA. Note that this function gets
1203 LSA type in network byte order, uses in host byte order and passes to
1204 ospf6_lstype_name() in network byte order again. */
1205 static unsigned ospf6_lsa_examin(struct ospf6_lsa_header
*lsah
,
1206 const uint16_t lsalen
,
1207 const uint8_t headeronly
)
1209 struct ospf6_intra_prefix_lsa
*intra_prefix_lsa
;
1210 struct ospf6_as_external_lsa
*as_external_lsa
;
1211 struct ospf6_link_lsa
*link_lsa
;
1212 unsigned exp_length
;
1216 /* In case an additional minimum length constraint is defined for
1218 LSA type, make sure that this constraint is met. */
1219 lsatype
= ntohs(lsah
->type
);
1220 ltindex
= lsatype
& OSPF6_LSTYPE_FCODE_MASK
;
1221 if (ltindex
< OSPF6_LSTYPE_SIZE
&& ospf6_lsa_minlen
[ltindex
]
1222 && lsalen
< ospf6_lsa_minlen
[ltindex
] + OSPF6_LSA_HEADER_SIZE
) {
1223 zlog_warn("%s: undersized (%u B) LSA", __func__
, lsalen
);
1227 case OSPF6_LSTYPE_ROUTER
:
1228 /* RFC5340 A.4.3, LSA header + OSPF6_ROUTER_LSA_MIN_SIZE bytes
1230 by N>=0 interface descriptions. */
1231 if ((lsalen
- OSPF6_LSA_HEADER_SIZE
- OSPF6_ROUTER_LSA_MIN_SIZE
)
1232 % OSPF6_ROUTER_LSDESC_FIX_SIZE
) {
1234 "%s: Router LSA interface description alignment error",
1239 case OSPF6_LSTYPE_NETWORK
:
1240 /* RFC5340 A.4.4, LSA header + OSPF6_NETWORK_LSA_MIN_SIZE bytes
1241 followed by N>=0 attached router descriptions. */
1242 if ((lsalen
- OSPF6_LSA_HEADER_SIZE
1243 - OSPF6_NETWORK_LSA_MIN_SIZE
)
1244 % OSPF6_NETWORK_LSDESC_FIX_SIZE
) {
1246 "%s: Network LSA router description alignment error",
1251 case OSPF6_LSTYPE_INTER_PREFIX
:
1252 /* RFC5340 A.4.5, LSA header + OSPF6_INTER_PREFIX_LSA_MIN_SIZE
1254 followed by 3-4 fields of a single IPv6 prefix. */
1257 return ospf6_prefixes_examin(
1258 (struct ospf6_prefix
1259 *)((caddr_t
)lsah
+ OSPF6_LSA_HEADER_SIZE
1260 + OSPF6_INTER_PREFIX_LSA_MIN_SIZE
),
1261 lsalen
- OSPF6_LSA_HEADER_SIZE
1262 - OSPF6_INTER_PREFIX_LSA_MIN_SIZE
,
1264 case OSPF6_LSTYPE_INTER_ROUTER
:
1265 /* RFC5340 A.4.6, fixed-size LSA. */
1267 > OSPF6_LSA_HEADER_SIZE
+ OSPF6_INTER_ROUTER_LSA_FIX_SIZE
) {
1268 zlog_warn("%s: Inter Router LSA oversized (%u B) LSA",
1273 case OSPF6_LSTYPE_AS_EXTERNAL
: /* RFC5340 A.4.7, same as A.4.8. */
1274 case OSPF6_LSTYPE_TYPE_7
:
1275 /* RFC5340 A.4.8, LSA header + OSPF6_AS_EXTERNAL_LSA_MIN_SIZE
1277 followed by 3-4 fields of IPv6 prefix and 3 conditional LSA
1279 16 bytes of forwarding address, 4 bytes of external route
1281 4 bytes of referenced link state ID. */
1285 (struct ospf6_as_external_lsa
1286 *)((caddr_t
)lsah
+ OSPF6_LSA_HEADER_SIZE
);
1288 OSPF6_LSA_HEADER_SIZE
+ OSPF6_AS_EXTERNAL_LSA_MIN_SIZE
;
1289 /* To find out if the last optional field (Referenced Link State
1291 assumed in this LSA, we need to access fixed fields of the
1293 prefix before ospf6_prefix_examin() confirms its sizing. */
1294 if (exp_length
+ OSPF6_PREFIX_MIN_SIZE
> lsalen
) {
1296 "%s: AS External undersized (%u B) LSA header",
1300 /* forwarding address */
1301 if (CHECK_FLAG(as_external_lsa
->bits_metric
, OSPF6_ASBR_BIT_F
))
1303 /* external route tag */
1304 if (CHECK_FLAG(as_external_lsa
->bits_metric
, OSPF6_ASBR_BIT_T
))
1306 /* referenced link state ID */
1307 if (as_external_lsa
->prefix
.u
._prefix_referenced_lstype
)
1309 /* All the fixed-size fields (mandatory and optional) must fit.
1311 this check does not include any IPv6 prefix fields. */
1312 if (exp_length
> lsalen
) {
1314 "%s: AS External undersized (%u B) LSA header",
1318 /* The last call completely covers the remainder (IPv6 prefix).
1320 return ospf6_prefixes_examin(
1321 (struct ospf6_prefix
1322 *)((caddr_t
)as_external_lsa
1323 + OSPF6_AS_EXTERNAL_LSA_MIN_SIZE
),
1324 lsalen
- exp_length
, 1);
1325 case OSPF6_LSTYPE_LINK
:
1326 /* RFC5340 A.4.9, LSA header + OSPF6_LINK_LSA_MIN_SIZE bytes
1328 by N>=0 IPv6 prefix blocks (with N declared beforehand). */
1331 link_lsa
= (struct ospf6_link_lsa
*)((caddr_t
)lsah
1332 + OSPF6_LSA_HEADER_SIZE
);
1333 return ospf6_prefixes_examin(
1334 (struct ospf6_prefix
*)((caddr_t
)link_lsa
1335 + OSPF6_LINK_LSA_MIN_SIZE
),
1336 lsalen
- OSPF6_LSA_HEADER_SIZE
1337 - OSPF6_LINK_LSA_MIN_SIZE
,
1338 ntohl(link_lsa
->prefix_num
) /* 32 bits */
1340 case OSPF6_LSTYPE_INTRA_PREFIX
:
1341 /* RFC5340 A.4.10, LSA header + OSPF6_INTRA_PREFIX_LSA_MIN_SIZE
1343 followed by N>=0 IPv6 prefixes (with N declared beforehand).
1348 (struct ospf6_intra_prefix_lsa
1349 *)((caddr_t
)lsah
+ OSPF6_LSA_HEADER_SIZE
);
1350 return ospf6_prefixes_examin(
1351 (struct ospf6_prefix
1352 *)((caddr_t
)intra_prefix_lsa
1353 + OSPF6_INTRA_PREFIX_LSA_MIN_SIZE
),
1354 lsalen
- OSPF6_LSA_HEADER_SIZE
1355 - OSPF6_INTRA_PREFIX_LSA_MIN_SIZE
,
1356 ntohs(intra_prefix_lsa
->prefix_num
) /* 16 bits */
1358 case OSPF6_LSTYPE_GRACE_LSA
:
1359 if (lsalen
< OSPF6_LSA_HEADER_SIZE
+ GRACE_PERIOD_TLV_SIZE
1360 + GRACE_RESTART_REASON_TLV_SIZE
) {
1361 if (IS_DEBUG_OSPF6_GR
)
1362 zlog_debug("%s: Undersized GraceLSA.",
1367 /* No additional validation is possible for unknown LSA types, which are
1368 themselves valid in OPSFv3, hence the default decision is to accept.
1373 /* Verify if the provided input buffer is a valid sequence of LSAs. This
1374 includes verification of LSA blocks length/alignment and dispatching
1375 of deeper-level checks. */
1377 ospf6_lsaseq_examin(struct ospf6_lsa_header
*lsah
, /* start of buffered data */
1378 size_t length
, const uint8_t headeronly
,
1379 /* When declared_num_lsas is not 0, compare it to the real
1381 and treat the difference as an error. */
1382 const uint32_t declared_num_lsas
)
1384 uint32_t counted_lsas
= 0;
1388 if (length
< OSPF6_LSA_HEADER_SIZE
) {
1390 "%s: undersized (%zu B) trailing (#%u) LSA header",
1391 __func__
, length
, counted_lsas
);
1394 /* save on ntohs() calls here and in the LSA validator */
1395 lsalen
= OSPF6_LSA_SIZE(lsah
);
1396 if (lsalen
< OSPF6_LSA_HEADER_SIZE
) {
1398 "%s: malformed LSA header #%u, declared length is %u B",
1399 __func__
, counted_lsas
, lsalen
);
1403 /* less checks here and in ospf6_lsa_examin() */
1404 if (MSG_OK
!= ospf6_lsa_examin(lsah
, lsalen
, 1)) {
1406 "%s: anomaly in header-only %s LSA #%u",
1407 __func__
, ospf6_lstype_name(lsah
->type
),
1411 lsah
= (struct ospf6_lsa_header
1413 + OSPF6_LSA_HEADER_SIZE
);
1414 length
-= OSPF6_LSA_HEADER_SIZE
;
1416 /* make sure the input buffer is deep enough before
1418 if (lsalen
> length
) {
1420 "%s: anomaly in %s LSA #%u: declared length is %u B, buffered length is %zu B",
1421 __func__
, ospf6_lstype_name(lsah
->type
),
1422 counted_lsas
, lsalen
, length
);
1425 if (MSG_OK
!= ospf6_lsa_examin(lsah
, lsalen
, 0)) {
1426 zlog_warn("%s: anomaly in %s LSA #%u", __func__
,
1427 ospf6_lstype_name(lsah
->type
),
1431 lsah
= (struct ospf6_lsa_header
*)((caddr_t
)lsah
1438 if (declared_num_lsas
&& counted_lsas
!= declared_num_lsas
) {
1439 zlog_warn("%s: #LSAs declared (%u) does not match actual (%u)",
1440 __func__
, declared_num_lsas
, counted_lsas
);
1446 /* Verify a complete OSPF packet for proper sizing/alignment. */
1447 static unsigned ospf6_packet_examin(struct ospf6_header
*oh
,
1448 const unsigned bytesonwire
)
1450 struct ospf6_lsupdate
*lsupd
;
1453 /* length, 1st approximation */
1454 if (bytesonwire
< OSPF6_HEADER_SIZE
) {
1455 zlog_warn("%s: undersized (%u B) packet", __func__
,
1460 /* Now it is safe to access header fields. */
1461 if (bytesonwire
!= ntohs(oh
->length
)) {
1462 zlog_warn("%s: %s packet length error (%u real, %u declared)",
1463 __func__
, ospf6_message_type(oh
->type
), bytesonwire
,
1469 if (oh
->version
!= OSPFV3_VERSION
) {
1470 zlog_warn("%s: invalid (%u) protocol version", __func__
,
1474 /* length, 2nd approximation */
1475 if (oh
->type
< OSPF6_MESSAGE_TYPE_ALL
&& ospf6_packet_minlen
[oh
->type
]
1477 < OSPF6_HEADER_SIZE
+ ospf6_packet_minlen
[oh
->type
]) {
1478 zlog_warn("%s: undersized (%u B) %s packet", __func__
,
1479 bytesonwire
, ospf6_message_type(oh
->type
));
1482 /* type-specific deeper validation */
1484 case OSPF6_MESSAGE_TYPE_HELLO
:
1485 /* RFC5340 A.3.2, packet header + OSPF6_HELLO_MIN_SIZE bytes
1487 by N>=0 router-IDs. */
1489 == (bytesonwire
- OSPF6_HEADER_SIZE
- OSPF6_HELLO_MIN_SIZE
)
1492 zlog_warn("%s: alignment error in %s packet", __func__
,
1493 ospf6_message_type(oh
->type
));
1495 case OSPF6_MESSAGE_TYPE_DBDESC
:
1496 /* RFC5340 A.3.3, packet header + OSPF6_DB_DESC_MIN_SIZE bytes
1498 by N>=0 header-only LSAs. */
1499 test
= ospf6_lsaseq_examin(
1500 (struct ospf6_lsa_header
*)((caddr_t
)oh
1502 + OSPF6_DB_DESC_MIN_SIZE
),
1503 bytesonwire
- OSPF6_HEADER_SIZE
1504 - OSPF6_DB_DESC_MIN_SIZE
,
1507 case OSPF6_MESSAGE_TYPE_LSREQ
:
1508 /* RFC5340 A.3.4, packet header + N>=0 LS description blocks. */
1510 == (bytesonwire
- OSPF6_HEADER_SIZE
- OSPF6_LS_REQ_MIN_SIZE
)
1511 % OSPF6_LSREQ_LSDESC_FIX_SIZE
)
1513 zlog_warn("%s: alignment error in %s packet", __func__
,
1514 ospf6_message_type(oh
->type
));
1516 case OSPF6_MESSAGE_TYPE_LSUPDATE
:
1517 /* RFC5340 A.3.5, packet header + OSPF6_LS_UPD_MIN_SIZE bytes
1519 by N>=0 full LSAs (with N declared beforehand). */
1520 lsupd
= (struct ospf6_lsupdate
*)((caddr_t
)oh
1521 + OSPF6_HEADER_SIZE
);
1522 test
= ospf6_lsaseq_examin(
1523 (struct ospf6_lsa_header
*)((caddr_t
)lsupd
1524 + OSPF6_LS_UPD_MIN_SIZE
),
1525 bytesonwire
- OSPF6_HEADER_SIZE
- OSPF6_LS_UPD_MIN_SIZE
,
1526 0, ntohl(lsupd
->lsa_number
) /* 32 bits */
1529 case OSPF6_MESSAGE_TYPE_LSACK
:
1530 /* RFC5340 A.3.6, packet header + N>=0 header-only LSAs. */
1531 test
= ospf6_lsaseq_examin(
1532 (struct ospf6_lsa_header
*)((caddr_t
)oh
1534 + OSPF6_LS_ACK_MIN_SIZE
),
1535 bytesonwire
- OSPF6_HEADER_SIZE
- OSPF6_LS_ACK_MIN_SIZE
,
1539 zlog_warn("%s: invalid (%u) message type", __func__
, oh
->type
);
1543 zlog_warn("%s: anomaly in %s packet", __func__
,
1544 ospf6_message_type(oh
->type
));
1548 /* Verify particular fields of otherwise correct received OSPF packet to
1549 meet the requirements of RFC. */
1550 static int ospf6_rxpacket_examin(struct ospf6_interface
*oi
,
1551 struct ospf6_header
*oh
,
1552 const unsigned bytesonwire
)
1555 if (MSG_OK
!= ospf6_packet_examin(oh
, bytesonwire
))
1559 if (oh
->area_id
!= oi
->area
->area_id
) {
1560 if (oh
->area_id
== OSPF_AREA_BACKBONE
)
1562 "VRF %s: I/F %s Message may be via Virtual Link: not supported",
1563 oi
->interface
->vrf
->name
, oi
->interface
->name
);
1566 "VRF %s: I/F %s Area-ID mismatch (my %pI4, rcvd %pI4)",
1567 oi
->interface
->vrf
->name
, oi
->interface
->name
,
1568 &oi
->area
->area_id
, &oh
->area_id
);
1572 /* Instance-ID check */
1573 if (oh
->instance_id
!= oi
->instance_id
) {
1575 "VRF %s: I/F %s Instance-ID mismatch (my %u, rcvd %u)",
1576 oi
->interface
->vrf
->name
, oi
->interface
->name
,
1577 oi
->instance_id
, oh
->instance_id
);
1581 /* Router-ID check */
1582 if (oh
->router_id
== oi
->area
->ospf6
->router_id
) {
1583 zlog_warn("VRF %s: I/F %s Duplicate Router-ID (%pI4)",
1584 oi
->interface
->vrf
->name
, oi
->interface
->name
,
1591 static void ospf6_lsupdate_recv(struct in6_addr
*src
, struct in6_addr
*dst
,
1592 struct ospf6_interface
*oi
,
1593 struct ospf6_header
*oh
)
1595 struct ospf6_neighbor
*on
;
1596 struct ospf6_lsupdate
*lsupdate
;
1599 on
= ospf6_neighbor_lookup(oh
->router_id
, oi
);
1601 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV_HDR
))
1602 zlog_debug("Neighbor not found, ignore");
1606 if (on
->state
!= OSPF6_NEIGHBOR_EXCHANGE
1607 && on
->state
!= OSPF6_NEIGHBOR_LOADING
1608 && on
->state
!= OSPF6_NEIGHBOR_FULL
) {
1609 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV_HDR
))
1610 zlog_debug("Neighbor state less than Exchange, ignore");
1614 lsupdate
= (struct ospf6_lsupdate
*)((caddr_t
)oh
1615 + sizeof(struct ospf6_header
));
1620 for (p
= (char *)((caddr_t
)lsupdate
+ sizeof(struct ospf6_lsupdate
));
1621 p
< OSPF6_MESSAGE_END(oh
)
1622 && p
+ OSPF6_LSA_SIZE(p
) <= OSPF6_MESSAGE_END(oh
);
1623 p
+= OSPF6_LSA_SIZE(p
)) {
1624 ospf6_receive_lsa(on
, (struct ospf6_lsa_header
*)p
);
1627 assert(p
== OSPF6_MESSAGE_END(oh
));
1630 static void ospf6_lsack_recv(struct in6_addr
*src
, struct in6_addr
*dst
,
1631 struct ospf6_interface
*oi
,
1632 struct ospf6_header
*oh
)
1634 struct ospf6_neighbor
*on
;
1636 struct ospf6_lsa
*his
, *mine
;
1637 struct ospf6_lsdb
*lsdb
= NULL
;
1639 assert(oh
->type
== OSPF6_MESSAGE_TYPE_LSACK
);
1641 on
= ospf6_neighbor_lookup(oh
->router_id
, oi
);
1643 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV_HDR
))
1644 zlog_debug("Neighbor not found, ignore");
1648 if (on
->state
!= OSPF6_NEIGHBOR_EXCHANGE
1649 && on
->state
!= OSPF6_NEIGHBOR_LOADING
1650 && on
->state
!= OSPF6_NEIGHBOR_FULL
) {
1651 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV_HDR
))
1652 zlog_debug("Neighbor state less than Exchange, ignore");
1658 for (p
= (char *)((caddr_t
)oh
+ sizeof(struct ospf6_header
));
1659 p
+ sizeof(struct ospf6_lsa_header
) <= OSPF6_MESSAGE_END(oh
);
1660 p
+= sizeof(struct ospf6_lsa_header
)) {
1661 his
= ospf6_lsa_create_headeronly((struct ospf6_lsa_header
*)p
);
1663 switch (OSPF6_LSA_SCOPE(his
->header
->type
)) {
1664 case OSPF6_SCOPE_LINKLOCAL
:
1665 lsdb
= on
->ospf6_if
->lsdb
;
1667 case OSPF6_SCOPE_AREA
:
1668 lsdb
= on
->ospf6_if
->area
->lsdb
;
1670 case OSPF6_SCOPE_AS
:
1671 lsdb
= on
->ospf6_if
->area
->ospf6
->lsdb
;
1673 case OSPF6_SCOPE_RESERVED
:
1674 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
1675 zlog_debug("Ignoring LSA of reserved scope");
1676 ospf6_lsa_delete(his
);
1680 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
1681 zlog_debug("%s acknowledged by %s", his
->name
,
1684 /* Find database copy */
1685 mine
= ospf6_lsdb_lookup(his
->header
->type
, his
->header
->id
,
1686 his
->header
->adv_router
, lsdb
);
1688 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
1689 zlog_debug("No database copy");
1690 ospf6_lsa_delete(his
);
1694 /* Check if the LSA is on his retrans-list */
1695 mine
= ospf6_lsdb_lookup(his
->header
->type
, his
->header
->id
,
1696 his
->header
->adv_router
,
1699 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
1700 zlog_debug("Not on %s's retrans-list",
1702 ospf6_lsa_delete(his
);
1706 if (ospf6_lsa_compare(his
, mine
) != 0) {
1707 /* Log this questionable acknowledgement,
1708 and examine the next one. */
1709 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
1710 zlog_debug("Questionable acknowledgement");
1711 ospf6_lsa_delete(his
);
1715 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
1717 "Acknowledged, remove from %s's retrans-list",
1720 ospf6_decrement_retrans_count(mine
);
1721 if (OSPF6_LSA_IS_MAXAGE(mine
))
1722 ospf6_maxage_remove(on
->ospf6_if
->area
->ospf6
);
1723 ospf6_lsdb_remove(mine
, on
->retrans_list
);
1724 ospf6_lsa_delete(his
);
1727 assert(p
== OSPF6_MESSAGE_END(oh
));
1730 static uint8_t *recvbuf
= NULL
;
1731 static uint8_t *sendbuf
= NULL
;
1732 static unsigned int iobuflen
= 0;
1734 int ospf6_iobuf_size(unsigned int size
)
1736 uint8_t *recvnew
, *sendnew
;
1738 if (size
<= iobuflen
)
1741 recvnew
= XMALLOC(MTYPE_OSPF6_MESSAGE
, size
);
1742 sendnew
= XMALLOC(MTYPE_OSPF6_MESSAGE
, size
);
1744 XFREE(MTYPE_OSPF6_MESSAGE
, recvbuf
);
1745 XFREE(MTYPE_OSPF6_MESSAGE
, sendbuf
);
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 memset(recvbuf
, 0, iobuflen
);
1783 iovector
[0].iov_base
= recvbuf
;
1784 iovector
[0].iov_len
= iobuflen
;
1785 iovector
[1].iov_base
= NULL
;
1786 iovector
[1].iov_len
= 0;
1788 /* receive message */
1789 len
= ospf6_recvmsg(&src
, &dst
, &ifindex
, iovector
, sockfd
);
1791 return OSPF6_READ_ERROR
;
1793 if ((uint
)len
> iobuflen
) {
1794 flog_err(EC_LIB_DEVELOPMENT
, "Excess message read");
1795 return OSPF6_READ_ERROR
;
1798 oi
= ospf6_interface_lookup_by_ifindex(ifindex
, ospf6
->vrf_id
);
1799 if (oi
== NULL
|| oi
->area
== NULL
1800 || CHECK_FLAG(oi
->flag
, OSPF6_INTERFACE_DISABLE
)) {
1801 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN
,
1803 zlog_debug("Message received on disabled interface");
1804 return OSPF6_READ_CONTINUE
;
1806 if (CHECK_FLAG(oi
->flag
, OSPF6_INTERFACE_PASSIVE
)) {
1807 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN
,
1809 zlog_debug("%s: Ignore message on passive interface %s",
1810 __func__
, oi
->interface
->name
);
1811 return OSPF6_READ_CONTINUE
;
1815 * Drop packet destined to another VRF.
1816 * This happens when raw_l3mdev_accept is set to 1.
1818 if (ospf6
->vrf_id
!= oi
->interface
->vrf
->vrf_id
)
1819 return OSPF6_READ_CONTINUE
;
1821 oh
= (struct ospf6_header
*)recvbuf
;
1822 ret
= ospf6_auth_validate_pkt(oi
, (uint32_t *)&len
, oh
, &at_len
,
1824 if (ret
== OSPF6_AUTH_VALIDATE_SUCCESS
) {
1825 ret
= ospf6_auth_check_digest(oh
, oi
, &src
, lls_len
);
1826 if (ret
== OSPF6_AUTH_VALIDATE_FAILURE
) {
1827 if (IS_OSPF6_DEBUG_AUTH_RX
)
1829 "RECV[%s]: OSPF packet auth digest miss-match on %s",
1830 oi
->interface
->name
,
1831 ospf6_message_type(oh
->type
));
1832 oi
->at_data
.rx_drop
++;
1833 return OSPF6_READ_CONTINUE
;
1835 } else if (ret
== OSPF6_AUTH_VALIDATE_FAILURE
) {
1836 oi
->at_data
.rx_drop
++;
1837 return OSPF6_READ_CONTINUE
;
1840 if (ospf6_rxpacket_examin(oi
, oh
, len
) != MSG_OK
)
1841 return OSPF6_READ_CONTINUE
;
1843 /* Being here means, that no sizing/alignment issues were detected in
1844 the input packet. This renders the additional checks performed below
1845 and also in the type-specific dispatching functions a dead code,
1846 which can be dismissed in a cleanup-focused review round later. */
1849 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV_HDR
)) {
1850 zlog_debug("%s received on %s", ospf6_message_type(oh
->type
),
1851 oi
->interface
->name
);
1852 zlog_debug(" src: %pI6", &src
);
1853 zlog_debug(" dst: %pI6", &dst
);
1856 case OSPF6_MESSAGE_TYPE_HELLO
:
1857 ospf6_hello_print(oh
, OSPF6_ACTION_RECV
);
1859 case OSPF6_MESSAGE_TYPE_DBDESC
:
1860 ospf6_dbdesc_print(oh
, OSPF6_ACTION_RECV
);
1862 case OSPF6_MESSAGE_TYPE_LSREQ
:
1863 ospf6_lsreq_print(oh
, OSPF6_ACTION_RECV
);
1865 case OSPF6_MESSAGE_TYPE_LSUPDATE
:
1866 ospf6_lsupdate_print(oh
, OSPF6_ACTION_RECV
);
1868 case OSPF6_MESSAGE_TYPE_LSACK
:
1869 ospf6_lsack_print(oh
, OSPF6_ACTION_RECV
);
1875 if ((at_len
!= 0) && IS_OSPF6_DEBUG_AUTH_RX
)
1876 ospf6_auth_hdr_dump_recv(oh
, (len
+ at_len
+ lls_len
),
1881 case OSPF6_MESSAGE_TYPE_HELLO
:
1882 ospf6_hello_recv(&src
, &dst
, oi
, oh
);
1885 case OSPF6_MESSAGE_TYPE_DBDESC
:
1886 ospf6_dbdesc_recv(&src
, &dst
, oi
, oh
);
1889 case OSPF6_MESSAGE_TYPE_LSREQ
:
1890 ospf6_lsreq_recv(&src
, &dst
, oi
, oh
);
1893 case OSPF6_MESSAGE_TYPE_LSUPDATE
:
1894 ospf6_lsupdate_recv(&src
, &dst
, oi
, oh
);
1897 case OSPF6_MESSAGE_TYPE_LSACK
:
1898 ospf6_lsack_recv(&src
, &dst
, oi
, oh
);
1905 return OSPF6_READ_CONTINUE
;
1908 void ospf6_receive(struct thread
*thread
)
1911 struct ospf6
*ospf6
;
1914 /* add next read thread */
1915 ospf6
= THREAD_ARG(thread
);
1916 sockfd
= THREAD_FD(thread
);
1918 thread_add_read(master
, ospf6_receive
, ospf6
, ospf6
->fd
,
1919 &ospf6
->t_ospf6_receive
);
1921 while (count
< ospf6
->write_oi_count
) {
1923 switch (ospf6_read_helper(sockfd
, ospf6
)) {
1924 case OSPF6_READ_ERROR
:
1926 case OSPF6_READ_CONTINUE
:
1932 static void ospf6_fill_hdr_checksum(struct ospf6_interface
*oi
,
1933 struct ospf6_packet
*op
)
1935 struct ipv6_ph ph
= {};
1936 struct ospf6_header
*oh
;
1937 void *offset
= NULL
;
1939 if (oi
->at_data
.flags
!= 0)
1942 memcpy(&ph
.src
, oi
->linklocal_addr
, sizeof(struct in6_addr
));
1943 memcpy(&ph
.dst
, &op
->dst
, sizeof(struct in6_addr
));
1944 ph
.ulpl
= htonl(op
->length
);
1945 ph
.next_hdr
= IPPROTO_OSPFIGP
;
1947 /* Suppress static analysis warnings about accessing icmp6 oob */
1948 oh
= (struct ospf6_header
*)STREAM_DATA(op
->s
);
1950 oh
->checksum
= in_cksum_with_ph6(&ph
, offset
, op
->length
);
1953 static void ospf6_make_header(uint8_t type
, struct ospf6_interface
*oi
,
1956 struct ospf6_header
*oh
;
1958 oh
= (struct ospf6_header
*)STREAM_DATA(s
);
1960 oh
->version
= (uint8_t)OSPFV3_VERSION
;
1964 oh
->router_id
= oi
->area
->ospf6
->router_id
;
1965 oh
->area_id
= oi
->area
->area_id
;
1967 oh
->instance_id
= oi
->instance_id
;
1970 stream_forward_endp(s
, OSPF6_HEADER_SIZE
);
1973 static void ospf6_fill_header(struct ospf6_interface
*oi
, struct stream
*s
,
1976 struct ospf6_header
*oh
;
1978 oh
= (struct ospf6_header
*)STREAM_DATA(s
);
1980 oh
->length
= htons(length
);
1983 static void ospf6_fill_lsupdate_header(struct stream
*s
, uint32_t lsa_num
)
1985 struct ospf6_header
*oh
;
1986 struct ospf6_lsupdate
*lsu
;
1988 oh
= (struct ospf6_header
*)STREAM_DATA(s
);
1990 lsu
= (struct ospf6_lsupdate
*)((caddr_t
)oh
1991 + sizeof(struct ospf6_header
));
1992 lsu
->lsa_number
= htonl(lsa_num
);
1995 static void ospf6_auth_trailer_copy_keychain_key(struct ospf6_interface
*oi
)
1997 char *keychain_name
= NULL
;
1998 struct keychain
*keychain
= NULL
;
1999 struct key
*key
= NULL
;
2001 keychain_name
= oi
->at_data
.keychain
;
2002 keychain
= keychain_lookup(keychain_name
);
2004 key
= key_lookup_for_send(keychain
);
2005 if (key
&& key
->string
&&
2006 key
->hash_algo
!= KEYCHAIN_ALGO_NULL
) {
2007 /* storing the values so that further
2008 * lookup can be avoided. after
2009 * processing the digest need to reset
2012 oi
->at_data
.hash_algo
= key
->hash_algo
;
2013 oi
->at_data
.auth_key
= XSTRDUP(
2014 MTYPE_OSPF6_AUTH_MANUAL_KEY
, key
->string
);
2015 oi
->at_data
.key_id
= key
->index
;
2016 SET_FLAG(oi
->at_data
.flags
,
2017 OSPF6_AUTH_TRAILER_KEYCHAIN_VALID
);
2022 static uint16_t ospf6_packet_max(struct ospf6_interface
*oi
)
2024 uint16_t at_len
= 0;
2026 assert(oi
->ifmtu
> sizeof(struct ip6_hdr
));
2028 if (oi
->at_data
.flags
!= 0) {
2029 if (CHECK_FLAG(oi
->at_data
.flags
, OSPF6_AUTH_TRAILER_KEYCHAIN
))
2030 ospf6_auth_trailer_copy_keychain_key(oi
);
2032 at_len
+= OSPF6_AUTH_HDR_MIN_SIZE
;
2033 at_len
+= keychain_get_hash_len(oi
->at_data
.hash_algo
);
2034 return oi
->ifmtu
- (sizeof(struct ip6_hdr
)) - at_len
;
2037 return oi
->ifmtu
- (sizeof(struct ip6_hdr
));
2040 static uint16_t ospf6_make_hello(struct ospf6_interface
*oi
, struct stream
*s
)
2042 struct listnode
*node
, *nnode
;
2043 struct ospf6_neighbor
*on
;
2044 uint16_t length
= OSPF6_HELLO_MIN_SIZE
;
2045 uint8_t options1
= oi
->area
->options
[1];
2047 if (oi
->at_data
.flags
!= 0)
2048 options1
|= OSPF6_OPT_AT
;
2050 stream_putl(s
, oi
->interface
->ifindex
);
2051 stream_putc(s
, oi
->priority
);
2052 stream_putc(s
, oi
->area
->options
[0]);
2053 stream_putc(s
, options1
);
2054 stream_putc(s
, oi
->area
->options
[2]);
2055 stream_putw(s
, oi
->hello_interval
);
2056 stream_putw(s
, oi
->dead_interval
);
2057 stream_put_ipv4(s
, oi
->drouter
);
2058 stream_put_ipv4(s
, oi
->bdrouter
);
2060 for (ALL_LIST_ELEMENTS(oi
->neighbor_list
, node
, nnode
, on
)) {
2061 if (on
->state
< OSPF6_NEIGHBOR_INIT
)
2064 if ((length
+ sizeof(uint32_t) + OSPF6_HEADER_SIZE
)
2065 > ospf6_packet_max(oi
)) {
2066 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_HELLO
,
2069 "sending Hello message: exceeds I/F MTU");
2073 stream_put_ipv4(s
, on
->router_id
);
2074 length
+= sizeof(uint32_t);
2080 static void ospf6_write(struct thread
*thread
)
2082 struct ospf6
*ospf6
= THREAD_ARG(thread
);
2083 struct ospf6_interface
*oi
;
2084 struct ospf6_interface
*last_serviced_oi
= NULL
;
2085 struct ospf6_header
*oh
;
2086 struct ospf6_packet
*op
;
2087 struct listnode
*node
;
2088 struct iovec iovector
[2];
2091 int64_t latency
= 0;
2092 struct timeval timestamp
;
2093 uint16_t at_len
= 0;
2095 if (ospf6
->fd
< 0) {
2096 zlog_warn("ospf6_write failed to send, fd %d", ospf6
->fd
);
2100 node
= listhead(ospf6
->oi_write_q
);
2102 oi
= listgetdata(node
);
2104 while ((pkt_count
< ospf6
->write_oi_count
) && oi
2105 && (last_serviced_oi
!= oi
)) {
2107 op
= ospf6_fifo_head(oi
->obuf
);
2109 assert(op
->length
>= OSPF6_HEADER_SIZE
);
2111 iovector
[0].iov_base
= (caddr_t
)stream_pnt(op
->s
);
2112 iovector
[0].iov_len
= op
->length
;
2113 iovector
[1].iov_base
= NULL
;
2114 iovector
[1].iov_len
= 0;
2116 oh
= (struct ospf6_header
*)STREAM_DATA(op
->s
);
2118 if (oi
->at_data
.flags
!= 0) {
2119 at_len
= ospf6_auth_len_get(oi
);
2121 iovector
[0].iov_len
=
2122 ntohs(oh
->length
) + at_len
;
2123 ospf6_auth_digest_send(oi
->linklocal_addr
, oi
,
2125 iovector
[0].iov_len
);
2127 iovector
[0].iov_len
= ntohs(oh
->length
);
2130 iovector
[0].iov_len
= ntohs(oh
->length
);
2133 len
= ospf6_sendmsg(oi
->linklocal_addr
, &op
->dst
,
2134 oi
->interface
->ifindex
, iovector
,
2137 if (len
!= (op
->length
+ (int)at_len
))
2138 flog_err(EC_LIB_DEVELOPMENT
,
2139 "Could not send entire message");
2141 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, SEND_HDR
)) {
2142 zlog_debug("%s send on %s",
2143 ospf6_message_type(oh
->type
),
2144 oi
->interface
->name
);
2145 zlog_debug(" src: %pI6", oi
->linklocal_addr
);
2146 zlog_debug(" dst: %pI6", &op
->dst
);
2148 case OSPF6_MESSAGE_TYPE_HELLO
:
2149 ospf6_hello_print(oh
, OSPF6_ACTION_SEND
);
2151 case OSPF6_MESSAGE_TYPE_DBDESC
:
2152 ospf6_dbdesc_print(oh
, OSPF6_ACTION_SEND
);
2154 case OSPF6_MESSAGE_TYPE_LSREQ
:
2155 ospf6_lsreq_print(oh
, OSPF6_ACTION_SEND
);
2157 case OSPF6_MESSAGE_TYPE_LSUPDATE
:
2158 ospf6_lsupdate_print(oh
, OSPF6_ACTION_SEND
);
2160 case OSPF6_MESSAGE_TYPE_LSACK
:
2161 ospf6_lsack_print(oh
, OSPF6_ACTION_SEND
);
2164 zlog_debug("Unknown message");
2170 case OSPF6_MESSAGE_TYPE_HELLO
:
2171 monotime(×tamp
);
2173 latency
= monotime_since(&oi
->last_hello
, NULL
)
2174 - ((int64_t)oi
->hello_interval
2177 /* log if latency exceeds the hello period */
2178 if (latency
> ((int64_t)oi
->hello_interval
* 1000000))
2179 zlog_warn("%s hello TX high latency %" PRId64
2182 oi
->last_hello
= timestamp
;
2185 case OSPF6_MESSAGE_TYPE_DBDESC
:
2188 case OSPF6_MESSAGE_TYPE_LSREQ
:
2191 case OSPF6_MESSAGE_TYPE_LSUPDATE
:
2194 case OSPF6_MESSAGE_TYPE_LSACK
:
2198 zlog_debug("Unknown message");
2203 if ((oi
->at_data
.flags
!= 0) &&
2204 (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, SEND_HDR
)) &&
2205 (IS_OSPF6_DEBUG_AUTH_TX
))
2206 ospf6_auth_hdr_dump_send(oh
, iovector
[0].iov_len
);
2208 /* initialize at_len to 0 for next packet */
2211 /* Now delete packet from queue. */
2212 ospf6_packet_delete(oi
);
2214 /* Move this interface to the tail of write_q to
2215 serve everyone in a round robin fashion */
2216 list_delete_node(ospf6
->oi_write_q
, node
);
2217 if (ospf6_fifo_head(oi
->obuf
) == NULL
) {
2219 last_serviced_oi
= NULL
;
2222 listnode_add(ospf6
->oi_write_q
, oi
);
2225 /* Setup to service from the head of the queue again */
2226 if (!list_isempty(ospf6
->oi_write_q
)) {
2227 node
= listhead(ospf6
->oi_write_q
);
2228 oi
= listgetdata(node
);
2232 /* If packets still remain in queue, call write thread. */
2233 if (!list_isempty(ospf6
->oi_write_q
))
2234 thread_add_write(master
, ospf6_write
, ospf6
, ospf6
->fd
,
2238 void ospf6_hello_send(struct thread
*thread
)
2240 struct ospf6_interface
*oi
;
2241 struct ospf6_packet
*op
;
2242 uint16_t length
= OSPF6_HEADER_SIZE
;
2244 oi
= (struct ospf6_interface
*)THREAD_ARG(thread
);
2246 if (oi
->state
<= OSPF6_INTERFACE_DOWN
) {
2247 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_HELLO
, SEND_HDR
))
2248 zlog_debug("Unable to send Hello on down interface %s",
2249 oi
->interface
->name
);
2253 op
= ospf6_packet_new(oi
->ifmtu
);
2255 ospf6_make_header(OSPF6_MESSAGE_TYPE_HELLO
, oi
, op
->s
);
2257 /* Prepare OSPF Hello body */
2258 length
+= ospf6_make_hello(oi
, op
->s
);
2259 if (length
== OSPF6_HEADER_SIZE
) {
2260 /* Hello overshooting MTU */
2261 ospf6_packet_free(op
);
2265 /* Fill OSPF header. */
2266 ospf6_fill_header(oi
, op
->s
, length
);
2268 /* Set packet length. */
2269 op
->length
= length
;
2271 op
->dst
= allspfrouters6
;
2273 ospf6_fill_hdr_checksum(oi
, op
);
2275 /* Add packet to the top of the interface output queue, so that they
2276 * can't get delayed by things like long queues of LS Update packets
2278 ospf6_packet_add_top(oi
, op
);
2280 /* set next thread */
2281 thread_add_timer(master
, ospf6_hello_send
, oi
, oi
->hello_interval
,
2282 &oi
->thread_send_hello
);
2284 OSPF6_MESSAGE_WRITE_ON(oi
);
2287 static uint16_t ospf6_make_dbdesc(struct ospf6_neighbor
*on
, struct stream
*s
)
2289 uint16_t length
= OSPF6_DB_DESC_MIN_SIZE
;
2290 struct ospf6_lsa
*lsa
, *lsanext
;
2291 uint8_t options1
= on
->ospf6_if
->area
->options
[1];
2293 if (on
->ospf6_if
->at_data
.flags
!= 0)
2294 options1
|= OSPF6_OPT_AT
;
2296 /* if this is initial one, initialize sequence number for DbDesc */
2297 if (CHECK_FLAG(on
->dbdesc_bits
, OSPF6_DBDESC_IBIT
)
2298 && (on
->dbdesc_seqnum
== 0)) {
2299 on
->dbdesc_seqnum
= monotime(NULL
);
2303 stream_putc(s
, 0); /* reserved 1 */
2304 stream_putc(s
, on
->ospf6_if
->area
->options
[0]);
2305 stream_putc(s
, options1
);
2306 stream_putc(s
, on
->ospf6_if
->area
->options
[2]);
2307 stream_putw(s
, on
->ospf6_if
->ifmtu
);
2308 stream_putc(s
, 0); /* reserved 2 */
2309 stream_putc(s
, on
->dbdesc_bits
);
2310 stream_putl(s
, on
->dbdesc_seqnum
);
2312 /* if this is not initial one, set LSA headers in dbdesc */
2313 if (!CHECK_FLAG(on
->dbdesc_bits
, OSPF6_DBDESC_IBIT
)) {
2314 for (ALL_LSDB(on
->dbdesc_list
, lsa
, lsanext
)) {
2315 ospf6_lsa_age_update_to_send(lsa
,
2316 on
->ospf6_if
->transdelay
);
2319 if ((length
+ sizeof(struct ospf6_lsa_header
)
2320 + OSPF6_HEADER_SIZE
)
2321 > ospf6_packet_max(on
->ospf6_if
)) {
2322 ospf6_lsa_unlock(lsa
);
2324 ospf6_lsa_unlock(lsanext
);
2327 stream_put(s
, lsa
->header
,
2328 sizeof(struct ospf6_lsa_header
));
2329 length
+= sizeof(struct ospf6_lsa_header
);
2335 void ospf6_dbdesc_send(struct thread
*thread
)
2337 struct ospf6_neighbor
*on
;
2338 uint16_t length
= OSPF6_HEADER_SIZE
;
2339 struct ospf6_packet
*op
;
2341 on
= (struct ospf6_neighbor
*)THREAD_ARG(thread
);
2342 on
->thread_send_dbdesc
= (struct thread
*)NULL
;
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 thread_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 thread
*thread
)
2381 struct ospf6_neighbor
*on
;
2382 struct ospf6_lsa
*lsa
, *lsanext
;
2383 unsigned int size
= 0;
2385 on
= (struct ospf6_neighbor
*)THREAD_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 thread_add_event(master
, exchange_done
, on
, 0,
2422 &on
->thread_exchange_done
);
2424 thread_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 thread
*thread
)
2503 struct ospf6_neighbor
*on
;
2504 struct ospf6_packet
*op
;
2505 uint16_t length
= OSPF6_HEADER_SIZE
;
2507 on
= (struct ospf6_neighbor
*)THREAD_ARG(thread
);
2508 on
->thread_send_lsreq
= (struct thread
*)NULL
;
2510 /* LSReq will be sent only in ExStart or Loading */
2511 if (on
->state
!= OSPF6_NEIGHBOR_EXCHANGE
2512 && on
->state
!= OSPF6_NEIGHBOR_LOADING
) {
2513 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_LSREQ
, SEND_HDR
))
2514 zlog_debug("Quit to send LSReq to neighbor %s state %s",
2516 ospf6_neighbor_state_str
[on
->state
]);
2520 /* schedule loading_done if request list is empty */
2521 if (on
->request_list
->count
== 0) {
2522 thread_add_event(master
, loading_done
, on
, 0, NULL
);
2526 op
= ospf6_packet_new(on
->ospf6_if
->ifmtu
);
2527 ospf6_make_header(OSPF6_MESSAGE_TYPE_LSREQ
, on
->ospf6_if
, op
->s
);
2529 length
+= ospf6_make_lsreq(on
, op
->s
);
2531 if (length
== OSPF6_HEADER_SIZE
) {
2532 /* Hello overshooting MTU */
2533 ospf6_packet_free(op
);
2537 /* Fill OSPF header. */
2538 ospf6_fill_header(on
->ospf6_if
, op
->s
, length
);
2540 /* Set packet length */
2541 op
->length
= length
;
2543 if (on
->ospf6_if
->state
== OSPF6_INTERFACE_POINTTOPOINT
)
2544 op
->dst
= allspfrouters6
;
2546 op
->dst
= on
->linklocal_addr
;
2548 ospf6_fill_hdr_checksum(on
->ospf6_if
, op
);
2549 ospf6_packet_add(on
->ospf6_if
, op
);
2551 OSPF6_MESSAGE_WRITE_ON(on
->ospf6_if
);
2553 /* set next thread */
2554 if (on
->request_list
->count
!= 0) {
2555 thread_add_timer(master
, ospf6_lsreq_send
, on
,
2556 on
->ospf6_if
->rxmt_interval
,
2557 &on
->thread_send_lsreq
);
2561 static void ospf6_send_lsupdate(struct ospf6_neighbor
*on
,
2562 struct ospf6_interface
*oi
,
2563 struct ospf6_packet
*op
)
2568 if ((on
->ospf6_if
->state
== OSPF6_INTERFACE_POINTTOPOINT
)
2569 || (on
->ospf6_if
->state
== OSPF6_INTERFACE_DR
)
2570 || (on
->ospf6_if
->state
== OSPF6_INTERFACE_BDR
))
2571 op
->dst
= allspfrouters6
;
2573 op
->dst
= on
->linklocal_addr
;
2576 if ((oi
->state
== OSPF6_INTERFACE_POINTTOPOINT
)
2577 || (oi
->state
== OSPF6_INTERFACE_DR
)
2578 || (oi
->state
== OSPF6_INTERFACE_BDR
))
2579 op
->dst
= allspfrouters6
;
2581 op
->dst
= alldrouters6
;
2584 ospf6_fill_hdr_checksum(oi
, op
);
2585 ospf6_packet_add(oi
, op
);
2586 /* If ospf instance is being deleted, send the packet
2589 if ((oi
->area
== NULL
) || (oi
->area
->ospf6
== NULL
))
2591 if (oi
->area
->ospf6
->inst_shutdown
) {
2592 if (oi
->on_write_q
== 0) {
2593 listnode_add(oi
->area
->ospf6
->oi_write_q
, oi
);
2596 thread_execute(master
, ospf6_write
, oi
->area
->ospf6
, 0);
2598 OSPF6_MESSAGE_WRITE_ON(oi
);
2602 static uint16_t ospf6_make_lsupdate_list(struct ospf6_neighbor
*on
,
2603 struct ospf6_packet
**op
, int *lsa_cnt
)
2605 uint16_t length
= OSPF6_LS_UPD_MIN_SIZE
;
2606 struct ospf6_lsa
*lsa
, *lsanext
;
2608 /* skip over fixed header */
2609 stream_forward_endp((*op
)->s
, OSPF6_LS_UPD_MIN_SIZE
);
2611 for (ALL_LSDB(on
->lsupdate_list
, lsa
, lsanext
)) {
2612 if ((length
+ OSPF6_LSA_SIZE(lsa
->header
) + OSPF6_HEADER_SIZE
) >
2613 ospf6_packet_max(on
->ospf6_if
)) {
2614 ospf6_fill_header(on
->ospf6_if
, (*op
)->s
,
2615 length
+ OSPF6_HEADER_SIZE
);
2616 (*op
)->length
= length
+ OSPF6_HEADER_SIZE
;
2617 ospf6_fill_lsupdate_header((*op
)->s
, *lsa_cnt
);
2618 ospf6_send_lsupdate(on
, NULL
, *op
);
2620 /* refresh packet */
2621 *op
= ospf6_packet_new(on
->ospf6_if
->ifmtu
);
2622 length
= OSPF6_LS_UPD_MIN_SIZE
;
2624 ospf6_make_header(OSPF6_MESSAGE_TYPE_LSUPDATE
,
2625 on
->ospf6_if
, (*op
)->s
);
2626 stream_forward_endp((*op
)->s
, OSPF6_LS_UPD_MIN_SIZE
);
2628 ospf6_lsa_age_update_to_send(lsa
, on
->ospf6_if
->transdelay
);
2629 stream_put((*op
)->s
, lsa
->header
, OSPF6_LSA_SIZE(lsa
->header
));
2631 length
+= OSPF6_LSA_SIZE(lsa
->header
);
2632 assert(lsa
->lock
== 2);
2633 ospf6_lsdb_remove(lsa
, on
->lsupdate_list
);
2638 static uint16_t ospf6_make_ls_retrans_list(struct ospf6_neighbor
*on
,
2639 struct ospf6_packet
**op
,
2642 uint16_t length
= OSPF6_LS_UPD_MIN_SIZE
;
2643 struct ospf6_lsa
*lsa
, *lsanext
;
2645 /* skip over fixed header */
2646 stream_forward_endp((*op
)->s
, OSPF6_LS_UPD_MIN_SIZE
);
2648 for (ALL_LSDB(on
->retrans_list
, lsa
, lsanext
)) {
2649 if ((length
+ OSPF6_LSA_SIZE(lsa
->header
) + OSPF6_HEADER_SIZE
) >
2650 ospf6_packet_max(on
->ospf6_if
)) {
2651 ospf6_fill_header(on
->ospf6_if
, (*op
)->s
,
2652 length
+ OSPF6_HEADER_SIZE
);
2653 (*op
)->length
= length
+ OSPF6_HEADER_SIZE
;
2654 ospf6_fill_lsupdate_header((*op
)->s
, *lsa_cnt
);
2655 if (on
->ospf6_if
->state
== OSPF6_INTERFACE_POINTTOPOINT
)
2656 (*op
)->dst
= allspfrouters6
;
2658 (*op
)->dst
= on
->linklocal_addr
;
2660 ospf6_fill_hdr_checksum(on
->ospf6_if
, *op
);
2661 ospf6_packet_add(on
->ospf6_if
, *op
);
2662 OSPF6_MESSAGE_WRITE_ON(on
->ospf6_if
);
2664 /* refresh packet */
2665 *op
= ospf6_packet_new(on
->ospf6_if
->ifmtu
);
2666 length
= OSPF6_LS_UPD_MIN_SIZE
;
2668 ospf6_make_header(OSPF6_MESSAGE_TYPE_LSUPDATE
,
2669 on
->ospf6_if
, (*op
)->s
);
2670 stream_forward_endp((*op
)->s
, OSPF6_LS_UPD_MIN_SIZE
);
2672 ospf6_lsa_age_update_to_send(lsa
, on
->ospf6_if
->transdelay
);
2673 stream_put((*op
)->s
, lsa
->header
, OSPF6_LSA_SIZE(lsa
->header
));
2675 length
+= OSPF6_LSA_SIZE(lsa
->header
);
2680 void ospf6_lsupdate_send_neighbor(struct thread
*thread
)
2682 struct ospf6_neighbor
*on
;
2683 struct ospf6_packet
*op
;
2684 uint16_t length
= OSPF6_HEADER_SIZE
;
2687 on
= (struct ospf6_neighbor
*)THREAD_ARG(thread
);
2688 on
->thread_send_lsupdate
= (struct thread
*)NULL
;
2690 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_LSUPDATE
, SEND_HDR
))
2691 zlog_debug("LSUpdate to neighbor %s", on
->name
);
2693 if (on
->state
< OSPF6_NEIGHBOR_EXCHANGE
) {
2694 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_LSUPDATE
,
2696 zlog_debug("Quit to send (neighbor state %s)",
2697 ospf6_neighbor_state_str
[on
->state
]);
2701 /* first do lsupdate_list */
2702 op
= ospf6_packet_new(on
->ospf6_if
->ifmtu
);
2703 ospf6_make_header(OSPF6_MESSAGE_TYPE_LSUPDATE
, on
->ospf6_if
, op
->s
);
2704 length
+= ospf6_make_lsupdate_list(on
, &op
, &lsa_cnt
);
2706 /* Fill OSPF header. */
2707 ospf6_fill_header(on
->ospf6_if
, op
->s
, length
);
2708 ospf6_fill_lsupdate_header(op
->s
, lsa_cnt
);
2709 op
->length
= length
;
2710 ospf6_send_lsupdate(on
, NULL
, op
);
2712 /* prepare new packet */
2713 op
= ospf6_packet_new(on
->ospf6_if
->ifmtu
);
2714 length
= OSPF6_HEADER_SIZE
;
2717 stream_reset(op
->s
);
2718 length
= OSPF6_HEADER_SIZE
;
2721 ospf6_make_header(OSPF6_MESSAGE_TYPE_LSUPDATE
, on
->ospf6_if
, op
->s
);
2722 /* now do retransmit list */
2723 length
+= ospf6_make_ls_retrans_list(on
, &op
, &lsa_cnt
);
2725 ospf6_fill_header(on
->ospf6_if
, op
->s
, length
);
2726 ospf6_fill_lsupdate_header(op
->s
, lsa_cnt
);
2727 op
->length
= length
;
2728 if (on
->ospf6_if
->state
== OSPF6_INTERFACE_POINTTOPOINT
)
2729 op
->dst
= allspfrouters6
;
2731 op
->dst
= on
->linklocal_addr
;
2732 ospf6_fill_hdr_checksum(on
->ospf6_if
, op
);
2733 ospf6_packet_add(on
->ospf6_if
, op
);
2734 OSPF6_MESSAGE_WRITE_ON(on
->ospf6_if
);
2736 ospf6_packet_free(op
);
2738 if (on
->lsupdate_list
->count
!= 0) {
2739 thread_add_event(master
, ospf6_lsupdate_send_neighbor
, on
, 0,
2740 &on
->thread_send_lsupdate
);
2741 } else if (on
->retrans_list
->count
!= 0) {
2742 thread_add_timer(master
, ospf6_lsupdate_send_neighbor
, on
,
2743 on
->ospf6_if
->rxmt_interval
,
2744 &on
->thread_send_lsupdate
);
2748 int ospf6_lsupdate_send_neighbor_now(struct ospf6_neighbor
*on
,
2749 struct ospf6_lsa
*lsa
)
2751 struct ospf6_packet
*op
;
2752 uint16_t length
= OSPF6_HEADER_SIZE
;
2754 op
= ospf6_packet_new(on
->ospf6_if
->ifmtu
);
2755 ospf6_make_header(OSPF6_MESSAGE_TYPE_LSUPDATE
, on
->ospf6_if
, op
->s
);
2757 /* skip over fixed header */
2758 stream_forward_endp(op
->s
, OSPF6_LS_UPD_MIN_SIZE
);
2759 ospf6_lsa_age_update_to_send(lsa
, on
->ospf6_if
->transdelay
);
2760 stream_put(op
->s
, lsa
->header
, OSPF6_LSA_SIZE(lsa
->header
));
2761 length
= OSPF6_HEADER_SIZE
+ OSPF6_LS_UPD_MIN_SIZE
2762 + OSPF6_LSA_SIZE(lsa
->header
);
2763 ospf6_fill_header(on
->ospf6_if
, op
->s
, length
);
2764 ospf6_fill_lsupdate_header(op
->s
, 1);
2765 op
->length
= length
;
2767 if (IS_OSPF6_DEBUG_FLOODING
2768 || IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_LSUPDATE
, SEND_HDR
))
2769 zlog_debug("%s: Send lsupdate with lsa %s (age %u)", __func__
,
2770 lsa
->name
, ntohs(lsa
->header
->age
));
2772 ospf6_send_lsupdate(on
, NULL
, op
);
2777 static uint16_t ospf6_make_lsupdate_interface(struct ospf6_interface
*oi
,
2778 struct ospf6_packet
**op
,
2781 uint16_t length
= OSPF6_LS_UPD_MIN_SIZE
;
2782 struct ospf6_lsa
*lsa
, *lsanext
;
2784 /* skip over fixed header */
2785 stream_forward_endp((*op
)->s
, OSPF6_LS_UPD_MIN_SIZE
);
2787 for (ALL_LSDB(oi
->lsupdate_list
, lsa
, lsanext
)) {
2788 if (length
+ OSPF6_LSA_SIZE(lsa
->header
) + OSPF6_HEADER_SIZE
>
2789 ospf6_packet_max(oi
)) {
2790 ospf6_fill_header(oi
, (*op
)->s
,
2791 length
+ OSPF6_HEADER_SIZE
);
2792 (*op
)->length
= length
+ OSPF6_HEADER_SIZE
;
2793 ospf6_fill_lsupdate_header((*op
)->s
, *lsa_cnt
);
2794 ospf6_send_lsupdate(NULL
, oi
, *op
);
2796 /* refresh packet */
2797 *op
= ospf6_packet_new(oi
->ifmtu
);
2798 length
= OSPF6_LS_UPD_MIN_SIZE
;
2800 ospf6_make_header(OSPF6_MESSAGE_TYPE_LSUPDATE
, oi
,
2802 stream_forward_endp((*op
)->s
, OSPF6_LS_UPD_MIN_SIZE
);
2805 ospf6_lsa_age_update_to_send(lsa
, oi
->transdelay
);
2806 stream_put((*op
)->s
, lsa
->header
, OSPF6_LSA_SIZE(lsa
->header
));
2808 length
+= OSPF6_LSA_SIZE(lsa
->header
);
2810 assert(lsa
->lock
== 2);
2811 ospf6_lsdb_remove(lsa
, oi
->lsupdate_list
);
2816 void ospf6_lsupdate_send_interface(struct thread
*thread
)
2818 struct ospf6_interface
*oi
;
2819 struct ospf6_packet
*op
;
2820 uint16_t length
= OSPF6_HEADER_SIZE
;
2823 oi
= (struct ospf6_interface
*)THREAD_ARG(thread
);
2824 oi
->thread_send_lsupdate
= (struct thread
*)NULL
;
2826 if (oi
->state
<= OSPF6_INTERFACE_WAITING
) {
2827 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_LSUPDATE
,
2830 "Quit to send LSUpdate to interface %s state %s",
2831 oi
->interface
->name
,
2832 ospf6_interface_state_str
[oi
->state
]);
2836 /* if we have nothing to send, return */
2837 if (oi
->lsupdate_list
->count
== 0)
2840 op
= ospf6_packet_new(oi
->ifmtu
);
2841 ospf6_make_header(OSPF6_MESSAGE_TYPE_LSUPDATE
, oi
, op
->s
);
2842 length
+= ospf6_make_lsupdate_interface(oi
, &op
, &lsa_cnt
);
2844 /* Fill OSPF header. */
2845 ospf6_fill_header(oi
, op
->s
, length
);
2846 ospf6_fill_lsupdate_header(op
->s
, lsa_cnt
);
2847 op
->length
= length
;
2848 ospf6_send_lsupdate(NULL
, oi
, op
);
2850 ospf6_packet_free(op
);
2852 if (oi
->lsupdate_list
->count
> 0) {
2853 thread_add_event(master
, ospf6_lsupdate_send_interface
, oi
, 0,
2854 &oi
->thread_send_lsupdate
);
2858 void ospf6_lsack_send_neighbor(struct thread
*thread
)
2860 struct ospf6_neighbor
*on
;
2861 struct ospf6_packet
*op
;
2862 uint16_t length
= OSPF6_HEADER_SIZE
;
2864 on
= (struct ospf6_neighbor
*)THREAD_ARG(thread
);
2865 on
->thread_send_lsack
= (struct thread
*)NULL
;
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
);
2942 oi
->thread_send_lsack
= (struct thread
*)NULL
;
2944 if (oi
->state
<= OSPF6_INTERFACE_WAITING
) {
2945 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_LSACK
, SEND_HDR
))
2947 "Quit to send LSAck to interface %s state %s",
2948 oi
->interface
->name
,
2949 ospf6_interface_state_str
[oi
->state
]);
2953 /* if we have nothing to send, return */
2954 if (oi
->lsack_list
->count
== 0)
2957 op
= ospf6_packet_new(oi
->ifmtu
);
2958 ospf6_make_header(OSPF6_MESSAGE_TYPE_LSACK
, oi
, op
->s
);
2960 length
+= ospf6_make_lsack_interface(oi
, op
);
2962 if (length
== OSPF6_HEADER_SIZE
) {
2963 ospf6_packet_free(op
);
2966 /* Fill OSPF header. */
2967 ospf6_fill_header(oi
, op
->s
, length
);
2969 /* Set packet length, dst and queue to FIFO. */
2970 op
->length
= length
;
2971 if ((oi
->state
== OSPF6_INTERFACE_POINTTOPOINT
)
2972 || (oi
->state
== OSPF6_INTERFACE_DR
)
2973 || (oi
->state
== OSPF6_INTERFACE_BDR
))
2974 op
->dst
= allspfrouters6
;
2976 op
->dst
= alldrouters6
;
2978 ospf6_fill_hdr_checksum(oi
, op
);
2979 ospf6_packet_add(oi
, op
);
2980 OSPF6_MESSAGE_WRITE_ON(oi
);
2982 if (oi
->lsack_list
->count
> 0)
2983 thread_add_event(master
, ospf6_lsack_send_interface
, oi
, 0,
2984 &oi
->thread_send_lsack
);
2988 DEFUN(debug_ospf6_message
, debug_ospf6_message_cmd
,
2989 "debug ospf6 message <unknown|hello|dbdesc|lsreq|lsupdate|lsack|all> [<send|recv|send-hdr|recv-hdr>]",
2991 "Debug OSPFv3 message\n"
2992 "Debug Unknown message\n"
2993 "Debug Hello message\n"
2994 "Debug Database Description message\n"
2995 "Debug Link State Request message\n"
2996 "Debug Link State Update message\n"
2997 "Debug Link State Acknowledgement message\n"
2998 "Debug All message\n"
2999 "Debug only sending message, entire packet\n"
3000 "Debug only receiving message, entire packet\n"
3001 "Debug only sending message, header only\n"
3002 "Debug only receiving message, header only\n")
3005 int idx_send_recv
= 4;
3006 unsigned char level
= 0;
3011 if (!strncmp(argv
[idx_packet
]->arg
, "u", 1))
3012 type
= OSPF6_MESSAGE_TYPE_UNKNOWN
;
3013 else if (!strncmp(argv
[idx_packet
]->arg
, "h", 1))
3014 type
= OSPF6_MESSAGE_TYPE_HELLO
;
3015 else if (!strncmp(argv
[idx_packet
]->arg
, "d", 1))
3016 type
= OSPF6_MESSAGE_TYPE_DBDESC
;
3017 else if (!strncmp(argv
[idx_packet
]->arg
, "lsr", 3))
3018 type
= OSPF6_MESSAGE_TYPE_LSREQ
;
3019 else if (!strncmp(argv
[idx_packet
]->arg
, "lsu", 3))
3020 type
= OSPF6_MESSAGE_TYPE_LSUPDATE
;
3021 else if (!strncmp(argv
[idx_packet
]->arg
, "lsa", 3))
3022 type
= OSPF6_MESSAGE_TYPE_LSACK
;
3023 else if (!strncmp(argv
[idx_packet
]->arg
, "a", 1))
3024 type
= OSPF6_MESSAGE_TYPE_ALL
;
3027 level
= OSPF6_DEBUG_MESSAGE_SEND
| OSPF6_DEBUG_MESSAGE_RECV
;
3028 else if (!strncmp(argv
[idx_send_recv
]->arg
, "send-h", 6))
3029 level
= OSPF6_DEBUG_MESSAGE_SEND_HDR
;
3030 else if (!strncmp(argv
[idx_send_recv
]->arg
, "s", 1))
3031 level
= OSPF6_DEBUG_MESSAGE_SEND
;
3032 else if (!strncmp(argv
[idx_send_recv
]->arg
, "recv-h", 6))
3033 level
= OSPF6_DEBUG_MESSAGE_RECV_HDR
;
3034 else if (!strncmp(argv
[idx_send_recv
]->arg
, "r", 1))
3035 level
= OSPF6_DEBUG_MESSAGE_RECV
;
3037 if (type
== OSPF6_MESSAGE_TYPE_ALL
) {
3038 for (i
= 0; i
< 6; i
++)
3039 OSPF6_DEBUG_MESSAGE_ON(i
, level
);
3041 OSPF6_DEBUG_MESSAGE_ON(type
, level
);
3046 DEFUN(no_debug_ospf6_message
, no_debug_ospf6_message_cmd
,
3047 "no debug ospf6 message <unknown|hello|dbdesc|lsreq|lsupdate|lsack|all> [<send|recv|send-hdr|recv-hdr>]",
3048 NO_STR DEBUG_STR OSPF6_STR
3049 "Debug OSPFv3 message\n"
3050 "Debug Unknown message\n"
3051 "Debug Hello message\n"
3052 "Debug Database Description message\n"
3053 "Debug Link State Request message\n"
3054 "Debug Link State Update message\n"
3055 "Debug Link State Acknowledgement message\n"
3056 "Debug All message\n"
3057 "Debug only sending message, entire pkt\n"
3058 "Debug only receiving message, entire pkt\n"
3059 "Debug only sending message, header only\n"
3060 "Debug only receiving message, header only\n")
3063 int idx_send_recv
= 5;
3064 unsigned char level
= 0;
3069 if (!strncmp(argv
[idx_packet
]->arg
, "u", 1))
3070 type
= OSPF6_MESSAGE_TYPE_UNKNOWN
;
3071 else if (!strncmp(argv
[idx_packet
]->arg
, "h", 1))
3072 type
= OSPF6_MESSAGE_TYPE_HELLO
;
3073 else if (!strncmp(argv
[idx_packet
]->arg
, "d", 1))
3074 type
= OSPF6_MESSAGE_TYPE_DBDESC
;
3075 else if (!strncmp(argv
[idx_packet
]->arg
, "lsr", 3))
3076 type
= OSPF6_MESSAGE_TYPE_LSREQ
;
3077 else if (!strncmp(argv
[idx_packet
]->arg
, "lsu", 3))
3078 type
= OSPF6_MESSAGE_TYPE_LSUPDATE
;
3079 else if (!strncmp(argv
[idx_packet
]->arg
, "lsa", 3))
3080 type
= OSPF6_MESSAGE_TYPE_LSACK
;
3081 else if (!strncmp(argv
[idx_packet
]->arg
, "a", 1))
3082 type
= OSPF6_MESSAGE_TYPE_ALL
;
3085 level
= OSPF6_DEBUG_MESSAGE_SEND
| OSPF6_DEBUG_MESSAGE_RECV
3086 | OSPF6_DEBUG_MESSAGE_SEND_HDR
3087 | OSPF6_DEBUG_MESSAGE_RECV_HDR
;
3088 else if (!strncmp(argv
[idx_send_recv
]->arg
, "send-h", 6))
3089 level
= OSPF6_DEBUG_MESSAGE_SEND_HDR
;
3090 else if (!strncmp(argv
[idx_send_recv
]->arg
, "s", 1))
3091 level
= OSPF6_DEBUG_MESSAGE_SEND
;
3092 else if (!strncmp(argv
[idx_send_recv
]->arg
, "recv-h", 6))
3093 level
= OSPF6_DEBUG_MESSAGE_RECV_HDR
;
3094 else if (!strncmp(argv
[idx_send_recv
]->arg
, "r", 1))
3095 level
= OSPF6_DEBUG_MESSAGE_RECV
;
3097 if (type
== OSPF6_MESSAGE_TYPE_ALL
) {
3098 for (i
= 0; i
< 6; i
++)
3099 OSPF6_DEBUG_MESSAGE_OFF(i
, level
);
3101 OSPF6_DEBUG_MESSAGE_OFF(type
, level
);
3107 int config_write_ospf6_debug_message(struct vty
*vty
)
3109 const char *type_str
[] = {"unknown", "hello", "dbdesc",
3110 "lsreq", "lsupdate", "lsack"};
3111 unsigned char s
= 0, r
= 0, sh
= 0, rh
= 0;
3114 for (i
= 0; i
< 6; i
++) {
3115 if (IS_OSPF6_DEBUG_MESSAGE_ENABLED(i
, SEND
))
3117 if (IS_OSPF6_DEBUG_MESSAGE_ENABLED(i
, RECV
))
3121 for (i
= 0; i
< 6; i
++) {
3122 if (IS_OSPF6_DEBUG_MESSAGE_ENABLED(i
, SEND_HDR
))
3124 if (IS_OSPF6_DEBUG_MESSAGE_ENABLED(i
, RECV_HDR
))
3128 if (s
== 0x3f && r
== 0x3f) {
3129 vty_out(vty
, "debug ospf6 message all\n");
3133 if (s
== 0x3f && r
== 0) {
3134 vty_out(vty
, "debug ospf6 message all send\n");
3136 } else if (s
== 0 && r
== 0x3f) {
3137 vty_out(vty
, "debug ospf6 message all recv\n");
3141 if (sh
== 0x3f && rh
== 0) {
3142 vty_out(vty
, "debug ospf6 message all send-hdr\n");
3144 } else if (sh
== 0 && rh
== 0x3f) {
3145 vty_out(vty
, "debug ospf6 message all recv-hdr\n");
3149 /* Unknown message is logged by default */
3150 if (!IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN
, SEND
)
3151 && !IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN
, RECV
))
3152 vty_out(vty
, "no debug ospf6 message unknown\n");
3153 else if (!IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN
, SEND
))
3154 vty_out(vty
, "no debug ospf6 message unknown send\n");
3155 else if (!IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN
, RECV
))
3156 vty_out(vty
, "no debug ospf6 message unknown recv\n");
3158 for (i
= 1; i
< 6; i
++) {
3159 if (IS_OSPF6_DEBUG_MESSAGE_ENABLED(i
, SEND
)
3160 && IS_OSPF6_DEBUG_MESSAGE_ENABLED(i
, RECV
)) {
3161 vty_out(vty
, "debug ospf6 message %s\n", type_str
[i
]);
3165 if (IS_OSPF6_DEBUG_MESSAGE_ENABLED(i
, SEND
))
3166 vty_out(vty
, "debug ospf6 message %s send\n",
3168 else if (IS_OSPF6_DEBUG_MESSAGE_ENABLED(i
, SEND_HDR
))
3169 vty_out(vty
, "debug ospf6 message %s send-hdr\n",
3172 if (IS_OSPF6_DEBUG_MESSAGE_ENABLED(i
, RECV
))
3173 vty_out(vty
, "debug ospf6 message %s recv\n",
3175 else if (IS_OSPF6_DEBUG_MESSAGE_ENABLED(i
, RECV_HDR
))
3176 vty_out(vty
, "debug ospf6 message %s recv-hdr\n",
3183 void install_element_ospf6_debug_message(void)
3185 install_element(ENABLE_NODE
, &debug_ospf6_message_cmd
);
3186 install_element(ENABLE_NODE
, &no_debug_ospf6_message_cmd
);
3187 install_element(CONFIG_NODE
, &debug_ospf6_message_cmd
);
3188 install_element(CONFIG_NODE
, &no_debug_ospf6_message_cmd
);