Пример #1
0
/* 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 ();
}
Пример #3
0
/* 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();
}
Пример #4
0
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);

}
Пример #6
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;
}
Пример #7
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;
}
Пример #8
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;
}
Пример #9
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);
}
Пример #10
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 ();
}
Пример #11
0
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);
        }
    }
}
Пример #14
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 */
}
Пример #15
0
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 */
}
Пример #16
0
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 */
    }
}
Пример #17
0
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
          */
        }
    }
}
Пример #18
0
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;
}
Пример #19
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 ();
}
Пример #20
0
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;
}