1/* 2 * Copyright (C) 2001 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 24void 25ospf6_asbr_external_lsa_update (struct ospf6_route_req *request) 26{ 27 char buffer [MAXLSASIZE]; 28 u_int16_t size; 29 struct ospf6_lsa_as_external *external; 30 char *p; 31 struct ospf6_route_req route; 32 char pbuf[BUFSIZ]; 33 34 /* assert this is best path; if not, return */ 35 ospf6_route_lookup (&route, &request->route.prefix, request->table); 36 if (memcmp (&route.path, &request->path, sizeof (route.path))) 37 return; 38 39 if (IS_OSPF6_DUMP_LSA) 40 zlog_info ("Update AS-External: ID: %lu", 41 (u_long) ntohl (request->path.origin.id)); 42 43 /* prepare buffer */ 44 memset (buffer, 0, sizeof (buffer)); 45 size = sizeof (struct ospf6_lsa_as_external); 46 external = (struct ospf6_lsa_as_external *) buffer; 47 p = (char *) (external + 1); 48 49 if (route.path.metric_type == 2) 50 SET_FLAG (external->bits_metric, OSPF6_ASBR_BIT_E); /* type2 */ 51 else 52 UNSET_FLAG (external->bits_metric, OSPF6_ASBR_BIT_E); /* type1 */ 53 54 /* forwarding address */ 55 if (! IN6_IS_ADDR_UNSPECIFIED (&route.nexthop.address)) 56 SET_FLAG (external->bits_metric, OSPF6_ASBR_BIT_F); 57 else 58 UNSET_FLAG (external->bits_metric, OSPF6_ASBR_BIT_F); 59 60 /* external route tag */ 61 UNSET_FLAG (external->bits_metric, OSPF6_ASBR_BIT_T); 62 63 /* set metric. note: related to E bit */ 64 OSPF6_ASBR_METRIC_SET (external, route.path.cost); 65 66 /* prefixlen */ 67 external->prefix.prefix_length = route.route.prefix.prefixlen; 68 69 /* PrefixOptions */ 70 external->prefix.prefix_options = route.path.prefix_options; 71 72 /* don't use refer LS-type */ 73 external->prefix.prefix_refer_lstype = htons (0); 74 75 if (IS_OSPF6_DUMP_LSA) 76 { 77 prefix2str (&route.route.prefix, pbuf, sizeof (pbuf)); 78 zlog_info (" Prefix: %s", pbuf); 79 } 80 81 /* set Prefix */ 82 memcpy (p, &route.route.prefix.u.prefix6, 83 OSPF6_PREFIX_SPACE (route.route.prefix.prefixlen)); 84 ospf6_prefix_apply_mask (&external->prefix); 85 size += OSPF6_PREFIX_SPACE (route.route.prefix.prefixlen); 86 p += OSPF6_PREFIX_SPACE (route.route.prefix.prefixlen); 87 88 /* Forwarding address */ 89 if (CHECK_FLAG (external->bits_metric, OSPF6_ASBR_BIT_F)) 90 { 91 memcpy (p, &route.nexthop.address, sizeof (struct in6_addr)); 92 size += sizeof (struct in6_addr); 93 p += sizeof (struct in6_addr); 94 } 95 96 /* External Route Tag */ 97 if (CHECK_FLAG (external->bits_metric, OSPF6_ASBR_BIT_T)) 98 { 99 /* xxx */ 100 } 101 102 ospf6_lsa_originate (htons (OSPF6_LSA_TYPE_AS_EXTERNAL), 103 route.path.origin.id, ospf6->router_id, 104 (char *) external, size, ospf6); 105 return; 106} 107 108void 109ospf6_asbr_external_route_add (struct ospf6_route_req *route) 110{ 111 ospf6_asbr_external_lsa_update (route); 112} 113 114void 115ospf6_asbr_external_route_remove (struct ospf6_route_req *route) 116{ 117 struct ospf6_lsa *lsa; 118 119 lsa = ospf6_lsdb_lookup_lsdb (htons (OSPF6_LSA_TYPE_AS_EXTERNAL), 120 htonl (route->path.origin.id), 121 ospf6->router_id, ospf6->lsdb); 122 if (lsa) 123 ospf6_lsa_premature_aging (lsa); 124} 125 126void 127ospf6_asbr_external_lsa_add (struct ospf6_lsa *lsa) 128{ 129 struct ospf6_lsa_as_external *external; 130 struct prefix_ls asbr_id; 131 struct ospf6_route_req asbr_entry; 132 struct ospf6_route_req request; 133 134 external = OSPF6_LSA_HEADER_END (lsa->header); 135 136 if (IS_LSA_MAXAGE (lsa)) 137 return; 138 139 if (IS_OSPF6_DUMP_ASBR) 140 zlog_info ("ASBR: Calculate %s", lsa->str); 141 142 if (lsa->header->adv_router == ospf6->router_id) 143 { 144 if (IS_OSPF6_DUMP_ASBR) 145 zlog_info ("ASBR: Self-originated, ignore"); 146 return; 147 } 148 149 if (OSPF6_ASBR_METRIC (external) == LS_INFINITY) 150 { 151 if (IS_OSPF6_DUMP_ASBR) 152 zlog_info ("ASBR: Metric is Infinity, ignore"); 153 return; 154 } 155 156 memset (&asbr_id, 0, sizeof (asbr_id)); 157 asbr_id.family = AF_UNSPEC; 158 asbr_id.prefixlen = 64; /* xxx */ 159 asbr_id.adv_router.s_addr = lsa->header->adv_router; 160 161 ospf6_route_lookup (&asbr_entry, (struct prefix *) &asbr_id, 162 ospf6->topology_table); 163 164 if (ospf6_route_end (&asbr_entry)) 165 { 166 if (IS_OSPF6_DUMP_ASBR) 167 { 168 char buf[64]; 169 inet_ntop (AF_INET, &asbr_id.adv_router, buf, sizeof (buf)); 170 zlog_info ("ASBR: ASBR %s not found, ignore", buf); 171 } 172 return; 173 } 174 175 memset (&request, 0, sizeof (request)); 176 request.route.type = OSPF6_DEST_TYPE_NETWORK; 177 request.route.prefix.family = AF_INET6; 178 request.route.prefix.prefixlen = external->prefix.prefix_length; 179 memcpy (&request.route.prefix.u.prefix6, (char *)(external + 1), 180 OSPF6_PREFIX_SPACE (request.route.prefix.prefixlen)); 181 182 request.path.area_id = asbr_entry.path.area_id; 183 request.path.origin.type = htons (OSPF6_LSA_TYPE_AS_EXTERNAL); 184 request.path.origin.id = lsa->header->id; 185 request.path.origin.adv_router = lsa->header->adv_router; 186 if (CHECK_FLAG (external->bits_metric, OSPF6_ASBR_BIT_E)) 187 { 188 request.path.type = OSPF6_PATH_TYPE_EXTERNAL2; 189 request.path.metric_type = 2; 190 request.path.cost = asbr_entry.path.cost; 191 request.path.cost_e2 = OSPF6_ASBR_METRIC (external); 192 } 193 else 194 { 195 request.path.type = OSPF6_PATH_TYPE_EXTERNAL1; 196 request.path.metric_type = 1; 197 request.path.cost = asbr_entry.path.cost 198 + OSPF6_ASBR_METRIC (external); 199 request.path.cost_e2 = 0; 200 } 201 request.path.prefix_options = external->prefix.prefix_options; 202 203 while (((struct prefix_ls *)&asbr_entry.route.prefix)->adv_router.s_addr == 204 asbr_id.adv_router.s_addr && 205 asbr_entry.route.type == OSPF6_DEST_TYPE_ROUTER) 206 { 207 memcpy (&request.nexthop, &asbr_entry.nexthop, 208 sizeof (struct ospf6_nexthop)); 209 ospf6_route_add (&request, ospf6->route_table); 210 ospf6_route_next (&asbr_entry); 211 } 212} 213 214void 215ospf6_asbr_external_lsa_remove (struct ospf6_lsa *lsa) 216{ 217 struct ospf6_lsa_as_external *external; 218 struct prefix dest; 219 char buf[64]; 220 struct ospf6_route_req request; 221 222 if (IS_OSPF6_DUMP_ASBR) 223 zlog_info ("ASBR: Withdraw route of %s", lsa->str); 224 225 if (lsa->header->adv_router == ospf6->router_id) 226 { 227 if (IS_OSPF6_DUMP_ASBR) 228 zlog_info ("ASBR: Self-originated, ignore"); 229 return; 230 } 231 232 external = OSPF6_LSA_HEADER_END (lsa->header); 233 memset (&dest, 0, sizeof (dest)); 234 dest.family = AF_INET6; 235 dest.prefixlen = external->prefix.prefix_length; 236 memcpy (&dest.u.prefix6, (char *)(external + 1), 237 OSPF6_PREFIX_SPACE (dest.prefixlen)); 238 239 prefix2str (&dest, buf, sizeof (buf)); 240 if (IS_OSPF6_DUMP_ASBR) 241 zlog_info ("ASBR: route: %s", buf); 242 243 ospf6_route_lookup (&request, &dest, ospf6->route_table); 244 if (ospf6_route_end (&request)) 245 { 246 zlog_info ("ASBR: route not found"); 247 return; 248 } 249 250 while (request.path.origin.id != lsa->header->id || 251 request.path.origin.adv_router != lsa->header->adv_router) 252 { 253 if (prefix_same (&request.route.prefix, &dest) != 1) 254 { 255 zlog_info ("ASBR: Can't find the entry matches the origin"); 256 return; 257 } 258 ospf6_route_next (&request); 259 } 260 assert (request.path.origin.id == lsa->header->id); 261 assert (request.path.origin.adv_router == request.path.origin.adv_router); 262 263 while (request.path.origin.id == lsa->header->id && 264 request.path.origin.adv_router == lsa->header->adv_router && 265 prefix_same (&request.route.prefix, &dest) == 1) 266 { 267 ospf6_route_remove (&request, ospf6->route_table); 268 ospf6_route_next (&request); 269 } 270} 271 272void 273ospf6_asbr_external_lsa_change (struct ospf6_lsa *old, struct ospf6_lsa *new) 274{ 275 assert (old || new); 276 277 if (old == NULL) 278 ospf6_asbr_external_lsa_add (new); 279 else if (new == NULL) 280 ospf6_asbr_external_lsa_remove (old); 281 else 282 { 283 ospf6_route_table_freeze (ospf6->route_table); 284 ospf6_asbr_external_lsa_remove (old); 285 ospf6_asbr_external_lsa_add (new); 286 ospf6_route_table_thaw (ospf6->route_table); 287 } 288} 289 290void 291ospf6_asbr_asbr_entry_add (struct ospf6_route_req *topo_entry) 292{ 293 struct ospf6_lsdb_node node; 294 295 struct prefix_ls *inter_router; 296 u_int32_t id, adv_router; 297 298 inter_router = (struct prefix_ls *) &topo_entry->route.prefix; 299 id = inter_router->id.s_addr; 300 adv_router = inter_router->adv_router.s_addr; 301 302 if (IS_OSPF6_DUMP_ASBR) 303 { 304 char buf[64]; 305 inet_ntop (AF_INET, &inter_router->adv_router, buf, sizeof (buf)); 306 zlog_info ("ASBR: New router found: %s", buf); 307 } 308 309 if (ntohl (id) != 0 || 310 ! OSPF6_OPT_ISSET (topo_entry->path.capability, OSPF6_OPT_E)) 311 { 312 zlog_warn ("ASBR: Inter topology table malformed"); 313 return; 314 } 315 316 for (ospf6_lsdb_type_router (&node, htons (OSPF6_LSA_TYPE_AS_EXTERNAL), 317 adv_router, ospf6->lsdb); 318 ! ospf6_lsdb_is_end (&node); 319 ospf6_lsdb_next (&node)) 320 ospf6_asbr_external_lsa_add (node.lsa); 321} 322 323void 324ospf6_asbr_asbr_entry_remove (struct ospf6_route_req *topo_entry) 325{ 326 struct prefix_ls *inter_router; 327 u_int32_t id, adv_router; 328 struct ospf6_route_req request; 329 330 inter_router = (struct prefix_ls *) &topo_entry->route.prefix; 331 id = inter_router->id.s_addr; 332 adv_router = inter_router->adv_router.s_addr; 333 334 if (IS_OSPF6_DUMP_ASBR) 335 { 336 char buf[64]; 337 inet_ntop (AF_INET, &inter_router->adv_router, buf, sizeof (buf)); 338 zlog_info ("ASBR: Router disappearing: %s", buf); 339 } 340 341 if (ntohl (id) != 0 || 342 ! OSPF6_OPT_ISSET (topo_entry->path.capability, OSPF6_OPT_E)) 343 { 344 zlog_warn ("ASBR: Inter topology table malformed"); 345 } 346 347 for (ospf6_route_head (&request, ospf6->route_table); 348 ! ospf6_route_end (&request); 349 ospf6_route_next (&request)) 350 { 351 if (request.path.type != OSPF6_PATH_TYPE_EXTERNAL1 && 352 request.path.type != OSPF6_PATH_TYPE_EXTERNAL2) 353 continue; 354 if (request.path.area_id != topo_entry->path.area_id) 355 continue; 356 if (request.path.origin.adv_router != topo_entry->path.origin.adv_router) 357 continue; 358 if (memcmp (&topo_entry->nexthop, &request.nexthop, 359 sizeof (struct ospf6_nexthop))) 360 continue; 361 362 ospf6_route_remove (&request, ospf6->route_table); 363 } 364} 365 366int 367ospf6_asbr_external_show (struct vty *vty, struct ospf6_lsa *lsa) 368{ 369 struct ospf6_lsa_as_external *external; 370 char buf[128], *ptr; 371 struct in6_addr in6; 372 373 assert (lsa->header); 374 external = (struct ospf6_lsa_as_external *)(lsa->header + 1); 375 376 /* bits */ 377 snprintf (buf, sizeof (buf), "%s%s%s", 378 (CHECK_FLAG (external->bits_metric, OSPF6_ASBR_BIT_E) ? 379 "E" : "-"), 380 (CHECK_FLAG (external->bits_metric, OSPF6_ASBR_BIT_F) ? 381 "F" : "-"), 382 (CHECK_FLAG (external->bits_metric, OSPF6_ASBR_BIT_T) ? 383 "T" : "-")); 384 385 vty_out (vty, " Bits: %s%s", buf, VTY_NEWLINE); 386 vty_out (vty, " Metric: %5lu%s", (u_long)OSPF6_ASBR_METRIC (external), 387 VTY_NEWLINE); 388 389 ospf6_prefix_options_str (external->prefix.prefix_options, 390 buf, sizeof (buf)); 391 vty_out (vty, " Prefix Options: %s%s", buf, VTY_NEWLINE); 392 393 vty_out (vty, " Referenced LSType: %d%s", 394 ntohs (external->prefix.prefix_refer_lstype), VTY_NEWLINE); 395 396 ospf6_prefix_in6_addr (&external->prefix, &in6); 397 inet_ntop (AF_INET6, &in6, buf, sizeof (buf)); 398 vty_out (vty, " Prefix: %s/%d%s", 399 buf, external->prefix.prefix_length, VTY_NEWLINE); 400 401 /* Forwarding-Address */ 402 if (CHECK_FLAG (external->bits_metric, OSPF6_ASBR_BIT_F)) 403 { 404 ptr = ((char *)(external + 1)) 405 + OSPF6_PREFIX_SPACE (external->prefix.prefix_length); 406 inet_ntop (AF_INET6, (struct in6_addr *) ptr, buf, sizeof (buf)); 407 vty_out (vty, " Forwarding-Address: %s%s", buf, VTY_NEWLINE); 408 } 409 410 return 0; 411} 412 413int 414ospf6_asbr_external_refresh (void *old) 415{ 416 struct ospf6_lsa *lsa = old; 417 struct ospf6_route_req route, *target; 418 419 assert (ospf6); 420 421 target = NULL; 422 for (ospf6_route_head (&route, ospf6->external_table); 423 ! ospf6_route_end (&route); 424 ospf6_route_next (&route)) 425 { 426 if (route.path.origin.id == lsa->header->id) 427 { 428 target = &route; 429 break; 430 } 431 } 432 433 if (target) 434 ospf6_asbr_external_lsa_update (target); 435 else 436 ospf6_lsa_premature_aging (lsa); 437 438 return 0; 439} 440 441void 442ospf6_asbr_database_hook (struct ospf6_lsa *old, struct ospf6_lsa *new) 443{ 444 if (old) 445 ospf6_asbr_external_lsa_remove (old); 446 if (new && ! IS_LSA_MAXAGE (new)) 447 ospf6_asbr_external_lsa_add (new); 448} 449 450void 451ospf6_asbr_register_as_external () 452{ 453 struct ospf6_lsa_slot slot; 454 455 memset (&slot, 0, sizeof (slot)); 456 slot.type = htons (OSPF6_LSA_TYPE_AS_EXTERNAL); 457 slot.name = "AS-External"; 458 slot.func_show = ospf6_asbr_external_show; 459 slot.func_refresh = ospf6_asbr_external_refresh; 460 ospf6_lsa_slot_register (&slot); 461 462 ospf6_lsdb_hook[OSPF6_LSA_TYPE_AS_EXTERNAL & OSPF6_LSTYPE_CODE_MASK].hook = 463 ospf6_asbr_database_hook; 464} 465 466void 467ospf6_asbr_init () 468{ 469 ospf6_asbr_register_as_external (); 470} 471 472 473