Ejemplo n.º 1
0
/* BGP try to connect to the peer.  */
int
bgp_connect (struct peer *peer)
{
  unsigned int ifindex = 0;

  /* Make socket for the peer. */
  peer->fd = sockunion_socket (&peer->su);
  if (peer->fd < 0)
    return -1;

  set_nonblocking (peer->fd);

  /* Set socket send buffer size */
  bgp_update_sock_send_buffer_size(peer->fd);

  bgp_set_socket_ttl (peer, peer->fd);

  sockopt_reuseaddr (peer->fd);
  sockopt_reuseport (peer->fd);
  
#ifdef IPTOS_PREC_INTERNETCONTROL
  if (bgpd_privs.change (ZPRIVS_RAISE))
    zlog_err ("%s: could not raise privs", __func__);
  if (sockunion_family (&peer->su) == AF_INET)
    setsockopt_ipv4_tos (peer->fd, IPTOS_PREC_INTERNETCONTROL);
# ifdef HAVE_IPV6
  else if (sockunion_family (&peer->su) == AF_INET6)
    setsockopt_ipv6_tclass (peer->fd, IPTOS_PREC_INTERNETCONTROL);
# endif
  if (bgpd_privs.change (ZPRIVS_LOWER))
    zlog_err ("%s: could not lower privs", __func__);
#endif

  if (peer->password)
    bgp_md5_set_connect (peer->fd, &peer->su, peer->password);

  /* Bind socket. */
  bgp_bind (peer);

  /* Update source bind. */
  bgp_update_source (peer);

#ifdef HAVE_IPV6
  if (peer->ifname)
    ifindex = ifname2ifindex (peer->ifname);
#endif /* HAVE_IPV6 */

  if (BGP_DEBUG (events, EVENTS))
    plog_debug (peer->log, "%s [Event] Connect start to %s fd %d",
	       peer->host, peer->host, peer->fd);

  /* Connect to the remote peer. */
  return sockunion_connect (peer->fd, &peer->su, htons (peer->port), ifindex);
}
Ejemplo n.º 2
0
/* Match function return 1 if match is success else return zero. */
static route_map_result_t
route_match_interface(void *rule, struct prefix *prefix,
                      route_map_object_t type, void *object)
{
    struct nexthop *nexthop;
    char *ifname = rule;
    unsigned int ifindex;

    if (type == RMAP_ZEBRA) {
        if (strcasecmp(ifname, "any") == 0)
            return RMAP_MATCH;
        ifindex = ifname2ifindex(ifname);
        if (ifindex == 0)
            return RMAP_NOMATCH;
        nexthop = object;
        if (!nexthop)
            return RMAP_NOMATCH;
        if (nexthop->ifindex == ifindex)
            return RMAP_MATCH;
    }
    return RMAP_NOMATCH;
}
Ejemplo n.º 3
0
/* BGP try to connect to the peer.  */
int bgp_connect(struct peer *peer)
{
	assert(!CHECK_FLAG(peer->thread_flags, PEER_THREAD_WRITES_ON));
	assert(!CHECK_FLAG(peer->thread_flags, PEER_THREAD_READS_ON));
	ifindex_t ifindex = 0;

	if (peer->conf_if && BGP_PEER_SU_UNSPEC(peer)) {
		zlog_debug("Peer address not learnt: Returning from connect");
		return 0;
	}
	frr_elevate_privs(&bgpd_privs) {
	/* Make socket for the peer. */
		peer->fd = vrf_sockunion_socket(&peer->su, peer->bgp->vrf_id,
						bgp_get_bound_name(peer));
	}
	if (peer->fd < 0)
		return -1;

	set_nonblocking(peer->fd);

	/* Set socket send buffer size */
	setsockopt_so_sendbuf(peer->fd, BGP_SOCKET_SNDBUF_SIZE);

	if (bgp_set_socket_ttl(peer, peer->fd) < 0)
		return -1;

	sockopt_reuseaddr(peer->fd);
	sockopt_reuseport(peer->fd);

#ifdef IPTOS_PREC_INTERNETCONTROL
	frr_elevate_privs(&bgpd_privs) {
		if (sockunion_family(&peer->su) == AF_INET)
			setsockopt_ipv4_tos(peer->fd,
					    IPTOS_PREC_INTERNETCONTROL);
		else if (sockunion_family(&peer->su) == AF_INET6)
			setsockopt_ipv6_tclass(peer->fd,
					       IPTOS_PREC_INTERNETCONTROL);
	}
#endif

	if (peer->password) {
		uint16_t prefixlen = peer->su.sa.sa_family == AF_INET
					     ? IPV4_MAX_PREFIXLEN
					     : IPV6_MAX_PREFIXLEN;

		bgp_md5_set_connect(peer->fd, &peer->su, prefixlen,
				    peer->password);
	}

	/* Update source bind. */
	if (bgp_update_source(peer) < 0) {
		return connect_error;
	}

	if (peer->conf_if || peer->ifname)
		ifindex = ifname2ifindex(peer->conf_if ? peer->conf_if
						       : peer->ifname,
					 peer->bgp->vrf_id);

	if (bgp_debug_neighbor_events(peer))
		zlog_debug("%s [Event] Connect start to %s fd %d", peer->host,
			   peer->host, peer->fd);

	/* Connect to the remote peer. */
	return sockunion_connect(peer->fd, &peer->su, htons(peer->port),
				 ifindex);
}
Ejemplo n.º 4
0
void
bgp_zebra_announce (struct prefix *p, struct bgp_info *info, struct bgp *bgp, safi_t safi)
{
  int flags;
  u_char distance;
  struct peer *peer;
  struct bgp_info *mpinfo;
  size_t oldsize, newsize;
  u_int32_t nhcount;
  route_tag_t tag = 0;

  if (zclient->sock < 0)
    return;

  if (! vrf_bitmap_check (zclient->redist[ZEBRA_ROUTE_BGP], VRF_DEFAULT))
    return;

  flags = 0;
  peer = info->peer;

  if ((info->attr->extra) && (info->attr->extra->tag != 0))
    tag = info->attr->extra->tag;

  if (peer->sort == BGP_PEER_IBGP || peer->sort == BGP_PEER_CONFED)
    {
      SET_FLAG (flags, ZEBRA_FLAG_IBGP);
      SET_FLAG (flags, ZEBRA_FLAG_INTERNAL);
    }

  if ((peer->sort == BGP_PEER_EBGP && peer_ttl (peer) != 1)
      || CHECK_FLAG (peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK))
    SET_FLAG (flags, ZEBRA_FLAG_INTERNAL);

  nhcount = 1 + bgp_info_mpath_count (info);

  if (p->family == AF_INET)
    {
      struct zapi_ipv4 api;
      struct in_addr *nexthop;

      /* resize nexthop buffer size if necessary */
      if ((oldsize = stream_get_size (bgp_nexthop_buf)) <
          (sizeof (struct in_addr *) * nhcount))
        {
          newsize = (sizeof (struct in_addr *) * nhcount);
          newsize = stream_resize (bgp_nexthop_buf, newsize);
          if (newsize == oldsize)
            {
	          zlog_err ("can't resize nexthop buffer");
	          return;
            }
        }
      stream_reset (bgp_nexthop_buf);

      api.vrf_id = VRF_DEFAULT;
      api.flags = flags;
      nexthop = &info->attr->nexthop;
      stream_put (bgp_nexthop_buf, &nexthop, sizeof (struct in_addr *));
      for (mpinfo = bgp_info_mpath_first (info); mpinfo;
	   mpinfo = bgp_info_mpath_next (mpinfo))
	{
	  nexthop = &mpinfo->attr->nexthop;
	  stream_put (bgp_nexthop_buf, &nexthop, sizeof (struct in_addr *));
	}

      api.type = ZEBRA_ROUTE_BGP;
      api.message = 0;
      api.safi = safi;
      SET_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP);
      api.nexthop_num = nhcount;
      api.nexthop = (struct in_addr **)STREAM_DATA (bgp_nexthop_buf);
      api.ifindex_num = 0;
      SET_FLAG (api.message, ZAPI_MESSAGE_METRIC);
      api.metric = info->attr->med;

      if (tag)
        {
          SET_FLAG (api.message, ZAPI_MESSAGE_TAG);
          api.tag = tag;
        }

      distance = bgp_distance_apply (p, info, bgp);

      if (distance)
	{
	  SET_FLAG (api.message, ZAPI_MESSAGE_DISTANCE);
	  api.distance = distance;
	}

      if (BGP_DEBUG(zebra, ZEBRA))
	{
	  int i;
	  char buf[2][INET_ADDRSTRLEN];
	  zlog_debug("Zebra send: IPv4 route add %s/%d nexthop %s metric %u"
	             " tag %u count %d",
		     inet_ntop(AF_INET, &p->u.prefix4, buf[0], sizeof(buf[0])),
		     p->prefixlen,
		     inet_ntop(AF_INET, api.nexthop[0], buf[1], sizeof(buf[1])),
		     api.metric, api.tag, api.nexthop_num);
	  for (i = 1; i < api.nexthop_num; i++)
	    zlog_debug("Zebra send: IPv4 route add [nexthop %d] %s",
		       i, inet_ntop(AF_INET, api.nexthop[i], buf[1],
				    sizeof(buf[1])));
	}

      zapi_ipv4_route (ZEBRA_IPV4_ROUTE_ADD, zclient, 
                       (struct prefix_ipv4 *) p, &api);
    }

  /* We have to think about a IPv6 link-local address curse. */
  if (p->family == AF_INET6)
    {
      ifindex_t ifindex;
      struct in6_addr *nexthop;
      struct zapi_ipv6 api;
      int valid_nh_count = 0;

      /* resize nexthop buffer size if necessary */
      if ((oldsize = stream_get_size (bgp_nexthop_buf)) <
          (sizeof (struct in6_addr *) * nhcount))
        {
          newsize = (sizeof (struct in6_addr *) * nhcount);
          newsize = stream_resize (bgp_nexthop_buf, newsize);
          if (newsize == oldsize)
            {
              zlog_err ("can't resize nexthop buffer");
              return;
            }
        }
      stream_reset (bgp_nexthop_buf);

      /* resize ifindices buffer size if necessary */
      if ((oldsize = stream_get_size (bgp_ifindices_buf)) <
          (sizeof (unsigned int) * nhcount))
        {
          newsize = (sizeof (unsigned int) * nhcount);
          newsize = stream_resize (bgp_ifindices_buf, newsize);
          if (newsize == oldsize)
            {
              zlog_err ("can't resize nexthop buffer");
              return;
            }
        }
      stream_reset (bgp_ifindices_buf);

      ifindex = 0;
      nexthop = NULL;

      assert (info->attr->extra);
      
      /* Only global address nexthop exists. */
      if (info->attr->extra->mp_nexthop_len == 16)
	nexthop = &info->attr->extra->mp_nexthop_global;
      
      /* If both global and link-local address present. */
      if (info->attr->extra->mp_nexthop_len == 32)
	{
	  /* Workaround for Cisco's nexthop bug.  */
	  if (IN6_IS_ADDR_UNSPECIFIED (&info->attr->extra->mp_nexthop_global)
	      && peer->su_remote->sa.sa_family == AF_INET6)
	    nexthop = &peer->su_remote->sin6.sin6_addr;
	  else
	    nexthop = &info->attr->extra->mp_nexthop_local;

	  if (info->peer->nexthop.ifp)
	    ifindex = info->peer->nexthop.ifp->ifindex;
	}

      if (nexthop == NULL)
	return;

      if (!ifindex)
	{
	  if (info->peer->ifname)
	    ifindex = ifname2ifindex (info->peer->ifname);
	  else if (info->peer->nexthop.ifp)
	    ifindex = info->peer->nexthop.ifp->ifindex;
	}
      stream_put (bgp_nexthop_buf, &nexthop, sizeof (struct in6_addr *));
      stream_put (bgp_ifindices_buf, &ifindex, sizeof (unsigned int));
      valid_nh_count++;

      for (mpinfo = bgp_info_mpath_first (info); mpinfo;
           mpinfo = bgp_info_mpath_next (mpinfo))
	{
	  ifindex = 0;

          /* Only global address nexthop exists. */
          if (mpinfo->attr->extra->mp_nexthop_len == 16)
              nexthop = &mpinfo->attr->extra->mp_nexthop_global;

          /* If both global and link-local address present. */
	  if (mpinfo->attr->extra->mp_nexthop_len == 32)
            {
              /* Workaround for Cisco's nexthop bug.  */
              if (IN6_IS_ADDR_UNSPECIFIED (&mpinfo->attr->extra->mp_nexthop_global)
                  && mpinfo->peer->su_remote->sa.sa_family == AF_INET6)
                {
		  nexthop = &mpinfo->peer->su_remote->sin6.sin6_addr;
                }
              else
                {
		  nexthop = &mpinfo->attr->extra->mp_nexthop_local;
	        }

              if (mpinfo->peer->nexthop.ifp)
                {
                  ifindex = mpinfo->peer->nexthop.ifp->ifindex;
                }
            }

	  if (nexthop == NULL)
	    {
	      continue;
	    }

          if (!ifindex)
	    {
	      if (mpinfo->peer->ifname)
                {
		  ifindex = if_nametoindex (mpinfo->peer->ifname);
		}
	      else if (mpinfo->peer->nexthop.ifp)
		{
		  ifindex = mpinfo->peer->nexthop.ifp->ifindex;
		}
	    }

	  if (ifindex == 0)
	    {
	      continue;
	    }

          stream_put (bgp_nexthop_buf, &nexthop, sizeof (struct in6_addr *));
          stream_put (bgp_ifindices_buf, &ifindex, sizeof (unsigned int));
          valid_nh_count++;
	}

      /* Make Zebra API structure. */
      api.vrf_id = VRF_DEFAULT;
      api.flags = flags;
      api.type = ZEBRA_ROUTE_BGP;
      api.message = 0;
      api.safi = safi;
      SET_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP);
      api.nexthop_num = valid_nh_count;
      api.nexthop = (struct in6_addr **)STREAM_DATA (bgp_nexthop_buf);
      SET_FLAG (api.message, ZAPI_MESSAGE_IFINDEX);
      api.ifindex_num = valid_nh_count;
      api.ifindex = (ifindex_t *)STREAM_DATA (bgp_ifindices_buf);
      SET_FLAG (api.message, ZAPI_MESSAGE_METRIC);
      api.metric = info->attr->med;

      distance = ipv6_bgp_distance_apply (p, info, bgp);

      if (distance)
        {
          SET_FLAG (api.message, ZAPI_MESSAGE_DISTANCE);
          api.distance = distance;
        }
      
      if (tag)
	{
	  SET_FLAG (api.message, ZAPI_MESSAGE_TAG);
	  api.tag = tag;
	}

      if (BGP_DEBUG(zebra, ZEBRA))
	{
	  char buf[2][INET6_ADDRSTRLEN];
	  zlog_debug("Zebra send: IPv6 route add %s/%d nexthop %s metric %u"
                     " tag %u",
		     inet_ntop(AF_INET6, &p->u.prefix6, buf[0], sizeof(buf[0])),
		     p->prefixlen,
		     inet_ntop(AF_INET6, nexthop, buf[1], sizeof(buf[1])),
		     api.metric, api.tag);
	}

      zapi_ipv6_route (ZEBRA_IPV6_ROUTE_ADD, zclient, 
                       (struct prefix_ipv6 *) p, &api);
    }
}