Ejemplo n.º 1
0
/*
 * add_node
 *
 * Add the given prefix (passed in as a string) to the given table.
 */
static void add_node(struct bgp_table *table, const char *prefix_str)
{
	struct prefix_ipv4 p;
	struct test_node_t *node;
	struct bgp_node *rn;

	assert(prefix_str);

	if (str2prefix_ipv4(prefix_str, &p) <= 0)
		assert(0);

	rn = bgp_node_get(table, (struct prefix *)&p);
	if (rn->info) {
		assert(0);
		return;
	}

	node = malloc(sizeof(struct test_node_t));
	assert(node);
	node->prefix_str = strdup(prefix_str);
	assert(node->prefix_str);
	rn->info = node;
}
Ejemplo n.º 2
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 */
}
Ejemplo n.º 3
0
/* Check specified next-hop is reachable or not. */
int
bgp_nexthop_lookup (afi_t afi, struct peer *peer, struct bgp_info *ri,
		    int *changed, int *metricchanged)
{
  struct bgp_node *rn;
  struct prefix p;
  struct bgp_nexthop_cache *bnc;
  struct in_addr addr;
  
  /* If lookup is not enabled, return valid. */
  if (zlookup->sock < 0)
    {
      if (ri->extra)
        ri->extra->igpmetric = 0;
      return 1;
    }
  
#ifdef HAVE_IPV6
  if (afi == AFI_IP6)
    return bgp_nexthop_lookup_ipv6 (peer, ri, changed, metricchanged);
#endif /* HAVE_IPV6 */

  addr = ri->attr->nexthop;

  memset (&p, 0, sizeof (struct prefix));
  p.family = AF_INET;
  p.prefixlen = IPV4_MAX_BITLEN;
  p.u.prefix4 = addr;

  /* IBGP or ebgp-multihop */
  rn = bgp_node_get (bgp_nexthop_cache_table[AFI_IP], &p);

  if (rn->info)
    {
      bnc = rn->info;
      bgp_unlock_node (rn);
    }
  else
    {
      if (NULL == (bnc = zlookup_query (addr)))
	bnc = bnc_new ();
      else
	{
	  if (changed)
	    {
	      struct bgp_table *old;
	      struct bgp_node *oldrn;

	      if (bgp_nexthop_cache_table[AFI_IP] == cache1_table[AFI_IP])
		old = cache2_table[AFI_IP];
	      else
		old = cache1_table[AFI_IP];

	      oldrn = bgp_node_lookup (old, &p);
	      if (oldrn)
		{
		  struct bgp_nexthop_cache *oldbnc = oldrn->info;

		  bnc->changed = bgp_nexthop_cache_different (bnc, oldbnc);

		  if (bnc->metric != oldbnc->metric)
		    bnc->metricchanged = 1;

                  bgp_unlock_node (oldrn);
		}
	    }
	}
      rn->info = bnc;
    }

  if (changed)
    *changed = bnc->changed;

  if (metricchanged)
    *metricchanged = bnc->metricchanged;

  if (bnc->valid && bnc->metric)
    (bgp_info_extra_get(ri))->igpmetric = bnc->metric;
  else if (ri->extra)
    ri->extra->igpmetric = 0;

  return bnc->valid;
}
Ejemplo n.º 4
0
/* Check specified next-hop is reachable or not. */
static int
bgp_nexthop_lookup_ipv6 (struct peer *peer, struct bgp_info *ri, int *changed,
			 int *metricchanged)
{
  struct bgp_node *rn;
  struct prefix p;
  struct bgp_nexthop_cache *bnc;
  struct attr *attr;
  
  /* If lookup is not enabled, return valid. */
  if (zlookup->sock < 0)
    {
      if (ri->extra)
        ri->extra->igpmetric = 0;
      return 1;
    }
  
  /* Only check IPv6 global address only nexthop. */
  attr = ri->attr;

  if (attr->extra->mp_nexthop_len != 16 
      || IN6_IS_ADDR_LINKLOCAL (&attr->extra->mp_nexthop_global))
    return 1;

  memset (&p, 0, sizeof (struct prefix));
  p.family = AF_INET6;
  p.prefixlen = IPV6_MAX_BITLEN;
  p.u.prefix6 = attr->extra->mp_nexthop_global;

  /* IBGP or ebgp-multihop */
  rn = bgp_node_get (bgp_nexthop_cache_table[AFI_IP6], &p);

  if (rn->info)
    {
      bnc = rn->info;
      bgp_unlock_node (rn);
    }
  else
    {
      if (NULL == (bnc = zlookup_query_ipv6 (&attr->extra->mp_nexthop_global)))
	bnc = bnc_new ();
      else
	{
	  if (changed)
	    {
	      struct bgp_table *old;
	      struct bgp_node *oldrn;

	      if (bgp_nexthop_cache_table[AFI_IP6] == cache1_table[AFI_IP6])
		old = cache2_table[AFI_IP6];
	      else
		old = cache1_table[AFI_IP6];

	      oldrn = bgp_node_lookup (old, &p);
	      if (oldrn)
		{
		  struct bgp_nexthop_cache *oldbnc = oldrn->info;

		  bnc->changed = bgp_nexthop_cache_different (bnc, oldbnc);

		  if (bnc->metric != oldbnc->metric)
		    bnc->metricchanged = 1;

                  bgp_unlock_node (oldrn);
		}
	    }
	}
      rn->info = bnc;
    }

  if (changed)
    *changed = bnc->changed;

  if (metricchanged)
    *metricchanged = bnc->metricchanged;

  if (bnc->valid && bnc->metric)
    (bgp_info_extra_get (ri))->igpmetric = bnc->metric;
  else if (ri->extra)
    ri->extra->igpmetric = 0;

  return bnc->valid;
}