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");
54 unsigned char conf_debug_ospf6_message
[6] = {0x03, 0, 0, 0, 0, 0};
55 static const struct message ospf6_message_type_str
[] = {
56 {OSPF6_MESSAGE_TYPE_HELLO
, "Hello"},
57 {OSPF6_MESSAGE_TYPE_DBDESC
, "DbDesc"},
58 {OSPF6_MESSAGE_TYPE_LSREQ
, "LSReq"},
59 {OSPF6_MESSAGE_TYPE_LSUPDATE
, "LSUpdate"},
60 {OSPF6_MESSAGE_TYPE_LSACK
, "LSAck"},
63 /* Minimum (besides the standard OSPF packet header) lengths for OSPF
64 packets of particular types, offset is the "type" field. */
65 const uint16_t ospf6_packet_minlen
[OSPF6_MESSAGE_TYPE_ALL
] = {
68 OSPF6_DB_DESC_MIN_SIZE
,
69 OSPF6_LS_REQ_MIN_SIZE
,
70 OSPF6_LS_UPD_MIN_SIZE
,
71 OSPF6_LS_ACK_MIN_SIZE
};
73 /* Minimum (besides the standard LSA header) lengths for LSAs of particular
74 types, offset is the "LSA function code" portion of "LSA type" field. */
75 const uint16_t ospf6_lsa_minlen
[OSPF6_LSTYPE_SIZE
] = {
77 /* 0x2001 */ OSPF6_ROUTER_LSA_MIN_SIZE
,
78 /* 0x2002 */ OSPF6_NETWORK_LSA_MIN_SIZE
,
79 /* 0x2003 */ OSPF6_INTER_PREFIX_LSA_MIN_SIZE
,
80 /* 0x2004 */ OSPF6_INTER_ROUTER_LSA_FIX_SIZE
,
81 /* 0x4005 */ OSPF6_AS_EXTERNAL_LSA_MIN_SIZE
,
83 /* 0x2007 */ OSPF6_AS_EXTERNAL_LSA_MIN_SIZE
,
84 /* 0x0008 */ OSPF6_LINK_LSA_MIN_SIZE
,
85 /* 0x2009 */ OSPF6_INTRA_PREFIX_LSA_MIN_SIZE
};
89 static void ospf6_header_print(struct ospf6_header
*oh
)
91 zlog_debug(" OSPFv%d Type:%d Len:%hu Router-ID:%pI4", oh
->version
,
92 oh
->type
, ntohs(oh
->length
), &oh
->router_id
);
93 zlog_debug(" Area-ID:%pI4 Cksum:%hx Instance-ID:%d", &oh
->area_id
,
94 ntohs(oh
->checksum
), oh
->instance_id
);
97 void ospf6_hello_print(struct ospf6_header
*oh
, int action
)
99 struct ospf6_hello
*hello
;
103 ospf6_header_print(oh
);
104 assert(oh
->type
== OSPF6_MESSAGE_TYPE_HELLO
);
106 hello
= (struct ospf6_hello
*)((caddr_t
)oh
107 + sizeof(struct ospf6_header
));
109 ospf6_options_printbuf(hello
->options
, options
, sizeof(options
));
111 zlog_debug(" I/F-Id:%ld Priority:%d Option:%s",
112 (unsigned long)ntohl(hello
->interface_id
), hello
->priority
,
114 zlog_debug(" HelloInterval:%hu DeadInterval:%hu",
115 ntohs(hello
->hello_interval
), ntohs(hello
->dead_interval
));
116 zlog_debug(" DR:%pI4 BDR:%pI4", &hello
->drouter
, &hello
->bdrouter
);
118 if ((IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
)
119 && action
== OSPF6_ACTION_RECV
)
120 || (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, SEND
)
121 && action
== OSPF6_ACTION_SEND
)) {
123 for (p
= (char *)((caddr_t
)hello
+ sizeof(struct ospf6_hello
));
124 p
+ sizeof(uint32_t) <= OSPF6_MESSAGE_END(oh
);
125 p
+= sizeof(uint32_t))
126 zlog_debug(" Neighbor: %pI4", (in_addr_t
*)p
);
128 assert(p
== OSPF6_MESSAGE_END(oh
));
132 void ospf6_dbdesc_print(struct ospf6_header
*oh
, int action
)
134 struct ospf6_dbdesc
*dbdesc
;
138 ospf6_header_print(oh
);
139 assert(oh
->type
== OSPF6_MESSAGE_TYPE_DBDESC
);
141 dbdesc
= (struct ospf6_dbdesc
*)((caddr_t
)oh
142 + sizeof(struct ospf6_header
));
144 ospf6_options_printbuf(dbdesc
->options
, options
, sizeof(options
));
146 zlog_debug(" MBZ: %#x Option: %s IfMTU: %hu", dbdesc
->reserved1
,
147 options
, ntohs(dbdesc
->ifmtu
));
148 zlog_debug(" MBZ: %#x Bits: %s%s%s SeqNum: %#lx", dbdesc
->reserved2
,
149 (CHECK_FLAG(dbdesc
->bits
, OSPF6_DBDESC_IBIT
) ? "I" : "-"),
150 (CHECK_FLAG(dbdesc
->bits
, OSPF6_DBDESC_MBIT
) ? "M" : "-"),
151 (CHECK_FLAG(dbdesc
->bits
, OSPF6_DBDESC_MSBIT
) ? "m" : "s"),
152 (unsigned long)ntohl(dbdesc
->seqnum
));
154 if ((IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
)
155 && action
== OSPF6_ACTION_RECV
)
156 || (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, SEND
)
157 && action
== OSPF6_ACTION_SEND
)) {
159 for (p
= (char *)((caddr_t
)dbdesc
160 + sizeof(struct ospf6_dbdesc
));
161 p
+ sizeof(struct ospf6_lsa_header
)
162 <= OSPF6_MESSAGE_END(oh
);
163 p
+= sizeof(struct ospf6_lsa_header
))
164 ospf6_lsa_header_print_raw(
165 (struct ospf6_lsa_header
*)p
);
167 assert(p
== OSPF6_MESSAGE_END(oh
));
171 void ospf6_lsreq_print(struct ospf6_header
*oh
, int action
)
175 ospf6_header_print(oh
);
176 assert(oh
->type
== OSPF6_MESSAGE_TYPE_LSREQ
);
178 if ((IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
)
179 && action
== OSPF6_ACTION_RECV
)
180 || (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, SEND
)
181 && action
== OSPF6_ACTION_SEND
)) {
183 for (p
= (char *)((caddr_t
)oh
+ sizeof(struct ospf6_header
));
184 p
+ sizeof(struct ospf6_lsreq_entry
)
185 <= OSPF6_MESSAGE_END(oh
);
186 p
+= sizeof(struct ospf6_lsreq_entry
)) {
187 struct ospf6_lsreq_entry
*e
=
188 (struct ospf6_lsreq_entry
*)p
;
190 zlog_debug(" [%s Id:%pI4 Adv:%pI4]",
191 ospf6_lstype_name(e
->type
), &e
->id
,
195 assert(p
== OSPF6_MESSAGE_END(oh
));
199 void ospf6_lsupdate_print(struct ospf6_header
*oh
, int action
)
201 struct ospf6_lsupdate
*lsupdate
;
205 ospf6_header_print(oh
);
206 assert(oh
->type
== OSPF6_MESSAGE_TYPE_LSUPDATE
);
208 lsupdate
= (struct ospf6_lsupdate
*)((caddr_t
)oh
209 + sizeof(struct ospf6_header
));
211 num
= ntohl(lsupdate
->lsa_number
);
212 zlog_debug(" Number of LSA: %ld", num
);
214 if ((IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
)
215 && action
== OSPF6_ACTION_RECV
)
216 || (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, SEND
)
217 && action
== OSPF6_ACTION_SEND
)) {
219 for (p
= (char *)((caddr_t
)lsupdate
220 + sizeof(struct ospf6_lsupdate
));
221 p
< OSPF6_MESSAGE_END(oh
)
222 && p
+ OSPF6_LSA_SIZE(p
) <= OSPF6_MESSAGE_END(oh
);
223 p
+= OSPF6_LSA_SIZE(p
)) {
224 ospf6_lsa_header_print_raw(
225 (struct ospf6_lsa_header
*)p
);
228 assert(p
== OSPF6_MESSAGE_END(oh
));
232 void ospf6_lsack_print(struct ospf6_header
*oh
, int action
)
236 ospf6_header_print(oh
);
237 assert(oh
->type
== OSPF6_MESSAGE_TYPE_LSACK
);
239 if ((IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
)
240 && action
== OSPF6_ACTION_RECV
)
241 || (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, SEND
)
242 && action
== OSPF6_ACTION_SEND
)) {
244 for (p
= (char *)((caddr_t
)oh
+ sizeof(struct ospf6_header
));
245 p
+ sizeof(struct ospf6_lsa_header
)
246 <= OSPF6_MESSAGE_END(oh
);
247 p
+= sizeof(struct ospf6_lsa_header
))
248 ospf6_lsa_header_print_raw(
249 (struct ospf6_lsa_header
*)p
);
251 assert(p
== OSPF6_MESSAGE_END(oh
));
255 static void ospf6_hello_recv(struct in6_addr
*src
, struct in6_addr
*dst
,
256 struct ospf6_interface
*oi
,
257 struct ospf6_header
*oh
)
259 struct ospf6_hello
*hello
;
260 struct ospf6_neighbor
*on
;
263 int neighborchange
= 0;
264 int neighbor_ifindex_change
= 0;
267 hello
= (struct ospf6_hello
*)((caddr_t
)oh
268 + sizeof(struct ospf6_header
));
270 /* HelloInterval check */
271 if (ntohs(hello
->hello_interval
) != oi
->hello_interval
) {
273 "VRF %s: I/F %s HelloInterval mismatch: (my %d, rcvd %d)",
274 vrf_id_to_name(oi
->interface
->vrf_id
),
275 oi
->interface
->name
, oi
->hello_interval
,
276 ntohs(hello
->hello_interval
));
280 /* RouterDeadInterval check */
281 if (ntohs(hello
->dead_interval
) != oi
->dead_interval
) {
283 "VRF %s: I/F %s DeadInterval mismatch: (my %d, rcvd %d)",
284 vrf_id_to_name(oi
->interface
->vrf_id
),
285 oi
->interface
->name
, oi
->dead_interval
,
286 ntohs(hello
->dead_interval
));
291 if (OSPF6_OPT_ISSET(hello
->options
, OSPF6_OPT_E
)
292 != OSPF6_OPT_ISSET(oi
->area
->options
, OSPF6_OPT_E
)) {
293 zlog_warn("VRF %s: IF %s E-bit mismatch",
294 vrf_id_to_name(oi
->interface
->vrf_id
),
295 oi
->interface
->name
);
299 /* Find neighbor, create if not exist */
300 on
= ospf6_neighbor_lookup(oh
->router_id
, oi
);
302 on
= ospf6_neighbor_create(oh
->router_id
, oi
);
303 on
->prev_drouter
= on
->drouter
= hello
->drouter
;
304 on
->prev_bdrouter
= on
->bdrouter
= hello
->bdrouter
;
305 on
->priority
= hello
->priority
;
308 /* Always override neighbor's source address */
309 memcpy(&on
->linklocal_addr
, src
, sizeof(struct in6_addr
));
311 /* Neighbor ifindex check */
312 if (on
->ifindex
!= (ifindex_t
)ntohl(hello
->interface_id
)) {
313 on
->ifindex
= ntohl(hello
->interface_id
);
314 neighbor_ifindex_change
++;
318 for (p
= (char *)((caddr_t
)hello
+ sizeof(struct ospf6_hello
));
319 p
+ sizeof(uint32_t) <= OSPF6_MESSAGE_END(oh
);
320 p
+= sizeof(uint32_t)) {
321 uint32_t *router_id
= (uint32_t *)p
;
323 if (*router_id
== oi
->area
->ospf6
->router_id
)
327 assert(p
== OSPF6_MESSAGE_END(oh
));
329 /* RouterPriority check */
330 if (on
->priority
!= hello
->priority
) {
331 on
->priority
= hello
->priority
;
336 if (on
->drouter
!= hello
->drouter
) {
337 on
->prev_drouter
= on
->drouter
;
338 on
->drouter
= hello
->drouter
;
339 if (on
->prev_drouter
== on
->router_id
340 || on
->drouter
== on
->router_id
)
345 if (on
->bdrouter
!= hello
->bdrouter
) {
346 on
->prev_bdrouter
= on
->bdrouter
;
347 on
->bdrouter
= hello
->bdrouter
;
348 if (on
->prev_bdrouter
== on
->router_id
349 || on
->bdrouter
== on
->router_id
)
353 /* BackupSeen check */
354 if (oi
->state
== OSPF6_INTERFACE_WAITING
) {
355 if (hello
->bdrouter
== on
->router_id
)
357 else if (hello
->drouter
== on
->router_id
358 && hello
->bdrouter
== htonl(0))
364 /* Execute neighbor events */
365 thread_execute(master
, hello_received
, on
, 0);
367 thread_execute(master
, twoway_received
, on
, 0);
369 thread_execute(master
, oneway_received
, on
, 0);
371 /* Schedule interface events */
373 thread_add_event(master
, backup_seen
, oi
, 0, NULL
);
375 thread_add_event(master
, neighbor_change
, oi
, 0, NULL
);
377 if (neighbor_ifindex_change
&& on
->state
== OSPF6_NEIGHBOR_FULL
)
378 OSPF6_ROUTER_LSA_SCHEDULE(oi
->area
);
381 static void ospf6_dbdesc_recv_master(struct ospf6_header
*oh
,
382 struct ospf6_neighbor
*on
)
384 struct ospf6_dbdesc
*dbdesc
;
387 dbdesc
= (struct ospf6_dbdesc
*)((caddr_t
)oh
388 + sizeof(struct ospf6_header
));
390 if (on
->state
< OSPF6_NEIGHBOR_INIT
) {
391 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV_HDR
))
392 zlog_debug("Neighbor state less than Init, ignore");
397 case OSPF6_NEIGHBOR_TWOWAY
:
398 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV_HDR
))
399 zlog_debug("Neighbor state is 2-Way, ignore");
402 case OSPF6_NEIGHBOR_INIT
:
403 thread_execute(master
, twoway_received
, on
, 0);
404 if (on
->state
!= OSPF6_NEIGHBOR_EXSTART
) {
405 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV_HDR
))
407 "Neighbor state is not ExStart, ignore");
410 /* else fall through to ExStart */
412 case OSPF6_NEIGHBOR_EXSTART
:
413 /* if neighbor obeys us as our slave, schedule negotiation_done
414 and process LSA Headers. Otherwise, ignore this message */
415 if (!CHECK_FLAG(dbdesc
->bits
, OSPF6_DBDESC_MSBIT
)
416 && !CHECK_FLAG(dbdesc
->bits
, OSPF6_DBDESC_IBIT
)
417 && ntohl(dbdesc
->seqnum
) == on
->dbdesc_seqnum
) {
418 /* execute NegotiationDone */
419 thread_execute(master
, negotiation_done
, on
, 0);
421 /* Record neighbor options */
422 memcpy(on
->options
, dbdesc
->options
,
423 sizeof(on
->options
));
426 "VRF %s: Nbr %s: Negotiation failed",
427 vrf_id_to_name(on
->ospf6_if
->interface
->vrf_id
),
431 /* fall through to exchange */
433 case OSPF6_NEIGHBOR_EXCHANGE
:
434 if (!memcmp(dbdesc
, &on
->dbdesc_last
,
435 sizeof(struct ospf6_dbdesc
))) {
436 /* Duplicated DatabaseDescription is dropped by master
438 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV_HDR
))
440 "Duplicated dbdesc discarded by Master, ignore");
444 if (CHECK_FLAG(dbdesc
->bits
, OSPF6_DBDESC_MSBIT
)) {
446 "DbDesc recv: Master/Slave bit mismatch Nbr %s",
448 thread_add_event(master
, seqnumber_mismatch
, on
, 0,
453 if (CHECK_FLAG(dbdesc
->bits
, OSPF6_DBDESC_IBIT
)) {
454 zlog_warn("DbDesc recv: Initialize bit mismatch Nbr %s",
456 thread_add_event(master
, seqnumber_mismatch
, on
, 0,
461 if (memcmp(on
->options
, dbdesc
->options
, sizeof(on
->options
))) {
462 zlog_warn("DbDesc recv: Option field mismatch Nbr %s",
464 thread_add_event(master
, seqnumber_mismatch
, on
, 0,
469 if (ntohl(dbdesc
->seqnum
) != on
->dbdesc_seqnum
) {
471 "DbDesc recv: Sequence number mismatch Nbr %s (%#lx expected)",
472 on
->name
, (unsigned long)on
->dbdesc_seqnum
);
473 thread_add_event(master
, seqnumber_mismatch
, on
, 0,
479 case OSPF6_NEIGHBOR_LOADING
:
480 case OSPF6_NEIGHBOR_FULL
:
481 if (!memcmp(dbdesc
, &on
->dbdesc_last
,
482 sizeof(struct ospf6_dbdesc
))) {
483 /* Duplicated DatabaseDescription is dropped by master
485 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV_HDR
))
487 "Duplicated dbdesc discarded by Master, ignore");
492 "DbDesc recv: Not duplicate dbdesc in state %s Nbr %s",
493 ospf6_neighbor_state_str
[on
->state
], on
->name
);
494 thread_add_event(master
, seqnumber_mismatch
, on
, 0, NULL
);
502 /* Process LSA headers */
503 for (p
= (char *)((caddr_t
)dbdesc
+ sizeof(struct ospf6_dbdesc
));
504 p
+ sizeof(struct ospf6_lsa_header
) <= OSPF6_MESSAGE_END(oh
);
505 p
+= sizeof(struct ospf6_lsa_header
)) {
506 struct ospf6_lsa
*his
, *mine
;
507 struct ospf6_lsdb
*lsdb
= NULL
;
509 his
= ospf6_lsa_create_headeronly((struct ospf6_lsa_header
*)p
);
511 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
512 zlog_debug("%s", his
->name
);
514 switch (OSPF6_LSA_SCOPE(his
->header
->type
)) {
515 case OSPF6_SCOPE_LINKLOCAL
:
516 lsdb
= on
->ospf6_if
->lsdb
;
518 case OSPF6_SCOPE_AREA
:
519 lsdb
= on
->ospf6_if
->area
->lsdb
;
522 lsdb
= on
->ospf6_if
->area
->ospf6
->lsdb
;
524 case OSPF6_SCOPE_RESERVED
:
525 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
526 zlog_debug("Ignoring LSA of reserved scope");
527 ospf6_lsa_delete(his
);
532 if (ntohs(his
->header
->type
) == OSPF6_LSTYPE_AS_EXTERNAL
533 && (IS_AREA_STUB(on
->ospf6_if
->area
)
534 || IS_AREA_NSSA(on
->ospf6_if
->area
))) {
535 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
537 "SeqNumMismatch (E-bit mismatch), discard");
538 ospf6_lsa_delete(his
);
539 thread_add_event(master
, seqnumber_mismatch
, on
, 0,
544 mine
= ospf6_lsdb_lookup(his
->header
->type
, his
->header
->id
,
545 his
->header
->adv_router
, lsdb
);
547 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
548 zlog_debug("Add request (No database copy)");
549 ospf6_lsdb_add(ospf6_lsa_copy(his
), on
->request_list
);
550 } else if (ospf6_lsa_compare(his
, mine
) < 0) {
551 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
552 zlog_debug("Add request (Received MoreRecent)");
553 ospf6_lsdb_add(ospf6_lsa_copy(his
), on
->request_list
);
555 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
556 zlog_debug("Discard (Existing MoreRecent)");
558 ospf6_lsa_delete(his
);
561 assert(p
== OSPF6_MESSAGE_END(oh
));
563 /* Increment sequence number */
566 /* schedule send lsreq */
567 if (on
->request_list
->count
)
568 thread_add_event(master
, ospf6_lsreq_send
, on
, 0,
569 &on
->thread_send_lsreq
);
571 THREAD_OFF(on
->thread_send_dbdesc
);
574 if (!CHECK_FLAG(dbdesc
->bits
, OSPF6_DBDESC_MBIT
)
575 && !CHECK_FLAG(on
->dbdesc_bits
, OSPF6_DBDESC_MBIT
))
576 thread_add_event(master
, exchange_done
, on
, 0, NULL
);
578 on
->thread_send_dbdesc
= NULL
;
579 thread_add_event(master
, ospf6_dbdesc_send_newone
, on
, 0,
580 &on
->thread_send_dbdesc
);
583 /* save last received dbdesc */
584 memcpy(&on
->dbdesc_last
, dbdesc
, sizeof(struct ospf6_dbdesc
));
587 static void ospf6_dbdesc_recv_slave(struct ospf6_header
*oh
,
588 struct ospf6_neighbor
*on
)
590 struct ospf6_dbdesc
*dbdesc
;
593 dbdesc
= (struct ospf6_dbdesc
*)((caddr_t
)oh
594 + sizeof(struct ospf6_header
));
596 if (on
->state
< OSPF6_NEIGHBOR_INIT
) {
597 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV_HDR
))
598 zlog_debug("Neighbor state less than Init, ignore");
603 case OSPF6_NEIGHBOR_TWOWAY
:
604 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV_HDR
))
605 zlog_debug("Neighbor state is 2-Way, ignore");
608 case OSPF6_NEIGHBOR_INIT
:
609 thread_execute(master
, twoway_received
, on
, 0);
610 if (on
->state
!= OSPF6_NEIGHBOR_EXSTART
) {
611 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV_HDR
))
613 "Neighbor state is not ExStart, ignore");
616 /* else fall through to ExStart */
618 case OSPF6_NEIGHBOR_EXSTART
:
619 /* If the neighbor is Master, act as Slave. Schedule
621 and process LSA Headers. Otherwise, ignore this message */
622 if (CHECK_FLAG(dbdesc
->bits
, OSPF6_DBDESC_IBIT
)
623 && CHECK_FLAG(dbdesc
->bits
, OSPF6_DBDESC_MBIT
)
624 && CHECK_FLAG(dbdesc
->bits
, OSPF6_DBDESC_MSBIT
)
626 == sizeof(struct ospf6_header
)
627 + sizeof(struct ospf6_dbdesc
)) {
628 /* set the master/slave bit to slave */
629 UNSET_FLAG(on
->dbdesc_bits
, OSPF6_DBDESC_MSBIT
);
631 /* set the DD sequence number to one specified by master
633 on
->dbdesc_seqnum
= ntohl(dbdesc
->seqnum
);
635 /* schedule NegotiationDone */
636 thread_execute(master
, negotiation_done
, on
, 0);
638 /* Record neighbor options */
639 memcpy(on
->options
, dbdesc
->options
,
640 sizeof(on
->options
));
643 "VRF %s: Nbr %s Negotiation failed",
644 vrf_id_to_name(on
->ospf6_if
->interface
->vrf_id
),
650 case OSPF6_NEIGHBOR_EXCHANGE
:
651 if (!memcmp(dbdesc
, &on
->dbdesc_last
,
652 sizeof(struct ospf6_dbdesc
))) {
653 /* Duplicated DatabaseDescription causes slave to
655 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV_HDR
))
657 "Duplicated dbdesc causes retransmit");
658 THREAD_OFF(on
->thread_send_dbdesc
);
659 on
->thread_send_dbdesc
= NULL
;
660 thread_add_event(master
, ospf6_dbdesc_send
, on
, 0,
661 &on
->thread_send_dbdesc
);
665 if (!CHECK_FLAG(dbdesc
->bits
, OSPF6_DBDESC_MSBIT
)) {
667 "DbDesc slave recv: Master/Slave bit mismatch Nbr %s",
669 thread_add_event(master
, seqnumber_mismatch
, on
, 0,
674 if (CHECK_FLAG(dbdesc
->bits
, OSPF6_DBDESC_IBIT
)) {
676 "DbDesc slave recv: Initialize bit mismatch Nbr %s",
678 thread_add_event(master
, seqnumber_mismatch
, on
, 0,
683 if (memcmp(on
->options
, dbdesc
->options
, sizeof(on
->options
))) {
685 "DbDesc slave recv: Option field mismatch Nbr %s",
687 thread_add_event(master
, seqnumber_mismatch
, on
, 0,
692 if (ntohl(dbdesc
->seqnum
) != on
->dbdesc_seqnum
+ 1) {
694 "DbDesc slave recv: Sequence number mismatch Nbr %s (%#lx expected)",
695 on
->name
, (unsigned long)on
->dbdesc_seqnum
+ 1);
696 thread_add_event(master
, seqnumber_mismatch
, on
, 0,
702 case OSPF6_NEIGHBOR_LOADING
:
703 case OSPF6_NEIGHBOR_FULL
:
704 if (!memcmp(dbdesc
, &on
->dbdesc_last
,
705 sizeof(struct ospf6_dbdesc
))) {
706 /* Duplicated DatabaseDescription causes slave to
708 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV_HDR
))
710 "Duplicated dbdesc causes retransmit");
711 THREAD_OFF(on
->thread_send_dbdesc
);
712 thread_add_event(master
, ospf6_dbdesc_send
, on
, 0,
713 &on
->thread_send_dbdesc
);
718 "DbDesc slave recv: Not duplicate dbdesc in state %s Nbr %s",
719 ospf6_neighbor_state_str
[on
->state
], on
->name
);
720 thread_add_event(master
, seqnumber_mismatch
, on
, 0, NULL
);
728 /* Process LSA headers */
729 for (p
= (char *)((caddr_t
)dbdesc
+ sizeof(struct ospf6_dbdesc
));
730 p
+ sizeof(struct ospf6_lsa_header
) <= OSPF6_MESSAGE_END(oh
);
731 p
+= sizeof(struct ospf6_lsa_header
)) {
732 struct ospf6_lsa
*his
, *mine
;
733 struct ospf6_lsdb
*lsdb
= NULL
;
735 his
= ospf6_lsa_create_headeronly((struct ospf6_lsa_header
*)p
);
737 switch (OSPF6_LSA_SCOPE(his
->header
->type
)) {
738 case OSPF6_SCOPE_LINKLOCAL
:
739 lsdb
= on
->ospf6_if
->lsdb
;
741 case OSPF6_SCOPE_AREA
:
742 lsdb
= on
->ospf6_if
->area
->lsdb
;
745 lsdb
= on
->ospf6_if
->area
->ospf6
->lsdb
;
747 case OSPF6_SCOPE_RESERVED
:
748 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
749 zlog_debug("Ignoring LSA of reserved scope");
750 ospf6_lsa_delete(his
);
755 if (OSPF6_LSA_SCOPE(his
->header
->type
) == OSPF6_SCOPE_AS
756 && (IS_AREA_STUB(on
->ospf6_if
->area
)
757 || IS_AREA_NSSA(on
->ospf6_if
->area
))) {
758 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
759 zlog_debug("E-bit mismatch with LSA Headers");
760 ospf6_lsa_delete(his
);
761 thread_add_event(master
, seqnumber_mismatch
, on
, 0,
766 mine
= ospf6_lsdb_lookup(his
->header
->type
, his
->header
->id
,
767 his
->header
->adv_router
, lsdb
);
768 if (mine
== NULL
|| ospf6_lsa_compare(his
, mine
) < 0) {
769 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
770 zlog_debug("Add request-list: %s", his
->name
);
771 ospf6_lsdb_add(ospf6_lsa_copy(his
), on
->request_list
);
773 ospf6_lsa_delete(his
);
776 assert(p
== OSPF6_MESSAGE_END(oh
));
778 /* Set sequence number to Master's */
779 on
->dbdesc_seqnum
= ntohl(dbdesc
->seqnum
);
781 /* schedule send lsreq */
782 if (on
->request_list
->count
)
783 thread_add_event(master
, ospf6_lsreq_send
, on
, 0,
784 &on
->thread_send_lsreq
);
786 THREAD_OFF(on
->thread_send_dbdesc
);
787 thread_add_event(master
, ospf6_dbdesc_send_newone
, on
, 0,
788 &on
->thread_send_dbdesc
);
790 /* save last received dbdesc */
791 memcpy(&on
->dbdesc_last
, dbdesc
, sizeof(struct ospf6_dbdesc
));
794 static void ospf6_dbdesc_recv(struct in6_addr
*src
, struct in6_addr
*dst
,
795 struct ospf6_interface
*oi
,
796 struct ospf6_header
*oh
)
798 struct ospf6_neighbor
*on
;
799 struct ospf6_dbdesc
*dbdesc
;
801 on
= ospf6_neighbor_lookup(oh
->router_id
, oi
);
803 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV_HDR
))
804 zlog_debug("Neighbor not found, ignore");
808 dbdesc
= (struct ospf6_dbdesc
*)((caddr_t
)oh
809 + sizeof(struct ospf6_header
));
811 /* Interface MTU check */
812 if (!oi
->mtu_ignore
&& ntohs(dbdesc
->ifmtu
) != oi
->ifmtu
) {
813 zlog_warn("VRF %s: I/F %s MTU mismatch (my %d rcvd %d)",
814 vrf_id_to_name(oi
->interface
->vrf_id
),
815 oi
->interface
->name
, oi
->ifmtu
, ntohs(dbdesc
->ifmtu
));
819 if (dbdesc
->reserved1
|| dbdesc
->reserved2
) {
820 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV_HDR
))
822 "Non-0 reserved field in %s's DbDesc, correct",
824 dbdesc
->reserved1
= 0;
825 dbdesc
->reserved2
= 0;
830 if (ntohl(oh
->router_id
) < ntohl(oi
->area
->ospf6
->router_id
))
831 ospf6_dbdesc_recv_master(oh
, on
);
832 else if (ntohl(oi
->area
->ospf6
->router_id
) < ntohl(oh
->router_id
))
833 ospf6_dbdesc_recv_slave(oh
, on
);
835 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV_HDR
))
836 zlog_debug("Can't decide which is master, ignore");
840 static void ospf6_lsreq_recv(struct in6_addr
*src
, struct in6_addr
*dst
,
841 struct ospf6_interface
*oi
,
842 struct ospf6_header
*oh
)
844 struct ospf6_neighbor
*on
;
846 struct ospf6_lsreq_entry
*e
;
847 struct ospf6_lsdb
*lsdb
= NULL
;
848 struct ospf6_lsa
*lsa
;
850 on
= ospf6_neighbor_lookup(oh
->router_id
, oi
);
852 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV_HDR
))
853 zlog_debug("Neighbor not found, ignore");
857 if (on
->state
!= OSPF6_NEIGHBOR_EXCHANGE
858 && on
->state
!= OSPF6_NEIGHBOR_LOADING
859 && on
->state
!= OSPF6_NEIGHBOR_FULL
) {
860 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV_HDR
))
861 zlog_debug("Neighbor state less than Exchange, ignore");
867 /* Process each request */
868 for (p
= (char *)((caddr_t
)oh
+ sizeof(struct ospf6_header
));
869 p
+ sizeof(struct ospf6_lsreq_entry
) <= OSPF6_MESSAGE_END(oh
);
870 p
+= sizeof(struct ospf6_lsreq_entry
)) {
871 e
= (struct ospf6_lsreq_entry
*)p
;
873 switch (OSPF6_LSA_SCOPE(e
->type
)) {
874 case OSPF6_SCOPE_LINKLOCAL
:
875 lsdb
= on
->ospf6_if
->lsdb
;
877 case OSPF6_SCOPE_AREA
:
878 lsdb
= on
->ospf6_if
->area
->lsdb
;
881 lsdb
= on
->ospf6_if
->area
->ospf6
->lsdb
;
884 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
885 zlog_debug("Ignoring LSA of reserved scope");
890 /* Find database copy */
891 lsa
= ospf6_lsdb_lookup(e
->type
, e
->id
, e
->adv_router
, lsdb
);
894 "Can't find requested lsa [%s Id:%pI4 Adv:%pI4] send badLSReq",
895 ospf6_lstype_name(e
->type
), &e
->id
,
897 thread_add_event(master
, bad_lsreq
, on
, 0, NULL
);
901 ospf6_lsdb_add(ospf6_lsa_copy(lsa
), on
->lsupdate_list
);
904 assert(p
== OSPF6_MESSAGE_END(oh
));
906 /* schedule send lsupdate */
907 THREAD_OFF(on
->thread_send_lsupdate
);
908 thread_add_event(master
, ospf6_lsupdate_send_neighbor
, on
, 0,
909 &on
->thread_send_lsupdate
);
912 /* Verify, that the specified memory area contains exactly N valid IPv6
913 prefixes as specified by RFC5340, A.4.1. */
914 static unsigned ospf6_prefixes_examin(
915 struct ospf6_prefix
*current
, /* start of buffer */
917 const uint32_t req_num_pfxs
/* always compared with the actual number
921 uint8_t requested_pfx_bytes
;
922 uint32_t real_num_pfxs
= 0;
925 if (length
< OSPF6_PREFIX_MIN_SIZE
) {
926 zlog_warn("%s: undersized IPv6 prefix header",
930 /* safe to look deeper */
931 if (current
->prefix_length
> IPV6_MAX_BITLEN
) {
932 zlog_warn("%s: invalid PrefixLength (%u bits)",
933 __func__
, current
->prefix_length
);
936 /* covers both fixed- and variable-sized fields */
937 requested_pfx_bytes
=
938 OSPF6_PREFIX_MIN_SIZE
939 + OSPF6_PREFIX_SPACE(current
->prefix_length
);
940 if (requested_pfx_bytes
> length
) {
941 zlog_warn("%s: undersized IPv6 prefix", __func__
);
945 length
-= requested_pfx_bytes
;
946 current
= (struct ospf6_prefix
*)((caddr_t
)current
947 + requested_pfx_bytes
);
950 if (real_num_pfxs
!= req_num_pfxs
) {
952 "%s: IPv6 prefix number mismatch (%u required, %u real)",
953 __func__
, req_num_pfxs
, real_num_pfxs
);
959 /* Verify an LSA to have a valid length and dispatch further (where
960 appropriate) to check if the contents, including nested IPv6 prefixes,
961 is properly sized/aligned within the LSA. Note that this function gets
962 LSA type in network byte order, uses in host byte order and passes to
963 ospf6_lstype_name() in network byte order again. */
964 static unsigned ospf6_lsa_examin(struct ospf6_lsa_header
*lsah
,
965 const uint16_t lsalen
,
966 const uint8_t headeronly
)
968 struct ospf6_intra_prefix_lsa
*intra_prefix_lsa
;
969 struct ospf6_as_external_lsa
*as_external_lsa
;
970 struct ospf6_link_lsa
*link_lsa
;
975 /* In case an additional minimum length constraint is defined for
977 LSA type, make sure that this constraint is met. */
978 lsatype
= ntohs(lsah
->type
);
979 ltindex
= lsatype
& OSPF6_LSTYPE_FCODE_MASK
;
980 if (ltindex
< OSPF6_LSTYPE_SIZE
&& ospf6_lsa_minlen
[ltindex
]
981 && lsalen
< ospf6_lsa_minlen
[ltindex
] + OSPF6_LSA_HEADER_SIZE
) {
982 zlog_warn("%s: undersized (%u B) LSA", __func__
, lsalen
);
986 case OSPF6_LSTYPE_ROUTER
:
987 /* RFC5340 A.4.3, LSA header + OSPF6_ROUTER_LSA_MIN_SIZE bytes
989 by N>=0 interface descriptions. */
990 if ((lsalen
- OSPF6_LSA_HEADER_SIZE
- OSPF6_ROUTER_LSA_MIN_SIZE
)
991 % OSPF6_ROUTER_LSDESC_FIX_SIZE
) {
993 "%s: Router LSA interface description alignment error",
998 case OSPF6_LSTYPE_NETWORK
:
999 /* RFC5340 A.4.4, LSA header + OSPF6_NETWORK_LSA_MIN_SIZE bytes
1000 followed by N>=0 attached router descriptions. */
1001 if ((lsalen
- OSPF6_LSA_HEADER_SIZE
1002 - OSPF6_NETWORK_LSA_MIN_SIZE
)
1003 % OSPF6_NETWORK_LSDESC_FIX_SIZE
) {
1005 "%s: Network LSA router description alignment error",
1010 case OSPF6_LSTYPE_INTER_PREFIX
:
1011 /* RFC5340 A.4.5, LSA header + OSPF6_INTER_PREFIX_LSA_MIN_SIZE
1013 followed by 3-4 fields of a single IPv6 prefix. */
1016 return ospf6_prefixes_examin(
1017 (struct ospf6_prefix
1018 *)((caddr_t
)lsah
+ OSPF6_LSA_HEADER_SIZE
1019 + OSPF6_INTER_PREFIX_LSA_MIN_SIZE
),
1020 lsalen
- OSPF6_LSA_HEADER_SIZE
1021 - OSPF6_INTER_PREFIX_LSA_MIN_SIZE
,
1023 case OSPF6_LSTYPE_INTER_ROUTER
:
1024 /* RFC5340 A.4.6, fixed-size LSA. */
1026 > OSPF6_LSA_HEADER_SIZE
+ OSPF6_INTER_ROUTER_LSA_FIX_SIZE
) {
1027 zlog_warn("%s: Inter Router LSA oversized (%u B) LSA",
1032 case OSPF6_LSTYPE_AS_EXTERNAL
: /* RFC5340 A.4.7, same as A.4.8. */
1033 case OSPF6_LSTYPE_TYPE_7
:
1034 /* RFC5340 A.4.8, LSA header + OSPF6_AS_EXTERNAL_LSA_MIN_SIZE
1036 followed by 3-4 fields of IPv6 prefix and 3 conditional LSA
1038 16 bytes of forwarding address, 4 bytes of external route
1040 4 bytes of referenced link state ID. */
1044 (struct ospf6_as_external_lsa
1045 *)((caddr_t
)lsah
+ OSPF6_LSA_HEADER_SIZE
);
1047 OSPF6_LSA_HEADER_SIZE
+ OSPF6_AS_EXTERNAL_LSA_MIN_SIZE
;
1048 /* To find out if the last optional field (Referenced Link State
1050 assumed in this LSA, we need to access fixed fields of the
1052 prefix before ospf6_prefix_examin() confirms its sizing. */
1053 if (exp_length
+ OSPF6_PREFIX_MIN_SIZE
> lsalen
) {
1055 "%s: AS External undersized (%u B) LSA header",
1059 /* forwarding address */
1060 if (CHECK_FLAG(as_external_lsa
->bits_metric
, OSPF6_ASBR_BIT_F
))
1062 /* external route tag */
1063 if (CHECK_FLAG(as_external_lsa
->bits_metric
, OSPF6_ASBR_BIT_T
))
1065 /* referenced link state ID */
1066 if (as_external_lsa
->prefix
.u
._prefix_referenced_lstype
)
1068 /* All the fixed-size fields (mandatory and optional) must fit.
1070 this check does not include any IPv6 prefix fields. */
1071 if (exp_length
> lsalen
) {
1073 "%s: AS External undersized (%u B) LSA header",
1077 /* The last call completely covers the remainder (IPv6 prefix).
1079 return ospf6_prefixes_examin(
1080 (struct ospf6_prefix
1081 *)((caddr_t
)as_external_lsa
1082 + OSPF6_AS_EXTERNAL_LSA_MIN_SIZE
),
1083 lsalen
- exp_length
, 1);
1084 case OSPF6_LSTYPE_LINK
:
1085 /* RFC5340 A.4.9, LSA header + OSPF6_LINK_LSA_MIN_SIZE bytes
1087 by N>=0 IPv6 prefix blocks (with N declared beforehand). */
1090 link_lsa
= (struct ospf6_link_lsa
*)((caddr_t
)lsah
1091 + OSPF6_LSA_HEADER_SIZE
);
1092 return ospf6_prefixes_examin(
1093 (struct ospf6_prefix
*)((caddr_t
)link_lsa
1094 + OSPF6_LINK_LSA_MIN_SIZE
),
1095 lsalen
- OSPF6_LSA_HEADER_SIZE
1096 - OSPF6_LINK_LSA_MIN_SIZE
,
1097 ntohl(link_lsa
->prefix_num
) /* 32 bits */
1099 case OSPF6_LSTYPE_INTRA_PREFIX
:
1100 /* RFC5340 A.4.10, LSA header + OSPF6_INTRA_PREFIX_LSA_MIN_SIZE
1102 followed by N>=0 IPv6 prefixes (with N declared beforehand).
1107 (struct ospf6_intra_prefix_lsa
1108 *)((caddr_t
)lsah
+ OSPF6_LSA_HEADER_SIZE
);
1109 return ospf6_prefixes_examin(
1110 (struct ospf6_prefix
1111 *)((caddr_t
)intra_prefix_lsa
1112 + OSPF6_INTRA_PREFIX_LSA_MIN_SIZE
),
1113 lsalen
- OSPF6_LSA_HEADER_SIZE
1114 - OSPF6_INTRA_PREFIX_LSA_MIN_SIZE
,
1115 ntohs(intra_prefix_lsa
->prefix_num
) /* 16 bits */
1118 /* No additional validation is possible for unknown LSA types, which are
1119 themselves valid in OPSFv3, hence the default decision is to accept.
1124 /* Verify if the provided input buffer is a valid sequence of LSAs. This
1125 includes verification of LSA blocks length/alignment and dispatching
1126 of deeper-level checks. */
1128 ospf6_lsaseq_examin(struct ospf6_lsa_header
*lsah
, /* start of buffered data */
1129 size_t length
, const uint8_t headeronly
,
1130 /* When declared_num_lsas is not 0, compare it to the real
1132 and treat the difference as an error. */
1133 const uint32_t declared_num_lsas
)
1135 uint32_t counted_lsas
= 0;
1139 if (length
< OSPF6_LSA_HEADER_SIZE
) {
1141 "%s: undersized (%zu B) trailing (#%u) LSA header",
1142 __func__
, length
, counted_lsas
);
1145 /* save on ntohs() calls here and in the LSA validator */
1146 lsalen
= OSPF6_LSA_SIZE(lsah
);
1147 if (lsalen
< OSPF6_LSA_HEADER_SIZE
) {
1149 "%s: malformed LSA header #%u, declared length is %u B",
1150 __func__
, counted_lsas
, lsalen
);
1154 /* less checks here and in ospf6_lsa_examin() */
1155 if (MSG_OK
!= ospf6_lsa_examin(lsah
, lsalen
, 1)) {
1157 "%s: anomaly in header-only %s LSA #%u",
1158 __func__
, ospf6_lstype_name(lsah
->type
),
1162 lsah
= (struct ospf6_lsa_header
1164 + OSPF6_LSA_HEADER_SIZE
);
1165 length
-= OSPF6_LSA_HEADER_SIZE
;
1167 /* make sure the input buffer is deep enough before
1169 if (lsalen
> length
) {
1171 "%s: anomaly in %s LSA #%u: declared length is %u B, buffered length is %zu B",
1172 __func__
, ospf6_lstype_name(lsah
->type
),
1173 counted_lsas
, lsalen
, length
);
1176 if (MSG_OK
!= ospf6_lsa_examin(lsah
, lsalen
, 0)) {
1177 zlog_warn("%s: anomaly in %s LSA #%u", __func__
,
1178 ospf6_lstype_name(lsah
->type
),
1182 lsah
= (struct ospf6_lsa_header
*)((caddr_t
)lsah
1189 if (declared_num_lsas
&& counted_lsas
!= declared_num_lsas
) {
1190 zlog_warn("%s: #LSAs declared (%u) does not match actual (%u)",
1191 __func__
, declared_num_lsas
, counted_lsas
);
1197 /* Verify a complete OSPF packet for proper sizing/alignment. */
1198 static unsigned ospf6_packet_examin(struct ospf6_header
*oh
,
1199 const unsigned bytesonwire
)
1201 struct ospf6_lsupdate
*lsupd
;
1204 /* length, 1st approximation */
1205 if (bytesonwire
< OSPF6_HEADER_SIZE
) {
1206 zlog_warn("%s: undersized (%u B) packet", __func__
,
1210 /* Now it is safe to access header fields. */
1211 if (bytesonwire
!= ntohs(oh
->length
)) {
1212 zlog_warn("%s: %s packet length error (%u real, %u declared)",
1214 lookup_msg(ospf6_message_type_str
, oh
->type
, NULL
),
1215 bytesonwire
, ntohs(oh
->length
));
1219 if (oh
->version
!= OSPFV3_VERSION
) {
1220 zlog_warn("%s: invalid (%u) protocol version", __func__
,
1224 /* length, 2nd approximation */
1225 if (oh
->type
< OSPF6_MESSAGE_TYPE_ALL
&& ospf6_packet_minlen
[oh
->type
]
1227 < OSPF6_HEADER_SIZE
+ ospf6_packet_minlen
[oh
->type
]) {
1228 zlog_warn("%s: undersized (%u B) %s packet", __func__
,
1230 lookup_msg(ospf6_message_type_str
, oh
->type
, NULL
));
1233 /* type-specific deeper validation */
1235 case OSPF6_MESSAGE_TYPE_HELLO
:
1236 /* RFC5340 A.3.2, packet header + OSPF6_HELLO_MIN_SIZE bytes
1238 by N>=0 router-IDs. */
1240 == (bytesonwire
- OSPF6_HEADER_SIZE
- OSPF6_HELLO_MIN_SIZE
)
1243 zlog_warn("%s: alignment error in %s packet", __func__
,
1244 lookup_msg(ospf6_message_type_str
, oh
->type
, NULL
));
1246 case OSPF6_MESSAGE_TYPE_DBDESC
:
1247 /* RFC5340 A.3.3, packet header + OSPF6_DB_DESC_MIN_SIZE bytes
1249 by N>=0 header-only LSAs. */
1250 test
= ospf6_lsaseq_examin(
1251 (struct ospf6_lsa_header
*)((caddr_t
)oh
1253 + OSPF6_DB_DESC_MIN_SIZE
),
1254 bytesonwire
- OSPF6_HEADER_SIZE
1255 - OSPF6_DB_DESC_MIN_SIZE
,
1258 case OSPF6_MESSAGE_TYPE_LSREQ
:
1259 /* RFC5340 A.3.4, packet header + N>=0 LS description blocks. */
1261 == (bytesonwire
- OSPF6_HEADER_SIZE
- OSPF6_LS_REQ_MIN_SIZE
)
1262 % OSPF6_LSREQ_LSDESC_FIX_SIZE
)
1264 zlog_warn("%s: alignment error in %s packet", __func__
,
1265 lookup_msg(ospf6_message_type_str
, oh
->type
, NULL
));
1267 case OSPF6_MESSAGE_TYPE_LSUPDATE
:
1268 /* RFC5340 A.3.5, packet header + OSPF6_LS_UPD_MIN_SIZE bytes
1270 by N>=0 full LSAs (with N declared beforehand). */
1271 lsupd
= (struct ospf6_lsupdate
*)((caddr_t
)oh
1272 + OSPF6_HEADER_SIZE
);
1273 test
= ospf6_lsaseq_examin(
1274 (struct ospf6_lsa_header
*)((caddr_t
)lsupd
1275 + OSPF6_LS_UPD_MIN_SIZE
),
1276 bytesonwire
- OSPF6_HEADER_SIZE
- OSPF6_LS_UPD_MIN_SIZE
,
1277 0, ntohl(lsupd
->lsa_number
) /* 32 bits */
1280 case OSPF6_MESSAGE_TYPE_LSACK
:
1281 /* RFC5340 A.3.6, packet header + N>=0 header-only LSAs. */
1282 test
= ospf6_lsaseq_examin(
1283 (struct ospf6_lsa_header
*)((caddr_t
)oh
1285 + OSPF6_LS_ACK_MIN_SIZE
),
1286 bytesonwire
- OSPF6_HEADER_SIZE
- OSPF6_LS_ACK_MIN_SIZE
,
1290 zlog_warn("%s: invalid (%u) message type", __func__
, oh
->type
);
1294 zlog_warn("%s: anomaly in %s packet", __func__
,
1295 lookup_msg(ospf6_message_type_str
, oh
->type
, NULL
));
1299 /* Verify particular fields of otherwise correct received OSPF packet to
1300 meet the requirements of RFC. */
1301 static int ospf6_rxpacket_examin(struct ospf6_interface
*oi
,
1302 struct ospf6_header
*oh
,
1303 const unsigned bytesonwire
)
1306 if (MSG_OK
!= ospf6_packet_examin(oh
, bytesonwire
))
1310 if (oh
->area_id
!= oi
->area
->area_id
) {
1311 if (oh
->area_id
== OSPF_AREA_BACKBONE
)
1313 "VRF %s: I/F %s Message may be via Virtual Link: not supported",
1314 vrf_id_to_name(oi
->interface
->vrf_id
),
1315 oi
->interface
->name
);
1318 "VRF %s: I/F %s Area-ID mismatch (my %pI4, rcvd %pI4)",
1319 vrf_id_to_name(oi
->interface
->vrf_id
),
1320 oi
->interface
->name
, &oi
->area
->area_id
,
1325 /* Instance-ID check */
1326 if (oh
->instance_id
!= oi
->instance_id
) {
1328 "VRF %s: I/F %s Instance-ID mismatch (my %u, rcvd %u)",
1329 vrf_id_to_name(oi
->interface
->vrf_id
),
1330 oi
->interface
->name
, oi
->instance_id
, oh
->instance_id
);
1334 /* Router-ID check */
1335 if (oh
->router_id
== oi
->area
->ospf6
->router_id
) {
1336 zlog_warn("VRF %s: I/F %s Duplicate Router-ID (%pI4)",
1337 vrf_id_to_name(oi
->interface
->vrf_id
),
1338 oi
->interface
->name
, &oh
->router_id
);
1344 static void ospf6_lsupdate_recv(struct in6_addr
*src
, struct in6_addr
*dst
,
1345 struct ospf6_interface
*oi
,
1346 struct ospf6_header
*oh
)
1348 struct ospf6_neighbor
*on
;
1349 struct ospf6_lsupdate
*lsupdate
;
1352 on
= ospf6_neighbor_lookup(oh
->router_id
, oi
);
1354 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV_HDR
))
1355 zlog_debug("Neighbor not found, ignore");
1359 if (on
->state
!= OSPF6_NEIGHBOR_EXCHANGE
1360 && on
->state
!= OSPF6_NEIGHBOR_LOADING
1361 && on
->state
!= OSPF6_NEIGHBOR_FULL
) {
1362 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV_HDR
))
1363 zlog_debug("Neighbor state less than Exchange, ignore");
1367 lsupdate
= (struct ospf6_lsupdate
*)((caddr_t
)oh
1368 + sizeof(struct ospf6_header
));
1373 for (p
= (char *)((caddr_t
)lsupdate
+ sizeof(struct ospf6_lsupdate
));
1374 p
< OSPF6_MESSAGE_END(oh
)
1375 && p
+ OSPF6_LSA_SIZE(p
) <= OSPF6_MESSAGE_END(oh
);
1376 p
+= OSPF6_LSA_SIZE(p
)) {
1377 ospf6_receive_lsa(on
, (struct ospf6_lsa_header
*)p
);
1380 assert(p
== OSPF6_MESSAGE_END(oh
));
1383 static void ospf6_lsack_recv(struct in6_addr
*src
, struct in6_addr
*dst
,
1384 struct ospf6_interface
*oi
,
1385 struct ospf6_header
*oh
)
1387 struct ospf6_neighbor
*on
;
1389 struct ospf6_lsa
*his
, *mine
;
1390 struct ospf6_lsdb
*lsdb
= NULL
;
1392 assert(oh
->type
== OSPF6_MESSAGE_TYPE_LSACK
);
1394 on
= ospf6_neighbor_lookup(oh
->router_id
, oi
);
1396 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV_HDR
))
1397 zlog_debug("Neighbor not found, ignore");
1401 if (on
->state
!= OSPF6_NEIGHBOR_EXCHANGE
1402 && on
->state
!= OSPF6_NEIGHBOR_LOADING
1403 && on
->state
!= OSPF6_NEIGHBOR_FULL
) {
1404 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV_HDR
))
1405 zlog_debug("Neighbor state less than Exchange, ignore");
1411 for (p
= (char *)((caddr_t
)oh
+ sizeof(struct ospf6_header
));
1412 p
+ sizeof(struct ospf6_lsa_header
) <= OSPF6_MESSAGE_END(oh
);
1413 p
+= sizeof(struct ospf6_lsa_header
)) {
1414 his
= ospf6_lsa_create_headeronly((struct ospf6_lsa_header
*)p
);
1416 switch (OSPF6_LSA_SCOPE(his
->header
->type
)) {
1417 case OSPF6_SCOPE_LINKLOCAL
:
1418 lsdb
= on
->ospf6_if
->lsdb
;
1420 case OSPF6_SCOPE_AREA
:
1421 lsdb
= on
->ospf6_if
->area
->lsdb
;
1423 case OSPF6_SCOPE_AS
:
1424 lsdb
= on
->ospf6_if
->area
->ospf6
->lsdb
;
1426 case OSPF6_SCOPE_RESERVED
:
1427 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
1428 zlog_debug("Ignoring LSA of reserved scope");
1429 ospf6_lsa_delete(his
);
1434 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
1435 zlog_debug("%s acknowledged by %s", his
->name
,
1438 /* Find database copy */
1439 mine
= ospf6_lsdb_lookup(his
->header
->type
, his
->header
->id
,
1440 his
->header
->adv_router
, lsdb
);
1442 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
1443 zlog_debug("No database copy");
1444 ospf6_lsa_delete(his
);
1448 /* Check if the LSA is on his retrans-list */
1449 mine
= ospf6_lsdb_lookup(his
->header
->type
, his
->header
->id
,
1450 his
->header
->adv_router
,
1453 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
1454 zlog_debug("Not on %s's retrans-list",
1456 ospf6_lsa_delete(his
);
1460 if (ospf6_lsa_compare(his
, mine
) != 0) {
1461 /* Log this questionable acknowledgement,
1462 and examine the next one. */
1463 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
1464 zlog_debug("Questionable acknowledgement");
1465 ospf6_lsa_delete(his
);
1469 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
1471 "Acknowledged, remove from %s's retrans-list",
1474 ospf6_decrement_retrans_count(mine
);
1475 if (OSPF6_LSA_IS_MAXAGE(mine
))
1476 ospf6_maxage_remove(on
->ospf6_if
->area
->ospf6
);
1477 ospf6_lsdb_remove(mine
, on
->retrans_list
);
1478 ospf6_lsa_delete(his
);
1481 assert(p
== OSPF6_MESSAGE_END(oh
));
1484 static uint8_t *recvbuf
= NULL
;
1485 static uint8_t *sendbuf
= NULL
;
1486 static unsigned int iobuflen
= 0;
1488 int ospf6_iobuf_size(unsigned int size
)
1490 uint8_t *recvnew
, *sendnew
;
1492 if (size
<= iobuflen
)
1495 recvnew
= XMALLOC(MTYPE_OSPF6_MESSAGE
, size
);
1496 sendnew
= XMALLOC(MTYPE_OSPF6_MESSAGE
, size
);
1498 XFREE(MTYPE_OSPF6_MESSAGE
, recvbuf
);
1499 XFREE(MTYPE_OSPF6_MESSAGE
, sendbuf
);
1507 void ospf6_message_terminate(void)
1509 XFREE(MTYPE_OSPF6_MESSAGE
, recvbuf
);
1510 XFREE(MTYPE_OSPF6_MESSAGE
, sendbuf
);
1515 int ospf6_receive(struct thread
*thread
)
1519 struct in6_addr src
, dst
;
1521 struct iovec iovector
[2];
1522 struct ospf6_interface
*oi
;
1523 struct ospf6_header
*oh
;
1524 struct ospf6
*ospf6
;
1526 /* add next read thread */
1527 ospf6
= THREAD_ARG(thread
);
1528 sockfd
= THREAD_FD(thread
);
1530 thread_add_read(master
, ospf6_receive
, ospf6
, ospf6
->fd
,
1531 &ospf6
->t_ospf6_receive
);
1534 memset(&src
, 0, sizeof(src
));
1535 memset(&dst
, 0, sizeof(dst
));
1537 memset(recvbuf
, 0, iobuflen
);
1538 iovector
[0].iov_base
= recvbuf
;
1539 iovector
[0].iov_len
= iobuflen
;
1540 iovector
[1].iov_base
= NULL
;
1541 iovector
[1].iov_len
= 0;
1543 /* receive message */
1544 len
= ospf6_recvmsg(&src
, &dst
, &ifindex
, iovector
, sockfd
);
1545 if (len
> iobuflen
) {
1546 flog_err(EC_LIB_DEVELOPMENT
, "Excess message read");
1550 oi
= ospf6_interface_lookup_by_ifindex(ifindex
, ospf6
->vrf_id
);
1551 if (oi
== NULL
|| oi
->area
== NULL
1552 || CHECK_FLAG(oi
->flag
, OSPF6_INTERFACE_DISABLE
)) {
1553 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN
,
1555 zlog_debug("Message received on disabled interface");
1558 if (CHECK_FLAG(oi
->flag
, OSPF6_INTERFACE_PASSIVE
)) {
1559 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN
,
1561 zlog_debug("%s: Ignore message on passive interface %s",
1562 __func__
, oi
->interface
->name
);
1566 oh
= (struct ospf6_header
*)recvbuf
;
1567 if (ospf6_rxpacket_examin(oi
, oh
, len
) != MSG_OK
)
1570 /* Being here means, that no sizing/alignment issues were detected in
1571 the input packet. This renders the additional checks performed below
1572 and also in the type-specific dispatching functions a dead code,
1573 which can be dismissed in a cleanup-focused review round later. */
1576 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV_HDR
)) {
1577 zlog_debug("%s received on %s",
1578 lookup_msg(ospf6_message_type_str
, oh
->type
, NULL
),
1579 oi
->interface
->name
);
1580 zlog_debug(" src: %pI6", &src
);
1581 zlog_debug(" dst: %pI6", &dst
);
1584 case OSPF6_MESSAGE_TYPE_HELLO
:
1585 ospf6_hello_print(oh
, OSPF6_ACTION_RECV
);
1587 case OSPF6_MESSAGE_TYPE_DBDESC
:
1588 ospf6_dbdesc_print(oh
, OSPF6_ACTION_RECV
);
1590 case OSPF6_MESSAGE_TYPE_LSREQ
:
1591 ospf6_lsreq_print(oh
, OSPF6_ACTION_RECV
);
1593 case OSPF6_MESSAGE_TYPE_LSUPDATE
:
1594 ospf6_lsupdate_print(oh
, OSPF6_ACTION_RECV
);
1596 case OSPF6_MESSAGE_TYPE_LSACK
:
1597 ospf6_lsack_print(oh
, OSPF6_ACTION_RECV
);
1605 case OSPF6_MESSAGE_TYPE_HELLO
:
1606 ospf6_hello_recv(&src
, &dst
, oi
, oh
);
1609 case OSPF6_MESSAGE_TYPE_DBDESC
:
1610 ospf6_dbdesc_recv(&src
, &dst
, oi
, oh
);
1613 case OSPF6_MESSAGE_TYPE_LSREQ
:
1614 ospf6_lsreq_recv(&src
, &dst
, oi
, oh
);
1617 case OSPF6_MESSAGE_TYPE_LSUPDATE
:
1618 ospf6_lsupdate_recv(&src
, &dst
, oi
, oh
);
1621 case OSPF6_MESSAGE_TYPE_LSACK
:
1622 ospf6_lsack_recv(&src
, &dst
, oi
, oh
);
1632 static void ospf6_send(struct in6_addr
*src
, struct in6_addr
*dst
,
1633 struct ospf6_interface
*oi
, struct ospf6_header
*oh
)
1637 struct iovec iovector
[2];
1640 iovector
[0].iov_base
= (caddr_t
)oh
;
1641 iovector
[0].iov_len
= ntohs(oh
->length
);
1642 iovector
[1].iov_base
= NULL
;
1643 iovector
[1].iov_len
= 0;
1645 /* fill OSPF header */
1646 oh
->version
= OSPFV3_VERSION
;
1647 /* message type must be set before */
1648 /* message length must be set before */
1649 oh
->router_id
= oi
->area
->ospf6
->router_id
;
1650 oh
->area_id
= oi
->area
->area_id
;
1651 /* checksum is calculated by kernel */
1652 oh
->instance_id
= oi
->instance_id
;
1656 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, SEND_HDR
)) {
1658 inet_ntop(AF_INET6
, src
, srcname
, sizeof(srcname
));
1660 memset(srcname
, 0, sizeof(srcname
));
1661 zlog_debug("%s send on %s",
1662 lookup_msg(ospf6_message_type_str
, oh
->type
, NULL
),
1663 oi
->interface
->name
);
1664 zlog_debug(" src: %s", srcname
);
1665 zlog_debug(" dst: %pI6", dst
);
1668 case OSPF6_MESSAGE_TYPE_HELLO
:
1669 ospf6_hello_print(oh
, OSPF6_ACTION_RECV
);
1671 case OSPF6_MESSAGE_TYPE_DBDESC
:
1672 ospf6_dbdesc_print(oh
, OSPF6_ACTION_RECV
);
1674 case OSPF6_MESSAGE_TYPE_LSREQ
:
1675 ospf6_lsreq_print(oh
, OSPF6_ACTION_RECV
);
1677 case OSPF6_MESSAGE_TYPE_LSUPDATE
:
1678 ospf6_lsupdate_print(oh
, OSPF6_ACTION_RECV
);
1680 case OSPF6_MESSAGE_TYPE_LSACK
:
1681 ospf6_lsack_print(oh
, OSPF6_ACTION_RECV
);
1684 zlog_debug("Unknown message");
1691 if (oi
->area
->ospf6
->fd
!= -1) {
1692 len
= ospf6_sendmsg(src
, dst
, oi
->interface
->ifindex
, iovector
,
1693 oi
->area
->ospf6
->fd
);
1694 if (len
!= ntohs(oh
->length
))
1695 flog_err(EC_LIB_DEVELOPMENT
,
1696 "Could not send entire message");
1700 static uint32_t ospf6_packet_max(struct ospf6_interface
*oi
)
1702 assert(oi
->ifmtu
> sizeof(struct ip6_hdr
));
1703 return oi
->ifmtu
- (sizeof(struct ip6_hdr
));
1706 int ospf6_hello_send(struct thread
*thread
)
1708 struct ospf6_interface
*oi
;
1709 struct ospf6_header
*oh
;
1710 struct ospf6_hello
*hello
;
1712 struct listnode
*node
, *nnode
;
1713 struct ospf6_neighbor
*on
;
1715 oi
= (struct ospf6_interface
*)THREAD_ARG(thread
);
1716 oi
->thread_send_hello
= (struct thread
*)NULL
;
1718 if (oi
->state
<= OSPF6_INTERFACE_DOWN
) {
1719 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_HELLO
, SEND_HDR
))
1720 zlog_debug("Unable to send Hello on down interface %s",
1721 oi
->interface
->name
);
1725 if (iobuflen
== 0) {
1726 zlog_debug("Unable to send Hello on interface %s iobuflen is 0",
1727 oi
->interface
->name
);
1731 /* set next thread */
1732 thread_add_timer(master
, ospf6_hello_send
, oi
, oi
->hello_interval
,
1733 &oi
->thread_send_hello
);
1735 memset(sendbuf
, 0, iobuflen
);
1736 oh
= (struct ospf6_header
*)sendbuf
;
1737 hello
= (struct ospf6_hello
*)((caddr_t
)oh
1738 + sizeof(struct ospf6_header
));
1740 hello
->interface_id
= htonl(oi
->interface
->ifindex
);
1741 hello
->priority
= oi
->priority
;
1742 hello
->options
[0] = oi
->area
->options
[0];
1743 hello
->options
[1] = oi
->area
->options
[1];
1744 hello
->options
[2] = oi
->area
->options
[2];
1745 hello
->hello_interval
= htons(oi
->hello_interval
);
1746 hello
->dead_interval
= htons(oi
->dead_interval
);
1747 hello
->drouter
= oi
->drouter
;
1748 hello
->bdrouter
= oi
->bdrouter
;
1750 p
= (uint8_t *)((caddr_t
)hello
+ sizeof(struct ospf6_hello
));
1752 for (ALL_LIST_ELEMENTS(oi
->neighbor_list
, node
, nnode
, on
)) {
1753 if (on
->state
< OSPF6_NEIGHBOR_INIT
)
1756 if (p
- sendbuf
+ sizeof(uint32_t) > ospf6_packet_max(oi
)) {
1757 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_HELLO
,
1760 "sending Hello message: exceeds I/F MTU");
1764 memcpy(p
, &on
->router_id
, sizeof(uint32_t));
1765 p
+= sizeof(uint32_t);
1768 oh
->type
= OSPF6_MESSAGE_TYPE_HELLO
;
1769 oh
->length
= htons(p
- sendbuf
);
1773 ospf6_send(oi
->linklocal_addr
, &allspfrouters6
, oi
, oh
);
1777 int ospf6_dbdesc_send(struct thread
*thread
)
1779 struct ospf6_neighbor
*on
;
1780 struct ospf6_header
*oh
;
1781 struct ospf6_dbdesc
*dbdesc
;
1783 struct ospf6_lsa
*lsa
, *lsanext
;
1784 struct in6_addr
*dst
;
1786 on
= (struct ospf6_neighbor
*)THREAD_ARG(thread
);
1787 on
->thread_send_dbdesc
= (struct thread
*)NULL
;
1789 if (on
->state
< OSPF6_NEIGHBOR_EXSTART
) {
1790 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_DBDESC
, SEND_HDR
))
1792 "Quit to send DbDesc to neighbor %s state %s",
1793 on
->name
, ospf6_neighbor_state_str
[on
->state
]);
1797 /* set next thread if master */
1798 if (CHECK_FLAG(on
->dbdesc_bits
, OSPF6_DBDESC_MSBIT
))
1799 thread_add_timer(master
, ospf6_dbdesc_send
, on
,
1800 on
->ospf6_if
->rxmt_interval
,
1801 &on
->thread_send_dbdesc
);
1803 memset(sendbuf
, 0, iobuflen
);
1804 oh
= (struct ospf6_header
*)sendbuf
;
1805 dbdesc
= (struct ospf6_dbdesc
*)((caddr_t
)oh
1806 + sizeof(struct ospf6_header
));
1808 /* if this is initial one, initialize sequence number for DbDesc */
1809 if (CHECK_FLAG(on
->dbdesc_bits
, OSPF6_DBDESC_IBIT
)
1810 && (on
->dbdesc_seqnum
== 0)) {
1811 on
->dbdesc_seqnum
= monotime(NULL
);
1814 dbdesc
->options
[0] = on
->ospf6_if
->area
->options
[0];
1815 dbdesc
->options
[1] = on
->ospf6_if
->area
->options
[1];
1816 dbdesc
->options
[2] = on
->ospf6_if
->area
->options
[2];
1817 dbdesc
->ifmtu
= htons(on
->ospf6_if
->ifmtu
);
1818 dbdesc
->bits
= on
->dbdesc_bits
;
1819 dbdesc
->seqnum
= htonl(on
->dbdesc_seqnum
);
1821 /* if this is not initial one, set LSA headers in dbdesc */
1822 p
= (uint8_t *)((caddr_t
)dbdesc
+ sizeof(struct ospf6_dbdesc
));
1823 if (!CHECK_FLAG(on
->dbdesc_bits
, OSPF6_DBDESC_IBIT
)) {
1824 for (ALL_LSDB(on
->dbdesc_list
, lsa
, lsanext
)) {
1825 ospf6_lsa_age_update_to_send(lsa
,
1826 on
->ospf6_if
->transdelay
);
1829 if (p
- sendbuf
+ sizeof(struct ospf6_lsa_header
)
1830 > ospf6_packet_max(on
->ospf6_if
)) {
1831 ospf6_lsa_unlock(lsa
);
1833 ospf6_lsa_unlock(lsanext
);
1836 memcpy(p
, lsa
->header
, sizeof(struct ospf6_lsa_header
));
1837 p
+= sizeof(struct ospf6_lsa_header
);
1841 oh
->type
= OSPF6_MESSAGE_TYPE_DBDESC
;
1842 oh
->length
= htons(p
- sendbuf
);
1845 if (on
->ospf6_if
->state
== OSPF6_INTERFACE_POINTTOPOINT
)
1846 dst
= &allspfrouters6
;
1848 dst
= &on
->linklocal_addr
;
1850 on
->ospf6_if
->db_desc_out
++;
1852 ospf6_send(on
->ospf6_if
->linklocal_addr
, dst
, on
->ospf6_if
, oh
);
1857 int ospf6_dbdesc_send_newone(struct thread
*thread
)
1859 struct ospf6_neighbor
*on
;
1860 struct ospf6_lsa
*lsa
, *lsanext
;
1861 unsigned int size
= 0;
1863 on
= (struct ospf6_neighbor
*)THREAD_ARG(thread
);
1864 ospf6_lsdb_remove_all(on
->dbdesc_list
);
1866 /* move LSAs from summary_list to dbdesc_list (within neighbor
1868 so that ospf6_send_dbdesc () can send those LSAs */
1869 size
= sizeof(struct ospf6_lsa_header
) + sizeof(struct ospf6_dbdesc
);
1870 for (ALL_LSDB(on
->summary_list
, lsa
, lsanext
)) {
1871 /* if stub area then don't advertise AS-External LSAs */
1872 if ((IS_AREA_STUB(on
->ospf6_if
->area
)
1873 || IS_AREA_NSSA(on
->ospf6_if
->area
))
1874 && ntohs(lsa
->header
->type
) == OSPF6_LSTYPE_AS_EXTERNAL
) {
1875 ospf6_lsdb_remove(lsa
, on
->summary_list
);
1879 if (size
+ sizeof(struct ospf6_lsa_header
)
1880 > ospf6_packet_max(on
->ospf6_if
)) {
1881 ospf6_lsa_unlock(lsa
);
1883 ospf6_lsa_unlock(lsanext
);
1887 ospf6_lsdb_add(ospf6_lsa_copy(lsa
), on
->dbdesc_list
);
1888 ospf6_lsdb_remove(lsa
, on
->summary_list
);
1889 size
+= sizeof(struct ospf6_lsa_header
);
1892 if (on
->summary_list
->count
== 0)
1893 UNSET_FLAG(on
->dbdesc_bits
, OSPF6_DBDESC_MBIT
);
1895 /* If slave, More bit check must be done here */
1896 if (!CHECK_FLAG(on
->dbdesc_bits
, OSPF6_DBDESC_MSBIT
) && /* Slave */
1897 !CHECK_FLAG(on
->dbdesc_last
.bits
, OSPF6_DBDESC_MBIT
)
1898 && !CHECK_FLAG(on
->dbdesc_bits
, OSPF6_DBDESC_MBIT
))
1899 thread_add_event(master
, exchange_done
, on
, 0, NULL
);
1901 thread_execute(master
, ospf6_dbdesc_send
, on
, 0);
1905 int ospf6_lsreq_send(struct thread
*thread
)
1907 struct ospf6_neighbor
*on
;
1908 struct ospf6_header
*oh
;
1909 struct ospf6_lsreq_entry
*e
;
1911 struct ospf6_lsa
*lsa
, *lsanext
, *last_req
;
1913 on
= (struct ospf6_neighbor
*)THREAD_ARG(thread
);
1914 on
->thread_send_lsreq
= (struct thread
*)NULL
;
1916 /* LSReq will be sent only in ExStart or Loading */
1917 if (on
->state
!= OSPF6_NEIGHBOR_EXCHANGE
1918 && on
->state
!= OSPF6_NEIGHBOR_LOADING
) {
1919 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_LSREQ
, SEND_HDR
))
1920 zlog_debug("Quit to send LSReq to neighbor %s state %s",
1922 ospf6_neighbor_state_str
[on
->state
]);
1926 /* schedule loading_done if request list is empty */
1927 if (on
->request_list
->count
== 0) {
1928 thread_add_event(master
, loading_done
, on
, 0, NULL
);
1932 memset(sendbuf
, 0, iobuflen
);
1933 oh
= (struct ospf6_header
*)sendbuf
;
1936 /* set Request entries in lsreq */
1937 p
= (uint8_t *)((caddr_t
)oh
+ sizeof(struct ospf6_header
));
1938 for (ALL_LSDB(on
->request_list
, lsa
, lsanext
)) {
1940 if (p
- sendbuf
+ sizeof(struct ospf6_lsreq_entry
)
1941 > ospf6_packet_max(on
->ospf6_if
)) {
1942 ospf6_lsa_unlock(lsa
);
1944 ospf6_lsa_unlock(lsanext
);
1948 e
= (struct ospf6_lsreq_entry
*)p
;
1949 e
->type
= lsa
->header
->type
;
1950 e
->id
= lsa
->header
->id
;
1951 e
->adv_router
= lsa
->header
->adv_router
;
1952 p
+= sizeof(struct ospf6_lsreq_entry
);
1956 if (last_req
!= NULL
) {
1957 if (on
->last_ls_req
!= NULL
)
1958 on
->last_ls_req
= ospf6_lsa_unlock(on
->last_ls_req
);
1960 ospf6_lsa_lock(last_req
);
1961 on
->last_ls_req
= last_req
;
1964 oh
->type
= OSPF6_MESSAGE_TYPE_LSREQ
;
1965 oh
->length
= htons(p
- sendbuf
);
1967 on
->ospf6_if
->ls_req_out
++;
1969 if (on
->ospf6_if
->state
== OSPF6_INTERFACE_POINTTOPOINT
)
1970 ospf6_send(on
->ospf6_if
->linklocal_addr
, &allspfrouters6
,
1973 ospf6_send(on
->ospf6_if
->linklocal_addr
, &on
->linklocal_addr
,
1976 /* set next thread */
1977 if (on
->request_list
->count
!= 0) {
1978 on
->thread_send_lsreq
= NULL
;
1979 thread_add_timer(master
, ospf6_lsreq_send
, on
,
1980 on
->ospf6_if
->rxmt_interval
,
1981 &on
->thread_send_lsreq
);
1987 static void ospf6_send_lsupdate(struct ospf6_neighbor
*on
,
1988 struct ospf6_interface
*oi
,
1989 struct ospf6_header
*oh
)
1993 on
->ospf6_if
->ls_upd_out
++;
1995 if ((on
->ospf6_if
->state
== OSPF6_INTERFACE_POINTTOPOINT
)
1996 || (on
->ospf6_if
->state
== OSPF6_INTERFACE_DR
)
1997 || (on
->ospf6_if
->state
== OSPF6_INTERFACE_BDR
)) {
1998 ospf6_send(on
->ospf6_if
->linklocal_addr
,
1999 &allspfrouters6
, on
->ospf6_if
, oh
);
2001 ospf6_send(on
->ospf6_if
->linklocal_addr
,
2002 &on
->linklocal_addr
, on
->ospf6_if
, oh
);
2008 if ((oi
->state
== OSPF6_INTERFACE_POINTTOPOINT
)
2009 || (oi
->state
== OSPF6_INTERFACE_DR
)
2010 || (oi
->state
== OSPF6_INTERFACE_BDR
)) {
2011 ospf6_send(oi
->linklocal_addr
, &allspfrouters6
, oi
, oh
);
2013 ospf6_send(oi
->linklocal_addr
, &alldrouters6
, oi
, oh
);
2018 int ospf6_lsupdate_send_neighbor(struct thread
*thread
)
2020 struct ospf6_neighbor
*on
;
2021 struct ospf6_header
*oh
;
2022 struct ospf6_lsupdate
*lsupdate
;
2025 struct ospf6_lsa
*lsa
, *lsanext
;
2027 on
= (struct ospf6_neighbor
*)THREAD_ARG(thread
);
2028 on
->thread_send_lsupdate
= (struct thread
*)NULL
;
2030 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_LSUPDATE
, SEND_HDR
))
2031 zlog_debug("LSUpdate to neighbor %s", on
->name
);
2033 if (on
->state
< OSPF6_NEIGHBOR_EXCHANGE
) {
2034 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_LSUPDATE
,
2036 zlog_debug("Quit to send (neighbor state %s)",
2037 ospf6_neighbor_state_str
[on
->state
]);
2041 memset(sendbuf
, 0, iobuflen
);
2042 oh
= (struct ospf6_header
*)sendbuf
;
2043 lsupdate
= (struct ospf6_lsupdate
*)((caddr_t
)oh
2044 + sizeof(struct ospf6_header
));
2046 p
= (uint8_t *)((caddr_t
)lsupdate
+ sizeof(struct ospf6_lsupdate
));
2049 /* lsupdate_list lists those LSA which doesn't need to be
2050 retransmitted. remove those from the list */
2051 for (ALL_LSDB(on
->lsupdate_list
, lsa
, lsanext
)) {
2053 if ((p
- sendbuf
+ (unsigned int)OSPF6_LSA_SIZE(lsa
->header
))
2054 > ospf6_packet_max(on
->ospf6_if
)) {
2056 oh
->type
= OSPF6_MESSAGE_TYPE_LSUPDATE
;
2057 oh
->length
= htons(p
- sendbuf
);
2058 lsupdate
->lsa_number
= htonl(lsa_cnt
);
2060 ospf6_send_lsupdate(on
, NULL
, oh
);
2062 memset(sendbuf
, 0, iobuflen
);
2063 oh
= (struct ospf6_header
*)sendbuf
;
2064 lsupdate
= (struct ospf6_lsupdate
2069 p
= (uint8_t *)((caddr_t
)lsupdate
2076 ospf6_lsa_age_update_to_send(lsa
, on
->ospf6_if
->transdelay
);
2077 memcpy(p
, lsa
->header
, OSPF6_LSA_SIZE(lsa
->header
));
2078 p
+= OSPF6_LSA_SIZE(lsa
->header
);
2081 assert(lsa
->lock
== 2);
2082 ospf6_lsdb_remove(lsa
, on
->lsupdate_list
);
2086 oh
->type
= OSPF6_MESSAGE_TYPE_LSUPDATE
;
2087 oh
->length
= htons(p
- sendbuf
);
2088 lsupdate
->lsa_number
= htonl(lsa_cnt
);
2089 ospf6_send_lsupdate(on
, NULL
, oh
);
2092 /* The addresses used for retransmissions are different from those sent
2094 first time and so we need to separate them here.
2096 memset(sendbuf
, 0, iobuflen
);
2097 oh
= (struct ospf6_header
*)sendbuf
;
2098 lsupdate
= (struct ospf6_lsupdate
*)((caddr_t
)oh
2099 + sizeof(struct ospf6_header
));
2100 p
= (uint8_t *)((caddr_t
)lsupdate
+ sizeof(struct ospf6_lsupdate
));
2103 for (ALL_LSDB(on
->retrans_list
, lsa
, lsanext
)) {
2105 if ((p
- sendbuf
+ (unsigned int)OSPF6_LSA_SIZE(lsa
->header
))
2106 > ospf6_packet_max(on
->ospf6_if
)) {
2108 oh
->type
= OSPF6_MESSAGE_TYPE_LSUPDATE
;
2109 oh
->length
= htons(p
- sendbuf
);
2110 lsupdate
->lsa_number
= htonl(lsa_cnt
);
2112 if (on
->ospf6_if
->state
2113 == OSPF6_INTERFACE_POINTTOPOINT
) {
2114 ospf6_send(on
->ospf6_if
->linklocal_addr
,
2118 ospf6_send(on
->ospf6_if
->linklocal_addr
,
2119 &on
->linklocal_addr
,
2123 memset(sendbuf
, 0, iobuflen
);
2124 oh
= (struct ospf6_header
*)sendbuf
;
2125 lsupdate
= (struct ospf6_lsupdate
2129 p
= (uint8_t *)((caddr_t
)lsupdate
2136 ospf6_lsa_age_update_to_send(lsa
, on
->ospf6_if
->transdelay
);
2137 memcpy(p
, lsa
->header
, OSPF6_LSA_SIZE(lsa
->header
));
2138 p
+= OSPF6_LSA_SIZE(lsa
->header
);
2143 oh
->type
= OSPF6_MESSAGE_TYPE_LSUPDATE
;
2144 oh
->length
= htons(p
- sendbuf
);
2145 lsupdate
->lsa_number
= htonl(lsa_cnt
);
2147 if (on
->ospf6_if
->state
== OSPF6_INTERFACE_POINTTOPOINT
)
2148 ospf6_send(on
->ospf6_if
->linklocal_addr
,
2149 &allspfrouters6
, on
->ospf6_if
, oh
);
2151 ospf6_send(on
->ospf6_if
->linklocal_addr
,
2152 &on
->linklocal_addr
, on
->ospf6_if
, oh
);
2155 if (on
->lsupdate_list
->count
!= 0) {
2156 on
->thread_send_lsupdate
= NULL
;
2157 thread_add_event(master
, ospf6_lsupdate_send_neighbor
, on
, 0,
2158 &on
->thread_send_lsupdate
);
2159 } else if (on
->retrans_list
->count
!= 0) {
2160 on
->thread_send_lsupdate
= NULL
;
2161 thread_add_timer(master
, ospf6_lsupdate_send_neighbor
, on
,
2162 on
->ospf6_if
->rxmt_interval
,
2163 &on
->thread_send_lsupdate
);
2168 int ospf6_lsupdate_send_neighbor_now(struct ospf6_neighbor
*on
,
2169 struct ospf6_lsa
*lsa
)
2171 struct ospf6_header
*oh
;
2172 struct ospf6_lsupdate
*lsupdate
;
2176 memset(sendbuf
, 0, iobuflen
);
2177 oh
= (struct ospf6_header
*)sendbuf
;
2178 lsupdate
= (struct ospf6_lsupdate
*)((caddr_t
)oh
2179 + sizeof(struct ospf6_header
));
2181 p
= (uint8_t *)((caddr_t
)lsupdate
+ sizeof(struct ospf6_lsupdate
));
2182 ospf6_lsa_age_update_to_send(lsa
, on
->ospf6_if
->transdelay
);
2183 memcpy(p
, lsa
->header
, OSPF6_LSA_SIZE(lsa
->header
));
2184 p
+= OSPF6_LSA_SIZE(lsa
->header
);
2187 oh
->type
= OSPF6_MESSAGE_TYPE_LSUPDATE
;
2188 oh
->length
= htons(p
- sendbuf
);
2189 lsupdate
->lsa_number
= htonl(lsa_cnt
);
2191 if (IS_OSPF6_DEBUG_FLOODING
2192 || IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_LSUPDATE
, SEND_HDR
))
2193 zlog_debug("%s: Send lsupdate with lsa %s (age %u)", __func__
,
2194 lsa
->name
, ntohs(lsa
->header
->age
));
2196 ospf6_send_lsupdate(on
, NULL
, oh
);
2201 int ospf6_lsupdate_send_interface(struct thread
*thread
)
2203 struct ospf6_interface
*oi
;
2204 struct ospf6_header
*oh
;
2205 struct ospf6_lsupdate
*lsupdate
;
2208 struct ospf6_lsa
*lsa
, *lsanext
;
2210 oi
= (struct ospf6_interface
*)THREAD_ARG(thread
);
2211 oi
->thread_send_lsupdate
= (struct thread
*)NULL
;
2213 if (oi
->state
<= OSPF6_INTERFACE_WAITING
) {
2214 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_LSUPDATE
,
2217 "Quit to send LSUpdate to interface %s state %s",
2218 oi
->interface
->name
,
2219 ospf6_interface_state_str
[oi
->state
]);
2223 /* if we have nothing to send, return */
2224 if (oi
->lsupdate_list
->count
== 0)
2227 memset(sendbuf
, 0, iobuflen
);
2228 oh
= (struct ospf6_header
*)sendbuf
;
2229 lsupdate
= (struct ospf6_lsupdate
*)((caddr_t
)oh
2230 + sizeof(struct ospf6_header
));
2232 p
= (uint8_t *)((caddr_t
)lsupdate
+ sizeof(struct ospf6_lsupdate
));
2235 for (ALL_LSDB(oi
->lsupdate_list
, lsa
, lsanext
)) {
2237 if ((p
- sendbuf
+ ((unsigned int)OSPF6_LSA_SIZE(lsa
->header
)))
2238 > ospf6_packet_max(oi
)) {
2240 oh
->type
= OSPF6_MESSAGE_TYPE_LSUPDATE
;
2241 oh
->length
= htons(p
- sendbuf
);
2242 lsupdate
->lsa_number
= htonl(lsa_cnt
);
2244 ospf6_send_lsupdate(NULL
, oi
, oh
);
2245 if (IS_OSPF6_DEBUG_MESSAGE(
2246 OSPF6_MESSAGE_TYPE_LSUPDATE
, SEND
))
2247 zlog_debug("%s: LSUpdate length %d",
2248 __func__
, ntohs(oh
->length
));
2250 memset(sendbuf
, 0, iobuflen
);
2251 oh
= (struct ospf6_header
*)sendbuf
;
2252 lsupdate
= (struct ospf6_lsupdate
2257 p
= (uint8_t *)((caddr_t
)lsupdate
2264 ospf6_lsa_age_update_to_send(lsa
, oi
->transdelay
);
2265 memcpy(p
, lsa
->header
, OSPF6_LSA_SIZE(lsa
->header
));
2266 p
+= OSPF6_LSA_SIZE(lsa
->header
);
2269 assert(lsa
->lock
== 2);
2270 ospf6_lsdb_remove(lsa
, oi
->lsupdate_list
);
2274 oh
->type
= OSPF6_MESSAGE_TYPE_LSUPDATE
;
2275 oh
->length
= htons(p
- sendbuf
);
2276 lsupdate
->lsa_number
= htonl(lsa_cnt
);
2278 ospf6_send_lsupdate(NULL
, oi
, oh
);
2281 if (oi
->lsupdate_list
->count
> 0) {
2282 oi
->thread_send_lsupdate
= NULL
;
2283 thread_add_event(master
, ospf6_lsupdate_send_interface
, oi
, 0,
2284 &oi
->thread_send_lsupdate
);
2290 int ospf6_lsack_send_neighbor(struct thread
*thread
)
2292 struct ospf6_neighbor
*on
;
2293 struct ospf6_header
*oh
;
2295 struct ospf6_lsa
*lsa
, *lsanext
;
2298 on
= (struct ospf6_neighbor
*)THREAD_ARG(thread
);
2299 on
->thread_send_lsack
= (struct thread
*)NULL
;
2301 if (on
->state
< OSPF6_NEIGHBOR_EXCHANGE
) {
2302 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_LSACK
, SEND_HDR
))
2303 zlog_debug("Quit to send LSAck to neighbor %s state %s",
2305 ospf6_neighbor_state_str
[on
->state
]);
2309 /* if we have nothing to send, return */
2310 if (on
->lsack_list
->count
== 0)
2313 memset(sendbuf
, 0, iobuflen
);
2314 oh
= (struct ospf6_header
*)sendbuf
;
2316 p
= (uint8_t *)((caddr_t
)oh
+ sizeof(struct ospf6_header
));
2318 for (ALL_LSDB(on
->lsack_list
, lsa
, lsanext
)) {
2320 if (p
- sendbuf
+ sizeof(struct ospf6_lsa_header
)
2321 > ospf6_packet_max(on
->ospf6_if
)) {
2322 /* if we run out of packet size/space here,
2323 better to try again soon. */
2325 oh
->type
= OSPF6_MESSAGE_TYPE_LSACK
;
2326 oh
->length
= htons(p
- sendbuf
);
2328 on
->ospf6_if
->ls_ack_out
++;
2330 ospf6_send(on
->ospf6_if
->linklocal_addr
,
2331 &on
->linklocal_addr
, on
->ospf6_if
,
2334 memset(sendbuf
, 0, iobuflen
);
2335 oh
= (struct ospf6_header
*)sendbuf
;
2336 p
= (uint8_t *)((caddr_t
)oh
2337 + sizeof(struct ospf6_header
));
2342 ospf6_lsa_age_update_to_send(lsa
, on
->ospf6_if
->transdelay
);
2343 memcpy(p
, lsa
->header
, sizeof(struct ospf6_lsa_header
));
2344 p
+= sizeof(struct ospf6_lsa_header
);
2346 assert(lsa
->lock
== 2);
2347 ospf6_lsdb_remove(lsa
, on
->lsack_list
);
2352 oh
->type
= OSPF6_MESSAGE_TYPE_LSACK
;
2353 oh
->length
= htons(p
- sendbuf
);
2355 on
->ospf6_if
->ls_ack_out
++;
2357 ospf6_send(on
->ospf6_if
->linklocal_addr
, &on
->linklocal_addr
,
2361 if (on
->lsack_list
->count
> 0)
2362 thread_add_event(master
, ospf6_lsack_send_neighbor
, on
, 0,
2363 &on
->thread_send_lsack
);
2368 int ospf6_lsack_send_interface(struct thread
*thread
)
2370 struct ospf6_interface
*oi
;
2371 struct ospf6_header
*oh
;
2373 struct ospf6_lsa
*lsa
, *lsanext
;
2376 oi
= (struct ospf6_interface
*)THREAD_ARG(thread
);
2377 oi
->thread_send_lsack
= (struct thread
*)NULL
;
2379 if (oi
->state
<= OSPF6_INTERFACE_WAITING
) {
2380 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_LSACK
, SEND_HDR
))
2382 "Quit to send LSAck to interface %s state %s",
2383 oi
->interface
->name
,
2384 ospf6_interface_state_str
[oi
->state
]);
2388 /* if we have nothing to send, return */
2389 if (oi
->lsack_list
->count
== 0)
2392 memset(sendbuf
, 0, iobuflen
);
2393 oh
= (struct ospf6_header
*)sendbuf
;
2395 p
= (uint8_t *)((caddr_t
)oh
+ sizeof(struct ospf6_header
));
2397 for (ALL_LSDB(oi
->lsack_list
, lsa
, lsanext
)) {
2399 if (p
- sendbuf
+ sizeof(struct ospf6_lsa_header
)
2400 > ospf6_packet_max(oi
)) {
2401 /* if we run out of packet size/space here,
2402 better to try again soon. */
2403 THREAD_OFF(oi
->thread_send_lsack
);
2404 thread_add_event(master
, ospf6_lsack_send_interface
, oi
,
2405 0, &oi
->thread_send_lsack
);
2407 ospf6_lsa_unlock(lsa
);
2409 ospf6_lsa_unlock(lsanext
);
2413 ospf6_lsa_age_update_to_send(lsa
, oi
->transdelay
);
2414 memcpy(p
, lsa
->header
, sizeof(struct ospf6_lsa_header
));
2415 p
+= sizeof(struct ospf6_lsa_header
);
2417 assert(lsa
->lock
== 2);
2418 ospf6_lsdb_remove(lsa
, oi
->lsack_list
);
2423 oh
->type
= OSPF6_MESSAGE_TYPE_LSACK
;
2424 oh
->length
= htons(p
- sendbuf
);
2426 if ((oi
->state
== OSPF6_INTERFACE_POINTTOPOINT
)
2427 || (oi
->state
== OSPF6_INTERFACE_DR
)
2428 || (oi
->state
== OSPF6_INTERFACE_BDR
))
2429 ospf6_send(oi
->linklocal_addr
, &allspfrouters6
, oi
, oh
);
2431 ospf6_send(oi
->linklocal_addr
, &alldrouters6
, oi
, oh
);
2434 if (oi
->lsack_list
->count
> 0)
2435 thread_add_event(master
, ospf6_lsack_send_interface
, oi
, 0,
2436 &oi
->thread_send_lsack
);
2443 DEFUN(debug_ospf6_message
, debug_ospf6_message_cmd
,
2444 "debug ospf6 message <unknown|hello|dbdesc|lsreq|lsupdate|lsack|all> [<send|recv|send-hdr|recv-hdr>]",
2446 "Debug OSPFv3 message\n"
2447 "Debug Unknown message\n"
2448 "Debug Hello message\n"
2449 "Debug Database Description message\n"
2450 "Debug Link State Request message\n"
2451 "Debug Link State Update message\n"
2452 "Debug Link State Acknowledgement message\n"
2453 "Debug All message\n"
2454 "Debug only sending message, entire packet\n"
2455 "Debug only receiving message, entire packet\n"
2456 "Debug only sending message, header only\n"
2457 "Debug only receiving message, header only\n")
2460 int idx_send_recv
= 4;
2461 unsigned char level
= 0;
2466 if (!strncmp(argv
[idx_packet
]->arg
, "u", 1))
2467 type
= OSPF6_MESSAGE_TYPE_UNKNOWN
;
2468 else if (!strncmp(argv
[idx_packet
]->arg
, "h", 1))
2469 type
= OSPF6_MESSAGE_TYPE_HELLO
;
2470 else if (!strncmp(argv
[idx_packet
]->arg
, "d", 1))
2471 type
= OSPF6_MESSAGE_TYPE_DBDESC
;
2472 else if (!strncmp(argv
[idx_packet
]->arg
, "lsr", 3))
2473 type
= OSPF6_MESSAGE_TYPE_LSREQ
;
2474 else if (!strncmp(argv
[idx_packet
]->arg
, "lsu", 3))
2475 type
= OSPF6_MESSAGE_TYPE_LSUPDATE
;
2476 else if (!strncmp(argv
[idx_packet
]->arg
, "lsa", 3))
2477 type
= OSPF6_MESSAGE_TYPE_LSACK
;
2478 else if (!strncmp(argv
[idx_packet
]->arg
, "a", 1))
2479 type
= OSPF6_MESSAGE_TYPE_ALL
;
2482 level
= OSPF6_DEBUG_MESSAGE_SEND
| OSPF6_DEBUG_MESSAGE_RECV
;
2483 else if (!strncmp(argv
[idx_send_recv
]->arg
, "send-h", 6))
2484 level
= OSPF6_DEBUG_MESSAGE_SEND_HDR
;
2485 else if (!strncmp(argv
[idx_send_recv
]->arg
, "s", 1))
2486 level
= OSPF6_DEBUG_MESSAGE_SEND
;
2487 else if (!strncmp(argv
[idx_send_recv
]->arg
, "recv-h", 6))
2488 level
= OSPF6_DEBUG_MESSAGE_RECV_HDR
;
2489 else if (!strncmp(argv
[idx_send_recv
]->arg
, "r", 1))
2490 level
= OSPF6_DEBUG_MESSAGE_RECV
;
2492 if (type
== OSPF6_MESSAGE_TYPE_ALL
) {
2493 for (i
= 0; i
< 6; i
++)
2494 OSPF6_DEBUG_MESSAGE_ON(i
, level
);
2496 OSPF6_DEBUG_MESSAGE_ON(type
, level
);
2501 DEFUN(no_debug_ospf6_message
, no_debug_ospf6_message_cmd
,
2502 "no debug ospf6 message <unknown|hello|dbdesc|lsreq|lsupdate|lsack|all> [<send|recv|send-hdr|recv-hdr>]",
2503 NO_STR DEBUG_STR OSPF6_STR
2504 "Debug OSPFv3 message\n"
2505 "Debug Unknown message\n"
2506 "Debug Hello message\n"
2507 "Debug Database Description message\n"
2508 "Debug Link State Request message\n"
2509 "Debug Link State Update message\n"
2510 "Debug Link State Acknowledgement message\n"
2511 "Debug All message\n"
2512 "Debug only sending message, entire pkt\n"
2513 "Debug only receiving message, entire pkt\n"
2514 "Debug only sending message, header only\n"
2515 "Debug only receiving message, header only\n")
2518 int idx_send_recv
= 5;
2519 unsigned char level
= 0;
2524 if (!strncmp(argv
[idx_packet
]->arg
, "u", 1))
2525 type
= OSPF6_MESSAGE_TYPE_UNKNOWN
;
2526 else if (!strncmp(argv
[idx_packet
]->arg
, "h", 1))
2527 type
= OSPF6_MESSAGE_TYPE_HELLO
;
2528 else if (!strncmp(argv
[idx_packet
]->arg
, "d", 1))
2529 type
= OSPF6_MESSAGE_TYPE_DBDESC
;
2530 else if (!strncmp(argv
[idx_packet
]->arg
, "lsr", 3))
2531 type
= OSPF6_MESSAGE_TYPE_LSREQ
;
2532 else if (!strncmp(argv
[idx_packet
]->arg
, "lsu", 3))
2533 type
= OSPF6_MESSAGE_TYPE_LSUPDATE
;
2534 else if (!strncmp(argv
[idx_packet
]->arg
, "lsa", 3))
2535 type
= OSPF6_MESSAGE_TYPE_LSACK
;
2536 else if (!strncmp(argv
[idx_packet
]->arg
, "a", 1))
2537 type
= OSPF6_MESSAGE_TYPE_ALL
;
2540 level
= OSPF6_DEBUG_MESSAGE_SEND
| OSPF6_DEBUG_MESSAGE_RECV
2541 | OSPF6_DEBUG_MESSAGE_SEND_HDR
2542 | OSPF6_DEBUG_MESSAGE_RECV_HDR
;
2543 else if (!strncmp(argv
[idx_send_recv
]->arg
, "send-h", 6))
2544 level
= OSPF6_DEBUG_MESSAGE_SEND_HDR
;
2545 else if (!strncmp(argv
[idx_send_recv
]->arg
, "s", 1))
2546 level
= OSPF6_DEBUG_MESSAGE_SEND
;
2547 else if (!strncmp(argv
[idx_send_recv
]->arg
, "recv-h", 6))
2548 level
= OSPF6_DEBUG_MESSAGE_RECV_HDR
;
2549 else if (!strncmp(argv
[idx_send_recv
]->arg
, "r", 1))
2550 level
= OSPF6_DEBUG_MESSAGE_RECV
;
2552 if (type
== OSPF6_MESSAGE_TYPE_ALL
) {
2553 for (i
= 0; i
< 6; i
++)
2554 OSPF6_DEBUG_MESSAGE_OFF(i
, level
);
2556 OSPF6_DEBUG_MESSAGE_OFF(type
, level
);
2562 int config_write_ospf6_debug_message(struct vty
*vty
)
2564 const char *type_str
[] = {"unknown", "hello", "dbdesc",
2565 "lsreq", "lsupdate", "lsack"};
2566 unsigned char s
= 0, r
= 0, sh
= 0, rh
= 0;
2569 for (i
= 0; i
< 6; i
++) {
2570 if (IS_OSPF6_DEBUG_MESSAGE_ENABLED(i
, SEND
))
2572 if (IS_OSPF6_DEBUG_MESSAGE_ENABLED(i
, RECV
))
2576 for (i
= 0; i
< 6; i
++) {
2577 if (IS_OSPF6_DEBUG_MESSAGE_ENABLED(i
, SEND_HDR
))
2579 if (IS_OSPF6_DEBUG_MESSAGE_ENABLED(i
, RECV_HDR
))
2583 if (s
== 0x3f && r
== 0x3f) {
2584 vty_out(vty
, "debug ospf6 message all\n");
2588 if (s
== 0x3f && r
== 0) {
2589 vty_out(vty
, "debug ospf6 message all send\n");
2591 } else if (s
== 0 && r
== 0x3f) {
2592 vty_out(vty
, "debug ospf6 message all recv\n");
2596 if (sh
== 0x3f && rh
== 0) {
2597 vty_out(vty
, "debug ospf6 message all send-hdr\n");
2599 } else if (sh
== 0 && rh
== 0x3f) {
2600 vty_out(vty
, "debug ospf6 message all recv-hdr\n");
2604 /* Unknown message is logged by default */
2605 if (!IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN
, SEND
)
2606 && !IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN
, RECV
))
2607 vty_out(vty
, "no debug ospf6 message unknown\n");
2608 else if (!IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN
, SEND
))
2609 vty_out(vty
, "no debug ospf6 message unknown send\n");
2610 else if (!IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN
, RECV
))
2611 vty_out(vty
, "no debug ospf6 message unknown recv\n");
2613 for (i
= 1; i
< 6; i
++) {
2614 if (IS_OSPF6_DEBUG_MESSAGE_ENABLED(i
, SEND
)
2615 && IS_OSPF6_DEBUG_MESSAGE_ENABLED(i
, RECV
)) {
2616 vty_out(vty
, "debug ospf6 message %s\n", type_str
[i
]);
2620 if (IS_OSPF6_DEBUG_MESSAGE_ENABLED(i
, SEND
))
2621 vty_out(vty
, "debug ospf6 message %s send\n",
2623 else if (IS_OSPF6_DEBUG_MESSAGE_ENABLED(i
, SEND_HDR
))
2624 vty_out(vty
, "debug ospf6 message %s send-hdr\n",
2627 if (IS_OSPF6_DEBUG_MESSAGE_ENABLED(i
, RECV
))
2628 vty_out(vty
, "debug ospf6 message %s recv\n",
2630 else if (IS_OSPF6_DEBUG_MESSAGE_ENABLED(i
, RECV_HDR
))
2631 vty_out(vty
, "debug ospf6 message %s recv-hdr\n",
2638 void install_element_ospf6_debug_message(void)
2640 install_element(ENABLE_NODE
, &debug_ospf6_message_cmd
);
2641 install_element(ENABLE_NODE
, &no_debug_ospf6_message_cmd
);
2642 install_element(CONFIG_NODE
, &debug_ospf6_message_cmd
);
2643 install_element(CONFIG_NODE
, &no_debug_ospf6_message_cmd
);