Skip to main content

socket9/
address.rs

1/*-
2 * socket9 - A RAW networking sockets manipulation and configration basing on 
3 * strong types.
4 * 
5 * Copyright (C) 2021 Aleksandr Morozov, Lucia Hoffmann
6 * Copyright (C) 2025 Aleksandr Morozov
7 * 
8 * The syslog-rs crate can be redistributed and/or modified
9 * under the terms of either of the following licenses:
10 *
11 *   1. EUROPEAN UNION PUBLIC LICENCE v. 1.2 EUPL © the European Union 2007, 2016 OR
12 *
13 *   2. the Mozilla Public License Version 2.0 (the “MPL”) OR
14 *                     
15 *   3. The MIT License (MIT)
16 */
17
18use std::
19{
20    borrow::Cow, 
21    fmt, 
22    io::{self, ErrorKind}, 
23    mem::{self, MaybeUninit}, 
24    net::{Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6}, 
25    path::{Path, PathBuf}, 
26    ptr
27};
28
29use crate::
30{
31    AF_INET, AF_INET6, AF_UNIX, LocalFrom, So9SockDomain, in_addr, in6_addr, msghdr, sa_family_t, 
32    sockaddr, sockaddr_in, sockaddr_in6, sockaddr_storage, sockaddr_un, socklen_t, UnixSocketAddr
33};
34
35/// A temporary container which is used to combine two different values received
36/// for Ip and Unix address types.
37pub enum RawAddressHolder
38{
39    /// The data was copied to instance.
40    Owned(sockaddr_storage, socklen_t),
41
42    /// A pointer to sockaddr is available.
43    Pointer(*const sockaddr, socklen_t)
44}
45
46#[cfg(unix)]
47impl fmt::Debug for RawAddressHolder
48{
49    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result 
50    {
51        match self {
52            Self::Owned(arg0, arg1) => 
53                f.debug_tuple("Owned").field(arg0).field(arg1).finish(),
54            Self::Pointer(arg0, arg1) => 
55                f.debug_tuple("Pointer").field(arg0).field(arg1).finish(),
56        }
57    }
58}
59
60#[cfg(windows)]
61impl fmt::Debug for RawAddressHolder
62{
63    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result 
64    {
65        match self {
66            Self::Owned(_arg0, arg1) => 
67                f.debug_tuple("Owned").field(arg1).finish(),
68            Self::Pointer(arg0, arg1) => 
69                f.debug_tuple("Pointer").field(arg0).field(arg1).finish(),
70        }
71    }
72}
73
74impl RawAddressHolder
75{
76    pub(crate) 
77    fn get_sockaddr_ptr(&self) -> (*const sockaddr, socklen_t)
78    {
79        match *self
80        {
81            Self::Owned(ref sockaddr, len) => 
82                (sockaddr as *const sockaddr_storage as *const sockaddr, len),
83            Self::Pointer(sockaddr, len) => 
84                (sockaddr, len),
85        }
86    }
87}
88
89/// A trait which is used to convert implemented type into the 
90/// `SAT` generic. For example to convert "192.168.1.1:80" provided as
91/// argument for function into [SocketAddr] or [SocketAddrV4].
92pub trait IntoSockAddrSpec<SAT: Clone>
93{
94    fn from_type(&self) -> io::Result<Cow<'_, SAT>>;
95}
96
97/// Provides an interface for converting the implemeted type into
98/// [RawAddressHolder].
99pub trait So9AddrIntoRaw
100{
101    fn into_raw_addr(&self) -> RawAddressHolder;
102}
103
104/// Provides the interface for the socket `domain` type resolution
105/// depending on the adress which holds the implemented type.
106pub trait So9AddrDomain
107{
108    fn get_addr_domain(&self) -> So9SockDomain;
109}
110
111/// An FFI template and implementation of the [libc::sockaddr_storage] and its size.
112#[derive(Debug)]
113pub struct So9SocketAddr(pub(crate) MaybeUninit<sockaddr_storage>, socklen_t);
114
115impl Default for So9SocketAddr
116{
117    fn default() -> Self 
118    {
119        return Self(MaybeUninit::zeroed(), So9SocketAddr::SO9SOCK_LEN)
120    }
121}
122
123impl So9SocketAddr
124{
125    pub(crate) const SO9SOCK_LEN: socklen_t = size_of::<sockaddr_storage>() as socklen_t;
126
127    #[cfg(unix)]
128    pub(crate) 
129    fn set_length(&mut self, msg: &msghdr)
130    {
131        self.1 = msg.msg_namelen;
132    }
133
134    #[cfg(windows)]
135    pub(crate) 
136    fn set_length(&mut self, msg: &msghdr)
137    {
138        self.1 = msg.cmsg_len as i32;
139    }
140
141    pub(crate) 
142    fn get_sockaddr_ptr(&mut self) -> *mut sockaddr
143    {
144        return self.0.as_mut_ptr() as *mut sockaddr;
145    }
146
147    pub(crate) 
148    fn get_capacity_mut(&mut self) -> &mut socklen_t
149    {
150        return &mut self.1;
151    }
152
153    pub(crate)  
154    fn get_sockaddr_storage_ptr(&mut self) -> *mut sockaddr_storage
155    {
156        return self.0.as_mut_ptr();
157    }
158
159    pub 
160    fn get_sa_fam(&self) -> sa_family_t
161    {
162        return unsafe{ self.0.assume_init_ref() }.ss_family;
163    }
164
165    pub 
166    fn get_len(&self) -> socklen_t
167    {
168        return self.1;
169    }
170}
171
172impl From<UnixSocketAddr> for So9SocketAddr
173{
174    fn from(un: UnixSocketAddr) -> Self 
175    {
176        un.into()
177    }
178}
179
180impl From<&UnixSocketAddr> for So9SocketAddr
181{
182    fn from(un: &UnixSocketAddr) -> Self 
183    {
184        let raw_un = un.into_raw();
185
186        let mut raw_sa = MaybeUninit::<sockaddr_storage>::zeroed();
187
188        let sockaddr_vin = unsafe{ &mut *raw_sa.as_mut_ptr().cast::<sockaddr_un>()}; 
189
190        sockaddr_vin.sun_family = AF_UNIX as sa_family_t;
191        sockaddr_vin.sun_path.copy_from_slice(&raw_un.0.sun_path);
192
193        return Self(raw_sa, raw_un.1);
194    }
195}
196
197impl From<SocketAddrV4> for So9SocketAddr
198{
199    fn from(inp_sa: SocketAddrV4) -> Self 
200    {
201        So9SocketAddr::from(&inp_sa)
202    }
203}
204
205impl From<SocketAddrV6> for So9SocketAddr
206{
207    fn from(inp_sa: SocketAddrV6) -> Self 
208    {
209        So9SocketAddr::from(&inp_sa)
210    }
211}
212
213impl From<SocketAddr> for So9SocketAddr
214{
215    fn from(inp_sa: SocketAddr) -> Self 
216    {
217        So9SocketAddr::from(&inp_sa)
218    }
219}
220
221impl From<&SocketAddr> for So9SocketAddr
222{
223    fn from(inp_sa: &SocketAddr) -> Self 
224    {
225        let res: So9SocketAddr = 
226            match inp_sa
227            {
228                SocketAddr::V4(socket_addr_v4) => 
229                {
230                    socket_addr_v4.into()
231                },
232                SocketAddr::V6(socket_addr_v6) => 
233                {
234                    socket_addr_v6.into()
235                },
236            };
237
238        return res;
239    }
240}
241
242impl From<&SocketAddrV4> for So9SocketAddr
243{
244    fn from(socket_addr_v4: &SocketAddrV4) -> Self 
245    {
246        let mut raw_sa = MaybeUninit::<sockaddr_storage>::zeroed();
247
248        let sockaddr_vin = unsafe{ &mut *raw_sa.as_mut_ptr().cast::<sockaddr_in>()}; 
249        //unsafe { &mut *ptr::addr_of_mut!(raw_sa).cast::<libc::sockaddr_in>() };
250        sockaddr_vin.sin_family = AF_INET as sa_family_t;
251        sockaddr_vin.sin_port = socket_addr_v4.port().to_be();
252        sockaddr_vin.sin_addr = <in_addr as LocalFrom<&Ipv4Addr>>::from(socket_addr_v4.ip());
253    
254        let ss_len = mem::size_of::<sockaddr_in>() as socklen_t;
255
256        #[cfg(any(
257            target_os = "dragonfly",
258            target_os = "freebsd",
259            target_os = "netbsd",
260            target_os = "openbsd",
261            target_os = "ios",
262            target_os = "macos",
263            target_os = "tvos",
264            target_os = "watchos",
265            target_os = "visionos",
266        ))]
267        {
268            raw_sa.ss_len = len as u8;
269        }
270
271        return Self(raw_sa, ss_len);
272    }
273}
274
275impl From<&SocketAddrV6> for So9SocketAddr
276{
277    fn from(socket_addr_v6: &SocketAddrV6) -> Self 
278    {
279        let mut raw_sa = MaybeUninit::<sockaddr_storage>::zeroed();
280
281        let sockaddr_vin = unsafe{ &mut *raw_sa.as_mut_ptr().cast::<sockaddr_in6>()}; 
282        //unsafe { &mut *ptr::addr_of_mut!(raw_sa).cast::<libc::sockaddr_in6>() };
283        sockaddr_vin.sin6_family = AF_INET6 as sa_family_t;
284        sockaddr_vin.sin6_port = socket_addr_v6.port().to_be();
285        sockaddr_vin.sin6_addr = <in6_addr as LocalFrom<&Ipv6Addr>>::from(socket_addr_v6.ip());
286        sockaddr_vin.sin6_flowinfo = socket_addr_v6.flowinfo();
287
288        #[cfg(unix)]
289        {
290            sockaddr_vin.sin6_scope_id = socket_addr_v6.scope_id();
291        }
292        #[cfg(windows)]
293        {
294            use windows_sys::Win32::Networking::WinSock::SOCKADDR_IN6_0;
295
296            sockaddr_vin.Anonymous = 
297                SOCKADDR_IN6_0 
298                {
299                    sin6_scope_id: socket_addr_v6.scope_id(),
300                };
301        }
302        
303        let ss_len = mem::size_of::<sockaddr_in6>() as socklen_t;
304
305        return Self(raw_sa, ss_len);
306    }
307}
308
309impl TryFrom<So9SocketAddr> for UnixSocketAddr
310{
311    type Error = io::Error;
312
313    fn try_from(so9_sa: So9SocketAddr) -> Result<Self, Self::Error> 
314    {
315        unsafe 
316        {
317            UnixSocketAddr::from_sockaddr_storage(so9_sa.0.assume_init_ref(), so9_sa.1)
318        }
319    }
320}
321
322impl TryFrom<So9SocketAddr> for SocketAddrV4
323{
324    type Error = io::Error;
325
326    fn try_from(so9_sa: So9SocketAddr) -> Result<Self, Self::Error> 
327    {
328        let sa = unsafe{ so9_sa.0.assume_init() };
329
330        if sa.ss_family == AF_INET as sa_family_t 
331        {
332            let addr = unsafe{ &*(ptr::addr_of!(sa).cast::<sockaddr_in>()) };
333            let ip = <Ipv4Addr as LocalFrom<in_addr>>::from(addr.sin_addr);
334            let port = u16::from_be(addr.sin_port);
335
336            return Ok(SocketAddrV4::new(ip, port));
337        } 
338
339        return Err(
340            io::Error::new(ErrorKind::InvalidData, 
341                format!("ss_family: {} is not of type SocketAddr", sa.ss_family))
342        );
343    }
344}
345
346impl TryFrom<So9SocketAddr> for SocketAddrV6
347{
348    type Error = io::Error;
349
350    fn try_from(so9_sa: So9SocketAddr) -> Result<Self, Self::Error> 
351    {
352        let sa = unsafe{ so9_sa.0.assume_init() };
353
354        if sa.ss_family == AF_INET6 as sa_family_t 
355        {
356            let addr = unsafe{ &*(ptr::addr_of!(sa).cast::<sockaddr_in6>()) };
357            let ip = <Ipv6Addr as LocalFrom<in6_addr>>::from(addr.sin6_addr);
358            let port = u16::from_be(addr.sin6_port);
359            
360            let res = 
361                SocketAddrV6::new(
362                    ip,
363                    port,
364                    addr.sin6_flowinfo,
365                    #[cfg(unix)]
366                    addr.sin6_scope_id,
367                    #[cfg(windows)]
368                    unsafe 
369                    {
370                        addr.Anonymous.sin6_scope_id
371                    },
372                );
373
374            return Ok(res);
375        } 
376
377        return Err(
378            io::Error::new(ErrorKind::InvalidData, 
379                format!("ss_family: {} is not of type SocketAddr", sa.ss_family))
380        );
381    }
382}
383
384impl TryFrom<So9SocketAddr> for SocketAddr
385{
386    type Error = io::Error;
387
388    fn try_from(so9_sa: So9SocketAddr) -> Result<Self, Self::Error> 
389    {
390        let sa = unsafe{ so9_sa.0.assume_init_ref() };
391
392        if sa.ss_family == AF_INET as sa_family_t 
393        {
394            return SocketAddrV4::try_from(so9_sa).map(|v| SocketAddr::V4(v));
395        } 
396        else if sa.ss_family == AF_INET6 as sa_family_t 
397        {
398            return SocketAddrV6::try_from(so9_sa).map(|v| SocketAddr::V6(v));
399        } 
400        else 
401        {
402            return Err(
403                io::Error::new(ErrorKind::InvalidData, 
404                    format!("ss_family: {} is not of type SocketAddr", sa.ss_family))
405            );
406        }
407    }
408}
409
410impl IntoSockAddrSpec<UnixSocketAddr> for UnixSocketAddr
411{
412    fn from_type(&self) -> io::Result<Cow<'_, UnixSocketAddr>>
413    {
414        Ok(Cow::Borrowed(self))
415    }
416}
417
418impl IntoSockAddrSpec<UnixSocketAddr> for &UnixSocketAddr
419{
420    fn from_type(&self) -> io::Result<Cow<'_, UnixSocketAddr>>
421    {
422        Ok(Cow::Borrowed(self))
423    }
424}
425
426impl IntoSockAddrSpec<SocketAddr> for SocketAddr
427{
428    fn from_type(&self) -> io::Result<Cow<'_, SocketAddr>>
429    {
430        Ok(Cow::Borrowed(self))
431    }
432}
433
434impl IntoSockAddrSpec<SocketAddr> for &SocketAddr
435{
436    fn from_type(&self) -> io::Result<Cow<'_, SocketAddr>>
437    {
438        Ok(Cow::Borrowed(self))
439    }
440}
441
442impl IntoSockAddrSpec<SocketAddr> for SocketAddrV6
443{
444    fn from_type(&self) -> io::Result<Cow<'_, SocketAddr>>
445    {
446        Ok(Cow::Owned(SocketAddr::from((*self).clone())))
447    }
448}
449
450impl IntoSockAddrSpec<SocketAddr> for &SocketAddrV6
451{
452    fn from_type(&self) -> io::Result<Cow<'_, SocketAddr>>
453    {
454        Ok(Cow::Owned(SocketAddr::from((*self).clone())))
455    }
456}
457
458
459
460impl IntoSockAddrSpec<UnixSocketAddr> for &str
461{
462    fn from_type(&self) -> io::Result<Cow<'_, UnixSocketAddr>>
463    {
464        UnixSocketAddr::new(self).map(|v| Cow::Owned(v))
465    }
466}
467
468impl IntoSockAddrSpec<UnixSocketAddr> for &Path
469{
470    fn from_type(&self) -> io::Result<Cow<'_, UnixSocketAddr>>
471    {
472        UnixSocketAddr::from_path(&self).map(|v| Cow::Owned(v))
473    }
474}
475
476impl IntoSockAddrSpec<UnixSocketAddr> for Path
477{
478    fn from_type(&self) -> io::Result<Cow<'_, UnixSocketAddr>>
479    {
480        UnixSocketAddr::from_path(&self).map(|v| Cow::Owned(v))
481    }
482}
483
484impl IntoSockAddrSpec<UnixSocketAddr> for &PathBuf
485{
486    fn from_type(&self) -> io::Result<Cow<'_, UnixSocketAddr>>
487    {
488        UnixSocketAddr::from_path(&self).map(|v| Cow::Owned(v))
489    }
490}
491
492impl IntoSockAddrSpec<UnixSocketAddr> for PathBuf
493{
494    fn from_type(&self) -> io::Result<Cow<'_, UnixSocketAddr>>
495    {
496        UnixSocketAddr::from_path(&self).map(|v| Cow::Owned(v))
497    }
498}
499
500impl IntoSockAddrSpec<SocketAddr> for &str
501{
502    fn from_type(&self) -> io::Result<Cow<'_, SocketAddr>>
503    {
504        return
505            self
506                .parse::<SocketAddr>()
507                .map_err(|e|
508                    io::Error::new(ErrorKind::InvalidInput, e.to_string())
509                )
510                .map(|v| Cow::Owned(v));
511    }
512}
513
514impl IntoSockAddrSpec<SocketAddr> for &SocketAddrV4
515{
516    fn from_type(&self) -> io::Result<Cow<'_, SocketAddr>>
517    {
518        Ok(Cow::Owned(SocketAddr::from((*self).clone())))
519    }
520}
521
522impl IntoSockAddrSpec<SocketAddrV4> for SocketAddrV4
523{
524    fn from_type(&self) -> io::Result<Cow<'_, SocketAddrV4>>
525    {
526        Ok(Cow::Borrowed(self))
527    }
528}
529
530impl IntoSockAddrSpec<SocketAddr> for SocketAddrV4
531{
532    fn from_type(&self) -> io::Result<Cow<'_, SocketAddr>>
533    {
534        Ok(Cow::Owned(SocketAddr::from((*self).clone())))
535    }
536}
537
538impl IntoSockAddrSpec<SocketAddrV4> for &str
539{
540    fn from_type(&self) -> io::Result<Cow<'_, SocketAddrV4>>
541    {
542        return
543            self
544                .parse::<SocketAddrV4>()
545                .map_err(|e|
546                    io::Error::new(ErrorKind::InvalidInput, e.to_string())
547                )
548                .map(|v| Cow::Owned(v));
549    }
550}
551
552impl IntoSockAddrSpec<SocketAddrV6> for &str
553{
554    fn from_type(&self) -> io::Result<Cow<'_, SocketAddrV6>>
555    {
556        return
557            self
558                .parse::<SocketAddrV6>()
559                .map_err(|e|
560                    io::Error::new(ErrorKind::InvalidInput, e.to_string())
561                )
562                .map(|v| Cow::Owned(v));
563    }
564}
565
566
567impl So9AddrIntoRaw for UnixSocketAddr
568{
569    fn into_raw_addr(&self) -> RawAddressHolder
570    {
571        let raw = unsafe { self.as_raw_ptr_general() };
572
573        return RawAddressHolder::Pointer(raw.0, raw.1);
574    }
575}
576
577impl So9AddrIntoRaw for SocketAddr
578{
579    fn into_raw_addr(&self) -> RawAddressHolder
580    {
581        let sa: So9SocketAddr = self.into();
582
583        return RawAddressHolder::Owned( unsafe{ sa.0.assume_init() }, sa.1);
584    }
585}
586
587impl So9AddrIntoRaw for SocketAddrV4
588{
589    fn into_raw_addr(&self) -> RawAddressHolder
590    {
591        let sa: So9SocketAddr = self.into();
592
593        return RawAddressHolder::Owned( unsafe{ sa.0.assume_init() }, sa.1);
594    }
595}
596
597impl So9AddrIntoRaw for SocketAddrV6
598{
599    fn into_raw_addr(&self) -> RawAddressHolder
600    {
601        let sa: So9SocketAddr = self.into();
602
603        return RawAddressHolder::Owned( unsafe{ sa.0.assume_init() }, sa.1);
604    }
605}
606
607impl So9AddrDomain for So9SockDomain
608{
609    fn get_addr_domain(&self) -> So9SockDomain 
610    {
611        return *self;
612    }
613}
614
615impl So9AddrDomain for UnixSocketAddr
616{
617    fn get_addr_domain(&self) -> So9SockDomain 
618    {
619        return So9SockDomain::UNIX;
620    }
621}
622
623impl So9AddrDomain for SocketAddr
624{
625    fn get_addr_domain(&self) -> So9SockDomain 
626    {
627        if self.is_ipv4() == true
628        {
629            return So9SockDomain::IPV4;
630        }
631        else
632        {
633            return So9SockDomain::IPV6;
634        }
635    }
636}
637
638impl So9AddrDomain for SocketAddrV4
639{
640    fn get_addr_domain(&self) -> So9SockDomain 
641    {
642        return So9SockDomain::IPV4;
643    }
644}
645
646impl So9AddrDomain for SocketAddrV6
647{
648    fn get_addr_domain(&self) -> So9SockDomain 
649    {
650        return So9SockDomain::IPV6;
651    }
652}
653
654/// A possible `inet` types for the socket `domain` which is working with
655/// `IP/IPv6`.
656#[repr(i32)]
657#[derive(Debug, Clone, Copy, PartialEq, Eq)]
658pub enum So9DomainInets
659{
660    Inet = So9SockDomain::IPV4.0 as i32,
661    Inet6 = So9SockDomain::IPV6.0 as i32,
662}
663
664#[cfg(target_family = "unix")]
665impl So9AddrDomain for So9DomainInets
666{
667    fn get_addr_domain(&self) -> So9SockDomain 
668    {
669        return So9SockDomain(*self as i32);
670    }
671}
672
673#[cfg(target_family = "windows")]
674impl So9AddrDomain for So9DomainInets
675{
676    fn get_addr_domain(&self) -> So9SockDomain 
677    {
678        return So9SockDomain(*self as u16);
679    }
680}
681
682/// A possible `unix` types for the socket `domain` which is working with 
683/// `unix sockets`.
684#[repr(i32)]
685#[derive(Debug, Clone, Copy, PartialEq, Eq)]
686pub enum So9DomainUnix
687{
688    Unix = So9SockDomain::UNIX.0 as i32,
689}
690
691#[cfg(target_family = "unix")]
692impl So9AddrDomain for So9DomainUnix
693{
694    fn get_addr_domain(&self) -> So9SockDomain 
695    {
696        return So9SockDomain(*self as i32);
697    }
698}
699
700#[cfg(target_family = "windows")]
701impl So9AddrDomain for So9DomainUnix
702{
703    fn get_addr_domain(&self) -> So9SockDomain 
704    {
705        return So9SockDomain(*self as u16);
706    }
707}
708
709
710
711#[cfg(test)]
712mod test_addr_int
713{
714    use super::*;
715
716    #[test]
717    fn test_addr_1()
718    {
719        let ipv4: SocketAddrV4 = "127.0.0.1:80".parse().unwrap();
720
721        let RawAddressHolder::Owned(s9_raw, s9_sz) = ipv4.into_raw_addr()
722            else { panic!("expected RawAddressHolder::Owned") };
723
724        let mut sa9 = So9SocketAddr::from(&ipv4);
725
726        assert_eq!(sa9.get_sa_fam(), s9_raw.ss_family);
727        assert_eq!(*sa9.get_capacity_mut(), s9_sz);
728        
729        let s9_raw_ptr = &s9_raw as *const sockaddr_storage as *const u8;
730        let sa9_ptr = sa9.get_sockaddr_storage_ptr() as *const u8;
731
732        for _ in 0..s9_sz
733        {
734            unsafe 
735            {
736                if s9_raw_ptr.as_ref().unwrap() != sa9_ptr.as_ref().unwrap()
737                {
738                    panic!("does not match");
739                }
740            }
741        }
742
743        let ipv4_back: SocketAddrV4 = sa9.try_into().unwrap();
744
745        assert_eq!(ipv4_back, ipv4);
746    }
747
748     #[test]
749    fn test_addr_2()
750    {
751        let ipv6: SocketAddrV6 = "[a20c:828f:aae4:ee01:0983:3506:2f58:5a64]:80".parse().unwrap();
752
753        let RawAddressHolder::Owned(s9_raw, s9_sz) = ipv6.into_raw_addr()
754            else { panic!("expected RawAddressHolder::Owned") };
755
756        let mut sa9 = So9SocketAddr::from(&ipv6);
757
758        assert_eq!(sa9.get_sa_fam(), s9_raw.ss_family);
759        assert_eq!(*sa9.get_capacity_mut(), s9_sz);
760        
761        let s9_raw_ptr = &s9_raw as *const sockaddr_storage as *const u8;
762        let sa9_ptr = sa9.get_sockaddr_storage_ptr() as *const u8;
763
764        for _ in 0..s9_sz
765        {
766            unsafe 
767            {
768                if s9_raw_ptr.as_ref().unwrap() != sa9_ptr.as_ref().unwrap()
769                {
770                    panic!("does not match");
771                }
772            }
773        }
774
775        let ipv6_back: SocketAddrV6 = sa9.try_into().unwrap();
776
777        assert_eq!(ipv6_back, ipv6);
778    }
779
780    #[test]
781    fn test_addr_4()
782    {
783        let ipv4: SocketAddr = "127.0.0.1:80".parse().unwrap();
784
785        let RawAddressHolder::Owned(s9_raw, s9_sz) = ipv4.into_raw_addr()
786            else { panic!("expected RawAddressHolder::Owned") };
787
788        let mut sa9 = So9SocketAddr::from(&ipv4);
789
790        assert_eq!(sa9.get_sa_fam(), s9_raw.ss_family);
791        assert_eq!(*sa9.get_capacity_mut(), s9_sz);
792        
793        let s9_raw_ptr = &s9_raw as *const sockaddr_storage as *const u8;
794        let sa9_ptr = sa9.get_sockaddr_storage_ptr() as *const u8;
795
796        for _ in 0..s9_sz
797        {
798            unsafe 
799            {
800                if s9_raw_ptr.as_ref().unwrap() != sa9_ptr.as_ref().unwrap()
801                {
802                    panic!("does not match");
803                }
804            }
805        }
806
807    }
808
809    #[test]
810    fn test_addr_5()
811    {
812        let unix_addr: UnixSocketAddr = UnixSocketAddr::from_path("/tmp/sock.sock").unwrap();
813
814        let RawAddressHolder::Pointer(s9_raw, s9_sz) = unix_addr.into_raw_addr()
815            else { panic!("expected RawAddressHolder::Owned") };
816
817        let mut sa9 = So9SocketAddr::from(&unix_addr);
818
819        assert_eq!(sa9.get_sa_fam(), unsafe { s9_raw.as_ref().unwrap() }.sa_family);
820        assert_eq!(*sa9.get_capacity_mut(), s9_sz);
821        
822        let s9_raw_ptr = s9_raw  as *const u8;
823        let sa9_ptr = sa9.get_sockaddr_storage_ptr() as *const u8;
824
825        for _ in 0..s9_sz
826        {
827            unsafe 
828            {
829                if s9_raw_ptr.as_ref().unwrap() != sa9_ptr.as_ref().unwrap()
830                {
831                    panic!("does not match");
832                }
833            }
834        }
835
836    }
837}