1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
//! OpenVPN data-channel offload (DCO) Generic Netlink family.
//!
//! The kernel's `ovpn` GENL family (stabilized in **Linux 6.16**)
//! lets userspace push OpenVPN 2.7 data-channel processing into
//! the kernel. The TLS handshake stays in userspace; the
//! pre-derived AEAD keys + per-peer socket descriptors are handed
//! to the kernel via this family, and packets are encrypted /
//! decrypted in-kernel from then on. This eliminates the
//! per-packet user/kernel boundary crossings that bottlenecked
//! pre-2.7 OpenVPN.
//!
//! # Status — Plan 197
//!
//! | Phase | Ships |
//! |---|---|
//! | Family marker + module scaffold | ✓ |
//! | Command + attribute + value enums | ✓ |
//! | Imperative `Connection<Ovpn>` methods | ✓ |
//! | Multicast `peers` group + `OvpnEvent` | ✓ |
//! | Declarative `OvpnConfig` + diff + apply | ✓ |
//! | `attach_socket` SCM_RIGHTS cross-netns | deferred |
//!
//! The interface itself is created via RTNL — see
//! [`OvpnLink`][crate::netlink::link::OvpnLink] (Plan 190 §2.3b).
//! The GENL family operates on an already-existing ovpn interface
//! by `ifindex`.
//!
//! # Construction
//!
//! ```no_run
//! # async fn example() -> Result<(), Box<dyn std::error::Error>> {
//! use nlink::netlink::{Connection, genl::ovpn::Ovpn};
//!
//! let conn = Connection::<Ovpn>::new_async().await?;
//! // Family ID resolved against the kernel "ovpn" registration;
//! // FamilyNotFound on kernels without CONFIG_OVPN.
//! # Ok(())
//! # }
//! ```
//!
//! Resolution failure is the common case on stock distro kernels
//! that don't load the `ovpn` module. Handle via
//! [`Error::is_not_found`](crate::Error::is_not_found):
//!
//! ```no_run
//! # async fn example() -> nlink::Result<()> {
//! # use nlink::Connection;
//! # use nlink::netlink::genl::ovpn::Ovpn;
//! match Connection::<Ovpn>::new_async().await {
//! Ok(conn) => { /* use it */ }
//! Err(e) if e.is_not_found() => {
//! tracing::warn!("OVPN DCO not available on this kernel; skipping");
//! }
//! Err(e) => return Err(e),
//! }
//! # Ok(())
//! # }
//! ```
//!
//! # Cipher constraints
//!
//! The kernel accepts AES-GCM (128 or 256-bit) and
//! ChaCha20-Poly1305 only — the TLS handshake in OpenVPN 2.7
//! must negotiate one of these. Legacy CBC + non-AEAD modes are
//! intentionally not supported in DCO mode.
use crategenl_family;
pub use ;
pub use OvpnEvent;
pub use ;
pub use ;
/// OVPN Generic Netlink family marker.
///
/// Constructed via [`Connection::<Ovpn>::new_async()`][Connection]
/// — the family ID is resolved against the kernel at connection
/// time. Returns
/// [`Error::FamilyNotFound`](crate::Error::FamilyNotFound) on
/// kernels without OVPN support (kernel < 6.16 or `ovpn` module
/// not loaded).
///
/// [Connection]: crate::netlink::Connection
;