1/* 2 * Copyright (C) 1999 Yasuhiro Ohara 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 * 16 * You should have received a copy of the GNU General Public License 17 * along with GNU Zebra; see the file COPYING. If not, write to the 18 * Free Software Foundation, Inc., 59 Temple Place - Suite 330, 19 * Boston, MA 02111-1307, USA. 20 */ 21 22#include "ospf6d.h" 23 24int 25is_ospf6_message_dump (u_char type) 26{ 27 if (type > OSPF6_MESSAGE_TYPE_LSACK) 28 type = OSPF6_MESSAGE_TYPE_UNKNOWN; 29 30 switch (type) 31 { 32 case OSPF6_MESSAGE_TYPE_UNKNOWN: 33 return 1; 34 break; 35 case OSPF6_MESSAGE_TYPE_HELLO: 36 if (IS_OSPF6_DUMP_HELLO) 37 return 1; 38 break; 39 case OSPF6_MESSAGE_TYPE_DBDESC: 40 if (IS_OSPF6_DUMP_DBDESC) 41 return 1; 42 break; 43 case OSPF6_MESSAGE_TYPE_LSREQ: 44 if (IS_OSPF6_DUMP_LSREQ) 45 return 1; 46 break; 47 case OSPF6_MESSAGE_TYPE_LSUPDATE: 48 if (IS_OSPF6_DUMP_LSUPDATE) 49 return 1; 50 break; 51 case OSPF6_MESSAGE_TYPE_LSACK: 52 if (IS_OSPF6_DUMP_LSACK) 53 return 1; 54 break; 55 default: 56 break; 57 } 58 return 0; 59} 60#define IS_OSPF6_DUMP_MESSAGE(x) (is_ospf6_message_dump(x)) 61 62char *ospf6_message_type_string[] = 63{ 64 "Unknown", "Hello", "DbDesc", "LSReq", "LSUpdate", "LSAck", NULL 65}; 66 67void 68ospf6_message_log_lsa_header (struct ospf6_lsa_header *lsa_header) 69{ 70 char buf_id[16], buf_router[16], typebuf[32]; 71 72 inet_ntop (AF_INET, &lsa_header->advrtr, buf_router, sizeof (buf_router)); 73 inet_ntop (AF_INET, &lsa_header->ls_id, buf_id, sizeof (buf_id)); 74 zlog_info (" [%s ID=%s Adv=%s]", 75 ospf6_lsa_type_string (lsa_header->type, typebuf, 76 sizeof (typebuf)), 77 buf_id, buf_router); 78 zlog_info (" Age=%hu SeqNum=%#lx Cksum=%#hx Len=%hu", 79 ntohs (lsa_header->age), (u_long)ntohl (lsa_header->seqnum), 80 ntohs (lsa_header->checksum), ntohs (lsa_header->length)); 81} 82 83static void 84ospf6_message_log_unknown (struct iovec *message) 85{ 86 zlog_info ("Message: Unknown"); 87} 88 89static void 90ospf6_message_log_hello (struct iovec *message) 91{ 92 struct ospf6_header *ospf6_header; 93 u_int16_t length_left; 94 struct ospf6_hello *hello; 95 char dr_str[16], bdr_str[16]; 96 char *start, *end, *current; 97 98 /* calculate length */ 99 ospf6_header = (struct ospf6_header *) message[0].iov_base; 100 length_left = ntohs (ospf6_header->len) - sizeof (struct ospf6_header); 101 length_left = (length_left < iov_totallen (message) - sizeof (struct ospf6_header) ? 102 length_left : iov_totallen (message) - sizeof (struct ospf6_header)); 103 104 hello = (struct ospf6_hello *) message[1].iov_base; 105 106 inet_ntop (AF_INET, &hello->dr, dr_str, sizeof (dr_str)); 107 inet_ntop (AF_INET, &hello->bdr, bdr_str, sizeof (bdr_str)); 108 109 zlog_info (" IFID:%ld Priority:%d Option:%s", 110 (u_long)ntohl (hello->interface_id), hello->rtr_pri, "xxx"); 111 zlog_info (" HelloInterval:%hu Deadinterval:%hu", 112 ntohs (hello->hello_interval), 113 ntohs (hello->router_dead_interval)); 114 zlog_info (" DR:%s BDR:%s", dr_str, bdr_str); 115 116 start = (char *) (hello + 1); 117 if (start >= (char *) message[1].iov_base + message[1].iov_len) 118 start = message[2].iov_base; 119 end = (char *) start + (length_left - sizeof (struct ospf6_hello)); 120 121 for (current = start; current < end; current += sizeof (u_int32_t)) 122 { 123 char neighbor[16]; 124 inet_ntop (AF_INET, current, neighbor, sizeof (neighbor)); 125 zlog_info (" Neighbor: %s", neighbor); 126 } 127} 128 129static void 130ospf6_message_log_dbdesc (struct iovec *message) 131{ 132 struct ospf6_header *ospf6_header; 133 u_int16_t length_left; 134 struct ospf6_dbdesc *dbdesc; 135 int i; 136 char buffer[16]; 137 struct ospf6_lsa_header *lsa_header; 138 139 /* calculate length */ 140 ospf6_header = (struct ospf6_header *) message[0].iov_base; 141 length_left = ntohs (ospf6_header->len) - sizeof (struct ospf6_header); 142 length_left = (length_left < iov_totallen (message) - sizeof (struct ospf6_header) ? 143 length_left : iov_totallen (message) - sizeof (struct ospf6_header)); 144 145 dbdesc = (struct ospf6_dbdesc *) message[1].iov_base; 146 ospf6_options_string (dbdesc->options, buffer, sizeof (buffer)); 147 148 zlog_info (" Option:%s IFMTU:%hu", buffer, ntohs (dbdesc->ifmtu)); 149 zlog_info (" Bits:%s%s%s SeqNum:%#lx", 150 (DD_IS_IBIT_SET (dbdesc->bits) ? "I" : "-"), 151 (DD_IS_MBIT_SET (dbdesc->bits) ? "M" : "-"), 152 (DD_IS_MSBIT_SET (dbdesc->bits) ? "m" : "s"), 153 (u_long)ntohl (dbdesc->seqnum)); 154 155 for (lsa_header = (struct ospf6_lsa_header *) (dbdesc + 1); 156 (char *)(lsa_header + 1) <= (char *)(message[1].iov_base + message[1].iov_len) && 157 (char *)(lsa_header + 1) <= (char *)dbdesc + length_left; 158 lsa_header++) 159 ospf6_message_log_lsa_header (lsa_header); 160 161 length_left -= message[1].iov_len; 162 for (i = 2; message[i].iov_base; i++) 163 { 164 for (lsa_header = (struct ospf6_lsa_header *) message[i].iov_base; 165 (char *)(lsa_header + 1) <= (char *) (message[i].iov_base + 166 message[i].iov_len) && 167 (char *)(lsa_header + 1) <= (char *) (message[i].iov_base + length_left); 168 lsa_header++) 169 ospf6_message_log_lsa_header (lsa_header); 170 length_left -= message[i].iov_len; 171 } 172} 173 174static void 175ospf6_message_log_lsreq (struct iovec *message) 176{ 177 struct ospf6_header *ospf6_header; 178 u_int16_t length_left; 179 int i; 180 struct ospf6_lsreq *lsreq; 181 char buf_router[16], buf_id[16], buf_type[16]; 182 183 /* calculate length */ 184 ospf6_header = (struct ospf6_header *) message[0].iov_base; 185 length_left = ntohs (ospf6_header->len) - sizeof (struct ospf6_header); 186 length_left = (length_left < iov_totallen (message) - sizeof (struct ospf6_header) ? 187 length_left : iov_totallen (message) - sizeof (struct ospf6_header)); 188 189 for (i = 1; message[i].iov_base; i++) 190 { 191 for (lsreq = (struct ospf6_lsreq *) message[i].iov_base; 192 (char *)(lsreq + 1) <= (char *) (message[i].iov_base + message[i].iov_len) && 193 (char *)(lsreq + 1) <= (char *) (message[i].iov_base + length_left); 194 lsreq++) 195 { 196 inet_ntop (AF_INET, &lsreq->adv_router, buf_router, sizeof (buf_router)); 197 inet_ntop (AF_INET, &lsreq->id, buf_id, sizeof (buf_id)); 198 zlog_info (" [%s ID=%s Adv=%s]", 199 ospf6_lsa_type_string (lsreq->type, buf_type, 200 sizeof (buf_type)), 201 buf_id, buf_router); 202 } 203 length_left -= message[i].iov_len; 204 } 205} 206 207static void 208ospf6_message_log_lsupdate (struct iovec *message) 209{ 210 struct ospf6_header *ospf6_header; 211 u_int16_t length_left; 212 int i, lsanum; 213 struct ospf6_lsupdate *lsupdate; 214 struct ospf6_lsa_header *lsa_header; 215 216 /* calculate length */ 217 ospf6_header = (struct ospf6_header *) message[0].iov_base; 218 length_left = ntohs (ospf6_header->len) - sizeof (struct ospf6_header); 219 length_left = (length_left < iov_totallen (message) - sizeof (struct ospf6_header) ? 220 length_left : iov_totallen (message) - sizeof (struct ospf6_header)); 221 222 lsupdate = (struct ospf6_lsupdate *) message[1].iov_base; 223 lsanum = ntohl (lsupdate->lsupdate_num); 224 225 zlog_info (" Number of LSA: #%d", lsanum); 226 227 for (lsa_header = (struct ospf6_lsa_header *) (lsupdate + 1); 228 (char *)lsa_header < (char *)(message[1].iov_base + message[1].iov_len) && 229 (char *)lsa_header < (char *)(message[1].iov_base + length_left); 230 lsa_header = OSPF6_LSA_NEXT (lsa_header)) 231 ospf6_message_log_lsa_header (lsa_header); 232 length_left -= message[1].iov_len; 233 234 for (i = 2; message[i].iov_base; i++) 235 { 236 237 for (lsa_header = (struct ospf6_lsa_header *) message[i].iov_base; 238 (char *)lsa_header < (char *) (message[i].iov_base + message[i].iov_len) && 239 (char *)lsa_header < (char *) (message[i].iov_base + length_left); 240 lsa_header = OSPF6_LSA_NEXT (lsa_header)) 241 ospf6_message_log_lsa_header (lsa_header); 242 length_left -= message[i].iov_len; 243 } 244} 245 246static void 247ospf6_message_log_lsack (struct iovec *message) 248{ 249 struct ospf6_header *ospf6_header; 250 u_int16_t length_left; 251 struct ospf6_lsa_header *lsa_header; 252 int i; 253 254 /* calculate length */ 255 ospf6_header = (struct ospf6_header *) message[0].iov_base; 256 length_left = ntohs (ospf6_header->len) - sizeof (struct ospf6_header); 257 length_left = (length_left < iov_totallen (message) - sizeof (struct ospf6_header) ? 258 length_left : iov_totallen (message) - sizeof (struct ospf6_header)); 259 260 for (i = 1; message[i].iov_base; i++) 261 { 262 for (lsa_header = (struct ospf6_lsa_header *) message[i].iov_base; 263 (char *)(lsa_header + 1) <= (char *) (message[i].iov_base + 264 message[i].iov_len) && 265 (char *)(lsa_header + 1) <= (char *) (message[i].iov_base + length_left); 266 lsa_header++) 267 ospf6_message_log_lsa_header (lsa_header); 268 length_left -= message[i].iov_len; 269 } 270} 271 272struct { 273 void (*message_log) (struct iovec *); 274} ospf6_message_log_body [] = 275{ 276 {ospf6_message_log_unknown}, 277 {ospf6_message_log_hello}, 278 {ospf6_message_log_dbdesc}, 279 {ospf6_message_log_lsreq}, 280 {ospf6_message_log_lsupdate}, 281 {ospf6_message_log_lsack}, 282}; 283 284static void 285ospf6_message_log (struct iovec *message) 286{ 287 struct ospf6_header *o6h; 288 char router_id[16], area_id[16]; 289 u_char type; 290 291 assert (message[0].iov_len == sizeof (struct ospf6_header)); 292 o6h = (struct ospf6_header *) message[0].iov_base; 293 294 inet_ntop (AF_INET, &o6h->router_id, router_id, sizeof (router_id)); 295 inet_ntop (AF_INET, &o6h->area_id, area_id, sizeof (area_id)); 296 297 zlog_info (" OSPFv%d Type:%d Len:%hu RouterID:%s", 298 o6h->version, o6h->type, ntohs (o6h->len), router_id); 299 zlog_info (" AreaID:%s Cksum:%hx InstanceID:%d", 300 area_id, ntohs (o6h->cksum), o6h->instance_id); 301 302 type = (OSPF6_MESSAGE_TYPE_UNKNOWN < o6h->type && 303 o6h->type <= OSPF6_MESSAGE_TYPE_LSACK ? 304 o6h->type : OSPF6_MESSAGE_TYPE_UNKNOWN); 305 (* ospf6_message_log_body[type].message_log) (&message[0]); 306} 307 308int 309ospf6_opt_is_mismatch (unsigned char opt, char *options1, char *options2) 310{ 311 return (OSPF6_OPT_ISSET (options1, opt) ^ OSPF6_OPT_ISSET (options2, opt)); 312} 313 314 315void 316ospf6_process_unknown (struct iovec *message, 317 struct in6_addr *src, 318 struct in6_addr *dst, 319 struct ospf6_interface *o6i, 320 u_int32_t router_id) 321{ 322 zlog_warn ("unknown message type, drop"); 323} 324 325void 326ospf6_process_hello (struct iovec *message, 327 struct in6_addr *src, 328 struct in6_addr *dst, 329 struct ospf6_interface *o6i, 330 u_int32_t router_id) 331{ 332 struct ospf6_header *ospf6_header; 333 u_int16_t length; 334 struct ospf6_hello *hello; 335 char changes = 0; 336#define CHANGE_RTRPRI (1 << 0) 337#define CHANGE_DR (1 << 1) 338#define CHANGE_BDR (1 << 2) 339 int twoway = 0, backupseen = 0, nbchange = 0; 340 u_int32_t *router_id_ptr; 341 int i, seenrtrnum = 0, router_id_space = 0; 342 char strbuf[64]; 343 struct ospf6_neighbor *o6n = NULL; 344 345 /* assert interface */ 346 assert (o6i); 347 348 /* caluculate length */ 349 ospf6_header = (struct ospf6_header *) message[0].iov_base; 350 length = ntohs (ospf6_header->len) - sizeof (struct ospf6_header); 351 length = (length < message[1].iov_len ? length : message[1].iov_len); 352 353 /* set hello pointer */ 354 hello = (struct ospf6_hello *) message[1].iov_base; 355 356 /* find neighbor. if cannot be found, create */ 357 o6n = ospf6_neighbor_lookup (router_id, o6i); 358 if (!o6n) 359 { 360 o6n = ospf6_neighbor_create (router_id, o6i); 361 o6n->ifid = ntohl (hello->interface_id); 362 o6n->prevdr = o6n->dr = hello->dr; 363 o6n->prevbdr = o6n->bdr = hello->bdr; 364 o6n->priority = hello->rtr_pri; 365 memcpy (&o6n->hisaddr, src, sizeof (struct in6_addr)); 366 } 367 368 /* HelloInterval check */ 369 if (ntohs (hello->hello_interval) != o6i->hello_interval) 370 { 371 zlog_warn ("HelloInterval mismatch with %s", o6n->str); 372 return; 373 } 374 375 /* RouterDeadInterval check */ 376 if (ntohs (hello->router_dead_interval) 377 != o6i->dead_interval) 378 { 379 zlog_warn ("RouterDeadInterval mismatch with %s", o6n->str); 380 return; 381 } 382 383 /* check options */ 384 /* Ebit */ 385 if (ospf6_opt_is_mismatch (OSPF6_OPT_E, hello->options, o6i->area->options)) 386 { 387 zlog_warn ("Ebit mismatch with %s", o6n->str); 388 return; 389 } 390 391 /* RouterPriority set */ 392 if (o6n->priority != hello->rtr_pri) 393 { 394 o6n->priority = hello->rtr_pri; 395 if (IS_OSPF6_DUMP_HELLO) 396 zlog_info ("%s: RouterPriority changed", o6n->str); 397 changes |= CHANGE_RTRPRI; 398 } 399 400 /* DR set */ 401 if (o6n->dr != hello->dr) 402 { 403 /* save previous dr, set current */ 404 o6n->prevdr = o6n->dr; 405 o6n->dr = hello->dr; 406 inet_ntop (AF_INET, &o6n->dr, strbuf, sizeof (strbuf)); 407 if (IS_OSPF6_DUMP_HELLO) 408 zlog_info ("%s declare %s as DR", o6n->str, strbuf); 409 changes |= CHANGE_DR; 410 } 411 412 /* BDR set */ 413 if (o6n->bdr != hello->bdr) 414 { 415 /* save previous bdr, set current */ 416 o6n->prevbdr = o6n->bdr; 417 o6n->bdr = hello->bdr; 418 inet_ntop (AF_INET, &o6n->bdr, strbuf, sizeof (strbuf)); 419 if (IS_OSPF6_DUMP_HELLO) 420 zlog_info ("%s declare %s as BDR", o6n->str, strbuf); 421 changes |= CHANGE_BDR; 422 } 423 424 /* TwoWay check */ 425 router_id_space = length - sizeof (struct ospf6_hello); 426 seenrtrnum = router_id_space / sizeof (u_int32_t); 427 router_id_ptr = (u_int32_t *) (hello + 1); 428 for (i = 0; i < seenrtrnum; i++) 429 { 430 if (*router_id_ptr == o6i->area->ospf6->router_id) 431 twoway++; 432 router_id_ptr++; 433 } 434 435 /* execute neighbor events */ 436 thread_execute (master, hello_received, o6n, 0); 437 if (twoway) 438 thread_execute (master, twoway_received, o6n, 0); 439 else 440 thread_execute (master, oneway_received, o6n, 0); 441 442 /* BackupSeen check */ 443 if (o6i->state == IFS_WAITING) 444 { 445 if (hello->dr == hello->bdr && 446 hello->dr == o6n->router_id) 447 zlog_warn ("*** DR Election of %s is illegal", o6n->str); 448 449 if (hello->bdr == o6n->router_id) 450 backupseen++; 451 else if (hello->dr == o6n->router_id && hello->bdr == 0) 452 backupseen++; 453 } 454 455 /* NeighborChange check */ 456 if (changes & CHANGE_RTRPRI) 457 nbchange++; 458 if (changes & CHANGE_DR) 459 if (o6n->prevdr == o6n->router_id || o6n->dr == o6n->router_id) 460 nbchange++; 461 if (changes & CHANGE_BDR) 462 if (o6n->prevbdr == o6n->router_id || o6n->bdr == o6n->router_id) 463 nbchange++; 464 465 /* schedule interface events */ 466 if (backupseen) 467 thread_add_event (master, backup_seen, o6i, 0); 468 if (nbchange) 469 thread_add_event (master, neighbor_change, o6i, 0); 470 471 return; 472} 473 474int 475ospf6_dbdesc_is_master (struct ospf6_neighbor *o6n) 476{ 477 char buf[128]; 478 479 if (o6n->router_id == ospf6->router_id) 480 { 481 inet_ntop (AF_INET6, &o6n->hisaddr, buf, sizeof (buf)); 482 zlog_warn ("Message: Neighbor router-id conflicts: %s: %s", 483 o6n->str, buf); 484 return -1; 485 } 486 else if (ntohl (o6n->router_id) > ntohl (ospf6->router_id)) 487 return 0; 488 return 1; 489} 490 491int 492ospf6_dbdesc_is_duplicate (struct ospf6_dbdesc *received, 493 struct ospf6_dbdesc *last_received) 494{ 495 if (memcmp (received->options, last_received->options, 3) != 0) 496 return 0; 497 if (received->ifmtu != last_received->ifmtu) 498 return 0; 499 if (received->bits != last_received->bits) 500 return 0; 501 if (received->seqnum != last_received->seqnum) 502 return 0; 503 return 1; 504} 505 506void 507ospf6_process_dbdesc_master (struct iovec *message, struct ospf6_neighbor *o6n) 508{ 509 struct ospf6_header *ospf6_header; 510 u_int16_t length, lsa_count; 511 struct ospf6_dbdesc *dbdesc; 512 struct ospf6_lsa_header *lsa_header; 513 514 /* caluculate length */ 515 ospf6_header = (struct ospf6_header *) message[0].iov_base; 516 length = ntohs (ospf6_header->len) - sizeof (struct ospf6_header); 517 length = (length < message[1].iov_len ? length : message[1].iov_len); 518 519 /* set database description pointer */ 520 dbdesc = (struct ospf6_dbdesc *) message[1].iov_base; 521 522 switch (o6n->state) 523 { 524 case NBS_DOWN: 525 case NBS_ATTEMPT: 526 case NBS_TWOWAY: 527 if (IS_OSPF6_DUMP_DBDESC) 528 zlog_info ("DbDesc from %s Ignored: state less than Init", 529 o6n->str); 530 return; 531 532 case NBS_INIT: 533 thread_execute (master, twoway_received, o6n, 0); 534 if (o6n->state != NBS_EXSTART) 535 { 536 if (IS_OSPF6_DUMP_DBDESC) 537 zlog_info ("DbDesc from %s Ignored: state less than ExStart", 538 o6n->str); 539 return; 540 } 541 /* else fall through to ExStart */ 542 case NBS_EXSTART: 543 if (DDBIT_IS_SLAVE (dbdesc->bits) && 544 !DDBIT_IS_INITIAL (dbdesc->bits) && 545 ntohl (dbdesc->seqnum) == o6n->dbdesc_seqnum) 546 { 547 ospf6_neighbor_dbex_init (o6n); 548 549 if (o6n->thread_rxmt_dbdesc) 550 thread_cancel (o6n->thread_rxmt_dbdesc); 551 o6n->thread_rxmt_dbdesc = (struct thread *) NULL; 552 553 thread_add_event (master, negotiation_done, o6n, 0); 554 } 555 else 556 { 557 if (IS_OSPF6_DUMP_DBDESC) 558 zlog_info (" negotiation failed with %s", o6n->str); 559 return; 560 } 561 break; 562 563 case NBS_EXCHANGE: 564 /* duplicate dbdesc dropped by master */ 565 if (!memcmp (dbdesc, &o6n->last_dd, 566 sizeof (struct ospf6_dbdesc))) 567 { 568 if (IS_OSPF6_DUMP_DBDESC) 569 zlog_info (" duplicate dbdesc, drop"); 570 return; 571 } 572 573 /* check Initialize bit and Master/Slave bit */ 574 if (DDBIT_IS_INITIAL (dbdesc->bits)) 575 { 576 if (IS_OSPF6_DUMP_DBDESC) 577 zlog_info ("Initialize bit mismatch"); 578 thread_add_event (master, seqnumber_mismatch, o6n, 0); 579 return; 580 } 581 if (DDBIT_IS_MASTER (dbdesc->bits)) 582 { 583 if (IS_OSPF6_DUMP_DBDESC) 584 zlog_info ("Master/Slave bit mismatch"); 585 thread_add_event (master, seqnumber_mismatch, o6n, 0); 586 return; 587 } 588 589 /* dbdesc option check */ 590 if (memcmp (dbdesc->options, o6n->last_dd.options, 591 sizeof (dbdesc->options))) 592 { 593 if (IS_OSPF6_DUMP_DBDESC) 594 zlog_info ("dbdesc option field changed"); 595 thread_add_event (master, seqnumber_mismatch, o6n, 0); 596 return; 597 } 598 599 /* dbdesc sequence number check */ 600 if (ntohl (dbdesc->seqnum) != o6n->dbdesc_seqnum) 601 { 602 if (IS_OSPF6_DUMP_DBDESC) 603 zlog_warn ("*** dbdesc seqnumber mismatch: %d expected", 604 o6n->dbdesc_seqnum); 605 thread_add_event (master, seqnumber_mismatch, o6n, 0); 606 return; 607 } 608 break; 609 610 case NBS_LOADING: 611 case NBS_FULL: 612 /* duplicate dbdesc dropped by master */ 613 if (ospf6_dbdesc_is_duplicate (dbdesc, &o6n->last_dd)) 614 { 615 if (IS_OSPF6_DUMP_DBDESC) 616 zlog_info (" duplicate dbdesc, drop"); 617 return; 618 } 619 else 620 { 621 if (IS_OSPF6_DUMP_DBDESC) 622 zlog_info (" not duplicate dbdesc in state %s", 623 ospf6_neighbor_state_string[o6n->state]); 624 thread_add_event (master, seqnumber_mismatch, o6n, 0); 625 return; 626 } 627 break; /* not reached */ 628 629 default: 630 assert (0); 631 break; /* not reached */ 632 } 633 634 /* process LSA headers */ 635 lsa_count = 0; 636 for (lsa_header = (struct ospf6_lsa_header *) (dbdesc + 1); 637 (char *)(lsa_header + 1) <= (char *)dbdesc + length; 638 lsa_header++) 639 { 640 if (ospf6_dbex_check_dbdesc_lsa_header (lsa_header, o6n) < 0) 641 { 642 thread_add_event (master, seqnumber_mismatch, o6n, 0); 643 return; 644 } 645 lsa_count ++; 646 } 647 648 /* increment dbdesc seqnum */ 649 o6n->dbdesc_seqnum++; 650 651 /* cancel transmission/retransmission thread */ 652 if (o6n->thread_send_dbdesc) 653 thread_cancel (o6n->thread_send_dbdesc); 654 o6n->thread_send_dbdesc = (struct thread *) NULL; 655 if (o6n->thread_rxmt_dbdesc) 656 thread_cancel (o6n->thread_rxmt_dbdesc); 657 o6n->thread_rxmt_dbdesc = (struct thread *) NULL; 658 659 /* more bit check */ 660 if (!DD_IS_MBIT_SET (dbdesc->bits) && !DD_IS_MBIT_SET (o6n->dbdesc_bits)) 661 thread_add_event (master, exchange_done, o6n, 0); 662 else 663 o6n->thread_send_dbdesc = 664 thread_add_event (master, ospf6_send_dbdesc, o6n, 0); 665 666 /* save last received dbdesc */ 667 memcpy (&o6n->last_dd, dbdesc, sizeof (struct ospf6_dbdesc)); 668 669 /* statistics */ 670 o6n->lsa_receive[OSPF6_MESSAGE_TYPE_DBDESC] += lsa_count; 671 672 return; 673} 674 675void 676ospf6_process_dbdesc_slave (struct iovec *message, struct ospf6_neighbor *o6n) 677{ 678 struct ospf6_header *ospf6_header; 679 u_int16_t length, lsa_count; 680 struct ospf6_dbdesc *dbdesc; 681 struct ospf6_lsa_header *lsa_header; 682 683 /* caluculate length */ 684 ospf6_header = (struct ospf6_header *) message[0].iov_base; 685 length = ntohs (ospf6_header->len) - sizeof (struct ospf6_header); 686 length = (length < message[1].iov_len ? length : message[1].iov_len); 687 688 /* set database description pointer */ 689 dbdesc = (struct ospf6_dbdesc *) message[1].iov_base; 690 691 switch (o6n->state) 692 { 693 case NBS_DOWN: 694 case NBS_ATTEMPT: 695 case NBS_TWOWAY: 696 return; 697 case NBS_INIT: 698 thread_execute (master, twoway_received, o6n, 0); 699 if (o6n->state != NBS_EXSTART) 700 { 701 return; 702 } 703 /* else fall through to ExStart */ 704 case NBS_EXSTART: 705 if (DD_IS_IBIT_SET (dbdesc->bits) && 706 DD_IS_MBIT_SET (dbdesc->bits) && 707 DD_IS_MSBIT_SET (dbdesc->bits)) 708 { 709 /* Master/Slave bit set to slave */ 710 DD_MSBIT_CLEAR (o6n->dbdesc_bits); 711 /* Initialize bit clear */ 712 DD_IBIT_CLEAR (o6n->dbdesc_bits); 713 /* sequence number set to master's */ 714 o6n->dbdesc_seqnum = ntohl (dbdesc->seqnum); 715 ospf6_neighbor_dbex_init (o6n); 716 717 if (o6n->thread_rxmt_dbdesc) 718 thread_cancel (o6n->thread_rxmt_dbdesc); 719 o6n->thread_rxmt_dbdesc = (struct thread *) NULL; 720 721 thread_add_event (master, negotiation_done, o6n, 0); 722 } 723 else 724 { 725 if (IS_OSPF6_DUMP_DBDESC) 726 zlog_info ("negotiation failed"); 727 return; 728 } 729 break; 730 731 case NBS_EXCHANGE: 732 /* duplicate dbdesc dropped by master */ 733 if (!memcmp (dbdesc, &o6n->last_dd, 734 sizeof (struct ospf6_dbdesc))) 735 { 736 if (IS_OSPF6_DUMP_DBDESC) 737 zlog_info (" duplicate dbdesc, retransmit dbdesc"); 738 739 if (o6n->thread_rxmt_dbdesc) 740 thread_cancel (o6n->thread_rxmt_dbdesc); 741 o6n->thread_rxmt_dbdesc = 742 thread_add_event (master, ospf6_send_dbdesc_rxmt, o6n, 0); 743 744 return; 745 } 746 747 /* check Initialize bit and Master/Slave bit */ 748 if (DDBIT_IS_INITIAL (dbdesc->bits)) 749 { 750 if (IS_OSPF6_DUMP_DBDESC) 751 zlog_info ("Initialize bit mismatch"); 752 thread_add_event (master, seqnumber_mismatch, o6n, 0); 753 return; 754 } 755 if (DDBIT_IS_SLAVE (dbdesc->bits)) 756 { 757 if (IS_OSPF6_DUMP_DBDESC) 758 zlog_info ("Master/Slave bit mismatch"); 759 thread_add_event (master, seqnumber_mismatch, o6n, 0); 760 return; 761 } 762 763 /* dbdesc option check */ 764 if (memcmp (dbdesc->options, o6n->last_dd.options, 765 sizeof (dbdesc->options))) 766 { 767 if (IS_OSPF6_DUMP_DBDESC) 768 zlog_info ("dbdesc option field changed"); 769 thread_add_event (master, seqnumber_mismatch, o6n, 0); 770 return; 771 } 772 773 /* dbdesc sequence number check */ 774 if (ntohl (dbdesc->seqnum) != o6n->dbdesc_seqnum + 1) 775 { 776 if (IS_OSPF6_DUMP_DBDESC) 777 zlog_warn ("*** dbdesc seqnumber mismatch: %d expected", 778 o6n->dbdesc_seqnum + 1); 779 thread_add_event (master, seqnumber_mismatch, o6n, 0); 780 return; 781 } 782 break; 783 784 case NBS_LOADING: 785 case NBS_FULL: 786 /* duplicate dbdesc cause slave to retransmit */ 787 if (ospf6_dbdesc_is_duplicate (dbdesc, &o6n->last_dd)) 788 { 789 if (IS_OSPF6_DUMP_DBDESC) 790 zlog_info (" duplicate dbdesc, retransmit"); 791 792 if (o6n->thread_rxmt_dbdesc) 793 thread_cancel (o6n->thread_rxmt_dbdesc); 794 o6n->thread_rxmt_dbdesc = 795 thread_add_event (master, ospf6_send_dbdesc_rxmt, o6n, 0); 796 797 return; 798 } 799 else 800 { 801 if (IS_OSPF6_DUMP_DBDESC) 802 zlog_info (" not duplicate dbdesc in state %s", 803 ospf6_neighbor_state_string[o6n->state]); 804 thread_add_event (master, seqnumber_mismatch, o6n, 0); 805 return; 806 } 807 break; /* not reached */ 808 809 default: 810 assert (0); 811 break; /* not reached */ 812 } 813 814 /* process LSA headers */ 815 lsa_count = 0; 816 for (lsa_header = (struct ospf6_lsa_header *) (dbdesc + 1); 817 (char *)(lsa_header + 1) <= (char *)dbdesc + length; 818 lsa_header++) 819 { 820 if (ospf6_dbex_check_dbdesc_lsa_header (lsa_header, o6n) < 0) 821 { 822 thread_add_event (master, seqnumber_mismatch, o6n, 0); 823 return; 824 } 825 lsa_count ++; 826 } 827 828 /* set dbdesc seqnum to master's */ 829 o6n->dbdesc_seqnum = ntohl (dbdesc->seqnum); 830 831 if (o6n->thread_send_dbdesc) 832 thread_cancel (o6n->thread_send_dbdesc); 833 o6n->thread_send_dbdesc = 834 thread_add_event (master, ospf6_send_dbdesc, o6n, 0); 835 836 /* save last received dbdesc */ 837 memcpy (&o6n->last_dd, dbdesc, sizeof (struct ospf6_dbdesc)); 838 839 /* statistics */ 840 o6n->lsa_receive[OSPF6_MESSAGE_TYPE_DBDESC] += lsa_count; 841 842 return; 843} 844 845void 846ospf6_process_dbdesc (struct iovec *message, 847 struct in6_addr *src, 848 struct in6_addr *dst, 849 struct ospf6_interface *o6i, 850 u_int32_t router_id) 851{ 852 struct ospf6_header *ospf6_header; 853 u_int16_t length; 854 struct ospf6_neighbor *o6n; 855 struct ospf6_dbdesc *dbdesc; 856 int Im_master = 0; 857 858 /* assert interface */ 859 assert (o6i); 860 861 /* caluculate length */ 862 ospf6_header = (struct ospf6_header *) message[0].iov_base; 863 length = ntohs (ospf6_header->len) - sizeof (struct ospf6_header); 864 length = (length < message[1].iov_len ? length : message[1].iov_len); 865 866 /* set database description pointer */ 867 dbdesc = (struct ospf6_dbdesc *) message[1].iov_base; 868 869 /* find neighbor. if cannot be found, reject this message */ 870 o6n = ospf6_neighbor_lookup (router_id, o6i); 871 if (!o6n) 872 { 873 if (IS_OSPF6_DUMP_DBDESC) 874 zlog_info ("neighbor not found, reject"); 875 return; 876 } 877 878 if (memcmp (src, &o6n->hisaddr, sizeof (struct in6_addr))) 879 { 880 if (IS_OSPF6_DUMP_MESSAGE (ospf6_header->type)) 881 zlog_info ("From Secondary I/F of the neighbor: ignore"); 882 return; 883 } 884 885 /* interface mtu check */ 886 /* xxx */ 887 888 /* check am I master */ 889 Im_master = ospf6_dbdesc_is_master (o6n); 890 if (Im_master < 0) 891 { 892 return; /* can't decide which is master, return */ 893 } 894 895 if (Im_master) 896 ospf6_process_dbdesc_master (message, o6n); 897 else 898 ospf6_process_dbdesc_slave (message, o6n); 899 900 return; 901} 902 903void 904ospf6_process_lsreq (struct iovec *message, 905 struct in6_addr *src, 906 struct in6_addr *dst, 907 struct ospf6_interface *o6i, 908 u_int32_t router_id) 909{ 910 struct ospf6_header *ospf6_header; 911 u_int16_t length; 912 struct ospf6_neighbor *o6n; 913 struct ospf6_lsreq *lsreq; 914 struct iovec response[OSPF6_MESSAGE_IOVEC_SIZE]; 915 struct ospf6_lsa *lsa; 916 unsigned long lsanum = 0; 917 struct ospf6_lsupdate lsupdate; 918 char buf_id[16], buf_router[16], buf_type[16]; 919 920 /* assert interface */ 921 assert (o6i); 922 923 /* caluculate length */ 924 ospf6_header = (struct ospf6_header *) message[0].iov_base; 925 length = ntohs (ospf6_header->len) - sizeof (struct ospf6_header); 926 length = (length < message[1].iov_len ? length : message[1].iov_len); 927 928 /* find neighbor. if cannot be found, reject this message */ 929 o6n = ospf6_neighbor_lookup (router_id, o6i); 930 if (!o6n) 931 { 932 if (IS_OSPF6_DUMP_LSREQ) 933 zlog_info (" neighbor not found, reject"); 934 return; 935 } 936 937 if (memcmp (src, &o6n->hisaddr, sizeof (struct in6_addr))) 938 { 939 if (IS_OSPF6_DUMP_MESSAGE (ospf6_header->type)) 940 zlog_info ("From Secondary I/F of the neighbor: ignore"); 941 return; 942 } 943 944 /* In states other than ExChange, Loading, or Full, the packet 945 should be ignored. */ 946 if (o6n->state != NBS_EXCHANGE && o6n->state != NBS_LOADING 947 && o6n->state != NBS_FULL) 948 { 949 if (IS_OSPF6_DUMP_LSREQ) 950 zlog_info (" neighbor state less than Exchange, reject"); 951 return; 952 } 953 954 /* Initialize response LSUpdate packet */ 955 OSPF6_MESSAGE_CLEAR (response); 956 memset (&lsupdate, 0, sizeof (struct ospf6_lsupdate)); 957 OSPF6_MESSAGE_ATTACH (response, &lsupdate, sizeof (struct ospf6_lsupdate)); 958 959 /* process each request */ 960 lsanum = 0; 961 for (lsreq = (struct ospf6_lsreq *) message[1].iov_base; 962 (char *)(lsreq + 1) <= (char *)(message[1].iov_base + length); 963 lsreq++) 964 { 965 inet_ntop (AF_INET, &lsreq->adv_router, buf_router, sizeof (buf_router)); 966 inet_ntop (AF_INET, &lsreq->id, buf_id, sizeof (buf_id)); 967 968 /* find instance of database copy */ 969 lsa = ospf6_lsdb_lookup (lsreq->type, lsreq->id, lsreq->adv_router, 970 ospf6_lsa_get_scope (lsreq->type, o6i)); 971 972 if (!lsa) 973 { 974 if (IS_OSPF6_DUMP_LSREQ) 975 zlog_info ("BadLSReq: %s requests [%s ID=%s Adv=%s] not found", 976 o6n->str, ospf6_lsa_type_string (lsreq->type, buf_type, 977 sizeof (buf_type)), 978 buf_id, buf_router); 979 thread_add_event (master, bad_lsreq, o6n, 0); 980 return; 981 } 982 983 /* I/F MTU check */ 984 if (sizeof (struct ospf6_header) + sizeof (struct ospf6_lsupdate) 985 + iov_totallen (response) + ntohs (lsa->header->length) 986 > o6i->ifmtu) 987 break; 988 989 OSPF6_MESSAGE_ATTACH (response, lsa->header, ntohs (lsa->header->length)); 990 lsanum++; 991 } 992 993 /* send response LSUpdate to this request */ 994 if (lsanum) 995 { 996 lsupdate.lsupdate_num = htonl (lsanum); 997 998 ospf6_message_send (OSPF6_MESSAGE_TYPE_LSUPDATE, response, 999 &o6n->hisaddr, o6i->if_id); 1000 } 1001 1002 /* statistics */ 1003 o6n->lsa_receive[OSPF6_MESSAGE_TYPE_LSREQ] 1004 += length / sizeof (struct ospf6_lsreq); 1005} 1006 1007void 1008ospf6_process_lsupdate (struct iovec *message, 1009 struct in6_addr *src, 1010 struct in6_addr *dst, 1011 struct ospf6_interface *o6i, 1012 u_int32_t router_id) 1013{ 1014 struct ospf6_header *ospf6_header; 1015 u_int16_t length; 1016 struct ospf6_lsupdate *lsupdate; 1017 struct ospf6_neighbor *o6n; 1018 unsigned long lsanum; 1019 struct ospf6_lsa_header *lsa_header; 1020 1021 /* assert interface */ 1022 assert (o6i); 1023 1024 /* caluculate length */ 1025 ospf6_header = (struct ospf6_header *) message[0].iov_base; 1026 length = ntohs (ospf6_header->len) - sizeof (struct ospf6_header); 1027 length = (length < message[1].iov_len ? length : message[1].iov_len); 1028 1029 /* find neighbor. if cannot be found, reject this message */ 1030 o6n = ospf6_neighbor_lookup (router_id, o6i); 1031 if (! o6n) 1032 { 1033 if (IS_OSPF6_DUMP_LSUPDATE) 1034 zlog_info (" neighbor not found, reject"); 1035 return; 1036 } 1037 1038 if (memcmp (src, &o6n->hisaddr, sizeof (struct in6_addr))) 1039 { 1040 if (IS_OSPF6_DUMP_MESSAGE (ospf6_header->type)) 1041 zlog_info ("From Secondary I/F of the neighbor: ignore"); 1042 return; 1043 } 1044 1045 /* if neighbor state less than ExChange, reject this message */ 1046 if (o6n->state < NBS_EXCHANGE) 1047 { 1048 if (IS_OSPF6_DUMP_LSUPDATE) 1049 zlog_info (" neighbor state less than Exchange, reject"); 1050 return; 1051 } 1052 1053 /* set linkstate update pointer */ 1054 lsupdate = (struct ospf6_lsupdate *) message[1].iov_base; 1055 1056 /* save linkstate update info */ 1057 lsanum = ntohl (lsupdate->lsupdate_num); 1058 1059 /* statistics */ 1060 o6n->ospf6_stat_received_lsa += lsanum; 1061 o6n->ospf6_stat_received_lsupdate++; 1062 1063 /* RFC2328 Section 10.9: When the neighbor responds to these requests 1064 with the proper Link State Update packet(s), the Link state request 1065 list is truncated and a new Link State Request packet is sent. */ 1066 1067 /* process LSAs */ 1068 for (lsa_header = (struct ospf6_lsa_header *) (lsupdate + 1); 1069 lsanum && (char *)lsa_header < (char *)lsupdate + length; 1070 lsanum--) 1071 { 1072 ospf6_dbex_receive_lsa (lsa_header, o6n); 1073 lsa_header = OSPF6_LSA_NEXT (lsa_header); 1074 } 1075 1076 /* send new Link State Request packet if this LS Update packet 1077 can be recognized as a response to our previous LS request */ 1078 if (! IN6_IS_ADDR_MULTICAST(dst) && 1079 (o6n->state == NBS_EXCHANGE || o6n->state == NBS_LOADING)) 1080 thread_add_event (master, ospf6_send_lsreq, o6n, 0); 1081 1082 return; 1083} 1084 1085void 1086ospf6_process_lsack (struct iovec *message, 1087 struct in6_addr *src, 1088 struct in6_addr *dst, 1089 struct ospf6_interface *o6i, 1090 u_int32_t router_id) 1091{ 1092 struct ospf6_header *ospf6_header; 1093 u_int16_t length; 1094 struct ospf6_neighbor *o6n; 1095 struct ospf6_lsa_header *lsa_header; 1096 struct ospf6_lsa *lsa, *copy, *rem; 1097 1098 /* assert interface */ 1099 assert (o6i); 1100 1101 /* caluculate length */ 1102 ospf6_header = (struct ospf6_header *) message[0].iov_base; 1103 length = ntohs (ospf6_header->len) - sizeof (struct ospf6_header); 1104 length = (length < message[1].iov_len ? length : message[1].iov_len); 1105 1106 /* find neighbor. if cannot be found, reject this message */ 1107 o6n = ospf6_neighbor_lookup (router_id, o6i); 1108 if (!o6n) 1109 { 1110 if (IS_OSPF6_DUMP_LSACK) 1111 zlog_info (" neighbor not found, reject"); 1112 return; 1113 } 1114 1115 if (memcmp (src, &o6n->hisaddr, sizeof (struct in6_addr))) 1116 { 1117 if (IS_OSPF6_DUMP_MESSAGE (ospf6_header->type)) 1118 zlog_info ("From Secondary I/F of the neighbor: ignore"); 1119 return; 1120 } 1121 1122 /* if neighbor state less than ExChange, reject this message */ 1123 if (o6n->state < NBS_EXCHANGE) 1124 { 1125 if (IS_OSPF6_DUMP_LSACK) 1126 zlog_info (" neighbor state less than Exchange, reject"); 1127 return; 1128 } 1129 1130 /* process each LSA header */ 1131 for (lsa_header = (struct ospf6_lsa_header *) message[1].iov_base; 1132 (char *)(lsa_header + 1) <= (char *)(message[1].iov_base + length); 1133 lsa_header++) 1134 { 1135 /* find database copy */ 1136 copy = ospf6_lsdb_lookup (lsa_header->type, lsa_header->ls_id, 1137 lsa_header->advrtr, 1138 ospf6_lsa_get_scope (lsa_header->type, o6i)); 1139 1140 /* if no database copy */ 1141 if (!copy) 1142 { 1143 if (IS_OSPF6_DUMP_LSACK) 1144 zlog_info ("no database copy, ignore"); 1145 continue; 1146 } 1147 1148 /* if not on his retrans list */ 1149 rem = ospf6_lsdb_lookup_lsdb (copy->header->type, copy->header->id, 1150 copy->header->adv_router, 1151 o6n->retrans_list); 1152 if (rem == NULL) 1153 { 1154 if (IS_OSPF6_DUMP_LSACK) 1155 zlog_info ("not on %s's retranslist, ignore", o6n->str); 1156 continue; 1157 } 1158 1159 /* create temporary LSA from Ack message */ 1160 lsa = ospf6_lsa_summary_create ((struct ospf6_lsa_header__ *) lsa_header); 1161 1162 /* if the same instance, remove from retrans list. 1163 else, log and ignore */ 1164 if (ospf6_lsa_check_recent (lsa, copy) == 0) 1165 ospf6_neighbor_retrans_remove (rem, o6n); 1166 else 1167 { 1168 /* Log the questionable acknowledgement, 1169 and examine the next one. */ 1170 zlog_warn ("LSAck: questionable acknowledge: LSAs differ"); 1171 } 1172 1173 /* release temporary LSA from Ack message */ 1174 ospf6_lsa_delete (lsa); 1175 } 1176 1177 ospf6_maxage_remover (); 1178 return; 1179} 1180 1181struct { 1182 void (*process) (struct iovec *, struct in6_addr *, struct in6_addr *, 1183 struct ospf6_interface *, u_int32_t); 1184} ospf6_message_process_type [] = 1185{ 1186 {ospf6_process_unknown}, 1187 {ospf6_process_hello}, 1188 {ospf6_process_dbdesc}, 1189 {ospf6_process_lsreq}, 1190 {ospf6_process_lsupdate}, 1191 {ospf6_process_lsack} 1192}; 1193 1194/* process ospf6 protocol header. then, call next process function 1195 for each message type */ 1196static void 1197ospf6_message_process (struct iovec *message, 1198 struct in6_addr *src, 1199 struct in6_addr *dst, 1200 struct ospf6_interface *o6i) 1201{ 1202 struct ospf6_header *ospf6_header = NULL; 1203 u_char type; 1204 u_int32_t router_id; 1205 char srcname[64]; 1206 1207 assert (o6i); 1208 assert (src); 1209 assert (dst); 1210 1211 /* set ospf6_hdr pointer to head of buffer */ 1212 ospf6_header = (struct ospf6_header *) message[0].iov_base; 1213 1214 /* version check */ 1215 if (ospf6_header->version != OSPF6_VERSION) 1216 { 1217 if (IS_OSPF6_DUMP_MESSAGE (ospf6_header->type)) 1218 zlog_info ("version mismatch, drop"); 1219 return; 1220 } 1221 1222 /* area id check */ 1223 if (ospf6_header->area_id != o6i->area->area_id) 1224 { 1225 if (ospf6_header->area_id == 0) 1226 { 1227 if (IS_OSPF6_DUMP_MESSAGE (ospf6_header->type)) 1228 zlog_info ("virtual link not yet, drop"); 1229 return; 1230 } 1231 1232 if (IS_OSPF6_DUMP_MESSAGE (ospf6_header->type)) 1233 zlog_info ("area id mismatch, drop"); 1234 return; 1235 } 1236 1237 /* instance id check */ 1238 if (ospf6_header->instance_id != o6i->instance_id) 1239 { 1240 if (IS_OSPF6_DUMP_MESSAGE (ospf6_header->type)) 1241 zlog_info ("instance id mismatch, drop"); 1242 return; 1243 } 1244 1245 /* router id check */ 1246 router_id = ospf6_header->router_id; 1247 if (ospf6_header->router_id == o6i->area->ospf6->router_id) 1248 { 1249 inet_ntop (AF_INET6, src, srcname, sizeof (srcname)); 1250 zlog_warn ("*** Router-ID mismatch: from %s on %s", 1251 srcname, o6i->interface->name); 1252 return; 1253 } 1254 1255 /* message type check */ 1256 type = (ospf6_header->type >= OSPF6_MESSAGE_TYPE_MAX ? 1257 OSPF6_MESSAGE_TYPE_UNKNOWN : ospf6_header->type); 1258 1259 /* octet statistics relies on some asumption: 1260 on ethernet, no IPv6 Extention header, etc */ 1261#define OSPF6_IP6_HEADER_SIZE 40 1262#define OSPF6_ETHER_HEADER_SIZE 14 1263 o6i->message_stat[type].recv++; 1264 o6i->message_stat[type].recv_octet += ntohs (ospf6_header->len) 1265 + OSPF6_IP6_HEADER_SIZE + OSPF6_ETHER_HEADER_SIZE; 1266 1267 /* futher process */ 1268 (*ospf6_message_process_type[type].process) (&message[0], src, dst, o6i, router_id); 1269 1270 return; 1271} 1272 1273int 1274ospf6_receive (struct thread *thread) 1275{ 1276 int sockfd; 1277 struct in6_addr src, dst; 1278 unsigned int ifindex; 1279 struct iovec message[OSPF6_MESSAGE_IOVEC_SIZE]; 1280 struct ospf6_header ospf6_header; 1281 char buffer[OSPF6_MESSAGE_RECEIVE_BUFSIZE]; 1282 struct ospf6_interface *o6i; 1283 char srcname[64], dstname[64]; 1284 unsigned char type; 1285 1286 /* get socket */ 1287 sockfd = THREAD_FD (thread); 1288 1289 /* initialize */ 1290 OSPF6_MESSAGE_CLEAR (message); 1291 memset (&ospf6_header, 0, sizeof (struct ospf6_header)); 1292 1293 OSPF6_MESSAGE_ATTACH (message, &ospf6_header, sizeof (struct ospf6_header)); 1294 OSPF6_MESSAGE_ATTACH (message, buffer, OSPF6_MESSAGE_RECEIVE_BUFSIZE); 1295 1296 /* receive message */ 1297 ospf6_recvmsg (&src, &dst, &ifindex, message); 1298 1299 type = (OSPF6_MESSAGE_TYPE_UNKNOWN < ospf6_header.type && 1300 ospf6_header.type <= OSPF6_MESSAGE_TYPE_LSACK ? 1301 ospf6_header.type : OSPF6_MESSAGE_TYPE_UNKNOWN); 1302 o6i = ospf6_interface_lookup_by_index (ifindex); 1303 if (!o6i || !o6i->area) 1304 { 1305 zlog_warn ("*** received interface ospf6 disabled"); 1306 thread_add_read (master, ospf6_receive, NULL, sockfd); 1307 return 0; 1308 } 1309 1310 /* log */ 1311 if (IS_OSPF6_DUMP_MESSAGE (type)) 1312 { 1313 inet_ntop (AF_INET6, &dst, dstname, sizeof (dstname)); 1314 inet_ntop (AF_INET6, &src, srcname, sizeof (srcname)); 1315 zlog_info ("Receive %s on %s", 1316 ospf6_message_type_string[type], o6i->interface->name); 1317 zlog_info (" %s -> %s", srcname, dstname); 1318 ospf6_message_log (message); 1319 } 1320 1321 /* if not passive, process message */ 1322 if (! CHECK_FLAG (o6i->flag, OSPF6_INTERFACE_FLAG_PASSIVE)) 1323 ospf6_message_process (message, &src, &dst, o6i); 1324 else if (IS_OSPF6_DUMP_MESSAGE (type)) 1325 zlog_info ("Ignore message on passive interface %s", 1326 o6i->interface->name); 1327 1328 /* add next read thread */ 1329 thread_add_read (master, ospf6_receive, NULL, sockfd); 1330 1331 return 0; 1332} 1333 1334 1335/* send section */ 1336int 1337ospf6_message_length (struct iovec *message) 1338{ 1339 int i, length = 0; 1340 for (i = 0; i < OSPF6_MESSAGE_IOVEC_SIZE; i++) 1341 { 1342 if (message[i].iov_base == NULL && message[i].iov_len == 0) 1343 break; 1344 length += message[i].iov_len; 1345 } 1346 return length; 1347} 1348#define OSPF6_MESSAGE_LENGTH(msg) \ 1349(ospf6_message_length (msg)) 1350 1351void 1352ospf6_message_send (unsigned char type, struct iovec *msg, 1353 struct in6_addr *dst, u_int ifindex) 1354{ 1355 struct ospf6_interface *o6i; 1356 struct ospf6_header ospf6_header; 1357 char dst_name[64], src_name[64]; 1358 struct iovec message[OSPF6_MESSAGE_IOVEC_SIZE]; 1359 int msg_len; 1360 1361 /* ospf6 interface lookup */ 1362 o6i = ospf6_interface_lookup_by_index (ifindex); 1363 assert (o6i); 1364 1365 msg_len = OSPF6_MESSAGE_LENGTH (msg); 1366 1367 /* I/F MTU check */ 1368#if 0 1369 if (msg_len + sizeof (struct ospf6_header) >= o6i->interface->mtu) 1370#else 1371 if (msg_len + sizeof (struct ospf6_header) >= o6i->ifmtu) 1372#endif 1373 { 1374 /* If Interface MTU is 0, save the case 1375 since zebra had been failed to get MTU from Kernel */ 1376 if (o6i->interface->mtu != 0) 1377 { 1378 zlog_warn ("Message: Send failed on %s: exceeds I/F MTU", 1379 o6i->interface->name); 1380 zlog_warn ("Message: while sending %s: Len:%d MTU:%d", 1381 ospf6_message_type_string[type], 1382 msg_len + sizeof (struct ospf6_header), 1383 o6i->ifmtu); 1384 return; 1385 } 1386 else 1387 { 1388 zlog_warn ("Message: I/F MTU check ignored on %s", 1389 o6i->interface->name); 1390 } 1391 } 1392 1393 /* Initialize */ 1394 OSPF6_MESSAGE_CLEAR (message); 1395 1396 /* set OSPF header */ 1397 memset (&ospf6_header, 0, sizeof (ospf6_header)); 1398 ospf6_header.version = OSPF6_VERSION; 1399 ospf6_header.type = type; 1400 ospf6_header.len = htons (msg_len + sizeof (struct ospf6_header)); 1401 ospf6_header.router_id = ospf6->router_id; 1402 ospf6_header.area_id = o6i->area->area_id; 1403 /* checksum is calculated by kernel */ 1404 ospf6_header.instance_id = o6i->instance_id; 1405 ospf6_header.reserved = 0; 1406 OSPF6_MESSAGE_ATTACH (message, &ospf6_header, sizeof (struct ospf6_header)); 1407 1408 /* Attach rest to message */ 1409 OSPF6_MESSAGE_JOIN (message, msg); 1410 1411 /* statistics */ 1412 if (type >= OSPF6_MESSAGE_TYPE_MAX) 1413 type = OSPF6_MESSAGE_TYPE_UNKNOWN; 1414 o6i->message_stat[type].send++; 1415 o6i->message_stat[type].send_octet += ntohs (ospf6_header.len); 1416 1417 /* log */ 1418 if (IS_OSPF6_DUMP_MESSAGE (type)) 1419 { 1420 inet_ntop (AF_INET6, dst, dst_name, sizeof (dst_name)); 1421 if (o6i->lladdr) 1422 inet_ntop (AF_INET6, o6i->lladdr, src_name, sizeof (src_name)); 1423 else 1424 memcpy (src_name, "Unknown", sizeof (src_name)); 1425 zlog_info ("Send %s on %s", 1426 ospf6_message_type_string[type], o6i->interface->name); 1427 zlog_info (" %s -> %s", src_name, dst_name); 1428 ospf6_message_log (message); 1429 } 1430 1431 /* send message */ 1432 ospf6_sendmsg (o6i->lladdr, dst, &ifindex, message); 1433} 1434 1435 1436int 1437ospf6_send_hello (struct thread *thread) 1438{ 1439 listnode n; 1440 struct ospf6_interface *o6i; 1441 struct ospf6_neighbor *o6n; 1442 struct in6_addr dst; 1443 struct iovec message[OSPF6_MESSAGE_IOVEC_SIZE]; 1444 struct ospf6_hello hello; 1445 char router_buffer[1024]; /* xxx */ 1446 u_int router_size; 1447 1448 /* which ospf6 interface to send */ 1449 o6i = (struct ospf6_interface *) THREAD_ARG (thread); 1450 o6i->thread_send_hello = (struct thread *) NULL; 1451 1452 /* assure interface is up */ 1453 if (o6i->state <= IFS_DOWN) 1454 { 1455 if (IS_OSPF6_DUMP_HELLO) 1456 zlog_warn ("Send HELLO Failed: Interface not enabled: %s", 1457 o6i->interface->name); 1458 return 0; 1459 } 1460 1461 /* clear message buffer */ 1462 OSPF6_MESSAGE_CLEAR (message); 1463 1464 /* set Hello fields */ 1465 hello.interface_id = htonl (o6i->if_id); 1466 hello.rtr_pri = o6i->priority; 1467 memcpy (hello.options, o6i->area->options, sizeof (hello.options)); 1468 hello.hello_interval = htons (o6i->hello_interval); 1469 hello.router_dead_interval = htons (o6i->dead_interval); 1470 hello.dr = o6i->dr; 1471 hello.bdr = o6i->bdr; 1472 OSPF6_MESSAGE_ATTACH (message, &hello, sizeof (struct ospf6_hello)); 1473 1474 /* set neighbor router id */ 1475 router_size = 0; 1476 for (n = listhead (o6i->neighbor_list); n; nextnode (n)) 1477 { 1478 o6n = (struct ospf6_neighbor *) getdata (n); 1479 1480 if (o6n->state < NBS_INIT) 1481 continue; 1482 1483 if (router_size + sizeof (o6n->router_id) > sizeof (router_buffer)) 1484 { 1485 zlog_warn ("Send HELLO: Buffer shortage on %s", 1486 o6i->interface->name); 1487 break; 1488 } 1489 1490 /* Copy Router-ID to Buffer */ 1491 memcpy (router_buffer + router_size, &o6n->router_id, 1492 sizeof (o6n->router_id)); 1493 router_size += sizeof (o6n->router_id); 1494 } 1495 OSPF6_MESSAGE_ATTACH (message, router_buffer, router_size); 1496 1497 /* set destionation */ 1498 inet_pton (AF_INET6, ALLSPFROUTERS6, &dst); 1499 1500 /* send hello */ 1501 ospf6_message_send (OSPF6_MESSAGE_TYPE_HELLO, message, &dst, 1502 o6i->interface->ifindex); 1503 1504 /* set next timer thread */ 1505 o6i->thread_send_hello = thread_add_timer (master, ospf6_send_hello, 1506 o6i, o6i->hello_interval); 1507 1508 return 0; 1509} 1510 1511void 1512ospf6_dbdesc_seqnum_init (struct ospf6_neighbor *o6n) 1513{ 1514 struct timeval tv; 1515 1516 if (gettimeofday (&tv, (struct timezone *) NULL) < 0) 1517 tv.tv_sec = 1; 1518 1519 o6n->dbdesc_seqnum = tv.tv_sec; 1520 1521 if (IS_OSPF6_DUMP_DBDESC) 1522 zlog_info ("set dbdesc seqnum %d for %s", o6n->dbdesc_seqnum, o6n->str); 1523} 1524 1525int 1526ospf6_send_dbdesc_rxmt (struct thread *thread) 1527{ 1528 struct ospf6_lsdb_node node; 1529 struct ospf6_neighbor *o6n; 1530 struct iovec message[OSPF6_MESSAGE_IOVEC_SIZE]; 1531 struct ospf6_lsa *lsa; 1532 struct ospf6_lsa_header *lsa_header; 1533 struct ospf6_dbdesc dbdesc; 1534 1535 o6n = (struct ospf6_neighbor *) THREAD_ARG (thread); 1536 assert (o6n); 1537 1538 /* clear thread */ 1539 o6n->thread_rxmt_dbdesc = (struct thread *) NULL; 1540 1541 /* if state less than ExStart, do nothing */ 1542 if (o6n->state < NBS_EXSTART) 1543 return 0; 1544 1545 OSPF6_MESSAGE_CLEAR (message); 1546 1547 /* set dbdesc */ 1548 memcpy (dbdesc.options, o6n->ospf6_interface->area->options, 1549 sizeof (dbdesc.options)); 1550 dbdesc.ifmtu = htons (o6n->ospf6_interface->interface->mtu); 1551 dbdesc.bits = o6n->dbdesc_bits; 1552 dbdesc.seqnum = htonl (o6n->dbdesc_seqnum); 1553 OSPF6_MESSAGE_ATTACH (message, &dbdesc, sizeof (struct ospf6_dbdesc)); 1554 1555 /* if this is not initial, set LSA summary to dbdesc */ 1556 if (! DD_IS_IBIT_SET (o6n->dbdesc_bits)) 1557 { 1558 for (ospf6_lsdb_head (&node, o6n->dbdesc_list); 1559 ! ospf6_lsdb_is_end (&node); ospf6_lsdb_next (&node)) 1560 { 1561 lsa = node.lsa; 1562 1563 /* xxx, no MTU check: no support for Dynamic MTU change */ 1564 1565 /* set age and add InfTransDelay */ 1566 ospf6_lsa_age_update_to_send (lsa, o6n->ospf6_interface->transdelay); 1567 1568 /* set LSA summary to send buffer */ 1569 lsa_header = (struct ospf6_lsa_header *) lsa->lsa_hdr; 1570 OSPF6_MESSAGE_ATTACH (message, lsa_header, 1571 sizeof (struct ospf6_lsa_header)); 1572 } 1573 } 1574 1575 /* send dbdesc */ 1576 ospf6_message_send (OSPF6_MESSAGE_TYPE_DBDESC, message, &o6n->hisaddr, 1577 o6n->ospf6_interface->interface->ifindex); 1578 1579 /* if master, set futher retransmission */ 1580 if (DD_IS_MSBIT_SET (o6n->dbdesc_bits)) 1581 o6n->thread_rxmt_dbdesc = 1582 thread_add_timer (master, ospf6_send_dbdesc_rxmt, 1583 o6n, o6n->ospf6_interface->rxmt_interval); 1584 1585 /* statistics */ 1586 o6n->ospf6_stat_retrans_dbdesc++; 1587 1588 return 0; 1589} 1590 1591int 1592ospf6_send_dbdesc (struct thread *thread) 1593{ 1594 struct ospf6_neighbor *o6n; 1595 struct ospf6_lsa *lsa; 1596 struct iovec message[OSPF6_MESSAGE_IOVEC_SIZE]; 1597 struct ospf6_dbdesc dbdesc; 1598 struct ospf6_lsdb_node node; 1599 1600 o6n = (struct ospf6_neighbor *) THREAD_ARG (thread); 1601 assert (o6n); 1602 1603 /* clear thread */ 1604 o6n->thread_send_dbdesc = (struct thread *) NULL; 1605 if (o6n->thread_rxmt_dbdesc) 1606 thread_cancel (o6n->thread_rxmt_dbdesc); 1607 o6n->thread_rxmt_dbdesc = (struct thread *) NULL; 1608 1609 /* if state less than ExStart, do nothing */ 1610 if (o6n->state < NBS_EXSTART) 1611 return 0; 1612 1613 OSPF6_MESSAGE_CLEAR (message); 1614 OSPF6_MESSAGE_ATTACH (message, &dbdesc, sizeof (struct ospf6_dbdesc)); 1615 1616 /* clear previous LSA summary sent */ 1617 ospf6_lsdb_remove_all (o6n->dbdesc_list); 1618 assert (o6n->dbdesc_list->count == 0); 1619 1620 /* if this is not initial, set LSA summary to dbdesc */ 1621 if (! DD_IS_IBIT_SET (o6n->dbdesc_bits)) 1622 { 1623 for (ospf6_lsdb_head (&node, o6n->summary_list); 1624 ! ospf6_lsdb_is_end (&node); 1625 ospf6_lsdb_next (&node)) 1626 { 1627 lsa = node.lsa; 1628 1629 /* MTU check */ 1630 if (OSPF6_MESSAGE_LENGTH (message) 1631 + sizeof (struct ospf6_lsa_header) 1632 + sizeof (struct ospf6_header) 1633 > o6n->ospf6_interface->ifmtu) 1634 break; 1635 1636 /* debug */ 1637 if (IS_OSPF6_DUMP_DBDESC) 1638 zlog_info ("Include DbDesc: %s", lsa->str); 1639 1640 /* attach to dbdesclist */ 1641 ospf6_neighbor_dbdesc_add (lsa, o6n); 1642 /* detach from summarylist */ 1643 ospf6_neighbor_summary_remove (lsa, o6n); 1644 1645 /* set age and add InfTransDelay */ 1646 ospf6_lsa_age_update_to_send (lsa, o6n->ospf6_interface->transdelay); 1647 1648 /* set LSA summary to send buffer */ 1649 OSPF6_MESSAGE_ATTACH (message, lsa->header, 1650 sizeof (struct ospf6_lsa_header)); 1651 } 1652 1653 if (o6n->summary_list->count == 0) 1654 { 1655 /* Clear more bit */ 1656 DD_MBIT_CLEAR (o6n->dbdesc_bits); 1657 1658 /* slave must schedule ExchangeDone on sending, here */ 1659 if (! DD_IS_MSBIT_SET (o6n->dbdesc_bits)) 1660 { 1661 if (! DD_IS_MBIT_SET (o6n->dbdesc_bits) && 1662 ! DD_IS_MBIT_SET (o6n->last_dd.bits)) 1663 thread_add_event (master, exchange_done, o6n, 0); 1664 } 1665 } 1666 } 1667 1668 /* if this is initial, set seqnum */ 1669 if (DDBIT_IS_INITIAL (o6n->dbdesc_bits)) 1670 ospf6_dbdesc_seqnum_init (o6n); 1671 1672 /* set dbdesc */ 1673 memcpy (dbdesc.options, o6n->ospf6_interface->area->options, 1674 sizeof (dbdesc.options)); 1675 dbdesc.ifmtu = htons (o6n->ospf6_interface->interface->mtu); 1676 dbdesc.bits = o6n->dbdesc_bits; 1677 dbdesc.seqnum = htonl (o6n->dbdesc_seqnum); 1678 1679 /* send dbdesc */ 1680 ospf6_message_send (OSPF6_MESSAGE_TYPE_DBDESC, message, &o6n->hisaddr, 1681 o6n->ospf6_interface->interface->ifindex); 1682 1683 /* if master, set retransmission */ 1684 if (DD_IS_MSBIT_SET (o6n->dbdesc_bits)) 1685 o6n->thread_rxmt_dbdesc = 1686 thread_add_timer (master, ospf6_send_dbdesc_rxmt, 1687 o6n, o6n->ospf6_interface->rxmt_interval); 1688 1689 /* statistics */ 1690 o6n->lsa_send[OSPF6_MESSAGE_TYPE_DBDESC] += o6n->dbdesc_list->count; 1691 1692 return 0; 1693} 1694 1695int 1696ospf6_send_lsreq_rxmt (struct thread *thread) 1697{ 1698 struct ospf6_neighbor *o6n; 1699 1700 o6n = (struct ospf6_neighbor *) THREAD_ARG (thread); 1701 assert (o6n); 1702 1703 o6n->thread_rxmt_lsreq = (struct thread *) NULL; 1704 o6n->thread_send_lsreq = thread_add_event (master, ospf6_send_lsreq, o6n, 0); 1705 return 0; 1706} 1707 1708int 1709ospf6_send_lsreq (struct thread *thread) 1710{ 1711 struct ospf6_neighbor *o6n; 1712 struct iovec message[OSPF6_MESSAGE_IOVEC_SIZE]; 1713 struct ospf6_lsreq lsreq[OSPF6_MESSAGE_IOVEC_SIZE]; 1714 struct ospf6_lsa *lsa; 1715 struct ospf6_lsdb_node node; 1716 int i; 1717 1718 o6n = (struct ospf6_neighbor *) THREAD_ARG (thread); 1719 assert (o6n); 1720 1721 /* LSReq will be send only in ExStart or Loading */ 1722 if (o6n->state != NBS_EXCHANGE && o6n->state != NBS_LOADING) 1723 return 0; 1724 1725 /* clear thread */ 1726 o6n->thread_send_lsreq = (struct thread *) NULL; 1727 if (o6n->thread_rxmt_lsreq) 1728 thread_cancel (o6n->thread_rxmt_lsreq); 1729 o6n->thread_rxmt_lsreq = (struct thread *) NULL; 1730 1731 /* schedule loading_done if request list is empty */ 1732 if (o6n->request_list->count == 0) 1733 { 1734 thread_add_event (master, loading_done, o6n, 0); 1735 return 0; 1736 } 1737 1738 /* clear message buffer */ 1739 OSPF6_MESSAGE_CLEAR (message); 1740 1741 i = 0; 1742 for (ospf6_lsdb_head (&node, o6n->request_list); 1743 ! ospf6_lsdb_is_end (&node); ospf6_lsdb_next (&node)) 1744 { 1745 lsa = node.lsa; 1746 1747 /* Buffer Overflow */ 1748 if (i >= OSPF6_MESSAGE_IOVEC_SIZE) 1749 break; 1750 1751 /* I/F MTU check */ 1752 if (OSPF6_MESSAGE_LENGTH (message) 1753 + sizeof (struct ospf6_lsreq) 1754 + sizeof (struct ospf6_header) 1755 > o6n->ospf6_interface->ifmtu) 1756 break; 1757 1758 lsreq[i].mbz = 0; 1759 lsreq[i].type = lsa->header->type; 1760 lsreq[i].id = lsa->header->id; 1761 lsreq[i].adv_router = lsa->header->adv_router; 1762 1763 OSPF6_MESSAGE_ATTACH (message, &lsreq[i], sizeof (struct ospf6_lsreq)); 1764 i++; 1765 } 1766 1767 ospf6_message_send (OSPF6_MESSAGE_TYPE_LSREQ, message, &o6n->hisaddr, 1768 o6n->ospf6_interface->interface->ifindex); 1769 1770 /* set retransmit thread */ 1771 o6n->thread_rxmt_lsreq = 1772 thread_add_timer (master, ospf6_send_lsreq_rxmt, 1773 o6n, o6n->ospf6_interface->rxmt_interval); 1774 1775 /* statistics */ 1776 o6n->lsa_send[OSPF6_MESSAGE_TYPE_LSREQ] += i; 1777 1778 return 0; 1779} 1780 1781/* Send LSUpdate directly to the neighbor, from his retransmission list */ 1782int 1783ospf6_send_lsupdate_rxmt (struct thread *thread) 1784{ 1785 struct ospf6_neighbor *o6n; 1786 struct iovec message[OSPF6_MESSAGE_IOVEC_SIZE]; 1787 struct ospf6_lsupdate lsupdate; 1788 struct ospf6_lsa *lsa; 1789 struct ospf6_lsdb_node node; 1790 1791 o6n = (struct ospf6_neighbor *) THREAD_ARG (thread); 1792 assert (o6n); 1793 1794 o6n->send_update = (struct thread *) NULL; 1795 1796 if (o6n->ospf6_interface->state <= IFS_WAITING) 1797 return -1; 1798 1799 /* clear message buffer */ 1800 OSPF6_MESSAGE_CLEAR (message); 1801 1802 /* set lsupdate header */ 1803 lsupdate.lsupdate_num = 0; /* set gradually */ 1804 OSPF6_MESSAGE_ATTACH (message, &lsupdate, sizeof (struct ospf6_lsupdate)); 1805 1806 /* for each LSA listed on retransmission-list */ 1807 for (ospf6_lsdb_head (&node, o6n->retrans_list); 1808 ! ospf6_lsdb_is_end (&node); 1809 ospf6_lsdb_next (&node)) 1810 { 1811 lsa = node.lsa; 1812 1813 /* I/F MTU check */ 1814 if (OSPF6_MESSAGE_LENGTH (message) 1815 + sizeof (struct ospf6_lsupdate) 1816 + sizeof (struct ospf6_header) 1817 + ntohs (lsa->header->length) 1818 > o6n->ospf6_interface->ifmtu) 1819 break; 1820 1821 ospf6_lsa_age_update_to_send (lsa, o6n->ospf6_interface->transdelay); 1822 OSPF6_MESSAGE_ATTACH (message, lsa->header, ntohs (lsa->header->length)); 1823 lsupdate.lsupdate_num++; 1824 } 1825 1826 /* check and correct lsupdate */ 1827 if (lsupdate.lsupdate_num == 0) 1828 return 0; 1829 lsupdate.lsupdate_num = htonl (lsupdate.lsupdate_num); 1830 1831 /* statistics */ 1832 o6n->ospf6_stat_retrans_lsupdate++; 1833 1834 ospf6_message_send (OSPF6_MESSAGE_TYPE_LSUPDATE, message, 1835 &o6n->hisaddr, o6n->ospf6_interface->if_id); 1836 1837 o6n->send_update = thread_add_timer (master, ospf6_send_lsupdate_rxmt, o6n, 1838 o6n->ospf6_interface->rxmt_interval); 1839 return 0; 1840} 1841 1842/* Send LSUpdate containing one LSA directly to the neighbor. 1843 This is "implied acknowledgement" */ 1844void 1845ospf6_send_lsupdate_direct (struct ospf6_lsa *lsa, struct ospf6_neighbor *o6n) 1846{ 1847 struct iovec message[OSPF6_MESSAGE_IOVEC_SIZE]; 1848 struct ospf6_lsupdate lsupdate; 1849 int lsa_len; 1850 1851 /* clear message buffer */ 1852 OSPF6_MESSAGE_CLEAR (message); 1853 1854 /* set lsupdate header */ 1855 lsupdate.lsupdate_num = ntohl (1); 1856 OSPF6_MESSAGE_ATTACH (message, &lsupdate, sizeof (struct ospf6_lsupdate)); 1857 1858 /* set one LSA */ 1859 lsa_len = ntohs (lsa->lsa_hdr->lsh_len); 1860 ospf6_lsa_age_update_to_send (lsa, o6n->ospf6_interface->transdelay); 1861 OSPF6_MESSAGE_ATTACH (message, lsa->lsa_hdr, lsa_len); 1862 1863 ospf6_message_send (OSPF6_MESSAGE_TYPE_LSUPDATE, message, &o6n->hisaddr, 1864 o6n->ospf6_interface->if_id); 1865} 1866 1867/* Send LSUpdate containing one LSA by multicast. 1868 On non-broadcast link, send it to each neighbor by unicast. 1869 This is ordinary flooding */ 1870void 1871ospf6_send_lsupdate_flood (struct ospf6_lsa *lsa, struct ospf6_interface *o6i) 1872{ 1873 struct iovec message[OSPF6_MESSAGE_IOVEC_SIZE]; 1874 struct ospf6_lsupdate lsupdate; 1875 struct in6_addr dst; 1876 int lsa_len; 1877 1878 /* clear message buffer */ 1879 OSPF6_MESSAGE_CLEAR (message); 1880 1881 /* set lsupdate header */ 1882 lsupdate.lsupdate_num = ntohl (1); 1883 OSPF6_MESSAGE_ATTACH (message, &lsupdate, sizeof (struct ospf6_lsupdate)); 1884 1885 /* set one LSA */ 1886 lsa_len = ntohs (lsa->lsa_hdr->lsh_len); 1887 ospf6_lsa_age_update_to_send (lsa, o6i->transdelay); 1888 OSPF6_MESSAGE_ATTACH (message, lsa->lsa_hdr, lsa_len); 1889 1890 if (if_is_broadcast (o6i->interface)) 1891 { 1892 /* set destination */ 1893 if (o6i->state == IFS_DR || o6i->state == IFS_BDR) 1894 inet_pton (AF_INET6, ALLSPFROUTERS6, &dst); 1895 else 1896 inet_pton (AF_INET6, ALLDROUTERS6, &dst); 1897 } 1898 else 1899 { 1900 /* IPv6 relies on link local multicast */ 1901 inet_pton (AF_INET6, ALLSPFROUTERS6, &dst); 1902 } 1903 1904 ospf6_message_send (OSPF6_MESSAGE_TYPE_LSUPDATE, message, &dst, 1905 o6i->if_id); 1906} 1907 1908int 1909ospf6_send_lsack_delayed (struct thread *thread) 1910{ 1911 struct ospf6_interface *o6i; 1912 struct iovec message[MAXIOVLIST]; 1913 struct ospf6_lsa *lsa; 1914 struct ospf6_lsdb_node node; 1915 1916 o6i = THREAD_ARG (thread); 1917 assert (o6i); 1918 1919 o6i->thread_send_lsack_delayed = (struct thread *) NULL; 1920 1921 if (o6i->state <= IFS_WAITING) 1922 return 0; 1923 1924 if (o6i->ack_list->count == 0) 1925 return 0; 1926 1927 iov_clear (message, MAXIOVLIST); 1928 1929 for (ospf6_lsdb_head (&node, o6i->ack_list); 1930 ! ospf6_lsdb_is_end (&node); 1931 ospf6_lsdb_next (&node)) 1932 { 1933 lsa = node.lsa; 1934 if (IS_OVER_MTU (message, o6i->ifmtu, sizeof (struct ospf6_lsa_hdr))) 1935 break; 1936 1937 OSPF6_MESSAGE_ATTACH (message, lsa->header, 1938 sizeof (struct ospf6_lsa_header)); 1939 ospf6_interface_delayed_ack_remove (lsa, o6i); 1940 } 1941 1942 /* statistics */ 1943 o6i->ospf6_stat_delayed_lsack++; 1944 1945 switch (o6i->state) 1946 { 1947 case IFS_DR: 1948 case IFS_BDR: 1949 ospf6_message_send (OSPF6_MESSAGE_TYPE_LSACK, message, 1950 &allspfrouters6.sin6_addr, o6i->if_id); 1951 break; 1952 default: 1953 ospf6_message_send (OSPF6_MESSAGE_TYPE_LSACK, message, 1954 &alldrouters6.sin6_addr, o6i->if_id); 1955 break; 1956 } 1957 1958 iov_clear (message, MAXIOVLIST); 1959 return 0; 1960} 1961 1962