-1

I want to parse output from the arp -a command on MacOS, in Go using the net.ParseMAC function, however I'm getting an error due to the weird formatting. Sample output from arp -a command:

> arp -a 
? (192.168.1.1) at 0:22:7:4a:21:d5 on en0 ifscope [ethernet]
? (224.0.0.251) at 1:0:5e:0:0:fb on en0 ifscope permanent [ethernet]
? (239.255.255.250) at 1:0:5e:7f:ff:fa on en0 ifscope permanent [ethernet]

The MAC formatting is unexpected because instead of doing 01 and 00, the MAC addresses include just 1 and 0. It seems the formatting is allowed to be A:B:C:D:E:F instead of AA:BB:CC:DD:EE:FF.

How can I make the output in the latter format, so it can be accepted by the net.ParseMAC function?


Edit: I made a simple Go function to solve the leaving off leading zeroes problem:

// FixMacOSMACNotation fixes the notation of MAC address on macOS.
// For instance: 1:0:5e:7f:ff:fa becomes 01:00:5e:7f:ff:fa
func FixMacOSMACNotation(s string) string {
    var newString string
    split := strings.Split(s, ":")
    for i, s := range split {
        if i != 0 {
            newString += ":"
        }
        if len(s) == 1 {
            newString += "0" + s
        } else {
            newString += s
        }
    }
    return newString
}

Which can then be used in net.ParseMAC successfully.

double-beep
  • 5,031
  • 17
  • 33
  • 41
asd12tgzxvbgt
  • 307
  • 2
  • 13
  • How are you formatting the output? The `net.HardwareAddr` type formats itself correctly: https://play.golang.org/p/WF9YkgJd2I8 – JimB Sep 13 '21 at 18:25
  • @JimB I am parsing the output from `arp -a` command, which is fetched using library: https://github.com/mostlygeek/arp . It returns MAC as string, which I use in net.ParseMAC. – asd12tgzxvbgt Sep 13 '21 at 18:29
  • If the question is about the `arp` command output, and it doesn't format the MAC addresses in the expected manner, you will have to reformat them yourself to pass into the `net.ParseMAC` function or parse them manually. That function takes a number of formats already, if you think this should be supported too you need to file an issue in the Go issue tracker. – JimB Sep 13 '21 at 18:40
  • Do you know what format the `arp` tool is using, cause I find very little information about it @JimB – asd12tgzxvbgt Sep 14 '21 at 20:48
  • I’m not sure what you mean, the “format” is the output you are showing here. – JimB Sep 14 '21 at 21:12
  • @JimB Take a look at the answers, it should make it clear what I wanted to achieve :) – asd12tgzxvbgt Sep 15 '21 at 13:02

1 Answers1

1

This version uses strings.Builder to fix the given input as desired by OP.

A [strings.]Builder is used to efficiently build a string using Write methods. It minimizes memory copying. The zero value is ready to use. Do not copy a non-zero Builder.

package main

import (
    "fmt"
    "strings"
)

func main() {
    inputs := []string{
        "1:0:5e:7f:ff:fa",
        "1:0:5e:7f:ff:f",
        "1:0:5e:7f:ff:",
        "1:0:5e::ff:",
    }

    for _, input := range inputs {
        fmt.Println()
        fmt.Println("FixMacOSMACNotation    ", FixMacOSMACNotation(input))
    }
}

// FixMacOSMACNotation fixes the notation of MAC address on macOS.
// For instance: 1:0:5e:7f:ff:fa becomes 01:00:5e:7f:ff:fa
func FixMacOSMACNotation(s string) string {
    var e int
    var sb strings.Builder
    for i := 0; i < len(s); i++ {
        r := s[i]
        if r == ':' {
            for j := e; j < 2; j++ {
                sb.WriteString("0")
            }
            sb.WriteString(s[i-e : i])
            sb.WriteString(":")
            e = 0
            continue
        }
        e++
    }
    for j := e; j < 2; j++ {
        sb.WriteString("0")
    }
    sb.WriteString(s[len(s)-e:])
    return sb.String()
}

try it here