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 || 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
)) {
666 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV_HDR
))
667 zlog_debug("Master/Slave bit mismatch");
668 thread_add_event(master
, seqnumber_mismatch
, on
, 0,
673 if (CHECK_FLAG(dbdesc
->bits
, OSPF6_DBDESC_IBIT
)) {
674 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV_HDR
))
675 zlog_debug("Initialize bit mismatch");
676 thread_add_event(master
, seqnumber_mismatch
, on
, 0,
681 if (memcmp(on
->options
, dbdesc
->options
, sizeof(on
->options
))) {
682 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV_HDR
))
683 zlog_debug("Option field mismatch");
684 thread_add_event(master
, seqnumber_mismatch
, on
, 0,
689 if (ntohl(dbdesc
->seqnum
) != on
->dbdesc_seqnum
+ 1) {
690 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV_HDR
))
692 "Sequence number mismatch (%#lx expected)",
693 (unsigned long)on
->dbdesc_seqnum
+ 1);
694 thread_add_event(master
, seqnumber_mismatch
, on
, 0,
700 case OSPF6_NEIGHBOR_LOADING
:
701 case OSPF6_NEIGHBOR_FULL
:
702 if (!memcmp(dbdesc
, &on
->dbdesc_last
,
703 sizeof(struct ospf6_dbdesc
))) {
704 /* Duplicated DatabaseDescription causes slave to
706 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV_HDR
))
708 "Duplicated dbdesc causes retransmit");
709 THREAD_OFF(on
->thread_send_dbdesc
);
710 thread_add_event(master
, ospf6_dbdesc_send
, on
, 0,
711 &on
->thread_send_dbdesc
);
715 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV_HDR
))
716 zlog_debug("Not duplicate dbdesc in state %s",
717 ospf6_neighbor_state_str
[on
->state
]);
718 thread_add_event(master
, seqnumber_mismatch
, on
, 0, NULL
);
726 /* Process LSA headers */
727 for (p
= (char *)((caddr_t
)dbdesc
+ sizeof(struct ospf6_dbdesc
));
728 p
+ sizeof(struct ospf6_lsa_header
) <= OSPF6_MESSAGE_END(oh
);
729 p
+= sizeof(struct ospf6_lsa_header
)) {
730 struct ospf6_lsa
*his
, *mine
;
731 struct ospf6_lsdb
*lsdb
= NULL
;
733 his
= ospf6_lsa_create_headeronly((struct ospf6_lsa_header
*)p
);
735 switch (OSPF6_LSA_SCOPE(his
->header
->type
)) {
736 case OSPF6_SCOPE_LINKLOCAL
:
737 lsdb
= on
->ospf6_if
->lsdb
;
739 case OSPF6_SCOPE_AREA
:
740 lsdb
= on
->ospf6_if
->area
->lsdb
;
743 lsdb
= on
->ospf6_if
->area
->ospf6
->lsdb
;
745 case OSPF6_SCOPE_RESERVED
:
746 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
747 zlog_debug("Ignoring LSA of reserved scope");
748 ospf6_lsa_delete(his
);
753 if (OSPF6_LSA_SCOPE(his
->header
->type
) == OSPF6_SCOPE_AS
754 && (IS_AREA_STUB(on
->ospf6_if
->area
)
755 || IS_AREA_NSSA(on
->ospf6_if
->area
))) {
756 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
757 zlog_debug("E-bit mismatch with LSA Headers");
758 ospf6_lsa_delete(his
);
759 thread_add_event(master
, seqnumber_mismatch
, on
, 0,
764 mine
= ospf6_lsdb_lookup(his
->header
->type
, his
->header
->id
,
765 his
->header
->adv_router
, lsdb
);
766 if (mine
== NULL
|| ospf6_lsa_compare(his
, mine
) < 0) {
767 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
768 zlog_debug("Add request-list: %s", his
->name
);
769 ospf6_lsdb_add(ospf6_lsa_copy(his
), on
->request_list
);
771 ospf6_lsa_delete(his
);
774 assert(p
== OSPF6_MESSAGE_END(oh
));
776 /* Set sequence number to Master's */
777 on
->dbdesc_seqnum
= ntohl(dbdesc
->seqnum
);
779 /* schedule send lsreq */
780 if (on
->request_list
->count
)
781 thread_add_event(master
, ospf6_lsreq_send
, on
, 0,
782 &on
->thread_send_lsreq
);
784 THREAD_OFF(on
->thread_send_dbdesc
);
785 thread_add_event(master
, ospf6_dbdesc_send_newone
, on
, 0,
786 &on
->thread_send_dbdesc
);
788 /* save last received dbdesc */
789 memcpy(&on
->dbdesc_last
, dbdesc
, sizeof(struct ospf6_dbdesc
));
792 static void ospf6_dbdesc_recv(struct in6_addr
*src
, struct in6_addr
*dst
,
793 struct ospf6_interface
*oi
,
794 struct ospf6_header
*oh
)
796 struct ospf6_neighbor
*on
;
797 struct ospf6_dbdesc
*dbdesc
;
799 on
= ospf6_neighbor_lookup(oh
->router_id
, oi
);
801 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV_HDR
))
802 zlog_debug("Neighbor not found, ignore");
806 dbdesc
= (struct ospf6_dbdesc
*)((caddr_t
)oh
807 + sizeof(struct ospf6_header
));
809 /* Interface MTU check */
810 if (!oi
->mtu_ignore
&& ntohs(dbdesc
->ifmtu
) != oi
->ifmtu
) {
811 zlog_warn("VRF %s: I/F %s MTU mismatch (my %d rcvd %d)",
812 vrf_id_to_name(oi
->interface
->vrf_id
),
813 oi
->interface
->name
, oi
->ifmtu
, ntohs(dbdesc
->ifmtu
));
817 if (dbdesc
->reserved1
|| dbdesc
->reserved2
) {
818 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV_HDR
))
820 "Non-0 reserved field in %s's DbDesc, correct",
822 dbdesc
->reserved1
= 0;
823 dbdesc
->reserved2
= 0;
828 if (ntohl(oh
->router_id
) < ntohl(oi
->area
->ospf6
->router_id
))
829 ospf6_dbdesc_recv_master(oh
, on
);
830 else if (ntohl(oi
->area
->ospf6
->router_id
) < ntohl(oh
->router_id
))
831 ospf6_dbdesc_recv_slave(oh
, on
);
833 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV_HDR
))
834 zlog_debug("Can't decide which is master, ignore");
838 static void ospf6_lsreq_recv(struct in6_addr
*src
, struct in6_addr
*dst
,
839 struct ospf6_interface
*oi
,
840 struct ospf6_header
*oh
)
842 struct ospf6_neighbor
*on
;
844 struct ospf6_lsreq_entry
*e
;
845 struct ospf6_lsdb
*lsdb
= NULL
;
846 struct ospf6_lsa
*lsa
;
848 on
= ospf6_neighbor_lookup(oh
->router_id
, oi
);
850 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV_HDR
))
851 zlog_debug("Neighbor not found, ignore");
855 if (on
->state
!= OSPF6_NEIGHBOR_EXCHANGE
856 && on
->state
!= OSPF6_NEIGHBOR_LOADING
857 && on
->state
!= OSPF6_NEIGHBOR_FULL
) {
858 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV_HDR
))
859 zlog_debug("Neighbor state less than Exchange, ignore");
865 /* Process each request */
866 for (p
= (char *)((caddr_t
)oh
+ sizeof(struct ospf6_header
));
867 p
+ sizeof(struct ospf6_lsreq_entry
) <= OSPF6_MESSAGE_END(oh
);
868 p
+= sizeof(struct ospf6_lsreq_entry
)) {
869 e
= (struct ospf6_lsreq_entry
*)p
;
871 switch (OSPF6_LSA_SCOPE(e
->type
)) {
872 case OSPF6_SCOPE_LINKLOCAL
:
873 lsdb
= on
->ospf6_if
->lsdb
;
875 case OSPF6_SCOPE_AREA
:
876 lsdb
= on
->ospf6_if
->area
->lsdb
;
879 lsdb
= on
->ospf6_if
->area
->ospf6
->lsdb
;
882 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
883 zlog_debug("Ignoring LSA of reserved scope");
888 /* Find database copy */
889 lsa
= ospf6_lsdb_lookup(e
->type
, e
->id
, e
->adv_router
, lsdb
);
891 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
)) {
893 "Can't find requested [%s Id:%pI4 Adv:%pI4]",
894 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 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN
,
928 zlog_debug("%s: undersized IPv6 prefix header",
932 /* safe to look deeper */
933 if (current
->prefix_length
> IPV6_MAX_BITLEN
) {
934 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN
,
936 zlog_debug("%s: invalid PrefixLength (%u bits)",
937 __func__
, current
->prefix_length
);
940 /* covers both fixed- and variable-sized fields */
941 requested_pfx_bytes
=
942 OSPF6_PREFIX_MIN_SIZE
943 + OSPF6_PREFIX_SPACE(current
->prefix_length
);
944 if (requested_pfx_bytes
> length
) {
945 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN
,
947 zlog_debug("%s: undersized IPv6 prefix",
952 length
-= requested_pfx_bytes
;
953 current
= (struct ospf6_prefix
*)((caddr_t
)current
954 + requested_pfx_bytes
);
957 if (real_num_pfxs
!= req_num_pfxs
) {
958 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN
,
961 "%s: IPv6 prefix number mismatch (%u required, %u real)",
962 __func__
, req_num_pfxs
, real_num_pfxs
);
968 /* Verify an LSA to have a valid length and dispatch further (where
969 appropriate) to check if the contents, including nested IPv6 prefixes,
970 is properly sized/aligned within the LSA. Note that this function gets
971 LSA type in network byte order, uses in host byte order and passes to
972 ospf6_lstype_name() in network byte order again. */
973 static unsigned ospf6_lsa_examin(struct ospf6_lsa_header
*lsah
,
974 const uint16_t lsalen
,
975 const uint8_t headeronly
)
977 struct ospf6_intra_prefix_lsa
*intra_prefix_lsa
;
978 struct ospf6_as_external_lsa
*as_external_lsa
;
979 struct ospf6_link_lsa
*link_lsa
;
984 /* In case an additional minimum length constraint is defined for
986 LSA type, make sure that this constraint is met. */
987 lsatype
= ntohs(lsah
->type
);
988 ltindex
= lsatype
& OSPF6_LSTYPE_FCODE_MASK
;
989 if (ltindex
< OSPF6_LSTYPE_SIZE
&& ospf6_lsa_minlen
[ltindex
]
990 && lsalen
< ospf6_lsa_minlen
[ltindex
] + OSPF6_LSA_HEADER_SIZE
) {
991 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN
,
993 zlog_debug("%s: undersized (%u B) LSA", __func__
,
998 case OSPF6_LSTYPE_ROUTER
:
999 /* RFC5340 A.4.3, LSA header + OSPF6_ROUTER_LSA_MIN_SIZE bytes
1001 by N>=0 interface descriptions. */
1002 if ((lsalen
- OSPF6_LSA_HEADER_SIZE
- OSPF6_ROUTER_LSA_MIN_SIZE
)
1003 % OSPF6_ROUTER_LSDESC_FIX_SIZE
) {
1004 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN
,
1007 "%s: interface description alignment error",
1012 case OSPF6_LSTYPE_NETWORK
:
1013 /* RFC5340 A.4.4, LSA header + OSPF6_NETWORK_LSA_MIN_SIZE bytes
1014 followed by N>=0 attached router descriptions. */
1015 if ((lsalen
- OSPF6_LSA_HEADER_SIZE
1016 - OSPF6_NETWORK_LSA_MIN_SIZE
)
1017 % OSPF6_NETWORK_LSDESC_FIX_SIZE
) {
1018 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN
,
1021 "%s: router description alignment error",
1026 case OSPF6_LSTYPE_INTER_PREFIX
:
1027 /* RFC5340 A.4.5, LSA header + OSPF6_INTER_PREFIX_LSA_MIN_SIZE
1029 followed by 3-4 fields of a single IPv6 prefix. */
1032 return ospf6_prefixes_examin(
1033 (struct ospf6_prefix
1034 *)((caddr_t
)lsah
+ OSPF6_LSA_HEADER_SIZE
1035 + OSPF6_INTER_PREFIX_LSA_MIN_SIZE
),
1036 lsalen
- OSPF6_LSA_HEADER_SIZE
1037 - OSPF6_INTER_PREFIX_LSA_MIN_SIZE
,
1039 case OSPF6_LSTYPE_INTER_ROUTER
:
1040 /* RFC5340 A.4.6, fixed-size LSA. */
1042 > OSPF6_LSA_HEADER_SIZE
+ OSPF6_INTER_ROUTER_LSA_FIX_SIZE
) {
1043 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN
,
1045 zlog_debug("%s: oversized (%u B) LSA", __func__
,
1050 case OSPF6_LSTYPE_AS_EXTERNAL
: /* RFC5340 A.4.7, same as A.4.8. */
1051 case OSPF6_LSTYPE_TYPE_7
:
1052 /* RFC5340 A.4.8, LSA header + OSPF6_AS_EXTERNAL_LSA_MIN_SIZE
1054 followed by 3-4 fields of IPv6 prefix and 3 conditional LSA
1056 16 bytes of forwarding address, 4 bytes of external route
1058 4 bytes of referenced link state ID. */
1062 (struct ospf6_as_external_lsa
1063 *)((caddr_t
)lsah
+ OSPF6_LSA_HEADER_SIZE
);
1065 OSPF6_LSA_HEADER_SIZE
+ OSPF6_AS_EXTERNAL_LSA_MIN_SIZE
;
1066 /* To find out if the last optional field (Referenced Link State
1068 assumed in this LSA, we need to access fixed fields of the
1070 prefix before ospf6_prefix_examin() confirms its sizing. */
1071 if (exp_length
+ OSPF6_PREFIX_MIN_SIZE
> lsalen
) {
1072 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN
,
1074 zlog_debug("%s: undersized (%u B) LSA header",
1078 /* forwarding address */
1079 if (CHECK_FLAG(as_external_lsa
->bits_metric
, OSPF6_ASBR_BIT_F
))
1081 /* external route tag */
1082 if (CHECK_FLAG(as_external_lsa
->bits_metric
, OSPF6_ASBR_BIT_T
))
1084 /* referenced link state ID */
1085 if (as_external_lsa
->prefix
.u
._prefix_referenced_lstype
)
1087 /* All the fixed-size fields (mandatory and optional) must fit.
1089 this check does not include any IPv6 prefix fields. */
1090 if (exp_length
> lsalen
) {
1091 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN
,
1093 zlog_debug("%s: undersized (%u B) LSA header",
1097 /* The last call completely covers the remainder (IPv6 prefix).
1099 return ospf6_prefixes_examin(
1100 (struct ospf6_prefix
1101 *)((caddr_t
)as_external_lsa
1102 + OSPF6_AS_EXTERNAL_LSA_MIN_SIZE
),
1103 lsalen
- exp_length
, 1);
1104 case OSPF6_LSTYPE_LINK
:
1105 /* RFC5340 A.4.9, LSA header + OSPF6_LINK_LSA_MIN_SIZE bytes
1107 by N>=0 IPv6 prefix blocks (with N declared beforehand). */
1110 link_lsa
= (struct ospf6_link_lsa
*)((caddr_t
)lsah
1111 + OSPF6_LSA_HEADER_SIZE
);
1112 return ospf6_prefixes_examin(
1113 (struct ospf6_prefix
*)((caddr_t
)link_lsa
1114 + OSPF6_LINK_LSA_MIN_SIZE
),
1115 lsalen
- OSPF6_LSA_HEADER_SIZE
1116 - OSPF6_LINK_LSA_MIN_SIZE
,
1117 ntohl(link_lsa
->prefix_num
) /* 32 bits */
1119 case OSPF6_LSTYPE_INTRA_PREFIX
:
1120 /* RFC5340 A.4.10, LSA header + OSPF6_INTRA_PREFIX_LSA_MIN_SIZE
1122 followed by N>=0 IPv6 prefixes (with N declared beforehand).
1127 (struct ospf6_intra_prefix_lsa
1128 *)((caddr_t
)lsah
+ OSPF6_LSA_HEADER_SIZE
);
1129 return ospf6_prefixes_examin(
1130 (struct ospf6_prefix
1131 *)((caddr_t
)intra_prefix_lsa
1132 + OSPF6_INTRA_PREFIX_LSA_MIN_SIZE
),
1133 lsalen
- OSPF6_LSA_HEADER_SIZE
1134 - OSPF6_INTRA_PREFIX_LSA_MIN_SIZE
,
1135 ntohs(intra_prefix_lsa
->prefix_num
) /* 16 bits */
1138 /* No additional validation is possible for unknown LSA types, which are
1139 themselves valid in OPSFv3, hence the default decision is to accept.
1144 /* Verify if the provided input buffer is a valid sequence of LSAs. This
1145 includes verification of LSA blocks length/alignment and dispatching
1146 of deeper-level checks. */
1148 ospf6_lsaseq_examin(struct ospf6_lsa_header
*lsah
, /* start of buffered data */
1149 size_t length
, const uint8_t headeronly
,
1150 /* When declared_num_lsas is not 0, compare it to the real
1152 and treat the difference as an error. */
1153 const uint32_t declared_num_lsas
)
1155 uint32_t counted_lsas
= 0;
1159 if (length
< OSPF6_LSA_HEADER_SIZE
) {
1160 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN
,
1163 "%s: undersized (%zu B) trailing (#%u) LSA header",
1164 __func__
, length
, counted_lsas
);
1167 /* save on ntohs() calls here and in the LSA validator */
1168 lsalen
= OSPF6_LSA_SIZE(lsah
);
1169 if (lsalen
< OSPF6_LSA_HEADER_SIZE
) {
1170 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN
,
1173 "%s: malformed LSA header #%u, declared length is %u B",
1174 __func__
, counted_lsas
, lsalen
);
1178 /* less checks here and in ospf6_lsa_examin() */
1179 if (MSG_OK
!= ospf6_lsa_examin(lsah
, lsalen
, 1)) {
1180 if (IS_OSPF6_DEBUG_MESSAGE(
1181 OSPF6_MESSAGE_TYPE_UNKNOWN
,
1184 "%s: anomaly in header-only %s LSA #%u",
1186 ospf6_lstype_name(lsah
->type
),
1190 lsah
= (struct ospf6_lsa_header
1192 + OSPF6_LSA_HEADER_SIZE
);
1193 length
-= OSPF6_LSA_HEADER_SIZE
;
1195 /* make sure the input buffer is deep enough before
1197 if (lsalen
> length
) {
1198 if (IS_OSPF6_DEBUG_MESSAGE(
1199 OSPF6_MESSAGE_TYPE_UNKNOWN
,
1202 "%s: anomaly in %s LSA #%u: declared length is %u B, buffered length is %zu B",
1204 ospf6_lstype_name(lsah
->type
),
1205 counted_lsas
, lsalen
, length
);
1208 if (MSG_OK
!= ospf6_lsa_examin(lsah
, lsalen
, 0)) {
1209 if (IS_OSPF6_DEBUG_MESSAGE(
1210 OSPF6_MESSAGE_TYPE_UNKNOWN
,
1213 "%s: anomaly in %s LSA #%u",
1215 ospf6_lstype_name(lsah
->type
),
1219 lsah
= (struct ospf6_lsa_header
*)((caddr_t
)lsah
1226 if (declared_num_lsas
&& counted_lsas
!= declared_num_lsas
) {
1227 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN
,
1230 "%s: #LSAs declared (%u) does not match actual (%u)",
1231 __func__
, declared_num_lsas
, counted_lsas
);
1237 /* Verify a complete OSPF packet for proper sizing/alignment. */
1238 static unsigned ospf6_packet_examin(struct ospf6_header
*oh
,
1239 const unsigned bytesonwire
)
1241 struct ospf6_lsupdate
*lsupd
;
1244 /* length, 1st approximation */
1245 if (bytesonwire
< OSPF6_HEADER_SIZE
) {
1246 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN
,
1248 zlog_debug("%s: undersized (%u B) packet", __func__
,
1252 /* Now it is safe to access header fields. */
1253 if (bytesonwire
!= ntohs(oh
->length
)) {
1254 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN
,
1257 "%s: %s packet length error (%u real, %u declared)",
1258 __func__
, lookup_msg(ospf6_message_type_str
,
1260 bytesonwire
, ntohs(oh
->length
));
1264 if (oh
->version
!= OSPFV3_VERSION
) {
1265 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN
,
1267 zlog_debug("%s: invalid (%u) protocol version",
1268 __func__
, oh
->version
);
1271 /* length, 2nd approximation */
1272 if (oh
->type
< OSPF6_MESSAGE_TYPE_ALL
&& ospf6_packet_minlen
[oh
->type
]
1274 < OSPF6_HEADER_SIZE
+ ospf6_packet_minlen
[oh
->type
]) {
1275 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN
,
1277 zlog_debug("%s: undersized (%u B) %s packet", __func__
,
1279 lookup_msg(ospf6_message_type_str
, oh
->type
,
1283 /* type-specific deeper validation */
1285 case OSPF6_MESSAGE_TYPE_HELLO
:
1286 /* RFC5340 A.3.2, packet header + OSPF6_HELLO_MIN_SIZE bytes
1288 by N>=0 router-IDs. */
1290 == (bytesonwire
- OSPF6_HEADER_SIZE
- OSPF6_HELLO_MIN_SIZE
)
1293 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN
,
1295 zlog_debug("%s: alignment error in %s packet", __func__
,
1296 lookup_msg(ospf6_message_type_str
, oh
->type
,
1299 case OSPF6_MESSAGE_TYPE_DBDESC
:
1300 /* RFC5340 A.3.3, packet header + OSPF6_DB_DESC_MIN_SIZE bytes
1302 by N>=0 header-only LSAs. */
1303 test
= ospf6_lsaseq_examin(
1304 (struct ospf6_lsa_header
*)((caddr_t
)oh
1306 + OSPF6_DB_DESC_MIN_SIZE
),
1307 bytesonwire
- OSPF6_HEADER_SIZE
1308 - OSPF6_DB_DESC_MIN_SIZE
,
1311 case OSPF6_MESSAGE_TYPE_LSREQ
:
1312 /* RFC5340 A.3.4, packet header + N>=0 LS description blocks. */
1314 == (bytesonwire
- OSPF6_HEADER_SIZE
- OSPF6_LS_REQ_MIN_SIZE
)
1315 % OSPF6_LSREQ_LSDESC_FIX_SIZE
)
1317 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN
,
1319 zlog_debug("%s: alignment error in %s packet", __func__
,
1320 lookup_msg(ospf6_message_type_str
, oh
->type
,
1323 case OSPF6_MESSAGE_TYPE_LSUPDATE
:
1324 /* RFC5340 A.3.5, packet header + OSPF6_LS_UPD_MIN_SIZE bytes
1326 by N>=0 full LSAs (with N declared beforehand). */
1327 lsupd
= (struct ospf6_lsupdate
*)((caddr_t
)oh
1328 + OSPF6_HEADER_SIZE
);
1329 test
= ospf6_lsaseq_examin(
1330 (struct ospf6_lsa_header
*)((caddr_t
)lsupd
1331 + OSPF6_LS_UPD_MIN_SIZE
),
1332 bytesonwire
- OSPF6_HEADER_SIZE
- OSPF6_LS_UPD_MIN_SIZE
,
1333 0, ntohl(lsupd
->lsa_number
) /* 32 bits */
1336 case OSPF6_MESSAGE_TYPE_LSACK
:
1337 /* RFC5340 A.3.6, packet header + N>=0 header-only LSAs. */
1338 test
= ospf6_lsaseq_examin(
1339 (struct ospf6_lsa_header
*)((caddr_t
)oh
1341 + OSPF6_LS_ACK_MIN_SIZE
),
1342 bytesonwire
- OSPF6_HEADER_SIZE
- OSPF6_LS_ACK_MIN_SIZE
,
1346 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN
,
1348 zlog_debug("%s: invalid (%u) message type", __func__
,
1353 && IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN
, RECV_HDR
))
1354 zlog_debug("%s: anomaly in %s packet", __func__
,
1355 lookup_msg(ospf6_message_type_str
, oh
->type
, NULL
));
1359 /* Verify particular fields of otherwise correct received OSPF packet to
1360 meet the requirements of RFC. */
1361 static int ospf6_rxpacket_examin(struct ospf6_interface
*oi
,
1362 struct ospf6_header
*oh
,
1363 const unsigned bytesonwire
)
1366 if (MSG_OK
!= ospf6_packet_examin(oh
, bytesonwire
))
1370 if (oh
->area_id
!= oi
->area
->area_id
) {
1371 if (oh
->area_id
== OSPF_AREA_BACKBONE
)
1373 "VRF %s: I/F %s Message may be via Virtual Link: not supported",
1374 vrf_id_to_name(oi
->interface
->vrf_id
),
1375 oi
->interface
->name
);
1378 "VRF %s: I/F %s Area-ID mismatch (my %pI4, rcvd %pI4)",
1379 vrf_id_to_name(oi
->interface
->vrf_id
),
1380 oi
->interface
->name
, &oi
->area
->area_id
,
1385 /* Instance-ID check */
1386 if (oh
->instance_id
!= oi
->instance_id
) {
1388 "VRF %s: I/F %s Instance-ID mismatch (my %u, rcvd %u)",
1389 vrf_id_to_name(oi
->interface
->vrf_id
),
1390 oi
->interface
->name
, oi
->instance_id
, oh
->instance_id
);
1394 /* Router-ID check */
1395 if (oh
->router_id
== oi
->area
->ospf6
->router_id
) {
1396 zlog_warn("VRF %s: I/F %s Duplicate Router-ID (%pI4)",
1397 vrf_id_to_name(oi
->interface
->vrf_id
),
1398 oi
->interface
->name
, &oh
->router_id
);
1404 static void ospf6_lsupdate_recv(struct in6_addr
*src
, struct in6_addr
*dst
,
1405 struct ospf6_interface
*oi
,
1406 struct ospf6_header
*oh
)
1408 struct ospf6_neighbor
*on
;
1409 struct ospf6_lsupdate
*lsupdate
;
1412 on
= ospf6_neighbor_lookup(oh
->router_id
, oi
);
1414 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV_HDR
))
1415 zlog_debug("Neighbor not found, ignore");
1419 if (on
->state
!= OSPF6_NEIGHBOR_EXCHANGE
1420 && on
->state
!= OSPF6_NEIGHBOR_LOADING
1421 && on
->state
!= OSPF6_NEIGHBOR_FULL
) {
1422 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV_HDR
))
1423 zlog_debug("Neighbor state less than Exchange, ignore");
1427 lsupdate
= (struct ospf6_lsupdate
*)((caddr_t
)oh
1428 + sizeof(struct ospf6_header
));
1433 for (p
= (char *)((caddr_t
)lsupdate
+ sizeof(struct ospf6_lsupdate
));
1434 p
< OSPF6_MESSAGE_END(oh
)
1435 && p
+ OSPF6_LSA_SIZE(p
) <= OSPF6_MESSAGE_END(oh
);
1436 p
+= OSPF6_LSA_SIZE(p
)) {
1437 ospf6_receive_lsa(on
, (struct ospf6_lsa_header
*)p
);
1440 assert(p
== OSPF6_MESSAGE_END(oh
));
1443 static void ospf6_lsack_recv(struct in6_addr
*src
, struct in6_addr
*dst
,
1444 struct ospf6_interface
*oi
,
1445 struct ospf6_header
*oh
)
1447 struct ospf6_neighbor
*on
;
1449 struct ospf6_lsa
*his
, *mine
;
1450 struct ospf6_lsdb
*lsdb
= NULL
;
1452 assert(oh
->type
== OSPF6_MESSAGE_TYPE_LSACK
);
1454 on
= ospf6_neighbor_lookup(oh
->router_id
, oi
);
1456 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV_HDR
))
1457 zlog_debug("Neighbor not found, ignore");
1461 if (on
->state
!= OSPF6_NEIGHBOR_EXCHANGE
1462 && on
->state
!= OSPF6_NEIGHBOR_LOADING
1463 && on
->state
!= OSPF6_NEIGHBOR_FULL
) {
1464 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV_HDR
))
1465 zlog_debug("Neighbor state less than Exchange, ignore");
1471 for (p
= (char *)((caddr_t
)oh
+ sizeof(struct ospf6_header
));
1472 p
+ sizeof(struct ospf6_lsa_header
) <= OSPF6_MESSAGE_END(oh
);
1473 p
+= sizeof(struct ospf6_lsa_header
)) {
1474 his
= ospf6_lsa_create_headeronly((struct ospf6_lsa_header
*)p
);
1476 switch (OSPF6_LSA_SCOPE(his
->header
->type
)) {
1477 case OSPF6_SCOPE_LINKLOCAL
:
1478 lsdb
= on
->ospf6_if
->lsdb
;
1480 case OSPF6_SCOPE_AREA
:
1481 lsdb
= on
->ospf6_if
->area
->lsdb
;
1483 case OSPF6_SCOPE_AS
:
1484 lsdb
= on
->ospf6_if
->area
->ospf6
->lsdb
;
1486 case OSPF6_SCOPE_RESERVED
:
1487 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
1488 zlog_debug("Ignoring LSA of reserved scope");
1489 ospf6_lsa_delete(his
);
1494 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
1495 zlog_debug("%s acknowledged by %s", his
->name
,
1498 /* Find database copy */
1499 mine
= ospf6_lsdb_lookup(his
->header
->type
, his
->header
->id
,
1500 his
->header
->adv_router
, lsdb
);
1502 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
1503 zlog_debug("No database copy");
1504 ospf6_lsa_delete(his
);
1508 /* Check if the LSA is on his retrans-list */
1509 mine
= ospf6_lsdb_lookup(his
->header
->type
, his
->header
->id
,
1510 his
->header
->adv_router
,
1513 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
1514 zlog_debug("Not on %s's retrans-list",
1516 ospf6_lsa_delete(his
);
1520 if (ospf6_lsa_compare(his
, mine
) != 0) {
1521 /* Log this questionable acknowledgement,
1522 and examine the next one. */
1523 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
1524 zlog_debug("Questionable acknowledgement");
1525 ospf6_lsa_delete(his
);
1529 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
1531 "Acknowledged, remove from %s's retrans-list",
1534 ospf6_decrement_retrans_count(mine
);
1535 if (OSPF6_LSA_IS_MAXAGE(mine
))
1536 ospf6_maxage_remove(on
->ospf6_if
->area
->ospf6
);
1537 ospf6_lsdb_remove(mine
, on
->retrans_list
);
1538 ospf6_lsa_delete(his
);
1541 assert(p
== OSPF6_MESSAGE_END(oh
));
1544 static uint8_t *recvbuf
= NULL
;
1545 static uint8_t *sendbuf
= NULL
;
1546 static unsigned int iobuflen
= 0;
1548 int ospf6_iobuf_size(unsigned int size
)
1550 uint8_t *recvnew
, *sendnew
;
1552 if (size
<= iobuflen
)
1555 recvnew
= XMALLOC(MTYPE_OSPF6_MESSAGE
, size
);
1556 sendnew
= XMALLOC(MTYPE_OSPF6_MESSAGE
, size
);
1558 XFREE(MTYPE_OSPF6_MESSAGE
, recvbuf
);
1559 XFREE(MTYPE_OSPF6_MESSAGE
, sendbuf
);
1567 void ospf6_message_terminate(void)
1569 XFREE(MTYPE_OSPF6_MESSAGE
, recvbuf
);
1570 XFREE(MTYPE_OSPF6_MESSAGE
, sendbuf
);
1575 int ospf6_receive(struct thread
*thread
)
1579 struct in6_addr src
, dst
;
1581 struct iovec iovector
[2];
1582 struct ospf6_interface
*oi
;
1583 struct ospf6_header
*oh
;
1584 struct ospf6
*ospf6
;
1586 /* add next read thread */
1587 ospf6
= THREAD_ARG(thread
);
1588 sockfd
= THREAD_FD(thread
);
1590 thread_add_read(master
, ospf6_receive
, ospf6
, ospf6
->fd
,
1591 &ospf6
->t_ospf6_receive
);
1594 memset(&src
, 0, sizeof(src
));
1595 memset(&dst
, 0, sizeof(dst
));
1597 memset(recvbuf
, 0, iobuflen
);
1598 iovector
[0].iov_base
= recvbuf
;
1599 iovector
[0].iov_len
= iobuflen
;
1600 iovector
[1].iov_base
= NULL
;
1601 iovector
[1].iov_len
= 0;
1603 /* receive message */
1604 len
= ospf6_recvmsg(&src
, &dst
, &ifindex
, iovector
, sockfd
);
1605 if (len
> iobuflen
) {
1606 flog_err(EC_LIB_DEVELOPMENT
, "Excess message read");
1610 oi
= ospf6_interface_lookup_by_ifindex(ifindex
, ospf6
->vrf_id
);
1611 if (oi
== NULL
|| oi
->area
== NULL
1612 || CHECK_FLAG(oi
->flag
, OSPF6_INTERFACE_DISABLE
)) {
1613 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN
,
1615 zlog_debug("Message received on disabled interface");
1618 if (CHECK_FLAG(oi
->flag
, OSPF6_INTERFACE_PASSIVE
)) {
1619 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN
,
1621 zlog_debug("%s: Ignore message on passive interface %s",
1622 __func__
, oi
->interface
->name
);
1626 oh
= (struct ospf6_header
*)recvbuf
;
1627 if (ospf6_rxpacket_examin(oi
, oh
, len
) != MSG_OK
)
1630 /* Being here means, that no sizing/alignment issues were detected in
1631 the input packet. This renders the additional checks performed below
1632 and also in the type-specific dispatching functions a dead code,
1633 which can be dismissed in a cleanup-focused review round later. */
1636 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV_HDR
)) {
1637 zlog_debug("%s received on %s",
1638 lookup_msg(ospf6_message_type_str
, oh
->type
, NULL
),
1639 oi
->interface
->name
);
1640 zlog_debug(" src: %pI6", &src
);
1641 zlog_debug(" dst: %pI6", &dst
);
1644 case OSPF6_MESSAGE_TYPE_HELLO
:
1645 ospf6_hello_print(oh
, OSPF6_ACTION_RECV
);
1647 case OSPF6_MESSAGE_TYPE_DBDESC
:
1648 ospf6_dbdesc_print(oh
, OSPF6_ACTION_RECV
);
1650 case OSPF6_MESSAGE_TYPE_LSREQ
:
1651 ospf6_lsreq_print(oh
, OSPF6_ACTION_RECV
);
1653 case OSPF6_MESSAGE_TYPE_LSUPDATE
:
1654 ospf6_lsupdate_print(oh
, OSPF6_ACTION_RECV
);
1656 case OSPF6_MESSAGE_TYPE_LSACK
:
1657 ospf6_lsack_print(oh
, OSPF6_ACTION_RECV
);
1665 case OSPF6_MESSAGE_TYPE_HELLO
:
1666 ospf6_hello_recv(&src
, &dst
, oi
, oh
);
1669 case OSPF6_MESSAGE_TYPE_DBDESC
:
1670 ospf6_dbdesc_recv(&src
, &dst
, oi
, oh
);
1673 case OSPF6_MESSAGE_TYPE_LSREQ
:
1674 ospf6_lsreq_recv(&src
, &dst
, oi
, oh
);
1677 case OSPF6_MESSAGE_TYPE_LSUPDATE
:
1678 ospf6_lsupdate_recv(&src
, &dst
, oi
, oh
);
1681 case OSPF6_MESSAGE_TYPE_LSACK
:
1682 ospf6_lsack_recv(&src
, &dst
, oi
, oh
);
1692 static void ospf6_send(struct in6_addr
*src
, struct in6_addr
*dst
,
1693 struct ospf6_interface
*oi
, struct ospf6_header
*oh
)
1697 struct iovec iovector
[2];
1700 iovector
[0].iov_base
= (caddr_t
)oh
;
1701 iovector
[0].iov_len
= ntohs(oh
->length
);
1702 iovector
[1].iov_base
= NULL
;
1703 iovector
[1].iov_len
= 0;
1705 /* fill OSPF header */
1706 oh
->version
= OSPFV3_VERSION
;
1707 /* message type must be set before */
1708 /* message length must be set before */
1709 oh
->router_id
= oi
->area
->ospf6
->router_id
;
1710 oh
->area_id
= oi
->area
->area_id
;
1711 /* checksum is calculated by kernel */
1712 oh
->instance_id
= oi
->instance_id
;
1716 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, SEND_HDR
)) {
1718 inet_ntop(AF_INET6
, src
, srcname
, sizeof(srcname
));
1720 memset(srcname
, 0, sizeof(srcname
));
1721 zlog_debug("%s send on %s",
1722 lookup_msg(ospf6_message_type_str
, oh
->type
, NULL
),
1723 oi
->interface
->name
);
1724 zlog_debug(" src: %s", srcname
);
1725 zlog_debug(" dst: %pI6", dst
);
1728 case OSPF6_MESSAGE_TYPE_HELLO
:
1729 ospf6_hello_print(oh
, OSPF6_ACTION_RECV
);
1731 case OSPF6_MESSAGE_TYPE_DBDESC
:
1732 ospf6_dbdesc_print(oh
, OSPF6_ACTION_RECV
);
1734 case OSPF6_MESSAGE_TYPE_LSREQ
:
1735 ospf6_lsreq_print(oh
, OSPF6_ACTION_RECV
);
1737 case OSPF6_MESSAGE_TYPE_LSUPDATE
:
1738 ospf6_lsupdate_print(oh
, OSPF6_ACTION_RECV
);
1740 case OSPF6_MESSAGE_TYPE_LSACK
:
1741 ospf6_lsack_print(oh
, OSPF6_ACTION_RECV
);
1744 zlog_debug("Unknown message");
1751 if (oi
->area
->ospf6
->fd
!= -1) {
1752 len
= ospf6_sendmsg(src
, dst
, oi
->interface
->ifindex
, iovector
,
1753 oi
->area
->ospf6
->fd
);
1754 if (len
!= ntohs(oh
->length
))
1755 flog_err(EC_LIB_DEVELOPMENT
,
1756 "Could not send entire message");
1760 static uint32_t ospf6_packet_max(struct ospf6_interface
*oi
)
1762 assert(oi
->ifmtu
> sizeof(struct ip6_hdr
));
1763 return oi
->ifmtu
- (sizeof(struct ip6_hdr
));
1766 int ospf6_hello_send(struct thread
*thread
)
1768 struct ospf6_interface
*oi
;
1769 struct ospf6_header
*oh
;
1770 struct ospf6_hello
*hello
;
1772 struct listnode
*node
, *nnode
;
1773 struct ospf6_neighbor
*on
;
1775 oi
= (struct ospf6_interface
*)THREAD_ARG(thread
);
1776 oi
->thread_send_hello
= (struct thread
*)NULL
;
1778 if (oi
->state
<= OSPF6_INTERFACE_DOWN
) {
1779 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_HELLO
, SEND_HDR
))
1780 zlog_debug("Unable to send Hello on down interface %s",
1781 oi
->interface
->name
);
1785 if (iobuflen
== 0) {
1786 zlog_debug("Unable to send Hello on interface %s iobuflen is 0",
1787 oi
->interface
->name
);
1791 /* set next thread */
1792 thread_add_timer(master
, ospf6_hello_send
, oi
, oi
->hello_interval
,
1793 &oi
->thread_send_hello
);
1795 memset(sendbuf
, 0, iobuflen
);
1796 oh
= (struct ospf6_header
*)sendbuf
;
1797 hello
= (struct ospf6_hello
*)((caddr_t
)oh
1798 + sizeof(struct ospf6_header
));
1800 hello
->interface_id
= htonl(oi
->interface
->ifindex
);
1801 hello
->priority
= oi
->priority
;
1802 hello
->options
[0] = oi
->area
->options
[0];
1803 hello
->options
[1] = oi
->area
->options
[1];
1804 hello
->options
[2] = oi
->area
->options
[2];
1805 hello
->hello_interval
= htons(oi
->hello_interval
);
1806 hello
->dead_interval
= htons(oi
->dead_interval
);
1807 hello
->drouter
= oi
->drouter
;
1808 hello
->bdrouter
= oi
->bdrouter
;
1810 p
= (uint8_t *)((caddr_t
)hello
+ sizeof(struct ospf6_hello
));
1812 for (ALL_LIST_ELEMENTS(oi
->neighbor_list
, node
, nnode
, on
)) {
1813 if (on
->state
< OSPF6_NEIGHBOR_INIT
)
1816 if (p
- sendbuf
+ sizeof(uint32_t) > ospf6_packet_max(oi
)) {
1817 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_HELLO
,
1820 "sending Hello message: exceeds I/F MTU");
1824 memcpy(p
, &on
->router_id
, sizeof(uint32_t));
1825 p
+= sizeof(uint32_t);
1828 oh
->type
= OSPF6_MESSAGE_TYPE_HELLO
;
1829 oh
->length
= htons(p
- sendbuf
);
1833 ospf6_send(oi
->linklocal_addr
, &allspfrouters6
, oi
, oh
);
1837 int ospf6_dbdesc_send(struct thread
*thread
)
1839 struct ospf6_neighbor
*on
;
1840 struct ospf6_header
*oh
;
1841 struct ospf6_dbdesc
*dbdesc
;
1843 struct ospf6_lsa
*lsa
, *lsanext
;
1844 struct in6_addr
*dst
;
1846 on
= (struct ospf6_neighbor
*)THREAD_ARG(thread
);
1847 on
->thread_send_dbdesc
= (struct thread
*)NULL
;
1849 if (on
->state
< OSPF6_NEIGHBOR_EXSTART
) {
1850 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_DBDESC
, SEND_HDR
))
1852 "Quit to send DbDesc to neighbor %s state %s",
1853 on
->name
, ospf6_neighbor_state_str
[on
->state
]);
1857 /* set next thread if master */
1858 if (CHECK_FLAG(on
->dbdesc_bits
, OSPF6_DBDESC_MSBIT
))
1859 thread_add_timer(master
, ospf6_dbdesc_send
, on
,
1860 on
->ospf6_if
->rxmt_interval
,
1861 &on
->thread_send_dbdesc
);
1863 memset(sendbuf
, 0, iobuflen
);
1864 oh
= (struct ospf6_header
*)sendbuf
;
1865 dbdesc
= (struct ospf6_dbdesc
*)((caddr_t
)oh
1866 + sizeof(struct ospf6_header
));
1868 /* if this is initial one, initialize sequence number for DbDesc */
1869 if (CHECK_FLAG(on
->dbdesc_bits
, OSPF6_DBDESC_IBIT
)
1870 && (on
->dbdesc_seqnum
== 0)) {
1871 on
->dbdesc_seqnum
= monotime(NULL
);
1874 dbdesc
->options
[0] = on
->ospf6_if
->area
->options
[0];
1875 dbdesc
->options
[1] = on
->ospf6_if
->area
->options
[1];
1876 dbdesc
->options
[2] = on
->ospf6_if
->area
->options
[2];
1877 dbdesc
->ifmtu
= htons(on
->ospf6_if
->ifmtu
);
1878 dbdesc
->bits
= on
->dbdesc_bits
;
1879 dbdesc
->seqnum
= htonl(on
->dbdesc_seqnum
);
1881 /* if this is not initial one, set LSA headers in dbdesc */
1882 p
= (uint8_t *)((caddr_t
)dbdesc
+ sizeof(struct ospf6_dbdesc
));
1883 if (!CHECK_FLAG(on
->dbdesc_bits
, OSPF6_DBDESC_IBIT
)) {
1884 for (ALL_LSDB(on
->dbdesc_list
, lsa
, lsanext
)) {
1885 ospf6_lsa_age_update_to_send(lsa
,
1886 on
->ospf6_if
->transdelay
);
1889 if (p
- sendbuf
+ sizeof(struct ospf6_lsa_header
)
1890 > ospf6_packet_max(on
->ospf6_if
)) {
1891 ospf6_lsa_unlock(lsa
);
1893 ospf6_lsa_unlock(lsanext
);
1896 memcpy(p
, lsa
->header
, sizeof(struct ospf6_lsa_header
));
1897 p
+= sizeof(struct ospf6_lsa_header
);
1901 oh
->type
= OSPF6_MESSAGE_TYPE_DBDESC
;
1902 oh
->length
= htons(p
- sendbuf
);
1905 if (on
->ospf6_if
->state
== OSPF6_INTERFACE_POINTTOPOINT
)
1906 dst
= &allspfrouters6
;
1908 dst
= &on
->linklocal_addr
;
1910 on
->ospf6_if
->db_desc_out
++;
1912 ospf6_send(on
->ospf6_if
->linklocal_addr
, dst
, on
->ospf6_if
, oh
);
1917 int ospf6_dbdesc_send_newone(struct thread
*thread
)
1919 struct ospf6_neighbor
*on
;
1920 struct ospf6_lsa
*lsa
, *lsanext
;
1921 unsigned int size
= 0;
1923 on
= (struct ospf6_neighbor
*)THREAD_ARG(thread
);
1924 ospf6_lsdb_remove_all(on
->dbdesc_list
);
1926 /* move LSAs from summary_list to dbdesc_list (within neighbor
1928 so that ospf6_send_dbdesc () can send those LSAs */
1929 size
= sizeof(struct ospf6_lsa_header
) + sizeof(struct ospf6_dbdesc
);
1930 for (ALL_LSDB(on
->summary_list
, lsa
, lsanext
)) {
1931 /* if stub area then don't advertise AS-External LSAs */
1932 if ((IS_AREA_STUB(on
->ospf6_if
->area
)
1933 || IS_AREA_NSSA(on
->ospf6_if
->area
))
1934 && ntohs(lsa
->header
->type
) == OSPF6_LSTYPE_AS_EXTERNAL
) {
1935 ospf6_lsdb_remove(lsa
, on
->summary_list
);
1939 if (size
+ sizeof(struct ospf6_lsa_header
)
1940 > ospf6_packet_max(on
->ospf6_if
)) {
1941 ospf6_lsa_unlock(lsa
);
1943 ospf6_lsa_unlock(lsanext
);
1947 ospf6_lsdb_add(ospf6_lsa_copy(lsa
), on
->dbdesc_list
);
1948 ospf6_lsdb_remove(lsa
, on
->summary_list
);
1949 size
+= sizeof(struct ospf6_lsa_header
);
1952 if (on
->summary_list
->count
== 0)
1953 UNSET_FLAG(on
->dbdesc_bits
, OSPF6_DBDESC_MBIT
);
1955 /* If slave, More bit check must be done here */
1956 if (!CHECK_FLAG(on
->dbdesc_bits
, OSPF6_DBDESC_MSBIT
) && /* Slave */
1957 !CHECK_FLAG(on
->dbdesc_last
.bits
, OSPF6_DBDESC_MBIT
)
1958 && !CHECK_FLAG(on
->dbdesc_bits
, OSPF6_DBDESC_MBIT
))
1959 thread_add_event(master
, exchange_done
, on
, 0, NULL
);
1961 thread_execute(master
, ospf6_dbdesc_send
, on
, 0);
1965 int ospf6_lsreq_send(struct thread
*thread
)
1967 struct ospf6_neighbor
*on
;
1968 struct ospf6_header
*oh
;
1969 struct ospf6_lsreq_entry
*e
;
1971 struct ospf6_lsa
*lsa
, *lsanext
, *last_req
;
1973 on
= (struct ospf6_neighbor
*)THREAD_ARG(thread
);
1974 on
->thread_send_lsreq
= (struct thread
*)NULL
;
1976 /* LSReq will be sent only in ExStart or Loading */
1977 if (on
->state
!= OSPF6_NEIGHBOR_EXCHANGE
1978 && on
->state
!= OSPF6_NEIGHBOR_LOADING
) {
1979 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_LSREQ
, SEND_HDR
))
1980 zlog_debug("Quit to send LSReq to neighbor %s state %s",
1982 ospf6_neighbor_state_str
[on
->state
]);
1986 /* schedule loading_done if request list is empty */
1987 if (on
->request_list
->count
== 0) {
1988 thread_add_event(master
, loading_done
, on
, 0, NULL
);
1992 memset(sendbuf
, 0, iobuflen
);
1993 oh
= (struct ospf6_header
*)sendbuf
;
1996 /* set Request entries in lsreq */
1997 p
= (uint8_t *)((caddr_t
)oh
+ sizeof(struct ospf6_header
));
1998 for (ALL_LSDB(on
->request_list
, lsa
, lsanext
)) {
2000 if (p
- sendbuf
+ sizeof(struct ospf6_lsreq_entry
)
2001 > ospf6_packet_max(on
->ospf6_if
)) {
2002 ospf6_lsa_unlock(lsa
);
2004 ospf6_lsa_unlock(lsanext
);
2008 e
= (struct ospf6_lsreq_entry
*)p
;
2009 e
->type
= lsa
->header
->type
;
2010 e
->id
= lsa
->header
->id
;
2011 e
->adv_router
= lsa
->header
->adv_router
;
2012 p
+= sizeof(struct ospf6_lsreq_entry
);
2016 if (last_req
!= NULL
) {
2017 if (on
->last_ls_req
!= NULL
)
2018 on
->last_ls_req
= ospf6_lsa_unlock(on
->last_ls_req
);
2020 ospf6_lsa_lock(last_req
);
2021 on
->last_ls_req
= last_req
;
2024 oh
->type
= OSPF6_MESSAGE_TYPE_LSREQ
;
2025 oh
->length
= htons(p
- sendbuf
);
2027 on
->ospf6_if
->ls_req_out
++;
2029 if (on
->ospf6_if
->state
== OSPF6_INTERFACE_POINTTOPOINT
)
2030 ospf6_send(on
->ospf6_if
->linklocal_addr
, &allspfrouters6
,
2033 ospf6_send(on
->ospf6_if
->linklocal_addr
, &on
->linklocal_addr
,
2036 /* set next thread */
2037 if (on
->request_list
->count
!= 0) {
2038 on
->thread_send_lsreq
= NULL
;
2039 thread_add_timer(master
, ospf6_lsreq_send
, on
,
2040 on
->ospf6_if
->rxmt_interval
,
2041 &on
->thread_send_lsreq
);
2047 static void ospf6_send_lsupdate(struct ospf6_neighbor
*on
,
2048 struct ospf6_interface
*oi
,
2049 struct ospf6_header
*oh
)
2053 on
->ospf6_if
->ls_upd_out
++;
2055 if ((on
->ospf6_if
->state
== OSPF6_INTERFACE_POINTTOPOINT
)
2056 || (on
->ospf6_if
->state
== OSPF6_INTERFACE_DR
)
2057 || (on
->ospf6_if
->state
== OSPF6_INTERFACE_BDR
)) {
2058 ospf6_send(on
->ospf6_if
->linklocal_addr
,
2059 &allspfrouters6
, on
->ospf6_if
, oh
);
2061 ospf6_send(on
->ospf6_if
->linklocal_addr
,
2062 &on
->linklocal_addr
, on
->ospf6_if
, oh
);
2068 if ((oi
->state
== OSPF6_INTERFACE_POINTTOPOINT
)
2069 || (oi
->state
== OSPF6_INTERFACE_DR
)
2070 || (oi
->state
== OSPF6_INTERFACE_BDR
)) {
2071 ospf6_send(oi
->linklocal_addr
, &allspfrouters6
, oi
, oh
);
2073 ospf6_send(oi
->linklocal_addr
, &alldrouters6
, oi
, oh
);
2078 int ospf6_lsupdate_send_neighbor(struct thread
*thread
)
2080 struct ospf6_neighbor
*on
;
2081 struct ospf6_header
*oh
;
2082 struct ospf6_lsupdate
*lsupdate
;
2085 struct ospf6_lsa
*lsa
, *lsanext
;
2087 on
= (struct ospf6_neighbor
*)THREAD_ARG(thread
);
2088 on
->thread_send_lsupdate
= (struct thread
*)NULL
;
2090 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_LSUPDATE
, SEND_HDR
))
2091 zlog_debug("LSUpdate to neighbor %s", on
->name
);
2093 if (on
->state
< OSPF6_NEIGHBOR_EXCHANGE
) {
2094 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_LSUPDATE
,
2096 zlog_debug("Quit to send (neighbor state %s)",
2097 ospf6_neighbor_state_str
[on
->state
]);
2101 memset(sendbuf
, 0, iobuflen
);
2102 oh
= (struct ospf6_header
*)sendbuf
;
2103 lsupdate
= (struct ospf6_lsupdate
*)((caddr_t
)oh
2104 + sizeof(struct ospf6_header
));
2106 p
= (uint8_t *)((caddr_t
)lsupdate
+ sizeof(struct ospf6_lsupdate
));
2109 /* lsupdate_list lists those LSA which doesn't need to be
2110 retransmitted. remove those from the list */
2111 for (ALL_LSDB(on
->lsupdate_list
, lsa
, lsanext
)) {
2113 if ((p
- sendbuf
+ (unsigned int)OSPF6_LSA_SIZE(lsa
->header
))
2114 > ospf6_packet_max(on
->ospf6_if
)) {
2116 oh
->type
= OSPF6_MESSAGE_TYPE_LSUPDATE
;
2117 oh
->length
= htons(p
- sendbuf
);
2118 lsupdate
->lsa_number
= htonl(lsa_cnt
);
2120 ospf6_send_lsupdate(on
, NULL
, oh
);
2122 memset(sendbuf
, 0, iobuflen
);
2123 oh
= (struct ospf6_header
*)sendbuf
;
2124 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
);
2141 assert(lsa
->lock
== 2);
2142 ospf6_lsdb_remove(lsa
, on
->lsupdate_list
);
2146 oh
->type
= OSPF6_MESSAGE_TYPE_LSUPDATE
;
2147 oh
->length
= htons(p
- sendbuf
);
2148 lsupdate
->lsa_number
= htonl(lsa_cnt
);
2149 ospf6_send_lsupdate(on
, NULL
, oh
);
2152 /* The addresses used for retransmissions are different from those sent
2154 first time and so we need to separate them here.
2156 memset(sendbuf
, 0, iobuflen
);
2157 oh
= (struct ospf6_header
*)sendbuf
;
2158 lsupdate
= (struct ospf6_lsupdate
*)((caddr_t
)oh
2159 + sizeof(struct ospf6_header
));
2160 p
= (uint8_t *)((caddr_t
)lsupdate
+ sizeof(struct ospf6_lsupdate
));
2163 for (ALL_LSDB(on
->retrans_list
, lsa
, lsanext
)) {
2165 if ((p
- sendbuf
+ (unsigned int)OSPF6_LSA_SIZE(lsa
->header
))
2166 > ospf6_packet_max(on
->ospf6_if
)) {
2168 oh
->type
= OSPF6_MESSAGE_TYPE_LSUPDATE
;
2169 oh
->length
= htons(p
- sendbuf
);
2170 lsupdate
->lsa_number
= htonl(lsa_cnt
);
2172 if (on
->ospf6_if
->state
2173 == OSPF6_INTERFACE_POINTTOPOINT
) {
2174 ospf6_send(on
->ospf6_if
->linklocal_addr
,
2178 ospf6_send(on
->ospf6_if
->linklocal_addr
,
2179 &on
->linklocal_addr
,
2183 memset(sendbuf
, 0, iobuflen
);
2184 oh
= (struct ospf6_header
*)sendbuf
;
2185 lsupdate
= (struct ospf6_lsupdate
2189 p
= (uint8_t *)((caddr_t
)lsupdate
2196 ospf6_lsa_age_update_to_send(lsa
, on
->ospf6_if
->transdelay
);
2197 memcpy(p
, lsa
->header
, OSPF6_LSA_SIZE(lsa
->header
));
2198 p
+= OSPF6_LSA_SIZE(lsa
->header
);
2203 oh
->type
= OSPF6_MESSAGE_TYPE_LSUPDATE
;
2204 oh
->length
= htons(p
- sendbuf
);
2205 lsupdate
->lsa_number
= htonl(lsa_cnt
);
2207 if (on
->ospf6_if
->state
== OSPF6_INTERFACE_POINTTOPOINT
)
2208 ospf6_send(on
->ospf6_if
->linklocal_addr
,
2209 &allspfrouters6
, on
->ospf6_if
, oh
);
2211 ospf6_send(on
->ospf6_if
->linklocal_addr
,
2212 &on
->linklocal_addr
, on
->ospf6_if
, oh
);
2215 if (on
->lsupdate_list
->count
!= 0) {
2216 on
->thread_send_lsupdate
= NULL
;
2217 thread_add_event(master
, ospf6_lsupdate_send_neighbor
, on
, 0,
2218 &on
->thread_send_lsupdate
);
2219 } else if (on
->retrans_list
->count
!= 0) {
2220 on
->thread_send_lsupdate
= NULL
;
2221 thread_add_timer(master
, ospf6_lsupdate_send_neighbor
, on
,
2222 on
->ospf6_if
->rxmt_interval
,
2223 &on
->thread_send_lsupdate
);
2228 int ospf6_lsupdate_send_neighbor_now(struct ospf6_neighbor
*on
,
2229 struct ospf6_lsa
*lsa
)
2231 struct ospf6_header
*oh
;
2232 struct ospf6_lsupdate
*lsupdate
;
2236 memset(sendbuf
, 0, iobuflen
);
2237 oh
= (struct ospf6_header
*)sendbuf
;
2238 lsupdate
= (struct ospf6_lsupdate
*)((caddr_t
)oh
2239 + sizeof(struct ospf6_header
));
2241 p
= (uint8_t *)((caddr_t
)lsupdate
+ sizeof(struct ospf6_lsupdate
));
2242 ospf6_lsa_age_update_to_send(lsa
, on
->ospf6_if
->transdelay
);
2243 memcpy(p
, lsa
->header
, OSPF6_LSA_SIZE(lsa
->header
));
2244 p
+= OSPF6_LSA_SIZE(lsa
->header
);
2247 oh
->type
= OSPF6_MESSAGE_TYPE_LSUPDATE
;
2248 oh
->length
= htons(p
- sendbuf
);
2249 lsupdate
->lsa_number
= htonl(lsa_cnt
);
2251 if (IS_OSPF6_DEBUG_FLOODING
2252 || IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_LSUPDATE
, SEND_HDR
))
2253 zlog_debug("%s: Send lsupdate with lsa %s (age %u)", __func__
,
2254 lsa
->name
, ntohs(lsa
->header
->age
));
2256 ospf6_send_lsupdate(on
, NULL
, oh
);
2261 int ospf6_lsupdate_send_interface(struct thread
*thread
)
2263 struct ospf6_interface
*oi
;
2264 struct ospf6_header
*oh
;
2265 struct ospf6_lsupdate
*lsupdate
;
2268 struct ospf6_lsa
*lsa
, *lsanext
;
2270 oi
= (struct ospf6_interface
*)THREAD_ARG(thread
);
2271 oi
->thread_send_lsupdate
= (struct thread
*)NULL
;
2273 if (oi
->state
<= OSPF6_INTERFACE_WAITING
) {
2274 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_LSUPDATE
,
2277 "Quit to send LSUpdate to interface %s state %s",
2278 oi
->interface
->name
,
2279 ospf6_interface_state_str
[oi
->state
]);
2283 /* if we have nothing to send, return */
2284 if (oi
->lsupdate_list
->count
== 0)
2287 memset(sendbuf
, 0, iobuflen
);
2288 oh
= (struct ospf6_header
*)sendbuf
;
2289 lsupdate
= (struct ospf6_lsupdate
*)((caddr_t
)oh
2290 + sizeof(struct ospf6_header
));
2292 p
= (uint8_t *)((caddr_t
)lsupdate
+ sizeof(struct ospf6_lsupdate
));
2295 for (ALL_LSDB(oi
->lsupdate_list
, lsa
, lsanext
)) {
2297 if ((p
- sendbuf
+ ((unsigned int)OSPF6_LSA_SIZE(lsa
->header
)))
2298 > ospf6_packet_max(oi
)) {
2300 oh
->type
= OSPF6_MESSAGE_TYPE_LSUPDATE
;
2301 oh
->length
= htons(p
- sendbuf
);
2302 lsupdate
->lsa_number
= htonl(lsa_cnt
);
2304 ospf6_send_lsupdate(NULL
, oi
, oh
);
2305 if (IS_OSPF6_DEBUG_MESSAGE(
2306 OSPF6_MESSAGE_TYPE_LSUPDATE
, SEND
))
2307 zlog_debug("%s: LSUpdate length %d",
2308 __func__
, ntohs(oh
->length
));
2310 memset(sendbuf
, 0, iobuflen
);
2311 oh
= (struct ospf6_header
*)sendbuf
;
2312 lsupdate
= (struct ospf6_lsupdate
2317 p
= (uint8_t *)((caddr_t
)lsupdate
2324 ospf6_lsa_age_update_to_send(lsa
, oi
->transdelay
);
2325 memcpy(p
, lsa
->header
, OSPF6_LSA_SIZE(lsa
->header
));
2326 p
+= OSPF6_LSA_SIZE(lsa
->header
);
2329 assert(lsa
->lock
== 2);
2330 ospf6_lsdb_remove(lsa
, oi
->lsupdate_list
);
2334 oh
->type
= OSPF6_MESSAGE_TYPE_LSUPDATE
;
2335 oh
->length
= htons(p
- sendbuf
);
2336 lsupdate
->lsa_number
= htonl(lsa_cnt
);
2338 ospf6_send_lsupdate(NULL
, oi
, oh
);
2341 if (oi
->lsupdate_list
->count
> 0) {
2342 oi
->thread_send_lsupdate
= NULL
;
2343 thread_add_event(master
, ospf6_lsupdate_send_interface
, oi
, 0,
2344 &oi
->thread_send_lsupdate
);
2350 int ospf6_lsack_send_neighbor(struct thread
*thread
)
2352 struct ospf6_neighbor
*on
;
2353 struct ospf6_header
*oh
;
2355 struct ospf6_lsa
*lsa
, *lsanext
;
2358 on
= (struct ospf6_neighbor
*)THREAD_ARG(thread
);
2359 on
->thread_send_lsack
= (struct thread
*)NULL
;
2361 if (on
->state
< OSPF6_NEIGHBOR_EXCHANGE
) {
2362 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_LSACK
, SEND_HDR
))
2363 zlog_debug("Quit to send LSAck to neighbor %s state %s",
2365 ospf6_neighbor_state_str
[on
->state
]);
2369 /* if we have nothing to send, return */
2370 if (on
->lsack_list
->count
== 0)
2373 memset(sendbuf
, 0, iobuflen
);
2374 oh
= (struct ospf6_header
*)sendbuf
;
2376 p
= (uint8_t *)((caddr_t
)oh
+ sizeof(struct ospf6_header
));
2378 for (ALL_LSDB(on
->lsack_list
, lsa
, lsanext
)) {
2380 if (p
- sendbuf
+ sizeof(struct ospf6_lsa_header
)
2381 > ospf6_packet_max(on
->ospf6_if
)) {
2382 /* if we run out of packet size/space here,
2383 better to try again soon. */
2385 oh
->type
= OSPF6_MESSAGE_TYPE_LSACK
;
2386 oh
->length
= htons(p
- sendbuf
);
2388 on
->ospf6_if
->ls_ack_out
++;
2390 ospf6_send(on
->ospf6_if
->linklocal_addr
,
2391 &on
->linklocal_addr
, on
->ospf6_if
,
2394 memset(sendbuf
, 0, iobuflen
);
2395 oh
= (struct ospf6_header
*)sendbuf
;
2396 p
= (uint8_t *)((caddr_t
)oh
2397 + sizeof(struct ospf6_header
));
2402 ospf6_lsa_age_update_to_send(lsa
, on
->ospf6_if
->transdelay
);
2403 memcpy(p
, lsa
->header
, sizeof(struct ospf6_lsa_header
));
2404 p
+= sizeof(struct ospf6_lsa_header
);
2406 assert(lsa
->lock
== 2);
2407 ospf6_lsdb_remove(lsa
, on
->lsack_list
);
2412 oh
->type
= OSPF6_MESSAGE_TYPE_LSACK
;
2413 oh
->length
= htons(p
- sendbuf
);
2415 on
->ospf6_if
->ls_ack_out
++;
2417 ospf6_send(on
->ospf6_if
->linklocal_addr
, &on
->linklocal_addr
,
2421 if (on
->lsack_list
->count
> 0)
2422 thread_add_event(master
, ospf6_lsack_send_neighbor
, on
, 0,
2423 &on
->thread_send_lsack
);
2428 int ospf6_lsack_send_interface(struct thread
*thread
)
2430 struct ospf6_interface
*oi
;
2431 struct ospf6_header
*oh
;
2433 struct ospf6_lsa
*lsa
, *lsanext
;
2436 oi
= (struct ospf6_interface
*)THREAD_ARG(thread
);
2437 oi
->thread_send_lsack
= (struct thread
*)NULL
;
2439 if (oi
->state
<= OSPF6_INTERFACE_WAITING
) {
2440 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_LSACK
, SEND_HDR
))
2442 "Quit to send LSAck to interface %s state %s",
2443 oi
->interface
->name
,
2444 ospf6_interface_state_str
[oi
->state
]);
2448 /* if we have nothing to send, return */
2449 if (oi
->lsack_list
->count
== 0)
2452 memset(sendbuf
, 0, iobuflen
);
2453 oh
= (struct ospf6_header
*)sendbuf
;
2455 p
= (uint8_t *)((caddr_t
)oh
+ sizeof(struct ospf6_header
));
2457 for (ALL_LSDB(oi
->lsack_list
, lsa
, lsanext
)) {
2459 if (p
- sendbuf
+ sizeof(struct ospf6_lsa_header
)
2460 > ospf6_packet_max(oi
)) {
2461 /* if we run out of packet size/space here,
2462 better to try again soon. */
2463 THREAD_OFF(oi
->thread_send_lsack
);
2464 thread_add_event(master
, ospf6_lsack_send_interface
, oi
,
2465 0, &oi
->thread_send_lsack
);
2467 ospf6_lsa_unlock(lsa
);
2469 ospf6_lsa_unlock(lsanext
);
2473 ospf6_lsa_age_update_to_send(lsa
, oi
->transdelay
);
2474 memcpy(p
, lsa
->header
, sizeof(struct ospf6_lsa_header
));
2475 p
+= sizeof(struct ospf6_lsa_header
);
2477 assert(lsa
->lock
== 2);
2478 ospf6_lsdb_remove(lsa
, oi
->lsack_list
);
2483 oh
->type
= OSPF6_MESSAGE_TYPE_LSACK
;
2484 oh
->length
= htons(p
- sendbuf
);
2486 if ((oi
->state
== OSPF6_INTERFACE_POINTTOPOINT
)
2487 || (oi
->state
== OSPF6_INTERFACE_DR
)
2488 || (oi
->state
== OSPF6_INTERFACE_BDR
))
2489 ospf6_send(oi
->linklocal_addr
, &allspfrouters6
, oi
, oh
);
2491 ospf6_send(oi
->linklocal_addr
, &alldrouters6
, oi
, oh
);
2494 if (oi
->lsack_list
->count
> 0)
2495 thread_add_event(master
, ospf6_lsack_send_interface
, oi
, 0,
2496 &oi
->thread_send_lsack
);
2503 DEFUN(debug_ospf6_message
, debug_ospf6_message_cmd
,
2504 "debug ospf6 message <unknown|hello|dbdesc|lsreq|lsupdate|lsack|all> [<send|recv|send-hdr|recv-hdr>]",
2506 "Debug OSPFv3 message\n"
2507 "Debug Unknown message\n"
2508 "Debug Hello message\n"
2509 "Debug Database Description message\n"
2510 "Debug Link State Request message\n"
2511 "Debug Link State Update message\n"
2512 "Debug Link State Acknowledgement message\n"
2513 "Debug All message\n"
2514 "Debug only sending message, entire packet\n"
2515 "Debug only receiving message, entire packet\n"
2516 "Debug only sending message, header only\n"
2517 "Debug only receiving message, header only\n")
2520 int idx_send_recv
= 4;
2521 unsigned char level
= 0;
2526 if (!strncmp(argv
[idx_packet
]->arg
, "u", 1))
2527 type
= OSPF6_MESSAGE_TYPE_UNKNOWN
;
2528 else if (!strncmp(argv
[idx_packet
]->arg
, "h", 1))
2529 type
= OSPF6_MESSAGE_TYPE_HELLO
;
2530 else if (!strncmp(argv
[idx_packet
]->arg
, "d", 1))
2531 type
= OSPF6_MESSAGE_TYPE_DBDESC
;
2532 else if (!strncmp(argv
[idx_packet
]->arg
, "lsr", 3))
2533 type
= OSPF6_MESSAGE_TYPE_LSREQ
;
2534 else if (!strncmp(argv
[idx_packet
]->arg
, "lsu", 3))
2535 type
= OSPF6_MESSAGE_TYPE_LSUPDATE
;
2536 else if (!strncmp(argv
[idx_packet
]->arg
, "lsa", 3))
2537 type
= OSPF6_MESSAGE_TYPE_LSACK
;
2538 else if (!strncmp(argv
[idx_packet
]->arg
, "a", 1))
2539 type
= OSPF6_MESSAGE_TYPE_ALL
;
2542 level
= OSPF6_DEBUG_MESSAGE_SEND
| OSPF6_DEBUG_MESSAGE_RECV
;
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_ON(i
, level
);
2556 OSPF6_DEBUG_MESSAGE_ON(type
, level
);
2561 DEFUN(no_debug_ospf6_message
, no_debug_ospf6_message_cmd
,
2562 "no debug ospf6 message <unknown|hello|dbdesc|lsreq|lsupdate|lsack|all> [<send|recv|send-hdr|recv-hdr>]",
2563 NO_STR DEBUG_STR OSPF6_STR
2564 "Debug OSPFv3 message\n"
2565 "Debug Unknown message\n"
2566 "Debug Hello message\n"
2567 "Debug Database Description message\n"
2568 "Debug Link State Request message\n"
2569 "Debug Link State Update message\n"
2570 "Debug Link State Acknowledgement message\n"
2571 "Debug All message\n"
2572 "Debug only sending message, entire pkt\n"
2573 "Debug only receiving message, entire pkt\n"
2574 "Debug only sending message, header only\n"
2575 "Debug only receiving message, header only\n")
2578 int idx_send_recv
= 5;
2579 unsigned char level
= 0;
2584 if (!strncmp(argv
[idx_packet
]->arg
, "u", 1))
2585 type
= OSPF6_MESSAGE_TYPE_UNKNOWN
;
2586 else if (!strncmp(argv
[idx_packet
]->arg
, "h", 1))
2587 type
= OSPF6_MESSAGE_TYPE_HELLO
;
2588 else if (!strncmp(argv
[idx_packet
]->arg
, "d", 1))
2589 type
= OSPF6_MESSAGE_TYPE_DBDESC
;
2590 else if (!strncmp(argv
[idx_packet
]->arg
, "lsr", 3))
2591 type
= OSPF6_MESSAGE_TYPE_LSREQ
;
2592 else if (!strncmp(argv
[idx_packet
]->arg
, "lsu", 3))
2593 type
= OSPF6_MESSAGE_TYPE_LSUPDATE
;
2594 else if (!strncmp(argv
[idx_packet
]->arg
, "lsa", 3))
2595 type
= OSPF6_MESSAGE_TYPE_LSACK
;
2596 else if (!strncmp(argv
[idx_packet
]->arg
, "a", 1))
2597 type
= OSPF6_MESSAGE_TYPE_ALL
;
2600 level
= OSPF6_DEBUG_MESSAGE_SEND
| OSPF6_DEBUG_MESSAGE_RECV
2601 | OSPF6_DEBUG_MESSAGE_SEND_HDR
2602 | OSPF6_DEBUG_MESSAGE_RECV_HDR
;
2603 else if (!strncmp(argv
[idx_send_recv
]->arg
, "send-h", 6))
2604 level
= OSPF6_DEBUG_MESSAGE_SEND_HDR
;
2605 else if (!strncmp(argv
[idx_send_recv
]->arg
, "s", 1))
2606 level
= OSPF6_DEBUG_MESSAGE_SEND
;
2607 else if (!strncmp(argv
[idx_send_recv
]->arg
, "recv-h", 6))
2608 level
= OSPF6_DEBUG_MESSAGE_RECV_HDR
;
2609 else if (!strncmp(argv
[idx_send_recv
]->arg
, "r", 1))
2610 level
= OSPF6_DEBUG_MESSAGE_RECV
;
2612 if (type
== OSPF6_MESSAGE_TYPE_ALL
) {
2613 for (i
= 0; i
< 6; i
++)
2614 OSPF6_DEBUG_MESSAGE_OFF(i
, level
);
2616 OSPF6_DEBUG_MESSAGE_OFF(type
, level
);
2622 int config_write_ospf6_debug_message(struct vty
*vty
)
2624 const char *type_str
[] = {"unknown", "hello", "dbdesc",
2625 "lsreq", "lsupdate", "lsack"};
2626 unsigned char s
= 0, r
= 0, sh
= 0, rh
= 0;
2629 for (i
= 0; i
< 6; i
++) {
2630 if (IS_OSPF6_DEBUG_MESSAGE_ENABLED(i
, SEND
))
2632 if (IS_OSPF6_DEBUG_MESSAGE_ENABLED(i
, RECV
))
2636 for (i
= 0; i
< 6; i
++) {
2637 if (IS_OSPF6_DEBUG_MESSAGE_ENABLED(i
, SEND_HDR
))
2639 if (IS_OSPF6_DEBUG_MESSAGE_ENABLED(i
, RECV_HDR
))
2643 if (s
== 0x3f && r
== 0x3f) {
2644 vty_out(vty
, "debug ospf6 message all\n");
2648 if (s
== 0x3f && r
== 0) {
2649 vty_out(vty
, "debug ospf6 message all send\n");
2651 } else if (s
== 0 && r
== 0x3f) {
2652 vty_out(vty
, "debug ospf6 message all recv\n");
2656 if (sh
== 0x3f && rh
== 0) {
2657 vty_out(vty
, "debug ospf6 message all send-hdr\n");
2659 } else if (sh
== 0 && rh
== 0x3f) {
2660 vty_out(vty
, "debug ospf6 message all recv-hdr\n");
2664 /* Unknown message is logged by default */
2665 if (!IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN
, SEND
)
2666 && !IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN
, RECV
))
2667 vty_out(vty
, "no debug ospf6 message unknown\n");
2668 else if (!IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN
, SEND
))
2669 vty_out(vty
, "no debug ospf6 message unknown send\n");
2670 else if (!IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN
, RECV
))
2671 vty_out(vty
, "no debug ospf6 message unknown recv\n");
2673 for (i
= 1; i
< 6; i
++) {
2674 if (IS_OSPF6_DEBUG_MESSAGE_ENABLED(i
, SEND
)
2675 && IS_OSPF6_DEBUG_MESSAGE_ENABLED(i
, RECV
)) {
2676 vty_out(vty
, "debug ospf6 message %s\n", type_str
[i
]);
2680 if (IS_OSPF6_DEBUG_MESSAGE_ENABLED(i
, SEND
))
2681 vty_out(vty
, "debug ospf6 message %s send\n",
2683 else if (IS_OSPF6_DEBUG_MESSAGE_ENABLED(i
, SEND_HDR
))
2684 vty_out(vty
, "debug ospf6 message %s send-hdr\n",
2687 if (IS_OSPF6_DEBUG_MESSAGE_ENABLED(i
, RECV
))
2688 vty_out(vty
, "debug ospf6 message %s recv\n",
2690 else if (IS_OSPF6_DEBUG_MESSAGE_ENABLED(i
, RECV_HDR
))
2691 vty_out(vty
, "debug ospf6 message %s recv-hdr\n",
2698 void install_element_ospf6_debug_message(void)
2700 install_element(ENABLE_NODE
, &debug_ospf6_message_cmd
);
2701 install_element(ENABLE_NODE
, &no_debug_ospf6_message_cmd
);
2702 install_element(CONFIG_NODE
, &debug_ospf6_message_cmd
);
2703 install_element(CONFIG_NODE
, &no_debug_ospf6_message_cmd
);