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}