1 /* 2 * Copyright 2006, Haiku, Inc. All Rights Reserved. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * Axel Dörfler, axeld@pinc-software.de 7 */ 8 9 10 #include "domains.h" 11 #include "interfaces.h" 12 #include "stack_private.h" 13 14 #include <net_device.h> 15 16 #include <lock.h> 17 #include <util/AutoLock.h> 18 19 #include <KernelExport.h> 20 21 #include <net/if_dl.h> 22 #include <new> 23 #include <stdlib.h> 24 #include <string.h> 25 26 27 #define TRACE_INTERFACES 28 #ifdef TRACE_INTERFACES 29 # define TRACE(x) dprintf x 30 #else 31 # define TRACE(x) ; 32 #endif 33 34 35 static benaphore sInterfaceLock; 36 static list sInterfaces; 37 static uint32 sInterfaceIndex; 38 static uint32 sDeviceIndex; 39 40 41 static net_device_interface * 42 find_device_interface(const char *name) 43 { 44 net_device_interface *interface = NULL; 45 46 while (true) { 47 interface = (net_device_interface *)list_get_next_item(&sInterfaces, interface); 48 if (interface == NULL) 49 break; 50 51 if (!strcmp(interface->name, name)) 52 return interface; 53 } 54 55 return NULL; 56 } 57 58 59 static status_t 60 domain_receive_adapter(void *cookie, net_buffer *buffer) 61 { 62 net_domain_private *domain = (net_domain_private *)cookie; 63 return domain->module->receive_data(buffer); 64 } 65 66 67 // #pragma mark - interfaces 68 69 70 /*! 71 Searches for a specific interface in a domain by name. 72 You need to have the domain's lock hold when calling this function. 73 */ 74 struct net_interface_private * 75 find_interface(struct net_domain *domain, const char *name) 76 { 77 net_interface_private *interface = NULL; 78 79 while (true) { 80 interface = (net_interface_private *)list_get_next_item( 81 &domain->interfaces, interface); 82 if (interface == NULL) 83 break; 84 85 if (!strcmp(interface->name, name)) 86 return interface; 87 } 88 89 return NULL; 90 } 91 92 93 /*! 94 Searches for a specific interface in a domain by index. 95 You need to have the domain's lock hold when calling this function. 96 */ 97 struct net_interface_private * 98 find_interface(struct net_domain *domain, uint32 index) 99 { 100 net_interface_private *interface = NULL; 101 102 while (true) { 103 interface = (net_interface_private *)list_get_next_item( 104 &domain->interfaces, interface); 105 if (interface == NULL) 106 break; 107 108 if (interface->index == index) 109 return interface; 110 } 111 112 return NULL; 113 } 114 115 116 status_t 117 create_interface(net_domain *domain, const char *name, const char *baseName, 118 net_device_interface *deviceInterface, net_interface_private **_interface) 119 { 120 net_interface_private *interface = 121 new (std::nothrow) net_interface_private; 122 if (interface == NULL) 123 return B_NO_MEMORY; 124 125 strlcpy(interface->name, name, IF_NAMESIZE); 126 strlcpy(interface->base_name, baseName, IF_NAMESIZE); 127 interface->domain = domain; 128 interface->device = deviceInterface->device; 129 130 interface->address = NULL; 131 interface->destination = NULL; 132 interface->mask = NULL; 133 134 interface->index = ++sInterfaceIndex; 135 interface->flags = deviceInterface->device->flags & ~IFF_UP; 136 interface->type = 0; 137 interface->mtu = deviceInterface->device->mtu; 138 interface->metric = 0; 139 interface->device_interface = deviceInterface; 140 141 status_t status = get_domain_datalink_protocols(interface); 142 if (status < B_OK) { 143 delete interface; 144 return status; 145 } 146 147 // Grab a reference to the networking stack, to make sure it won't be 148 // unloaded as long as an interface exists 149 module_info *module; 150 get_module(NET_STARTER_MODULE_NAME, &module); 151 152 *_interface = interface; 153 return B_OK; 154 } 155 156 157 void 158 delete_interface(net_interface_private *interface) 159 { 160 if ((interface->flags & IFF_UP) != 0) { 161 // the interface is still up - we need to change that before deleting it 162 interface->flags &= ~IFF_UP; 163 interface->device_interface->module->down(interface->device_interface->device); 164 } 165 166 put_device_interface(interface->device_interface); 167 168 free(interface->address); 169 free(interface->destination); 170 free(interface->mask); 171 172 delete interface; 173 174 // Release reference of the stack - at this point, our stack may be unloaded 175 // if no other interfaces or sockets are left 176 put_module(NET_STARTER_MODULE_NAME); 177 } 178 179 180 void 181 put_interface(struct net_interface_private *interface) 182 { 183 // TODO: reference counting 184 // TODO: better locking scheme 185 benaphore_unlock(&((net_domain_private *)interface->domain)->lock); 186 } 187 188 189 struct net_interface_private * 190 get_interface(net_domain *_domain, const char *name) 191 { 192 net_domain_private *domain = (net_domain_private *)_domain; 193 benaphore_lock(&domain->lock); 194 195 net_interface_private *interface = NULL; 196 while (true) { 197 interface = (net_interface_private *)list_get_next_item( 198 &domain->interfaces, interface); 199 if (interface == NULL) 200 break; 201 202 if (!strcmp(interface->name, name)) 203 return interface; 204 } 205 206 benaphore_unlock(&domain->lock); 207 return NULL; 208 } 209 210 211 // #pragma mark - device interfaces 212 213 214 void 215 get_device_interface_address(net_device_interface *interface, sockaddr *_address) 216 { 217 sockaddr_dl &address = *(sockaddr_dl *)_address; 218 219 address.sdl_family = AF_LINK; 220 address.sdl_index = interface->device->index; 221 address.sdl_type = interface->device->type; 222 address.sdl_nlen = strlen(interface->name); 223 address.sdl_slen = 0; 224 memcpy(address.sdl_data, interface->name, address.sdl_nlen); 225 226 address.sdl_alen = interface->device->address.length; 227 memcpy(LLADDR(&address), interface->device->address.data, address.sdl_alen); 228 229 address.sdl_len = sizeof(sockaddr_dl) - sizeof(address.sdl_data) 230 + address.sdl_nlen + address.sdl_alen; 231 } 232 233 234 uint32 235 count_device_interfaces() 236 { 237 BenaphoreLocker locker(sInterfaceLock); 238 239 net_device_interface *interface = NULL; 240 uint32 count = 0; 241 242 while (true) { 243 interface = (net_device_interface *)list_get_next_item(&sInterfaces, 244 interface); 245 if (interface == NULL) 246 break; 247 248 count++; 249 } 250 251 return count; 252 } 253 254 255 /*! 256 Dumps a list of all interfaces into the supplied userland buffer. 257 If the interfaces don't fit into the buffer, an error (\c ENOBUFS) is 258 returned. 259 */ 260 status_t 261 list_device_interfaces(void *buffer, size_t size) 262 { 263 BenaphoreLocker locker(sInterfaceLock); 264 265 net_device_interface *interface = NULL; 266 size_t spaceLeft = size; 267 268 while (true) { 269 interface = (net_device_interface *)list_get_next_item(&sInterfaces, 270 interface); 271 if (interface == NULL) 272 break; 273 274 ifreq request; 275 strlcpy(request.ifr_name, interface->name, IF_NAMESIZE); 276 get_device_interface_address(interface, &request.ifr_addr); 277 278 size = IF_NAMESIZE + request.ifr_addr.sa_len; 279 if (spaceLeft < size) 280 return ENOBUFS; 281 282 if (user_memcpy(buffer, &request, size) < B_OK) 283 return B_BAD_ADDRESS; 284 285 buffer = (void *)((addr_t)buffer + size); 286 spaceLeft -= size; 287 } 288 289 return B_OK; 290 } 291 292 293 /*! 294 Releases the reference for the interface. When all references are 295 released, the interface is removed. 296 */ 297 void 298 put_device_interface(struct net_device_interface *interface) 299 { 300 if (atomic_add(&interface->ref_count, -1) != 1) 301 return; 302 303 // we need to remove this interface! 304 305 { 306 BenaphoreLocker locker(sInterfaceLock); 307 list_remove_item(&sInterfaces, interface); 308 } 309 310 interface->module->uninit_device(interface->device); 311 put_module(interface->module->info.name); 312 } 313 314 315 /*! 316 Finds an interface by the specified index and grabs a reference to it. 317 */ 318 struct net_device_interface * 319 get_device_interface(uint32 index) 320 { 321 BenaphoreLocker locker(sInterfaceLock); 322 net_device_interface *interface = NULL; 323 324 while (true) { 325 interface = (net_device_interface *)list_get_next_item(&sInterfaces, interface); 326 if (interface == NULL) 327 break; 328 329 if (interface->device->index == index) { 330 if (atomic_add(&interface->ref_count, 1) != 0) 331 return interface; 332 } 333 } 334 335 return NULL; 336 } 337 338 339 /*! 340 Finds an interface by the specified name and grabs a reference to it. 341 If the interface does not yet exist, a new one is created. 342 */ 343 struct net_device_interface * 344 get_device_interface(const char *name) 345 { 346 BenaphoreLocker locker(sInterfaceLock); 347 348 net_device_interface *interface = find_device_interface(name); 349 if (interface != NULL) { 350 if (atomic_add(&interface->ref_count, 1) != 0) 351 return interface; 352 353 // try to recreate interface - it just got removed 354 } 355 356 void *cookie = open_module_list("network/devices"); 357 if (cookie == NULL) 358 return NULL; 359 360 while (true) { 361 char moduleName[B_FILE_NAME_LENGTH]; 362 size_t length = sizeof(moduleName); 363 if (read_next_module_name(cookie, moduleName, &length) != B_OK) 364 break; 365 366 TRACE(("get_device_interface: ask \"%s\" for %s\n", moduleName, name)); 367 368 net_device_module_info *module; 369 if (get_module(moduleName, (module_info **)&module) == B_OK) { 370 net_device *device; 371 status_t status = module->init_device(name, &device); 372 if (status == B_OK) { 373 // create new module interface for this 374 interface = new (std::nothrow) net_device_interface; 375 if (interface != NULL) { 376 interface->name = device->name; 377 interface->module = module; 378 interface->device = device; 379 interface->up_count = 0; 380 interface->ref_count = 1; 381 interface->deframe_func = NULL; 382 interface->deframe_ref_count = 0; 383 384 device->index = ++sDeviceIndex; 385 device->module = module; 386 387 list_add_item(&sInterfaces, interface); 388 return interface; 389 } else 390 module->uninit_device(device); 391 } 392 393 put_module(moduleName); 394 } 395 } 396 397 return NULL; 398 } 399 400 401 // #pragma mark - devices 402 403 404 /*! 405 Unregisters a previously registered deframer function. 406 This function is part of the net_manager_module_info API. 407 */ 408 status_t 409 unregister_device_deframer(net_device *device) 410 { 411 BenaphoreLocker locker(sInterfaceLock); 412 413 // find device interface for this device 414 net_device_interface *interface = find_device_interface(device->name); 415 if (interface == NULL) 416 return ENODEV; 417 418 if (--interface->deframe_ref_count == 0) 419 interface->deframe_func = NULL; 420 421 return B_OK; 422 } 423 424 425 /*! 426 Registers the deframer function for the specified \a device. 427 Note, however, that right now, you can only register one single 428 deframer function per device. 429 430 If the need arises, we might want to lift that limitation at a 431 later time (which would require a slight API change, though). 432 433 This function is part of the net_manager_module_info API. 434 */ 435 status_t 436 register_device_deframer(net_device *device, net_deframe_func deframeFunc) 437 { 438 BenaphoreLocker locker(sInterfaceLock); 439 440 // find device interface for this device 441 net_device_interface *interface = find_device_interface(device->name); 442 if (interface == NULL) 443 return ENODEV; 444 445 if (interface->deframe_func != NULL && interface->deframe_func != deframeFunc) 446 return B_ERROR; 447 448 interface->deframe_func = deframeFunc; 449 interface->deframe_ref_count++; 450 return B_OK; 451 } 452 453 454 status_t 455 register_domain_device_handler(struct net_device *device, int32 type, 456 struct net_domain *_domain) 457 { 458 net_domain_private *domain = (net_domain_private *)_domain; 459 if (domain->module == NULL || domain->module->receive_data == NULL) 460 return B_BAD_VALUE; 461 462 return register_device_handler(device, type, &domain_receive_adapter, domain); 463 } 464 465 466 status_t 467 register_device_handler(struct net_device *device, int32 type, 468 net_receive_func receiveFunc, void *cookie) 469 { 470 BenaphoreLocker locker(sInterfaceLock); 471 472 // find device interface for this device 473 net_device_interface *interface = find_device_interface(device->name); 474 if (interface == NULL) 475 return ENODEV; 476 477 // see if such a handler already for this device 478 479 DeviceHandlerList::Iterator iterator = interface->receive_funcs.GetIterator(); 480 while (iterator.HasNext()) { 481 net_device_handler *handler = iterator.Next(); 482 483 if (handler->type == type) 484 return B_ERROR; 485 } 486 487 // Add new handler 488 489 net_device_handler *handler = new (std::nothrow) net_device_handler; 490 if (handler == NULL) 491 return B_NO_MEMORY; 492 493 handler->func = receiveFunc; 494 handler->type = type; 495 handler->cookie = cookie; 496 interface->receive_funcs.Add(handler); 497 return B_OK; 498 } 499 500 501 status_t 502 unregister_device_handler(struct net_device *device, int32 type) 503 { 504 BenaphoreLocker locker(sInterfaceLock); 505 506 // find device interface for this device 507 net_device_interface *interface = find_device_interface(device->name); 508 if (interface == NULL) 509 return ENODEV; 510 511 // search for the handler 512 513 DeviceHandlerList::Iterator iterator = interface->receive_funcs.GetIterator(); 514 while (iterator.HasNext()) { 515 net_device_handler *handler = iterator.Next(); 516 517 if (handler->type == type) { 518 // found it 519 iterator.Remove(); 520 delete handler; 521 return B_OK; 522 } 523 } 524 525 return B_BAD_VALUE; 526 } 527 528 529 status_t 530 register_device_monitor(struct net_device *device, 531 net_receive_func receiveFunc, void *cookie) 532 { 533 BenaphoreLocker locker(sInterfaceLock); 534 535 // find device interface for this device 536 net_device_interface *interface = find_device_interface(device->name); 537 if (interface == NULL) 538 return ENODEV; 539 540 // Add new monitor 541 542 net_device_monitor *monitor = new (std::nothrow) net_device_monitor; 543 if (monitor == NULL) 544 return B_NO_MEMORY; 545 546 monitor->func = receiveFunc; 547 monitor->cookie = cookie; 548 interface->monitor_funcs.Add(monitor); 549 return B_OK; 550 } 551 552 553 status_t 554 unregister_device_monitor(struct net_device *device, 555 net_receive_func receiveFunc, void *cookie) 556 { 557 BenaphoreLocker locker(sInterfaceLock); 558 559 // find device interface for this device 560 net_device_interface *interface = find_device_interface(device->name); 561 if (interface == NULL) 562 return ENODEV; 563 564 // search for the monitor 565 566 DeviceMonitorList::Iterator iterator = interface->monitor_funcs.GetIterator(); 567 while (iterator.HasNext()) { 568 net_device_monitor *monitor = iterator.Next(); 569 570 if (monitor->cookie == cookie && monitor->func == receiveFunc) { 571 // found it 572 iterator.Remove(); 573 delete monitor; 574 return B_OK; 575 } 576 } 577 578 return B_BAD_VALUE; 579 } 580 581 582 /*! 583 This function is called by device modules once their device got 584 physically removed, ie. a USB networking card is unplugged. 585 It is part of the net_manager_module_info API. 586 */ 587 status_t 588 device_removed(net_device *device) 589 { 590 BenaphoreLocker locker(sInterfaceLock); 591 // TODO: all what this function should do is to clear the IFF_UP flag of the interfaces. 592 return B_OK; 593 } 594 595 596 // #pragma mark - 597 598 599 status_t 600 init_interfaces() 601 { 602 if (benaphore_init(&sInterfaceLock, "net interfaces") < B_OK) 603 return B_ERROR; 604 605 list_init(&sInterfaces); 606 return B_OK; 607 } 608 609 610 status_t 611 uninit_interfaces() 612 { 613 benaphore_destroy(&sInterfaceLock); 614 return B_OK; 615 } 616 617