Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 0 additions & 43 deletions src/link/link_info/gre.rs

This file was deleted.

110 changes: 110 additions & 0 deletions src/link/link_info/gre/gre_common.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
// SPDX-License-Identifier: MIT

use std::fmt::Display;

const GRE_CSUM: u16 = 0x8000;
const GRE_ROUTING: u16 = 0x4000;
const GRE_KEY: u16 = 0x2000;
const GRE_SEQ: u16 = 0x1000;
const GRE_STRICT: u16 = 0x0800;
const GRE_REC: u16 = 0x0700;
const GRE_ACK: u16 = 0x0080;
const GRE_FLAGS: u16 = 0x0078;
const GRE_VERSION: u16 = 0x0007;

const TUNNEL_ENCAP_FLAG_CSUM: u16 = 0x0100;
const TUNNEL_ENCAP_FLAG_CSUM6: u16 = 0x0200;
const TUNNEL_ENCAP_FLAG_REMCSUM: u16 = 0x0400;

bitflags! {
#[derive(Clone, Eq, PartialEq, Debug, Copy, Default)]
#[non_exhaustive]
pub struct GreIOFlags: u16 {
const Checksum = GRE_CSUM;
const Routing = GRE_ROUTING;
const Key = GRE_KEY;
const Seq = GRE_SEQ;
const Strict0 = GRE_STRICT;
const Rec = GRE_REC;
const Ack = GRE_ACK;
const Flags = GRE_FLAGS;
const Version = GRE_VERSION;

const _ = !0;
}

#[derive(Clone, Eq, PartialEq, Debug, Copy, Default)]
#[non_exhaustive]
pub struct GreEncapFlags: u16 {
const Checksum = TUNNEL_ENCAP_FLAG_CSUM;
const Checksum6 = TUNNEL_ENCAP_FLAG_CSUM6;
const RemoteChecksum = TUNNEL_ENCAP_FLAG_REMCSUM;

const _ = !0;
}
}

const TUNNEL_ENCAP_NONE: u16 = 0;
const TUNNEL_ENCAP_FOU: u16 = 1;
const TUNNEL_ENCAP_GUE: u16 = 2;

#[derive(Debug, PartialEq, Eq, Clone, Copy, Default)]
#[non_exhaustive]
pub enum GreEncapType {
#[default]
None,
Fou,
Gue,
Other(u16),
}
impl From<u16> for GreEncapType {
fn from(d: u16) -> Self {
match d {
TUNNEL_ENCAP_NONE => GreEncapType::None,
TUNNEL_ENCAP_FOU => GreEncapType::Fou,
TUNNEL_ENCAP_GUE => GreEncapType::Gue,
_ => Self::Other(d),
}
}
}
impl From<&GreEncapType> for u16 {
fn from(t: &GreEncapType) -> Self {
match t {
GreEncapType::None => TUNNEL_ENCAP_NONE,
GreEncapType::Fou => TUNNEL_ENCAP_FOU,
GreEncapType::Gue => TUNNEL_ENCAP_GUE,
GreEncapType::Other(d) => *d,
}
}
}

impl Display for GreEncapType {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
GreEncapType::None => write!(f, "none"),
GreEncapType::Fou => write!(f, "fou"),
GreEncapType::Gue => write!(f, "gue"),
GreEncapType::Other(d) => write!(f, "other({d})"),
}
}
}

pub(super) const IFLA_GRE_LINK: u16 = 1;
pub(super) const IFLA_GRE_IFLAGS: u16 = 2;
pub(super) const IFLA_GRE_OFLAGS: u16 = 3;
pub(super) const IFLA_GRE_IKEY: u16 = 4;
pub(super) const IFLA_GRE_OKEY: u16 = 5;
pub(super) const IFLA_GRE_LOCAL: u16 = 6;
pub(super) const IFLA_GRE_REMOTE: u16 = 7;
pub(super) const IFLA_GRE_TTL: u16 = 8;
pub(super) const IFLA_GRE_TOS: u16 = 9;
pub(super) const IFLA_GRE_PMTUDISC: u16 = 10;
pub(super) const IFLA_GRE_ENCAP_LIMIT: u16 = 11;
pub(super) const IFLA_GRE_FLOWINFO: u16 = 12;
// pub(super) const IFLA_GRE_FLAGS: u16 = 13;
pub(super) const IFLA_GRE_ENCAP_TYPE: u16 = 14;
pub(super) const IFLA_GRE_ENCAP_FLAGS: u16 = 15;
pub(super) const IFLA_GRE_ENCAP_SPORT: u16 = 16;
pub(super) const IFLA_GRE_ENCAP_DPORT: u16 = 17;
pub(super) const IFLA_GRE_COLLECT_METADATA: u16 = 18;
pub(super) const IFLA_GRE_FWMARK: u16 = 20;
184 changes: 184 additions & 0 deletions src/link/link_info/gre/info_gre.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,184 @@
// SPDX-License-Identifier: MIT

use std::{mem::size_of, net::Ipv4Addr};

use netlink_packet_core::{
emit_u16_be, emit_u32_be, parse_u16_be, parse_u32_be, parse_u8,
DecodeError, DefaultNla, ErrorContext, Nla, NlaBuffer, Parseable,
};

use super::{
gre_common::{
IFLA_GRE_COLLECT_METADATA, IFLA_GRE_ENCAP_DPORT, IFLA_GRE_ENCAP_FLAGS,
IFLA_GRE_ENCAP_SPORT, IFLA_GRE_ENCAP_TYPE, IFLA_GRE_FWMARK,
IFLA_GRE_IFLAGS, IFLA_GRE_IKEY, IFLA_GRE_LOCAL, IFLA_GRE_OFLAGS,
IFLA_GRE_OKEY, IFLA_GRE_PMTUDISC, IFLA_GRE_REMOTE, IFLA_GRE_TOS,
IFLA_GRE_TTL,
},
GreEncapFlags, GreEncapType, GreIOFlags,
};
use crate::{
ip::parse_ipv4_addr, link::link_info::gre::gre_common::IFLA_GRE_LINK,
};

#[derive(Debug, PartialEq, Eq, Clone)]
#[non_exhaustive]
pub enum InfoGre {
Link(u32),
IFlags(GreIOFlags),
OFlags(GreIOFlags),
IKey(u32),
OKey(u32),
Local(Ipv4Addr),
Remote(Ipv4Addr),
Ttl(u8),
Tos(u8),
PathMTUDiscovery(bool),
EncapType(GreEncapType),
EncapFlags(GreEncapFlags),
SourcePort(u16),
DestinationPort(u16),
CollectMetadata,
FwMask(u32),
Other(DefaultNla),
}

impl Nla for InfoGre {
fn value_len(&self) -> usize {
match self {
Self::Link(_) => size_of::<u32>(),
Self::IFlags(_) | Self::OFlags(_) => size_of::<u16>(),
Self::IKey(_) | Self::OKey(_) => size_of::<u32>(),
Self::Local(_) | Self::Remote(_) => size_of::<Ipv4Addr>(),
Self::Ttl(_) | Self::Tos(_) | Self::PathMTUDiscovery(_) => {
size_of::<u8>()
}
Self::EncapType(_) => size_of::<u16>(),
Self::EncapFlags(_) => size_of::<u16>(),
Self::SourcePort(_) | Self::DestinationPort(_) => size_of::<u16>(),
Self::CollectMetadata => 0,
Self::FwMask(_) => size_of::<u32>(),
Self::Other(nla) => nla.value_len(),
}
}

fn emit_value(&self, buffer: &mut [u8]) {
match self {
Self::Link(id) => emit_u32_be(buffer, *id).unwrap(),
Self::IFlags(flags) | Self::OFlags(flags) => {
emit_u16_be(buffer, flags.bits()).unwrap()
}
Self::IKey(key) | Self::OKey(key) => {
emit_u32_be(buffer, *key).unwrap()
}
Self::Local(ip) | Self::Remote(ip) => {
buffer.copy_from_slice(&ip.octets());
}
Self::Ttl(value) | Self::Tos(value) => buffer[0] = *value,
Self::PathMTUDiscovery(discover) => {
buffer[0] = if *discover { 1 } else { 0 }
}
Self::EncapType(t) => emit_u16_be(buffer, t.into()).unwrap(),
Self::EncapFlags(flags) => {
emit_u16_be(buffer, flags.bits()).unwrap()
}
Self::SourcePort(port) | Self::DestinationPort(port) => {
emit_u16_be(buffer, *port).unwrap()
}
Self::CollectMetadata => {}
Self::FwMask(fw_mask) => emit_u32_be(buffer, *fw_mask).unwrap(),
Self::Other(nla) => nla.emit_value(buffer),
}
}

fn kind(&self) -> u16 {
match self {
Self::Link(_) => IFLA_GRE_LINK,
Self::IFlags(_) => IFLA_GRE_IFLAGS,
Self::OFlags(_) => IFLA_GRE_OFLAGS,
Self::IKey(_) => IFLA_GRE_IKEY,
Self::Local(_) => IFLA_GRE_LOCAL,
Self::Remote(_) => IFLA_GRE_REMOTE,
Self::OKey(_) => IFLA_GRE_OKEY,
Self::Ttl(_) => IFLA_GRE_TTL,
Self::Tos(_) => IFLA_GRE_TOS,
Self::PathMTUDiscovery(_) => IFLA_GRE_PMTUDISC,
Self::EncapType(_) => IFLA_GRE_ENCAP_TYPE,
Self::EncapFlags(_) => IFLA_GRE_ENCAP_FLAGS,
Self::SourcePort(_) => IFLA_GRE_ENCAP_SPORT,
Self::DestinationPort(_) => IFLA_GRE_ENCAP_DPORT,
Self::CollectMetadata => IFLA_GRE_COLLECT_METADATA,
Self::FwMask(_) => IFLA_GRE_FWMARK,
Self::Other(nla) => nla.kind(),
}
}
}

impl<'a, T: AsRef<[u8]> + ?Sized> Parseable<NlaBuffer<&'a T>> for InfoGre {
fn parse(buf: &NlaBuffer<&'a T>) -> Result<Self, DecodeError> {
let payload = buf.value();
Ok(match buf.kind() {
IFLA_GRE_LINK => Self::Link(
parse_u32_be(payload).context("invalid IFLA_GRE_LINK value")?,
),
IFLA_GRE_IFLAGS => Self::IFlags(GreIOFlags::from_bits_retain(
parse_u16_be(payload)
.context("invalid IFLA_GRE_IFLAGS value")?,
)),
IFLA_GRE_OFLAGS => Self::OFlags(GreIOFlags::from_bits_retain(
parse_u16_be(payload)
.context("invalid IFLA_GRE_OFLAGS value")?,
)),
IFLA_GRE_IKEY => Self::IKey(
parse_u32_be(payload).context("invalid IFLA_GRE_IKEY value")?,
),
IFLA_GRE_OKEY => Self::OKey(
parse_u32_be(payload).context("invalid IFLA_GRE_OKEY value")?,
),
IFLA_GRE_LOCAL => Self::Local(
parse_ipv4_addr(payload)
.context("invalid IFLA_GRE_LOCAL value")?,
),
IFLA_GRE_REMOTE => Self::Remote(
parse_ipv4_addr(payload)
.context("invalid IFLA_GRE_LOCAL value")?,
),
IFLA_GRE_TTL => Self::Ttl(
parse_u8(payload).context("invalid IFLA_GRE_TTL value")?,
),
IFLA_GRE_TOS => Self::Tos(
parse_u8(payload).context("invalid IFLA_GRE_TOS value")?,
),
IFLA_GRE_PMTUDISC => Self::PathMTUDiscovery(
parse_u8(payload).context("invalid IFLA_GRE_TOS value")? == 1,
),
IFLA_GRE_ENCAP_TYPE => Self::EncapType(GreEncapType::from(
parse_u16_be(payload)
.context("invalid IFLA_GRE_ENCAP_TYPE value")?,
)),
IFLA_GRE_ENCAP_FLAGS => {
Self::EncapFlags(GreEncapFlags::from_bits_retain(
parse_u16_be(payload)
.context("invalid IFLA_GRE_ENCAP_FLAGS value")?,
))
}
IFLA_GRE_ENCAP_SPORT => Self::SourcePort(
parse_u16_be(payload)
.context("invalid IFLA_GRE_ENCAP_SPORT value")?,
),
IFLA_GRE_ENCAP_DPORT => Self::DestinationPort(
parse_u16_be(payload)
.context("invalid IFLA_GRE_ENCAP_DPORT value")?,
),
IFLA_GRE_COLLECT_METADATA => Self::CollectMetadata,
IFLA_GRE_FWMARK => Self::FwMask(
parse_u32_be(payload)
.context("invalid IFLA_GRE_FWMARK value")?,
),
kind => Self::Other(
DefaultNla::parse(buf)
.context(format!("unknown NLA type {kind} for ip6gre"))?,
),
})
}
}
Loading
Loading