Skip to main content

L2tpHandle

Struct L2tpHandle 

Source
pub struct L2tpHandle { /* private fields */ }
Expand description

Shared async handle for L2TP generic-netlink operations.

Implementations§

Source§

impl L2tpHandle

Source

pub async fn new() -> Result<Self>

Create a new L2TP Generic Netlink handle.

The calling thread’s network namespace is retained, including when inherited from a container. Further event connections use that same namespace; opening them from another namespace requires the privileges needed by setns(2).

This must be awaited while running inside a Tokio runtime with I/O enabled, because the internal Generic Netlink connection task is spawned onto the current Tokio executor. Without a runtime, or with a runtime built without enable_io, this returns Error::Io. Tokio reports a missing I/O driver by panicking inside the netlink socket registration; that panic is caught and turned into the error, so the panic hook still runs. The handle is cheap to clone; clones share one netlink connection.

Requests that refer to a tunnel or session the kernel does not know fail with Error::KernelError carrying ENODEV. Every L2TP command needs CAP_NET_ADMIN; without it the kernel replies EPERM.

Source

pub async fn new_in(netns: &NetNs) -> Result<Self>

Like new, but controls the L2TP subsystem of the network namespace netns.

Entering a different namespace needs CAP_SYS_ADMIN; see NetNs. Tunnel sockets for managed tunnels must be created in the same namespace, for example inside NetNs::run.

Source

pub async fn create_tunnel( &self, config: TunnelConfig, socket: TunnelSocket, ) -> Result<TunnelHandle>

Creates a managed tunnel using an owned socket fd.

The returned TunnelHandle owns socket; when that socket is dropped, the kernel tears down the tunnel. UDP checksum settings from config are applied to socket before registering it with the kernel.

For IP encapsulation, socket must be bound to the same tunnel ID as config; otherwise this returns Error::TunnelIdMismatch. TunnelSocket::for_config creates a matching socket, and TunnelConfig::for_socket describes an existing one.

Once started inside a Tokio runtime, creation continues through the kernel’s acknowledgement even if the caller cancels this future. The socket stays owned until then; an unclaimed tunnel is dropped with auto-delete enabled. The runtime must keep running for cleanup to finish.

Source

pub async fn create_unmanaged_tunnel( &self, config: TunnelConfig, ) -> Result<TunnelHandle>

Creates an unmanaged tunnel (no owned socket fd in this process).

The kernel creates/manages the underlying socket using netlink tunnel address attributes. The tunnel outlives this process; it is removed when the returned handle is dropped (unless auto-delete is disabled), by TunnelHandle::delete, or by L2tpHandle::delete_tunnel. Disabling UDP checksums for an IPv4-mapped peer returns Error::UnmanagedUdpChecksum, and link-local endpoints Error::UnmanagedLinkLocal; use a managed socket for these.

Once started inside a Tokio runtime, creation continues through the kernel’s acknowledgement even if the caller cancels this future. An unclaimed tunnel is dropped with auto-delete enabled. The runtime must keep running for this best-effort cleanup to finish.

Source

pub async fn open_tunnel(&self, tunnel_id: TunnelId) -> Result<TunnelHandle>

Returns a handle for an existing tunnel after checking that the kernel knows it.

The handle has auto-delete disabled and no socket, so dropping it leaves the tunnel alone; enable auto-delete or call TunnelHandle::delete to take ownership.

Source

pub async fn create_session( &self, config: SessionConfig, ) -> Result<SessionHandle>

Creates a session in an existing tunnel.

Session identifiers above 65535 are rejected with Error::V2IdTooLarge when the parent tunnel uses L2TPv2. Such identifiers require a parent-tunnel lookup before creation; L2TPv3 accepts the full 32-bit range.

Once started inside a Tokio runtime, creation continues through the kernel’s acknowledgement and follow-up lookup even if the caller cancels this future. An unclaimed session is dropped with auto-delete enabled. The runtime must keep running for this best-effort cleanup to finish.

For Ethernet pseudowires the handle also carries the interface index of the new l2tpeth device, captured from the kernel’s registration broadcast; see SessionHandle::ifindex. Give the session an explicit, unique SessionConfig::ifname where interfaces may be renamed by other software.

Source

pub async fn open_session( &self, tunnel_id: TunnelId, session_id: SessionId, ) -> Result<SessionHandle>

Returns a handle for an existing session after checking that the kernel knows it; auto-delete is disabled.

The interface index is looked up by the session’s creation-time name; see SessionHandle::ifindex.

Source

pub async fn open_session_by_ifname( &self, ifname: &L2tpIfName, ) -> Result<SessionHandle>

Returns a handle for the existing Ethernet pseudowire session whose interface is ifname; auto-delete is disabled.

ifname is the name the interface had when the session was created; see get_session_by_ifname. The interface index is looked up by that name too.

Source

pub async fn get_tunnel(&self, tunnel_id: TunnelId) -> Result<TunnelInfo>

Returns information for a single tunnel.

Source

pub async fn get_session( &self, tunnel_id: TunnelId, session_id: SessionId, ) -> Result<SessionInfo>

Returns information for a single session.

Source

pub async fn get_session_by_ifname( &self, ifname: &L2tpIfName, ) -> Result<SessionInfo>

Returns information for the Ethernet pseudowire session whose interface is ifname.

The kernel matches ifname against the name it recorded when the session was created. It does not follow later renames of the l2tpeth device, so a renamed interface is still found under its original name and never under its current one. An application that renames interfaces should resolve the reported name to its interface index right after creation with L2tpIfNameExt::index and address the device by that index from then on. Only L2TPv3 sessions are searched.

Source

pub async fn list_tunnels(&self) -> Result<Vec<TunnelInfo>>

Lists all tunnels.

If the kernel’s tables change during the dump, this fails with an error whose kind is io::ErrorKind::Interrupted; retrying usually succeeds.

Source

pub async fn list_sessions( &self, tunnel_id: TunnelId, ) -> Result<Vec<SessionInfo>>

Lists all sessions that belong to a tunnel.

Source

pub async fn list_all_sessions(&self) -> Result<Vec<SessionInfo>>

Lists all sessions across all tunnels.

If the kernel’s tables change during the dump, this fails with an error whose kind is io::ErrorKind::Interrupted; retrying usually succeeds.

Source

pub async fn delete_tunnel(&self, tunnel_id: TunnelId) -> Result<()>

Deletes a tunnel and its sessions.

The kernel acknowledges the request and then tears the tunnel down on a work queue, during which lookups still find it and creating a tunnel with the same identifier fails with EEXIST. This therefore also waits, for up to about two seconds, until a lookup reports ENODEV. Once the deletion is acknowledged it is not undone: a lookup that fails otherwise is returned as is, and a tunnel still listed after the wait is reported as Error::DeletionPending, which callers should treat as deleted, because repeating the request then fails with ENODEV. The wait needs neither a Tokio timer nor a free blocking thread.

Source

pub async fn delete_session( &self, tunnel_id: TunnelId, session_id: SessionId, ) -> Result<()>

Deletes a session from a tunnel.

Source

pub async fn delete_session_by_ifname(&self, ifname: &L2tpIfName) -> Result<()>

Deletes the Ethernet pseudowire session whose interface is ifname.

ifname is the name the interface had when the session was created; see get_session_by_ifname.

Source

pub async fn tunnel_stats(&self, tunnel_id: TunnelId) -> Result<TunnelStats>

Returns tunnel statistics.

Source

pub async fn session_stats( &self, tunnel_id: TunnelId, session_id: SessionId, ) -> Result<SessionStats>

Returns session statistics.

Source

pub async fn session_stats_by_ifname( &self, ifname: &L2tpIfName, ) -> Result<SessionStats>

Returns the statistics of the Ethernet pseudowire session whose interface is ifname.

ifname is the name the interface had when the session was created; see get_session_by_ifname.

Source

pub async fn modify_session( &self, tunnel_id: TunnelId, session_id: SessionId, params: SessionModify, ) -> Result<()>

Applies mutable session parameters.

Source

pub async fn modify_session_by_ifname( &self, ifname: &L2tpIfName, params: SessionModify, ) -> Result<()>

Applies mutable session parameters to the Ethernet pseudowire session whose interface is ifname.

ifname is the name the interface had when the session was created; see get_session_by_ifname.

Source

pub async fn events(&self) -> Result<Events>

Subscribes to the kernel’s L2TP notifications.

The stream reports kernel multicast notifications about tunnels and sessions created, modified or deleted through netlink commands. Its socket belongs to the handle’s original network namespace.

Some kernels, including Linux 6.8, multicast L2TP events into every network namespace, including containers, without identifying the originating namespace. Such events cannot be reliably filtered by tunnel/session IDs, which can collide across namespaces. Treat events as hints to reconcile state through this handle’s query methods, rather than instructions to mutate the named objects.

The kernel announces nothing for the teardown it performs on its own: a tunnel whose managed socket was closed, the sessions removed together with a deleted tunnel, or a PPP session whose PPPoL2TP socket was released. Reconcile with list_tunnels and list_all_sessions to catch those.

The stream uses its own netlink connection on the current runtime; dropping it leaves the multicast group. Joining needs no privilege. Opening the socket from another namespace requires permission to enter the handle’s original namespace. The subscription is bound to the family and group identifiers of the loaded l2tp_netlink module; if the module is reloaded, subscribe again.

Trait Implementations§

Source§

impl Clone for L2tpHandle

Source§

fn clone(&self) -> Self

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for L2tpHandle

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> Read<Exclusive, BecauseExclusive> for T
where T: ?Sized,

Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.