//! Who may connect: only the addresses of configured peers, and each of //! them only so many times at once. use std::net::{Ipv4Addr, SocketAddr}; use std::time::Duration; use bgp_integration_tests::test_peer::TestPeer; use bgp_integration_tests::test_server::TestServer; use bgp_server::config::PeerConfig; use bgp_server::family::FamilySet; use bgp_server::policy::ImportPolicy; use eyre::Result; use tokio::net::TcpListener; const LOCAL_ASN: u32 = 65000; const PEER_ASN: u32 = 65001; const TIMEOUT: Duration = Duration::from_secs(5); fn peer_at(endpoint: SocketAddr) -> PeerConfig { PeerConfig { name: "r1".into(), endpoint: endpoint.into(), remote_asn: PEER_ASN, hold_time_secs: 90, local_address: None, families: FamilySet::supported(), add_path: None, import: ImportPolicy::permissive(), role: None, require_role: false, import_hook: None, export_hook: None, } } /// Whether the server closed the connection without sending anything. async fn closed_unanswered(peer: &mut TestPeer) -> bool { matches!(tokio::time::timeout(TIMEOUT, peer.recv()).await, Ok(Err(_))) } /// A host that is not a configured peer gets nothing: no OPEN to answer, /// no session, no routes taken from it. Any host used to be able to open a /// session as any AS it named. #[tokio::test] async fn test_a_host_that_is_not_a_configured_peer_is_refused() -> Result<()> { // The only peer configured is somewhere else (documentation space). let server = TestServer::start_with(LOCAL_ASN, |c| { c.accept_unconfigured_peers = false; c.peers = vec![peer_at("192.0.2.9:179".parse().unwrap())]; }) .await?; let mut stranger = TestPeer::connect(server.addr).await?; assert!(closed_unanswered(&mut stranger).await); assert!(server.registry.list().is_empty()); Ok(()) } /// The address of a configured peer is let in, and held to what is /// configured for that peer. #[tokio::test] async fn test_a_configured_peer_is_let_in() -> Result<()> { // Somewhere for the server's own dialling to go; never answered. let listener = TcpListener::bind((Ipv4Addr::LOCALHOST, 0)).await?; let endpoint = listener.local_addr()?; let server = TestServer::start_with(LOCAL_ASN, |c| { c.accept_unconfigured_peers = false; c.peers = vec![peer_at(endpoint)]; }) .await?; let mut peer = TestPeer::connect(server.addr).await?; peer.handshake(PEER_ASN, Ipv4Addr::new(10, 0, 0, 2), 90) .await?; tokio::time::timeout(TIMEOUT, async { while server.registry.list().is_empty() { tokio::time::sleep(Duration::from_millis(10)).await; } }) .await?; assert_eq!(server.registry.list()[0].name.as_deref(), Some("r1")); Ok(()) } /// One address may hold only a few connections at a time, so that one host /// cannot use up the server's sockets with connections that never get as /// far as a session. #[tokio::test] async fn test_one_address_may_open_only_a_few_connections() -> Result<()> { let server = TestServer::start(LOCAL_ASN).await?; // Four that say nothing: each is sent the server's OPEN and waited on. let mut held = Vec::new(); for _ in 0..4 { let mut peer = TestPeer::connect(server.addr).await?; tokio::time::timeout(TIMEOUT, peer.recv_open()).await??; held.push(peer); } let mut one_too_many = TestPeer::connect(server.addr).await?; assert!(closed_unanswered(&mut one_too_many).await); // When one of them goes, there is room again. held.pop(); tokio::time::timeout(TIMEOUT, async { loop { let mut peer = TestPeer::connect(server.addr).await?; if peer.recv_open().await.is_ok() { return Ok::<_, eyre::Report>(()); } tokio::time::sleep(Duration::from_millis(20)).await; } }) .await??; Ok(()) }