mirror of
				https://github.com/prometheus/node_exporter.git
				synced 2025-08-20 18:33:52 -07:00 
			
		
		
		
	Update vendored wifi, handle stations with missing info
This commit is contained in:
		
							parent
							
								
									92537020a3
								
							
						
					
					
						commit
						ca3f07feef
					
				| 
						 | 
				
			
			@ -155,12 +155,6 @@ func (c *wifiCollector) Update(ch chan<- prometheus.Metric) error {
 | 
			
		|||
			continue
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		info, err := stat.StationInfo(ifi)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return fmt.Errorf("failed to retrieve station info for device %s: %v",
 | 
			
		||||
				ifi.Name, err)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		ch <- prometheus.MustNewConstMetric(
 | 
			
		||||
			c.InterfaceFrequencyHertz,
 | 
			
		||||
			prometheus.GaugeValue,
 | 
			
		||||
| 
						 | 
				
			
			@ -168,6 +162,16 @@ func (c *wifiCollector) Update(ch chan<- prometheus.Metric) error {
 | 
			
		|||
			ifi.Name,
 | 
			
		||||
		)
 | 
			
		||||
 | 
			
		||||
		info, err := stat.StationInfo(ifi)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			if os.IsNotExist(err) {
 | 
			
		||||
				continue
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			return fmt.Errorf("failed to retrieve station info for device %s: %v",
 | 
			
		||||
				ifi.Name, err)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		c.updateStationStats(ch, ifi.Name, info)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										13
									
								
								vendor/github.com/mdlayher/wifi/client.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										13
									
								
								vendor/github.com/mdlayher/wifi/client.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| 
						 | 
				
			
			@ -2,12 +2,19 @@ package wifi
 | 
			
		|||
 | 
			
		||||
import (
 | 
			
		||||
	"errors"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"runtime"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
var (
 | 
			
		||||
	// errNotStation is returned when attempting to query station info for
 | 
			
		||||
	// an interface which is not a station.
 | 
			
		||||
	errNotStation = errors.New("interface is not a station")
 | 
			
		||||
 | 
			
		||||
	// errUnimplemented is returned by all functions on platforms that
 | 
			
		||||
	// do not have package wifi implemented.
 | 
			
		||||
	errUnimplemented = fmt.Errorf("package wifi not implemented on %s/%s",
 | 
			
		||||
		runtime.GOOS, runtime.GOARCH)
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// A Client is a type which can access WiFi device actions and statistics
 | 
			
		||||
| 
						 | 
				
			
			@ -38,6 +45,11 @@ func (c *Client) Interfaces() ([]*Interface, error) {
 | 
			
		|||
	return c.c.Interfaces()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// BSS retrieves the BSS associated with a WiFi interface.
 | 
			
		||||
func (c *Client) BSS(ifi *Interface) (*BSS, error) {
 | 
			
		||||
	return c.c.BSS(ifi)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// StationInfo retrieves statistics about a WiFi interface operating in
 | 
			
		||||
// station mode.
 | 
			
		||||
func (c *Client) StationInfo(ifi *Interface) (*StationInfo, error) {
 | 
			
		||||
| 
						 | 
				
			
			@ -52,5 +64,6 @@ func (c *Client) StationInfo(ifi *Interface) (*StationInfo, error) {
 | 
			
		|||
type osClient interface {
 | 
			
		||||
	Close() error
 | 
			
		||||
	Interfaces() ([]*Interface, error)
 | 
			
		||||
	BSS(ifi *Interface) (*BSS, error)
 | 
			
		||||
	StationInfo(ifi *Interface) (*StationInfo, error)
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										158
									
								
								vendor/github.com/mdlayher/wifi/client_linux.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										158
									
								
								vendor/github.com/mdlayher/wifi/client_linux.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| 
						 | 
				
			
			@ -3,11 +3,13 @@
 | 
			
		|||
package wifi
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"bytes"
 | 
			
		||||
	"errors"
 | 
			
		||||
	"math"
 | 
			
		||||
	"net"
 | 
			
		||||
	"os"
 | 
			
		||||
	"time"
 | 
			
		||||
	"unicode/utf8"
 | 
			
		||||
 | 
			
		||||
	"github.com/mdlayher/netlink"
 | 
			
		||||
	"github.com/mdlayher/netlink/genetlink"
 | 
			
		||||
| 
						 | 
				
			
			@ -96,10 +98,40 @@ func (c *client) Interfaces() ([]*Interface, error) {
 | 
			
		|||
	return parseInterfaces(msgs)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// BSS requests that nl80211 return the BSS for the specified Interface.
 | 
			
		||||
func (c *client) BSS(ifi *Interface) (*BSS, error) {
 | 
			
		||||
	b, err := netlink.MarshalAttributes(ifi.idAttrs())
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Ask nl80211 to retrieve BSS information for the interface specified
 | 
			
		||||
	// by its attributes
 | 
			
		||||
	req := genetlink.Message{
 | 
			
		||||
		Header: genetlink.Header{
 | 
			
		||||
			Command: nl80211.CmdGetScan,
 | 
			
		||||
			Version: c.familyVersion,
 | 
			
		||||
		},
 | 
			
		||||
		Data: b,
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	flags := netlink.HeaderFlagsRequest | netlink.HeaderFlagsDump
 | 
			
		||||
	msgs, err := c.c.Execute(req, c.familyID, flags)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if err := c.checkMessages(msgs, nl80211.CmdNewScanResults); err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return parseBSS(msgs)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// StationInfo requests that nl80211 return station info for the specified
 | 
			
		||||
// Interface.
 | 
			
		||||
func (c *client) StationInfo(ifi *Interface) (*StationInfo, error) {
 | 
			
		||||
	b, err := netlink.MarshalAttributes(ifi.stationInfoAttrs())
 | 
			
		||||
	b, err := netlink.MarshalAttributes(ifi.idAttrs())
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -176,9 +208,9 @@ func parseInterfaces(msgs []genetlink.Message) ([]*Interface, error) {
 | 
			
		|||
	return ifis, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// stationInfoAttrs returns the netlink attributes required from an Interface
 | 
			
		||||
// to retrieve a StationInfo.
 | 
			
		||||
func (ifi *Interface) stationInfoAttrs() []netlink.Attribute {
 | 
			
		||||
// idAttrs returns the netlink attributes required from an Interface to retrieve
 | 
			
		||||
// more data about it.
 | 
			
		||||
func (ifi *Interface) idAttrs() []netlink.Attribute {
 | 
			
		||||
	return []netlink.Attribute{
 | 
			
		||||
		{
 | 
			
		||||
			Type: nl80211.AttrIfindex,
 | 
			
		||||
| 
						 | 
				
			
			@ -217,6 +249,80 @@ func (ifi *Interface) parseAttributes(attrs []netlink.Attribute) error {
 | 
			
		|||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// parseBSS parses a single BSS with a status attribute from nl80211 BSS messages.
 | 
			
		||||
func parseBSS(msgs []genetlink.Message) (*BSS, error) {
 | 
			
		||||
	for _, m := range msgs {
 | 
			
		||||
		attrs, err := netlink.UnmarshalAttributes(m.Data)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		for _, a := range attrs {
 | 
			
		||||
			if a.Type != nl80211.AttrBss {
 | 
			
		||||
				continue
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			nattrs, err := netlink.UnmarshalAttributes(a.Data)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				return nil, err
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			// The BSS which is associated with an interface will have a status
 | 
			
		||||
			// attribute
 | 
			
		||||
			if !attrsContain(nattrs, nl80211.BssStatus) {
 | 
			
		||||
				continue
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			var bss BSS
 | 
			
		||||
			if err := (&bss).parseAttributes(nattrs); err != nil {
 | 
			
		||||
				return nil, err
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			return &bss, nil
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return nil, os.ErrNotExist
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// parseAttributes parses netlink attributes into a BSS's fields.
 | 
			
		||||
func (b *BSS) parseAttributes(attrs []netlink.Attribute) error {
 | 
			
		||||
	for _, a := range attrs {
 | 
			
		||||
		switch a.Type {
 | 
			
		||||
		case nl80211.BssBssid:
 | 
			
		||||
			b.BSSID = net.HardwareAddr(a.Data)
 | 
			
		||||
		case nl80211.BssFrequency:
 | 
			
		||||
			b.Frequency = int(nlenc.Uint32(a.Data))
 | 
			
		||||
		case nl80211.BssBeaconInterval:
 | 
			
		||||
			// Raw value is in "Time Units (TU)".  See:
 | 
			
		||||
			// https://en.wikipedia.org/wiki/Beacon_frame
 | 
			
		||||
			b.BeaconInterval = time.Duration(nlenc.Uint16(a.Data)) * 1024 * time.Microsecond
 | 
			
		||||
		case nl80211.BssSeenMsAgo:
 | 
			
		||||
			// * @NL80211_BSS_SEEN_MS_AGO: age of this BSS entry in ms
 | 
			
		||||
			b.LastSeen = time.Duration(nlenc.Uint32(a.Data)) * time.Millisecond
 | 
			
		||||
		case nl80211.BssStatus:
 | 
			
		||||
			// NOTE: BSSStatus copies the ordering of nl80211's BSS status
 | 
			
		||||
			// constants.  This may not be the case on other operating systems.
 | 
			
		||||
			b.Status = BSSStatus(nlenc.Uint32(a.Data))
 | 
			
		||||
		case nl80211.BssInformationElements:
 | 
			
		||||
			ies, err := parseIEs(a.Data)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				return err
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			// TODO(mdlayher): return more IEs if they end up being generally useful
 | 
			
		||||
			for _, ie := range ies {
 | 
			
		||||
				switch ie.ID {
 | 
			
		||||
				case ieSSID:
 | 
			
		||||
					b.SSID = decodeSSID(ie.Data)
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// parseStationInfo parses StationInfo attributes from a byte slice of
 | 
			
		||||
// netlink attributes.
 | 
			
		||||
func parseStationInfo(b []byte) (*StationInfo, error) {
 | 
			
		||||
| 
						 | 
				
			
			@ -262,23 +368,23 @@ func (info *StationInfo) parseAttributes(attrs []netlink.Attribute) error {
 | 
			
		|||
			// * @NL80211_STA_INFO_INACTIVE_TIME: time since last activity (u32, msecs)
 | 
			
		||||
			info.Inactive = time.Duration(nlenc.Uint32(a.Data)) * time.Millisecond
 | 
			
		||||
		case nl80211.StaInfoRxBytes64:
 | 
			
		||||
			info.ReceivedBytes = nlenc.Uint64(a.Data)
 | 
			
		||||
			info.ReceivedBytes = int(nlenc.Uint64(a.Data))
 | 
			
		||||
		case nl80211.StaInfoTxBytes64:
 | 
			
		||||
			info.TransmittedBytes = nlenc.Uint64(a.Data)
 | 
			
		||||
			info.TransmittedBytes = int(nlenc.Uint64(a.Data))
 | 
			
		||||
		case nl80211.StaInfoSignal:
 | 
			
		||||
			// Converted into the typical negative strength format
 | 
			
		||||
			//  * @NL80211_STA_INFO_SIGNAL: signal strength of last received PPDU (u8, dBm)
 | 
			
		||||
			info.Signal = int(a.Data[0]) - math.MaxUint8
 | 
			
		||||
		case nl80211.StaInfoRxPackets:
 | 
			
		||||
			info.ReceivedPackets = nlenc.Uint32(a.Data)
 | 
			
		||||
			info.ReceivedPackets = int(nlenc.Uint32(a.Data))
 | 
			
		||||
		case nl80211.StaInfoTxPackets:
 | 
			
		||||
			info.TransmittedPackets = nlenc.Uint32(a.Data)
 | 
			
		||||
			info.TransmittedPackets = int(nlenc.Uint32(a.Data))
 | 
			
		||||
		case nl80211.StaInfoTxRetries:
 | 
			
		||||
			info.TransmitRetries = nlenc.Uint32(a.Data)
 | 
			
		||||
			info.TransmitRetries = int(nlenc.Uint32(a.Data))
 | 
			
		||||
		case nl80211.StaInfoTxFailed:
 | 
			
		||||
			info.TransmitFailed = nlenc.Uint32(a.Data)
 | 
			
		||||
			info.TransmitFailed = int(nlenc.Uint32(a.Data))
 | 
			
		||||
		case nl80211.StaInfoBeaconLoss:
 | 
			
		||||
			info.BeaconLoss = nlenc.Uint32(a.Data)
 | 
			
		||||
			info.BeaconLoss = int(nlenc.Uint32(a.Data))
 | 
			
		||||
		case nl80211.StaInfoRxBitrate, nl80211.StaInfoTxBitrate:
 | 
			
		||||
			rate, err := parseRateInfo(a.Data)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
| 
						 | 
				
			
			@ -299,10 +405,10 @@ func (info *StationInfo) parseAttributes(attrs []netlink.Attribute) error {
 | 
			
		|||
		// If the 64-bit counters appear later in the slice, they will overwrite
 | 
			
		||||
		// these values.
 | 
			
		||||
		if info.ReceivedBytes == 0 && a.Type == nl80211.StaInfoRxBytes {
 | 
			
		||||
			info.ReceivedBytes = uint64(nlenc.Uint32(a.Data))
 | 
			
		||||
			info.ReceivedBytes = int(nlenc.Uint32(a.Data))
 | 
			
		||||
		}
 | 
			
		||||
		if info.TransmittedBytes == 0 && a.Type == nl80211.StaInfoTxBytes {
 | 
			
		||||
			info.TransmittedBytes = uint64(nlenc.Uint32(a.Data))
 | 
			
		||||
			info.TransmittedBytes = int(nlenc.Uint32(a.Data))
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -345,6 +451,32 @@ func parseRateInfo(b []byte) (*rateInfo, error) {
 | 
			
		|||
	return &info, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// attrsContain checks if a slice of netlink attributes contains an attribute
 | 
			
		||||
// with the specified type.
 | 
			
		||||
func attrsContain(attrs []netlink.Attribute, typ uint16) bool {
 | 
			
		||||
	for _, a := range attrs {
 | 
			
		||||
		if a.Type == typ {
 | 
			
		||||
			return true
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return false
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// decodeSSID safely parses a byte slice into UTF-8 runes, and returns the
 | 
			
		||||
// resulting string from the runes.
 | 
			
		||||
func decodeSSID(b []byte) string {
 | 
			
		||||
	buf := bytes.NewBuffer(nil)
 | 
			
		||||
	for len(b) > 0 {
 | 
			
		||||
		r, size := utf8.DecodeRune(b)
 | 
			
		||||
		b = b[size:]
 | 
			
		||||
 | 
			
		||||
		buf.WriteRune(r)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return buf.String()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var _ genl = &sysGENL{}
 | 
			
		||||
 | 
			
		||||
// sysGENL is the system implementation of genl, using generic netlink.
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										17
									
								
								vendor/github.com/mdlayher/wifi/client_others.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										17
									
								
								vendor/github.com/mdlayher/wifi/client_others.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| 
						 | 
				
			
			@ -2,18 +2,6 @@
 | 
			
		|||
 | 
			
		||||
package wifi
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"runtime"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
var (
 | 
			
		||||
	// errUnimplemented is returned by all functions on platforms that
 | 
			
		||||
	// do not have package wifi implemented.
 | 
			
		||||
	errUnimplemented = fmt.Errorf("package wifi not implemented on %s/%s",
 | 
			
		||||
		runtime.GOOS, runtime.GOARCH)
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
var _ osClient = &client{}
 | 
			
		||||
 | 
			
		||||
// A conn is the no-op implementation of a netlink sockets connection.
 | 
			
		||||
| 
						 | 
				
			
			@ -34,6 +22,11 @@ func (c *client) Interfaces() ([]*Interface, error) {
 | 
			
		|||
	return nil, errUnimplemented
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// BSS always returns an error.
 | 
			
		||||
func (c *client) BSS(ifi *Interface) (*BSS, error) {
 | 
			
		||||
	return nil, errUnimplemented
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// StationInfo always returns an error.
 | 
			
		||||
func (c *client) StationInfo(ifi *Interface) (*StationInfo, error) {
 | 
			
		||||
	return nil, errUnimplemented
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										119
									
								
								vendor/github.com/mdlayher/wifi/wifi.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										119
									
								
								vendor/github.com/mdlayher/wifi/wifi.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| 
						 | 
				
			
			@ -1,10 +1,17 @@
 | 
			
		|||
package wifi
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"errors"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"net"
 | 
			
		||||
	"time"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
var (
 | 
			
		||||
	// errInvalidIE is returned when one or more IEs are malformed.
 | 
			
		||||
	errInvalidIE = errors.New("invalid 802.11 information element")
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// An InterfaceType is the operating mode of an Interface.
 | 
			
		||||
type InterfaceType int
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -96,16 +103,16 @@ type StationInfo struct {
 | 
			
		|||
	Inactive time.Duration
 | 
			
		||||
 | 
			
		||||
	// The number of bytes received by this station.
 | 
			
		||||
	ReceivedBytes uint64
 | 
			
		||||
	ReceivedBytes int
 | 
			
		||||
 | 
			
		||||
	// The number of bytes transmitted by this station.
 | 
			
		||||
	TransmittedBytes uint64
 | 
			
		||||
	TransmittedBytes int
 | 
			
		||||
 | 
			
		||||
	// The number of packets received by this station.
 | 
			
		||||
	ReceivedPackets uint32
 | 
			
		||||
	ReceivedPackets int
 | 
			
		||||
 | 
			
		||||
	// The number of packets transmitted by this station.
 | 
			
		||||
	TransmittedPackets uint32
 | 
			
		||||
	TransmittedPackets int
 | 
			
		||||
 | 
			
		||||
	// The current data receive bitrate, in bits/second.
 | 
			
		||||
	ReceiveBitrate int
 | 
			
		||||
| 
						 | 
				
			
			@ -117,11 +124,109 @@ type StationInfo struct {
 | 
			
		|||
	Signal int
 | 
			
		||||
 | 
			
		||||
	// The number of times the station has had to retry while sending a packet.
 | 
			
		||||
	TransmitRetries uint32
 | 
			
		||||
	TransmitRetries int
 | 
			
		||||
 | 
			
		||||
	// The number of times a packet transmission failed.
 | 
			
		||||
	TransmitFailed uint32
 | 
			
		||||
	TransmitFailed int
 | 
			
		||||
 | 
			
		||||
	// The number of times a beacon loss was detected.
 | 
			
		||||
	BeaconLoss uint32
 | 
			
		||||
	BeaconLoss int
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// A BSS is an 802.11 basic service set.  It contains information about a wireless
 | 
			
		||||
// network associated with an Interface.
 | 
			
		||||
type BSS struct {
 | 
			
		||||
	// The service set identifier, or "network name" of the BSS.
 | 
			
		||||
	SSID string
 | 
			
		||||
 | 
			
		||||
	// The BSS service set identifier.  In infrastructure mode, this is the
 | 
			
		||||
	// hardware address of the wireless access point that a client is associated
 | 
			
		||||
	// with.
 | 
			
		||||
	BSSID net.HardwareAddr
 | 
			
		||||
 | 
			
		||||
	// The frequency used by the BSS, in MHz.
 | 
			
		||||
	Frequency int
 | 
			
		||||
 | 
			
		||||
	// The interval between beacon transmissions for this BSS.
 | 
			
		||||
	BeaconInterval time.Duration
 | 
			
		||||
 | 
			
		||||
	// The time since the client last scanned this BSS's information.
 | 
			
		||||
	LastSeen time.Duration
 | 
			
		||||
 | 
			
		||||
	// The status of the client within the BSS.
 | 
			
		||||
	Status BSSStatus
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// A BSSStatus indicates the current status of client within a BSS.
 | 
			
		||||
type BSSStatus int
 | 
			
		||||
 | 
			
		||||
const (
 | 
			
		||||
	// BSSStatusAuthenticated indicates that a client is authenticated with a BSS.
 | 
			
		||||
	BSSStatusAuthenticated BSSStatus = iota
 | 
			
		||||
 | 
			
		||||
	// BSSStatusAssociated indicates that a client is associated with a BSS.
 | 
			
		||||
	BSSStatusAssociated
 | 
			
		||||
 | 
			
		||||
	// BSSStatusIBSSJoined indicates that a client has joined an independent BSS.
 | 
			
		||||
	BSSStatusIBSSJoined
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// String returns the string representation of a BSSStatus.
 | 
			
		||||
func (s BSSStatus) String() string {
 | 
			
		||||
	switch s {
 | 
			
		||||
	case BSSStatusAuthenticated:
 | 
			
		||||
		return "authenticated"
 | 
			
		||||
	case BSSStatusAssociated:
 | 
			
		||||
		return "associated"
 | 
			
		||||
	case BSSStatusIBSSJoined:
 | 
			
		||||
		return "IBSS joined"
 | 
			
		||||
	default:
 | 
			
		||||
		return fmt.Sprintf("unknown(%d)", s)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// List of 802.11 Information Element types.
 | 
			
		||||
const (
 | 
			
		||||
	ieSSID = 0
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// An ie is an 802.11 information element.
 | 
			
		||||
type ie struct {
 | 
			
		||||
	ID uint8
 | 
			
		||||
	// Length field implied by length of data
 | 
			
		||||
	Data []byte
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// parseIEs parses zero or more ies from a byte slice.
 | 
			
		||||
// Reference:
 | 
			
		||||
//   https://www.safaribooksonline.com/library/view/80211-wireless-networks/0596100523/ch04.html#wireless802dot112-CHP-4-FIG-31
 | 
			
		||||
func parseIEs(b []byte) ([]ie, error) {
 | 
			
		||||
	var ies []ie
 | 
			
		||||
	var i int
 | 
			
		||||
	for {
 | 
			
		||||
		if len(b[i:]) == 0 {
 | 
			
		||||
			break
 | 
			
		||||
		}
 | 
			
		||||
		if len(b[i:]) < 2 {
 | 
			
		||||
			return nil, errInvalidIE
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		id := b[i]
 | 
			
		||||
		i++
 | 
			
		||||
		l := int(b[i])
 | 
			
		||||
		i++
 | 
			
		||||
 | 
			
		||||
		if len(b[i:]) < l {
 | 
			
		||||
			return nil, errInvalidIE
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		ies = append(ies, ie{
 | 
			
		||||
			ID:   id,
 | 
			
		||||
			Data: b[i : i+l],
 | 
			
		||||
		})
 | 
			
		||||
 | 
			
		||||
		i += l
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return ies, nil
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										6
									
								
								vendor/vendor.json
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										6
									
								
								vendor/vendor.json
									
									
									
									
										vendored
									
									
								
							| 
						 | 
				
			
			@ -69,10 +69,10 @@
 | 
			
		|||
			"revisionTime": "2017-01-04T04:59:06Z"
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			"checksumSHA1": "l8M/rZH5s/ZVtCCyeiUQXZ5FosA=",
 | 
			
		||||
			"checksumSHA1": "J6L0K9aHO8riicB4BY8/WHb6wBI=",
 | 
			
		||||
			"path": "github.com/mdlayher/wifi",
 | 
			
		||||
			"revision": "eb8b29b956ba5ff2fdd2d2f1f0b988b57fd3d8a3",
 | 
			
		||||
			"revisionTime": "2017-01-12T20:47:29Z"
 | 
			
		||||
			"revision": "85a20a7adc659e5007fb9dd0961ba4e8b7ea2f80",
 | 
			
		||||
			"revisionTime": "2017-01-17T05:43:47Z"
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			"checksumSHA1": "VzutdH69PUqRqhrDVv6F91ebQd4=",
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue