bosun.org@v0.0.0-20210513094433-e25bc3e69a1f/cmd/scollector/collectors/snmp_ips.go (about)

     1  package collectors
     2  
     3  import (
     4  	"encoding/json"
     5  	"fmt"
     6  	"net"
     7  	"sort"
     8  	"strings"
     9  	"time"
    10  
    11  	"bosun.org/cmd/scollector/conf"
    12  	"bosun.org/metadata"
    13  	"bosun.org/opentsdb"
    14  	"bosun.org/slog"
    15  )
    16  
    17  const ifIPAdEntAddr = ".1.3.6.1.2.1.4.20.1"
    18  
    19  // SNMPIfaces registers a SNMP Interfaces collector for the given community and host.
    20  func SNMPIPAddresses(cfg conf.SNMP) {
    21  	collectors = append(collectors, &IntervalCollector{
    22  		F: func() (opentsdb.MultiDataPoint, error) {
    23  			return c_snmp_ips(cfg.Community, cfg.Host)
    24  		},
    25  		Interval: time.Minute * 1,
    26  		name:     fmt.Sprintf("snmp-ips-%s", cfg.Host),
    27  	})
    28  }
    29  
    30  type ipAdEntAddr struct {
    31  	InterfaceId int64
    32  	net.IPNet
    33  }
    34  
    35  func c_snmp_ips(community, host string) (opentsdb.MultiDataPoint, error) {
    36  	ifIPAdEntAddrRaw, err := snmp_subtree(host, community, ifIPAdEntAddr)
    37  	if err != nil {
    38  		return nil, err
    39  	}
    40  	ipAdEnts := make(map[string]*ipAdEntAddr)
    41  	for id, value := range ifIPAdEntAddrRaw {
    42  		// Split entry type id from ip address
    43  		sp := strings.SplitN(id, ".", 2)
    44  		if len(sp) != 2 {
    45  			slog.Errorln("unexpected length of snmp resonse")
    46  		}
    47  		typeId := sp[0]
    48  		address := sp[1]
    49  		if _, ok := ipAdEnts[address]; !ok {
    50  			ipAdEnts[address] = &ipAdEntAddr{}
    51  		}
    52  		switch typeId {
    53  		case "1":
    54  			if v, ok := value.([]byte); ok {
    55  				ipAdEnts[address].IP = v
    56  			}
    57  		case "2":
    58  			if v, ok := value.(int64); ok {
    59  				ipAdEnts[address].InterfaceId = v
    60  			}
    61  		case "3":
    62  			if v, ok := value.([]byte); ok {
    63  				ipAdEnts[address].Mask = v
    64  			}
    65  		}
    66  	}
    67  	ipsByInt := make(map[int64][]net.IPNet)
    68  	for _, ipNet := range ipAdEnts {
    69  		ipsByInt[ipNet.InterfaceId] = append(ipsByInt[ipNet.InterfaceId], ipNet.IPNet)
    70  	}
    71  	for intId, ipNets := range ipsByInt {
    72  		var ips []string
    73  		for _, ipNet := range ipNets {
    74  			ips = append(ips, ipNet.String())
    75  		}
    76  		sort.Strings(ips)
    77  		j, err := json.Marshal(ips)
    78  		if err != nil {
    79  			slog.Errorf("error marshaling ips for host %v: %v", host, err)
    80  		}
    81  		metadata.AddMeta("", opentsdb.TagSet{"host": host, "iface": fmt.Sprintf("%v", intId)}, "addresses", string(j), false)
    82  	}
    83  	return nil, nil
    84  }