Skip to content
This repository has been archived by the owner on Sep 14, 2019. It is now read-only.

Commit

Permalink
[medium] netstat: evolve results format to support arrays of items
Browse files Browse the repository at this point in the history
  • Loading branch information
jvehent committed Sep 15, 2014
1 parent c76239c commit 49498bf
Show file tree
Hide file tree
Showing 4 changed files with 129 additions and 75 deletions.
130 changes: 80 additions & 50 deletions src/mig/modules/netstat/netstat.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,26 +40,40 @@ type params struct {
}

type results struct {
LocalMAC []result `json:"localmac,omitempty"`
LocalIP []result `json:"localip,omitempty"`
NeighborMAC []result `json:"neighbormac,omitempty"`
NeighborIP []result `json:"neighborip,omitempty"`
ConnectedIP []result `json:"connectedip,omitempty"`
ListeningPort []result `json:"listeningport,omitempty"`
FoundAnything bool `json:"foundanything"`
Success bool `json:"success"`
Errors []string `json:"errors,omitempty"`
LocalMAC map[string]result `json:"localmac,omitempty"`
LocalIP map[string]result `json:"localip,omitempty"`
NeighborMAC map[string]result `json:"neighbormac,omitempty"`
NeighborIP map[string]result `json:"neighborip,omitempty"`
ConnectedIP map[string]result `json:"connectedip,omitempty"`
ListeningPort map[string]result `json:"listeningport,omitempty"`
FoundAnything bool `json:"foundanything"`
Success bool `json:"success"`
Errors []string `json:"errors,omitempty"`
}

type result struct {
Item string `json:"item"`
Found bool `json:"found"`
LocalMACAddr string `json:"localmacaddr,omitempty"`
RemoteMACAddr string `json:"remotemacaddr,omitempty"`
LocalAddr string `json:"localaddr,omitempty"`
LocalPort string `json:"localport,omitempty"`
RemoteAddr string `json:"remoteaddr,omitempty"`
RemotePort string `json:"remoteport,omitempty"`
Found bool `json:"found"`
Elements []element `json:"element"`
}

type element struct {
LocalMACAddr string `json:"localmacaddr,omitempty"`
RemoteMACAddr string `json:"remotemacaddr,omitempty"`
LocalAddr string `json:"localaddr,omitempty"`
LocalPort float64 `json:"localport,omitempty"`
RemoteAddr string `json:"remoteaddr,omitempty"`
RemotePort float64 `json:"remoteport,omitempty"`
}

func newResults() *results {
var r results
r.LocalMAC = make(map[string]result)
r.LocalIP = make(map[string]result)
r.NeighborMAC = make(map[string]result)
r.NeighborIP = make(map[string]result)
r.ConnectedIP = make(map[string]result)
r.ListeningPort = make(map[string]result)
return &r
}

func (r Runner) ValidateParameters() (err error) {
Expand Down Expand Up @@ -123,7 +137,7 @@ func validateIP(val string) error {
func validatePort(val string) error {
port, err := strconv.Atoi(val)
if err != nil {
return err
return fmt.Errorf("%s is not a valid port", val)
}
if port < 0 || port > 65535 {
return fmt.Errorf("port out of range. must be between 1 and 65535")
Expand Down Expand Up @@ -152,58 +166,60 @@ func (r Runner) Run(args []byte) (resStr string) {
if err != nil {
panic(err)
}

r.Results = *newResults()

for _, val := range r.Parameters.LocalMAC {
var result result
result.Item = val
result.Found, result.LocalMACAddr, err = HasLocalMAC(val)
result.Found, result.Elements, err = HasLocalMAC(val)
if err != nil {
r.Results.Errors = append(r.Results.Errors, fmt.Sprintf("%v", err))
}
r.Results.LocalMAC = append(r.Results.LocalMAC, result)
r.Results.LocalMAC[val] = result
if result.Found {
r.Results.FoundAnything = true
}
}
for _, val := range r.Parameters.NeighborMAC {
var result result
result.Item = val
result.Found, result.RemoteMACAddr, result.RemoteAddr, err = HasSeenMac(val)
result.Found, result.Elements, err = HasSeenMac(val)
if err != nil {
r.Results.Errors = append(r.Results.Errors, fmt.Sprintf("%v", err))
}
r.Results.NeighborMAC = append(r.Results.NeighborMAC, result)
r.Results.NeighborMAC[val] = result
if result.Found {
r.Results.FoundAnything = true
}
}
for _, val := range r.Parameters.LocalIP {
var result result
result.Item = val
result.Found, result.LocalAddr, err = HasLocalIP(val)
result.Found, result.Elements, err = HasLocalIP(val)
if err != nil {
r.Results.Errors = append(r.Results.Errors, fmt.Sprintf("%v", err))
}
r.Results.LocalIP = append(r.Results.LocalIP, result)
r.Results.LocalIP[val] = result
if result.Found {
r.Results.FoundAnything = true
}
}
for _, val := range r.Parameters.ConnectedIP {
result, err := HasIPConnected(val)
var result result
result.Found, result.Elements, err = HasIPConnected(val)
if err != nil {
r.Results.Errors = append(r.Results.Errors, fmt.Sprintf("%v", err))
}
r.Results.ConnectedIP = append(r.Results.ConnectedIP, result)
r.Results.ConnectedIP[val] = result
if result.Found {
r.Results.FoundAnything = true
}
}
for _, val := range r.Parameters.ListeningPort {
result, err := HasListeningPort(val)
for _, port := range r.Parameters.ListeningPort {
var result result
result.Found, result.Elements, err = HasListeningPort(port)
if err != nil {
r.Results.Errors = append(r.Results.Errors, fmt.Sprintf("%v", err))
}
r.Results.ListeningPort = append(r.Results.ListeningPort, result)
r.Results.ListeningPort[port] = result
if result.Found {
r.Results.FoundAnything = true
}
Expand All @@ -218,60 +234,74 @@ func (r Runner) Run(args []byte) (resStr string) {
return
}

// HasLocalMac compares an input mac address with the mac addresses
// of the local interfaces, and returns found=true when found
func HasLocalMAC(macstr string) (found bool, addr string, err error) {
// HasLocalMac returns the mac addresses that match an input MAC regex
func HasLocalMAC(macstr string) (found bool, elements []element, err error) {
defer func() {
if e := recover(); e != nil {
err = fmt.Errorf("HasLocalMac() -> %v", e)
}
}()
found = false
re, err := regexp.Compile("(?i)" + macstr)
if err != nil {
return found, addr, err
panic(err)
}
ifaces, err := net.Interfaces()
if err != nil {
return found, addr, err
panic(err)
}
for _, iface := range ifaces {
if re.MatchString(iface.HardwareAddr.String()) {
found = true
addr = iface.HardwareAddr.String()
return found, addr, err
var el element
el.LocalMACAddr = iface.HardwareAddr.String()
elements = append(elements, el)
}
}
return found, addr, err
return
}

// HasLocalIP compares an input ip address with the ip addresses
// of the local interfaces, and returns found=true when found
func HasLocalIP(ipStr string) (found bool, addr string, err error) {
func HasLocalIP(ipStr string) (found bool, elements []element, err error) {
defer func() {
if e := recover(); e != nil {
err = fmt.Errorf("HasLocalIP() -> %v", e)
}
}()
found = false
if strings.IndexAny(ipStr, "/") > 0 {
_, ipnet, err := net.ParseCIDR(ipStr)
if err != nil {
return found, addr, err
panic(err)
}
ifaceAddrs, err := net.InterfaceAddrs()
if err != nil {
return found, addr, err
panic(err)
}
for _, ifaceAddr := range ifaceAddrs {
addr = strings.Split(ifaceAddr.String(), "/")[0]
addr := strings.Split(ifaceAddr.String(), "/")[0]
if ipnet.Contains(net.ParseIP(addr)) {
found = true
return found, addr, err
var el element
el.LocalAddr = addr
elements = append(elements, el)
}
}
return found, addr, err
return found, elements, err
}
ifaceAddrs, err := net.InterfaceAddrs()
if err != nil {
return found, addr, err
panic(err)
}
for _, ifaceAddr := range ifaceAddrs {
addr = strings.Split(ifaceAddr.String(), "/")[0]
addr := strings.Split(ifaceAddr.String(), "/")[0]
if ipStr == addr {
found = true
return found, addr, err
var el element
el.LocalAddr = addr
elements = append(elements, el)
}
}
return found, addr, err
return
}
25 changes: 17 additions & 8 deletions src/mig/modules/netstat/netstat_darwin.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,47 +17,56 @@ import (

// HasSeenMac on darwin looks at the output of `arp -a` for a matching mac address
// and returns its MAC and IP address if found
func HasSeenMac(val string) (found bool, macaddr, addr string, err error) {
func HasSeenMac(val string) (found bool, elements []element, err error) {
defer func() {
if e := recover(); e != nil {
err = fmt.Errorf("HasSeenMac() -> %v", e)
}
}()
found = false
out, err := exec.Command("arp", "-a").Output()
if err != nil {
return found, macaddr, addr, err
panic(err)
}
// arp -a has a static format:
// <Hostname> (<IP Address>) at <Mac Address> on <Interface> [ifscope <type>]
// fedbox (172.21.0.3) at 8c:70:5a:c8:be:50 on en1 ifscope [ethernet]
re, err := regexp.Compile(val)
if err != nil {
return found, macaddr, addr, err
panic(err)
}
buf := bytes.NewReader(out)
reader := bufio.NewReader(buf)
for {
lineBytes, _, err := reader.ReadLine()
if err != nil {
panic(err)
}
line := fmt.Sprintf("%s", lineBytes)
fields := strings.Fields(line)
if len(fields) < 4 {
continue
}
if re.MatchString(fields[3]) {
found = true
var el element
// remove heading and trailing parenthesis
if len(fields[1]) > 2 {
addr = fields[1][1 : len(fields[1])-1]
el.RemoteAddr = fields[1][1 : len(fields[1])-1]
}
macaddr = fields[3]
return found, macaddr, addr, err
el.RemoteMACAddr = fields[3]
elements = append(elements, el)
}
}
return
}

func HasIPConnected(val string) (r result, err error) {
func HasIPConnected(val string) (found bool, elements []element, err error) {
err = fmt.Errorf("HasIPConnected() is not implemented on %s", runtime.GOOS)
return
}

func HasListeningPort(val string) (r result, err error) {
func HasListeningPort(port string) (found bool, elements []element, err error) {
err = fmt.Errorf("HasListeningPort() is not implemented on %s", runtime.GOOS)
return
}
24 changes: 15 additions & 9 deletions src/mig/modules/netstat/netstat_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,18 +16,24 @@ import (

// HasSeenMac on linux looks for a matching mac address in /proc/net/arp
// and returns its MAC and IP address if found
func HasSeenMac(val string) (found bool, macaddr, addr string, err error) {
func HasSeenMac(val string) (found bool, elements []element, err error) {
defer func() {
if e := recover(); e != nil {
err = fmt.Errorf("HasSeenMac() -> %v", e)
}
}()
found = false
fd, err := os.Open("/proc/net/arp")
defer fd.Close()
if err != nil {
return found, macaddr, addr, err
panic(err)
}
// /proc/net/arp has a static format:
// IP address HW type Flags HW address Mask Device
// we split the string on fields, and compare field #4 with our search regex
re, err := regexp.Compile(val)
if err != nil {
return found, macaddr, addr, err
panic(err)
}
scanner := bufio.NewScanner(fd)
scanner.Scan() // skip the header
Expand All @@ -41,21 +47,21 @@ func HasSeenMac(val string) (found bool, macaddr, addr string, err error) {
}
if re.MatchString(fields[3]) {
found = true
addr = fields[0]
macaddr = fields[3]
return found, macaddr, addr, err
var el element
el.RemoteAddr = fields[0]
el.RemoteMACAddr = fields[3]
elements = append(elements, el)
}
}
fd.Close()
return
}

func HasIPConnected(val string) (r result, err error) {
func HasIPConnected(val string) (found bool, elements []element, err error) {
err = fmt.Errorf("HasIPConnected() is not implemented on %s", runtime.GOOS)
return
}

func HasListeningPort(val string) (r result, err error) {
func HasListeningPort(port string) (found bool, elements []element, err error) {
err = fmt.Errorf("HasListeningPort() is not implemented on %s", runtime.GOOS)
return
}
Loading

0 comments on commit 49498bf

Please sign in to comment.