]> git.proxmox.com Git - mirror_frr.git/blame - ospf6d/ospf6_message.c
*: add indent control files
[mirror_frr.git] / ospf6d / ospf6_message.c
CommitLineData
718e3744 1/*
508e53e2 2 * Copyright (C) 2003 Yasuhiro Ohara
718e3744 3 *
4 * This file is part of GNU Zebra.
5 *
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
9 * later version.
10 *
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.
15 *
896014f4
DL
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
718e3744 19 */
20
508e53e2 21#include <zebra.h>
22
3b4cd3a9 23#include "memory.h"
508e53e2 24#include "log.h"
25#include "vty.h"
26#include "command.h"
27#include "thread.h"
28#include "linklist.h"
29
508e53e2 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"
718e3744 35
508e53e2 36#include "ospf6_top.h"
37#include "ospf6_area.h"
38#include "ospf6_neighbor.h"
39#include "ospf6_interface.h"
718e3744 40
abc7ef44
DO
41/* for structures and macros ospf6_lsa_examin() needs */
42#include "ospf6_abr.h"
43#include "ospf6_asbr.h"
44#include "ospf6_intra.h"
45
508e53e2 46#include "ospf6_flood.h"
049207c3 47#include "ospf6d.h"
718e3744 48
681b84e8
DT
49#include <netinet/ip6.h>
50
508e53e2 51unsigned char conf_debug_ospf6_message[6] = {0x03, 0, 0, 0, 0, 0};
5031ed13
DO
52static const struct message ospf6_message_type_str [] =
53{
54 { OSPF6_MESSAGE_TYPE_HELLO, "Hello" },
55 { OSPF6_MESSAGE_TYPE_DBDESC, "DbDesc" },
56 { OSPF6_MESSAGE_TYPE_LSREQ, "LSReq" },
57 { OSPF6_MESSAGE_TYPE_LSUPDATE, "LSUpdate" },
58 { OSPF6_MESSAGE_TYPE_LSACK, "LSAck" },
56b40679 59 { 0 }
5031ed13 60};
718e3744 61
abc7ef44
DO
62/* Minimum (besides the standard OSPF packet header) lengths for OSPF
63 packets of particular types, offset is the "type" field. */
64const u_int16_t ospf6_packet_minlen[OSPF6_MESSAGE_TYPE_ALL] =
65{
66 0,
67 OSPF6_HELLO_MIN_SIZE,
68 OSPF6_DB_DESC_MIN_SIZE,
69 OSPF6_LS_REQ_MIN_SIZE,
70 OSPF6_LS_UPD_MIN_SIZE,
71 OSPF6_LS_ACK_MIN_SIZE
72};
73
74/* Minimum (besides the standard LSA header) lengths for LSAs of particular
75 types, offset is the "LSA function code" portion of "LSA type" field. */
76const u_int16_t ospf6_lsa_minlen[OSPF6_LSTYPE_SIZE] =
77{
78 0,
79 /* 0x2001 */ OSPF6_ROUTER_LSA_MIN_SIZE,
80 /* 0x2002 */ OSPF6_NETWORK_LSA_MIN_SIZE,
81 /* 0x2003 */ OSPF6_INTER_PREFIX_LSA_MIN_SIZE,
82 /* 0x2004 */ OSPF6_INTER_ROUTER_LSA_FIX_SIZE,
83 /* 0x4005 */ OSPF6_AS_EXTERNAL_LSA_MIN_SIZE,
84 /* 0x2006 */ 0,
85 /* 0x2007 */ OSPF6_AS_EXTERNAL_LSA_MIN_SIZE,
86 /* 0x0008 */ OSPF6_LINK_LSA_MIN_SIZE,
87 /* 0x2009 */ OSPF6_INTRA_PREFIX_LSA_MIN_SIZE
88};
89
508e53e2 90/* print functions */
718e3744 91
92static void
508e53e2 93ospf6_header_print (struct ospf6_header *oh)
718e3744 94{
508e53e2 95 char router_id[16], area_id[16];
96 inet_ntop (AF_INET, &oh->router_id, router_id, sizeof (router_id));
97 inet_ntop (AF_INET, &oh->area_id, area_id, sizeof (area_id));
98
c6487d61 99 zlog_debug (" OSPFv%d Type:%d Len:%hu Router-ID:%s",
508e53e2 100 oh->version, oh->type, ntohs (oh->length), router_id);
c6487d61 101 zlog_debug (" Area-ID:%s Cksum:%hx Instance-ID:%d",
508e53e2 102 area_id, ntohs (oh->checksum), oh->instance_id);
718e3744 103}
104
508e53e2 105void
106ospf6_hello_print (struct ospf6_header *oh)
718e3744 107{
718e3744 108 struct ospf6_hello *hello;
508e53e2 109 char options[16];
110 char drouter[16], bdrouter[16], neighbor[16];
111 char *p;
718e3744 112
508e53e2 113 ospf6_header_print (oh);
114 assert (oh->type == OSPF6_MESSAGE_TYPE_HELLO);
718e3744 115
508e53e2 116 hello = (struct ospf6_hello *)
117 ((caddr_t) oh + sizeof (struct ospf6_header));
718e3744 118
508e53e2 119 inet_ntop (AF_INET, &hello->drouter, drouter, sizeof (drouter));
120 inet_ntop (AF_INET, &hello->bdrouter, bdrouter, sizeof (bdrouter));
121 ospf6_options_printbuf (hello->options, options, sizeof (options));
718e3744 122
c6487d61 123 zlog_debug (" I/F-Id:%ld Priority:%d Option:%s",
508e53e2 124 (u_long) ntohl (hello->interface_id), hello->priority, options);
c6487d61 125 zlog_debug (" HelloInterval:%hu DeadInterval:%hu",
508e53e2 126 ntohs (hello->hello_interval), ntohs (hello->dead_interval));
c6487d61 127 zlog_debug (" DR:%s BDR:%s", drouter, bdrouter);
718e3744 128
508e53e2 129 for (p = (char *) ((caddr_t) hello + sizeof (struct ospf6_hello));
130 p + sizeof (u_int32_t) <= OSPF6_MESSAGE_END (oh);
131 p += sizeof (u_int32_t))
718e3744 132 {
508e53e2 133 inet_ntop (AF_INET, (void *) p, neighbor, sizeof (neighbor));
c6487d61 134 zlog_debug (" Neighbor: %s", neighbor);
718e3744 135 }
508e53e2 136
fa079666 137 assert (p == OSPF6_MESSAGE_END (oh));
718e3744 138}
139
508e53e2 140void
141ospf6_dbdesc_print (struct ospf6_header *oh)
718e3744 142{
718e3744 143 struct ospf6_dbdesc *dbdesc;
508e53e2 144 char options[16];
145 char *p;
146
147 ospf6_header_print (oh);
148 assert (oh->type == OSPF6_MESSAGE_TYPE_DBDESC);
149
150 dbdesc = (struct ospf6_dbdesc *)
151 ((caddr_t) oh + sizeof (struct ospf6_header));
152
153 ospf6_options_printbuf (dbdesc->options, options, sizeof (options));
154
c6487d61 155 zlog_debug (" MBZ: %#x Option: %s IfMTU: %hu",
508e53e2 156 dbdesc->reserved1, options, ntohs (dbdesc->ifmtu));
c6487d61 157 zlog_debug (" MBZ: %#x Bits: %s%s%s SeqNum: %#lx",
508e53e2 158 dbdesc->reserved2,
159 (CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_IBIT) ? "I" : "-"),
160 (CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_MBIT) ? "M" : "-"),
161 (CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_MSBIT) ? "m" : "s"),
162 (u_long) ntohl (dbdesc->seqnum));
163
164 for (p = (char *) ((caddr_t) dbdesc + sizeof (struct ospf6_dbdesc));
165 p + sizeof (struct ospf6_lsa_header) <= OSPF6_MESSAGE_END (oh);
166 p += sizeof (struct ospf6_lsa_header))
167 ospf6_lsa_header_print_raw ((struct ospf6_lsa_header *) p);
168
fa079666 169 assert (p == OSPF6_MESSAGE_END (oh));
718e3744 170}
171
508e53e2 172void
173ospf6_lsreq_print (struct ospf6_header *oh)
718e3744 174{
508e53e2 175 char id[16], adv_router[16];
176 char *p;
718e3744 177
508e53e2 178 ospf6_header_print (oh);
179 assert (oh->type == OSPF6_MESSAGE_TYPE_LSREQ);
718e3744 180
508e53e2 181 for (p = (char *) ((caddr_t) oh + sizeof (struct ospf6_header));
182 p + sizeof (struct ospf6_lsreq_entry) <= OSPF6_MESSAGE_END (oh);
183 p += sizeof (struct ospf6_lsreq_entry))
718e3744 184 {
508e53e2 185 struct ospf6_lsreq_entry *e = (struct ospf6_lsreq_entry *) p;
186 inet_ntop (AF_INET, &e->adv_router, adv_router, sizeof (adv_router));
187 inet_ntop (AF_INET, &e->id, id, sizeof (id));
c6487d61 188 zlog_debug (" [%s Id:%s Adv:%s]",
1e05838a 189 ospf6_lstype_name (e->type), id, adv_router);
718e3744 190 }
508e53e2 191
fa079666 192 assert (p == OSPF6_MESSAGE_END (oh));
718e3744 193}
194
508e53e2 195void
196ospf6_lsupdate_print (struct ospf6_header *oh)
718e3744 197{
718e3744 198 struct ospf6_lsupdate *lsupdate;
508e53e2 199 u_long num;
200 char *p;
718e3744 201
508e53e2 202 ospf6_header_print (oh);
203 assert (oh->type == OSPF6_MESSAGE_TYPE_LSUPDATE);
718e3744 204
508e53e2 205 lsupdate = (struct ospf6_lsupdate *)
206 ((caddr_t) oh + sizeof (struct ospf6_header));
718e3744 207
508e53e2 208 num = ntohl (lsupdate->lsa_number);
c6487d61 209 zlog_debug (" Number of LSA: %ld", num);
718e3744 210
508e53e2 211 for (p = (char *) ((caddr_t) lsupdate + sizeof (struct ospf6_lsupdate));
212 p < OSPF6_MESSAGE_END (oh) &&
213 p + OSPF6_LSA_SIZE (p) <= OSPF6_MESSAGE_END (oh);
214 p += OSPF6_LSA_SIZE (p))
215 {
216 ospf6_lsa_header_print_raw ((struct ospf6_lsa_header *) p);
508e53e2 217 }
718e3744 218
fa079666 219 assert (p == OSPF6_MESSAGE_END (oh));
718e3744 220}
221
508e53e2 222void
223ospf6_lsack_print (struct ospf6_header *oh)
718e3744 224{
508e53e2 225 char *p;
718e3744 226
508e53e2 227 ospf6_header_print (oh);
228 assert (oh->type == OSPF6_MESSAGE_TYPE_LSACK);
718e3744 229
508e53e2 230 for (p = (char *) ((caddr_t) oh + sizeof (struct ospf6_header));
231 p + sizeof (struct ospf6_lsa_header) <= OSPF6_MESSAGE_END (oh);
232 p += sizeof (struct ospf6_lsa_header))
233 ospf6_lsa_header_print_raw ((struct ospf6_lsa_header *) p);
234
fa079666 235 assert (p == OSPF6_MESSAGE_END (oh));
718e3744 236}
237
6ac29a51 238static void
508e53e2 239ospf6_hello_recv (struct in6_addr *src, struct in6_addr *dst,
240 struct ospf6_interface *oi, struct ospf6_header *oh)
718e3744 241{
718e3744 242 struct ospf6_hello *hello;
508e53e2 243 struct ospf6_neighbor *on;
244 char *p;
245 int twoway = 0;
246 int neighborchange = 0;
552237cf 247 int neighbor_ifindex_change = 0;
508e53e2 248 int backupseen = 0;
249
508e53e2 250 hello = (struct ospf6_hello *)
251 ((caddr_t) oh + sizeof (struct ospf6_header));
718e3744 252
253 /* HelloInterval check */
508e53e2 254 if (ntohs (hello->hello_interval) != oi->hello_interval)
718e3744 255 {
508e53e2 256 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
c6487d61 257 zlog_debug ("HelloInterval mismatch");
718e3744 258 return;
259 }
260
261 /* RouterDeadInterval check */
508e53e2 262 if (ntohs (hello->dead_interval) != oi->dead_interval)
718e3744 263 {
508e53e2 264 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
c6487d61 265 zlog_debug ("RouterDeadInterval mismatch");
718e3744 266 return;
267 }
268
508e53e2 269 /* E-bit check */
270 if (OSPF6_OPT_ISSET (hello->options, OSPF6_OPT_E) !=
271 OSPF6_OPT_ISSET (oi->area->options, OSPF6_OPT_E))
718e3744 272 {
508e53e2 273 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
c6487d61 274 zlog_debug ("E-bit mismatch");
718e3744 275 return;
276 }
277
508e53e2 278 /* Find neighbor, create if not exist */
279 on = ospf6_neighbor_lookup (oh->router_id, oi);
280 if (on == NULL)
718e3744 281 {
508e53e2 282 on = ospf6_neighbor_create (oh->router_id, oi);
283 on->prev_drouter = on->drouter = hello->drouter;
284 on->prev_bdrouter = on->bdrouter = hello->bdrouter;
285 on->priority = hello->priority;
718e3744 286 }
287
552237cf 288 /* Always override neighbor's source address */
7b6ae028 289 memcpy (&on->linklocal_addr, src, sizeof (struct in6_addr));
290
552237cf 291 /* Neighbor ifindex check */
b892f1dd 292 if (on->ifindex != (ifindex_t)ntohl (hello->interface_id))
552237cf
DS
293 {
294 on->ifindex = ntohl (hello->interface_id);
295 neighbor_ifindex_change++;
296 }
297
508e53e2 298 /* TwoWay check */
299 for (p = (char *) ((caddr_t) hello + sizeof (struct ospf6_hello));
300 p + sizeof (u_int32_t) <= OSPF6_MESSAGE_END (oh);
301 p += sizeof (u_int32_t))
718e3744 302 {
508e53e2 303 u_int32_t *router_id = (u_int32_t *) p;
304
305 if (*router_id == oi->area->ospf6->router_id)
306 twoway++;
718e3744 307 }
308
fa079666 309 assert (p == OSPF6_MESSAGE_END (oh));
718e3744 310
508e53e2 311 /* RouterPriority check */
312 if (on->priority != hello->priority)
718e3744 313 {
508e53e2 314 on->priority = hello->priority;
315 neighborchange++;
718e3744 316 }
317
508e53e2 318 /* DR check */
319 if (on->drouter != hello->drouter)
320 {
321 on->prev_drouter = on->drouter;
322 on->drouter = hello->drouter;
323 if (on->prev_drouter == on->router_id || on->drouter == on->router_id)
324 neighborchange++;
325 }
718e3744 326
508e53e2 327 /* BDR check */
328 if (on->bdrouter != hello->bdrouter)
718e3744 329 {
508e53e2 330 on->prev_bdrouter = on->bdrouter;
331 on->bdrouter = hello->bdrouter;
332 if (on->prev_bdrouter == on->router_id || on->bdrouter == on->router_id)
333 neighborchange++;
334 }
718e3744 335
508e53e2 336 /* BackupSeen check */
337 if (oi->state == OSPF6_INTERFACE_WAITING)
338 {
339 if (hello->bdrouter == on->router_id)
718e3744 340 backupseen++;
508e53e2 341 else if (hello->drouter == on->router_id && hello->bdrouter == htonl (0))
718e3744 342 backupseen++;
343 }
344
508e53e2 345 /* Execute neighbor events */
346 thread_execute (master, hello_received, on, 0);
347 if (twoway)
348 thread_execute (master, twoway_received, on, 0);
349 else
350 thread_execute (master, oneway_received, on, 0);
718e3744 351
508e53e2 352 /* Schedule interface events */
718e3744 353 if (backupseen)
ffa2c898 354 thread_add_event (master, backup_seen, oi, 0, NULL);
508e53e2 355 if (neighborchange)
ffa2c898 356 thread_add_event (master, neighbor_change, oi, 0, NULL);
552237cf
DS
357
358 if (neighbor_ifindex_change && on->state == OSPF6_NEIGHBOR_FULL)
359 OSPF6_ROUTER_LSA_SCHEDULE (oi->area);
718e3744 360}
361
508e53e2 362static void
363ospf6_dbdesc_recv_master (struct ospf6_header *oh,
364 struct ospf6_neighbor *on)
718e3744 365{
508e53e2 366 struct ospf6_dbdesc *dbdesc;
367 char *p;
718e3744 368
508e53e2 369 dbdesc = (struct ospf6_dbdesc *)
370 ((caddr_t) oh + sizeof (struct ospf6_header));
371
372 if (on->state < OSPF6_NEIGHBOR_INIT)
718e3744 373 {
508e53e2 374 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
c6487d61 375 zlog_debug ("Neighbor state less than Init, ignore");
508e53e2 376 return;
718e3744 377 }
718e3744 378
508e53e2 379 switch (on->state)
380 {
381 case OSPF6_NEIGHBOR_TWOWAY:
382 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
c6487d61 383 zlog_debug ("Neighbor state is 2-Way, ignore");
508e53e2 384 return;
718e3744 385
508e53e2 386 case OSPF6_NEIGHBOR_INIT:
387 thread_execute (master, twoway_received, on, 0);
388 if (on->state != OSPF6_NEIGHBOR_EXSTART)
389 {
390 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
c6487d61 391 zlog_debug ("Neighbor state is not ExStart, ignore");
508e53e2 392 return;
393 }
394 /* else fall through to ExStart */
acd738fc 395 /* fallthru */
508e53e2 396 case OSPF6_NEIGHBOR_EXSTART:
397 /* if neighbor obeys us as our slave, schedule negotiation_done
398 and process LSA Headers. Otherwise, ignore this message */
399 if (! CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_MSBIT) &&
400 ! CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_IBIT) &&
401 ntohl (dbdesc->seqnum) == on->dbdesc_seqnum)
402 {
403 /* execute NegotiationDone */
404 thread_execute (master, negotiation_done, on, 0);
718e3744 405
508e53e2 406 /* Record neighbor options */
407 memcpy (on->options, dbdesc->options, sizeof (on->options));
408 }
409 else
410 {
411 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
c6487d61 412 zlog_debug ("Negotiation failed");
508e53e2 413 return;
414 }
415 /* fall through to exchange */
718e3744 416
508e53e2 417 case OSPF6_NEIGHBOR_EXCHANGE:
418 if (! memcmp (dbdesc, &on->dbdesc_last, sizeof (struct ospf6_dbdesc)))
419 {
420 /* Duplicated DatabaseDescription is dropped by master */
421 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
c6487d61 422 zlog_debug ("Duplicated dbdesc discarded by Master, ignore");
508e53e2 423 return;
424 }
718e3744 425
508e53e2 426 if (CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_MSBIT))
427 {
428 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
c6487d61 429 zlog_debug ("Master/Slave bit mismatch");
ffa2c898 430 thread_add_event (master, seqnumber_mismatch, on, 0, NULL);
508e53e2 431 return;
432 }
433
434 if (CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_IBIT))
435 {
436 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
c6487d61 437 zlog_debug ("Initialize bit mismatch");
ffa2c898 438 thread_add_event (master, seqnumber_mismatch, on, 0, NULL);
508e53e2 439 return;
440 }
441
442 if (memcmp (on->options, dbdesc->options, sizeof (on->options)))
443 {
444 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
c6487d61 445 zlog_debug ("Option field mismatch");
ffa2c898 446 thread_add_event (master, seqnumber_mismatch, on, 0, NULL);
508e53e2 447 return;
448 }
449
450 if (ntohl (dbdesc->seqnum) != on->dbdesc_seqnum)
451 {
452 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
c6487d61 453 zlog_debug ("Sequence number mismatch (%#lx expected)",
508e53e2 454 (u_long) on->dbdesc_seqnum);
ffa2c898 455 thread_add_event (master, seqnumber_mismatch, on, 0, NULL);
508e53e2 456 return;
457 }
458 break;
459
460 case OSPF6_NEIGHBOR_LOADING:
461 case OSPF6_NEIGHBOR_FULL:
462 if (! memcmp (dbdesc, &on->dbdesc_last, sizeof (struct ospf6_dbdesc)))
463 {
464 /* Duplicated DatabaseDescription is dropped by master */
465 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
c6487d61 466 zlog_debug ("Duplicated dbdesc discarded by Master, ignore");
508e53e2 467 return;
468 }
469
470 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
c6487d61 471 zlog_debug ("Not duplicate dbdesc in state %s",
472 ospf6_neighbor_state_str[on->state]);
ffa2c898 473 thread_add_event (master, seqnumber_mismatch, on, 0, NULL);
508e53e2 474 return;
475
476 default:
477 assert (0);
478 break;
718e3744 479 }
480
508e53e2 481 /* Process LSA headers */
482 for (p = (char *) ((caddr_t) dbdesc + sizeof (struct ospf6_dbdesc));
483 p + sizeof (struct ospf6_lsa_header) <= OSPF6_MESSAGE_END (oh);
484 p += sizeof (struct ospf6_lsa_header))
718e3744 485 {
508e53e2 486 struct ospf6_lsa *his, *mine;
487 struct ospf6_lsdb *lsdb = NULL;
488
489 his = ospf6_lsa_create_headeronly ((struct ospf6_lsa_header *) p);
6452df09 490
491 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
c6487d61 492 zlog_debug ("%s", his->name);
6452df09 493
494 switch (OSPF6_LSA_SCOPE (his->header->type))
508e53e2 495 {
6452df09 496 case OSPF6_SCOPE_LINKLOCAL:
497 lsdb = on->ospf6_if->lsdb;
498 break;
499 case OSPF6_SCOPE_AREA:
500 lsdb = on->ospf6_if->area->lsdb;
501 break;
502 case OSPF6_SCOPE_AS:
503 lsdb = on->ospf6_if->area->ospf6->lsdb;
504 break;
505 case OSPF6_SCOPE_RESERVED:
506 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
c6487d61 507 zlog_debug ("Ignoring LSA of reserved scope");
508e53e2 508 ospf6_lsa_delete (his);
6452df09 509 continue;
510 break;
508e53e2 511 }
512
513 if (ntohs (his->header->type) == OSPF6_LSTYPE_AS_EXTERNAL &&
6452df09 514 IS_AREA_STUB (on->ospf6_if->area))
718e3744 515 {
508e53e2 516 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
c6487d61 517 zlog_debug ("SeqNumMismatch (E-bit mismatch), discard");
508e53e2 518 ospf6_lsa_delete (his);
ffa2c898 519 thread_add_event (master, seqnumber_mismatch, on, 0, NULL);
718e3744 520 return;
521 }
508e53e2 522
523 mine = ospf6_lsdb_lookup (his->header->type, his->header->id,
524 his->header->adv_router, lsdb);
6452df09 525 if (mine == NULL)
508e53e2 526 {
6452df09 527 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
c6487d61 528 zlog_debug ("Add request (No database copy)");
eb82e9ee 529 ospf6_lsdb_add (ospf6_lsa_copy(his), on->request_list);
6452df09 530 }
531 else if (ospf6_lsa_compare (his, mine) < 0)
532 {
533 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
c6487d61 534 zlog_debug ("Add request (Received MoreRecent)");
eb82e9ee 535 ospf6_lsdb_add (ospf6_lsa_copy(his), on->request_list);
508e53e2 536 }
537 else
6452df09 538 {
539 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
c6487d61 540 zlog_debug ("Discard (Existing MoreRecent)");
6452df09 541 }
eb82e9ee 542 ospf6_lsa_delete (his);
718e3744 543 }
544
fa079666 545 assert (p == OSPF6_MESSAGE_END (oh));
718e3744 546
508e53e2 547 /* Increment sequence number */
548 on->dbdesc_seqnum ++;
718e3744 549
508e53e2 550 /* schedule send lsreq */
ffa2c898
QY
551 if (on->request_list->count)
552 thread_add_event (master, ospf6_lsreq_send, on, 0, &on->thread_send_lsreq);
718e3744 553
508e53e2 554 THREAD_OFF (on->thread_send_dbdesc);
718e3744 555
508e53e2 556 /* More bit check */
557 if (! CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_MBIT) &&
558 ! CHECK_FLAG (on->dbdesc_bits, OSPF6_DBDESC_MBIT))
ffa2c898 559 thread_add_event (master, exchange_done, on, 0, NULL);
66e78ae6
QY
560 else {
561 on->thread_send_dbdesc = NULL;
562 thread_add_event(master, ospf6_dbdesc_send_newone, on, 0,
563 &on->thread_send_dbdesc);
564 }
718e3744 565
508e53e2 566 /* save last received dbdesc */
567 memcpy (&on->dbdesc_last, dbdesc, sizeof (struct ospf6_dbdesc));
718e3744 568}
569
508e53e2 570static void
571ospf6_dbdesc_recv_slave (struct ospf6_header *oh,
572 struct ospf6_neighbor *on)
718e3744 573{
718e3744 574 struct ospf6_dbdesc *dbdesc;
508e53e2 575 char *p;
718e3744 576
508e53e2 577 dbdesc = (struct ospf6_dbdesc *)
578 ((caddr_t) oh + sizeof (struct ospf6_header));
579
580 if (on->state < OSPF6_NEIGHBOR_INIT)
581 {
582 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
c6487d61 583 zlog_debug ("Neighbor state less than Init, ignore");
508e53e2 584 return;
585 }
718e3744 586
508e53e2 587 switch (on->state)
588 {
589 case OSPF6_NEIGHBOR_TWOWAY:
590 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
c6487d61 591 zlog_debug ("Neighbor state is 2-Way, ignore");
508e53e2 592 return;
718e3744 593
508e53e2 594 case OSPF6_NEIGHBOR_INIT:
595 thread_execute (master, twoway_received, on, 0);
596 if (on->state != OSPF6_NEIGHBOR_EXSTART)
597 {
598 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
c6487d61 599 zlog_debug ("Neighbor state is not ExStart, ignore");
508e53e2 600 return;
601 }
602 /* else fall through to ExStart */
acd738fc 603 /* fallthru */
508e53e2 604 case OSPF6_NEIGHBOR_EXSTART:
605 /* If the neighbor is Master, act as Slave. Schedule negotiation_done
606 and process LSA Headers. Otherwise, ignore this message */
607 if (CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_IBIT) &&
608 CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_MBIT) &&
609 CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_MSBIT) &&
610 ntohs (oh->length) == sizeof (struct ospf6_header) +
611 sizeof (struct ospf6_dbdesc))
612 {
613 /* set the master/slave bit to slave */
614 UNSET_FLAG (on->dbdesc_bits, OSPF6_DBDESC_MSBIT);
615
616 /* set the DD sequence number to one specified by master */
617 on->dbdesc_seqnum = ntohl (dbdesc->seqnum);
618
619 /* schedule NegotiationDone */
620 thread_execute (master, negotiation_done, on, 0);
621
622 /* Record neighbor options */
623 memcpy (on->options, dbdesc->options, sizeof (on->options));
624 }
625 else
626 {
627 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
c6487d61 628 zlog_debug ("Negotiation failed");
508e53e2 629 return;
630 }
631 break;
632
633 case OSPF6_NEIGHBOR_EXCHANGE:
634 if (! memcmp (dbdesc, &on->dbdesc_last, sizeof (struct ospf6_dbdesc)))
635 {
636 /* Duplicated DatabaseDescription causes slave to retransmit */
637 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
c6487d61 638 zlog_debug ("Duplicated dbdesc causes retransmit");
508e53e2 639 THREAD_OFF (on->thread_send_dbdesc);
66e78ae6
QY
640 on->thread_send_dbdesc = NULL;
641 thread_add_event(master, ospf6_dbdesc_send, on, 0,
642 &on->thread_send_dbdesc);
508e53e2 643 return;
644 }
645
646 if (! CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_MSBIT))
647 {
648 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
c6487d61 649 zlog_debug ("Master/Slave bit mismatch");
ffa2c898 650 thread_add_event (master, seqnumber_mismatch, on, 0, NULL);
508e53e2 651 return;
652 }
653
654 if (CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_IBIT))
655 {
656 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
c6487d61 657 zlog_debug ("Initialize bit mismatch");
ffa2c898 658 thread_add_event (master, seqnumber_mismatch, on, 0, NULL);
508e53e2 659 return;
660 }
661
662 if (memcmp (on->options, dbdesc->options, sizeof (on->options)))
663 {
664 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
c6487d61 665 zlog_debug ("Option field mismatch");
ffa2c898 666 thread_add_event (master, seqnumber_mismatch, on, 0, NULL);
508e53e2 667 return;
668 }
669
670 if (ntohl (dbdesc->seqnum) != on->dbdesc_seqnum + 1)
671 {
672 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
c6487d61 673 zlog_debug ("Sequence number mismatch (%#lx expected)",
674 (u_long) on->dbdesc_seqnum + 1);
ffa2c898 675 thread_add_event (master, seqnumber_mismatch, on, 0, NULL);
508e53e2 676 return;
677 }
678 break;
679
680 case OSPF6_NEIGHBOR_LOADING:
681 case OSPF6_NEIGHBOR_FULL:
682 if (! memcmp (dbdesc, &on->dbdesc_last, sizeof (struct ospf6_dbdesc)))
683 {
684 /* Duplicated DatabaseDescription causes slave to retransmit */
685 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
c6487d61 686 zlog_debug ("Duplicated dbdesc causes retransmit");
508e53e2 687 THREAD_OFF (on->thread_send_dbdesc);
ffa2c898 688 thread_add_event (master, ospf6_dbdesc_send, on, 0, &on->thread_send_dbdesc);
508e53e2 689 return;
690 }
691
692 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
c6487d61 693 zlog_debug ("Not duplicate dbdesc in state %s",
694 ospf6_neighbor_state_str[on->state]);
ffa2c898 695 thread_add_event (master, seqnumber_mismatch, on, 0, NULL);
508e53e2 696 return;
697
698 default:
699 assert (0);
700 break;
718e3744 701 }
702
508e53e2 703 /* Process LSA headers */
704 for (p = (char *) ((caddr_t) dbdesc + sizeof (struct ospf6_dbdesc));
705 p + sizeof (struct ospf6_lsa_header) <= OSPF6_MESSAGE_END (oh);
706 p += sizeof (struct ospf6_lsa_header))
718e3744 707 {
508e53e2 708 struct ospf6_lsa *his, *mine;
709 struct ospf6_lsdb *lsdb = NULL;
710
711 his = ospf6_lsa_create_headeronly ((struct ospf6_lsa_header *) p);
6452df09 712
713 switch (OSPF6_LSA_SCOPE (his->header->type))
508e53e2 714 {
6452df09 715 case OSPF6_SCOPE_LINKLOCAL:
716 lsdb = on->ospf6_if->lsdb;
717 break;
718 case OSPF6_SCOPE_AREA:
719 lsdb = on->ospf6_if->area->lsdb;
720 break;
721 case OSPF6_SCOPE_AS:
722 lsdb = on->ospf6_if->area->ospf6->lsdb;
723 break;
724 case OSPF6_SCOPE_RESERVED:
725 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
c6487d61 726 zlog_debug ("Ignoring LSA of reserved scope");
508e53e2 727 ospf6_lsa_delete (his);
6452df09 728 continue;
729 break;
508e53e2 730 }
731
6452df09 732 if (OSPF6_LSA_SCOPE (his->header->type) == OSPF6_SCOPE_AS &&
733 IS_AREA_STUB (on->ospf6_if->area))
718e3744 734 {
508e53e2 735 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
c6487d61 736 zlog_debug ("E-bit mismatch with LSA Headers");
508e53e2 737 ospf6_lsa_delete (his);
ffa2c898 738 thread_add_event (master, seqnumber_mismatch, on, 0, NULL);
718e3744 739 return;
740 }
508e53e2 741
742 mine = ospf6_lsdb_lookup (his->header->type, his->header->id,
743 his->header->adv_router, lsdb);
744 if (mine == NULL || ospf6_lsa_compare (his, mine) < 0)
745 {
6452df09 746 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
c6487d61 747 zlog_debug ("Add request-list: %s", his->name);
eb82e9ee 748 ospf6_lsdb_add (ospf6_lsa_copy(his), on->request_list);
508e53e2 749 }
eb82e9ee 750 ospf6_lsa_delete (his);
718e3744 751 }
752
fa079666 753 assert (p == OSPF6_MESSAGE_END (oh));
718e3744 754
508e53e2 755 /* Set sequence number to Master's */
756 on->dbdesc_seqnum = ntohl (dbdesc->seqnum);
718e3744 757
508e53e2 758 /* schedule send lsreq */
ffa2c898
QY
759 if (on->request_list->count)
760 thread_add_event (master, ospf6_lsreq_send, on, 0, &on->thread_send_lsreq);
718e3744 761
508e53e2 762 THREAD_OFF (on->thread_send_dbdesc);
ffa2c898 763 thread_add_event (master, ospf6_dbdesc_send_newone, on, 0, &on->thread_send_dbdesc);
718e3744 764
508e53e2 765 /* save last received dbdesc */
766 memcpy (&on->dbdesc_last, dbdesc, sizeof (struct ospf6_dbdesc));
718e3744 767}
768
6ac29a51 769static void
508e53e2 770ospf6_dbdesc_recv (struct in6_addr *src, struct in6_addr *dst,
771 struct ospf6_interface *oi, struct ospf6_header *oh)
718e3744 772{
508e53e2 773 struct ospf6_neighbor *on;
718e3744 774 struct ospf6_dbdesc *dbdesc;
718e3744 775
508e53e2 776 on = ospf6_neighbor_lookup (oh->router_id, oi);
777 if (on == NULL)
718e3744 778 {
508e53e2 779 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
c6487d61 780 zlog_debug ("Neighbor not found, ignore");
718e3744 781 return;
782 }
783
508e53e2 784 dbdesc = (struct ospf6_dbdesc *)
785 ((caddr_t) oh + sizeof (struct ospf6_header));
718e3744 786
508e53e2 787 /* Interface MTU check */
d42306d9 788 if (!oi->mtu_ignore && ntohs (dbdesc->ifmtu) != oi->ifmtu)
718e3744 789 {
508e53e2 790 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
c6487d61 791 zlog_debug ("I/F MTU mismatch");
508e53e2 792 return;
718e3744 793 }
794
508e53e2 795 if (dbdesc->reserved1 || dbdesc->reserved2)
796 {
797 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
c6487d61 798 zlog_debug ("Non-0 reserved field in %s's DbDesc, correct",
799 on->name);
508e53e2 800 dbdesc->reserved1 = 0;
801 dbdesc->reserved2 = 0;
802 }
718e3744 803
508e53e2 804 if (ntohl (oh->router_id) < ntohl (ospf6->router_id))
805 ospf6_dbdesc_recv_master (oh, on);
806 else if (ntohl (ospf6->router_id) < ntohl (oh->router_id))
807 ospf6_dbdesc_recv_slave (oh, on);
808 else
809 {
810 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
c6487d61 811 zlog_debug ("Can't decide which is master, ignore");
508e53e2 812 }
718e3744 813}
814
6ac29a51 815static void
508e53e2 816ospf6_lsreq_recv (struct in6_addr *src, struct in6_addr *dst,
817 struct ospf6_interface *oi, struct ospf6_header *oh)
718e3744 818{
508e53e2 819 struct ospf6_neighbor *on;
820 char *p;
821 struct ospf6_lsreq_entry *e;
508e53e2 822 struct ospf6_lsdb *lsdb = NULL;
718e3744 823 struct ospf6_lsa *lsa;
718e3744 824
508e53e2 825 on = ospf6_neighbor_lookup (oh->router_id, oi);
826 if (on == NULL)
718e3744 827 {
508e53e2 828 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
c6487d61 829 zlog_debug ("Neighbor not found, ignore");
718e3744 830 return;
831 }
832
508e53e2 833 if (on->state != OSPF6_NEIGHBOR_EXCHANGE &&
834 on->state != OSPF6_NEIGHBOR_LOADING &&
835 on->state != OSPF6_NEIGHBOR_FULL)
718e3744 836 {
508e53e2 837 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
c6487d61 838 zlog_debug ("Neighbor state less than Exchange, ignore");
718e3744 839 return;
840 }
841
508e53e2 842 /* Process each request */
843 for (p = (char *) ((caddr_t) oh + sizeof (struct ospf6_header));
844 p + sizeof (struct ospf6_lsreq_entry) <= OSPF6_MESSAGE_END (oh);
845 p += sizeof (struct ospf6_lsreq_entry))
718e3744 846 {
508e53e2 847 e = (struct ospf6_lsreq_entry *) p;
6452df09 848
849 switch (OSPF6_LSA_SCOPE (e->type))
850 {
851 case OSPF6_SCOPE_LINKLOCAL:
852 lsdb = on->ospf6_if->lsdb;
853 break;
854 case OSPF6_SCOPE_AREA:
855 lsdb = on->ospf6_if->area->lsdb;
856 break;
857 case OSPF6_SCOPE_AS:
858 lsdb = on->ospf6_if->area->ospf6->lsdb;
859 break;
860 default:
861 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
c6487d61 862 zlog_debug ("Ignoring LSA of reserved scope");
6452df09 863 continue;
864 break;
865 }
718e3744 866
508e53e2 867 /* Find database copy */
868 lsa = ospf6_lsdb_lookup (e->type, e->id, e->adv_router, lsdb);
869 if (lsa == NULL)
718e3744 870 {
508e53e2 871 char id[16], adv_router[16];
872 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
873 {
874 inet_ntop (AF_INET, &e->id, id, sizeof (id));
875 inet_ntop (AF_INET, &e->adv_router, adv_router,
876 sizeof (adv_router));
c6487d61 877 zlog_debug ("Can't find requested [%s Id:%s Adv:%s]",
878 ospf6_lstype_name (e->type), id, adv_router);
508e53e2 879 }
ffa2c898 880 thread_add_event (master, bad_lsreq, on, 0, NULL);
718e3744 881 return;
882 }
883
508e53e2 884 ospf6_lsdb_add (ospf6_lsa_copy (lsa), on->lsupdate_list);
718e3744 885 }
886
fa079666 887 assert (p == OSPF6_MESSAGE_END (oh));
718e3744 888
508e53e2 889 /* schedule send lsupdate */
890 THREAD_OFF (on->thread_send_lsupdate);
ffa2c898 891 thread_add_event (master, ospf6_lsupdate_send_neighbor, on, 0, &on->thread_send_lsupdate);
718e3744 892}
893
abc7ef44
DO
894/* Verify, that the specified memory area contains exactly N valid IPv6
895 prefixes as specified by RFC5340, A.4.1. */
896static unsigned
897ospf6_prefixes_examin
898(
899 struct ospf6_prefix *current, /* start of buffer */
900 unsigned length,
901 const u_int32_t req_num_pfxs /* always compared with the actual number of prefixes */
902)
903{
904 u_char requested_pfx_bytes;
905 u_int32_t real_num_pfxs = 0;
906
907 while (length)
908 {
909 if (length < OSPF6_PREFIX_MIN_SIZE)
910 {
911 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
912 zlog_debug ("%s: undersized IPv6 prefix header", __func__);
913 return MSG_NG;
914 }
915 /* safe to look deeper */
916 if (current->prefix_length > IPV6_MAX_BITLEN)
917 {
918 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
919 zlog_debug ("%s: invalid PrefixLength (%u bits)", __func__, current->prefix_length);
920 return MSG_NG;
921 }
922 /* covers both fixed- and variable-sized fields */
923 requested_pfx_bytes = OSPF6_PREFIX_MIN_SIZE + OSPF6_PREFIX_SPACE (current->prefix_length);
924 if (requested_pfx_bytes > length)
925 {
926 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
927 zlog_debug ("%s: undersized IPv6 prefix", __func__);
928 return MSG_NG;
929 }
930 /* next prefix */
931 length -= requested_pfx_bytes;
932 current = (struct ospf6_prefix *) ((caddr_t) current + requested_pfx_bytes);
933 real_num_pfxs++;
934 }
935 if (real_num_pfxs != req_num_pfxs)
936 {
937 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
938 zlog_debug ("%s: IPv6 prefix number mismatch (%u required, %u real)",
939 __func__, req_num_pfxs, real_num_pfxs);
940 return MSG_NG;
941 }
942 return MSG_OK;
943}
944
945/* Verify an LSA to have a valid length and dispatch further (where
946 appropriate) to check if the contents, including nested IPv6 prefixes,
947 is properly sized/aligned within the LSA. Note that this function gets
948 LSA type in network byte order, uses in host byte order and passes to
949 ospf6_lstype_name() in network byte order again. */
950static unsigned
951ospf6_lsa_examin (struct ospf6_lsa_header *lsah, const u_int16_t lsalen, const u_char headeronly)
952{
953 struct ospf6_intra_prefix_lsa *intra_prefix_lsa;
954 struct ospf6_as_external_lsa *as_external_lsa;
955 struct ospf6_link_lsa *link_lsa;
956 unsigned exp_length;
957 u_int8_t ltindex;
958 u_int16_t lsatype;
959
960 /* In case an additional minimum length constraint is defined for current
961 LSA type, make sure that this constraint is met. */
962 lsatype = ntohs (lsah->type);
963 ltindex = lsatype & OSPF6_LSTYPE_FCODE_MASK;
964 if
965 (
966 ltindex < OSPF6_LSTYPE_SIZE &&
967 ospf6_lsa_minlen[ltindex] &&
968 lsalen < ospf6_lsa_minlen[ltindex] + OSPF6_LSA_HEADER_SIZE
969 )
970 {
971 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
972 zlog_debug ("%s: undersized (%u B) LSA", __func__, lsalen);
973 return MSG_NG;
974 }
975 switch (lsatype)
976 {
977 case OSPF6_LSTYPE_ROUTER:
978 /* RFC5340 A.4.3, LSA header + OSPF6_ROUTER_LSA_MIN_SIZE bytes followed
979 by N>=0 interface descriptions. */
980 if ((lsalen - OSPF6_LSA_HEADER_SIZE - OSPF6_ROUTER_LSA_MIN_SIZE) % OSPF6_ROUTER_LSDESC_FIX_SIZE)
981 {
982 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
983 zlog_debug ("%s: interface description alignment error", __func__);
984 return MSG_NG;
985 }
986 break;
987 case OSPF6_LSTYPE_NETWORK:
988 /* RFC5340 A.4.4, LSA header + OSPF6_NETWORK_LSA_MIN_SIZE bytes
989 followed by N>=0 attached router descriptions. */
990 if ((lsalen - OSPF6_LSA_HEADER_SIZE - OSPF6_NETWORK_LSA_MIN_SIZE) % OSPF6_NETWORK_LSDESC_FIX_SIZE)
991 {
992 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
993 zlog_debug ("%s: router description alignment error", __func__);
994 return MSG_NG;
995 }
996 break;
997 case OSPF6_LSTYPE_INTER_PREFIX:
998 /* RFC5340 A.4.5, LSA header + OSPF6_INTER_PREFIX_LSA_MIN_SIZE bytes
999 followed by 3-4 fields of a single IPv6 prefix. */
1000 if (headeronly)
1001 break;
1002 return ospf6_prefixes_examin
1003 (
1004 (struct ospf6_prefix *) ((caddr_t) lsah + OSPF6_LSA_HEADER_SIZE + OSPF6_INTER_PREFIX_LSA_MIN_SIZE),
1005 lsalen - OSPF6_LSA_HEADER_SIZE - OSPF6_INTER_PREFIX_LSA_MIN_SIZE,
1006 1
1007 );
1008 case OSPF6_LSTYPE_INTER_ROUTER:
1009 /* RFC5340 A.4.6, fixed-size LSA. */
1010 if (lsalen > OSPF6_LSA_HEADER_SIZE + OSPF6_INTER_ROUTER_LSA_FIX_SIZE)
1011 {
1012 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
1013 zlog_debug ("%s: oversized (%u B) LSA", __func__, lsalen);
1014 return MSG_NG;
1015 }
1016 break;
1017 case OSPF6_LSTYPE_AS_EXTERNAL: /* RFC5340 A.4.7, same as A.4.8. */
1018 case OSPF6_LSTYPE_TYPE_7:
1019 /* RFC5340 A.4.8, LSA header + OSPF6_AS_EXTERNAL_LSA_MIN_SIZE bytes
1020 followed by 3-4 fields of IPv6 prefix and 3 conditional LSA fields:
1021 16 bytes of forwarding address, 4 bytes of external route tag,
1022 4 bytes of referenced link state ID. */
1023 if (headeronly)
1024 break;
1025 as_external_lsa = (struct ospf6_as_external_lsa *) ((caddr_t) lsah + OSPF6_LSA_HEADER_SIZE);
1026 exp_length = OSPF6_LSA_HEADER_SIZE + OSPF6_AS_EXTERNAL_LSA_MIN_SIZE;
1027 /* To find out if the last optional field (Referenced Link State ID) is
1028 assumed in this LSA, we need to access fixed fields of the IPv6
1029 prefix before ospf6_prefix_examin() confirms its sizing. */
1030 if (exp_length + OSPF6_PREFIX_MIN_SIZE > lsalen)
1031 {
1032 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
1033 zlog_debug ("%s: undersized (%u B) LSA header", __func__, lsalen);
1034 return MSG_NG;
1035 }
1036 /* forwarding address */
1037 if (CHECK_FLAG (as_external_lsa->bits_metric, OSPF6_ASBR_BIT_F))
1038 exp_length += 16;
1039 /* external route tag */
1040 if (CHECK_FLAG (as_external_lsa->bits_metric, OSPF6_ASBR_BIT_T))
1041 exp_length += 4;
1042 /* referenced link state ID */
1043 if (as_external_lsa->prefix.u._prefix_referenced_lstype)
1044 exp_length += 4;
1045 /* All the fixed-size fields (mandatory and optional) must fit. I.e.,
1046 this check does not include any IPv6 prefix fields. */
1047 if (exp_length > lsalen)
1048 {
1049 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
1050 zlog_debug ("%s: undersized (%u B) LSA header", __func__, lsalen);
1051 return MSG_NG;
1052 }
1053 /* The last call completely covers the remainder (IPv6 prefix). */
1054 return ospf6_prefixes_examin
1055 (
1056 (struct ospf6_prefix *) ((caddr_t) as_external_lsa + OSPF6_AS_EXTERNAL_LSA_MIN_SIZE),
1057 lsalen - exp_length,
1058 1
1059 );
1060 case OSPF6_LSTYPE_LINK:
1061 /* RFC5340 A.4.9, LSA header + OSPF6_LINK_LSA_MIN_SIZE bytes followed
1062 by N>=0 IPv6 prefix blocks (with N declared beforehand). */
1063 if (headeronly)
1064 break;
1065 link_lsa = (struct ospf6_link_lsa *) ((caddr_t) lsah + OSPF6_LSA_HEADER_SIZE);
1066 return ospf6_prefixes_examin
1067 (
1068 (struct ospf6_prefix *) ((caddr_t) link_lsa + OSPF6_LINK_LSA_MIN_SIZE),
1069 lsalen - OSPF6_LSA_HEADER_SIZE - OSPF6_LINK_LSA_MIN_SIZE,
1070 ntohl (link_lsa->prefix_num) /* 32 bits */
1071 );
1072 case OSPF6_LSTYPE_INTRA_PREFIX:
1073 /* RFC5340 A.4.10, LSA header + OSPF6_INTRA_PREFIX_LSA_MIN_SIZE bytes
1074 followed by N>=0 IPv6 prefixes (with N declared beforehand). */
1075 if (headeronly)
1076 break;
1077 intra_prefix_lsa = (struct ospf6_intra_prefix_lsa *) ((caddr_t) lsah + OSPF6_LSA_HEADER_SIZE);
1078 return ospf6_prefixes_examin
1079 (
1080 (struct ospf6_prefix *) ((caddr_t) intra_prefix_lsa + OSPF6_INTRA_PREFIX_LSA_MIN_SIZE),
1081 lsalen - OSPF6_LSA_HEADER_SIZE - OSPF6_INTRA_PREFIX_LSA_MIN_SIZE,
1082 ntohs (intra_prefix_lsa->prefix_num) /* 16 bits */
1083 );
1084 }
1085 /* No additional validation is possible for unknown LSA types, which are
1086 themselves valid in OPSFv3, hence the default decision is to accept. */
1087 return MSG_OK;
1088}
1089
1090/* Verify if the provided input buffer is a valid sequence of LSAs. This
1091 includes verification of LSA blocks length/alignment and dispatching
1092 of deeper-level checks. */
1093static unsigned
1094ospf6_lsaseq_examin
1095(
1096 struct ospf6_lsa_header *lsah, /* start of buffered data */
1097 size_t length,
1098 const u_char headeronly,
1099 /* When declared_num_lsas is not 0, compare it to the real number of LSAs
1100 and treat the difference as an error. */
1101 const u_int32_t declared_num_lsas
1102)
1103{
1104 u_int32_t counted_lsas = 0;
1105
1106 while (length)
1107 {
1108 u_int16_t lsalen;
1109 if (length < OSPF6_LSA_HEADER_SIZE)
1110 {
1111 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
cba1fab2 1112 zlog_debug ("%s: undersized (%zu B) trailing (#%u) LSA header",
abc7ef44
DO
1113 __func__, length, counted_lsas);
1114 return MSG_NG;
1115 }
1116 /* save on ntohs() calls here and in the LSA validator */
1117 lsalen = OSPF6_LSA_SIZE (lsah);
1118 if (lsalen < OSPF6_LSA_HEADER_SIZE)
1119 {
1120 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
1121 zlog_debug ("%s: malformed LSA header #%u, declared length is %u B",
1122 __func__, counted_lsas, lsalen);
1123 return MSG_NG;
1124 }
1125 if (headeronly)
1126 {
1127 /* less checks here and in ospf6_lsa_examin() */
1128 if (MSG_OK != ospf6_lsa_examin (lsah, lsalen, 1))
1129 {
1130 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
1131 zlog_debug ("%s: anomaly in header-only %s LSA #%u", __func__,
1132 ospf6_lstype_name (lsah->type), counted_lsas);
1133 return MSG_NG;
1134 }
1135 lsah = (struct ospf6_lsa_header *) ((caddr_t) lsah + OSPF6_LSA_HEADER_SIZE);
1136 length -= OSPF6_LSA_HEADER_SIZE;
1137 }
1138 else
1139 {
1140 /* make sure the input buffer is deep enough before further checks */
1141 if (lsalen > length)
1142 {
1143 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
cba1fab2 1144 zlog_debug ("%s: anomaly in %s LSA #%u: declared length is %u B, buffered length is %zu B",
abc7ef44
DO
1145 __func__, ospf6_lstype_name (lsah->type), counted_lsas, lsalen, length);
1146 return MSG_NG;
1147 }
1148 if (MSG_OK != ospf6_lsa_examin (lsah, lsalen, 0))
1149 {
1150 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
1151 zlog_debug ("%s: anomaly in %s LSA #%u", __func__,
1152 ospf6_lstype_name (lsah->type), counted_lsas);
1153 return MSG_NG;
1154 }
1155 lsah = (struct ospf6_lsa_header *) ((caddr_t) lsah + lsalen);
1156 length -= lsalen;
1157 }
1158 counted_lsas++;
1159 }
1160
1161 if (declared_num_lsas && counted_lsas != declared_num_lsas)
1162 {
1163 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
1164 zlog_debug ("%s: #LSAs declared (%u) does not match actual (%u)",
1165 __func__, declared_num_lsas, counted_lsas);
1166 return MSG_NG;
1167 }
1168 return MSG_OK;
1169}
1170
1171/* Verify a complete OSPF packet for proper sizing/alignment. */
1172static unsigned
1173ospf6_packet_examin (struct ospf6_header *oh, const unsigned bytesonwire)
1174{
1175 struct ospf6_lsupdate *lsupd;
1176 unsigned test;
1177
1178 /* length, 1st approximation */
1179 if (bytesonwire < OSPF6_HEADER_SIZE)
1180 {
1181 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
1182 zlog_debug ("%s: undersized (%u B) packet", __func__, bytesonwire);
1183 return MSG_NG;
1184 }
1185 /* Now it is safe to access header fields. */
1186 if (bytesonwire != ntohs (oh->length))
1187 {
1188 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
1189 zlog_debug ("%s: packet length error (%u real, %u declared)",
1190 __func__, bytesonwire, ntohs (oh->length));
1191 return MSG_NG;
1192 }
1193 /* version check */
1194 if (oh->version != OSPFV3_VERSION)
1195 {
1196 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
1197 zlog_debug ("%s: invalid (%u) protocol version", __func__, oh->version);
1198 return MSG_NG;
1199 }
1200 /* length, 2nd approximation */
1201 if
1202 (
1203 oh->type < OSPF6_MESSAGE_TYPE_ALL &&
1204 ospf6_packet_minlen[oh->type] &&
1205 bytesonwire < OSPF6_HEADER_SIZE + ospf6_packet_minlen[oh->type]
1206 )
1207 {
1208 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
1209 zlog_debug ("%s: undersized (%u B) %s packet", __func__,
56b40679 1210 bytesonwire, lookup_msg(ospf6_message_type_str, oh->type, NULL));
abc7ef44
DO
1211 return MSG_NG;
1212 }
1213 /* type-specific deeper validation */
1214 switch (oh->type)
1215 {
1216 case OSPF6_MESSAGE_TYPE_HELLO:
1217 /* RFC5340 A.3.2, packet header + OSPF6_HELLO_MIN_SIZE bytes followed
1218 by N>=0 router-IDs. */
1219 if (0 == (bytesonwire - OSPF6_HEADER_SIZE - OSPF6_HELLO_MIN_SIZE) % 4)
1220 return MSG_OK;
1221 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
1222 zlog_debug ("%s: alignment error in %s packet",
56b40679 1223 __func__, lookup_msg(ospf6_message_type_str, oh->type, NULL));
abc7ef44
DO
1224 return MSG_NG;
1225 case OSPF6_MESSAGE_TYPE_DBDESC:
1226 /* RFC5340 A.3.3, packet header + OSPF6_DB_DESC_MIN_SIZE bytes followed
1227 by N>=0 header-only LSAs. */
1228 test = ospf6_lsaseq_examin
1229 (
1230 (struct ospf6_lsa_header *) ((caddr_t) oh + OSPF6_HEADER_SIZE + OSPF6_DB_DESC_MIN_SIZE),
1231 bytesonwire - OSPF6_HEADER_SIZE - OSPF6_DB_DESC_MIN_SIZE,
1232 1,
1233 0
1234 );
1235 break;
1236 case OSPF6_MESSAGE_TYPE_LSREQ:
1237 /* RFC5340 A.3.4, packet header + N>=0 LS description blocks. */
1238 if (0 == (bytesonwire - OSPF6_HEADER_SIZE - OSPF6_LS_REQ_MIN_SIZE) % OSPF6_LSREQ_LSDESC_FIX_SIZE)
1239 return MSG_OK;
1240 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
1241 zlog_debug ("%s: alignment error in %s packet",
56b40679 1242 __func__, lookup_msg(ospf6_message_type_str, oh->type, NULL));
abc7ef44
DO
1243 return MSG_NG;
1244 case OSPF6_MESSAGE_TYPE_LSUPDATE:
1245 /* RFC5340 A.3.5, packet header + OSPF6_LS_UPD_MIN_SIZE bytes followed
1246 by N>=0 full LSAs (with N declared beforehand). */
1247 lsupd = (struct ospf6_lsupdate *) ((caddr_t) oh + OSPF6_HEADER_SIZE);
1248 test = ospf6_lsaseq_examin
1249 (
1250 (struct ospf6_lsa_header *) ((caddr_t) lsupd + OSPF6_LS_UPD_MIN_SIZE),
1251 bytesonwire - OSPF6_HEADER_SIZE - OSPF6_LS_UPD_MIN_SIZE,
1252 0,
1253 ntohl (lsupd->lsa_number) /* 32 bits */
1254 );
1255 break;
1256 case OSPF6_MESSAGE_TYPE_LSACK:
1257 /* RFC5340 A.3.6, packet header + N>=0 header-only LSAs. */
1258 test = ospf6_lsaseq_examin
1259 (
1260 (struct ospf6_lsa_header *) ((caddr_t) oh + OSPF6_HEADER_SIZE + OSPF6_LS_ACK_MIN_SIZE),
1261 bytesonwire - OSPF6_HEADER_SIZE - OSPF6_LS_ACK_MIN_SIZE,
1262 1,
1263 0
1264 );
1265 break;
1266 default:
1267 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
1268 zlog_debug ("%s: invalid (%u) message type", __func__, oh->type);
1269 return MSG_NG;
1270 }
1271 if (test != MSG_OK && IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
56b40679 1272 zlog_debug ("%s: anomaly in %s packet", __func__, lookup_msg(ospf6_message_type_str, oh->type, NULL));
abc7ef44
DO
1273 return test;
1274}
1275
1276/* Verify particular fields of otherwise correct received OSPF packet to
1277 meet the requirements of RFC. */
1278static int
1279ospf6_rxpacket_examin (struct ospf6_interface *oi, struct ospf6_header *oh, const unsigned bytesonwire)
1280{
1281 char buf[2][INET_ADDRSTRLEN];
1282
1283 if (MSG_OK != ospf6_packet_examin (oh, bytesonwire))
1284 return MSG_NG;
1285
1286 /* Area-ID check */
1287 if (oh->area_id != oi->area->area_id)
1288 {
1289 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
1290 {
8551e6da 1291 if (oh->area_id == OSPF_AREA_BACKBONE)
abc7ef44
DO
1292 zlog_debug ("%s: Message may be via Virtual Link: not supported", __func__);
1293 else
1294 zlog_debug
1295 (
1296 "%s: Area-ID mismatch (my %s, rcvd %s)", __func__,
1297 inet_ntop (AF_INET, &oi->area->area_id, buf[0], INET_ADDRSTRLEN),
1298 inet_ntop (AF_INET, &oh->area_id, buf[1], INET_ADDRSTRLEN)
1299 );
1300 }
1301 return MSG_NG;
1302 }
1303
1304 /* Instance-ID check */
1305 if (oh->instance_id != oi->instance_id)
1306 {
1307 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
1308 zlog_debug ("%s: Instance-ID mismatch (my %u, rcvd %u)", __func__, oi->instance_id, oh->instance_id);
1309 return MSG_NG;
1310 }
1311
1312 /* Router-ID check */
1313 if (oh->router_id == oi->area->ospf6->router_id)
1314 {
1315 zlog_warn ("%s: Duplicate Router-ID (%s)", __func__, inet_ntop (AF_INET, &oh->router_id, buf[0], INET_ADDRSTRLEN));
1316 return MSG_NG;
1317 }
1318 return MSG_OK;
1319}
1320
6ac29a51 1321static void
508e53e2 1322ospf6_lsupdate_recv (struct in6_addr *src, struct in6_addr *dst,
1323 struct ospf6_interface *oi, struct ospf6_header *oh)
718e3744 1324{
508e53e2 1325 struct ospf6_neighbor *on;
718e3744 1326 struct ospf6_lsupdate *lsupdate;
508e53e2 1327 char *p;
718e3744 1328
508e53e2 1329 on = ospf6_neighbor_lookup (oh->router_id, oi);
1330 if (on == NULL)
718e3744 1331 {
508e53e2 1332 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
c6487d61 1333 zlog_debug ("Neighbor not found, ignore");
718e3744 1334 return;
1335 }
1336
508e53e2 1337 if (on->state != OSPF6_NEIGHBOR_EXCHANGE &&
1338 on->state != OSPF6_NEIGHBOR_LOADING &&
1339 on->state != OSPF6_NEIGHBOR_FULL)
718e3744 1340 {
508e53e2 1341 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
c6487d61 1342 zlog_debug ("Neighbor state less than Exchange, ignore");
718e3744 1343 return;
1344 }
1345
508e53e2 1346 lsupdate = (struct ospf6_lsupdate *)
1347 ((caddr_t) oh + sizeof (struct ospf6_header));
718e3744 1348
508e53e2 1349 /* Process LSAs */
1350 for (p = (char *) ((caddr_t) lsupdate + sizeof (struct ospf6_lsupdate));
1351 p < OSPF6_MESSAGE_END (oh) &&
1352 p + OSPF6_LSA_SIZE (p) <= OSPF6_MESSAGE_END (oh);
1353 p += OSPF6_LSA_SIZE (p))
1354 {
6452df09 1355 ospf6_receive_lsa (on, (struct ospf6_lsa_header *) p);
508e53e2 1356 }
1357
fa079666 1358 assert (p == OSPF6_MESSAGE_END (oh));
718e3744 1359
508e53e2 1360}
1361
6ac29a51 1362static void
508e53e2 1363ospf6_lsack_recv (struct in6_addr *src, struct in6_addr *dst,
1364 struct ospf6_interface *oi, struct ospf6_header *oh)
1365{
1366 struct ospf6_neighbor *on;
1367 char *p;
1368 struct ospf6_lsa *his, *mine;
1369 struct ospf6_lsdb *lsdb = NULL;
1370
1371 assert (oh->type == OSPF6_MESSAGE_TYPE_LSACK);
508e53e2 1372
1373 on = ospf6_neighbor_lookup (oh->router_id, oi);
1374 if (on == NULL)
1375 {
1376 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
c6487d61 1377 zlog_debug ("Neighbor not found, ignore");
508e53e2 1378 return;
1379 }
1380
508e53e2 1381 if (on->state != OSPF6_NEIGHBOR_EXCHANGE &&
1382 on->state != OSPF6_NEIGHBOR_LOADING &&
1383 on->state != OSPF6_NEIGHBOR_FULL)
718e3744 1384 {
508e53e2 1385 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
c6487d61 1386 zlog_debug ("Neighbor state less than Exchange, ignore");
508e53e2 1387 return;
718e3744 1388 }
1389
508e53e2 1390 for (p = (char *) ((caddr_t) oh + sizeof (struct ospf6_header));
1391 p + sizeof (struct ospf6_lsa_header) <= OSPF6_MESSAGE_END (oh);
1392 p += sizeof (struct ospf6_lsa_header))
1393 {
1394 his = ospf6_lsa_create_headeronly ((struct ospf6_lsa_header *) p);
508e53e2 1395
6452df09 1396 switch (OSPF6_LSA_SCOPE (his->header->type))
1397 {
1398 case OSPF6_SCOPE_LINKLOCAL:
1399 lsdb = on->ospf6_if->lsdb;
1400 break;
1401 case OSPF6_SCOPE_AREA:
1402 lsdb = on->ospf6_if->area->lsdb;
1403 break;
1404 case OSPF6_SCOPE_AS:
1405 lsdb = on->ospf6_if->area->ospf6->lsdb;
1406 break;
1407 case OSPF6_SCOPE_RESERVED:
1408 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
c6487d61 1409 zlog_debug ("Ignoring LSA of reserved scope");
6452df09 1410 ospf6_lsa_delete (his);
1411 continue;
1412 break;
1413 }
1414
1415 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
c6487d61 1416 zlog_debug ("%s acknowledged by %s", his->name, on->name);
508e53e2 1417
1418 /* Find database copy */
1419 mine = ospf6_lsdb_lookup (his->header->type, his->header->id,
1420 his->header->adv_router, lsdb);
1421 if (mine == NULL)
1422 {
1423 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
c6487d61 1424 zlog_debug ("No database copy");
508e53e2 1425 ospf6_lsa_delete (his);
1426 continue;
1427 }
1428
1429 /* Check if the LSA is on his retrans-list */
1430 mine = ospf6_lsdb_lookup (his->header->type, his->header->id,
1431 his->header->adv_router, on->retrans_list);
1432 if (mine == NULL)
1433 {
1434 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
c6487d61 1435 zlog_debug ("Not on %s's retrans-list", on->name);
508e53e2 1436 ospf6_lsa_delete (his);
1437 continue;
1438 }
1439
1440 if (ospf6_lsa_compare (his, mine) != 0)
1441 {
1442 /* Log this questionable acknowledgement,
1443 and examine the next one. */
1444 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
c6487d61 1445 zlog_debug ("Questionable acknowledgement");
508e53e2 1446 ospf6_lsa_delete (his);
1447 continue;
1448 }
1449
6452df09 1450 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
c6487d61 1451 zlog_debug ("Acknowledged, remove from %s's retrans-list",
1452 on->name);
508e53e2 1453
932bf197 1454 ospf6_decrement_retrans_count (mine);
508e53e2 1455 if (OSPF6_LSA_IS_MAXAGE (mine))
1456 ospf6_maxage_remove (on->ospf6_if->area->ospf6);
cf1ce250 1457 ospf6_lsdb_remove (mine, on->retrans_list);
508e53e2 1458 ospf6_lsa_delete (his);
1459 }
1460
fa079666 1461 assert (p == OSPF6_MESSAGE_END (oh));
508e53e2 1462}
1463
6ac29a51
PJ
1464static u_char *recvbuf = NULL;
1465static u_char *sendbuf = NULL;
1466static unsigned int iobuflen = 0;
3b4cd3a9 1467
1468int
0c083ee9 1469ospf6_iobuf_size (unsigned int size)
3b4cd3a9 1470{
6ac29a51 1471 u_char *recvnew, *sendnew;
3b4cd3a9 1472
1473 if (size <= iobuflen)
1474 return iobuflen;
1475
1476 recvnew = XMALLOC (MTYPE_OSPF6_MESSAGE, size);
1477 sendnew = XMALLOC (MTYPE_OSPF6_MESSAGE, size);
1478 if (recvnew == NULL || sendnew == NULL)
1479 {
b596c71e 1480 if (recvnew)
1481 XFREE (MTYPE_OSPF6_MESSAGE, recvnew);
1482 if (sendnew)
1483 XFREE (MTYPE_OSPF6_MESSAGE, sendnew);
c6487d61 1484 zlog_debug ("Could not allocate I/O buffer of size %d.", size);
3b4cd3a9 1485 return iobuflen;
1486 }
1487
1488 if (recvbuf)
1489 XFREE (MTYPE_OSPF6_MESSAGE, recvbuf);
1490 if (sendbuf)
1491 XFREE (MTYPE_OSPF6_MESSAGE, sendbuf);
1492 recvbuf = recvnew;
1493 sendbuf = sendnew;
1494 iobuflen = size;
1495
1496 return iobuflen;
1497}
508e53e2 1498
ae2254aa
TG
1499void
1500ospf6_message_terminate (void)
1501{
1502 if (recvbuf)
1503 {
1504 XFREE (MTYPE_OSPF6_MESSAGE, recvbuf);
1505 recvbuf = NULL;
1506 }
1507
1508 if (sendbuf)
1509 {
1510 XFREE (MTYPE_OSPF6_MESSAGE, sendbuf);
1511 sendbuf = NULL;
1512 }
1513
1514 iobuflen = 0;
1515}
1516
508e53e2 1517int
1518ospf6_receive (struct thread *thread)
1519{
0c083ee9 1520 int sockfd;
1521 unsigned int len;
508e53e2 1522 char srcname[64], dstname[64];
1523 struct in6_addr src, dst;
b892f1dd 1524 ifindex_t ifindex;
508e53e2 1525 struct iovec iovector[2];
1526 struct ospf6_interface *oi;
1527 struct ospf6_header *oh;
1528
1529 /* add next read thread */
1530 sockfd = THREAD_FD (thread);
ffa2c898 1531 thread_add_read (master, ospf6_receive, NULL, sockfd, NULL);
508e53e2 1532
1533 /* initialize */
cf1ce250
PJ
1534 memset (&src, 0, sizeof (src));
1535 memset (&dst, 0, sizeof (dst));
1536 ifindex = 0;
3b4cd3a9 1537 memset (recvbuf, 0, iobuflen);
508e53e2 1538 iovector[0].iov_base = recvbuf;
3b4cd3a9 1539 iovector[0].iov_len = iobuflen;
508e53e2 1540 iovector[1].iov_base = NULL;
1541 iovector[1].iov_len = 0;
1542
1543 /* receive message */
1544 len = ospf6_recvmsg (&src, &dst, &ifindex, iovector);
3b4cd3a9 1545 if (len > iobuflen)
508e53e2 1546 {
1547 zlog_err ("Excess message read");
1548 return 0;
1549 }
508e53e2 1550
1551 oi = ospf6_interface_lookup_by_ifindex (ifindex);
d9628728 1552 if (oi == NULL || oi->area == NULL || CHECK_FLAG(oi->flag, OSPF6_INTERFACE_DISABLE))
508e53e2 1553 {
c6487d61 1554 zlog_debug ("Message received on disabled interface");
508e53e2 1555 return 0;
1556 }
abc7ef44
DO
1557 if (CHECK_FLAG (oi->flag, OSPF6_INTERFACE_PASSIVE))
1558 {
1559 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
1560 zlog_debug ("%s: Ignore message on passive interface %s",
1561 __func__, oi->interface->name);
1562 return 0;
1563 }
508e53e2 1564
1565 oh = (struct ospf6_header *) recvbuf;
abc7ef44
DO
1566 if (ospf6_rxpacket_examin (oi, oh, len) != MSG_OK)
1567 return 0;
1568
1569 /* Being here means, that no sizing/alignment issues were detected in
1570 the input packet. This renders the additional checks performed below
1571 and also in the type-specific dispatching functions a dead code,
1572 which can be dismissed in a cleanup-focused review round later. */
508e53e2 1573
1574 /* Log */
1575 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
1576 {
1577 inet_ntop (AF_INET6, &src, srcname, sizeof (srcname));
1578 inet_ntop (AF_INET6, &dst, dstname, sizeof (dstname));
c6487d61 1579 zlog_debug ("%s received on %s",
56b40679 1580 lookup_msg(ospf6_message_type_str, oh->type, NULL), oi->interface->name);
c6487d61 1581 zlog_debug (" src: %s", srcname);
1582 zlog_debug (" dst: %s", dstname);
508e53e2 1583
1584 switch (oh->type)
1585 {
1586 case OSPF6_MESSAGE_TYPE_HELLO:
1587 ospf6_hello_print (oh);
1588 break;
1589 case OSPF6_MESSAGE_TYPE_DBDESC:
1590 ospf6_dbdesc_print (oh);
1591 break;
1592 case OSPF6_MESSAGE_TYPE_LSREQ:
1593 ospf6_lsreq_print (oh);
1594 break;
1595 case OSPF6_MESSAGE_TYPE_LSUPDATE:
1596 ospf6_lsupdate_print (oh);
1597 break;
1598 case OSPF6_MESSAGE_TYPE_LSACK:
1599 ospf6_lsack_print (oh);
1600 break;
1601 default:
fa079666 1602 assert (0);
508e53e2 1603 }
508e53e2 1604 }
1605
1606 switch (oh->type)
1607 {
1608 case OSPF6_MESSAGE_TYPE_HELLO:
1609 ospf6_hello_recv (&src, &dst, oi, oh);
1610 break;
1611
1612 case OSPF6_MESSAGE_TYPE_DBDESC:
1613 ospf6_dbdesc_recv (&src, &dst, oi, oh);
1614 break;
1615
1616 case OSPF6_MESSAGE_TYPE_LSREQ:
1617 ospf6_lsreq_recv (&src, &dst, oi, oh);
1618 break;
1619
1620 case OSPF6_MESSAGE_TYPE_LSUPDATE:
1621 ospf6_lsupdate_recv (&src, &dst, oi, oh);
1622 break;
1623
1624 case OSPF6_MESSAGE_TYPE_LSACK:
1625 ospf6_lsack_recv (&src, &dst, oi, oh);
1626 break;
1627
1628 default:
fa079666 1629 assert (0);
508e53e2 1630 }
718e3744 1631
508e53e2 1632 return 0;
718e3744 1633}
1634
6ac29a51 1635static void
508e53e2 1636ospf6_send (struct in6_addr *src, struct in6_addr *dst,
1637 struct ospf6_interface *oi, struct ospf6_header *oh)
718e3744 1638{
b07c4cb3 1639 unsigned int len;
508e53e2 1640 char srcname[64], dstname[64];
1641 struct iovec iovector[2];
718e3744 1642
508e53e2 1643 /* initialize */
1644 iovector[0].iov_base = (caddr_t) oh;
1645 iovector[0].iov_len = ntohs (oh->length);
1646 iovector[1].iov_base = NULL;
1647 iovector[1].iov_len = 0;
1648
1649 /* fill OSPF header */
1650 oh->version = OSPFV3_VERSION;
1651 /* message type must be set before */
1652 /* message length must be set before */
1653 oh->router_id = oi->area->ospf6->router_id;
1654 oh->area_id = oi->area->area_id;
1655 /* checksum is calculated by kernel */
1656 oh->instance_id = oi->instance_id;
1657 oh->reserved = 0;
718e3744 1658
508e53e2 1659 /* Log */
1660 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, SEND))
718e3744 1661 {
508e53e2 1662 inet_ntop (AF_INET6, dst, dstname, sizeof (dstname));
1663 if (src)
1664 inet_ntop (AF_INET6, src, srcname, sizeof (srcname));
718e3744 1665 else
508e53e2 1666 memset (srcname, 0, sizeof (srcname));
c6487d61 1667 zlog_debug ("%s send on %s",
56b40679 1668 lookup_msg(ospf6_message_type_str, oh->type, NULL), oi->interface->name);
c6487d61 1669 zlog_debug (" src: %s", srcname);
1670 zlog_debug (" dst: %s", dstname);
508e53e2 1671
1672 switch (oh->type)
718e3744 1673 {
508e53e2 1674 case OSPF6_MESSAGE_TYPE_HELLO:
1675 ospf6_hello_print (oh);
1676 break;
1677 case OSPF6_MESSAGE_TYPE_DBDESC:
1678 ospf6_dbdesc_print (oh);
1679 break;
1680 case OSPF6_MESSAGE_TYPE_LSREQ:
1681 ospf6_lsreq_print (oh);
1682 break;
1683 case OSPF6_MESSAGE_TYPE_LSUPDATE:
1684 ospf6_lsupdate_print (oh);
1685 break;
1686 case OSPF6_MESSAGE_TYPE_LSACK:
1687 ospf6_lsack_print (oh);
1688 break;
1689 default:
c6487d61 1690 zlog_debug ("Unknown message");
508e53e2 1691 assert (0);
1692 break;
718e3744 1693 }
718e3744 1694 }
1695
508e53e2 1696 /* send message */
1697 len = ospf6_sendmsg (src, dst, &oi->interface->ifindex, iovector);
1698 if (len != ntohs (oh->length))
1699 zlog_err ("Could not send entire message");
718e3744 1700}
1701
cba1fab2 1702static uint32_t
681b84e8
DT
1703ospf6_packet_max(struct ospf6_interface *oi)
1704{
cba1fab2
VT
1705 assert (oi->ifmtu > sizeof (struct ip6_hdr));
1706 return oi->ifmtu - (sizeof (struct ip6_hdr));
681b84e8
DT
1707}
1708
508e53e2 1709int
1710ospf6_hello_send (struct thread *thread)
718e3744 1711{
508e53e2 1712 struct ospf6_interface *oi;
1713 struct ospf6_header *oh;
1714 struct ospf6_hello *hello;
0c083ee9 1715 u_char *p;
1eb8ef25 1716 struct listnode *node, *nnode;
508e53e2 1717 struct ospf6_neighbor *on;
718e3744 1718
508e53e2 1719 oi = (struct ospf6_interface *) THREAD_ARG (thread);
1720 oi->thread_send_hello = (struct thread *) NULL;
718e3744 1721
508e53e2 1722 if (oi->state <= OSPF6_INTERFACE_DOWN)
718e3744 1723 {
508e53e2 1724 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_HELLO, SEND))
c6487d61 1725 zlog_debug ("Unable to send Hello on down interface %s",
508e53e2 1726 oi->interface->name);
1727 return 0;
718e3744 1728 }
1729
1db65fad
IF
1730 if (iobuflen == 0)
1731 {
1732 zlog_debug ("Unable to send Hello on interface %s iobuflen is 0",
1733 oi->interface->name);
1734 return 0;
1735 }
1736
508e53e2 1737 /* set next thread */
ffa2c898 1738 thread_add_timer (master, ospf6_hello_send, oi, oi->hello_interval, &oi->thread_send_hello);
718e3744 1739
3b4cd3a9 1740 memset (sendbuf, 0, iobuflen);
508e53e2 1741 oh = (struct ospf6_header *) sendbuf;
1742 hello = (struct ospf6_hello *)((caddr_t) oh + sizeof (struct ospf6_header));
718e3744 1743
508e53e2 1744 hello->interface_id = htonl (oi->interface->ifindex);
1745 hello->priority = oi->priority;
1746 hello->options[0] = oi->area->options[0];
1747 hello->options[1] = oi->area->options[1];
1748 hello->options[2] = oi->area->options[2];
1749 hello->hello_interval = htons (oi->hello_interval);
1750 hello->dead_interval = htons (oi->dead_interval);
1751 hello->drouter = oi->drouter;
1752 hello->bdrouter = oi->bdrouter;
718e3744 1753
6ac29a51 1754 p = (u_char *)((caddr_t) hello + sizeof (struct ospf6_hello));
718e3744 1755
1eb8ef25 1756 for (ALL_LIST_ELEMENTS (oi->neighbor_list, node, nnode, on))
718e3744 1757 {
508e53e2 1758 if (on->state < OSPF6_NEIGHBOR_INIT)
1759 continue;
1760
681b84e8 1761 if (p - sendbuf + sizeof (u_int32_t) > ospf6_packet_max(oi))
508e53e2 1762 {
1763 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_HELLO, SEND))
c6487d61 1764 zlog_debug ("sending Hello message: exceeds I/F MTU");
508e53e2 1765 break;
1766 }
718e3744 1767
508e53e2 1768 memcpy (p, &on->router_id, sizeof (u_int32_t));
1769 p += sizeof (u_int32_t);
1770 }
718e3744 1771
508e53e2 1772 oh->type = OSPF6_MESSAGE_TYPE_HELLO;
1773 oh->length = htons (p - sendbuf);
718e3744 1774
508e53e2 1775 ospf6_send (oi->linklocal_addr, &allspfrouters6, oi, oh);
1776 return 0;
718e3744 1777}
1778
1779int
508e53e2 1780ospf6_dbdesc_send (struct thread *thread)
718e3744 1781{
508e53e2 1782 struct ospf6_neighbor *on;
1783 struct ospf6_header *oh;
1784 struct ospf6_dbdesc *dbdesc;
0c083ee9 1785 u_char *p;
508e53e2 1786 struct ospf6_lsa *lsa;
c5926a92 1787 struct in6_addr *dst;
718e3744 1788
508e53e2 1789 on = (struct ospf6_neighbor *) THREAD_ARG (thread);
1790 on->thread_send_dbdesc = (struct thread *) NULL;
718e3744 1791
508e53e2 1792 if (on->state < OSPF6_NEIGHBOR_EXSTART)
1793 {
1794 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_DBDESC, SEND))
c6487d61 1795 zlog_debug ("Quit to send DbDesc to neighbor %s state %s",
1796 on->name, ospf6_neighbor_state_str[on->state]);
508e53e2 1797 return 0;
1798 }
718e3744 1799
508e53e2 1800 /* set next thread if master */
1801 if (CHECK_FLAG (on->dbdesc_bits, OSPF6_DBDESC_MSBIT))
ffa2c898
QY
1802 thread_add_timer (master, ospf6_dbdesc_send, on,
1803 on->ospf6_if->rxmt_interval,
1804 &on->thread_send_dbdesc);
718e3744 1805
3b4cd3a9 1806 memset (sendbuf, 0, iobuflen);
508e53e2 1807 oh = (struct ospf6_header *) sendbuf;
1808 dbdesc = (struct ospf6_dbdesc *)((caddr_t) oh +
1809 sizeof (struct ospf6_header));
718e3744 1810
508e53e2 1811 /* if this is initial one, initialize sequence number for DbDesc */
7a10a359
DD
1812 if (CHECK_FLAG (on->dbdesc_bits, OSPF6_DBDESC_IBIT) &&
1813 (on->dbdesc_seqnum == 0))
508e53e2 1814 {
cf672a86 1815 on->dbdesc_seqnum = monotime(NULL);
508e53e2 1816 }
1817
1818 dbdesc->options[0] = on->ospf6_if->area->options[0];
1819 dbdesc->options[1] = on->ospf6_if->area->options[1];
1820 dbdesc->options[2] = on->ospf6_if->area->options[2];
1821 dbdesc->ifmtu = htons (on->ospf6_if->ifmtu);
1822 dbdesc->bits = on->dbdesc_bits;
1823 dbdesc->seqnum = htonl (on->dbdesc_seqnum);
718e3744 1824
508e53e2 1825 /* if this is not initial one, set LSA headers in dbdesc */
6ac29a51 1826 p = (u_char *)((caddr_t) dbdesc + sizeof (struct ospf6_dbdesc));
508e53e2 1827 if (! CHECK_FLAG (on->dbdesc_bits, OSPF6_DBDESC_IBIT))
718e3744 1828 {
49dd8e37 1829 for (ALL_LSDB(on->dbdesc_list, lsa))
508e53e2 1830 {
1831 ospf6_lsa_age_update_to_send (lsa, on->ospf6_if->transdelay);
1832
1833 /* MTU check */
1834 if (p - sendbuf + sizeof (struct ospf6_lsa_header) >
681b84e8 1835 ospf6_packet_max(on->ospf6_if))
508e53e2 1836 {
a765eb93 1837 ospf6_lsdb_lsa_unlock (lsa);
508e53e2 1838 break;
1839 }
1840 memcpy (p, lsa->header, sizeof (struct ospf6_lsa_header));
1841 p += sizeof (struct ospf6_lsa_header);
1842 }
718e3744 1843 }
1844
508e53e2 1845 oh->type = OSPF6_MESSAGE_TYPE_DBDESC;
1846 oh->length = htons (p - sendbuf);
718e3744 1847
c5926a92
DD
1848
1849 if (on->ospf6_if->state == OSPF6_INTERFACE_POINTTOPOINT)
1850 dst = &allspfrouters6;
1851 else
1852 dst = &on->linklocal_addr;
1853
1854 ospf6_send (on->ospf6_if->linklocal_addr, dst, on->ospf6_if, oh);
1855
718e3744 1856 return 0;
1857}
1858
718e3744 1859int
508e53e2 1860ospf6_dbdesc_send_newone (struct thread *thread)
718e3744 1861{
508e53e2 1862 struct ospf6_neighbor *on;
1863 struct ospf6_lsa *lsa;
1864 unsigned int size = 0;
1865
1866 on = (struct ospf6_neighbor *) THREAD_ARG (thread);
508e53e2 1867 ospf6_lsdb_remove_all (on->dbdesc_list);
1868
1869 /* move LSAs from summary_list to dbdesc_list (within neighbor structure)
1870 so that ospf6_send_dbdesc () can send those LSAs */
1871 size = sizeof (struct ospf6_lsa_header) + sizeof (struct ospf6_dbdesc);
49dd8e37 1872 for (ALL_LSDB(on->summary_list, lsa))
718e3744 1873 {
681b84e8 1874 if (size + sizeof (struct ospf6_lsa_header) > ospf6_packet_max(on->ospf6_if))
718e3744 1875 {
a765eb93 1876 ospf6_lsdb_lsa_unlock (lsa);
508e53e2 1877 break;
718e3744 1878 }
508e53e2 1879
508e53e2 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);
718e3744 1883 }
1884
508e53e2 1885 if (on->summary_list->count == 0)
1886 UNSET_FLAG (on->dbdesc_bits, OSPF6_DBDESC_MBIT);
718e3744 1887
508e53e2 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))
ffa2c898 1892 thread_add_event (master, exchange_done, on, 0, NULL);
718e3744 1893
508e53e2 1894 thread_execute (master, ospf6_dbdesc_send, on, 0);
1895 return 0;
1896}
718e3744 1897
508e53e2 1898int
1899ospf6_lsreq_send (struct thread *thread)
1900{
1901 struct ospf6_neighbor *on;
1902 struct ospf6_header *oh;
1903 struct ospf6_lsreq_entry *e;
0c083ee9 1904 u_char *p;
eb82e9ee 1905 struct ospf6_lsa *lsa, *last_req;
718e3744 1906
508e53e2 1907 on = (struct ospf6_neighbor *) THREAD_ARG (thread);
1908 on->thread_send_lsreq = (struct thread *) NULL;
1909
1910 /* LSReq will be sent only in ExStart or Loading */
1911 if (on->state != OSPF6_NEIGHBOR_EXCHANGE &&
1912 on->state != OSPF6_NEIGHBOR_LOADING)
718e3744 1913 {
508e53e2 1914 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_LSREQ, SEND))
c6487d61 1915 zlog_debug ("Quit to send LSReq to neighbor %s state %s",
1916 on->name, ospf6_neighbor_state_str[on->state]);
508e53e2 1917 return 0;
718e3744 1918 }
1919
508e53e2 1920 /* schedule loading_done if request list is empty */
1921 if (on->request_list->count == 0)
1922 {
ffa2c898 1923 thread_add_event (master, loading_done, on, 0, NULL);
718e3744 1924 return 0;
1925 }
1926
3b4cd3a9 1927 memset (sendbuf, 0, iobuflen);
508e53e2 1928 oh = (struct ospf6_header *) sendbuf;
eb82e9ee 1929 last_req = NULL;
718e3744 1930
508e53e2 1931 /* set Request entries in lsreq */
6ac29a51 1932 p = (u_char *)((caddr_t) oh + sizeof (struct ospf6_header));
49dd8e37 1933 for (ALL_LSDB(on->request_list, lsa))
718e3744 1934 {
508e53e2 1935 /* MTU check */
681b84e8 1936 if (p - sendbuf + sizeof (struct ospf6_lsreq_entry) > ospf6_packet_max(on->ospf6_if))
718e3744 1937 {
a765eb93 1938 ospf6_lsdb_lsa_unlock (lsa);
718e3744 1939 break;
1940 }
1941
508e53e2 1942 e = (struct ospf6_lsreq_entry *) p;
1943 e->type = lsa->header->type;
1944 e->id = lsa->header->id;
1945 e->adv_router = lsa->header->adv_router;
1946 p += sizeof (struct ospf6_lsreq_entry);
eb82e9ee
DD
1947 last_req = lsa;
1948 }
1949
1950 if (last_req != NULL)
1951 {
1952 if (on->last_ls_req != NULL)
1953 {
1954 ospf6_lsa_unlock (on->last_ls_req);
1955 }
1956 ospf6_lsa_lock (last_req);
1957 on->last_ls_req = last_req;
718e3744 1958 }
718e3744 1959
508e53e2 1960 oh->type = OSPF6_MESSAGE_TYPE_LSREQ;
1961 oh->length = htons (p - sendbuf);
718e3744 1962
c5926a92
DD
1963 if (on->ospf6_if->state == OSPF6_INTERFACE_POINTTOPOINT)
1964 ospf6_send (on->ospf6_if->linklocal_addr, &allspfrouters6,
508e53e2 1965 on->ospf6_if, oh);
c5926a92
DD
1966 else
1967 ospf6_send (on->ospf6_if->linklocal_addr, &on->linklocal_addr,
1968 on->ospf6_if, oh);
1969
eb82e9ee
DD
1970 /* set next thread */
1971 if (on->request_list->count != 0)
1972 {
66e78ae6
QY
1973 on->thread_send_lsreq = NULL;
1974 thread_add_timer(master, ospf6_lsreq_send, on, on->ospf6_if->rxmt_interval,
1975 &on->thread_send_lsreq);
eb82e9ee
DD
1976 }
1977
718e3744 1978 return 0;
1979}
1980
718e3744 1981int
508e53e2 1982ospf6_lsupdate_send_neighbor (struct thread *thread)
718e3744 1983{
508e53e2 1984 struct ospf6_neighbor *on;
1985 struct ospf6_header *oh;
1986 struct ospf6_lsupdate *lsupdate;
0c083ee9 1987 u_char *p;
c5926a92 1988 int lsa_cnt;
718e3744 1989 struct ospf6_lsa *lsa;
718e3744 1990
508e53e2 1991 on = (struct ospf6_neighbor *) THREAD_ARG (thread);
1992 on->thread_send_lsupdate = (struct thread *) NULL;
718e3744 1993
6452df09 1994 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_LSUPDATE, SEND))
c6487d61 1995 zlog_debug ("LSUpdate to neighbor %s", on->name);
6452df09 1996
508e53e2 1997 if (on->state < OSPF6_NEIGHBOR_EXCHANGE)
1998 {
1999 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_LSUPDATE, SEND))
c6487d61 2000 zlog_debug ("Quit to send (neighbor state %s)",
2001 ospf6_neighbor_state_str[on->state]);
508e53e2 2002 return 0;
2003 }
718e3744 2004
3b4cd3a9 2005 memset (sendbuf, 0, iobuflen);
508e53e2 2006 oh = (struct ospf6_header *) sendbuf;
2007 lsupdate = (struct ospf6_lsupdate *)
2008 ((caddr_t) oh + sizeof (struct ospf6_header));
718e3744 2009
6ac29a51 2010 p = (u_char *)((caddr_t) lsupdate + sizeof (struct ospf6_lsupdate));
c5926a92 2011 lsa_cnt = 0;
718e3744 2012
508e53e2 2013 /* lsupdate_list lists those LSA which doesn't need to be
2014 retransmitted. remove those from the list */
49dd8e37 2015 for (ALL_LSDB(on->lsupdate_list, lsa))
718e3744 2016 {
508e53e2 2017 /* MTU check */
0c083ee9 2018 if ( (p - sendbuf + (unsigned int)OSPF6_LSA_SIZE (lsa->header))
c5926a92
DD
2019 > ospf6_packet_max(on->ospf6_if))
2020 {
a765eb93 2021 ospf6_lsdb_lsa_unlock (lsa);
c5926a92
DD
2022 break;
2023 }
718e3744 2024
508e53e2 2025 ospf6_lsa_age_update_to_send (lsa, on->ospf6_if->transdelay);
2026 memcpy (p, lsa->header, OSPF6_LSA_SIZE (lsa->header));
2027 p += OSPF6_LSA_SIZE (lsa->header);
c5926a92 2028 lsa_cnt++;
718e3744 2029
508e53e2 2030 assert (lsa->lock == 2);
2031 ospf6_lsdb_remove (lsa, on->lsupdate_list);
2032 }
2033
c5926a92
DD
2034 if (lsa_cnt)
2035 {
2036 oh->type = OSPF6_MESSAGE_TYPE_LSUPDATE;
2037 oh->length = htons (p - sendbuf);
2038 lsupdate->lsa_number = htonl (lsa_cnt);
2039
2040 if ((on->ospf6_if->state == OSPF6_INTERFACE_POINTTOPOINT) ||
2041 (on->ospf6_if->state == OSPF6_INTERFACE_DR) ||
2042 (on->ospf6_if->state == OSPF6_INTERFACE_BDR))
2043 ospf6_send (on->ospf6_if->linklocal_addr, &allspfrouters6,
2044 on->ospf6_if, oh);
2045 else
2046 ospf6_send (on->ospf6_if->linklocal_addr, &on->linklocal_addr,
2047 on->ospf6_if, oh);
2048 }
2049
2050 /* The addresses used for retransmissions are different from those sent the
2051 first time and so we need to separate them here.
2052 */
2053 memset (sendbuf, 0, iobuflen);
2054 oh = (struct ospf6_header *) sendbuf;
2055 lsupdate = (struct ospf6_lsupdate *)
2056 ((caddr_t) oh + sizeof (struct ospf6_header));
2057 p = (u_char *)((caddr_t) lsupdate + sizeof (struct ospf6_lsupdate));
2058 lsa_cnt = 0;
2059
49dd8e37 2060 for (ALL_LSDB(on->retrans_list, lsa))
508e53e2 2061 {
2062 /* MTU check */
0c083ee9 2063 if ( (p - sendbuf + (unsigned int)OSPF6_LSA_SIZE (lsa->header))
c5926a92
DD
2064 > ospf6_packet_max(on->ospf6_if))
2065 {
a765eb93 2066 ospf6_lsdb_lsa_unlock (lsa);
c5926a92
DD
2067 break;
2068 }
508e53e2 2069
508e53e2 2070 ospf6_lsa_age_update_to_send (lsa, on->ospf6_if->transdelay);
2071 memcpy (p, lsa->header, OSPF6_LSA_SIZE (lsa->header));
2072 p += OSPF6_LSA_SIZE (lsa->header);
c5926a92 2073 lsa_cnt++;
718e3744 2074 }
2075
c5926a92 2076 if (lsa_cnt)
508e53e2 2077 {
c5926a92
DD
2078 oh->type = OSPF6_MESSAGE_TYPE_LSUPDATE;
2079 oh->length = htons (p - sendbuf);
2080 lsupdate->lsa_number = htonl (lsa_cnt);
2081
2082 if (on->ospf6_if->state == OSPF6_INTERFACE_POINTTOPOINT)
2083 ospf6_send (on->ospf6_if->linklocal_addr, &allspfrouters6,
2084 on->ospf6_if, oh);
508e53e2 2085 else
c5926a92
DD
2086 ospf6_send (on->ospf6_if->linklocal_addr, &on->linklocal_addr,
2087 on->ospf6_if, oh);
508e53e2 2088 }
718e3744 2089
66e78ae6
QY
2090 if (on->lsupdate_list->count != 0) {
2091 on->thread_send_lsupdate = NULL;
2092 thread_add_event(master, ospf6_lsupdate_send_neighbor, on, 0,
2093 &on->thread_send_lsupdate);
2094 }
2095 else if (on->retrans_list->count != 0) {
2096 on->thread_send_lsupdate = NULL;
2097 thread_add_timer(master, ospf6_lsupdate_send_neighbor, on, on->ospf6_if->rxmt_interval,
2098 &on->thread_send_lsupdate);
2099 }
718e3744 2100 return 0;
2101}
2102
2103int
508e53e2 2104ospf6_lsupdate_send_interface (struct thread *thread)
718e3744 2105{
508e53e2 2106 struct ospf6_interface *oi;
2107 struct ospf6_header *oh;
2108 struct ospf6_lsupdate *lsupdate;
0c083ee9 2109 u_char *p;
c5926a92 2110 int lsa_cnt;
718e3744 2111 struct ospf6_lsa *lsa;
718e3744 2112
508e53e2 2113 oi = (struct ospf6_interface *) THREAD_ARG (thread);
2114 oi->thread_send_lsupdate = (struct thread *) NULL;
718e3744 2115
508e53e2 2116 if (oi->state <= OSPF6_INTERFACE_WAITING)
718e3744 2117 {
508e53e2 2118 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_LSUPDATE, SEND))
c6487d61 2119 zlog_debug ("Quit to send LSUpdate to interface %s state %s",
2120 oi->interface->name, ospf6_interface_state_str[oi->state]);
508e53e2 2121 return 0;
2122 }
718e3744 2123
508e53e2 2124 /* if we have nothing to send, return */
2125 if (oi->lsupdate_list->count == 0)
2126 return 0;
718e3744 2127
3b4cd3a9 2128 memset (sendbuf, 0, iobuflen);
508e53e2 2129 oh = (struct ospf6_header *) sendbuf;
2130 lsupdate = (struct ospf6_lsupdate *)((caddr_t) oh +
c5926a92 2131 sizeof (struct ospf6_header));
718e3744 2132
6ac29a51 2133 p = (u_char *)((caddr_t) lsupdate + sizeof (struct ospf6_lsupdate));
c5926a92 2134 lsa_cnt = 0;
718e3744 2135
49dd8e37 2136 for (ALL_LSDB(oi->lsupdate_list, lsa))
508e53e2 2137 {
2138 /* MTU check */
0c083ee9 2139 if ( (p - sendbuf + ((unsigned int)OSPF6_LSA_SIZE (lsa->header)))
c5926a92
DD
2140 > ospf6_packet_max(oi))
2141 {
a765eb93 2142 ospf6_lsdb_lsa_unlock (lsa);
c5926a92
DD
2143 break;
2144 }
718e3744 2145
508e53e2 2146 ospf6_lsa_age_update_to_send (lsa, oi->transdelay);
2147 memcpy (p, lsa->header, OSPF6_LSA_SIZE (lsa->header));
2148 p += OSPF6_LSA_SIZE (lsa->header);
c5926a92 2149 lsa_cnt++;
718e3744 2150
508e53e2 2151 assert (lsa->lock == 2);
2152 ospf6_lsdb_remove (lsa, oi->lsupdate_list);
2153 }
718e3744 2154
c5926a92
DD
2155 if (lsa_cnt)
2156 {
2157 lsupdate->lsa_number = htonl (lsa_cnt);
718e3744 2158
c5926a92
DD
2159 oh->type = OSPF6_MESSAGE_TYPE_LSUPDATE;
2160 oh->length = htons (p - sendbuf);
718e3744 2161
c5926a92
DD
2162 if ((oi->state == OSPF6_INTERFACE_POINTTOPOINT) ||
2163 (oi->state == OSPF6_INTERFACE_DR) ||
2164 (oi->state == OSPF6_INTERFACE_BDR))
2165 ospf6_send (oi->linklocal_addr, &allspfrouters6, oi, oh);
2166 else
2167 ospf6_send (oi->linklocal_addr, &alldrouters6, oi, oh);
2168
2169 }
718e3744 2170
508e53e2 2171 if (oi->lsupdate_list->count > 0)
2172 {
66e78ae6
QY
2173 oi->thread_send_lsupdate = NULL;
2174 thread_add_event(master, ospf6_lsupdate_send_interface, oi, 0,
2175 &oi->thread_send_lsupdate);
508e53e2 2176 }
718e3744 2177
718e3744 2178 return 0;
2179}
2180
2181int
508e53e2 2182ospf6_lsack_send_neighbor (struct thread *thread)
718e3744 2183{
508e53e2 2184 struct ospf6_neighbor *on;
2185 struct ospf6_header *oh;
0c083ee9 2186 u_char *p;
718e3744 2187 struct ospf6_lsa *lsa;
c5926a92 2188 int lsa_cnt = 0;
718e3744 2189
508e53e2 2190 on = (struct ospf6_neighbor *) THREAD_ARG (thread);
2191 on->thread_send_lsack = (struct thread *) NULL;
718e3744 2192
508e53e2 2193 if (on->state < OSPF6_NEIGHBOR_EXCHANGE)
718e3744 2194 {
508e53e2 2195 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_LSACK, SEND))
c6487d61 2196 zlog_debug ("Quit to send LSAck to neighbor %s state %s",
2197 on->name, ospf6_neighbor_state_str[on->state]);
718e3744 2198 return 0;
2199 }
2200
508e53e2 2201 /* if we have nothing to send, return */
2202 if (on->lsack_list->count == 0)
2203 return 0;
718e3744 2204
3b4cd3a9 2205 memset (sendbuf, 0, iobuflen);
508e53e2 2206 oh = (struct ospf6_header *) sendbuf;
718e3744 2207
6ac29a51 2208 p = (u_char *)((caddr_t) oh + sizeof (struct ospf6_header));
718e3744 2209
49dd8e37 2210 for (ALL_LSDB(on->lsack_list, lsa))
508e53e2 2211 {
2212 /* MTU check */
681b84e8 2213 if (p - sendbuf + sizeof (struct ospf6_lsa_header) > ospf6_packet_max(on->ospf6_if))
c5926a92
DD
2214 {
2215 /* if we run out of packet size/space here,
2216 better to try again soon. */
2217 THREAD_OFF (on->thread_send_lsack);
ffa2c898 2218 thread_add_event (master, ospf6_lsack_send_neighbor, on, 0, &on->thread_send_lsack);
718e3744 2219
a765eb93 2220 ospf6_lsdb_lsa_unlock (lsa);
c5926a92
DD
2221 break;
2222 }
718e3744 2223
508e53e2 2224 ospf6_lsa_age_update_to_send (lsa, on->ospf6_if->transdelay);
2225 memcpy (p, lsa->header, sizeof (struct ospf6_lsa_header));
2226 p += sizeof (struct ospf6_lsa_header);
718e3744 2227
508e53e2 2228 assert (lsa->lock == 2);
2229 ospf6_lsdb_remove (lsa, on->lsack_list);
c5926a92 2230 lsa_cnt++;
508e53e2 2231 }
718e3744 2232
c5926a92
DD
2233 if (lsa_cnt)
2234 {
2235 oh->type = OSPF6_MESSAGE_TYPE_LSACK;
2236 oh->length = htons (p - sendbuf);
2237
2238 ospf6_send (on->ospf6_if->linklocal_addr, &on->linklocal_addr,
2239 on->ospf6_if, oh);
2240 }
2241
ffa2c898
QY
2242 if (on->lsack_list->count > 0)
2243 thread_add_event (master, ospf6_lsack_send_neighbor, on, 0, &on->thread_send_lsack);
718e3744 2244
2245 return 0;
2246}
2247
718e3744 2248int
508e53e2 2249ospf6_lsack_send_interface (struct thread *thread)
718e3744 2250{
508e53e2 2251 struct ospf6_interface *oi;
2252 struct ospf6_header *oh;
0c083ee9 2253 u_char *p;
718e3744 2254 struct ospf6_lsa *lsa;
c5926a92 2255 int lsa_cnt = 0;
718e3744 2256
508e53e2 2257 oi = (struct ospf6_interface *) THREAD_ARG (thread);
2258 oi->thread_send_lsack = (struct thread *) NULL;
718e3744 2259
508e53e2 2260 if (oi->state <= OSPF6_INTERFACE_WAITING)
2261 {
2262 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_LSACK, SEND))
c6487d61 2263 zlog_debug ("Quit to send LSAck to interface %s state %s",
2264 oi->interface->name, ospf6_interface_state_str[oi->state]);
508e53e2 2265 return 0;
2266 }
718e3744 2267
508e53e2 2268 /* if we have nothing to send, return */
2269 if (oi->lsack_list->count == 0)
2270 return 0;
718e3744 2271
3b4cd3a9 2272 memset (sendbuf, 0, iobuflen);
508e53e2 2273 oh = (struct ospf6_header *) sendbuf;
718e3744 2274
6ac29a51 2275 p = (u_char *)((caddr_t) oh + sizeof (struct ospf6_header));
718e3744 2276
49dd8e37 2277 for (ALL_LSDB(oi->lsack_list, lsa))
718e3744 2278 {
508e53e2 2279 /* MTU check */
681b84e8 2280 if (p - sendbuf + sizeof (struct ospf6_lsa_header) > ospf6_packet_max(oi))
c5926a92
DD
2281 {
2282 /* if we run out of packet size/space here,
2283 better to try again soon. */
2284 THREAD_OFF (oi->thread_send_lsack);
ffa2c898
QY
2285 thread_add_event (master, ospf6_lsack_send_interface, oi, 0,
2286 &oi->thread_send_lsack);
718e3744 2287
a765eb93 2288 ospf6_lsdb_lsa_unlock (lsa);
c5926a92
DD
2289 break;
2290 }
718e3744 2291
508e53e2 2292 ospf6_lsa_age_update_to_send (lsa, oi->transdelay);
2293 memcpy (p, lsa->header, sizeof (struct ospf6_lsa_header));
2294 p += sizeof (struct ospf6_lsa_header);
718e3744 2295
508e53e2 2296 assert (lsa->lock == 2);
2297 ospf6_lsdb_remove (lsa, oi->lsack_list);
c5926a92 2298 lsa_cnt++;
508e53e2 2299 }
718e3744 2300
c5926a92
DD
2301 if (lsa_cnt)
2302 {
2303 oh->type = OSPF6_MESSAGE_TYPE_LSACK;
2304 oh->length = htons (p - sendbuf);
718e3744 2305
c5926a92
DD
2306 if ((oi->state == OSPF6_INTERFACE_POINTTOPOINT) ||
2307 (oi->state == OSPF6_INTERFACE_DR) ||
2308 (oi->state == OSPF6_INTERFACE_BDR))
2309 ospf6_send (oi->linklocal_addr, &allspfrouters6, oi, oh);
2310 else
2311 ospf6_send (oi->linklocal_addr, &alldrouters6, oi, oh);
2312 }
718e3744 2313
ffa2c898
QY
2314 if (oi->lsack_list->count > 0)
2315 thread_add_event (master, ospf6_lsack_send_interface, oi, 0, &oi->thread_send_lsack);
718e3744 2316
718e3744 2317 return 0;
2318}
2319
6b0655a2 2320
508e53e2 2321/* Commands */
2322DEFUN (debug_ospf6_message,
2323 debug_ospf6_message_cmd,
1d68dbfe 2324 "debug ospf6 message <unknown|hello|dbdesc|lsreq|lsupdate|lsack|all> [<send|recv>]",
508e53e2 2325 DEBUG_STR
2326 OSPF6_STR
2327 "Debug OSPFv3 message\n"
2328 "Debug Unknown message\n"
2329 "Debug Hello message\n"
2330 "Debug Database Description message\n"
2331 "Debug Link State Request message\n"
2332 "Debug Link State Update message\n"
2333 "Debug Link State Acknowledgement message\n"
2334 "Debug All message\n"
1d68dbfe
DW
2335 "Debug only sending message\n"
2336 "Debug only receiving message\n")
718e3744 2337{
51c26414 2338 int idx_packet = 3;
1d68dbfe 2339 int idx_send_recv = 4;
508e53e2 2340 unsigned char level = 0;
2341 int type = 0;
2342 int i;
718e3744 2343
508e53e2 2344 /* check type */
51c26414 2345 if (! strncmp (argv[idx_packet]->arg, "u", 1))
508e53e2 2346 type = OSPF6_MESSAGE_TYPE_UNKNOWN;
51c26414 2347 else if (! strncmp (argv[idx_packet]->arg, "h", 1))
508e53e2 2348 type = OSPF6_MESSAGE_TYPE_HELLO;
51c26414 2349 else if (! strncmp (argv[idx_packet]->arg, "d", 1))
508e53e2 2350 type = OSPF6_MESSAGE_TYPE_DBDESC;
51c26414 2351 else if (! strncmp (argv[idx_packet]->arg, "lsr", 3))
508e53e2 2352 type = OSPF6_MESSAGE_TYPE_LSREQ;
51c26414 2353 else if (! strncmp (argv[idx_packet]->arg, "lsu", 3))
508e53e2 2354 type = OSPF6_MESSAGE_TYPE_LSUPDATE;
51c26414 2355 else if (! strncmp (argv[idx_packet]->arg, "lsa", 3))
508e53e2 2356 type = OSPF6_MESSAGE_TYPE_LSACK;
51c26414 2357 else if (! strncmp (argv[idx_packet]->arg, "a", 1))
508e53e2 2358 type = OSPF6_MESSAGE_TYPE_ALL;
2359
1d68dbfe 2360 if (argc == 4)
508e53e2 2361 level = OSPF6_DEBUG_MESSAGE_SEND | OSPF6_DEBUG_MESSAGE_RECV;
1d68dbfe 2362 else if (! strncmp (argv[idx_send_recv]->arg, "s", 1))
508e53e2 2363 level = OSPF6_DEBUG_MESSAGE_SEND;
1d68dbfe 2364 else if (! strncmp (argv[idx_send_recv]->arg, "r", 1))
508e53e2 2365 level = OSPF6_DEBUG_MESSAGE_RECV;
2366
2367 if (type == OSPF6_MESSAGE_TYPE_ALL)
2368 {
2369 for (i = 0; i < 6; i++)
2370 OSPF6_DEBUG_MESSAGE_ON (i, level);
2371 }
2372 else
2373 OSPF6_DEBUG_MESSAGE_ON (type, level);
718e3744 2374
508e53e2 2375 return CMD_SUCCESS;
718e3744 2376}
2377
508e53e2 2378DEFUN (no_debug_ospf6_message,
2379 no_debug_ospf6_message_cmd,
1d68dbfe 2380 "no debug ospf6 message <unknown|hello|dbdesc|lsreq|lsupdate|lsack|all> [<send|recv>]",
508e53e2 2381 NO_STR
2382 DEBUG_STR
2383 OSPF6_STR
2384 "Debug OSPFv3 message\n"
2385 "Debug Unknown message\n"
2386 "Debug Hello message\n"
2387 "Debug Database Description message\n"
2388 "Debug Link State Request message\n"
2389 "Debug Link State Update message\n"
2390 "Debug Link State Acknowledgement message\n"
2391 "Debug All message\n"
1d68dbfe
DW
2392 "Debug only sending message\n"
2393 "Debug only receiving message\n")
508e53e2 2394{
51c26414 2395 int idx_packet = 4;
1d68dbfe 2396 int idx_send_recv = 5;
508e53e2 2397 unsigned char level = 0;
2398 int type = 0;
2399 int i;
718e3744 2400
508e53e2 2401 /* check type */
51c26414 2402 if (! strncmp (argv[idx_packet]->arg, "u", 1))
508e53e2 2403 type = OSPF6_MESSAGE_TYPE_UNKNOWN;
51c26414 2404 else if (! strncmp (argv[idx_packet]->arg, "h", 1))
508e53e2 2405 type = OSPF6_MESSAGE_TYPE_HELLO;
51c26414 2406 else if (! strncmp (argv[idx_packet]->arg, "d", 1))
508e53e2 2407 type = OSPF6_MESSAGE_TYPE_DBDESC;
51c26414 2408 else if (! strncmp (argv[idx_packet]->arg, "lsr", 3))
508e53e2 2409 type = OSPF6_MESSAGE_TYPE_LSREQ;
51c26414 2410 else if (! strncmp (argv[idx_packet]->arg, "lsu", 3))
508e53e2 2411 type = OSPF6_MESSAGE_TYPE_LSUPDATE;
51c26414 2412 else if (! strncmp (argv[idx_packet]->arg, "lsa", 3))
508e53e2 2413 type = OSPF6_MESSAGE_TYPE_LSACK;
51c26414 2414 else if (! strncmp (argv[idx_packet]->arg, "a", 1))
508e53e2 2415 type = OSPF6_MESSAGE_TYPE_ALL;
2416
1d68dbfe 2417 if (argc == 5)
508e53e2 2418 level = OSPF6_DEBUG_MESSAGE_SEND | OSPF6_DEBUG_MESSAGE_RECV;
1d68dbfe 2419 else if (! strncmp (argv[idx_send_recv]->arg, "s", 1))
508e53e2 2420 level = OSPF6_DEBUG_MESSAGE_SEND;
1d68dbfe 2421 else if (! strncmp (argv[idx_send_recv]->arg, "r", 1))
508e53e2 2422 level = OSPF6_DEBUG_MESSAGE_RECV;
2423
2424 if (type == OSPF6_MESSAGE_TYPE_ALL)
718e3744 2425 {
508e53e2 2426 for (i = 0; i < 6; i++)
2427 OSPF6_DEBUG_MESSAGE_OFF (i, level);
718e3744 2428 }
2429 else
508e53e2 2430 OSPF6_DEBUG_MESSAGE_OFF (type, level);
718e3744 2431
508e53e2 2432 return CMD_SUCCESS;
718e3744 2433}
2434
508e53e2 2435
718e3744 2436int
508e53e2 2437config_write_ospf6_debug_message (struct vty *vty)
718e3744 2438{
0c083ee9 2439 const char *type_str[] = {"unknown", "hello", "dbdesc",
508e53e2 2440 "lsreq", "lsupdate", "lsack"};
2441 unsigned char s = 0, r = 0;
2442 int i;
718e3744 2443
508e53e2 2444 for (i = 0; i < 6; i++)
2445 {
2446 if (IS_OSPF6_DEBUG_MESSAGE (i, SEND))
2447 s |= 1 << i;
2448 if (IS_OSPF6_DEBUG_MESSAGE (i, RECV))
2449 r |= 1 << i;
2450 }
718e3744 2451
508e53e2 2452 if (s == 0x3f && r == 0x3f)
718e3744 2453 {
26a429fe 2454 vty_out (vty, "debug ospf6 message all\n");
508e53e2 2455 return 0;
2456 }
718e3744 2457
508e53e2 2458 if (s == 0x3f && r == 0)
2459 {
26a429fe 2460 vty_out (vty, "debug ospf6 message all send\n");
508e53e2 2461 return 0;
2462 }
2463 else if (s == 0 && r == 0x3f)
2464 {
26a429fe 2465 vty_out (vty, "debug ospf6 message all recv\n");
508e53e2 2466 return 0;
718e3744 2467 }
2468
508e53e2 2469 /* Unknown message is logged by default */
2470 if (! IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, SEND) &&
2471 ! IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
26a429fe 2472 vty_out (vty, "no debug ospf6 message unknown\n");
508e53e2 2473 else if (! IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, SEND))
26a429fe 2474 vty_out (vty, "no debug ospf6 message unknown send\n");
508e53e2 2475 else if (! IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
26a429fe 2476 vty_out (vty, "no debug ospf6 message unknown recv\n");
718e3744 2477
508e53e2 2478 for (i = 1; i < 6; i++)
718e3744 2479 {
508e53e2 2480 if (IS_OSPF6_DEBUG_MESSAGE (i, SEND) &&
2481 IS_OSPF6_DEBUG_MESSAGE (i, RECV))
55f70b67 2482 vty_out (vty, "debug ospf6 message %s\n", type_str[i]);
508e53e2 2483 else if (IS_OSPF6_DEBUG_MESSAGE (i, SEND))
55f70b67 2484 vty_out (vty, "debug ospf6 message %s send\n", type_str[i]);
508e53e2 2485 else if (IS_OSPF6_DEBUG_MESSAGE (i, RECV))
55f70b67 2486 vty_out (vty, "debug ospf6 message %s recv\n", type_str[i]);
718e3744 2487 }
2488
718e3744 2489 return 0;
2490}
2491
508e53e2 2492void
6ac29a51 2493install_element_ospf6_debug_message (void)
508e53e2 2494{
2495 install_element (ENABLE_NODE, &debug_ospf6_message_cmd);
2496 install_element (ENABLE_NODE, &no_debug_ospf6_message_cmd);
508e53e2 2497 install_element (CONFIG_NODE, &debug_ospf6_message_cmd);
2498 install_element (CONFIG_NODE, &no_debug_ospf6_message_cmd);
508e53e2 2499}
2500
2501