1extern crate libc;
145
146use std::convert::TryInto;
147use std::net::{Ipv4Addr,Ipv6Addr,SocketAddr,SocketAddrV4,SocketAddrV6};
148use std::str::FromStr;
149
150#[cfg(not(target_os = "windows"))]
151use libc::{sockaddr, sockaddr_in, sockaddr_in6, AF_INET, AF_INET6};
152
153#[cfg(target_os = "windows")]
154use winapi::shared::{
155 ws2def::{AF_INET, AF_INET6, SOCKADDR as sockaddr, SOCKADDR_IN as sockaddr_in},
156 ws2ipdef::SOCKADDR_IN6_LH as sockaddr_in6,
157};
158
159#[derive(Copy, Clone)]
174#[repr(C)]
175pub union OsSocketAddr {
176 sa4: sockaddr_in,
177 sa6: sockaddr_in6,
178}
179
180
181#[cfg(not(target_os = "windows"))]
185pub use libc::socklen_t;
186#[cfg(target_os = "windows")]
191pub use winapi::um::ws2tcpip::socklen_t;
192
193
194#[allow(dead_code)]
195impl OsSocketAddr {
196 pub fn new() -> Self {
198 OsSocketAddr {
199 sa6: unsafe { std::mem::zeroed() },
200 }
201 }
202
203 pub unsafe fn copy_from_raw(ptr: *const sockaddr, len: socklen_t) -> Self {
216 let mut addr = OsSocketAddr::new();
217 if !ptr.is_null() {
218 let src = std::slice::from_raw_parts(ptr as *const u8, len as usize);
219 let dst = addr.as_mut();
220 let nb = src.len().min(dst.len());
221 dst[..nb].copy_from_slice(&src[..nb]);
222 }
223 addr
224 }
225
226 #[deprecated(since="0.2.4", note="use copy_from_raw()")]
228 pub unsafe fn from_raw_parts(ptr: *const u8, len: usize) -> Self {
229 Self::copy_from_raw(ptr as *const sockaddr, len as socklen_t)
230 }
231
232
233 pub unsafe fn copy_to_raw(&self, ptr: *mut sockaddr, len: *mut socklen_t) -> Result<(), BadFamilyError>
248 {
249 if !ptr.is_null() {
250 let src = self.as_ref();
251 let dst = std::slice::from_raw_parts_mut(ptr as *mut u8, *len as usize);
252 if src.len() == 0 {
253 *len = 0;
254 return Err(BadFamilyError(self.sa4.sin_family as i32))
255 }
256 let nb = src.len().min(dst.len());
257 dst[..nb].copy_from_slice(&src[..nb]);
258 *len = src.len() as socklen_t
259 }
260 Ok(())
261 }
262
263 pub fn from(addr: SocketAddr) -> Self {
265 addr.into()
266 }
267
268 pub fn into_addr(self) -> Option<SocketAddr> {
276 self.into()
277 }
278
279 pub fn len(&self) -> socklen_t {
286 (match unsafe { self.sa6.sin6_family } as i32 {
287 AF_INET => std::mem::size_of::<sockaddr_in>(),
288 AF_INET6 => std::mem::size_of::<sockaddr_in6>(),
289 _ => 0,
290 }) as socklen_t
291 }
292
293 pub fn capacity(&self) -> socklen_t {
295 std::mem::size_of::<sockaddr_in6>() as socklen_t
296 }
297
298 pub fn as_ptr(&self) -> *const sockaddr {
300 unsafe { &self.sa6 as *const _ as *const _ }
301 }
302
303 pub fn as_mut_ptr(&mut self) -> *mut sockaddr {
305 unsafe { &mut self.sa6 as *mut _ as *mut _ }
306 }
307}
308
309impl AsRef<[u8]> for OsSocketAddr {
310 fn as_ref(&self) -> &[u8] {
316 unsafe {
317 std::slice::from_raw_parts(&self.sa6 as *const _ as *const u8, self.len() as usize)
318 }
319 }
320}
321
322impl AsMut<[u8]> for OsSocketAddr {
323 fn as_mut(&mut self) -> &mut [u8] {
325 unsafe {
326 std::slice::from_raw_parts_mut(
327 &mut self.sa6 as *mut _ as *mut u8,
328 self.capacity() as usize,
329 )
330 }
331 }
332}
333
334impl Into<Option<SocketAddr>> for OsSocketAddr {
335 fn into(self) -> Option<SocketAddr> {
343 self.try_into().ok()
344 }
345}
346
347impl TryInto<SocketAddr> for OsSocketAddr {
348 type Error = BadFamilyError;
349
350 fn try_into(self) -> Result<SocketAddr, BadFamilyError> {
358 unsafe {
359 match self.sa6.sin6_family as i32 {
360 AF_INET => {
361 #[cfg(not(target_os = "windows"))]
362 let ip = self.sa4.sin_addr.s_addr;
363 #[cfg(target_os = "windows")]
364 let ip = *self.sa4.sin_addr.S_un.S_addr();
365
366 Ok(SocketAddr::V4(SocketAddrV4::new(
367 Ipv4Addr::from(u32::from_be(ip)),
368 u16::from_be(self.sa4.sin_port),
369 )))
370 },
371 AF_INET6 => {
372 #[cfg(not(target_os = "windows"))]
373 let (ip, scope_id) = (self.sa6.sin6_addr.s6_addr, self.sa6.sin6_scope_id);
374 #[cfg(target_os = "windows")]
375 let (ip, scope_id) = (*self.sa6.sin6_addr.u.Byte(), *self.sa6.u.sin6_scope_id());
376
377 Ok(SocketAddr::V6(SocketAddrV6::new(
378 Ipv6Addr::from(u128::from_be_bytes(ip)),
379 u16::from_be(self.sa6.sin6_port),
380 self.sa6.sin6_flowinfo,
381 scope_id)))
382 },
383 f => Err(BadFamilyError(f)),
384 }
385 }
386 }
387}
388
389#[derive(Debug,Eq,PartialEq)]
391pub struct BadFamilyError(i32);
392impl std::error::Error for BadFamilyError {}
393impl std::fmt::Display for BadFamilyError {
394 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result
395 {
396 "not an ip address (family=".fmt(f)?;
397 self.0.fmt(f)?;
398 ')'.fmt(f)
399 }
400}
401
402impl From<SocketAddr> for OsSocketAddr {
403 fn from(addr: SocketAddr) -> Self {
404 let mut result : Self = unsafe { std::mem::zeroed() };
405 match addr {
406 SocketAddr::V4(addr) => {
407 let sa4 = unsafe { &mut result.sa4 };
408
409 #[cfg(any(
410 target_os = "dragonfly",
411 target_os = "freebsd",
412 target_os = "haiku",
413 target_os = "hermit",
414 target_os = "ios",
415 target_os = "macos",
416 target_os = "netbsd",
417 target_os = "openbsd",
418 target_os = "vxworks",
419 target_os = "watchos",
420 ))]
421 {
422 sa4.sin_len = std::mem::size_of::<sockaddr_in>() as u8;
423 }
424
425 sa4.sin_family = AF_INET.try_into().unwrap();
426 sa4.sin_port = u16::to_be(addr.port());
427
428 let raw_ip = u32::to_be((*addr.ip()).into());
429 #[cfg(not(target_os = "windows"))]
430 {
431 sa4.sin_addr.s_addr = raw_ip;
432 }
433 #[cfg(target_os = "windows")]
434 unsafe {
435 *sa4.sin_addr.S_un.S_addr_mut() = raw_ip;
436 }
437 },
438 SocketAddr::V6(addr) => {
439 let sa6 = unsafe { &mut result.sa6 };
440
441 #[cfg(any(
442 target_os = "dragonfly",
443 target_os = "freebsd",
444 target_os = "haiku",
445 target_os = "hermit",
446 target_os = "ios",
447 target_os = "macos",
448 target_os = "netbsd",
449 target_os = "openbsd",
450 target_os = "vxworks",
451 target_os = "watchos",
452 ))]
453 {
454 sa6.sin6_len = std::mem::size_of::<sockaddr_in6>() as u8;
455 }
456
457 sa6.sin6_family = AF_INET6.try_into().unwrap();
458 sa6.sin6_port = u16::to_be(addr.port());
459 sa6.sin6_flowinfo = addr.flowinfo();
460
461 let raw_ip = u128::to_be_bytes((*addr.ip()).into());
462 #[cfg(not(target_os = "windows"))]
463 {
464 sa6.sin6_addr.s6_addr = raw_ip;
465 sa6.sin6_scope_id = addr.scope_id();
466 }
467 #[cfg(target_os = "windows")]
468 unsafe {
469 *sa6.sin6_addr.u.Byte_mut() = raw_ip;
470 *sa6.u.sin6_scope_id_mut() = addr.scope_id();
471 }
472 }
473 }
474 result
475 }
476}
477
478impl From<Option<SocketAddr>> for OsSocketAddr {
479 fn from(addr: Option<SocketAddr>) -> Self {
480 match addr {
481 None => Self::new(),
482 Some(addr) => addr.into(),
483 }
484 }
485}
486
487impl FromStr for OsSocketAddr {
488 type Err = std::net::AddrParseError;
489 fn from_str(val: &str) -> Result<Self,Self::Err> {
490 let addr : SocketAddr = val.parse()?;
491 Ok(addr.into())
492 }
493}
494
495impl std::fmt::Debug for OsSocketAddr {
496 fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result {
497 self.into_addr().fmt(fmt)
498 }
499}
500
501#[cfg(test)]
502mod tests {
503 use super::*;
504 use std::net::SocketAddrV6;
505
506 #[cfg(not(target_os = "windows"))]
507 use libc::{in6_addr, in_addr};
508
509 #[cfg(target_os = "windows")]
510 use winapi::shared::{in6addr::in6_addr, inaddr::in_addr};
511
512 fn check_as_mut(osa: &mut OsSocketAddr) {
513 let ptr = osa as *mut _ as usize;
514 let buf = osa.as_mut();
515 assert_eq!(buf.as_mut_ptr(), ptr as *mut _);
516 assert_eq!(buf.len(), std::mem::size_of::<sockaddr_in6>());
517 }
518
519 #[test]
520 fn ptr_and_capacity() {
521 let mut osa = OsSocketAddr::new();
522 assert_eq!(osa.as_ptr(), &osa as *const _ as *const _);
523 assert_eq!(osa.as_mut_ptr(), &mut osa as *mut _ as *mut _);
524 assert_eq!(osa.capacity() as usize, std::mem::size_of::<sockaddr_in6>());
525 }
526
527 #[test]
528 fn as_slice() {
529 let mut osa = OsSocketAddr::new();
530 {
531 let sl = osa.as_ref();
532 assert_eq!(sl.as_ptr(), &osa as *const _ as *const _);
533 assert_eq!(sl.len(), 0);
534 }
535 {
536 let ptr = &mut osa as *mut _ as *mut _;
537 let sl = osa.as_mut();
538 assert_eq!(sl.as_mut_ptr(), ptr);
539 assert_eq!(sl.len(), std::mem::size_of::<sockaddr_in6>());
540 }
541 }
542
543 #[test]
544 fn convert_from_and_to_raw() {
545 let osa4 : OsSocketAddr = "12.34.56.78:12345".parse().unwrap();
546 let osa6 : OsSocketAddr = "[0123:4567:89ab:cdef:fedc:ba98:7654:3210]:12345"
547 .parse().unwrap();
548 const LEN4 : usize = std::mem::size_of::<sockaddr_in>();
549 const LEN6 : usize = std::mem::size_of::<sockaddr_in6>();
550
551 fn with_buf<F>(len: usize, f: F)
552 where F: Fn(&mut [u8], *mut sockaddr, *mut socklen_t)
553 {
554 let mut buf = Vec::new();
555 buf.resize(len, 0xff);
556 let sa = buf.as_mut_ptr() as *mut sockaddr;
557 let mut sa_len = len as socklen_t;
558 f(&mut buf, sa , &mut sa_len as *mut socklen_t);
559 }
560 with_buf(128, |buf, sa, sa_len| unsafe {
562 osa4.copy_to_raw(sa, sa_len).unwrap();
563
564 assert_eq!(*sa_len as usize, LEN4);
565 assert_eq!(&buf[..LEN4], osa4.as_ref());
566 assert!(buf[LEN4..].iter().all(|v| *v==0xff));
567
568 let mut osa4_bis = OsSocketAddr::copy_from_raw(sa, *sa_len);
569 assert_eq!(osa4.into_addr(), osa4_bis.into_addr());
570 assert_eq!(&osa4_bis.as_ref()[..LEN4], &buf[..LEN4]);
571 assert!(osa4_bis.as_mut()[LEN4..].iter().all(|v| *v==0x0));
572
573 let mut osa4_ter = OsSocketAddr::copy_from_raw(sa, 128);
574 assert_eq!(osa4.into_addr(), osa4_ter.into_addr());
575 assert_eq!(&osa4_ter.as_ref()[..LEN4], &buf[..LEN4]);
576 assert!(osa4_ter.as_mut()[LEN4..].iter().all(|v| *v==0xff));
577 });
578 with_buf(128, |buf, sa, sa_len| unsafe {
580 osa6.copy_to_raw(sa, sa_len).unwrap();
581
582 assert_eq!(*sa_len as usize, LEN6);
583 assert_eq!(&buf[..LEN6], osa6.as_ref());
584 assert!(buf[LEN6..].iter().all(|v| *v==0xff));
585
586 let mut osa6_bis = OsSocketAddr::copy_from_raw(sa, *sa_len);
587 assert_eq!(osa6.into_addr(), osa6_bis.into_addr());
588 assert_eq!(osa6_bis.as_ref(), &buf[..LEN6]);
589 assert_eq!(osa6_bis.as_mut(), &buf[..LEN6]);
590 });
591 with_buf(128, |buf, sa, sa_len| unsafe {
593 let limit = 6;
594
595 *sa_len = limit as socklen_t;
596 osa4.copy_to_raw(sa, sa_len).unwrap();
597 assert_eq!(*sa_len as usize, LEN4);
598 assert_eq!(&buf[..limit], &osa4.as_ref()[..limit]);
599 assert!(buf[limit..].iter().all(|v| *v==0xff));
600
601 buf.fill(0xff);
602 *sa_len = limit as socklen_t;
603 osa6.copy_to_raw(sa, sa_len).unwrap();
604 assert_eq!(*sa_len as usize, LEN6);
605 assert_eq!(&buf[..limit], &osa6.as_ref()[..limit]);
606 assert!(buf[limit..].iter().all(|v| *v==0xff));
607 });
608 with_buf(128, |_, sa, sa_len| unsafe {
610 assert_eq!(OsSocketAddr::new().copy_to_raw(sa, sa_len), Err(BadFamilyError(0)));
611 assert_eq!(*sa_len, 0);
612 });
613 unsafe { osa4.copy_to_raw(std::ptr::null_mut(), std::ptr::null_mut()).unwrap(); }
615
616 let mut null = unsafe { OsSocketAddr::copy_from_raw(std::ptr::null(), 456) };
617 assert_eq!(null.as_mut(), OsSocketAddr::new().as_mut());
618 }
619
620 #[test]
621 fn os_socketaddr_ipv4() {
622 let addr: SocketAddr = "12.34.56.78:4242".parse().unwrap();
623 unsafe {
624 #[cfg(any(
625 target_os = "android",
626 target_os = "emscripten",
627 target_os = "fuchsia",
628 target_os = "illumos",
629 target_os = "l4re",
630 target_os = "linux",
631 target_os = "redox",
632 target_os = "solaris",
633
634 target_os = "windows",
635 ))]
636 let sa = sockaddr_in {
637 sin_family: AF_INET as u16,
638 sin_addr: *(&[12u8, 34, 56, 78] as *const _ as *const in_addr),
639 sin_port: 4242u16.to_be(),
640 sin_zero: std::mem::zeroed(),
641 };
642 #[cfg(any(
643 target_os = "dragonfly",
644 target_os = "freebsd",
645 target_os = "haiku",
646 target_os = "hermit",
647 target_os = "ios",
648 target_os = "macos",
649 target_os = "netbsd",
650 target_os = "openbsd",
651 target_os = "vxworks",
652 target_os = "watchos",
653 ))]
654 let sa = sockaddr_in {
655 sin_len: std::mem::size_of::<sockaddr_in>() as u8,
656 sin_family: AF_INET as u8,
657 sin_addr: *(&[12u8, 34, 56, 78] as *const _ as *const in_addr),
658 sin_port: 4242u16.to_be(),
659 sin_zero: std::mem::zeroed(),
660 };
661 let mut osa = OsSocketAddr::copy_from_raw(
662 &sa as *const _ as *const sockaddr,
663 std::mem::size_of_val(&sa) as socklen_t,
664 );
665 assert_eq!(osa.len() as usize, std::mem::size_of::<sockaddr_in>());
666 assert_eq!(osa.capacity() as usize, std::mem::size_of::<sockaddr_in6>());
667 assert_eq!(osa.into_addr(), Some(addr));
668 assert_eq!(osa.try_into(), Ok(addr));
669 assert_eq!(OsSocketAddr::from(addr).into_addr(), Some(addr));
670 {
671 let buf = osa.as_ref();
672 assert_eq!(buf.as_ptr(), &osa as *const _ as *const _);
673 assert_eq!(buf.len(), std::mem::size_of_val(&sa));
674 }
675 check_as_mut(&mut osa);
676 }
677 }
678
679 #[test]
680 fn os_socketaddr_ipv6() {
681 let ip = [
682 7u8, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22,
683 ];
684 let addr = SocketAddr::V6(SocketAddrV6::new(ip.into(), 4242, 0x11223344, 0x55667788));
685 unsafe {
686 #[cfg(any(
687 target_os = "android",
688 target_os = "emscripten",
689 target_os = "fuchsia",
690 target_os = "illumos",
691 target_os = "l4re",
692 target_os = "linux",
693 target_os = "redox",
694 target_os = "solaris",
695 ))]
696 let sa = sockaddr_in6 {
697 sin6_family: AF_INET6 as u16,
698 sin6_addr: *(&ip as *const _ as *const in6_addr),
699 sin6_port: 4242u16.to_be(),
700 sin6_flowinfo: 0x11223344,
701 sin6_scope_id: 0x55667788,
702 };
703 #[cfg(any(
704 target_os = "dragonfly",
705 target_os = "freebsd",
706 target_os = "haiku",
707 target_os = "hermit",
708 target_os = "ios",
709 target_os = "macos",
710 target_os = "netbsd",
711 target_os = "openbsd",
712 target_os = "vxworks",
713 target_os = "watchos",
714 ))]
715 let sa = sockaddr_in6 {
716 sin6_len: std::mem::size_of::<sockaddr_in6>() as u8,
717 sin6_family: AF_INET6 as u8,
718 sin6_addr: *(&ip as *const _ as *const in6_addr),
719 sin6_port: 4242u16.to_be(),
720 sin6_flowinfo: 0x11223344,
721 sin6_scope_id: 0x55667788,
722 };
723 #[cfg(target_os = "windows")]
724 let mut sa = sockaddr_in6 {
725 sin6_family: AF_INET6 as u16,
726 sin6_addr: *(&ip as *const _ as *const in6_addr),
727 sin6_port: 4242u16.to_be(),
728 sin6_flowinfo: 0x11223344,
729 u: std::mem::zeroed(),
730 };
731 #[cfg(target_os = "windows")]
732 let sa = {
733 let scope_id = sa.u.sin6_scope_id_mut();
734 *scope_id = 0x55667788;
735 sa
736 };
737
738 let mut osa = OsSocketAddr::copy_from_raw(
739 &sa as *const _ as *const sockaddr,
740 std::mem::size_of_val(&sa) as socklen_t,
741 );
742 assert_eq!(osa.len() as usize, std::mem::size_of::<sockaddr_in6>());
743 assert_eq!(osa.capacity() as usize, std::mem::size_of::<sockaddr_in6>());
744 assert_eq!(osa.into_addr(), Some(addr));
745 assert_eq!(osa.try_into(), Ok(addr));
746 assert_eq!(OsSocketAddr::from(addr).into_addr(), Some(addr));
747 {
748 let buf = osa.as_ref();
749 assert_eq!(buf.as_ptr(), &osa as *const _ as *const _);
750 assert_eq!(buf.len(), std::mem::size_of_val(&sa));
751 }
752 check_as_mut(&mut osa);
753 }
754 }
755
756 #[test]
757 fn os_socketaddr_other() {
758 fn check(mut osa: OsSocketAddr) {
759 assert_eq!(osa.into_addr(), None);
760
761 let r : Result<SocketAddr, _> = osa.try_into();
762 assert!(r.is_err());
763 {
764 let buf = osa.as_ref();
765 assert_eq!(buf.len(), 0);
766 assert_eq!(osa.len(), 0);
767 assert_eq!(osa.capacity() as usize, std::mem::size_of::<sockaddr_in6>());
768 }
769 check_as_mut(&mut osa);
770 }
771
772 check(OsSocketAddr::new());
773 check(None.into());
774 unsafe {
775 check(OsSocketAddr::copy_from_raw(
776 [0xde, 0xad, 0xbe, 0xef].as_ptr() as *const sockaddr,
777 4,
778 ));
779 }
780
781 let r : Result<SocketAddr, BadFamilyError> = OsSocketAddr::new().try_into();
782 assert!(r.is_err());
783 let e = r.unwrap_err();
784 assert_eq!(e, BadFamilyError(0));
785 assert_eq!(e.to_string(), "not an ip address (family=0)");
786 }
787}