package utils import ( "fmt" "strings" ) // Mac is a 48-bit hardware address. type Mac struct { Addr [6]byte } // Format renders the canonical lowercase, zero-padded form aa:bb:cc:dd:ee:ff. func (m *Mac) Format() string { return fmt.Sprintf("%02x:%02x:%02x:%02x:%02x:%02x", m.Addr[0], m.Addr[1], m.Addr[2], m.Addr[3], m.Addr[4], m.Addr[5]) } // ParseMac reads a colon-separated hex MAC. It tolerates uppercase and the // zero-stripped octets macOS prints (e.g. "8:0:27:ab:cd:ef"). func ParseMac(s string) (*Mac, error) { mac := &Mac{} t := strings.TrimSpace(s) n, err := fmt.Sscanf(t, "%x:%x:%x:%x:%x:%x", &mac.Addr[0], &mac.Addr[1], &mac.Addr[2], &mac.Addr[3], &mac.Addr[4], &mac.Addr[5]) if err != nil { return nil, err } if n != 6 { return nil, fmt.Errorf("invalid mac %q: parsed %d of 6 octets", s, n) } return mac, nil } // INet4 is an IPv4 address. type INet4 struct { Addr [4]byte } // Format renders the dotted-decimal form a.b.c.d. func (n *INet4) Format() string { return fmt.Sprintf("%d.%d.%d.%d", n.Addr[0], n.Addr[1], n.Addr[2], n.Addr[3]) } // ParseINet4 reads a dotted-decimal IPv4 address. Out-of-range octets (>255) // overflow the byte and are rejected. func ParseINet4(s string) (*INet4, error) { addr := &INet4{} t := strings.TrimSpace(s) n, err := fmt.Sscanf(t, "%d.%d.%d.%d", &addr.Addr[0], &addr.Addr[1], &addr.Addr[2], &addr.Addr[3]) if err != nil { return nil, err } if n != 4 { return nil, fmt.Errorf("invalid ipv4 %q: parsed %d of 4 octets", s, n) } return addr, nil }