Skip to content

Commit 640e2fe

Browse files
author
luozijun
committed
Impl EtherAddr(MAC Addr)
1 parent 4e7a6ec commit 640e2fe

File tree

1 file changed

+131
-1
lines changed

1 file changed

+131
-1
lines changed

src/sys/socket/addr.rs

Lines changed: 131 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -206,7 +206,7 @@ impl AddressFamily {
206206
/// Create a new `AddressFamily` from an integer value retrieved from `libc`, usually from
207207
/// the `sa_family` field of a `sockaddr`.
208208
///
209-
/// Currently only supports these address families: Unix, Inet (v4 & v6), Netlink
209+
/// Currently only supports these address families: Unix, Inet (v4 & v6), Netlink, Link
210210
/// and System. Returns None for unsupported or unknown address families.
211211
pub fn from_i32(family: i32) -> Option<AddressFamily> {
212212
match family {
@@ -217,6 +217,15 @@ impl AddressFamily {
217217
libc::AF_NETLINK => Some(AddressFamily::Netlink),
218218
#[cfg(any(target_os = "macos", target_os = "macos"))]
219219
libc::AF_SYSTEM => Some(AddressFamily::System),
220+
#[cfg(any(target_os = "android", target_os = "linux"))]
221+
libc::AF_PACKET => Some(AddressFamily::Packet),
222+
#[cfg(any(target_os = "dragonfly",
223+
target_os = "freebsd",
224+
target_os = "ios",
225+
target_os = "macos",
226+
target_os = "netbsd",
227+
target_os = "openbsd"))]
228+
libc::AF_LINK => Some(AddressFamily::Link),
220229
_ => None
221230
}
222231
}
@@ -721,6 +730,8 @@ pub enum SockAddr {
721730
Netlink(NetlinkAddr),
722731
#[cfg(any(target_os = "ios", target_os = "macos"))]
723732
SysControl(SysControlAddr),
733+
/// Ethernet MAC address
734+
Ether(EtherAddr)
724735
}
725736

726737
impl SockAddr {
@@ -751,6 +762,15 @@ impl SockAddr {
751762
SockAddr::Netlink(..) => AddressFamily::Netlink,
752763
#[cfg(any(target_os = "ios", target_os = "macos"))]
753764
SockAddr::SysControl(..) => AddressFamily::System,
765+
#[cfg(any(target_os = "android", target_os = "linux"))]
766+
SockAddr::Ether(..) => AddressFamily::Packet,
767+
#[cfg(any(target_os = "dragonfly",
768+
target_os = "freebsd",
769+
target_os = "ios",
770+
target_os = "macos",
771+
target_os = "netbsd",
772+
target_os = "openbsd"))]
773+
SockAddr::Ether(..) => AddressFamily::Link
754774
}
755775
}
756776

@@ -778,6 +798,23 @@ impl SockAddr {
778798
#[cfg(any(target_os = "ios", target_os = "macos"))]
779799
Some(AddressFamily::System) => Some(SockAddr::SysControl(
780800
SysControlAddr(*(addr as *const sys_control::sockaddr_ctl)))),
801+
#[cfg(any(target_os = "android", target_os = "linux"))]
802+
Some(AddressFamily::Packet) => match EtherAddr::from_libc_sockaddr_ll(
803+
addr as *const libc::sockaddr_ll) {
804+
Some(mac_addr) => Some(SockAddr::Ether(mac_addr)),
805+
None => None
806+
},
807+
#[cfg(any(target_os = "dragonfly",
808+
target_os = "freebsd",
809+
target_os = "ios",
810+
target_os = "macos",
811+
target_os = "netbsd",
812+
target_os = "openbsd"))]
813+
Some(AddressFamily::Link) => match EtherAddr::from_libc_sockaddr_dl(
814+
addr as *const libc::sockaddr_dl) {
815+
Some(mac_addr) => Some(SockAddr::Ether(mac_addr)),
816+
None => None
817+
},
781818
// Other address families are currently not supported and simply yield a None
782819
// entry instead of a proper conversion to a `SockAddr`.
783820
Some(_) => None,
@@ -795,6 +832,7 @@ impl SockAddr {
795832
SockAddr::Netlink(NetlinkAddr(ref sa)) => (mem::transmute(sa), mem::size_of::<libc::sockaddr_nl>() as libc::socklen_t),
796833
#[cfg(any(target_os = "ios", target_os = "macos"))]
797834
SockAddr::SysControl(SysControlAddr(ref sa)) => (mem::transmute(sa), mem::size_of::<sys_control::sockaddr_ctl>() as libc::socklen_t),
835+
SockAddr::Ether(_) => unimplemented!()
798836
}
799837
}
800838
}
@@ -812,6 +850,9 @@ impl PartialEq for SockAddr {
812850
(SockAddr::Netlink(ref a), SockAddr::Netlink(ref b)) => {
813851
a == b
814852
}
853+
(SockAddr::Ether(ref a), SockAddr::Ether(ref b)) => {
854+
a == b
855+
}
815856
_ => false,
816857
}
817858
}
@@ -829,6 +870,7 @@ impl hash::Hash for SockAddr {
829870
SockAddr::Netlink(ref a) => a.hash(s),
830871
#[cfg(any(target_os = "ios", target_os = "macos"))]
831872
SockAddr::SysControl(ref a) => a.hash(s),
873+
SockAddr::Ether(ref ether_addr) => ether_addr.hash(s)
832874
}
833875
}
834876
}
@@ -848,6 +890,7 @@ impl fmt::Display for SockAddr {
848890
SockAddr::Netlink(ref nl) => nl.fmt(f),
849891
#[cfg(any(target_os = "ios", target_os = "macos"))]
850892
SockAddr::SysControl(ref sc) => sc.fmt(f),
893+
SockAddr::Ether(ref ether_addr) => ether_addr.fmt(f)
851894
}
852895
}
853896
}
@@ -1016,3 +1059,90 @@ pub mod sys_control {
10161059
}
10171060
}
10181061
}
1062+
1063+
#[derive(Clone, Copy, Eq, Hash, PartialEq)]
1064+
pub struct EtherAddr {
1065+
pub a: u8,
1066+
pub b: u8,
1067+
pub c: u8,
1068+
pub d: u8,
1069+
pub e: u8,
1070+
pub f: u8,
1071+
}
1072+
1073+
impl EtherAddr {
1074+
pub fn new(a: u8, b: u8, c: u8, d: u8, e: u8, f: u8) -> EtherAddr {
1075+
EtherAddr {
1076+
a: a,
1077+
b: b,
1078+
c: c,
1079+
d: d,
1080+
e: e,
1081+
f: f,
1082+
}
1083+
}
1084+
1085+
#[cfg(any(target_os = "android", target_os = "linux"))]
1086+
pub unsafe fn from_libc_sockaddr_ll(sll: *const libc::sockaddr_ll) -> Option<EtherAddr> {
1087+
let mac = EtherAddr::new(
1088+
(*sll).sll_addr[0],
1089+
(*sll).sll_addr[1],
1090+
(*sll).sll_addr[2],
1091+
(*sll).sll_addr[3],
1092+
(*sll).sll_addr[4],
1093+
(*sll).sll_addr[5]);
1094+
Some(mac)
1095+
}
1096+
1097+
#[cfg(any(target_os = "dragonfly",
1098+
target_os = "freebsd",
1099+
target_os = "ios",
1100+
target_os = "macos",
1101+
target_os = "netbsd",
1102+
target_os = "openbsd"))]
1103+
pub unsafe fn from_libc_sockaddr_dl(sdl: *const libc::sockaddr_dl) -> Option<EtherAddr> {
1104+
let nlen = (*sdl).sdl_nlen as usize;
1105+
let max_nlen: usize = if cfg!(target_os = "macos") || cfg!(target_os = "ios") {
1106+
12
1107+
} else if cfg!(target_os = "freebsd") {
1108+
46
1109+
} else if cfg!(target_os = "dragonfly") {
1110+
12
1111+
} else if cfg!(target_os = "netbsd") {
1112+
12
1113+
} else if cfg!(target_os = "openbsd") {
1114+
24
1115+
} else {
1116+
unreachable!();
1117+
};
1118+
if nlen + 5 >= max_nlen {
1119+
return None;
1120+
}
1121+
let mac = EtherAddr::new(
1122+
(*sdl).sdl_data[nlen ] as u8,
1123+
(*sdl).sdl_data[nlen + 1] as u8,
1124+
(*sdl).sdl_data[nlen + 2] as u8,
1125+
(*sdl).sdl_data[nlen + 3] as u8,
1126+
(*sdl).sdl_data[nlen + 4] as u8,
1127+
(*sdl).sdl_data[nlen + 5] as u8);
1128+
Some(mac)
1129+
}
1130+
}
1131+
1132+
impl fmt::Display for EtherAddr {
1133+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1134+
write!(f, "{:02x}:{:02x}:{:02x}:{:02x}:{:02x}:{:02x}",
1135+
self.a,
1136+
self.b,
1137+
self.c,
1138+
self.d,
1139+
self.e,
1140+
self.f)
1141+
}
1142+
}
1143+
1144+
impl fmt::Debug for EtherAddr {
1145+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1146+
fmt::Display::fmt(self, f)
1147+
}
1148+
}

0 commit comments

Comments
 (0)