Example #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;

  /* If we can get socket for the peer, adjest TTL and make connection. */
  if (peer_sort (peer) == BGP_PEER_EBGP) {
    sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
    if (peer->gtsm_hops)
      sockopt_minttl (peer->su.sa.sa_family, peer->fd, MAXTTL + 1 - peer->gtsm_hops);
  }

  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 = if_nametoindex (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);
}
Example #2
0
int bgp_set_socket_ttl(struct peer *peer, int bgp_sock)
{
	char buf[INET_ADDRSTRLEN];
	int ret = 0;

	/* In case of peer is EBGP, we should set TTL for this connection.  */
	if (!peer->gtsm_hops && (peer_sort(peer) == BGP_PEER_EBGP)) {
		ret = sockopt_ttl(peer->su.sa.sa_family, bgp_sock, peer->ttl);
		if (ret) {
			flog_err(
				EC_LIB_SOCKET,
				"%s: Can't set TxTTL on peer (rtrid %s) socket, err = %d",
				__func__,
				inet_ntop(AF_INET, &peer->remote_id, buf,
					  sizeof(buf)),
				errno);
			return ret;
		}
	} else if (peer->gtsm_hops) {
		/* On Linux, setting minttl without setting ttl seems to mess
		   with the
		   outgoing ttl. Therefore setting both.
		*/
		ret = sockopt_ttl(peer->su.sa.sa_family, bgp_sock, MAXTTL);
		if (ret) {
			flog_err(
				EC_LIB_SOCKET,
				"%s: Can't set TxTTL on peer (rtrid %s) socket, err = %d",
				__func__,
				inet_ntop(AF_INET, &peer->remote_id, buf,
					  sizeof(buf)),
				errno);
			return ret;
		}
		ret = sockopt_minttl(peer->su.sa.sa_family, bgp_sock,
				     MAXTTL + 1 - peer->gtsm_hops);
		if (ret) {
			flog_err(
				EC_LIB_SOCKET,
				"%s: Can't set MinTTL on peer (rtrid %s) socket, err = %d",
				__func__,
				inet_ntop(AF_INET, &peer->remote_id, buf,
					  sizeof(buf)),
				errno);
			return ret;
		}
	}

	return ret;
}
Example #3
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;

  /* If we can get socket for the peer, adjest TTL and make connection. */
  if (peer_sort (peer) == BGP_PEER_EBGP)
    sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);

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

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

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

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

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

#ifdef HAVE_TCP_SIGNATURE
  if (CHECK_FLAG (peer->flags, PEER_FLAG_PASSWORD))
    bgp_tcpsig_set (peer->fd, peer);
#endif /* HAVE_TCP_SIGNATURE */

  /* Connect to the remote peer. */
  return sockunion_connect (peer->fd, &peer->su, htons (peer->port), ifindex);
}
Example #4
0
/*******************************************************************************
 函数名称  : bgp_info_mpath_update
 功能描述  : mpath队列更新
 输入参数  : 
 输出参数  : 
 返 回 值  : 无
--------------------------------------------------------------------------------
 最近一次修改记录 :
 修改作者   :      
 修改目的   :      新添加函数
 修改日期   :       2012-8-15
*******************************************************************************/
void bgp_info_mpath_update (struct bgp_node *rn, struct bgp_info *new_best,
               struct bgp_info *old_best, struct list *mp_list, struct bgp_maxpaths_cfg *mpath_cfg)
{
	u16 maxpaths, mpath_count, old_mpath_count;
	struct listnode *mp_node, *mp_next_node;
	struct bgp_info *cur_mpath, *new_mpath, *next_mpath, *prev_mpath;
	s32 mpath_changed;
	
	mpath_changed = 0;
	maxpaths = BGP_DEFAULT_MAXPATHS;
	mpath_count = 0;
	cur_mpath = NULL;
	old_mpath_count = 0;
	prev_mpath = new_best;
	mp_node = listhead (mp_list);
	
	if (new_best)
    {
		mpath_count++;
		if (new_best != old_best)
		{
	        bgp_info_mpath_dequeue (new_best);
        }
		maxpaths = (peer_sort (new_best->peer) == BGP_PEER_IBGP) ?
		        mpath_cfg->maxpaths_ibgp : mpath_cfg->maxpaths_ebgp;
    }
    
	if (old_best)
	{
		cur_mpath = bgp_info_mpath_first (old_best);
		old_mpath_count = bgp_info_mpath_count (old_best);
		bgp_info_mpath_count_set (old_best, 0);
		bgp_info_mpath_dequeue (old_best);
	}

	while (mp_node || cur_mpath)
    {
		if (!cur_mpath && (mpath_count >= maxpaths))
		{
	        break;
		}
		mp_next_node = mp_node ? listnextnode (mp_node) : NULL;
		next_mpath = cur_mpath ? bgp_info_mpath_next (cur_mpath) : NULL;
		if (mp_node && (listgetdata (mp_node) == cur_mpath))
        {
			list_delete_node (mp_list, mp_node);
			bgp_info_mpath_dequeue (cur_mpath);
			if ((mpath_count < maxpaths) && bgp_info_nexthop_cmp (prev_mpath, cur_mpath))
	        {
				bgp_info_mpath_enqueue (prev_mpath, cur_mpath);
				prev_mpath = cur_mpath;
				mpath_count++;
	        }
			else
	        {
				mpath_changed = 1;
	        }
			mp_node = mp_next_node;
			cur_mpath = next_mpath;
			continue;
	    }
	    
		if (cur_mpath && (!mp_node || (bgp_info_mpath_cmp (cur_mpath, listgetdata (mp_node)) < 0)))
		{
			bgp_info_mpath_dequeue (cur_mpath);
			mpath_changed = 1;
			cur_mpath = next_mpath;
		}
		else
        {
			new_mpath = listgetdata (mp_node);
			list_delete_node (mp_list, mp_node);
			if ((mpath_count < maxpaths) && (new_mpath != new_best) &&
	              bgp_info_nexthop_cmp (prev_mpath, new_mpath))
	        {
				if (new_mpath == next_mpath)
				{
					next_mpath = bgp_info_mpath_next (new_mpath);
				}	
				bgp_info_mpath_dequeue (new_mpath);

				bgp_info_mpath_enqueue (prev_mpath, new_mpath);
				prev_mpath = new_mpath;
				mpath_changed = 1;
				mpath_count++;
            }
			mp_node = mp_next_node;
	    }
	}
	
	if (new_best)
	{
		bgp_info_mpath_count_set (new_best, mpath_count-1);
		if (mpath_changed || (bgp_info_mpath_count (new_best) != old_mpath_count))
		{
	        SET_FLAG (new_best->flags, BGP_INFO_MULTIPATH_CHG);
        }
	}
}
Example #5
0
/* BGP Peer General TCP Socket Option Settings */
s_int32_t
bpn_sock_set_opt (struct bgp_peer *peer,
                  pal_sock_handle_t sck_fd,
                  bool_t do_bind)
{
  fib_id_t fib_id;
  s_int32_t ret;
  int flags = 1;


  fib_id = LIB_VRF_GET_FIB_ID (peer->bgp->owning_ivrf);
  ret = 0;

  /* set socket as ipv6 only */
  if (peer->su.sa.sa_family == AF_INET6)
    {
      ret = setsockopt(sck_fd, IPPROTO_IPV6, IPV6_V6ONLY, (char *) &flags, sizeof(flags));
      if (ret < 0)
        {
          zlog_err (&BLG, "%s-%s [NETWORK] Set Sock Opt: "
                    "failed to set option: Sock = %d",
                    peer->host, BGP_PEER_DIR_STR (peer), sck_fd);
        }
    }

  /* Set Socket as Non-blocking */
  pal_sock_set_nonblocking (sck_fd, PAL_TRUE);

  /* Set Socket to reuse Addr and Port */
  ret = pal_sock_set_reuseaddr (sck_fd, PAL_TRUE);
  if (ret < 0)
    {
      zlog_err (&BLG, "%s-%s [NETWORK] Set Sock Opt: "
                "failed to reuse addr: Sock %d",
                peer->host, BGP_PEER_DIR_STR (peer), sck_fd);

      return ret;
    }
  pal_sock_set_reuseport (sck_fd, PAL_TRUE);

  /* Set TTL for EBGP peers */
  if (peer_sort (peer) == BGP_PEER_EBGP)
    {
      if (peer->su.sa.sa_family == AF_INET)
        ret = (s_int32_t)pal_sock_set_ipv4_unicast_hops (sck_fd, peer->ttl);
#ifdef HAVE_IPV6
      else if (BGP_CAP_HAVE_IPV6
               && peer->su.sa.sa_family == AF_INET6)
        ret = (s_int32_t)pal_sock_set_ipv6_hoplimit (sck_fd, peer->ttl);
#endif /* HAVE_IPV6 */
      
      if (ret < 0)
        zlog_warn (&BLG, "Can't set Hop Limit: %s(%d)",    
	           pal_strerror (errno), errno);
    }

  if (PAL_TRUE == do_bind)
    {
      /* Bind socket to FIB */
      ret = pal_sock_set_bindtofib (sck_fd, fib_id);
      if (ret < 0)
        {
          zlog_err (&BLG, "%s-%s [NETWORK] Set Sock Opt: Failed to bind "
              "Sock %d to FIB with VRF-ID %d",
              peer->host, BGP_PEER_DIR_STR (peer), sck_fd, fib_id);

          return ret;
        }
    }

  /* Bind Socket to Interface */
#ifdef SO_BINDTODEVICE
  if (peer->ifname)
    {
      ret = pal_sock_set_bindtodevice (sck_fd, peer->ifname);
      if (ret < 0)
        {
          zlog_err (&BLG, "%s-%s [NETWORK] Set Sock Opt: Failed to "
                    "bind Sock %d to IF %s", peer->host,
                    BGP_PEER_DIR_STR (peer), sck_fd, peer->ifname);

          return ret;
        }
    }
#endif /* SO_BINDTODEVICE */

  /* Update-source address bind */
  if (do_bind == PAL_TRUE)
    {
      ret = bpn_sock_bind_address (peer, sck_fd);
      if (ret < 0)
        {
          zlog_err (&BLG, "%s-%s [NETWORK] Set Sock Opt: Update-source "
                    "failed on Sock %d", peer->host,
                    BGP_PEER_DIR_STR (peer), sck_fd);

          return ret;
        }
    }

  /* Set TCP MD5 authentication */
#ifdef HAVE_TCP_MD5SIG
  if (CHECK_FLAG (peer->config, PEER_CONFIG_PASSWORD))
    if (sockunion_family (&peer->su) == AF_INET)
      bgp_md5_set (sck_fd, &peer->su.sin.sin_addr, peer->password);
#endif /* TCP_MD5SIG */

  return ret;
}
Example #6
0
/* Accept bgp connection. */
static int
bgp_accept (struct thread *thread)
{
  int bgp_sock;
  int accept_sock;
  union sockunion su;
  struct bgp_listener *listener = THREAD_ARG(thread);
  struct peer *peer;
  struct peer *peer1;
  char buf[SU_ADDRSTRLEN];

  /* Register accept thread. */
  accept_sock = THREAD_FD (thread);
  if (accept_sock < 0)
    {
      zlog_err ("accept_sock is nevative value %d", accept_sock);
      return -1;
    }
  listener->thread = thread_add_read (master, bgp_accept, listener, accept_sock);

  /* Accept client connection. */
  bgp_sock = sockunion_accept (accept_sock, &su);
  if (bgp_sock < 0)
    {
      zlog_err ("[Error] BGP socket accept failed (%s)", safe_strerror (errno));
      return -1;
    }
  set_nonblocking (bgp_sock);

  if (BGP_DEBUG (events, EVENTS))
    zlog_debug ("[Event] BGP connection from host %s", inet_sutop (&su, buf));
  
  /* Check remote IP address */
  peer1 = peer_lookup (NULL, &su);
  if (! peer1 || peer1->status == Idle)
    {
      if (BGP_DEBUG (events, EVENTS))
	{
	  if (! peer1)
	    zlog_debug ("[Event] BGP connection IP address %s is not configured",
		       inet_sutop (&su, buf));
	  else
	    zlog_debug ("[Event] BGP connection IP address %s is Idle state",
		       inet_sutop (&su, buf));
	}
      close (bgp_sock);
      return -1;
    }

  /* In case of peer is EBGP, we should set TTL for this connection.  */
  if (peer_sort (peer1) == BGP_PEER_EBGP) {
    sockopt_ttl (peer1->su.sa.sa_family, bgp_sock, peer1->ttl);
    if (peer1->gtsm_hops)
      sockopt_minttl (peer1->su.sa.sa_family, bgp_sock, MAXTTL + 1 - peer1->gtsm_hops);
  }

  /* Make dummy peer until read Open packet. */
  if (BGP_DEBUG (events, EVENTS))
    zlog_debug ("[Event] Make dummy peer structure until read Open packet");

  {
    char buf[SU_ADDRSTRLEN + 1];

    peer = peer_create_accept (peer1->bgp);
    SET_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER);
    peer->su = su;
    peer->fd = bgp_sock;
    peer->status = Active;
    peer->local_id = peer1->local_id;
    peer->v_holdtime = peer1->v_holdtime;
    peer->v_keepalive = peer1->v_keepalive;

    /* Make peer's address string. */
    sockunion2str (&su, buf, SU_ADDRSTRLEN);
    peer->host = STRDUP (MTYPE_BGP_PEER_HOST, buf);
  }

  BGP_EVENT_ADD (peer, TCP_connection_open);

  return 0;
}
Example #7
0
static void
bgp_scan (afi_t afi, safi_t safi)
{
  struct bgp_node *rn;
  struct bgp *bgp;
  struct bgp_info *bi;
  struct bgp_info *next;
  struct peer *peer;
  struct listnode *node, *nnode;
  int valid;
  int current;
  int changed;
  int metricchanged;

  /* Change cache. */
  if (bgp_nexthop_cache_table[afi] == cache1_table[afi])
    bgp_nexthop_cache_table[afi] = cache2_table[afi];
  else
    bgp_nexthop_cache_table[afi] = cache1_table[afi];

  /* Get default bgp. */
  bgp = bgp_get_default ();
  if (bgp == NULL)
    return;

  /* Maximum prefix check */
  for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
    {
      if (peer->status != Established)
	continue;

      if (peer->afc[afi][SAFI_UNICAST])
	bgp_maximum_prefix_overflow (peer, afi, SAFI_UNICAST, 1);
      if (peer->afc[afi][SAFI_MULTICAST])
	bgp_maximum_prefix_overflow (peer, afi, SAFI_MULTICAST, 1);
      if (peer->afc[afi][SAFI_MPLS_VPN])
	bgp_maximum_prefix_overflow (peer, afi, SAFI_MPLS_VPN, 1);
    }

  for (rn = bgp_table_top (bgp->rib[afi][SAFI_UNICAST]); rn;
       rn = bgp_route_next (rn))
    {
      for (bi = rn->info; bi; bi = next)
	{
	  next = bi->next;

	  if (bi->type == ZEBRA_ROUTE_BGP && bi->sub_type == BGP_ROUTE_NORMAL)
	    {
	      changed = 0;
	      metricchanged = 0;

	      if (peer_sort (bi->peer) == BGP_PEER_EBGP && bi->peer->ttl == 1)
		valid = bgp_nexthop_check_ebgp (afi, bi->attr);
	      else
		valid = bgp_nexthop_lookup (afi, bi->peer, bi,
					    &changed, &metricchanged);

	      current = CHECK_FLAG (bi->flags, BGP_INFO_VALID) ? 1 : 0;

	      if (changed)
		SET_FLAG (bi->flags, BGP_INFO_IGP_CHANGED);
	      else
		UNSET_FLAG (bi->flags, BGP_INFO_IGP_CHANGED);

	      if (valid != current)
		{
		  if (CHECK_FLAG (bi->flags, BGP_INFO_VALID))
		    {
		      bgp_aggregate_decrement (bgp, &rn->p, bi,
					       afi, SAFI_UNICAST);
		      bgp_info_unset_flag (rn, bi, BGP_INFO_VALID);
		    }
		  else
		    {
		      bgp_info_set_flag (rn, bi, BGP_INFO_VALID);
		      bgp_aggregate_increment (bgp, &rn->p, bi,
					       afi, SAFI_UNICAST);
		    }
		}

              if (CHECK_FLAG (bgp->af_flags[afi][SAFI_UNICAST],
		  BGP_CONFIG_DAMPENING)
                  &&  bi->extra && bi->extra->damp_info )
                if (bgp_damp_scan (bi, afi, SAFI_UNICAST))
		  bgp_aggregate_increment (bgp, &rn->p, bi,
					   afi, SAFI_UNICAST);
	    }
	}
      bgp_process (bgp, rn, afi, SAFI_UNICAST);
    }

  /* Flash old cache. */
  if (bgp_nexthop_cache_table[afi] == cache1_table[afi])
    bgp_nexthop_cache_reset (cache2_table[afi]);
  else
    bgp_nexthop_cache_reset (cache1_table[afi]);

  if (BGP_DEBUG (events, EVENTS))
    {
      if (afi == AFI_IP)
	zlog_debug ("scanning IPv4 Unicast routing tables");
      else if (afi == AFI_IP6)
	zlog_debug ("scanning IPv6 Unicast routing tables");
    }
}