@@ -60,6 +60,7 @@ impl Socket {
6060#[ non_exhaustive]
6161pub enum IpAncillaryData {
6262 Ttl ( u8 ) ,
63+ HopLimit ( u8 ) ,
6364}
6465
6566impl IpAncillaryData {
@@ -84,6 +85,17 @@ impl IpAncillaryData {
8485 IpAncillaryData :: Ttl ( ttl)
8586 }
8687
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+
8799 unsafe fn try_from ( cmsg : & libc:: cmsghdr ) -> Result < Self , AncillaryError > {
88100 let data = get_data_from_cmsghdr ( cmsg) ;
89101
@@ -94,6 +106,12 @@ impl IpAncillaryData {
94106 Err ( AncillaryError :: Unknown { cmsg_level : libc:: IPPROTO_IP , cmsg_type } )
95107 }
96108 } ,
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+ } ,
97115 cmsg_level => Err ( AncillaryError :: Unknown { cmsg_level, cmsg_type : ( * cmsg) . cmsg_type } ) ,
98116 }
99117 }
@@ -146,7 +164,7 @@ pub struct IpAncillary<'a> {
146164}
147165
148166impl < ' a > IpAncillary < ' a > {
149- /// Create an ancillary data with the given buffer.
167+ /// Create ancillary data backed by the given buffer.
150168 ///
151169 /// # Example
152170 ///
@@ -186,12 +204,53 @@ impl<'a> IpAncillary<'a> {
186204 self . inner . messages ( )
187205 }
188206
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+
189249 /// Add TTL to the ancillary data.
190250 ///
191251 /// The function returns `true` if there was enough space in the buffer.
192252 /// 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`.
195254 ///
196255 /// # Example
197256 /// ```no_run
0 commit comments