// parseAttributes parses netlink attributes into a StationInfo's fields. func (info *StationInfo) parseAttributes(attrs []netlink.Attribute) error { for _, a := range attrs { switch a.Type { case nl80211.StaInfoConnectedTime: // Though nl80211 does not specify, this value appears to be in seconds: // * @NL80211_STA_INFO_CONNECTED_TIME: time since the station is last connected info.Connected = time.Duration(nlenc.Uint32(a.Data)) * time.Second case nl80211.StaInfoInactiveTime: // * @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) case nl80211.StaInfoTxBytes64: info.TransmittedBytes = 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) case nl80211.StaInfoTxPackets: info.TransmittedPackets = nlenc.Uint32(a.Data) case nl80211.StaInfoTxRetries: info.TransmitRetries = nlenc.Uint32(a.Data) case nl80211.StaInfoTxFailed: info.TransmitFailed = nlenc.Uint32(a.Data) case nl80211.StaInfoBeaconLoss: info.BeaconLoss = nlenc.Uint32(a.Data) case nl80211.StaInfoRxBitrate, nl80211.StaInfoTxBitrate: rate, err := parseRateInfo(a.Data) if err != nil { return err } // TODO(mdlayher): return more statistics if they end up being // generally useful switch a.Type { case nl80211.StaInfoRxBitrate: info.ReceiveBitrate = rate.Bitrate case nl80211.StaInfoTxBitrate: info.TransmitBitrate = rate.Bitrate } } // Only use 32-bit counters if the 64-bit counters are not present. // 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)) } if info.TransmittedBytes == 0 && a.Type == nl80211.StaInfoTxBytes { info.TransmittedBytes = uint64(nlenc.Uint32(a.Data)) } } return nil }
// parseAttributes parses netlink attributes into an Interface's fields. func (ifi *Interface) parseAttributes(attrs []netlink.Attribute) error { for _, a := range attrs { switch a.Type { case nl80211.AttrIfindex: ifi.Index = int(nlenc.Uint32(a.Data)) case nl80211.AttrIfname: ifi.Name = nlenc.String(a.Data) case nl80211.AttrMac: ifi.HardwareAddr = net.HardwareAddr(a.Data) case nl80211.AttrWiphy: ifi.PHY = int(nlenc.Uint32(a.Data)) case nl80211.AttrIftype: // NOTE: InterfaceType copies the ordering of nl80211's interface type // constants. This may not be the case on other operating systems. ifi.Type = InterfaceType(nlenc.Uint32(a.Data)) case nl80211.AttrWdev: ifi.Device = int(nlenc.Uint64(a.Data)) case nl80211.AttrWiphyFreq: ifi.Frequency = int(nlenc.Uint32(a.Data)) } } return nil }