Skip to content

Commit

Permalink
first
Browse files Browse the repository at this point in the history
  • Loading branch information
hdhog committed Oct 3, 2016
0 parents commit bfc8239
Show file tree
Hide file tree
Showing 5 changed files with 303 additions and 0 deletions.
15 changes: 15 additions & 0 deletions .drone.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
workspace:
base: /go
pipeline:
build:
image: golang:${GO_VERSION}
commands:
- go get -v
- go test -v
- go build -v
matrix:
GO_VERSION:
- 1.7
GO_ARCH:
- amd64
- 386
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
*.exe
gocdp
44 changes: 44 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# GoCDP

Show CDP over snmp

Example run:

```bash
gocdp nei -s 10.0.0.1
```
Command line help
```bash
NAME:
gocdp - show CDP by snmp

USAGE:
gocdp [global options] command [command options] [arguments...]

VERSION:
1.0.3

AUTHOR(S):
hdhog <[email protected]>

COMMANDS:
neigbors, n, nei Show CDP neigbors by snmp
help, h Shows a list of commands or help for one command

GLOBAL OPTIONS:
--help, -h show help
--version, -v print the version

```
```bash
NAME:
gocdp neigbors - Show CDP neigbors by snmp

USAGE:
gocdp neigbors [command options] [arguments...]

OPTIONS:
--community value, -c value community string (default: "public")
--host value, -s value host address

```
216 changes: 216 additions & 0 deletions main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,216 @@
package main

import (
"fmt"
"net"
"os"
"sort"
"strings"

"github.com/k-sone/snmpgo"
"github.com/olekukonko/tablewriter"
"github.com/urfave/cli"
)

const (
oidSysName = "1.3.6.1.2.1.1.5"
oidIfDescr = "1.3.6.1.2.1.2.2.1.2"
oidCDPCacheEntry = "1.3.6.1.4.1.9.9.23.1.2.1.1"
oidCDPCacheDeviceid = "1.3.6.1.4.1.9.9.23.1.2.1.1.6"
oidCDPCacheDevicePort = "1.3.6.1.4.1.9.9.23.1.2.1.1.7"
oidCDPCacheAddress = "1.3.6.1.4.1.9.9.23.1.2.1.1.4"
cacheAddress = 4
cacheDeviceid = 6
cacheDevicePort = 7
)

// Информация о версии приложения
var (
Version = "0.0.1"
)

type cdpNeighbor struct {
LName string
LIP string
LIfName string
RName string
RIP string
RIfName string
}

func compactIfName(ifname string) string {
if strings.HasPrefix(ifname, "Ten") {
return strings.Replace(ifname, "TenGigabitEthernet", "Te ", -1)
}
if strings.HasPrefix(ifname, "Gig") {
return strings.Replace(ifname, "GigabitEthernet", "Gi ", -1)
}
if strings.HasPrefix(ifname, "Fas") {
return strings.Replace(ifname, "FastEthernet", "Fa ", -1)
}
return ifname
}

func prepareOids() (snmpgo.Oids, error) {
return snmpgo.NewOids([]string{
oidCDPCacheDeviceid,
oidCDPCacheDevicePort,
oidCDPCacheAddress,
oidIfDescr,
oidSysName,
})
}

func getCDPNeighbors(host, community string) (map[string]cdpNeighbor, error) {
nei := map[string]cdpNeighbor{}

snmpAddr := net.JoinHostPort(host, "161")

snmp, err := snmpgo.NewSNMP(snmpgo.SNMPArguments{
Version: snmpgo.V2c,
Address: snmpAddr,
Retries: 1,
Community: community,
})

if err != nil {
return nil, err
}

cacheEntry, err := prepareOids()

if err != nil {
return nil, err
}

if err = snmp.Open(); err != nil {
return nil, err
}
defer snmp.Close()

pdu, err := snmp.GetBulkWalk(cacheEntry, 0, 10)
if err != nil {
return nil, err
}

if pdu.ErrorStatus() != snmpgo.NoError {
fmt.Println(pdu.ErrorStatus(), pdu.ErrorIndex())
}

oid, err := snmpgo.NewOid(oidCDPCacheEntry)
if err != nil {
return nil, err
}
cacheEntrys := pdu.VarBinds().MatchBaseOids(oid)
sysName := pdu.VarBinds().MatchBaseOids(snmpgo.MustNewOid(oidSysName))[0]

for _, val := range cacheEntrys {
ifindex := fmt.Sprintf("%d", val.Oid.Value[14])
if _, ok := nei[ifindex]; !ok {
oid, err = snmpgo.NewOid(oidIfDescr + "." + ifindex)
if err != nil {
return nil, err
}
ifnames := pdu.VarBinds().MatchBaseOids(oid)
rifname := ifnames.MatchOid(oid).Variable.String()
nei[ifindex] = cdpNeighbor{
RIfName: compactIfName(rifname),
}
}

cdp := nei[ifindex]
cdp.RName = sysName.Variable.String()
cdp.RIP = host

switch val.Oid.Value[13] {
case cacheAddress:
cdp.LIP = val.Variable.String()
var ip, ip1, ip2, ip3 int
fmt.Sscanf(val.Variable.String(), "%x:%x:%x:%x", &ip, &ip1, &ip2, &ip3)
cdp.LIP = fmt.Sprintf("%d.%d.%d.%d", ip, ip1, ip2, ip3)
case cacheDeviceid:
cdp.LName = val.Variable.String()
case cacheDevicePort:
cdp.LIfName = compactIfName(val.Variable.String())
}

nei[ifindex] = cdp
}

return nei, nil
}

func printTable(neigbors map[string]cdpNeighbor) {
table := tablewriter.NewWriter(os.Stdout)
table.SetHeader([]string{"Name", "IP", "Local IF", "--", "Remote IF", "Remote IP", "Remote Name"})
table.SetBorder(false)
var data [][]string
var keys []string
for k := range neigbors {
keys = append(keys, k)
}
sort.Strings(keys)

for _, k := range keys {
v := neigbors[k]
data = append(data, []string{v.RName, v.RIP, v.RIfName, "->", v.LIfName, v.LIP, v.LName})
}
table.SetAlignment(4)
table.AppendBulk(data)
table.Render()
}

func neighbors(c *cli.Context) error {
community := c.String("community")
host := c.String("host")
if host == "" {
if err := cli.ShowCommandHelp(c, "neigbors"); err != nil {
return err
}
return cli.NewExitError("Host address required", 1)
}
res, err := getCDPNeighbors(host, community)
if err != nil {
return cli.NewExitError(err.Error(), 1)
}
printTable(res)

return nil
}

func main() {
app := cli.NewApp()
app.Name = "gocdp"
app.Usage = "show CDP by snmp"
app.Version = Version
app.Authors = []cli.Author{
cli.Author{
Name: "hdhog",
Email: "[email protected]",
},
}
app.Commands = []cli.Command{
{
Name: "neigbors",
Aliases: []string{"n", "nei"},
Usage: "Show CDP neigbors over snmp",
Flags: []cli.Flag{
cli.StringFlag{
Name: "community, c",
Value: "public",
Usage: "community string",
},
cli.StringFlag{
Name: "host ,s",
Usage: "host address",
},
},
Action: neighbors,
},
}

if err := app.Run(os.Args); err != nil {
fmt.Println(err)
os.Exit(1)
}
}
26 changes: 26 additions & 0 deletions main_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package main

import "testing"

func Test_compactIfName(t *testing.T) {
t.Run("Ifname", func(t *testing.T) {
t.Run("FastEthernet", func(t *testing.T) {
data := compactIfName("FastEthernet0/1")
if data != "Fa 0/1" {
t.Error("Error compaction ifname")
}
})
t.Run("GigabitEthernet", func(t *testing.T) {
data := compactIfName("GigabitEthernet0/1")
if data != "Gi 0/1" {
t.Error("Error compaction ifname")
}
})
t.Run("TenGigabitEthernet", func(t *testing.T) {
data := compactIfName("TenGigabitEthernet0/1")
if data != "Te 0/1" {
t.Error("Error compaction ifname")
}
})
})
}

0 comments on commit bfc8239

Please sign in to comment.