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
)) {
445 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV_HDR
))
446 zlog_debug("Master/Slave bit mismatch");
447 thread_add_event(master
, seqnumber_mismatch
, on
, 0,
452 if (CHECK_FLAG(dbdesc
->bits
, OSPF6_DBDESC_IBIT
)) {
453 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV_HDR
))
454 zlog_debug("Initialize bit mismatch");
455 thread_add_event(master
, seqnumber_mismatch
, on
, 0,
460 if (memcmp(on
->options
, dbdesc
->options
, sizeof(on
->options
))) {
461 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV_HDR
))
462 zlog_debug("Option field mismatch");
463 thread_add_event(master
, seqnumber_mismatch
, on
, 0,
468 if (ntohl(dbdesc
->seqnum
) != on
->dbdesc_seqnum
) {
469 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV_HDR
))
471 "Sequence number mismatch (%#lx expected)",
472 (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");
491 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV_HDR
))
492 zlog_debug("Not duplicate dbdesc in state %s",
493 ospf6_neighbor_state_str
[on
->state
]);
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 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
536 "SeqNumMismatch (E-bit mismatch), discard");
537 ospf6_lsa_delete(his
);
538 thread_add_event(master
, seqnumber_mismatch
, on
, 0,
543 mine
= ospf6_lsdb_lookup(his
->header
->type
, his
->header
->id
,
544 his
->header
->adv_router
, lsdb
);
546 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
547 zlog_debug("Add request (No database copy)");
548 ospf6_lsdb_add(ospf6_lsa_copy(his
), on
->request_list
);
549 } else if (ospf6_lsa_compare(his
, mine
) < 0) {
550 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
551 zlog_debug("Add request (Received MoreRecent)");
552 ospf6_lsdb_add(ospf6_lsa_copy(his
), on
->request_list
);
554 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
555 zlog_debug("Discard (Existing MoreRecent)");
557 ospf6_lsa_delete(his
);
560 assert(p
== OSPF6_MESSAGE_END(oh
));
562 /* Increment sequence number */
565 /* schedule send lsreq */
566 if (on
->request_list
->count
)
567 thread_add_event(master
, ospf6_lsreq_send
, on
, 0,
568 &on
->thread_send_lsreq
);
570 THREAD_OFF(on
->thread_send_dbdesc
);
573 if (!CHECK_FLAG(dbdesc
->bits
, OSPF6_DBDESC_MBIT
)
574 && !CHECK_FLAG(on
->dbdesc_bits
, OSPF6_DBDESC_MBIT
))
575 thread_add_event(master
, exchange_done
, on
, 0, NULL
);
577 on
->thread_send_dbdesc
= NULL
;
578 thread_add_event(master
, ospf6_dbdesc_send_newone
, on
, 0,
579 &on
->thread_send_dbdesc
);
582 /* save last received dbdesc */
583 memcpy(&on
->dbdesc_last
, dbdesc
, sizeof(struct ospf6_dbdesc
));
586 static void ospf6_dbdesc_recv_slave(struct ospf6_header
*oh
,
587 struct ospf6_neighbor
*on
)
589 struct ospf6_dbdesc
*dbdesc
;
592 dbdesc
= (struct ospf6_dbdesc
*)((caddr_t
)oh
593 + sizeof(struct ospf6_header
));
595 if (on
->state
< OSPF6_NEIGHBOR_INIT
) {
596 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV_HDR
))
597 zlog_debug("Neighbor state less than Init, ignore");
602 case OSPF6_NEIGHBOR_TWOWAY
:
603 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV_HDR
))
604 zlog_debug("Neighbor state is 2-Way, ignore");
607 case OSPF6_NEIGHBOR_INIT
:
608 thread_execute(master
, twoway_received
, on
, 0);
609 if (on
->state
!= OSPF6_NEIGHBOR_EXSTART
) {
610 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV_HDR
))
612 "Neighbor state is not ExStart, ignore");
615 /* else fall through to ExStart */
617 case OSPF6_NEIGHBOR_EXSTART
:
618 /* If the neighbor is Master, act as Slave. Schedule
620 and process LSA Headers. Otherwise, ignore this message */
621 if (CHECK_FLAG(dbdesc
->bits
, OSPF6_DBDESC_IBIT
)
622 && CHECK_FLAG(dbdesc
->bits
, OSPF6_DBDESC_MBIT
)
623 && CHECK_FLAG(dbdesc
->bits
, OSPF6_DBDESC_MSBIT
)
625 == sizeof(struct ospf6_header
)
626 + sizeof(struct ospf6_dbdesc
)) {
627 /* set the master/slave bit to slave */
628 UNSET_FLAG(on
->dbdesc_bits
, OSPF6_DBDESC_MSBIT
);
630 /* set the DD sequence number to one specified by master
632 on
->dbdesc_seqnum
= ntohl(dbdesc
->seqnum
);
634 /* schedule NegotiationDone */
635 thread_execute(master
, negotiation_done
, on
, 0);
637 /* Record neighbor options */
638 memcpy(on
->options
, dbdesc
->options
,
639 sizeof(on
->options
));
642 "VRF %s: Nbr %s Negotiation failed",
643 vrf_id_to_name(on
->ospf6_if
->interface
->vrf_id
),
649 case OSPF6_NEIGHBOR_EXCHANGE
:
650 if (!memcmp(dbdesc
, &on
->dbdesc_last
,
651 sizeof(struct ospf6_dbdesc
))) {
652 /* Duplicated DatabaseDescription causes slave to
654 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV_HDR
))
656 "Duplicated dbdesc causes retransmit");
657 THREAD_OFF(on
->thread_send_dbdesc
);
658 on
->thread_send_dbdesc
= NULL
;
659 thread_add_event(master
, ospf6_dbdesc_send
, on
, 0,
660 &on
->thread_send_dbdesc
);
664 if (!CHECK_FLAG(dbdesc
->bits
, OSPF6_DBDESC_MSBIT
)) {
665 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV_HDR
))
666 zlog_debug("Master/Slave bit mismatch");
667 thread_add_event(master
, seqnumber_mismatch
, on
, 0,
672 if (CHECK_FLAG(dbdesc
->bits
, OSPF6_DBDESC_IBIT
)) {
673 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV_HDR
))
674 zlog_debug("Initialize bit mismatch");
675 thread_add_event(master
, seqnumber_mismatch
, on
, 0,
680 if (memcmp(on
->options
, dbdesc
->options
, sizeof(on
->options
))) {
681 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV_HDR
))
682 zlog_debug("Option field mismatch");
683 thread_add_event(master
, seqnumber_mismatch
, on
, 0,
688 if (ntohl(dbdesc
->seqnum
) != on
->dbdesc_seqnum
+ 1) {
689 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV_HDR
))
691 "Sequence number mismatch (%#lx expected)",
692 (unsigned long)on
->dbdesc_seqnum
+ 1);
693 thread_add_event(master
, seqnumber_mismatch
, on
, 0,
699 case OSPF6_NEIGHBOR_LOADING
:
700 case OSPF6_NEIGHBOR_FULL
:
701 if (!memcmp(dbdesc
, &on
->dbdesc_last
,
702 sizeof(struct ospf6_dbdesc
))) {
703 /* Duplicated DatabaseDescription causes slave to
705 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV_HDR
))
707 "Duplicated dbdesc causes retransmit");
708 THREAD_OFF(on
->thread_send_dbdesc
);
709 thread_add_event(master
, ospf6_dbdesc_send
, on
, 0,
710 &on
->thread_send_dbdesc
);
714 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV_HDR
))
715 zlog_debug("Not duplicate dbdesc in state %s",
716 ospf6_neighbor_state_str
[on
->state
]);
717 thread_add_event(master
, seqnumber_mismatch
, on
, 0, NULL
);
725 /* Process LSA headers */
726 for (p
= (char *)((caddr_t
)dbdesc
+ sizeof(struct ospf6_dbdesc
));
727 p
+ sizeof(struct ospf6_lsa_header
) <= OSPF6_MESSAGE_END(oh
);
728 p
+= sizeof(struct ospf6_lsa_header
)) {
729 struct ospf6_lsa
*his
, *mine
;
730 struct ospf6_lsdb
*lsdb
= NULL
;
732 his
= ospf6_lsa_create_headeronly((struct ospf6_lsa_header
*)p
);
734 switch (OSPF6_LSA_SCOPE(his
->header
->type
)) {
735 case OSPF6_SCOPE_LINKLOCAL
:
736 lsdb
= on
->ospf6_if
->lsdb
;
738 case OSPF6_SCOPE_AREA
:
739 lsdb
= on
->ospf6_if
->area
->lsdb
;
742 lsdb
= on
->ospf6_if
->area
->ospf6
->lsdb
;
744 case OSPF6_SCOPE_RESERVED
:
745 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
746 zlog_debug("Ignoring LSA of reserved scope");
747 ospf6_lsa_delete(his
);
752 if (OSPF6_LSA_SCOPE(his
->header
->type
) == OSPF6_SCOPE_AS
753 && IS_AREA_STUB(on
->ospf6_if
->area
)) {
754 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
755 zlog_debug("E-bit mismatch with LSA Headers");
756 ospf6_lsa_delete(his
);
757 thread_add_event(master
, seqnumber_mismatch
, on
, 0,
762 mine
= ospf6_lsdb_lookup(his
->header
->type
, his
->header
->id
,
763 his
->header
->adv_router
, lsdb
);
764 if (mine
== NULL
|| ospf6_lsa_compare(his
, mine
) < 0) {
765 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
766 zlog_debug("Add request-list: %s", his
->name
);
767 ospf6_lsdb_add(ospf6_lsa_copy(his
), on
->request_list
);
769 ospf6_lsa_delete(his
);
772 assert(p
== OSPF6_MESSAGE_END(oh
));
774 /* Set sequence number to Master's */
775 on
->dbdesc_seqnum
= ntohl(dbdesc
->seqnum
);
777 /* schedule send lsreq */
778 if (on
->request_list
->count
)
779 thread_add_event(master
, ospf6_lsreq_send
, on
, 0,
780 &on
->thread_send_lsreq
);
782 THREAD_OFF(on
->thread_send_dbdesc
);
783 thread_add_event(master
, ospf6_dbdesc_send_newone
, on
, 0,
784 &on
->thread_send_dbdesc
);
786 /* save last received dbdesc */
787 memcpy(&on
->dbdesc_last
, dbdesc
, sizeof(struct ospf6_dbdesc
));
790 static void ospf6_dbdesc_recv(struct in6_addr
*src
, struct in6_addr
*dst
,
791 struct ospf6_interface
*oi
,
792 struct ospf6_header
*oh
)
794 struct ospf6_neighbor
*on
;
795 struct ospf6_dbdesc
*dbdesc
;
797 on
= ospf6_neighbor_lookup(oh
->router_id
, oi
);
799 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV_HDR
))
800 zlog_debug("Neighbor not found, ignore");
804 dbdesc
= (struct ospf6_dbdesc
*)((caddr_t
)oh
805 + sizeof(struct ospf6_header
));
807 /* Interface MTU check */
808 if (!oi
->mtu_ignore
&& ntohs(dbdesc
->ifmtu
) != oi
->ifmtu
) {
809 zlog_warn("VRF %s: I/F %s MTU mismatch (my %d rcvd %d)",
810 vrf_id_to_name(oi
->interface
->vrf_id
),
811 oi
->interface
->name
, oi
->ifmtu
, ntohs(dbdesc
->ifmtu
));
815 if (dbdesc
->reserved1
|| dbdesc
->reserved2
) {
816 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV_HDR
))
818 "Non-0 reserved field in %s's DbDesc, correct",
820 dbdesc
->reserved1
= 0;
821 dbdesc
->reserved2
= 0;
826 if (ntohl(oh
->router_id
) < ntohl(oi
->area
->ospf6
->router_id
))
827 ospf6_dbdesc_recv_master(oh
, on
);
828 else if (ntohl(oi
->area
->ospf6
->router_id
) < ntohl(oh
->router_id
))
829 ospf6_dbdesc_recv_slave(oh
, on
);
831 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV_HDR
))
832 zlog_debug("Can't decide which is master, ignore");
836 static void ospf6_lsreq_recv(struct in6_addr
*src
, struct in6_addr
*dst
,
837 struct ospf6_interface
*oi
,
838 struct ospf6_header
*oh
)
840 struct ospf6_neighbor
*on
;
842 struct ospf6_lsreq_entry
*e
;
843 struct ospf6_lsdb
*lsdb
= NULL
;
844 struct ospf6_lsa
*lsa
;
846 on
= ospf6_neighbor_lookup(oh
->router_id
, oi
);
848 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV_HDR
))
849 zlog_debug("Neighbor not found, ignore");
853 if (on
->state
!= OSPF6_NEIGHBOR_EXCHANGE
854 && on
->state
!= OSPF6_NEIGHBOR_LOADING
855 && on
->state
!= OSPF6_NEIGHBOR_FULL
) {
856 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV_HDR
))
857 zlog_debug("Neighbor state less than Exchange, ignore");
863 /* Process each request */
864 for (p
= (char *)((caddr_t
)oh
+ sizeof(struct ospf6_header
));
865 p
+ sizeof(struct ospf6_lsreq_entry
) <= OSPF6_MESSAGE_END(oh
);
866 p
+= sizeof(struct ospf6_lsreq_entry
)) {
867 e
= (struct ospf6_lsreq_entry
*)p
;
869 switch (OSPF6_LSA_SCOPE(e
->type
)) {
870 case OSPF6_SCOPE_LINKLOCAL
:
871 lsdb
= on
->ospf6_if
->lsdb
;
873 case OSPF6_SCOPE_AREA
:
874 lsdb
= on
->ospf6_if
->area
->lsdb
;
877 lsdb
= on
->ospf6_if
->area
->ospf6
->lsdb
;
880 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
881 zlog_debug("Ignoring LSA of reserved scope");
886 /* Find database copy */
887 lsa
= ospf6_lsdb_lookup(e
->type
, e
->id
, e
->adv_router
, lsdb
);
889 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
)) {
891 "Can't find requested [%s Id:%pI4 Adv:%pI4]",
892 ospf6_lstype_name(e
->type
), &e
->id
,
895 thread_add_event(master
, bad_lsreq
, on
, 0, NULL
);
899 ospf6_lsdb_add(ospf6_lsa_copy(lsa
), on
->lsupdate_list
);
902 assert(p
== OSPF6_MESSAGE_END(oh
));
904 /* schedule send lsupdate */
905 THREAD_OFF(on
->thread_send_lsupdate
);
906 thread_add_event(master
, ospf6_lsupdate_send_neighbor
, on
, 0,
907 &on
->thread_send_lsupdate
);
910 /* Verify, that the specified memory area contains exactly N valid IPv6
911 prefixes as specified by RFC5340, A.4.1. */
912 static unsigned ospf6_prefixes_examin(
913 struct ospf6_prefix
*current
, /* start of buffer */
915 const uint32_t req_num_pfxs
/* always compared with the actual number
919 uint8_t requested_pfx_bytes
;
920 uint32_t real_num_pfxs
= 0;
923 if (length
< OSPF6_PREFIX_MIN_SIZE
) {
924 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN
,
926 zlog_debug("%s: undersized IPv6 prefix header",
930 /* safe to look deeper */
931 if (current
->prefix_length
> IPV6_MAX_BITLEN
) {
932 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN
,
934 zlog_debug("%s: invalid PrefixLength (%u bits)",
935 __func__
, current
->prefix_length
);
938 /* covers both fixed- and variable-sized fields */
939 requested_pfx_bytes
=
940 OSPF6_PREFIX_MIN_SIZE
941 + OSPF6_PREFIX_SPACE(current
->prefix_length
);
942 if (requested_pfx_bytes
> length
) {
943 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN
,
945 zlog_debug("%s: undersized IPv6 prefix",
950 length
-= requested_pfx_bytes
;
951 current
= (struct ospf6_prefix
*)((caddr_t
)current
952 + requested_pfx_bytes
);
955 if (real_num_pfxs
!= req_num_pfxs
) {
956 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN
,
959 "%s: IPv6 prefix number mismatch (%u required, %u real)",
960 __func__
, req_num_pfxs
, real_num_pfxs
);
966 /* Verify an LSA to have a valid length and dispatch further (where
967 appropriate) to check if the contents, including nested IPv6 prefixes,
968 is properly sized/aligned within the LSA. Note that this function gets
969 LSA type in network byte order, uses in host byte order and passes to
970 ospf6_lstype_name() in network byte order again. */
971 static unsigned ospf6_lsa_examin(struct ospf6_lsa_header
*lsah
,
972 const uint16_t lsalen
,
973 const uint8_t headeronly
)
975 struct ospf6_intra_prefix_lsa
*intra_prefix_lsa
;
976 struct ospf6_as_external_lsa
*as_external_lsa
;
977 struct ospf6_link_lsa
*link_lsa
;
982 /* In case an additional minimum length constraint is defined for
984 LSA type, make sure that this constraint is met. */
985 lsatype
= ntohs(lsah
->type
);
986 ltindex
= lsatype
& OSPF6_LSTYPE_FCODE_MASK
;
987 if (ltindex
< OSPF6_LSTYPE_SIZE
&& ospf6_lsa_minlen
[ltindex
]
988 && lsalen
< ospf6_lsa_minlen
[ltindex
] + OSPF6_LSA_HEADER_SIZE
) {
989 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN
,
991 zlog_debug("%s: undersized (%u B) LSA", __func__
,
996 case OSPF6_LSTYPE_ROUTER
:
997 /* RFC5340 A.4.3, LSA header + OSPF6_ROUTER_LSA_MIN_SIZE bytes
999 by N>=0 interface descriptions. */
1000 if ((lsalen
- OSPF6_LSA_HEADER_SIZE
- OSPF6_ROUTER_LSA_MIN_SIZE
)
1001 % OSPF6_ROUTER_LSDESC_FIX_SIZE
) {
1002 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN
,
1005 "%s: interface description alignment error",
1010 case OSPF6_LSTYPE_NETWORK
:
1011 /* RFC5340 A.4.4, LSA header + OSPF6_NETWORK_LSA_MIN_SIZE bytes
1012 followed by N>=0 attached router descriptions. */
1013 if ((lsalen
- OSPF6_LSA_HEADER_SIZE
1014 - OSPF6_NETWORK_LSA_MIN_SIZE
)
1015 % OSPF6_NETWORK_LSDESC_FIX_SIZE
) {
1016 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN
,
1019 "%s: router description alignment error",
1024 case OSPF6_LSTYPE_INTER_PREFIX
:
1025 /* RFC5340 A.4.5, LSA header + OSPF6_INTER_PREFIX_LSA_MIN_SIZE
1027 followed by 3-4 fields of a single IPv6 prefix. */
1030 return ospf6_prefixes_examin(
1031 (struct ospf6_prefix
1032 *)((caddr_t
)lsah
+ OSPF6_LSA_HEADER_SIZE
1033 + OSPF6_INTER_PREFIX_LSA_MIN_SIZE
),
1034 lsalen
- OSPF6_LSA_HEADER_SIZE
1035 - OSPF6_INTER_PREFIX_LSA_MIN_SIZE
,
1037 case OSPF6_LSTYPE_INTER_ROUTER
:
1038 /* RFC5340 A.4.6, fixed-size LSA. */
1040 > OSPF6_LSA_HEADER_SIZE
+ OSPF6_INTER_ROUTER_LSA_FIX_SIZE
) {
1041 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN
,
1043 zlog_debug("%s: oversized (%u B) LSA", __func__
,
1048 case OSPF6_LSTYPE_AS_EXTERNAL
: /* RFC5340 A.4.7, same as A.4.8. */
1049 case OSPF6_LSTYPE_TYPE_7
:
1050 /* RFC5340 A.4.8, LSA header + OSPF6_AS_EXTERNAL_LSA_MIN_SIZE
1052 followed by 3-4 fields of IPv6 prefix and 3 conditional LSA
1054 16 bytes of forwarding address, 4 bytes of external route
1056 4 bytes of referenced link state ID. */
1060 (struct ospf6_as_external_lsa
1061 *)((caddr_t
)lsah
+ OSPF6_LSA_HEADER_SIZE
);
1063 OSPF6_LSA_HEADER_SIZE
+ OSPF6_AS_EXTERNAL_LSA_MIN_SIZE
;
1064 /* To find out if the last optional field (Referenced Link State
1066 assumed in this LSA, we need to access fixed fields of the
1068 prefix before ospf6_prefix_examin() confirms its sizing. */
1069 if (exp_length
+ OSPF6_PREFIX_MIN_SIZE
> lsalen
) {
1070 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN
,
1072 zlog_debug("%s: undersized (%u B) LSA header",
1076 /* forwarding address */
1077 if (CHECK_FLAG(as_external_lsa
->bits_metric
, OSPF6_ASBR_BIT_F
))
1079 /* external route tag */
1080 if (CHECK_FLAG(as_external_lsa
->bits_metric
, OSPF6_ASBR_BIT_T
))
1082 /* referenced link state ID */
1083 if (as_external_lsa
->prefix
.u
._prefix_referenced_lstype
)
1085 /* All the fixed-size fields (mandatory and optional) must fit.
1087 this check does not include any IPv6 prefix fields. */
1088 if (exp_length
> lsalen
) {
1089 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN
,
1091 zlog_debug("%s: undersized (%u B) LSA header",
1095 /* The last call completely covers the remainder (IPv6 prefix).
1097 return ospf6_prefixes_examin(
1098 (struct ospf6_prefix
1099 *)((caddr_t
)as_external_lsa
1100 + OSPF6_AS_EXTERNAL_LSA_MIN_SIZE
),
1101 lsalen
- exp_length
, 1);
1102 case OSPF6_LSTYPE_LINK
:
1103 /* RFC5340 A.4.9, LSA header + OSPF6_LINK_LSA_MIN_SIZE bytes
1105 by N>=0 IPv6 prefix blocks (with N declared beforehand). */
1108 link_lsa
= (struct ospf6_link_lsa
*)((caddr_t
)lsah
1109 + OSPF6_LSA_HEADER_SIZE
);
1110 return ospf6_prefixes_examin(
1111 (struct ospf6_prefix
*)((caddr_t
)link_lsa
1112 + OSPF6_LINK_LSA_MIN_SIZE
),
1113 lsalen
- OSPF6_LSA_HEADER_SIZE
1114 - OSPF6_LINK_LSA_MIN_SIZE
,
1115 ntohl(link_lsa
->prefix_num
) /* 32 bits */
1117 case OSPF6_LSTYPE_INTRA_PREFIX
:
1118 /* RFC5340 A.4.10, LSA header + OSPF6_INTRA_PREFIX_LSA_MIN_SIZE
1120 followed by N>=0 IPv6 prefixes (with N declared beforehand).
1125 (struct ospf6_intra_prefix_lsa
1126 *)((caddr_t
)lsah
+ OSPF6_LSA_HEADER_SIZE
);
1127 return ospf6_prefixes_examin(
1128 (struct ospf6_prefix
1129 *)((caddr_t
)intra_prefix_lsa
1130 + OSPF6_INTRA_PREFIX_LSA_MIN_SIZE
),
1131 lsalen
- OSPF6_LSA_HEADER_SIZE
1132 - OSPF6_INTRA_PREFIX_LSA_MIN_SIZE
,
1133 ntohs(intra_prefix_lsa
->prefix_num
) /* 16 bits */
1136 /* No additional validation is possible for unknown LSA types, which are
1137 themselves valid in OPSFv3, hence the default decision is to accept.
1142 /* Verify if the provided input buffer is a valid sequence of LSAs. This
1143 includes verification of LSA blocks length/alignment and dispatching
1144 of deeper-level checks. */
1146 ospf6_lsaseq_examin(struct ospf6_lsa_header
*lsah
, /* start of buffered data */
1147 size_t length
, const uint8_t headeronly
,
1148 /* When declared_num_lsas is not 0, compare it to the real
1150 and treat the difference as an error. */
1151 const uint32_t declared_num_lsas
)
1153 uint32_t counted_lsas
= 0;
1157 if (length
< OSPF6_LSA_HEADER_SIZE
) {
1158 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN
,
1161 "%s: undersized (%zu B) trailing (#%u) LSA header",
1162 __func__
, length
, counted_lsas
);
1165 /* save on ntohs() calls here and in the LSA validator */
1166 lsalen
= OSPF6_LSA_SIZE(lsah
);
1167 if (lsalen
< OSPF6_LSA_HEADER_SIZE
) {
1168 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN
,
1171 "%s: malformed LSA header #%u, declared length is %u B",
1172 __func__
, counted_lsas
, lsalen
);
1176 /* less checks here and in ospf6_lsa_examin() */
1177 if (MSG_OK
!= ospf6_lsa_examin(lsah
, lsalen
, 1)) {
1178 if (IS_OSPF6_DEBUG_MESSAGE(
1179 OSPF6_MESSAGE_TYPE_UNKNOWN
,
1182 "%s: anomaly in header-only %s LSA #%u",
1184 ospf6_lstype_name(lsah
->type
),
1188 lsah
= (struct ospf6_lsa_header
1190 + OSPF6_LSA_HEADER_SIZE
);
1191 length
-= OSPF6_LSA_HEADER_SIZE
;
1193 /* make sure the input buffer is deep enough before
1195 if (lsalen
> length
) {
1196 if (IS_OSPF6_DEBUG_MESSAGE(
1197 OSPF6_MESSAGE_TYPE_UNKNOWN
,
1200 "%s: anomaly in %s LSA #%u: declared length is %u B, buffered length is %zu B",
1202 ospf6_lstype_name(lsah
->type
),
1203 counted_lsas
, lsalen
, length
);
1206 if (MSG_OK
!= ospf6_lsa_examin(lsah
, lsalen
, 0)) {
1207 if (IS_OSPF6_DEBUG_MESSAGE(
1208 OSPF6_MESSAGE_TYPE_UNKNOWN
,
1211 "%s: anomaly in %s LSA #%u",
1213 ospf6_lstype_name(lsah
->type
),
1217 lsah
= (struct ospf6_lsa_header
*)((caddr_t
)lsah
1224 if (declared_num_lsas
&& counted_lsas
!= declared_num_lsas
) {
1225 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN
,
1228 "%s: #LSAs declared (%u) does not match actual (%u)",
1229 __func__
, declared_num_lsas
, counted_lsas
);
1235 /* Verify a complete OSPF packet for proper sizing/alignment. */
1236 static unsigned ospf6_packet_examin(struct ospf6_header
*oh
,
1237 const unsigned bytesonwire
)
1239 struct ospf6_lsupdate
*lsupd
;
1242 /* length, 1st approximation */
1243 if (bytesonwire
< OSPF6_HEADER_SIZE
) {
1244 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN
,
1246 zlog_debug("%s: undersized (%u B) packet", __func__
,
1250 /* Now it is safe to access header fields. */
1251 if (bytesonwire
!= ntohs(oh
->length
)) {
1252 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN
,
1255 "%s: %s packet length error (%u real, %u declared)",
1256 __func__
, lookup_msg(ospf6_message_type_str
,
1258 bytesonwire
, ntohs(oh
->length
));
1262 if (oh
->version
!= OSPFV3_VERSION
) {
1263 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN
,
1265 zlog_debug("%s: invalid (%u) protocol version",
1266 __func__
, oh
->version
);
1269 /* length, 2nd approximation */
1270 if (oh
->type
< OSPF6_MESSAGE_TYPE_ALL
&& ospf6_packet_minlen
[oh
->type
]
1272 < OSPF6_HEADER_SIZE
+ ospf6_packet_minlen
[oh
->type
]) {
1273 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN
,
1275 zlog_debug("%s: undersized (%u B) %s packet", __func__
,
1277 lookup_msg(ospf6_message_type_str
, oh
->type
,
1281 /* type-specific deeper validation */
1283 case OSPF6_MESSAGE_TYPE_HELLO
:
1284 /* RFC5340 A.3.2, packet header + OSPF6_HELLO_MIN_SIZE bytes
1286 by N>=0 router-IDs. */
1288 == (bytesonwire
- OSPF6_HEADER_SIZE
- OSPF6_HELLO_MIN_SIZE
)
1291 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN
,
1293 zlog_debug("%s: alignment error in %s packet", __func__
,
1294 lookup_msg(ospf6_message_type_str
, oh
->type
,
1297 case OSPF6_MESSAGE_TYPE_DBDESC
:
1298 /* RFC5340 A.3.3, packet header + OSPF6_DB_DESC_MIN_SIZE bytes
1300 by N>=0 header-only LSAs. */
1301 test
= ospf6_lsaseq_examin(
1302 (struct ospf6_lsa_header
*)((caddr_t
)oh
1304 + OSPF6_DB_DESC_MIN_SIZE
),
1305 bytesonwire
- OSPF6_HEADER_SIZE
1306 - OSPF6_DB_DESC_MIN_SIZE
,
1309 case OSPF6_MESSAGE_TYPE_LSREQ
:
1310 /* RFC5340 A.3.4, packet header + N>=0 LS description blocks. */
1312 == (bytesonwire
- OSPF6_HEADER_SIZE
- OSPF6_LS_REQ_MIN_SIZE
)
1313 % OSPF6_LSREQ_LSDESC_FIX_SIZE
)
1315 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN
,
1317 zlog_debug("%s: alignment error in %s packet", __func__
,
1318 lookup_msg(ospf6_message_type_str
, oh
->type
,
1321 case OSPF6_MESSAGE_TYPE_LSUPDATE
:
1322 /* RFC5340 A.3.5, packet header + OSPF6_LS_UPD_MIN_SIZE bytes
1324 by N>=0 full LSAs (with N declared beforehand). */
1325 lsupd
= (struct ospf6_lsupdate
*)((caddr_t
)oh
1326 + OSPF6_HEADER_SIZE
);
1327 test
= ospf6_lsaseq_examin(
1328 (struct ospf6_lsa_header
*)((caddr_t
)lsupd
1329 + OSPF6_LS_UPD_MIN_SIZE
),
1330 bytesonwire
- OSPF6_HEADER_SIZE
- OSPF6_LS_UPD_MIN_SIZE
,
1331 0, ntohl(lsupd
->lsa_number
) /* 32 bits */
1334 case OSPF6_MESSAGE_TYPE_LSACK
:
1335 /* RFC5340 A.3.6, packet header + N>=0 header-only LSAs. */
1336 test
= ospf6_lsaseq_examin(
1337 (struct ospf6_lsa_header
*)((caddr_t
)oh
1339 + OSPF6_LS_ACK_MIN_SIZE
),
1340 bytesonwire
- OSPF6_HEADER_SIZE
- OSPF6_LS_ACK_MIN_SIZE
,
1344 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN
,
1346 zlog_debug("%s: invalid (%u) message type", __func__
,
1351 && IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN
, RECV_HDR
))
1352 zlog_debug("%s: anomaly in %s packet", __func__
,
1353 lookup_msg(ospf6_message_type_str
, oh
->type
, NULL
));
1357 /* Verify particular fields of otherwise correct received OSPF packet to
1358 meet the requirements of RFC. */
1359 static int ospf6_rxpacket_examin(struct ospf6_interface
*oi
,
1360 struct ospf6_header
*oh
,
1361 const unsigned bytesonwire
)
1364 if (MSG_OK
!= ospf6_packet_examin(oh
, bytesonwire
))
1368 if (oh
->area_id
!= oi
->area
->area_id
) {
1369 if (oh
->area_id
== OSPF_AREA_BACKBONE
)
1371 "VRF %s: I/F %s Message may be via Virtual Link: not supported",
1372 vrf_id_to_name(oi
->interface
->vrf_id
),
1373 oi
->interface
->name
);
1376 "VRF %s: I/F %s Area-ID mismatch (my %pI4, rcvd %pI4)",
1377 vrf_id_to_name(oi
->interface
->vrf_id
),
1378 oi
->interface
->name
, &oi
->area
->area_id
,
1383 /* Instance-ID check */
1384 if (oh
->instance_id
!= oi
->instance_id
) {
1386 "VRF %s: I/F %s Instance-ID mismatch (my %u, rcvd %u)",
1387 vrf_id_to_name(oi
->interface
->vrf_id
),
1388 oi
->interface
->name
, oi
->instance_id
, oh
->instance_id
);
1392 /* Router-ID check */
1393 if (oh
->router_id
== oi
->area
->ospf6
->router_id
) {
1394 zlog_warn("VRF %s: I/F %s Duplicate Router-ID (%pI4)",
1395 vrf_id_to_name(oi
->interface
->vrf_id
),
1396 oi
->interface
->name
, &oh
->router_id
);
1402 static void ospf6_lsupdate_recv(struct in6_addr
*src
, struct in6_addr
*dst
,
1403 struct ospf6_interface
*oi
,
1404 struct ospf6_header
*oh
)
1406 struct ospf6_neighbor
*on
;
1407 struct ospf6_lsupdate
*lsupdate
;
1410 on
= ospf6_neighbor_lookup(oh
->router_id
, oi
);
1412 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV_HDR
))
1413 zlog_debug("Neighbor not found, ignore");
1417 if (on
->state
!= OSPF6_NEIGHBOR_EXCHANGE
1418 && on
->state
!= OSPF6_NEIGHBOR_LOADING
1419 && on
->state
!= OSPF6_NEIGHBOR_FULL
) {
1420 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV_HDR
))
1421 zlog_debug("Neighbor state less than Exchange, ignore");
1425 lsupdate
= (struct ospf6_lsupdate
*)((caddr_t
)oh
1426 + sizeof(struct ospf6_header
));
1431 for (p
= (char *)((caddr_t
)lsupdate
+ sizeof(struct ospf6_lsupdate
));
1432 p
< OSPF6_MESSAGE_END(oh
)
1433 && p
+ OSPF6_LSA_SIZE(p
) <= OSPF6_MESSAGE_END(oh
);
1434 p
+= OSPF6_LSA_SIZE(p
)) {
1435 ospf6_receive_lsa(on
, (struct ospf6_lsa_header
*)p
);
1438 assert(p
== OSPF6_MESSAGE_END(oh
));
1441 static void ospf6_lsack_recv(struct in6_addr
*src
, struct in6_addr
*dst
,
1442 struct ospf6_interface
*oi
,
1443 struct ospf6_header
*oh
)
1445 struct ospf6_neighbor
*on
;
1447 struct ospf6_lsa
*his
, *mine
;
1448 struct ospf6_lsdb
*lsdb
= NULL
;
1450 assert(oh
->type
== OSPF6_MESSAGE_TYPE_LSACK
);
1452 on
= ospf6_neighbor_lookup(oh
->router_id
, oi
);
1454 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV_HDR
))
1455 zlog_debug("Neighbor not found, ignore");
1459 if (on
->state
!= OSPF6_NEIGHBOR_EXCHANGE
1460 && on
->state
!= OSPF6_NEIGHBOR_LOADING
1461 && on
->state
!= OSPF6_NEIGHBOR_FULL
) {
1462 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV_HDR
))
1463 zlog_debug("Neighbor state less than Exchange, ignore");
1469 for (p
= (char *)((caddr_t
)oh
+ sizeof(struct ospf6_header
));
1470 p
+ sizeof(struct ospf6_lsa_header
) <= OSPF6_MESSAGE_END(oh
);
1471 p
+= sizeof(struct ospf6_lsa_header
)) {
1472 his
= ospf6_lsa_create_headeronly((struct ospf6_lsa_header
*)p
);
1474 switch (OSPF6_LSA_SCOPE(his
->header
->type
)) {
1475 case OSPF6_SCOPE_LINKLOCAL
:
1476 lsdb
= on
->ospf6_if
->lsdb
;
1478 case OSPF6_SCOPE_AREA
:
1479 lsdb
= on
->ospf6_if
->area
->lsdb
;
1481 case OSPF6_SCOPE_AS
:
1482 lsdb
= on
->ospf6_if
->area
->ospf6
->lsdb
;
1484 case OSPF6_SCOPE_RESERVED
:
1485 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
1486 zlog_debug("Ignoring LSA of reserved scope");
1487 ospf6_lsa_delete(his
);
1492 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
1493 zlog_debug("%s acknowledged by %s", his
->name
,
1496 /* Find database copy */
1497 mine
= ospf6_lsdb_lookup(his
->header
->type
, his
->header
->id
,
1498 his
->header
->adv_router
, lsdb
);
1500 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
1501 zlog_debug("No database copy");
1502 ospf6_lsa_delete(his
);
1506 /* Check if the LSA is on his retrans-list */
1507 mine
= ospf6_lsdb_lookup(his
->header
->type
, his
->header
->id
,
1508 his
->header
->adv_router
,
1511 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
1512 zlog_debug("Not on %s's retrans-list",
1514 ospf6_lsa_delete(his
);
1518 if (ospf6_lsa_compare(his
, mine
) != 0) {
1519 /* Log this questionable acknowledgement,
1520 and examine the next one. */
1521 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
1522 zlog_debug("Questionable acknowledgement");
1523 ospf6_lsa_delete(his
);
1527 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
1529 "Acknowledged, remove from %s's retrans-list",
1532 ospf6_decrement_retrans_count(mine
);
1533 if (OSPF6_LSA_IS_MAXAGE(mine
))
1534 ospf6_maxage_remove(on
->ospf6_if
->area
->ospf6
);
1535 ospf6_lsdb_remove(mine
, on
->retrans_list
);
1536 ospf6_lsa_delete(his
);
1539 assert(p
== OSPF6_MESSAGE_END(oh
));
1542 static uint8_t *recvbuf
= NULL
;
1543 static uint8_t *sendbuf
= NULL
;
1544 static unsigned int iobuflen
= 0;
1546 int ospf6_iobuf_size(unsigned int size
)
1548 uint8_t *recvnew
, *sendnew
;
1550 if (size
<= iobuflen
)
1553 recvnew
= XMALLOC(MTYPE_OSPF6_MESSAGE
, size
);
1554 sendnew
= XMALLOC(MTYPE_OSPF6_MESSAGE
, size
);
1556 XFREE(MTYPE_OSPF6_MESSAGE
, recvbuf
);
1557 XFREE(MTYPE_OSPF6_MESSAGE
, sendbuf
);
1565 void ospf6_message_terminate(void)
1567 XFREE(MTYPE_OSPF6_MESSAGE
, recvbuf
);
1568 XFREE(MTYPE_OSPF6_MESSAGE
, sendbuf
);
1573 int ospf6_receive(struct thread
*thread
)
1577 struct in6_addr src
, dst
;
1579 struct iovec iovector
[2];
1580 struct ospf6_interface
*oi
;
1581 struct ospf6_header
*oh
;
1582 struct ospf6
*ospf6
;
1584 /* add next read thread */
1585 ospf6
= THREAD_ARG(thread
);
1586 sockfd
= THREAD_FD(thread
);
1588 thread_add_read(master
, ospf6_receive
, ospf6
, ospf6
->fd
,
1589 &ospf6
->t_ospf6_receive
);
1592 memset(&src
, 0, sizeof(src
));
1593 memset(&dst
, 0, sizeof(dst
));
1595 memset(recvbuf
, 0, iobuflen
);
1596 iovector
[0].iov_base
= recvbuf
;
1597 iovector
[0].iov_len
= iobuflen
;
1598 iovector
[1].iov_base
= NULL
;
1599 iovector
[1].iov_len
= 0;
1601 /* receive message */
1602 len
= ospf6_recvmsg(&src
, &dst
, &ifindex
, iovector
, sockfd
);
1603 if (len
> iobuflen
) {
1604 flog_err(EC_LIB_DEVELOPMENT
, "Excess message read");
1608 oi
= ospf6_interface_lookup_by_ifindex(ifindex
, ospf6
->vrf_id
);
1609 if (oi
== NULL
|| oi
->area
== NULL
1610 || CHECK_FLAG(oi
->flag
, OSPF6_INTERFACE_DISABLE
)) {
1611 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN
,
1613 zlog_debug("Message received on disabled interface");
1616 if (CHECK_FLAG(oi
->flag
, OSPF6_INTERFACE_PASSIVE
)) {
1617 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN
,
1619 zlog_debug("%s: Ignore message on passive interface %s",
1620 __func__
, oi
->interface
->name
);
1624 oh
= (struct ospf6_header
*)recvbuf
;
1625 if (ospf6_rxpacket_examin(oi
, oh
, len
) != MSG_OK
)
1628 /* Being here means, that no sizing/alignment issues were detected in
1629 the input packet. This renders the additional checks performed below
1630 and also in the type-specific dispatching functions a dead code,
1631 which can be dismissed in a cleanup-focused review round later. */
1634 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV_HDR
)) {
1635 zlog_debug("%s received on %s",
1636 lookup_msg(ospf6_message_type_str
, oh
->type
, NULL
),
1637 oi
->interface
->name
);
1638 zlog_debug(" src: %pI6", &src
);
1639 zlog_debug(" dst: %pI6", &dst
);
1642 case OSPF6_MESSAGE_TYPE_HELLO
:
1643 ospf6_hello_print(oh
, OSPF6_ACTION_RECV
);
1645 case OSPF6_MESSAGE_TYPE_DBDESC
:
1646 ospf6_dbdesc_print(oh
, OSPF6_ACTION_RECV
);
1648 case OSPF6_MESSAGE_TYPE_LSREQ
:
1649 ospf6_lsreq_print(oh
, OSPF6_ACTION_RECV
);
1651 case OSPF6_MESSAGE_TYPE_LSUPDATE
:
1652 ospf6_lsupdate_print(oh
, OSPF6_ACTION_RECV
);
1654 case OSPF6_MESSAGE_TYPE_LSACK
:
1655 ospf6_lsack_print(oh
, OSPF6_ACTION_RECV
);
1663 case OSPF6_MESSAGE_TYPE_HELLO
:
1664 ospf6_hello_recv(&src
, &dst
, oi
, oh
);
1667 case OSPF6_MESSAGE_TYPE_DBDESC
:
1668 ospf6_dbdesc_recv(&src
, &dst
, oi
, oh
);
1671 case OSPF6_MESSAGE_TYPE_LSREQ
:
1672 ospf6_lsreq_recv(&src
, &dst
, oi
, oh
);
1675 case OSPF6_MESSAGE_TYPE_LSUPDATE
:
1676 ospf6_lsupdate_recv(&src
, &dst
, oi
, oh
);
1679 case OSPF6_MESSAGE_TYPE_LSACK
:
1680 ospf6_lsack_recv(&src
, &dst
, oi
, oh
);
1690 static void ospf6_send(struct in6_addr
*src
, struct in6_addr
*dst
,
1691 struct ospf6_interface
*oi
, struct ospf6_header
*oh
)
1695 struct iovec iovector
[2];
1698 iovector
[0].iov_base
= (caddr_t
)oh
;
1699 iovector
[0].iov_len
= ntohs(oh
->length
);
1700 iovector
[1].iov_base
= NULL
;
1701 iovector
[1].iov_len
= 0;
1703 /* fill OSPF header */
1704 oh
->version
= OSPFV3_VERSION
;
1705 /* message type must be set before */
1706 /* message length must be set before */
1707 oh
->router_id
= oi
->area
->ospf6
->router_id
;
1708 oh
->area_id
= oi
->area
->area_id
;
1709 /* checksum is calculated by kernel */
1710 oh
->instance_id
= oi
->instance_id
;
1714 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, SEND_HDR
)) {
1716 inet_ntop(AF_INET6
, src
, srcname
, sizeof(srcname
));
1718 memset(srcname
, 0, sizeof(srcname
));
1719 zlog_debug("%s send on %s",
1720 lookup_msg(ospf6_message_type_str
, oh
->type
, NULL
),
1721 oi
->interface
->name
);
1722 zlog_debug(" src: %s", srcname
);
1723 zlog_debug(" dst: %pI6", dst
);
1726 case OSPF6_MESSAGE_TYPE_HELLO
:
1727 ospf6_hello_print(oh
, OSPF6_ACTION_RECV
);
1729 case OSPF6_MESSAGE_TYPE_DBDESC
:
1730 ospf6_dbdesc_print(oh
, OSPF6_ACTION_RECV
);
1732 case OSPF6_MESSAGE_TYPE_LSREQ
:
1733 ospf6_lsreq_print(oh
, OSPF6_ACTION_RECV
);
1735 case OSPF6_MESSAGE_TYPE_LSUPDATE
:
1736 ospf6_lsupdate_print(oh
, OSPF6_ACTION_RECV
);
1738 case OSPF6_MESSAGE_TYPE_LSACK
:
1739 ospf6_lsack_print(oh
, OSPF6_ACTION_RECV
);
1742 zlog_debug("Unknown message");
1749 if (oi
->area
->ospf6
->fd
!= -1) {
1750 len
= ospf6_sendmsg(src
, dst
, oi
->interface
->ifindex
, iovector
,
1751 oi
->area
->ospf6
->fd
);
1752 if (len
!= ntohs(oh
->length
))
1753 flog_err(EC_LIB_DEVELOPMENT
,
1754 "Could not send entire message");
1758 static uint32_t ospf6_packet_max(struct ospf6_interface
*oi
)
1760 assert(oi
->ifmtu
> sizeof(struct ip6_hdr
));
1761 return oi
->ifmtu
- (sizeof(struct ip6_hdr
));
1764 int ospf6_hello_send(struct thread
*thread
)
1766 struct ospf6_interface
*oi
;
1767 struct ospf6_header
*oh
;
1768 struct ospf6_hello
*hello
;
1770 struct listnode
*node
, *nnode
;
1771 struct ospf6_neighbor
*on
;
1773 oi
= (struct ospf6_interface
*)THREAD_ARG(thread
);
1774 oi
->thread_send_hello
= (struct thread
*)NULL
;
1776 if (oi
->state
<= OSPF6_INTERFACE_DOWN
) {
1777 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_HELLO
, SEND_HDR
))
1778 zlog_debug("Unable to send Hello on down interface %s",
1779 oi
->interface
->name
);
1783 if (iobuflen
== 0) {
1784 zlog_debug("Unable to send Hello on interface %s iobuflen is 0",
1785 oi
->interface
->name
);
1789 /* set next thread */
1790 thread_add_timer(master
, ospf6_hello_send
, oi
, oi
->hello_interval
,
1791 &oi
->thread_send_hello
);
1793 memset(sendbuf
, 0, iobuflen
);
1794 oh
= (struct ospf6_header
*)sendbuf
;
1795 hello
= (struct ospf6_hello
*)((caddr_t
)oh
1796 + sizeof(struct ospf6_header
));
1798 hello
->interface_id
= htonl(oi
->interface
->ifindex
);
1799 hello
->priority
= oi
->priority
;
1800 hello
->options
[0] = oi
->area
->options
[0];
1801 hello
->options
[1] = oi
->area
->options
[1];
1802 hello
->options
[2] = oi
->area
->options
[2];
1803 hello
->hello_interval
= htons(oi
->hello_interval
);
1804 hello
->dead_interval
= htons(oi
->dead_interval
);
1805 hello
->drouter
= oi
->drouter
;
1806 hello
->bdrouter
= oi
->bdrouter
;
1808 p
= (uint8_t *)((caddr_t
)hello
+ sizeof(struct ospf6_hello
));
1810 for (ALL_LIST_ELEMENTS(oi
->neighbor_list
, node
, nnode
, on
)) {
1811 if (on
->state
< OSPF6_NEIGHBOR_INIT
)
1814 if (p
- sendbuf
+ sizeof(uint32_t) > ospf6_packet_max(oi
)) {
1815 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_HELLO
,
1818 "sending Hello message: exceeds I/F MTU");
1822 memcpy(p
, &on
->router_id
, sizeof(uint32_t));
1823 p
+= sizeof(uint32_t);
1826 oh
->type
= OSPF6_MESSAGE_TYPE_HELLO
;
1827 oh
->length
= htons(p
- sendbuf
);
1831 ospf6_send(oi
->linklocal_addr
, &allspfrouters6
, oi
, oh
);
1835 int ospf6_dbdesc_send(struct thread
*thread
)
1837 struct ospf6_neighbor
*on
;
1838 struct ospf6_header
*oh
;
1839 struct ospf6_dbdesc
*dbdesc
;
1841 struct ospf6_lsa
*lsa
, *lsanext
;
1842 struct in6_addr
*dst
;
1844 on
= (struct ospf6_neighbor
*)THREAD_ARG(thread
);
1845 on
->thread_send_dbdesc
= (struct thread
*)NULL
;
1847 if (on
->state
< OSPF6_NEIGHBOR_EXSTART
) {
1848 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_DBDESC
, SEND_HDR
))
1850 "Quit to send DbDesc to neighbor %s state %s",
1851 on
->name
, ospf6_neighbor_state_str
[on
->state
]);
1855 /* set next thread if master */
1856 if (CHECK_FLAG(on
->dbdesc_bits
, OSPF6_DBDESC_MSBIT
))
1857 thread_add_timer(master
, ospf6_dbdesc_send
, on
,
1858 on
->ospf6_if
->rxmt_interval
,
1859 &on
->thread_send_dbdesc
);
1861 memset(sendbuf
, 0, iobuflen
);
1862 oh
= (struct ospf6_header
*)sendbuf
;
1863 dbdesc
= (struct ospf6_dbdesc
*)((caddr_t
)oh
1864 + sizeof(struct ospf6_header
));
1866 /* if this is initial one, initialize sequence number for DbDesc */
1867 if (CHECK_FLAG(on
->dbdesc_bits
, OSPF6_DBDESC_IBIT
)
1868 && (on
->dbdesc_seqnum
== 0)) {
1869 on
->dbdesc_seqnum
= monotime(NULL
);
1872 dbdesc
->options
[0] = on
->ospf6_if
->area
->options
[0];
1873 dbdesc
->options
[1] = on
->ospf6_if
->area
->options
[1];
1874 dbdesc
->options
[2] = on
->ospf6_if
->area
->options
[2];
1875 dbdesc
->ifmtu
= htons(on
->ospf6_if
->ifmtu
);
1876 dbdesc
->bits
= on
->dbdesc_bits
;
1877 dbdesc
->seqnum
= htonl(on
->dbdesc_seqnum
);
1879 /* if this is not initial one, set LSA headers in dbdesc */
1880 p
= (uint8_t *)((caddr_t
)dbdesc
+ sizeof(struct ospf6_dbdesc
));
1881 if (!CHECK_FLAG(on
->dbdesc_bits
, OSPF6_DBDESC_IBIT
)) {
1882 for (ALL_LSDB(on
->dbdesc_list
, lsa
, lsanext
)) {
1883 ospf6_lsa_age_update_to_send(lsa
,
1884 on
->ospf6_if
->transdelay
);
1887 if (p
- sendbuf
+ sizeof(struct ospf6_lsa_header
)
1888 > ospf6_packet_max(on
->ospf6_if
)) {
1889 ospf6_lsa_unlock(lsa
);
1891 ospf6_lsa_unlock(lsanext
);
1894 memcpy(p
, lsa
->header
, sizeof(struct ospf6_lsa_header
));
1895 p
+= sizeof(struct ospf6_lsa_header
);
1899 oh
->type
= OSPF6_MESSAGE_TYPE_DBDESC
;
1900 oh
->length
= htons(p
- sendbuf
);
1903 if (on
->ospf6_if
->state
== OSPF6_INTERFACE_POINTTOPOINT
)
1904 dst
= &allspfrouters6
;
1906 dst
= &on
->linklocal_addr
;
1908 on
->ospf6_if
->db_desc_out
++;
1910 ospf6_send(on
->ospf6_if
->linklocal_addr
, dst
, on
->ospf6_if
, oh
);
1915 int ospf6_dbdesc_send_newone(struct thread
*thread
)
1917 struct ospf6_neighbor
*on
;
1918 struct ospf6_lsa
*lsa
, *lsanext
;
1919 unsigned int size
= 0;
1921 on
= (struct ospf6_neighbor
*)THREAD_ARG(thread
);
1922 ospf6_lsdb_remove_all(on
->dbdesc_list
);
1924 /* move LSAs from summary_list to dbdesc_list (within neighbor
1926 so that ospf6_send_dbdesc () can send those LSAs */
1927 size
= sizeof(struct ospf6_lsa_header
) + sizeof(struct ospf6_dbdesc
);
1928 for (ALL_LSDB(on
->summary_list
, lsa
, lsanext
)) {
1929 /* if stub area then don't advertise AS-External LSAs */
1930 if (IS_AREA_STUB(on
->ospf6_if
->area
)
1931 && ntohs(lsa
->header
->type
) == OSPF6_LSTYPE_AS_EXTERNAL
) {
1932 ospf6_lsdb_remove(lsa
, on
->summary_list
);
1936 if (size
+ sizeof(struct ospf6_lsa_header
)
1937 > ospf6_packet_max(on
->ospf6_if
)) {
1938 ospf6_lsa_unlock(lsa
);
1940 ospf6_lsa_unlock(lsanext
);
1944 ospf6_lsdb_add(ospf6_lsa_copy(lsa
), on
->dbdesc_list
);
1945 ospf6_lsdb_remove(lsa
, on
->summary_list
);
1946 size
+= sizeof(struct ospf6_lsa_header
);
1949 if (on
->summary_list
->count
== 0)
1950 UNSET_FLAG(on
->dbdesc_bits
, OSPF6_DBDESC_MBIT
);
1952 /* If slave, More bit check must be done here */
1953 if (!CHECK_FLAG(on
->dbdesc_bits
, OSPF6_DBDESC_MSBIT
) && /* Slave */
1954 !CHECK_FLAG(on
->dbdesc_last
.bits
, OSPF6_DBDESC_MBIT
)
1955 && !CHECK_FLAG(on
->dbdesc_bits
, OSPF6_DBDESC_MBIT
))
1956 thread_add_event(master
, exchange_done
, on
, 0, NULL
);
1958 thread_execute(master
, ospf6_dbdesc_send
, on
, 0);
1962 int ospf6_lsreq_send(struct thread
*thread
)
1964 struct ospf6_neighbor
*on
;
1965 struct ospf6_header
*oh
;
1966 struct ospf6_lsreq_entry
*e
;
1968 struct ospf6_lsa
*lsa
, *lsanext
, *last_req
;
1970 on
= (struct ospf6_neighbor
*)THREAD_ARG(thread
);
1971 on
->thread_send_lsreq
= (struct thread
*)NULL
;
1973 /* LSReq will be sent only in ExStart or Loading */
1974 if (on
->state
!= OSPF6_NEIGHBOR_EXCHANGE
1975 && on
->state
!= OSPF6_NEIGHBOR_LOADING
) {
1976 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_LSREQ
, SEND_HDR
))
1977 zlog_debug("Quit to send LSReq to neighbor %s state %s",
1979 ospf6_neighbor_state_str
[on
->state
]);
1983 /* schedule loading_done if request list is empty */
1984 if (on
->request_list
->count
== 0) {
1985 thread_add_event(master
, loading_done
, on
, 0, NULL
);
1989 memset(sendbuf
, 0, iobuflen
);
1990 oh
= (struct ospf6_header
*)sendbuf
;
1993 /* set Request entries in lsreq */
1994 p
= (uint8_t *)((caddr_t
)oh
+ sizeof(struct ospf6_header
));
1995 for (ALL_LSDB(on
->request_list
, lsa
, lsanext
)) {
1997 if (p
- sendbuf
+ sizeof(struct ospf6_lsreq_entry
)
1998 > ospf6_packet_max(on
->ospf6_if
)) {
1999 ospf6_lsa_unlock(lsa
);
2001 ospf6_lsa_unlock(lsanext
);
2005 e
= (struct ospf6_lsreq_entry
*)p
;
2006 e
->type
= lsa
->header
->type
;
2007 e
->id
= lsa
->header
->id
;
2008 e
->adv_router
= lsa
->header
->adv_router
;
2009 p
+= sizeof(struct ospf6_lsreq_entry
);
2013 if (last_req
!= NULL
) {
2014 if (on
->last_ls_req
!= NULL
)
2015 on
->last_ls_req
= ospf6_lsa_unlock(on
->last_ls_req
);
2017 ospf6_lsa_lock(last_req
);
2018 on
->last_ls_req
= last_req
;
2021 oh
->type
= OSPF6_MESSAGE_TYPE_LSREQ
;
2022 oh
->length
= htons(p
- sendbuf
);
2024 on
->ospf6_if
->ls_req_out
++;
2026 if (on
->ospf6_if
->state
== OSPF6_INTERFACE_POINTTOPOINT
)
2027 ospf6_send(on
->ospf6_if
->linklocal_addr
, &allspfrouters6
,
2030 ospf6_send(on
->ospf6_if
->linklocal_addr
, &on
->linklocal_addr
,
2033 /* set next thread */
2034 if (on
->request_list
->count
!= 0) {
2035 on
->thread_send_lsreq
= NULL
;
2036 thread_add_timer(master
, ospf6_lsreq_send
, on
,
2037 on
->ospf6_if
->rxmt_interval
,
2038 &on
->thread_send_lsreq
);
2044 static void ospf6_send_lsupdate(struct ospf6_neighbor
*on
,
2045 struct ospf6_interface
*oi
,
2046 struct ospf6_header
*oh
)
2050 on
->ospf6_if
->ls_upd_out
++;
2052 if ((on
->ospf6_if
->state
== OSPF6_INTERFACE_POINTTOPOINT
)
2053 || (on
->ospf6_if
->state
== OSPF6_INTERFACE_DR
)
2054 || (on
->ospf6_if
->state
== OSPF6_INTERFACE_BDR
)) {
2055 ospf6_send(on
->ospf6_if
->linklocal_addr
,
2056 &allspfrouters6
, on
->ospf6_if
, oh
);
2058 ospf6_send(on
->ospf6_if
->linklocal_addr
,
2059 &on
->linklocal_addr
, on
->ospf6_if
, oh
);
2065 if ((oi
->state
== OSPF6_INTERFACE_POINTTOPOINT
)
2066 || (oi
->state
== OSPF6_INTERFACE_DR
)
2067 || (oi
->state
== OSPF6_INTERFACE_BDR
)) {
2068 ospf6_send(oi
->linklocal_addr
, &allspfrouters6
, oi
, oh
);
2070 ospf6_send(oi
->linklocal_addr
, &alldrouters6
, oi
, oh
);
2075 int ospf6_lsupdate_send_neighbor(struct thread
*thread
)
2077 struct ospf6_neighbor
*on
;
2078 struct ospf6_header
*oh
;
2079 struct ospf6_lsupdate
*lsupdate
;
2082 struct ospf6_lsa
*lsa
, *lsanext
;
2084 on
= (struct ospf6_neighbor
*)THREAD_ARG(thread
);
2085 on
->thread_send_lsupdate
= (struct thread
*)NULL
;
2087 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_LSUPDATE
, SEND_HDR
))
2088 zlog_debug("LSUpdate to neighbor %s", on
->name
);
2090 if (on
->state
< OSPF6_NEIGHBOR_EXCHANGE
) {
2091 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_LSUPDATE
,
2093 zlog_debug("Quit to send (neighbor state %s)",
2094 ospf6_neighbor_state_str
[on
->state
]);
2098 memset(sendbuf
, 0, iobuflen
);
2099 oh
= (struct ospf6_header
*)sendbuf
;
2100 lsupdate
= (struct ospf6_lsupdate
*)((caddr_t
)oh
2101 + sizeof(struct ospf6_header
));
2103 p
= (uint8_t *)((caddr_t
)lsupdate
+ sizeof(struct ospf6_lsupdate
));
2106 /* lsupdate_list lists those LSA which doesn't need to be
2107 retransmitted. remove those from the list */
2108 for (ALL_LSDB(on
->lsupdate_list
, lsa
, lsanext
)) {
2110 if ((p
- sendbuf
+ (unsigned int)OSPF6_LSA_SIZE(lsa
->header
))
2111 > ospf6_packet_max(on
->ospf6_if
)) {
2113 oh
->type
= OSPF6_MESSAGE_TYPE_LSUPDATE
;
2114 oh
->length
= htons(p
- sendbuf
);
2115 lsupdate
->lsa_number
= htonl(lsa_cnt
);
2117 ospf6_send_lsupdate(on
, NULL
, oh
);
2119 memset(sendbuf
, 0, iobuflen
);
2120 oh
= (struct ospf6_header
*)sendbuf
;
2121 lsupdate
= (struct ospf6_lsupdate
2126 p
= (uint8_t *)((caddr_t
)lsupdate
2133 ospf6_lsa_age_update_to_send(lsa
, on
->ospf6_if
->transdelay
);
2134 memcpy(p
, lsa
->header
, OSPF6_LSA_SIZE(lsa
->header
));
2135 p
+= OSPF6_LSA_SIZE(lsa
->header
);
2138 assert(lsa
->lock
== 2);
2139 ospf6_lsdb_remove(lsa
, on
->lsupdate_list
);
2143 oh
->type
= OSPF6_MESSAGE_TYPE_LSUPDATE
;
2144 oh
->length
= htons(p
- sendbuf
);
2145 lsupdate
->lsa_number
= htonl(lsa_cnt
);
2146 ospf6_send_lsupdate(on
, NULL
, oh
);
2149 /* The addresses used for retransmissions are different from those sent
2151 first time and so we need to separate them here.
2153 memset(sendbuf
, 0, iobuflen
);
2154 oh
= (struct ospf6_header
*)sendbuf
;
2155 lsupdate
= (struct ospf6_lsupdate
*)((caddr_t
)oh
2156 + sizeof(struct ospf6_header
));
2157 p
= (uint8_t *)((caddr_t
)lsupdate
+ sizeof(struct ospf6_lsupdate
));
2160 for (ALL_LSDB(on
->retrans_list
, lsa
, lsanext
)) {
2162 if ((p
- sendbuf
+ (unsigned int)OSPF6_LSA_SIZE(lsa
->header
))
2163 > ospf6_packet_max(on
->ospf6_if
)) {
2165 oh
->type
= OSPF6_MESSAGE_TYPE_LSUPDATE
;
2166 oh
->length
= htons(p
- sendbuf
);
2167 lsupdate
->lsa_number
= htonl(lsa_cnt
);
2169 if (on
->ospf6_if
->state
2170 == OSPF6_INTERFACE_POINTTOPOINT
) {
2171 ospf6_send(on
->ospf6_if
->linklocal_addr
,
2175 ospf6_send(on
->ospf6_if
->linklocal_addr
,
2176 &on
->linklocal_addr
,
2180 memset(sendbuf
, 0, iobuflen
);
2181 oh
= (struct ospf6_header
*)sendbuf
;
2182 lsupdate
= (struct ospf6_lsupdate
2186 p
= (uint8_t *)((caddr_t
)lsupdate
2193 ospf6_lsa_age_update_to_send(lsa
, on
->ospf6_if
->transdelay
);
2194 memcpy(p
, lsa
->header
, OSPF6_LSA_SIZE(lsa
->header
));
2195 p
+= OSPF6_LSA_SIZE(lsa
->header
);
2200 oh
->type
= OSPF6_MESSAGE_TYPE_LSUPDATE
;
2201 oh
->length
= htons(p
- sendbuf
);
2202 lsupdate
->lsa_number
= htonl(lsa_cnt
);
2204 if (on
->ospf6_if
->state
== OSPF6_INTERFACE_POINTTOPOINT
)
2205 ospf6_send(on
->ospf6_if
->linklocal_addr
,
2206 &allspfrouters6
, on
->ospf6_if
, oh
);
2208 ospf6_send(on
->ospf6_if
->linklocal_addr
,
2209 &on
->linklocal_addr
, on
->ospf6_if
, oh
);
2212 if (on
->lsupdate_list
->count
!= 0) {
2213 on
->thread_send_lsupdate
= NULL
;
2214 thread_add_event(master
, ospf6_lsupdate_send_neighbor
, on
, 0,
2215 &on
->thread_send_lsupdate
);
2216 } else if (on
->retrans_list
->count
!= 0) {
2217 on
->thread_send_lsupdate
= NULL
;
2218 thread_add_timer(master
, ospf6_lsupdate_send_neighbor
, on
,
2219 on
->ospf6_if
->rxmt_interval
,
2220 &on
->thread_send_lsupdate
);
2225 int ospf6_lsupdate_send_neighbor_now(struct ospf6_neighbor
*on
,
2226 struct ospf6_lsa
*lsa
)
2228 struct ospf6_header
*oh
;
2229 struct ospf6_lsupdate
*lsupdate
;
2233 memset(sendbuf
, 0, iobuflen
);
2234 oh
= (struct ospf6_header
*)sendbuf
;
2235 lsupdate
= (struct ospf6_lsupdate
*)((caddr_t
)oh
2236 + sizeof(struct ospf6_header
));
2238 p
= (uint8_t *)((caddr_t
)lsupdate
+ sizeof(struct ospf6_lsupdate
));
2239 ospf6_lsa_age_update_to_send(lsa
, on
->ospf6_if
->transdelay
);
2240 memcpy(p
, lsa
->header
, OSPF6_LSA_SIZE(lsa
->header
));
2241 p
+= OSPF6_LSA_SIZE(lsa
->header
);
2244 oh
->type
= OSPF6_MESSAGE_TYPE_LSUPDATE
;
2245 oh
->length
= htons(p
- sendbuf
);
2246 lsupdate
->lsa_number
= htonl(lsa_cnt
);
2248 if (IS_OSPF6_DEBUG_FLOODING
2249 || IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_LSUPDATE
, SEND_HDR
))
2250 zlog_debug("%s: Send lsupdate with lsa %s (age %u)", __func__
,
2251 lsa
->name
, ntohs(lsa
->header
->age
));
2253 ospf6_send_lsupdate(on
, NULL
, oh
);
2258 int ospf6_lsupdate_send_interface(struct thread
*thread
)
2260 struct ospf6_interface
*oi
;
2261 struct ospf6_header
*oh
;
2262 struct ospf6_lsupdate
*lsupdate
;
2265 struct ospf6_lsa
*lsa
, *lsanext
;
2267 oi
= (struct ospf6_interface
*)THREAD_ARG(thread
);
2268 oi
->thread_send_lsupdate
= (struct thread
*)NULL
;
2270 if (oi
->state
<= OSPF6_INTERFACE_WAITING
) {
2271 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_LSUPDATE
,
2274 "Quit to send LSUpdate to interface %s state %s",
2275 oi
->interface
->name
,
2276 ospf6_interface_state_str
[oi
->state
]);
2280 /* if we have nothing to send, return */
2281 if (oi
->lsupdate_list
->count
== 0)
2284 memset(sendbuf
, 0, iobuflen
);
2285 oh
= (struct ospf6_header
*)sendbuf
;
2286 lsupdate
= (struct ospf6_lsupdate
*)((caddr_t
)oh
2287 + sizeof(struct ospf6_header
));
2289 p
= (uint8_t *)((caddr_t
)lsupdate
+ sizeof(struct ospf6_lsupdate
));
2292 for (ALL_LSDB(oi
->lsupdate_list
, lsa
, lsanext
)) {
2294 if ((p
- sendbuf
+ ((unsigned int)OSPF6_LSA_SIZE(lsa
->header
)))
2295 > ospf6_packet_max(oi
)) {
2297 oh
->type
= OSPF6_MESSAGE_TYPE_LSUPDATE
;
2298 oh
->length
= htons(p
- sendbuf
);
2299 lsupdate
->lsa_number
= htonl(lsa_cnt
);
2301 ospf6_send_lsupdate(NULL
, oi
, oh
);
2302 if (IS_OSPF6_DEBUG_MESSAGE(
2303 OSPF6_MESSAGE_TYPE_LSUPDATE
, SEND
))
2304 zlog_debug("%s: LSUpdate length %d",
2305 __func__
, ntohs(oh
->length
));
2307 memset(sendbuf
, 0, iobuflen
);
2308 oh
= (struct ospf6_header
*)sendbuf
;
2309 lsupdate
= (struct ospf6_lsupdate
2314 p
= (uint8_t *)((caddr_t
)lsupdate
2321 ospf6_lsa_age_update_to_send(lsa
, oi
->transdelay
);
2322 memcpy(p
, lsa
->header
, OSPF6_LSA_SIZE(lsa
->header
));
2323 p
+= OSPF6_LSA_SIZE(lsa
->header
);
2326 assert(lsa
->lock
== 2);
2327 ospf6_lsdb_remove(lsa
, oi
->lsupdate_list
);
2331 oh
->type
= OSPF6_MESSAGE_TYPE_LSUPDATE
;
2332 oh
->length
= htons(p
- sendbuf
);
2333 lsupdate
->lsa_number
= htonl(lsa_cnt
);
2335 ospf6_send_lsupdate(NULL
, oi
, oh
);
2338 if (oi
->lsupdate_list
->count
> 0) {
2339 oi
->thread_send_lsupdate
= NULL
;
2340 thread_add_event(master
, ospf6_lsupdate_send_interface
, oi
, 0,
2341 &oi
->thread_send_lsupdate
);
2347 int ospf6_lsack_send_neighbor(struct thread
*thread
)
2349 struct ospf6_neighbor
*on
;
2350 struct ospf6_header
*oh
;
2352 struct ospf6_lsa
*lsa
, *lsanext
;
2355 on
= (struct ospf6_neighbor
*)THREAD_ARG(thread
);
2356 on
->thread_send_lsack
= (struct thread
*)NULL
;
2358 if (on
->state
< OSPF6_NEIGHBOR_EXCHANGE
) {
2359 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_LSACK
, SEND_HDR
))
2360 zlog_debug("Quit to send LSAck to neighbor %s state %s",
2362 ospf6_neighbor_state_str
[on
->state
]);
2366 /* if we have nothing to send, return */
2367 if (on
->lsack_list
->count
== 0)
2370 memset(sendbuf
, 0, iobuflen
);
2371 oh
= (struct ospf6_header
*)sendbuf
;
2373 p
= (uint8_t *)((caddr_t
)oh
+ sizeof(struct ospf6_header
));
2375 for (ALL_LSDB(on
->lsack_list
, lsa
, lsanext
)) {
2377 if (p
- sendbuf
+ sizeof(struct ospf6_lsa_header
)
2378 > ospf6_packet_max(on
->ospf6_if
)) {
2379 /* if we run out of packet size/space here,
2380 better to try again soon. */
2382 oh
->type
= OSPF6_MESSAGE_TYPE_LSACK
;
2383 oh
->length
= htons(p
- sendbuf
);
2385 on
->ospf6_if
->ls_ack_out
++;
2387 ospf6_send(on
->ospf6_if
->linklocal_addr
,
2388 &on
->linklocal_addr
, on
->ospf6_if
,
2391 memset(sendbuf
, 0, iobuflen
);
2392 oh
= (struct ospf6_header
*)sendbuf
;
2393 p
= (uint8_t *)((caddr_t
)oh
2394 + sizeof(struct ospf6_header
));
2399 ospf6_lsa_age_update_to_send(lsa
, on
->ospf6_if
->transdelay
);
2400 memcpy(p
, lsa
->header
, sizeof(struct ospf6_lsa_header
));
2401 p
+= sizeof(struct ospf6_lsa_header
);
2403 assert(lsa
->lock
== 2);
2404 ospf6_lsdb_remove(lsa
, on
->lsack_list
);
2409 oh
->type
= OSPF6_MESSAGE_TYPE_LSACK
;
2410 oh
->length
= htons(p
- sendbuf
);
2412 on
->ospf6_if
->ls_ack_out
++;
2414 ospf6_send(on
->ospf6_if
->linklocal_addr
, &on
->linklocal_addr
,
2418 if (on
->lsack_list
->count
> 0)
2419 thread_add_event(master
, ospf6_lsack_send_neighbor
, on
, 0,
2420 &on
->thread_send_lsack
);
2425 int ospf6_lsack_send_interface(struct thread
*thread
)
2427 struct ospf6_interface
*oi
;
2428 struct ospf6_header
*oh
;
2430 struct ospf6_lsa
*lsa
, *lsanext
;
2433 oi
= (struct ospf6_interface
*)THREAD_ARG(thread
);
2434 oi
->thread_send_lsack
= (struct thread
*)NULL
;
2436 if (oi
->state
<= OSPF6_INTERFACE_WAITING
) {
2437 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_LSACK
, SEND_HDR
))
2439 "Quit to send LSAck to interface %s state %s",
2440 oi
->interface
->name
,
2441 ospf6_interface_state_str
[oi
->state
]);
2445 /* if we have nothing to send, return */
2446 if (oi
->lsack_list
->count
== 0)
2449 memset(sendbuf
, 0, iobuflen
);
2450 oh
= (struct ospf6_header
*)sendbuf
;
2452 p
= (uint8_t *)((caddr_t
)oh
+ sizeof(struct ospf6_header
));
2454 for (ALL_LSDB(oi
->lsack_list
, lsa
, lsanext
)) {
2456 if (p
- sendbuf
+ sizeof(struct ospf6_lsa_header
)
2457 > ospf6_packet_max(oi
)) {
2458 /* if we run out of packet size/space here,
2459 better to try again soon. */
2460 THREAD_OFF(oi
->thread_send_lsack
);
2461 thread_add_event(master
, ospf6_lsack_send_interface
, oi
,
2462 0, &oi
->thread_send_lsack
);
2464 ospf6_lsa_unlock(lsa
);
2466 ospf6_lsa_unlock(lsanext
);
2470 ospf6_lsa_age_update_to_send(lsa
, oi
->transdelay
);
2471 memcpy(p
, lsa
->header
, sizeof(struct ospf6_lsa_header
));
2472 p
+= sizeof(struct ospf6_lsa_header
);
2474 assert(lsa
->lock
== 2);
2475 ospf6_lsdb_remove(lsa
, oi
->lsack_list
);
2480 oh
->type
= OSPF6_MESSAGE_TYPE_LSACK
;
2481 oh
->length
= htons(p
- sendbuf
);
2483 if ((oi
->state
== OSPF6_INTERFACE_POINTTOPOINT
)
2484 || (oi
->state
== OSPF6_INTERFACE_DR
)
2485 || (oi
->state
== OSPF6_INTERFACE_BDR
))
2486 ospf6_send(oi
->linklocal_addr
, &allspfrouters6
, oi
, oh
);
2488 ospf6_send(oi
->linklocal_addr
, &alldrouters6
, oi
, oh
);
2491 if (oi
->lsack_list
->count
> 0)
2492 thread_add_event(master
, ospf6_lsack_send_interface
, oi
, 0,
2493 &oi
->thread_send_lsack
);
2500 DEFUN(debug_ospf6_message
, debug_ospf6_message_cmd
,
2501 "debug ospf6 message <unknown|hello|dbdesc|lsreq|lsupdate|lsack|all> [<send|recv|send-hdr|recv-hdr>]",
2503 "Debug OSPFv3 message\n"
2504 "Debug Unknown message\n"
2505 "Debug Hello message\n"
2506 "Debug Database Description message\n"
2507 "Debug Link State Request message\n"
2508 "Debug Link State Update message\n"
2509 "Debug Link State Acknowledgement message\n"
2510 "Debug All message\n"
2511 "Debug only sending message, entire packet\n"
2512 "Debug only receiving message, entire packet\n"
2513 "Debug only sending message, header only\n"
2514 "Debug only receiving message, header only\n")
2517 int idx_send_recv
= 4;
2518 unsigned char level
= 0;
2523 if (!strncmp(argv
[idx_packet
]->arg
, "u", 1))
2524 type
= OSPF6_MESSAGE_TYPE_UNKNOWN
;
2525 else if (!strncmp(argv
[idx_packet
]->arg
, "h", 1))
2526 type
= OSPF6_MESSAGE_TYPE_HELLO
;
2527 else if (!strncmp(argv
[idx_packet
]->arg
, "d", 1))
2528 type
= OSPF6_MESSAGE_TYPE_DBDESC
;
2529 else if (!strncmp(argv
[idx_packet
]->arg
, "lsr", 3))
2530 type
= OSPF6_MESSAGE_TYPE_LSREQ
;
2531 else if (!strncmp(argv
[idx_packet
]->arg
, "lsu", 3))
2532 type
= OSPF6_MESSAGE_TYPE_LSUPDATE
;
2533 else if (!strncmp(argv
[idx_packet
]->arg
, "lsa", 3))
2534 type
= OSPF6_MESSAGE_TYPE_LSACK
;
2535 else if (!strncmp(argv
[idx_packet
]->arg
, "a", 1))
2536 type
= OSPF6_MESSAGE_TYPE_ALL
;
2539 level
= OSPF6_DEBUG_MESSAGE_SEND
| OSPF6_DEBUG_MESSAGE_RECV
;
2540 else if (!strncmp(argv
[idx_send_recv
]->arg
, "send-h", 6))
2541 level
= OSPF6_DEBUG_MESSAGE_SEND_HDR
;
2542 else if (!strncmp(argv
[idx_send_recv
]->arg
, "s", 1))
2543 level
= OSPF6_DEBUG_MESSAGE_SEND
;
2544 else if (!strncmp(argv
[idx_send_recv
]->arg
, "recv-h", 6))
2545 level
= OSPF6_DEBUG_MESSAGE_RECV_HDR
;
2546 else if (!strncmp(argv
[idx_send_recv
]->arg
, "r", 1))
2547 level
= OSPF6_DEBUG_MESSAGE_RECV
;
2549 if (type
== OSPF6_MESSAGE_TYPE_ALL
) {
2550 for (i
= 0; i
< 6; i
++)
2551 OSPF6_DEBUG_MESSAGE_ON(i
, level
);
2553 OSPF6_DEBUG_MESSAGE_ON(type
, level
);
2558 DEFUN(no_debug_ospf6_message
, no_debug_ospf6_message_cmd
,
2559 "no debug ospf6 message <unknown|hello|dbdesc|lsreq|lsupdate|lsack|all> [<send|recv|send-hdr|recv-hdr>]",
2560 NO_STR DEBUG_STR OSPF6_STR
2561 "Debug OSPFv3 message\n"
2562 "Debug Unknown message\n"
2563 "Debug Hello message\n"
2564 "Debug Database Description message\n"
2565 "Debug Link State Request message\n"
2566 "Debug Link State Update message\n"
2567 "Debug Link State Acknowledgement message\n"
2568 "Debug All message\n"
2569 "Debug only sending message, entire pkt\n"
2570 "Debug only receiving message, entire pkt\n"
2571 "Debug only sending message, header only\n"
2572 "Debug only receiving message, header only\n")
2575 int idx_send_recv
= 5;
2576 unsigned char level
= 0;
2581 if (!strncmp(argv
[idx_packet
]->arg
, "u", 1))
2582 type
= OSPF6_MESSAGE_TYPE_UNKNOWN
;
2583 else if (!strncmp(argv
[idx_packet
]->arg
, "h", 1))
2584 type
= OSPF6_MESSAGE_TYPE_HELLO
;
2585 else if (!strncmp(argv
[idx_packet
]->arg
, "d", 1))
2586 type
= OSPF6_MESSAGE_TYPE_DBDESC
;
2587 else if (!strncmp(argv
[idx_packet
]->arg
, "lsr", 3))
2588 type
= OSPF6_MESSAGE_TYPE_LSREQ
;
2589 else if (!strncmp(argv
[idx_packet
]->arg
, "lsu", 3))
2590 type
= OSPF6_MESSAGE_TYPE_LSUPDATE
;
2591 else if (!strncmp(argv
[idx_packet
]->arg
, "lsa", 3))
2592 type
= OSPF6_MESSAGE_TYPE_LSACK
;
2593 else if (!strncmp(argv
[idx_packet
]->arg
, "a", 1))
2594 type
= OSPF6_MESSAGE_TYPE_ALL
;
2597 level
= OSPF6_DEBUG_MESSAGE_SEND
| OSPF6_DEBUG_MESSAGE_RECV
2598 | OSPF6_DEBUG_MESSAGE_SEND_HDR
2599 | OSPF6_DEBUG_MESSAGE_RECV_HDR
;
2600 else if (!strncmp(argv
[idx_send_recv
]->arg
, "send-h", 6))
2601 level
= OSPF6_DEBUG_MESSAGE_SEND_HDR
;
2602 else if (!strncmp(argv
[idx_send_recv
]->arg
, "s", 1))
2603 level
= OSPF6_DEBUG_MESSAGE_SEND
;
2604 else if (!strncmp(argv
[idx_send_recv
]->arg
, "recv-h", 6))
2605 level
= OSPF6_DEBUG_MESSAGE_RECV_HDR
;
2606 else if (!strncmp(argv
[idx_send_recv
]->arg
, "r", 1))
2607 level
= OSPF6_DEBUG_MESSAGE_RECV
;
2609 if (type
== OSPF6_MESSAGE_TYPE_ALL
) {
2610 for (i
= 0; i
< 6; i
++)
2611 OSPF6_DEBUG_MESSAGE_OFF(i
, level
);
2613 OSPF6_DEBUG_MESSAGE_OFF(type
, level
);
2619 int config_write_ospf6_debug_message(struct vty
*vty
)
2621 const char *type_str
[] = {"unknown", "hello", "dbdesc",
2622 "lsreq", "lsupdate", "lsack"};
2623 unsigned char s
= 0, r
= 0, sh
= 0, rh
= 0;
2626 for (i
= 0; i
< 6; i
++) {
2627 if (IS_OSPF6_DEBUG_MESSAGE_ENABLED(i
, SEND
))
2629 if (IS_OSPF6_DEBUG_MESSAGE_ENABLED(i
, RECV
))
2633 for (i
= 0; i
< 6; i
++) {
2634 if (IS_OSPF6_DEBUG_MESSAGE_ENABLED(i
, SEND_HDR
))
2636 if (IS_OSPF6_DEBUG_MESSAGE_ENABLED(i
, RECV_HDR
))
2640 if (s
== 0x3f && r
== 0x3f) {
2641 vty_out(vty
, "debug ospf6 message all\n");
2645 if (s
== 0x3f && r
== 0) {
2646 vty_out(vty
, "debug ospf6 message all send\n");
2648 } else if (s
== 0 && r
== 0x3f) {
2649 vty_out(vty
, "debug ospf6 message all recv\n");
2653 if (sh
== 0x3f && rh
== 0) {
2654 vty_out(vty
, "debug ospf6 message all send-hdr\n");
2656 } else if (sh
== 0 && rh
== 0x3f) {
2657 vty_out(vty
, "debug ospf6 message all recv-hdr\n");
2661 /* Unknown message is logged by default */
2662 if (!IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN
, SEND
)
2663 && !IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN
, RECV
))
2664 vty_out(vty
, "no debug ospf6 message unknown\n");
2665 else if (!IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN
, SEND
))
2666 vty_out(vty
, "no debug ospf6 message unknown send\n");
2667 else if (!IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN
, RECV
))
2668 vty_out(vty
, "no debug ospf6 message unknown recv\n");
2670 for (i
= 1; i
< 6; i
++) {
2671 if (IS_OSPF6_DEBUG_MESSAGE_ENABLED(i
, SEND
)
2672 && IS_OSPF6_DEBUG_MESSAGE_ENABLED(i
, RECV
))
2673 vty_out(vty
, "debug ospf6 message %s\n", type_str
[i
]);
2674 else if (IS_OSPF6_DEBUG_MESSAGE_ENABLED(i
, SEND
))
2675 vty_out(vty
, "debug ospf6 message %s send\n",
2677 else if (IS_OSPF6_DEBUG_MESSAGE_ENABLED(i
, RECV
))
2678 vty_out(vty
, "debug ospf6 message %s recv\n",
2680 else if (IS_OSPF6_DEBUG_MESSAGE_ENABLED(i
, SEND_HDR
)
2681 && IS_OSPF6_DEBUG_MESSAGE_ENABLED(i
, RECV_HDR
))
2682 vty_out(vty
, "debug ospf6 message %s; header only\n",
2684 else if (IS_OSPF6_DEBUG_MESSAGE_ENABLED(i
, RECV_HDR
))
2685 vty_out(vty
, "debug ospf6 message %s recv-hdr\n",
2687 else if (IS_OSPF6_DEBUG_MESSAGE_ENABLED(i
, SEND_HDR
))
2688 vty_out(vty
, "debug ospf6 message %s send-hdr\n",
2695 void install_element_ospf6_debug_message(void)
2697 install_element(ENABLE_NODE
, &debug_ospf6_message_cmd
);
2698 install_element(ENABLE_NODE
, &no_debug_ospf6_message_cmd
);
2699 install_element(CONFIG_NODE
, &debug_ospf6_message_cmd
);
2700 install_element(CONFIG_NODE
, &no_debug_ospf6_message_cmd
);