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