1/* 2 * OSPF AS Boundary Router functions. 3 * Copyright (C) 1999, 2000 Kunihiro Ishiguro, Toshiaki Takada 4 * 5 * This file is part of GNU Zebra. 6 * 7 * GNU Zebra is free software; you can redistribute it and/or modify it 8 * under the terms of the GNU General Public License as published by the 9 * Free Software Foundation; either version 2, or (at your option) any 10 * later version. 11 * 12 * GNU Zebra is distributed in the hope that it will be useful, but 13 * WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 * General Public License for more details. 16 * 17 * You should have received a copy of the GNU General Public License 18 * along with GNU Zebra; see the file COPYING. If not, write to the Free 19 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 20 * 02111-1307, USA. 21 */ 22 23#include <zebra.h> 24 25#include "thread.h" 26#include "memory.h" 27#include "linklist.h" 28#include "prefix.h" 29#include "if.h" 30#include "table.h" 31#include "vty.h" 32#include "filter.h" 33#include "log.h" 34 35#include "ospfd/ospfd.h" 36#include "ospfd/ospf_interface.h" 37#include "ospfd/ospf_asbr.h" 38#include "ospfd/ospf_lsa.h" 39#include "ospfd/ospf_lsdb.h" 40#include "ospfd/ospf_neighbor.h" 41#include "ospfd/ospf_spf.h" 42#include "ospfd/ospf_flood.h" 43#include "ospfd/ospf_route.h" 44#include "ospfd/ospf_zebra.h" 45#include "ospfd/ospf_dump.h" 46 47/* Remove external route. */ 48void 49ospf_external_route_remove (struct prefix_ipv4 *p) 50{ 51 struct route_node *rn; 52 struct ospf_route *or; 53 54 rn = route_node_lookup (ospf_top->old_external_route, (struct prefix *) p); 55 if (rn) 56 if ((or = rn->info)) 57 { 58 zlog_info ("Route[%s/%d]: external path deleted", 59 inet_ntoa (p->prefix), p->prefixlen); 60 61 /* Remove route from zebra. */ 62 if (or->type == OSPF_DESTINATION_NETWORK) 63 ospf_zebra_delete ((struct prefix_ipv4 *) &rn->p, or); 64 65 ospf_route_free (or); 66 rn->info = NULL; 67 68 route_unlock_node (rn); 69 route_unlock_node (rn); 70 return; 71 } 72 73 zlog_info ("Route[%s/%d]: no such external path", 74 inet_ntoa (p->prefix), p->prefixlen); 75} 76 77/* Lookup external route. */ 78struct ospf_route * 79ospf_external_route_lookup (struct prefix_ipv4 *p) 80{ 81 struct route_node *rn; 82 83 rn = route_node_lookup (ospf_top->old_external_route, (struct prefix *) p); 84 if (rn) 85 { 86 route_unlock_node (rn); 87 if (rn->info) 88 return rn->info; 89 } 90 91 zlog_warn ("Route[%s/%d]: lookup, no such prefix", 92 inet_ntoa (p->prefix), p->prefixlen); 93 94 return NULL; 95} 96 97 98/* Add an External info for AS-external-LSA. */ 99struct external_info * 100ospf_external_info_new (u_char type) 101{ 102 struct external_info *new; 103 104 new = (struct external_info *) 105 XMALLOC (MTYPE_OSPF_EXTERNAL_INFO, sizeof (struct external_info)); 106 memset (new, 0, sizeof (struct external_info)); 107 new->type = type; 108 109 ospf_reset_route_map_set_values (&new->route_map_set); 110 return new; 111} 112 113void 114ospf_external_info_free (struct external_info *ei) 115{ 116 XFREE (MTYPE_OSPF_EXTERNAL_INFO, ei); 117} 118 119void 120ospf_reset_route_map_set_values (struct route_map_set_values *values) 121{ 122 values->metric = -1; 123 values->metric_type = -1; 124} 125 126int 127ospf_route_map_set_compare (struct route_map_set_values *values1, 128 struct route_map_set_values *values2) 129{ 130 return values1->metric == values2->metric && 131 values1->metric_type == values2->metric_type; 132} 133 134/* Add an External info for AS-external-LSA. */ 135struct external_info * 136ospf_external_info_add (u_char type, struct prefix_ipv4 p, 137 unsigned int ifindex, struct in_addr nexthop) 138{ 139 struct external_info *new; 140 struct route_node *rn; 141 142 /* Initialize route table. */ 143 if (EXTERNAL_INFO (type) == NULL) 144 EXTERNAL_INFO (type) = route_table_init (); 145 146 rn = route_node_get (EXTERNAL_INFO (type), (struct prefix *) &p); 147 /* If old info exists, -- discard new one or overwrite with new one? */ 148 if (rn) 149 if (rn->info) 150 { 151 route_unlock_node (rn); 152 zlog_warn ("Redistribute[%s]: %s/%d already exists, discard.", 153 LOOKUP (ospf_redistributed_proto, type), 154 inet_ntoa (p.prefix), p.prefixlen); 155 /* XFREE (MTYPE_OSPF_TMP, rn->info); */ 156 return rn->info; 157 } 158 159 /* Create new External info instance. */ 160 new = ospf_external_info_new (type); 161 new->p = p; 162 new->ifindex = ifindex; 163 new->nexthop = nexthop; 164 new->tag = 0; 165 166 rn->info = new; 167 168 if (IS_DEBUG_OSPF (lsa, LSA_GENERATE)) 169 zlog_info ("Redistribute[%s]: %s/%d external info created.", 170 LOOKUP (ospf_redistributed_proto, type), 171 inet_ntoa (p.prefix), p.prefixlen); 172 return new; 173} 174 175void 176ospf_external_info_delete (u_char type, struct prefix_ipv4 p) 177{ 178 struct route_node *rn; 179 180 rn = route_node_lookup (EXTERNAL_INFO (type), (struct prefix *) &p); 181 if (rn) 182 { 183 ospf_external_info_free (rn->info); 184 rn->info = NULL; 185 route_unlock_node (rn); 186 route_unlock_node (rn); 187 } 188} 189 190struct external_info * 191ospf_external_info_lookup (u_char type, struct prefix_ipv4 *p) 192{ 193 struct route_node *rn; 194 rn = route_node_lookup (EXTERNAL_INFO (type), (struct prefix *) p); 195 if (rn) 196 { 197 route_unlock_node (rn); 198 if (rn->info) 199 return rn->info; 200 } 201 202 return NULL; 203} 204 205struct ospf_lsa * 206ospf_external_info_find_lsa (struct prefix_ipv4 *p) 207{ 208 struct ospf_lsa *lsa; 209 struct as_external_lsa *al; 210 struct in_addr mask, id; 211 212 lsa = ospf_lsdb_lookup_by_id (ospf_top->lsdb, OSPF_AS_EXTERNAL_LSA, 213 p->prefix, ospf_top->router_id); 214 215 if (!lsa) 216 return NULL; 217 218 al = (struct as_external_lsa *) lsa->data; 219 220 masklen2ip (p->prefixlen, &mask); 221 222 if (mask.s_addr != al->mask.s_addr) 223 { 224 id.s_addr = p->prefix.s_addr | (~mask.s_addr); 225 lsa = ospf_lsdb_lookup_by_id (ospf_top->lsdb, OSPF_AS_EXTERNAL_LSA, 226 id, ospf_top->router_id); 227 if (!lsa) 228 return NULL; 229 } 230 231 return lsa; 232} 233 234 235/* Update ASBR status. */ 236void 237ospf_asbr_status_update (u_char status) 238{ 239 zlog_info ("ASBR[Status:%d]: Update", status); 240 241 /* ASBR on. */ 242 if (status) 243 { 244 /* Already ASBR. */ 245 if (OSPF_IS_ASBR) 246 { 247 zlog_info ("ASBR[Status:%d]: Already ASBR", status); 248 return; 249 } 250 SET_FLAG (ospf_top->flags, OSPF_FLAG_ASBR); 251 } 252 else 253 { 254 /* Already non ASBR. */ 255 if (! OSPF_IS_ASBR) 256 { 257 zlog_info ("ASBR[Status:%d]: Already non ASBR", status); 258 return; 259 } 260 UNSET_FLAG (ospf_top->flags, OSPF_FLAG_ASBR); 261 } 262 263 /* Transition from/to status ASBR, schedule timer. */ 264 ospf_spf_calculate_schedule (); 265 OSPF_TIMER_ON (ospf_top->t_router_lsa_update, 266 ospf_router_lsa_update_timer, OSPF_LSA_UPDATE_DELAY); 267} 268 269void 270ospf_redistribute_withdraw (u_char type) 271{ 272 struct route_node *rn; 273 struct external_info *ei; 274 275 /* Delete external info for specified type. */ 276 if (EXTERNAL_INFO (type)) 277 for (rn = route_top (EXTERNAL_INFO (type)); rn; rn = route_next (rn)) 278 if ((ei = rn->info)) 279 if (ospf_external_info_find_lsa (&ei->p)) 280 { 281 if (is_prefix_default (&ei->p) && 282 ospf_top->default_originate != DEFAULT_ORIGINATE_NONE) 283 continue; 284 ospf_external_lsa_flush (type, &ei->p, ei->ifindex, ei->nexthop); 285 ospf_external_info_delete (type, ei->p); 286 } 287} 288