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))
326 /* Execute neighbor events */
327 thread_execute(master
, hello_received
, on
, 0);
329 thread_execute(master
, twoway_received
, on
, 0);
331 thread_execute(master
, oneway_received
, on
, 0);
333 /* Schedule interface events */
335 thread_add_event(master
, backup_seen
, oi
, 0, NULL
);
337 thread_add_event(master
, neighbor_change
, oi
, 0, NULL
);
339 if (neighbor_ifindex_change
&& on
->state
== OSPF6_NEIGHBOR_FULL
)
340 OSPF6_ROUTER_LSA_SCHEDULE(oi
->area
);
343 static void ospf6_dbdesc_recv_master(struct ospf6_header
*oh
,
344 struct ospf6_neighbor
*on
)
346 struct ospf6_dbdesc
*dbdesc
;
349 dbdesc
= (struct ospf6_dbdesc
*)((caddr_t
)oh
350 + sizeof(struct ospf6_header
));
352 if (on
->state
< OSPF6_NEIGHBOR_INIT
) {
353 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
354 zlog_debug("Neighbor state less than Init, ignore");
359 case OSPF6_NEIGHBOR_TWOWAY
:
360 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
361 zlog_debug("Neighbor state is 2-Way, ignore");
364 case OSPF6_NEIGHBOR_INIT
:
365 thread_execute(master
, twoway_received
, on
, 0);
366 if (on
->state
!= OSPF6_NEIGHBOR_EXSTART
) {
367 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
369 "Neighbor state is not ExStart, ignore");
372 /* else fall through to ExStart */
374 case OSPF6_NEIGHBOR_EXSTART
:
375 /* if neighbor obeys us as our slave, schedule negotiation_done
376 and process LSA Headers. Otherwise, ignore this message */
377 if (!CHECK_FLAG(dbdesc
->bits
, OSPF6_DBDESC_MSBIT
)
378 && !CHECK_FLAG(dbdesc
->bits
, OSPF6_DBDESC_IBIT
)
379 && ntohl(dbdesc
->seqnum
) == on
->dbdesc_seqnum
) {
380 /* execute NegotiationDone */
381 thread_execute(master
, negotiation_done
, on
, 0);
383 /* Record neighbor options */
384 memcpy(on
->options
, dbdesc
->options
,
385 sizeof(on
->options
));
387 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
388 zlog_debug("Negotiation failed");
391 /* fall through to exchange */
393 case OSPF6_NEIGHBOR_EXCHANGE
:
394 if (!memcmp(dbdesc
, &on
->dbdesc_last
,
395 sizeof(struct ospf6_dbdesc
))) {
396 /* Duplicated DatabaseDescription is dropped by master
398 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
400 "Duplicated dbdesc discarded by Master, ignore");
404 if (CHECK_FLAG(dbdesc
->bits
, OSPF6_DBDESC_MSBIT
)) {
405 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
406 zlog_debug("Master/Slave bit mismatch");
407 thread_add_event(master
, seqnumber_mismatch
, on
, 0,
412 if (CHECK_FLAG(dbdesc
->bits
, OSPF6_DBDESC_IBIT
)) {
413 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
414 zlog_debug("Initialize bit mismatch");
415 thread_add_event(master
, seqnumber_mismatch
, on
, 0,
420 if (memcmp(on
->options
, dbdesc
->options
, sizeof(on
->options
))) {
421 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
422 zlog_debug("Option field mismatch");
423 thread_add_event(master
, seqnumber_mismatch
, on
, 0,
428 if (ntohl(dbdesc
->seqnum
) != on
->dbdesc_seqnum
) {
429 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
431 "Sequence number mismatch (%#lx expected)",
432 (u_long
)on
->dbdesc_seqnum
);
433 thread_add_event(master
, seqnumber_mismatch
, on
, 0,
439 case OSPF6_NEIGHBOR_LOADING
:
440 case OSPF6_NEIGHBOR_FULL
:
441 if (!memcmp(dbdesc
, &on
->dbdesc_last
,
442 sizeof(struct ospf6_dbdesc
))) {
443 /* Duplicated DatabaseDescription is dropped by master
445 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
447 "Duplicated dbdesc discarded by Master, ignore");
451 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
452 zlog_debug("Not duplicate dbdesc in state %s",
453 ospf6_neighbor_state_str
[on
->state
]);
454 thread_add_event(master
, seqnumber_mismatch
, on
, 0, NULL
);
462 /* Process LSA headers */
463 for (p
= (char *)((caddr_t
)dbdesc
+ sizeof(struct ospf6_dbdesc
));
464 p
+ sizeof(struct ospf6_lsa_header
) <= OSPF6_MESSAGE_END(oh
);
465 p
+= sizeof(struct ospf6_lsa_header
)) {
466 struct ospf6_lsa
*his
, *mine
;
467 struct ospf6_lsdb
*lsdb
= NULL
;
469 his
= ospf6_lsa_create_headeronly((struct ospf6_lsa_header
*)p
);
471 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
472 zlog_debug("%s", his
->name
);
474 switch (OSPF6_LSA_SCOPE(his
->header
->type
)) {
475 case OSPF6_SCOPE_LINKLOCAL
:
476 lsdb
= on
->ospf6_if
->lsdb
;
478 case OSPF6_SCOPE_AREA
:
479 lsdb
= on
->ospf6_if
->area
->lsdb
;
482 lsdb
= on
->ospf6_if
->area
->ospf6
->lsdb
;
484 case OSPF6_SCOPE_RESERVED
:
485 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
486 zlog_debug("Ignoring LSA of reserved scope");
487 ospf6_lsa_delete(his
);
492 if (ntohs(his
->header
->type
) == OSPF6_LSTYPE_AS_EXTERNAL
493 && IS_AREA_STUB(on
->ospf6_if
->area
)) {
494 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
496 "SeqNumMismatch (E-bit mismatch), discard");
497 ospf6_lsa_delete(his
);
498 thread_add_event(master
, seqnumber_mismatch
, on
, 0,
503 mine
= ospf6_lsdb_lookup(his
->header
->type
, his
->header
->id
,
504 his
->header
->adv_router
, lsdb
);
506 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
507 zlog_debug("Add request (No database copy)");
508 ospf6_lsdb_add(ospf6_lsa_copy(his
), on
->request_list
);
509 } else if (ospf6_lsa_compare(his
, mine
) < 0) {
510 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
511 zlog_debug("Add request (Received MoreRecent)");
512 ospf6_lsdb_add(ospf6_lsa_copy(his
), on
->request_list
);
514 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
515 zlog_debug("Discard (Existing MoreRecent)");
517 ospf6_lsa_delete(his
);
520 assert(p
== OSPF6_MESSAGE_END(oh
));
522 /* Increment sequence number */
525 /* schedule send lsreq */
526 if (on
->request_list
->count
)
527 thread_add_event(master
, ospf6_lsreq_send
, on
, 0,
528 &on
->thread_send_lsreq
);
530 THREAD_OFF(on
->thread_send_dbdesc
);
533 if (!CHECK_FLAG(dbdesc
->bits
, OSPF6_DBDESC_MBIT
)
534 && !CHECK_FLAG(on
->dbdesc_bits
, OSPF6_DBDESC_MBIT
))
535 thread_add_event(master
, exchange_done
, on
, 0, NULL
);
537 on
->thread_send_dbdesc
= NULL
;
538 thread_add_event(master
, ospf6_dbdesc_send_newone
, on
, 0,
539 &on
->thread_send_dbdesc
);
542 /* save last received dbdesc */
543 memcpy(&on
->dbdesc_last
, dbdesc
, sizeof(struct ospf6_dbdesc
));
546 static void ospf6_dbdesc_recv_slave(struct ospf6_header
*oh
,
547 struct ospf6_neighbor
*on
)
549 struct ospf6_dbdesc
*dbdesc
;
552 dbdesc
= (struct ospf6_dbdesc
*)((caddr_t
)oh
553 + sizeof(struct ospf6_header
));
555 if (on
->state
< OSPF6_NEIGHBOR_INIT
) {
556 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
557 zlog_debug("Neighbor state less than Init, ignore");
562 case OSPF6_NEIGHBOR_TWOWAY
:
563 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
564 zlog_debug("Neighbor state is 2-Way, ignore");
567 case OSPF6_NEIGHBOR_INIT
:
568 thread_execute(master
, twoway_received
, on
, 0);
569 if (on
->state
!= OSPF6_NEIGHBOR_EXSTART
) {
570 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
572 "Neighbor state is not ExStart, ignore");
575 /* else fall through to ExStart */
577 case OSPF6_NEIGHBOR_EXSTART
:
578 /* If the neighbor is Master, act as Slave. Schedule
580 and process LSA Headers. Otherwise, ignore this message */
581 if (CHECK_FLAG(dbdesc
->bits
, OSPF6_DBDESC_IBIT
)
582 && CHECK_FLAG(dbdesc
->bits
, OSPF6_DBDESC_MBIT
)
583 && CHECK_FLAG(dbdesc
->bits
, OSPF6_DBDESC_MSBIT
)
585 == sizeof(struct ospf6_header
)
586 + sizeof(struct ospf6_dbdesc
)) {
587 /* set the master/slave bit to slave */
588 UNSET_FLAG(on
->dbdesc_bits
, OSPF6_DBDESC_MSBIT
);
590 /* set the DD sequence number to one specified by master
592 on
->dbdesc_seqnum
= ntohl(dbdesc
->seqnum
);
594 /* schedule NegotiationDone */
595 thread_execute(master
, negotiation_done
, on
, 0);
597 /* Record neighbor options */
598 memcpy(on
->options
, dbdesc
->options
,
599 sizeof(on
->options
));
601 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
602 zlog_debug("Negotiation failed");
607 case OSPF6_NEIGHBOR_EXCHANGE
:
608 if (!memcmp(dbdesc
, &on
->dbdesc_last
,
609 sizeof(struct ospf6_dbdesc
))) {
610 /* Duplicated DatabaseDescription causes slave to
612 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
614 "Duplicated dbdesc causes retransmit");
615 THREAD_OFF(on
->thread_send_dbdesc
);
616 on
->thread_send_dbdesc
= NULL
;
617 thread_add_event(master
, ospf6_dbdesc_send
, on
, 0,
618 &on
->thread_send_dbdesc
);
622 if (!CHECK_FLAG(dbdesc
->bits
, OSPF6_DBDESC_MSBIT
)) {
623 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
624 zlog_debug("Master/Slave bit mismatch");
625 thread_add_event(master
, seqnumber_mismatch
, on
, 0,
630 if (CHECK_FLAG(dbdesc
->bits
, OSPF6_DBDESC_IBIT
)) {
631 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
632 zlog_debug("Initialize bit mismatch");
633 thread_add_event(master
, seqnumber_mismatch
, on
, 0,
638 if (memcmp(on
->options
, dbdesc
->options
, sizeof(on
->options
))) {
639 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
640 zlog_debug("Option field mismatch");
641 thread_add_event(master
, seqnumber_mismatch
, on
, 0,
646 if (ntohl(dbdesc
->seqnum
) != on
->dbdesc_seqnum
+ 1) {
647 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
649 "Sequence number mismatch (%#lx expected)",
650 (u_long
)on
->dbdesc_seqnum
+ 1);
651 thread_add_event(master
, seqnumber_mismatch
, on
, 0,
657 case OSPF6_NEIGHBOR_LOADING
:
658 case OSPF6_NEIGHBOR_FULL
:
659 if (!memcmp(dbdesc
, &on
->dbdesc_last
,
660 sizeof(struct ospf6_dbdesc
))) {
661 /* Duplicated DatabaseDescription causes slave to
663 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
665 "Duplicated dbdesc causes retransmit");
666 THREAD_OFF(on
->thread_send_dbdesc
);
667 thread_add_event(master
, ospf6_dbdesc_send
, on
, 0,
668 &on
->thread_send_dbdesc
);
672 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
673 zlog_debug("Not duplicate dbdesc in state %s",
674 ospf6_neighbor_state_str
[on
->state
]);
675 thread_add_event(master
, seqnumber_mismatch
, on
, 0, NULL
);
683 /* Process LSA headers */
684 for (p
= (char *)((caddr_t
)dbdesc
+ sizeof(struct ospf6_dbdesc
));
685 p
+ sizeof(struct ospf6_lsa_header
) <= OSPF6_MESSAGE_END(oh
);
686 p
+= sizeof(struct ospf6_lsa_header
)) {
687 struct ospf6_lsa
*his
, *mine
;
688 struct ospf6_lsdb
*lsdb
= NULL
;
690 his
= ospf6_lsa_create_headeronly((struct ospf6_lsa_header
*)p
);
692 switch (OSPF6_LSA_SCOPE(his
->header
->type
)) {
693 case OSPF6_SCOPE_LINKLOCAL
:
694 lsdb
= on
->ospf6_if
->lsdb
;
696 case OSPF6_SCOPE_AREA
:
697 lsdb
= on
->ospf6_if
->area
->lsdb
;
700 lsdb
= on
->ospf6_if
->area
->ospf6
->lsdb
;
702 case OSPF6_SCOPE_RESERVED
:
703 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
704 zlog_debug("Ignoring LSA of reserved scope");
705 ospf6_lsa_delete(his
);
710 if (OSPF6_LSA_SCOPE(his
->header
->type
) == OSPF6_SCOPE_AS
711 && IS_AREA_STUB(on
->ospf6_if
->area
)) {
712 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
713 zlog_debug("E-bit mismatch with LSA Headers");
714 ospf6_lsa_delete(his
);
715 thread_add_event(master
, seqnumber_mismatch
, on
, 0,
720 mine
= ospf6_lsdb_lookup(his
->header
->type
, his
->header
->id
,
721 his
->header
->adv_router
, lsdb
);
722 if (mine
== NULL
|| ospf6_lsa_compare(his
, mine
) < 0) {
723 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
724 zlog_debug("Add request-list: %s", his
->name
);
725 ospf6_lsdb_add(ospf6_lsa_copy(his
), on
->request_list
);
727 ospf6_lsa_delete(his
);
730 assert(p
== OSPF6_MESSAGE_END(oh
));
732 /* Set sequence number to Master's */
733 on
->dbdesc_seqnum
= ntohl(dbdesc
->seqnum
);
735 /* schedule send lsreq */
736 if (on
->request_list
->count
)
737 thread_add_event(master
, ospf6_lsreq_send
, on
, 0,
738 &on
->thread_send_lsreq
);
740 THREAD_OFF(on
->thread_send_dbdesc
);
741 thread_add_event(master
, ospf6_dbdesc_send_newone
, on
, 0,
742 &on
->thread_send_dbdesc
);
744 /* save last received dbdesc */
745 memcpy(&on
->dbdesc_last
, dbdesc
, sizeof(struct ospf6_dbdesc
));
748 static void ospf6_dbdesc_recv(struct in6_addr
*src
, struct in6_addr
*dst
,
749 struct ospf6_interface
*oi
,
750 struct ospf6_header
*oh
)
752 struct ospf6_neighbor
*on
;
753 struct ospf6_dbdesc
*dbdesc
;
755 on
= ospf6_neighbor_lookup(oh
->router_id
, oi
);
757 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
758 zlog_debug("Neighbor not found, ignore");
762 dbdesc
= (struct ospf6_dbdesc
*)((caddr_t
)oh
763 + sizeof(struct ospf6_header
));
765 /* Interface MTU check */
766 if (!oi
->mtu_ignore
&& ntohs(dbdesc
->ifmtu
) != oi
->ifmtu
) {
767 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
768 zlog_debug("I/F MTU mismatch");
772 if (dbdesc
->reserved1
|| dbdesc
->reserved2
) {
773 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
775 "Non-0 reserved field in %s's DbDesc, correct",
777 dbdesc
->reserved1
= 0;
778 dbdesc
->reserved2
= 0;
783 if (ntohl(oh
->router_id
) < ntohl(ospf6
->router_id
))
784 ospf6_dbdesc_recv_master(oh
, on
);
785 else if (ntohl(ospf6
->router_id
) < ntohl(oh
->router_id
))
786 ospf6_dbdesc_recv_slave(oh
, on
);
788 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
789 zlog_debug("Can't decide which is master, ignore");
793 static void ospf6_lsreq_recv(struct in6_addr
*src
, struct in6_addr
*dst
,
794 struct ospf6_interface
*oi
,
795 struct ospf6_header
*oh
)
797 struct ospf6_neighbor
*on
;
799 struct ospf6_lsreq_entry
*e
;
800 struct ospf6_lsdb
*lsdb
= NULL
;
801 struct ospf6_lsa
*lsa
;
803 on
= ospf6_neighbor_lookup(oh
->router_id
, oi
);
805 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
806 zlog_debug("Neighbor not found, ignore");
810 if (on
->state
!= OSPF6_NEIGHBOR_EXCHANGE
811 && on
->state
!= OSPF6_NEIGHBOR_LOADING
812 && on
->state
!= OSPF6_NEIGHBOR_FULL
) {
813 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
814 zlog_debug("Neighbor state less than Exchange, ignore");
820 /* Process each request */
821 for (p
= (char *)((caddr_t
)oh
+ sizeof(struct ospf6_header
));
822 p
+ sizeof(struct ospf6_lsreq_entry
) <= OSPF6_MESSAGE_END(oh
);
823 p
+= sizeof(struct ospf6_lsreq_entry
)) {
824 e
= (struct ospf6_lsreq_entry
*)p
;
826 switch (OSPF6_LSA_SCOPE(e
->type
)) {
827 case OSPF6_SCOPE_LINKLOCAL
:
828 lsdb
= on
->ospf6_if
->lsdb
;
830 case OSPF6_SCOPE_AREA
:
831 lsdb
= on
->ospf6_if
->area
->lsdb
;
834 lsdb
= on
->ospf6_if
->area
->ospf6
->lsdb
;
837 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
838 zlog_debug("Ignoring LSA of reserved scope");
843 /* Find database copy */
844 lsa
= ospf6_lsdb_lookup(e
->type
, e
->id
, e
->adv_router
, lsdb
);
846 char id
[16], adv_router
[16];
847 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
)) {
848 inet_ntop(AF_INET
, &e
->id
, id
, sizeof(id
));
849 inet_ntop(AF_INET
, &e
->adv_router
, adv_router
,
852 "Can't find requested [%s Id:%s Adv:%s]",
853 ospf6_lstype_name(e
->type
), id
,
856 thread_add_event(master
, bad_lsreq
, on
, 0, NULL
);
860 ospf6_lsdb_add(ospf6_lsa_copy(lsa
), on
->lsupdate_list
);
863 assert(p
== OSPF6_MESSAGE_END(oh
));
865 /* schedule send lsupdate */
866 THREAD_OFF(on
->thread_send_lsupdate
);
867 thread_add_event(master
, ospf6_lsupdate_send_neighbor
, on
, 0,
868 &on
->thread_send_lsupdate
);
871 /* Verify, that the specified memory area contains exactly N valid IPv6
872 prefixes as specified by RFC5340, A.4.1. */
873 static unsigned ospf6_prefixes_examin(
874 struct ospf6_prefix
*current
, /* start of buffer */
876 const u_int32_t req_num_pfxs
/* always compared with the actual number
880 u_char requested_pfx_bytes
;
881 u_int32_t real_num_pfxs
= 0;
884 if (length
< OSPF6_PREFIX_MIN_SIZE
) {
885 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN
,
887 zlog_debug("%s: undersized IPv6 prefix header",
891 /* safe to look deeper */
892 if (current
->prefix_length
> IPV6_MAX_BITLEN
) {
893 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN
,
895 zlog_debug("%s: invalid PrefixLength (%u bits)",
896 __func__
, current
->prefix_length
);
899 /* covers both fixed- and variable-sized fields */
900 requested_pfx_bytes
=
901 OSPF6_PREFIX_MIN_SIZE
902 + OSPF6_PREFIX_SPACE(current
->prefix_length
);
903 if (requested_pfx_bytes
> length
) {
904 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN
,
906 zlog_debug("%s: undersized IPv6 prefix",
911 length
-= requested_pfx_bytes
;
912 current
= (struct ospf6_prefix
*)((caddr_t
)current
913 + requested_pfx_bytes
);
916 if (real_num_pfxs
!= req_num_pfxs
) {
917 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN
, RECV
))
919 "%s: IPv6 prefix number mismatch (%u required, %u real)",
920 __func__
, req_num_pfxs
, real_num_pfxs
);
926 /* Verify an LSA to have a valid length and dispatch further (where
927 appropriate) to check if the contents, including nested IPv6 prefixes,
928 is properly sized/aligned within the LSA. Note that this function gets
929 LSA type in network byte order, uses in host byte order and passes to
930 ospf6_lstype_name() in network byte order again. */
931 static unsigned ospf6_lsa_examin(struct ospf6_lsa_header
*lsah
,
932 const u_int16_t lsalen
,
933 const u_char headeronly
)
935 struct ospf6_intra_prefix_lsa
*intra_prefix_lsa
;
936 struct ospf6_as_external_lsa
*as_external_lsa
;
937 struct ospf6_link_lsa
*link_lsa
;
942 /* In case an additional minimum length constraint is defined for
944 LSA type, make sure that this constraint is met. */
945 lsatype
= ntohs(lsah
->type
);
946 ltindex
= lsatype
& OSPF6_LSTYPE_FCODE_MASK
;
947 if (ltindex
< OSPF6_LSTYPE_SIZE
&& ospf6_lsa_minlen
[ltindex
]
948 && lsalen
< ospf6_lsa_minlen
[ltindex
] + OSPF6_LSA_HEADER_SIZE
) {
949 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN
, RECV
))
950 zlog_debug("%s: undersized (%u B) LSA", __func__
,
955 case OSPF6_LSTYPE_ROUTER
:
956 /* RFC5340 A.4.3, LSA header + OSPF6_ROUTER_LSA_MIN_SIZE bytes
958 by N>=0 interface descriptions. */
959 if ((lsalen
- OSPF6_LSA_HEADER_SIZE
- OSPF6_ROUTER_LSA_MIN_SIZE
)
960 % OSPF6_ROUTER_LSDESC_FIX_SIZE
) {
961 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN
,
964 "%s: interface description alignment error",
969 case OSPF6_LSTYPE_NETWORK
:
970 /* RFC5340 A.4.4, LSA header + OSPF6_NETWORK_LSA_MIN_SIZE bytes
971 followed by N>=0 attached router descriptions. */
972 if ((lsalen
- OSPF6_LSA_HEADER_SIZE
973 - OSPF6_NETWORK_LSA_MIN_SIZE
)
974 % OSPF6_NETWORK_LSDESC_FIX_SIZE
) {
975 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN
,
978 "%s: router description alignment error",
983 case OSPF6_LSTYPE_INTER_PREFIX
:
984 /* RFC5340 A.4.5, LSA header + OSPF6_INTER_PREFIX_LSA_MIN_SIZE
986 followed by 3-4 fields of a single IPv6 prefix. */
989 return ospf6_prefixes_examin(
991 *)((caddr_t
)lsah
+ OSPF6_LSA_HEADER_SIZE
992 + OSPF6_INTER_PREFIX_LSA_MIN_SIZE
),
993 lsalen
- OSPF6_LSA_HEADER_SIZE
994 - OSPF6_INTER_PREFIX_LSA_MIN_SIZE
,
996 case OSPF6_LSTYPE_INTER_ROUTER
:
997 /* RFC5340 A.4.6, fixed-size LSA. */
999 > OSPF6_LSA_HEADER_SIZE
+ OSPF6_INTER_ROUTER_LSA_FIX_SIZE
) {
1000 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN
,
1002 zlog_debug("%s: oversized (%u B) LSA", __func__
,
1007 case OSPF6_LSTYPE_AS_EXTERNAL
: /* RFC5340 A.4.7, same as A.4.8. */
1008 case OSPF6_LSTYPE_TYPE_7
:
1009 /* RFC5340 A.4.8, LSA header + OSPF6_AS_EXTERNAL_LSA_MIN_SIZE
1011 followed by 3-4 fields of IPv6 prefix and 3 conditional LSA
1013 16 bytes of forwarding address, 4 bytes of external route
1015 4 bytes of referenced link state ID. */
1019 (struct ospf6_as_external_lsa
1020 *)((caddr_t
)lsah
+ OSPF6_LSA_HEADER_SIZE
);
1022 OSPF6_LSA_HEADER_SIZE
+ OSPF6_AS_EXTERNAL_LSA_MIN_SIZE
;
1023 /* To find out if the last optional field (Referenced Link State
1025 assumed in this LSA, we need to access fixed fields of the
1027 prefix before ospf6_prefix_examin() confirms its sizing. */
1028 if (exp_length
+ OSPF6_PREFIX_MIN_SIZE
> lsalen
) {
1029 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN
,
1031 zlog_debug("%s: undersized (%u B) LSA header",
1035 /* forwarding address */
1036 if (CHECK_FLAG(as_external_lsa
->bits_metric
, OSPF6_ASBR_BIT_F
))
1038 /* external route tag */
1039 if (CHECK_FLAG(as_external_lsa
->bits_metric
, OSPF6_ASBR_BIT_T
))
1041 /* referenced link state ID */
1042 if (as_external_lsa
->prefix
.u
._prefix_referenced_lstype
)
1044 /* All the fixed-size fields (mandatory and optional) must fit.
1046 this check does not include any IPv6 prefix fields. */
1047 if (exp_length
> lsalen
) {
1048 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN
,
1050 zlog_debug("%s: undersized (%u B) LSA header",
1054 /* The last call completely covers the remainder (IPv6 prefix).
1056 return ospf6_prefixes_examin(
1057 (struct ospf6_prefix
1058 *)((caddr_t
)as_external_lsa
1059 + OSPF6_AS_EXTERNAL_LSA_MIN_SIZE
),
1060 lsalen
- exp_length
, 1);
1061 case OSPF6_LSTYPE_LINK
:
1062 /* RFC5340 A.4.9, LSA header + OSPF6_LINK_LSA_MIN_SIZE bytes
1064 by N>=0 IPv6 prefix blocks (with N declared beforehand). */
1067 link_lsa
= (struct ospf6_link_lsa
*)((caddr_t
)lsah
1068 + OSPF6_LSA_HEADER_SIZE
);
1069 return ospf6_prefixes_examin(
1070 (struct ospf6_prefix
*)((caddr_t
)link_lsa
1071 + OSPF6_LINK_LSA_MIN_SIZE
),
1072 lsalen
- OSPF6_LSA_HEADER_SIZE
1073 - OSPF6_LINK_LSA_MIN_SIZE
,
1074 ntohl(link_lsa
->prefix_num
) /* 32 bits */
1076 case OSPF6_LSTYPE_INTRA_PREFIX
:
1077 /* RFC5340 A.4.10, LSA header + OSPF6_INTRA_PREFIX_LSA_MIN_SIZE
1079 followed by N>=0 IPv6 prefixes (with N declared beforehand).
1084 (struct ospf6_intra_prefix_lsa
1085 *)((caddr_t
)lsah
+ OSPF6_LSA_HEADER_SIZE
);
1086 return ospf6_prefixes_examin(
1087 (struct ospf6_prefix
1088 *)((caddr_t
)intra_prefix_lsa
1089 + OSPF6_INTRA_PREFIX_LSA_MIN_SIZE
),
1090 lsalen
- OSPF6_LSA_HEADER_SIZE
1091 - OSPF6_INTRA_PREFIX_LSA_MIN_SIZE
,
1092 ntohs(intra_prefix_lsa
->prefix_num
) /* 16 bits */
1095 /* No additional validation is possible for unknown LSA types, which are
1096 themselves valid in OPSFv3, hence the default decision is to accept.
1101 /* Verify if the provided input buffer is a valid sequence of LSAs. This
1102 includes verification of LSA blocks length/alignment and dispatching
1103 of deeper-level checks. */
1105 ospf6_lsaseq_examin(struct ospf6_lsa_header
*lsah
, /* start of buffered data */
1106 size_t length
, const u_char headeronly
,
1107 /* When declared_num_lsas is not 0, compare it to the real
1109 and treat the difference as an error. */
1110 const u_int32_t declared_num_lsas
)
1112 u_int32_t counted_lsas
= 0;
1116 if (length
< OSPF6_LSA_HEADER_SIZE
) {
1117 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN
,
1120 "%s: undersized (%zu B) trailing (#%u) LSA header",
1121 __func__
, length
, counted_lsas
);
1124 /* save on ntohs() calls here and in the LSA validator */
1125 lsalen
= OSPF6_LSA_SIZE(lsah
);
1126 if (lsalen
< OSPF6_LSA_HEADER_SIZE
) {
1127 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN
,
1130 "%s: malformed LSA header #%u, declared length is %u B",
1131 __func__
, counted_lsas
, lsalen
);
1135 /* less checks here and in ospf6_lsa_examin() */
1136 if (MSG_OK
!= ospf6_lsa_examin(lsah
, lsalen
, 1)) {
1137 if (IS_OSPF6_DEBUG_MESSAGE(
1138 OSPF6_MESSAGE_TYPE_UNKNOWN
, RECV
))
1140 "%s: anomaly in header-only %s LSA #%u",
1142 ospf6_lstype_name(lsah
->type
),
1146 lsah
= (struct ospf6_lsa_header
1148 + OSPF6_LSA_HEADER_SIZE
);
1149 length
-= OSPF6_LSA_HEADER_SIZE
;
1151 /* make sure the input buffer is deep enough before
1153 if (lsalen
> length
) {
1154 if (IS_OSPF6_DEBUG_MESSAGE(
1155 OSPF6_MESSAGE_TYPE_UNKNOWN
, RECV
))
1157 "%s: anomaly in %s LSA #%u: declared length is %u B, buffered length is %zu B",
1159 ospf6_lstype_name(lsah
->type
),
1160 counted_lsas
, lsalen
, length
);
1163 if (MSG_OK
!= ospf6_lsa_examin(lsah
, lsalen
, 0)) {
1164 if (IS_OSPF6_DEBUG_MESSAGE(
1165 OSPF6_MESSAGE_TYPE_UNKNOWN
, RECV
))
1167 "%s: anomaly in %s LSA #%u",
1169 ospf6_lstype_name(lsah
->type
),
1173 lsah
= (struct ospf6_lsa_header
*)((caddr_t
)lsah
1180 if (declared_num_lsas
&& counted_lsas
!= declared_num_lsas
) {
1181 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN
, RECV
))
1183 "%s: #LSAs declared (%u) does not match actual (%u)",
1184 __func__
, declared_num_lsas
, counted_lsas
);
1190 /* Verify a complete OSPF packet for proper sizing/alignment. */
1191 static unsigned ospf6_packet_examin(struct ospf6_header
*oh
,
1192 const unsigned bytesonwire
)
1194 struct ospf6_lsupdate
*lsupd
;
1197 /* length, 1st approximation */
1198 if (bytesonwire
< OSPF6_HEADER_SIZE
) {
1199 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN
, RECV
))
1200 zlog_debug("%s: undersized (%u B) packet", __func__
,
1204 /* Now it is safe to access header fields. */
1205 if (bytesonwire
!= ntohs(oh
->length
)) {
1206 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN
, RECV
))
1208 "%s: %s packet length error (%u real, %u declared)",
1209 __func__
, lookup_msg(ospf6_message_type_str
,
1211 bytesonwire
, ntohs(oh
->length
));
1215 if (oh
->version
!= OSPFV3_VERSION
) {
1216 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN
, RECV
))
1217 zlog_debug("%s: invalid (%u) protocol version",
1218 __func__
, oh
->version
);
1221 /* length, 2nd approximation */
1222 if (oh
->type
< OSPF6_MESSAGE_TYPE_ALL
&& ospf6_packet_minlen
[oh
->type
]
1224 < OSPF6_HEADER_SIZE
+ ospf6_packet_minlen
[oh
->type
]) {
1225 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN
, RECV
))
1226 zlog_debug("%s: undersized (%u B) %s packet", __func__
,
1228 lookup_msg(ospf6_message_type_str
, oh
->type
,
1232 /* type-specific deeper validation */
1234 case OSPF6_MESSAGE_TYPE_HELLO
:
1235 /* RFC5340 A.3.2, packet header + OSPF6_HELLO_MIN_SIZE bytes
1237 by N>=0 router-IDs. */
1239 == (bytesonwire
- OSPF6_HEADER_SIZE
- OSPF6_HELLO_MIN_SIZE
)
1242 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN
, RECV
))
1243 zlog_debug("%s: alignment error in %s packet", __func__
,
1244 lookup_msg(ospf6_message_type_str
, oh
->type
,
1247 case OSPF6_MESSAGE_TYPE_DBDESC
:
1248 /* RFC5340 A.3.3, packet header + OSPF6_DB_DESC_MIN_SIZE bytes
1250 by N>=0 header-only LSAs. */
1251 test
= ospf6_lsaseq_examin(
1252 (struct ospf6_lsa_header
*)((caddr_t
)oh
1254 + OSPF6_DB_DESC_MIN_SIZE
),
1255 bytesonwire
- OSPF6_HEADER_SIZE
1256 - OSPF6_DB_DESC_MIN_SIZE
,
1259 case OSPF6_MESSAGE_TYPE_LSREQ
:
1260 /* RFC5340 A.3.4, packet header + N>=0 LS description blocks. */
1262 == (bytesonwire
- OSPF6_HEADER_SIZE
- OSPF6_LS_REQ_MIN_SIZE
)
1263 % OSPF6_LSREQ_LSDESC_FIX_SIZE
)
1265 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN
, RECV
))
1266 zlog_debug("%s: alignment error in %s packet", __func__
,
1267 lookup_msg(ospf6_message_type_str
, oh
->type
,
1270 case OSPF6_MESSAGE_TYPE_LSUPDATE
:
1271 /* RFC5340 A.3.5, packet header + OSPF6_LS_UPD_MIN_SIZE bytes
1273 by N>=0 full LSAs (with N declared beforehand). */
1274 lsupd
= (struct ospf6_lsupdate
*)((caddr_t
)oh
1275 + OSPF6_HEADER_SIZE
);
1276 test
= ospf6_lsaseq_examin(
1277 (struct ospf6_lsa_header
*)((caddr_t
)lsupd
1278 + OSPF6_LS_UPD_MIN_SIZE
),
1279 bytesonwire
- OSPF6_HEADER_SIZE
- OSPF6_LS_UPD_MIN_SIZE
,
1280 0, ntohl(lsupd
->lsa_number
) /* 32 bits */
1283 case OSPF6_MESSAGE_TYPE_LSACK
:
1284 /* RFC5340 A.3.6, packet header + N>=0 header-only LSAs. */
1285 test
= ospf6_lsaseq_examin(
1286 (struct ospf6_lsa_header
*)((caddr_t
)oh
1288 + OSPF6_LS_ACK_MIN_SIZE
),
1289 bytesonwire
- OSPF6_HEADER_SIZE
- OSPF6_LS_ACK_MIN_SIZE
,
1293 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN
, RECV
))
1294 zlog_debug("%s: invalid (%u) message type", __func__
,
1299 && IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN
, RECV
))
1300 zlog_debug("%s: anomaly in %s packet", __func__
,
1301 lookup_msg(ospf6_message_type_str
, oh
->type
, NULL
));
1305 /* Verify particular fields of otherwise correct received OSPF packet to
1306 meet the requirements of RFC. */
1307 static int ospf6_rxpacket_examin(struct ospf6_interface
*oi
,
1308 struct ospf6_header
*oh
,
1309 const unsigned bytesonwire
)
1311 char buf
[2][INET_ADDRSTRLEN
];
1313 if (MSG_OK
!= ospf6_packet_examin(oh
, bytesonwire
))
1317 if (oh
->area_id
!= oi
->area
->area_id
) {
1318 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
)) {
1319 if (oh
->area_id
== OSPF_AREA_BACKBONE
)
1321 "%s: Message may be via Virtual Link: not supported",
1325 "%s: Area-ID mismatch (my %s, rcvd %s)",
1327 inet_ntop(AF_INET
, &oi
->area
->area_id
,
1328 buf
[0], INET_ADDRSTRLEN
),
1329 inet_ntop(AF_INET
, &oh
->area_id
, buf
[1],
1335 /* Instance-ID check */
1336 if (oh
->instance_id
!= oi
->instance_id
) {
1337 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
1338 zlog_debug("%s: Instance-ID mismatch (my %u, rcvd %u)",
1339 __func__
, oi
->instance_id
, oh
->instance_id
);
1343 /* Router-ID check */
1344 if (oh
->router_id
== oi
->area
->ospf6
->router_id
) {
1345 zlog_warn("%s: Duplicate Router-ID (%s)", __func__
,
1346 inet_ntop(AF_INET
, &oh
->router_id
, buf
[0],
1353 static void ospf6_lsupdate_recv(struct in6_addr
*src
, struct in6_addr
*dst
,
1354 struct ospf6_interface
*oi
,
1355 struct ospf6_header
*oh
)
1357 struct ospf6_neighbor
*on
;
1358 struct ospf6_lsupdate
*lsupdate
;
1361 on
= ospf6_neighbor_lookup(oh
->router_id
, oi
);
1363 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
1364 zlog_debug("Neighbor not found, ignore");
1368 if (on
->state
!= OSPF6_NEIGHBOR_EXCHANGE
1369 && on
->state
!= OSPF6_NEIGHBOR_LOADING
1370 && on
->state
!= OSPF6_NEIGHBOR_FULL
) {
1371 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
1372 zlog_debug("Neighbor state less than Exchange, ignore");
1376 lsupdate
= (struct ospf6_lsupdate
*)((caddr_t
)oh
1377 + sizeof(struct ospf6_header
));
1382 for (p
= (char *)((caddr_t
)lsupdate
+ sizeof(struct ospf6_lsupdate
));
1383 p
< OSPF6_MESSAGE_END(oh
)
1384 && p
+ OSPF6_LSA_SIZE(p
) <= OSPF6_MESSAGE_END(oh
);
1385 p
+= OSPF6_LSA_SIZE(p
)) {
1386 ospf6_receive_lsa(on
, (struct ospf6_lsa_header
*)p
);
1389 assert(p
== OSPF6_MESSAGE_END(oh
));
1392 static void ospf6_lsack_recv(struct in6_addr
*src
, struct in6_addr
*dst
,
1393 struct ospf6_interface
*oi
,
1394 struct ospf6_header
*oh
)
1396 struct ospf6_neighbor
*on
;
1398 struct ospf6_lsa
*his
, *mine
;
1399 struct ospf6_lsdb
*lsdb
= NULL
;
1401 assert(oh
->type
== OSPF6_MESSAGE_TYPE_LSACK
);
1403 on
= ospf6_neighbor_lookup(oh
->router_id
, oi
);
1405 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
1406 zlog_debug("Neighbor not found, ignore");
1410 if (on
->state
!= OSPF6_NEIGHBOR_EXCHANGE
1411 && on
->state
!= OSPF6_NEIGHBOR_LOADING
1412 && on
->state
!= OSPF6_NEIGHBOR_FULL
) {
1413 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
1414 zlog_debug("Neighbor state less than Exchange, ignore");
1420 for (p
= (char *)((caddr_t
)oh
+ sizeof(struct ospf6_header
));
1421 p
+ sizeof(struct ospf6_lsa_header
) <= OSPF6_MESSAGE_END(oh
);
1422 p
+= sizeof(struct ospf6_lsa_header
)) {
1423 his
= ospf6_lsa_create_headeronly((struct ospf6_lsa_header
*)p
);
1425 switch (OSPF6_LSA_SCOPE(his
->header
->type
)) {
1426 case OSPF6_SCOPE_LINKLOCAL
:
1427 lsdb
= on
->ospf6_if
->lsdb
;
1429 case OSPF6_SCOPE_AREA
:
1430 lsdb
= on
->ospf6_if
->area
->lsdb
;
1432 case OSPF6_SCOPE_AS
:
1433 lsdb
= on
->ospf6_if
->area
->ospf6
->lsdb
;
1435 case OSPF6_SCOPE_RESERVED
:
1436 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
1437 zlog_debug("Ignoring LSA of reserved scope");
1438 ospf6_lsa_delete(his
);
1443 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
1444 zlog_debug("%s acknowledged by %s", his
->name
,
1447 /* Find database copy */
1448 mine
= ospf6_lsdb_lookup(his
->header
->type
, his
->header
->id
,
1449 his
->header
->adv_router
, lsdb
);
1451 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
1452 zlog_debug("No database copy");
1453 ospf6_lsa_delete(his
);
1457 /* Check if the LSA is on his retrans-list */
1458 mine
= ospf6_lsdb_lookup(his
->header
->type
, his
->header
->id
,
1459 his
->header
->adv_router
,
1462 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
1463 zlog_debug("Not on %s's retrans-list",
1465 ospf6_lsa_delete(his
);
1469 if (ospf6_lsa_compare(his
, mine
) != 0) {
1470 /* Log this questionable acknowledgement,
1471 and examine the next one. */
1472 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
1473 zlog_debug("Questionable acknowledgement");
1474 ospf6_lsa_delete(his
);
1478 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
))
1480 "Acknowledged, remove from %s's retrans-list",
1483 ospf6_decrement_retrans_count(mine
);
1484 if (OSPF6_LSA_IS_MAXAGE(mine
))
1485 ospf6_maxage_remove(on
->ospf6_if
->area
->ospf6
);
1486 ospf6_lsdb_remove(mine
, on
->retrans_list
);
1487 ospf6_lsa_delete(his
);
1490 assert(p
== OSPF6_MESSAGE_END(oh
));
1493 static u_char
*recvbuf
= NULL
;
1494 static u_char
*sendbuf
= NULL
;
1495 static unsigned int iobuflen
= 0;
1497 int ospf6_iobuf_size(unsigned int size
)
1499 u_char
*recvnew
, *sendnew
;
1501 if (size
<= iobuflen
)
1504 recvnew
= XMALLOC(MTYPE_OSPF6_MESSAGE
, size
);
1505 sendnew
= XMALLOC(MTYPE_OSPF6_MESSAGE
, size
);
1506 if (recvnew
== NULL
|| sendnew
== NULL
) {
1508 XFREE(MTYPE_OSPF6_MESSAGE
, recvnew
);
1510 XFREE(MTYPE_OSPF6_MESSAGE
, sendnew
);
1511 zlog_debug("Could not allocate I/O buffer of size %d.", size
);
1516 XFREE(MTYPE_OSPF6_MESSAGE
, recvbuf
);
1518 XFREE(MTYPE_OSPF6_MESSAGE
, sendbuf
);
1526 void ospf6_message_terminate(void)
1529 XFREE(MTYPE_OSPF6_MESSAGE
, recvbuf
);
1534 XFREE(MTYPE_OSPF6_MESSAGE
, sendbuf
);
1541 int ospf6_receive(struct thread
*thread
)
1545 char srcname
[64], dstname
[64];
1546 struct in6_addr src
, dst
;
1548 struct iovec iovector
[2];
1549 struct ospf6_interface
*oi
;
1550 struct ospf6_header
*oh
;
1552 /* add next read thread */
1553 sockfd
= THREAD_FD(thread
);
1554 thread_add_read(master
, ospf6_receive
, NULL
, sockfd
, NULL
);
1557 memset(&src
, 0, sizeof(src
));
1558 memset(&dst
, 0, sizeof(dst
));
1560 memset(recvbuf
, 0, iobuflen
);
1561 iovector
[0].iov_base
= recvbuf
;
1562 iovector
[0].iov_len
= iobuflen
;
1563 iovector
[1].iov_base
= NULL
;
1564 iovector
[1].iov_len
= 0;
1566 /* receive message */
1567 len
= ospf6_recvmsg(&src
, &dst
, &ifindex
, iovector
);
1568 if (len
> iobuflen
) {
1569 zlog_err("Excess message read");
1573 oi
= ospf6_interface_lookup_by_ifindex(ifindex
);
1574 if (oi
== NULL
|| oi
->area
== NULL
1575 || CHECK_FLAG(oi
->flag
, OSPF6_INTERFACE_DISABLE
)) {
1576 zlog_debug("Message received on disabled interface");
1579 if (CHECK_FLAG(oi
->flag
, OSPF6_INTERFACE_PASSIVE
)) {
1580 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN
, RECV
))
1581 zlog_debug("%s: Ignore message on passive interface %s",
1582 __func__
, oi
->interface
->name
);
1586 oh
= (struct ospf6_header
*)recvbuf
;
1587 if (ospf6_rxpacket_examin(oi
, oh
, len
) != MSG_OK
)
1590 /* Being here means, that no sizing/alignment issues were detected in
1591 the input packet. This renders the additional checks performed below
1592 and also in the type-specific dispatching functions a dead code,
1593 which can be dismissed in a cleanup-focused review round later. */
1596 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, RECV
)) {
1597 inet_ntop(AF_INET6
, &src
, srcname
, sizeof(srcname
));
1598 inet_ntop(AF_INET6
, &dst
, dstname
, sizeof(dstname
));
1599 zlog_debug("%s received on %s",
1600 lookup_msg(ospf6_message_type_str
, oh
->type
, NULL
),
1601 oi
->interface
->name
);
1602 zlog_debug(" src: %s", srcname
);
1603 zlog_debug(" dst: %s", dstname
);
1606 case OSPF6_MESSAGE_TYPE_HELLO
:
1607 ospf6_hello_print(oh
);
1609 case OSPF6_MESSAGE_TYPE_DBDESC
:
1610 ospf6_dbdesc_print(oh
);
1612 case OSPF6_MESSAGE_TYPE_LSREQ
:
1613 ospf6_lsreq_print(oh
);
1615 case OSPF6_MESSAGE_TYPE_LSUPDATE
:
1616 ospf6_lsupdate_print(oh
);
1618 case OSPF6_MESSAGE_TYPE_LSACK
:
1619 ospf6_lsack_print(oh
);
1627 case OSPF6_MESSAGE_TYPE_HELLO
:
1628 ospf6_hello_recv(&src
, &dst
, oi
, oh
);
1631 case OSPF6_MESSAGE_TYPE_DBDESC
:
1632 ospf6_dbdesc_recv(&src
, &dst
, oi
, oh
);
1635 case OSPF6_MESSAGE_TYPE_LSREQ
:
1636 ospf6_lsreq_recv(&src
, &dst
, oi
, oh
);
1639 case OSPF6_MESSAGE_TYPE_LSUPDATE
:
1640 ospf6_lsupdate_recv(&src
, &dst
, oi
, oh
);
1643 case OSPF6_MESSAGE_TYPE_LSACK
:
1644 ospf6_lsack_recv(&src
, &dst
, oi
, oh
);
1654 static void ospf6_send(struct in6_addr
*src
, struct in6_addr
*dst
,
1655 struct ospf6_interface
*oi
, struct ospf6_header
*oh
)
1658 char srcname
[64], dstname
[64];
1659 struct iovec iovector
[2];
1662 iovector
[0].iov_base
= (caddr_t
)oh
;
1663 iovector
[0].iov_len
= ntohs(oh
->length
);
1664 iovector
[1].iov_base
= NULL
;
1665 iovector
[1].iov_len
= 0;
1667 /* fill OSPF header */
1668 oh
->version
= OSPFV3_VERSION
;
1669 /* message type must be set before */
1670 /* message length must be set before */
1671 oh
->router_id
= oi
->area
->ospf6
->router_id
;
1672 oh
->area_id
= oi
->area
->area_id
;
1673 /* checksum is calculated by kernel */
1674 oh
->instance_id
= oi
->instance_id
;
1678 if (IS_OSPF6_DEBUG_MESSAGE(oh
->type
, SEND
)) {
1679 inet_ntop(AF_INET6
, dst
, dstname
, sizeof(dstname
));
1681 inet_ntop(AF_INET6
, src
, srcname
, sizeof(srcname
));
1683 memset(srcname
, 0, sizeof(srcname
));
1684 zlog_debug("%s send on %s",
1685 lookup_msg(ospf6_message_type_str
, oh
->type
, NULL
),
1686 oi
->interface
->name
);
1687 zlog_debug(" src: %s", srcname
);
1688 zlog_debug(" dst: %s", dstname
);
1691 case OSPF6_MESSAGE_TYPE_HELLO
:
1692 ospf6_hello_print(oh
);
1694 case OSPF6_MESSAGE_TYPE_DBDESC
:
1695 ospf6_dbdesc_print(oh
);
1697 case OSPF6_MESSAGE_TYPE_LSREQ
:
1698 ospf6_lsreq_print(oh
);
1700 case OSPF6_MESSAGE_TYPE_LSUPDATE
:
1701 ospf6_lsupdate_print(oh
);
1703 case OSPF6_MESSAGE_TYPE_LSACK
:
1704 ospf6_lsack_print(oh
);
1707 zlog_debug("Unknown message");
1714 len
= ospf6_sendmsg(src
, dst
, &oi
->interface
->ifindex
, iovector
);
1715 if (len
!= ntohs(oh
->length
))
1716 zlog_err("Could not send entire message");
1719 static uint32_t ospf6_packet_max(struct ospf6_interface
*oi
)
1721 assert(oi
->ifmtu
> sizeof(struct ip6_hdr
));
1722 return oi
->ifmtu
- (sizeof(struct ip6_hdr
));
1725 int ospf6_hello_send(struct thread
*thread
)
1727 struct ospf6_interface
*oi
;
1728 struct ospf6_header
*oh
;
1729 struct ospf6_hello
*hello
;
1731 struct listnode
*node
, *nnode
;
1732 struct ospf6_neighbor
*on
;
1734 oi
= (struct ospf6_interface
*)THREAD_ARG(thread
);
1735 oi
->thread_send_hello
= (struct thread
*)NULL
;
1737 if (oi
->state
<= OSPF6_INTERFACE_DOWN
) {
1738 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_HELLO
, SEND
))
1739 zlog_debug("Unable to send Hello on down interface %s",
1740 oi
->interface
->name
);
1744 if (iobuflen
== 0) {
1745 zlog_debug("Unable to send Hello on interface %s iobuflen is 0",
1746 oi
->interface
->name
);
1750 /* set next thread */
1751 thread_add_timer(master
, ospf6_hello_send
, oi
, oi
->hello_interval
,
1752 &oi
->thread_send_hello
);
1754 memset(sendbuf
, 0, iobuflen
);
1755 oh
= (struct ospf6_header
*)sendbuf
;
1756 hello
= (struct ospf6_hello
*)((caddr_t
)oh
1757 + sizeof(struct ospf6_header
));
1759 hello
->interface_id
= htonl(oi
->interface
->ifindex
);
1760 hello
->priority
= oi
->priority
;
1761 hello
->options
[0] = oi
->area
->options
[0];
1762 hello
->options
[1] = oi
->area
->options
[1];
1763 hello
->options
[2] = oi
->area
->options
[2];
1764 hello
->hello_interval
= htons(oi
->hello_interval
);
1765 hello
->dead_interval
= htons(oi
->dead_interval
);
1766 hello
->drouter
= oi
->drouter
;
1767 hello
->bdrouter
= oi
->bdrouter
;
1769 p
= (u_char
*)((caddr_t
)hello
+ sizeof(struct ospf6_hello
));
1771 for (ALL_LIST_ELEMENTS(oi
->neighbor_list
, node
, nnode
, on
)) {
1772 if (on
->state
< OSPF6_NEIGHBOR_INIT
)
1775 if (p
- sendbuf
+ sizeof(u_int32_t
) > ospf6_packet_max(oi
)) {
1776 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_HELLO
,
1779 "sending Hello message: exceeds I/F MTU");
1783 memcpy(p
, &on
->router_id
, sizeof(u_int32_t
));
1784 p
+= sizeof(u_int32_t
);
1787 oh
->type
= OSPF6_MESSAGE_TYPE_HELLO
;
1788 oh
->length
= htons(p
- sendbuf
);
1792 ospf6_send(oi
->linklocal_addr
, &allspfrouters6
, oi
, oh
);
1796 int ospf6_dbdesc_send(struct thread
*thread
)
1798 struct ospf6_neighbor
*on
;
1799 struct ospf6_header
*oh
;
1800 struct ospf6_dbdesc
*dbdesc
;
1802 struct ospf6_lsa
*lsa
;
1803 struct in6_addr
*dst
;
1805 on
= (struct ospf6_neighbor
*)THREAD_ARG(thread
);
1806 on
->thread_send_dbdesc
= (struct thread
*)NULL
;
1808 if (on
->state
< OSPF6_NEIGHBOR_EXSTART
) {
1809 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_DBDESC
, SEND
))
1811 "Quit to send DbDesc to neighbor %s state %s",
1812 on
->name
, ospf6_neighbor_state_str
[on
->state
]);
1816 /* set next thread if master */
1817 if (CHECK_FLAG(on
->dbdesc_bits
, OSPF6_DBDESC_MSBIT
))
1818 thread_add_timer(master
, ospf6_dbdesc_send
, on
,
1819 on
->ospf6_if
->rxmt_interval
,
1820 &on
->thread_send_dbdesc
);
1822 memset(sendbuf
, 0, iobuflen
);
1823 oh
= (struct ospf6_header
*)sendbuf
;
1824 dbdesc
= (struct ospf6_dbdesc
*)((caddr_t
)oh
1825 + sizeof(struct ospf6_header
));
1827 /* if this is initial one, initialize sequence number for DbDesc */
1828 if (CHECK_FLAG(on
->dbdesc_bits
, OSPF6_DBDESC_IBIT
)
1829 && (on
->dbdesc_seqnum
== 0)) {
1830 on
->dbdesc_seqnum
= monotime(NULL
);
1833 dbdesc
->options
[0] = on
->ospf6_if
->area
->options
[0];
1834 dbdesc
->options
[1] = on
->ospf6_if
->area
->options
[1];
1835 dbdesc
->options
[2] = on
->ospf6_if
->area
->options
[2];
1836 dbdesc
->ifmtu
= htons(on
->ospf6_if
->ifmtu
);
1837 dbdesc
->bits
= on
->dbdesc_bits
;
1838 dbdesc
->seqnum
= htonl(on
->dbdesc_seqnum
);
1840 /* if this is not initial one, set LSA headers in dbdesc */
1841 p
= (u_char
*)((caddr_t
)dbdesc
+ sizeof(struct ospf6_dbdesc
));
1842 if (!CHECK_FLAG(on
->dbdesc_bits
, OSPF6_DBDESC_IBIT
)) {
1843 for (ALL_LSDB(on
->dbdesc_list
, lsa
)) {
1844 ospf6_lsa_age_update_to_send(lsa
,
1845 on
->ospf6_if
->transdelay
);
1848 if (p
- sendbuf
+ sizeof(struct ospf6_lsa_header
)
1849 > ospf6_packet_max(on
->ospf6_if
)) {
1850 ospf6_lsdb_lsa_unlock(lsa
);
1853 memcpy(p
, lsa
->header
, sizeof(struct ospf6_lsa_header
));
1854 p
+= sizeof(struct ospf6_lsa_header
);
1858 oh
->type
= OSPF6_MESSAGE_TYPE_DBDESC
;
1859 oh
->length
= htons(p
- sendbuf
);
1862 if (on
->ospf6_if
->state
== OSPF6_INTERFACE_POINTTOPOINT
)
1863 dst
= &allspfrouters6
;
1865 dst
= &on
->linklocal_addr
;
1867 on
->ospf6_if
->db_desc_out
++;
1869 ospf6_send(on
->ospf6_if
->linklocal_addr
, dst
, on
->ospf6_if
, oh
);
1874 int ospf6_dbdesc_send_newone(struct thread
*thread
)
1876 struct ospf6_neighbor
*on
;
1877 struct ospf6_lsa
*lsa
;
1878 unsigned int size
= 0;
1880 on
= (struct ospf6_neighbor
*)THREAD_ARG(thread
);
1881 ospf6_lsdb_remove_all(on
->dbdesc_list
);
1883 /* move LSAs from summary_list to dbdesc_list (within neighbor
1885 so that ospf6_send_dbdesc () can send those LSAs */
1886 size
= sizeof(struct ospf6_lsa_header
) + sizeof(struct ospf6_dbdesc
);
1887 for (ALL_LSDB(on
->summary_list
, lsa
)) {
1888 if (size
+ sizeof(struct ospf6_lsa_header
)
1889 > ospf6_packet_max(on
->ospf6_if
)) {
1890 ospf6_lsdb_lsa_unlock(lsa
);
1894 ospf6_lsdb_add(ospf6_lsa_copy(lsa
), on
->dbdesc_list
);
1895 ospf6_lsdb_remove(lsa
, on
->summary_list
);
1896 size
+= sizeof(struct ospf6_lsa_header
);
1899 if (on
->summary_list
->count
== 0)
1900 UNSET_FLAG(on
->dbdesc_bits
, OSPF6_DBDESC_MBIT
);
1902 /* If slave, More bit check must be done here */
1903 if (!CHECK_FLAG(on
->dbdesc_bits
, OSPF6_DBDESC_MSBIT
) && /* Slave */
1904 !CHECK_FLAG(on
->dbdesc_last
.bits
, OSPF6_DBDESC_MBIT
)
1905 && !CHECK_FLAG(on
->dbdesc_bits
, OSPF6_DBDESC_MBIT
))
1906 thread_add_event(master
, exchange_done
, on
, 0, NULL
);
1908 thread_execute(master
, ospf6_dbdesc_send
, on
, 0);
1912 int ospf6_lsreq_send(struct thread
*thread
)
1914 struct ospf6_neighbor
*on
;
1915 struct ospf6_header
*oh
;
1916 struct ospf6_lsreq_entry
*e
;
1918 struct ospf6_lsa
*lsa
, *last_req
;
1920 on
= (struct ospf6_neighbor
*)THREAD_ARG(thread
);
1921 on
->thread_send_lsreq
= (struct thread
*)NULL
;
1923 /* LSReq will be sent only in ExStart or Loading */
1924 if (on
->state
!= OSPF6_NEIGHBOR_EXCHANGE
1925 && on
->state
!= OSPF6_NEIGHBOR_LOADING
) {
1926 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_LSREQ
, SEND
))
1927 zlog_debug("Quit to send LSReq to neighbor %s state %s",
1929 ospf6_neighbor_state_str
[on
->state
]);
1933 /* schedule loading_done if request list is empty */
1934 if (on
->request_list
->count
== 0) {
1935 thread_add_event(master
, loading_done
, on
, 0, NULL
);
1939 memset(sendbuf
, 0, iobuflen
);
1940 oh
= (struct ospf6_header
*)sendbuf
;
1943 /* set Request entries in lsreq */
1944 p
= (u_char
*)((caddr_t
)oh
+ sizeof(struct ospf6_header
));
1945 for (ALL_LSDB(on
->request_list
, lsa
)) {
1947 if (p
- sendbuf
+ sizeof(struct ospf6_lsreq_entry
)
1948 > ospf6_packet_max(on
->ospf6_if
)) {
1949 ospf6_lsdb_lsa_unlock(lsa
);
1953 e
= (struct ospf6_lsreq_entry
*)p
;
1954 e
->type
= lsa
->header
->type
;
1955 e
->id
= lsa
->header
->id
;
1956 e
->adv_router
= lsa
->header
->adv_router
;
1957 p
+= sizeof(struct ospf6_lsreq_entry
);
1961 if (last_req
!= NULL
) {
1962 if (on
->last_ls_req
!= NULL
) {
1963 ospf6_lsa_unlock(on
->last_ls_req
);
1965 ospf6_lsa_lock(last_req
);
1966 on
->last_ls_req
= last_req
;
1969 oh
->type
= OSPF6_MESSAGE_TYPE_LSREQ
;
1970 oh
->length
= htons(p
- sendbuf
);
1972 on
->ospf6_if
->ls_req_out
++;
1974 if (on
->ospf6_if
->state
== OSPF6_INTERFACE_POINTTOPOINT
)
1975 ospf6_send(on
->ospf6_if
->linklocal_addr
, &allspfrouters6
,
1978 ospf6_send(on
->ospf6_if
->linklocal_addr
, &on
->linklocal_addr
,
1981 /* set next thread */
1982 if (on
->request_list
->count
!= 0) {
1983 on
->thread_send_lsreq
= NULL
;
1984 thread_add_timer(master
, ospf6_lsreq_send
, on
,
1985 on
->ospf6_if
->rxmt_interval
,
1986 &on
->thread_send_lsreq
);
1992 static void ospf6_send_lsupdate(struct ospf6_neighbor
*on
,
1993 struct ospf6_interface
*oi
,
1994 struct ospf6_header
*oh
)
1998 on
->ospf6_if
->ls_upd_out
++;
2000 if ((on
->ospf6_if
->state
== OSPF6_INTERFACE_POINTTOPOINT
) ||
2001 (on
->ospf6_if
->state
== OSPF6_INTERFACE_DR
) ||
2002 (on
->ospf6_if
->state
== OSPF6_INTERFACE_BDR
)) {
2003 ospf6_send(on
->ospf6_if
->linklocal_addr
,
2004 &allspfrouters6
, on
->ospf6_if
, oh
);
2006 ospf6_send(on
->ospf6_if
->linklocal_addr
,
2007 &on
->linklocal_addr
, on
->ospf6_if
, oh
);
2013 if ((oi
->state
== OSPF6_INTERFACE_POINTTOPOINT
) ||
2014 (oi
->state
== OSPF6_INTERFACE_DR
) ||
2015 (oi
->state
== OSPF6_INTERFACE_BDR
)) {
2016 ospf6_send(oi
->linklocal_addr
, &allspfrouters6
, oi
, oh
);
2018 ospf6_send(oi
->linklocal_addr
, &alldrouters6
, oi
, oh
);
2023 int ospf6_lsupdate_send_neighbor(struct thread
*thread
)
2025 struct ospf6_neighbor
*on
;
2026 struct ospf6_header
*oh
;
2027 struct ospf6_lsupdate
*lsupdate
;
2030 struct ospf6_lsa
*lsa
;
2032 on
= (struct ospf6_neighbor
*)THREAD_ARG(thread
);
2033 on
->thread_send_lsupdate
= (struct thread
*)NULL
;
2035 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_LSUPDATE
, SEND
))
2036 zlog_debug("LSUpdate to neighbor %s", on
->name
);
2038 if (on
->state
< OSPF6_NEIGHBOR_EXCHANGE
) {
2039 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_LSUPDATE
, SEND
))
2040 zlog_debug("Quit to send (neighbor state %s)",
2041 ospf6_neighbor_state_str
[on
->state
]);
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
+ sizeof(struct ospf6_lsupdate
));
2053 /* lsupdate_list lists those LSA which doesn't need to be
2054 retransmitted. remove those from the list */
2055 for (ALL_LSDB(on
->lsupdate_list
, lsa
)) {
2057 if ((p
- sendbuf
+ (unsigned int)OSPF6_LSA_SIZE(lsa
->header
))
2058 > ospf6_packet_max(on
->ospf6_if
)) {
2060 oh
->type
= OSPF6_MESSAGE_TYPE_LSUPDATE
;
2061 oh
->length
= htons(p
- sendbuf
);
2062 lsupdate
->lsa_number
= htonl(lsa_cnt
);
2064 ospf6_send_lsupdate(on
, NULL
, oh
);
2066 memset(sendbuf
, 0, iobuflen
);
2067 oh
= (struct ospf6_header
*)sendbuf
;
2068 lsupdate
= (struct ospf6_lsupdate
*)((caddr_t
)oh
2069 + sizeof(struct ospf6_header
));
2071 p
= (u_char
*)((caddr_t
)lsupdate
2072 + sizeof(struct ospf6_lsupdate
));
2077 ospf6_lsa_age_update_to_send(lsa
, on
->ospf6_if
->transdelay
);
2078 memcpy(p
, lsa
->header
, OSPF6_LSA_SIZE(lsa
->header
));
2079 p
+= OSPF6_LSA_SIZE(lsa
->header
);
2082 assert(lsa
->lock
== 2);
2083 ospf6_lsdb_remove(lsa
, on
->lsupdate_list
);
2087 oh
->type
= OSPF6_MESSAGE_TYPE_LSUPDATE
;
2088 oh
->length
= htons(p
- sendbuf
);
2089 lsupdate
->lsa_number
= htonl(lsa_cnt
);
2090 ospf6_send_lsupdate(on
, NULL
, oh
);
2093 /* The addresses used for retransmissions are different from those sent
2095 first time and so we need to separate them here.
2097 memset(sendbuf
, 0, iobuflen
);
2098 oh
= (struct ospf6_header
*)sendbuf
;
2099 lsupdate
= (struct ospf6_lsupdate
*)((caddr_t
)oh
2100 + sizeof(struct ospf6_header
));
2101 p
= (u_char
*)((caddr_t
)lsupdate
+ sizeof(struct ospf6_lsupdate
));
2104 for (ALL_LSDB(on
->retrans_list
, lsa
)) {
2106 if ((p
- sendbuf
+ (unsigned int)OSPF6_LSA_SIZE(lsa
->header
))
2107 > ospf6_packet_max(on
->ospf6_if
)) {
2109 oh
->type
= OSPF6_MESSAGE_TYPE_LSUPDATE
;
2110 oh
->length
= htons(p
- sendbuf
);
2111 lsupdate
->lsa_number
= htonl(lsa_cnt
);
2113 if (on
->ospf6_if
->state
==
2114 OSPF6_INTERFACE_POINTTOPOINT
) {
2115 ospf6_send(on
->ospf6_if
->linklocal_addr
,
2119 ospf6_send(on
->ospf6_if
->linklocal_addr
,
2120 &on
->linklocal_addr
,
2124 memset(sendbuf
, 0, iobuflen
);
2125 oh
= (struct ospf6_header
*)sendbuf
;
2126 lsupdate
= (struct ospf6_lsupdate
*)((caddr_t
)oh
2127 + sizeof(struct ospf6_header
));
2128 p
= (u_char
*)((caddr_t
)lsupdate
+
2129 sizeof(struct ospf6_lsupdate
));
2134 ospf6_lsa_age_update_to_send(lsa
, on
->ospf6_if
->transdelay
);
2135 memcpy(p
, lsa
->header
, OSPF6_LSA_SIZE(lsa
->header
));
2136 p
+= OSPF6_LSA_SIZE(lsa
->header
);
2141 oh
->type
= OSPF6_MESSAGE_TYPE_LSUPDATE
;
2142 oh
->length
= htons(p
- sendbuf
);
2143 lsupdate
->lsa_number
= htonl(lsa_cnt
);
2145 if (on
->ospf6_if
->state
== OSPF6_INTERFACE_POINTTOPOINT
)
2146 ospf6_send(on
->ospf6_if
->linklocal_addr
,
2147 &allspfrouters6
, on
->ospf6_if
, oh
);
2149 ospf6_send(on
->ospf6_if
->linklocal_addr
,
2150 &on
->linklocal_addr
, on
->ospf6_if
, oh
);
2153 if (on
->lsupdate_list
->count
!= 0) {
2154 on
->thread_send_lsupdate
= NULL
;
2155 thread_add_event(master
, ospf6_lsupdate_send_neighbor
, on
, 0,
2156 &on
->thread_send_lsupdate
);
2157 } else if (on
->retrans_list
->count
!= 0) {
2158 on
->thread_send_lsupdate
= NULL
;
2159 thread_add_timer(master
, ospf6_lsupdate_send_neighbor
, on
,
2160 on
->ospf6_if
->rxmt_interval
,
2161 &on
->thread_send_lsupdate
);
2166 int ospf6_lsupdate_send_neighbor_now(struct ospf6_neighbor
*on
,
2167 struct ospf6_lsa
*lsa
)
2169 struct ospf6_header
*oh
;
2170 struct ospf6_lsupdate
*lsupdate
;
2174 memset(sendbuf
, 0, iobuflen
);
2175 oh
= (struct ospf6_header
*)sendbuf
;
2176 lsupdate
= (struct ospf6_lsupdate
*)((caddr_t
)oh
2177 + sizeof(struct ospf6_header
));
2179 p
= (u_char
*)((caddr_t
)lsupdate
+ sizeof(struct ospf6_lsupdate
));
2180 ospf6_lsa_age_update_to_send(lsa
, on
->ospf6_if
->transdelay
);
2181 memcpy(p
, lsa
->header
, OSPF6_LSA_SIZE(lsa
->header
));
2182 p
+= OSPF6_LSA_SIZE(lsa
->header
);
2185 oh
->type
= OSPF6_MESSAGE_TYPE_LSUPDATE
;
2186 oh
->length
= htons(p
- sendbuf
);
2187 lsupdate
->lsa_number
= htonl(lsa_cnt
);
2189 if (IS_OSPF6_DEBUG_FLOODING
||
2190 IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_LSUPDATE
, SEND
))
2191 zlog_debug("%s: Send lsupdate with lsa %s (age %u)",
2192 __PRETTY_FUNCTION__
, lsa
->name
,
2193 ntohs(lsa
->header
->age
));
2195 ospf6_send_lsupdate(on
, NULL
, oh
);
2200 int ospf6_lsupdate_send_interface(struct thread
*thread
)
2202 struct ospf6_interface
*oi
;
2203 struct ospf6_header
*oh
;
2204 struct ospf6_lsupdate
*lsupdate
;
2207 struct ospf6_lsa
*lsa
;
2209 oi
= (struct ospf6_interface
*)THREAD_ARG(thread
);
2210 oi
->thread_send_lsupdate
= (struct thread
*)NULL
;
2212 if (oi
->state
<= OSPF6_INTERFACE_WAITING
) {
2213 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_LSUPDATE
, SEND
))
2215 "Quit to send LSUpdate to interface %s state %s",
2216 oi
->interface
->name
,
2217 ospf6_interface_state_str
[oi
->state
]);
2221 /* if we have nothing to send, return */
2222 if (oi
->lsupdate_list
->count
== 0)
2225 memset(sendbuf
, 0, iobuflen
);
2226 oh
= (struct ospf6_header
*)sendbuf
;
2227 lsupdate
= (struct ospf6_lsupdate
*)((caddr_t
)oh
2228 + sizeof(struct ospf6_header
));
2230 p
= (u_char
*)((caddr_t
)lsupdate
+ sizeof(struct ospf6_lsupdate
));
2233 for (ALL_LSDB(oi
->lsupdate_list
, lsa
)) {
2235 if ((p
- sendbuf
+ ((unsigned int)OSPF6_LSA_SIZE(lsa
->header
)))
2236 > ospf6_packet_max(oi
)) {
2238 oh
->type
= OSPF6_MESSAGE_TYPE_LSUPDATE
;
2239 oh
->length
= htons(p
- sendbuf
);
2240 lsupdate
->lsa_number
= htonl(lsa_cnt
);
2242 ospf6_send_lsupdate(NULL
, oi
, oh
);
2243 if (IS_OSPF6_DEBUG_MESSAGE(
2244 OSPF6_MESSAGE_TYPE_LSUPDATE
, SEND
))
2245 zlog_debug("%s: LSUpdate length %d",
2246 __PRETTY_FUNCTION__
,
2249 memset(sendbuf
, 0, iobuflen
);
2250 oh
= (struct ospf6_header
*)sendbuf
;
2251 lsupdate
= (struct ospf6_lsupdate
*)((caddr_t
)oh
2252 + sizeof(struct ospf6_header
));
2254 p
= (u_char
*)((caddr_t
)lsupdate
2255 + sizeof(struct ospf6_lsupdate
));
2260 ospf6_lsa_age_update_to_send(lsa
, oi
->transdelay
);
2261 memcpy(p
, lsa
->header
, OSPF6_LSA_SIZE(lsa
->header
));
2262 p
+= OSPF6_LSA_SIZE(lsa
->header
);
2265 assert(lsa
->lock
== 2);
2266 ospf6_lsdb_remove(lsa
, oi
->lsupdate_list
);
2270 oh
->type
= OSPF6_MESSAGE_TYPE_LSUPDATE
;
2271 oh
->length
= htons(p
- sendbuf
);
2272 lsupdate
->lsa_number
= htonl(lsa_cnt
);
2274 ospf6_send_lsupdate(NULL
, oi
, oh
);
2277 if (oi
->lsupdate_list
->count
> 0) {
2278 oi
->thread_send_lsupdate
= NULL
;
2279 thread_add_event(master
, ospf6_lsupdate_send_interface
, oi
, 0,
2280 &oi
->thread_send_lsupdate
);
2286 int ospf6_lsack_send_neighbor(struct thread
*thread
)
2288 struct ospf6_neighbor
*on
;
2289 struct ospf6_header
*oh
;
2291 struct ospf6_lsa
*lsa
;
2294 on
= (struct ospf6_neighbor
*)THREAD_ARG(thread
);
2295 on
->thread_send_lsack
= (struct thread
*)NULL
;
2297 if (on
->state
< OSPF6_NEIGHBOR_EXCHANGE
) {
2298 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_LSACK
, SEND
))
2299 zlog_debug("Quit to send LSAck to neighbor %s state %s",
2301 ospf6_neighbor_state_str
[on
->state
]);
2305 /* if we have nothing to send, return */
2306 if (on
->lsack_list
->count
== 0)
2309 memset(sendbuf
, 0, iobuflen
);
2310 oh
= (struct ospf6_header
*)sendbuf
;
2312 p
= (u_char
*)((caddr_t
)oh
+ sizeof(struct ospf6_header
));
2314 for (ALL_LSDB(on
->lsack_list
, lsa
)) {
2316 if (p
- sendbuf
+ sizeof(struct ospf6_lsa_header
)
2317 > ospf6_packet_max(on
->ospf6_if
)) {
2318 /* if we run out of packet size/space here,
2319 better to try again soon. */
2321 oh
->type
= OSPF6_MESSAGE_TYPE_LSACK
;
2322 oh
->length
= htons(p
- sendbuf
);
2324 on
->ospf6_if
->ls_ack_out
++;
2326 ospf6_send(on
->ospf6_if
->linklocal_addr
,
2327 &on
->linklocal_addr
,
2330 memset(sendbuf
, 0, iobuflen
);
2331 oh
= (struct ospf6_header
*)sendbuf
;
2332 p
= (u_char
*)((caddr_t
)oh
+
2333 sizeof(struct ospf6_header
));
2338 ospf6_lsa_age_update_to_send(lsa
, on
->ospf6_if
->transdelay
);
2339 memcpy(p
, lsa
->header
, sizeof(struct ospf6_lsa_header
));
2340 p
+= sizeof(struct ospf6_lsa_header
);
2342 assert(lsa
->lock
== 2);
2343 ospf6_lsdb_remove(lsa
, on
->lsack_list
);
2348 oh
->type
= OSPF6_MESSAGE_TYPE_LSACK
;
2349 oh
->length
= htons(p
- sendbuf
);
2351 on
->ospf6_if
->ls_ack_out
++;
2353 ospf6_send(on
->ospf6_if
->linklocal_addr
, &on
->linklocal_addr
,
2357 if (on
->lsack_list
->count
> 0)
2358 thread_add_event(master
, ospf6_lsack_send_neighbor
, on
, 0,
2359 &on
->thread_send_lsack
);
2364 int ospf6_lsack_send_interface(struct thread
*thread
)
2366 struct ospf6_interface
*oi
;
2367 struct ospf6_header
*oh
;
2369 struct ospf6_lsa
*lsa
;
2372 oi
= (struct ospf6_interface
*)THREAD_ARG(thread
);
2373 oi
->thread_send_lsack
= (struct thread
*)NULL
;
2375 if (oi
->state
<= OSPF6_INTERFACE_WAITING
) {
2376 if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_LSACK
, SEND
))
2378 "Quit to send LSAck to interface %s state %s",
2379 oi
->interface
->name
,
2380 ospf6_interface_state_str
[oi
->state
]);
2384 /* if we have nothing to send, return */
2385 if (oi
->lsack_list
->count
== 0)
2388 memset(sendbuf
, 0, iobuflen
);
2389 oh
= (struct ospf6_header
*)sendbuf
;
2391 p
= (u_char
*)((caddr_t
)oh
+ sizeof(struct ospf6_header
));
2393 for (ALL_LSDB(oi
->lsack_list
, lsa
)) {
2395 if (p
- sendbuf
+ sizeof(struct ospf6_lsa_header
)
2396 > ospf6_packet_max(oi
)) {
2397 /* if we run out of packet size/space here,
2398 better to try again soon. */
2399 THREAD_OFF(oi
->thread_send_lsack
);
2400 thread_add_event(master
, ospf6_lsack_send_interface
, oi
,
2401 0, &oi
->thread_send_lsack
);
2403 ospf6_lsdb_lsa_unlock(lsa
);
2407 ospf6_lsa_age_update_to_send(lsa
, oi
->transdelay
);
2408 memcpy(p
, lsa
->header
, sizeof(struct ospf6_lsa_header
));
2409 p
+= sizeof(struct ospf6_lsa_header
);
2411 assert(lsa
->lock
== 2);
2412 ospf6_lsdb_remove(lsa
, oi
->lsack_list
);
2417 oh
->type
= OSPF6_MESSAGE_TYPE_LSACK
;
2418 oh
->length
= htons(p
- sendbuf
);
2420 if ((oi
->state
== OSPF6_INTERFACE_POINTTOPOINT
)
2421 || (oi
->state
== OSPF6_INTERFACE_DR
)
2422 || (oi
->state
== OSPF6_INTERFACE_BDR
))
2423 ospf6_send(oi
->linklocal_addr
, &allspfrouters6
, oi
, oh
);
2425 ospf6_send(oi
->linklocal_addr
, &alldrouters6
, oi
, oh
);
2428 if (oi
->lsack_list
->count
> 0)
2429 thread_add_event(master
, ospf6_lsack_send_interface
, oi
, 0,
2430 &oi
->thread_send_lsack
);
2437 DEFUN (debug_ospf6_message
,
2438 debug_ospf6_message_cmd
,
2439 "debug ospf6 message <unknown|hello|dbdesc|lsreq|lsupdate|lsack|all> [<send|recv>]",
2442 "Debug OSPFv3 message\n"
2443 "Debug Unknown message\n"
2444 "Debug Hello message\n"
2445 "Debug Database Description message\n"
2446 "Debug Link State Request message\n"
2447 "Debug Link State Update message\n"
2448 "Debug Link State Acknowledgement message\n"
2449 "Debug All message\n"
2450 "Debug only sending message\n"
2451 "Debug only receiving message\n")
2454 int idx_send_recv
= 4;
2455 unsigned char level
= 0;
2460 if (!strncmp(argv
[idx_packet
]->arg
, "u", 1))
2461 type
= OSPF6_MESSAGE_TYPE_UNKNOWN
;
2462 else if (!strncmp(argv
[idx_packet
]->arg
, "h", 1))
2463 type
= OSPF6_MESSAGE_TYPE_HELLO
;
2464 else if (!strncmp(argv
[idx_packet
]->arg
, "d", 1))
2465 type
= OSPF6_MESSAGE_TYPE_DBDESC
;
2466 else if (!strncmp(argv
[idx_packet
]->arg
, "lsr", 3))
2467 type
= OSPF6_MESSAGE_TYPE_LSREQ
;
2468 else if (!strncmp(argv
[idx_packet
]->arg
, "lsu", 3))
2469 type
= OSPF6_MESSAGE_TYPE_LSUPDATE
;
2470 else if (!strncmp(argv
[idx_packet
]->arg
, "lsa", 3))
2471 type
= OSPF6_MESSAGE_TYPE_LSACK
;
2472 else if (!strncmp(argv
[idx_packet
]->arg
, "a", 1))
2473 type
= OSPF6_MESSAGE_TYPE_ALL
;
2476 level
= OSPF6_DEBUG_MESSAGE_SEND
| OSPF6_DEBUG_MESSAGE_RECV
;
2477 else if (!strncmp(argv
[idx_send_recv
]->arg
, "s", 1))
2478 level
= OSPF6_DEBUG_MESSAGE_SEND
;
2479 else if (!strncmp(argv
[idx_send_recv
]->arg
, "r", 1))
2480 level
= OSPF6_DEBUG_MESSAGE_RECV
;
2482 if (type
== OSPF6_MESSAGE_TYPE_ALL
) {
2483 for (i
= 0; i
< 6; i
++)
2484 OSPF6_DEBUG_MESSAGE_ON(i
, level
);
2486 OSPF6_DEBUG_MESSAGE_ON(type
, level
);
2491 DEFUN (no_debug_ospf6_message
,
2492 no_debug_ospf6_message_cmd
,
2493 "no debug ospf6 message <unknown|hello|dbdesc|lsreq|lsupdate|lsack|all> [<send|recv>]",
2497 "Debug OSPFv3 message\n"
2498 "Debug Unknown message\n"
2499 "Debug Hello message\n"
2500 "Debug Database Description message\n"
2501 "Debug Link State Request message\n"
2502 "Debug Link State Update message\n"
2503 "Debug Link State Acknowledgement message\n"
2504 "Debug All message\n"
2505 "Debug only sending message\n"
2506 "Debug only receiving message\n")
2509 int idx_send_recv
= 5;
2510 unsigned char level
= 0;
2515 if (!strncmp(argv
[idx_packet
]->arg
, "u", 1))
2516 type
= OSPF6_MESSAGE_TYPE_UNKNOWN
;
2517 else if (!strncmp(argv
[idx_packet
]->arg
, "h", 1))
2518 type
= OSPF6_MESSAGE_TYPE_HELLO
;
2519 else if (!strncmp(argv
[idx_packet
]->arg
, "d", 1))
2520 type
= OSPF6_MESSAGE_TYPE_DBDESC
;
2521 else if (!strncmp(argv
[idx_packet
]->arg
, "lsr", 3))
2522 type
= OSPF6_MESSAGE_TYPE_LSREQ
;
2523 else if (!strncmp(argv
[idx_packet
]->arg
, "lsu", 3))
2524 type
= OSPF6_MESSAGE_TYPE_LSUPDATE
;
2525 else if (!strncmp(argv
[idx_packet
]->arg
, "lsa", 3))
2526 type
= OSPF6_MESSAGE_TYPE_LSACK
;
2527 else if (!strncmp(argv
[idx_packet
]->arg
, "a", 1))
2528 type
= OSPF6_MESSAGE_TYPE_ALL
;
2531 level
= OSPF6_DEBUG_MESSAGE_SEND
| OSPF6_DEBUG_MESSAGE_RECV
;
2532 else if (!strncmp(argv
[idx_send_recv
]->arg
, "s", 1))
2533 level
= OSPF6_DEBUG_MESSAGE_SEND
;
2534 else if (!strncmp(argv
[idx_send_recv
]->arg
, "r", 1))
2535 level
= OSPF6_DEBUG_MESSAGE_RECV
;
2537 if (type
== OSPF6_MESSAGE_TYPE_ALL
) {
2538 for (i
= 0; i
< 6; i
++)
2539 OSPF6_DEBUG_MESSAGE_OFF(i
, level
);
2541 OSPF6_DEBUG_MESSAGE_OFF(type
, level
);
2547 int config_write_ospf6_debug_message(struct vty
*vty
)
2549 const char *type_str
[] = {"unknown", "hello", "dbdesc",
2550 "lsreq", "lsupdate", "lsack"};
2551 unsigned char s
= 0, r
= 0;
2554 for (i
= 0; i
< 6; i
++) {
2555 if (IS_OSPF6_DEBUG_MESSAGE(i
, SEND
))
2557 if (IS_OSPF6_DEBUG_MESSAGE(i
, RECV
))
2561 if (s
== 0x3f && r
== 0x3f) {
2562 vty_out(vty
, "debug ospf6 message all\n");
2566 if (s
== 0x3f && r
== 0) {
2567 vty_out(vty
, "debug ospf6 message all send\n");
2569 } else if (s
== 0 && r
== 0x3f) {
2570 vty_out(vty
, "debug ospf6 message all recv\n");
2574 /* Unknown message is logged by default */
2575 if (!IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN
, SEND
)
2576 && !IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN
, RECV
))
2577 vty_out(vty
, "no debug ospf6 message unknown\n");
2578 else if (!IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN
, SEND
))
2579 vty_out(vty
, "no debug ospf6 message unknown send\n");
2580 else if (!IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN
, RECV
))
2581 vty_out(vty
, "no debug ospf6 message unknown recv\n");
2583 for (i
= 1; i
< 6; i
++) {
2584 if (IS_OSPF6_DEBUG_MESSAGE(i
, SEND
)
2585 && IS_OSPF6_DEBUG_MESSAGE(i
, RECV
))
2586 vty_out(vty
, "debug ospf6 message %s\n", type_str
[i
]);
2587 else if (IS_OSPF6_DEBUG_MESSAGE(i
, SEND
))
2588 vty_out(vty
, "debug ospf6 message %s send\n",
2590 else if (IS_OSPF6_DEBUG_MESSAGE(i
, RECV
))
2591 vty_out(vty
, "debug ospf6 message %s recv\n",
2598 void install_element_ospf6_debug_message(void)
2600 install_element(ENABLE_NODE
, &debug_ospf6_message_cmd
);
2601 install_element(ENABLE_NODE
, &no_debug_ospf6_message_cmd
);
2602 install_element(CONFIG_NODE
, &debug_ospf6_message_cmd
);
2603 install_element(CONFIG_NODE
, &no_debug_ospf6_message_cmd
);