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 FileDescriptorCloser socket(::socket(AF_INET, SOCK_DGRAM, 0)); 41 if (!socket.IsSet()) 42 return 0; 43 44 ifconf config; 45 config.ifc_len = sizeof(config.ifc_value); 46 if (ioctl(socket.Get(), SIOCGIFCOUNT, &config, sizeof(struct ifconf)) != 0) 47 return 0; 48 49 return (size_t)config.ifc_value; 50 } 51 52 53 status_t 54 BNetworkRoster::GetNextInterface(uint32* cookie, 55 BNetworkInterface& interface) const 56 { 57 // TODO: think about caching the interfaces! 58 59 if (cookie == NULL) 60 return B_BAD_VALUE; 61 62 // get a list of all interfaces 63 64 FileDescriptorCloser socket (::socket(AF_INET, SOCK_DGRAM, 0)); 65 if (!socket.IsSet()) 66 return errno; 67 68 ifconf config; 69 config.ifc_len = sizeof(config.ifc_value); 70 if (ioctl(socket.Get(), SIOCGIFCOUNT, &config, sizeof(struct ifconf)) < 0) 71 return errno; 72 73 size_t count = (size_t)config.ifc_value; 74 if (count == 0) 75 return B_BAD_VALUE; 76 77 char* buffer = (char*)malloc(count * sizeof(struct ifreq)); 78 if (buffer == NULL) 79 return B_NO_MEMORY; 80 81 MemoryDeleter deleter(buffer); 82 83 config.ifc_len = count * sizeof(struct ifreq); 84 config.ifc_buf = buffer; 85 if (ioctl(socket.Get(), SIOCGIFCONF, &config, sizeof(struct ifconf)) < 0) 86 return errno; 87 88 ifreq* interfaces = (ifreq*)buffer; 89 ifreq* end = (ifreq*)(buffer + config.ifc_len); 90 91 for (uint32 i = 0; interfaces < end; i++) { 92 interface.SetTo(interfaces[0].ifr_name); 93 if (i == *cookie) { 94 (*cookie)++; 95 return B_OK; 96 } 97 98 interfaces = (ifreq*)((uint8*)interfaces 99 + _SIZEOF_ADDR_IFREQ(interfaces[0])); 100 } 101 102 return B_BAD_VALUE; 103 } 104 105 106 status_t 107 BNetworkRoster::AddInterface(const char* name) 108 { 109 FileDescriptorCloser socket (::socket(AF_INET, SOCK_DGRAM, 0)); 110 if (!socket.IsSet()) 111 return errno; 112 113 ifaliasreq request; 114 memset(&request, 0, sizeof(ifaliasreq)); 115 strlcpy(request.ifra_name, name, IF_NAMESIZE); 116 117 if (ioctl(socket.Get(), SIOCAIFADDR, &request, sizeof(request)) != 0) 118 return errno; 119 120 return B_OK; 121 } 122 123 124 status_t 125 BNetworkRoster::AddInterface(const BNetworkInterface& interface) 126 { 127 return AddInterface(interface.Name()); 128 } 129 130 131 status_t 132 BNetworkRoster::RemoveInterface(const char* name) 133 { 134 FileDescriptorCloser socket(::socket(AF_INET, SOCK_DGRAM, 0)); 135 if (!socket.IsSet()) 136 return errno; 137 138 ifreq request; 139 strlcpy(request.ifr_name, name, IF_NAMESIZE); 140 141 request.ifr_addr.sa_family = AF_UNSPEC; 142 143 if (ioctl(socket.Get(), SIOCDIFADDR, &request, sizeof(request)) != 0) 144 return errno; 145 146 return B_OK; 147 } 148 149 150 status_t 151 BNetworkRoster::RemoveInterface(const BNetworkInterface& interface) 152 { 153 return RemoveInterface(interface.Name()); 154 } 155 156 157 int32 158 BNetworkRoster::CountPersistentNetworks() const 159 { 160 BMessenger networkServer(kNetServerSignature); 161 BMessage message(kMsgCountPersistentNetworks); 162 BMessage reply; 163 if (networkServer.SendMessage(&message, &reply) != B_OK) 164 return 0; 165 166 int32 count = 0; 167 if (reply.FindInt32("count", &count) != B_OK) 168 return 0; 169 170 return count; 171 } 172 173 174 status_t 175 BNetworkRoster::GetNextPersistentNetwork(uint32* cookie, 176 wireless_network& network) const 177 { 178 BMessenger networkServer(kNetServerSignature); 179 BMessage message(kMsgGetPersistentNetwork); 180 message.AddInt32("index", (int32)*cookie); 181 182 BMessage reply; 183 status_t result = networkServer.SendMessage(&message, &reply); 184 if (result != B_OK) 185 return result; 186 187 status_t status; 188 if (reply.FindInt32("status", &status) != B_OK) 189 return B_ERROR; 190 if (status != B_OK) 191 return status; 192 193 BMessage networkMessage; 194 if (reply.FindMessage("network", &networkMessage) != B_OK) 195 return B_ERROR; 196 197 BString networkName; 198 if (networkMessage.FindString("name", &networkName) != B_OK) 199 return B_ERROR; 200 201 memset(network.name, 0, sizeof(network.name)); 202 strlcpy(network.name, networkName.String(), sizeof(network.name)); 203 204 BNetworkAddress address; 205 if (networkMessage.FindFlat("address", &network.address) != B_OK) 206 network.address.Unset(); 207 208 if (networkMessage.FindUInt32("flags", &network.flags) != B_OK) 209 network.flags = 0; 210 211 if (networkMessage.FindUInt32("authentication_mode", 212 &network.authentication_mode) != B_OK) { 213 network.authentication_mode = B_NETWORK_AUTHENTICATION_NONE; 214 } 215 216 if (networkMessage.FindUInt32("cipher", &network.cipher) != B_OK) 217 network.cipher = B_NETWORK_CIPHER_NONE; 218 219 if (networkMessage.FindUInt32("group_cipher", &network.group_cipher) 220 != B_OK) { 221 network.group_cipher = B_NETWORK_CIPHER_NONE; 222 } 223 224 if (networkMessage.FindUInt32("key_mode", &network.key_mode) != B_OK) 225 network.key_mode = B_KEY_MODE_NONE; 226 227 return B_OK; 228 } 229 230 231 status_t 232 BNetworkRoster::AddPersistentNetwork(const wireless_network& network) 233 { 234 BMessage message(kMsgAddPersistentNetwork); 235 BString networkName; 236 networkName.SetTo(network.name, sizeof(network.name)); 237 status_t status = message.AddString("name", networkName); 238 if (status == B_OK) { 239 BNetworkAddress address = network.address; 240 status = message.AddFlat("address", &address); 241 } 242 243 if (status == B_OK) 244 status = message.AddUInt32("flags", network.flags); 245 if (status == B_OK) { 246 status = message.AddUInt32("authentication_mode", 247 network.authentication_mode); 248 } 249 if (status == B_OK) 250 status = message.AddUInt32("cipher", network.cipher); 251 if (status == B_OK) 252 status = message.AddUInt32("group_cipher", network.group_cipher); 253 if (status == B_OK) 254 status = message.AddUInt32("key_mode", network.key_mode); 255 256 if (status != B_OK) 257 return status; 258 259 BMessenger networkServer(kNetServerSignature); 260 BMessage reply; 261 status = networkServer.SendMessage(&message, &reply); 262 if (status == B_OK) 263 reply.FindInt32("status", &status); 264 265 return status; 266 } 267 268 269 status_t 270 BNetworkRoster::RemovePersistentNetwork(const char* name) 271 { 272 BMessage message(kMsgRemovePersistentNetwork); 273 status_t status = message.AddString("name", name); 274 if (status != B_OK) 275 return status; 276 277 BMessenger networkServer(kNetServerSignature); 278 BMessage reply; 279 status = networkServer.SendMessage(&message, &reply); 280 if (status == B_OK) 281 reply.FindInt32("status", &status); 282 283 return status; 284 } 285 286 287 status_t 288 BNetworkRoster::StartWatching(const BMessenger& target, uint32 eventMask) 289 { 290 return start_watching_network(eventMask, target); 291 } 292 293 294 void 295 BNetworkRoster::StopWatching(const BMessenger& target) 296 { 297 stop_watching_network(target); 298 } 299 300 301 // #pragma mark - private 302 303 304 BNetworkRoster::BNetworkRoster() 305 { 306 } 307 308 309 BNetworkRoster::~BNetworkRoster() 310 { 311 } 312