Fetch device list

This commit is contained in:
Ian Gulliver
2020-07-26 18:05:48 +00:00
parent c1f41b038b
commit 57778feb75
2 changed files with 97 additions and 4 deletions

17
main.go
View File

@@ -25,7 +25,7 @@ func main() {
}
log.Printf("Network interface: %s", link.Attrs().Name)
api, err := findApi(link)
api, err := findAPI(link)
if err != nil {
log.Fatal(err)
}
@@ -48,6 +48,15 @@ func main() {
if err != nil {
log.Fatal(err)
}
devices, err := unifi.ListDevices()
if err != nil {
log.Fatal(err)
}
for _, dev := range devices {
log.Printf("%#v", dev)
}
}
type upstream struct {
@@ -102,7 +111,7 @@ func getUpstream(intName string) (*upstream, error) {
return ret, nil
}
func findApi(link netlink.Link) (string, error) {
func findAPI(link netlink.Link) (string, error) {
addrs, err := netlink.AddrList(link, 2 /* AF_INET */)
if err != nil {
return "", err
@@ -116,7 +125,7 @@ func findApi(link netlink.Link) (string, error) {
start := ip & mask
end := ip | (^mask & 0xffffffff)
addr_apis, err := findApis(start, end)
addr_apis, err := findAPIs(start, end)
if err != nil {
return "", err
}
@@ -135,7 +144,7 @@ func findApi(link netlink.Link) (string, error) {
return apis[0], nil
}
func findApis(start_ip, end_ip uint32) ([]string, error) {
func findAPIs(start_ip, end_ip uint32) ([]string, error) {
wg := sync.WaitGroup{}
wg.Add(int(end_ip - start_ip + 1))

View File

@@ -22,6 +22,32 @@ type Client struct {
base_url string
}
type Device struct {
// Fields directly from UniFi
Name string `json:"name"`
MAC string `json:"mac"`
// Constructed fields
Neighbors map[string]*Device
// Intermediate data; ignore
Ports []*Port `json:"port_table"`
}
type Port struct {
LLDP []*LLDP `json:"lldp_table"`
}
type LLDP struct {
MAC string `json:"lldp_chassis_id"`
Port string `json:"lldp_port_id"`
Name string `json:"lldp_system_name"`
}
type DeviceResp struct {
Data []*Device `json:"data"`
}
func NewClient(base_url string) (*Client, error) {
jar, err := cookiejar.New(nil)
if err != nil {
@@ -69,6 +95,9 @@ func (c *Client) Login() error {
}
req, err := http.NewRequest("POST", fmt.Sprintf("%s/api/auth/login", c.base_url), bytes.NewBuffer(body))
if err != nil {
return err
}
req.Header.Set("Content-Type", "application/json")
resp, err := c.http_client.Do(req)
@@ -99,6 +128,61 @@ func (c *Client) Login() error {
return nil
}
func (c *Client) ListDevices() (map[string]*Device, error) {
req, err := http.NewRequest("GET", fmt.Sprintf("%s/proxy/network/api/s/default/stat/device", c.base_url), nil)
resp, err := c.http_client.Do(req)
if err != nil {
return nil, err
}
defer resp.Body.Close()
if resp.StatusCode != 200 {
dec := json.NewDecoder(resp.Body)
error_resp := ErrorResp{}
err = dec.Decode(&error_resp)
if err != nil {
return nil, err
}
return nil, fmt.Errorf("%s", error_resp.Errors[0])
}
dec := json.NewDecoder(resp.Body)
device_resp := DeviceResp{}
err = dec.Decode(&device_resp)
if err != nil {
return nil, err
}
ret := map[string]*Device{}
for _, dev := range device_resp.Data {
dev.MAC = strings.ToUpper(dev.MAC)
ret[dev.MAC] = dev
}
// Second loop after the table is populated
for _, dev := range ret {
dev.Neighbors = map[string]*Device{}
for _, port := range dev.Ports {
for _, lldp := range port.LLDP {
lldp.MAC = strings.ToUpper(lldp.MAC)
neighbor := ret[lldp.MAC]
if neighbor == nil {
continue
}
dev.Neighbors[neighbor.MAC] = neighbor
}
}
dev.Ports = nil
}
return ret, nil
}
func loadCreds() (*Creds, error) {
fh, err := os.OpenFile(credPath(), os.O_RDONLY, 0)
if err != nil {