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 ifaliasreq request; 118 memset(&request, 0, sizeof(ifaliasreq)); 119 strlcpy(request.ifra_name, name, IF_NAMESIZE); 120 121 if (ioctl(socket, SIOCAIFADDR, &request, sizeof(request)) != 0) 122 return errno; 123 124 return B_OK; 125 } 126 127 128 status_t 129 BNetworkRoster::AddInterface(const BNetworkInterface& interface) 130 { 131 return AddInterface(interface.Name()); 132 } 133 134 135 status_t 136 BNetworkRoster::RemoveInterface(const char* name) 137 { 138 int socket = ::socket(AF_INET, SOCK_DGRAM, 0); 139 if (socket < 0) 140 return errno; 141 142 ifreq request; 143 strlcpy(request.ifr_name, name, IF_NAMESIZE); 144 145 request.ifr_addr.sa_family = AF_UNSPEC; 146 147 if (ioctl(socket, SIOCDIFADDR, &request, sizeof(request)) != 0) 148 return errno; 149 150 return B_OK; 151 } 152 153 154 status_t 155 BNetworkRoster::RemoveInterface(const BNetworkInterface& interface) 156 { 157 return RemoveInterface(interface.Name()); 158 } 159 160 161 int32 162 BNetworkRoster::CountPersistentNetworks() const 163 { 164 BMessenger networkServer(kNetServerSignature); 165 BMessage message(kMsgCountPersistentNetworks); 166 BMessage reply; 167 if (networkServer.SendMessage(&message, &reply) != B_OK) 168 return 0; 169 170 int32 count = 0; 171 if (reply.FindInt32("count", &count) != B_OK) 172 return 0; 173 174 return count; 175 } 176 177 178 status_t 179 BNetworkRoster::GetNextPersistentNetwork(uint32* cookie, 180 wireless_network& network) const 181 { 182 BMessenger networkServer(kNetServerSignature); 183 BMessage message(kMsgGetPersistentNetwork); 184 message.AddInt32("index", (int32)*cookie); 185 186 BMessage reply; 187 status_t result = networkServer.SendMessage(&message, &reply); 188 if (result != B_OK) 189 return result; 190 191 status_t status; 192 if (reply.FindInt32("status", &status) != B_OK) 193 return B_ERROR; 194 if (status != B_OK) 195 return status; 196 197 BMessage networkMessage; 198 if (reply.FindMessage("network", &networkMessage) != B_OK) 199 return B_ERROR; 200 201 BString networkName; 202 if (networkMessage.FindString("name", &networkName) != B_OK) 203 return B_ERROR; 204 205 memset(network.name, 0, sizeof(network.name)); 206 strncpy(network.name, networkName.String(), sizeof(network.name)); 207 208 BNetworkAddress address; 209 if (networkMessage.FindFlat("address", &network.address) != B_OK) 210 network.address.Unset(); 211 212 if (networkMessage.FindUInt32("flags", &network.flags) != B_OK) 213 network.flags = 0; 214 215 if (networkMessage.FindUInt32("authentication_mode", 216 &network.authentication_mode) != B_OK) { 217 network.authentication_mode = B_NETWORK_AUTHENTICATION_NONE; 218 } 219 220 if (networkMessage.FindUInt32("cipher", &network.cipher) != B_OK) 221 network.cipher = B_NETWORK_CIPHER_NONE; 222 223 if (networkMessage.FindUInt32("group_cipher", &network.group_cipher) 224 != B_OK) { 225 network.group_cipher = B_NETWORK_CIPHER_NONE; 226 } 227 228 if (networkMessage.FindUInt32("key_mode", &network.key_mode) != B_OK) 229 network.key_mode = B_KEY_MODE_NONE; 230 231 return B_OK; 232 } 233 234 235 status_t 236 BNetworkRoster::AddPersistentNetwork(const wireless_network& network) 237 { 238 BMessage message(kMsgAddPersistentNetwork); 239 BString networkName; 240 networkName.SetTo(network.name, sizeof(network.name)); 241 status_t status = message.AddString("name", networkName); 242 if (status == B_OK) { 243 BNetworkAddress address = network.address; 244 status = message.AddFlat("address", &address); 245 } 246 247 if (status == B_OK) 248 status = message.AddUInt32("flags", network.flags); 249 if (status == B_OK) { 250 status = message.AddUInt32("authentication_mode", 251 network.authentication_mode); 252 } 253 if (status == B_OK) 254 status = message.AddUInt32("cipher", network.cipher); 255 if (status == B_OK) 256 status = message.AddUInt32("group_cipher", network.group_cipher); 257 if (status == B_OK) 258 status = message.AddUInt32("key_mode", network.key_mode); 259 260 if (status != B_OK) 261 return status; 262 263 BMessenger networkServer(kNetServerSignature); 264 BMessage reply; 265 status = networkServer.SendMessage(&message, &reply); 266 if (status == B_OK) 267 reply.FindInt32("status", &status); 268 269 return status; 270 } 271 272 273 status_t 274 BNetworkRoster::RemovePersistentNetwork(const char* name) 275 { 276 BMessage message(kMsgRemovePersistentNetwork); 277 status_t status = message.AddString("name", name); 278 if (status != B_OK) 279 return status; 280 281 BMessenger networkServer(kNetServerSignature); 282 BMessage reply; 283 status = networkServer.SendMessage(&message, &reply); 284 if (status == B_OK) 285 reply.FindInt32("status", &status); 286 287 return status; 288 } 289 290 291 status_t 292 BNetworkRoster::StartWatching(const BMessenger& target, uint32 eventMask) 293 { 294 return start_watching_network(eventMask, target); 295 } 296 297 298 void 299 BNetworkRoster::StopWatching(const BMessenger& target) 300 { 301 stop_watching_network(target); 302 } 303 304 305 // #pragma mark - private 306 307 308 BNetworkRoster::BNetworkRoster() 309 { 310 } 311 312 313 BNetworkRoster::~BNetworkRoster() 314 { 315 } 316