linux_io/socket/
ip.rs

1/// Socket address type for the IPv4 protocol family.
2#[derive(Clone, Copy, Debug)]
3#[repr(C, align(8))]
4pub struct SockAddrIpv4 {
5    sin_family: linux_unsafe::sa_family_t,
6    sin_port: u16, // (but in network byte order)
7    sin_addr: Ipv4Addr,
8
9    // The kernel expects sockaddr_in to be 16 bytes long, even though
10    // only the first eight bytes are actually useful. We always set these
11    // padding bytes to zero.
12    sin_zero: [u8; 8],
13}
14
15impl SockAddrIpv4 {
16    /// Create a new [`SockAddrIpv4`] with the specified IP address and port
17    /// number.
18    ///
19    /// Port number should be provided in the host's native byte order. This
20    /// function will convert it to network byte order where necessary.
21    #[inline]
22    pub const fn new(host_addr: Ipv4Addr, port: u16) -> Self {
23        Self {
24            sin_family: AF_INET,
25            sin_port: port.to_be(),
26            sin_addr: host_addr,
27            sin_zero: [0; 8],
28        }
29    }
30
31    /// Returns the host address part of the socket address.
32    #[inline(always)]
33    pub const fn host_address(&self) -> Ipv4Addr {
34        self.sin_addr
35    }
36
37    /// Returns the port number in host (_not_ network) byte order.
38    #[inline(always)]
39    pub const fn port(&self) -> u16 {
40        self.sin_port.to_be() // Swaps the bytes if we're running on a little-endian system
41    }
42}
43
44/// Representation of an IPv4 host address.
45///
46/// Note that this isn't an IPv4 _socket address_ type; use [`SockAddrIpv4`]
47/// to represent both the host address and port number for an IPv4 socket.
48#[derive(Clone, Copy, Debug)]
49#[repr(C)]
50pub struct Ipv4Addr {
51    s_addr: u32, // (but in network byte order)
52}
53
54impl Ipv4Addr {
55    /// Equivalent to the constant `INADDR_ANY` in C.
56    pub const ANY: Self = Self { s_addr: 0x00000000 };
57
58    /// Equivalent to the constant `INADDR_NONE` in C.
59    pub const NONE: Self = Self { s_addr: 0xffffffff };
60
61    /// Equivalent to the constant `INADDR_BROADCAST` in C.
62    pub const BROADCAST: Self = Self { s_addr: 0xffffffff };
63
64    /// Equivalent to the constant `INADDR_DUMMY` in C.
65    pub const DUMMY: Self = Self {
66        s_addr: 0xc0000008_u32.to_be(),
67    };
68
69    /// Equivalent to the constant `INADDR_LOOPBACK` in C.
70    pub const LOOPBACK: Self = Self {
71        s_addr: 0x7f000001_u32.to_be(),
72    };
73
74    /// Equivalent to the constant `INADDR_UNSPEC_GROUP` in C.
75    pub const UNSPEC_GROUP: Self = Self {
76        s_addr: 0xe0000000_u32.to_be(),
77    };
78    /// Equivalent to the constant `INADDR_ALLHOSTS_GROUP` in C.
79    pub const ALLHOSTS_GROUP: Self = Self {
80        s_addr: 0xe0000001_u32.to_be(),
81    };
82    /// Equivalent to the constant `INADDR_ALLRTRS_GROUP` in C.
83    pub const ALLRTRS_GROUP: Self = Self {
84        s_addr: 0xe0000002_u32.to_be(),
85    };
86    /// Equivalent to the constant `INADDR_ALLSNOOPERS_GROUP` in C.
87    pub const ALLSNOOPERS_GROUP: Self = Self {
88        s_addr: 0xe000006a_u32.to_be(),
89    };
90
91    /// Constructs an [`Ipv4Addr`] directly from a u32 value written in the
92    /// host byte order.
93    ///
94    /// For example, the standard loopback address `127.0.0.1` should be
95    /// provided as `0x7f000001` on all platforms, which would be encoded as
96    /// `[0x01, 0x00, 0x00, 0x7f]` on a little-endian system but this
97    /// function will then convert it to network byte order automatically.
98    #[inline(always)]
99    pub const fn from_u32(raw: u32) -> Self {
100        Self {
101            s_addr: raw.to_be(),
102        }
103    }
104
105    /// Constructs an [`Ipv4Addr`] from the given octets which are interpreted
106    /// in network byte order, meaning that the first element corresponds with
107    /// the first decimal digit in the conventional four-segment dotted decimal
108    /// IP address representation.
109    #[inline(always)]
110    pub const fn from_octets(raw: [u8; 4]) -> Self {
111        // Note: we're first interpreting raw into the _host_ byte order, and
112        // then from_u32 will reinterpret that into the network byte order.
113        Self::from_u32(u32::from_be_bytes(raw))
114    }
115
116    /// Returns the raw u32 value of the address in host (_not_ network) byte order.
117    #[inline(always)]
118    pub const fn as_u32(&self) -> u32 {
119        self.s_addr.to_be() // undoes the to_be we did on construction if we're on a little-endian system
120    }
121
122    /// Returns the raw octets of the address in network byte order.
123    #[inline(always)]
124    pub const fn as_octets(&self) -> [u8; 4] {
125        self.as_u32().to_be_bytes()
126    }
127
128    /// Returns the same IP address in the "IPv6 mapped" form.
129    pub const fn to_ipv6_mapped(&self) -> Ipv6Addr {
130        let our_octets = self.as_octets();
131        let mut new_octets = [0_u8; 16];
132        new_octets[10] = 0xff;
133        new_octets[11] = 0xff;
134        new_octets[12] = our_octets[0];
135        new_octets[13] = our_octets[1];
136        new_octets[14] = our_octets[2];
137        new_octets[15] = our_octets[3];
138        Ipv6Addr::from_octets(new_octets)
139    }
140}
141
142/// Socket address type for the IPv6 protocol family.
143#[derive(Clone, Copy, Debug)]
144#[repr(C, align(8))]
145pub struct SockAddrIpv6 {
146    sin6_family: linux_unsafe::sa_family_t,
147    sin6_port: u16, // (but in network byte order)
148    sin6_flowinfo: u32,
149    sin6_addr: Ipv6Addr,
150    sin6_scope_id: u32,
151}
152
153impl SockAddrIpv6 {
154    /// Create a new [`SockAddrIpv6`] with the specified IP address and port
155    /// number.
156    ///
157    /// Port number should be provided in the host's native byte order. This
158    /// function will convert it to network byte order where necessary.
159    #[inline]
160    pub const fn new(host_addr: Ipv6Addr, port: u16) -> Self {
161        Self {
162            sin6_family: AF_INET6,
163            sin6_port: port.to_be(),
164            sin6_addr: host_addr,
165
166            sin6_flowinfo: 0,
167            sin6_scope_id: 0,
168        }
169    }
170
171    /// Create a new [`SockAddrIpv6`] with the specified IP address, port
172    /// number, and scope id.
173    ///
174    /// Port number should be provided in the host's native byte order. This
175    /// function will convert it to network byte order where necessary.
176    #[inline]
177    pub const fn new_with_scope(host_addr: Ipv6Addr, port: u16, scope_id: u32) -> Self {
178        Self {
179            sin6_family: AF_INET6,
180            sin6_port: port.to_be(),
181            sin6_addr: host_addr,
182
183            sin6_flowinfo: 0,
184            sin6_scope_id: scope_id,
185        }
186    }
187
188    /// Returns the host address part of the socket address.
189    #[inline(always)]
190    pub const fn host_address(&self) -> Ipv6Addr {
191        self.sin6_addr
192    }
193
194    /// Returns the port number in host (_not_ network) byte order.
195    #[inline(always)]
196    pub const fn port(&self) -> u16 {
197        self.sin6_port.to_be() // Swaps the bytes if we're running on a little-endian system
198    }
199
200    /// Returns the scope ID of the address.
201    #[inline(always)]
202    pub const fn scope_id(&self) -> u32 {
203        self.sin6_scope_id
204    }
205}
206
207/// Representation of an IPv6 host address.
208///
209/// Note that this isn't an IPv6 _socket address_ type; use [`SockAddrIpv6`]
210/// to represent both the host address and port number for an IPv4 socket.
211#[derive(Clone, Copy, Debug)]
212#[repr(C)]
213pub struct Ipv6Addr {
214    s6_addr: [u8; 16],
215}
216
217impl Ipv6Addr {
218    /// Equivalent to the constant `IN6ADDR_ANY_INIT` in C.
219    pub const ANY: Self = Self {
220        s6_addr: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
221    };
222
223    /// Equivalent to the constant `IN6ADDR_LOOPBACK_INIT` in C.
224    pub const LOOPBACK: Self = Self {
225        s6_addr: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
226    };
227
228    /// Equivalent to the constant `IN6ADDR_LINKLOCAL_ALLNODES_INIT` in C.
229    pub const LINKLOCAL_ALLNODES: Self = Self {
230        s6_addr: [0xff, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
231    };
232
233    /// Equivalent to the constant `IN6ADDR_LINKLOCAL_ALLROUTERS_INIT` in C.
234    pub const LINKLOCAL_ALLROUTERS: Self = Self {
235        s6_addr: [0xff, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2],
236    };
237
238    /// Equivalent to the constant `IN6ADDR_INTERFACELOCAL_ALLNODES_INIT` in C.
239    pub const INTERFACELOCAL_ALLNODES: Self = Self {
240        s6_addr: [0xff, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
241    };
242
243    /// Equivalent to the constant `IN6ADDR_INTERFACELOCAL_ALLROUTERS_INIT` in C.
244    pub const INTERFACELOCAL_ALLROUTERS: Self = Self {
245        s6_addr: [0xff, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2],
246    };
247
248    /// Equivalent to the constant `IN6ADDR_SITELOCAL_ALLROUTERS_INIT` in C.
249    pub const SITELOCAL_ALLROUTERS: Self = Self {
250        s6_addr: [0xff, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2],
251    };
252
253    /// Constructs an [`Ipv6Addr`] from the given octets which are interpreted
254    /// in network byte order, meaning that the first element corresponds with
255    /// the first decimal digit in the conventional four-segment dotted decimal
256    /// IP address representation.
257    #[inline(always)]
258    pub const fn from_octets(raw: [u8; 16]) -> Self {
259        // Note: we're first interpreting raw into the _host_ byte order, and
260        // then from_u32 will reinterpret that into the network byte order.
261        Self { s6_addr: raw }
262    }
263
264    /// Returns the raw octets of the address in network byte order.
265    #[inline(always)]
266    pub const fn as_octets(&self) -> [u8; 16] {
267        self.s6_addr
268    }
269}
270
271/// Represents a socket address that can be for either an IPv4 socket or an
272/// IPv6 socket, chosen dynamically at runtime.
273#[derive(Clone, Copy)]
274#[repr(transparent)]
275pub struct SockAddrIp(SockAddrIpInner);
276
277#[derive(Clone, Copy)]
278#[repr(C, align(8))]
279union SockAddrIpInner {
280    // A struct that covers only the "family" field that both real address
281    // types have in common. We use this only to retrieve the tag before
282    // deciding which of the other two fields is the active one.
283    jt: SockAddrJustTag,
284
285    // Every `SockAddrIpInner` has one of these, with the "family" field
286    // of both serving as the discriminator.
287    v4: SockAddrIpv4,
288    v6: SockAddrIpv6,
289}
290
291#[derive(Clone, Copy, Debug)]
292#[repr(C, align(8))]
293struct SockAddrJustTag {
294    family: linux_unsafe::sa_family_t,
295}
296
297impl SockAddrIp {
298    pub fn new(host_address: impl Into<IpAddr>, port: u16) -> Self {
299        let host_address = host_address.into();
300        match host_address {
301            IpAddr::V4(addr) => Self(SockAddrIpInner {
302                v4: SockAddrIpv4::new(addr, port),
303            }),
304            IpAddr::V6(addr) => Self(SockAddrIpInner {
305                v6: SockAddrIpv6::new(addr, port),
306            }),
307        }
308    }
309
310    /// Get the address family that this address is for.
311    ///
312    /// The result is either [`AF_INET`] or [`AF_INET6`].
313    pub const fn address_family(&self) -> linux_unsafe::sa_family_t {
314        // Safe because `new` populates either v4 or v6, both of which
315        // have the family field as the first field with compatible
316        // storage and both always initialize it to the appropriate constant.
317        unsafe { self.0.jt.family }
318    }
319
320    /// Get the IP address associated with the socket address.
321    ///
322    /// The result can be either an IPv4 or IPv6 address depending on the
323    /// address family of the socket address.
324    pub const fn host_address(&self) -> IpAddr {
325        match self.address_family() {
326            AF_INET => IpAddr::V4(unsafe { self.0.v4 }.host_address()),
327            AF_INET6 => IpAddr::V6(unsafe { self.0.v6 }.host_address()),
328            _ => unreachable!(),
329        }
330    }
331
332    /// Returns the port number in host (_not_ network) byte order.
333    #[inline(always)]
334    pub const fn port(&self) -> u16 {
335        match self.address_family() {
336            AF_INET => unsafe { self.0.v4 }.port(),
337            AF_INET6 => unsafe { self.0.v6 }.port(),
338            _ => unreachable!(),
339        }
340    }
341}
342
343impl core::fmt::Debug for SockAddrIp {
344    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
345        match self.address_family() {
346            AF_INET => unsafe { self.0.v4 }.fmt(f),
347            AF_INET6 => unsafe { self.0.v6 }.fmt(f),
348            _ => unreachable!(),
349        }
350    }
351}
352
353/// Represents a host address that can be either an IPv4 address or an IPv6
354/// address chosen dynamically at runtime.
355#[derive(Clone, Copy, Debug)]
356pub enum IpAddr {
357    V4(Ipv4Addr),
358    V6(Ipv6Addr),
359}
360
361impl IpAddr {
362    /// Returns the equivalent IPv6 address, either directly (when the source
363    /// is already IPv6) or as an IPv4-mapped-in-IPv6 address.
364    ///
365    /// The Linux IPv6 implementation can support IPv4 too when using a
366    /// mapped address, so using this method can allow the rest of the program
367    /// to use `AF_INET6` exclusively, if desired.
368    pub const fn to_ipv6_mapped(self) -> Ipv6Addr {
369        match self {
370            IpAddr::V4(addr) => addr.to_ipv6_mapped(),
371            IpAddr::V6(addr) => addr,
372        }
373    }
374}
375
376/// Represents the IPv4 address family.
377pub const AF_INET: linux_unsafe::sa_family_t = 2;
378
379/// Represents the IPv6 address family.
380pub const AF_INET6: linux_unsafe::sa_family_t = 10;
381
382pub const IPPROTO_TCP: super::SocketProtocolFixed<tcp::TcpSocketDevice> =
383    unsafe { super::socket_protocol(6) };
384
385pub const IPPROTO_ICMP: linux_unsafe::int = 1;
386pub const IPPROTO_IGMP: linux_unsafe::int = 4;
387pub const IPPROTO_EGP: linux_unsafe::int = 8;
388pub const IPPROTO_PUP: linux_unsafe::int = 12;
389pub const IPPROTO_UDP: linux_unsafe::int = 17;
390pub const IPPROTO_IDP: linux_unsafe::int = 22;
391pub const IPPROTO_TP: linux_unsafe::int = 29;
392pub const IPPROTO_DCCP: linux_unsafe::int = 33;
393pub const IPPROTO_IPV6: linux_unsafe::int = 41;
394pub const IPPROTO_RSVP: linux_unsafe::int = 46;
395pub const IPPROTO_GRE: linux_unsafe::int = 47;
396pub const IPPROTO_ESP: linux_unsafe::int = 50;
397pub const IPPROTO_AH: linux_unsafe::int = 51;
398pub const IPPROTO_MTP: linux_unsafe::int = 92;
399pub const IPPROTO_ENCAP: linux_unsafe::int = 98;
400pub const IPPROTO_PIM: linux_unsafe::int = 103;
401pub const IPPROTO_COMP: linux_unsafe::int = 108;
402pub const IPPROTO_L2TP: linux_unsafe::int = 115;
403pub const IPPROTO_SCTP: linux_unsafe::int = 132;
404pub const IPPROTO_UDPLITE: linux_unsafe::int = 136;
405pub const IPPROTO_MPLS: linux_unsafe::int = 137;
406pub const IPPROTO_ETHERNET: linux_unsafe::int = 143;
407pub const IPPROTO_RAW: linux_unsafe::int = 255;
408pub const IPPROTO_MPTCP: linux_unsafe::int = 262;
409
410unsafe impl super::SockAddr for SockAddrIpv4 {
411    #[inline(always)]
412    unsafe fn sockaddr_raw_const(
413        &self,
414    ) -> (*const linux_unsafe::sockaddr, linux_unsafe::socklen_t) {
415        (
416            self as *const Self as *const _,
417            core::mem::size_of::<Self>() as linux_unsafe::socklen_t,
418        )
419    }
420
421    #[inline(always)]
422    unsafe fn sockaddr_raw_mut(
423        &mut self,
424    ) -> (*mut linux_unsafe::sockaddr, linux_unsafe::socklen_t) {
425        (
426            self as *mut Self as *mut _,
427            core::mem::size_of::<Self>() as linux_unsafe::socklen_t,
428        )
429    }
430}
431
432unsafe impl super::SockAddr for SockAddrIpv6 {
433    #[inline(always)]
434    unsafe fn sockaddr_raw_const(
435        &self,
436    ) -> (*const linux_unsafe::sockaddr, linux_unsafe::socklen_t) {
437        (
438            self as *const Self as *const _,
439            core::mem::size_of::<Self>() as linux_unsafe::socklen_t,
440        )
441    }
442
443    #[inline(always)]
444    unsafe fn sockaddr_raw_mut(
445        &mut self,
446    ) -> (*mut linux_unsafe::sockaddr, linux_unsafe::socklen_t) {
447        (
448            self as *mut Self as *mut _,
449            core::mem::size_of::<Self>() as linux_unsafe::socklen_t,
450        )
451    }
452}
453
454unsafe impl super::SockAddr for SockAddrIp {
455    #[inline(always)]
456    unsafe fn sockaddr_raw_const(
457        &self,
458    ) -> (*const linux_unsafe::sockaddr, linux_unsafe::socklen_t) {
459        // Our inner is a union over the possible address types, and we can use
460        // the required "family" field as the tag for our union without needing
461        // any additional storage.
462        match self.address_family() {
463            AF_INET => self.0.v4.sockaddr_raw_const(),
464            AF_INET6 => self.0.v6.sockaddr_raw_const(),
465            _ => unreachable!(), // af field is not publicly exposed so cannot have any other value
466        }
467    }
468
469    #[inline(always)]
470    unsafe fn sockaddr_raw_mut(
471        &mut self,
472    ) -> (*mut linux_unsafe::sockaddr, linux_unsafe::socklen_t) {
473        // Our inner is a union over the possible address types, and we can use
474        // the required "family" field as the tag for our union without needing
475        // any additional storage.
476        match self.address_family() {
477            AF_INET => self.0.v4.sockaddr_raw_mut(),
478            AF_INET6 => self.0.v6.sockaddr_raw_mut(),
479            _ => unreachable!(), // af field is not publicly exposed so cannot have any other value
480        }
481    }
482}
483
484impl From<Ipv4Addr> for IpAddr {
485    fn from(value: Ipv4Addr) -> Self {
486        IpAddr::V4(value)
487    }
488}
489
490impl From<Ipv6Addr> for IpAddr {
491    fn from(value: Ipv6Addr) -> Self {
492        IpAddr::V6(value)
493    }
494}
495
496#[cfg(feature = "std")]
497extern crate std;
498
499/// Additional functions available when the `std` feature is active, for
500/// integrating with the standard library.
501#[cfg(feature = "std")]
502impl Ipv4Addr {
503    /// Converts the standard library's representation of IPv4 addresses into
504    /// our representation.
505    #[inline]
506    pub const fn from_std(addr: std::net::Ipv4Addr) -> Self {
507        Self::from_octets(addr.octets())
508    }
509}
510
511#[cfg(feature = "std")]
512impl From<std::net::Ipv4Addr> for Ipv4Addr {
513    fn from(value: std::net::Ipv4Addr) -> Self {
514        Self::from_std(value)
515    }
516}
517
518/// Additional functions available when the `std` feature is active, for
519/// integrating with the standard library.
520#[cfg(feature = "std")]
521impl Ipv6Addr {
522    /// Converts the standard library's representation of IPv4 addresses into
523    /// our representation.
524    #[inline]
525    pub const fn from_std(addr: std::net::Ipv6Addr) -> Self {
526        Self::from_octets(addr.octets())
527    }
528}
529
530#[cfg(feature = "std")]
531impl From<std::net::Ipv6Addr> for Ipv6Addr {
532    fn from(value: std::net::Ipv6Addr) -> Self {
533        Self::from_std(value)
534    }
535}
536
537/// Additional functions available when the `std` feature is active, for
538/// integrating with the standard library.
539#[cfg(feature = "std")]
540impl IpAddr {
541    /// Converts the standard library's representation of IPv4 addresses into
542    /// our representation.
543    #[inline]
544    pub const fn from_std(addr: std::net::IpAddr) -> Self {
545        match addr {
546            std::net::IpAddr::V4(addr) => Self::V4(Ipv4Addr::from_octets(addr.octets())),
547            std::net::IpAddr::V6(addr) => Self::V6(Ipv6Addr::from_octets(addr.octets())),
548        }
549    }
550}
551
552#[cfg(feature = "std")]
553impl From<std::net::IpAddr> for IpAddr {
554    fn from(value: std::net::IpAddr) -> Self {
555        Self::from_std(value)
556    }
557}
558
559/// Device type marker for [`crate::File`] instances that represent IPv4 sockets.
560#[derive(Clone, Copy)]
561pub struct Ipv4SocketDevice;
562
563impl crate::fd::ioctl::IoDevice for Ipv4SocketDevice {}
564unsafe impl crate::fd::ioctl::SubDevice<super::SocketDevice> for Ipv4SocketDevice {}
565
566/// Device type marker for [`crate::File`] instances that represent IPv4 sockets.
567#[derive(Clone, Copy)]
568pub struct Ipv6SocketDevice;
569
570impl crate::fd::ioctl::IoDevice for Ipv6SocketDevice {}
571unsafe impl crate::fd::ioctl::SubDevice<super::SocketDevice> for Ipv6SocketDevice {}
572
573/// Extra types and constants for working with TCP sockets.
574pub mod tcp;