1 /* 2 * Copyright 2010, Axel Dörfler, axeld@pinc-software.de. 3 * Distributed under the terms of the MIT License. 4 */ 5 6 7 #include <NetworkRoster.h> 8 9 #include <errno.h> 10 #include <sys/sockio.h> 11 12 #include <NetworkDevice.h> 13 #include <NetworkInterface.h> 14 15 #include <net_notifications.h> 16 #include <AutoDeleter.h> 17 #include <NetServer.h> 18 19 20 // TODO: using AF_INET for the socket isn't really a smart idea, as one 21 // could completely remove IPv4 support from the stack easily. 22 // Since in the stack, device_interfaces are pretty much interfaces now, we 23 // could get rid of them more or less, and make AF_LINK provide the same 24 // information as AF_INET for the interface functions mostly. 25 26 27 BNetworkRoster BNetworkRoster::sDefault; 28 29 30 /*static*/ BNetworkRoster& 31 BNetworkRoster::Default() 32 { 33 return sDefault; 34 } 35 36 37 size_t 38 BNetworkRoster::CountInterfaces() const 39 { 40 int socket = ::socket(AF_INET, SOCK_DGRAM, 0); 41 if (socket < 0) 42 return 0; 43 44 FileDescriptorCloser closer(socket); 45 46 ifconf config; 47 config.ifc_len = sizeof(config.ifc_value); 48 if (ioctl(socket, SIOCGIFCOUNT, &config, sizeof(struct ifconf)) != 0) 49 return 0; 50 51 return (size_t)config.ifc_value; 52 } 53 54 55 status_t 56 BNetworkRoster::GetNextInterface(uint32* cookie, 57 BNetworkInterface& interface) const 58 { 59 // TODO: think about caching the interfaces! 60 61 if (cookie == NULL) 62 return B_BAD_VALUE; 63 64 // get a list of all interfaces 65 66 int socket = ::socket(AF_INET, SOCK_DGRAM, 0); 67 if (socket < 0) 68 return errno; 69 70 FileDescriptorCloser closer(socket); 71 72 ifconf config; 73 config.ifc_len = sizeof(config.ifc_value); 74 if (ioctl(socket, SIOCGIFCOUNT, &config, sizeof(struct ifconf)) < 0) 75 return errno; 76 77 size_t count = (size_t)config.ifc_value; 78 if (count == 0) 79 return B_BAD_VALUE; 80 81 char* buffer = (char*)malloc(count * sizeof(struct ifreq)); 82 if (buffer == NULL) 83 return B_NO_MEMORY; 84 85 MemoryDeleter deleter(buffer); 86 87 config.ifc_len = count * sizeof(struct ifreq); 88 config.ifc_buf = buffer; 89 if (ioctl(socket, SIOCGIFCONF, &config, sizeof(struct ifconf)) < 0) 90 return errno; 91 92 ifreq* interfaces = (ifreq*)buffer; 93 ifreq* end = (ifreq*)(buffer + config.ifc_len); 94 95 for (uint32 i = 0; interfaces < end; i++) { 96 interface.SetTo(interfaces[0].ifr_name); 97 if (i == *cookie) { 98 (*cookie)++; 99 return B_OK; 100 } 101 102 interfaces = (ifreq*)((uint8*)interfaces 103 + _SIZEOF_ADDR_IFREQ(interfaces[0])); 104 } 105 106 return B_BAD_VALUE; 107 } 108 109 110 status_t 111 BNetworkRoster::AddInterface(const char* name) 112 { 113 int socket = ::socket(AF_INET, SOCK_DGRAM, 0); 114 if (socket < 0) 115 return errno; 116 117 FileDescriptorCloser closer(socket); 118 119 ifaliasreq request; 120 memset(&request, 0, sizeof(ifaliasreq)); 121 strlcpy(request.ifra_name, name, IF_NAMESIZE); 122 123 if (ioctl(socket, SIOCAIFADDR, &request, sizeof(request)) != 0) 124 return errno; 125 126 return B_OK; 127 } 128 129 130 status_t 131 BNetworkRoster::AddInterface(const BNetworkInterface& interface) 132 { 133 return AddInterface(interface.Name()); 134 } 135 136 137 status_t 138 BNetworkRoster::RemoveInterface(const char* name) 139 { 140 int socket = ::socket(AF_INET, SOCK_DGRAM, 0); 141 if (socket < 0) 142 return errno; 143 144 FileDescriptorCloser closer(socket); 145 146 ifreq request; 147 strlcpy(request.ifr_name, name, IF_NAMESIZE); 148 149 request.ifr_addr.sa_family = AF_UNSPEC; 150 151 if (ioctl(socket, SIOCDIFADDR, &request, sizeof(request)) != 0) 152 return errno; 153 154 return B_OK; 155 } 156 157 158 status_t 159 BNetworkRoster::RemoveInterface(const BNetworkInterface& interface) 160 { 161 return RemoveInterface(interface.Name()); 162 } 163 164 165 int32 166 BNetworkRoster::CountPersistentNetworks() const 167 { 168 BMessenger networkServer(kNetServerSignature); 169 BMessage message(kMsgCountPersistentNetworks); 170 BMessage reply; 171 if (networkServer.SendMessage(&message, &reply) != B_OK) 172 return 0; 173 174 int32 count = 0; 175 if (reply.FindInt32("count", &count) != B_OK) 176 return 0; 177 178 return count; 179 } 180 181 182 status_t 183 BNetworkRoster::GetNextPersistentNetwork(uint32* cookie, 184 wireless_network& network) const 185 { 186 BMessenger networkServer(kNetServerSignature); 187 BMessage message(kMsgGetPersistentNetwork); 188 message.AddInt32("index", (int32)*cookie); 189 190 BMessage reply; 191 status_t result = networkServer.SendMessage(&message, &reply); 192 if (result != B_OK) 193 return result; 194 195 status_t status; 196 if (reply.FindInt32("status", &status) != B_OK) 197 return B_ERROR; 198 if (status != B_OK) 199 return status; 200 201 BMessage networkMessage; 202 if (reply.FindMessage("network", &networkMessage) != B_OK) 203 return B_ERROR; 204 205 BString networkName; 206 if (networkMessage.FindString("name", &networkName) != B_OK) 207 return B_ERROR; 208 209 memset(network.name, 0, sizeof(network.name)); 210 strncpy(network.name, networkName.String(), sizeof(network.name)); 211 212 BNetworkAddress address; 213 if (networkMessage.FindFlat("address", &network.address) != B_OK) 214 network.address.Unset(); 215 216 if (networkMessage.FindUInt32("flags", &network.flags) != B_OK) 217 network.flags = 0; 218 219 if (networkMessage.FindUInt32("authentication_mode", 220 &network.authentication_mode) != B_OK) { 221 network.authentication_mode = B_NETWORK_AUTHENTICATION_NONE; 222 } 223 224 if (networkMessage.FindUInt32("cipher", &network.cipher) != B_OK) 225 network.cipher = B_NETWORK_CIPHER_NONE; 226 227 if (networkMessage.FindUInt32("group_cipher", &network.group_cipher) 228 != B_OK) { 229 network.group_cipher = B_NETWORK_CIPHER_NONE; 230 } 231 232 if (networkMessage.FindUInt32("key_mode", &network.key_mode) != B_OK) 233 network.key_mode = B_KEY_MODE_NONE; 234 235 return B_OK; 236 } 237 238 239 status_t 240 BNetworkRoster::AddPersistentNetwork(const wireless_network& network) 241 { 242 BMessage message(kMsgAddPersistentNetwork); 243 BString networkName; 244 networkName.SetTo(network.name, sizeof(network.name)); 245 status_t status = message.AddString("name", networkName); 246 if (status == B_OK) { 247 BNetworkAddress address = network.address; 248 status = message.AddFlat("address", &address); 249 } 250 251 if (status == B_OK) 252 status = message.AddUInt32("flags", network.flags); 253 if (status == B_OK) { 254 status = message.AddUInt32("authentication_mode", 255 network.authentication_mode); 256 } 257 if (status == B_OK) 258 status = message.AddUInt32("cipher", network.cipher); 259 if (status == B_OK) 260 status = message.AddUInt32("group_cipher", network.group_cipher); 261 if (status == B_OK) 262 status = message.AddUInt32("key_mode", network.key_mode); 263 264 if (status != B_OK) 265 return status; 266 267 BMessenger networkServer(kNetServerSignature); 268 BMessage reply; 269 status = networkServer.SendMessage(&message, &reply); 270 if (status == B_OK) 271 reply.FindInt32("status", &status); 272 273 return status; 274 } 275 276 277 status_t 278 BNetworkRoster::RemovePersistentNetwork(const char* name) 279 { 280 BMessage message(kMsgRemovePersistentNetwork); 281 status_t status = message.AddString("name", name); 282 if (status != B_OK) 283 return status; 284 285 BMessenger networkServer(kNetServerSignature); 286 BMessage reply; 287 status = networkServer.SendMessage(&message, &reply); 288 if (status == B_OK) 289 reply.FindInt32("status", &status); 290 291 return status; 292 } 293 294 295 status_t 296 BNetworkRoster::StartWatching(const BMessenger& target, uint32 eventMask) 297 { 298 return start_watching_network(eventMask, target); 299 } 300 301 302 void 303 BNetworkRoster::StopWatching(const BMessenger& target) 304 { 305 stop_watching_network(target); 306 } 307 308 309 // #pragma mark - private 310 311 312 BNetworkRoster::BNetworkRoster() 313 { 314 } 315 316 317 BNetworkRoster::~BNetworkRoster() 318 { 319 } 320