summaryrefslogtreecommitdiff
path: root/utils/net.go
diff options
context:
space:
mode:
authorElizabeth Alexander Hunt <me@liz.coffee>2026-06-20 09:40:07 -0700
committerElizabeth Alexander Hunt <me@liz.coffee>2026-06-20 09:40:07 -0700
commitfb653292612eddca5b088ed88466c546d1597107 (patch)
tree900ed32e066812688858ed3bb15128c41bb78054 /utils/net.go
downloadpenguins.lan-fb653292612eddca5b088ed88466c546d1597107.tar.gz
penguins.lan-fb653292612eddca5b088ed88466c546d1597107.zip
Initial commit
Diffstat (limited to 'utils/net.go')
-rw-r--r--utils/net.go59
1 files changed, 59 insertions, 0 deletions
diff --git a/utils/net.go b/utils/net.go
new file mode 100644
index 0000000..76454bd
--- /dev/null
+++ b/utils/net.go
@@ -0,0 +1,59 @@
+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
+}