// parseStationInfo parses StationInfo attributes from a byte slice of // netlink attributes. func parseStationInfo(b []byte) (*StationInfo, error) { attrs, err := netlink.UnmarshalAttributes(b) if err != nil { return nil, err } for _, a := range attrs { // The other attributes that are returned here appear to indicate the // interface index and MAC address, which is information we already // possess. No need to parse them for now. if a.Type != nl80211.AttrStaInfo { continue } nattrs, err := netlink.UnmarshalAttributes(a.Data) if err != nil { return nil, err } var info StationInfo if err := (&info).parseAttributes(nattrs); err != nil { return nil, err } return &info, nil } // No station info found return nil, os.ErrNotExist }
// parseMulticastGroups parses an array of multicast group nested attributes // into a slice of MulticastGroups. func parseMulticastGroups(b []byte) ([]MulticastGroup, error) { attrs, err := netlink.UnmarshalAttributes(b) if err != nil { return nil, err } groups := make([]MulticastGroup, 0, len(attrs)) for i, a := range attrs { // The type attribute is essentially an array index here; it starts // at 1 and should increment for each new array element if int(a.Type) != i+1 { return nil, errInvalidMulticastGroupArray } nattrs, err := netlink.UnmarshalAttributes(a.Data) if err != nil { return nil, err } var g MulticastGroup for _, na := range nattrs { switch na.Type { case attrMGName: g.Name = nlenc.String(na.Data) case attrMGID: g.ID = nlenc.Uint32(na.Data) } } groups = append(groups, g) } return groups, nil }
// parseRateInfo parses a rateInfo from netlink attributes. func parseRateInfo(b []byte) (*rateInfo, error) { attrs, err := netlink.UnmarshalAttributes(b) if err != nil { return nil, err } var info rateInfo for _, a := range attrs { switch a.Type { case nl80211.RateInfoBitrate32: info.Bitrate = int(nlenc.Uint32(a.Data)) } // Only use 16-bit counters if the 32-bit counters are not present. // If the 32-bit counters appear later in the slice, they will overwrite // these values. if info.Bitrate == 0 && a.Type == nl80211.RateInfoBitrate { info.Bitrate = int(nlenc.Uint16(a.Data)) } } // Scale bitrate to bits/second as base unit instead of 100kbits/second. // * @NL80211_RATE_INFO_BITRATE: total bitrate (u16, 100kbit/s) info.Bitrate *= 100 * 1000 return &info, nil }
// parseInterfaces parses zero or more Interfaces from nl80211 interface // messages. func parseInterfaces(msgs []genetlink.Message) ([]*Interface, error) { ifis := make([]*Interface, 0, len(msgs)) for _, m := range msgs { attrs, err := netlink.UnmarshalAttributes(m.Data) if err != nil { return nil, err } var ifi Interface if err := (&ifi).parseAttributes(attrs); err != nil { return nil, err } ifis = append(ifis, &ifi) } return ifis, nil }
// buildFamilies builds a slice of Families by parsing attributes from the // input Messages. func buildFamilies(msgs []Message) ([]Family, error) { families := make([]Family, 0, len(msgs)) for _, m := range msgs { attrs, err := netlink.UnmarshalAttributes(m.Data) if err != nil { return nil, err } var f Family if err := (&f).parseAttributes(attrs); err != nil { return nil, err } families = append(families, f) } return families, nil }