Skip to main content

uds_fork/
traits.rs

1
2use std::
3{
4    ffi::c_void, io::{self, IoSlice, IoSliceMut}, os::
5    {
6        fd::{AsFd, OwnedFd, RawFd}, 
7        unix::{io::{AsRawFd, FromRawFd}, net::{UnixDatagram, UnixListener, UnixStream}} 
8    }
9};
10
11use libc::{MSG_PEEK, recvfrom, sendto};
12
13use crate::addr::UnixSocketAddr;
14use crate::helpers::*;
15use crate::ancillary::*;
16use crate::credentials::*;
17
18/// Extension trait for `std::os::unix::net::UnixStream` and nonblocking equivalents.
19pub trait UnixStreamExt: AsFd + AsRawFd + FromRawFd 
20{
21    /// Get the address of this socket, as a type that fully supports abstract addresses.
22    fn local_unix_addr(&self) -> Result<UnixSocketAddr, io::Error> 
23    {
24        get_unix_local_addr(self)
25    }
26
27    /// Returns the address of the other end of this stream,
28    /// as a type that fully supports abstract addresses.
29    fn peer_unix_addr(&self) -> Result<UnixSocketAddr, io::Error> 
30    {
31        get_unix_peer_addr(self)
32    }
33
34    /// Creates a connection to a listening path-based or abstract named socket.
35    fn connect_to_unix_addr(addr: &UnixSocketAddr) -> Result<Self, io::Error> where Self: Sized;
36
37    /// Creates a path-based or abstract-named socket and connects to a listening socket.
38    fn connect_from_to_unix_addr(from: &UnixSocketAddr, to: &UnixSocketAddr) -> Result<Self, io::Error> 
39        where Self: Sized;
40
41    /// Sends file descriptors in addition to bytes.
42    fn send_fds(&self, bytes: &[u8], fds: Vec<OwnedFd>) -> Result<usize, io::Error> 
43    {
44        let fds_raw = fds.iter().map(|fd| fd.as_raw_fd()).collect::<Vec<RawFd>>();
45
46        send_ancillary(self, None, 0, &[IoSlice::new(bytes)], &fds_raw, None)
47    }
48
49    /// Receives file descriptors in addition to bytes.
50    /// 
51    /// A FDs are placed into pre-allocated mutable slice. Received valies are stored
52    /// in reception sequence. The first [Option::None] does mean the rest are None too.
53    fn recv_slice_fds(&self, buf: &mut[u8], fd_buf: &mut [Option<OwnedFd>]) -> Result<(usize, usize), io::Error> 
54    {
55        recv_slice_fds(self, None, &mut[IoSliceMut::new(buf)], fd_buf)
56            .map(|(bytes, _, fds)| (bytes, fds) )
57    }
58
59    /// A FDs are placed into Vec with the specific capacity. 
60    /// 
61    /// A FDs will be truncated if the capacity is not large enough.
62    fn recv_fds(&self,  buf: &mut[u8], fd_buf: &mut Vec<OwnedFd>) -> Result<(usize, usize), io::Error> 
63    {
64        recv_fds(self, None, &mut[IoSliceMut::new(buf)], fd_buf)
65            .map(|(bytes, _, fds)| (bytes, fds) )
66    }
67
68    /// Returns the credentials of the process that created the other end of this stream.
69    fn initial_peer_credentials(&self) -> Result<ConnCredentials, io::Error> 
70    {
71        peer_credentials(self)
72    }
73    /// Returns the SELinux security context of the process that created the other end of this stream.
74    ///
75    /// Will return an error on other operating systems than Linux or Android,
76    /// and also if running under kubernetes.
77    /// On success the number of bytes used is returned. (like `Read`)
78    ///
79    /// The default security context is `unconfined`, without any trailing NUL.  
80    /// A buffor of 50 bytes is probably always big enough.
81    fn initial_peer_selinux_context(&self, buffer: &mut[u8]) -> Result<usize, io::Error> 
82    {
83        selinux_context(self, buffer)
84    }
85}
86
87impl UnixStreamExt for UnixStream 
88{
89    fn connect_to_unix_addr(addr: &UnixSocketAddr) -> Result<Self, io::Error> 
90    {
91        let socket = Socket::<SocketStream>::new(false)?;
92        socket.set_unix_peer_addr(addr)?;
93        
94        return Ok(Self::from( <Socket<SocketStream> as Into<OwnedFd>>::into(socket)));
95    }
96
97    fn connect_from_to_unix_addr(from: &UnixSocketAddr,  to: &UnixSocketAddr) -> Result<Self, io::Error> 
98    {
99        let socket = Socket::<SocketStream>::new(false)?;
100        socket.set_unix_local_addr(from)?;
101        socket.set_unix_peer_addr(to)?;
102        
103        return Ok(Self::from( <Socket<SocketStream> as Into<OwnedFd>>::into(socket)));
104    }
105}
106
107#[cfg(feature = "mio")]
108impl UnixStreamExt for mio::net::UnixStream 
109{
110    fn connect_to_unix_addr(addr: &UnixSocketAddr) -> Result<Self, io::Error> 
111    {
112        let socket = Socket::<SocketStream>::new(true)?;
113        socket.set_unix_peer_addr(addr)?;
114
115        return Ok(Self::from( <Socket<SocketStream> as Into<OwnedFd>>::into(socket)));
116    }
117
118    fn connect_from_to_unix_addr(from: &UnixSocketAddr,  to: &UnixSocketAddr) -> Result<Self, io::Error> 
119    {
120        let socket = Socket::<SocketStream>::new(true)?;
121        socket.set_unix_local_addr(from)?;
122        socket.set_unix_peer_addr(to)?;
123
124        return Ok(Self::from( <Socket<SocketStream> as Into<OwnedFd>>::into(socket)));
125    }
126}
127
128/// Extension trait for using [`UnixSocketAddr`](struct.UnixSocketAddr.html) with `UnixListener` types.
129pub trait UnixListenerExt: AsFd + AsRawFd + FromRawFd 
130{
131    /// The type represeting the stream connection returned by `accept_unix_addr()`.
132    type Conn: FromRawFd;
133
134    /// Creates a socket bound to a `UnixSocketAddr` and starts listening on it.
135    fn bind_unix_addr(on: &UnixSocketAddr) -> Result<Self, io::Error> 
136        where Self: Sized;
137
138    /// Returns the address this socket is listening on.
139    fn local_unix_addr(&self) -> Result<UnixSocketAddr, io::Error> 
140    {
141        get_unix_local_addr(self)
142    }
143
144    /// Accepts a connection and returns the client's address as
145    /// an `uds_fork::UnixSocketAddr`.
146    fn accept_unix_addr(&self) -> Result<(Self::Conn, UnixSocketAddr), io::Error>;
147}
148
149impl UnixListenerExt for UnixListener 
150{
151    type Conn = UnixStream;
152
153    fn bind_unix_addr(on: &UnixSocketAddr) -> Result<Self, io::Error> 
154    {
155        let socket = Socket::<SocketStream>::new(false)?;
156        socket.set_unix_local_addr(on)?;
157
158        socket.start_listening()?;
159        
160        return 
161            Ok(Self::from( <Socket<SocketStream> as Into<OwnedFd>>::into(socket)));
162    }
163
164    fn accept_unix_addr(&self) -> Result<(Self::Conn, UnixSocketAddr), io::Error> 
165    {
166        let (socket, addr) = Socket::<SocketStream>::accept_from(self, false)?;
167        let conn = 
168                Self::Conn::from(<Socket<SocketStream> as Into<OwnedFd>>::into(socket));
169        
170        return Ok((conn, addr));
171    }
172}
173
174
175#[cfg(feature = "mio")]
176impl UnixListenerExt for mio::net::UnixListener 
177{
178    type Conn = mio::net::UnixStream;
179
180    fn bind_unix_addr(on: &UnixSocketAddr) -> Result<Self, io::Error> 
181    {
182        let socket = Socket::<SocketStream>::new(true)?;
183        socket.set_unix_local_addr(on)?;
184
185        socket.start_listening()?;
186
187        return 
188            Ok(Self::from( <Socket<SocketStream> as Into<OwnedFd>>::into(socket)));
189    }
190
191    fn accept_unix_addr(&self) -> Result<(Self::Conn, UnixSocketAddr), io::Error> 
192    {
193        let (socket, addr) = Socket::<SocketStream>::accept_from(self, true)?;
194    
195        let conn = 
196                Self::Conn::from(<Socket<SocketStream> as Into<OwnedFd>>::into(socket));
197
198        Ok((conn, addr))
199    }
200}
201
202/// Extension trait for `std::os::unix::net::UnixDatagram` and nonblocking equivalents.
203pub trait UnixDatagramExt: AsFd + AsRawFd + FromRawFd 
204{
205    /// Create a socket bound to a path or abstract name.
206    ///
207    /// # Examples
208    ///
209    #[cfg_attr(any(target_os="linux", target_os="android"), doc="```")]
210    #[cfg_attr(not(any(target_os="linux", target_os="android")), doc="```no_run")]
211    /// # use std::os::unix::net::UnixDatagram;
212    /// # use uds_fork::{UnixDatagramExt, UnixSocketAddr};
213    /// #
214    /// # fn main() -> Result<(), std::io::Error> {
215    /// let addr = UnixSocketAddr::new("@abstract")?;
216    /// let socket = UnixDatagram::bind_unix_addr(&addr)?;
217    /// # let _ = socket.send_to_unix_addr(b"where are you", &addr);
218    /// # Ok(())
219    /// # }
220    /// ```
221    ///
222    /// This is equivalent of:
223    ///
224    /// ```
225    /// # use std::os::unix::net::UnixDatagram;
226    /// # use uds_fork::{UnixDatagramExt, UnixSocketAddr};
227    /// #
228    /// # fn main() -> Result<(), std::io::Error> {
229    /// # let addr = UnixSocketAddr::new("/tmp/me")?;
230    /// let socket = UnixDatagram::unbound()?;
231    /// socket.bind_to_unix_addr(&addr)?;
232    /// # let _ = std::fs::remove_file("/tmp/me");
233    /// # Ok(())
234    /// # }
235    /// ```
236    fn bind_unix_addr(addr: &UnixSocketAddr) -> Result<Self, io::Error> 
237        where Self: Sized;
238
239    /// Returns the address of this socket, as a type that fully supports abstract addresses.
240    fn local_unix_addr(&self) -> Result<UnixSocketAddr, io::Error> 
241    {
242        get_unix_local_addr(self)
243    }
244
245    /// Returns the address of the connected socket, as a type that fully supports abstract addresses.
246    fn peer_unix_addr(&self) -> Result<UnixSocketAddr, io::Error> 
247    {
248        get_unix_peer_addr(self)
249    }
250
251    /// Creates a path or abstract name for the socket.
252    fn bind_to_unix_addr(&self,  addr: &UnixSocketAddr) -> Result<(), io::Error> 
253    {
254        set_unix_local_addr(self, addr)
255    }
256
257    /// Connects the socket to a path-based or abstract named socket.
258    fn connect_to_unix_addr(&self,  addr: &UnixSocketAddr) -> Result<(), io::Error> 
259    {
260        set_unix_peer_addr(self, addr)
261    }
262
263    /// Sends to the specified address, using an address type that
264    /// supports abstract addresses.
265    ///
266    /// # Examples
267    ///
268    /// Send to an abstract address:
269    ///
270    #[cfg_attr(any(target_os="linux", target_os="android"), doc="```")]
271    #[cfg_attr(not(any(target_os="linux", target_os="android")), doc="```no_run")]
272    /// # use std::os::unix::net::UnixDatagram;
273    /// # use uds_fork::{UnixDatagramExt, UnixSocketAddr};
274    /// #
275    /// let socket = UnixDatagram::unbound().expect("create datagram socket");
276    /// let _ = socket.send_to_unix_addr(
277    ///     b"Is there anyone there?",
278    ///     &UnixSocketAddr::from_abstract("somewhere").expect("OS supports abstract addresses"),
279    /// );
280    /// ```
281    fn send_to_unix_addr(&self,  datagram: &[u8],  addr: &UnixSocketAddr) -> Result<usize, io::Error> 
282    {
283        let (sockaddr, socklen) = addr.as_raw_general();
284        
285        return 
286            unsafe {
287                cvt_r!(
288                    sendto(
289                        self.as_raw_fd(),
290                        datagram.as_ptr() as *const c_void,
291                        datagram.len(),
292                        MSG_NOSIGNAL,
293                        sockaddr,
294                        socklen,
295                    )
296                )
297                .map(|signed| signed as usize )
298            };
299    }
300    /// Sends a datagram created from multiple segments to the specified address,
301    /// using an address type that supports abstract addresses.
302    ///
303    /// # Examples
304    ///
305    /// Send a datagram with a fixed header:
306    ///
307    /// ```
308    /// # use std::os::unix::net::UnixDatagram;
309    /// # use std::io::IoSlice;
310    /// # use uds_fork::{UnixDatagramExt, UnixSocketAddr};
311    /// #
312    /// let socket = UnixDatagram::unbound().expect("create datagram socket");
313    /// let to = UnixSocketAddr::new("/var/run/someone.sock").unwrap();
314    /// let msg = [
315    ///     IoSlice::new(b"hello "),
316    ///     IoSlice::new(to.as_pathname().unwrap().to_str().unwrap().as_bytes()),
317    /// ];
318    /// let _ = socket.send_vectored_to_unix_addr(&msg, &to);
319    /// ```
320    fn send_vectored_to_unix_addr(&self,  datagram: &[IoSlice],  addr: &UnixSocketAddr) -> Result<usize, io::Error> 
321    {
322        send_ancillary(self, Some(addr), 0, datagram, &[], None)
323    }
324
325    /// Receives from any peer, storing its address in a type that exposes
326    /// abstract addresses.
327    ///
328    /// # Examples
329    ///
330    /// Respond to the received datagram, regardsless of where it was sent from:
331    ///
332    /// ```
333    /// use std::os::unix::net::UnixDatagram;
334    /// use uds_fork::{UnixSocketAddr, UnixDatagramExt};
335    ///
336    /// let dir = tempfile::tempdir().unwrap();
337    /// let mut file_path = dir.path().join("echo.sock");
338    /// 
339    /// let server = UnixDatagram::bind(&file_path).expect("create server socket");
340    ///
341    /// let mut cli_file_path = dir.path().join("echo_client.sock");
342    /// 
343    /// let client_addr = UnixSocketAddr::new("@echo_client")
344    ///     .or(UnixSocketAddr::new(cli_file_path.as_os_str().to_str().unwrap()))
345    ///     .unwrap();
346    /// let client = UnixDatagram::unbound().expect("create client ocket");
347    /// client.bind_to_unix_addr(&client_addr).expect("create client socket");
348    /// client.connect_to_unix_addr(&UnixSocketAddr::new(file_path.as_os_str().to_str().unwrap()).unwrap())
349    ///     .expect("connect to server");
350    /// client.send(b"hello").expect("send");
351    ///
352    /// let mut buf = [0; 1024];
353    /// let (len, from) = server.recv_from_unix_addr(&mut buf).expect("receive");
354    /// server.send_to_unix_addr(&buf[..len], &from).expect("respond");
355    ///
356    /// let len = client.recv(&mut buf).expect("receive response");
357    /// assert_eq!(&buf[..len], "hello".as_bytes());
358    ///
359    /// let _ = std::fs::remove_file(&file_path);
360    /// if let Some(client_path) = client_addr.as_pathname() {
361    ///     let _ = std::fs::remove_file(client_path);
362    /// }
363    /// ```
364    fn recv_from_unix_addr(&self,  buf: &mut[u8]) -> Result<(usize, UnixSocketAddr), io::Error> 
365    {
366        UnixSocketAddr::new_from_ffi(
367            |addr, len| 
368            {
369                unsafe {
370                    cvt_r!(
371                        recvfrom(
372                            self.as_raw_fd(),
373                            buf.as_ptr() as *mut c_void,
374                            buf.len(),
375                            MSG_NOSIGNAL,
376                            addr,
377                            len,
378                        )
379                    )
380                    .map(|signed| signed as usize )
381                }
382            }
383        )
384    }
385    /// Uses multiple buffers to receive from any peer, storing its address in
386    /// a type that exposes abstract addresses.
387    fn recv_vectored_from_unix_addr(&self,  bufs: &mut[IoSliceMut]) -> Result<(usize, UnixSocketAddr), io::Error> 
388    {
389        let mut addr = UnixSocketAddr::default();
390
391        recv_slice_fds(self, Some(&mut addr), bufs, &mut [])
392            .map(|(bytes, _, _)| (bytes, addr) )
393    }
394    
395    /// Reads the next datagram without removing it from the queue.
396    ///
397    /// # Examples
398    ///
399    /// Discard datagram if it's the wrong protocol:
400    ///
401    /// ```
402    /// # use std::os::unix::net::UnixDatagram;
403    /// # use uds_fork::{UnixSocketAddr, UnixDatagramExt};
404    /// #
405    /// let checker = UnixDatagram::bind("/tmp/checker.sock").expect("create receiver socket");
406    ///
407    /// let client = UnixDatagram::unbound().expect("create client ocket");
408    /// client.send_to(b"hello", "/tmp/checker.sock").expect("send");
409    ///
410    /// let mut header = [0; 4];
411    /// let (len, _from) = checker.peek_from_unix_addr(&mut header).expect("receive");
412    /// if len != 4  ||  header != *b"WTFP" {
413    ///     let _ = checker.recv(&mut header); // discard
414    /// } else {
415    ///     // call function that receives and processes it
416    /// }
417    /// #
418    /// # let _ = std::fs::remove_file("/tmp/checker.sock");
419    /// ```
420    fn peek_from_unix_addr(&self,  buf: &mut[u8]) -> Result<(usize, UnixSocketAddr), io::Error> 
421    {
422        UnixSocketAddr::new_from_ffi(
423            |addr, len| 
424            {
425            unsafe 
426            {
427                cvt_r!(
428                    recvfrom(
429                        self.as_raw_fd(),
430                        buf.as_ptr() as *mut c_void,
431                        buf.len(),
432                        MSG_PEEK | MSG_NOSIGNAL,
433                        addr,
434                        len,
435                    )
436                )
437                .map(|signed| signed as usize )
438            }
439        })
440    }
441
442    /// Uses multiple buffers to read the next datagram without removing it
443    /// from the queue.
444    ///
445    /// # Examples
446    ///
447    #[cfg_attr(any(target_os="linux", target_os="android"), doc="```")]
448    #[cfg_attr(not(any(target_os="linux", target_os="android")), doc="```no_run")]
449    /// use std::os::unix::net::UnixDatagram;
450    /// use std::io::IoSliceMut;
451    /// use tempfile::TempDir;
452    /// use uds_fork::{UnixDatagramExt, UnixSocketAddr};
453    /// 
454    /// let dir = tempfile::tempdir().unwrap();
455    /// let mut path = dir.path().join("datagram_server.sock");
456    /// 
457    /// let server = UnixDatagram::bind(&path).unwrap();
458    ///
459    /// // get a random abstract address on Linux
460    /// let client = UnixDatagram::unbound().unwrap();
461    /// client.bind_to_unix_addr(&UnixSocketAddr::new_unspecified()).unwrap();
462    /// client.connect(&path).unwrap();
463    /// client.send(b"headerbodybody").unwrap();
464    ///
465    /// let (mut buf_a, mut buf_b) = ([0; 6], [0; 12]);
466    /// let mut vector = [IoSliceMut::new(&mut buf_a), IoSliceMut::new(&mut buf_b)];
467    /// let (bytes, addr) = server.peek_vectored_from_unix_addr(&mut vector).unwrap();
468    /// assert_eq!(addr, client.local_unix_addr().unwrap());
469    /// assert_eq!(bytes, 14);
470    /// assert_eq!(&buf_a, b"header");
471    /// assert_eq!(&buf_b[..8], b"bodybody");
472    /// #
473    /// ```
474    fn peek_vectored_from_unix_addr(&self,  bufs: &mut[IoSliceMut]) -> Result<(usize, UnixSocketAddr), io::Error> 
475    {
476        let mut addr = UnixSocketAddr::default();
477
478        recv_ancillary(self,Some(&mut addr),MSG_PEEK | MSG_NOSIGNAL, bufs,&mut[])
479            .map(|(bytes, _)| (bytes, addr) )
480    }
481
482    /// Sends file descriptors along with the datagram, on an unconnected socket.
483    fn send_fds_to(&self, datagram: &[u8], fds: Vec<OwnedFd>, addr: &UnixSocketAddr) -> Result<usize, io::Error> 
484    {
485        let fds_raw = fds.iter().map(|fd| fd.as_raw_fd()).collect::<Vec<RawFd>>();
486
487        send_ancillary(self, Some(addr), 0, &[IoSlice::new(datagram)], &fds_raw, None)
488    }
489
490    unsafe 
491    fn send_fds_to_raw(&self, datagram: &[u8], fds: &[RawFd], addr: &UnixSocketAddr) -> Result<usize, io::Error> 
492    {
493        send_ancillary(self, Some(addr), 0, &[IoSlice::new(datagram)], fds, None)
494    }
495
496    /// Sends file descriptors along with the datagram, on a connected socket.
497    fn send_fds(&self, datagram: &[u8], fds: Vec<OwnedFd>) -> Result<usize, io::Error> 
498    {
499        let fds_raw = fds.iter().map(|fd| fd.as_raw_fd()).collect::<Vec<RawFd>>();
500
501        send_ancillary(self, None, 0, &[IoSlice::new(datagram)], &fds_raw, None)
502    }
503
504    unsafe 
505    fn send_fds_raw(&self, datagram: &[u8], fds: &[RawFd]) -> Result<usize, io::Error> 
506    {
507        send_ancillary(self, None, 0, &[IoSlice::new(datagram)], 
508            fds, None)
509    }
510
511    /// Receives file descriptors along with the datagram, on an unconnected socket
512    fn recv_slice_fds_from(&self,  buf: &mut[u8],  fd_buf: &mut [Option<OwnedFd>]) -> Result<(usize, usize, UnixSocketAddr), io::Error> 
513    {
514        let mut addr = UnixSocketAddr::default();
515        recv_slice_fds(self, Some(&mut addr), &mut[IoSliceMut::new(buf)], fd_buf)
516            .map(|(bytes, _, fds)| (bytes, fds, addr) )
517    }
518
519    fn recv_fds_from(&self,  buf: &mut[u8],  fd_buf: &mut Vec<OwnedFd>) -> Result<(usize, usize, UnixSocketAddr), io::Error> 
520    {
521        let mut addr = UnixSocketAddr::default();
522
523        recv_fds(self, Some(&mut addr), &mut[IoSliceMut::new(buf)], fd_buf)
524            .map(|(bytes, _, fds)| (bytes, fds, addr) )
525    }
526
527    /// Receives file descriptors along with the datagram, on a connected socket
528    fn recv_slice_fds(&self,  buf: &mut[u8],  fd_buf: &mut [Option<OwnedFd>]) -> Result<(usize, usize), io::Error> 
529    {
530        recv_slice_fds(self, None, &mut[IoSliceMut::new(buf)], fd_buf)
531            .map(|(bytes, _, fds)| (bytes, fds) )
532    }
533
534    
535    fn recv_fds(&self,  buf: &mut[u8],  fd_buf: &mut Vec<OwnedFd>) -> Result<(usize, usize), io::Error> 
536    {
537        recv_fds(self, None, &mut[IoSliceMut::new(buf)], fd_buf)
538            .map(|(bytes, _, fds)| (bytes, fds) )
539    }
540
541
542    /// Returns the credentials of the process that created a socket pair.
543    ///
544    /// This information is only available on Linux, and only for sockets that
545    /// was created with `pair()` or the underlying `socketpair()`.
546    /// For sockets that have merely been "connected" to an address
547    /// or not connected at all, an error of kind `NotConnected`
548    /// or `InvalidInput` is returned.
549    ///
550    /// The use cases of this function gotta be very narrow:
551    ///
552    /// * It will return the credentials of the current process unless
553    ///   the side of the socket this method is called on was received via
554    ///   FD-passing or inherited from a parent.
555    /// * If it was created by the direct parent process,
556    ///   one might as well use `getppid()` and go from there?
557    /// * A returned pid can be repurposed by the OS before the call returns.
558    /// * uids or groups will be those in effect when the pair was created,
559    ///   and will not reflect changes in privileges.
560    ///
561    /// Despite these limitations, the feature is supported by Linux at least
562    /// (but not macOS or FreeBSD), so might as well expose it.
563    fn initial_pair_credentials(&self) -> Result<ConnCredentials, io::Error> 
564    {
565        peer_credentials(self)
566    }
567    /// Returns the SELinux security context of the process that created a socket pair.
568    ///
569    /// Has the same limitations and gotchas as `initial_pair_credentials()`,
570    /// and will return an error on other OSes than Linux or Android
571    /// or if running under kubernetes.
572    ///
573    /// The default security context is the string `unconfined`.
574    fn initial_pair_selinux_context(&self,  buffer: &mut[u8]) -> Result<usize, io::Error> 
575    {
576        selinux_context(self, buffer)
577    }
578}
579
580impl UnixDatagramExt for UnixDatagram 
581{
582    fn bind_unix_addr(addr: &UnixSocketAddr) -> Result<Self, io::Error> 
583    {
584        return 
585            UnixDatagram::unbound()
586                .map_or_else(
587                    |e| Err(e), 
588                    |socket|
589                        socket
590                            .bind_to_unix_addr(addr)
591                            .map_or_else(
592                                |e| Err(e), 
593                                |_| Ok(socket)
594                            )
595                );
596    }
597}
598
599#[cfg(feature = "mio")]
600impl UnixDatagramExt for mio::net::UnixDatagram 
601{
602    fn bind_unix_addr(addr: &UnixSocketAddr) -> Result<Self, io::Error> 
603    {
604        return 
605            mio::net::UnixDatagram
606                ::unbound()
607                    .map_or_else(
608                        |e| Err(e), 
609                        |socket|
610                            socket
611                                .bind_to_unix_addr(addr)
612                                .map_or_else(
613                                    |e| Err(e), 
614                                    |_| Ok(socket)
615                                )
616                    );
617    }
618}