github.com/simpleiot/simpleiot@v0.18.3/client/network-manager-device.go (about) 1 //go:build linux 2 // +build linux 3 4 package client 5 6 import ( 7 "encoding/json" 8 9 nm "github.com/Wifx/gonetworkmanager/v2" 10 ) 11 12 // NetworkManagerDevice is a device managed by NetworkManager 13 type NetworkManagerDevice struct { 14 ID string `node:"id"` 15 Parent string `node:"parent"` 16 Path string `point:"path"` 17 Interface string `point:"interface"` 18 State string `point:"state"` 19 DeviceType string `point:"deviceType"` 20 // ActiveConnectionID 21 IPv4Addresses []IPv4Address `point:"ipv4Addresses"` 22 IPv4Netmasks []IPv4Netmask `point:"ipv4Netmasks"` 23 IPv4Gateway IPv4Address `point:"ipv4Gateway"` 24 IPv4Nameservers []IPv4Address `point:"ipv4Nameservers"` 25 IPv6Addresses []IPv6Address `point:"ipv6Addresses"` 26 IPv6Prefixes []uint8 `point:"ipv6Prefixes"` 27 IPv6Gateway IPv6Address `point:"ipv6Gateway"` 28 IPv6Nameservers []IPv6Address `point:"ipv6Nameservers"` 29 HardwareAddress string `point:"hardwareAddress"` 30 Managed bool 31 // Wi-Fi specific properties 32 ActiveAccessPoint *AccessPoint `point:"activeAccessPoint"` 33 AccessPoints []string `point:"accessPoints"` // JSON-encoded strings 34 } 35 36 // ResolveDevice returns a NetworkManagerDevice from a NetworkManager Device 37 func ResolveDevice(parent string, device nm.Device) ( 38 dev NetworkManagerDevice, err error, 39 ) { 40 dev.Parent = parent 41 42 // Read device info via D-Bus 43 dev.Path = string(device.GetPath()) 44 dev.ID = dev.Path 45 46 dev.Interface, err = device.GetPropertyInterface() 47 if err != nil { 48 return dev, err 49 } 50 if dev.Interface != "" { 51 dev.ID = dev.Interface 52 } 53 54 ipIface, err := device.GetPropertyIpInterface() 55 if err != nil { 56 return dev, err 57 } 58 if ipIface != "" { 59 dev.ID = ipIface 60 } 61 62 state, err := device.GetPropertyState() 63 if err != nil { 64 return dev, err 65 } 66 dev.State = state.String() 67 68 // Populate IPv4 state 69 ipv4, err := device.GetPropertyIP4Config() 70 if err != nil { 71 return dev, err 72 } 73 if ipv4 != nil { 74 ip4Addresses, err := ipv4.GetPropertyAddressData() 75 if err != nil { 76 return dev, err 77 } 78 for _, addr := range ip4Addresses { 79 dev.IPv4Addresses = append(dev.IPv4Addresses, 80 IPv4Address(addr.Address), 81 ) 82 dev.IPv4Netmasks = append(dev.IPv4Netmasks, 83 IPv4NetmaskPrefix(addr.Prefix), 84 ) 85 } 86 87 gateway, err := ipv4.GetPropertyGateway() 88 if err != nil { 89 return dev, err 90 } 91 dev.IPv4Gateway = IPv4Address(gateway) 92 93 nameservers, err := ipv4.GetPropertyNameserverData() 94 if err != nil { 95 return dev, err 96 } 97 for _, addr := range nameservers { 98 if addr.Address != "" { 99 dev.IPv4Nameservers = append(dev.IPv4Nameservers, 100 IPv4Address(addr.Address), 101 ) 102 } 103 } 104 } 105 106 ipv6, err := device.GetPropertyIP6Config() 107 if err != nil { 108 return dev, err 109 } 110 if ipv6 != nil { 111 // Populate IPv6 state 112 ip6Addresses, err := ipv6.GetPropertyAddressData() 113 if err != nil { 114 return dev, err 115 } 116 for _, addr := range ip6Addresses { 117 dev.IPv6Addresses = append(dev.IPv6Addresses, IPv6Address(addr.Address)) 118 dev.IPv6Prefixes = append(dev.IPv6Prefixes, addr.Prefix) 119 } 120 121 gateway, err := ipv6.GetPropertyGateway() 122 if err != nil { 123 return dev, err 124 } 125 dev.IPv6Gateway = IPv6Address(gateway) 126 127 nameservers, err := ipv6.GetPropertyNameservers() 128 if err != nil { 129 return dev, err 130 } 131 for _, addr := range nameservers { 132 dev.IPv6Nameservers = append(dev.IPv6Nameservers, 133 NewIPv6Address(addr), 134 ) 135 } 136 } 137 138 dev.Managed, err = device.GetPropertyManaged() 139 if err != nil { 140 return dev, err 141 } 142 143 deviceType, err := device.GetPropertyDeviceType() 144 if err != nil { 145 return dev, err 146 } 147 dev.DeviceType = deviceType.String() 148 149 if devHwAddr, ok := device.(interface { 150 GetPropertyHwAddress() (string, error) 151 }); ok { 152 dev.HardwareAddress, err = devHwAddr.GetPropertyHwAddress() 153 if err != nil { 154 return dev, err 155 } 156 if dev.HardwareAddress != "" && dev.HardwareAddress != "00:00:00:00:00:00" { 157 dev.ID = dev.HardwareAddress 158 } 159 } 160 161 // Add WiFi access point 162 if devAP, ok := device.(interface { 163 GetPropertyActiveAccessPoint() (nm.AccessPoint, error) 164 }); ok { 165 ap, err := devAP.GetPropertyActiveAccessPoint() 166 if err != nil { 167 return dev, err 168 } 169 if ap == nil { 170 dev.ActiveAccessPoint = nil 171 } else { 172 resolvedAP, err := ResolveAccessPoint(ap) 173 if err != nil { 174 return dev, err 175 } 176 dev.ActiveAccessPoint = &resolvedAP 177 } 178 } 179 180 // Add device type prefix to ID 181 dev.ID = deviceType.String() + "_" + dev.ID 182 return dev, err 183 } 184 185 // RescanTimeoutSeconds is the maximum number of seconds since LastScan that can 186 // elapse before scanning for access points is requested 187 const RescanTimeoutSeconds = 10 188 189 // AccessPoint describes a network access point 190 type AccessPoint struct { 191 SSID string `json:"ssid"` 192 BSSID string `json:"bssid"` 193 Strength uint8 `json:"strength"` 194 Flags uint32 `json:"flags"` 195 WPAFlags uint32 `json:"wpaFlags"` 196 RSNFlags uint32 `json:"rsnFlags"` 197 } 198 199 // ResolveAccessPoint returns an AccessPoint from a NetworkManager AccessPoint 200 func ResolveAccessPoint(ap nm.AccessPoint) (apOut AccessPoint, err error) { 201 ssid, err := ap.GetPropertySSID() 202 if err != nil { 203 return apOut, err 204 } 205 apOut.SSID = string(ssid) 206 207 apOut.BSSID, err = ap.GetPropertyHWAddress() 208 if err != nil { 209 return apOut, err 210 } 211 212 apOut.Strength, err = ap.GetPropertyStrength() 213 if err != nil { 214 return apOut, err 215 } 216 217 apOut.Flags, err = ap.GetPropertyFlags() 218 if err != nil { 219 return apOut, err 220 } 221 222 apOut.WPAFlags, err = ap.GetPropertyWPAFlags() 223 if err != nil { 224 return apOut, err 225 } 226 227 apOut.RSNFlags, err = ap.GetPropertyRSNFlags() 228 if err != nil { 229 return apOut, err 230 } 231 232 return apOut, err 233 } 234 235 // MarshallJSON returns a JSON representation of the AP 236 func (ap AccessPoint) MarshallJSON() ([]byte, error) { 237 return json.Marshal(ap) 238 }