1/* 2 * Copyright (C) 2002 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 24static int intra_index; 25#define IS_OSPF6_DUMP_INTRA (ospf6_dump_is_on (intra_index)) 26 27#define ADD 0 28#define REMOVE 1 29 30static void 31ospf6_intra_route_calculate (int type, struct ospf6_lsa *lsa, 32 struct ospf6_route_req *topo_entry) 33{ 34 struct ospf6_intra_area_prefix_lsa *intra_prefix; 35 char *start, *end; 36 struct ospf6_prefix *ospf6_prefix; 37 struct ospf6_route_req request; 38 struct ospf6_area *area; 39 40 intra_prefix = OSPF6_LSA_HEADER_END (lsa->header); 41 42 area = lsa->scope; 43 assert (area); 44 45 start = (char *) (intra_prefix + 1); 46 end = (char *) lsa->header + ntohs (lsa->header->length); 47 for (ospf6_prefix = (struct ospf6_prefix *) start; 48 (char *) ospf6_prefix < end; 49 ospf6_prefix = OSPF6_NEXT_PREFIX (ospf6_prefix)) 50 { 51 memset (&request, 0, sizeof (request)); 52 53 request.route.type = OSPF6_DEST_TYPE_NETWORK; 54 request.route.prefix.family = AF_INET6; 55 request.route.prefix.prefixlen = ospf6_prefix->prefix_length; 56 ospf6_prefix_in6_addr (ospf6_prefix, &request.route.prefix.u.prefix6); 57 58 request.path.type = OSPF6_PATH_TYPE_INTRA; 59 request.path.area_id = area->area_id; 60 request.path.origin.type = lsa->header->type; 61 request.path.origin.id = lsa->header->id; 62 request.path.origin.adv_router = lsa->header->adv_router; 63 request.path.cost = topo_entry->path.cost + 64 ntohs (ospf6_prefix->prefix_metric); 65 request.path.capability[0] = topo_entry->path.capability[0]; 66 request.path.capability[1] = topo_entry->path.capability[1]; 67 request.path.capability[2] = topo_entry->path.capability[2]; 68 69 memcpy (&request.nexthop.address, &topo_entry->nexthop.address, 70 sizeof (request.nexthop.address)); 71 request.nexthop.ifindex = topo_entry->nexthop.ifindex; 72 73 if (type == ADD) 74 ospf6_route_add (&request, area->route_table); 75 else if (type == REMOVE) 76 ospf6_route_remove (&request, area->route_table); 77 else 78 assert (0); 79 } 80} 81 82int 83ospf6_intra_prefix_database_hook_remove (void *data) 84{ 85 struct ospf6_lsa *lsa = data; 86 struct ospf6_area *area; 87 struct ospf6_intra_area_prefix_lsa *iap; 88 struct prefix_ls prefix_ls; 89 struct ospf6_route_req topo_entry; 90 91 if (lsa->header->type != htons (OSPF6_LSA_TYPE_INTRA_PREFIX)) 92 return 0; 93 94 area = (struct ospf6_area *) lsa->scope; 95 assert (area); 96 97 if (IS_OSPF6_DUMP_INTRA) 98 zlog_info ("INTRA: area %s remove: %s", area->str, lsa->str); 99 100 iap = OSPF6_LSA_HEADER_END (lsa->header); 101 memset (&prefix_ls, 0, sizeof (prefix_ls)); 102 prefix_ls.prefixlen = 64; 103 prefix_ls.adv_router.s_addr = iap->refer_advrtr; 104 prefix_ls.id.s_addr = iap->refer_lsid; 105 106 if (iap->refer_lstype == htons (OSPF6_LSA_TYPE_ROUTER) && 107 iap->refer_lsid != htonl (0)) 108 { 109 zlog_warn ("SPF: Malformed ID %lu of Router reference in %s", 110 (u_long) ntohl (iap->refer_lsid), lsa->str); 111 prefix_ls.id.s_addr = htonl (0); 112 } 113 114 ospf6_route_lookup (&topo_entry, (struct prefix *) &prefix_ls, 115 area->table_topology); 116 117 while (iap->refer_lstype == topo_entry.path.origin.type && 118 iap->refer_lsid == topo_entry.path.origin.id && 119 iap->refer_advrtr == topo_entry.path.origin.adv_router) 120 { 121 ospf6_intra_route_calculate (REMOVE, lsa, &topo_entry); 122 ospf6_route_next (&topo_entry); 123 } 124 return 0; 125} 126 127int 128ospf6_intra_prefix_database_hook_add (void *data) 129{ 130 struct ospf6_lsa *lsa = data; 131 struct ospf6_area *area; 132 struct ospf6_intra_area_prefix_lsa *iap; 133 struct prefix_ls prefix_ls; 134 struct ospf6_route_req topo_entry; 135 136 if (lsa->header->type != htons (OSPF6_LSA_TYPE_INTRA_PREFIX)) 137 return 0; 138 139 area = (struct ospf6_area *) lsa->scope; 140 assert (area); 141 142 if (IS_LSA_MAXAGE (lsa)) 143 { 144 ospf6_intra_prefix_database_hook_remove (lsa); 145 return 0; 146 } 147 148 if (IS_OSPF6_DUMP_INTRA) 149 zlog_info ("INTRA: area %s add: %s", area->str, lsa->str); 150 151 iap = OSPF6_LSA_HEADER_END (lsa->header); 152 153 memset (&prefix_ls, 0, sizeof (struct prefix_ls)); 154 prefix_ls.prefixlen = 64; 155 prefix_ls.adv_router.s_addr = iap->refer_advrtr; 156 prefix_ls.id.s_addr = iap->refer_lsid; 157 158 if (iap->refer_lstype == htons (OSPF6_LSA_TYPE_ROUTER) && 159 iap->refer_lsid != htonl (0)) 160 { 161 zlog_warn ("INTRA: Malformed ID %lu of Router reference in %s", 162 (u_long) ntohl (iap->refer_lsid), lsa->str); 163 prefix_ls.id.s_addr = htonl (0); 164 } 165 166 ospf6_route_lookup (&topo_entry, (struct prefix *) &prefix_ls, 167 area->table_topology); 168 169 while (iap->refer_lstype == topo_entry.path.origin.type && 170 iap->refer_lsid == topo_entry.path.origin.id && 171 iap->refer_advrtr == topo_entry.path.origin.adv_router) 172 { 173 ospf6_intra_route_calculate (ADD, lsa, &topo_entry); 174 ospf6_route_next (&topo_entry); 175 } 176 return 0; 177} 178 179void 180ospf6_intra_topology_add (void *data) 181{ 182 struct ospf6_route_req *topo_entry = data; 183 struct ospf6_area *area; 184 struct ospf6_intra_area_prefix_lsa *iap; 185 struct ospf6_lsdb_node node; 186 187 area = ospf6_area_lookup (topo_entry->path.area_id, ospf6); 188 if (! area) 189 return; 190 191 if (topo_entry->route.type == OSPF6_DEST_TYPE_ROUTER && 192 (CHECK_FLAG (topo_entry->path.router_bits, OSPF6_ROUTER_LSA_BIT_B) || 193 CHECK_FLAG (topo_entry->path.router_bits, OSPF6_ROUTER_LSA_BIT_E))) 194 ospf6_route_add (topo_entry, ospf6->topology_table); 195 196 for (ospf6_lsdb_type (&node, htons (OSPF6_LSA_TYPE_INTRA_PREFIX), 197 area->lsdb); 198 ! ospf6_lsdb_is_end (&node); 199 ospf6_lsdb_next (&node)) 200 { 201 if (IS_OSPF6_DUMP_INTRA) 202 zlog_info ("INTRA: topology hook: Examining %s (%p)", 203 node.lsa->str, node.lsa); 204 205 if (IS_LSA_MAXAGE (node.lsa)) 206 continue; 207 208 iap = OSPF6_LSA_HEADER_END (node.lsa->header); 209 210 if (iap->refer_lstype == htons (OSPF6_LSA_TYPE_ROUTER) && 211 iap->refer_lsid != htonl (0)) 212 { 213 zlog_warn ("INTRA: Malformed ID %lu of Router reference in %s", 214 (u_long) ntohl (iap->refer_lsid), node.lsa->str); 215 } 216 217 if (iap->refer_lstype != topo_entry->path.origin.type || 218 iap->refer_lsid != topo_entry->path.origin.id || 219 iap->refer_advrtr != topo_entry->path.origin.adv_router) 220 continue; 221 222 ospf6_intra_route_calculate (ADD, node.lsa, topo_entry); 223 } 224} 225 226void 227ospf6_intra_topology_remove (void *data) 228{ 229 struct ospf6_route_req *topo_entry = data; 230 struct ospf6_area *area; 231 struct ospf6_intra_area_prefix_lsa *iap; 232 struct ospf6_lsdb_node node; 233 234 area = ospf6_area_lookup (topo_entry->path.area_id, ospf6); 235 if (! area) 236 return; 237 238 if (topo_entry->route.type == OSPF6_DEST_TYPE_ROUTER && 239 (CHECK_FLAG (topo_entry->path.router_bits, OSPF6_ROUTER_LSA_BIT_B) || 240 CHECK_FLAG (topo_entry->path.router_bits, OSPF6_ROUTER_LSA_BIT_E))) 241 ospf6_route_remove (topo_entry, ospf6->topology_table); 242 243 for (ospf6_lsdb_type (&node, htons (OSPF6_LSA_TYPE_INTRA_PREFIX), 244 area->lsdb); 245 ! ospf6_lsdb_is_end (&node); 246 ospf6_lsdb_next (&node)) 247 { 248 if (IS_LSA_MAXAGE (node.lsa)) 249 continue; 250 251 iap = OSPF6_LSA_HEADER_END (node.lsa->header); 252 253 if (iap->refer_lstype == htons (OSPF6_LSA_TYPE_ROUTER) && 254 iap->refer_lsid != htonl (0)) 255 zlog_warn ("SPF: Malformed ID %lu of Router reference in %s", 256 (u_long) ntohl (iap->refer_lsid), node.lsa->str); 257 258 if (iap->refer_lstype != topo_entry->path.origin.type || 259 iap->refer_lsid != topo_entry->path.origin.id || 260 iap->refer_advrtr != topo_entry->path.origin.adv_router) 261 continue; 262 263 ospf6_intra_route_calculate (REMOVE, node.lsa, topo_entry); 264 } 265} 266 267 268/*****************************************/ 269/* RFC2740 3.4.3.7 Intra-Area-Prefix-LSA */ 270/*****************************************/ 271 272#define CONTINUE_IF_ADDRESS_LINKLOCAL(addr)\ 273 if (IN6_IS_ADDR_LINKLOCAL (&(addr)->u.prefix6))\ 274 {\ 275 char buf[64];\ 276 prefix2str (addr, buf, sizeof (buf));\ 277 if (IS_OSPF6_DUMP_PREFIX)\ 278 zlog_info (" Filter out Linklocal: %s", buf);\ 279 continue;\ 280 } 281 282#define CONTINUE_IF_ADDRESS_UNSPECIFIED(addr)\ 283 if (IN6_IS_ADDR_UNSPECIFIED (&(addr)->u.prefix6))\ 284 {\ 285 char buf[64];\ 286 prefix2str (addr, buf, sizeof (buf));\ 287 if (IS_OSPF6_DUMP_PREFIX)\ 288 zlog_info (" Filter out Unspecified: %s", buf);\ 289 continue;\ 290 } 291 292#define CONTINUE_IF_ADDRESS_LOOPBACK(addr)\ 293 if (IN6_IS_ADDR_LOOPBACK (&(addr)->u.prefix6))\ 294 {\ 295 char buf[64];\ 296 prefix2str (addr, buf, sizeof (buf));\ 297 if (IS_OSPF6_DUMP_PREFIX)\ 298 zlog_info (" Filter out Loopback: %s", buf);\ 299 continue;\ 300 } 301 302#define CONTINUE_IF_ADDRESS_V4COMPAT(addr)\ 303 if (IN6_IS_ADDR_V4COMPAT (&(addr)->u.prefix6))\ 304 {\ 305 char buf[64];\ 306 prefix2str (addr, buf, sizeof (buf));\ 307 if (IS_OSPF6_DUMP_PREFIX)\ 308 zlog_info (" Filter out V4Compat: %s", buf);\ 309 continue;\ 310 } 311 312#define CONTINUE_IF_ADDRESS_V4MAPPED(addr)\ 313 if (IN6_IS_ADDR_V4MAPPED (&(addr)->u.prefix6))\ 314 {\ 315 char buf[64];\ 316 prefix2str (addr, buf, sizeof (buf));\ 317 if (IS_OSPF6_DUMP_PREFIX)\ 318 zlog_info (" Filter out V4Mapped: %s", buf);\ 319 continue;\ 320 } 321 322 323int 324ospf6_lsa_intra_prefix_show (struct vty *vty, struct ospf6_lsa *lsa) 325{ 326 struct ospf6_intra_area_prefix_lsa *iap_lsa; 327 struct ospf6_prefix *prefix; 328 unsigned short prefixnum; 329 char buf[128], type[32], id[32], adv_router[32]; 330 struct in6_addr in6; 331 char *start, *end, *current; 332 333 assert (lsa->header); 334 iap_lsa = (struct ospf6_intra_area_prefix_lsa *) (lsa->header + 1); 335 336 prefixnum = ntohs (iap_lsa->prefix_number); 337 ospf6_lsa_type_string (iap_lsa->refer_lstype, type, sizeof (type)); 338 inet_ntop (AF_INET, &iap_lsa->refer_lsid, id, sizeof (id)); 339 inet_ntop (AF_INET, &iap_lsa->refer_advrtr, adv_router, 340 sizeof (adv_router)); 341 342 vty_out (vty, " Number of Prefix: %d%s", prefixnum, VTY_NEWLINE); 343 vty_out (vty, " Referenced LS Type: %s%s", type, VTY_NEWLINE); 344 vty_out (vty, " Referenced LS ID: %s%s", id, VTY_NEWLINE); 345 vty_out (vty, " Referenced Advertising Router: %s%s", adv_router, 346 VTY_NEWLINE); 347 348 start = (char *) lsa->header + sizeof (struct ospf6_lsa_header) 349 + sizeof (struct ospf6_intra_area_prefix_lsa); 350 end = (char *) lsa->header + ntohs (lsa->header->length); 351 352 for (current = start; current < end; current += OSPF6_PREFIX_SIZE (prefix)) 353 { 354 prefix = (struct ospf6_prefix *) current; 355 if (current + OSPF6_PREFIX_SIZE (prefix) > end) 356 { 357 vty_out (vty, " Trailing %d byte garbage ... Malformed%s", 358 end - current, VTY_NEWLINE); 359 return -1; 360 } 361 362 ospf6_prefix_options_str (prefix->prefix_options, buf, sizeof (buf)); 363 vty_out (vty, " Prefix Options: %s%s", buf, VTY_NEWLINE); 364 365 ospf6_prefix_in6_addr (prefix, &in6); 366 inet_ntop (AF_INET6, &in6, buf, sizeof (buf)); 367 vty_out (vty, " Prefix: %s/%d%s", 368 buf, prefix->prefix_length, VTY_NEWLINE); 369 } 370 371 return 0; 372} 373 374void 375ospf6_lsa_intra_prefix_update_transit (char *ifname) 376{ 377 char buffer [MAXLSASIZE]; 378 u_int16_t size; 379 struct ospf6_lsa *old; 380 struct interface *ifp; 381 struct ospf6_interface *o6i; 382 struct ospf6_neighbor *o6n; 383 384 struct ospf6_intra_area_prefix_lsa *iap; 385 struct ospf6_lsdb_node n; 386 listnode node; 387 char *start, *end, *current; 388 struct ospf6_prefix *prefix, *dup, *src, *dst; 389 struct ospf6_link_lsa *link; 390 char buf[128]; 391 int count, prefix_num; 392 393 list adv_list; 394 395 ifp = if_lookup_by_name (ifname); 396 if (! ifp) 397 { 398 zlog_warn ("Update Intra-Prefix (Transit): No such Interface: %s", 399 ifname); 400 return; 401 } 402 403 o6i = (struct ospf6_interface *) ifp->info; 404 if (! o6i || ! o6i->area) 405 { 406 zlog_warn ("Update Intra-Prefix (Transit): Interface not enabled: %s", 407 ifname); 408 return; 409 } 410 411 /* find previous LSA */ 412 old = ospf6_lsdb_lookup (htons (OSPF6_LSA_TYPE_INTRA_PREFIX), 413 htonl (o6i->if_id), ospf6->router_id, 414 o6i->area); 415 416 /* Don't originate Network-LSA if not DR */ 417 if (o6i->state != IFS_DR) 418 { 419 if (old) 420 { 421 if (IS_OSPF6_DUMP_PREFIX) 422 zlog_info ("Update Intra-Prefix (Transit): %s not DR", 423 o6i->interface->name); 424 ospf6_lsa_premature_aging (old); 425 } 426 return; 427 } 428 429 /* If none of neighbor is adjacent to us */ 430 count = 0; 431 o6i->foreach_nei (o6i, &count, NBS_FULL, ospf6_count_state); 432 if (count == 0) 433 { 434 if (IS_OSPF6_DUMP_PREFIX) 435 zlog_info ("Update Intra-Prefix (Transit): %s is Stub", 436 o6i->interface->name); 437 if (old) 438 ospf6_lsa_premature_aging (old); 439 return; 440 } 441 442 if (IS_OSPF6_DUMP_PREFIX) 443 zlog_info ("Update Intra-Prefix (Transit): Interface %s", 444 o6i->interface->name); 445 446 adv_list = list_new (); 447 448 /* foreach Link-LSA associated with this Link */ 449 for (ospf6_lsdb_type (&n, htons (OSPF6_LSA_TYPE_LINK), o6i->lsdb); 450 ! ospf6_lsdb_is_end (&n); ospf6_lsdb_next (&n)) 451 { 452 if (IS_LSA_MAXAGE (n.lsa)) 453 continue; 454 455 if (IS_OSPF6_DUMP_PREFIX) 456 zlog_info ("Update Intra-Prefix (Transit): Checking %s", 457 n.lsa->str); 458 459 /* Check status of the advertising router */ 460 if (n.lsa->header->adv_router != o6i->area->ospf6->router_id) 461 { 462 o6n = ospf6_neighbor_lookup (n.lsa->header->adv_router, o6i); 463 if (! o6n) 464 { 465 if (IS_OSPF6_DUMP_PREFIX) 466 zlog_info ("Update Intra-Prefix (Transit): neighbor not found"); 467 continue; 468 } 469 470 if (o6n->state != NBS_FULL) 471 { 472 if (IS_OSPF6_DUMP_PREFIX) 473 zlog_info ("Update Intra-Prefix (Transit): %s not FULL", 474 o6n->str); 475 continue; 476 } 477 } 478 479 /* For each Prefix in this Link-LSA */ 480 link = (struct ospf6_link_lsa *) (n.lsa->header + 1); 481 prefix_num = ntohl (link->llsa_prefix_num); 482 483 if (IS_OSPF6_DUMP_PREFIX) 484 zlog_info (" Prefix #%d", prefix_num); 485 486 start = (char *) (link + 1); 487 end = (char *) (n.lsa->header) + ntohs (n.lsa->header->length); 488 prefix = (struct ospf6_prefix *) start; 489 for (current = start; current < end; 490 current += OSPF6_PREFIX_SIZE (prefix)) 491 { 492 prefix = (struct ospf6_prefix *) current; 493 ospf6_prefix_string (prefix, buf, sizeof (buf)); 494 495 /* Check duplicate prefix */ 496 dup = ospf6_prefix_lookup (adv_list, prefix); 497 if (dup) 498 { 499 if (IS_OSPF6_DUMP_PREFIX) 500 zlog_info (" Duplicate %s", buf); 501 dup->prefix_options |= prefix->prefix_options; 502 continue; 503 } 504 505 if (prefix_num <= 0) 506 { 507 zlog_warn (" Wong prefix number ..."); 508 break; 509 } 510 511 if (IS_OSPF6_DUMP_PREFIX) 512 zlog_info (" Prefix %s", buf); 513 514 /* copy prefix to advertise list */ 515 ospf6_prefix_add (adv_list, prefix); 516 517 prefix_num --; 518 } 519 } 520 521 /* if no prefix to advertise, return */ 522 if (listcount (adv_list) == 0) 523 { 524 if (IS_OSPF6_DUMP_PREFIX) 525 zlog_info (" No Prefix to advertise"); 526 if (old) 527 ospf6_lsa_premature_aging (old); 528 return; 529 } 530 531 /* prepare buffer */ 532 memset (buffer, 0, sizeof (buffer)); 533 size = sizeof (struct ospf6_intra_area_prefix_lsa); 534 iap = (struct ospf6_intra_area_prefix_lsa *) buffer; 535 536 /* Set Referenced LSA field */ 537 iap->refer_lstype = htons (OSPF6_LSA_TYPE_NETWORK); 538 iap->refer_lsid = htonl (o6i->if_id); 539 iap->refer_advrtr = o6i->area->ospf6->router_id; 540 541 dst = (struct ospf6_prefix *) (iap + 1); 542 for (node = listhead (adv_list); node; nextnode (node)) 543 { 544 src = (struct ospf6_prefix *) getdata (node); 545 546 memcpy (dst, src, OSPF6_PREFIX_SIZE (src)); 547 548 size += OSPF6_PREFIX_SIZE (dst); 549 dst = OSPF6_NEXT_PREFIX (dst); 550 } 551 iap->prefix_number = htons (listcount (adv_list)); 552 553 while ((node = listhead (adv_list)) != NULL) 554 { 555 prefix = getdata (node); 556 ospf6_prefix_delete (prefix); 557 listnode_delete (adv_list, prefix); 558 } 559 list_delete (adv_list); 560 561 ospf6_lsa_originate (htons (OSPF6_LSA_TYPE_INTRA_PREFIX), 562 htonl (o6i->if_id), ospf6->router_id, 563 buffer, size, o6i->area); 564} 565 566void 567ospf6_lsa_intra_prefix_update_stub (u_int32_t area_id) 568{ 569 char buffer [MAXLSASIZE]; 570 u_int16_t size; 571 struct ospf6_lsa *old; 572 struct ospf6_area *o6a; 573 int count; 574 575 struct ospf6_intra_area_prefix_lsa *iap; 576 listnode i,j; 577 struct ospf6_interface *o6i = NULL; 578 struct ospf6_prefix *prefix, *dst, *src; 579 struct connected *c; 580 char buf[128]; 581 582 list adv_list; 583 listnode node; 584 char prefix_buf[sizeof (struct ospf6_prefix) + sizeof (struct in6_addr)]; 585 586 o6a = ospf6_area_lookup (area_id, ospf6); 587 if (! o6a) 588 { 589 char tmp[16]; 590 inet_ntop (AF_INET, &area_id, tmp, sizeof (tmp)); 591 zlog_warn ("Update Intra-Prefix (Stub): No such area: %s", tmp); 592 return; 593 } 594 else if (IS_OSPF6_DUMP_PREFIX) 595 { 596 zlog_info ("Update Intra-Prefix (Stub): area: %s", o6a->str); 597 } 598 599 /* find previous LSA */ 600 old = ospf6_lsdb_lookup (htons (OSPF6_LSA_TYPE_INTRA_PREFIX), 601 htonl (0), ospf6->router_id, 602 o6a); /* xxx, ls-id */ 603 604 adv_list = list_new (); 605 606 /* Examin for each interface */ 607 for (i = listhead (o6a->if_list); i; nextnode (i)) 608 { 609 o6i = (struct ospf6_interface *) getdata (i); 610 611 if (o6i->state == IFS_DOWN) 612 { 613 if (IS_OSPF6_DUMP_PREFIX) 614 zlog_info (" Interface %s: down", o6i->interface->name); 615 continue; 616 } 617 618 count = 0; 619 o6i->foreach_nei (o6i, &count, NBS_FULL, ospf6_count_state); 620 if (o6i->state != IFS_LOOPBACK && o6i->state != IFS_PTOP && 621 count != 0) 622 { 623 /* This interface's prefix will be included in DR's */ 624 if (IS_OSPF6_DUMP_PREFIX) 625 zlog_info (" Interface %s: not stub", o6i->interface->name); 626 continue; 627 } 628 629 if (IS_OSPF6_DUMP_PREFIX) 630 zlog_info (" Interface %s:", o6i->interface->name); 631 632 /* copy foreach address prefix */ 633 for (j = listhead (o6i->interface->connected); j; nextnode (j)) 634 { 635 c = (struct connected *) getdata (j); 636 637 /* filter prefix not IPv6 */ 638 if (c->address->family != AF_INET6) 639 continue; 640 641 /* for log */ 642 prefix2str (c->address, buf, sizeof (buf)); 643 644 CONTINUE_IF_ADDRESS_LINKLOCAL (c->address); 645 CONTINUE_IF_ADDRESS_UNSPECIFIED (c->address); 646 CONTINUE_IF_ADDRESS_LOOPBACK (c->address); 647 CONTINUE_IF_ADDRESS_V4COMPAT (c->address); 648 CONTINUE_IF_ADDRESS_V4MAPPED (c->address); 649 650 /* filter prefix specified by configuration */ 651 if (o6i->plist_name) 652 { 653 struct prefix_list *plist; 654 enum prefix_list_type result = PREFIX_PERMIT; 655 656 plist = prefix_list_lookup (AFI_IP6, o6i->plist_name); 657 if (plist) 658 result = prefix_list_apply (plist, c->address); 659 else 660 zlog_warn ("Update Intra-Prefix (Stub): " 661 "Prefix list \"%s\" not found", 662 o6i->plist_name); 663 664 if (result == PREFIX_DENY) 665 { 666 if (IS_OSPF6_DUMP_PREFIX) 667 zlog_info (" %s: Filtered by %s", 668 buf, o6i->plist_name); 669 continue; 670 } 671 } 672 673 /* initialize buffer for ospf6 prefix */ 674 memset (prefix_buf, 0, sizeof (prefix_buf)); 675 prefix = (struct ospf6_prefix *) prefix_buf; 676 677 /* set ospf6 prefix according to its state */ 678 /* xxx, virtual links */ 679 if (! CHECK_FLAG (o6i->flag, OSPF6_INTERFACE_FLAG_FORCE_PREFIX) && 680 (o6i->state == IFS_LOOPBACK || o6i->state == IFS_PTOP 681 /* xxx, PoinToMultiPoint I/F type */ )) 682 { 683 prefix->prefix_length = 128; 684 prefix->prefix_options = OSPF6_PREFIX_OPTION_LA; 685 prefix->prefix_metric = htons (0); 686 memcpy (prefix + 1, &c->address->u.prefix6, 687 OSPF6_PREFIX_SPACE (prefix->prefix_length)); 688 } 689 else 690 { 691 struct prefix_ipv6 prefix_ipv6; 692 /* apply mask */ 693 prefix_copy ((struct prefix *) &prefix_ipv6, c->address); 694 apply_mask_ipv6 (&prefix_ipv6); 695 696 prefix->prefix_length = prefix_ipv6.prefixlen; 697 prefix->prefix_options = 0; /* xxx, no options yet */ 698 prefix->prefix_metric = htons (o6i->cost); 699 memcpy (prefix + 1, &prefix_ipv6.prefix, 700 OSPF6_PREFIX_SPACE (prefix->prefix_length)); 701 } 702 703 ospf6_prefix_string (prefix, buf, sizeof (buf)); 704 if (IS_OSPF6_DUMP_PREFIX) 705 zlog_info (" Advertise %s", buf); 706 707 /* check in the prefix to advertising prefix list */ 708 ospf6_prefix_add (adv_list, prefix); 709 } 710 } 711 712 /* If no prefix to advertise */ 713 if (listcount (adv_list) == 0) 714 { 715 if (IS_OSPF6_DUMP_PREFIX) 716 zlog_info (" No prefix to advertise"); 717 if (old) 718 ospf6_lsa_premature_aging (old); 719 return; 720 } 721 722 /* prepare buffer */ 723 memset (buffer, 0, sizeof (buffer)); 724 size = sizeof (struct ospf6_intra_area_prefix_lsa); 725 iap = (struct ospf6_intra_area_prefix_lsa *) buffer; 726 727 /* Set Referenced LSA field */ 728 iap->refer_lstype = htons (OSPF6_LSA_TYPE_ROUTER); 729 iap->refer_lsid = htonl (0); 730 iap->refer_advrtr = o6a->ospf6->router_id; 731 732 dst = (struct ospf6_prefix *) (iap + 1); 733 for (node = listhead (adv_list); node; nextnode (node)) 734 { 735 src = (struct ospf6_prefix *) getdata (node); 736 737 memcpy (dst, src, OSPF6_PREFIX_SIZE (src)); 738 739 size += OSPF6_PREFIX_SIZE (dst); 740 dst = OSPF6_NEXT_PREFIX (dst); 741 } 742 iap->prefix_number = htons (listcount (adv_list)); 743 744 while ((node = listhead (adv_list)) != NULL) 745 { 746 prefix = getdata (node); 747 ospf6_prefix_delete (prefix); 748 listnode_delete (adv_list, prefix); 749 } 750 list_delete (adv_list); 751 752 ospf6_lsa_originate (htons (OSPF6_LSA_TYPE_INTRA_PREFIX), 753 htonl (0) /* xxx */, ospf6->router_id, 754 buffer, size, o6a); 755} 756 757int 758ospf6_lsa_intra_prefix_hook_interface (void *interface) 759{ 760 struct ospf6_interface *o6i = interface; 761 if (o6i->area) 762 { 763 ospf6_lsa_intra_prefix_update_transit (o6i->interface->name); 764 ospf6_lsa_intra_prefix_update_stub (o6i->area->area_id); 765 } 766 return 0; 767} 768 769int 770ospf6_lsa_intra_prefix_hook_neighbor (void *neighbor) 771{ 772 struct ospf6_neighbor *o6n = neighbor; 773 if (o6n->ospf6_interface->area) 774 { 775 ospf6_lsa_intra_prefix_update_transit (o6n->ospf6_interface->interface->name); 776 ospf6_lsa_intra_prefix_update_stub (o6n->ospf6_interface->area->area_id); 777 } 778 return 0; 779} 780 781int 782ospf6_intra_prefix_link_database_hook (void *new) 783{ 784 struct ospf6_lsa *lsa = new; 785 struct ospf6_interface *o6i; 786 787 if (lsa->header->type != htons (OSPF6_LSA_TYPE_LINK)) 788 return 0; 789 790 o6i = lsa->scope; 791 if (o6i->state != IFS_DR) 792 return 0; 793 794 ospf6_lsa_intra_prefix_update_transit (o6i->interface->name); 795 ospf6_lsa_intra_prefix_update_stub (o6i->area->area_id); 796 return 0; 797} 798 799int 800ospf6_lsa_intra_prefix_refresh (void *old) 801{ 802 struct ospf6_lsa *lsa = old; 803 struct ospf6_interface *o6i; 804 struct ospf6_area *o6a; 805 u_int32_t id; 806 807 id = ntohl (lsa->header->id); 808 if (id) 809 { 810 o6i = ospf6_interface_lookup_by_index (id); 811 if (o6i) 812 ospf6_lsa_intra_prefix_update_transit (o6i->interface->name); 813 else 814 ospf6_lsa_premature_aging (lsa); 815 } 816 else 817 { 818 o6a = lsa->scope; 819 ospf6_lsa_intra_prefix_update_stub (o6a->area_id); 820 } 821 822 return 0; 823} 824 825void 826ospf6_intra_prefix_register () 827{ 828 struct ospf6_lsa_slot slot, *sp; 829 struct ospf6_hook hook; 830 831 memset (&slot, 0, sizeof (struct ospf6_lsa_slot)); 832 slot.type = htons (OSPF6_LSA_TYPE_INTRA_PREFIX); 833 slot.name = "Intra-Prefix"; 834 slot.func_show = ospf6_lsa_intra_prefix_show; 835 slot.func_refresh = ospf6_lsa_intra_prefix_refresh; 836 ospf6_lsa_slot_register (&slot); 837 838 memset (&hook, 0, sizeof (hook)); 839 hook.name = "OriginateIntraPrefix"; 840 hook.hook_add = ospf6_lsa_intra_prefix_hook_interface; 841 hook.hook_change = ospf6_lsa_intra_prefix_hook_interface; 842 hook.hook_remove = NULL; /* XXX */ 843 ospf6_hook_register (&hook, &interface_hook); 844 845 memset (&hook, 0, sizeof (hook)); 846 hook.name = "OriginateIntraPrefix"; 847 hook.hook_add = ospf6_lsa_intra_prefix_hook_neighbor; 848 hook.hook_change = ospf6_lsa_intra_prefix_hook_neighbor; 849 hook.hook_remove = ospf6_lsa_intra_prefix_hook_neighbor; 850 ospf6_hook_register (&hook, &neighbor_hook); 851 852 sp = ospf6_lsa_slot_get (htons (OSPF6_LSA_TYPE_INTRA_PREFIX)); 853 hook.name = "CalculateIntraPrefix"; 854 hook.hook_add = ospf6_intra_prefix_database_hook_add; 855 hook.hook_change = ospf6_intra_prefix_database_hook_add; 856 hook.hook_remove = ospf6_intra_prefix_database_hook_remove; 857 ospf6_hook_register (&hook, &sp->database_hook); 858} 859 860void 861ospf6_intra_database_hook_intra_prefix (struct ospf6_lsa *old, 862 struct ospf6_lsa *new) 863{ 864 if (old) 865 ospf6_intra_prefix_database_hook_remove (old); 866 if (new && ! IS_LSA_MAXAGE (new)) 867 ospf6_intra_prefix_database_hook_add (new); 868} 869 870void 871ospf6_intra_database_hook_link (struct ospf6_lsa *old, 872 struct ospf6_lsa *new) 873{ 874 ospf6_intra_prefix_link_database_hook (new); 875 ospf6_spf_database_hook (old, new); 876} 877 878void 879ospf6_intra_init () 880{ 881 ospf6_lsdb_hook[OSPF6_LSA_TYPE_INTRA_PREFIX & OSPF6_LSTYPE_CODE_MASK].hook = 882 ospf6_intra_database_hook_intra_prefix; 883 ospf6_lsdb_hook[OSPF6_LSA_TYPE_LINK & OSPF6_LSTYPE_CODE_MASK].hook = 884 ospf6_intra_database_hook_link; 885 886 intra_index = ospf6_dump_install ("intra-area", "Intra-area calculation\n"); 887 ospf6_intra_prefix_register (); 888} 889 890 891