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 24char * 25dtype_name[OSPF6_DEST_TYPE_MAX] = 26{ 27 "Unknown", "Router", "Network", "Discard" 28}; 29#define DTYPE_NAME(x) \ 30 (0 < (x) && (x) < sizeof (dtype_name) ? \ 31 dtype_name[(x)] : dtype_name[0]) 32 33char * 34dtype_abname[OSPF6_DEST_TYPE_MAX] = 35{ 36 "?", "R", "N", "D" 37}; 38#define DTYPE_ABNAME(x) \ 39 (0 < (x) && (x) < sizeof (dtype_abname) ? \ 40 dtype_abname[(x)] : dtype_abname[0]) 41 42char * 43ptype_name[OSPF6_PATH_TYPE_MAX] = 44{ 45 "Unknown", "Intra", "Inter", "External-1", "External-2", 46 "System", "Kernel", "Connect", "Static", "RIP", "RIPng", 47 "OSPF", "OSPF6", "BGP" 48}; 49#define PTYPE_NAME(x) \ 50 (0 < (x) && (x) < sizeof (ptype_name) ? \ 51 ptype_name[(x)] : ptype_name[0]) 52 53char * 54ptype_abname[OSPF6_PATH_TYPE_MAX] = 55{ 56 "??", "Ia", "Ie", "E1", "E2", 57 "-X", "-K", "-C", "-S", "-R", "-R", 58 "-O", "-O", "-B" 59}; 60#define PTYPE_ABNAME(x) \ 61 (0 < (x) && (x) < sizeof (ptype_abname) ? \ 62 ptype_abname[(x)] : ptype_abname[0]) 63 64 65 66int 67ospf6_path_cmp (void *arg1, void *arg2) 68{ 69 struct ospf6_path_node *pn1 = arg1; 70 struct ospf6_path_node *pn2 = arg2; 71 struct ospf6_path *p1 = &pn1->path; 72 struct ospf6_path *p2 = &pn2->path; 73 74 if (p1->type < p2->type) 75 return -1; 76 else if (p1->type > p2->type) 77 return 1; 78 79 if (p1->type == OSPF6_PATH_TYPE_EXTERNAL2) 80 { 81 if (p1->cost_e2 < p2->cost_e2) 82 return -1; 83 else if (p1->cost_e2 > p2->cost_e2) 84 return 1; 85 } 86 87 if (p1->cost < p2->cost) 88 return -1; 89 else if (p1->cost > p2->cost) 90 return 1; 91 92 /* if from the same source, recognize as identical 93 (and treat this as update) */ 94 if (! memcmp (&p1->origin, &p2->origin, sizeof (struct ls_origin)) && 95 p1->area_id == p2->area_id) 96 return 0; 97 98 /* else, always prefer left */ 99 return -1; 100} 101 102int 103ospf6_nexthop_cmp (void *arg1, void *arg2) 104{ 105 int i, ret = 0; 106 struct ospf6_nexthop_node *nn1 = arg1; 107 struct ospf6_nexthop_node *nn2 = arg2; 108 struct ospf6_nexthop *n1 = &nn1->nexthop; 109 struct ospf6_nexthop *n2 = &nn2->nexthop; 110 111 if (memcmp (n1, n2, sizeof (struct ospf6_nexthop)) == 0) 112 return 0; 113 114 for (i = 0; i < sizeof (struct in6_addr); i++) 115 { 116 if (nn1->nexthop.address.s6_addr[i] != nn2->nexthop.address.s6_addr[i]) 117 { 118 ret = nn1->nexthop.address.s6_addr[i] - 119 nn2->nexthop.address.s6_addr[i]; 120 break; 121 } 122 } 123 124 if (ret == 0) 125 ret = -1; 126 127 return ret; 128} 129 130static void 131ospf6_route_request (struct ospf6_route_req *request, 132 struct ospf6_route_node *rn, 133 struct ospf6_path_node *pn, 134 struct ospf6_nexthop_node *nn) 135{ 136 assert (request); 137 assert (rn && pn && nn); 138 139 request->route_node = rn->route_node; 140 141 linklist_head (rn->path_list, &request->path_lnode); 142 while (request->path_lnode.data != pn) 143 { 144 //assert (! linklist_end (&request->path_lnode)); 145 if (linklist_end (&request->path_lnode)) 146 { 147 struct linklist_node node; 148 149 zlog_info ("rn: %p, pn: %p", rn, pn); 150 zlog_info ("origin: %hx %x %x bits: %x opt: %x%x%x popt: %x area: %x type: %d cost %d %d %d", 151 pn->path.origin.type, pn->path.origin.id, pn->path.origin.adv_router, (int)pn->path.router_bits, (int)pn->path.capability[0], 152 (int)pn->path.capability[1], (int)pn->path.capability[2], 153 (int)pn->path.prefix_options, pn->path.area_id, 154 pn->path.type, pn->path.metric_type, pn->path.cost, pn->path.cost_e2); 155 156 for (linklist_head (rn->path_list, &node); ! linklist_end (&node); 157 linklist_next (&node)) 158 { 159 struct ospf6_path_node *pn2 = node.data; 160 161 zlog_info (" %p: path data with pn(%p): %s", pn2, pn, 162 (memcmp (&pn->path, &pn2->path, 163 sizeof (struct ospf6_path)) ? 164 "different" : "same")); 165 166 zlog_info (" origin: %hx %x %x bits: %x opt: %x%x%x popt: %x area: %x type: %d cost %d %d %d", 167 pn2->path.origin.type, pn2->path.origin.id, pn2->path.origin.adv_router, (int)pn2->path.router_bits, (int)pn2->path.capability[0], 168 (int)pn2->path.capability[1], (int)pn2->path.capability[2], 169 (int)pn2->path.prefix_options, pn2->path.area_id, 170 pn2->path.type, pn2->path.metric_type, pn2->path.cost, pn2->path.cost_e2); 171 172 if (! memcmp (&pn->path, &pn2->path, sizeof (struct ospf6_path))) 173 { 174 pn = pn2; 175 request->nexthop_lnode.data = pn2; 176 } 177 } 178 break; 179 } 180 linklist_next (&request->path_lnode); 181 } 182 assert (request->path_lnode.data == pn); 183 184 linklist_head (pn->nexthop_list, &request->nexthop_lnode); 185 while (request->nexthop_lnode.data != nn) 186 { 187 assert (! linklist_end (&request->nexthop_lnode)); 188 linklist_next (&request->nexthop_lnode); 189 } 190 assert (request->nexthop_lnode.data == nn); 191 192 request->table = rn->table; 193 request->count = rn->count; 194 request->route_id = rn->route_id; 195 memcpy (&request->route, &rn->route, sizeof (struct ospf6_route)); 196 memcpy (&request->path, &pn->path, sizeof (struct ospf6_path)); 197 memcpy (&request->nexthop, &nn->nexthop, sizeof (struct ospf6_nexthop)); 198} 199 200int 201ospf6_route_count (struct ospf6_route_req *request) 202{ 203 return request->count; 204} 205 206int 207ospf6_route_lookup (struct ospf6_route_req *request, 208 struct prefix *prefix, 209 struct ospf6_route_table *table) 210{ 211 struct route_node *node; 212 struct ospf6_route_node *rn = NULL; 213 struct ospf6_path_node *pn = NULL; 214 struct ospf6_nexthop_node *nn = NULL; 215 struct linklist_node lnode; 216 217 if (request) 218 memset ((void *) request, 0, sizeof (struct ospf6_route_req)); 219 220 node = route_node_lookup (table->table, prefix); 221 if (! node) 222 return 0; 223 224 rn = (struct ospf6_route_node *) node->info; 225 if (! rn) 226 return 0; 227 228 if (request) 229 { 230 linklist_head (rn->path_list, &lnode); 231 pn = lnode.data; 232 linklist_head (pn->nexthop_list, &lnode); 233 nn = lnode.data; 234 235 ospf6_route_request (request, rn, pn, nn); 236 } 237 238 return 1; 239} 240 241void 242ospf6_route_head (struct ospf6_route_req *request, 243 struct ospf6_route_table *table) 244{ 245 struct route_node *node; 246 struct ospf6_route_node *rn = NULL; 247 struct ospf6_path_node *pn = NULL; 248 struct ospf6_nexthop_node *nn = NULL; 249 struct linklist_node lnode; 250 251 if (request) 252 memset (request, 0, sizeof (struct ospf6_route_req)); 253 254 node = route_top (table->table); 255 if (! node) 256 return; 257 258 while (node && node->info == NULL) 259 node = route_next (node); 260 if (! node) 261 return; 262 263 rn = (struct ospf6_route_node *) node->info; 264 linklist_head (rn->path_list, &lnode); 265 pn = lnode.data; 266 linklist_head (pn->nexthop_list, &lnode); 267 nn = lnode.data; 268 269 ospf6_route_request (request, rn, pn, nn); 270} 271 272int 273ospf6_route_end (struct ospf6_route_req *request) 274{ 275 if (request->route_node == NULL && 276 linklist_end (&request->path_lnode) && 277 linklist_end (&request->nexthop_lnode) && 278 request->nexthop.ifindex == 0 && 279 IN6_IS_ADDR_UNSPECIFIED (&request->nexthop.address)) 280 return 1; 281 return 0; 282} 283 284void 285ospf6_route_next (struct ospf6_route_req *request) 286{ 287 struct ospf6_route_node *route_node = NULL; 288 struct ospf6_path_node *path_node = NULL; 289 struct ospf6_nexthop_node *nexthop_node = NULL; 290 291 linklist_next (&request->nexthop_lnode); 292 if (linklist_end (&request->nexthop_lnode)) 293 { 294 linklist_next (&request->path_lnode); 295 if (linklist_end (&request->path_lnode)) 296 { 297 request->route_node = route_next (request->route_node); 298 while (request->route_node && request->route_node->info == NULL) 299 request->route_node = route_next (request->route_node); 300 if (request->route_node) 301 { 302 route_node = request->route_node->info; 303 if (route_node) 304 linklist_head (route_node->path_list, &request->path_lnode); 305 } 306 } 307 308 path_node = request->path_lnode.data; 309 if (path_node) 310 linklist_head (path_node->nexthop_list, &request->nexthop_lnode); 311 } 312 313 nexthop_node = request->nexthop_lnode.data; 314 315 if (nexthop_node == NULL) 316 { 317 assert (path_node == NULL); 318 assert (route_node == NULL); 319 320 memset (&request->route, 0, sizeof (struct ospf6_route)); 321 memset (&request->path, 0, sizeof (struct ospf6_path)); 322 memset (&request->nexthop, 0, sizeof (struct ospf6_nexthop)); 323 } 324 else 325 { 326 path_node = request->path_lnode.data; 327 route_node = request->route_node->info; 328 329 assert (path_node != NULL); 330 assert (route_node != NULL); 331 332 memcpy (&request->route, &route_node->route, 333 sizeof (struct ospf6_route)); 334 memcpy (&request->path, &path_node->path, 335 sizeof (struct ospf6_path)); 336 memcpy (&request->nexthop, &nexthop_node->nexthop, 337 sizeof (struct ospf6_nexthop)); 338 } 339} 340 341#define ADD 0 342#define CHANGE 1 343#define REMOVE 2 344 345void 346ospf6_route_hook_call (int type, 347 struct ospf6_route_req *request, 348 struct ospf6_route_table *table) 349{ 350 struct linklist_node node; 351 void (*func) (struct ospf6_route_req *); 352 353 for (linklist_head (table->hook_list[type], &node); 354 ! linklist_end (&node); 355 linklist_next (&node)) 356 { 357 func = node.data; 358 (*func) (request); 359 } 360} 361 362void 363ospf6_route_hook_register (void (*add) (struct ospf6_route_req *), 364 void (*change) (struct ospf6_route_req *), 365 void (*remove) (struct ospf6_route_req *), 366 struct ospf6_route_table *table) 367{ 368 linklist_add (add, table->hook_list[ADD]); 369 linklist_add (change, table->hook_list[CHANGE]); 370 linklist_add (remove, table->hook_list[REMOVE]); 371} 372 373void 374ospf6_route_hook_unregister (void (*add) (struct ospf6_route_req *), 375 void (*change) (struct ospf6_route_req *), 376 void (*remove) (struct ospf6_route_req *), 377 struct ospf6_route_table *table) 378{ 379 linklist_remove (add, table->hook_list[ADD]); 380 linklist_remove (change, table->hook_list[CHANGE]); 381 linklist_remove (remove, table->hook_list[REMOVE]); 382} 383 384 385int 386prefix_ls2str (struct prefix *p, char *str, int size) 387{ 388 char id[BUFSIZ], adv_router[BUFSIZ]; 389 struct prefix_ls *pl = (struct prefix_ls *) p; 390 391 inet_ntop (AF_INET, &pl->id, id, BUFSIZ); 392 inet_ntop (AF_INET, &pl->adv_router, adv_router, BUFSIZ); 393 snprintf (str, size, "%s-%s", adv_router, id); 394 return 0; 395} 396 397void 398ospf6_route_log_request (char *what, char *where, 399 struct ospf6_route_req *request) 400{ 401 char prefix[64]; 402 char area_id[16]; 403 char type[16], id[16], adv[16]; 404 char address[64], ifname[IFNAMSIZ]; 405 406 if (request->route.prefix.family != AF_INET && 407 request->route.prefix.family != AF_INET6) 408 prefix_ls2str (&request->route.prefix, prefix, sizeof (prefix)); 409 else 410 prefix2str (&request->route.prefix, prefix, sizeof (prefix)); 411 412 inet_ntop (AF_INET, &request->path.area_id, area_id, sizeof (area_id)); 413 414 ospf6_lsa_type_string (request->path.origin.type, type, sizeof (type)); 415 inet_ntop (AF_INET, &request->path.origin.id, id, sizeof (id)); 416 inet_ntop (AF_INET, &request->path.origin.adv_router, adv, sizeof (adv)); 417 418 inet_ntop (AF_INET6, &request->nexthop.address, address, sizeof (address)); 419 420 zlog_info ("ROUTE: %s %s %s %s %s", 421 what, DTYPE_ABNAME (request->route.type), prefix, 422 ((strcmp ("Add", what) == 0) ? "to" : "from"), where); 423 zlog_info ("ROUTE: Area: %s type: %s cost: %lu (E2: %lu)", 424 area_id, PTYPE_NAME (request->path.type), 425 (u_long) request->path.cost, (u_long) request->path.cost_e2); 426 zlog_info ("ROUTE: Origin: Type: %s", type); 427 zlog_info ("ROUTE: Origin: Id: %s Adv: %s", id, adv); 428 zlog_info ("ROUTE: Nexthop: %s", address); 429 zlog_info ("ROUTE: Nexthop: Ifindex: %u (%s)", 430 request->nexthop.ifindex, 431 if_indextoname (request->nexthop.ifindex, ifname)); 432} 433 434struct ospf6_path_node * 435ospf6_route_find_path_node (struct ospf6_route_req *request, 436 struct ospf6_route_node *rn) 437{ 438 struct linklist_node node; 439 440 for (linklist_head (rn->path_list, &node); ! linklist_end (&node); 441 linklist_next (&node)) 442 { 443 struct ospf6_path_node *path_node = node.data; 444 445 if (path_node->path.area_id == request->path.area_id && 446 path_node->path.origin.type == request->path.origin.type && 447 path_node->path.origin.id == request->path.origin.id && 448 path_node->path.origin.adv_router == request->path.origin.adv_router) 449 return path_node; 450 } 451 452#if 0 453 zlog_info ("req path : area: %#x origin: type: %d, id: %d, adv_router: %#x", 454 request->path.area_id, request->path.origin.type, 455 request->path.origin.id, request->path.origin.adv_router); 456 for (linklist_head (rn->path_list, &node); ! linklist_end (&node); 457 linklist_next (&node)) 458 { 459 struct ospf6_path_node *path_node = node.data; 460 zlog_info (" path : area: %#x origin: type: %d, id: %d, adv_router: %#x", 461 path_node->path.area_id, path_node->path.origin.type, 462 path_node->path.origin.id, path_node->path.origin.adv_router); 463 } 464#endif 465 466 return NULL; 467} 468 469struct ospf6_nexthop_node * 470ospf6_route_find_nexthop_node (struct ospf6_route_req *request, 471 struct ospf6_path_node *pn) 472{ 473 struct linklist_node node; 474 for (linklist_head (pn->nexthop_list, &node); ! linklist_end (&node); 475 linklist_next (&node)) 476 { 477 struct ospf6_nexthop_node *nexthop_node = node.data; 478 479 if (! memcmp (&nexthop_node->nexthop, &request->nexthop, 480 sizeof (struct ospf6_nexthop))) 481 return nexthop_node; 482 } 483 return NULL; 484} 485 486void 487ospf6_route_add (struct ospf6_route_req *request, 488 struct ospf6_route_table *table) 489{ 490 struct ospf6_route_node *rn; 491 struct ospf6_path_node *pn; 492 struct ospf6_nexthop_node *nn; 493 struct route_node *route_node; 494 495 struct ospf6_route_req route; 496 497 int route_change = 0; 498 int path_change = 0; 499 int nexthop_change = 0; 500 501 /* find the requested route */ 502 route_node = route_node_get (table->table, &request->route.prefix); 503 rn = (struct ospf6_route_node *) route_node->info; 504 505 if (rn) 506 { 507 if (memcmp (&rn->route, &request->route, sizeof (struct ospf6_route))) 508 { 509 memcpy (&rn->route, &request->route, sizeof (struct ospf6_route)); 510 route_change++; 511 } 512 } 513 else 514 { 515 rn = XCALLOC (MTYPE_OSPF6_ROUTE, sizeof (struct ospf6_route_node)); 516 rn->table = table; 517 rn->route_node = route_node; 518 rn->route_id = table->route_id++; 519 rn->path_list = linklist_create (); 520 rn->path_list->cmp = ospf6_path_cmp; 521 memcpy (&rn->route, &request->route, sizeof (struct ospf6_route)); 522 route_node->info = rn; 523 } 524 525 /* find the same path */ 526 pn = ospf6_route_find_path_node (request, rn); 527 528 if (pn) 529 { 530 if (memcmp (&pn->path, &request->path, sizeof (struct ospf6_path))) 531 { 532 memcpy (&pn->path, &request->path, sizeof (struct ospf6_path)); 533 path_change++; 534 } 535 } 536 else 537 { 538 pn = XCALLOC (MTYPE_OSPF6_ROUTE, sizeof (struct ospf6_path_node)); 539 pn->route_node = rn; 540 pn->nexthop_list = linklist_create (); 541 pn->nexthop_list->cmp = ospf6_nexthop_cmp; 542 memcpy (&pn->path, &request->path, sizeof (struct ospf6_path)); 543 linklist_add (pn, rn->path_list); 544 } 545 546 /* find the same nexthop */ 547 nn = ospf6_route_find_nexthop_node (request, pn); 548 549 if (nn) 550 { 551 if (memcmp (&nn->nexthop, &request->nexthop, 552 sizeof (struct ospf6_nexthop))) 553 { 554 memcpy (&nn->nexthop, &request->nexthop, 555 sizeof (struct ospf6_nexthop)); 556 nexthop_change++; 557 gettimeofday (&nn->installed, (struct timezone *) NULL); 558 } 559 } 560 else 561 { 562 nn = XCALLOC (MTYPE_OSPF6_ROUTE, sizeof (struct ospf6_nexthop_node)); 563 nn->path_node = pn; 564 memcpy (&nn->nexthop, &request->nexthop, sizeof (struct ospf6_nexthop)); 565 linklist_add (nn, pn->nexthop_list); 566 rn->count++; 567 gettimeofday (&nn->installed, (struct timezone *) NULL); 568 } 569 570 SET_FLAG (nn->flag, OSPF6_ROUTE_FLAG_ADD); 571 if (route_change) 572 SET_FLAG (nn->flag, OSPF6_ROUTE_FLAG_ROUTE_CHANGE); 573 if (path_change) 574 SET_FLAG (nn->flag, OSPF6_ROUTE_FLAG_PATH_CHANGE); 575 if (nexthop_change) 576 SET_FLAG (nn->flag, OSPF6_ROUTE_FLAG_CHANGE); 577 578 if (table->freeze) 579 return; 580 581 if (IS_OSPF6_DUMP_ROUTE) 582 { 583 ospf6_route_log_request ("Add", table->name, request); 584 585 if (CHECK_FLAG (nn->flag, OSPF6_ROUTE_FLAG_ROUTE_CHANGE)) 586 zlog_info ("ROUTE: route attribute change"); 587 if (CHECK_FLAG (nn->flag, OSPF6_ROUTE_FLAG_PATH_CHANGE)) 588 zlog_info ("ROUTE: path attribute change"); 589 if (CHECK_FLAG (nn->flag, OSPF6_ROUTE_FLAG_CHANGE)) 590 zlog_info ("ROUTE: nexthop attribute change"); 591 } 592 593 if (CHECK_FLAG (nn->flag, OSPF6_ROUTE_FLAG_ROUTE_CHANGE) || 594 CHECK_FLAG (nn->flag, OSPF6_ROUTE_FLAG_PATH_CHANGE)) 595 SET_FLAG (nn->flag, OSPF6_ROUTE_FLAG_CHANGE); 596 597 /* Call hooks */ 598 ospf6_route_request (&route, rn, pn, nn); 599 if (CHECK_FLAG (nn->flag, OSPF6_ROUTE_FLAG_ADD)) 600 ospf6_route_hook_call (ADD, &route, table); 601 else if (CHECK_FLAG (nn->flag, OSPF6_ROUTE_FLAG_CHANGE)) 602 ospf6_route_hook_call (CHANGE, &route, table); 603 604 if (table->hook_add && 605 CHECK_FLAG (nn->flag, OSPF6_ROUTE_FLAG_ADD)) 606 (*table->hook_add) (&route); 607 else if (table->hook_change && 608 CHECK_FLAG (nn->flag, OSPF6_ROUTE_FLAG_CHANGE)) 609 (*table->hook_change) (&route); 610 611 /* clear flag */ 612 nn->flag = 0; 613} 614 615void 616ospf6_route_remove (struct ospf6_route_req *request, 617 struct ospf6_route_table *table) 618{ 619 struct ospf6_route_node *rn; 620 struct ospf6_path_node *pn; 621 struct ospf6_nexthop_node *nn; 622 struct route_node *route_node; 623 struct ospf6_route_req route; 624 625 /* find the requested route */ 626 route_node = route_node_get (table->table, &request->route.prefix); 627 rn = (struct ospf6_route_node *) route_node->info; 628 629 if (! rn) 630 { 631 if (IS_OSPF6_DUMP_ROUTE) 632 { 633 ospf6_route_log_request ("Remove", table->name, request); 634 zlog_info ("ROUTE: Can't remove: No such route"); 635 } 636 return; 637 } 638 639 pn = ospf6_route_find_path_node (request, rn); 640 if (! pn) 641 { 642 if (IS_OSPF6_DUMP_ROUTE) 643 { 644 ospf6_route_log_request ("Remove", table->name, request); 645 zlog_info ("ROUTE: Can't remove: No such path"); 646 } 647 return; 648 } 649 650 if (pn->path.area_id != request->path.area_id || 651 pn->path.origin.type != request->path.origin.type || 652 pn->path.origin.id != request->path.origin.id || 653 pn->path.origin.adv_router != request->path.origin.adv_router) 654 { 655 if (IS_OSPF6_DUMP_ROUTE) 656 { 657 ospf6_route_log_request ("Remove", table->name, request); 658 zlog_info ("ROUTE: Can't remove: Path differ"); 659 { 660 char *s, *e, *c; 661 char line[512], *p; 662 663 p = line; 664 s = (char *) &pn->path; 665 e = s + sizeof (struct ospf6_path); 666 for (c = s; c < e; c++) 667 { 668 if ((c - s) % 4 == 0) 669 snprintf (p++, line + sizeof (line) - p, " "); 670 snprintf (p, line + sizeof (line) - p, "%02x", *c); 671 p += 2; 672 } 673 zlog_info ("ROUTE: path: %s", line); 674 675 p = line; 676 s = (char *) &request->path; 677 e = s + sizeof (struct ospf6_path); 678 for (c = s; c < e; c++) 679 { 680 if ((c - s) % 4 == 0) 681 snprintf (p++, line + sizeof (line) - p, " "); 682 snprintf (p, line + sizeof (line) - p, "%02x", *c); 683 p += 2; 684 } 685 zlog_info ("ROUTE: req : %s", line); 686 687 } 688 } 689 return; 690 } 691 692 nn = ospf6_route_find_nexthop_node (request, pn); 693 if (! nn) 694 { 695 if (IS_OSPF6_DUMP_ROUTE) 696 { 697 ospf6_route_log_request ("Remove", table->name, request); 698 zlog_info ("ROUTE: Can't remove: No such nexthop"); 699 } 700 return; 701 } 702 703 if (memcmp (&nn->nexthop, &request->nexthop, sizeof (struct ospf6_nexthop))) 704 { 705 if (IS_OSPF6_DUMP_ROUTE) 706 { 707 ospf6_route_log_request ("Remove", table->name, request); 708 zlog_info ("ROUTE: Can't remove: Nexthop differ"); 709 } 710 return; 711 } 712 713 SET_FLAG (nn->flag, OSPF6_ROUTE_FLAG_REMOVE); 714 715 if (table->freeze) 716 return; 717 718 if (IS_OSPF6_DUMP_ROUTE) 719 ospf6_route_log_request ("Remove", table->name, request); 720 721 ospf6_route_request (&route, rn, pn, nn); 722 ospf6_route_hook_call (REMOVE, &route, table); 723 if (table->hook_remove) 724 (*table->hook_remove) (&route); 725 726 /* clear flag */ 727 nn->flag = 0; 728 729 /* remove nexthop */ 730 linklist_remove (nn, pn->nexthop_list); 731 rn->count--; 732 XFREE (MTYPE_OSPF6_ROUTE, nn); 733 734 /* remove path if there's no nexthop for the path */ 735 if (pn->nexthop_list->count != 0) 736 return; 737 linklist_remove (pn, rn->path_list); 738 linklist_delete (pn->nexthop_list); 739 XFREE (MTYPE_OSPF6_ROUTE, pn); 740 741 /* remove route if there's no path for the route */ 742 if (rn->path_list->count != 0) 743 return; 744 route_node->info = NULL; 745 linklist_delete (rn->path_list); 746 XFREE (MTYPE_OSPF6_ROUTE, rn); 747} 748 749void 750ospf6_route_remove_all (struct ospf6_route_table *table) 751{ 752 struct ospf6_route_req request; 753 754 for (ospf6_route_head (&request, table); ! ospf6_route_end (&request); 755 ospf6_route_next (&request)) 756 ospf6_route_remove (&request, table); 757} 758 759 760struct ospf6_route_table * 761ospf6_route_table_create (char *name) 762{ 763 int i; 764 struct ospf6_route_table *new; 765 766 new = XCALLOC (MTYPE_OSPF6_ROUTE, sizeof (struct ospf6_route_table)); 767 snprintf (new->name, sizeof (new->name), "%s", name); 768 769 new->table = route_table_init (); 770 for (i = 0; i < 3; i++) 771 new->hook_list[i] = linklist_create (); 772 773 return new; 774} 775 776void 777ospf6_route_table_delete (struct ospf6_route_table *table) 778{ 779 int i; 780 781 ospf6_route_remove_all (table); 782 route_table_finish (table->table); 783 for (i = 0; i < 3; i++) 784 linklist_delete (table->hook_list[i]); 785 XFREE (MTYPE_OSPF6_ROUTE, table); 786} 787 788void 789ospf6_route_table_freeze (struct ospf6_route_table *route_table) 790{ 791 if (IS_OSPF6_DUMP_ROUTE) 792 zlog_info ("ROUTE: Table freeze: %s", route_table->name); 793 assert (route_table->freeze == 0); 794 route_table->freeze = 1; 795} 796 797void 798ospf6_route_table_thaw (struct ospf6_route_table *route_table) 799{ 800 struct route_node *node; 801 struct linklist_node pnode; 802 struct linklist_node nnode; 803 804 struct ospf6_route_node *rn; 805 struct ospf6_path_node *pn; 806 struct ospf6_nexthop_node *nn; 807 808 struct ospf6_route_req request; 809 810 if (IS_OSPF6_DUMP_ROUTE) 811 zlog_info ("ROUTE: Table thaw: %s", route_table->name); 812 813 assert (route_table->freeze == 1); 814 route_table->freeze = 0; 815 816 for (node = route_top (route_table->table); node; 817 node = route_next (node)) 818 { 819 rn = node->info; 820 if (! rn) 821 continue; 822 823 for (linklist_head (rn->path_list, &pnode); 824 ! linklist_end (&pnode); 825 linklist_next (&pnode)) 826 { 827 pn = pnode.data; 828 829 for (linklist_head (pn->nexthop_list, &nnode); 830 ! linklist_end (&nnode); 831 linklist_next (&nnode)) 832 { 833 nn = nnode.data; 834 835 /* if the add and remove flag set without change flag, 836 do nothing with this route */ 837 if (! CHECK_FLAG (nn->flag, OSPF6_ROUTE_FLAG_CHANGE) && 838 CHECK_FLAG (nn->flag, OSPF6_ROUTE_FLAG_ADD) && 839 CHECK_FLAG (nn->flag, OSPF6_ROUTE_FLAG_REMOVE)) 840 { 841 nn->flag = 0; 842 continue; 843 } 844 845 memset (&request, 0, sizeof (request)); 846 memcpy (&request.route, &rn->route, sizeof (rn->route)); 847 memcpy (&request.path, &pn->path, sizeof (pn->path)); 848 memcpy (&request.nexthop, &nn->nexthop, sizeof (nn->nexthop)); 849 850 if (CHECK_FLAG (nn->flag, OSPF6_ROUTE_FLAG_ADD) || 851 CHECK_FLAG (nn->flag, OSPF6_ROUTE_FLAG_CHANGE)) 852 ospf6_route_add (&request, route_table); 853 else if (CHECK_FLAG (nn->flag, OSPF6_ROUTE_FLAG_REMOVE)) 854 ospf6_route_remove (&request, route_table); 855 } 856 } 857 } 858} 859 860 861/* VTY commands */ 862 863void 864ospf6_route_show (struct vty *vty, struct ospf6_route_node *rn) 865{ 866 struct linklist_node pnode; 867 struct linklist_node nnode; 868 struct ospf6_path_node *pn; 869 struct ospf6_nexthop_node *nn; 870 871 struct timeval now, res; 872 char duration[16]; 873 874 u_int pc = 0; 875 u_int nc = 0; 876#define HEAD (pc == 0 && nc == 0) 877 878 char prefix[64], nexthop[64], ifname[IFNAMSIZ]; 879 880 gettimeofday (&now, (struct timezone *) NULL); 881 882 /* destination */ 883 if (rn->route.prefix.family == AF_INET || 884 rn->route.prefix.family == AF_INET6) 885 prefix2str (&rn->route.prefix, prefix, sizeof (prefix)); 886 else 887 prefix_ls2str (&rn->route.prefix, prefix, sizeof (prefix)); 888 889 for (linklist_head (rn->path_list, &pnode); ! linklist_end (&pnode); 890 linklist_next (&pnode)) 891 { 892 pn = pnode.data; 893 894 for (linklist_head (pn->nexthop_list, &nnode); ! linklist_end (&nnode); 895 linklist_next (&nnode)) 896 { 897 nn = nnode.data; 898 899 inet_ntop (AF_INET6, &nn->nexthop.address, nexthop, 900 sizeof (nexthop)); 901 if (! if_indextoname (nn->nexthop.ifindex, ifname)) 902 snprintf (ifname, sizeof (ifname), "%d", nn->nexthop.ifindex); 903 904 ospf6_timeval_sub (&now, &nn->installed, &res); 905 ospf6_timeval_string_summary (&res, duration, sizeof (duration)); 906 907 vty_out (vty, "%c%1s %2s %-30s %-25s %6s %s%s", 908 (HEAD ? '*' : ' '), 909 DTYPE_ABNAME (rn->route.type), 910 PTYPE_ABNAME (pn->path.type), 911 prefix, nexthop, ifname, duration, VTY_NEWLINE); 912 913 nc++; 914 } 915 pc++; 916 } 917} 918 919void 920ospf6_route_show_detail (struct vty *vty, struct ospf6_route_node *rn) 921{ 922 struct linklist_node pnode; 923 struct linklist_node nnode; 924 struct ospf6_path_node *pn; 925 struct ospf6_nexthop_node *nn; 926 927 u_int pc = 0; 928 u_int nc = 0; 929 930 char prefix[64], nexthop[64], ifname[IFNAMSIZ]; 931 char area_id[16], type[16], id[16], adv[16]; 932 char capa[64]; 933 934 /* destination */ 935 if (rn->route.prefix.family == AF_INET || 936 rn->route.prefix.family == AF_INET6) 937 prefix2str (&rn->route.prefix, prefix, sizeof (prefix)); 938 else 939 prefix_ls2str (&rn->route.prefix, prefix, sizeof (prefix)); 940 941 vty_out (vty, "%s%s%s", VTY_NEWLINE, prefix, VTY_NEWLINE); 942 vty_out (vty, " Destination Type: %s%s", 943 DTYPE_NAME (rn->route.type), VTY_NEWLINE); 944 945 for (linklist_head (rn->path_list, &pnode); ! linklist_end (&pnode); 946 linklist_next (&pnode)) 947 { 948 pn = pnode.data; 949 950 inet_ntop (AF_INET, &pn->path.area_id, area_id, sizeof (area_id)); 951 ospf6_lsa_type_string (pn->path.origin.type, type, sizeof (type)); 952 inet_ntop (AF_INET, &pn->path.origin.id, id, sizeof (id)); 953 inet_ntop (AF_INET, &pn->path.origin.adv_router, adv, sizeof (adv)); 954 ospf6_options_string (pn->path.capability, capa, sizeof (capa)); 955 956 vty_out (vty, " Path:%s", VTY_NEWLINE); 957 vty_out (vty, " Associated Area: %s%s", area_id, VTY_NEWLINE); 958 vty_out (vty, " LS Origin: %s ID: %s Adv: %s%s", 959 type, id, adv, VTY_NEWLINE); 960 vty_out (vty, " Path Type: %s%s", 961 PTYPE_NAME (pn->path.type), VTY_NEWLINE); 962 vty_out (vty, " Metric Type: %d%s", 963 pn->path.metric_type, VTY_NEWLINE); 964 vty_out (vty, " Cost: Type-1: %lu Type-2: %lu%s", 965 (u_long) pn->path.cost, (u_long) pn->path.cost_e2, 966 VTY_NEWLINE); 967 vty_out (vty, " Router Bits: %s|%s|%s|%s%s", 968 (CHECK_FLAG (pn->path.router_bits, OSPF6_ROUTER_LSA_BIT_W) ? 969 "W" : "-"), 970 (CHECK_FLAG (pn->path.router_bits, OSPF6_ROUTER_LSA_BIT_V) ? 971 "V" : "-"), 972 (CHECK_FLAG (pn->path.router_bits, OSPF6_ROUTER_LSA_BIT_E) ? 973 "E" : "-"), 974 (CHECK_FLAG (pn->path.router_bits, OSPF6_ROUTER_LSA_BIT_B) ? 975 "B" : "-"), VTY_NEWLINE); 976 vty_out (vty, " Optional Capabilities: %s%s", capa, VTY_NEWLINE); 977 vty_out (vty, " Prefix Options: %s%s", "xxx", VTY_NEWLINE); 978 vty_out (vty, " Next Hops:%s", VTY_NEWLINE); 979 980 for (linklist_head (pn->nexthop_list, &nnode); ! linklist_end (&nnode); 981 linklist_next (&nnode)) 982 { 983 nn = nnode.data; 984 985 inet_ntop (AF_INET6, &nn->nexthop.address, nexthop, 986 sizeof (nexthop)); 987 if (! if_indextoname (nn->nexthop.ifindex, ifname)) 988 snprintf (ifname, sizeof (ifname), "%d", nn->nexthop.ifindex); 989 990 vty_out (vty, " %c%s%%%s%s", 991 (HEAD ? '*' : ' '), nexthop, ifname, VTY_NEWLINE); 992 993 nc++; 994 } 995 pc++; 996 } 997 vty_out (vty, "%s", VTY_NEWLINE); 998} 999 1000int 1001ospf6_route_table_show (struct vty *vty, int argc, char **argv, 1002 struct ospf6_route_table *table) 1003{ 1004 int i, ret; 1005 unsigned long ret_ul; 1006 char *endptr; 1007 struct prefix prefix; 1008 int detail = 0; 1009 int arg_ipv6 = 0; 1010 int arg_ipv4 = 0; 1011 int arg_digit = 0; 1012 struct prefix_ipv6 *p6 = (struct prefix_ipv6 *) &prefix; 1013 struct prefix_ls *pl = (struct prefix_ls *) &prefix; 1014 struct route_node *node; 1015 1016 memset (&prefix, 0, sizeof (struct prefix)); 1017 1018 for (i = 0; i < argc; i++) 1019 { 1020 if (! strcmp (argv[i], "detail")) 1021 { 1022 detail++; 1023 break; 1024 } 1025 1026 if (! arg_ipv6 && ! arg_ipv4 && ! arg_digit) 1027 { 1028 1029 if ((ret = inet_pton (AF_INET6, argv[i], &p6->prefix)) == 1) 1030 { 1031 p6->family = AF_INET6; 1032 p6->prefixlen = 128; 1033 arg_ipv6++; 1034 continue; 1035 } 1036 else if ((ret = inet_pton (AF_INET, argv[i], &pl->adv_router)) == 1) 1037 { 1038 pl->family = AF_UNSPEC; 1039 pl->prefixlen = 64; /* xxx */ 1040 arg_ipv4++; 1041 continue; 1042 } 1043 else 1044 { 1045 ret_ul = strtoul (argv[i], &endptr, 10); 1046 if (*endptr == '\0') 1047 { 1048 pl->adv_router.s_addr = htonl (ret_ul); 1049 pl->family = AF_UNSPEC; 1050 pl->prefixlen = 64; /* xxx */ 1051 arg_digit++; 1052 continue; 1053 } 1054 else 1055 { 1056 vty_out (vty, "Malformed argument: %s%s", 1057 argv[i], VTY_NEWLINE); 1058 return CMD_SUCCESS; 1059 } 1060 } 1061 } 1062 1063 if (arg_ipv4 || arg_digit) 1064 { 1065 if ((ret = inet_pton (AF_INET, argv[i], &pl->id)) == 1) 1066 { 1067 arg_ipv4++; 1068 } 1069 else 1070 { 1071 ret_ul = strtoul (argv[i], &endptr, 10); 1072 if (*endptr == '\0') 1073 { 1074 pl->id.s_addr = htonl (ret_ul); 1075 arg_digit++; 1076 } 1077 else 1078 { 1079 vty_out (vty, "Malformed argument: %s%s", 1080 argv[i], VTY_NEWLINE); 1081 return CMD_SUCCESS; 1082 } 1083 } 1084 } 1085 } 1086 1087 if (arg_ipv4 || arg_ipv6 || arg_digit) 1088 { 1089 node = route_node_match (table->table, &prefix); 1090 if (node && node->info) 1091 ospf6_route_show_detail (vty, node->info); 1092 return CMD_SUCCESS; 1093 } 1094 1095 if (! detail) 1096 { 1097 vty_out (vty, "%s%c%1s %2s %-30s %-25s %6s%s", VTY_NEWLINE, 1098 ' ', " ", " ", "Destination", "Gateway", "I/F", VTY_NEWLINE); 1099 vty_out (vty, "---------------------------%s", VTY_NEWLINE); 1100 } 1101 1102 for (node = route_top (table->table); node; node = route_next (node)) 1103 { 1104 if (! node->info) 1105 continue; 1106 1107 if (detail) 1108 ospf6_route_show_detail (vty, node->info); 1109 else 1110 ospf6_route_show (vty, node->info); 1111 } 1112 1113 return CMD_SUCCESS; 1114} 1115 1116