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"
31 #include "ospf6_proto.h"
32 #include "ospf6_lsa.h"
33 #include "ospf6_lsdb.h"
34 #include "ospf6_top.h"
35 #include "ospf6_network.h"
36 #include "ospf6_message.h"
38 #include "ospf6_area.h"
39 #include "ospf6_neighbor.h"
40 #include "ospf6_interface.h"
42 /* for structures and macros ospf6_lsa_examin() needs */
43 #include "ospf6_abr.h"
44 #include "ospf6_asbr.h"
45 #include "ospf6_intra.h"
47 #include "ospf6_flood.h"
50 #include <netinet/ip6.h>
52 DEFINE_MTYPE_STATIC(OSPF6D
, OSPF6_MESSAGE
, "OSPF6 message");
53 DEFINE_MTYPE_STATIC(OSPF6D
, OSPF6_PACKET
, "OSPF6 packet");
54 DEFINE_MTYPE_STATIC(OSPF6D
, OSPF6_FIFO
, "OSPF6 FIFO queue");
56 unsigned char conf_debug_ospf6_message
[6] = {0x03, 0, 0, 0, 0, 0};
57 static const struct message ospf6_message_type_str
[] = {
58 {OSPF6_MESSAGE_TYPE_HELLO
, "Hello"},
59 {OSPF6_MESSAGE_TYPE_DBDESC
, "DbDesc"},
60 {OSPF6_MESSAGE_TYPE_LSREQ
, "LSReq"},
61 {OSPF6_MESSAGE_TYPE_LSUPDATE
, "LSUpdate"},
62 {OSPF6_MESSAGE_TYPE_LSACK
, "LSAck"},
65 /* Minimum (besides the standard OSPF packet header) lengths for OSPF
66 packets of particular types, offset is the "type" field. */
67 const uint16_t ospf6_packet_minlen
[OSPF6_MESSAGE_TYPE_ALL
] = {
70 OSPF6_DB_DESC_MIN_SIZE
,
71 OSPF6_LS_REQ_MIN_SIZE
,
72 OSPF6_LS_UPD_MIN_SIZE
,
73 OSPF6_LS_ACK_MIN_SIZE
};
75 /* Minimum (besides the standard LSA header) lengths for LSAs of particular
76 types, offset is the "LSA function code" portion of "LSA type" field. */
77 const uint16_t ospf6_lsa_minlen
[OSPF6_LSTYPE_SIZE
] = {
79 /* 0x2001 */ OSPF6_ROUTER_LSA_MIN_SIZE
,
80 /* 0x2002 */ OSPF6_NETWORK_LSA_MIN_SIZE
,
81 /* 0x2003 */ OSPF6_INTER_PREFIX_LSA_MIN_SIZE
,
82 /* 0x2004 */ OSPF6_INTER_ROUTER_LSA_FIX_SIZE
,
83 /* 0x4005 */ OSPF6_AS_EXTERNAL_LSA_MIN_SIZE
,
85 /* 0x2007 */ OSPF6_AS_EXTERNAL_LSA_MIN_SIZE
,
86 /* 0x0008 */ OSPF6_LINK_LSA_MIN_SIZE
,
87 /* 0x2009 */ OSPF6_INTRA_PREFIX_LSA_MIN_SIZE
};
91 static void ospf6_header_print(struct ospf6_header
*oh
)
93 zlog_debug(" OSPFv%d Type:%d Len:%hu Router-ID:%pI4", oh
->version
,
94 oh
->type
, ntohs(oh
->length
), &oh
->router_id
);
95 zlog_debug(" Area-ID:%pI4 Cksum:%hx Instance-ID:%d", &oh
->area_id
,
96 ntohs(oh
->checksum
), oh
->instance_id
);
99 void ospf6_hello_print(struct ospf6_header
*oh
, int action
)
101 struct ospf6_hello
*hello
;
105 ospf6_header_print(oh
);
106 assert(oh
->type
== OSPF6_MESSAGE_TYPE_HELLO
);
108 hello
= (struct ospf6_hello
*)((caddr_t
)oh
109 + sizeof(struct ospf6_header
));
111 ospf6_options_printbuf(hello
->options
, options
, sizeof(options
));
113 zlog_debug(" I/F-Id:%ld Priority:%d Option:%s",
114 (unsigned long)ntohl(hello
->interface_id
), hello
->priority
,
116 zlog_debug(" HelloInterval:%hu DeadInterval:%hu",
117 ntohs(hello
->hello_interval
), ntohs(hello
->dead_interval
));
118 zlog_debug(" DR:%pI4 BDR:%pI4", &hello
->drouter
, &hello
->bdrouter
);
120 if ((IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
)
121 && action
== OSPF6_ACTION_RECV
)
122 || (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, SEND
)
123 && action
== OSPF6_ACTION_SEND
)) {
125 for (p
= (char *)((caddr_t
)hello
+ sizeof(struct ospf6_hello
));
126 p
+ sizeof(uint32_t) <= OSPF6_MESSAGE_END(oh
);
127 p
+= sizeof(uint32_t))
128 zlog_debug(" Neighbor: %pI4", (in_addr_t
*)p
);
130 assert(p
== OSPF6_MESSAGE_END(oh
));
134 void ospf6_dbdesc_print(struct ospf6_header
*oh
, int action
)
136 struct ospf6_dbdesc
*dbdesc
;
140 ospf6_header_print(oh
);
141 assert(oh
->type
== OSPF6_MESSAGE_TYPE_DBDESC
);
143 dbdesc
= (struct ospf6_dbdesc
*)((caddr_t
)oh
144 + sizeof(struct ospf6_header
));
146 ospf6_options_printbuf(dbdesc
->options
, options
, sizeof(options
));
148 zlog_debug(" MBZ: %#x Option: %s IfMTU: %hu", dbdesc
->reserved1
,
149 options
, ntohs(dbdesc
->ifmtu
));
150 zlog_debug(" MBZ: %#x Bits: %s%s%s SeqNum: %#lx", dbdesc
->reserved2
,
151 (CHECK_FLAG(dbdesc
->bits
, OSPF6_DBDESC_IBIT
) ? "I" : "-"),
152 (CHECK_FLAG(dbdesc
->bits
, OSPF6_DBDESC_MBIT
) ? "M" : "-"),
153 (CHECK_FLAG(dbdesc
->bits
, OSPF6_DBDESC_MSBIT
) ? "m" : "s"),
154 (unsigned long)ntohl(dbdesc
->seqnum
));
156 if ((IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
)
157 && action
== OSPF6_ACTION_RECV
)
158 || (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, SEND
)
159 && action
== OSPF6_ACTION_SEND
)) {
161 for (p
= (char *)((caddr_t
)dbdesc
162 + sizeof(struct ospf6_dbdesc
));
163 p
+ sizeof(struct ospf6_lsa_header
)
164 <= OSPF6_MESSAGE_END(oh
);
165 p
+= sizeof(struct ospf6_lsa_header
))
166 ospf6_lsa_header_print_raw(
167 (struct ospf6_lsa_header
*)p
);
169 assert(p
== OSPF6_MESSAGE_END(oh
));
173 void ospf6_lsreq_print(struct ospf6_header
*oh
, int action
)
177 ospf6_header_print(oh
);
178 assert(oh
->type
== OSPF6_MESSAGE_TYPE_LSREQ
);
180 if ((IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
)
181 && action
== OSPF6_ACTION_RECV
)
182 || (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, SEND
)
183 && action
== OSPF6_ACTION_SEND
)) {
185 for (p
= (char *)((caddr_t
)oh
+ sizeof(struct ospf6_header
));
186 p
+ sizeof(struct ospf6_lsreq_entry
)
187 <= OSPF6_MESSAGE_END(oh
);
188 p
+= sizeof(struct ospf6_lsreq_entry
)) {
189 struct ospf6_lsreq_entry
*e
=
190 (struct ospf6_lsreq_entry
*)p
;
192 zlog_debug(" [%s Id:%pI4 Adv:%pI4]",
193 ospf6_lstype_name(e
->type
), &e
->id
,
197 assert(p
== OSPF6_MESSAGE_END(oh
));
201 void ospf6_lsupdate_print(struct ospf6_header
*oh
, int action
)
203 struct ospf6_lsupdate
*lsupdate
;
207 ospf6_header_print(oh
);
208 assert(oh
->type
== OSPF6_MESSAGE_TYPE_LSUPDATE
);
210 lsupdate
= (struct ospf6_lsupdate
*)((caddr_t
)oh
211 + sizeof(struct ospf6_header
));
213 num
= ntohl(lsupdate
->lsa_number
);
214 zlog_debug(" Number of LSA: %ld", num
);
216 if ((IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
)
217 && action
== OSPF6_ACTION_RECV
)
218 || (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, SEND
)
219 && action
== OSPF6_ACTION_SEND
)) {
221 for (p
= (char *)((caddr_t
)lsupdate
222 + sizeof(struct ospf6_lsupdate
));
223 p
< OSPF6_MESSAGE_END(oh
)
224 && p
+ OSPF6_LSA_SIZE(p
) <= OSPF6_MESSAGE_END(oh
);
225 p
+= OSPF6_LSA_SIZE(p
)) {
226 ospf6_lsa_header_print_raw(
227 (struct ospf6_lsa_header
*)p
);
230 assert(p
== OSPF6_MESSAGE_END(oh
));
234 void ospf6_lsack_print(struct ospf6_header
*oh
, int action
)
238 ospf6_header_print(oh
);
239 assert(oh
->type
== OSPF6_MESSAGE_TYPE_LSACK
);
241 if ((IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
)
242 && action
== OSPF6_ACTION_RECV
)
243 || (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, SEND
)
244 && action
== OSPF6_ACTION_SEND
)) {
246 for (p
= (char *)((caddr_t
)oh
+ sizeof(struct ospf6_header
));
247 p
+ sizeof(struct ospf6_lsa_header
)
248 <= OSPF6_MESSAGE_END(oh
);
249 p
+= sizeof(struct ospf6_lsa_header
))
250 ospf6_lsa_header_print_raw(
251 (struct ospf6_lsa_header
*)p
);
253 assert(p
== OSPF6_MESSAGE_END(oh
));
257 static struct ospf6_packet
*ospf6_packet_new(size_t size
)
259 struct ospf6_packet
*new;
261 new = XCALLOC(MTYPE_OSPF6_PACKET
, sizeof(struct ospf6_packet
));
262 new->s
= stream_new(size
);
267 static void ospf6_packet_free(struct ospf6_packet
*op
)
272 XFREE(MTYPE_OSPF6_PACKET
, op
);
275 struct ospf6_fifo
*ospf6_fifo_new(void)
277 struct ospf6_fifo
*new;
279 new = XCALLOC(MTYPE_OSPF6_FIFO
, sizeof(struct ospf6_fifo
));
283 /* Add new packet to fifo. */
284 static void ospf6_fifo_push(struct ospf6_fifo
*fifo
, struct ospf6_packet
*op
)
287 fifo
->tail
->next
= op
;
296 /* Add new packet to head of fifo. */
297 static void ospf6_fifo_push_head(struct ospf6_fifo
*fifo
,
298 struct ospf6_packet
*op
)
300 op
->next
= fifo
->head
;
302 if (fifo
->tail
== NULL
)
310 /* Delete first packet from fifo. */
311 static struct ospf6_packet
*ospf6_fifo_pop(struct ospf6_fifo
*fifo
)
313 struct ospf6_packet
*op
;
318 fifo
->head
= op
->next
;
320 if (fifo
->head
== NULL
)
329 /* Return first fifo entry. */
330 static struct ospf6_packet
*ospf6_fifo_head(struct ospf6_fifo
*fifo
)
335 /* Flush ospf packet fifo. */
336 void ospf6_fifo_flush(struct ospf6_fifo
*fifo
)
338 struct ospf6_packet
*op
;
339 struct ospf6_packet
*next
;
341 for (op
= fifo
->head
; op
; op
= next
) {
343 ospf6_packet_free(op
);
345 fifo
->head
= fifo
->tail
= NULL
;
349 /* Free ospf packet fifo. */
350 void ospf6_fifo_free(struct ospf6_fifo
*fifo
)
352 ospf6_fifo_flush(fifo
);
354 XFREE(MTYPE_OSPF6_FIFO
, fifo
);
357 static void ospf6_packet_add(struct ospf6_interface
*oi
,
358 struct ospf6_packet
*op
)
360 /* Add packet to end of queue. */
361 ospf6_fifo_push(oi
->obuf
, op
);
363 /* Debug of packet fifo*/
364 /* ospf_fifo_debug (oi->obuf); */
367 static void ospf6_packet_add_top(struct ospf6_interface
*oi
,
368 struct ospf6_packet
*op
)
370 /* Add packet to head of queue. */
371 ospf6_fifo_push_head(oi
->obuf
, op
);
373 /* Debug of packet fifo*/
374 /* ospf_fifo_debug (oi->obuf); */
377 static void ospf6_packet_delete(struct ospf6_interface
*oi
)
379 struct ospf6_packet
*op
;
381 op
= ospf6_fifo_pop(oi
->obuf
);
384 ospf6_packet_free(op
);
388 static void ospf6_hello_recv(struct in6_addr
*src
, struct in6_addr
*dst
,
389 struct ospf6_interface
*oi
,
390 struct ospf6_header
*oh
)
392 struct ospf6_hello
*hello
;
393 struct ospf6_neighbor
*on
;
396 int neighborchange
= 0;
397 int neighbor_ifindex_change
= 0;
400 struct timeval timestamp
;
402 monotime(×tamp
);
403 hello
= (struct ospf6_hello
*)((caddr_t
)oh
404 + sizeof(struct ospf6_header
));
406 /* HelloInterval check */
407 if (ntohs(hello
->hello_interval
) != oi
->hello_interval
) {
409 "VRF %s: I/F %s HelloInterval mismatch: (my %d, rcvd %d)",
410 vrf_id_to_name(oi
->interface
->vrf_id
),
411 oi
->interface
->name
, oi
->hello_interval
,
412 ntohs(hello
->hello_interval
));
416 /* RouterDeadInterval check */
417 if (ntohs(hello
->dead_interval
) != oi
->dead_interval
) {
419 "VRF %s: I/F %s DeadInterval mismatch: (my %d, rcvd %d)",
420 vrf_id_to_name(oi
->interface
->vrf_id
),
421 oi
->interface
->name
, oi
->dead_interval
,
422 ntohs(hello
->dead_interval
));
427 if (OSPF6_OPT_ISSET(hello
->options
, OSPF6_OPT_E
)
428 != OSPF6_OPT_ISSET(oi
->area
->options
, OSPF6_OPT_E
)) {
429 zlog_warn("VRF %s: IF %s E-bit mismatch",
430 vrf_id_to_name(oi
->interface
->vrf_id
),
431 oi
->interface
->name
);
435 /* Find neighbor, create if not exist */
436 on
= ospf6_neighbor_lookup(oh
->router_id
, oi
);
438 on
= ospf6_neighbor_create(oh
->router_id
, oi
);
439 on
->prev_drouter
= on
->drouter
= hello
->drouter
;
440 on
->prev_bdrouter
= on
->bdrouter
= hello
->bdrouter
;
441 on
->priority
= hello
->priority
;
444 /* check latency against hello period */
446 latency
= monotime_since(&on
->last_hello
, NULL
)
447 - (oi
->hello_interval
* 1000000);
448 /* log if latency exceeds the hello period */
449 if (latency
> (oi
->hello_interval
* 1000000))
450 zlog_warn("%s RX %pI4 high latency %" PRId64
"us.", __func__
,
451 &on
->router_id
, latency
);
452 on
->last_hello
= timestamp
;
455 /* Always override neighbor's source address */
456 memcpy(&on
->linklocal_addr
, src
, sizeof(struct in6_addr
));
458 /* Neighbor ifindex check */
459 if (on
->ifindex
!= (ifindex_t
)ntohl(hello
->interface_id
)) {
460 on
->ifindex
= ntohl(hello
->interface_id
);
461 neighbor_ifindex_change
++;
465 for (p
= (char *)((caddr_t
)hello
+ sizeof(struct ospf6_hello
));
466 p
+ sizeof(uint32_t) <= OSPF6_MESSAGE_END(oh
);
467 p
+= sizeof(uint32_t)) {
468 uint32_t *router_id
= (uint32_t *)p
;
470 if (*router_id
== oi
->area
->ospf6
->router_id
)
474 assert(p
== OSPF6_MESSAGE_END(oh
));
476 /* RouterPriority check */
477 if (on
->priority
!= hello
->priority
) {
478 on
->priority
= hello
->priority
;
483 if (on
->drouter
!= hello
->drouter
) {
484 on
->prev_drouter
= on
->drouter
;
485 on
->drouter
= hello
->drouter
;
486 if (on
->prev_drouter
== on
->router_id
487 || on
->drouter
== on
->router_id
)
492 if (on
->bdrouter
!= hello
->bdrouter
) {
493 on
->prev_bdrouter
= on
->bdrouter
;
494 on
->bdrouter
= hello
->bdrouter
;
495 if (on
->prev_bdrouter
== on
->router_id
496 || on
->bdrouter
== on
->router_id
)
500 /* BackupSeen check */
501 if (oi
->state
== OSPF6_INTERFACE_WAITING
) {
502 if (hello
->bdrouter
== on
->router_id
)
504 else if (hello
->drouter
== on
->router_id
505 && hello
->bdrouter
== htonl(0))
511 /* Execute neighbor events */
512 thread_execute(master
, hello_received
, on
, 0);
514 thread_execute(master
, twoway_received
, on
, 0);
516 thread_execute(master
, oneway_received
, on
, 0);
518 /* Schedule interface events */
520 thread_add_event(master
, backup_seen
, oi
, 0, NULL
);
522 thread_add_event(master
, neighbor_change
, oi
, 0, NULL
);
524 if (neighbor_ifindex_change
&& on
->state
== OSPF6_NEIGHBOR_FULL
)
525 OSPF6_ROUTER_LSA_SCHEDULE(oi
->area
);
528 static void ospf6_dbdesc_recv_master(struct ospf6_header
*oh
,
529 struct ospf6_neighbor
*on
)
531 struct ospf6_dbdesc
*dbdesc
;
534 dbdesc
= (struct ospf6_dbdesc
*)((caddr_t
)oh
535 + sizeof(struct ospf6_header
));
537 if (on
->state
< OSPF6_NEIGHBOR_INIT
) {
538 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV_HDR
))
539 zlog_debug("Neighbor state less than Init, ignore");
544 case OSPF6_NEIGHBOR_TWOWAY
:
545 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV_HDR
))
546 zlog_debug("Neighbor state is 2-Way, ignore");
549 case OSPF6_NEIGHBOR_INIT
:
550 thread_execute(master
, twoway_received
, on
, 0);
551 if (on
->state
!= OSPF6_NEIGHBOR_EXSTART
) {
552 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV_HDR
))
554 "Neighbor state is not ExStart, ignore");
557 /* else fall through to ExStart */
559 case OSPF6_NEIGHBOR_EXSTART
:
560 /* if neighbor obeys us as our slave, schedule negotiation_done
561 and process LSA Headers. Otherwise, ignore this message */
562 if (!CHECK_FLAG(dbdesc
->bits
, OSPF6_DBDESC_MSBIT
)
563 && !CHECK_FLAG(dbdesc
->bits
, OSPF6_DBDESC_IBIT
)
564 && ntohl(dbdesc
->seqnum
) == on
->dbdesc_seqnum
) {
565 /* execute NegotiationDone */
566 thread_execute(master
, negotiation_done
, on
, 0);
568 /* Record neighbor options */
569 memcpy(on
->options
, dbdesc
->options
,
570 sizeof(on
->options
));
573 "VRF %s: Nbr %s: Negotiation failed",
574 vrf_id_to_name(on
->ospf6_if
->interface
->vrf_id
),
578 /* fall through to exchange */
580 case OSPF6_NEIGHBOR_EXCHANGE
:
581 if (!memcmp(dbdesc
, &on
->dbdesc_last
,
582 sizeof(struct ospf6_dbdesc
))) {
583 /* Duplicated DatabaseDescription is dropped by master
585 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV_HDR
))
587 "Duplicated dbdesc discarded by Master, ignore");
591 if (CHECK_FLAG(dbdesc
->bits
, OSPF6_DBDESC_MSBIT
)) {
592 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV_HDR
))
593 zlog_debug("Master/Slave bit mismatch");
594 thread_add_event(master
, seqnumber_mismatch
, on
, 0,
599 if (CHECK_FLAG(dbdesc
->bits
, OSPF6_DBDESC_IBIT
)) {
600 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV_HDR
))
601 zlog_debug("Initialize bit mismatch");
602 thread_add_event(master
, seqnumber_mismatch
, on
, 0,
607 if (memcmp(on
->options
, dbdesc
->options
, sizeof(on
->options
))) {
608 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV_HDR
))
609 zlog_debug("Option field mismatch");
610 thread_add_event(master
, seqnumber_mismatch
, on
, 0,
615 if (ntohl(dbdesc
->seqnum
) != on
->dbdesc_seqnum
) {
616 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV_HDR
))
618 "Sequence number mismatch (%#lx expected)",
619 (unsigned long)on
->dbdesc_seqnum
);
620 thread_add_event(master
, seqnumber_mismatch
, on
, 0,
626 case OSPF6_NEIGHBOR_LOADING
:
627 case OSPF6_NEIGHBOR_FULL
:
628 if (!memcmp(dbdesc
, &on
->dbdesc_last
,
629 sizeof(struct ospf6_dbdesc
))) {
630 /* Duplicated DatabaseDescription is dropped by master
632 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV_HDR
))
634 "Duplicated dbdesc discarded by Master, ignore");
638 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV_HDR
))
639 zlog_debug("Not duplicate dbdesc in state %s",
640 ospf6_neighbor_state_str
[on
->state
]);
641 thread_add_event(master
, seqnumber_mismatch
, on
, 0, NULL
);
649 /* Process LSA headers */
650 for (p
= (char *)((caddr_t
)dbdesc
+ sizeof(struct ospf6_dbdesc
));
651 p
+ sizeof(struct ospf6_lsa_header
) <= OSPF6_MESSAGE_END(oh
);
652 p
+= sizeof(struct ospf6_lsa_header
)) {
653 struct ospf6_lsa
*his
, *mine
;
654 struct ospf6_lsdb
*lsdb
= NULL
;
656 his
= ospf6_lsa_create_headeronly((struct ospf6_lsa_header
*)p
);
658 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
659 zlog_debug("%s", his
->name
);
661 switch (OSPF6_LSA_SCOPE(his
->header
->type
)) {
662 case OSPF6_SCOPE_LINKLOCAL
:
663 lsdb
= on
->ospf6_if
->lsdb
;
665 case OSPF6_SCOPE_AREA
:
666 lsdb
= on
->ospf6_if
->area
->lsdb
;
669 lsdb
= on
->ospf6_if
->area
->ospf6
->lsdb
;
671 case OSPF6_SCOPE_RESERVED
:
672 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
673 zlog_debug("Ignoring LSA of reserved scope");
674 ospf6_lsa_delete(his
);
679 if (ntohs(his
->header
->type
) == OSPF6_LSTYPE_AS_EXTERNAL
680 && (IS_AREA_STUB(on
->ospf6_if
->area
)
681 || IS_AREA_NSSA(on
->ospf6_if
->area
))) {
682 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
684 "SeqNumMismatch (E-bit mismatch), discard");
685 ospf6_lsa_delete(his
);
686 thread_add_event(master
, seqnumber_mismatch
, on
, 0,
691 mine
= ospf6_lsdb_lookup(his
->header
->type
, his
->header
->id
,
692 his
->header
->adv_router
, lsdb
);
694 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
695 zlog_debug("Add request (No database copy)");
696 ospf6_lsdb_add(ospf6_lsa_copy(his
), on
->request_list
);
697 } else if (ospf6_lsa_compare(his
, mine
) < 0) {
698 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
699 zlog_debug("Add request (Received MoreRecent)");
700 ospf6_lsdb_add(ospf6_lsa_copy(his
), on
->request_list
);
702 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
703 zlog_debug("Discard (Existing MoreRecent)");
705 ospf6_lsa_delete(his
);
708 assert(p
== OSPF6_MESSAGE_END(oh
));
710 /* Increment sequence number */
713 /* schedule send lsreq */
714 if (on
->request_list
->count
)
715 thread_add_event(master
, ospf6_lsreq_send
, on
, 0,
716 &on
->thread_send_lsreq
);
718 THREAD_OFF(on
->thread_send_dbdesc
);
721 if (!CHECK_FLAG(dbdesc
->bits
, OSPF6_DBDESC_MBIT
)
722 && !CHECK_FLAG(on
->dbdesc_bits
, OSPF6_DBDESC_MBIT
))
723 thread_add_event(master
, exchange_done
, on
, 0, NULL
);
725 on
->thread_send_dbdesc
= NULL
;
726 thread_add_event(master
, ospf6_dbdesc_send_newone
, on
, 0,
727 &on
->thread_send_dbdesc
);
730 /* save last received dbdesc */
731 memcpy(&on
->dbdesc_last
, dbdesc
, sizeof(struct ospf6_dbdesc
));
734 static void ospf6_dbdesc_recv_slave(struct ospf6_header
*oh
,
735 struct ospf6_neighbor
*on
)
737 struct ospf6_dbdesc
*dbdesc
;
740 dbdesc
= (struct ospf6_dbdesc
*)((caddr_t
)oh
741 + sizeof(struct ospf6_header
));
743 if (on
->state
< OSPF6_NEIGHBOR_INIT
) {
744 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV_HDR
))
745 zlog_debug("Neighbor state less than Init, ignore");
750 case OSPF6_NEIGHBOR_TWOWAY
:
751 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV_HDR
))
752 zlog_debug("Neighbor state is 2-Way, ignore");
755 case OSPF6_NEIGHBOR_INIT
:
756 thread_execute(master
, twoway_received
, on
, 0);
757 if (on
->state
!= OSPF6_NEIGHBOR_EXSTART
) {
758 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV_HDR
))
760 "Neighbor state is not ExStart, ignore");
763 /* else fall through to ExStart */
765 case OSPF6_NEIGHBOR_EXSTART
:
766 /* If the neighbor is Master, act as Slave. Schedule
768 and process LSA Headers. Otherwise, ignore this message */
769 if (CHECK_FLAG(dbdesc
->bits
, OSPF6_DBDESC_IBIT
)
770 && CHECK_FLAG(dbdesc
->bits
, OSPF6_DBDESC_MBIT
)
771 && CHECK_FLAG(dbdesc
->bits
, OSPF6_DBDESC_MSBIT
)
773 == sizeof(struct ospf6_header
)
774 + sizeof(struct ospf6_dbdesc
)) {
775 /* set the master/slave bit to slave */
776 UNSET_FLAG(on
->dbdesc_bits
, OSPF6_DBDESC_MSBIT
);
778 /* set the DD sequence number to one specified by master
780 on
->dbdesc_seqnum
= ntohl(dbdesc
->seqnum
);
782 /* schedule NegotiationDone */
783 thread_execute(master
, negotiation_done
, on
, 0);
785 /* Record neighbor options */
786 memcpy(on
->options
, dbdesc
->options
,
787 sizeof(on
->options
));
790 "VRF %s: Nbr %s Negotiation failed",
791 vrf_id_to_name(on
->ospf6_if
->interface
->vrf_id
),
797 case OSPF6_NEIGHBOR_EXCHANGE
:
798 if (!memcmp(dbdesc
, &on
->dbdesc_last
,
799 sizeof(struct ospf6_dbdesc
))) {
800 /* Duplicated DatabaseDescription causes slave to
802 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV_HDR
))
804 "Duplicated dbdesc causes retransmit");
805 THREAD_OFF(on
->thread_send_dbdesc
);
806 on
->thread_send_dbdesc
= NULL
;
807 thread_add_event(master
, ospf6_dbdesc_send
, on
, 0,
808 &on
->thread_send_dbdesc
);
812 if (!CHECK_FLAG(dbdesc
->bits
, OSPF6_DBDESC_MSBIT
)) {
813 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV_HDR
))
814 zlog_debug("Master/Slave bit mismatch");
815 thread_add_event(master
, seqnumber_mismatch
, on
, 0,
820 if (CHECK_FLAG(dbdesc
->bits
, OSPF6_DBDESC_IBIT
)) {
821 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV_HDR
))
822 zlog_debug("Initialize bit mismatch");
823 thread_add_event(master
, seqnumber_mismatch
, on
, 0,
828 if (memcmp(on
->options
, dbdesc
->options
, sizeof(on
->options
))) {
829 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV_HDR
))
830 zlog_debug("Option field mismatch");
831 thread_add_event(master
, seqnumber_mismatch
, on
, 0,
836 if (ntohl(dbdesc
->seqnum
) != on
->dbdesc_seqnum
+ 1) {
837 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV_HDR
))
839 "Sequence number mismatch (%#lx expected)",
840 (unsigned long)on
->dbdesc_seqnum
+ 1);
841 thread_add_event(master
, seqnumber_mismatch
, on
, 0,
847 case OSPF6_NEIGHBOR_LOADING
:
848 case OSPF6_NEIGHBOR_FULL
:
849 if (!memcmp(dbdesc
, &on
->dbdesc_last
,
850 sizeof(struct ospf6_dbdesc
))) {
851 /* Duplicated DatabaseDescription causes slave to
853 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV_HDR
))
855 "Duplicated dbdesc causes retransmit");
856 THREAD_OFF(on
->thread_send_dbdesc
);
857 thread_add_event(master
, ospf6_dbdesc_send
, on
, 0,
858 &on
->thread_send_dbdesc
);
862 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV_HDR
))
863 zlog_debug("Not duplicate dbdesc in state %s",
864 ospf6_neighbor_state_str
[on
->state
]);
865 thread_add_event(master
, seqnumber_mismatch
, on
, 0, NULL
);
873 /* Process LSA headers */
874 for (p
= (char *)((caddr_t
)dbdesc
+ sizeof(struct ospf6_dbdesc
));
875 p
+ sizeof(struct ospf6_lsa_header
) <= OSPF6_MESSAGE_END(oh
);
876 p
+= sizeof(struct ospf6_lsa_header
)) {
877 struct ospf6_lsa
*his
, *mine
;
878 struct ospf6_lsdb
*lsdb
= NULL
;
880 his
= ospf6_lsa_create_headeronly((struct ospf6_lsa_header
*)p
);
882 switch (OSPF6_LSA_SCOPE(his
->header
->type
)) {
883 case OSPF6_SCOPE_LINKLOCAL
:
884 lsdb
= on
->ospf6_if
->lsdb
;
886 case OSPF6_SCOPE_AREA
:
887 lsdb
= on
->ospf6_if
->area
->lsdb
;
890 lsdb
= on
->ospf6_if
->area
->ospf6
->lsdb
;
892 case OSPF6_SCOPE_RESERVED
:
893 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
894 zlog_debug("Ignoring LSA of reserved scope");
895 ospf6_lsa_delete(his
);
900 if (OSPF6_LSA_SCOPE(his
->header
->type
) == OSPF6_SCOPE_AS
901 && (IS_AREA_STUB(on
->ospf6_if
->area
)
902 || IS_AREA_NSSA(on
->ospf6_if
->area
))) {
903 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
904 zlog_debug("E-bit mismatch with LSA Headers");
905 ospf6_lsa_delete(his
);
906 thread_add_event(master
, seqnumber_mismatch
, on
, 0,
911 mine
= ospf6_lsdb_lookup(his
->header
->type
, his
->header
->id
,
912 his
->header
->adv_router
, lsdb
);
913 if (mine
== NULL
|| ospf6_lsa_compare(his
, mine
) < 0) {
914 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
915 zlog_debug("Add request-list: %s", his
->name
);
916 ospf6_lsdb_add(ospf6_lsa_copy(his
), on
->request_list
);
918 ospf6_lsa_delete(his
);
921 assert(p
== OSPF6_MESSAGE_END(oh
));
923 /* Set sequence number to Master's */
924 on
->dbdesc_seqnum
= ntohl(dbdesc
->seqnum
);
926 /* schedule send lsreq */
927 if (on
->request_list
->count
)
928 thread_add_event(master
, ospf6_lsreq_send
, on
, 0,
929 &on
->thread_send_lsreq
);
931 THREAD_OFF(on
->thread_send_dbdesc
);
932 thread_add_event(master
, ospf6_dbdesc_send_newone
, on
, 0,
933 &on
->thread_send_dbdesc
);
935 /* save last received dbdesc */
936 memcpy(&on
->dbdesc_last
, dbdesc
, sizeof(struct ospf6_dbdesc
));
939 static void ospf6_dbdesc_recv(struct in6_addr
*src
, struct in6_addr
*dst
,
940 struct ospf6_interface
*oi
,
941 struct ospf6_header
*oh
)
943 struct ospf6_neighbor
*on
;
944 struct ospf6_dbdesc
*dbdesc
;
946 on
= ospf6_neighbor_lookup(oh
->router_id
, oi
);
948 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV_HDR
))
949 zlog_debug("Neighbor not found, ignore");
953 dbdesc
= (struct ospf6_dbdesc
*)((caddr_t
)oh
954 + sizeof(struct ospf6_header
));
956 /* Interface MTU check */
957 if (!oi
->mtu_ignore
&& ntohs(dbdesc
->ifmtu
) != oi
->ifmtu
) {
958 zlog_warn("VRF %s: I/F %s MTU mismatch (my %d rcvd %d)",
959 vrf_id_to_name(oi
->interface
->vrf_id
),
960 oi
->interface
->name
, oi
->ifmtu
, ntohs(dbdesc
->ifmtu
));
964 if (dbdesc
->reserved1
|| dbdesc
->reserved2
) {
965 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV_HDR
))
967 "Non-0 reserved field in %s's DbDesc, correct",
969 dbdesc
->reserved1
= 0;
970 dbdesc
->reserved2
= 0;
975 if (ntohl(oh
->router_id
) < ntohl(oi
->area
->ospf6
->router_id
))
976 ospf6_dbdesc_recv_master(oh
, on
);
977 else if (ntohl(oi
->area
->ospf6
->router_id
) < ntohl(oh
->router_id
))
978 ospf6_dbdesc_recv_slave(oh
, on
);
980 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV_HDR
))
981 zlog_debug("Can't decide which is master, ignore");
985 static void ospf6_lsreq_recv(struct in6_addr
*src
, struct in6_addr
*dst
,
986 struct ospf6_interface
*oi
,
987 struct ospf6_header
*oh
)
989 struct ospf6_neighbor
*on
;
991 struct ospf6_lsreq_entry
*e
;
992 struct ospf6_lsdb
*lsdb
= NULL
;
993 struct ospf6_lsa
*lsa
;
995 on
= ospf6_neighbor_lookup(oh
->router_id
, oi
);
997 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV_HDR
))
998 zlog_debug("Neighbor not found, ignore");
1002 if (on
->state
!= OSPF6_NEIGHBOR_EXCHANGE
1003 && on
->state
!= OSPF6_NEIGHBOR_LOADING
1004 && on
->state
!= OSPF6_NEIGHBOR_FULL
) {
1005 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV_HDR
))
1006 zlog_debug("Neighbor state less than Exchange, ignore");
1012 /* Process each request */
1013 for (p
= (char *)((caddr_t
)oh
+ sizeof(struct ospf6_header
));
1014 p
+ sizeof(struct ospf6_lsreq_entry
) <= OSPF6_MESSAGE_END(oh
);
1015 p
+= sizeof(struct ospf6_lsreq_entry
)) {
1016 e
= (struct ospf6_lsreq_entry
*)p
;
1018 switch (OSPF6_LSA_SCOPE(e
->type
)) {
1019 case OSPF6_SCOPE_LINKLOCAL
:
1020 lsdb
= on
->ospf6_if
->lsdb
;
1022 case OSPF6_SCOPE_AREA
:
1023 lsdb
= on
->ospf6_if
->area
->lsdb
;
1025 case OSPF6_SCOPE_AS
:
1026 lsdb
= on
->ospf6_if
->area
->ospf6
->lsdb
;
1029 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
1030 zlog_debug("Ignoring LSA of reserved scope");
1035 /* Find database copy */
1036 lsa
= ospf6_lsdb_lookup(e
->type
, e
->id
, e
->adv_router
, lsdb
);
1038 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
)) {
1040 "Can't find requested [%s Id:%pI4 Adv:%pI4]",
1041 ospf6_lstype_name(e
->type
), &e
->id
,
1044 thread_add_event(master
, bad_lsreq
, on
, 0, NULL
);
1048 ospf6_lsdb_add(ospf6_lsa_copy(lsa
), on
->lsupdate_list
);
1051 assert(p
== OSPF6_MESSAGE_END(oh
));
1053 /* schedule send lsupdate */
1054 THREAD_OFF(on
->thread_send_lsupdate
);
1055 thread_add_event(master
, ospf6_lsupdate_send_neighbor
, on
, 0,
1056 &on
->thread_send_lsupdate
);
1059 /* Verify, that the specified memory area contains exactly N valid IPv6
1060 prefixes as specified by RFC5340, A.4.1. */
1061 static unsigned ospf6_prefixes_examin(
1062 struct ospf6_prefix
*current
, /* start of buffer */
1064 const uint32_t req_num_pfxs
/* always compared with the actual number
1068 uint8_t requested_pfx_bytes
;
1069 uint32_t real_num_pfxs
= 0;
1072 if (length
< OSPF6_PREFIX_MIN_SIZE
) {
1073 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN
,
1075 zlog_debug("%s: undersized IPv6 prefix header",
1079 /* safe to look deeper */
1080 if (current
->prefix_length
> IPV6_MAX_BITLEN
) {
1081 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN
,
1083 zlog_debug("%s: invalid PrefixLength (%u bits)",
1084 __func__
, current
->prefix_length
);
1087 /* covers both fixed- and variable-sized fields */
1088 requested_pfx_bytes
=
1089 OSPF6_PREFIX_MIN_SIZE
1090 + OSPF6_PREFIX_SPACE(current
->prefix_length
);
1091 if (requested_pfx_bytes
> length
) {
1092 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN
,
1094 zlog_debug("%s: undersized IPv6 prefix",
1099 length
-= requested_pfx_bytes
;
1100 current
= (struct ospf6_prefix
*)((caddr_t
)current
1101 + requested_pfx_bytes
);
1104 if (real_num_pfxs
!= req_num_pfxs
) {
1105 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN
,
1108 "%s: IPv6 prefix number mismatch (%u required, %u real)",
1109 __func__
, req_num_pfxs
, real_num_pfxs
);
1115 /* Verify an LSA to have a valid length and dispatch further (where
1116 appropriate) to check if the contents, including nested IPv6 prefixes,
1117 is properly sized/aligned within the LSA. Note that this function gets
1118 LSA type in network byte order, uses in host byte order and passes to
1119 ospf6_lstype_name() in network byte order again. */
1120 static unsigned ospf6_lsa_examin(struct ospf6_lsa_header
*lsah
,
1121 const uint16_t lsalen
,
1122 const uint8_t headeronly
)
1124 struct ospf6_intra_prefix_lsa
*intra_prefix_lsa
;
1125 struct ospf6_as_external_lsa
*as_external_lsa
;
1126 struct ospf6_link_lsa
*link_lsa
;
1127 unsigned exp_length
;
1131 /* In case an additional minimum length constraint is defined for
1133 LSA type, make sure that this constraint is met. */
1134 lsatype
= ntohs(lsah
->type
);
1135 ltindex
= lsatype
& OSPF6_LSTYPE_FCODE_MASK
;
1136 if (ltindex
< OSPF6_LSTYPE_SIZE
&& ospf6_lsa_minlen
[ltindex
]
1137 && lsalen
< ospf6_lsa_minlen
[ltindex
] + OSPF6_LSA_HEADER_SIZE
) {
1138 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN
,
1140 zlog_debug("%s: undersized (%u B) LSA", __func__
,
1145 case OSPF6_LSTYPE_ROUTER
:
1146 /* RFC5340 A.4.3, LSA header + OSPF6_ROUTER_LSA_MIN_SIZE bytes
1148 by N>=0 interface descriptions. */
1149 if ((lsalen
- OSPF6_LSA_HEADER_SIZE
- OSPF6_ROUTER_LSA_MIN_SIZE
)
1150 % OSPF6_ROUTER_LSDESC_FIX_SIZE
) {
1151 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN
,
1154 "%s: interface description alignment error",
1159 case OSPF6_LSTYPE_NETWORK
:
1160 /* RFC5340 A.4.4, LSA header + OSPF6_NETWORK_LSA_MIN_SIZE bytes
1161 followed by N>=0 attached router descriptions. */
1162 if ((lsalen
- OSPF6_LSA_HEADER_SIZE
1163 - OSPF6_NETWORK_LSA_MIN_SIZE
)
1164 % OSPF6_NETWORK_LSDESC_FIX_SIZE
) {
1165 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN
,
1168 "%s: router description alignment error",
1173 case OSPF6_LSTYPE_INTER_PREFIX
:
1174 /* RFC5340 A.4.5, LSA header + OSPF6_INTER_PREFIX_LSA_MIN_SIZE
1176 followed by 3-4 fields of a single IPv6 prefix. */
1179 return ospf6_prefixes_examin(
1180 (struct ospf6_prefix
1181 *)((caddr_t
)lsah
+ OSPF6_LSA_HEADER_SIZE
1182 + OSPF6_INTER_PREFIX_LSA_MIN_SIZE
),
1183 lsalen
- OSPF6_LSA_HEADER_SIZE
1184 - OSPF6_INTER_PREFIX_LSA_MIN_SIZE
,
1186 case OSPF6_LSTYPE_INTER_ROUTER
:
1187 /* RFC5340 A.4.6, fixed-size LSA. */
1189 > OSPF6_LSA_HEADER_SIZE
+ OSPF6_INTER_ROUTER_LSA_FIX_SIZE
) {
1190 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN
,
1192 zlog_debug("%s: oversized (%u B) LSA", __func__
,
1197 case OSPF6_LSTYPE_AS_EXTERNAL
: /* RFC5340 A.4.7, same as A.4.8. */
1198 case OSPF6_LSTYPE_TYPE_7
:
1199 /* RFC5340 A.4.8, LSA header + OSPF6_AS_EXTERNAL_LSA_MIN_SIZE
1201 followed by 3-4 fields of IPv6 prefix and 3 conditional LSA
1203 16 bytes of forwarding address, 4 bytes of external route
1205 4 bytes of referenced link state ID. */
1209 (struct ospf6_as_external_lsa
1210 *)((caddr_t
)lsah
+ OSPF6_LSA_HEADER_SIZE
);
1212 OSPF6_LSA_HEADER_SIZE
+ OSPF6_AS_EXTERNAL_LSA_MIN_SIZE
;
1213 /* To find out if the last optional field (Referenced Link State
1215 assumed in this LSA, we need to access fixed fields of the
1217 prefix before ospf6_prefix_examin() confirms its sizing. */
1218 if (exp_length
+ OSPF6_PREFIX_MIN_SIZE
> lsalen
) {
1219 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN
,
1221 zlog_debug("%s: undersized (%u B) LSA header",
1225 /* forwarding address */
1226 if (CHECK_FLAG(as_external_lsa
->bits_metric
, OSPF6_ASBR_BIT_F
))
1228 /* external route tag */
1229 if (CHECK_FLAG(as_external_lsa
->bits_metric
, OSPF6_ASBR_BIT_T
))
1231 /* referenced link state ID */
1232 if (as_external_lsa
->prefix
.u
._prefix_referenced_lstype
)
1234 /* All the fixed-size fields (mandatory and optional) must fit.
1236 this check does not include any IPv6 prefix fields. */
1237 if (exp_length
> lsalen
) {
1238 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN
,
1240 zlog_debug("%s: undersized (%u B) LSA header",
1244 /* The last call completely covers the remainder (IPv6 prefix).
1246 return ospf6_prefixes_examin(
1247 (struct ospf6_prefix
1248 *)((caddr_t
)as_external_lsa
1249 + OSPF6_AS_EXTERNAL_LSA_MIN_SIZE
),
1250 lsalen
- exp_length
, 1);
1251 case OSPF6_LSTYPE_LINK
:
1252 /* RFC5340 A.4.9, LSA header + OSPF6_LINK_LSA_MIN_SIZE bytes
1254 by N>=0 IPv6 prefix blocks (with N declared beforehand). */
1257 link_lsa
= (struct ospf6_link_lsa
*)((caddr_t
)lsah
1258 + OSPF6_LSA_HEADER_SIZE
);
1259 return ospf6_prefixes_examin(
1260 (struct ospf6_prefix
*)((caddr_t
)link_lsa
1261 + OSPF6_LINK_LSA_MIN_SIZE
),
1262 lsalen
- OSPF6_LSA_HEADER_SIZE
1263 - OSPF6_LINK_LSA_MIN_SIZE
,
1264 ntohl(link_lsa
->prefix_num
) /* 32 bits */
1266 case OSPF6_LSTYPE_INTRA_PREFIX
:
1267 /* RFC5340 A.4.10, LSA header + OSPF6_INTRA_PREFIX_LSA_MIN_SIZE
1269 followed by N>=0 IPv6 prefixes (with N declared beforehand).
1274 (struct ospf6_intra_prefix_lsa
1275 *)((caddr_t
)lsah
+ OSPF6_LSA_HEADER_SIZE
);
1276 return ospf6_prefixes_examin(
1277 (struct ospf6_prefix
1278 *)((caddr_t
)intra_prefix_lsa
1279 + OSPF6_INTRA_PREFIX_LSA_MIN_SIZE
),
1280 lsalen
- OSPF6_LSA_HEADER_SIZE
1281 - OSPF6_INTRA_PREFIX_LSA_MIN_SIZE
,
1282 ntohs(intra_prefix_lsa
->prefix_num
) /* 16 bits */
1285 /* No additional validation is possible for unknown LSA types, which are
1286 themselves valid in OPSFv3, hence the default decision is to accept.
1291 /* Verify if the provided input buffer is a valid sequence of LSAs. This
1292 includes verification of LSA blocks length/alignment and dispatching
1293 of deeper-level checks. */
1295 ospf6_lsaseq_examin(struct ospf6_lsa_header
*lsah
, /* start of buffered data */
1296 size_t length
, const uint8_t headeronly
,
1297 /* When declared_num_lsas is not 0, compare it to the real
1299 and treat the difference as an error. */
1300 const uint32_t declared_num_lsas
)
1302 uint32_t counted_lsas
= 0;
1306 if (length
< OSPF6_LSA_HEADER_SIZE
) {
1307 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN
,
1310 "%s: undersized (%zu B) trailing (#%u) LSA header",
1311 __func__
, length
, counted_lsas
);
1314 /* save on ntohs() calls here and in the LSA validator */
1315 lsalen
= OSPF6_LSA_SIZE(lsah
);
1316 if (lsalen
< OSPF6_LSA_HEADER_SIZE
) {
1317 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN
,
1320 "%s: malformed LSA header #%u, declared length is %u B",
1321 __func__
, counted_lsas
, lsalen
);
1325 /* less checks here and in ospf6_lsa_examin() */
1326 if (MSG_OK
!= ospf6_lsa_examin(lsah
, lsalen
, 1)) {
1327 if (IS_OSPF6_DEBUG_MESSAGE(
1328 OSPF6_MESSAGE_TYPE_UNKNOWN
,
1331 "%s: anomaly in header-only %s LSA #%u",
1333 ospf6_lstype_name(lsah
->type
),
1337 lsah
= (struct ospf6_lsa_header
1339 + OSPF6_LSA_HEADER_SIZE
);
1340 length
-= OSPF6_LSA_HEADER_SIZE
;
1342 /* make sure the input buffer is deep enough before
1344 if (lsalen
> length
) {
1345 if (IS_OSPF6_DEBUG_MESSAGE(
1346 OSPF6_MESSAGE_TYPE_UNKNOWN
,
1349 "%s: anomaly in %s LSA #%u: declared length is %u B, buffered length is %zu B",
1351 ospf6_lstype_name(lsah
->type
),
1352 counted_lsas
, lsalen
, length
);
1355 if (MSG_OK
!= ospf6_lsa_examin(lsah
, lsalen
, 0)) {
1356 if (IS_OSPF6_DEBUG_MESSAGE(
1357 OSPF6_MESSAGE_TYPE_UNKNOWN
,
1360 "%s: anomaly in %s LSA #%u",
1362 ospf6_lstype_name(lsah
->type
),
1366 lsah
= (struct ospf6_lsa_header
*)((caddr_t
)lsah
1373 if (declared_num_lsas
&& counted_lsas
!= declared_num_lsas
) {
1374 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN
,
1377 "%s: #LSAs declared (%u) does not match actual (%u)",
1378 __func__
, declared_num_lsas
, counted_lsas
);
1384 /* Verify a complete OSPF packet for proper sizing/alignment. */
1385 static unsigned ospf6_packet_examin(struct ospf6_header
*oh
,
1386 const unsigned bytesonwire
)
1388 struct ospf6_lsupdate
*lsupd
;
1391 /* length, 1st approximation */
1392 if (bytesonwire
< OSPF6_HEADER_SIZE
) {
1393 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN
,
1395 zlog_debug("%s: undersized (%u B) packet", __func__
,
1399 /* Now it is safe to access header fields. */
1400 if (bytesonwire
!= ntohs(oh
->length
)) {
1401 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN
,
1404 "%s: %s packet length error (%u real, %u declared)",
1405 __func__
, lookup_msg(ospf6_message_type_str
,
1407 bytesonwire
, ntohs(oh
->length
));
1411 if (oh
->version
!= OSPFV3_VERSION
) {
1412 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN
,
1414 zlog_debug("%s: invalid (%u) protocol version",
1415 __func__
, oh
->version
);
1418 /* length, 2nd approximation */
1419 if (oh
->type
< OSPF6_MESSAGE_TYPE_ALL
&& ospf6_packet_minlen
[oh
->type
]
1421 < OSPF6_HEADER_SIZE
+ ospf6_packet_minlen
[oh
->type
]) {
1422 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN
,
1424 zlog_debug("%s: undersized (%u B) %s packet", __func__
,
1426 lookup_msg(ospf6_message_type_str
, oh
->type
,
1430 /* type-specific deeper validation */
1432 case OSPF6_MESSAGE_TYPE_HELLO
:
1433 /* RFC5340 A.3.2, packet header + OSPF6_HELLO_MIN_SIZE bytes
1435 by N>=0 router-IDs. */
1437 == (bytesonwire
- OSPF6_HEADER_SIZE
- OSPF6_HELLO_MIN_SIZE
)
1440 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN
,
1442 zlog_debug("%s: alignment error in %s packet", __func__
,
1443 lookup_msg(ospf6_message_type_str
, oh
->type
,
1446 case OSPF6_MESSAGE_TYPE_DBDESC
:
1447 /* RFC5340 A.3.3, packet header + OSPF6_DB_DESC_MIN_SIZE bytes
1449 by N>=0 header-only LSAs. */
1450 test
= ospf6_lsaseq_examin(
1451 (struct ospf6_lsa_header
*)((caddr_t
)oh
1453 + OSPF6_DB_DESC_MIN_SIZE
),
1454 bytesonwire
- OSPF6_HEADER_SIZE
1455 - OSPF6_DB_DESC_MIN_SIZE
,
1458 case OSPF6_MESSAGE_TYPE_LSREQ
:
1459 /* RFC5340 A.3.4, packet header + N>=0 LS description blocks. */
1461 == (bytesonwire
- OSPF6_HEADER_SIZE
- OSPF6_LS_REQ_MIN_SIZE
)
1462 % OSPF6_LSREQ_LSDESC_FIX_SIZE
)
1464 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN
,
1466 zlog_debug("%s: alignment error in %s packet", __func__
,
1467 lookup_msg(ospf6_message_type_str
, oh
->type
,
1470 case OSPF6_MESSAGE_TYPE_LSUPDATE
:
1471 /* RFC5340 A.3.5, packet header + OSPF6_LS_UPD_MIN_SIZE bytes
1473 by N>=0 full LSAs (with N declared beforehand). */
1474 lsupd
= (struct ospf6_lsupdate
*)((caddr_t
)oh
1475 + OSPF6_HEADER_SIZE
);
1476 test
= ospf6_lsaseq_examin(
1477 (struct ospf6_lsa_header
*)((caddr_t
)lsupd
1478 + OSPF6_LS_UPD_MIN_SIZE
),
1479 bytesonwire
- OSPF6_HEADER_SIZE
- OSPF6_LS_UPD_MIN_SIZE
,
1480 0, ntohl(lsupd
->lsa_number
) /* 32 bits */
1483 case OSPF6_MESSAGE_TYPE_LSACK
:
1484 /* RFC5340 A.3.6, packet header + N>=0 header-only LSAs. */
1485 test
= ospf6_lsaseq_examin(
1486 (struct ospf6_lsa_header
*)((caddr_t
)oh
1488 + OSPF6_LS_ACK_MIN_SIZE
),
1489 bytesonwire
- OSPF6_HEADER_SIZE
- OSPF6_LS_ACK_MIN_SIZE
,
1493 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN
,
1495 zlog_debug("%s: invalid (%u) message type", __func__
,
1500 && IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN
, RECV_HDR
))
1501 zlog_debug("%s: anomaly in %s packet", __func__
,
1502 lookup_msg(ospf6_message_type_str
, oh
->type
, NULL
));
1506 /* Verify particular fields of otherwise correct received OSPF packet to
1507 meet the requirements of RFC. */
1508 static int ospf6_rxpacket_examin(struct ospf6_interface
*oi
,
1509 struct ospf6_header
*oh
,
1510 const unsigned bytesonwire
)
1513 if (MSG_OK
!= ospf6_packet_examin(oh
, bytesonwire
))
1517 if (oh
->area_id
!= oi
->area
->area_id
) {
1518 if (oh
->area_id
== OSPF_AREA_BACKBONE
)
1520 "VRF %s: I/F %s Message may be via Virtual Link: not supported",
1521 vrf_id_to_name(oi
->interface
->vrf_id
),
1522 oi
->interface
->name
);
1525 "VRF %s: I/F %s Area-ID mismatch (my %pI4, rcvd %pI4)",
1526 vrf_id_to_name(oi
->interface
->vrf_id
),
1527 oi
->interface
->name
, &oi
->area
->area_id
,
1532 /* Instance-ID check */
1533 if (oh
->instance_id
!= oi
->instance_id
) {
1535 "VRF %s: I/F %s Instance-ID mismatch (my %u, rcvd %u)",
1536 vrf_id_to_name(oi
->interface
->vrf_id
),
1537 oi
->interface
->name
, oi
->instance_id
, oh
->instance_id
);
1541 /* Router-ID check */
1542 if (oh
->router_id
== oi
->area
->ospf6
->router_id
) {
1543 zlog_warn("VRF %s: I/F %s Duplicate Router-ID (%pI4)",
1544 vrf_id_to_name(oi
->interface
->vrf_id
),
1545 oi
->interface
->name
, &oh
->router_id
);
1551 static void ospf6_lsupdate_recv(struct in6_addr
*src
, struct in6_addr
*dst
,
1552 struct ospf6_interface
*oi
,
1553 struct ospf6_header
*oh
)
1555 struct ospf6_neighbor
*on
;
1556 struct ospf6_lsupdate
*lsupdate
;
1559 on
= ospf6_neighbor_lookup(oh
->router_id
, oi
);
1561 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV_HDR
))
1562 zlog_debug("Neighbor not found, ignore");
1566 if (on
->state
!= OSPF6_NEIGHBOR_EXCHANGE
1567 && on
->state
!= OSPF6_NEIGHBOR_LOADING
1568 && on
->state
!= OSPF6_NEIGHBOR_FULL
) {
1569 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV_HDR
))
1570 zlog_debug("Neighbor state less than Exchange, ignore");
1574 lsupdate
= (struct ospf6_lsupdate
*)((caddr_t
)oh
1575 + sizeof(struct ospf6_header
));
1580 for (p
= (char *)((caddr_t
)lsupdate
+ sizeof(struct ospf6_lsupdate
));
1581 p
< OSPF6_MESSAGE_END(oh
)
1582 && p
+ OSPF6_LSA_SIZE(p
) <= OSPF6_MESSAGE_END(oh
);
1583 p
+= OSPF6_LSA_SIZE(p
)) {
1584 ospf6_receive_lsa(on
, (struct ospf6_lsa_header
*)p
);
1587 assert(p
== OSPF6_MESSAGE_END(oh
));
1590 static void ospf6_lsack_recv(struct in6_addr
*src
, struct in6_addr
*dst
,
1591 struct ospf6_interface
*oi
,
1592 struct ospf6_header
*oh
)
1594 struct ospf6_neighbor
*on
;
1596 struct ospf6_lsa
*his
, *mine
;
1597 struct ospf6_lsdb
*lsdb
= NULL
;
1599 assert(oh
->type
== OSPF6_MESSAGE_TYPE_LSACK
);
1601 on
= ospf6_neighbor_lookup(oh
->router_id
, oi
);
1603 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV_HDR
))
1604 zlog_debug("Neighbor not found, ignore");
1608 if (on
->state
!= OSPF6_NEIGHBOR_EXCHANGE
1609 && on
->state
!= OSPF6_NEIGHBOR_LOADING
1610 && on
->state
!= OSPF6_NEIGHBOR_FULL
) {
1611 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV_HDR
))
1612 zlog_debug("Neighbor state less than Exchange, ignore");
1618 for (p
= (char *)((caddr_t
)oh
+ sizeof(struct ospf6_header
));
1619 p
+ sizeof(struct ospf6_lsa_header
) <= OSPF6_MESSAGE_END(oh
);
1620 p
+= sizeof(struct ospf6_lsa_header
)) {
1621 his
= ospf6_lsa_create_headeronly((struct ospf6_lsa_header
*)p
);
1623 switch (OSPF6_LSA_SCOPE(his
->header
->type
)) {
1624 case OSPF6_SCOPE_LINKLOCAL
:
1625 lsdb
= on
->ospf6_if
->lsdb
;
1627 case OSPF6_SCOPE_AREA
:
1628 lsdb
= on
->ospf6_if
->area
->lsdb
;
1630 case OSPF6_SCOPE_AS
:
1631 lsdb
= on
->ospf6_if
->area
->ospf6
->lsdb
;
1633 case OSPF6_SCOPE_RESERVED
:
1634 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
1635 zlog_debug("Ignoring LSA of reserved scope");
1636 ospf6_lsa_delete(his
);
1641 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
1642 zlog_debug("%s acknowledged by %s", his
->name
,
1645 /* Find database copy */
1646 mine
= ospf6_lsdb_lookup(his
->header
->type
, his
->header
->id
,
1647 his
->header
->adv_router
, lsdb
);
1649 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
1650 zlog_debug("No database copy");
1651 ospf6_lsa_delete(his
);
1655 /* Check if the LSA is on his retrans-list */
1656 mine
= ospf6_lsdb_lookup(his
->header
->type
, his
->header
->id
,
1657 his
->header
->adv_router
,
1660 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
1661 zlog_debug("Not on %s's retrans-list",
1663 ospf6_lsa_delete(his
);
1667 if (ospf6_lsa_compare(his
, mine
) != 0) {
1668 /* Log this questionable acknowledgement,
1669 and examine the next one. */
1670 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
1671 zlog_debug("Questionable acknowledgement");
1672 ospf6_lsa_delete(his
);
1676 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
1678 "Acknowledged, remove from %s's retrans-list",
1681 ospf6_decrement_retrans_count(mine
);
1682 if (OSPF6_LSA_IS_MAXAGE(mine
))
1683 ospf6_maxage_remove(on
->ospf6_if
->area
->ospf6
);
1684 ospf6_lsdb_remove(mine
, on
->retrans_list
);
1685 ospf6_lsa_delete(his
);
1688 assert(p
== OSPF6_MESSAGE_END(oh
));
1691 static uint8_t *recvbuf
= NULL
;
1692 static uint8_t *sendbuf
= NULL
;
1693 static unsigned int iobuflen
= 0;
1695 int ospf6_iobuf_size(unsigned int size
)
1697 uint8_t *recvnew
, *sendnew
;
1699 if (size
<= iobuflen
)
1702 recvnew
= XMALLOC(MTYPE_OSPF6_MESSAGE
, size
);
1703 sendnew
= XMALLOC(MTYPE_OSPF6_MESSAGE
, size
);
1705 XFREE(MTYPE_OSPF6_MESSAGE
, recvbuf
);
1706 XFREE(MTYPE_OSPF6_MESSAGE
, sendbuf
);
1714 void ospf6_message_terminate(void)
1716 XFREE(MTYPE_OSPF6_MESSAGE
, recvbuf
);
1717 XFREE(MTYPE_OSPF6_MESSAGE
, sendbuf
);
1722 enum ospf6_read_return_enum
{
1724 OSPF6_READ_CONTINUE
,
1727 static int ospf6_read_helper(int sockfd
, struct ospf6
*ospf6
)
1730 struct in6_addr src
, dst
;
1732 struct iovec iovector
[2];
1733 struct ospf6_interface
*oi
;
1734 struct ospf6_header
*oh
;
1737 memset(&src
, 0, sizeof(src
));
1738 memset(&dst
, 0, sizeof(dst
));
1740 memset(recvbuf
, 0, iobuflen
);
1741 iovector
[0].iov_base
= recvbuf
;
1742 iovector
[0].iov_len
= iobuflen
;
1743 iovector
[1].iov_base
= NULL
;
1744 iovector
[1].iov_len
= 0;
1746 /* receive message */
1747 len
= ospf6_recvmsg(&src
, &dst
, &ifindex
, iovector
, sockfd
);
1749 return OSPF6_READ_ERROR
;
1751 if ((uint
)len
> iobuflen
) {
1752 flog_err(EC_LIB_DEVELOPMENT
, "Excess message read");
1753 return OSPF6_READ_ERROR
;
1756 oi
= ospf6_interface_lookup_by_ifindex(ifindex
, ospf6
->vrf_id
);
1757 if (oi
== NULL
|| oi
->area
== NULL
1758 || CHECK_FLAG(oi
->flag
, OSPF6_INTERFACE_DISABLE
)) {
1759 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN
,
1761 zlog_debug("Message received on disabled interface");
1762 return OSPF6_READ_CONTINUE
;
1764 if (CHECK_FLAG(oi
->flag
, OSPF6_INTERFACE_PASSIVE
)) {
1765 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN
,
1767 zlog_debug("%s: Ignore message on passive interface %s",
1768 __func__
, oi
->interface
->name
);
1769 return OSPF6_READ_CONTINUE
;
1772 oh
= (struct ospf6_header
*)recvbuf
;
1773 if (ospf6_rxpacket_examin(oi
, oh
, len
) != MSG_OK
)
1774 return OSPF6_READ_CONTINUE
;
1776 /* Being here means, that no sizing/alignment issues were detected in
1777 the input packet. This renders the additional checks performed below
1778 and also in the type-specific dispatching functions a dead code,
1779 which can be dismissed in a cleanup-focused review round later. */
1782 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV_HDR
)) {
1783 zlog_debug("%s received on %s",
1784 lookup_msg(ospf6_message_type_str
, oh
->type
, NULL
),
1785 oi
->interface
->name
);
1786 zlog_debug(" src: %pI6", &src
);
1787 zlog_debug(" dst: %pI6", &dst
);
1790 case OSPF6_MESSAGE_TYPE_HELLO
:
1791 ospf6_hello_print(oh
, OSPF6_ACTION_RECV
);
1793 case OSPF6_MESSAGE_TYPE_DBDESC
:
1794 ospf6_dbdesc_print(oh
, OSPF6_ACTION_RECV
);
1796 case OSPF6_MESSAGE_TYPE_LSREQ
:
1797 ospf6_lsreq_print(oh
, OSPF6_ACTION_RECV
);
1799 case OSPF6_MESSAGE_TYPE_LSUPDATE
:
1800 ospf6_lsupdate_print(oh
, OSPF6_ACTION_RECV
);
1802 case OSPF6_MESSAGE_TYPE_LSACK
:
1803 ospf6_lsack_print(oh
, OSPF6_ACTION_RECV
);
1811 case OSPF6_MESSAGE_TYPE_HELLO
:
1812 ospf6_hello_recv(&src
, &dst
, oi
, oh
);
1815 case OSPF6_MESSAGE_TYPE_DBDESC
:
1816 ospf6_dbdesc_recv(&src
, &dst
, oi
, oh
);
1819 case OSPF6_MESSAGE_TYPE_LSREQ
:
1820 ospf6_lsreq_recv(&src
, &dst
, oi
, oh
);
1823 case OSPF6_MESSAGE_TYPE_LSUPDATE
:
1824 ospf6_lsupdate_recv(&src
, &dst
, oi
, oh
);
1827 case OSPF6_MESSAGE_TYPE_LSACK
:
1828 ospf6_lsack_recv(&src
, &dst
, oi
, oh
);
1835 return OSPF6_READ_CONTINUE
;
1838 int ospf6_receive(struct thread
*thread
)
1841 struct ospf6
*ospf6
;
1844 /* add next read thread */
1845 ospf6
= THREAD_ARG(thread
);
1846 sockfd
= THREAD_FD(thread
);
1848 thread_add_read(master
, ospf6_receive
, ospf6
, ospf6
->fd
,
1849 &ospf6
->t_ospf6_receive
);
1851 while (count
< ospf6
->write_oi_count
) {
1853 switch (ospf6_read_helper(sockfd
, ospf6
)) {
1854 case OSPF6_READ_ERROR
:
1856 case OSPF6_READ_CONTINUE
:
1864 static void ospf6_make_header(uint8_t type
, struct ospf6_interface
*oi
,
1867 struct ospf6_header
*oh
;
1869 oh
= (struct ospf6_header
*)STREAM_DATA(s
);
1871 oh
->version
= (uint8_t)OSPFV3_VERSION
;
1874 oh
->router_id
= oi
->area
->ospf6
->router_id
;
1875 oh
->area_id
= oi
->area
->area_id
;
1876 oh
->instance_id
= oi
->instance_id
;
1878 stream_forward_endp(s
, OSPF6_HEADER_SIZE
);
1881 static void ospf6_fill_header(struct ospf6_interface
*oi
, struct stream
*s
,
1884 struct ospf6_header
*oh
;
1886 oh
= (struct ospf6_header
*)STREAM_DATA(s
);
1888 oh
->length
= htons(length
);
1891 static void ospf6_fill_lsupdate_header(struct stream
*s
, uint32_t lsa_num
)
1893 struct ospf6_header
*oh
;
1894 struct ospf6_lsupdate
*lsu
;
1896 oh
= (struct ospf6_header
*)STREAM_DATA(s
);
1898 lsu
= (struct ospf6_lsupdate
*)((caddr_t
)oh
1899 + sizeof(struct ospf6_header
));
1900 lsu
->lsa_number
= htonl(lsa_num
);
1903 static uint32_t ospf6_packet_max(struct ospf6_interface
*oi
)
1905 assert(oi
->ifmtu
> sizeof(struct ip6_hdr
));
1906 return oi
->ifmtu
- (sizeof(struct ip6_hdr
));
1909 static uint16_t ospf6_make_hello(struct ospf6_interface
*oi
, struct stream
*s
)
1911 struct listnode
*node
, *nnode
;
1912 struct ospf6_neighbor
*on
;
1913 uint16_t length
= OSPF6_HELLO_MIN_SIZE
;
1915 stream_putl(s
, oi
->interface
->ifindex
);
1916 stream_putc(s
, oi
->priority
);
1917 stream_putc(s
, oi
->area
->options
[0]);
1918 stream_putc(s
, oi
->area
->options
[1]);
1919 stream_putc(s
, oi
->area
->options
[2]);
1920 stream_putw(s
, oi
->hello_interval
);
1921 stream_putw(s
, oi
->dead_interval
);
1922 stream_put_ipv4(s
, oi
->drouter
);
1923 stream_put_ipv4(s
, oi
->bdrouter
);
1925 for (ALL_LIST_ELEMENTS(oi
->neighbor_list
, node
, nnode
, on
)) {
1926 if (on
->state
< OSPF6_NEIGHBOR_INIT
)
1929 if ((length
+ sizeof(uint32_t) + OSPF6_HEADER_SIZE
)
1930 > ospf6_packet_max(oi
)) {
1931 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_HELLO
,
1934 "sending Hello message: exceeds I/F MTU");
1938 stream_put_ipv4(s
, on
->router_id
);
1939 length
+= sizeof(uint32_t);
1945 static int ospf6_write(struct thread
*thread
)
1947 struct ospf6
*ospf6
= THREAD_ARG(thread
);
1948 struct ospf6_interface
*oi
;
1949 struct ospf6_interface
*last_serviced_oi
= NULL
;
1950 struct ospf6_header
*oh
;
1951 struct ospf6_packet
*op
;
1952 struct listnode
*node
;
1953 char srcname
[64], dstname
[64];
1954 struct iovec iovector
[2];
1957 int64_t latency
= 0;
1958 struct timeval timestamp
;
1960 if (ospf6
->fd
< 0) {
1961 zlog_warn("ospf6_write failed to send, fd %d", ospf6
->fd
);
1965 node
= listhead(ospf6
->oi_write_q
);
1967 oi
= listgetdata(node
);
1969 while ((pkt_count
< ospf6
->write_oi_count
) && oi
1970 && (last_serviced_oi
!= oi
)) {
1972 op
= ospf6_fifo_head(oi
->obuf
);
1974 assert(op
->length
>= OSPF6_HEADER_SIZE
);
1976 iovector
[0].iov_base
= (caddr_t
)stream_pnt(op
->s
);
1977 iovector
[0].iov_len
= op
->length
;
1978 iovector
[1].iov_base
= NULL
;
1979 iovector
[1].iov_len
= 0;
1981 oh
= (struct ospf6_header
*)STREAM_DATA(op
->s
);
1983 len
= ospf6_sendmsg(oi
->linklocal_addr
, &op
->dst
,
1984 oi
->interface
->ifindex
, iovector
,
1986 if (len
!= op
->length
)
1987 flog_err(EC_LIB_DEVELOPMENT
,
1988 "Could not send entire message");
1990 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, SEND
)) {
1991 inet_ntop(AF_INET6
, &op
->dst
, dstname
, sizeof(dstname
));
1992 inet_ntop(AF_INET6
, oi
->linklocal_addr
, srcname
,
1994 zlog_debug("%s send on %s",
1995 lookup_msg(ospf6_message_type_str
, oh
->type
,
1997 oi
->interface
->name
);
1998 zlog_debug(" src: %s", srcname
);
1999 zlog_debug(" dst: %s", dstname
);
2002 case OSPF6_MESSAGE_TYPE_HELLO
:
2003 monotime(×tamp
);
2005 latency
= monotime_since(&oi
->last_hello
, NULL
)
2006 - (oi
->hello_interval
* 1000000);
2008 /* log if latency exceeds the hello period */
2009 if (latency
> (oi
->hello_interval
* 1000000))
2010 zlog_warn("%s hello TX high latency %" PRId64
2013 oi
->last_hello
= timestamp
;
2015 ospf6_hello_print(oh
, OSPF6_ACTION_SEND
);
2017 case OSPF6_MESSAGE_TYPE_DBDESC
:
2019 ospf6_dbdesc_print(oh
, OSPF6_ACTION_SEND
);
2021 case OSPF6_MESSAGE_TYPE_LSREQ
:
2023 ospf6_lsreq_print(oh
, OSPF6_ACTION_SEND
);
2025 case OSPF6_MESSAGE_TYPE_LSUPDATE
:
2027 ospf6_lsupdate_print(oh
, OSPF6_ACTION_SEND
);
2029 case OSPF6_MESSAGE_TYPE_LSACK
:
2031 ospf6_lsack_print(oh
, OSPF6_ACTION_SEND
);
2034 zlog_debug("Unknown message");
2038 /* Now delete packet from queue. */
2039 ospf6_packet_delete(oi
);
2041 /* Move this interface to the tail of write_q to
2042 serve everyone in a round robin fashion */
2043 list_delete_node(ospf6
->oi_write_q
, node
);
2044 if (ospf6_fifo_head(oi
->obuf
) == NULL
) {
2046 last_serviced_oi
= NULL
;
2049 listnode_add(ospf6
->oi_write_q
, oi
);
2052 /* Setup to service from the head of the queue again */
2053 if (!list_isempty(ospf6
->oi_write_q
)) {
2054 node
= listhead(ospf6
->oi_write_q
);
2055 oi
= listgetdata(node
);
2059 /* If packets still remain in queue, call write thread. */
2060 if (!list_isempty(ospf6
->oi_write_q
))
2061 thread_add_write(master
, ospf6_write
, ospf6
, ospf6
->fd
,
2067 int ospf6_hello_send(struct thread
*thread
)
2069 struct ospf6_interface
*oi
;
2070 struct ospf6_packet
*op
;
2071 uint16_t length
= OSPF6_HEADER_SIZE
;
2073 oi
= (struct ospf6_interface
*)THREAD_ARG(thread
);
2074 oi
->thread_send_hello
= (struct thread
*)NULL
;
2076 if (oi
->state
<= OSPF6_INTERFACE_DOWN
) {
2077 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_HELLO
, SEND_HDR
))
2078 zlog_debug("Unable to send Hello on down interface %s",
2079 oi
->interface
->name
);
2083 op
= ospf6_packet_new(oi
->ifmtu
);
2085 ospf6_make_header(OSPF6_MESSAGE_TYPE_HELLO
, oi
, op
->s
);
2087 /* Prepare OSPF Hello body */
2088 length
+= ospf6_make_hello(oi
, op
->s
);
2089 if (length
== OSPF6_HEADER_SIZE
) {
2090 /* Hello overshooting MTU */
2091 ospf6_packet_free(op
);
2095 /* Fill OSPF header. */
2096 ospf6_fill_header(oi
, op
->s
, length
);
2098 /* Set packet length. */
2099 op
->length
= length
;
2101 op
->dst
= allspfrouters6
;
2103 /* Add packet to the top of the interface output queue, so that they
2104 * can't get delayed by things like long queues of LS Update packets
2106 ospf6_packet_add_top(oi
, op
);
2108 /* set next thread */
2109 thread_add_timer(master
, ospf6_hello_send
, oi
, oi
->hello_interval
,
2110 &oi
->thread_send_hello
);
2112 OSPF6_MESSAGE_WRITE_ON(oi
);
2117 static uint16_t ospf6_make_dbdesc(struct ospf6_neighbor
*on
, struct stream
*s
)
2119 uint16_t length
= OSPF6_DB_DESC_MIN_SIZE
;
2120 struct ospf6_lsa
*lsa
, *lsanext
;
2122 /* if this is initial one, initialize sequence number for DbDesc */
2123 if (CHECK_FLAG(on
->dbdesc_bits
, OSPF6_DBDESC_IBIT
)
2124 && (on
->dbdesc_seqnum
== 0)) {
2125 on
->dbdesc_seqnum
= monotime(NULL
);
2129 stream_putc(s
, 0); /* reserved 1 */
2130 stream_putc(s
, on
->ospf6_if
->area
->options
[0]);
2131 stream_putc(s
, on
->ospf6_if
->area
->options
[1]);
2132 stream_putc(s
, on
->ospf6_if
->area
->options
[2]);
2133 stream_putw(s
, on
->ospf6_if
->ifmtu
);
2134 stream_putc(s
, 0); /* reserved 2 */
2135 stream_putc(s
, on
->dbdesc_bits
);
2136 stream_putl(s
, on
->dbdesc_seqnum
);
2138 /* if this is not initial one, set LSA headers in dbdesc */
2139 if (!CHECK_FLAG(on
->dbdesc_bits
, OSPF6_DBDESC_IBIT
)) {
2140 for (ALL_LSDB(on
->dbdesc_list
, lsa
, lsanext
)) {
2141 ospf6_lsa_age_update_to_send(lsa
,
2142 on
->ospf6_if
->transdelay
);
2145 if ((length
+ sizeof(struct ospf6_lsa_header
)
2146 + OSPF6_HEADER_SIZE
)
2147 > ospf6_packet_max(on
->ospf6_if
)) {
2148 ospf6_lsa_unlock(lsa
);
2150 ospf6_lsa_unlock(lsanext
);
2153 stream_put(s
, lsa
->header
,
2154 sizeof(struct ospf6_lsa_header
));
2155 length
+= sizeof(struct ospf6_lsa_header
);
2161 int ospf6_dbdesc_send(struct thread
*thread
)
2163 struct ospf6_neighbor
*on
;
2164 uint16_t length
= OSPF6_HEADER_SIZE
;
2165 struct ospf6_packet
*op
;
2167 on
= (struct ospf6_neighbor
*)THREAD_ARG(thread
);
2168 on
->thread_send_dbdesc
= (struct thread
*)NULL
;
2170 if (on
->state
< OSPF6_NEIGHBOR_EXSTART
) {
2171 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_DBDESC
, SEND
))
2173 "Quit to send DbDesc to neighbor %s state %s",
2174 on
->name
, ospf6_neighbor_state_str
[on
->state
]);
2178 /* set next thread if master */
2179 if (CHECK_FLAG(on
->dbdesc_bits
, OSPF6_DBDESC_MSBIT
))
2180 thread_add_timer(master
, ospf6_dbdesc_send
, on
,
2181 on
->ospf6_if
->rxmt_interval
,
2182 &on
->thread_send_dbdesc
);
2184 op
= ospf6_packet_new(on
->ospf6_if
->ifmtu
);
2185 ospf6_make_header(OSPF6_MESSAGE_TYPE_DBDESC
, on
->ospf6_if
, op
->s
);
2187 length
+= ospf6_make_dbdesc(on
, op
->s
);
2188 ospf6_fill_header(on
->ospf6_if
, op
->s
, length
);
2190 /* Set packet length. */
2191 op
->length
= length
;
2193 if (on
->ospf6_if
->state
== OSPF6_INTERFACE_POINTTOPOINT
)
2194 op
->dst
= allspfrouters6
;
2196 op
->dst
= on
->linklocal_addr
;
2198 ospf6_packet_add(on
->ospf6_if
, op
);
2200 OSPF6_MESSAGE_WRITE_ON(on
->ospf6_if
);
2205 int ospf6_dbdesc_send_newone(struct thread
*thread
)
2207 struct ospf6_neighbor
*on
;
2208 struct ospf6_lsa
*lsa
, *lsanext
;
2209 unsigned int size
= 0;
2211 on
= (struct ospf6_neighbor
*)THREAD_ARG(thread
);
2212 ospf6_lsdb_remove_all(on
->dbdesc_list
);
2214 /* move LSAs from summary_list to dbdesc_list (within neighbor
2216 so that ospf6_send_dbdesc () can send those LSAs */
2217 size
= sizeof(struct ospf6_lsa_header
) + sizeof(struct ospf6_dbdesc
);
2218 for (ALL_LSDB(on
->summary_list
, lsa
, lsanext
)) {
2219 /* if stub area then don't advertise AS-External LSAs */
2220 if ((IS_AREA_STUB(on
->ospf6_if
->area
)
2221 || IS_AREA_NSSA(on
->ospf6_if
->area
))
2222 && ntohs(lsa
->header
->type
) == OSPF6_LSTYPE_AS_EXTERNAL
) {
2223 ospf6_lsdb_remove(lsa
, on
->summary_list
);
2227 if (size
+ sizeof(struct ospf6_lsa_header
)
2228 > ospf6_packet_max(on
->ospf6_if
)) {
2229 ospf6_lsa_unlock(lsa
);
2231 ospf6_lsa_unlock(lsanext
);
2235 ospf6_lsdb_add(ospf6_lsa_copy(lsa
), on
->dbdesc_list
);
2236 ospf6_lsdb_remove(lsa
, on
->summary_list
);
2237 size
+= sizeof(struct ospf6_lsa_header
);
2240 if (on
->summary_list
->count
== 0)
2241 UNSET_FLAG(on
->dbdesc_bits
, OSPF6_DBDESC_MBIT
);
2243 /* If slave, More bit check must be done here */
2244 if (!CHECK_FLAG(on
->dbdesc_bits
, OSPF6_DBDESC_MSBIT
) && /* Slave */
2245 !CHECK_FLAG(on
->dbdesc_last
.bits
, OSPF6_DBDESC_MBIT
)
2246 && !CHECK_FLAG(on
->dbdesc_bits
, OSPF6_DBDESC_MBIT
))
2247 thread_add_event(master
, exchange_done
, on
, 0, NULL
);
2249 thread_execute(master
, ospf6_dbdesc_send
, on
, 0);
2253 static uint16_t ospf6_make_lsreq(struct ospf6_neighbor
*on
, struct stream
*s
)
2255 uint16_t length
= 0;
2256 struct ospf6_lsa
*lsa
, *lsanext
, *last_req
= NULL
;
2258 for (ALL_LSDB(on
->request_list
, lsa
, lsanext
)) {
2259 if ((length
+ OSPF6_HEADER_SIZE
)
2260 > ospf6_packet_max(on
->ospf6_if
)) {
2261 ospf6_lsa_unlock(lsa
);
2263 ospf6_lsa_unlock(lsanext
);
2266 stream_putw(s
, 0); /* reserved */
2267 stream_putw(s
, ntohs(lsa
->header
->type
));
2268 stream_putl(s
, ntohl(lsa
->header
->id
));
2269 stream_putl(s
, ntohl(lsa
->header
->adv_router
));
2270 length
+= sizeof(struct ospf6_lsreq_entry
);
2274 if (last_req
!= NULL
) {
2275 if (on
->last_ls_req
!= NULL
)
2276 on
->last_ls_req
= ospf6_lsa_unlock(on
->last_ls_req
);
2278 ospf6_lsa_lock(last_req
);
2279 on
->last_ls_req
= last_req
;
2285 static uint16_t ospf6_make_lsack_neighbor(struct ospf6_neighbor
*on
,
2286 struct ospf6_packet
**op
)
2288 uint16_t length
= 0;
2289 struct ospf6_lsa
*lsa
, *lsanext
;
2292 for (ALL_LSDB(on
->lsack_list
, lsa
, lsanext
)) {
2293 if ((length
+ sizeof(struct ospf6_lsa_header
)
2294 + OSPF6_HEADER_SIZE
)
2295 > ospf6_packet_max(on
->ospf6_if
)) {
2296 /* if we run out of packet size/space here,
2297 better to try again soon. */
2299 ospf6_fill_header(on
->ospf6_if
, (*op
)->s
,
2300 length
+ OSPF6_HEADER_SIZE
);
2302 (*op
)->length
= length
+ OSPF6_HEADER_SIZE
;
2303 (*op
)->dst
= on
->linklocal_addr
;
2304 ospf6_packet_add(on
->ospf6_if
, *op
);
2305 OSPF6_MESSAGE_WRITE_ON(on
->ospf6_if
);
2307 *op
= ospf6_packet_new(on
->ospf6_if
->ifmtu
);
2308 ospf6_make_header(OSPF6_MESSAGE_TYPE_LSACK
,
2309 on
->ospf6_if
, (*op
)->s
);
2314 ospf6_lsa_age_update_to_send(lsa
, on
->ospf6_if
->transdelay
);
2315 stream_put((*op
)->s
, lsa
->header
,
2316 sizeof(struct ospf6_lsa_header
));
2317 length
+= sizeof(struct ospf6_lsa_header
);
2319 assert(lsa
->lock
== 2);
2320 ospf6_lsdb_remove(lsa
, on
->lsack_list
);
2326 int ospf6_lsreq_send(struct thread
*thread
)
2328 struct ospf6_neighbor
*on
;
2329 struct ospf6_packet
*op
;
2330 uint16_t length
= OSPF6_HEADER_SIZE
;
2332 on
= (struct ospf6_neighbor
*)THREAD_ARG(thread
);
2333 on
->thread_send_lsreq
= (struct thread
*)NULL
;
2335 /* LSReq will be sent only in ExStart or Loading */
2336 if (on
->state
!= OSPF6_NEIGHBOR_EXCHANGE
2337 && on
->state
!= OSPF6_NEIGHBOR_LOADING
) {
2338 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_LSREQ
, SEND_HDR
))
2339 zlog_debug("Quit to send LSReq to neighbor %s state %s",
2341 ospf6_neighbor_state_str
[on
->state
]);
2345 /* schedule loading_done if request list is empty */
2346 if (on
->request_list
->count
== 0) {
2347 thread_add_event(master
, loading_done
, on
, 0, NULL
);
2351 op
= ospf6_packet_new(on
->ospf6_if
->ifmtu
);
2352 ospf6_make_header(OSPF6_MESSAGE_TYPE_LSREQ
, on
->ospf6_if
, op
->s
);
2354 length
+= ospf6_make_lsreq(on
, op
->s
);
2356 if (length
== OSPF6_HEADER_SIZE
) {
2357 /* Hello overshooting MTU */
2358 ospf6_packet_free(op
);
2362 /* Fill OSPF header. */
2363 ospf6_fill_header(on
->ospf6_if
, op
->s
, length
);
2365 /* Set packet length */
2366 op
->length
= length
;
2368 if (on
->ospf6_if
->state
== OSPF6_INTERFACE_POINTTOPOINT
)
2369 op
->dst
= allspfrouters6
;
2371 op
->dst
= on
->linklocal_addr
;
2373 ospf6_packet_add(on
->ospf6_if
, op
);
2375 OSPF6_MESSAGE_WRITE_ON(on
->ospf6_if
);
2377 /* set next thread */
2378 if (on
->request_list
->count
!= 0) {
2379 on
->thread_send_lsreq
= NULL
;
2380 thread_add_timer(master
, ospf6_lsreq_send
, on
,
2381 on
->ospf6_if
->rxmt_interval
,
2382 &on
->thread_send_lsreq
);
2388 static void ospf6_send_lsupdate(struct ospf6_neighbor
*on
,
2389 struct ospf6_interface
*oi
,
2390 struct ospf6_packet
*op
)
2395 if ((on
->ospf6_if
->state
== OSPF6_INTERFACE_POINTTOPOINT
)
2396 || (on
->ospf6_if
->state
== OSPF6_INTERFACE_DR
)
2397 || (on
->ospf6_if
->state
== OSPF6_INTERFACE_BDR
))
2398 op
->dst
= allspfrouters6
;
2400 op
->dst
= on
->linklocal_addr
;
2403 if ((oi
->state
== OSPF6_INTERFACE_POINTTOPOINT
)
2404 || (oi
->state
== OSPF6_INTERFACE_DR
)
2405 || (oi
->state
== OSPF6_INTERFACE_BDR
))
2406 op
->dst
= allspfrouters6
;
2408 op
->dst
= alldrouters6
;
2411 ospf6_packet_add(oi
, op
);
2412 OSPF6_MESSAGE_WRITE_ON(oi
);
2416 static uint16_t ospf6_make_lsupdate_list(struct ospf6_neighbor
*on
,
2417 struct ospf6_packet
**op
, int *lsa_cnt
)
2419 uint16_t length
= OSPF6_LS_UPD_MIN_SIZE
;
2420 struct ospf6_lsa
*lsa
, *lsanext
;
2422 /* skip over fixed header */
2423 stream_forward_endp((*op
)->s
, OSPF6_LS_UPD_MIN_SIZE
);
2425 for (ALL_LSDB(on
->lsupdate_list
, lsa
, lsanext
)) {
2426 if ((length
+ (unsigned int)OSPF6_LSA_SIZE(lsa
->header
)
2427 + OSPF6_HEADER_SIZE
)
2428 > ospf6_packet_max(on
->ospf6_if
)) {
2429 ospf6_fill_header(on
->ospf6_if
, (*op
)->s
,
2430 length
+ OSPF6_HEADER_SIZE
);
2431 (*op
)->length
= length
+ OSPF6_HEADER_SIZE
;
2432 ospf6_fill_lsupdate_header((*op
)->s
, *lsa_cnt
);
2433 ospf6_send_lsupdate(on
, NULL
, *op
);
2435 /* refresh packet */
2436 *op
= ospf6_packet_new(on
->ospf6_if
->ifmtu
);
2437 length
= OSPF6_LS_UPD_MIN_SIZE
;
2439 ospf6_make_header(OSPF6_MESSAGE_TYPE_LSUPDATE
,
2440 on
->ospf6_if
, (*op
)->s
);
2441 stream_forward_endp((*op
)->s
, OSPF6_LS_UPD_MIN_SIZE
);
2443 ospf6_lsa_age_update_to_send(lsa
, on
->ospf6_if
->transdelay
);
2444 stream_put((*op
)->s
, lsa
->header
, OSPF6_LSA_SIZE(lsa
->header
));
2446 length
+= OSPF6_LSA_SIZE(lsa
->header
);
2447 assert(lsa
->lock
== 2);
2448 ospf6_lsdb_remove(lsa
, on
->lsupdate_list
);
2453 static uint16_t ospf6_make_ls_retrans_list(struct ospf6_neighbor
*on
,
2454 struct ospf6_packet
**op
,
2457 uint16_t length
= OSPF6_LS_UPD_MIN_SIZE
;
2458 struct ospf6_lsa
*lsa
, *lsanext
;
2460 /* skip over fixed header */
2461 stream_forward_endp((*op
)->s
, OSPF6_LS_UPD_MIN_SIZE
);
2463 for (ALL_LSDB(on
->retrans_list
, lsa
, lsanext
)) {
2464 if ((length
+ (unsigned int)OSPF6_LSA_SIZE(lsa
->header
)
2465 + OSPF6_HEADER_SIZE
)
2466 > ospf6_packet_max(on
->ospf6_if
)) {
2467 ospf6_fill_header(on
->ospf6_if
, (*op
)->s
,
2468 length
+ OSPF6_HEADER_SIZE
);
2469 (*op
)->length
= length
+ OSPF6_HEADER_SIZE
;
2470 ospf6_fill_lsupdate_header((*op
)->s
, *lsa_cnt
);
2471 if (on
->ospf6_if
->state
== OSPF6_INTERFACE_POINTTOPOINT
)
2472 (*op
)->dst
= allspfrouters6
;
2474 (*op
)->dst
= on
->linklocal_addr
;
2476 ospf6_packet_add(on
->ospf6_if
, *op
);
2477 OSPF6_MESSAGE_WRITE_ON(on
->ospf6_if
);
2479 /* refresh packet */
2480 *op
= ospf6_packet_new(on
->ospf6_if
->ifmtu
);
2481 length
= OSPF6_LS_UPD_MIN_SIZE
;
2483 ospf6_make_header(OSPF6_MESSAGE_TYPE_LSUPDATE
,
2484 on
->ospf6_if
, (*op
)->s
);
2485 stream_forward_endp((*op
)->s
, OSPF6_LS_UPD_MIN_SIZE
);
2487 ospf6_lsa_age_update_to_send(lsa
, on
->ospf6_if
->transdelay
);
2488 stream_put((*op
)->s
, lsa
->header
, OSPF6_LSA_SIZE(lsa
->header
));
2490 length
+= OSPF6_LSA_SIZE(lsa
->header
);
2495 int ospf6_lsupdate_send_neighbor(struct thread
*thread
)
2497 struct ospf6_neighbor
*on
;
2498 struct ospf6_packet
*op
;
2499 uint16_t length
= OSPF6_HEADER_SIZE
;
2502 on
= (struct ospf6_neighbor
*)THREAD_ARG(thread
);
2503 on
->thread_send_lsupdate
= (struct thread
*)NULL
;
2505 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_LSUPDATE
, SEND_HDR
))
2506 zlog_debug("LSUpdate to neighbor %s", on
->name
);
2508 if (on
->state
< OSPF6_NEIGHBOR_EXCHANGE
) {
2509 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_LSUPDATE
,
2511 zlog_debug("Quit to send (neighbor state %s)",
2512 ospf6_neighbor_state_str
[on
->state
]);
2516 /* first do lsupdate_list */
2517 op
= ospf6_packet_new(on
->ospf6_if
->ifmtu
);
2518 ospf6_make_header(OSPF6_MESSAGE_TYPE_LSUPDATE
, on
->ospf6_if
, op
->s
);
2519 length
+= ospf6_make_lsupdate_list(on
, &op
, &lsa_cnt
);
2521 /* Fill OSPF header. */
2522 ospf6_fill_header(on
->ospf6_if
, op
->s
, length
);
2523 ospf6_fill_lsupdate_header(op
->s
, lsa_cnt
);
2524 op
->length
= length
;
2525 ospf6_send_lsupdate(on
, NULL
, op
);
2527 /* prepare new packet */
2528 op
= ospf6_packet_new(on
->ospf6_if
->ifmtu
);
2529 length
= OSPF6_HEADER_SIZE
;
2532 stream_reset(op
->s
);
2533 length
= OSPF6_HEADER_SIZE
;
2536 ospf6_make_header(OSPF6_MESSAGE_TYPE_LSUPDATE
, on
->ospf6_if
, op
->s
);
2537 /* now do retransmit list */
2538 length
+= ospf6_make_ls_retrans_list(on
, &op
, &lsa_cnt
);
2540 ospf6_fill_header(on
->ospf6_if
, op
->s
, length
);
2541 ospf6_fill_lsupdate_header(op
->s
, lsa_cnt
);
2542 op
->length
= length
;
2543 if (on
->ospf6_if
->state
== OSPF6_INTERFACE_POINTTOPOINT
)
2544 op
->dst
= allspfrouters6
;
2546 op
->dst
= on
->linklocal_addr
;
2547 ospf6_packet_add(on
->ospf6_if
, op
);
2548 OSPF6_MESSAGE_WRITE_ON(on
->ospf6_if
);
2550 ospf6_packet_free(op
);
2552 if (on
->lsupdate_list
->count
!= 0) {
2553 on
->thread_send_lsupdate
= NULL
;
2554 thread_add_event(master
, ospf6_lsupdate_send_neighbor
, on
, 0,
2555 &on
->thread_send_lsupdate
);
2556 } else if (on
->retrans_list
->count
!= 0) {
2557 on
->thread_send_lsupdate
= NULL
;
2558 thread_add_timer(master
, ospf6_lsupdate_send_neighbor
, on
,
2559 on
->ospf6_if
->rxmt_interval
,
2560 &on
->thread_send_lsupdate
);
2565 int ospf6_lsupdate_send_neighbor_now(struct ospf6_neighbor
*on
,
2566 struct ospf6_lsa
*lsa
)
2568 struct ospf6_packet
*op
;
2569 uint16_t length
= OSPF6_HEADER_SIZE
;
2571 op
= ospf6_packet_new(on
->ospf6_if
->ifmtu
);
2572 ospf6_make_header(OSPF6_MESSAGE_TYPE_LSUPDATE
, on
->ospf6_if
, op
->s
);
2574 /* skip over fixed header */
2575 stream_forward_endp(op
->s
, OSPF6_LS_UPD_MIN_SIZE
);
2576 ospf6_lsa_age_update_to_send(lsa
, on
->ospf6_if
->transdelay
);
2577 stream_put(op
->s
, lsa
->header
, OSPF6_LSA_SIZE(lsa
->header
));
2578 length
= OSPF6_HEADER_SIZE
+ OSPF6_LS_UPD_MIN_SIZE
2579 + OSPF6_LSA_SIZE(lsa
->header
);
2580 ospf6_fill_header(on
->ospf6_if
, op
->s
, length
);
2581 ospf6_fill_lsupdate_header(op
->s
, 1);
2582 op
->length
= length
;
2584 if (IS_OSPF6_DEBUG_FLOODING
2585 || IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_LSUPDATE
, SEND_HDR
))
2586 zlog_debug("%s: Send lsupdate with lsa %s (age %u)", __func__
,
2587 lsa
->name
, ntohs(lsa
->header
->age
));
2589 ospf6_send_lsupdate(on
, NULL
, op
);
2594 static uint16_t ospf6_make_lsupdate_interface(struct ospf6_interface
*oi
,
2595 struct ospf6_packet
**op
,
2598 uint16_t length
= OSPF6_LS_UPD_MIN_SIZE
;
2599 struct ospf6_lsa
*lsa
, *lsanext
;
2601 /* skip over fixed header */
2602 stream_forward_endp((*op
)->s
, OSPF6_LS_UPD_MIN_SIZE
);
2604 for (ALL_LSDB(oi
->lsupdate_list
, lsa
, lsanext
)) {
2605 if (length
+ (unsigned int)OSPF6_LSA_SIZE(lsa
->header
)
2607 > ospf6_packet_max(oi
)) {
2608 ospf6_fill_header(oi
, (*op
)->s
,
2609 length
+ OSPF6_HEADER_SIZE
);
2610 (*op
)->length
= length
+ OSPF6_HEADER_SIZE
;
2611 ospf6_fill_lsupdate_header((*op
)->s
, *lsa_cnt
);
2612 ospf6_send_lsupdate(NULL
, oi
, *op
);
2614 /* refresh packet */
2615 *op
= ospf6_packet_new(oi
->ifmtu
);
2616 length
= OSPF6_LS_UPD_MIN_SIZE
;
2618 ospf6_make_header(OSPF6_MESSAGE_TYPE_LSUPDATE
, oi
,
2620 stream_forward_endp((*op
)->s
, OSPF6_LS_UPD_MIN_SIZE
);
2623 ospf6_lsa_age_update_to_send(lsa
, oi
->transdelay
);
2624 stream_put((*op
)->s
, lsa
->header
, OSPF6_LSA_SIZE(lsa
->header
));
2626 length
+= OSPF6_LSA_SIZE(lsa
->header
);
2628 assert(lsa
->lock
== 2);
2629 ospf6_lsdb_remove(lsa
, oi
->lsupdate_list
);
2634 int ospf6_lsupdate_send_interface(struct thread
*thread
)
2636 struct ospf6_interface
*oi
;
2637 struct ospf6_packet
*op
;
2638 uint16_t length
= OSPF6_HEADER_SIZE
;
2641 oi
= (struct ospf6_interface
*)THREAD_ARG(thread
);
2642 oi
->thread_send_lsupdate
= (struct thread
*)NULL
;
2644 if (oi
->state
<= OSPF6_INTERFACE_WAITING
) {
2645 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_LSUPDATE
,
2648 "Quit to send LSUpdate to interface %s state %s",
2649 oi
->interface
->name
,
2650 ospf6_interface_state_str
[oi
->state
]);
2654 /* if we have nothing to send, return */
2655 if (oi
->lsupdate_list
->count
== 0)
2658 op
= ospf6_packet_new(oi
->ifmtu
);
2659 ospf6_make_header(OSPF6_MESSAGE_TYPE_LSUPDATE
, oi
, op
->s
);
2660 length
+= ospf6_make_lsupdate_interface(oi
, &op
, &lsa_cnt
);
2662 /* Fill OSPF header. */
2663 ospf6_fill_header(oi
, op
->s
, length
);
2664 ospf6_fill_lsupdate_header(op
->s
, lsa_cnt
);
2665 op
->length
= length
;
2666 ospf6_send_lsupdate(NULL
, oi
, op
);
2668 ospf6_packet_free(op
);
2670 if (oi
->lsupdate_list
->count
> 0) {
2671 oi
->thread_send_lsupdate
= NULL
;
2672 thread_add_event(master
, ospf6_lsupdate_send_interface
, oi
, 0,
2673 &oi
->thread_send_lsupdate
);
2679 int ospf6_lsack_send_neighbor(struct thread
*thread
)
2681 struct ospf6_neighbor
*on
;
2682 struct ospf6_packet
*op
;
2683 uint16_t length
= OSPF6_HEADER_SIZE
;
2685 on
= (struct ospf6_neighbor
*)THREAD_ARG(thread
);
2686 on
->thread_send_lsack
= (struct thread
*)NULL
;
2688 if (on
->state
< OSPF6_NEIGHBOR_EXCHANGE
) {
2689 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_LSACK
, SEND_HDR
))
2690 zlog_debug("Quit to send LSAck to neighbor %s state %s",
2692 ospf6_neighbor_state_str
[on
->state
]);
2696 /* if we have nothing to send, return */
2697 if (on
->lsack_list
->count
== 0)
2700 op
= ospf6_packet_new(on
->ospf6_if
->ifmtu
);
2701 ospf6_make_header(OSPF6_MESSAGE_TYPE_LSACK
, on
->ospf6_if
, op
->s
);
2703 length
+= ospf6_make_lsack_neighbor(on
, &op
);
2705 if (length
== OSPF6_HEADER_SIZE
) {
2706 ospf6_packet_free(op
);
2710 /* Fill OSPF header. */
2711 ospf6_fill_header(on
->ospf6_if
, op
->s
, length
);
2713 /* Set packet length, dst and queue to FIFO. */
2714 op
->length
= length
;
2715 op
->dst
= on
->linklocal_addr
;
2716 ospf6_packet_add(on
->ospf6_if
, op
);
2717 OSPF6_MESSAGE_WRITE_ON(on
->ospf6_if
);
2719 if (on
->lsack_list
->count
> 0)
2720 thread_add_event(master
, ospf6_lsack_send_neighbor
, on
, 0,
2721 &on
->thread_send_lsack
);
2726 static uint16_t ospf6_make_lsack_interface(struct ospf6_interface
*oi
,
2727 struct ospf6_packet
*op
)
2729 uint16_t length
= 0;
2730 struct ospf6_lsa
*lsa
, *lsanext
;
2732 for (ALL_LSDB(oi
->lsack_list
, lsa
, lsanext
)) {
2733 if ((length
+ sizeof(struct ospf6_lsa_header
)
2734 + OSPF6_HEADER_SIZE
)
2735 > ospf6_packet_max(oi
)) {
2736 /* if we run out of packet size/space here,
2737 better to try again soon. */
2738 THREAD_OFF(oi
->thread_send_lsack
);
2739 thread_add_event(master
, ospf6_lsack_send_interface
, oi
,
2740 0, &oi
->thread_send_lsack
);
2742 ospf6_lsa_unlock(lsa
);
2744 ospf6_lsa_unlock(lsanext
);
2747 ospf6_lsa_age_update_to_send(lsa
, oi
->transdelay
);
2748 stream_put(op
->s
, lsa
->header
, sizeof(struct ospf6_lsa_header
));
2749 length
+= sizeof(struct ospf6_lsa_header
);
2751 assert(lsa
->lock
== 2);
2752 ospf6_lsdb_remove(lsa
, oi
->lsack_list
);
2757 int ospf6_lsack_send_interface(struct thread
*thread
)
2759 struct ospf6_interface
*oi
;
2760 struct ospf6_packet
*op
;
2761 uint16_t length
= OSPF6_HEADER_SIZE
;
2763 oi
= (struct ospf6_interface
*)THREAD_ARG(thread
);
2764 oi
->thread_send_lsack
= (struct thread
*)NULL
;
2766 if (oi
->state
<= OSPF6_INTERFACE_WAITING
) {
2767 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_LSACK
, SEND_HDR
))
2769 "Quit to send LSAck to interface %s state %s",
2770 oi
->interface
->name
,
2771 ospf6_interface_state_str
[oi
->state
]);
2775 /* if we have nothing to send, return */
2776 if (oi
->lsack_list
->count
== 0)
2779 op
= ospf6_packet_new(oi
->ifmtu
);
2780 ospf6_make_header(OSPF6_MESSAGE_TYPE_LSACK
, oi
, op
->s
);
2782 length
+= ospf6_make_lsack_interface(oi
, op
);
2784 if (length
== OSPF6_HEADER_SIZE
) {
2785 ospf6_packet_free(op
);
2788 /* Fill OSPF header. */
2789 ospf6_fill_header(oi
, op
->s
, length
);
2791 /* Set packet length, dst and queue to FIFO. */
2792 op
->length
= length
;
2793 if ((oi
->state
== OSPF6_INTERFACE_POINTTOPOINT
)
2794 || (oi
->state
== OSPF6_INTERFACE_DR
)
2795 || (oi
->state
== OSPF6_INTERFACE_BDR
))
2796 op
->dst
= allspfrouters6
;
2798 op
->dst
= alldrouters6
;
2800 ospf6_packet_add(oi
, op
);
2801 OSPF6_MESSAGE_WRITE_ON(oi
);
2803 if (oi
->lsack_list
->count
> 0)
2804 thread_add_event(master
, ospf6_lsack_send_interface
, oi
, 0,
2805 &oi
->thread_send_lsack
);
2811 DEFUN(debug_ospf6_message
, debug_ospf6_message_cmd
,
2812 "debug ospf6 message <unknown|hello|dbdesc|lsreq|lsupdate|lsack|all> [<send|recv|send-hdr|recv-hdr>]",
2814 "Debug OSPFv3 message\n"
2815 "Debug Unknown message\n"
2816 "Debug Hello message\n"
2817 "Debug Database Description message\n"
2818 "Debug Link State Request message\n"
2819 "Debug Link State Update message\n"
2820 "Debug Link State Acknowledgement message\n"
2821 "Debug All message\n"
2822 "Debug only sending message, entire packet\n"
2823 "Debug only receiving message, entire packet\n"
2824 "Debug only sending message, header only\n"
2825 "Debug only receiving message, header only\n")
2828 int idx_send_recv
= 4;
2829 unsigned char level
= 0;
2834 if (!strncmp(argv
[idx_packet
]->arg
, "u", 1))
2835 type
= OSPF6_MESSAGE_TYPE_UNKNOWN
;
2836 else if (!strncmp(argv
[idx_packet
]->arg
, "h", 1))
2837 type
= OSPF6_MESSAGE_TYPE_HELLO
;
2838 else if (!strncmp(argv
[idx_packet
]->arg
, "d", 1))
2839 type
= OSPF6_MESSAGE_TYPE_DBDESC
;
2840 else if (!strncmp(argv
[idx_packet
]->arg
, "lsr", 3))
2841 type
= OSPF6_MESSAGE_TYPE_LSREQ
;
2842 else if (!strncmp(argv
[idx_packet
]->arg
, "lsu", 3))
2843 type
= OSPF6_MESSAGE_TYPE_LSUPDATE
;
2844 else if (!strncmp(argv
[idx_packet
]->arg
, "lsa", 3))
2845 type
= OSPF6_MESSAGE_TYPE_LSACK
;
2846 else if (!strncmp(argv
[idx_packet
]->arg
, "a", 1))
2847 type
= OSPF6_MESSAGE_TYPE_ALL
;
2850 level
= OSPF6_DEBUG_MESSAGE_SEND
| OSPF6_DEBUG_MESSAGE_RECV
;
2851 else if (!strncmp(argv
[idx_send_recv
]->arg
, "send-h", 6))
2852 level
= OSPF6_DEBUG_MESSAGE_SEND_HDR
;
2853 else if (!strncmp(argv
[idx_send_recv
]->arg
, "s", 1))
2854 level
= OSPF6_DEBUG_MESSAGE_SEND
;
2855 else if (!strncmp(argv
[idx_send_recv
]->arg
, "recv-h", 6))
2856 level
= OSPF6_DEBUG_MESSAGE_RECV_HDR
;
2857 else if (!strncmp(argv
[idx_send_recv
]->arg
, "r", 1))
2858 level
= OSPF6_DEBUG_MESSAGE_RECV
;
2860 if (type
== OSPF6_MESSAGE_TYPE_ALL
) {
2861 for (i
= 0; i
< 6; i
++)
2862 OSPF6_DEBUG_MESSAGE_ON(i
, level
);
2864 OSPF6_DEBUG_MESSAGE_ON(type
, level
);
2869 DEFUN(no_debug_ospf6_message
, no_debug_ospf6_message_cmd
,
2870 "no debug ospf6 message <unknown|hello|dbdesc|lsreq|lsupdate|lsack|all> [<send|recv|send-hdr|recv-hdr>]",
2871 NO_STR DEBUG_STR OSPF6_STR
2872 "Debug OSPFv3 message\n"
2873 "Debug Unknown message\n"
2874 "Debug Hello message\n"
2875 "Debug Database Description message\n"
2876 "Debug Link State Request message\n"
2877 "Debug Link State Update message\n"
2878 "Debug Link State Acknowledgement message\n"
2879 "Debug All message\n"
2880 "Debug only sending message, entire pkt\n"
2881 "Debug only receiving message, entire pkt\n"
2882 "Debug only sending message, header only\n"
2883 "Debug only receiving message, header only\n")
2886 int idx_send_recv
= 5;
2887 unsigned char level
= 0;
2892 if (!strncmp(argv
[idx_packet
]->arg
, "u", 1))
2893 type
= OSPF6_MESSAGE_TYPE_UNKNOWN
;
2894 else if (!strncmp(argv
[idx_packet
]->arg
, "h", 1))
2895 type
= OSPF6_MESSAGE_TYPE_HELLO
;
2896 else if (!strncmp(argv
[idx_packet
]->arg
, "d", 1))
2897 type
= OSPF6_MESSAGE_TYPE_DBDESC
;
2898 else if (!strncmp(argv
[idx_packet
]->arg
, "lsr", 3))
2899 type
= OSPF6_MESSAGE_TYPE_LSREQ
;
2900 else if (!strncmp(argv
[idx_packet
]->arg
, "lsu", 3))
2901 type
= OSPF6_MESSAGE_TYPE_LSUPDATE
;
2902 else if (!strncmp(argv
[idx_packet
]->arg
, "lsa", 3))
2903 type
= OSPF6_MESSAGE_TYPE_LSACK
;
2904 else if (!strncmp(argv
[idx_packet
]->arg
, "a", 1))
2905 type
= OSPF6_MESSAGE_TYPE_ALL
;
2908 level
= OSPF6_DEBUG_MESSAGE_SEND
| OSPF6_DEBUG_MESSAGE_RECV
2909 | OSPF6_DEBUG_MESSAGE_SEND_HDR
2910 | OSPF6_DEBUG_MESSAGE_RECV_HDR
;
2911 else if (!strncmp(argv
[idx_send_recv
]->arg
, "send-h", 6))
2912 level
= OSPF6_DEBUG_MESSAGE_SEND_HDR
;
2913 else if (!strncmp(argv
[idx_send_recv
]->arg
, "s", 1))
2914 level
= OSPF6_DEBUG_MESSAGE_SEND
;
2915 else if (!strncmp(argv
[idx_send_recv
]->arg
, "recv-h", 6))
2916 level
= OSPF6_DEBUG_MESSAGE_RECV_HDR
;
2917 else if (!strncmp(argv
[idx_send_recv
]->arg
, "r", 1))
2918 level
= OSPF6_DEBUG_MESSAGE_RECV
;
2920 if (type
== OSPF6_MESSAGE_TYPE_ALL
) {
2921 for (i
= 0; i
< 6; i
++)
2922 OSPF6_DEBUG_MESSAGE_OFF(i
, level
);
2924 OSPF6_DEBUG_MESSAGE_OFF(type
, level
);
2930 int config_write_ospf6_debug_message(struct vty
*vty
)
2932 const char *type_str
[] = {"unknown", "hello", "dbdesc",
2933 "lsreq", "lsupdate", "lsack"};
2934 unsigned char s
= 0, r
= 0, sh
= 0, rh
= 0;
2937 for (i
= 0; i
< 6; i
++) {
2938 if (IS_OSPF6_DEBUG_MESSAGE_ENABLED(i
, SEND
))
2940 if (IS_OSPF6_DEBUG_MESSAGE_ENABLED(i
, RECV
))
2944 for (i
= 0; i
< 6; i
++) {
2945 if (IS_OSPF6_DEBUG_MESSAGE_ENABLED(i
, SEND_HDR
))
2947 if (IS_OSPF6_DEBUG_MESSAGE_ENABLED(i
, RECV_HDR
))
2951 if (s
== 0x3f && r
== 0x3f) {
2952 vty_out(vty
, "debug ospf6 message all\n");
2956 if (s
== 0x3f && r
== 0) {
2957 vty_out(vty
, "debug ospf6 message all send\n");
2959 } else if (s
== 0 && r
== 0x3f) {
2960 vty_out(vty
, "debug ospf6 message all recv\n");
2964 if (sh
== 0x3f && rh
== 0) {
2965 vty_out(vty
, "debug ospf6 message all send-hdr\n");
2967 } else if (sh
== 0 && rh
== 0x3f) {
2968 vty_out(vty
, "debug ospf6 message all recv-hdr\n");
2972 /* Unknown message is logged by default */
2973 if (!IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN
, SEND
)
2974 && !IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN
, RECV
))
2975 vty_out(vty
, "no debug ospf6 message unknown\n");
2976 else if (!IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN
, SEND
))
2977 vty_out(vty
, "no debug ospf6 message unknown send\n");
2978 else if (!IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN
, RECV
))
2979 vty_out(vty
, "no debug ospf6 message unknown recv\n");
2981 for (i
= 1; i
< 6; i
++) {
2982 if (IS_OSPF6_DEBUG_MESSAGE_ENABLED(i
, SEND
)
2983 && IS_OSPF6_DEBUG_MESSAGE_ENABLED(i
, RECV
)) {
2984 vty_out(vty
, "debug ospf6 message %s\n", type_str
[i
]);
2988 if (IS_OSPF6_DEBUG_MESSAGE_ENABLED(i
, SEND
))
2989 vty_out(vty
, "debug ospf6 message %s send\n",
2991 else if (IS_OSPF6_DEBUG_MESSAGE_ENABLED(i
, SEND_HDR
))
2992 vty_out(vty
, "debug ospf6 message %s send-hdr\n",
2995 if (IS_OSPF6_DEBUG_MESSAGE_ENABLED(i
, RECV
))
2996 vty_out(vty
, "debug ospf6 message %s recv\n",
2998 else if (IS_OSPF6_DEBUG_MESSAGE_ENABLED(i
, RECV_HDR
))
2999 vty_out(vty
, "debug ospf6 message %s recv-hdr\n",
3006 void install_element_ospf6_debug_message(void)
3008 install_element(ENABLE_NODE
, &debug_ospf6_message_cmd
);
3009 install_element(ENABLE_NODE
, &no_debug_ospf6_message_cmd
);
3010 install_element(CONFIG_NODE
, &debug_ospf6_message_cmd
);
3011 install_element(CONFIG_NODE
, &no_debug_ospf6_message_cmd
);