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