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
30 #include "ospf6_proto.h"
31 #include "ospf6_lsa.h"
32 #include "ospf6_lsdb.h"
33 #include "ospf6_network.h"
34 #include "ospf6_message.h"
36 #include "ospf6_top.h"
37 #include "ospf6_area.h"
38 #include "ospf6_neighbor.h"
39 #include "ospf6_interface.h"
41 /* for structures and macros ospf6_lsa_examin() needs */
42 #include "ospf6_abr.h"
43 #include "ospf6_asbr.h"
44 #include "ospf6_intra.h"
46 #include "ospf6_flood.h"
49 #include <netinet/ip6.h>
51 unsigned char conf_debug_ospf6_message
[6] = {0x03, 0, 0, 0, 0, 0};
52 static const struct message ospf6_message_type_str
[] = {
53 {OSPF6_MESSAGE_TYPE_HELLO
, "Hello"},
54 {OSPF6_MESSAGE_TYPE_DBDESC
, "DbDesc"},
55 {OSPF6_MESSAGE_TYPE_LSREQ
, "LSReq"},
56 {OSPF6_MESSAGE_TYPE_LSUPDATE
, "LSUpdate"},
57 {OSPF6_MESSAGE_TYPE_LSACK
, "LSAck"},
60 /* Minimum (besides the standard OSPF packet header) lengths for OSPF
61 packets of particular types, offset is the "type" field. */
62 const u_int16_t ospf6_packet_minlen
[OSPF6_MESSAGE_TYPE_ALL
] = {
65 OSPF6_DB_DESC_MIN_SIZE
,
66 OSPF6_LS_REQ_MIN_SIZE
,
67 OSPF6_LS_UPD_MIN_SIZE
,
68 OSPF6_LS_ACK_MIN_SIZE
};
70 /* Minimum (besides the standard LSA header) lengths for LSAs of particular
71 types, offset is the "LSA function code" portion of "LSA type" field. */
72 const u_int16_t ospf6_lsa_minlen
[OSPF6_LSTYPE_SIZE
] = {
74 /* 0x2001 */ OSPF6_ROUTER_LSA_MIN_SIZE
,
75 /* 0x2002 */ OSPF6_NETWORK_LSA_MIN_SIZE
,
76 /* 0x2003 */ OSPF6_INTER_PREFIX_LSA_MIN_SIZE
,
77 /* 0x2004 */ OSPF6_INTER_ROUTER_LSA_FIX_SIZE
,
78 /* 0x4005 */ OSPF6_AS_EXTERNAL_LSA_MIN_SIZE
,
80 /* 0x2007 */ OSPF6_AS_EXTERNAL_LSA_MIN_SIZE
,
81 /* 0x0008 */ OSPF6_LINK_LSA_MIN_SIZE
,
82 /* 0x2009 */ OSPF6_INTRA_PREFIX_LSA_MIN_SIZE
};
86 static void ospf6_header_print(struct ospf6_header
*oh
)
88 char router_id
[16], area_id
[16];
89 inet_ntop(AF_INET
, &oh
->router_id
, router_id
, sizeof(router_id
));
90 inet_ntop(AF_INET
, &oh
->area_id
, area_id
, sizeof(area_id
));
92 zlog_debug(" OSPFv%d Type:%d Len:%hu Router-ID:%s", oh
->version
,
93 oh
->type
, ntohs(oh
->length
), router_id
);
94 zlog_debug(" Area-ID:%s Cksum:%hx Instance-ID:%d", area_id
,
95 ntohs(oh
->checksum
), oh
->instance_id
);
98 void ospf6_hello_print(struct ospf6_header
*oh
)
100 struct ospf6_hello
*hello
;
102 char drouter
[16], bdrouter
[16], neighbor
[16];
105 ospf6_header_print(oh
);
106 assert(oh
->type
== OSPF6_MESSAGE_TYPE_HELLO
);
108 hello
= (struct ospf6_hello
*)((caddr_t
)oh
109 + sizeof(struct ospf6_header
));
111 inet_ntop(AF_INET
, &hello
->drouter
, drouter
, sizeof(drouter
));
112 inet_ntop(AF_INET
, &hello
->bdrouter
, bdrouter
, sizeof(bdrouter
));
113 ospf6_options_printbuf(hello
->options
, options
, sizeof(options
));
115 zlog_debug(" I/F-Id:%ld Priority:%d Option:%s",
116 (u_long
)ntohl(hello
->interface_id
), hello
->priority
,
118 zlog_debug(" HelloInterval:%hu DeadInterval:%hu",
119 ntohs(hello
->hello_interval
), ntohs(hello
->dead_interval
));
120 zlog_debug(" DR:%s BDR:%s", drouter
, bdrouter
);
122 for (p
= (char *)((caddr_t
)hello
+ sizeof(struct ospf6_hello
));
123 p
+ sizeof(u_int32_t
) <= OSPF6_MESSAGE_END(oh
);
124 p
+= sizeof(u_int32_t
)) {
125 inet_ntop(AF_INET
, (void *)p
, neighbor
, sizeof(neighbor
));
126 zlog_debug(" Neighbor: %s", neighbor
);
129 assert(p
== OSPF6_MESSAGE_END(oh
));
132 void ospf6_dbdesc_print(struct ospf6_header
*oh
)
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 (u_long
)ntohl(dbdesc
->seqnum
));
154 for (p
= (char *)((caddr_t
)dbdesc
+ sizeof(struct ospf6_dbdesc
));
155 p
+ sizeof(struct ospf6_lsa_header
) <= OSPF6_MESSAGE_END(oh
);
156 p
+= sizeof(struct ospf6_lsa_header
))
157 ospf6_lsa_header_print_raw((struct ospf6_lsa_header
*)p
);
159 assert(p
== OSPF6_MESSAGE_END(oh
));
162 void ospf6_lsreq_print(struct ospf6_header
*oh
)
164 char id
[16], adv_router
[16];
167 ospf6_header_print(oh
);
168 assert(oh
->type
== OSPF6_MESSAGE_TYPE_LSREQ
);
170 for (p
= (char *)((caddr_t
)oh
+ sizeof(struct ospf6_header
));
171 p
+ sizeof(struct ospf6_lsreq_entry
) <= OSPF6_MESSAGE_END(oh
);
172 p
+= sizeof(struct ospf6_lsreq_entry
)) {
173 struct ospf6_lsreq_entry
*e
= (struct ospf6_lsreq_entry
*)p
;
174 inet_ntop(AF_INET
, &e
->adv_router
, adv_router
,
176 inet_ntop(AF_INET
, &e
->id
, id
, sizeof(id
));
177 zlog_debug(" [%s Id:%s Adv:%s]", ospf6_lstype_name(e
->type
),
181 assert(p
== OSPF6_MESSAGE_END(oh
));
184 void ospf6_lsupdate_print(struct ospf6_header
*oh
)
186 struct ospf6_lsupdate
*lsupdate
;
190 ospf6_header_print(oh
);
191 assert(oh
->type
== OSPF6_MESSAGE_TYPE_LSUPDATE
);
193 lsupdate
= (struct ospf6_lsupdate
*)((caddr_t
)oh
194 + sizeof(struct ospf6_header
));
196 num
= ntohl(lsupdate
->lsa_number
);
197 zlog_debug(" Number of LSA: %ld", num
);
199 for (p
= (char *)((caddr_t
)lsupdate
+ sizeof(struct ospf6_lsupdate
));
200 p
< OSPF6_MESSAGE_END(oh
)
201 && p
+ OSPF6_LSA_SIZE(p
) <= OSPF6_MESSAGE_END(oh
);
202 p
+= OSPF6_LSA_SIZE(p
)) {
203 ospf6_lsa_header_print_raw((struct ospf6_lsa_header
*)p
);
206 assert(p
== OSPF6_MESSAGE_END(oh
));
209 void ospf6_lsack_print(struct ospf6_header
*oh
)
213 ospf6_header_print(oh
);
214 assert(oh
->type
== OSPF6_MESSAGE_TYPE_LSACK
);
216 for (p
= (char *)((caddr_t
)oh
+ sizeof(struct ospf6_header
));
217 p
+ sizeof(struct ospf6_lsa_header
) <= OSPF6_MESSAGE_END(oh
);
218 p
+= sizeof(struct ospf6_lsa_header
))
219 ospf6_lsa_header_print_raw((struct ospf6_lsa_header
*)p
);
221 assert(p
== OSPF6_MESSAGE_END(oh
));
224 static void ospf6_hello_recv(struct in6_addr
*src
, struct in6_addr
*dst
,
225 struct ospf6_interface
*oi
,
226 struct ospf6_header
*oh
)
228 struct ospf6_hello
*hello
;
229 struct ospf6_neighbor
*on
;
232 int neighborchange
= 0;
233 int neighbor_ifindex_change
= 0;
236 hello
= (struct ospf6_hello
*)((caddr_t
)oh
237 + sizeof(struct ospf6_header
));
239 /* HelloInterval check */
240 if (ntohs(hello
->hello_interval
) != oi
->hello_interval
) {
241 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
242 zlog_debug("HelloInterval mismatch");
246 /* RouterDeadInterval check */
247 if (ntohs(hello
->dead_interval
) != oi
->dead_interval
) {
248 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
249 zlog_debug("RouterDeadInterval mismatch");
254 if (OSPF6_OPT_ISSET(hello
->options
, OSPF6_OPT_E
)
255 != OSPF6_OPT_ISSET(oi
->area
->options
, OSPF6_OPT_E
)) {
256 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
257 zlog_debug("E-bit mismatch");
261 /* Find neighbor, create if not exist */
262 on
= ospf6_neighbor_lookup(oh
->router_id
, oi
);
264 on
= ospf6_neighbor_create(oh
->router_id
, oi
);
265 on
->prev_drouter
= on
->drouter
= hello
->drouter
;
266 on
->prev_bdrouter
= on
->bdrouter
= hello
->bdrouter
;
267 on
->priority
= hello
->priority
;
270 /* Always override neighbor's source address */
271 memcpy(&on
->linklocal_addr
, src
, sizeof(struct in6_addr
));
273 /* Neighbor ifindex check */
274 if (on
->ifindex
!= (ifindex_t
)ntohl(hello
->interface_id
)) {
275 on
->ifindex
= ntohl(hello
->interface_id
);
276 neighbor_ifindex_change
++;
280 for (p
= (char *)((caddr_t
)hello
+ sizeof(struct ospf6_hello
));
281 p
+ sizeof(u_int32_t
) <= OSPF6_MESSAGE_END(oh
);
282 p
+= sizeof(u_int32_t
)) {
283 u_int32_t
*router_id
= (u_int32_t
*)p
;
285 if (*router_id
== oi
->area
->ospf6
->router_id
)
289 assert(p
== OSPF6_MESSAGE_END(oh
));
291 /* RouterPriority check */
292 if (on
->priority
!= hello
->priority
) {
293 on
->priority
= hello
->priority
;
298 if (on
->drouter
!= hello
->drouter
) {
299 on
->prev_drouter
= on
->drouter
;
300 on
->drouter
= hello
->drouter
;
301 if (on
->prev_drouter
== on
->router_id
302 || on
->drouter
== on
->router_id
)
307 if (on
->bdrouter
!= hello
->bdrouter
) {
308 on
->prev_bdrouter
= on
->bdrouter
;
309 on
->bdrouter
= hello
->bdrouter
;
310 if (on
->prev_bdrouter
== on
->router_id
311 || on
->bdrouter
== on
->router_id
)
315 /* BackupSeen check */
316 if (oi
->state
== OSPF6_INTERFACE_WAITING
) {
317 if (hello
->bdrouter
== on
->router_id
)
319 else if (hello
->drouter
== on
->router_id
320 && hello
->bdrouter
== htonl(0))
324 /* Execute neighbor events */
325 thread_execute(master
, hello_received
, on
, 0);
327 thread_execute(master
, twoway_received
, on
, 0);
329 thread_execute(master
, oneway_received
, on
, 0);
331 /* Schedule interface events */
333 thread_add_event(master
, backup_seen
, oi
, 0, NULL
);
335 thread_add_event(master
, neighbor_change
, oi
, 0, NULL
);
337 if (neighbor_ifindex_change
&& on
->state
== OSPF6_NEIGHBOR_FULL
)
338 OSPF6_ROUTER_LSA_SCHEDULE(oi
->area
);
341 static void ospf6_dbdesc_recv_master(struct ospf6_header
*oh
,
342 struct ospf6_neighbor
*on
)
344 struct ospf6_dbdesc
*dbdesc
;
347 dbdesc
= (struct ospf6_dbdesc
*)((caddr_t
)oh
348 + sizeof(struct ospf6_header
));
350 if (on
->state
< OSPF6_NEIGHBOR_INIT
) {
351 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
352 zlog_debug("Neighbor state less than Init, ignore");
357 case OSPF6_NEIGHBOR_TWOWAY
:
358 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
359 zlog_debug("Neighbor state is 2-Way, ignore");
362 case OSPF6_NEIGHBOR_INIT
:
363 thread_execute(master
, twoway_received
, on
, 0);
364 if (on
->state
!= OSPF6_NEIGHBOR_EXSTART
) {
365 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
367 "Neighbor state is not ExStart, ignore");
370 /* else fall through to ExStart */
372 case OSPF6_NEIGHBOR_EXSTART
:
373 /* if neighbor obeys us as our slave, schedule negotiation_done
374 and process LSA Headers. Otherwise, ignore this message */
375 if (!CHECK_FLAG(dbdesc
->bits
, OSPF6_DBDESC_MSBIT
)
376 && !CHECK_FLAG(dbdesc
->bits
, OSPF6_DBDESC_IBIT
)
377 && ntohl(dbdesc
->seqnum
) == on
->dbdesc_seqnum
) {
378 /* execute NegotiationDone */
379 thread_execute(master
, negotiation_done
, on
, 0);
381 /* Record neighbor options */
382 memcpy(on
->options
, dbdesc
->options
,
383 sizeof(on
->options
));
385 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
386 zlog_debug("Negotiation failed");
389 /* fall through to exchange */
391 case OSPF6_NEIGHBOR_EXCHANGE
:
392 if (!memcmp(dbdesc
, &on
->dbdesc_last
,
393 sizeof(struct ospf6_dbdesc
))) {
394 /* Duplicated DatabaseDescription is dropped by master
396 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
398 "Duplicated dbdesc discarded by Master, ignore");
402 if (CHECK_FLAG(dbdesc
->bits
, OSPF6_DBDESC_MSBIT
)) {
403 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
404 zlog_debug("Master/Slave bit mismatch");
405 thread_add_event(master
, seqnumber_mismatch
, on
, 0,
410 if (CHECK_FLAG(dbdesc
->bits
, OSPF6_DBDESC_IBIT
)) {
411 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
412 zlog_debug("Initialize bit mismatch");
413 thread_add_event(master
, seqnumber_mismatch
, on
, 0,
418 if (memcmp(on
->options
, dbdesc
->options
, sizeof(on
->options
))) {
419 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
420 zlog_debug("Option field mismatch");
421 thread_add_event(master
, seqnumber_mismatch
, on
, 0,
426 if (ntohl(dbdesc
->seqnum
) != on
->dbdesc_seqnum
) {
427 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
429 "Sequence number mismatch (%#lx expected)",
430 (u_long
)on
->dbdesc_seqnum
);
431 thread_add_event(master
, seqnumber_mismatch
, on
, 0,
437 case OSPF6_NEIGHBOR_LOADING
:
438 case OSPF6_NEIGHBOR_FULL
:
439 if (!memcmp(dbdesc
, &on
->dbdesc_last
,
440 sizeof(struct ospf6_dbdesc
))) {
441 /* Duplicated DatabaseDescription is dropped by master
443 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
445 "Duplicated dbdesc discarded by Master, ignore");
449 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
450 zlog_debug("Not duplicate dbdesc in state %s",
451 ospf6_neighbor_state_str
[on
->state
]);
452 thread_add_event(master
, seqnumber_mismatch
, on
, 0, NULL
);
460 /* Process LSA headers */
461 for (p
= (char *)((caddr_t
)dbdesc
+ sizeof(struct ospf6_dbdesc
));
462 p
+ sizeof(struct ospf6_lsa_header
) <= OSPF6_MESSAGE_END(oh
);
463 p
+= sizeof(struct ospf6_lsa_header
)) {
464 struct ospf6_lsa
*his
, *mine
;
465 struct ospf6_lsdb
*lsdb
= NULL
;
467 his
= ospf6_lsa_create_headeronly((struct ospf6_lsa_header
*)p
);
469 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
470 zlog_debug("%s", his
->name
);
472 switch (OSPF6_LSA_SCOPE(his
->header
->type
)) {
473 case OSPF6_SCOPE_LINKLOCAL
:
474 lsdb
= on
->ospf6_if
->lsdb
;
476 case OSPF6_SCOPE_AREA
:
477 lsdb
= on
->ospf6_if
->area
->lsdb
;
480 lsdb
= on
->ospf6_if
->area
->ospf6
->lsdb
;
482 case OSPF6_SCOPE_RESERVED
:
483 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
484 zlog_debug("Ignoring LSA of reserved scope");
485 ospf6_lsa_delete(his
);
490 if (ntohs(his
->header
->type
) == OSPF6_LSTYPE_AS_EXTERNAL
491 && IS_AREA_STUB(on
->ospf6_if
->area
)) {
492 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
494 "SeqNumMismatch (E-bit mismatch), discard");
495 ospf6_lsa_delete(his
);
496 thread_add_event(master
, seqnumber_mismatch
, on
, 0,
501 mine
= ospf6_lsdb_lookup(his
->header
->type
, his
->header
->id
,
502 his
->header
->adv_router
, lsdb
);
504 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
505 zlog_debug("Add request (No database copy)");
506 ospf6_lsdb_add(ospf6_lsa_copy(his
), on
->request_list
);
507 } else if (ospf6_lsa_compare(his
, mine
) < 0) {
508 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
509 zlog_debug("Add request (Received MoreRecent)");
510 ospf6_lsdb_add(ospf6_lsa_copy(his
), on
->request_list
);
512 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
513 zlog_debug("Discard (Existing MoreRecent)");
515 ospf6_lsa_delete(his
);
518 assert(p
== OSPF6_MESSAGE_END(oh
));
520 /* Increment sequence number */
523 /* schedule send lsreq */
524 if (on
->request_list
->count
)
525 thread_add_event(master
, ospf6_lsreq_send
, on
, 0,
526 &on
->thread_send_lsreq
);
528 THREAD_OFF(on
->thread_send_dbdesc
);
531 if (!CHECK_FLAG(dbdesc
->bits
, OSPF6_DBDESC_MBIT
)
532 && !CHECK_FLAG(on
->dbdesc_bits
, OSPF6_DBDESC_MBIT
))
533 thread_add_event(master
, exchange_done
, on
, 0, NULL
);
535 on
->thread_send_dbdesc
= NULL
;
536 thread_add_event(master
, ospf6_dbdesc_send_newone
, on
, 0,
537 &on
->thread_send_dbdesc
);
540 /* save last received dbdesc */
541 memcpy(&on
->dbdesc_last
, dbdesc
, sizeof(struct ospf6_dbdesc
));
544 static void ospf6_dbdesc_recv_slave(struct ospf6_header
*oh
,
545 struct ospf6_neighbor
*on
)
547 struct ospf6_dbdesc
*dbdesc
;
550 dbdesc
= (struct ospf6_dbdesc
*)((caddr_t
)oh
551 + sizeof(struct ospf6_header
));
553 if (on
->state
< OSPF6_NEIGHBOR_INIT
) {
554 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
555 zlog_debug("Neighbor state less than Init, ignore");
560 case OSPF6_NEIGHBOR_TWOWAY
:
561 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
562 zlog_debug("Neighbor state is 2-Way, ignore");
565 case OSPF6_NEIGHBOR_INIT
:
566 thread_execute(master
, twoway_received
, on
, 0);
567 if (on
->state
!= OSPF6_NEIGHBOR_EXSTART
) {
568 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
570 "Neighbor state is not ExStart, ignore");
573 /* else fall through to ExStart */
575 case OSPF6_NEIGHBOR_EXSTART
:
576 /* If the neighbor is Master, act as Slave. Schedule
578 and process LSA Headers. Otherwise, ignore this message */
579 if (CHECK_FLAG(dbdesc
->bits
, OSPF6_DBDESC_IBIT
)
580 && CHECK_FLAG(dbdesc
->bits
, OSPF6_DBDESC_MBIT
)
581 && CHECK_FLAG(dbdesc
->bits
, OSPF6_DBDESC_MSBIT
)
583 == sizeof(struct ospf6_header
)
584 + sizeof(struct ospf6_dbdesc
)) {
585 /* set the master/slave bit to slave */
586 UNSET_FLAG(on
->dbdesc_bits
, OSPF6_DBDESC_MSBIT
);
588 /* set the DD sequence number to one specified by master
590 on
->dbdesc_seqnum
= ntohl(dbdesc
->seqnum
);
592 /* schedule NegotiationDone */
593 thread_execute(master
, negotiation_done
, on
, 0);
595 /* Record neighbor options */
596 memcpy(on
->options
, dbdesc
->options
,
597 sizeof(on
->options
));
599 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
600 zlog_debug("Negotiation failed");
605 case OSPF6_NEIGHBOR_EXCHANGE
:
606 if (!memcmp(dbdesc
, &on
->dbdesc_last
,
607 sizeof(struct ospf6_dbdesc
))) {
608 /* Duplicated DatabaseDescription causes slave to
610 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
612 "Duplicated dbdesc causes retransmit");
613 THREAD_OFF(on
->thread_send_dbdesc
);
614 on
->thread_send_dbdesc
= NULL
;
615 thread_add_event(master
, ospf6_dbdesc_send
, on
, 0,
616 &on
->thread_send_dbdesc
);
620 if (!CHECK_FLAG(dbdesc
->bits
, OSPF6_DBDESC_MSBIT
)) {
621 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
622 zlog_debug("Master/Slave bit mismatch");
623 thread_add_event(master
, seqnumber_mismatch
, on
, 0,
628 if (CHECK_FLAG(dbdesc
->bits
, OSPF6_DBDESC_IBIT
)) {
629 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
630 zlog_debug("Initialize bit mismatch");
631 thread_add_event(master
, seqnumber_mismatch
, on
, 0,
636 if (memcmp(on
->options
, dbdesc
->options
, sizeof(on
->options
))) {
637 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
638 zlog_debug("Option field mismatch");
639 thread_add_event(master
, seqnumber_mismatch
, on
, 0,
644 if (ntohl(dbdesc
->seqnum
) != on
->dbdesc_seqnum
+ 1) {
645 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
647 "Sequence number mismatch (%#lx expected)",
648 (u_long
)on
->dbdesc_seqnum
+ 1);
649 thread_add_event(master
, seqnumber_mismatch
, on
, 0,
655 case OSPF6_NEIGHBOR_LOADING
:
656 case OSPF6_NEIGHBOR_FULL
:
657 if (!memcmp(dbdesc
, &on
->dbdesc_last
,
658 sizeof(struct ospf6_dbdesc
))) {
659 /* Duplicated DatabaseDescription causes slave to
661 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
663 "Duplicated dbdesc causes retransmit");
664 THREAD_OFF(on
->thread_send_dbdesc
);
665 thread_add_event(master
, ospf6_dbdesc_send
, on
, 0,
666 &on
->thread_send_dbdesc
);
670 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
671 zlog_debug("Not duplicate dbdesc in state %s",
672 ospf6_neighbor_state_str
[on
->state
]);
673 thread_add_event(master
, seqnumber_mismatch
, on
, 0, NULL
);
681 /* Process LSA headers */
682 for (p
= (char *)((caddr_t
)dbdesc
+ sizeof(struct ospf6_dbdesc
));
683 p
+ sizeof(struct ospf6_lsa_header
) <= OSPF6_MESSAGE_END(oh
);
684 p
+= sizeof(struct ospf6_lsa_header
)) {
685 struct ospf6_lsa
*his
, *mine
;
686 struct ospf6_lsdb
*lsdb
= NULL
;
688 his
= ospf6_lsa_create_headeronly((struct ospf6_lsa_header
*)p
);
690 switch (OSPF6_LSA_SCOPE(his
->header
->type
)) {
691 case OSPF6_SCOPE_LINKLOCAL
:
692 lsdb
= on
->ospf6_if
->lsdb
;
694 case OSPF6_SCOPE_AREA
:
695 lsdb
= on
->ospf6_if
->area
->lsdb
;
698 lsdb
= on
->ospf6_if
->area
->ospf6
->lsdb
;
700 case OSPF6_SCOPE_RESERVED
:
701 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
702 zlog_debug("Ignoring LSA of reserved scope");
703 ospf6_lsa_delete(his
);
708 if (OSPF6_LSA_SCOPE(his
->header
->type
) == OSPF6_SCOPE_AS
709 && IS_AREA_STUB(on
->ospf6_if
->area
)) {
710 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
711 zlog_debug("E-bit mismatch with LSA Headers");
712 ospf6_lsa_delete(his
);
713 thread_add_event(master
, seqnumber_mismatch
, on
, 0,
718 mine
= ospf6_lsdb_lookup(his
->header
->type
, his
->header
->id
,
719 his
->header
->adv_router
, lsdb
);
720 if (mine
== NULL
|| ospf6_lsa_compare(his
, mine
) < 0) {
721 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
722 zlog_debug("Add request-list: %s", his
->name
);
723 ospf6_lsdb_add(ospf6_lsa_copy(his
), on
->request_list
);
725 ospf6_lsa_delete(his
);
728 assert(p
== OSPF6_MESSAGE_END(oh
));
730 /* Set sequence number to Master's */
731 on
->dbdesc_seqnum
= ntohl(dbdesc
->seqnum
);
733 /* schedule send lsreq */
734 if (on
->request_list
->count
)
735 thread_add_event(master
, ospf6_lsreq_send
, on
, 0,
736 &on
->thread_send_lsreq
);
738 THREAD_OFF(on
->thread_send_dbdesc
);
739 thread_add_event(master
, ospf6_dbdesc_send_newone
, on
, 0,
740 &on
->thread_send_dbdesc
);
742 /* save last received dbdesc */
743 memcpy(&on
->dbdesc_last
, dbdesc
, sizeof(struct ospf6_dbdesc
));
746 static void ospf6_dbdesc_recv(struct in6_addr
*src
, struct in6_addr
*dst
,
747 struct ospf6_interface
*oi
,
748 struct ospf6_header
*oh
)
750 struct ospf6_neighbor
*on
;
751 struct ospf6_dbdesc
*dbdesc
;
753 on
= ospf6_neighbor_lookup(oh
->router_id
, oi
);
755 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
756 zlog_debug("Neighbor not found, ignore");
760 dbdesc
= (struct ospf6_dbdesc
*)((caddr_t
)oh
761 + sizeof(struct ospf6_header
));
763 /* Interface MTU check */
764 if (!oi
->mtu_ignore
&& ntohs(dbdesc
->ifmtu
) != oi
->ifmtu
) {
765 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
766 zlog_debug("I/F MTU mismatch");
770 if (dbdesc
->reserved1
|| dbdesc
->reserved2
) {
771 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
773 "Non-0 reserved field in %s's DbDesc, correct",
775 dbdesc
->reserved1
= 0;
776 dbdesc
->reserved2
= 0;
779 if (ntohl(oh
->router_id
) < ntohl(ospf6
->router_id
))
780 ospf6_dbdesc_recv_master(oh
, on
);
781 else if (ntohl(ospf6
->router_id
) < ntohl(oh
->router_id
))
782 ospf6_dbdesc_recv_slave(oh
, on
);
784 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
785 zlog_debug("Can't decide which is master, ignore");
789 static void ospf6_lsreq_recv(struct in6_addr
*src
, struct in6_addr
*dst
,
790 struct ospf6_interface
*oi
,
791 struct ospf6_header
*oh
)
793 struct ospf6_neighbor
*on
;
795 struct ospf6_lsreq_entry
*e
;
796 struct ospf6_lsdb
*lsdb
= NULL
;
797 struct ospf6_lsa
*lsa
;
799 on
= ospf6_neighbor_lookup(oh
->router_id
, oi
);
801 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
802 zlog_debug("Neighbor not found, ignore");
806 if (on
->state
!= OSPF6_NEIGHBOR_EXCHANGE
807 && on
->state
!= OSPF6_NEIGHBOR_LOADING
808 && on
->state
!= OSPF6_NEIGHBOR_FULL
) {
809 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
810 zlog_debug("Neighbor state less than Exchange, ignore");
814 /* Process each request */
815 for (p
= (char *)((caddr_t
)oh
+ sizeof(struct ospf6_header
));
816 p
+ sizeof(struct ospf6_lsreq_entry
) <= OSPF6_MESSAGE_END(oh
);
817 p
+= sizeof(struct ospf6_lsreq_entry
)) {
818 e
= (struct ospf6_lsreq_entry
*)p
;
820 switch (OSPF6_LSA_SCOPE(e
->type
)) {
821 case OSPF6_SCOPE_LINKLOCAL
:
822 lsdb
= on
->ospf6_if
->lsdb
;
824 case OSPF6_SCOPE_AREA
:
825 lsdb
= on
->ospf6_if
->area
->lsdb
;
828 lsdb
= on
->ospf6_if
->area
->ospf6
->lsdb
;
831 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
832 zlog_debug("Ignoring LSA of reserved scope");
837 /* Find database copy */
838 lsa
= ospf6_lsdb_lookup(e
->type
, e
->id
, e
->adv_router
, lsdb
);
840 char id
[16], adv_router
[16];
841 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
)) {
842 inet_ntop(AF_INET
, &e
->id
, id
, sizeof(id
));
843 inet_ntop(AF_INET
, &e
->adv_router
, adv_router
,
846 "Can't find requested [%s Id:%s Adv:%s]",
847 ospf6_lstype_name(e
->type
), id
,
850 thread_add_event(master
, bad_lsreq
, on
, 0, NULL
);
854 ospf6_lsdb_add(ospf6_lsa_copy(lsa
), on
->lsupdate_list
);
857 assert(p
== OSPF6_MESSAGE_END(oh
));
859 /* schedule send lsupdate */
860 THREAD_OFF(on
->thread_send_lsupdate
);
861 thread_add_event(master
, ospf6_lsupdate_send_neighbor
, on
, 0,
862 &on
->thread_send_lsupdate
);
865 /* Verify, that the specified memory area contains exactly N valid IPv6
866 prefixes as specified by RFC5340, A.4.1. */
867 static unsigned ospf6_prefixes_examin(
868 struct ospf6_prefix
*current
, /* start of buffer */
870 const u_int32_t req_num_pfxs
/* always compared with the actual number
874 u_char requested_pfx_bytes
;
875 u_int32_t real_num_pfxs
= 0;
878 if (length
< OSPF6_PREFIX_MIN_SIZE
) {
879 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN
,
881 zlog_debug("%s: undersized IPv6 prefix header",
885 /* safe to look deeper */
886 if (current
->prefix_length
> IPV6_MAX_BITLEN
) {
887 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN
,
889 zlog_debug("%s: invalid PrefixLength (%u bits)",
890 __func__
, current
->prefix_length
);
893 /* covers both fixed- and variable-sized fields */
894 requested_pfx_bytes
=
895 OSPF6_PREFIX_MIN_SIZE
896 + OSPF6_PREFIX_SPACE(current
->prefix_length
);
897 if (requested_pfx_bytes
> length
) {
898 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN
,
900 zlog_debug("%s: undersized IPv6 prefix",
905 length
-= requested_pfx_bytes
;
906 current
= (struct ospf6_prefix
*)((caddr_t
)current
907 + requested_pfx_bytes
);
910 if (real_num_pfxs
!= req_num_pfxs
) {
911 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN
, RECV
))
913 "%s: IPv6 prefix number mismatch (%u required, %u real)",
914 __func__
, req_num_pfxs
, real_num_pfxs
);
920 /* Verify an LSA to have a valid length and dispatch further (where
921 appropriate) to check if the contents, including nested IPv6 prefixes,
922 is properly sized/aligned within the LSA. Note that this function gets
923 LSA type in network byte order, uses in host byte order and passes to
924 ospf6_lstype_name() in network byte order again. */
925 static unsigned ospf6_lsa_examin(struct ospf6_lsa_header
*lsah
,
926 const u_int16_t lsalen
,
927 const u_char headeronly
)
929 struct ospf6_intra_prefix_lsa
*intra_prefix_lsa
;
930 struct ospf6_as_external_lsa
*as_external_lsa
;
931 struct ospf6_link_lsa
*link_lsa
;
936 /* In case an additional minimum length constraint is defined for
938 LSA type, make sure that this constraint is met. */
939 lsatype
= ntohs(lsah
->type
);
940 ltindex
= lsatype
& OSPF6_LSTYPE_FCODE_MASK
;
941 if (ltindex
< OSPF6_LSTYPE_SIZE
&& ospf6_lsa_minlen
[ltindex
]
942 && lsalen
< ospf6_lsa_minlen
[ltindex
] + OSPF6_LSA_HEADER_SIZE
) {
943 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN
, RECV
))
944 zlog_debug("%s: undersized (%u B) LSA", __func__
,
949 case OSPF6_LSTYPE_ROUTER
:
950 /* RFC5340 A.4.3, LSA header + OSPF6_ROUTER_LSA_MIN_SIZE bytes
952 by N>=0 interface descriptions. */
953 if ((lsalen
- OSPF6_LSA_HEADER_SIZE
- OSPF6_ROUTER_LSA_MIN_SIZE
)
954 % OSPF6_ROUTER_LSDESC_FIX_SIZE
) {
955 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN
,
958 "%s: interface description alignment error",
963 case OSPF6_LSTYPE_NETWORK
:
964 /* RFC5340 A.4.4, LSA header + OSPF6_NETWORK_LSA_MIN_SIZE bytes
965 followed by N>=0 attached router descriptions. */
966 if ((lsalen
- OSPF6_LSA_HEADER_SIZE
967 - OSPF6_NETWORK_LSA_MIN_SIZE
)
968 % OSPF6_NETWORK_LSDESC_FIX_SIZE
) {
969 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN
,
972 "%s: router description alignment error",
977 case OSPF6_LSTYPE_INTER_PREFIX
:
978 /* RFC5340 A.4.5, LSA header + OSPF6_INTER_PREFIX_LSA_MIN_SIZE
980 followed by 3-4 fields of a single IPv6 prefix. */
983 return ospf6_prefixes_examin(
985 *)((caddr_t
)lsah
+ OSPF6_LSA_HEADER_SIZE
986 + OSPF6_INTER_PREFIX_LSA_MIN_SIZE
),
987 lsalen
- OSPF6_LSA_HEADER_SIZE
988 - OSPF6_INTER_PREFIX_LSA_MIN_SIZE
,
990 case OSPF6_LSTYPE_INTER_ROUTER
:
991 /* RFC5340 A.4.6, fixed-size LSA. */
993 > OSPF6_LSA_HEADER_SIZE
+ OSPF6_INTER_ROUTER_LSA_FIX_SIZE
) {
994 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN
,
996 zlog_debug("%s: oversized (%u B) LSA", __func__
,
1001 case OSPF6_LSTYPE_AS_EXTERNAL
: /* RFC5340 A.4.7, same as A.4.8. */
1002 case OSPF6_LSTYPE_TYPE_7
:
1003 /* RFC5340 A.4.8, LSA header + OSPF6_AS_EXTERNAL_LSA_MIN_SIZE
1005 followed by 3-4 fields of IPv6 prefix and 3 conditional LSA
1007 16 bytes of forwarding address, 4 bytes of external route
1009 4 bytes of referenced link state ID. */
1013 (struct ospf6_as_external_lsa
1014 *)((caddr_t
)lsah
+ OSPF6_LSA_HEADER_SIZE
);
1016 OSPF6_LSA_HEADER_SIZE
+ OSPF6_AS_EXTERNAL_LSA_MIN_SIZE
;
1017 /* To find out if the last optional field (Referenced Link State
1019 assumed in this LSA, we need to access fixed fields of the
1021 prefix before ospf6_prefix_examin() confirms its sizing. */
1022 if (exp_length
+ OSPF6_PREFIX_MIN_SIZE
> lsalen
) {
1023 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN
,
1025 zlog_debug("%s: undersized (%u B) LSA header",
1029 /* forwarding address */
1030 if (CHECK_FLAG(as_external_lsa
->bits_metric
, OSPF6_ASBR_BIT_F
))
1032 /* external route tag */
1033 if (CHECK_FLAG(as_external_lsa
->bits_metric
, OSPF6_ASBR_BIT_T
))
1035 /* referenced link state ID */
1036 if (as_external_lsa
->prefix
.u
._prefix_referenced_lstype
)
1038 /* All the fixed-size fields (mandatory and optional) must fit.
1040 this check does not include any IPv6 prefix fields. */
1041 if (exp_length
> lsalen
) {
1042 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN
,
1044 zlog_debug("%s: undersized (%u B) LSA header",
1048 /* The last call completely covers the remainder (IPv6 prefix).
1050 return ospf6_prefixes_examin(
1051 (struct ospf6_prefix
1052 *)((caddr_t
)as_external_lsa
1053 + OSPF6_AS_EXTERNAL_LSA_MIN_SIZE
),
1054 lsalen
- exp_length
, 1);
1055 case OSPF6_LSTYPE_LINK
:
1056 /* RFC5340 A.4.9, LSA header + OSPF6_LINK_LSA_MIN_SIZE bytes
1058 by N>=0 IPv6 prefix blocks (with N declared beforehand). */
1061 link_lsa
= (struct ospf6_link_lsa
*)((caddr_t
)lsah
1062 + OSPF6_LSA_HEADER_SIZE
);
1063 return ospf6_prefixes_examin(
1064 (struct ospf6_prefix
*)((caddr_t
)link_lsa
1065 + OSPF6_LINK_LSA_MIN_SIZE
),
1066 lsalen
- OSPF6_LSA_HEADER_SIZE
1067 - OSPF6_LINK_LSA_MIN_SIZE
,
1068 ntohl(link_lsa
->prefix_num
) /* 32 bits */
1070 case OSPF6_LSTYPE_INTRA_PREFIX
:
1071 /* RFC5340 A.4.10, LSA header + OSPF6_INTRA_PREFIX_LSA_MIN_SIZE
1073 followed by N>=0 IPv6 prefixes (with N declared beforehand).
1078 (struct ospf6_intra_prefix_lsa
1079 *)((caddr_t
)lsah
+ OSPF6_LSA_HEADER_SIZE
);
1080 return ospf6_prefixes_examin(
1081 (struct ospf6_prefix
1082 *)((caddr_t
)intra_prefix_lsa
1083 + OSPF6_INTRA_PREFIX_LSA_MIN_SIZE
),
1084 lsalen
- OSPF6_LSA_HEADER_SIZE
1085 - OSPF6_INTRA_PREFIX_LSA_MIN_SIZE
,
1086 ntohs(intra_prefix_lsa
->prefix_num
) /* 16 bits */
1089 /* No additional validation is possible for unknown LSA types, which are
1090 themselves valid in OPSFv3, hence the default decision is to accept.
1095 /* Verify if the provided input buffer is a valid sequence of LSAs. This
1096 includes verification of LSA blocks length/alignment and dispatching
1097 of deeper-level checks. */
1099 ospf6_lsaseq_examin(struct ospf6_lsa_header
*lsah
, /* start of buffered data */
1100 size_t length
, const u_char headeronly
,
1101 /* When declared_num_lsas is not 0, compare it to the real
1103 and treat the difference as an error. */
1104 const u_int32_t declared_num_lsas
)
1106 u_int32_t counted_lsas
= 0;
1110 if (length
< OSPF6_LSA_HEADER_SIZE
) {
1111 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN
,
1114 "%s: undersized (%zu B) trailing (#%u) LSA header",
1115 __func__
, length
, counted_lsas
);
1118 /* save on ntohs() calls here and in the LSA validator */
1119 lsalen
= OSPF6_LSA_SIZE(lsah
);
1120 if (lsalen
< OSPF6_LSA_HEADER_SIZE
) {
1121 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN
,
1124 "%s: malformed LSA header #%u, declared length is %u B",
1125 __func__
, counted_lsas
, lsalen
);
1129 /* less checks here and in ospf6_lsa_examin() */
1130 if (MSG_OK
!= ospf6_lsa_examin(lsah
, lsalen
, 1)) {
1131 if (IS_OSPF6_DEBUG_MESSAGE(
1132 OSPF6_MESSAGE_TYPE_UNKNOWN
, RECV
))
1134 "%s: anomaly in header-only %s LSA #%u",
1136 ospf6_lstype_name(lsah
->type
),
1140 lsah
= (struct ospf6_lsa_header
1142 + OSPF6_LSA_HEADER_SIZE
);
1143 length
-= OSPF6_LSA_HEADER_SIZE
;
1145 /* make sure the input buffer is deep enough before
1147 if (lsalen
> length
) {
1148 if (IS_OSPF6_DEBUG_MESSAGE(
1149 OSPF6_MESSAGE_TYPE_UNKNOWN
, RECV
))
1151 "%s: anomaly in %s LSA #%u: declared length is %u B, buffered length is %zu B",
1153 ospf6_lstype_name(lsah
->type
),
1154 counted_lsas
, lsalen
, length
);
1157 if (MSG_OK
!= ospf6_lsa_examin(lsah
, lsalen
, 0)) {
1158 if (IS_OSPF6_DEBUG_MESSAGE(
1159 OSPF6_MESSAGE_TYPE_UNKNOWN
, RECV
))
1161 "%s: anomaly in %s LSA #%u",
1163 ospf6_lstype_name(lsah
->type
),
1167 lsah
= (struct ospf6_lsa_header
*)((caddr_t
)lsah
1174 if (declared_num_lsas
&& counted_lsas
!= declared_num_lsas
) {
1175 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN
, RECV
))
1177 "%s: #LSAs declared (%u) does not match actual (%u)",
1178 __func__
, declared_num_lsas
, counted_lsas
);
1184 /* Verify a complete OSPF packet for proper sizing/alignment. */
1185 static unsigned ospf6_packet_examin(struct ospf6_header
*oh
,
1186 const unsigned bytesonwire
)
1188 struct ospf6_lsupdate
*lsupd
;
1191 /* length, 1st approximation */
1192 if (bytesonwire
< OSPF6_HEADER_SIZE
) {
1193 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN
, RECV
))
1194 zlog_debug("%s: undersized (%u B) packet", __func__
,
1198 /* Now it is safe to access header fields. */
1199 if (bytesonwire
!= ntohs(oh
->length
)) {
1200 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN
, RECV
))
1202 "%s: %s packet length error (%u real, %u declared)",
1203 __func__
, lookup_msg(ospf6_message_type_str
,
1205 bytesonwire
, ntohs(oh
->length
));
1209 if (oh
->version
!= OSPFV3_VERSION
) {
1210 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN
, RECV
))
1211 zlog_debug("%s: invalid (%u) protocol version",
1212 __func__
, oh
->version
);
1215 /* length, 2nd approximation */
1216 if (oh
->type
< OSPF6_MESSAGE_TYPE_ALL
&& ospf6_packet_minlen
[oh
->type
]
1218 < OSPF6_HEADER_SIZE
+ ospf6_packet_minlen
[oh
->type
]) {
1219 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN
, RECV
))
1220 zlog_debug("%s: undersized (%u B) %s packet", __func__
,
1222 lookup_msg(ospf6_message_type_str
, oh
->type
,
1226 /* type-specific deeper validation */
1228 case OSPF6_MESSAGE_TYPE_HELLO
:
1229 /* RFC5340 A.3.2, packet header + OSPF6_HELLO_MIN_SIZE bytes
1231 by N>=0 router-IDs. */
1233 == (bytesonwire
- OSPF6_HEADER_SIZE
- OSPF6_HELLO_MIN_SIZE
)
1236 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN
, RECV
))
1237 zlog_debug("%s: alignment error in %s packet", __func__
,
1238 lookup_msg(ospf6_message_type_str
, oh
->type
,
1241 case OSPF6_MESSAGE_TYPE_DBDESC
:
1242 /* RFC5340 A.3.3, packet header + OSPF6_DB_DESC_MIN_SIZE bytes
1244 by N>=0 header-only LSAs. */
1245 test
= ospf6_lsaseq_examin(
1246 (struct ospf6_lsa_header
*)((caddr_t
)oh
1248 + OSPF6_DB_DESC_MIN_SIZE
),
1249 bytesonwire
- OSPF6_HEADER_SIZE
1250 - OSPF6_DB_DESC_MIN_SIZE
,
1253 case OSPF6_MESSAGE_TYPE_LSREQ
:
1254 /* RFC5340 A.3.4, packet header + N>=0 LS description blocks. */
1256 == (bytesonwire
- OSPF6_HEADER_SIZE
- OSPF6_LS_REQ_MIN_SIZE
)
1257 % OSPF6_LSREQ_LSDESC_FIX_SIZE
)
1259 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN
, RECV
))
1260 zlog_debug("%s: alignment error in %s packet", __func__
,
1261 lookup_msg(ospf6_message_type_str
, oh
->type
,
1264 case OSPF6_MESSAGE_TYPE_LSUPDATE
:
1265 /* RFC5340 A.3.5, packet header + OSPF6_LS_UPD_MIN_SIZE bytes
1267 by N>=0 full LSAs (with N declared beforehand). */
1268 lsupd
= (struct ospf6_lsupdate
*)((caddr_t
)oh
1269 + OSPF6_HEADER_SIZE
);
1270 test
= ospf6_lsaseq_examin(
1271 (struct ospf6_lsa_header
*)((caddr_t
)lsupd
1272 + OSPF6_LS_UPD_MIN_SIZE
),
1273 bytesonwire
- OSPF6_HEADER_SIZE
- OSPF6_LS_UPD_MIN_SIZE
,
1274 0, ntohl(lsupd
->lsa_number
) /* 32 bits */
1277 case OSPF6_MESSAGE_TYPE_LSACK
:
1278 /* RFC5340 A.3.6, packet header + N>=0 header-only LSAs. */
1279 test
= ospf6_lsaseq_examin(
1280 (struct ospf6_lsa_header
*)((caddr_t
)oh
1282 + OSPF6_LS_ACK_MIN_SIZE
),
1283 bytesonwire
- OSPF6_HEADER_SIZE
- OSPF6_LS_ACK_MIN_SIZE
,
1287 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN
, RECV
))
1288 zlog_debug("%s: invalid (%u) message type", __func__
,
1293 && IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN
, RECV
))
1294 zlog_debug("%s: anomaly in %s packet", __func__
,
1295 lookup_msg(ospf6_message_type_str
, oh
->type
, NULL
));
1299 /* Verify particular fields of otherwise correct received OSPF packet to
1300 meet the requirements of RFC. */
1301 static int ospf6_rxpacket_examin(struct ospf6_interface
*oi
,
1302 struct ospf6_header
*oh
,
1303 const unsigned bytesonwire
)
1305 char buf
[2][INET_ADDRSTRLEN
];
1307 if (MSG_OK
!= ospf6_packet_examin(oh
, bytesonwire
))
1311 if (oh
->area_id
!= oi
->area
->area_id
) {
1312 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
)) {
1313 if (oh
->area_id
== OSPF_AREA_BACKBONE
)
1315 "%s: Message may be via Virtual Link: not supported",
1319 "%s: Area-ID mismatch (my %s, rcvd %s)",
1321 inet_ntop(AF_INET
, &oi
->area
->area_id
,
1322 buf
[0], INET_ADDRSTRLEN
),
1323 inet_ntop(AF_INET
, &oh
->area_id
, buf
[1],
1329 /* Instance-ID check */
1330 if (oh
->instance_id
!= oi
->instance_id
) {
1331 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
1332 zlog_debug("%s: Instance-ID mismatch (my %u, rcvd %u)",
1333 __func__
, oi
->instance_id
, oh
->instance_id
);
1337 /* Router-ID check */
1338 if (oh
->router_id
== oi
->area
->ospf6
->router_id
) {
1339 zlog_warn("%s: Duplicate Router-ID (%s)", __func__
,
1340 inet_ntop(AF_INET
, &oh
->router_id
, buf
[0],
1347 static void ospf6_lsupdate_recv(struct in6_addr
*src
, struct in6_addr
*dst
,
1348 struct ospf6_interface
*oi
,
1349 struct ospf6_header
*oh
)
1351 struct ospf6_neighbor
*on
;
1352 struct ospf6_lsupdate
*lsupdate
;
1355 on
= ospf6_neighbor_lookup(oh
->router_id
, oi
);
1357 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
1358 zlog_debug("Neighbor not found, ignore");
1362 if (on
->state
!= OSPF6_NEIGHBOR_EXCHANGE
1363 && on
->state
!= OSPF6_NEIGHBOR_LOADING
1364 && on
->state
!= OSPF6_NEIGHBOR_FULL
) {
1365 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
1366 zlog_debug("Neighbor state less than Exchange, ignore");
1370 lsupdate
= (struct ospf6_lsupdate
*)((caddr_t
)oh
1371 + sizeof(struct ospf6_header
));
1374 for (p
= (char *)((caddr_t
)lsupdate
+ sizeof(struct ospf6_lsupdate
));
1375 p
< OSPF6_MESSAGE_END(oh
)
1376 && p
+ OSPF6_LSA_SIZE(p
) <= OSPF6_MESSAGE_END(oh
);
1377 p
+= OSPF6_LSA_SIZE(p
)) {
1378 ospf6_receive_lsa(on
, (struct ospf6_lsa_header
*)p
);
1381 assert(p
== OSPF6_MESSAGE_END(oh
));
1384 static void ospf6_lsack_recv(struct in6_addr
*src
, struct in6_addr
*dst
,
1385 struct ospf6_interface
*oi
,
1386 struct ospf6_header
*oh
)
1388 struct ospf6_neighbor
*on
;
1390 struct ospf6_lsa
*his
, *mine
;
1391 struct ospf6_lsdb
*lsdb
= NULL
;
1393 assert(oh
->type
== OSPF6_MESSAGE_TYPE_LSACK
);
1395 on
= ospf6_neighbor_lookup(oh
->router_id
, oi
);
1397 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
1398 zlog_debug("Neighbor not found, ignore");
1402 if (on
->state
!= OSPF6_NEIGHBOR_EXCHANGE
1403 && on
->state
!= OSPF6_NEIGHBOR_LOADING
1404 && on
->state
!= OSPF6_NEIGHBOR_FULL
) {
1405 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
1406 zlog_debug("Neighbor state less than Exchange, ignore");
1410 for (p
= (char *)((caddr_t
)oh
+ sizeof(struct ospf6_header
));
1411 p
+ sizeof(struct ospf6_lsa_header
) <= OSPF6_MESSAGE_END(oh
);
1412 p
+= sizeof(struct ospf6_lsa_header
)) {
1413 his
= ospf6_lsa_create_headeronly((struct ospf6_lsa_header
*)p
);
1415 switch (OSPF6_LSA_SCOPE(his
->header
->type
)) {
1416 case OSPF6_SCOPE_LINKLOCAL
:
1417 lsdb
= on
->ospf6_if
->lsdb
;
1419 case OSPF6_SCOPE_AREA
:
1420 lsdb
= on
->ospf6_if
->area
->lsdb
;
1422 case OSPF6_SCOPE_AS
:
1423 lsdb
= on
->ospf6_if
->area
->ospf6
->lsdb
;
1425 case OSPF6_SCOPE_RESERVED
:
1426 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
1427 zlog_debug("Ignoring LSA of reserved scope");
1428 ospf6_lsa_delete(his
);
1433 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
1434 zlog_debug("%s acknowledged by %s", his
->name
,
1437 /* Find database copy */
1438 mine
= ospf6_lsdb_lookup(his
->header
->type
, his
->header
->id
,
1439 his
->header
->adv_router
, lsdb
);
1441 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
1442 zlog_debug("No database copy");
1443 ospf6_lsa_delete(his
);
1447 /* Check if the LSA is on his retrans-list */
1448 mine
= ospf6_lsdb_lookup(his
->header
->type
, his
->header
->id
,
1449 his
->header
->adv_router
,
1452 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
1453 zlog_debug("Not on %s's retrans-list",
1455 ospf6_lsa_delete(his
);
1459 if (ospf6_lsa_compare(his
, mine
) != 0) {
1460 /* Log this questionable acknowledgement,
1461 and examine the next one. */
1462 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
1463 zlog_debug("Questionable acknowledgement");
1464 ospf6_lsa_delete(his
);
1468 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
1470 "Acknowledged, remove from %s's retrans-list",
1473 ospf6_decrement_retrans_count(mine
);
1474 if (OSPF6_LSA_IS_MAXAGE(mine
))
1475 ospf6_maxage_remove(on
->ospf6_if
->area
->ospf6
);
1476 ospf6_lsdb_remove(mine
, on
->retrans_list
);
1477 ospf6_lsa_delete(his
);
1480 assert(p
== OSPF6_MESSAGE_END(oh
));
1483 static u_char
*recvbuf
= NULL
;
1484 static u_char
*sendbuf
= NULL
;
1485 static unsigned int iobuflen
= 0;
1487 int ospf6_iobuf_size(unsigned int size
)
1489 u_char
*recvnew
, *sendnew
;
1491 if (size
<= iobuflen
)
1494 recvnew
= XMALLOC(MTYPE_OSPF6_MESSAGE
, size
);
1495 sendnew
= XMALLOC(MTYPE_OSPF6_MESSAGE
, size
);
1496 if (recvnew
== NULL
|| sendnew
== NULL
) {
1498 XFREE(MTYPE_OSPF6_MESSAGE
, recvnew
);
1500 XFREE(MTYPE_OSPF6_MESSAGE
, sendnew
);
1501 zlog_debug("Could not allocate I/O buffer of size %d.", size
);
1506 XFREE(MTYPE_OSPF6_MESSAGE
, recvbuf
);
1508 XFREE(MTYPE_OSPF6_MESSAGE
, sendbuf
);
1516 void ospf6_message_terminate(void)
1519 XFREE(MTYPE_OSPF6_MESSAGE
, recvbuf
);
1524 XFREE(MTYPE_OSPF6_MESSAGE
, sendbuf
);
1531 int ospf6_receive(struct thread
*thread
)
1535 char srcname
[64], dstname
[64];
1536 struct in6_addr src
, dst
;
1538 struct iovec iovector
[2];
1539 struct ospf6_interface
*oi
;
1540 struct ospf6_header
*oh
;
1542 /* add next read thread */
1543 sockfd
= THREAD_FD(thread
);
1544 thread_add_read(master
, ospf6_receive
, NULL
, sockfd
, NULL
);
1547 memset(&src
, 0, sizeof(src
));
1548 memset(&dst
, 0, sizeof(dst
));
1550 memset(recvbuf
, 0, iobuflen
);
1551 iovector
[0].iov_base
= recvbuf
;
1552 iovector
[0].iov_len
= iobuflen
;
1553 iovector
[1].iov_base
= NULL
;
1554 iovector
[1].iov_len
= 0;
1556 /* receive message */
1557 len
= ospf6_recvmsg(&src
, &dst
, &ifindex
, iovector
);
1558 if (len
> iobuflen
) {
1559 zlog_err("Excess message read");
1563 oi
= ospf6_interface_lookup_by_ifindex(ifindex
);
1564 if (oi
== NULL
|| oi
->area
== NULL
1565 || CHECK_FLAG(oi
->flag
, OSPF6_INTERFACE_DISABLE
)) {
1566 zlog_debug("Message received on disabled interface");
1569 if (CHECK_FLAG(oi
->flag
, OSPF6_INTERFACE_PASSIVE
)) {
1570 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN
, RECV
))
1571 zlog_debug("%s: Ignore message on passive interface %s",
1572 __func__
, oi
->interface
->name
);
1576 oh
= (struct ospf6_header
*)recvbuf
;
1577 if (ospf6_rxpacket_examin(oi
, oh
, len
) != MSG_OK
)
1580 /* Being here means, that no sizing/alignment issues were detected in
1581 the input packet. This renders the additional checks performed below
1582 and also in the type-specific dispatching functions a dead code,
1583 which can be dismissed in a cleanup-focused review round later. */
1586 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
)) {
1587 inet_ntop(AF_INET6
, &src
, srcname
, sizeof(srcname
));
1588 inet_ntop(AF_INET6
, &dst
, dstname
, sizeof(dstname
));
1589 zlog_debug("%s received on %s",
1590 lookup_msg(ospf6_message_type_str
, oh
->type
, NULL
),
1591 oi
->interface
->name
);
1592 zlog_debug(" src: %s", srcname
);
1593 zlog_debug(" dst: %s", dstname
);
1596 case OSPF6_MESSAGE_TYPE_HELLO
:
1597 ospf6_hello_print(oh
);
1599 case OSPF6_MESSAGE_TYPE_DBDESC
:
1600 ospf6_dbdesc_print(oh
);
1602 case OSPF6_MESSAGE_TYPE_LSREQ
:
1603 ospf6_lsreq_print(oh
);
1605 case OSPF6_MESSAGE_TYPE_LSUPDATE
:
1606 ospf6_lsupdate_print(oh
);
1608 case OSPF6_MESSAGE_TYPE_LSACK
:
1609 ospf6_lsack_print(oh
);
1617 case OSPF6_MESSAGE_TYPE_HELLO
:
1618 ospf6_hello_recv(&src
, &dst
, oi
, oh
);
1621 case OSPF6_MESSAGE_TYPE_DBDESC
:
1622 ospf6_dbdesc_recv(&src
, &dst
, oi
, oh
);
1625 case OSPF6_MESSAGE_TYPE_LSREQ
:
1626 ospf6_lsreq_recv(&src
, &dst
, oi
, oh
);
1629 case OSPF6_MESSAGE_TYPE_LSUPDATE
:
1630 ospf6_lsupdate_recv(&src
, &dst
, oi
, oh
);
1633 case OSPF6_MESSAGE_TYPE_LSACK
:
1634 ospf6_lsack_recv(&src
, &dst
, oi
, oh
);
1644 static void ospf6_send(struct in6_addr
*src
, struct in6_addr
*dst
,
1645 struct ospf6_interface
*oi
, struct ospf6_header
*oh
)
1648 char srcname
[64], dstname
[64];
1649 struct iovec iovector
[2];
1652 iovector
[0].iov_base
= (caddr_t
)oh
;
1653 iovector
[0].iov_len
= ntohs(oh
->length
);
1654 iovector
[1].iov_base
= NULL
;
1655 iovector
[1].iov_len
= 0;
1657 /* fill OSPF header */
1658 oh
->version
= OSPFV3_VERSION
;
1659 /* message type must be set before */
1660 /* message length must be set before */
1661 oh
->router_id
= oi
->area
->ospf6
->router_id
;
1662 oh
->area_id
= oi
->area
->area_id
;
1663 /* checksum is calculated by kernel */
1664 oh
->instance_id
= oi
->instance_id
;
1668 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, SEND
)) {
1669 inet_ntop(AF_INET6
, dst
, dstname
, sizeof(dstname
));
1671 inet_ntop(AF_INET6
, src
, srcname
, sizeof(srcname
));
1673 memset(srcname
, 0, sizeof(srcname
));
1674 zlog_debug("%s send on %s",
1675 lookup_msg(ospf6_message_type_str
, oh
->type
, NULL
),
1676 oi
->interface
->name
);
1677 zlog_debug(" src: %s", srcname
);
1678 zlog_debug(" dst: %s", dstname
);
1681 case OSPF6_MESSAGE_TYPE_HELLO
:
1682 ospf6_hello_print(oh
);
1684 case OSPF6_MESSAGE_TYPE_DBDESC
:
1685 ospf6_dbdesc_print(oh
);
1687 case OSPF6_MESSAGE_TYPE_LSREQ
:
1688 ospf6_lsreq_print(oh
);
1690 case OSPF6_MESSAGE_TYPE_LSUPDATE
:
1691 ospf6_lsupdate_print(oh
);
1693 case OSPF6_MESSAGE_TYPE_LSACK
:
1694 ospf6_lsack_print(oh
);
1697 zlog_debug("Unknown message");
1704 len
= ospf6_sendmsg(src
, dst
, &oi
->interface
->ifindex
, iovector
);
1705 if (len
!= ntohs(oh
->length
))
1706 zlog_err("Could not send entire message");
1709 static uint32_t ospf6_packet_max(struct ospf6_interface
*oi
)
1711 assert(oi
->ifmtu
> sizeof(struct ip6_hdr
));
1712 return oi
->ifmtu
- (sizeof(struct ip6_hdr
));
1715 int ospf6_hello_send(struct thread
*thread
)
1717 struct ospf6_interface
*oi
;
1718 struct ospf6_header
*oh
;
1719 struct ospf6_hello
*hello
;
1721 struct listnode
*node
, *nnode
;
1722 struct ospf6_neighbor
*on
;
1724 oi
= (struct ospf6_interface
*)THREAD_ARG(thread
);
1725 oi
->thread_send_hello
= (struct thread
*)NULL
;
1727 if (oi
->state
<= OSPF6_INTERFACE_DOWN
) {
1728 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_HELLO
, SEND
))
1729 zlog_debug("Unable to send Hello on down interface %s",
1730 oi
->interface
->name
);
1734 if (iobuflen
== 0) {
1735 zlog_debug("Unable to send Hello on interface %s iobuflen is 0",
1736 oi
->interface
->name
);
1740 /* set next thread */
1741 thread_add_timer(master
, ospf6_hello_send
, oi
, oi
->hello_interval
,
1742 &oi
->thread_send_hello
);
1744 memset(sendbuf
, 0, iobuflen
);
1745 oh
= (struct ospf6_header
*)sendbuf
;
1746 hello
= (struct ospf6_hello
*)((caddr_t
)oh
1747 + sizeof(struct ospf6_header
));
1749 hello
->interface_id
= htonl(oi
->interface
->ifindex
);
1750 hello
->priority
= oi
->priority
;
1751 hello
->options
[0] = oi
->area
->options
[0];
1752 hello
->options
[1] = oi
->area
->options
[1];
1753 hello
->options
[2] = oi
->area
->options
[2];
1754 hello
->hello_interval
= htons(oi
->hello_interval
);
1755 hello
->dead_interval
= htons(oi
->dead_interval
);
1756 hello
->drouter
= oi
->drouter
;
1757 hello
->bdrouter
= oi
->bdrouter
;
1759 p
= (u_char
*)((caddr_t
)hello
+ sizeof(struct ospf6_hello
));
1761 for (ALL_LIST_ELEMENTS(oi
->neighbor_list
, node
, nnode
, on
)) {
1762 if (on
->state
< OSPF6_NEIGHBOR_INIT
)
1765 if (p
- sendbuf
+ sizeof(u_int32_t
) > ospf6_packet_max(oi
)) {
1766 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_HELLO
,
1769 "sending Hello message: exceeds I/F MTU");
1773 memcpy(p
, &on
->router_id
, sizeof(u_int32_t
));
1774 p
+= sizeof(u_int32_t
);
1777 oh
->type
= OSPF6_MESSAGE_TYPE_HELLO
;
1778 oh
->length
= htons(p
- sendbuf
);
1780 ospf6_send(oi
->linklocal_addr
, &allspfrouters6
, oi
, oh
);
1784 int ospf6_dbdesc_send(struct thread
*thread
)
1786 struct ospf6_neighbor
*on
;
1787 struct ospf6_header
*oh
;
1788 struct ospf6_dbdesc
*dbdesc
;
1790 struct ospf6_lsa
*lsa
;
1791 struct in6_addr
*dst
;
1793 on
= (struct ospf6_neighbor
*)THREAD_ARG(thread
);
1794 on
->thread_send_dbdesc
= (struct thread
*)NULL
;
1796 if (on
->state
< OSPF6_NEIGHBOR_EXSTART
) {
1797 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_DBDESC
, SEND
))
1799 "Quit to send DbDesc to neighbor %s state %s",
1800 on
->name
, ospf6_neighbor_state_str
[on
->state
]);
1804 /* set next thread if master */
1805 if (CHECK_FLAG(on
->dbdesc_bits
, OSPF6_DBDESC_MSBIT
))
1806 thread_add_timer(master
, ospf6_dbdesc_send
, on
,
1807 on
->ospf6_if
->rxmt_interval
,
1808 &on
->thread_send_dbdesc
);
1810 memset(sendbuf
, 0, iobuflen
);
1811 oh
= (struct ospf6_header
*)sendbuf
;
1812 dbdesc
= (struct ospf6_dbdesc
*)((caddr_t
)oh
1813 + sizeof(struct ospf6_header
));
1815 /* if this is initial one, initialize sequence number for DbDesc */
1816 if (CHECK_FLAG(on
->dbdesc_bits
, OSPF6_DBDESC_IBIT
)
1817 && (on
->dbdesc_seqnum
== 0)) {
1818 on
->dbdesc_seqnum
= monotime(NULL
);
1821 dbdesc
->options
[0] = on
->ospf6_if
->area
->options
[0];
1822 dbdesc
->options
[1] = on
->ospf6_if
->area
->options
[1];
1823 dbdesc
->options
[2] = on
->ospf6_if
->area
->options
[2];
1824 dbdesc
->ifmtu
= htons(on
->ospf6_if
->ifmtu
);
1825 dbdesc
->bits
= on
->dbdesc_bits
;
1826 dbdesc
->seqnum
= htonl(on
->dbdesc_seqnum
);
1828 /* if this is not initial one, set LSA headers in dbdesc */
1829 p
= (u_char
*)((caddr_t
)dbdesc
+ sizeof(struct ospf6_dbdesc
));
1830 if (!CHECK_FLAG(on
->dbdesc_bits
, OSPF6_DBDESC_IBIT
)) {
1831 for (ALL_LSDB(on
->dbdesc_list
, lsa
)) {
1832 ospf6_lsa_age_update_to_send(lsa
,
1833 on
->ospf6_if
->transdelay
);
1836 if (p
- sendbuf
+ sizeof(struct ospf6_lsa_header
)
1837 > ospf6_packet_max(on
->ospf6_if
)) {
1838 ospf6_lsdb_lsa_unlock(lsa
);
1841 memcpy(p
, lsa
->header
, sizeof(struct ospf6_lsa_header
));
1842 p
+= sizeof(struct ospf6_lsa_header
);
1846 oh
->type
= OSPF6_MESSAGE_TYPE_DBDESC
;
1847 oh
->length
= htons(p
- sendbuf
);
1850 if (on
->ospf6_if
->state
== OSPF6_INTERFACE_POINTTOPOINT
)
1851 dst
= &allspfrouters6
;
1853 dst
= &on
->linklocal_addr
;
1855 ospf6_send(on
->ospf6_if
->linklocal_addr
, dst
, on
->ospf6_if
, oh
);
1860 int ospf6_dbdesc_send_newone(struct thread
*thread
)
1862 struct ospf6_neighbor
*on
;
1863 struct ospf6_lsa
*lsa
;
1864 unsigned int size
= 0;
1866 on
= (struct ospf6_neighbor
*)THREAD_ARG(thread
);
1867 ospf6_lsdb_remove_all(on
->dbdesc_list
);
1869 /* move LSAs from summary_list to dbdesc_list (within neighbor
1871 so that ospf6_send_dbdesc () can send those LSAs */
1872 size
= sizeof(struct ospf6_lsa_header
) + sizeof(struct ospf6_dbdesc
);
1873 for (ALL_LSDB(on
->summary_list
, lsa
)) {
1874 if (size
+ sizeof(struct ospf6_lsa_header
)
1875 > ospf6_packet_max(on
->ospf6_if
)) {
1876 ospf6_lsdb_lsa_unlock(lsa
);
1880 ospf6_lsdb_add(ospf6_lsa_copy(lsa
), on
->dbdesc_list
);
1881 ospf6_lsdb_remove(lsa
, on
->summary_list
);
1882 size
+= sizeof(struct ospf6_lsa_header
);
1885 if (on
->summary_list
->count
== 0)
1886 UNSET_FLAG(on
->dbdesc_bits
, OSPF6_DBDESC_MBIT
);
1888 /* If slave, More bit check must be done here */
1889 if (!CHECK_FLAG(on
->dbdesc_bits
, OSPF6_DBDESC_MSBIT
) && /* Slave */
1890 !CHECK_FLAG(on
->dbdesc_last
.bits
, OSPF6_DBDESC_MBIT
)
1891 && !CHECK_FLAG(on
->dbdesc_bits
, OSPF6_DBDESC_MBIT
))
1892 thread_add_event(master
, exchange_done
, on
, 0, NULL
);
1894 thread_execute(master
, ospf6_dbdesc_send
, on
, 0);
1898 int ospf6_lsreq_send(struct thread
*thread
)
1900 struct ospf6_neighbor
*on
;
1901 struct ospf6_header
*oh
;
1902 struct ospf6_lsreq_entry
*e
;
1904 struct ospf6_lsa
*lsa
, *last_req
;
1906 on
= (struct ospf6_neighbor
*)THREAD_ARG(thread
);
1907 on
->thread_send_lsreq
= (struct thread
*)NULL
;
1909 /* LSReq will be sent only in ExStart or Loading */
1910 if (on
->state
!= OSPF6_NEIGHBOR_EXCHANGE
1911 && on
->state
!= OSPF6_NEIGHBOR_LOADING
) {
1912 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_LSREQ
, SEND
))
1913 zlog_debug("Quit to send LSReq to neighbor %s state %s",
1915 ospf6_neighbor_state_str
[on
->state
]);
1919 /* schedule loading_done if request list is empty */
1920 if (on
->request_list
->count
== 0) {
1921 thread_add_event(master
, loading_done
, on
, 0, NULL
);
1925 memset(sendbuf
, 0, iobuflen
);
1926 oh
= (struct ospf6_header
*)sendbuf
;
1929 /* set Request entries in lsreq */
1930 p
= (u_char
*)((caddr_t
)oh
+ sizeof(struct ospf6_header
));
1931 for (ALL_LSDB(on
->request_list
, lsa
)) {
1933 if (p
- sendbuf
+ sizeof(struct ospf6_lsreq_entry
)
1934 > ospf6_packet_max(on
->ospf6_if
)) {
1935 ospf6_lsdb_lsa_unlock(lsa
);
1939 e
= (struct ospf6_lsreq_entry
*)p
;
1940 e
->type
= lsa
->header
->type
;
1941 e
->id
= lsa
->header
->id
;
1942 e
->adv_router
= lsa
->header
->adv_router
;
1943 p
+= sizeof(struct ospf6_lsreq_entry
);
1947 if (last_req
!= NULL
) {
1948 if (on
->last_ls_req
!= NULL
) {
1949 ospf6_lsa_unlock(on
->last_ls_req
);
1951 ospf6_lsa_lock(last_req
);
1952 on
->last_ls_req
= last_req
;
1955 oh
->type
= OSPF6_MESSAGE_TYPE_LSREQ
;
1956 oh
->length
= htons(p
- sendbuf
);
1958 if (on
->ospf6_if
->state
== OSPF6_INTERFACE_POINTTOPOINT
)
1959 ospf6_send(on
->ospf6_if
->linklocal_addr
, &allspfrouters6
,
1962 ospf6_send(on
->ospf6_if
->linklocal_addr
, &on
->linklocal_addr
,
1965 /* set next thread */
1966 if (on
->request_list
->count
!= 0) {
1967 on
->thread_send_lsreq
= NULL
;
1968 thread_add_timer(master
, ospf6_lsreq_send
, on
,
1969 on
->ospf6_if
->rxmt_interval
,
1970 &on
->thread_send_lsreq
);
1976 static void ospf6_send_lsupdate(struct ospf6_neighbor
*on
,
1977 struct ospf6_interface
*oi
,
1978 struct ospf6_header
*oh
)
1982 if ((on
->ospf6_if
->state
== OSPF6_INTERFACE_POINTTOPOINT
) ||
1983 (on
->ospf6_if
->state
== OSPF6_INTERFACE_DR
) ||
1984 (on
->ospf6_if
->state
== OSPF6_INTERFACE_BDR
)) {
1985 ospf6_send(on
->ospf6_if
->linklocal_addr
,
1986 &allspfrouters6
, on
->ospf6_if
, oh
);
1988 ospf6_send(on
->ospf6_if
->linklocal_addr
,
1989 &on
->linklocal_addr
, on
->ospf6_if
, oh
);
1992 if ((oi
->state
== OSPF6_INTERFACE_POINTTOPOINT
) ||
1993 (oi
->state
== OSPF6_INTERFACE_DR
) ||
1994 (oi
->state
== OSPF6_INTERFACE_BDR
)) {
1995 ospf6_send(oi
->linklocal_addr
, &allspfrouters6
, oi
, oh
);
1997 ospf6_send(oi
->linklocal_addr
, &alldrouters6
, oi
, oh
);
2002 int ospf6_lsupdate_send_neighbor(struct thread
*thread
)
2004 struct ospf6_neighbor
*on
;
2005 struct ospf6_header
*oh
;
2006 struct ospf6_lsupdate
*lsupdate
;
2009 struct ospf6_lsa
*lsa
;
2011 on
= (struct ospf6_neighbor
*)THREAD_ARG(thread
);
2012 on
->thread_send_lsupdate
= (struct thread
*)NULL
;
2014 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_LSUPDATE
, SEND
))
2015 zlog_debug("LSUpdate to neighbor %s", on
->name
);
2017 if (on
->state
< OSPF6_NEIGHBOR_EXCHANGE
) {
2018 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_LSUPDATE
, SEND
))
2019 zlog_debug("Quit to send (neighbor state %s)",
2020 ospf6_neighbor_state_str
[on
->state
]);
2024 memset(sendbuf
, 0, iobuflen
);
2025 oh
= (struct ospf6_header
*)sendbuf
;
2026 lsupdate
= (struct ospf6_lsupdate
*)((caddr_t
)oh
2027 + sizeof(struct ospf6_header
));
2029 p
= (u_char
*)((caddr_t
)lsupdate
+ sizeof(struct ospf6_lsupdate
));
2032 /* lsupdate_list lists those LSA which doesn't need to be
2033 retransmitted. remove those from the list */
2034 for (ALL_LSDB(on
->lsupdate_list
, lsa
)) {
2036 if ((p
- sendbuf
+ (unsigned int)OSPF6_LSA_SIZE(lsa
->header
))
2037 > ospf6_packet_max(on
->ospf6_if
)) {
2039 oh
->type
= OSPF6_MESSAGE_TYPE_LSUPDATE
;
2040 oh
->length
= htons(p
- sendbuf
);
2041 lsupdate
->lsa_number
= htonl(lsa_cnt
);
2043 ospf6_send_lsupdate(on
, NULL
, oh
);
2045 memset(sendbuf
, 0, iobuflen
);
2046 oh
= (struct ospf6_header
*)sendbuf
;
2047 lsupdate
= (struct ospf6_lsupdate
*)((caddr_t
)oh
2048 + sizeof(struct ospf6_header
));
2050 p
= (u_char
*)((caddr_t
)lsupdate
2051 + sizeof(struct ospf6_lsupdate
));
2056 ospf6_lsa_age_update_to_send(lsa
, on
->ospf6_if
->transdelay
);
2057 memcpy(p
, lsa
->header
, OSPF6_LSA_SIZE(lsa
->header
));
2058 p
+= OSPF6_LSA_SIZE(lsa
->header
);
2061 assert(lsa
->lock
== 2);
2062 ospf6_lsdb_remove(lsa
, on
->lsupdate_list
);
2066 oh
->type
= OSPF6_MESSAGE_TYPE_LSUPDATE
;
2067 oh
->length
= htons(p
- sendbuf
);
2068 lsupdate
->lsa_number
= htonl(lsa_cnt
);
2069 ospf6_send_lsupdate(on
, NULL
, oh
);
2072 /* The addresses used for retransmissions are different from those sent
2074 first time and so we need to separate them here.
2076 memset(sendbuf
, 0, iobuflen
);
2077 oh
= (struct ospf6_header
*)sendbuf
;
2078 lsupdate
= (struct ospf6_lsupdate
*)((caddr_t
)oh
2079 + sizeof(struct ospf6_header
));
2080 p
= (u_char
*)((caddr_t
)lsupdate
+ sizeof(struct ospf6_lsupdate
));
2083 for (ALL_LSDB(on
->retrans_list
, lsa
)) {
2085 if ((p
- sendbuf
+ (unsigned int)OSPF6_LSA_SIZE(lsa
->header
))
2086 > ospf6_packet_max(on
->ospf6_if
)) {
2088 oh
->type
= OSPF6_MESSAGE_TYPE_LSUPDATE
;
2089 oh
->length
= htons(p
- sendbuf
);
2090 lsupdate
->lsa_number
= htonl(lsa_cnt
);
2092 if (on
->ospf6_if
->state
==
2093 OSPF6_INTERFACE_POINTTOPOINT
) {
2094 ospf6_send(on
->ospf6_if
->linklocal_addr
,
2098 ospf6_send(on
->ospf6_if
->linklocal_addr
,
2099 &on
->linklocal_addr
,
2103 memset(sendbuf
, 0, iobuflen
);
2104 oh
= (struct ospf6_header
*)sendbuf
;
2105 lsupdate
= (struct ospf6_lsupdate
*)((caddr_t
)oh
2106 + sizeof(struct ospf6_header
));
2107 p
= (u_char
*)((caddr_t
)lsupdate
+
2108 sizeof(struct ospf6_lsupdate
));
2113 ospf6_lsa_age_update_to_send(lsa
, on
->ospf6_if
->transdelay
);
2114 memcpy(p
, lsa
->header
, OSPF6_LSA_SIZE(lsa
->header
));
2115 p
+= OSPF6_LSA_SIZE(lsa
->header
);
2120 oh
->type
= OSPF6_MESSAGE_TYPE_LSUPDATE
;
2121 oh
->length
= htons(p
- sendbuf
);
2122 lsupdate
->lsa_number
= htonl(lsa_cnt
);
2124 if (on
->ospf6_if
->state
== OSPF6_INTERFACE_POINTTOPOINT
)
2125 ospf6_send(on
->ospf6_if
->linklocal_addr
,
2126 &allspfrouters6
, on
->ospf6_if
, oh
);
2128 ospf6_send(on
->ospf6_if
->linklocal_addr
,
2129 &on
->linklocal_addr
, on
->ospf6_if
, oh
);
2132 if (on
->lsupdate_list
->count
!= 0) {
2133 on
->thread_send_lsupdate
= NULL
;
2134 thread_add_event(master
, ospf6_lsupdate_send_neighbor
, on
, 0,
2135 &on
->thread_send_lsupdate
);
2136 } else if (on
->retrans_list
->count
!= 0) {
2137 on
->thread_send_lsupdate
= NULL
;
2138 thread_add_timer(master
, ospf6_lsupdate_send_neighbor
, on
,
2139 on
->ospf6_if
->rxmt_interval
,
2140 &on
->thread_send_lsupdate
);
2145 int ospf6_lsupdate_send_interface(struct thread
*thread
)
2147 struct ospf6_interface
*oi
;
2148 struct ospf6_header
*oh
;
2149 struct ospf6_lsupdate
*lsupdate
;
2152 struct ospf6_lsa
*lsa
;
2154 oi
= (struct ospf6_interface
*)THREAD_ARG(thread
);
2155 oi
->thread_send_lsupdate
= (struct thread
*)NULL
;
2157 if (oi
->state
<= OSPF6_INTERFACE_WAITING
) {
2158 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_LSUPDATE
, SEND
))
2160 "Quit to send LSUpdate to interface %s state %s",
2161 oi
->interface
->name
,
2162 ospf6_interface_state_str
[oi
->state
]);
2166 /* if we have nothing to send, return */
2167 if (oi
->lsupdate_list
->count
== 0)
2170 memset(sendbuf
, 0, iobuflen
);
2171 oh
= (struct ospf6_header
*)sendbuf
;
2172 lsupdate
= (struct ospf6_lsupdate
*)((caddr_t
)oh
2173 + sizeof(struct ospf6_header
));
2175 p
= (u_char
*)((caddr_t
)lsupdate
+ sizeof(struct ospf6_lsupdate
));
2178 for (ALL_LSDB(oi
->lsupdate_list
, lsa
)) {
2180 if ((p
- sendbuf
+ ((unsigned int)OSPF6_LSA_SIZE(lsa
->header
)))
2181 > ospf6_packet_max(oi
)) {
2183 oh
->type
= OSPF6_MESSAGE_TYPE_LSUPDATE
;
2184 oh
->length
= htons(p
- sendbuf
);
2185 lsupdate
->lsa_number
= htonl(lsa_cnt
);
2187 ospf6_send_lsupdate(NULL
, oi
, oh
);
2188 zlog_debug("%s: LSUpdate length %d",
2189 __PRETTY_FUNCTION__
, ntohs(oh
->length
));
2191 memset(sendbuf
, 0, iobuflen
);
2192 oh
= (struct ospf6_header
*)sendbuf
;
2193 lsupdate
= (struct ospf6_lsupdate
*)((caddr_t
)oh
2194 + sizeof(struct ospf6_header
));
2196 p
= (u_char
*)((caddr_t
)lsupdate
2197 + sizeof(struct ospf6_lsupdate
));
2202 ospf6_lsa_age_update_to_send(lsa
, oi
->transdelay
);
2203 memcpy(p
, lsa
->header
, OSPF6_LSA_SIZE(lsa
->header
));
2204 p
+= OSPF6_LSA_SIZE(lsa
->header
);
2207 assert(lsa
->lock
== 2);
2208 ospf6_lsdb_remove(lsa
, oi
->lsupdate_list
);
2212 oh
->type
= OSPF6_MESSAGE_TYPE_LSUPDATE
;
2213 oh
->length
= htons(p
- sendbuf
);
2214 lsupdate
->lsa_number
= htonl(lsa_cnt
);
2216 ospf6_send_lsupdate(NULL
, oi
, oh
);
2219 if (oi
->lsupdate_list
->count
> 0) {
2220 oi
->thread_send_lsupdate
= NULL
;
2221 thread_add_event(master
, ospf6_lsupdate_send_interface
, oi
, 0,
2222 &oi
->thread_send_lsupdate
);
2228 int ospf6_lsack_send_neighbor(struct thread
*thread
)
2230 struct ospf6_neighbor
*on
;
2231 struct ospf6_header
*oh
;
2233 struct ospf6_lsa
*lsa
;
2236 on
= (struct ospf6_neighbor
*)THREAD_ARG(thread
);
2237 on
->thread_send_lsack
= (struct thread
*)NULL
;
2239 if (on
->state
< OSPF6_NEIGHBOR_EXCHANGE
) {
2240 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_LSACK
, SEND
))
2241 zlog_debug("Quit to send LSAck to neighbor %s state %s",
2243 ospf6_neighbor_state_str
[on
->state
]);
2247 /* if we have nothing to send, return */
2248 if (on
->lsack_list
->count
== 0)
2251 memset(sendbuf
, 0, iobuflen
);
2252 oh
= (struct ospf6_header
*)sendbuf
;
2254 p
= (u_char
*)((caddr_t
)oh
+ sizeof(struct ospf6_header
));
2256 for (ALL_LSDB(on
->lsack_list
, lsa
)) {
2258 if (p
- sendbuf
+ sizeof(struct ospf6_lsa_header
)
2259 > ospf6_packet_max(on
->ospf6_if
)) {
2260 /* if we run out of packet size/space here,
2261 better to try again soon. */
2263 oh
->type
= OSPF6_MESSAGE_TYPE_LSACK
;
2264 oh
->length
= htons(p
- sendbuf
);
2266 ospf6_send(on
->ospf6_if
->linklocal_addr
,
2267 &on
->linklocal_addr
,
2270 memset(sendbuf
, 0, iobuflen
);
2271 oh
= (struct ospf6_header
*)sendbuf
;
2272 p
= (u_char
*)((caddr_t
)oh
+
2273 sizeof(struct ospf6_header
));
2278 ospf6_lsa_age_update_to_send(lsa
, on
->ospf6_if
->transdelay
);
2279 memcpy(p
, lsa
->header
, sizeof(struct ospf6_lsa_header
));
2280 p
+= sizeof(struct ospf6_lsa_header
);
2282 assert(lsa
->lock
== 2);
2283 ospf6_lsdb_remove(lsa
, on
->lsack_list
);
2288 oh
->type
= OSPF6_MESSAGE_TYPE_LSACK
;
2289 oh
->length
= htons(p
- sendbuf
);
2291 ospf6_send(on
->ospf6_if
->linklocal_addr
, &on
->linklocal_addr
,
2295 if (on
->lsack_list
->count
> 0)
2296 thread_add_event(master
, ospf6_lsack_send_neighbor
, on
, 0,
2297 &on
->thread_send_lsack
);
2302 int ospf6_lsack_send_interface(struct thread
*thread
)
2304 struct ospf6_interface
*oi
;
2305 struct ospf6_header
*oh
;
2307 struct ospf6_lsa
*lsa
;
2310 oi
= (struct ospf6_interface
*)THREAD_ARG(thread
);
2311 oi
->thread_send_lsack
= (struct thread
*)NULL
;
2313 if (oi
->state
<= OSPF6_INTERFACE_WAITING
) {
2314 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_LSACK
, SEND
))
2316 "Quit to send LSAck to interface %s state %s",
2317 oi
->interface
->name
,
2318 ospf6_interface_state_str
[oi
->state
]);
2322 /* if we have nothing to send, return */
2323 if (oi
->lsack_list
->count
== 0)
2326 memset(sendbuf
, 0, iobuflen
);
2327 oh
= (struct ospf6_header
*)sendbuf
;
2329 p
= (u_char
*)((caddr_t
)oh
+ sizeof(struct ospf6_header
));
2331 for (ALL_LSDB(oi
->lsack_list
, lsa
)) {
2333 if (p
- sendbuf
+ sizeof(struct ospf6_lsa_header
)
2334 > ospf6_packet_max(oi
)) {
2335 /* if we run out of packet size/space here,
2336 better to try again soon. */
2337 THREAD_OFF(oi
->thread_send_lsack
);
2338 thread_add_event(master
, ospf6_lsack_send_interface
, oi
,
2339 0, &oi
->thread_send_lsack
);
2341 ospf6_lsdb_lsa_unlock(lsa
);
2345 ospf6_lsa_age_update_to_send(lsa
, oi
->transdelay
);
2346 memcpy(p
, lsa
->header
, sizeof(struct ospf6_lsa_header
));
2347 p
+= sizeof(struct ospf6_lsa_header
);
2349 assert(lsa
->lock
== 2);
2350 ospf6_lsdb_remove(lsa
, oi
->lsack_list
);
2355 oh
->type
= OSPF6_MESSAGE_TYPE_LSACK
;
2356 oh
->length
= htons(p
- sendbuf
);
2358 if ((oi
->state
== OSPF6_INTERFACE_POINTTOPOINT
)
2359 || (oi
->state
== OSPF6_INTERFACE_DR
)
2360 || (oi
->state
== OSPF6_INTERFACE_BDR
))
2361 ospf6_send(oi
->linklocal_addr
, &allspfrouters6
, oi
, oh
);
2363 ospf6_send(oi
->linklocal_addr
, &alldrouters6
, oi
, oh
);
2366 if (oi
->lsack_list
->count
> 0)
2367 thread_add_event(master
, ospf6_lsack_send_interface
, oi
, 0,
2368 &oi
->thread_send_lsack
);
2375 DEFUN (debug_ospf6_message
,
2376 debug_ospf6_message_cmd
,
2377 "debug ospf6 message <unknown|hello|dbdesc|lsreq|lsupdate|lsack|all> [<send|recv>]",
2380 "Debug OSPFv3 message\n"
2381 "Debug Unknown message\n"
2382 "Debug Hello message\n"
2383 "Debug Database Description message\n"
2384 "Debug Link State Request message\n"
2385 "Debug Link State Update message\n"
2386 "Debug Link State Acknowledgement message\n"
2387 "Debug All message\n"
2388 "Debug only sending message\n"
2389 "Debug only receiving message\n")
2392 int idx_send_recv
= 4;
2393 unsigned char level
= 0;
2398 if (!strncmp(argv
[idx_packet
]->arg
, "u", 1))
2399 type
= OSPF6_MESSAGE_TYPE_UNKNOWN
;
2400 else if (!strncmp(argv
[idx_packet
]->arg
, "h", 1))
2401 type
= OSPF6_MESSAGE_TYPE_HELLO
;
2402 else if (!strncmp(argv
[idx_packet
]->arg
, "d", 1))
2403 type
= OSPF6_MESSAGE_TYPE_DBDESC
;
2404 else if (!strncmp(argv
[idx_packet
]->arg
, "lsr", 3))
2405 type
= OSPF6_MESSAGE_TYPE_LSREQ
;
2406 else if (!strncmp(argv
[idx_packet
]->arg
, "lsu", 3))
2407 type
= OSPF6_MESSAGE_TYPE_LSUPDATE
;
2408 else if (!strncmp(argv
[idx_packet
]->arg
, "lsa", 3))
2409 type
= OSPF6_MESSAGE_TYPE_LSACK
;
2410 else if (!strncmp(argv
[idx_packet
]->arg
, "a", 1))
2411 type
= OSPF6_MESSAGE_TYPE_ALL
;
2414 level
= OSPF6_DEBUG_MESSAGE_SEND
| OSPF6_DEBUG_MESSAGE_RECV
;
2415 else if (!strncmp(argv
[idx_send_recv
]->arg
, "s", 1))
2416 level
= OSPF6_DEBUG_MESSAGE_SEND
;
2417 else if (!strncmp(argv
[idx_send_recv
]->arg
, "r", 1))
2418 level
= OSPF6_DEBUG_MESSAGE_RECV
;
2420 if (type
== OSPF6_MESSAGE_TYPE_ALL
) {
2421 for (i
= 0; i
< 6; i
++)
2422 OSPF6_DEBUG_MESSAGE_ON(i
, level
);
2424 OSPF6_DEBUG_MESSAGE_ON(type
, level
);
2429 DEFUN (no_debug_ospf6_message
,
2430 no_debug_ospf6_message_cmd
,
2431 "no debug ospf6 message <unknown|hello|dbdesc|lsreq|lsupdate|lsack|all> [<send|recv>]",
2435 "Debug OSPFv3 message\n"
2436 "Debug Unknown message\n"
2437 "Debug Hello message\n"
2438 "Debug Database Description message\n"
2439 "Debug Link State Request message\n"
2440 "Debug Link State Update message\n"
2441 "Debug Link State Acknowledgement message\n"
2442 "Debug All message\n"
2443 "Debug only sending message\n"
2444 "Debug only receiving message\n")
2447 int idx_send_recv
= 5;
2448 unsigned char level
= 0;
2453 if (!strncmp(argv
[idx_packet
]->arg
, "u", 1))
2454 type
= OSPF6_MESSAGE_TYPE_UNKNOWN
;
2455 else if (!strncmp(argv
[idx_packet
]->arg
, "h", 1))
2456 type
= OSPF6_MESSAGE_TYPE_HELLO
;
2457 else if (!strncmp(argv
[idx_packet
]->arg
, "d", 1))
2458 type
= OSPF6_MESSAGE_TYPE_DBDESC
;
2459 else if (!strncmp(argv
[idx_packet
]->arg
, "lsr", 3))
2460 type
= OSPF6_MESSAGE_TYPE_LSREQ
;
2461 else if (!strncmp(argv
[idx_packet
]->arg
, "lsu", 3))
2462 type
= OSPF6_MESSAGE_TYPE_LSUPDATE
;
2463 else if (!strncmp(argv
[idx_packet
]->arg
, "lsa", 3))
2464 type
= OSPF6_MESSAGE_TYPE_LSACK
;
2465 else if (!strncmp(argv
[idx_packet
]->arg
, "a", 1))
2466 type
= OSPF6_MESSAGE_TYPE_ALL
;
2469 level
= OSPF6_DEBUG_MESSAGE_SEND
| OSPF6_DEBUG_MESSAGE_RECV
;
2470 else if (!strncmp(argv
[idx_send_recv
]->arg
, "s", 1))
2471 level
= OSPF6_DEBUG_MESSAGE_SEND
;
2472 else if (!strncmp(argv
[idx_send_recv
]->arg
, "r", 1))
2473 level
= OSPF6_DEBUG_MESSAGE_RECV
;
2475 if (type
== OSPF6_MESSAGE_TYPE_ALL
) {
2476 for (i
= 0; i
< 6; i
++)
2477 OSPF6_DEBUG_MESSAGE_OFF(i
, level
);
2479 OSPF6_DEBUG_MESSAGE_OFF(type
, level
);
2485 int config_write_ospf6_debug_message(struct vty
*vty
)
2487 const char *type_str
[] = {"unknown", "hello", "dbdesc",
2488 "lsreq", "lsupdate", "lsack"};
2489 unsigned char s
= 0, r
= 0;
2492 for (i
= 0; i
< 6; i
++) {
2493 if (IS_OSPF6_DEBUG_MESSAGE(i
, SEND
))
2495 if (IS_OSPF6_DEBUG_MESSAGE(i
, RECV
))
2499 if (s
== 0x3f && r
== 0x3f) {
2500 vty_out(vty
, "debug ospf6 message all\n");
2504 if (s
== 0x3f && r
== 0) {
2505 vty_out(vty
, "debug ospf6 message all send\n");
2507 } else if (s
== 0 && r
== 0x3f) {
2508 vty_out(vty
, "debug ospf6 message all recv\n");
2512 /* Unknown message is logged by default */
2513 if (!IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN
, SEND
)
2514 && !IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN
, RECV
))
2515 vty_out(vty
, "no debug ospf6 message unknown\n");
2516 else if (!IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN
, SEND
))
2517 vty_out(vty
, "no debug ospf6 message unknown send\n");
2518 else if (!IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN
, RECV
))
2519 vty_out(vty
, "no debug ospf6 message unknown recv\n");
2521 for (i
= 1; i
< 6; i
++) {
2522 if (IS_OSPF6_DEBUG_MESSAGE(i
, SEND
)
2523 && IS_OSPF6_DEBUG_MESSAGE(i
, RECV
))
2524 vty_out(vty
, "debug ospf6 message %s\n", type_str
[i
]);
2525 else if (IS_OSPF6_DEBUG_MESSAGE(i
, SEND
))
2526 vty_out(vty
, "debug ospf6 message %s send\n",
2528 else if (IS_OSPF6_DEBUG_MESSAGE(i
, RECV
))
2529 vty_out(vty
, "debug ospf6 message %s recv\n",
2536 void install_element_ospf6_debug_message(void)
2538 install_element(ENABLE_NODE
, &debug_ospf6_message_cmd
);
2539 install_element(ENABLE_NODE
, &no_debug_ospf6_message_cmd
);
2540 install_element(CONFIG_NODE
, &debug_ospf6_message_cmd
);
2541 install_element(CONFIG_NODE
, &no_debug_ospf6_message_cmd
);