/* Utility function to convert ipv4 prefixes to Classful prefixes */ void apply_classful_mask_ipv4 (struct prefix_ipv4 *p) { u_int32_t destination; destination = ntohl (p->prefix.s_addr); if (p->prefixlen == IPV4_MAX_PREFIXLEN); /* do nothing for host routes */ else if (IN_CLASSC (destination)) { p->prefixlen=24; apply_mask_ipv4(p); } else if (IN_CLASSB(destination)) { p->prefixlen=16; apply_mask_ipv4(p); } else { p->prefixlen=8; apply_mask_ipv4(p); } }
void connected_down_ipv4 (struct interface *ifp, struct connected *ifc) { struct prefix_ipv4 p; struct prefix_ipv4 *addr; struct prefix_ipv4 *dest; if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL)) return; addr = (struct prefix_ipv4 *)ifc->address; dest = (struct prefix_ipv4 *)ifc->destination; memset (&p, 0, sizeof (struct prefix_ipv4)); p.family = AF_INET; p.prefixlen = addr->prefixlen; /* Point-to-point check. */ if (CONNECTED_POINTOPOINT_HOST(ifc)) p.prefix = dest->prefix; else p.prefix = addr->prefix; /* Apply mask to the network. */ apply_mask_ipv4 (&p); /* In case of connected address is 0.0.0.0/0 we treat it tunnel address. */ if (prefix_ipv4_any (&p)) return; rib_delete_ipv4 (ZEBRA_ROUTE_CONNECT, 0, &p, NULL, ifp->ifindex, 0); rib_update (); }
/* Called from if_up(). */ void connected_up_ipv4(struct interface *ifp, struct connected *ifc) { struct prefix_ipv4 p; if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_REAL)) return; PREFIX_COPY_IPV4(&p, CONNECTED_PREFIX(ifc)); /* Apply mask to the network. */ apply_mask_ipv4(&p); /* In case of connected address is 0.0.0.0/0 we treat it tunnel address. */ if (prefix_ipv4_any(&p)) return; rib_add_ipv4(ZEBRA_ROUTE_CONNECT, 0, &p, NULL, NULL, ifp->ifindex, RT_TABLE_MAIN, ifp->metric, 0, SAFI_UNICAST); rib_add_ipv4(ZEBRA_ROUTE_CONNECT, 0, &p, NULL, NULL, ifp->ifindex, RT_TABLE_MAIN, ifp->metric, 0, SAFI_MULTICAST); rib_update(); }
void connected_down_ipv4(struct interface *ifp, struct connected *ifc) { struct prefix_ipv4 p; if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_REAL)) return; PREFIX_COPY_IPV4(&p, CONNECTED_PREFIX(ifc)); /* Apply mask to the network. */ apply_mask_ipv4(&p); /* In case of connected address is 0.0.0.0/0 we treat it tunnel address. */ if (prefix_ipv4_any(&p)) return; /* Same logic as for connected_up_ipv4(): push the changes into the head. */ rib_delete_ipv4(ZEBRA_ROUTE_CONNECT, 0, &p, NULL, ifp->ifindex, 0, SAFI_UNICAST); rib_delete_ipv4(ZEBRA_ROUTE_CONNECT, 0, &p, NULL, ifp->ifindex, 0, SAFI_MULTICAST); rib_update(); }
static void rip_apply_address_add (struct connected *ifc) { struct prefix_ipv4 address; struct prefix *p; if (!rip) return; if (! if_is_up(ifc->ifp)) return; p = ifc->address; memset (&address, 0, sizeof (address)); address.family = p->family; address.prefix = p->u.prefix4; address.prefixlen = p->prefixlen; apply_mask_ipv4(&address); /* Check if this interface is RIP enabled or not or Check if this address's prefix is RIP enabled */ if ((rip_enable_if_lookup(ifc->ifp->name) >= 0) || (rip_enable_network_lookup2(ifc) >= 0)) rip_redistribute_add(ZEBRA_ROUTE_CONNECT, RIP_ROUTE_INTERFACE, &address, ifc->ifp->ifindex, NULL, 0, 0); }
static int process_transit_summary_lsa(struct ospf_area *area, struct route_table *rt, struct route_table *rtrs, struct ospf_lsa *lsa) { struct ospf *ospf = area->ospf; struct summary_lsa *sl; struct prefix_ipv4 p; uint32_t metric; if (lsa == NULL) return 0; sl = (struct summary_lsa *)lsa->data; if (IS_DEBUG_OSPF_EVENT) zlog_debug("process_transit_summaries(): LS ID: %s", inet_ntoa(lsa->data->id)); metric = GET_METRIC(sl->metric); if (metric == OSPF_LS_INFINITY) { if (IS_DEBUG_OSPF_EVENT) zlog_debug( "process_transit_summaries(): metric is infinity, skip"); return 0; } if (IS_LSA_MAXAGE(lsa)) { if (IS_DEBUG_OSPF_EVENT) zlog_debug( "process_transit_summaries(): This LSA is too old"); return 0; } if (ospf_lsa_is_self_originated(area->ospf, lsa)) { if (IS_DEBUG_OSPF_EVENT) zlog_debug( "process_transit_summaries(): This LSA is mine, skip"); return 0; } p.family = AF_INET; p.prefix = sl->header.id; if (sl->header.type == OSPF_SUMMARY_LSA) p.prefixlen = ip_masklen(sl->mask); else p.prefixlen = IPV4_MAX_BITLEN; apply_mask_ipv4(&p); if (sl->header.type == OSPF_SUMMARY_LSA) ospf_update_network_route(ospf, rt, rtrs, sl, &p, area); else ospf_update_router_route(ospf, rtrs, sl, &p, area); return 0; }
int process_transit_summary_lsa (struct ospf_lsa *l, void *v, int i) { struct summary_lsa *sl; struct prefix_ipv4 p; u_int32_t metric; struct ia_args *args; if (l == NULL) return 0; args = (struct ia_args *) v; sl = (struct summary_lsa *) l->data; if (IS_DEBUG_OSPF_EVENT) zlog_info ("process_transit_summaries(): LS ID: %s", inet_ntoa (l->data->id)); metric = GET_METRIC (sl->metric); if (metric == OSPF_LS_INFINITY) { if (IS_DEBUG_OSPF_EVENT) zlog_info ("process_transit_summaries(): metric is infinity, skip"); return 0; } if (IS_LSA_MAXAGE (l)) { if (IS_DEBUG_OSPF_EVENT) zlog_info ("process_transit_summaries(): This LSA is too old"); return 0; } if (ospf_lsa_is_self_originated (l)) { if (IS_DEBUG_OSPF_EVENT) zlog_info ("process_transit_summaries(): This LSA is mine, skip"); return 0; } p.family = AF_INET; p.prefix = sl->header.id; if (sl->header.type == OSPF_SUMMARY_LSA) p.prefixlen = ip_masklen (sl->mask); else p.prefixlen = IPV4_MAX_BITLEN; apply_mask_ipv4 (&p); if (sl->header.type == OSPF_SUMMARY_LSA) ospf_update_network_route (args->rt, args->rtrs, sl, &p, args->area); else ospf_update_router_route (args->rtrs, sl, &p, args->area); return 0; }
/* Set up interface's address, netmask (and broadcas? ). Linux or Solaris uses ifname:number semantics to set IP address aliases. */ int if_set_prefix_ctx(const struct zebra_dplane_ctx *ctx) { int ret; struct ifreq ifreq; struct sockaddr_in addr; struct sockaddr_in broad; struct sockaddr_in mask; struct prefix_ipv4 ifaddr; struct prefix_ipv4 *p; p = (struct prefix_ipv4 *)dplane_ctx_get_intf_addr(ctx); ifaddr = *p; strlcpy(ifreq.ifr_name, dplane_ctx_get_ifname(ctx), sizeof(ifreq.ifr_name)); addr.sin_addr = p->prefix; addr.sin_family = p->family; memcpy(&ifreq.ifr_addr, &addr, sizeof(struct sockaddr_in)); ret = if_ioctl(SIOCSIFADDR, (caddr_t)&ifreq); if (ret < 0) return ret; /* We need mask for make broadcast addr. */ masklen2ip(p->prefixlen, &mask.sin_addr); if (dplane_ctx_intf_is_broadcast(ctx)) { apply_mask_ipv4(&ifaddr); addr.sin_addr = ifaddr.prefix; broad.sin_addr.s_addr = (addr.sin_addr.s_addr | ~mask.sin_addr.s_addr); broad.sin_family = p->family; memcpy(&ifreq.ifr_broadaddr, &broad, sizeof(struct sockaddr_in)); ret = if_ioctl(SIOCSIFBRDADDR, (caddr_t)&ifreq); if (ret < 0) return ret; } mask.sin_family = p->family; #ifdef SUNOS_5 memcpy(&mask, &ifreq.ifr_addr, sizeof(mask)); #else memcpy(&ifreq.ifr_addr, &mask, sizeof(struct sockaddr_in)); #endif /* SUNOS5 */ ret = if_ioctl(SIOCSIFNETMASK, (caddr_t)&ifreq); if (ret < 0) return ret; return 0; }
/* Set up interface's address, netmask (and broadcast? ). Solaris uses ifname:number semantics to set IP address aliases. */ int if_set_prefix(struct interface *ifp, struct connected *ifc) { int ret; struct ifreq ifreq; struct sockaddr_in addr; struct sockaddr_in broad; struct sockaddr_in mask; struct prefix_ipv4 ifaddr; struct prefix_ipv4 *p; p = (struct prefix_ipv4 *)ifc->address; ifaddr = *p; strncpy(ifreq.ifr_name, ifp->name, IFNAMSIZ); addr.sin_addr = p->prefix; addr.sin_family = p->family; memcpy(&ifreq.ifr_addr, &addr, sizeof(struct sockaddr_in)); ret = if_ioctl(SIOCSIFADDR, (caddr_t)&ifreq); if (ret < 0) return ret; /* We need mask for make broadcast addr. */ masklen2ip(p->prefixlen, &mask.sin_addr); if (if_is_broadcast(ifp)) { apply_mask_ipv4(&ifaddr); addr.sin_addr = ifaddr.prefix; broad.sin_addr.s_addr = (addr.sin_addr.s_addr | ~mask.sin_addr.s_addr); broad.sin_family = p->family; memcpy(&ifreq.ifr_broadaddr, &broad, sizeof(struct sockaddr_in)); ret = if_ioctl(SIOCSIFBRDADDR, (caddr_t)&ifreq); if (ret < 0) return ret; } mask.sin_family = p->family; #ifdef SUNOS_5 memcpy(&mask, &ifreq.ifr_addr, sizeof(mask)); #else memcpy(&ifreq.ifr_netmask, &mask, sizeof(struct sockaddr_in)); #endif /* SUNOS_5 */ ret = if_ioctl(SIOCSIFNETMASK, (caddr_t)&ifreq); return ((ret < 0) ? ret : 0); }
/* Called from if_up(). */ void connected_up_ipv4 (struct interface *ifp, struct connected *ifc) { struct prefix_ipv4 p; struct prefix_ipv4 *addr; struct prefix_ipv4 *dest; if (IS_ZEBRA_DEBUG_RIB) zlog_debug ("%s: start", __func__); /* if(product != NULL)*/ if(product != NULL && product->board_type != BOARD_IS_ACTIVE_MASTER)/*gjd : change for active master 在删除ip时,直连路由没删除,因为重复添加,导致refcnt不为0释放不掉*/ goto skip; if(product != NULL && product->board_type == BOARD_IS_ACTIVE_MASTER &&CHECK_FLAG(ifp->if_scope, INTERFACE_LOCAL)) goto skip;/*local interface , skip the check the ifc->conf, because the ip address not install in the kernel .*/ if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL)) return; skip: addr = (struct prefix_ipv4 *) ifc->address; dest = (struct prefix_ipv4 *) ifc->destination; memset (&p, 0, sizeof (struct prefix_ipv4)); p.family = AF_INET; p.prefixlen = addr->prefixlen; /* Point-to-point check. */ if (CONNECTED_POINTOPOINT_HOST(ifc)) p.prefix = dest->prefix; else p.prefix = addr->prefix; /* Apply mask to the network. */ apply_mask_ipv4 (&p); /* In case of connected address is 0.0.0.0/0 we treat it tunnel address. */ if (prefix_ipv4_any (&p)) return; rib_add_ipv4 (ZEBRA_ROUTE_CONNECT, 0, &p, NULL, ifp->ifindex, RT_TABLE_MAIN, ifp->metric, 0); if (IS_ZEBRA_DEBUG_RIB) zlog_debug ("%s: goto rib_update ", __func__); rib_update (); }
void apply_mask(struct prefix *p) { switch (p->family) { case AF_INET: apply_mask_ipv4((struct prefix_ipv4 *)p); break; #ifdef HAVE_IPV6 case AF_INET6: apply_mask_ipv6((struct prefix_ipv6 *)p); break; #endif /* HAVE_IPV6 */ default: break; } return; }
static void rip_apply_address_del (struct connected *ifc) { struct prefix_ipv4 address; struct prefix *p; if (!rip) return; if (! if_is_up(ifc->ifp)) return; p = ifc->address; memset (&address, 0, sizeof (address)); address.family = p->family; address.prefix = p->u.prefix4; address.prefixlen = p->prefixlen; apply_mask_ipv4(&address); rip_redistribute_delete(ZEBRA_ROUTE_CONNECT, RIP_ROUTE_INTERFACE, &address, ifc->ifp->ifindex); }
static void rip_connect_set (struct interface *ifp, int set) { struct listnode *node, *nnode; struct connected *connected; struct prefix_ipv4 address; for (ALL_LIST_ELEMENTS (ifp->connected, node, nnode, connected)) { struct prefix *p; p = connected->address; if (p->family != AF_INET) continue; address.family = AF_INET; address.prefix = p->u.prefix4; address.prefixlen = p->prefixlen; apply_mask_ipv4 (&address); if (set) { /* Check once more wether this prefix is within a "network IF_OR_PREF" one */ if ((rip_enable_if_lookup(connected->ifp->name) >= 0) || (rip_enable_network_lookup2(connected) >= 0)) rip_redistribute_add (ZEBRA_ROUTE_CONNECT, RIP_ROUTE_INTERFACE, &address, connected->ifp->ifindex, NULL, 0, 0); } else { rip_redistribute_delete (ZEBRA_ROUTE_CONNECT, RIP_ROUTE_INTERFACE, &address, connected->ifp->ifindex); if (rip_redistribute_check (ZEBRA_ROUTE_CONNECT)) rip_redistribute_add (ZEBRA_ROUTE_CONNECT, RIP_ROUTE_REDISTRIBUTE, &address, connected->ifp->ifindex, NULL, 0, 0); } } }
void bgp_connected_delete (struct connected *ifc) { struct prefix p; struct prefix *addr; struct interface *ifp; struct bgp_node *rn; struct bgp_connected_ref *bc; ifp = ifc->ifp; if (if_is_loopback (ifp)) return; addr = ifc->address; if (addr->family == AF_INET) { PREFIX_COPY_IPV4(&p, CONNECTED_PREFIX(ifc)); apply_mask_ipv4 ((struct prefix_ipv4 *) &p); if (prefix_ipv4_any ((struct prefix_ipv4 *) &p)) return; bgp_address_del (addr); rn = bgp_node_lookup (bgp_connected_table[AFI_IP], &p); if (! rn) return; bc = rn->info; bc->refcnt--; if (bc->refcnt == 0) { XFREE (MTYPE_BGP_CONN, bc); rn->info = NULL; } bgp_unlock_node (rn); bgp_unlock_node (rn); } #ifdef HAVE_IPV6 else if (addr->family == AF_INET6) { PREFIX_COPY_IPV6(&p, CONNECTED_PREFIX(ifc)); apply_mask_ipv6 ((struct prefix_ipv6 *) &p); if (IN6_IS_ADDR_UNSPECIFIED (&p.u.prefix6)) return; if (IN6_IS_ADDR_LINKLOCAL (&p.u.prefix6)) return; rn = bgp_node_lookup (bgp_connected_table[AFI_IP6], (struct prefix *) &p); if (! rn) return; bc = rn->info; bc->refcnt--; if (bc->refcnt == 0) { XFREE (MTYPE_BGP_CONN, bc); rn->info = NULL; } bgp_unlock_node (rn); bgp_unlock_node (rn); } #endif /* HAVE_IPV6 */ }
void bgp_connected_add (struct connected *ifc) { struct prefix p; struct prefix *addr; struct interface *ifp; struct bgp_node *rn; struct bgp_connected_ref *bc; ifp = ifc->ifp; if (! ifp) return; if (if_is_loopback (ifp)) return; addr = ifc->address; if (addr->family == AF_INET) { PREFIX_COPY_IPV4(&p, CONNECTED_PREFIX(ifc)); apply_mask_ipv4 ((struct prefix_ipv4 *) &p); if (prefix_ipv4_any ((struct prefix_ipv4 *) &p)) return; bgp_address_add (addr); rn = bgp_node_get (bgp_connected_table[AFI_IP], (struct prefix *) &p); if (rn->info) { bc = rn->info; bc->refcnt++; } else { bc = XCALLOC (MTYPE_BGP_CONN, sizeof (struct bgp_connected_ref)); bc->refcnt = 1; rn->info = bc; } } #ifdef HAVE_IPV6 else if (addr->family == AF_INET6) { PREFIX_COPY_IPV6(&p, CONNECTED_PREFIX(ifc)); apply_mask_ipv6 ((struct prefix_ipv6 *) &p); if (IN6_IS_ADDR_UNSPECIFIED (&p.u.prefix6)) return; if (IN6_IS_ADDR_LINKLOCAL (&p.u.prefix6)) return; rn = bgp_node_get (bgp_connected_table[AFI_IP6], (struct prefix *) &p); if (rn->info) { bc = rn->info; bc->refcnt++; } else { bc = XCALLOC (MTYPE_BGP_CONN, sizeof (struct bgp_connected_ref)); bc->refcnt = 1; rn->info = bc; } } #endif /* HAVE_IPV6 */ }
static void ospf_update_router_route (struct ospf *ospf, struct route_table *rtrs, struct summary_lsa *lsa, struct prefix_ipv4 *p, struct ospf_area *area) { struct ospf_route *or, *abr_or, *new_or; struct prefix_ipv4 abr; u_int32_t cost; abr.family = AF_INET; abr.prefix = lsa->header.adv_router; abr.prefixlen = IPV4_MAX_BITLEN; apply_mask_ipv4 (&abr); abr_or = ospf_find_abr_route (rtrs, &abr, area); if (abr_or == NULL) { if (IS_DEBUG_OSPF_EVENT) zlog_debug ("ospf_update_router_route(): can't find a route to the ABR"); return; } cost = abr_or->cost + GET_METRIC (lsa->metric); /* First try to find a backbone path, because standard ABR can update only BB-associated paths */ if ((ospf->backbone == NULL) && (ospf->abr_type != OSPF_ABR_SHORTCUT)) return; /* no BB area, not Shortcut ABR, exiting */ /* find the backbone route, if possible */ if ((ospf->backbone == NULL) || !(or = ospf_find_asbr_route_through_area (rtrs, p, ospf->backbone))) { if (ospf->abr_type != OSPF_ABR_SHORTCUT) /* route to ASBR through the BB not found the router is not Shortcut ABR, exiting */ return; else /* We're a Shortcut ABR*/ { /* Let it either add a new router or update the route through the same (non-BB) area. */ new_or = ospf_route_new (); new_or->type = OSPF_DESTINATION_ROUTER; new_or->id = lsa->header.id; new_or->mask = lsa->mask; new_or->u.std.options = lsa->header.options; new_or->u.std.origin = (struct lsa_header *)lsa; new_or->cost = cost; new_or->u.std.area_id = area->area_id; new_or->u.std.external_routing = area->external_routing; new_or->path_type = OSPF_PATH_INTER_AREA; new_or->u.std.flags = ROUTER_LSA_EXTERNAL; ospf_ia_router_route (ospf, rtrs, p, new_or, abr_or); return; } } /* At this point the "or" is always bb-associated */ if (!(or->u.std.flags & ROUTER_LSA_EXTERNAL)) { if (IS_DEBUG_OSPF_EVENT) zlog_debug ("ospf_upd_router_route(): the remote router is not an ASBR"); return; } if (or->path_type != OSPF_PATH_INTRA_AREA && or->path_type != OSPF_PATH_INTER_AREA) return; if (or->cost < cost) return; else if (or->cost == cost) ospf_route_copy_nexthops (or, abr_or->paths); else if (or->cost > cost) { ospf_route_subst_nexthops (or, abr_or->paths); or->cost = cost; /* Even if the ABR runs in Shortcut mode, we can't change the path type and area, because the "or" is always bb-associated at this point and even Shortcut ABR can't change these attributes */ } }
static void ospf_update_network_route (struct ospf *ospf, struct route_table *rt, struct route_table *rtrs, struct summary_lsa *lsa, struct prefix_ipv4 *p, struct ospf_area *area) { struct route_node *rn; struct ospf_route *or, *abr_or, *new_or; struct prefix_ipv4 abr; u_int32_t cost; abr.family = AF_INET; abr.prefix =lsa->header.adv_router; abr.prefixlen = IPV4_MAX_BITLEN; apply_mask_ipv4 (&abr); abr_or = ospf_find_abr_route (rtrs, &abr, area); if (abr_or == NULL) { if (IS_DEBUG_OSPF_EVENT) zlog_debug ("ospf_update_network_route(): can't find a route to the ABR"); return; } cost = abr_or->cost + GET_METRIC (lsa->metric); rn = route_node_lookup (rt, (struct prefix *) p); if (! rn) { if (ospf->abr_type != OSPF_ABR_SHORTCUT) return; /* Standard ABR can update only already installed backbone paths */ if (IS_DEBUG_OSPF_EVENT) zlog_debug ("ospf_update_network_route(): " "Allowing Shortcut ABR to add new route"); new_or = ospf_route_new (); new_or->type = OSPF_DESTINATION_NETWORK; new_or->id = lsa->header.id; new_or->mask = lsa->mask; new_or->u.std.options = lsa->header.options; new_or->u.std.origin = (struct lsa_header *) lsa; new_or->cost = cost; new_or->u.std.area_id = area->area_id; new_or->u.std.external_routing = area->external_routing; new_or->path_type = OSPF_PATH_INTER_AREA; ospf_route_add (rt, p, new_or, abr_or); return; } else { route_unlock_node (rn); if (rn->info == NULL) return; } or = rn->info; if (or->path_type != OSPF_PATH_INTRA_AREA && or->path_type != OSPF_PATH_INTER_AREA) { if (IS_DEBUG_OSPF_EVENT) zlog_debug ("ospf_update_network_route(): ERR: path type is wrong"); return; } if (ospf->abr_type == OSPF_ABR_SHORTCUT) { if (or->path_type == OSPF_PATH_INTRA_AREA && !OSPF_IS_AREA_ID_BACKBONE (or->u.std.area_id)) { if (IS_DEBUG_OSPF_EVENT) zlog_debug ("ospf_update_network_route(): Shortcut: " "this intra-area path is not backbone"); return; } } else /* Not Shortcut ABR */ { if (!OSPF_IS_AREA_ID_BACKBONE (or->u.std.area_id)) { if (IS_DEBUG_OSPF_EVENT) zlog_debug ("ospf_update_network_route(): " "route is not BB-associated"); return; /* We can update only BB routes */ } } if (or->cost < cost) { if (IS_DEBUG_OSPF_EVENT) zlog_debug ("ospf_update_network_route(): new route is worse"); return; } if (or->cost == cost) { if (IS_DEBUG_OSPF_EVENT) zlog_debug ("ospf_update_network_route(): " "new route is same distance, adding nexthops"); ospf_route_copy_nexthops (or, abr_or->paths); } if (or->cost > cost) { if (IS_DEBUG_OSPF_EVENT) zlog_debug ("ospf_update_network_route(): " "new route is better, overriding nexthops"); ospf_route_subst_nexthops (or, abr_or->paths); or->cost = cost; if ((ospf->abr_type == OSPF_ABR_SHORTCUT) && !OSPF_IS_AREA_ID_BACKBONE (or->u.std.area_id)) { or->path_type = OSPF_PATH_INTER_AREA; or->u.std.area_id = area->area_id; or->u.std.external_routing = area->external_routing; /* Note that we can do this only in Shortcut ABR mode, because standard ABR must leave the route type and area unchanged */ } } }
static int process_summary_lsa (struct ospf_area *area, struct route_table *rt, struct route_table *rtrs, struct ospf_lsa *lsa) { struct ospf *ospf = area->ospf; struct ospf_area_range *range; struct ospf_route *abr_or, *new_or; struct summary_lsa *sl; struct prefix_ipv4 p, abr; u_int32_t metric; if (lsa == NULL) return 0; sl = (struct summary_lsa *) lsa->data; if (IS_DEBUG_OSPF_EVENT) zlog_debug ("process_summary_lsa(): LS ID: %s", inet_ntoa (sl->header.id)); metric = GET_METRIC (sl->metric); if (metric == OSPF_LS_INFINITY) return 0; if (IS_LSA_MAXAGE (lsa)) return 0; if (ospf_lsa_is_self_originated (area->ospf, lsa)) return 0; p.family = AF_INET; p.prefix = sl->header.id; if (sl->header.type == OSPF_SUMMARY_LSA) p.prefixlen = ip_masklen (sl->mask); else p.prefixlen = IPV4_MAX_BITLEN; apply_mask_ipv4 (&p); if (sl->header.type == OSPF_SUMMARY_LSA && (range = ospf_area_range_match_any (ospf, &p)) && ospf_area_range_active (range)) return 0; /* XXX: This check seems dubious to me. If an ABR has already decided * to consider summaries received in this area, then why would one wish * to exclude default? */ if (IS_OSPF_ABR(ospf) && ospf->abr_type != OSPF_ABR_STAND && area->external_routing != OSPF_AREA_DEFAULT && p.prefix.s_addr == OSPF_DEFAULT_DESTINATION && p.prefixlen == 0) return 0; /* Ignore summary default from a stub area */ abr.family = AF_INET; abr.prefix = sl->header.adv_router; abr.prefixlen = IPV4_MAX_BITLEN; apply_mask_ipv4 (&abr); abr_or = ospf_find_abr_route (rtrs, &abr, area); if (abr_or == NULL) return 0; new_or = ospf_route_new (); new_or->type = OSPF_DESTINATION_NETWORK; new_or->id = sl->header.id; new_or->mask = sl->mask; new_or->u.std.options = sl->header.options; new_or->u.std.origin = (struct lsa_header *) sl; new_or->cost = abr_or->cost + metric; new_or->u.std.area_id = area->area_id; new_or->u.std.external_routing = area->external_routing; new_or->path_type = OSPF_PATH_INTER_AREA; if (sl->header.type == OSPF_SUMMARY_LSA) ospf_ia_network_route (ospf, rt, &p, new_or, abr_or); else { new_or->type = OSPF_DESTINATION_ROUTER; new_or->u.std.flags = ROUTER_LSA_EXTERNAL; ospf_ia_router_route (ospf, rtrs, &p, new_or, abr_or); } return 0; }
void connected_down_ipv4 (struct interface *ifp, struct connected *ifc) { struct prefix_ipv4 p; struct prefix_ipv4 *addr; struct prefix_ipv4 *dest; if (IS_ZEBRA_DEBUG_RIB) zlog_debug ("%s: start ", __func__); /*gujd: 2012-10-19, pm 3:49. When vrrp use virtual IP address , destination is NULL, so can't return.*/ #if 0 if(!ifc || !ifc->address || !ifc->destination|| !ifc->ifp) { zlog_err("ifc(%p), ifc->address(%p), ifc->destination(%p).\n", ifc,ifc->address,ifc->destination); return; } #else if(!ifc || !ifc->address || !ifc->ifp) { /*CID 11026 (#1 of 1): Dereference after null check (FORWARD_NULL) 4. var_deref_op: Dereferencing null pointer "ifc". Make sure , here is bug. So changed.*/ /*zlog_err("ifc(%p), ifc->address(%p), ifc->ifp(%p).\n", ifc,ifc->address,ifc->ifp); return ;*/ if(!ifc) { zlog_err("%s: line %d, ifc is null.\n",__func__,__LINE__); return ; } else { zlog_err("%s: line %d, ifc->address(%p), ifc->ifp(%p).\n", __func__,__LINE__,ifc->address,ifc->ifp); return ; } } #endif /* if(product != NULL)*/ if(product != NULL && product->board_type != BOARD_IS_ACTIVE_MASTER)/*gjd : change for active master 在删除ip时,直连路由没删除,因为重复添加,导致refcnt不为0释放不掉*/ goto skip; if(product != NULL && product->board_type == BOARD_IS_ACTIVE_MASTER &&CHECK_FLAG(ifp->if_scope, INTERFACE_LOCAL)) goto skip;/*local interface , skip the check the ifc->conf, because the ip address not install in the kernel .*/ if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL)) return; skip: addr = (struct prefix_ipv4 *)ifc->address; dest = (struct prefix_ipv4 *)ifc->destination; memset (&p, 0, sizeof (struct prefix_ipv4)); p.family = AF_INET; p.prefixlen = addr->prefixlen; /* Point-to-point check. */ if (CONNECTED_POINTOPOINT_HOST(ifc)) p.prefix = dest->prefix; else p.prefix = addr->prefix; /* Apply mask to the network. */ apply_mask_ipv4 (&p); /* In case of connected address is 0.0.0.0/0 we treat it tunnel address. */ if (prefix_ipv4_any (&p)) return; rib_delete_ipv4 (ZEBRA_ROUTE_CONNECT, 0, &p, NULL, ifp->ifindex, 0); if (IS_ZEBRA_DEBUG_RIB) zlog_debug ("%s: goto rib_update ", __func__); rib_update (); }
int process_summary_lsa (struct ospf_lsa *l, void *v, int i) { struct ospf_area_range *range; struct ospf_route *abr_or, *new_or; struct summary_lsa *sl; struct prefix_ipv4 p, abr; u_int32_t metric; struct ia_args *args; if (l == NULL) return 0; args = (struct ia_args *) v; sl = (struct summary_lsa *) l->data; if (IS_DEBUG_OSPF_EVENT) zlog_info ("process_summary_lsa(): LS ID: %s", inet_ntoa (sl->header.id)); metric = GET_METRIC (sl->metric); if (metric == OSPF_LS_INFINITY) return 0; if (IS_LSA_MAXAGE (l)) return 0; if (ospf_lsa_is_self_originated (l)) return 0; p.family = AF_INET; p.prefix = sl->header.id; if (sl->header.type == OSPF_SUMMARY_LSA) p.prefixlen = ip_masklen (sl->mask); else p.prefixlen = IPV4_MAX_BITLEN; apply_mask_ipv4 (&p); if (sl->header.type == OSPF_SUMMARY_LSA && (range = ospf_area_range_match_any (ospf_top, &p)) && ospf_area_range_active (range)) return 0; if (ospf_top->abr_type != OSPF_ABR_STAND && args->area->external_routing != OSPF_AREA_DEFAULT && p.prefix.s_addr == OSPF_DEFAULT_DESTINATION && p.prefixlen == 0) return 0; /* Ignore summary default from a stub area */ abr.family = AF_INET; abr.prefix = sl->header.adv_router; abr.prefixlen = IPV4_MAX_BITLEN; apply_mask_ipv4 (&abr); abr_or = ospf_find_abr_route (args->rtrs, &abr, args->area); if (abr_or == NULL) return 0; new_or = ospf_route_new (); new_or->type = OSPF_DESTINATION_NETWORK; new_or->id = sl->header.id; new_or->mask = sl->mask; new_or->u.std.options = sl->header.options; new_or->u.std.origin = (struct lsa_header *) sl; new_or->cost = abr_or->cost + metric; new_or->u.std.area_id = args->area->area_id; #ifdef HAVE_NSSA new_or->u.std.external_routing = args->area->external_routing; #endif /* HAVE_NSSA */ new_or->path_type = OSPF_PATH_INTER_AREA; if (sl->header.type == OSPF_SUMMARY_LSA) ospf_ia_network_route (args->rt, &p, new_or, abr_or); else { new_or->type = OSPF_DESTINATION_ROUTER; new_or->u.std.flags = ROUTER_LSA_EXTERNAL; ospf_ia_router_route (args->rtrs, &p, new_or, abr_or); } return 0; }