@@ -60,6 +60,7 @@ impl Socket {
60
60
#[ non_exhaustive]
61
61
pub enum IpAncillaryData {
62
62
Ttl ( u8 ) ,
63
+ HopLimit ( u8 ) ,
63
64
}
64
65
65
66
impl IpAncillaryData {
@@ -84,6 +85,17 @@ impl IpAncillaryData {
84
85
IpAncillaryData :: Ttl ( ttl)
85
86
}
86
87
88
+ /// Create a `AncillaryData::HopLimit` variant.
89
+ ///
90
+ /// # Safety
91
+ ///
92
+ /// `data` must contain a valid control message and the control message must be type of
93
+ /// `IPPROTO_IPV6` and level of `IPV6_HOPLIMIT`.
94
+ unsafe fn as_hop_limit ( data : & [ u8 ] ) -> Self {
95
+ let hop_limit = IpAncillaryData :: as_u8 ( data) ;
96
+ IpAncillaryData :: HopLimit ( hop_limit)
97
+ }
98
+
87
99
unsafe fn try_from ( cmsg : & libc:: cmsghdr ) -> Result < Self , AncillaryError > {
88
100
let data = get_data_from_cmsghdr ( cmsg) ;
89
101
@@ -94,6 +106,12 @@ impl IpAncillaryData {
94
106
Err ( AncillaryError :: Unknown { cmsg_level : libc:: IPPROTO_IP , cmsg_type } )
95
107
}
96
108
} ,
109
+ libc:: IPPROTO_IPV6 => match ( * cmsg) . cmsg_type {
110
+ libc:: IPV6_HOPLIMIT => Ok ( IpAncillaryData :: as_hop_limit ( data) ) ,
111
+ cmsg_type => {
112
+ Err ( AncillaryError :: Unknown { cmsg_level : libc:: IPPROTO_IPV6 , cmsg_type } )
113
+ }
114
+ } ,
97
115
cmsg_level => Err ( AncillaryError :: Unknown { cmsg_level, cmsg_type : ( * cmsg) . cmsg_type } ) ,
98
116
}
99
117
}
@@ -146,7 +164,7 @@ pub struct IpAncillary<'a> {
146
164
}
147
165
148
166
impl < ' a > IpAncillary < ' a > {
149
- /// Create an ancillary data with the given buffer.
167
+ /// Create ancillary data backed by the given buffer.
150
168
///
151
169
/// # Example
152
170
///
@@ -186,12 +204,53 @@ impl<'a> IpAncillary<'a> {
186
204
self . inner . messages ( )
187
205
}
188
206
207
+ /// Add hop-limit to the ancillary data.
208
+ ///
209
+ /// The function returns `true` if there was enough space in the buffer.
210
+ /// If there was not enough space then no hop-limit was appended.
211
+ /// This adds a control message with the level `IPPROTO_IPV6` and type `IPV6_HOPLIMIT`.
212
+ ///
213
+ /// # Example
214
+ /// ```no_run
215
+ /// #![feature(unix_socket_ancillary_data)]
216
+ /// use std::io::IoSlice;
217
+ /// use std::net::UdpSocket;
218
+ /// use std::os::unix::net::IpAncillary;
219
+ ///
220
+ /// fn main() -> std::io::Result<()> {
221
+ /// let sock = UdpSocket::bind("[::1]:34254")?;
222
+ /// sock.connect("[::1]:41203")?;
223
+ /// let buf1 = [1; 8];
224
+ /// let buf2 = [2; 16];
225
+ /// let buf3 = [3; 8];
226
+ /// let bufs = &[
227
+ /// IoSlice::new(&buf1),
228
+ /// IoSlice::new(&buf2),
229
+ /// IoSlice::new(&buf3),
230
+ /// ][..];
231
+ /// let mut ancillary_buffer = [0; 128];
232
+ /// let mut ancillary = IpAncillary::new(&mut ancillary_buffer[..]);
233
+ /// ancillary.add_hop_limit(20);
234
+ /// sock.send_vectored_with_ancillary(bufs, &mut ancillary)
235
+ /// .expect("send_vectored_with_ancillary function failed");
236
+ /// Ok(())
237
+ /// }
238
+ /// ```
239
+ #[ unstable( feature = "unix_socket_ancillary_data" , issue = "76915" ) ]
240
+ pub fn add_hop_limit ( & mut self , hop_limit : u8 ) -> bool {
241
+ let hop_limit: libc:: c_int = hop_limit as libc:: c_int ;
242
+ self . inner . add_to_ancillary_data (
243
+ from_ref ( & hop_limit) ,
244
+ libc:: IPPROTO_IPV6 ,
245
+ libc:: IPV6_HOPLIMIT ,
246
+ )
247
+ }
248
+
189
249
/// Add TTL to the ancillary data.
190
250
///
191
251
/// The function returns `true` if there was enough space in the buffer.
192
252
/// If there was not enough space then no file descriptors was appended.
193
- /// Technically, that means this operation adds a control message with the level `IPPROTO_IP`
194
- /// and type `IP_TTL`.
253
+ /// This adds a control message with the level `IPPROTO_IP` and type `IP_TTL`.
195
254
///
196
255
/// # Example
197
256
/// ```no_run
0 commit comments