Skip to main content

zond_engine/core/models/
mac.rs

1// Copyright (c) 2026 Erik Lening (hollowpointer) and Contributors
2//
3// This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
4// If a copy of the MPL was not distributed with this file, You can obtain one at
5// https://mozilla.org/MPL/2.0/.
6
7//! This module provides a native **Medium Access Control (MAC)** address type
8//! to eliminate dependency on external network parsing libraries within the core.
9//!
10//! It also includes **Organizationally Unique Identifier (OUI)** database
11//! initialization and handling for vendor identification.
12
13use mac_oui::Oui;
14use std::fmt;
15use std::sync::OnceLock;
16
17/// A native, framework-agnostic MAC address representation.
18#[derive(Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
19pub struct MacAddr(pub [u8; 6]);
20
21impl MacAddr {
22    /// Creates a new `MacAddr` from 6 octets.
23    pub const fn new(a: u8, b: u8, c: u8, d: u8, e: u8, f: u8) -> Self {
24        Self([a, b, c, d, e, f])
25    }
26}
27
28impl From<[u8; 6]> for MacAddr {
29    fn from(octets: [u8; 6]) -> Self {
30        Self(octets)
31    }
32}
33
34impl fmt::Debug for MacAddr {
35    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
36        write!(
37            f,
38            "{:02x}:{:02x}:{:02x}:{:02x}:{:02x}:{:02x}",
39            self.0[0], self.0[1], self.0[2], self.0[3], self.0[4], self.0[5]
40        )
41    }
42}
43
44impl fmt::Display for MacAddr {
45    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
46        write!(
47            f,
48            "{:02x}:{:02x}:{:02x}:{:02x}:{:02x}:{:02x}",
49            self.0[0], self.0[1], self.0[2], self.0[3], self.0[4], self.0[5]
50        )
51    }
52}
53
54static OUI_DB: OnceLock<Oui> = OnceLock::new();
55
56/// Retrieves or initializes the **Organizationally unique identifier** database.
57///
58/// Used for linking a vendor to a MAC address (LAN)
59fn get_oui_db() -> &'static Oui {
60    OUI_DB.get_or_init(|| Oui::default().expect("failed to load OUI database"))
61}
62
63/// Identify the vendor of a MAC address.
64pub fn vendor(mac: &MacAddr) -> Option<String> {
65    let db = get_oui_db();
66    let mac_str = mac.to_string();
67    match db.lookup_by_mac(&mac_str) {
68        Ok(Some(entry)) => Some(entry.company_name.clone()),
69        _ => None,
70    }
71}
72
73#[cfg(test)]
74mod tests {
75    use super::*;
76
77    #[test]
78    fn test_mac_display_and_debug() {
79        let mac = MacAddr::new(0x00, 0x1A, 0x2B, 0x3C, 0x4D, 0x5E);
80        assert_eq!(mac.to_string(), "00:1a:2b:3c:4d:5e");
81        assert_eq!(format!("{:?}", mac), "00:1a:2b:3c:4d:5e");
82    }
83
84    #[test]
85    fn test_mac_from_array() {
86        let arr = [0x11, 0x22, 0x33, 0x44, 0x55, 0x66];
87        let mac = MacAddr::from(arr);
88        assert_eq!(mac.0, arr);
89    }
90
91    #[test]
92    fn test_vendor_lookup() {
93        let mac = MacAddr::new(0x00, 0x0C, 0x29, 0xAB, 0xCD, 0xEF);
94        let vendor = vendor(&mac);
95        assert_eq!(vendor, Some("VMware, Inc".to_string()));
96    }
97
98    #[test]
99    fn test_unknown_vendor_lookup() {
100        let mac = MacAddr::new(0x02, 0x00, 0x00, 0x00, 0x00, 0x00); // Locally administered
101        let vendor = vendor(&mac);
102        assert_eq!(vendor, None);
103    }
104}