Skip to content

Commit cfacb5b

Browse files
author
luozijun
committed
Impl EtherAddr(MAC Addr)
1 parent bc82685 commit cfacb5b

File tree

3 files changed

+324
-2
lines changed

3 files changed

+324
-2
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,8 @@ This project adheres to [Semantic Versioning](http://semver.org/).
5050
([#741](https://github.com/nix-rust/nix/pull/741))
5151
- Added more standard trait implementations for various types.
5252
([#814](https://github.com/nix-rust/nix/pull/814))
53+
- Added `nix::sys::socket::EtherAddr` on Linux and all bsdlike system.
54+
([#813](https://github.com/nix-rust/nix/pull/813))
5355

5456
### Changed
5557
- Use native `pipe2` on all BSD targets. Users should notice no difference.

src/sys/socket/addr.rs

Lines changed: 312 additions & 2 deletions
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/Packet
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
}
@@ -720,6 +729,16 @@ pub enum SockAddr {
720729
Netlink(NetlinkAddr),
721730
#[cfg(any(target_os = "ios", target_os = "macos"))]
722731
SysControl(SysControlAddr),
732+
/// Ethernet MAC address
733+
#[cfg(any(target_os = "dragonfly",
734+
target_os = "freebsd",
735+
target_os = "ios",
736+
target_os = "macos",
737+
target_os = "netbsd",
738+
target_os = "openbsd",
739+
target_os = "android",
740+
target_os = "linux"))]
741+
Ether(EtherAddr)
723742
}
724743

725744
impl SockAddr {
@@ -750,6 +769,15 @@ impl SockAddr {
750769
SockAddr::Netlink(..) => AddressFamily::Netlink,
751770
#[cfg(any(target_os = "ios", target_os = "macos"))]
752771
SockAddr::SysControl(..) => AddressFamily::System,
772+
#[cfg(any(target_os = "android", target_os = "linux"))]
773+
SockAddr::Ether(..) => AddressFamily::Packet,
774+
#[cfg(any(target_os = "dragonfly",
775+
target_os = "freebsd",
776+
target_os = "ios",
777+
target_os = "macos",
778+
target_os = "netbsd",
779+
target_os = "openbsd"))]
780+
SockAddr::Ether(..) => AddressFamily::Link
753781
}
754782
}
755783

@@ -777,6 +805,27 @@ impl SockAddr {
777805
#[cfg(any(target_os = "ios", target_os = "macos"))]
778806
Some(AddressFamily::System) => Some(SockAddr::SysControl(
779807
SysControlAddr(*(addr as *const sys_control::sockaddr_ctl)))),
808+
#[cfg(any(target_os = "android", target_os = "linux"))]
809+
Some(AddressFamily::Packet) => {
810+
let ether_addr = EtherAddr::new(*(addr as *const libc::sockaddr_ll));
811+
match ether_addr {
812+
Some(ether_addr) => Some(SockAddr::Ether(ether_addr)),
813+
None => None
814+
}
815+
},
816+
#[cfg(any(target_os = "dragonfly",
817+
target_os = "freebsd",
818+
target_os = "ios",
819+
target_os = "macos",
820+
target_os = "netbsd",
821+
target_os = "openbsd"))]
822+
Some(AddressFamily::Link) => {
823+
let ether_addr = EtherAddr::new(*(addr as *const libc::sockaddr_dl));
824+
match ether_addr {
825+
Some(ether_addr) => Some(SockAddr::Ether(ether_addr)),
826+
None => None
827+
}
828+
},
780829
// Other address families are currently not supported and simply yield a None
781830
// entry instead of a proper conversion to a `SockAddr`.
782831
Some(_) => None,
@@ -794,6 +843,15 @@ impl SockAddr {
794843
SockAddr::Netlink(NetlinkAddr(ref sa)) => (mem::transmute(sa), mem::size_of::<libc::sockaddr_nl>() as libc::socklen_t),
795844
#[cfg(any(target_os = "ios", target_os = "macos"))]
796845
SockAddr::SysControl(SysControlAddr(ref sa)) => (mem::transmute(sa), mem::size_of::<sys_control::sockaddr_ctl>() as libc::socklen_t),
846+
#[cfg(any(target_os = "dragonfly",
847+
target_os = "freebsd",
848+
target_os = "ios",
849+
target_os = "macos",
850+
target_os = "netbsd",
851+
target_os = "openbsd",
852+
target_os = "linux",
853+
target_os = "android"))]
854+
SockAddr::Ether(_) => unimplemented!()
797855
}
798856
}
799857
}
@@ -811,6 +869,17 @@ impl PartialEq for SockAddr {
811869
(SockAddr::Netlink(ref a), SockAddr::Netlink(ref b)) => {
812870
a == b
813871
}
872+
#[cfg(any(target_os = "dragonfly",
873+
target_os = "freebsd",
874+
target_os = "ios",
875+
target_os = "macos",
876+
target_os = "netbsd",
877+
target_os = "openbsd",
878+
target_os = "linux",
879+
target_os = "android"))]
880+
(SockAddr::Ether(ref a), SockAddr::Ether(ref b)) => {
881+
a == b
882+
}
814883
_ => false,
815884
}
816885
}
@@ -828,6 +897,15 @@ impl hash::Hash for SockAddr {
828897
SockAddr::Netlink(ref a) => a.hash(s),
829898
#[cfg(any(target_os = "ios", target_os = "macos"))]
830899
SockAddr::SysControl(ref a) => a.hash(s),
900+
#[cfg(any(target_os = "dragonfly",
901+
target_os = "freebsd",
902+
target_os = "ios",
903+
target_os = "macos",
904+
target_os = "netbsd",
905+
target_os = "openbsd",
906+
target_os = "linux",
907+
target_os = "android"))]
908+
SockAddr::Ether(ref ether_addr) => ether_addr.hash(s)
831909
}
832910
}
833911
}
@@ -847,6 +925,15 @@ impl fmt::Display for SockAddr {
847925
SockAddr::Netlink(ref nl) => nl.fmt(f),
848926
#[cfg(any(target_os = "ios", target_os = "macos"))]
849927
SockAddr::SysControl(ref sc) => sc.fmt(f),
928+
#[cfg(any(target_os = "dragonfly",
929+
target_os = "freebsd",
930+
target_os = "ios",
931+
target_os = "macos",
932+
target_os = "netbsd",
933+
target_os = "openbsd",
934+
target_os = "linux",
935+
target_os = "android"))]
936+
SockAddr::Ether(ref ether_addr) => ether_addr.fmt(f)
850937
}
851938
}
852939
}
@@ -1014,4 +1101,227 @@ pub mod sys_control {
10141101
fmt::Display::fmt(self, f)
10151102
}
10161103
}
1017-
}
1104+
}
1105+
1106+
1107+
#[cfg(any(target_os = "android", target_os = "linux"))]
1108+
#[derive(Clone, Copy)]
1109+
pub struct EtherAddr(pub libc::sockaddr_ll);
1110+
1111+
#[cfg(any(target_os = "dragonfly",
1112+
target_os = "freebsd",
1113+
target_os = "ios",
1114+
target_os = "macos",
1115+
target_os = "netbsd",
1116+
target_os = "openbsd"))]
1117+
#[derive(Clone, Copy)]
1118+
pub struct EtherAddr(pub libc::sockaddr_dl);
1119+
1120+
1121+
#[cfg(any(target_os = "android", target_os = "linux"))]
1122+
impl EtherAddr {
1123+
pub fn new(sll: libc::sockaddr_ll) -> Option<EtherAddr> {
1124+
Some(EtherAddr(sll))
1125+
}
1126+
1127+
pub fn is_empty(&self) -> bool {
1128+
false
1129+
}
1130+
1131+
pub fn addr(&self) -> [u8; 6] {
1132+
[self.0.sll_addr[0],
1133+
self.0.sll_addr[1],
1134+
self.0.sll_addr[2],
1135+
self.0.sll_addr[3],
1136+
self.0.sll_addr[4],
1137+
self.0.sll_addr[5]]
1138+
}
1139+
}
1140+
1141+
#[cfg(any(target_os = "dragonfly",
1142+
target_os = "freebsd",
1143+
target_os = "ios",
1144+
target_os = "macos",
1145+
target_os = "netbsd",
1146+
target_os = "openbsd"))]
1147+
impl EtherAddr {
1148+
pub fn new(sdl: libc::sockaddr_dl) -> Option<EtherAddr> {
1149+
let sdl_wrap = EtherAddr(sdl);
1150+
match sdl_wrap.is_empty() {
1151+
true => None,
1152+
false => Some(sdl_wrap),
1153+
}
1154+
}
1155+
1156+
pub fn nlen(&self) -> usize {
1157+
self.0.sdl_nlen as usize
1158+
}
1159+
1160+
pub fn is_empty(&self) -> bool {
1161+
self.nlen() + 5 >= self.max_nlen()
1162+
}
1163+
1164+
#[cfg(any(target_os = "macos",
1165+
target_os = "ios",
1166+
target_os = "dragonfly",
1167+
target_os = "netbsd"))]
1168+
pub fn max_nlen(&self) -> usize { 12 }
1169+
1170+
#[cfg(target_os = "openbsd")]
1171+
pub fn max_nlen(&self) -> usize { 24 }
1172+
1173+
#[cfg(target_os = "freebsd")]
1174+
pub fn max_nlen(&self) -> usize { 46 }
1175+
1176+
pub fn addr(&self) -> [u8; 6] {
1177+
assert_eq!(self.is_empty(), false);
1178+
let nlen = self.nlen();
1179+
1180+
[self.0.sdl_data[nlen ] as u8,
1181+
self.0.sdl_data[nlen + 1] as u8,
1182+
self.0.sdl_data[nlen + 2] as u8,
1183+
self.0.sdl_data[nlen + 3] as u8,
1184+
self.0.sdl_data[nlen + 4] as u8,
1185+
self.0.sdl_data[nlen + 5] as u8 ]
1186+
}
1187+
1188+
}
1189+
1190+
#[cfg(any(target_os = "dragonfly",
1191+
target_os = "freebsd",
1192+
target_os = "ios",
1193+
target_os = "macos",
1194+
target_os = "netbsd",
1195+
target_os = "openbsd",
1196+
target_os = "linux",
1197+
target_os = "android"))]
1198+
impl Eq for EtherAddr {}
1199+
1200+
1201+
#[cfg(any(target_os = "android", target_os = "linux"))]
1202+
impl PartialEq for EtherAddr {
1203+
fn eq(&self, other: &Self) -> bool {
1204+
let (a, b) = (self.0, other.0);
1205+
(a.sll_family, a.sll_protocol, a.sll_ifindex, a.sll_hatype,
1206+
a.sll_pkttype, a.sll_halen, a.sll_addr) ==
1207+
(b.sll_family, b.sll_protocol, b.sll_ifindex, b.sll_hatype,
1208+
b.sll_pkttype, b.sll_halen, b.sll_addr)
1209+
}
1210+
}
1211+
1212+
#[cfg(any(target_os = "android", target_os = "linux"))]
1213+
impl hash::Hash for EtherAddr {
1214+
fn hash<H: hash::Hasher>(&self, s: &mut H) {
1215+
let a = self.0;
1216+
(a.sll_family, a.sll_protocol, a.sll_ifindex, a.sll_hatype,
1217+
a.sll_pkttype, a.sll_halen, a.sll_addr).hash(s);
1218+
}
1219+
}
1220+
1221+
#[cfg(any(target_os = "dragonfly",
1222+
target_os = "freebsd",
1223+
target_os = "ios",
1224+
target_os = "macos",
1225+
target_os = "netbsd",
1226+
target_os = "openbsd"))]
1227+
impl PartialEq for EtherAddr {
1228+
#[cfg(any(target_os = "macos",
1229+
target_os = "ios",
1230+
target_os = "netbsd",
1231+
target_os = "openbsd"))]
1232+
fn eq(&self, other: &Self) -> bool {
1233+
let (a, b) = (self.0, other.0);
1234+
(a.sdl_len, a.sdl_family, a.sdl_index, a.sdl_type,
1235+
a.sdl_nlen, a.sdl_alen, a.sdl_slen, a.sdl_data) ==
1236+
(b.sdl_len, b.sdl_family, b.sdl_index, b.sdl_type,
1237+
b.sdl_nlen, b.sdl_alen, b.sdl_slen, b.sdl_data)
1238+
}
1239+
1240+
#[cfg(target_os = "freebsd")]
1241+
fn eq(&self, other: &Self) -> bool {
1242+
let (a, b) = (self.0, other.0);
1243+
(a.sdl_len, a.sdl_family, a.sdl_index, a.sdl_type,
1244+
a.sdl_nlen, a.sdl_alen, a.sdl_slen,
1245+
&a.sdl_data[0..30], &a.sdl_data[30..46]) ==
1246+
(b.sdl_len, b.sdl_family, b.sdl_index, b.sdl_type,
1247+
b.sdl_nlen, b.sdl_alen, b.sdl_slen,
1248+
&b.sdl_data[0..30], &b.sdl_data[30..46])
1249+
}
1250+
1251+
#[cfg(target_os = "dragonfly")]
1252+
fn eq(&self, other: &Self) -> bool {
1253+
let (a, b) = (self.0, other.0);
1254+
(a.sdl_len, a.sdl_family, a.sdl_index, a.sdl_type, a.sdl_nlen,
1255+
a.sdl_alen, a.sdl_slen, a.sdl_data, a.sdl_rcf, a.sdl_route) ==
1256+
(b.sdl_len, b.sdl_family, b.sdl_index, b.sdl_type, b.sdl_nlen,
1257+
b.sdl_alen, b.sdl_slen, b.sdl_data, b.sdl_rcf, b.sdl_route)
1258+
}
1259+
}
1260+
1261+
#[cfg(any(target_os = "dragonfly",
1262+
target_os = "freebsd",
1263+
target_os = "ios",
1264+
target_os = "macos",
1265+
target_os = "netbsd",
1266+
target_os = "openbsd"))]
1267+
impl hash::Hash for EtherAddr {
1268+
#[cfg(any(target_os = "macos",
1269+
target_os = "ios",
1270+
target_os = "netbsd",
1271+
target_os = "openbsd"))]
1272+
fn hash<H: hash::Hasher>(&self, s: &mut H) {
1273+
let a = self.0;
1274+
(a.sdl_len, a.sdl_family, a.sdl_index, a.sdl_type,
1275+
a.sdl_nlen, a.sdl_alen, a.sdl_slen, a.sdl_data).hash(s);
1276+
}
1277+
1278+
#[cfg(target_os = "freebsd")]
1279+
fn hash<H: hash::Hasher>(&self, s: &mut H) {
1280+
let a = self.0;
1281+
(a.sdl_len, a.sdl_family, a.sdl_index, a.sdl_type,
1282+
a.sdl_nlen, a.sdl_alen, a.sdl_slen,
1283+
&a.sdl_data[0..30], &a.sdl_data[30..46]).hash(s);
1284+
}
1285+
1286+
#[cfg(target_os = "dragonfly")]
1287+
fn hash<H: hash::Hasher>(&self, s: &mut H) {
1288+
let a = self.0;
1289+
(a.sdl_len, a.sdl_family, a.sdl_index, a.sdl_type, a.sdl_nlen,
1290+
a.sdl_alen, a.sdl_slen, a.sdl_data, a.sdl_rcf, a.sdl_route).hash(s);
1291+
}
1292+
}
1293+
1294+
#[cfg(any(target_os = "dragonfly",
1295+
target_os = "freebsd",
1296+
target_os = "ios",
1297+
target_os = "macos",
1298+
target_os = "netbsd",
1299+
target_os = "openbsd",
1300+
target_os = "linux",
1301+
target_os = "android"))]
1302+
impl fmt::Display for EtherAddr {
1303+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1304+
let addr = self.addr();
1305+
write!(f, "{:02x}:{:02x}:{:02x}:{:02x}:{:02x}:{:02x}",
1306+
addr[0],
1307+
addr[1],
1308+
addr[2],
1309+
addr[3],
1310+
addr[4],
1311+
addr[5])
1312+
}
1313+
}
1314+
1315+
#[cfg(any(target_os = "dragonfly",
1316+
target_os = "freebsd",
1317+
target_os = "ios",
1318+
target_os = "macos",
1319+
target_os = "netbsd",
1320+
target_os = "openbsd",
1321+
target_os = "linux",
1322+
target_os = "android"))]
1323+
impl fmt::Debug for EtherAddr {
1324+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1325+
fmt::Display::fmt(self, f)
1326+
}
1327+
}

0 commit comments

Comments
 (0)