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_network.h"
35 #include "ospf6_message.h"
37 #include "ospf6_top.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 unsigned char conf_debug_ospf6_message
[6] = {0x03, 0, 0, 0, 0, 0};
53 static const struct message ospf6_message_type_str
[] = {
54 {OSPF6_MESSAGE_TYPE_HELLO
, "Hello"},
55 {OSPF6_MESSAGE_TYPE_DBDESC
, "DbDesc"},
56 {OSPF6_MESSAGE_TYPE_LSREQ
, "LSReq"},
57 {OSPF6_MESSAGE_TYPE_LSUPDATE
, "LSUpdate"},
58 {OSPF6_MESSAGE_TYPE_LSACK
, "LSAck"},
61 /* Minimum (besides the standard OSPF packet header) lengths for OSPF
62 packets of particular types, offset is the "type" field. */
63 const uint16_t ospf6_packet_minlen
[OSPF6_MESSAGE_TYPE_ALL
] = {
66 OSPF6_DB_DESC_MIN_SIZE
,
67 OSPF6_LS_REQ_MIN_SIZE
,
68 OSPF6_LS_UPD_MIN_SIZE
,
69 OSPF6_LS_ACK_MIN_SIZE
};
71 /* Minimum (besides the standard LSA header) lengths for LSAs of particular
72 types, offset is the "LSA function code" portion of "LSA type" field. */
73 const uint16_t ospf6_lsa_minlen
[OSPF6_LSTYPE_SIZE
] = {
75 /* 0x2001 */ OSPF6_ROUTER_LSA_MIN_SIZE
,
76 /* 0x2002 */ OSPF6_NETWORK_LSA_MIN_SIZE
,
77 /* 0x2003 */ OSPF6_INTER_PREFIX_LSA_MIN_SIZE
,
78 /* 0x2004 */ OSPF6_INTER_ROUTER_LSA_FIX_SIZE
,
79 /* 0x4005 */ OSPF6_AS_EXTERNAL_LSA_MIN_SIZE
,
81 /* 0x2007 */ OSPF6_AS_EXTERNAL_LSA_MIN_SIZE
,
82 /* 0x0008 */ OSPF6_LINK_LSA_MIN_SIZE
,
83 /* 0x2009 */ OSPF6_INTRA_PREFIX_LSA_MIN_SIZE
};
87 static void ospf6_header_print(struct ospf6_header
*oh
)
89 char router_id
[16], area_id
[16];
90 inet_ntop(AF_INET
, &oh
->router_id
, router_id
, sizeof(router_id
));
91 inet_ntop(AF_INET
, &oh
->area_id
, area_id
, sizeof(area_id
));
93 zlog_debug(" OSPFv%d Type:%d Len:%hu Router-ID:%s", oh
->version
,
94 oh
->type
, ntohs(oh
->length
), router_id
);
95 zlog_debug(" Area-ID:%s Cksum:%hx Instance-ID:%d", area_id
,
96 ntohs(oh
->checksum
), oh
->instance_id
);
99 void ospf6_hello_print(struct ospf6_header
*oh
)
101 struct ospf6_hello
*hello
;
103 char drouter
[16], bdrouter
[16], neighbor
[16];
106 ospf6_header_print(oh
);
107 assert(oh
->type
== OSPF6_MESSAGE_TYPE_HELLO
);
109 hello
= (struct ospf6_hello
*)((caddr_t
)oh
110 + sizeof(struct ospf6_header
));
112 inet_ntop(AF_INET
, &hello
->drouter
, drouter
, sizeof(drouter
));
113 inet_ntop(AF_INET
, &hello
->bdrouter
, bdrouter
, sizeof(bdrouter
));
114 ospf6_options_printbuf(hello
->options
, options
, sizeof(options
));
116 zlog_debug(" I/F-Id:%ld Priority:%d Option:%s",
117 (unsigned long)ntohl(hello
->interface_id
), hello
->priority
,
119 zlog_debug(" HelloInterval:%hu DeadInterval:%hu",
120 ntohs(hello
->hello_interval
), ntohs(hello
->dead_interval
));
121 zlog_debug(" DR:%s BDR:%s", drouter
, bdrouter
);
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 inet_ntop(AF_INET
, (void *)p
, neighbor
, sizeof(neighbor
));
127 zlog_debug(" Neighbor: %s", neighbor
);
130 assert(p
== OSPF6_MESSAGE_END(oh
));
133 void ospf6_dbdesc_print(struct ospf6_header
*oh
)
135 struct ospf6_dbdesc
*dbdesc
;
139 ospf6_header_print(oh
);
140 assert(oh
->type
== OSPF6_MESSAGE_TYPE_DBDESC
);
142 dbdesc
= (struct ospf6_dbdesc
*)((caddr_t
)oh
143 + sizeof(struct ospf6_header
));
145 ospf6_options_printbuf(dbdesc
->options
, options
, sizeof(options
));
147 zlog_debug(" MBZ: %#x Option: %s IfMTU: %hu", dbdesc
->reserved1
,
148 options
, ntohs(dbdesc
->ifmtu
));
149 zlog_debug(" MBZ: %#x Bits: %s%s%s SeqNum: %#lx", dbdesc
->reserved2
,
150 (CHECK_FLAG(dbdesc
->bits
, OSPF6_DBDESC_IBIT
) ? "I" : "-"),
151 (CHECK_FLAG(dbdesc
->bits
, OSPF6_DBDESC_MBIT
) ? "M" : "-"),
152 (CHECK_FLAG(dbdesc
->bits
, OSPF6_DBDESC_MSBIT
) ? "m" : "s"),
153 (unsigned long)ntohl(dbdesc
->seqnum
));
155 for (p
= (char *)((caddr_t
)dbdesc
+ sizeof(struct ospf6_dbdesc
));
156 p
+ sizeof(struct ospf6_lsa_header
) <= OSPF6_MESSAGE_END(oh
);
157 p
+= sizeof(struct ospf6_lsa_header
))
158 ospf6_lsa_header_print_raw((struct ospf6_lsa_header
*)p
);
160 assert(p
== OSPF6_MESSAGE_END(oh
));
163 void ospf6_lsreq_print(struct ospf6_header
*oh
)
165 char id
[16], adv_router
[16];
168 ospf6_header_print(oh
);
169 assert(oh
->type
== OSPF6_MESSAGE_TYPE_LSREQ
);
171 for (p
= (char *)((caddr_t
)oh
+ sizeof(struct ospf6_header
));
172 p
+ sizeof(struct ospf6_lsreq_entry
) <= OSPF6_MESSAGE_END(oh
);
173 p
+= sizeof(struct ospf6_lsreq_entry
)) {
174 struct ospf6_lsreq_entry
*e
= (struct ospf6_lsreq_entry
*)p
;
175 inet_ntop(AF_INET
, &e
->adv_router
, adv_router
,
177 inet_ntop(AF_INET
, &e
->id
, id
, sizeof(id
));
178 zlog_debug(" [%s Id:%s Adv:%s]", ospf6_lstype_name(e
->type
),
182 assert(p
== OSPF6_MESSAGE_END(oh
));
185 void ospf6_lsupdate_print(struct ospf6_header
*oh
)
187 struct ospf6_lsupdate
*lsupdate
;
191 ospf6_header_print(oh
);
192 assert(oh
->type
== OSPF6_MESSAGE_TYPE_LSUPDATE
);
194 lsupdate
= (struct ospf6_lsupdate
*)((caddr_t
)oh
195 + sizeof(struct ospf6_header
));
197 num
= ntohl(lsupdate
->lsa_number
);
198 zlog_debug(" Number of LSA: %ld", num
);
200 for (p
= (char *)((caddr_t
)lsupdate
+ sizeof(struct ospf6_lsupdate
));
201 p
< OSPF6_MESSAGE_END(oh
)
202 && p
+ OSPF6_LSA_SIZE(p
) <= OSPF6_MESSAGE_END(oh
);
203 p
+= OSPF6_LSA_SIZE(p
)) {
204 ospf6_lsa_header_print_raw((struct ospf6_lsa_header
*)p
);
207 assert(p
== OSPF6_MESSAGE_END(oh
));
210 void ospf6_lsack_print(struct ospf6_header
*oh
)
214 ospf6_header_print(oh
);
215 assert(oh
->type
== OSPF6_MESSAGE_TYPE_LSACK
);
217 for (p
= (char *)((caddr_t
)oh
+ sizeof(struct ospf6_header
));
218 p
+ sizeof(struct ospf6_lsa_header
) <= OSPF6_MESSAGE_END(oh
);
219 p
+= sizeof(struct ospf6_lsa_header
))
220 ospf6_lsa_header_print_raw((struct ospf6_lsa_header
*)p
);
222 assert(p
== OSPF6_MESSAGE_END(oh
));
225 static void ospf6_hello_recv(struct in6_addr
*src
, struct in6_addr
*dst
,
226 struct ospf6_interface
*oi
,
227 struct ospf6_header
*oh
)
229 struct ospf6_hello
*hello
;
230 struct ospf6_neighbor
*on
;
233 int neighborchange
= 0;
234 int neighbor_ifindex_change
= 0;
237 hello
= (struct ospf6_hello
*)((caddr_t
)oh
238 + sizeof(struct ospf6_header
));
240 /* HelloInterval check */
241 if (ntohs(hello
->hello_interval
) != oi
->hello_interval
) {
242 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
243 zlog_debug("HelloInterval mismatch");
247 /* RouterDeadInterval check */
248 if (ntohs(hello
->dead_interval
) != oi
->dead_interval
) {
249 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
250 zlog_debug("RouterDeadInterval mismatch");
255 if (OSPF6_OPT_ISSET(hello
->options
, OSPF6_OPT_E
)
256 != OSPF6_OPT_ISSET(oi
->area
->options
, OSPF6_OPT_E
)) {
257 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
258 zlog_debug("E-bit mismatch");
262 /* Find neighbor, create if not exist */
263 on
= ospf6_neighbor_lookup(oh
->router_id
, oi
);
265 on
= ospf6_neighbor_create(oh
->router_id
, oi
);
266 on
->prev_drouter
= on
->drouter
= hello
->drouter
;
267 on
->prev_bdrouter
= on
->bdrouter
= hello
->bdrouter
;
268 on
->priority
= hello
->priority
;
271 /* Always override neighbor's source address */
272 memcpy(&on
->linklocal_addr
, src
, sizeof(struct in6_addr
));
274 /* Neighbor ifindex check */
275 if (on
->ifindex
!= (ifindex_t
)ntohl(hello
->interface_id
)) {
276 on
->ifindex
= ntohl(hello
->interface_id
);
277 neighbor_ifindex_change
++;
281 for (p
= (char *)((caddr_t
)hello
+ sizeof(struct ospf6_hello
));
282 p
+ sizeof(uint32_t) <= OSPF6_MESSAGE_END(oh
);
283 p
+= sizeof(uint32_t)) {
284 uint32_t *router_id
= (uint32_t *)p
;
286 if (*router_id
== oi
->area
->ospf6
->router_id
)
290 assert(p
== OSPF6_MESSAGE_END(oh
));
292 /* RouterPriority check */
293 if (on
->priority
!= hello
->priority
) {
294 on
->priority
= hello
->priority
;
299 if (on
->drouter
!= hello
->drouter
) {
300 on
->prev_drouter
= on
->drouter
;
301 on
->drouter
= hello
->drouter
;
302 if (on
->prev_drouter
== on
->router_id
303 || on
->drouter
== on
->router_id
)
308 if (on
->bdrouter
!= hello
->bdrouter
) {
309 on
->prev_bdrouter
= on
->bdrouter
;
310 on
->bdrouter
= hello
->bdrouter
;
311 if (on
->prev_bdrouter
== on
->router_id
312 || on
->bdrouter
== on
->router_id
)
316 /* BackupSeen check */
317 if (oi
->state
== OSPF6_INTERFACE_WAITING
) {
318 if (hello
->bdrouter
== on
->router_id
)
320 else if (hello
->drouter
== on
->router_id
321 && hello
->bdrouter
== htonl(0))
327 /* Execute neighbor events */
328 thread_execute(master
, hello_received
, on
, 0);
330 thread_execute(master
, twoway_received
, on
, 0);
332 thread_execute(master
, oneway_received
, on
, 0);
334 /* Schedule interface events */
336 thread_add_event(master
, backup_seen
, oi
, 0, NULL
);
338 thread_add_event(master
, neighbor_change
, oi
, 0, NULL
);
340 if (neighbor_ifindex_change
&& on
->state
== OSPF6_NEIGHBOR_FULL
)
341 OSPF6_ROUTER_LSA_SCHEDULE(oi
->area
);
344 static void ospf6_dbdesc_recv_master(struct ospf6_header
*oh
,
345 struct ospf6_neighbor
*on
)
347 struct ospf6_dbdesc
*dbdesc
;
350 dbdesc
= (struct ospf6_dbdesc
*)((caddr_t
)oh
351 + sizeof(struct ospf6_header
));
353 if (on
->state
< OSPF6_NEIGHBOR_INIT
) {
354 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
355 zlog_debug("Neighbor state less than Init, ignore");
360 case OSPF6_NEIGHBOR_TWOWAY
:
361 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
362 zlog_debug("Neighbor state is 2-Way, ignore");
365 case OSPF6_NEIGHBOR_INIT
:
366 thread_execute(master
, twoway_received
, on
, 0);
367 if (on
->state
!= OSPF6_NEIGHBOR_EXSTART
) {
368 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
370 "Neighbor state is not ExStart, ignore");
373 /* else fall through to ExStart */
375 case OSPF6_NEIGHBOR_EXSTART
:
376 /* if neighbor obeys us as our slave, schedule negotiation_done
377 and process LSA Headers. Otherwise, ignore this message */
378 if (!CHECK_FLAG(dbdesc
->bits
, OSPF6_DBDESC_MSBIT
)
379 && !CHECK_FLAG(dbdesc
->bits
, OSPF6_DBDESC_IBIT
)
380 && ntohl(dbdesc
->seqnum
) == on
->dbdesc_seqnum
) {
381 /* execute NegotiationDone */
382 thread_execute(master
, negotiation_done
, on
, 0);
384 /* Record neighbor options */
385 memcpy(on
->options
, dbdesc
->options
,
386 sizeof(on
->options
));
388 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
389 zlog_debug("Negotiation failed");
392 /* fall through to exchange */
394 case OSPF6_NEIGHBOR_EXCHANGE
:
395 if (!memcmp(dbdesc
, &on
->dbdesc_last
,
396 sizeof(struct ospf6_dbdesc
))) {
397 /* Duplicated DatabaseDescription is dropped by master
399 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
401 "Duplicated dbdesc discarded by Master, ignore");
405 if (CHECK_FLAG(dbdesc
->bits
, OSPF6_DBDESC_MSBIT
)) {
406 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
407 zlog_debug("Master/Slave bit mismatch");
408 thread_add_event(master
, seqnumber_mismatch
, on
, 0,
413 if (CHECK_FLAG(dbdesc
->bits
, OSPF6_DBDESC_IBIT
)) {
414 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
415 zlog_debug("Initialize bit mismatch");
416 thread_add_event(master
, seqnumber_mismatch
, on
, 0,
421 if (memcmp(on
->options
, dbdesc
->options
, sizeof(on
->options
))) {
422 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
423 zlog_debug("Option field mismatch");
424 thread_add_event(master
, seqnumber_mismatch
, on
, 0,
429 if (ntohl(dbdesc
->seqnum
) != on
->dbdesc_seqnum
) {
430 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
432 "Sequence number mismatch (%#lx expected)",
433 (unsigned long)on
->dbdesc_seqnum
);
434 thread_add_event(master
, seqnumber_mismatch
, on
, 0,
440 case OSPF6_NEIGHBOR_LOADING
:
441 case OSPF6_NEIGHBOR_FULL
:
442 if (!memcmp(dbdesc
, &on
->dbdesc_last
,
443 sizeof(struct ospf6_dbdesc
))) {
444 /* Duplicated DatabaseDescription is dropped by master
446 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
448 "Duplicated dbdesc discarded by Master, ignore");
452 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
453 zlog_debug("Not duplicate dbdesc in state %s",
454 ospf6_neighbor_state_str
[on
->state
]);
455 thread_add_event(master
, seqnumber_mismatch
, on
, 0, NULL
);
463 /* Process LSA headers */
464 for (p
= (char *)((caddr_t
)dbdesc
+ sizeof(struct ospf6_dbdesc
));
465 p
+ sizeof(struct ospf6_lsa_header
) <= OSPF6_MESSAGE_END(oh
);
466 p
+= sizeof(struct ospf6_lsa_header
)) {
467 struct ospf6_lsa
*his
, *mine
;
468 struct ospf6_lsdb
*lsdb
= NULL
;
470 his
= ospf6_lsa_create_headeronly((struct ospf6_lsa_header
*)p
);
472 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
473 zlog_debug("%s", his
->name
);
475 switch (OSPF6_LSA_SCOPE(his
->header
->type
)) {
476 case OSPF6_SCOPE_LINKLOCAL
:
477 lsdb
= on
->ospf6_if
->lsdb
;
479 case OSPF6_SCOPE_AREA
:
480 lsdb
= on
->ospf6_if
->area
->lsdb
;
483 lsdb
= on
->ospf6_if
->area
->ospf6
->lsdb
;
485 case OSPF6_SCOPE_RESERVED
:
486 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
487 zlog_debug("Ignoring LSA of reserved scope");
488 ospf6_lsa_delete(his
);
493 if (ntohs(his
->header
->type
) == OSPF6_LSTYPE_AS_EXTERNAL
494 && IS_AREA_STUB(on
->ospf6_if
->area
)) {
495 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
497 "SeqNumMismatch (E-bit mismatch), discard");
498 ospf6_lsa_delete(his
);
499 thread_add_event(master
, seqnumber_mismatch
, on
, 0,
504 mine
= ospf6_lsdb_lookup(his
->header
->type
, his
->header
->id
,
505 his
->header
->adv_router
, lsdb
);
507 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
508 zlog_debug("Add request (No database copy)");
509 ospf6_lsdb_add(ospf6_lsa_copy(his
), on
->request_list
);
510 } else if (ospf6_lsa_compare(his
, mine
) < 0) {
511 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
512 zlog_debug("Add request (Received MoreRecent)");
513 ospf6_lsdb_add(ospf6_lsa_copy(his
), on
->request_list
);
515 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
516 zlog_debug("Discard (Existing MoreRecent)");
518 ospf6_lsa_delete(his
);
521 assert(p
== OSPF6_MESSAGE_END(oh
));
523 /* Increment sequence number */
526 /* schedule send lsreq */
527 if (on
->request_list
->count
)
528 thread_add_event(master
, ospf6_lsreq_send
, on
, 0,
529 &on
->thread_send_lsreq
);
531 THREAD_OFF(on
->thread_send_dbdesc
);
534 if (!CHECK_FLAG(dbdesc
->bits
, OSPF6_DBDESC_MBIT
)
535 && !CHECK_FLAG(on
->dbdesc_bits
, OSPF6_DBDESC_MBIT
))
536 thread_add_event(master
, exchange_done
, on
, 0, NULL
);
538 on
->thread_send_dbdesc
= NULL
;
539 thread_add_event(master
, ospf6_dbdesc_send_newone
, on
, 0,
540 &on
->thread_send_dbdesc
);
543 /* save last received dbdesc */
544 memcpy(&on
->dbdesc_last
, dbdesc
, sizeof(struct ospf6_dbdesc
));
547 static void ospf6_dbdesc_recv_slave(struct ospf6_header
*oh
,
548 struct ospf6_neighbor
*on
)
550 struct ospf6_dbdesc
*dbdesc
;
553 dbdesc
= (struct ospf6_dbdesc
*)((caddr_t
)oh
554 + sizeof(struct ospf6_header
));
556 if (on
->state
< OSPF6_NEIGHBOR_INIT
) {
557 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
558 zlog_debug("Neighbor state less than Init, ignore");
563 case OSPF6_NEIGHBOR_TWOWAY
:
564 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
565 zlog_debug("Neighbor state is 2-Way, ignore");
568 case OSPF6_NEIGHBOR_INIT
:
569 thread_execute(master
, twoway_received
, on
, 0);
570 if (on
->state
!= OSPF6_NEIGHBOR_EXSTART
) {
571 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
573 "Neighbor state is not ExStart, ignore");
576 /* else fall through to ExStart */
578 case OSPF6_NEIGHBOR_EXSTART
:
579 /* If the neighbor is Master, act as Slave. Schedule
581 and process LSA Headers. Otherwise, ignore this message */
582 if (CHECK_FLAG(dbdesc
->bits
, OSPF6_DBDESC_IBIT
)
583 && CHECK_FLAG(dbdesc
->bits
, OSPF6_DBDESC_MBIT
)
584 && CHECK_FLAG(dbdesc
->bits
, OSPF6_DBDESC_MSBIT
)
586 == sizeof(struct ospf6_header
)
587 + sizeof(struct ospf6_dbdesc
)) {
588 /* set the master/slave bit to slave */
589 UNSET_FLAG(on
->dbdesc_bits
, OSPF6_DBDESC_MSBIT
);
591 /* set the DD sequence number to one specified by master
593 on
->dbdesc_seqnum
= ntohl(dbdesc
->seqnum
);
595 /* schedule NegotiationDone */
596 thread_execute(master
, negotiation_done
, on
, 0);
598 /* Record neighbor options */
599 memcpy(on
->options
, dbdesc
->options
,
600 sizeof(on
->options
));
602 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
603 zlog_debug("Negotiation failed");
608 case OSPF6_NEIGHBOR_EXCHANGE
:
609 if (!memcmp(dbdesc
, &on
->dbdesc_last
,
610 sizeof(struct ospf6_dbdesc
))) {
611 /* Duplicated DatabaseDescription causes slave to
613 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
615 "Duplicated dbdesc causes retransmit");
616 THREAD_OFF(on
->thread_send_dbdesc
);
617 on
->thread_send_dbdesc
= NULL
;
618 thread_add_event(master
, ospf6_dbdesc_send
, on
, 0,
619 &on
->thread_send_dbdesc
);
623 if (!CHECK_FLAG(dbdesc
->bits
, OSPF6_DBDESC_MSBIT
)) {
624 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
625 zlog_debug("Master/Slave bit mismatch");
626 thread_add_event(master
, seqnumber_mismatch
, on
, 0,
631 if (CHECK_FLAG(dbdesc
->bits
, OSPF6_DBDESC_IBIT
)) {
632 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
633 zlog_debug("Initialize bit mismatch");
634 thread_add_event(master
, seqnumber_mismatch
, on
, 0,
639 if (memcmp(on
->options
, dbdesc
->options
, sizeof(on
->options
))) {
640 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
641 zlog_debug("Option field mismatch");
642 thread_add_event(master
, seqnumber_mismatch
, on
, 0,
647 if (ntohl(dbdesc
->seqnum
) != on
->dbdesc_seqnum
+ 1) {
648 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
650 "Sequence number mismatch (%#lx expected)",
651 (unsigned long)on
->dbdesc_seqnum
+ 1);
652 thread_add_event(master
, seqnumber_mismatch
, on
, 0,
658 case OSPF6_NEIGHBOR_LOADING
:
659 case OSPF6_NEIGHBOR_FULL
:
660 if (!memcmp(dbdesc
, &on
->dbdesc_last
,
661 sizeof(struct ospf6_dbdesc
))) {
662 /* Duplicated DatabaseDescription causes slave to
664 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
666 "Duplicated dbdesc causes retransmit");
667 THREAD_OFF(on
->thread_send_dbdesc
);
668 thread_add_event(master
, ospf6_dbdesc_send
, on
, 0,
669 &on
->thread_send_dbdesc
);
673 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
674 zlog_debug("Not duplicate dbdesc in state %s",
675 ospf6_neighbor_state_str
[on
->state
]);
676 thread_add_event(master
, seqnumber_mismatch
, on
, 0, NULL
);
684 /* Process LSA headers */
685 for (p
= (char *)((caddr_t
)dbdesc
+ sizeof(struct ospf6_dbdesc
));
686 p
+ sizeof(struct ospf6_lsa_header
) <= OSPF6_MESSAGE_END(oh
);
687 p
+= sizeof(struct ospf6_lsa_header
)) {
688 struct ospf6_lsa
*his
, *mine
;
689 struct ospf6_lsdb
*lsdb
= NULL
;
691 his
= ospf6_lsa_create_headeronly((struct ospf6_lsa_header
*)p
);
693 switch (OSPF6_LSA_SCOPE(his
->header
->type
)) {
694 case OSPF6_SCOPE_LINKLOCAL
:
695 lsdb
= on
->ospf6_if
->lsdb
;
697 case OSPF6_SCOPE_AREA
:
698 lsdb
= on
->ospf6_if
->area
->lsdb
;
701 lsdb
= on
->ospf6_if
->area
->ospf6
->lsdb
;
703 case OSPF6_SCOPE_RESERVED
:
704 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
705 zlog_debug("Ignoring LSA of reserved scope");
706 ospf6_lsa_delete(his
);
711 if (OSPF6_LSA_SCOPE(his
->header
->type
) == OSPF6_SCOPE_AS
712 && IS_AREA_STUB(on
->ospf6_if
->area
)) {
713 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
714 zlog_debug("E-bit mismatch with LSA Headers");
715 ospf6_lsa_delete(his
);
716 thread_add_event(master
, seqnumber_mismatch
, on
, 0,
721 mine
= ospf6_lsdb_lookup(his
->header
->type
, his
->header
->id
,
722 his
->header
->adv_router
, lsdb
);
723 if (mine
== NULL
|| ospf6_lsa_compare(his
, mine
) < 0) {
724 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
725 zlog_debug("Add request-list: %s", his
->name
);
726 ospf6_lsdb_add(ospf6_lsa_copy(his
), on
->request_list
);
728 ospf6_lsa_delete(his
);
731 assert(p
== OSPF6_MESSAGE_END(oh
));
733 /* Set sequence number to Master's */
734 on
->dbdesc_seqnum
= ntohl(dbdesc
->seqnum
);
736 /* schedule send lsreq */
737 if (on
->request_list
->count
)
738 thread_add_event(master
, ospf6_lsreq_send
, on
, 0,
739 &on
->thread_send_lsreq
);
741 THREAD_OFF(on
->thread_send_dbdesc
);
742 thread_add_event(master
, ospf6_dbdesc_send_newone
, on
, 0,
743 &on
->thread_send_dbdesc
);
745 /* save last received dbdesc */
746 memcpy(&on
->dbdesc_last
, dbdesc
, sizeof(struct ospf6_dbdesc
));
749 static void ospf6_dbdesc_recv(struct in6_addr
*src
, struct in6_addr
*dst
,
750 struct ospf6_interface
*oi
,
751 struct ospf6_header
*oh
)
753 struct ospf6_neighbor
*on
;
754 struct ospf6_dbdesc
*dbdesc
;
756 on
= ospf6_neighbor_lookup(oh
->router_id
, oi
);
758 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
759 zlog_debug("Neighbor not found, ignore");
763 dbdesc
= (struct ospf6_dbdesc
*)((caddr_t
)oh
764 + sizeof(struct ospf6_header
));
766 /* Interface MTU check */
767 if (!oi
->mtu_ignore
&& ntohs(dbdesc
->ifmtu
) != oi
->ifmtu
) {
768 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
769 zlog_debug("I/F MTU mismatch");
773 if (dbdesc
->reserved1
|| dbdesc
->reserved2
) {
774 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
776 "Non-0 reserved field in %s's DbDesc, correct",
778 dbdesc
->reserved1
= 0;
779 dbdesc
->reserved2
= 0;
784 if (ntohl(oh
->router_id
) < ntohl(ospf6
->router_id
))
785 ospf6_dbdesc_recv_master(oh
, on
);
786 else if (ntohl(ospf6
->router_id
) < ntohl(oh
->router_id
))
787 ospf6_dbdesc_recv_slave(oh
, on
);
789 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
790 zlog_debug("Can't decide which is master, ignore");
794 static void ospf6_lsreq_recv(struct in6_addr
*src
, struct in6_addr
*dst
,
795 struct ospf6_interface
*oi
,
796 struct ospf6_header
*oh
)
798 struct ospf6_neighbor
*on
;
800 struct ospf6_lsreq_entry
*e
;
801 struct ospf6_lsdb
*lsdb
= NULL
;
802 struct ospf6_lsa
*lsa
;
804 on
= ospf6_neighbor_lookup(oh
->router_id
, oi
);
806 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
807 zlog_debug("Neighbor not found, ignore");
811 if (on
->state
!= OSPF6_NEIGHBOR_EXCHANGE
812 && on
->state
!= OSPF6_NEIGHBOR_LOADING
813 && on
->state
!= OSPF6_NEIGHBOR_FULL
) {
814 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
815 zlog_debug("Neighbor state less than Exchange, ignore");
821 /* Process each request */
822 for (p
= (char *)((caddr_t
)oh
+ sizeof(struct ospf6_header
));
823 p
+ sizeof(struct ospf6_lsreq_entry
) <= OSPF6_MESSAGE_END(oh
);
824 p
+= sizeof(struct ospf6_lsreq_entry
)) {
825 e
= (struct ospf6_lsreq_entry
*)p
;
827 switch (OSPF6_LSA_SCOPE(e
->type
)) {
828 case OSPF6_SCOPE_LINKLOCAL
:
829 lsdb
= on
->ospf6_if
->lsdb
;
831 case OSPF6_SCOPE_AREA
:
832 lsdb
= on
->ospf6_if
->area
->lsdb
;
835 lsdb
= on
->ospf6_if
->area
->ospf6
->lsdb
;
838 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
839 zlog_debug("Ignoring LSA of reserved scope");
844 /* Find database copy */
845 lsa
= ospf6_lsdb_lookup(e
->type
, e
->id
, e
->adv_router
, lsdb
);
847 char id
[16], adv_router
[16];
848 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
)) {
849 inet_ntop(AF_INET
, &e
->id
, id
, sizeof(id
));
850 inet_ntop(AF_INET
, &e
->adv_router
, adv_router
,
853 "Can't find requested [%s Id:%s Adv:%s]",
854 ospf6_lstype_name(e
->type
), id
,
857 thread_add_event(master
, bad_lsreq
, on
, 0, NULL
);
861 ospf6_lsdb_add(ospf6_lsa_copy(lsa
), on
->lsupdate_list
);
864 assert(p
== OSPF6_MESSAGE_END(oh
));
866 /* schedule send lsupdate */
867 THREAD_OFF(on
->thread_send_lsupdate
);
868 thread_add_event(master
, ospf6_lsupdate_send_neighbor
, on
, 0,
869 &on
->thread_send_lsupdate
);
872 /* Verify, that the specified memory area contains exactly N valid IPv6
873 prefixes as specified by RFC5340, A.4.1. */
874 static unsigned ospf6_prefixes_examin(
875 struct ospf6_prefix
*current
, /* start of buffer */
877 const uint32_t req_num_pfxs
/* always compared with the actual number
881 uint8_t requested_pfx_bytes
;
882 uint32_t real_num_pfxs
= 0;
885 if (length
< OSPF6_PREFIX_MIN_SIZE
) {
886 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN
,
888 zlog_debug("%s: undersized IPv6 prefix header",
892 /* safe to look deeper */
893 if (current
->prefix_length
> IPV6_MAX_BITLEN
) {
894 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN
,
896 zlog_debug("%s: invalid PrefixLength (%u bits)",
897 __func__
, current
->prefix_length
);
900 /* covers both fixed- and variable-sized fields */
901 requested_pfx_bytes
=
902 OSPF6_PREFIX_MIN_SIZE
903 + OSPF6_PREFIX_SPACE(current
->prefix_length
);
904 if (requested_pfx_bytes
> length
) {
905 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN
,
907 zlog_debug("%s: undersized IPv6 prefix",
912 length
-= requested_pfx_bytes
;
913 current
= (struct ospf6_prefix
*)((caddr_t
)current
914 + requested_pfx_bytes
);
917 if (real_num_pfxs
!= req_num_pfxs
) {
918 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN
, RECV
))
920 "%s: IPv6 prefix number mismatch (%u required, %u real)",
921 __func__
, req_num_pfxs
, real_num_pfxs
);
927 /* Verify an LSA to have a valid length and dispatch further (where
928 appropriate) to check if the contents, including nested IPv6 prefixes,
929 is properly sized/aligned within the LSA. Note that this function gets
930 LSA type in network byte order, uses in host byte order and passes to
931 ospf6_lstype_name() in network byte order again. */
932 static unsigned ospf6_lsa_examin(struct ospf6_lsa_header
*lsah
,
933 const uint16_t lsalen
,
934 const uint8_t headeronly
)
936 struct ospf6_intra_prefix_lsa
*intra_prefix_lsa
;
937 struct ospf6_as_external_lsa
*as_external_lsa
;
938 struct ospf6_link_lsa
*link_lsa
;
943 /* In case an additional minimum length constraint is defined for
945 LSA type, make sure that this constraint is met. */
946 lsatype
= ntohs(lsah
->type
);
947 ltindex
= lsatype
& OSPF6_LSTYPE_FCODE_MASK
;
948 if (ltindex
< OSPF6_LSTYPE_SIZE
&& ospf6_lsa_minlen
[ltindex
]
949 && lsalen
< ospf6_lsa_minlen
[ltindex
] + OSPF6_LSA_HEADER_SIZE
) {
950 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN
, RECV
))
951 zlog_debug("%s: undersized (%u B) LSA", __func__
,
956 case OSPF6_LSTYPE_ROUTER
:
957 /* RFC5340 A.4.3, LSA header + OSPF6_ROUTER_LSA_MIN_SIZE bytes
959 by N>=0 interface descriptions. */
960 if ((lsalen
- OSPF6_LSA_HEADER_SIZE
- OSPF6_ROUTER_LSA_MIN_SIZE
)
961 % OSPF6_ROUTER_LSDESC_FIX_SIZE
) {
962 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN
,
965 "%s: interface description alignment error",
970 case OSPF6_LSTYPE_NETWORK
:
971 /* RFC5340 A.4.4, LSA header + OSPF6_NETWORK_LSA_MIN_SIZE bytes
972 followed by N>=0 attached router descriptions. */
973 if ((lsalen
- OSPF6_LSA_HEADER_SIZE
974 - OSPF6_NETWORK_LSA_MIN_SIZE
)
975 % OSPF6_NETWORK_LSDESC_FIX_SIZE
) {
976 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN
,
979 "%s: router description alignment error",
984 case OSPF6_LSTYPE_INTER_PREFIX
:
985 /* RFC5340 A.4.5, LSA header + OSPF6_INTER_PREFIX_LSA_MIN_SIZE
987 followed by 3-4 fields of a single IPv6 prefix. */
990 return ospf6_prefixes_examin(
992 *)((caddr_t
)lsah
+ OSPF6_LSA_HEADER_SIZE
993 + OSPF6_INTER_PREFIX_LSA_MIN_SIZE
),
994 lsalen
- OSPF6_LSA_HEADER_SIZE
995 - OSPF6_INTER_PREFIX_LSA_MIN_SIZE
,
997 case OSPF6_LSTYPE_INTER_ROUTER
:
998 /* RFC5340 A.4.6, fixed-size LSA. */
1000 > OSPF6_LSA_HEADER_SIZE
+ OSPF6_INTER_ROUTER_LSA_FIX_SIZE
) {
1001 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN
,
1003 zlog_debug("%s: oversized (%u B) LSA", __func__
,
1008 case OSPF6_LSTYPE_AS_EXTERNAL
: /* RFC5340 A.4.7, same as A.4.8. */
1009 case OSPF6_LSTYPE_TYPE_7
:
1010 /* RFC5340 A.4.8, LSA header + OSPF6_AS_EXTERNAL_LSA_MIN_SIZE
1012 followed by 3-4 fields of IPv6 prefix and 3 conditional LSA
1014 16 bytes of forwarding address, 4 bytes of external route
1016 4 bytes of referenced link state ID. */
1020 (struct ospf6_as_external_lsa
1021 *)((caddr_t
)lsah
+ OSPF6_LSA_HEADER_SIZE
);
1023 OSPF6_LSA_HEADER_SIZE
+ OSPF6_AS_EXTERNAL_LSA_MIN_SIZE
;
1024 /* To find out if the last optional field (Referenced Link State
1026 assumed in this LSA, we need to access fixed fields of the
1028 prefix before ospf6_prefix_examin() confirms its sizing. */
1029 if (exp_length
+ OSPF6_PREFIX_MIN_SIZE
> lsalen
) {
1030 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN
,
1032 zlog_debug("%s: undersized (%u B) LSA header",
1036 /* forwarding address */
1037 if (CHECK_FLAG(as_external_lsa
->bits_metric
, OSPF6_ASBR_BIT_F
))
1039 /* external route tag */
1040 if (CHECK_FLAG(as_external_lsa
->bits_metric
, OSPF6_ASBR_BIT_T
))
1042 /* referenced link state ID */
1043 if (as_external_lsa
->prefix
.u
._prefix_referenced_lstype
)
1045 /* All the fixed-size fields (mandatory and optional) must fit.
1047 this check does not include any IPv6 prefix fields. */
1048 if (exp_length
> lsalen
) {
1049 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN
,
1051 zlog_debug("%s: undersized (%u B) LSA header",
1055 /* The last call completely covers the remainder (IPv6 prefix).
1057 return ospf6_prefixes_examin(
1058 (struct ospf6_prefix
1059 *)((caddr_t
)as_external_lsa
1060 + OSPF6_AS_EXTERNAL_LSA_MIN_SIZE
),
1061 lsalen
- exp_length
, 1);
1062 case OSPF6_LSTYPE_LINK
:
1063 /* RFC5340 A.4.9, LSA header + OSPF6_LINK_LSA_MIN_SIZE bytes
1065 by N>=0 IPv6 prefix blocks (with N declared beforehand). */
1068 link_lsa
= (struct ospf6_link_lsa
*)((caddr_t
)lsah
1069 + OSPF6_LSA_HEADER_SIZE
);
1070 return ospf6_prefixes_examin(
1071 (struct ospf6_prefix
*)((caddr_t
)link_lsa
1072 + OSPF6_LINK_LSA_MIN_SIZE
),
1073 lsalen
- OSPF6_LSA_HEADER_SIZE
1074 - OSPF6_LINK_LSA_MIN_SIZE
,
1075 ntohl(link_lsa
->prefix_num
) /* 32 bits */
1077 case OSPF6_LSTYPE_INTRA_PREFIX
:
1078 /* RFC5340 A.4.10, LSA header + OSPF6_INTRA_PREFIX_LSA_MIN_SIZE
1080 followed by N>=0 IPv6 prefixes (with N declared beforehand).
1085 (struct ospf6_intra_prefix_lsa
1086 *)((caddr_t
)lsah
+ OSPF6_LSA_HEADER_SIZE
);
1087 return ospf6_prefixes_examin(
1088 (struct ospf6_prefix
1089 *)((caddr_t
)intra_prefix_lsa
1090 + OSPF6_INTRA_PREFIX_LSA_MIN_SIZE
),
1091 lsalen
- OSPF6_LSA_HEADER_SIZE
1092 - OSPF6_INTRA_PREFIX_LSA_MIN_SIZE
,
1093 ntohs(intra_prefix_lsa
->prefix_num
) /* 16 bits */
1096 /* No additional validation is possible for unknown LSA types, which are
1097 themselves valid in OPSFv3, hence the default decision is to accept.
1102 /* Verify if the provided input buffer is a valid sequence of LSAs. This
1103 includes verification of LSA blocks length/alignment and dispatching
1104 of deeper-level checks. */
1106 ospf6_lsaseq_examin(struct ospf6_lsa_header
*lsah
, /* start of buffered data */
1107 size_t length
, const uint8_t headeronly
,
1108 /* When declared_num_lsas is not 0, compare it to the real
1110 and treat the difference as an error. */
1111 const uint32_t declared_num_lsas
)
1113 uint32_t counted_lsas
= 0;
1117 if (length
< OSPF6_LSA_HEADER_SIZE
) {
1118 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN
,
1121 "%s: undersized (%zu B) trailing (#%u) LSA header",
1122 __func__
, length
, counted_lsas
);
1125 /* save on ntohs() calls here and in the LSA validator */
1126 lsalen
= OSPF6_LSA_SIZE(lsah
);
1127 if (lsalen
< OSPF6_LSA_HEADER_SIZE
) {
1128 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN
,
1131 "%s: malformed LSA header #%u, declared length is %u B",
1132 __func__
, counted_lsas
, lsalen
);
1136 /* less checks here and in ospf6_lsa_examin() */
1137 if (MSG_OK
!= ospf6_lsa_examin(lsah
, lsalen
, 1)) {
1138 if (IS_OSPF6_DEBUG_MESSAGE(
1139 OSPF6_MESSAGE_TYPE_UNKNOWN
, RECV
))
1141 "%s: anomaly in header-only %s LSA #%u",
1143 ospf6_lstype_name(lsah
->type
),
1147 lsah
= (struct ospf6_lsa_header
1149 + OSPF6_LSA_HEADER_SIZE
);
1150 length
-= OSPF6_LSA_HEADER_SIZE
;
1152 /* make sure the input buffer is deep enough before
1154 if (lsalen
> length
) {
1155 if (IS_OSPF6_DEBUG_MESSAGE(
1156 OSPF6_MESSAGE_TYPE_UNKNOWN
, RECV
))
1158 "%s: anomaly in %s LSA #%u: declared length is %u B, buffered length is %zu B",
1160 ospf6_lstype_name(lsah
->type
),
1161 counted_lsas
, lsalen
, length
);
1164 if (MSG_OK
!= ospf6_lsa_examin(lsah
, lsalen
, 0)) {
1165 if (IS_OSPF6_DEBUG_MESSAGE(
1166 OSPF6_MESSAGE_TYPE_UNKNOWN
, RECV
))
1168 "%s: anomaly in %s LSA #%u",
1170 ospf6_lstype_name(lsah
->type
),
1174 lsah
= (struct ospf6_lsa_header
*)((caddr_t
)lsah
1181 if (declared_num_lsas
&& counted_lsas
!= declared_num_lsas
) {
1182 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN
, RECV
))
1184 "%s: #LSAs declared (%u) does not match actual (%u)",
1185 __func__
, declared_num_lsas
, counted_lsas
);
1191 /* Verify a complete OSPF packet for proper sizing/alignment. */
1192 static unsigned ospf6_packet_examin(struct ospf6_header
*oh
,
1193 const unsigned bytesonwire
)
1195 struct ospf6_lsupdate
*lsupd
;
1198 /* length, 1st approximation */
1199 if (bytesonwire
< OSPF6_HEADER_SIZE
) {
1200 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN
, RECV
))
1201 zlog_debug("%s: undersized (%u B) packet", __func__
,
1205 /* Now it is safe to access header fields. */
1206 if (bytesonwire
!= ntohs(oh
->length
)) {
1207 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN
, RECV
))
1209 "%s: %s packet length error (%u real, %u declared)",
1210 __func__
, lookup_msg(ospf6_message_type_str
,
1212 bytesonwire
, ntohs(oh
->length
));
1216 if (oh
->version
!= OSPFV3_VERSION
) {
1217 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN
, RECV
))
1218 zlog_debug("%s: invalid (%u) protocol version",
1219 __func__
, oh
->version
);
1222 /* length, 2nd approximation */
1223 if (oh
->type
< OSPF6_MESSAGE_TYPE_ALL
&& ospf6_packet_minlen
[oh
->type
]
1225 < OSPF6_HEADER_SIZE
+ ospf6_packet_minlen
[oh
->type
]) {
1226 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN
, RECV
))
1227 zlog_debug("%s: undersized (%u B) %s packet", __func__
,
1229 lookup_msg(ospf6_message_type_str
, oh
->type
,
1233 /* type-specific deeper validation */
1235 case OSPF6_MESSAGE_TYPE_HELLO
:
1236 /* RFC5340 A.3.2, packet header + OSPF6_HELLO_MIN_SIZE bytes
1238 by N>=0 router-IDs. */
1240 == (bytesonwire
- OSPF6_HEADER_SIZE
- OSPF6_HELLO_MIN_SIZE
)
1243 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN
, RECV
))
1244 zlog_debug("%s: alignment error in %s packet", __func__
,
1245 lookup_msg(ospf6_message_type_str
, oh
->type
,
1248 case OSPF6_MESSAGE_TYPE_DBDESC
:
1249 /* RFC5340 A.3.3, packet header + OSPF6_DB_DESC_MIN_SIZE bytes
1251 by N>=0 header-only LSAs. */
1252 test
= ospf6_lsaseq_examin(
1253 (struct ospf6_lsa_header
*)((caddr_t
)oh
1255 + OSPF6_DB_DESC_MIN_SIZE
),
1256 bytesonwire
- OSPF6_HEADER_SIZE
1257 - OSPF6_DB_DESC_MIN_SIZE
,
1260 case OSPF6_MESSAGE_TYPE_LSREQ
:
1261 /* RFC5340 A.3.4, packet header + N>=0 LS description blocks. */
1263 == (bytesonwire
- OSPF6_HEADER_SIZE
- OSPF6_LS_REQ_MIN_SIZE
)
1264 % OSPF6_LSREQ_LSDESC_FIX_SIZE
)
1266 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN
, RECV
))
1267 zlog_debug("%s: alignment error in %s packet", __func__
,
1268 lookup_msg(ospf6_message_type_str
, oh
->type
,
1271 case OSPF6_MESSAGE_TYPE_LSUPDATE
:
1272 /* RFC5340 A.3.5, packet header + OSPF6_LS_UPD_MIN_SIZE bytes
1274 by N>=0 full LSAs (with N declared beforehand). */
1275 lsupd
= (struct ospf6_lsupdate
*)((caddr_t
)oh
1276 + OSPF6_HEADER_SIZE
);
1277 test
= ospf6_lsaseq_examin(
1278 (struct ospf6_lsa_header
*)((caddr_t
)lsupd
1279 + OSPF6_LS_UPD_MIN_SIZE
),
1280 bytesonwire
- OSPF6_HEADER_SIZE
- OSPF6_LS_UPD_MIN_SIZE
,
1281 0, ntohl(lsupd
->lsa_number
) /* 32 bits */
1284 case OSPF6_MESSAGE_TYPE_LSACK
:
1285 /* RFC5340 A.3.6, packet header + N>=0 header-only LSAs. */
1286 test
= ospf6_lsaseq_examin(
1287 (struct ospf6_lsa_header
*)((caddr_t
)oh
1289 + OSPF6_LS_ACK_MIN_SIZE
),
1290 bytesonwire
- OSPF6_HEADER_SIZE
- OSPF6_LS_ACK_MIN_SIZE
,
1294 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN
, RECV
))
1295 zlog_debug("%s: invalid (%u) message type", __func__
,
1300 && IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN
, RECV
))
1301 zlog_debug("%s: anomaly in %s packet", __func__
,
1302 lookup_msg(ospf6_message_type_str
, oh
->type
, NULL
));
1306 /* Verify particular fields of otherwise correct received OSPF packet to
1307 meet the requirements of RFC. */
1308 static int ospf6_rxpacket_examin(struct ospf6_interface
*oi
,
1309 struct ospf6_header
*oh
,
1310 const unsigned bytesonwire
)
1312 char buf
[2][INET_ADDRSTRLEN
];
1314 if (MSG_OK
!= ospf6_packet_examin(oh
, bytesonwire
))
1318 if (oh
->area_id
!= oi
->area
->area_id
) {
1319 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
)) {
1320 if (oh
->area_id
== OSPF_AREA_BACKBONE
)
1322 "%s: Message may be via Virtual Link: not supported",
1326 "%s: Area-ID mismatch (my %s, rcvd %s)",
1328 inet_ntop(AF_INET
, &oi
->area
->area_id
,
1329 buf
[0], INET_ADDRSTRLEN
),
1330 inet_ntop(AF_INET
, &oh
->area_id
, buf
[1],
1336 /* Instance-ID check */
1337 if (oh
->instance_id
!= oi
->instance_id
) {
1338 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
1339 zlog_debug("%s: Instance-ID mismatch (my %u, rcvd %u)",
1340 __func__
, oi
->instance_id
, oh
->instance_id
);
1344 /* Router-ID check */
1345 if (oh
->router_id
== oi
->area
->ospf6
->router_id
) {
1346 zlog_warn("%s: Duplicate Router-ID (%s)", __func__
,
1347 inet_ntop(AF_INET
, &oh
->router_id
, buf
[0],
1354 static void ospf6_lsupdate_recv(struct in6_addr
*src
, struct in6_addr
*dst
,
1355 struct ospf6_interface
*oi
,
1356 struct ospf6_header
*oh
)
1358 struct ospf6_neighbor
*on
;
1359 struct ospf6_lsupdate
*lsupdate
;
1362 on
= ospf6_neighbor_lookup(oh
->router_id
, oi
);
1364 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
1365 zlog_debug("Neighbor not found, ignore");
1369 if (on
->state
!= OSPF6_NEIGHBOR_EXCHANGE
1370 && on
->state
!= OSPF6_NEIGHBOR_LOADING
1371 && on
->state
!= OSPF6_NEIGHBOR_FULL
) {
1372 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
1373 zlog_debug("Neighbor state less than Exchange, ignore");
1377 lsupdate
= (struct ospf6_lsupdate
*)((caddr_t
)oh
1378 + sizeof(struct ospf6_header
));
1383 for (p
= (char *)((caddr_t
)lsupdate
+ sizeof(struct ospf6_lsupdate
));
1384 p
< OSPF6_MESSAGE_END(oh
)
1385 && p
+ OSPF6_LSA_SIZE(p
) <= OSPF6_MESSAGE_END(oh
);
1386 p
+= OSPF6_LSA_SIZE(p
)) {
1387 ospf6_receive_lsa(on
, (struct ospf6_lsa_header
*)p
);
1390 assert(p
== OSPF6_MESSAGE_END(oh
));
1393 static void ospf6_lsack_recv(struct in6_addr
*src
, struct in6_addr
*dst
,
1394 struct ospf6_interface
*oi
,
1395 struct ospf6_header
*oh
)
1397 struct ospf6_neighbor
*on
;
1399 struct ospf6_lsa
*his
, *mine
;
1400 struct ospf6_lsdb
*lsdb
= NULL
;
1402 assert(oh
->type
== OSPF6_MESSAGE_TYPE_LSACK
);
1404 on
= ospf6_neighbor_lookup(oh
->router_id
, oi
);
1406 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
1407 zlog_debug("Neighbor not found, ignore");
1411 if (on
->state
!= OSPF6_NEIGHBOR_EXCHANGE
1412 && on
->state
!= OSPF6_NEIGHBOR_LOADING
1413 && on
->state
!= OSPF6_NEIGHBOR_FULL
) {
1414 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
1415 zlog_debug("Neighbor state less than Exchange, ignore");
1421 for (p
= (char *)((caddr_t
)oh
+ sizeof(struct ospf6_header
));
1422 p
+ sizeof(struct ospf6_lsa_header
) <= OSPF6_MESSAGE_END(oh
);
1423 p
+= sizeof(struct ospf6_lsa_header
)) {
1424 his
= ospf6_lsa_create_headeronly((struct ospf6_lsa_header
*)p
);
1426 switch (OSPF6_LSA_SCOPE(his
->header
->type
)) {
1427 case OSPF6_SCOPE_LINKLOCAL
:
1428 lsdb
= on
->ospf6_if
->lsdb
;
1430 case OSPF6_SCOPE_AREA
:
1431 lsdb
= on
->ospf6_if
->area
->lsdb
;
1433 case OSPF6_SCOPE_AS
:
1434 lsdb
= on
->ospf6_if
->area
->ospf6
->lsdb
;
1436 case OSPF6_SCOPE_RESERVED
:
1437 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
1438 zlog_debug("Ignoring LSA of reserved scope");
1439 ospf6_lsa_delete(his
);
1444 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
1445 zlog_debug("%s acknowledged by %s", his
->name
,
1448 /* Find database copy */
1449 mine
= ospf6_lsdb_lookup(his
->header
->type
, his
->header
->id
,
1450 his
->header
->adv_router
, lsdb
);
1452 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
1453 zlog_debug("No database copy");
1454 ospf6_lsa_delete(his
);
1458 /* Check if the LSA is on his retrans-list */
1459 mine
= ospf6_lsdb_lookup(his
->header
->type
, his
->header
->id
,
1460 his
->header
->adv_router
,
1463 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
1464 zlog_debug("Not on %s's retrans-list",
1466 ospf6_lsa_delete(his
);
1470 if (ospf6_lsa_compare(his
, mine
) != 0) {
1471 /* Log this questionable acknowledgement,
1472 and examine the next one. */
1473 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
1474 zlog_debug("Questionable acknowledgement");
1475 ospf6_lsa_delete(his
);
1479 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
1481 "Acknowledged, remove from %s's retrans-list",
1484 ospf6_decrement_retrans_count(mine
);
1485 if (OSPF6_LSA_IS_MAXAGE(mine
))
1486 ospf6_maxage_remove(on
->ospf6_if
->area
->ospf6
);
1487 ospf6_lsdb_remove(mine
, on
->retrans_list
);
1488 ospf6_lsa_delete(his
);
1491 assert(p
== OSPF6_MESSAGE_END(oh
));
1494 static uint8_t *recvbuf
= NULL
;
1495 static uint8_t *sendbuf
= NULL
;
1496 static unsigned int iobuflen
= 0;
1498 int ospf6_iobuf_size(unsigned int size
)
1500 uint8_t *recvnew
, *sendnew
;
1502 if (size
<= iobuflen
)
1505 recvnew
= XMALLOC(MTYPE_OSPF6_MESSAGE
, size
);
1506 sendnew
= XMALLOC(MTYPE_OSPF6_MESSAGE
, size
);
1508 XFREE(MTYPE_OSPF6_MESSAGE
, recvbuf
);
1509 XFREE(MTYPE_OSPF6_MESSAGE
, sendbuf
);
1517 void ospf6_message_terminate(void)
1520 XFREE(MTYPE_OSPF6_MESSAGE
, recvbuf
);
1525 XFREE(MTYPE_OSPF6_MESSAGE
, sendbuf
);
1532 int ospf6_receive(struct thread
*thread
)
1536 char srcname
[64], dstname
[64];
1537 struct in6_addr src
, dst
;
1539 struct iovec iovector
[2];
1540 struct ospf6_interface
*oi
;
1541 struct ospf6_header
*oh
;
1543 /* add next read thread */
1544 sockfd
= THREAD_FD(thread
);
1545 thread_add_read(master
, ospf6_receive
, NULL
, sockfd
, NULL
);
1548 memset(&src
, 0, sizeof(src
));
1549 memset(&dst
, 0, sizeof(dst
));
1551 memset(recvbuf
, 0, iobuflen
);
1552 iovector
[0].iov_base
= recvbuf
;
1553 iovector
[0].iov_len
= iobuflen
;
1554 iovector
[1].iov_base
= NULL
;
1555 iovector
[1].iov_len
= 0;
1557 /* receive message */
1558 len
= ospf6_recvmsg(&src
, &dst
, &ifindex
, iovector
);
1559 if (len
> iobuflen
) {
1560 flog_err(EC_LIB_DEVELOPMENT
, "Excess message read");
1564 oi
= ospf6_interface_lookup_by_ifindex(ifindex
);
1565 if (oi
== NULL
|| oi
->area
== NULL
1566 || CHECK_FLAG(oi
->flag
, OSPF6_INTERFACE_DISABLE
)) {
1567 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN
, RECV
))
1568 zlog_debug("Message received on disabled interface");
1571 if (CHECK_FLAG(oi
->flag
, OSPF6_INTERFACE_PASSIVE
)) {
1572 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN
, RECV
))
1573 zlog_debug("%s: Ignore message on passive interface %s",
1574 __func__
, oi
->interface
->name
);
1578 oh
= (struct ospf6_header
*)recvbuf
;
1579 if (ospf6_rxpacket_examin(oi
, oh
, len
) != MSG_OK
)
1582 /* Being here means, that no sizing/alignment issues were detected in
1583 the input packet. This renders the additional checks performed below
1584 and also in the type-specific dispatching functions a dead code,
1585 which can be dismissed in a cleanup-focused review round later. */
1588 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
)) {
1589 inet_ntop(AF_INET6
, &src
, srcname
, sizeof(srcname
));
1590 inet_ntop(AF_INET6
, &dst
, dstname
, sizeof(dstname
));
1591 zlog_debug("%s received on %s",
1592 lookup_msg(ospf6_message_type_str
, oh
->type
, NULL
),
1593 oi
->interface
->name
);
1594 zlog_debug(" src: %s", srcname
);
1595 zlog_debug(" dst: %s", dstname
);
1598 case OSPF6_MESSAGE_TYPE_HELLO
:
1599 ospf6_hello_print(oh
);
1601 case OSPF6_MESSAGE_TYPE_DBDESC
:
1602 ospf6_dbdesc_print(oh
);
1604 case OSPF6_MESSAGE_TYPE_LSREQ
:
1605 ospf6_lsreq_print(oh
);
1607 case OSPF6_MESSAGE_TYPE_LSUPDATE
:
1608 ospf6_lsupdate_print(oh
);
1610 case OSPF6_MESSAGE_TYPE_LSACK
:
1611 ospf6_lsack_print(oh
);
1619 case OSPF6_MESSAGE_TYPE_HELLO
:
1620 ospf6_hello_recv(&src
, &dst
, oi
, oh
);
1623 case OSPF6_MESSAGE_TYPE_DBDESC
:
1624 ospf6_dbdesc_recv(&src
, &dst
, oi
, oh
);
1627 case OSPF6_MESSAGE_TYPE_LSREQ
:
1628 ospf6_lsreq_recv(&src
, &dst
, oi
, oh
);
1631 case OSPF6_MESSAGE_TYPE_LSUPDATE
:
1632 ospf6_lsupdate_recv(&src
, &dst
, oi
, oh
);
1635 case OSPF6_MESSAGE_TYPE_LSACK
:
1636 ospf6_lsack_recv(&src
, &dst
, oi
, oh
);
1646 static void ospf6_send(struct in6_addr
*src
, struct in6_addr
*dst
,
1647 struct ospf6_interface
*oi
, struct ospf6_header
*oh
)
1650 char srcname
[64], dstname
[64];
1651 struct iovec iovector
[2];
1654 iovector
[0].iov_base
= (caddr_t
)oh
;
1655 iovector
[0].iov_len
= ntohs(oh
->length
);
1656 iovector
[1].iov_base
= NULL
;
1657 iovector
[1].iov_len
= 0;
1659 /* fill OSPF header */
1660 oh
->version
= OSPFV3_VERSION
;
1661 /* message type must be set before */
1662 /* message length must be set before */
1663 oh
->router_id
= oi
->area
->ospf6
->router_id
;
1664 oh
->area_id
= oi
->area
->area_id
;
1665 /* checksum is calculated by kernel */
1666 oh
->instance_id
= oi
->instance_id
;
1670 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, SEND
)) {
1671 inet_ntop(AF_INET6
, dst
, dstname
, sizeof(dstname
));
1673 inet_ntop(AF_INET6
, src
, srcname
, sizeof(srcname
));
1675 memset(srcname
, 0, sizeof(srcname
));
1676 zlog_debug("%s send on %s",
1677 lookup_msg(ospf6_message_type_str
, oh
->type
, NULL
),
1678 oi
->interface
->name
);
1679 zlog_debug(" src: %s", srcname
);
1680 zlog_debug(" dst: %s", dstname
);
1683 case OSPF6_MESSAGE_TYPE_HELLO
:
1684 ospf6_hello_print(oh
);
1686 case OSPF6_MESSAGE_TYPE_DBDESC
:
1687 ospf6_dbdesc_print(oh
);
1689 case OSPF6_MESSAGE_TYPE_LSREQ
:
1690 ospf6_lsreq_print(oh
);
1692 case OSPF6_MESSAGE_TYPE_LSUPDATE
:
1693 ospf6_lsupdate_print(oh
);
1695 case OSPF6_MESSAGE_TYPE_LSACK
:
1696 ospf6_lsack_print(oh
);
1699 zlog_debug("Unknown message");
1706 len
= ospf6_sendmsg(src
, dst
, &oi
->interface
->ifindex
, iovector
);
1707 if (len
!= ntohs(oh
->length
))
1708 flog_err(EC_LIB_DEVELOPMENT
, "Could not send entire message");
1711 static uint32_t ospf6_packet_max(struct ospf6_interface
*oi
)
1713 assert(oi
->ifmtu
> sizeof(struct ip6_hdr
));
1714 return oi
->ifmtu
- (sizeof(struct ip6_hdr
));
1717 int ospf6_hello_send(struct thread
*thread
)
1719 struct ospf6_interface
*oi
;
1720 struct ospf6_header
*oh
;
1721 struct ospf6_hello
*hello
;
1723 struct listnode
*node
, *nnode
;
1724 struct ospf6_neighbor
*on
;
1726 oi
= (struct ospf6_interface
*)THREAD_ARG(thread
);
1727 oi
->thread_send_hello
= (struct thread
*)NULL
;
1729 if (oi
->state
<= OSPF6_INTERFACE_DOWN
) {
1730 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_HELLO
, SEND
))
1731 zlog_debug("Unable to send Hello on down interface %s",
1732 oi
->interface
->name
);
1736 if (iobuflen
== 0) {
1737 zlog_debug("Unable to send Hello on interface %s iobuflen is 0",
1738 oi
->interface
->name
);
1742 /* set next thread */
1743 thread_add_timer(master
, ospf6_hello_send
, oi
, oi
->hello_interval
,
1744 &oi
->thread_send_hello
);
1746 memset(sendbuf
, 0, iobuflen
);
1747 oh
= (struct ospf6_header
*)sendbuf
;
1748 hello
= (struct ospf6_hello
*)((caddr_t
)oh
1749 + sizeof(struct ospf6_header
));
1751 hello
->interface_id
= htonl(oi
->interface
->ifindex
);
1752 hello
->priority
= oi
->priority
;
1753 hello
->options
[0] = oi
->area
->options
[0];
1754 hello
->options
[1] = oi
->area
->options
[1];
1755 hello
->options
[2] = oi
->area
->options
[2];
1756 hello
->hello_interval
= htons(oi
->hello_interval
);
1757 hello
->dead_interval
= htons(oi
->dead_interval
);
1758 hello
->drouter
= oi
->drouter
;
1759 hello
->bdrouter
= oi
->bdrouter
;
1761 p
= (uint8_t *)((caddr_t
)hello
+ sizeof(struct ospf6_hello
));
1763 for (ALL_LIST_ELEMENTS(oi
->neighbor_list
, node
, nnode
, on
)) {
1764 if (on
->state
< OSPF6_NEIGHBOR_INIT
)
1767 if (p
- sendbuf
+ sizeof(uint32_t) > ospf6_packet_max(oi
)) {
1768 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_HELLO
,
1771 "sending Hello message: exceeds I/F MTU");
1775 memcpy(p
, &on
->router_id
, sizeof(uint32_t));
1776 p
+= sizeof(uint32_t);
1779 oh
->type
= OSPF6_MESSAGE_TYPE_HELLO
;
1780 oh
->length
= htons(p
- sendbuf
);
1784 ospf6_send(oi
->linklocal_addr
, &allspfrouters6
, oi
, oh
);
1788 int ospf6_dbdesc_send(struct thread
*thread
)
1790 struct ospf6_neighbor
*on
;
1791 struct ospf6_header
*oh
;
1792 struct ospf6_dbdesc
*dbdesc
;
1794 struct ospf6_lsa
*lsa
;
1795 struct in6_addr
*dst
;
1797 on
= (struct ospf6_neighbor
*)THREAD_ARG(thread
);
1798 on
->thread_send_dbdesc
= (struct thread
*)NULL
;
1800 if (on
->state
< OSPF6_NEIGHBOR_EXSTART
) {
1801 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_DBDESC
, SEND
))
1803 "Quit to send DbDesc to neighbor %s state %s",
1804 on
->name
, ospf6_neighbor_state_str
[on
->state
]);
1808 /* set next thread if master */
1809 if (CHECK_FLAG(on
->dbdesc_bits
, OSPF6_DBDESC_MSBIT
))
1810 thread_add_timer(master
, ospf6_dbdesc_send
, on
,
1811 on
->ospf6_if
->rxmt_interval
,
1812 &on
->thread_send_dbdesc
);
1814 memset(sendbuf
, 0, iobuflen
);
1815 oh
= (struct ospf6_header
*)sendbuf
;
1816 dbdesc
= (struct ospf6_dbdesc
*)((caddr_t
)oh
1817 + sizeof(struct ospf6_header
));
1819 /* if this is initial one, initialize sequence number for DbDesc */
1820 if (CHECK_FLAG(on
->dbdesc_bits
, OSPF6_DBDESC_IBIT
)
1821 && (on
->dbdesc_seqnum
== 0)) {
1822 on
->dbdesc_seqnum
= monotime(NULL
);
1825 dbdesc
->options
[0] = on
->ospf6_if
->area
->options
[0];
1826 dbdesc
->options
[1] = on
->ospf6_if
->area
->options
[1];
1827 dbdesc
->options
[2] = on
->ospf6_if
->area
->options
[2];
1828 dbdesc
->ifmtu
= htons(on
->ospf6_if
->ifmtu
);
1829 dbdesc
->bits
= on
->dbdesc_bits
;
1830 dbdesc
->seqnum
= htonl(on
->dbdesc_seqnum
);
1832 /* if this is not initial one, set LSA headers in dbdesc */
1833 p
= (uint8_t *)((caddr_t
)dbdesc
+ sizeof(struct ospf6_dbdesc
));
1834 if (!CHECK_FLAG(on
->dbdesc_bits
, OSPF6_DBDESC_IBIT
)) {
1835 for (ALL_LSDB(on
->dbdesc_list
, lsa
)) {
1836 ospf6_lsa_age_update_to_send(lsa
,
1837 on
->ospf6_if
->transdelay
);
1840 if (p
- sendbuf
+ sizeof(struct ospf6_lsa_header
)
1841 > ospf6_packet_max(on
->ospf6_if
)) {
1842 ospf6_lsdb_lsa_unlock(lsa
);
1845 memcpy(p
, lsa
->header
, sizeof(struct ospf6_lsa_header
));
1846 p
+= sizeof(struct ospf6_lsa_header
);
1850 oh
->type
= OSPF6_MESSAGE_TYPE_DBDESC
;
1851 oh
->length
= htons(p
- sendbuf
);
1854 if (on
->ospf6_if
->state
== OSPF6_INTERFACE_POINTTOPOINT
)
1855 dst
= &allspfrouters6
;
1857 dst
= &on
->linklocal_addr
;
1859 on
->ospf6_if
->db_desc_out
++;
1861 ospf6_send(on
->ospf6_if
->linklocal_addr
, dst
, on
->ospf6_if
, oh
);
1866 int ospf6_dbdesc_send_newone(struct thread
*thread
)
1868 struct ospf6_neighbor
*on
;
1869 struct ospf6_lsa
*lsa
;
1870 unsigned int size
= 0;
1872 on
= (struct ospf6_neighbor
*)THREAD_ARG(thread
);
1873 ospf6_lsdb_remove_all(on
->dbdesc_list
);
1875 /* move LSAs from summary_list to dbdesc_list (within neighbor
1877 so that ospf6_send_dbdesc () can send those LSAs */
1878 size
= sizeof(struct ospf6_lsa_header
) + sizeof(struct ospf6_dbdesc
);
1879 for (ALL_LSDB(on
->summary_list
, lsa
)) {
1880 if (size
+ sizeof(struct ospf6_lsa_header
)
1881 > ospf6_packet_max(on
->ospf6_if
)) {
1882 ospf6_lsdb_lsa_unlock(lsa
);
1886 ospf6_lsdb_add(ospf6_lsa_copy(lsa
), on
->dbdesc_list
);
1887 ospf6_lsdb_remove(lsa
, on
->summary_list
);
1888 size
+= sizeof(struct ospf6_lsa_header
);
1891 if (on
->summary_list
->count
== 0)
1892 UNSET_FLAG(on
->dbdesc_bits
, OSPF6_DBDESC_MBIT
);
1894 /* If slave, More bit check must be done here */
1895 if (!CHECK_FLAG(on
->dbdesc_bits
, OSPF6_DBDESC_MSBIT
) && /* Slave */
1896 !CHECK_FLAG(on
->dbdesc_last
.bits
, OSPF6_DBDESC_MBIT
)
1897 && !CHECK_FLAG(on
->dbdesc_bits
, OSPF6_DBDESC_MBIT
))
1898 thread_add_event(master
, exchange_done
, on
, 0, NULL
);
1900 thread_execute(master
, ospf6_dbdesc_send
, on
, 0);
1904 int ospf6_lsreq_send(struct thread
*thread
)
1906 struct ospf6_neighbor
*on
;
1907 struct ospf6_header
*oh
;
1908 struct ospf6_lsreq_entry
*e
;
1910 struct ospf6_lsa
*lsa
, *last_req
;
1912 on
= (struct ospf6_neighbor
*)THREAD_ARG(thread
);
1913 on
->thread_send_lsreq
= (struct thread
*)NULL
;
1915 /* LSReq will be sent only in ExStart or Loading */
1916 if (on
->state
!= OSPF6_NEIGHBOR_EXCHANGE
1917 && on
->state
!= OSPF6_NEIGHBOR_LOADING
) {
1918 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_LSREQ
, SEND
))
1919 zlog_debug("Quit to send LSReq to neighbor %s state %s",
1921 ospf6_neighbor_state_str
[on
->state
]);
1925 /* schedule loading_done if request list is empty */
1926 if (on
->request_list
->count
== 0) {
1927 thread_add_event(master
, loading_done
, on
, 0, NULL
);
1931 memset(sendbuf
, 0, iobuflen
);
1932 oh
= (struct ospf6_header
*)sendbuf
;
1935 /* set Request entries in lsreq */
1936 p
= (uint8_t *)((caddr_t
)oh
+ sizeof(struct ospf6_header
));
1937 for (ALL_LSDB(on
->request_list
, lsa
)) {
1939 if (p
- sendbuf
+ sizeof(struct ospf6_lsreq_entry
)
1940 > ospf6_packet_max(on
->ospf6_if
)) {
1941 ospf6_lsdb_lsa_unlock(lsa
);
1945 e
= (struct ospf6_lsreq_entry
*)p
;
1946 e
->type
= lsa
->header
->type
;
1947 e
->id
= lsa
->header
->id
;
1948 e
->adv_router
= lsa
->header
->adv_router
;
1949 p
+= sizeof(struct ospf6_lsreq_entry
);
1953 if (last_req
!= NULL
) {
1954 if (on
->last_ls_req
!= NULL
) {
1955 ospf6_lsa_unlock(on
->last_ls_req
);
1957 ospf6_lsa_lock(last_req
);
1958 on
->last_ls_req
= last_req
;
1961 oh
->type
= OSPF6_MESSAGE_TYPE_LSREQ
;
1962 oh
->length
= htons(p
- sendbuf
);
1964 on
->ospf6_if
->ls_req_out
++;
1966 if (on
->ospf6_if
->state
== OSPF6_INTERFACE_POINTTOPOINT
)
1967 ospf6_send(on
->ospf6_if
->linklocal_addr
, &allspfrouters6
,
1970 ospf6_send(on
->ospf6_if
->linklocal_addr
, &on
->linklocal_addr
,
1973 /* set next thread */
1974 if (on
->request_list
->count
!= 0) {
1975 on
->thread_send_lsreq
= NULL
;
1976 thread_add_timer(master
, ospf6_lsreq_send
, on
,
1977 on
->ospf6_if
->rxmt_interval
,
1978 &on
->thread_send_lsreq
);
1984 static void ospf6_send_lsupdate(struct ospf6_neighbor
*on
,
1985 struct ospf6_interface
*oi
,
1986 struct ospf6_header
*oh
)
1990 on
->ospf6_if
->ls_upd_out
++;
1992 if ((on
->ospf6_if
->state
== OSPF6_INTERFACE_POINTTOPOINT
)
1993 || (on
->ospf6_if
->state
== OSPF6_INTERFACE_DR
)
1994 || (on
->ospf6_if
->state
== OSPF6_INTERFACE_BDR
)) {
1995 ospf6_send(on
->ospf6_if
->linklocal_addr
,
1996 &allspfrouters6
, on
->ospf6_if
, oh
);
1998 ospf6_send(on
->ospf6_if
->linklocal_addr
,
1999 &on
->linklocal_addr
, on
->ospf6_if
, oh
);
2005 if ((oi
->state
== OSPF6_INTERFACE_POINTTOPOINT
)
2006 || (oi
->state
== OSPF6_INTERFACE_DR
)
2007 || (oi
->state
== OSPF6_INTERFACE_BDR
)) {
2008 ospf6_send(oi
->linklocal_addr
, &allspfrouters6
, oi
, oh
);
2010 ospf6_send(oi
->linklocal_addr
, &alldrouters6
, oi
, oh
);
2015 int ospf6_lsupdate_send_neighbor(struct thread
*thread
)
2017 struct ospf6_neighbor
*on
;
2018 struct ospf6_header
*oh
;
2019 struct ospf6_lsupdate
*lsupdate
;
2022 struct ospf6_lsa
*lsa
;
2024 on
= (struct ospf6_neighbor
*)THREAD_ARG(thread
);
2025 on
->thread_send_lsupdate
= (struct thread
*)NULL
;
2027 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_LSUPDATE
, SEND
))
2028 zlog_debug("LSUpdate to neighbor %s", on
->name
);
2030 if (on
->state
< OSPF6_NEIGHBOR_EXCHANGE
) {
2031 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_LSUPDATE
, SEND
))
2032 zlog_debug("Quit to send (neighbor state %s)",
2033 ospf6_neighbor_state_str
[on
->state
]);
2037 memset(sendbuf
, 0, iobuflen
);
2038 oh
= (struct ospf6_header
*)sendbuf
;
2039 lsupdate
= (struct ospf6_lsupdate
*)((caddr_t
)oh
2040 + sizeof(struct ospf6_header
));
2042 p
= (uint8_t *)((caddr_t
)lsupdate
+ sizeof(struct ospf6_lsupdate
));
2045 /* lsupdate_list lists those LSA which doesn't need to be
2046 retransmitted. remove those from the list */
2047 for (ALL_LSDB(on
->lsupdate_list
, lsa
)) {
2049 if ((p
- sendbuf
+ (unsigned int)OSPF6_LSA_SIZE(lsa
->header
))
2050 > ospf6_packet_max(on
->ospf6_if
)) {
2052 oh
->type
= OSPF6_MESSAGE_TYPE_LSUPDATE
;
2053 oh
->length
= htons(p
- sendbuf
);
2054 lsupdate
->lsa_number
= htonl(lsa_cnt
);
2056 ospf6_send_lsupdate(on
, NULL
, oh
);
2058 memset(sendbuf
, 0, iobuflen
);
2059 oh
= (struct ospf6_header
*)sendbuf
;
2060 lsupdate
= (struct ospf6_lsupdate
2065 p
= (uint8_t *)((caddr_t
)lsupdate
2072 ospf6_lsa_age_update_to_send(lsa
, on
->ospf6_if
->transdelay
);
2073 memcpy(p
, lsa
->header
, OSPF6_LSA_SIZE(lsa
->header
));
2074 p
+= OSPF6_LSA_SIZE(lsa
->header
);
2077 assert(lsa
->lock
== 2);
2078 ospf6_lsdb_remove(lsa
, on
->lsupdate_list
);
2082 oh
->type
= OSPF6_MESSAGE_TYPE_LSUPDATE
;
2083 oh
->length
= htons(p
- sendbuf
);
2084 lsupdate
->lsa_number
= htonl(lsa_cnt
);
2085 ospf6_send_lsupdate(on
, NULL
, oh
);
2088 /* The addresses used for retransmissions are different from those sent
2090 first time and so we need to separate them here.
2092 memset(sendbuf
, 0, iobuflen
);
2093 oh
= (struct ospf6_header
*)sendbuf
;
2094 lsupdate
= (struct ospf6_lsupdate
*)((caddr_t
)oh
2095 + sizeof(struct ospf6_header
));
2096 p
= (uint8_t *)((caddr_t
)lsupdate
+ sizeof(struct ospf6_lsupdate
));
2099 for (ALL_LSDB(on
->retrans_list
, lsa
)) {
2101 if ((p
- sendbuf
+ (unsigned int)OSPF6_LSA_SIZE(lsa
->header
))
2102 > ospf6_packet_max(on
->ospf6_if
)) {
2104 oh
->type
= OSPF6_MESSAGE_TYPE_LSUPDATE
;
2105 oh
->length
= htons(p
- sendbuf
);
2106 lsupdate
->lsa_number
= htonl(lsa_cnt
);
2108 if (on
->ospf6_if
->state
2109 == OSPF6_INTERFACE_POINTTOPOINT
) {
2110 ospf6_send(on
->ospf6_if
->linklocal_addr
,
2114 ospf6_send(on
->ospf6_if
->linklocal_addr
,
2115 &on
->linklocal_addr
,
2119 memset(sendbuf
, 0, iobuflen
);
2120 oh
= (struct ospf6_header
*)sendbuf
;
2121 lsupdate
= (struct ospf6_lsupdate
2125 p
= (uint8_t *)((caddr_t
)lsupdate
2132 ospf6_lsa_age_update_to_send(lsa
, on
->ospf6_if
->transdelay
);
2133 memcpy(p
, lsa
->header
, OSPF6_LSA_SIZE(lsa
->header
));
2134 p
+= OSPF6_LSA_SIZE(lsa
->header
);
2139 oh
->type
= OSPF6_MESSAGE_TYPE_LSUPDATE
;
2140 oh
->length
= htons(p
- sendbuf
);
2141 lsupdate
->lsa_number
= htonl(lsa_cnt
);
2143 if (on
->ospf6_if
->state
== OSPF6_INTERFACE_POINTTOPOINT
)
2144 ospf6_send(on
->ospf6_if
->linklocal_addr
,
2145 &allspfrouters6
, on
->ospf6_if
, oh
);
2147 ospf6_send(on
->ospf6_if
->linklocal_addr
,
2148 &on
->linklocal_addr
, on
->ospf6_if
, oh
);
2151 if (on
->lsupdate_list
->count
!= 0) {
2152 on
->thread_send_lsupdate
= NULL
;
2153 thread_add_event(master
, ospf6_lsupdate_send_neighbor
, on
, 0,
2154 &on
->thread_send_lsupdate
);
2155 } else if (on
->retrans_list
->count
!= 0) {
2156 on
->thread_send_lsupdate
= NULL
;
2157 thread_add_timer(master
, ospf6_lsupdate_send_neighbor
, on
,
2158 on
->ospf6_if
->rxmt_interval
,
2159 &on
->thread_send_lsupdate
);
2164 int ospf6_lsupdate_send_neighbor_now(struct ospf6_neighbor
*on
,
2165 struct ospf6_lsa
*lsa
)
2167 struct ospf6_header
*oh
;
2168 struct ospf6_lsupdate
*lsupdate
;
2172 memset(sendbuf
, 0, iobuflen
);
2173 oh
= (struct ospf6_header
*)sendbuf
;
2174 lsupdate
= (struct ospf6_lsupdate
*)((caddr_t
)oh
2175 + sizeof(struct ospf6_header
));
2177 p
= (uint8_t *)((caddr_t
)lsupdate
+ sizeof(struct ospf6_lsupdate
));
2178 ospf6_lsa_age_update_to_send(lsa
, on
->ospf6_if
->transdelay
);
2179 memcpy(p
, lsa
->header
, OSPF6_LSA_SIZE(lsa
->header
));
2180 p
+= OSPF6_LSA_SIZE(lsa
->header
);
2183 oh
->type
= OSPF6_MESSAGE_TYPE_LSUPDATE
;
2184 oh
->length
= htons(p
- sendbuf
);
2185 lsupdate
->lsa_number
= htonl(lsa_cnt
);
2187 if (IS_OSPF6_DEBUG_FLOODING
2188 || IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_LSUPDATE
, SEND
))
2189 zlog_debug("%s: Send lsupdate with lsa %s (age %u)",
2190 __PRETTY_FUNCTION__
, lsa
->name
,
2191 ntohs(lsa
->header
->age
));
2193 ospf6_send_lsupdate(on
, NULL
, oh
);
2198 int ospf6_lsupdate_send_interface(struct thread
*thread
)
2200 struct ospf6_interface
*oi
;
2201 struct ospf6_header
*oh
;
2202 struct ospf6_lsupdate
*lsupdate
;
2205 struct ospf6_lsa
*lsa
;
2207 oi
= (struct ospf6_interface
*)THREAD_ARG(thread
);
2208 oi
->thread_send_lsupdate
= (struct thread
*)NULL
;
2210 if (oi
->state
<= OSPF6_INTERFACE_WAITING
) {
2211 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_LSUPDATE
, SEND
))
2213 "Quit to send LSUpdate to interface %s state %s",
2214 oi
->interface
->name
,
2215 ospf6_interface_state_str
[oi
->state
]);
2219 /* if we have nothing to send, return */
2220 if (oi
->lsupdate_list
->count
== 0)
2223 memset(sendbuf
, 0, iobuflen
);
2224 oh
= (struct ospf6_header
*)sendbuf
;
2225 lsupdate
= (struct ospf6_lsupdate
*)((caddr_t
)oh
2226 + sizeof(struct ospf6_header
));
2228 p
= (uint8_t *)((caddr_t
)lsupdate
+ sizeof(struct ospf6_lsupdate
));
2231 for (ALL_LSDB(oi
->lsupdate_list
, lsa
)) {
2233 if ((p
- sendbuf
+ ((unsigned int)OSPF6_LSA_SIZE(lsa
->header
)))
2234 > ospf6_packet_max(oi
)) {
2236 oh
->type
= OSPF6_MESSAGE_TYPE_LSUPDATE
;
2237 oh
->length
= htons(p
- sendbuf
);
2238 lsupdate
->lsa_number
= htonl(lsa_cnt
);
2240 ospf6_send_lsupdate(NULL
, oi
, oh
);
2241 if (IS_OSPF6_DEBUG_MESSAGE(
2242 OSPF6_MESSAGE_TYPE_LSUPDATE
, SEND
))
2243 zlog_debug("%s: LSUpdate length %d",
2244 __PRETTY_FUNCTION__
,
2247 memset(sendbuf
, 0, iobuflen
);
2248 oh
= (struct ospf6_header
*)sendbuf
;
2249 lsupdate
= (struct ospf6_lsupdate
2254 p
= (uint8_t *)((caddr_t
)lsupdate
2261 ospf6_lsa_age_update_to_send(lsa
, oi
->transdelay
);
2262 memcpy(p
, lsa
->header
, OSPF6_LSA_SIZE(lsa
->header
));
2263 p
+= OSPF6_LSA_SIZE(lsa
->header
);
2266 assert(lsa
->lock
== 2);
2267 ospf6_lsdb_remove(lsa
, oi
->lsupdate_list
);
2271 oh
->type
= OSPF6_MESSAGE_TYPE_LSUPDATE
;
2272 oh
->length
= htons(p
- sendbuf
);
2273 lsupdate
->lsa_number
= htonl(lsa_cnt
);
2275 ospf6_send_lsupdate(NULL
, oi
, oh
);
2278 if (oi
->lsupdate_list
->count
> 0) {
2279 oi
->thread_send_lsupdate
= NULL
;
2280 thread_add_event(master
, ospf6_lsupdate_send_interface
, oi
, 0,
2281 &oi
->thread_send_lsupdate
);
2287 int ospf6_lsack_send_neighbor(struct thread
*thread
)
2289 struct ospf6_neighbor
*on
;
2290 struct ospf6_header
*oh
;
2292 struct ospf6_lsa
*lsa
;
2295 on
= (struct ospf6_neighbor
*)THREAD_ARG(thread
);
2296 on
->thread_send_lsack
= (struct thread
*)NULL
;
2298 if (on
->state
< OSPF6_NEIGHBOR_EXCHANGE
) {
2299 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_LSACK
, SEND
))
2300 zlog_debug("Quit to send LSAck to neighbor %s state %s",
2302 ospf6_neighbor_state_str
[on
->state
]);
2306 /* if we have nothing to send, return */
2307 if (on
->lsack_list
->count
== 0)
2310 memset(sendbuf
, 0, iobuflen
);
2311 oh
= (struct ospf6_header
*)sendbuf
;
2313 p
= (uint8_t *)((caddr_t
)oh
+ sizeof(struct ospf6_header
));
2315 for (ALL_LSDB(on
->lsack_list
, lsa
)) {
2317 if (p
- sendbuf
+ sizeof(struct ospf6_lsa_header
)
2318 > ospf6_packet_max(on
->ospf6_if
)) {
2319 /* if we run out of packet size/space here,
2320 better to try again soon. */
2322 oh
->type
= OSPF6_MESSAGE_TYPE_LSACK
;
2323 oh
->length
= htons(p
- sendbuf
);
2325 on
->ospf6_if
->ls_ack_out
++;
2327 ospf6_send(on
->ospf6_if
->linklocal_addr
,
2328 &on
->linklocal_addr
, on
->ospf6_if
,
2331 memset(sendbuf
, 0, iobuflen
);
2332 oh
= (struct ospf6_header
*)sendbuf
;
2333 p
= (uint8_t *)((caddr_t
)oh
2334 + sizeof(struct ospf6_header
));
2339 ospf6_lsa_age_update_to_send(lsa
, on
->ospf6_if
->transdelay
);
2340 memcpy(p
, lsa
->header
, sizeof(struct ospf6_lsa_header
));
2341 p
+= sizeof(struct ospf6_lsa_header
);
2343 assert(lsa
->lock
== 2);
2344 ospf6_lsdb_remove(lsa
, on
->lsack_list
);
2349 oh
->type
= OSPF6_MESSAGE_TYPE_LSACK
;
2350 oh
->length
= htons(p
- sendbuf
);
2352 on
->ospf6_if
->ls_ack_out
++;
2354 ospf6_send(on
->ospf6_if
->linklocal_addr
, &on
->linklocal_addr
,
2358 if (on
->lsack_list
->count
> 0)
2359 thread_add_event(master
, ospf6_lsack_send_neighbor
, on
, 0,
2360 &on
->thread_send_lsack
);
2365 int ospf6_lsack_send_interface(struct thread
*thread
)
2367 struct ospf6_interface
*oi
;
2368 struct ospf6_header
*oh
;
2370 struct ospf6_lsa
*lsa
;
2373 oi
= (struct ospf6_interface
*)THREAD_ARG(thread
);
2374 oi
->thread_send_lsack
= (struct thread
*)NULL
;
2376 if (oi
->state
<= OSPF6_INTERFACE_WAITING
) {
2377 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_LSACK
, SEND
))
2379 "Quit to send LSAck to interface %s state %s",
2380 oi
->interface
->name
,
2381 ospf6_interface_state_str
[oi
->state
]);
2385 /* if we have nothing to send, return */
2386 if (oi
->lsack_list
->count
== 0)
2389 memset(sendbuf
, 0, iobuflen
);
2390 oh
= (struct ospf6_header
*)sendbuf
;
2392 p
= (uint8_t *)((caddr_t
)oh
+ sizeof(struct ospf6_header
));
2394 for (ALL_LSDB(oi
->lsack_list
, lsa
)) {
2396 if (p
- sendbuf
+ sizeof(struct ospf6_lsa_header
)
2397 > ospf6_packet_max(oi
)) {
2398 /* if we run out of packet size/space here,
2399 better to try again soon. */
2400 THREAD_OFF(oi
->thread_send_lsack
);
2401 thread_add_event(master
, ospf6_lsack_send_interface
, oi
,
2402 0, &oi
->thread_send_lsack
);
2404 ospf6_lsdb_lsa_unlock(lsa
);
2408 ospf6_lsa_age_update_to_send(lsa
, oi
->transdelay
);
2409 memcpy(p
, lsa
->header
, sizeof(struct ospf6_lsa_header
));
2410 p
+= sizeof(struct ospf6_lsa_header
);
2412 assert(lsa
->lock
== 2);
2413 ospf6_lsdb_remove(lsa
, oi
->lsack_list
);
2418 oh
->type
= OSPF6_MESSAGE_TYPE_LSACK
;
2419 oh
->length
= htons(p
- sendbuf
);
2421 if ((oi
->state
== OSPF6_INTERFACE_POINTTOPOINT
)
2422 || (oi
->state
== OSPF6_INTERFACE_DR
)
2423 || (oi
->state
== OSPF6_INTERFACE_BDR
))
2424 ospf6_send(oi
->linklocal_addr
, &allspfrouters6
, oi
, oh
);
2426 ospf6_send(oi
->linklocal_addr
, &alldrouters6
, oi
, oh
);
2429 if (oi
->lsack_list
->count
> 0)
2430 thread_add_event(master
, ospf6_lsack_send_interface
, oi
, 0,
2431 &oi
->thread_send_lsack
);
2438 DEFUN (debug_ospf6_message
,
2439 debug_ospf6_message_cmd
,
2440 "debug ospf6 message <unknown|hello|dbdesc|lsreq|lsupdate|lsack|all> [<send|recv>]",
2443 "Debug OSPFv3 message\n"
2444 "Debug Unknown message\n"
2445 "Debug Hello message\n"
2446 "Debug Database Description message\n"
2447 "Debug Link State Request message\n"
2448 "Debug Link State Update message\n"
2449 "Debug Link State Acknowledgement message\n"
2450 "Debug All message\n"
2451 "Debug only sending message\n"
2452 "Debug only receiving message\n")
2455 int idx_send_recv
= 4;
2456 unsigned char level
= 0;
2461 if (!strncmp(argv
[idx_packet
]->arg
, "u", 1))
2462 type
= OSPF6_MESSAGE_TYPE_UNKNOWN
;
2463 else if (!strncmp(argv
[idx_packet
]->arg
, "h", 1))
2464 type
= OSPF6_MESSAGE_TYPE_HELLO
;
2465 else if (!strncmp(argv
[idx_packet
]->arg
, "d", 1))
2466 type
= OSPF6_MESSAGE_TYPE_DBDESC
;
2467 else if (!strncmp(argv
[idx_packet
]->arg
, "lsr", 3))
2468 type
= OSPF6_MESSAGE_TYPE_LSREQ
;
2469 else if (!strncmp(argv
[idx_packet
]->arg
, "lsu", 3))
2470 type
= OSPF6_MESSAGE_TYPE_LSUPDATE
;
2471 else if (!strncmp(argv
[idx_packet
]->arg
, "lsa", 3))
2472 type
= OSPF6_MESSAGE_TYPE_LSACK
;
2473 else if (!strncmp(argv
[idx_packet
]->arg
, "a", 1))
2474 type
= OSPF6_MESSAGE_TYPE_ALL
;
2477 level
= OSPF6_DEBUG_MESSAGE_SEND
| OSPF6_DEBUG_MESSAGE_RECV
;
2478 else if (!strncmp(argv
[idx_send_recv
]->arg
, "s", 1))
2479 level
= OSPF6_DEBUG_MESSAGE_SEND
;
2480 else if (!strncmp(argv
[idx_send_recv
]->arg
, "r", 1))
2481 level
= OSPF6_DEBUG_MESSAGE_RECV
;
2483 if (type
== OSPF6_MESSAGE_TYPE_ALL
) {
2484 for (i
= 0; i
< 6; i
++)
2485 OSPF6_DEBUG_MESSAGE_ON(i
, level
);
2487 OSPF6_DEBUG_MESSAGE_ON(type
, level
);
2492 DEFUN (no_debug_ospf6_message
,
2493 no_debug_ospf6_message_cmd
,
2494 "no debug ospf6 message <unknown|hello|dbdesc|lsreq|lsupdate|lsack|all> [<send|recv>]",
2498 "Debug OSPFv3 message\n"
2499 "Debug Unknown message\n"
2500 "Debug Hello message\n"
2501 "Debug Database Description message\n"
2502 "Debug Link State Request message\n"
2503 "Debug Link State Update message\n"
2504 "Debug Link State Acknowledgement message\n"
2505 "Debug All message\n"
2506 "Debug only sending message\n"
2507 "Debug only receiving message\n")
2510 int idx_send_recv
= 5;
2511 unsigned char level
= 0;
2516 if (!strncmp(argv
[idx_packet
]->arg
, "u", 1))
2517 type
= OSPF6_MESSAGE_TYPE_UNKNOWN
;
2518 else if (!strncmp(argv
[idx_packet
]->arg
, "h", 1))
2519 type
= OSPF6_MESSAGE_TYPE_HELLO
;
2520 else if (!strncmp(argv
[idx_packet
]->arg
, "d", 1))
2521 type
= OSPF6_MESSAGE_TYPE_DBDESC
;
2522 else if (!strncmp(argv
[idx_packet
]->arg
, "lsr", 3))
2523 type
= OSPF6_MESSAGE_TYPE_LSREQ
;
2524 else if (!strncmp(argv
[idx_packet
]->arg
, "lsu", 3))
2525 type
= OSPF6_MESSAGE_TYPE_LSUPDATE
;
2526 else if (!strncmp(argv
[idx_packet
]->arg
, "lsa", 3))
2527 type
= OSPF6_MESSAGE_TYPE_LSACK
;
2528 else if (!strncmp(argv
[idx_packet
]->arg
, "a", 1))
2529 type
= OSPF6_MESSAGE_TYPE_ALL
;
2532 level
= OSPF6_DEBUG_MESSAGE_SEND
| OSPF6_DEBUG_MESSAGE_RECV
;
2533 else if (!strncmp(argv
[idx_send_recv
]->arg
, "s", 1))
2534 level
= OSPF6_DEBUG_MESSAGE_SEND
;
2535 else if (!strncmp(argv
[idx_send_recv
]->arg
, "r", 1))
2536 level
= OSPF6_DEBUG_MESSAGE_RECV
;
2538 if (type
== OSPF6_MESSAGE_TYPE_ALL
) {
2539 for (i
= 0; i
< 6; i
++)
2540 OSPF6_DEBUG_MESSAGE_OFF(i
, level
);
2542 OSPF6_DEBUG_MESSAGE_OFF(type
, level
);
2548 int config_write_ospf6_debug_message(struct vty
*vty
)
2550 const char *type_str
[] = {"unknown", "hello", "dbdesc",
2551 "lsreq", "lsupdate", "lsack"};
2552 unsigned char s
= 0, r
= 0;
2555 for (i
= 0; i
< 6; i
++) {
2556 if (IS_OSPF6_DEBUG_MESSAGE(i
, SEND
))
2558 if (IS_OSPF6_DEBUG_MESSAGE(i
, RECV
))
2562 if (s
== 0x3f && r
== 0x3f) {
2563 vty_out(vty
, "debug ospf6 message all\n");
2567 if (s
== 0x3f && r
== 0) {
2568 vty_out(vty
, "debug ospf6 message all send\n");
2570 } else if (s
== 0 && r
== 0x3f) {
2571 vty_out(vty
, "debug ospf6 message all recv\n");
2575 /* Unknown message is logged by default */
2576 if (!IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN
, SEND
)
2577 && !IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN
, RECV
))
2578 vty_out(vty
, "no debug ospf6 message unknown\n");
2579 else if (!IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN
, SEND
))
2580 vty_out(vty
, "no debug ospf6 message unknown send\n");
2581 else if (!IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN
, RECV
))
2582 vty_out(vty
, "no debug ospf6 message unknown recv\n");
2584 for (i
= 1; i
< 6; i
++) {
2585 if (IS_OSPF6_DEBUG_MESSAGE(i
, SEND
)
2586 && IS_OSPF6_DEBUG_MESSAGE(i
, RECV
))
2587 vty_out(vty
, "debug ospf6 message %s\n", type_str
[i
]);
2588 else if (IS_OSPF6_DEBUG_MESSAGE(i
, SEND
))
2589 vty_out(vty
, "debug ospf6 message %s send\n",
2591 else if (IS_OSPF6_DEBUG_MESSAGE(i
, RECV
))
2592 vty_out(vty
, "debug ospf6 message %s recv\n",
2599 void install_element_ospf6_debug_message(void)
2601 install_element(ENABLE_NODE
, &debug_ospf6_message_cmd
);
2602 install_element(ENABLE_NODE
, &no_debug_ospf6_message_cmd
);
2603 install_element(CONFIG_NODE
, &debug_ospf6_message_cmd
);
2604 install_element(CONFIG_NODE
, &no_debug_ospf6_message_cmd
);