void ospf_delete_from_if (struct interface *ifp, struct ospf_interface *oi) { struct route_node *rn; struct prefix p; p = *oi->address; p.prefixlen = IPV4_MAX_PREFIXLEN; rn = route_node_lookup (IF_OIFS (oi->ifp), &p); assert (rn); assert (rn->info); rn->info = NULL; route_unlock_node (rn); route_unlock_node (rn); }
/* Check wether connected is within the ripng_enable_network table. */ static int ripng_enable_network_lookup2 (struct connected *connected) { struct prefix_ipv6 address; struct prefix *p; p = connected->address; if (p->family == AF_INET6) { struct route_node *node; address.family = p->family; address.prefix = p->u.prefix6; address.prefixlen = IPV6_MAX_BITLEN; /* LPM on p->family, p->u.prefix6/IPV6_MAX_BITLEN within ripng_enable_network */ node = route_node_match (ripng_enable_network, (struct prefix *)&address); if (node) { route_unlock_node (node); return 1; } } return -1; }
/* Install external reachability information into a * specific area for a specific level. * Schedule an lsp regenerate if necessary */ static void isis_redist_install(struct isis_area *area, int level, struct prefix *p, struct isis_ext_info *info) { int family = p->family; struct route_table *er_table = get_ext_reach(area, family, level); struct route_node *er_node; if (!er_table) { zlog_warn("%s: External reachability table of area %s" " is not initialized.", __func__, area->area_tag); return; } er_node = route_node_get(er_table, p); if (er_node->info) { route_unlock_node(er_node); /* Don't update/reschedule lsp generation if nothing changed. */ if (!memcmp(er_node->info, info, sizeof(*info))) return; } else { er_node->info = XMALLOC(MTYPE_ISIS, sizeof(*info)); } memcpy(er_node->info, info, sizeof(*info)); lsp_regenerate_schedule(area, level, 0); }
void ospf6_lsdb_remove (struct ospf6_lsa *lsa, struct ospf6_lsdb *lsdb) { struct route_node *node; struct prefix_ipv6 key; memset (&key, 0, sizeof (key)); ospf6_lsdb_set_key (&key, &lsa->header->type, sizeof (lsa->header->type)); ospf6_lsdb_set_key (&key, &lsa->header->adv_router, sizeof (lsa->header->adv_router)); ospf6_lsdb_set_key (&key, &lsa->header->id, sizeof (lsa->header->id)); node = route_node_lookup (lsdb->table, (struct prefix *) &key); assert (node && node->info == lsa); if (lsa->prev) lsa->prev->next = lsa->next; if (lsa->next) lsa->next->prev = lsa->prev; node->info = NULL; lsdb->count--; if (lsdb->hook_remove) (*lsdb->hook_remove) (lsa); ospf6_lsa_unlock (lsa); route_unlock_node (node); ospf6_lsdb_count_assert (lsdb); }
struct ospf6_lsa * ospf6_lsdb_type_head (u_int16_t type, struct ospf6_lsdb *lsdb) { struct route_node *node; struct prefix_ipv6 key; struct ospf6_lsa *lsa; memset (&key, 0, sizeof (key)); ospf6_lsdb_set_key (&key, &type, sizeof (type)); /* Walk down tree. */ node = lsdb->table->top; while (node && node->p.prefixlen <= key.prefixlen && prefix_match (&node->p, (struct prefix *) &key)) node = node->link[prefix6_bit(&key.prefix, node->p.prefixlen)]; if (node) route_lock_node (node); while (node && node->info == NULL) node = route_next (node); if (node == NULL) return NULL; else route_unlock_node (node); if (! prefix_match ((struct prefix *) &key, &node->p)) return NULL; lsa = node->info; ospf6_lsa_lock (lsa); return lsa; }
struct interface * rip_ifaddr_lookup_next (struct in_addr *addr) { struct prefix_ipv4 p; struct route_node *rn; struct interface *ifp; p.family = AF_INET; p.prefixlen = IPV4_MAX_BITLEN; p.prefix = *addr; rn = route_node_get (rip_ifaddr_table, (struct prefix *) &p); for (rn = route_next (rn); rn; rn = route_next (rn)) if (rn->info) break; if (rn && rn->info) { ifp = rn->info; *addr = rn->p.u.prefix4; route_unlock_node (rn); return ifp; } return NULL; }
/* Check wether the interface has at least a connected prefix that * is within the ripng_enable_network table. */ static int ripng_enable_network_lookup_if (struct interface *ifp) { struct listnode *node; struct connected *connected; struct prefix_ipv6 address; for (ALL_LIST_ELEMENTS_RO (ifp->connected, node, connected)) { struct prefix *p; struct route_node *node; p = connected->address; if (p->family == AF_INET6) { address.family = AF_INET6; address.prefix = p->u.prefix6; address.prefixlen = IPV6_MAX_BITLEN; node = route_node_match (ripng_enable_network, (struct prefix *)&address); if (node) { route_unlock_node (node); return 1; } } } return -1; }
/* Check LSA is related to external info. */ struct external_info * ospf_external_info_check (struct ospf_lsa *lsa) { struct as_external_lsa *al; struct prefix_ipv4 p; struct route_node *rn; int type; al = (struct as_external_lsa *) lsa->data; p.family = AF_INET; p.prefix = lsa->data->id; p.prefixlen = ip_masklen (al->mask); for (type = 0; type <= ZEBRA_ROUTE_MAX; type++) { int redist_type = is_prefix_default (&p) ? DEFAULT_ROUTE : type; if (ospf_is_type_redistributed (redist_type)) if (EXTERNAL_INFO (type)) { rn = route_node_lookup (EXTERNAL_INFO (type), (struct prefix *) &p); if (rn) { route_unlock_node (rn); if (rn->info != NULL) return (struct external_info *) rn->info; } } } return NULL; }
struct ospf_neighbor *ospf_nbr_get(struct ospf_interface *oi, struct ospf_header *ospfh, struct ip *iph, struct prefix *p) { struct route_node *rn; struct prefix key; struct ospf_neighbor *nbr; key.family = AF_INET; key.prefixlen = IPV4_MAX_BITLEN; if (oi->type == OSPF_IFTYPE_VIRTUALLINK) key.u.prefix4 = ospfh->router_id; /* index vlink nbrs by router-id */ else key.u.prefix4 = iph->ip_src; rn = route_node_get(oi->nbrs, &key); if (rn->info) { route_unlock_node(rn); nbr = rn->info; if (oi->type == OSPF_IFTYPE_NBMA && nbr->state == NSM_Attempt) { nbr->src = iph->ip_src; memcpy(&nbr->address, p, sizeof(struct prefix)); } } else { rn->info = nbr = ospf_nbr_add(oi, ospfh, p); } nbr->router_id = ospfh->router_id; return nbr; }
void ospf_area_range_delete (struct ospf_area *area, struct ospf_area_range *range) { struct route_node *rn; struct prefix_ipv4 p; p.family = AF_INET; p.prefixlen = range->masklen; p.prefix = range->addr; rn = route_node_lookup (area->ranges, (struct prefix *)&p); if (rn) { ospf_area_range_free (rn->info); rn->info = NULL; route_unlock_node (rn); route_unlock_node (rn); } }
/* Untie an interface address from its derived subnet list of addresses. */ int if_subnet_delete (struct interface *ifp, struct connected *ifc) { struct route_node *rn; struct zebra_if *zebra_if; struct list *addr_list; assert (ifp && ifp->info && ifc); zebra_if = ifp->info; /* Get address derived subnet node. */ rn = route_node_lookup (zebra_if->ipv4_subnets, ifc->address); if (! (rn && rn->info)) return -1; route_unlock_node (rn); /* Untie address from subnet's address list. */ addr_list = rn->info; listnode_delete (addr_list, ifc); route_unlock_node (rn); /* Return list element count, if not empty. */ if (addr_list->count) { /* If deleted address is primary, mark subsequent one as such and distribute. */ if (! CHECK_FLAG (ifc->flags, ZEBRA_IFA_SECONDARY)) { ifc = listgetdata (listhead (addr_list)); zebra_interface_address_delete_update (ifp, ifc); UNSET_FLAG (ifc->flags, ZEBRA_IFA_SECONDARY); zebra_interface_address_add_update (ifp, ifc); } return addr_list->count; } /* Otherwise, free list and route node. */ list_free (addr_list); rn->info = NULL; route_unlock_node (rn); return 0; }
/* Delete RIPng enable network. */ static int ripng_enable_network_delete (struct prefix *p) { struct route_node *node; node = route_node_lookup (ripng_enable_network, p); if (node) { node->info = NULL; /* Unlock info lock. */ route_unlock_node (node); /* Unlock lookup lock. */ route_unlock_node (node); return 1; } return -1; }
/* Delete RIP neighbor from the neighbor tree. */ static int rip_neighbor_delete (struct prefix_ipv4 *p) { struct route_node *node; /* Lock for look up. */ node = route_node_lookup (rip->neighbor, (struct prefix *) p); if (! node) return -1; node->info = NULL; /* Unlock lookup lock. */ route_unlock_node (node); /* Unlock real neighbor information lock. */ route_unlock_node (node); return 0; }
/* Check LSA is related to external info. */ struct external_info *ospf_external_info_check(struct ospf *ospf, struct ospf_lsa *lsa) { struct as_external_lsa *al; struct prefix_ipv4 p; struct route_node *rn; int type; al = (struct as_external_lsa *)lsa->data; p.family = AF_INET; p.prefix = lsa->data->id; p.prefixlen = ip_masklen(al->mask); for (type = 0; type < ZEBRA_ROUTE_MAX; type++) { int redist_on = 0; redist_on = is_prefix_default(&p) ? vrf_bitmap_check(zclient->default_information, ospf->vrf_id) : (zclient->mi_redist[AFI_IP][type].enabled || vrf_bitmap_check( zclient->redist[AFI_IP][type], ospf->vrf_id)); // Pending: check for MI above. if (redist_on) { struct list *ext_list; struct listnode *node; struct ospf_external *ext; ext_list = ospf->external[type]; if (!ext_list) continue; for (ALL_LIST_ELEMENTS_RO(ext_list, node, ext)) { rn = NULL; if (ext->external_info) rn = route_node_lookup( ext->external_info, (struct prefix *)&p); if (rn) { route_unlock_node(rn); if (rn->info != NULL) return (struct external_info *) rn->info; } } } } return NULL; }
static void ifaddr_ipv4_delete (struct in_addr *ifaddr, struct interface *ifp) { struct route_node *rn; struct prefix_ipv4 p; p.family = AF_INET; p.prefixlen = IPV4_MAX_PREFIXLEN; p.prefix = *ifaddr; rn = route_node_lookup (ifaddr_ipv4_table, (struct prefix *) &p); if (! rn) { zlog_info ("ifaddr_ipv4_delete(): can't find address %s", inet_ntoa (*ifaddr)); return; } rn->info = NULL; route_unlock_node (rn); route_unlock_node (rn); }
/* Delete specified OSPF neighbor from interface. */ void ospf_nbr_delete (struct ospf_neighbor *nbr) { struct ospf_interface *oi; struct route_node *rn; struct prefix p; oi = nbr->oi; /* get appropriate prefix 'key' */ ospf_nbr_key (oi, nbr, &p); rn = route_node_lookup (oi->nbrs, &p); if (rn) { /* If lookup for a NBR succeeds, the leaf route_node could * only exist because there is (or was) a nbr there. * If the nbr was deleted, the leaf route_node should have * lost its last refcount too, and be deleted. * Therefore a looked-up leaf route_node in nbrs table * should never have NULL info. */ assert (rn->info); if (rn->info) { rn->info = NULL; route_unlock_node (rn); } else zlog_info ("Can't find neighbor %s in the interface %s", inet_ntoa (nbr->src), IF_NAME (oi)); route_unlock_node (rn); } /* Free ospf_neighbor structure. */ ospf_nbr_free (nbr); }
struct ospf_area_range * ospf_area_range_match (struct ospf_area *area, struct prefix_ipv4 *p) { struct route_node *node; node = route_node_match (area->ranges, (struct prefix *) p); if (node) { route_unlock_node (node); return node->info; } return NULL; }
/* Return the iterator of the first VRF. */ vrf_iter_t vrf_first (void) { struct route_node *rn; for (rn = route_top (vrf_table); rn; rn = route_next (rn)) if (rn->info) { route_unlock_node (rn); /* top/next */ return (vrf_iter_t)rn; } return VRF_ITER_INVALID; }
struct ospf_area_range * ospf_area_range_lookup (struct ospf_area *area, struct prefix_ipv4 *p) { struct route_node *rn; rn = route_node_lookup (area->ranges, (struct prefix *)p); if (rn) { route_unlock_node (rn); return rn->info; } return NULL; }
void rip_ifaddr_delete (struct interface *ifp, struct connected *ifc) { struct prefix *p; struct route_node *rn; struct interface *i; p = ifc->address; if (p->family != AF_INET) return; rn = route_node_lookup (rip_ifaddr_table, p); if (! rn) return; i = rn->info; if (rn && !strncmp(i->name,ifp->name,INTERFACE_NAMSIZ)) { rn->info = NULL; route_unlock_node (rn); route_unlock_node (rn); } }
/* Delete RIP enable network. */ static int rip_enable_network_delete (struct prefix *p) { struct route_node *node; node = route_node_lookup (rip_enable_network, p); if (node) { node->info = NULL; /* Unlock info lock. */ route_unlock_node (node); /* Unlock lookup lock. */ route_unlock_node (node); /* XXX: One should find a better solution than a generic one */ rip_enable_apply_all (); return 1; } return -1; }
/* Handle notification about route being added */ void isis_redist_add(int type, struct prefix *p, u_char distance, uint32_t metric) { int family = p->family; struct route_table *ei_table = get_ext_info(isis, family); struct route_node *ei_node; struct isis_ext_info *info; struct listnode *node; struct isis_area *area; int level; struct isis_redist *redist; char debug_buf[BUFSIZ]; prefix2str(p, debug_buf, sizeof(debug_buf)); zlog_debug("%s: New route %s from %s.", __func__, debug_buf, zebra_route_string(type)); if (!ei_table) { zlog_warn("%s: External information table not initialized.", __func__); return; } ei_node = route_node_get(ei_table, p); if (ei_node->info) route_unlock_node(ei_node); else ei_node->info = XCALLOC(MTYPE_ISIS, sizeof(struct isis_ext_info)); info = ei_node->info; info->origin = type; info->distance = distance; info->metric = metric; if (is_default(p)) type = DEFAULT_ROUTE; for (ALL_LIST_ELEMENTS_RO(isis->area_list, node, area)) for (level = 1; level <= ISIS_LEVELS; level++) { redist = get_redist_settings(area, family, type, level); if (!redist->redist) continue; isis_redist_update_ext_reach(area, level, redist, p, info); } }
void ospf_free_if_params (struct interface *ifp, struct in_addr addr) { struct ospf_if_params *oip; struct prefix_ipv4 p; struct route_node *rn; p.family = AF_INET; p.prefixlen = IPV4_MAX_PREFIXLEN; p.prefix = addr; rn = route_node_lookup (IF_OIFS_PARAMS (ifp), (struct prefix*)&p); if (!rn || !rn->info) return; oip = rn->info; route_unlock_node (rn); if (!OSPF_IF_PARAM_CONFIGURED (oip, output_cost_cmd) && !OSPF_IF_PARAM_CONFIGURED (oip, transmit_delay) && !OSPF_IF_PARAM_CONFIGURED (oip, retransmit_interval) && !OSPF_IF_PARAM_CONFIGURED (oip, passive_interface) && !OSPF_IF_PARAM_CONFIGURED (oip, v_hello) && !OSPF_IF_PARAM_CONFIGURED (oip, fast_hello) && !OSPF_IF_PARAM_CONFIGURED (oip, v_wait) && !OSPF_IF_PARAM_CONFIGURED (oip, priority) && !OSPF_IF_PARAM_CONFIGURED (oip, type) && !OSPF_IF_PARAM_CONFIGURED (oip, auth_simple) && !OSPF_IF_PARAM_CONFIGURED (oip, auth_type) && listcount (oip->auth_crypt) == 0 && ntohl (oip->network_lsa_seqnum) != OSPF_INITIAL_SEQUENCE_NUMBER) { ospf_del_if_params (oip); rn->info = NULL; route_unlock_node (rn); } }
struct ospf_neighbor *ospf_nbr_lookup_by_routerid(struct route_table *nbrs, struct in_addr *id) { struct route_node *rn; struct ospf_neighbor *nbr; for (rn = route_top(nbrs); rn; rn = route_next(rn)) if ((nbr = rn->info) != NULL) if (IPV4_ADDR_SAME(&nbr->router_id, id)) { route_unlock_node(rn); return nbr; } return NULL; }
struct ospf_neighbor * ospf_nbr_get (struct ospf_interface *oi, struct ospf_header *ospfh, struct ip *iph, struct prefix *p) { struct route_node *rn; struct prefix key; struct ospf_neighbor *nbr; key.family = AF_INET; key.prefixlen = IPV4_MAX_BITLEN; if (oi->type == OSPF_IFTYPE_VIRTUALLINK) { key.u.prefix4 = ospfh->router_id; /* index vlink nbrs by router-id */ } else { key.u.prefix4 = iph->ip_src; } rn = route_node_get (oi->nbrs, &key); if (rn->info) { route_unlock_node (rn); nbr = rn->info; if (oi->type == OSPF_IFTYPE_NBMA && nbr->state == NSM_Attempt) { nbr->src = iph->ip_src; memcpy (&nbr->address, p, sizeof (struct prefix)); } /*add by bill 20091224. if the nbr's router id is changed, then the nbr's state is transit to ExStart, to refresh the adjacency*/ if(IPV4_ADDR_CMP(&nbr->router_id, &ospfh->router_id)) { nbr->router_id = ospfh->router_id; OSPF_NSM_EVENT_EXECUTE (nbr, NSM_AdjOK); } } else { rn->info = nbr = ospf_nbr_add (oi, ospfh, p); nbr->router_id = ospfh->router_id; } return nbr; }
static int ospf_interface_address_delete (int command, struct zclient *zclient, zebra_size_t length, vrf_id_t vrf_id) { struct connected *c; struct interface *ifp; struct ospf_interface *oi; struct route_node *rn; struct prefix p; c = zebra_interface_address_read (command, zclient->ibuf, vrf_id); if (c == NULL) return 0; if (IS_DEBUG_OSPF (zebra, ZEBRA_INTERFACE)) { char buf[128]; prefix2str(c->address, buf, sizeof(buf)); zlog_debug("Zebra: interface %s address delete %s", c->ifp->name, buf); } ifp = c->ifp; p = *c->address; p.prefixlen = IPV4_MAX_PREFIXLEN; rn = route_node_lookup (IF_OIFS (ifp), &p); if (!rn) { connected_free (c); return 0; } assert (rn->info); oi = rn->info; route_unlock_node (rn); /* Call interface hook functions to clean up */ ospf_if_free (oi); #ifdef HAVE_SNMP ospf_snmp_if_update (c->ifp); #endif /* HAVE_SNMP */ connected_free (c); return 0; }
void ospf_area_range_add (struct ospf_area *area, struct ospf_area_range *range) { struct route_node *rn; struct prefix_ipv4 p; p.family = AF_INET; p.prefixlen = range->masklen; p.prefix = range->addr; rn = route_node_get (area->ranges, (struct prefix *)&p); if (rn->info) route_unlock_node (rn); else rn->info = range; }
/* Look up a VRF by identifier. */ static struct vrf * vrf_lookup (vrf_id_t vrf_id) { struct prefix p; struct route_node *rn; struct vrf *vrf = NULL; vrf_build_key (vrf_id, &p); rn = route_node_lookup (vrf_table, &p); if (rn) { vrf = (struct vrf *)rn->info; route_unlock_node (rn); /* lookup */ } return vrf; }
/* Return the next VRF iterator to the given iterator. */ vrf_iter_t vrf_next (vrf_iter_t iter) { struct route_node *rn = NULL; /* Lock it first because route_next() will unlock it. */ if (iter != VRF_ITER_INVALID) rn = route_next (route_lock_node ((struct route_node *)iter)); for (; rn; rn = route_next (rn)) if (rn->info) { route_unlock_node (rn); /* next */ return (vrf_iter_t)rn; } return VRF_ITER_INVALID; }
/* lookup oi for specified prefix/ifp */ struct ospf_interface *ospf_if_table_lookup(struct interface *ifp, struct prefix *prefix) { struct prefix p; struct route_node *rn; struct ospf_interface *rninfo = NULL; p = *prefix; p.prefixlen = IPV4_MAX_PREFIXLEN; /* route_node_get implicitely locks */ if ((rn = route_node_lookup(IF_OIFS(ifp), &p))) { rninfo = (struct ospf_interface *)rn->info; route_unlock_node(rn); } return rninfo; }