Skip to main content

snap_tun/
lib.rs

1// Copyright 2025 Anapaya Systems
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//   http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14//! SNAP tunnel library.
15
16pub mod cert_validator;
17pub mod client;
18pub mod metrics;
19pub mod requests;
20pub(crate) mod scion_packet;
21pub mod server;
22pub mod server_deprecated;
23
24use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
25
26use ipnet::{IpNet, Ipv4Net, Ipv6Net};
27use scion_proto::address::{EndhostAddr, IsdAsn};
28
29/// The socket address assign connect RPC endpoint.
30pub(crate) const PATH_SOCK_ADDR_ASSIGNMENT: &str = "/connectrpc.v1.snaptun/assign_socketaddr";
31/// The update token connect RPC endpoint.
32pub(crate) const PATH_UPDATE_TOKEN: &str = "/connectrpc.v1.snaptun/update_token";
33pub(crate) const AUTH_HEADER: &str = "Authorization";
34
35/// Placeholder IPv4-Address that should be used by callers to
36/// [AddressAllocator::allocate] if the caller wants to request any of the
37/// available IPv4-addresses.
38pub const IPV4_WILDCARD: IpNet = IpNet::V4(Ipv4Net::new_assert(Ipv4Addr::UNSPECIFIED, 32));
39/// Placeholder IPv6-Address that should be used by callers to
40/// [AddressAllocator::allocate] if the caller wants to request any of the
41/// available IPv4-addresses.
42pub const IPV6_WILDCARD: IpNet = IpNet::V6(Ipv6Net::new_assert(Ipv6Addr::UNSPECIFIED, 128));
43
44/// Address allocation identifier.
45#[derive(Debug, Clone, PartialEq, Eq, Hash)]
46pub struct AddressAllocationId {
47    /// Registry identifier.
48    pub registry_id: u64,
49    /// Unique identifier for the allocation.
50    pub alloc_id: String,
51}
52
53/// Address allocation.
54#[derive(Debug, Clone, PartialEq, Eq, Hash)]
55pub struct AddressAllocation {
56    /// Address allocation identifier.
57    pub id: AddressAllocationId,
58    /// Allocated endhost address.
59    pub address: EndhostAddr,
60}
61
62/// Address allocator trait.
63pub trait AddressAllocator<Token>: Send + Sync {
64    /// Allocate an address to a client.
65    ///
66    /// * The implementation SHOULD renew existing allocation, if the token claims matches an
67    ///   existing allocation and return the corresponding address.
68    ///
69    /// * The implementation MUST attempt to return a concrete address if either [IPV4_WILDCARD] or
70    ///   [IPV6_WILDCARD] is provided.
71    fn allocate(
72        &self,
73        isd_as: IsdAsn,
74        prefix: IpNet,
75        claims: Token,
76    ) -> Result<AddressAllocation, AddressAllocationError>;
77
78    /// Sets an address on hold
79    ///
80    /// The hold prevents the address from being reallocated for a certain period of time.
81    fn put_on_hold(&self, id: AddressAllocationId) -> bool;
82
83    /// Immediately deallocates an address
84    ///
85    /// Returns `true` if allocation was found and removed, `false` if allocation was not found
86    fn deallocate(&self, id: AddressAllocationId) -> bool;
87}
88
89/// Address allocation error.
90#[derive(Debug, thiserror::Error)]
91pub enum AddressAllocationError {
92    /// No address manager for the given ISD-AS.
93    #[error("no address registry for ISD-AS {0}")]
94    NoAddressManagerForIsdAs(IsdAsn),
95    /// Address already registered.
96    #[error("address {0} already registered")]
97    AddressAlreadyRegistered(EndhostAddr),
98    /// Address not in allocation range.
99    #[error("address {0} not in allocation range")]
100    AddressNotInAllocationRange(IpAddr),
101    /// IA not in allocation range.
102    #[error("address {0} not in allocation ISD-AS {1}")]
103    IaNotInAllocationRange(IsdAsn, IsdAsn),
104    /// No addresses available.
105    #[error("no addresses available")]
106    NoAddressesAvailable,
107    /// Prefix allocation rejected.
108    #[error("prefix allocation rejected")]
109    AddressAllocationRejected,
110}