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