use std::os::fd::RawFd;
use super::Ovpn;
use crate::{
macros::GenlTypedDumpStream,
netlink::{
Connection,
error::{Error, Result},
genl::ovpn::{
messages::{
OvpnKeyDelRequest, OvpnKeyGetRequest, OvpnKeyNewRequest, OvpnKeyReply,
OvpnKeySwapRequest, OvpnKeyconf, OvpnPeer, OvpnPeerDelRequest, OvpnPeerGetRequest,
OvpnPeerNewRequest, OvpnPeerReply, OvpnPeerSetRequest,
},
types::OvpnKeySlot,
},
},
};
impl Connection<Ovpn> {
pub async fn peer_new(&self, ifindex: u32, peer: OvpnPeer) -> Result<()> {
let _: OvpnPeerReply = self
.send_typed(OvpnPeerNewRequest::new(ifindex, peer))
.await?;
Ok(())
}
pub async fn peer_set(&self, ifindex: u32, peer: OvpnPeer) -> Result<()> {
let _: OvpnPeerReply = self
.send_typed(OvpnPeerSetRequest::new(ifindex, peer))
.await?;
Ok(())
}
pub async fn peer_get(&self, ifindex: u32, peer_id: u32) -> Result<OvpnPeer> {
let reply: OvpnPeerReply = self
.send_typed(OvpnPeerGetRequest::by_id(ifindex, peer_id))
.await?;
reply.peer.ok_or_else(|| {
Error::InvalidMessage(format!(
"peer_get(ifindex={ifindex}, peer_id={peer_id}): kernel reply missing OVPN_A_PEER"
))
})
}
pub async fn peer_dump(&self, ifindex: u32) -> Result<Vec<OvpnPeer>> {
use tokio_stream::StreamExt;
let mut stream: GenlTypedDumpStream<'_, Ovpn, OvpnPeerReply> = self
.dump_typed_stream(OvpnPeerGetRequest::dump(ifindex))
.await?;
let mut out = Vec::new();
while let Some(reply) = stream.next().await {
let reply = reply?;
if let Some(peer) = reply.peer {
out.push(peer);
}
}
Ok(out)
}
pub async fn peer_del(&self, ifindex: u32, peer_id: u32) -> Result<()> {
let _: OvpnPeerReply = self
.send_typed(OvpnPeerDelRequest::new(ifindex, peer_id))
.await?;
Ok(())
}
pub async fn key_new(&self, ifindex: u32, keyconf: OvpnKeyconf) -> Result<()> {
let _: OvpnKeyReply = self
.send_typed(OvpnKeyNewRequest::new(ifindex, keyconf))
.await?;
Ok(())
}
pub async fn key_get(
&self,
ifindex: u32,
peer_id: u32,
slot: OvpnKeySlot,
) -> Result<OvpnKeyconf> {
let reply: OvpnKeyReply = self
.send_typed(OvpnKeyGetRequest::new(ifindex, peer_id, slot))
.await?;
reply.keyconf.ok_or_else(|| {
Error::InvalidMessage(format!(
"key_get(ifindex={ifindex}, peer_id={peer_id}, slot={slot:?}): \
kernel reply missing OVPN_A_KEYCONF"
))
})
}
pub async fn key_swap(&self, ifindex: u32, peer_id: u32) -> Result<()> {
let _: OvpnKeyReply = self
.send_typed(OvpnKeySwapRequest::new(ifindex, peer_id))
.await?;
Ok(())
}
pub async fn key_del(&self, ifindex: u32, peer_id: u32, slot: OvpnKeySlot) -> Result<()> {
let _: OvpnKeyReply = self
.send_typed(OvpnKeyDelRequest::new(ifindex, peer_id, slot))
.await?;
Ok(())
}
pub async fn attach_socket(&self, ifindex: u32, peer_id: u32, fd: RawFd) -> Result<()> {
self.attach_socket_inner(ifindex, peer_id, fd, None).await
}
pub async fn attach_socket_in_netns(
&self,
ifindex: u32,
peer_id: u32,
fd: RawFd,
netnsid: i32,
) -> Result<()> {
self.attach_socket_inner(ifindex, peer_id, fd, Some(netnsid))
.await
}
async fn attach_socket_inner(
&self,
ifindex: u32,
peer_id: u32,
fd: RawFd,
netnsid: Option<i32>,
) -> Result<()> {
let mut peer = OvpnPeer::identity(peer_id);
peer.socket = Some(fd as u32);
peer.socket_netnsid = netnsid;
let _: OvpnPeerReply = self
.send_typed(OvpnPeerSetRequest::new(ifindex, peer))
.await?;
Ok(())
}
}