Skip to content

Commit f002e81

Browse files
committed
Refactor: Use enums for subsystem and message types
This refactors the crate to use type-safe enums for netfilter subsystems and message types, for a safer and more idiomatic API. - Introduces a `Subsystem` enum to replace raw `u8` identifiers for `NfLog` and `Conntrack` subsystems. - Introduces `NfLogMessageType` and `ConntrackMessageType` enums to provide type safety for messages within each subsystem. - Makes the top-level `NetfilterMessage::message_type()` function private to guide users towards the safer pattern of matching on `NetfilterMessageInner`. - Updates the internal parsing logic in `buffer.rs` to use the new `Subsystem` enum. Signed-off-by: Shivang K Raghuvanshi <[email protected]>
1 parent 61dbec7 commit f002e81

File tree

9 files changed

+142
-61
lines changed

9 files changed

+142
-61
lines changed

src/buffer.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
use crate::{
44
conntrack::ConntrackMessage,
55
message::{
6-
NetfilterHeader, NetfilterMessage, NetfilterMessageInner,
6+
NetfilterHeader, NetfilterMessage, NetfilterMessageInner, Subsystem,
77
NETFILTER_HEADER_LEN,
88
},
99
nflog::NfLogMessage,
@@ -53,17 +53,17 @@ impl<'a, T: AsRef<[u8]> + ?Sized>
5353
.context("failed to parse netfilter header")?;
5454
let subsys = (message_type >> 8) as u8;
5555
let message_type = message_type as u8;
56-
let inner = match subsys {
57-
NfLogMessage::SUBSYS => NetfilterMessageInner::NfLog(
56+
let inner = match Subsystem::from(subsys) {
57+
Subsystem::NfLog => NetfilterMessageInner::NfLog(
5858
NfLogMessage::parse_with_param(buf, message_type)
5959
.context("failed to parse nflog payload")?,
6060
),
61-
ConntrackMessage::SUBSYS => NetfilterMessageInner::Conntrack(
61+
Subsystem::Conntrack => NetfilterMessageInner::Conntrack(
6262
ConntrackMessage::parse_with_param(buf, message_type)
6363
.context("failed to parse conntrack payload")?,
6464
),
65-
_ => NetfilterMessageInner::Other {
66-
subsys,
65+
subsys_enum @ Subsystem::Other(_) => NetfilterMessageInner::Other {
66+
subsys: subsys_enum,
6767
message_type,
6868
attributes: buf.default_nlas()?,
6969
},

src/conntrack/message.rs

Lines changed: 41 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,6 @@
11
// SPDX-License-Identifier: MIT
22

3-
use crate::{
4-
buffer::NetfilterBuffer,
5-
conntrack::attributes::ConntrackNla,
6-
constants::{IPCTNL_MSG_CT_GET, NFNL_SUBSYS_CTNETLINK},
7-
};
3+
use crate::{buffer::NetfilterBuffer, conntrack::attributes::ConntrackNla};
84
use netlink_packet_core::{
95
DecodeError, DefaultNla, Emitable, Parseable, ParseableParametrized,
106
};
@@ -19,13 +15,40 @@ pub enum ConntrackMessage {
1915
},
2016
}
2117

22-
impl ConntrackMessage {
23-
pub(crate) const SUBSYS: u8 = NFNL_SUBSYS_CTNETLINK;
18+
const IPCTNL_MSG_CT_GET: u8 = 1;
19+
20+
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
21+
#[non_exhaustive]
22+
pub enum ConntrackMessageType {
23+
Get,
24+
Other(u8),
25+
}
26+
27+
impl From<u8> for ConntrackMessageType {
28+
fn from(value: u8) -> Self {
29+
match value {
30+
IPCTNL_MSG_CT_GET => Self::Get,
31+
v => Self::Other(v),
32+
}
33+
}
34+
}
35+
36+
impl From<ConntrackMessageType> for u8 {
37+
fn from(value: ConntrackMessageType) -> Self {
38+
match value {
39+
ConntrackMessageType::Get => IPCTNL_MSG_CT_GET,
40+
ConntrackMessageType::Other(v) => v,
41+
}
42+
}
43+
}
2444

25-
pub fn message_type(&self) -> u8 {
45+
impl ConntrackMessage {
46+
pub fn message_type(&self) -> ConntrackMessageType {
2647
match self {
27-
ConntrackMessage::Get(_) => IPCTNL_MSG_CT_GET,
28-
ConntrackMessage::Other { message_type, .. } => *message_type,
48+
ConntrackMessage::Get(_) => ConntrackMessageType::Get,
49+
ConntrackMessage::Other { message_type, .. } => {
50+
(*message_type).into()
51+
}
2952
}
3053
}
3154
}
@@ -61,16 +84,18 @@ impl<'a, T: AsRef<[u8]> + ?Sized>
6184
buf: &NetfilterBuffer<&'a T>,
6285
message_type: u8,
6386
) -> Result<Self, DecodeError> {
64-
Ok(match message_type {
65-
IPCTNL_MSG_CT_GET => {
87+
Ok(match ConntrackMessageType::from(message_type) {
88+
ConntrackMessageType::Get => {
6689
let attributes = buf
6790
.parse_all_nlas(|nla_buf| ConntrackNla::parse(&nla_buf))?;
6891
ConntrackMessage::Get(attributes)
6992
}
70-
_ => ConntrackMessage::Other {
71-
message_type,
72-
attributes: buf.default_nlas()?,
73-
},
93+
ConntrackMessageType::Other(message_type) => {
94+
ConntrackMessage::Other {
95+
message_type,
96+
attributes: buf.default_nlas()?,
97+
}
98+
}
7499
})
75100
}
76101
}

src/conntrack/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// SPDX-License-Identifier: MIT
22

33
mod message;
4-
pub use message::ConntrackMessage;
4+
pub use message::{ConntrackMessage, ConntrackMessageType};
55
mod attributes;
66
pub use attributes::{
77
ConntrackNla, IPTuple, ProtoInfo, ProtoInfoTCP, ProtoTuple, Protocol,

src/constants.rs

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -43,10 +43,8 @@ pub const AF_ALG: u8 = libc::AF_ALG as u8;
4343
pub const NFNETLINK_V0: u8 = libc::NFNETLINK_V0 as u8;
4444

4545
pub const NFNL_SUBSYS_NONE: u8 = libc::NFNL_SUBSYS_NONE as u8;
46-
pub const NFNL_SUBSYS_CTNETLINK: u8 = libc::NFNL_SUBSYS_CTNETLINK as u8;
4746
pub const NFNL_SUBSYS_CTNETLINK_EXP: u8 = libc::NFNL_SUBSYS_CTNETLINK_EXP as u8;
4847
pub const NFNL_SUBSYS_QUEUE: u8 = libc::NFNL_SUBSYS_QUEUE as u8;
49-
pub const NFNL_SUBSYS_ULOG: u8 = libc::NFNL_SUBSYS_ULOG as u8;
5048
pub const NFNL_SUBSYS_OSF: u8 = libc::NFNL_SUBSYS_OSF as u8;
5149
pub const NFNL_SUBSYS_IPSET: u8 = libc::NFNL_SUBSYS_IPSET as u8;
5250
pub const NFNL_SUBSYS_ACCT: u8 = libc::NFNL_SUBSYS_ACCT as u8;
@@ -83,8 +81,3 @@ pub const NFULA_HWHEADER: u16 = libc::NFULA_HWHEADER as u16;
8381
pub const NFULA_HWLEN: u16 = libc::NFULA_HWLEN as u16;
8482
pub const NFULA_CT: u16 = libc::NFULA_CT as u16;
8583
pub const NFULA_CT_INFO: u16 = libc::NFULA_CT_INFO as u16;
86-
87-
pub const NFULNL_MSG_CONFIG: u8 = libc::NFULNL_MSG_CONFIG as u8;
88-
pub const NFULNL_MSG_PACKET: u8 = libc::NFULNL_MSG_PACKET as u8;
89-
90-
pub(crate) const IPCTNL_MSG_CT_GET: u8 = 1;

src/lib.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,9 @@
33
pub(crate) mod buffer;
44
pub mod constants;
55
mod message;
6-
pub use message::{NetfilterHeader, NetfilterMessage, NetfilterMessageInner};
6+
pub use message::{
7+
NetfilterHeader, NetfilterMessage, NetfilterMessageInner, Subsystem,
8+
};
79
pub mod conntrack;
810
pub mod nflog;
911
#[cfg(test)]

src/message.rs

Lines changed: 41 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -60,13 +60,44 @@ impl<T: AsRef<[u8]>> Parseable<NetfilterHeaderBuffer<T>> for NetfilterHeader {
6060
}
6161
}
6262

63+
const NFNL_SUBSYS_CTNETLINK: u8 = libc::NFNL_SUBSYS_CTNETLINK as u8;
64+
const NFNL_SUBSYS_ULOG: u8 = libc::NFNL_SUBSYS_ULOG as u8;
65+
66+
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
67+
#[non_exhaustive]
68+
pub enum Subsystem {
69+
NfLog,
70+
Conntrack,
71+
Other(u8),
72+
}
73+
74+
impl From<u8> for Subsystem {
75+
fn from(value: u8) -> Self {
76+
match value {
77+
NFNL_SUBSYS_ULOG => Self::NfLog,
78+
NFNL_SUBSYS_CTNETLINK => Self::Conntrack,
79+
v => Self::Other(v),
80+
}
81+
}
82+
}
83+
84+
impl From<Subsystem> for u8 {
85+
fn from(value: Subsystem) -> Self {
86+
match value {
87+
Subsystem::NfLog => NFNL_SUBSYS_ULOG,
88+
Subsystem::Conntrack => NFNL_SUBSYS_CTNETLINK,
89+
Subsystem::Other(v) => v,
90+
}
91+
}
92+
}
93+
6394
#[derive(Debug, PartialEq, Eq, Clone)]
6495
#[non_exhaustive]
6596
pub enum NetfilterMessageInner {
6697
NfLog(NfLogMessage),
6798
Conntrack(ConntrackMessage),
6899
Other {
69-
subsys: u8,
100+
subsys: Subsystem,
70101
message_type: u8,
71102
attributes: Vec<DefaultNla>,
72103
},
@@ -123,19 +154,21 @@ impl NetfilterMessage {
123154
}
124155
}
125156

126-
pub fn subsys(&self) -> u8 {
157+
pub fn subsys(&self) -> Subsystem {
127158
match self.inner {
128-
NetfilterMessageInner::NfLog(_) => NfLogMessage::SUBSYS,
129-
NetfilterMessageInner::Conntrack(_) => ConntrackMessage::SUBSYS,
159+
NetfilterMessageInner::NfLog(_) => Subsystem::NfLog,
160+
NetfilterMessageInner::Conntrack(_) => Subsystem::Conntrack,
130161
NetfilterMessageInner::Other { subsys, .. } => subsys,
131162
}
132163
}
133164

134-
pub fn message_type(&self) -> u8 {
165+
fn message_type(&self) -> u8 {
135166
match self.inner {
136-
NetfilterMessageInner::NfLog(ref message) => message.message_type(),
167+
NetfilterMessageInner::NfLog(ref message) => {
168+
message.message_type().into()
169+
}
137170
NetfilterMessageInner::Conntrack(ref message) => {
138-
message.message_type()
171+
message.message_type().into()
139172
}
140173
NetfilterMessageInner::Other { message_type, .. } => message_type,
141174
}
@@ -155,7 +188,7 @@ impl Emitable for NetfilterMessage {
155188

156189
impl NetlinkSerializable for NetfilterMessage {
157190
fn message_type(&self) -> u16 {
158-
((self.subsys() as u16) << 8) | self.message_type() as u16
191+
((u8::from(self.subsys()) as u16) << 8) | self.message_type() as u16
159192
}
160193

161194
fn buffer_len(&self) -> usize {

src/nflog/message.rs

Lines changed: 39 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ use netlink_packet_core::{
66

77
use crate::{
88
buffer::NetfilterBuffer,
9-
constants::{NFNL_SUBSYS_ULOG, NFULNL_MSG_CONFIG, NFULNL_MSG_PACKET},
109
nflog::nlas::{config::ConfigNla, packet::PacketNla},
1110
};
1211

@@ -20,14 +19,43 @@ pub enum NfLogMessage {
2019
},
2120
}
2221

23-
impl NfLogMessage {
24-
pub const SUBSYS: u8 = NFNL_SUBSYS_ULOG;
22+
const NFULNL_MSG_CONFIG: u8 = libc::NFULNL_MSG_CONFIG as u8;
23+
const NFULNL_MSG_PACKET: u8 = libc::NFULNL_MSG_PACKET as u8;
24+
25+
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
26+
#[non_exhaustive]
27+
pub enum NfLogMessageType {
28+
Config,
29+
Packet,
30+
Other(u8),
31+
}
32+
33+
impl From<u8> for NfLogMessageType {
34+
fn from(value: u8) -> Self {
35+
match value {
36+
NFULNL_MSG_CONFIG => Self::Config,
37+
NFULNL_MSG_PACKET => Self::Packet,
38+
v => Self::Other(v),
39+
}
40+
}
41+
}
42+
43+
impl From<NfLogMessageType> for u8 {
44+
fn from(value: NfLogMessageType) -> Self {
45+
match value {
46+
NfLogMessageType::Config => NFULNL_MSG_CONFIG,
47+
NfLogMessageType::Packet => NFULNL_MSG_PACKET,
48+
NfLogMessageType::Other(v) => v,
49+
}
50+
}
51+
}
2552

26-
pub fn message_type(&self) -> u8 {
53+
impl NfLogMessage {
54+
pub fn message_type(&self) -> NfLogMessageType {
2755
match self {
28-
NfLogMessage::Config(_) => NFULNL_MSG_CONFIG,
29-
NfLogMessage::Packet(_) => NFULNL_MSG_PACKET,
30-
NfLogMessage::Other { message_type, .. } => *message_type,
56+
NfLogMessage::Config(_) => NfLogMessageType::Config,
57+
NfLogMessage::Packet(_) => NfLogMessageType::Packet,
58+
NfLogMessage::Other { message_type, .. } => (*message_type).into(),
3159
}
3260
}
3361
}
@@ -57,18 +85,18 @@ impl<'a, T: AsRef<[u8]> + ?Sized>
5785
buf: &NetfilterBuffer<&'a T>,
5886
message_type: u8,
5987
) -> Result<Self, DecodeError> {
60-
Ok(match message_type {
61-
NFULNL_MSG_CONFIG => {
88+
Ok(match NfLogMessageType::from(message_type) {
89+
NfLogMessageType::Config => {
6290
let nlas =
6391
buf.parse_all_nlas(|nla_buf| ConfigNla::parse(&nla_buf))?;
6492
NfLogMessage::Config(nlas)
6593
}
66-
NFULNL_MSG_PACKET => {
94+
NfLogMessageType::Packet => {
6795
let nlas =
6896
buf.parse_all_nlas(|nla_buf| PacketNla::parse(&nla_buf))?;
6997
NfLogMessage::Packet(nlas)
7098
}
71-
_ => NfLogMessage::Other {
99+
NfLogMessageType::Other(message_type) => NfLogMessage::Other {
72100
message_type,
73101
nlas: buf.default_nlas()?,
74102
},

src/nflog/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// SPDX-License-Identifier: MIT
22

33
mod message;
4-
pub use message::NfLogMessage;
4+
pub use message::{NfLogMessage, NfLogMessageType};
55
pub mod nlas;
66

77
use netlink_packet_core::{

src/tests.rs

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,16 @@
22

33
use std::net::IpAddr;
44

5-
use libc::NFNL_SUBSYS_CTNETLINK;
65
use netlink_packet_core::{Emitable, ParseableParametrized};
76

87
use crate::{
98
buffer::NetfilterBuffer,
109
conntrack::{
11-
ConntrackMessage, ConntrackNla, IPTuple, ProtoInfo, ProtoInfoTCP,
12-
ProtoTuple, Protocol, TCPFlags, Tuple,
10+
ConntrackMessage, ConntrackMessageType, ConntrackNla, IPTuple,
11+
ProtoInfo, ProtoInfoTCP, ProtoTuple, Protocol, TCPFlags, Tuple,
1312
},
14-
constants::{AF_INET, AF_INET6, AF_UNSPEC, IPCTNL_MSG_CT_GET},
13+
constants::{AF_INET, AF_INET6, AF_UNSPEC},
14+
message::Subsystem,
1515
NetfilterHeader, NetfilterMessage,
1616
};
1717

@@ -32,8 +32,8 @@ fn test_dump_conntrack() {
3232
// Check if the serialization was correct
3333
assert_eq!(buffer, raw);
3434

35-
let message_type =
36-
((NFNL_SUBSYS_CTNETLINK as u16) << 8) | (IPCTNL_MSG_CT_GET as u16);
35+
let message_type = ((u8::from(Subsystem::Conntrack) as u16) << 8)
36+
| (u8::from(ConntrackMessageType::Get) as u16);
3737
// Check if the deserialization was correct
3838
assert_eq!(
3939
NetfilterMessage::parse_with_param(
@@ -100,8 +100,8 @@ fn test_get_conntrack_tcp_ipv4() {
100100
// Check if the serialization was correct
101101
assert_eq!(buffer, raw);
102102

103-
let message_type =
104-
((NFNL_SUBSYS_CTNETLINK as u16) << 8) | (IPCTNL_MSG_CT_GET as u16);
103+
let message_type = ((u8::from(Subsystem::Conntrack) as u16) << 8)
104+
| (u8::from(ConntrackMessageType::Get) as u16);
105105
// Check if the deserialization was correct
106106
assert_eq!(
107107
NetfilterMessage::parse_with_param(
@@ -156,8 +156,8 @@ fn test_get_conntrack_udp_ipv6() {
156156
// Check if the serialization was correct
157157
assert_eq!(buffer, raw);
158158

159-
let message_type =
160-
((NFNL_SUBSYS_CTNETLINK as u16) << 8) | (IPCTNL_MSG_CT_GET as u16);
159+
let message_type = ((u8::from(Subsystem::Conntrack) as u16) << 8)
160+
| (u8::from(ConntrackMessageType::Get) as u16);
161161
// Check if the deserialization was correct
162162
assert_eq!(
163163
NetfilterMessage::parse_with_param(

0 commit comments

Comments
 (0)